import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { Alert, Empty, Input, InputNumber, Select, Space, Switch, Tag } from 'antd'; import { onNumber } from '@/utils/onNumber'; import { SettingListItem } from '@/components/ui'; import { BurstObservatorySchema, ObservatoryHttpMethodSchema, ObservatorySchema, type BurstObservatoryObject, type ObservatoryHttpMethod, type ObservatoryObject, type PingConfigObject, } from '@/schemas/observatory'; import type { XraySettingsValue } from '@/hooks/useXraySetting'; import { settingsRequireBurstObservatory } from './balancer-helpers'; interface ObservatorySettingsTabProps { templateSettings: XraySettingsValue | null; mutate: (mutator: (next: XraySettingsValue) => void) => void; } const OBSERVATORY_DEFAULTS = ObservatorySchema.parse({}); const BURST_DEFAULTS = BurstObservatorySchema.parse({}); function asObject(value: unknown): Record { return value && typeof value === 'object' ? (value as Record) : {}; } function SelectorTags({ tags }: { tags: string[] }) { if (!tags || tags.length === 0) return ; return ( <> {tags.map((sel) => ( {sel} ))} ); } export default function ObservatorySettingsTab({ templateSettings, mutate, }: ObservatorySettingsTabProps) { const { t } = useTranslation(); const observatory = useMemo(() => { const raw = templateSettings?.observatory; if (raw == null) return null; return { ...OBSERVATORY_DEFAULTS, ...asObject(raw) } as ObservatoryObject; }, [templateSettings?.observatory]); const burst = useMemo(() => { const raw = templateSettings?.burstObservatory; if (raw == null) return null; const merged = { ...BURST_DEFAULTS, ...asObject(raw) } as BurstObservatoryObject; merged.pingConfig = { ...BURST_DEFAULTS.pingConfig, ...asObject(merged.pingConfig) } as PingConfigObject; return merged; }, [templateSettings?.burstObservatory]); const hasObservatory = observatory != null; const hasBurst = burst != null; const hasMixedObservers = hasObservatory && hasBurst; const activeView = hasBurst && (!hasObservatory || settingsRequireBurstObservatory(templateSettings)) ? 'burstObservatory' : 'observatory'; function patchObservatory(patch: Partial) { mutate((tt) => { tt.observatory = { ...OBSERVATORY_DEFAULTS, ...asObject(tt.observatory), ...patch }; }); } function patchPingConfig(patch: Partial) { mutate((tt) => { const current = asObject(tt.burstObservatory); const currentPing = asObject(current.pingConfig); tt.burstObservatory = { ...BURST_DEFAULTS, ...current, pingConfig: { ...BURST_DEFAULTS.pingConfig, ...currentPing, ...patch }, }; }); } if (!hasObservatory && !hasBurst) { return ; } const observatorySection = observatory && ( <> patchObservatory({ probeURL: e.target.value })} placeholder="https://www.google.com/generate_204" /> patchObservatory({ probeInterval: e.target.value })} placeholder="1m" /> patchObservatory({ enableConcurrency: v })} /> ); const burstSection = burst && ( <> patchPingConfig({ destination: e.target.value })} placeholder="https://www.google.com/generate_204" /> patchPingConfig({ connectivity: e.target.value })} placeholder="http://connectivitycheck.platform.hicloud.com/generate_204" /> patchPingConfig({ interval: e.target.value })} placeholder="1m" /> patchPingConfig({ timeout: e.target.value })} placeholder="5s" /> patchPingConfig({ sampling: v }))} style={{ width: '100%' }} /> value={burst.pingConfig.httpMethod} onChange={(v) => patchPingConfig({ httpMethod: v })} options={ObservatoryHttpMethodSchema.options.map((m) => ({ value: m, label: m }))} style={{ width: '100%' }} /> ); return ( {hasMixedObservers && ( )}
{activeView === 'observatory' ? observatorySection : burstSection}
); }