OSDN Git Service

Add the language information
[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 { DropdownButton, MenuItem } from 'react-bootstrap'
4 import componentClassNames from 'utility/componentClassNames'
5 import { PageContent, ErrorBanner, PageTitle } from 'features/shared/components'
6 import React from 'react'
7 import styles from './CoreIndex.scss'
8 import testnetUtils from 'features/testnet/utils'
9 import { docsRoot } from 'utility/environment'
10 import Sync from 'features/app/components/Sync/Sync'
11
12
13 class CoreIndex extends React.Component {
14   constructor(props) {
15     super(props)
16     this.state = {}
17     this.deleteClick = this.deleteClick.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   render() {
54     const {
55       onTestnet,
56       testnetBlockchainMismatch,
57       testnetNetworkMismatch,
58       testnetNextReset,
59     } = this.props
60
61     let generatorUrl
62     if (this.props.core.generator) {
63       generatorUrl = window.location.origin
64     } else if (onTestnet) {
65       generatorUrl = <span>
66         {this.props.core.generatorUrl}
67         &nbsp;
68         <span className='label label-primary'>Chain Testnet</span>
69       </span>
70     } else {
71       generatorUrl = this.props.core.generatorUrl
72     }
73
74     let languageBlock =  (
75       <DropdownButton
76         className={'btn btn-default'}
77         id='input-dropdown-addon'
78         title={this.props.core.lang === 'zh' ? '中文' : 'English'}
79         onSelect={this.props.setLang}
80       >
81         <MenuItem eventKey='zh'>中文</MenuItem>
82         <MenuItem eventKey='en'>English</MenuItem>
83       </DropdownButton>
84     )
85
86     let configBlock = (
87       <div className={[styles.left, styles.col].join(' ')}>
88         <div>
89           <h4>Configuration</h4>
90           <table className={styles.table}>
91             <tbody>
92               <tr>
93                 <td className={styles.row_label}>Core type:</td>
94                 <td>{this.props.core.coreType}</td>
95               </tr>
96               <tr>
97                 <td className={styles.row_label}>Setup time:</td>
98                 <td>{this.props.core.configuredAt}</td>
99               </tr>
100               <tr>
101                 <td className={styles.row_label}>Version:</td>
102                 <td><code>{this.props.core.version}</code></td>
103               </tr>
104               <tr>
105                 <td className={styles.row_label}>Language:</td>
106                 <td>{this.props.core.lang === 'zh' ? '中文' : 'English'}</td>
107               </tr>
108               <tr>
109                 <td className={styles.row_label}>MockHSM enabled:</td>
110                 <td><code>{this.props.core.mockhsm.toString()}</code></td>
111               </tr>
112               <tr>
113                 <td className={styles.row_label}>Localhost auth:</td>
114                 <td><code>{this.props.core.localhostAuth.toString()}</code></td>
115               </tr>
116               <tr>
117                 <td className={styles.row_label}>Reset enabled:</td>
118                 <td><code>{this.props.core.reset.toString()}</code></td>
119               </tr>
120               <tr>
121                 <td className={styles.row_label}>Non-TLS HTTP requests enabled:</td>
122                 <td><code>{this.props.core.httpOk.toString()}</code></td>
123               </tr>
124               <tr>
125                 <td colSpan={2}><hr /></td>
126               </tr>
127               <tr>
128                 <td className={styles.row_label}>Generator URL:</td>
129                 <td>{generatorUrl}</td>
130               </tr>
131               {onTestnet && !!testnetNextReset &&
132                 <tr>
133                   <td className={styles.row_label}>Next Chain Testnet data reset:</td>
134                   <td>{testnetNextReset.toString()}</td>
135                 </tr>}
136               {!this.props.core.generator &&
137                 <tr>
138                   <td className={styles.row_label}>Generator Access Token:</td>
139                   <td><code>{this.props.core.generatorAccessToken}</code></td>
140                 </tr>}
141               <tr>
142                 <td className={styles.row_label}>Blockchain ID:</td>
143                 <td><code className={styles.block_hash}>{this.props.core.blockchainId}</code></td>
144               </tr>
145             </tbody>
146           </table>
147         </div>
148       </div>
149     )
150
151     let testnetErr
152     if (onTestnet) {
153       if (testnetBlockchainMismatch) {
154         testnetErr = 'Chain Testnet has been reset. Please reset your core below.'
155       } else if (testnetNetworkMismatch) {
156         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>}
157       }
158     }
159
160     let requestStatusBlock =
161         this.state.requestStatus && (<div className={styles['sub-row']}>
162           <h4>Request status</h4>
163           <table className={styles.table}>
164             <tbody>
165             {Object.keys(this.state.requestStatus).map(key => (
166               <tr key={key}>
167                 <td className={styles.row_label}> {key}: </td>
168                 <td className={styles.row_value}>{ String(this.state.requestStatus[key])}</td>
169               </tr>))}
170             </tbody>
171           </table>
172         </div>
173     )
174
175     let networkStatusBlock = (
176       <div className={styles.right}>
177         <div ref="requestComponent">
178           <div className={[styles.top, styles['sub-row']].join(' ')}>
179             <h4>Network status</h4>
180             <table className={styles.table}>
181               <tbody>
182               <tr>
183                 <td className={styles.row_label}>Generator block:</td>
184                 <td className={styles.row_value}>{this.props.core.generatorBlockHeight}</td>
185               </tr>
186               <tr>
187                 <td className={styles.row_label}>Local block:</td>
188                 <td className={styles.row_value}>{this.props.core.blockHeight}</td>
189               </tr>
190               <tr>
191                 <td className={styles.row_label}>Replication lag:</td>
192                 <td className={`${styles.replication_lag} ${styles[this.props.core.replicationLagClass]}`}>
193                   {this.props.core.replicationLag === null ? '???' : this.props.core.replicationLag}
194                 </td>
195               </tr>
196               </tbody>
197             </table>
198           </div>
199           {requestStatusBlock}
200         </div>
201         {testnetErr && <ErrorBanner title='Chain Testnet error' error={testnetErr} />}
202       </div>
203     )
204
205
206     let resetDataBlock = (
207       <div className='row'>
208         <div className='col-sm-6'>
209           <h4>Reset data</h4>
210
211           {this.props.core.reset ?
212             <div>
213               <p>
214                 This will permanently delete all data stored in this core,
215                 including blockchain data, accounts, assets, indexes,
216                 and MockHSM keys.
217               </p>
218
219               {this.state.deleteError && <ErrorBanner
220                 title='Error resetting data'
221                 message={this.state.deleteError.toString()}
222               />}
223
224               <button
225                 className='btn btn-danger'
226                 onClick={this.deleteClick}
227                 disabled={this.state.deleteDisabled}
228               >
229                 Delete all data
230               </button>
231             </div> :
232             <p>
233               This core is not configured with reset capabilities.
234             </p>}
235         </div>
236       </div>
237     )
238
239     return (
240       <div className={componentClassNames(this, 'flex-container', styles.mainContainer)}>
241         <PageTitle title='Core' />
242
243         <PageContent>
244           <div className={`${styles.top} ${styles.flex}`}>
245             {configBlock}
246             {networkStatusBlock}
247           </div>
248           {resetDataBlock}
249         </PageContent>
250       </div>
251     )
252   }
253 }
254
255 const mapStateToProps = (state) => ({
256   core: state.core,
257   onTestnet: state.core.onTestnet,
258   testnetBlockchainMismatch: testnetUtils.isBlockchainMismatch(state),
259   testnetNetworkMismatch: testnetUtils.isCrosscoreRpcMismatch(state),
260   testnetNextReset: state.testnet.nextReset,
261 })
262
263 const mapDispatchToProps = (dispatch) => ({
264   setLang: (event) => {
265     dispatch({
266       type: 'UPDATE_CORE_LANGUAGE',
267       lang: event
268     })
269   }
270 })
271
272 export default connect(
273   mapStateToProps,
274   mapDispatchToProps
275 )(CoreIndex)