142 lines
5.8 KiB
Swift
142 lines
5.8 KiB
Swift
import SwiftUI
|
|
|
|
struct OLTDetailView: View {
|
|
let connection: MCMSConnection
|
|
@State private var vm: OLTDetailViewModel
|
|
@State private var showResetConfirm = false
|
|
private let title: String
|
|
|
|
init(connection: MCMSConnection, oltId: String, title: String? = nil) {
|
|
self.connection = connection
|
|
self.title = title ?? oltId
|
|
_vm = State(initialValue: OLTDetailViewModel(connection: connection, oltId: oltId))
|
|
}
|
|
|
|
var body: some View {
|
|
Group {
|
|
switch vm.phase {
|
|
case .idle:
|
|
LoadingView()
|
|
case .loading where vm.olt == nil:
|
|
LoadingView()
|
|
case .failed(let msg):
|
|
ErrorStateView(message: msg) { Task { await vm.load() } }
|
|
default:
|
|
content
|
|
}
|
|
}
|
|
.navigationTitle(title)
|
|
.navigationBarTitleDisplayMode(.inline)
|
|
.toolbar {
|
|
ToolbarItem(placement: .topBarTrailing) {
|
|
Menu {
|
|
Button(role: .destructive) { showResetConfirm = true } label: {
|
|
Label("Reset OLT", systemImage: "arrow.clockwise")
|
|
}
|
|
} label: {
|
|
Image(systemName: "ellipsis.circle")
|
|
}
|
|
.disabled(vm.isPerformingAction)
|
|
}
|
|
}
|
|
.sheet(isPresented: $showResetConfirm) {
|
|
ResetConfirmSheet(deviceKind: "OLT", deviceName: title) {
|
|
Task { await vm.reset() }
|
|
}
|
|
}
|
|
.alert("Operation", isPresented: Binding(
|
|
get: { vm.actionMessage != nil },
|
|
set: { if !$0 { vm.actionMessage = nil } }
|
|
)) {
|
|
Button("OK") { vm.actionMessage = nil }
|
|
} message: {
|
|
Text(vm.actionMessage ?? "")
|
|
}
|
|
.task { if vm.phase == .idle { await vm.load() } }
|
|
.refreshable { await vm.load() }
|
|
}
|
|
|
|
@ViewBuilder
|
|
private var content: some View {
|
|
if let olt = vm.olt {
|
|
List {
|
|
Section("Status") {
|
|
LabeledContent("ONUs", value: onuSummary(olt))
|
|
if let model = olt.model { LabeledContent("Model", value: model) }
|
|
if let mode = olt.ponMode { LabeledContent("PON mode", value: mode) }
|
|
if let fw = olt.firmwareVersion { LabeledContent("Firmware", value: fw) }
|
|
if let online = olt.onlineTime {
|
|
if let up = MongoTimestamp.duration(from: online, to: olt.lastUpdate) {
|
|
LabeledContent("Uptime", value: up)
|
|
}
|
|
LabeledContent("Online since", value: MongoTimestamp.displayString(online) ?? online)
|
|
}
|
|
if let updated = MongoTimestamp.displayString(olt.lastUpdate) {
|
|
LabeledContent("Last update", value: updated)
|
|
}
|
|
}
|
|
|
|
if olt.rxRateBps != nil || olt.txRateBps != nil || olt.txUtilPercent != nil {
|
|
Section("PON traffic") {
|
|
LabeledContent("Downstream",
|
|
value: "\(Format.bps(olt.txRateBps)) · \(Format.percent(olt.txUtilPercent)) util")
|
|
LabeledContent("Upstream",
|
|
value: "\(Format.bps(olt.rxRateBps)) · \(Format.percent(olt.rxUtilPercent)) util")
|
|
}
|
|
}
|
|
|
|
if olt.asicTempC != nil || olt.voltage != nil {
|
|
Section("Environment") {
|
|
if let temp = olt.asicTempC { LabeledContent("ASIC temp", value: "\(temp) °C") }
|
|
if let volts = olt.voltage {
|
|
LabeledContent("Voltage", value: "\(volts.formatted(.number.precision(.fractionLength(2)))) V")
|
|
}
|
|
}
|
|
}
|
|
|
|
if let switchName = olt.switchName {
|
|
Section("Uplink") {
|
|
LabeledContent("Switch", value: switchName)
|
|
if let port = olt.switchPort { LabeledContent("Port", value: port) }
|
|
if let addr = olt.switchAddress { LabeledContent("Address", value: addr) }
|
|
}
|
|
}
|
|
|
|
if olt.populatedBuckets.isEmpty {
|
|
Section { Text("No ONUs registered on this OLT.").foregroundStyle(.secondary) }
|
|
} else {
|
|
ForEach(olt.populatedBuckets, id: \.state) { bucket in
|
|
Section {
|
|
ForEach(bucket.ids, id: \.self) { onuId in
|
|
NavigationLink {
|
|
ONUDetailView(connection: connection, onuId: onuId)
|
|
} label: {
|
|
Text(onuId)
|
|
}
|
|
}
|
|
} header: {
|
|
HStack {
|
|
StateBadge(text: bucket.state.label, color: bucket.state.color)
|
|
Spacer()
|
|
Text("\(bucket.ids.count)")
|
|
.font(.caption.monospacedDigit())
|
|
.foregroundStyle(.secondary)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Section("Raw document") {
|
|
JSONTreeView(value: olt.raw)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private func onuSummary(_ olt: OLTStateDoc) -> String {
|
|
let down = olt.totalONUs - olt.onlineONUs
|
|
var summary = "\(olt.totalONUs) · \(olt.onlineONUs) online"
|
|
if down > 0 { summary += " · \(down) down" }
|
|
return summary
|
|
}
|
|
}
|