Merge branch 'kanban'
Some checks failed
Build Docker Image / Docker-Build (push) Failing after 1m59s
Build Docker Image / Clean-Registry (push) Successful in -6s

This commit is contained in:
2026-03-11 22:28:33 +01:00
3 changed files with 33 additions and 39 deletions

View File

@@ -228,8 +228,7 @@ public class Task implements Mappable {
return tags;
}
@Override
public Map<String, Object> toMap() {
public Map<String,Object> toMap(boolean renderMarkdown){
var map = new HashMap<String,Object>();
var memberMap = new HashMap<Long,Map<String,Object>>();
if (members != null) for (var entry : members.entrySet()){
@@ -240,7 +239,7 @@ public class Task implements Mappable {
map.put(PARENT_TASK_ID, parentTaskId);
map.put(PRIORITY,priority);
map.put(NAME, name);
map.put(DESCRIPTION, mapMarkdown(description));
map.put(DESCRIPTION, renderMarkdown ? mapMarkdown(description) : Map.of(SOURCE,description));
map.put(STATUS, status);
map.put(EST_TIME, estimatedTime);
map.put(START_DATE,start);
@@ -254,6 +253,11 @@ public class Task implements Mappable {
return map;
}
@Override
public Map<String, Object> toMap() {
return toMap(true);
}
private int totalPrio() {
if (status >= Status.COMPLETE.code()) return 0; // task is done, do no longer highlight
int total = priority;

View File

@@ -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,8 @@
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)
});
selector.rendered = false;
var resp = await post(url,selector);
if (resp.ok){
var json = await resp.json();
for (var task_id of Object.keys(json)) {
@@ -239,11 +224,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');

View File

@@ -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<Long,Map<String,Object>> mapTasks(Map<Long,Task> 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);
}