Files
task-inventory/lib/storage.mjs
mikael-lovqvists-claude-agent b7ee5006d2 Add hierarchical tasks with tree and flat mode
- parent_id on tasks; roots shown by default, others expandable
- Expand/collapse per node with expand/collapse button
- Sub button creates subtask directly from the row
- Make subtask of button in edit dialog with searchable picker
- Remove parent clears the parent link in the dialog
- Flat mode toggle shows all tasks indented by depth
- Tree filter shows nodes whose descendants match, not only direct matches
- Deletion blocked if task has subtasks (client + server)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 18:55:14 +00:00

44 lines
985 B
JavaScript

import { mkdirSync } from 'node:fs';
import { Simple_KeyValue_Store } from './kv-store.mjs';
mkdirSync('./data', { recursive: true });
const store = new Simple_KeyValue_Store('./data/tasks.ndjson', {
auto_load: true,
auto_store: true,
debounce_flush_timeout: 5000,
});
// --- Tasks ---
export function list_tasks() {
const result = [];
for (const [key] of store.data.entries()) {
if (key.startsWith('task:')) {
result.push(store.get(key));
}
}
return result.sort((a, b) => b.created_at - a.created_at);
}
export function get_task(id) {
return store.get(`task:${id}`) ?? null;
}
export function set_task(task) {
store.set(`task:${task.id}`, task);
}
export function delete_task(id) {
return store.delete(`task:${id}`);
}
export function has_child_tasks(parent_id) {
for (const [key] of store.data.entries()) {
if (!key.startsWith('task:')) { continue; }
const task = store.get(key);
if (task.parent_id === parent_id) { return true; }
}
return false;
}