From 77fe114489e8b9447172dae0486c1dacf616a2b7 Mon Sep 17 00:00:00 2001 From: ziteh Date: Thu, 3 Oct 2024 08:27:31 +0800 Subject: [PATCH 1/6] chore: update git hook, add Prettify hook --- .pre-commit-config.yaml | 7 ++++++ .vscode/settings.json | 15 ------------- hie.code-workspace | 47 +++++++++++++++++++++++++++++++++++++++++ prettify-pre-commit.sh | 11 ++++++++++ 4 files changed, 65 insertions(+), 15 deletions(-) delete mode 100644 .vscode/settings.json create mode 100644 hie.code-workspace create mode 100644 prettify-pre-commit.sh diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2319abb..4728d8b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -18,3 +18,10 @@ repos: rev: v0.19.1 hooks: - id: gitlint + - repo: local + hooks: + - id: prettify + name: prettify + entry: bash ./prettify-pre-commit.sh + language: system + files: \.(js|ts|jsx|tsx|css|html)$ diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 8c23962..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "editor.tabSize": 2, - "editor.insertSpaces": true, - "workbench.editor.customLabels.patterns": { - "{**/index.*,**/route.*,**/layout.*,**/page.*}": "${dirname}.${extname} (${filename})" - }, - "cSpell.words": [ - "hie", - "nextjs", - "openapi", - "tailwindcss", - "Topbar", - "zustand" - ] -} diff --git a/hie.code-workspace b/hie.code-workspace new file mode 100644 index 0000000..995e287 --- /dev/null +++ b/hie.code-workspace @@ -0,0 +1,47 @@ +{ + "folders": [ + { + "name": "Page: Database", + "path": "app/database" + }, + { + "name": "Page: Explorer", + "path": "app/explorer" + }, + { + "name": "Components", + "path": "app/components" + }, + { + "name": "Lib", + "path": "app/lib" + }, + { + "name": "API: Server", + "path": "app/api" + }, + { + "name": "API: OpenAPI", + "path": "public/openapi" + }, + { + "name": "Root", + "path": "." + } + ], + "settings": { + "editor.tabSize": 2, + "editor.insertSpaces": true, + "workbench.editor.customLabels.patterns": { + "{**/index.*,**/route.*,**/layout.*,**/page.*}": "${dirname}.${extname} (${filename})" + }, + "cSpell.words": [ + "hie", + "nextjs", + "openapi", + "tailwindcss", + "Topbar", + "zustand" + ] + } +} diff --git a/prettify-pre-commit.sh b/prettify-pre-commit.sh new file mode 100644 index 0000000..396c029 --- /dev/null +++ b/prettify-pre-commit.sh @@ -0,0 +1,11 @@ +#!/bin/bash +FILES=$(git diff --cached --name-only --diff-filter=ACMR | sed 's| |\\ |g') +[ -z "$FILES" ] && exit 0 + +# Prettify all selected files +echo "$FILES" | xargs ./node_modules/.bin/prettier --ignore-unknown --write + +# Add back the modified/prettified files to staging +echo "$FILES" | xargs git add + +exit 0 From d88bb7e034564a41c497e4a2f6a48529e88f9a01 Mon Sep 17 00:00:00 2001 From: ziteh Date: Thu, 3 Oct 2024 13:06:48 +0800 Subject: [PATCH 2/6] fix: correct the format and functions of the API --- app/api/items/[id]/route.ts | 10 ++- app/api/items/relation/[id]/route.ts | 68 +++++++++++++++++ app/api/items/relation/route.ts | 64 +++++----------- app/api/tags/relation/[id]/route.ts | 75 +++++++++++++++++++ app/api/tags/relation/route.ts | 67 +++++------------ prisma/schema.prisma | 2 +- public/openapi/document.yaml | 10 ++- public/openapi/items/id.yaml | 33 ++++++-- public/openapi/items/relation/id.yaml | 39 ++++++++++ .../{relation.yaml => relation/index.yaml} | 37 +-------- public/openapi/tags/id.yaml | 37 +++++++-- public/openapi/tags/relation/id.yaml | 40 ++++++++++ .../{relation.yaml => relation/index.yaml} | 37 +-------- 13 files changed, 331 insertions(+), 188 deletions(-) create mode 100644 app/api/items/relation/[id]/route.ts create mode 100644 app/api/tags/relation/[id]/route.ts create mode 100644 public/openapi/items/relation/id.yaml rename public/openapi/items/{relation.yaml => relation/index.yaml} (52%) create mode 100644 public/openapi/tags/relation/id.yaml rename public/openapi/tags/{relation.yaml => relation/index.yaml} (52%) diff --git a/app/api/items/[id]/route.ts b/app/api/items/[id]/route.ts index 18831e6..6ab36f5 100644 --- a/app/api/items/[id]/route.ts +++ b/app/api/items/[id]/route.ts @@ -39,11 +39,15 @@ export async function DELETE( { params }: { params: { id: string } } ) { try { + await prisma.itemRelation.deleteMany({ + where: { itemId: Number(params.id) }, + }); + const deleted = await prisma.item.delete({ where: { id: Number(params.id) }, }); - return NextResponse.json(deleted); + return NextResponse.json(deleted); // TODO change to 204? } catch (error) { console.error("Error deleting item:", error); return NextResponse.json( @@ -62,7 +66,7 @@ export async function PATCH( const { folderId, path, name, starred } = await request.json(); // Normalization - const fmtPath = path.replace(/\\/g, "/"); // Replace backslashes with forward + const fmtPath = path === undefined ? undefined : path.replace(/\\/g, "/"); // Replace backslashes with forward const item = await prisma.item.update({ where: { id: Number(params.id) }, @@ -73,7 +77,7 @@ export async function PATCH( } catch (error) { console.error("Error update item:", error); return NextResponse.json( - { error: "Error deleting item" }, + { error: "Error update item" }, { status: StatusCodes.INTERNAL_SERVER_ERROR } ); } diff --git a/app/api/items/relation/[id]/route.ts b/app/api/items/relation/[id]/route.ts new file mode 100644 index 0000000..a853d43 --- /dev/null +++ b/app/api/items/relation/[id]/route.ts @@ -0,0 +1,68 @@ +import { NextResponse } from "next/server"; +import { prisma } from "@/app/lib/config/prisma"; +import { StatusCodes } from "http-status-codes"; + +export async function PATCH( + request: Request, + { params }: { params: { id: string } } +) { + try { + const { tagId, itemId } = await request.json(); + + if (tagId !== undefined) { + const tag = await prisma.tag.findUnique({ + where: { id: tagId }, + }); + if (tag === null) { + return NextResponse.json( + { error: "Tag not found" }, + { status: StatusCodes.NOT_FOUND } + ); + } + } + + if (itemId !== undefined) { + const item = await prisma.item.findUnique({ + where: { id: itemId }, + }); + if (item === null) { + return NextResponse.json( + { error: "Item not found" }, + { status: StatusCodes.NOT_FOUND } + ); + } + } + + const updated = await prisma.itemRelation.update({ + where: { id: Number(params.id) }, + data: { tagId, itemId }, + }); + + return NextResponse.json(updated); + } catch (error) { + console.error("Error update item relation:", error); + return NextResponse.json( + { error: "Error updating item relation" }, + { status: StatusCodes.INTERNAL_SERVER_ERROR } + ); + } +} + +export async function DELETE( + _request: Request, + { params }: { params: { id: string } } +) { + try { + const deleted = await prisma.tagRelation.delete({ + where: { id: Number(params.id) }, + }); + + return NextResponse.json(deleted); + } catch (error) { + console.error("Error deleting item relation:", error); + return NextResponse.json( + { error: "Error deleting item relation" }, + { status: StatusCodes.INTERNAL_SERVER_ERROR } + ); + } +} diff --git a/app/api/items/relation/route.ts b/app/api/items/relation/route.ts index db3cf28..8f2090c 100644 --- a/app/api/items/relation/route.ts +++ b/app/api/items/relation/route.ts @@ -7,6 +7,26 @@ export async function POST(request: Request) { const { tagId, itemId } = await request.json(); console.debug("Received data:", { tagId, itemId }); + const tag = await prisma.tag.findUnique({ + where: { id: tagId }, + }); + if (tag === null) { + return NextResponse.json( + { error: "Tag not found" }, + { status: StatusCodes.NOT_FOUND } + ); + } + + const item = await prisma.item.findUnique({ + where: { id: itemId }, + }); + if (item === null) { + return NextResponse.json( + { error: "Item not found" }, + { status: StatusCodes.NOT_FOUND } + ); + } + const created = await prisma.itemRelation.create({ data: { tagId, itemId }, }); @@ -21,25 +41,6 @@ export async function POST(request: Request) { } } -export async function PATCH(request: Request) { - try { - const { id, tagId, itemId } = await request.json(); - - const updated = await prisma.itemRelation.update({ - where: { id }, - data: { tagId, itemId }, - }); - - return NextResponse.json(updated); - } catch (error) { - console.error("Error update item relation:", error); - return NextResponse.json( - { error: "Error updating item relation" }, - { status: StatusCodes.INTERNAL_SERVER_ERROR } - ); - } -} - export async function GET() { try { const relations = await prisma.itemRelation.findMany(); @@ -52,28 +53,3 @@ export async function GET() { ); } } - -export async function DELETE(request: Request) { - try { - const { id } = await request.json(); - - if (!id) { - return NextResponse.json( - { error: "ID is required" }, - { status: StatusCodes.BAD_REQUEST } - ); - } - - const deleted = await prisma.tagRelation.delete({ - where: { id }, - }); - - return NextResponse.json(deleted); - } catch (error) { - console.error("Error deleting tag:", error); - return NextResponse.json( - { error: "Error deleting tag" }, - { status: StatusCodes.INTERNAL_SERVER_ERROR } - ); - } -} diff --git a/app/api/tags/relation/[id]/route.ts b/app/api/tags/relation/[id]/route.ts new file mode 100644 index 0000000..f7738f0 --- /dev/null +++ b/app/api/tags/relation/[id]/route.ts @@ -0,0 +1,75 @@ +import { NextResponse } from "next/server"; +import { prisma } from "@/app/lib/config/prisma"; +import { StatusCodes } from "http-status-codes"; + +export async function PATCH( + request: Request, + { params }: { params: { id: string } } +) { + try { + const { parentId, childId } = await request.json(); + + if (parentId === childId) { + return NextResponse.json( + { error: "Parent cannot be equal to Child" }, + { status: StatusCodes.BAD_REQUEST } + ); + } + + if (parentId !== undefined) { + const parentTag = await prisma.tag.findUnique({ + where: { id: parentId }, + }); + if (parentTag === null) { + return NextResponse.json( + { error: "Parent or child tag not found" }, + { status: StatusCodes.NOT_FOUND } + ); + } + } + + if (childId !== undefined) { + const childTag = await prisma.tag.findUnique({ + where: { id: childId }, + }); + if (childTag === null) { + return NextResponse.json( + { error: "Parent or child tag not found" }, + { status: StatusCodes.NOT_FOUND } + ); + } + } + + const updated = await prisma.tagRelation.update({ + where: { id: Number(params.id) }, + data: { parentId, childId }, + }); + + return NextResponse.json(updated); + } catch (error) { + console.error("Error update tag relation:", error); + return NextResponse.json( + { error: "Error updating tag relation" }, + { status: StatusCodes.INTERNAL_SERVER_ERROR } + ); + } +} + +export async function DELETE( + _request: Request, + { params }: { params: { id: string } } +) { + try { + const deleted = await prisma.tagRelation.delete({ + where: { id: Number(params.id) }, + }); + + return NextResponse.json(deleted); + } catch (error) { + console.error("Error deleting tag relation:", error); + return NextResponse.json( + { error: "Error deleting tag relation" }, + { status: StatusCodes.INTERNAL_SERVER_ERROR } + ); + } +} diff --git a/app/api/tags/relation/route.ts b/app/api/tags/relation/route.ts index 92af231..7cc57be 100644 --- a/app/api/tags/relation/route.ts +++ b/app/api/tags/relation/route.ts @@ -14,41 +14,35 @@ export async function POST(request: Request) { ); } - const created = await prisma.tagRelation.create({ - data: { parentId, childId }, + const parentTag = await prisma.tag.findUnique({ + where: { id: parentId }, }); + if (parentTag === null) { + return NextResponse.json( + { error: "Parent tag not found" }, + { status: StatusCodes.NOT_FOUND } + ); + } - return NextResponse.json(created); - } catch (error) { - console.error("Error creating tag relation:", error); - return NextResponse.json( - { error: "Error creating tag relation" }, - { status: StatusCodes.INTERNAL_SERVER_ERROR } - ); - } -} - -export async function PATCH(request: Request) { - try { - const { id, parentId, childId } = await request.json(); - - if (parentId === childId) { + const childTag = await prisma.tag.findUnique({ + where: { id: childId }, + }); + if (childTag === null) { return NextResponse.json( - { error: "Parent cannot be equal to Child" }, - { status: StatusCodes.BAD_REQUEST } + { error: "Child tag not found" }, + { status: StatusCodes.NOT_FOUND } ); } - const updated = await prisma.tagRelation.update({ - where: { id }, + const created = await prisma.tagRelation.create({ data: { parentId, childId }, }); - return NextResponse.json(updated); + return NextResponse.json(created); } catch (error) { - console.error("Error update tag relation:", error); + console.error("Error creating tag relation:", error); return NextResponse.json( - { error: "Error updating tag relation" }, + { error: "Error creating tag relation" }, { status: StatusCodes.INTERNAL_SERVER_ERROR } ); } @@ -66,28 +60,3 @@ export async function GET() { ); } } - -export async function DELETE(request: Request) { - try { - const { id } = await request.json(); - - if (!id) { - return NextResponse.json( - { error: "ID is required" }, - { status: StatusCodes.BAD_REQUEST } - ); - } - - const deleted = await prisma.tagRelation.delete({ - where: { id }, - }); - - return NextResponse.json(deleted); - } catch (error) { - console.error("Error deleting tag:", error); - return NextResponse.json( - { error: "Error deleting tag" }, - { status: StatusCodes.INTERNAL_SERVER_ERROR } - ); - } -} diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 7c86d80..b0b97fd 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -30,7 +30,7 @@ model Tag { model Item { id Int @id @default(autoincrement()) path String - folder Folder @relation(fields: [folderId], references: [id]) + folder Folder @relation(fields: [folderId], references: [id], onDelete: Cascade) folderId Int name String? starred Boolean @default(false) diff --git a/public/openapi/document.yaml b/public/openapi/document.yaml index 1a8bed9..e89393d 100644 --- a/public/openapi/document.yaml +++ b/public/openapi/document.yaml @@ -21,14 +21,18 @@ paths: /api/tags/{id}: $ref: "./tags/id.yaml" /api/tags/relation: - $ref: "./tags/relation.yaml" + $ref: "./tags/relation/index.yaml" + /api/tags/relation/{id}: + $ref: "./tags/relation/id.yaml" /api/items: $ref: "./items/index.yaml" - /api/items{id}: + /api/items/{id}: $ref: "./items/id.yaml" /api/items/relation: - $ref: "./items/relation.yaml" + $ref: "./items/relation/index.yaml" + /api/items/relation/{id}: + $ref: "./items/relation/id.yaml" /api/folders: $ref: "./folders/index.yaml" diff --git a/public/openapi/items/id.yaml b/public/openapi/items/id.yaml index fc8ce83..0e27179 100644 --- a/public/openapi/items/id.yaml +++ b/public/openapi/items/id.yaml @@ -2,6 +2,14 @@ patch: summary: Update item tags: - Items + parameters: + - name: id + in: path + required: true + schema: + type: integer + example: 1 + description: ID of the item to update requestBody: required: true content: @@ -11,26 +19,35 @@ patch: properties: path: type: string + description: Optional path, omit to leave unchanged + example: "my-img.jpg" folderId: type: integer + description: Optional folder ID, omit to leave unchanged + example: 1 name: type: string + description: Optional name, omit to leave unchanged + example: "MyImage" starred: type: boolean + description: Optional starred status, omit to leave unchanged responses: "200": description: Item updated successfully delete: - summary: Delete a item + summary: Delete an item tags: - Items - requestBody: - required: true - content: - application/json: - schema: - type: object + parameters: + - name: id + in: path + required: true + schema: + type: integer + example: 1 + description: ID of the item to delete responses: - "204": + "200": description: Item deleted successfully diff --git a/public/openapi/items/relation/id.yaml b/public/openapi/items/relation/id.yaml new file mode 100644 index 0000000..dc46f8f --- /dev/null +++ b/public/openapi/items/relation/id.yaml @@ -0,0 +1,39 @@ +patch: + summary: Update item relation + tags: + - Items relation + parameters: + - name: id + in: path + required: true + schema: + type: integer + example: 1 + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + tagId: + type: number + itemId: + type: number + responses: + "200": + description: Item relation updated successfully +delete: + summary: Delete a item relation + tags: + - Items relation + parameters: + - name: id + in: path + required: true + schema: + type: integer + example: 1 + responses: + "204": + description: Item relation deleted successfully diff --git a/public/openapi/items/relation.yaml b/public/openapi/items/relation/index.yaml similarity index 52% rename from public/openapi/items/relation.yaml rename to public/openapi/items/relation/index.yaml index 9ac0424..bb246d0 100644 --- a/public/openapi/items/relation.yaml +++ b/public/openapi/items/relation/index.yaml @@ -16,42 +16,7 @@ post: responses: "200": description: Item relation created successfully -patch: - summary: Update item relation - tags: - - Items relation - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - id: - type: integer - tagId: - type: number - itemId: - type: number - responses: - "200": - description: Item relation updated successfully -delete: - summary: Delete a item relation - tags: - - Items relation - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - id: - type: integer - responses: - "204": - description: Item relation deleted successfully + get: summary: List all item relations tags: diff --git a/public/openapi/tags/id.yaml b/public/openapi/tags/id.yaml index 69a7b97..b6c0a70 100644 --- a/public/openapi/tags/id.yaml +++ b/public/openapi/tags/id.yaml @@ -2,6 +2,14 @@ patch: summary: Update a tag tags: - Tags + parameters: + - name: id + in: path + required: true + schema: + type: integer + example: 1 + description: ID of the tag to update requestBody: required: true content: @@ -11,36 +19,49 @@ patch: properties: name: type: string + description: Optional name, omit to leave unchanged + example: "MyTag" type: type: string + enum: [normal, category] + description: Optional type, omit to leave unchanged + example: "normal" starred: type: boolean + description: Optional starred state, omit to leave unchanged + example: true backColor: type: string + description: Optional background color, omit to leave unchanged textColor: type: string + description: Optional text color, omit to leave unchanged responses: "200": description: Tag updated successfully + delete: summary: Delete a tag tags: - Tags - requestBody: - required: true - content: - application/json: - schema: - type: object + parameters: + - name: id + in: path + required: true + schema: + type: integer + example: 1 + description: ID of the tag to delete responses: - "204": + "200": description: Tag deleted successfully + get: summary: Get a specific tag by ID tags: - Tags parameters: - - name: tagId + - name: id in: path required: true schema: diff --git a/public/openapi/tags/relation/id.yaml b/public/openapi/tags/relation/id.yaml new file mode 100644 index 0000000..3e6f55d --- /dev/null +++ b/public/openapi/tags/relation/id.yaml @@ -0,0 +1,40 @@ +patch: + summary: Update tag relation + tags: + - Tags relation + parameters: + - name: id + in: path + required: true + schema: + type: integer + example: 1 + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + parentId: + type: number + childId: + type: number + responses: + "200": + description: Tag relation updated successfully + +delete: + summary: Delete a tag relation + tags: + - Tags relation + parameters: + - name: id + in: path + required: true + schema: + type: integer + example: 1 + responses: + "200": + description: Tag relation deleted successfully diff --git a/public/openapi/tags/relation.yaml b/public/openapi/tags/relation/index.yaml similarity index 52% rename from public/openapi/tags/relation.yaml rename to public/openapi/tags/relation/index.yaml index 651455e..828321a 100644 --- a/public/openapi/tags/relation.yaml +++ b/public/openapi/tags/relation/index.yaml @@ -16,42 +16,7 @@ post: responses: "400": description: Parent cannot be equal to Child -patch: - summary: Update tag relation - tags: - - Tags relation - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - id: - type: integer - parentId: - type: number - childId: - type: number - responses: - "200": - description: Tag relation updated successfully -delete: - summary: Delete a tag relation - tags: - - Tags relation - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - id: - type: integer - responses: - "204": - description: Tag relation deleted successfully + get: summary: List all tag relations tags: From 7b62c76e5aaf9a155cbf6894923da79a125c9d0d Mon Sep 17 00:00:00 2001 From: ziteh Date: Thu, 3 Oct 2024 13:56:54 +0800 Subject: [PATCH 3/6] feat: add JSON parsing error handle --- app/api/folders/[id]/route.ts | 27 ++++++++++++++----- app/api/folders/route.ts | 21 ++++++++++----- app/api/items/[id]/route.ts | 22 +++++++++++++--- app/api/items/relation/[id]/route.ts | 15 ++++++++++- app/api/items/relation/route.ts | 14 +++++++++- app/api/items/route.ts | 22 +++++++++++++--- app/api/tags/[id]/route.ts | 39 +++++++++++++++++++++++++++- app/api/tags/relation/[id]/route.ts | 27 ++++++++++++++----- app/api/tags/relation/route.ts | 26 ++++++++++++++----- app/api/tags/route.ts | 27 ++++++++++++++++++- 10 files changed, 202 insertions(+), 38 deletions(-) diff --git a/app/api/folders/[id]/route.ts b/app/api/folders/[id]/route.ts index b4e7eae..c751899 100644 --- a/app/api/folders/[id]/route.ts +++ b/app/api/folders/[id]/route.ts @@ -27,18 +27,33 @@ export async function PATCH( request: Request, { params }: { params: { id: string } } ) { + let name: string | undefined; + let path: string | undefined; try { - const { name, path } = await request.json(); + const json = await request.json(); + name = json.name; + let rawPath = json.path; - // Normalization - let fmtPath = path.replace(/\\/g, "/").trim(); // Replace backslashes with forward - if (!fmtPath.endsWith("/")) { - fmtPath += "/"; // Always add trailing slash + if (rawPath === undefined) { + path = undefined; + } else { + // Normalization + path = rawPath.replace(/\\/g, "/").trim(); // Replace backslashes with forward + if (path !== undefined && !path.endsWith("/")) { + path += "/"; // Always add trailing slash + } } + } catch (error) { + return NextResponse.json( + { error: `Error parsing request body, ${error}` }, + { status: StatusCodes.BAD_REQUEST } + ); + } + try { const updated = await prisma.folder.update({ where: { id: Number(params.id) }, - data: { name, path: fmtPath }, + data: { name, path }, }); return NextResponse.json(updated); diff --git a/app/api/folders/route.ts b/app/api/folders/route.ts index a189303..e536cf7 100644 --- a/app/api/folders/route.ts +++ b/app/api/folders/route.ts @@ -4,18 +4,27 @@ import { StatusCodes } from "http-status-codes"; // Create a folder export async function POST(request: Request) { + let name: string; + let path: string; try { - const { name, path } = await request.json(); - console.debug("Received data:", { name, path }); + const json = await request.json(); + name = json.name; // Normalization - let fmtPath = path.replace(/\\/g, "/").trim(); // Replace backslashes with forward - if (!fmtPath.endsWith("/")) { - fmtPath += "/"; // Always add trailing slash + path = json.path.replace(/\\/g, "/").trim(); // Replace backslashes with forward + if (!path.endsWith("/")) { + path += "/"; // Always add trailing slash } + } catch (error) { + return NextResponse.json( + { error: `Error parsing request body, ${error}` }, + { status: StatusCodes.BAD_REQUEST } + ); + } + try { const created = await prisma.folder.create({ - data: { name, path: fmtPath }, + data: { name, path }, }); return NextResponse.json(created); diff --git a/app/api/items/[id]/route.ts b/app/api/items/[id]/route.ts index 6ab36f5..bee9e07 100644 --- a/app/api/items/[id]/route.ts +++ b/app/api/items/[id]/route.ts @@ -62,15 +62,29 @@ export async function PATCH( request: Request, { params }: { params: { id: string } } ) { + let path: string | undefined; + let folderId: number | undefined; + let name: string | undefined; + let starred: boolean | undefined; try { - const { folderId, path, name, starred } = await request.json(); + const json = await request.json(); + let rawPath = json.path; + folderId = json.folderId; + name = json.name; + starred = json.starred; - // Normalization - const fmtPath = path === undefined ? undefined : path.replace(/\\/g, "/"); // Replace backslashes with forward + path = rawPath === undefined ? undefined : rawPath.replace(/\\/g, "/"); // Replace backslashes with forward + } catch (error) { + return NextResponse.json( + { error: `Error parsing request body, ${error}` }, + { status: StatusCodes.BAD_REQUEST } + ); + } + try { const item = await prisma.item.update({ where: { id: Number(params.id) }, - data: { path: fmtPath, folderId, name, starred }, + data: { path, folderId, name, starred }, }); return NextResponse.json(item); diff --git a/app/api/items/relation/[id]/route.ts b/app/api/items/relation/[id]/route.ts index a853d43..dbcc200 100644 --- a/app/api/items/relation/[id]/route.ts +++ b/app/api/items/relation/[id]/route.ts @@ -6,9 +6,22 @@ export async function PATCH( request: Request, { params }: { params: { id: string } } ) { + let tagId: number | undefined; + let itemId: number | undefined; try { - const { tagId, itemId } = await request.json(); + const json = await request.json(); + tagId = json.tagId; + itemId = json.itemId; + console.debug("Received data:", { tagId, itemId }); + } catch (error) { + return NextResponse.json( + { error: `Error parsing request body, ${error}` }, + { status: StatusCodes.BAD_REQUEST } + ); + } + + try { if (tagId !== undefined) { const tag = await prisma.tag.findUnique({ where: { id: tagId }, diff --git a/app/api/items/relation/route.ts b/app/api/items/relation/route.ts index 8f2090c..fba6b49 100644 --- a/app/api/items/relation/route.ts +++ b/app/api/items/relation/route.ts @@ -3,10 +3,22 @@ import { prisma } from "@/app/lib/config/prisma"; import { StatusCodes } from "http-status-codes"; export async function POST(request: Request) { + let tagId: number; + let itemId: number; try { - const { tagId, itemId } = await request.json(); + const json = await request.json(); + tagId = json.tagId; + itemId = json.itemId; + console.debug("Received data:", { tagId, itemId }); + } catch (error) { + return NextResponse.json( + { error: `Error parsing request body, ${error}` }, + { status: StatusCodes.BAD_REQUEST } + ); + } + try { const tag = await prisma.tag.findUnique({ where: { id: tagId }, }); diff --git a/app/api/items/route.ts b/app/api/items/route.ts index a9a87eb..49dafef 100644 --- a/app/api/items/route.ts +++ b/app/api/items/route.ts @@ -4,15 +4,29 @@ import { StatusCodes } from "http-status-codes"; // Create a new item export async function POST(request: Request) { + let path: string; + let folderId: number; + let name: string; + let starred: boolean; try { - const { path, folderId, name, starred } = await request.json(); - console.debug("Received data:", { path, name, starred }); + const json = await request.json(); + let rawPath = json.path; + folderId = json.folderId; + name = json.name; + starred = json.starred; // Normalization - const fmtPath = path.replace(/\\/g, "/").trim(); // Replace backslashes with forward + path = rawPath.replace(/\\/g, "/").trim(); // Replace backslashes with forward + } catch (error) { + return NextResponse.json( + { error: `Error parsing request body, ${error}` }, + { status: StatusCodes.BAD_REQUEST } + ); + } + try { const item = await prisma.item.create({ - data: { path: fmtPath, folderId, name, starred }, + data: { path, folderId, name, starred }, }); return NextResponse.json(item); diff --git a/app/api/tags/[id]/route.ts b/app/api/tags/[id]/route.ts index 1a18b7b..0f19c6c 100644 --- a/app/api/tags/[id]/route.ts +++ b/app/api/tags/[id]/route.ts @@ -1,6 +1,7 @@ import { NextResponse } from "next/server"; import { prisma } from "@/app/lib/config/prisma"; import { StatusCodes } from "http-status-codes"; +import { TagType } from "@/app/lib/types"; // Get a tag export async function GET( @@ -63,9 +64,45 @@ export async function PATCH( request: Request, { params }: { params: { id: string } } ) { + let name: string | undefined; + let type: string | undefined; + let starred: boolean | undefined; + let backColor: string | undefined; + let textColor: string | undefined; try { - const { name, type, starred, backColor, textColor } = await request.json(); + const json = await request.json(); + name = json.name; + type = json.type; + starred = json.starred; + backColor = json.backColor; + textColor = json.textColor; + if ( + type !== undefined && + type !== TagType.Normal && + type !== TagType.Category + ) { + return NextResponse.json( + { error: "Invalid tag type" }, + { status: StatusCodes.BAD_REQUEST } + ); + } + + console.debug("Received data:", { + name, + type, + starred, + backColor, + textColor, + }); + } catch (error) { + return NextResponse.json( + { error: `Error parsing request body, ${error}` }, + { status: StatusCodes.BAD_REQUEST } + ); + } + + try { const tag = await prisma.tag.update({ where: { id: Number(params.id) }, data: { diff --git a/app/api/tags/relation/[id]/route.ts b/app/api/tags/relation/[id]/route.ts index f7738f0..2aa0941 100644 --- a/app/api/tags/relation/[id]/route.ts +++ b/app/api/tags/relation/[id]/route.ts @@ -6,16 +6,29 @@ export async function PATCH( request: Request, { params }: { params: { id: string } } ) { + let parentId: number | undefined; + let childId: number | undefined; try { - const { parentId, childId } = await request.json(); + const json = await request.json(); + parentId = json.parentId; + childId = json.childId; - if (parentId === childId) { - return NextResponse.json( - { error: "Parent cannot be equal to Child" }, - { status: StatusCodes.BAD_REQUEST } - ); - } + console.debug("Received data:", { parentId, childId }); + } catch (error) { + return NextResponse.json( + { error: `Error parsing request body, ${error}` }, + { status: StatusCodes.BAD_REQUEST } + ); + } + if (parentId === childId) { + return NextResponse.json( + { error: "Parent cannot be equal to Child" }, + { status: StatusCodes.BAD_REQUEST } + ); + } + + try { if (parentId !== undefined) { const parentTag = await prisma.tag.findUnique({ where: { id: parentId }, diff --git a/app/api/tags/relation/route.ts b/app/api/tags/relation/route.ts index 7cc57be..c1ab074 100644 --- a/app/api/tags/relation/route.ts +++ b/app/api/tags/relation/route.ts @@ -3,17 +3,29 @@ import { prisma } from "@/app/lib/config/prisma"; import { StatusCodes } from "http-status-codes"; export async function POST(request: Request) { + let parentId: number; + let childId: number; try { - const { parentId, childId } = await request.json(); + const json = await request.json(); + parentId = json.parentId; + childId = json.childId; + console.debug("Received data:", { parentId, childId }); + } catch (error) { + return NextResponse.json( + { error: `Error parsing request body, ${error}` }, + { status: StatusCodes.BAD_REQUEST } + ); + } - if (parentId === childId) { - return NextResponse.json( - { error: "Parent cannot be equal to Child" }, - { status: StatusCodes.BAD_REQUEST } - ); - } + if (parentId === childId) { + return NextResponse.json( + { error: "Parent cannot be equal to Child" }, + { status: StatusCodes.BAD_REQUEST } + ); + } + try { const parentTag = await prisma.tag.findUnique({ where: { id: parentId }, }); diff --git a/app/api/tags/route.ts b/app/api/tags/route.ts index fb23398..ca089bc 100644 --- a/app/api/tags/route.ts +++ b/app/api/tags/route.ts @@ -5,8 +5,26 @@ import { TagType } from "@/app/lib/types"; // Create a new tag export async function POST(request: Request) { + let name: string; + let type: string; + let starred: boolean; + let backColor: string; + let textColor: string; try { - const { name, type, starred, backColor, textColor } = await request.json(); + const json = await request.json(); + name = json.name; + type = json.type; + starred = json.starred; + backColor = json.backColor; + textColor = json.textColor; + + if (type !== TagType.Normal && type !== TagType.Category) { + return NextResponse.json( + { error: "Invalid tag type" }, + { status: StatusCodes.BAD_REQUEST } + ); + } + console.debug("Received data:", { name, type, @@ -14,7 +32,14 @@ export async function POST(request: Request) { backColor, textColor, }); + } catch (error) { + return NextResponse.json( + { error: `Error parsing request body, ${error}` }, + { status: StatusCodes.BAD_REQUEST } + ); + } + try { const tag = await prisma.tag.create({ data: { name, type, starred, backColor, textColor }, }); From 88819cc8828a99be212248954b81ca93c9903723 Mon Sep 17 00:00:00 2001 From: ziteh Date: Thu, 3 Oct 2024 14:02:00 +0800 Subject: [PATCH 4/6] fix: add param `id` for folder OpenAPI docs --- public/openapi/folders/id.yaml | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/public/openapi/folders/id.yaml b/public/openapi/folders/id.yaml index 9c42e4d..b07b6c0 100644 --- a/public/openapi/folders/id.yaml +++ b/public/openapi/folders/id.yaml @@ -2,6 +2,14 @@ patch: summary: Update a folder tags: - Folders + parameters: + - name: id + in: path + required: true + schema: + type: integer + example: 1 + description: ID of the folder to update requestBody: required: true content: @@ -21,12 +29,14 @@ delete: summary: Delete a folder tags: - Folders - requestBody: - required: true - content: - application/json: - schema: - type: object + parameters: + - name: id + in: path + required: true + schema: + type: integer + example: 1 + description: ID of the folder to delete responses: "204": description: Folder deleted successfully From 3bb2ef2d59e072a1959482ef5e987315ab3fed03 Mon Sep 17 00:00:00 2001 From: ziteh Date: Thu, 3 Oct 2024 14:21:08 +0800 Subject: [PATCH 5/6] docs: update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad27f00..f97ab39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ Types of changes: ### Changed +- Updated the API of items/{id}, items/relation, tags/relation - Move "New Tag/Item/Folder" button from database page to sidebar ### Security From d7a2d630c0412ef15989d496c5409188c077d3d3 Mon Sep 17 00:00:00 2001 From: ziteh Date: Thu, 3 Oct 2024 16:32:49 +0800 Subject: [PATCH 6/6] feat: adjust the display layout of explorer showcase --- CHANGELOG.md | 1 + app/explorer/[tag]/itemGrid/index.tsx | 4 ++- .../[tag]/itemGrid/showcase/index.tsx | 36 +++++++------------ 3 files changed, 16 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f97ab39..c88ca32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ Types of changes: ### Changed - Updated the API of items/{id}, items/relation, tags/relation +- Updated the layout of explorer showcase - Move "New Tag/Item/Folder" button from database page to sidebar ### Security diff --git a/app/explorer/[tag]/itemGrid/index.tsx b/app/explorer/[tag]/itemGrid/index.tsx index e3d2390..2b25b3b 100644 --- a/app/explorer/[tag]/itemGrid/index.tsx +++ b/app/explorer/[tag]/itemGrid/index.tsx @@ -7,6 +7,8 @@ import { getTag } from "@/app/lib/tags"; import { Backdrop, Button, ImageList, ImageListItem } from "@mui/material"; import Showcase from "./showcase"; +const SHOW_CASE_QUANTITY = 85; + interface Props { tagId: number; } @@ -111,7 +113,7 @@ export default function ItemGrid(props: Props) { ))} diff --git a/app/explorer/[tag]/itemGrid/showcase/index.tsx b/app/explorer/[tag]/itemGrid/showcase/index.tsx index dd0db5d..532f898 100644 --- a/app/explorer/[tag]/itemGrid/showcase/index.tsx +++ b/app/explorer/[tag]/itemGrid/showcase/index.tsx @@ -25,30 +25,18 @@ export default function Showcase(props: Props) { open={open} onClick={onClick} > - - {/* - - - - - - - */} - - ? - - + ? ); }