@sascha384/tic 5.16.0 → 5.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/dist/backends/ado/index.js +1 -1
- package/dist/backends/ado/index.js.map +1 -1
- package/dist/backends/ado/mappers.d.ts +2 -2
- package/dist/backends/ado/mappers.js +7 -2
- package/dist/backends/ado/mappers.js.map +1 -1
- package/dist/backends/files/index.d.ts +6 -0
- package/dist/backends/files/index.js +36 -0
- package/dist/backends/files/index.js.map +1 -1
- package/dist/backends/files/sync.d.ts +2 -2
- package/dist/backends/files/sync.js +9 -7
- package/dist/backends/files/sync.js.map +1 -1
- package/dist/backends/github/index.js +3 -3
- package/dist/backends/github/index.js.map +1 -1
- package/dist/backends/github/mappers.js +2 -1
- package/dist/backends/github/mappers.js.map +1 -1
- package/dist/backends/github/pr-mappers.d.ts +1 -1
- package/dist/backends/github/pr-mappers.js +1 -1
- package/dist/backends/github/pr-mappers.js.map +1 -1
- package/dist/backends/gitlab/index.js +13 -6
- package/dist/backends/gitlab/index.js.map +1 -1
- package/dist/backends/gitlab/mappers.js +2 -1
- package/dist/backends/gitlab/mappers.js.map +1 -1
- package/dist/backends/jira/index.js +2 -2
- package/dist/backends/jira/index.js.map +1 -1
- package/dist/backends/jira/mappers.d.ts +1 -1
- package/dist/backends/jira/mappers.js +5 -4
- package/dist/backends/jira/mappers.js.map +1 -1
- package/dist/backends/local/items.js +9 -2
- package/dist/backends/local/items.js.map +1 -1
- package/dist/backends/types.d.ts +2 -3
- package/dist/backends/types.js +8 -2
- package/dist/backends/types.js.map +1 -1
- package/dist/cli/commands/config.js +0 -1
- package/dist/cli/commands/config.js.map +1 -1
- package/dist/cli/commands/item.js +45 -17
- package/dist/cli/commands/item.js.map +1 -1
- package/dist/cli/commands/mcp.js +24 -9
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/cli/commands/pr.js +12 -6
- package/dist/cli/commands/pr.js.map +1 -1
- package/dist/cli/index.js +13 -6
- package/dist/cli/index.js.map +1 -1
- package/dist/components/BranchList.js +4 -2
- package/dist/components/BranchList.js.map +1 -1
- package/dist/components/CommandBar.js +8 -7
- package/dist/components/CommandBar.js.map +1 -1
- package/dist/components/DetailPanel.js +2 -2
- package/dist/components/DetailPanel.js.map +1 -1
- package/dist/components/Settings.js +1 -1
- package/dist/components/Settings.js.map +1 -1
- package/dist/components/StatusScreen.js +2 -2
- package/dist/components/StatusScreen.js.map +1 -1
- package/dist/components/WorkItemForm.js +107 -73
- package/dist/components/WorkItemForm.js.map +1 -1
- package/dist/components/WorkItemList.d.ts +5 -3
- package/dist/components/WorkItemList.js +175 -124
- package/dist/components/WorkItemList.js.map +1 -1
- package/dist/components/buildTree.js +15 -13
- package/dist/components/buildTree.js.map +1 -1
- package/dist/components/fuzzyMatch.js +1 -1
- package/dist/components/fuzzyMatch.js.map +1 -1
- package/dist/components/getMarkedDistribution.d.ts +2 -2
- package/dist/components/getMarkedDistribution.js +1 -1
- package/dist/components/getMarkedDistribution.js.map +1 -1
- package/dist/git.d.ts +2 -1
- package/dist/hooks/useFormValidation.js +31 -21
- package/dist/hooks/useFormValidation.js.map +1 -1
- package/dist/implement.js +3 -3
- package/dist/implement.js.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/storage/config.d.ts +0 -1
- package/dist/storage/config.js +0 -6
- package/dist/storage/config.js.map +1 -1
- package/dist/storage/index.d.ts +25 -6
- package/dist/storage/index.js +304 -183
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/mappers.d.ts +1 -1
- package/dist/storage/mappers.js +5 -3
- package/dist/storage/mappers.js.map +1 -1
- package/dist/storage/schema.d.ts +83 -380
- package/dist/storage/schema.js +27 -55
- package/dist/storage/schema.js.map +1 -1
- package/dist/storage/syncQueue.d.ts +2 -3
- package/dist/storage/syncQueue.js +10 -17
- package/dist/storage/syncQueue.js.map +1 -1
- package/dist/storage/undo.js +7 -6
- package/dist/storage/undo.js.map +1 -1
- package/dist/stores/backendDataStore.js +3 -1
- package/dist/stores/backendDataStore.js.map +1 -1
- package/dist/stores/formStackStore.d.ts +1 -1
- package/dist/stores/listViewStore.d.ts +6 -6
- package/dist/stores/navigationStore.d.ts +7 -7
- package/dist/stores/undoStore.d.ts +2 -2
- package/dist/sync/SyncManager.d.ts +6 -1
- package/dist/sync/SyncManager.js +80 -76
- package/dist/sync/SyncManager.js.map +1 -1
- package/dist/sync/types.d.ts +6 -7
- package/dist/test-helpers.d.ts +1 -1
- package/dist/test-helpers.js +11 -8
- package/dist/test-helpers.js.map +1 -1
- package/dist/types.d.ts +6 -5
- package/drizzle/0006_dual_id.sql +173 -0
- package/drizzle/meta/_journal.json +7 -0
- package/package.json +1 -1
|
@@ -37,7 +37,7 @@ function buildWorkItemColumns(capabilities, collapsedIds, selectionFg) {
|
|
|
37
37
|
width: 4, // overridden dynamically via useMemo
|
|
38
38
|
required: true,
|
|
39
39
|
sortable: true,
|
|
40
|
-
render: (ti, selected) => (_jsx(Text, { color: selected ? selectionFg : undefined, bold: selected, dimColor: ti.isCrossType && !selected, children: ti.item.id })),
|
|
40
|
+
render: (ti, selected) => (_jsx(Text, { color: selected ? selectionFg : undefined, bold: selected, dimColor: ti.isCrossType && !selected, children: ti.item.id ?? '\u00B7' })),
|
|
41
41
|
});
|
|
42
42
|
// Title column (flex)
|
|
43
43
|
columns.push({
|
|
@@ -49,7 +49,7 @@ function buildWorkItemColumns(capabilities, collapsedIds, selectionFg) {
|
|
|
49
49
|
render: (ti, selected) => {
|
|
50
50
|
const { item, prefix, isCrossType, hasChildren } = ti;
|
|
51
51
|
const collapseIndicator = hasChildren
|
|
52
|
-
? collapsedIds.has(item.
|
|
52
|
+
? collapsedIds.has(item.rowId)
|
|
53
53
|
? '\u25B6 '
|
|
54
54
|
: '\u25BC '
|
|
55
55
|
: ' ';
|
|
@@ -124,11 +124,26 @@ function buildWorkItemColumns(capabilities, collapsedIds, selectionFg) {
|
|
|
124
124
|
}
|
|
125
125
|
return columns;
|
|
126
126
|
}
|
|
127
|
-
|
|
127
|
+
/** Get display IDs (strings) for target items. Used for backend API calls. */
|
|
128
|
+
export function getTargetIds(markedIds, cursorItem, allItems) {
|
|
129
|
+
if (markedIds.size > 0) {
|
|
130
|
+
// Look up display IDs from rowIds
|
|
131
|
+
const ids = [];
|
|
132
|
+
for (const rowId of markedIds) {
|
|
133
|
+
const item = allItems.find((i) => i.rowId === rowId);
|
|
134
|
+
if (item?.id)
|
|
135
|
+
ids.push(item.id);
|
|
136
|
+
}
|
|
137
|
+
return ids;
|
|
138
|
+
}
|
|
139
|
+
return cursorItem?.id ? [cursorItem.id] : [];
|
|
140
|
+
}
|
|
141
|
+
/** Get rowIds for target items. Used for undo entries and store operations. */
|
|
142
|
+
export function getTargetRowIds(markedIds, cursorItem) {
|
|
128
143
|
if (markedIds.size > 0) {
|
|
129
144
|
return [...markedIds];
|
|
130
145
|
}
|
|
131
|
-
return cursorItem ? [cursorItem.
|
|
146
|
+
return cursorItem ? [cursorItem.rowId] : [];
|
|
132
147
|
}
|
|
133
148
|
export function WorkItemList() {
|
|
134
149
|
const { accent, success, error: errorColor, warning: warningColor, marked, mutedDim, selectionBg, } = useThemeStore((s) => s.colors);
|
|
@@ -250,11 +265,16 @@ export function WorkItemList() {
|
|
|
250
265
|
}
|
|
251
266
|
}, [savedViews, defaultView]);
|
|
252
267
|
const queue = useBackendDataStore((s) => s.queue);
|
|
253
|
-
|
|
268
|
+
/** Look up the rowId for a display ID. Returns -1 if not found. */
|
|
269
|
+
const rowIdOf = (displayId) => {
|
|
270
|
+
const item = allItems.find((i) => i.id === displayId);
|
|
271
|
+
return item?.rowId ?? -1;
|
|
272
|
+
};
|
|
273
|
+
const queueWrite = async (action, itemRowId) => {
|
|
254
274
|
if (queue) {
|
|
255
275
|
await queue.append({
|
|
256
276
|
action,
|
|
257
|
-
|
|
277
|
+
itemRowId,
|
|
258
278
|
timestamp: new Date().toISOString(),
|
|
259
279
|
});
|
|
260
280
|
syncManager?.pushPending().catch((err) => {
|
|
@@ -272,7 +292,7 @@ export function WorkItemList() {
|
|
|
272
292
|
type: 'update',
|
|
273
293
|
label,
|
|
274
294
|
itemSnapshots: snapshots,
|
|
275
|
-
|
|
295
|
+
syncItemRowIds: snapshots.map((s) => s.rowId),
|
|
276
296
|
syncAction: 'update',
|
|
277
297
|
});
|
|
278
298
|
};
|
|
@@ -307,14 +327,16 @@ export function WorkItemList() {
|
|
|
307
327
|
capabilities.relationships,
|
|
308
328
|
sortStack,
|
|
309
329
|
]);
|
|
310
|
-
const parentSuggestions = useMemo(() => allItems
|
|
330
|
+
const parentSuggestions = useMemo(() => allItems
|
|
331
|
+
.filter((item) => item.id !== null)
|
|
332
|
+
.map((item) => `${item.id} - ${item.title}`), [allItems]);
|
|
311
333
|
// Collapse state: set of item IDs that are collapsed (collapsed by default)
|
|
312
334
|
// Track explicitly expanded items (inverse of collapsed).
|
|
313
335
|
// All parents are collapsed by default; expanding removes from this set.
|
|
314
336
|
// expandedIds comes from listViewStore (imported above)
|
|
315
337
|
// Derive collapsedIds: all parents minus explicitly expanded ones
|
|
316
338
|
const collapsedIds = useMemo(() => {
|
|
317
|
-
const parentIds = new Set(fullTree.filter((t) => t.hasChildren).map((t) => t.item.
|
|
339
|
+
const parentIds = new Set(fullTree.filter((t) => t.hasChildren).map((t) => t.item.rowId));
|
|
318
340
|
const collapsed = new Set();
|
|
319
341
|
for (const id of parentIds) {
|
|
320
342
|
if (!expandedIds.has(id)) {
|
|
@@ -332,7 +354,7 @@ export function WorkItemList() {
|
|
|
332
354
|
continue;
|
|
333
355
|
skipDepth = null;
|
|
334
356
|
result.push(t);
|
|
335
|
-
if (collapsedIds.has(t.item.
|
|
357
|
+
if (collapsedIds.has(t.item.rowId)) {
|
|
336
358
|
skipDepth = t.depth;
|
|
337
359
|
}
|
|
338
360
|
}
|
|
@@ -388,14 +410,15 @@ export function WorkItemList() {
|
|
|
388
410
|
}
|
|
389
411
|
if (key.return) {
|
|
390
412
|
const item = treeItems[cursor]?.item;
|
|
391
|
-
if (item) {
|
|
413
|
+
if (item && item.id) {
|
|
414
|
+
const displayId = item.id;
|
|
392
415
|
editorStore.getState().init(item.description ?? '', {
|
|
393
416
|
returnScreen: 'list',
|
|
394
417
|
onSave: (content) => {
|
|
395
418
|
const state = backendDataStore.getState();
|
|
396
419
|
if (state.backend) {
|
|
397
420
|
void state.backend
|
|
398
|
-
.cachedUpdateWorkItem(
|
|
421
|
+
.cachedUpdateWorkItem(displayId, { description: content })
|
|
399
422
|
.then(() => backendDataStore.getState().refresh());
|
|
400
423
|
}
|
|
401
424
|
},
|
|
@@ -451,7 +474,7 @@ export function WorkItemList() {
|
|
|
451
474
|
setCursor(newCursor);
|
|
452
475
|
const start = Math.min(anchor, newCursor);
|
|
453
476
|
const end = Math.max(anchor, newCursor);
|
|
454
|
-
setMarkedIds(new Set(treeItems.slice(start, end + 1).map((t) => t.item.
|
|
477
|
+
setMarkedIds(new Set(treeItems.slice(start, end + 1).map((t) => t.item.rowId)));
|
|
455
478
|
clearWarning();
|
|
456
479
|
}
|
|
457
480
|
if (matchesCommand('list-navigate', input, key)) {
|
|
@@ -487,18 +510,18 @@ export function WorkItemList() {
|
|
|
487
510
|
const current = treeItems[cursor];
|
|
488
511
|
if (current &&
|
|
489
512
|
current.hasChildren &&
|
|
490
|
-
collapsedIds.has(current.item.
|
|
491
|
-
toggleExpanded(current.item.
|
|
513
|
+
collapsedIds.has(current.item.rowId)) {
|
|
514
|
+
toggleExpanded(current.item.rowId);
|
|
492
515
|
}
|
|
493
516
|
}
|
|
494
517
|
if (matchesCommand('list-collapse', input, key) && treeItems.length > 0) {
|
|
495
518
|
const current = treeItems[cursor];
|
|
496
519
|
if (current) {
|
|
497
|
-
if (current.hasChildren && !collapsedIds.has(current.item.
|
|
498
|
-
toggleExpanded(current.item.
|
|
520
|
+
if (current.hasChildren && !collapsedIds.has(current.item.rowId)) {
|
|
521
|
+
toggleExpanded(current.item.rowId);
|
|
499
522
|
}
|
|
500
523
|
else if (current.depth > 0 && current.item.parent) {
|
|
501
|
-
const parentIdx = treeItems.findIndex((t) => t.item.
|
|
524
|
+
const parentIdx = treeItems.findIndex((t) => t.item.rowId === current.item.parent);
|
|
502
525
|
if (parentIdx >= 0)
|
|
503
526
|
setCursor(parentIdx);
|
|
504
527
|
}
|
|
@@ -506,7 +529,7 @@ export function WorkItemList() {
|
|
|
506
529
|
}
|
|
507
530
|
if (matchesCommand('edit', input, key) && treeItems.length > 0) {
|
|
508
531
|
setFormMode('item');
|
|
509
|
-
selectWorkItem(treeItems[cursor].item.
|
|
532
|
+
selectWorkItem(treeItems[cursor].item.rowId);
|
|
510
533
|
navigate('form');
|
|
511
534
|
}
|
|
512
535
|
if (matchesCommand('quit', input, key))
|
|
@@ -514,7 +537,7 @@ export function WorkItemList() {
|
|
|
514
537
|
if (matchesCommand('set-iteration', input, key) &&
|
|
515
538
|
capabilities.iterations &&
|
|
516
539
|
treeItems.length > 0) {
|
|
517
|
-
const targetIds = getTargetIds(markedIds, treeItems[cursor]?.item);
|
|
540
|
+
const targetIds = getTargetIds(markedIds, treeItems[cursor]?.item, allItems);
|
|
518
541
|
if (targetIds.length > 0) {
|
|
519
542
|
openOverlay({ type: 'iteration-picker', targetIds });
|
|
520
543
|
}
|
|
@@ -554,14 +577,14 @@ export function WorkItemList() {
|
|
|
554
577
|
formStackStore.getState().clear();
|
|
555
578
|
navigationStore
|
|
556
579
|
.getState()
|
|
557
|
-
.setCreateChildParentId(treeItems[cursor].item.
|
|
580
|
+
.setCreateChildParentId(treeItems[cursor].item.rowId);
|
|
558
581
|
setFormMode('item');
|
|
559
582
|
setActiveTemplate(null);
|
|
560
583
|
selectWorkItem(null);
|
|
561
584
|
navigate('form');
|
|
562
585
|
}
|
|
563
586
|
if (matchesCommand('delete', input, key) && treeItems.length > 0) {
|
|
564
|
-
const targetIds = getTargetIds(markedIds, treeItems[cursor]?.item);
|
|
587
|
+
const targetIds = getTargetIds(markedIds, treeItems[cursor]?.item, allItems);
|
|
565
588
|
if (targetIds.length > 0) {
|
|
566
589
|
openOverlay({ type: 'delete-confirm', targetIds });
|
|
567
590
|
}
|
|
@@ -574,38 +597,42 @@ export function WorkItemList() {
|
|
|
574
597
|
if (entry.type === 'delete') {
|
|
575
598
|
if (isSoftDeleteBackend(backend)) {
|
|
576
599
|
for (const snap of entry.itemSnapshots) {
|
|
577
|
-
|
|
600
|
+
if (snap.id)
|
|
601
|
+
await backend.restoreWorkItem(snap.id);
|
|
578
602
|
}
|
|
579
603
|
}
|
|
580
604
|
if (queue) {
|
|
581
|
-
await queue.
|
|
605
|
+
await queue.removeByRowIds(entry.syncItemRowIds, 'delete');
|
|
582
606
|
}
|
|
583
607
|
refreshData();
|
|
584
608
|
setToast(entry.itemSnapshots.length === 1
|
|
585
|
-
? `Restored #${entry.itemSnapshots[0].id}`
|
|
609
|
+
? `Restored #${entry.itemSnapshots[0].id ?? entry.itemSnapshots[0].rowId}`
|
|
586
610
|
: `Restored ${entry.itemSnapshots.length} items`);
|
|
587
611
|
}
|
|
588
612
|
else if (entry.type === 'create') {
|
|
589
|
-
for (const
|
|
590
|
-
|
|
613
|
+
for (const rowId of entry.createdRowIds ?? []) {
|
|
614
|
+
const item = allItems.find((i) => i.rowId === rowId);
|
|
615
|
+
if (item?.id)
|
|
616
|
+
await backend.cachedDeleteWorkItem(item.id);
|
|
591
617
|
}
|
|
592
618
|
if (queue) {
|
|
593
|
-
await queue.
|
|
619
|
+
await queue.removeByRowIds(entry.syncItemRowIds, 'create');
|
|
594
620
|
}
|
|
595
621
|
refreshData();
|
|
596
|
-
setToast((entry.
|
|
597
|
-
? `Undid create #${entry.
|
|
598
|
-
: `Undid create of ${entry.
|
|
622
|
+
setToast((entry.createdRowIds?.length ?? 0) === 1
|
|
623
|
+
? `Undid create #${entry.createdRowIds?.[0]}`
|
|
624
|
+
: `Undid create of ${entry.createdRowIds?.length} items`);
|
|
599
625
|
}
|
|
600
626
|
else if (entry.type === 'update') {
|
|
601
627
|
for (const snap of entry.itemSnapshots) {
|
|
602
|
-
|
|
628
|
+
if (snap.id)
|
|
629
|
+
await backend.cachedUpdateWorkItem(snap.id, snap);
|
|
603
630
|
}
|
|
604
631
|
if (queue) {
|
|
605
|
-
await queue.
|
|
632
|
+
await queue.removeByRowIds(entry.syncItemRowIds, 'update');
|
|
606
633
|
}
|
|
607
634
|
for (const snap of entry.itemSnapshots) {
|
|
608
|
-
await queueWrite('update', snap.
|
|
635
|
+
await queueWrite('update', snap.rowId);
|
|
609
636
|
}
|
|
610
637
|
refreshData();
|
|
611
638
|
setToast(`Undid ${entry.label}`);
|
|
@@ -618,39 +645,44 @@ export function WorkItemList() {
|
|
|
618
645
|
}
|
|
619
646
|
if (matchesCommand('open', input, key) && treeItems.length > 0) {
|
|
620
647
|
setFormMode('item');
|
|
621
|
-
selectWorkItem(treeItems[cursor].item.
|
|
648
|
+
selectWorkItem(treeItems[cursor].item.rowId);
|
|
622
649
|
navigate('form');
|
|
623
650
|
}
|
|
624
651
|
if (matchesCommand('branch', input, key) &&
|
|
625
652
|
gitAvailable &&
|
|
626
653
|
treeItems.length > 0) {
|
|
627
654
|
const item = treeItems[cursor].item;
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
const itemUrl = backend?.getItemUrl(item.id) || '';
|
|
631
|
-
// Suspend terminal for interactive child process
|
|
632
|
-
process.stdin.setRawMode?.(false);
|
|
633
|
-
const result = beginImplementation(item, comments, { branchMode, branchCommand, copyToClipboard }, process.cwd(), { itemUrl });
|
|
634
|
-
// Restore terminal after interactive shell
|
|
635
|
-
process.stdin.setRawMode?.(true);
|
|
636
|
-
console.clear();
|
|
637
|
-
let msg = result.resumed
|
|
638
|
-
? `Resumed work on #${item.id}`
|
|
639
|
-
: `Started work on #${item.id}`;
|
|
640
|
-
if (result.commandFailed) {
|
|
641
|
-
msg += ' (branch command failed, fell back to shell)';
|
|
642
|
-
}
|
|
643
|
-
setWarning(msg);
|
|
655
|
+
if (!item.id) {
|
|
656
|
+
setWarning('Cannot create branch for item without display ID');
|
|
644
657
|
}
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
658
|
+
else {
|
|
659
|
+
const comments = item.comments;
|
|
660
|
+
try {
|
|
661
|
+
const itemUrl = backend?.getItemUrl(item.id) || '';
|
|
662
|
+
// Suspend terminal for interactive child process
|
|
663
|
+
process.stdin.setRawMode?.(false);
|
|
664
|
+
const result = beginImplementation(item, comments, { branchMode, branchCommand, copyToClipboard }, process.cwd(), { itemUrl });
|
|
665
|
+
// Restore terminal after interactive shell
|
|
666
|
+
process.stdin.setRawMode?.(true);
|
|
667
|
+
console.clear();
|
|
668
|
+
let msg = result.resumed
|
|
669
|
+
? `Resumed work on #${item.id}`
|
|
670
|
+
: `Started work on #${item.id}`;
|
|
671
|
+
if (result.commandFailed) {
|
|
672
|
+
msg += ' (branch command failed, fell back to shell)';
|
|
673
|
+
}
|
|
674
|
+
setWarning(msg);
|
|
675
|
+
}
|
|
676
|
+
catch (e) {
|
|
677
|
+
process.stdin.setRawMode?.(true);
|
|
678
|
+
console.clear();
|
|
679
|
+
setWarning(e instanceof Error ? e.message : 'Failed to start implementation');
|
|
680
|
+
}
|
|
681
|
+
void backendDataStore
|
|
682
|
+
.getState()
|
|
683
|
+
.reloadItem(item.id)
|
|
684
|
+
.catch(() => { });
|
|
649
685
|
}
|
|
650
|
-
void backendDataStore
|
|
651
|
-
.getState()
|
|
652
|
-
.reloadItem(item.id)
|
|
653
|
-
.catch(() => { });
|
|
654
686
|
}
|
|
655
687
|
if (matchesCommand('status', input, key)) {
|
|
656
688
|
navigate('status');
|
|
@@ -669,7 +701,7 @@ export function WorkItemList() {
|
|
|
669
701
|
setToast('Filters cleared');
|
|
670
702
|
}
|
|
671
703
|
if (matchesCommand('list-status', input, key) && treeItems.length > 0) {
|
|
672
|
-
const targetIds = getTargetIds(markedIds, treeItems[cursor]?.item);
|
|
704
|
+
const targetIds = getTargetIds(markedIds, treeItems[cursor]?.item, allItems);
|
|
673
705
|
if (targetIds.length > 0) {
|
|
674
706
|
openOverlay({ type: 'status-picker', targetIds });
|
|
675
707
|
}
|
|
@@ -690,7 +722,7 @@ export function WorkItemList() {
|
|
|
690
722
|
prCapabilities.create &&
|
|
691
723
|
treeItems.length > 0) {
|
|
692
724
|
const item = treeItems[cursor]?.item;
|
|
693
|
-
if (item) {
|
|
725
|
+
if (item && item.id) {
|
|
694
726
|
const cwd = process.cwd();
|
|
695
727
|
const currentBranch = getCurrentBranch(cwd);
|
|
696
728
|
const expectedBranch = `tic/${slugify(item.id, item.title)}`;
|
|
@@ -700,7 +732,7 @@ export function WorkItemList() {
|
|
|
700
732
|
.createPullRequest({
|
|
701
733
|
title: item.title,
|
|
702
734
|
sourceBranch,
|
|
703
|
-
linkedItems: [item.
|
|
735
|
+
linkedItems: [item.rowId],
|
|
704
736
|
})
|
|
705
737
|
.then((pr) => {
|
|
706
738
|
setToast(`PR #${String(pr.number)} created`);
|
|
@@ -731,12 +763,12 @@ export function WorkItemList() {
|
|
|
731
763
|
}
|
|
732
764
|
if (matchesCommand('mark', input, key) && treeItems.length > 0) {
|
|
733
765
|
setRangeAnchor(null);
|
|
734
|
-
const
|
|
735
|
-
toggleMarked(
|
|
766
|
+
const itemRowId = treeItems[cursor].item.rowId;
|
|
767
|
+
toggleMarked(itemRowId);
|
|
736
768
|
}
|
|
737
769
|
if (matchesCommand('clear-marks', input, key) && treeItems.length > 0) {
|
|
738
770
|
setRangeAnchor(null);
|
|
739
|
-
const visibleIds = treeItems.map((t) => t.item.
|
|
771
|
+
const visibleIds = treeItems.map((t) => t.item.rowId);
|
|
740
772
|
const allMarked = visibleIds.every((id) => markedIds.has(id));
|
|
741
773
|
if (allMarked) {
|
|
742
774
|
clearMarked();
|
|
@@ -751,7 +783,7 @@ export function WorkItemList() {
|
|
|
751
783
|
if (matchesCommand('set-priority', input, key) &&
|
|
752
784
|
capabilities.fields.priority &&
|
|
753
785
|
treeItems.length > 0) {
|
|
754
|
-
const targetIds = getTargetIds(markedIds, treeItems[cursor]?.item);
|
|
786
|
+
const targetIds = getTargetIds(markedIds, treeItems[cursor]?.item, allItems);
|
|
755
787
|
if (targetIds.length > 0) {
|
|
756
788
|
openOverlay({ type: 'priority-picker', targetIds });
|
|
757
789
|
}
|
|
@@ -759,7 +791,7 @@ export function WorkItemList() {
|
|
|
759
791
|
if (matchesCommand('list-parent', input, key) &&
|
|
760
792
|
capabilities.fields.parent &&
|
|
761
793
|
treeItems.length > 0) {
|
|
762
|
-
const targetIds = getTargetIds(markedIds, treeItems[cursor]?.item);
|
|
794
|
+
const targetIds = getTargetIds(markedIds, treeItems[cursor]?.item, allItems);
|
|
763
795
|
if (targetIds.length > 0) {
|
|
764
796
|
openOverlay({ type: 'parent-input', targetIds });
|
|
765
797
|
}
|
|
@@ -767,7 +799,7 @@ export function WorkItemList() {
|
|
|
767
799
|
if (matchesCommand('set-assignee', input, key) &&
|
|
768
800
|
capabilities.fields.assignee &&
|
|
769
801
|
treeItems.length > 0) {
|
|
770
|
-
const targetIds = getTargetIds(markedIds, treeItems[cursor]?.item);
|
|
802
|
+
const targetIds = getTargetIds(markedIds, treeItems[cursor]?.item, allItems);
|
|
771
803
|
if (targetIds.length > 0) {
|
|
772
804
|
openOverlay({ type: 'assignee-input', targetIds });
|
|
773
805
|
}
|
|
@@ -775,7 +807,7 @@ export function WorkItemList() {
|
|
|
775
807
|
if (matchesCommand('set-labels', input, key) &&
|
|
776
808
|
capabilities.fields.labels &&
|
|
777
809
|
treeItems.length > 0) {
|
|
778
|
-
const targetIds = getTargetIds(markedIds, treeItems[cursor]?.item);
|
|
810
|
+
const targetIds = getTargetIds(markedIds, treeItems[cursor]?.item, allItems);
|
|
779
811
|
if (targetIds.length > 0) {
|
|
780
812
|
openOverlay({ type: 'labels-input', targetIds });
|
|
781
813
|
}
|
|
@@ -783,7 +815,7 @@ export function WorkItemList() {
|
|
|
783
815
|
if (matchesCommand('set-type', input, key) &&
|
|
784
816
|
capabilities.customTypes &&
|
|
785
817
|
treeItems.length > 0) {
|
|
786
|
-
const targetIds = getTargetIds(markedIds, treeItems[cursor]?.item);
|
|
818
|
+
const targetIds = getTargetIds(markedIds, treeItems[cursor]?.item, allItems);
|
|
787
819
|
if (targetIds.length > 0) {
|
|
788
820
|
openOverlay({ type: 'type-picker', targetIds });
|
|
789
821
|
}
|
|
@@ -962,20 +994,20 @@ export function WorkItemList() {
|
|
|
962
994
|
if (treeItems[cursor]) {
|
|
963
995
|
navigationStore
|
|
964
996
|
.getState()
|
|
965
|
-
.setCreateChildParentId(treeItems[cursor].item.
|
|
997
|
+
.setCreateChildParentId(treeItems[cursor].item.rowId);
|
|
966
998
|
selectWorkItem(null);
|
|
967
999
|
navigate('form');
|
|
968
1000
|
}
|
|
969
1001
|
break;
|
|
970
1002
|
case 'edit':
|
|
971
1003
|
if (treeItems[cursor]) {
|
|
972
|
-
selectWorkItem(treeItems[cursor].item.
|
|
1004
|
+
selectWorkItem(treeItems[cursor].item.rowId);
|
|
973
1005
|
navigate('form');
|
|
974
1006
|
}
|
|
975
1007
|
break;
|
|
976
1008
|
case 'delete':
|
|
977
1009
|
if (treeItems.length > 0) {
|
|
978
|
-
const targetIds = getTargetIds(markedIds, treeItems[cursor]?.item);
|
|
1010
|
+
const targetIds = getTargetIds(markedIds, treeItems[cursor]?.item, allItems);
|
|
979
1011
|
if (targetIds.length > 0) {
|
|
980
1012
|
openOverlay({ type: 'delete-confirm', targetIds });
|
|
981
1013
|
}
|
|
@@ -984,37 +1016,44 @@ export function WorkItemList() {
|
|
|
984
1016
|
case 'open':
|
|
985
1017
|
if (treeItems[cursor]) {
|
|
986
1018
|
setFormMode('item');
|
|
987
|
-
selectWorkItem(treeItems[cursor].item.
|
|
1019
|
+
selectWorkItem(treeItems[cursor].item.rowId);
|
|
988
1020
|
navigate('form');
|
|
989
1021
|
}
|
|
990
1022
|
break;
|
|
991
1023
|
case 'branch':
|
|
992
1024
|
if (treeItems[cursor]) {
|
|
993
1025
|
const item = treeItems[cursor].item;
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
const itemUrl = backend?.getItemUrl(item.id) || '';
|
|
997
|
-
process.stdin.setRawMode?.(false);
|
|
998
|
-
const result = beginImplementation(item, comments, { branchMode, branchCommand, copyToClipboard }, process.cwd(), { itemUrl });
|
|
999
|
-
process.stdin.setRawMode?.(true);
|
|
1000
|
-
console.clear();
|
|
1001
|
-
let msg = result.resumed
|
|
1002
|
-
? `Resumed work on #${item.id}`
|
|
1003
|
-
: `Started work on #${item.id}`;
|
|
1004
|
-
if (result.commandFailed) {
|
|
1005
|
-
msg += ' (branch command failed, fell back to shell)';
|
|
1006
|
-
}
|
|
1007
|
-
setWarning(msg);
|
|
1026
|
+
if (!item.id) {
|
|
1027
|
+
setWarning('Cannot create branch for item without display ID');
|
|
1008
1028
|
}
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1029
|
+
else {
|
|
1030
|
+
const comments = item.comments;
|
|
1031
|
+
try {
|
|
1032
|
+
const itemUrl = backend?.getItemUrl(item.id) || '';
|
|
1033
|
+
process.stdin.setRawMode?.(false);
|
|
1034
|
+
const result = beginImplementation(item, comments, { branchMode, branchCommand, copyToClipboard }, process.cwd(), { itemUrl });
|
|
1035
|
+
process.stdin.setRawMode?.(true);
|
|
1036
|
+
console.clear();
|
|
1037
|
+
let msg = result.resumed
|
|
1038
|
+
? `Resumed work on #${item.id}`
|
|
1039
|
+
: `Started work on #${item.id}`;
|
|
1040
|
+
if (result.commandFailed) {
|
|
1041
|
+
msg += ' (branch command failed, fell back to shell)';
|
|
1042
|
+
}
|
|
1043
|
+
setWarning(msg);
|
|
1044
|
+
}
|
|
1045
|
+
catch (e) {
|
|
1046
|
+
process.stdin.setRawMode?.(true);
|
|
1047
|
+
console.clear();
|
|
1048
|
+
setWarning(e instanceof Error
|
|
1049
|
+
? e.message
|
|
1050
|
+
: 'Failed to start implementation');
|
|
1051
|
+
}
|
|
1052
|
+
void backendDataStore
|
|
1053
|
+
.getState()
|
|
1054
|
+
.reloadItem(item.id)
|
|
1055
|
+
.catch(() => { });
|
|
1013
1056
|
}
|
|
1014
|
-
void backendDataStore
|
|
1015
|
-
.getState()
|
|
1016
|
-
.reloadItem(item.id)
|
|
1017
|
-
.catch(() => { });
|
|
1018
1057
|
}
|
|
1019
1058
|
break;
|
|
1020
1059
|
case 'sync':
|
|
@@ -1029,7 +1068,7 @@ export function WorkItemList() {
|
|
|
1029
1068
|
break;
|
|
1030
1069
|
case 'set-iteration':
|
|
1031
1070
|
if (treeItems.length > 0) {
|
|
1032
|
-
const targetIds = getTargetIds(markedIds, treeItems[cursor]?.item);
|
|
1071
|
+
const targetIds = getTargetIds(markedIds, treeItems[cursor]?.item, allItems);
|
|
1033
1072
|
if (targetIds.length > 0) {
|
|
1034
1073
|
openOverlay({ type: 'iteration-picker', targetIds });
|
|
1035
1074
|
}
|
|
@@ -1049,8 +1088,8 @@ export function WorkItemList() {
|
|
|
1049
1088
|
break;
|
|
1050
1089
|
case 'mark':
|
|
1051
1090
|
if (treeItems[cursor]) {
|
|
1052
|
-
const
|
|
1053
|
-
toggleMarked(
|
|
1091
|
+
const itemRowId = treeItems[cursor].item.rowId;
|
|
1092
|
+
toggleMarked(itemRowId);
|
|
1054
1093
|
}
|
|
1055
1094
|
break;
|
|
1056
1095
|
case 'clear-marks':
|
|
@@ -1058,7 +1097,7 @@ export function WorkItemList() {
|
|
|
1058
1097
|
break;
|
|
1059
1098
|
case 'set-priority':
|
|
1060
1099
|
{
|
|
1061
|
-
const targetIds = getTargetIds(markedIds, treeItems[cursor]?.item);
|
|
1100
|
+
const targetIds = getTargetIds(markedIds, treeItems[cursor]?.item, allItems);
|
|
1062
1101
|
if (targetIds.length > 0) {
|
|
1063
1102
|
openOverlay({ type: 'priority-picker', targetIds });
|
|
1064
1103
|
}
|
|
@@ -1066,7 +1105,7 @@ export function WorkItemList() {
|
|
|
1066
1105
|
break;
|
|
1067
1106
|
case 'set-assignee':
|
|
1068
1107
|
{
|
|
1069
|
-
const targetIds = getTargetIds(markedIds, treeItems[cursor]?.item);
|
|
1108
|
+
const targetIds = getTargetIds(markedIds, treeItems[cursor]?.item, allItems);
|
|
1070
1109
|
if (targetIds.length > 0) {
|
|
1071
1110
|
openOverlay({ type: 'assignee-input', targetIds });
|
|
1072
1111
|
}
|
|
@@ -1074,7 +1113,7 @@ export function WorkItemList() {
|
|
|
1074
1113
|
break;
|
|
1075
1114
|
case 'set-labels':
|
|
1076
1115
|
{
|
|
1077
|
-
const targetIds = getTargetIds(markedIds, treeItems[cursor]?.item);
|
|
1116
|
+
const targetIds = getTargetIds(markedIds, treeItems[cursor]?.item, allItems);
|
|
1078
1117
|
if (targetIds.length > 0) {
|
|
1079
1118
|
openOverlay({ type: 'labels-input', targetIds });
|
|
1080
1119
|
}
|
|
@@ -1082,7 +1121,7 @@ export function WorkItemList() {
|
|
|
1082
1121
|
break;
|
|
1083
1122
|
case 'set-type':
|
|
1084
1123
|
{
|
|
1085
|
-
const targetIds = getTargetIds(markedIds, treeItems[cursor]?.item);
|
|
1124
|
+
const targetIds = getTargetIds(markedIds, treeItems[cursor]?.item, allItems);
|
|
1086
1125
|
if (targetIds.length > 0) {
|
|
1087
1126
|
openOverlay({ type: 'type-picker', targetIds });
|
|
1088
1127
|
}
|
|
@@ -1125,7 +1164,7 @@ export function WorkItemList() {
|
|
|
1125
1164
|
}
|
|
1126
1165
|
};
|
|
1127
1166
|
const handleBulkAction = (action) => {
|
|
1128
|
-
const targetIds = getTargetIds(markedIds, treeItems[cursor]?.item);
|
|
1167
|
+
const targetIds = getTargetIds(markedIds, treeItems[cursor]?.item, allItems);
|
|
1129
1168
|
if (targetIds.length === 0)
|
|
1130
1169
|
return;
|
|
1131
1170
|
switch (action) {
|
|
@@ -1160,7 +1199,7 @@ export function WorkItemList() {
|
|
|
1160
1199
|
: '';
|
|
1161
1200
|
const visibleTreeItems = useMemo(() => treeItems.slice(viewport.start, viewport.end), [treeItems, viewport.start, viewport.end]);
|
|
1162
1201
|
const workItemColumns = useMemo(() => {
|
|
1163
|
-
const maxIdLen = visibleTreeItems.reduce((max, { item }) => Math.max(max, item.id.length), 2);
|
|
1202
|
+
const maxIdLen = visibleTreeItems.reduce((max, { item }) => Math.max(max, (item.id ?? '\u00B7').length), 2);
|
|
1164
1203
|
const cols = buildWorkItemColumns(capabilities, collapsedIds, autoFg(selectionBg));
|
|
1165
1204
|
cols[0].width = maxIdLen + 2;
|
|
1166
1205
|
return cols;
|
|
@@ -1174,7 +1213,7 @@ export function WorkItemList() {
|
|
|
1174
1213
|
? formatIterationDates(it.startDate, it.endDate)
|
|
1175
1214
|
: null;
|
|
1176
1215
|
return dates ? ` ${dates}` : '';
|
|
1177
|
-
})()] }), _jsx(Text, { dimColor: mutedDim, children: ` (${filterCount > 0 ? `${items.length}/${unfilteredCount}` : items.length} item${unfilteredCount === 1 ? '' : 's'})` }), markedCount > 0 && (_jsxs(Text, { color: marked, children: [` ● ${markedCount}`, markedDistribution.above > 0 && ` ↑${markedDistribution.above}`, markedDistribution.below > 0 && ` ↓${markedDistribution.below}`] })), filterCount > 0 && (_jsx(Text, { color: warningColor, children: ` [${filterCount} filter${filterCount === 1 ? '' : 's'}${activeViewName ? `: ${activeViewName}` : ''}]` }))] }) }), _jsx(TableLayout, { items: visibleTreeItems, columns: workItemColumns, cursor: viewport.visibleCursor, terminalWidth: terminalWidth, getKey: (ti) => `${ti.item.
|
|
1216
|
+
})()] }), _jsx(Text, { dimColor: mutedDim, children: ` (${filterCount > 0 ? `${items.length}/${unfilteredCount}` : items.length} item${unfilteredCount === 1 ? '' : 's'})` }), markedCount > 0 && (_jsxs(Text, { color: marked, children: [` ● ${markedCount}`, markedDistribution.above > 0 && ` ↑${markedDistribution.above}`, markedDistribution.below > 0 && ` ↓${markedDistribution.below}`] })), filterCount > 0 && (_jsx(Text, { color: warningColor, children: ` [${filterCount} filter${filterCount === 1 ? '' : 's'}${activeViewName ? `: ${activeViewName}` : ''}]` }))] }) }), _jsx(TableLayout, { items: visibleTreeItems, columns: workItemColumns, cursor: viewport.visibleCursor, terminalWidth: terminalWidth, getKey: (ti) => `${ti.item.rowId}-${ti.item.type}`, isMarked: (ti) => markedIds.has(ti.item.rowId), sortStack: sortStack }), treeItems.length === 0 && !loading && initError && (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { color: errorColor, children: "Failed to connect to backend:" }), _jsx(Box, { marginLeft: 2, children: _jsx(Text, { color: errorColor, children: initError }) }), _jsx(Text, { dimColor: mutedDim, children: "Press , for settings or q to quit." })] })), treeItems.length === 0 && !loading && !initError && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: mutedDim, children: ["No ", activeType ?? 'item', "s in this iteration. Press c to create, / to search all."] }) })), loading && treeItems.length === 0 && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: mutedDim, children: "Loading..." }) })), showDetailPanel && treeItems.length > 0 && treeItems[cursor] && (_jsx(Box, { marginTop: 1, children: _jsx(DetailPanel, { item: treeItems[cursor].item, terminalWidth: terminalWidth, showFullDescription: showFullDescription, descriptionScrollOffset: descriptionScrollOffset, maxDescriptionHeight: maxDescriptionHeight }) })), _jsx(Box, { marginTop: 1, children: showFullDescription ? (_jsxs(Box, { children: [_jsx(Text, { dimColor: mutedDim, children: "\u2191\u2193 scroll space/esc close" }), positionText && _jsxs(Text, { dimColor: mutedDim, children: [" ", positionText] })] })) : activeOverlay?.type === 'command-bar' ? (_jsx(CommandBar, { commands: paletteCommands, onCommand: handleCommandSelect, onCancel: closeOverlay })) : activeOverlay?.type === 'bulk-menu' ? ((() => {
|
|
1178
1217
|
const bulkItems = [];
|
|
1179
1218
|
bulkItems.push({
|
|
1180
1219
|
id: 'status',
|
|
@@ -1252,7 +1291,7 @@ export function WorkItemList() {
|
|
|
1252
1291
|
await backend.cachedUpdateWorkItem(id, {
|
|
1253
1292
|
status: item.value,
|
|
1254
1293
|
});
|
|
1255
|
-
await queueWrite('update', id);
|
|
1294
|
+
await queueWrite('update', rowIdOf(id));
|
|
1256
1295
|
}
|
|
1257
1296
|
for (const id of targetIds) {
|
|
1258
1297
|
await backendDataStore.getState().reloadItem(id);
|
|
@@ -1280,7 +1319,7 @@ export function WorkItemList() {
|
|
|
1280
1319
|
await backend.cachedUpdateWorkItem(id, {
|
|
1281
1320
|
type: item.value,
|
|
1282
1321
|
});
|
|
1283
|
-
await queueWrite('update', id);
|
|
1322
|
+
await queueWrite('update', rowIdOf(id));
|
|
1284
1323
|
}
|
|
1285
1324
|
for (const id of targetIds) {
|
|
1286
1325
|
await backendDataStore.getState().reloadItem(id);
|
|
@@ -1308,7 +1347,7 @@ export function WorkItemList() {
|
|
|
1308
1347
|
pushUpdateUndo(targetIds, 'priority change');
|
|
1309
1348
|
for (const id of targetIds) {
|
|
1310
1349
|
await backend.cachedUpdateWorkItem(id, { priority });
|
|
1311
|
-
await queueWrite('update', id);
|
|
1350
|
+
await queueWrite('update', rowIdOf(id));
|
|
1312
1351
|
}
|
|
1313
1352
|
for (const id of targetIds) {
|
|
1314
1353
|
await backendDataStore.getState().reloadItem(id);
|
|
@@ -1350,16 +1389,21 @@ export function WorkItemList() {
|
|
|
1350
1389
|
return;
|
|
1351
1390
|
void (async () => {
|
|
1352
1391
|
const raw = item.value.trim();
|
|
1353
|
-
const
|
|
1392
|
+
const parentDisplayId = raw.includes(' - ')
|
|
1354
1393
|
? raw.split(' - ')[0].trim()
|
|
1355
1394
|
: raw;
|
|
1395
|
+
const newParent = rowIdOf(parentDisplayId);
|
|
1396
|
+
if (newParent === -1) {
|
|
1397
|
+
setWarning(`Parent "${parentDisplayId}" not found`);
|
|
1398
|
+
return;
|
|
1399
|
+
}
|
|
1356
1400
|
try {
|
|
1357
1401
|
pushUpdateUndo(targetIds, 'parent change');
|
|
1358
1402
|
for (const id of targetIds) {
|
|
1359
1403
|
await backend.cachedUpdateWorkItem(id, {
|
|
1360
1404
|
parent: newParent,
|
|
1361
1405
|
});
|
|
1362
|
-
await queueWrite('update', id);
|
|
1406
|
+
await queueWrite('update', rowIdOf(id));
|
|
1363
1407
|
}
|
|
1364
1408
|
clearWarning();
|
|
1365
1409
|
}
|
|
@@ -1380,18 +1424,24 @@ export function WorkItemList() {
|
|
|
1380
1424
|
return;
|
|
1381
1425
|
void (async () => {
|
|
1382
1426
|
const raw = text.trim();
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1427
|
+
let newParent = null;
|
|
1428
|
+
if (raw !== '') {
|
|
1429
|
+
const parentDisplayId = raw.includes(' - ')
|
|
1386
1430
|
? raw.split(' - ')[0].trim()
|
|
1387
1431
|
: raw;
|
|
1432
|
+
newParent = rowIdOf(parentDisplayId);
|
|
1433
|
+
if (newParent === -1) {
|
|
1434
|
+
setWarning(`Parent "${parentDisplayId}" not found`);
|
|
1435
|
+
return;
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1388
1438
|
try {
|
|
1389
1439
|
pushUpdateUndo(targetIds, 'parent change');
|
|
1390
1440
|
for (const id of targetIds) {
|
|
1391
1441
|
await backend.cachedUpdateWorkItem(id, {
|
|
1392
1442
|
parent: newParent,
|
|
1393
1443
|
});
|
|
1394
|
-
await queueWrite('update', id);
|
|
1444
|
+
await queueWrite('update', rowIdOf(id));
|
|
1395
1445
|
}
|
|
1396
1446
|
clearWarning();
|
|
1397
1447
|
}
|
|
@@ -1417,7 +1467,7 @@ export function WorkItemList() {
|
|
|
1417
1467
|
await backend.cachedUpdateWorkItem(id, {
|
|
1418
1468
|
assignee: item.value.trim(),
|
|
1419
1469
|
});
|
|
1420
|
-
await queueWrite('update', id);
|
|
1470
|
+
await queueWrite('update', rowIdOf(id));
|
|
1421
1471
|
}
|
|
1422
1472
|
for (const id of targetIds) {
|
|
1423
1473
|
await backendDataStore.getState().reloadItem(id);
|
|
@@ -1441,7 +1491,7 @@ export function WorkItemList() {
|
|
|
1441
1491
|
await backend.cachedUpdateWorkItem(id, {
|
|
1442
1492
|
assignee: text.trim(),
|
|
1443
1493
|
});
|
|
1444
|
-
await queueWrite('update', id);
|
|
1494
|
+
await queueWrite('update', rowIdOf(id));
|
|
1445
1495
|
}
|
|
1446
1496
|
for (const id of targetIds) {
|
|
1447
1497
|
await backendDataStore.getState().reloadItem(id);
|
|
@@ -1468,7 +1518,7 @@ export function WorkItemList() {
|
|
|
1468
1518
|
const labels = selected.map((i) => i.value);
|
|
1469
1519
|
for (const id of targetIds) {
|
|
1470
1520
|
await backend.cachedUpdateWorkItem(id, { labels });
|
|
1471
|
-
await queueWrite('update', id);
|
|
1521
|
+
await queueWrite('update', rowIdOf(id));
|
|
1472
1522
|
}
|
|
1473
1523
|
for (const id of targetIds) {
|
|
1474
1524
|
await backendDataStore.getState().reloadItem(id);
|
|
@@ -1494,7 +1544,7 @@ export function WorkItemList() {
|
|
|
1494
1544
|
.filter(Boolean);
|
|
1495
1545
|
for (const id of targetIds) {
|
|
1496
1546
|
await backend.cachedUpdateWorkItem(id, { labels });
|
|
1497
|
-
await queueWrite('update', id);
|
|
1547
|
+
await queueWrite('update', rowIdOf(id));
|
|
1498
1548
|
}
|
|
1499
1549
|
for (const id of targetIds) {
|
|
1500
1550
|
await backendDataStore.getState().reloadItem(id);
|
|
@@ -1664,7 +1714,7 @@ export function WorkItemList() {
|
|
|
1664
1714
|
await backend.cachedUpdateWorkItem(id, {
|
|
1665
1715
|
iteration: item.value,
|
|
1666
1716
|
});
|
|
1667
|
-
await queueWrite('update', id);
|
|
1717
|
+
await queueWrite('update', rowIdOf(id));
|
|
1668
1718
|
}
|
|
1669
1719
|
for (const id of targetIds) {
|
|
1670
1720
|
await backendDataStore.getState().reloadItem(id);
|
|
@@ -1697,7 +1747,7 @@ export function WorkItemList() {
|
|
|
1697
1747
|
else {
|
|
1698
1748
|
await backend.cachedDeleteWorkItem(id);
|
|
1699
1749
|
}
|
|
1700
|
-
await queueWrite('delete', id);
|
|
1750
|
+
await queueWrite('delete', rowIdOf(id));
|
|
1701
1751
|
}
|
|
1702
1752
|
if (softDelete) {
|
|
1703
1753
|
const evicted = undoStore.getState().pushUndo({
|
|
@@ -1706,18 +1756,19 @@ export function WorkItemList() {
|
|
|
1706
1756
|
? `deleted #${targetIds[0]}`
|
|
1707
1757
|
: `deleted ${targetIds.length} items`,
|
|
1708
1758
|
itemSnapshots: snapshots,
|
|
1709
|
-
|
|
1759
|
+
syncItemRowIds: snapshots.map((s) => s.rowId),
|
|
1710
1760
|
syncAction: 'delete',
|
|
1711
1761
|
});
|
|
1712
1762
|
if (evicted?.type === 'delete') {
|
|
1713
1763
|
for (const snap of evicted.itemSnapshots) {
|
|
1714
|
-
|
|
1764
|
+
if (snap.id)
|
|
1765
|
+
await backend.permanentlyDeleteWorkItem(snap.id);
|
|
1715
1766
|
}
|
|
1716
1767
|
}
|
|
1717
1768
|
}
|
|
1718
1769
|
closeOverlay();
|
|
1719
1770
|
for (const id of targetIds) {
|
|
1720
|
-
removeDeletedItem(id);
|
|
1771
|
+
removeDeletedItem(rowIdOf(id));
|
|
1721
1772
|
}
|
|
1722
1773
|
setCursor(Math.max(0, cursor - 1));
|
|
1723
1774
|
for (const id of targetIds) {
|