added better deadline and date range selectors.
continuous-integration/drone/push Build is passing

This commit is contained in:
2021-01-24 17:10:52 +01:00
parent ef94b1556a
commit afa5fa00cb
8 changed files with 353 additions and 24 deletions
@@ -0,0 +1,127 @@
<script lang="ts">
import { onMount } from "svelte";
import { endOfMonth, endOfWeek, endOfYear, formatFormTime, lastMonth, monthName, nextMonth, startOfMonth, startOfWeek, startOfYear } from "../utils/time";
import EveryMinute from "./EveryMinute.svelte";
interface DateOption {
id: string
label: string
from: Date
to: Date
}
export let fromValue: string;
export let toValue: string;
export let disabled: boolean;
export let styled: boolean;
let selected: string = "custom";
let options: DateOption[] = [];
let now: Date = new Date();
onMount(() => {
for (const option of options) {
if (formatFormTime(option.from) === fromValue && formatFormTime(option.to) === toValue) {
selected = option.id;
}
}
});
$: {
if (options.length === 0) {
let current = startOfMonth(now);
const nextWeek = new Date(Date.now() + (86400000 * 7));
const lastWeek = new Date(Date.now() - (86400000 * 7));
options.push({
id: "this_week",
label: "This Week",
from: startOfWeek(now),
to: endOfWeek(now),
});
options.push({
id: "next_week",
label: "Next Week",
from: startOfWeek(nextWeek),
to: endOfWeek(nextWeek),
});
options.push({
id: "last_week",
label: "Last Week",
from: startOfWeek(lastWeek),
to: endOfWeek(lastWeek),
});
options.push({
id: "this_month",
label: "This Month",
from: current,
to: endOfMonth(current),
});
options.push({
id: "next_month",
label: "Next Month",
from: nextMonth(current),
to: endOfMonth(nextMonth(current)),
});
options.push({
id: "last_month",
label: "Last Month",
from: lastMonth(current),
to: endOfMonth(lastMonth(current)),
});
options.push({
id: "this_year",
label: "This Year",
from: startOfYear(now),
to: endOfYear(now),
});
options.push({
id: "next_year",
label: "Next Year",
from: startOfYear(new Date(Date.now() + (366.25 * 86400000))),
to: endOfYear(new Date(Date.now() + (365.25 * 86400000))),
});
options.push({
id: "last_year",
label: "Last Year",
from: startOfYear(new Date(Date.now() - (365.25 * 86400000))),
to: endOfYear(new Date(Date.now() - (365.25 * 86400000))),
});
options.push({
id: "custom",
label: "Specific Dates",
from: null,
to: null,
});
}
}
$: {
if (selected !== "custom") {
const option = options.find(o => o.id === selected);
if (option != null) {
fromValue = formatFormTime(option.from);
toValue = formatFormTime(option.to);
}
}
}
</script>
<EveryMinute bind:now={now} />
<div class:styled>
<label for="timeRange">Time Period</label>
<select name="timeRange" disabled={disabled} bind:value={selected}>
{#each options as option (option.id)}
<option value={option.id}>{option.label}</option>
{/each}
</select>
{#if selected === "custom"}
<label for="startTime">Start Time</label>
<input disabled={disabled} name="startTime" type="datetime-local" bind:value={fromValue} />
<label for="endTime">End Time</label>
<input disabled={disabled} name="endTime" type="datetime-local" bind:value={toValue} />
{/if}
</div>
@@ -0,0 +1,118 @@
<script lang="ts">
import { onMount } from "svelte";
import { endOfMonth, endOfWeek, endOfYear, formatFormTime, lastMonth, monthName, nextMonth, startOfMonth, startOfWeek, startOfYear } from "../utils/time";
import EveryMinute from "./EveryMinute.svelte";
interface DateOption {
id: string
label: string
value: Date
}
export let value: string;
export let disabled: boolean;
let selected: string = "custom";
let options: DateOption[] = [];
let now: Date = new Date();
onMount(() => {
if (value === "") {
selected = "none";
return;
}
for (const option of options) {
if (formatFormTime(option.value) === value) {
selected = option.id;
}
}
});
$: {
if (options.length === 0) {
let current = startOfMonth(now);
const nextWeek = new Date(now.getTime() + (86400000 * 7));
const lastWeek = new Date(now.getTime() - (86400000 * 7));
options.push({
id: "none",
label: "No deadline",
value: new Date(Number.NaN),
});
options.push({
id: "this_week",
label: "End of this Week",
value: endOfWeek(now),
});
options.push({
id: "next_week",
label: "End of next Week",
value: endOfWeek(nextWeek),
});
options.push({
id: "last_week",
label: "End of last Week",
value: endOfWeek(lastWeek),
});
options.push({
id: "this_month",
label: "End of this month",
value: endOfMonth(current),
});
options.push({
id: "next_month",
label: "End of next month",
value: endOfMonth(nextMonth(current)),
});
options.push({
id: "last_month",
label: "End of last month",
value: endOfMonth(lastMonth(current)),
});
options.push({
id: "this_year",
label: "This Year",
value: endOfYear(now),
});
options.push({
id: "next_year",
label: "Next Year",
value: endOfYear(new Date(Date.now() + (365.25 * 86400000))),
});
options.push({
id: "last_year",
label: "Last Year",
value: endOfYear(new Date(Date.now() - (365.25 * 86400000))),
});
options.push({
id: "custom",
label: "Specific Dates",
value: null,
});
}
}
$: {
if (selected !== "custom") {
const option = options.find(o => o.id === selected);
if (option != null) {
value = formatFormTime(option.value);
}
}
}
</script>
<EveryMinute bind:now={now} />
<select name="endTime" disabled={disabled} bind:value={selected}>
{#each options as option (option.id)}
<option value={option.id}>{option.label}</option>
{/each}
</select>
{#if selected === "custom"}
<input disabled={disabled} name="value" type="datetime-local" bind:value={value} />
{/if}
+1 -1
View File
@@ -107,7 +107,7 @@ import TimeProgress from "./TimeProgress.svelte";
padding: 0 0.5ch;
width: 2ch;
padding-top: 0.125em;
color: #333;
color: #444;
}
div.icon.completed {
color: #484;
+10 -16
View File
@@ -26,6 +26,7 @@
let completedTasks: TaskResult[] = [];
let onholdTasks: TaskResult[] = [];
let failedTasks: TaskResult[] = [];
let nonHiddenTasks: TaskResult[] = [];
$: mdAddTask = {name:"task.add", project};
$: mdProjectEdit = {name:"project.edit", project};
@@ -33,25 +34,18 @@
$: {
activeTasks = project.tasks.filter(t => t.active);
inactiveTasks = project.tasks.filter(t => !t.active);
if (!hideInactive) {
inactiveTasks = project.tasks.filter(t => !t.active);
todoTasks = inactiveTasks.filter(t => t.statusTag === "to do" || t.statusTag === "idea");
onholdTasks = inactiveTasks.filter(t => t.statusTag === "on hold");
completedTasks = inactiveTasks.filter(t => t.statusTag === "completed" || t.statusTag == null);
failedTasks = inactiveTasks.filter(t => t.statusTag === "failed" || t.statusTag === "declined");
todoTasks = inactiveTasks.filter(t => t.statusTag === "to do" || t.statusTag === "idea");
completedTasks = inactiveTasks.filter(t => t.statusTag === "completed" || t.statusTag == null);
onholdTasks = inactiveTasks.filter(t => t.statusTag === "on hold" || t.statusTag === "postponed");
failedTasks = inactiveTasks.filter(t => t.statusTag === "failed" || t.statusTag === "declined" || t.statusTag === "wont do");
} else {
inactiveTasks = [];
todoTasks = [];
completedTasks = [];
onholdTasks = [];
failedTasks = [];
}
nonHiddenTasks = [...activeTasks, ...todoTasks, ...onholdTasks];
}
</script>
<StatusColor affects="project" selected entry={project}>
<StatusColor affects="project" entry={project}>
<ParentEntry
full={showAllOptions}
entry={project}
@@ -69,12 +63,12 @@
</OptionRow>
{/if}
{#if hideInactive}
<TaskList header="" tasks={activeTasks} project={project} showAllOptions={showAllOptions} />
<TaskList header="" tasks={nonHiddenTasks} project={project} showAllOptions={showAllOptions} />
{:else}
<TaskList header="Active" tasks={activeTasks} project={project} showAllOptions={showAllOptions} />
<TaskList header="To Do" tasks={todoTasks} project={project} showAllOptions={showAllOptions} />
<TaskList header="Completed" tasks={completedTasks} project={project} showAllOptions={showAllOptions} />
<TaskList header="On Hold" tasks={onholdTasks} project={project} showAllOptions={showAllOptions} />
<TaskList header="Completed" tasks={completedTasks} project={project} showAllOptions={showAllOptions} />
<TaskList header="Failed" tasks={failedTasks} project={project} showAllOptions={showAllOptions} />
{/if}
</ParentEntry>
+52 -1
View File
@@ -1,6 +1,10 @@
<script lang="ts">
import { tick } from "svelte";
import stuffLogClient from "../clients/stufflog";
import type Project from "../models/project";
import type { TaskResult } from "../models/task";
import type { TaskResult, TaskUpdate } from "../models/task";
import markStale from "../stores/markStale";
import type { ModalData } from "../stores/modal";
import ChildEntry from "./ChildEntry.svelte";
import DateSpan from "./DateSpan.svelte";
@@ -19,11 +23,42 @@
let mdLogAdd: ModalData;
let mdTaskEdit: ModalData;
let mdTaskDelete: ModalData;
let isMoving = false;
function toggleShowLogs() {
showLogs = !showLogs;
}
function updateTask(update: TaskUpdate) {
isMoving = true;
stuffLogClient.updateTask(task.id, update).finally(() => {
markStale("task", "project");
tick().then(() => {
isMoving = false;
});
});
}
function moveToActive() {
updateTask({clearStatusTag: true, active: true});
}
function moveToToDo() {
updateTask({statusTag: "to do", active: false});
}
function moveToOnHold() {
updateTask({statusTag: "on hold", active: false});
}
function moveToFailed() {
updateTask({statusTag: "failed", active: false});
}
function moveToDeclined() {
updateTask({statusTag: "declined", active: false});
}
$: mdLogAdd = {name: "log.add", task: {...task, project}};
$: mdTaskEdit = {name: "task.edit", task: {...task, project}};
$: mdTaskDelete = {name: "task.delete", task: {...task, project}};
@@ -43,6 +78,22 @@
{#if showAllOptions}
<Option open={mdTaskEdit}>Edit</Option>
<Option open={mdTaskDelete}>Delete</Option>
·
{#if !isMoving && (!task.active) }
<Option on:click={moveToActive}>Active</Option>
{/if}
{#if !isMoving && (task.statusTag !== "to do") }
<Option on:click={moveToToDo}>To Do</Option>
{/if}
{#if !isMoving && (task.statusTag !== "on hold") }
<Option on:click={moveToOnHold}>On Hold</Option>
{/if}
{#if !isMoving && (task.statusTag !== "declined") }
<Option on:click={moveToDeclined}>Won't Do</Option>
{/if}
{#if !isMoving && (task.statusTag !== "failed") }
<Option on:click={moveToFailed}>Failed</Option>
{/if}
{/if}
</OptionRow>
{#if showLogs && task.logs.length > 0}