Files
stufflog2/svelte-ui/src/components/TableOfContent.svelte
T

147 lines
3.2 KiB
Svelte
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script lang="ts" context="module">
import type { IconName } from "../external/icons";
interface ToCGroup {
icon: IconName
href: string
name: string
completed: boolean
items: ToCItem[]
}
interface ToCItem {
href: string
name: string
completed: boolean
}
</script>
<script lang="ts">
import type { GroupResult } from "../models/group";
import type { ProjectResult } from "../models/project";
import Icon from "./Icon.svelte";
export let projects: ProjectResult[] = [];
export let groups: GroupResult[] = [];
export let hideInactive: boolean = false;
let tocGroups: ToCGroup[];
let show = false;
function toggleShow() {
show = !show;
}
$: {
tocGroups = [];
for (const project of projects) {
tocGroups.push({
icon: project.icon,
name: project.name,
href: `/projects#${project.id}`,
completed: !project.active,
items: project.tasks.filter(t => !hideInactive || t.active).map(task => ({
name: task.name,
completed: !task.active,
href: `/projects#${task.id}`,
})),
})
}
for (const group of groups) {
tocGroups.push({
icon: group.icon,
name: group.name,
href: `/items#${group.id}`,
completed: false,
items: group.items.map(item => ({
name: item.name,
completed: false,
href: `/items#${item.id}`,
})),
})
}
}
</script>
<div class="toc" class:show={show}>
<div class="show-button" on:click={toggleShow}>
<div class="icon"><Icon name={show ? "chevron_down" : "chevron_right"} /></div>
<div class="text">{show ? "Hide" : "Show"} Table of Contents</div>
</div>
{#if show}
{#each tocGroups as tocGroup (tocGroup.href)}
<div class="toc-group" class:completed={tocGroup.completed}>
<a href={tocGroup.href}>
<div class="icon">
<Icon name={tocGroup.icon} />
</div>
<div class="text">{tocGroup.name}</div>
</a>
</div>
{#each tocGroup.items as tocItem (tocItem.href)}
<div class="toc-item" class:completed={tocItem.completed}>
<a href={tocItem.href}>
<div class="text">{tocItem.name}</div>
</a>
</div>
{/each}
{/each}
{/if}
</div>
<style>
div.toc {
padding: 1em;
color: #777;
margin: 0 auto;
}
div.toc.show {
padding-bottom: 2em;
}
div.toc-item {
margin-left: 1.5ch;
padding-left: 1ch;
border-left: 2px solid #222;
}
div.toc-item + div.toc-group, div.toc-group + div.toc-group {
padding-top: 1em;
}
a {
color: inherit;
display: flex;
flex-direction: row;
padding: 0.125em 0.5ch;
}
a > div.icon {
padding: 0.125em 0.5ch;
}
a > div.text {
vertical-align: middle;
}
div.show-button {
display: flex;
flex-direction: row;
-webkit-user-select: none;
-moz-user-select: none;
padding-bottom: 1em;
}
div.show-button div.icon {
margin-left: auto;
padding: 0 1ch;
padding-top: 0.25em;
}
div.show-button div.text {
margin-right: auto;
margin-top: auto;
margin-bottom: auto;
}
div.completed {
color: #484;
}
</style>