agent-tasks 1.9.10 → 1.9.12

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/panel.js CHANGED
@@ -189,14 +189,19 @@ function renderPanelContent(task) {
189
189
  <span class="panel-task-id">#${task.id}</span>
190
190
  <span class="panel-stage-badge ${stageClass}">${esc(task.stage)}</span>
191
191
  </div>
192
- <button class="panel-close-btn" data-action="close-panel" aria-label="Close panel">
193
- <span class="material-symbols-outlined">close</span>
194
- </button>`;
192
+ <div class="panel-header-right">
193
+ <button class="panel-delete-btn" data-action="delete-task" data-task-id="${task.id}" aria-label="Delete task" title="Delete task">
194
+ <span class="material-symbols-outlined">delete</span>
195
+ </button>
196
+ <button class="panel-close-btn" data-action="close-panel" aria-label="Close panel">
197
+ <span class="material-symbols-outlined">close</span>
198
+ </button>
199
+ </div>`;
195
200
 
196
201
  const deps = state.dependencies.filter((d) => d.task_id === task.id);
197
202
  const blocking = state.dependencies.filter((d) => d.depends_on === task.id);
198
203
 
199
- let html = `<div class="panel-title">${esc(task.title)}</div>`;
204
+ let html = `<div class="panel-title" data-action="edit-panel-title" data-task-id="${task.id}" title="Click to edit">${esc(task.title)}</div>`;
200
205
 
201
206
  html += '<div class="panel-section">';
202
207
  html +=
@@ -235,13 +240,17 @@ function renderPanelContent(task) {
235
240
 
236
241
  html += '</div></div>';
237
242
 
243
+ html += '<div class="panel-section">';
244
+ html +=
245
+ '<div class="panel-section-title"><span class="material-symbols-outlined">notes</span> Description' +
246
+ `<button class="panel-edit-btn" data-action="edit-description" data-task-id="${task.id}" title="Edit description">` +
247
+ '<span class="material-symbols-outlined">edit</span></button></div>';
238
248
  if (task.description) {
239
- html += '<div class="panel-section">';
240
- html +=
241
- '<div class="panel-section-title"><span class="material-symbols-outlined">notes</span> Description</div>';
242
249
  html += `<div class="panel-description">${renderMarkdown(task.description)}</div>`;
243
- html += '</div>';
250
+ } else {
251
+ html += '<div class="panel-description panel-description-empty">No description</div>';
244
252
  }
253
+ html += '</div>';
245
254
 
246
255
  if (task.result) {
247
256
  html += '<div class="panel-section">';
@@ -516,6 +525,145 @@ function initPanelResize() {
516
525
 
517
526
  // ---- Panel event delegation ----
518
527
 
528
+ function startPanelTitleEdit(titleEl) {
529
+ var taskId = parseInt(titleEl.dataset.taskId, 10);
530
+ var task = TaskBoard.state.tasks.find(function (t) {
531
+ return t.id === taskId;
532
+ });
533
+ if (!task) return;
534
+
535
+ titleEl.setAttribute('contenteditable', 'true');
536
+ titleEl.focus();
537
+
538
+ var range = document.createRange();
539
+ range.selectNodeContents(titleEl);
540
+ var sel = window.getSelection();
541
+ sel.removeAllRanges();
542
+ sel.addRange(range);
543
+
544
+ var finish = function () {
545
+ titleEl.removeAttribute('contenteditable');
546
+ var newTitle = titleEl.textContent.trim();
547
+ if (newTitle && newTitle !== task.title) {
548
+ TaskBoard.updateTask(taskId, { title: newTitle });
549
+ } else {
550
+ titleEl.textContent = task.title;
551
+ }
552
+ };
553
+
554
+ titleEl.addEventListener('blur', finish, { once: true });
555
+ titleEl.addEventListener(
556
+ 'keydown',
557
+ function (ev) {
558
+ if (ev.key === 'Enter') {
559
+ ev.preventDefault();
560
+ ev.stopPropagation();
561
+ titleEl.blur();
562
+ } else if (ev.key === 'Escape') {
563
+ ev.preventDefault();
564
+ ev.stopPropagation();
565
+ titleEl.textContent = task.title;
566
+ titleEl.removeAttribute('contenteditable');
567
+ }
568
+ },
569
+ { once: true },
570
+ );
571
+ }
572
+
573
+ function startDescriptionEdit(taskId) {
574
+ var esc = TaskBoard.esc;
575
+ var task = TaskBoard.state.tasks.find(function (t) {
576
+ return t.id === taskId;
577
+ });
578
+ if (!task) return;
579
+
580
+ var descEl = TaskBoard._root.querySelector('.panel-description');
581
+ if (!descEl) return;
582
+
583
+ var editor = document.createElement('div');
584
+ editor.className = 'panel-description-editor';
585
+ editor.innerHTML =
586
+ '<textarea class="panel-desc-textarea" rows="6">' +
587
+ esc(task.description || '') +
588
+ '</textarea>' +
589
+ '<div class="panel-desc-actions">' +
590
+ '<button class="panel-desc-save" data-task-id="' +
591
+ taskId +
592
+ '">Save</button>' +
593
+ '<button class="panel-desc-cancel">Cancel</button>' +
594
+ '</div>';
595
+
596
+ descEl.replaceWith(editor);
597
+ editor.querySelector('.panel-desc-textarea').focus();
598
+
599
+ editor.querySelector('.panel-desc-save').addEventListener('click', function () {
600
+ var newDesc = editor.querySelector('.panel-desc-textarea').value.trim();
601
+ TaskBoard.updateTask(taskId, { description: newDesc || null });
602
+ setTimeout(function () {
603
+ openPanel(taskId);
604
+ }, 300);
605
+ });
606
+
607
+ editor.querySelector('.panel-desc-cancel').addEventListener('click', function () {
608
+ openPanel(taskId);
609
+ });
610
+ }
611
+
612
+ function deleteTask(taskId) {
613
+ var task = TaskBoard.state.tasks.find(function (t) {
614
+ return t.id === taskId;
615
+ });
616
+ if (!task) return;
617
+
618
+ var overlay = document.createElement('div');
619
+ overlay.className = 'confirm-overlay';
620
+ overlay.innerHTML =
621
+ '<div class="confirm-dialog">' +
622
+ '<div class="confirm-title">Delete task #' +
623
+ taskId +
624
+ '?</div>' +
625
+ '<div class="confirm-body">' +
626
+ TaskBoard.esc(task.title) +
627
+ '</div>' +
628
+ '<div class="confirm-actions">' +
629
+ '<button class="confirm-cancel">Cancel</button>' +
630
+ '<button class="confirm-delete">Delete</button>' +
631
+ '</div></div>';
632
+
633
+ var root =
634
+ TaskBoard._root === document
635
+ ? document.body
636
+ : TaskBoard._root.querySelector('[class*="wrapper"]') || TaskBoard._root;
637
+ root.appendChild(overlay);
638
+
639
+ overlay.querySelector('.confirm-cancel').addEventListener('click', function () {
640
+ overlay.remove();
641
+ });
642
+
643
+ overlay.querySelector('.confirm-delete').addEventListener('click', function () {
644
+ overlay.remove();
645
+ TaskBoard._fetch('/api/tasks/' + taskId, { method: 'DELETE' })
646
+ .then(function (r) {
647
+ return r.json();
648
+ })
649
+ .then(function (result) {
650
+ if (result.error) {
651
+ TaskBoard.showToast('Delete failed', result.error, 'error');
652
+ } else {
653
+ TaskBoard.showToast('Deleted', 'Task #' + taskId + ' deleted', 'success');
654
+ closePanel();
655
+ }
656
+ })
657
+ .catch(function () {
658
+ TaskBoard.showToast('Delete failed', 'Network error', 'error');
659
+ });
660
+ });
661
+
662
+ overlay.addEventListener('click', function (ev) {
663
+ if (ev.target === overlay) overlay.remove();
664
+ });
665
+ }
666
+
519
667
  function initPanelEvents() {
520
668
  TaskBoard._root.getElementById('side-panel').addEventListener('click', (e) => {
521
669
  const closeBtn = e.target.closest('[data-action="close-panel"]');
@@ -524,6 +672,24 @@ function initPanelEvents() {
524
672
  return;
525
673
  }
526
674
 
675
+ const editTitle = e.target.closest('[data-action="edit-panel-title"]');
676
+ if (editTitle && !editTitle.hasAttribute('contenteditable')) {
677
+ startPanelTitleEdit(editTitle);
678
+ return;
679
+ }
680
+
681
+ const editDesc = e.target.closest('[data-action="edit-description"]');
682
+ if (editDesc) {
683
+ startDescriptionEdit(parseInt(editDesc.dataset.taskId, 10));
684
+ return;
685
+ }
686
+
687
+ const delBtn = e.target.closest('[data-action="delete-task"]');
688
+ if (delBtn) {
689
+ deleteTask(parseInt(delBtn.dataset.taskId, 10));
690
+ return;
691
+ }
692
+
527
693
  const subtask = e.target.closest('[data-subtask-id]');
528
694
  if (subtask) {
529
695
  openPanel(parseInt(subtask.dataset.subtaskId, 10));
@@ -1661,14 +1661,196 @@ header {
1661
1661
  line-height: 1.35;
1662
1662
  margin-bottom: 16px;
1663
1663
  word-break: break-word;
1664
+ user-select: text;
1664
1665
  }
1665
1666
 
1667
+ .panel-title[data-action='edit-panel-title'] {
1668
+ cursor: text;
1669
+ border-radius: var(--radius-sm);
1670
+ padding: 2px 4px;
1671
+ margin: -2px -4px 16px;
1672
+ transition: background var(--transition-fast);
1673
+ }
1674
+ .panel-title[data-action='edit-panel-title']:hover {
1675
+ background: var(--bg-hover);
1676
+ }
1666
1677
  .panel-title[contenteditable='true'] {
1667
1678
  outline: none;
1679
+ background: var(--bg-surface);
1668
1680
  border-bottom: 2px solid var(--accent);
1669
1681
  cursor: text;
1670
1682
  }
1671
1683
 
1684
+ .panel-header-right {
1685
+ display: flex;
1686
+ align-items: center;
1687
+ gap: 4px;
1688
+ flex-shrink: 0;
1689
+ }
1690
+
1691
+ .panel-delete-btn {
1692
+ background: none;
1693
+ border: none;
1694
+ cursor: pointer;
1695
+ color: var(--text-dim);
1696
+ padding: 4px;
1697
+ border-radius: var(--radius-sm);
1698
+ display: flex;
1699
+ align-items: center;
1700
+ justify-content: center;
1701
+ transition: all var(--transition-fast);
1702
+ }
1703
+ .panel-delete-btn:hover {
1704
+ color: var(--red);
1705
+ background: var(--red-dim);
1706
+ }
1707
+ .panel-delete-btn .material-symbols-outlined {
1708
+ font-size: 18px;
1709
+ }
1710
+
1711
+ .panel-edit-btn {
1712
+ background: none;
1713
+ border: none;
1714
+ color: var(--text-dim);
1715
+ cursor: pointer;
1716
+ padding: 2px;
1717
+ border-radius: 4px;
1718
+ margin-left: auto;
1719
+ opacity: 0;
1720
+ transition:
1721
+ opacity var(--transition-fast),
1722
+ color var(--transition-fast);
1723
+ display: flex;
1724
+ align-items: center;
1725
+ }
1726
+ .panel-section-title:hover .panel-edit-btn {
1727
+ opacity: 1;
1728
+ }
1729
+ .panel-edit-btn:hover {
1730
+ color: var(--accent);
1731
+ background: var(--bg-hover);
1732
+ }
1733
+ .panel-edit-btn .material-symbols-outlined {
1734
+ font-size: 16px;
1735
+ }
1736
+
1737
+ .panel-description-empty {
1738
+ color: var(--text-dim);
1739
+ font-style: italic;
1740
+ font-size: 12px;
1741
+ }
1742
+
1743
+ .panel-description-editor {
1744
+ display: flex;
1745
+ flex-direction: column;
1746
+ gap: 8px;
1747
+ }
1748
+ .panel-desc-textarea {
1749
+ width: 100%;
1750
+ min-height: 120px;
1751
+ padding: 10px 12px;
1752
+ background: var(--bg-surface);
1753
+ border: 1px solid var(--border);
1754
+ border-radius: var(--radius-sm);
1755
+ color: var(--text);
1756
+ font-family: var(--font-mono);
1757
+ font-size: 12px;
1758
+ line-height: 1.6;
1759
+ resize: vertical;
1760
+ }
1761
+ .panel-desc-textarea:focus {
1762
+ outline: none;
1763
+ border-color: var(--accent);
1764
+ box-shadow: 0 0 0 2px var(--focus-ring);
1765
+ }
1766
+ .panel-desc-actions {
1767
+ display: flex;
1768
+ gap: 8px;
1769
+ justify-content: flex-end;
1770
+ }
1771
+ .panel-desc-save,
1772
+ .panel-desc-cancel {
1773
+ padding: 4px 12px;
1774
+ border-radius: 4px;
1775
+ font-size: 12px;
1776
+ cursor: pointer;
1777
+ border: 1px solid var(--border);
1778
+ background: var(--bg-surface);
1779
+ color: var(--text);
1780
+ transition: all var(--transition-fast);
1781
+ }
1782
+ .panel-desc-save {
1783
+ background: var(--accent);
1784
+ color: #fff;
1785
+ border-color: var(--accent);
1786
+ }
1787
+ .panel-desc-save:hover {
1788
+ background: var(--accent-hover);
1789
+ }
1790
+ .panel-desc-cancel:hover {
1791
+ background: var(--bg-hover);
1792
+ }
1793
+
1794
+ .confirm-overlay {
1795
+ position: fixed;
1796
+ inset: 0;
1797
+ background: rgba(0, 0, 0, 0.5);
1798
+ display: flex;
1799
+ align-items: center;
1800
+ justify-content: center;
1801
+ z-index: 9999;
1802
+ }
1803
+ .confirm-dialog {
1804
+ background: var(--bg-surface);
1805
+ border: 1px solid var(--border);
1806
+ border-radius: var(--radius);
1807
+ padding: 20px;
1808
+ min-width: 320px;
1809
+ max-width: 480px;
1810
+ box-shadow: var(--shadow-3);
1811
+ }
1812
+ .confirm-title {
1813
+ font-size: 14px;
1814
+ font-weight: 700;
1815
+ margin-bottom: 8px;
1816
+ }
1817
+ .confirm-body {
1818
+ font-size: 13px;
1819
+ color: var(--text-muted);
1820
+ margin-bottom: 16px;
1821
+ word-break: break-word;
1822
+ }
1823
+ .confirm-actions {
1824
+ display: flex;
1825
+ gap: 8px;
1826
+ justify-content: flex-end;
1827
+ }
1828
+ .confirm-cancel,
1829
+ .confirm-delete {
1830
+ padding: 6px 16px;
1831
+ border-radius: var(--radius-sm);
1832
+ font-size: 12px;
1833
+ font-weight: 600;
1834
+ cursor: pointer;
1835
+ border: 1px solid var(--border);
1836
+ transition: all var(--transition-fast);
1837
+ }
1838
+ .confirm-cancel {
1839
+ background: var(--bg-elevated);
1840
+ color: var(--text);
1841
+ }
1842
+ .confirm-cancel:hover {
1843
+ background: var(--bg-hover);
1844
+ }
1845
+ .confirm-delete {
1846
+ background: var(--red);
1847
+ color: #fff;
1848
+ border-color: var(--red);
1849
+ }
1850
+ .confirm-delete:hover {
1851
+ opacity: 0.9;
1852
+ }
1853
+
1672
1854
  .panel-section {
1673
1855
  margin-bottom: 20px;
1674
1856
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-tasks",
3
- "version": "1.9.10",
3
+ "version": "1.9.12",
4
4
  "description": "Pipeline-driven task management for AI coding agents — stages, dependencies, artifacts, and multi-agent claiming",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",