fix: handle lazy startup failures

This commit is contained in:
ajnart committed 2026-07-29 07:23:09 +02:00
1 parent 84f87ce24e
commit c80e9878de
5 files changed
+85 -21

No files matched your search

@@ -5,6 +5,7 @@ import { useElementSize } from "@mantine/hooks";
import { QueryErrorResetBoundary, useQueryClient } from "@tanstack/react-query";
import combineClasses from "clsx";
import { NoIntegrationSelectedError } from "@homarr/widgets/errors/classes";
import type { FallbackProps } from "react-error-boundary";
import { ErrorBoundary } from "react-error-boundary";
import { useRequiredBoard } from "@homarr/boards/context";
@@ -33,6 +34,12 @@ const getOverflowFromKind = (kind: SectionItem["kind"]) => {
return undefined;
};
const WidgetDefinitionLoadError = ({ error, resetErrorBoundary }: FallbackProps) => (
<Center className={classes.itemCard} h="100%">
<WidgetError error={error} resetErrorBoundary={resetErrorBoundary} />
</Center>
);
export const BoardItemContent = ({ item }: BoardItemContentProps) => {
const { ref, width, height } = useElementSize<HTMLDivElement>();
const board = useRequiredBoard();
@@ -40,21 +47,23 @@ export const BoardItemContent = ({ item }: BoardItemContentProps) => {
return (
<>
<Suspense
fallback={
<Center ref={ref} className={classes.itemCard} h="100%">
<Loader size="sm" />
</Center>
}
>
<LoadedBoardItemContent
item={item}
width={width}
height={height}
widgetStateRef={widgetStateRef}
innerRef={ref}
/>
</Suspense>
<ErrorBoundary resetKeys={[item.kind]} fallbackRender={WidgetDefinitionLoadError}>
<Suspense
fallback={
<Center ref={ref} className={classes.itemCard} h="100%">
<Loader size="sm" />
</Center>
}
>
<LoadedBoardItemContent
item={item}
width={width}
height={height}
widgetStateRef={widgetStateRef}
innerRef={ref}
/>
</Suspense>
</ErrorBoundary>
{item.advancedOptions.title?.trim() && (
<Badge
pos="absolute"
@@ -43,7 +43,11 @@ export const IntegrationMultiSelectGrid = ({
[selectedKindsArray, onSelectionChange],
);
const { data: integrations = [], isPending } = useQuery({
const {
data: integrations = [],
isPending,
isError,
} = useQuery({
queryKey: ["widget-integrations", { enableMockIntegration, onboarding }],
queryFn: () => buildSortedIntegrations({ enableMockIntegration, onboarding }),
});
@@ -136,7 +140,14 @@ export const IntegrationMultiSelectGrid = ({
);
})}
{!isPending && filtered.length === 0 && (
{isError && (
<Center p="xl">
<Text c="red" role="alert">
{t("common.error")}
</Text>
</Center>
)}
{!isPending && !isError && filtered.length === 0 && (
<Center p="xl">
<Text c="dimmed">{t("common.noResults")}</Text>
</Center>
@@ -20,7 +20,11 @@ export const IntegrationSelectGrid = ({ onSelect, enableMockIntegration = false
const [search, setSearch] = useState("");
const t = useI18n();
const { data: integrations = [], isPending } = useQuery({
const {
data: integrations = [],
isPending,
isError,
} = useQuery({
queryKey: ["widget-integrations", { enableMockIntegration }],
queryFn: () => buildSortedIntegrations({ enableMockIntegration }),
});
@@ -89,7 +93,14 @@ export const IntegrationSelectGrid = ({ onSelect, enableMockIntegration = false
</Card>
))}
{!isPending && filtered.length === 0 && (
{isError && (
<Center p="xl">
<Text c="red" role="alert">
{t("common.error")}
</Text>
</Center>
)}
{!isPending && !isError && filtered.length === 0 && (
<Center p="xl">
<Text c="dimmed">{t("common.noResults")}</Text>
</Center>