gitbay/Dashboard/DashboardModels.swift
81 lines · 3168 bytes
1import Foundation
2
3/// The `dashboard` command: the same account aggregate as the web
4/// dashboard, in one read. Newer arrays default empty so an updated app
5/// can still talk to a server from before the dashboard parity contract.
6nonisolated struct DashboardData: Decodable, Sendable, Hashable {
7 let reviewQueue: [DashboardItem]
8 let assignedIssues: [DashboardItem]
9 let openMRs: [DashboardItem]
10 let openIssues: [DashboardItem]
11 /// Pinned repos share `repo list`'s row shape.
12 let pinned: [RepoSummary]
13 let recentActivity: [FeedEvent]
14 /// Retained by the CLI for compatibility; builds are not a web
15 /// dashboard section.
16 let builds: [DashboardBuild]
17 /// The unread notification count, so a client showing a badge does
18 /// not need a second read to fill it.
19 let unread: Int
20 /// Pinned saved queries with their first rows (gitbay v1.39.0).
21 let queries: [DashboardQuery]
22
23 enum CodingKeys: String, CodingKey {
24 case pinned, builds, unread, queries
25 case reviewQueue = "review_queue"
26 case openMRs = "open_mrs"
27 case assignedIssues = "assigned_issues"
28 case openIssues = "open_issues"
29 case recentActivity = "recent_activity"
30 }
31
32 init(from decoder: any Decoder) throws {
33 let values = try decoder.container(keyedBy: CodingKeys.self)
34 reviewQueue = try values.decodeIfPresent([DashboardItem].self, forKey: .reviewQueue) ?? []
35 assignedIssues = try values.decodeIfPresent([DashboardItem].self, forKey: .assignedIssues) ?? []
36 openMRs = try values.decodeIfPresent([DashboardItem].self, forKey: .openMRs) ?? []
37 openIssues = try values.decodeIfPresent([DashboardItem].self, forKey: .openIssues) ?? []
38 pinned = try values.decodeIfPresent([RepoSummary].self, forKey: .pinned) ?? []
39 recentActivity = try values.decodeIfPresent([FeedEvent].self, forKey: .recentActivity) ?? []
40 builds = try values.decodeIfPresent([DashboardBuild].self, forKey: .builds) ?? []
41 unread = try values.decodeIfPresent(Int.self, forKey: .unread) ?? 0
42 queries = try values.decodeIfPresent([DashboardQuery].self, forKey: .queries) ?? []
43 }
44}
45
46/// One open issue or MR row, repo resolved server-side.
47nonisolated struct DashboardItem: Decodable, Sendable, Hashable, Identifiable {
48 let repo: String
49 let number: Int64
50 let title: String
51 let author: String
52 let state: String
53 let updatedAt: Date
54
55 enum CodingKeys: String, CodingKey {
56 case repo, number, title, author, state
57 case updatedAt = "updated_at"
58 }
59
60 var id: String { "\(repo)#\(number)" }
61}
62
63/// One build row with its repo attached.
64nonisolated struct DashboardBuild: Decodable, Sendable, Hashable, Identifiable {
65 let repo: String
66 let number: Int64
67 let job: String
68 let status: String
69 let sha: String
70 let ref: String
71 let createdAt: Date
72 let finishedAt: Date?
73
74 enum CodingKeys: String, CodingKey {
75 case repo, number, job, status, sha, ref
76 case createdAt = "created_at"
77 case finishedAt = "finished_at"
78 }
79
80 var id: String { "\(repo)#\(number)" }
81}