@sascha384/tic 4.1.0 → 4.3.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/app.js +4 -2
- package/dist/app.js.map +1 -1
- package/dist/auth/ado.js +76 -28
- package/dist/auth/ado.js.map +1 -1
- package/dist/auth/github.js +57 -24
- package/dist/auth/github.js.map +1 -1
- package/dist/auth/gitlab.js +54 -23
- package/dist/auth/gitlab.js.map +1 -1
- package/dist/auth/jira.d.ts +8 -0
- package/dist/auth/jira.js +24 -0
- package/dist/auth/jira.js.map +1 -0
- package/dist/backends/ado/api.d.ts +1 -0
- package/dist/backends/ado/api.js +66 -16
- package/dist/backends/ado/api.js.map +1 -1
- package/dist/backends/ado/index.js +4 -1
- package/dist/backends/ado/index.js.map +1 -1
- package/dist/backends/factory.js +1 -1
- package/dist/backends/factory.js.map +1 -1
- package/dist/backends/files/index.js +1 -0
- package/dist/backends/files/index.js.map +1 -1
- package/dist/backends/github/api.js +61 -17
- package/dist/backends/github/api.js.map +1 -1
- package/dist/backends/github/index.js +1 -0
- package/dist/backends/github/index.js.map +1 -1
- package/dist/backends/github/mappers.d.ts +1 -1
- package/dist/backends/github/mappers.js +1 -1
- package/dist/backends/github/mappers.js.map +1 -1
- package/dist/backends/gitlab/api.js +22 -8
- package/dist/backends/gitlab/api.js.map +1 -1
- package/dist/backends/gitlab/index.js +1 -0
- package/dist/backends/gitlab/index.js.map +1 -1
- package/dist/backends/jira/api.d.ts +9 -0
- package/dist/backends/jira/api.js +89 -0
- package/dist/backends/jira/api.js.map +1 -0
- package/dist/backends/jira/index.d.ts +10 -2
- package/dist/backends/jira/index.js +140 -161
- package/dist/backends/jira/index.js.map +1 -1
- package/dist/backends/jira/mappers.d.ts +8 -2
- package/dist/backends/jira/mappers.js +20 -5
- package/dist/backends/jira/mappers.js.map +1 -1
- package/dist/backends/shared/api-client.d.ts +1 -0
- package/dist/backends/shared/api-client.js +18 -3
- package/dist/backends/shared/api-client.js.map +1 -1
- package/dist/backends/types.d.ts +1 -0
- package/dist/backends/types.js.map +1 -1
- package/dist/cli/commands/auth.js +34 -2
- package/dist/cli/commands/auth.js.map +1 -1
- package/dist/cli/commands/item.js +2 -2
- package/dist/cli/commands/item.js.map +1 -1
- package/dist/components/AuthPrompt.js +36 -4
- package/dist/components/AuthPrompt.js.map +1 -1
- package/dist/components/ErrorBoundary.d.ts +14 -0
- package/dist/components/ErrorBoundary.js +30 -0
- package/dist/components/ErrorBoundary.js.map +1 -0
- package/dist/components/Settings.js +82 -17
- package/dist/components/Settings.js.map +1 -1
- package/dist/components/StatusScreen.js +3 -1
- package/dist/components/StatusScreen.js.map +1 -1
- package/dist/components/WorkItemForm.js +57 -14
- package/dist/components/WorkItemForm.js.map +1 -1
- package/dist/components/WorkItemList.js +141 -35
- package/dist/components/WorkItemList.js.map +1 -1
- package/dist/components/getMarkedDistribution.d.ts +6 -0
- package/dist/components/getMarkedDistribution.js +17 -0
- package/dist/components/getMarkedDistribution.js.map +1 -0
- package/dist/editor.js +0 -1
- package/dist/editor.js.map +1 -1
- package/dist/hooks/useFormValidation.d.ts +20 -0
- package/dist/hooks/useFormValidation.js +146 -0
- package/dist/hooks/useFormValidation.js.map +1 -0
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/storage/index.js +15 -12
- package/dist/storage/index.js.map +1 -1
- package/dist/stores/backendDataStore.d.ts +2 -1
- package/dist/stores/backendDataStore.js +78 -6
- package/dist/stores/backendDataStore.js.map +1 -1
- package/dist/stores/recentCommandsStore.js +3 -1
- package/dist/stores/recentCommandsStore.js.map +1 -1
- package/dist/sync/SyncManager.d.ts +1 -1
- package/dist/sync/SyncManager.js +51 -10
- package/dist/sync/SyncManager.js.map +1 -1
- package/dist/update-checker.js +5 -3
- package/dist/update-checker.js.map +1 -1
- package/package.json +1 -1
- package/dist/backends/jira/acli.d.ts +0 -6
- package/dist/backends/jira/acli.js +0 -35
- package/dist/backends/jira/acli.js.map +0 -1
|
@@ -7,6 +7,7 @@ import { isGitRepo } from '../git.js';
|
|
|
7
7
|
import { beginImplementation } from '../implement.js';
|
|
8
8
|
import { configStore, useConfigStore } from '../stores/configStore.js';
|
|
9
9
|
import { uiStore, useUIStore, getOverlayTargetIds } from '../stores/uiStore.js';
|
|
10
|
+
import { getMarkedDistribution } from './getMarkedDistribution.js';
|
|
10
11
|
import { TableLayout } from './TableLayout.js';
|
|
11
12
|
import { useTerminalSize } from '../hooks/useTerminalSize.js';
|
|
12
13
|
import { useScrollViewport } from '../hooks/useScrollViewport.js';
|
|
@@ -113,7 +114,10 @@ export function WorkItemList() {
|
|
|
113
114
|
// Marked count for header display
|
|
114
115
|
const markedCount = markedIds.size;
|
|
115
116
|
const refreshData = useCallback(() => {
|
|
116
|
-
void backendDataStore
|
|
117
|
+
void backendDataStore
|
|
118
|
+
.getState()
|
|
119
|
+
.refresh()
|
|
120
|
+
.catch(() => { });
|
|
117
121
|
}, []);
|
|
118
122
|
useEffect(() => {
|
|
119
123
|
if (!toast)
|
|
@@ -128,9 +132,25 @@ export function WorkItemList() {
|
|
|
128
132
|
return () => clearTimeout(timer);
|
|
129
133
|
}, [warning, clearWarning]);
|
|
130
134
|
useEffect(() => {
|
|
131
|
-
if (capabilities.templates
|
|
132
|
-
|
|
133
|
-
|
|
135
|
+
if (!capabilities.templates || !backend)
|
|
136
|
+
return;
|
|
137
|
+
let cancelled = false;
|
|
138
|
+
void backend
|
|
139
|
+
.listTemplates()
|
|
140
|
+
.then((t) => {
|
|
141
|
+
if (!cancelled)
|
|
142
|
+
setTemplates(t);
|
|
143
|
+
})
|
|
144
|
+
.catch((err) => {
|
|
145
|
+
if (cancelled)
|
|
146
|
+
return;
|
|
147
|
+
uiStore
|
|
148
|
+
.getState()
|
|
149
|
+
.setToast(err instanceof Error ? err.message : 'Failed to load templates');
|
|
150
|
+
});
|
|
151
|
+
return () => {
|
|
152
|
+
cancelled = true;
|
|
153
|
+
};
|
|
134
154
|
}, [backend, capabilities.templates]);
|
|
135
155
|
// Load default view on startup
|
|
136
156
|
const defaultViewLoadedRef = useRef(false);
|
|
@@ -156,7 +176,11 @@ export function WorkItemList() {
|
|
|
156
176
|
itemId,
|
|
157
177
|
timestamp: new Date().toISOString(),
|
|
158
178
|
});
|
|
159
|
-
syncManager?.pushPending().catch(() => {
|
|
179
|
+
syncManager?.pushPending().catch((err) => {
|
|
180
|
+
uiStore
|
|
181
|
+
.getState()
|
|
182
|
+
.setToast(err instanceof Error ? err.message : 'Sync failed');
|
|
183
|
+
});
|
|
160
184
|
}
|
|
161
185
|
};
|
|
162
186
|
const pushUpdateUndo = (targetIds, label) => {
|
|
@@ -245,9 +269,16 @@ export function WorkItemList() {
|
|
|
245
269
|
if (activeOverlay?.type !== 'command-bar' || !backend)
|
|
246
270
|
return;
|
|
247
271
|
let cancelled = false;
|
|
248
|
-
void backend
|
|
272
|
+
void backend
|
|
273
|
+
.listWorkItems()
|
|
274
|
+
.then((items) => {
|
|
249
275
|
if (!cancelled)
|
|
250
276
|
setAllSearchItems(items);
|
|
277
|
+
})
|
|
278
|
+
.catch((err) => {
|
|
279
|
+
uiStore
|
|
280
|
+
.getState()
|
|
281
|
+
.setToast(err instanceof Error ? err.message : 'Failed to load items');
|
|
251
282
|
});
|
|
252
283
|
return () => {
|
|
253
284
|
cancelled = true;
|
|
@@ -282,6 +313,7 @@ export function WorkItemList() {
|
|
|
282
313
|
chromeLines,
|
|
283
314
|
linesPerItem: 1,
|
|
284
315
|
});
|
|
316
|
+
const markedDistribution = useMemo(() => getMarkedDistribution(markedIds, treeItems.map((t) => t.item), viewport.start, viewport.end), [markedIds, treeItems, viewport.start, viewport.end]);
|
|
285
317
|
// Block 1.5: Description scroll handler — active when full description is shown
|
|
286
318
|
useInput((_input, key) => {
|
|
287
319
|
if (_input === ' ' || key.escape) {
|
|
@@ -456,14 +488,21 @@ export function WorkItemList() {
|
|
|
456
488
|
refreshData();
|
|
457
489
|
setToast(`Undid ${entry.label}`);
|
|
458
490
|
}
|
|
459
|
-
})()
|
|
491
|
+
})().catch((err) => {
|
|
492
|
+
uiStore
|
|
493
|
+
.getState()
|
|
494
|
+
.setToast(err instanceof Error ? err.message : 'Undo failed');
|
|
495
|
+
});
|
|
460
496
|
}
|
|
461
497
|
if (input === 'o' && treeItems.length > 0 && backend) {
|
|
462
498
|
void (async () => {
|
|
463
499
|
const itemId = treeItems[cursor].item.id;
|
|
464
500
|
await backend.openItem(itemId);
|
|
465
|
-
void backendDataStore
|
|
466
|
-
|
|
501
|
+
void backendDataStore
|
|
502
|
+
.getState()
|
|
503
|
+
.reloadItem(itemId)
|
|
504
|
+
.catch(() => { });
|
|
505
|
+
})().catch(() => { });
|
|
467
506
|
}
|
|
468
507
|
if (input === 'b' && gitAvailable && treeItems.length > 0) {
|
|
469
508
|
const item = treeItems[cursor].item;
|
|
@@ -485,7 +524,10 @@ export function WorkItemList() {
|
|
|
485
524
|
process.stdin.setRawMode?.(true);
|
|
486
525
|
setWarning(e instanceof Error ? e.message : 'Failed to start implementation');
|
|
487
526
|
}
|
|
488
|
-
void backendDataStore
|
|
527
|
+
void backendDataStore
|
|
528
|
+
.getState()
|
|
529
|
+
.reloadItem(item.id)
|
|
530
|
+
.catch(() => { });
|
|
489
531
|
}
|
|
490
532
|
if (input === 'S') {
|
|
491
533
|
navigate('status');
|
|
@@ -512,7 +554,8 @@ export function WorkItemList() {
|
|
|
512
554
|
if (input === 'v') {
|
|
513
555
|
void configStore
|
|
514
556
|
.getState()
|
|
515
|
-
.update({ showDetailPanel: !showDetailPanel })
|
|
557
|
+
.update({ showDetailPanel: !showDetailPanel })
|
|
558
|
+
.catch(() => { });
|
|
516
559
|
}
|
|
517
560
|
if (input === ' ' && showDetailPanel && hasDescription) {
|
|
518
561
|
setShowFullDescription(true);
|
|
@@ -532,8 +575,13 @@ export function WorkItemList() {
|
|
|
532
575
|
clearWarning();
|
|
533
576
|
}
|
|
534
577
|
if (input === 'r' && syncManager) {
|
|
535
|
-
void syncManager
|
|
578
|
+
void syncManager
|
|
579
|
+
.sync()
|
|
580
|
+
.then(() => {
|
|
536
581
|
refreshData();
|
|
582
|
+
})
|
|
583
|
+
.catch(() => {
|
|
584
|
+
// Errors recorded in syncStatus by SyncManager
|
|
537
585
|
});
|
|
538
586
|
}
|
|
539
587
|
if (input === 'm' && treeItems.length > 0) {
|
|
@@ -820,8 +868,11 @@ export function WorkItemList() {
|
|
|
820
868
|
void (async () => {
|
|
821
869
|
const itemId = treeItems[cursor].item.id;
|
|
822
870
|
await backend.openItem(itemId);
|
|
823
|
-
void backendDataStore
|
|
824
|
-
|
|
871
|
+
void backendDataStore
|
|
872
|
+
.getState()
|
|
873
|
+
.reloadItem(itemId)
|
|
874
|
+
.catch(() => { });
|
|
875
|
+
})().catch(() => { });
|
|
825
876
|
}
|
|
826
877
|
break;
|
|
827
878
|
case 'branch':
|
|
@@ -844,12 +895,20 @@ export function WorkItemList() {
|
|
|
844
895
|
process.stdin.setRawMode?.(true);
|
|
845
896
|
setWarning(e instanceof Error ? e.message : 'Failed to start implementation');
|
|
846
897
|
}
|
|
847
|
-
void backendDataStore
|
|
898
|
+
void backendDataStore
|
|
899
|
+
.getState()
|
|
900
|
+
.reloadItem(item.id)
|
|
901
|
+
.catch(() => { });
|
|
848
902
|
}
|
|
849
903
|
break;
|
|
850
904
|
case 'sync':
|
|
851
905
|
if (syncManager) {
|
|
852
|
-
void syncManager
|
|
906
|
+
void syncManager
|
|
907
|
+
.sync()
|
|
908
|
+
.then(() => refreshData())
|
|
909
|
+
.catch(() => {
|
|
910
|
+
// Errors recorded in syncStatus by SyncManager
|
|
911
|
+
});
|
|
853
912
|
}
|
|
854
913
|
break;
|
|
855
914
|
case 'iterations':
|
|
@@ -979,7 +1038,7 @@ export function WorkItemList() {
|
|
|
979
1038
|
const positionText = treeItems.length > viewport.maxVisible
|
|
980
1039
|
? `${cursor + 1}/${treeItems.length}`
|
|
981
1040
|
: '';
|
|
982
|
-
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { wrap: "truncate", children: [_jsxs(Text, { bold: true, color: "cyan", children: [typeLabel, " \u2014 ", iteration] }), _jsx(Text, { dimColor: true, children: ` (${filterCount > 0 ? `${items.length}/${unfilteredCount}` : items.length} item${unfilteredCount === 1 ? '' : 's'})` }), markedCount > 0 && (
|
|
1041
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { wrap: "truncate", children: [_jsxs(Text, { bold: true, color: "cyan", children: [typeLabel, " \u2014 ", iteration] }), _jsx(Text, { dimColor: true, children: ` (${filterCount > 0 ? `${items.length}/${unfilteredCount}` : items.length} item${unfilteredCount === 1 ? '' : 's'})` }), markedCount > 0 && (_jsxs(Text, { color: "magenta", children: [` ● ${markedCount}`, markedDistribution.above > 0 && ` ↑${markedDistribution.above}`, markedDistribution.below > 0 && ` ↓${markedDistribution.below}`] })), filterCount > 0 && (_jsx(Text, { color: "yellow", children: ` [${filterCount} filter${filterCount === 1 ? '' : 's'}${activeViewName ? `: ${activeViewName}` : ''}]` }))] }) }), _jsx(TableLayout, { treeItems: visibleTreeItems, cursor: viewport.visibleCursor, capabilities: capabilities, collapsedIds: collapsedIds, markedIds: markedIds, terminalWidth: terminalWidth, sortStack: sortStack }), treeItems.length === 0 && !loading && initError && (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { color: "red", children: "Failed to connect to backend:" }), _jsx(Box, { marginLeft: 2, children: _jsx(Text, { color: "red", children: initError }) }), _jsx(Text, { dimColor: true, children: "Press , for settings or q to quit." })] })), treeItems.length === 0 && !loading && !initError && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, 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: true, 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: true, children: "\u2191\u2193 scroll space/esc close" }), positionText && _jsxs(Text, { dimColor: true, children: [" ", positionText] })] })) : activeOverlay?.type === 'command-bar' ? (_jsx(OverlayPanel, { title: "Commands", items: commandBarItems, placeholder: "Type to search...", externalFilter: true, onQueryChange: setCommandBarQuery, onSelect: (item) => {
|
|
983
1042
|
if (item.kind === 'issue') {
|
|
984
1043
|
const workItem = allSearchItems.find((i) => i.id === item.value);
|
|
985
1044
|
if (workItem)
|
|
@@ -1079,7 +1138,11 @@ export function WorkItemList() {
|
|
|
1079
1138
|
setToast(targetIds.length === 1
|
|
1080
1139
|
? 'Status updated — press u to undo'
|
|
1081
1140
|
: `${targetIds.length} items updated — press u to undo`);
|
|
1082
|
-
})()
|
|
1141
|
+
})().catch((err) => {
|
|
1142
|
+
uiStore
|
|
1143
|
+
.getState()
|
|
1144
|
+
.setToast(err instanceof Error ? err.message : 'Update failed');
|
|
1145
|
+
});
|
|
1083
1146
|
}, onCancel: () => closeOverlay() })) : activeOverlay?.type === 'type-picker' ? (_jsx(OverlayPanel, { title: "Set Type", items: types.map((t) => ({
|
|
1084
1147
|
id: t,
|
|
1085
1148
|
label: t.charAt(0).toUpperCase() + t.slice(1),
|
|
@@ -1103,7 +1166,11 @@ export function WorkItemList() {
|
|
|
1103
1166
|
setToast(targetIds.length === 1
|
|
1104
1167
|
? 'Type updated — press u to undo'
|
|
1105
1168
|
: `${targetIds.length} items updated — press u to undo`);
|
|
1106
|
-
})()
|
|
1169
|
+
})().catch((err) => {
|
|
1170
|
+
uiStore
|
|
1171
|
+
.getState()
|
|
1172
|
+
.setToast(err instanceof Error ? err.message : 'Update failed');
|
|
1173
|
+
});
|
|
1107
1174
|
}, onCancel: () => closeOverlay() })) : activeOverlay?.type === 'priority-picker' ? (_jsx(OverlayPanel, { title: "Set Priority", items: [
|
|
1108
1175
|
{ id: 'critical', label: 'Critical', value: 'critical' },
|
|
1109
1176
|
{ id: 'high', label: 'High', value: 'high' },
|
|
@@ -1127,7 +1194,11 @@ export function WorkItemList() {
|
|
|
1127
1194
|
setToast(targetIds.length === 1
|
|
1128
1195
|
? 'Priority updated — press u to undo'
|
|
1129
1196
|
: `${targetIds.length} items updated — press u to undo`);
|
|
1130
|
-
})()
|
|
1197
|
+
})().catch((err) => {
|
|
1198
|
+
uiStore
|
|
1199
|
+
.getState()
|
|
1200
|
+
.setToast(err instanceof Error ? err.message : 'Update failed');
|
|
1201
|
+
});
|
|
1131
1202
|
}, onCancel: () => closeOverlay() })) : activeOverlay?.type === 'template-picker' ? (_jsx(OverlayPanel, { title: "Select Template", items: [
|
|
1132
1203
|
{ id: '__none__', label: 'No template', value: '__none__' },
|
|
1133
1204
|
...templates.map((t) => ({
|
|
@@ -1180,7 +1251,7 @@ export function WorkItemList() {
|
|
|
1180
1251
|
setToast(targetIds.length === 1
|
|
1181
1252
|
? 'Parent updated — press u to undo'
|
|
1182
1253
|
: `${targetIds.length} items updated — press u to undo`);
|
|
1183
|
-
})();
|
|
1254
|
+
})().catch(() => { });
|
|
1184
1255
|
}, onSubmitFreeform: (text) => {
|
|
1185
1256
|
const targetIds = getOverlayTargetIds();
|
|
1186
1257
|
if (!backend)
|
|
@@ -1212,7 +1283,7 @@ export function WorkItemList() {
|
|
|
1212
1283
|
setToast(targetIds.length === 1
|
|
1213
1284
|
? 'Parent updated — press u to undo'
|
|
1214
1285
|
: `${targetIds.length} items updated — press u to undo`);
|
|
1215
|
-
})();
|
|
1286
|
+
})().catch(() => { });
|
|
1216
1287
|
}, onCancel: () => closeOverlay(), placeholder: "Type parent ID or title...", emptyMessage: "Type a parent ID (empty to clear)" })) : activeOverlay?.type === 'assignee-input' ? (_jsx(OverlayPanel, { title: `Set Assignee (${activeOverlay.targetIds.length} item${activeOverlay.targetIds.length > 1 ? 's' : ''})`, items: assignees.map((a) => ({ id: a, label: a, value: a })), allowFreeform: true, onSelect: (item) => {
|
|
1217
1288
|
const targetIds = getOverlayTargetIds();
|
|
1218
1289
|
closeOverlay();
|
|
@@ -1232,7 +1303,11 @@ export function WorkItemList() {
|
|
|
1232
1303
|
setToast(targetIds.length === 1
|
|
1233
1304
|
? 'Assignee updated — press u to undo'
|
|
1234
1305
|
: `${targetIds.length} items updated — press u to undo`);
|
|
1235
|
-
})()
|
|
1306
|
+
})().catch((err) => {
|
|
1307
|
+
uiStore
|
|
1308
|
+
.getState()
|
|
1309
|
+
.setToast(err instanceof Error ? err.message : 'Update failed');
|
|
1310
|
+
});
|
|
1236
1311
|
}, onSubmitFreeform: (text) => {
|
|
1237
1312
|
const targetIds = getOverlayTargetIds();
|
|
1238
1313
|
closeOverlay();
|
|
@@ -1252,7 +1327,11 @@ export function WorkItemList() {
|
|
|
1252
1327
|
setToast(targetIds.length === 1
|
|
1253
1328
|
? 'Assignee updated — press u to undo'
|
|
1254
1329
|
: `${targetIds.length} items updated — press u to undo`);
|
|
1255
|
-
})()
|
|
1330
|
+
})().catch((err) => {
|
|
1331
|
+
uiStore
|
|
1332
|
+
.getState()
|
|
1333
|
+
.setToast(err instanceof Error ? err.message : 'Update failed');
|
|
1334
|
+
});
|
|
1256
1335
|
}, onCancel: () => closeOverlay(), placeholder: "Type assignee name..." })) : activeOverlay?.type === 'labels-input' ? (_jsx(OverlayPanel, { title: `Set Labels (${activeOverlay.targetIds.length} item${activeOverlay.targetIds.length > 1 ? 's' : ''})`, items: labelSuggestions.map((l) => ({
|
|
1257
1336
|
id: l,
|
|
1258
1337
|
label: l,
|
|
@@ -1275,7 +1354,11 @@ export function WorkItemList() {
|
|
|
1275
1354
|
setToast(targetIds.length === 1
|
|
1276
1355
|
? 'Labels updated — press u to undo'
|
|
1277
1356
|
: `${targetIds.length} items updated — press u to undo`);
|
|
1278
|
-
})()
|
|
1357
|
+
})().catch((err) => {
|
|
1358
|
+
uiStore
|
|
1359
|
+
.getState()
|
|
1360
|
+
.setToast(err instanceof Error ? err.message : 'Update failed');
|
|
1361
|
+
});
|
|
1279
1362
|
}, onSubmitFreeform: (text) => {
|
|
1280
1363
|
const targetIds = getOverlayTargetIds();
|
|
1281
1364
|
closeOverlay();
|
|
@@ -1297,7 +1380,11 @@ export function WorkItemList() {
|
|
|
1297
1380
|
setToast(targetIds.length === 1
|
|
1298
1381
|
? 'Labels updated — press u to undo'
|
|
1299
1382
|
: `${targetIds.length} items updated — press u to undo`);
|
|
1300
|
-
})()
|
|
1383
|
+
})().catch((err) => {
|
|
1384
|
+
uiStore
|
|
1385
|
+
.getState()
|
|
1386
|
+
.setToast(err instanceof Error ? err.message : 'Update failed');
|
|
1387
|
+
});
|
|
1301
1388
|
}, onCancel: () => closeOverlay(), placeholder: "Type to filter labels..." })) : activeOverlay?.type === 'sort-picker' ? (_jsx(OverlayPanel, { title: "Order by", items: sortPickerItems, onSelect: (item) => {
|
|
1302
1389
|
closeOverlay();
|
|
1303
1390
|
if (item.value === '__clear__') {
|
|
@@ -1360,9 +1447,12 @@ export function WorkItemList() {
|
|
|
1360
1447
|
...(sortStack.length > 0 ? { sort: [...sortStack] } : {}),
|
|
1361
1448
|
};
|
|
1362
1449
|
const existing = savedViews.filter((v) => v.name !== lastViewName);
|
|
1363
|
-
void configStore
|
|
1450
|
+
void configStore
|
|
1451
|
+
.getState()
|
|
1452
|
+
.update({
|
|
1364
1453
|
views: [...existing, newView],
|
|
1365
|
-
})
|
|
1454
|
+
})
|
|
1455
|
+
.catch(() => { });
|
|
1366
1456
|
filterStore.setState({
|
|
1367
1457
|
activeViewName: lastViewName,
|
|
1368
1458
|
});
|
|
@@ -1388,11 +1478,17 @@ export function WorkItemList() {
|
|
|
1388
1478
|
}, onAction: (item) => {
|
|
1389
1479
|
if (item.value === '__no-filters__' ||
|
|
1390
1480
|
item.value === defaultView) {
|
|
1391
|
-
void configStore
|
|
1481
|
+
void configStore
|
|
1482
|
+
.getState()
|
|
1483
|
+
.update({ defaultView: undefined })
|
|
1484
|
+
.catch(() => { });
|
|
1392
1485
|
setToast('Default view cleared');
|
|
1393
1486
|
}
|
|
1394
1487
|
else {
|
|
1395
|
-
void configStore
|
|
1488
|
+
void configStore
|
|
1489
|
+
.getState()
|
|
1490
|
+
.update({ defaultView: item.value })
|
|
1491
|
+
.catch(() => { });
|
|
1396
1492
|
setToast(`View "${item.value}" set as default`);
|
|
1397
1493
|
}
|
|
1398
1494
|
}, onCancel: () => closeOverlay(), footer: "\u2191\u2193 navigate enter load tab set default esc cancel" })) : activeOverlay?.type === 'save-view-input' ? (_jsx(OverlayPanel, { title: "Save View", items: [], allowFreeform: true, onSelect: () => { }, onSubmitFreeform: (name) => {
|
|
@@ -1406,20 +1502,26 @@ export function WorkItemList() {
|
|
|
1406
1502
|
...(sortStack.length > 0 ? { sort: [...sortStack] } : {}),
|
|
1407
1503
|
};
|
|
1408
1504
|
const existing = savedViews.filter((v) => v.name !== name.trim());
|
|
1409
|
-
void configStore
|
|
1505
|
+
void configStore
|
|
1506
|
+
.getState()
|
|
1507
|
+
.update({
|
|
1410
1508
|
views: [...existing, newView],
|
|
1411
|
-
})
|
|
1509
|
+
})
|
|
1510
|
+
.catch(() => { });
|
|
1412
1511
|
filterStore.setState({ activeViewName: name.trim() });
|
|
1413
1512
|
closeOverlay();
|
|
1414
1513
|
setToast(`View "${name.trim()}" saved`);
|
|
1415
1514
|
}, onCancel: () => closeOverlay(), placeholder: "Enter view name...", emptyMessage: "Type a name and press enter" })) : activeOverlay?.type === 'delete-view-picker' ? (_jsx(OverlayPanel, { title: "Delete View", items: viewPickerItems.filter((i) => i.id !== '__no-filters__'), onSelect: (item) => {
|
|
1416
1515
|
const remaining = savedViews.filter((v) => v.name !== item.value);
|
|
1417
|
-
void configStore
|
|
1516
|
+
void configStore
|
|
1517
|
+
.getState()
|
|
1518
|
+
.update({
|
|
1418
1519
|
views: remaining,
|
|
1419
1520
|
...(defaultView === item.value
|
|
1420
1521
|
? { defaultView: undefined }
|
|
1421
1522
|
: {}),
|
|
1422
|
-
})
|
|
1523
|
+
})
|
|
1524
|
+
.catch(() => { });
|
|
1423
1525
|
if (activeViewName === item.value) {
|
|
1424
1526
|
filterStore.setState({ activeViewName: null });
|
|
1425
1527
|
}
|
|
@@ -1474,7 +1576,11 @@ export function WorkItemList() {
|
|
|
1474
1576
|
setToast(targetIds.length === 1
|
|
1475
1577
|
? `Item #${targetIds[0]} deleted${softDelete ? ' — press u to undo' : ''}`
|
|
1476
1578
|
: `${targetIds.length} items deleted${softDelete ? ' — press u to undo' : ''}`);
|
|
1477
|
-
})()
|
|
1579
|
+
})().catch((err) => {
|
|
1580
|
+
uiStore
|
|
1581
|
+
.getState()
|
|
1582
|
+
.setToast(err instanceof Error ? err.message : 'Delete failed');
|
|
1583
|
+
});
|
|
1478
1584
|
}
|
|
1479
1585
|
else {
|
|
1480
1586
|
closeOverlay();
|