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 a263f33b..4341b4a0 100644 --- a/bookmark/src/main/java/de/srsoftware/umbrella/bookmarks/BookmarkApi.java +++ b/bookmark/src/main/java/de/srsoftware/umbrella/bookmarks/BookmarkApi.java @@ -1,7 +1,6 @@ /* © SRSoftware 2025 */ package de.srsoftware.umbrella.bookmarks; -import static de.srsoftware.umbrella.messagebus.events.Event.EventType; import static de.srsoftware.umbrella.bookmarks.Constants.*; import static de.srsoftware.umbrella.core.ConnectionProvider.connect; import static de.srsoftware.umbrella.core.ModuleRegistry.tagService; @@ -29,14 +28,9 @@ import de.srsoftware.umbrella.core.constants.Text; import de.srsoftware.umbrella.core.exceptions.UmbrellaException; import de.srsoftware.umbrella.core.model.Token; import de.srsoftware.umbrella.core.model.UmbrellaUser; - -import java.awt.print.Book; +import de.srsoftware.umbrella.messagebus.events.BookmarkEvent; import java.io.IOException; import java.util.*; - -import de.srsoftware.umbrella.messagebus.events.BookmarkEvent; -import de.srsoftware.umbrella.messagebus.events.Event; -import de.srsoftware.umbrella.messagebus.events.TaskEvent; import org.json.JSONArray; public class BookmarkApi extends BaseHandler implements BookmarkService { 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 020ba968..8e94d9cb 100644 --- a/bookmark/src/main/java/de/srsoftware/umbrella/bookmarks/BookmarkDb.java +++ b/bookmark/src/main/java/de/srsoftware/umbrella/bookmarks/BookmarkDb.java @@ -3,7 +3,6 @@ package de.srsoftware.umbrella.bookmarks; import de.srsoftware.umbrella.core.model.Bookmark; import de.srsoftware.umbrella.core.model.UmbrellaUser; - import java.time.LocalDateTime; import java.util.Collection; import java.util.Map; 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 4ef4a8fd..5a965e61 100644 --- a/bookmark/src/main/java/de/srsoftware/umbrella/bookmarks/SqliteDb.java +++ b/bookmark/src/main/java/de/srsoftware/umbrella/bookmarks/SqliteDb.java @@ -12,8 +12,6 @@ import static de.srsoftware.umbrella.core.constants.Field.*; import static de.srsoftware.umbrella.core.constants.Text.BOOKMARK; import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*; import static de.srsoftware.umbrella.messagebus.MessageBus.messageBus; -import static de.srsoftware.umbrella.messagebus.events.Event.EventType.CREATE; -import static de.srsoftware.umbrella.messagebus.events.Event.EventType.UPDATE; import static java.text.MessageFormat.format; import static java.time.ZoneOffset.UTC; @@ -24,7 +22,6 @@ import de.srsoftware.umbrella.core.model.Translatable; import de.srsoftware.umbrella.core.model.UmbrellaUser; import de.srsoftware.umbrella.messagebus.events.BookmarkEvent; import de.srsoftware.umbrella.messagebus.events.Event; - import java.sql.Connection; import java.sql.SQLException; import java.time.LocalDateTime; diff --git a/bus/src/main/java/de/srsoftware/umbrella/messagebus/events/BookmarkEvent.java b/bus/src/main/java/de/srsoftware/umbrella/messagebus/events/BookmarkEvent.java index 21723970..0447e8e7 100644 --- a/bus/src/main/java/de/srsoftware/umbrella/messagebus/events/BookmarkEvent.java +++ b/bus/src/main/java/de/srsoftware/umbrella/messagebus/events/BookmarkEvent.java @@ -1,17 +1,16 @@ +/* © SRSoftware 2025 */ package de.srsoftware.umbrella.messagebus.events; -import de.srsoftware.umbrella.core.constants.Field; -import de.srsoftware.umbrella.core.model.Bookmark; -import de.srsoftware.umbrella.core.model.Task; -import de.srsoftware.umbrella.core.model.Translatable; -import de.srsoftware.umbrella.core.model.UmbrellaUser; - -import java.util.Collection; -import java.util.List; - import static de.srsoftware.umbrella.core.constants.Module.BOOKMARK; import static de.srsoftware.umbrella.core.model.Translatable.t; +import de.srsoftware.umbrella.core.constants.Field; +import de.srsoftware.umbrella.core.model.Bookmark; +import de.srsoftware.umbrella.core.model.Translatable; +import de.srsoftware.umbrella.core.model.UmbrellaUser; +import java.util.Collection; +import java.util.List; + public class BookmarkEvent extends Event { public BookmarkEvent(UmbrellaUser initiator, Bookmark bookmark, EventType type){ diff --git a/bus/src/main/java/de/srsoftware/umbrella/messagebus/events/ItemEvent.java b/bus/src/main/java/de/srsoftware/umbrella/messagebus/events/ItemEvent.java index 2bfbde2b..9f886933 100644 --- a/bus/src/main/java/de/srsoftware/umbrella/messagebus/events/ItemEvent.java +++ b/bus/src/main/java/de/srsoftware/umbrella/messagebus/events/ItemEvent.java @@ -1,16 +1,15 @@ +/* © SRSoftware 2025 */ package de.srsoftware.umbrella.messagebus.events; -import de.srsoftware.umbrella.core.ModuleRegistry; -import de.srsoftware.umbrella.core.api.Owner; -import de.srsoftware.umbrella.core.constants.Field; -import de.srsoftware.umbrella.core.model.*; - -import java.util.Collection; -import java.util.List; - import static de.srsoftware.umbrella.core.constants.Field.*; import static de.srsoftware.umbrella.core.model.Translatable.t; +import de.srsoftware.umbrella.core.ModuleRegistry; +import de.srsoftware.umbrella.core.api.Owner; +import de.srsoftware.umbrella.core.model.*; +import java.util.Collection; +import java.util.List; + public class ItemEvent extends Event{ public ItemEvent(UmbrellaUser initiator, String module, Item item, EventType type) { super(initiator, module, item, type); diff --git a/core/src/main/java/de/srsoftware/umbrella/core/constants/Field.java b/core/src/main/java/de/srsoftware/umbrella/core/constants/Field.java index c343cbf7..430e524a 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/constants/Field.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/constants/Field.java @@ -150,6 +150,7 @@ public class Field { public static final String SUBJECT = "subject"; public static final String TABLE = "table"; + public static final String TAG = "tag"; public static final String TAGS = "tags"; public static final String TAG_COLORS = "tag_colors"; public static final String TASK = "task"; diff --git a/core/src/main/java/de/srsoftware/umbrella/core/model/Poll.java b/core/src/main/java/de/srsoftware/umbrella/core/model/Poll.java index 20b5b5f8..8b92e731 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/model/Poll.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/model/Poll.java @@ -1,19 +1,19 @@ +/* © SRSoftware 2025 */ package de.srsoftware.umbrella.core.model; +import static de.srsoftware.umbrella.core.constants.Field.*; +import static java.text.MessageFormat.format; + import de.srsoftware.tools.Mappable; import de.srsoftware.umbrella.core.ModuleRegistry; import de.srsoftware.umbrella.core.Util; import de.srsoftware.umbrella.core.api.Owner; import de.srsoftware.umbrella.core.constants.Field; - import java.sql.ResultSet; import java.sql.SQLException; import java.util.*; import java.util.stream.Collectors; -import static de.srsoftware.umbrella.core.constants.Field.*; -import static java.text.MessageFormat.format; - public class Poll implements Mappable { public static class Option implements Mappable{ diff --git a/frontend/src/Components/Autocomplete.svelte b/frontend/src/Components/Autocomplete.svelte index 74eae485..ad859226 100644 --- a/frontend/src/Components/Autocomplete.svelte +++ b/frontend/src/Components/Autocomplete.svelte @@ -79,6 +79,7 @@ candidates = []; selected = []; onCommit(candidate); + candidate = { display : '' }; } return false; } diff --git a/frontend/src/routes/tags/TagList.svelte b/frontend/src/routes/tags/TagList.svelte index 40f72f13..a9b0d9b7 100644 --- a/frontend/src/routes/tags/TagList.svelte +++ b/frontend/src/routes/tags/TagList.svelte @@ -2,7 +2,9 @@ import {onMount} from 'svelte'; import { useTinyRouter } from 'svelte-tiny-router'; - import { api } from '../../urls.svelte.js'; + import Autocomplete from '../../Components/Autocomplete.svelte'; + + import { api, get, post } from '../../urls.svelte.js'; import { error, yikes } from '../../warn.svelte'; import { t } from '../../translations.svelte.js'; import { user } from '../../user.svelte.js' @@ -13,10 +15,9 @@ tags = $bindable([]), user_list = [], } = $props(); - let newTag = $state(''); let router = useTinyRouter(); - async function addTag(){ + async function addTag(newTag){ if (!newTag) return; if (!id) { // when creating elements, they don`t have an id, yet @@ -63,10 +64,21 @@ return false; } + async function getCandidates(input){ + if (!input || input.length <3) return []; + const url = api(`tags/search/${encodeURI(input)}`); + const res = await get(url); + if (res.ok){ + yikes(); + const list = await res.json(); + return list.map(elem => {return {display:elem}}); + } else error(res); + } + async function loadTags(entityId){ if (!entityId) return; // when crating elements, they dont`t have an id, yet. const url = api(`tags/${module}/${entityId}`); - const resp = await fetch(url,{credentials:'include'}); + const resp = await get(url); if (resp.ok) { tags = await resp.json(); tags = tags.sort(); @@ -75,13 +87,16 @@ } } + async function onCommit(wrapped){ + addTag(wrapped.display); + } + + function onSelect(dummy){} + function show(tag){ router.navigate(`/tags/use/${tag}`); } - function typed(ev){ - if (ev.keyCode == 13) addTag(); - } $effect(() => loadTags(id)); @@ -93,6 +108,6 @@ {/each} - + diff --git a/poll/src/main/java/de/srsoftware/umbrella/poll/PollDb.java b/poll/src/main/java/de/srsoftware/umbrella/poll/PollDb.java index 943df9c1..3c06741d 100644 --- a/poll/src/main/java/de/srsoftware/umbrella/poll/PollDb.java +++ b/poll/src/main/java/de/srsoftware/umbrella/poll/PollDb.java @@ -4,7 +4,6 @@ package de.srsoftware.umbrella.poll; import de.srsoftware.umbrella.core.model.Permission; import de.srsoftware.umbrella.core.model.Poll; import de.srsoftware.umbrella.core.model.UmbrellaUser; - import java.util.Collection; import java.util.Map; diff --git a/poll/src/main/java/de/srsoftware/umbrella/poll/PollModule.java b/poll/src/main/java/de/srsoftware/umbrella/poll/PollModule.java index 067f8d9c..339911b4 100644 --- a/poll/src/main/java/de/srsoftware/umbrella/poll/PollModule.java +++ b/poll/src/main/java/de/srsoftware/umbrella/poll/PollModule.java @@ -11,7 +11,7 @@ import static de.srsoftware.umbrella.poll.Constants.CONFIG_DATABASE; import static java.lang.System.Logger.Level.WARNING; import static java.net.HttpURLConnection.HTTP_OK; import static java.text.MessageFormat.format; -import static de.srsoftware.umbrella.core.model.Permission.READ_ONLY; + import com.sun.net.httpserver.HttpExchange; import de.srsoftware.configuration.Configuration; import de.srsoftware.tools.Path; @@ -26,10 +26,9 @@ import de.srsoftware.umbrella.core.model.Permission; import de.srsoftware.umbrella.core.model.Poll; import de.srsoftware.umbrella.core.model.Token; import de.srsoftware.umbrella.core.model.UmbrellaUser; -import org.json.JSONObject; - import java.io.IOException; import java.util.*; +import org.json.JSONObject; public class PollModule extends BaseHandler implements PollService { diff --git a/poll/src/main/java/de/srsoftware/umbrella/poll/SqliteDb.java b/poll/src/main/java/de/srsoftware/umbrella/poll/SqliteDb.java index b8b40a31..ecaad114 100644 --- a/poll/src/main/java/de/srsoftware/umbrella/poll/SqliteDb.java +++ b/poll/src/main/java/de/srsoftware/umbrella/poll/SqliteDb.java @@ -21,7 +21,6 @@ import de.srsoftware.umbrella.core.exceptions.UmbrellaException; import de.srsoftware.umbrella.core.model.Permission; import de.srsoftware.umbrella.core.model.Poll; import de.srsoftware.umbrella.core.model.UmbrellaUser; - import java.sql.Connection; import java.sql.SQLException; import java.util.*; diff --git a/tags/src/main/java/de/srsoftware/umbrella/tags/SqliteDb.java b/tags/src/main/java/de/srsoftware/umbrella/tags/SqliteDb.java index ac398e9e..294ac9b7 100644 --- a/tags/src/main/java/de/srsoftware/umbrella/tags/SqliteDb.java +++ b/tags/src/main/java/de/srsoftware/umbrella/tags/SqliteDb.java @@ -10,6 +10,7 @@ import static de.srsoftware.tools.jdbc.Query.SelectQuery.ALL; import static de.srsoftware.umbrella.bookmarks.Constants.*; import static de.srsoftware.umbrella.core.Errors.*; import static de.srsoftware.umbrella.core.constants.Field.*; +import static de.srsoftware.umbrella.core.constants.Field.TAG; import static de.srsoftware.umbrella.core.constants.Field.TAGS; import static de.srsoftware.umbrella.core.constants.Module.BOOKMARK; import static de.srsoftware.umbrella.core.constants.Text.TABLE_WITH_NAME; @@ -25,8 +26,10 @@ import de.srsoftware.tools.Tuple; import de.srsoftware.tools.jdbc.Query; import de.srsoftware.umbrella.bookmarks.BookmarkDb; import de.srsoftware.umbrella.core.BaseDb; +import de.srsoftware.umbrella.core.constants.Field; import de.srsoftware.umbrella.core.constants.Text; import de.srsoftware.umbrella.core.model.Translatable; +import de.srsoftware.umbrella.core.model.UmbrellaUser; import java.sql.Connection; import java.sql.SQLException; import java.time.LocalDateTime; @@ -333,6 +336,19 @@ CREATE TABLE IF NOT EXISTS {0} ( } } + @Override + public Collection search(String key, UmbrellaUser user) { + try { + var tags = new HashSet(); + var rs = select("DISTINCT tag").from(TABLE_TAGS).where(USER_ID,equal(user.id())).where(Field.TAG,like("%"+key+"%")).exec(db); + while (rs.next()) tags.add(rs.getString(1)); + rs.close(); + return tags; + } catch (SQLException s){ + throw failedToLoadObject(Text.TAGS); + } + } + @Override public void updateId(String module, Object oldId, Object newId) { try { diff --git a/tags/src/main/java/de/srsoftware/umbrella/tags/TagDB.java b/tags/src/main/java/de/srsoftware/umbrella/tags/TagDB.java index 575fc6e1..b6e8f313 100644 --- a/tags/src/main/java/de/srsoftware/umbrella/tags/TagDB.java +++ b/tags/src/main/java/de/srsoftware/umbrella/tags/TagDB.java @@ -3,6 +3,7 @@ package de.srsoftware.umbrella.tags; import de.srsoftware.tools.Tuple; +import de.srsoftware.umbrella.core.model.UmbrellaUser; import java.util.Collection; import java.util.List; import java.util.Map; @@ -32,5 +33,7 @@ public interface TagDB { void save(Collection userIds, String module, long entityId, Collection tags); + Collection search(String key, UmbrellaUser user); + void updateId(String module, Object oldId, Object newId); } diff --git a/tags/src/main/java/de/srsoftware/umbrella/tags/TagModule.java b/tags/src/main/java/de/srsoftware/umbrella/tags/TagModule.java index 47c094bf..cf985419 100644 --- a/tags/src/main/java/de/srsoftware/umbrella/tags/TagModule.java +++ b/tags/src/main/java/de/srsoftware/umbrella/tags/TagModule.java @@ -5,6 +5,7 @@ import static de.srsoftware.umbrella.core.ConnectionProvider.connect; import static de.srsoftware.umbrella.core.ModuleRegistry.userService; import static de.srsoftware.umbrella.core.ResponseCode.HTTP_UNPROCESSABLE; import static de.srsoftware.umbrella.core.constants.Field.USER_LIST; +import static de.srsoftware.umbrella.core.constants.Path.SEARCH; import static de.srsoftware.umbrella.core.constants.Path.USES; import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*; import static de.srsoftware.umbrella.tags.Constants.*; @@ -66,11 +67,13 @@ public class TagModule extends BaseHandler implements TagService { var user = userService().refreshSession(ex); if (user.isEmpty()) return unauthorized(ex); var module = path.pop(); - if (module == null) return getUserTags(ex, user.get()); - var head = path.pop(); - if (USES.equals(module)) return getTagUses(ex,head,user.get()); - long entityId = Long.parseLong(head); - return sendContent(ex, getTags(module,entityId,user.get())); + return switch (module){ + case SEARCH -> searchTags(ex,path.pop(),user.get()); + case USES -> getTagUses(ex,path.pop(),user.get()); + case null -> getUserTags(ex, user.get()); + default -> sendContent(ex, getTags(module,Long.parseLong(path.pop()),user.get())); + }; + } catch (NumberFormatException e){ return sendContent(ex,HTTP_UNPROCESSABLE,"Entity id missing in path."); } catch (UmbrellaException e){ @@ -150,6 +153,10 @@ public class TagModule extends BaseHandler implements TagService { return tag; } + private boolean searchTags(HttpExchange ex, String head, UmbrellaUser user) throws IOException { + return sendContent(ex, tagDb.search(head, user)); + } + @Override public void updateId(String module, Object oldId, Object newId) { tagDb.updateId(module,oldId,newId); diff --git a/task/src/main/java/de/srsoftware/umbrella/task/TaskModule.java b/task/src/main/java/de/srsoftware/umbrella/task/TaskModule.java index 6fffe48c..1b013b87 100644 --- a/task/src/main/java/de/srsoftware/umbrella/task/TaskModule.java +++ b/task/src/main/java/de/srsoftware/umbrella/task/TaskModule.java @@ -32,7 +32,6 @@ import de.srsoftware.tools.SessionToken; import de.srsoftware.umbrella.core.BaseHandler; import de.srsoftware.umbrella.core.ModuleRegistry; import de.srsoftware.umbrella.core.api.*; -import de.srsoftware.umbrella.core.constants.Field; import de.srsoftware.umbrella.core.constants.Text; import de.srsoftware.umbrella.core.exceptions.UmbrellaException; import de.srsoftware.umbrella.core.model.*;