update ui and state

This commit is contained in:
fmtabbara
2022-01-12 20:30:56 +00:00
parent 955583d0f0
commit fadb5b4ff9
9 changed files with 102 additions and 53 deletions
+36
View File
@@ -0,0 +1,36 @@
import React from 'react'
import { Typography } from '@mui/material'
import { CircleOutlined, PauseCircleOutlined, CheckCircleOutline } from '@mui/icons-material'
import { MixnodeStatus } from '../types'
export const NodeStatus = ({ status }: { status: MixnodeStatus }) => {
switch (status) {
case 'active':
return <Active />
case 'inactive':
return <Inactive />
case 'standby':
return <Standby />
default:
null
}
return null
}
const Active = () => (
<Typography sx={{ color: 'success.main', display: 'flex', alignItems: 'center' }}>
<CheckCircleOutline fontSize="small" color="success" sx={{ mr: 1 }} /> Active
</Typography>
)
const Inactive = () => (
<Typography sx={{ color: 'nym.text.dark', display: 'flex', alignItems: 'center' }}>
<CircleOutlined fontSize="small" sx={{ color: 'nym.text.dark', mr: 1 }} /> Inactive
</Typography>
)
const Standby = () => (
<Typography sx={{ color: 'info.main', display: 'flex', alignItems: 'center' }}>
<PauseCircleOutlined fontSize="small" color="info" sx={{ mr: 1 }} /> Standby
</Typography>
)
+2 -2
View File
@@ -1,5 +1,5 @@
import React from 'react'
import { Card, CardContent, CardHeader } from '@mui/material'
import { Box, Card, CardContent, CardHeader } from '@mui/material'
import { styled } from '@mui/material/styles'
export const NymCard: React.FC<{
@@ -16,7 +16,7 @@ export const NymCard: React.FC<{
data-testid={title}
titleTypographyProps={{ variant: 'h5' }}
subheaderTypographyProps={{ variant: 'subtitle1' }}
action={Action}
action={<Box sx={{ mt: 1 }}>{Action}</Box>}
sx={{
color: 'nym.background.dark',
py: 2.5,
+13 -9
View File
@@ -9,6 +9,7 @@ import { SystemVariables } from './system-variables'
import { NodeStats } from './node-stats'
import { Overview } from './overview'
import { useSettingsState } from './useSettingsState'
import { NodeStatus } from '../../components/NodeStatus'
const tabs = ['Profile', 'System variables', 'Node stats']
@@ -16,26 +17,23 @@ export const Settings = () => {
const { showSettings, handleShowSettings } = useContext(ClientContext)
const [selectedTab, setSelectedTab] = useState(0)
const { mixnodeDetails, status, saturation } = useSettingsState(showSettings)
const { mixnodeDetails, status, saturation, rewardEstimation } = useSettingsState(showSettings)
console.log({ status, saturation })
const handleTabChange = (event: React.SyntheticEvent, newTab: number) => setSelectedTab(newTab)
const handleTabChange = (_: React.SyntheticEvent, newTab: number) => setSelectedTab(newTab)
return showSettings ? (
<Dialog open={true} onClose={handleShowSettings} maxWidth="md" fullWidth>
<NymCard
title={
<Box display="flex" alignItems="center">
<SettingsOutlined sx={{ mr: 1 }} /> Settings
<SettingsOutlined sx={{ mr: 1 }} />
Node Settings
</Box>
}
Action={<NodeStatus status={status} />}
noPadding
>
<>
<Typography variant="h5" sx={{ py: 2, px: 4 }}>
Node settings
</Typography>
<Tabs tabs={tabs} selectedTab={selectedTab} onChange={handleTabChange} disabled={!mixnodeDetails} />
<Overview details={mixnodeDetails} />
{!mixnodeDetails && (
@@ -44,7 +42,13 @@ export const Settings = () => {
</Alert>
)}
{selectedTab === 0 && mixnodeDetails && <Profile />}
{selectedTab === 1 && mixnodeDetails && <SystemVariables mixnodeDetails={mixnodeDetails.mix_node} />}
{selectedTab === 1 && mixnodeDetails && (
<SystemVariables
mixnodeDetails={mixnodeDetails.mix_node}
saturation={saturation}
rewardEstimation={rewardEstimation}
/>
)}
{selectedTab === 2 && mixnodeDetails && <NodeStats mixnodeId={mixnodeDetails.mix_node.identity_key} />}
</>
</NymCard>
+1 -31
View File
@@ -1,40 +1,10 @@
import React from 'react'
import { Divider, Stack, Typography } from '@mui/material'
import { CheckCircleOutline, CircleOutlined, PauseCircleOutlined } from '@mui/icons-material'
import { TMixnodeBondDetails } from '../../types'
type TMixnodeStatus = 'active' | 'inactive' | 'standby'
export const Overview = ({
mixnodeStatus,
details,
}: {
mixnodeStatus?: TMixnodeStatus
details?: TMixnodeBondDetails | null
}) => (
export const Overview = ({ details }: { details?: TMixnodeBondDetails | null }) => (
<Stack spacing={3} sx={{ p: 4, pb: 0 }}>
<Typography sx={{ color: 'grey.600' }}>Node identity {details?.mix_node.identity_key || 'n/a'}</Typography>
{mixnodeStatus === 'active' && <ActiveMessage />}
{mixnodeStatus === 'inactive' && <InActiveMessage />}
{mixnodeStatus === 'standby' && <StandbyMessage />}
<Divider />
</Stack>
)
const ActiveMessage = () => (
<Typography sx={{ color: 'success.main', display: 'flex', alignItems: 'center' }}>
<CheckCircleOutline fontSize="small" color="success" sx={{ mr: 1 }} /> Mixnode is active in this epoch
</Typography>
)
const InActiveMessage = () => (
<Typography sx={{ color: 'nym.text.dark', display: 'flex', alignItems: 'center' }}>
<CircleOutlined fontSize="small" sx={{ color: 'nym.text.dark', mr: 1 }} /> Mixnode is active in this epoch
</Typography>
)
const StandbyMessage = () => (
<Typography sx={{ color: 'info.main', display: 'flex', alignItems: 'center' }}>
<PauseCircleOutlined fontSize="small" color="info" sx={{ mr: 1 }} /> Mixnode is on standy by in this epoch
</Typography>
)
@@ -24,7 +24,15 @@ type TFormData = {
profitMarginPercent: number
}
export const SystemVariables = ({ mixnodeDetails }: { mixnodeDetails: TMixnodeBondDetails['mix_node'] }) => {
export const SystemVariables = ({
mixnodeDetails,
saturation,
rewardEstimation,
}: {
mixnodeDetails: TMixnodeBondDetails['mix_node']
saturation: number
rewardEstimation: number
}) => {
const [nodeUpdateResponse, setNodeUpdateResponse] = useState<'success' | 'failed'>()
const [configFee, setConfigFee] = useState<string>()
@@ -78,7 +86,11 @@ export const SystemVariables = ({ mixnodeDetails }: { mixnodeDetails: TMixnodeBo
<DataField
title="Estimated reward"
info="Estimated reward per epoch for this profit margin if your node is selected in the active set."
Indicator={<Chip label="Coming soon" icon={<AccessTimeOutlined fontSize="small" />} />}
Indicator={
<Typography sx={{ color: (theme) => theme.palette.nym.fee, fontWeight: '600' }}>
{rewardEstimation} {MAJOR_CURRENCY}
</Typography>
}
/>
<Divider />
<DataField
@@ -96,7 +108,7 @@ export const SystemVariables = ({ mixnodeDetails }: { mixnodeDetails: TMixnodeBo
<DataField
title="Node stake saturation"
info="Level of stake saturation for this node. Nodes receive more rewards the higher their saturation level, up to 100%. Beyond 100% no additional rewards are granted. The current stake saturation level is: 1 million NYM, computed as S/K where S is the total amount of tokens available to stakeholders and K is the number of nodes in the reward set."
Indicator={<Chip label="Coming soon" icon={<AccessTimeOutlined fontSize="small" />} />}
Indicator={<PercentIndicator value={saturation} />}
/>
</Stack>
</Box>
@@ -1,12 +1,19 @@
import { useContext, useEffect, useState } from 'react'
import { ClientContext } from '../../context/main'
import { getMixnodeBondDetails, getMixnodeStakeSaturation, getMixnodeStatus } from '../../requests'
import { TMixnodeBondDetails, StakeSaturationResponse, MixnodeStatusResponse } from '../../types'
import {
getMixnodeBondDetails,
getMixnodeRewardEstimation,
getMixnodeStakeSaturation,
getMixnodeStatus,
minorToMajor,
} from '../../requests'
import { TMixnodeBondDetails, MixnodeStatus } from '../../types'
export const useSettingsState = (showSettings: boolean) => {
const [mixnodeDetails, setMixnodeDetails] = useState<TMixnodeBondDetails | null>()
const [status, setStatus] = useState<MixnodeStatusResponse>()
const [saturation, setSaturation] = useState<StakeSaturationResponse>()
const [status, setStatus] = useState<MixnodeStatus>('NotFound')
const [saturation, setSaturation] = useState<number>(0)
const [rewardEstimation, setRewardEstimation] = useState<number>(0)
const { clientDetails } = useContext(ClientContext)
@@ -18,14 +25,26 @@ export const useSettingsState = (showSettings: boolean) => {
const getStatus = async () => {
if (clientDetails?.client_address) {
const status = await getMixnodeStatus(clientDetails?.contract_address)
setStatus(status)
setStatus(status.status)
}
}
const getStakeSaturation = async () => {
if (clientDetails?.client_address) {
const saturation = await getMixnodeStakeSaturation(clientDetails?.contract_address)
setSaturation(saturation)
if (saturation) {
setSaturation(Math.round(saturation.saturation * 100))
}
}
}
const getRewardEstimation = async () => {
if (clientDetails?.client_address) {
const rewardEstimation = await getMixnodeRewardEstimation(clientDetails?.contract_address)
if (rewardEstimation) {
const toMajor = await minorToMajor(rewardEstimation.estimated_total_node_reward.toString())
setRewardEstimation(parseInt(toMajor.amount))
}
}
}
@@ -34,6 +53,7 @@ export const useSettingsState = (showSettings: boolean) => {
getBondDetails()
getStatus()
getStakeSaturation()
getRewardEstimation()
}
}, [showSettings])
@@ -41,5 +61,6 @@ export const useSettingsState = (showSettings: boolean) => {
status,
saturation,
mixnodeDetails,
rewardEstimation,
}
}
+5 -1
View File
@@ -8,6 +8,7 @@ import {
MixNode,
MixnodeStatusResponse,
Operation,
RewardEstimationResponse,
StakeSaturationResponse,
TauriContractStateParams,
TauriTxResult,
@@ -89,8 +90,11 @@ export const getMixnodeBondDetails = async (): Promise<TMixnodeBondDetails | nul
export const getMixnodeStakeSaturation = async (identity: string): Promise<StakeSaturationResponse> =>
await invoke('mixnode_stake_saturation', { identity })
export const getMixnodeRewardEstimation = async (identity: string): Promise<RewardEstimationResponse> =>
await invoke('mixnode_reward_estimation', { identity })
export const getMixnodeStatus = async (identity: string): Promise<MixnodeStatusResponse> =>
await invoke('mixnode_status', { identity })
export const updateMixnode = async ({ profitMarginPercent }: { profitMarginPercent: number }) =>
await invoke('update_mixnode', { profitMarginPercent })
+2
View File
@@ -12,3 +12,5 @@ export * from './transactiondetails'
export * from './mixnodestatus'
export * from './mixnodestatusresponse'
export * from './stakesaturaionresponse'
export * from './rewardestimationresponse'
export * from './mixnodestatus'
+1 -1
View File
@@ -1 +1 @@
export type MixnodeStatus = "Active" | "Standby" | "Inactive" | "NotFound";
export type MixnodeStatus = 'active' | 'standby' | 'inactive' | 'NotFound'