implemented selection functions
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
@@ -11,6 +11,50 @@
|
|||||||
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)));
|
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(){
|
async function loadTimes(){
|
||||||
const url = api('time');
|
const url = api('time');
|
||||||
@@ -26,6 +70,26 @@
|
|||||||
router.navigate(`task/${tid}/view`);
|
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){
|
async function update(time){
|
||||||
const url = api(`time/${time.id}`);
|
const url = api(`time/${time.id}`);
|
||||||
time.start_time = time.start_time.split(':').slice(0,2).join(':');
|
time.start_time = time.start_time.split(':').slice(0,2).join(':');
|
||||||
@@ -53,6 +117,12 @@
|
|||||||
|
|
||||||
<style>
|
<style>
|
||||||
td { vertical-align: top; }
|
td { vertical-align: top; }
|
||||||
|
.year, .month{
|
||||||
|
border: 1px solid;
|
||||||
|
}
|
||||||
|
.selected td:not(.year):not(.month){
|
||||||
|
background: navy;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<h1>{t('timetracking')}</h1>
|
<h1>{t('timetracking')}</h1>
|
||||||
@@ -63,6 +133,8 @@
|
|||||||
<table class="timetracks">
|
<table class="timetracks">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
<th>{t('year')}</th>
|
||||||
|
<th>{t('month')}</th>
|
||||||
<th>{t('start_end')}</th>
|
<th>{t('start_end')}</th>
|
||||||
<th>{t('duration')}</th>
|
<th>{t('duration')}</th>
|
||||||
<th>{t('subject')}</th>
|
<th>{t('subject')}</th>
|
||||||
@@ -71,35 +143,44 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{#each sortedTimes as time}
|
{#each sortedTimes as time,line}
|
||||||
{#if detail == time.id}
|
<tr class={selected[time.id]?'selected':''}>
|
||||||
<tr>
|
{#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}
|
||||||
<td colspan="5">
|
<td colspan="5">
|
||||||
<TimeEditor record={time} onSet={update} />
|
<TimeEditor record={time} onSet={update} />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
{:else}
|
||||||
{:else}
|
<td class="start_end" onclick={e => toggleSelect(time.id)}>
|
||||||
<tr onclick={e => {detail = time.id}}>
|
|
||||||
<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>
|
||||||
<td class="duration">{#if time.duration}
|
<td class="duration" onclick={e => {detail = time.id}}>
|
||||||
|
{#if time.duration}
|
||||||
{time.duration.toFixed(3)} h
|
{time.duration.toFixed(3)} h
|
||||||
{/if}
|
{/if}
|
||||||
</td>
|
</td>
|
||||||
<td class="subject">
|
<td class="subject" onclick={e => {detail = time.id}}>
|
||||||
{time.subject}
|
{time.subject}
|
||||||
</td>
|
</td>
|
||||||
<td class="tasks">
|
<td class="tasks" onclick={e => {detail = time.id}}>
|
||||||
{#each Object.entries(time.tasks) as [tid,task]}
|
{#each Object.entries(time.tasks) as [tid,task]}
|
||||||
<a href="#" onclick={e => openTask(tid)}>{task}</a>
|
<a href="#" onclick={e => openTask(tid)}>{task}</a>
|
||||||
{/each}
|
{/each}
|
||||||
</td>
|
</td>
|
||||||
<td class="state">
|
<td class="state" onclick={e => {detail = time.id}}>
|
||||||
{t("state_"+time.state.name.toLowerCase())}
|
{t("state_"+time.state.name.toLowerCase())}
|
||||||
</td>
|
</td>
|
||||||
|
{/if}
|
||||||
</tr>
|
</tr>
|
||||||
{/if}
|
|
||||||
{/each}
|
{/each}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
Reference in New Issue
Block a user