feat: implement PL-7, PL-8, PL-9 — state-driven board, module/cycle views, link panels + graph edges

PL-7 — Task Board Columns from States:
- Add State, Module, Cycle, Link TypeScript types to types/index.ts
- Add stateId, moduleId, cycleId, trackedMinutes to Task type
- Rewrite tasks.tsx: fetch states from API, render 5 state-group columns
  (backlog/unstarted/started/completed/cancelled), drag-and-drop updates
  stateId via PATCH /tasks/:id, colored state badges, state filter dropdown,
  project filter
- Fix deprecated POST /tasks/:id/status → PATCH /tasks/:id with stateId
- Update tasks/.tsx: state selector dropdown replaces hardcoded status enum,
  toggle complete uses state-based approach, dependencies replaced with
  link-based UI using /api/links

PL-8 — Module + Cycle Views:
- Create apps/api/src/routes/cycles.ts: full CRUD + task assignment/removal
- Create apps/api/src/routes/links.ts: list/create/delete links between entities
- Register cycleRoutes and linkRoutes in API index
- Add Modules tab to project detail: list modules, expand to show tasks,
  add/remove tasks from modules, create/edit/delete module dialogs
- Add Cycles tab to project detail: sprint board grid, backlog lane,
  manual task transfer between cycles and backlog, create/edit cycle dialogs
- Fix ProjectTasks toggle to use PATCH with stateId instead of deprecated endpoint

PL-9 — Link Panels + Graph:
- Update graph API to read links bidirectionally (source OR target)
- Add link type color map (LINK_TYPE_COLORS) for edge rendering
- Graph edges now colored by linkType (blocks=red, relates=gray, etc.)
- Filter panel shows link types with color indicators
- Task detail Dependencies tab now uses /api/links for add/remove links
- Added link type selector (blocks/relates/parent-child/created-from)
This commit is contained in:
2026-09-07 20:24:54 +00:00
parent 14bb1aa1a8
commit c6328c120a
9 changed files with 1525 additions and 228 deletions
+5
View File
@@ -28,6 +28,8 @@ import { importExportRoutes } from "./routes/import-export";
import { notificationRoutes } from "./routes/notifications";
import { stateRoutes } from "./routes/states";
import { moduleRoutes } from "./routes/modules";
import { cycleRoutes } from "./routes/cycles";
import { linkRoutes } from "./routes/links";
import { healthHandler } from "./routes/health";
const app = new Hono();
@@ -47,6 +49,7 @@ app.get("/api/health", async (c) => {
app.route("/api/auth", authRoutes);
app.route("/api/domains", domainRoutes);
app.route("/api/projects/:projectId/modules", moduleRoutes);
app.route("/api/projects/:projectId/cycles", cycleRoutes);
app.route("/api/modules", moduleRoutes);
app.route("/api/tasks", taskRoutes);
app.route("/api/habits", habitRoutes);
@@ -67,6 +70,8 @@ app.route("/api/analytics", analyticsRoutes);
app.route("/api/activity", activityRoutes);
app.route("/api/notifications", notificationRoutes);
app.route("/api/states", stateRoutes);
app.route("/api/cycles", cycleRoutes);
app.route("/api/links", linkRoutes);
app.route("/api", importExportRoutes);
app.route("/api", realtimeRoutes);
app.route("/api/mcp", mcpRoutes);