improved time selector in document editor
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
@@ -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}
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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}
|
||||
|
||||
Reference in New Issue
Block a user