← back to Ticket System
Add PARKED tile to desktop ticket bar, mirroring the board's parked-lane peel-out
0c0dc768a52e0ff59a2cc5d9bf47e79ee3b2ad10 · 2026-09-22 12:22:50 -0700 · Steve Abrams
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
M desktop-bar/TicketBar.swift
Diff
commit 0c0dc768a52e0ff59a2cc5d9bf47e79ee3b2ad10
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Tue Sep 22 12:22:50 2026 -0700
Add PARKED tile to desktop ticket bar, mirroring the board's parked-lane peel-out
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
desktop-bar/TicketBar.swift | 28 +++++++++++++++++++++-------
1 file changed, 21 insertions(+), 7 deletions(-)
diff --git a/desktop-bar/TicketBar.swift b/desktop-bar/TicketBar.swift
index 7d645888..102d02e8 100644
--- a/desktop-bar/TicketBar.swift
+++ b/desktop-bar/TicketBar.swift
@@ -72,6 +72,7 @@ private final class BarController: NSObject, NSApplicationDelegate, NSWindowDele
private let openLabel = NSTextField(labelWithString: "OPEN …")
private let blockedLabel = NSTextField(labelWithString: "BLOCKED …")
private let doingLabel = NSTextField(labelWithString: "DOING …")
+ private let parkedLabel = NSTextField(labelWithString: "PARKED …")
private let working = NSTextField(labelWithString: "Working · —")
private let latest = NSTextField(labelWithString: "Latest · —")
private let cpuLabel = NSTextField(labelWithString: "CPU · —")
@@ -143,7 +144,7 @@ private final class BarController: NSObject, NSApplicationDelegate, NSWindowDele
isNight = UserDefaults.standard.object(forKey: "ticketBarNight") as? Bool ?? true
barPosition = UserDefaults.standard.string(forKey: "ticketBarPosition") ?? "top"
- let countLabels = [openLabel, blockedLabel, doingLabel]
+ let countLabels = [openLabel, blockedLabel, doingLabel, parkedLabel]
for label in countLabels + [working, latest] {
label.font = .systemFont(ofSize: 12, weight: countLabels.contains(label) ? .bold : .medium)
label.lineBreakMode = .byTruncatingTail
@@ -156,6 +157,7 @@ private final class BarController: NSObject, NSApplicationDelegate, NSWindowDele
// dropdown listing that status's tickets. Working + Latest unchanged.
let definitions: [(String, NSTextField, CGFloat)] = [
("open", openLabel, 150), ("blocked", blockedLabel, 175), ("doing", doingLabel, 150),
+ ("parked", parkedLabel, 150),
("working", working, 560), ("latest", latest, 520)
]
let savedOrder = UserDefaults.standard.stringArray(forKey: "ticketBarOrder") ?? definitions.map(\.0)
@@ -377,6 +379,8 @@ private final class BarController: NSObject, NSApplicationDelegate, NSWindowDele
: NSColor(calibratedRed: 0.74, green: 0.18, blue: 0.22, alpha: 1)
doingLabel.textColor = night ? NSColor(calibratedRed: 0.43, green: 0.70, blue: 0.95, alpha: 1)
: NSColor(calibratedRed: 0.16, green: 0.44, blue: 0.72, alpha: 1)
+ parkedLabel.textColor = night ? NSColor(calibratedRed: 1.00, green: 0.62, blue: 0.80, alpha: 1)
+ : NSColor(calibratedRed: 0.82, green: 0.14, blue: 0.50, alpha: 1)
working.textColor = night ? NSColor(calibratedRed: 0.45, green: 0.78, blue: 1.00, alpha: 1)
: NSColor(calibratedRed: 0.10, green: 0.45, blue: 0.82, alpha: 1)
latest.textColor = night ? NSColor(calibratedWhite: 0.72, alpha: 1)
@@ -500,7 +504,7 @@ private final class BarController: NSObject, NSApplicationDelegate, NSWindowDele
// greyed-out/disabled — and each row is clickable (jumps to that ticket).
menu.autoenablesItems = false
let details: [String]
- if key == "open" || key == "blocked" || key == "doing" {
+ if key == "open" || key == "blocked" || key == "doing" || key == "parked" {
let list = statusDetails[key] ?? []
details = list.isEmpty ? ["No \(key) tickets"] : list
} else if key == "working" {
@@ -1056,6 +1060,7 @@ private final class BarController: NSObject, NSApplicationDelegate, NSWindowDele
private struct BoardTicket {
let id: String, title: String, status: String, updated: String, created: String
let rank: Int?, priority: Double
+ let parked: Bool
}
// One GET, no semaphore: the completion already runs off-main; callers hop to main for UI.
@@ -1070,7 +1075,8 @@ private final class BarController: NSObject, NSApplicationDelegate, NSWindowDele
guard let id = t["id"] as? String, id.hasPrefix("TK-") else { return nil }
return BoardTicket(id: id, title: t["title"] as? String ?? id, status: t["status"] as? String ?? "open",
updated: t["updated_at"] as? String ?? "", created: t["created_at"] as? String ?? "",
- rank: t["rank"] as? Int, priority: (t["priority"] as? NSNumber)?.doubleValue ?? 0)
+ rank: t["rank"] as? Int, priority: (t["priority"] as? NSNumber)?.doubleValue ?? 0,
+ parked: t["parked"] as? Bool ?? false)
})
}.resume()
}
@@ -1140,6 +1146,7 @@ private final class BarController: NSObject, NSApplicationDelegate, NSWindowDele
self.openLabel.stringValue = "OPEN —"
self.blockedLabel.stringValue = "BLOCKED —"
self.doingLabel.stringValue = "DOING —"
+ self.parkedLabel.stringValue = "PARKED —"
self.working.stringValue = "Working · board unreachable"
self.statusDetails = [:]
self.workingDetails = []
@@ -1153,9 +1160,15 @@ private final class BarController: NSObject, NSApplicationDelegate, NSWindowDele
if ra != rb { return ra < rb }
return a.updated > b.updated
}
- let openList = tickets.filter { $0.status == "open" }.sorted(by: byPrio)
- let blockedList = tickets.filter { $0.status == "blocked" }.sorted(by: byPrio)
- let doing = tickets.filter { $0.status == "doing" }.sorted(by: byPrio)
+ // Mirror the board's peel-out exactly (server.js ~487): an active parked ticket
+ // leaves its status bucket and joins the PARKED lane so it isn't double-counted.
+ func bucket(_ t: BoardTicket) -> String {
+ (t.parked && ["open", "blocked", "doing"].contains(t.status)) ? "parked" : t.status
+ }
+ let openList = tickets.filter { bucket($0) == "open" }.sorted(by: byPrio)
+ let blockedList = tickets.filter { bucket($0) == "blocked" }.sorted(by: byPrio)
+ let doing = tickets.filter { bucket($0) == "doing" }.sorted(by: byPrio)
+ let parkedList = tickets.filter { bucket($0) == "parked" }.sorted(by: byPrio)
let workText = doing.prefix(3).map { "\(self.shortID($0.id)) \(self.fiveWords($0.title))" }.joined(separator: " • ")
// Row: TK-xxxx #rank p<priority> · title 🕓 created date/time
let row: (BoardTicket) -> String = { t in
@@ -1171,7 +1184,8 @@ private final class BarController: NSObject, NSApplicationDelegate, NSWindowDele
self.openLabel.stringValue = "OPEN \(openList.count)"
self.blockedLabel.stringValue = "BLOCKED \(blockedList.count)"
self.doingLabel.stringValue = "DOING \(doing.count)"
- self.statusDetails = ["open": openList.map(row), "blocked": blockedList.map(row), "doing": doing.map(row)]
+ self.parkedLabel.stringValue = "PARKED \(parkedList.count)"
+ self.statusDetails = ["open": openList.map(row), "blocked": blockedList.map(row), "doing": doing.map(row), "parked": parkedList.map(row)]
self.working.stringValue = "Working · \(workText.isEmpty ? "none" : workText)"
self.workingDetails = doing.map(row)
self.panel.orderFrontRegardless()
← 802dbd64 auto-data-snapshot: 2026-09-22T12:15:47 (1 data files) — dat
·
back to Ticket System
·
ticketbar: add one-click Compact/Full toggle button (parity 27c33873 →