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:
@@ -1,6 +1,6 @@
|
||||
import { Hono } from "hono";
|
||||
import { db, domains, notes, tasks, habits, projects, sections, tags as tagsTable, links } from "@project-e/db";
|
||||
import { and, eq, inArray, isNull } from "drizzle-orm";
|
||||
import { and, eq, inArray, isNull, or } from "drizzle-orm";
|
||||
import { requireAuth, requireWorkspaceAccess, AuthError } from "../middleware/auth";
|
||||
import { recordActivity } from "../middleware/activity";
|
||||
import { z } from "zod";
|
||||
@@ -57,11 +57,11 @@ async function getGraphData(domainId: string): Promise<{ nodes: GraphNode[]; edg
|
||||
for (const s of sectionRows) addNode(s.id, s.name, 'section');
|
||||
for (const t of tagRows) addNode(t.id, t.name, 'tag');
|
||||
|
||||
// Read links from the canonical links table
|
||||
const allIds = [...noteRows.map(n => n.id), ...taskRows.map(t => t.id)];
|
||||
// Read links from the canonical links table (both directions)
|
||||
const allIds = [...noteRows.map(n => n.id), ...taskRows.map(t => t.id), ...projectRows.map(p => p.id), ...sectionRows.map(s => s.id)];
|
||||
if (allIds.length > 0) {
|
||||
const linkRows = await db.select().from(links)
|
||||
.where(inArray(links.sourceId, allIds));
|
||||
.where(or(inArray(links.sourceId, allIds), inArray(links.targetId, allIds)));
|
||||
for (const l of linkRows) addEdge(l.sourceId, l.targetId, l.linkType);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user