Gisle Aune
4 years ago
21 changed files with 347 additions and 166 deletions
-
9database/postgres/tasks.go
-
9migrations/postgres/20210124104325_rename_project_status_tag_todo.sql
-
9migrations/postgres/20210124104330_rename_project_status_tag_onhold.sql
-
11migrations/postgres/20210124105003_add_task_column_status_tag.sql
-
9migrations/postgres/20210124110913_update_task_default_inactive_tag.sql
-
9models/task.go
-
2svelte-ui/src/components/Progress.svelte
-
49svelte-ui/src/components/ProjectEntry.svelte
-
28svelte-ui/src/components/ProjectIcon.svelte
-
2svelte-ui/src/components/QLListItem.svelte
-
10svelte-ui/src/components/QuestLog.svelte
-
64svelte-ui/src/components/StatusColor.svelte
-
13svelte-ui/src/components/StatusTagSelect.svelte
-
53svelte-ui/src/components/TaskEntry.svelte
-
63svelte-ui/src/components/TaskIcon.svelte
-
30svelte-ui/src/components/TaskList.svelte
-
44svelte-ui/src/external/icons.ts
-
10svelte-ui/src/forms/ProjectForm.svelte
-
16svelte-ui/src/forms/TaskForm.svelte
-
7svelte-ui/src/models/goal.ts
-
4svelte-ui/src/models/task.ts
@ -0,0 +1,9 @@ |
|||||
|
-- +goose Up |
||||
|
-- +goose StatementBegin |
||||
|
UPDATE project SET status_tag='to do' WHERE status_tag='idea'; |
||||
|
-- +goose StatementEnd |
||||
|
|
||||
|
-- +goose Down |
||||
|
-- +goose StatementBegin |
||||
|
SELECT 'Nothing to do'; |
||||
|
-- +goose StatementEnd |
@ -0,0 +1,9 @@ |
|||||
|
-- +goose Up |
||||
|
-- +goose StatementBegin |
||||
|
UPDATE project SET status_tag='on hold' WHERE status_tag='postponed'; |
||||
|
-- +goose StatementEnd |
||||
|
|
||||
|
-- +goose Down |
||||
|
-- +goose StatementBegin |
||||
|
SELECT 'Nothing to do'; |
||||
|
-- +goose StatementEnd |
@ -0,0 +1,11 @@ |
|||||
|
-- +goose Up |
||||
|
-- +goose StatementBegin |
||||
|
ALTER TABLE task |
||||
|
ADD COLUMN status_tag TEXT DEFAULT NULL; |
||||
|
-- +goose StatementEnd |
||||
|
|
||||
|
-- +goose Down |
||||
|
-- +goose StatementBegin |
||||
|
ALTER TABLE task |
||||
|
DROP COLUMN status_tag; |
||||
|
-- +goose StatementEnd |
@ -0,0 +1,9 @@ |
|||||
|
-- +goose Up |
||||
|
-- +goose StatementBegin |
||||
|
UPDATE task SET status_tag='completed' WHERE active=false; |
||||
|
-- +goose StatementEnd |
||||
|
|
||||
|
-- +goose Down |
||||
|
-- +goose StatementBegin |
||||
|
SELECT 'Nothing to do'; |
||||
|
-- +goose StatementEnd |
@ -1,42 +1,58 @@ |
|||||
<script lang="ts"> |
<script lang="ts"> |
||||
interface ProjectLike { |
|
||||
|
interface EntryCommon { |
||||
active: boolean |
active: boolean |
||||
statusTag?: string |
statusTag?: string |
||||
} |
} |
||||
|
|
||||
export let selected = false; |
export let selected = false; |
||||
export let project: ProjectLike; |
|
||||
|
export let entry: EntryCommon; |
||||
|
export let affects: "project" | "task" = "project"; |
||||
|
|
||||
let completed: boolean; |
let completed: boolean; |
||||
let failed: boolean; |
let failed: boolean; |
||||
let postponed: boolean; |
|
||||
let idea: boolean; |
|
||||
|
let onhold: boolean; |
||||
|
let todo: boolean; |
||||
|
let wontdo: boolean; |
||||
|
let project: boolean; |
||||
|
let task: boolean; |
||||
|
|
||||
$: completed = !project.active && project.statusTag === "completed"; |
|
||||
$: failed = !project.active && project.statusTag === "failed"; |
|
||||
$: postponed = !project.active && project.statusTag === "postponed"; |
|
||||
$: idea = !project.active && project.statusTag === "idea"; |
|
||||
|
$: completed = !entry.active && entry.statusTag === "completed"; |
||||
|
$: failed = !entry.active && entry.statusTag === "failed"; |
||||
|
$: onhold = !entry.active && entry.statusTag === "on hold"; |
||||
|
$: todo = !entry.active && entry.statusTag === "to do"; |
||||
|
$: wontdo = !entry.active && entry.statusTag === "declined"; |
||||
|
$: task = affects === "task"; |
||||
|
$: project = affects === "project"; |
||||
|
|
||||
</script> |
</script> |
||||
|
|
||||
<div class="status-color-context" class:selected class:completed class:failed class:postponed class:idea> |
|
||||
|
<div class="status-color-context" class:project class:task class:selected class:completed class:failed class:onhold class:todo class:wontdo> |
||||
<slot></slot> |
<slot></slot> |
||||
</div> |
</div> |
||||
|
|
||||
<style> |
<style> |
||||
.status-color-context :global(.sccfg) { color: #444 !important; } |
|
||||
.status-color-context.selected :global(.sccfg) { color: #666 !important; } |
|
||||
.status-color-context :global(.sccpb) { background-color: #78ff78 !important; } |
|
||||
.status-color-context.completed :global(.sccfg) { color: #484 !important; } |
|
||||
.status-color-context.completed.selected :global(.sccfg) { color: #78ff78 !important; } |
|
||||
.status-color-context.completed :global(.sccpb) { background-color: #78ff78 !important; } |
|
||||
.status-color-context.failed :global(.sccfg) { color: #852a24 !important; } |
|
||||
.status-color-context.failed.selected :global(.sccfg) { color: #ff4545 !important; } |
|
||||
.status-color-context.failed :global(.sccpb) { background-color: #ff4545 !important; } |
|
||||
.status-color-context.postponed :global(.sccfg) { color: #446d88 !important; } |
|
||||
.status-color-context.postponed.selected :global(.sccfg) { color: #78c9ff !important; } |
|
||||
.status-color-context.postponed :global(.sccpb) { background-color: #78c9ff !important; } |
|
||||
.status-color-context.idea :global(.sccfg) { color: #878844 !important; } |
|
||||
.status-color-context.idea.selected :global(.sccfg) { color: #e7e55e !important; } |
|
||||
.status-color-context.idea :global(.sccpb) { background-color: #e7e55e !important; } |
|
||||
|
.status-color-context.project :global(.sccfg) { color: #444 !important; } |
||||
|
.status-color-context.project.selected :global(.sccfg) { color: #666 !important; } |
||||
|
.status-color-context.project :global(.sccpb) { background-color: #78ff78 !important; } |
||||
|
.status-color-context.project.completed :global(.sccfg) { color: #484 !important; } |
||||
|
.status-color-context.project.completed.selected :global(.sccfg) { color: #78ff78 !important; } |
||||
|
.status-color-context.project.completed :global(.sccpb) { background-color: #78ff78 !important; } |
||||
|
.status-color-context.project.failed :global(.sccfg) { color: #852a24 !important; } |
||||
|
.status-color-context.project.failed.selected :global(.sccfg) { color: #ff4545 !important; } |
||||
|
.status-color-context.project.failed :global(.sccpb) { background-color: #ff4545 !important; } |
||||
|
.status-color-context.project.onhold :global(.sccfg) { color: #446d88 !important; } |
||||
|
.status-color-context.project.onhold.selected :global(.sccfg) { color: #78c9ff !important; } |
||||
|
.status-color-context.project.onhold :global(.sccpb) { background-color: #78c9ff !important; } |
||||
|
.status-color-context.project.todo :global(.sccfg) { color: #7a7429 !important; } |
||||
|
.status-color-context.project.todo.selected :global(.sccfg) { color: #e7e55e !important; } |
||||
|
.status-color-context.project.todo :global(.sccpb) { background-color: #e7e55e !important; } |
||||
|
.status-color-context.project.wontdo :global(.sccfg) { color: #7a2973 !important; } |
||||
|
.status-color-context.project.wontdo.selected :global(.sccfg) { color: #e75ed0 !important; } |
||||
|
.status-color-context.project.wontdo :global(.sccpb) { background-color: #e75ed0 !important; } |
||||
|
|
||||
|
.status-color-context.task.completed :global(.sccsi) { background-color: #484 !important; color: #78ff78 !important; } |
||||
|
.status-color-context.task.failed :global(.sccsi) { background-color: #85242c !important; color: #ff4545 !important; } |
||||
|
.status-color-context.task.onhold :global(.sccsi) { background-color: #447288 !important; color: #78c9ff !important; } |
||||
|
.status-color-context.task.todo :global(.sccsi) { background-color: #7a7429 !important; color: #e7e55e !important; } |
||||
|
.status-color-context.task.wontdo :global(.sccsi) { background-color: #7a2973 !important; color: #e75ed0 !important; } |
||||
</style> |
</style> |
@ -0,0 +1,13 @@ |
|||||
|
<script lang="ts"> |
||||
|
export let value: string; |
||||
|
export let disabled: boolean = false; |
||||
|
</script> |
||||
|
|
||||
|
<select name="statusTag" bind:value={value} disabled={disabled}> |
||||
|
<option value="" selected={"" === value}>Active / In Progress</option> |
||||
|
<option value="completed" selected={"completed" === value}>Completed</option> |
||||
|
<option value="failed" selected={"failed" === value}>Failed</option> |
||||
|
<option value="on hold" selected={"on hold" === value}>On Hold</option> |
||||
|
<option value="to do" selected={"to do" === value}>To Do</option> |
||||
|
<option value="declined" selected={"declined" === value}>Won't Do</option> |
||||
|
</select> |
@ -0,0 +1,63 @@ |
|||||
|
<script lang="ts"> |
||||
|
import type { IconName } from "../external/icons"; |
||||
|
|
||||
|
import type { TaskResult } from "../models/task"; |
||||
|
import Icon from "./Icon.svelte"; |
||||
|
|
||||
|
export let task: TaskResult; |
||||
|
export let iconName: IconName; |
||||
|
|
||||
|
$: { |
||||
|
switch (task.statusTag) { |
||||
|
case "to do": iconName = "lightbulb"; break; |
||||
|
case "on hold": iconName = "hourglass"; break; |
||||
|
case "declined": iconName = "times"; break; |
||||
|
case "failed": iconName = "times"; break; |
||||
|
default: iconName = "check"; break; |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<div class="icon sccsi" class:inactive={!task.active}> |
||||
|
{#if !task.active} |
||||
|
<span class="on"><Icon block name={iconName} /></span> |
||||
|
<span class="off"> |
||||
|
{task.completedAmount} / {task.itemAmount} |
||||
|
</span> |
||||
|
{:else} |
||||
|
{task.completedAmount} / {task.itemAmount} |
||||
|
{/if} |
||||
|
</div> |
||||
|
|
||||
|
<style> |
||||
|
div.icon { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
font-size: 1em; |
||||
|
padding: 0.2em .5ch; |
||||
|
|
||||
|
margin-right: 0.5em; |
||||
|
background: #444; |
||||
|
color: #CCC; |
||||
|
} |
||||
|
div.icon.inactive { |
||||
|
padding-top: 0.295em; |
||||
|
padding-bottom: 0.115em; |
||||
|
|
||||
|
background: #484; |
||||
|
color: #78ff78; |
||||
|
} |
||||
|
div.icon.inactive span.off { |
||||
|
display: none; |
||||
|
} |
||||
|
div.icon.inactive:hover { |
||||
|
padding-top: 0.16em; |
||||
|
padding-bottom: 0.27em; |
||||
|
} |
||||
|
div.icon.inactive:hover span.on { |
||||
|
display: none; |
||||
|
} |
||||
|
div.icon.inactive:hover span.off { |
||||
|
display: inline; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,30 @@ |
|||||
|
<script lang="ts"> |
||||
|
import type Project from "../models/project"; |
||||
|
import type { TaskResult } from "../models/task"; |
||||
|
import TaskEntry from "./TaskEntry.svelte"; |
||||
|
|
||||
|
export let project: Project; |
||||
|
export let tasks: TaskResult[]; |
||||
|
export let showAllOptions: boolean; |
||||
|
export let header: string; |
||||
|
</script> |
||||
|
|
||||
|
{#if tasks.length > 0} |
||||
|
<h3>{header}</h3> |
||||
|
{#each tasks as task (task.id)} |
||||
|
<TaskEntry showAllOptions={showAllOptions} task={task} project={project} /> |
||||
|
{/each} |
||||
|
{/if} |
||||
|
|
||||
|
<style> |
||||
|
h3:empty { |
||||
|
display: none; |
||||
|
} |
||||
|
|
||||
|
h3 { |
||||
|
padding: 0; |
||||
|
margin: 0; |
||||
|
margin-top: 0.5em; |
||||
|
font-weight: 100; |
||||
|
} |
||||
|
</style> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue