diff --git a/core/src/main/java/de/srsoftware/umbrella/core/api/TagService.java b/core/src/main/java/de/srsoftware/umbrella/core/api/TagService.java index 8afc1d3..4bb15ec 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/api/TagService.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/api/TagService.java @@ -4,12 +4,23 @@ package de.srsoftware.umbrella.core.api; import de.srsoftware.umbrella.core.exceptions.UmbrellaException; import de.srsoftware.umbrella.core.model.UmbrellaUser; import java.util.Collection; +import java.util.Map; public interface TagService { void deleteEntity(String task, long taskId); Collection getTags(String module, long entityId, UmbrellaUser user) throws UmbrellaException; + /** + * Loads the tags for all the entities denominated by the collection entityIds. + * @param module the realm the entities belong to + * @param entityIds the set of entities of the respective realm + * @param user the user, for whom the tags shall be loaded + * @return a map from entity ids to assigned tags + * @throws UmbrellaException + */ + Map> getTags(String module, Collection entityIds, UmbrellaUser user) throws UmbrellaException; + void save(String module, long entityId, Collection userIds, Collection tags); String save(String module, long entityId, Collection userIds, String tag); diff --git a/tags/src/main/java/de/srsoftware/umbrella/tags/SqliteDb.java b/tags/src/main/java/de/srsoftware/umbrella/tags/SqliteDb.java index 9ca1138..a2a0651 100644 --- a/tags/src/main/java/de/srsoftware/umbrella/tags/SqliteDb.java +++ b/tags/src/main/java/de/srsoftware/umbrella/tags/SqliteDb.java @@ -253,8 +253,13 @@ CREATE TABLE IF NOT EXISTS {0} ( public Set list(long userId, String module, long entityId) { try { var tags = new HashSet(); + + // load tags assigned to user var rs = select(TAG).from(TABLE_TAGS).where(MODULE,equal(module)).where(ENTITY_ID,equal(entityId)).where(USER_ID,equal(userId)).exec(db); while (rs.next()) tags.add(rs.getString(1)); + rs.close(); + + // load tags assigned to no user rs = select(TAG).from(TABLE_TAGS).where(MODULE,equal(module)).where(ENTITY_ID,equal(entityId)).where(USER_ID,isNull()).exec(db); while (rs.next()) tags.add(rs.getString(1)); rs.close(); @@ -264,6 +269,26 @@ CREATE TABLE IF NOT EXISTS {0} ( } } + @Override + public Map> list(long userId, String module, Collection entityIds) { + try { + var tags = new HashMap>(); + + // load tags assigned to user + var rs = select(ENTITY_ID,TAG).from(TABLE_TAGS).where(MODULE,equal(module)).where(ENTITY_ID,in(entityIds.toArray())).where(USER_ID,equal(userId)).exec(db); + while (rs.next()) tags.computeIfAbsent(rs.getLong(ENTITY_ID), k -> new HashSet<>()).add(rs.getString(TAG)); + rs.close(); + + // load tags assigned to no user + rs = select(TAG).from(TABLE_TAGS).where(MODULE,equal(module)).where(ENTITY_ID,in(entityIds.toArray())).where(USER_ID,isNull()).exec(db); + while (rs.next()) tags.computeIfAbsent(rs.getLong(ENTITY_ID), k -> new HashSet<>()).add(rs.getString(TAG)); + rs.close(); + return tags; + } catch (SQLException e) { + throw new UmbrellaException("Failed to load tags"); + } + } + @Override public void save(Collection userIds, String module, long entityId, Collection tags) { try { diff --git a/tags/src/main/java/de/srsoftware/umbrella/tags/TagDB.java b/tags/src/main/java/de/srsoftware/umbrella/tags/TagDB.java index 0f5aa6b..a04f89c 100644 --- a/tags/src/main/java/de/srsoftware/umbrella/tags/TagDB.java +++ b/tags/src/main/java/de/srsoftware/umbrella/tags/TagDB.java @@ -1,6 +1,8 @@ /* © SRSoftware 2025 */ package de.srsoftware.umbrella.tags; +import de.srsoftware.umbrella.core.exceptions.UmbrellaException; + import java.util.Collection; import java.util.List; import java.util.Map; @@ -15,8 +17,16 @@ public interface TagDB { Set list(long userId, String module, long entityId); + /** + * Loads the tags for all the entities denominated by the collection entityIds. + * @param module the realm the entities belong to + * @param entityIds the set of entities of the respective realm + * @param userId the id of the user, for whom the tags shall be loaded + * @return a map from entity ids to assigned tags + */ + Map> list(long userId, String module, Collection entityIds); + void save(Collection userIds, String module, long entityId, Collection tags); void updateId(String module, Object oldId, Object newId); - } diff --git a/tags/src/main/java/de/srsoftware/umbrella/tags/TagModule.java b/tags/src/main/java/de/srsoftware/umbrella/tags/TagModule.java index 2019d67..07277bf 100644 --- a/tags/src/main/java/de/srsoftware/umbrella/tags/TagModule.java +++ b/tags/src/main/java/de/srsoftware/umbrella/tags/TagModule.java @@ -121,6 +121,11 @@ public class TagModule extends BaseHandler implements TagService { return tagDb.list(user.id(),module,entityId); } + @Override + public Map> getTags(String module, Collection entityIds, UmbrellaUser user) throws UmbrellaException { + return tagDb.list(user.id(),module,entityIds); + } + @Override public void save(String module, long entityId, Collection userIds, Collection tags) { tagDb.save(userIds,module,entityId,tags); 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 479fab6..fc42b79 100644 --- a/task/src/main/java/de/srsoftware/umbrella/task/TaskModule.java +++ b/task/src/main/java/de/srsoftware/umbrella/task/TaskModule.java @@ -13,6 +13,7 @@ import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*; import static de.srsoftware.umbrella.core.model.Permission.*; import static de.srsoftware.umbrella.project.Constants.PERMISSIONS; import static de.srsoftware.umbrella.task.Constants.*; +import static java.lang.System.Logger.Level.DEBUG; import static java.lang.System.Logger.Level.WARNING; import static java.net.HttpURLConnection.HTTP_BAD_REQUEST; @@ -385,14 +386,22 @@ public class TaskModule extends BaseHandler implements TaskService { private boolean postTaskList(UmbrellaUser user, HttpExchange ex) throws IOException { var json = json(ex); LOG.log(WARNING, "Missing permission check in {0}.postTaskList!", getClass().getSimpleName()); - var showClosed = json.has(SHOW_CLOSED) && json.get(SHOW_CLOSED) instanceof Boolean bool ? bool : false; - 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 showClosed = json.has(SHOW_CLOSED) && json.get(SHOW_CLOSED) instanceof Boolean bool ? bool : false; + 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; if (isSet(projectId)) { - if (parentTaskId == null) return sendContent(ex, mapValues(taskDb.listRootTasks(projectId, user, showClosed))); + if (parentTaskId == null) { + var list = taskDb.listRootTasks(projectId, user, showClosed); + return sendContent(ex, mapValues(list)); + } var projectTasks = taskDb.listProjectTasks(projectId, parentTaskId, noIndex); loadMembers(projectTasks.values()); + var tags = tagService().getTags(TASK,projectTasks.keySet(),user); + LOG.log(DEBUG,"tags: {0}",tags); + + // TODO: add tags to result map + return sendContent(ex, mapValues(projectTasks)); } if (isSet(parentTaskId)) return sendContent(ex, mapValues(taskDb.listChildrenOf(parentTaskId, user, showClosed)));