feat: add folders (#1711)

This commit is contained in:
Catalin Pit
2025-05-01 19:46:59 +03:00
committed by GitHub
parent 12ada567f5
commit 17370749b4
91 changed files with 10497 additions and 183 deletions

View File

@ -0,0 +1,39 @@
-- AlterTable
ALTER TABLE "Document" ADD COLUMN "folderId" INTEGER;
-- CreateTable
CREATE TABLE "Folder" (
"id" SERIAL NOT NULL,
"name" TEXT NOT NULL,
"userId" INTEGER NOT NULL,
"teamId" INTEGER,
"parentId" INTEGER,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "Folder_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE INDEX "Folder_userId_idx" ON "Folder"("userId");
-- CreateIndex
CREATE INDEX "Folder_teamId_idx" ON "Folder"("teamId");
-- CreateIndex
CREATE INDEX "Folder_parentId_idx" ON "Folder"("parentId");
-- CreateIndex
CREATE INDEX "Document_folderId_idx" ON "Document"("folderId");
-- AddForeignKey
ALTER TABLE "Folder" ADD CONSTRAINT "Folder_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Folder" ADD CONSTRAINT "Folder_teamId_fkey" FOREIGN KEY ("teamId") REFERENCES "Team"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Folder" ADD CONSTRAINT "Folder_parentId_fkey" FOREIGN KEY ("parentId") REFERENCES "Folder"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Document" ADD CONSTRAINT "Document_folderId_fkey" FOREIGN KEY ("folderId") REFERENCES "Folder"("id") ON DELETE SET NULL ON UPDATE CASCADE;

View File

@ -0,0 +1,29 @@
/*
Warnings:
- The primary key for the `Folder` table will be changed. If it partially fails, the table could be left without primary key constraint.
*/
-- DropForeignKey
ALTER TABLE "Document" DROP CONSTRAINT "Document_folderId_fkey";
-- DropForeignKey
ALTER TABLE "Folder" DROP CONSTRAINT "Folder_parentId_fkey";
-- AlterTable
ALTER TABLE "Document" ALTER COLUMN "folderId" SET DATA TYPE TEXT;
-- AlterTable
ALTER TABLE "Folder" DROP CONSTRAINT "Folder_pkey",
ADD COLUMN "pinned" BOOLEAN NOT NULL DEFAULT false,
ALTER COLUMN "id" DROP DEFAULT,
ALTER COLUMN "id" SET DATA TYPE TEXT,
ALTER COLUMN "parentId" SET DATA TYPE TEXT,
ADD CONSTRAINT "Folder_pkey" PRIMARY KEY ("id");
DROP SEQUENCE "Folder_id_seq";
-- AddForeignKey
ALTER TABLE "Folder" ADD CONSTRAINT "Folder_parentId_fkey" FOREIGN KEY ("parentId") REFERENCES "Folder"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Document" ADD CONSTRAINT "Document_folderId_fkey" FOREIGN KEY ("folderId") REFERENCES "Folder"("id") ON DELETE SET NULL ON UPDATE CASCADE;

View File

@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "Folder" ADD COLUMN "visibility" "DocumentVisibility" NOT NULL DEFAULT 'EVERYONE';

View File

@ -0,0 +1,20 @@
/*
Warnings:
- Added the required column `type` to the `Folder` table without a default value. This is not possible if the table is not empty.
*/
-- CreateEnum
CREATE TYPE "FolderType" AS ENUM ('DOCUMENT', 'TEMPLATE');
-- AlterTable
ALTER TABLE "Folder" ADD COLUMN "type" "FolderType" NOT NULL;
-- AlterTable
ALTER TABLE "Template" ADD COLUMN "folderId" TEXT;
-- CreateIndex
CREATE INDEX "Folder_type_idx" ON "Folder"("type");
-- AddForeignKey
ALTER TABLE "Template" ADD CONSTRAINT "Template_folderId_fkey" FOREIGN KEY ("folderId") REFERENCES "Folder"("id") ON DELETE SET NULL ON UPDATE CASCADE;

View File

@ -0,0 +1,11 @@
-- DropForeignKey
ALTER TABLE "Document" DROP CONSTRAINT "Document_folderId_fkey";
-- DropForeignKey
ALTER TABLE "Template" DROP CONSTRAINT "Template_folderId_fkey";
-- AddForeignKey
ALTER TABLE "Document" ADD CONSTRAINT "Document_folderId_fkey" FOREIGN KEY ("folderId") REFERENCES "Folder"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Template" ADD CONSTRAINT "Template_folderId_fkey" FOREIGN KEY ("folderId") REFERENCES "Folder"("id") ON DELETE CASCADE ON UPDATE CASCADE;

View File

@ -56,6 +56,7 @@ model User {
accounts Account[]
sessions Session[]
documents Document[]
folders Folder[]
subscriptions Subscription[]
passwordResetTokens PasswordResetToken[]
ownedTeams Team[]
@ -312,6 +313,35 @@ enum DocumentVisibility {
ADMIN
}
enum FolderType {
DOCUMENT
TEMPLATE
}
model Folder {
id String @id @default(cuid())
name String
userId Int
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
teamId Int?
team Team? @relation(fields: [teamId], references: [id], onDelete: Cascade)
pinned Boolean @default(false)
parentId String?
parent Folder? @relation("FolderToFolder", fields: [parentId], references: [id], onDelete: Cascade)
documents Document[]
templates Template[]
createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt
subfolders Folder[] @relation("FolderToFolder")
visibility DocumentVisibility @default(EVERYONE)
type FolderType
@@index([userId])
@@index([teamId])
@@index([parentId])
@@index([type])
}
/// @zod.import(["import { ZDocumentAuthOptionsSchema } from '@documenso/lib/types/document-auth';", "import { ZDocumentFormValuesSchema } from '@documenso/lib/types/document-form-values';"])
model Document {
id Int @id @default(autoincrement())
@ -344,10 +374,13 @@ model Document {
template Template? @relation(fields: [templateId], references: [id], onDelete: SetNull)
auditLogs DocumentAuditLog[]
folder Folder? @relation(fields: [folderId], references: [id], onDelete: Cascade)
folderId String?
@@unique([documentDataId])
@@index([userId])
@@index([status])
@@index([folderId])
}
model DocumentAuditLog {
@ -593,6 +626,7 @@ model Team {
documents Document[]
templates Template[]
folders Folder[]
apiTokens ApiToken[]
webhooks Webhook[]
}
@ -721,6 +755,8 @@ model Template {
fields Field[]
directLink TemplateDirectLink?
documents Document[]
folder Folder? @relation(fields: [folderId], references: [id], onDelete: Cascade)
folderId String?
@@unique([templateDocumentDataId])
}

View File

@ -0,0 +1,33 @@
import type { User } from '@prisma/client';
import { DocumentStatus, FolderType } from '@prisma/client';
import { prisma } from '..';
import type { Prisma } from '../client';
import { seedDocuments } from './documents';
type CreateFolderOptions = {
type?: string;
createFolderOptions?: Partial<Prisma.FolderUncheckedCreateInput>;
};
export const seedBlankFolder = async (user: User, options: CreateFolderOptions = {}) => {
return await prisma.folder.create({
data: {
name: 'My folder',
userId: user.id,
type: FolderType.DOCUMENT,
...options.createFolderOptions,
},
});
};
export const seedFolderWithDocuments = async (user: User, options: CreateFolderOptions = {}) => {
const folder = await seedBlankFolder(user, options);
await seedDocuments([
{
sender: user,
recipients: [user],
type: DocumentStatus.DRAFT,
},
]);
};