From d5f0d9b6956e6271bf0e57f3427a32605c9be781 Mon Sep 17 00:00:00 2001 From: Nezumi-2711 Date: Tue, 15 Sep 2026 12:15:31 +0700 Subject: [PATCH] [#000] fix: improve the setting pages --- .../components/settings/AiActivityPanel.tsx | 16 +- .../settings/AiIncidentMessagesPanel.tsx | 165 +++ .../settings/MaintenanceWindowDialog.tsx | 39 +- .../settings/MaintenanceWindowsPanel.tsx | 21 +- .../settings/NotificationChannelDialog.tsx | 46 +- .../settings/NotificationChannelsPanel.tsx | 55 +- src/client/pages/SettingsPage.tsx | 285 ++--- src/client/styles.css | 78 +- src/client/styles/SettingsPage.css | 1099 ----------------- src/components/ui/tabs.tsx | 44 + 10 files changed, 473 insertions(+), 1375 deletions(-) create mode 100644 src/client/components/settings/AiIncidentMessagesPanel.tsx delete mode 100644 src/client/styles/SettingsPage.css create mode 100644 src/components/ui/tabs.tsx diff --git a/src/client/components/settings/AiActivityPanel.tsx b/src/client/components/settings/AiActivityPanel.tsx index bd124d0..44af587 100644 --- a/src/client/components/settings/AiActivityPanel.tsx +++ b/src/client/components/settings/AiActivityPanel.tsx @@ -19,8 +19,8 @@ export function AiActivityPanel() { const { events, summary } = query.data; const tokenTotal = summary.promptTokens + summary.completionTokens; return ( -
-
+
+
{summary.total ? Math.round((summary.ok / summary.total) * 100) : 0}% Success rate @@ -39,14 +39,20 @@ export function AiActivityPanel() {
{events.length === 0 ? ( - + No AI activity yet Attempts will appear here after AI generation or autopilot runs. ) : ( -
+
{events.map((event) => ( -
+
{event.outcome.replaceAll('_', ' ')} diff --git a/src/client/components/settings/AiIncidentMessagesPanel.tsx b/src/client/components/settings/AiIncidentMessagesPanel.tsx new file mode 100644 index 0000000..aaefb1e --- /dev/null +++ b/src/client/components/settings/AiIncidentMessagesPanel.tsx @@ -0,0 +1,165 @@ +import { type FormEvent, useState } from 'react'; +import { Sparkles } from 'lucide-react'; +import { Button } from '@/components/ui/button'; +import { Empty, EmptyTitle } from '@/components/ui/empty'; +import { Input } from '@/components/ui/input'; +import { Switch } from '@/components/ui/switch'; +import type { AiSettings } from '../../api/settings'; +import { useAiSettingsQuery, useTestAiSettingsMutation, useUpdateAiSettingsMutation } from '../../queries/settings'; + +function AiSettingsForm({ settings }: { settings: AiSettings }) { + const [baseUrl, setBaseUrl] = useState(settings.baseUrl ?? 'https://api.openai.com/v1'); + const [apiKey, setApiKey] = useState(''); + const [model, setModel] = useState(settings.model ?? 'gpt-4o-mini'); + const [enabled, setEnabled] = useState(settings.enabled); + const [autopilotEnabled, setAutopilotEnabled] = useState(settings.autopilotEnabled); + const [followupMinutes, setFollowupMinutes] = useState(settings.autopilotFollowupMinutes); + const [maxUpdates, setMaxUpdates] = useState(settings.autopilotMaxUpdates); + const [advanceStatus, setAdvanceStatus] = useState(settings.autopilotAdvanceStatus); + const [degradedIncidents, setDegradedIncidents] = useState(settings.autopilotDegradedIncidents); + const updateMutation = useUpdateAiSettingsMutation(); + const testMutation = useTestAiSettingsMutation(); + + function submit(event: FormEvent) { + event.preventDefault(); + updateMutation.mutate({ + enabled, + baseUrl: baseUrl.trim() || null, + model: model.trim() || null, + apiKey: apiKey.trim() || null, + autopilotEnabled, + autopilotFollowupMinutes: followupMinutes, + autopilotMaxUpdates: maxUpdates, + autopilotAdvanceStatus: advanceStatus, + autopilotDegradedIncidents: degradedIncidents, + }); + } + + return ( +
+ + + +
+ + +
+
+ Autopilot +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ + +
+ {updateMutation.isSuccess && ( +

+ AI settings saved. +

+ )} + {testMutation.isSuccess && ( +

+ {testMutation.data.message} +

+ )} + {(updateMutation.error || testMutation.error) && ( +

{(updateMutation.error ?? testMutation.error)?.message ?? 'Request failed'}

+ )} +
+ ); +} + +export function AiIncidentMessagesPanel() { + const aiSettingsQuery = useAiSettingsQuery(); + if (aiSettingsQuery.isPending) return
Loading settings…
; + if (aiSettingsQuery.isError) { + return ( + + Unable to load AI settings + + ); + } + return ; +} diff --git a/src/client/components/settings/MaintenanceWindowDialog.tsx b/src/client/components/settings/MaintenanceWindowDialog.tsx index 23f55d1..22488a3 100644 --- a/src/client/components/settings/MaintenanceWindowDialog.tsx +++ b/src/client/components/settings/MaintenanceWindowDialog.tsx @@ -115,8 +115,8 @@ export function MaintenanceWindowDialog({ editing, onClose }: { editing: Mainten {editing ? `Edit ${editing.name}` : 'Add maintenance window'} Probes continue, but alerts and uptime calculations pause for selected services. -
-