2022-08-12 15:30:53 +02:00
|
|
|
import { createStyles, Stack, Title, useMantineColorScheme, useMantineTheme } from '@mantine/core';
|
2022-06-27 17:27:59 +02:00
|
|
|
import { IconCalendar as CalendarIcon } from '@tabler/icons';
|
|
|
|
|
import axios from 'axios';
|
2022-08-22 09:50:54 +02:00
|
|
|
import { useTranslation } from 'next-i18next';
|
2022-06-27 17:27:59 +02:00
|
|
|
import { useEffect, useState } from 'react';
|
2022-07-23 22:22:55 +02:00
|
|
|
import { useConfig } from '../../tools/state';
|
|
|
|
|
import { serviceItem } from '../../tools/types';
|
|
|
|
|
import { IModule } from '../ModuleTypes';
|
2022-06-27 17:27:59 +02:00
|
|
|
|
|
|
|
|
const asModule = <T extends IModule>(t: T) => t;
|
|
|
|
|
export const DashdotModule = asModule({
|
2022-08-24 20:13:53 +02:00
|
|
|
title: 'Dash.',
|
2022-06-27 17:27:59 +02:00
|
|
|
icon: CalendarIcon,
|
|
|
|
|
component: DashdotComponent,
|
|
|
|
|
options: {
|
|
|
|
|
cpuMultiView: {
|
2022-08-24 19:51:54 +02:00
|
|
|
name: 'descriptor.settings.cpuMultiView.label',
|
2022-06-27 17:27:59 +02:00
|
|
|
value: false,
|
|
|
|
|
},
|
|
|
|
|
storageMultiView: {
|
2022-08-24 19:51:54 +02:00
|
|
|
name: 'descriptor.settings.storageMultiView.label',
|
2022-06-27 17:27:59 +02:00
|
|
|
value: false,
|
|
|
|
|
},
|
|
|
|
|
useCompactView: {
|
2022-08-24 19:51:54 +02:00
|
|
|
name: 'descriptor.settings.useCompactView.label',
|
2022-06-27 17:27:59 +02:00
|
|
|
value: false,
|
|
|
|
|
},
|
2022-06-28 12:51:44 +02:00
|
|
|
graphs: {
|
2022-08-24 19:51:54 +02:00
|
|
|
name: 'descriptor.settings.graphs.label',
|
2022-06-28 12:51:44 +02:00
|
|
|
value: ['CPU', 'RAM', 'Storage', 'Network'],
|
2022-09-09 21:09:47 +02:00
|
|
|
options: ['CPU', 'RAM', 'Storage', 'Network', 'GPU'],
|
2022-06-27 17:27:59 +02:00
|
|
|
},
|
2022-08-10 14:13:20 +02:00
|
|
|
url: {
|
2022-08-24 19:51:54 +02:00
|
|
|
name: 'descriptor.settings.url.label',
|
2022-08-10 14:13:20 +02:00
|
|
|
value: '',
|
|
|
|
|
},
|
2022-06-27 17:27:59 +02:00
|
|
|
},
|
2022-08-25 11:07:25 +02:00
|
|
|
id: 'dashdot',
|
2022-06-27 17:27:59 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const useStyles = createStyles((theme, _params) => ({
|
|
|
|
|
heading: {
|
|
|
|
|
marginTop: 0,
|
|
|
|
|
marginBottom: 10,
|
|
|
|
|
},
|
|
|
|
|
table: {
|
|
|
|
|
display: 'table',
|
|
|
|
|
},
|
|
|
|
|
tableRow: {
|
|
|
|
|
display: 'table-row',
|
|
|
|
|
},
|
|
|
|
|
tableLabel: {
|
|
|
|
|
display: 'table-cell',
|
|
|
|
|
paddingRight: 10,
|
|
|
|
|
},
|
|
|
|
|
tableValue: {
|
|
|
|
|
display: 'table-cell',
|
|
|
|
|
whiteSpace: 'pre-wrap',
|
|
|
|
|
paddingBottom: 5,
|
|
|
|
|
},
|
|
|
|
|
graphsContainer: {
|
|
|
|
|
display: 'flex',
|
|
|
|
|
flexDirection: 'row',
|
|
|
|
|
flexWrap: 'wrap',
|
2022-06-30 16:08:26 +02:00
|
|
|
rowGap: 10,
|
2022-06-27 17:27:59 +02:00
|
|
|
columnGap: 10,
|
|
|
|
|
},
|
|
|
|
|
iframe: {
|
|
|
|
|
flex: '1 0 auto',
|
|
|
|
|
maxWidth: '100%',
|
|
|
|
|
height: '140px',
|
|
|
|
|
borderRadius: theme.radius.lg,
|
|
|
|
|
},
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
const bpsPrettyPrint = (bits?: number) =>
|
|
|
|
|
!bits
|
|
|
|
|
? '-'
|
|
|
|
|
: bits > 1000 * 1000 * 1000
|
|
|
|
|
? `${(bits / 1000 / 1000 / 1000).toFixed(1)} Gb/s`
|
|
|
|
|
: bits > 1000 * 1000
|
|
|
|
|
? `${(bits / 1000 / 1000).toFixed(1)} Mb/s`
|
|
|
|
|
: bits > 1000
|
|
|
|
|
? `${(bits / 1000).toFixed(1)} Kb/s`
|
|
|
|
|
: `${bits.toFixed(1)} b/s`;
|
|
|
|
|
|
|
|
|
|
const bytePrettyPrint = (byte: number): string =>
|
|
|
|
|
byte > 1024 * 1024 * 1024
|
|
|
|
|
? `${(byte / 1024 / 1024 / 1024).toFixed(1)} GiB`
|
|
|
|
|
: byte > 1024 * 1024
|
|
|
|
|
? `${(byte / 1024 / 1024).toFixed(1)} MiB`
|
|
|
|
|
: byte > 1024
|
|
|
|
|
? `${(byte / 1024).toFixed(1)} KiB`
|
|
|
|
|
: `${byte.toFixed(1)} B`;
|
|
|
|
|
|
2022-08-01 16:36:00 +02:00
|
|
|
const useJson = (targetUrl: string, url: string) => {
|
2022-06-27 17:27:59 +02:00
|
|
|
const [data, setData] = useState<any | undefined>();
|
|
|
|
|
|
|
|
|
|
const doRequest = async () => {
|
|
|
|
|
try {
|
2022-09-12 17:46:46 +02:00
|
|
|
const resp = await axios.get('/api/modules/dashdot',{ params: { url, base: targetUrl } });
|
2022-06-27 17:27:59 +02:00
|
|
|
|
|
|
|
|
setData(resp.data);
|
|
|
|
|
// eslint-disable-next-line no-empty
|
|
|
|
|
} catch (e) {}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
2022-08-01 16:36:00 +02:00
|
|
|
if (targetUrl) {
|
2022-06-27 17:27:59 +02:00
|
|
|
doRequest();
|
|
|
|
|
}
|
2022-08-01 16:36:00 +02:00
|
|
|
}, [targetUrl]);
|
2022-06-27 17:27:59 +02:00
|
|
|
|
|
|
|
|
return data;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export function DashdotComponent() {
|
|
|
|
|
const { config } = useConfig();
|
|
|
|
|
const theme = useMantineTheme();
|
|
|
|
|
const { classes } = useStyles();
|
|
|
|
|
const { colorScheme } = useMantineColorScheme();
|
|
|
|
|
|
2022-09-09 21:09:47 +02:00
|
|
|
const dashConfig = config.modules?.[DashdotModule.id].options as typeof DashdotModule['options'];
|
2022-06-27 17:27:59 +02:00
|
|
|
const isCompact = dashConfig?.useCompactView?.value ?? false;
|
2022-08-01 16:36:00 +02:00
|
|
|
const dashdotService: serviceItem | undefined = config.services.filter(
|
|
|
|
|
(service) => service.type === 'Dash.'
|
|
|
|
|
)[0];
|
|
|
|
|
const dashdotUrl = dashdotService?.url ?? dashConfig?.url?.value ?? '';
|
2022-06-28 12:51:44 +02:00
|
|
|
const enabledGraphs = dashConfig?.graphs?.value ?? ['CPU', 'RAM', 'Storage', 'Network'];
|
|
|
|
|
const cpuEnabled = enabledGraphs.includes('CPU');
|
|
|
|
|
const storageEnabled = enabledGraphs.includes('Storage');
|
|
|
|
|
const ramEnabled = enabledGraphs.includes('RAM');
|
|
|
|
|
const networkEnabled = enabledGraphs.includes('Network');
|
|
|
|
|
const gpuEnabled = enabledGraphs.includes('GPU');
|
2022-06-27 17:27:59 +02:00
|
|
|
|
2022-08-01 16:36:00 +02:00
|
|
|
const info = useJson(dashdotUrl, '/info');
|
|
|
|
|
const storageLoad = useJson(dashdotUrl, '/load/storage');
|
2022-06-27 17:27:59 +02:00
|
|
|
|
|
|
|
|
const totalUsed =
|
|
|
|
|
(storageLoad?.layout as any[])?.reduce((acc, curr) => (curr.load ?? 0) + acc, 0) ?? 0;
|
|
|
|
|
const totalSize =
|
|
|
|
|
(info?.storage?.layout as any[])?.reduce((acc, curr) => (curr.size ?? 0) + acc, 0) ?? 0;
|
|
|
|
|
|
2022-08-25 11:07:25 +02:00
|
|
|
const { t } = useTranslation('modules/dashdot');
|
2022-08-22 09:50:54 +02:00
|
|
|
|
2022-06-27 17:27:59 +02:00
|
|
|
const graphs = [
|
|
|
|
|
{
|
2022-09-19 21:13:39 +02:00
|
|
|
id: 'cpu',
|
2022-08-22 09:50:54 +02:00
|
|
|
name: t('card.graphs.cpu.title'),
|
2022-06-27 17:27:59 +02:00
|
|
|
enabled: cpuEnabled,
|
|
|
|
|
params: {
|
|
|
|
|
multiView: dashConfig?.cpuMultiView?.value ?? false,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
2022-09-19 21:13:39 +02:00
|
|
|
id: 'storage',
|
2022-09-09 21:09:47 +02:00
|
|
|
name: t('card.graphs.storage.title'),
|
2022-06-27 17:27:59 +02:00
|
|
|
enabled: storageEnabled && !isCompact,
|
|
|
|
|
params: {
|
|
|
|
|
multiView: dashConfig?.storageMultiView?.value ?? false,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
2022-09-19 21:13:39 +02:00
|
|
|
id: 'ram',
|
2022-08-22 09:50:54 +02:00
|
|
|
name: t('card.graphs.memory.title'),
|
2022-06-27 17:27:59 +02:00
|
|
|
enabled: ramEnabled,
|
|
|
|
|
},
|
|
|
|
|
{
|
2022-09-19 21:13:39 +02:00
|
|
|
id: 'network',
|
2022-08-22 09:50:54 +02:00
|
|
|
name: t('card.graphs.network.title'),
|
2022-06-27 17:27:59 +02:00
|
|
|
enabled: networkEnabled,
|
|
|
|
|
spanTwo: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
2022-09-19 21:13:39 +02:00
|
|
|
id: 'gpu',
|
2022-08-22 09:50:54 +02:00
|
|
|
name: t('card.graphs.gpu.title'),
|
2022-06-27 17:27:59 +02:00
|
|
|
enabled: gpuEnabled,
|
|
|
|
|
spanTwo: true,
|
|
|
|
|
},
|
|
|
|
|
].filter((g) => g.enabled);
|
|
|
|
|
|
2022-08-01 16:36:00 +02:00
|
|
|
if (dashdotUrl === '') {
|
|
|
|
|
return (
|
|
|
|
|
<div>
|
2022-08-22 09:50:54 +02:00
|
|
|
<h2 className={classes.heading}>{t('card.title')}</h2>
|
|
|
|
|
<p>{t('card.errors.noService')}</p>
|
2022-08-01 16:36:00 +02:00
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-27 17:27:59 +02:00
|
|
|
return (
|
|
|
|
|
<div>
|
2022-08-22 09:50:54 +02:00
|
|
|
<h2 className={classes.heading}>{t('card.title')}</h2>
|
2022-06-27 17:27:59 +02:00
|
|
|
|
2022-08-01 16:36:00 +02:00
|
|
|
{!info ? (
|
2022-08-22 09:50:54 +02:00
|
|
|
<p>{t('card.errors.noInformation')}</p>
|
2022-06-27 17:27:59 +02:00
|
|
|
) : (
|
|
|
|
|
<div className={classes.graphsContainer}>
|
|
|
|
|
<div className={classes.table}>
|
|
|
|
|
{storageEnabled && isCompact && (
|
|
|
|
|
<div className={classes.tableRow}>
|
2022-08-22 09:50:54 +02:00
|
|
|
<p className={classes.tableLabel}>{t('card.graphs.storage.label')}</p>
|
2022-06-27 17:27:59 +02:00
|
|
|
<p className={classes.tableValue}>
|
2022-07-21 11:43:43 +02:00
|
|
|
{((100 * totalUsed) / (totalSize || 1)).toFixed(1)}%{'\n'}
|
2022-06-27 17:27:59 +02:00
|
|
|
{bytePrettyPrint(totalUsed)} / {bytePrettyPrint(totalSize)}
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
2022-07-20 14:47:51 +02:00
|
|
|
{networkEnabled && (
|
|
|
|
|
<div className={classes.tableRow}>
|
2022-08-22 09:50:54 +02:00
|
|
|
<p className={classes.tableLabel}>{t('card.graphs.network.label')}</p>
|
2022-07-20 14:47:51 +02:00
|
|
|
<p className={classes.tableValue}>
|
2022-08-22 09:50:54 +02:00
|
|
|
{bpsPrettyPrint(info?.network?.speedUp)} {t('card.graphs.network.metrics.upload')}
|
2022-08-18 21:46:46 +02:00
|
|
|
{'\n'}
|
|
|
|
|
{bpsPrettyPrint(info?.network?.speedDown)}
|
2022-08-22 09:50:54 +02:00
|
|
|
{t('card.graphs.network.metrics.download')}
|
2022-07-20 14:47:51 +02:00
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
2022-06-27 17:27:59 +02:00
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{graphs.map((graph) => (
|
2022-09-09 21:09:47 +02:00
|
|
|
<Stack
|
|
|
|
|
style={
|
|
|
|
|
isCompact
|
|
|
|
|
? {
|
|
|
|
|
width: graph.spanTwo ? '100%' : 'calc(50% - 5px)',
|
|
|
|
|
position: 'relative',
|
|
|
|
|
}
|
|
|
|
|
: undefined
|
|
|
|
|
}
|
|
|
|
|
>
|
2022-08-12 15:30:53 +02:00
|
|
|
<Title style={{ position: 'absolute', right: 0 }} order={4} mt={10} mr={25}>
|
|
|
|
|
{graph.name}
|
|
|
|
|
</Title>
|
|
|
|
|
<iframe
|
|
|
|
|
className={classes.iframe}
|
|
|
|
|
key={graph.name}
|
|
|
|
|
title={graph.name}
|
2022-09-19 21:13:39 +02:00
|
|
|
src={`${dashdotUrl}?singleGraphMode=true&graph=${graph.id.toLowerCase()}&theme=${colorScheme}&surface=${(colorScheme ===
|
2022-08-12 15:30:53 +02:00
|
|
|
'dark'
|
|
|
|
|
? theme.colors.dark[7]
|
|
|
|
|
: theme.colors.gray[0]
|
|
|
|
|
).substring(1)}${isCompact ? '&gap=10' : '&gap=5'}&innerRadius=${theme.radius.lg}${
|
|
|
|
|
graph.params
|
|
|
|
|
? `&${Object.entries(graph.params)
|
|
|
|
|
.map(([key, value]) => `${key}=${value.toString()}`)
|
|
|
|
|
.join('&')}`
|
|
|
|
|
: ''
|
|
|
|
|
}`}
|
|
|
|
|
frameBorder="0"
|
|
|
|
|
/>
|
|
|
|
|
</Stack>
|
2022-06-27 17:27:59 +02:00
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|