add quest log aesthetic.
continuous-integration/drone/push Build is passing

This commit is contained in:
2021-01-17 16:12:32 +01:00
parent 1d3c8dee73
commit d3a6487dc8
17 changed files with 319 additions and 26 deletions
+24 -6
View File
@@ -1,5 +1,6 @@
<script lang="ts">
import { link } from "svelte-routing";
import selectionStore from "../stores/selection";
export let location: string = window.location.pathname.split("?")[0];
@@ -9,19 +10,23 @@
}, 0);
}
$: console.log($selectionStore);
$: selected = {
home: location == "/",
goals: location.startsWith("/goals"),
projects: location.startsWith("/projects"),
items: location.startsWith("/items"),
logs: location.startsWith("/logs"),
home: $selectionStore.path === "/",
goals: $selectionStore.path.startsWith("/goals"),
questlog: $selectionStore.path.startsWith("/questlog"),
projects: $selectionStore.path.startsWith("/projects"),
items: $selectionStore.path.startsWith("/items"),
logs: $selectionStore.path.startsWith("/logs"),
}
</script>
<nav>
<a on:click={updateLocation} class:selected={selected.home} use:link href="/">Stufflog</a>
<a on:click={updateLocation} class:selected={selected.goals} use:link href="/goals">Goals</a>
<a on:click={updateLocation} class:selected={selected.projects} use:link href="/projects">Projects</a>
<a class="desktop" on:click={updateLocation} class:selected={selected.questlog} use:link href="/questlog">Projects</a>
<a class="mobile" on:click={updateLocation} class:selected={selected.projects} use:link href="/projects">Projects</a>
<a on:click={updateLocation} class:selected={selected.items} use:link href="/items">Items</a>
<a on:click={updateLocation} class:selected={selected.logs} use:link href="/logs">Logs</a>
</nav>
@@ -41,4 +46,17 @@
a.selected {
color: #AAA;
}
a.mobile {
display: none;
}
@media screen and (max-width: 600px) {
a.mobile {
display: inline-block;
}
a.desktop {
display: none;
}
}
</style>
+16 -7
View File
@@ -1,10 +1,11 @@
<script lang="ts">
import type { IconName } from "../external/icons";
import type { TaskResult } from "../models/task";
import DaysLeft from "./DaysLeft.svelte";
import Icon from "./Icon.svelte";
import LinkHook from "./LinkHook.svelte";
import Markdown from "./Markdown.svelte";
import Progress from "./Progress.svelte";
import ProjectProgress from "./ProjectProgress.svelte";
interface EntryIconHolder {
icon: IconName
@@ -20,14 +21,15 @@
createdTime?: string
group?: EntryIconHolder
project?: EntryIconHolder
tasks?: TaskResult[]
active?: boolean
}
export let entry: EntryCommon;
export let full = false;
export let headerLink = "";
export let progressAmount: number = null;
export let progressTarget: number = null;
export let hideProgress: boolean = false;
export let hideIcon: boolean = false;
let iconName: IconName;
@@ -44,7 +46,11 @@
<div class="parent-entry" class:full={full}>
<LinkHook id={entry.id} />
<div class="icon"><Icon block name={iconName} /></div>
{#if !hideIcon}
<div class="icon" class:completed={entry.active === false}>
<Icon block name={iconName} />
</div>
{/if}
<div class="body">
<div class="header">
<div class="name">
@@ -60,8 +66,8 @@
</div>
{/if}
</div>
{#if (progressAmount != null)}
<Progress thin green count={progressAmount} target={progressTarget} />
{#if (!hideProgress && entry.tasks != null)}
<ProjectProgress project={entry} />
{/if}
{#if (full)}
<Markdown source={entry.description} />
@@ -86,6 +92,9 @@
padding-top: 0.125em;
color: #333;
}
div.icon.completed {
color: #484;
}
div.body {
display: flex;
flex-direction: column;
+7 -9
View File
@@ -1,6 +1,9 @@
<script lang="ts">
import type { ProjectResult } from "../models/project";
import type { TaskResult } from "../models/task";
import type { ModalData } from "../stores/modal";
import projectStore from "../stores/project";
import taskStore from "../stores/tasks";
import Option from "./Option.svelte";
import OptionRow from "./OptionRow.svelte";
import ParentEntry from "./ParentEntry.svelte";
@@ -9,30 +12,25 @@
export let project: ProjectResult = null;
export let showAllOptions: boolean = false;
export let hideInactive: boolean = false;
export let hideProgress: boolean = false;
export let linkProject: boolean = false;
export let hideIcon: boolean = false;
let mdAddTask: ModalData;
let mdProjectEdit: ModalData;
let mdProjectDelete: ModalData;
let progressAmount: number;
let progressTarget: number;
$: mdAddTask = {name:"task.add", project};
$: mdProjectEdit = {name:"project.edit", project};
$: mdProjectDelete = {name:"project.delete", project};
$: progressAmount = project.tasks.map(t => t.active
? Math.min(t.completedAmount, t.itemAmount) * t.item.groupWeight
: 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>
<ParentEntry
full={showAllOptions}
entry={project}
headerLink={linkProject ? "/projects#"+project.id : ""}
progressAmount={progressAmount}
progressTarget={progressTarget}
hideProgress={hideProgress}
hideIcon={hideIcon}
>
{#if showAllOptions}
<OptionRow>
@@ -0,0 +1,21 @@
<script lang="ts">
import type { TaskResult } from "../models/task";
import Progress from "./Progress.svelte";
interface ProjectLike {
tasks?: TaskResult[]
}
export let project: ProjectLike;
let progressAmount: number;
let progressTarget: number;
$: progressAmount = (project.tasks||[]).map(t => t.active
? Math.min(t.completedAmount, t.itemAmount) * t.item.groupWeight
: 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>
<Progress thin green count={progressAmount} target={progressTarget} />
+28
View File
@@ -0,0 +1,28 @@
<script lang="ts">
import type { ProjectResult } from "../models/project";
import QlListItem from "./QLListItem.svelte";
export let projects: ProjectResult[];
export let label: string = "";
</script>
{#if projects.length > 0}
<div class="ql-list">
<h2>{label}</h2>
{#each projects as project (project.id)}
<QlListItem project={project} />
{/each}
</div>
{/if}
<style>
div.ql-list {
margin: 1em 0;
}
h2 {
font-weight: 100;
margin: 0;
padding-bottom: 0.125em;
}
</style>
@@ -0,0 +1,77 @@
<script lang="ts">
import type { ProjectResult } from "../models/project";
import selectionStore from "../stores/selection";
import Icon from "./Icon.svelte";
import ProjectProgress from "./ProjectProgress.svelte";
export let project: ProjectResult;
let selected: boolean;
let completed: boolean;
function handleClick() {
window.location.hash = "#" + project.id;
selectionStore.change("hash", project.id);
}
$: selected = $selectionStore.hash === project.id;
$: completed = !project.active;
</script>
<div class="ql-list-item" on:click={handleClick} class:selected>
<div class="icon" class:completed>
<Icon block name={project.icon} />
</div>
<div class="header">
<div class="name">{project.name}</div>
<ProjectProgress project={project} />
</div>
</div>
<style>
div.ql-list-item {
display: flex;
flex-direction: row;
-webkit-user-select: none;
-moz-user-select: none;
color: #777;
padding: 0.2em;
padding-bottom: 0.05em;
cursor: pointer;
}
div.ql-list-item:hover {
color: #ccc;
background-color: #191919;
}
div.ql-list-item.selected {
background-color: #222;
}
div.icon {
color: #444;
padding: 0.3em 0.5ch;
padding-right: 1ch;
}
div.ql-list-item.selected div.icon {
color: #666;
}
div.icon.completed {
color: #484;
}
div.ql-list-item.selected div.icon.completed {
color: #78ff78;
}
div.ql-list-item:hover div.icon {
color: #ccc;
}
div.header {
flex-grow: 1;
flex-shrink: 0;
padding-right: 0.5ch;
}
</style>
+57
View File
@@ -0,0 +1,57 @@
<script lang="ts">
import type { ProjectResult } from "../models/project";
import selectionStore from "../stores/selection";
import ProjectEntry from "./ProjectEntry.svelte";
import QlList from "./QLList.svelte";
export let projects: ProjectResult[];
let expiringProjects: ProjectResult[];
let activeProjects: ProjectResult[];
let completedProjects: ProjectResult[];
let project: ProjectResult = null;
$: project = $selectionStore.hash.startsWith("P") ? projects.find(p => p.id === $selectionStore.hash) : null;
$: expiringProjects = projects.filter(p => p.active && p.endTime).sort((a,b) => Date.parse(a.endTime) - Date.parse(b.endTime));
$: activeProjects = projects.filter(p => p.active && !p.endTime).sort((a,b) => a.name.localeCompare(b.name));
$: completedProjects = projects.filter(p => !p.active).sort((a,b) => a.name.localeCompare(b.name));
$: {
if (project === null && projects.length > 0) {
project = expiringProjects[0] || activeProjects[0] || completedProjects[0] || null;
if (project !== null) {
selectionStore.change("hash", project.id);
}
}
}
</script>
<div class="quest-log">
<div class="list">
<QlList label="Deadlines" projects={expiringProjects} />
<QlList label="Acitve" projects={activeProjects} />
<QlList label="Completed" projects={completedProjects} />
</div>
<div class="body">
{#if project != null}
<ProjectEntry hideIcon project={project} showAllOptions />
{/if}
</div>
</div>
<style>
div.quest-log {
display: flex;
flex-direction: row;
}
div.list {
flex-shrink: 0;
width: 32ch;
}
div.body {
flex-grow: 1;
margin: 1em 1ch;
}
</style>
@@ -0,0 +1,8 @@
<script lang="ts">
import { onMount } from "svelte";
import selectionStore from "../stores/selection";
onMount(() => {
selectionStore.refresh();
})
</script>