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 { onMount } from 'svelte';
|
||||||
import { useTinyRouter } from 'svelte-tiny-router';
|
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 { error, yikes } from '../../warn.svelte';
|
||||||
import { t } from '../../translations.svelte.js';
|
import { t } from '../../translations.svelte.js';
|
||||||
|
|
||||||
import Position from './Position.svelte';
|
import Position from './Position.svelte';
|
||||||
|
import PositionSelector from './PositionSelector.svelte';
|
||||||
|
|
||||||
var {
|
var {
|
||||||
document = $bindable(null),
|
document = $bindable(null),
|
||||||
@@ -15,6 +16,18 @@
|
|||||||
|
|
||||||
let editable = $derived(document.state == 1);
|
let editable = $derived(document.state == 1);
|
||||||
let sums = $derived.by(calcSums);
|
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(){
|
function calcSums(){
|
||||||
let data = {}
|
let data = {}
|
||||||
@@ -69,6 +82,12 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<legend>
|
||||||
|
{t('positions')}
|
||||||
|
{#if editable}
|
||||||
|
<button onclick={() => position_select = true}>{t('add_object',{object:t('position')})}</button>
|
||||||
|
{/if}
|
||||||
|
</legend>
|
||||||
{#if document.positions}
|
{#if document.positions}
|
||||||
<table class="positions">
|
<table class="positions">
|
||||||
<thead>
|
<thead>
|
||||||
@@ -98,3 +117,6 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
{/if}
|
{/if}
|
||||||
|
{#if position_select}
|
||||||
|
<PositionSelector close={() => position_select=false} doc={document} onSelect={addPosition} />
|
||||||
|
{/if}
|
||||||
@@ -13,13 +13,8 @@
|
|||||||
|
|
||||||
let source = $state(0);
|
let source = $state(0);
|
||||||
|
|
||||||
function select(position){
|
|
||||||
close();
|
|
||||||
onSelect(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
function estimateSelected(estimate){
|
function estimateSelected(estimate){
|
||||||
select({
|
onSelect({
|
||||||
item_code : t('estimated_time'),
|
item_code : t('estimated_time'),
|
||||||
title : estimate.name,
|
title : estimate.name,
|
||||||
description : estimate.description.source,
|
description : estimate.description.source,
|
||||||
@@ -56,11 +51,11 @@
|
|||||||
};
|
};
|
||||||
if (tax) data['tax'] = tax;
|
if (tax) data['tax'] = tax;
|
||||||
|
|
||||||
select(data);
|
onSelect(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
function timeSelected(time){
|
function timeSelected(time){
|
||||||
select({
|
onSelect({
|
||||||
item_code : t('timetrack'),
|
item_code : t('timetrack'),
|
||||||
title : time.subject,
|
title : time.subject,
|
||||||
description : time.description.source,
|
description : time.description.source,
|
||||||
@@ -100,6 +95,7 @@
|
|||||||
{:else if source == 1}
|
{:else if source == 1}
|
||||||
<EstimateList company_id={doc.company.id} onSelect={estimateSelected} />
|
<EstimateList company_id={doc.company.id} onSelect={estimateSelected} />
|
||||||
{:else}
|
{:else}
|
||||||
<TimeList company_id={doc.company.id} onSelect={timeSelected} />
|
<TimeList company_id={doc.company.id} hide={doc.positions} onSelect={timeSelected} />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
<pre>
|
||||||
|
</div>
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
<script>
|
<script>
|
||||||
import { onMount } from 'svelte';
|
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 { error, yikes } from '../../warn.svelte';
|
||||||
import { t } from '../../translations.svelte.js';
|
import { t } from '../../translations.svelte.js';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
company_id,
|
company_id,
|
||||||
|
hide = {},
|
||||||
onSelect = (time) => {}
|
onSelect = (time) => {}
|
||||||
} = $props();
|
} = $props();
|
||||||
|
|
||||||
@@ -16,11 +17,7 @@
|
|||||||
async function loadProjects(){
|
async function loadProjects(){
|
||||||
const url = api('project/list');
|
const url = api('project/list');
|
||||||
let data = { company_id: company_id };
|
let data = { company_id: company_id };
|
||||||
const resp = await fetch(url,{
|
const resp = await post(url,data);
|
||||||
credentials : 'include',
|
|
||||||
method : 'POST',
|
|
||||||
body : JSON.stringify(data)
|
|
||||||
});
|
|
||||||
if (resp.ok){
|
if (resp.ok){
|
||||||
projects = await resp.json();
|
projects = await resp.json();
|
||||||
yikes();
|
yikes();
|
||||||
@@ -29,19 +26,25 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function filter(newTimes, excluded_ids){
|
||||||
|
times = newTimes.filter(time => !excluded_ids.includes(time.id));
|
||||||
|
}
|
||||||
|
|
||||||
async function loadTimes(projectId){
|
async function loadTimes(projectId){
|
||||||
const url = api('time/list');
|
const url = api('time/list');
|
||||||
let data = { company_id: company_id, project_id: projectId };
|
let data = { company_id: company_id, project_id: projectId };
|
||||||
const resp = await fetch(url,{
|
const resp = await post(url,data);
|
||||||
credentials : 'include',
|
|
||||||
method : 'POST',
|
|
||||||
body : JSON.stringify(data)
|
|
||||||
});
|
|
||||||
if (resp.ok){
|
if (resp.ok){
|
||||||
times = await resp.json();
|
yikes();
|
||||||
} else {
|
let newTimes = await resp.json();
|
||||||
error(resp);
|
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);
|
onMount(loadProjects);
|
||||||
@@ -56,12 +59,13 @@
|
|||||||
{/if}
|
{/if}
|
||||||
{#if times}
|
{#if times}
|
||||||
{#each times as time,idx2}
|
{#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="duration">{(time.duration).toFixed(3)} {t('hours')}</span>
|
||||||
<span class="subject">{time.subject}</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>
|
<span class="description">{@html target(time.description.rendered)}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<hr/>
|
||||||
{/each}
|
{/each}
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -12,13 +12,11 @@
|
|||||||
import MultilineEditor from '../../Components/MultilineEditor.svelte';
|
import MultilineEditor from '../../Components/MultilineEditor.svelte';
|
||||||
import Notes from '../notes/RelatedNotes.svelte';
|
import Notes from '../notes/RelatedNotes.svelte';
|
||||||
import PositionList from './PositionList.svelte';
|
import PositionList from './PositionList.svelte';
|
||||||
import PositionSelector from './PositionSelector.svelte';
|
|
||||||
import StateSelector from './StateSelector.svelte';
|
import StateSelector from './StateSelector.svelte';
|
||||||
import Tags from '../tags/TagList.svelte';
|
import Tags from '../tags/TagList.svelte';
|
||||||
import TemplateSelector from './TemplateSelector.svelte';
|
import TemplateSelector from './TemplateSelector.svelte';
|
||||||
import TypeSelector from './TypeSelector.svelte';
|
import TypeSelector from './TypeSelector.svelte';
|
||||||
|
|
||||||
|
|
||||||
let doc = $state(null);
|
let doc = $state(null);
|
||||||
let editable = $derived(doc.state == 1);
|
let editable = $derived(doc.state == 1);
|
||||||
let { id } = $props();
|
let { id } = $props();
|
||||||
@@ -27,16 +25,7 @@
|
|||||||
const router = useTinyRouter();
|
const router = useTinyRouter();
|
||||||
let sndDisabled = $state(false);
|
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){
|
async function changeState(newVal){
|
||||||
let success = false;
|
let success = false;
|
||||||
@@ -234,12 +223,7 @@
|
|||||||
<MarkdownEditor bind:value={doc.head} editable={editable} onSet={(val) => update('head',val)} />
|
<MarkdownEditor bind:value={doc.head} editable={editable} onSet={(val) => update('head',val)} />
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<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} />
|
<PositionList bind:document={doc} submit={update} />
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
@@ -262,6 +246,3 @@
|
|||||||
<Notes module="document" entity_id={id} />
|
<Notes module="document" entity_id={id} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if position_select}
|
|
||||||
<PositionSelector close={() => position_select=false} {doc} onSelect={addPosition} />
|
|
||||||
{/if}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user