feat: monitor allow edit notifications

This commit is contained in:
moonrailgun 2023-10-20 00:48:56 +08:00
parent 0346dc21d9
commit 0c1c72ccab
7 changed files with 95 additions and 12 deletions

View File

@ -3,6 +3,7 @@ import type { Monitor } from '@prisma/client';
import { Button, Form, Input, InputNumber, Select } from 'antd'; import { Button, Form, Input, InputNumber, Select } from 'antd';
import { monitorProviders } from './provider'; import { monitorProviders } from './provider';
import { useEvent } from '../../../hooks/useEvent'; import { useEvent } from '../../../hooks/useEvent';
import { NotificationPicker } from '../../notification/NotificationPicker';
export type MonitorInfoEditorValues = Omit< export type MonitorInfoEditorValues = Omit<
Monitor, Monitor,
@ -10,6 +11,7 @@ export type MonitorInfoEditorValues = Omit<
> & { > & {
id?: string; id?: string;
payload: Record<string, any>; payload: Record<string, any>;
notificationIds?: string[];
}; };
const defaultValues: Omit<MonitorInfoEditorValues, 'payload'> = { const defaultValues: Omit<MonitorInfoEditorValues, 'payload'> = {
@ -82,6 +84,10 @@ export const MonitorInfoEditor: React.FC<MonitorInfoEditorProps> = React.memo(
{formEl} {formEl}
<Form.Item label="Notification" name="notificationIds">
<NotificationPicker allowClear={true} mode="multiple" />
</Form.Item>
<Button type="primary" htmlType="submit"> <Button type="primary" htmlType="submit">
Save Save
</Button> </Button>

View File

@ -56,12 +56,12 @@ export const MonitorList: React.FC = React.memo(() => {
} }
return ( return (
<div> <div className="p-2">
{monitors.map((monitor) => ( {monitors.map((monitor) => (
<div <div
key={monitor.name} key={monitor.name}
className={clsx( className={clsx(
'flex rounded-lg py-3 px-4 cursor-pointer', 'flex rounded-lg py-3 px-4 cursor-pointer mb-1',
selectedMonitorId === monitor.id selectedMonitorId === monitor.id
? 'bg-green-500 bg-opacity-20' ? 'bg-green-500 bg-opacity-20'
: 'bg-green-500 bg-opacity-0 hover:bg-opacity-10' : 'bg-green-500 bg-opacity-0 hover:bg-opacity-10'

View File

@ -0,0 +1,27 @@
import { Select, SelectProps } from 'antd';
import React from 'react';
import { trpc } from '../../api/trpc';
import { useCurrentWorkspaceId } from '../../store/user';
import { ColorTag } from '../ColorTag';
interface NotificationPickerProps extends SelectProps<string> {}
export const NotificationPicker: React.FC<NotificationPickerProps> = React.memo(
(props) => {
const workspaceId = useCurrentWorkspaceId();
const { data: allNotification = [] } = trpc.notification.all.useQuery({
workspaceId,
});
return (
<Select {...props}>
{allNotification.map((m) => (
<Select.Option key={m.id} value={m.id}>
<ColorTag label={m.type} />
{m.name}
</Select.Option>
))}
</Select>
);
}
);
NotificationPicker.displayName = 'NotificationPicker';

View File

@ -31,7 +31,12 @@ export const MonitorEdit: React.FC = React.memo(() => {
return ( return (
<div> <div>
<MonitorInfoEditor <MonitorInfoEditor
initialValues={monitor as MonitorInfoEditorValues} initialValues={
{
...monitor,
notificationIds: monitor.notifications.map((n) => n.id),
} as MonitorInfoEditorValues
}
onSave={async (value) => { onSave={async (value) => {
const monitor = await mutation.mutateAsync({ const monitor = await mutation.mutateAsync({
...value, ...value,

View File

@ -8,7 +8,12 @@ import dayjs from 'dayjs';
export type MonitorUpsertData = Pick< export type MonitorUpsertData = Pick<
Monitor, Monitor,
'workspaceId' | 'name' | 'type' | 'interval' 'workspaceId' | 'name' | 'type' | 'interval'
> & { id?: string; active?: boolean; payload: Record<string, any> }; > & {
id?: string;
active?: boolean;
notificationIds?: string[];
payload: Record<string, any>;
};
type MonitorWithNotification = Monitor & { notifications: Notification[] }; type MonitorWithNotification = Monitor & { notifications: Notification[] };
@ -21,13 +26,19 @@ class MonitorManager {
*/ */
async upsert(data: MonitorUpsertData): Promise<MonitorWithNotification> { async upsert(data: MonitorUpsertData): Promise<MonitorWithNotification> {
let monitor: MonitorWithNotification; let monitor: MonitorWithNotification;
if (data.id) { const { id, notificationIds = [], ...others } = data;
if (id) {
// update // update
monitor = await prisma.monitor.update({ monitor = await prisma.monitor.update({
where: { where: {
id: data.id, id,
},
data: {
...others,
notifications: {
set: notificationIds.map((id) => ({ id })),
},
}, },
data: { ...data },
include: { include: {
notifications: true, notifications: true,
}, },
@ -37,7 +48,12 @@ class MonitorManager {
} else { } else {
// create // create
monitor = await prisma.monitor.create({ monitor = await prisma.monitor.create({
data: { ...data }, data: {
...others,
notifications: {
connect: notificationIds.map((id) => ({ id })),
},
},
include: { include: {
notifications: true, notifications: true,
}, },

View File

@ -2,7 +2,7 @@ import { router, workspaceOwnerProcedure, workspaceProcedure } from '../trpc';
import { prisma } from '../../model/_client'; import { prisma } from '../../model/_client';
import { z } from 'zod'; import { z } from 'zod';
import { monitorManager } from '../../model/monitor'; import { monitorManager } from '../../model/monitor';
import { MonitorInfo } from '../../../types'; import { MonitorInfoWithNotificationIds } from '../../../types';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
export const monitorRouter = router({ export const monitorRouter = router({
@ -12,9 +12,16 @@ export const monitorRouter = router({
where: { where: {
workspaceId, workspaceId,
}, },
include: {
notifications: {
select: {
id: true,
},
},
},
}); });
return monitors as MonitorInfo[]; return monitors as MonitorInfoWithNotificationIds[];
}), }),
get: workspaceProcedure get: workspaceProcedure
.input( .input(
@ -29,9 +36,16 @@ export const monitorRouter = router({
id, id,
workspaceId, workspaceId,
}, },
include: {
notifications: {
select: {
id: true,
},
},
},
}); });
return monitor as MonitorInfo; return monitor as MonitorInfoWithNotificationIds;
}), }),
upsert: workspaceOwnerProcedure upsert: workspaceOwnerProcedure
.input( .input(
@ -41,11 +55,21 @@ export const monitorRouter = router({
type: z.string(), type: z.string(),
active: z.boolean().default(true), active: z.boolean().default(true),
interval: z.number().int().default(20), interval: z.number().int().default(20),
notificationIds: z.array(z.string()).default([]),
payload: z.object({}).passthrough(), payload: z.object({}).passthrough(),
}) })
) )
.mutation(async ({ input }) => { .mutation(async ({ input }) => {
const { id, workspaceId, name, type, active, interval, payload } = input; const {
id,
workspaceId,
name,
type,
active,
interval,
notificationIds,
payload,
} = input;
const monitor = await monitorManager.upsert({ const monitor = await monitorManager.upsert({
id, id,
@ -54,6 +78,7 @@ export const monitorRouter = router({
type, type,
active, active,
interval, interval,
notificationIds,
payload, payload,
}); });

View File

@ -7,3 +7,7 @@ export type MonitorInfo = ExactType<
payload: Record<string, any>; payload: Record<string, any>;
} }
>; >;
export type MonitorInfoWithNotificationIds = MonitorInfo & {
notifications: { id: string }[];
};