tickets: file T-343 — ticket-panel type filter chips
Bug / Ticket / Epic / Initiative toggle chips at the top of the tickets panel, all on by default. Single-click toggles a type; double-click solos it (chart-legend pattern), double-click again restores all; last-off resets to all-on. Filed under the UI epic T-276 with a Frame0 wireframe. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3435,3 +3435,4 @@ SCOPE CLARIFICATION (2026-06-10, from user):
|
||||
- Net behaviour: a fan-out of N agents -> N distinct collapsed cards, each containing its own complete run; surrounding non-agent tool calls still group into their normal Activity card.
|
||||
|
||||
Test additions: (a) two concurrent agents whose sidechain items interleave -> each agent''s run items land under its own card, none cross-attributed; (b) an unattributable sidechain item (no parent_tool_use_id, broken chain) is NOT swept into the nearest agent''s card; (c) regression: consecutive Bash/Read calls still form one Activity cluster.', NULL, '2026-06-10 15:28:52', '2026-06-10 15:28:52', '2026-06-10 15:28:52', NULL, '0352b24d88a4bf24ede628880fe9b502', 2) ON CONFLICT(hash) DO NOTHING;
|
||||
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB4FDREHRYRR7B9ER72KCQKC', 'status', 'backlog', 'in_progress', NULL, '2026-06-10 15:54:23', '2026-06-10 15:54:23', '2026-06-10 15:54:23', NULL, '8061a1d449acdb1e467239de0dce5d1d', 2) ON CONFLICT(hash) DO NOTHING;
|
||||
|
||||
@@ -2903,3 +2903,59 @@ SCOPE CLARIFICATION (2026-06-10, from user):
|
||||
- Net behaviour: a fan-out of N agents -> N distinct collapsed cards, each containing its own complete run; surrounding non-agent tool calls still group into their normal Activity card.
|
||||
|
||||
Test additions: (a) two concurrent agents whose sidechain items interleave -> each agent''s run items land under its own card, none cross-attributed; (b) an unattributable sidechain item (no parent_tool_use_id, broken chain) is NOT swept into the nearest agent''s card; (c) regression: consecutive Bash/Read calls still form one Activity cluster.', 'backlog', 'medium', NULL, NULL, NULL, '2026-06-10 15:26:33', '2026-06-10 15:28:52', NULL, '05bc2daa013de8cf163cdd54c6014f07', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
||||
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB4FDREHRYRR7B9ER72KCQKC', 'story', '06FB0TNQM5TWC00GW0P3X02HZW', 'Ticket panel: per-type filter chips (Bug / Ticket / Epic / Initiative)', 'Add a row of type-filter toggle chips at the top of the tickets panel, directly below the "Filter tickets…" box (no section header — the chips read on their own). One chip per ticket type the user thinks in: Bug, Ticket, Epic, Initiative. All four ON by default.
|
||||
|
||||
## Behaviour
|
||||
- Single-click a chip → toggle that type in/out of the list.
|
||||
- Double-click a chip → isolate (solo) that type: turns it ON and all others OFF. Double-click the same chip again → restore all to ON. This is the chart-legend solo pattern (Plotly/Tableau/Grafana) — learnable and fully reversible.
|
||||
- Last-off resets to all-on: disabling the final remaining type snaps all chips back ON. An empty type filter means "no filter", so the list is never mysteriously blank.
|
||||
- Tooltip per chip: "Click to toggle · double-click to isolate".
|
||||
|
||||
## Type mapping (pql → chip)
|
||||
pql ticket types are initiative, epic, story, task, bug (see lib/builtin/tickets/src/ticket_colors.dart). The four chips map as:
|
||||
- Bug → bug
|
||||
- Ticket → story + task (leaf work items)
|
||||
- Epic → epic
|
||||
- Initiative → initiative
|
||||
|
||||
Each chip carries its type-colored dot + border using TicketTypeColors (bug #E87D7D, story/task green/grey, epic #78A0F8, initiative #C792EA).
|
||||
|
||||
## Filtering
|
||||
- Type filter is ANDed with the existing text filter in _TicketsViewState (lib/builtin/tickets/src/tickets_view.dart): a ticket shows only if its type is enabled AND it matches the text filter.
|
||||
- When the type filter hides all items in a status section, that section collapses out (same as text-filter behaviour today).
|
||||
|
||||
## Implementation notes
|
||||
- Active-chip visual: filled tint + type-colored border (active) vs muted/no border (inactive) — reuse the _Toggle pattern from lib/builtin/search/src/search_panel_view.dart and ClideTappable.
|
||||
- Persist nothing across sessions for v1 (always all-on on load); revisit if requested.
|
||||
- a11y: Semantics(button, toggled) per chip, mirroring the search-panel toggle.
|
||||
|
||||
## Wireframe
|
||||
docs/design/wireframes/tickets/ticket-type-filters.json (+ .png export)', 'backlog', 'medium', NULL, NULL, NULL, '2026-06-10 15:54:09', '2026-06-10 15:54:09', NULL, '3e7c03bbb536a4c2d45f770abfee8b13', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
||||
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB4FDREHRYRR7B9ER72KCQKC', 'story', '06FB0TNQM5TWC00GW0P3X02HZW', 'Ticket panel: per-type filter chips (Bug / Ticket / Epic / Initiative)', 'Add a row of type-filter toggle chips at the top of the tickets panel, directly below the "Filter tickets…" box (no section header — the chips read on their own). One chip per ticket type the user thinks in: Bug, Ticket, Epic, Initiative. All four ON by default.
|
||||
|
||||
## Behaviour
|
||||
- Single-click a chip → toggle that type in/out of the list.
|
||||
- Double-click a chip → isolate (solo) that type: turns it ON and all others OFF. Double-click the same chip again → restore all to ON. This is the chart-legend solo pattern (Plotly/Tableau/Grafana) — learnable and fully reversible.
|
||||
- Last-off resets to all-on: disabling the final remaining type snaps all chips back ON. An empty type filter means "no filter", so the list is never mysteriously blank.
|
||||
- Tooltip per chip: "Click to toggle · double-click to isolate".
|
||||
|
||||
## Type mapping (pql → chip)
|
||||
pql ticket types are initiative, epic, story, task, bug (see lib/builtin/tickets/src/ticket_colors.dart). The four chips map as:
|
||||
- Bug → bug
|
||||
- Ticket → story + task (leaf work items)
|
||||
- Epic → epic
|
||||
- Initiative → initiative
|
||||
|
||||
Each chip carries its type-colored dot + border using TicketTypeColors (bug #E87D7D, story/task green/grey, epic #78A0F8, initiative #C792EA).
|
||||
|
||||
## Filtering
|
||||
- Type filter is ANDed with the existing text filter in _TicketsViewState (lib/builtin/tickets/src/tickets_view.dart): a ticket shows only if its type is enabled AND it matches the text filter.
|
||||
- When the type filter hides all items in a status section, that section collapses out (same as text-filter behaviour today).
|
||||
|
||||
## Implementation notes
|
||||
- Active-chip visual: filled tint + type-colored border (active) vs muted/no border (inactive) — reuse the _Toggle pattern from lib/builtin/search/src/search_panel_view.dart and ClideTappable.
|
||||
- Persist nothing across sessions for v1 (always all-on on load); revisit if requested.
|
||||
- a11y: Semantics(button, toggled) per chip, mirroring the search-panel toggle.
|
||||
|
||||
## Wireframe
|
||||
docs/design/wireframes/tickets/ticket-type-filters.json (+ .png export)', 'in_progress', 'medium', NULL, NULL, NULL, '2026-06-10 15:54:09', '2026-06-10 15:54:23', NULL, 'f5614424c00196aabab868db75483bf2', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
{
|
||||
"name": "Ticket Panel — Type Filters",
|
||||
"shapes": {
|
||||
"panel": {
|
||||
"type": "Rectangle",
|
||||
"left": 80, "top": 60, "width": 400, "height": 520,
|
||||
"fillColor": "#0d0d11",
|
||||
"strokeColor": "#23232b",
|
||||
"corners": [6, 6, 6, 6]
|
||||
},
|
||||
|
||||
"filter-box": {
|
||||
"type": "Rectangle",
|
||||
"parent": "panel",
|
||||
"left": 96, "top": 76, "width": 368, "height": 30,
|
||||
"fillColor": "#16161c",
|
||||
"strokeColor": "#2c2c36",
|
||||
"corners": [5, 5, 5, 5]
|
||||
},
|
||||
"filter-icon": {
|
||||
"type": "Text",
|
||||
"parent": "filter-box",
|
||||
"left": 108, "top": 84,
|
||||
"text": "⌕",
|
||||
"fontColor": "#5b5b66",
|
||||
"fontSize": 13
|
||||
},
|
||||
"filter-text": {
|
||||
"type": "Text",
|
||||
"parent": "filter-box",
|
||||
"left": 126, "top": 85,
|
||||
"text": "Filter tickets…",
|
||||
"fontColor": "#5b5b66",
|
||||
"fontSize": 12
|
||||
},
|
||||
"refresh-icon": {
|
||||
"type": "Text",
|
||||
"parent": "filter-box",
|
||||
"left": 442, "top": 84,
|
||||
"text": "↻",
|
||||
"fontColor": "#5b5b66",
|
||||
"fontSize": 13
|
||||
},
|
||||
|
||||
"chip-bug": {
|
||||
"type": "Rectangle",
|
||||
"parent": "panel",
|
||||
"left": 96, "top": 118, "width": 66, "height": 24,
|
||||
"fillColor": "#211519",
|
||||
"strokeColor": "#E87D7D",
|
||||
"corners": [4, 4, 4, 4]
|
||||
},
|
||||
"chip-bug-dot": {
|
||||
"type": "Ellipse",
|
||||
"parent": "chip-bug",
|
||||
"left": 104, "top": 126, "width": 8, "height": 8,
|
||||
"fillColor": "#E87D7D",
|
||||
"strokeColor": "#E87D7D"
|
||||
},
|
||||
"chip-bug-label": {
|
||||
"type": "Text",
|
||||
"parent": "chip-bug",
|
||||
"left": 117, "top": 124,
|
||||
"text": "Bug",
|
||||
"fontColor": "#e8e8ee",
|
||||
"fontSize": 11
|
||||
},
|
||||
|
||||
"chip-ticket": {
|
||||
"type": "Rectangle",
|
||||
"parent": "panel",
|
||||
"left": 168, "top": 118, "width": 78, "height": 24,
|
||||
"fillColor": "#15191d",
|
||||
"strokeColor": "#7DD3A8",
|
||||
"corners": [4, 4, 4, 4]
|
||||
},
|
||||
"chip-ticket-dot": {
|
||||
"type": "Ellipse",
|
||||
"parent": "chip-ticket",
|
||||
"left": 176, "top": 126, "width": 8, "height": 8,
|
||||
"fillColor": "#7DD3A8",
|
||||
"strokeColor": "#7DD3A8"
|
||||
},
|
||||
"chip-ticket-label": {
|
||||
"type": "Text",
|
||||
"parent": "chip-ticket",
|
||||
"left": 189, "top": 124,
|
||||
"text": "Ticket",
|
||||
"fontColor": "#e8e8ee",
|
||||
"fontSize": 11
|
||||
},
|
||||
|
||||
"chip-epic": {
|
||||
"type": "Rectangle",
|
||||
"parent": "panel",
|
||||
"left": 252, "top": 118, "width": 68, "height": 24,
|
||||
"fillColor": "#14171f",
|
||||
"strokeColor": "#78A0F8",
|
||||
"corners": [4, 4, 4, 4]
|
||||
},
|
||||
"chip-epic-dot": {
|
||||
"type": "Ellipse",
|
||||
"parent": "chip-epic",
|
||||
"left": 260, "top": 126, "width": 8, "height": 8,
|
||||
"fillColor": "#78A0F8",
|
||||
"strokeColor": "#78A0F8"
|
||||
},
|
||||
"chip-epic-label": {
|
||||
"type": "Text",
|
||||
"parent": "chip-epic",
|
||||
"left": 273, "top": 124,
|
||||
"text": "Epic",
|
||||
"fontColor": "#e8e8ee",
|
||||
"fontSize": 11
|
||||
},
|
||||
|
||||
"chip-init": {
|
||||
"type": "Rectangle",
|
||||
"parent": "panel",
|
||||
"left": 326, "top": 118, "width": 86, "height": 24,
|
||||
"fillColor": "#1a151f",
|
||||
"strokeColor": "#C792EA",
|
||||
"corners": [4, 4, 4, 4]
|
||||
},
|
||||
"chip-init-dot": {
|
||||
"type": "Ellipse",
|
||||
"parent": "chip-init",
|
||||
"left": 334, "top": 126, "width": 8, "height": 8,
|
||||
"fillColor": "#C792EA",
|
||||
"strokeColor": "#C792EA"
|
||||
},
|
||||
"chip-init-label": {
|
||||
"type": "Text",
|
||||
"parent": "chip-init",
|
||||
"left": 347, "top": 124,
|
||||
"text": "Initiative",
|
||||
"fontColor": "#e8e8ee",
|
||||
"fontSize": 11
|
||||
},
|
||||
|
||||
"divider": {
|
||||
"type": "Line",
|
||||
"parent": "panel",
|
||||
"left": 96, "top": 158, "width": 368, "height": 1,
|
||||
"strokeColor": "#23232b"
|
||||
},
|
||||
|
||||
"section-header": {
|
||||
"type": "Text",
|
||||
"parent": "panel",
|
||||
"left": 98, "top": 172,
|
||||
"text": "▾ BACKLOG · 61",
|
||||
"fontColor": "#6b6b76",
|
||||
"fontSize": 10
|
||||
},
|
||||
|
||||
"card-1": {
|
||||
"type": "Rectangle",
|
||||
"parent": "panel",
|
||||
"left": 96, "top": 192, "width": 368, "height": 56,
|
||||
"fillColor": "#0d0d11",
|
||||
"strokeColor": "#23232b",
|
||||
"corners": [4, 4, 4, 4]
|
||||
},
|
||||
"card-1-dot": {
|
||||
"type": "Ellipse",
|
||||
"parent": "card-1",
|
||||
"left": 108, "top": 204, "width": 8, "height": 8,
|
||||
"fillColor": "#C792EA",
|
||||
"strokeColor": "#C792EA"
|
||||
},
|
||||
"card-1-id": {
|
||||
"type": "Text",
|
||||
"parent": "card-1",
|
||||
"left": 122, "top": 200,
|
||||
"text": "T-8",
|
||||
"fontColor": "#e8e8ee",
|
||||
"fontSize": 11
|
||||
},
|
||||
"card-1-title": {
|
||||
"type": "Text",
|
||||
"parent": "card-1",
|
||||
"left": 108, "top": 220,
|
||||
"text": "Tier 6 — extension API, settings, theming, builds",
|
||||
"fontColor": "#b8b8c2",
|
||||
"fontSize": 11
|
||||
},
|
||||
|
||||
"card-2": {
|
||||
"type": "Rectangle",
|
||||
"parent": "panel",
|
||||
"left": 96, "top": 254, "width": 368, "height": 56,
|
||||
"fillColor": "#0d0d11",
|
||||
"strokeColor": "#23232b",
|
||||
"corners": [4, 4, 4, 4]
|
||||
},
|
||||
"card-2-dot": {
|
||||
"type": "Ellipse",
|
||||
"parent": "card-2",
|
||||
"left": 108, "top": 266, "width": 8, "height": 8,
|
||||
"fillColor": "#E87D7D",
|
||||
"strokeColor": "#E87D7D"
|
||||
},
|
||||
"card-2-id": {
|
||||
"type": "Text",
|
||||
"parent": "card-2",
|
||||
"left": 122, "top": 262,
|
||||
"text": "T-19",
|
||||
"fontColor": "#e8e8ee",
|
||||
"fontSize": 11
|
||||
},
|
||||
"card-2-title": {
|
||||
"type": "Text",
|
||||
"parent": "card-2",
|
||||
"left": 108, "top": 282,
|
||||
"text": "Filter box loses focus on refresh tick",
|
||||
"fontColor": "#b8b8c2",
|
||||
"fontSize": 11
|
||||
},
|
||||
|
||||
"caption": {
|
||||
"type": "Text",
|
||||
"parent": "panel",
|
||||
"left": 96, "top": 540,
|
||||
"text": "All four type filters ON by default — tap a chip to toggle that type out.",
|
||||
"fontColor": "#56565f",
|
||||
"fontSize": 10
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
Reference in New Issue
Block a user