You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
142 lines
4.1 KiB
142 lines
4.1 KiB
<script lang="ts">
|
|
import LogEntry from "../components/LogEntry.svelte";
|
|
import type { LogResult } from "../models/log";
|
|
import logStore from "../stores/logs";
|
|
import { endOfWeek, formatFormTime, formatWeekdayDate, startOfWeek } from "../utils/time";
|
|
import EmptyList from "../components/EmptyList.svelte";
|
|
import RefreshSelection from "../components/RefreshSelection.svelte";
|
|
import DateRangeSelect from "../components/DateRangeSelect.svelte";
|
|
import EveryMinute from "../components/EveryMinute.svelte";
|
|
|
|
let groupedLogs: {day: number, text: string, logs: LogResult[]}[] = [];
|
|
let minTime = formatFormTime($logStore.filter.minTime || startOfWeek(new Date()));
|
|
let maxTime = formatFormTime(endOfWeek(new Date()));
|
|
let emptyMessage = `No logs since ${formatWeekdayDate(minTime)}.`;
|
|
let error = "";
|
|
let now = new Date();
|
|
|
|
$: {
|
|
const min = new Date(minTime);
|
|
const max = new Date(maxTime);
|
|
|
|
error = "";
|
|
|
|
if (!Number.isNaN(min.getTime()) && !Number.isNaN(max.getTime())) {
|
|
if (min.getTime() < max.getTime()) {
|
|
if (!$logStore.loading) {
|
|
if ($logStore.stale || $logStore.filter.minTime?.getTime() != min.getTime() || $logStore.filter.maxTime?.getTime() != max.getTime()) {
|
|
logStore.load({
|
|
minTime: min,
|
|
maxTime: max,
|
|
});
|
|
}
|
|
}
|
|
} else {
|
|
error = "Time only goes one way in this universe, you should respect that."
|
|
}
|
|
} else {
|
|
error = "The dates must be valid."
|
|
}
|
|
}
|
|
|
|
$: {
|
|
if (!$logStore.loading && !$logStore.stale) {
|
|
emptyMessage = `No logs between ${formatWeekdayDate(minTime)} and ${formatWeekdayDate(maxTime)}.`;
|
|
}
|
|
}
|
|
|
|
$: {
|
|
if (!$logStore.loading) {
|
|
groupedLogs = [];
|
|
|
|
if ($logStore.logs.length > 0) {
|
|
const firstUtc = Math.floor(Date.parse($logStore.logs[0].loggedTime) / 86400000) * 86400000;
|
|
const todayUtc = Math.floor(now.getTime() / 86400000) * 86400000;
|
|
const first = firstUtc + (now.getTimezoneOffset() * 60000);
|
|
const today = todayUtc + (now.getTimezoneOffset() * 60000);
|
|
const yesterday = today - 86400000;
|
|
const tomorrow = today + 86400000;
|
|
|
|
let currentDay = first;
|
|
let remainingLogs = $logStore.logs;
|
|
|
|
while (remainingLogs.length > 0) {
|
|
const currentLogs: LogResult[] = [];
|
|
for (const log of remainingLogs) {
|
|
if (Date.parse(log.loggedTime) >= currentDay) {
|
|
currentLogs.push(log);
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (currentLogs.length > 0) {
|
|
remainingLogs = remainingLogs.slice(currentLogs.length);
|
|
|
|
let text = formatWeekdayDate(currentDay);
|
|
if (currentDay === tomorrow) {
|
|
text = "Tomorrow";
|
|
} else if (currentDay === today) {
|
|
text = "Today";
|
|
} else if (currentDay === yesterday) {
|
|
text = "Yesterday";
|
|
}
|
|
|
|
groupedLogs.push({day: currentDay, text, logs: currentLogs});
|
|
}
|
|
|
|
currentDay -= 86400000;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<div class="page">
|
|
<DateRangeSelect label="Time Filter" noFuture styled bind:fromValue={minTime} bind:toValue={maxTime} />
|
|
<div class="error">{error}</div>
|
|
<div class="log-list" class:loading={$logStore.loading}>
|
|
{#each groupedLogs as logGroup (logGroup.day)}
|
|
<h2>{logGroup.text}</h2>
|
|
{#each logGroup.logs as log (log.id)}
|
|
<LogEntry log={log} />
|
|
{/each}
|
|
{/each}
|
|
{#if groupedLogs.length === 0}
|
|
<EmptyList icon="list" text={emptyMessage} />
|
|
{/if}
|
|
</div>
|
|
</div>
|
|
<RefreshSelection />
|
|
<EveryMinute bind:now={now} />
|
|
|
|
<style>
|
|
div.error {
|
|
color: #ff4545;
|
|
text-align: center;
|
|
}
|
|
div.error:empty {
|
|
display: none;
|
|
}
|
|
|
|
div.page {
|
|
display: block;
|
|
margin: auto;
|
|
max-width: 100%;
|
|
width: 640px;
|
|
margin-top: 0;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
div.log-list.loading {
|
|
opacity: 0.75;
|
|
}
|
|
|
|
h2 {
|
|
font-size: 1.5em;
|
|
font-weight: 100;
|
|
text-align: center;
|
|
margin: 0;
|
|
margin-top: 1em;
|
|
}
|
|
</style>
|