Add terminal in dev mode

This commit is contained in:
Mark Sinclair
2022-04-22 11:30:15 +01:00
parent 67f6394a26
commit bbdd53d2aa
4 changed files with 199 additions and 2 deletions
+11 -1
View File
@@ -1,12 +1,15 @@
import React, { useContext } from 'react';
import { AppBar as MuiAppBar, Grid, IconButton, Toolbar } from '@mui/material';
import { Logout } from '@mui/icons-material';
import TerminalIcon from '@mui/icons-material/Terminal';
import { ClientContext } from '../context/main';
import { NetworkSelector } from './NetworkSelector';
import { Node as NodeIcon } from '../svg-icons/node';
import { config } from '../../config';
export const AppBar = () => {
const { showSettings, logOut, handleShowSettings } = useContext(ClientContext);
const { showSettings, logOut, handleShowSettings, handleShowTerminal } = useContext(ClientContext);
const { IS_DEV_MODE } = config;
return (
<MuiAppBar position="sticky" sx={{ boxShadow: 'none', bgcolor: 'transparent' }}>
@@ -16,6 +19,13 @@ export const AppBar = () => {
<NetworkSelector />
</Grid>
<Grid item container justifyContent="flex-end" md={12} lg={5} spacing={2}>
{IS_DEV_MODE && (
<Grid item>
<IconButton size="small" onClick={handleShowTerminal} sx={{ color: 'nym.background.dark' }}>
<TerminalIcon fontSize="small" />
</IconButton>
</Grid>
)}
<Grid item>
<IconButton
onClick={handleShowSettings}
+19 -1
View File
@@ -29,6 +29,7 @@ type TClientContext = {
userBalance: TUseuserBalance;
showAdmin: boolean;
showSettings: boolean;
showTerminal: boolean;
network?: Network;
currency?: TCurrency;
isLoading: boolean;
@@ -39,6 +40,7 @@ type TClientContext = {
getBondDetails: () => Promise<void>;
handleShowSettings: () => void;
handleShowAdmin: () => void;
handleShowTerminal: () => void;
logIn: (opts: { type: 'mnemonic' | 'password'; value: string }) => void;
signInWithPassword: (password: string) => void;
logOut: () => void;
@@ -53,6 +55,7 @@ export const ClientContextProvider = ({ children }: { children: React.ReactNode
const [currency, setCurrency] = useState<TCurrency>();
const [showAdmin, setShowAdmin] = useState(false);
const [showSettings, setShowSettings] = useState(false);
const [showTerminal, setShowTerminal] = useState(false);
const [mode] = useState<'light' | 'dark'>('light');
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string>();
@@ -128,6 +131,7 @@ export const ClientContextProvider = ({ children }: { children: React.ReactNode
const handleShowAdmin = () => setShowAdmin((show) => !show);
const handleShowSettings = () => setShowSettings((show) => !show);
const handleShowTerminal = () => setShowTerminal((show) => !show);
const switchNetwork = (_network: Network) => setNetwork(_network);
const memoizedValue = useMemo(
@@ -140,6 +144,7 @@ export const ClientContextProvider = ({ children }: { children: React.ReactNode
userBalance,
showAdmin,
showSettings,
showTerminal,
network,
currency,
setIsLoading,
@@ -149,10 +154,23 @@ export const ClientContextProvider = ({ children }: { children: React.ReactNode
getBondDetails,
handleShowSettings,
handleShowAdmin,
handleShowTerminal,
logIn,
logOut,
}),
[mode, isLoading, error, clientDetails, mixnodeDetails, userBalance, showAdmin, showSettings, network, currency],
[
mode,
isLoading,
error,
clientDetails,
mixnodeDetails,
userBalance,
showAdmin,
showSettings,
showTerminal,
network,
currency,
],
);
return <ClientContext.Provider value={memoizedValue}>{children}</ClientContext.Provider>;
+2
View File
@@ -11,6 +11,7 @@ import { ErrorFallback } from './components';
import { NymWalletTheme, WelcomeTheme } from './theme';
import { maximizeWindow } from './utils';
import { SignInProvider } from './pages/sign-in/context';
import { Terminal } from './pages/terminal';
const App = () => {
const { clientDetails } = useContext(ClientContext);
@@ -30,6 +31,7 @@ const App = () => {
<ApplicationLayout>
<Settings />
<Admin />
<Terminal />
<AppRoutes />
</ApplicationLayout>
</NymWalletTheme>
+167
View File
@@ -0,0 +1,167 @@
import React, { useContext, useState } from 'react';
import { Alert, Box, Dialog, Paper, Typography } from '@mui/material';
import TerminalIcon from '@mui/icons-material/Terminal';
import RefreshIcon from '@mui/icons-material/Refresh';
import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
import ArrowDropUpIcon from '@mui/icons-material/ArrowDropUp';
import { ClientContext } from '../../context/main';
import { NymCard } from '../../components';
import { getCurrentEpoch, getPendingDelegations, getReverseMixDelegations } from '../../requests';
import { useGetBalance } from '../../hooks/useGetBalance';
const TerminalSection: React.FC<{
heading: React.ReactNode;
}> = ({ heading, children }) => {
const [isCollapsed, setIsCollapsed] = useState<boolean>(true);
const toggleCollapse = () => {
setIsCollapsed((prev) => !prev);
};
return (
<Box mb={2}>
<Typography display="flex">
{isCollapsed ? <ArrowDropDownIcon onClick={toggleCollapse} /> : <ArrowDropUpIcon onClick={toggleCollapse} />}
<Typography ml={2} fontWeight={600}>
{heading}
</Typography>
</Typography>
{!isCollapsed && <Paper sx={{ px: 3, py: 0.5 }}>{children}</Paper>}
</Box>
);
};
export const Terminal: React.FC = () => {
const { userBalance, clientDetails, showTerminal, handleShowTerminal } = useContext(ClientContext);
const { balance, vestingAccountInfo, currentVestingPeriod, originalVesting, fetchBalance, fetchTokenAllocation } =
useGetBalance(clientDetails?.client_address);
const [mixnodeDelegations, setMixnodeDelegations] = useState<any>();
const [pendingEvents, setPendingEvents] = useState<any>();
const [epoch, setEpoch] = useState<any>();
const [isBusy, setIsBusy] = useState<boolean>();
const [error, setError] = useState<any>();
const [status, setStatus] = useState<string | undefined>();
const withErrorCatch = async (fn: () => Promise<void>) => {
try {
await fn();
} catch (e) {
setError(e);
}
};
const refresh = async () => {
setError(undefined);
setIsBusy(true);
setStatus('Getting reverse mix delegations...');
await withErrorCatch(async () => {
setMixnodeDelegations(await getReverseMixDelegations());
});
setStatus('Getting pending delegations...');
await withErrorCatch(async () => {
setPendingEvents(await getPendingDelegations());
});
setStatus('Getting current epoch...');
await withErrorCatch(async () => {
setEpoch(await getCurrentEpoch());
});
setStatus('Fetching balance...');
await withErrorCatch(async () => {
await fetchBalance();
});
setStatus('Fetching token allocation...');
await withErrorCatch(async () => {
await fetchTokenAllocation();
});
setStatus(undefined);
setIsBusy(false);
};
React.useEffect(() => {
refresh();
}, []);
if (!showTerminal) {
return null;
}
return (
<Dialog open onClose={handleShowTerminal} maxWidth="md" fullWidth>
<NymCard
title={
<Box display="flex" alignItems="center">
<TerminalIcon sx={{ mr: 1 }} />
<Typography mr={4}>Terminal</Typography>
{!isBusy && <RefreshIcon onClick={refresh} />}
</Box>
}
>
{error && <Alert color="error">{error}</Alert>}
{status ? (
<Alert color="info" sx={{ mb: 2 }}>
<strong>{status}</strong>
</Alert>
) : (
<Alert color="success" sx={{ mb: 2 }}>
<strong>Data loading complete</strong>
</Alert>
)}
<TerminalSection heading="Client Details">
<pre>{JSON.stringify(clientDetails, null, 2)}</pre>
</TerminalSection>
<TerminalSection heading="User Balance">
<pre>{JSON.stringify(userBalance, null, 2)}</pre>
</TerminalSection>
<TerminalSection
heading={
<>
<code>useGetBalance</code> Balance
</>
}
>
<pre>{JSON.stringify(balance, null, 2)}</pre>
</TerminalSection>
<TerminalSection
heading={
<>
<code>useGetBalance</code> Vesting Account Info
</>
}
>
<pre>{JSON.stringify(vestingAccountInfo, null, 2)}</pre>
</TerminalSection>
<TerminalSection
heading={
<>
<code>useGetBalance</code> Current Vest Period
</>
}
>
<pre>{JSON.stringify(currentVestingPeriod, null, 2)}</pre>
</TerminalSection>
<TerminalSection heading="Original Vesting">
<pre>{JSON.stringify(originalVesting, null, 2)}</pre>
</TerminalSection>
<TerminalSection heading="Mixnode Delegations">
<pre>{JSON.stringify(mixnodeDelegations, null, 2)}</pre>
</TerminalSection>
<TerminalSection heading="Pending Delegation Events">
<pre>{JSON.stringify(pendingEvents, null, 2)}</pre>
</TerminalSection>
<TerminalSection heading="Epoch">
<pre>{JSON.stringify(epoch, null, 2)}</pre>
</TerminalSection>
</NymCard>
</Dialog>
);
};