From b73fb7c716effda008899eb11844fefd66ee4131 Mon Sep 17 00:00:00 2001 From: Stephan Richter Date: Wed, 11 Mar 2026 18:10:08 +0100 Subject: [PATCH 1/2] simplifying kanban.svelte Signed-off-by: Stephan Richter --- frontend/src/routes/project/Kanban.svelte | 36 +++++------------------ 1 file changed, 8 insertions(+), 28 deletions(-) diff --git a/frontend/src/routes/project/Kanban.svelte b/frontend/src/routes/project/Kanban.svelte index 76fcf8eb..c43bda5d 100644 --- a/frontend/src/routes/project/Kanban.svelte +++ b/frontend/src/routes/project/Kanban.svelte @@ -2,7 +2,7 @@ import { onDestroy, onMount } from 'svelte'; import { useTinyRouter } from 'svelte-tiny-router'; - import { api, eventStream, target } from '../../urls.svelte.js'; + import { api, patch, post, eventStream, target } from '../../urls.svelte.js'; import { error, messages, yikes } from '../../warn.svelte'; import { t } from '../../translations.svelte.js'; import { user } from '../../user.svelte.js'; @@ -46,11 +46,7 @@ } task.members[user_id] = { permission: { name : 'ASSIGNEE' }}; task.members[user.id] = { permission: { name : 'OWNER' }}; - const resp = await fetch(url,{ - credentials : 'include', - method : 'POST', - body : JSON.stringify(task) - }); + const resp = await post(url,task); if (resp.ok) { task = await resp.json(); task.assignee = user_id; @@ -69,11 +65,7 @@ ex.preventDefault(); var task = dragged; const url = api(`task/${task.id}`); - const resp = await fetch(url,{ - credentials : 'include', - method : 'PATCH', - body : JSON.stringify({no_index:true}) - }); + const resp = await patch(url,{no_index:true}); delete highlight.archive; if (resp.ok){ yikes(); @@ -89,14 +81,10 @@ highlight = {}; if (task.assignee == user_id && task.status == state) return; // no change - let patch = {members:{},status:+state} - patch.members[user_id] = 'ASSIGNEE'; + let data = {members:{},status:+state} + data.members[user_id] = 'ASSIGNEE'; const url = api(`task/${task.id}`); - const resp = await fetch(url,{ - credentials : 'include', - method : 'PATCH', - body : JSON.stringify(patch) - }); + const resp = await patch(url,data); if (resp.ok){ yikes(); } else { @@ -190,11 +178,7 @@ const url = api('task/list'); selector.show_closed = true; selector.no_index = true; - var resp = await fetch(url,{ - credentials :'include', - method : 'POST', - body : JSON.stringify(selector) - }); + var resp = await post(url,selector); if (resp.ok){ var json = await resp.json(); for (var task_id of Object.keys(json)) { @@ -239,11 +223,7 @@ share : user_ids } const url = api('bookmark'); - const resp = await fetch(url,{ - credentials : 'include', - method : 'POST', - body : JSON.stringify(data) - }); + const resp = await post(url,data); if (resp.ok) { yikes(); router.navigate('/bookmark'); From e4a9463307c56c13898ccaa8dc2d1826a13040f0 Mon Sep 17 00:00:00 2001 From: Stephan Richter Date: Wed, 11 Mar 2026 18:26:33 +0100 Subject: [PATCH 2/2] implemented option to list tasks without rendering markdown Signed-off-by: Stephan Richter --- .../srsoftware/umbrella/core/model/Task.java | 20 +++++++++++-------- frontend/src/routes/project/Kanban.svelte | 1 + .../srsoftware/umbrella/task/TaskModule.java | 15 +++++++++++--- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/core/src/main/java/de/srsoftware/umbrella/core/model/Task.java b/core/src/main/java/de/srsoftware/umbrella/core/model/Task.java index ebc04e99..f7ae2a8f 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/model/Task.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/model/Task.java @@ -228,20 +228,19 @@ public class Task implements Mappable { return tags; } - @Override - public Map toMap() { + public Map toMap(boolean renderMarkdown){ var map = new HashMap(); var memberMap = new HashMap>(); if (members != null) for (var entry : members.entrySet()){ memberMap.put(entry.getKey(),entry.getValue().toMap()); } map.put(ID, id); - map.put(PROJECT_ID, projectId); - map.put(PARENT_TASK_ID, parentTaskId); - map.put(PRIORITY,priority); - map.put(NAME, name); - map.put(DESCRIPTION, mapMarkdown(description)); - map.put(STATUS, status); + map.put(PROJECT_ID, projectId); + map.put(PARENT_TASK_ID, parentTaskId); + map.put(PRIORITY,priority); + map.put(NAME, name); + map.put(DESCRIPTION, renderMarkdown ? mapMarkdown(description) : Map.of(SOURCE,description)); + map.put(STATUS, status); map.put(EST_TIME, estimatedTime); map.put(START_DATE,start); map.put(DUE_DATE,dueDate); @@ -254,6 +253,11 @@ public class Task implements Mappable { return map; } + @Override + public Map toMap() { + return toMap(true); + } + private int totalPrio() { if (status >= Status.COMPLETE.code()) return 0; // task is done, do no longer highlight int total = priority; diff --git a/frontend/src/routes/project/Kanban.svelte b/frontend/src/routes/project/Kanban.svelte index c43bda5d..f04f329d 100644 --- a/frontend/src/routes/project/Kanban.svelte +++ b/frontend/src/routes/project/Kanban.svelte @@ -178,6 +178,7 @@ const url = api('task/list'); selector.show_closed = true; selector.no_index = true; + selector.rendered = false; var resp = await post(url,selector); if (resp.ok){ var json = await resp.json(); 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 12902760..6fffe48c 100644 --- a/task/src/main/java/de/srsoftware/umbrella/task/TaskModule.java +++ b/task/src/main/java/de/srsoftware/umbrella/task/TaskModule.java @@ -32,6 +32,7 @@ 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.*; @@ -271,6 +272,12 @@ public class TaskModule extends BaseHandler implements TaskService { return taskList; } + private Map> mapTasks(Map tasks, boolean render){ + if (render) return mapValues(tasks); + return tasks.entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getKey,e -> e.getValue().toMap(false))); + } + private boolean newParentIsSubtask(Task task, long newParent) { var parent = taskDb.load(newParent); while (parent != null) { @@ -422,21 +429,23 @@ public class TaskModule extends BaseHandler implements TaskService { var noIndex = json.has(NO_INDEX) && json.get(NO_INDEX) instanceof Boolean bool ? bool : false; var projectId = json.has(PROJECT_ID) && json.get(PROJECT_ID) instanceof Number number ? number.longValue() : null; var parentTaskId = json.has(PARENT_TASK_ID) && json.get(PARENT_TASK_ID) instanceof Number number ? number.longValue() : null; + var markdown = !json.has(RENDERED) || !(json.get(RENDERED) instanceof Boolean render) || render; if (isSet(projectId)) { if (parentTaskId == null) { var list = taskDb.listRootTasks(projectId, user, showClosed); - return sendContent(ex, mapValues(list)); + return sendContent(ex, mapTasks(list,markdown)); } var projectTasks = taskDb.listProjectTasks(projectId, parentTaskId, noIndex); loadMembers(projectTasks.values()); var tags = tagService().getTags(TASK,projectTasks.keySet(),user); projectTasks = addTags(projectTasks, tags); - return sendContent(ex, mapValues(projectTasks)); + return sendContent(ex, mapTasks(projectTasks, markdown)); } if (isSet(parentTaskId)) return sendContent(ex, mapValues(taskDb.listChildrenOf(parentTaskId, user, showClosed))); var taskIds = json.has(IDS) && json.get(IDS) instanceof JSONArray ids ? ids.toList().stream().map(Object::toString).map(Long::parseLong).toList() : null; - if (isSet(taskIds)) return sendContent(ex, mapValues(taskDb.load(taskIds))); + var tasks = taskDb.load(taskIds); + if (isSet(taskIds)) return sendContent(ex, mapTasks(tasks,markdown)); return sendEmptyResponse(HTTP_NOT_IMPLEMENTED, ex); }