Skip to content

Commit 926edfd

Browse files
committed
fix: improve task realtime update handling
1 parent 7825183 commit 926edfd

10 files changed

+109
-31
lines changed

src/lib/api/appwrite/tasks.api.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,11 +111,13 @@ export const updateTaskTitle = async (
111111
taskId: string,
112112
taskTitle: string,
113113
boardId: string,
114+
prevStatusId: string,
114115
): Promise<void> => {
115116
try {
116117
await checkForBoardAccess(boardId);
117118
await db.updateDocument(KRELLO_DB_ID, TASK_COLLECTION_ID, taskId, {
118119
title: taskTitle,
120+
prevStatusId,
119121
});
120122
} catch (e: any) {
121123
console.error(e);
@@ -127,11 +129,13 @@ export const updateTaskPriority = async (
127129
taskId: string,
128130
priority: string,
129131
boardId: string,
132+
prevStatusId: string,
130133
): Promise<void> => {
131134
try {
132135
await checkForBoardAccess(boardId);
133136
await db.updateDocument(KRELLO_DB_ID, TASK_COLLECTION_ID, taskId, {
134137
priority,
138+
prevStatusId,
135139
});
136140
} catch (e: any) {
137141
console.error(e);
@@ -143,11 +147,13 @@ export const updateTaskDescription = async (
143147
taskId: string,
144148
description: string,
145149
boardId: string,
150+
prevStatusId: string,
146151
): Promise<void> => {
147152
try {
148153
await checkForBoardAccess(boardId);
149154
await db.updateDocument(KRELLO_DB_ID, TASK_COLLECTION_ID, taskId, {
150155
description,
156+
prevStatusId,
151157
});
152158
toast.success('Task description updated successfully');
153159
} catch (e) {
@@ -161,11 +167,13 @@ export const addLabelInTask = async (
161167
newLabelId: string,
162168
labels: CardLabel[],
163169
boardId: string,
170+
prevStatusId: string,
164171
): Promise<void> => {
165172
try {
166173
await checkForBoardAccess(boardId);
167174
await db.updateDocument(KRELLO_DB_ID, TASK_COLLECTION_ID, taskId, {
168175
labels: [...labels.map((label) => label.id), newLabelId],
176+
prevStatusId,
169177
});
170178
toast.success('Task updated successfully');
171179
} catch (e) {
@@ -179,11 +187,13 @@ export const removeLabelInTask = async (
179187
removedLabelId: string,
180188
labels: CardLabel[],
181189
boardId: string,
190+
prevStatusId: string,
182191
): Promise<void> => {
183192
try {
184193
await checkForBoardAccess(boardId);
185194
await db.updateDocument(KRELLO_DB_ID, TASK_COLLECTION_ID, taskId, {
186195
labels: labels.filter((oldLabel) => oldLabel.id !== removedLabelId).map((label) => label.id),
196+
prevStatusId,
187197
});
188198
toast.success('Task updated successfully');
189199
} catch (e) {
@@ -196,6 +206,7 @@ export const updateTaskCoverUrl = async (
196206
taskDocId: string,
197207
cover: string | File,
198208
boardId: string,
209+
prevStatusId: string,
199210
): Promise<string> => {
200211
await checkForBoardAccess(boardId);
201212
let coverUrl;
@@ -207,6 +218,7 @@ export const updateTaskCoverUrl = async (
207218

208219
await db.updateDocument(KRELLO_DB_ID, TASK_COLLECTION_ID, taskDocId, {
209220
coverUrl,
221+
prevStatusId,
210222
});
211223
return coverUrl;
212224
};

src/lib/components/TaskDetails/TaskDetails.component.svelte

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
<script lang="ts">
22
import { Badge, Button, Dropzone, Modal, Spinner } from 'flowbite-svelte';
33
import type { Task } from '$types/kanban';
4-
import TaskTitle from './TaskTitle.component.svelte';
5-
import TaskStatus from './TaskStatus.component.svelte';
6-
import TaskDescription from './TaskDescription.component.svelte';
7-
import TaskPriority from './TaskPriority.component.svelte';
4+
import TaskTitle from './components/TaskTitle.component.svelte';
5+
import TaskStatus from './components/TaskStatus.component.svelte';
6+
import TaskDescription from './components/TaskDescription.component.svelte';
7+
import TaskPriority from './components/TaskPriority.component.svelte';
88
import SelectLabel from '$components/NewTask/SelectLabel.component.svelte';
99
import {
1010
addLabelInTask,
@@ -13,17 +13,37 @@
1313
} from '$lib/api/appwrite/tasks.api';
1414
import type { CardLabel } from '$types/card';
1515
import Icon from '@iconify/svelte';
16-
import CoverUploader from './CoverUploader.component.svelte';
16+
import CoverUploader from './components/CoverUploader.component.svelte';
1717
import { Status } from '$enums/Status.enums';
1818
import toast from 'svelte-french-toast';
19-
import TaskActivity from './TaskActivity.component.svelte';
19+
import TaskActivity from './components/TaskActivity.component.svelte';
2020
import { onDestroy } from 'svelte';
2121
import type { Board } from '$lib/types/board';
2222
import boardStore from '$lib/store/boards.store';
23+
import { kanbanStore } from '$lib/store';
2324
2425
export let taskDetails: Task | null,
2526
isModalOpen = false;
2627
28+
const unsubscribe = kanbanStore.subscribe((store) => {
29+
store.kanbanBoard;
30+
31+
// Iterate over each column in the kanban board
32+
for (const columnId in store.kanbanBoard) {
33+
const columnData = store.kanbanBoard[columnId];
34+
const { tasks } = columnData;
35+
36+
// Iterate over the tasks in the current column
37+
for (const task of tasks) {
38+
if (task.id === taskDetails?.id) {
39+
taskDetails = task;
40+
}
41+
}
42+
}
43+
});
44+
45+
onDestroy(unsubscribe);
46+
2747
let currentBoard: Board;
2848
const unsub = boardStore.subscribe((store) => {
2949
currentBoard = store.currentBoard as Board;
@@ -34,13 +54,25 @@
3454
const hanldeAddLabel = async (e: CustomEvent): Promise<void> => {
3555
if (!taskDetails) return;
3656
const newLabel = e.detail as CardLabel;
37-
await addLabelInTask(taskDetails.id, newLabel.id, taskDetails.labels, currentBoard.id);
57+
await addLabelInTask(
58+
taskDetails.id,
59+
newLabel.id,
60+
taskDetails.labels,
61+
currentBoard.id,
62+
taskDetails.status.id,
63+
);
3864
};
3965
const hanldeRemoveLabel = async (e: MouseEvent): Promise<void> => {
4066
if (!taskDetails) return;
4167
4268
const removedLabelId = (e.currentTarget as HTMLButtonElement).id;
43-
await removeLabelInTask(taskDetails?.id, removedLabelId, taskDetails.labels, currentBoard.id);
69+
await removeLabelInTask(
70+
taskDetails?.id,
71+
removedLabelId,
72+
taskDetails.labels,
73+
currentBoard.id,
74+
taskDetails.status.id,
75+
);
4476
};
4577
4678
// file uploads
@@ -76,7 +108,12 @@
76108
coverUplaodStatus = Status.LOADING;
77109
try {
78110
if (taskDetails && taskDetails.id && imageFile) {
79-
await updateTaskCoverUrl(taskDetails?.id, imageFile, currentBoard.id);
111+
await updateTaskCoverUrl(
112+
taskDetails?.id,
113+
imageFile,
114+
currentBoard.id,
115+
taskDetails.status.id,
116+
);
80117
}
81118
toast.success('Cover updated successfully');
82119
} catch (e: any) {
@@ -138,9 +175,9 @@
138175
{/if}
139176

140177
<div class="flex flex-col gap-y-2">
141-
<TaskTitle taskId={taskDetails.id} title={taskDetails.title} />
142-
<TaskStatus status={taskDetails.status} taskId={taskDetails.id} />
143-
<TaskPriority priority={taskDetails.priority} taskId={taskDetails.id} />
178+
<TaskTitle {taskDetails} />
179+
<TaskStatus {taskDetails} />
180+
<TaskPriority {taskDetails} />
144181

145182
{#if taskDetails.labels.length > 0}
146183
<div class="flex mt-2 items-center gap-4">
@@ -171,7 +208,7 @@
171208

172209
<div class="flex gap-8">
173210
<section class="flex-1 flex flex-col gap-y-4">
174-
<TaskDescription taskDescription={taskDetails.description} taskId={taskDetails.id} />
211+
<TaskDescription {taskDetails} />
175212
</section>
176213

177214
<section class="w-80 flex flex-col gap-4">
@@ -180,7 +217,7 @@
180217
</section>
181218
</div>
182219

183-
<TaskActivity taskId={taskDetails.id} />
220+
<TaskActivity {taskDetails} />
184221
</div>
185222
</Modal>
186223
{/if}

src/lib/components/TaskDetails/TaskActivity.component.svelte renamed to src/lib/components/TaskDetails/components/TaskActivity.component.svelte

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,16 @@
1212
import type { CommentDoc } from '$types/appwriteDocs.types';
1313
import type { AuthState, UserDetails } from '$types/authStore';
1414
import type { CreateCommentFormValues } from '$types/formValues';
15-
import type { CommentType } from '$types/kanban';
15+
import type { CommentType, Task } from '$types/kanban';
1616
import { createCommentValidationSchema } from '$lib/validations/task.validations';
1717
import Icon from '@iconify/svelte';
1818
import { Avatar, Helper, Spinner } from 'flowbite-svelte';
1919
import { Textarea, Button } from 'flowbite-svelte';
2020
import { onDestroy, onMount } from 'svelte';
2121
import { createForm } from 'svelte-forms-lib';
2222
23-
export let taskId: string;
23+
export let taskDetails: Task;
24+
let taskId = taskDetails.id;
2425
2526
let userDetails: UserDetails = $authStore.userDetails;
2627
let isAnonymous: boolean = $authStore.isAnonymous;

src/lib/components/TaskDetails/TaskDescription.component.svelte renamed to src/lib/components/TaskDetails/components/TaskDescription.component.svelte

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,13 @@
88
import { onDestroy } from 'svelte';
99
import type { Board } from '$lib/types/board';
1010
import boardStore from '$lib/store/boards.store';
11+
import type { Task } from '$lib/types/kanban';
1112
12-
export let taskDescription = '',
13-
taskId: string;
13+
export let taskDetails: Task;
14+
let taskDescription = taskDetails.description;
15+
16+
let markdownContent = taskDetails.description;
17+
const taskId = taskDetails.id;
1418
let isEditing = false;
1519
1620
let currentBoard: Board;
@@ -29,13 +33,22 @@
2933
description: taskDescription ?? '',
3034
},
3135
onSubmit: async (values) => {
32-
await updateTaskDescription(taskId, values.description, currentBoard.id);
36+
await updateTaskDescription(
37+
taskId,
38+
values.description,
39+
currentBoard.id,
40+
taskDetails.status.id,
41+
);
42+
43+
markdownContent = values.description;
44+
isEditing = false;
3345
},
3446
});
3547
3648
const handleCancel = (): void => {
3749
form.update((prev) => ({ ...prev, description: taskDescription ?? '' }));
3850
isEditing = false;
51+
// markdownContent = taskDescription ?? '';
3952
};
4053
</script>
4154

@@ -98,7 +111,7 @@
98111
</div>
99112
</form>
100113
{:else}
101-
<div class={`${styles.markdown} mt-4`}>
102-
<SvelteMarkdown source={taskDescription ?? ''} />
114+
<div class={`${styles.markdown}`}>
115+
<SvelteMarkdown source={markdownContent ?? ''} />
103116
</div>
104117
{/if}

src/lib/components/TaskDetails/TaskPriority.component.svelte renamed to src/lib/components/TaskDetails/components/TaskPriority.component.svelte

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@
33
import { updateTaskPriority } from '$lib/api/appwrite/tasks.api';
44
import boardStore from '$lib/store/boards.store';
55
import type { Board } from '$lib/types/board';
6-
import type { TaskPriority } from '$types/kanban';
6+
import type { Task } from '$types/kanban';
77
import { Select } from 'flowbite-svelte';
88
import { onDestroy } from 'svelte';
99
10-
export let taskId: string;
11-
export let priority: TaskPriority | null;
10+
export let taskDetails: Task;
11+
12+
let priority = taskDetails.priority;
1213
1314
let currentBoard: Board;
1415
const unsub = boardStore.subscribe((store) => {
@@ -26,7 +27,7 @@
2627
2728
const hanldeChange = async (e: Event): Promise<void> => {
2829
const target = e.target as HTMLSelectElement;
29-
await updateTaskPriority(taskId, target.value, currentBoard.id);
30+
await updateTaskPriority(taskDetails.id, target.value, currentBoard.id, taskDetails.status.id);
3031
};
3132
</script>
3233

src/lib/components/TaskDetails/TaskStatus.component.svelte renamed to src/lib/components/TaskDetails/components/TaskStatus.component.svelte

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
import { kanbanStore } from '$lib/store';
44
import boardStore from '$lib/store/boards.store';
55
import type { Board } from '$lib/types/board';
6-
import type { TaskStatus } from '$types/kanban';
6+
import type { Task, TaskStatus } from '$types/kanban';
77
import { Select } from 'flowbite-svelte';
88
import { onDestroy } from 'svelte';
9-
export let taskId: string;
10-
export let status: TaskStatus;
9+
10+
export let taskDetails: Task;
11+
let taskId: string = taskDetails.id;
12+
let status: TaskStatus = taskDetails.status;
1113
1214
let currentBoard: Board;
1315

src/lib/components/TaskDetails/TaskTitle.component.svelte renamed to src/lib/components/TaskDetails/components/TaskTitle.component.svelte

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,18 @@
44
import { updateTaskTitle } from '$lib/api/appwrite/tasks.api';
55
import type { Board } from '$lib/types/board';
66
import boardStore from '$lib/store/boards.store';
7+
import type { Task } from '$lib/types/kanban';
78
8-
export let taskId: string, title: string;
9+
export let taskDetails: Task;
10+
11+
const taskId = taskDetails.id,
12+
title = taskDetails.title;
913
1014
let currentBoard: Board;
1115
const unsub = boardStore.subscribe((store) => {
1216
currentBoard = store.currentBoard as Board;
1317
});
18+
1419
onDestroy(unsub);
1520
1621
let isEditing = false;
@@ -47,7 +52,13 @@
4752
const hanldeTaskTitleChange = (e: Event): void => {
4853
const target = e.target as HTMLInputElement;
4954
50-
const update = updateTaskTitle.bind(null, taskId, target.value, currentBoard.id);
55+
const update = updateTaskTitle.bind(
56+
null,
57+
taskId,
58+
target.value,
59+
currentBoard.id,
60+
taskDetails.status.id,
61+
);
5162
lodash.debounce(update, 100)();
5263
};
5364
</script>

src/lib/sass/markdown.module.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
/* Paragraph */
1414
p {
15-
margin: 1em 0;
15+
line-height: 16px;
1616
}
1717

1818
/* Links */

src/lib/store/kanbanBoard.store.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export const addNewTaskInStore = (newTask: Task): void => {
3939
};
4040

4141
export const updateTask = (updatedTask: Task): void => {
42+
console.log('updateTask', updatedTask);
4243
kanbanStore.update((prevStore) => {
4344
const canUpdate =
4445
Object.hasOwn(prevStore.kanbanBoard, updatedTask.prevStatusId) &&

0 commit comments

Comments
 (0)