diff --git a/svelte-ui/package-lock.json b/svelte-ui/package-lock.json index ac3f2ce..c4c3d27 100644 --- a/svelte-ui/package-lock.json +++ b/svelte-ui/package-lock.json @@ -2757,6 +2757,12 @@ "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=", "dev": true }, + "assignment": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/assignment/-/assignment-2.0.0.tgz", + "integrity": "sha1-/9F7Ib9dayLnd7mJaBqBVFaj3T4=", + "dev": true + }, "async": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async/-/async-1.0.0.tgz", @@ -3256,6 +3262,12 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, + "he": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/he/-/he-0.5.0.tgz", + "integrity": "sha1-LAX/rvkLaOhg8/0rVO9YCYknfuI=", + "dev": true + }, "http-assert": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.4.1.tgz", @@ -3355,6 +3367,16 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "insane": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/insane/-/insane-2.6.2.tgz", + "integrity": "sha1-wqtouz4AarRRVg0bRGkXMpwKgSA=", + "dev": true, + "requires": { + "assignment": "2.0.0", + "he": "0.5.0" + } + }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", diff --git a/svelte-ui/package.json b/svelte-ui/package.json index 499d936..f96ed14 100644 --- a/svelte-ui/package.json +++ b/svelte-ui/package.json @@ -22,6 +22,7 @@ "amazon-cognito-identity-js": "^4.5.6", "aws-amplify": "^3.3.14", "fa-svelte": "^3.1.0", + "insane": "^2.6.2", "lodash-es": "^4.17.20", "marked": "^1.2.7", "rollup": "^2.3.4", diff --git a/svelte-ui/src/components/DateRangeSelect.svelte b/svelte-ui/src/components/DateRangeSelect.svelte index 2b541d3..d33313a 100644 --- a/svelte-ui/src/components/DateRangeSelect.svelte +++ b/svelte-ui/src/components/DateRangeSelect.svelte @@ -14,6 +14,8 @@ import EveryMinute from "./EveryMinute.svelte"; export let toValue: string; export let disabled: boolean; export let styled: boolean; + export let noFuture: boolean; + export let label: string = "Time Period"; let selected: string = "custom"; let options: DateOption[] = []; @@ -39,12 +41,14 @@ import EveryMinute from "./EveryMinute.svelte"; from: startOfWeek(now), to: endOfWeek(now), }); - options.push({ - id: "next_week", - label: "Next Week", - from: startOfWeek(nextWeek), - to: endOfWeek(nextWeek), - }); + if (!noFuture) { + options.push({ + id: "next_week", + label: "Next Week", + from: startOfWeek(nextWeek), + to: endOfWeek(nextWeek), + }); + } options.push({ id: "last_week", label: "Last Week", @@ -58,12 +62,14 @@ import EveryMinute from "./EveryMinute.svelte"; from: current, to: endOfMonth(current), }); - options.push({ - id: "next_month", - label: "Next Month", - from: nextMonth(current), - to: endOfMonth(nextMonth(current)), - }); + if (!noFuture) { + options.push({ + id: "next_month", + label: "Next Month", + from: nextMonth(current), + to: endOfMonth(nextMonth(current)), + }); + } options.push({ id: "last_month", label: "Last Month", @@ -77,12 +83,14 @@ import EveryMinute from "./EveryMinute.svelte"; from: startOfYear(now), to: endOfYear(now), }); - options.push({ - id: "next_year", - label: "Next Year", - from: startOfYear(new Date(Date.now() + (366.25 * 86400000))), - to: endOfYear(new Date(Date.now() + (365.25 * 86400000))), - }); + if (!noFuture) { + options.push({ + id: "next_year", + label: "Next Year", + from: startOfYear(new Date(Date.now() + (366.25 * 86400000))), + to: endOfYear(new Date(Date.now() + (365.25 * 86400000))), + }); + } options.push({ id: "last_year", label: "Last Year", @@ -112,16 +120,73 @@ import EveryMinute from "./EveryMinute.svelte";
- - +
+ + +
{#if selected === "custom"} - - - - +
+ + +
+
+ + +
{/if} -
\ No newline at end of file + + + \ No newline at end of file diff --git a/svelte-ui/src/components/Markdown.svelte b/svelte-ui/src/components/Markdown.svelte index de0a76e..8e90752 100644 --- a/svelte-ui/src/components/Markdown.svelte +++ b/svelte-ui/src/components/Markdown.svelte @@ -1,10 +1,11 @@
{@html outputHtml}
diff --git a/svelte-ui/src/pages/GoalPage.svelte b/svelte-ui/src/pages/GoalPage.svelte index b5c7741..3d271d4 100644 --- a/svelte-ui/src/pages/GoalPage.svelte +++ b/svelte-ui/src/pages/GoalPage.svelte @@ -4,23 +4,37 @@ import type { ModalData } from "../stores/modal"; import goalStore from "../stores/goal"; import RefreshSelection from "../components/RefreshSelection.svelte"; + import { endOfWeek, formatFormTime, startOfWeek } from "../utils/time"; + import DateRangeSelect from "../components/DateRangeSelect.svelte"; const mdGoalAdd: ModalData = {name: "goal.add"}; - let minTime = new Date(Date.now() - 366 * 86400000); + let minTime = formatFormTime($goalStore.filter.minTime || startOfWeek(new Date())); + let maxTime = formatFormTime(endOfWeek(new Date())); $: { - if ($goalStore.stale && !$goalStore.loading) { - goalStore.load({minTime}); + const min = new Date(minTime); + const max = new Date(maxTime); + + if (!$goalStore.loading) { + if ($goalStore.stale || $goalStore.filter.minTime?.getTime() != min.getTime() || $goalStore.filter.maxTime?.getTime() != max.getTime()) { + goalStore.load({ + minTime: min, + maxTime: max, + }); + } } }
- {#each $goalStore.goals as goal (goal.id)} - - {/each} - Add Goal + +
+ {#each $goalStore.goals as goal (goal.id)} + + {/each} + Add Goal +
@@ -33,4 +47,8 @@ margin-top: 0; box-sizing: border-box; } + + div.goal-list.loading { + opacity: 0.75; + } \ No newline at end of file diff --git a/svelte-ui/src/pages/LogsPage.svelte b/svelte-ui/src/pages/LogsPage.svelte index 6ba454f..734e755 100644 --- a/svelte-ui/src/pages/LogsPage.svelte +++ b/svelte-ui/src/pages/LogsPage.svelte @@ -2,33 +2,33 @@ import LogEntry from "../components/LogEntry.svelte"; import type { LogResult } from "../models/log"; import logStore from "../stores/logs"; - import { formatDate, formatTime, formatWeekdayDate } from "../utils/time"; - import Boi from "../components/Boi.svelte"; + import { endOfWeek, formatFormTime, formatWeekdayDate, startOfWeek } from "../utils/time"; import EmptyList from "../components/EmptyList.svelte"; import RefreshSelection from "../components/RefreshSelection.svelte"; + import DateRangeSelect from "../components/DateRangeSelect.svelte"; let groupedLogs: {day: number, text: string, logs: LogResult[]}[] = []; - let minTime = $logStore.filter.minTime || new Date(Date.now() - (86400000*30)); + let minTime = formatFormTime($logStore.filter.minTime || startOfWeek(new Date())); + let maxTime = formatFormTime(endOfWeek(new Date())); let emptyMessage = `No logs since ${formatWeekdayDate(minTime)}.`; - function loadMore() { - if (!$logStore.stale && !$logStore.loading) { - minTime = new Date(minTime.getTime() - (86400000*30)); - logStore.markStale(); - } - } - $: { - if ($logStore.stale && !$logStore.loading) { - logStore.load({ - minTime: minTime, - }); + const min = new Date(minTime); + const max = new Date(maxTime); + + if (!$logStore.loading) { + if ($logStore.stale || $logStore.filter.minTime?.getTime() != min.getTime() || $logStore.filter.maxTime?.getTime() != max.getTime()) { + logStore.load({ + minTime: min, + maxTime: max, + }); + } } } $: { if (!$logStore.loading && !$logStore.stale) { - emptyMessage = `No logs since ${formatWeekdayDate(minTime)}.`; + emptyMessage = `No logs between ${formatWeekdayDate(minTime)} and ${formatWeekdayDate(maxTime)}.`; } } @@ -81,20 +81,18 @@
- {#each groupedLogs as logGroup (logGroup.day)} -

{logGroup.text}

- {#each logGroup.logs as log (log.id)} - + +
+ {#each groupedLogs as logGroup (logGroup.day)} +

{logGroup.text}

+ {#each logGroup.logs as log (log.id)} + + {/each} {/each} - {/each} - {#if groupedLogs.length === 0} - - {/if} - {#if !$logStore.loading && !$logStore.stale} - Load More - {:else} - Loading... - {/if} + {#if groupedLogs.length === 0} + + {/if} +
@@ -108,6 +106,10 @@ box-sizing: border-box; } + div.log-list.loading { + opacity: 0.75; + } + h2 { font-size: 1.5em; font-weight: 100; diff --git a/svelte-ui/src/stores/goal.ts b/svelte-ui/src/stores/goal.ts index 012a99e..eafd5c6 100644 --- a/svelte-ui/src/stores/goal.ts +++ b/svelte-ui/src/stores/goal.ts @@ -6,6 +6,7 @@ interface GoalStoreData { loading: boolean stale: boolean goals: GoalResult[] + filter: GoalFilter } function createGoalStore() { @@ -13,8 +14,12 @@ function createGoalStore() { loading: false, stale: true, goals: [], + filter: {}, }); + let lastLoad = 0; + let spamPoints = 3; + return { subscribe, @@ -24,6 +29,23 @@ function createGoalStore() { async load(filter: GoalFilter) { update(v => ({...v, loading: true, filter})); + + // Prevent too much spammery when tweaking the date. + const timeSince = Date.now() - lastLoad; + if (timeSince < 3000) { + if (timeSince < 1000) { + spamPoints -= 1; + } + + if (spamPoints <= 0) { + await new Promise(resolve => setTimeout(resolve, 3000 - timeSince)); + spamPoints = 3; + } + } else { + spamPoints = 3; + } + lastLoad = Date.now(); + const goals = await stuffLogClient.listGoals(filter); const expireds = []; diff --git a/svelte-ui/src/stores/logs.ts b/svelte-ui/src/stores/logs.ts index aebeee4..b80c878 100644 --- a/svelte-ui/src/stores/logs.ts +++ b/svelte-ui/src/stores/logs.ts @@ -17,6 +17,9 @@ function createProjectStore() { filter: {}, }); + let lastLoad = 0; + let spamPoints = 10; + return { subscribe, @@ -26,6 +29,23 @@ function createProjectStore() { async load(filter: LogFilter) { update(v => ({...v, loading: true, filter})); + + // Prevent too much spammery when tweaking the date. + const timeSince = Date.now() - lastLoad; + if (timeSince < 3000) { + if (timeSince < 1000) { + spamPoints -= 1; + } + + if (spamPoints <= 0) { + await new Promise(resolve => setTimeout(resolve, 3000 - timeSince)); + spamPoints = 10; + } + } else { + spamPoints = 10; + } + lastLoad = Date.now(); + const logs = await stuffLogClient.listLogs(filter); update(v => ({...v, loading: false, stale: false, logs: logs.reverse()})); },