feat: modernize dashboard widgets
This commit is contained in:
1 parent
1a5e083fd0
commit
6f2cd7fc2b
270 files changed
+10189
-3544
No files matched your search
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { Group, Stack, Text } from "@mantine/core";
|
||||
import { Group, Progress, ScrollArea, SimpleGrid, Stack, Text } from "@mantine/core";
|
||||
import { IconDatabase, IconPhoto, IconUsers, IconVideo } from "@tabler/icons-react";
|
||||
|
||||
import { clientApi } from "@homarr/api/client";
|
||||
@@ -15,16 +15,22 @@ import classes from "./component.module.css";
|
||||
export default function ImmichServerStatsWidget({
|
||||
integrationIds,
|
||||
options,
|
||||
displayMode = "compact",
|
||||
width,
|
||||
}: WidgetComponentProps<"immich-serverStats">) {
|
||||
const t = useI18n();
|
||||
const { data: stats } = clientApi.widget.immich.getServerStats.useQuery({
|
||||
integrationId: integrationIds[0] ?? "",
|
||||
});
|
||||
const { data: albums = [] } = clientApi.widget.immich.getAlbums.useQuery(
|
||||
{ integrationId: integrationIds[0] ?? "" },
|
||||
{ enabled: displayMode === "advanced" && integrationIds.length > 0, staleTime: 15 * 60 * 1000 },
|
||||
);
|
||||
|
||||
if (!stats) return <WidgetEmptyState />;
|
||||
|
||||
return (
|
||||
<Stack gap="md" h="100%" p="md">
|
||||
const statsContent = (
|
||||
<SimpleGrid cols={displayMode === "advanced" ? 4 : width >= 320 ? 2 : 1} spacing="sm">
|
||||
{options.showUsers && (
|
||||
<StatItem icon={<IconUsers size={20} />} label={t("widget.immich-serverStats.users")} value={stats.userCount} />
|
||||
)}
|
||||
@@ -49,6 +55,39 @@ export default function ImmichServerStatsWidget({
|
||||
value={formatBytes(stats.totalLibraryUsageInBytes)}
|
||||
/>
|
||||
)}
|
||||
</SimpleGrid>
|
||||
);
|
||||
|
||||
if (displayMode === "compact") {
|
||||
return (
|
||||
<Stack gap="md" h="100%" p="md" justify="center">
|
||||
{statsContent}
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
const sortedAlbums = [...albums].toSorted((left, right) => right.assetCount - left.assetCount);
|
||||
const maxAssets = sortedAlbums[0]?.assetCount ?? 1;
|
||||
return (
|
||||
<Stack gap="lg" h="100%" p="lg">
|
||||
{statsContent}
|
||||
<ScrollArea style={{ flex: 1, minHeight: 0 }}>
|
||||
<SimpleGrid cols={width >= 900 ? 2 : 1} spacing="xs">
|
||||
{sortedAlbums.map((album) => (
|
||||
<Stack key={album.id} gap={4} p="xs">
|
||||
<Group justify="space-between" wrap="nowrap">
|
||||
<Text size="sm" fw={600} truncate>
|
||||
{album.albumName}
|
||||
</Text>
|
||||
<Text size="xs" c="dimmed">
|
||||
{album.assetCount.toLocaleString()}
|
||||
</Text>
|
||||
</Group>
|
||||
<Progress value={(album.assetCount / Math.max(maxAssets, 1)) * 100} size="sm" />
|
||||
</Stack>
|
||||
))}
|
||||
</SimpleGrid>
|
||||
</ScrollArea>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ export const { definition, componentLoader } = createWidgetDefinition("immich-se
|
||||
refetchInterval: null,
|
||||
supportedIntegrations: ["immich"],
|
||||
integrationsRequired: true,
|
||||
maxIntegrations: 1,
|
||||
createOptions() {
|
||||
return optionsBuilder.from((factory) => ({
|
||||
showUsers: factory.switch({
|
||||
|
||||
Reference in new issue
Block a user