Add topology classify inventory, fabric lifecycle, and broader collect targets.

Treat Fabric as an inventory sheet for role/region tagging and slices; detach fabric links on managed/UME delete instead of cascading map deletes. Extend collection to all managed and UME NEs, show NE source in management, and refine canvas vendor icon tones.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
oliver 2026-08-02 11:09:58 +08:00
parent 90dff56e48
commit a5a3a4f156
30 changed files with 5986 additions and 495 deletions

View file

@ -52,6 +52,7 @@ const en = {
devices: "Device list",
topology: "Topology",
lldpLinks: "LLDP links",
topoClassify: "Classify & slices",
alarms: "Alarms",
configs: "Configurations",
webcrt: "WebCRT",
@ -473,8 +474,8 @@ const en = {
selectedCount: "{{count}} selected",
clearSelected: "Clear selection",
remove: "Remove",
pickTitle: "Eligible NEs (connectivity passed)",
pickHint: "Only NEs with connect_status=pass. Run connectivity test in NE Management first.",
pickTitle: "Eligible NEs",
pickHint: "All managed and UME inventory NEs are selectable (any connect status). UME uses CLI connect profile credentials.",
pickEmpty: "No matching NEs.",
filterKeyword: "Filter",
filterKeywordPh: "Name / IP / vendor / device type",
@ -488,9 +489,9 @@ const en = {
meta: "{{ne}} NE(s) selected · {{cmd}} command(s)",
},
eligible: {
title: "Eligible NEs (connectivity passed)",
hint: "Only NEs with connect_status=pass. Run connectivity test in NE Management first.",
empty: "No NEs with passed connectivity test.",
title: "Eligible NEs",
hint: "All managed and UME inventory NEs are selectable (any connect status).",
empty: "No NEs.",
},
form: {
title: "Collection setup",
@ -591,6 +592,7 @@ const en = {
name: "Name",
vendor: "Vendor",
deviceType: "Device type",
source: "Source",
ip: "Management IP",
port: "Port",
protocol: "Protocol",
@ -602,6 +604,12 @@ const en = {
testedAt: "Tested at",
actions: "Actions",
},
source: {
manual: "Manual",
ume_sync: "UME sync",
webcrt: "WebCRT",
lldp: "LLDP placeholder",
},
connect: {
run: "Connectivity test",
running: "Testing…",
@ -1185,6 +1193,43 @@ const en = {
topology: {
title: "Topology",
maps: "Maps",
tree: "Topology tree",
treeLoading: "Loading tree…",
treeHint: "Regions hold a physical map plus optional custom maps; open a map to edit the canvas.",
rootName: "Regions",
selectRegion: "Select a region",
openMap: "Open map",
kindPhysical: "Physical",
kindCustom: "Custom",
regionNodeHint: "{{count}} map(s)",
layerNodeHint: "{{count}} NE(s)",
layerNodeEmpty: "Click to create & open",
rootCanvasHint: "Pick a region from the left tree.",
regionCanvasHint: "Open a map to edit devices, or create a custom map.",
regionBrowseHint: "Region folder: physical + custom maps. Click to open.",
browserTitle: "Topology folder",
browserRegionSub: "{{count}} map(s)",
browserEmptyMaps: "No maps in this region yet.",
addNe: "Add NE",
backUp: "Back to region",
newRegion: "New region",
newRegionName: "New region",
newRegionPrompt: "Region name",
regionCreated: "Region created",
regionDeleted: "Region deleted",
deleteRegion: "Delete region",
deleteRegionConfirm: "Delete region \"{{name}}\"? Its physical and custom maps will also be deleted.",
renameRegion: "Rename region",
renameRegionPrompt: "Region name",
regionRenamed: "Region renamed",
collapseRegion: "Collapse region",
expandRegion: "Expand region",
newCustom: "Custom map",
newCustomName: "Custom topology",
newCustomPrompt: "Custom map name",
folderHint: "Regions group maps. Each region gets a physical map; add custom maps as needed.",
folderHintShort: "Region folder",
outsidePeers: "{{count}} outside peer(s) linked but not on this map",
newMap: "New",
newMapName: "New topology",
rename: "Rename",
@ -1193,7 +1238,7 @@ const en = {
renamed: "Topology map renamed",
deleteMap: "Delete map",
deleteMapConfirm: "Delete map \"{{name}}\"? Nodes and edges will be removed.",
emptyMaps: "No maps yet. Create one to start.",
emptyMaps: "No regions yet. Create a region first.",
palette: "NE library",
paletteHint: "Click or drag onto the canvas",
filterPh: "Type to filter: name / IP / vendor",
@ -1214,7 +1259,7 @@ const en = {
sourcePort: "Local port",
targetPort: "Remote port",
canvasHint:
"Add NEs from the palette, drag then save positions; LLDP discovery writes the global fabric. Blue dashed=discovered, red=stale.",
"Left tree lists regions with a physical map and optional custom maps. Open a map to edit devices; use Add NE and save positions.",
selected: "Selected",
selectedEdge: "Selected edge",
selectedCount: "{{count}} selected",
@ -1337,6 +1382,66 @@ const en = {
staleRemoved: "Removed {{count}} missing edge(s)",
connectHint: "Connect mode: click source node, then target (Esc or Select to exit)",
},
topoClassify: {
title: "Classify & slices",
openTopo: "Topology",
inventory: "NE inventory",
keywordPh: "Filter by name/IP",
filterRoleAll: "All roles",
filterRegionAll: "All regions",
filterUnmatchedOff: "No unmatched filter",
kindAny: "Role or region empty",
kindRole: "Role empty",
kindRegion: "Region empty",
filterLinkAll: "All link states",
filterLinkLinked: "Linked inventory",
filterLinkOrphaned: "Detached",
colLink: "Link",
linkManaged: "Managed",
linkUme: "UME",
linkBoth: "Managed+UME",
linkOrphaned: "Detached",
regexTitle: "Regex find",
patternPh: "Regex, e.g. ^CORE- or -BJ-",
fieldName: "Name",
fieldNameIp: "Name+IP",
findMatches: "Find matches",
matchOk: "Matched {{count}}; selected",
matchHint: "{{count}} matched",
assignRole: "Role only",
assignRegion: "Region only",
assignBoth: "Role + region",
clearRegion: "Clear region",
confirmAssign: "Confirm assign",
bulkConfirm: "Write tags to {{count}} selected/matched NE(s)?",
bulkOk: "Updated {{count}}",
selectedCount: "{{count}} selected",
selectPage: "Select page",
colNe: "NE",
colRole: "Role",
colRegion: "Region",
colActions: "Actions",
edit: "Edit",
save: "Save",
cancel: "Cancel",
rowSaved: "Saved",
loading: "Loading…",
empty: "No NEs.",
showSlices: "Show slice maps",
hideSlices: "Hide slice maps",
slices: "Slice maps",
pickRegion: "Pick region",
tplCore: "Core only",
tplCoreAgg: "Core + neighbor Agg",
tplAggAcc: "Agg + neighbor Access",
seedPhysical: "Also place Cores on physical overview",
slicePreview: "Preview slices",
sliceApply: "Generate maps",
sliceConfirm: "Create custom maps and freeze placements?",
sliceOk: "Created {{count}} slice map(s)",
sliceStats: "{{maps}} map(s) planned, {{overlap}} NE(s) on multiple maps",
nodeCount: "{{count}} NE(s)",
},
};
export default en;