updating kanban on

* task creation
* task update
* task deletion
This commit is contained in:
2025-12-20 13:51:06 +01:00
parent 78cae4644d
commit 711addd75c
4 changed files with 62 additions and 33 deletions

View File

@@ -103,20 +103,40 @@
}
}
function handleUpdateEvent(evt){
function handleCreateEvent(evt){
handleEvent(evt,'create');
}
function handleEvent(evt,method){
let json = JSON.parse(evt.data);
if (json.task && json.user){
// drop from kanban
for (let uid in tasks){
if (!uid) continue;
for (let state in tasks[uid]) delete tasks[uid][state][json.task.id];
}
processTask(json.task);
// (re) add to kanban
if (method != 'delete') processTask(json.task);
// show notification
if (json.user.id != user.id) {
info = t("user_updated_entity",{user:json.user.name,entity:json.task.name});
let term = "user_updated_entity";
if (method == 'create') term = "user_created_entity";
if (method == 'delete') term = "user_deleted_entity";
info = t(term,{user:json.user.name,entity:json.task.name});
setTimeout(() => { info = null; },2500);
}
}
}
function handleDeleteEvent(evt){
console.log('delete task');
handleEvent(evt,'delete');
}
function handleUpdateEvent(evt){
handleEvent(evt,'update');
}
function hover(ev,user_id,state){
@@ -135,7 +155,7 @@
async function load(){
try {
eventSource = eventStream(handleUpdateEvent);
eventSource = eventStream(handleCreateEvent,handleUpdateEvent,handleDeleteEvent);
await loadProject();
loadTasks({project_id:+id,parent_task_id:0});
} catch (ignored) {}

View File

@@ -15,9 +15,11 @@ export function drop(url){
});
}
export function eventStream(updateHandler){
export function eventStream(createHandler,updateHandler,deleteHandler){
const es = new EventSource(api('bus'), {withCredentials: true});
if (createHandler) es.addEventListener('CREATE', createHandler);
if (updateHandler) es.addEventListener('UPDATE', updateHandler);
if (deleteHandler) es.addEventListener('DELETE', deleteHandler);
return es;
}

View File

@@ -11,6 +11,7 @@ import static de.srsoftware.umbrella.core.Util.mapValues;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*;
import static de.srsoftware.umbrella.core.model.Permission.*;
import static de.srsoftware.umbrella.core.model.Permission.OWNER;
import static de.srsoftware.umbrella.messagebus.Event.EventType.CREATE;
import static de.srsoftware.umbrella.messagebus.Event.EventType.UPDATE;
import static de.srsoftware.umbrella.messagebus.MessageBus.messageBus;
import static de.srsoftware.umbrella.project.Constants.PERMISSIONS;
@@ -31,6 +32,7 @@ import de.srsoftware.umbrella.core.model.*;
import de.srsoftware.umbrella.core.model.Task;
import de.srsoftware.umbrella.core.model.Token;
import de.srsoftware.umbrella.core.model.UmbrellaUser;
import de.srsoftware.umbrella.messagebus.Event;
import de.srsoftware.umbrella.messagebus.TaskEvent;
import java.io.IOException;
import java.util.*;
@@ -40,6 +42,22 @@ import org.json.JSONObject;
public class TaskModule extends BaseHandler implements TaskService {
private static class TaggedTask extends Task{
private final Collection<String> tags;
public TaggedTask(Task task, Collection<String> tags) {
super(task.id(), task.projectId(), task.parentTaskId(), task.name(), task.description(), task.status(), task.estimatedTime(), task.start(), task.dueDate(), task.showClosed(), task.noIndex(), task.members(), task.priority());
this.tags = tags;
}
@Override
public Map<String, Object> toMap() {
var map = super.toMap();
map.put(TAGS,tags);
return map;
}
}
private final TaskDb taskDb;
public TaskModule(Configuration config) throws UmbrellaException {
@@ -63,6 +81,7 @@ public class TaskModule extends BaseHandler implements TaskService {
taskDb.delete(task);
noteService().deleteEntity(TASK, "" + taskId);
tagService().deleteEntity(TASK, taskId);
messageBus().dispatch(new TaskEvent(user,task,Event.EventType.DELETE));
return sendContent(ex, Map.of(DELETED, taskId));
}
@@ -261,6 +280,16 @@ public class TaskModule extends BaseHandler implements TaskService {
return taskList;
}
private boolean newParentIsSubtask(Task task, long newParent) {
var parent = taskDb.load(newParent);
while (parent != null) {
if (task.id() == parent.id()) return true;
if (parent.parentTaskId() == null) break;
parent = taskDb.load(parent.parentTaskId());
}
return false;
}
private Map<String, Object> placeInTree(Task task, HashMap<Long, Map<String, Object>> taskTree, Map<Long, Task> taskMap) {
var mappedTask = task.toMap();
if (task.parentTaskId() != null) {
@@ -319,16 +348,6 @@ public class TaskModule extends BaseHandler implements TaskService {
return sendContent(ex, task);
}
private boolean newParentIsSubtask(Task task, long newParent) {
var parent = taskDb.load(newParent);
while (parent != null) {
if (task.id() == parent.id()) return true;
if (parent.parentTaskId() == null) break;
parent = taskDb.load(parent.parentTaskId());
}
return false;
}
private boolean postNewTask(UmbrellaUser user, HttpExchange ex) throws IOException {
var json = json(ex);
if (!(json.has(PROJECT_ID) && json.get(PROJECT_ID) instanceof Number pid)) throw missingFieldException(PROJECT_ID);
@@ -385,7 +404,10 @@ public class TaskModule extends BaseHandler implements TaskService {
if ((tagList == null || tagList.isEmpty()) && parentTask != null) tagList = tagService().getTags(TASK, parentTask.id(), user);
if ((tagList == null || tagList.isEmpty())) tagList = tagService().getTags(PROJECT, projectId, user);
if (tagList != null && !tagList.isEmpty()) tagService().save(TASK, task.id(), null, tagList);
return sendContent(ex, loadMembers(task));
task = loadMembers(task);
messageBus().dispatch(new TaskEvent(user,new TaggedTask(task,tagList), CREATE));
return sendContent(ex, task);
}
private boolean postSearch(UmbrellaUser user, HttpExchange ex) throws IOException {
@@ -424,23 +446,6 @@ public class TaskModule extends BaseHandler implements TaskService {
return sendEmptyResponse(HTTP_NOT_IMPLEMENTED, ex);
}
private static class TaggedTask extends Task{
private final Collection<String> tags;
public TaggedTask(Task task, Collection<String> tags) {
super(task.id(), task.projectId(), task.parentTaskId(), task.name(), task.description(), task.status(), task.estimatedTime(), task.start(), task.dueDate(), task.showClosed(), task.noIndex(), task.members(), task.priority());
this.tags = tags;
}
@Override
public Map<String, Object> toMap() {
var map = super.toMap();
map.put(TAGS,tags);
return map;
}
}
private Map<Long, Task> addTags(Map<Long, Task> taskList, Map<Long, ? extends Collection<String>> tags) {
return taskList.values().stream().map(task -> new TaggedTask(task, tags.get(task.id()))).collect(Collectors.toMap(Task::id, t -> t));
}

View File

@@ -343,6 +343,8 @@
"user_list": "Benutzer-Liste",
"user_module" : "Umbrella User-Verwaltung",
"users": "Benutzer",
"user_created_entity": "{user} hat \"{entity}\" angelegt",
"user_deleted_entity": "{user} hat \"{entity}\" gelöscht",
"user_updated_entity": "{user} hat \"{entity}\" bearbeitet",
"website": "Website",