add log filters for project group, project and item.
continuous-integration/drone/push Build is passing

This commit is contained in:
2021-08-09 18:58:00 +02:00
parent 7973373419
commit f7d7d99c83
12 changed files with 177 additions and 33 deletions
+10 -1
View File
@@ -131,7 +131,7 @@ export class StufflogClient {
return data.log;
}
async listLogs({minTime, maxTime}: LogFilter): Promise<LogResult[]> {
async listLogs({minTime, maxTime, itemIds, projectIds, projectGroupIds}: LogFilter): Promise<LogResult[]> {
let queries = [];
if (minTime != null) {
queries.push(`minTime=${minTime.toISOString()}`);
@@ -139,6 +139,15 @@ export class StufflogClient {
if (maxTime != null) {
queries.push(`maxTime=${maxTime.toISOString()}`);
}
if (itemIds != null) {
queries.push(`items=${itemIds.join(",")}`)
}
if (projectIds != null) {
queries.push(`projects=${projectIds.join(",")}`)
}
if (projectGroupIds != null) {
queries.push(`groups=${projectGroupIds.join(",")}`)
}
const query = queries.length > 0 ? `?${queries.join("&")}` : "";
@@ -65,14 +65,19 @@ div.styled > div:first {
}
div.styled > div {
padding: 0.5em;
padding: 0 0.5em;
margin: 0 auto;
width: 35%;
}
div.styled label {
line-height: 1.5em;
}
div.styled select, div.styled input {
width: 100%;
margin-bottom: 0.5em;
padding: 0.35em;
background: #222;
color: #777;
@@ -5,6 +5,7 @@
export let name = "";
export let disabled = false;
export let optional = false;
export let enableWholeGroup = false;
$: {
if ($groupStore.stale && !$groupStore.loading) {
@@ -28,6 +29,9 @@
{/if}
{#each $groupStore.groups as group (group.id)}
<optgroup label={group.name}>
{#if enableWholeGroup}
<option value={group.items.map(it => it.id).join(",")}>All "{group.name}" items</option>
{/if}
{#each group.items as item (item.id)}
<option value={item.id} selected={item.id === value}>{item.name} ({item.groupWeight})</option>
{/each}
@@ -9,7 +9,7 @@
<select name={name} bind:value={value} disabled={disabled || $projectGroupStore.loading}>
{#if optional}
<option value={""} selected={"" === value}>None</option>
<option value={""} selected={"" === value}>{$projectGroupStore.loading ? "Loading..." : "None"}</option>
{/if}
{#each $projectGroupStore.groups as group (group.id)}
{#if group.id !== "META_UNGROUPED"}
@@ -12,6 +12,7 @@ import projectGroupStore from "../stores/projectGroup";
export let groupId = "";
export let disabled = false;
export let optional = false;
export let forceGroup = false;
let optGroups: OptGroup[]
@@ -23,7 +24,13 @@ import projectGroupStore from "../stores/projectGroup";
if (group != null) {
projects = group.projects;
labels = group.categoryNames;
if (forceGroup && !group.projects.find(p => p.id === value)) {
value = "";
}
}
} else if (forceGroup) {
value = "";
}
optGroups = [
@@ -78,7 +85,7 @@ import projectGroupStore from "../stores/projectGroup";
<select name={name} bind:value={value} disabled={disabled || $projectStore.loading}>
{#if optional}
<option value={""} selected={"" === value}>None</option>
<option value={""} selected={"" === value}>{$projectStore.loading ? "Loading..." : "None"}</option>
{/if}
{#each optGroups as group (group.status)}
{#if group.projects.length > 0}
+3
View File
@@ -15,6 +15,9 @@ export default interface Log {
export interface LogFilter {
minTime?: Date
maxTime?: Date
itemIds?: string[]
projectIds?: string[]
projectGroupIds?: string[]
}
export interface LogResult extends Log {
+96 -11
View File
@@ -1,28 +1,52 @@
<script lang="ts">
import LogEntry from "../components/LogEntry.svelte";
import type { LogResult } from "../models/log";
import type { LogFilter, LogResult } from "../models/log";
import logStore from "../stores/logs";
import { addDays, endOfDay, endOfWeek, formatFormTime, formatWeekdayDate, startOfDay, startOfWeek } from "../utils/time";
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 { allOffsets, RelativeDateRange } from "../utils/date-range";
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 = `No logs since ${formatWeekdayDate(range.calculate(now)[0])}.`;
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 = "";
@@ -30,11 +54,16 @@
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,
});
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 {
@@ -47,7 +76,9 @@
$: {
if (!$logStore.loading && !$logStore.stale) {
emptyMessage = `No logs between ${formatWeekdayDate(min)} and ${formatWeekdayDate(max)}.`;
emptyMessage = `No matching logs between ${formatWeekdayDate(min)} and ${formatWeekdayDate(max)}.`;
} else {
emptyMessage = "Loading...";
}
}
@@ -101,6 +132,20 @@
<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())}
@@ -139,6 +184,35 @@
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;
@@ -146,4 +220,15 @@
margin: 0;
margin-top: 1em;
}
@media screen and (max-width: 900px) {
div.extra-filters {
flex-direction: column;
}
div.filter-group {
width: 90%;
}
}
</style>