import SwiftUI /// The web's /admin page: the server build, a way to the accounts, and /// every worker queue's backlog in the web's order and words. struct AdminView: View { @State private var model: AdminOverviewViewModel init(client: GitbayClient) { _model = State(initialValue: AdminOverviewViewModel(client: client)) } var body: some View { List { if let overview = model.state.value { Section { NavigationLink(value: RepoRoute.adminUsers) { Label("Accounts", systemImage: "person.2") } .accessibilityIdentifier("admin-accounts") NavigationLink(value: RepoRoute.adminRepos) { Label("Repositories", systemImage: "books.vertical") } .accessibilityIdentifier("admin-repos") NavigationLink(value: RepoRoute.adminOrgLimits) { Label("Organization limits", systemImage: "building.2") } .accessibilityIdentifier("admin-org-limits") NavigationLink(value: RepoRoute.adminStats) { Label("Statistics", systemImage: "chart.bar") } .accessibilityIdentifier("admin-stats") NavigationLink(value: RepoRoute.adminAudit) { Label("Audit log", systemImage: "list.bullet.rectangle") } .accessibilityIdentifier("admin-audit") NavigationLink(value: RepoRoute.adminRunners) { Label("Runners", systemImage: "hammer") } .accessibilityIdentifier("admin-runners") NavigationLink(value: RepoRoute.adminInbound) { Label("Inbound mail", systemImage: "tray.and.arrow.down") } .accessibilityIdentifier("admin-inbound") } footer: { if let commit = overview.commit { Text("Server build \(commit).") } } ForEach(overview.sections) { section in Section { if section.rows.isEmpty { Text(section.empty) .font(.gbSans(.subheadline)) .foregroundStyle(.secondary) } else { ForEach(section.rows) { line in VStack(alignment: .leading, spacing: 2) { Text(line.title) .font(.gbSans(.subheadline).weight(.medium)) Text(line.detail) .font(.gbSans(.caption)) .foregroundStyle(.secondary) } } } } header: { Text("\(section.heading) \(section.count)") } footer: { if let summary = section.summary { Text(summary) } } } } } .overlay { LoadStateOverlay(state: model.state) } .navigationTitle("Admin") .navigationBarTitleDisplayMode(.inline) .task { await model.load() } .refreshable { await model.load() } } }