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.
 
 
 
 
 
 

234 lines
6.4 KiB

<script lang="ts">
import LogEntry from "../components/LogEntry.svelte";
import type { LogFilter, LogResult } from "../models/log";
import logStore from "../stores/logs";
import { addDays, formatWeekdayDate, startOfDay } from "../utils/time";
import { allOffsets, RelativeDateRange } from "../utils/date-range";
import EmptyList from "../components/EmptyList.svelte";
import RefreshSelection from "../components/RefreshSelection.svelte";
import DateRangeSelect from "../components/DateRangeSelect.svelte";
import EveryMinute from "../components/EveryMinute.svelte";
import ProjectGroupSelect from "../components/ProjectGroupSelect.svelte";
import ProjectSelect from "../components/ProjectSelect.svelte";
import ItemSelect from "../components/ItemSelect.svelte";
import projectStore from "../stores/project";
import projectGroupStore from "../stores/projectGroup";
const lsValue = localStorage.getItem("sl2.logspage.range")
let groupedLogs: {day: Date, text: string, logs: LogResult[]}[] = [];
let range = allOffsets.find(o => o.name === lsValue) || new RelativeDateRange(-7, "day");
let now = new Date();
let error = "";
let emptyMessage = "Loading...";
let min: Date;
let max: Date;
let projectGroupId = localStorage.getItem("sl2.logspage.project_group_id");
let projectId = localStorage.getItem("sl2.logspage.project_id");
let itemId = localStorage.getItem("sl2.logspage.item_id");
$: [min, max] = range.calculate(now);
$: localStorage.setItem("sl2.logspage.range", range.name);
$: localStorage.setItem("sl2.logspage.project_group_id", projectGroupId);
$: localStorage.setItem("sl2.logspage.project_id", projectId);
$: localStorage.setItem("sl2.logspage.item_id", itemId);
$: {
if ($projectStore.stale && !$projectStore.loading) {
projectStore.load({});
}
}
$: {
if ($projectGroupStore.stale && !$projectGroupStore.loading) {
projectGroupStore.load();
}
}
$: {
error = "";
if (!Number.isNaN(min.getTime()) && !Number.isNaN(max.getTime())) {
if (min.getTime() < max.getTime()) {
if (!$logStore.loading) {
const filter: LogFilter = {
minTime: min,
maxTime: max,
itemIds: itemId ? itemId.split(",") : void(0),
projectIds: projectId ? [projectId] : void(0),
projectGroupIds: (!projectId && projectGroupId) ? [projectGroupId] : void(0),
}
if ($logStore.stale || JSON.stringify(filter) !== JSON.stringify($logStore.filter)) {
logStore.load(filter);
}
}
} 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 matching logs between ${formatWeekdayDate(min)} and ${formatWeekdayDate(max)}.`;
} else {
emptyMessage = "Loading...";
}
}
$: {
if (!$logStore.loading) {
groupedLogs = [];
if ($logStore.logs.length > 0) {
const today = new Date();
const tomorrow = addDays(today, 1);
const yesterday = addDays(today, -1);
let current = new Date($logStore.logs[0].loggedTime);
let remainingLogs = $logStore.logs;
while (remainingLogs.length > 0) {
const currentDay = startOfDay(current);
const currentLogs: LogResult[] = [];
for (const log of remainingLogs) {
if (Date.parse(log.loggedTime) >= currentDay.getTime()) {
currentLogs.push(log);
} else {
break;
}
}
if (currentLogs.length > 0) {
remainingLogs = remainingLogs.slice(currentLogs.length);
let text = formatWeekdayDate(current);
if (current.getTime() === tomorrow.getTime()) {
text = "Tomorrow";
} else if (current.getTime() === today.getTime()) {
text = "Today";
} else if (current.getTime() === yesterday.getTime()) {
text = "Yesterday";
}
groupedLogs.push({day: current, text, logs: currentLogs});
}
current = addDays(current, -1);
}
}
}
}
</script>
<div class="page">
<DateRangeSelect label="Time Filter" noFuture styled bind:value={range} />
<div class="extra-filters">
<div class="filter-group">
<label for="projectGroup">Project Group</label>
<ProjectGroupSelect name="projectGroup" optional bind:value={projectGroupId} />
</div>
<div class="filter-group">
<label for="project">Project</label>
<ProjectSelect name="project" disabled={projectGroupId === ""} optional bind:value={projectId} groupId={projectGroupId} forceGroup />
</div>
<div class="filter-group">
<label for="item">Item</label>
<ItemSelect name="item" optional bind:value={itemId} enableWholeGroup />
</div>
</div>
<div class="error">{error}</div>
<div class="log-list" class:loading={$logStore.loading}>
{#each groupedLogs as logGroup (logGroup.day.getTime())}
<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;
}
div.extra-filters {
display: flex;
flex-direction: row;
}
div.filter-group {
flex: 1;
padding: 0 0.5em;
margin: 0 auto;
}
div.filter-group label {
line-height: 1.5em;
}
div.filter-group :global(select) {
width: 100%;
margin-bottom: 0.5em;
background: #222;
color: #777;
border: none;
outline: none;
resize: vertical;
}
div.filter-group :global(select:focus) {
background: #191919;
color: #CCC;
border: none;
outline: none;
}
h2 {
font-size: 1.5em;
font-weight: 100;
text-align: center;
margin: 0;
margin-top: 1em;
}
@media screen and (max-width: 900px) {
div.extra-filters {
flex-direction: column;
}
div.filter-group {
width: 90%;
}
}
</style>