feat: add spinner

main
Josue 4 years ago committed by Tsu-ba-me
parent 0e1098d893
commit 64f0c2d756
  1. 48
      striker-ui/components/CPU.tsx
  2. 23
      striker-ui/components/Hosts/index.tsx
  3. 76
      striker-ui/components/Memory.tsx
  4. 73
      striker-ui/components/Network/Network.tsx
  5. 106
      striker-ui/components/Servers.tsx
  6. 71
      striker-ui/components/SharedStorage/SharedStorage.tsx
  7. 31
      striker-ui/components/Spinner.tsx

@ -5,6 +5,7 @@ import { AllocationBar } from './Bars';
import { HeaderText, BodyText } from './Text';
import PeriodicFetch from '../lib/fetchers/periodicFetch';
import { AnvilContext } from './AnvilContext';
import Spinner from './Spinner';
const CPU = (): JSX.Element => {
const { uuid } = useContext(AnvilContext);
@ -19,26 +20,33 @@ const CPU = (): JSX.Element => {
return (
<Panel>
<HeaderText text="CPU" />
<Box display="flex" width="100%">
<Box flexGrow={1}>
<BodyText text={`Allocated: ${cpuData.allocated}`} />
</Box>
<Box>
<BodyText text={`Free: ${cpuData.cores - cpuData.allocated}`} />
</Box>
</Box>
<Box display="flex" width="100%">
<Box flexGrow={1}>
<AllocationBar
allocated={(cpuData.allocated / cpuData.cores) * 100}
/>
</Box>
</Box>
<Box display="flex" justifyContent="center" width="100%">
<BodyText
text={`Total Cores: ${cpuData.cores}c | ${cpuData.threads}t`}
/>
</Box>
{!isLoading ? (
<>
{' '}
<Box display="flex" width="100%">
<Box flexGrow={1}>
<BodyText text={`Allocated: ${cpuData.allocated}`} />
</Box>
<Box>
<BodyText text={`Free: ${cpuData.cores - cpuData.allocated}`} />
</Box>
</Box>
<Box display="flex" width="100%">
<Box flexGrow={1}>
<AllocationBar
allocated={(cpuData.allocated / cpuData.cores) * 100}
/>
</Box>
</Box>
<Box display="flex" justifyContent="center" width="100%">
<BodyText
text={`Total Cores: ${cpuData.cores}c | ${cpuData.threads}t`}
/>
</Box>
</>
) : (
<Spinner />
)}
</Panel>
);
};

@ -4,25 +4,32 @@ import { HeaderText } from '../Text';
import AnvilHost from './AnvilHost';
import PeriodicFetch from '../../lib/fetchers/periodicFetch';
import { AnvilContext } from '../AnvilContext';
import Spinner from '../Spinner';
const Hosts = ({ anvil }: { anvil: AnvilListItem[] }): JSX.Element => {
const { uuid } = useContext(AnvilContext);
const { data } = PeriodicFetch<AnvilStatus>(
const { data, isLoading } = PeriodicFetch<AnvilStatus>(
`${process.env.NEXT_PUBLIC_API_URL}/get_status?anvil_uuid=${uuid}`,
);
return (
<Panel>
<HeaderText text="Nodes" />
{anvil.findIndex((a) => a.anvil_uuid === uuid) !== -1 && data && (
<AnvilHost
hosts={anvil[anvil.findIndex((a) => a.anvil_uuid === uuid)].hosts.map(
(host, index) => {
return data.hosts[index];
},
{!isLoading ? (
<>
{anvil.findIndex((a) => a.anvil_uuid === uuid) !== -1 && data && (
<AnvilHost
hosts={anvil[
anvil.findIndex((a) => a.anvil_uuid === uuid)
].hosts.map((host, index) => {
return data.hosts[index];
})}
/>
)}
/>
</>
) : (
<Spinner />
)}
</Panel>
);

@ -6,6 +6,7 @@ import { AllocationBar } from './Bars';
import { HeaderText, BodyText } from './Text';
import PeriodicFetch from '../lib/fetchers/periodicFetch';
import { AnvilContext } from './AnvilContext';
import Spinner from './Spinner';
const Memory = (): JSX.Element => {
const { uuid } = useContext(AnvilContext);
@ -19,41 +20,48 @@ const Memory = (): JSX.Element => {
return (
<Panel>
<HeaderText text="Memory" />
<Box display="flex" width="100%">
<Box flexGrow={1}>
<BodyText
text={`Allocated: ${prettyBytes.default(memoryData.allocated, {
binary: true,
})}`}
/>
</Box>
<Box>
<BodyText
text={`Free: ${prettyBytes.default(
memoryData.total - memoryData.allocated,
{
{!isLoading ? (
<>
{' '}
<Box display="flex" width="100%">
<Box flexGrow={1}>
<BodyText
text={`Allocated: ${prettyBytes.default(memoryData.allocated, {
binary: true,
})}`}
/>
</Box>
<Box>
<BodyText
text={`Free: ${prettyBytes.default(
memoryData.total - memoryData.allocated,
{
binary: true,
},
)}`}
/>
</Box>
</Box>
<Box display="flex" width="100%">
<Box flexGrow={1}>
<AllocationBar
allocated={(memoryData.allocated / memoryData.total) * 100}
/>
</Box>
</Box>
<Box display="flex" justifyContent="center" width="100%">
<BodyText
text={`Total: ${prettyBytes.default(memoryData.total, {
binary: true,
},
)}`}
/>
</Box>
</Box>
<Box display="flex" width="100%">
<Box flexGrow={1}>
<AllocationBar
allocated={(memoryData.allocated / memoryData.total) * 100}
/>
</Box>
</Box>
<Box display="flex" justifyContent="center" width="100%">
<BodyText
text={`Total: ${prettyBytes.default(memoryData.total, {
binary: true,
})} | Reserved: ${prettyBytes.default(memoryData.reserved, {
binary: true,
})}`}
/>
</Box>
})} | Reserved: ${prettyBytes.default(memoryData.reserved, {
binary: true,
})}`}
/>
</Box>
</>
) : (
<Spinner />
)}
</Panel>
);
};

@ -8,6 +8,7 @@ import { DIVIDER } from '../../lib/consts/DEFAULT_THEME';
import processNetworkData from './processNetwork';
import { AnvilContext } from '../AnvilContext';
import Decorator, { Colours } from '../Decorator';
import Spinner from '../Spinner';
const useStyles = makeStyles((theme) => ({
container: {
@ -48,7 +49,7 @@ const Network = (): JSX.Element => {
const { uuid } = useContext(AnvilContext);
const classes = useStyles();
const { data } = PeriodicFetch<AnvilNetwork>(
const { data, isLoading } = PeriodicFetch<AnvilNetwork>(
`${process.env.NEXT_PUBLIC_API_URL}/get_networks?anvil_uuid=${uuid}`,
);
@ -56,40 +57,44 @@ const Network = (): JSX.Element => {
return (
<Panel>
<HeaderText text="Network" />
<Box className={classes.container}>
{data &&
processed.bonds.map((bond: ProcessedBond) => {
return (
<>
<Box
display="flex"
flexDirection="row"
width="100%"
className={classes.root}
>
<Box p={1} className={classes.noPaddingLeft}>
<Decorator colour={selectDecorator(bond.bond_state)} />
</Box>
<Box p={1} flexGrow={1} className={classes.noPaddingLeft}>
<BodyText text={bond.bond_name} />
<BodyText text={`${bond.bond_speed}Mbps`} />
</Box>
{bond.hosts.map(
(host): JSX.Element => (
<Box p={1} key={host.host_name}>
<Box>
<BodyText text={host.host_name} selected={false} />
<BodyText text={host.link.link_name} />
{!isLoading ? (
<Box className={classes.container}>
{data &&
processed.bonds.map((bond: ProcessedBond) => {
return (
<>
<Box
display="flex"
flexDirection="row"
width="100%"
className={classes.root}
>
<Box p={1} className={classes.noPaddingLeft}>
<Decorator colour={selectDecorator(bond.bond_state)} />
</Box>
<Box p={1} flexGrow={1} className={classes.noPaddingLeft}>
<BodyText text={bond.bond_name} />
<BodyText text={`${bond.bond_speed}Mbps`} />
</Box>
{bond.hosts.map(
(host): JSX.Element => (
<Box p={1} key={host.host_name}>
<Box>
<BodyText text={host.host_name} selected={false} />
<BodyText text={host.link.link_name} />
</Box>
</Box>
</Box>
),
)}
</Box>
<Divider className={classes.divider} />
</>
);
})}
</Box>
),
)}
</Box>
<Divider className={classes.divider} />
</>
);
})}
</Box>
) : (
<Spinner />
)}
</Panel>
);
};

@ -8,6 +8,7 @@ import { HOVER, DIVIDER } from '../lib/consts/DEFAULT_THEME';
import { AnvilContext } from './AnvilContext';
import serverState from '../lib/consts/SERVERS';
import Decorator, { Colours } from './Decorator';
import Spinner from './Spinner';
const useStyles = makeStyles((theme) => ({
root: {
@ -49,64 +50,69 @@ const Servers = ({ anvil }: { anvil: AnvilListItem[] }): JSX.Element => {
const { uuid } = useContext(AnvilContext);
const classes = useStyles();
const { data } = PeriodicFetch<AnvilServers>(
const { data, isLoading } = PeriodicFetch<AnvilServers>(
`${process.env.NEXT_PUBLIC_API_URL}/get_servers?anvil_uuid=${uuid}`,
);
return (
<Panel>
<div className={classes.headerPadding}>
<HeaderText text="Servers" />
</div>
<Box className={classes.root}>
<List component="nav">
{data &&
data.servers.map((server: AnvilServer) => {
return (
<>
<ListItem
button
className={classes.button}
key={server.server_uuid}
>
<Box display="flex" flexDirection="row" width="100%">
<Box p={1}>
<Decorator
colour={selectDecorator(server.server_state)}
/>
</Box>
<Box p={1} flexGrow={1}>
<BodyText text={server.server_name} />
<BodyText
text={
serverState.get(server.server_state) ||
'Not Available'
}
/>
{!isLoading ? (
<Box className={classes.root}>
<List component="nav">
{data &&
data.servers.map((server: AnvilServer) => {
return (
<>
<ListItem
button
className={classes.button}
key={server.server_uuid}
>
<Box display="flex" flexDirection="row" width="100%">
<Box p={1}>
<Decorator
colour={selectDecorator(server.server_state)}
/>
</Box>
<Box p={1} flexGrow={1}>
<BodyText text={server.server_name} />
<BodyText
text={
serverState.get(server.server_state) ||
'Not Available'
}
/>
</Box>
{server.server_state !== 'shut_off' &&
server.server_state !== 'crashed' &&
anvil[
anvil.findIndex((a) => a.anvil_uuid === uuid)
].hosts.map(
(host: AnvilStatusHost): JSX.Element => (
<Box p={1} key={host.host_uuid}>
<BodyText
text={host.host_name}
selected={
server.server_host_uuid === host.host_uuid
}
/>
</Box>
),
)}
</Box>
{server.server_state !== 'shut_off' &&
server.server_state !== 'crashed' &&
anvil[
anvil.findIndex((a) => a.anvil_uuid === uuid)
].hosts.map(
(host: AnvilStatusHost): JSX.Element => (
<Box p={1} key={host.host_uuid}>
<BodyText
text={host.host_name}
selected={
server.server_host_uuid === host.host_uuid
}
/>
</Box>
),
)}
</Box>
</ListItem>
<Divider className={classes.divider} />
</>
);
})}
</List>
</Box>
</ListItem>
<Divider className={classes.divider} />
</>
);
})}
</List>
</Box>
) : (
<Spinner />
)}
</Panel>
);
};

@ -7,6 +7,7 @@ import { Panel, InnerPanel, PanelHeader } from '../Panels';
import SharedStorageHost from './SharedStorageHost';
import PeriodicFetch from '../../lib/fetchers/periodicFetch';
import { AnvilContext } from '../AnvilContext';
import Spinner from '../Spinner';
const useStyles = makeStyles((theme) => ({
header: {
@ -26,45 +27,49 @@ const useStyles = makeStyles((theme) => ({
const SharedStorage = ({ anvil }: { anvil: AnvilListItem[] }): JSX.Element => {
const classes = useStyles();
const { uuid } = useContext(AnvilContext);
const { data } = PeriodicFetch<AnvilSharedStorage>(
const { data, isLoading } = PeriodicFetch<AnvilSharedStorage>(
`${process.env.NEXT_PUBLIC_API_URL}/get_shared_storage?anvil_uuid=${uuid}`,
);
return (
<Panel>
<HeaderText text="Shared Storage" />
<Box className={classes.root}>
{data?.file_systems &&
data.file_systems.map(
(fs: AnvilSharedStorageFileSystem): JSX.Element => (
<InnerPanel key={fs.mount_point}>
<PanelHeader>
<Box display="flex" width="100%" className={classes.header}>
<Box>
<BodyText text={fs.mount_point} />
{!isLoading ? (
<Box className={classes.root}>
{data?.file_systems &&
data.file_systems.map(
(fs: AnvilSharedStorageFileSystem): JSX.Element => (
<InnerPanel key={fs.mount_point}>
<PanelHeader>
<Box display="flex" width="100%" className={classes.header}>
<Box>
<BodyText text={fs.mount_point} />
</Box>
</Box>
</Box>
</PanelHeader>
{fs?.hosts &&
fs.hosts.map(
(
host: AnvilSharedStorageHost,
index: number,
): JSX.Element => (
<SharedStorageHost
host={{
...host,
...anvil[
anvil.findIndex((a) => a.anvil_uuid === uuid)
].hosts[index],
}}
key={fs.hosts[index].free}
/>
),
)}
</InnerPanel>
),
)}
</Box>
</PanelHeader>
{fs?.hosts &&
fs.hosts.map(
(
host: AnvilSharedStorageHost,
index: number,
): JSX.Element => (
<SharedStorageHost
host={{
...host,
...anvil[
anvil.findIndex((a) => a.anvil_uuid === uuid)
].hosts[index],
}}
key={fs.hosts[index].free}
/>
),
)}
</InnerPanel>
),
)}
</Box>
) : (
<Spinner />
)}
</Panel>
);
};

@ -0,0 +1,31 @@
import { makeStyles } from '@material-ui/core/styles';
import CircularProgress from '@material-ui/core/CircularProgress';
const useStyles = makeStyles(() => ({
root: {
display: 'flex',
/* '& > * + *': {
marginLeft: theme.spacing(2),
}, */
alignItems: 'center',
justifyContent: 'center',
marginTop: '3em',
},
spinner: {
color: '#FFF',
variant: 'indeterminate',
size: '50em',
},
}));
const Spinner = (): JSX.Element => {
const classes = useStyles();
return (
<div className={classes.root}>
<CircularProgress className={classes.spinner} />
</div>
);
};
export default Spinner;
Loading…
Cancel
Save