diff --git a/apps/nextjs/src/components/board/items/item-content.tsx b/apps/nextjs/src/components/board/items/item-content.tsx index db9323c66..12e4e5961 100644 --- a/apps/nextjs/src/components/board/items/item-content.tsx +++ b/apps/nextjs/src/components/board/items/item-content.tsx @@ -79,7 +79,13 @@ const InnerContent = ({ item, ...dimensions }: InnerContentProps) => { > ( action: IntegrationAction, ...kinds: AtLeastOneOf // Ensure at least one kind is provided ) => { - return publicProcedure - .input(z.object({ integrationIds: z.array(z.string()).min(1) })) - .use(async ({ ctx, input, next }) => { - const dbIntegrations = await ctx.db.query.integrations.findMany({ - where: and(inArray(integrations.id, input.integrationIds), inArray(integrations.kind, kinds)), - with: { - secrets: true, - items: { + return publicProcedure.input(z.object({ integrationIds: z.array(z.string()) })).use(async ({ ctx, input, next }) => { + const dbIntegrations = + input.integrationIds.length >= 1 + ? await ctx.db.query.integrations.findMany({ + where: and(inArray(integrations.id, input.integrationIds), inArray(integrations.kind, kinds)), with: { - item: { + secrets: true, + items: { with: { - section: { - columns: { - boardId: true, + item: { + with: { + section: { + columns: { + boardId: true, + }, + }, }, }, }, }, + userPermissions: true, + groupPermissions: true, }, - }, - userPermissions: true, - groupPermissions: true, - }, + }) + : []; + + const offset = input.integrationIds.length - dbIntegrations.length; + if (offset !== 0) { + throw new TRPCError({ + code: "NOT_FOUND", + message: `${offset} of the specified integrations not found or not of kinds ${kinds.join(",")}: ([${input.integrationIds.join(",")}] compared to [${dbIntegrations.map(({ id, kind }) => `${kind}:${id}`).join(",")}])`, }); + } - const offset = input.integrationIds.length - dbIntegrations.length; - if (offset !== 0) { - throw new TRPCError({ - code: "NOT_FOUND", - message: `${offset} of the specified integrations not found or not of kinds ${kinds.join(",")}: ([${input.integrationIds.join(",")}] compared to [${dbIntegrations.map(({ id, kind }) => `${kind}:${id}`).join(",")}])`, - }); - } - + if (dbIntegrations.length >= 1) { await throwIfActionIsNotAllowedAsync(action, ctx.db, dbIntegrations, ctx.session); + } - return next({ - ctx: { - integrations: dbIntegrations.map( - ({ secrets, kind, items: _ignore1, groupPermissions: _ignore2, userPermissions: _ignore3, ...rest }) => ({ - ...rest, - kind: kind as TKind, - decryptedSecrets: secrets.map((secret) => ({ - ...secret, - value: decryptSecret(secret.value), - })), - }), - ), - }, - }); + return next({ + ctx: { + integrations: dbIntegrations.map( + ({ secrets, kind, items: _ignore1, groupPermissions: _ignore2, userPermissions: _ignore3, ...rest }) => ({ + ...rest, + kind: kind as TKind, + decryptedSecrets: secrets.map((secret) => ({ + ...secret, + value: decryptSecret(secret.value), + })), + }), + ), + }, }); + }); }; /** diff --git a/packages/widgets/src/calendar/component.tsx b/packages/widgets/src/calendar/component.tsx index d2eb3c780..5c74327a4 100644 --- a/packages/widgets/src/calendar/component.tsx +++ b/packages/widgets/src/calendar/component.tsx @@ -5,6 +5,7 @@ import { useParams } from "next/navigation"; import { Calendar } from "@mantine/dates"; import dayjs from "dayjs"; +import type { RouterOutputs } from "@homarr/api"; import { clientApi } from "@homarr/api/client"; import type { CalendarEvent } from "@homarr/integrations/types"; @@ -12,8 +13,22 @@ import type { WidgetComponentProps } from "../definition"; import { CalendarDay } from "./calender-day"; import classes from "./component.module.css"; -export default function CalendarWidget({ isEditMode, integrationIds, options }: WidgetComponentProps<"calendar">) { +export default function CalendarWidget(props: WidgetComponentProps<"calendar">) { const [month, setMonth] = useState(new Date()); + + if (props.integrationIds.length === 0) { + return ; + } + + return ; +} + +interface FetchCalendarProps extends WidgetComponentProps<"calendar"> { + month: Date; + setMonth: (date: Date) => void; +} + +const FetchCalendar = ({ month, setMonth, isEditMode, integrationIds, options }: FetchCalendarProps) => { const [events] = clientApi.widget.calendar.findAllEvents.useSuspenseQuery( { integrationIds, @@ -28,6 +43,19 @@ export default function CalendarWidget({ isEditMode, integrationIds, options }: retry: false, }, ); + + return ; +}; + +interface CalendarBaseProps { + isEditMode: boolean; + events: RouterOutputs["widget"]["calendar"]["findAllEvents"]; + month: Date; + setMonth: (date: Date) => void; + options: WidgetComponentProps<"calendar">["options"]; +} + +const CalendarBase = ({ isEditMode, events, month, setMonth, options }: CalendarBaseProps) => { const params = useParams(); const locale = params.locale as string; const [firstDayOfWeek] = clientApi.user.getFirstDayOfWeekForUserOrDefault.useSuspenseQuery(); @@ -37,6 +65,7 @@ export default function CalendarWidget({ isEditMode, integrationIds, options }: defaultDate={new Date()} onPreviousMonth={setMonth} onNextMonth={setMonth} + highlightToday locale={locale} hideWeekdays={false} date={month} @@ -95,4 +124,4 @@ export default function CalendarWidget({ isEditMode, integrationIds, options }: }} /> ); -} +}; diff --git a/packages/widgets/src/calendar/index.ts b/packages/widgets/src/calendar/index.ts index 8afb3fe1e..6ce92f0a5 100644 --- a/packages/widgets/src/calendar/index.ts +++ b/packages/widgets/src/calendar/index.ts @@ -27,4 +27,5 @@ export const { definition, componentLoader } = createWidgetDefinition("calendar" }), })), supportedIntegrations: getIntegrationKindsByCategory("calendar"), + integrationsRequired: false, }).withDynamicImport(() => import("./component")); diff --git a/packages/widgets/src/definition.ts b/packages/widgets/src/definition.ts index 77238b469..7ee07ed37 100644 --- a/packages/widgets/src/definition.ts +++ b/packages/widgets/src/definition.ts @@ -29,6 +29,7 @@ export const createWidgetDefinition =