working on meaningfull messages for task and project related events

Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
2026-01-19 21:09:25 +01:00
parent be8f21c734
commit a8d1b376a2
11 changed files with 148 additions and 32 deletions

View File

@@ -18,6 +18,7 @@ public abstract class Event<Payload extends Mappable> {
public enum EventType {
CREATE,
MEMBER_ADDED,
UPDATE,
DELETE;
}
@@ -59,7 +60,7 @@ public abstract class Event<Payload extends Mappable> {
}
public Optional<String> diff(){
return oldData == null ? empty() : of(Diff.MapDiff.diff(dropMarkdown(oldData),dropMarkdown(payload.toMap())));
return oldData == null ? empty() : of(Diff.MapDiff.diff(filter(oldData),filter(payload.toMap())));
}
@@ -67,6 +68,10 @@ public abstract class Event<Payload extends Mappable> {
return eventType;
}
protected Map<String,Object> filter(Map<String,Object> map){
return dropMarkdown(map);
}
public boolean isIntendedFor(UmbrellaUser user){
return audience().contains(user);
}
@@ -93,6 +98,10 @@ public abstract class Event<Payload extends Mappable> {
return module;
}
protected Map<String, Object> oldData() {
return oldData;
}
public Payload payload(){
return payload;
}

View File

@@ -1,23 +1,36 @@
/* © SRSoftware 2025 */
package de.srsoftware.umbrella.messagebus.events;
import static de.srsoftware.umbrella.core.constants.Field.OBJECT;
import static de.srsoftware.umbrella.core.constants.Field.USER;
import static de.srsoftware.umbrella.core.ModuleRegistry.projectService;
import static de.srsoftware.umbrella.core.ModuleRegistry.taskService;
import static de.srsoftware.umbrella.core.constants.Field.*;
import static de.srsoftware.umbrella.core.constants.Module.PROJECT;
import static de.srsoftware.umbrella.core.model.Translatable.t;
import static de.srsoftware.umbrella.messagebus.events.Event.EventType.MEMBER_ADDED;
import de.srsoftware.umbrella.core.constants.Field;
import de.srsoftware.umbrella.core.model.*;
import java.util.Collection;
import java.util.List;
import java.util.Map;
public class ProjectEvent extends Event<Project>{
private UmbrellaUser newMember;
public ProjectEvent(UmbrellaUser initiator, Project project, EventType type){
super(initiator, PROJECT, project, type);
newMember = null;
}
public ProjectEvent(UmbrellaUser initiator, Project project, Map<String, Object> oldData){
super(initiator, PROJECT, project, oldData);
newMember = null;
}
public ProjectEvent(UmbrellaUser initiator, Project project, UmbrellaUser newMember){
super(initiator, PROJECT, project, MEMBER_ADDED);
this.newMember = newMember;
}
@Override
@@ -27,10 +40,30 @@ public class ProjectEvent extends Event<Project>{
@Override
public Translatable describe() {
return diff().map(UnTranslatable::new).map(Translatable.class::cast)
.orElseGet(() -> t("[TODO: {object}.describe]",OBJECT,this.getClass().getSimpleName()));
return switch (eventType()){
case CREATE -> describeCreate();
case DELETE -> t("The project '{project}' has been deleted by {user}", Field.PROJECT, payload().name(), USER, initiator().name());
case MEMBER_ADDED -> describeMemberAdded();
case UPDATE -> describeUpdate();
};
}
private Translatable describeCreate() {
var head = t("You have been added to the new project '{project}', created by {user}':\n\n{body}", Field.PROJECT, payload().name(), BODY, payload().description(), USER, initiator().name());
return t("{head}\n\n{link}","head",head,"link",link());
}
private Translatable describeMemberAdded() {
var head = t("'{name}' has been added to '{project}' by '{user}'.",NAME,newMember.name(),Field.PROJECT,payload().name(),USER,initiator().name());
return t("{head}\n\n{link}","head",head,"link",link());
}
private Translatable describeUpdate() {
var head = t("Changes in project '{project}':\n\n{body}",Field.PROJECT,payload().name(),BODY,diff().orElse(""));
return t("{head}\n\n{link}","head",head,"link",link());
}
@Override
public boolean isIntendedFor(UmbrellaUser user) {
for (var member : payload().members().values()){
@@ -39,8 +72,13 @@ public class ProjectEvent extends Event<Project>{
return false;
}
private Translatable link() {
return t("You can view/edit this project at {base_url}/project/{id}/view",ID,payload().id());
}
@Override
public Translatable subject() {
return t("{user} edited {object}",USER,initiator(),OBJECT,payload());
return t("{user} edited {object}",USER,initiator(),OBJECT,payload().name());
}
}

View File

@@ -7,6 +7,7 @@ import static de.srsoftware.umbrella.core.ModuleRegistry.taskService;
import static de.srsoftware.umbrella.core.constants.Field.*;
import static de.srsoftware.umbrella.core.constants.Module.TASK;
import static de.srsoftware.umbrella.core.model.Translatable.t;
import static de.srsoftware.umbrella.messagebus.events.Event.EventType.MEMBER_ADDED;
import de.srsoftware.umbrella.core.ModuleRegistry;
import de.srsoftware.umbrella.core.constants.Field;
@@ -17,12 +18,21 @@ import java.util.Map;
public class TaskEvent extends Event<Task>{
private final UmbrellaUser newMember;
public TaskEvent(UmbrellaUser initiator, Task task, EventType type){
super(initiator, TASK, task, type);
newMember = null;
}
public TaskEvent(UmbrellaUser initiator, Task task, Map<String, Object> oldData){
super(initiator, TASK, task, oldData);
newMember = null;
}
public TaskEvent(UmbrellaUser initiator, Task task, UmbrellaUser newMember) {
super(initiator, TASK, task, MEMBER_ADDED);
this.newMember = newMember;
}
@Override
@@ -33,25 +43,45 @@ public class TaskEvent extends Event<Task>{
@Override
public Translatable describe() {
return switch (eventType()){
case CREATE -> {
String parentName = null;
var pid = payload().parentTaskId();
if (pid != null) {
var parent = taskService().load(List.of(pid)).get(pid);
if (parent != null) parentName = parent.name();
}
if (parentName == null){
var project = projectService().load(payload().projectId());
if (project != null) parentName = project.name();
}
if (parentName == null) parentName = "?";
yield t("'{task}' has been added to '{object}':\n\n{body}", Field.TASK, payload().name(), OBJECT, parentName, BODY, payload().description());
}
case CREATE -> describeCreate();
case DELETE -> t("The task '{task}' has been deleted by {user}",Field.TASK, payload().name(), USER, initiator().name());
case UPDATE -> t("Changes in task '{task}':\n\n{body}",Field.TASK,payload().name(),BODY,diff().orElse(""));
case MEMBER_ADDED -> describeMemberAdded();
case UPDATE -> describeUpdate();
};
}
private Translatable describeMemberAdded() {
var head = t("'{name}' has been added to '{task}' by '{user}'.",NAME,newMember.name(),Field.TASK,payload().name(),USER,initiator().name());
return t("{head}\n\n{link}","head",head,"link",link());
}
private Translatable describeCreate() {
String parentName = null;
var pid = payload().parentTaskId();
if (pid != null) {
var parent = taskService().load(List.of(pid)).get(pid);
if (parent != null) parentName = parent.name();
}
if (parentName == null){
var project = projectService().load(payload().projectId());
if (project != null) parentName = project.name();
}
if (parentName == null) parentName = "?";
var head = t("'{task}' has been added to '{object}':\n\n{body}", Field.TASK, payload().name(), OBJECT, parentName, BODY, payload().description());
return t("{head}\n\n{link}","head",head,"link",link());
}
private Translatable describeUpdate() {
var head = t("Changes in task '{task}':\n\n{body}",Field.TASK,payload().name(),BODY,diff().orElse(""));
return t("{head}\n\n{link}","head",head,"link",link());
}
@Override
protected Map<String, Object> filter(Map<String, Object> map) {
map.remove(MEMBERS);
return super.filter(map);
}
@Override
public boolean isIntendedFor(UmbrellaUser user) {
for (var member : payload().members().values()){
@@ -60,11 +90,15 @@ public class TaskEvent extends Event<Task>{
return false;
}
private Translatable link() {
return t("You can view/edit this task at {base_url}/task/{id}/view",ID,payload().id());
}
@Override
public Translatable subject() {
return switch (eventType()){
case CREATE -> t("The task '{task}' has been created", Field.TASK, payload().name());
case DELETE -> t("The task '{task}' has been deleted",Field.TASK, payload().name());
case UPDATE -> t("Task '{task} was edited",Field.TASK,payload().name());
case MEMBER_ADDED, UPDATE -> t("Task '{task}' was edited",Field.TASK,payload().name());
};
}}