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 9e8bba8..deff899 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 @@ -3,9 +3,10 @@ package de.srsoftware.umbrella.core.model; import static de.srsoftware.umbrella.core.Constants.*; import static de.srsoftware.umbrella.core.Util.*; +import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.invalidFieldException; +import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.unprocessable; import de.srsoftware.tools.Mappable; -import de.srsoftware.umbrella.core.exceptions.UmbrellaException; import java.sql.ResultSet; import java.sql.SQLException; import java.time.LocalDateTime; @@ -126,7 +127,24 @@ public class Time implements Mappable{ if (json.has(START_TIME) && json.get(START_TIME) instanceof Number st) start = st.longValue(); if (json.has(END_TIME) && json.get(END_TIME) instanceof Number e) end = e.longValue(); if (end == 0) end = null; - if (end != null && end < start) throw UmbrellaException.invalidFieldException(END_TIME,"after start_time"); + if (end != null && end < start) throw invalidFieldException(END_TIME,"after start_time"); + if (json.has(STATE)) { + var o = json.get(STATE); + try { + switch (o) { + case String stateName: + state = State.valueOf(stateName); + break; + case Number stateCode: + state = State.of(stateCode.intValue()); + break; + default: + throw invalidFieldException(STATE, "state name or code"); + } + } catch (Exception e){ + throw unprocessable("\"{0}\" is not a valid state name or code!",o); + } + } return this; } diff --git a/frontend/src/routes/time/Index.svelte b/frontend/src/routes/time/Index.svelte index efaf2f0..0964a53 100644 --- a/frontend/src/routes/time/Index.svelte +++ b/frontend/src/routes/time/Index.svelte @@ -142,11 +142,13 @@ async function multi_update(changeSet){ console.log({ids:Object.keys(selected),patch:patch}); + changeSet.ids = Object.keys(selected).map(id => +id); const url = api('time'); const res = await patch(url,changeSet); if (res.ok){ yikes(); - alert('todo'); + var updated = await res.json(); + times = {...times, ...updated}; } else error(res); } @@ -210,9 +212,9 @@ {#if selectionSum}
{t('sum_of_records')}: {selectionSum.toFixed(3)} {t('hours')} - - - + + +
{/if} diff --git a/time/src/main/java/de/srsoftware/umbrella/time/Constants.java b/time/src/main/java/de/srsoftware/umbrella/time/Constants.java index ca7ad49..ff345c4 100644 --- a/time/src/main/java/de/srsoftware/umbrella/time/Constants.java +++ b/time/src/main/java/de/srsoftware/umbrella/time/Constants.java @@ -7,6 +7,7 @@ public class Constants { public static final String CHILDREN = "children"; public static final String CONFIG_DATABASE = "umbrella.modules.time.database"; public static final String DOCUMENTS = "documents"; + public static final String IDS = "ids"; public static final String JOIN = "join"; public static final String PROJECTS = "projects"; public static final String TABLE_TASK_TIMES = "task_times"; diff --git a/time/src/main/java/de/srsoftware/umbrella/time/TimeModule.java b/time/src/main/java/de/srsoftware/umbrella/time/TimeModule.java index 1d01ab4..4868ce7 100644 --- a/time/src/main/java/de/srsoftware/umbrella/time/TimeModule.java +++ b/time/src/main/java/de/srsoftware/umbrella/time/TimeModule.java @@ -22,6 +22,8 @@ import de.srsoftware.umbrella.core.exceptions.UmbrellaException; import de.srsoftware.umbrella.core.model.*; import java.io.IOException; import java.util.*; +import java.util.stream.Collectors; +import org.json.JSONArray; public class TimeModule extends BaseHandler implements TimeService { @@ -34,6 +36,9 @@ public class TimeModule extends BaseHandler implements TimeService { ModuleRegistry.add(this); } + private boolean accessible(Time time, UmbrellaUser user) { + return time.userId() == user.id(); + } private boolean deleteTime(UmbrellaUser user, long timeId, HttpExchange ex) throws IOException { var time = timeDb.load(timeId); @@ -85,11 +90,17 @@ public class TimeModule extends BaseHandler implements TimeService { Optional token = SessionToken.from(ex).map(Token::of); var user = userService().loadUser(token); if (user.isEmpty()) return unauthorized(ex); + var head = path.pop(); - var timeId = Long.parseLong(head); - return patchTime(user.get(),timeId,ex); - } catch (NumberFormatException e){ - return send(ex,invalidFieldException(TIME_ID,"long value")); + + if (head == null){ + return patchTimes(user.get(),ex); + } else try { + var timeId = Long.parseLong(head); + return patchTime(user.get(), timeId, ex); + } catch (NumberFormatException e) { + return send(ex, invalidFieldException(TIME_ID, "long value")); + } } catch (UmbrellaException e){ return send(ex,e); } @@ -241,12 +252,26 @@ public class TimeModule extends BaseHandler implements TimeService { private boolean patchTime(UmbrellaUser user, long timeId, HttpExchange ex) throws IOException { var time = timeDb.load(timeId); - if (time.userId() != user.id()) throw forbidden("You are not allowed to alter this time!"); + if (!accessible(time, user)) throw forbidden("You are not allowed to alter this time!"); var json = json(ex); timeDb.save(time.patch(json)); return sendContent(ex,time); } + private boolean patchTimes(UmbrellaUser user, HttpExchange ex) throws IOException { + var json = json(ex); + if (!json.has(IDS) || !(json.get(IDS) instanceof JSONArray ids)) throw missingFieldException(IDS); + var times = new HashSet