import { Fragment, useMemo, useState } from "react"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { apiPost, disconnectUmeToken, fetchUmeNe, cancelUmeAlarmSubscription, clearLocalUmeAlarmSubscription, establishUmeAlarmSubscription, fetchUmeAlarmSubscriptionStatus, fetchUmeAlarmKeywords, fetchUmeInventoryNeTypes, fetchUmeKeyAlertMonitor, fetchUmeNotificationIds, fetchUmeSyncStatus, fetchUmeTokenStatus, fetchCliTargets, refreshUmeToken, upsertUmeKeyAlertRule, deleteUmeKeyAlertRule, patchUmeKeyAlertRule, updateUmeKeyAlertMonitorConfig, } from "../services/api"; import { HelpHint } from "../components/HelpHint"; import { UmeCliConnectPanel } from "../components/UmeCliConnectPanel"; import { queryKeys } from "../constants/queryKeys"; import { useI18n } from "../i18n"; import { useToast } from "../hooks/useToast"; import type { UmeAlarmSubscriptionStatus, UmeKeyAlertRuleItem } from "../types"; import { pageCount, runtimeIntervalLabel } from "../utils/display"; import { runtimeLastError, wsConnectionLabel } from "../utils/runtimeMessages"; import { formatSystemTime } from "../utils/time"; import { openOrFocusModule } from "../utils/moduleWindows"; export function UmePage() { const { t } = useI18n(); const { showOk, showError } = useToast(); const queryClient = useQueryClient(); const [tokenOpError, setTokenOpError] = useState(""); const [runtimeTaskError, setRuntimeTaskError] = useState(""); const [subscriptionOpError, setSubscriptionOpError] = useState(""); const [syncPage, setSyncPage] = useState(1); const [syncPageSize, setSyncPageSize] = useState(20); const [neKeyword, setNeKeyword] = useState(""); const [nePage, setNePage] = useState(1); const [nePageSize, setNePageSize] = useState(50); const [expandedNeId, setExpandedNeId] = useState(""); const [nePanelOpen, setNePanelOpen] = useState(false); const [syncStatusPanelOpen, setSyncStatusPanelOpen] = useState(false); const [keyAlertPanelOpen, setKeyAlertPanelOpen] = useState(false); const [keyAlertMatchType, setKeyAlertMatchType] = useState<"notification_id" | "keyword">("keyword"); const [keyAlertMatchValue, setKeyAlertMatchValue] = useState(""); const [keyAlertLabel, setKeyAlertLabel] = useState(""); const [keyAlertOpError, setKeyAlertOpError] = useState(""); const [keyAlertKeywordHints, setKeyAlertKeywordHints] = useState([]); const [keyAlertIdHints, setKeyAlertIdHints] = useState< Array<{ notification_id: string; native_probable_cause_sample: string }> >([]); const [keyAlertPage, setKeyAlertPage] = useState(1); const [keyAlertPageSize, setKeyAlertPageSize] = useState(20); const [keyAlertFilterKeyword, setKeyAlertFilterKeyword] = useState(""); const [keyAlertFilterEnabled, setKeyAlertFilterEnabled] = useState<"" | "true" | "false">(""); const [keyAlertFilterMatchType, setKeyAlertFilterMatchType] = useState<"" | "notification_id" | "keyword">(""); const [keyAlertNeTypes, setKeyAlertNeTypes] = useState([]); const [keyAlertEditRule, setKeyAlertEditRule] = useState(null); const [keyAlertEditNeTypes, setKeyAlertEditNeTypes] = useState([]); const [cliPanelOpen, setCliPanelOpen] = useState(false); const syncStatusQuery = useQuery({ queryKey: queryKeys.umeSyncStatus(syncPage, syncPageSize), queryFn: () => fetchUmeSyncStatus({ page: syncPage, pageSize: syncPageSize }), staleTime: 5000, refetchInterval: 5000, }); const tokenStatusQuery = useQuery({ queryKey: queryKeys.umeTokenStatus, queryFn: fetchUmeTokenStatus, staleTime: 3000, refetchInterval: 5000, }); const tokenRefreshMutation = useMutation({ mutationFn: refreshUmeToken, onMutate: () => setTokenOpError(""), onSuccess: async (res) => { if (!res?.ok) { const msg = String(res.error || res.error_kind || "token_refresh_failed"); setTokenOpError(msg); showError(msg); } else { setTokenOpError(""); showOk(res.changed ? t("ume.token.renewOkChanged") : t("ume.token.renewOkSame")); } await queryClient.invalidateQueries({ queryKey: queryKeys.umeTokenStatus }); await queryClient.invalidateQueries({ queryKey: queryKeys.umeSyncStatusAll }); }, onError: (err) => { const msg = String(err); setTokenOpError(msg); showError(msg); }, }); const subscriptionStatusQuery = useQuery({ queryKey: queryKeys.umeAlarmSubscription, queryFn: fetchUmeAlarmSubscriptionStatus, staleTime: 3000, refetchInterval: 5000, }); const keyAlertMonitorQuery = useQuery({ queryKey: queryKeys.umeKeyAlertMonitor( keyAlertPage, keyAlertPageSize, keyAlertFilterKeyword, keyAlertFilterEnabled, keyAlertFilterMatchType, ), queryFn: () => fetchUmeKeyAlertMonitor({ page: keyAlertPage, pageSize: keyAlertPageSize, keyword: keyAlertFilterKeyword, enabled: keyAlertFilterEnabled, matchType: keyAlertFilterMatchType, }), staleTime: 3000, refetchInterval: 5000, enabled: keyAlertPanelOpen, }); const keyAlertNeTypesQuery = useQuery({ queryKey: queryKeys.umeInventoryNeTypes, queryFn: () => fetchUmeInventoryNeTypes(), staleTime: 60_000, }); const confirmClearLocalSubscription = (hint?: string) => window.confirm(hint || t("ume.subscription.confirmClearDefault")); const subscriptionEstablishMutation = useMutation({ mutationFn: (opts?: { forceReestablish?: boolean }) => establishUmeAlarmSubscription(opts), onMutate: () => setSubscriptionOpError(""), onSuccess: async (res) => { if (!res?.active) { const msg = t("ume.subscription.establishInvalid"); setSubscriptionOpError(msg); showError(msg); } else { setSubscriptionOpError(""); showOk(res.already_exists ? t("ume.subscription.establishExists") : t("ume.subscription.establishOk")); } await queryClient.invalidateQueries({ queryKey: queryKeys.umeAlarmSubscription }); await queryClient.invalidateQueries({ queryKey: queryKeys.umeSyncStatusAll }); }, onError: (err) => { const msg = String(err); setSubscriptionOpError(msg); showError(msg); }, }); const subscriptionClearLocalMutation = useMutation({ mutationFn: clearLocalUmeAlarmSubscription, onMutate: () => setSubscriptionOpError(""), onSuccess: async () => { setSubscriptionOpError(""); showOk(t("ume.subscription.clearLocalOk")); await queryClient.invalidateQueries({ queryKey: queryKeys.umeAlarmSubscription }); await queryClient.invalidateQueries({ queryKey: queryKeys.umeSyncStatusAll }); }, onError: (err) => { const msg = String(err); setSubscriptionOpError(msg); showError(msg); }, }); const subscriptionCancelMutation = useMutation({ mutationFn: (opts?: { forceClearLocal?: boolean }) => cancelUmeAlarmSubscription(opts), onMutate: () => setSubscriptionOpError(""), onSuccess: async (res) => { if (res?.needs_local_cleanup) { const msg = res.message || t("ume.subscription.serverLostMsg"); if (confirmClearLocalSubscription(msg)) { subscriptionCancelMutation.mutate({ forceClearLocal: true }); return; } setSubscriptionOpError(msg); showError(msg); await queryClient.invalidateQueries({ queryKey: queryKeys.umeAlarmSubscription }); await queryClient.invalidateQueries({ queryKey: queryKeys.umeSyncStatusAll }); return; } if (res?.active) { const msg = t("ume.subscription.cancelFailed"); setSubscriptionOpError(msg); showError(msg); } else { setSubscriptionOpError(""); showOk(res?.ume_already_missing ? t("ume.subscription.cancelOkMissing") : t("ume.subscription.cancelOk")); } await queryClient.invalidateQueries({ queryKey: queryKeys.umeAlarmSubscription }); await queryClient.invalidateQueries({ queryKey: queryKeys.umeSyncStatusAll }); }, onError: (err) => { const msg = String(err); setSubscriptionOpError(msg); showError(msg); }, }); const tokenDisconnectMutation = useMutation({ mutationFn: disconnectUmeToken, onMutate: () => setTokenOpError(""), onSuccess: async (res) => { if (!res?.ok) { const msg = String(res.error || res.error_kind || "token_disconnect_failed"); setTokenOpError(msg); showError(msg); } else { setTokenOpError(""); showOk(t("ume.token.disconnectOk")); } await queryClient.invalidateQueries({ queryKey: queryKeys.umeTokenStatus }); await queryClient.invalidateQueries({ queryKey: queryKeys.umeSyncStatusAll }); }, onError: (err) => { const msg = String(err); setTokenOpError(msg); showError(msg); }, }); const tokenExpiresIn = Number(tokenStatusQuery.data?.expires_in_s || 0); const hasToken = Boolean(tokenStatusQuery.data?.has_token); const tokenNeedsRenewal = hasToken && tokenExpiresIn <= 0; const tokenLevel = !hasToken ? "down" : tokenNeedsRenewal ? "warn" : tokenExpiresIn < 15 ? "down" : tokenExpiresIn < 60 ? "unknown" : "up"; const neQuery = useQuery({ queryKey: queryKeys.umeNE(neKeyword, nePage, nePageSize), queryFn: () => fetchUmeNe({ keyword: neKeyword, page: nePage, pageSize: nePageSize }), staleTime: 5000, }); const cliTargetsQuery = useQuery({ queryKey: queryKeys.cliTargets(neKeyword, nePage, nePageSize), queryFn: () => fetchCliTargets({ source: "ume", keyword: neKeyword, page: nePage, pageSize: nePageSize }), enabled: nePanelOpen, staleTime: 5000, }); const cliStatusByNeId = useMemo(() => { const map = new Map(); for (const row of cliTargetsQuery.data?.items || []) { map.set(row.id, row.connect_status); } return map; }, [cliTargetsQuery.data]); const runningTasks = (syncStatusQuery.data?.items || []).filter((x) => String(x.status || "").toLowerCase() === "running"); const runtimeTasks = syncStatusQuery.data?.runtime_tasks || []; const alarmSub: UmeAlarmSubscriptionStatus = subscriptionStatusQuery.data ?? syncStatusQuery.data?.alarm_subscription ?? { active: false }; const wsConsumer = runtimeTasks.find((x) => x.task === "alarms_current_ws_consumer"); const wsConn = subscriptionStatusQuery.data?.ws_connection; const wsState = String(wsConn?.state || ""); const wsPaused = Boolean(wsConsumer?.paused); const wsLabel = (wsPaused ? t("ume.subscription.wssPaused") : wsConnectionLabel(wsState, wsConn?.label, t)) || runtimeLastError(wsConsumer?.last_error, t) || wsConsumer?.status || t("common.empty"); const subscriptionActive = Boolean(alarmSub.active); const serverSubLost = Boolean( subscriptionStatusQuery.data?.server_subscription_lost ?? alarmSub.server_subscription_lost, ); const serverSubLostReason = String( subscriptionStatusQuery.data?.server_subscription_lost_reason ?? alarmSub.server_subscription_lost_reason ?? "", ); const currentAlarmsMode = subscriptionStatusQuery.data?.current_alarms_mode ?? alarmSub.current_alarms_mode ?? "rest"; const scheduledSyncSkipped = Boolean( subscriptionStatusQuery.data?.scheduled_sync_skipped ?? alarmSub.scheduled_sync_skipped, ); const wsPillLevel = serverSubLost || wsState === "subscription_lost" ? "warn" : wsPaused || wsState === "paused" ? "warn" : wsState === "connected" ? "up" : wsState === "connecting" || wsState === "reconnecting" || wsState === "waiting_token" ? "warn" : wsState === "no_subscription" || wsState === "disconnected" || wsState === "error" || wsState === "init" ? "down" : String(wsConsumer?.last_error || "").includes("connected") || String(wsConsumer?.last_error || "").includes("ws:connected") ? "up" : "unknown"; const wsLogs = [...(subscriptionStatusQuery.data?.ws_logs ?? alarmSub.ws_logs ?? [])].reverse(); const subPending = subscriptionEstablishMutation.isPending || subscriptionCancelMutation.isPending || subscriptionClearLocalMutation.isPending; const runtimeTaskMutation = useMutation({ mutationFn: async (vars: { task: string; action: "pause" | "resume" }) => apiPost<{ ok: boolean }>(`/v1/ume/runtime/tasks/${encodeURIComponent(vars.task)}/${vars.action}`, {}), onMutate: () => setRuntimeTaskError(""), onSuccess: async () => { await queryClient.invalidateQueries({ queryKey: queryKeys.umeSyncStatusAll }); }, onError: (err) => setRuntimeTaskError(String(err)), }); const keyAlertAddMutation = useMutation({ mutationFn: () => upsertUmeKeyAlertRule({ match_type: keyAlertMatchType, match_value: keyAlertMatchValue.trim(), label: keyAlertLabel.trim(), enabled: true, ne_types: keyAlertNeTypes, }), onMutate: () => setKeyAlertOpError(""), onSuccess: async () => { setKeyAlertMatchValue(""); setKeyAlertLabel(""); setKeyAlertNeTypes([]); showOk(t("ume.keyAlert.addOk")); await queryClient.invalidateQueries({ queryKey: queryKeys.umeKeyAlertMonitorAll }); await queryClient.invalidateQueries({ queryKey: queryKeys.integrationsStatus }); }, onError: (err) => { const msg = String(err); setKeyAlertOpError(msg); showError(msg); }, }); const keyAlertDeleteMutation = useMutation({ mutationFn: (notificationId: string) => deleteUmeKeyAlertRule(notificationId), onMutate: () => setKeyAlertOpError(""), onSuccess: async () => { showOk(t("ume.keyAlert.deleteOk")); await queryClient.invalidateQueries({ queryKey: queryKeys.umeKeyAlertMonitorAll }); await queryClient.invalidateQueries({ queryKey: queryKeys.integrationsStatus }); }, onError: (err) => { const msg = String(err); setKeyAlertOpError(msg); showError(msg); }, }); const keyAlertToggleMutation = useMutation({ mutationFn: (vars: { ruleKey: string; enabled: boolean }) => patchUmeKeyAlertRule(vars.ruleKey, { enabled: vars.enabled }), onMutate: () => setKeyAlertOpError(""), onSuccess: async () => { await queryClient.invalidateQueries({ queryKey: queryKeys.umeKeyAlertMonitorAll }); }, onError: (err) => { const msg = String(err); setKeyAlertOpError(msg); showError(msg); }, }); const keyAlertEditMutation = useMutation({ mutationFn: (vars: { ruleKey: string; ne_types: string[] }) => patchUmeKeyAlertRule(vars.ruleKey, { ne_types: vars.ne_types }), onMutate: () => setKeyAlertOpError(""), onSuccess: async () => { setKeyAlertEditRule(null); showOk(t("ume.keyAlert.editOk")); await queryClient.invalidateQueries({ queryKey: queryKeys.umeKeyAlertMonitorAll }); }, onError: (err) => { const msg = String(err); setKeyAlertOpError(msg); showError(msg); }, }); const keyAlertConfigMutation = useMutation({ mutationFn: (forwardOnClear: boolean) => updateUmeKeyAlertMonitorConfig({ forward_on_clear: forwardOnClear }), onMutate: () => setKeyAlertOpError(""), onSuccess: async () => { await queryClient.invalidateQueries({ queryKey: queryKeys.umeKeyAlertMonitorAll }); }, onError: (err) => { const msg = String(err); setKeyAlertOpError(msg); showError(msg); }, }); const syncTotal = Number(syncStatusQuery.data?.total || 0); const syncPages = pageCount(syncTotal, syncPageSize); const neTotal = Number(neQuery.data?.total || 0); const nePages = pageCount(neTotal, nePageSize); const keyAlertForwarder = keyAlertMonitorQuery.data?.forwarder; const keyAlertRules = keyAlertMonitorQuery.data?.rules || []; const keyAlertTotal = Number(keyAlertMonitorQuery.data?.total || keyAlertRules.length); const keyAlertPages = pageCount(keyAlertTotal, keyAlertPageSize); const keyAlertForwardOnClear = Boolean(keyAlertMonitorQuery.data?.config?.forward_on_clear); const oclawWsPill = !keyAlertForwarder?.enabled ? "unknown" : keyAlertForwarder.paused ? "warn" : keyAlertForwarder.connected ? "up" : "down"; const runtimeTaskLabel = (task: string) => { const key = `ume.tasks.runtimeTask.${task}`; const label = t(key); return label === key ? task : label; }; const perPage = (n: number) => t("common.perPage", { n: String(n) }); return ( <>

{t("ume.token.title")}

token:{" "} {!hasToken ? t("ume.token.disconnected") : tokenNeedsRenewal ? t("ume.token.connectedRenew") : t("ume.token.connected")} {t("ume.token.expiresIn")}:{" "} {typeof tokenStatusQuery.data?.expires_in_s === "number" ? tokenNeedsRenewal ? t("ume.token.needsRenew") : `${tokenStatusQuery.data.expires_in_s}s` : t("common.empty")} {tokenStatusQuery.data?.token_preview ? ( {t("ume.token.preview")}: {tokenStatusQuery.data.token_preview} ) : null}
{(tokenOpError || tokenRefreshMutation.error || tokenDisconnectMutation.error) && (
{t("common.opFailed")}: {tokenOpError || String(tokenRefreshMutation.error || tokenDisconnectMutation.error)}
)}

{t("ume.tasks.currentTitle")}

0 ? "unknown" : "up"}`}> {t("ume.tasks.running")}: {runningTasks.length}
{runningTasks.map((x) => ( ))} {!syncStatusQuery.isLoading && runningTasks.length === 0 && ( )}
ID domain trigger_mode status started_at error
{x.id} {x.domain} {x.trigger_mode} {x.status} {formatSystemTime(x.started_at)} {x.error_message || t("common.empty")}
{t("ume.tasks.noRunning")}

{t("ume.tasks.runtimeTitle")}

{runtimeTaskError ? (
{t("ume.tasks.runtimeOpFailed")}: {runtimeTaskError}
) : null}
{runtimeTasks.map((x) => ( ))} {!syncStatusQuery.isLoading && runtimeTasks.length === 0 && ( )}
task interval status last_run_at {t("ume.tasks.lastErrorCol")} actions
{runtimeTaskLabel(x.task)} {runtimeIntervalLabel(x.interval_label)} {x.status} {x.last_run_at ? formatSystemTime(x.last_run_at) : t("common.empty")} {runtimeLastError(x.last_error, t) || t("common.empty")} {Boolean(x.paused) ? ( ) : ( )}
{t("ume.tasks.noRuntime")}

{t("ume.subscription.title")}

{t("ume.subscription.sub")}: {subscriptionActive ? t("ume.subscription.subActive") : t("ume.subscription.subInactive")} {subscriptionActive && alarmSub.subscription_id ? ( id: {String(alarmSub.subscription_id).slice(0, 12)}… ) : null} {subscriptionActive || wsConsumer ? ( WSS: {wsLabel} ) : null}
{scheduledSyncSkipped && !serverSubLost ? (
{t("ume.subscription.wssModeBanner", { mode: currentAlarmsMode })}
) : null} {serverSubLost ? (
{t("ume.subscription.serverLostBanner")} {serverSubLostReason ? (
{serverSubLostReason.slice(0, 280)}
) : null}
) : null}
{serverSubLost && subscriptionActive ? ( ) : null}
{subscriptionOpError ? (
{t("ume.subscription.opFailed")}: {subscriptionOpError}
) : null}
{t("ume.subscription.wsLogs")} {wsConsumer?.last_run_at ? t("ume.subscription.wsActivity", { time: formatSystemTime(String(wsConsumer.last_run_at)) }) : t("ume.subscription.wsAutoRefresh")}
{wsLogs.length === 0 ? (
{t("ume.subscription.wsLogsEmpty")}
) : ( wsLogs.map((line, idx) => { const lvl = String(line.level || "info").toLowerCase(); const cls = lvl === "error" ? "ws-log-line--error" : lvl === "warning" ? "ws-log-line--warning" : "ws-log-line--info"; return (
{formatSystemTime(line.ts)} [{lvl}] {line.message} {line.subscription_id ? ( · {String(line.subscription_id).slice(0, 8)}… ) : null}
); }) )}

{t("ume.cli.title")}

{cliPanelOpen ? : null}

{t("ume.keyAlert.title")}

{keyAlertPanelOpen ? ( <>
{t("ume.keyAlert.ws")}:{" "} {!keyAlertForwarder?.enabled ? t("ume.keyAlert.wsDisabled") : keyAlertForwarder.paused ? t("ume.keyAlert.wsPaused") : keyAlertForwarder.connected ? t("ume.keyAlert.wsConnected") : t("ume.keyAlert.wsDisconnected")} {keyAlertForwarder?.enabled ? ( <> {t("ume.keyAlert.publishedOk")}: {Number(keyAlertForwarder.published_ok || 0)} {t("ume.keyAlert.publishedFail")}: {Number(keyAlertForwarder.published_fail || 0)} {t("ume.keyAlert.queue")}: {Number(keyAlertForwarder.queue_size || 0)} ) : null}
setKeyAlertMatchValue(e.target.value)} list="ume-key-alert-match-options" /> setKeyAlertLabel(e.target.value)} /> {keyAlertMatchType === "keyword" ? keyAlertKeywordHints.map((kw) => ))}
{t("ume.keyAlert.neTypesLabel")}
{keyAlertNeTypesQuery.isLoading ? ( {t("common.refreshing")} ) : (keyAlertNeTypesQuery.data?.items || []).length === 0 ? ( {t("ume.keyAlert.neTypesEmpty")} ) : (
{(keyAlertNeTypesQuery.data?.items || []).map((item) => ( ))}
)}
{t("ume.keyAlert.neTypesHint")}
{keyAlertOpError ? (
{t("common.opFailed")}: {keyAlertOpError}
) : null}
{ setKeyAlertFilterKeyword(e.target.value); setKeyAlertPage(1); }} />
{keyAlertRules.map((rule) => ( ))} {!keyAlertMonitorQuery.isLoading && keyAlertRules.length === 0 ? ( ) : null}
{t("ume.keyAlert.colMonitor")} {t("ume.keyAlert.colType")} {t("ume.keyAlert.colMatch")} {t("ume.keyAlert.colLabel")} {t("ume.keyAlert.colNeTypes")} {t("ume.keyAlert.colPublished")} {t("ume.keyAlert.colAttempts")} {t("ume.keyAlert.colLast")} {t("ume.keyAlert.colActions")}
{rule.match_type === "keyword" ? t("ume.keyAlert.matchKeyword") : t("ume.keyAlert.matchNotificationId")} {rule.match_value || rule.notification_id} {rule.label || t("common.empty")} {rule.ne_types?.length ? rule.ne_types.join(", ") : t("ume.keyAlert.neTypesAll")} {Number(rule.forward_stats?.published_ok || 0)} {Number(rule.forward_stats?.attempts || 0)} {rule.forward_stats?.last_forwarded_at ? formatSystemTime(rule.forward_stats.last_forwarded_at) : t("common.empty")}
{t("ume.keyAlert.emptyRules")}
{t("common.pagerMeta", { total: keyAlertTotal, page: keyAlertPage, pages: keyAlertPages })}
) : null}

{t("ume.syncStatus.title")}

{syncStatusPanelOpen ? (
{(syncStatusQuery.data?.items || []).map((x) => ( ))} {!syncStatusQuery.isLoading && (syncStatusQuery.data?.items || []).length === 0 && ( )}
ID domain status pulled inserted updated deleted started_at ended_at error
{x.id} {x.domain} {x.status} {x.pulled_count} {x.inserted_count} {x.updated_count} {Number(x.deleted ?? 0)} {formatSystemTime(x.started_at)} {x.ended_at ? formatSystemTime(x.ended_at) : t("common.empty")} {x.error_message || t("common.empty")}
{t("ume.syncStatus.empty")}
{t("common.pagerMeta", { total: syncTotal, page: syncPage, pages: syncPages })}
) : null}

{t("ume.ne.title")}

{nePanelOpen ? (
setNeKeyword(e.target.value)} />
{(neQuery.data?.items || []).map((x) => ( {expandedNeId === x.ne_id ? ( ) : null} ))}
ne_id user_label ip type device_level host_name {t("ume.ne.cliConnect")} hw_ver last_seen
{x.user_label} {x.ip_address} {x.ne_type} {x.device_level || t("common.empty")} {x.host_name || t("common.empty")} {cliStatusByNeId.get(x.ne_id) || "unknown"} {x.hardware_version || t("common.empty")} {x.last_seen_at ? formatSystemTime(x.last_seen_at) : t("common.empty")}
consistent_state: {x.consistent_state || t("common.empty")}
admin_status: {x.admin_status || t("common.empty")}
connection_status: {x.connection_status || t("common.empty")}
maintain_status: {x.maintain_status || t("common.empty")}
address_type: {x.address_type || t("common.empty")}
location: {x.location || t("common.empty")}
loopback: {x.loopback || t("common.empty")}
net_mask: {x.net_mask || t("common.empty")}
mac: {x.mac || t("common.empty")}
interface_version: {x.interface_version || t("common.empty")}
create_time: {x.create_time || t("common.empty")}
creator: {x.creator || t("common.empty")}
{t("common.pagerMeta", { total: neTotal, page: nePage, pages: nePages })}
) : null}

{t("ume.alarms.title")}

{t("ume.alarms.movedHint")}{" "} { e.preventDefault(); openOrFocusModule({ moduleId: "network", path: "/network/alarms" }); }}> {t("network.nav.alarms")}

{keyAlertEditRule ? (
setKeyAlertEditRule(null)}>
e.stopPropagation()}>

{t("ume.keyAlert.editTitle")}

{keyAlertEditRule.match_type === "keyword" ? t("ume.keyAlert.matchKeyword") : t("ume.keyAlert.matchNotificationId")} : {keyAlertEditRule.match_value || keyAlertEditRule.notification_id} {keyAlertEditRule.label ? ` · ${keyAlertEditRule.label}` : ""}

{t("ume.keyAlert.neTypesLabel")}
{keyAlertNeTypesQuery.isLoading ? ( {t("common.refreshing")} ) : (keyAlertNeTypesQuery.data?.items || []).length === 0 ? ( {t("ume.keyAlert.neTypesEmpty")} ) : (
{(keyAlertNeTypesQuery.data?.items || []).map((item) => ( ))}
)}
{t("ume.keyAlert.neTypesHint")}
) : null} ); }