improved time selector in document editor
All checks were successful
Build Docker Image / Docker-Build (push) Successful in 2m23s
Build Docker Image / Clean-Registry (push) Successful in -11s

Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
2026-03-26 10:52:22 +01:00
parent 03b9a472c3
commit dba2657894
4 changed files with 52 additions and 49 deletions

View File

@@ -2,11 +2,12 @@
import { onMount } from 'svelte';
import { useTinyRouter } from 'svelte-tiny-router';
import { api } from '../../urls.svelte.js';
import { api, post } from '../../urls.svelte.js';
import { error, yikes } from '../../warn.svelte';
import { t } from '../../translations.svelte.js';
import Position from './Position.svelte';
import PositionSelector from './PositionSelector.svelte';
var {
document = $bindable(null),
@@ -15,6 +16,18 @@
let editable = $derived(document.state == 1);
let sums = $derived.by(calcSums);
let position_select = $state(false);
async function addPosition(selected){
const url = api(`document/${document.id}/position`);
const resp = await post(url,selected);
if (resp.ok){
document.positions = await resp.json();
yikes();
} else {
error(resp);
}
}
function calcSums(){
let data = {}
@@ -69,6 +82,12 @@
}
</script>
<legend>
{t('positions')}
{#if editable}
<button onclick={() => position_select = true}>{t('add_object',{object:t('position')})}</button>
{/if}
</legend>
{#if document.positions}
<table class="positions">
<thead>
@@ -98,3 +117,6 @@
</tbody>
</table>
{/if}
{#if position_select}
<PositionSelector close={() => position_select=false} doc={document} onSelect={addPosition} />
{/if}

View File

@@ -13,13 +13,8 @@
let source = $state(0);
function select(position){
close();
onSelect(position);
}
function estimateSelected(estimate){
select({
onSelect({
item_code : t('estimated_time'),
title : estimate.name,
description : estimate.description.source,
@@ -56,11 +51,11 @@
};
if (tax) data['tax'] = tax;
select(data);
onSelect(data);
}
function timeSelected(time){
select({
onSelect({
item_code : t('timetrack'),
title : time.subject,
description : time.description.source,
@@ -100,6 +95,7 @@
{:else if source == 1}
<EstimateList company_id={doc.company.id} onSelect={estimateSelected} />
{:else}
<TimeList company_id={doc.company.id} onSelect={timeSelected} />
<TimeList company_id={doc.company.id} hide={doc.positions} onSelect={timeSelected} />
{/if}
</div>
<pre>
</div>

View File

@@ -1,12 +1,13 @@
<script>
import { onMount } from 'svelte';
import { api, target } from '../../urls.svelte.js';
import { api, post, target } from '../../urls.svelte.js';
import { error, yikes } from '../../warn.svelte';
import { t } from '../../translations.svelte.js';
let {
company_id,
hide = {},
onSelect = (time) => {}
} = $props();
@@ -16,11 +17,7 @@
async function loadProjects(){
const url = api('project/list');
let data = { company_id: company_id };
const resp = await fetch(url,{
credentials : 'include',
method : 'POST',
body : JSON.stringify(data)
});
const resp = await post(url,data);
if (resp.ok){
projects = await resp.json();
yikes();
@@ -29,19 +26,25 @@
}
}
function filter(newTimes, excluded_ids){
times = newTimes.filter(time => !excluded_ids.includes(time.id));
}
async function loadTimes(projectId){
const url = api('time/list');
let data = { company_id: company_id, project_id: projectId };
const resp = await fetch(url,{
credentials : 'include',
method : 'POST',
body : JSON.stringify(data)
});
const resp = await post(url,data);
if (resp.ok){
times = await resp.json();
} else {
error(resp);
}
yikes();
let newTimes = await resp.json();
let present_times = Object.values(hide).filter(pos => pos.time_id).map(pos => pos.time_id)
filter(newTimes,present_times);
} else error(resp);
}
function select(time){
filter(times,[time.id]);
onSelect(time);
}
onMount(loadProjects);
@@ -56,12 +59,13 @@
{/if}
{#if times}
{#each times as time,idx2}
<div class="time" onclick={() => onSelect(time)}>
<div class="time" onclick={() => select(time)}>
<span class="duration">{(time.duration).toFixed(3)} {t('hours')}</span>
<span class="subject">{time.subject}</span>
<span class="start_time">{time.start_time}</span>
<span class="start_time">{new Date(time.start_time*1000).toUTCString()}</span>
<span class="description">{@html target(time.description.rendered)}</span>
</div>
<hr/>
{/each}
{/if}
</div>

View File

@@ -12,13 +12,11 @@
import MultilineEditor from '../../Components/MultilineEditor.svelte';
import Notes from '../notes/RelatedNotes.svelte';
import PositionList from './PositionList.svelte';
import PositionSelector from './PositionSelector.svelte';
import StateSelector from './StateSelector.svelte';
import Tags from '../tags/TagList.svelte';
import TemplateSelector from './TemplateSelector.svelte';
import TypeSelector from './TypeSelector.svelte';
let doc = $state(null);
let editable = $derived(doc.state == 1);
let { id } = $props();
@@ -27,16 +25,7 @@
const router = useTinyRouter();
let sndDisabled = $state(false);
async function addPosition(selected){
const url = api(`document/${doc.id}/position`);
const resp = await post(url,selected);
if (resp.ok){
doc.positions = await resp.json();
yikes();
} else {
error(resp);
}
}
async function changeState(newVal){
let success = false;
@@ -234,12 +223,7 @@
<MarkdownEditor bind:value={doc.head} editable={editable} onSet={(val) => update('head',val)} />
</fieldset>
<fieldset>
<legend>
{t('positions')}
{#if editable}
<button onclick={() => position_select = true}>{t('add_object',{object:t('position')})}</button>
{/if}
</legend>
<PositionList bind:document={doc} submit={update} />
</fieldset>
<fieldset>
@@ -262,6 +246,3 @@
<Notes module="document" entity_id={id} />
</div>
{#if position_select}
<PositionSelector close={() => position_select=false} {doc} onSelect={addPosition} />
{/if}