Files
RouterOS/RouterOSAssistant/Features/Expert/ExpertView.swift
T
KayandClaude Sonnet 5 bf2ae58a20 Experte-Tab: ausführlichere Tooltips, Sektions-Überschrift, aktive Auswahl hervorgehoben
Alle RouterOSFieldSchema.help-Texte in RouterOSSchemaCatalog.swift
überarbeitet — jedes Adress-/Netz-/Bereichs-Feld hat jetzt ein
konkretes Beispiel (z.B. 192.168.88.1/24), vorher leere Hilfetexte
gefüllt.

Zusätzlich zwei UI-Wünsche umgesetzt: fette Überschrift (Menüname +
Kategorie) im Detailbereich, da vorher unklar war, in welcher Sektion
man sich befindet; und hellblaue Hervorhebung des aktiven Eintrags in
der linken Liste (per Zeileninhalt-Hintergrund statt
.listRowBackground, das vom macOS-Sidebar-Stil überschrieben wird).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YDmUd93KxsYGr2kLTotWnG
2026-09-15 11:16:10 +02:00

83 lines
4.1 KiB
Swift

import SwiftUI
struct ExpertView: View {
@ObservedObject var connectionService: ConnectionService
@StateObject private var viewModel: ExpertViewModel
init(connectionService: ConnectionService) {
self.connectionService = connectionService
_viewModel = StateObject(wrappedValue: ExpertViewModel(connectionService: connectionService))
}
var body: some View {
Group {
if connectionService.credentials == nil {
ContentUnavailableView(
"Nicht verbunden",
systemImage: "network.slash",
description: Text("Verbinde dich zuerst im Tab \"Verbinden\" mit deinem Router.")
)
} else {
NavigationSplitView {
List {
ForEach(RouterOSMenuCategory.allCases) { category in
let schemas = RouterOSSchemaCatalog.schemas(in: category)
if !schemas.isEmpty {
Section(category.rawValue) {
ForEach(schemas) { schema in
let isSelected = viewModel.selectedSchema?.menuPath == schema.menuPath
Button {
viewModel.open(schema)
} label: {
Text(schema.displayName)
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.vertical, 4)
.padding(.horizontal, 6)
.background(
RoundedRectangle(cornerRadius: 6)
.fill(isSelected ? Color.blue.opacity(0.25) : Color.clear)
)
.contentShape(Rectangle())
}
.buttonStyle(.plain)
}
}
}
}
Section("Eigener Menüpfad") {
Text("Jeder RouterOS-Menüpfad ist erreichbar, auch wenn er oben nicht gelistet ist — die Felder erscheinen dann generisch (Schlüssel/Wert), ohne kuratierte Erklärung.")
.font(.caption)
.foregroundStyle(.secondary)
TextField("Menüpfad, z.B. /ip firewall filter", text: $viewModel.customMenuPath)
.help("Der RouterOS-CLI-Pfad, z.B. \"/interface wireguard\" oder \"/routing ospf instance\".")
TextField("REST-Pfad, z.B. ip/firewall/filter", text: $viewModel.customRestPath)
.help("Derselbe Pfad in REST-API-Schreibweise: führende \"/\" weg, Leerzeichen zu \"/\".")
Button("Öffnen") { viewModel.openCustomPath() }
.disabled(viewModel.customMenuPath.isEmpty || viewModel.customRestPath.isEmpty)
}
}
.navigationTitle("Experte")
} detail: {
if let schema = viewModel.selectedSchema {
ExpertMenuDetailView(
viewModel: viewModel,
schema: schema
)
} else {
ContentUnavailableView(
"Kein Menü ausgewählt",
systemImage: "list.bullet.rectangle",
description: Text("Wähle links einen RouterOS-Bereich aus.")
)
}
}
}
}
}
}
#Preview {
ExpertView(connectionService: ConnectionService())
}