From 4f481c32adfe3c550240b60ed55119e03c7bb538 Mon Sep 17 00:00:00 2001 From: Stephan Richter Date: Tue, 19 Aug 2025 09:42:06 +0200 Subject: [PATCH] implemented task search --- .../umbrella/bookmarks/Constants.java | 1 - .../srsoftware/umbrella/core/Constants.java | 1 + frontend/src/routes/search/Search.svelte | 38 +++++++++++++++++-- .../de/srsoftware/umbrella/task/SqliteDb.java | 26 ++++++++++++- .../de/srsoftware/umbrella/task/TaskDb.java | 2 + .../srsoftware/umbrella/task/TaskModule.java | 10 +++++ 6 files changed, 72 insertions(+), 6 deletions(-) diff --git a/bookmark/src/main/java/de/srsoftware/umbrella/bookmarks/Constants.java b/bookmark/src/main/java/de/srsoftware/umbrella/bookmarks/Constants.java index 5c44a71..cb5311a 100644 --- a/bookmark/src/main/java/de/srsoftware/umbrella/bookmarks/Constants.java +++ b/bookmark/src/main/java/de/srsoftware/umbrella/bookmarks/Constants.java @@ -3,7 +3,6 @@ package de.srsoftware.umbrella.bookmarks; public class Constants { public static final String CONFIG_DATABASE = "umbrella.modules.bookmark.database"; - public static final String FULLTEXT = "fulltext"; public static final String SHARE = "share"; public static final String TABLE_TOKENS = "tokens"; public static final String TABLE_URLS = "urls"; diff --git a/core/src/main/java/de/srsoftware/umbrella/core/Constants.java b/core/src/main/java/de/srsoftware/umbrella/core/Constants.java index fde9ba2..b038cbc 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/Constants.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/Constants.java @@ -98,6 +98,7 @@ public class Constants { public static final String FIELD_TYPE_PREFIX = "type_prefix"; public static final String FIELD_TYPE_SUFFIX = "type_suffix"; public static final String FIELD_UNIT = "unit"; + public static final String FULLTEXT = "fulltext"; public static final String GET = "GET"; diff --git a/frontend/src/routes/search/Search.svelte b/frontend/src/routes/search/Search.svelte index 8f5b323..fa4476a 100644 --- a/frontend/src/routes/search/Search.svelte +++ b/frontend/src/routes/search/Search.svelte @@ -9,10 +9,11 @@ const router = useTinyRouter(); console.log(router); let bookmarks = $state(null); + let error = $state(null); let fulltext = false; let key = $state(router.getQueryParam('key')); let input = $state(router.getQueryParam('key')); - let error = $state(null); + let tasks = $state(null); async function setKey(ev){ if (ev) ev.preventDefault(); @@ -31,17 +32,32 @@ window.history.replaceState(history.state, '', url); const data = { key : key, fulltext : fulltext }; - fetch(api('bookmark/search'),{ + const options = { credentials:'include', method: 'POST', body: JSON.stringify(data) - }).then(handleBookmarks); + }; + fetch(api('bookmark/search'),options).then(handleBookmarks); + fetch(api('task/search'),options).then(handleTasks); + } + + function go(path){ + router.navigate(path); + return false; } async function handleBookmarks(resp){ if (resp.ok){ bookmarks = await resp.json(); - console.log(bookmarks); + } else { + error = await resp.text(); + } + } + + async function handleTasks(resp){ + if (resp.ok){ + tasks = await resp.json(); + console.log(tasks); } else { error = await resp.text(); } @@ -68,6 +84,20 @@ +{#if tasks} +
+ + {t('tasks')} + + +
+{/if} {#if bookmarks}
diff --git a/task/src/main/java/de/srsoftware/umbrella/task/SqliteDb.java b/task/src/main/java/de/srsoftware/umbrella/task/SqliteDb.java index 722fd98..f6404ad 100644 --- a/task/src/main/java/de/srsoftware/umbrella/task/SqliteDb.java +++ b/task/src/main/java/de/srsoftware/umbrella/task/SqliteDb.java @@ -114,6 +114,30 @@ CREATE TABLE IF NOT EXISTS {0} ( } } + @Override + public HashMap find(long userId, List keys, boolean fulltext) { + try { + var tasks = new HashMap(); + var query = select(ALL).from(TABLE_TASKS).leftJoin(ID,TABLE_TASKS_USERS,TASK_ID) + .where(USER_ID,equal(userId)); + for (var key : keys) query.where(NAME,like("%"+key+"%")); + if (fulltext) { + for (var key : keys) query.where(DESCRIPTION,like("%"+key+"%")); + } + + var rs = query.exec(db); + while (rs.next()){ + var task = Task.of(rs); + tasks.put(task.id(),task); + } + rs.close(); + return tasks; + } catch (SQLException e){ + LOG.log(WARNING,"Failed to load tasks for user (user_id: {0}",userId,e); + throw new UmbrellaException("Failed to load tasks for project id"); + } + } + @Override public Map getMembers(Task task) { try { @@ -170,7 +194,7 @@ CREATE TABLE IF NOT EXISTS {0} ( } } - public HashMap listChildrenOf(Long parentTaskId, UmbrellaUser user, boolean showClosed) { + public HashMap listChildrenOf(Long parentTaskId, UmbrellaUser user, boolean showClosed) { try { var tasks = new HashMap(); var query = select(ALL).from(TABLE_TASKS).leftJoin(ID,TABLE_TASKS_USERS,TASK_ID) diff --git a/task/src/main/java/de/srsoftware/umbrella/task/TaskDb.java b/task/src/main/java/de/srsoftware/umbrella/task/TaskDb.java index 89a6ee5..808c1ab 100644 --- a/task/src/main/java/de/srsoftware/umbrella/task/TaskDb.java +++ b/task/src/main/java/de/srsoftware/umbrella/task/TaskDb.java @@ -15,11 +15,13 @@ public interface TaskDb { void delete(Task task) throws UmbrellaException; void dropMember(long projectId, long userId); + HashMap find(long userId, List keys, boolean fulltext); Map getMembers(Task task); HashMap listChildrenOf(Long parentTaskId, UmbrellaUser user, boolean showClosed); HashMap listProjectTasks(Long projectId, Long parentTaskId, boolean noIndex) throws UmbrellaException; HashMap listRootTasks(Long projectId, UmbrellaUser user, boolean showClosed); HashMap listTasks(Collection projectIds) throws UmbrellaException; + List listUserTasks(long userId, Long limit, long offset, boolean showClosed); Task load(long taskId) throws UmbrellaException; 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 e1fec80..d09e853 100644 --- a/task/src/main/java/de/srsoftware/umbrella/task/TaskModule.java +++ b/task/src/main/java/de/srsoftware/umbrella/task/TaskModule.java @@ -135,6 +135,7 @@ public class TaskModule extends BaseHandler implements TaskService { case ADD -> postNewTask(user.get(),ex); case ESTIMATED_TIMES -> estimatedTimes(user.get(),ex); case LIST -> postTaskList(user.get(),ex); + case SEARCH -> postSearch(user.get(),ex); default -> super.doPost(path,ex); }; } catch (UmbrellaException e){ @@ -346,6 +347,15 @@ public class TaskModule extends BaseHandler implements TaskService { return sendContent(ex,loadMembers(task)); } + private boolean postSearch(UmbrellaUser user, HttpExchange ex) throws IOException { + var json = json(ex); + if (!(json.has(KEY) && json.get(KEY) instanceof String key)) throw missingFieldException(KEY); + var keys = Arrays.asList(key.split(" ")); + var fulltext = json.has(FULLTEXT) && json.get(FULLTEXT) instanceof Boolean val && val; + var tasks = taskDb.find(user.id(),keys,fulltext); + return sendContent(ex,mapValues(tasks)); + } + private boolean postTaskList(UmbrellaUser user, HttpExchange ex) throws IOException { var json = json(ex); LOG.log(WARNING,"Missing permission check in {0}.postTaskList!",getClass().getSimpleName());