refactor: replace serverdata with suspense query (#1265)
* refactor: replace serverdata with suspense query * fix: deepsource issues
This commit is contained in:
@@ -21,7 +21,7 @@ import {
|
||||
Title,
|
||||
Tooltip,
|
||||
} from "@mantine/core";
|
||||
import { useDisclosure, useListState, useTimeout } from "@mantine/hooks";
|
||||
import { useDisclosure, useTimeout } from "@mantine/hooks";
|
||||
import type { IconProps } from "@tabler/icons-react";
|
||||
import {
|
||||
IconAlertTriangle,
|
||||
@@ -40,9 +40,6 @@ import { MantineReactTable, useMantineReactTable } from "mantine-react-table";
|
||||
import { clientApi } from "@homarr/api/client";
|
||||
import { useIntegrationsWithInteractAccess } from "@homarr/auth/client";
|
||||
import { humanFileSize } from "@homarr/common";
|
||||
import type { Modify } from "@homarr/common/types";
|
||||
import type { Integration } from "@homarr/db/schema/sqlite";
|
||||
import type { IntegrationKindByCategory } from "@homarr/definitions";
|
||||
import { getIconUrl, getIntegrationKindsByCategory } from "@homarr/definitions";
|
||||
import type {
|
||||
DownloadClientJobsAndStatus,
|
||||
@@ -91,30 +88,35 @@ export default function DownloadClientsWidget({
|
||||
isEditMode,
|
||||
integrationIds,
|
||||
options,
|
||||
serverData,
|
||||
setOptions,
|
||||
}: WidgetComponentProps<"downloads">) {
|
||||
const integrationsWithInteractions = useIntegrationsWithInteractAccess().flatMap(({ id }) =>
|
||||
integrationIds.includes(id) ? [id] : [],
|
||||
);
|
||||
|
||||
const [currentItems, currentItemsHandlers] = useListState<{
|
||||
integration: Modify<Integration, { kind: IntegrationKindByCategory<"downloadClient"> }>;
|
||||
timestamp: Date;
|
||||
data: DownloadClientJobsAndStatus | null;
|
||||
}>(
|
||||
//Automatically invalidate data older than 30 seconds
|
||||
serverData?.initialData?.map((item) =>
|
||||
dayjs().diff(item.timestamp) < invalidateTime ? item : { ...item, timestamp: new Date(0), data: null },
|
||||
) ?? [],
|
||||
const [currentItems] = clientApi.widget.downloads.getJobsAndStatuses.useSuspenseQuery(
|
||||
{
|
||||
integrationIds,
|
||||
},
|
||||
{
|
||||
refetchOnMount: false,
|
||||
refetchOnWindowFocus: false,
|
||||
refetchOnReconnect: false,
|
||||
retry: false,
|
||||
select(data) {
|
||||
return data.map((item) =>
|
||||
dayjs().diff(item.timestamp) < invalidateTime ? item : { ...item, timestamp: new Date(0), data: null },
|
||||
);
|
||||
},
|
||||
},
|
||||
);
|
||||
const utils = clientApi.useUtils();
|
||||
|
||||
//Invalidate all data after no update for 30 seconds using timer
|
||||
const invalidationTimer = useTimeout(
|
||||
() => {
|
||||
currentItemsHandlers.applyWhere(
|
||||
() => true,
|
||||
(item) => ({ ...item, timestamp: new Date(0), data: null }),
|
||||
utils.widget.downloads.getJobsAndStatuses.setData({ integrationIds }, (prevData) =>
|
||||
prevData?.map((item) => ({ ...item, timestamp: new Date(0), data: null })),
|
||||
);
|
||||
},
|
||||
invalidateTime,
|
||||
@@ -146,20 +148,24 @@ export default function DownloadClientsWidget({
|
||||
//Don't update already invalid data (new Date (0))
|
||||
.filter(({ timestamp }) => dayjs().diff(timestamp) > invalidateTime && timestamp > new Date(0))
|
||||
.map(({ integration }) => integration.id);
|
||||
currentItemsHandlers.applyWhere(
|
||||
({ integration }) => invalidIndexes.includes(integration.id),
|
||||
//Set date to now so it won't update that integration for at least 30 seconds
|
||||
(item) => ({ ...item, timestamp: new Date(0), data: null }),
|
||||
utils.widget.downloads.getJobsAndStatuses.setData({ integrationIds }, (prevData) =>
|
||||
prevData?.map((item) =>
|
||||
invalidIndexes.includes(item.integration.id) ? item : { ...item, timestamp: new Date(0), data: null },
|
||||
),
|
||||
);
|
||||
//Find id to update
|
||||
const updateIndex = currentItems.findIndex((pair) => pair.integration.id === data.integration.id);
|
||||
if (updateIndex >= 0) {
|
||||
//Update found index
|
||||
currentItemsHandlers.setItem(updateIndex, data);
|
||||
} else if (integrationIds.includes(data.integration.id)) {
|
||||
//Append index not found (new integration)
|
||||
currentItemsHandlers.append(data);
|
||||
}
|
||||
utils.widget.downloads.getJobsAndStatuses.setData({ integrationIds }, (prevData) => {
|
||||
const updateIndex = currentItems.findIndex((pair) => pair.integration.id === data.integration.id);
|
||||
if (updateIndex >= 0) {
|
||||
//Update found index
|
||||
return prevData?.map((pair, index) => (index === updateIndex ? data : pair));
|
||||
} else if (integrationIds.includes(data.integration.id)) {
|
||||
//Append index not found (new integration)
|
||||
return [...(prevData ?? []), data];
|
||||
}
|
||||
|
||||
return undefined;
|
||||
});
|
||||
|
||||
//Reset no update timer
|
||||
invalidationTimer.clear();
|
||||
invalidationTimer.start();
|
||||
|
||||
@@ -31,7 +31,7 @@ const columnsSort = columnsList.filter((column) =>
|
||||
sortingExclusion.some((exclusion) => exclusion !== column),
|
||||
) as Exclude<typeof columnsList, (typeof sortingExclusion)[number]>;
|
||||
|
||||
export const { definition, componentLoader, serverDataLoader } = createWidgetDefinition("downloads", {
|
||||
export const { definition, componentLoader } = createWidgetDefinition("downloads", {
|
||||
icon: IconDownload,
|
||||
options: optionsBuilder.from(
|
||||
(factory) => ({
|
||||
@@ -105,6 +105,4 @@ export const { definition, componentLoader, serverDataLoader } = createWidgetDef
|
||||
},
|
||||
),
|
||||
supportedIntegrations: getIntegrationKindsByCategory("downloadClient"),
|
||||
})
|
||||
.withServerData(() => import("./serverData"))
|
||||
.withDynamicImport(() => import("./component"));
|
||||
}).withDynamicImport(() => import("./component"));
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
"use server";
|
||||
|
||||
import { api } from "@homarr/api/server";
|
||||
|
||||
import type { WidgetProps } from "../definition";
|
||||
|
||||
export default async function getServerDataAsync({ integrationIds }: WidgetProps<"downloads">) {
|
||||
if (integrationIds.length === 0) {
|
||||
return {
|
||||
initialData: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
const jobsAndStatuses = await api.widget.downloads.getJobsAndStatuses({
|
||||
integrationIds,
|
||||
});
|
||||
|
||||
return {
|
||||
initialData: jobsAndStatuses,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user