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 =