From 5d1ab29955146eea7be073984261eec031dd29e8 Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Sat, 30 Sep 2023 04:11:58 -0400 Subject: [PATCH] fix(striker-ui): add anvil summary components --- striker-ui/components/Anvils/AnvilSummary.tsx | 202 ++++++++++++++++++ .../components/Anvils/AnvilSummaryList.tsx | 71 ++++++ striker-ui/types/AnvilSummary.d.ts | 7 + 3 files changed, 280 insertions(+) create mode 100644 striker-ui/components/Anvils/AnvilSummary.tsx create mode 100644 striker-ui/components/Anvils/AnvilSummaryList.tsx create mode 100644 striker-ui/types/AnvilSummary.d.ts diff --git a/striker-ui/components/Anvils/AnvilSummary.tsx b/striker-ui/components/Anvils/AnvilSummary.tsx new file mode 100644 index 00000000..053ab415 --- /dev/null +++ b/striker-ui/components/Anvils/AnvilSummary.tsx @@ -0,0 +1,202 @@ +import { Grid, gridClasses } from '@mui/material'; +import { dSizeStr } from 'format-data-size'; +import { FC, useMemo } from 'react'; + +import { BLUE, PURPLE, RED } from '../../lib/consts/DEFAULT_THEME'; + +import { + toAnvilMemoryCalcable, + toAnvilSharedStorageOverview, +} from '../../lib/api_converters'; +import FlexBox from '../FlexBox'; +import Spinner from '../Spinner'; +import StackBar from '../Bars/StackBar'; +import { BodyText, InlineMonoText, MonoText } from '../Text'; +import useFetch from '../../hooks/useFetch'; + +const n100 = BigInt(100); + +const AnvilSummary: FC = (props) => { + const { anvilUuid } = props; + + const { data: cpu, loading: loadingCpu } = useFetch( + `/anvil/${anvilUuid}/cpu`, + ); + + const cpuSubnodes = useMemo( + () => cpu && Object.values(cpu.hosts), + [cpu], + ); + + const { data: rMemory, loading: loadingMemory } = useFetch( + `/anvil/${anvilUuid}/memory`, + ); + + const memory = useMemo( + () => rMemory && toAnvilMemoryCalcable(rMemory), + [rMemory], + ); + + const { data: rStorages, loading: loadingStorages } = + useFetch(`/anvil/${anvilUuid}/store`); + + const storages = useMemo( + () => rStorages && toAnvilSharedStorageOverview(rStorages), + [rStorages], + ); + + const loading = useMemo( + () => loadingCpu || loadingMemory || loadingStorages, + [loadingCpu, loadingMemory, loadingStorages], + ); + + const cpuSummary = useMemo( + () => + cpu && + cpuSubnodes && ( + + + {cpuSubnodes[0].name} + {cpuSubnodes[0].vendor} + + .${gridClasses.item}:nth-child(-n + 2)`]: { + marginBottom: '-.6em', + }, + }} + width="calc(0% + 4em)" + > + + CORES + + + {cpu.cores} + + + THREADS + + + {cpu.threads} + + + + {cpuSubnodes[1].name} + {cpuSubnodes[1].vendor} + + + ), + [cpu, cpuSubnodes], + ); + + const memorySummary = useMemo( + () => + memory && ( + + + + FREE + + {dSizeStr(memory.total - (memory.reserved + memory.allocated), { + toUnit: 'ibyte', + })} + + / + + {dSizeStr(memory.total, { toUnit: 'ibyte' })} + + + + + + ), + [memory], + ); + + const storeSummary = useMemo( + () => + storages && ( + + + + FREE + + {dSizeStr(storages.totalFree, { toUnit: 'ibyte' })} + + / + + {dSizeStr(storages.totalSize, { toUnit: 'ibyte' })} + + + + + + ), + [storages], + ); + + return loading ? ( + + ) : ( + .${gridClasses.item}:nth-child(odd)`]: { + alignItems: 'center', + display: 'flex', + height: '2.5em', + }, + }} + > + + CPU + + + {cpuSummary} + + + Memory + + + {memorySummary} + + + Storage + + + {storeSummary} + + + ); +}; + +export default AnvilSummary; diff --git a/striker-ui/components/Anvils/AnvilSummaryList.tsx b/striker-ui/components/Anvils/AnvilSummaryList.tsx new file mode 100644 index 00000000..5c09eb5f --- /dev/null +++ b/striker-ui/components/Anvils/AnvilSummaryList.tsx @@ -0,0 +1,71 @@ +import { FC, ReactNode, useMemo } from 'react'; + +import AnvilSummary from './AnvilSummary'; +import { toAnvilOverviewList } from '../../lib/api_converters'; +import Grid from '../Grid'; +import { + InnerPanel, + InnerPanelBody, + InnerPanelHeader, + Panel, + PanelHeader, +} from '../Panels'; +import Spinner from '../Spinner'; +import { BodyText, HeaderText } from '../Text'; +import useFetch from '../../hooks/useFetch'; + +const AnvilSummaryList: FC = () => { + const { data: rawAnvils, loading: loadingAnvils } = + useFetch('/anvil', { refreshInterval: 5000 }); + + const anvils = useMemo( + () => rawAnvils && toAnvilOverviewList(rawAnvils), + [rawAnvils], + ); + + const grid = useMemo( + () => + anvils && ( + ( + (previous, current) => { + const { description, name, uuid } = current; + + const key = `anvil-${uuid}`; + + previous[key] = { + children: ( + + + + {name}: {description} + + + + + + + ), + }; + + return previous; + }, + {}, + )} + /> + ), + [anvils], + ); + + return ( + + + Nodes + + {loadingAnvils ? : grid} + + ); +}; + +export default AnvilSummaryList; diff --git a/striker-ui/types/AnvilSummary.d.ts b/striker-ui/types/AnvilSummary.d.ts new file mode 100644 index 00000000..8cfd05ff --- /dev/null +++ b/striker-ui/types/AnvilSummary.d.ts @@ -0,0 +1,7 @@ +type AnvilSummaryOptionalProps = { + loading?: boolean; +}; + +type AnvilSummaryProps = AnvilSummaryOptionalProps & { + anvilUuid: string; +};