@critical-path/svelte 0.17.11 → 0.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -0
- package/dist/activity-state.svelte.d.ts +3 -0
- package/dist/activity-state.svelte.d.ts.map +1 -1
- package/dist/attachment-state.svelte.d.ts +3 -0
- package/dist/attachment-state.svelte.d.ts.map +1 -1
- package/dist/comment-state.svelte.d.ts +3 -0
- package/dist/comment-state.svelte.d.ts.map +1 -1
- package/dist/critical-path-state.svelte.d.ts +3 -0
- package/dist/critical-path-state.svelte.d.ts.map +1 -1
- package/dist/deliverable-state.svelte.d.ts +3 -0
- package/dist/deliverable-state.svelte.d.ts.map +1 -1
- package/dist/deliverable-summary-state.svelte.d.ts +3 -0
- package/dist/deliverable-summary-state.svelte.d.ts.map +1 -1
- package/dist/index.js +645 -551
- package/dist/latest-request.d.ts +15 -0
- package/dist/latest-request.d.ts.map +1 -0
- package/dist/project-state.svelte.d.ts +3 -0
- package/dist/project-state.svelte.d.ts.map +1 -1
- package/dist/task-metrics-state.svelte.d.ts +3 -0
- package/dist/task-metrics-state.svelte.d.ts.map +1 -1
- package/dist/task-state.svelte.d.ts +3 -0
- package/dist/task-state.svelte.d.ts.map +1 -1
- package/dist/task-transitions-state.svelte.d.ts +3 -0
- package/dist/task-transitions-state.svelte.d.ts.map +1 -1
- package/dist/timeline-ladder-state.svelte.d.ts +3 -0
- package/dist/timeline-ladder-state.svelte.d.ts.map +1 -1
- package/dist/workflow-state.svelte.d.ts +3 -0
- package/dist/workflow-state.svelte.d.ts.map +1 -1
- package/dist/workload-state.svelte.d.ts +3 -0
- package/dist/workload-state.svelte.d.ts.map +1 -1
- package/package.json +10 -6
- package/CHANGELOG.md +0 -714
- package/dist/index.test.d.ts +0 -2
- package/dist/index.test.d.ts.map +0 -1
- package/src/activity-state.svelte.ts +0 -193
- package/src/attachment-state.svelte.ts +0 -61
- package/src/comment-state.svelte.ts +0 -130
- package/src/critical-path-state.svelte.ts +0 -33
- package/src/deliverable-state.svelte.ts +0 -77
- package/src/deliverable-summary-state.svelte.ts +0 -41
- package/src/index.test.ts +0 -885
- package/src/index.ts +0 -23
- package/src/kanban-state.svelte.ts +0 -113
- package/src/project-state.svelte.ts +0 -54
- package/src/task-metrics-state.svelte.ts +0 -83
- package/src/task-state.svelte.ts +0 -195
- package/src/task-transitions-state.svelte.ts +0 -36
- package/src/timeline-ladder-state.svelte.ts +0 -58
- package/src/webmcp-state.svelte.ts +0 -78
- package/src/workflow-state.svelte.ts +0 -62
- package/src/workload-state.svelte.ts +0 -83
- package/tsconfig.json +0 -8
- package/vite.config.ts +0 -22
- package/vitest.config.ts +0 -6
package/src/index.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { CriticalPathClient, type ClientOptions } from '@critical-path/client';
|
|
2
|
-
|
|
3
|
-
export function createCriticalPathClient(options: ClientOptions): CriticalPathClient {
|
|
4
|
-
return new CriticalPathClient(options);
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export * from './project-state.svelte.js';
|
|
8
|
-
export * from './task-state.svelte.js';
|
|
9
|
-
export * from './workflow-state.svelte.js';
|
|
10
|
-
export * from './comment-state.svelte.js';
|
|
11
|
-
export * from './attachment-state.svelte.js';
|
|
12
|
-
export * from './activity-state.svelte.js';
|
|
13
|
-
export * from './deliverable-state.svelte.js';
|
|
14
|
-
export * from './deliverable-summary-state.svelte.js';
|
|
15
|
-
export * from './kanban-state.svelte.js';
|
|
16
|
-
export * from './task-transitions-state.svelte.js';
|
|
17
|
-
export * from './webmcp-state.svelte.js';
|
|
18
|
-
export * from './critical-path-state.svelte.js';
|
|
19
|
-
export * from './timeline-ladder-state.svelte.js';
|
|
20
|
-
export * from './task-metrics-state.svelte.js';
|
|
21
|
-
export * from './workload-state.svelte.js';
|
|
22
|
-
|
|
23
|
-
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
/// <reference types="svelte" />
|
|
2
|
-
import type { CreateTaskBody } from '@critical-path/core/schemas';
|
|
3
|
-
import type { CriticalPathClient } from '@critical-path/client';
|
|
4
|
-
import type { Task, TaskStatus, StatusDefinition, SemanticStatus } from '@critical-path/core';
|
|
5
|
-
import { resolveStatusDefinition } from '@critical-path/core';
|
|
6
|
-
import { TaskState } from './task-state.svelte.js';
|
|
7
|
-
|
|
8
|
-
export interface KanbanStateOptions {
|
|
9
|
-
groupBy?: 'workflow' | 'semantic';
|
|
10
|
-
customDefinitions?: StatusDefinition[];
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export class KanbanState {
|
|
14
|
-
private taskState: TaskState;
|
|
15
|
-
|
|
16
|
-
get data(): Task[] {
|
|
17
|
-
return this.taskState.data;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
get tasks(): Task[] {
|
|
21
|
-
return this.taskState.data;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
get loading(): boolean {
|
|
25
|
-
return this.taskState.loading;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
get error(): Error | null {
|
|
29
|
-
return this.taskState.error;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
columns = $derived.by<Record<string, Task[]>>(() => {
|
|
33
|
-
const tasks = this.taskState.data;
|
|
34
|
-
if (this.options?.groupBy === 'semantic') {
|
|
35
|
-
const semanticCols: Record<SemanticStatus, Task[]> = {
|
|
36
|
-
not_started: [],
|
|
37
|
-
in_progress: [],
|
|
38
|
-
completed: [],
|
|
39
|
-
canceled: []
|
|
40
|
-
};
|
|
41
|
-
for (const task of tasks) {
|
|
42
|
-
const category =
|
|
43
|
-
task.semanticStatus ||
|
|
44
|
-
resolveStatusDefinition(task.status, this.options?.customDefinitions).category;
|
|
45
|
-
if (semanticCols[category]) {
|
|
46
|
-
semanticCols[category].push(task);
|
|
47
|
-
} else {
|
|
48
|
-
semanticCols.not_started.push(task);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
return semanticCols;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const workflowCols: Record<string, Task[]> = {};
|
|
55
|
-
if (this.options?.customDefinitions && this.options.customDefinitions.length > 0) {
|
|
56
|
-
for (const def of this.options.customDefinitions) {
|
|
57
|
-
workflowCols[def.key] = [];
|
|
58
|
-
}
|
|
59
|
-
} else {
|
|
60
|
-
workflowCols.backlog = [];
|
|
61
|
-
workflowCols.todo = [];
|
|
62
|
-
workflowCols.in_progress = [];
|
|
63
|
-
workflowCols.in_review = [];
|
|
64
|
-
workflowCols.done = [];
|
|
65
|
-
workflowCols.canceled = [];
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
for (const task of tasks) {
|
|
69
|
-
if (!workflowCols[task.status]) {
|
|
70
|
-
workflowCols[task.status] = [];
|
|
71
|
-
}
|
|
72
|
-
workflowCols[task.status].push(task);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return workflowCols;
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
constructor(
|
|
79
|
-
client: CriticalPathClient,
|
|
80
|
-
public projectId?: string,
|
|
81
|
-
public options: KanbanStateOptions = {}
|
|
82
|
-
) {
|
|
83
|
-
this.taskState = new TaskState(client, projectId);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
async fetch() {
|
|
87
|
-
return this.taskState.fetch();
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
async createTask(input: CreateTaskBody) {
|
|
91
|
-
return this.taskState.createTask(input);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
async moveTask(taskId: string, targetStatus: TaskStatus) {
|
|
95
|
-
return this.taskState.updateTaskStatus(taskId, targetStatus);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
async updateTaskStatus(taskId: string, status: TaskStatus) {
|
|
99
|
-
return this.taskState.updateTaskStatus(taskId, status);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
async deleteTask(taskId: string) {
|
|
103
|
-
return this.taskState.deleteTask(taskId);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
export function createKanbanState(
|
|
108
|
-
client: CriticalPathClient,
|
|
109
|
-
projectId?: string,
|
|
110
|
-
options?: KanbanStateOptions
|
|
111
|
-
): KanbanState {
|
|
112
|
-
return new KanbanState(client, projectId, options);
|
|
113
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
/// <reference types="svelte" />
|
|
2
|
-
import type { CriticalPathClient } from '@critical-path/client';
|
|
3
|
-
import type { Project } from '@critical-path/core';
|
|
4
|
-
|
|
5
|
-
export class ProjectState {
|
|
6
|
-
data = $state<Project[]>([]);
|
|
7
|
-
loading = $state<boolean>(false);
|
|
8
|
-
error = $state<Error | null>(null);
|
|
9
|
-
|
|
10
|
-
constructor(private client: CriticalPathClient) {}
|
|
11
|
-
|
|
12
|
-
async fetch() {
|
|
13
|
-
this.loading = true;
|
|
14
|
-
this.error = null;
|
|
15
|
-
try {
|
|
16
|
-
this.data = await this.client.getProjects();
|
|
17
|
-
} catch (err) {
|
|
18
|
-
this.error = err instanceof Error ? err : new Error(String(err));
|
|
19
|
-
} finally {
|
|
20
|
-
this.loading = false;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
async createProject(input: Omit<Project, 'id' | 'createdAt' | 'updatedAt'>) {
|
|
25
|
-
const tempId = `temp_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;
|
|
26
|
-
const now = new Date().toISOString();
|
|
27
|
-
const tempProject: Project = {
|
|
28
|
-
...input,
|
|
29
|
-
id: tempId,
|
|
30
|
-
createdAt: now,
|
|
31
|
-
updatedAt: now
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
// Optimistically add temp project
|
|
35
|
-
this.data = [...this.data, tempProject];
|
|
36
|
-
|
|
37
|
-
try {
|
|
38
|
-
const created = await this.client.createProject(input);
|
|
39
|
-
// Replace temp project with server created project
|
|
40
|
-
this.data = this.data.map((p) => (p.id === tempId ? created : p));
|
|
41
|
-
return created;
|
|
42
|
-
} catch (err) {
|
|
43
|
-
// Rollback on error
|
|
44
|
-
this.data = this.data.filter((p) => p.id !== tempId);
|
|
45
|
-
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
46
|
-
this.error = errorObj;
|
|
47
|
-
throw errorObj;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export function createProjectState(client: CriticalPathClient): ProjectState {
|
|
53
|
-
return new ProjectState(client);
|
|
54
|
-
}
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
/// <reference types="svelte" />
|
|
2
|
-
import type { CriticalPathClient } from '@critical-path/client';
|
|
3
|
-
import type {
|
|
4
|
-
TaskMetrics,
|
|
5
|
-
TaskProgressHistory,
|
|
6
|
-
TaskInferredActuals,
|
|
7
|
-
RealityDelta,
|
|
8
|
-
TaskProgressInference,
|
|
9
|
-
TaskEVM,
|
|
10
|
-
ProgressCurveProfile
|
|
11
|
-
} from '@critical-path/core';
|
|
12
|
-
|
|
13
|
-
export class TaskMetricsState {
|
|
14
|
-
metrics = $state<TaskMetrics | null>(null);
|
|
15
|
-
history = $state<TaskProgressHistory | null>(null);
|
|
16
|
-
loading = $state<boolean>(false);
|
|
17
|
-
error = $state<Error | null>(null);
|
|
18
|
-
|
|
19
|
-
inferredActuals = $derived<TaskInferredActuals | null>(this.metrics?.inferredActuals ?? null);
|
|
20
|
-
realityDelta = $derived<RealityDelta | null>(this.metrics?.realityDelta ?? null);
|
|
21
|
-
progress = $derived<TaskProgressInference | null>(this.metrics?.progress ?? null);
|
|
22
|
-
evm = $derived<TaskEVM | null>(this.metrics?.evm ?? null);
|
|
23
|
-
curveProfile = $derived<ProgressCurveProfile | null>(this.history?.curveProfile ?? null);
|
|
24
|
-
|
|
25
|
-
constructor(
|
|
26
|
-
private client: CriticalPathClient,
|
|
27
|
-
public taskId: string
|
|
28
|
-
) {}
|
|
29
|
-
|
|
30
|
-
async fetchMetrics(): Promise<TaskMetrics | null> {
|
|
31
|
-
this.loading = true;
|
|
32
|
-
this.error = null;
|
|
33
|
-
try {
|
|
34
|
-
this.metrics = await this.client.getTaskMetrics(this.taskId);
|
|
35
|
-
return this.metrics;
|
|
36
|
-
} catch (err) {
|
|
37
|
-
this.error = err instanceof Error ? err : new Error(String(err));
|
|
38
|
-
return null;
|
|
39
|
-
} finally {
|
|
40
|
-
this.loading = false;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
async fetchHistory(): Promise<TaskProgressHistory | null> {
|
|
45
|
-
this.loading = true;
|
|
46
|
-
this.error = null;
|
|
47
|
-
try {
|
|
48
|
-
this.history = await this.client.getTaskProgressHistory(this.taskId);
|
|
49
|
-
return this.history;
|
|
50
|
-
} catch (err) {
|
|
51
|
-
this.error = err instanceof Error ? err : new Error(String(err));
|
|
52
|
-
return null;
|
|
53
|
-
} finally {
|
|
54
|
-
this.loading = false;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
async fetchAll(): Promise<{ metrics: TaskMetrics | null; history: TaskProgressHistory | null }> {
|
|
59
|
-
this.loading = true;
|
|
60
|
-
this.error = null;
|
|
61
|
-
try {
|
|
62
|
-
const [m, h] = await Promise.all([
|
|
63
|
-
this.client.getTaskMetrics(this.taskId),
|
|
64
|
-
this.client.getTaskProgressHistory(this.taskId)
|
|
65
|
-
]);
|
|
66
|
-
this.metrics = m;
|
|
67
|
-
this.history = h;
|
|
68
|
-
return { metrics: m, history: h };
|
|
69
|
-
} catch (err) {
|
|
70
|
-
this.error = err instanceof Error ? err : new Error(String(err));
|
|
71
|
-
return { metrics: null, history: null };
|
|
72
|
-
} finally {
|
|
73
|
-
this.loading = false;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export function createTaskMetricsState(
|
|
79
|
-
client: CriticalPathClient,
|
|
80
|
-
taskId: string
|
|
81
|
-
): TaskMetricsState {
|
|
82
|
-
return new TaskMetricsState(client, taskId);
|
|
83
|
-
}
|
package/src/task-state.svelte.ts
DELETED
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
/// <reference types="svelte" />
|
|
2
|
-
import type { CreateTaskBody, UpdateTaskBody } from '@critical-path/core/schemas';
|
|
3
|
-
import type { CriticalPathClient } from '@critical-path/client';
|
|
4
|
-
import { type Task, type TaskStatus, isTempTaskId } from '@critical-path/core';
|
|
5
|
-
|
|
6
|
-
export class TaskState {
|
|
7
|
-
data = $state<Task[]>([]);
|
|
8
|
-
loading = $state<boolean>(false);
|
|
9
|
-
error = $state<Error | null>(null);
|
|
10
|
-
|
|
11
|
-
private pendingCreations = new Map<string, Promise<Task>>();
|
|
12
|
-
private tempToRealIdMap = new Map<string, string>();
|
|
13
|
-
|
|
14
|
-
constructor(
|
|
15
|
-
private client: CriticalPathClient,
|
|
16
|
-
public projectId?: string
|
|
17
|
-
) {}
|
|
18
|
-
|
|
19
|
-
async fetch() {
|
|
20
|
-
this.loading = true;
|
|
21
|
-
this.error = null;
|
|
22
|
-
try {
|
|
23
|
-
this.data = await this.client.getTasks(this.projectId);
|
|
24
|
-
} catch (err) {
|
|
25
|
-
this.error = err instanceof Error ? err : new Error(String(err));
|
|
26
|
-
} finally {
|
|
27
|
-
this.loading = false;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
async createTask(input: CreateTaskBody) {
|
|
32
|
-
const tempId = `temp_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;
|
|
33
|
-
const now = new Date().toISOString();
|
|
34
|
-
const tempTask: Task = {
|
|
35
|
-
...input,
|
|
36
|
-
// Placeholders until the server responds with the workflow's real defaults
|
|
37
|
-
status: input.status ?? 'todo',
|
|
38
|
-
priority: input.priority ?? 'medium',
|
|
39
|
-
id: tempId,
|
|
40
|
-
createdAt: now,
|
|
41
|
-
updatedAt: now
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
// Optimistically add temp task
|
|
45
|
-
this.data = [...this.data, tempTask];
|
|
46
|
-
|
|
47
|
-
const promise = this.client.createTask(input);
|
|
48
|
-
this.pendingCreations.set(tempId, promise);
|
|
49
|
-
|
|
50
|
-
try {
|
|
51
|
-
const created = await promise;
|
|
52
|
-
this.tempToRealIdMap.set(tempId, created.id);
|
|
53
|
-
// Replace temp task with created task from server
|
|
54
|
-
this.data = this.data.map((t) => (t.id === tempId ? created : t));
|
|
55
|
-
return created;
|
|
56
|
-
} catch (err) {
|
|
57
|
-
// Rollback on error
|
|
58
|
-
this.data = this.data.filter((t) => t.id !== tempId);
|
|
59
|
-
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
60
|
-
this.error = errorObj;
|
|
61
|
-
throw errorObj;
|
|
62
|
-
} finally {
|
|
63
|
-
this.pendingCreations.delete(tempId);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
async updateTask(taskId: string, updates: UpdateTaskBody) {
|
|
68
|
-
let targetId = taskId;
|
|
69
|
-
if (this.tempToRealIdMap.has(taskId)) {
|
|
70
|
-
targetId = this.tempToRealIdMap.get(taskId)!;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// 1. Immediately apply optimistic updates to the local task (temp or confirmed)
|
|
74
|
-
const idx = this.data.findIndex((t) => t.id === targetId || t.id === taskId);
|
|
75
|
-
let previousTask: Task | undefined;
|
|
76
|
-
if (idx !== -1) {
|
|
77
|
-
previousTask = this.data[idx];
|
|
78
|
-
const optimisticTask: Task = {
|
|
79
|
-
...previousTask,
|
|
80
|
-
...updates,
|
|
81
|
-
updatedAt: new Date().toISOString()
|
|
82
|
-
};
|
|
83
|
-
const newData = [...this.data];
|
|
84
|
-
newData[idx] = optimisticTask;
|
|
85
|
-
this.data = newData;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// 2. If it's a temporary task, await pending creation if in flight
|
|
89
|
-
if (isTempTaskId(targetId)) {
|
|
90
|
-
const pendingPromise =
|
|
91
|
-
this.pendingCreations.get(targetId) ||
|
|
92
|
-
(this.pendingCreations.size === 1
|
|
93
|
-
? Array.from(this.pendingCreations.values())[0]
|
|
94
|
-
: undefined);
|
|
95
|
-
|
|
96
|
-
if (pendingPromise) {
|
|
97
|
-
try {
|
|
98
|
-
const created = await pendingPromise;
|
|
99
|
-
if (created && created.id) {
|
|
100
|
-
targetId = created.id;
|
|
101
|
-
this.tempToRealIdMap.set(taskId, targetId);
|
|
102
|
-
}
|
|
103
|
-
} catch {
|
|
104
|
-
throw new Error(`Failed to update task: task creation failed for "${taskId}"`);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// If still a temp ID, task exists purely in local client state; avoid sending unresolvable temp ID
|
|
110
|
-
if (isTempTaskId(targetId)) {
|
|
111
|
-
const currentTask = this.data.find((t) => t.id === targetId || t.id === taskId);
|
|
112
|
-
return (currentTask || { id: targetId, ...updates }) as Task;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
try {
|
|
116
|
-
const updated = await this.client.updateTask(targetId, updates);
|
|
117
|
-
const currentIdx = this.data.findIndex((t) => t.id === targetId || t.id === taskId);
|
|
118
|
-
if (currentIdx !== -1) {
|
|
119
|
-
const confirmedData = [...this.data];
|
|
120
|
-
confirmedData[currentIdx] = updated;
|
|
121
|
-
this.data = confirmedData;
|
|
122
|
-
}
|
|
123
|
-
return updated;
|
|
124
|
-
} catch (err) {
|
|
125
|
-
// Rollback to previous task on error
|
|
126
|
-
if (previousTask) {
|
|
127
|
-
const rollbackIdx = this.data.findIndex((t) => t.id === targetId || t.id === taskId);
|
|
128
|
-
if (rollbackIdx !== -1) {
|
|
129
|
-
const rollbackData = [...this.data];
|
|
130
|
-
rollbackData[rollbackIdx] = previousTask;
|
|
131
|
-
this.data = rollbackData;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
135
|
-
this.error = errorObj;
|
|
136
|
-
throw errorObj;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
async updateTaskStatus(taskId: string, status: TaskStatus) {
|
|
141
|
-
return this.updateTask(taskId, { status });
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
async deleteTask(taskId: string) {
|
|
145
|
-
let targetId = taskId;
|
|
146
|
-
if (this.tempToRealIdMap.has(taskId)) {
|
|
147
|
-
targetId = this.tempToRealIdMap.get(taskId)!;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
const idx = this.data.findIndex((t) => t.id === targetId || t.id === taskId);
|
|
151
|
-
const previousTask = idx !== -1 ? this.data[idx] : undefined;
|
|
152
|
-
|
|
153
|
-
// Optimistically remove task from local state
|
|
154
|
-
if (idx !== -1) {
|
|
155
|
-
this.data = this.data.filter((t) => t.id !== targetId && t.id !== taskId);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// If temporary task:
|
|
159
|
-
if (isTempTaskId(targetId)) {
|
|
160
|
-
const pendingPromise = this.pendingCreations.get(targetId);
|
|
161
|
-
if (pendingPromise) {
|
|
162
|
-
try {
|
|
163
|
-
const created = await pendingPromise;
|
|
164
|
-
if (created && created.id) {
|
|
165
|
-
await this.client.deleteTask(created.id);
|
|
166
|
-
}
|
|
167
|
-
} catch {
|
|
168
|
-
// If creation failed anyway, task is already gone
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
return;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
try {
|
|
175
|
-
await this.client.deleteTask(targetId);
|
|
176
|
-
} catch (err) {
|
|
177
|
-
// Rollback on error by re-inserting at previous index
|
|
178
|
-
if (previousTask && idx !== -1) {
|
|
179
|
-
const restoredData = [...this.data];
|
|
180
|
-
restoredData.splice(idx, 0, previousTask);
|
|
181
|
-
this.data = restoredData;
|
|
182
|
-
}
|
|
183
|
-
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
184
|
-
this.error = errorObj;
|
|
185
|
-
throw errorObj;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
export function createTaskState(
|
|
191
|
-
client: CriticalPathClient,
|
|
192
|
-
projectId?: string
|
|
193
|
-
): TaskState {
|
|
194
|
-
return new TaskState(client, projectId);
|
|
195
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
/// <reference types="svelte" />
|
|
2
|
-
import type { CriticalPathClient } from '@critical-path/client';
|
|
3
|
-
|
|
4
|
-
export class TaskTransitionsState {
|
|
5
|
-
allowedTransitions = $state<string[]>([]);
|
|
6
|
-
loading = $state<boolean>(false);
|
|
7
|
-
error = $state<Error | null>(null);
|
|
8
|
-
|
|
9
|
-
constructor(private client: CriticalPathClient, public taskId?: string) {}
|
|
10
|
-
|
|
11
|
-
async fetch(taskId?: string) {
|
|
12
|
-
const targetTaskId = taskId || this.taskId;
|
|
13
|
-
if (!targetTaskId) {
|
|
14
|
-
this.allowedTransitions = [];
|
|
15
|
-
this.loading = false;
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
this.taskId = targetTaskId;
|
|
19
|
-
this.loading = true;
|
|
20
|
-
this.error = null;
|
|
21
|
-
try {
|
|
22
|
-
this.allowedTransitions = await this.client.getAllowedTaskTransitions(targetTaskId);
|
|
23
|
-
} catch (err) {
|
|
24
|
-
this.error = err instanceof Error ? err : new Error(String(err));
|
|
25
|
-
} finally {
|
|
26
|
-
this.loading = false;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export function createTaskTransitionsState(
|
|
32
|
-
client: CriticalPathClient,
|
|
33
|
-
taskId?: string
|
|
34
|
-
): TaskTransitionsState {
|
|
35
|
-
return new TaskTransitionsState(client, taskId);
|
|
36
|
-
}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
/// <reference types="svelte" />
|
|
2
|
-
import type { CriticalPathClient } from '@critical-path/client';
|
|
3
|
-
import type {
|
|
4
|
-
TimelineLadder,
|
|
5
|
-
TimelineLadderOptions,
|
|
6
|
-
AbstractionLevel,
|
|
7
|
-
MacroTimelineSummary,
|
|
8
|
-
ConcreteTaskEvidence
|
|
9
|
-
} from '@critical-path/core';
|
|
10
|
-
|
|
11
|
-
export class TimelineLadderState {
|
|
12
|
-
data = $state<TimelineLadder | null>(null);
|
|
13
|
-
level = $state<AbstractionLevel>('all');
|
|
14
|
-
loading = $state<boolean>(false);
|
|
15
|
-
error = $state<Error | null>(null);
|
|
16
|
-
|
|
17
|
-
macro = $derived<MacroTimelineSummary | null>(this.data?.macro ?? null);
|
|
18
|
-
standard = $derived<TimelineLadder['standard'] | null>(this.data?.standard ?? null);
|
|
19
|
-
concrete = $derived<Record<string, ConcreteTaskEvidence> | null>(this.data?.concrete ?? null);
|
|
20
|
-
|
|
21
|
-
constructor(
|
|
22
|
-
private client: CriticalPathClient,
|
|
23
|
-
public projectId: string,
|
|
24
|
-
initialOptions?: TimelineLadderOptions
|
|
25
|
-
) {
|
|
26
|
-
if (initialOptions?.level) {
|
|
27
|
-
this.level = initialOptions.level;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
async setLevel(newLevel: AbstractionLevel) {
|
|
32
|
-
this.level = newLevel;
|
|
33
|
-
await this.fetch();
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async fetch(options?: TimelineLadderOptions) {
|
|
37
|
-
this.loading = true;
|
|
38
|
-
this.error = null;
|
|
39
|
-
try {
|
|
40
|
-
this.data = await this.client.getTimelineLadder(this.projectId, {
|
|
41
|
-
level: this.level,
|
|
42
|
-
...options
|
|
43
|
-
});
|
|
44
|
-
} catch (err) {
|
|
45
|
-
this.error = err instanceof Error ? err : new Error(String(err));
|
|
46
|
-
} finally {
|
|
47
|
-
this.loading = false;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export function createTimelineLadderState(
|
|
53
|
-
client: CriticalPathClient,
|
|
54
|
-
projectId: string,
|
|
55
|
-
initialOptions?: TimelineLadderOptions
|
|
56
|
-
): TimelineLadderState {
|
|
57
|
-
return new TimelineLadderState(client, projectId, initialOptions);
|
|
58
|
-
}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import type { CriticalPathClient } from '@critical-path/client';
|
|
2
|
-
import { registerWebMcpTools, type WebMcpRegistryHandle } from '@critical-path/mcp/web';
|
|
3
|
-
|
|
4
|
-
export interface WebMcpStateOptions {
|
|
5
|
-
projectId?: string;
|
|
6
|
-
tools?: string[];
|
|
7
|
-
autoRegister?: boolean;
|
|
8
|
-
document?: any;
|
|
9
|
-
navigator?: any;
|
|
10
|
-
window?: any;
|
|
11
|
-
onToolExecuted?: (toolName: string, input: any, result: any) => void;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export class WebMcpState {
|
|
15
|
-
registered = $state<boolean>(false);
|
|
16
|
-
activeProjectId = $state<string | undefined>(undefined);
|
|
17
|
-
tools = $state<string[]>([]);
|
|
18
|
-
error = $state<Error | null>(null);
|
|
19
|
-
|
|
20
|
-
private handle: WebMcpRegistryHandle | null = null;
|
|
21
|
-
private abortController: AbortController | null = null;
|
|
22
|
-
|
|
23
|
-
constructor(private client: CriticalPathClient, private options: WebMcpStateOptions = {}) {
|
|
24
|
-
this.activeProjectId = options.projectId;
|
|
25
|
-
if (options.autoRegister ?? true) {
|
|
26
|
-
this.register();
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
register(): void {
|
|
31
|
-
if (this.registered) return;
|
|
32
|
-
this.error = null;
|
|
33
|
-
|
|
34
|
-
try {
|
|
35
|
-
this.abortController = new AbortController();
|
|
36
|
-
this.handle = registerWebMcpTools({
|
|
37
|
-
client: this.client,
|
|
38
|
-
projectId: this.activeProjectId,
|
|
39
|
-
tools: this.options.tools,
|
|
40
|
-
signal: this.abortController.signal,
|
|
41
|
-
document: this.options.document,
|
|
42
|
-
navigator: this.options.navigator,
|
|
43
|
-
window: this.options.window,
|
|
44
|
-
onToolExecuted: (name, input, result) => {
|
|
45
|
-
this.options.onToolExecuted?.(name, input, result);
|
|
46
|
-
}
|
|
47
|
-
});
|
|
48
|
-
this.tools = this.handle.getRegisteredTools().map((t) => t.name);
|
|
49
|
-
this.registered = true;
|
|
50
|
-
} catch (err) {
|
|
51
|
-
this.error = err instanceof Error ? err : new Error(String(err));
|
|
52
|
-
this.registered = false;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
unregister(): void {
|
|
57
|
-
if (!this.registered) return;
|
|
58
|
-
this.abortController?.abort();
|
|
59
|
-
this.handle?.unregister();
|
|
60
|
-
this.handle = null;
|
|
61
|
-
this.abortController = null;
|
|
62
|
-
this.registered = false;
|
|
63
|
-
this.tools = [];
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
setProjectId(projectId?: string): void {
|
|
67
|
-
if (this.activeProjectId === projectId) return;
|
|
68
|
-
this.activeProjectId = projectId;
|
|
69
|
-
if (this.registered) {
|
|
70
|
-
this.unregister();
|
|
71
|
-
this.register();
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export function createWebMcpState(client: CriticalPathClient, options?: WebMcpStateOptions): WebMcpState {
|
|
77
|
-
return new WebMcpState(client, options);
|
|
78
|
-
}
|