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/CHANGELOG.md b/CHANGELOG.md
index ad27f00..c88ca32 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,6 +18,8 @@ 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/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 18831e6..bee9e07 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(
@@ -58,22 +62,36 @@ 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.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);
} 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..dbcc200
--- /dev/null
+++ b/app/api/items/relation/[id]/route.ts
@@ -0,0 +1,81 @@
+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 } }
+) {
+ let tagId: number | undefined;
+ let itemId: number | undefined;
+ try {
+ 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 },
+ });
+ 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..fba6b49 100644
--- a/app/api/items/relation/route.ts
+++ b/app/api/items/relation/route.ts
@@ -3,38 +3,51 @@ 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();
- console.debug("Received data:", { tagId, itemId });
-
- const created = await prisma.itemRelation.create({
- data: { tagId, itemId },
- });
+ const json = await request.json();
+ tagId = json.tagId;
+ itemId = json.itemId;
- return NextResponse.json(created);
+ console.debug("Received data:", { tagId, itemId });
} catch (error) {
- console.error("Error creating item relation:", error);
return NextResponse.json(
- { error: "Error creating item relation" },
- { status: StatusCodes.INTERNAL_SERVER_ERROR }
+ { error: `Error parsing request body, ${error}` },
+ { status: StatusCodes.BAD_REQUEST }
);
}
-}
-export async function PATCH(request: Request) {
try {
- const { id, tagId, itemId } = await request.json();
+ 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 updated = await prisma.itemRelation.update({
- where: { id },
+ const created = await prisma.itemRelation.create({
data: { tagId, itemId },
});
- return NextResponse.json(updated);
+ return NextResponse.json(created);
} catch (error) {
- console.error("Error update item relation:", error);
+ console.error("Error creating item relation:", error);
return NextResponse.json(
- { error: "Error updating item relation" },
+ { error: "Error creating item relation" },
{ status: StatusCodes.INTERNAL_SERVER_ERROR }
);
}
@@ -52,28 +65,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/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
new file mode 100644
index 0000000..2aa0941
--- /dev/null
+++ b/app/api/tags/relation/[id]/route.ts
@@ -0,0 +1,88 @@
+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 } }
+) {
+ let parentId: number | undefined;
+ let childId: number | undefined;
+ try {
+ 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 }
+ );
+ }
+
+ try {
+ 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..c1ab074 100644
--- a/app/api/tags/relation/route.ts
+++ b/app/api/tags/relation/route.ts
@@ -3,52 +3,58 @@ 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();
- console.debug("Received data:", { parentId, childId });
-
- if (parentId === childId) {
- return NextResponse.json(
- { error: "Parent cannot be equal to Child" },
- { status: StatusCodes.BAD_REQUEST }
- );
- }
+ const json = await request.json();
+ parentId = json.parentId;
+ childId = json.childId;
- const created = await prisma.tagRelation.create({
- data: { parentId, childId },
- });
-
- return NextResponse.json(created);
+ console.debug("Received data:", { parentId, childId });
} catch (error) {
- console.error("Error creating tag relation:", error);
return NextResponse.json(
- { error: "Error creating tag relation" },
- { status: StatusCodes.INTERNAL_SERVER_ERROR }
+ { 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 }
);
}
-}
-export async function PATCH(request: Request) {
try {
- const { id, parentId, childId } = await request.json();
+ const parentTag = await prisma.tag.findUnique({
+ where: { id: parentId },
+ });
+ if (parentTag === null) {
+ return NextResponse.json(
+ { error: "Parent tag not found" },
+ { status: StatusCodes.NOT_FOUND }
+ );
+ }
- 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 +72,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/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 },
});
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}
>
-
- {/*
-
-
-
-
-
-
- */}
-
-
-
-
+
);
}
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
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/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
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: