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";
-
Time Period
-
- {#each options as option (option.id)}
- {option.label}
- {/each}
-
+
+ {label}
+
+ {#each options as option (option.id)}
+ {option.label}
+ {/each}
+
+
{#if selected === "custom"}
-
Start Time
-
-
End Time
-
+
+ Start Time
+
+
+
+ End Time
+
+
{/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()}));
},