Browse Source

implemented editor for times

feature/join_times
Stephan Richter 2 months ago
parent
commit
49461199cd
  1. 17
      core/src/main/java/de/srsoftware/umbrella/core/model/Time.java
  2. 24
      frontend/src/Components/DateTimeEditor.svelte
  3. 37
      frontend/src/Components/TimeRecordEditor.svelte
  4. 38
      frontend/src/routes/time/Index.svelte
  5. 1
      translations/src/main/resources/de.json

17
core/src/main/java/de/srsoftware/umbrella/core/model/Time.java

@ -108,12 +108,21 @@ public class Time implements Mappable{
); );
} }
private LocalDateTime parse(String time){
if (time.contains("T")) return LocalDateTime.parse(time);
return LocalDateTime.parse(time,DT);
}
public Time patch(JSONObject json) { public Time patch(JSONObject json) {
if (json.has(SUBJECT) && json.get(SUBJECT) instanceof String s) subject = s; if (json.has(SUBJECT) && json.get(SUBJECT) instanceof String s) subject = s;
if (json.has(DESCRIPTION) && json.get(DESCRIPTION) instanceof String d) description = d; if (json.has(DESCRIPTION)) {
if (json.has(START_TIME) && json.get(START_TIME) instanceof String st) start = LocalDateTime.parse(st, DT); var o = json.get(DESCRIPTION);
if (json.has(END_TIME) && json.get(END_TIME) instanceof String e) end = LocalDateTime.parse(e,DT); if (o instanceof JSONObject nested && nested.get(SOURCE) instanceof String src) o = src;
if (end != null && !start.isBefore(end)) throw UmbrellaException.invalidFieldException(END_TIME,"after start_time"); if (o instanceof String d) description = d;
}
if (json.has(START_TIME) && json.get(START_TIME) instanceof String st) start = parse(st);
if (json.has(END_TIME) && json.get(END_TIME) instanceof String e) end = parse(e);
if (end != null && end.isBefore(start)) throw UmbrellaException.invalidFieldException(END_TIME,"after start_time");
return this; return this;
} }

24
frontend/src/Components/DateTimeEditor.svelte

@ -1,24 +0,0 @@
<script>
let { onSet = (dateTime) => {}, value = ' ' } = $props();
let date = $state(value.split(' ')[0]);
let time = $state(value.split(' ')[1]);
console.log({date:date,time:time,value:value});
function handleSubmit(e){
e.preventDefault();
onSet(`${date} ${time}`);
}
</script>
<style>
button{ display: none }
</style>
<form onsubmit={handleSubmit} >
<input type="date" bind:value={date} />
<input type="time" bind:value={time} />
<button type="submit">ok</button>
</form>

37
frontend/src/Components/TimeRecordEditor.svelte

@ -0,0 +1,37 @@
<script>
import { t } from '../translations.svelte.js';
import MarkdownEditor from './MarkdownEditor.svelte';
let { record = null, onSet = time => {} } = $props();
function onsubmit(e){
e.preventDefault();
onSet(record);
}
</script>
{#if record}
<form {onsubmit}>
<fieldset>
<legend>{t('edit_object',{object:t('record')})}</legend>
<label>
{t('start')}
<input type="datetime-local" bind:value={record.start_time} />
</label>
<label>
{t('end')}
<input type="datetime-local" bind:value={record.end_time} />
</label>
<label>
{t('subject')}
<input type="text" bind:value={record.subject} />
</label>
<label>
{t('description')}
<MarkdownEditor simple={true} bind:value={record.description} />
</label>
<button type="submit">{t('save')}</button>
</fieldset>
</form>
{record.description.source}
{/if}

38
frontend/src/routes/time/Index.svelte

@ -4,14 +4,13 @@
import { api } from '../../urls.svelte.js'; import { api } from '../../urls.svelte.js';
import { t } from '../../translations.svelte.js'; import { t } from '../../translations.svelte.js';
import DateTimeEditor from '../../Components/DateTimeEditor.svelte'; import TimeEditor from '../../Components/TimeRecordEditor.svelte';
import LineEditor from '../../Components/LineEditor.svelte';
import MarkdownEditor from '../../Components/MarkdownEditor.svelte';
let error = $state(null); let error = $state(null);
let router = useTinyRouter(); let router = useTinyRouter();
let times = $state(null); let times = $state(null);
let detail = $state(null); let detail = $state(null);
let sortedTimes = $derived.by(() => Object.values(times).sort((b, a) => a.start_time.localeCompare(b.start_time)));
async function loadTimes(){ async function loadTimes(){
const url = api('time'); const url = api('time');
@ -27,17 +26,20 @@
router.navigate(`task/${tid}/view`); router.navigate(`task/${tid}/view`);
} }
async function update(tid,field,newVal){ async function update(time){
times[tid][field] = newVal; const url = api(`time/${time.id}`);
detail = null; time.start_time = time.start_time.split(':').slice(0,2).join(':');
const url = api(`time/${tid}`); time.end_time = time.end_time.split(':').slice(0,2).join(':');
const res = await fetch(url,{ const res = await fetch(url,{
credentials:'include', credentials:'include',
method:'PATCH', method:'PATCH',
body:JSON.stringify(times[tid]) body:JSON.stringify(time)
}); });
if (res.ok){ if (res.ok){
times[tid] = await res.json(); let json = await res.json();
let id = json.id;
for (let key of Object.keys(json)) times[id][key] = json[key];
detail = null;
error = null; error = null;
return true; return true;
} else { } else {
@ -69,23 +71,15 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{#each Object.entries(times) as [tid,time]} {#each sortedTimes as time}
{#if detail == tid} {#if detail == time.id}
<tr> <tr>
<td> <td colspan="5">
<div> <TimeEditor record={time} onSet={update} />
<DateTimeEditor value={time.start_time} onSet={dateTime => update(tid,'start_time',dateTime)} />
<DateTimeEditor value={time.end_time} onSet={dateTime => update(tid,'end_time',dateTime)} />
</div>
</td>
<td colspan="2">
<LineEditor simple={true} value={time.subject} onSet={subject => update(tid,'subject',subject)} />
<MarkdownEditor simple={true} value={time.description} onSet={desc => update(tid,'description',desc)} />
</td> </td>
</tr> </tr>
{:else} {:else}
<tr onclick={e => {detail = tid}}> <tr onclick={e => {detail = time.id}}>
<td class="start_end"> <td class="start_end">
{time.start_time}{#if time.end_time}{time.end_time}{/if} {time.start_time}{#if time.end_time}{time.end_time}{/if}
</td> </td>

1
translations/src/main/resources/de.json

@ -173,6 +173,7 @@
"project": "Projekt", "project": "Projekt",
"projects": "Projekte", "projects": "Projekte",
"record": "Eintrag",
"repeat_new_password": "Wiederholung", "repeat_new_password": "Wiederholung",
"results": "Ergebnisse", "results": "Ergebnisse",

Loading…
Cancel
Save