feat: rollback card/list if duplicate index
This commit is contained in:
@@ -210,7 +210,7 @@ export const boardRouter = createTRPCRouter({
|
||||
deletedBy: userId,
|
||||
});
|
||||
|
||||
if (!deletedLists?.length) {
|
||||
if (!Array.isArray(deletedLists)) {
|
||||
throw new TRPCError({
|
||||
message: `Failed to delete lists`,
|
||||
code: "INTERNAL_SERVER_ERROR",
|
||||
@@ -223,7 +223,7 @@ export const boardRouter = createTRPCRouter({
|
||||
deletedBy: userId,
|
||||
});
|
||||
|
||||
if (!deletedCards?.length) {
|
||||
if (!Array.isArray(deletedCards)) {
|
||||
throw new TRPCError({
|
||||
message: `Failed to delete cards`,
|
||||
code: "INTERNAL_SERVER_ERROR",
|
||||
|
||||
@@ -53,7 +53,8 @@ export const listRouter = createTRPCRouter({
|
||||
name: input.name,
|
||||
createdBy: userId,
|
||||
boardId: board.id,
|
||||
index: latestListIndex ? latestListIndex + 1 : 0,
|
||||
index:
|
||||
latestListIndex || latestListIndex === 0 ? latestListIndex + 1 : 0,
|
||||
});
|
||||
|
||||
if (!result)
|
||||
@@ -161,7 +162,7 @@ export const listRouter = createTRPCRouter({
|
||||
deletedBy: userId,
|
||||
});
|
||||
|
||||
if (!deletedCards?.length)
|
||||
if (!Array.isArray(deletedCards))
|
||||
throw new TRPCError({
|
||||
message: `Failed to delete cards`,
|
||||
code: "INTERNAL_SERVER_ERROR",
|
||||
@@ -177,7 +178,7 @@ export const listRouter = createTRPCRouter({
|
||||
|
||||
await listRepo.shiftIndex(ctx.db, {
|
||||
boardId: list.boardId,
|
||||
listIndex: list.id,
|
||||
listIndex: list.index,
|
||||
});
|
||||
|
||||
return { success: true };
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { api } from "~/utils/api";
|
||||
import { useBoard } from "~/providers/board";
|
||||
import { useModal } from "~/providers/modal";
|
||||
import { usePopup } from "~/providers/popup";
|
||||
|
||||
import Button from "~/components/Button";
|
||||
|
||||
@@ -14,6 +15,7 @@ export function DeleteListConfirmation({
|
||||
const utils = api.useUtils();
|
||||
const { boardData } = useBoard();
|
||||
const { closeModal } = useModal();
|
||||
const { showPopup } = usePopup();
|
||||
|
||||
const refetchBoard = async () => {
|
||||
if (boardData?.publicId) {
|
||||
@@ -30,6 +32,14 @@ export function DeleteListConfirmation({
|
||||
closeModal();
|
||||
return refetchBoard();
|
||||
},
|
||||
onError: async () => {
|
||||
closeModal();
|
||||
await refetchBoard();
|
||||
showPopup({
|
||||
header: "Unable to delete list",
|
||||
message: "Please try again later, or contact customer support.",
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -46,7 +56,10 @@ export function DeleteListConfirmation({
|
||||
<Button onClick={() => closeModal()} variant="secondary">
|
||||
Cancel
|
||||
</Button>
|
||||
<Button onClick={() => deleteList.mutate({ listPublicId })}>
|
||||
<Button
|
||||
isLoading={deleteList.isPending}
|
||||
onClick={() => deleteList.mutate({ listPublicId })}
|
||||
>
|
||||
Delete
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -1,20 +1,36 @@
|
||||
CREATE OR REPLACE FUNCTION reorder_lists(board_id BIGINT, list_id BIGINT, current_index INT, new_index INT)
|
||||
RETURNS VOID
|
||||
LANGUAGE SQL
|
||||
AS $$
|
||||
UPDATE list
|
||||
SET index =
|
||||
CASE
|
||||
WHEN index = current_index AND id = list_id THEN new_index
|
||||
WHEN current_index < new_index AND index > current_index AND index <= new_index THEN index - 1
|
||||
WHEN current_index > new_index AND index >= new_index AND index < current_index THEN index + 1
|
||||
ELSE index
|
||||
END
|
||||
WHERE "boardId" = board_id;
|
||||
RETURNS BOOLEAN
|
||||
LANGUAGE PLPGSQL
|
||||
AS $$
|
||||
BEGIN
|
||||
UPDATE list
|
||||
SET index =
|
||||
CASE
|
||||
WHEN index = current_index AND id = list_id THEN new_index
|
||||
WHEN current_index < new_index AND index > current_index AND index <= new_index THEN index - 1
|
||||
WHEN current_index > new_index AND index >= new_index AND index < current_index THEN index + 1
|
||||
ELSE index
|
||||
END
|
||||
WHERE "boardId" = board_id;
|
||||
|
||||
-- Check for duplicate indices after the update
|
||||
IF EXISTS (
|
||||
SELECT index, COUNT(*)
|
||||
FROM list
|
||||
WHERE "boardId" = board_id
|
||||
AND "deletedAt" IS NULL
|
||||
GROUP BY index
|
||||
HAVING COUNT(*) > 1
|
||||
) THEN
|
||||
RAISE EXCEPTION 'Duplicate indices found after reordering in board %', board_id;
|
||||
END IF;
|
||||
|
||||
RETURN TRUE;
|
||||
END;
|
||||
$$;
|
||||
|
||||
CREATE OR REPLACE FUNCTION reorder_cards(card_id BIGINT, current_list_id BIGINT, new_list_id BIGINT, current_index INT, new_index INT)
|
||||
RETURNS VOID
|
||||
RETURNS BOOLEAN
|
||||
LANGUAGE PLPGSQL
|
||||
AS $$
|
||||
DECLARE
|
||||
@@ -45,8 +61,22 @@ AS $$
|
||||
SET "listId" = new_list_id, index = new_index
|
||||
WHERE id = card_id AND "deletedAt" IS NULL;
|
||||
END IF;
|
||||
|
||||
-- Check for duplicate indices in both affected lists
|
||||
IF EXISTS (
|
||||
SELECT index, COUNT(*)
|
||||
FROM card
|
||||
WHERE "listId" IN (current_list_id, new_list_id)
|
||||
AND "deletedAt" IS NULL
|
||||
GROUP BY "listId", index
|
||||
HAVING COUNT(*) > 1
|
||||
) THEN
|
||||
RAISE EXCEPTION 'Duplicate indices found after reordering in list % or %', current_list_id, new_list_id;
|
||||
END IF;
|
||||
|
||||
RETURN TRUE;
|
||||
END;
|
||||
$$
|
||||
$$;
|
||||
|
||||
CREATE OR REPLACE FUNCTION shift_list_index(board_id BIGINT, list_index INT)
|
||||
RETURNS VOID
|
||||
|
||||
Reference in New Issue
Block a user