This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
<script lang="ts">
|
||||
import type { GroupResult } from "../models/group";
|
||||
|
||||
export let value = "";
|
||||
export let name = "";
|
||||
export let disabled = false;
|
||||
export let optional = false;
|
||||
export let optionalLabel = "None";
|
||||
export let group: GroupResult = null;
|
||||
|
||||
$: {
|
||||
if (group != null && !group.items.find(t => t.id === value)) {
|
||||
if (optional) {
|
||||
value = "";
|
||||
} else {
|
||||
value = group.items[0]?.id || "";
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<select name={name} bind:value={value} disabled={disabled || group == null || group.items.length === 0}>
|
||||
{#if optional}
|
||||
<option value={""} selected={"" === value}>{optionalLabel}</option>
|
||||
{/if}
|
||||
{#if group != null}
|
||||
{#each group.items as item (item.id)}
|
||||
<option value={item.id} selected={item.id === value}>{item.name} ({item.groupWeight})</option>
|
||||
{/each}
|
||||
{/if}
|
||||
</select>
|
||||
@@ -3,9 +3,14 @@
|
||||
import Icon from "./Icon.svelte";
|
||||
|
||||
export let item: Item = null;
|
||||
export let amount: number = null;
|
||||
export let noPadding: boolean = false;
|
||||
</script>
|
||||
|
||||
<div class="item">
|
||||
<div class="item" class:noPadding>
|
||||
{#if amount != null}
|
||||
<div class="item-amount">{amount}x</div>
|
||||
{/if}
|
||||
<div class="item-icon">
|
||||
<Icon name={item.icon} />
|
||||
</div>
|
||||
@@ -22,13 +27,21 @@
|
||||
margin-bottom: 0em;
|
||||
font-size: 0.75em;
|
||||
}
|
||||
div.item a {
|
||||
a {
|
||||
color: inherit;
|
||||
}
|
||||
div.item div.item-icon {
|
||||
div.item-icon {
|
||||
padding: 0.25em 0.5ch 0.25em 0;
|
||||
}
|
||||
div.item div.item-name {
|
||||
div.item-name {
|
||||
padding: 0.125em;
|
||||
}
|
||||
div.item-amount {
|
||||
padding: 0.125em;
|
||||
padding-right: 1ch;
|
||||
}
|
||||
|
||||
div.item.noPadding {
|
||||
margin-top: 0em;
|
||||
}
|
||||
</style>
|
||||
@@ -4,6 +4,7 @@
|
||||
export let value = "";
|
||||
export let name = "";
|
||||
export let disabled = false;
|
||||
export let optional = false;
|
||||
|
||||
$: {
|
||||
if ($groupStore.stale && !$groupStore.loading) {
|
||||
@@ -12,7 +13,7 @@
|
||||
}
|
||||
|
||||
$: {
|
||||
if ($groupStore.groups.length > 0 && value === "") {
|
||||
if ($groupStore.groups.length > 0 && value === "" && !optional) {
|
||||
const nonEmpty = $groupStore.groups.find(g => g.items.length > 0);
|
||||
if (nonEmpty != null) {
|
||||
value = nonEmpty.items[0].id;
|
||||
@@ -22,6 +23,9 @@
|
||||
</script>
|
||||
|
||||
<select name={name} bind:value={value} disabled={disabled || $groupStore.loading}>
|
||||
{#if optional}
|
||||
<option value={""} selected={"" === value}>None</option>
|
||||
{/if}
|
||||
{#each $groupStore.groups as group (group.id)}
|
||||
<optgroup label={group.name}>
|
||||
{#each group.items as item (item.id)}
|
||||
|
||||
@@ -21,7 +21,10 @@
|
||||
</script>
|
||||
|
||||
<ChildEntry entry={log}>
|
||||
<ItemLink item={log.item} />
|
||||
<ItemLink amount={log.itemAmount} item={log.item} />
|
||||
{#if log.secondaryItem != null}
|
||||
<ItemLink noPadding amount={log.secondaryItemAmount} item={log.secondaryItem} />
|
||||
{/if}
|
||||
<OptionRow>
|
||||
<Option open={mdLogEdit}>Edit Log</Option>
|
||||
<Option open={mdLogDelete}>Delete Log</Option>
|
||||
|
||||
@@ -186,9 +186,6 @@ div.modal :global(textarea:disabled) {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
div.modal :global(input:last-of-type) {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
div.modal :global(input.nolast) {
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
import ChildEntry from "./ChildEntry.svelte";
|
||||
import DateSpan from "./DateSpan.svelte";
|
||||
import Icon from "./Icon.svelte";
|
||||
import ItemLink from "./ItemLink.svelte";
|
||||
import Option from "./Option.svelte";
|
||||
import OptionRow from "./OptionRow.svelte";
|
||||
|
||||
@@ -37,14 +38,7 @@
|
||||
{task.completedAmount} / {task.itemAmount}
|
||||
{/if}
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="item-icon">
|
||||
<Icon name={task.item.icon} />
|
||||
</div>
|
||||
<div class="item-name">
|
||||
<a href="/items#{task.item.groupId}">{task.item.name} ({task.item.groupWeight})</a>
|
||||
</div>
|
||||
</div>
|
||||
<ItemLink item={task.item} />
|
||||
<OptionRow>
|
||||
{#if task.logs.length > 0}
|
||||
<Option on:click={toggleShowLogs}>{showLogs ? "Hide Logs" : "Show Logs"}</Option>
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
import { formatFormTime, nextMonth } from "../utils/time";
|
||||
import GroupSelect from "../components/GroupSelect.svelte";
|
||||
import markStale from "../stores/markStale";
|
||||
import Checkbox from "../components/Checkbox.svelte";
|
||||
import GroupItemSelect from "../components/GroupItemSelect.svelte";
|
||||
import groupStore from "../stores/group";
|
||||
import type { GroupResult } from "../models/group";
|
||||
|
||||
export let deletion = false;
|
||||
export let creation = false;
|
||||
@@ -21,6 +25,9 @@
|
||||
name: "",
|
||||
description: "",
|
||||
completedAmount: 0,
|
||||
unweighted: false,
|
||||
compositionMode: "item",
|
||||
itemId: null,
|
||||
group: {id: "", name: "", icon: "question", description: ""},
|
||||
items: [],
|
||||
logs: [],
|
||||
@@ -37,11 +44,15 @@
|
||||
let description = goal.description;
|
||||
let groupId = goal.groupId;
|
||||
let amount = goal.amount;
|
||||
let unweighted = goal.unweighted;
|
||||
let itemId = goal.itemId || "";
|
||||
let compositionMode = goal.compositionMode;
|
||||
let startTime = formatFormTime(goal.startTime);
|
||||
let endTime = formatFormTime(goal.endTime);
|
||||
|
||||
let error = null;
|
||||
let loading = false;
|
||||
let selectedGroup: GroupResult = null;
|
||||
|
||||
function onSubmit() {
|
||||
loading = true;
|
||||
@@ -50,7 +61,8 @@
|
||||
stuffLogClient.createGoal({
|
||||
startTime: new Date(startTime),
|
||||
endTime: new Date(endTime),
|
||||
groupId, name, description, amount,
|
||||
itemId: itemId || null,
|
||||
groupId, name, description, amount, unweighted, compositionMode
|
||||
}).then(() => {
|
||||
markStale("goal");
|
||||
modalStore.close();
|
||||
@@ -72,7 +84,9 @@
|
||||
stuffLogClient.updateGoal(goal.id, {
|
||||
startTime: new Date(startTime),
|
||||
endTime: new Date(endTime),
|
||||
name, description, amount,
|
||||
itemId: itemId || null,
|
||||
clearItemId: itemId === "",
|
||||
name, description, amount, compositionMode, unweighted,
|
||||
}).then(() => {
|
||||
markStale("goal");
|
||||
modalStore.close();
|
||||
@@ -89,6 +103,8 @@
|
||||
function onClose() {
|
||||
modalStore.close();
|
||||
}
|
||||
|
||||
$: selectedGroup = $groupStore.groups.find(g => g.id === groupId);
|
||||
</script>
|
||||
|
||||
<Modal show title="{verb} Goal" error={error} closable on:close={onClose}>
|
||||
@@ -99,12 +115,20 @@
|
||||
<textarea disabled={deletion} name="description" bind:value={description} />
|
||||
<label for="groupId">Group</label>
|
||||
<GroupSelect disabled={!creation} name="groupId" bind:value={groupId}/>
|
||||
<label for="groupId">Specific Item</label>
|
||||
<GroupItemSelect disabled={deletion} optional optionalLabel="Whole Group" group={selectedGroup} name="itemId" bind:value={itemId}/>
|
||||
<label for="amount">Amount</label>
|
||||
<input disabled={deletion} name="amount" type="number" bind:value={amount} />
|
||||
<label for="compositionMode">Composition Mode (does nothing right now)</label>
|
||||
<select name="compositionMode" bind:value={compositionMode} disabled={deletion}>
|
||||
<option value="item" selected={"item" === compositionMode}>Item</option>
|
||||
<option value="task" selected={"task" === compositionMode}>Task</option>
|
||||
</select>
|
||||
<label for="startTime">Start Time</label>
|
||||
<input disabled={deletion} name="startTime" type="datetime-local" bind:value={startTime} />
|
||||
<label for="endTime">End Time</label>
|
||||
<input disabled={deletion} name="endTime" type="datetime-local" bind:value={endTime} />
|
||||
<Checkbox bind:checked={unweighted} label="Unweighted (All items count as 1)" />
|
||||
|
||||
<hr />
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import stuffLogClient from "../clients/stufflog";
|
||||
import Checkbox from "../components/Checkbox.svelte";
|
||||
import ItemSelect from "../components/ItemSelect.svelte";
|
||||
import Modal from "../components/Modal.svelte";
|
||||
import type { LogResult } from "../models/log";
|
||||
import markStale from "../stores/markStale";
|
||||
@@ -17,8 +18,12 @@
|
||||
itemId: "",
|
||||
loggedTime: new Date().toISOString(),
|
||||
description: "",
|
||||
itemAmount: 1,
|
||||
secondaryItemAmount: 0,
|
||||
secondaryItemId: null,
|
||||
task: null,
|
||||
item: null,
|
||||
secondaryItem: null,
|
||||
}
|
||||
let defaultMarkInactive = false;
|
||||
let verb = "Add";
|
||||
@@ -34,6 +39,9 @@
|
||||
|
||||
let loggedTime = formatFormTime(log.loggedTime);
|
||||
let description = log.description;
|
||||
let itemAmount = log.itemAmount;
|
||||
let secondaryItemId = log.secondaryItemId || "";
|
||||
let secondaryItemAmount = log.secondaryItemAmount;
|
||||
let markInactive = defaultMarkInactive;
|
||||
let error = null;
|
||||
let loading = false;
|
||||
@@ -46,7 +54,8 @@
|
||||
stuffLogClient.createLog({
|
||||
taskId: log.task.id,
|
||||
loggedTime: new Date(loggedTime).toISOString(),
|
||||
description,
|
||||
secondaryItemId: secondaryItemId || null,
|
||||
description, itemAmount, secondaryItemAmount,
|
||||
}).then(() => {
|
||||
markStale("project", "task", "goal", "log");
|
||||
|
||||
@@ -74,7 +83,9 @@
|
||||
} else {
|
||||
stuffLogClient.updateLog(log.id, {
|
||||
loggedTime: new Date(loggedTime).toISOString(),
|
||||
description,
|
||||
secondaryItemId: secondaryItemId || null,
|
||||
clearSecondaryItemId: secondaryItemId == "",
|
||||
description, itemAmount, secondaryItemAmount
|
||||
}).then(() => {
|
||||
markStale("project", "task", "goal", "log");
|
||||
modalStore.close();
|
||||
@@ -97,8 +108,17 @@
|
||||
<input disabled name="taskName" type="text" value={log.task.name} />
|
||||
<label for="loggedTime">Logged Time</label>
|
||||
<input disabled={deletion} name="loggedTime" type="datetime-local" bind:value={loggedTime} />
|
||||
<label for="itemAmount">Item Amount</label>
|
||||
<input disabled={deletion} name="itemAmount" type="number" bind:value={itemAmount} />
|
||||
<label for="description">Description</label>
|
||||
<textarea disabled={deletion} name="description" bind:value={description} />
|
||||
<label for="secondaryItemId">Secondary Item</label>
|
||||
<ItemSelect name="secondaryItemId" disabled={deletion} optional bind:value={secondaryItemId} />
|
||||
{#if secondaryItemId != ""}
|
||||
<label for="secondaryItemAmount">Secondary Item Amount</label>
|
||||
<input disabled={deletion} name="secondaryItemAmount" type="number" bind:value={secondaryItemAmount} />
|
||||
{/if}
|
||||
|
||||
<Checkbox disabled={deletion} bind:checked={markInactive} label="Mark task inactive/completed." />
|
||||
|
||||
<hr />
|
||||
|
||||
@@ -5,11 +5,14 @@ import type { LogResult } from "./log";
|
||||
export default interface Goal {
|
||||
id: string
|
||||
groupId: string
|
||||
itemId?: string
|
||||
startTime: string
|
||||
endTime: string
|
||||
amount: number
|
||||
name: string
|
||||
description: string
|
||||
unweighted: boolean
|
||||
compositionMode: string
|
||||
}
|
||||
|
||||
export interface GoalFilter {
|
||||
@@ -31,17 +34,24 @@ interface GoalResultItem extends Item {
|
||||
|
||||
export interface GoalInput {
|
||||
groupId: string
|
||||
itemId: string
|
||||
startTime: string | Date
|
||||
endTime: string | Date
|
||||
amount: number
|
||||
name: string
|
||||
description: string
|
||||
unweighted: boolean
|
||||
compositionMode: string
|
||||
}
|
||||
|
||||
export interface GoalUpdate {
|
||||
itemId?: string
|
||||
startTime?: string | Date
|
||||
endTime?: string | Date
|
||||
amount?: number
|
||||
name?: string
|
||||
description?: string
|
||||
unweighted?: boolean
|
||||
compositionMode?: string
|
||||
clearItemId?: boolean
|
||||
}
|
||||
@@ -5,11 +5,13 @@ export default interface Log {
|
||||
id: string
|
||||
taskId: string
|
||||
itemId: string
|
||||
itemAmount: number
|
||||
secondaryItemId?: string
|
||||
secondaryItemAmount: number
|
||||
loggedTime: string
|
||||
description: string
|
||||
}
|
||||
|
||||
|
||||
export interface LogFilter {
|
||||
minTime?: Date
|
||||
maxTime?: Date
|
||||
@@ -18,15 +20,23 @@ export interface LogFilter {
|
||||
export interface LogResult extends Log {
|
||||
task: Task
|
||||
item: Item
|
||||
secondaryItem?: Item
|
||||
}
|
||||
|
||||
export interface LogInput {
|
||||
taskId: string
|
||||
loggedTime?: string
|
||||
description: string
|
||||
itemAmount: number
|
||||
secondaryItemId?: string
|
||||
secondaryItemAmount?: number
|
||||
}
|
||||
|
||||
export interface LogUpdate {
|
||||
loggedTime?: string
|
||||
description?: string
|
||||
itemAmount?: number
|
||||
secondaryItemId?: string
|
||||
secondaryItemAmount?: number
|
||||
clearSecondaryItemId?: boolean
|
||||
}
|
||||
Reference in New Issue
Block a user