M15 erweitert: Interfaces direkt editierbar (Übersicht + Experte-Tab)
Jedes Interface bekommt jetzt ein editTarget — VLAN-Interfaces über das
kuratierte /interface vlan-Schema (mit der eigenen .id aus /interface
vlan, nicht der generischen /interface-Liste), alle anderen Typen
(Ethernet, Bridge, WLAN, WireGuard) generisch über /interface.
Dabei live einen echten Stolperstein gefunden: für /interface gab es
bisher kein kuratiertes Schema, alle Felder landeten unbeschriftet in
"Weitere Parameter" — beim Versuch, ether5 zu ether51 umzubenennen,
wurde versehentlich default-name (RouterOS' Werksname, nie änderbar)
statt name geändert ("bad parameter default-name"). Fix: /interface
jetzt mit kuratiertem Schema (Name/Kommentar/Deaktiviert), Tooltip auf
"Name" warnt explizit vor der Verwechslung mit default-name.
Adress-Listen-Knoten bleiben bewusst weiter nicht editierbar (fassen
mehrere Einträge zusammen, bräuchten eine andere UI-Form).
Live bestätigt ("funktioniert"). 60 Unit-Tests grün. Manual.md/
HANDOFF.md aktualisiert.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YDmUd93KxsYGr2kLTotWnG
This commit is contained in:
@@ -199,6 +199,22 @@ enum RouterOSSchemaCatalog {
|
||||
// MARK: - Interfaces (generic, browsing + free-form fields)
|
||||
|
||||
private static let interfaceFamily: [RouterOSMenuSchema] = [
|
||||
RouterOSMenuSchema(
|
||||
menuPath: "/interface", restPath: "interface", category: .interfaces,
|
||||
displayName: "Alle Interfaces (generisch)",
|
||||
summary: "Gemeinsame Felder, die für jedes Interface gelten, unabhängig vom Typ (Ethernet, Bridge, WLAN, WireGuard, VLAN, ...).",
|
||||
explanation: "RouterOS listet hier alle Interfaces zusammen. Typ-spezifische Felder (z.B. die VLAN-ID eines VLAN-Interfaces) liegen in den jeweils eigenen Menüs (z.B. \"VLAN-Interfaces\") — hier nur das, was für jeden Interface-Typ gleich funktioniert.",
|
||||
warning: "RouterOS liefert hier zusätzlich einen \"default-name\" (Werksname des Ports) mit — der erscheint unten bei \"Weitere Parameter\", ist aber nicht änderbar (\"bad parameter default-name\", live bestätigt). Zum Umbenennen nur das Feld \"Name\" oben verwenden.",
|
||||
fields: [
|
||||
RouterOSFieldSchema(key: "name", label: "Name", kind: .text,
|
||||
help: "Der aktuelle Name dieses Interfaces, z.B. ether5 oder vlan20 — nicht zu verwechseln mit \"default-name\" (Werksname, weiter unten bei \"Weitere Parameter\", nicht änderbar).", required: true),
|
||||
RouterOSFieldSchema(key: "comment", label: "Kommentar", kind: .text,
|
||||
help: "Nur zur eigenen Wiedererkennung, ohne technische Wirkung."),
|
||||
RouterOSFieldSchema(key: "disabled", label: "Deaktiviert", kind: .bool,
|
||||
help: "Interface inaktiv schalten, ohne es zu löschen.", defaultValue: "no")
|
||||
],
|
||||
listColumns: ["name"]
|
||||
),
|
||||
RouterOSMenuSchema(
|
||||
menuPath: "/interface bridge", restPath: "interface/bridge", category: .interfaces,
|
||||
displayName: "Bridge",
|
||||
|
||||
@@ -81,10 +81,10 @@ final class OverviewViewModel: ObservableObject {
|
||||
// Interfaces: every physical/virtual interface RouterOS reports (ethernet, vlan, bridge,
|
||||
// wireless, wireguard, ...). "vlan-id"/parent info is filled in below from "/interface
|
||||
// vlan", since the generic "/interface" listing alone doesn't carry it.
|
||||
var vlanInfoByName: [String: (vlanID: String, parent: String)] = [:]
|
||||
var vlanInfoByName: [String: (vlanID: String, parent: String, itemID: String)] = [:]
|
||||
for item in vlans {
|
||||
guard let name = item.fields["name"] else { continue }
|
||||
vlanInfoByName[name] = (item.fields["vlan-id"] ?? "?", item.fields["interface"] ?? "")
|
||||
vlanInfoByName[name] = (item.fields["vlan-id"] ?? "?", item.fields["interface"] ?? "", item.id)
|
||||
}
|
||||
|
||||
for item in interfaces {
|
||||
@@ -98,10 +98,24 @@ final class OverviewViewModel: ObservableObject {
|
||||
if item.fields["disabled"] == "true" || item.fields["disabled"] == "yes" {
|
||||
subtitle += " · deaktiviert"
|
||||
}
|
||||
// VLAN interfaces edit through their own curated "/interface vlan" schema (name/
|
||||
// vlan-id/interface/disabled) using that menu's own item id — every other interface
|
||||
// type (ethernet, bridge, wireless, wireguard, ...) has no curated schema of its own
|
||||
// here, so it falls back to the generic "/interface" menu, which does support the
|
||||
// common fields (name, comment, disabled) via a plain "set", just without curated
|
||||
// field labels/tooltips (same free-form editor the Experte-Tab uses for any
|
||||
// uncurated menu).
|
||||
let editTarget: OverviewNode.EditTarget
|
||||
if let vlanInfo = vlanInfoByName[name] {
|
||||
editTarget = .init(menuPath: "/interface vlan", restPath: "interface/vlan", itemID: vlanInfo.itemID)
|
||||
} else {
|
||||
editTarget = .init(menuPath: "/interface", restPath: "interface", itemID: item.id)
|
||||
}
|
||||
nodes.append(OverviewNode(
|
||||
id: nodeID(.interface, name), category: .interface, kind: type,
|
||||
title: name, subtitle: subtitle,
|
||||
detail: sortedDetail(item.fields)
|
||||
detail: sortedDetail(item.fields),
|
||||
editTarget: editTarget
|
||||
))
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user