add project progress indicator and sort front page projects by deadline.
continuous-integration/drone/push Build is passing
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -11,6 +11,8 @@
|
||||
<script lang="ts">
|
||||
export let target = 1;
|
||||
export let count = 0;
|
||||
export let green = false;
|
||||
export let thin = false;
|
||||
|
||||
let offClass = COLORS[0];
|
||||
let onClass = COLORS[1];
|
||||
@@ -19,7 +21,7 @@
|
||||
|
||||
$: {
|
||||
let level = Math.floor(count / target);
|
||||
if (level >= COLORS.length - 1) {
|
||||
if (level >= COLORS.length - 1 || (level > 1 && green)) {
|
||||
offs = 0;
|
||||
ons = target;
|
||||
offClass = "gold";
|
||||
@@ -34,10 +36,15 @@
|
||||
offClass = COLORS[level];
|
||||
onClass = COLORS[level + 1];
|
||||
}
|
||||
|
||||
if (green) {
|
||||
onClass = "green"
|
||||
offClass = "none"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="bar">
|
||||
<div class="bar" class:thin>
|
||||
{#each {length: ons} as _}
|
||||
<div class={"on " + onClass}></div>
|
||||
{/each}
|
||||
@@ -61,7 +68,7 @@
|
||||
flex-basis: 0;
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
border: 0.1px solid #000;
|
||||
border: 1px solid #000;
|
||||
}
|
||||
|
||||
div.none { background-color: #555555; }
|
||||
@@ -69,6 +76,7 @@
|
||||
div.silver { background-color: #d8dce4; }
|
||||
div.gold { background-color: #ffd966; }
|
||||
div.diamond { background-color: #84f5ff; }
|
||||
div.green { background-color: #78ff78; }
|
||||
|
||||
div.on {
|
||||
opacity: 0.75;
|
||||
@@ -77,4 +85,8 @@
|
||||
div.off {
|
||||
opacity: 0.33;
|
||||
}
|
||||
|
||||
div.bar.thin {
|
||||
height: 0.25em;
|
||||
}
|
||||
</style>
|
||||
@@ -1,31 +1,32 @@
|
||||
<script lang="ts">
|
||||
import type { IconName } from "../external/icons";
|
||||
import TaskAddForm from "../forms/TaskAddForm.svelte";
|
||||
import type { ProjectResult } from "../models/project";
|
||||
import type { ModalData } from "../stores/modal";
|
||||
import DaysLeft from "./DaysLeft.svelte";
|
||||
import Icon from "./Icon.svelte";
|
||||
import Option from "./Option.svelte";
|
||||
import OptionRow from "./OptionRow.svelte";
|
||||
import Progress from "./Progress.svelte";
|
||||
import TaskEntry from "./TaskEntry.svelte";
|
||||
|
||||
export let project: ProjectResult = null;
|
||||
export let showAllOptions: boolean = false;
|
||||
export let hideInactive: boolean = false;
|
||||
|
||||
let iconName: IconName = "question";
|
||||
let mdAddTask: ModalData;
|
||||
let mdProjectEdit: ModalData;
|
||||
let mdProjectDelete: ModalData;
|
||||
let progressAmount: number;
|
||||
let progressTarget: number;
|
||||
|
||||
$: iconName = project.icon as IconName;
|
||||
$: mdAddTask = {name:"task.add", project};
|
||||
$: mdProjectEdit = {name:"project.edit", project};
|
||||
$: mdProjectDelete = {name:"project.delete", project};
|
||||
$: progressAmount = project.tasks.map(t => Math.min(t.completedAmount, t.itemAmount) * t.item.groupWeight).reduce((n,m) => n+m, 0);
|
||||
$: progressTarget = Math.max(project.tasks.map(t => t.itemAmount * t.item.groupWeight).reduce((n,m) => n+m, 0), 1);
|
||||
</script>
|
||||
|
||||
<div class="project">
|
||||
<div class="icon" class:inactive={!project.active}><Icon block name={iconName} /></div>
|
||||
<div class="icon" class:inactive={!project.active}><Icon block name={project.icon} /></div>
|
||||
<div class="body">
|
||||
<div class="header">
|
||||
<div class="name">{project.name}</div>
|
||||
@@ -35,6 +36,7 @@ import TaskAddForm from "../forms/TaskAddForm.svelte";
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<Progress thin green count={progressAmount} target={progressTarget} />
|
||||
{#if showAllOptions}
|
||||
<div class="description">
|
||||
<p>{project.description}</p>
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
export let task: TaskResult = null;
|
||||
export let showAllOptions: boolean = false;
|
||||
|
||||
let itomIconName: IconName = "question";
|
||||
let showLogs = false;
|
||||
let mdLogAdd: ModalData;
|
||||
let mdTaskEdit: ModalData;
|
||||
@@ -21,7 +20,6 @@
|
||||
showLogs = !showLogs;
|
||||
}
|
||||
|
||||
$: itomIconName = task.item.icon as IconName;
|
||||
$: mdLogAdd = {name: "log.add", task};
|
||||
$: mdTaskEdit = {name: "task.edit", task};
|
||||
$: mdTaskDelete = {name: "task.delete", task};
|
||||
@@ -53,7 +51,7 @@
|
||||
<p>{task.description}</p>
|
||||
<div class="item">
|
||||
<div class="item-icon">
|
||||
<Icon name={itomIconName} />
|
||||
<Icon name={task.item.icon} />
|
||||
</div>
|
||||
<div class="item-name">{task.item.name} ({task.item.groupWeight})</div>
|
||||
</div>
|
||||
|
||||
@@ -4,10 +4,11 @@
|
||||
import ProjectEntry from "../components/ProjectEntry.svelte";
|
||||
import type { ProjectResult } from "../models/project";
|
||||
import { fpGoalStore } from "../stores/goal";
|
||||
import { fpProjectStore } from "../stores/project";
|
||||
import { fpTaskStore } from "../stores/tasks";
|
||||
import projectStore, { fpProjectStore } from "../stores/project";
|
||||
import taskStore, { fpTaskStore } from "../stores/tasks";
|
||||
|
||||
let fakeProject: ProjectResult
|
||||
let sortedProjects: ProjectResult[]
|
||||
|
||||
$: {
|
||||
if ($fpGoalStore.stale && !$fpGoalStore.loading) {
|
||||
@@ -44,12 +45,22 @@
|
||||
description: "",
|
||||
icon: "list",
|
||||
name: "Individual Tasks",
|
||||
tasks: $fpTaskStore.tasks.filter(t => $fpProjectStore.projects.find(p => p.id === t.id) == null),
|
||||
tasks: $fpTaskStore.tasks.filter(t => $fpProjectStore.projects.find(p => p.id === t.id) == null)
|
||||
.sort((a,b) => Date.parse(a.endTime) - Date.parse(b.endTime)),
|
||||
endTime: null,
|
||||
}
|
||||
|
||||
if (fakeProject.tasks.length > 0) {
|
||||
fakeProject.endTime = fakeProject.tasks[0].endTime;
|
||||
}
|
||||
|
||||
console.log(fakeProject, $fpTaskStore);
|
||||
}
|
||||
|
||||
$: {
|
||||
const projects = fakeProject.tasks.length > 0 ? [...$fpProjectStore.projects, fakeProject] : [...$fpProjectStore.projects];
|
||||
sortedProjects = projects.sort((a,b) => Date.parse(a.endTime) - Date.parse(b.endTime));
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="page">
|
||||
@@ -68,12 +79,9 @@
|
||||
{#if !$fpProjectStore.loading || $fpProjectStore.projects.length > 0}
|
||||
<h1>Upcoming Deadlines</h1>
|
||||
{/if}
|
||||
{#each $fpProjectStore.projects as project (project.id)}
|
||||
{#each sortedProjects as project (project.id)}
|
||||
<ProjectEntry hideInactive project={project} />
|
||||
{/each}
|
||||
{#if fakeProject.tasks.length > 0}
|
||||
<ProjectEntry project={fakeProject} />
|
||||
{/if}
|
||||
{#if fakeProject.tasks.length === 0 && !$fpProjectStore.loading && $fpProjectStore.projects.length === 0}
|
||||
<EmptyList icon="check" text="All good!" />
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user