Skip to content

Commit 3ebee0e

Browse files
authored
Merge pull request #544 from fccview/develop
fix drag/drop for kanban when statuses are default
2 parents 984f2ee + b40adaa commit 3ebee0e

3 files changed

Lines changed: 49 additions & 4 deletions

File tree

app/_server/actions/checklist-item/drop.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { broadcast } from "@/app/_server/ws/broadcast";
1010
import { applyDrop } from "@/app/_utils/kanban/board-utils";
1111
import { listToMarkdown } from "@/app/_utils/checklist-utils";
1212
import { CHECKLISTS_FOLDER } from "@/app/_consts/checklists";
13+
import { DEFAULT_KANBAN_STATUSES } from "@/app/_consts/kanban";
1314
import { Checklist, Result } from "@/app/_types";
1415
import { ItemTypes, PermissionTypes } from "@/app/_types/enums";
1516

@@ -61,9 +62,11 @@ export const dropItem = async (
6162
return { success: false, error: "Item not found" };
6263
}
6364

64-
const isValidStatus = (list.statuses || []).some(
65-
(s) => s.id === targetStatus,
66-
);
65+
const statuses =
66+
list.statuses && list.statuses.length > 0
67+
? list.statuses
68+
: DEFAULT_KANBAN_STATUSES;
69+
const isValidStatus = statuses.some((s) => s.id === targetStatus);
6770
if (!isValidStatus) {
6871
return { success: false, error: "Invalid target status" };
6972
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "jotty.page",
3-
"version": "1.25.0",
3+
"version": "1.25.1",
44
"private": true,
55
"scripts": {
66
"dev": "next dev",

tests/server-actions/drop-item.test.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,48 @@ describe("dropItem", () => {
190190
expect(mockServerWriteFile).not.toHaveBeenCalled();
191191
});
192192

193+
it("accepts a default status on a legacy board without explicit statuses", async () => {
194+
const { statuses: _statuses, ...legacyBoard } = mockBoard;
195+
mockGetListById.mockImplementation(async (id: string) =>
196+
id === BOARD_UUID ? structuredClone(legacyBoard) : undefined,
197+
);
198+
199+
const result = await dropItem(
200+
createFormData({
201+
uuid: BOARD_UUID,
202+
itemId: "task-1",
203+
targetStatus: "in_progress",
204+
targetIndex: "0",
205+
}),
206+
);
207+
208+
expect(result.success).toBe(true);
209+
expect(result.data!.items.find((i) => i.id === "task-1")?.status).toBe(
210+
"in_progress",
211+
);
212+
expect(mockServerWriteFile).toHaveBeenCalledTimes(1);
213+
});
214+
215+
it("rejects a target status that is not a default when none are defined", async () => {
216+
const { statuses: _statuses, ...legacyBoard } = mockBoard;
217+
mockGetListById.mockImplementation(async (id: string) =>
218+
id === BOARD_UUID ? structuredClone(legacyBoard) : undefined,
219+
);
220+
221+
const result = await dropItem(
222+
createFormData({
223+
uuid: BOARD_UUID,
224+
itemId: "task-1",
225+
targetStatus: "nonsense",
226+
targetIndex: "0",
227+
}),
228+
);
229+
230+
expect(result.success).toBe(false);
231+
expect(result.error).toBe("Invalid target status");
232+
expect(mockServerWriteFile).not.toHaveBeenCalled();
233+
});
234+
193235
it("rejects without edit permission", async () => {
194236
mockCheckUserPermission.mockResolvedValue(false);
195237

0 commit comments

Comments
 (0)