From 0cf934c9e3d8769f52fa81ecbdb59a86a14ed84f Mon Sep 17 00:00:00 2001 From: moonrailgun Date: Wed, 13 Dec 2023 19:46:32 +0800 Subject: [PATCH] feat: add status list and add route --- src/client/pages/Monitor/PageAdd.tsx | 94 +++++++++++++++++++++++++++ src/client/pages/Monitor/PageList.tsx | 40 ++++++++++++ src/client/pages/Monitor/index.tsx | 21 ++++-- src/server/trpc/routers/monitor.ts | 17 +++++ src/shared/regex.ts | 2 + 5 files changed, 170 insertions(+), 4 deletions(-) create mode 100644 src/client/pages/Monitor/PageAdd.tsx create mode 100644 src/client/pages/Monitor/PageList.tsx diff --git a/src/client/pages/Monitor/PageAdd.tsx b/src/client/pages/Monitor/PageAdd.tsx new file mode 100644 index 0000000..cdc0ab9 --- /dev/null +++ b/src/client/pages/Monitor/PageAdd.tsx @@ -0,0 +1,94 @@ +import React from 'react'; +import { useNavigate } from 'react-router'; +import { useCurrentWorkspaceId } from '../../store/user'; +import { trpc } from '../../api/trpc'; +import { Button, Form, Input, Typography } from 'antd'; +import { useEvent } from '../../hooks/useEvent'; +import { z } from 'zod'; +import { slugRegex } from '../../../shared'; + +const { Text, Paragraph } = Typography; + +interface Values { + title: string; + slug: string; +} + +export const MonitorPageAdd: React.FC = React.memo(() => { + const workspaceId = useCurrentWorkspaceId()!; + const navigate = useNavigate(); + + const createPageMutation = trpc.monitor.createPage.useMutation(); + const trpcUtils = trpc.useContext(); + + const handleFinish = useEvent(async (values: Values) => { + await createPageMutation.mutateAsync({ + workspaceId, + title: values.title, + slug: values.slug, + }); + + trpcUtils.monitor.getAllPages.refetch(); + + navigate('/monitor/pages'); + }); + + return ( +
+ layout="vertical" onFinish={handleFinish}> + + + + + +
+ Accept characters: a-z 0-9{' '} + - +
+
+ No consecutive dashes -- +
+
+ } + rules={[ + { + required: true, + }, + { + validator(rule, value, callback) { + try { + z.string().regex(slugRegex).parse(value); + callback(); + } catch (err) { + callback('Not valid slug'); + } + }, + }, + ]} + > + + + + + + ); +}); +MonitorPageAdd.displayName = 'MonitorPageAdd'; diff --git a/src/client/pages/Monitor/PageList.tsx b/src/client/pages/Monitor/PageList.tsx new file mode 100644 index 0000000..15f61a9 --- /dev/null +++ b/src/client/pages/Monitor/PageList.tsx @@ -0,0 +1,40 @@ +import React from 'react'; +import { useNavigate } from 'react-router'; +import { useCurrentWorkspaceId } from '../../store/user'; +import { trpc } from '../../api/trpc'; +import { Button, Card } from 'antd'; +import { EditOutlined, EyeOutlined } from '@ant-design/icons'; + +export const MonitorPageList: React.FC = React.memo(() => { + const workspaceId = useCurrentWorkspaceId()!; + const { data: pages = [] } = trpc.monitor.getAllPages.useQuery({ + workspaceId, + }); + const navigate = useNavigate(); + + return ( +
+ + +
+ {pages.map((p) => ( + +
+
{p.title}
+
+
+
+
+ ))} +
+
+ ); +}); +MonitorPageList.displayName = 'MonitorPageList'; diff --git a/src/client/pages/Monitor/index.tsx b/src/client/pages/Monitor/index.tsx index 23e302c..8914bf2 100644 --- a/src/client/pages/Monitor/index.tsx +++ b/src/client/pages/Monitor/index.tsx @@ -5,6 +5,9 @@ import { MonitorAdd } from './Add'; import { MonitorDetail } from './Detail'; import { MonitorEdit } from './Edit'; import { MonitorOverview } from './Overview'; +import { Button } from 'antd'; +import { MonitorPageList } from './PageList'; +import { MonitorPageAdd } from './PageAdd'; export const MonitorPage: React.FC = React.memo(() => { const navigate = useNavigate(); @@ -12,13 +15,21 @@ export const MonitorPage: React.FC = React.memo(() => { return (
-
-
+
+ +
@@ -31,6 +42,8 @@ export const MonitorPage: React.FC = React.memo(() => { } /> } /> } /> + } /> + } />
diff --git a/src/server/trpc/routers/monitor.ts b/src/server/trpc/routers/monitor.ts index d85b444..3d354b1 100644 --- a/src/server/trpc/routers/monitor.ts +++ b/src/server/trpc/routers/monitor.ts @@ -418,6 +418,23 @@ export const monitorRouter = router({ }, }); }), + getAllPages: workspaceProcedure + .meta( + buildMonitorOpenapi({ + method: 'GET', + path: '/getAllPages', + }) + ) + .output(z.array(MonitorStatusPageModelSchema)) + .query(({ input }) => { + const { workspaceId } = input; + + return prisma.monitorStatusPage.findMany({ + where: { + workspaceId, + }, + }); + }), createPage: workspaceOwnerProcedure .meta( buildMonitorOpenapi({ diff --git a/src/shared/regex.ts b/src/shared/regex.ts index b37ddd3..044ffa9 100644 --- a/src/shared/regex.ts +++ b/src/shared/regex.ts @@ -1,2 +1,4 @@ export const hostnameRegex = /^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]).)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9-]*[A-Za-z0-9])$/; + +export const slugRegex = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;