diff --git a/src/client/api/model/monitor.ts b/src/client/api/model/monitor.ts index bd1c380..855e05f 100644 --- a/src/client/api/model/monitor.ts +++ b/src/client/api/model/monitor.ts @@ -8,6 +8,11 @@ export function useMonitorUpsert() { workspaceId: data.workspaceId, }); + utils.monitor.get.refetch({ + workspaceId: data.workspaceId, + monitorId: data.id, + }); + defaultSuccessHandler(); }, onError: defaultErrorHandler, diff --git a/src/client/components/monitor/MonitorDataChart.tsx b/src/client/components/monitor/MonitorDataChart.tsx index 44e5784..9ceb084 100644 --- a/src/client/components/monitor/MonitorDataChart.tsx +++ b/src/client/components/monitor/MonitorDataChart.tsx @@ -1,7 +1,7 @@ import { AreaConfig, Area } from '@ant-design/charts'; import { Select } from 'antd'; import dayjs, { Dayjs } from 'dayjs'; -import { uniqBy } from 'lodash-es'; +import { max, min, uniqBy } from 'lodash-es'; import React, { useState, useMemo } from 'react'; import { useSocketSubscribeList } from '../../api/socketio'; import { trpc } from '../../api/trpc'; @@ -97,6 +97,16 @@ export const MonitorDataChart: React.FC<{ monitorId: string }> = React.memo( }, [_recentData, _data, subscribedDataList]); const config = useMemo(() => { + const values = data.map((d) => d.value); + const maxValue = max(values) ?? 0; + const minValue = min(values) ?? 0; + + const isTrendingMode = monitorInfo?.trendingMode ?? false; // if true, y axis not start from 0 + + const yMin = isTrendingMode + ? Math.max(minValue - (maxValue - minValue) / 10, 0) + : 0; + return { data, height: 200, @@ -104,6 +114,9 @@ export const MonitorDataChart: React.FC<{ monitorId: string }> = React.memo( yField: 'value', smooth: true, meta: { + value: { + min: yMin, + }, time: { formatter(value) { return dayjs(value).format( @@ -112,6 +125,10 @@ export const MonitorDataChart: React.FC<{ monitorId: string }> = React.memo( }, }, }, + // need explore how to display null data + // xAxis: { + // type: 'time', + // }, color: 'rgb(34 197 94 / 0.8)', areaStyle: () => { return { diff --git a/src/client/components/monitor/MonitorInfoEditor.tsx b/src/client/components/monitor/MonitorInfoEditor.tsx index 177034b..7ef6b95 100644 --- a/src/client/components/monitor/MonitorInfoEditor.tsx +++ b/src/client/components/monitor/MonitorInfoEditor.tsx @@ -1,6 +1,6 @@ import React, { useMemo } from 'react'; import type { Monitor } from '../../../server/types/prisma'; -import { Button, Form, Input, InputNumber, Select } from 'antd'; +import { Button, Form, Input, InputNumber, Select, Switch } from 'antd'; import { getMonitorProvider, monitorProviders } from './provider'; import { useEventWithLoading } from '../../hooks/useEvent'; import { NotificationPicker } from '../notification/NotificationPicker'; @@ -12,6 +12,7 @@ export type MonitorInfoEditorValues = Omit< > & { id?: string; payload: Record; + trendingMode: boolean; notificationIds?: string[]; }; @@ -21,6 +22,7 @@ const defaultValues: Omit = { active: true, interval: 60, maxRetries: 0, + trendingMode: false, }; interface MonitorInfoEditorProps { @@ -105,6 +107,15 @@ export const MonitorInfoEditor: React.FC = React.memo( {formEl} + + + + diff --git a/src/server/model/monitor/manager.ts b/src/server/model/monitor/manager.ts index ed9d019..705cefc 100644 --- a/src/server/model/monitor/manager.ts +++ b/src/server/model/monitor/manager.ts @@ -5,7 +5,7 @@ import { logger } from '../../utils/logger'; export type MonitorUpsertData = Pick< Monitor, - 'workspaceId' | 'name' | 'type' | 'interval' | 'maxRetries' + 'workspaceId' | 'name' | 'type' | 'interval' | 'maxRetries' | 'trendingMode' > & { id?: string; active?: boolean; diff --git a/src/server/prisma/migrations/20240502082154_add_monitor_trending_mode/migration.sql b/src/server/prisma/migrations/20240502082154_add_monitor_trending_mode/migration.sql new file mode 100644 index 0000000..6ad865d --- /dev/null +++ b/src/server/prisma/migrations/20240502082154_add_monitor_trending_mode/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "Monitor" ADD COLUMN "trendingMode" BOOLEAN NOT NULL DEFAULT false; diff --git a/src/server/prisma/schema.prisma b/src/server/prisma/schema.prisma index 15db4df..0bac4ef 100644 --- a/src/server/prisma/schema.prisma +++ b/src/server/prisma/schema.prisma @@ -284,20 +284,21 @@ model Notification { } model Monitor { - id String @id() @default(cuid()) @db.VarChar(30) - workspaceId String @db.VarChar(30) - name String @db.VarChar(100) - type String @db.VarChar(100) - active Boolean @default(true) @db.Boolean - interval Int @default(20) @db.Integer - maxRetries Int @default(0) @db.Integer + id String @id() @default(cuid()) @db.VarChar(30) + workspaceId String @db.VarChar(30) + name String @db.VarChar(100) + type String @db.VarChar(100) + active Boolean @default(true) @db.Boolean + interval Int @default(20) @db.Integer + maxRetries Int @default(0) @db.Integer // TODO // retryInterval Int @default(0) @db.Integer /// [CommonPayload] /// @zod.custom(imports.CommonPayloadSchema) - payload Json @db.Json - createdAt DateTime @default(now()) @db.Timestamptz(6) - updatedAt DateTime @default(now()) @updatedAt @db.Timestamptz(6) + payload Json @db.Json + trendingMode Boolean @default(false) @db.Boolean + createdAt DateTime @default(now()) @db.Timestamptz(6) + updatedAt DateTime @default(now()) @updatedAt @db.Timestamptz(6) workspace Workspace @relation(fields: [workspaceId], references: [id]) diff --git a/src/server/prisma/zod/monitor.ts b/src/server/prisma/zod/monitor.ts index 030eba3..e5dc916 100644 --- a/src/server/prisma/zod/monitor.ts +++ b/src/server/prisma/zod/monitor.ts @@ -20,6 +20,7 @@ export const MonitorModelSchema = z.object({ * [CommonPayload] */ payload: imports.CommonPayloadSchema, + trendingMode: z.boolean(), createdAt: z.date(), updatedAt: z.date(), }) diff --git a/src/server/trpc/routers/monitor.ts b/src/server/trpc/routers/monitor.ts index c2a4f71..586b1f4 100644 --- a/src/server/trpc/routers/monitor.ts +++ b/src/server/trpc/routers/monitor.ts @@ -128,6 +128,7 @@ export const monitorRouter = router({ active: z.boolean().default(true), interval: z.number().int().min(5).max(10000).default(20), maxRetries: z.number().int().min(0).max(10).default(0), + trendingMode: z.boolean().default(false), notificationIds: z.array(z.string()).default([]), payload: z.object({}).passthrough(), }) @@ -142,6 +143,7 @@ export const monitorRouter = router({ active, interval, maxRetries, + trendingMode, notificationIds, payload, } = input; @@ -154,6 +156,7 @@ export const monitorRouter = router({ active, interval, maxRetries, + trendingMode, notificationIds, payload, });