Gisle Aune
4 years ago
17 changed files with 365 additions and 46 deletions
-
60api/task.go
-
5database/postgres/project.go
-
96database/postgres/tasks.go
-
15migrations/postgres/20210403142913_create_table_task_link.sql
-
10models/task.go
-
13services/loader.go
-
3svelte-ui/src/App.svelte
-
14svelte-ui/src/clients/stufflog.ts
-
5svelte-ui/src/components/ProgressNumbers.svelte
-
3svelte-ui/src/components/ProjectEntry.svelte
-
14svelte-ui/src/components/ProjectSelect.svelte
-
8svelte-ui/src/components/TaskEntry.svelte
-
36svelte-ui/src/components/TaskSelect.svelte
-
69svelte-ui/src/forms/TaskLinkForm.svelte
-
6svelte-ui/src/models/task.ts
-
2svelte-ui/src/pages/QLPage.svelte
-
4svelte-ui/src/stores/modal.ts
@ -0,0 +1,15 @@ |
|||
-- +goose Up |
|||
-- +goose StatementBegin |
|||
CREATE TABLE task_link ( |
|||
project_id CHAR(16) NOT NULL, |
|||
task_id CHAR(16) NOT NULL, |
|||
|
|||
PRIMARY KEY (project_id, task_id), |
|||
UNIQUE (task_id, project_id) |
|||
); |
|||
-- +goose StatementEnd |
|||
|
|||
-- +goose Down |
|||
-- +goose StatementBegin |
|||
DROP TABLE task_link; |
|||
-- +goose StatementEnd |
@ -0,0 +1,36 @@ |
|||
<script lang="ts"> |
|||
import projectStore from "../stores/project"; |
|||
|
|||
export let value = ""; |
|||
export let name = ""; |
|||
export let disabled = false; |
|||
export let optional = false; |
|||
|
|||
$: { |
|||
if ($projectStore.stale && !$projectStore.loading) { |
|||
projectStore.load({}); |
|||
} |
|||
} |
|||
|
|||
$: { |
|||
if ($projectStore.projects.length > 0 && value === "" && !optional) { |
|||
const nonEmpty = $projectStore.projects.find(g => g.tasks.length > 0); |
|||
if (nonEmpty != null) { |
|||
value = nonEmpty.tasks[0].id; |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<select name={name} bind:value={value} disabled={disabled || $projectStore.loading}> |
|||
{#if optional} |
|||
<option value={""} selected={"" === value}>None</option> |
|||
{/if} |
|||
{#each $projectStore.projects as project (project.id)} |
|||
<optgroup label={project.name}> |
|||
{#each project.tasks as task (task.id)} |
|||
<option value={task.id} selected={task.id === value}>{task.name}</option> |
|||
{/each} |
|||
</optgroup> |
|||
{/each} |
|||
</select> |
@ -0,0 +1,69 @@ |
|||
<script lang="ts"> |
|||
import stuffLogClient from "../clients/stufflog"; |
|||
import Modal from "../components/Modal.svelte"; |
|||
import ProjectSelect from "../components/ProjectSelect.svelte"; |
|||
import TaskSelect from "../components/TaskSelect.svelte"; |
|||
import markStale from "../stores/markStale"; |
|||
import modalStore from "../stores/modal"; |
|||
|
|||
export let deletion = false; |
|||
export let creation = false; |
|||
|
|||
const md = $modalStore; |
|||
|
|||
let projectId = ""; |
|||
let taskId = ""; |
|||
let verb = "Add"; |
|||
|
|||
if (md.name === "tasklink.delete") { |
|||
projectId = md.project.id; |
|||
taskId = md.task.id; |
|||
verb = "Delete"; |
|||
} else if (md.name === "tasklink.add") { |
|||
projectId = (md.project||{id:""}).id; |
|||
taskId = (md.task||{id:""}).id; |
|||
} else { |
|||
throw new Error(`Wrong form ${md.name}`) |
|||
} |
|||
|
|||
let error = null; |
|||
let loading = false; |
|||
|
|||
function onSubmit() { |
|||
loading = true; |
|||
error = null; |
|||
|
|||
if (creation) { |
|||
stuffLogClient.createTaskLink(projectId, taskId).then(() => { |
|||
markStale("goal", "project"); |
|||
modalStore.close(); |
|||
}).catch(err => { |
|||
error = err.message ? err.message : err.toString(); |
|||
}).finally(() => { |
|||
loading = false; |
|||
}) |
|||
} else if (deletion) { |
|||
stuffLogClient.deleteTaskLink(projectId, taskId).then(() => { |
|||
markStale("goal", "project"); |
|||
modalStore.close(); |
|||
}).catch(err => { |
|||
error = err.message ? err.message : err.toString(); |
|||
}).finally(() => { |
|||
loading = false; |
|||
}) |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<Modal show title="{verb} Link" error={error} closable on:close={modalStore.close}> |
|||
<form on:submit|preventDefault={onSubmit}> |
|||
<label for="taskId">Source Task</label> |
|||
<TaskSelect disabled={deletion} name="taskId" bind:value={taskId} /> |
|||
<label for="projectId">Destination Project</label> |
|||
<ProjectSelect disabled={deletion} name="projectId" bind:value={projectId} /> |
|||
|
|||
<hr /> |
|||
|
|||
<button disabled={loading} type="submit">{verb} Link</button> |
|||
</form> |
|||
</Modal> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue