feat: add Nextcloud notification provider

fix: resolve hydration error in add-board modal
This commit is contained in:
Lorinc936 committed 2026-03-23 17:25:22 +01:00
1 parent 3ed31d8f59
commit b7c3a48377
3 files changed
+46 -7

No files matched your search

+1 -1
View File
@@ -217,7 +217,7 @@ export const integrationDefs = {
name: "Nextcloud",
secretKinds: [["username", "password"]],
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/nextcloud.svg",
category: ["calendar"],
category: ["calendar", "notifications"],
documentationUrl: createDocumentationLink("/docs/integrations/nextcloud"),
},
unifiController: {
@@ -6,7 +6,7 @@ import type { RequestInit as NodeFetchRequestInit } from "node-fetch";
import * as ical from "node-ical";
import { DAVClient } from "tsdav";
import { createHttpsAgentAsync } from "@homarr/core/infrastructure/http";
import { fetchWithTrustedCertificatesAsync, createHttpsAgentAsync } from "@homarr/core/infrastructure/http";
import { createLogger } from "@homarr/core/infrastructure/logs";
import { HandleIntegrationErrors } from "../base/errors/decorator";
@@ -16,6 +16,8 @@ import { Integration } from "../base/integration";
import type { TestingResult } from "../base/test-connection/test-connection-service";
import type { ICalendarIntegration } from "../interfaces/calendar/calendar-integration";
import type { CalendarEvent } from "../interfaces/calendar/calendar-types";
import type { INotificationsIntegration } from "../interfaces/notifications/notifications-integration";
import type { Notification } from "../interfaces/notifications/notification-types";
const logger = createLogger({ module: "nextcloudIntegration" });
@@ -23,7 +25,7 @@ dayjs.extend(utc);
dayjs.extend(timezone);
@HandleIntegrationErrors([integrationTsdavHttpErrorHandler])
export class NextcloudIntegration extends Integration implements ICalendarIntegration {
export class NextcloudIntegration extends Integration implements ICalendarIntegration, INotificationsIntegration {
protected async testingAsync(input: IntegrationTestingInput): Promise<TestingResult> {
const client = await this.createCalendarClientAsync(await createHttpsAgentAsync(input.options));
await client.login();
@@ -104,6 +106,40 @@ export class NextcloudIntegration extends Integration implements ICalendarIntegr
.flat();
}
public async getNotificationsAsync(): Promise<Notification[]> {
const url = this.url("/ocs/v2.php/apps/notifications/api/v2/notifications", { format: "json" });
const response = await fetchWithTrustedCertificatesAsync(url, {
headers: {
Authorization: `Basic ${Buffer.from(
`${this.getSecretValue("username")}:${this.getSecretValue("password")}`,
).toString("base64")}`,
"OCS-APIRequest": "true",
},
});
if (!response.ok) {
throw new Error(`Nextcloud notifications request failed: ${response.status}`);
}
const json = (await response.json()) as {
ocs: {
data: {
notification_id: number;
datetime: string;
subject: string;
message: string;
}[];
};
};
return json.ocs.data.map((n) => ({
id: String(n.notification_id),
time: new Date(n.datetime),
title: n.subject,
body: n.message,
}));
}
private async createCalendarClientAsync(agent?: Agent) {
return new DAVClient({
serverUrl: this.integration.url,
@@ -55,14 +55,17 @@ export const AddBoardModal = createModal(({ actions }) => {
label={t("board.field.name.label")}
data-autofocus
{...form.getInputProps("name")}
description={
boardNameStatus.description ? (
description={
boardNameStatus.description ? (
<span>
<Group c={boardNameStatus.description.color} gap="xs" align="center">
{boardNameStatus.description.icon ? <boardNameStatus.description.icon size={16} /> : null}
<span>{boardNameStatus.description.label}</span>
</Group>
) : null
}
</span>
) : null
}
/>
<InputWrapper label={t("board.field.columnCount.label")} {...form.getInputProps("columnCount")}>
<Slider