You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
162 lines
5.2 KiB
162 lines
5.2 KiB
<script lang="ts">
|
|
import stuffLogClient from "../clients/stufflog";
|
|
|
|
import type { ProjectResult, ProjectUpdate } from "../models/project";
|
|
import type { TaskResult } from "../models/task";
|
|
import markStale from "../stores/markStale";
|
|
import type { ModalData } from "../stores/modal";
|
|
import IS_MOBILE from "../utils/phone-check";
|
|
import Icon from "./Icon.svelte";
|
|
import Option from "./Option.svelte";
|
|
import OptionRow from "./OptionRow.svelte";
|
|
import ParentEntry from "./ParentEntry.svelte";
|
|
import ProgressNumbers from "./ProgressNumbers.svelte";
|
|
import StatusColor from "./StatusColor.svelte";
|
|
import TagList from "./TagList.svelte";
|
|
import TaskList from "./TaskList.svelte";
|
|
|
|
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;
|
|
export let isFake: boolean = false;
|
|
export let removeHook: boolean = false;
|
|
|
|
let mdAddTask: ModalData;
|
|
let mdProjectEdit: ModalData;
|
|
let mdProjectDelete: ModalData;
|
|
let mdLinkTask: ModalData;
|
|
let linkTarget: string = "";
|
|
let activeTasks: TaskResult[] = [];
|
|
let inactiveTasks: TaskResult[] = [];
|
|
let todoTasks: TaskResult[] = [];
|
|
let completedTasks: TaskResult[] = [];
|
|
let onholdTasks: TaskResult[] = [];
|
|
let failedTasks: TaskResult[] = [];
|
|
let nonHiddenTasks: TaskResult[] = [];
|
|
let toggling = false;
|
|
let canComplete = false;
|
|
|
|
function updateProject(update: ProjectUpdate) {
|
|
if (toggling) {
|
|
return
|
|
}
|
|
toggling = true
|
|
|
|
stuffLogClient.updateProject(project.id, {...update}).then(() => {
|
|
markStale("project");
|
|
}).catch(err => {
|
|
console.warn("Failed to toggle favorite:", err);
|
|
}).finally(() => {
|
|
toggling = false;
|
|
})
|
|
}
|
|
|
|
function toggleFavorite() {
|
|
updateProject({
|
|
favorite: !project.favorite,
|
|
});
|
|
}
|
|
|
|
function markCompleted() {
|
|
updateProject({
|
|
statusTag: "completed",
|
|
active: false,
|
|
})
|
|
}
|
|
|
|
function markFailed() {
|
|
updateProject({
|
|
statusTag: "failed",
|
|
active: false,
|
|
})
|
|
}
|
|
|
|
$: mdAddTask = {name:"task.add", project};
|
|
$: mdLinkTask = {name:"tasklink.add", project};
|
|
$: mdProjectEdit = {name:"project.edit", project};
|
|
$: mdProjectDelete = {name:"project.delete", project};
|
|
|
|
$: {
|
|
activeTasks = project.tasks.filter(t => t.active);
|
|
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");
|
|
|
|
nonHiddenTasks = [...activeTasks, ...todoTasks, ...onholdTasks];
|
|
}
|
|
|
|
$: canComplete = project.active && completedTasks.length + failedTasks.length === project.tasks.length;
|
|
|
|
$: linkTarget = IS_MOBILE ? `/projects#${project.id}` : `/questlog#${project.id}`
|
|
</script>
|
|
|
|
<StatusColor affects="project" entry={project}>
|
|
<ParentEntry
|
|
full={showAllOptions}
|
|
entry={project}
|
|
headerLink={linkProject ? linkTarget : ""}
|
|
hideProgress={hideProgress}
|
|
hideIcon={hideIcon}
|
|
showTimeProgress={!hideProgress}
|
|
removeHook={removeHook}
|
|
>
|
|
<div slot="pre-annotation" class="favorite" class:enabled={project.favorite} class:toggling on:click={toggleFavorite}>
|
|
{#if !isFake}
|
|
<Icon block name="star" />
|
|
{/if}
|
|
</div>
|
|
<div slot="post-seprator">
|
|
<ProgressNumbers project={project} />
|
|
</div>
|
|
<div slot="above-description">
|
|
{#if showAllOptions}
|
|
<TagList tags={project.tags} />
|
|
{/if}
|
|
</div>
|
|
{#if showAllOptions}
|
|
<OptionRow>
|
|
<Option open={mdAddTask}>Add Task</Option>
|
|
<Option open={mdLinkTask}>Link Task</Option>
|
|
<Option open={mdProjectEdit}>Edit</Option>
|
|
<Option open={mdProjectDelete}>Delete</Option>
|
|
{#if canComplete}
|
|
<Option disabled={!toggling} color="green" on:click={markCompleted}>Complete Project</Option>
|
|
<Option disabled={!toggling} color="red" on:click={markFailed}>Fail Project</Option>
|
|
{/if}
|
|
</OptionRow>
|
|
{/if}
|
|
{#if hideInactive}
|
|
<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="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>
|
|
</StatusColor>
|
|
|
|
<style>
|
|
div.favorite {
|
|
margin: auto 0;
|
|
padding: 0 0.5ch;
|
|
line-height: 0em;
|
|
color: #333;
|
|
cursor: pointer;
|
|
}
|
|
|
|
div.favorite.enabled {
|
|
color: #e7e55e
|
|
}
|
|
|
|
div.favorite.toggling {
|
|
opacity: 0.5;
|
|
}
|
|
</style>
|