feat: delete lists
This commit is contained in:
@@ -29,7 +29,7 @@ export default async function Layout(props: { children: React.ReactNode }) {
|
|||||||
<div className="flex h-full w-full">
|
<div className="flex h-full w-full">
|
||||||
<nav className="flex w-72 flex-col justify-between border-r border-dark-600 px-5 py-5">
|
<nav className="flex w-72 flex-col justify-between border-r border-dark-600 px-5 py-5">
|
||||||
<div>
|
<div>
|
||||||
<ul role="list" className="-mx-2 my-6 space-y-1">
|
<ul role="list" className="-mx-2 my-3 space-y-1">
|
||||||
{navigation.map((item) => (
|
{navigation.map((item) => (
|
||||||
<li key={item.name}>
|
<li key={item.name}>
|
||||||
<ReactiveButton
|
<ReactiveButton
|
||||||
@@ -42,7 +42,6 @@ export default async function Layout(props: { children: React.ReactNode }) {
|
|||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button className="flex items-center">
|
<button className="flex items-center">
|
||||||
{session?.user.image ? (
|
{session?.user.image ? (
|
||||||
<Image
|
<Image
|
||||||
@@ -52,12 +51,23 @@ export default async function Layout(props: { children: React.ReactNode }) {
|
|||||||
height={30}
|
height={30}
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : (
|
||||||
<p className="ml-2 truncate text-sm text-dark-1000">
|
<span className="inline-block h-6 w-6 overflow-hidden rounded-full bg-dark-400">
|
||||||
|
<svg
|
||||||
|
className="h-full w-full text-dark-700"
|
||||||
|
fill="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path d="M24 20.993V24H0v-2.996A14.977 14.977 0 0112.004 15c4.904 0 9.26 2.354 11.996 5.993zM16.002 8.999a4 4 0 11-8 0 4 4 0 018 0z" />
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
<p className="ml-2 truncate text-sm text-dark-900">
|
||||||
{session?.user.email}
|
{session?.user.email}
|
||||||
</p>
|
</p>
|
||||||
</button>
|
</button>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div className="w-full overflow-hidden">{props.children}</div>
|
<div className="w-full overflow-hidden">{props.children}</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
58
src/app/boards/[...id]/DeleteListConfirmation.tsx
Normal file
58
src/app/boards/[...id]/DeleteListConfirmation.tsx
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { api } from "~/trpc/react";
|
||||||
|
import { useBoard } from "~/app/providers/board";
|
||||||
|
import { useModal } from "~/app/providers/modal";
|
||||||
|
|
||||||
|
interface DeleteListConfirmationProps {
|
||||||
|
listPublicId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function DeleteListConfirmation({
|
||||||
|
listPublicId,
|
||||||
|
}: DeleteListConfirmationProps) {
|
||||||
|
const utils = api.useUtils();
|
||||||
|
const { boardData } = useBoard();
|
||||||
|
const { closeModal } = useModal();
|
||||||
|
|
||||||
|
const refetchBoard = () =>
|
||||||
|
utils.board.byId.refetch({ id: boardData.publicId });
|
||||||
|
|
||||||
|
const deleteList = api.list.delete.useMutation({
|
||||||
|
onSuccess: async () => {
|
||||||
|
closeModal();
|
||||||
|
await refetchBoard();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="flex w-full flex-col justify-between pb-4">
|
||||||
|
<h2 className="text-md pb-4 font-medium text-dark-1000">
|
||||||
|
Are you sure you want to delete this list?
|
||||||
|
</h2>
|
||||||
|
<p className="text-sm font-medium text-dark-900">
|
||||||
|
{"This action can't be undone."}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="mt-5 flex justify-end sm:mt-6">
|
||||||
|
<button
|
||||||
|
className="mr-4 inline-flex justify-center rounded-md border-[1px] border-dark-600 bg-dark-300 px-3 py-2 text-sm font-semibold text-dark-1000 shadow-sm focus-visible:outline-none"
|
||||||
|
onClick={() => closeModal()}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
deleteList.mutate({
|
||||||
|
listPublicId,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
className="inline-flex justify-center rounded-md bg-dark-1000 px-3 py-2 text-sm font-semibold text-dark-50 shadow-sm focus-visible:outline-none"
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
54
src/app/boards/[...id]/ListDropdown.tsx
Normal file
54
src/app/boards/[...id]/ListDropdown.tsx
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import { Fragment } from "react";
|
||||||
|
import { Menu, Transition } from "@headlessui/react";
|
||||||
|
import { HiEllipsisHorizontal } from "react-icons/hi2";
|
||||||
|
import { useModal } from "~/app/providers/modal";
|
||||||
|
|
||||||
|
interface ListDropdownProps {
|
||||||
|
setSelectedPublicListId: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ListDropdown({
|
||||||
|
setSelectedPublicListId,
|
||||||
|
}: ListDropdownProps) {
|
||||||
|
const { openModal } = useModal();
|
||||||
|
|
||||||
|
const handleOpenDeleteListConfirmation = () => {
|
||||||
|
setSelectedPublicListId();
|
||||||
|
openModal("DELETE_LIST");
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Menu as="div" className="relative inline-block text-left">
|
||||||
|
<div>
|
||||||
|
<Menu.Button className="mr-1 inline-flex h-fit items-center rounded-md p-1 px-1 text-sm font-semibold text-dark-50 hover:bg-dark-400">
|
||||||
|
<HiEllipsisHorizontal className="h-5 w-5 text-dark-900" />
|
||||||
|
</Menu.Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Transition
|
||||||
|
as={Fragment}
|
||||||
|
enter="transition ease-out duration-100"
|
||||||
|
enterFrom="transform opacity-0 scale-95"
|
||||||
|
enterTo="transform opacity-100 scale-100"
|
||||||
|
leave="transition ease-in duration-75"
|
||||||
|
leaveFrom="transform opacity-100 scale-100"
|
||||||
|
leaveTo="transform opacity-0 scale-95"
|
||||||
|
>
|
||||||
|
<Menu.Items className="absolute right-0 z-10 mt-2 w-56 origin-top-right rounded-md border border-dark-400 bg-dark-300 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
|
||||||
|
<div className="flex">
|
||||||
|
<Menu.Item>
|
||||||
|
{() => (
|
||||||
|
<button
|
||||||
|
onClick={handleOpenDeleteListConfirmation}
|
||||||
|
className="m-1 w-full rounded-[5px] px-3 py-2 text-left text-sm text-dark-1000 hover:bg-dark-400"
|
||||||
|
>
|
||||||
|
Delete list
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</Menu.Item>
|
||||||
|
</div>
|
||||||
|
</Menu.Items>
|
||||||
|
</Transition>
|
||||||
|
</Menu>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -18,6 +18,8 @@ import { useModal } from "~/app/providers/modal";
|
|||||||
|
|
||||||
import Modal from "~/app/_components/modal";
|
import Modal from "~/app/_components/modal";
|
||||||
|
|
||||||
|
import { DeleteListConfirmation } from "./DeleteListConfirmation";
|
||||||
|
import ListDropdown from "./ListDropdown";
|
||||||
import { NewCardForm } from "./NewCardForm";
|
import { NewCardForm } from "./NewCardForm";
|
||||||
import { NewListForm } from "./NewListForm";
|
import { NewListForm } from "./NewListForm";
|
||||||
|
|
||||||
@@ -210,15 +212,22 @@ export default function BoardPage() {
|
|||||||
<p className="mb-4 px-4 pt-1 text-sm font-medium text-dark-1000">
|
<p className="mb-4 px-4 pt-1 text-sm font-medium text-dark-1000">
|
||||||
{list.name}
|
{list.name}
|
||||||
</p>
|
</p>
|
||||||
<button
|
<div>
|
||||||
className="mx-1 inline-flex h-fit items-center rounded-md p-1 px-1 text-sm font-semibold text-dark-50 hover:bg-dark-400"
|
<button
|
||||||
onClick={() => openNewCardForm(list.publicId)}
|
className="mx-1 inline-flex h-fit items-center rounded-md p-1 px-1 text-sm font-semibold text-dark-50 hover:bg-dark-400"
|
||||||
>
|
onClick={() => openNewCardForm(list.publicId)}
|
||||||
<HiOutlinePlusSmall
|
>
|
||||||
className="h-5 w-5 text-dark-900"
|
<HiOutlinePlusSmall
|
||||||
aria-hidden="true"
|
className="h-5 w-5 text-dark-900"
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
<ListDropdown
|
||||||
|
setSelectedPublicListId={() =>
|
||||||
|
setSelectedPublicListId(list.publicId)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</button>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Droppable droppableId={`${list.publicId}`} type="CARD">
|
<Droppable droppableId={`${list.publicId}`} type="CARD">
|
||||||
{(provided) => (
|
{(provided) => (
|
||||||
@@ -283,6 +292,9 @@ export default function BoardPage() {
|
|||||||
</DragDropContext>
|
</DragDropContext>
|
||||||
</div>
|
</div>
|
||||||
<Modal>
|
<Modal>
|
||||||
|
{modalContentType === "DELETE_LIST" && (
|
||||||
|
<DeleteListConfirmation listPublicId={selectedPublicListId} />
|
||||||
|
)}
|
||||||
{modalContentType === "NEW_CARD" && (
|
{modalContentType === "NEW_CARD" && (
|
||||||
<NewCardForm listPublicId={selectedPublicListId} />
|
<NewCardForm listPublicId={selectedPublicListId} />
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export default function RootLayout({
|
|||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<html lang="en" className={`${jakarta.variable}`}>
|
<html lang="en" className={`${jakarta.variable}`}>
|
||||||
<body>
|
<body className="h-screen overflow-hidden">
|
||||||
<TRPCReactProvider headers={headers()}>
|
<TRPCReactProvider headers={headers()}>
|
||||||
<ModalProvider>
|
<ModalProvider>
|
||||||
<BoardProvider>{children}</BoardProvider>
|
<BoardProvider>{children}</BoardProvider>
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ export const boardRouter = createTRPCRouter({
|
|||||||
with: {
|
with: {
|
||||||
lists: {
|
lists: {
|
||||||
orderBy: [asc(lists.index)],
|
orderBy: [asc(lists.index)],
|
||||||
|
where: isNull(cards.deletedAt),
|
||||||
columns: {
|
columns: {
|
||||||
publicId: true,
|
publicId: true,
|
||||||
name: true,
|
name: true,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { desc, eq, sql } from "drizzle-orm";
|
import { desc, eq, sql } from "drizzle-orm";
|
||||||
|
|
||||||
import { boards, lists } from "~/server/db/schema";
|
import { boards, cards, lists } from "~/server/db/schema";
|
||||||
import { generateUID } from "~/utils/generateUID";
|
import { generateUID } from "~/utils/generateUID";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -79,5 +79,29 @@ export const listRouter = createTRPCRouter({
|
|||||||
WHERE ${lists.boardId} = ${list.boardId};
|
WHERE ${lists.boardId} = ${list.boardId};
|
||||||
`);
|
`);
|
||||||
})
|
})
|
||||||
})
|
}),
|
||||||
|
delete: publicProcedure
|
||||||
|
.input(
|
||||||
|
z.object({
|
||||||
|
listPublicId: z.string().min(12),
|
||||||
|
}))
|
||||||
|
.mutation(({ ctx, input }) => {
|
||||||
|
const userId = ctx.session?.user.id;
|
||||||
|
|
||||||
|
if (!userId) return;
|
||||||
|
|
||||||
|
return ctx.db.transaction(async (tx) => {
|
||||||
|
const list = await tx.query.lists.findFirst({
|
||||||
|
where: eq(lists.publicId, input.listPublicId),
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!list) return;
|
||||||
|
|
||||||
|
await tx.update(lists).set({ deletedAt: new Date(), deletedBy: userId}).where(eq(lists.id, list.id));
|
||||||
|
|
||||||
|
await tx.update(cards).set({ deletedAt: new Date(), deletedBy: userId}).where(eq(cards.listId, list.id));
|
||||||
|
|
||||||
|
await tx.execute(sql`UPDATE ${lists} SET ${lists.index} = ${lists.index} - 1 WHERE ${lists.boardId} = ${list.boardId} AND ${lists.index} > ${list.index} AND ${lists.deletedAt} IS NULL;`);
|
||||||
|
})
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
2
src/server/db/migrations/0005_hard_colossus.sql
Normal file
2
src/server/db/migrations/0005_hard_colossus.sql
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE `list` ADD `deletedAt` timestamp;--> statement-breakpoint
|
||||||
|
ALTER TABLE `list` ADD `deletedBy` varchar(256);
|
||||||
661
src/server/db/migrations/meta/0005_snapshot.json
Normal file
661
src/server/db/migrations/meta/0005_snapshot.json
Normal file
@@ -0,0 +1,661 @@
|
|||||||
|
{
|
||||||
|
"version": "5",
|
||||||
|
"dialect": "mysql",
|
||||||
|
"id": "263f81b0-eac9-47a0-9d24-ed61d6dd6061",
|
||||||
|
"prevId": "52bf8e38-66ad-4bb6-9924-798177dbd1b5",
|
||||||
|
"tables": {
|
||||||
|
"account": {
|
||||||
|
"name": "account",
|
||||||
|
"columns": {
|
||||||
|
"userId": {
|
||||||
|
"name": "userId",
|
||||||
|
"type": "varchar(255)",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"name": "type",
|
||||||
|
"type": "varchar(255)",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"provider": {
|
||||||
|
"name": "provider",
|
||||||
|
"type": "varchar(255)",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"providerAccountId": {
|
||||||
|
"name": "providerAccountId",
|
||||||
|
"type": "varchar(255)",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"refresh_token": {
|
||||||
|
"name": "refresh_token",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"access_token": {
|
||||||
|
"name": "access_token",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"expires_at": {
|
||||||
|
"name": "expires_at",
|
||||||
|
"type": "int",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"token_type": {
|
||||||
|
"name": "token_type",
|
||||||
|
"type": "varchar(255)",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"scope": {
|
||||||
|
"name": "scope",
|
||||||
|
"type": "varchar(255)",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"id_token": {
|
||||||
|
"name": "id_token",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"session_state": {
|
||||||
|
"name": "session_state",
|
||||||
|
"type": "varchar(255)",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {
|
||||||
|
"userId_idx": {
|
||||||
|
"name": "userId_idx",
|
||||||
|
"columns": [
|
||||||
|
"userId"
|
||||||
|
],
|
||||||
|
"isUnique": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"foreignKeys": {},
|
||||||
|
"compositePrimaryKeys": {
|
||||||
|
"account_provider_providerAccountId": {
|
||||||
|
"name": "account_provider_providerAccountId",
|
||||||
|
"columns": [
|
||||||
|
"provider",
|
||||||
|
"providerAccountId"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uniqueConstraints": {}
|
||||||
|
},
|
||||||
|
"board": {
|
||||||
|
"name": "board",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "bigint",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": true
|
||||||
|
},
|
||||||
|
"publicId": {
|
||||||
|
"name": "publicId",
|
||||||
|
"type": "varchar(12)",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"name": "name",
|
||||||
|
"type": "varchar(255)",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"createdBy": {
|
||||||
|
"name": "createdBy",
|
||||||
|
"type": "varchar(255)",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"createdAt": {
|
||||||
|
"name": "createdAt",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "CURRENT_TIMESTAMP"
|
||||||
|
},
|
||||||
|
"updatedAt": {
|
||||||
|
"name": "updatedAt",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"onUpdate": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {},
|
||||||
|
"compositePrimaryKeys": {
|
||||||
|
"board_id": {
|
||||||
|
"name": "board_id",
|
||||||
|
"columns": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uniqueConstraints": {
|
||||||
|
"board_publicId_unique": {
|
||||||
|
"name": "board_publicId_unique",
|
||||||
|
"columns": [
|
||||||
|
"publicId"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"card": {
|
||||||
|
"name": "card",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "bigint",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": true
|
||||||
|
},
|
||||||
|
"publicId": {
|
||||||
|
"name": "publicId",
|
||||||
|
"type": "varchar(12)",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"name": "title",
|
||||||
|
"type": "varchar(256)",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"name": "description",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"createdBy": {
|
||||||
|
"name": "createdBy",
|
||||||
|
"type": "varchar(256)",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"createdAt": {
|
||||||
|
"name": "createdAt",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "CURRENT_TIMESTAMP"
|
||||||
|
},
|
||||||
|
"updatedAt": {
|
||||||
|
"name": "updatedAt",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"onUpdate": true
|
||||||
|
},
|
||||||
|
"listId": {
|
||||||
|
"name": "listId",
|
||||||
|
"type": "bigint",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"index": {
|
||||||
|
"name": "index",
|
||||||
|
"type": "int",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"deletedAt": {
|
||||||
|
"name": "deletedAt",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"deletedBy": {
|
||||||
|
"name": "deletedBy",
|
||||||
|
"type": "varchar(256)",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {},
|
||||||
|
"compositePrimaryKeys": {
|
||||||
|
"card_id": {
|
||||||
|
"name": "card_id",
|
||||||
|
"columns": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uniqueConstraints": {
|
||||||
|
"card_publicId_unique": {
|
||||||
|
"name": "card_publicId_unique",
|
||||||
|
"columns": [
|
||||||
|
"publicId"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"card_label": {
|
||||||
|
"name": "card_label",
|
||||||
|
"columns": {
|
||||||
|
"cardId": {
|
||||||
|
"name": "cardId",
|
||||||
|
"type": "bigint",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"labelId": {
|
||||||
|
"name": "labelId",
|
||||||
|
"type": "bigint",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"card_label_cardId_card_id_fk": {
|
||||||
|
"name": "card_label_cardId_card_id_fk",
|
||||||
|
"tableFrom": "card_label",
|
||||||
|
"tableTo": "card",
|
||||||
|
"columnsFrom": [
|
||||||
|
"cardId"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "no action",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
},
|
||||||
|
"card_label_labelId_label_id_fk": {
|
||||||
|
"name": "card_label_labelId_label_id_fk",
|
||||||
|
"tableFrom": "card_label",
|
||||||
|
"tableTo": "label",
|
||||||
|
"columnsFrom": [
|
||||||
|
"labelId"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "no action",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {
|
||||||
|
"card_label_cardId_labelId": {
|
||||||
|
"name": "card_label_cardId_labelId",
|
||||||
|
"columns": [
|
||||||
|
"cardId",
|
||||||
|
"labelId"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uniqueConstraints": {}
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"name": "label",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "bigint",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": true
|
||||||
|
},
|
||||||
|
"publicId": {
|
||||||
|
"name": "publicId",
|
||||||
|
"type": "varchar(12)",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"name": "name",
|
||||||
|
"type": "varchar(256)",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"colourCode": {
|
||||||
|
"name": "colourCode",
|
||||||
|
"type": "varchar(12)",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"createdBy": {
|
||||||
|
"name": "createdBy",
|
||||||
|
"type": "varchar(256)",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"createdAt": {
|
||||||
|
"name": "createdAt",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "CURRENT_TIMESTAMP"
|
||||||
|
},
|
||||||
|
"updatedAt": {
|
||||||
|
"name": "updatedAt",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"onUpdate": true
|
||||||
|
},
|
||||||
|
"boardId": {
|
||||||
|
"name": "boardId",
|
||||||
|
"type": "bigint",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {},
|
||||||
|
"compositePrimaryKeys": {
|
||||||
|
"label_id": {
|
||||||
|
"name": "label_id",
|
||||||
|
"columns": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uniqueConstraints": {
|
||||||
|
"label_publicId_unique": {
|
||||||
|
"name": "label_publicId_unique",
|
||||||
|
"columns": [
|
||||||
|
"publicId"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"list": {
|
||||||
|
"name": "list",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "bigint",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": true
|
||||||
|
},
|
||||||
|
"publicId": {
|
||||||
|
"name": "publicId",
|
||||||
|
"type": "varchar(12)",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"name": "name",
|
||||||
|
"type": "varchar(256)",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"createdBy": {
|
||||||
|
"name": "createdBy",
|
||||||
|
"type": "varchar(256)",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"createdAt": {
|
||||||
|
"name": "createdAt",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "CURRENT_TIMESTAMP"
|
||||||
|
},
|
||||||
|
"updatedAt": {
|
||||||
|
"name": "updatedAt",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"onUpdate": true
|
||||||
|
},
|
||||||
|
"boardId": {
|
||||||
|
"name": "boardId",
|
||||||
|
"type": "bigint",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"index": {
|
||||||
|
"name": "index",
|
||||||
|
"type": "int",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"deletedAt": {
|
||||||
|
"name": "deletedAt",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"deletedBy": {
|
||||||
|
"name": "deletedBy",
|
||||||
|
"type": "varchar(256)",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {},
|
||||||
|
"compositePrimaryKeys": {
|
||||||
|
"list_id": {
|
||||||
|
"name": "list_id",
|
||||||
|
"columns": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uniqueConstraints": {
|
||||||
|
"list_publicId_unique": {
|
||||||
|
"name": "list_publicId_unique",
|
||||||
|
"columns": [
|
||||||
|
"publicId"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"session": {
|
||||||
|
"name": "session",
|
||||||
|
"columns": {
|
||||||
|
"sessionToken": {
|
||||||
|
"name": "sessionToken",
|
||||||
|
"type": "varchar(255)",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"userId": {
|
||||||
|
"name": "userId",
|
||||||
|
"type": "varchar(255)",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"expires": {
|
||||||
|
"name": "expires",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {
|
||||||
|
"userId_idx": {
|
||||||
|
"name": "userId_idx",
|
||||||
|
"columns": [
|
||||||
|
"userId"
|
||||||
|
],
|
||||||
|
"isUnique": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"foreignKeys": {},
|
||||||
|
"compositePrimaryKeys": {
|
||||||
|
"session_sessionToken": {
|
||||||
|
"name": "session_sessionToken",
|
||||||
|
"columns": [
|
||||||
|
"sessionToken"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uniqueConstraints": {}
|
||||||
|
},
|
||||||
|
"user": {
|
||||||
|
"name": "user",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "varchar(255)",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"name": "name",
|
||||||
|
"type": "varchar(255)",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"name": "email",
|
||||||
|
"type": "varchar(255)",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"emailVerified": {
|
||||||
|
"name": "emailVerified",
|
||||||
|
"type": "timestamp(3)",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "CURRENT_TIMESTAMP(3)"
|
||||||
|
},
|
||||||
|
"image": {
|
||||||
|
"name": "image",
|
||||||
|
"type": "varchar(255)",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {},
|
||||||
|
"compositePrimaryKeys": {
|
||||||
|
"user_id": {
|
||||||
|
"name": "user_id",
|
||||||
|
"columns": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uniqueConstraints": {
|
||||||
|
"user_email_unique": {
|
||||||
|
"name": "user_email_unique",
|
||||||
|
"columns": [
|
||||||
|
"email"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"verificationToken": {
|
||||||
|
"name": "verificationToken",
|
||||||
|
"columns": {
|
||||||
|
"identifier": {
|
||||||
|
"name": "identifier",
|
||||||
|
"type": "varchar(255)",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"token": {
|
||||||
|
"name": "token",
|
||||||
|
"type": "varchar(255)",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"expires": {
|
||||||
|
"name": "expires",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {},
|
||||||
|
"compositePrimaryKeys": {
|
||||||
|
"verificationToken_identifier_token": {
|
||||||
|
"name": "verificationToken_identifier_token",
|
||||||
|
"columns": [
|
||||||
|
"identifier",
|
||||||
|
"token"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uniqueConstraints": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"schemas": {},
|
||||||
|
"_meta": {
|
||||||
|
"schemas": {},
|
||||||
|
"tables": {},
|
||||||
|
"columns": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -36,6 +36,13 @@
|
|||||||
"when": 1702924641678,
|
"when": 1702924641678,
|
||||||
"tag": "0004_tidy_lord_hawal",
|
"tag": "0004_tidy_lord_hawal",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 5,
|
||||||
|
"version": "5",
|
||||||
|
"when": 1704193352729,
|
||||||
|
"tag": "0005_hard_colossus",
|
||||||
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -103,7 +103,9 @@ export const lists = mySqlTable(
|
|||||||
.notNull(),
|
.notNull(),
|
||||||
updatedAt: timestamp("updatedAt").onUpdateNow(),
|
updatedAt: timestamp("updatedAt").onUpdateNow(),
|
||||||
boardId: bigint("boardId", { mode: "number" }).notNull(),
|
boardId: bigint("boardId", { mode: "number" }).notNull(),
|
||||||
index: int("index").notNull()
|
index: int("index").notNull(),
|
||||||
|
deletedAt: timestamp("deletedAt"),
|
||||||
|
deletedBy: varchar("deletedBy", { length: 256 })
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -116,7 +118,11 @@ export const listsRelations = relations(lists, ({ one, many }) => ({
|
|||||||
fields: [lists.boardId],
|
fields: [lists.boardId],
|
||||||
references: [boards.id],
|
references: [boards.id],
|
||||||
}),
|
}),
|
||||||
cards: many(cards)
|
cards: many(cards),
|
||||||
|
deletedBy: one(users, {
|
||||||
|
fields: [lists.deletedBy],
|
||||||
|
references: [users.id],
|
||||||
|
}),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const cards = mySqlTable(
|
export const cards = mySqlTable(
|
||||||
@@ -151,7 +157,6 @@ export const cardsRelations = relations(cards, ({ one, many }) => ({
|
|||||||
fields: [cards.deletedBy],
|
fields: [cards.deletedBy],
|
||||||
references: [users.id],
|
references: [users.id],
|
||||||
}),
|
}),
|
||||||
|
|
||||||
labels: many(cardsToLabels)
|
labels: many(cardsToLabels)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user