OSDN Git Service

Add the advanced toggle function in core status page
[bytom/bytom-electron.git] / src / features / core / components / CoreIndex / CoreIndex.jsx
1 import { chainClient } from 'utility/environment'
2 import { connect } from 'react-redux'
3 import componentClassNames from 'utility/componentClassNames'
4 import { PageContent, ErrorBanner, PageTitle } from 'features/shared/components'
5 import React from 'react'
6 import styles from './CoreIndex.scss'
7 import testnetUtils from 'features/testnet/utils'
8 import { docsRoot } from 'utility/environment'
9 import actions from 'actions'
10
11
12 class CoreIndex extends React.Component {
13   constructor(props) {
14     super(props)
15     this.state = {}
16     this.deleteClick = this.deleteClick.bind(this)
17     this.handleAdvancedOptionChange = this.handleAdvancedOptionChange.bind(this)
18   }
19
20   componentDidMount() {
21     const fetchInfo = () => {
22       if(this.refs.requestComponent) {
23         chainClient().config.info().then(resp => {
24           this.setState({requestStatus: resp.data})
25         })
26       }
27     }
28     setInterval(fetchInfo.bind(this), 2 * 1000)
29   }
30
31   deleteClick() {
32     if (!window.confirm('Are you sure you want to delete all data on this core?')) {
33       return
34     }
35
36     this.setState({deleteDisabled: true})
37
38     chainClient().config.reset(true).then(() => {
39       // TODO: Use Redux state reset and nav action instead of window.location.
40       // Also, move confirmation message to a bonafide flash div. alert() in a
41       // browser microtask is going away. cf https://www.chromestatus.com/features/5647113010544640
42       setTimeout(function(){
43         window.location.href = '/'
44       }, 500)
45     }).catch((err) => {
46       this.setState({
47         deleteError: err,
48         deleteDisabled: false,
49       })
50     })
51   }
52
53   handleAdvancedOptionChange(event) {
54     const target = event.target
55     if( target.checked ){
56       this.props.showNavAdvanced()
57       window.localStorage.setItem('NavState', 'advance')
58     }else{
59       this.props.hideNavAdvanced()
60       window.localStorage.setItem('NavState', 'normal')
61     }
62   }
63
64   render() {
65     const {
66       onTestnet,
67       testnetBlockchainMismatch,
68       testnetNetworkMismatch,
69       testnetNextReset,
70     } = this.props
71
72     let generatorUrl
73     if (this.props.core.generator) {
74       generatorUrl = window.location.origin
75     } else if (onTestnet) {
76       generatorUrl = <span>
77         {this.props.core.generatorUrl}
78         &nbsp;
79         <span className='label label-primary'>Chain Testnet</span>
80       </span>
81     } else {
82       generatorUrl = this.props.core.generatorUrl
83     }
84
85     let navState = window.localStorage.getItem('NavState') === 'advance'
86
87     let configBlock = (
88       <div className={[styles.left, styles.col].join(' ')}>
89         <div>
90           <h4>Configuration</h4>
91           <table className={styles.table}>
92             <tbody>
93               <tr>
94                 <td className={styles.row_label}>Core type:</td>
95                 <td>{this.props.core.coreType}</td>
96               </tr>
97               <tr>
98                 <td className={styles.row_label}>Setup time:</td>
99                 <td>{this.props.core.configuredAt}</td>
100               </tr>
101               <tr>
102                 <td className={styles.row_label}>Version:</td>
103                 <td><code>{this.props.core.version}</code></td>
104               </tr>
105               <tr>
106                 <td className={styles.row_label}>Language:</td>
107                 <td>{this.props.core.lang === 'zh' ? '中文' : 'English'}</td>
108               </tr>
109               <tr>
110                 <td className={styles.row_label}>MockHSM enabled:</td>
111                 <td><code>{this.props.core.mockhsm.toString()}</code></td>
112               </tr>
113               <tr>
114                 <td className={styles.row_label}>Localhost auth:</td>
115                 <td><code>{this.props.core.localhostAuth.toString()}</code></td>
116               </tr>
117               <tr>
118                 <td className={styles.row_label}>Reset enabled:</td>
119                 <td><code>{this.props.core.reset.toString()}</code></td>
120               </tr>
121               <tr>
122                 <td className={styles.row_label}>Non-TLS HTTP requests enabled:</td>
123                 <td><code>{this.props.core.httpOk.toString()}</code></td>
124               </tr>
125               <tr>
126                 <td colSpan={2}><hr /></td>
127               </tr>
128               <tr>
129                 <td className={styles.row_label}>Generator URL:</td>
130                 <td>{generatorUrl}</td>
131               </tr>
132               {onTestnet && !!testnetNextReset &&
133                 <tr>
134                   <td className={styles.row_label}>Next Chain Testnet data reset:</td>
135                   <td>{testnetNextReset.toString()}</td>
136                 </tr>}
137               {!this.props.core.generator &&
138                 <tr>
139                   <td className={styles.row_label}>Generator Access Token:</td>
140                   <td><code>{this.props.core.generatorAccessToken}</code></td>
141                 </tr>}
142               <tr>
143                 <td className={styles.row_label}>Blockchain ID:</td>
144                 <td><code className={styles.block_hash}>{this.props.core.blockchainId}</code></td>
145               </tr>
146               <tr>
147                 <td colSpan={2}><hr /></td>
148               </tr>
149               <tr>
150                 <td className={styles.row_label}>Advanced: </td>
151                 <td>
152                   <label className={styles.switch}>
153                     <input
154                       type='checkbox'
155                       onChange={this.handleAdvancedOptionChange}
156                       checked={navState}
157                     />
158                     <span className={styles.slider}></span>
159                   </label>
160                 </td>
161               </tr>
162             </tbody>
163           </table>
164         </div>
165       </div>
166     )
167
168     let testnetErr
169     if (onTestnet) {
170       if (testnetBlockchainMismatch) {
171         testnetErr = 'Chain Testnet has been reset. Please reset your core below.'
172       } else if (testnetNetworkMismatch) {
173         testnetErr = {message: <span>This core is no longer compatible with Chain Testnet. <a href={`${docsRoot}/core/get-started/install`} target='_blank'>Please upgrade Chain Core</a>.</span>}
174       }
175     }
176
177     let requestStatusBlock =
178         this.state.requestStatus && (<div className={styles['sub-row']}>
179           <h4>Request status</h4>
180           <table className={styles.table}>
181             <tbody>
182             {Object.keys(this.state.requestStatus).map(key => (
183               <tr key={key}>
184                 <td className={styles.row_label}> {key}: </td>
185                 <td className={styles.row_value}>{ String(this.state.requestStatus[key])}</td>
186               </tr>))}
187             </tbody>
188           </table>
189         </div>
190     )
191
192     let networkStatusBlock = (
193       <div className={styles.right}>
194         <div ref='requestComponent'>
195           <div className={[styles.top, styles['sub-row']].join(' ')}>
196             <h4>Network status</h4>
197             <table className={styles.table}>
198               <tbody>
199               <tr>
200                 <td className={styles.row_label}>Generator block:</td>
201                 <td className={styles.row_value}>{this.props.core.generatorBlockHeight}</td>
202               </tr>
203               <tr>
204                 <td className={styles.row_label}>Local block:</td>
205                 <td className={styles.row_value}>{this.props.core.blockHeight}</td>
206               </tr>
207               <tr>
208                 <td className={styles.row_label}>Replication lag:</td>
209                 <td className={`${styles.replication_lag} ${styles[this.props.core.replicationLagClass]}`}>
210                   {this.props.core.replicationLag === null ? '???' : this.props.core.replicationLag}
211                 </td>
212               </tr>
213               </tbody>
214             </table>
215           </div>
216           {requestStatusBlock}
217         </div>
218         {testnetErr && <ErrorBanner title='Chain Testnet error' error={testnetErr} />}
219       </div>
220     )
221
222     let resetDataBlock = (
223       <div className='row'>
224         <div className='col-sm-6'>
225           <h4>Reset data</h4>
226
227           {this.props.core.reset ?
228             <div>
229               <p>
230                 This will permanently delete all data stored in this core,
231                 including blockchain data, accounts, assets, indexes,
232                 and MockHSM keys.
233               </p>
234
235               {this.state.deleteError && <ErrorBanner
236                 title='Error resetting data'
237                 message={this.state.deleteError.toString()}
238               />}
239
240               <button
241                 className='btn btn-danger'
242                 onClick={this.deleteClick}
243                 disabled={this.state.deleteDisabled}
244               >
245                 Delete all data
246               </button>
247             </div> :
248             <p>
249               This core is not configured with reset capabilities.
250             </p>}
251         </div>
252       </div>
253     )
254
255     return (
256       <div className={componentClassNames(this, 'flex-container', styles.mainContainer)}>
257         <PageTitle title='Core' />
258
259         <PageContent>
260           <div className={`${styles.top} ${styles.flex}`}>
261             {configBlock}
262             {networkStatusBlock}
263           </div>
264           {resetDataBlock}
265         </PageContent>
266       </div>
267     )
268   }
269 }
270
271 const mapStateToProps = (state) => ({
272   core: state.core,
273   onTestnet: state.core.onTestnet,
274   testnetBlockchainMismatch: testnetUtils.isBlockchainMismatch(state),
275   testnetNetworkMismatch: testnetUtils.isCrosscoreRpcMismatch(state),
276   testnetNextReset: state.testnet.nextReset,
277 })
278
279 const mapDispatchToProps = (dispatch) => ({
280   showNavAdvanced: () => dispatch(actions.app.showNavAdvanced),
281   hideNavAdvanced: () => dispatch(actions.app.hideNavAdvanced)
282 })
283
284 export default connect(
285   mapStateToProps,
286   mapDispatchToProps
287 )(CoreIndex)