OSDN Git Service

add the rescan function for the balance page
authorZhiting Lin <zlin035@uottawa.ca>
Wed, 18 Jul 2018 11:13:29 +0000 (19:13 +0800)
committerZhiting Lin <zlin035@uottawa.ca>
Wed, 18 Jul 2018 11:13:29 +0000 (19:13 +0800)
src/features/app/components/Modal/Modal.jsx
src/features/balances/actions.js
src/features/balances/components/List.jsx
src/features/balances/components/RescanDialog/RescanDialog.jsx [new file with mode: 0644]
src/features/balances/components/RescanDialog/RescanDialog.scss [new file with mode: 0644]
src/features/balances/reducers.js
src/features/core/components/CoreIndex/CoreIndex.jsx

index 92c9210..48950ca 100644 (file)
@@ -21,8 +21,9 @@ class Modal extends React.Component {
       dispatch(actions.app.hideModal)
     }
     const cancel = cancelAction ? () => dispatch(cancelAction) : null
-    const backdropAction = cancel || accept
+    const backdropAction = this.props.options.dialog? null : (cancel || accept)
     const boxStyle = this.props.options.box
+    const noCloseBtn = this.props.options.noCloseBtn
 
     return(
       <div className={styles.main}>
@@ -36,9 +37,9 @@ class Modal extends React.Component {
               </div>
           }
           {body}
-          {!boxStyle && <button className={`btn btn-${this.props.options.danger ? 'danger' : 'primary'} ${styles.accept}`} onClick={accept}>
+          {!noCloseBtn && <button className={`btn btn-${this.props.options.danger ? 'danger' : 'primary'} ${styles.accept}`} onClick={accept}>
             { lang === 'zh' ?  '关闭' : 'OK' }</button>}
-          {!boxStyle && cancel && <button className={`btn btn-link ${styles.cancel}`} onClick={cancel}>Cancel</button>}
+          {!noCloseBtn && cancel && <button className={`btn btn-link ${styles.cancel}`} onClick={cancel}>Cancel</button>}
         </div>
       </div>
     )
index f5dee48..fce2f40 100644 (file)
@@ -1,2 +1,48 @@
 import { baseListActions } from 'features/shared/actions'
-export default baseListActions('balance')
+import { chainClient } from 'utility/environment'
+
+const updateInfo = (param) => ({type: 'UPDATE_WALLET_INFO', param})
+
+const rescan = () => {
+  return (dispatch) => {
+    return chainClient().backUp.rescan()
+      .then((resp) => {
+        if (resp.status === 'fail') {
+          dispatch({type: 'ERROR', payload: {'message': resp.msg}})
+        } else {
+          dispatch({type: 'START_RESCAN'})
+        }
+      })
+      .catch(err => {
+        throw {_error: err}
+      })
+  }
+}
+
+const walletInfo = () => {
+  return (dispatch) => {
+    return chainClient().backUp.info()
+      .then((info) => {
+        if (info.status === 'fail') {
+          dispatch({type: 'ERROR', payload: {'message': info.msg}})
+        } else {
+          if (info.data.bestBlockHeight === info.data.walletHeight) {
+            dispatch({type: 'STOP_RESCAN'})
+          }else{
+            dispatch(updateInfo(info.data))
+          }
+        }
+      })
+      .catch((err) => {
+        dispatch({type: 'ERROR', payload: err})
+      })
+  }
+}
+
+let actions = {
+  updateInfo,
+  rescan,
+  walletInfo,
+  ...baseListActions('balance')
+}
+export default actions
index 3e16a43..04e2b6a 100644 (file)
@@ -1,18 +1,89 @@
 import { BaseList } from 'features/shared/components'
+import { ProgressBar } from 'react-bootstrap'
 import ListItem from './ListItem'
+import React from 'react'
+import actions from 'actions'
+import RescanDialog from './RescanDialog/RescanDialog'
 
 const type = 'balance'
 
+class List extends React.Component {
+  rescanWallet(){
+    // this.props.rescan()
+
+    // debugger
+    // if (this.props.rescanning) {
+    //   window.setTimeout(this.props.info(), 1000)
+    // }
+
+    // let progressInstance = (<ProgressBar now={now} />)
+    // let now = 0
+    //
+    // this.setStat = () => {
+    //   if (this.props.rescanning) {
+    //     this.props.info()
+    //     now = this.props.rescanProgress.bestBlockHeight? this.props.rescanProgress.walletHeight/ this.props.rescanProgress.bestBlockHeight :0
+    //     setTimeout(this.setStat, 1000)
+    //   }else{
+    //     this.props.info()
+    //     console.log('successfully rescan')
+    //   }
+    // }
+
+    // this.setStat()
+
+    this.props.showModal(
+      <RescanDialog
+        // now={now}
+        lang={this.props.lang}
+        closeModal = {this.props.closeModal()}
+      />
+    )
+  }
+
+  render() {
+    const ItemList = BaseList.ItemList
+    const newButton = <button key='showRescan' className='btn btn-primary' onClick={() => this.rescanWallet()}>
+      {this.props.lang === 'zh' ? '重新扫描' : 'Rescan'}
+    </button>
+    return <div>
+      <ItemList
+        actions={[newButton]}
+      {...this.props}
+      />
+    </div>
+  }
+}
+
 const newStateToProps = (state, ownProps) => {
   const props =  {
     ...BaseList.mapStateToProps(type, ListItem)(state, ownProps),
+    rescanning: state.balance.rescanning,
+    rescanProgress: state.balance.rescanProgress,
     skipCreate: true
   }
 
   return props
 }
 
+const mapDispatchToProps = ( dispatch ) => ({
+  rescan: () => dispatch(actions.balance.rescan()),
+  info: () => dispatch(actions.balance.walletInfo()),
+  showModal: (body) => dispatch(actions.app.showModal(
+    body,
+    actions.app.hideModal,
+    null,
+    {
+      dialog: true,
+      noCloseBtn: true
+    }
+  )),
+  closeModal:() => dispatch(actions.app.hideModal),
+  ...BaseList.mapDispatchToProps(type),
+})
+
 export default BaseList.connect(
   newStateToProps,
-  BaseList.mapDispatchToProps(type)
+  mapDispatchToProps,
+  List
 )
diff --git a/src/features/balances/components/RescanDialog/RescanDialog.jsx b/src/features/balances/components/RescanDialog/RescanDialog.jsx
new file mode 100644 (file)
index 0000000..eefeb39
--- /dev/null
@@ -0,0 +1,99 @@
+import React from 'react'
+import { ProgressBar } from 'react-bootstrap'
+import styles from './RescanDialog.scss'
+import actions from 'actions'
+import {connect} from 'react-redux'
+
+class RescanDialog extends React.Component {
+  constructor(props) {
+    super(props)
+    this.state={
+      now: 0
+    }
+  }
+
+  componentDidMount(){
+    let now = 0
+    this.props.rescan()
+      .then(()=>{
+        return this.setStat()
+      })
+
+    this.setStat = () => {
+      if (this.props.rescanning) {
+        this.props.fetchInfo()
+        now = this.props.rescanProgress.bestBlockHeight?
+          (this.props.rescanProgress.walletHeight*100/ this.props.rescanProgress.bestBlockHeight).toFixed(2)
+          :0
+        this.setState({
+          now: now
+        })
+        setTimeout(this.setStat, 2000)
+      }else{
+        this.setState({
+          now: 100
+        })
+      }
+    }
+  }
+
+  render() {
+    const now = this.state.now
+    const lang = this.props.lang
+    const success = (lang === 'zh' ? '扫描成功!!!':'Success!!!')
+    const start = (lang === 'zh' ? '扫描开始...':'Starting...')
+    const rescan = (lang === 'zh' ? '扫描中...':'Rescanning...')
+    return (
+      <div>
+        <h2 className={styles.title}>
+          { now === 100?
+            success:
+            (now === 0? start: rescan)
+          }
+        </h2>
+        { now === 100?
+          <pre className={styles.infoContainer}>
+            <p>{lang === 'zh' ? '已经成功扫描资产余额。' :'Successfully rescanned spent outputs.'}</p>
+          </pre>
+          :
+          (now === 0?
+            (<pre className={styles.infoContainer}>
+              <p>{lang === 'zh' ? '扫描正在启动...' : 'Rescan is starting...'}</p>
+            </pre>):
+            (<pre className={styles.infoContainer}>
+              <p>{lang === 'zh' ? '钱包正在扫描中...' : 'Wallet Rescanning...'}</p>
+              <ProgressBar now={now} />
+             </pre>))
+
+        }
+        <div className={styles.submitBtn}>
+          <button
+            key='submit'
+            className={'btn btn-primary'}
+            onClick={() => this.props.closeModal()}
+            disabled={ now!==100 }
+          >
+            {lang === 'zh' ? '确定' : 'OK'}
+          </button>
+        </div>
+      </div>
+    )
+  }
+}
+
+const mapStateToProps = (state) => ({
+  rescanning: state.balance.rescanning,
+  rescanProgress: state.balance.rescanProgress,
+})
+
+
+const mapDispatchToProps = ( dispatch ) => ({
+  rescan: () => dispatch(actions.balance.rescan()),
+  fetchInfo: () => dispatch(actions.balance.walletInfo()),
+  closeModal:() => dispatch(actions.app.hideModal),
+})
+
+export default connect(
+  mapStateToProps,
+  mapDispatchToProps
+)( RescanDialog)
diff --git a/src/features/balances/components/RescanDialog/RescanDialog.scss b/src/features/balances/components/RescanDialog/RescanDialog.scss
new file mode 100644 (file)
index 0000000..72cb29f
--- /dev/null
@@ -0,0 +1,12 @@
+.title{
+  text-align: center;
+}
+
+.submitBtn{
+  display: flex;
+  justify-content: center;
+}
+
+.infoContainer{
+  word-break: break-word;
+}
index 9083a53..007cb65 100644 (file)
@@ -26,8 +26,24 @@ const queriesReducer = (state = {}, action) => {
   return state
 }
 
+const rescanProgress = (state = {}, action) => {
+  if (action.type == 'UPDATE_WALLET_INFO') {
+    return action.param
+  }
+  return state
+}
+
+
+const rescanning = (state = {}, action) => {
+  if (action.type == 'START_RESCAN') return true
+  else if (action.type == 'STOP_RESCAN') return false
+  return state
+}
+
 
 export default combineReducers({
   items: itemsReducer,
-  queries: queriesReducer
+  queries: queriesReducer,
+  rescanning,
+  rescanProgress
 })
index 42e15f7..fcb371b 100644 (file)
@@ -222,7 +222,8 @@ const mapDispatchToProps = (dispatch) => ({
     null,
     {
       box: true,
-      wide: true
+      wide: true,
+      noCloseBtn: true
     }
   )),
   cmd: (data) => dispatch(actions.app.cmd(data))