feat: add task comments feature with CRUD operations
- Introduced a new `task_comments` table in the database schema. - Implemented task comments API endpoints for listing, creating, and deleting comments. - Enhanced the task detail dialog to display comments and allow users to add new comments. - Updated task row component to handle click events for viewing task details. - Added a theme provider to manage light/dark mode across the application. - Refactored Milkdown editor to use Crepe for improved markdown editing experience. - Updated global styles to accommodate new editor and theme changes. - Enhanced task filtering and sorting functionality in the tasks page.
This commit is contained in:
@@ -3,8 +3,9 @@ import { z } from 'zod';
|
||||
import { eq, asc, inArray, and, or, like, sql } from 'drizzle-orm';
|
||||
import { alias } from 'drizzle-orm/sqlite-core';
|
||||
import { getDb } from '../db';
|
||||
import { clients, projects, tasks, checkpoints, notes } from '../db/schema';
|
||||
import { clients, projects, tasks, checkpoints, notes, taskComments } from '../db/schema';
|
||||
import { getStore } from '../store';
|
||||
import { saveTokenAndInit, hasActiveToken } from '../ai/provider';
|
||||
|
||||
const t = initTRPC.create();
|
||||
|
||||
@@ -199,12 +200,13 @@ const tasksRouter = router({
|
||||
: undefined,
|
||||
);
|
||||
|
||||
const orderByClause =
|
||||
const priorityExpr = sql`CASE ${tasks.priority} WHEN 'high' THEN 1 WHEN 'medium' THEN 2 WHEN 'low' THEN 3 ELSE 4 END`;
|
||||
const orderByClauses =
|
||||
input?.orderBy === 'dueDate'
|
||||
? asc(tasks.dueDate)
|
||||
? [asc(tasks.dueDate), asc(priorityExpr)]
|
||||
: input?.orderBy === 'priority'
|
||||
? asc(sql`CASE ${tasks.priority} WHEN 'high' THEN 1 WHEN 'medium' THEN 2 WHEN 'low' THEN 3 ELSE 4 END`)
|
||||
: asc(tasks.createdAt);
|
||||
? [asc(priorityExpr), asc(tasks.dueDate)]
|
||||
: [asc(tasks.dueDate), asc(priorityExpr)];
|
||||
|
||||
return db
|
||||
.select({
|
||||
@@ -226,7 +228,7 @@ const tasksRouter = router({
|
||||
.leftJoin(clients, eq(projects.clientId, clients.id))
|
||||
.leftJoin(parentClients, eq(clients.parentId, parentClients.id))
|
||||
.where(conditions)
|
||||
.orderBy(orderByClause)
|
||||
.orderBy(...orderByClauses)
|
||||
.all();
|
||||
}),
|
||||
|
||||
@@ -436,6 +438,41 @@ const notesRouter = router({
|
||||
}),
|
||||
});
|
||||
|
||||
const taskCommentsRouter = router({
|
||||
list: publicProcedure
|
||||
.input(z.object({ taskId: z.string() }))
|
||||
.query(({ input }) => {
|
||||
return getDb()
|
||||
.select()
|
||||
.from(taskComments)
|
||||
.where(eq(taskComments.taskId, input.taskId))
|
||||
.orderBy(asc(taskComments.createdAt))
|
||||
.all();
|
||||
}),
|
||||
|
||||
create: publicProcedure
|
||||
.input(z.object({ taskId: z.string(), author: z.string(), content: z.string() }))
|
||||
.mutation(({ input }) => {
|
||||
const id = crypto.randomUUID();
|
||||
const now = Date.now();
|
||||
getDb().insert(taskComments).values({
|
||||
id,
|
||||
taskId: input.taskId,
|
||||
author: input.author,
|
||||
content: input.content,
|
||||
createdAt: now,
|
||||
}).run();
|
||||
return { id, taskId: input.taskId, author: input.author, content: input.content, createdAt: now };
|
||||
}),
|
||||
|
||||
delete: publicProcedure
|
||||
.input(z.object({ id: z.string() }))
|
||||
.mutation(({ input }) => {
|
||||
getDb().delete(taskComments).where(eq(taskComments.id, input.id)).run();
|
||||
return { success: true as const };
|
||||
}),
|
||||
});
|
||||
|
||||
const settingsRouter = router({
|
||||
getSidebarCollapsed: publicProcedure.query(() => getStore().get('sidebarCollapsed')),
|
||||
setSidebarCollapsed: publicProcedure
|
||||
@@ -458,8 +495,13 @@ const aiRouter = router({
|
||||
.mutation(() => ({ response: '' })),
|
||||
setToken: publicProcedure
|
||||
.input(z.object({ token: z.string() }))
|
||||
.mutation(() => null),
|
||||
hasToken: publicProcedure.query(() => false),
|
||||
.mutation(async ({ input }) => {
|
||||
await saveTokenAndInit(input.token);
|
||||
return { success: true };
|
||||
}),
|
||||
hasToken: publicProcedure.query(async () => {
|
||||
return hasActiveToken();
|
||||
}),
|
||||
});
|
||||
|
||||
export const appRouter = router({
|
||||
@@ -470,6 +512,7 @@ export const appRouter = router({
|
||||
tasks: tasksRouter,
|
||||
checkpoints: checkpointsRouter,
|
||||
notes: notesRouter,
|
||||
taskComments: taskCommentsRouter,
|
||||
ai: aiRouter,
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user