Merge branch 'dev' into fix/beszel-widget-transparency-and-errors
This commit is contained in:
70 files changed
+1930
-1254
No files matched your search
@@ -200,6 +200,17 @@ export default function DockerWidget({ options, width, isEditMode }: WidgetCompo
|
||||
|
||||
const totalContainers = containers.length;
|
||||
|
||||
const totals = useMemo(() => {
|
||||
return containers.reduce(
|
||||
(acc, container) => {
|
||||
acc.cpu += safeValue(container.cpuUsage);
|
||||
acc.memory += safeValue(container.memoryUsage);
|
||||
return acc;
|
||||
},
|
||||
{ cpu: 0, memory: 0 }
|
||||
);
|
||||
}, [containers]);
|
||||
|
||||
const columns = useMemo(() => createColumns(t), [t]);
|
||||
|
||||
const table = useTranslatedMantineReactTable({
|
||||
@@ -261,12 +272,26 @@ export default function DockerWidget({ options, width, isEditMode }: WidgetCompo
|
||||
}}
|
||||
p={4}
|
||||
>
|
||||
<Group gap={4}>
|
||||
<IconBrandDocker size={20} />
|
||||
<Text size="sm">{t("table.footer", { count: totalContainers.toString() })}</Text>
|
||||
<Group gap={4} wrap="nowrap">
|
||||
<IconBrandDocker size={20} style={{ flexShrink: 0 }} />
|
||||
<Text size="sm" truncate="end">
|
||||
{t("table.footer", { count: totalContainers.toString() })}
|
||||
</Text>
|
||||
</Group>
|
||||
|
||||
<Text size="sm">{t("table.updated", { when: relativeTime })}</Text>
|
||||
<Group gap="sm" wrap="wrap" justify="flex-end" style={{ flex: 1, minWidth: 0 }}>
|
||||
<Text size="sm" style={{ whiteSpace: "nowrap" }}>
|
||||
{t("table.totalCpu", { cpu: totals.cpu.toFixed(2) })}
|
||||
</Text>
|
||||
|
||||
<Text size="sm" style={{ whiteSpace: "nowrap" }}>
|
||||
{t("table.totalMemory", { memory: humanFileSize(totals.memory) })}
|
||||
</Text>
|
||||
|
||||
<Text size="sm" style={{ whiteSpace: "nowrap" }}>
|
||||
{t("table.updated", { when: relativeTime })}
|
||||
</Text>
|
||||
</Group>
|
||||
</Group>
|
||||
)}
|
||||
</Stack>
|
||||
|
||||
@@ -529,6 +529,16 @@ export default function DownloadClientsWidget({
|
||||
},
|
||||
{
|
||||
...columnsDefBase({ key: "time", showHeader: true }),
|
||||
sortingFn: (rowA, rowB) => {
|
||||
const timeA = rowA.getValue<ExtendedDownloadClientItem["time"]>("time");
|
||||
const timeB = rowB.getValue<ExtendedDownloadClientItem["time"]>("time");
|
||||
// Map time values to canonical sort keys:
|
||||
// positive = ETA in ms (sort as-is, smaller = sooner)
|
||||
// 0 = stalled/infinite (sort last in ascending = Infinity)
|
||||
// negative = time since completion in ms (sort first in ascending = very negative)
|
||||
const toSortKey = (time: number) => (time === 0 ? Infinity : time);
|
||||
return toSortKey(timeA) - toSortKey(timeB);
|
||||
},
|
||||
Cell: ({ cell }) => {
|
||||
const time = cell.getValue<ExtendedDownloadClientItem["time"]>();
|
||||
return time === 0 ? <IconInfinity size={16} /> : <Text size="xs">{dayjs().add(time).fromNow()}</Text>;
|
||||
|
||||
Reference in new issue
Block a user