Browse Source

add scheduling.

master
Gisle Aune 2 years ago
parent
commit
20b23ae822
  1. 77
      frontend/src/lib/components/controls/ScheduledDateInput.svelte
  2. 19
      frontend/src/lib/components/project/ItemTimeInfo.svelte
  3. 5
      frontend/src/lib/modals/ItemCreateModal.svelte
  4. 1
      frontend/src/lib/models/item.ts
  5. 20
      frontend/src/lib/utils/date.ts
  6. 5
      frontend/src/routes/[scope=prettyid]/overview.svelte
  7. 5
      frontend/src/routes/index.svelte

77
frontend/src/lib/components/controls/ScheduledDateInput.svelte

@ -0,0 +1,77 @@
<script lang="ts">
import { endOfMonth, endOfWeek, endOfYear, formatDate, nextMonth, nextYear } from "$lib/utils/date";
export let value: string;
export let openDate: Date;
let selected: "none" | "date" | "eod" | "eot" | "eow" | "eonw" | "eonnw" | "eom" | "eonm" | "eoy" | "eony" = !!value ? "date" : "none";
$: {
switch (selected) {
case "eod":
value = formatDate(openDate);
break;
case "eot":
value = formatDate(new Date(openDate.getTime() + 86400000));
break;
case "eow":
value = formatDate(endOfWeek(openDate))
break;
case "eonw":
value = formatDate(endOfWeek(new Date(openDate.getTime() + (86400000 * 7))))
break;
case "eonnw":
value = formatDate(endOfWeek(new Date(openDate.getTime() + (86400000 * 14))))
break;
case "eom":
value = formatDate(endOfMonth(openDate))
break;
case "eonm":
value = formatDate(endOfMonth(nextMonth(openDate)))
break;
case "eoy":
value = formatDate(endOfYear(openDate))
break;
case "eony":
value = formatDate(endOfYear(nextYear(openDate)))
break;
case "date":
if (value == "") {
value = formatDate(openDate);
}
break;
case "none":
value = "";
break;
}
}
</script>
<select bind:value={selected}>
<option value="none">Not Scheduled</option>
<option value="eod">Today</option>
<option value="eot">Tomorrow</option>
<option value="eow">Sunday</option>
<option value="eonw">Next Sunday</option>
<option value="eonnw">The Sunday after Next</option>
<option value="eom">End of Month</option>
<option value="eonm">End of Next Month</option>
<option value="eoy">End of Year</option>
<option value="eony">End of Next Year</option>
<option value="date">Specific Date</option>
</select>
{#if selected !== "none"}
<input type="date" disabled={selected !== "date"} bind:value={value} />
{/if}
<style>
select {
margin-bottom: 0.25em !important;
}
input {
margin-top: 0 !important;
resize: none !important;
}
</style>

19
frontend/src/lib/components/project/ItemTimeInfo.svelte

@ -14,27 +14,32 @@
$: {
const ct = new Date(item.createdTime);
let t = ct;
let noTime = false;
if (item.acquiredTime != null) {
const at = new Date(item.acquiredTime);
t = at;
if (Math.abs(at.getTime() - ct.getTime()) < 300000) {
action = "Created/Acquired"
action = "Created/Acquired";
} else {
action = "Acquired"
action = "Acquired";
}
colorClass = "acquired"
colorClass = "acquired";
} else if (item.scheduledDate != null) {
t = new Date(item.scheduledDate);
action = "Scheduled for"
colorClass = "scheduled"
action = "Scheduled for";
colorClass = "scheduled";
noTime = true;
} else {
action = "Created"
colorClass = "created"
action = "Created";
colorClass = "created";
}
timeStr = formatPrettyTime(t, $now);
if (noTime) {
timeStr = timeStr.split(" at ")[0];
}
}
</script>

5
frontend/src/lib/modals/ItemCreateModal.svelte

@ -13,6 +13,7 @@
import { getSprintListContext } from "$lib/components/contexts/SprintListContext.svelte";
import AcquiredTimeInput from "$lib/components/controls/AcquiredTimeInput.svelte";
import RequirementSelect from "$lib/components/controls/RequirementSelect.svelte";
import ScheduledDateInput from "$lib/components/controls/ScheduledDateInput.svelte";
import StatInput from "$lib/components/controls/StatInput.svelte";
import Checkbox from "$lib/components/layout/Checkbox.svelte";
import type Item from "$lib/models/item";
@ -123,6 +124,8 @@
const submission: ItemInput = {
...item,
acquiredTime: item.acquiredTime ? new Date(item.acquiredTime).toISOString() : void(0),
scheduledDate: item.scheduledDate || void(0),
clearScheduledDate: !item.scheduledDate,
stats: item.stats.filter(s => s.required > 0).map(s => ({...s})),
}
@ -192,6 +195,8 @@
<AcquiredTimeInput openDate={openedDate} bind:value={item.acquiredTime} />
<label for="description">Description</label>
<textarea name="description" bind:value={item.description} />
<label for="scheduledTime">Scheduled</label>
<ScheduledDateInput openDate={openedDate} bind:value={item.scheduledDate} />
{#if op === "Create"}
<Checkbox bind:checked={addAnother} label="Add another." />
{/if}

1
frontend/src/lib/models/item.ts

@ -42,6 +42,7 @@ export interface ItemInput {
acquiredTime?: string
scheduledDate?: string
clearAcquiredTime?: boolean
clearScheduledDate?: boolean
stats: StatValueInput[]
}

20
frontend/src/lib/utils/date.ts

@ -139,18 +139,28 @@ export function formatPrettyTime(date: Date, now: Date) {
const d = startOfDay(date);
const n = startOfDay(now);
const diff = (d.getTime() - n.getTime()) / (86400000);
const diff = Math.round((d.getTime() - n.getTime()) / (86400000));
const hhmm = `${pad(date.getHours())}:${pad(date.getMinutes())}`;
const dayOfMonth = date.getDate();
var ordinalDay = dayOfMonth + "th";
if (dayOfMonth == 1) {
ordinalDay = dayOfMonth + "st";
} else if (dayOfMonth == 2) {
ordinalDay = dayOfMonth + "nd"
} else if (dayOfMonth == 3) {
ordinalDay = dayOfMonth + "rd"
}
if (diff === 0) {
return `today at ${hhmm}`;
} else if (diff === 1) {
return `tomorrow at ${hhmm}`;
} else if (diff === -1) {
return `yesterday at ${hhmm}`;
} else if (diff > -3 && diff < 6) {
return `${weekDay[date.getDay()]} at ${hhmm}`;
} else if (diff > -7 && diff < 7) {
return `${weekDay[date.getDay()]}, the ${ordinalDay} at ${hhmm}`;
} else {
return `${monthName(date)} ${date.getDate()} at ${hhmm}`;
return `${ordinalDay} of ${monthName(date)} at ${hhmm}`;
}
}

5
frontend/src/routes/[scope=prettyid]/overview.svelte

@ -4,7 +4,8 @@
function generateItemFilters(now: Date): {scheduledFilter: ItemFilter, acquiredFilter: ItemFilter, looseFilter: ItemFilter} {
return {
scheduledFilter: {
scheduledDate: datesOf(parseInterval("next:7d", now)),
scheduledDate: datesOf(parseInterval("next:30d", now)),
unAcquired: true,
},
acquiredFilter: {
acquiredTime: morningInterval(parseInterval("today", now)),
@ -103,7 +104,7 @@
<Card on:click={openEditScope} pointerCursor><CardHeader>Edit Scope</CardHeader></Card>
<Card on:click={openDeleteScope} pointerCursor><CardHeader>Delete Scope</CardHeader></Card>
</Row>
<ItemListRow title="Scheduled" key="scheduleItems" />
<ItemListRow title="Scheduled" key="scheduledItems" />
<ItemListRow title="Today" key="acquiredItems" showAcquiredTime />
<ItemListRow title="Loose" key="looseItems" />
</Column>

5
frontend/src/routes/index.svelte

@ -5,7 +5,8 @@
function generateItemFilters(now: Date): {scheduledFilter: ItemFilter, acquiredFilter: ItemFilter, looseFilter: ItemFilter} {
return {
scheduledFilter: {
scheduledDate: datesOf(parseInterval("next:7d", now)),
scheduledDate: datesOf(parseInterval("next:30d", now)),
unAcquired: true,
},
acquiredFilter: {
acquiredTime: morningInterval(parseInterval("today", now)),
@ -90,7 +91,7 @@
</OptionsRow>
<ScopeLinkList />
</Row>
<ItemListRow title="Scheduled" key="scheduleItems" />
<ItemListRow title="Scheduled" key="scheduledItems" />
<ItemListRow title="Today" key="acquiredItems" showAcquiredTime />
<ItemListRow title="Loose" key="looseItems" />
</Column>

Loading…
Cancel
Save