172 lines
3.6 KiB
Svelte
172 lines
3.6 KiB
Svelte
<script lang="ts">
|
|
import type { Task } from "$lib/server/services/tasks";
|
|
|
|
type DisplayableTask = Task & {
|
|
taskId: NonNullable<Task["taskId"]>;
|
|
type: Task["type"] & {
|
|
prefix: NonNullable<Task["type"]["prefix"]>;
|
|
};
|
|
};
|
|
|
|
let { task, parent, children }: {
|
|
task: DisplayableTask;
|
|
parent: {
|
|
prefix: Task["type"]["prefix"];
|
|
taskId: Task["taskId"];
|
|
description: Task["description"];
|
|
};
|
|
children: Array<{
|
|
prefix: Task["type"]["prefix"];
|
|
taskId: Task["taskId"];
|
|
description: Task["description"];
|
|
status: Task["status"];
|
|
}>;
|
|
} = $props();
|
|
</script>
|
|
|
|
{@render description(task.type.prefix, task.taskId, task.description)}
|
|
{@render details(
|
|
task.status,
|
|
task.priority,
|
|
task.openDate,
|
|
task.closeDate,
|
|
parent,
|
|
children,
|
|
)}
|
|
{@render checklist(task.checklist)}
|
|
{@render body(task.body, task.bodyHistory)}
|
|
{@render integrations(task.integrations)}
|
|
|
|
<style>
|
|
.container {
|
|
display: flex;
|
|
gap: 1rem;
|
|
}
|
|
|
|
.id-bg {
|
|
background: beige;
|
|
color: cadetblue;
|
|
border-radius: 1rem;
|
|
border: 2px solid cadetblue;
|
|
padding: 0.5rem;
|
|
}
|
|
|
|
.desc-separator {}
|
|
|
|
.desc {}
|
|
</style>
|
|
|
|
{#snippet description(
|
|
prefix: NonNullable<Task["type"]["prefix"]>,
|
|
taskId: NonNullable<Task["taskId"]>,
|
|
description: Task["description"],
|
|
)}
|
|
<h1>
|
|
<span class="id-bg">{prefix + taskId}</span>
|
|
<span class="desc-separator">•</span>
|
|
<span class="desc">{description}</span>
|
|
</h1>
|
|
{/snippet}
|
|
|
|
{#snippet details(
|
|
status: Task["status"],
|
|
priority: Task["priority"],
|
|
opened: Task["openDate"],
|
|
closed: Task["closeDate"],
|
|
parent: {
|
|
prefix: Task["type"]["prefix"];
|
|
taskId: Task["taskId"];
|
|
description: Task["description"];
|
|
},
|
|
children: Array<
|
|
{
|
|
prefix: Task["type"]["prefix"];
|
|
taskId: Task["taskId"];
|
|
description: Task["description"];
|
|
status: Task["status"];
|
|
}
|
|
>,
|
|
)}
|
|
<div class="details">
|
|
<div class="labeled-field">
|
|
<span class="label">Status:</span>
|
|
<span>{status ?? "--"}</span>
|
|
</div>
|
|
<div class="labeled-field">
|
|
<span class="label">Priority:</span>
|
|
<span>{priority ?? "--"}</span>
|
|
</div>
|
|
|
|
<div class="labeled-field">
|
|
<span class="label">Opened:</span>
|
|
<span>{opened ?? "--"}</span>
|
|
</div>
|
|
<div class="labeled-field">
|
|
<span class="label">Closed:</span>
|
|
<span>{closed ?? "--"}</span>
|
|
</div>
|
|
<div>
|
|
<span class="label">Parent:</span>
|
|
<span>{
|
|
!Object.values(parent).some(value => value === null)
|
|
? `${parent.prefix}${parent.taskId} | ${parent.description}`
|
|
: "--"
|
|
}</span>
|
|
</div>
|
|
<div>
|
|
<h3>Children</h3>
|
|
<table>
|
|
<tbody>
|
|
{#each children as child (child.taskId)}
|
|
<tr>
|
|
<td>{child.prefix + child.taskId}</td>
|
|
<td>{child.description}</td>
|
|
<td>{child.status}</td>
|
|
</tr>
|
|
{/each}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
{/snippet}
|
|
|
|
{#snippet body(body: Task["body"], history: Task["bodyHistory"])}
|
|
<div>
|
|
<h2>Body</h2>
|
|
<p>{body}</p>
|
|
{#if history}
|
|
<h3>History</h3>
|
|
<p>{history}</p>
|
|
{/if}
|
|
</div>
|
|
<div>
|
|
<h2>Updates</h2>
|
|
<p>
|
|
{
|
|
task.updateChain
|
|
? JSON.stringify(task.updateChain)
|
|
: "--"
|
|
}
|
|
</p>
|
|
</div>
|
|
{/snippet}
|
|
|
|
{#snippet checklist(checklist: Task["checklist"])}
|
|
<div>
|
|
<h2>Checklist</h2>
|
|
<p>
|
|
{checklist ? JSON.stringify(checklist) : "--"}
|
|
</p>
|
|
</div>
|
|
{/snippet}
|
|
|
|
{#snippet integrations(integrations: Task["integrations"])}
|
|
<div>
|
|
<h2>Integrations</h2>
|
|
<p>
|
|
{integrations ? JSON.stringify(integrations) : "--"}
|
|
</p>
|
|
</div>
|
|
{/snippet}
|
|
|