feat: add basic notification settings ui

This commit is contained in:
moonrailgun 2023-09-21 00:19:37 +08:00
parent 254c5079c4
commit c180d1d5f1
7 changed files with 206 additions and 13 deletions

View File

@ -0,0 +1,14 @@
import React from 'react';
export const PageHeader: React.FC<{
title: string;
action?: React.ReactNode;
}> = React.memo((props) => {
return (
<div className="h-24 flex items-center">
<div className="text-2xl flex-1">{props.title}</div>
{props.action}
</div>
);
});
PageHeader.displayName = 'PageHeader';

View File

@ -18,6 +18,7 @@ import { useRequest } from '../hooks/useRequest';
import { useUserStore } from '../store/user';
import { useEvent } from '../hooks/useEvent';
import { useNavigate } from 'react-router';
import { PageHeader } from './PageHeader';
export const WebsiteList: React.FC = React.memo(() => {
const [isModalOpen, setIsModalOpen] = useState(false);
@ -43,8 +44,9 @@ export const WebsiteList: React.FC = React.memo(() => {
return (
<div>
<div className="h-24 flex items-center">
<div className="text-2xl flex-1">Websites</div>
<PageHeader
title="Websites"
action={
<div>
<Button
type="primary"
@ -55,7 +57,8 @@ export const WebsiteList: React.FC = React.memo(() => {
Add Website
</Button>
</div>
</div>
}
/>
<WebsiteListTable workspaceId={currentWorkspace.id} />

View File

@ -0,0 +1,55 @@
import { Form, Input, Modal, ModalProps, Select } from 'antd';
import React, { useMemo, useState } from 'react';
import { notificationStrategies } from './strategies';
interface NotificationInfoModalProps
extends Pick<ModalProps, 'open' | 'onOk' | 'onCancel'> {}
export const NotificationInfoModal: React.FC<NotificationInfoModalProps> =
React.memo((props) => {
const [notificationType, setNotificationType] = useState(
notificationStrategies[0].name
);
const form = useMemo(() => {
const strategy = notificationStrategies.find(
(s) => s.name === notificationType
);
if (!strategy) {
return null;
}
const Component = strategy.form;
return <Component />;
}, [notificationType]);
return (
<Modal
title="Notification"
open={props.open}
onOk={props.onOk}
onCancel={props.onCancel}
>
<Form layout="vertical">
<Form.Item label="Notification Type">
<Select
value={notificationType}
onChange={(val) => setNotificationType(val)}
>
{notificationStrategies.map((s) => (
<Select.Option value={s.name}>{s.label}</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item label="Display Name" name="name">
<Input />
</Form.Item>
{form}
</Form>
</Modal>
);
});
NotificationInfoModal.displayName = 'NotificationInfoModal';

View File

@ -0,0 +1,16 @@
import React from 'react';
import { NotificationSMTP } from './smtp';
interface NotificationStrategy {
label: string;
name: string;
form: React.ComponentType;
}
export const notificationStrategies: NotificationStrategy[] = [
{
label: 'Email(SMTP)',
name: 'smtp',
form: NotificationSMTP,
},
];

View File

@ -0,0 +1,43 @@
import { Checkbox, Form, Input, InputNumber, Select } from 'antd';
import React from 'react';
export const NotificationSMTP: React.FC = React.memo(() => {
return (
<>
<Form.Item label="Host" name="hostname">
<Input />
</Form.Item>
<Form.Item label="Port" name="port">
<InputNumber max={65535} min={1} />
</Form.Item>
<Form.Item label="Security" name="security">
<Select>
<Select.Option value={false}>None / STARTTLS (25, 587)</Select.Option>
<Select.Option value={true}>TLS (465)</Select.Option>
</Select>
</Form.Item>
<Form name="ignoreTLS">
<Checkbox>Ignore TLS Error</Checkbox>
</Form>
<Form.Item label="Username" name="username">
<Input />
</Form.Item>
<Form.Item label="Password" name="password">
<Input.Password />
</Form.Item>
<Form.Item label="From Email" name="from">
<Input />
</Form.Item>
<Form.Item label="To Email" name="to">
<Input />
</Form.Item>
<Form.Item label="CC" name="cc">
<Input />
</Form.Item>
<Form.Item label="BCC" name="bcc">
<Input />
</Form.Item>
</>
);
});
NotificationSMTP.displayName = 'NotificationSMTP';

View File

@ -0,0 +1,56 @@
import { PlusOutlined } from '@ant-design/icons';
import { Button, List } from 'antd';
import React, { useState } from 'react';
import { NotificationInfoModal } from '../../components/modals/NotificationInfo';
import { PageHeader } from '../../components/PageHeader';
import { useEvent } from '../../hooks/useEvent';
export const NotificationList: React.FC = React.memo(() => {
const [open, setOpen] = useState(false);
const handleOk = useEvent(() => {
console.log('ok');
setOpen(false);
});
return (
<div>
<PageHeader
title="Notification List"
action={
<div>
<Button
type="primary"
icon={<PlusOutlined />}
size="large"
onClick={() => setOpen(true)}
>
New
</Button>
</div>
}
/>
<List
bordered={true}
dataSource={[
{ id: '1', name: 'Email Notify' },
{ id: '1', name: 'Email Notify' },
{ id: '1', name: 'Email Notify' },
]}
renderItem={(item) => (
<List.Item actions={[<Button>edit</Button>]}>
<List.Item.Meta title={item.name} />
</List.Item>
)}
/>
<NotificationInfoModal
open={open}
onOk={handleOk}
onCancel={() => setOpen(false)}
/>
</div>
);
});
NotificationList.displayName = 'NotificationList';

View File

@ -4,6 +4,7 @@ import { Routes, Route, useLocation, useNavigate } from 'react-router-dom';
import { WebsiteInfo } from '../../components/WebsiteInfo';
import { WebsiteList } from '../../components/WebsiteList';
import { useEvent } from '../../hooks/useEvent';
import { NotificationList } from './NotificationList';
export const SettingsPage: React.FC = React.memo(() => {
const navigate = useNavigate();
@ -14,6 +15,10 @@ export const SettingsPage: React.FC = React.memo(() => {
key: 'websites',
label: 'Websites',
},
{
key: 'notifications',
label: 'Notifications',
},
];
const onClick: MenuProps['onClick'] = useEvent((e) => {
@ -40,6 +45,7 @@ export const SettingsPage: React.FC = React.memo(() => {
<Route path="/" element={<WebsiteList />} />
<Route path="/websites" element={<WebsiteList />} />
<Route path="/website/:websiteId" element={<WebsiteInfo />} />
<Route path="/notifications" element={<NotificationList />} />
</Routes>
</div>
</div>