mirror of
https://github.com/Portabase/portabase.git
synced 2026-07-14 11:16:13 +02:00
feat: front form for default notification settings page choice
This commit is contained in:
@@ -6,6 +6,7 @@ import {SettingsTabs} from "@/components/wrappers/dashboard/admin/settings/setti
|
||||
import {desc, isNull} from "drizzle-orm";
|
||||
import * as drizzleDb from "@/db";
|
||||
import {StorageChannelWith} from "@/db/schema/12_storage-channel";
|
||||
import {NotificationChannelWith} from "@/db/schema/09_notification-channel";
|
||||
|
||||
export default async function RoutePage(props: PageParams<{}>) {
|
||||
|
||||
@@ -21,7 +22,16 @@ export default async function RoutePage(props: PageParams<{}>) {
|
||||
orderBy: desc(drizzleDb.schemas.storageChannel.createdAt)
|
||||
}) as StorageChannelWith[]
|
||||
|
||||
if (!settings || !storageChannels ) {
|
||||
const notificationChannels = await db.query.notificationChannel.findMany({
|
||||
with: {
|
||||
organizations: true
|
||||
},
|
||||
where: isNull(drizzleDb.schemas.notificationChannel.organizationId),
|
||||
orderBy: desc(drizzleDb.schemas.notificationChannel.createdAt)
|
||||
}) as NotificationChannelWith[]
|
||||
|
||||
|
||||
if (!settings || !storageChannels || !notificationChannels ) {
|
||||
notFound()
|
||||
}
|
||||
|
||||
@@ -33,7 +43,7 @@ export default async function RoutePage(props: PageParams<{}>) {
|
||||
</div>
|
||||
</PageHeader>
|
||||
<PageContent className="flex flex-col gap-5">
|
||||
<SettingsTabs storageChannels={storageChannels} settings={settings} />
|
||||
<SettingsTabs storageChannels={storageChannels} notificationChannels={notificationChannels} settings={settings} />
|
||||
</PageContent>
|
||||
</Page>
|
||||
);
|
||||
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
"use client"
|
||||
import {Alert, AlertDescription, AlertTitle} from "@/components/ui/alert";
|
||||
import {Info} from "lucide-react";
|
||||
import {ButtonWithLoading} from "@/components/wrappers/common/button/button-with-loading";
|
||||
import {useRouter} from "next/navigation";
|
||||
import {Setting} from "@/db/schema/01_setting";
|
||||
import {
|
||||
Form,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
useZodForm
|
||||
} from "@/components/ui/form";
|
||||
import {Select, SelectContent, SelectItem, SelectTrigger, SelectValue} from "@/components/ui/select";
|
||||
import {useMutation} from "@tanstack/react-query";
|
||||
import {getChannelIcon} from "@/components/wrappers/dashboard/admin/channels/helpers/common";
|
||||
import {NotificationChannelWith} from "@/db/schema/09_notification-channel";
|
||||
import {
|
||||
DefaultNotificationSchema, DefaultNotificationType
|
||||
} from "@/components/wrappers/dashboard/admin/settings/notification/settings-notification.schema";
|
||||
|
||||
export type SettingsNotificationSectionProps = {
|
||||
settings: Setting;
|
||||
notificationChannels: NotificationChannelWith[];
|
||||
};
|
||||
|
||||
export const SettingsNotificationSection = ({settings, notificationChannels}: SettingsNotificationSectionProps) => {
|
||||
const router = useRouter();
|
||||
|
||||
const form = useZodForm({
|
||||
schema: DefaultNotificationSchema,
|
||||
defaultValues: {
|
||||
// notificationChannels: settings.defaultNotificationChannelId ?? undefined,
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
const mutation = useMutation({
|
||||
mutationFn: async (values: DefaultNotificationType) => {
|
||||
// const result = await updateStorageSettingsAction({name: "system", data: values})
|
||||
// const inner = result?.data;
|
||||
//
|
||||
// if (inner?.success) {
|
||||
// toast.success(inner.actionSuccess?.message);
|
||||
// router.refresh();
|
||||
// } else {
|
||||
// toast.error(inner?.actionError?.message);
|
||||
// }
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-full">
|
||||
<Alert className="mt-3">
|
||||
<Info className="h-4 w-4"/>
|
||||
<AlertTitle>Informations</AlertTitle>
|
||||
<AlertDescription>
|
||||
The default notification channel will be used to send agent health alert notifications, and will be applied by default if no notification policy is defined at the database or organization level.</AlertDescription>
|
||||
</Alert>
|
||||
<div className="flex flex-col h-full py-4 gap-3">
|
||||
<Form
|
||||
className="space-y-4"
|
||||
form={form}
|
||||
onSubmit={async (values) => {
|
||||
await mutation.mutateAsync(values);
|
||||
}}
|
||||
>
|
||||
<div className="flex flex-wrap items-center gap-3">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="storageChannelId"
|
||||
render={({field}) => (
|
||||
<FormItem className="flex-grow min-w-[200px] sm:flex-grow-0 sm:w-64">
|
||||
<FormLabel>Default Notification Provider</FormLabel>
|
||||
<Select value={field.value} onValueChange={field.onChange}>
|
||||
<SelectTrigger className="w-full h-full mb-0">
|
||||
<SelectValue placeholder="Select a default channel"/>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{notificationChannels.map((channel) => (
|
||||
<SelectItem key={channel.id} value={channel.id}>
|
||||
<div className="flex items-center gap-2">
|
||||
{getChannelIcon(channel.provider)}
|
||||
<span className="font-medium">{channel.name}</span>
|
||||
<span
|
||||
className="text-[9px] uppercase bg-secondary px-1.5 py-0.5 rounded">
|
||||
{channel.provider}
|
||||
</span>
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<ButtonWithLoading className="flex-shrink-0 w-full sm:w-auto" type="submit">
|
||||
Confirm
|
||||
</ButtonWithLoading>
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
import {z} from "zod";
|
||||
|
||||
export const DefaultNotificationSchema = z.object({
|
||||
notificationChannelId: z.string(),
|
||||
});
|
||||
|
||||
export type DefaultNotificationType = z.infer<typeof DefaultNotificationSchema>;
|
||||
@@ -7,14 +7,20 @@ import {Setting} from "@/db/schema/01_setting";
|
||||
import {SettingsEmailSection} from "@/components/wrappers/dashboard/admin/settings/email/settings-email-section";
|
||||
import {SettingsStorageSection} from "@/components/wrappers/dashboard/admin/settings/storage/settings-storage-section";
|
||||
import {StorageChannelWith} from "@/db/schema/12_storage-channel";
|
||||
import {MailboxIcon, Save} from "lucide-react";
|
||||
import {AlarmClock, MailboxIcon, Save} from "lucide-react";
|
||||
import {
|
||||
SettingsNotificationSection
|
||||
} from "@/components/wrappers/dashboard/admin/settings/notification/settings-notification-section";
|
||||
import {NotificationChannelWith} from "@/db/schema/09_notification-channel";
|
||||
|
||||
export type SettingsTabsProps = {
|
||||
settings: Setting
|
||||
storageChannels: StorageChannelWith[]
|
||||
storageChannels: StorageChannelWith[],
|
||||
notificationChannels: NotificationChannelWith[];
|
||||
|
||||
};
|
||||
|
||||
export const SettingsTabs = ({settings, storageChannels}: SettingsTabsProps) => {
|
||||
export const SettingsTabs = ({settings, storageChannels, notificationChannels}: SettingsTabsProps) => {
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
|
||||
@@ -47,6 +53,15 @@ export const SettingsTabs = ({settings, storageChannels}: SettingsTabsProps) =>
|
||||
content: (
|
||||
<SettingsStorageSection storageChannels={storageChannels} settings={settings}/>
|
||||
|
||||
)
|
||||
},
|
||||
{
|
||||
name: 'Notification',
|
||||
value: 'notification',
|
||||
icon: AlarmClock,
|
||||
content: (
|
||||
<SettingsNotificationSection notificationChannels={notificationChannels} settings={settings}/>
|
||||
|
||||
)
|
||||
}
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user