Browse Source

implemented selection functions

Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
feature/join_times
Stephan Richter 2 months ago
parent
commit
9fe94da5a6
  1. 101
      frontend/src/routes/time/Index.svelte

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

@ -11,6 +11,50 @@ @@ -11,6 +11,50 @@
let times = $state(null);
let detail = $state(null);
let sortedTimes = $derived.by(() => Object.values(times).sort((b, a) => a.start_time.localeCompare(b.start_time)));
let selected = $state({});
let ranges = {};
let timeMap = $derived.by(() => {
let result = {
months : {},
years : {}
}
let lastYear = null;
let lastMonth = null;
let yearCount = 0;
let monthCount = 0;
let yearIndex = 0;
let monthIndex = 0;
for (let idx in sortedTimes){
const time = sortedTimes[idx];
const start = time.start_time;
const year = start.substring(0,4);
const month = start.substring(5,7);
if (year != lastYear){
lastYear = year;
if (yearCount) result.years[yearIndex] = yearCount;
yearCount = 0;
yearIndex = idx;
}
yearCount +=1;
if (month != lastMonth){
lastMonth = month;
if (monthCount) result.months[monthIndex] = monthCount;
monthCount = 0;
monthIndex = idx;
}
monthCount +=1;
}
if (yearCount) result.years[yearIndex] = yearCount;
if (monthCount) result.months[monthIndex] = monthCount;
console.log(result);
return result;
});
function calcYearMap(){
let result = Object.values(times).length;
console.log({result:result});
return result;
}
async function loadTimes(){
const url = api('time');
@ -26,6 +70,26 @@ @@ -26,6 +70,26 @@
router.navigate(`task/${tid}/view`);
}
function toggleRange(range){
let affected = sortedTimes.filter(time => time.start_time.startsWith(range));
if (ranges[range]){
delete ranges[range];
for (let time of affected){
if (selected[time.id]) delete selected[time.id]
}
} else {
for (let time of affected) selected[time.id] = true;
ranges[range] = true;
}
}
function toggleSelect(time_id){
detail = null;
if (selected[time_id]) {
delete selected[time_id]
} else selected[time_id] = true;
}
async function update(time){
const url = api(`time/${time.id}`);
time.start_time = time.start_time.split(':').slice(0,2).join(':');
@ -53,6 +117,12 @@ @@ -53,6 +117,12 @@
<style>
td { vertical-align: top; }
.year, .month{
border: 1px solid;
}
.selected td:not(.year):not(.month){
background: navy;
}
</style>
<h1>{t('timetracking')}</h1>
@ -63,6 +133,8 @@ @@ -63,6 +133,8 @@
<table class="timetracks">
<thead>
<tr>
<th>{t('year')}</th>
<th>{t('month')}</th>
<th>{t('start_end')}</th>
<th>{t('duration')}</th>
<th>{t('subject')}</th>
@ -71,35 +143,44 @@ @@ -71,35 +143,44 @@
</tr>
</thead>
<tbody>
{#each sortedTimes as time}
{#each sortedTimes as time,line}
<tr class={selected[time.id]?'selected':''}>
{#if timeMap.years[line]}
<td class="year" rowspan={timeMap.years[line]} onclick={e => toggleRange(time.start_time.substring(0,4))}>
{time.start_time.substring(0,4)}
</td>
{/if}
{#if timeMap.months[line]}
<td class="month" rowspan={timeMap.months[line]} onclick={e => toggleRange(time.start_time.substring(0,7))}>
{time.start_time.substring(5,7)}
</td>
{/if}
{#if detail == time.id}
<tr>
<td colspan="5">
<TimeEditor record={time} onSet={update} />
</td>
</tr>
{:else}
<tr onclick={e => {detail = time.id}}>
<td class="start_end">
<td class="start_end" onclick={e => toggleSelect(time.id)}>
{time.start_time}{#if time.end_time}{time.end_time}{/if}
</td>
<td class="duration">{#if time.duration}
<td class="duration" onclick={e => {detail = time.id}}>
{#if time.duration}
{time.duration.toFixed(3)}&nbsp;h
{/if}
</td>
<td class="subject">
<td class="subject" onclick={e => {detail = time.id}}>
{time.subject}
</td>
<td class="tasks">
<td class="tasks" onclick={e => {detail = time.id}}>
{#each Object.entries(time.tasks) as [tid,task]}
<a href="#" onclick={e => openTask(tid)}>{task}</a>
{/each}
</td>
<td class="state">
<td class="state" onclick={e => {detail = time.id}}>
{t("state_"+time.state.name.toLowerCase())}
</td>
</tr>
{/if}
</tr>
{/each}
</tbody>
</table>

Loading…
Cancel
Save