working on task update by event

This commit is contained in:
2025-12-20 17:09:06 +01:00
parent f6813d8a75
commit 18c7965b2e
13 changed files with 67 additions and 25 deletions

View File

@@ -1,6 +1,8 @@
/* © SRSoftware 2025 */ /* © SRSoftware 2025 */
package de.srsoftware.umbrella.messagebus; package de.srsoftware.umbrella.messagebus;
import de.srsoftware.umbrella.messagebus.events.Event;
public interface EventListener { public interface EventListener {
void onEvent(Event event); void onEvent(Event event);
} }

View File

@@ -1,6 +1,8 @@
/* © SRSoftware 2025 */ /* © SRSoftware 2025 */
package de.srsoftware.umbrella.messagebus; package de.srsoftware.umbrella.messagebus;
import de.srsoftware.umbrella.messagebus.events.Event;
import static de.srsoftware.umbrella.messagebus.MessageBus.messageBus; import static de.srsoftware.umbrella.messagebus.MessageBus.messageBus;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;

View File

@@ -14,6 +14,8 @@ import de.srsoftware.tools.SessionToken;
import de.srsoftware.umbrella.core.BaseHandler; import de.srsoftware.umbrella.core.BaseHandler;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException; import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.core.model.Token; import de.srsoftware.umbrella.core.model.Token;
import de.srsoftware.umbrella.messagebus.events.Event;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;

View File

@@ -1,6 +1,8 @@
/* © SRSoftware 2025 */ /* © SRSoftware 2025 */
package de.srsoftware.umbrella.messagebus; package de.srsoftware.umbrella.messagebus;
import de.srsoftware.umbrella.messagebus.events.Event;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;

View File

@@ -1,5 +1,5 @@
/* © SRSoftware 2025 */ /* © SRSoftware 2025 */
package de.srsoftware.umbrella.messagebus; package de.srsoftware.umbrella.messagebus.events;
import static de.srsoftware.umbrella.core.Constants.USER; import static de.srsoftware.umbrella.core.Constants.USER;

View File

@@ -0,0 +1,24 @@
/* © SRSoftware 2025 */
package de.srsoftware.umbrella.messagebus.events;
import de.srsoftware.umbrella.core.model.Project;
import de.srsoftware.umbrella.core.model.Task;
import de.srsoftware.umbrella.core.model.UmbrellaUser;
import static de.srsoftware.umbrella.core.Constants.PROJECT;
import static de.srsoftware.umbrella.core.Constants.TASK;
public class ProjectEvent extends Event<Project>{
public ProjectEvent(UmbrellaUser initiator, Project project, EventType type){
super(initiator, PROJECT, project, type);
}
@Override
public boolean isIntendedFor(UmbrellaUser user) {
for (var member : payload().members().values()){
if (member.user().equals(user)) return true;
}
return false;
}
}

View File

@@ -1,5 +1,5 @@
/* © SRSoftware 2025 */ /* © SRSoftware 2025 */
package de.srsoftware.umbrella.messagebus; package de.srsoftware.umbrella.messagebus.events;
import static de.srsoftware.umbrella.core.Constants.TASK; import static de.srsoftware.umbrella.core.Constants.TASK;

View File

@@ -116,6 +116,6 @@
</div> </div>
{/if} {/if}
{:else} {:else}
<svelte:element this={type} {onclick} {oncontextmenu} class={{editable}} title={t('right_click_to_edit')} >{@html target(editValue.rendered)}</svelte:element> <svelte:element this={type} {onclick} {oncontextmenu} class={{editable}} title={t('right_click_to_edit')} >{@html target(value.rendered)}</svelte:element>
{/if} {/if}
</div> </div>

View File

@@ -14,7 +14,7 @@
import Tags from '../tags/TagList.svelte'; import Tags from '../tags/TagList.svelte';
import TaskList from '../task/TaskList.svelte'; import TaskList from '../task/TaskList.svelte';
let eventSource = null; let eventSource = $state(null);
let { id } = $props(); let { id } = $props();
let lastEvent = $state(null); let lastEvent = $state(null);
let estimated_time = $state({sum:0}); let estimated_time = $state({sum:0});
@@ -98,6 +98,7 @@
let json = JSON.parse(evt.data); let json = JSON.parse(evt.data);
json.event = 'update'; json.event = 'update';
lastEvent = json; lastEvent = json;
if (json.project && json.project.id == project.id) project = json.project;
} }
function kanban(){ function kanban(){
@@ -303,7 +304,7 @@
</div> </div>
<div class="tasks"> <div class="tasks">
{#if tasks} {#if tasks}
<TaskList {tasks} {estimated_time} {lastEvent} states={project?.allowed_states} show_closed={show_closed || project.show_closed} /> <TaskList {tasks} {estimated_time} {lastEvent} {eventSource} states={project?.allowed_states} show_closed={show_closed || project.show_closed} />
{/if} {/if}
</div> </div>
</div> </div>

View File

@@ -1,8 +1,8 @@
<script> <script>
import { onDestroy, onMount } from 'svelte'; import { onDestroy } from 'svelte';
import { useTinyRouter } from 'svelte-tiny-router'; import { useTinyRouter } from 'svelte-tiny-router';
import { api, eventStream } from '../../urls.svelte'; import { api, eventStream } from '../../urls.svelte';
import { error, yikes } from '../../warn.svelte'; import { error, yikes } from '../../warn.svelte';
import { t } from '../../translations.svelte'; import { t } from '../../translations.svelte';
import { timetrack } from '../../user.svelte.js'; import { timetrack } from '../../user.svelte.js';
@@ -17,7 +17,7 @@
import TagList from '../tags/TagList.svelte'; import TagList from '../tags/TagList.svelte';
import TaskList from './TaskList.svelte'; import TaskList from './TaskList.svelte';
let eventSource = null; let eventSource = $state(null);
let { id } = $props(); let { id } = $props();
let children = $state(null); let children = $state(null);
let dummy = $derived(updateOn(id)); let dummy = $derived(updateOn(id));
@@ -28,7 +28,10 @@
let show_closed = $state(false); let show_closed = $state(false);
let task = $state(null); let task = $state(null);
$effect(() => updateOn(id)); $effect(() => {
if (!eventSource) eventSource = eventStream(null,handleUpdateEvent,null);
updateOn(id)
});
function addChild(){ function addChild(){
router.navigate(`/task/${id}/add_subtask`); router.navigate(`/task/${id}/add_subtask`);
@@ -83,16 +86,15 @@
router.navigate(`/project/${project.id}/view`) router.navigate(`/project/${project.id}/view`)
} }
function handleUpdateEvent(evt){ function handleUpdateEvent(evt){
let json = JSON.parse(evt.data); let json = JSON.parse(evt.data);
if (json.task && json.task.id == id) updateOn(id); if (json.task) {
} if (json.task.id == id) updateOn(id);
if (json.task.parent_task_id == id) children[json.task.id] = json.task;
}
}
function load(){ async function loadChildren(){
eventSource = eventStream(null,handleUpdateEvent,null);
}
async function loadChildren(){
const url = api('task/list'); const url = api('task/list');
const data = { const data = {
parent_task_id : +task.id, parent_task_id : +task.id,
@@ -204,7 +206,6 @@
onDestroy(() => { onDestroy(() => {
if (eventSource) eventSource.close(); if (eventSource) eventSource.close();
}); });
onMount(load);
</script> </script>
<svelte:head> <svelte:head>
@@ -319,7 +320,7 @@
</div> </div>
<div class="children"> <div class="children">
{#if children} {#if children}
<TaskList states={project?.allowed_states} tasks={children} {estimated_time} show_closed={task.show_closed} /> <TaskList {eventSource} states={project?.allowed_states} tasks={children} {estimated_time} show_closed={task.show_closed} />
{/if} {/if}
</div> </div>

View File

@@ -1,5 +1,6 @@
description = "Umbrella : Projects" description = "Umbrella : Projects"
dependencies{ dependencies{
implementation(project(":bus"))
implementation(project(":core")) implementation(project(":core"))
} }

View File

@@ -12,6 +12,8 @@ import static de.srsoftware.umbrella.core.model.Permission.*;
import static de.srsoftware.umbrella.core.model.Permission.OWNER; import static de.srsoftware.umbrella.core.model.Permission.OWNER;
import static de.srsoftware.umbrella.core.model.Status.OPEN; import static de.srsoftware.umbrella.core.model.Status.OPEN;
import static de.srsoftware.umbrella.core.model.Status.PREDEFINED; import static de.srsoftware.umbrella.core.model.Status.PREDEFINED;
import static de.srsoftware.umbrella.messagebus.MessageBus.messageBus;
import static de.srsoftware.umbrella.messagebus.events.Event.EventType.UPDATE;
import static de.srsoftware.umbrella.project.Constants.CONFIG_DATABASE; import static de.srsoftware.umbrella.project.Constants.CONFIG_DATABASE;
import static java.lang.Boolean.TRUE; import static java.lang.Boolean.TRUE;
import static java.net.HttpURLConnection.HTTP_BAD_REQUEST; import static java.net.HttpURLConnection.HTTP_BAD_REQUEST;
@@ -27,6 +29,10 @@ import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.core.model.*; import de.srsoftware.umbrella.core.model.*;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.*;
import de.srsoftware.umbrella.messagebus.events.Event;
import de.srsoftware.umbrella.messagebus.events.ProjectEvent;
import de.srsoftware.umbrella.messagebus.events.TaskEvent;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;
@@ -211,7 +217,8 @@ public class ProjectModule extends BaseHandler implements ProjectService {
if (json.has(MEMBERS) && json.get(MEMBERS) instanceof JSONObject memberJson) patchMembers(project,memberJson); if (json.has(MEMBERS) && json.get(MEMBERS) instanceof JSONObject memberJson) patchMembers(project,memberJson);
if (json.has(NEW_MEMBER) && json.get(NEW_MEMBER) instanceof Number num) addMember(project,num.longValue()); if (json.has(NEW_MEMBER) && json.get(NEW_MEMBER) instanceof Number num) addMember(project,num.longValue());
projectDb.save(project.patch(json), user); project = projectDb.save(project.patch(json), user);
messageBus().dispatch(new ProjectEvent(user,project, UPDATE));
return sendContent(ex,project.toMap()); return sendContent(ex,project.toMap());
} }

View File

@@ -11,8 +11,8 @@ import static de.srsoftware.umbrella.core.Util.mapValues;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*; import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*;
import static de.srsoftware.umbrella.core.model.Permission.*; import static de.srsoftware.umbrella.core.model.Permission.*;
import static de.srsoftware.umbrella.core.model.Permission.OWNER; import static de.srsoftware.umbrella.core.model.Permission.OWNER;
import static de.srsoftware.umbrella.messagebus.Event.EventType.CREATE; import static de.srsoftware.umbrella.messagebus.events.Event.EventType.CREATE;
import static de.srsoftware.umbrella.messagebus.Event.EventType.UPDATE; import static de.srsoftware.umbrella.messagebus.events.Event.EventType.UPDATE;
import static de.srsoftware.umbrella.messagebus.MessageBus.messageBus; import static de.srsoftware.umbrella.messagebus.MessageBus.messageBus;
import static de.srsoftware.umbrella.project.Constants.PERMISSIONS; import static de.srsoftware.umbrella.project.Constants.PERMISSIONS;
import static de.srsoftware.umbrella.task.Constants.*; import static de.srsoftware.umbrella.task.Constants.*;
@@ -32,8 +32,8 @@ import de.srsoftware.umbrella.core.model.*;
import de.srsoftware.umbrella.core.model.Task; import de.srsoftware.umbrella.core.model.Task;
import de.srsoftware.umbrella.core.model.Token; import de.srsoftware.umbrella.core.model.Token;
import de.srsoftware.umbrella.core.model.UmbrellaUser; import de.srsoftware.umbrella.core.model.UmbrellaUser;
import de.srsoftware.umbrella.messagebus.Event; import de.srsoftware.umbrella.messagebus.events.Event;
import de.srsoftware.umbrella.messagebus.TaskEvent; import de.srsoftware.umbrella.messagebus.events.TaskEvent;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;