summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorivarlovlie <git@ivarlovlie.no>2022-06-04 13:54:44 +0200
committerivarlovlie <git@ivarlovlie.no>2022-06-04 13:54:44 +0200
commitfdbeffe78e5cd7393d28915189ec518a06b941f1 (patch)
treeb652b5187b4d08c87cc39ebbad38ddbf00e4a498
parent098c5bdde3860941f1c03585071a4e3584a7317f (diff)
downloadgreatoffice-fdbeffe78e5cd7393d28915189ec518a06b941f1.tar.xz
greatoffice-fdbeffe78e5cd7393d28915189ec518a06b941f1.zip
feat: !WIP start implementation of svelte-query
-rw-r--r--apps/projects/src/app/index.svelte18
-rw-r--r--apps/projects/src/app/pages/home.svelte41
-rw-r--r--apps/projects/src/package.json2
-rw-r--r--apps/projects/src/pnpm-lock.yaml102
-rw-r--r--apps/web-shared/src/lib/api/time-entry.ts2
-rw-r--r--apps/web-shared/src/lib/configuration.ts6
-rw-r--r--apps/web-shared/src/lib/helpers.ts11
7 files changed, 158 insertions, 24 deletions
diff --git a/apps/projects/src/app/index.svelte b/apps/projects/src/app/index.svelte
index 9dd2bf8..c217797 100644
--- a/apps/projects/src/app/index.svelte
+++ b/apps/projects/src/app/index.svelte
@@ -5,6 +5,7 @@
import {logout_user} from "$app/lib/services/user-service";
import Router from "svelte-spa-router";
import {wrap} from "svelte-spa-router/wrap";
+ import {QueryClient, QueryClientProvider} from "@sveltestack/svelte-query";
import {is_active} from "$shared/lib/session";
import UiWorkbench from "$app/pages/ui-workbench.svelte";
import NotFound from "$app/pages/not-found.svelte";
@@ -22,6 +23,9 @@
return true;
}
+ const queryClient = new QueryClient();
+
+
const routes = {
"/home": wrap({
component: Home,
@@ -44,13 +48,15 @@
};
</script>
<PreHeader show="{!online}">You seem to be offline, please check your internet connection.</PreHeader>
-<Router
- {routes}
- restoreScrollState={true}
- on:routeLoading={() => {
+<QueryClientProvider client={queryClient}>
+ <Router
+ {routes}
+ restoreScrollState={true}
+ on:routeLoading={() => {
document.getElementById("loader").style.display = "inline-block";
}}
- on:routeLoaded={() => {
+ on:routeLoaded={() => {
document.getElementById("loader").style.display = "none";
}}
-/>
+ />
+</QueryClientProvider>
diff --git a/apps/projects/src/app/pages/home.svelte b/apps/projects/src/app/pages/home.svelte
index c3e7af4..84d6728 100644
--- a/apps/projects/src/app/pages/home.svelte
+++ b/apps/projects/src/app/pages/home.svelte
@@ -1,7 +1,9 @@
<script lang="ts">
- import {IconNames} from "$shared/lib/configuration";
+ import {delete_time_entry, get_time_entries, get_time_entry, update_time_entry} from "$shared/lib/api/time-entry";
+ import {IconNames, QueryKeys} from "$shared/lib/configuration";
import {TimeEntryDto} from "$shared/lib/models/TimeEntryDto";
import {Temporal} from "@js-temporal/polyfill";
+ import {useMutation, useQuery, useQueryClient} from "@sveltestack/svelte-query";
import {onMount} from "svelte";
import Tile from "$shared/components/tile.svelte";
import Button from "$shared/components/button.svelte";
@@ -11,7 +13,6 @@
import EntryFrom from "$app/pages/views/entry-form/index.svelte";
import {seconds_to_hour_minute_string, unwrap_date_time_from_entry} from "$shared/lib/helpers";
import {TimeEntryQueryDuration} from "$shared/lib/models/TimeEntryQuery";
- import entries, {delete_entry_async, get_time_entry, reload_entries} from "$app/lib/stores/entries";
let currentTime = "";
let isLoading = false;
@@ -19,31 +20,40 @@
let timeEntries = [] as Array<TimeEntryDto>;
let timeLoggedTodayString = "0h0m";
+ const queryClient = useQueryClient();
+ const queryResult = useQuery(QueryKeys.entries, async () => await get_time_entries({
+ duration: TimeEntryQueryDuration.TODAY,
+ page: 1,
+ pageSize: 100,
+ })?.data ?? []
+ );
+
function set_current_time() {
currentTime = Temporal.Now.plainTimeISO().toLocaleString(undefined, {
timeStyle: "short",
});
}
+ const delete_entry_mutation = useMutation(delete_time_entry, {
+ onSuccess: (data) => {
+ queryClient.invalidateQueries([QueryKeys.entries, data.data.id]);
+ },
+ });
+
async function on_edit_entry_button_click(event, entryId: string) {
- const response = get_time_entry(entryId);
+ const response = useQuery([QueryKeys.entries, entryId], () => {
+ return get_time_entry(entryId);
+ });
+
EditEntryForm.set_values(response);
}
async function on_delete_entry_button_click(event, entryId: string) {
if (confirm("Are you sure you want to delete this entry?")) {
- await delete_entry_async(entryId);
+ $delete_entry_mutation.mutate(entryId);
}
}
- async function load_todays_entries() {
- await reload_entries({
- duration: TimeEntryQueryDuration.TODAY,
- page: 1,
- pageSize: 100,
- });
- }
-
function on_create_from_stopwatch(event) {
EditEntryForm.set_time({to: event.detail.to, from: event.detail.from});
if (event.detail.description) {
@@ -56,11 +66,10 @@
setInterval(() => {
set_current_time();
}, 1e4);
- await load_todays_entries();
- entries.subscribe((val) => {
+ queryResult.subscribe((result) => {
const newEntries = [];
let loggedSecondsToday = 0;
- for (const entry of val) {
+ for (const entry of result.data?.results ?? []) {
const date_time = unwrap_date_time_from_entry(entry);
newEntries.push({
id: entry.id,
@@ -115,7 +124,7 @@
icon_width="1.2rem"
icon_height="1.2rem"
title="Refresh today's entries"
- on:click={load_todays_entries}/>
+ on:click={() => queryClient.invalidateQueries(QueryKeys.entries)}/>
</TCell>
</THead>
<TBody>
diff --git a/apps/projects/src/package.json b/apps/projects/src/package.json
index b3fee26..636df49 100644
--- a/apps/projects/src/package.json
+++ b/apps/projects/src/package.json
@@ -8,6 +8,8 @@
},
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "1.0.0-next.43",
+ "@sveltestack/svelte-query": "^1.6.0",
+ "broadcast-channel": "^4.13.0",
"sass": "^1.51.0",
"svelte": "^3.48.0",
"svelte-preprocess": "^4.10.6",
diff --git a/apps/projects/src/pnpm-lock.yaml b/apps/projects/src/pnpm-lock.yaml
index 3b56115..aae0331 100644
--- a/apps/projects/src/pnpm-lock.yaml
+++ b/apps/projects/src/pnpm-lock.yaml
@@ -3,6 +3,8 @@ lockfileVersion: 5.4
specifiers:
'@js-temporal/polyfill': ^0.4.1
'@sveltejs/vite-plugin-svelte': 1.0.0-next.43
+ '@sveltestack/svelte-query': ^1.6.0
+ broadcast-channel: ^4.13.0
fuzzysort: ^1.9.0
sass: ^1.51.0
svelte: ^3.48.0
@@ -17,6 +19,8 @@ dependencies:
devDependencies:
'@sveltejs/vite-plugin-svelte': 1.0.0-next.43_svelte@3.48.0+vite@2.9.8
+ '@sveltestack/svelte-query': 1.6.0_broadcast-channel@4.13.0
+ broadcast-channel: 4.13.0
sass: 1.51.0
svelte: 3.48.0
svelte-preprocess: 4.10.6_24ezlekk4ocevlsjgs2qnqmjum
@@ -26,6 +30,13 @@ devDependencies:
packages:
+ /@babel/runtime/7.18.3:
+ resolution: {integrity: sha512-38Y8f7YUhce/K7RMwTp7m0uCumpv9hZkitCbBClqQIow1qSbCvGkcegKOXpEWCQLfWmevgRiWokZ1GkpfhbZug==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ regenerator-runtime: 0.13.9
+ dev: true
+
/@js-temporal/polyfill/0.4.1:
resolution: {integrity: sha512-q45ecIocpa2TLem2jNOsCrDwP/sgKZdSkt+C1Rx07OkdKsdbvVfHcD1iDiK9scxBZrBQ38uJ8VQISXBS70ql1w==}
engines: {node: '>=12'}
@@ -65,6 +76,17 @@ packages:
- supports-color
dev: true
+ /@sveltestack/svelte-query/1.6.0_broadcast-channel@4.13.0:
+ resolution: {integrity: sha512-C0wWuh6av1zu3Pzwrg6EQmX3BhDZQ4gMAdYu6Tfv4bjbEZTB00uEDz52z92IZdONh+iUKuyo0xRZ2e16k2Xifg==}
+ peerDependencies:
+ broadcast-channel: ^4.5.0
+ peerDependenciesMeta:
+ broadcast-channel:
+ optional: true
+ dependencies:
+ broadcast-channel: 4.13.0
+ dev: true
+
/@types/node/17.0.31:
resolution: {integrity: sha512-AR0x5HbXGqkEx9CadRH3EBYx/VkiUgZIhP4wvPn/+5KIsgpNoyFaRlVe0Zlx9gRtg8fA06a9tskE2MSN7TcG4Q==}
dev: true
@@ -110,6 +132,18 @@ packages:
fill-range: 7.0.1
dev: true
+ /broadcast-channel/4.13.0:
+ resolution: {integrity: sha512-fcDr8QNJ4SOb6jyjUNZatVNmcHtSWfW4PFcs4xIEFZAtorKCIFoEYtjIjaQ4c0jrbr/Bl8NIwOWiLSyspoAnEQ==}
+ dependencies:
+ '@babel/runtime': 7.18.3
+ detect-node: 2.1.0
+ microtime: 3.0.0
+ oblivious-set: 1.1.1
+ p-queue: 6.6.2
+ rimraf: 3.0.2
+ unload: 2.3.1
+ dev: true
+
/buffer-crc32/0.2.13:
resolution: {integrity: sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=}
dev: true
@@ -155,6 +189,10 @@ packages:
engines: {node: '>=8'}
dev: true
+ /detect-node/2.1.0:
+ resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==}
+ dev: true
+
/es6-promise/3.3.1:
resolution: {integrity: sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=}
dev: true
@@ -371,6 +409,10 @@ packages:
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
dev: true
+ /eventemitter3/4.0.7:
+ resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==}
+ dev: true
+
/fill-range/7.0.1:
resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
engines: {node: '>=8'}
@@ -494,6 +536,15 @@ packages:
sourcemap-codec: 1.4.8
dev: true
+ /microtime/3.0.0:
+ resolution: {integrity: sha512-SirJr7ZL4ow2iWcb54bekS4aWyBQNVcEDBiwAz9D/sTgY59A+uE8UJU15cp5wyZmPBwg/3zf8lyCJ5NUe1nVlQ==}
+ engines: {node: '>= 4.0.0'}
+ requiresBuild: true
+ dependencies:
+ node-addon-api: 1.7.2
+ node-gyp-build: 3.9.0
+ dev: true
+
/min-indent/1.0.1:
resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
engines: {node: '>=4'}
@@ -526,17 +577,50 @@ packages:
hasBin: true
dev: true
+ /node-addon-api/1.7.2:
+ resolution: {integrity: sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==}
+ dev: true
+
+ /node-gyp-build/3.9.0:
+ resolution: {integrity: sha512-zLcTg6P4AbcHPq465ZMFNXx7XpKKJh+7kkN699NiQWisR2uWYOWNWqRHAmbnmKiL4e9aLSlmy5U7rEMUXV59+A==}
+ hasBin: true
+ dev: true
+
/normalize-path/3.0.0:
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
engines: {node: '>=0.10.0'}
dev: true
+ /oblivious-set/1.1.1:
+ resolution: {integrity: sha512-Oh+8fK09mgGmAshFdH6hSVco6KZmd1tTwNFWj35OvzdmJTMZtAkbn05zar2iG3v6sDs1JLEtOiBGNb6BHwkb2w==}
+ dev: true
+
/once/1.4.0:
resolution: {integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=}
dependencies:
wrappy: 1.0.2
dev: true
+ /p-finally/1.0.0:
+ resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /p-queue/6.6.2:
+ resolution: {integrity: sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==}
+ engines: {node: '>=8'}
+ dependencies:
+ eventemitter3: 4.0.7
+ p-timeout: 3.2.0
+ dev: true
+
+ /p-timeout/3.2.0:
+ resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==}
+ engines: {node: '>=8'}
+ dependencies:
+ p-finally: 1.0.0
+ dev: true
+
/path-is-absolute/1.0.1:
resolution: {integrity: sha1-F0uSaHNVNP+8es5r9TpanhtcX18=}
engines: {node: '>=0.10.0'}
@@ -571,6 +655,10 @@ packages:
picomatch: 2.3.1
dev: true
+ /regenerator-runtime/0.13.9:
+ resolution: {integrity: sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==}
+ dev: true
+
/regexparam/2.0.0:
resolution: {integrity: sha512-gJKwd2MVPWHAIFLsaYDZfyKzHNS4o7E/v8YmNf44vmeV2e4YfVoDToTOKTvE7ab68cRJ++kLuEXJBaEeJVt5ow==}
engines: {node: '>=8'}
@@ -592,6 +680,13 @@ packages:
glob: 7.2.0
dev: true
+ /rimraf/3.0.2:
+ resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
+ hasBin: true
+ dependencies:
+ glob: 7.2.0
+ dev: true
+
/rollup/2.72.1:
resolution: {integrity: sha512-NTc5UGy/NWFGpSqF1lFY8z9Adri6uhyMLI6LvPAXdBKoPRFhIIiBUpt+Qg2awixqO3xvzSijjhnb4+QEZwJmxA==}
engines: {node: '>=10.0.0'}
@@ -739,6 +834,13 @@ packages:
hasBin: true
dev: true
+ /unload/2.3.1:
+ resolution: {integrity: sha512-MUZEiDqvAN9AIDRbbBnVYVvfcR6DrjCqeU2YQMmliFZl9uaBUjTkhuDQkBiyAy8ad5bx1TXVbqZ3gg7namsWjA==}
+ dependencies:
+ '@babel/runtime': 7.18.3
+ detect-node: 2.1.0
+ dev: true
+
/vite/2.9.8_sass@1.51.0:
resolution: {integrity: sha512-zsBGwn5UT3YS0NLSJ7hnR54+vUKfgzMUh/Z9CxF1YKEBVIe213+63jrFLmZphgGI5zXwQCSmqIdbPuE8NJywPw==}
engines: {node: '>=12.2.0'}
diff --git a/apps/web-shared/src/lib/api/time-entry.ts b/apps/web-shared/src/lib/api/time-entry.ts
index e81329d..064964a 100644
--- a/apps/web-shared/src/lib/api/time-entry.ts
+++ b/apps/web-shared/src/lib/api/time-entry.ts
@@ -39,8 +39,6 @@ export async function update_time_entry(entryDto: TimeEntryDto): Promise<IIntern
}
// LABELS
-
-
export async function create_time_label(labelDto: TimeLabelDto): Promise<IInternalFetchResponse> {
return http_post(api_base("v1/labels/create"), labelDto);
}
diff --git a/apps/web-shared/src/lib/configuration.ts b/apps/web-shared/src/lib/configuration.ts
index f597bb4..e4cd1ef 100644
--- a/apps/web-shared/src/lib/configuration.ts
+++ b/apps/web-shared/src/lib/configuration.ts
@@ -33,6 +33,12 @@ export function is_debug(): boolean {
return localStorage.getItem(StorageKeys.debug) !== "true";
}
+export const QueryKeys = {
+ labels: "labels",
+ categories: "categories",
+ entries: "entries",
+};
+
export const IconNames = {
github: "github",
verticalDots: "verticalDots",
diff --git a/apps/web-shared/src/lib/helpers.ts b/apps/web-shared/src/lib/helpers.ts
index ed526af..acf74d7 100644
--- a/apps/web-shared/src/lib/helpers.ts
+++ b/apps/web-shared/src/lib/helpers.ts
@@ -8,6 +8,17 @@ export const URL_REGEX = new RegExp(/^(http:\/\/www\.|https:\/\/www\.|http:\/\/|
export const GUID_REGEX = new RegExp(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i);
export const NORWEGIAN_PHONE_NUMBER_REGEX = new RegExp(/(0047|\+47|47)?\d{8,12}/);
+export function get_default_sorted(unsorted: Array<TimeEntryDto>): Array<TimeEntryDto> {
+ if (unsorted.length < 1) return unsorted;
+ const byStart = unsorted.sort((a, b) => {
+ return Temporal.Instant.compare(Temporal.Instant.from(b.start), Temporal.Instant.from(a.start));
+ });
+
+ return byStart.sort((a, b) => {
+ return Temporal.Instant.compare(Temporal.Instant.from(b.stop), Temporal.Instant.from(a.stop));
+ });
+}
+
export function is_email(value: string): boolean {
return EMAIL_REGEX.test(String(value).toLowerCase());
}