feat(todo): richer metadata (tags, startDate, files) + edit/detail dialog
ToDoアイテムのメタデータを拡充し、編集/詳細ダイアログを追加。
- lib/db/migrations/003_todo_tags.sql: todo_items に tags 列を追加
- TodoRepository/TodoService: startDate(従来ハードコードNULL)とtagsをcreate/updateで永続化、fileIdsで添付紐付け(トランザクション)、deleteItemで添付クリーンアップ、getItem/getItemAttachments を追加
- API: GET /todos/items/[itemId] ({item, attachments}) を追加、POST/PATCH で startDate/tags/fileIds を受理、PATCH は null(クリア)と undefined(更新しない)を区別
- UI: TodoDialog(タイトル/説明/担当/優先度/開始日/期限/タグ/添付を編集、完了日時・タイムスタンプは読み取り専用)、KanbanBoard のカードクリックでダイアログを開きメタデータを表示
- MilestoneRepository の todo マッピングに tags を追加し as never キャストを修正
- docs/functional-design.md に tags / file_assets.source / attachments テーブルを追記
This commit is contained in:
@ -24,6 +24,7 @@ interface TodoItemRow {
|
||||
completed_at: string | null;
|
||||
order_index: number;
|
||||
milestone_id: number | null;
|
||||
tags: string | null;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
deleted_at: string | null;
|
||||
@ -55,6 +56,7 @@ function mapItem(row: TodoItemRow): TodoItem {
|
||||
completedAt: row.completed_at,
|
||||
orderIndex: row.order_index,
|
||||
milestoneId: row.milestone_id,
|
||||
tags: row.tags,
|
||||
createdAt: row.created_at,
|
||||
updatedAt: row.updated_at,
|
||||
deletedAt: row.deleted_at,
|
||||
@ -75,7 +77,9 @@ export interface CreateItemInput {
|
||||
description?: string | null;
|
||||
assigneeId?: number | null;
|
||||
priority?: TodoPriority;
|
||||
startDate?: string | null;
|
||||
dueDate?: string | null;
|
||||
tags?: string | null;
|
||||
orderIndex: number;
|
||||
}
|
||||
|
||||
@ -84,7 +88,9 @@ export interface UpdateItemInput {
|
||||
description?: string | null;
|
||||
assigneeId?: number | null;
|
||||
priority?: TodoPriority;
|
||||
startDate?: string | null;
|
||||
dueDate?: string | null;
|
||||
tags?: string | null;
|
||||
completedAt?: string | null;
|
||||
columnId?: number;
|
||||
orderIndex?: number;
|
||||
@ -193,8 +199,8 @@ export class TodoRepository {
|
||||
createItem(input: CreateItemInput): TodoItem {
|
||||
const now = new Date().toISOString();
|
||||
const result = this.db.execute(
|
||||
`INSERT INTO todo_items (project_id, column_id, title, description, assignee_id, creator_id, priority, start_date, due_date, completed_at, order_index, milestone_id, created_at, updated_at, deleted_at)
|
||||
VALUES (@projectId, @columnId, @title, @description, @assigneeId, @creatorId, @priority, NULL, @dueDate, NULL, @orderIndex, @milestoneId, @createdAt, @updatedAt, NULL)`,
|
||||
`INSERT INTO todo_items (project_id, column_id, title, description, assignee_id, creator_id, priority, start_date, due_date, completed_at, order_index, milestone_id, tags, created_at, updated_at, deleted_at)
|
||||
VALUES (@projectId, @columnId, @title, @description, @assigneeId, @creatorId, @priority, @startDate, @dueDate, NULL, @orderIndex, @milestoneId, @tags, @createdAt, @updatedAt, NULL)`,
|
||||
{
|
||||
projectId: input.projectId,
|
||||
columnId: input.columnId,
|
||||
@ -203,9 +209,11 @@ export class TodoRepository {
|
||||
assigneeId: input.assigneeId ?? null,
|
||||
creatorId: input.creatorId,
|
||||
priority: input.priority ?? 'normal',
|
||||
startDate: input.startDate ?? null,
|
||||
dueDate: input.dueDate ?? null,
|
||||
orderIndex: input.orderIndex,
|
||||
milestoneId: null,
|
||||
tags: input.tags ?? null,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
}
|
||||
@ -237,10 +245,18 @@ export class TodoRepository {
|
||||
fields.push('priority = @priority');
|
||||
params.priority = input.priority;
|
||||
}
|
||||
if (input.startDate !== undefined) {
|
||||
fields.push('start_date = @startDate');
|
||||
params.startDate = input.startDate;
|
||||
}
|
||||
if (input.dueDate !== undefined) {
|
||||
fields.push('due_date = @dueDate');
|
||||
params.dueDate = input.dueDate;
|
||||
}
|
||||
if (input.tags !== undefined) {
|
||||
fields.push('tags = @tags');
|
||||
params.tags = input.tags;
|
||||
}
|
||||
if (input.completedAt !== undefined) {
|
||||
fields.push('completed_at = @completedAt');
|
||||
params.completedAt = input.completedAt;
|
||||
|
||||
Reference in New Issue
Block a user