From e411a495f01895e75aad43ef59556b8ddd83bbbd Mon Sep 17 00:00:00 2001 From: holymingo Date: Fri, 12 May 2023 16:50:26 +0800 Subject: [PATCH 1/2] =?UTF-8?q?refactor:=20=F0=9F=92=A1=20MyVote=20compone?= =?UTF-8?q?nt=20with=20functional?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Vote/MyVote/MyVote.js | 344 ++++++++++---------------------- 1 file changed, 106 insertions(+), 238 deletions(-) diff --git a/src/pages/Vote/MyVote/MyVote.js b/src/pages/Vote/MyVote/MyVote.js index 8a9b2835d..b1a593108 100644 --- a/src/pages/Vote/MyVote/MyVote.js +++ b/src/pages/Vote/MyVote/MyVote.js @@ -1,284 +1,152 @@ -import React, { Component } from 'react'; -import moment from 'moment'; - -import StatisticalData from '@components/StatisticalData/'; -import { getAllTeamDesc, fetchPageableCandidateInformation } from '@api/vote'; -import publicKeyToAddress from '@utils/publicKeyToAddress'; -import { RANK_NOT_EXISTED_SYMBOL } from '@src/pages/Vote/constants'; -import { MY_VOTE_DATA_TIP } from '@src/constants'; -import { Button, Spin } from 'antd'; -import NightElfCheck from '../../../utils/NightElfCheck'; -import getLogin from '../../../utils/getLogin'; -import MyVoteRecord from './MyVoteRecords'; -import { ELF_DECIMAL, myVoteStatistData } from '../constants'; -import { getPublicKeyFromObject } from '../../../utils/getPublicKey'; -import addressFormat from '../../../utils/addressFormat'; - -import './MyVote.style.less'; - -export default class MyVote extends Component { - constructor(props) { - super(props); - this.state = { - statistData: myVoteStatistData, - tableData: [], - spinningLoading: true, - currentWallet: { - address: null, - name: null, - pubKey: { - x: null, - y: null, - }, - }, - }; - - this.hasRun = false; - } - - componentDidMount() { - if (this.props.currentWallet) { - this.getCurrentWallet(); +import React, { useState, useEffect } from "react"; +import moment from "moment"; +import StatisticalData from "@components/StatisticalData/"; +import { getAllTeamDesc, fetchPageableCandidateInformation } from "@api/vote"; +import publicKeyToAddress from "@utils/publicKeyToAddress"; +import { + RANK_NOT_EXISTED_SYMBOL, + ELF_DECIMAL, + myVoteStatistData, +} from "@src/pages/Vote/constants"; +import { MY_VOTE_DATA_TIP } from "@src/constants"; +import { Button, Spin } from "antd"; +import NightElfCheck from "../../../utils/NightElfCheck"; +import getLogin from "../../../utils/getLogin"; +import MyVoteRecord from "./MyVoteRecords"; +import { getPublicKeyFromObject } from "../../../utils/getPublicKey"; +import addressFormat from "../../../utils/addressFormat"; + +import "./MyVote.style.less"; + +const MyVote = (props) => { + const [statistData, setStatistData] = useState(myVoteStatistData); + const [tableData, setTableData] = useState([]); + const [spinningLoading, setSpinningLoading] = useState(true); + const [currentWallet, setCurrentWallet] = useState({ + address: null, + name: null, + pubKey: { + x: null, + y: null, + }, + }); + + const [hasRun, setHasRun] = useState(false); + + useEffect(() => { + if (props.currentWallet) { + getCurrentWallet(); } - } + }, [props.currentWallet]); - // todo: update the vote info after switch to this tab - componentDidUpdate(prevProps, prevState) { - if (this.props.currentWallet && !prevProps.currentWallet) { - this.getCurrentWallet(); - } - if (prevProps.currentWallet && prevProps.currentWallet.address !== this.props.currentWallet.address) { - this.getCurrentWallet(); + useEffect(() => { + if (props.currentWallet && !hasRun) { + fetchTableDataAndStatistData(); + setHasRun(true); } - if (!this.hasRun) { - this.fetchTableDataAndStatistData(); - } - } + }, [props.currentWallet, hasRun]); - getCurrentWallet() { + const getCurrentWallet = () => { NightElfCheck.getInstance() .check.then((ready) => { const nightElf = NightElfCheck.getAelfInstanceByExtension(); getLogin( nightElf, - { file: 'MyVote.js' }, + { file: "MyVote.js" }, (result) => { if (result.error) { - this.setState({ - spinningLoading: false, - }); - // message.warn(result.message || result.errorMessage.message); + setSpinningLoading(false); } else { const wallet = JSON.parse(result.detail); - const currentWallet = { + const newCurrentWallet = { formattedAddress: addressFormat(wallet.address), address: wallet.address, name: wallet.name, pubKey: getPublicKeyFromObject(wallet.publicKey), }; - this.setState({ - currentWallet, - }); - this.props.checkExtensionLockStatus(); + setCurrentWallet(newCurrentWallet); + props.checkExtensionLockStatus(); setTimeout(() => { - this.fetchTableDataAndStatistData(currentWallet); + fetchTableDataAndStatistData(newCurrentWallet); }); } }, - false, + false ); }) .catch((error) => { - this.setState({ - spinningLoading: false, - }); - // message.warn('Please download and install NightELF browser extension.'); + setSpinningLoading(false); }); - } + }; - fetchTableDataAndStatistData(currentWalletTemp) { - const { electionContract } = this.props; + const fetchTableDataAndStatistData = (currentWalletTemp) => { + const { electionContract } = props; if (!electionContract) return; - this.hasRun = true; - const currentWallet = currentWalletTemp || this.state.currentWallet; - if (!currentWallet || !currentWallet.address) { - this.hasRun = false; + setHasRun(true); + const newCurrentWallet = currentWalletTemp || currentWallet; + if (!newCurrentWallet || !newCurrentWallet.address) { + setHasRun(false); return false; } - // todo: is it ok to get the same data twice in different tabs - // todo: add error handle Promise.all([ electionContract.GetElectorVoteWithAllRecords.call({ - value: currentWallet.pubKey, + value: newCurrentWallet.pubKey, }), getAllTeamDesc(), fetchPageableCandidateInformation(electionContract, { start: 0, - // length: A_NUMBER_LARGE_ENOUGH_TO_GET_ALL // FIXME: length: 20, }), ]) .then((resArr) => { - console.log('resArr', resArr); - this.processData(resArr); + processData(resArr); }) .catch((err) => { - console.error('err', 'fetchTableDataAndStatistData', err); + console.error("err", "fetchTableDataAndStatistData", err); }); - } - - processData(resArr) { - const electorVotes = resArr[0]; - const allNodeInfo = (resArr[2] ? resArr[2].value : []) - .sort((a, b) => +b.obtainedVotesAmount - +a.obtainedVotesAmount) - .map((item, index) => { - item.rank = index + 1; - return item; - }); - let allTeamInfo = null; - const withdrawableVoteRecords = []; - let withdrawableVoteAmount = 0; - if (resArr[1].code === 0) { - allTeamInfo = resArr[1].data; - } - - const myVoteRecords = [ - ...electorVotes.activeVotingRecords, - ...electorVotes.withdrawnVotesRecords, - ]; - electorVotes.activeVotingRecords.forEach((record) => { - if (record.unlockTimestamp.seconds < moment().unix()) { - withdrawableVoteRecords.push(record); - } - }); - - // assign rank - myVoteRecords.forEach((record) => { - const foundedNode = allNodeInfo.find( - (item) => item.candidateInformation.pubkey === record.candidate, - ); - if (foundedNode === undefined) { - // rank: used to sort - record.rank = 9999999; - // displayedRank: used to display - record.displayedRank = RANK_NOT_EXISTED_SYMBOL; - } else { - record.rank = foundedNode.rank; - record.displayedRank = foundedNode.rank; - } - }); - const myTotalVotesAmount = electorVotes.allVotedVotesAmount; - withdrawableVoteAmount = withdrawableVoteRecords.reduce( - (total, current) => total + +current.amount, - 0, - ); - console.log({ - myTotalVotesAmount, - withdrawableVoteAmount, - }); - this.processStatistData( - 'myTotalVotesAmount', - 'num', - myTotalVotesAmount / ELF_DECIMAL, - ); - this.processStatistData( - 'withdrawableVotesAmount', - 'num', - withdrawableVoteAmount / ELF_DECIMAL, - ); - this.processTableData(myVoteRecords, allTeamInfo); - } - - // eslint-disable-next-line class-methods-use-this - processTableData(myVoteRecords, allTeamInfo) { - // add node name - const tableData = myVoteRecords; - tableData.forEach((record) => { - const teamInfo = allTeamInfo.find( - (team) => team.public_key === record.candidate, - ); - console.log('teamInfo', teamInfo); - if (teamInfo === undefined) { - record.address = publicKeyToAddress(record.candidate); - record.name = addressFormat(record.address); - } else { - record.name = teamInfo.name; - } - if (record.isWithdrawn) { - record.type = 'Redeem'; - record.operationTime = moment - .unix(record.withdrawTimestamp.seconds) - .format('YYYY-MM-DD HH:mm:ss'); - } else if (record.isChangeTarget) { - record.type = 'Switch Vote'; - record.operationTime = moment - .unix(record.voteTimestamp.seconds) - .format('YYYY-MM-DD HH:mm:ss'); - } else { - record.type = 'Vote'; - record.operationTime = moment - .unix(record.voteTimestamp.seconds) - .format('YYYY-MM-DD HH:mm:ss'); - } - record.status = 'Success'; - console.log('record.lockTime', record.lockTime); - const start = moment.unix(record.voteTimestamp.seconds); - const end = moment.unix(record.unlockTimestamp.seconds); - record.formattedLockTime = end.from(start, true); - record.formattedUnlockTime = end.format('YYYY-MM-DD HH:mm:ss'); - record.isRedeemable = record.unlockTimestamp.seconds <= moment().unix(); - }); - // todo: withdrawn's timestamp - - this.setState({ - tableData, - spinningLoading: false, - }); - } - - processStatistData(key, param, value) { - const { statistData } = this.state; - this.setState({ - statistData: { - ...statistData, - [key]: { - ...(statistData[key] || {}), - [param]: value - } + }; + + const processData = (resArr) => { + + // 更新状态 + setTableData(tableData); + setSpinningLoading(false); + }; + + const processStatistData = (key, param, value) => { + // 更新状态 + setStatistData({ + ...statistData, + [key]: { + ...(statistData[key] || {}), + [param]: value, }, - spinningLoading: false, }); - } - - render() { - const { - statistData, - spinningLoading, - tableData, - currentWallet, - } = this.state; - - const onLogin = () => { - this.getCurrentWallet(); - }; - - return ( -
- {currentWallet.address ? ( - - - - - ) : ( -
-

It seems like you are not logged in.

- -
- )} -
- ); - } -} + setSpinningLoading(false); + }; + + const onLogin = () => { + getCurrentWallet(); + }; + + return ( +
+ {currentWallet.address ? ( + + + + + ) : ( +
+

It seems like you are not logged in.

+ +
+ )} +
+ ); +}; + +export default MyVote; From 08251deb2d7788b7a95bf69a4eb444931dae2b44 Mon Sep 17 00:00:00 2001 From: holymingo Date: Fri, 12 May 2023 17:17:00 +0800 Subject: [PATCH 2/2] =?UTF-8?q?refactor:=20=F0=9F=92=A1=20fill=20code=20in?= =?UTF-8?q?=20process=20functions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Vote/MyVote/MyVote.js | 170 +++++++++++++++++++++++++------- 1 file changed, 134 insertions(+), 36 deletions(-) diff --git a/src/pages/Vote/MyVote/MyVote.js b/src/pages/Vote/MyVote/MyVote.js index b1a593108..aea4ac6e3 100644 --- a/src/pages/Vote/MyVote/MyVote.js +++ b/src/pages/Vote/MyVote/MyVote.js @@ -1,22 +1,19 @@ -import React, { useState, useEffect } from "react"; -import moment from "moment"; -import StatisticalData from "@components/StatisticalData/"; -import { getAllTeamDesc, fetchPageableCandidateInformation } from "@api/vote"; -import publicKeyToAddress from "@utils/publicKeyToAddress"; -import { - RANK_NOT_EXISTED_SYMBOL, - ELF_DECIMAL, - myVoteStatistData, -} from "@src/pages/Vote/constants"; -import { MY_VOTE_DATA_TIP } from "@src/constants"; -import { Button, Spin } from "antd"; -import NightElfCheck from "../../../utils/NightElfCheck"; -import getLogin from "../../../utils/getLogin"; -import MyVoteRecord from "./MyVoteRecords"; -import { getPublicKeyFromObject } from "../../../utils/getPublicKey"; -import addressFormat from "../../../utils/addressFormat"; - -import "./MyVote.style.less"; +import React, { useState, useEffect } from 'react'; +import moment from 'moment'; + +import StatisticalData from '@components/StatisticalData/'; +import { getAllTeamDesc, fetchPageableCandidateInformation } from '@api/vote'; +import publicKeyToAddress from '@utils/publicKeyToAddress'; +import { RANK_NOT_EXISTED_SYMBOL , ELF_DECIMAL, myVoteStatistData } from '@src/pages/Vote/constants'; +import { MY_VOTE_DATA_TIP } from '@src/constants'; +import { Button, Spin } from 'antd'; +import NightElfCheck from '../../../utils/NightElfCheck'; +import getLogin from '../../../utils/getLogin'; +import MyVoteRecord from './MyVoteRecords'; +import { getPublicKeyFromObject } from '../../../utils/getPublicKey'; +import addressFormat from '../../../utils/addressFormat'; + +import './MyVote.style.less'; const MyVote = (props) => { const [statistData, setStatistData] = useState(myVoteStatistData); @@ -30,7 +27,6 @@ const MyVote = (props) => { y: null, }, }); - const [hasRun, setHasRun] = useState(false); useEffect(() => { @@ -40,38 +36,38 @@ const MyVote = (props) => { }, [props.currentWallet]); useEffect(() => { - if (props.currentWallet && !hasRun) { + if (!hasRun) { fetchTableDataAndStatistData(); - setHasRun(true); } - }, [props.currentWallet, hasRun]); + }, [hasRun]); + const getCurrentWallet = () => { NightElfCheck.getInstance() .check.then((ready) => { const nightElf = NightElfCheck.getAelfInstanceByExtension(); getLogin( nightElf, - { file: "MyVote.js" }, + { file: 'MyVote.js' }, (result) => { if (result.error) { setSpinningLoading(false); } else { const wallet = JSON.parse(result.detail); - const newCurrentWallet = { + const currentWallet = { formattedAddress: addressFormat(wallet.address), address: wallet.address, name: wallet.name, pubKey: getPublicKeyFromObject(wallet.publicKey), }; - setCurrentWallet(newCurrentWallet); + setCurrentWallet(currentWallet); props.checkExtensionLockStatus(); setTimeout(() => { - fetchTableDataAndStatistData(newCurrentWallet); + fetchTableDataAndStatistData(currentWallet); }); } }, - false + false, ); }) .catch((error) => { @@ -83,19 +79,22 @@ const MyVote = (props) => { const { electionContract } = props; if (!electionContract) return; setHasRun(true); - const newCurrentWallet = currentWalletTemp || currentWallet; - if (!newCurrentWallet || !newCurrentWallet.address) { + const currentWallet = currentWalletTemp || currentWallet; + if (!currentWallet || !currentWallet.address) { setHasRun(false); return false; } + // todo: is it ok to get the same data twice in different tabs + // todo: add error handle Promise.all([ electionContract.GetElectorVoteWithAllRecords.call({ - value: newCurrentWallet.pubKey, + value: currentWallet.pubKey, }), getAllTeamDesc(), fetchPageableCandidateInformation(electionContract, { start: 0, + // length: A_NUMBER_LARGE_ENOUGH_TO_GET_ALL // FIXME: length: 20, }), ]) @@ -103,29 +102,128 @@ const MyVote = (props) => { processData(resArr); }) .catch((err) => { - console.error("err", "fetchTableDataAndStatistData", err); + console.error('err', 'fetchTableDataAndStatistData', err); }); }; const processData = (resArr) => { + const electorVotes = resArr[0]; + const allNodeInfo = (resArr[2] ? resArr[2].value : []) + .sort((a, b) => +b.obtainedVotesAmount - +a.obtainedVotesAmount) + .map((item, index) => { + item.rank = index + 1; + return item; + }); + let allTeamInfo = null; + const withdrawableVoteRecords = []; + let withdrawableVoteAmount = 0; + if (resArr[1].code === 0) { + allTeamInfo = resArr[1].data; + } + + const myVoteRecords = [ + ...electorVotes.activeVotingRecords, + ...electorVotes.withdrawnVotesRecords, + ]; + electorVotes.activeVotingRecords.forEach((record) => { + if (record.unlockTimestamp.seconds < moment().unix()) { + withdrawableVoteRecords.push(record); + } + }); - // 更新状态 + // assign rank + myVoteRecords.forEach((record) => { + const foundedNode = allNodeInfo.find( + (item) => item.candidateInformation.pubkey === record.candidate, + ); + if (foundedNode === undefined) { + // rank: used to sort + record.rank = 9999999; + // displayedRank: used to display + record.displayedRank = RANK_NOT_EXISTED_SYMBOL; + } else { + record.rank = foundedNode.rank; + record.displayedRank = foundedNode.rank; + } + }); + const myTotalVotesAmount = electorVotes.allVotedVotesAmount; + withdrawableVoteAmount = withdrawableVoteRecords.reduce( + (total, current) => total + +current.amount, + 0, + ); + console.log({ + myTotalVotesAmount, + withdrawableVoteAmount, + }); + processStatistData( + 'myTotalVotesAmount', + 'num', + myTotalVotesAmount / ELF_DECIMAL, + ); + processStatistData( + 'withdrawableVotesAmount', + 'num', + withdrawableVoteAmount / ELF_DECIMAL, + ); + processTableData(myVoteRecords, allTeamInfo); + }; + + const processTableData = (myVoteRecords, allTeamInfo) => { + // add node name + const tableData = myVoteRecords; + tableData.forEach((record) => { + const teamInfo = allTeamInfo.find( + (team) => team.public_key === record.candidate, + ); + console.log('teamInfo', teamInfo); + if (teamInfo === undefined) { + record.address = publicKeyToAddress(record.candidate); + record.name = addressFormat(record.address); + } else { + record.name = teamInfo.name; + } + if (record.isWithdrawn) { + record.type = 'Redeem'; + record.operationTime = moment + .unix(record.withdrawTimestamp.seconds) + .format('YYYY-MM-DD HH:mm:ss'); + } else if (record.isChangeTarget) { + record.type = 'Switch Vote'; + record.operationTime = moment + .unix(record.voteTimestamp.seconds) + .format('YYYY-MM-DD HH:mm:ss'); + } else { + record.type = 'Vote'; + record.operationTime = moment + .unix(record.voteTimestamp.seconds) + .format('YYYY-MM-DD HH:mm:ss'); + } + record.status = 'Success'; + console.log('record.lockTime', record.lockTime); + const start = moment.unix(record.voteTimestamp.seconds); + const end = moment.unix(record.unlockTimestamp.seconds); + record.formattedLockTime = end.from(start, true); + record.formattedUnlockTime = end.format('YYYY-MM-DD HH:mm:ss'); + record.isRedeemable = record.unlockTimestamp.seconds <= moment().unix(); + }); + setTableData(tableData); setSpinningLoading(false); }; + const processStatistData = (key, param, value) => { - // 更新状态 setStatistData({ ...statistData, [key]: { ...(statistData[key] || {}), - [param]: value, - }, + [param]: value + } }); setSpinningLoading(false); }; + const onLogin = () => { getCurrentWallet(); };