diff options
Diffstat (limited to 'apps/projects-web/src')
45 files changed, 0 insertions, 3404 deletions
diff --git a/apps/projects-web/src/_assets/pre.css b/apps/projects-web/src/_assets/pre.css deleted file mode 100644 index 9c9446e..0000000 --- a/apps/projects-web/src/_assets/pre.css +++ /dev/null @@ -1,128 +0,0 @@ -:root { - --loader-primary: hsl(250, 84%, 54%); - --loader-accent: hsl(342, 89%, 48%); - --loader-contrast: hsl(180, 1%, 84%); - --loader-easing: cubic-bezier(0.645, 0.045, 0.355, 1); -} - -[data-theme="dark"] :root { - --loader-primary: hsl(250, 93%, 65%); - --loader-accent: hsl(342, 92%, 54%); - --loader-contrast: hsl(208, 12%, 24%); - --loader-easing: cubic-bezier(0.645, 0.045, 0.355, 1); -} - -[data-theme="dark"] { - background-color: hsl(203, 24%, 13%); -} - -.fill-loader { - position: relative; - overflow: hidden; - display: inline-block; - margin: 3rem; -} - -.fill-loader__fill { - position: absolute; -} - -@supports (-webkit-animation-name: this) or (animation-name: this) { - .fill-loader__label { - position: absolute; - clip: rect(1px, 1px, 1px, 1px); - -webkit-clip-path: inset(50%); - clip-path: inset(50%); - } -} - -@supports (-webkit-animation-name: this) or (animation-name: this) { - .fill-loader--v4 { - width: 90%; - max-width: 300px; - } - - .fill-loader--v4 .fill-loader__base { - height: 4px; - background-color: var(--loader-contrast); - } - - .fill-loader--v4 .fill-loader__fill { - top: 0; - left: 0; - right: 0; - height: 100%; - background-color: var(--loader-primary); - -webkit-animation: fill-loader-4 1.6s infinite var(--loader-easing); - animation: fill-loader-4 1.6s infinite var(--loader-easing); - will-change: left, right; - } -} - -@-webkit-keyframes fill-loader-4 { - 0% { - left: 0; - right: 100%; - background-color: var(--loader-primary); - } - - 10%, - 60% { - left: 0; - } - - 40%, - 90% { - right: 0; - } - - 50% { - left: 100%; - background-color: var(--loader-primary); - } - - 51% { - left: 0; - right: 100%; - background-color: var(--loader-accent); - } - - 100% { - left: 100%; - background-color: var(--loader-accent); - } -} - -@keyframes fill-loader-4 { - 0% { - left: 0; - right: 100%; - background-color: var(--loader-primary); - } - - 10%, - 60% { - left: 0; - } - - 40%, - 90% { - right: 0; - } - - 50% { - left: 100%; - background-color: var(--loader-primary); - } - - 51% { - left: 0; - right: 100%; - background-color: var(--loader-accent); - } - - 100% { - left: 100%; - background-color: var(--loader-accent); - } -} diff --git a/apps/projects-web/src/_assets/pwa/android-chrome-192x192.png b/apps/projects-web/src/_assets/pwa/android-chrome-192x192.png Binary files differdeleted file mode 100644 index 5c098bc..0000000 --- a/apps/projects-web/src/_assets/pwa/android-chrome-192x192.png +++ /dev/null diff --git a/apps/projects-web/src/_assets/pwa/android-chrome-512x512.png b/apps/projects-web/src/_assets/pwa/android-chrome-512x512.png Binary files differdeleted file mode 100644 index 973a1c3..0000000 --- a/apps/projects-web/src/_assets/pwa/android-chrome-512x512.png +++ /dev/null diff --git a/apps/projects-web/src/_assets/pwa/apple-touch-icon.png b/apps/projects-web/src/_assets/pwa/apple-touch-icon.png Binary files differdeleted file mode 100644 index b4d9773..0000000 --- a/apps/projects-web/src/_assets/pwa/apple-touch-icon.png +++ /dev/null diff --git a/apps/projects-web/src/_assets/pwa/browserconfig.xml b/apps/projects-web/src/_assets/pwa/browserconfig.xml deleted file mode 100644 index b3930d0..0000000 --- a/apps/projects-web/src/_assets/pwa/browserconfig.xml +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<browserconfig> - <msapplication> - <tile> - <square150x150logo src="/mstile-150x150.png"/> - <TileColor>#da532c</TileColor> - </tile> - </msapplication> -</browserconfig> diff --git a/apps/projects-web/src/_assets/pwa/favicon-16x16.png b/apps/projects-web/src/_assets/pwa/favicon-16x16.png Binary files differdeleted file mode 100644 index 5dde9f9..0000000 --- a/apps/projects-web/src/_assets/pwa/favicon-16x16.png +++ /dev/null diff --git a/apps/projects-web/src/_assets/pwa/favicon-32x32.png b/apps/projects-web/src/_assets/pwa/favicon-32x32.png Binary files differdeleted file mode 100644 index 9cef4c4..0000000 --- a/apps/projects-web/src/_assets/pwa/favicon-32x32.png +++ /dev/null diff --git a/apps/projects-web/src/_assets/pwa/favicon.ico b/apps/projects-web/src/_assets/pwa/favicon.ico Binary files differdeleted file mode 100644 index 89c7542..0000000 --- a/apps/projects-web/src/_assets/pwa/favicon.ico +++ /dev/null diff --git a/apps/projects-web/src/_assets/pwa/favicon.svg b/apps/projects-web/src/_assets/pwa/favicon.svg deleted file mode 100644 index 964dbb8..0000000 --- a/apps/projects-web/src/_assets/pwa/favicon.svg +++ /dev/null @@ -1,4 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-stopwatch" viewBox="0 0 16 16"> - <path d="M8.5 5.6a.5.5 0 1 0-1 0v2.9h-3a.5.5 0 0 0 0 1H8a.5.5 0 0 0 .5-.5V5.6z"/> - <path d="M6.5 1A.5.5 0 0 1 7 .5h2a.5.5 0 0 1 0 1v.57c1.36.196 2.594.78 3.584 1.64a.715.715 0 0 1 .012-.013l.354-.354-.354-.353a.5.5 0 0 1 .707-.708l1.414 1.415a.5.5 0 1 1-.707.707l-.353-.354-.354.354a.512.512 0 0 1-.013.012A7 7 0 1 1 7 2.071V1.5a.5.5 0 0 1-.5-.5zM8 3a6 6 0 1 0 .001 12A6 6 0 0 0 8 3z"/> -</svg>
\ No newline at end of file diff --git a/apps/projects-web/src/_assets/pwa/manifest.json b/apps/projects-web/src/_assets/pwa/manifest.json deleted file mode 100644 index 4c550fe..0000000 --- a/apps/projects-web/src/_assets/pwa/manifest.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "manifest_version": 2, - "version": "0.1", - "name": "Time Tracker", - "short_name": "Time Tracker", - "display": "standalone", - "background_color": "#fff", - "theme_color": "#4D3DF7", - "start_url": ".", - "orientation": "portrait", - "icons": [ - { - "src": "/favicon.svg", - "purpose": "maskable any", - "sizes": "any" - }, - { - "src": "/pwa/android-chrome-192x192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "/pwa/android-chrome-512x512.png", - "sizes": "512x512", - "type": "image/png" - } - ] -} diff --git a/apps/projects-web/src/_assets/pwa/mstile-144x144.png b/apps/projects-web/src/_assets/pwa/mstile-144x144.png Binary files differdeleted file mode 100644 index 84d94cb..0000000 --- a/apps/projects-web/src/_assets/pwa/mstile-144x144.png +++ /dev/null diff --git a/apps/projects-web/src/_assets/pwa/mstile-150x150.png b/apps/projects-web/src/_assets/pwa/mstile-150x150.png Binary files differdeleted file mode 100644 index b1398ae..0000000 --- a/apps/projects-web/src/_assets/pwa/mstile-150x150.png +++ /dev/null diff --git a/apps/projects-web/src/_assets/pwa/mstile-310x150.png b/apps/projects-web/src/_assets/pwa/mstile-310x150.png Binary files differdeleted file mode 100644 index 76b16a0..0000000 --- a/apps/projects-web/src/_assets/pwa/mstile-310x150.png +++ /dev/null diff --git a/apps/projects-web/src/_assets/pwa/mstile-310x310.png b/apps/projects-web/src/_assets/pwa/mstile-310x310.png Binary files differdeleted file mode 100644 index d8e4097..0000000 --- a/apps/projects-web/src/_assets/pwa/mstile-310x310.png +++ /dev/null diff --git a/apps/projects-web/src/_assets/pwa/mstile-70x70.png b/apps/projects-web/src/_assets/pwa/mstile-70x70.png Binary files differdeleted file mode 100644 index 0df1e8c..0000000 --- a/apps/projects-web/src/_assets/pwa/mstile-70x70.png +++ /dev/null diff --git a/apps/projects-web/src/_assets/pwa/safari-pinned-tab.svg b/apps/projects-web/src/_assets/pwa/safari-pinned-tab.svg deleted file mode 100644 index ba2220c..0000000 --- a/apps/projects-web/src/_assets/pwa/safari-pinned-tab.svg +++ /dev/null @@ -1,50 +0,0 @@ -<?xml version="1.0" standalone="no"?> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" - "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> -<svg version="1.0" xmlns="http://www.w3.org/2000/svg" - width="700.000000pt" height="700.000000pt" viewBox="0 0 700.000000 700.000000" - preserveAspectRatio="xMidYMid meet"> -<metadata> -Created by potrace 1.14, written by Peter Selinger 2001-2017 -</metadata> -<g transform="translate(0.000000,700.000000) scale(0.100000,-0.100000)" -fill="#000000" stroke="none"> -<path d="M3195 6780 c-116 -3 -211 -10 -226 -17 -39 -17 -105 -98 -116 -142 --19 -72 -2 -146 45 -202 26 -31 96 -69 131 -72 25 -2 31 -6 32 -27 1 -27 1 --198 0 -216 -1 -6 -47 -19 -103 -28 -160 -28 -451 -107 -533 -146 -11 -5 -51 --21 -90 -36 -60 -23 -246 -112 -325 -155 -431 -236 -834 -619 -1101 -1045 --207 -328 -364 -733 -423 -1089 -51 -307 -61 -583 -31 -875 26 -261 119 -615 -225 -861 185 -430 432 -773 800 -1108 75 -69 387 -301 405 -301 1 0 33 -18 70 --40 209 -128 602 -288 796 -325 12 -2 29 -7 39 -10 72 -23 273 -56 435 -73 -144 -14 601 -5 658 13 7 2 37 7 67 10 273 33 616 141 904 283 725 357 1275 -982 1542 1754 55 159 113 395 129 523 4 28 8 57 10 65 2 8 7 47 10 85 3 39 8 -93 10 120 6 66 6 327 0 390 -2 28 -7 82 -10 120 -3 39 -11 99 -16 135 -6 36 --13 79 -16 95 -15 98 -61 279 -103 405 -121 372 -298 694 -542 993 -27 32 -48 -61 -48 65 0 4 35 41 78 84 l77 76 90 -90 c53 -54 108 -99 134 -110 62 -28 130 --25 191 8 95 52 135 151 103 257 -13 46 -44 79 -362 397 -322 323 -351 349 --398 363 -148 44 -287 -61 -285 -215 1 -62 35 -118 126 -208 47 -47 86 -87 86 --90 0 -6 -91 -101 -132 -138 l-25 -23 -46 38 c-264 223 -584 405 -924 528 -92 -34 -320 100 -376 109 -15 3 -35 7 -45 10 -9 3 -34 7 -54 10 -86 13 -113 18 --117 22 -2 2 -4 56 -4 121 l0 118 29 9 c66 19 114 47 139 80 72 95 65 215 -18 -296 -58 56 -83 60 -402 63 -159 1 -380 0 -490 -3z m560 -1104 c224 -24 547 --99 670 -156 11 -5 56 -24 100 -41 90 -37 282 -134 306 -155 8 -8 19 -14 23 --14 13 0 192 -124 286 -199 97 -77 297 -270 364 -351 237 -288 405 -598 509 --941 30 -98 44 -157 72 -299 3 -14 8 -47 11 -75 3 -27 7 -56 10 -63 22 -69 21 --519 -1 -642 -1 -8 -6 -40 -10 -70 -4 -30 -9 -64 -11 -75 -2 -11 -7 -33 -10 --50 -3 -16 -14 -66 -26 -110 -11 -44 -21 -84 -22 -90 -18 -79 -93 -275 -154 --408 -39 -83 -158 -296 -171 -307 -3 -3 -26 -34 -50 -70 -116 -169 -312 -384 --466 -508 -38 -32 -78 -65 -89 -74 -25 -22 -229 -160 -281 -189 -177 -99 -405 --197 -570 -244 -126 -36 -305 -74 -375 -81 -19 -2 -48 -5 -65 -8 -121 -22 --509 -22 -618 0 -12 2 -42 6 -67 10 -369 45 -795 215 -1125 448 -192 135 -399 -326 -517 476 -23 30 -48 61 -55 67 -57 60 -227 336 -291 473 -64 135 -150 365 --167 444 -2 12 -6 30 -9 41 -28 120 -36 156 -41 193 -3 24 -7 53 -10 65 -32 -148 -38 552 -10 707 2 14 7 45 10 70 33 274 160 643 313 910 60 106 201 312 -232 340 3 3 23 28 45 55 22 28 85 96 140 151 347 352 768 590 1252 709 56 14 -118 27 137 30 20 2 61 9 93 14 32 6 92 13 133 17 41 3 76 7 77 8 6 5 368 -2 -428 -8z"/> -<path d="M3423 4754 c-45 -17 -95 -61 -121 -109 -15 -27 -17 -93 -19 -650 -1 --341 -2 -641 -3 -666 l0 -47 -679 0 -679 -1 -49 -24 c-59 -30 -76 -49 -104 --112 -54 -122 23 -270 154 -293 23 -5 400 -8 837 -7 l795 1 42 22 c52 27 98 -82 112 136 8 29 10 273 9 826 -3 854 1 796 -59 867 -53 63 -153 87 -236 57z"/> -</g> -</svg> diff --git a/apps/projects-web/src/app/index.d.ts b/apps/projects-web/src/app/index.d.ts deleted file mode 100644 index c044583..0000000 --- a/apps/projects-web/src/app/index.d.ts +++ /dev/null @@ -1,48 +0,0 @@ -/* Use this file to declare any custom file extensions for importing */ -/* Use this folder to also add/extend a package d.ts file, if needed. */ - -/* CSS MODULES */ -declare module "*.module.css" { - const classes: { [key: string]: string }; - export default classes; -} -declare module "*.module.scss" { - const classes: { [key: string]: string }; - export default classes; -} - -/* CSS */ -declare module "*.css"; -declare module "*.scss"; - -/* IMAGES */ -declare module "*.svg" { - const ref: string; - export default ref; -} -declare module "*.bmp" { - const ref: string; - export default ref; -} -declare module "*.gif" { - const ref: string; - export default ref; -} -declare module "*.jpg" { - const ref: string; - export default ref; -} -declare module "*.jpeg" { - const ref: string; - export default ref; -} -declare module "*.png" { - const ref: string; - export default ref; -} - -/* CUSTOM: ADD YOUR OWN HERE */ -declare module "*.svelte" { - const value: any; - export default value; -} diff --git a/apps/projects-web/src/app/index.html b/apps/projects-web/src/app/index.html deleted file mode 100644 index 7e0b0e1..0000000 --- a/apps/projects-web/src/app/index.html +++ /dev/null @@ -1,63 +0,0 @@ -<!doctype html> -<html lang="en"> - -<head> - <meta charset="UTF-8"> - <meta name="viewport" - content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> - <link rel="apple-touch-icon" - sizes="180x180" - href="../_assets/pwa/apple-touch-icon.png"> - <link rel="icon" - type="image/png" - sizes="32x32" - href="../_assets/pwa/favicon-32x32.png"> - <link rel="icon" - type="image/png" - sizes="16x16" - href="../_assets/pwa/favicon-16x16.png"> - <link rel="manifest" - href="../_assets/pwa/manifest.json"> - <link rel="mask-icon" - href="../_assets/pwa/safari-pinned-tab.svg" - color="#5bbad5"> - <meta name="msapplication-TileColor" - content="#da532c"> - <link rel="icon" - href="../_assets/pwa/favicon.svg"> - <script> - const currentTheme = localStorage.getItem("theme"); - if (currentTheme === "light") { - document.querySelector("html").dataset.theme = "light"; - } else { - document.querySelector("html").dataset.theme = "dark"; - } - </script> - <link rel="stylesheet" - href="../_assets/pre.css"> - <title>Time Tracker</title> -</head> - -<body> - -<noscript> - This page is built with javascript. Allow it and try again. -</noscript> - -<div class="fill-loader fill-loader--v4" - id="loader" - role="alert"> - <p class="fill-loader__label">Loading Time Tracker...</p> - <div aria-hidden="true"> - <div class="fill-loader__base"></div> - <div class="fill-loader__fill"></div> - </div> -</div> - -<div id="root"></div> - -<script type="module" - src="./index.ts"></script> -</body> - -</html> diff --git a/apps/projects-web/src/app/index.scss b/apps/projects-web/src/app/index.scss deleted file mode 100644 index 4794787..0000000 --- a/apps/projects-web/src/app/index.scss +++ /dev/null @@ -1,38 +0,0 @@ -@use '../../web-shared/src/styles/base'as * with ($breakpoints: ('xs': "768px", - 'sm': "768px", - 'md': "1200px", - 'lg': "1200px", - 'xl': "1600px", - ), - $grid-columns: 12); - -@use '../../web-shared/src/styles/custom-style/colors'; -@use '../../web-shared/src/styles/custom-style/spacing'; -@use '../../web-shared/src/styles/custom-style/shared-styles'; -@use '../../web-shared/src/styles/custom-style/typography'; -@use '../../web-shared/src/styles/custom-style/icons'; -@use '../../web-shared/src/styles/custom-style/buttons'; -@use '../../web-shared/src/styles/custom-style/forms'; -@use '../../web-shared/src/styles/custom-style/util'; - -@use '../../web-shared/src/styles/components/radios-checkboxes'; -@use '../../web-shared/src/styles/components/circle-loader'; -@use '../../web-shared/src/styles/components/list'; -@use '../../web-shared/src/styles/components/form-validator'; -@use '../../web-shared/src/styles/components/btn-states'; -@use '../../web-shared/src/styles/components/alert'; -@use '../../web-shared/src/styles/components/details'; -@use '../../web-shared/src/styles/components/tabbed-navigation'; -@use '../../web-shared/src/styles/components/dropdown'; -@use '../../web-shared/src/styles/components/modal'; -@use '../../web-shared/src/styles/components/chip'; -@use '../../web-shared/src/styles/components/autocomplete'; -@use '../../web-shared/src/styles/components/select-autocomplete'; -@use '../../web-shared/src/styles/components/interactive-table'; -@use '../../web-shared/src/styles/components/pagination'; -@use '../../web-shared/src/styles/components/custom-select'; -@use '../../web-shared/src/styles/components/pre-header'; -@use '../../web-shared/src/styles/components/table'; -@use '../../web-shared/src/styles/components/custom-checkbox'; -@use '../../web-shared/src/styles/components/menu'; -@use '../../web-shared/src/styles/components/user-menu'; diff --git a/apps/projects-web/src/app/index.svelte b/apps/projects-web/src/app/index.svelte deleted file mode 100644 index 9dd2bf8..0000000 --- a/apps/projects-web/src/app/index.svelte +++ /dev/null @@ -1,56 +0,0 @@ -<svelte:options immutable={true}/> -<svelte:window bind:online={online}/> - -<script> - import {logout_user} from "$app/lib/services/user-service"; - import Router from "svelte-spa-router"; - import {wrap} from "svelte-spa-router/wrap"; - import {is_active} from "$shared/lib/session"; - import UiWorkbench from "$app/pages/ui-workbench.svelte"; - import NotFound from "$app/pages/not-found.svelte"; - import Home from "$app/pages/home.svelte"; - import Settings from "$app/pages/settings.svelte"; - import Data from "$app/pages/data.svelte"; - import PreHeader from "$shared/components/pre-header.svelte"; - - let online = true; - - async function user_is_logged_in() { - if (!await is_active()) { - await logout_user("expired"); - } - return true; - } - - const routes = { - "/home": wrap({ - component: Home, - conditions: [user_is_logged_in], - }), - "/": wrap({ - component: Home, - conditions: [user_is_logged_in], - }), - "/settings": wrap({ - component: Settings, - conditions: [user_is_logged_in], - }), - "/data": wrap({ - component: Data, - conditions: [user_is_logged_in], - }), - "/ui-workbench": UiWorkbench, - "*": NotFound, - }; -</script> -<PreHeader show="{!online}">You seem to be offline, please check your internet connection.</PreHeader> -<Router - {routes} - restoreScrollState={true} - on:routeLoading={() => { - document.getElementById("loader").style.display = "inline-block"; - }} - on:routeLoaded={() => { - document.getElementById("loader").style.display = "none"; - }} -/> diff --git a/apps/projects-web/src/app/index.ts b/apps/projects-web/src/app/index.ts deleted file mode 100644 index febb583..0000000 --- a/apps/projects-web/src/app/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -// @ts-ignore -import App from "./index.svelte"; -import "./index.scss"; -import {is_debug, is_development} from "$shared/lib/configuration"; -import {noop} from "$shared/lib/helpers"; - -if (is_development() || is_debug()) { - console.log("%c Debug", "background-color:yellow;color:black;font-size:18px;"); -} else { - console.log("%c Production; Suppressing logs", "background-color:yellow;color:black;font-size:18px;"); - console.log = noop; -} - -export default new App({ - target: document.getElementById("root"), -}); diff --git a/apps/projects-web/src/app/lib/services/user-service.ts b/apps/projects-web/src/app/lib/services/user-service.ts deleted file mode 100644 index 7bffa49..0000000 --- a/apps/projects-web/src/app/lib/services/user-service.ts +++ /dev/null @@ -1,21 +0,0 @@ -import {delete_account, logout} from "$shared/lib/api/user"; -import {accounts_base} from "$shared/lib/configuration"; -import {clear_session_data} from "$shared/lib/session"; -import {clear_categories} from "$app/lib/stores/categories"; -import {clear_entries} from "$app/lib/stores/entries"; -import {clear_labels} from "$app/lib/stores/labels"; - -export async function logout_user(reason: string = "") { - await logout(); - clear_session_data(); - clear_categories(); - clear_labels(); - clear_entries(); - location.replace(accounts_base("#/login" + (reason ? "?" + reason : ""))); -} - -export async function delete_user() { - await delete_account(); - clear_session_data(); - location.replace(accounts_base("#/login?deleted")); -} diff --git a/apps/projects-web/src/app/lib/stores/categories.ts b/apps/projects-web/src/app/lib/stores/categories.ts deleted file mode 100644 index 2a63c42..0000000 --- a/apps/projects-web/src/app/lib/stores/categories.ts +++ /dev/null @@ -1,44 +0,0 @@ -import {writable, get} from "svelte/store"; -import {create_time_category, delete_time_category, get_time_categories} from "$shared/lib/api/time-entry"; -import type {TimeCategoryDto} from "$shared/lib/models/TimeCategoryDto"; -import type {IInternalFetchResponse} from "$shared/lib/models/IInternalFetchResponse"; - -const categories = writable<Array<TimeCategoryDto>>([]); - -export async function reload_categories() { - const get_categories_response = await get_time_categories(); - if (!get_categories_response.ok) { - clear_categories(); - return; - } - categories.set(get_categories_response.data ?? []); -} - -export function clear_categories() { - categories.set([]); -} - -export async function create_category_async(request: TimeCategoryDto): Promise<IInternalFetchResponse> { - const create_entry_response = await create_time_category(request); - if (create_entry_response.ok) { - const stored_entries = get(categories); - stored_entries.push(create_entry_response.data); - categories.set(stored_entries); - } - return create_entry_response; -} - -export async function edit_category_async(entry: TimeCategoryDto) { - if (!entry.id) return; -} - -export async function delete_category_async(entry: TimeCategoryDto) { - if (!entry.id) return; - const http_request = await delete_time_category(entry.id); - if (http_request.ok) { - const stored_entries = get(categories); - categories.set(stored_entries.filter(e => e.id !== entry.id)); - } -} - -export default categories; diff --git a/apps/projects-web/src/app/lib/stores/entries.ts b/apps/projects-web/src/app/lib/stores/entries.ts deleted file mode 100644 index e933568..0000000 --- a/apps/projects-web/src/app/lib/stores/entries.ts +++ /dev/null @@ -1,74 +0,0 @@ -import {Temporal} from "@js-temporal/polyfill"; -import {writable, get} from "svelte/store"; -import {get_time_entries, create_time_entry, delete_time_entry, update_time_entry} from "$shared/lib/api/time-entry"; -import type {TimeEntryDto} from "$shared/lib/models/TimeEntryDto"; -import type {IInternalFetchResponse} from "$shared/lib/models/IInternalFetchResponse"; -import type {TimeEntryQuery} from "$shared/lib/models/TimeEntryQuery"; - -const entries = writable<Array<TimeEntryDto>>([]); - -export function get_time_entry(id: string): TimeEntryDto { - return get(entries).find(c => c.id === id); -} - -export async function reload_entries(query: TimeEntryQuery): Promise<void> { - const get_entries_response = await get_time_entries(query); - if (!get_entries_response.ok) { - clear_entries(); - return; - } - entries.set(get_default_sorted(get_entries_response.data?.results ?? [])); -} - -export function clear_entries() { - entries.set([]); -} - -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 async function create_entry_async(request: TimeEntryDto): Promise<IInternalFetchResponse> { - const create_entry_response = await create_time_entry(request); - if (create_entry_response.ok) { - const stored_entries = get(entries) ?? []; - stored_entries.push(create_entry_response.data); - entries.set(get_default_sorted(stored_entries)); - } - return create_entry_response; -} - -export async function edit_entry_async(request: TimeEntryDto): Promise<IInternalFetchResponse> { - if (!request.id) return; - const edit_entry_response = await update_time_entry(request); - if (edit_entry_response.ok) { - const stored_entries = get(entries) ?? []; - const index = stored_entries.findIndex(c => c.id === request.id); - if (index === -1) { - stored_entries.push(edit_entry_response.data); - } else { - stored_entries[index] = edit_entry_response.data; - } - entries.set(get_default_sorted(stored_entries)); - } - return edit_entry_response; -} - -export async function delete_entry_async(entry_id: string): Promise<void> { - if (!entry_id) throw new Error("No id was supplied when deleting query"); - const delete_entry_response = await delete_time_entry(entry_id); - if (delete_entry_response.ok) { - const stored_entries = get(entries) ?? []; - entries.set(get_default_sorted(stored_entries.filter((e) => e.id !== entry_id) ?? [])); - } -} - - -export default entries; diff --git a/apps/projects-web/src/app/lib/stores/labels.ts b/apps/projects-web/src/app/lib/stores/labels.ts deleted file mode 100644 index d5ffaa9..0000000 --- a/apps/projects-web/src/app/lib/stores/labels.ts +++ /dev/null @@ -1,44 +0,0 @@ -import {writable, get} from "svelte/store"; -import {create_time_label, delete_time_label, get_time_labels} from "$shared/lib/api/time-entry"; -import type {IInternalFetchResponse} from "$shared/lib/models/IInternalFetchResponse"; -import type {TimeLabelDto} from "$shared/lib/models/TimeLabelDto"; - -const labels = writable<Array<TimeLabelDto>>([]); - -export async function reload_labels() { - const get_labels_response = await get_time_labels(); - if (!get_labels_response.ok) { - clear_labels(); - return; - } - labels.set(get_labels_response.data ?? []); -} - -export function clear_labels() { - labels.set([]); -} - -export async function create_label_async(request: TimeLabelDto): Promise<IInternalFetchResponse> { - const create_label_response = await create_time_label(request); - if (create_label_response.ok) { - const stored_entries = get(labels) ?? []; - stored_entries.push(create_label_response.data); - labels.set(stored_entries); - } - return create_label_response; -} - -export async function edit_label_async(entry: TimeLabelDto) { - if (!entry.id) throw new Error("Label id is required"); -} - -export async function delete_label_async(entry: TimeLabelDto) { - if (!entry.id) return; - const http_request = await delete_time_label(entry.id); - if (http_request.ok) { - const stored_entries = get(labels) ?? []; - labels.set(stored_entries.filter(e => e.id !== entry.id)); - } -} - -export default labels; diff --git a/apps/projects-web/src/app/pages/_layout.svelte b/apps/projects-web/src/app/pages/_layout.svelte deleted file mode 100644 index 24a9370..0000000 --- a/apps/projects-web/src/app/pages/_layout.svelte +++ /dev/null @@ -1,79 +0,0 @@ -<script> - import {onMount} from "svelte"; - import {location, link} from "svelte-spa-router"; - import {logout_user} from "$app/lib/services/user-service"; - import {random_string, switch_theme} from "$shared/lib/helpers"; - import {get_session_data} from "$shared/lib/session"; - import ProfileModal from "$app/pages/views/profile-modal.svelte"; - import {Menu, MenuItem, MenuItemSeparator} from "$shared/components/menu"; - import Button from "$shared/components/button.svelte"; - import {IconNames} from "$shared/lib/configuration"; - - let ProfileModalFunctions = {}; - let showUserMenu = false; - let userMenuTriggerNode; - const userMenuId = "__menu_" + random_string(3); - const username = get_session_data().profile.username; - - onMount(() => { - userMenuTriggerNode = document.getElementById("open-user-menu"); - }); -</script> - -<ProfileModal bind:functions={ProfileModalFunctions}/> - -<nav class="container max-width-xl@md width-fit-content@md width-100% max-width-none margin-y-xs@md margin-bottom-xs block@md position-relative@md position-absolute bottom-unset@md bottom-0"> - <div class="tabs-nav-v2 justify-between"> - <div class="tab-v2"> - <div class="tab-v2"> - <a href="/home" - use:link - class="tabs-nav-v2__item {$location === '/home' ? 'tabs-nav-v2__item--selected' : ''}">Home</a> - </div> - <div class="tab-v2"> - <a href="/data" - use:link - class="tabs-nav-v2__item {$location === '/data' ? 'tabs-nav-v2__item--selected' : ''}">Data</a> - </div> - <div class="tab-v2"> - <a href="/settings" - use:link - class="tabs-nav-v2__item {$location === '/settings' ? 'tabs-nav-v2__item--selected' : ''}">Settings</a> - </div> - </div> - <div class="tab-v2 padding-x-sm"> - <Button class="user-menu-control" - variant="reset" - id="open-user-menu" - on:click={() => showUserMenu = !showUserMenu} - text={username} - icon={IconNames.chevronDown} - icon_width="2rem" - icon_height="2rem" - icon_right_aligned="true" - title="Toggle user menu" - aria-controls="{userMenuId}" - /> - <Menu bind:show="{showUserMenu}" - trigger={userMenuTriggerNode} - id="{userMenuId}"> - <div slot="options"> - <MenuItem on:click={() => ProfileModalFunctions.open()}> - <span title="Administrate your profile">Profile</span> - </MenuItem> - <MenuItem on:click={() => switch_theme()}> - <span title="Change between a dark and light theme">Switch theme</span> - </MenuItem> - <MenuItemSeparator/> - <MenuItem danger="true" on:click={() => logout_user()}> - <span title="Log out of your profile">Log out</span> - </MenuItem> - </div> - </Menu> - </div> - </div> -</nav> - -<main class="container max-width-xl"> - <slot/> -</main> diff --git a/apps/projects-web/src/app/pages/data.svelte b/apps/projects-web/src/app/pages/data.svelte deleted file mode 100644 index 070b98b..0000000 --- a/apps/projects-web/src/app/pages/data.svelte +++ /dev/null @@ -1,392 +0,0 @@ -<script> - import {IconNames} from "$shared/lib/configuration"; - import {onMount} from "svelte"; - import {Temporal} from "@js-temporal/polyfill"; - import Layout from "./_layout.svelte"; - import Modal from "$shared/components/modal.svelte"; - import Tile from "$shared/components/tile.svelte"; - import Icon from "$shared/components/icon.svelte"; - import EntryForm from "$app/pages/views/entry-form/index.svelte"; - import {Table, THead, TBody, TCell, TRow, TablePaginator} from "$shared/components/table"; - import {TimeEntryQueryDuration} from "$shared/lib/models/TimeEntryQuery"; - import {delete_time_entry, get_time_entries, get_time_entry} from "$shared/lib/api/time-entry"; - import {seconds_to_hour_minute_string, is_guid, move_focus, unwrap_date_time_from_entry} from "$shared/lib/helpers"; - import Button from "$shared/components/button.svelte"; - - let pageCount = 1; - let page = 1; - - const defaultQuery = { - duration: TimeEntryQueryDuration.THIS_YEAR, - categories: [], - labels: [], - page: page, - pageSize: 50, - }; - - let isLoading; - let categories = []; - let labels = []; - let entries = []; - let durationSummary = false; - let EditEntryModal; - let EditEntryForm; - let currentTimespanFilter = TimeEntryQueryDuration.THIS_YEAR; - let currentSpecificDateFilter = Temporal.Now.plainDateTimeISO().subtract({days: 1}).toString().substring(0, 10); - let currentDateRangeFilter = {}; - let currentCategoryFilter = "all"; - let currentLabelFilter = "all"; - let showDateFilterOptions = false; - let secondsLogged = 0; - - function set_duration_summary_string() { - if (entries.length > 0) { - durationSummary = `Showing ${entries.length} ${entries.length === 1 ? "entry" : "entries"}, totalling in ${seconds_to_hour_minute_string(secondsLogged)}`; - } else { - durationSummary = ""; - } - } - - async function load_entries(query = defaultQuery) { - isLoading = true; - const response = await get_time_entries(query); - if (response.status === 200) { - const responseEntries = []; - secondsLogged = 0; - for (const entry of response.data.results) { - const date_time = unwrap_date_time_from_entry(entry); - const seconds = (date_time.duration.hours * 60 * 60) + (date_time.duration.minutes * 60); - responseEntries.push({ - id: entry.id, - date: date_time.start_date, - start: date_time.start_time, - stop: date_time.stop_time, - durationString: date_time.duration.hours + "h" + date_time.duration.minutes + "m", - seconds: seconds, - category: entry.category, - labels: entry.labels, - description: entry.description, - }); - secondsLogged += seconds; - } - entries = responseEntries; - page = response.data.page; - pageCount = response.data.totalPageCount; - } else { - entries = []; - page = 0; - pageCount = 0; - } - isLoading = false; - set_duration_summary_string(); - } - - function load_entries_with_filter(page = 1) { - let query = defaultQuery; - query.duration = currentTimespanFilter; - query.labels = []; - query.categories = []; - query.page = page; - - if (currentTimespanFilter === TimeEntryQueryDuration.SPECIFIC_DATE) { - query.specificDate = currentSpecificDateFilter; - } else { - delete query.specificDate; - } - - if (currentTimespanFilter === TimeEntryQueryDuration.DATE_RANGE) { - query.dateRange = currentDateRangeFilter; - } else { - delete query.dateRange; - } - - if ((currentCategoryFilter !== "all" && currentCategoryFilter?.length > 0) ?? false) { - for (const chosenCategoryId of currentCategoryFilter) { - if (chosenCategoryId === "all") { - continue; - } - query.categories.push({ - id: chosenCategoryId, - }); - } - } - - if ((currentLabelFilter !== "all" && currentLabelFilter?.length > 0) ?? false) { - for (const chosenLabelId of currentLabelFilter) { - if (chosenLabelId === "all") { - continue; - } - query.labels.push({ - id: chosenLabelId, - }); - } - } - - load_entries(query); - } - - async function handle_delete_entry_button_click(e, entryId) { - if (confirm("Are you sure you want to delete this entry?")) { - const response = await delete_time_entry(entryId); - if (response.ok) { - const indexOfEntry = entries.findIndex((c) => c.id === entryId); - if (indexOfEntry !== -1) { - secondsLogged -= entries[indexOfEntry].seconds; - entries.splice(indexOfEntry, 1); - entries = entries; - set_duration_summary_string(); - } - } - } - } - - function handle_edit_entry_form_updated() { - load_entries_with_filter(page); - EditEntryModal.close(); - } - - async function handle_edit_entry_button_click(event, entryId) { - const response = await get_time_entry(entryId); - if (response.status === 200) { - if (is_guid(response.data.id)) { - EditEntryForm.set_values(response.data); - EditEntryModal.open(); - move_focus(document.querySelector("input[id='date']")); - } - } - } - - function close_date_filter_box(event) { - if (!event.target.closest(".date_filter_box_el")) { - showDateFilterOptions = false; - window.removeEventListener("click", close_date_filter_box); - } - } - - function toggle_date_filter_box(event) { - const box = document.getElementById("date_filter_box"); - const rect = event.target.getBoundingClientRect(); - box.style.top = rect.y + "px"; - box.style.left = rect.x - 50 + "px"; - showDateFilterOptions = true; - window.addEventListener("click", close_date_filter_box); - } - - onMount(() => { - isLoading = true; - Promise.all([load_entries()]).then(() => { - isLoading = false; - }); - }); -</script> - -<Modal title="Edit entry" - bind:functions={EditEntryModal} - on:closed={() => EditEntryForm.reset()}> - <EntryForm bind:functions={EditEntryForm} - on:updated={handle_edit_entry_form_updated}/> -</Modal> - -<div id="date_filter_box" - style="margin-top:25px" - class="padding-xs z-index-overlay bg shadow-sm position-absolute date_filter_box_el border {showDateFilterOptions ? '' : 'hide'}"> - <div class="flex items-baseline margin-bottom-xxxxs"> - <label class="text-sm color-contrast-medium margin-right-xs" - for="durationSelect">Timespan:</label> - <div class="select inline-block js-select"> - <select name="durationSelect" - bind:value={currentTimespanFilter} - id="durationSelect"> - <option value={TimeEntryQueryDuration.TODAY} - selected> Today - </option> - <option value={TimeEntryQueryDuration.THIS_WEEK}>This week</option> - <option value={TimeEntryQueryDuration.THIS_MONTH}>This month</option> - <option value={TimeEntryQueryDuration.THIS_YEAR}>This year</option> - <option value={TimeEntryQueryDuration.SPECIFIC_DATE}>Spesific date</option> - <option value={TimeEntryQueryDuration.DATE_RANGE}>Date range</option> - </select> - - <svg class="icon icon--xxxs margin-left-xxs" - viewBox="0 0 8 8"> - <path d="M7.934,1.251A.5.5,0,0,0,7.5,1H.5a.5.5,0,0,0-.432.752l3.5,6a.5.5,0,0,0,.864,0l3.5-6A.5.5,0,0,0,7.934,1.251Z"/> - </svg> - </div> - </div> - - {#if currentTimespanFilter === TimeEntryQueryDuration.SPECIFIC_DATE} - <div class="flex items-baseline margin-bottom-xxxxs justify-between"> - <span class="text-sm color-contrast-medium margin-right-xs">Date:</span> - <span class="text-sm"> - <input type="date" - class="border-none padding-0 color-inherit bg-transparent" - bind:value={currentSpecificDateFilter}/> - </span> - </div> - {/if} - - {#if currentTimespanFilter === TimeEntryQueryDuration.DATE_RANGE} - <div class="flex items-baseline margin-bottom-xxxxs justify-between"> - <span class="text-sm color-contrast-medium margin-right-xs">From:</span> - <span class="text-sm"> - <input type="date" - class="border-none padding-0 color-inherit bg-transparent" - on:change={(e) => (currentDateRangeFilter.from = e.target.value)}/> - </span> - </div> - - <div class="flex items-baseline margin-bottom-xxxxs justify-between"> - <span class="text-sm color-contrast-medium margin-right-xs">To:</span> - <span class="text-sm"> - <input type="date" - class="border-none padding-0 color-inherit bg-transparent" - on:change={(e) => (currentDateRangeFilter.to = e.target.value)}/> - </span> - </div> - {/if} - - <div class="flex items-baseline justify-end"> - <Button variant="subtle" - on:click={() => load_entries_with_filter(page)} - class="text-sm" - text="Save"/> - </div> -</div> - -<Layout> - <Tile class="{isLoading ? 'c-disabled loading' : ''}"> - <nav class="s-tabs text-sm"> - <ul class="s-tabs__list"> - <li><span class="s-tabs__link s-tabs__link--current">All (21)</span></li> - <li><span class="s-tabs__link">Published (19)</span></li> - <li><span class="s-tabs__link">Draft (2)</span></li> - </ul> - </nav> - <div class="max-width-100% overflow-auto" - style="max-height: 82.5vh"> - <Table class="text-sm width-100% int-table--sticky-header"> - <THead> - <TCell type="th" - style="width: 30px;"> - <div class="custom-checkbox int-table__checkbox"> - <input class="custom-checkbox__input" - type="checkbox" - aria-label="Select all rows"/> - <div class="custom-checkbox__control" - aria-hidden="true"></div> - </div> - </TCell> - - <TCell type="th" - style="width: 100px"> - <div class="flex items-center justify-between"> - <span>Date</span> - <div class="date_filter_box_el cursor-pointer" - on:click={toggle_date_filter_box}> - <Icon name="{IconNames.funnel}"/> - </div> - </div> - </TCell> - - <TCell type="th" - style="width: 100px"> - <div class="flex items-center"> - <span>Duration</span> - </div> - </TCell> - - <TCell type="th" - style="width: 100px;"> - <div class="flex items-center"> - <span>Category</span> - </div> - </TCell> - - <TCell type="th" - style="width: 300px;"> - <div class="flex items-center"> - <span>Description</span> - </div> - </TCell> - <TCell type="th" - style="width: 50px"></TCell> - </THead> - <TBody> - {#if entries.length > 0} - {#each entries as entry} - <TRow class="text-nowrap" - data-id={entry.id}> - <TCell type="th" - thScope="row"> - <div class="custom-checkbox int-table__checkbox"> - <input class="custom-checkbox__input" - type="checkbox" - aria-label="Select this row"/> - <div class="custom-checkbox__control" - aria-hidden="true"></div> - </div> - </TCell> - <TCell> - <pre>{entry.date.toLocaleString()}</pre> - </TCell> - <TCell> - <pre class="flex justify-between"> - <div class="flex justify-between"> - <span>{entry.start.toLocaleString(undefined, {timeStyle: "short"})}</span> - <span> - </span> - <span>{entry.stop.toLocaleString(undefined, {timeStyle: "short"})}</span> - </div> - </pre> - </TCell> - <TCell> - <span data-id={entry.category.id}>{entry.category.name}</span> - </TCell> - <TCell class="text-truncate max-width-xxxxs" - title="{entry.description}"> - {entry.description ?? ""} - </TCell> - <TCell class="flex flex-row justify-end items-center"> - <Button icon="{IconNames.pencilSquare}" - variant="reset" - icon_width="1.2rem" - icon_height="1.2rem" - on:click={(e) => handle_edit_entry_button_click(e, entry.id)} - title="Edit entry"/> - <Button icon="{IconNames.trash}" - variant="reset" - icon_width="1.2rem" - icon_height="1.2rem" - on:click={(e) => handle_delete_entry_button_click(e, entry.id)} - title="Delete entry"/> - </TCell> - </TRow> - {/each} - {:else} - <TRow class="text-nowrap"> - <TCell type="th" - thScope="row" - colspan="7"> - {isLoading ? "Loading..." : "No entries"} - </TCell> - </TRow> - {/if} - </TBody> - </Table> - </div> - <div class="flex items-center justify-between"> - <p class="text-sm"> - {#if durationSummary} - <small class={isLoading ? "c-disabled loading" : ""}>{durationSummary}</small> - {:else} - <small class={isLoading ? "c-disabled loading" : ""}>No entries</small> - {/if} - </p> - - <nav class="grid padding-y-sm {isLoading ? 'c-disabled loading' : ''}"> - <TablePaginator {page} - on:value_change={(e) => load_entries_with_filter(e.detail.newValue)} - {pageCount}/> - </nav> - </div> - </Tile> -</Layout> diff --git a/apps/projects-web/src/app/pages/home.svelte b/apps/projects-web/src/app/pages/home.svelte deleted file mode 100644 index c3e7af4..0000000 --- a/apps/projects-web/src/app/pages/home.svelte +++ /dev/null @@ -1,167 +0,0 @@ -<script lang="ts"> - import {IconNames} from "$shared/lib/configuration"; - import {TimeEntryDto} from "$shared/lib/models/TimeEntryDto"; - import {Temporal} from "@js-temporal/polyfill"; - import {onMount} from "svelte"; - import Tile from "$shared/components/tile.svelte"; - import Button from "$shared/components/button.svelte"; - import Stopwatch from "$shared/components/stopwatch.svelte"; - import {Table, THead, TBody, TCell, TRow} from "$shared/components/table"; - import Layout from "./_layout.svelte"; - 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; - let EditEntryForm: any; - let timeEntries = [] as Array<TimeEntryDto>; - let timeLoggedTodayString = "0h0m"; - - function set_current_time() { - currentTime = Temporal.Now.plainTimeISO().toLocaleString(undefined, { - timeStyle: "short", - }); - } - - async function on_edit_entry_button_click(event, entryId: string) { - const response = 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); - } - } - - 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) { - EditEntryForm.set_description(event.detail.description); - } - } - - onMount(async () => { - set_current_time(); - setInterval(() => { - set_current_time(); - }, 1e4); - await load_todays_entries(); - entries.subscribe((val) => { - const newEntries = []; - let loggedSecondsToday = 0; - for (const entry of val) { - const date_time = unwrap_date_time_from_entry(entry); - newEntries.push({ - id: entry.id, - start: date_time.start_time, - stop: date_time.stop_time, - category: entry.category, - }); - loggedSecondsToday += (date_time.duration.hours * 60 * 60) + (date_time.duration.minutes * 60); - } - timeLoggedTodayString = seconds_to_hour_minute_string(loggedSecondsToday); - timeEntries = newEntries; - }); - }); -</script> - -<Layout> - <div class="grid gap-md margin-top-xs flex-row@md items-start flex-column-reverse"> - <Tile class="col"> - <h3 class="text-md padding-bottom-xxxs">New entry</h3> - <EntryFrom bind:functions={EditEntryForm}/> - </Tile> - <div class="col grid gap-sm"> - <Tile class="col-6@md col-12"> - <p class="text-xxl">{timeLoggedTodayString}</p> - <p class="text-xs margin-bottom-xxs">Logged time today</p> - <pre class="text-xxl">{currentTime}</pre> - <p class="text-xs">Current time</p> - </Tile> - <Tile class="col-6@md col-12"> - <Stopwatch on:create={on_create_from_stopwatch}> - <h3 slot="header" - class="text-md">Stopwatch</h3> - </Stopwatch> - </Tile> - <Tile class="col-12"> - <h3 class="text-md padding-bottom-xxxs">Today's entries</h3> - <div class="max-width-100% overflow-auto"> - <Table class="width-100% text-sm"> - <THead> - <TCell type="th" - class="text-left"> - <span>Category</span> - </TCell> - <TCell type="th" - class="text-left"> - <span>Timespan</span> - </TCell> - <TCell type="th" - class="text-right"> - <Button icon="{IconNames.refresh}" - variant="reset" - icon_width="1.2rem" - icon_height="1.2rem" - title="Refresh today's entries" - on:click={load_todays_entries}/> - </TCell> - </THead> - <TBody> - {#if timeEntries.length > 0} - {#each timeEntries as entry} - <TRow class="text-nowrap text-left" - data-id={entry.id}> - <TCell> - <span data-id={entry.category?.id}> - {entry.category?.name} - </span> - </TCell> - <TCell> - {entry.start.toLocaleString(undefined, {timeStyle: "short"})} - <span>-</span> - {entry.stop.toLocaleString(undefined, {timeStyle: "short"})} - </TCell> - <TCell class="flex flex-row justify-end items-center"> - <Button icon="{IconNames.pencilSquare}" - variant="reset" - icon_width="1.2rem" - icon_height="1.2rem" - on:click={(e) => on_edit_entry_button_click(e, entry.id)} - title="Edit entry"/> - <Button icon="{IconNames.trash}" - variant="reset" - icon_width="1.2rem" - icon_height="1.2rem" - on:click={(e) => on_delete_entry_button_click(e, entry.id)} - title="Delete entry"/> - </TCell> - </TRow> - {/each} - {:else} - <TRow class="text-nowrap"> - <TCell type="th" - thScope="row" - colspan="7"> - {isLoading ? "Loading..." : "No entries today"} - </TCell> - </TRow> - {/if} - </TBody> - </Table> - </div> - </Tile> - </div> - </div> -</Layout> diff --git a/apps/projects-web/src/app/pages/not-found.svelte b/apps/projects-web/src/app/pages/not-found.svelte deleted file mode 100644 index 46d0d1d..0000000 --- a/apps/projects-web/src/app/pages/not-found.svelte +++ /dev/null @@ -1,24 +0,0 @@ -<script> - import {link} from "svelte-spa-router"; -</script> - -<style> - header { - font-size: 12rem; - } - - main { - position: absolute; - left: 50%; - top: 50%; - transform: translate(-50%, -50%); - text-align: center; - } -</style> - -<main> - <header>404</header> - <p>Page not found!</p> - <a use:link - href="/">Go to front</a> -</main> diff --git a/apps/projects-web/src/app/pages/settings.svelte b/apps/projects-web/src/app/pages/settings.svelte deleted file mode 100644 index ca9fd47..0000000 --- a/apps/projects-web/src/app/pages/settings.svelte +++ /dev/null @@ -1,12 +0,0 @@ -<script> - import Layout from "./_layout.svelte"; - import CategoriesTile from "$app/pages/views/settings-categories-tile.svelte"; - import LabelsTile from "$app/pages/views/settings-labels-tile.svelte"; -</script> - -<Layout> - <section class="grid gap-md"> - <CategoriesTile/> - <LabelsTile/> - </section> -</Layout> diff --git a/apps/projects-web/src/app/pages/ui-workbench.svelte b/apps/projects-web/src/app/pages/ui-workbench.svelte deleted file mode 100644 index 5e92c9d..0000000 --- a/apps/projects-web/src/app/pages/ui-workbench.svelte +++ /dev/null @@ -1,48 +0,0 @@ -<script> - import Dropdown from "$shared/components/dropdown.svelte"; - import {generate_random_hex_color} from "$shared/lib/colors"; - import {uuid_v4} from "$shared/lib/helpers"; - - let entries = []; - - let dropdown; - - for (let i = 1; i < 20; i++) { - entries.push({ - id: uuid_v4(), - name: "Option " + i, - selected: false, - color: generate_random_hex_color(true) - }); - } - - function on_create({detail}) { - const copy = entries; - const entry = {id: uuid_v4(), name: detail.name}; - copy.push(entry); - entries = copy; - console.log("Created", entry); - dropdown.select_entry(entry.id); - } - - function on_select({detail}) { - console.log(detail); - } -</script> - -<main class="grid gap-y-lg padding-md"> - <div class="row"> - <label for="dropdown">Choose an entry</label> - <Dropdown id="dropdown" - name="dropdown" - placeholder="Search or create" - maxlength="50" - creatable="true" - multiple="false" - {entries} - bind:this={dropdown} - on:create={on_create} - on:select={on_select} - /> - </div> -</main> diff --git a/apps/projects-web/src/app/pages/views/category-form/index.svelte b/apps/projects-web/src/app/pages/views/category-form/index.svelte deleted file mode 100644 index e8c0f94..0000000 --- a/apps/projects-web/src/app/pages/views/category-form/index.svelte +++ /dev/null @@ -1,144 +0,0 @@ -<script lang="ts"> - import Alert from "$shared/components/alert.svelte"; - import Dropdown from "$shared/components/dropdown.svelte"; - import labels, {reload_labels, create_label_async} from "$app/lib/stores/labels"; - import {generate_random_hex_color} from "$shared/lib/colors"; - import {get} from "svelte/store"; - - let LabelsDropdown; - - const dough = { - error: "", - fields: { - name: { - value: "", - error: "", - validate() { - return false; - } - }, - color: { - value: "", - error: "", - validate() { - return true; - } - }, - labels: { - loading: false, - value: [], - error: "", - validate() { - return true; - }, - async create({name}) { - dough.fields.labels.loading = true; - const response = await create_label_async({ - name: name, - color: generate_random_hex_color(), - }); - dough.fields.labels.loading = false; - if (response.ok) { - // Small pause to allow loading state to update everywhere. - setTimeout(() => LabelsDropdown.select_entry(response.data.id), 50); - } - } - }, - archived: { - value: false, - error: "", - validate() { - return true; - } - } - }, - bake() { - // labels.filter((c) => Object.hasOwn(c, "selected") && c.selected === true); - return { - labels: dough.fields.labels.value, - name: dough.fields.name.value, - color: dough.fields.color.value, - }; - }, - submit(event) { - const bread = dough.bake(); - console.log(bread); - console.log("Submitted"); - } - }; - - const functions = { - set(values) { - functions.set_archived(values.archived); - functions.set_labels(values.labels); - functions.set_color(values.color); - functions.set_name(values.name); - }, - is_valid() { - let isValid = true; - if (!dough.fields.labels.validate()) isValid = false; - if (!dough.fields.color.validate()) isValid = false; - if (!dough.fields.name.validate()) isValid = false; - if (!dough.fields.archived.validate()) isValid = false; - return isValid; - }, - set_archived(value) { - dough.fields.archived.value = value; - }, - set_labels(value) { - dough.fields.labels.value = value; - }, - set_color(value) { - dough.fields.color.value = value; - }, - set_name(value) { - dough.fields.name.value = value; - }, - }; -</script> - -<form on:submit|preventDefault={dough.submit}> - <div class="margin-y-sm"> - <Alert visible={dough.error !== ""} - message={dough.error} - type="error"/> - </div> - <div class="grid gap-x-xs margin-bottom-sm"> - <div class="col-10"> - <label for="name" - class="form-label margin-bottom-xxs">Name</label> - <input type="text" - class="form-control width-100%" - id="name" - bind:value={dough.fields.name.value}/> - {#if dough.fields.name.error} - <small class="color-error">{dough.fields.name.error}</small> - {/if} - </div> - <div class="col-2"> - <label for="color" - class="form-label margin-bottom-xxs">Color</label> - <input type="color" - class="form-control width-100%" - id="color" - style="height: 41px" - bind:value={dough.fields.color.value}/> - {#if dough.fields.color.error} - <small class="color-error">{dough.fields.color.error}</small> - {/if} - </div> - </div> - <div class="margin-bottom-sm"> - <label for="labels" - class="form-label margin-bottom-xxs">Default labels</label> - <Dropdown id="labels" - createable={true} - placeholder="Search or create" - entries={$labels} - multiple={true} - on_create_async={(name) => dough.fields.labels.create({name})}/> - {#if dough.fields.labels.error} - <small class="color-error">{dough.fields.labels.error}</small> - {/if} - </div> -</form> diff --git a/apps/projects-web/src/app/pages/views/data-table-paginator.svelte b/apps/projects-web/src/app/pages/views/data-table-paginator.svelte deleted file mode 100644 index 7696ca2..0000000 --- a/apps/projects-web/src/app/pages/views/data-table-paginator.svelte +++ /dev/null @@ -1,107 +0,0 @@ -<script> - import {createEventDispatcher, onMount} from "svelte"; - import {restrict_input_to_numbers} from "$shared/lib/helpers"; - - const dispatch = createEventDispatcher(); - export let page = 1; - export let pageCount = 1; - let prevCount = page; - let canIncrement = false; - let canDecrement = false; - $: canIncrement = page < pageCount; - $: canDecrement = page > 1; - - onMount(() => { - restrict_input_to_numbers(document.querySelector("#curr-page")); - }); - - function increment() { - if (canIncrement) { - page++; - } - } - - function decrement() { - if (canDecrement) { - page--; - } - } - - $: if (page) { - handle_change(); - } - - function handle_change() { - if (page === prevCount) { - return; - } - prevCount = page; - if (page > pageCount) { - page = pageCount; - } - dispatch("value_change", { - newValue: page, - }); - } -</script> - -<nav class="pagination" - aria-label="Pagination"> - <ul - class="pagination__list flex flex-wrap gap-xxxs justify-center justify-end@md" - > - <li> - <button - on:click={decrement} - class="reset pagination__item {canDecrement ? '' : 'c-disabled'}" - > - <svg class="icon icon--xs flip-x" - viewBox="0 0 16 16" - ><title>Go to previous page</title> - <polyline - points="6 2 12 8 6 14" - fill="none" - stroke="currentColor" - stroke-linecap="round" - stroke-linejoin="round" - stroke-width="2" - /> - </svg> - </button> - </li> - - <li> - <span class="pagination__jumper flex items-center"> - <input - aria-label="Page number" - class="form-control" - id="curr-page" - type="text" - on:change={handle_change} - value={page} - /> - <em>of {pageCount}</em> - </span> - </li> - - <li> - <button - on:click={increment} - class="reset pagination__item {canIncrement ? '' : 'c-disabled'}" - > - <svg class="icon icon--xs" - viewBox="0 0 16 16" - ><title>Go to next page</title> - <polyline - points="6 2 12 8 6 14" - fill="none" - stroke="currentColor" - stroke-linecap="round" - stroke-linejoin="round" - stroke-width="2" - /> - </svg> - </button> - </li> - </ul> -</nav> diff --git a/apps/projects-web/src/app/pages/views/entry-form/index.svelte b/apps/projects-web/src/app/pages/views/entry-form/index.svelte deleted file mode 100644 index cb974ed..0000000 --- a/apps/projects-web/src/app/pages/views/entry-form/index.svelte +++ /dev/null @@ -1,196 +0,0 @@ -<script lang="ts"> - import {TimeEntryDto} from "$shared/lib/models/TimeEntryDto"; - import {Temporal} from "@js-temporal/polyfill"; - import {createEventDispatcher, onMount, onDestroy} from "svelte"; - import DateTimePart from "./sections/date-time.svelte"; - import LabelsPart from "./sections/labels.svelte"; - import CategoryPart from "./sections/category.svelte"; - import Button from "$shared/components/button.svelte"; - import {Textarea} from "$shared/components/form"; - import Alert from "$shared/components/alert.svelte"; - import {is_guid} from "$shared/lib/helpers"; - import {create_entry_async, edit_entry_async} from "$app/lib/stores/entries"; - - const dispatch = createEventDispatcher(); - - let formError = ""; - let formIsLoading = false; - let description = ""; - let descriptionError = ""; - let dateTimePart; - let labelsPart; - let categoryPart; - let entryId; - - onMount(() => { - formIsLoading = true; - - Promise.all([categoryPart.load_categories(), labelsPart.load_labels()]).then(() => { - formIsLoading = false; - }); - - window.addEventListener("keydown", handle_window_keydown); - }); - - onDestroy(() => { - window.removeEventListener("keydown", handle_window_keydown); - }); - - function handle_window_keydown(event) { - if (event.ctrlKey && event.code === "Enter") { - submit_form(); - } - } - - function validate_form() { - return dateTimePart.is_valid() && categoryPart.is_valid() && description_is_valid(); - } - - function description_is_valid() { - if (!description) { - descriptionError = "Description is required"; - } else { - descriptionError = ""; - } - - return description; - } - - function get_payload() { - const response = {} as TimeEntryDto; - const values = get_values(); - if (!is_guid(values.id)) { - delete values.id; - } else { - response.id = values.id; - } - - const currentTimeZone = Temporal.Now.zonedDateTimeISO().offset; - response.start = values.date + "T" + values.fromTimeValue + currentTimeZone.toString(); - response.stop = values.date + "T" + values.toTimeValue + currentTimeZone.toString(); - - response.category = { - id: values.category.id, - }; - - const selectedLabels = values.labels; - if (selectedLabels?.length > 0 ?? false) { - response.labels = selectedLabels; - } - - const descriptionContent = description?.trim(); - if (descriptionContent?.length > 0 ?? false) { - response.description = descriptionContent; - } - - return response; - } - - async function submit_form() { - formError = ""; - if (validate_form()) { - const payload = get_payload() as TimeEntryDto; - formIsLoading = true; - if (is_guid(payload.id)) { - const response = await edit_entry_async(payload); - if (response.ok) { - functions.reset(); - dispatch("updated", response.data); - } else { - formError = "An error occured while updating the entry, try again soon"; - formIsLoading = false; - } - } else { - const response = await create_entry_async(payload); - if (response.ok) { - functions.reset(); - dispatch("created"); - } else { - formError = "An error occured while creating the entry, try again soon"; - formIsLoading = false; - } - } - } - } - - function get_values() { - return { - id: entryId, - toTimeValue: dateTimePart.get_to_time_value(), - fromTimeValue: dateTimePart.get_from_time_value(), - date: dateTimePart.get_date(), - category: categoryPart.get_selected(), - labels: labelsPart.get_selected(), - description: description, - }; - } - - export const functions = { - set_values(values) { - entryId = values.id; - dateTimePart.set_values(values); - labelsPart.select_labels(values?.labels.map((c) => c.id) ?? []); - categoryPart.select_category(values?.category?.id); - description = values.description; - }, - set_time(value: {to: Temporal.PlainTime, from: Temporal.PlainTime}) { - dateTimePart.set_times(value); - }, - set_description(value: string) { - if (description) description = description + "\n\n" + value; - else description = value; - }, - reset() { - formIsLoading = false; - entryId = ""; - labelsPart.reset(); - categoryPart.reset(); - dateTimePart.reset(true); - description = ""; - formError = ""; - }, - }; -</script> - -<form on:submit|preventDefault={submit_form} - on:reset={() => functions.reset()}> - <div class="margin-y-sm"> - <Alert visible={formError !== ""} - message={formError} - type="error"/> - </div> - - <div class="margin-bottom-sm"> - <DateTimePart bind:functions={dateTimePart}/> - </div> - - <div class="margin-bottom-sm"> - <CategoryPart bind:functions={categoryPart}/> - </div> - - <div class="margin-bottom-sm"> - <LabelsPart bind:functions={labelsPart}/> - </div> - - <div class="margin-bottom-sm"> - <Textarea class="width-100%" - id="description" - label="Description" - errorText="{descriptionError}" - bind:value={description}></Textarea> - </div> - - <div class="flex flex-row justify-end gap-x-xs"> - {#if entryId} - <Button text="Reset" - on:click={() => functions.reset()} - variant="subtle" - /> - {/if} - <Button loading={formIsLoading} - type="submit" - variant="primary" - text={entryId ? "Save" : "Create"} - /> - </div> -</form> diff --git a/apps/projects-web/src/app/pages/views/entry-form/sections/category.svelte b/apps/projects-web/src/app/pages/views/entry-form/sections/category.svelte deleted file mode 100644 index f98c045..0000000 --- a/apps/projects-web/src/app/pages/views/entry-form/sections/category.svelte +++ /dev/null @@ -1,75 +0,0 @@ -<script> - import {generate_random_hex_color} from "$shared/lib/colors"; - import Dropdown from "$shared/components/dropdown.svelte"; - import {is_guid, move_focus} from "$shared/lib/helpers"; - import categories, {reload_categories, create_category_async} from "$app/lib/stores/categories"; - - let categoriesError = ""; - let loading = false; - - let DropdownExports; - - function reset() { - DropdownExports.reset(); - categoriesError = ""; - console.log("Reset category-part"); - } - - async function on_create({name}) { - loading = true; - const response = await create_category_async({ - name: name, - color: generate_random_hex_color(), - }); - loading = false; - if (response.ok) { - // Small pause to allow loading state to update everywhere. - setTimeout(() => select_category(response.data.id), 50); - } - } - - function get_selected() { - return $categories.find((c) => c.selected === true); - } - - function select_category(id) { - DropdownExports.select(id); - } - - function is_valid() { - let isValid = true; - const category = get_selected(); - if (!is_guid(category?.id)) { - categoriesError = "Category is required"; - isValid = false; - move_focus(document.getElementById("category-dropdown")); - } else { - categoriesError = ""; - } - return isValid; - } - - export const functions = { - get_selected, - reset, - is_valid, - select_category, - load_categories: reload_categories, - }; -</script> - -<Dropdown - entries={$categories} - label="Category" - maxlength="50" - createable={true} - placeholder="Search or create" - id="category-dropdown" - loading={loading} - name="category-dropdown" - on_create_async={on_create} - noResultsText="No categories available (Create a new one by searching for it and pressing enter)" - errorText="{categoriesError}" - bind:this={DropdownExports} -/> - diff --git a/apps/projects-web/src/app/pages/views/entry-form/sections/date-time.svelte b/apps/projects-web/src/app/pages/views/entry-form/sections/date-time.svelte deleted file mode 100644 index c91e014..0000000 --- a/apps/projects-web/src/app/pages/views/entry-form/sections/date-time.svelte +++ /dev/null @@ -1,165 +0,0 @@ -<script lang="ts"> - import {Temporal} from "@js-temporal/polyfill"; - - // TIME - let fromTimeValue = ""; - let fromTimeError = ""; - let toTimeValue = ""; - let toTimeError = ""; - - function handle_from_time_changed(e) { - fromTimeValue = e.target.value; - if (fromTimeValue) { - fromTimeError = ""; - } - } - - function handle_to_time_changed(e) { - toTimeValue = e.target.value; - if (toTimeValue) { - toTimeError = ""; - } - } - - // DATE - let date = Temporal.Now.plainDateTimeISO().toString().substring(0, 10); - let dateError = ""; - - function is_valid() { - let isValid = true; - let focusIsSet = false; - if (!date) { - dateError = "Date is required"; - isValid = false; - if (!focusIsSet) { - document.getElementById("date")?.focus(); - focusIsSet = true; - } - } else { - dateError = ""; - } - - if (!fromTimeValue) { - fromTimeError = "From is required"; - isValid = false; - if (!focusIsSet) { - document.getElementById("from")?.focus(); - focusIsSet = true; - } - } else if (toTimeValue && fromTimeValue > toTimeValue) { - fromTimeError = "From can not be after To"; - isValid = false; - if (!focusIsSet) { - document.getElementById("from")?.focus(); - focusIsSet = true; - } - } else if (fromTimeValue === toTimeValue) { - fromTimeError = "From and To can not be equal"; - isValid = false; - if (!focusIsSet) { - document.getElementById("from")?.focus(); - focusIsSet = true; - } - } else { - fromTimeError = ""; - } - - if (!toTimeValue) { - toTimeError = "To is required"; - isValid = false; - if (!focusIsSet) { - document.getElementById("to")?.focus(); - focusIsSet = true; - } - } else if (fromTimeValue && toTimeValue < fromTimeValue) { - toTimeError = "To can not be before From"; - isValid = false; - if (!focusIsSet) { - document.getElementById("to")?.focus(); - focusIsSet = true; - } - } else { - toTimeError = ""; - } - - return isValid; - } - - export const functions = { - get_from_time_value() { - return fromTimeValue; - }, - get_to_time_value() { - return toTimeValue; - }, - get_date() { - return date; - }, - is_valid, - reset(focusDate = false) { - fromTimeValue = ""; - toTimeValue = ""; - if (focusDate) { - document.getElementById("date")?.focus(); - } - }, - set_times(value) { - console.log(value); - fromTimeValue = value.from.toString().substring(0, 5); - toTimeValue = value.to.toString().substring(0, 5); - }, - set_date(new_date: Temporal.PlainDate) { - date = new_date.toString(); - }, - set_values(values) { - const currentTimeZone = Temporal.Now.timeZone().id; - const startDate = Temporal.Instant.from(values.start); - const stopDate = Temporal.Instant.from(values.stop); - fromTimeValue = startDate.toZonedDateTimeISO(currentTimeZone).toPlainTime().toString().substring(0, 5); - toTimeValue = stopDate.toZonedDateTimeISO(currentTimeZone).toPlainTime().toString().substring(0, 5); - date = startDate.toZonedDateTimeISO(currentTimeZone).toPlainDate().toString(); - } - }; -</script> - -<div class="grid gap-xs"> - <div class="col-4"> - <label for="date" - class="form-label margin-bottom-xxs">Date</label> - <input type="date" - id="date" - class="form-control width-100%" - bind:value={date}> - {#if dateError} - <small class="color-error">{dateError}</small> - {/if} - </div> - <div class="col-4"> - <label for="from" - class="form-label margin-bottom-xxs">From</label> - <input id="from" - class="form-control width-100%" - pattern="[0-9][0-9]:[0-9][0-9]" - type="time" - bind:value={fromTimeValue} - on:input={handle_from_time_changed} - /> - {#if fromTimeError} - <small class="color-error">{fromTimeError}</small> - {/if} - </div> - <div class="col-4"> - <label for="to" - class="form-label margin-bottom-xxs">To</label> - <input id="to" - class="form-control width-100%" - pattern="[0-9][0-9]:[0-9][0-9]" - type="time" - bind:value={toTimeValue} - on:input={handle_to_time_changed} - /> - {#if toTimeError} - <small class="color-error">{toTimeError}</small> - {/if} - </div> -</div> diff --git a/apps/projects-web/src/app/pages/views/entry-form/sections/labels.svelte b/apps/projects-web/src/app/pages/views/entry-form/sections/labels.svelte deleted file mode 100644 index 06c703d..0000000 --- a/apps/projects-web/src/app/pages/views/entry-form/sections/labels.svelte +++ /dev/null @@ -1,65 +0,0 @@ -<script> - import {generate_random_hex_color} from "$shared/lib/colors"; - import labels, {reload_labels, create_label_async} from "$app/lib/stores/labels"; - import Dropdown from "$shared/components/dropdown.svelte"; - - let labelsError = ""; - let loading = false; - let DropdownExports; - - function reset() { - DropdownExports.reset(); - console.log("Reset labels-part"); - } - - function get_selected() { - return $labels.filter((c) => Object.hasOwn(c, "selected") && c.selected === true); - } - - function select_label(id) { - DropdownExports.select(id); - } - - function select_labels(ids) { - for (const id of ids) { - DropdownExports.select(id); - } - } - - async function on_create({name}) { - loading = true; - const response = await create_label_async({ - name: name, - color: generate_random_hex_color(), - }); - loading = false; - if (response.ok) { - // Small pause to allow loading state to update everywhere. - setTimeout(() => select_label(response.data.id), 50); - } - } - - export const functions = { - get_selected, - reset, - load_labels: reload_labels, - select_labels, - select_label, - }; -</script> - -<Dropdown - entries={$labels} - label="Labels" - maxlength="50" - createable={true} - placeholder="Search or create" - multiple="{true}" - id="labels-search" - name="labels-search" - on_create_async={on_create} - noResultsText="No labels available (Create a new one by searching for it and pressing enter)" - errorText="{labelsError}" - bind:this={DropdownExports} - {loading} -/> diff --git a/apps/projects-web/src/app/pages/views/profile-modal.svelte b/apps/projects-web/src/app/pages/views/profile-modal.svelte deleted file mode 100644 index 839b59d..0000000 --- a/apps/projects-web/src/app/pages/views/profile-modal.svelte +++ /dev/null @@ -1,156 +0,0 @@ -<script> - import {update_profile} from "$shared/lib/api/user"; - import Modal from "$shared/components/modal.svelte"; - import Alert from "$shared/components/alert.svelte"; - import Button from "$shared/components/button.svelte"; - import {is_email} from "$shared/lib/helpers"; - import {api_base} from "$shared/lib/configuration"; - import {delete_user} from "$app/lib/services/user-service"; - import {get_session_data} from "$shared/lib/session"; - - const archiveLink = api_base("_/api/account/archive"); - - let modal; - let understands = false; - - let formIsLoading = false; - let formError; - - let username = get_session_data()?.profile.username; - let usernameFieldMessage; - let usernameFieldMessageClass = "color-error"; - - let password; - let passwordFieldMessage; - let passwordFieldMessageClass = "color-error"; - - async function submit_form(e) { - e.preventDefault(); - if (!username && !password) { - console.error("Not submitting becuase both values is empty"); - return; - } - - usernameFieldMessage = ""; - passwordFieldMessage = ""; - - if (username && !is_email(username)) { - usernameFieldMessage = "Username has to be a valid email"; - return; - } - - if (password && password?.length < 6) { - passwordFieldMessage = "The new password must contain at least 6 characters"; - return; - } - - formIsLoading = true; - - const response = await update_profile({ - username, - password, - }); - - formIsLoading = false; - - if (response.ok) { - if (password) { - passwordFieldMessage = "Successfully updated"; - passwordFieldMessageClass = "color-success"; - password = ""; - } - if (username) { - usernameFieldMessage = "Successfully updated"; - usernameFieldMessageClass = "color-success"; - password = ""; - } - } else { - formError = response.data.title ?? "An unknown error occured"; - } - } - - async function handle_delete_account_button_click() { - if (understands && confirm("Are you absolutely sure that you want to delete your account?")) { - await delete_user(); - } - } - - export const functions = { - open() { - modal.open(); - }, - close() { - // modal.close(); - }, - }; -</script> - -<Modal title="Profile" - bind:functions={modal}> - <section class="margin-bottom-md"> - <p class="text-md margin-bottom-sm">Update your information</p> - <form on:submit={submit_form} - autocomplete="new-password"> - {#if formError} - <small class="color-danger">{formError}</small> - {/if} - <div class="margin-bottom-sm"> - <label for="email" - class="form-label margin-bottom-xxs">New username</label> - <input type="email" - class="form-control width-100%" - id="email" - placeholder={username} - bind:value={username}/> - {#if usernameFieldMessage} - <small class={usernameFieldMessageClass}>{usernameFieldMessage}</small> - {/if} - </div> - <div class="margin-bottom-sm"> - <label for="password" - class="form-label margin-bottom-xxs">New password</label> - <input type="password" - class="form-control width-100%" - id="password" - bind:value={password}/> - {#if passwordFieldMessage} - <small class={passwordFieldMessageClass}>{passwordFieldMessage}</small> - {/if} - </div> - <div class="flex justify-end"> - <Button text="Save" - on:click={submit_form} - variant="primary" - loading={formIsLoading}/> - </div> - </form> - </section> - <section class="margin-bottom-md"> - <p class="text-md margin-bottom-sm">Download your data</p> - <a class="btn btn--subtle" - href={archiveLink} - download>Click here to download your data</a> - </section> - <section> - <p class="text-md margin-bottom-sm">Delete account</p> - <div class="margin-bottom-sm"> - <Alert - message="Deleting your account and data means that all of your data (entries, categories, etc.) will be unrecoverable forever.<br>You should probably download your data before continuing." - type="info" - /> - </div> - <div class="form-check margin-bottom-sm"> - <input type="checkbox" - class="checkbox" - id="the-consequences" - bind:checked={understands}/> - <label for="the-consequences">I understand the consequences of deleting my account and data.</label> - </div> - <div class="flex justify-end"> - <Button text="Delete everything" - variant="accent" - disabled={!understands} - on:click={handle_delete_account_button_click}/> - </div> - </section> -</Modal> diff --git a/apps/projects-web/src/app/pages/views/settings-categories-tile.svelte b/apps/projects-web/src/app/pages/views/settings-categories-tile.svelte deleted file mode 100644 index 890609a..0000000 --- a/apps/projects-web/src/app/pages/views/settings-categories-tile.svelte +++ /dev/null @@ -1,127 +0,0 @@ -<script> - import {IconNames} from "$shared/lib/configuration"; - import {onMount} from "svelte"; - import { - delete_time_category, - get_time_categories, - } from "$shared/lib/api/time-entry"; - import Button from "$shared/components/button.svelte"; - import Tile from "$shared/components/tile.svelte"; - import {Table, THead, TBody, TCell, TRow} from "$shared/components/table"; - - let is_loading = true; - let categories = []; - - $: active_categories = categories.filter(c => !c.archived); - $: archived_categories = categories.filter(c => c.archived); - - async function load_categories() { - is_loading = true; - const response = await get_time_categories(); - if (response.status === 200) { - categories = response.data; - } else if (response.status === 204) { - categories = []; - console.log("Empty response when getting time categories"); - } else { - categories = []; - console.error("Error when getting time categories"); - } - is_loading = false; - } - - async function handle_edit_category_click(event) { - } - - async function handle_delete_category_click(event) { - const row = event.target.closest("tr"); - if ( - row && - row.dataset.id && - confirm( - "Are you sure you want to delete this category?\nThis will delete all relating entries!" - ) - ) { - const response = await delete_time_category(row.dataset.id); - if (response.ok) { - // svelte errors if we remove the row. - row.classList.add("d-none"); - } - } - } - - onMount(() => { - load_categories(); - }); -</script> - -<Tile class="col-6@md col-12 {is_loading ? 'c-disabled loading' : ''}"> - <h2 class="margin-bottom-xxs">Categories</h2> - {#if active_categories.length > 0 && archived_categories.length > 0} - <nav class="s-tabs text-sm"> - <ul class="s-tabs__list"> - <li><a class="s-tabs__link s-tabs__link--current" - href="#0">Active ({active_categories.length})</a></li> - <li><a class="s-tabs__link" - href="#0">Archived ({archived_categories.length})</a></li> - </ul> - </nav> - {/if} - <div class="max-width-100% overflow-auto"> - <Table class="text-sm width-100%"> - <THead class="text-left"> - <TCell type="th" - thScope="col"> - Name - </TCell> - <TCell type="th" - thScope="col"> - Color - </TCell> - <TCell type="th" - thScope="col" - style="width:50px"></TCell> - </THead> - <TBody class="text-left"> - {#if categories.length > 0} - {#each categories as category} - <TRow class="text-nowrap" - data-id={category.id}> - <TCell> - {category.name} - </TCell> - <TCell> - <span style="border-left: 3px solid {category.color}; background-color:{category.color}25;"> - {category.color} - </span> - </TCell> - <TCell> - <Button icon="{IconNames.pencilSquare}" - variant="reset" - icon_width="1.2rem" - class="hide" - icon_height="1.2rem" - on:click={handle_edit_category_click} - title="Edit entry"/> - <Button icon="{IconNames.trash}" - variant="reset" - icon_width="1.2rem" - icon_height="1.2rem" - on:click={handle_delete_category_click} - title="Delete entry"/> - - </TCell> - </TRow> - {/each} - {:else} - <TRow> - <TCell type="th" - thScope="3"> - No categories - </TCell> - </TRow> - {/if} - </TBody> - </Table> - </div> -</Tile> diff --git a/apps/projects-web/src/app/pages/views/settings-labels-tile.svelte b/apps/projects-web/src/app/pages/views/settings-labels-tile.svelte deleted file mode 100644 index f59e233..0000000 --- a/apps/projects-web/src/app/pages/views/settings-labels-tile.svelte +++ /dev/null @@ -1,112 +0,0 @@ -<script> - import {IconNames} from "$shared/lib/configuration"; - import {onMount} from "svelte"; - import labels, {reload_labels, delete_label_async} from "$app/lib/stores/labels"; - import Button from "$shared/components/button.svelte"; - import Tile from "$shared/components/tile.svelte"; - import {Table, THead, TBody, TCell, TRow} from "$shared/components/table"; - - let is_loading = true; - - $: active_labels = $labels.filter(c => !c.archived); - $: archived_labels = $labels.filter(c => c.archived); - - async function load_labels() { - is_loading = true; - await reload_labels(); - is_loading = false; - } - - async function handle_edit_label_click(event) { - } - - async function handle_delete_label_click(event) { - const row = event.target.closest("tr"); - if ( - row && - row.dataset.id && - confirm( - "Are you sure you want to delete this label?\nIt will be removed from all related entries!" - ) - ) { - await delete_label_async({id: row.dataset.id}); - row.classList.add("d-none"); - } - } - - onMount(() => { - load_labels(); - }); -</script> - -<Tile class="col-6@md col-12 {is_loading ? 'c-disabled loading' : ''}"> - <h2 class="margin-bottom-xxs">Labels</h2> - {#if active_labels.length > 0 && archived_labels.length > 0} - <nav class="s-tabs text-sm"> - <ul class="s-tabs__list"> - <li><a class="s-tabs__link s-tabs__link--current" - href="#0">Active ({active_labels.length})</a></li> - <li><a class="s-tabs__link" - href="#0">Archived ({archived_labels.length})</a></li> - </ul> - </nav> - {/if} - <div class="max-width-100% overflow-auto"> - <Table class="text-sm width-100%"> - <THead class="text-left"> - <TCell type="th" - thScope="row"> - Name - </TCell> - <TCell type="th" - thScope="row"> - Color - </TCell> - <TCell type="th" - thScope="row" - style="width: 50px;"> - </TCell> - </THead> - <TBody class="text-left"> - {#if $labels.length > 0} - {#each $labels as label} - <TRow class="text-nowrap" - dataId={label.id}> - <TCell> - {label.name} - </TCell> - <TCell> - <span style="border-left: 3px solid {label.color}; background-color:{label.color}25;"> - {label.color} - </span> - </TCell> - <TCell> - <Button icon="{IconNames.pencilSquare}" - variant="reset" - icon_width="1.2rem" - class="hide" - icon_height="1.2rem" - on:click={handle_edit_label_click} - title="Edit entry"/> - <Button icon="{IconNames.trash}" - variant="reset" - icon_width="1.2rem" - icon_height="1.2rem" - on:click={handle_delete_label_click} - title="Delete entry"/> - </TCell> - </TRow> - {/each} - {:else} - <TRow> - <TCell type="th" - thScope="row" - colspan="3"> - No labels - </TCell> - </TRow> - {/if} - </TBody> - </Table> - </div> -</Tile> diff --git a/apps/projects-web/src/index.html b/apps/projects-web/src/index.html deleted file mode 100644 index 985b62b..0000000 --- a/apps/projects-web/src/index.html +++ /dev/null @@ -1,63 +0,0 @@ -<!doctype html> -<html lang="en"> - -<head> - <meta charset="UTF-8"> - <meta name="viewport" - content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> - <link rel="apple-touch-icon" - sizes="180x180" - href="./_assets/pwa/apple-touch-icon.png"> - <link rel="icon" - type="image/png" - sizes="32x32" - href="./_assets/pwa/favicon-32x32.png"> - <link rel="icon" - type="image/png" - sizes="16x16" - href="./_assets/pwa/favicon-16x16.png"> - <link rel="manifest" - href="./_assets/pwa/manifest.json"> - <link rel="mask-icon" - href="./_assets/pwa/safari-pinned-tab.svg" - color="#5bbad5"> - <meta name="msapplication-TileColor" - content="#da532c"> - <link rel="icon" - href="./_assets/pwa/favicon.svg"> - <script> - const currentTheme = localStorage.getItem("theme"); - if (currentTheme === "light") { - document.querySelector("html").dataset.theme = "light"; - } else { - document.querySelector("html").dataset.theme = "dark"; - } - </script> - <link rel="stylesheet" - href="./_assets/pre.css"> - <title>Time Tracker</title> -</head> - -<body> - -<noscript> - This page is built with javascript. Allow it and try again. -</noscript> - -<div class="fill-loader fill-loader--v4" - id="loader" - role="alert"> - <p class="fill-loader__label">Loading Time Tracker...</p> - <div aria-hidden="true"> - <div class="fill-loader__base"></div> - <div class="fill-loader__fill"></div> - </div> -</div> - -<div id="root"></div> - -<script type="module" - src="./app/index.ts"></script> -</body> - -</html> diff --git a/apps/projects-web/src/package.json b/apps/projects-web/src/package.json deleted file mode 100644 index 8ff516d..0000000 --- a/apps/projects-web/src/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "time-tracker-public", - "version": "0.0.1", - "private": "true", - "scripts": { - "dev": "vite", - "build": "vite build" - }, - "devDependencies": { - "@sveltejs/vite-plugin-svelte": "1.0.0-next.43", - "sass": "^1.51.0", - "svelte": "^3.48.0", - "svelte-preprocess": "^4.10.6", - "svelte-spa-router": "^3.2.0", - "typescript": "4.6.4", - "vite": "^2.9.8" - }, - "dependencies": { - "@js-temporal/polyfill": "^0.4.1", - "fuzzysort": "^1.9.0" - } -} diff --git a/apps/projects-web/src/pnpm-lock.yaml b/apps/projects-web/src/pnpm-lock.yaml deleted file mode 100644 index 3b56115..0000000 --- a/apps/projects-web/src/pnpm-lock.yaml +++ /dev/null @@ -1,769 +0,0 @@ -lockfileVersion: 5.4 - -specifiers: - '@js-temporal/polyfill': ^0.4.1 - '@sveltejs/vite-plugin-svelte': 1.0.0-next.43 - fuzzysort: ^1.9.0 - sass: ^1.51.0 - svelte: ^3.48.0 - svelte-preprocess: ^4.10.6 - svelte-spa-router: ^3.2.0 - typescript: 4.6.4 - vite: ^2.9.8 - -dependencies: - '@js-temporal/polyfill': 0.4.1 - fuzzysort: 1.9.0 - -devDependencies: - '@sveltejs/vite-plugin-svelte': 1.0.0-next.43_svelte@3.48.0+vite@2.9.8 - sass: 1.51.0 - svelte: 3.48.0 - svelte-preprocess: 4.10.6_24ezlekk4ocevlsjgs2qnqmjum - svelte-spa-router: 3.2.0 - typescript: 4.6.4 - vite: 2.9.8_sass@1.51.0 - -packages: - - /@js-temporal/polyfill/0.4.1: - resolution: {integrity: sha512-q45ecIocpa2TLem2jNOsCrDwP/sgKZdSkt+C1Rx07OkdKsdbvVfHcD1iDiK9scxBZrBQ38uJ8VQISXBS70ql1w==} - engines: {node: '>=12'} - dependencies: - jsbi: 4.3.0 - tslib: 2.4.0 - dev: false - - /@rollup/pluginutils/4.2.1: - resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} - engines: {node: '>= 8.0.0'} - dependencies: - estree-walker: 2.0.2 - picomatch: 2.3.1 - dev: true - - /@sveltejs/vite-plugin-svelte/1.0.0-next.43_svelte@3.48.0+vite@2.9.8: - resolution: {integrity: sha512-MzeczqGrnDmbAldw/LfXV/dhpLC2bdUzuMhcx0C2j79V2uNzQERHDinxXnG2AVTCTjSpbQxzQwMMmYflnI7W1g==} - engines: {node: ^14.13.1 || >= 16} - peerDependencies: - diff-match-patch: ^1.0.5 - svelte: ^3.44.0 - vite: ^2.9.0 - peerDependenciesMeta: - diff-match-patch: - optional: true - dependencies: - '@rollup/pluginutils': 4.2.1 - debug: 4.3.4 - deepmerge: 4.2.2 - kleur: 4.1.4 - magic-string: 0.26.1 - svelte: 3.48.0 - svelte-hmr: 0.14.11_svelte@3.48.0 - vite: 2.9.8_sass@1.51.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@types/node/17.0.31: - resolution: {integrity: sha512-AR0x5HbXGqkEx9CadRH3EBYx/VkiUgZIhP4wvPn/+5KIsgpNoyFaRlVe0Zlx9gRtg8fA06a9tskE2MSN7TcG4Q==} - dev: true - - /@types/pug/2.0.6: - resolution: {integrity: sha512-SnHmG9wN1UVmagJOnyo/qkk0Z7gejYxOYYmaAwr5u2yFYfsupN3sg10kyzN8Hep/2zbHxCnsumxOoRIRMBwKCg==} - dev: true - - /@types/sass/1.43.1: - resolution: {integrity: sha512-BPdoIt1lfJ6B7rw35ncdwBZrAssjcwzI5LByIrYs+tpXlj/CAkuVdRsgZDdP4lq5EjyWzwxZCqAoFyHKFwp32g==} - dependencies: - '@types/node': 17.0.31 - dev: true - - /anymatch/3.1.2: - resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} - engines: {node: '>= 8'} - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - dev: true - - /balanced-match/1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - dev: true - - /binary-extensions/2.2.0: - resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} - engines: {node: '>=8'} - dev: true - - /brace-expansion/1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - dev: true - - /braces/3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} - dependencies: - fill-range: 7.0.1 - dev: true - - /buffer-crc32/0.2.13: - resolution: {integrity: sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=} - dev: true - - /chokidar/3.5.3: - resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} - engines: {node: '>= 8.10.0'} - dependencies: - anymatch: 3.1.2 - braces: 3.0.2 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.2 - dev: true - - /concat-map/0.0.1: - resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} - dev: true - - /debug/4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 - dev: true - - /deepmerge/4.2.2: - resolution: {integrity: sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==} - engines: {node: '>=0.10.0'} - dev: true - - /detect-indent/6.1.0: - resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} - engines: {node: '>=8'} - dev: true - - /es6-promise/3.3.1: - resolution: {integrity: sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=} - dev: true - - /esbuild-android-64/0.14.38: - resolution: {integrity: sha512-aRFxR3scRKkbmNuGAK+Gee3+yFxkTJO/cx83Dkyzo4CnQl/2zVSurtG6+G86EQIZ+w+VYngVyK7P3HyTBKu3nw==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /esbuild-android-arm64/0.14.38: - resolution: {integrity: sha512-L2NgQRWuHFI89IIZIlpAcINy9FvBk6xFVZ7xGdOwIm8VyhX1vNCEqUJO3DPSSy945Gzdg98cxtNt8Grv1CsyhA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /esbuild-darwin-64/0.14.38: - resolution: {integrity: sha512-5JJvgXkX87Pd1Og0u/NJuO7TSqAikAcQQ74gyJ87bqWRVeouky84ICoV4sN6VV53aTW+NE87qLdGY4QA2S7KNA==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /esbuild-darwin-arm64/0.14.38: - resolution: {integrity: sha512-eqF+OejMI3mC5Dlo9Kdq/Ilbki9sQBw3QlHW3wjLmsLh+quNfHmGMp3Ly1eWm981iGBMdbtSS9+LRvR2T8B3eQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /esbuild-freebsd-64/0.14.38: - resolution: {integrity: sha512-epnPbhZUt93xV5cgeY36ZxPXDsQeO55DppzsIgWM8vgiG/Rz+qYDLmh5ts3e+Ln1wA9dQ+nZmVHw+RjaW3I5Ig==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /esbuild-freebsd-arm64/0.14.38: - resolution: {integrity: sha512-/9icXUYJWherhk+y5fjPI5yNUdFPtXHQlwP7/K/zg8t8lQdHVj20SqU9/udQmeUo5pDFHMYzcEFfJqgOVeKNNQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /esbuild-linux-32/0.14.38: - resolution: {integrity: sha512-QfgfeNHRFvr2XeHFzP8kOZVnal3QvST3A0cgq32ZrHjSMFTdgXhMhmWdKzRXP/PKcfv3e2OW9tT9PpcjNvaq6g==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /esbuild-linux-64/0.14.38: - resolution: {integrity: sha512-uuZHNmqcs+Bj1qiW9k/HZU3FtIHmYiuxZ/6Aa+/KHb/pFKr7R3aVqvxlAudYI9Fw3St0VCPfv7QBpUITSmBR1Q==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /esbuild-linux-arm/0.14.38: - resolution: {integrity: sha512-FiFvQe8J3VKTDXG01JbvoVRXQ0x6UZwyrU4IaLBZeq39Bsbatd94Fuc3F1RGqPF5RbIWW7RvkVQjn79ejzysnA==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /esbuild-linux-arm64/0.14.38: - resolution: {integrity: sha512-HlMGZTEsBrXrivr64eZ/EO0NQM8H8DuSENRok9d+Jtvq8hOLzrxfsAT9U94K3KOGk2XgCmkaI2KD8hX7F97lvA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /esbuild-linux-mips64le/0.14.38: - resolution: {integrity: sha512-qd1dLf2v7QBiI5wwfil9j0HG/5YMFBAmMVmdeokbNAMbcg49p25t6IlJFXAeLzogv1AvgaXRXvgFNhScYEUXGQ==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /esbuild-linux-ppc64le/0.14.38: - resolution: {integrity: sha512-mnbEm7o69gTl60jSuK+nn+pRsRHGtDPfzhrqEUXyCl7CTOCLtWN2bhK8bgsdp6J/2NyS/wHBjs1x8aBWwP2X9Q==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /esbuild-linux-riscv64/0.14.38: - resolution: {integrity: sha512-+p6YKYbuV72uikChRk14FSyNJZ4WfYkffj6Af0/Tw63/6TJX6TnIKE+6D3xtEc7DeDth1fjUOEqm+ApKFXbbVQ==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /esbuild-linux-s390x/0.14.38: - resolution: {integrity: sha512-0zUsiDkGJiMHxBQ7JDU8jbaanUY975CdOW1YDrurjrM0vWHfjv9tLQsW9GSyEb/heSK1L5gaweRjzfUVBFoybQ==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /esbuild-netbsd-64/0.14.38: - resolution: {integrity: sha512-cljBAApVwkpnJZfnRVThpRBGzCi+a+V9Ofb1fVkKhtrPLDYlHLrSYGtmnoTVWDQdU516qYI8+wOgcGZ4XIZh0Q==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - dev: true - optional: true - - /esbuild-openbsd-64/0.14.38: - resolution: {integrity: sha512-CDswYr2PWPGEPpLDUO50mL3WO/07EMjnZDNKpmaxUPsrW+kVM3LoAqr/CE8UbzugpEiflYqJsGPLirThRB18IQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - dev: true - optional: true - - /esbuild-sunos-64/0.14.38: - resolution: {integrity: sha512-2mfIoYW58gKcC3bck0j7lD3RZkqYA7MmujFYmSn9l6TiIcAMpuEvqksO+ntBgbLep/eyjpgdplF7b+4T9VJGOA==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - dev: true - optional: true - - /esbuild-windows-32/0.14.38: - resolution: {integrity: sha512-L2BmEeFZATAvU+FJzJiRLFUP+d9RHN+QXpgaOrs2klshoAm1AE6Us4X6fS9k33Uy5SzScn2TpcgecbqJza1Hjw==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /esbuild-windows-64/0.14.38: - resolution: {integrity: sha512-Khy4wVmebnzue8aeSXLC+6clo/hRYeNIm0DyikoEqX+3w3rcvrhzpoix0S+MF9vzh6JFskkIGD7Zx47ODJNyCw==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /esbuild-windows-arm64/0.14.38: - resolution: {integrity: sha512-k3FGCNmHBkqdJXuJszdWciAH77PukEyDsdIryEHn9cKLQFxzhT39dSumeTuggaQcXY57UlmLGIkklWZo2qzHpw==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /esbuild/0.14.38: - resolution: {integrity: sha512-12fzJ0fsm7gVZX1YQ1InkOE5f9Tl7cgf6JPYXRJtPIoE0zkWAbHdPHVPPaLi9tYAcEBqheGzqLn/3RdTOyBfcA==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true - optionalDependencies: - esbuild-android-64: 0.14.38 - esbuild-android-arm64: 0.14.38 - esbuild-darwin-64: 0.14.38 - esbuild-darwin-arm64: 0.14.38 - esbuild-freebsd-64: 0.14.38 - esbuild-freebsd-arm64: 0.14.38 - esbuild-linux-32: 0.14.38 - esbuild-linux-64: 0.14.38 - esbuild-linux-arm: 0.14.38 - esbuild-linux-arm64: 0.14.38 - esbuild-linux-mips64le: 0.14.38 - esbuild-linux-ppc64le: 0.14.38 - esbuild-linux-riscv64: 0.14.38 - esbuild-linux-s390x: 0.14.38 - esbuild-netbsd-64: 0.14.38 - esbuild-openbsd-64: 0.14.38 - esbuild-sunos-64: 0.14.38 - esbuild-windows-32: 0.14.38 - esbuild-windows-64: 0.14.38 - esbuild-windows-arm64: 0.14.38 - dev: true - - /estree-walker/2.0.2: - resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} - dev: true - - /fill-range/7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} - dependencies: - to-regex-range: 5.0.1 - dev: true - - /fs.realpath/1.0.0: - resolution: {integrity: sha1-FQStJSMVjKpA20onh8sBQRmU6k8=} - dev: true - - /fsevents/2.3.2: - resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /function-bind/1.1.1: - resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} - dev: true - - /fuzzysort/1.9.0: - resolution: {integrity: sha512-MOxCT0qLTwLqmEwc7UtU045RKef7mc8Qz8eR4r2bLNEq9dy/c3ZKMEFp6IEst69otkQdFZ4FfgH2dmZD+ddX1g==} - dev: false - - /glob-parent/5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - dependencies: - is-glob: 4.0.3 - dev: true - - /glob/7.2.0: - resolution: {integrity: sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==} - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: true - - /graceful-fs/4.2.10: - resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} - dev: true - - /has/1.0.3: - resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} - engines: {node: '>= 0.4.0'} - dependencies: - function-bind: 1.1.1 - dev: true - - /immutable/4.0.0: - resolution: {integrity: sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==} - dev: true - - /inflight/1.0.6: - resolution: {integrity: sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=} - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - dev: true - - /inherits/2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: true - - /is-binary-path/2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - dependencies: - binary-extensions: 2.2.0 - dev: true - - /is-core-module/2.9.0: - resolution: {integrity: sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==} - dependencies: - has: 1.0.3 - dev: true - - /is-extglob/2.1.1: - resolution: {integrity: sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=} - engines: {node: '>=0.10.0'} - dev: true - - /is-glob/4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - dependencies: - is-extglob: 2.1.1 - dev: true - - /is-number/7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - dev: true - - /jsbi/4.3.0: - resolution: {integrity: sha512-SnZNcinB4RIcnEyZqFPdGPVgrg2AcnykiBy0sHVJQKHYeaLUvi3Exj+iaPpLnFVkDPZIV4U0yvgC9/R4uEAZ9g==} - dev: false - - /kleur/4.1.4: - resolution: {integrity: sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA==} - engines: {node: '>=6'} - dev: true - - /magic-string/0.25.9: - resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} - dependencies: - sourcemap-codec: 1.4.8 - dev: true - - /magic-string/0.26.1: - resolution: {integrity: sha512-ndThHmvgtieXe8J/VGPjG+Apu7v7ItcD5mhEIvOscWjPF/ccOiLxHaSuCAS2G+3x4GKsAbT8u7zdyamupui8Tg==} - engines: {node: '>=12'} - dependencies: - sourcemap-codec: 1.4.8 - dev: true - - /min-indent/1.0.1: - resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} - engines: {node: '>=4'} - dev: true - - /minimatch/3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - dependencies: - brace-expansion: 1.1.11 - dev: true - - /minimist/1.2.6: - resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==} - dev: true - - /mkdirp/0.5.6: - resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} - hasBin: true - dependencies: - minimist: 1.2.6 - dev: true - - /ms/2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - dev: true - - /nanoid/3.3.4: - resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - dev: true - - /normalize-path/3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - dev: true - - /once/1.4.0: - resolution: {integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=} - dependencies: - wrappy: 1.0.2 - dev: true - - /path-is-absolute/1.0.1: - resolution: {integrity: sha1-F0uSaHNVNP+8es5r9TpanhtcX18=} - engines: {node: '>=0.10.0'} - dev: true - - /path-parse/1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - dev: true - - /picocolors/1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} - dev: true - - /picomatch/2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - dev: true - - /postcss/8.4.13: - resolution: {integrity: sha512-jtL6eTBrza5MPzy8oJLFuUscHDXTV5KcLlqAWHl5q5WYRfnNRGSmOZmOZ1T6Gy7A99mOZfqungmZMpMmCVJ8ZA==} - engines: {node: ^10 || ^12 || >=14} - dependencies: - nanoid: 3.3.4 - picocolors: 1.0.0 - source-map-js: 1.0.2 - dev: true - - /readdirp/3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} - dependencies: - picomatch: 2.3.1 - dev: true - - /regexparam/2.0.0: - resolution: {integrity: sha512-gJKwd2MVPWHAIFLsaYDZfyKzHNS4o7E/v8YmNf44vmeV2e4YfVoDToTOKTvE7ab68cRJ++kLuEXJBaEeJVt5ow==} - engines: {node: '>=8'} - dev: true - - /resolve/1.22.0: - resolution: {integrity: sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==} - hasBin: true - dependencies: - is-core-module: 2.9.0 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - dev: true - - /rimraf/2.7.1: - resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} - 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'} - hasBin: true - optionalDependencies: - fsevents: 2.3.2 - dev: true - - /sander/0.5.1: - resolution: {integrity: sha1-dB4kXiMfB8r7b98PEzrfohalAq0=} - dependencies: - es6-promise: 3.3.1 - graceful-fs: 4.2.10 - mkdirp: 0.5.6 - rimraf: 2.7.1 - dev: true - - /sass/1.51.0: - resolution: {integrity: sha512-haGdpTgywJTvHC2b91GSq+clTKGbtkkZmVAb82jZQN/wTy6qs8DdFm2lhEQbEwrY0QDRgSQ3xDurqM977C3noA==} - engines: {node: '>=12.0.0'} - hasBin: true - dependencies: - chokidar: 3.5.3 - immutable: 4.0.0 - source-map-js: 1.0.2 - dev: true - - /sorcery/0.10.0: - resolution: {integrity: sha1-iukK19fLBfxZ8asMY3hF1cFaUrc=} - hasBin: true - dependencies: - buffer-crc32: 0.2.13 - minimist: 1.2.6 - sander: 0.5.1 - sourcemap-codec: 1.4.8 - dev: true - - /source-map-js/1.0.2: - resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} - engines: {node: '>=0.10.0'} - dev: true - - /sourcemap-codec/1.4.8: - resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} - dev: true - - /strip-indent/3.0.0: - resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} - engines: {node: '>=8'} - dependencies: - min-indent: 1.0.1 - dev: true - - /supports-preserve-symlinks-flag/1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - dev: true - - /svelte-hmr/0.14.11_svelte@3.48.0: - resolution: {integrity: sha512-R9CVfX6DXxW1Kn45Jtmx+yUe+sPhrbYSUp7TkzbW0jI5fVPn6lsNG9NEs5dFg5qRhFNAoVdRw5qQDLALNKhwbQ==} - engines: {node: ^12.20 || ^14.13.1 || >= 16} - peerDependencies: - svelte: '>=3.19.0' - dependencies: - svelte: 3.48.0 - dev: true - - /svelte-preprocess/4.10.6_24ezlekk4ocevlsjgs2qnqmjum: - resolution: {integrity: sha512-I2SV1w/AveMvgIQlUF/ZOO3PYVnhxfcpNyGt8pxpUVhPfyfL/CZBkkw/KPfuFix5FJ9TnnNYMhACK3DtSaYVVQ==} - engines: {node: '>= 9.11.2'} - requiresBuild: true - peerDependencies: - '@babel/core': ^7.10.2 - coffeescript: ^2.5.1 - less: ^3.11.3 || ^4.0.0 - node-sass: '*' - postcss: ^7 || ^8 - postcss-load-config: ^2.1.0 || ^3.0.0 - pug: ^3.0.0 - sass: ^1.26.8 - stylus: ^0.55.0 - sugarss: ^2.0.0 - svelte: ^3.23.0 - typescript: ^3.9.5 || ^4.0.0 - peerDependenciesMeta: - '@babel/core': - optional: true - coffeescript: - optional: true - less: - optional: true - node-sass: - optional: true - postcss: - optional: true - postcss-load-config: - optional: true - pug: - optional: true - sass: - optional: true - stylus: - optional: true - sugarss: - optional: true - typescript: - optional: true - dependencies: - '@types/pug': 2.0.6 - '@types/sass': 1.43.1 - detect-indent: 6.1.0 - magic-string: 0.25.9 - sass: 1.51.0 - sorcery: 0.10.0 - strip-indent: 3.0.0 - svelte: 3.48.0 - typescript: 4.6.4 - dev: true - - /svelte-spa-router/3.2.0: - resolution: {integrity: sha512-igemo5Vs82TGBBw+DjWt6qKameXYzNs6aDXcTxou5XbEvOjiRcAM6MLkdVRCatn6u8r42dE99bt/br7T4qe/AQ==} - dependencies: - regexparam: 2.0.0 - dev: true - - /svelte/3.48.0: - resolution: {integrity: sha512-fN2YRm/bGumvjUpu6yI3BpvZnpIm9I6A7HR4oUNYd7ggYyIwSA/BX7DJ+UXXffLp6XNcUijyLvttbPVCYa/3xQ==} - engines: {node: '>= 8'} - dev: true - - /to-regex-range/5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - dependencies: - is-number: 7.0.0 - dev: true - - /tslib/2.4.0: - resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} - dev: false - - /typescript/4.6.4: - resolution: {integrity: sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==} - engines: {node: '>=4.2.0'} - hasBin: true - dev: true - - /vite/2.9.8_sass@1.51.0: - resolution: {integrity: sha512-zsBGwn5UT3YS0NLSJ7hnR54+vUKfgzMUh/Z9CxF1YKEBVIe213+63jrFLmZphgGI5zXwQCSmqIdbPuE8NJywPw==} - engines: {node: '>=12.2.0'} - hasBin: true - peerDependencies: - less: '*' - sass: '*' - stylus: '*' - peerDependenciesMeta: - less: - optional: true - sass: - optional: true - stylus: - optional: true - dependencies: - esbuild: 0.14.38 - postcss: 8.4.13 - resolve: 1.22.0 - rollup: 2.72.1 - sass: 1.51.0 - optionalDependencies: - fsevents: 2.3.2 - dev: true - - /wrappy/1.0.2: - resolution: {integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=} - dev: true diff --git a/apps/projects-web/src/tsconfig.json b/apps/projects-web/src/tsconfig.json deleted file mode 100644 index c60fce6..0000000 --- a/apps/projects-web/src/tsconfig.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "include": [ - "./**/*.d.ts", - "./**/*.ts", - "./**/*.js", - "./**/*.svelte" - ], - "exclude": [ - "./node_modules" - ], - "compilerOptions": { - "target": "esnext", - "useDefineForClassFields": true, - "module": "esnext", - "moduleResolution": "node", - "allowJs": true, - "checkJs": false, - "paths": { - "$app/*": [ - "./app/*" - ], - "$shared/*": [ - "../../web-shared/src/*" - ] - } - } -} diff --git a/apps/projects-web/src/vite.config.ts b/apps/projects-web/src/vite.config.ts deleted file mode 100644 index ac44266..0000000 --- a/apps/projects-web/src/vite.config.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { defineConfig } from "vite"; -import { svelte } from "@sveltejs/vite-plugin-svelte"; -import sveltePreprocess from "svelte-preprocess"; -// @ts-ignore -import path from "path"; - -// https://vitejs.dev/config/ -export default defineConfig({ - resolve: { - alias: { - "$shared": path.resolve(__dirname, "../../web-shared/src"), - "$app": path.resolve(__dirname, "./app"), - "$public": path.resolve(__dirname, "./_public"), - } - }, - build: { - outDir: "build", - emptyOutDir: true, - rollupOptions: { - input: { - main: path.resolve(__dirname, "index.html"), - } - } - }, - - plugins: [ - svelte({ - preprocess: sveltePreprocess() - }) - ], -}); |
