mirror of
https://github.com/hansjone/netx.git
synced 2026-10-16 10:13:16 +08:00
Refactor web UI: feature-first structure, tokenized styles, modern blue theme.
Structure
- pages/ -> features/<domain>/{Page, components, hooks, lib}; 95 files moved,
333 imports rewritten, verified with tsc.
- services/api.ts -> services/api/<domain>.ts (250 exports preserved),
types.ts -> types/<domain>.ts, i18n zh/en -> locales/<lang>/<namespace>.ts
(2696 messages deep-equal before/after).
- ESLint rule: shared layers must not import features/.
Styles
- index.css (16k lines) split losslessly into styles/{base,layout,components,
pages,legacy,theme}; compiled CSS was byte-identical before tokenizing.
- ~930 hard-coded colors replaced by --nx-* tokens (theme/tokens.css); WebCRT
off-palette colors unified; fixed dark-on-dark text introduced by mapping.
- theme/theme.css: modern blue design language (rounded shapes, gradients,
unified buttons/fields/tables/modals), form-grid alignment fix, flat nav list
without tree indent, soft selected state instead of left accent bar.
Docs: WEB.md documents code structure and style rules.
Not touched: the large Biz*/Webcrt/Topology page components (to be split later).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
3b45d6abe3
commit
0d894efe5e
196 changed files with 26947 additions and 28091 deletions
344
web/src/i18n/locales/en/topology.ts
Normal file
344
web/src/i18n/locales/en/topology.ts
Normal file
|
|
@ -0,0 +1,344 @@
|
|||
const topology = {
|
||||
title: "Topology",
|
||||
maps: "Maps",
|
||||
tree: "Topology tree",
|
||||
treeLoading: "Loading tree…",
|
||||
treeLoadFailed: "Failed to load topology tree",
|
||||
treeRetry: "Retry",
|
||||
graphLoading: "Loading topology…",
|
||||
graphLoadFailed: "Failed to load topology",
|
||||
graphRefreshing: "Refreshing…",
|
||||
canvasEmpty: "No NEs on this map yet",
|
||||
canvasEmptyHint: "Use Add NE, or pick a region that already has devices.",
|
||||
treeHint: "Top level is a Root (nav only); its unique Root Map is the canvas. Open the root map or a sub-region to edit devices.",
|
||||
treeSearch: "Search NEs across maps",
|
||||
treeSearchPh: "Name / IP",
|
||||
treeSearchEmpty: "No matching NEs",
|
||||
treeSearchNoViews: "Not on any map",
|
||||
treeSearchNotOnMap: "This NE is not placed on any topology map yet",
|
||||
locateNotOnCanvas:
|
||||
"This NE is missing from the world-map sample and has no world coordinates. Open a region map instead.",
|
||||
treeSearchViewCount: "{{count}} map(s)",
|
||||
treeSearchTruncated: "Showing first 30 of {{total}}",
|
||||
rootName: "Roots",
|
||||
selectRegion: "Select a root or region",
|
||||
openMap: "Open map",
|
||||
openRegion: "Open",
|
||||
kindPhysical: "Physical",
|
||||
kindCustom: "Custom",
|
||||
layerNodeHint: "{{count}} NE(s)",
|
||||
layerNodeEmpty: "Click to create & open",
|
||||
rootCanvasHint: "Pick a root from the left tree.",
|
||||
regionCanvasHint: "Open the root map to edit devices; create sub-regions on that canvas.",
|
||||
regionBrowseHint: "Root folder: unique root map below. Click to open.",
|
||||
browserTitle: "Topology folder",
|
||||
browserRegionSub: "{{count}} map(s)",
|
||||
browserRegionsSub: "{{count}} item(s)",
|
||||
browserEmptyMaps: "No root map under this root yet.",
|
||||
addNe: "Add NE",
|
||||
more: "More",
|
||||
backUp: "Back",
|
||||
newRegion: "New root",
|
||||
newRegionName: "New root",
|
||||
newRegionPrompt: "Root name",
|
||||
newSubRegion: "New sub-region",
|
||||
newSubRegionName: "New sub-region",
|
||||
newSubRegionPrompt: "Sub-region name",
|
||||
subRegionNotOnFlat: "The world map has no regions. Create sub-regions on World or a lower-level canvas.",
|
||||
worldMapNoDirectNes: "Cannot add NEs on the world map — add them on a sub-region canvas.",
|
||||
worldMapName: "World map",
|
||||
worldMapOffline: "World map is temporarily offline",
|
||||
rootMapName: "Root map",
|
||||
worldHud: "World {{total}} · close-up {{cached}} · z{{zoom}} · {{lod}}",
|
||||
worldEmptyCoords: "World map has no coordinates yet",
|
||||
worldEmptyCoordsHint:
|
||||
"Dock has {{dock}} NEs, but Fabric / world coords are empty. Apply without pulling UME.",
|
||||
worldApply: "Apply to world map",
|
||||
worldApplying: "Applying…",
|
||||
worldApplyOk: "Applied to world map",
|
||||
subRegionNeedParent: "Open a root map or region canvas first, then create a sub-region.",
|
||||
regionCreated: "Created",
|
||||
regionDeleted: "Deleted",
|
||||
deleteRegion: "Delete",
|
||||
deleteRegionConfirm: "Delete \"{{name}}\"? Its maps will also be deleted.",
|
||||
deleteUmeWorldConfirm:
|
||||
"Delete \"{{name}}\"? This cascades all UME regions and maps under it. A later UME topology apply may recreate it.",
|
||||
renameRegion: "Rename",
|
||||
renameRegionPrompt: "Name",
|
||||
regionRenamed: "Renamed",
|
||||
collapseRegion: "Collapse",
|
||||
expandRegion: "Expand",
|
||||
newCustom: "Custom map",
|
||||
newCustomName: "Custom topology",
|
||||
newCustomPrompt: "Custom map name",
|
||||
folderHint: "Creating a root auto-creates its unique root map. Add sub-regions on that canvas.",
|
||||
folderHintShort: "Root folder",
|
||||
outsidePeers: "{{count}} outside peer(s) linked but not on this map",
|
||||
outsidePeersView: "Off-map NEs {{count}}",
|
||||
outsidePeersTitle: "Outside peers",
|
||||
outsidePeersHint: "Linked to this map but not placed. Select and add only what you need.",
|
||||
outsidePeersVia: "via {{name}}",
|
||||
outsidePeersFilterPh: "Filter: name / IP / via",
|
||||
outsidePeersEmpty: "No matching outside peers",
|
||||
projectNeighbors: "Project neighbors",
|
||||
projectedNeighbors: "Projected {{count}} neighbor(s) onto the map",
|
||||
localBrowserOnly: "this browser only",
|
||||
deleteEdgeConfirm:
|
||||
"Remove selected link(s) from the canvas? They are deleted from Fabric only when you Save. LLDP may recreate them on the next collect.",
|
||||
edgeDeleted: "Queued {{count}} link delete(s) — Save to apply",
|
||||
discoverCancelled: "Discovery cancelled",
|
||||
truncatedMembership: "Membership cap reached; some neighbors were not placed. Use classify or a new map.",
|
||||
truncatedFrozen: "This map membership is frozen; neighbors cannot be projected. Unfreeze via classify workflow or create a new map.",
|
||||
truncatedNodes: "Too many view nodes; display truncated. Narrow membership or create another map.",
|
||||
truncatedEdges: "Too many edges; display truncated. Filter status or create another map.",
|
||||
truncatedGeneric: "Graph data truncated. Narrow scope or create another map.",
|
||||
deleteSelectionConfirm:
|
||||
"Remove {{nodes}} NE(s) from this map and {{edges}} link(s)? Link deletes apply on Save; NE remove from map applies on Save.",
|
||||
selectionDeleted: "Queued: remove {{nodes}} NE(s), delete {{edges}} link(s) — Save to apply",
|
||||
newMap: "New",
|
||||
newMapName: "New topology",
|
||||
rename: "Rename",
|
||||
renamePrompt: "Topology map name",
|
||||
renameHint: "Double-click to rename",
|
||||
renamed: "Topology map renamed",
|
||||
deleteMap: "Delete map",
|
||||
deleteMapConfirm: "Delete map \"{{name}}\"? Nodes and edges will be removed.",
|
||||
emptyMaps: "No roots yet. Create a root first.",
|
||||
palette: "NE library",
|
||||
paletteHint: "Select multiple to add in batch, or drag one onto the canvas",
|
||||
paletteDragHint: "Drag onto canvas to add",
|
||||
selectAllVisible: "Select all visible",
|
||||
addSelected: "Add selected ({{count}})",
|
||||
addSelectedDone: "Added {{count}} NE(s)",
|
||||
addingNe: "Adding…",
|
||||
filterPh: "Type to filter: name / IP / vendor",
|
||||
save: "Save",
|
||||
saveDirty: "Save *",
|
||||
unsavedConfirm: "You have unsaved changes. Discard and switch maps?",
|
||||
saving: "Saving…",
|
||||
saved: "Topology saved",
|
||||
saveFailed: "Save failed: {{detail}}",
|
||||
readOnlyBanner: "Read-only (ne:write scope required to edit)",
|
||||
readOnlyHint: "Read-only — no write permission",
|
||||
discoverTimeout: "Discovery timed out; check LLDP tasks for progress",
|
||||
policySyncFailed: "Failed to sync LLDP policy; local toggle still applies to canvas discovery",
|
||||
discover: "Discover links",
|
||||
discovering: "Discovering…",
|
||||
discoverOne: "Discover links",
|
||||
discovered: "Discovery done: +{{added}} updated {{updated}} missing {{stale}}",
|
||||
discoverFail: "Discovery failed: {{detail}}",
|
||||
discoverOneNeedNe: "This node is not linked to a scannable NE",
|
||||
selectMap: "Select or create a topology map",
|
||||
renameNode: "Rename",
|
||||
renameNodePrompt: "Node display name",
|
||||
sourcePort: "Local port",
|
||||
targetPort: "Remote port",
|
||||
endpointA: "Endpoint A",
|
||||
endpointB: "Endpoint B",
|
||||
port: "port",
|
||||
expandPhysicalLinks: "Expand physical links",
|
||||
scaleBundleWidth: "Thicken bundles by link count",
|
||||
linkMembers: "Physical members ({{count}})",
|
||||
canvasHint:
|
||||
"Left tree lists regions; add maps yourself, then open a map to edit devices with Add NE and save positions.",
|
||||
selected: "Selected",
|
||||
selectedEdge: "Selected edge",
|
||||
selectedCount: "{{count}} selected",
|
||||
toolModes: "Edit modes",
|
||||
toolSelect: "Select",
|
||||
toolPan: "Pan",
|
||||
toolDrag: "Drag",
|
||||
toolConnect: "Connect",
|
||||
layout: "Layout",
|
||||
layoutHierarchicalTb: "Hierarchical · top-bottom",
|
||||
layoutHierarchicalLr: "Hierarchical · left-right",
|
||||
layoutForce: "Force-directed",
|
||||
layoutGrid: "Grid",
|
||||
layoutRadial: "Radial",
|
||||
layoutSelected: "Selected only (hierarchical)",
|
||||
layoutNeedSelection: "Select nodes to lay out first",
|
||||
align: "Align",
|
||||
alignLeft: "Align left",
|
||||
alignRight: "Align right",
|
||||
alignTop: "Align top",
|
||||
alignBottom: "Align bottom",
|
||||
alignHCenter: "Align center X",
|
||||
alignVCenter: "Align center Y",
|
||||
alignHDistribute: "Distribute horizontally",
|
||||
alignVDistribute: "Distribute vertically",
|
||||
alignNeedSelection: "Select at least two nodes",
|
||||
snapGrid: "Snap to grid",
|
||||
autoLayoutDiscover: "Auto-layout after discover",
|
||||
discoverAutoAddUnmatched: "Auto-add unmatched NEs as placeholders on discover",
|
||||
discoverProjectNeighbors:
|
||||
"After discover, project neighbors of scanned NEs onto the canvas (Save to keep permanently)",
|
||||
undo: "Undo",
|
||||
redo: "Redo",
|
||||
discoverSelected: "Discover links ({{count}})",
|
||||
removeSelected: "Remove selected ({{count}})",
|
||||
openWebcrt: "Open terminal",
|
||||
openNe: "NE details",
|
||||
openAlarms: "View alarms",
|
||||
noAlarmLink: "Cannot build an alarm filter for this node",
|
||||
removeNode: "Remove from canvas",
|
||||
deletePlaceholder: "Delete placeholder",
|
||||
deletePlaceholderConfirm:
|
||||
"Permanently delete this placeholder NE (inventory + Fabric links)? This cannot be undone with canvas Undo.",
|
||||
deletePlaceholderDone: "Placeholder deleted",
|
||||
removeEdge: "Delete edge",
|
||||
nodeMenu: "Node",
|
||||
paneMenu: "Canvas",
|
||||
edgeMenu: "Edge",
|
||||
createNe: "New NE",
|
||||
createNeModeHint:
|
||||
"Create a full managed NE, or a topology placeholder (credentials can be filled later).",
|
||||
createNeManaged: "Managed NE",
|
||||
createNeManagedHint: "Same full form as NE management; placed on the canvas after create.",
|
||||
createNePlaceholder: "Placeholder NE",
|
||||
createNePlaceholderHint: "Name/IP only; topology placeholder for sketching first.",
|
||||
createNeTitle: "New topology placeholder NE",
|
||||
createNeHint:
|
||||
"Source is topology placeholder. Complete login via WebCRT, or promote in NE management.",
|
||||
createNeName: "Name",
|
||||
createNeNamePh: "e.g. SW-CORE-01",
|
||||
createNeNameRequired: "NE name is required",
|
||||
createNeIp: "IP (optional)",
|
||||
createNeIpPh: "Can fill later during setup",
|
||||
createNeDone: "Created placeholder {{name}}",
|
||||
createManagedNeDone: "Created and placed {{name}}",
|
||||
createManagedNePlaceFailed:
|
||||
"{{name}} was created in inventory, but placing on the map failed: {{error}}. Add it again from NE management or the sidebar.",
|
||||
createManagedNePosFailed:
|
||||
"{{name}} is on the map, but could not move to the click position (kept default layout coords)",
|
||||
createNeBusy: "Creating…",
|
||||
connectTest: "Connectivity test",
|
||||
connectTestSelected: "Connectivity test ({{count}})",
|
||||
connectTestNeedManaged: "Node is not linked to a managed NE; cannot run connectivity test",
|
||||
connectTestSkipped: "skipped {{count}} without managed link",
|
||||
selectionMenu: "Selection",
|
||||
edgeStyle: "Edge style",
|
||||
edgeColor: "Color",
|
||||
edgeLineStyle: "Line",
|
||||
edgeLineSolid: "Solid",
|
||||
edgeLineDashed: "Dashed",
|
||||
edgeLineDotted: "Dotted",
|
||||
edgeWidth: "Width",
|
||||
edgeStyleReset: "Reset style",
|
||||
edgeDefaults: "Default edge styles",
|
||||
edgeDefaultsReset: "Factory reset",
|
||||
noNeLink: "Not linked to a managed NE",
|
||||
completeNeFirst:
|
||||
"Login details are incomplete (vendor, hop/proxy, etc. belong in NE inventory). Complete the NE first, then open the terminal.",
|
||||
edgeManual: "Manual",
|
||||
edgeUme: "UME",
|
||||
edgeDiscovered: "LLDP",
|
||||
edgeStale: "Missing",
|
||||
fit: "Fit view",
|
||||
export: "Export",
|
||||
exportSvg: "SVG vector",
|
||||
exportXml: "XML data",
|
||||
exporting: "Exporting…",
|
||||
exportEmpty: "Nothing on the canvas to export",
|
||||
exportedSvg: "SVG exported",
|
||||
exportedXml: "XML exported",
|
||||
exportFailed: "Export failed: {{detail}}",
|
||||
liveSync: "Live sync",
|
||||
liveSyncOn: "Syncing…",
|
||||
liveSyncHint: "Poll the tree about every 5s and the open map every 3s (watch MCP create/draw). Off by default",
|
||||
fullscreen: "Fullscreen",
|
||||
exitFullscreen: "Exit fullscreen",
|
||||
display: "Display",
|
||||
canvasBg: "Canvas background",
|
||||
canvasBgColor: "Background color",
|
||||
canvasBgReset: "Reset default",
|
||||
textColors: "Text colors",
|
||||
textColorsReset: "Reset default",
|
||||
labelColor: "NE name",
|
||||
edgeLabelColor: "Link numbers",
|
||||
vendorColors: "Vendor icon colors",
|
||||
vendorColorsReset: "Reset default",
|
||||
vendorTone: {
|
||||
cisco: "Cisco",
|
||||
huawei: "Huawei",
|
||||
zte: "ZTE",
|
||||
juniper: "Juniper",
|
||||
nokia: "Nokia",
|
||||
ericsson: "Ericsson",
|
||||
h3c: "H3C",
|
||||
ruijie: "Ruijie",
|
||||
mikrotik: "MikroTik",
|
||||
gray: "Unknown / unmanaged",
|
||||
},
|
||||
hideIp: "Hide IP",
|
||||
hideVendor: "Hide vendor",
|
||||
showPlaceholderBadge: "Show placeholder badge (TOPO/LLDP)",
|
||||
showConnectStatus: "Show connect-status dots",
|
||||
showAlarmOverlay: "Show alarm overlay",
|
||||
showLevelColors: "Color by classify level",
|
||||
levelUnmatched: "Unclassified",
|
||||
level: {
|
||||
external: "External",
|
||||
core: "Core",
|
||||
aggregation: "Aggregation",
|
||||
access: "Access",
|
||||
edge: "Edge",
|
||||
},
|
||||
hidePorts: "Hide ports",
|
||||
edgeFlow: "Edge flow",
|
||||
collapseSidebar: "Collapse sidebar",
|
||||
expandSidebar: "Expand sidebar",
|
||||
resizeSidebar: "Drag to resize sidebar",
|
||||
hideAdded: "Hide added",
|
||||
paletteEmpty: "No matching NEs.",
|
||||
paletteHiddenAll: "Added NEs are hidden; uncheck to show them again.",
|
||||
paletteSource: "NE source",
|
||||
paletteManaged: "Managed",
|
||||
paletteUme: "UME",
|
||||
paletteLoading: "Loading…",
|
||||
discoverReport: "Discovery progress",
|
||||
discoverClose: "Close",
|
||||
discoverCancel: "Cancel discovery",
|
||||
discoverProgress: "Scanning {{count}} managed NE(s) on the map (serial LLDP; please wait)…",
|
||||
discoverProgressLive: "Scanning {{index}}/{{total}}: {{name}}",
|
||||
discoverSummary: "Scanned {{scanned}} · added {{added}} · updated {{updated}} · missing {{stale}} · failed {{failed}}",
|
||||
discoverNeOk: "neighbors {{neighbors}} · added {{added}} · updated {{updated}}",
|
||||
discoverNeFail: "Collect failed",
|
||||
discoverUnmatched: "unmatched {{count}}",
|
||||
discoverUnmatchedMore: "{{count}} more not listed",
|
||||
discoverVendorRequired: "Vendor/device type missing; skipped LLDP command",
|
||||
discoverParserStub: "Parser \"{{parser}}\" is still a stub; output was collected but neighbors were not parsed",
|
||||
discoverNoTargets:
|
||||
"No scannable NEs on the map. Add managed NEs, or UME NEs with a CLI connect profile.",
|
||||
discoverViewDetail: "Detail",
|
||||
discoverLinkCount: "{{count}} link(s)",
|
||||
discoverLinksTitle: "Matched links ({{count}})",
|
||||
discoverLinksEmpty: "No on-map peer links matched in this scan.",
|
||||
discoverUnmatchedTitle: "Unmatched neighbors ({{count}})",
|
||||
discoverUnmatchedEmpty: "No unmatched neighbors.",
|
||||
discoverColPeer: "Peer NE",
|
||||
discoverColRemote: "Neighbor",
|
||||
discoverColLocalPort: "Local port",
|
||||
discoverColRemotePort: "Remote port",
|
||||
discoverColProtocol: "Protocol",
|
||||
discoverColAction: "Result",
|
||||
discoverLinkAdded: "Added",
|
||||
discoverLinkUpdated: "Updated",
|
||||
discoverLinkKeptManual: "Kept manual",
|
||||
discoverLocatePeer: "Locate peer",
|
||||
discoverLocateNe: "Locate NE",
|
||||
discoverRawPreview: "Raw output preview (truncated when long; parsing uses full output)",
|
||||
discoverGoLldp: "Details → LLDP links",
|
||||
findNode: "Find",
|
||||
findNodePh: "Type to search: name / IP / vendor",
|
||||
findNoMatch: "No matching node on the canvas",
|
||||
findMore: "{{count}} more matches…",
|
||||
locateOnCanvas: "Click to locate on canvas",
|
||||
openPortTraffic: "Open port traffic",
|
||||
removeStale: "Clear missing ({{count}})",
|
||||
removeStaleHint:
|
||||
"Queue delete of red missing edges (applies on Save); scheduled collect also purges after 4 consecutive misses",
|
||||
staleRemoved: "Queued {{count}} missing edge delete(s) — Save to apply",
|
||||
connectHint: "Connect mode: drag from the NE center anchor to the target (Esc or Select to exit)",
|
||||
};
|
||||
|
||||
export default topology;
|
||||
Loading…
Add table
Add a link
Reference in a new issue