@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
|
@@ -54,11 +54,21 @@ export function WorkItemForm() {
|
|
|
54
54
|
popWorkItem: s.popWorkItem,
|
|
55
55
|
})));
|
|
56
56
|
const queue = useBackendDataStore((s) => s.queue);
|
|
57
|
-
|
|
57
|
+
/** Look up the rowId for a display ID. Returns -1 if not found. */
|
|
58
|
+
const rowIdOf = (displayId) => {
|
|
59
|
+
const item = allItems.find((i) => i.id === displayId);
|
|
60
|
+
return item?.rowId ?? -1;
|
|
61
|
+
};
|
|
62
|
+
/** Look up the display ID for a rowId. Returns null if not found. */
|
|
63
|
+
const displayIdOf = (rowId) => {
|
|
64
|
+
const item = allItems.find((i) => i.rowId === rowId);
|
|
65
|
+
return item?.id ?? null;
|
|
66
|
+
};
|
|
67
|
+
const queueWrite = async (action, itemRowId, extra) => {
|
|
58
68
|
if (queue) {
|
|
59
69
|
await queue.append({
|
|
60
70
|
action,
|
|
61
|
-
|
|
71
|
+
itemRowId,
|
|
62
72
|
timestamp: new Date().toISOString(),
|
|
63
73
|
...(extra?.commentData ? { commentData: extra.commentData } : {}),
|
|
64
74
|
...(extra?.templateSlug ? { templateSlug: extra.templateSlug } : {}),
|
|
@@ -97,16 +107,24 @@ export function WorkItemForm() {
|
|
|
97
107
|
}
|
|
98
108
|
let cancelled = false;
|
|
99
109
|
setItemLoading(true);
|
|
110
|
+
const displayId = displayIdOf(selectedWorkItemId);
|
|
111
|
+
if (!displayId) {
|
|
112
|
+
setItemLoading(false);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
100
115
|
void (async () => {
|
|
101
116
|
try {
|
|
102
|
-
const item = await backend.getWorkItem(
|
|
117
|
+
const item = await backend.getWorkItem(displayId);
|
|
103
118
|
const [ch, dep] = capabilities.relationships
|
|
104
119
|
? await Promise.all([
|
|
105
|
-
backend.getChildren(
|
|
106
|
-
backend.getDependents(
|
|
120
|
+
backend.getChildren(displayId),
|
|
121
|
+
backend.getDependents(displayId),
|
|
107
122
|
])
|
|
108
123
|
: [[], []];
|
|
109
|
-
const
|
|
124
|
+
const parentDisplayId = item.parent !== null ? displayIdOf(item.parent) : null;
|
|
125
|
+
const pi = parentDisplayId
|
|
126
|
+
? await backend.getWorkItem(parentDisplayId)
|
|
127
|
+
: null;
|
|
110
128
|
if (cancelled)
|
|
111
129
|
return;
|
|
112
130
|
setExistingItem(item);
|
|
@@ -180,10 +198,10 @@ export function WorkItemForm() {
|
|
|
180
198
|
all.push('rel-parent');
|
|
181
199
|
}
|
|
182
200
|
for (const child of children) {
|
|
183
|
-
all.push(`rel-child-${child.
|
|
201
|
+
all.push(`rel-child-${child.rowId}`);
|
|
184
202
|
}
|
|
185
203
|
for (const dep of dependents) {
|
|
186
|
-
all.push(`rel-dependent-${dep.
|
|
204
|
+
all.push(`rel-dependent-${dep.rowId}`);
|
|
187
205
|
}
|
|
188
206
|
}
|
|
189
207
|
return all;
|
|
@@ -205,7 +223,9 @@ export function WorkItemForm() {
|
|
|
205
223
|
return required;
|
|
206
224
|
}, [selectedWorkItemId, capabilities.customTypes]);
|
|
207
225
|
const requiredFieldsList = useMemo(() => capabilities.requiredFields ?? [...requiredFields], [capabilities.requiredFields, requiredFields]);
|
|
208
|
-
|
|
226
|
+
// Convert selectedWorkItemId (rowId) to display ID for validation
|
|
227
|
+
const selectedDisplayId = selectedWorkItemId !== null ? displayIdOf(selectedWorkItemId) : null;
|
|
228
|
+
const { errors: validationErrors, validate, clearError, } = useFormValidation(allItems, selectedDisplayId, requiredFieldsList);
|
|
209
229
|
const [comments, setComments] = useState([]);
|
|
210
230
|
// Derive field values from current draft
|
|
211
231
|
const title = currentDraft?.fields.title ?? '';
|
|
@@ -252,10 +272,9 @@ export function WorkItemForm() {
|
|
|
252
272
|
const { createChildParentId, setCreateChildParentId } = navigationStore.getState();
|
|
253
273
|
let parentId = '';
|
|
254
274
|
if (selectedWorkItemId === null && createChildParentId) {
|
|
255
|
-
const parent = allItems.find((i) => i.
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
: `#${createChildParentId}`;
|
|
275
|
+
const parent = allItems.find((i) => i.rowId === createChildParentId);
|
|
276
|
+
const displayId = parent?.id ?? String(createChildParentId);
|
|
277
|
+
parentId = parent ? `#${displayId} - ${parent.title}` : `#${displayId}`;
|
|
259
278
|
setCreateChildParentId(null);
|
|
260
279
|
}
|
|
261
280
|
const initialFields = {
|
|
@@ -273,7 +292,9 @@ export function WorkItemForm() {
|
|
|
273
292
|
};
|
|
274
293
|
const draft = {
|
|
275
294
|
itemId: selectedWorkItemId,
|
|
276
|
-
itemTitle: selectedWorkItemId
|
|
295
|
+
itemTitle: selectedWorkItemId
|
|
296
|
+
? `#${selectedDisplayId ?? selectedWorkItemId}`
|
|
297
|
+
: '(new)',
|
|
277
298
|
fields: initialFields,
|
|
278
299
|
initialSnapshot: { ...initialFields },
|
|
279
300
|
focusedField: 0,
|
|
@@ -291,16 +312,20 @@ export function WorkItemForm() {
|
|
|
291
312
|
// Build field values
|
|
292
313
|
const parentIdValue = existingItem.parent !== null && existingItem.parent !== undefined
|
|
293
314
|
? (() => {
|
|
294
|
-
const pi = allItems.find((i) => i.
|
|
315
|
+
const pi = allItems.find((i) => i.rowId === existingItem.parent);
|
|
316
|
+
const parentDisplayId = pi?.id ?? String(existingItem.parent);
|
|
295
317
|
return pi
|
|
296
|
-
? `#${
|
|
318
|
+
? `#${parentDisplayId} - ${pi.title}`
|
|
297
319
|
: String(existingItem.parent);
|
|
298
320
|
})()
|
|
299
321
|
: '';
|
|
300
322
|
const dependsOnValue = existingItem.dependsOn
|
|
301
|
-
?.map((
|
|
302
|
-
const depItem = allItems.find((i) => i.
|
|
303
|
-
|
|
323
|
+
?.map((depRowId) => {
|
|
324
|
+
const depItem = allItems.find((i) => i.rowId === depRowId);
|
|
325
|
+
const depDisplayId = depItem?.id ?? String(depRowId);
|
|
326
|
+
return depItem
|
|
327
|
+
? `#${depDisplayId} - ${depItem.title}`
|
|
328
|
+
: String(depRowId);
|
|
304
329
|
})
|
|
305
330
|
.join(', ') ?? '';
|
|
306
331
|
const newFields = {
|
|
@@ -403,7 +428,7 @@ export function WorkItemForm() {
|
|
|
403
428
|
}, [formMode, editingTemplateSlug, backend]);
|
|
404
429
|
const parentSuggestions = useMemo(() => {
|
|
405
430
|
return allItems
|
|
406
|
-
.filter((item) => item.id !==
|
|
431
|
+
.filter((item) => item.rowId !== selectedWorkItemId && item.id !== null)
|
|
407
432
|
.map((item) => `#${item.id} - ${item.title}`);
|
|
408
433
|
}, [allItems, selectedWorkItemId]);
|
|
409
434
|
const [editing, setEditing] = useState(false);
|
|
@@ -431,23 +456,26 @@ export function WorkItemForm() {
|
|
|
431
456
|
.split(',')
|
|
432
457
|
.map((l) => l.trim())
|
|
433
458
|
.filter((l) => l.length > 0);
|
|
459
|
+
// Parse display IDs from form fields and resolve to rowIds
|
|
434
460
|
const parsedParent = (() => {
|
|
435
461
|
const trimmed = parentId.trim();
|
|
436
462
|
if (!trimmed)
|
|
437
463
|
return null;
|
|
438
464
|
const match = trimmed.match(/^#(\S+)\s*-\s/);
|
|
439
|
-
|
|
465
|
+
const displayId = match ? match[1] : trimmed;
|
|
466
|
+
return rowIdOf(displayId);
|
|
440
467
|
})();
|
|
441
468
|
const parsedDependsOn = dependsOn
|
|
442
469
|
.split(',')
|
|
443
470
|
.map((s) => {
|
|
444
471
|
const trimmed = s.trim();
|
|
445
472
|
if (!trimmed)
|
|
446
|
-
return
|
|
473
|
+
return -1;
|
|
447
474
|
const match = trimmed.match(/^#(\S+)\s*-\s/);
|
|
448
|
-
|
|
475
|
+
const displayId = match ? match[1] : trimmed;
|
|
476
|
+
return rowIdOf(displayId);
|
|
449
477
|
})
|
|
450
|
-
.filter((
|
|
478
|
+
.filter((rowId) => rowId !== -1);
|
|
451
479
|
if (formMode === 'template') {
|
|
452
480
|
const template = {
|
|
453
481
|
slug: editingTemplateSlug ?? slugifyTemplateName(title),
|
|
@@ -467,19 +495,23 @@ export function WorkItemForm() {
|
|
|
467
495
|
template.iteration = iteration;
|
|
468
496
|
if (description)
|
|
469
497
|
template.description = description;
|
|
470
|
-
if (parsedParent)
|
|
471
|
-
template.parent = parsedParent;
|
|
472
|
-
|
|
473
|
-
|
|
498
|
+
if (parsedParent !== null) {
|
|
499
|
+
template.parent = displayIdOf(parsedParent);
|
|
500
|
+
}
|
|
501
|
+
if (parsedDependsOn.length > 0) {
|
|
502
|
+
template.dependsOn = parsedDependsOn
|
|
503
|
+
.map((rid) => displayIdOf(rid))
|
|
504
|
+
.filter((id) => id !== null);
|
|
505
|
+
}
|
|
474
506
|
if (editingTemplateSlug) {
|
|
475
507
|
await backend.updateTemplate(editingTemplateSlug, template);
|
|
476
|
-
await queueWrite('template-update',
|
|
508
|
+
await queueWrite('template-update', 0, {
|
|
477
509
|
templateSlug: template.slug,
|
|
478
510
|
});
|
|
479
511
|
}
|
|
480
512
|
else {
|
|
481
513
|
await backend.createTemplate(template);
|
|
482
|
-
await queueWrite('template-create',
|
|
514
|
+
await queueWrite('template-create', 0, {
|
|
483
515
|
templateSlug: template.slug,
|
|
484
516
|
});
|
|
485
517
|
}
|
|
@@ -488,9 +520,9 @@ export function WorkItemForm() {
|
|
|
488
520
|
setEditingTemplateSlug(null);
|
|
489
521
|
return;
|
|
490
522
|
}
|
|
491
|
-
if (selectedWorkItemId !== null) {
|
|
492
|
-
const snapshot = await backend.getWorkItem(
|
|
493
|
-
await backend.cachedUpdateWorkItem(
|
|
523
|
+
if (selectedWorkItemId !== null && selectedDisplayId) {
|
|
524
|
+
const snapshot = await backend.getWorkItem(selectedDisplayId);
|
|
525
|
+
await backend.cachedUpdateWorkItem(selectedDisplayId, {
|
|
494
526
|
title,
|
|
495
527
|
type,
|
|
496
528
|
status,
|
|
@@ -505,13 +537,13 @@ export function WorkItemForm() {
|
|
|
505
537
|
await queueWrite('update', selectedWorkItemId);
|
|
506
538
|
undoStore.getState().pushUndo({
|
|
507
539
|
type: 'update',
|
|
508
|
-
label: `edited #${
|
|
540
|
+
label: `edited #${selectedDisplayId}`,
|
|
509
541
|
itemSnapshots: [snapshot],
|
|
510
|
-
|
|
542
|
+
syncItemRowIds: [selectedWorkItemId],
|
|
511
543
|
syncAction: 'update',
|
|
512
544
|
});
|
|
513
545
|
if (capabilities.comments && newComment.trim().length > 0) {
|
|
514
|
-
const added = await backend.addComment(
|
|
546
|
+
const added = await backend.addComment(selectedDisplayId, {
|
|
515
547
|
author: 'me',
|
|
516
548
|
body: newComment.trim(),
|
|
517
549
|
});
|
|
@@ -521,10 +553,10 @@ export function WorkItemForm() {
|
|
|
521
553
|
setComments((prev) => [...prev, added]);
|
|
522
554
|
setNewComment('');
|
|
523
555
|
}
|
|
524
|
-
await backendDataStore.getState().reloadItem(
|
|
556
|
+
await backendDataStore.getState().reloadItem(selectedDisplayId);
|
|
525
557
|
uiStore
|
|
526
558
|
.getState()
|
|
527
|
-
.setToast(`Item #${
|
|
559
|
+
.setToast(`Item #${selectedDisplayId} updated — press u to undo`);
|
|
528
560
|
}
|
|
529
561
|
else {
|
|
530
562
|
const created = await backend.cachedCreateWorkItem({
|
|
@@ -539,28 +571,30 @@ export function WorkItemForm() {
|
|
|
539
571
|
parent: parsedParent,
|
|
540
572
|
dependsOn: parsedDependsOn,
|
|
541
573
|
});
|
|
542
|
-
await queueWrite('create', created.
|
|
574
|
+
await queueWrite('create', created.rowId);
|
|
543
575
|
undoStore.getState().pushUndo({
|
|
544
576
|
type: 'create',
|
|
545
|
-
label: `created #${created.id}`,
|
|
577
|
+
label: `created #${created.id ?? created.rowId}`,
|
|
546
578
|
itemSnapshots: [],
|
|
547
|
-
|
|
579
|
+
syncItemRowIds: [created.rowId],
|
|
548
580
|
syncAction: 'create',
|
|
549
|
-
|
|
581
|
+
createdRowIds: [created.rowId],
|
|
550
582
|
});
|
|
551
|
-
if (capabilities.comments && newComment.trim().length > 0) {
|
|
583
|
+
if (capabilities.comments && newComment.trim().length > 0 && created.id) {
|
|
552
584
|
await backend.addComment(created.id, {
|
|
553
585
|
author: 'me',
|
|
554
586
|
body: newComment.trim(),
|
|
555
587
|
});
|
|
556
|
-
await queueWrite('comment', created.
|
|
588
|
+
await queueWrite('comment', created.rowId, {
|
|
557
589
|
commentData: { author: 'me', body: newComment.trim() },
|
|
558
590
|
});
|
|
559
591
|
}
|
|
560
|
-
|
|
592
|
+
if (created.id) {
|
|
593
|
+
await backendDataStore.getState().reloadItem(created.id);
|
|
594
|
+
}
|
|
561
595
|
uiStore
|
|
562
596
|
.getState()
|
|
563
|
-
.setToast(`Item #${created.id} created — press u to undo`);
|
|
597
|
+
.setToast(`Item #${created.id ?? created.rowId} created — press u to undo`);
|
|
564
598
|
setActiveTemplate(null);
|
|
565
599
|
}
|
|
566
600
|
// Update the initialSnapshot after saving so isDirty becomes false
|
|
@@ -592,7 +626,7 @@ export function WorkItemForm() {
|
|
|
592
626
|
await save();
|
|
593
627
|
if (pendingRelNav) {
|
|
594
628
|
// Push a new draft for the target item
|
|
595
|
-
const targetItem = allItems.find((i) => i.
|
|
629
|
+
const targetItem = allItems.find((i) => i.rowId === pendingRelNav);
|
|
596
630
|
const defaultFields = {
|
|
597
631
|
title: '',
|
|
598
632
|
type: activeType ?? types[0] ?? '',
|
|
@@ -608,7 +642,7 @@ export function WorkItemForm() {
|
|
|
608
642
|
};
|
|
609
643
|
const newDraft = {
|
|
610
644
|
itemId: pendingRelNav,
|
|
611
|
-
itemTitle: targetItem?.title ?? `#${pendingRelNav}`,
|
|
645
|
+
itemTitle: targetItem?.title ?? `#${targetItem?.id ?? pendingRelNav}`,
|
|
612
646
|
fields: defaultFields,
|
|
613
647
|
initialSnapshot: { ...defaultFields },
|
|
614
648
|
focusedField: 0,
|
|
@@ -642,7 +676,7 @@ export function WorkItemForm() {
|
|
|
642
676
|
if (pendingRelNav) {
|
|
643
677
|
// Push a new draft for the target item (discarding current)
|
|
644
678
|
formStackStore.getState().pop();
|
|
645
|
-
const targetItem = allItems.find((i) => i.
|
|
679
|
+
const targetItem = allItems.find((i) => i.rowId === pendingRelNav);
|
|
646
680
|
const defaultFields = {
|
|
647
681
|
title: '',
|
|
648
682
|
type: activeType ?? types[0] ?? '',
|
|
@@ -658,7 +692,7 @@ export function WorkItemForm() {
|
|
|
658
692
|
};
|
|
659
693
|
const newDraft = {
|
|
660
694
|
itemId: pendingRelNav,
|
|
661
|
-
itemTitle: targetItem?.title ?? `#${pendingRelNav}`,
|
|
695
|
+
itemTitle: targetItem?.title ?? `#${targetItem?.id ?? pendingRelNav}`,
|
|
662
696
|
fields: defaultFields,
|
|
663
697
|
initialSnapshot: { ...defaultFields },
|
|
664
698
|
focusedField: 0,
|
|
@@ -790,24 +824,24 @@ export function WorkItemForm() {
|
|
|
790
824
|
}
|
|
791
825
|
if (matchesCommand('form-edit', _input, key)) {
|
|
792
826
|
if (isRelationshipField) {
|
|
793
|
-
let
|
|
827
|
+
let targetRowId = null;
|
|
794
828
|
if (currentField === 'rel-parent' && existingItem?.parent) {
|
|
795
|
-
|
|
829
|
+
targetRowId = existingItem.parent;
|
|
796
830
|
}
|
|
797
831
|
else if (currentField.startsWith('rel-child-')) {
|
|
798
|
-
|
|
832
|
+
targetRowId = Number(currentField.slice('rel-child-'.length));
|
|
799
833
|
}
|
|
800
834
|
else if (currentField.startsWith('rel-dependent-')) {
|
|
801
|
-
|
|
835
|
+
targetRowId = Number(currentField.slice('rel-dependent-'.length));
|
|
802
836
|
}
|
|
803
|
-
if (
|
|
837
|
+
if (targetRowId) {
|
|
804
838
|
if (isDirty) {
|
|
805
|
-
setPendingRelNav(
|
|
839
|
+
setPendingRelNav(targetRowId);
|
|
806
840
|
setShowDirtyPrompt(true);
|
|
807
841
|
}
|
|
808
842
|
else {
|
|
809
843
|
// Create new draft for target item before navigating
|
|
810
|
-
const targetItem = allItems.find((i) => i.
|
|
844
|
+
const targetItem = allItems.find((i) => i.rowId === targetRowId);
|
|
811
845
|
const defaultFields = {
|
|
812
846
|
title: '',
|
|
813
847
|
type: activeType ?? types[0] ?? '',
|
|
@@ -822,14 +856,14 @@ export function WorkItemForm() {
|
|
|
822
856
|
newComment: '',
|
|
823
857
|
};
|
|
824
858
|
const newDraft = {
|
|
825
|
-
itemId:
|
|
826
|
-
itemTitle: targetItem?.title ?? `#${
|
|
859
|
+
itemId: targetRowId,
|
|
860
|
+
itemTitle: targetItem?.title ?? `#${targetItem?.id ?? targetRowId}`,
|
|
827
861
|
fields: defaultFields,
|
|
828
862
|
initialSnapshot: { ...defaultFields },
|
|
829
863
|
focusedField: 0,
|
|
830
864
|
};
|
|
831
865
|
pushDraft(newDraft);
|
|
832
|
-
pushWorkItem(
|
|
866
|
+
pushWorkItem(targetRowId);
|
|
833
867
|
}
|
|
834
868
|
}
|
|
835
869
|
}
|
|
@@ -1089,24 +1123,24 @@ export function WorkItemForm() {
|
|
|
1089
1123
|
function renderRelationshipField(field, index) {
|
|
1090
1124
|
const focused = index === focusedField;
|
|
1091
1125
|
const cursor = focused ? '>' : ' ';
|
|
1092
|
-
const
|
|
1093
|
-
? field.slice('rel-child-'.length)
|
|
1126
|
+
const rowId = field.startsWith('rel-child-')
|
|
1127
|
+
? Number(field.slice('rel-child-'.length))
|
|
1094
1128
|
: field.startsWith('rel-dependent-')
|
|
1095
|
-
? field.slice('rel-dependent-'.length)
|
|
1129
|
+
? Number(field.slice('rel-dependent-'.length))
|
|
1096
1130
|
: null;
|
|
1097
|
-
let
|
|
1131
|
+
let relItem = null;
|
|
1098
1132
|
if (field === 'rel-parent' && parentItem) {
|
|
1099
|
-
|
|
1133
|
+
relItem = parentItem;
|
|
1100
1134
|
}
|
|
1101
|
-
else if (
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1135
|
+
else if (rowId !== null) {
|
|
1136
|
+
relItem =
|
|
1137
|
+
children.find((c) => c.rowId === rowId) ??
|
|
1138
|
+
dependents.find((d) => d.rowId === rowId) ??
|
|
1139
|
+
null;
|
|
1106
1140
|
}
|
|
1107
|
-
if (!
|
|
1141
|
+
if (!relItem)
|
|
1108
1142
|
return null;
|
|
1109
|
-
return (_jsxs(Box, { children: [_jsxs(Text, { color: focused ? accent : undefined, children: [cursor, " "] }), _jsxs(Text, { bold: focused, color: focused ? accent : undefined, children: ["#",
|
|
1143
|
+
return (_jsxs(Box, { children: [_jsxs(Text, { color: focused ? accent : undefined, children: [cursor, " "] }), _jsxs(Text, { bold: focused, color: focused ? accent : undefined, children: ["#", relItem.id ?? relItem.rowId, " (", relItem.title, ")"] })] }, field));
|
|
1110
1144
|
}
|
|
1111
1145
|
const formStackLength = useFormStackStore((s) => s.stack.length);
|
|
1112
1146
|
const chromeLines = useMemo(() => {
|
|
@@ -1151,7 +1185,7 @@ export function WorkItemForm() {
|
|
|
1151
1185
|
const typeLabel = formMode === 'template' ? '' : type.charAt(0).toUpperCase() + type.slice(1);
|
|
1152
1186
|
const isFieldVisible = (index) => index >= viewport.start && index < viewport.end;
|
|
1153
1187
|
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { bold: true, color: accent, children: [mode, typeLabel ? ` ${typeLabel}` : '', formMode !== 'template' && selectedWorkItemId !== null
|
|
1154
|
-
? ` #${selectedWorkItemId}`
|
|
1188
|
+
? ` #${selectedDisplayId ?? selectedWorkItemId}`
|
|
1155
1189
|
: ''] }) }), _jsx(Breadcrumbs, {}), fields.map((field, index) => {
|
|
1156
1190
|
if (field === 'rel-parent' ||
|
|
1157
1191
|
field.startsWith('rel-child-') ||
|