agkan 1.6.0 → 2.0.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/README.ja.md +6 -0
- package/README.md +25 -0
- package/dist/board/server.d.ts +7 -0
- package/dist/board/server.d.ts.map +1 -0
- package/dist/board/server.js +546 -0
- package/dist/board/server.js.map +1 -0
- package/dist/cli/commands/board.d.ts +3 -0
- package/dist/cli/commands/board.d.ts.map +1 -0
- package/dist/cli/commands/board.js +26 -0
- package/dist/cli/commands/board.js.map +1 -0
- package/dist/cli/index.js +4 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/models/Priority.d.ts +9 -0
- package/dist/models/Priority.d.ts.map +1 -0
- package/dist/models/Priority.js +19 -0
- package/dist/models/Priority.js.map +1 -0
- package/dist/models/index.d.ts +2 -0
- package/dist/models/index.d.ts.map +1 -1
- package/dist/models/index.js +5 -0
- package/dist/models/index.js.map +1 -1
- package/package.json +4 -1
package/README.ja.md
CHANGED
|
@@ -17,6 +17,12 @@ TypeScriptで実装された軽量なCLIタスク管理ツールです。エー
|
|
|
17
17
|
- **ブロック関係**: タスク間の依存関係を管理(循環参照検出機能付き)
|
|
18
18
|
- **タグ機能**: タスクにタグを付けて分類・検索が可能
|
|
19
19
|
|
|
20
|
+
## Agent Skills
|
|
21
|
+
|
|
22
|
+
agkanをClaude Codeのスキル(タスクの自動実行、プランニング、レビューなど)と連携して使用するには、以下のスキルパッケージをインストールしてください:
|
|
23
|
+
|
|
24
|
+
- **[agkan-skills](https://github.com/gendosu/agkan-skills)** - agkanタスク管理用のClaude Codeスキル
|
|
25
|
+
|
|
20
26
|
## インストール
|
|
21
27
|
|
|
22
28
|
### 前提条件
|
package/README.md
CHANGED
|
@@ -16,6 +16,13 @@ A lightweight CLI task management tool implemented in TypeScript. Optimized for
|
|
|
16
16
|
- **Parent-Child Relationships**: Manage task hierarchy (tree view supported)
|
|
17
17
|
- **Blocking Relationships**: Manage task dependencies (includes circular reference detection)
|
|
18
18
|
- **Tag System**: Classify and search tasks with tags
|
|
19
|
+
- **Kanban Board**: Local web-based Kanban board viewer
|
|
20
|
+
|
|
21
|
+
## Agent Skills
|
|
22
|
+
|
|
23
|
+
To use agkan with Claude Code skills (automated task execution, planning, review, etc.), install the companion skills package:
|
|
24
|
+
|
|
25
|
+
- **[agkan-skills](https://github.com/gendosu/agkan-skills)** - Claude Code skills for agkan task management
|
|
19
26
|
|
|
20
27
|
## Installation
|
|
21
28
|
|
|
@@ -513,6 +520,20 @@ agkan task count --status in_progress --json
|
|
|
513
520
|
}
|
|
514
521
|
```
|
|
515
522
|
|
|
523
|
+
### Kanban Board (Web UI)
|
|
524
|
+
|
|
525
|
+
Start a local Kanban board viewer in your browser:
|
|
526
|
+
```bash
|
|
527
|
+
agkan board
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
Specify a custom port:
|
|
531
|
+
```bash
|
|
532
|
+
agkan board -p 3000
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
The board is served at `http://localhost:8080` by default.
|
|
536
|
+
|
|
516
537
|
### Display Help
|
|
517
538
|
|
|
518
539
|
Show command list:
|
|
@@ -887,6 +908,7 @@ For detailed information about planned features, see [docs/planned-features.md](
|
|
|
887
908
|
- **CLI Framework**: Commander.js
|
|
888
909
|
- **Database**: SQLite3 (better-sqlite3)
|
|
889
910
|
- **Terminal Display**: Chalk
|
|
911
|
+
- **Web Server**: Hono (for Kanban board viewer)
|
|
890
912
|
- **Build Tool**: TypeScript Compiler
|
|
891
913
|
|
|
892
914
|
## Project Structure
|
|
@@ -914,6 +936,7 @@ agkan/
|
|
|
914
936
|
│ │ │ │ ├── detach.ts
|
|
915
937
|
│ │ │ │ ├── list.ts
|
|
916
938
|
│ │ │ │ └── show.ts
|
|
939
|
+
│ │ │ ├── board.ts # Kanban board command
|
|
917
940
|
│ │ │ └── task/ # Task commands
|
|
918
941
|
│ │ │ ├── add.ts
|
|
919
942
|
│ │ │ ├── count.ts
|
|
@@ -925,6 +948,8 @@ agkan/
|
|
|
925
948
|
│ │ │ └── update.ts
|
|
926
949
|
│ │ ├── utils/ # CLI utilities
|
|
927
950
|
│ │ └── index.ts # CLI entry point and command registration
|
|
951
|
+
│ ├── board/
|
|
952
|
+
│ │ └── server.ts # Kanban board web server (Hono)
|
|
928
953
|
│ ├── db/
|
|
929
954
|
│ │ ├── config.ts # DB configuration
|
|
930
955
|
│ │ ├── connection.ts # Database connection management
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Hono } from 'hono';
|
|
2
|
+
import { TaskService } from '../services/TaskService';
|
|
3
|
+
import { TaskTagService } from '../services/TaskTagService';
|
|
4
|
+
import { MetadataService } from '../services/MetadataService';
|
|
5
|
+
export declare function createBoardApp(taskService?: TaskService, taskTagService?: TaskTagService, metadataService?: MetadataService): Hono;
|
|
6
|
+
export declare function startBoardServer(port: number): void;
|
|
7
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/board/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAqd9D,wBAAgB,cAAc,CAC5B,WAAW,CAAC,EAAE,WAAW,EACzB,cAAc,CAAC,EAAE,cAAc,EAC/B,eAAe,CAAC,EAAE,eAAe,GAChC,IAAI,CA6FN;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAMnD"}
|
|
@@ -0,0 +1,546 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createBoardApp = createBoardApp;
|
|
4
|
+
exports.startBoardServer = startBoardServer;
|
|
5
|
+
const hono_1 = require("hono");
|
|
6
|
+
const node_server_1 = require("@hono/node-server");
|
|
7
|
+
const TaskService_1 = require("../services/TaskService");
|
|
8
|
+
const TaskTagService_1 = require("../services/TaskTagService");
|
|
9
|
+
const MetadataService_1 = require("../services/MetadataService");
|
|
10
|
+
const models_1 = require("../models");
|
|
11
|
+
const STATUSES = ['icebox', 'backlog', 'ready', 'in_progress', 'review', 'done', 'closed'];
|
|
12
|
+
const STATUS_LABELS = {
|
|
13
|
+
icebox: 'Icebox',
|
|
14
|
+
backlog: 'Backlog',
|
|
15
|
+
ready: 'Ready',
|
|
16
|
+
in_progress: 'In Progress',
|
|
17
|
+
review: 'Review',
|
|
18
|
+
done: 'Done',
|
|
19
|
+
closed: 'Closed',
|
|
20
|
+
};
|
|
21
|
+
const STATUS_COLORS = {
|
|
22
|
+
icebox: '#6b7280',
|
|
23
|
+
backlog: '#3b82f6',
|
|
24
|
+
ready: '#8b5cf6',
|
|
25
|
+
in_progress: '#f97316',
|
|
26
|
+
review: '#eab308',
|
|
27
|
+
done: '#22c55e',
|
|
28
|
+
closed: '#374151',
|
|
29
|
+
};
|
|
30
|
+
function escapeHtml(text) {
|
|
31
|
+
return text
|
|
32
|
+
.replace(/&/g, '&')
|
|
33
|
+
.replace(/</g, '<')
|
|
34
|
+
.replace(/>/g, '>')
|
|
35
|
+
.replace(/"/g, '"')
|
|
36
|
+
.replace(/'/g, ''');
|
|
37
|
+
}
|
|
38
|
+
function renderCard(task, tags, metadata) {
|
|
39
|
+
const priority = metadata.find((m) => m.key === 'priority')?.value;
|
|
40
|
+
const priorityBadge = priority
|
|
41
|
+
? `<span class="priority priority-${escapeHtml(priority)}">${escapeHtml(priority)}</span>`
|
|
42
|
+
: '';
|
|
43
|
+
const tagBadges = tags.map((t) => `<span class="tag">${escapeHtml(t.name)}</span>`).join('');
|
|
44
|
+
return `
|
|
45
|
+
<div class="card" draggable="true" data-id="${task.id}" data-status="${task.status}">
|
|
46
|
+
<div class="card-header">
|
|
47
|
+
<span class="card-id">#${task.id}</span>
|
|
48
|
+
${priorityBadge}
|
|
49
|
+
</div>
|
|
50
|
+
<div class="card-title">${escapeHtml(task.title)}</div>
|
|
51
|
+
${tagBadges ? `<div class="card-tags">${tagBadges}</div>` : ''}
|
|
52
|
+
</div>`;
|
|
53
|
+
}
|
|
54
|
+
function renderBoard(tasksByStatus, tagMap, metaMap) {
|
|
55
|
+
const columns = STATUSES.map((status) => {
|
|
56
|
+
const tasks = tasksByStatus.get(status) || [];
|
|
57
|
+
const color = STATUS_COLORS[status];
|
|
58
|
+
const label = STATUS_LABELS[status];
|
|
59
|
+
const cards = tasks.map((t) => renderCard(t, tagMap.get(t.id) || [], metaMap.get(t.id) || [])).join('');
|
|
60
|
+
return `
|
|
61
|
+
<div class="column" data-status="${status}">
|
|
62
|
+
<div class="column-header" style="border-top-color:${color}">
|
|
63
|
+
<span class="column-title" style="color:${color}">${label}</span>
|
|
64
|
+
<span class="column-header-right">
|
|
65
|
+
<span class="column-count">${tasks.length}</span>
|
|
66
|
+
<button class="add-btn" data-status="${status}" title="Add task">+</button>
|
|
67
|
+
</span>
|
|
68
|
+
</div>
|
|
69
|
+
<div class="column-body" id="col-${status}">
|
|
70
|
+
${cards}
|
|
71
|
+
</div>
|
|
72
|
+
</div>`;
|
|
73
|
+
}).join('');
|
|
74
|
+
return `<!DOCTYPE html>
|
|
75
|
+
<html lang="en">
|
|
76
|
+
<head>
|
|
77
|
+
<meta charset="UTF-8">
|
|
78
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
79
|
+
<title>agkan board</title>
|
|
80
|
+
<style>
|
|
81
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
82
|
+
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: #f1f5f9; color: #1e293b; }
|
|
83
|
+
header { background: #1e293b; color: white; padding: 12px 20px; }
|
|
84
|
+
header h1 { font-size: 18px; font-weight: 700; }
|
|
85
|
+
.board { display: flex; gap: 12px; padding: 16px; overflow-x: auto; min-height: calc(100vh - 48px); align-items: flex-start; }
|
|
86
|
+
.column { background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 8px; width: 240px; flex-shrink: 0; display: flex; flex-direction: column; border-top: 3px solid transparent; }
|
|
87
|
+
.column-header { padding: 10px 12px; display: flex; align-items: center; justify-content: space-between; border-bottom: 1px solid #e2e8f0; }
|
|
88
|
+
.column-title { font-size: 13px; font-weight: 700; }
|
|
89
|
+
.column-header-right { display: flex; align-items: center; gap: 6px; }
|
|
90
|
+
.column-count { background: #e2e8f0; color: #64748b; border-radius: 10px; font-size: 11px; font-weight: 600; padding: 2px 7px; }
|
|
91
|
+
.add-btn { background: none; border: 1px solid #cbd5e1; color: #64748b; border-radius: 4px; width: 22px; height: 22px; font-size: 14px; line-height: 1; cursor: pointer; display: flex; align-items: center; justify-content: center; }
|
|
92
|
+
.add-btn:hover { background: #e2e8f0; color: #1e293b; }
|
|
93
|
+
.column-body { padding: 8px; min-height: 60px; }
|
|
94
|
+
.column.drag-over .column-body { background: #eff6ff; border-radius: 6px; }
|
|
95
|
+
.card { background: white; border: 1px solid #e2e8f0; border-radius: 6px; padding: 10px; margin-bottom: 6px; cursor: grab; transition: box-shadow 0.15s; }
|
|
96
|
+
.card:hover { box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
|
|
97
|
+
.card.dragging { opacity: 0.5; }
|
|
98
|
+
.card-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 5px; }
|
|
99
|
+
.card-id { font-size: 11px; color: #94a3b8; font-weight: 600; }
|
|
100
|
+
.card-title { font-size: 13px; font-weight: 500; line-height: 1.4; }
|
|
101
|
+
.card-tags { margin-top: 6px; display: flex; flex-wrap: wrap; gap: 4px; }
|
|
102
|
+
.tag { background: #e0f2fe; color: #0369a1; font-size: 10px; font-weight: 600; padding: 2px 6px; border-radius: 10px; }
|
|
103
|
+
.priority { font-size: 10px; font-weight: 700; padding: 2px 6px; border-radius: 10px; text-transform: uppercase; }
|
|
104
|
+
.priority-critical { background: #fee2e2; color: #dc2626; }
|
|
105
|
+
.priority-high { background: #fee2e2; color: #dc2626; }
|
|
106
|
+
.priority-medium { background: #fef9c3; color: #ca8a04; }
|
|
107
|
+
.priority-low { background: #dcfce7; color: #16a34a; }
|
|
108
|
+
.context-menu { position: fixed; background: white; border: 1px solid #e2e8f0; border-radius: 6px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); padding: 4px 0; z-index: 1000; display: none; min-width: 140px; }
|
|
109
|
+
.context-menu-item { padding: 8px 14px; font-size: 13px; cursor: pointer; display: flex; align-items: center; gap: 8px; }
|
|
110
|
+
.context-menu-item:hover { background: #f1f5f9; }
|
|
111
|
+
.context-menu-item.danger { color: #dc2626; }
|
|
112
|
+
.context-menu-item.danger:hover { background: #fef2f2; }
|
|
113
|
+
.modal-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.4); z-index: 2000; display: none; align-items: center; justify-content: center; }
|
|
114
|
+
.modal-overlay.show { display: flex; }
|
|
115
|
+
.modal { background: white; border-radius: 8px; padding: 20px; width: 360px; box-shadow: 0 8px 24px rgba(0,0,0,0.2); }
|
|
116
|
+
.modal h2 { font-size: 16px; margin-bottom: 14px; }
|
|
117
|
+
.modal label { display: block; font-size: 12px; font-weight: 600; color: #64748b; margin-bottom: 4px; }
|
|
118
|
+
.modal input, .modal textarea, .modal select { width: 100%; border: 1px solid #e2e8f0; border-radius: 6px; padding: 8px 10px; font-size: 13px; font-family: inherit; margin-bottom: 12px; background: white; }
|
|
119
|
+
.modal textarea { resize: vertical; min-height: 60px; }
|
|
120
|
+
.modal input:focus, .modal textarea:focus, .modal select:focus { outline: none; border-color: #3b82f6; box-shadow: 0 0 0 2px rgba(59,130,246,0.2); }
|
|
121
|
+
.modal-actions { display: flex; justify-content: flex-end; gap: 8px; }
|
|
122
|
+
.modal-actions button { padding: 6px 14px; border-radius: 6px; font-size: 13px; font-weight: 600; cursor: pointer; border: 1px solid #e2e8f0; background: white; color: #64748b; }
|
|
123
|
+
.modal-actions button:hover { background: #f1f5f9; }
|
|
124
|
+
.modal-actions button.primary { background: #3b82f6; color: white; border-color: #3b82f6; }
|
|
125
|
+
.modal-actions button.primary:hover { background: #2563eb; }
|
|
126
|
+
.toast { position: fixed; bottom: 20px; right: 20px; background: #ef4444; color: white; padding: 10px 16px; border-radius: 6px; font-size: 13px; opacity: 0; transition: opacity 0.3s; pointer-events: none; }
|
|
127
|
+
.toast.show { opacity: 1; }
|
|
128
|
+
.detail-panel { position: fixed; top: 0; right: 0; width: 400px; height: 100vh; background: white; box-shadow: -4px 0 16px rgba(0,0,0,0.1); z-index: 1500; transform: translateX(100%); transition: transform 0.25s ease; display: flex; flex-direction: column; }
|
|
129
|
+
.detail-panel.open { transform: translateX(0); }
|
|
130
|
+
.detail-panel-header { display: flex; align-items: center; justify-content: space-between; padding: 16px 20px; border-bottom: 1px solid #e2e8f0; }
|
|
131
|
+
.detail-panel-header h2 { font-size: 16px; font-weight: 700; color: #1e293b; margin: 0; }
|
|
132
|
+
.detail-panel-close { background: none; border: none; font-size: 20px; color: #64748b; cursor: pointer; width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; border-radius: 4px; }
|
|
133
|
+
.detail-panel-close:hover { background: #f1f5f9; color: #1e293b; }
|
|
134
|
+
.detail-panel-body { flex: 1; overflow-y: auto; padding: 20px; }
|
|
135
|
+
.detail-field { margin-bottom: 16px; }
|
|
136
|
+
.detail-field-label { font-size: 11px; font-weight: 700; text-transform: uppercase; color: #94a3b8; margin-bottom: 4px; letter-spacing: 0.05em; }
|
|
137
|
+
.detail-field-value { font-size: 13px; color: #1e293b; line-height: 1.5; }
|
|
138
|
+
.detail-field-value.empty { color: #94a3b8; font-style: italic; }
|
|
139
|
+
.detail-status-badge { display: inline-block; padding: 3px 10px; border-radius: 12px; font-size: 12px; font-weight: 600; color: white; }
|
|
140
|
+
.detail-tags { display: flex; flex-wrap: wrap; gap: 4px; }
|
|
141
|
+
.detail-meta-table { width: 100%; border-collapse: collapse; }
|
|
142
|
+
.detail-meta-table td { padding: 4px 0; font-size: 12px; }
|
|
143
|
+
.detail-meta-table td:first-child { color: #64748b; width: 100px; }
|
|
144
|
+
.detail-meta-table td:last-child { color: #1e293b; }
|
|
145
|
+
</style>
|
|
146
|
+
</head>
|
|
147
|
+
<body>
|
|
148
|
+
<header><h1>agkan board</h1></header>
|
|
149
|
+
<div class="board">${columns}</div>
|
|
150
|
+
<div class="modal-overlay" id="add-modal">
|
|
151
|
+
<div class="modal">
|
|
152
|
+
<h2>Add Task</h2>
|
|
153
|
+
<label for="add-title">Title</label>
|
|
154
|
+
<input type="text" id="add-title" placeholder="Task title">
|
|
155
|
+
<label for="add-body">Description</label>
|
|
156
|
+
<textarea id="add-body" placeholder="Optional"></textarea>
|
|
157
|
+
<label for="add-priority">Priority</label>
|
|
158
|
+
<select id="add-priority">
|
|
159
|
+
<option value="">None</option>
|
|
160
|
+
${models_1.PRIORITIES.map((p) => `<option value="${p}">${p.charAt(0).toUpperCase() + p.slice(1)}</option>`).join('\n ')}
|
|
161
|
+
</select>
|
|
162
|
+
<input type="hidden" id="add-status">
|
|
163
|
+
<div class="modal-actions">
|
|
164
|
+
<button id="add-cancel">Cancel</button>
|
|
165
|
+
<button id="add-submit" class="primary">Add</button>
|
|
166
|
+
</div>
|
|
167
|
+
</div>
|
|
168
|
+
</div>
|
|
169
|
+
<div class="context-menu" id="context-menu">
|
|
170
|
+
<div class="context-menu-item danger" id="ctx-delete">Delete task</div>
|
|
171
|
+
</div>
|
|
172
|
+
<div class="detail-panel" id="detail-panel">
|
|
173
|
+
<div class="detail-panel-header">
|
|
174
|
+
<h2 id="detail-panel-title">Task Detail</h2>
|
|
175
|
+
<button class="detail-panel-close" id="detail-panel-close" title="Close">×</button>
|
|
176
|
+
</div>
|
|
177
|
+
<div class="detail-panel-body" id="detail-panel-body"></div>
|
|
178
|
+
</div>
|
|
179
|
+
<div class="toast" id="toast">Failed to update task</div>
|
|
180
|
+
<script>
|
|
181
|
+
let draggedCard = null;
|
|
182
|
+
let sourceBody = null;
|
|
183
|
+
|
|
184
|
+
document.querySelectorAll('.card').forEach(card => {
|
|
185
|
+
card.addEventListener('dragstart', e => {
|
|
186
|
+
draggedCard = card;
|
|
187
|
+
sourceBody = card.parentElement;
|
|
188
|
+
card.classList.add('dragging');
|
|
189
|
+
e.dataTransfer.effectAllowed = 'move';
|
|
190
|
+
});
|
|
191
|
+
card.addEventListener('dragend', () => {
|
|
192
|
+
card.classList.remove('dragging');
|
|
193
|
+
draggedCard = null;
|
|
194
|
+
sourceBody = null;
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
document.querySelectorAll('.column').forEach(col => {
|
|
199
|
+
col.addEventListener('dragover', e => {
|
|
200
|
+
e.preventDefault();
|
|
201
|
+
col.classList.add('drag-over');
|
|
202
|
+
});
|
|
203
|
+
col.addEventListener('dragleave', () => col.classList.remove('drag-over'));
|
|
204
|
+
col.addEventListener('drop', e => handleDrop(e, col.dataset.status, col));
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
async function handleDrop(e, newStatus, colEl) {
|
|
208
|
+
e.preventDefault();
|
|
209
|
+
colEl.classList.remove('drag-over');
|
|
210
|
+
if (!draggedCard) return;
|
|
211
|
+
const taskId = draggedCard.dataset.id;
|
|
212
|
+
const oldStatus = draggedCard.dataset.status;
|
|
213
|
+
if (oldStatus === newStatus) return;
|
|
214
|
+
|
|
215
|
+
const targetBody = document.getElementById('col-' + newStatus);
|
|
216
|
+
const prevBody = sourceBody;
|
|
217
|
+
targetBody.appendChild(draggedCard);
|
|
218
|
+
draggedCard.dataset.status = newStatus;
|
|
219
|
+
updateCount(oldStatus);
|
|
220
|
+
updateCount(newStatus);
|
|
221
|
+
|
|
222
|
+
try {
|
|
223
|
+
const res = await fetch('/api/tasks/' + taskId, {
|
|
224
|
+
method: 'PATCH',
|
|
225
|
+
headers: { 'Content-Type': 'application/json' },
|
|
226
|
+
body: JSON.stringify({ status: newStatus })
|
|
227
|
+
});
|
|
228
|
+
if (!res.ok) throw new Error('Server error');
|
|
229
|
+
} catch {
|
|
230
|
+
prevBody.appendChild(draggedCard);
|
|
231
|
+
draggedCard.dataset.status = oldStatus;
|
|
232
|
+
updateCount(oldStatus);
|
|
233
|
+
updateCount(newStatus);
|
|
234
|
+
showToast();
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function updateCount(status) {
|
|
239
|
+
const col = document.querySelector('.column[data-status="' + status + '"]');
|
|
240
|
+
if (!col) return;
|
|
241
|
+
col.querySelector('.column-count').textContent = col.querySelector('.column-body').children.length;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function showToast(msg) {
|
|
245
|
+
const toast = document.getElementById('toast');
|
|
246
|
+
if (msg) toast.textContent = msg;
|
|
247
|
+
toast.classList.add('show');
|
|
248
|
+
setTimeout(() => toast.classList.remove('show'), 3000);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Add task modal
|
|
252
|
+
const addModal = document.getElementById('add-modal');
|
|
253
|
+
const addTitle = document.getElementById('add-title');
|
|
254
|
+
const addBody = document.getElementById('add-body');
|
|
255
|
+
const addPriority = document.getElementById('add-priority');
|
|
256
|
+
const addStatus = document.getElementById('add-status');
|
|
257
|
+
|
|
258
|
+
document.querySelectorAll('.add-btn').forEach(btn => {
|
|
259
|
+
btn.addEventListener('click', e => {
|
|
260
|
+
e.stopPropagation();
|
|
261
|
+
addStatus.value = btn.dataset.status;
|
|
262
|
+
addTitle.value = '';
|
|
263
|
+
addBody.value = '';
|
|
264
|
+
addPriority.value = '';
|
|
265
|
+
addModal.classList.add('show');
|
|
266
|
+
addTitle.focus();
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
document.getElementById('add-cancel').addEventListener('click', () => {
|
|
271
|
+
addModal.classList.remove('show');
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
addModal.addEventListener('click', e => {
|
|
275
|
+
if (e.target === addModal) addModal.classList.remove('show');
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
addTitle.addEventListener('keydown', e => {
|
|
279
|
+
if (e.key === 'Enter') { e.preventDefault(); document.getElementById('add-submit').click(); }
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
document.getElementById('add-submit').addEventListener('click', async () => {
|
|
283
|
+
const title = addTitle.value.trim();
|
|
284
|
+
if (!title) { addTitle.focus(); return; }
|
|
285
|
+
const status = addStatus.value;
|
|
286
|
+
addModal.classList.remove('show');
|
|
287
|
+
|
|
288
|
+
try {
|
|
289
|
+
const res = await fetch('/api/tasks', {
|
|
290
|
+
method: 'POST',
|
|
291
|
+
headers: { 'Content-Type': 'application/json' },
|
|
292
|
+
body: JSON.stringify({ title, body: addBody.value.trim() || null, status, priority: addPriority.value || null })
|
|
293
|
+
});
|
|
294
|
+
if (!res.ok) throw new Error('Server error');
|
|
295
|
+
location.reload();
|
|
296
|
+
} catch {
|
|
297
|
+
showToast('Failed to add task');
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
// Context menu
|
|
302
|
+
const ctxMenu = document.getElementById('context-menu');
|
|
303
|
+
let ctxTargetCard = null;
|
|
304
|
+
|
|
305
|
+
document.addEventListener('contextmenu', e => {
|
|
306
|
+
const card = e.target.closest('.card');
|
|
307
|
+
if (!card) { ctxMenu.style.display = 'none'; return; }
|
|
308
|
+
e.preventDefault();
|
|
309
|
+
ctxTargetCard = card;
|
|
310
|
+
ctxMenu.style.left = e.clientX + 'px';
|
|
311
|
+
ctxMenu.style.top = e.clientY + 'px';
|
|
312
|
+
ctxMenu.style.display = 'block';
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
document.addEventListener('click', e => {
|
|
316
|
+
if (!e.target.closest('#context-menu')) {
|
|
317
|
+
ctxMenu.style.display = 'none';
|
|
318
|
+
ctxTargetCard = null;
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
document.getElementById('ctx-delete').addEventListener('click', async e => {
|
|
323
|
+
e.stopPropagation();
|
|
324
|
+
ctxMenu.style.display = 'none';
|
|
325
|
+
if (!ctxTargetCard) return;
|
|
326
|
+
const card = ctxTargetCard;
|
|
327
|
+
ctxTargetCard = null;
|
|
328
|
+
const taskId = card.dataset.id;
|
|
329
|
+
const status = card.dataset.status;
|
|
330
|
+
if (!confirm('Delete task #' + taskId + '?')) return;
|
|
331
|
+
|
|
332
|
+
card.remove();
|
|
333
|
+
updateCount(status);
|
|
334
|
+
|
|
335
|
+
try {
|
|
336
|
+
const res = await fetch('/api/tasks/' + taskId, { method: 'DELETE' });
|
|
337
|
+
if (!res.ok) throw new Error('Server error');
|
|
338
|
+
} catch {
|
|
339
|
+
location.reload();
|
|
340
|
+
showToast('Failed to delete task');
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
// Detail panel
|
|
345
|
+
const detailPanel = document.getElementById('detail-panel');
|
|
346
|
+
const detailPanelTitle = document.getElementById('detail-panel-title');
|
|
347
|
+
const detailPanelBody = document.getElementById('detail-panel-body');
|
|
348
|
+
|
|
349
|
+
function closeDetailPanel() {
|
|
350
|
+
detailPanel.classList.remove('open');
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
document.getElementById('detail-panel-close').addEventListener('click', closeDetailPanel);
|
|
354
|
+
|
|
355
|
+
const statusColors = ${JSON.stringify(STATUS_COLORS)};
|
|
356
|
+
|
|
357
|
+
function renderDetailPanel(data) {
|
|
358
|
+
const task = data.task;
|
|
359
|
+
const tags = data.tags || [];
|
|
360
|
+
const metadata = data.metadata || [];
|
|
361
|
+
const priority = metadata.find(m => m.key === 'priority');
|
|
362
|
+
|
|
363
|
+
detailPanelTitle.textContent = '#' + task.id + ' ' + task.title;
|
|
364
|
+
|
|
365
|
+
let html = '';
|
|
366
|
+
|
|
367
|
+
// Status
|
|
368
|
+
const sColor = statusColors[task.status] || '#64748b';
|
|
369
|
+
html += '<div class="detail-field">';
|
|
370
|
+
html += '<div class="detail-field-label">Status</div>';
|
|
371
|
+
html += '<div class="detail-field-value"><span class="detail-status-badge" style="background:' + sColor + '">' + escapeHtmlClient(task.status.replace('_', ' ')) + '</span></div>';
|
|
372
|
+
html += '</div>';
|
|
373
|
+
|
|
374
|
+
// Priority
|
|
375
|
+
if (priority) {
|
|
376
|
+
html += '<div class="detail-field">';
|
|
377
|
+
html += '<div class="detail-field-label">Priority</div>';
|
|
378
|
+
html += '<div class="detail-field-value"><span class="priority priority-' + escapeHtmlClient(priority.value) + '">' + escapeHtmlClient(priority.value) + '</span></div>';
|
|
379
|
+
html += '</div>';
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// Body
|
|
383
|
+
html += '<div class="detail-field">';
|
|
384
|
+
html += '<div class="detail-field-label">Description</div>';
|
|
385
|
+
if (task.body) {
|
|
386
|
+
html += '<div class="detail-field-value">' + escapeHtmlClient(task.body) + '</div>';
|
|
387
|
+
} else {
|
|
388
|
+
html += '<div class="detail-field-value empty">No description</div>';
|
|
389
|
+
}
|
|
390
|
+
html += '</div>';
|
|
391
|
+
|
|
392
|
+
// Tags
|
|
393
|
+
if (tags.length > 0) {
|
|
394
|
+
html += '<div class="detail-field">';
|
|
395
|
+
html += '<div class="detail-field-label">Tags</div>';
|
|
396
|
+
html += '<div class="detail-field-value detail-tags">';
|
|
397
|
+
tags.forEach(t => { html += '<span class="tag">' + escapeHtmlClient(t.name) + '</span>'; });
|
|
398
|
+
html += '</div></div>';
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// Metadata table
|
|
402
|
+
const otherMeta = metadata.filter(m => m.key !== 'priority');
|
|
403
|
+
if (otherMeta.length > 0) {
|
|
404
|
+
html += '<div class="detail-field">';
|
|
405
|
+
html += '<div class="detail-field-label">Metadata</div>';
|
|
406
|
+
html += '<table class="detail-meta-table">';
|
|
407
|
+
otherMeta.forEach(m => {
|
|
408
|
+
html += '<tr><td>' + escapeHtmlClient(m.key) + '</td><td>' + escapeHtmlClient(m.value) + '</td></tr>';
|
|
409
|
+
});
|
|
410
|
+
html += '</table></div>';
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// Timestamps
|
|
414
|
+
html += '<div class="detail-field">';
|
|
415
|
+
html += '<div class="detail-field-label">Created</div>';
|
|
416
|
+
html += '<div class="detail-field-value">' + escapeHtmlClient(task.created_at) + '</div>';
|
|
417
|
+
html += '</div>';
|
|
418
|
+
html += '<div class="detail-field">';
|
|
419
|
+
html += '<div class="detail-field-label">Updated</div>';
|
|
420
|
+
html += '<div class="detail-field-value">' + escapeHtmlClient(task.updated_at) + '</div>';
|
|
421
|
+
html += '</div>';
|
|
422
|
+
|
|
423
|
+
detailPanelBody.innerHTML = html;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
function escapeHtmlClient(str) {
|
|
427
|
+
if (!str) return '';
|
|
428
|
+
const div = document.createElement('div');
|
|
429
|
+
div.textContent = String(str);
|
|
430
|
+
return div.innerHTML;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
document.querySelectorAll('.card').forEach(card => {
|
|
434
|
+
card.addEventListener('click', async e => {
|
|
435
|
+
if (e.defaultPrevented) return;
|
|
436
|
+
const taskId = card.dataset.id;
|
|
437
|
+
try {
|
|
438
|
+
const res = await fetch('/api/tasks/' + taskId);
|
|
439
|
+
if (!res.ok) throw new Error('Server error');
|
|
440
|
+
const data = await res.json();
|
|
441
|
+
renderDetailPanel(data);
|
|
442
|
+
detailPanel.classList.add('open');
|
|
443
|
+
} catch {
|
|
444
|
+
showToast('Failed to load task details');
|
|
445
|
+
}
|
|
446
|
+
});
|
|
447
|
+
});
|
|
448
|
+
</script>
|
|
449
|
+
</body>
|
|
450
|
+
</html>`;
|
|
451
|
+
}
|
|
452
|
+
function sortByPriority(tasks, metaMap) {
|
|
453
|
+
return [...tasks].sort((a, b) => {
|
|
454
|
+
const pa = metaMap.get(a.id)?.find((m) => m.key === 'priority')?.value;
|
|
455
|
+
const pb = metaMap.get(b.id)?.find((m) => m.key === 'priority')?.value;
|
|
456
|
+
const oa = pa && (0, models_1.isPriority)(pa) ? models_1.PRIORITY_ORDER[pa] : 4;
|
|
457
|
+
const ob = pb && (0, models_1.isPriority)(pb) ? models_1.PRIORITY_ORDER[pb] : 4;
|
|
458
|
+
return oa - ob;
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
function createBoardApp(taskService, taskTagService, metadataService) {
|
|
462
|
+
const app = new hono_1.Hono();
|
|
463
|
+
const ts = taskService ?? new TaskService_1.TaskService();
|
|
464
|
+
const tts = taskTagService ?? new TaskTagService_1.TaskTagService();
|
|
465
|
+
const ms = metadataService ?? new MetadataService_1.MetadataService();
|
|
466
|
+
app.get('/', (c) => {
|
|
467
|
+
const tasks = ts.listTasks({}, 'id', 'asc');
|
|
468
|
+
const tagMap = tts.getAllTaskTags();
|
|
469
|
+
const metaMap = ms.getAllTasksMetadata();
|
|
470
|
+
const tasksByStatus = new Map();
|
|
471
|
+
for (const status of STATUSES) {
|
|
472
|
+
tasksByStatus.set(status, []);
|
|
473
|
+
}
|
|
474
|
+
for (const task of tasks) {
|
|
475
|
+
tasksByStatus.get(task.status)?.push(task);
|
|
476
|
+
}
|
|
477
|
+
for (const [status, statusTasks] of tasksByStatus) {
|
|
478
|
+
tasksByStatus.set(status, sortByPriority(statusTasks, metaMap));
|
|
479
|
+
}
|
|
480
|
+
return c.html(renderBoard(tasksByStatus, tagMap, metaMap));
|
|
481
|
+
});
|
|
482
|
+
app.get('/api/tasks', (c) => {
|
|
483
|
+
const tasks = ts.listTasks({}, 'id', 'asc');
|
|
484
|
+
return c.json({ tasks });
|
|
485
|
+
});
|
|
486
|
+
app.post('/api/tasks', async (c) => {
|
|
487
|
+
const body = await c.req.json();
|
|
488
|
+
if (!body.title || typeof body.title !== 'string' || !body.title.trim()) {
|
|
489
|
+
return c.json({ error: 'Title is required' }, 400);
|
|
490
|
+
}
|
|
491
|
+
const status = body.status && STATUSES.includes(body.status) ? body.status : 'backlog';
|
|
492
|
+
const task = ts.createTask({ title: body.title.trim(), body: body.body || undefined, status });
|
|
493
|
+
if (body.priority && (0, models_1.isPriority)(body.priority)) {
|
|
494
|
+
ms.setMetadata({ task_id: task.id, key: 'priority', value: body.priority });
|
|
495
|
+
}
|
|
496
|
+
return c.json(task, 201);
|
|
497
|
+
});
|
|
498
|
+
app.get('/api/tasks/:id', (c) => {
|
|
499
|
+
const id = Number(c.req.param('id'));
|
|
500
|
+
if (isNaN(id)) {
|
|
501
|
+
return c.json({ error: 'Invalid task id' }, 400);
|
|
502
|
+
}
|
|
503
|
+
const task = ts.getTask(id);
|
|
504
|
+
if (!task) {
|
|
505
|
+
return c.json({ error: 'Task not found' }, 404);
|
|
506
|
+
}
|
|
507
|
+
const tags = tts.getTagsForTask(id);
|
|
508
|
+
const metadata = ms.listMetadata(id);
|
|
509
|
+
return c.json({ task, tags, metadata });
|
|
510
|
+
});
|
|
511
|
+
app.patch('/api/tasks/:id', async (c) => {
|
|
512
|
+
const id = Number(c.req.param('id'));
|
|
513
|
+
if (isNaN(id)) {
|
|
514
|
+
return c.json({ error: 'Invalid task id' }, 400);
|
|
515
|
+
}
|
|
516
|
+
const body = await c.req.json();
|
|
517
|
+
if (!STATUSES.includes(body.status)) {
|
|
518
|
+
return c.json({ error: 'Invalid status' }, 400);
|
|
519
|
+
}
|
|
520
|
+
const task = ts.updateTask(id, { status: body.status });
|
|
521
|
+
if (!task) {
|
|
522
|
+
return c.json({ error: 'Task not found' }, 404);
|
|
523
|
+
}
|
|
524
|
+
return c.json(task);
|
|
525
|
+
});
|
|
526
|
+
app.delete('/api/tasks/:id', (c) => {
|
|
527
|
+
const id = Number(c.req.param('id'));
|
|
528
|
+
if (isNaN(id)) {
|
|
529
|
+
return c.json({ error: 'Invalid task id' }, 400);
|
|
530
|
+
}
|
|
531
|
+
const task = ts.getTask(id);
|
|
532
|
+
if (!task) {
|
|
533
|
+
return c.json({ error: 'Task not found' }, 404);
|
|
534
|
+
}
|
|
535
|
+
ts.deleteTask(id);
|
|
536
|
+
return c.json({ success: true });
|
|
537
|
+
});
|
|
538
|
+
return app;
|
|
539
|
+
}
|
|
540
|
+
function startBoardServer(port) {
|
|
541
|
+
const app = createBoardApp();
|
|
542
|
+
(0, node_server_1.serve)({ fetch: app.fetch, port }, () => {
|
|
543
|
+
console.log(`Board running at http://localhost:${port}`);
|
|
544
|
+
});
|
|
545
|
+
}
|
|
546
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/board/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"board.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/board.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAkBxD"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.setupBoardCommand = setupBoardCommand;
|
|
4
|
+
const server_1 = require("../../board/server");
|
|
5
|
+
const error_handler_1 = require("../utils/error-handler");
|
|
6
|
+
function setupBoardCommand(program) {
|
|
7
|
+
program
|
|
8
|
+
.command('board')
|
|
9
|
+
.description('Start a local Kanban board viewer at localhost')
|
|
10
|
+
.option('-p, --port <number>', 'Port to listen on', '8080')
|
|
11
|
+
.action((options) => {
|
|
12
|
+
try {
|
|
13
|
+
const port = parseInt(options.port, 10);
|
|
14
|
+
if (isNaN(port) || port < 1 || port > 65535) {
|
|
15
|
+
console.error('Invalid port number');
|
|
16
|
+
process.exit(1);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
(0, server_1.startBoardServer)(port);
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
(0, error_handler_1.handleError)(error, {});
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=board.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"board.js","sourceRoot":"","sources":["../../../src/cli/commands/board.ts"],"names":[],"mappings":";;AAIA,8CAkBC;AArBD,+CAAsD;AACtD,0DAAqD;AAErD,SAAgB,iBAAiB,CAAC,OAAgB;IAChD,OAAO;SACJ,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,gDAAgD,CAAC;SAC7D,MAAM,CAAC,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,CAAC;SAC1D,MAAM,CAAC,CAAC,OAAyB,EAAE,EAAE;QACpC,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YACxC,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,KAAK,EAAE,CAAC;gBAC5C,OAAO,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;gBACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAChB,OAAO;YACT,CAAC;YACD,IAAA,yBAAgB,EAAC,IAAI,CAAC,CAAC;QACzB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAA,2BAAW,EAAC,KAAc,EAAE,EAAE,CAAC,CAAC;QAClC,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
package/dist/cli/index.js
CHANGED
|
@@ -30,6 +30,8 @@ const set_1 = require("./commands/meta/set");
|
|
|
30
30
|
const get_2 = require("./commands/meta/get");
|
|
31
31
|
const list_4 = require("./commands/meta/list");
|
|
32
32
|
const delete_3 = require("./commands/meta/delete");
|
|
33
|
+
// Board command handler
|
|
34
|
+
const board_1 = require("./commands/board");
|
|
33
35
|
// Agent guide command handler
|
|
34
36
|
const agent_guide_1 = require("./commands/agent-guide");
|
|
35
37
|
const program = new commander_1.Command();
|
|
@@ -67,6 +69,8 @@ program.command('tag').description('Tag management commands');
|
|
|
67
69
|
(0, get_2.setupMetaGetCommand)(program);
|
|
68
70
|
(0, list_4.setupMetaListCommand)(program);
|
|
69
71
|
(0, delete_3.setupMetaDeleteCommand)(program);
|
|
72
|
+
// Register board command
|
|
73
|
+
(0, board_1.setupBoardCommand)(program);
|
|
70
74
|
// Register agent-guide command
|
|
71
75
|
(0, agent_guide_1.setupAgentGuideCommand)(program);
|
|
72
76
|
// Execute program
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";;;AAEA,yCAAoC;AACpC,2BAAkC;AAClC,+BAA4B;AAE5B,wBAAwB;AACxB,6CAA0D;AAC1D,+CAA4D;AAC5D,6CAA0D;AAC1D,mDAAgE;AAChE,+CAA4D;AAC5D,iDAA8D;AAC9D,iEAA6E;AAC7E,mDAAgE;AAEhE,yBAAyB;AACzB,8CAA4D;AAC5D,oDAAkE;AAClE,gDAA8D;AAE9D,uBAAuB;AACvB,4CAAwD;AACxD,8CAA0D;AAC1D,kDAA8D;AAC9D,kDAA8D;AAC9D,kDAA8D;AAC9D,8CAA0D;AAC1D,kDAA8D;AAE9D,wBAAwB;AACxB,6CAA0D;AAC1D,6CAA0D;AAC1D,+CAA4D;AAC5D,mDAAgE;AAEhE,8BAA8B;AAC9B,wDAAgE;AAEhE,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,iCAAiC;AACjC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,IAAA,iBAAY,EAAC,IAAA,WAAI,EAAC,SAAS,EAAE,oBAAoB,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AAE5F,4BAA4B;AAC5B,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,2CAA2C,CAAC,CAAC;AAE5G,4BAA4B;AAC5B,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,0BAA0B,CAAC,CAAC;AAEhE,yBAAyB;AACzB,IAAA,yBAAmB,EAAC,OAAO,CAAC,CAAC;AAC7B,IAAA,2BAAoB,EAAC,OAAO,CAAC,CAAC;AAC9B,IAAA,yBAAmB,EAAC,OAAO,CAAC,CAAC;AAC7B,IAAA,+BAAsB,EAAC,OAAO,CAAC,CAAC;AAChC,IAAA,2BAAoB,EAAC,OAAO,CAAC,CAAC;AAC9B,IAAA,6BAAqB,EAAC,OAAO,CAAC,CAAC;AAC/B,IAAA,4CAA4B,EAAC,OAAO,CAAC,CAAC;AACtC,IAAA,+BAAsB,EAAC,OAAO,CAAC,CAAC;AAEhC,gFAAgF;AAChF,IAAA,0BAAoB,EAAC,OAAO,CAAC,CAAC;AAC9B,IAAA,gCAAuB,EAAC,OAAO,CAAC,CAAC;AACjC,IAAA,4BAAqB,EAAC,OAAO,CAAC,CAAC;AAE/B,2BAA2B;AAC3B,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,yBAAyB,CAAC,CAAC;AAE9D,wBAAwB;AACxB,IAAA,wBAAkB,EAAC,OAAO,CAAC,CAAC;AAC5B,IAAA,0BAAmB,EAAC,OAAO,CAAC,CAAC;AAC7B,IAAA,8BAAqB,EAAC,OAAO,CAAC,CAAC;AAC/B,IAAA,8BAAqB,EAAC,OAAO,CAAC,CAAC;AAC/B,IAAA,8BAAqB,EAAC,OAAO,CAAC,CAAC;AAC/B,IAAA,0BAAmB,EAAC,OAAO,CAAC,CAAC;AAC7B,IAAA,8BAAqB,EAAC,OAAO,CAAC,CAAC;AAE/B,yBAAyB;AACzB,IAAA,yBAAmB,EAAC,OAAO,CAAC,CAAC;AAC7B,IAAA,yBAAmB,EAAC,OAAO,CAAC,CAAC;AAC7B,IAAA,2BAAoB,EAAC,OAAO,CAAC,CAAC;AAC9B,IAAA,+BAAsB,EAAC,OAAO,CAAC,CAAC;AAEhC,+BAA+B;AAC/B,IAAA,oCAAsB,EAAC,OAAO,CAAC,CAAC;AAEhC,kBAAkB;AAClB,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";;;AAEA,yCAAoC;AACpC,2BAAkC;AAClC,+BAA4B;AAE5B,wBAAwB;AACxB,6CAA0D;AAC1D,+CAA4D;AAC5D,6CAA0D;AAC1D,mDAAgE;AAChE,+CAA4D;AAC5D,iDAA8D;AAC9D,iEAA6E;AAC7E,mDAAgE;AAEhE,yBAAyB;AACzB,8CAA4D;AAC5D,oDAAkE;AAClE,gDAA8D;AAE9D,uBAAuB;AACvB,4CAAwD;AACxD,8CAA0D;AAC1D,kDAA8D;AAC9D,kDAA8D;AAC9D,kDAA8D;AAC9D,8CAA0D;AAC1D,kDAA8D;AAE9D,wBAAwB;AACxB,6CAA0D;AAC1D,6CAA0D;AAC1D,+CAA4D;AAC5D,mDAAgE;AAEhE,wBAAwB;AACxB,4CAAqD;AAErD,8BAA8B;AAC9B,wDAAgE;AAEhE,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,iCAAiC;AACjC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,IAAA,iBAAY,EAAC,IAAA,WAAI,EAAC,SAAS,EAAE,oBAAoB,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AAE5F,4BAA4B;AAC5B,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,2CAA2C,CAAC,CAAC;AAE5G,4BAA4B;AAC5B,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,0BAA0B,CAAC,CAAC;AAEhE,yBAAyB;AACzB,IAAA,yBAAmB,EAAC,OAAO,CAAC,CAAC;AAC7B,IAAA,2BAAoB,EAAC,OAAO,CAAC,CAAC;AAC9B,IAAA,yBAAmB,EAAC,OAAO,CAAC,CAAC;AAC7B,IAAA,+BAAsB,EAAC,OAAO,CAAC,CAAC;AAChC,IAAA,2BAAoB,EAAC,OAAO,CAAC,CAAC;AAC9B,IAAA,6BAAqB,EAAC,OAAO,CAAC,CAAC;AAC/B,IAAA,4CAA4B,EAAC,OAAO,CAAC,CAAC;AACtC,IAAA,+BAAsB,EAAC,OAAO,CAAC,CAAC;AAEhC,gFAAgF;AAChF,IAAA,0BAAoB,EAAC,OAAO,CAAC,CAAC;AAC9B,IAAA,gCAAuB,EAAC,OAAO,CAAC,CAAC;AACjC,IAAA,4BAAqB,EAAC,OAAO,CAAC,CAAC;AAE/B,2BAA2B;AAC3B,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,yBAAyB,CAAC,CAAC;AAE9D,wBAAwB;AACxB,IAAA,wBAAkB,EAAC,OAAO,CAAC,CAAC;AAC5B,IAAA,0BAAmB,EAAC,OAAO,CAAC,CAAC;AAC7B,IAAA,8BAAqB,EAAC,OAAO,CAAC,CAAC;AAC/B,IAAA,8BAAqB,EAAC,OAAO,CAAC,CAAC;AAC/B,IAAA,8BAAqB,EAAC,OAAO,CAAC,CAAC;AAC/B,IAAA,0BAAmB,EAAC,OAAO,CAAC,CAAC;AAC7B,IAAA,8BAAqB,EAAC,OAAO,CAAC,CAAC;AAE/B,yBAAyB;AACzB,IAAA,yBAAmB,EAAC,OAAO,CAAC,CAAC;AAC7B,IAAA,yBAAmB,EAAC,OAAO,CAAC,CAAC;AAC7B,IAAA,2BAAoB,EAAC,OAAO,CAAC,CAAC;AAC9B,IAAA,+BAAsB,EAAC,OAAO,CAAC,CAAC;AAEhC,yBAAyB;AACzB,IAAA,yBAAiB,EAAC,OAAO,CAAC,CAAC;AAE3B,+BAA+B;AAC/B,IAAA,oCAAsB,EAAC,OAAO,CAAC,CAAC;AAEhC,kBAAkB;AAClB,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Priority model
|
|
3
|
+
* Type definitions and constants for task priority
|
|
4
|
+
*/
|
|
5
|
+
export type Priority = 'critical' | 'high' | 'medium' | 'low';
|
|
6
|
+
export declare const PRIORITIES: Priority[];
|
|
7
|
+
export declare const PRIORITY_ORDER: Record<Priority, number>;
|
|
8
|
+
export declare function isPriority(value: string): value is Priority;
|
|
9
|
+
//# sourceMappingURL=Priority.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Priority.d.ts","sourceRoot":"","sources":["../../src/models/Priority.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AAE9D,eAAO,MAAM,UAAU,EAAE,QAAQ,EAA0C,CAAC;AAE5E,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAKnD,CAAC;AAEF,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,QAAQ,CAE3D"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Priority model
|
|
4
|
+
* Type definitions and constants for task priority
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.PRIORITY_ORDER = exports.PRIORITIES = void 0;
|
|
8
|
+
exports.isPriority = isPriority;
|
|
9
|
+
exports.PRIORITIES = ['critical', 'high', 'medium', 'low'];
|
|
10
|
+
exports.PRIORITY_ORDER = {
|
|
11
|
+
critical: 0,
|
|
12
|
+
high: 1,
|
|
13
|
+
medium: 2,
|
|
14
|
+
low: 3,
|
|
15
|
+
};
|
|
16
|
+
function isPriority(value) {
|
|
17
|
+
return exports.PRIORITIES.includes(value);
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=Priority.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Priority.js","sourceRoot":"","sources":["../../src/models/Priority.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAaH,gCAEC;AAXY,QAAA,UAAU,GAAe,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;AAE/D,QAAA,cAAc,GAA6B;IACtD,QAAQ,EAAE,CAAC;IACX,IAAI,EAAE,CAAC;IACP,MAAM,EAAE,CAAC;IACT,GAAG,EAAE,CAAC;CACP,CAAC;AAEF,SAAgB,UAAU,CAAC,KAAa;IACtC,OAAO,kBAAU,CAAC,QAAQ,CAAC,KAAiB,CAAC,CAAC;AAChD,CAAC"}
|
package/dist/models/index.d.ts
CHANGED
|
@@ -7,4 +7,6 @@ export type { TaskBlock, CreateTaskBlockInput } from './TaskBlock';
|
|
|
7
7
|
export type { Tag, CreateTagInput, UpdateTagInput } from './Tag';
|
|
8
8
|
export type { TaskTag, CreateTaskTagInput } from './TaskTag';
|
|
9
9
|
export type { TaskMetadata, CreateTaskMetadataInput, UpdateTaskMetadataInput } from './TaskMetadata';
|
|
10
|
+
export type { Priority } from './Priority';
|
|
11
|
+
export { PRIORITIES, PRIORITY_ORDER, isPriority } from './Priority';
|
|
10
12
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/models/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAGjF,YAAY,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAGnE,YAAY,EAAE,GAAG,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAGjE,YAAY,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAG7D,YAAY,EAAE,YAAY,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/models/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAGjF,YAAY,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAGnE,YAAY,EAAE,GAAG,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAGjE,YAAY,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAG7D,YAAY,EAAE,YAAY,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAGrG,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/models/index.js
CHANGED
|
@@ -4,4 +4,9 @@
|
|
|
4
4
|
* Centralized management of all model type definitions
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.isPriority = exports.PRIORITY_ORDER = exports.PRIORITIES = void 0;
|
|
8
|
+
var Priority_1 = require("./Priority");
|
|
9
|
+
Object.defineProperty(exports, "PRIORITIES", { enumerable: true, get: function () { return Priority_1.PRIORITIES; } });
|
|
10
|
+
Object.defineProperty(exports, "PRIORITY_ORDER", { enumerable: true, get: function () { return Priority_1.PRIORITY_ORDER; } });
|
|
11
|
+
Object.defineProperty(exports, "isPriority", { enumerable: true, get: function () { return Priority_1.isPriority; } });
|
|
7
12
|
//# sourceMappingURL=index.js.map
|
package/dist/models/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/models/index.ts"],"names":[],"mappings":";AAAA;;;GAGG"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/models/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAmBH,uCAAoE;AAA3D,sGAAA,UAAU,OAAA;AAAE,0GAAA,cAAc,OAAA;AAAE,sGAAA,UAAU,OAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agkan",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "TypeScript-based CLI task management tool with SQLite storage",
|
|
5
5
|
"main": "dist/cli/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"scripts": {
|
|
14
14
|
"build": "tsc",
|
|
15
15
|
"dev": "tsc --watch",
|
|
16
|
+
"board": "tsc && node dist/cli/index.js board",
|
|
16
17
|
"start": "node dist/cli/index.js",
|
|
17
18
|
"test": "vitest",
|
|
18
19
|
"test:all": "npm install && npm run build && npm run type-check && npm run lint && vitest run && npm run test:e2e",
|
|
@@ -48,9 +49,11 @@
|
|
|
48
49
|
"node": ">=18.0.0"
|
|
49
50
|
},
|
|
50
51
|
"dependencies": {
|
|
52
|
+
"@hono/node-server": "^1.19.11",
|
|
51
53
|
"better-sqlite3": "^11.7.0",
|
|
52
54
|
"chalk": "^4.1.2",
|
|
53
55
|
"commander": "^14.0.3",
|
|
56
|
+
"hono": "^4.12.5",
|
|
54
57
|
"js-yaml": "^4.1.1"
|
|
55
58
|
},
|
|
56
59
|
"devDependencies": {
|