implemented /bookmark/<ID>/view
This commit is contained in:
@@ -19,11 +19,10 @@ import de.srsoftware.umbrella.core.api.UserService;
|
|||||||
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
||||||
import de.srsoftware.umbrella.core.model.Token;
|
import de.srsoftware.umbrella.core.model.Token;
|
||||||
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
||||||
import org.json.JSONArray;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import org.json.JSONArray;
|
||||||
|
|
||||||
public class BookmarkApi extends BaseHandler {
|
public class BookmarkApi extends BaseHandler {
|
||||||
private final BookmarkDb db;
|
private final BookmarkDb db;
|
||||||
@@ -47,7 +46,11 @@ public class BookmarkApi extends BaseHandler {
|
|||||||
var head = path.pop();
|
var head = path.pop();
|
||||||
return switch (head) {
|
return switch (head) {
|
||||||
case LIST -> getUserBookmarks(user.get(),ex);
|
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){
|
} catch (NumberFormatException e){
|
||||||
return sendContent(ex,HTTP_BAD_REQUEST,"Invalid project id");
|
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
|
@Override
|
||||||
public boolean doPost(Path path, HttpExchange ex) throws IOException {
|
public boolean doPost(Path path, HttpExchange ex) throws IOException {
|
||||||
addCors(ex);
|
addCors(ex);
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ import de.srsoftware.umbrella.core.model.Bookmark;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public interface BookmarkDb {
|
public interface BookmarkDb {
|
||||||
Bookmark save(String url, String comment, long userId);
|
Map<Long, Bookmark> list(long userId);
|
||||||
|
|
||||||
Map<Long, Bookmark> list(long id);
|
Bookmark load(long id, long userId);
|
||||||
|
|
||||||
|
Bookmark save(String url, String comment, long userId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,20 @@
|
|||||||
/* © SRSoftware 2025 */
|
/* © SRSoftware 2025 */
|
||||||
package de.srsoftware.umbrella.bookmarks;
|
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.*;
|
||||||
import static de.srsoftware.tools.jdbc.Query.SelectQuery.ALL;
|
import static de.srsoftware.tools.jdbc.Query.SelectQuery.ALL;
|
||||||
import static de.srsoftware.umbrella.bookmarks.Constants.*;
|
import static de.srsoftware.umbrella.bookmarks.Constants.*;
|
||||||
import static de.srsoftware.umbrella.core.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.Constants.ERROR_FAILED_CREATE_TABLE;
|
||||||
import static de.srsoftware.umbrella.core.Util.sha1;
|
|
||||||
import static java.lang.System.Logger.Level.ERROR;
|
import static java.lang.System.Logger.Level.ERROR;
|
||||||
import static java.text.MessageFormat.format;
|
import static java.text.MessageFormat.format;
|
||||||
import static java.time.ZoneOffset.UTC;
|
import static java.time.ZoneOffset.UTC;
|
||||||
|
|
||||||
import de.srsoftware.tools.jdbc.Condition;
|
|
||||||
import de.srsoftware.umbrella.core.BaseDb;
|
import de.srsoftware.umbrella.core.BaseDb;
|
||||||
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
||||||
import de.srsoftware.umbrella.core.model.Bookmark;
|
import de.srsoftware.umbrella.core.model.Bookmark;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.PreparedStatement;
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -73,7 +71,7 @@ CREATE TABLE IF NOT EXISTS {0} (
|
|||||||
public Map<Long, Bookmark> list(long userId) {
|
public Map<Long, Bookmark> list(long userId) {
|
||||||
try {
|
try {
|
||||||
var map = new HashMap<Long,Bookmark>();
|
var map = new HashMap<Long,Bookmark>();
|
||||||
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()){
|
while (rs.next()){
|
||||||
var bookmark = Bookmark.of(rs);
|
var bookmark = Bookmark.of(rs);
|
||||||
map.put(bookmark.id(),bookmark);
|
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
|
@Override
|
||||||
public Bookmark save(String url, String comment, long userId) {
|
public Bookmark save(String url, String comment, long userId) {
|
||||||
try {
|
try {
|
||||||
var timestamp = LocalDateTime.now();
|
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;
|
var id = 0L;
|
||||||
if (rs.next()) id = rs.getLong(ID);
|
if (rs.next()) id = rs.getLong(ID);
|
||||||
rs.close();
|
rs.close();
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
package de.srsoftware.umbrella.core.model;
|
package de.srsoftware.umbrella.core.model;
|
||||||
|
|
||||||
import static de.srsoftware.umbrella.core.Constants.*;
|
import static de.srsoftware.umbrella.core.Constants.*;
|
||||||
|
import static de.srsoftware.umbrella.core.Util.markdown;
|
||||||
import static java.time.ZoneOffset.UTC;
|
import static java.time.ZoneOffset.UTC;
|
||||||
|
|
||||||
import de.srsoftware.tools.Mappable;
|
import de.srsoftware.tools.Mappable;
|
||||||
@@ -27,7 +28,7 @@ public record Bookmark(long id, String url, String comment, LocalDateTime timest
|
|||||||
return Map.of(
|
return Map.of(
|
||||||
ID,id,
|
ID,id,
|
||||||
URL, url,
|
URL, url,
|
||||||
COMMENT, comment,
|
COMMENT, Map.of(SOURCE,comment,RENDERED,markdown(comment)),
|
||||||
TAGS, tags,
|
TAGS, tags,
|
||||||
TIMESTAMP, timestamp.withNano(0)
|
TIMESTAMP, timestamp.withNano(0)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
import AddDoc from "./routes/document/Add.svelte";
|
import AddDoc from "./routes/document/Add.svelte";
|
||||||
import AddTask from "./routes/task/Add.svelte";
|
import AddTask from "./routes/task/Add.svelte";
|
||||||
|
import Bookmark from "./routes/bookmark/View.svelte";
|
||||||
import Bookmarks from "./routes/bookmark/Index.svelte";
|
import Bookmarks from "./routes/bookmark/Index.svelte";
|
||||||
import Callback from "./routes/user/OidcCallback.svelte";
|
import Callback from "./routes/user/OidcCallback.svelte";
|
||||||
import DocList from "./routes/document/List.svelte";
|
import DocList from "./routes/document/List.svelte";
|
||||||
@@ -52,6 +53,7 @@
|
|||||||
<Menu />
|
<Menu />
|
||||||
<Route path="/" component={User} />
|
<Route path="/" component={User} />
|
||||||
<Route path="/bookmark" component={Bookmarks} />
|
<Route path="/bookmark" component={Bookmarks} />
|
||||||
|
<Route path="/bookmark/:id/view" component={Bookmark} />
|
||||||
<Route path="/document" component={DocList} />
|
<Route path="/document" component={DocList} />
|
||||||
<Route path="/document/add" component={AddDoc} />
|
<Route path="/document/add" component={AddDoc} />
|
||||||
<Route path="/document/:id/send" component={SendDoc} />
|
<Route path="/document/:id/send" component={SendDoc} />
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
import Editor from '../../Components/MarkdownEditor.svelte';
|
import Editor from '../../Components/MarkdownEditor.svelte';
|
||||||
import Tags from '../tags/TagList.svelte';
|
import Tags from '../tags/TagList.svelte';
|
||||||
|
import Template from './Template.svelte';
|
||||||
|
|
||||||
let bookmarks = $state(null);
|
let bookmarks = $state(null);
|
||||||
let new_bookmark = $state({
|
let new_bookmark = $state({
|
||||||
@@ -75,16 +76,7 @@
|
|||||||
<button {onclick}>{t('save')}</button>
|
<button {onclick}>{t('save')}</button>
|
||||||
{#if bookmarks}
|
{#if bookmarks}
|
||||||
{#each bookmarks as bookmark}
|
{#each bookmarks as bookmark}
|
||||||
<fieldset class="bookmark">
|
<Template {bookmark} />
|
||||||
<legend>
|
|
||||||
<a href={bookmark.url} target="_blank" class="url">{bookmark.url}</a>
|
|
||||||
</legend>
|
|
||||||
<legend class="date">
|
|
||||||
{bookmark.timestamp.replace('T',' ')}
|
|
||||||
</legend>
|
|
||||||
{bookmark.comment}
|
|
||||||
<Tags module="bookmark" id={bookmark.id} />
|
|
||||||
</fieldset>
|
|
||||||
{/each}
|
{/each}
|
||||||
{/if}
|
{/if}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
18
frontend/src/routes/bookmark/Template.svelte
Normal file
18
frontend/src/routes/bookmark/Template.svelte
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<script>
|
||||||
|
import Tags from '../tags/TagList.svelte';
|
||||||
|
|
||||||
|
let { bookmark } = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if bookmark}
|
||||||
|
<fieldset class="bookmark">
|
||||||
|
<legend>
|
||||||
|
<a href={bookmark.url} target="_blank" class="url">{bookmark.url}</a>
|
||||||
|
</legend>
|
||||||
|
<legend class="date">
|
||||||
|
{bookmark.timestamp.replace('T',' ')}
|
||||||
|
</legend>
|
||||||
|
{@html bookmark.comment.rendered}
|
||||||
|
<Tags module="bookmark" id={bookmark.id} />
|
||||||
|
</fieldset>
|
||||||
|
{/if}
|
||||||
32
frontend/src/routes/bookmark/View.svelte
Normal file
32
frontend/src/routes/bookmark/View.svelte
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<script>
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
|
||||||
|
import Bookmark from './Template.svelte';
|
||||||
|
|
||||||
|
import { api } from '../../urls.svelte.js';
|
||||||
|
import { t } from '../../translations.svelte.js';
|
||||||
|
|
||||||
|
import Editor from '../../Components/MarkdownEditor.svelte';
|
||||||
|
import Template from './Template.svelte';
|
||||||
|
|
||||||
|
let bookmark = $state(null);
|
||||||
|
let error = $state(null);
|
||||||
|
let { id } = $props();
|
||||||
|
|
||||||
|
async function load(){
|
||||||
|
const url = api(`bookmark/${id}`);
|
||||||
|
const resp = await fetch(url,{credentials:'include'});
|
||||||
|
if (resp.ok){
|
||||||
|
bookmark = await resp.json();
|
||||||
|
} else {
|
||||||
|
error = await resp.text();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(load);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if error}
|
||||||
|
<span class="error">{error}</span>
|
||||||
|
{/if}
|
||||||
|
<Template {bookmark} />
|
||||||
Reference in New Issue
Block a user