--- /dev/null
+import React from 'react'
+import componentClassNames from 'utility/componentClassNames'
+import {PageContent, PageTitle} from 'features/shared/components'
+import styles from './Backup.scss'
+import {connect} from 'react-redux'
+import {chainClient} from 'utility/environment'
+
+class Backup extends React.Component {
+ constructor(props) {
+ super(props)
+ this.connection = chainClient().connection
+ }
+
+ backup() {
+ this.connection.request('/backup-wallet').then(resp => {
+ const date = new Date()
+ const dateStr = date.toLocaleDateString().split(' ')[0]
+ const fileName = 'bytom-wallet-backup-' + dateStr
+
+ var element = document.createElement('a')
+ element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(JSON.stringify(resp.data)))
+ element.setAttribute('download', fileName)
+ element.style.display = 'none'
+ document.body.appendChild(element)
+ element.click()
+
+ document.body.removeChild(element)
+ })
+ }
+
+ render() {
+ const lang = this.props.core.lang
+ const newButton = <button key='showCreate' className='btn btn-primary' onClick={this.backup.bind(this)}>
+ {lang === 'zh' ? '备份' : 'Backup'}
+ </button>
+
+ return (
+ <div className={componentClassNames(this, 'flex-container', styles.mainContainer)}>
+ <PageTitle title={lang === 'zh' ? '备份与恢复' : 'Backup and restore'}/>
+ <PageContent>
+ {newButton}
+ </PageContent>
+ </div>
+ )
+ }
+}
+
+const mapStateToProps = (state) => ({
+ core: state.core,
+ navAdvancedState: state.app.navAdvancedState,
+})
+
+export default connect(
+ mapStateToProps
+)(Backup)
--- /dev/null
+.page_header h1 {
+ margin-bottom: 0;
+}
+
+.table {
+ margin-bottom: $grid-gutter-width;
+
+ td {
+ vertical-align: top;
+ }
+}
+
+.row_label {
+ padding-right: $grid-gutter-width;
+ text-transform: capitalize;
+ font-weight: 500;
+ white-space: pre;
+}
+
+.row_value {
+ white-space: pre;
+ text-align: right;
+}
+
+.block_hash {
+ display: block;
+ word-wrap: break-word;
+ word-break: break-all;
+}
+
+.flex {
+ display: flex;
+ //overflow:hidden;
+}
+
+.col {
+ display: flex;
+ width: 50%;
+ padding: $grid-gutter-width;
+ h4 {
+ margin-top: 0;
+ }
+}
+
+.sub-row {
+ padding: $grid-gutter-width $grid-gutter-width 0;
+}
+
+.top {
+ border-bottom: 1px solid $border-color;
+}
+
+.left {
+ padding-left: 0;
+ width: 67%;
+}
+
+.right {
+ border-left: 1px solid $border-color;
+ width: 33%;
+}
+
+.replication_lag {
+ display: inline-block;
+ float: right;
+ border-radius: $border-radius-base;
+ color: white;
+ padding: 0 8px;
+ line-height: 1.5;
+ margin-top: 2px;
+ margin-left: -8px;
+}
+
+.green {
+ background: $highlight-secondary;
+}
+
+.yellow {
+ background: $brand-warning;
+}
+
+.red {
+ background: darken($highlight-danger-background, 20%);
+}
+
+.mainContainer {
+ background-color: $background-color;
+}
+
+code {
+ padding-left: 0;
+ font-size: $font-size-code;
+}
+
+.switch {
+ position: relative;
+ display: inline-block;
+ width: 44px;
+ height: 22px;
+
+ /* Hide default HTML checkbox */
+ input {display:none;}
+
+ input:checked + .slider {
+ background-color: $highlight-default;
+ }
+
+ input:focus + .slider {
+ box-shadow: 0 0 1px $highlight-default;
+ }
+
+ input:checked + .slider:before {
+ -webkit-transform: translateX(22px);
+ -ms-transform: translateX(22px);
+ transform: translateX(22px);
+ }
+}
+
+/* The slider */
+.slider {
+ position: absolute;
+ cursor: pointer;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: #ccc;
+ -webkit-transition: .4s;
+ transition: .4s;
+ border-radius: 34px;
+}
+
+.slider:before {
+ position: absolute;
+ content: "";
+ height: 18px;
+ width: 18px;
+ left: 2px;
+ bottom: 2px;
+ background-color: white;
+ -webkit-transition: .4s;
+ transition: .4s;
+ border-radius: 50%;
+}
\ No newline at end of file
--- /dev/null
+import Backup from './Backup'
+
+export {
+ Backup
+}
--- /dev/null
+import routes from './routes'
+
+export {
+ routes,
+}
--- /dev/null
+import { RoutingContainer } from 'features/shared/components'
+import { Backup } from './components'
+
+export default {
+ path: 'backup',
+ component: RoutingContainer,
+ indexRoute: { component: Backup }
+}
import { routes as transactionFeeds } from 'features/transactionFeeds'
import { routes as unspents } from 'features/unspents'
import { routes as mockhsm } from 'features/mockhsm'
+import { routes as backup } from 'features/backup'
const makeRoutes = (store) => ({
path: '/',
transactionFeeds(store),
unspents(store),
mockhsm(store),
+ backup,
{
path: '*',
component: NotFound