diff --git a/bookmark/src/main/java/de/srsoftware/umbrella/bookmarks/BookmarkApi.java b/bookmark/src/main/java/de/srsoftware/umbrella/bookmarks/BookmarkApi.java index 800f6a8..dbe54d6 100644 --- a/bookmark/src/main/java/de/srsoftware/umbrella/bookmarks/BookmarkApi.java +++ b/bookmark/src/main/java/de/srsoftware/umbrella/bookmarks/BookmarkApi.java @@ -19,11 +19,10 @@ import de.srsoftware.umbrella.core.api.UserService; import de.srsoftware.umbrella.core.exceptions.UmbrellaException; import de.srsoftware.umbrella.core.model.Token; import de.srsoftware.umbrella.core.model.UmbrellaUser; -import org.json.JSONArray; - import java.io.IOException; import java.util.List; import java.util.Optional; +import org.json.JSONArray; public class BookmarkApi extends BaseHandler { private final BookmarkDb db; @@ -47,7 +46,11 @@ public class BookmarkApi extends BaseHandler { var head = path.pop(); return switch (head) { case LIST -> getUserBookmarks(user.get(),ex); - case null, default -> super.doPost(path,ex); + case null -> super.doPost(path,ex); + default -> { + var id = Long.parseLong(head); + yield getBookmark(user.get(),id,ex); + } }; } catch (NumberFormatException e){ return sendContent(ex,HTTP_BAD_REQUEST,"Invalid project id"); @@ -56,6 +59,12 @@ public class BookmarkApi extends BaseHandler { } } + private boolean getBookmark(UmbrellaUser user, long id, HttpExchange ex) throws IOException { + var bookmark = db.load(id,user.id()); + tags.getTags(BOOKMARK, id, user).forEach(bookmark.tags()::add); + return sendContent(ex,bookmark); + } + @Override public boolean doPost(Path path, HttpExchange ex) throws IOException { addCors(ex); diff --git a/bookmark/src/main/java/de/srsoftware/umbrella/bookmarks/BookmarkDb.java b/bookmark/src/main/java/de/srsoftware/umbrella/bookmarks/BookmarkDb.java index b28bd35..e64f3b2 100644 --- a/bookmark/src/main/java/de/srsoftware/umbrella/bookmarks/BookmarkDb.java +++ b/bookmark/src/main/java/de/srsoftware/umbrella/bookmarks/BookmarkDb.java @@ -5,7 +5,9 @@ import de.srsoftware.umbrella.core.model.Bookmark; import java.util.Map; public interface BookmarkDb { - Bookmark save(String url, String comment, long userId); + Map list(long userId); + + Bookmark load(long id, long userId); - Map list(long id); + Bookmark save(String url, String comment, long userId); } diff --git a/bookmark/src/main/java/de/srsoftware/umbrella/bookmarks/SqliteDb.java b/bookmark/src/main/java/de/srsoftware/umbrella/bookmarks/SqliteDb.java index ba2cf23..a6bb26d 100644 --- a/bookmark/src/main/java/de/srsoftware/umbrella/bookmarks/SqliteDb.java +++ b/bookmark/src/main/java/de/srsoftware/umbrella/bookmarks/SqliteDb.java @@ -1,22 +1,20 @@ /* © SRSoftware 2025 */ package de.srsoftware.umbrella.bookmarks; +import static de.srsoftware.tools.jdbc.Condition.equal; import static de.srsoftware.tools.jdbc.Query.*; import static de.srsoftware.tools.jdbc.Query.SelectQuery.ALL; import static de.srsoftware.umbrella.bookmarks.Constants.*; import static de.srsoftware.umbrella.core.Constants.*; import static de.srsoftware.umbrella.core.Constants.ERROR_FAILED_CREATE_TABLE; -import static de.srsoftware.umbrella.core.Util.sha1; import static java.lang.System.Logger.Level.ERROR; import static java.text.MessageFormat.format; import static java.time.ZoneOffset.UTC; -import de.srsoftware.tools.jdbc.Condition; import de.srsoftware.umbrella.core.BaseDb; import de.srsoftware.umbrella.core.exceptions.UmbrellaException; import de.srsoftware.umbrella.core.model.Bookmark; import java.sql.Connection; -import java.sql.PreparedStatement; import java.sql.SQLException; import java.time.LocalDateTime; import java.util.HashMap; @@ -73,7 +71,7 @@ CREATE TABLE IF NOT EXISTS {0} ( public Map list(long userId) { try { var map = new HashMap(); - var rs = select(ALL).from(TABLE_URL_COMMENTS).leftJoin(URL_ID,TABLE_URLS,ID).where(USER_ID, Condition.equal(userId)).exec(db); + var rs = select(ALL).from(TABLE_URL_COMMENTS).leftJoin(URL_ID,TABLE_URLS,ID).where(USER_ID, equal(userId)).exec(db); while (rs.next()){ var bookmark = Bookmark.of(rs); map.put(bookmark.id(),bookmark); @@ -85,11 +83,25 @@ CREATE TABLE IF NOT EXISTS {0} ( } } + @Override + public Bookmark load(long id, long userId) { + try { + Bookmark result = null; + var rs = select(ALL).from(TABLE_URLS).leftJoin(ID,TABLE_URL_COMMENTS,URL_ID).where(ID,equal(id)).where(USER_ID,equal(userId)).exec(db); + if (rs.next()) result = Bookmark.of(rs); + rs.close(); + if (result != null) return result; + throw UmbrellaException.notFound("No bookmark with id {0}",id); + } catch (SQLException e) { + throw new UmbrellaException("Failed to load bookmark"); + } + } + @Override public Bookmark save(String url, String comment, long userId) { try { var timestamp = LocalDateTime.now(); - var rs = select(ID).from(TABLE_URLS).where(URL,Condition.equal(url)).exec(db); + var rs = select(ID).from(TABLE_URLS).where(URL, equal(url)).exec(db); var id = 0L; if (rs.next()) id = rs.getLong(ID); rs.close(); diff --git a/core/src/main/java/de/srsoftware/umbrella/core/model/Bookmark.java b/core/src/main/java/de/srsoftware/umbrella/core/model/Bookmark.java index 24d5ae8..fdbf210 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/model/Bookmark.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/model/Bookmark.java @@ -2,6 +2,7 @@ package de.srsoftware.umbrella.core.model; import static de.srsoftware.umbrella.core.Constants.*; +import static de.srsoftware.umbrella.core.Util.markdown; import static java.time.ZoneOffset.UTC; import de.srsoftware.tools.Mappable; @@ -27,7 +28,7 @@ public record Bookmark(long id, String url, String comment, LocalDateTime timest return Map.of( ID,id, URL, url, - COMMENT, comment, + COMMENT, Map.of(SOURCE,comment,RENDERED,markdown(comment)), TAGS, tags, TIMESTAMP, timestamp.withNano(0) ); diff --git a/frontend/src/App.svelte b/frontend/src/App.svelte index 0315570..1b67cd8 100644 --- a/frontend/src/App.svelte +++ b/frontend/src/App.svelte @@ -7,6 +7,7 @@ import AddDoc from "./routes/document/Add.svelte"; import AddTask from "./routes/task/Add.svelte"; + import Bookmark from "./routes/bookmark/View.svelte"; import Bookmarks from "./routes/bookmark/Index.svelte"; import Callback from "./routes/user/OidcCallback.svelte"; import DocList from "./routes/document/List.svelte"; @@ -52,6 +53,7 @@ + diff --git a/frontend/src/routes/bookmark/Index.svelte b/frontend/src/routes/bookmark/Index.svelte index d56e9ea..aa5a79b 100644 --- a/frontend/src/routes/bookmark/Index.svelte +++ b/frontend/src/routes/bookmark/Index.svelte @@ -6,6 +6,7 @@ import Editor from '../../Components/MarkdownEditor.svelte'; import Tags from '../tags/TagList.svelte'; + import Template from './Template.svelte'; let bookmarks = $state(null); let new_bookmark = $state({ @@ -75,16 +76,7 @@ {#if bookmarks} {#each bookmarks as bookmark} -
- - {bookmark.url} - - - {bookmark.timestamp.replace('T',' ')} - - {bookmark.comment} - -
+