agent-tasks 1.9.5 → 1.9.7
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/dist/ui/app.js +401 -356
- package/dist/ui/drag.js +1 -1
- package/dist/ui/index.html +1 -0
- package/dist/ui/inline-edit.js +2 -2
- package/dist/ui/panel.js +4 -4
- package/dist/ui/template.js +91 -0
- package/package.json +1 -1
package/dist/ui/app.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
//
|
|
4
4
|
// WebSocket connection, state management, initialization, tab/filter management,
|
|
5
5
|
// theme, keyboard navigation, cleanup dialog, theme sync.
|
|
6
|
-
// Modules: ui-utils.js, board.js, panel.js, drag.js, inline-edit.js
|
|
6
|
+
// Modules: ui-utils.js, board.js, panel.js, drag.js, inline-edit.js, template.js
|
|
7
7
|
// =============================================================================
|
|
8
8
|
|
|
9
9
|
window.TaskBoard = window.TaskBoard || {};
|
|
@@ -25,6 +25,12 @@ var state = {
|
|
|
25
25
|
|
|
26
26
|
TaskBoard.state = state;
|
|
27
27
|
|
|
28
|
+
TaskBoard._baseUrl = '';
|
|
29
|
+
TaskBoard._fetch = function (url, opts) {
|
|
30
|
+
return fetch(TaskBoard._baseUrl + url, opts);
|
|
31
|
+
};
|
|
32
|
+
TaskBoard._wsUrl = null;
|
|
33
|
+
|
|
28
34
|
var filters = {
|
|
29
35
|
search: '',
|
|
30
36
|
project: '',
|
|
@@ -73,22 +79,6 @@ function updateThemeIcon(theme) {
|
|
|
73
79
|
if (icon) icon.textContent = theme === 'dark' ? 'light_mode' : 'dark_mode';
|
|
74
80
|
}
|
|
75
81
|
|
|
76
|
-
var savedTheme = localStorage.getItem('agent-tasks-theme');
|
|
77
|
-
if (savedTheme === 'dark') document.documentElement.setAttribute('data-theme', 'dark');
|
|
78
|
-
updateThemeIcon(savedTheme || 'light');
|
|
79
|
-
|
|
80
|
-
document.getElementById('theme-toggle').addEventListener('click', () => {
|
|
81
|
-
var isDark = document.documentElement.getAttribute('data-theme') === 'dark';
|
|
82
|
-
var next = isDark ? 'light' : 'dark';
|
|
83
|
-
if (isDark) {
|
|
84
|
-
document.documentElement.removeAttribute('data-theme');
|
|
85
|
-
} else {
|
|
86
|
-
document.documentElement.setAttribute('data-theme', 'dark');
|
|
87
|
-
}
|
|
88
|
-
localStorage.setItem('agent-tasks-theme', next);
|
|
89
|
-
updateThemeIcon(next);
|
|
90
|
-
});
|
|
91
|
-
|
|
92
82
|
// ---- Blocked tasks ----
|
|
93
83
|
|
|
94
84
|
function getBlockedTaskIds() {
|
|
@@ -146,37 +136,6 @@ function updateFilterDropdowns() {
|
|
|
146
136
|
assigneeSelect.value = currentAssignee;
|
|
147
137
|
}
|
|
148
138
|
|
|
149
|
-
document.getElementById('filter-search').addEventListener('input', (e) => {
|
|
150
|
-
clearTimeout(searchDebounce);
|
|
151
|
-
searchDebounce = setTimeout(() => {
|
|
152
|
-
filters.search = e.target.value;
|
|
153
|
-
saveFilters();
|
|
154
|
-
TaskBoard.resetColumnVisibleCounts();
|
|
155
|
-
render();
|
|
156
|
-
}, 200);
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
document.getElementById('filter-project').addEventListener('change', (e) => {
|
|
160
|
-
filters.project = e.target.value;
|
|
161
|
-
saveFilters();
|
|
162
|
-
TaskBoard.resetColumnVisibleCounts();
|
|
163
|
-
render();
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
document.getElementById('filter-assignee').addEventListener('change', (e) => {
|
|
167
|
-
filters.assignee = e.target.value;
|
|
168
|
-
saveFilters();
|
|
169
|
-
TaskBoard.resetColumnVisibleCounts();
|
|
170
|
-
render();
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
document.getElementById('filter-priority').addEventListener('change', (e) => {
|
|
174
|
-
filters.minPriority = parseInt(e.target.value) || 0;
|
|
175
|
-
saveFilters();
|
|
176
|
-
TaskBoard.resetColumnVisibleCounts();
|
|
177
|
-
render();
|
|
178
|
-
});
|
|
179
|
-
|
|
180
139
|
function applyRestoredFilters() {
|
|
181
140
|
var searchInput = document.getElementById('filter-search');
|
|
182
141
|
if (filters.search && searchInput) searchInput.value = filters.search;
|
|
@@ -199,7 +158,7 @@ function render() {
|
|
|
199
158
|
|
|
200
159
|
function connect() {
|
|
201
160
|
var proto = location.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
202
|
-
ws = new WebSocket(`${proto}//${location.host}`);
|
|
161
|
+
ws = new WebSocket(`${proto}//${TaskBoard._wsUrl || location.host}`);
|
|
203
162
|
setConnectionStatus('connecting');
|
|
204
163
|
|
|
205
164
|
ws.onopen = () => setConnectionStatus('connected');
|
|
@@ -395,365 +354,451 @@ function handleEvent(event) {
|
|
|
395
354
|
}
|
|
396
355
|
}
|
|
397
356
|
|
|
398
|
-
// ----
|
|
399
|
-
|
|
400
|
-
document.getElementById('board').addEventListener('click', (e) => {
|
|
401
|
-
var action = e.target.closest('[data-action]');
|
|
357
|
+
// ---- Legacy Modal (cleanup only) ----
|
|
402
358
|
|
|
403
|
-
|
|
404
|
-
|
|
359
|
+
function closeModal() {
|
|
360
|
+
document.getElementById('task-modal').hidden = true;
|
|
361
|
+
}
|
|
405
362
|
|
|
406
|
-
|
|
407
|
-
e.stopPropagation();
|
|
408
|
-
var stage = action.dataset.stage;
|
|
409
|
-
if (state.collapsedColumns.has(stage)) {
|
|
410
|
-
state.collapsedColumns.delete(stage);
|
|
411
|
-
} else {
|
|
412
|
-
state.collapsedColumns.add(stage);
|
|
413
|
-
}
|
|
414
|
-
saveCollapsed();
|
|
415
|
-
render();
|
|
416
|
-
return;
|
|
417
|
-
}
|
|
363
|
+
// ---- Init ----
|
|
418
364
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
}
|
|
365
|
+
function _init() {
|
|
366
|
+
var savedTheme = localStorage.getItem('agent-tasks-theme');
|
|
367
|
+
if (savedTheme === 'dark') document.documentElement.setAttribute('data-theme', 'dark');
|
|
368
|
+
updateThemeIcon(savedTheme || 'light');
|
|
424
369
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
370
|
+
document.getElementById('theme-toggle')?.addEventListener('click', () => {
|
|
371
|
+
var isDark = document.documentElement.getAttribute('data-theme') === 'dark';
|
|
372
|
+
var next = isDark ? 'light' : 'dark';
|
|
373
|
+
if (isDark) {
|
|
374
|
+
document.documentElement.removeAttribute('data-theme');
|
|
375
|
+
} else {
|
|
376
|
+
document.documentElement.setAttribute('data-theme', 'dark');
|
|
429
377
|
}
|
|
378
|
+
localStorage.setItem('agent-tasks-theme', next);
|
|
379
|
+
updateThemeIcon(next);
|
|
380
|
+
});
|
|
430
381
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
382
|
+
document.getElementById('filter-search')?.addEventListener('input', (e) => {
|
|
383
|
+
clearTimeout(searchDebounce);
|
|
384
|
+
searchDebounce = setTimeout(() => {
|
|
385
|
+
filters.search = e.target.value;
|
|
386
|
+
saveFilters();
|
|
387
|
+
TaskBoard.resetColumnVisibleCounts();
|
|
388
|
+
render();
|
|
389
|
+
}, 200);
|
|
390
|
+
});
|
|
436
391
|
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
392
|
+
document.getElementById('filter-project')?.addEventListener('change', (e) => {
|
|
393
|
+
filters.project = e.target.value;
|
|
394
|
+
saveFilters();
|
|
395
|
+
TaskBoard.resetColumnVisibleCounts();
|
|
396
|
+
render();
|
|
397
|
+
});
|
|
442
398
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
}
|
|
399
|
+
document.getElementById('filter-assignee')?.addEventListener('change', (e) => {
|
|
400
|
+
filters.assignee = e.target.value;
|
|
401
|
+
saveFilters();
|
|
402
|
+
TaskBoard.resetColumnVisibleCounts();
|
|
403
|
+
render();
|
|
404
|
+
});
|
|
450
405
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
406
|
+
document.getElementById('filter-priority')?.addEventListener('change', (e) => {
|
|
407
|
+
filters.minPriority = parseInt(e.target.value) || 0;
|
|
408
|
+
saveFilters();
|
|
409
|
+
TaskBoard.resetColumnVisibleCounts();
|
|
410
|
+
render();
|
|
411
|
+
});
|
|
456
412
|
|
|
457
|
-
|
|
458
|
-
var titleEl = e.target.closest('[data-action="edit-title"]');
|
|
459
|
-
if (titleEl) {
|
|
460
|
-
e.stopPropagation();
|
|
461
|
-
TaskBoard.startInlineEdit(titleEl);
|
|
462
|
-
}
|
|
463
|
-
});
|
|
413
|
+
// ---- Event Delegation (board) ----
|
|
464
414
|
|
|
465
|
-
document.getElementById('board')
|
|
466
|
-
|
|
467
|
-
var card = e.target.closest('.task-card[data-task-id]');
|
|
468
|
-
if (card) TaskBoard.openPanel(parseInt(card.dataset.taskId, 10));
|
|
469
|
-
}
|
|
470
|
-
});
|
|
415
|
+
document.getElementById('board')?.addEventListener('click', (e) => {
|
|
416
|
+
var action = e.target.closest('[data-action]');
|
|
471
417
|
|
|
472
|
-
|
|
418
|
+
if (action) {
|
|
419
|
+
var act = action.dataset.action;
|
|
473
420
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
421
|
+
if (act === 'toggle-collapse') {
|
|
422
|
+
e.stopPropagation();
|
|
423
|
+
var stage = action.dataset.stage;
|
|
424
|
+
if (state.collapsedColumns.has(stage)) {
|
|
425
|
+
state.collapsedColumns.delete(stage);
|
|
426
|
+
} else {
|
|
427
|
+
state.collapsedColumns.add(stage);
|
|
428
|
+
}
|
|
429
|
+
saveCollapsed();
|
|
430
|
+
render();
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
483
433
|
|
|
484
|
-
|
|
434
|
+
if (act === 'inline-create') {
|
|
435
|
+
e.stopPropagation();
|
|
436
|
+
TaskBoard.showInlineCreate(action.dataset.stage);
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
485
439
|
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
440
|
+
if (act === 'add-task') {
|
|
441
|
+
e.stopPropagation();
|
|
442
|
+
TaskBoard.showInlineCreate(action.dataset.stage);
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
489
445
|
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
446
|
+
if (act === 'cycle-priority') {
|
|
447
|
+
e.stopPropagation();
|
|
448
|
+
TaskBoard.cyclePriority(parseInt(action.dataset.taskId, 10));
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
494
451
|
|
|
495
|
-
|
|
452
|
+
if (act === 'change-assignee') {
|
|
453
|
+
e.stopPropagation();
|
|
454
|
+
TaskBoard.showAssigneeDropdown(parseInt(action.dataset.taskId, 10), action);
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
496
457
|
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
458
|
+
if (act === 'show-more') {
|
|
459
|
+
e.stopPropagation();
|
|
460
|
+
TaskBoard.showMoreCards(action.dataset.stage);
|
|
461
|
+
render();
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
502
464
|
}
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
465
|
+
|
|
466
|
+
var card = e.target.closest('.task-card[data-task-id]');
|
|
467
|
+
if (card) {
|
|
468
|
+
TaskBoard.openPanel(parseInt(card.dataset.taskId, 10));
|
|
506
469
|
}
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
document.getElementById('board')?.addEventListener('dblclick', (e) => {
|
|
473
|
+
var titleEl = e.target.closest('[data-action="edit-title"]');
|
|
474
|
+
if (titleEl) {
|
|
475
|
+
e.stopPropagation();
|
|
476
|
+
TaskBoard.startInlineEdit(titleEl);
|
|
510
477
|
}
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
478
|
+
});
|
|
479
|
+
|
|
480
|
+
document.getElementById('board')?.addEventListener('keydown', (e) => {
|
|
481
|
+
if (e.key === 'Enter') {
|
|
482
|
+
var card = e.target.closest('.task-card[data-task-id]');
|
|
483
|
+
if (card) TaskBoard.openPanel(parseInt(card.dataset.taskId, 10));
|
|
515
484
|
}
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
// ---- Collapsed column click (expand) ----
|
|
488
|
+
|
|
489
|
+
document.getElementById('board')?.addEventListener('click', (e) => {
|
|
490
|
+
var col = e.target.closest('.kanban-column.collapsed');
|
|
491
|
+
if (col) {
|
|
492
|
+
var stage = col.dataset.stage;
|
|
493
|
+
state.collapsedColumns.delete(stage);
|
|
494
|
+
saveCollapsed();
|
|
495
|
+
render();
|
|
520
496
|
}
|
|
521
|
-
}
|
|
497
|
+
});
|
|
522
498
|
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
if (
|
|
529
|
-
(e.key === '/' && !e.ctrlKey && !e.metaKey && !isInput) ||
|
|
530
|
-
((e.ctrlKey || e.metaKey) && e.key === 'k')
|
|
531
|
-
) {
|
|
532
|
-
e.preventDefault();
|
|
533
|
-
document.getElementById('filter-search').focus();
|
|
534
|
-
}
|
|
535
|
-
});
|
|
499
|
+
document.getElementById('modal-close-btn')?.addEventListener('click', closeModal);
|
|
500
|
+
document.getElementById('task-modal')?.addEventListener('click', (e) => {
|
|
501
|
+
if (e.target === e.currentTarget) closeModal();
|
|
502
|
+
});
|
|
536
503
|
|
|
537
|
-
// ----
|
|
504
|
+
// ---- Keyboard Navigation ----
|
|
538
505
|
|
|
539
|
-
document.
|
|
540
|
-
|
|
541
|
-
|
|
506
|
+
document.addEventListener('keydown', (e) => {
|
|
507
|
+
if (e.key === 'Escape') {
|
|
508
|
+
if (TaskBoard.getActiveDropdown()) {
|
|
509
|
+
TaskBoard.dismissDropdown();
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
if (TaskBoard.getActiveInlineCreate()) {
|
|
513
|
+
TaskBoard.dismissInlineCreate();
|
|
514
|
+
return;
|
|
515
|
+
}
|
|
516
|
+
if (state.panelTaskId) {
|
|
517
|
+
TaskBoard.closePanel();
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
var modal = document.getElementById('task-modal');
|
|
521
|
+
if (modal && !modal.hidden) {
|
|
522
|
+
closeModal();
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
525
|
+
var cleanupModal = document.getElementById('cleanup-modal');
|
|
526
|
+
if (cleanupModal && !cleanupModal.classList.contains('hidden')) {
|
|
527
|
+
cleanupModal.classList.add('hidden');
|
|
528
|
+
return;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
var isInput =
|
|
533
|
+
document.activeElement?.tagName === 'INPUT' ||
|
|
534
|
+
document.activeElement?.tagName === 'TEXTAREA' ||
|
|
535
|
+
document.activeElement?.getAttribute('contenteditable') === 'true';
|
|
536
|
+
|
|
537
|
+
if (
|
|
538
|
+
(e.key === '/' && !e.ctrlKey && !e.metaKey && !isInput) ||
|
|
539
|
+
((e.ctrlKey || e.metaKey) && e.key === 'k')
|
|
540
|
+
) {
|
|
541
|
+
e.preventDefault();
|
|
542
|
+
document.getElementById('filter-search')?.focus();
|
|
543
|
+
}
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
// ---- Cleanup Dialog ----
|
|
542
547
|
|
|
543
|
-
document.getElementById('cleanup-
|
|
544
|
-
|
|
545
|
-
});
|
|
548
|
+
document.getElementById('cleanup-btn')?.addEventListener('click', () => {
|
|
549
|
+
document.getElementById('cleanup-modal').classList.remove('hidden');
|
|
550
|
+
});
|
|
546
551
|
|
|
547
|
-
document.getElementById('cleanup-
|
|
548
|
-
if (e.target === e.currentTarget) {
|
|
552
|
+
document.getElementById('cleanup-close-btn')?.addEventListener('click', () => {
|
|
549
553
|
document.getElementById('cleanup-modal').classList.add('hidden');
|
|
550
|
-
}
|
|
551
|
-
});
|
|
554
|
+
});
|
|
552
555
|
|
|
553
|
-
document.getElementById('cleanup-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
.
|
|
562
|
-
.
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
'success',
|
|
567
|
-
);
|
|
556
|
+
document.getElementById('cleanup-modal')?.addEventListener('click', (e) => {
|
|
557
|
+
if (e.target === e.currentTarget) {
|
|
558
|
+
document.getElementById('cleanup-modal').classList.add('hidden');
|
|
559
|
+
}
|
|
560
|
+
});
|
|
561
|
+
|
|
562
|
+
document.getElementById('cleanup-completed')?.addEventListener('click', () => {
|
|
563
|
+
var showToast = TaskBoard.showToast;
|
|
564
|
+
document.getElementById('cleanup-modal').classList.add('hidden');
|
|
565
|
+
TaskBoard._fetch('/api/cleanup', {
|
|
566
|
+
method: 'POST',
|
|
567
|
+
headers: { 'Content-Type': 'application/json' },
|
|
568
|
+
body: JSON.stringify({ force: true }),
|
|
568
569
|
})
|
|
569
|
-
|
|
570
|
-
|
|
570
|
+
.then((r) => r.json())
|
|
571
|
+
.then((result) => {
|
|
572
|
+
showToast(
|
|
573
|
+
'Cleanup complete',
|
|
574
|
+
`Purged ${result.purgedTasks} tasks, ${result.purgedComments} comments, ${result.purgedApprovals} approvals`,
|
|
575
|
+
'success',
|
|
576
|
+
);
|
|
577
|
+
})
|
|
578
|
+
.catch(() => showToast('Cleanup failed', 'Network error', 'error'));
|
|
579
|
+
});
|
|
571
580
|
|
|
572
|
-
document.getElementById('cleanup-everything')?.addEventListener('click', () => {
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
581
|
+
document.getElementById('cleanup-everything')?.addEventListener('click', () => {
|
|
582
|
+
var showToast = TaskBoard.showToast;
|
|
583
|
+
if (
|
|
584
|
+
!confirm(
|
|
585
|
+
'This will remove ALL tasks — completed, in-progress, everything. This cannot be undone. Continue?',
|
|
586
|
+
)
|
|
577
587
|
)
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
body: JSON.stringify({ all: true }),
|
|
585
|
-
})
|
|
586
|
-
.then((r) => r.json())
|
|
587
|
-
.then((result) => {
|
|
588
|
-
showToast(
|
|
589
|
-
'Everything purged',
|
|
590
|
-
`Purged ${result.purgedTasks} tasks, ${result.purgedComments} comments, ${result.purgedApprovals} approvals`,
|
|
591
|
-
'success',
|
|
592
|
-
);
|
|
588
|
+
return;
|
|
589
|
+
document.getElementById('cleanup-modal').classList.add('hidden');
|
|
590
|
+
TaskBoard._fetch('/api/cleanup', {
|
|
591
|
+
method: 'POST',
|
|
592
|
+
headers: { 'Content-Type': 'application/json' },
|
|
593
|
+
body: JSON.stringify({ all: true }),
|
|
593
594
|
})
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
function ensureContrast(bg, fg) {
|
|
605
|
-
var lum = function (hex) {
|
|
606
|
-
if (!hex || hex.charAt(0) !== '#' || hex.length < 7) return 0.5;
|
|
607
|
-
var r = parseInt(hex.slice(1, 3), 16) / 255;
|
|
608
|
-
var g = parseInt(hex.slice(3, 5), 16) / 255;
|
|
609
|
-
var b = parseInt(hex.slice(5, 7), 16) / 255;
|
|
610
|
-
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
|
611
|
-
};
|
|
612
|
-
var bgLum = lum(bg);
|
|
613
|
-
return bgLum < 0.5 ? (lum(fg) < 0.4 ? '#e0e0e0' : fg) : lum(fg) > 0.6 ? '#333333' : fg;
|
|
614
|
-
}
|
|
595
|
+
.then((r) => r.json())
|
|
596
|
+
.then((result) => {
|
|
597
|
+
showToast(
|
|
598
|
+
'Everything purged',
|
|
599
|
+
`Purged ${result.purgedTasks} tasks, ${result.purgedComments} comments, ${result.purgedApprovals} approvals`,
|
|
600
|
+
'success',
|
|
601
|
+
);
|
|
602
|
+
})
|
|
603
|
+
.catch(() => showToast('Cleanup failed', 'Network error', 'error'));
|
|
604
|
+
});
|
|
615
605
|
|
|
616
|
-
|
|
617
|
-
|
|
606
|
+
// ---- Theme sync from parent (agent-desk) via executeJavaScript ----
|
|
607
|
+
|
|
608
|
+
window.addEventListener('message', function (event) {
|
|
609
|
+
if (!event.data || event.data.type !== 'theme-sync') return;
|
|
610
|
+
var colors = event.data.colors;
|
|
611
|
+
if (!colors) return;
|
|
612
|
+
|
|
613
|
+
function ensureContrast(bg, fg) {
|
|
614
|
+
var lum = function (hex) {
|
|
615
|
+
if (!hex || hex.charAt(0) !== '#' || hex.length < 7) return 0.5;
|
|
616
|
+
var r = parseInt(hex.slice(1, 3), 16) / 255;
|
|
617
|
+
var g = parseInt(hex.slice(3, 5), 16) / 255;
|
|
618
|
+
var b = parseInt(hex.slice(5, 7), 16) / 255;
|
|
619
|
+
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
|
620
|
+
};
|
|
621
|
+
var bgLum = lum(bg);
|
|
622
|
+
return bgLum < 0.5 ? (lum(fg) < 0.4 ? '#e0e0e0' : fg) : lum(fg) > 0.6 ? '#333333' : fg;
|
|
623
|
+
}
|
|
618
624
|
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
if (colors.bgElevated) root.style.setProperty('--bg-elevated', colors.bgElevated);
|
|
622
|
-
if (colors.bgHover) root.style.setProperty('--bg-hover', colors.bgHover);
|
|
623
|
-
if (colors.bgInset) root.style.setProperty('--bg-inset', colors.bgInset);
|
|
625
|
+
var root = document.documentElement;
|
|
626
|
+
var bgColor = colors.bg || null;
|
|
624
627
|
|
|
625
|
-
|
|
626
|
-
|
|
628
|
+
if (colors.bg) root.style.setProperty('--bg', colors.bg);
|
|
629
|
+
if (colors.bgSurface) root.style.setProperty('--bg-surface', colors.bgSurface);
|
|
630
|
+
if (colors.bgElevated) root.style.setProperty('--bg-elevated', colors.bgElevated);
|
|
631
|
+
if (colors.bgHover) root.style.setProperty('--bg-hover', colors.bgHover);
|
|
632
|
+
if (colors.bgInset) root.style.setProperty('--bg-inset', colors.bgInset);
|
|
627
633
|
|
|
628
|
-
|
|
629
|
-
root.style.setProperty('--
|
|
630
|
-
if (colors.textSecondary)
|
|
631
|
-
root.style.setProperty(
|
|
632
|
-
'--text-secondary',
|
|
633
|
-
bgColor ? ensureContrast(bgColor, colors.textSecondary) : colors.textSecondary,
|
|
634
|
-
);
|
|
635
|
-
if (colors.textMuted)
|
|
636
|
-
root.style.setProperty(
|
|
637
|
-
'--text-muted',
|
|
638
|
-
bgColor ? ensureContrast(bgColor, colors.textMuted) : colors.textMuted,
|
|
639
|
-
);
|
|
640
|
-
if (colors.textDim)
|
|
641
|
-
root.style.setProperty(
|
|
642
|
-
'--text-dim',
|
|
643
|
-
bgColor ? ensureContrast(bgColor, colors.textDim) : colors.textDim,
|
|
644
|
-
);
|
|
634
|
+
if (colors.border) root.style.setProperty('--border', colors.border);
|
|
635
|
+
if (colors.borderLight) root.style.setProperty('--border-light', colors.borderLight);
|
|
645
636
|
|
|
646
|
-
|
|
647
|
-
if (colors.accentHover) root.style.setProperty('--accent-hover', colors.accentHover);
|
|
648
|
-
if (colors.accentDim) root.style.setProperty('--accent-dim', colors.accentDim);
|
|
649
|
-
if (colors.accentSolid) root.style.setProperty('--accent-solid', colors.accentSolid);
|
|
650
|
-
if (colors.accentGlow) root.style.setProperty('--accent-glow', colors.accentGlow);
|
|
651
|
-
|
|
652
|
-
if (colors.green) root.style.setProperty('--green', colors.green);
|
|
653
|
-
if (colors.greenDim) root.style.setProperty('--green-dim', colors.greenDim);
|
|
654
|
-
if (colors.yellow) root.style.setProperty('--yellow', colors.yellow);
|
|
655
|
-
if (colors.yellowDim) root.style.setProperty('--yellow-dim', colors.yellowDim);
|
|
656
|
-
if (colors.orange) root.style.setProperty('--orange', colors.orange);
|
|
657
|
-
if (colors.orangeDim) root.style.setProperty('--orange-dim', colors.orangeDim);
|
|
658
|
-
if (colors.red) root.style.setProperty('--red', colors.red);
|
|
659
|
-
if (colors.redDim) root.style.setProperty('--red-dim', colors.redDim);
|
|
660
|
-
if (colors.purple) root.style.setProperty('--purple', colors.purple);
|
|
661
|
-
if (colors.purpleDim) root.style.setProperty('--purple-dim', colors.purpleDim);
|
|
662
|
-
if (colors.blue) root.style.setProperty('--blue', colors.blue);
|
|
663
|
-
if (colors.blueDim) root.style.setProperty('--blue-dim', colors.blueDim);
|
|
664
|
-
if (colors.indigo) root.style.setProperty('--indigo', colors.indigo);
|
|
665
|
-
if (colors.indigoDim) root.style.setProperty('--indigo-dim', colors.indigoDim);
|
|
666
|
-
if (colors.amber) root.style.setProperty('--amber', colors.amber);
|
|
667
|
-
if (colors.amberDim) root.style.setProperty('--amber-dim', colors.amberDim);
|
|
668
|
-
if (colors.gray) root.style.setProperty('--gray', colors.gray);
|
|
669
|
-
if (colors.grayDim) root.style.setProperty('--gray-dim', colors.grayDim);
|
|
670
|
-
|
|
671
|
-
if (colors.stageBacklog) root.style.setProperty('--stage-backlog', colors.stageBacklog);
|
|
672
|
-
if (colors.stageSpec) root.style.setProperty('--stage-spec', colors.stageSpec);
|
|
673
|
-
if (colors.stagePlan) root.style.setProperty('--stage-plan', colors.stagePlan);
|
|
674
|
-
if (colors.stageImplement) root.style.setProperty('--stage-implement', colors.stageImplement);
|
|
675
|
-
if (colors.stageTest) root.style.setProperty('--stage-test', colors.stageTest);
|
|
676
|
-
if (colors.stageReview) root.style.setProperty('--stage-review', colors.stageReview);
|
|
677
|
-
if (colors.stageDone) root.style.setProperty('--stage-done', colors.stageDone);
|
|
678
|
-
if (colors.stageCancelled) root.style.setProperty('--stage-cancelled', colors.stageCancelled);
|
|
679
|
-
|
|
680
|
-
if (colors.focusRing) root.style.setProperty('--focus-ring', colors.focusRing);
|
|
681
|
-
|
|
682
|
-
if (colors.isDark !== undefined) {
|
|
683
|
-
if (colors.isDark) {
|
|
684
|
-
root.style.setProperty(
|
|
685
|
-
'--shadow-1',
|
|
686
|
-
'0px 1px 2px 0px rgba(0,0,0,0.6), 0px 1px 3px 1px rgba(0,0,0,0.3)',
|
|
687
|
-
);
|
|
688
|
-
root.style.setProperty(
|
|
689
|
-
'--shadow-2',
|
|
690
|
-
'0px 1px 2px 0px rgba(0,0,0,0.6), 0px 2px 6px 2px rgba(0,0,0,0.3)',
|
|
691
|
-
);
|
|
692
|
-
root.style.setProperty(
|
|
693
|
-
'--shadow-3',
|
|
694
|
-
'0px 1px 3px 0px rgba(0,0,0,0.6), 0px 4px 8px 3px rgba(0,0,0,0.3)',
|
|
695
|
-
);
|
|
637
|
+
if (colors.text)
|
|
696
638
|
root.style.setProperty(
|
|
697
|
-
'--
|
|
698
|
-
|
|
639
|
+
'--text',
|
|
640
|
+
bgColor ? ensureContrast(bgColor, colors.text) : colors.text,
|
|
699
641
|
);
|
|
642
|
+
if (colors.textSecondary)
|
|
700
643
|
root.style.setProperty(
|
|
701
|
-
'--
|
|
702
|
-
|
|
644
|
+
'--text-secondary',
|
|
645
|
+
bgColor ? ensureContrast(bgColor, colors.textSecondary) : colors.textSecondary,
|
|
703
646
|
);
|
|
647
|
+
if (colors.textMuted)
|
|
704
648
|
root.style.setProperty(
|
|
705
|
-
'--
|
|
706
|
-
|
|
707
|
-
);
|
|
708
|
-
} else {
|
|
709
|
-
root.style.setProperty(
|
|
710
|
-
'--shadow-1',
|
|
711
|
-
'0px 1px 2px 0px rgba(0,0,0,0.3), 0px 1px 3px 1px rgba(0,0,0,0.15)',
|
|
712
|
-
);
|
|
713
|
-
root.style.setProperty(
|
|
714
|
-
'--shadow-2',
|
|
715
|
-
'0px 1px 2px 0px rgba(0,0,0,0.3), 0px 2px 6px 2px rgba(0,0,0,0.15)',
|
|
716
|
-
);
|
|
717
|
-
root.style.setProperty(
|
|
718
|
-
'--shadow-3',
|
|
719
|
-
'0px 1px 3px 0px rgba(0,0,0,0.3), 0px 4px 8px 3px rgba(0,0,0,0.15)',
|
|
720
|
-
);
|
|
721
|
-
root.style.setProperty(
|
|
722
|
-
'--shadow-hover',
|
|
723
|
-
'0px 2px 4px 0px rgba(0,0,0,0.25), 0px 4px 12px 4px rgba(0,0,0,0.15)',
|
|
649
|
+
'--text-muted',
|
|
650
|
+
bgColor ? ensureContrast(bgColor, colors.textMuted) : colors.textMuted,
|
|
724
651
|
);
|
|
652
|
+
if (colors.textDim)
|
|
725
653
|
root.style.setProperty(
|
|
726
|
-
'--
|
|
727
|
-
|
|
728
|
-
);
|
|
729
|
-
root.style.setProperty(
|
|
730
|
-
'--shadow-panel',
|
|
731
|
-
'-2px 0px 8px 0px rgba(0,0,0,0.3), -4px 0px 16px 2px rgba(0,0,0,0.15)',
|
|
654
|
+
'--text-dim',
|
|
655
|
+
bgColor ? ensureContrast(bgColor, colors.textDim) : colors.textDim,
|
|
732
656
|
);
|
|
657
|
+
|
|
658
|
+
if (colors.accent) root.style.setProperty('--accent', colors.accent);
|
|
659
|
+
if (colors.accentHover) root.style.setProperty('--accent-hover', colors.accentHover);
|
|
660
|
+
if (colors.accentDim) root.style.setProperty('--accent-dim', colors.accentDim);
|
|
661
|
+
if (colors.accentSolid) root.style.setProperty('--accent-solid', colors.accentSolid);
|
|
662
|
+
if (colors.accentGlow) root.style.setProperty('--accent-glow', colors.accentGlow);
|
|
663
|
+
|
|
664
|
+
if (colors.green) root.style.setProperty('--green', colors.green);
|
|
665
|
+
if (colors.greenDim) root.style.setProperty('--green-dim', colors.greenDim);
|
|
666
|
+
if (colors.yellow) root.style.setProperty('--yellow', colors.yellow);
|
|
667
|
+
if (colors.yellowDim) root.style.setProperty('--yellow-dim', colors.yellowDim);
|
|
668
|
+
if (colors.orange) root.style.setProperty('--orange', colors.orange);
|
|
669
|
+
if (colors.orangeDim) root.style.setProperty('--orange-dim', colors.orangeDim);
|
|
670
|
+
if (colors.red) root.style.setProperty('--red', colors.red);
|
|
671
|
+
if (colors.redDim) root.style.setProperty('--red-dim', colors.redDim);
|
|
672
|
+
if (colors.purple) root.style.setProperty('--purple', colors.purple);
|
|
673
|
+
if (colors.purpleDim) root.style.setProperty('--purple-dim', colors.purpleDim);
|
|
674
|
+
if (colors.blue) root.style.setProperty('--blue', colors.blue);
|
|
675
|
+
if (colors.blueDim) root.style.setProperty('--blue-dim', colors.blueDim);
|
|
676
|
+
if (colors.indigo) root.style.setProperty('--indigo', colors.indigo);
|
|
677
|
+
if (colors.indigoDim) root.style.setProperty('--indigo-dim', colors.indigoDim);
|
|
678
|
+
if (colors.amber) root.style.setProperty('--amber', colors.amber);
|
|
679
|
+
if (colors.amberDim) root.style.setProperty('--amber-dim', colors.amberDim);
|
|
680
|
+
if (colors.gray) root.style.setProperty('--gray', colors.gray);
|
|
681
|
+
if (colors.grayDim) root.style.setProperty('--gray-dim', colors.grayDim);
|
|
682
|
+
|
|
683
|
+
if (colors.stageBacklog) root.style.setProperty('--stage-backlog', colors.stageBacklog);
|
|
684
|
+
if (colors.stageSpec) root.style.setProperty('--stage-spec', colors.stageSpec);
|
|
685
|
+
if (colors.stagePlan) root.style.setProperty('--stage-plan', colors.stagePlan);
|
|
686
|
+
if (colors.stageImplement) root.style.setProperty('--stage-implement', colors.stageImplement);
|
|
687
|
+
if (colors.stageTest) root.style.setProperty('--stage-test', colors.stageTest);
|
|
688
|
+
if (colors.stageReview) root.style.setProperty('--stage-review', colors.stageReview);
|
|
689
|
+
if (colors.stageDone) root.style.setProperty('--stage-done', colors.stageDone);
|
|
690
|
+
if (colors.stageCancelled) root.style.setProperty('--stage-cancelled', colors.stageCancelled);
|
|
691
|
+
|
|
692
|
+
if (colors.focusRing) root.style.setProperty('--focus-ring', colors.focusRing);
|
|
693
|
+
|
|
694
|
+
if (colors.isDark !== undefined) {
|
|
695
|
+
if (colors.isDark) {
|
|
696
|
+
root.style.setProperty(
|
|
697
|
+
'--shadow-1',
|
|
698
|
+
'0px 1px 2px 0px rgba(0,0,0,0.6), 0px 1px 3px 1px rgba(0,0,0,0.3)',
|
|
699
|
+
);
|
|
700
|
+
root.style.setProperty(
|
|
701
|
+
'--shadow-2',
|
|
702
|
+
'0px 1px 2px 0px rgba(0,0,0,0.6), 0px 2px 6px 2px rgba(0,0,0,0.3)',
|
|
703
|
+
);
|
|
704
|
+
root.style.setProperty(
|
|
705
|
+
'--shadow-3',
|
|
706
|
+
'0px 1px 3px 0px rgba(0,0,0,0.6), 0px 4px 8px 3px rgba(0,0,0,0.3)',
|
|
707
|
+
);
|
|
708
|
+
root.style.setProperty(
|
|
709
|
+
'--shadow-hover',
|
|
710
|
+
'0px 2px 4px 0px rgba(0,0,0,0.5), 0px 6px 16px 4px rgba(0,0,0,0.4)',
|
|
711
|
+
);
|
|
712
|
+
root.style.setProperty(
|
|
713
|
+
'--shadow-drag',
|
|
714
|
+
'0px 4px 8px 0px rgba(0,0,0,0.5), 0px 12px 32px 6px rgba(0,0,0,0.4)',
|
|
715
|
+
);
|
|
716
|
+
root.style.setProperty(
|
|
717
|
+
'--shadow-panel',
|
|
718
|
+
'-2px 0px 8px 0px rgba(0,0,0,0.5), -4px 0px 16px 2px rgba(0,0,0,0.3)',
|
|
719
|
+
);
|
|
720
|
+
} else {
|
|
721
|
+
root.style.setProperty(
|
|
722
|
+
'--shadow-1',
|
|
723
|
+
'0px 1px 2px 0px rgba(0,0,0,0.3), 0px 1px 3px 1px rgba(0,0,0,0.15)',
|
|
724
|
+
);
|
|
725
|
+
root.style.setProperty(
|
|
726
|
+
'--shadow-2',
|
|
727
|
+
'0px 1px 2px 0px rgba(0,0,0,0.3), 0px 2px 6px 2px rgba(0,0,0,0.15)',
|
|
728
|
+
);
|
|
729
|
+
root.style.setProperty(
|
|
730
|
+
'--shadow-3',
|
|
731
|
+
'0px 1px 3px 0px rgba(0,0,0,0.3), 0px 4px 8px 3px rgba(0,0,0,0.15)',
|
|
732
|
+
);
|
|
733
|
+
root.style.setProperty(
|
|
734
|
+
'--shadow-hover',
|
|
735
|
+
'0px 2px 4px 0px rgba(0,0,0,0.25), 0px 4px 12px 4px rgba(0,0,0,0.15)',
|
|
736
|
+
);
|
|
737
|
+
root.style.setProperty(
|
|
738
|
+
'--shadow-drag',
|
|
739
|
+
'0px 4px 8px 0px rgba(0,0,0,0.3), 0px 12px 32px 6px rgba(0,0,0,0.25)',
|
|
740
|
+
);
|
|
741
|
+
root.style.setProperty(
|
|
742
|
+
'--shadow-panel',
|
|
743
|
+
'-2px 0px 8px 0px rgba(0,0,0,0.3), -4px 0px 16px 2px rgba(0,0,0,0.15)',
|
|
744
|
+
);
|
|
745
|
+
}
|
|
733
746
|
}
|
|
734
|
-
}
|
|
735
747
|
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
748
|
+
if (colors.isDark !== undefined) {
|
|
749
|
+
var theme = colors.isDark ? 'dark' : 'light';
|
|
750
|
+
if (colors.isDark) {
|
|
751
|
+
document.documentElement.setAttribute('data-theme', 'dark');
|
|
752
|
+
} else {
|
|
753
|
+
document.documentElement.removeAttribute('data-theme');
|
|
754
|
+
}
|
|
755
|
+
localStorage.setItem('agent-tasks-theme', theme);
|
|
756
|
+
updateThemeIcon(theme);
|
|
742
757
|
}
|
|
743
|
-
localStorage.setItem('agent-tasks-theme', theme);
|
|
744
|
-
updateThemeIcon(theme);
|
|
745
|
-
}
|
|
746
758
|
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
});
|
|
759
|
+
var themeToggle = document.getElementById('theme-toggle');
|
|
760
|
+
if (themeToggle) themeToggle.style.display = 'none';
|
|
761
|
+
});
|
|
762
|
+
|
|
763
|
+
// ---- Initialize modules ----
|
|
764
|
+
|
|
765
|
+
TaskBoard.initDragEvents();
|
|
766
|
+
TaskBoard.initPanelEvents();
|
|
767
|
+
TaskBoard.initPanelResize();
|
|
768
|
+
|
|
769
|
+
// ---- Boot ----
|
|
750
770
|
|
|
751
|
-
|
|
771
|
+
connect();
|
|
772
|
+
}
|
|
752
773
|
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
TaskBoard.
|
|
774
|
+
// ---- Plugin mount/unmount ----
|
|
775
|
+
|
|
776
|
+
TaskBoard.mount = function (container, options) {
|
|
777
|
+
options = options || {};
|
|
778
|
+
TaskBoard._baseUrl = options.baseUrl || '';
|
|
779
|
+
TaskBoard._wsUrl = options.wsUrl || null;
|
|
780
|
+
if (options.cssUrl && !document.getElementById('tb-plugin-css')) {
|
|
781
|
+
var link = document.createElement('link');
|
|
782
|
+
link.id = 'tb-plugin-css';
|
|
783
|
+
link.rel = 'stylesheet';
|
|
784
|
+
link.href = options.cssUrl;
|
|
785
|
+
document.head.appendChild(link);
|
|
786
|
+
}
|
|
787
|
+
if (typeof TaskBoard._template === 'function') {
|
|
788
|
+
container.innerHTML = TaskBoard._template();
|
|
789
|
+
}
|
|
790
|
+
_init();
|
|
791
|
+
};
|
|
792
|
+
|
|
793
|
+
TaskBoard.unmount = function () {
|
|
794
|
+
if (ws) {
|
|
795
|
+
ws.onclose = null;
|
|
796
|
+
ws.close();
|
|
797
|
+
ws = null;
|
|
798
|
+
}
|
|
799
|
+
clearTimeout(reconnectTimer);
|
|
800
|
+
};
|
|
756
801
|
|
|
757
|
-
// ----
|
|
802
|
+
// ---- Auto-init for standalone mode ----
|
|
758
803
|
|
|
759
|
-
|
|
804
|
+
_init();
|
package/dist/ui/drag.js
CHANGED
|
@@ -59,7 +59,7 @@ function onDrop(e, col) {
|
|
|
59
59
|
const task = state.tasks.find((t) => t.id === draggedTaskId);
|
|
60
60
|
if (!task || task.stage === targetStage) return;
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
TaskBoard._fetch(`/api/tasks/${draggedTaskId}/stage`, {
|
|
63
63
|
method: 'PUT',
|
|
64
64
|
headers: { 'Content-Type': 'application/json' },
|
|
65
65
|
body: JSON.stringify({ stage: targetStage }),
|
package/dist/ui/index.html
CHANGED
package/dist/ui/inline-edit.js
CHANGED
|
@@ -64,7 +64,7 @@ function dismissInlineCreate() {
|
|
|
64
64
|
|
|
65
65
|
function createTaskInline(title, stage) {
|
|
66
66
|
var showToast = TaskBoard.showToast;
|
|
67
|
-
|
|
67
|
+
TaskBoard._fetch('/api/tasks', {
|
|
68
68
|
method: 'POST',
|
|
69
69
|
headers: { 'Content-Type': 'application/json' },
|
|
70
70
|
body: JSON.stringify({ title, stage, created_by: 'dashboard' }),
|
|
@@ -205,7 +205,7 @@ function dismissDropdownOnOutsideClick(e) {
|
|
|
205
205
|
|
|
206
206
|
function updateTask(taskId, updates) {
|
|
207
207
|
var showToast = TaskBoard.showToast;
|
|
208
|
-
|
|
208
|
+
TaskBoard._fetch(`/api/tasks/${taskId}`, {
|
|
209
209
|
method: 'PUT',
|
|
210
210
|
headers: { 'Content-Type': 'application/json' },
|
|
211
211
|
body: JSON.stringify(updates),
|
package/dist/ui/panel.js
CHANGED
|
@@ -294,13 +294,13 @@ function renderPanelContent(task) {
|
|
|
294
294
|
panelBody.innerHTML = html + skeletonHTML;
|
|
295
295
|
|
|
296
296
|
Promise.all([
|
|
297
|
-
|
|
297
|
+
TaskBoard._fetch(`/api/tasks/${task.id}/artifacts`)
|
|
298
298
|
.then((r) => r.json())
|
|
299
299
|
.catch(() => []),
|
|
300
|
-
|
|
300
|
+
TaskBoard._fetch(`/api/tasks/${task.id}/comments`)
|
|
301
301
|
.then((r) => r.json())
|
|
302
302
|
.catch(() => []),
|
|
303
|
-
|
|
303
|
+
TaskBoard._fetch(`/api/tasks/${task.id}/subtasks`)
|
|
304
304
|
.then((r) => r.json())
|
|
305
305
|
.catch(() => []),
|
|
306
306
|
]).then(([artifacts, comments, subtasks]) => {
|
|
@@ -379,7 +379,7 @@ function submitComment(taskId) {
|
|
|
379
379
|
const content = input?.value?.trim();
|
|
380
380
|
if (!content) return;
|
|
381
381
|
|
|
382
|
-
|
|
382
|
+
TaskBoard._fetch(`/api/tasks/${taskId}/comments`, {
|
|
383
383
|
method: 'POST',
|
|
384
384
|
headers: { 'Content-Type': 'application/json' },
|
|
385
385
|
body: JSON.stringify({ content, agent_id: 'dashboard' }),
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// agent-tasks — Template Module
|
|
3
|
+
//
|
|
4
|
+
// HTML template for plugin mount mode. Extracted from index.html body content.
|
|
5
|
+
// =============================================================================
|
|
6
|
+
|
|
7
|
+
window.TaskBoard = window.TaskBoard || {};
|
|
8
|
+
|
|
9
|
+
TaskBoard._template = function () {
|
|
10
|
+
return (
|
|
11
|
+
'<header role="banner">' +
|
|
12
|
+
'<div class="header-left">' +
|
|
13
|
+
'<span class="material-symbols-outlined brand-icon">view_kanban</span>' +
|
|
14
|
+
'<h1>agent-tasks</h1>' +
|
|
15
|
+
'<span class="version" id="version"></span>' +
|
|
16
|
+
'<span id="connection-status" class="status-badge disconnected" role="status" aria-live="polite">Connecting</span>' +
|
|
17
|
+
'</div>' +
|
|
18
|
+
'<div class="header-right">' +
|
|
19
|
+
'<div class="stats" id="stats" aria-live="polite" aria-atomic="true"></div>' +
|
|
20
|
+
'<button id="cleanup-btn" class="icon-btn" title="Clean up" aria-label="Clean up old tasks">' +
|
|
21
|
+
'<span class="material-symbols-outlined">mop</span>' +
|
|
22
|
+
'</button>' +
|
|
23
|
+
'<button id="theme-toggle" class="icon-btn" title="Toggle theme" aria-label="Toggle theme">' +
|
|
24
|
+
'<span class="material-symbols-outlined theme-icon">dark_mode</span>' +
|
|
25
|
+
'</button>' +
|
|
26
|
+
'</div>' +
|
|
27
|
+
'</header>' +
|
|
28
|
+
'<div class="filter-bar" id="filter-bar" role="search" aria-label="Task filters">' +
|
|
29
|
+
'<div class="filter-group">' +
|
|
30
|
+
'<span class="material-symbols-outlined filter-icon" aria-hidden="true">filter_list</span>' +
|
|
31
|
+
'<input type="text" id="filter-search" class="filter-input" placeholder="Search tasks... (/ or Ctrl+K)" autocomplete="off" aria-label="Search tasks" />' +
|
|
32
|
+
'<select id="filter-project" class="filter-select" aria-label="Filter by project">' +
|
|
33
|
+
'<option value="">All projects</option>' +
|
|
34
|
+
'</select>' +
|
|
35
|
+
'<select id="filter-assignee" class="filter-select" aria-label="Filter by assignee">' +
|
|
36
|
+
'<option value="">All assignees</option>' +
|
|
37
|
+
'</select>' +
|
|
38
|
+
'<select id="filter-priority" class="filter-select" aria-label="Filter by minimum priority">' +
|
|
39
|
+
'<option value="">Any priority</option>' +
|
|
40
|
+
'<option value="1">P1+</option>' +
|
|
41
|
+
'<option value="3">P3+</option>' +
|
|
42
|
+
'<option value="5">P5+</option>' +
|
|
43
|
+
'<option value="10">P10+</option>' +
|
|
44
|
+
'</select>' +
|
|
45
|
+
'</div>' +
|
|
46
|
+
'<div class="filter-chips" id="filter-chips"></div>' +
|
|
47
|
+
'</div>' +
|
|
48
|
+
'<div class="board-wrapper" id="board-wrapper">' +
|
|
49
|
+
'<main id="board" class="kanban-board" role="region" aria-label="Task board"></main>' +
|
|
50
|
+
'<aside id="side-panel" class="side-panel" role="complementary" aria-label="Task details">' +
|
|
51
|
+
'<div class="panel-header" id="panel-header-content"></div>' +
|
|
52
|
+
'<div class="panel-body" id="panel-body"></div>' +
|
|
53
|
+
'</aside>' +
|
|
54
|
+
'</div>' +
|
|
55
|
+
'<div id="loading-overlay" class="loading-overlay" aria-label="Loading">' +
|
|
56
|
+
'<div class="loading-spinner"></div>' +
|
|
57
|
+
'<div class="loading-text">Connecting to agent-tasks...</div>' +
|
|
58
|
+
'</div>' +
|
|
59
|
+
'<div id="task-modal" class="modal-overlay" hidden role="dialog" aria-modal="true" aria-labelledby="modal-title">' +
|
|
60
|
+
'<div class="modal">' +
|
|
61
|
+
'<div class="modal-header">' +
|
|
62
|
+
'<h2 id="modal-title"></h2>' +
|
|
63
|
+
'<button class="icon-btn modal-close" id="modal-close-btn" aria-label="Close dialog">×</button>' +
|
|
64
|
+
'</div>' +
|
|
65
|
+
'<div id="modal-body" class="modal-body"></div>' +
|
|
66
|
+
'</div>' +
|
|
67
|
+
'</div>' +
|
|
68
|
+
'<div id="cleanup-modal" class="modal-overlay hidden" role="dialog" aria-modal="true">' +
|
|
69
|
+
'<div class="modal" style="max-width: 420px">' +
|
|
70
|
+
'<div class="modal-header">' +
|
|
71
|
+
'<h2><span class="material-symbols-outlined" style="font-size: 20px; vertical-align: middle; margin-right: 6px">mop</span>Clean Up</h2>' +
|
|
72
|
+
'<button class="icon-btn modal-close" id="cleanup-close-btn" aria-label="Close">×</button>' +
|
|
73
|
+
'</div>' +
|
|
74
|
+
'<div class="modal-body">' +
|
|
75
|
+
'<p style="color: var(--text-muted); margin-bottom: 12px">Remove old tasks and stale data:</p>' +
|
|
76
|
+
'<div class="cleanup-options">' +
|
|
77
|
+
'<button id="cleanup-completed" class="cleanup-option">' +
|
|
78
|
+
'<span class="material-symbols-outlined">auto_delete</span>' +
|
|
79
|
+
'<div><strong>Purge completed</strong><span>Remove all completed and cancelled tasks</span></div>' +
|
|
80
|
+
'</button>' +
|
|
81
|
+
'<button id="cleanup-everything" class="cleanup-option cleanup-option-danger">' +
|
|
82
|
+
'<span class="material-symbols-outlined">delete_forever</span>' +
|
|
83
|
+
'<div><strong>Purge everything</strong><span>Remove ALL tasks regardless of status</span></div>' +
|
|
84
|
+
'</button>' +
|
|
85
|
+
'</div>' +
|
|
86
|
+
'</div>' +
|
|
87
|
+
'</div>' +
|
|
88
|
+
'</div>' +
|
|
89
|
+
'<div id="toast-container" class="toast-container" aria-live="polite"></div>'
|
|
90
|
+
);
|
|
91
|
+
};
|
package/package.json
CHANGED