add status tags to tasks and reorganize them to have more familiar names.
continuous-integration/drone/push Build is passing
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -60,7 +60,7 @@
|
||||
|
||||
// Mark it non-segmented if the target is too high. This prevents a clunky progress bar,
|
||||
// or a browser freeze if you set the target very high.
|
||||
nonSegmented = (target >= 50);
|
||||
nonSegmented = (target >= 60);
|
||||
}
|
||||
|
||||
$: {
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
<script lang="ts">
|
||||
import type { ProjectResult } from "../models/project";
|
||||
import type { TaskResult } from "../models/task";
|
||||
import type { TaskResult } from "../models/task";
|
||||
import type { ModalData } from "../stores/modal";
|
||||
import projectStore from "../stores/project";
|
||||
import taskStore from "../stores/tasks";
|
||||
import Composition from "./Composition.svelte";
|
||||
import Option from "./Option.svelte";
|
||||
import OptionRow from "./OptionRow.svelte";
|
||||
import ParentEntry from "./ParentEntry.svelte";
|
||||
import StatusColor from "./StatusColor.svelte";
|
||||
import TaskEntry from "./TaskEntry.svelte";
|
||||
import StatusColor from "./StatusColor.svelte";
|
||||
import TaskList from "./TaskList.svelte";
|
||||
|
||||
export let project: ProjectResult = null;
|
||||
export let showAllOptions: boolean = false;
|
||||
@@ -22,12 +19,38 @@ import StatusColor from "./StatusColor.svelte";
|
||||
let mdProjectEdit: ModalData;
|
||||
let mdProjectDelete: ModalData;
|
||||
|
||||
let activeTasks: TaskResult[] = [];
|
||||
let inactiveTasks: TaskResult[] = [];
|
||||
let completedTasks: TaskResult[] = [];
|
||||
let todoTasks: TaskResult[] = [];
|
||||
let onholdTasks: TaskResult[] = [];
|
||||
let failedTasks: TaskResult[] = [];
|
||||
|
||||
$: mdAddTask = {name:"task.add", project};
|
||||
$: mdProjectEdit = {name:"project.edit", project};
|
||||
$: mdProjectDelete = {name:"project.delete", project};
|
||||
|
||||
$: {
|
||||
activeTasks = project.tasks.filter(t => t.active);
|
||||
|
||||
if (!hideInactive) {
|
||||
inactiveTasks = project.tasks.filter(t => !t.active);
|
||||
|
||||
completedTasks = inactiveTasks.filter(t => t.statusTag === "completed" || t.statusTag == null);
|
||||
todoTasks = inactiveTasks.filter(t => t.statusTag === "to do" || t.statusTag === "idea");
|
||||
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 = [];
|
||||
completedTasks = [];
|
||||
todoTasks = [];
|
||||
onholdTasks = [];
|
||||
failedTasks = [];
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<StatusColor selected project={project}>
|
||||
<StatusColor affects="project" selected entry={project}>
|
||||
<ParentEntry
|
||||
full={showAllOptions}
|
||||
entry={project}
|
||||
@@ -43,10 +66,14 @@ import StatusColor from "./StatusColor.svelte";
|
||||
<Option open={mdProjectDelete}>Delete</Option>
|
||||
</OptionRow>
|
||||
{/if}
|
||||
{#each project.tasks as task (task.id)}
|
||||
{#if !hideInactive || task.active}
|
||||
<TaskEntry showAllOptions={showAllOptions} task={task} project={project} />
|
||||
{/if}
|
||||
{/each}
|
||||
{#if hideInactive}
|
||||
<TaskList header="" tasks={activeTasks} project={project} showAllOptions={showAllOptions} />
|
||||
{:else}
|
||||
<TaskList header="Active" tasks={activeTasks} project={project} showAllOptions={showAllOptions} />
|
||||
<TaskList header="Completed" tasks={completedTasks} project={project} showAllOptions={showAllOptions} />
|
||||
<TaskList header="To Do" tasks={todoTasks} project={project} showAllOptions={showAllOptions} />
|
||||
<TaskList header="On Hold" tasks={onholdTasks} project={project} showAllOptions={showAllOptions} />
|
||||
<TaskList header="Failed" tasks={failedTasks} project={project} showAllOptions={showAllOptions} />
|
||||
{/if}
|
||||
</ParentEntry>
|
||||
</StatusColor>
|
||||
|
||||
@@ -5,37 +5,11 @@
|
||||
|
||||
interface ProjectLike {
|
||||
icon?: IconName
|
||||
active?: boolean
|
||||
statusTag?: string
|
||||
}
|
||||
|
||||
export let project: ProjectLike
|
||||
export let selected: boolean;
|
||||
|
||||
let completed: boolean;
|
||||
let failed: boolean;
|
||||
let postponed: boolean;
|
||||
let idea: boolean;
|
||||
|
||||
$: completed = !project.active && project.statusTag === "completed";
|
||||
$: failed = !project.active && project.statusTag === "failed";
|
||||
$: postponed = !project.active && project.statusTag === "postponed";
|
||||
$: idea = !project.active && project.statusTag === "idea";
|
||||
</script>
|
||||
|
||||
<span class:selected class:completed class:failed class:postponed class:idea>
|
||||
<span class="sccfg" >
|
||||
<Icon block name={project.icon} />
|
||||
</span>
|
||||
|
||||
<style>
|
||||
span { color: #444; }
|
||||
span.selected { color: #666; }
|
||||
span.completed { color: #484; }
|
||||
span.completed.selected { color: #78ff78; }
|
||||
span.failed { color: #884844; }
|
||||
span.failed.selected { color: #ff9878; }
|
||||
span.postponed { color: #446d88; }
|
||||
span.postponed.selected { color: #78c9ff; }
|
||||
span.idea { color: #878844; }
|
||||
span.idea.selected { color: #fffd78; }
|
||||
</style>
|
||||
@@ -22,7 +22,7 @@
|
||||
$: completed = !project.active;
|
||||
</script>
|
||||
|
||||
<StatusColor project={project} selected={selected}>
|
||||
<StatusColor affects="project" entry={project} selected={selected}>
|
||||
<div class="ql-list-item" on:click={handleClick} class:selected>
|
||||
<div class="icon sccfg" class:completed>
|
||||
<Icon block name={project.icon} />
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
$: activeProjects = projects.filter(p => p.active && !p.endTime).sort((a,b) => a.name.localeCompare(b.name));
|
||||
$: inactiveProjects = projects.filter(p => !p.active).sort((a,b) => a.name.localeCompare(b.name));
|
||||
$: completedProjects = inactiveProjects.filter(p => p.statusTag === "completed" || p.statusTag == null);
|
||||
$: failedProjects = inactiveProjects.filter(p => p.statusTag === "failed" || p.statusTag == null);
|
||||
$: postponedProjects = inactiveProjects.filter(p => p.statusTag === "postponed" || p.statusTag == null);
|
||||
$: ideaProjects = inactiveProjects.filter(p => p.statusTag === "idea" || p.statusTag == null);
|
||||
$: failedProjects = inactiveProjects.filter(p => p.statusTag === "failed" || p.statusTag === "declined");
|
||||
$: postponedProjects = inactiveProjects.filter(p => p.statusTag === "on hold" || p.statusTag === "postponed");
|
||||
$: ideaProjects = inactiveProjects.filter(p => p.statusTag === "to do" || p.statusTag === "idea");
|
||||
|
||||
$: {
|
||||
if (project === null && projects.length > 0) {
|
||||
@@ -38,9 +38,9 @@
|
||||
<div class="list">
|
||||
<QlList label="Deadlines" projects={expiringProjects} />
|
||||
<QlList label="Active" projects={activeProjects} />
|
||||
<QlList label="To Do" projects={ideaProjects} />
|
||||
<QlList label="On Hold" projects={postponedProjects} />
|
||||
<QlList label="Completed" projects={completedProjects} />
|
||||
<QlList label="Postponed" projects={postponedProjects} />
|
||||
<QlList label="Ideas" projects={ideaProjects} />
|
||||
<QlList label="Failed" projects={failedProjects} />
|
||||
</div>
|
||||
<div class="body">
|
||||
|
||||
@@ -1,42 +1,58 @@
|
||||
<script lang="ts">
|
||||
interface ProjectLike {
|
||||
interface EntryCommon {
|
||||
active: boolean
|
||||
statusTag?: string
|
||||
}
|
||||
|
||||
export let selected = false;
|
||||
export let project: ProjectLike;
|
||||
export let entry: EntryCommon;
|
||||
export let affects: "project" | "task" = "project";
|
||||
|
||||
let completed: boolean;
|
||||
let failed: boolean;
|
||||
let postponed: boolean;
|
||||
let idea: boolean;
|
||||
let onhold: boolean;
|
||||
let todo: boolean;
|
||||
let wontdo: boolean;
|
||||
let project: boolean;
|
||||
let task: boolean;
|
||||
|
||||
$: completed = !project.active && project.statusTag === "completed";
|
||||
$: failed = !project.active && project.statusTag === "failed";
|
||||
$: postponed = !project.active && project.statusTag === "postponed";
|
||||
$: idea = !project.active && project.statusTag === "idea";
|
||||
$: completed = !entry.active && entry.statusTag === "completed";
|
||||
$: failed = !entry.active && entry.statusTag === "failed";
|
||||
$: onhold = !entry.active && entry.statusTag === "on hold";
|
||||
$: todo = !entry.active && entry.statusTag === "to do";
|
||||
$: wontdo = !entry.active && entry.statusTag === "declined";
|
||||
$: task = affects === "task";
|
||||
$: project = affects === "project";
|
||||
|
||||
</script>
|
||||
|
||||
<div class="status-color-context" class:selected class:completed class:failed class:postponed class:idea>
|
||||
<div class="status-color-context" class:project class:task class:selected class:completed class:failed class:onhold class:todo class:wontdo>
|
||||
<slot></slot>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.status-color-context :global(.sccfg) { color: #444 !important; }
|
||||
.status-color-context.selected :global(.sccfg) { color: #666 !important; }
|
||||
.status-color-context :global(.sccpb) { background-color: #78ff78 !important; }
|
||||
.status-color-context.completed :global(.sccfg) { color: #484 !important; }
|
||||
.status-color-context.completed.selected :global(.sccfg) { color: #78ff78 !important; }
|
||||
.status-color-context.completed :global(.sccpb) { background-color: #78ff78 !important; }
|
||||
.status-color-context.failed :global(.sccfg) { color: #852a24 !important; }
|
||||
.status-color-context.failed.selected :global(.sccfg) { color: #ff4545 !important; }
|
||||
.status-color-context.failed :global(.sccpb) { background-color: #ff4545 !important; }
|
||||
.status-color-context.postponed :global(.sccfg) { color: #446d88 !important; }
|
||||
.status-color-context.postponed.selected :global(.sccfg) { color: #78c9ff !important; }
|
||||
.status-color-context.postponed :global(.sccpb) { background-color: #78c9ff !important; }
|
||||
.status-color-context.idea :global(.sccfg) { color: #878844 !important; }
|
||||
.status-color-context.idea.selected :global(.sccfg) { color: #e7e55e !important; }
|
||||
.status-color-context.idea :global(.sccpb) { background-color: #e7e55e !important; }
|
||||
.status-color-context.project :global(.sccfg) { color: #444 !important; }
|
||||
.status-color-context.project.selected :global(.sccfg) { color: #666 !important; }
|
||||
.status-color-context.project :global(.sccpb) { background-color: #78ff78 !important; }
|
||||
.status-color-context.project.completed :global(.sccfg) { color: #484 !important; }
|
||||
.status-color-context.project.completed.selected :global(.sccfg) { color: #78ff78 !important; }
|
||||
.status-color-context.project.completed :global(.sccpb) { background-color: #78ff78 !important; }
|
||||
.status-color-context.project.failed :global(.sccfg) { color: #852a24 !important; }
|
||||
.status-color-context.project.failed.selected :global(.sccfg) { color: #ff4545 !important; }
|
||||
.status-color-context.project.failed :global(.sccpb) { background-color: #ff4545 !important; }
|
||||
.status-color-context.project.onhold :global(.sccfg) { color: #446d88 !important; }
|
||||
.status-color-context.project.onhold.selected :global(.sccfg) { color: #78c9ff !important; }
|
||||
.status-color-context.project.onhold :global(.sccpb) { background-color: #78c9ff !important; }
|
||||
.status-color-context.project.todo :global(.sccfg) { color: #7a7429 !important; }
|
||||
.status-color-context.project.todo.selected :global(.sccfg) { color: #e7e55e !important; }
|
||||
.status-color-context.project.todo :global(.sccpb) { background-color: #e7e55e !important; }
|
||||
.status-color-context.project.wontdo :global(.sccfg) { color: #7a2973 !important; }
|
||||
.status-color-context.project.wontdo.selected :global(.sccfg) { color: #e75ed0 !important; }
|
||||
.status-color-context.project.wontdo :global(.sccpb) { background-color: #e75ed0 !important; }
|
||||
|
||||
.status-color-context.task.completed :global(.sccsi) { background-color: #484 !important; color: #78ff78 !important; }
|
||||
.status-color-context.task.failed :global(.sccsi) { background-color: #85242c !important; color: #ff4545 !important; }
|
||||
.status-color-context.task.onhold :global(.sccsi) { background-color: #447288 !important; color: #78c9ff !important; }
|
||||
.status-color-context.task.todo :global(.sccsi) { background-color: #7a7429 !important; color: #e7e55e !important; }
|
||||
.status-color-context.task.wontdo :global(.sccsi) { background-color: #7a2973 !important; color: #e75ed0 !important; }
|
||||
</style>
|
||||
@@ -0,0 +1,13 @@
|
||||
<script lang="ts">
|
||||
export let value: string;
|
||||
export let disabled: boolean = false;
|
||||
</script>
|
||||
|
||||
<select name="statusTag" bind:value={value} disabled={disabled}>
|
||||
<option value="" selected={"" === value}>Active / In Progress</option>
|
||||
<option value="completed" selected={"completed" === value}>Completed</option>
|
||||
<option value="failed" selected={"failed" === value}>Failed</option>
|
||||
<option value="on hold" selected={"on hold" === value}>On Hold</option>
|
||||
<option value="to do" selected={"to do" === value}>To Do</option>
|
||||
<option value="declined" selected={"declined" === value}>Won't Do</option>
|
||||
</select>
|
||||
@@ -4,11 +4,12 @@
|
||||
import type { ModalData } from "../stores/modal";
|
||||
import ChildEntry from "./ChildEntry.svelte";
|
||||
import DateSpan from "./DateSpan.svelte";
|
||||
import Icon from "./Icon.svelte";
|
||||
import ItemLink from "./ItemLink.svelte";
|
||||
import Markdown from "./Markdown.svelte";
|
||||
import Markdown from "./Markdown.svelte";
|
||||
import Option from "./Option.svelte";
|
||||
import OptionRow from "./OptionRow.svelte";
|
||||
import StatusColor from "./StatusColor.svelte";
|
||||
import TaskIcon from "./TaskIcon.svelte";
|
||||
|
||||
export let task: TaskResult = null;
|
||||
export let project: Project = null;
|
||||
@@ -28,74 +29,38 @@ import Markdown from "./Markdown.svelte";
|
||||
$: mdTaskDelete = {name: "task.delete", task: {...task, project}};
|
||||
</script>
|
||||
|
||||
<ChildEntry entry={task}>
|
||||
<div slot="icon" class="icon" class:done={!task.active}>
|
||||
{#if !task.active}
|
||||
<span class="on"><Icon block name="check" /></span>
|
||||
<span class="off">
|
||||
{task.completedAmount} / {task.itemAmount}
|
||||
</span>
|
||||
{:else}
|
||||
{task.completedAmount} / {task.itemAmount}
|
||||
{/if}
|
||||
</div>
|
||||
<ItemLink item={task.item} />
|
||||
<OptionRow>
|
||||
{#if task.logs.length > 0}
|
||||
<Option on:click={toggleShowLogs}>{showLogs ? "Hide Logs" : "Show Logs"}</Option>
|
||||
{/if}
|
||||
<Option open={mdLogAdd}>Add Log</Option>
|
||||
{#if showAllOptions}
|
||||
<Option open={mdTaskEdit}>Edit</Option>
|
||||
<Option open={mdTaskDelete}>Delete</Option>
|
||||
{/if}
|
||||
</OptionRow>
|
||||
{#if showLogs && task.logs.length > 0}
|
||||
<div class="log-list">
|
||||
{#each task.logs as log (log.id)}
|
||||
<div class="log">
|
||||
<div class="log-time"><DateSpan time={log.loggedTime} /></div>
|
||||
<div class="log-description">
|
||||
<Markdown source={log.description} />
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
<StatusColor affects="task" entry={task}>
|
||||
<ChildEntry entry={task}>
|
||||
<div slot="icon">
|
||||
<TaskIcon task={task} />
|
||||
</div>
|
||||
{/if}
|
||||
</ChildEntry>
|
||||
<ItemLink item={task.item} />
|
||||
<OptionRow>
|
||||
{#if task.logs.length > 0}
|
||||
<Option on:click={toggleShowLogs}>{showLogs ? "Hide Logs" : "Show Logs"}</Option>
|
||||
{/if}
|
||||
<Option open={mdLogAdd}>Add Log</Option>
|
||||
{#if showAllOptions}
|
||||
<Option open={mdTaskEdit}>Edit</Option>
|
||||
<Option open={mdTaskDelete}>Delete</Option>
|
||||
{/if}
|
||||
</OptionRow>
|
||||
{#if showLogs && task.logs.length > 0}
|
||||
<div class="log-list">
|
||||
{#each task.logs as log (log.id)}
|
||||
<div class="log">
|
||||
<div class="log-time"><DateSpan time={log.loggedTime} /></div>
|
||||
<div class="log-description">
|
||||
<Markdown source={log.description} />
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</ChildEntry>
|
||||
</StatusColor>
|
||||
|
||||
<style>
|
||||
div.icon {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-size: 1em;
|
||||
padding: 0.2em .5ch;
|
||||
|
||||
margin-right: 0.5em;
|
||||
background: #444;
|
||||
color: #CCC;
|
||||
}
|
||||
div.icon.done {
|
||||
padding-top: 0.285em;
|
||||
padding-bottom: 0.115em;
|
||||
|
||||
background: #484;
|
||||
color: #78ff78;
|
||||
}
|
||||
div.icon.done span.off {
|
||||
display: none;
|
||||
}
|
||||
div.icon.done:hover {
|
||||
padding-top: 0.2em;
|
||||
padding-bottom: 0.2em;
|
||||
}
|
||||
div.icon.done:hover span.on {
|
||||
display: none;
|
||||
}
|
||||
div.icon.done:hover span.off {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
div.log-list {
|
||||
padding: 0.5em 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
<script lang="ts">
|
||||
import type { IconName } from "../external/icons";
|
||||
|
||||
import type { TaskResult } from "../models/task";
|
||||
import Icon from "./Icon.svelte";
|
||||
|
||||
export let task: TaskResult;
|
||||
export let iconName: IconName;
|
||||
|
||||
$: {
|
||||
switch (task.statusTag) {
|
||||
case "to do": iconName = "lightbulb"; break;
|
||||
case "on hold": iconName = "hourglass"; break;
|
||||
case "declined": iconName = "times"; break;
|
||||
case "failed": iconName = "times"; break;
|
||||
default: iconName = "check"; break;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="icon sccsi" class:inactive={!task.active}>
|
||||
{#if !task.active}
|
||||
<span class="on"><Icon block name={iconName} /></span>
|
||||
<span class="off">
|
||||
{task.completedAmount} / {task.itemAmount}
|
||||
</span>
|
||||
{:else}
|
||||
{task.completedAmount} / {task.itemAmount}
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
div.icon {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-size: 1em;
|
||||
padding: 0.2em .5ch;
|
||||
|
||||
margin-right: 0.5em;
|
||||
background: #444;
|
||||
color: #CCC;
|
||||
}
|
||||
div.icon.inactive {
|
||||
padding-top: 0.295em;
|
||||
padding-bottom: 0.115em;
|
||||
|
||||
background: #484;
|
||||
color: #78ff78;
|
||||
}
|
||||
div.icon.inactive span.off {
|
||||
display: none;
|
||||
}
|
||||
div.icon.inactive:hover {
|
||||
padding-top: 0.16em;
|
||||
padding-bottom: 0.27em;
|
||||
}
|
||||
div.icon.inactive:hover span.on {
|
||||
display: none;
|
||||
}
|
||||
div.icon.inactive:hover span.off {
|
||||
display: inline;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,30 @@
|
||||
<script lang="ts">
|
||||
import type Project from "../models/project";
|
||||
import type { TaskResult } from "../models/task";
|
||||
import TaskEntry from "./TaskEntry.svelte";
|
||||
|
||||
export let project: Project;
|
||||
export let tasks: TaskResult[];
|
||||
export let showAllOptions: boolean;
|
||||
export let header: string;
|
||||
</script>
|
||||
|
||||
{#if tasks.length > 0}
|
||||
<h3>{header}</h3>
|
||||
{#each tasks as task (task.id)}
|
||||
<TaskEntry showAllOptions={showAllOptions} task={task} project={project} />
|
||||
{/each}
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
h3:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
h3 {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
margin-top: 0.5em;
|
||||
font-weight: 100;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user