implement edit bookmark dialog

This commit is contained in:
2025-05-25 15:40:16 +01:00
parent 255acfcb32
commit 6afb5dee9a
22 changed files with 630 additions and 127 deletions

View File

@@ -1,4 +1,4 @@
import type { Bookmark, BookmarkTag } from "@markone/core/bookmark"
import type { Bookmark, Tag, TaggedBookmark } from "@markone/core"
import { DEMO_USER } from "@markone/core/user"
import { type } from "arktype"
import { ulid } from "ulid"
@@ -15,8 +15,11 @@ import {
findBookmarkCachedContent,
findBookmarkTags,
insertBookmark,
updateBookmarkTags,
updateBookmarkTitle,
} from "./bookmark.ts"
import { insertTags } from "./tag.ts"
import { insertTags } from "~/tag/tag.js"
const BOOKMARK_PAGINATION_LIMIT = 100
@@ -33,6 +36,11 @@ const AddBookmarkRequestBody = type({
"force?": "boolean",
})
const UpdateBookmarkRequestBody = type({
"title?": "string",
"tags?": "string[]",
})
const AddTagRequestBody = type({
name: "string",
})
@@ -93,7 +101,6 @@ async function addBookmark(request: Bun.BunRequest<"/api/bookmarks">, user: User
if (user.id !== DEMO_USER.id) {
const body = AddBookmarkRequestBody(await request.json())
if (body instanceof type.errors) {
console.log(body)
throw new HttpError(400)
}
@@ -118,7 +125,7 @@ async function addBookmark(request: Bun.BunRequest<"/api/bookmarks">, user: User
}
}
const bookmark: Bookmark = {
const bookmark: TaggedBookmark = {
id: ulid(),
title: "",
url: body.url,
@@ -134,7 +141,7 @@ async function addBookmark(request: Bun.BunRequest<"/api/bookmarks">, user: User
insertBookmark(bookmark, cachedContent, user)
if (tagNames.size > 0) {
const tagQuery = db.query<Partial<BookmarkTag>, string[]>(`
const tagQuery = db.query<Partial<Tag>, string[]>(`
SELECT id, name FROM tags
WHERE user_id = ? AND name IN (${Array(tagNames.size).fill("?").join(",")})
`)
@@ -142,7 +149,7 @@ async function addBookmark(request: Bun.BunRequest<"/api/bookmarks">, user: User
for (const tag of tags) {
if (tag.id && tag.name) {
bookmark.tags.push(tag as BookmarkTag)
bookmark.tags.push(tag as Tag)
tagNames.delete(tag.name)
}
}
@@ -190,7 +197,7 @@ async function fetchBookmark(request: Bun.BunRequest<"/api/bookmarks/:id">, user
}
async function listUserTags(request: Bun.BunRequest<"/api/tags">, user: User) {
const query = db.query<BookmarkTag, { id: string }>("SELECT id, name FROM tags WHERE user_id = $id")
const query = db.query<Tag, { id: string }>("SELECT id, name FROM tags WHERE user_id = $id")
const tags = query.all({ id: user.id })
return Response.json(tags, { status: 200 })
}
@@ -208,7 +215,7 @@ async function createUserTag(request: Bun.BunRequest<"/api/tags">, user: User) {
throw new HttpError(400)
}
const tag: BookmarkTag = {
const tag: Tag = {
id: ulid(),
name: body.name,
}
@@ -230,6 +237,44 @@ async function listBookmarkTags(request: Bun.BunRequest<"/api/bookmarks/:id/tags
return Response.json(tags, { status: 200 })
}
async function updateBookmark(request: Bun.BunRequest<"/api/bookmarks/:id">, user: User) {
const bodyJson = await request.json().catch(() => {
throw new HttpError(400)
})
const body = UpdateBookmarkRequestBody(bodyJson)
if (body instanceof type.errors) {
throw new HttpError(400)
}
if (!body.title || !body.tags) {
return Response.json(undefined, { status: 204 })
}
const bookmark = findBookmark(request.params.id, user)
if (!bookmark) {
throw new HttpError(404)
}
if (body.title) {
updateBookmarkTitle(bookmark, body.title, user)
bookmark.title = body.title
}
if (body.tags) {
const taggedBookmark = bookmark as TaggedBookmark
for (const tag of body.tags) {
if (tag.length === 0 || /[\s#]/g.test(tag)) {
throw new HttpError(400, "InvalidTag", "Tags cannot contain '#' or whitespaces")
}
}
taggedBookmark.tags = updateBookmarkTags(bookmark, body.tags, user)
return Response.json(taggedBookmark, { status: 200 })
}
return Response.json(bookmark, { status: 200 })
}
export {
addBookmark,
fetchBookmark,
@@ -238,4 +283,5 @@ export {
listUserTags,
createUserTag,
listBookmarkTags,
updateBookmark,
}