Skip to content

Commit

Permalink
feat(neuron-ui): move the miner info from overview to wallet list (#907)
Browse files Browse the repository at this point in the history
* feat(neuron-ui): move the miner info from overview to wallet list

* feat(neuron-ui): use text instead of icon button to display the miner info trigger

* test(neuron-wallet): update the e2e test according to the new layout of wallet list
  • Loading branch information
Keith-CY committed Sep 4, 2019
1 parent c8ce2dd commit 1378768
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 103 deletions.
89 changes: 7 additions & 82 deletions packages/neuron-ui/src/components/Overview/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -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<StateWithDispatch & RouteComponentProps>) => {
const [t] = useTranslation()
const [displayBlockchainInfo, setDisplayBlockchainInfo] = useState(false)
const [displayMinerInfo, setDisplayMinerInfo] = useState(false)

const blockchainInfoRef = useRef<HTMLDivElement>(null)
const minerInfoRef = useRef<HTMLDivElement>(null)

useEffect(() => {
if (id) {
Expand Down Expand Up @@ -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 => {
Expand Down Expand Up @@ -342,11 +315,6 @@ const Overview = ({
{t('overview.blockchain-status')}
</DefaultButton>
</div>
<div ref={minerInfoRef}>
<DefaultButton onClick={showMinerInfo} styles={{ root: { width: '200px' } }}>
{t('overview.miner-info')}
</DefaultButton>
</div>
</Stack>
</Stack>
<Text as="h2" variant={TITLE_FONT_SIZE}>
Expand Down Expand Up @@ -375,49 +343,6 @@ const Overview = ({
</Stack>
</Callout>
) : null}
{minerInfoRef.current ? (
<Callout target={minerInfoRef.current} hidden={!displayMinerInfo} onDismiss={hideMinerInfo} gapSpace={0}>
<Stack tokens={{ padding: 15 }}>
{defaultAddress ? (
<Stack tokens={{ childrenGap: 15 }} styles={{ root: { padding: 5 } }}>
<Stack tokens={{ childrenGap: 15 }}>
<Text variant="small" style={{ fontWeight: 600 }}>
{t('overview.address')}
</Text>
<Text variant="small" className="monospacedFont">
{defaultAddress.address}
</Text>
</Stack>
<Stack tokens={{ childrenGap: 15 }}>
<Text variant="small" style={{ fontWeight: 600 }}>
{t('overview.code-hash')}
</Text>
<Text variant="small" className="monospacedFont">
{codeHash}
</Text>
</Stack>
<Stack tokens={{ childrenGap: 15 }}>
<Text variant="small" style={{ fontWeight: 600 }}>
{t('overview.lock-arg')}
</Text>
<Text variant="small" className="monospacedFont">
{defaultAddress.identifier}
</Text>
</Stack>
<Stack horizontalAlign="end">
<ActionButton iconProps={{ iconName: 'MiniCopy' }} onClick={onCopyPubkeyHash}>
{t('overview.copy-pubkey-hash')}
</ActionButton>
</Stack>
</Stack>
) : (
<MessageBar messageBarType={MessageBarType.error}>
{t(`messages.codes.${ErrorCode.FieldNotFound}`, { fieldName: `default-address` })}
</MessageBar>
)}
</Stack>
</Callout>
) : null}
</Stack>
)
}
Expand Down
111 changes: 104 additions & 7 deletions packages/neuron-ui/src/components/WalletSetting/index.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,28 @@
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,
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 = [
{
Expand All @@ -28,11 +41,34 @@ const buttons = [

const WalletSetting = ({
wallet: { id: currentID = '' },
chain: { codeHash = '' },
settings: { wallets = [] },
dispatch,
history,
}: React.PropsWithoutRef<StateWithDispatch & RouteComponentProps>) => {
const [t] = useTranslation()
const [target, setTarget] = useState<any>(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) {
Expand Down Expand Up @@ -65,9 +101,29 @@ const WalletSetting = ({
checked: wallet.id === currentID,
onRenderLabel: ({ text }: IChoiceGroupOption) => {
return (
<span className="ms-ChoiceFieldLabel" onContextMenu={onContextMenu(wallet.id)}>
{text}
</span>
<Stack>
<span className="ms-ChoiceFieldLabel" onContextMenu={onContextMenu(wallet.id)}>
{text}
</span>
{wallet.minerAddress ? (
<Text
variant="tiny"
className="ms-ChoiceFieldLabel"
onClick={(e: React.MouseEvent<HTMLDivElement>) => {
e.preventDefault()
setTarget(e.target)
if (wallet.minerAddress) {
showMinerInfo(wallet.minerAddress)
}
}}
styles={{
root: [{ color: theme.semanticColors.bodySubtext, fontSize: '12px!important' }],
}}
>
{t('overview.miner-info')}
</Text>
) : null}
</Stack>
)
},
}))}
Expand All @@ -79,6 +135,47 @@ const WalletSetting = ({
<PrimaryButton key={label} onClick={navTo(url)} text={t(label)} />
))}
</Stack>
<Callout target={target} hidden={!minerInfo.address} onDismiss={hideMinerInfo} gapSpace={0}>
<Stack tokens={{ padding: 15 }}>
{minerInfo.address ? (
<Stack tokens={{ childrenGap: 15 }} styles={{ root: { padding: 5 } }}>
<Stack tokens={{ childrenGap: 15 }}>
<Text variant="small" style={{ fontWeight: 600 }}>
{t('overview.address')}
</Text>
<Text variant="small" className="monospacedFont">
{minerInfo.address}
</Text>
</Stack>
<Stack tokens={{ childrenGap: 15 }}>
<Text variant="small" style={{ fontWeight: 600 }}>
{t('overview.code-hash')}
</Text>
<Text variant="small" className="monospacedFont">
{codeHash}
</Text>
</Stack>
<Stack tokens={{ childrenGap: 15 }}>
<Text variant="small" style={{ fontWeight: 600 }}>
{t('overview.lock-arg')}
</Text>
<Text variant="small" className="monospacedFont">
{minerInfo.identifier}
</Text>
</Stack>
<Stack horizontalAlign="end">
<ActionButton iconProps={{ iconName: 'MiniCopy' }} onClick={onCopyPubkeyHash}>
{t('overview.copy-pubkey-hash')}
</ActionButton>
</Stack>
</Stack>
) : (
<MessageBar messageBarType={MessageBarType.error}>
{t(`messages.codes.${ErrorCode.FieldNotFound}`, { fieldName: `default-address` })}
</MessageBar>
)}
</Stack>
</Callout>
</Stack>
)
}
Expand Down
1 change: 1 addition & 0 deletions packages/neuron-ui/src/types/App/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ declare namespace State {
interface WalletIdentity {
id: string
name: string
minerAddress?: { address: string; identifier: string }
}

interface Address {
Expand Down
19 changes: 18 additions & 1 deletion packages/neuron-wallet/src/controllers/app/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
: [])
Expand All @@ -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,
Expand Down
18 changes: 17 additions & 1 deletion packages/neuron-wallet/src/controllers/wallets/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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] })),
}
}

Expand Down
Loading

0 comments on commit 1378768

Please sign in to comment.