summaryrefslogtreecommitdiff
path: root/Hutch/Views/Tickets/TicketDetailViewModel.swift
diff options
context:
space:
mode:
authorChristian Cleberg <[email protected]>2026-04-01 22:03:14 -0500
committerChristian Cleberg <[email protected]>2026-04-01 22:03:14 -0500
commit902055d5eaa7f5512b76e22f57df3939f956181f (patch)
tree08b7bb220b980adc9eaa9c195dc26e846707b311 /Hutch/Views/Tickets/TicketDetailViewModel.swift
parent209155dc431cf70d9c8dba20625bab7e3b1a5085 (diff)
downloadhutch-2.7.0.tar.gz
hutch-2.7.0.tar.bz2
hutch-2.7.0.zip
Add tracker management (delete/update, ACLs, labels)v2.7.0
- Add swipe actions (delete/edit) to tracker list - Add tracker settings menu on detail screen - Implement updateTracker and deleteTracker mutations - Implement ACL management (updateUserACL, updateTrackerACL, deleteACL) - Implement label management (createLabel, updateLabel, deleteLabel) - Add dedicated UI flows for ACLs and labels - Ensure state refresh after mutations - Handle loading, errors, and destructive confirmations Implements: https://todo.sr.ht/~ccleberg/Hutch/12
Diffstat (limited to 'Hutch/Views/Tickets/TicketDetailViewModel.swift')
-rw-r--r--Hutch/Views/Tickets/TicketDetailViewModel.swift124
1 files changed, 54 insertions, 70 deletions
diff --git a/Hutch/Views/Tickets/TicketDetailViewModel.swift b/Hutch/Views/Tickets/TicketDetailViewModel.swift
index 142c62b..999374b 100644
--- a/Hutch/Views/Tickets/TicketDetailViewModel.swift
+++ b/Hutch/Views/Tickets/TicketDetailViewModel.swift
@@ -3,10 +3,6 @@ import Foundation
// MARK: - Response types (file-private to avoid @MainActor Decodable issues)
private struct TicketDetailResponse: Decodable, Sendable {
- let user: UserTrackerTicketWrapper
-}
-
-private struct UserTrackerTicketWrapper: Decodable, Sendable {
let tracker: TrackerTicketWrapper
}
@@ -85,10 +81,6 @@ private struct CreateLabelResponse: Decodable, Sendable {
}
private struct TrackerLabelsResponse: Decodable, Sendable {
- let user: UserTrackerLabelsWrapper
-}
-
-private struct UserTrackerLabelsWrapper: Decodable, Sendable {
let tracker: TrackerLabelsWrapper
}
@@ -155,57 +147,55 @@ final class TicketDetailViewModel {
// MARK: - Queries
private static let detailQuery = """
- query ticket($owner: String!, $tracker: String!, $ticketId: Int!) {
- user(username: $owner) {
- tracker(name: $tracker) {
- ticket(id: $ticketId) {
- id
- created
- updated
- title: subject
- description: body
- status
- resolution
- authenticity
- submitter { canonicalName }
- assignees { canonicalName }
- labels { id name backgroundColor foregroundColor }
- events {
- results {
- id
- created
- changes {
- eventType
- ... on Comment {
- author { canonicalName }
- text
- authenticity
- }
- ... on StatusChange {
- oldStatus
- newStatus
- }
- ... on LabelUpdate {
- labeler { canonicalName }
- label { name }
- }
- ... on Assignment {
- assigner { canonicalName }
- assignee { canonicalName }
- }
- ... on TicketMention {
- mentioned { id }
- }
- ... on UserMention {
- mentioned { canonicalName }
- }
- ... on Created {
- author { canonicalName }
- }
+ query ticket($rid: ID!, $ticketId: Int!) {
+ tracker(rid: $rid) {
+ ticket(id: $ticketId) {
+ id
+ created
+ updated
+ title: subject
+ description: body
+ status
+ resolution
+ authenticity
+ submitter { canonicalName }
+ assignees { canonicalName }
+ labels { id name backgroundColor foregroundColor }
+ events {
+ results {
+ id
+ created
+ changes {
+ eventType
+ ... on Comment {
+ author { canonicalName }
+ text
+ authenticity
+ }
+ ... on StatusChange {
+ oldStatus
+ newStatus
+ }
+ ... on LabelUpdate {
+ labeler { canonicalName }
+ label { name }
+ }
+ ... on Assignment {
+ assigner { canonicalName }
+ assignee { canonicalName }
+ }
+ ... on TicketMention {
+ mentioned { id }
+ }
+ ... on UserMention {
+ mentioned { canonicalName }
+ }
+ ... on Created {
+ author { canonicalName }
}
}
- cursor
}
+ cursor
}
}
}
@@ -268,12 +258,10 @@ final class TicketDetailViewModel {
"""
private static let trackerLabelsQuery = """
- query trackerLabels($owner: String!, $tracker: String!) {
- user(username: $owner) {
- tracker(name: $tracker) {
- labels {
- results { id name backgroundColor foregroundColor }
- }
+ query trackerLabels($rid: ID!) {
+ tracker(rid: $rid) {
+ labels {
+ results { id name backgroundColor foregroundColor }
}
}
}
@@ -302,13 +290,12 @@ final class TicketDetailViewModel {
service: .todo,
query: Self.detailQuery,
variables: [
- "owner": ownerUsername,
- "tracker": trackerName,
+ "rid": trackerRid,
"ticketId": ticketId
],
responseType: TicketDetailResponse.self
)
- let payload = result.user.tracker.ticket
+ let payload = result.tracker.ticket
ticket = TicketDetail(
id: payload.id,
created: payload.created,
@@ -579,13 +566,10 @@ final class TicketDetailViewModel {
let result = try await client.execute(
service: .todo,
query: Self.trackerLabelsQuery,
- variables: [
- "owner": ownerUsername,
- "tracker": trackerName
- ],
+ variables: ["rid": trackerRid],
responseType: TrackerLabelsResponse.self
)
- trackerLabels = result.user.tracker.labels.results
+ trackerLabels = result.tracker.labels.results
} catch {
self.error = error.userFacingMessage
}