diff options
| author | Christian Cleberg <[email protected]> | 2026-03-19 15:18:38 -0500 |
|---|---|---|
| committer | Christian Cleberg <[email protected]> | 2026-03-19 15:18:38 -0500 |
| commit | 659c76df9ff3926cb68886c16167808c23bd8f75 (patch) | |
| tree | 572bef546fcca19ad37bc1aa7cfb153eb2bf8eb7 /Hutch/Views/Tickets/TicketDetailViewModel.swift | |
| parent | ed48e72520c51e4635cd3840dbc569bdd74c950f (diff) | |
| parent | 6ba4e967d5dfb5d3c7bb97a0f2662f3180595563 (diff) | |
| download | hutch-2.tar.gz hutch-2.tar.bz2 hutch-2.zip | |
v2.0: Merge branch 'dev'v2
Diffstat (limited to 'Hutch/Views/Tickets/TicketDetailViewModel.swift')
| -rw-r--r-- | Hutch/Views/Tickets/TicketDetailViewModel.swift | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/Hutch/Views/Tickets/TicketDetailViewModel.swift b/Hutch/Views/Tickets/TicketDetailViewModel.swift index 90e33aa..660715b 100644 --- a/Hutch/Views/Tickets/TicketDetailViewModel.swift +++ b/Hutch/Views/Tickets/TicketDetailViewModel.swift @@ -433,6 +433,64 @@ final class TicketDetailViewModel { isPerformingAction = false } + func assignToCurrentUser(_ user: User) async { + guard !isPerformingAction, let currentTicket = ticket else { return } + + let currentAssignees = currentTicket.assignees + let currentEntity = Entity(canonicalName: user.canonicalName) + guard !currentAssignees.contains(where: { Self.matchesAssignee($0, user: user) }) else { + return + } + + isPerformingAction = true + error = nil + + ticket = TicketDetail( + id: currentTicket.id, + created: currentTicket.created, + updated: currentTicket.updated, + title: currentTicket.title, + description: currentTicket.description, + status: currentTicket.status, + resolution: currentTicket.resolution, + authenticity: currentTicket.authenticity, + submitter: currentTicket.submitter, + assignees: currentAssignees + [currentEntity], + labels: currentTicket.labels + ) + + do { + _ = try await client.execute( + service: .todo, + query: Self.assignUserMutation, + variables: [ + "trackerId": trackerId, + "ticketId": ticketId, + "userId": user.id + ], + responseType: AssignUserResponse.self + ) + await loadTicket() + } catch { + ticket = TicketDetail( + id: currentTicket.id, + created: currentTicket.created, + updated: currentTicket.updated, + title: currentTicket.title, + description: currentTicket.description, + status: currentTicket.status, + resolution: currentTicket.resolution, + authenticity: currentTicket.authenticity, + submitter: currentTicket.submitter, + assignees: currentAssignees, + labels: currentTicket.labels + ) + self.error = error.localizedDescription + } + + isPerformingAction = false + } + func unassignUser(username: String) async { guard !isPerformingAction else { return } isPerformingAction = true @@ -558,4 +616,26 @@ final class TicketDetailViewModel { isPerformingAction = false } + static func matchesAssignee(_ entity: Entity, user: User) -> Bool { + let assigneeCanonical = normalizedCanonicalName(entity.canonicalName) + let userCanonical = normalizedCanonicalName(user.canonicalName) + if assigneeCanonical == userCanonical { + return true + } + return normalizedUsername(entity.canonicalName) == normalizedUsername(user.username) + } + + private static func normalizedCanonicalName(_ value: String) -> String { + let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines) + if trimmed.hasPrefix("~") { + return trimmed + } + return "~\(trimmed)" + } + + private static func normalizedUsername(_ value: String) -> String { + let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines) + return trimmed.hasPrefix("~") ? String(trimmed.dropFirst()) : trimmed + } + } |
