mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-07-25 05:46:18 +00:00
feat: replace notification checkboxes with card-based layout (#5421)
Replace EventBusCheckboxes with card-based notification settings: - Each event group gets its own card with responsive grid layout - Master checkbox per group with indeterminate state - Inline parameter inputs (CPU threshold) appear when enabled - Theme-adaptive via Ant Design Card component Components: - NotificationLayout, NotificationCard, NotificationHeader, NotificationEvent - TelegramNotifications, EmailNotifications with explicit event configs
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
import { InputNumber } from 'antd';
|
||||
import { CloudServerOutlined, ThunderboltOutlined, DesktopOutlined, DashboardOutlined, SafetyOutlined } from '@ant-design/icons';
|
||||
import type { AllSetting } from '@/models/setting';
|
||||
import { NotificationLayout } from './NotificationLayout';
|
||||
import { NotificationGroup } from './NotificationGroup';
|
||||
import type { NotificationGroupConfig } from './types';
|
||||
|
||||
const GROUPS: NotificationGroupConfig[] = [
|
||||
{
|
||||
icon: <CloudServerOutlined />,
|
||||
title: 'eventGroupOutbound',
|
||||
events: [
|
||||
{ key: 'outbound.down', label: 'eventOutboundDown', settingKey: '' },
|
||||
{ key: 'outbound.up', label: 'eventOutboundUp', settingKey: '' },
|
||||
],
|
||||
},
|
||||
{
|
||||
icon: <ThunderboltOutlined />,
|
||||
title: 'eventGroupXray',
|
||||
events: [
|
||||
{ key: 'xray.crash', label: 'eventXrayCrash', settingKey: '' },
|
||||
],
|
||||
},
|
||||
{
|
||||
icon: <DesktopOutlined />,
|
||||
title: 'eventGroupNode',
|
||||
events: [
|
||||
{ key: 'node.down', label: 'eventNodeDown', settingKey: '' },
|
||||
{ key: 'node.up', label: 'eventNodeUp', settingKey: '' },
|
||||
],
|
||||
},
|
||||
{
|
||||
icon: <DashboardOutlined />,
|
||||
title: 'eventGroupSystem',
|
||||
events: [
|
||||
{
|
||||
key: 'cpu.high',
|
||||
label: 'eventCPUHigh',
|
||||
settingKey: 'smtpCpu',
|
||||
extra: ({ value, onChange }) => (
|
||||
<InputNumber size="small" min={0} max={100} value={value} onChange={onChange} style={{ width: 80 }} />
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
icon: <SafetyOutlined />,
|
||||
title: 'eventGroupSecurity',
|
||||
events: [
|
||||
{ key: 'login.attempt', label: 'eventLoginAttempt', settingKey: '' },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
interface Props {
|
||||
allSetting: AllSetting;
|
||||
updateSetting: (patch: Partial<AllSetting>) => void;
|
||||
}
|
||||
|
||||
export function EmailNotifications({ allSetting, updateSetting }: Props) {
|
||||
const events = allSetting.smtpEnabledEvents || '';
|
||||
const selected = events ? events.split(',').map((s) => s.trim()).filter(Boolean) : [];
|
||||
|
||||
function toggle(key: string) {
|
||||
const next = selected.includes(key)
|
||||
? selected.filter((e) => e !== key)
|
||||
: [...selected, key];
|
||||
updateSetting({ smtpEnabledEvents: next.join(',') });
|
||||
}
|
||||
|
||||
function toggleAll(keys: string[]) {
|
||||
const allSelected = keys.every((v) => selected.includes(v));
|
||||
const next = allSelected
|
||||
? selected.filter((v) => !keys.includes(v))
|
||||
: [...new Set([...selected, ...keys])];
|
||||
updateSetting({ smtpEnabledEvents: next.join(',') });
|
||||
}
|
||||
|
||||
return (
|
||||
<NotificationLayout>
|
||||
{GROUPS.map((group, i) => (
|
||||
<NotificationGroup
|
||||
key={i}
|
||||
config={group}
|
||||
selected={selected}
|
||||
onToggle={toggle}
|
||||
onToggleAll={toggleAll}
|
||||
allSetting={allSetting}
|
||||
updateSetting={updateSetting}
|
||||
/>
|
||||
))}
|
||||
</NotificationLayout>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user