improved tag handling

This commit is contained in:
2025-07-28 14:22:34 +02:00
parent 382eae000c
commit 57b68015c3
6 changed files with 29 additions and 13 deletions

View File

@@ -3,9 +3,7 @@ package de.srsoftware.umbrella.core.api;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException; import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.core.model.UmbrellaUser; import de.srsoftware.umbrella.core.model.UmbrellaUser;
import java.util.Collection; import java.util.Collection;
import java.util.Set;
public interface TagService { public interface TagService {
void deleteEntity(String task, long taskId); void deleteEntity(String task, long taskId);

View File

@@ -9,6 +9,7 @@
import MarkdownEditor from '../../Components/MarkdownEditor.svelte'; import MarkdownEditor from '../../Components/MarkdownEditor.svelte';
import MemberEditor from '../../Components/MemberEditor.svelte'; import MemberEditor from '../../Components/MemberEditor.svelte';
import StateSelector from '../../Components/StateSelector.svelte'; import StateSelector from '../../Components/StateSelector.svelte';
import Tags from '../tags/TagList.svelte';
import TaskList from '../task/TaskList.svelte'; import TaskList from '../task/TaskList.svelte';
let router = useTinyRouter(); let router = useTinyRouter();
@@ -190,6 +191,12 @@
<td class="estimated_time">{estimated_time.sum} h</td> <td class="estimated_time">{estimated_time.sum} h</td>
</tr> </tr>
{/if} {/if}
<tr>
<th>{t('tags')}</th>
<td>
<Tags module="project" {id} user_list={null} />
</td>
</tr>
<tr> <tr>
<th> <th>
{t('tasks')} {t('tasks')}
@@ -203,4 +210,4 @@
</tr> </tr>
</tbody> </tbody>
</table> </table>
{/if} {/if}

View File

@@ -33,6 +33,7 @@
tag = await resp.text(); tag = await resp.text();
tags.push(tag); tags.push(tag);
tags = tags.sort(); tags = tags.sort();
error = null;
} else { } else {
error = await resp.text(); error = await resp.text();
} }

View File

@@ -26,7 +26,6 @@ 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 org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;

View File

@@ -2,8 +2,8 @@
package de.srsoftware.umbrella.tags; package de.srsoftware.umbrella.tags;
import static de.srsoftware.tools.jdbc.Condition.equal; import static de.srsoftware.tools.jdbc.Condition.equal;
import static de.srsoftware.tools.jdbc.Condition.isNull;
import static de.srsoftware.tools.jdbc.Query.*; import static de.srsoftware.tools.jdbc.Query.*;
import static de.srsoftware.tools.jdbc.Query.SelectQuery.ALL;
import static de.srsoftware.umbrella.core.Constants.*; import static de.srsoftware.umbrella.core.Constants.*;
import static de.srsoftware.umbrella.core.Constants.ERROR_FAILED_CREATE_TABLE; import static de.srsoftware.umbrella.core.Constants.ERROR_FAILED_CREATE_TABLE;
import static de.srsoftware.umbrella.core.Constants.USER_ID; import static de.srsoftware.umbrella.core.Constants.USER_ID;
@@ -14,7 +14,6 @@ import static java.text.MessageFormat.format;
import de.srsoftware.tools.jdbc.Query; import de.srsoftware.tools.jdbc.Query;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException; import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import java.sql.Connection; import java.sql.Connection;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Collection; import java.util.Collection;
@@ -72,7 +71,7 @@ CREATE TABLE IF NOT EXISTS "{0}" (
{1} VARCHAR(255) NOT NULL, {1} VARCHAR(255) NOT NULL,
{2} VARCHAR(20) NOT NULL, {2} VARCHAR(20) NOT NULL,
{3} INTEGER NOT NULL, {3} INTEGER NOT NULL,
{4} INTEGER NOT NULL, {4} INTEGER,
PRIMARY KEY ({1}, {2}, {3}, {4}) PRIMARY KEY ({1}, {2}, {3}, {4})
)"""; )""";
try { try {
@@ -91,6 +90,9 @@ CREATE TABLE IF NOT EXISTS "{0}" (
Query.delete().from(TABLE_TAGS) Query.delete().from(TABLE_TAGS)
.where(TAG,equal(tag)).where(MODULE,equal(module)).where(ID,equal(entityId)).where(USER_ID,equal(userId)) .where(TAG,equal(tag)).where(MODULE,equal(module)).where(ID,equal(entityId)).where(USER_ID,equal(userId))
.execute(db); .execute(db);
Query.delete().from(TABLE_TAGS)
.where(TAG,equal(tag)).where(MODULE,equal(module)).where(ID,equal(entityId)).where(USER_ID,isNull())
.execute(db);
return tag; return tag;
} catch (SQLException e){ } catch (SQLException e){
throw new UmbrellaException("Failed to delete tag {0}",tag); throw new UmbrellaException("Failed to delete tag {0}",tag);
@@ -119,6 +121,8 @@ CREATE TABLE IF NOT EXISTS "{0}" (
var tags = new HashSet<String>(); var tags = new HashSet<String>();
var rs = select(TAG).from(TABLE_TAGS).where(MODULE,equal(module)).where(ID,equal(entityId)).where(USER_ID,equal(userId)).exec(db); var rs = select(TAG).from(TABLE_TAGS).where(MODULE,equal(module)).where(ID,equal(entityId)).where(USER_ID,equal(userId)).exec(db);
while (rs.next()) tags.add(rs.getString(1)); while (rs.next()) tags.add(rs.getString(1));
rs = select(TAG).from(TABLE_TAGS).where(MODULE,equal(module)).where(ID,equal(entityId)).where(USER_ID,isNull()).exec(db);
while (rs.next()) tags.add(rs.getString(1));
rs.close(); rs.close();
return tags; return tags;
} catch (SQLException e) { } catch (SQLException e) {

View File

@@ -20,10 +20,9 @@ import de.srsoftware.umbrella.core.api.UserService;
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.core.model.UmbrellaUser; import de.srsoftware.umbrella.core.model.UmbrellaUser;
import org.json.JSONArray;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.*;
import org.json.JSONArray;
public class TagModule extends BaseHandler implements TagService { public class TagModule extends BaseHandler implements TagService {
private final SqliteDb tagDb; private final SqliteDb tagDb;
@@ -98,10 +97,18 @@ public class TagModule extends BaseHandler implements TagService {
long entityId = Long.parseLong(head); long entityId = Long.parseLong(head);
var json = json(ex); var json = json(ex);
if (!(json.has(TAG) && json.get(TAG) instanceof String tag)) throw missingFieldException(TAG); if (!(json.has(TAG) && json.get(TAG) instanceof String tag)) throw missingFieldException(TAG);
List<Long> userList = json.has(USER_LIST) && json.get(USER_LIST) instanceof JSONArray arr ? List<Long> userList = null;
arr.toList().stream().filter(elem -> elem instanceof Number).map(elem -> (Number) elem).map(Number::longValue).toList() if (!json.has(USER_LIST)) throw missingFieldException(USER_LIST);
: List.of(user.get().id()); var ul = json.isNull(USER_LIST) ? null : json.get(USER_LIST);
if (userList.isEmpty()) throw missingFieldException(USER_LIST); if (ul instanceof JSONArray arr){
userList = arr.toList().stream()
.filter(elem -> elem instanceof Number)
.map(Number.class::cast)
.map(Number::longValue)
.toList();
} else if (ul != null) throw unprocessable("User list must be NULL or array of user ids!");
// userList == null → tag is shared with all users
if (userList != null && userList.isEmpty()) throw unprocessable("User list must not be an empty list!");
tag = save(module, entityId, userList, tag); tag = save(module, entityId, userList, tag);
return sendContent(ex, tag); return sendContent(ex, tag);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {