initial commit
This commit is contained in:
commit
8de962eeb8
44 changed files with 4843 additions and 0 deletions
142
OLTDetailView.swift
Normal file
142
OLTDetailView.swift
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
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
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue