feat: add monitor editor
This commit is contained in:
parent
a92dd513f1
commit
ea5c237c29
@ -1,17 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import type { Monitor } from '@prisma/client';
|
|
||||||
|
|
||||||
type MonitorInfoEditorValues = Omit<Monitor, 'id'> & {
|
|
||||||
id?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
interface MonitorInfoEditorProps {
|
|
||||||
initValue?: MonitorInfoEditorValues;
|
|
||||||
onSave: (value: MonitorInfoEditorValues) => void;
|
|
||||||
}
|
|
||||||
export const MonitorInfoEditor: React.FC<MonitorInfoEditorProps> = React.memo(
|
|
||||||
(props) => {
|
|
||||||
return <div>MonitorInfoEditor</div>;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
MonitorInfoEditor.displayName = 'MonitorInfoEditor';
|
|
@ -3,7 +3,6 @@ import {
|
|||||||
Form,
|
Form,
|
||||||
FormProps,
|
FormProps,
|
||||||
Input,
|
Input,
|
||||||
message,
|
|
||||||
Modal,
|
Modal,
|
||||||
ModalProps,
|
ModalProps,
|
||||||
Select,
|
Select,
|
||||||
|
92
src/client/components/modals/monitor/MonitorInfoEditor.tsx
Normal file
92
src/client/components/modals/monitor/MonitorInfoEditor.tsx
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
import React, { useMemo } from 'react';
|
||||||
|
import type { Monitor } from '@prisma/client';
|
||||||
|
import { Button, Form, Input, InputNumber, Select } from 'antd';
|
||||||
|
import { monitorProviders } from './provider';
|
||||||
|
import { useEvent } from '../../../hooks/useEvent';
|
||||||
|
|
||||||
|
type MonitorInfoEditorValues = Omit<
|
||||||
|
Monitor,
|
||||||
|
'id' | 'workspaceId' | 'createdAt'
|
||||||
|
> & {
|
||||||
|
id?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const defaultValues: Omit<MonitorInfoEditorValues, 'payload'> = {
|
||||||
|
name: 'New Monitor',
|
||||||
|
type: monitorProviders[0].name,
|
||||||
|
active: true,
|
||||||
|
interval: 60,
|
||||||
|
};
|
||||||
|
|
||||||
|
interface MonitorInfoEditorProps {
|
||||||
|
initialValues?: MonitorInfoEditorValues;
|
||||||
|
onSave: (value: MonitorInfoEditorValues) => void;
|
||||||
|
}
|
||||||
|
export const MonitorInfoEditor: React.FC<MonitorInfoEditorProps> = React.memo(
|
||||||
|
(props) => {
|
||||||
|
const [form] = Form.useForm();
|
||||||
|
const typeValue = Form.useWatch('type', form);
|
||||||
|
|
||||||
|
const formEl = useMemo(() => {
|
||||||
|
const provider = monitorProviders.find((s) => s.name === typeValue);
|
||||||
|
|
||||||
|
if (!provider) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Component = provider.form;
|
||||||
|
|
||||||
|
return <Component />;
|
||||||
|
}, [typeValue]);
|
||||||
|
|
||||||
|
const handleSubmit = useEvent((values) => {
|
||||||
|
props.onSave({
|
||||||
|
...values,
|
||||||
|
active: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="px-4">
|
||||||
|
<Form
|
||||||
|
preserve={false}
|
||||||
|
form={form}
|
||||||
|
layout="vertical"
|
||||||
|
initialValues={props.initialValues ?? defaultValues}
|
||||||
|
onFinish={handleSubmit}
|
||||||
|
>
|
||||||
|
<Form.Item hidden name="id" />
|
||||||
|
|
||||||
|
<Form.Item label="Monitor Type" name="type">
|
||||||
|
<Select>
|
||||||
|
{monitorProviders.map((m) => (
|
||||||
|
<Select.Option key={m.name} value={m.name}>
|
||||||
|
{m.label}
|
||||||
|
</Select.Option>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item label="Name" name="name" rules={[{ required: true }]}>
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item
|
||||||
|
label="Check Interval"
|
||||||
|
name="interval"
|
||||||
|
rules={[{ required: true }]}
|
||||||
|
>
|
||||||
|
<InputNumber min={5} max={10000} step={10} />
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
{formEl}
|
||||||
|
|
||||||
|
<Button type="primary" htmlType="submit">
|
||||||
|
Save
|
||||||
|
</Button>
|
||||||
|
</Form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
MonitorInfoEditor.displayName = 'MonitorInfoEditor';
|
@ -1,9 +1,9 @@
|
|||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { trpc } from '../api/trpc';
|
import { trpc } from '../../../api/trpc';
|
||||||
import { useCurrentWorkspaceId } from '../store/user';
|
import { useCurrentWorkspaceId } from '../../../store/user';
|
||||||
import { HealthBar } from './HealthBar';
|
import { HealthBar } from '../../HealthBar';
|
||||||
import { NoWorkspaceTip } from './NoWorkspaceTip';
|
import { NoWorkspaceTip } from '../../NoWorkspaceTip';
|
||||||
|
|
||||||
export const MonitorList: React.FC = React.memo(() => {
|
export const MonitorList: React.FC = React.memo(() => {
|
||||||
const currentWorkspaceId = useCurrentWorkspaceId()!;
|
const currentWorkspaceId = useCurrentWorkspaceId()!;
|
16
src/client/components/modals/monitor/provider/index.ts
Normal file
16
src/client/components/modals/monitor/provider/index.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { MonitorPing } from './ping';
|
||||||
|
|
||||||
|
interface MonitorProvider {
|
||||||
|
label: string;
|
||||||
|
name: string;
|
||||||
|
form: React.ComponentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const monitorProviders: MonitorProvider[] = [
|
||||||
|
{
|
||||||
|
label: 'Ping',
|
||||||
|
name: 'ping',
|
||||||
|
form: MonitorPing,
|
||||||
|
},
|
||||||
|
];
|
17
src/client/components/modals/monitor/provider/ping.tsx
Normal file
17
src/client/components/modals/monitor/provider/ping.tsx
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { Form, Input } from 'antd';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export const MonitorPing: React.FC = React.memo(() => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Form.Item
|
||||||
|
label="Host"
|
||||||
|
name={['payload', 'hostname']}
|
||||||
|
rules={[{ required: true }]}
|
||||||
|
>
|
||||||
|
<Input placeholder="example.com or 1.2.3.4" />
|
||||||
|
</Form.Item>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
MonitorPing.displayName = 'MonitorPing';
|
@ -28,7 +28,7 @@ export const Layout: React.FC = React.memo(() => {
|
|||||||
<NavItem to="/dashboard" label="Dashboard" />
|
<NavItem to="/dashboard" label="Dashboard" />
|
||||||
<NavItem to="/monitor" label="Monitor" />
|
<NavItem to="/monitor" label="Monitor" />
|
||||||
<NavItem to="/website" label="Website" />
|
<NavItem to="/website" label="Website" />
|
||||||
<NavItem to="/Servers" label="Servers" />
|
<NavItem to="/servers" label="Servers" />
|
||||||
<NavItem to="/settings" label="Settings" />
|
<NavItem to="/settings" label="Settings" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { MonitorInfoEditor } from '../../components/MonitorInfoEditor';
|
import { MonitorInfoEditor } from '../../components/modals/monitor/MonitorInfoEditor';
|
||||||
import { useCurrentWorkspaceId } from '../../store/user';
|
import { useCurrentWorkspaceId } from '../../store/user';
|
||||||
|
|
||||||
export const MonitorAdd: React.FC = React.memo(() => {
|
export const MonitorAdd: React.FC = React.memo(() => {
|
||||||
|
@ -3,7 +3,7 @@ import { useParams } from 'react-router';
|
|||||||
import { trpc } from '../../api/trpc';
|
import { trpc } from '../../api/trpc';
|
||||||
import { ErrorTip } from '../../components/ErrorTip';
|
import { ErrorTip } from '../../components/ErrorTip';
|
||||||
import { Loading } from '../../components/Loading';
|
import { Loading } from '../../components/Loading';
|
||||||
import { MonitorInfoEditor } from '../../components/MonitorInfoEditor';
|
import { MonitorInfoEditor } from '../../components/modals/monitor/MonitorInfoEditor';
|
||||||
import { useCurrentWorkspaceId } from '../../store/user';
|
import { useCurrentWorkspaceId } from '../../store/user';
|
||||||
|
|
||||||
export const MonitorEdit: React.FC = React.memo(() => {
|
export const MonitorEdit: React.FC = React.memo(() => {
|
||||||
@ -25,7 +25,7 @@ export const MonitorEdit: React.FC = React.memo(() => {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<MonitorInfoEditor
|
<MonitorInfoEditor
|
||||||
initValue={monitor}
|
initialValues={monitor}
|
||||||
onSave={(value) => {
|
onSave={(value) => {
|
||||||
console.log(value);
|
console.log(value);
|
||||||
}}
|
}}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Route, Routes, useNavigate } from 'react-router';
|
import { Route, Routes, useNavigate } from 'react-router';
|
||||||
import { MonitorList } from '../../components/MonitorList';
|
import { MonitorList } from '../../components/modals/monitor/MonitorList';
|
||||||
import { MonitorAdd } from './Add';
|
import { MonitorAdd } from './Add';
|
||||||
import { MonitorDetail } from './Detail';
|
import { MonitorDetail } from './Detail';
|
||||||
import { MonitorEdit } from './Edit';
|
import { MonitorEdit } from './Edit';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { ping } from './ping';
|
import { ping } from './ping';
|
||||||
import type { MonitorProvider } from './type';
|
import type { MonitorProvider } from './type';
|
||||||
|
|
||||||
export const monitorProviders: Record<string, MonitorProvider> = {
|
export const monitorProviders: Record<string, MonitorProvider<any>> = {
|
||||||
ping,
|
ping,
|
||||||
};
|
};
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
import { MonitorProvider } from './type';
|
import { MonitorProvider } from './type';
|
||||||
import pingUtils from 'ping';
|
import pingUtils from 'ping';
|
||||||
|
|
||||||
export const ping: MonitorProvider = {
|
export const ping: MonitorProvider<{
|
||||||
|
hostname: string;
|
||||||
|
}> = {
|
||||||
run: async (monitor) => {
|
run: async (monitor) => {
|
||||||
if (typeof monitor.payload !== 'object') {
|
if (typeof monitor.payload !== 'object') {
|
||||||
throw new Error('monitor.payload should be object');
|
throw new Error('monitor.payload should be object');
|
||||||
}
|
}
|
||||||
|
|
||||||
const { hostname } = monitor.payload as any;
|
const { hostname } = monitor.payload;
|
||||||
|
|
||||||
const res = await pingAction(hostname);
|
const res = await pingAction(hostname);
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { Monitor } from '@prisma/client';
|
import { Monitor } from '@prisma/client';
|
||||||
|
import type { ExactType } from '../../../../types';
|
||||||
|
|
||||||
export interface MonitorProvider {
|
export interface MonitorProvider<Payload extends Record<string, any>> {
|
||||||
run: (monitor: Monitor) => Promise<number>;
|
run: (monitor: ExactType<Monitor, { payload: Payload }>) => Promise<number>;
|
||||||
}
|
}
|
||||||
|
@ -1 +1,2 @@
|
|||||||
export * from './server';
|
export * from './server';
|
||||||
|
export * from './utils';
|
||||||
|
1
src/types/utils.ts
Normal file
1
src/types/utils.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export type ExactType<T, U extends Partial<T>> = Omit<T, keyof U> & U;
|
Loading…
Reference in New Issue
Block a user