94d32c524a
- types/note.ts: Note gains systems? + arose_from_id?; TaskKind includes 'issue'. - stores/tasks.ts: create/update accept IssueFields (kind/system_ids/arose_from_id). - api/systems.ts: getProjectIssues + TaskLike. - DashboardView.vue: 'Open issues' rail section from dashboard.open_issues (links to /tasks/<id>, project + status). - SystemsSection.vue (project Systems tab): 'Open issues' list via getProjectIssues, with system chips, links to /tasks/<id>. Both reuse existing CSS tokens. Issue-editor controls (kind selector / system multi-select / arose-from picker in WorkspaceTaskPanel) are the remaining S4b piece. NEEDS operator browser verification (CI typechecks only). Refs plan 825 (S4b frontend — lists). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
65 lines
1.7 KiB
TypeScript
65 lines
1.7 KiB
TypeScript
import { apiGet, apiPost, apiPatch, apiDelete } from "@/api/client";
|
|
|
|
export interface System {
|
|
id: number;
|
|
project_id: number;
|
|
name: string;
|
|
description: string;
|
|
color: string | null;
|
|
status: "active" | "archived";
|
|
order_index: number;
|
|
open_issue_count: number;
|
|
created_at: string | null;
|
|
updated_at: string | null;
|
|
}
|
|
|
|
export async function listSystems(projectId: number): Promise<System[]> {
|
|
const data = await apiGet<{ systems: System[] }>(`/api/projects/${projectId}/systems`);
|
|
return data.systems;
|
|
}
|
|
|
|
export async function createSystem(
|
|
projectId: number,
|
|
data: { name: string; description?: string; color?: string },
|
|
): Promise<System> {
|
|
return apiPost(`/api/projects/${projectId}/systems`, data);
|
|
}
|
|
|
|
export async function updateSystem(
|
|
projectId: number,
|
|
systemId: number,
|
|
data: Partial<{
|
|
name: string;
|
|
description: string;
|
|
color: string | null;
|
|
status: "active" | "archived";
|
|
order_index: number;
|
|
}>,
|
|
): Promise<System> {
|
|
return apiPatch(`/api/projects/${projectId}/systems/${systemId}`, data);
|
|
}
|
|
|
|
export async function deleteSystem(projectId: number, systemId: number): Promise<void> {
|
|
return apiDelete(`/api/projects/${projectId}/systems/${systemId}`);
|
|
}
|
|
|
|
// Lightweight issue shape returned by the project-issues list endpoint.
|
|
export interface TaskLike {
|
|
id: number;
|
|
title: string;
|
|
status: string;
|
|
priority: string;
|
|
systems?: System[];
|
|
updated_at?: string | null;
|
|
}
|
|
|
|
export async function getProjectIssues(
|
|
projectId: number,
|
|
openOnly = true,
|
|
): Promise<TaskLike[]> {
|
|
const data = await apiGet<{ issues: TaskLike[] }>(
|
|
`/api/projects/${projectId}/issues?open_only=${openOnly}`,
|
|
);
|
|
return data.issues;
|
|
}
|