mirror of
https://github.com/hansjone/netxops.git
synced 2026-10-13 05:40:44 +08:00
59 lines
3.5 KiB
TypeScript
59 lines
3.5 KiB
TypeScript
/** Exercise the real card and controller with an in-memory Host for visual QA. */
|
|
import { useSyncExternalStore } from 'react'
|
|
import { createRoot } from 'react-dom/client'
|
|
import { NetxopsCard } from '../../src/client/NetxopsCard.tsx'
|
|
import { NetxopsCardController } from '../../src/client/controller.ts'
|
|
import { zh, en } from '../../src/client/locales.ts'
|
|
import { unconfiguredKbSnapshot } from '../../src/netx/kb-manifest.ts'
|
|
|
|
const base = {
|
|
apiUrl: 'http://127.0.0.1:8890', lang: 'zh', thinkingLanguage: 'auto', replyLanguage: 'follow-user',
|
|
nmsProvider: 'zte-ume', tokenCredentialRef: 'NETX_API_TOKEN', toolsEnabled: true,
|
|
groupOpsInPreset: true, groupOpsPublic: false, groupOpsPresets: '',
|
|
groupTopologyInPreset: false, groupTopologyPublic: false, groupTopologyPresets: '',
|
|
groupBizMonitorInPreset: true, groupBizMonitorPublic: false, groupBizMonitorPresets: '',
|
|
kbRoot: '', groupKbInPreset: true, groupKbPublic: false, groupKbPresets: '',
|
|
alarmPushEnabled: false, alarmDeliverDsh: true, alarmDeliverIm: false,
|
|
imTargets: '', imBotId: '', imTargetId: '',
|
|
}
|
|
const user = {}, listeners = new Set<() => void>()
|
|
const scope = {
|
|
getSnapshot: () => ({ status: 'ready', writable: true, value: { ...base, ...user }, base, user }),
|
|
subscribe(fn: () => void) { listeners.add(fn); return () => listeners.delete(fn) },
|
|
async set(field: string, value: unknown) { user[field] = value; for (const fn of listeners) fn() },
|
|
async unset(field: string) { delete user[field]; for (const fn of listeners) fn() },
|
|
}
|
|
const previewCredentials = {
|
|
async describe(refs: string[]) {
|
|
return { ok: true, value: Object.fromEntries(refs.map(ref => [ref, { configured: true, writable: true }])) }
|
|
},
|
|
async set() { /* Preview only; no credentials are stored. */ },
|
|
}
|
|
const controller = new NetxopsCardController(scope, {
|
|
get: key => key === 'remote.credentials' ? previewCredentials : undefined,
|
|
} as never)
|
|
controller.setAlarmPushRpc(async (_channel, endpoint) => {
|
|
const value = scope.getSnapshot().value
|
|
if (endpoint === 'presets.catalog') return { ok: true, value: { presets: [
|
|
{ id: 'netxops', name: 'Netx Ops' }, { id: 'standard', name: '标准助手' },
|
|
{ id: 'review', name: '代码审查' }, { id: 'network-analyst', name: '网络分析' },
|
|
] } }
|
|
if (endpoint === 'tools.status') return { ok: true, value: {
|
|
mounts: [{ source: 'Netx Ops', plane: 'preset', version: 'dev', groups: ['ops', 'bizMonitor'],
|
|
names: value.toolsEnabled ? Array.from({ length: 23 }, (_, i) => `netx__preview${i}`) : [],
|
|
count: value.toolsEnabled ? 23 : 0 }],
|
|
connection: { toolsEnabled: value.toolsEnabled, apiUrl: value.apiUrl, tokenConfigured: false },
|
|
} }
|
|
if (endpoint === 'kb.status' || endpoint === 'kb.reload') return { ok: true, value: unconfiguredKbSnapshot() }
|
|
if (endpoint === 'alarm-push.status') return { ok: true, value: { phase: 'disabled', enabled: false, wsUrl: '' } }
|
|
if (endpoint === 'im-delivery.catalog') return { ok: true, value: { available: false, options: [] } }
|
|
return { ok: true, value: { available: false, reasonCode: 'no_persistence', sessionCount: 0 } }
|
|
})
|
|
const face = controller.inject(), store = face.hooks.netxopsCard
|
|
const dictionary = new URLSearchParams(location.search).get('lang') === 'en' ? en : zh
|
|
function Preview() {
|
|
const state = useSyncExternalStore(store.subscribe, store.getSnapshot)
|
|
return <NetxopsCard {...face} t={key => dictionary[key]}
|
|
useNetxopsCard={selector => selector(state)} {...({} as never)} />
|
|
}
|
|
createRoot(document.getElementById('root')!).render(<Preview />)
|