diff options
| author | Christian Cleberg <[email protected]> | 2026-04-12 22:42:33 -0500 |
|---|---|---|
| committer | Christian Cleberg <[email protected]> | 2026-04-12 22:42:33 -0500 |
| commit | 576bb6c2432a15f5138771c06019b55fd2244e15 (patch) | |
| tree | 167b4704658c11ea6b9e7170390098e13c89b94b /Hutch/Models | |
| parent | 54d037548261c1546555a89a6a803b542a769880 (diff) | |
| download | hutch-576bb6c2432a15f5138771c06019b55fd2244e15.tar.gz hutch-576bb6c2432a15f5138771c06019b55fd2244e15.tar.bz2 hutch-576bb6c2432a15f5138771c06019b55fd2244e15.zip | |
feat: add ticket label management and bulk actions
Implements: https://todo.sr.ht/~ccleberg/hutch/45
Implements: https://todo.sr.ht/~ccleberg/hutch/46
Diffstat (limited to 'Hutch/Models')
| -rw-r--r-- | Hutch/Models/TicketBulkAction.swift | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/Hutch/Models/TicketBulkAction.swift b/Hutch/Models/TicketBulkAction.swift new file mode 100644 index 0000000..dcf7676 --- /dev/null +++ b/Hutch/Models/TicketBulkAction.swift @@ -0,0 +1,88 @@ +import Foundation + +enum TicketBulkActionKind: String, Sendable { + case close + case assign + + var displayName: String { + switch self { + case .close: + "Close" + case .assign: + "Assign" + } + } + + var pastTenseDisplayName: String { + switch self { + case .close: + "Closed" + case .assign: + "Assigned" + } + } +} + +struct TicketBulkActionResult: Identifiable, Sendable { + let id = UUID() + let action: TicketBulkActionKind + let totalCount: Int + let updatedCount: Int + let unchangedCount: Int + let failures: [TicketBulkActionFailure] + + var failedCount: Int { + failures.count + } + + var title: String { + if updatedCount == 0, failedCount > 0 { + return "\(action.displayName) Failed" + } + if failedCount > 0 { + return "\(action.displayName) Partially Applied" + } + return "\(action.displayName) Complete" + } + + var message: String { + var components: [String] = [] + + if updatedCount > 0 { + components.append("\(action.pastTenseDisplayName) \(updatedCount) \(ticketWord(for: updatedCount)).") + } + + if unchangedCount > 0 { + let unchangedDescription: String + switch action { + case .close: + unchangedDescription = "\(unchangedCount) already closed." + case .assign: + unchangedDescription = "\(unchangedCount) already assigned." + } + components.append(unchangedDescription) + } + + if failedCount > 0 { + let ids = failures + .map { "#\($0.ticketID)" } + .joined(separator: ", ") + components.append("Failed: \(ids).") + } + + if components.isEmpty { + components.append("No tickets were selected.") + } + + return components.joined(separator: " ") + } + + private func ticketWord(for count: Int) -> String { + count == 1 ? "ticket" : "tickets" + } +} + +struct TicketBulkActionFailure: Sendable { + let ticketID: Int + let message: String +} |
