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,
|
||||
FormProps,
|
||||
Input,
|
||||
message,
|
||||
Modal,
|
||||
ModalProps,
|
||||
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 React, { useState } from 'react';
|
||||
import { trpc } from '../api/trpc';
|
||||
import { useCurrentWorkspaceId } from '../store/user';
|
||||
import { HealthBar } from './HealthBar';
|
||||
import { NoWorkspaceTip } from './NoWorkspaceTip';
|
||||
import { trpc } from '../../../api/trpc';
|
||||
import { useCurrentWorkspaceId } from '../../../store/user';
|
||||
import { HealthBar } from '../../HealthBar';
|
||||
import { NoWorkspaceTip } from '../../NoWorkspaceTip';
|
||||
|
||||
export const MonitorList: React.FC = React.memo(() => {
|
||||
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="/monitor" label="Monitor" />
|
||||
<NavItem to="/website" label="Website" />
|
||||
<NavItem to="/Servers" label="Servers" />
|
||||
<NavItem to="/servers" label="Servers" />
|
||||
<NavItem to="/settings" label="Settings" />
|
||||
</div>
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { MonitorInfoEditor } from '../../components/MonitorInfoEditor';
|
||||
import { MonitorInfoEditor } from '../../components/modals/monitor/MonitorInfoEditor';
|
||||
import { useCurrentWorkspaceId } from '../../store/user';
|
||||
|
||||
export const MonitorAdd: React.FC = React.memo(() => {
|
||||
|
@ -3,7 +3,7 @@ import { useParams } from 'react-router';
|
||||
import { trpc } from '../../api/trpc';
|
||||
import { ErrorTip } from '../../components/ErrorTip';
|
||||
import { Loading } from '../../components/Loading';
|
||||
import { MonitorInfoEditor } from '../../components/MonitorInfoEditor';
|
||||
import { MonitorInfoEditor } from '../../components/modals/monitor/MonitorInfoEditor';
|
||||
import { useCurrentWorkspaceId } from '../../store/user';
|
||||
|
||||
export const MonitorEdit: React.FC = React.memo(() => {
|
||||
@ -25,7 +25,7 @@ export const MonitorEdit: React.FC = React.memo(() => {
|
||||
return (
|
||||
<div>
|
||||
<MonitorInfoEditor
|
||||
initValue={monitor}
|
||||
initialValues={monitor}
|
||||
onSave={(value) => {
|
||||
console.log(value);
|
||||
}}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Route, Routes, useNavigate } from 'react-router';
|
||||
import { MonitorList } from '../../components/MonitorList';
|
||||
import { MonitorList } from '../../components/modals/monitor/MonitorList';
|
||||
import { MonitorAdd } from './Add';
|
||||
import { MonitorDetail } from './Detail';
|
||||
import { MonitorEdit } from './Edit';
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { ping } from './ping';
|
||||
import type { MonitorProvider } from './type';
|
||||
|
||||
export const monitorProviders: Record<string, MonitorProvider> = {
|
||||
export const monitorProviders: Record<string, MonitorProvider<any>> = {
|
||||
ping,
|
||||
};
|
||||
|
@ -1,13 +1,15 @@
|
||||
import { MonitorProvider } from './type';
|
||||
import pingUtils from 'ping';
|
||||
|
||||
export const ping: MonitorProvider = {
|
||||
export const ping: MonitorProvider<{
|
||||
hostname: string;
|
||||
}> = {
|
||||
run: async (monitor) => {
|
||||
if (typeof monitor.payload !== 'object') {
|
||||
throw new Error('monitor.payload should be object');
|
||||
}
|
||||
|
||||
const { hostname } = monitor.payload as any;
|
||||
const { hostname } = monitor.payload;
|
||||
|
||||
const res = await pingAction(hostname);
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { Monitor } from '@prisma/client';
|
||||
import type { ExactType } from '../../../../types';
|
||||
|
||||
export interface MonitorProvider {
|
||||
run: (monitor: Monitor) => Promise<number>;
|
||||
export interface MonitorProvider<Payload extends Record<string, any>> {
|
||||
run: (monitor: ExactType<Monitor, { payload: Payload }>) => Promise<number>;
|
||||
}
|
||||
|
@ -1 +1,2 @@
|
||||
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