From 3d81ddd3c56c593dca9388adbc4d2e37116f6def Mon Sep 17 00:00:00 2001 From: Stephan Richter Date: Fri, 25 Jul 2025 23:02:54 +0200 Subject: [PATCH] improved handling of null values when mapping entities to json --- .../de/srsoftware/umbrella/core/Util.java | 8 +++ .../umbrella/core/model/Project.java | 3 +- .../srsoftware/umbrella/core/model/Task.java | 5 +- .../srsoftware/umbrella/core/model/Time.java | 5 +- .../umbrella/documents/model/Document.java | 5 +- .../umbrella/documents/model/Position.java | 4 +- frontend/src/routes/project/Create.svelte | 56 +++++++++++++------ frontend/src/routes/task/Add.svelte | 4 +- frontend/src/routes/task/View.svelte | 6 +- frontend/src/unused/ClickInput.svelte | 27 --------- frontend/src/unused/ClickSelect.svelte | 34 ----------- frontend/src/unused/EditableField.svelte | 31 ---------- .../de/srsoftware/umbrella/items/Item.java | 3 +- .../umbrella/project/ProjectModule.java | 7 ++- web/src/main/resources/web/css/default.css | 7 +++ 15 files changed, 81 insertions(+), 124 deletions(-) delete mode 100644 frontend/src/unused/ClickInput.svelte delete mode 100644 frontend/src/unused/ClickSelect.svelte delete mode 100644 frontend/src/unused/EditableField.svelte diff --git a/core/src/main/java/de/srsoftware/umbrella/core/Util.java b/core/src/main/java/de/srsoftware/umbrella/core/Util.java index bede39d..bb2da1a 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/Util.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/Util.java @@ -48,7 +48,15 @@ public class Util { return result; } + public static HashMap mapMarkdown(String source){ + var map = new HashMap(); + map.put(SOURCE,source); + map.put(RENDERED,markdown(source)); + return map; + } + public static String markdown(String source){ + if (source == null) return source; try { if (plantumlJar.exists()) { var matcher = UML_PATTERN.matcher(source); 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 7709135..b54a637 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 @@ -3,6 +3,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.Util.markdown; import de.srsoftware.tools.Mappable; @@ -95,7 +96,7 @@ public class Project implements Mappable { } map.put(ID,id); map.put(NAME,name); - map.put(DESCRIPTION,Map.of(SOURCE,description,RENDERED,markdown(description))); + map.put(DESCRIPTION,mapMarkdown(description)); map.put(STATUS,Map.of(STATUS_CODE,status.code(), NAME,status.name())); map.put(COMPANY_ID,companyId); map.put(SHOW_CLOSED,showClosed); diff --git a/core/src/main/java/de/srsoftware/umbrella/core/model/Task.java b/core/src/main/java/de/srsoftware/umbrella/core/model/Task.java index 5d754dd..626f4f9 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/model/Task.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/model/Task.java @@ -3,8 +3,7 @@ package de.srsoftware.umbrella.core.model; import static de.srsoftware.tools.Optionals.nullIfEmpty; import static de.srsoftware.umbrella.core.Constants.*; -import static de.srsoftware.umbrella.core.Util.LOG; -import static de.srsoftware.umbrella.core.Util.markdown; +import static de.srsoftware.umbrella.core.Util.*; import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.invalidFieldException; import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingFieldException; import static java.lang.System.Logger.Level.WARNING; @@ -182,7 +181,7 @@ public class Task implements Mappable { map.put(PROJECT_ID, projectId); map.put(PARENT_TASK_ID, parentTaskId); map.put(NAME, name); - map.put(DESCRIPTION, Map.of(SOURCE,description,RENDERED,markdown(description))); + map.put(DESCRIPTION, mapMarkdown(description)); map.put(STATUS, Map.of(NAME,status.name(),STATUS_CODE,status.code())); map.put(ESTIMATED_TIME, estimatedTime); map.put(START_DATE,start); diff --git a/core/src/main/java/de/srsoftware/umbrella/core/model/Time.java b/core/src/main/java/de/srsoftware/umbrella/core/model/Time.java index d8afb71..efd466a 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/model/Time.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/model/Time.java @@ -2,8 +2,7 @@ package de.srsoftware.umbrella.core.model; import static de.srsoftware.umbrella.core.Constants.*; -import static de.srsoftware.umbrella.core.Util.dateTimeOf; -import static de.srsoftware.umbrella.core.Util.markdown; +import static de.srsoftware.umbrella.core.Util.*; import de.srsoftware.tools.Mappable; import java.sql.ResultSet; @@ -103,7 +102,7 @@ public class Time implements Mappable{ map.put(ID,id); map.put(USER_ID,userId); map.put(SUBJECT,subject); - map.put(DESCRIPTION,Map.of(SOURCE,description,RENDERED,markdown(description))); + map.put(DESCRIPTION,mapMarkdown(description)); map.put(START_TIME,start.toString().replace("T"," ")); map.put(END_TIME,end.toString().replace("T"," ")); map.put(STATE,Map.of(STATUS_CODE,state.code,NAME,state.name())); diff --git a/documents/src/main/java/de/srsoftware/umbrella/documents/model/Document.java b/documents/src/main/java/de/srsoftware/umbrella/documents/model/Document.java index fa79140..9c38a34 100644 --- a/documents/src/main/java/de/srsoftware/umbrella/documents/model/Document.java +++ b/documents/src/main/java/de/srsoftware/umbrella/documents/model/Document.java @@ -3,6 +3,7 @@ package de.srsoftware.umbrella.documents.model; import static de.srsoftware.umbrella.core.Constants.*; import static de.srsoftware.umbrella.core.ResponseCode.HTTP_UNPROCESSABLE; +import static de.srsoftware.umbrella.core.Util.mapMarkdown; import static de.srsoftware.umbrella.core.Util.markdown; import static de.srsoftware.umbrella.documents.Constants.*; import static de.srsoftware.umbrella.documents.Constants.FIELD_CUSTOMER; @@ -218,8 +219,8 @@ public final class Document implements Mappable { map.put(DATE, date); map.put(STATE, state.code); map.put(FIELD_DELIVERY, delivery == null ? "" : delivery); - map.put(FIELD_HEAD, Map.of(SOURCE,head,RENDERED,markdown(head))); - map.put(FIELD_FOOTER, Map.of(SOURCE,footer,RENDERED,markdown(footer))); + map.put(FIELD_HEAD, mapMarkdown(head)); + map.put(FIELD_FOOTER, mapMarkdown(footer)); map.put(FIELD_CURRENCY, currency); map.put(SENDER, sender.toMap()); map.put(FIELD_CUSTOMER, customer.toMap()); diff --git a/documents/src/main/java/de/srsoftware/umbrella/documents/model/Position.java b/documents/src/main/java/de/srsoftware/umbrella/documents/model/Position.java index 988d6c4..c72adbc 100644 --- a/documents/src/main/java/de/srsoftware/umbrella/documents/model/Position.java +++ b/documents/src/main/java/de/srsoftware/umbrella/documents/model/Position.java @@ -3,6 +3,7 @@ package de.srsoftware.umbrella.documents.model; import static de.srsoftware.umbrella.core.Constants.*; +import static de.srsoftware.umbrella.core.Util.mapMarkdown; import static de.srsoftware.umbrella.core.Util.markdown; import static de.srsoftware.umbrella.documents.Constants.*; @@ -188,7 +189,6 @@ public final class Position implements Mappable { } public Map renderToMap() { - var descr = Map.of(SOURCE,description,RENDERED,markdown(description)); var map = new HashMap(); map.put(FIELD_DOCUMENT_ID, docId); map.put(NUMBER, num); @@ -196,7 +196,7 @@ public final class Position implements Mappable { map.put(FIELD_AMOUNT, amount); map.put(FIELD_UNIT, unit); map.put(TITLE, title); - map.put(DESCRIPTION, descr); + map.put(DESCRIPTION, mapMarkdown(description)); map.put(FIELD_UNIT_PRICE, unitPrice); map.put(FIELD_TAX, tax); map.put(FIELD_TIME_ID, timeId); diff --git a/frontend/src/routes/project/Create.svelte b/frontend/src/routes/project/Create.svelte index 15bb22e..56df5b0 100644 --- a/frontend/src/routes/project/Create.svelte +++ b/frontend/src/routes/project/Create.svelte @@ -3,6 +3,7 @@ import { t } from '../../translations.svelte.js'; import CompanySelector from '../../Components/CompanySelector.svelte'; + import MarkdownEditor from '../../Components/MarkdownEditor.svelte'; import Settings from './Settings.svelte'; let showSettings = $state(false); let ready = $derived(!!project.name.trim()) @@ -11,7 +12,7 @@ let project = $state({ name:'', - description:'', + description : { source : '', rendered : '' }, settings:{ show_closed:false } @@ -53,21 +54,44 @@
{t('basic_data')} - - - - {#if !showSettings} - - {/if} + + + + + + + + + + + + + + + {#if !showSettings} + + + + + {/if} + +
+ {t('company_optional')} + + +
+ {t('Name')} + + +
+ {t('description')} + + +
+ {t('settings')} + + +
{#if showSettings} diff --git a/frontend/src/routes/task/Add.svelte b/frontend/src/routes/task/Add.svelte index 2780dd3..6450808 100644 --- a/frontend/src/routes/task/Add.svelte +++ b/frontend/src/routes/task/Add.svelte @@ -84,7 +84,9 @@ }); if (resp.ok) { task = await resp.json(); - router.navigate(`/task/${task.id}/view`); + if (task.parent_task_id){ + router.navigate(`/task/${task.parent_task_id}/view`); + } else router.navigate(`/task/${task.id}/view`); error = null; } else { error = await resp.text(); diff --git a/frontend/src/routes/task/View.svelte b/frontend/src/routes/task/View.svelte index 9957f44..8544aa9 100644 --- a/frontend/src/routes/task/View.svelte +++ b/frontend/src/routes/task/View.svelte @@ -175,9 +175,11 @@ - {t('subtasks')} - + + {t('subtasks')} + + {#if children} {/if} diff --git a/frontend/src/unused/ClickInput.svelte b/frontend/src/unused/ClickInput.svelte deleted file mode 100644 index 7a2e6c6..0000000 --- a/frontend/src/unused/ClickInput.svelte +++ /dev/null @@ -1,27 +0,0 @@ - - -{#if input} - -{:else} - {value} -{/if} diff --git a/frontend/src/unused/ClickSelect.svelte b/frontend/src/unused/ClickSelect.svelte deleted file mode 100644 index 4bc264e..0000000 --- a/frontend/src/unused/ClickSelect.svelte +++ /dev/null @@ -1,34 +0,0 @@ - - -{#if options.length > 0} - -{:else} - {value} -{/if} diff --git a/frontend/src/unused/EditableField.svelte b/frontend/src/unused/EditableField.svelte deleted file mode 100644 index fad3ccc..0000000 --- a/frontend/src/unused/EditableField.svelte +++ /dev/null @@ -1,31 +0,0 @@ - - - {t(key)} - {#if input} - - - - {:else} - {value} - {/if} - \ No newline at end of file diff --git a/items/src/main/java/de/srsoftware/umbrella/items/Item.java b/items/src/main/java/de/srsoftware/umbrella/items/Item.java index fe718e2..a9a42e3 100644 --- a/items/src/main/java/de/srsoftware/umbrella/items/Item.java +++ b/items/src/main/java/de/srsoftware/umbrella/items/Item.java @@ -3,6 +3,7 @@ package de.srsoftware.umbrella.items; import static de.srsoftware.umbrella.core.Constants.*; import static de.srsoftware.umbrella.core.Constants.CODE; +import static de.srsoftware.umbrella.core.Util.mapMarkdown; import static de.srsoftware.umbrella.core.Util.markdown; import static de.srsoftware.umbrella.items.Constants.*; @@ -31,7 +32,7 @@ public record Item(long id, long companyId, String code, String name, String des ID,id, COMPANY_ID,companyId, CODE,code,NAME,name, - DESCRIPTION,Map.of(SOURCE,description,RENDERED,markdown(description)), + DESCRIPTION,mapMarkdown(description), UNIT,unit, UNIT_PRICE,unitPrice, TAX,tax); 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 cffc296..f74c160 100644 --- a/project/src/main/java/de/srsoftware/umbrella/project/ProjectModule.java +++ b/project/src/main/java/de/srsoftware/umbrella/project/ProjectModule.java @@ -216,7 +216,12 @@ public class ProjectModule extends BaseHandler implements ProjectService { private boolean postProject(HttpExchange ex, UmbrellaUser user) throws IOException, UmbrellaException { var json = json(ex); if (!(json.has(NAME) && json.get(NAME) instanceof String name)) throw missingFieldException(NAME); - var description = json.has(DESCRIPTION) && json.get(DESCRIPTION) instanceof String d ? d : null; + String description = null; + if (json.has(DESCRIPTION)){ + var desc = json.get(DESCRIPTION); + if (desc instanceof String d) description = d; + if (desc instanceof JSONObject nested && nested.has(SOURCE) && nested.get(SOURCE) instanceof String d) description = d; + } Long companyId = null; if (json.has(COMPANY_ID) && json.get(COMPANY_ID) instanceof Number number){ if (!companies.membership(number.longValue(), user.id())) throw forbidden("You are not a member of company {0}!",number); diff --git a/web/src/main/resources/web/css/default.css b/web/src/main/resources/web/css/default.css index cad49f2..e43a9c8 100644 --- a/web/src/main/resources/web/css/default.css +++ b/web/src/main/resources/web/css/default.css @@ -7,6 +7,7 @@ a { color: orange; } body { + font-family: sans; background: black; color: orange; margin: 0; @@ -113,4 +114,10 @@ td, tr{ padding: 10px; border: 1px solid orange; border-radius: 5px; +} + +.project .name, +.task .name{ + font-size: 32px; + font-weight: bold; } \ No newline at end of file