@critical-path/svelte 0.5.4 → 0.7.0
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/CHANGELOG.md +24 -0
- package/README.md +7 -0
- package/dist/activity-state.svelte.d.ts +8 -0
- package/dist/activity-state.svelte.d.ts.map +1 -1
- package/dist/comment-state.svelte.d.ts +8 -0
- package/dist/comment-state.svelte.d.ts.map +1 -1
- package/dist/index.js +74 -0
- package/dist/task-state.svelte.d.ts +1 -0
- package/dist/task-state.svelte.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/activity-state.svelte.ts +40 -0
- package/src/comment-state.svelte.ts +40 -0
- package/src/index.test.ts +18 -2
- package/src/task-state.svelte.ts +41 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# @critical-path/svelte
|
|
2
2
|
|
|
3
|
+
## 0.7.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- e9003d3: Add emoji reactions support for comment conversations with domain events, deduplication, REST endpoints, client SDK, and React/Svelte state integrations.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [e9003d3]
|
|
12
|
+
- @critical-path/core@0.10.0
|
|
13
|
+
- @critical-path/client@0.5.0
|
|
14
|
+
|
|
15
|
+
## 0.6.0
|
|
16
|
+
|
|
17
|
+
### Minor Changes
|
|
18
|
+
|
|
19
|
+
- e983557: Add first-class optional todo list (checklist) support to Task model and TaskEntity with helper methods (addTodo, toggleTodo, removeTodo) and updateTask helper in @critical-path/svelte.
|
|
20
|
+
|
|
21
|
+
### Patch Changes
|
|
22
|
+
|
|
23
|
+
- Updated dependencies [e983557]
|
|
24
|
+
- @critical-path/core@0.9.0
|
|
25
|
+
- @critical-path/client@0.4.4
|
|
26
|
+
|
|
3
27
|
## 0.5.4
|
|
4
28
|
|
|
5
29
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -89,6 +89,13 @@ Combines threaded comments with inline attachments (`attachment.commentId === co
|
|
|
89
89
|
</div>
|
|
90
90
|
{/if}
|
|
91
91
|
|
|
92
|
+
<!-- Emoji Reactions -->
|
|
93
|
+
<div class="reactions">
|
|
94
|
+
<button on:click={() => activityState.addReaction(thread.id, '👍', 'user_1')}>👍</button>
|
|
95
|
+
<button on:click={() => activityState.addReaction(thread.id, '🚀', 'user_1')}>🚀</button>
|
|
96
|
+
<span>{thread.reactions?.length || 0} reactions</span>
|
|
97
|
+
</div>
|
|
98
|
+
|
|
92
99
|
<!-- Threaded replies -->
|
|
93
100
|
{#each thread.replies as reply}
|
|
94
101
|
<div class="reply">
|
|
@@ -22,6 +22,14 @@ export declare class TaskActivityState {
|
|
|
22
22
|
addAttachment(input: Omit<Attachment, 'id' | 'taskId' | 'createdAt' | 'updatedAt'>): Promise<Attachment>;
|
|
23
23
|
deleteComment(id: string): Promise<void>;
|
|
24
24
|
deleteAttachment(id: string): Promise<void>;
|
|
25
|
+
addReaction(commentId: string, reactionOrEmoji: {
|
|
26
|
+
emoji: string;
|
|
27
|
+
userId: string;
|
|
28
|
+
} | string, maybeUserId?: string): Promise<Comment>;
|
|
29
|
+
removeReaction(commentId: string, reactionOrEmoji: {
|
|
30
|
+
emoji: string;
|
|
31
|
+
userId: string;
|
|
32
|
+
} | string, maybeUserId?: string): Promise<Comment>;
|
|
25
33
|
}
|
|
26
34
|
export declare function createTaskActivityState(client: CriticalPathClient, taskId?: string): TaskActivityState;
|
|
27
35
|
//# sourceMappingURL=activity-state.svelte.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"activity-state.svelte.d.ts","sourceRoot":"","sources":["../src/activity-state.svelte.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAE/D,MAAM,WAAW,8BAA+B,SAAQ,OAAO;IAC7D,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,OAAO,EAAE,8BAA8B,EAAE,CAAC;CAC3C;AAED,qBAAa,iBAAiB;IA6ChB,OAAO,CAAC,MAAM;IAA6B,MAAM,CAAC,EAAE,MAAM;IA5CtE,QAAQ,YAAyB;IACjC,WAAW,eAA4B;IACvC,OAAO,UAA0B;IACjC,KAAK,eAA8B;IAEnC,OAAO,mCAiCJ;IAEH,qBAAqB,eAElB;gBAEiB,MAAM,EAAE,kBAAkB,EAAS,MAAM,CAAC,EAAE,MAAM,YAAA;IAEhE,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM;IAwBrB,UAAU,CACd,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,CAAC,EACjE,gBAAgB,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,CAAC,CAAC;;;;IAiCjG,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,CAAC;IAelF,aAAa,CAAC,EAAE,EAAE,MAAM;IAaxB,gBAAgB,CAAC,EAAE,EAAE,MAAM;
|
|
1
|
+
{"version":3,"file":"activity-state.svelte.d.ts","sourceRoot":"","sources":["../src/activity-state.svelte.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAE/D,MAAM,WAAW,8BAA+B,SAAQ,OAAO;IAC7D,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,OAAO,EAAE,8BAA8B,EAAE,CAAC;CAC3C;AAED,qBAAa,iBAAiB;IA6ChB,OAAO,CAAC,MAAM;IAA6B,MAAM,CAAC,EAAE,MAAM;IA5CtE,QAAQ,YAAyB;IACjC,WAAW,eAA4B;IACvC,OAAO,UAA0B;IACjC,KAAK,eAA8B;IAEnC,OAAO,mCAiCJ;IAEH,qBAAqB,eAElB;gBAEiB,MAAM,EAAE,kBAAkB,EAAS,MAAM,CAAC,EAAE,MAAM,YAAA;IAEhE,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM;IAwBrB,UAAU,CACd,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,CAAC,EACjE,gBAAgB,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,CAAC,CAAC;;;;IAiCjG,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,CAAC;IAelF,aAAa,CAAC,EAAE,EAAE,MAAM;IAaxB,gBAAgB,CAAC,EAAE,EAAE,MAAM;IAa3B,WAAW,CACf,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,EAC3D,WAAW,CAAC,EAAE,MAAM;IAiBhB,cAAc,CAClB,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,EAC3D,WAAW,CAAC,EAAE,MAAM;CAgBvB;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,kBAAkB,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,iBAAiB,CAEtG"}
|
|
@@ -15,6 +15,14 @@ export declare class CommentState {
|
|
|
15
15
|
addComment(input: Omit<Comment, 'id' | 'taskId' | 'createdAt' | 'updatedAt'>): Promise<Comment>;
|
|
16
16
|
updateComment(id: string, updates: Partial<Comment>): Promise<Comment>;
|
|
17
17
|
deleteComment(id: string): Promise<void>;
|
|
18
|
+
addReaction(commentId: string, reactionOrEmoji: {
|
|
19
|
+
emoji: string;
|
|
20
|
+
userId: string;
|
|
21
|
+
} | string, maybeUserId?: string): Promise<Comment>;
|
|
22
|
+
removeReaction(commentId: string, reactionOrEmoji: {
|
|
23
|
+
emoji: string;
|
|
24
|
+
userId: string;
|
|
25
|
+
} | string, maybeUserId?: string): Promise<Comment>;
|
|
18
26
|
}
|
|
19
27
|
export declare function createCommentState(client: CriticalPathClient, taskId?: string): CommentState;
|
|
20
28
|
//# sourceMappingURL=comment-state.svelte.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"comment-state.svelte.d.ts","sourceRoot":"","sources":["../src/comment-state.svelte.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAEnD,MAAM,WAAW,eAAgB,SAAQ,OAAO;IAC9C,OAAO,EAAE,eAAe,EAAE,CAAC;CAC5B;AAED,qBAAa,YAAY;IAyBX,OAAO,CAAC,MAAM;IAA6B,MAAM,CAAC,EAAE,MAAM;IAxBtE,IAAI,YAAyB;IAC7B,OAAO,UAA0B;IACjC,KAAK,eAA8B;IAEnC,OAAO,oBAkBJ;gBAEiB,MAAM,EAAE,kBAAkB,EAAS,MAAM,CAAC,EAAE,MAAM,YAAA;IAEhE,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM;IAkBrB,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,CAAC;IAe5E,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC;IAYnD,aAAa,CAAC,EAAE,EAAE,MAAM;
|
|
1
|
+
{"version":3,"file":"comment-state.svelte.d.ts","sourceRoot":"","sources":["../src/comment-state.svelte.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAEnD,MAAM,WAAW,eAAgB,SAAQ,OAAO;IAC9C,OAAO,EAAE,eAAe,EAAE,CAAC;CAC5B;AAED,qBAAa,YAAY;IAyBX,OAAO,CAAC,MAAM;IAA6B,MAAM,CAAC,EAAE,MAAM;IAxBtE,IAAI,YAAyB;IAC7B,OAAO,UAA0B;IACjC,KAAK,eAA8B;IAEnC,OAAO,oBAkBJ;gBAEiB,MAAM,EAAE,kBAAkB,EAAS,MAAM,CAAC,EAAE,MAAM,YAAA;IAEhE,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM;IAkBrB,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,CAAC;IAe5E,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC;IAYnD,aAAa,CAAC,EAAE,EAAE,MAAM;IAaxB,WAAW,CACf,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,EAC3D,WAAW,CAAC,EAAE,MAAM;IAiBhB,cAAc,CAClB,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,EAC3D,WAAW,CAAC,EAAE,MAAM;CAgBvB;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,kBAAkB,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,YAAY,CAE5F"}
|
package/dist/index.js
CHANGED
|
@@ -114,6 +114,32 @@ var i = class {
|
|
|
114
114
|
throw this.error = n, n;
|
|
115
115
|
}
|
|
116
116
|
}
|
|
117
|
+
async updateTask(e, t) {
|
|
118
|
+
let n = this.data.findIndex((t) => t.id === e);
|
|
119
|
+
if (n === -1) return this.client.updateTask(e, t);
|
|
120
|
+
let r = this.data[n], i = {
|
|
121
|
+
...r,
|
|
122
|
+
...t,
|
|
123
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
124
|
+
}, a = [...this.data];
|
|
125
|
+
a[n] = i, this.data = a;
|
|
126
|
+
try {
|
|
127
|
+
let n = await this.client.updateTask(e, t), r = this.data.findIndex((t) => t.id === e);
|
|
128
|
+
if (r !== -1) {
|
|
129
|
+
let e = [...this.data];
|
|
130
|
+
e[r] = n, this.data = e;
|
|
131
|
+
}
|
|
132
|
+
return n;
|
|
133
|
+
} catch (t) {
|
|
134
|
+
let n = this.data.findIndex((t) => t.id === e);
|
|
135
|
+
if (n !== -1) {
|
|
136
|
+
let e = [...this.data];
|
|
137
|
+
e[n] = r, this.data = e;
|
|
138
|
+
}
|
|
139
|
+
let i = t instanceof Error ? t : Error(String(t));
|
|
140
|
+
throw this.error = i, i;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
117
143
|
async updateTaskStatus(e, t) {
|
|
118
144
|
let n = this.data.findIndex((t) => t.id === e);
|
|
119
145
|
if (n === -1) return this.client.updateTask(e, { status: t });
|
|
@@ -321,6 +347,30 @@ var c = class {
|
|
|
321
347
|
throw this.error = n, n;
|
|
322
348
|
}
|
|
323
349
|
}
|
|
350
|
+
async addReaction(e, t, n) {
|
|
351
|
+
try {
|
|
352
|
+
let r = typeof t == "string" ? {
|
|
353
|
+
emoji: t,
|
|
354
|
+
userId: n
|
|
355
|
+
} : t, i = await this.client.addCommentReaction(e, r);
|
|
356
|
+
return this.data = this.data.map((t) => t.id === e ? i : t), i;
|
|
357
|
+
} catch (e) {
|
|
358
|
+
let t = e instanceof Error ? e : Error(String(e));
|
|
359
|
+
throw this.error = t, t;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
async removeReaction(e, t, n) {
|
|
363
|
+
try {
|
|
364
|
+
let r = typeof t == "string" ? {
|
|
365
|
+
emoji: t,
|
|
366
|
+
userId: n
|
|
367
|
+
} : t, i = await this.client.removeCommentReaction(e, r);
|
|
368
|
+
return this.data = this.data.map((t) => t.id === e ? i : t), i;
|
|
369
|
+
} catch (e) {
|
|
370
|
+
let t = e instanceof Error ? e : Error(String(e));
|
|
371
|
+
throw this.error = t, t;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
324
374
|
};
|
|
325
375
|
function l(e, t) {
|
|
326
376
|
return new c(e, t);
|
|
@@ -522,6 +572,30 @@ var f = class {
|
|
|
522
572
|
throw this.error = n, n;
|
|
523
573
|
}
|
|
524
574
|
}
|
|
575
|
+
async addReaction(e, t, n) {
|
|
576
|
+
try {
|
|
577
|
+
let r = typeof t == "string" ? {
|
|
578
|
+
emoji: t,
|
|
579
|
+
userId: n
|
|
580
|
+
} : t, i = await this.client.addCommentReaction(e, r);
|
|
581
|
+
return this.comments = this.comments.map((t) => t.id === e ? i : t), i;
|
|
582
|
+
} catch (e) {
|
|
583
|
+
let t = e instanceof Error ? e : Error(String(e));
|
|
584
|
+
throw this.error = t, t;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
async removeReaction(e, t, n) {
|
|
588
|
+
try {
|
|
589
|
+
let r = typeof t == "string" ? {
|
|
590
|
+
emoji: t,
|
|
591
|
+
userId: n
|
|
592
|
+
} : t, i = await this.client.removeCommentReaction(e, r);
|
|
593
|
+
return this.comments = this.comments.map((t) => t.id === e ? i : t), i;
|
|
594
|
+
} catch (e) {
|
|
595
|
+
let t = e instanceof Error ? e : Error(String(e));
|
|
596
|
+
throw this.error = t, t;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
525
599
|
};
|
|
526
600
|
function p(e, t) {
|
|
527
601
|
return new f(e, t);
|
|
@@ -9,6 +9,7 @@ export declare class TaskState {
|
|
|
9
9
|
constructor(client: CriticalPathClient, projectId?: string | undefined);
|
|
10
10
|
fetch(): Promise<void>;
|
|
11
11
|
createTask(input: Omit<Task, 'id' | 'createdAt' | 'updatedAt'>): Promise<Task>;
|
|
12
|
+
updateTask(taskId: string, updates: Partial<Task>): Promise<Task>;
|
|
12
13
|
updateTaskStatus(taskId: string, status: TaskStatus): Promise<Task>;
|
|
13
14
|
deleteTask(taskId: string): Promise<boolean | undefined>;
|
|
14
15
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-state.svelte.d.ts","sourceRoot":"","sources":["../src/task-state.svelte.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAE5D,qBAAa,SAAS;IAMlB,OAAO,CAAC,MAAM;IACP,SAAS,CAAC,EAAE,MAAM;IAN3B,IAAI,SAAsB;IAC1B,OAAO,UAA0B;IACjC,KAAK,eAA8B;gBAGzB,MAAM,EAAE,kBAAkB,EAC3B,SAAS,CAAC,EAAE,MAAM,YAAA;IAGrB,KAAK;IAYL,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,WAAW,GAAG,WAAW,CAAC;IA2B9D,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU;IAyCnD,UAAU,CAAC,MAAM,EAAE,MAAM;CAuBhC;AAED,wBAAgB,eAAe,CAC7B,MAAM,EAAE,kBAAkB,EAC1B,SAAS,CAAC,EAAE,MAAM,GACjB,SAAS,CAEX"}
|
|
1
|
+
{"version":3,"file":"task-state.svelte.d.ts","sourceRoot":"","sources":["../src/task-state.svelte.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAE5D,qBAAa,SAAS;IAMlB,OAAO,CAAC,MAAM;IACP,SAAS,CAAC,EAAE,MAAM;IAN3B,IAAI,SAAsB;IAC1B,OAAO,UAA0B;IACjC,KAAK,eAA8B;gBAGzB,MAAM,EAAE,kBAAkB,EAC3B,SAAS,CAAC,EAAE,MAAM,YAAA;IAGrB,KAAK;IAYL,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,WAAW,GAAG,WAAW,CAAC;IA2B9D,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC;IAyCjD,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU;IAyCnD,UAAU,CAAC,MAAM,EAAE,MAAM;CAuBhC;AAED,wBAAgB,eAAe,CAC7B,MAAM,EAAE,kBAAkB,EAC1B,SAAS,CAAC,EAAE,MAAM,GACjB,SAAS,CAEX"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@critical-path/svelte",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Svelte 5 Runes state and reactive integrations for Critical Path headless project management framework",
|
|
5
5
|
"author": "Jack James",
|
|
6
6
|
"license": "MIT",
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
}
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@critical-path/client": "0.
|
|
22
|
-
"@critical-path/core": "0.
|
|
21
|
+
"@critical-path/client": "0.5.0",
|
|
22
|
+
"@critical-path/core": "0.10.0"
|
|
23
23
|
},
|
|
24
24
|
"peerDependencies": {
|
|
25
25
|
"svelte": "^5.0.0"
|
|
@@ -153,6 +153,46 @@ export class TaskActivityState {
|
|
|
153
153
|
throw errorObj;
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
|
+
|
|
157
|
+
async addReaction(
|
|
158
|
+
commentId: string,
|
|
159
|
+
reactionOrEmoji: { emoji: string; userId: string } | string,
|
|
160
|
+
maybeUserId?: string
|
|
161
|
+
) {
|
|
162
|
+
try {
|
|
163
|
+
const payload =
|
|
164
|
+
typeof reactionOrEmoji === 'string'
|
|
165
|
+
? { emoji: reactionOrEmoji, userId: maybeUserId! }
|
|
166
|
+
: reactionOrEmoji;
|
|
167
|
+
const updated = await this.client.addCommentReaction(commentId, payload);
|
|
168
|
+
this.comments = this.comments.map((c) => (c.id === commentId ? updated : c));
|
|
169
|
+
return updated;
|
|
170
|
+
} catch (err) {
|
|
171
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
172
|
+
this.error = errorObj;
|
|
173
|
+
throw errorObj;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
async removeReaction(
|
|
178
|
+
commentId: string,
|
|
179
|
+
reactionOrEmoji: { emoji: string; userId: string } | string,
|
|
180
|
+
maybeUserId?: string
|
|
181
|
+
) {
|
|
182
|
+
try {
|
|
183
|
+
const payload =
|
|
184
|
+
typeof reactionOrEmoji === 'string'
|
|
185
|
+
? { emoji: reactionOrEmoji, userId: maybeUserId! }
|
|
186
|
+
: reactionOrEmoji;
|
|
187
|
+
const updated = await this.client.removeCommentReaction(commentId, payload);
|
|
188
|
+
this.comments = this.comments.map((c) => (c.id === commentId ? updated : c));
|
|
189
|
+
return updated;
|
|
190
|
+
} catch (err) {
|
|
191
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
192
|
+
this.error = errorObj;
|
|
193
|
+
throw errorObj;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
156
196
|
}
|
|
157
197
|
|
|
158
198
|
export function createTaskActivityState(client: CriticalPathClient, taskId?: string): TaskActivityState {
|
|
@@ -90,6 +90,46 @@ export class CommentState {
|
|
|
90
90
|
throw errorObj;
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
|
+
|
|
94
|
+
async addReaction(
|
|
95
|
+
commentId: string,
|
|
96
|
+
reactionOrEmoji: { emoji: string; userId: string } | string,
|
|
97
|
+
maybeUserId?: string
|
|
98
|
+
) {
|
|
99
|
+
try {
|
|
100
|
+
const payload =
|
|
101
|
+
typeof reactionOrEmoji === 'string'
|
|
102
|
+
? { emoji: reactionOrEmoji, userId: maybeUserId! }
|
|
103
|
+
: reactionOrEmoji;
|
|
104
|
+
const updated = await this.client.addCommentReaction(commentId, payload);
|
|
105
|
+
this.data = this.data.map((c) => (c.id === commentId ? updated : c));
|
|
106
|
+
return updated;
|
|
107
|
+
} catch (err) {
|
|
108
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
109
|
+
this.error = errorObj;
|
|
110
|
+
throw errorObj;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async removeReaction(
|
|
115
|
+
commentId: string,
|
|
116
|
+
reactionOrEmoji: { emoji: string; userId: string } | string,
|
|
117
|
+
maybeUserId?: string
|
|
118
|
+
) {
|
|
119
|
+
try {
|
|
120
|
+
const payload =
|
|
121
|
+
typeof reactionOrEmoji === 'string'
|
|
122
|
+
? { emoji: reactionOrEmoji, userId: maybeUserId! }
|
|
123
|
+
: reactionOrEmoji;
|
|
124
|
+
const updated = await this.client.removeCommentReaction(commentId, payload);
|
|
125
|
+
this.data = this.data.map((c) => (c.id === commentId ? updated : c));
|
|
126
|
+
return updated;
|
|
127
|
+
} catch (err) {
|
|
128
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
129
|
+
this.error = errorObj;
|
|
130
|
+
throw errorObj;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
93
133
|
}
|
|
94
134
|
|
|
95
135
|
export function createCommentState(client: CriticalPathClient, taskId?: string): CommentState {
|
package/src/index.test.ts
CHANGED
|
@@ -131,7 +131,7 @@ describe('@critical-path/svelte Svelte 5 Runes Test Suite', () => {
|
|
|
131
131
|
const mockClient = {
|
|
132
132
|
getTasks: vi.fn().mockResolvedValue([mockTask]),
|
|
133
133
|
createTask: vi.fn().mockResolvedValue(mockTask),
|
|
134
|
-
updateTask: vi.fn().
|
|
134
|
+
updateTask: vi.fn().mockImplementation((taskId: string, updates: Partial<Task>) => Promise.resolve({ ...mockTask, ...updates })),
|
|
135
135
|
deleteTask: vi.fn().mockResolvedValue(undefined)
|
|
136
136
|
} as unknown as CriticalPathClient;
|
|
137
137
|
|
|
@@ -144,6 +144,12 @@ describe('@critical-path/svelte Svelte 5 Runes Test Suite', () => {
|
|
|
144
144
|
await taskState.updateTaskStatus('task_1', 'in_progress');
|
|
145
145
|
expect(taskState.data[0].status).toBe('in_progress');
|
|
146
146
|
|
|
147
|
+
// Update task generic updates (e.g. todos)
|
|
148
|
+
await taskState.updateTask('task_1', {
|
|
149
|
+
todos: [{ id: 'todo_1', title: 'Checklist item', completed: true }]
|
|
150
|
+
});
|
|
151
|
+
expect(taskState.data[0].todos).toEqual([{ id: 'todo_1', title: 'Checklist item', completed: true }]);
|
|
152
|
+
|
|
147
153
|
// Delete task
|
|
148
154
|
await taskState.deleteTask('task_1');
|
|
149
155
|
expect(taskState.data).toEqual([]);
|
|
@@ -210,12 +216,15 @@ describe('@critical-path/svelte Svelte 5 Runes Test Suite', () => {
|
|
|
210
216
|
updatedAt: '2026-01-01'
|
|
211
217
|
};
|
|
212
218
|
const updatedComment = { ...mockComment, content: 'Updated comment' };
|
|
219
|
+
const reactedComment = { ...mockComment, reactions: [{ emoji: '🔥', userId: 'u2', createdAt: '2026-01-01' }] };
|
|
213
220
|
|
|
214
221
|
const mockClient = {
|
|
215
222
|
getComments: vi.fn().mockResolvedValue([mockComment]),
|
|
216
223
|
addComment: vi.fn().mockResolvedValue(mockComment),
|
|
217
224
|
updateComment: vi.fn().mockResolvedValue(updatedComment),
|
|
218
|
-
deleteComment: vi.fn().mockResolvedValue(true)
|
|
225
|
+
deleteComment: vi.fn().mockResolvedValue(true),
|
|
226
|
+
addCommentReaction: vi.fn().mockResolvedValue(reactedComment),
|
|
227
|
+
removeCommentReaction: vi.fn().mockResolvedValue(mockComment)
|
|
219
228
|
} as unknown as CriticalPathClient;
|
|
220
229
|
|
|
221
230
|
const commentState = new CommentState(mockClient, 'task_1');
|
|
@@ -226,6 +235,13 @@ describe('@critical-path/svelte Svelte 5 Runes Test Suite', () => {
|
|
|
226
235
|
await commentState.updateComment('cmt_1', { content: 'Updated comment' });
|
|
227
236
|
expect(commentState.data[0].content).toBe('Updated comment');
|
|
228
237
|
|
|
238
|
+
await commentState.addReaction('cmt_1', '🔥', 'u2');
|
|
239
|
+
expect(commentState.data[0].reactions).toHaveLength(1);
|
|
240
|
+
expect(commentState.data[0].reactions?.[0].emoji).toBe('🔥');
|
|
241
|
+
|
|
242
|
+
await commentState.removeReaction('cmt_1', '🔥', 'u2');
|
|
243
|
+
expect(commentState.data[0].reactions).toBeUndefined();
|
|
244
|
+
|
|
229
245
|
await commentState.deleteComment('cmt_1');
|
|
230
246
|
expect(commentState.data).toEqual([]);
|
|
231
247
|
});
|
package/src/task-state.svelte.ts
CHANGED
|
@@ -51,6 +51,47 @@ export class TaskState {
|
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
async updateTask(taskId: string, updates: Partial<Task>) {
|
|
55
|
+
const idx = this.data.findIndex((t) => t.id === taskId);
|
|
56
|
+
if (idx === -1) {
|
|
57
|
+
return this.client.updateTask(taskId, updates);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const previousTask = this.data[idx];
|
|
61
|
+
const optimisticTask: Task = {
|
|
62
|
+
...previousTask,
|
|
63
|
+
...updates,
|
|
64
|
+
updatedAt: new Date().toISOString()
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// Optimistically update local task
|
|
68
|
+
const newData = [...this.data];
|
|
69
|
+
newData[idx] = optimisticTask;
|
|
70
|
+
this.data = newData;
|
|
71
|
+
|
|
72
|
+
try {
|
|
73
|
+
const updated = await this.client.updateTask(taskId, updates);
|
|
74
|
+
const currentIdx = this.data.findIndex((t) => t.id === taskId);
|
|
75
|
+
if (currentIdx !== -1) {
|
|
76
|
+
const confirmedData = [...this.data];
|
|
77
|
+
confirmedData[currentIdx] = updated;
|
|
78
|
+
this.data = confirmedData;
|
|
79
|
+
}
|
|
80
|
+
return updated;
|
|
81
|
+
} catch (err) {
|
|
82
|
+
// Rollback to previous task on error
|
|
83
|
+
const rollbackIdx = this.data.findIndex((t) => t.id === taskId);
|
|
84
|
+
if (rollbackIdx !== -1) {
|
|
85
|
+
const rollbackData = [...this.data];
|
|
86
|
+
rollbackData[rollbackIdx] = previousTask;
|
|
87
|
+
this.data = rollbackData;
|
|
88
|
+
}
|
|
89
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
90
|
+
this.error = errorObj;
|
|
91
|
+
throw errorObj;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
54
95
|
async updateTaskStatus(taskId: string, status: TaskStatus) {
|
|
55
96
|
const idx = this.data.findIndex((t) => t.id === taskId);
|
|
56
97
|
if (idx === -1) {
|