22 changed files with 277 additions and 36 deletions
-
2entities/project.go
-
11frontend/src/lib/clients/sl3.ts
-
4frontend/src/lib/components/common/AmountRow.svelte
-
2frontend/src/lib/components/contexts/ModalContext.svelte
-
23frontend/src/lib/components/contexts/ScopeContext.svelte
-
4frontend/src/lib/components/controls/StatInput.svelte
-
0frontend/src/lib/components/layout/Main.svelte
-
25frontend/src/lib/components/layout/Row.svelte
-
0frontend/src/lib/components/layout/Section.svelte
-
4frontend/src/lib/components/layout/SubSection.svelte
-
6frontend/src/lib/components/project/ItemSubSection.svelte
-
8frontend/src/lib/components/project/ProjectMain.svelte
-
8frontend/src/lib/components/project/RequirementSection.svelte
-
24frontend/src/lib/components/scope/StatSubSection.svelte
-
9frontend/src/lib/modals/DeletionModal.svelte
-
113frontend/src/lib/modals/StatCreateEditModal.svelte
-
4frontend/src/lib/models/item.ts
-
4frontend/src/lib/models/project.ts
-
9frontend/src/lib/models/stat.ts
-
6frontend/src/lib/utils/stat.ts
-
41frontend/src/routes/[scope=prettyid]/index.svelte
-
6frontend/src/routes/[scope=prettyid]/projects/[project=prettyid].svelte
@ -0,0 +1,24 @@ |
|||
<script lang="ts"> |
|||
import type Stat from "$lib/models/stat"; |
|||
import Amount from "../common/Amount.svelte"; |
|||
import AmountRow from "../common/AmountRow.svelte"; |
|||
import Markdown from "../common/Markdown.svelte"; |
|||
import Option from "../layout/Option.svelte"; |
|||
import OptionsRow from "../layout/OptionsRow.svelte"; |
|||
import SubSection from "../layout/SubSection.svelte"; |
|||
|
|||
export let stat: Stat; |
|||
</script> |
|||
|
|||
<SubSection noProgress title={stat.name} subtitle="{stat.weight}x"> |
|||
<OptionsRow slot="right"> |
|||
<Option open={{name: "stat.edit", stat}}>Edit</Option> |
|||
<Option open={{name: "stat.delete", stat}} color="red">Delete</Option> |
|||
</OptionsRow> |
|||
<Markdown source={stat.description} /> |
|||
<AmountRow> |
|||
{#each (stat.allowedAmounts || []) as amount (amount.value)} |
|||
<Amount label={amount.label} value={amount.value} /> |
|||
{/each} |
|||
</AmountRow> |
|||
</SubSection> |
@ -0,0 +1,113 @@ |
|||
<script lang="ts"> |
|||
import { sl3 } from "$lib/clients/sl3"; |
|||
|
|||
import Modal from "$lib/components/common/Modal.svelte"; |
|||
import ModalBody from "$lib/components/common/ModalBody.svelte"; |
|||
import { getModalContext } from "$lib/components/contexts/ModalContext.svelte"; |
|||
import { getScopeContext } from "$lib/components/contexts/ScopeContext.svelte"; |
|||
import type { Requirement } from "$lib/models/project"; |
|||
import type Scope from "$lib/models/scope"; |
|||
import type { StatInput } from "$lib/models/stat"; |
|||
import type Stat from "$lib/models/stat"; |
|||
import { getAllContexts } from "svelte"; |
|||
|
|||
const {currentModal, closeModal} = getModalContext(); |
|||
const {scope, upsertStat} = getScopeContext(); |
|||
|
|||
let stat: StatInput |
|||
let statId: number |
|||
let op: string |
|||
|
|||
let error: string |
|||
let loading: boolean |
|||
let show: boolean |
|||
|
|||
$: switch ($currentModal.name) { |
|||
case "stat.create": |
|||
initCreate($scope) |
|||
break; |
|||
case "stat.edit": |
|||
initEdit($currentModal.stat) |
|||
break; |
|||
|
|||
default: |
|||
loading = false; |
|||
error = null; |
|||
show = false; |
|||
} |
|||
|
|||
function initCreate(scope: Scope, requirement?: Requirement) { |
|||
let stats = requirement?.stats.map(s => ({statId: s.id, required: 0, acquired: 0})); |
|||
if (stats == null) { |
|||
stats = scope.stats.map(s => ({statId: s.id, required: 0, acquired: 0})) |
|||
} |
|||
|
|||
stat = { |
|||
name: "", |
|||
weight: 1, |
|||
description: "", |
|||
allowedAmounts: null, |
|||
} |
|||
|
|||
op = "Create" |
|||
show = true; |
|||
} |
|||
|
|||
function initEdit(current: Stat) { |
|||
stat = { |
|||
name: current.name, |
|||
weight: current.weight, |
|||
description: current.description, |
|||
allowedAmounts: current.allowedAmounts ? current.allowedAmounts.slice() : void(0), |
|||
}; |
|||
statId = current.id; |
|||
|
|||
op = "Edit" |
|||
show = true; |
|||
} |
|||
|
|||
async function submit() { |
|||
error = null; |
|||
loading = true; |
|||
|
|||
try { |
|||
switch (op) { |
|||
case "Create": |
|||
const createdStat = await sl3(fetch).createStat($scope.id, stat); |
|||
upsertStat(createdStat); |
|||
break; |
|||
case "Edit": |
|||
const editedStat = await sl3(fetch).updateStat($scope.id, statId, { |
|||
...stat, |
|||
allowedAmounts: void(0), |
|||
}); |
|||
upsertStat(editedStat); |
|||
break; |
|||
} |
|||
|
|||
closeModal(); |
|||
} catch(err) { |
|||
if (err.statusCode != null) { |
|||
error = err.statusMessage; |
|||
} else { |
|||
error = err |
|||
} |
|||
|
|||
} finally { |
|||
loading = false; |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<form on:submit|preventDefault={submit}> |
|||
<Modal closable show={show} verb={op} noun="Item" disabled={loading} error={error}> |
|||
<ModalBody> |
|||
<label for="name">Name</label> |
|||
<input name="name" type="text" bind:value={stat.name} /> |
|||
<label for="weight">Weight</label> |
|||
<input name="weight" type="number" min={0} step={0.001} bind:value={stat.weight} /> |
|||
<label for="description">Description</label> |
|||
<textarea name="description" bind:value={stat.description} /> |
|||
</ModalBody> |
|||
</Modal> |
|||
</form> |
@ -1,10 +1,49 @@ |
|||
<script lang="ts" context="module"> |
|||
import Column from "$lib/components/layout/Column.svelte"; |
|||
import Columns from "$lib/components/layout/Columns.svelte"; |
|||
|
|||
import Row from "$lib/components/layout/Row.svelte"; |
|||
|
|||
import type { Load } from "@sveltejs/kit/types/internal"; |
|||
|
|||
export const load: Load = async({}) => { |
|||
export const load: Load = async({}) => { |
|||
return { |
|||
props: {} |
|||
}; |
|||
} |
|||
</script> |
|||
|
|||
<script lang="ts"> |
|||
import { getScopeContext } from "$lib/components/contexts/ScopeContext.svelte"; |
|||
import Option from "$lib/components/layout/Option.svelte"; |
|||
import OptionsRow from "$lib/components/layout/OptionsRow.svelte"; |
|||
import StatSubSection from "$lib/components/scope/StatSubSection.svelte"; |
|||
import DeletionModal from "$lib/modals/DeletionModal.svelte"; |
|||
import StatCreateEditModal from "$lib/modals/StatCreateEditModal.svelte"; |
|||
|
|||
const {scope} = getScopeContext(); |
|||
</script> |
|||
|
|||
<Columns wide> |
|||
<Column> |
|||
<Row title="Schedule"> |
|||
</Row> |
|||
<Row title="Today"> |
|||
</Row> |
|||
</Column> |
|||
<Column> |
|||
<Row title="Sprints"> |
|||
</Row> |
|||
<Row title="Stats"> |
|||
<OptionsRow slot="right"> |
|||
<Option open={{name: "stat.create"}}>Create</Option> |
|||
</OptionsRow> |
|||
{#each $scope.stats as stat (stat.id)} |
|||
<StatSubSection stat={stat} /> |
|||
{/each} |
|||
</Row> |
|||
</Column> |
|||
</Columns> |
|||
|
|||
<StatCreateEditModal /> |
|||
<DeletionModal /> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue