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'
13 class CoreIndex extends React.Component {
17 this.deleteClick = this.deleteClick.bind(this)
21 const fetchInfo = () => {
22 if(this.refs.requestComponent) {
23 chainClient().config.info().then(resp => {
24 this.setState({requestStatus: resp.data})
28 setInterval(fetchInfo.bind(this), 2 * 1000)
32 if (!window.confirm('Are you sure you want to delete all data on this core?')) {
36 this.setState({deleteDisabled: true})
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 = '/'
48 deleteDisabled: false,
56 testnetBlockchainMismatch,
57 testnetNetworkMismatch,
62 if (this.props.core.generator) {
63 generatorUrl = window.location.origin
64 } else if (onTestnet) {
66 {this.props.core.generatorUrl}
68 <span className='label label-primary'>Chain Testnet</span>
71 generatorUrl = this.props.core.generatorUrl
76 className={'btn btn-default'}
77 id='input-dropdown-addon'
78 title={this.props.core.lang === 'zh' ? '中文' : 'English'}
79 onSelect={this.props.setLang}
81 <MenuItem eventKey='zh'>中文</MenuItem>
82 <MenuItem eventKey='en'>English</MenuItem>
87 <div className={[styles.left, styles.col].join(' ')}>
89 <h4>Configuration</h4>
90 <table className={styles.table}>
93 <td className={styles.row_label}>Core type:</td>
94 <td>{this.props.core.coreType}</td>
97 <td className={styles.row_label}>Setup time:</td>
98 <td>{this.props.core.configuredAt}</td>
101 <td className={styles.row_label}>Version:</td>
102 <td><code>{this.props.core.version}</code></td>
105 <td className={styles.row_label}>Language:</td>
106 <td>{this.props.core.lang === 'zh' ? '中文' : 'English'}</td>
109 <td className={styles.row_label}>MockHSM enabled:</td>
110 <td><code>{this.props.core.mockhsm.toString()}</code></td>
113 <td className={styles.row_label}>Localhost auth:</td>
114 <td><code>{this.props.core.localhostAuth.toString()}</code></td>
117 <td className={styles.row_label}>Reset enabled:</td>
118 <td><code>{this.props.core.reset.toString()}</code></td>
121 <td className={styles.row_label}>Non-TLS HTTP requests enabled:</td>
122 <td><code>{this.props.core.httpOk.toString()}</code></td>
125 <td colSpan={2}><hr /></td>
128 <td className={styles.row_label}>Generator URL:</td>
129 <td>{generatorUrl}</td>
131 {onTestnet && !!testnetNextReset &&
133 <td className={styles.row_label}>Next Chain Testnet data reset:</td>
134 <td>{testnetNextReset.toString()}</td>
136 {!this.props.core.generator &&
138 <td className={styles.row_label}>Generator Access Token:</td>
139 <td><code>{this.props.core.generatorAccessToken}</code></td>
142 <td className={styles.row_label}>Blockchain ID:</td>
143 <td><code className={styles.block_hash}>{this.props.core.blockchainId}</code></td>
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>}
160 let requestStatusBlock =
161 this.state.requestStatus && (<div className={styles['sub-row']}>
162 <h4>Request status</h4>
163 <table className={styles.table}>
165 {Object.keys(this.state.requestStatus).map(key => (
167 <td className={styles.row_label}> {key}: </td>
168 <td className={styles.row_value}>{ String(this.state.requestStatus[key])}</td>
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}>
183 <td className={styles.row_label}>Generator block:</td>
184 <td className={styles.row_value}>{this.props.core.generatorBlockHeight}</td>
187 <td className={styles.row_label}>Local block:</td>
188 <td className={styles.row_value}>{this.props.core.blockHeight}</td>
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}
201 {testnetErr && <ErrorBanner title='Chain Testnet error' error={testnetErr} />}
206 let resetDataBlock = (
207 <div className='row'>
208 <div className='col-sm-6'>
211 {this.props.core.reset ?
214 This will permanently delete all data stored in this core,
215 including blockchain data, accounts, assets, indexes,
219 {this.state.deleteError && <ErrorBanner
220 title='Error resetting data'
221 message={this.state.deleteError.toString()}
225 className='btn btn-danger'
226 onClick={this.deleteClick}
227 disabled={this.state.deleteDisabled}
233 This core is not configured with reset capabilities.
240 <div className={componentClassNames(this, 'flex-container', styles.mainContainer)}>
241 <PageTitle title='Core' />
244 <div className={`${styles.top} ${styles.flex}`}>
255 const mapStateToProps = (state) => ({
257 onTestnet: state.core.onTestnet,
258 testnetBlockchainMismatch: testnetUtils.isBlockchainMismatch(state),
259 testnetNetworkMismatch: testnetUtils.isCrosscoreRpcMismatch(state),
260 testnetNextReset: state.testnet.nextReset,
263 const mapDispatchToProps = (dispatch) => ({
264 setLang: (event) => {
266 type: 'UPDATE_CORE_LANGUAGE',
272 export default connect(