mirror of
https://github.com/ajnart/homarr.git
synced 2026-02-28 01:10:54 +01:00
fix: trpc error at least one integration (#1660)
This commit is contained in:
@@ -2,9 +2,10 @@ import { Card } from "@mantine/core";
|
||||
import { useElementSize } from "@mantine/hooks";
|
||||
import { QueryErrorResetBoundary } from "@tanstack/react-query";
|
||||
import combineClasses from "clsx";
|
||||
import { NoIntegrationSelectedError } from "node_modules/@homarr/widgets/src/errors";
|
||||
import { ErrorBoundary } from "react-error-boundary";
|
||||
|
||||
import { loadWidgetDynamic, reduceWidgetOptionsWithDefaultValues } from "@homarr/widgets";
|
||||
import { loadWidgetDynamic, reduceWidgetOptionsWithDefaultValues, widgetImports } from "@homarr/widgets";
|
||||
import { WidgetError } from "@homarr/widgets/errors";
|
||||
|
||||
import type { Item } from "~/app/[locale]/boards/_types";
|
||||
@@ -54,11 +55,14 @@ const InnerContent = ({ item, ...dimensions }: InnerContentProps) => {
|
||||
const board = useRequiredBoard();
|
||||
const [isEditMode] = useEditMode();
|
||||
const Comp = loadWidgetDynamic(item.kind);
|
||||
const { definition } = widgetImports[item.kind];
|
||||
const options = reduceWidgetOptionsWithDefaultValues(item.kind, item.options);
|
||||
const newItem = { ...item, options };
|
||||
const { updateItemOptions } = useItemActions();
|
||||
const updateOptions = ({ newOptions }: { newOptions: Record<string, unknown> }) =>
|
||||
updateItemOptions({ itemId: item.id, newOptions });
|
||||
const widgetSupportsIntegrations =
|
||||
"supportedIntegrations" in definition && definition.supportedIntegrations.length >= 1;
|
||||
|
||||
return (
|
||||
<QueryErrorResetBoundary>
|
||||
@@ -72,6 +76,10 @@ const InnerContent = ({ item, ...dimensions }: InnerContentProps) => {
|
||||
</>
|
||||
)}
|
||||
>
|
||||
<Throw
|
||||
error={new NoIntegrationSelectedError()}
|
||||
when={widgetSupportsIntegrations && item.integrationIds.length === 0}
|
||||
/>
|
||||
<BoardItemMenu offset={4} item={newItem} />
|
||||
<Comp
|
||||
options={options as never}
|
||||
@@ -87,3 +95,8 @@ const InnerContent = ({ item, ...dimensions }: InnerContentProps) => {
|
||||
</QueryErrorResetBoundary>
|
||||
);
|
||||
};
|
||||
|
||||
const Throw = ({ when, error }: { when: boolean; error: Error }) => {
|
||||
if (when) throw error;
|
||||
return null;
|
||||
};
|
||||
|
||||
@@ -29,7 +29,6 @@ import { useI18n } from "@homarr/translation/client";
|
||||
|
||||
import type { widgetKind } from ".";
|
||||
import type { WidgetComponentProps } from "../../definition";
|
||||
import { NoIntegrationSelectedError } from "../../errors";
|
||||
import TimerModal from "./TimerModal";
|
||||
|
||||
const dnsLightStatus = (enabled: boolean | undefined) =>
|
||||
@@ -184,10 +183,6 @@ export default function DnsHoleControlsWidget({
|
||||
|
||||
const controlAllButtonsVisible = options.showToggleAllButtons && integrationsWithInteractions.length > 0;
|
||||
|
||||
if (integrationIds.length === 0) {
|
||||
throw new NoIntegrationSelectedError();
|
||||
}
|
||||
|
||||
return (
|
||||
<Flex
|
||||
className="dns-hole-controls-stack"
|
||||
|
||||
@@ -17,7 +17,6 @@ import type { TablerIcon } from "@homarr/ui";
|
||||
|
||||
import type { widgetKind } from ".";
|
||||
import type { WidgetComponentProps, WidgetProps } from "../../definition";
|
||||
import { NoIntegrationSelectedError } from "../../errors";
|
||||
|
||||
export default function DnsHoleSummaryWidget({ options, integrationIds }: WidgetComponentProps<typeof widgetKind>) {
|
||||
const [summaries] = clientApi.widget.dnsHole.summary.useSuspenseQuery(
|
||||
@@ -62,10 +61,6 @@ export default function DnsHoleSummaryWidget({ options, integrationIds }: Widget
|
||||
|
||||
const data = useMemo(() => summaries.flatMap(({ summary }) => summary), [summaries]);
|
||||
|
||||
if (integrationIds.length === 0) {
|
||||
throw new NoIntegrationSelectedError();
|
||||
}
|
||||
|
||||
return (
|
||||
<Box h="100%" {...boxPropsByLayout(options.layout)} p="2cqmin">
|
||||
{data.length > 0 ? (
|
||||
|
||||
@@ -45,7 +45,6 @@ import type { ExtendedClientStatus, ExtendedDownloadClientItem } from "@homarr/i
|
||||
import { useScopedI18n } from "@homarr/translation/client";
|
||||
|
||||
import type { WidgetComponentProps } from "../definition";
|
||||
import { NoIntegrationSelectedError } from "../errors";
|
||||
|
||||
//Ratio table for relative width between columns
|
||||
const columnsRatios: Record<keyof ExtendedDownloadClientItem, number> = {
|
||||
@@ -636,10 +635,6 @@ export default function DownloadClientsWidget({
|
||||
{ up: 0, down: 0 },
|
||||
);
|
||||
|
||||
if (integrationIds.length === 0) {
|
||||
throw new NoIntegrationSelectedError();
|
||||
}
|
||||
|
||||
if (options.columns.length === 0)
|
||||
return (
|
||||
<Center h="100%">
|
||||
|
||||
@@ -37,7 +37,6 @@ import type { TranslationFunction } from "@homarr/translation";
|
||||
import { useI18n } from "@homarr/translation/client";
|
||||
|
||||
import type { WidgetComponentProps } from "../definition";
|
||||
import { NoIntegrationSelectedError } from "../errors";
|
||||
|
||||
dayjs.extend(duration);
|
||||
|
||||
@@ -76,9 +75,6 @@ export default function HealthMonitoringWidget({ options, integrationIds }: Widg
|
||||
},
|
||||
);
|
||||
|
||||
if (integrationIds.length === 0) {
|
||||
throw new NoIntegrationSelectedError();
|
||||
}
|
||||
return (
|
||||
<Stack h="100%" gap="2.5cqmin" className="health-monitoring">
|
||||
{healthData.map(({ integrationId, integrationName, healthInfo, updatedAt }) => {
|
||||
|
||||
@@ -7,7 +7,6 @@ import { clientApi } from "@homarr/api/client";
|
||||
import { useI18n } from "@homarr/translation/client";
|
||||
|
||||
import type { WidgetComponentProps } from "../definition";
|
||||
import { NoIntegrationSelectedError } from "../errors";
|
||||
|
||||
export default function IndexerManagerWidget({ options, integrationIds }: WidgetComponentProps<"indexerManager">) {
|
||||
const t = useI18n();
|
||||
@@ -39,10 +38,6 @@ export default function IndexerManagerWidget({ options, integrationIds }: Widget
|
||||
|
||||
const iconStyle = { height: "7.5cqmin", width: "7.5cqmin" };
|
||||
|
||||
if (integrationIds.length === 0) {
|
||||
throw new NoIntegrationSelectedError();
|
||||
}
|
||||
|
||||
return (
|
||||
<Flex className="indexer-manager-container" h="100%" direction="column" gap="2.5cqmin" p="2.5cqmin" align="center">
|
||||
<Text className="indexer-manager-title" size="6.5cqmin">
|
||||
|
||||
@@ -9,7 +9,6 @@ import type { ScopedTranslationFunction } from "@homarr/translation";
|
||||
import { useScopedI18n } from "@homarr/translation/client";
|
||||
|
||||
import type { WidgetComponentProps } from "../../definition";
|
||||
import { NoIntegrationSelectedError } from "../../errors";
|
||||
import { NoIntegrationDataError } from "../../errors/no-data-integration";
|
||||
|
||||
export default function MediaServerWidget({
|
||||
@@ -58,8 +57,6 @@ export default function MediaServerWidget({
|
||||
|
||||
const { mutate: mutateRequestAnswer } = clientApi.widget.mediaRequests.answerRequest.useMutation();
|
||||
|
||||
if (integrationIds.length === 0) throw new NoIntegrationSelectedError();
|
||||
|
||||
if (mediaRequests.length === 0) throw new NoIntegrationDataError();
|
||||
|
||||
return (
|
||||
|
||||
@@ -21,7 +21,6 @@ import type { RequestStats } from "@homarr/integrations/types";
|
||||
import { useScopedI18n } from "@homarr/translation/client";
|
||||
|
||||
import type { WidgetComponentProps } from "../../definition";
|
||||
import { NoIntegrationSelectedError } from "../../errors";
|
||||
import { NoIntegrationDataError } from "../../errors/no-data-integration";
|
||||
import classes from "./component.module.css";
|
||||
|
||||
@@ -43,8 +42,6 @@ export default function MediaServerWidget({
|
||||
|
||||
const { width, height, ref } = useElementSize();
|
||||
|
||||
if (integrationIds.length === 0) throw new NoIntegrationSelectedError();
|
||||
|
||||
if (requestStats.users.length === 0 && requestStats.stats.length === 0) throw new NoIntegrationDataError();
|
||||
|
||||
//Add processing and available
|
||||
|
||||
@@ -8,27 +8,16 @@ import { clientApi } from "@homarr/api/client";
|
||||
import { useRegisterSpotlightContextActions } from "@homarr/spotlight";
|
||||
|
||||
import type { WidgetComponentProps } from "../../definition";
|
||||
import { NoIntegrationSelectedError } from "../../errors";
|
||||
|
||||
export default function SmartHomeEntityStateWidget({
|
||||
options,
|
||||
integrationIds,
|
||||
isEditMode,
|
||||
}: WidgetComponentProps<"smartHome-entityState">) {
|
||||
const integrationId = integrationIds[0];
|
||||
// It will always have at least one integration as otherwise the NoIntegrationSelectedError would be thrown in item-content.tsx
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const integrationId = integrationIds[0]!;
|
||||
|
||||
if (!integrationId) {
|
||||
throw new NoIntegrationSelectedError();
|
||||
}
|
||||
|
||||
return <InnerComponent options={options} integrationId={integrationId} isEditMode={isEditMode} />;
|
||||
}
|
||||
|
||||
type InnerComponentProps = Pick<WidgetComponentProps<"smartHome-entityState">, "options" | "isEditMode"> & {
|
||||
integrationId: string;
|
||||
};
|
||||
|
||||
const InnerComponent = ({ options, integrationId, isEditMode }: InnerComponentProps) => {
|
||||
const input = {
|
||||
entityId: options.entityId,
|
||||
integrationId,
|
||||
@@ -103,4 +92,4 @@ const InnerComponent = ({ options, integrationId, isEditMode }: InnerComponentPr
|
||||
</Center>
|
||||
</UnstyledButton>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user