diff --git a/core/src/main/java/de/srsoftware/umbrella/core/Constants.java b/core/src/main/java/de/srsoftware/umbrella/core/Constants.java index 44aa986..eeb501c 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/Constants.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/Constants.java @@ -10,6 +10,7 @@ public class Constants { private Constants(){} public static final String ADDRESS = "address"; + public static final String ALLOWED_STATES = "allowed_states"; public static final String ATTACHMENTS = "attachments"; public static final String AUTHORIZATION = "Authorization"; diff --git a/core/src/main/java/de/srsoftware/umbrella/core/model/Project.java b/core/src/main/java/de/srsoftware/umbrella/core/model/Project.java index b4c4c8a..2fc8397 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/model/Project.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/model/Project.java @@ -4,6 +4,7 @@ package de.srsoftware.umbrella.core.model; import static de.srsoftware.tools.Optionals.nullable; import static de.srsoftware.umbrella.core.Constants.*; import static de.srsoftware.umbrella.core.Util.mapMarkdown; +import static de.srsoftware.umbrella.core.model.Status.PREDEFINED; import de.srsoftware.tools.Mappable; import java.sql.ResultSet; @@ -13,6 +14,7 @@ import org.json.JSONObject; public class Project implements Mappable { private final Map members; + private final Collection allowedStates; private boolean showClosed; private final Long companyId; private int status; @@ -21,7 +23,7 @@ public class Project implements Mappable { private String description; private final Set dirtyFields = new HashSet<>(); - public Project(long id, String name, String description, int status, Long companyId, boolean showClosed, Map members) { + public Project(long id, String name, String description, int status, Long companyId, boolean showClosed, Map members, Collection allowedStates) { this.id = id; this.name = name; this.description = description; @@ -29,6 +31,11 @@ public class Project implements Mappable { this.companyId = companyId; this.showClosed = showClosed; this.members = members; + this.allowedStates = allowedStates; + } + + public Collection allowedStates(){ + return allowedStates; } public Project clean() { @@ -81,7 +88,7 @@ public class Project implements Mappable { public static Project of(ResultSet rs) throws SQLException { var companyId = rs.getLong(COMPANY_ID); - return new Project(rs.getLong(ID),rs.getString(NAME),rs.getString(DESCRIPTION),rs.getInt(STATUS),companyId == 0 ? null : companyId,rs.getBoolean(SHOW_CLOSED),new HashMap<>()); + return new Project(rs.getLong(ID),rs.getString(NAME),rs.getString(DESCRIPTION),rs.getInt(STATUS),companyId == 0 ? null : companyId,rs.getBoolean(SHOW_CLOSED),new HashMap<>(),PREDEFINED); } public Project patch(JSONObject json) { @@ -120,6 +127,9 @@ public class Project implements Mappable { map.put(COMPANY_ID,companyId); map.put(SHOW_CLOSED,showClosed); map.put(MEMBERS,memberMap); + var stateMap = new HashMap(); + for (var state : allowedStates) stateMap.put(state.code(),state.name()); + map.put(ALLOWED_STATES,stateMap); return map; } } diff --git a/core/src/main/java/de/srsoftware/umbrella/core/model/Status.java b/core/src/main/java/de/srsoftware/umbrella/core/model/Status.java index b4bd6d7..9a1a33d 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/model/Status.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/model/Status.java @@ -1,13 +1,16 @@ /* © SRSoftware 2025 */ package de.srsoftware.umbrella.core.model; +import java.util.ArrayList; +import java.util.List; + public record Status(String name, int code){ public static final Status OPEN = new Status("OPEN",10); public static final Status STARTED = new Status("STARTED",20); public static final Status PENDING = new Status("PENDING", 40); public static final Status COMPLETE = new Status("COMPLETE",60); public static final Status CANCELLED = new Status("CANCELLED", 100); - public static final Status[] PREDEFINED = {OPEN, STARTED, PENDING, COMPLETE, CANCELLED}; + public static final List PREDEFINED = new ArrayList<>(List.of(OPEN, STARTED, PENDING, COMPLETE, CANCELLED)); public static Status of(int code){ return switch (code){ diff --git a/frontend/src/routes/project/List.svelte b/frontend/src/routes/project/List.svelte index 63f4fd0..b171c8e 100644 --- a/frontend/src/routes/project/List.svelte +++ b/frontend/src/routes/project/List.svelte @@ -95,7 +95,7 @@ show(project.id)} > - {t("state_"+project.status.name.toLowerCase())} + {t("state_"+project.allowed_states[project.status].toLowerCase())} show(project.id)} > {#each Object.entries(project.members) as [uid,member]} @@ -104,7 +104,7 @@ - {#if project.status.code < 60} + {#if project.status < 60} {:else} diff --git a/frontend/src/routes/project/View.svelte b/frontend/src/routes/project/View.svelte index fff045c..181acb8 100644 --- a/frontend/src/routes/project/View.svelte +++ b/frontend/src/routes/project/View.svelte @@ -142,7 +142,7 @@ {t('state')} - update({status:val})} project_id={id} /> + update({status:val})} project_id={id} /> {#if project.company} @@ -205,7 +205,7 @@ {#if tasks} - + {/if} diff --git a/frontend/src/routes/task/ListTask.svelte b/frontend/src/routes/task/ListTask.svelte index a06957f..192c41b 100644 --- a/frontend/src/routes/task/ListTask.svelte +++ b/frontend/src/routes/task/ListTask.svelte @@ -13,6 +13,7 @@ estimated_time, show_closed, siblings, + states = {}, task } = $props(); let children = $state(null); @@ -117,24 +118,24 @@ {#if !deleted} -
  • e.preventDefault()} {ondragstart} class="task {task.status.name.toLowerCase()}"> +
  • e.preventDefault()} {ondragstart} class="task {states[task.status].toLowerCase()}"> {#if task.estimated_time} ({+task.estimated_time} h) {/if} - {#if task.status.name != 'PENDING'} + {#if states[task.status] != 'PENDING'} {/if} - {#if task.status.name != 'OPEN'} + {#if states[task.status] != 'OPEN'} {/if} - {#if task.status.name != 'STARTED'} + {#if states[task.status] != 'STARTED'} {/if} - {#if task.status.name != 'COMPLETE'} + {#if states[task.status] != 'COMPLETE'} {/if} - {#if task.status.name != 'CANCELLED'} + {#if states[task.status] != 'CANCELLED'} {/if} @@ -143,7 +144,7 @@ {error} {/if} {#if children} - + {/if}
  • {/if} diff --git a/frontend/src/routes/task/TaskList.svelte b/frontend/src/routes/task/TaskList.svelte index d6e9122..a6475aa 100644 --- a/frontend/src/routes/task/TaskList.svelte +++ b/frontend/src/routes/task/TaskList.svelte @@ -2,7 +2,7 @@ import { t } from '../../translations.svelte.js'; import ListTask from './ListTask.svelte'; - let { estimated_time, show_closed, tasks } = $props(); + let { estimated_time, show_closed, states = {}, tasks } = $props(); let sortedTasks = $derived.by(() => Object.values(tasks).sort((a, b) => a.name.localeCompare(b.name))); @@ -10,6 +10,6 @@
      {#each sortedTasks as task} - + {/each}
    \ No newline at end of file diff --git a/frontend/src/routes/task/View.svelte b/frontend/src/routes/task/View.svelte index 0ca30e3..8479f9a 100644 --- a/frontend/src/routes/task/View.svelte +++ b/frontend/src/routes/task/View.svelte @@ -181,7 +181,7 @@ {t('state')} - update({status:val})} project_id={task.project_id} /> + update({status:val})} project_id={task.project_id} /> {#if task.description} diff --git a/project/src/main/java/de/srsoftware/umbrella/project/ProjectModule.java b/project/src/main/java/de/srsoftware/umbrella/project/ProjectModule.java index 9c6ae3e..a590472 100644 --- a/project/src/main/java/de/srsoftware/umbrella/project/ProjectModule.java +++ b/project/src/main/java/de/srsoftware/umbrella/project/ProjectModule.java @@ -249,7 +249,7 @@ public class ProjectModule extends BaseHandler implements ProjectService { showClosed = settingsJson.has(SHOW_CLOSED) && settingsJson.get(SHOW_CLOSED) == TRUE; } var owner = Map.of(user.id(),new Member(user,OWNER)); - var prj = new Project(0,name,description, OPEN.code(),companyId,showClosed, owner); + var prj = new Project(0,name,description, OPEN.code(),companyId,showClosed, owner, PREDEFINED); prj = projects.save(prj); if (json.has(TAGS) && json.get(TAGS) instanceof JSONArray arr){ diff --git a/project/src/main/java/de/srsoftware/umbrella/project/SqliteDb.java b/project/src/main/java/de/srsoftware/umbrella/project/SqliteDb.java index 5ad1fcd..a1050ea 100644 --- a/project/src/main/java/de/srsoftware/umbrella/project/SqliteDb.java +++ b/project/src/main/java/de/srsoftware/umbrella/project/SqliteDb.java @@ -210,7 +210,7 @@ CREATE TABLE IF NOT EXISTS {0} ( {1} VARCHAR(255) PRIMARY KEY, {2} VARCHAR(255) for (var member : prj.members().entrySet()) query.values(id, member.getKey(), member.getValue().permission().code()); query.execute(db).close(); } - return new Project(id, prj.name(), prj.description(),prj.status(),prj.companyId().orElse(null),prj.showClosed(),prj.members()); + return new Project(id, prj.name(), prj.description(),prj.status(),prj.companyId().orElse(null),prj.showClosed(),prj.members(),prj.allowedStates()); } } catch (SQLException e) { throw new UmbrellaException("Failed to insert project into database");