import { Button, Input } from "@heroui/react"; import { useState } from "react"; import { useQuery } from "@tanstack/react-query"; import { ListPager } from "../../components/ListPager"; import { FieldSelect } from "../../components/ui/FieldSelect"; import { queryKeys } from "../../constants/queryKeys"; import { useDebouncedValue } from "../../hooks/useDebouncedValue"; import { useToast } from "../../hooks/useToast"; import { useI18n } from "../../i18n"; import { fetchCliTargets, formatErr } from "../../services/api"; import type { CliTargetItem } from "../../types"; import { downloadCsv, fetchAllPages } from "../../utils/csvExport"; import { pageCount } from "../../utils/display"; import { openNewModuleWindow } from "../../utils/moduleWindows"; import { connectChipColor, NmStatusChip, sourceChipColor } from "./nmChips"; function openWebcrt(row: CliTargetItem) { const path = row.source === "ume" ? `/webcrt?ne_id=${encodeURIComponent(row.id)}&source=ume` : `/webcrt?ne_id=${encodeURIComponent(row.id)}`; openNewModuleWindow({ moduleId: "webcrt", path }); } /** Inventory of managed + UME NEs for Network Management. */ export function NetworkDevicesPage() { const { t } = useI18n(); const { showOk, showError } = useToast(); const [keyword, setKeyword] = useState(""); const [source, setSource] = useState<"all" | "managed" | "ume">("all"); const [page, setPage] = useState(1); const [pageSize, setPageSize] = useState(10); const [exporting, setExporting] = useState(false); const debouncedKeyword = useDebouncedValue(keyword, 300); const listQuery = useQuery({ queryKey: queryKeys.cliTargets(`${source}:${debouncedKeyword}`, page, pageSize), queryFn: () => fetchCliTargets({ source, keyword: debouncedKeyword, page, pageSize }), staleTime: 5000, }); const items = listQuery.data?.items ?? []; const total = Number(listQuery.data?.total || 0); const pages = pageCount(total, pageSize); const hasFilters = Boolean(keyword.trim() || source !== "all"); const exportCsv = async () => { setExporting(true); try { const rows = await fetchAllPages({ pageSize: 200, maxRows: 2000, fetchPage: (p, ps) => fetchCliTargets({ source, keyword: debouncedKeyword, page: p, pageSize: ps }), }); downloadCsv(`${t("networkDevices.exportName")}-${new Date().toISOString().slice(0, 10)}.csv`, rows, [ { key: "source", header: t("networkDevices.col.source") }, { key: "name", header: t("networkDevices.col.name"), value: (r) => r.name || r.id }, { key: "ip_address", header: "IP" }, { key: "vendor", header: t("networkDevices.col.vendor") }, { key: "device_type", header: t("networkDevices.col.deviceType"), value: (r) => r.device_type || r.ne_type || "", }, { key: "connect_status", header: t("networkDevices.col.connect") }, { key: "id", header: "ID" }, ]); if (rows.length < total) { showOk(t("common.exportTruncated", { count: String(rows.length), total: String(total) })); } else { showOk(t("common.exportOk", { count: String(rows.length) })); } } catch (err) { showError(t("common.exportFailed") + ": " + formatErr(err)); } finally { setExporting(false); } }; return (

{t("networkDevices.title")}

{ setKeyword(e.target.value); setPage(1); }} /> { setSource(e.target.value as "all" | "managed" | "ume"); setPage(1); }} >
{listQuery.isLoading ?

{t("common.refreshing")}

: null} {listQuery.isError ?

{t("common.opFailed")}

: null} {!items.length && !listQuery.isLoading ? (

{t("networkDevices.empty")}

) : (
{items.map((row) => ( ))}
{t("networkDevices.col.source")} {t("networkDevices.col.name")} IP {t("networkDevices.col.vendor")} {t("networkDevices.col.deviceType")} {t("networkDevices.col.connect")} {t("networkDevices.col.actions")}
{row.source} {row.name || row.id} {row.ip_address || "—"} {row.vendor || "—"} {row.device_type || row.ne_type || "—"} {row.connect_status || "—"}
)} { setPageSize(size); setPage(1); }} disabled={listQuery.isLoading} />
); }