From b3d5410f374456554e365094095c5ed35eccccc2 Mon Sep 17 00:00:00 2001 From: Doug Pilcher Date: Wed, 3 Sep 2025 14:39:09 -0500 Subject: [PATCH] add image folder --- .../migration.sql | 16 ++++ schema.graphql | 82 +++++++++++++++++++ schema.prisma | 18 +++- schema.ts | 26 ++++++ 4 files changed, 138 insertions(+), 4 deletions(-) create mode 100644 migrations/20250903193625_add_image_folder/migration.sql diff --git a/migrations/20250903193625_add_image_folder/migration.sql b/migrations/20250903193625_add_image_folder/migration.sql new file mode 100644 index 0000000..495b198 --- /dev/null +++ b/migrations/20250903193625_add_image_folder/migration.sql @@ -0,0 +1,16 @@ +-- AlterTable +ALTER TABLE "Image" ADD COLUMN "folder" TEXT; + +-- CreateTable +CREATE TABLE "ImageFolder" ( + "id" TEXT NOT NULL, + "name" TEXT NOT NULL DEFAULT '', + + CONSTRAINT "ImageFolder_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE INDEX "Image_folder_idx" ON "Image"("folder"); + +-- AddForeignKey +ALTER TABLE "Image" ADD CONSTRAINT "Image_folder_fkey" FOREIGN KEY ("folder") REFERENCES "ImageFolder"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/schema.graphql b/schema.graphql index 255069f..68a73aa 100644 --- a/schema.graphql +++ b/schema.graphql @@ -523,6 +523,7 @@ type Image { name: String altText: String image: ImageFieldOutput + folder: ImageFolder } type ImageFieldOutput { @@ -552,6 +553,7 @@ input ImageWhereInput { id: IDFilter name: StringFilter altText: StringFilter + folder: ImageFolderWhereInput } input ImageOrderByInput { @@ -564,12 +566,19 @@ input ImageUpdateInput { name: String altText: String image: ImageFieldInput + folder: ImageFolderRelateToOneForUpdateInput } input ImageFieldInput { upload: Upload! } +input ImageFolderRelateToOneForUpdateInput { + create: ImageFolderCreateInput + connect: ImageFolderWhereUniqueInput + disconnect: Boolean +} + input ImageUpdateArgs { where: ImageWhereUniqueInput! data: ImageUpdateInput! @@ -579,6 +588,70 @@ input ImageCreateInput { name: String altText: String image: ImageFieldInput + folder: ImageFolderRelateToOneForCreateInput +} + +input ImageFolderRelateToOneForCreateInput { + create: ImageFolderCreateInput + connect: ImageFolderWhereUniqueInput +} + +type ImageFolder { + id: ID! + name: String + images(where: ImageWhereInput! = {}, orderBy: [ImageOrderByInput!]! = [], take: Int, skip: Int! = 0, cursor: ImageWhereUniqueInput): [Image!] + imagesCount(where: ImageWhereInput! = {}): Int +} + +input ImageFolderWhereUniqueInput { + id: ID +} + +input ImageFolderWhereInput { + AND: [ImageFolderWhereInput!] + OR: [ImageFolderWhereInput!] + NOT: [ImageFolderWhereInput!] + id: IDFilter + name: StringFilter + images: ImageManyRelationFilter +} + +input ImageManyRelationFilter { + every: ImageWhereInput + some: ImageWhereInput + none: ImageWhereInput +} + +input ImageFolderOrderByInput { + id: OrderDirection + name: OrderDirection +} + +input ImageFolderUpdateInput { + name: String + images: ImageRelateToManyForUpdateInput +} + +input ImageRelateToManyForUpdateInput { + disconnect: [ImageWhereUniqueInput!] + set: [ImageWhereUniqueInput!] + create: [ImageCreateInput!] + connect: [ImageWhereUniqueInput!] +} + +input ImageFolderUpdateArgs { + where: ImageFolderWhereUniqueInput! + data: ImageFolderUpdateInput! +} + +input ImageFolderCreateInput { + name: String + images: ImageRelateToManyForCreateInput +} + +input ImageRelateToManyForCreateInput { + create: [ImageCreateInput!] + connect: [ImageWhereUniqueInput!] } """ @@ -617,6 +690,12 @@ type Mutation { updateImages(data: [ImageUpdateArgs!]!): [Image] deleteImage(where: ImageWhereUniqueInput!): Image deleteImages(where: [ImageWhereUniqueInput!]!): [Image] + createImageFolder(data: ImageFolderCreateInput!): ImageFolder + createImageFolders(data: [ImageFolderCreateInput!]!): [ImageFolder] + updateImageFolder(where: ImageFolderWhereUniqueInput!, data: ImageFolderUpdateInput!): ImageFolder + updateImageFolders(data: [ImageFolderUpdateArgs!]!): [ImageFolder] + deleteImageFolder(where: ImageFolderWhereUniqueInput!): ImageFolder + deleteImageFolders(where: [ImageFolderWhereUniqueInput!]!): [ImageFolder] endSession: Boolean! authenticateUserWithPassword(email: String!, password: String!): UserAuthenticationWithPasswordResult createInitialUser(data: CreateInitialUserInput!): UserAuthenticationWithPasswordSuccess! @@ -655,6 +734,9 @@ type Query { image(where: ImageWhereUniqueInput!): Image images(where: ImageWhereInput! = {}, orderBy: [ImageOrderByInput!]! = [], take: Int, skip: Int! = 0, cursor: ImageWhereUniqueInput): [Image!] imagesCount(where: ImageWhereInput! = {}): Int + imageFolder(where: ImageFolderWhereUniqueInput!): ImageFolder + imageFolders(where: ImageFolderWhereInput! = {}, orderBy: [ImageFolderOrderByInput!]! = [], take: Int, skip: Int! = 0, cursor: ImageFolderWhereUniqueInput): [ImageFolder!] + imageFoldersCount(where: ImageFolderWhereInput! = {}): Int keystone: KeystoneMeta! authenticatedItem: AuthenticatedItem getPopularPosts(take: Int = 8): [Post!] diff --git a/schema.prisma b/schema.prisma index b2b59d1..7c7e913 100644 --- a/schema.prisma +++ b/schema.prisma @@ -69,13 +69,23 @@ model Tag { } model Image { - id String @id @default(cuid()) - name String @default("") - altText String @default("") + id String @id @default(cuid()) + name String @default("") + altText String @default("") image_id String? image_filesize Int? image_width Int? image_height Int? image_extension String? - from_Post_headerImage Post[] @relation("Post_headerImage") + folder ImageFolder? @relation("Image_folder", fields: [folderId], references: [id]) + folderId String? @map("folder") + from_Post_headerImage Post[] @relation("Post_headerImage") + + @@index([folderId]) +} + +model ImageFolder { + id String @id @default(cuid()) + name String @default("") + images Image[] @relation("Image_folder") } diff --git a/schema.ts b/schema.ts index 4bef6f7..173a34e 100644 --- a/schema.ts +++ b/schema.ts @@ -625,6 +625,7 @@ export const lists: Lists = { }), Image: list({ access: allowAll, + description: "Images to use as post headers or within the post content", fields: { name: text({ validation: { @@ -633,6 +634,31 @@ export const lists: Lists = { }), altText: text(), image: image({ storage: "localImages" }), + folder: relationship({ + ref: "ImageFolder.images", + many: false, + ui: { + displayMode: "cards", + cardFields: ["name"], + inlineEdit: { fields: ["name"] }, + linkToItem: true, + inlineConnect: true, + inlineCreate: { fields: ["name"] }, + }, + }), + }, + ui: { + listView: { + initialColumns: ["image", "name", "folder"], + }, + }, + }), + ImageFolder: list({ + access: allowAll, + description: "Categorical folders to organiza images", + fields: { + name: text({ validation: { isRequired: true } }), + images: relationship({ ref: "Image.folder", many: true }), }, }), };