From 54c93f29b9460fe72dbd55f0ac061ff35415d95f Mon Sep 17 00:00:00 2001 From: Keith Date: Tue, 3 Sep 2019 16:44:47 +0800 Subject: [PATCH 1/3] feat(neuron-ui): move the miner info from overview to wallet list --- .../src/components/Overview/index.tsx | 89 ++------------ .../src/components/WalletSetting/index.tsx | 110 ++++++++++++++++-- packages/neuron-ui/src/theme.tsx | 2 + packages/neuron-ui/src/types/App/index.d.ts | 1 + .../src/controllers/app/index.ts | 19 ++- .../src/controllers/wallets/index.ts | 18 ++- 6 files changed, 148 insertions(+), 91 deletions(-) diff --git a/packages/neuron-ui/src/components/Overview/index.tsx b/packages/neuron-ui/src/components/Overview/index.tsx index cc7eca0a0d..0fff40fbcf 100644 --- a/packages/neuron-ui/src/components/Overview/index.tsx +++ b/packages/neuron-ui/src/components/Overview/index.tsx @@ -17,18 +17,16 @@ import { IDetailsRowStyles, FontSizes, Callout, - MessageBar, - MessageBarType, } from 'office-ui-fabric-react' import PropertyList, { Property } from 'widgets/PropertyList' import { StateWithDispatch } from 'states/stateProvider/reducer' -import { updateTransactionList, addPopup } from 'states/stateProvider/actionCreators' +import { updateTransactionList } from 'states/stateProvider/actionCreators' -import { showTransactionDetails, showErrorMessage } from 'services/remote' +import { showTransactionDetails } from 'services/remote' import { localNumberFormatter, shannonToCKBFormatter, uniformTimeFormatter as timeFormatter } from 'utils/formatters' -import { PAGE_SIZE, Routes, CONFIRMATION_THRESHOLD, ErrorCode } from 'utils/const' +import { PAGE_SIZE, Routes, CONFIRMATION_THRESHOLD } from 'utils/const' import { backToTop } from 'utils/animations' const TITLE_FONT_SIZE = 'xxLarge' @@ -157,20 +155,17 @@ const ActivityList = ({ const Overview = ({ dispatch, app: { tipBlockNumber, chain, epoch, difficulty }, - wallet: { id, name, balance = '', addresses = [] }, + wallet: { id, name, balance = '' }, chain: { tipBlockNumber: syncedBlockNumber, - codeHash = '', transactions: { items = [] }, }, history, }: React.PropsWithoutRef) => { const [t] = useTranslation() const [displayBlockchainInfo, setDisplayBlockchainInfo] = useState(false) - const [displayMinerInfo, setDisplayMinerInfo] = useState(false) const blockchainInfoRef = useRef(null) - const minerInfoRef = useRef(null) useEffect(() => { if (id) { @@ -264,33 +259,11 @@ const Overview = ({ [t, chain, epoch, difficulty, tipBlockNumber] ) - const [showBlockchainStatus, hideBlockchainStatus, showMinerInfo, hideMinerInfo] = useMemo( - () => [ - () => setDisplayBlockchainInfo(true), - () => setDisplayBlockchainInfo(false), - () => setDisplayMinerInfo(true), - () => setDisplayMinerInfo(false), - ], - [setDisplayBlockchainInfo, setDisplayMinerInfo] + const [showBlockchainStatus, hideBlockchainStatus] = useMemo( + () => [() => setDisplayBlockchainInfo(true), () => setDisplayBlockchainInfo(false)], + [setDisplayBlockchainInfo] ) - const defaultAddress = useMemo(() => { - return addresses.find(addr => addr.type === 0 && addr.index === 0) - }, [addresses]) - - const onCopyPubkeyHash = useCallback(() => { - if (defaultAddress) { - window.navigator.clipboard.writeText(defaultAddress.identifier) - hideMinerInfo() - addPopup('lock-arg-copied')(dispatch) - } else { - showErrorMessage( - t(`messages.error`), - t(`messages.codes.${ErrorCode.FieldNotFound}`, { fieldName: `default-address` }) - ) - } - }, [defaultAddress, t, hideMinerInfo, dispatch]) - const activityItems = useMemo( () => items.map(item => { @@ -342,11 +315,6 @@ const Overview = ({ {t('overview.blockchain-status')} -
- - {t('overview.miner-info')} - -
@@ -375,49 +343,6 @@ const Overview = ({ ) : null} - {minerInfoRef.current ? ( - - ) : null} ) } diff --git a/packages/neuron-ui/src/components/WalletSetting/index.tsx b/packages/neuron-ui/src/components/WalletSetting/index.tsx index 5842b2de62..50d4c1d200 100644 --- a/packages/neuron-ui/src/components/WalletSetting/index.tsx +++ b/packages/neuron-ui/src/components/WalletSetting/index.tsx @@ -1,15 +1,29 @@ -import React, { useCallback } from 'react' +import React, { useState, useCallback, useMemo } from 'react' import { RouteComponentProps } from 'react-router-dom' import { useTranslation } from 'react-i18next' -import { Stack, PrimaryButton, ChoiceGroup, IChoiceGroupOption } from 'office-ui-fabric-react' +import { + Stack, + PrimaryButton, + ChoiceGroup, + IChoiceGroupOption, + IconButton, + Text, + Callout, + MessageBar, + MessageBarType, + ActionButton, + getTheme, +} from 'office-ui-fabric-react' import { StateWithDispatch } from 'states/stateProvider/reducer' -import { setCurrentWallet } from 'states/stateProvider/actionCreators' +import { setCurrentWallet, addPopup } from 'states/stateProvider/actionCreators' import { WalletWizardPath } from 'components/WalletWizard' import { contextMenu } from 'services/remote' -import { Routes, MnemonicAction } from 'utils/const' +import { Routes, MnemonicAction, ErrorCode } from 'utils/const' + +const theme = getTheme() const buttons = [ { @@ -28,11 +42,34 @@ const buttons = [ const WalletSetting = ({ wallet: { id: currentID = '' }, + chain: { codeHash = '' }, settings: { wallets = [] }, dispatch, history, }: React.PropsWithoutRef) => { const [t] = useTranslation() + const [target, setTarget] = useState(null) + const [minerInfo, setMinerInfo] = useState<{ address: string; identifier: string }>({ + address: '', + identifier: '', + }) + + const [showMinerInfo, hideMinerInfo] = useMemo( + () => [ + (info: { address: string; identifier: string }) => setMinerInfo(info), + () => setMinerInfo({ address: '', identifier: '' }), + ], + [setMinerInfo] + ) + + const onCopyPubkeyHash = useCallback(() => { + if (minerInfo) { + window.navigator.clipboard.writeText(minerInfo.identifier) + hideMinerInfo() + addPopup('lock-arg-copied')(dispatch) + } + }, [minerInfo, t, hideMinerInfo, dispatch]) + const onChange = useCallback( (_e, option) => { if (option) { @@ -65,9 +102,27 @@ const WalletSetting = ({ checked: wallet.id === currentID, onRenderLabel: ({ text }: IChoiceGroupOption) => { return ( - - {text} - + <> + + {text} + + {wallet.minerAddress ? ( + ) => { + setTarget(e.target) + if (wallet.minerAddress) { + showMinerInfo(wallet.minerAddress) + } + }} + styles={{ + root: { + height: theme.fonts.xLarge.fontSize, + }, + }} + /> + ) : null} + ) }, }))} @@ -79,6 +134,47 @@ const WalletSetting = ({ ))} + ) } diff --git a/packages/neuron-ui/src/theme.tsx b/packages/neuron-ui/src/theme.tsx index 07f3da0e82..fd66a107bf 100644 --- a/packages/neuron-ui/src/theme.tsx +++ b/packages/neuron-ui/src/theme.tsx @@ -8,6 +8,7 @@ import { CircleInformation as InfoIcon, Close as DismissIcon, Close as FailIcon, + ContactInfo as MinerInfoIcon, Copy as CopyIcon, Down as ArrowDownIcon, FormEdit as EditIcon, @@ -86,6 +87,7 @@ registerIcons({ TransactionPending: , Keystore: , Edit: , + MinerInfo: , }, }) diff --git a/packages/neuron-ui/src/types/App/index.d.ts b/packages/neuron-ui/src/types/App/index.d.ts index 76e9e2682c..c73b5ad88d 100644 --- a/packages/neuron-ui/src/types/App/index.d.ts +++ b/packages/neuron-ui/src/types/App/index.d.ts @@ -107,6 +107,7 @@ declare namespace State { interface WalletIdentity { id: string name: string + minerAddress?: { address: string; identifier: string } } interface Address { diff --git a/packages/neuron-wallet/src/controllers/app/index.ts b/packages/neuron-wallet/src/controllers/app/index.ts index bea0c9dd84..1b4bddd185 100644 --- a/packages/neuron-wallet/src/controllers/app/index.ts +++ b/packages/neuron-wallet/src/controllers/app/index.ts @@ -72,6 +72,23 @@ export default class AppController { SystemScriptSubject.pipe(take(1)).subscribe(({ codeHash: currentCodeHash }) => resolve(currentCodeHash)) }), ]) + + const minerAddresses = await Promise.all( + wallets.map(({ id }) => + WalletsController.getAllAddresses(id).then(addrRes => { + if (addrRes.result) { + const minerAddr = addrRes.result.find(addr => addr.type === 0 && addr.index === 0) + if (minerAddr) { + return { + address: minerAddr.address, + identifier: minerAddr.identifier, + } + } + } + return undefined + }) + ) + ) const addresses: Controller.Address[] = await (currentWallet ? WalletsController.getAllAddresses(currentWallet.id).then(res => res.result) : []) @@ -86,7 +103,7 @@ export default class AppController { : [] const initState = { currentWallet, - wallets: [...wallets.map(({ name, id }) => ({ id, name }))], + wallets: [...wallets.map(({ name, id }, idx: number) => ({ id, name, minerAddress: minerAddresses[idx] }))], currentNetworkID, networks, addresses, diff --git a/packages/neuron-wallet/src/controllers/wallets/index.ts b/packages/neuron-wallet/src/controllers/wallets/index.ts index 0f98884eb9..8b56066e49 100644 --- a/packages/neuron-wallet/src/controllers/wallets/index.ts +++ b/packages/neuron-wallet/src/controllers/wallets/index.ts @@ -35,9 +35,25 @@ export default class WalletsController { if (!wallets) { throw new ServiceHasNoResponse('Wallet') } + const minerAddresses = await Promise.all( + wallets.map(({ id }) => + WalletsController.getAllAddresses(id).then(addrRes => { + if (addrRes.result) { + const minerAddr = addrRes.result.find(addr => addr.type === 0 && addr.index === 0) + if (minerAddr) { + return { + address: minerAddr.address, + identifier: minerAddr.identifier, + } + } + } + return undefined + }) + ) + ) return { status: ResponseCode.Success, - result: wallets.map(({ name, id }) => ({ name, id })), + result: wallets.map(({ name, id }, idx) => ({ name, id, minerAddress: minerAddresses[idx] })), } } From 48da734a6772b397631d43d114635eed0ac68ea3 Mon Sep 17 00:00:00 2001 From: Keith Date: Tue, 3 Sep 2019 19:42:40 +0800 Subject: [PATCH 2/3] feat(neuron-ui): use text instead of icon button to display the miner info trigger --- .../src/components/WalletSetting/index.tsx | 19 ++++++++++--------- packages/neuron-ui/src/theme.tsx | 2 -- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/packages/neuron-ui/src/components/WalletSetting/index.tsx b/packages/neuron-ui/src/components/WalletSetting/index.tsx index 50d4c1d200..415e86f482 100644 --- a/packages/neuron-ui/src/components/WalletSetting/index.tsx +++ b/packages/neuron-ui/src/components/WalletSetting/index.tsx @@ -6,7 +6,6 @@ import { PrimaryButton, ChoiceGroup, IChoiceGroupOption, - IconButton, Text, Callout, MessageBar, @@ -102,27 +101,29 @@ const WalletSetting = ({ checked: wallet.id === currentID, onRenderLabel: ({ text }: IChoiceGroupOption) => { return ( - <> + {text} {wallet.minerAddress ? ( - ) => { + e.preventDefault() setTarget(e.target) if (wallet.minerAddress) { showMinerInfo(wallet.minerAddress) } }} styles={{ - root: { - height: theme.fonts.xLarge.fontSize, - }, + root: [{ color: theme.semanticColors.bodySubtext, fontSize: '12px!important' }], }} - /> + > + {t('overview.miner-info')} + ) : null} - + ) }, }))} diff --git a/packages/neuron-ui/src/theme.tsx b/packages/neuron-ui/src/theme.tsx index fd66a107bf..07f3da0e82 100644 --- a/packages/neuron-ui/src/theme.tsx +++ b/packages/neuron-ui/src/theme.tsx @@ -8,7 +8,6 @@ import { CircleInformation as InfoIcon, Close as DismissIcon, Close as FailIcon, - ContactInfo as MinerInfoIcon, Copy as CopyIcon, Down as ArrowDownIcon, FormEdit as EditIcon, @@ -87,7 +86,6 @@ registerIcons({ TransactionPending: , Keystore: , Edit: , - MinerInfo: , }, }) From 870a0ba9f55d79eb24e2296145ba55c1f20003f7 Mon Sep 17 00:00:00 2001 From: Keith Date: Wed, 4 Sep 2019 11:41:25 +0800 Subject: [PATCH 3/3] test(neuron-wallet): update the e2e test according to the new layout of wallet list --- .../neuron-wallet/tests-e2e/tests/wallet.ts | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/packages/neuron-wallet/tests-e2e/tests/wallet.ts b/packages/neuron-wallet/tests-e2e/tests/wallet.ts index d98a2b0605..8deaaa36eb 100644 --- a/packages/neuron-wallet/tests-e2e/tests/wallet.ts +++ b/packages/neuron-wallet/tests-e2e/tests/wallet.ts @@ -1,4 +1,4 @@ -import Application from '../application'; +import Application from '../application' import { createWallet, importWallet } from '../operations' // Start: Guide page @@ -12,7 +12,7 @@ export default (app: Application) => { const createWalletButton = await app.getElementByTagName('button', 'Create a Wallet') expect(createWalletButton).not.toBeNull() await client.elementIdClick(createWalletButton!.ELEMENT) - console.log(`clicked create wallet button ${new Date().toTimeString()}`); + console.info(`clicked create wallet button ${new Date().toTimeString()}`) await createWallet(app) await app.waitUntilLoaded() @@ -27,21 +27,20 @@ export default (app: Application) => { expect(networkElement.value).not.toBeNull() await client.elementIdClick(networkElement.value.ELEMENT) await app.waitUntilLoaded() - console.log(`Go to setting page ${new Date().toLocaleTimeString()}`); - + console.info(`Go to setting page ${new Date().toLocaleTimeString()}`) // Switch to wallet setting const walletSettingButton = await app.getElementByTagName('button', 'Wallets') expect(walletSettingButton).not.toBeNull() await client.elementIdClick(walletSettingButton!.ELEMENT) await app.waitUntilLoaded() - console.log(`Switch to wallet setting ${new Date().toLocaleTimeString()}`); + console.info(`Switch to wallet setting ${new Date().toLocaleTimeString()}`) // Go to import wallet page const importWalletButton = await app.getElementByTagName('button', 'Import Mnemonic Seed') expect(importWalletButton).not.toBeNull() await client.elementIdClick(importWalletButton!.ELEMENT) - console.log(`Go to import wallet page ${new Date().toLocaleTimeString()}`); + console.info(`Go to import wallet page ${new Date().toLocaleTimeString()}`) const mnemonicText = 'refuse ecology globe virus demand gentle couch scrub bulk project chronic dog' await importWallet(app, mnemonicText) @@ -63,7 +62,7 @@ export default (app: Application) => { await app.waitUntilLoaded() // Switch to first wallet - const firstWallet = await app.element('//MAIN/DIV/DIV[3]/DIV/DIV/DIV/DIV/DIV') + const firstWallet = await app.element('label span') expect(firstWallet).not.toBeNull() const firstWalletName = await client.elementIdText(firstWallet.value.ELEMENT) await client.elementIdClick(firstWallet.value.ELEMENT) @@ -84,11 +83,11 @@ export default (app: Application) => { const walletNameElement = await app.element('//MAIN/DIV/H1') expect(walletNameElement.value).not.toBeNull() const walletName = await client.elementIdText(walletNameElement.value.ELEMENT) - + // Click delete wallet menu item await app.clickMenu(['Wallet', 'Delete Current Wallet']) await app.waitUntilLoaded() - + // Input password const inputElement = await app.element('//INPUT') expect(inputElement.value).not.toBeNull() @@ -137,7 +136,7 @@ export default (app: Application) => { await app.setElementValue('', 'Azusa') await app.waitUntilLoaded() const walletNameInputText = await client.elementIdAttribute(walletNameInputElement.value.ELEMENT, 'value') - console.log(`walletNameInputText - ${walletNameInputText.value}`); + console.info(`walletNameInputText - ${walletNameInputText.value}`) // Save const saveButton = await app.getElementByTagName('button', 'Save') expect(saveButton).not.toBeNull() @@ -145,10 +144,10 @@ export default (app: Application) => { await app.waitUntilLoaded() // Check wallet name - const newWalletNameElement = await app.element('//MAIN/DIV/DIV[3]/DIV/DIV/DIV/DIV/DIV[1]') + const newWalletNameElement = await app.element('label span') expect(newWalletNameElement).not.toBeNull() const newWalletName = await client.elementIdText(newWalletNameElement.value.ELEMENT) expect(newWalletName.value).toBe(walletNameInputText.value) - console.log(`newWalletName - ${newWalletName.value}`); + console.info(`newWalletName - ${newWalletName.value}`) }) }