Compare commits

..

156 Commits

Author SHA1 Message Date
330755c63e 🚀RELEASE v0.1.5
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-10 17:18:55 +01:00
9cf0174b41 Merge commit '16f572480ad55425890061f9dad65fe85f2f39ad' into dev
close #30
2021-01-10 17:18:33 +01:00
16f572480a add versionbuilder script to release hook
ref #30
2021-01-10 17:18:16 +01:00
b8a9e4f272 📅 dynamic copyright year in Footer component
ref #30
2021-01-10 17:17:07 +01:00
c089bb3929 ⤵ load dynamic build info in Footer component
ref #30
2021-01-10 17:16:51 +01:00
3caa1fc277 🔨 sample build of index.html with versionbuilder script
ref #30
2021-01-10 17:16:07 +01:00
43b406592e 👀 improved Footer layout + display on Login component
ref #30
2021-01-10 17:15:46 +01:00
1dd6674faa added versionbuilder.js script
ref #30
2021-01-10 17:15:01 +01:00
4674b52717 🚀RELEASE v0.1.4
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-10 15:30:59 +01:00
cd5831251a Merge commit '45ec97066f425ac2ac66914be649cbd5a1038e10' into dev
close #20
2021-01-10 15:30:42 +01:00
45ec97066f 🌎 add remaining translation keys for filepond
ref #20
2021-01-10 15:30:13 +01:00
b08c0f145a add basic i18n logic to filepond
ref #20
2021-01-10 15:26:52 +01:00
0e31ba212f About - change license modal icon to "legal"
Some checks failed
continuous-integration/drone/push Build was killed
2021-01-10 15:04:05 +01:00
692c906cd2 🌎 About - i18n 2021-01-10 15:03:32 +01:00
4f3837ac45 new license file version [CI SKIP] 2021-01-10 13:47:30 +00:00
ccb5125a48 🚀RELEASE v0.1.3
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-10 14:46:31 +01:00
1c356a41f5 🌎 improved i18n for AddUserModal and UserDetail
ref #12
2021-01-10 14:45:34 +01:00
6012d0577e 🖊 add basic UserDetail editing reactivity
ref #12
2021-01-10 14:26:52 +01:00
5ec1dfa8b0 sample layout for advanced search
ref #12
2021-01-10 13:35:46 +01:00
3754f09b2f 🌎 added i18n for UsersOverview
ref #12
2021-01-10 13:31:46 +01:00
b9e0be4483 🔍 UsersOverview table - basic fuzzy search
ref #12
2021-01-10 13:30:26 +01:00
e1d5d54cfb 🧹 simplified UsersOverview table
ref #12
2021-01-10 13:30:04 +01:00
e97c5c3b7e Merge branch 'dev' into feature/12-user-management 2021-01-10 13:09:42 +01:00
242b5afbe9 🚀RELEASE v0.1.2
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-10 13:08:24 +01:00
12e5835360 Merge branch 'dev' of https://git.odit.services/lfk/frontend into dev 2021-01-10 13:07:50 +01:00
4af3cd158d Merge commit '2a37dfafa426e070aa136d171a1a01aa7f609d18' into dev
close #29
2021-01-10 13:07:43 +01:00
2a37dfafa4 dropped redundant console.log
ref #29
2021-01-10 13:06:48 +01:00
2cbb431acc 💾 save new auth data to localstorage
ref#29
2021-01-10 13:06:01 +01:00
d92c6c0de9 🔒 added basic manual refresh every 4mins
ref #29
2021-01-10 13:03:48 +01:00
19887c8f96 Merge branch 'dev' into feature/12-user-management 2021-01-10 12:37:18 +01:00
519ba79e1d new license file version [CI SKIP] 2021-01-10 11:36:40 +00:00
4ccd18ca9f Merge commit '5810b4ec4396ad650d90493fb48e2a8320865b42' into dev
All checks were successful
continuous-integration/drone/push Build is passing
close #4
2021-01-10 12:35:44 +01:00
5810b4ec43 🚀RELEASE v0.1.2-1 2021-01-10 12:30:23 +01:00
52aa99681b 🧪 modified auto-changelog to commit CHANGELOG.md
ref #4
2021-01-10 12:30:11 +01:00
0276c3deeb 🚀RELEASE v0.1.2-0 2021-01-10 12:26:07 +01:00
b28f76a1d4 🧪 experimental - auto changelog generation
ref #4
2021-01-10 12:25:42 +01:00
a66f6bbec8 🚀RELEASE v0.1.1 2021-01-10 12:24:29 +01:00
139b3294cd 🧪 move changelog generation to default 2021-01-10 12:24:19 +01:00
1aac783df3 🚀RELEASE v0.1.0 2021-01-10 12:21:35 +01:00
e361c89f6c add basic package script
ref #4
2021-01-10 12:18:22 +01:00
52a19c2036 added basic release-it config
ref #4
2021-01-10 12:18:00 +01:00
0023e22524 added release-it dev dependency
ref #4
2021-01-10 12:17:49 +01:00
b9aa00e8de Merge branch 'dev' into feature/12-user-management 2021-01-10 11:42:35 +01:00
8f25a874cb move serviceworker registration to separate module
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-10 11:42:30 +01:00
ded31980bf userdetail - dynamic buttons
ref #12
2021-01-09 19:11:46 +01:00
264e0d7ed9 AddUserModal - data validation
ref #12
2021-01-09 18:55:54 +01:00
7cf2ffce2d 🐞 fix malfuntion in logout logic
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-09 18:39:13 +01:00
848fb2fb65 Merge branch 'feature/12-user-management' into dev
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-09 18:29:47 +01:00
6529907a13 display full user names in overview table
ref #12
2021-01-09 18:27:22 +01:00
e5ec98bf6f basic AddUserModal ui
ref #12
2021-01-09 18:26:14 +01:00
2048533fda actually perform user logout (recreate Cookies, invalidate token) 2021-01-09 18:24:57 +01:00
cb58fdfd8e working on AddUserModal
ref #12
2021-01-09 17:39:17 +01:00
9684c22da3 simplified css classes for cleanliness 2021-01-09 17:15:52 +01:00
59d5ad5bd3 logic cleanup 🧠
All checks were successful
continuous-integration/drone/push Build is passing
ref #12
2021-01-09 16:06:03 +01:00
71c761187f UserOverview cleanup
ref #12
2021-01-09 15:58:58 +01:00
11457b2792 added Breadcrumb nav to UserDetail
ref #12
2021-01-09 15:40:10 +01:00
4fd1ac28c5 display profilepic properly
ref #12
2021-01-09 15:39:56 +01:00
8cf73a2be0 added middlename input field to mock
ref #12
2021-01-09 15:39:43 +01:00
644b9a7683 proper middlename display support
ref #12
2021-01-09 15:39:28 +01:00
23e03bec35 UserDetailOne sample ui
All checks were successful
continuous-integration/drone/push Build is passing
ref #12
2021-01-09 14:16:07 +01:00
9e19c48258 added general PromiseError component
ref #12
2021-01-09 14:15:55 +01:00
e7f63cf07b Merge branch 'dev' into feature/12-user-management 2021-01-09 14:05:00 +01:00
c38d33a549 ignore licenses.json in serviceworker
All checks were successful
continuous-integration/drone/push Build is passing
ref #17
2021-01-09 14:02:10 +01:00
1c2636d669 i18n 🌍
ref #17
2021-01-09 14:01:20 +01:00
c0328c5cdb AboutPage - read license text modal
ref #17
2021-01-09 13:57:25 +01:00
919910d4a8 bump to @odit/license-exporter@0.0.9 for version support
ref #17
2021-01-09 13:56:55 +01:00
9ab72aed19 license.json export + usage
ref #17
2021-01-09 13:32:54 +01:00
0e08c7f075 working on user detail page
ref #12
2021-01-09 12:54:55 +01:00
d5703365e4 first UserDetail page mockup
ref #12
2021-01-09 12:46:47 +01:00
58d68c8324 User Overview table expansion
ref #12
2021-01-09 12:46:35 +01:00
3c4a10944e added routing to UserDetail page
ref #12
2021-01-09 12:46:21 +01:00
6e4fe37378 general dependency bump 2021-01-09 12:07:29 +01:00
04794ff75e Merge branch 'feature/12-user-management' into dev
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-08 21:20:44 +01:00
f7d7b837c4 general dependency bump 2021-01-08 21:20:20 +01:00
08278b36a5 basic User Components
ref #12
2021-01-08 21:19:43 +01:00
9aeb99d775 dependency bump
ref #12
2021-01-08 21:19:05 +01:00
e8c98a0a29 basic ForgotPassword improvements
All checks were successful
continuous-integration/drone/push Build is passing
validation, steps towards error handlind
2021-01-08 17:32:31 +01:00
b107f5de95 move OpenAPI config to App component rather than Login 2021-01-08 17:31:37 +01:00
0c7bc07d67 🐞👀 visual fix in Footer component 2021-01-08 16:28:38 +01:00
970a7c58d3 Merge commit '2657f30cf3acaa592408d2d4cddcb02bf76bb6af' into dev
 close #27
2021-01-08 16:24:11 +01:00
2657f30cf3 use outsideclick custom directive in AddTrackModal component
ref #27
2021-01-08 16:23:45 +01:00
a042c8a870 added outsideclick as custom directive
ref #27
2021-01-08 16:23:20 +01:00
fc5c8d1309 Login Component Accessibility 👀
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-07 20:56:24 +01:00
32e4f223f8 NGINX config - fix 404 error for SPA usage 2021-01-07 20:56:09 +01:00
1f5057438f NGINX config - enable brotli compression 2021-01-07 20:55:49 +01:00
dbc660c48e remove duplicate class usage in Dash Component
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-07 20:32:56 +01:00
be440684b3 Merge commit '80d30a8e5425f4041e79c299095c36386b8d7777' into dev
All checks were successful
continuous-integration/drone/push Build is passing
close #26
2021-01-07 20:24:44 +01:00
80d30a8e54 ▶ ENTER key submit
ref #26
2021-01-07 20:23:45 +01:00
0c3e74f8a3 escape key support
ref #26
2021-01-07 20:21:17 +01:00
ac952b6906 📦 further Dockerfile/ Bundle optimizations
All checks were successful
continuous-integration/drone/push Build is passing
close #25
2021-01-07 20:14:45 +01:00
43ecd83213 general + PWA optimizations
All checks were successful
continuous-integration/drone/push Build is passing
selfhosting logo + PWA score optimization
2021-01-07 19:55:18 +01:00
aaef97dd43 🐳 added Docker buildsteps for sw generation
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-07 18:27:44 +01:00
bc66ebbf0a PWA optimizations
All checks were successful
continuous-integration/drone/push Build is passing
this supports asset caching + proper handling of the /env.js file (might have lead to config errors in previous versions)
2021-01-07 18:16:36 +01:00
44029c812e Dashboard - fix accessibility focus state on nav Dropdown + Logout
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-07 14:18:22 +01:00
3e8d0b5462 🐞fixed snowpack config for bundle optimization 2021-01-07 14:17:45 +01:00
6915123973 re-enable Tailwind compile with postcss 2021-01-07 14:16:03 +01:00
089813146f Merge commit 'bb0eb6d1e276186af2c1e5d26abda4413c278981' into dev
All checks were successful
continuous-integration/drone/push Build is passing
close #11
2021-01-05 22:24:18 +01:00
bb0eb6d1e2 AddTrackModal - minlaptime validation
ref #11
2021-01-05 22:15:20 +01:00
388fc8f239 AddTrackModal - autofocus on modal open
ref #11
2021-01-05 22:11:06 +01:00
0e7640bf86 AddTrackModal - trap focus if active
ref #11
2021-01-05 22:07:38 +01:00
d45eec94ab AddTrackModal - placeholder input
ref #11
2021-01-05 22:05:22 +01:00
7bb5a18527 AddTrackModal - add track icon
ref #11
2021-01-05 22:05:06 +01:00
fe297f6779 AddTrackModal - more input validation response
ref #11
2021-01-05 22:02:41 +01:00
591dc09228 AddTrackModal - basic validation w/ class + layout responses
ref #11
2021-01-05 21:53:06 +01:00
7d1b51918f delete confirmation
ref #11
2021-01-05 21:42:42 +01:00
e5fcb2ef68 Track edit animation
ref #11
2021-01-05 21:38:57 +01:00
34ecb8b2fb move toastify css to app base
ref #11
2021-01-05 21:38:47 +01:00
68de076227 edit is working 🎉
ref #11
2021-01-05 21:30:01 +01:00
039fd8f90e basic edit logic in table
ref #11
2021-01-05 21:16:50 +01:00
02bfecd540 EmptyState fixup
ref #11
2021-01-05 20:34:10 +01:00
10bf88e4ba fixed datatable-emptystate transition
ref #11
2021-01-05 20:27:06 +01:00
6e00ac8f1f improved empty state
ref #11
2021-01-05 18:31:36 +01:00
35a9aa40cb basic track deletion working
ref #11
2021-01-05 18:31:26 +01:00
c23fb5a450 Merge branch 'feature/24-i18n-formatting' into dev
All checks were successful
continuous-integration/drone/push Build is passing
close #24
2021-01-04 20:29:58 +01:00
1cd03ef027 add package script
ref #24
2021-01-04 20:29:43 +01:00
17e7778d15 re-added missing i18n keys
All checks were successful
continuous-integration/drone/push Build is passing
ref #11
2021-01-04 19:59:18 +01:00
70e10f7a70 demo run
ref #24
2021-01-04 19:55:23 +01:00
947482c1b5 improved order script for scalability
ref #24
2021-01-04 19:55:12 +01:00
f9aa262cab basic formatting script
ref #24
2021-01-04 19:52:05 +01:00
ff91995337 Merge branch 'dev' into feature/11-tracks-management
All checks were successful
continuous-integration/drone/push Build is passing
# Conflicts:
#	src/locales/en.json
2021-01-04 19:40:53 +01:00
5b15141ecc general cleanups
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-04 19:39:57 +01:00
008c91a552 track lap time interactive placeholder
ref #11
2021-01-04 19:37:17 +01:00
d830727036 AddTrackModal padding style
ref #11
2021-01-04 19:37:02 +01:00
dadccc1b5f 🌍 i18n lap time
ref #11
2021-01-04 19:33:48 +01:00
6022953417 Merge branch 'dev' into feature/11-tracks-management 2021-01-04 19:20:45 +01:00
e62277bdd2 tinro dependency bump
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-04 19:20:41 +01:00
7210f1b947 include minimum lap times
ref #11
2021-01-04 19:20:13 +01:00
8af63fc22a Merge commit '3a702aa91e768ab58e017d859732fcac960edac6' into feature/11-tracks-management 2021-01-04 18:24:56 +01:00
3a702aa91e 🎨 OrgDetail style fix
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-04 18:24:35 +01:00
312ddef193 Merge branch 'feature/17-license_collection' into dev
All checks were successful
continuous-integration/drone/push Build is passing
close #17
2021-01-03 19:39:27 +01:00
236aba89c2 bump lfk client 2021-01-03 19:34:03 +01:00
ba87349a88 dependency bump 2021-01-03 19:07:53 +01:00
9527167fbc StatCards direct linking to detail page 2021-01-03 19:01:14 +01:00
9309ea9a30 move FormLayout component to Settings Page 2021-01-03 19:00:59 +01:00
02d8888d97 🎨 general page styles 2021-01-03 18:54:54 +01:00
56556bad6e Merge branch 'dev' into feature/11-tracks-management
# Conflicts:
#	src/locales/en.json
2021-01-03 18:18:31 +01:00
84430854df 🌍 i18n 2021-01-03 18:14:40 +01:00
3f961dd3bd general page cleanups
let's go, devspeed 🚀
2021-01-03 18:14:31 +01:00
5c218c64ab improved sidebar icons 2021-01-03 18:04:03 +01:00
51c9c3fe3c new layout margin from page title
ref #11
2021-01-03 17:52:21 +01:00
281747a681 🌍 i18n
ref #11
2021-01-03 17:52:02 +01:00
f37ba1dbf7 reactivity on adding a new Track
ref #11
2021-01-03 17:51:46 +01:00
48ddc62192 🌍 translations
ref #11
2021-01-03 16:01:46 +01:00
1954909786 Merge branch 'dev' into feature/11-tracks-management 2021-01-03 15:55:50 +01:00
b1114634e8 Component + Login cleanup 2021-01-03 15:55:46 +01:00
501bf7a5f4 AddTrackModal action
ref #11
2021-01-03 15:55:29 +01:00
9975c0cf64 Tracks datatable action ui
ref #11
2021-01-03 15:55:16 +01:00
f5d0e285fb AddTrackModal cleanup
ref #11
2021-01-03 15:53:13 +01:00
89fcfe6a49 Dashboard component cleanup 2021-01-03 14:03:08 +01:00
72f1645767 Track page cleanup 2021-01-03 13:59:58 +01:00
9af4cfe73f Tracks page cleanup 2021-01-03 13:50:31 +01:00
0842640fec Dependency: Bumped license-exporter version
ref odit/license-exporter#1 odit/license-exporter#3
2021-01-02 20:50:55 +01:00
b538b6cb71 Updated dev branch name 2021-01-01 14:02:29 +01:00
4c96b9a3e0 Initial license export
ref #18
2020-12-31 22:42:50 +01:00
9bf21a0eeb Added drone file with pipeline for dev
ref #18
2020-12-31 22:41:30 +01:00
1fba3ef9e4 Added script for license export
ref #18
2020-12-31 22:41:10 +01:00
54 changed files with 2151 additions and 787 deletions

3
.dockerignore Normal file
View File

@@ -0,0 +1,3 @@
public/env.sample.js
public/workbox-*.js
public/workbox-*.js.map

41
.drone.yml Normal file
View File

@@ -0,0 +1,41 @@
---
kind: pipeline
type: docker
name: build:dev
steps:
- name: build dev
image: plugins/docker
depends_on: [clone]
settings:
username:
from_secret: DOCKER_REGISTRY_USER
password:
from_secret: DOCKER_REGISTRY_PASSWORD
repo: registry.odit.services/lfk/frontend
tags:
- dev
registry: registry.odit.services
- name: run full license export
depends_on: ["clone"]
image: node:alpine
commands:
- yarn
- yarn licenses:export
- name: push new licenses file to repo
depends_on: ["run full license export"]
image: appleboy/drone-git-push
settings:
branch: dev
commit: true
commit_message: new license file version [CI SKIP]
author_email: bot@odit.services
remote: git@git.odit.services:lfk/frontend.git
ssh_key:
from_secret: GITLAB_SSHKEY
trigger:
branch:
- dev
event:
- push

3
.gitignore vendored
View File

@@ -6,4 +6,5 @@ dist-ssr
public/env.js public/env.js
/build /build
yarn.lock yarn.lock
package-lock.json package-lock.json
*.map

274
CHANGELOG.md Normal file
View File

@@ -0,0 +1,274 @@
### Changelog
All notable changes to this project will be documented in this file. Dates are displayed in UTC.
#### [0.1.5](https://git.odit.services/lfk/frontend/compare/0.1.4...0.1.5)
- Merge commit '16f572480ad55425890061f9dad65fe85f2f39ad' into dev [`#30`](https://git.odit.services/lfk/frontend/issues/30)
- ⤵ load dynamic build info in Footer component [`c089bb3`](https://git.odit.services/lfk/frontend/commit/c089bb39298fb1067093c2fa81101130c214947c)
- 📅 dynamic copyright year in Footer component [`b8a9e4f`](https://git.odit.services/lfk/frontend/commit/b8a9e4f272f925999b9a032dd009f7498acbfae0)
- 👀 improved Footer layout + display on Login component [`43b4065`](https://git.odit.services/lfk/frontend/commit/43b406592ebe115cea04a8dbf36874c0a5bdd7e9)
- ✨ added versionbuilder.js script [`1dd6674`](https://git.odit.services/lfk/frontend/commit/1dd6674faad686c0048a62b4cd25ab21b5c8b04f)
- ⚡ add versionbuilder script to release hook [`16f5724`](https://git.odit.services/lfk/frontend/commit/16f572480ad55425890061f9dad65fe85f2f39ad)
- 🔨 sample build of index.html with versionbuilder script [`3caa1fc`](https://git.odit.services/lfk/frontend/commit/3caa1fc277b99ee767c1e1fc4a28fd247d98e659)
#### [0.1.4](https://git.odit.services/lfk/frontend/compare/0.1.3...0.1.4)
> 10 January 2021
- Merge commit '45ec97066f425ac2ac66914be649cbd5a1038e10' into dev [`#20`](https://git.odit.services/lfk/frontend/issues/20)
- 🌎 add remaining translation keys for filepond [`45ec970`](https://git.odit.services/lfk/frontend/commit/45ec97066f425ac2ac66914be649cbd5a1038e10)
- add basic i18n logic to filepond [`b08c0f1`](https://git.odit.services/lfk/frontend/commit/b08c0f145a13d295b2a51c7a6da76faceb80a90c)
- 🚀RELEASE v0.1.4 [`4674b52`](https://git.odit.services/lfk/frontend/commit/4674b52717e388122e113553b8a136c649ce030c)
- 🌎 About - i18n [`692c906`](https://git.odit.services/lfk/frontend/commit/692c906cd26bdb7f7d730b90734d23748e0ab451)
- ✨ About - change license modal icon to "legal" [`0e31ba2`](https://git.odit.services/lfk/frontend/commit/0e31ba212f99d90b133bc242e5b4d163aa99b93b)
- new license file version [CI SKIP] [`4f3837a`](https://git.odit.services/lfk/frontend/commit/4f3837ac45a5df9a7476fd68ec9c069dc6b128cd)
#### [0.1.3](https://git.odit.services/lfk/frontend/compare/0.1.2...0.1.3)
> 10 January 2021
- 🌎 improved i18n for AddUserModal and UserDetail [`1c356a4`](https://git.odit.services/lfk/frontend/commit/1c356a41f54a954afaa69ed524f62c1676f7bbee)
- 🧹 simplified UsersOverview table [`e1d5d54`](https://git.odit.services/lfk/frontend/commit/e1d5d54cfb1fb20e56f0e971e2cfd196e9a913ac)
- 🌎 added i18n for UsersOverview [`3754f09`](https://git.odit.services/lfk/frontend/commit/3754f09b2f395a82ff8c3a9c655ab8a782e7eb71)
- 🖊 add basic UserDetail editing reactivity [`6012d05`](https://git.odit.services/lfk/frontend/commit/6012d0577e2ae6caf44aaee54335188bc767fff7)
- AddUserModal - data validation [`264e0d7`](https://git.odit.services/lfk/frontend/commit/264e0d7ed98c5000da543af154d6e36a6b956e4a)
- ✨ sample layout for advanced search [`5ec1dfa`](https://git.odit.services/lfk/frontend/commit/5ec1dfa8b0da4619f14e73794b9a9e22872aa330)
- userdetail - dynamic buttons [`ded3198`](https://git.odit.services/lfk/frontend/commit/ded31980bfbf9f09afa2818bdcc8cc3e40748441)
- 🚀RELEASE v0.1.3 [`ccb5125`](https://git.odit.services/lfk/frontend/commit/ccb5125a48486ef55709419eccd7d9e912a1e64c)
- 🔍 UsersOverview table - basic fuzzy search [`b9e0be4`](https://git.odit.services/lfk/frontend/commit/b9e0be448398d087005e220d08e34461490be14e)
#### [0.1.2](https://git.odit.services/lfk/frontend/compare/0.1.2-1...0.1.2)
> 10 January 2021
- Merge commit '2a37dfafa426e070aa136d171a1a01aa7f609d18' into dev [`#29`](https://git.odit.services/lfk/frontend/issues/29)
- Merge commit '5810b4ec4396ad650d90493fb48e2a8320865b42' into dev [`#4`](https://git.odit.services/lfk/frontend/issues/4)
- 🔒 added basic manual refresh every 4mins [`d92c6c0`](https://git.odit.services/lfk/frontend/commit/d92c6c0de9d6b72027b8aa27b22e3dc7b5116af1)
- 🚀RELEASE v0.1.2 [`242b5af`](https://git.odit.services/lfk/frontend/commit/242b5afbe93a6100826b0340f821ad2a2c4de343)
- dropped redundant console.log [`2a37dfa`](https://git.odit.services/lfk/frontend/commit/2a37dfafa426e070aa136d171a1a01aa7f609d18)
- 💾 save new auth data to localstorage [`2cbb431`](https://git.odit.services/lfk/frontend/commit/2cbb431acc0fe1aa333ddedb76510486a5fcf191)
- new license file version [CI SKIP] [`519ba79`](https://git.odit.services/lfk/frontend/commit/519ba79e1d5d97e2f59f769ef952a649481b55c0)
#### [0.1.2-1](https://git.odit.services/lfk/frontend/compare/0.1.2-0...0.1.2-1)
> 10 January 2021
- 🚀RELEASE v0.1.2-1 [`5810b4e`](https://git.odit.services/lfk/frontend/commit/5810b4ec4396ad650d90493fb48e2a8320865b42)
- 🧪 modified auto-changelog to commit CHANGELOG.md [`52aa996`](https://git.odit.services/lfk/frontend/commit/52aa99681bb02472e0433cb32b89dde814cd9467)
#### [0.1.2-0](https://git.odit.services/lfk/frontend/compare/0.1.1...0.1.2-0)
> 10 January 2021
- 🧪 experimental - auto changelog generation [`b28f76a`](https://git.odit.services/lfk/frontend/commit/b28f76a1d46a7abdd3014398d41ff976bf39230b)
- 🚀RELEASE v0.1.2-0 [`0276c3d`](https://git.odit.services/lfk/frontend/commit/0276c3deeb8d78f9773bea724e4007f03e8de5e4)
#### [0.1.1](https://git.odit.services/lfk/frontend/compare/0.1.0...0.1.1)
> 10 January 2021
- 🚀RELEASE v0.1.1 [`a66f6bb`](https://git.odit.services/lfk/frontend/commit/a66f6bbec8e9d6be4fd0b68e0a388d351dbc5cb1)
- 🧪 move changelog generation to default [`139b329`](https://git.odit.services/lfk/frontend/commit/139b3294cdfd2437605142de0e4bb029f03f54f6)
#### 0.1.0
> 10 January 2021
- Merge commit '2657f30cf3acaa592408d2d4cddcb02bf76bb6af' into dev [`#27`](https://git.odit.services/lfk/frontend/issues/27)
- Merge commit '80d30a8e5425f4041e79c299095c36386b8d7777' into dev [`#26`](https://git.odit.services/lfk/frontend/issues/26)
- 📦 further Dockerfile/ Bundle optimizations [`#25`](https://git.odit.services/lfk/frontend/issues/25)
- Merge commit 'bb0eb6d1e276186af2c1e5d26abda4413c278981' into dev [`#11`](https://git.odit.services/lfk/frontend/issues/11)
- Merge branch 'feature/24-i18n-formatting' into dev [`#24`](https://git.odit.services/lfk/frontend/issues/24)
- Merge branch 'feature/17-license_collection' into dev [`#17`](https://git.odit.services/lfk/frontend/issues/17)
- Merge pull request 'feature/10-dashboard-stats' (#21) from feature/10-dashboard-stats into develop [`#10`](https://git.odit.services/lfk/frontend/issues/10)
- Merge pull request 'feature/8-login-preserve' (#19) from feature/8-login-preserve into develop [`#8`](https://git.odit.services/lfk/frontend/issues/8)
- Merge pull request 'feature/5-base-components' (#18) from feature/5-base-components into develop [`#5`](https://git.odit.services/lfk/frontend/issues/5)
- Merge commit 'de7cd1267df684b5befd6111aa347e76c6f2ffdd' into develop [`#7`](https://git.odit.services/lfk/frontend/issues/7)
- 🌑 enable tailwind darkmode in config [`#6`](https://git.odit.services/lfk/frontend/issues/6)
- basic move to snowpack [`#3`](https://git.odit.services/lfk/frontend/issues/3)
- tailwind config [`#2`](https://git.odit.services/lfk/frontend/issues/2)
- license.json export + usage [`9ab72ae`](https://git.odit.services/lfk/frontend/commit/9ab72aed19f4174abdff83e45d9f3bfd16448ad4)
- basic User Components [`08278b3`](https://git.odit.services/lfk/frontend/commit/08278b36a5ed8096ae1d8eed6d10dcc1abdc5943)
- general page cleanups [`3f961dd`](https://git.odit.services/lfk/frontend/commit/3f961dd3bd559968626ee9cacb2b4fb00f776a64)
- demo run [`70e10f7`](https://git.odit.services/lfk/frontend/commit/70e10f7a70cf24fe4b78eee91bf4af3e37452fff)
- basic AddUserModal ui [`e5ec98b`](https://git.odit.services/lfk/frontend/commit/e5ec98bf6f599fe7fcf53065666cff880e0d5dfd)
- working on user detail page [`0e08c7f`](https://git.odit.services/lfk/frontend/commit/0e08c7f075571c8734bcda3347e2e2635c46c806)
- simplified css classes for cleanliness [`9684c22`](https://git.odit.services/lfk/frontend/commit/9684c22da3c9029d00057a3efe9a0fe34fd41070)
- first UserDetail page mockup [`d570336`](https://git.odit.services/lfk/frontend/commit/d5703365e46e52ee5b3090a89526a887db9ffc0d)
- AboutPage - read license text modal [`c0328c5`](https://git.odit.services/lfk/frontend/commit/c0328c5cdb1edc1c3dca368d65b84e640ef4df3c)
- fixed datatable-emptystate transition [`10bf88e`](https://git.odit.services/lfk/frontend/commit/10bf88e4ba2390dbf78925f0541c49a4abe3041d)
- working on AddUserModal [`cb58fdf`](https://git.odit.services/lfk/frontend/commit/cb58fdfd8ed6c20551d99cefe37e10e9e46f13bf)
- display full user names in overview table [`6529907`](https://git.odit.services/lfk/frontend/commit/6529907a139edd8450e699a8ea9befae622137f7)
- reactivity on adding a new Track [`f37ba1d`](https://git.odit.services/lfk/frontend/commit/f37ba1dbf7cc71573bcfbc1fe09c2a4b9d0d3404)
- User Overview table expansion [`58d68c8`](https://git.odit.services/lfk/frontend/commit/58d68c8324b6306be697cde0be53f0c5caf262aa)
- basic track deletion working ✅ [`35a9aa4`](https://git.odit.services/lfk/frontend/commit/35a9aa40cbbb86bd004cf18792951dd3f81fc859)
- Track edit animation [`e5fcb2e`](https://git.odit.services/lfk/frontend/commit/e5fcb2ef68cdbc55875d5bf7f97ddfe297abe7e1)
- basic edit logic in table [`039fd8f`](https://git.odit.services/lfk/frontend/commit/039fd8f90ebccf8594c608c4cd7c8fe5178c66d0)
- ⚡ PWA optimizations [`bc66ebb`](https://git.odit.services/lfk/frontend/commit/bc66ebbf0aa2a756829b92a0869b60c093f5e7f8)
- UserDetailOne sample ui [`23e03be`](https://git.odit.services/lfk/frontend/commit/23e03bec352a9ec53cb3962b4f6ec64b0ea643ad)
- improved sidebar icons [`5c218c6`](https://git.odit.services/lfk/frontend/commit/5c218c64abc3e54fcc00ba996a9b4749d3340c75)
- added Breadcrumb nav to UserDetail [`11457b2`](https://git.odit.services/lfk/frontend/commit/11457b2792dca55225280854456481b7c6978071)
- basic ForgotPassword improvements [`e8c98a0`](https://git.odit.services/lfk/frontend/commit/e8c98a0a29518063d4f573a3c6a1055f3bf18906)
- 🎨 general page styles [`02d8888`](https://git.odit.services/lfk/frontend/commit/02d8888d97da0125d47269bd8526c94535ff1efd)
- AddTrackModal - basic validation w/ class + layout responses [`591dc09`](https://git.odit.services/lfk/frontend/commit/591dc09228408f4fff0349a42807c1d6268a59e3)
- general dependency bump ⏫ [`6e4fe37`](https://git.odit.services/lfk/frontend/commit/6e4fe37378ab4af8e438fa7d0c7cf43fc45b2c99)
- edit is working 🎉 [`68de076`](https://git.odit.services/lfk/frontend/commit/68de0762271eb9dbe0e7135f6457cf0b09d889d6)
- move serviceworker registration to separate module [`8f25a87`](https://git.odit.services/lfk/frontend/commit/8f25a874cb2f7fc3181c356514e9e6c11136c9bc)
- 🌍 i18n [`8443085`](https://git.odit.services/lfk/frontend/commit/84430854df8581b43eb48a153b52030cb1b384f1)
- AddTrackModal action [`501bf7a`](https://git.odit.services/lfk/frontend/commit/501bf7a5f4895f5b821abfe62830602171a57655)
- 🌍 translations [`48ddc62`](https://git.odit.services/lfk/frontend/commit/48ddc621921f796a02c0bf74d5721a7851cd1523)
- general cleanups [`5b15141`](https://git.odit.services/lfk/frontend/commit/5b15141ecc0a5ed6a689e739b0f8990be244fa53)
- 🐞👀 visual fix in Footer component [`0c7bc07`](https://git.odit.services/lfk/frontend/commit/0c7bc07d67f7449e51bbb3d5f1f7af3241aa2839)
- include minimum lap times [`7210f1b`](https://git.odit.services/lfk/frontend/commit/7210f1b947de01ca6f3ebad600744fd49b0a561f)
- general + PWA optimizations [`43ecd83`](https://git.odit.services/lfk/frontend/commit/43ecd83213abe401f324e058bd255ce0b76f553c)
- improved order script for scalability [`947482c`](https://git.odit.services/lfk/frontend/commit/947482c1b51ad1b5a055eddf112e6aa6b88f5939)
- i18n 🌍 [`1c2636d`](https://git.odit.services/lfk/frontend/commit/1c2636d6693cafe9011d24c1cbdefc9a3eaa008c)
- delete confirmation [`7d1b519`](https://git.odit.services/lfk/frontend/commit/7d1b51918f5fee8791d1bd4e36056c4d979a2a96)
- Component + Login cleanup [`b111463`](https://git.odit.services/lfk/frontend/commit/b1114634e804b0f41b80c87afa6903ffc17f575c)
- AddTrackModal - more input validation response [`fe297f6`](https://git.odit.services/lfk/frontend/commit/fe297f67795c35f3ea0e9a88b8453b27a4de05e0)
- UserOverview cleanup [`71c7611`](https://git.odit.services/lfk/frontend/commit/71c761187f0e645ef06808fac930045589cb7c1a)
- AddTrackModal - minlaptime validation [`bb0eb6d`](https://git.odit.services/lfk/frontend/commit/bb0eb6d1e276186af2c1e5d26abda4413c278981)
- AddTrackModal - add track icon [`7bb5a18`](https://git.odit.services/lfk/frontend/commit/7bb5a18527994f4fe3f23a87106a431f1ebfe7d1)
- StatCards direct linking to detail page [`9527167`](https://git.odit.services/lfk/frontend/commit/9527167fbc8774d57fce206b40800f249fd50ed8)
- added basic release-it config [`52a19c2`](https://git.odit.services/lfk/frontend/commit/52a19c2036e6d928c790f914f53ebd614d0e1bea)
- move FormLayout component to Settings Page [`9309ea9`](https://git.odit.services/lfk/frontend/commit/9309ea9a30a062ecb6ddc4152174ca9371fd32b8)
- logic cleanup 🧠 [`59d5ad5`](https://git.odit.services/lfk/frontend/commit/59d5ad5bd32ad45ccfb50ab4ae4dfe47db182113)
- use outsideclick custom directive in AddTrackModal component [`2657f30`](https://git.odit.services/lfk/frontend/commit/2657f30cf3acaa592408d2d4cddcb02bf76bb6af)
- 🐳 added Docker buildsteps for sw generation [`aaef97d`](https://git.odit.services/lfk/frontend/commit/aaef97dd431d27dbab023fd05c281b8b35a1b6df)
- improved empty state [`6e00ac8`](https://git.odit.services/lfk/frontend/commit/6e00ac8f1f9bcc9ac714177c5ab2d1d04854aaa5)
- AddTrackModal padding style [`d830727`](https://git.odit.services/lfk/frontend/commit/d830727036a5bf0f7d81efba2d15ac4394ea82e4)
- added general PromiseError component [`9e19c48`](https://git.odit.services/lfk/frontend/commit/9e19c482584062380403d505be28c1ce13a7f442)
- basic formatting script [`f9aa262`](https://git.odit.services/lfk/frontend/commit/f9aa262cab64596185323dbf5fb96e70019bf126)
- 🌍 i18n lap time [`dadccc1`](https://git.odit.services/lfk/frontend/commit/dadccc1b5f7e38adeae8c988efe1ad63252f7599)
- added routing to UserDetail page [`3c4a109`](https://git.odit.services/lfk/frontend/commit/3c4a10944ebcf7a627f2749e21572342059452da)
- added outsideclick as custom directive [`a042c8a`](https://git.odit.services/lfk/frontend/commit/a042c8a870323262803989df840f15c351393a24)
- added middlename input field to mock [`8cf73a2`](https://git.odit.services/lfk/frontend/commit/8cf73a2be0ae5cb842d78ae2071fdc54bb18c4bc)
- re-enable Tailwind compile with postcss [`6915123`](https://git.odit.services/lfk/frontend/commit/6915123973460fea5a7e6934404dc5906114a812)
- display profilepic properly [`4fd1ac2`](https://git.odit.services/lfk/frontend/commit/4fd1ac28c58366d6d719942a2953d093b3829a01)
- general dependency bump ⏫ [`f7d7b83`](https://git.odit.services/lfk/frontend/commit/f7d7b837c457e6ed324f3512979506e96386b207)
- Login Component Accessibility 👀 [`fc5c8d1`](https://git.odit.services/lfk/frontend/commit/fc5c8d13093023632129134cbae702cd840e95c2)
- NGINX config - enable brotli compression [`1f50574`](https://git.odit.services/lfk/frontend/commit/1f5057438fa75e3c5ff3fd76f4bb52658f4b74ec)
- remove duplicate class usage in Dash Component [`dbc660c`](https://git.odit.services/lfk/frontend/commit/dbc660c48e33d98b8c7e0c5ddb33729c0cc54799)
- ❌ escape key support [`0c3e74f`](https://git.odit.services/lfk/frontend/commit/0c3e74f8a3f04997faa3f1aa10926f09972ac3f6)
- 🚀RELEASE v0.1.0 [`1aac783`](https://git.odit.services/lfk/frontend/commit/1aac783df351526787ba8aff12c013a8ab06524f)
- ▶ ENTER key submit [`80d30a8`](https://git.odit.services/lfk/frontend/commit/80d30a8e5425f4041e79c299095c36386b8d7777)
- EmptyState fixup [`02bfecd`](https://git.odit.services/lfk/frontend/commit/02bfecd54015ad6c6de25c246552feeab5c084ef)
- 🎨 OrgDetail style fix [`3a702aa`](https://git.odit.services/lfk/frontend/commit/3a702aa91e768ab58e017d859732fcac960edac6)
- re-added missing i18n keys [`17e7778`](https://git.odit.services/lfk/frontend/commit/17e7778d15380a2bd3d2f0bb38ed9c69bcb0bdce)
- ⏫ bump to @odit/license-exporter@0.0.9 for version support [`919910d`](https://git.odit.services/lfk/frontend/commit/919910d4a8c7ee2876b51de78b72311230476a32)
- AddTrackModal - autofocus on modal open [`388fc8f`](https://git.odit.services/lfk/frontend/commit/388fc8f239560be221687c69bfbffd9e1b3e56e1)
- AddTrackModal - trap focus if active [`0e7640b`](https://git.odit.services/lfk/frontend/commit/0e7640bf86b6710d01cd6c553f205cad934f58bb)
- ⏫ bump lfk client [`236aba8`](https://git.odit.services/lfk/frontend/commit/236aba89c2967c38402b909e65ad724e27144f17)
- ⏫ dependency bump [`ba87349`](https://git.odit.services/lfk/frontend/commit/ba87349a88a54152874b6a30218042a676799c68)
- 🌍 i18n [`281747a`](https://git.odit.services/lfk/frontend/commit/281747a681624ecaeee902910f1ff3c52f9e3155)
- move OpenAPI config to App component rather than Login [`b107f5d`](https://git.odit.services/lfk/frontend/commit/b107f5de95489b02fe73e8fdc2836b02d1d29d02)
- NGINX config - fix 404 error for SPA usage [`32e4f22`](https://git.odit.services/lfk/frontend/commit/32e4f223f89d2b58ffc2466aded008fa1c948290)
- 🐞fixed snowpack config for bundle optimization [`3e8d0b5`](https://git.odit.services/lfk/frontend/commit/3e8d0b54627f175bfe29bfc14308fa433e2c72af)
- 🐞 fix malfuntion in logout logic [`7cf2ffc`](https://git.odit.services/lfk/frontend/commit/7cf2ffce2d2b7905388169a9c38462337699b5e5)
- actually perform user logout (recreate Cookies, invalidate token) [`2048533`](https://git.odit.services/lfk/frontend/commit/2048533fda6da6fdc0aeb0f42f3c6a66d7e87911)
- proper middlename display support [`644b9a7`](https://git.odit.services/lfk/frontend/commit/644b9a76836c626fb3581a352ae53c72cd99b5b0)
- ignore licenses.json in serviceworker [`c38d33a`](https://git.odit.services/lfk/frontend/commit/c38d33a549143143d08ccbe5b82f14174eaebf70)
- dependency bump ⏫ [`9aeb99d`](https://git.odit.services/lfk/frontend/commit/9aeb99d775e1bb7a8a26d68836dd8d4a4b085406)
- Dashboard - fix accessibility focus state on nav Dropdown + Logout [`44029c8`](https://git.odit.services/lfk/frontend/commit/44029c812eebe3ee591dc2133c35082c5b3de41f)
- move toastify css to app base [`34ecb8b`](https://git.odit.services/lfk/frontend/commit/34ecb8b2fb19d243db35bd59f98d93f08d522f25)
- ⏫ tinro dependency bump [`e62277b`](https://git.odit.services/lfk/frontend/commit/e62277bdd2492119dd78a41d6cb3c415c7ce69b8)
- new layout margin from page title [`51c9c3f`](https://git.odit.services/lfk/frontend/commit/51c9c3fe3c7dc3d6f4d5665e3eac1fbc6f837659)
- add basic package script [`e361c89`](https://git.odit.services/lfk/frontend/commit/e361c89f6c6b719e4a7fa1b0db23885249cd3b2b)
- added release-it dev dependency [`0023e22`](https://git.odit.services/lfk/frontend/commit/0023e225243af7b6e2d85ee18522ee7f67828b73)
- AddTrackModal - placeholder input [`d45eec9`](https://git.odit.services/lfk/frontend/commit/d45eec94ab7386ef29170b03e73c7683b36a3a0d)
- add package script [`1cd03ef`](https://git.odit.services/lfk/frontend/commit/1cd03ef02748f55b8e66e5e26b3e2be64b659313)
- track lap time interactive placeholder [`008c91a`](https://git.odit.services/lfk/frontend/commit/008c91a5526edc51d4995565f1681f300f980b51)
- Merge commit '3a702aa91e768ab58e017d859732fcac960edac6' into feature/11-tracks-management [`8af63fc`](https://git.odit.services/lfk/frontend/commit/8af63fc22a47959859153f8e742df86f73b9be54)
- init [`32357ec`](https://git.odit.services/lfk/frontend/commit/32357ece0a7195ea1135c9c3e4c6c84323f95b4d)
- tmp [`1b7173c`](https://git.odit.services/lfk/frontend/commit/1b7173cda9134ee8058a00bdc030defa80d46bfc)
- Login - move to env.js import [`8ef0b21`](https://git.odit.services/lfk/frontend/commit/8ef0b21819309752c573d0485f6514152fb684e6)
- initial commit [`4bb3bae`](https://git.odit.services/lfk/frontend/commit/4bb3bae4e6fc89c35a8a2b36b7cd6e6d47958eae)
- Initial license export [`4c96b9a`](https://git.odit.services/lfk/frontend/commit/4c96b9a3e04dbb7c021c71aa8828a29248509fbe)
- 🚚 move to tinro svelte router [`a50ea15`](https://git.odit.services/lfk/frontend/commit/a50ea15b38023b867a9f7757e973184cbcdd2457)
- new Dashboard [`7270ce9`](https://git.odit.services/lfk/frontend/commit/7270ce9d32869abd4f6ac65ab7c2c87363633cbe)
- Tracks sample page w/ modal [`c2cf8a0`](https://git.odit.services/lfk/frontend/commit/c2cf8a098974c6f2e75690a5f767a8282fd95789)
- Profile page [`d580522`](https://git.odit.services/lfk/frontend/commit/d5805229b3dfed37a3a210fcbcc1435fe1b6952e)
- PwReset view [`98bc810`](https://git.odit.services/lfk/frontend/commit/98bc810e515fc04192e6058e0dce272a2e34e76a)
- StatCards - fetch real data from API [`3d93b04`](https://git.odit.services/lfk/frontend/commit/3d93b04264e99f4717e48e68136a08c85e54d4a0)
- general UI cleanup [`0e5fbb8`](https://git.odit.services/lfk/frontend/commit/0e5fbb8835331966c23522d831be2a6a08ae123f)
- Dashboard component cleanup [`89fcfe6`](https://git.odit.services/lfk/frontend/commit/89fcfe6a4903f77360257883b11fce689de9f5cb)
- improved About page + route [`45cd532`](https://git.odit.services/lfk/frontend/commit/45cd532c1ae322759b7fe5393bb27c17c3c03f83)
- 🌎 first i18n support [`2c77450`](https://git.odit.services/lfk/frontend/commit/2c774508848d918b0348cac5c81c376952c07ae5)
- i18n fix + more pages [`4633a9b`](https://git.odit.services/lfk/frontend/commit/4633a9b3aeec136ad6f434fa46a3925b37ac5524)
- i18n compatible datatable [`3c36bea`](https://git.odit.services/lfk/frontend/commit/3c36bea07cdd2bf690e93fe8ddfbf5be62ddc7cb)
- more translations [`1dc4983`](https://git.odit.services/lfk/frontend/commit/1dc498302f9ab0563187439a7c207b00f0af3acb)
- tmp [`8ff1c55`](https://git.odit.services/lfk/frontend/commit/8ff1c55ba4e52f36931eb53aaa18021a1b894a7a)
- Tags [`3bd954e`](https://git.odit.services/lfk/frontend/commit/3bd954e9ffe558495427b899e0f33baffc9d227d)
- About page [`a977b34`](https://git.odit.services/lfk/frontend/commit/a977b34adbf5b95b8813ab0a18252dab7f3a8a75)
- ForgotPassword page [`25e62f0`](https://git.odit.services/lfk/frontend/commit/25e62f09075dbb0150d48698d8dd4ba4bb9530e3)
- Sidebar [`4765fae`](https://git.odit.services/lfk/frontend/commit/4765faeddc3e90c3d8696595f1db223c97e4b890)
- ✨ Avatars [`7e69eee`](https://git.odit.services/lfk/frontend/commit/7e69eeef295901749dcb2a9b5d57a40959288fa4)
- 🖼 new icons + i18n for card titles [`4f02a5b`](https://git.odit.services/lfk/frontend/commit/4f02a5bac0b12f89cfa95e8effc65d5b9cdad732)
- basic dependencies + first layout [`3ce8284`](https://git.odit.services/lfk/frontend/commit/3ce82840783e24ed605837fbde76f5562f1256c1)
- 💡 sample card layout + data [`20ee0c1`](https://git.odit.services/lfk/frontend/commit/20ee0c1a9efe588a8a24d47cc345c24e76c02e6f)
- Breadcrumb component [`815e07c`](https://git.odit.services/lfk/frontend/commit/815e07c13262607f2f0e701423b8b85d7996cf9c)
- ✨ Badges [`2fa102b`](https://git.odit.services/lfk/frontend/commit/2fa102b5430cbd57dfb63823450c15abd71bbd3b)
- first working router 🎉 [`b4d1370`](https://git.odit.services/lfk/frontend/commit/b4d13701a7ee16ad0281271b233eb03632673ffc)
- Dashboard code cleanup [`9b036de`](https://git.odit.services/lfk/frontend/commit/9b036de4d7adce065ff454b3183dcd78866a2363)
- 💾 login state preserve (localstorage) + JWT payload parsing [`13ccb56`](https://git.odit.services/lfk/frontend/commit/13ccb56354135704834ffade8085ddbc8c03b369)
- profile actions dropdown [`a80d3b0`](https://git.odit.services/lfk/frontend/commit/a80d3b060faad61f625776e23739f4b2837927c5)
- Added drone file with pipeline for dev [`9bf21a0`](https://git.odit.services/lfk/frontend/commit/9bf21a0eeb6d32cab18dcbb55f571969773fffac)
- DataTable [`d293859`](https://git.odit.services/lfk/frontend/commit/d2938591bf157e88acfd274ff1dfd527a1ce8588)
- 🚧 move to new config based env [`2cdd1cd`](https://git.odit.services/lfk/frontend/commit/2cdd1cd96196f586abfa50ba2f2b05f99545c669)
- Dashboard - dropdown arrow change [`b27fb8c`](https://git.odit.services/lfk/frontend/commit/b27fb8c0b5532710c97947731f0725e37f13c579)
- filepond integration ✅ [`ada6888`](https://git.odit.services/lfk/frontend/commit/ada68887a2e6a4a552c1d093f5ec1afaebd918d3)
- more translations [`186803f`](https://git.odit.services/lfk/frontend/commit/186803f8216c991927d8f5c8ec6aa19016267858)
- general cleanups [`428d2e2`](https://git.odit.services/lfk/frontend/commit/428d2e25790e7509c535970accbe9f79fbf6ab65)
- 🐳 move to new + simple Dockerfile [`9202b47`](https://git.odit.services/lfk/frontend/commit/9202b473f579c50f9a0b269ee2ef9530cd690d2c)
- TracksOverview route [`f3f318f`](https://git.odit.services/lfk/frontend/commit/f3f318fd01372eea1edff265d678f1a03e252377)
- Sidebar - UX logic w/ interactivity [`773800e`](https://git.odit.services/lfk/frontend/commit/773800e73203d438fe2f3e8245b6d13e9407f996)
- Login component - enter key listener [`016f08b`](https://git.odit.services/lfk/frontend/commit/016f08b07cf2b40a53a57642d7bc75ebd669feab)
- 🐳 new Dockerfile [`33d8622`](https://git.odit.services/lfk/frontend/commit/33d8622eb27d284dddb9bc14740e7a90b4b809d5)
- AddTrackModal cleanup [`f5d0e28`](https://git.odit.services/lfk/frontend/commit/f5d0e285fb3a913b7a26bf2ce7b7621502b68e49)
- Footer component cleanup [`05306c7`](https://git.odit.services/lfk/frontend/commit/05306c75a555d38adad3f3fc4a4d3bd1211c626c)
- ♻️ drop svelte-spa-router [`46491f3`](https://git.odit.services/lfk/frontend/commit/46491f38a0cf8d2ef3ceac00ce1be289a594eade)
- 🚧 working on sidebar [`e4c6c57`](https://git.odit.services/lfk/frontend/commit/e4c6c5711d55e8acb4366cebbd9c8b7c45741c5e)
- added webmanifest 🧾 [`de7cd12`](https://git.odit.services/lfk/frontend/commit/de7cd1267df684b5befd6111aa347e76c6f2ffdd)
- basic service worker registration via workbox [`13b6b32`](https://git.odit.services/lfk/frontend/commit/13b6b320411a4fda24c49cdec5fd890d09d02c9c)
- more i18n usage + logo [`d817058`](https://git.odit.services/lfk/frontend/commit/d817058e515cf79c782446c4b8c9443b15211523)
- ✨ Tabs [`e6815eb`](https://git.odit.services/lfk/frontend/commit/e6815eb75f45b56a8404a24d0d96b3e79ba73834)
- Dashboard - use sample components [`b2b05a4`](https://git.odit.services/lfk/frontend/commit/b2b05a4ec9f565ec92ebbf84ad4ed5f1eb80cbfe)
- Tracks page cleanup [`9af4cfe`](https://git.odit.services/lfk/frontend/commit/9af4cfe73f92f28e42c0d2bd83f687be16d4b8f0)
- Track page cleanup [`72f1645`](https://git.odit.services/lfk/frontend/commit/72f1645767ab57a6ce94bbe80eff2858a113bace)
- first language support [`35d379d`](https://git.odit.services/lfk/frontend/commit/35d379d84303cfb119c8df97d8ad0222e9749826)
- cleaned up Login component for darkmode compatibility [`040359a`](https://git.odit.services/lfk/frontend/commit/040359aa933bdfd3d2119229d29c95aa5a308a86)
- Tracks datatable action ui [`9975c0c`](https://git.odit.services/lfk/frontend/commit/9975c0cf64c356c30e229127bfa6d04df1b41a4a)
- hash based routing in env file [`3396d17`](https://git.odit.services/lfk/frontend/commit/3396d173586a6bb9518d07e4f9d84b6ba0bcf4b9)
- 🌎 translations [`0ff0a29`](https://git.odit.services/lfk/frontend/commit/0ff0a29dfe73c38b1c0c2dfb9b1e92a1b90e6c9c)
- dependency bumps ⏫ [`0dc8bff`](https://git.odit.services/lfk/frontend/commit/0dc8bffaec36b5f0419f84ee5722805b0d329f86)
- 🧠 logic cleanup in Login component [`90be420`](https://git.odit.services/lfk/frontend/commit/90be4200ca2578fe6b7f516b6c2b427e4875694a)
- demo login [`5499669`](https://git.odit.services/lfk/frontend/commit/5499669564801aab526a54cac4dca154e0fac6a4)
- [tmp] - move to cdn usage [`1473267`](https://git.odit.services/lfk/frontend/commit/1473267e8c7fd303c67ae8044c9846cd5ec94f9c)
- 🧹 drop nanoid dependency [`71b6258`](https://git.odit.services/lfk/frontend/commit/71b6258bc36576b4d9ad61556661ba299831e988)
- updated Dockerfile for snowpack ❄ [`6f787f6`](https://git.odit.services/lfk/frontend/commit/6f787f63f7530d6da94195e0e148b97f581b0bed)
- add Tracks route to app [`728dd40`](https://git.odit.services/lfk/frontend/commit/728dd40f16f11dd80275388cff75e2971172eb5a)
- small bugfix [`b9410dc`](https://git.odit.services/lfk/frontend/commit/b9410dc5f1611f274c882e74312e2187757be246)
- 🌍 i18n - general_promise_error [`f1b2c1d`](https://git.odit.services/lfk/frontend/commit/f1b2c1de267dd0388de293e481d2739a3eb64d38)
- move filepond import to css-in-js [`e48502f`](https://git.odit.services/lfk/frontend/commit/e48502fb41f483685e24b8d054406a8cc7459451)
- Dashboard - demo urls [`c65c138`](https://git.odit.services/lfk/frontend/commit/c65c138830f883d85c897478dc1c44ef527f195e)
- gitignore yarn.lock package-lock.json [`112516c`](https://git.odit.services/lfk/frontend/commit/112516ccfd6f00014c611cc14bf5a4bb431a9bca)
- ⏫ dependency bump [`1104ab2`](https://git.odit.services/lfk/frontend/commit/1104ab20c7de0ab5c97e0dc636835b2a4e25ed6b)
- Updated dev branch name [`b538b6c`](https://git.odit.services/lfk/frontend/commit/b538b6cb7103b47ef7bc34c04087580918c09f6d)
- Added script for license export [`1fba3ef`](https://git.odit.services/lfk/frontend/commit/1fba3ef9e43f3d9302409446d6ed2a641e554d7c)
- added translations 🌍 [`b4df123`](https://git.odit.services/lfk/frontend/commit/b4df123c0402ab7ae42fd8289ae9bb2f3fff9d5e)
- ✨ NotFound [`d188ae6`](https://git.odit.services/lfk/frontend/commit/d188ae658af7541764d34884e8ca67a59f0955c2)
- DataTable - load from json object [`a379327`](https://git.odit.services/lfk/frontend/commit/a379327d67ba5e9bab1724cf7e170c01166b4d64)
- ⏫ dependency bump svelte [`905d8b0`](https://git.odit.services/lfk/frontend/commit/905d8b0a201631cdca462a8a33d5fd394db36305)
- favicon + title [`d2b2542`](https://git.odit.services/lfk/frontend/commit/d2b254241295fa177af01a9f2f0fb747a7f9f02e)
- 🎨 TailwindStyles - Chromium fix [`9fbe1c7`](https://git.odit.services/lfk/frontend/commit/9fbe1c7c6cce21ba536128ceaa35b72c7841f67f)
- 👋 sample user info usage on dashboard [`813c058`](https://git.odit.services/lfk/frontend/commit/813c058a9a805bc2f63586e50c5b949d33406654)
- 🔧 re-enable jwtinfo userdetails in Dashboard [`12eb207`](https://git.odit.services/lfk/frontend/commit/12eb207605f69598a9a2308cf9b1c2d4916f8cb3)
- Dependency: Bumped license-exporter version [`0842640`](https://git.odit.services/lfk/frontend/commit/0842640fec285a3d99f0c7551f008919e64e5dcd)
- move StatCards up in Dashboard UI [`e9a6637`](https://git.odit.services/lfk/frontend/commit/e9a6637eb9f303dc93dbbc3287f9b7b4d92ed42a)
- 🐞 translation fix [`517c638`](https://git.odit.services/lfk/frontend/commit/517c6381bae270346c8ba60dd3287d96d17d4bf3)
- Dashboard - hide overflow [`4c161b3`](https://git.odit.services/lfk/frontend/commit/4c161b3c7067ed042deeea3bea0ef24b306c94a1)
- ⏫ bump client to 0.0.5 [`9633a09`](https://git.odit.services/lfk/frontend/commit/9633a09b730be91c31419cd8bfcea108c82976d3)
- ⏫ Bump snowpack to 3.0.0-rc.2 🧪❄ [`9a53e32`](https://git.odit.services/lfk/frontend/commit/9a53e326917bc1b9756baf2ce511447974779c8f)
- ✒ package rename [`937d044`](https://git.odit.services/lfk/frontend/commit/937d044b59095192859d516fbf60c04b057562be)
- add theme color to index [`fe40fd9`](https://git.odit.services/lfk/frontend/commit/fe40fd9a91f634046a974a90986e915ee3c53cc0)

View File

@@ -3,11 +3,17 @@ WORKDIR /app
RUN npm i -g pnpm RUN npm i -g pnpm
COPY package.json ./ COPY package.json ./
RUN pnpm i RUN pnpm i
COPY package.json *.config.js ./ COPY package.json *.config.js workbox-config.js ./
COPY src ./src COPY src ./src
COPY public ./public COPY public ./public
RUN pnpm run build:sw
RUN pnpm run build RUN pnpm run build
# final image # final image
FROM alpine
COPY --from=0 /app/build /app
RUN rm -rf /app/build/_dist_/components
RUN rm -rf /app/build/_dist_/locales
RUN rm -rf /app/build-manifest.json
FROM fholzer/nginx-brotli:v1.19.1 FROM fholzer/nginx-brotli:v1.19.1
COPY --from=0 /app/build /usr/share/nginx/html COPY --from=1 /app /usr/share/nginx/html
COPY ./nginx.conf /etc/nginx/nginx.conf COPY ./nginx.conf /etc/nginx/nginx.conf

View File

@@ -6,16 +6,19 @@ http {
server { server {
error_page 404 /index.html; error_page 404 /index.html;
root /usr/share/nginx/html; root /usr/share/nginx/html;
location / {
try_files $uri $uri/ /index.html;
}
location ~* \.(?:ico|css|js|gif|jpe?g|png)$ { location ~* \.(?:ico|css|js|gif|jpe?g|png)$ {
expires 1y; expires 1y;
add_header Pragma public; add_header Pragma public;
add_header Cache-Control "public"; add_header Cache-Control "public";
} }
# --- Brotli # --- Brotli
# brotli on; brotli on;
# brotli_comp_level 6; brotli_comp_level 6;
# brotli_static on; brotli_static on;
# brotli_types application/atom+xml application/javascript application/json application/rss+xml application/vnd.ms-fontobject application/x-font-opentype application/x-font-truetype application/x-font-ttf application/x-javascript application/xhtml+xml application/xml font/eot font/opentype font/otf font/truetype image/svg+xml image/vnd.microsoft.icon image/x-icon image/x-win-bitmap text/css text/javascript text/plain text/xml; brotli_types application/atom+xml application/javascript application/json application/rss+xml application/vnd.ms-fontobject application/x-font-opentype application/x-font-truetype application/x-font-ttf application/x-javascript application/xhtml+xml application/xml font/eot font/opentype font/otf font/truetype image/svg+xml image/vnd.microsoft.icon image/x-icon image/x-win-bitmap text/css text/javascript text/plain text/xml;
# --- GZIP # --- GZIP
gzip on; gzip on;
gzip_disable "msie6"; gzip_disable "msie6";

16
order.js Normal file
View File

@@ -0,0 +1,16 @@
const fs = require('fs');
// get all language files
const files = fs.readdirSync('./src/locales/');
files.forEach((f) => {
// read file as object
const unordered = JSON.parse(fs.readFileSync(`src/locales/${f}`));
// order object by keys alpabetically A-Z
const ordered = Object.keys(unordered).sort().reduce((obj, key) => {
obj[key] = unordered[key];
return obj;
}, {});
// format output as json for commit diff compatibility
const out = JSON.stringify(ordered, 0, 4);
// write output file
fs.writeFileSync(`src/locales/${f}`, out);
});

View File

@@ -1,29 +1,57 @@
{ {
"name": "@odit/lfk-frontend", "name": "@odit/lfk-frontend",
"version": "0.0.0", "version": "0.1.5",
"scripts": { "scripts": {
"i18n-order": "node order.js",
"dev": "snowpack dev", "dev": "snowpack dev",
"build": "snowpack build" "build": "snowpack build",
"build:sw": "workbox generateSW workbox-config.js",
"release": "release-it",
"changelog": "npx auto-changelog --commit-limit false --template https://raw.githubusercontent.com/release-it/release-it/master/templates/changelog-compact.hbs",
"licenses:export": "license-exporter --json -o public"
}, },
"dependencies": { "dependencies": {
"@odit/lfk-client-js": "0.0.6", "@odit/lfk-client-js": "0.0.10",
"filepond": "^4.25.1", "filepond": "4.25.1",
"gridjs": "^3.2.1", "gridjs": "3.2.1",
"localforage": "^1.9.0", "localforage": "1.9.0",
"svelte-filepond": "^0.0.1", "lodash.isequal": "^4.5.0",
"svelte-i18n": "^3.3.0", "svelte-filepond": "0.0.1",
"tailwindcss": "^2.0.2", "svelte-focus-trap": "1.0.1",
"tinro": "^0.4.10", "svelte-i18n": "3.3.0",
"toastify-js": "^1.9.3", "tailwindcss": "2.0.2",
"validator": "^13.5.2" "tinro": "0.5.6",
"toastify-js": "1.9.3",
"validator": "13.5.2"
}, },
"devDependencies": { "devDependencies": {
"@snowpack/plugin-svelte": "^3.4.1", "@odit/license-exporter": "0.0.9",
"autoprefixer": "^10.1.0", "@snowpack/plugin-svelte": "3.4.1",
"postcss": "^8.2.2", "auto-changelog": "^2.2.1",
"postcss-load-config": "^3.0.0", "autoprefixer": "10.2.1",
"postcss": "8.2.4",
"postcss-load-config": "3.0.0",
"release-it": "^14.2.2",
"snowpack": "3.0.0-rc.2", "snowpack": "3.0.0-rc.2",
"svelte": "^3.31.0", "svelte": "3.31.2",
"svelte-preprocess": "^4.6.1" "svelte-preprocess": "4.6.1",
"workbox-cli": "6.0.2"
},
"release-it": {
"git": {
"commit": true,
"requireCleanWorkingDir": false,
"commitMessage": "🚀RELEASE v${version}",
"push": false,
"tag": true,
"tagName": null,
"tagAnnotation": "v${version}"
},
"npm": {
"publish": false
},
"hooks": {
"after:bump": "npx auto-changelog --commit-limit false -p -u --hide-credit && git add CHANGELOG.md && node versionbuilder.js && git add public/index.html"
}
} }
} }

View File

@@ -1,7 +1,5 @@
const config = { const config = {
baseurl: 'http://localhost:4010', baseurl: 'http://localhost:4010',
// optional params ⏬ // optional
fallback_username: 'demo',
fallback_password: 'demo',
prefersHashRouting: true prefersHashRouting: true
}; };

View File

@@ -5,14 +5,15 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<link rel="icon" href="/favicon.png" /> <link rel="icon" href="/favicon.png" />
<link rel="manifest" href="/manifest.webmanifest"> <link rel="manifest" href="/manifest.webmanifest">
<link rel="apple-touch-icon" href="/lfk-logo.png">
<meta name="theme-color" content="#FFFFFF"> <meta name="theme-color" content="#FFFFFF">
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="Lauf Für Kaya! - Admin" /> <meta name="description" content="Lauf Für Kaya! - Admin" />
<title>Lauf für Kaya! - Admin</title> <title>Lauf für Kaya! - Admin</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/tailwindcss@2.0.2/dist/tailwind.min.css">
</head> </head>
<body> <body>
<span style="display: none;visibility: hidden;" id="buildinfo">RELEASE_INFO-0.1.5-RELEASE_INFO</span>
<noscript>You need to enable JavaScript to run this app.</noscript> <noscript>You need to enable JavaScript to run this app.</noscript>
<script src="/env.js"></script> <script src="/env.js"></script>
<script defer type="module" src="/_dist_/index.js"></script> <script defer type="module" src="/_dist_/index.js"></script>

BIN
public/lfk-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

1
public/licenses.json Normal file

File diff suppressed because one or more lines are too long

View File

@@ -4,6 +4,7 @@
"start_url": ".", "start_url": ".",
"display": "standalone", "display": "standalone",
"background_color": "#fff", "background_color": "#fff",
"theme_color": "#fff",
"description": "Lauf für Kaya! - Admin", "description": "Lauf für Kaya! - Admin",
"icons": [ "icons": [
{ {
@@ -15,6 +16,12 @@
"src": "/favicon.png", "src": "/favicon.png",
"sizes": "144x144", "sizes": "144x144",
"type": "image/png" "type": "image/png"
} },
{
"src": "/lfk-logo.png",
"sizes": "1540x144",
"type": "image/png"
},
{ "src": "/maskable_icon_x1.png", "sizes": "750x750", "type": "image/png", "purpose": "any maskable" }
] ]
} }

BIN
public/maskable_icon_x1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

View File

@@ -1 +1,2 @@
if(!self.define){const e=e=>{"require"!==e&&(e+=".js");let r=Promise.resolve();return s[e]||(r=new Promise((async r=>{if("document"in self){const s=document.createElement("script");s.src=e,document.head.appendChild(s),s.onload=r}else importScripts(e),r()}))),r.then((()=>{if(!s[e])throw new Error(`Module ${e} didnt register its module`);return s[e]}))},r=(r,s)=>{Promise.all(r.map(e)).then((e=>s(1===e.length?e[0]:e)))},s={require:Promise.resolve(r)};self.define=(r,i,c)=>{s[r]||(s[r]=Promise.resolve().then((()=>{let s={};const o={uri:location.origin+r.slice(1)};return Promise.all(i.map((r=>{switch(r){case"exports":return s;case"module":return o;default:return e(r)}}))).then((e=>{const r=c(...e);return s.default||(s.default=r),s}))})))}}define("./sw.js",["./workbox-c8ead010"],(function(e){"use strict";self.addEventListener("message",(e=>{e.data&&"SKIP_WAITING"===e.data.type&&self.skipWaiting()})),e.precacheAndRoute([{url:"env.js",revision:"d774a7cf97a5e7390045bcf8b304062c"},{url:"env.sample.js",revision:"83a2a360688fb3ab53c67f3137a72683"},{url:"favicon.ico",revision:"ba44f340afba5bb1a07f14decc15dd04"},{url:"favicon.png",revision:"07a9941cec62319578fa2a1734db9959"},{url:"favicon.svg",revision:"689d6c6fda51e359c0e5725d9e905064"},{url:"index.html",revision:"4c19a21d81de8fd5ca73503cec356c7c"},{url:"logo.svg",revision:"4c9e31a1f4268d7e36e22cda7656e561"},{url:"robots.txt",revision:"61c27d2cd39a713f7829422c3d9edcc7"}],{})})); if(!self.define){const e=e=>{"require"!==e&&(e+=".js");let r=Promise.resolve();return i[e]||(r=new Promise((async r=>{if("document"in self){const i=document.createElement("script");i.src=e,document.head.appendChild(i),i.onload=r}else importScripts(e),r()}))),r.then((()=>{if(!i[e])throw new Error(`Module ${e} didnt register its module`);return i[e]}))},r=(r,i)=>{Promise.all(r.map(e)).then((e=>i(1===e.length?e[0]:e)))},i={require:Promise.resolve(r)};self.define=(r,s,o)=>{i[r]||(i[r]=Promise.resolve().then((()=>{let i={};const c={uri:location.origin+r.slice(1)};return Promise.all(s.map((r=>{switch(r){case"exports":return i;case"module":return c;default:return e(r)}}))).then((e=>{const r=o(...e);return i.default||(i.default=r),i}))})))}}define("./sw.js",["./workbox-c8ead010"],(function(e){"use strict";self.addEventListener("message",(e=>{e.data&&"SKIP_WAITING"===e.data.type&&self.skipWaiting()})),e.precacheAndRoute([{url:"favicon.ico",revision:"ba44f340afba5bb1a07f14decc15dd04"},{url:"favicon.png",revision:"07a9941cec62319578fa2a1734db9959"},{url:"favicon.svg",revision:"689d6c6fda51e359c0e5725d9e905064"},{url:"index.html",revision:"931c34f3675364dcc09411aa0f223776"},{url:"logo.svg",revision:"4c9e31a1f4268d7e36e22cda7656e561"},{url:"manifest.webmanifest",revision:"75c93eb352c4877216e77b1d7f73445f"},{url:"robots.txt",revision:"61c27d2cd39a713f7829422c3d9edcc7"}],{})}));
//# sourceMappingURL=sw.js.map

File diff suppressed because one or more lines are too long

View File

@@ -10,6 +10,7 @@ module.exports = {
], ],
installOptions: { installOptions: {
/* ... */ /* ... */
sourceMap: false
}, },
devOptions: { devOptions: {
/* ... */ /* ... */
@@ -22,5 +23,8 @@ module.exports = {
}, },
alias: { alias: {
/* ... */ /* ... */
},
experiments: {
optimize: { bundle: true, minify: true }
} }
}; };

View File

@@ -1,12 +1,10 @@
<script> <script>
// import TailwindStyles from "./TailwindStyles.svelte"; import "./TailwindStyles.svelte";
import "toastify-js/src/toastify.css";
import { Route, router } from "tinro"; import { Route, router } from "tinro";
router.subscribe((routeInfo) => { router.subscribe((routeInfo) => {
console.log(routeInfo.path);
window.scrollTo(0, 0); window.scrollTo(0, 0);
}); });
console.log($router.path);
console.log(config);
if (config.prefersHashRouting) { if (config.prefersHashRouting) {
if (config.prefersHashRouting === true) { if (config.prefersHashRouting === true) {
router.useHashNavigation(); router.useHashNavigation();
@@ -43,21 +41,15 @@
import Runners from "./components/Runners.svelte"; import Runners from "./components/Runners.svelte";
import Footer from "./components/Footer.svelte"; import Footer from "./components/Footer.svelte";
import Tracks from "./components/Tracks.svelte"; import Tracks from "./components/Tracks.svelte";
import TracksOverview from "./components/TracksOverview.svelte"; import TracksOverview from "./components/TracksOverview.svelte";
import OrgDetail from "./components/OrgDetail.svelte";
import Teams from "./components/Teams.svelte";
import { OpenAPI, AuthService } from "@odit/lfk-client-js";
import UserDetail from "./components/UserDetail.svelte";
OpenAPI.BASE = config.baseurl;
import { register as registerSW } from "./swmodule";
store.init(); store.init();
// registerSW();
// if ("serviceWorker" in navigator) {
// window.addEventListener("load", () => {
// navigator.serviceWorker.register("/sw.js").then(
// (registration) => {
// console.log(`sw successful with scope: ${registration.scope}`);
// },
// (err) => {
// console.log(`sw failed: ${err}`);
// }
// );
// });
// }
</script> </script>
<Route> <Route>
@@ -75,8 +67,13 @@ import TracksOverview from "./components/TracksOverview.svelte";
<Route path="/"> <Route path="/">
<MainDashContent /> <MainDashContent />
</Route> </Route>
<Route path="/users"> <Route path="/users/*">
<Users /> <Route path="/">
<Users />
</Route>
<Route path="/:userid" let:params>
<UserDetail {params} />
</Route>
</Route> </Route>
<Route path="/tracks/*"> <Route path="/tracks/*">
<Route path="/"> <Route path="/">
@@ -87,89 +84,15 @@ import TracksOverview from "./components/TracksOverview.svelte";
<Route path="/runners"> <Route path="/runners">
<Runners /> <Runners />
</Route> </Route>
<Route path="/teams">
<Teams />
</Route>
<Route path="/orgs/*"> <Route path="/orgs/*">
<Route path="/"> <Route path="/">
<div class="bg-white p-5">
<h1>Portfolio introduction</h1>
<nav><a class="underline" href="./1">Org 1</a></nav>
</div>
<Orgs /> <Orgs />
</Route> </Route>
<Route path="/:orgid" let:params> <Route path="/:orgid" let:params>
<div class="bg-white p-5"> <OrgDetail {params} />
<div class="flex flex-row mb-4">
<div class="w-full">
<nav class="w-full flex">
<ol
class="list-none flex flex-row items-center justify-start">
<li class="mr-2 flex items-center">
<svg
stroke="currentColor"
fill="none"
stroke-width="2"
viewBox="0 0 24 24"
stroke-linecap="round"
stroke-linejoin="round"
class="h-3 w-3 stroke-current"
height="1em"
width="1em"
xmlns="http://www.w3.org/2000/svg"><path
d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
<polyline points="9 22 9 12 15 12 15 22" /></svg>
</li>
<li class="flex items-center">
<a class="mr-2" href="/">Home</a><svg
stroke="currentColor"
fill="none"
stroke-width="2"
viewBox="0 0 24 24"
stroke-linecap="round"
stroke-linejoin="round"
class="h-3 w-3 mr-2 stroke-current"
height="1em"
width="1em"
xmlns="http://www.w3.org/2000/svg"><line
x1="5"
y1="12"
x2="19"
y2="12" />
<polyline points="12 5 19 12 12 19" /></svg>
</li>
<li class="mr-2 flex items-center">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="24"
height="24"><path fill="none" d="M0 0h24v24H0z" />
<path
d="M21 20h2v2H1v-2h2V3a1 1 0 0 1 1-1h16a1 1 0 0 1 1 1v17zm-2 0V4H5v16h14zM8 11h3v2H8v-2zm0-4h3v2H8V7zm0 8h3v2H8v-2zm5 0h3v2h-3v-2zm0-4h3v2h-3v-2zm0-4h3v2h-3V7z" /></svg>
</li>
<li class="flex items-center">
<a class="mr-2" href="./">Orgs</a><svg
stroke="currentColor"
fill="none"
stroke-width="2"
viewBox="0 0 24 24"
stroke-linecap="round"
stroke-linejoin="round"
class="h-3 w-3 mr-2 stroke-current"
height="1em"
width="1em"
xmlns="http://www.w3.org/2000/svg"><line
x1="5"
y1="12"
x2="19"
y2="12" />
<polyline points="12 5 19 12 12 19" /></svg>
</li>
<li class="flex items-center">
<span class="mr-2">Org-Details #{params.orgid}</span>
</li>
</ol>
</nav>
</div>
</div>
</div>
</Route> </Route>
</Route> </Route>
<Route path="/about"> <Route path="/about">

View File

@@ -1,18 +1,92 @@
<script> <script>
import { _ } from "svelte-i18n"; import { _ } from "svelte-i18n";
import { clickOutside } from "./outsideclick";
import { focusTrap } from "svelte-focus-trap";
export let modal_open;
(function () {
document.onkeydown = function (e) {
e = e || window.event;
if (e.key === "Escape") {
modal_open = false;
}
};
})();
const license_promise = fetch("/licenses.json");
let licenses = [];
$: currentlicense = "";
$: licensetext = "";
license_promise
.then((response) => response.json())
.then((json) => {
licenses = json;
});
</script> </script>
<style> {#if modal_open}
* { <div
font-family: "Agave", sans-serif; class="fixed z-10 inset-0 overflow-y-auto"
} use:focusTrap
</style> use:clickOutside
on:click_outside={() => {
<svelte:head> modal_open = false;
<link }}>
rel="stylesheet" <div
href="https://cdn.jsdelivr.net/npm/@xz/fonts@1/serve/agave.min.css" /> class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
</svelte:head> <div class="fixed inset-0 transition-opacity" aria-hidden="true">
<div
class="absolute inset-0 bg-gray-500 opacity-75"
data-id="modal_backdrop" />
</div>
<span
class="hidden sm:inline-block sm:align-middle sm:h-screen"
aria-hidden="true">&#8203;</span>
<div
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
role="dialog"
aria-modal="true"
aria-labelledby="modal-headline">
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<div class="sm:flex sm:items-start">
<div
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10">
<svg
fill="currentColor"
class="h-6 w-6 text-blue-600"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="24"
height="24"><path fill="none" d="M0 0h24v24H0z" />
<path
d="M14 20v2H2v-2h12zM14.586.686l7.778 7.778L20.95 9.88l-1.06-.354L17.413 12l5.657 5.657-1.414 1.414L16 13.414l-2.404 2.404.283 1.132-1.415 1.414-7.778-7.778 1.415-1.414 1.13.282 6.294-6.293-.353-1.06L14.586.686z" /></svg>
</div>
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
<h3 class="text-lg leading-6 font-medium">
{$_('read-license')}
</h3>
<div class="mt-2 mb-6">
<p class="text-sm text-gray-500">{currentlicense}</p>
</div>
<div class="mt-2 mb-6">
<p class="text-sm text-gray-500">{licensetext}</p>
</div>
</div>
</div>
</div>
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<button
on:click={() => {
modal_open = false;
}}
type="button"
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">
{$_('close')}
</button>
</div>
</div>
</div>
</div>
{/if}
<!-- /// -->
<div class="pt-12 px-4 sm:px-6 lg:px-8 lg:pt-20 bg-gray-900 pb-12"> <div class="pt-12 px-4 sm:px-6 lg:px-8 lg:pt-20 bg-gray-900 pb-12">
<div class="text-center mb-8"> <div class="text-center mb-8">
<h1 <h1
@@ -33,161 +107,68 @@
</div> </div>
</div> </div>
<div class="pt-0 pb-16 bg-gray-50 overflow-hidden lg:pt-12 lg:py-24"> <div class="pt-0 pb-16 overflow-hidden lg:pt-12 lg:py-24">
<div class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8"> <div class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
<h2 class="text-4xl font-display font-semibold text-gray-900 md:text-5xl"> <h2 class="text-4xl font-display font-semibold md:text-5xl">
{$_('credits')} {$_('credits')}
</h2> </h2>
<div <div class="max-w-3xl mx-auto text-xl leading-8 font-medium mt-8">
class="max-w-3xl mx-auto text-xl leading-8 font-medium text-gray-900 mt-8">
<p class="text-center">{$_('oss_credit_description')}</p> <p class="text-center">{$_('oss_credit_description')}</p>
</div> </div>
<div class="w-screen leading-8 pl-5 mt-5"> <div class="w-screen leading-8 pl-5 mt-5">
<!-- --> {#await license_promise}
<table> <p class="text-center w-full">{$_('licenses-are-being-loaded')}</p>
<thead> {:then}
<tr> <table>
<th>name</th> <thead>
<th>licenseType</th> <tr>
<th>link</th> <th>{$_('dependency_name')}</th>
<th>installedVersion</th> <th>{$_('license')}</th>
<th>author</th> <th>{$_('repo_link')}</th>
</tr> <th>{$_('installed-version')}</th>
</thead> <th>{$_('author')}</th>
<tbody> </tr>
<tr> </thead>
<td>@odit/lfk-client-js</td> <tbody>
<td>CC-BY-NC-SA-4.0</td> {#each licenses as l}
<td>https://git.odit.services/lfk/lfk-client-js</td> <tr>
<td>0.0.5</td> <td>{l.name}</td>
<td>ODIT.Services</td> <td>
</tr> {l.license || '?'}<br /><span
<tr> class="underline cursor-pointer"
<td>filepond</td> on:click={() => {
<td>MIT</td> modal_open = true;
<td>https://github.com/pqina/filepond.git</td> currentlicense = l.name + '@' + l.version;
<td>4.25.1</td> licensetext = l.licensetext || $_('no-license-text-could-be-found');
<td>PQINA</td> }}>{$_('read-license')}</span>
</tr> </td>
<tr> <td>
<td>gridjs</td> {(l.repo?.url || l.repo)
<td>MIT</td> .replace('git+', '')
<td>https://github.com/grid-js/gridjs.git</td> .replace('git://', '')}
<td>3.2.0</td> </td>
<td>Afshin Mehrabani</td> <td>{l.version || '?'}</td>
</tr> <td>{l.author?.name || l.author || '?'}</td>
<tr> </tr>
<td>svelte-filepond</td> {/each}
<td>MIT</td> </tbody>
<td>https://github.com/pqina/svelte-filepond.git</td> </table>
<td>0.0.1</td> {:catch error}
<td>PQINA</td> <div
</tr> class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500">
<tr> <span class="inline-block align-middle mr-8">
<td>svelte-i18n</td> <b class="capitalize">{$_('general_promise_error')}</b>
<td>MIT</td> {error}
<td>https://github.com/kaisermann/svelte-i18n.git</td> </span>
<td>3.3.0</td> </div>
<td>Christian Kaisermann</td> {/await}
</tr>
<tr>
<td>tailwindcss</td>
<td>MIT</td>
<td>https://github.com/tailwindlabs/tailwindcss.git</td>
<td>2.0.2</td>
<td />
</tr>
<tr>
<td>toastify-js</td>
<td>MIT</td>
<td>https://github.com/apvarun/toastify-js.git</td>
<td>1.9.3</td>
<td>Varun A P</td>
</tr>
<tr>
<td>validator</td>
<td>MIT</td>
<td>https://github.com/chriso/validator.js.git</td>
<td>13.5.2</td>
<td>Chris O'Hara</td>
</tr>
<tr>
<td>@snowpack/plugin-svelte</td>
<td>MIT</td>
<td>https://github.com/snowpackjs/snowpack.git</td>
<td>3.4.1</td>
<td />
</tr>
<tr>
<td>autoprefixer</td>
<td>MIT</td>
<td>https://github.com/postcss/autoprefixer.git</td>
<td>10.1.0</td>
<td>Andrey Sitnik</td>
</tr>
<tr>
<td>postcss</td>
<td>MIT</td>
<td>https://github.com/postcss/postcss.git</td>
<td>8.2.1</td>
<td>Andrey Sitnik</td>
</tr>
<tr>
<td>postcss-load-config</td>
<td>MIT</td>
<td>https://github.com/postcss/postcss-load-config.git</td>
<td>3.0.0</td>
<td>Michael Ciniawky</td>
</tr>
<tr>
<td>snowpack</td>
<td>MIT</td>
<td>https://github.com/snowpackjs/snowpack.git</td>
<td>3.0.0-rc.2</td>
<td>Fred K. Schott</td>
</tr>
<tr>
<td>svelte</td>
<td>MIT</td>
<td>https://github.com/sveltejs/svelte.git</td>
<td>3.31.0</td>
<td>Rich Harris</td>
</tr>
<tr>
<td>svelte-preprocess</td>
<td>MIT</td>
<td>https://github.com/sveltejs/svelte-preprocess.git</td>
<td>4.6.1</td>
<td>Christian Kaisermann</td>
</tr>
</tbody>
</table>
<!-- -->
<!-- <ul class="list-disc text-gray-500">
<li>
Snowpack:
<a
class="underline"
href="https://snowpack.dev"
target="_blank">https://snowpack.dev</a>
</li>
<li>
SvelteJS:
<a
class="underline"
href="https://svelte.dev"
target="_blank">https://svelte.dev</a>
</li>
</ul> -->
</div> </div>
<h2 class="text-4xl font-display font-semibold text-gray-900 md:text-5xl"> <h2 class="text-4xl font-display font-semibold md:text-5xl">{$_('faq')}</h2>
Fragen
</h2>
<div class="mt-6 border-t-2 border-gray-100 pt-10"> <div class="mt-6 border-t-2 border-gray-100 pt-10">
<dl class="md:grid md:grid-cols-2 md:gap-8"> <dl class="md:grid md:grid-cols-2 md:gap-8">
<div> <div>
<div> <div>
<dt class="text-lg leading-6 font-medium text-gray-900">Q</dt> <dt class="text-lg leading-6 font-medium">Q</dt>
<dd class="mt-2"> <dd class="mt-2">
<p class="text-base text-gray-500">A</p> <p class="text-base text-gray-500">A</p>
</dd> </dd>
@@ -195,13 +176,13 @@
</div> </div>
<div class="mt-12 sm:mt-0"> <div class="mt-12 sm:mt-0">
<div id="team-pricing"> <div id="team-pricing">
<dt class="text-lg leading-6 font-medium text-gray-900">Q</dt> <dt class="text-lg leading-6 font-medium">Q</dt>
<dd class="mt-2"> <dd class="mt-2">
<p class="text-base text-gray-500">A</p> <p class="text-base text-gray-500">A</p>
</dd> </dd>
</div> </div>
<div class="mt-12"> <div class="mt-12">
<dt class="text-lg leading-6 font-medium text-gray-900">Q</dt> <dt class="text-lg leading-6 font-medium">Q</dt>
<dd class="mt-2"> <dd class="mt-2">
<p class="text-base text-gray-500">A</p> <p class="text-base text-gray-500">A</p>
</dd> </dd>

View File

@@ -1,51 +1,99 @@
<script> <script>
import { _ } from "svelte-i18n"; import { _ } from "svelte-i18n";
import { onMount } from "svelte"; import { clickOutside } from "./outsideclick";
let trackname_input; import { focusTrap } from "svelte-focus-trap";
let trackname_input_value; import { tracks as tracksstore } from "../store.js";
let tracklength; import { TrackService } from "@odit/lfk-client-js";
import Toastify from "toastify-js";
import "toastify-js/src/toastify.css";
export let modal_open; export let modal_open;
onMount(() => { let trackname_input;
// trackname_input.focus(); function focus(el) {
}); el.focus();
}
$: trackname_input_value = "";
$: track_min_duration = 0;
$: tracklength = 0;
$: processed_last_submit = true;
$: smart_track_min_duration_placeholder = parseInt(tracklength || 0) * 0.369;
$: isTracknameValid = trackname_input_value.trim().length === 0;
$: isTracklengthValid = tracklength <= 0;
$: trackMintimevalid = track_min_duration >= 0;
$: createbtnenabled = !isTracknameValid && !isTracklengthValid;
(function () {
document.onkeydown = function (e) {
e = e || window.event;
if (e.key === "Escape") {
modal_open = false;
}
if (e.keyCode === 13) {
if (createbtnenabled === true) {
createbtnenabled = false;
submit();
}
}
};
})();
function submit() { function submit() {
console.log(trackname_input_value); if (processed_last_submit === true) {
console.log(tracklength); processed_last_submit = false;
const toast = Toastify({
text: $_("track-is-being-added"),
duration: -1,
}).showToast();
TrackService.trackControllerPost({
distance: parseInt(tracklength),
name: trackname_input_value,
minimumLapTime: track_min_duration,
})
.then((result) => {
trackname_input_value = "";
track_min_duration = 0;
tracklength = 0;
modal_open = false;
//
Toastify({
text: $_("track-added"),
duration: 500,
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
}).showToast();
let storeval = [];
tracksstore.subscribe((val) => {
storeval = val;
});
storeval.push(result);
tracksstore.set(storeval);
})
.catch((err) => {
//
})
.finally(() => {
processed_last_submit = true;
//
toast.hideToast();
});
}
} }
</script> </script>
{#if modal_open} {#if modal_open}
<div class="fixed z-10 inset-0 overflow-y-auto"> <div
class="fixed z-10 inset-0 overflow-y-auto"
use:focusTrap
use:clickOutside
on:click_outside={() => {
modal_open = false;
}}>
<div <div
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"> class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<!--
Background overlay, show/hide based on modal state.
Entering: "ease-out duration-300"
From: "opacity-0"
To: "opacity-100"
Leaving: "ease-in duration-200"
From: "opacity-100"
To: "opacity-0"
-->
<div class="fixed inset-0 transition-opacity" aria-hidden="true"> <div class="fixed inset-0 transition-opacity" aria-hidden="true">
<div class="absolute inset-0 bg-gray-500 opacity-75" /> <div
class="absolute inset-0 bg-gray-500 opacity-75"
data-id="modal_backdrop" />
</div> </div>
<!-- This element is to trick the browser into centering the modal contents. -->
<span <span
class="hidden sm:inline-block sm:align-middle sm:h-screen" class="hidden sm:inline-block sm:align-middle sm:h-screen"
aria-hidden="true">&#8203;</span> aria-hidden="true">&#8203;</span>
<!--
Modal panel, show/hide based on modal state.
Entering: "ease-out duration-300"
From: "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
To: "opacity-100 translate-y-0 sm:scale-100"
Leaving: "ease-in duration-200"
From: "opacity-100 translate-y-0 sm:scale-100"
To: "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
-->
<div <div
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full" class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
role="dialog" role="dialog"
@@ -55,20 +103,15 @@
<div class="sm:flex sm:items-start"> <div class="sm:flex sm:items-start">
<div <div
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"> class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10">
<!-- Heroicon name: exclamation -->
<svg <svg
class="h-6 w-6 text-blue-600" class="h-6 w-6 text-blue-600"
xmlns="http://www.w3.org/2000/svg"
fill="none" fill="none"
viewBox="0 0 24 24" width="24"
stroke="currentColor" height="24"
aria-hidden="true"> xmlns="http://www.w3.org/2000/svg"
<path viewBox="0 0 640 512"><path
stroke-linecap="round" fill="currentColor"
stroke-linejoin="round" d="M635.7 167.2L556.1 31.7c-8.8-15-28.3-20.1-43.5-11.5l-69 39.1L503.3 161c2.2 3.8.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9L416 75l-55.2 31.3 27.9 47.4c2.2 3.8.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9L333.2 122 278 153.3 337.8 255c2.2 3.7.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9l-59.7-101.7-55.2 31.3 27.9 47.4c2.2 3.8.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9l-27.9-47.5-55.2 31.3 59.7 101.7c2.2 3.7.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9L84.9 262.9l-69 39.1C.7 310.7-4.6 329.8 4.2 344.8l79.6 135.6c8.8 15 28.3 20.1 43.5 11.5L624.1 210c15.2-8.6 20.4-27.8 11.6-42.8z" /></svg>
stroke-width="2"
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
</svg>
</div> </div>
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left"> <div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
<h3 class="text-lg leading-6 font-medium text-gray-900"> <h3 class="text-lg leading-6 font-medium text-gray-900">
@@ -85,11 +128,23 @@
for="trackname" for="trackname"
class="block text-sm font-medium text-gray-700">{$_('track-name')}</label> class="block text-sm font-medium text-gray-700">{$_('track-name')}</label>
<input <input
use:focus
autocomplete="off"
placeholder={$_('track-name')}
class:border-red-500={isTracknameValid}
class:focus:border-red-500={isTracknameValid}
class:focus:ring-red-500={isTracknameValid}
bind:value={trackname_input_value} bind:value={trackname_input_value}
bind:this={trackname_input} bind:this={trackname_input}
type="text" type="text"
name="trackname" name="trackname"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-sm border-gray-300 rounded-md" /> class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
{#if isTracknameValid}
<span
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
Track name must not be empty
</span>
{/if}
</div> </div>
<div class="col-span-6"> <div class="col-span-6">
<label <label
@@ -97,14 +152,49 @@
class="block text-sm font-medium text-gray-700">{$_('track-length-in-m')}</label> class="block text-sm font-medium text-gray-700">{$_('track-length-in-m')}</label>
<div class="mt-1 flex rounded-md shadow-sm"> <div class="mt-1 flex rounded-md shadow-sm">
<input <input
autocomplete="off"
class:border-red-500={isTracklengthValid}
class:focus:border-red-500={isTracklengthValid}
class:focus:ring-red-500={isTracklengthValid}
bind:value={tracklength} bind:value={tracklength}
type="tel" type="number"
name="track_length_m" name="track_length_m"
class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-r-md sm:text-sm border-gray-300" class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 p-2"
placeholder="1000" /> placeholder="1000" />
<span <span
class="inline-flex items-center px-3 rounded-r-md border border-l-0 border-gray-300 bg-gray-50 text-gray-500 text-sm">m</span> class="inline-flex items-center px-3 rounded-r-md border border-gray-300 bg-gray-50 text-gray-500 text-sm">m</span>
</div> </div>
{#if isTracklengthValid}
<span
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
Track length must be greater than 0
</span>
{/if}
</div>
<div class="col-span-6">
<label
for="track_min_duration"
class="block text-sm font-medium text-gray-700">{$_('minimum-lap-time-in-s')}</label>
<div class="mt-1 flex rounded-md shadow-sm">
<input
autocomplete="off"
class:border-red-500={!trackMintimevalid}
class:focus:border-red-500={!trackMintimevalid}
class:focus:ring-red-500={!trackMintimevalid}
bind:value={track_min_duration}
type="number"
name="track_min_duration"
class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 p-2"
placeholder={smart_track_min_duration_placeholder} />
<span
class="inline-flex items-center px-3 rounded-r-md border border-gray-300 bg-gray-50 text-gray-500 text-sm">s</span>
</div>
{#if !trackMintimevalid}
<span
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
minimum lap time must be a positive number or 0
</span>
{/if}
</div> </div>
</div> </div>
</div> </div>
@@ -112,6 +202,8 @@
</div> </div>
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse"> <div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<button <button
disabled={!createbtnenabled}
class:opacity-50={!createbtnenabled}
on:click={submit} on:click={submit}
type="button" type="button"
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"> class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">

View File

@@ -0,0 +1,263 @@
<script>
import { _ } from "svelte-i18n";
import { clickOutside } from "./outsideclick";
import { focusTrap } from "svelte-focus-trap";
import { tracks as tracksstore } from "../store.js";
import { UserService } from "@odit/lfk-client-js";
import isEmail from "validator/es/lib/isEmail";
import Toastify from "toastify-js";
import "toastify-js/src/toastify.css";
export let modal_open;
let firstname_input;
let lastname_input;
let middlename_input;
let password_input;
let email_input;
function focus(el) {
el.focus();
}
$: middlename_input_value = "";
$: password_input_value = "";
$: email_input_value = "";
$: lastname_input_value = "";
$: firstname_input_value = "";
$: processed_last_submit = true;
$: isPasswordValid = password_input_value.trim().length !== 0;
$: isEmailValid = isEmail(email_input_value);
$: isLastnameValid = lastname_input_value.trim().length !== 0;
$: isFirstnameValid = firstname_input_value.trim().length !== 0;
$: createbtnenabled =
isFirstnameValid && isLastnameValid && isEmailValid && isPasswordValid;
(function () {
document.onkeydown = function (e) {
e = e || window.event;
if (e.key === "Escape") {
modal_open = false;
}
if (e.keyCode === 13) {
if (createbtnenabled === true) {
createbtnenabled = false;
submit();
}
}
};
})();
function submit() {
if (processed_last_submit === true) {
processed_last_submit = false;
const toast = Toastify({
text: "User is being added...",
duration: -1,
}).showToast();
UserService.userControllerPost({
firstname: firstname_input_value,
lastname: lastname_input_value,
middlename: middlename_input_value,
email: email_input_value,
password: password_input_value,
})
.then((result) => {
firstname_input_value = "";
lastname_input_value = "";
middlename_input_value = "";
modal_open = false;
//
Toastify({
text: "User added",
duration: 500,
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
}).showToast();
let storeval = [];
tracksstore.subscribe((val) => {
storeval = val;
});
storeval.push(result);
tracksstore.set(storeval);
})
.catch((err) => {
//
})
.finally(() => {
processed_last_submit = true;
//
toast.hideToast();
});
}
}
</script>
{#if modal_open}
<div
class="fixed z-10 inset-0 overflow-y-auto"
use:focusTrap
use:clickOutside
on:click_outside={() => {
modal_open = false;
}}>
<div
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
<div
class="absolute inset-0 bg-gray-500 opacity-75"
data-id="modal_backdrop" />
</div>
<span
class="hidden sm:inline-block sm:align-middle sm:h-screen"
aria-hidden="true">&#8203;</span>
<div
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
role="dialog"
aria-modal="true"
aria-labelledby="modal-headline">
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<div class="sm:flex sm:items-start">
<div
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10">
<svg
class="h-6 w-6 text-blue-600"
fill="currentColor"
width="24"
height="24"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 640 512"><path
fill="currentColor"
d="M610.5 341.3c2.6-14.1 2.6-28.5 0-42.6l25.8-14.9c3-1.7 4.3-5.2 3.3-8.5-6.7-21.6-18.2-41.2-33.2-57.4-2.3-2.5-6-3.1-9-1.4l-25.8 14.9c-10.9-9.3-23.4-16.5-36.9-21.3v-29.8c0-3.4-2.4-6.4-5.7-7.1-22.3-5-45-4.8-66.2 0-3.3.7-5.7 3.7-5.7 7.1v29.8c-13.5 4.8-26 12-36.9 21.3l-25.8-14.9c-2.9-1.7-6.7-1.1-9 1.4-15 16.2-26.5 35.8-33.2 57.4-1 3.3.4 6.8 3.3 8.5l25.8 14.9c-2.6 14.1-2.6 28.5 0 42.6l-25.8 14.9c-3 1.7-4.3 5.2-3.3 8.5 6.7 21.6 18.2 41.1 33.2 57.4 2.3 2.5 6 3.1 9 1.4l25.8-14.9c10.9 9.3 23.4 16.5 36.9 21.3v29.8c0 3.4 2.4 6.4 5.7 7.1 22.3 5 45 4.8 66.2 0 3.3-.7 5.7-3.7 5.7-7.1v-29.8c13.5-4.8 26-12 36.9-21.3l25.8 14.9c2.9 1.7 6.7 1.1 9-1.4 15-16.2 26.5-35.8 33.2-57.4 1-3.3-.4-6.8-3.3-8.5l-25.8-14.9zM496 368.5c-26.8 0-48.5-21.8-48.5-48.5s21.8-48.5 48.5-48.5 48.5 21.8 48.5 48.5-21.7 48.5-48.5 48.5zM96 224c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm224 32c1.9 0 3.7-.5 5.6-.6 8.3-21.7 20.5-42.1 36.3-59.2 7.4-8 17.9-12.6 28.9-12.6 6.9 0 13.7 1.8 19.6 5.3l7.9 4.6c.8-.5 1.6-.9 2.4-1.4 7-14.6 11.2-30.8 11.2-48 0-61.9-50.1-112-112-112S208 82.1 208 144c0 61.9 50.1 112 112 112zm105.2 194.5c-2.3-1.2-4.6-2.6-6.8-3.9-8.2 4.8-15.3 9.8-27.5 9.8-10.9 0-21.4-4.6-28.9-12.6-18.3-19.8-32.3-43.9-40.2-69.6-10.7-34.5 24.9-49.7 25.8-50.3-.1-2.6-.1-5.2 0-7.8l-7.9-4.6c-3.8-2.2-7-5-9.8-8.1-3.3.2-6.5.6-9.8.6-24.6 0-47.6-6-68.5-16h-8.3C179.6 288 128 339.6 128 403.2V432c0 26.5 21.5 48 48 48h255.4c-3.7-6-6.2-12.8-6.2-20.3v-9.2zM173.1 274.6C161.5 263.1 145.6 256 128 256H64c-35.3 0-64 28.7-64 64v32c0 17.7 14.3 32 32 32h65.9c6.3-47.4 34.9-87.3 75.2-109.4z" /></svg>
</div>
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
<h3 class="text-lg leading-6 font-medium text-gray-900">
Create a new User
</h3>
<div class="mt-2 mb-6">
<p class="text-sm text-gray-500">
Please provide the required information to add a new user.
</p>
</div>
<div class="grid grid-cols-6 gap-6">
<div class="col-span-6">
<label
for="firstname"
class="block text-sm font-medium text-gray-700">{$_('first-name')}</label>
<input
use:focus
autocomplete="off"
placeholder={$_('first-name')}
class:border-red-500={!isFirstnameValid}
class:focus:border-red-500={!isFirstnameValid}
class:focus:ring-red-500={!isFirstnameValid}
bind:value={firstname_input_value}
bind:this={firstname_input}
type="text"
name="firstname"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
{#if !isFirstnameValid}
<span
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
{$_('first-name-is-required')}
</span>
{/if}
</div>
<div class="col-span-6">
<label
for="trackname"
class="block text-sm font-medium text-gray-700">{$_('middle-name')}</label>
<input
autocomplete="off"
placeholder={$_('middle-name')}
bind:value={middlename_input_value}
bind:this={middlename_input}
type="text"
name="trackname"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
</div>
<div class="col-span-6">
<label
for="lastname"
class="block text-sm font-medium text-gray-700">Last Name</label>
<input
autocomplete="off"
placeholder="Last Name"
class:border-red-500={!isLastnameValid}
class:focus:border-red-500={!isLastnameValid}
class:focus:ring-red-500={!isLastnameValid}
bind:value={lastname_input_value}
bind:this={lastname_input}
type="text"
name="lastname"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
{#if !isLastnameValid}
<span
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
{$_('last-name-is-required')}
</span>
{/if}
</div>
<div class="col-span-6">
<label
for="password"
class="block text-sm font-medium text-gray-700">{$_('password')}</label>
<input
autocomplete="off"
placeholder={$_('password')}
class:border-red-500={!isPasswordValid}
class:focus:border-red-500={!isPasswordValid}
class:focus:ring-red-500={!isPasswordValid}
bind:value={password_input_value}
bind:this={password_input}
type="password"
name="password"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
{#if !isPasswordValid}
<span
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
{$_('password-is-required')}
</span>
{/if}
</div>
<div class="col-span-6">
<label
for="email"
class="block text-sm font-medium text-gray-700">{$_('e-mail-adress')}</label>
<input
autocomplete="off"
placeholder={$_('e-mail-adress')}
class:border-red-500={!isEmailValid}
class:focus:border-red-500={!isEmailValid}
class:focus:ring-red-500={!isEmailValid}
bind:value={email_input_value}
bind:this={email_input}
type="email"
name="email"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
{#if !isEmailValid}
<span
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
{$_('valid-email-is-required')}
</span>
{/if}
</div>
</div>
</div>
</div>
</div>
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<button
disabled={!createbtnenabled}
class:opacity-50={!createbtnenabled}
on:click={submit}
type="button"
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">
{$_('create')}
</button>
<button
on:click={() => {
modal_open = false;
}}
type="button"
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
{$_('cancel')}
</button>
</div>
</div>
</div>
</div>
{/if}

View File

@@ -0,0 +1,75 @@
<script>
import Avatars from "./Avatars.svelte";
import Badges from "./Badges.svelte";
import BreadcrumbNav from "./BreadcrumbNav.svelte";
import FileUpload from "./FileUpload.svelte";
import Pagination from "./Pagination.svelte";
import Table from "./Table.svelte";
import Tabs from "./Tabs.svelte";
import Tags from "./Tags.svelte";
</script>
<div class="border-4 border-dashed rounded h-96 mb-4" />
<div class="mb-8">
<FileUpload />
</div>
<div class="mb-8">
<Tabs />
</div>
<div class="mb-8">
<Tags />
</div>
<div class="mb-8">
<Badges />
</div>
<div class="mb-8">
<Avatars />
</div>
<Pagination />
<div class="mb-8">
<Table />
</div>
<div
class="widget w-full p-4 mb-4 rounded-lg bg-white border border-grey-100 dark:bg-grey-895 dark:border-grey-890">
<div class="flex flex-row items-center justify-between mb-6">
<div class="flex flex-col">
<div class="text-sm font-light text-grey-500">Regular</div>
<div class="text-sm font-bold"><span>Text inputs</span></div>
</div>
</div>
<div class="flex flex-col lg:flex-row lg:flex-wrap w-full lg:space-x-4">
<div class="w-full lg:w-1/4">
<div class="form-element ">
<div class="form-label">Label</div><input
name="name"
type="text"
class="form-input"
placeholder="Enter something..." />
<div class="form-hint">This is a hint</div>
</div>
</div>
<div class="w-full lg:w-1/4">
<div class="form-element ">
<div class="form-label">First name</div><input
name="name"
type="text"
class="form-input form-input-invalid"
placeholder="john@example.com" />
<div class="form-error">First name is required</div>
</div>
</div>
<div class="w-full lg:w-1/4">
<div class="form-element ">
<div class="form-label">First name</div><input
name="name"
type="text"
class="form-input form-input-valid"
placeholder="john@example.com" />
<div class="form-success">First name is valid</div>
</div>
</div>
</div>
</div>
<div class="mb-8">
<BreadcrumbNav />
</div>

View File

@@ -538,7 +538,7 @@
stroke-linejoin="round" size="18" height="18" width="18" xmlns="http://www.w3.org/2000/svg"> stroke-linejoin="round" size="18" height="18" width="18" xmlns="http://www.w3.org/2000/svg">
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path> <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
</svg><span </svg><span
class="absolute uppercase font-bold inline-flex text-center p-0 leading-none text-2xs h-4 w-4 inline-flex items-center justify-center rounded-full bg-blue-500 text-white" class="absolute uppercase font-bold inline-flex text-center p-0 leading-none text-2xs h-4 w-4 items-center justify-center rounded-full bg-blue-500 text-white"
style="top:14px;right:8px">5</span></button> style="top:14px;right:8px">5</span></button>
<div class="dropdown absolute top-0 right-0 mt-16 "> <div class="dropdown absolute top-0 right-0 mt-16 ">
<div class="dropdown-content w-64 bottom-start"> <div class="dropdown-content w-64 bottom-start">
@@ -659,7 +659,7 @@
<div class="relative"><button class="flex h-16 w-8 rounded-full ml-2 relative"><span <div class="relative"><button class="flex h-16 w-8 rounded-full ml-2 relative"><span
class="absolute top-0 left-0 pt-4"><img class="h-8 w-8 rounded-full shadow" src="/images/faces/m1.png" class="absolute top-0 left-0 pt-4"><img class="h-8 w-8 rounded-full shadow" src="/images/faces/m1.png"
alt="avatar"><span alt="avatar"><span
class="absolute uppercase font-bold inline-flex text-center p-0 leading-none text-2xs h-4 w-4 inline-flex items-center justify-center rounded-full bg-red-500 text-white shadow-outline-white" class="absolute uppercase font-bold inline-flex text-center p-0 leading-none text-2xs h-4 w-4 items-center justify-center rounded-full bg-red-500 text-white shadow-outline-white"
style="top:10px;right:-4px">2</span></span></button> style="top:10px;right:-4px">2</span></span></button>
<div class="dropdown absolute top-0 right-0 mt-16 "> <div class="dropdown absolute top-0 right-0 mt-16 ">
<div class="dropdown-content w-48 bottom-end"> <div class="dropdown-content w-48 bottom-end">
@@ -672,7 +672,7 @@
<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path> <path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path>
<polyline points="22,6 12,13 2,6"></polyline> <polyline points="22,6 12,13 2,6"></polyline>
</svg><span class="mx-2">Inbox</span><span </svg><span class="mx-2">Inbox</span><span
class="uppercase font-bold inline-flex text-center p-0 leading-none text-2xs h-4 w-4 inline-flex items-center justify-center rounded-full bg-red-500 text-white ml-auto">2</span></a> class="uppercase font-bold inline-flex text-center p-0 leading-none text-2xs h-4 w-4 items-center justify-center rounded-full bg-red-500 text-white ml-auto">2</span></a>
</li> </li>
<li class="dropdown-item"><a class="flex flex-row items-center justify-start h-10 w-full px-2" <li class="dropdown-item"><a class="flex flex-row items-center justify-start h-10 w-full px-2"
href="/"><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" href="/"><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24"
@@ -682,7 +682,7 @@
points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"> points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2">
</polygon> </polygon>
</svg><span class="mx-2">Messages</span><span </svg><span class="mx-2">Messages</span><span
class="uppercase font-bold inline-flex text-center p-0 leading-none text-2xs h-4 w-4 inline-flex items-center justify-center rounded-full bg-blue-500 text-white ml-auto">3</span></a> class="uppercase font-bold inline-flex text-center p-0 leading-none text-2xs h-4 w-4 items-center justify-center rounded-full bg-blue-500 text-white ml-auto">3</span></a>
</li> </li>
<li class="dropdown-item"><a class="flex flex-row items-center justify-start h-10 w-full px-2" <li class="dropdown-item"><a class="flex flex-row items-center justify-start h-10 w-full px-2"
href="/extras/user-profile"><svg stroke="currentColor" fill="none" stroke-width="2" href="/extras/user-profile"><svg stroke="currentColor" fill="none" stroke-width="2"

View File

@@ -6,6 +6,7 @@
import store from "../store"; import store from "../store";
import NoComponentLoaded from "./NoComponentLoaded.svelte"; import NoComponentLoaded from "./NoComponentLoaded.svelte";
import { AuthService, OpenAPI } from "@odit/lfk-client-js";
let activePage = "dashboard"; let activePage = "dashboard";
let dropdown1 = false; let dropdown1 = false;
@@ -32,21 +33,22 @@
} }
</script> </script>
<section class="min-h-screen bg-gray-50"> <section class="min-h-screen bg-gray-50 dark:bg-black dark:text-gray-100">
<nav <nav
class:hidden={!navOpen && mobile} class:hidden={!navOpen && mobile}
class="select-none fixed top-0 left-0 z-20 h-full pb-10 overflow-x-hidden overflow-y-auto transition origin-left transform bg-white border-r w-60 md:translate-x-0"> class="select-none fixed top-0 left-0 z-20 h-full pb-10 overflow-x-hidden overflow-y-auto transition origin-left transform border-r w-60 md:translate-x-0">
<a href="/" class="flex items-center px-4 py-5"> <a href="/" class="flex items-center px-4 py-5">
<img <img
src="https://lauf-fuer-kaya.de/Bilder/kaya-logo-quadrat.png" src="/lfk-logo.png"
alt="Logo" alt="Logo"
class="h-10" /> class="h-10" />
<h3 class="text-lg">Lauf für Kaya! Admin</h3> <h3 class="text-lg">Lauf für Kaya! Admin</h3>
</a> </a>
<nav class="text-sm font-medium text-gray-600" aria-label="Main Navigation"> <nav class="text-sm font-medium text-gray-600" aria-label="Main Navigation">
<a <a
class:dark:bg-gray-900={$router.path === '/'}
class:bg-gray-100={$router.path === '/'} class:bg-gray-100={$router.path === '/'}
class="flex items-center px-4 py-3 text-gray-900 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900" class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
href="/"> href="/">
<svg <svg
class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600" class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
@@ -56,9 +58,10 @@
<path <path
d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z" /> d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z" />
</svg> </svg>
<span>Dashboard</span> <span>{$_('dashboard-title')}</span>
</a> </a>
<a <a
class:dark:bg-gray-900={$router.path.includes('/orgs/')}
class:bg-gray-100={$router.path.includes('/orgs/')} class:bg-gray-100={$router.path.includes('/orgs/')}
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900" class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
href="/orgs/"> href="/orgs/">
@@ -71,26 +74,28 @@
height="24"><path fill="none" d="M0 0h24v24H0z" /> height="24"><path fill="none" d="M0 0h24v24H0z" />
<path <path
d="M17 19h2v-8h-6v8h2v-6h2v6zM3 19V4a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v5h2v10h1v2H2v-2h1zm4-8v2h2v-2H7zm0 4v2h2v-2H7zm0-8v2h2V7H7z" /></svg> d="M17 19h2v-8h-6v8h2v-6h2v6zM3 19V4a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v5h2v10h1v2H2v-2h1zm4-8v2h2v-2H7zm0 4v2h2v-2H7zm0-8v2h2V7H7z" /></svg>
<span>Orgs</span> <span>{$_('orgs')}</span>
</a> </a>
<a <a
class:dark:bg-gray-900={$router.path === '/users/'}
class:bg-gray-100={$router.path === '/users/'} class:bg-gray-100={$router.path === '/users/'}
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900" class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
href="/users/"> href="/users/">
<svg <svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600" class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
width="24"
fill="currentColor" fill="currentColor"
height="24"><path fill="none" d="M0 0h24v24H0z" /> width="24"
<path height="24"
d="M2 22a8 8 0 1 1 16 0H2zm8-9c-3.315 0-6-2.685-6-6s2.685-6 6-6 6 2.685 6 6-2.685 6-6 6zm7.363 2.233A7.505 7.505 0 0 1 22.983 22H20c0-2.61-1-4.986-2.637-6.767zm-2.023-2.276A7.98 7.98 0 0 0 18 7a7.964 7.964 0 0 0-1.015-3.903A5 5 0 0 1 21 8a4.999 4.999 0 0 1-5.66 4.957z" /></svg> xmlns="http://www.w3.org/2000/svg"
<span>Users</span> viewBox="0 0 640 512"><path
fill="currentColor"
d="M610.5 341.3c2.6-14.1 2.6-28.5 0-42.6l25.8-14.9c3-1.7 4.3-5.2 3.3-8.5-6.7-21.6-18.2-41.2-33.2-57.4-2.3-2.5-6-3.1-9-1.4l-25.8 14.9c-10.9-9.3-23.4-16.5-36.9-21.3v-29.8c0-3.4-2.4-6.4-5.7-7.1-22.3-5-45-4.8-66.2 0-3.3.7-5.7 3.7-5.7 7.1v29.8c-13.5 4.8-26 12-36.9 21.3l-25.8-14.9c-2.9-1.7-6.7-1.1-9 1.4-15 16.2-26.5 35.8-33.2 57.4-1 3.3.4 6.8 3.3 8.5l25.8 14.9c-2.6 14.1-2.6 28.5 0 42.6l-25.8 14.9c-3 1.7-4.3 5.2-3.3 8.5 6.7 21.6 18.2 41.1 33.2 57.4 2.3 2.5 6 3.1 9 1.4l25.8-14.9c10.9 9.3 23.4 16.5 36.9 21.3v29.8c0 3.4 2.4 6.4 5.7 7.1 22.3 5 45 4.8 66.2 0 3.3-.7 5.7-3.7 5.7-7.1v-29.8c13.5-4.8 26-12 36.9-21.3l25.8 14.9c2.9 1.7 6.7 1.1 9-1.4 15-16.2 26.5-35.8 33.2-57.4 1-3.3-.4-6.8-3.3-8.5l-25.8-14.9zM496 368.5c-26.8 0-48.5-21.8-48.5-48.5s21.8-48.5 48.5-48.5 48.5 21.8 48.5 48.5-21.7 48.5-48.5 48.5zM96 224c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm224 32c1.9 0 3.7-.5 5.6-.6 8.3-21.7 20.5-42.1 36.3-59.2 7.4-8 17.9-12.6 28.9-12.6 6.9 0 13.7 1.8 19.6 5.3l7.9 4.6c.8-.5 1.6-.9 2.4-1.4 7-14.6 11.2-30.8 11.2-48 0-61.9-50.1-112-112-112S208 82.1 208 144c0 61.9 50.1 112 112 112zm105.2 194.5c-2.3-1.2-4.6-2.6-6.8-3.9-8.2 4.8-15.3 9.8-27.5 9.8-10.9 0-21.4-4.6-28.9-12.6-18.3-19.8-32.3-43.9-40.2-69.6-10.7-34.5 24.9-49.7 25.8-50.3-.1-2.6-.1-5.2 0-7.8l-7.9-4.6c-3.8-2.2-7-5-9.8-8.1-3.3.2-6.5.6-9.8.6-24.6 0-47.6-6-68.5-16h-8.3C179.6 288 128 339.6 128 403.2V432c0 26.5 21.5 48 48 48h255.4c-3.7-6-6.2-12.8-6.2-20.3v-9.2zM173.1 274.6C161.5 263.1 145.6 256 128 256H64c-35.3 0-64 28.7-64 64v32c0 17.7 14.3 32 32 32h65.9c6.3-47.4 34.9-87.3 75.2-109.4z" /></svg>
<span>{$_('users')}</span>
</a> </a>
<a <a
class:dark:bg-gray-900={$router.path === '/runners/'}
class:bg-gray-100={$router.path === '/runners/'} class:bg-gray-100={$router.path === '/runners/'}
class="flex items-center px-4 py-3 text-gray-900 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900" class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
href="/runners/"> href="/runners/">
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@@ -101,21 +106,42 @@
height="24"><path fill="none" d="M0 0h24v24H0z" /> height="24"><path fill="none" d="M0 0h24v24H0z" />
<path <path
d="M9.83 8.79L8 9.456V13H6V8.05h.015l5.268-1.918c.244-.093.51-.14.782-.131a2.616 2.616 0 0 1 2.427 1.82c.186.583.356.977.51 1.182A4.992 4.992 0 0 0 19 11v2a6.986 6.986 0 0 1-5.402-2.547l-.581 3.297L15 15.67V23h-2v-5.986l-2.05-1.987-.947 4.298-6.894-1.215.348-1.97 4.924.868L9.83 8.79zM13.5 5.5a2 2 0 1 1 0-4 2 2 0 0 1 0 4z" /></svg> d="M9.83 8.79L8 9.456V13H6V8.05h.015l5.268-1.918c.244-.093.51-.14.782-.131a2.616 2.616 0 0 1 2.427 1.82c.186.583.356.977.51 1.182A4.992 4.992 0 0 0 19 11v2a6.986 6.986 0 0 1-5.402-2.547l-.581 3.297L15 15.67V23h-2v-5.986l-2.05-1.987-.947 4.298-6.894-1.215.348-1.97 4.924.868L9.83 8.79zM13.5 5.5a2 2 0 1 1 0-4 2 2 0 0 1 0 4z" /></svg>
<span>Runners</span> <span>{$_('runners')}</span>
</a> </a>
<a <a
class:dark:bg-gray-900={$router.path === '/teams/'}
class:bg-gray-100={$router.path === '/teams/'}
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
href="/teams/">
<svg
class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
fill="currentColor"
width="24"
height="24"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 640 512"><path
fill="currentColor"
d="M96 224c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm448 0c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm32 32h-64c-17.6 0-33.5 7.1-45.1 18.6 40.3 22.1 68.9 62 75.1 109.4h66c17.7 0 32-14.3 32-32v-32c0-35.3-28.7-64-64-64zm-256 0c61.9 0 112-50.1 112-112S381.9 32 320 32 208 82.1 208 144s50.1 112 112 112zm76.8 32h-8.3c-20.8 10-43.9 16-68.5 16s-47.6-6-68.5-16h-8.3C179.6 288 128 339.6 128 403.2V432c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48v-28.8c0-63.6-51.6-115.2-115.2-115.2zm-223.7-13.4C161.5 263.1 145.6 256 128 256H64c-35.3 0-64 28.7-64 64v32c0 17.7 14.3 32 32 32h65.9c6.3-47.4 34.9-87.3 75.2-109.4z" /></svg>
<span>{$_('teams')}</span>
</a>
<a
class:dark:bg-gray-900={$router.path === '/tracks/'}
class:bg-gray-100={$router.path === '/tracks/'} class:bg-gray-100={$router.path === '/tracks/'}
class="flex items-center px-4 py-3 text-gray-900 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900" class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
href="/tracks/"> href="/tracks/">
<svg xmlns="http://www.w3.org/2000/svg" height="24" width="24"><path <svg
d="M0 0h24v24H0z" class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600" fill="currentColor"
fill="none" /> width="24"
<path height="24"
d="M21 6H3c-1.1 0-2 .9-2 2v8c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 10H3V8h2v4h2V8h2v4h2V8h2v4h2V8h2v4h2V8h2v8z" /></svg> xmlns="http://www.w3.org/2000/svg"
<span>Tracks</span> viewBox="0 0 640 512"><path
fill="currentColor"
d="M635.7 167.2L556.1 31.7c-8.8-15-28.3-20.1-43.5-11.5l-69 39.1L503.3 161c2.2 3.8.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9L416 75l-55.2 31.3 27.9 47.4c2.2 3.8.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9L333.2 122 278 153.3 337.8 255c2.2 3.7.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9l-59.7-101.7-55.2 31.3 27.9 47.4c2.2 3.8.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9l-27.9-47.5-55.2 31.3 59.7 101.7c2.2 3.7.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9L84.9 262.9l-69 39.1C.7 310.7-4.6 329.8 4.2 344.8l79.6 135.6c8.8 15 28.3 20.1 43.5 11.5L624.1 210c15.2-8.6 20.4-27.8 11.6-42.8z" /></svg>
<span>{$_('tracks')}</span>
</a> </a>
<a <a
class:dark:bg-gray-900={activePage === 'blub'}
class:bg-gray-100={activePage === 'blub'} class:bg-gray-100={activePage === 'blub'}
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900" class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
href="#"> href="#">
@@ -134,6 +160,8 @@
</a> </a>
<div> <div>
<div <div
tabindex="0"
class:dark:bg-gray-900={activePage === 'blub'}
class:bg-gray-100={activePage === 'blub'} class:bg-gray-100={activePage === 'blub'}
class="flex items-center justify-between px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900" class="flex items-center justify-between px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
role="button" role="button"
@@ -206,9 +234,10 @@
clip-rule="evenodd" /> clip-rule="evenodd" />
<path d="M9 11H3v5a2 2 0 002 2h4v-7zM11 18h4a2 2 0 002-2v-5h-6v7z" /> <path d="M9 11H3v5a2 2 0 002 2h4v-7zM11 18h4a2 2 0 002-2v-5h-6v7z" />
</svg> </svg>
<span>Changelog</span> <span>{$_('changelog')}</span>
</a> </a>
<a <a
class:dark:bg-gray-900={$router.path === '/settings/'}
class:bg-gray-100={$router.path === '/settings/'} class:bg-gray-100={$router.path === '/settings/'}
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900" class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
href="/settings/"> href="/settings/">
@@ -222,9 +251,10 @@
d="M11.49 3.17c-.38-1.56-2.6-1.56-2.98 0a1.532 1.532 0 01-2.286.948c-1.372-.836-2.942.734-2.106 2.106.54.886.061 2.042-.947 2.287-1.561.379-1.561 2.6 0 2.978a1.532 1.532 0 01.947 2.287c-.836 1.372.734 2.942 2.106 2.106a1.532 1.532 0 012.287.947c.379 1.561 2.6 1.561 2.978 0a1.533 1.533 0 012.287-.947c1.372.836 2.942-.734 2.106-2.106a1.533 1.533 0 01.947-2.287c1.561-.379 1.561-2.6 0-2.978a1.532 1.532 0 01-.947-2.287c.836-1.372-.734-2.942-2.106-2.106a1.532 1.532 0 01-2.287-.947zM10 13a3 3 0 100-6 3 3 0 000 6z" d="M11.49 3.17c-.38-1.56-2.6-1.56-2.98 0a1.532 1.532 0 01-2.286.948c-1.372-.836-2.942.734-2.106 2.106.54.886.061 2.042-.947 2.287-1.561.379-1.561 2.6 0 2.978a1.532 1.532 0 01.947 2.287c-.836 1.372.734 2.942 2.106 2.106a1.532 1.532 0 012.287.947c.379 1.561 2.6 1.561 2.978 0a1.533 1.533 0 012.287-.947c1.372.836 2.942-.734 2.106-2.106a1.533 1.533 0 01.947-2.287c1.561-.379 1.561-2.6 0-2.978a1.532 1.532 0 01-.947-2.287c.836-1.372-.734-2.942-2.106-2.106a1.532 1.532 0 01-2.287-.947zM10 13a3 3 0 100-6 3 3 0 000 6z"
clip-rule="evenodd" /> clip-rule="evenodd" />
</svg> </svg>
<span>Settings</span> <span>{$_('settings')}</span>
</a> </a>
<a <a
class:dark:bg-gray-900={$router.path === '/about/'}
class:bg-gray-100={$router.path === '/about/'} class:bg-gray-100={$router.path === '/about/'}
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900" class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
href="/about/"> href="/about/">
@@ -238,28 +268,31 @@
stroke-linejoin="round" stroke-linejoin="round"
viewBox="0 0 24 24"><circle cx="12" cy="12" r="10" /> viewBox="0 0 24 24"><circle cx="12" cy="12" r="10" />
<path d="M12 16v-4M12 8h.01" /></svg> <path d="M12 16v-4M12 8h.01" /></svg>
<span>About</span> <span>{$_('about')}</span>
</a> </a>
<span <span
tabindex="0"
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900" class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
on:click={() => { on:click={() => {
AuthService.authControllerLogout();
logout(); logout();
}}> }}>
<svg <svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600" class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
fill="currentColor"
width="24" width="24"
height="24"><path fill="none" d="M0 0h24v24H0z" /> height="24"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z" />
<path <path
d="M5 22a1 1 0 0 1-1-1V3a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v3h-2V4H6v16h12v-2h2v3a1 1 0 0 1-1 1H5zm13-6v-3h-7v-2h7V8l5 4-5 4z" /></svg> d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2a9.985 9.985 0 0 1 8 4h-2.71a8 8 0 1 0 .001 12h2.71A9.985 9.985 0 0 1 12 22zm7-6v-3h-8v-2h8V8l5 4-5 4z" /></svg>
<span>Logout</span> <span>{$_('logout')}</span>
</span> </span>
</nav> </nav>
</nav> </nav>
<div class="ml-0 transition md:ml-60"> <div class="ml-0 transition md:ml-60">
<header <header
class="flex items-center justify-between w-full px-4 bg-white border-b h-14"> class="flex items-center justify-between w-full px-4 border-b h-14">
<button <button
on:click={() => { on:click={() => {
navOpen = !navOpen; navOpen = !navOpen;

View File

@@ -1,22 +1,71 @@
<script> <script>
import "filepond/dist/filepond.css"; import "filepond/dist/filepond.css";
import FilePond from "svelte-filepond"; import FilePond from "svelte-filepond";
import { _ } from "svelte-i18n";
let pond; let pond;
// pond.getFiles() will return the active files // pond.getFiles() will return the active files
// the name to use for the internal file input // the name to use for the internal file input
let name = "filepond"; let name = "filepond";
function handleInit() { function handleInit() {
console.log("FilePond has initialised"); // console.log("FilePond has initialised");
} }
function handleAddFile(err, fileItem) { function handleAddFile(err, fileItem) {
console.log("A file has been added", fileItem); // console.log("A file has been added", fileItem);
} }
const labelInvalidField = $_("filepond__field-contains-invalid-files");
const labelFileWaitingForSize = $_("filepond__waiting-for-size");
const labelFileSizeNotAvailable = $_("filepond__size-not-available");
const labelFileLoading = $_("filepond__loading");
const labelFileLoadError = $_("filepond__error-during-load");
const labelFileProcessing = $_("filepond__uploading");
const labelFileProcessingComplete = $_("filepond__upload-complete");
const labelFileProcessingAborted = $_("filepond__upload-cancelled");
const labelFileProcessingError = $_("filepond__error-during-upload");
const labelFileProcessingRevertError = $_("filepond__error-during-revert");
const labelFileRemoveError = $_("filepond__error-during-remove");
const labelTapToCancel = $_("filepond__tap-to-cancel");
const labelTapToRetry = $_("filepond__tap-to-retry");
const labelTapToUndo = $_("filepond__tap-to-undo");
const labelButtonRemoveItem = $_("filepond__remove");
const labelButtonAbortItemLoad = $_("filepond__abort");
const labelButtonRetryItemLoad = $_("filepond__retry");
const labelButtonAbortItemProcessing = $_("filepond__cancel");
const labelButtonUndoItemProcessing = $_("filepond__undo");
const labelButtonRetryItemProcessing = $_("filepond__retry");
const labelButtonProcessItem = $_("filepond__upload");
const labelIdle =
$_("drag-and-drop-your-files-or") +
` <span class="filepond--label-action"> ` +
$_("browse") +
` </span>`;
</script> </script>
<div class="app"> <div class="app">
<FilePond <FilePond
bind:this={pond} bind:this={pond}
{name} {name}
{labelFileWaitingForSize}
{labelFileSizeNotAvailable}
{labelFileLoading}
{labelFileLoadError}
{labelFileProcessing}
{labelFileProcessingComplete}
{labelFileProcessingAborted}
{labelFileProcessingError}
{labelFileProcessingRevertError}
{labelFileRemoveError}
{labelTapToCancel}
{labelTapToRetry}
{labelTapToUndo}
{labelButtonRemoveItem}
{labelButtonAbortItemLoad}
{labelButtonRetryItemLoad}
{labelButtonAbortItemProcessing}
{labelButtonUndoItemProcessing}
{labelButtonRetryItemProcessing}
{labelButtonProcessItem}
{labelIdle}
{labelInvalidField}
server="/api" server="/api"
allowMultiple={false} allowMultiple={false}
credits={false} credits={false}

View File

@@ -1,21 +1,32 @@
<script> <script>
import { _ } from "svelte-i18n"; import { _ } from "svelte-i18n";
const releaseinfo = document
.getElementById("buildinfo")
.textContent.replace("RELEASE_INFO-", "")
.replace("-RELEASE_INFO", "");
const year = new Date().getFullYear();
</script> </script>
<footer class="block py-4"> <footer class="p-5 w-full">
<div class="container mx-auto px-4"> <p class="text-sm text-gray-500 mt-4">
<hr class="mb-4 border-b-1 border-gray-300" /> Lauf für Kaya! Läufersystem - Copyright ©
<footer class="text-gray-700 body-font"> {year}
<div class="container mx-auto flex items-center sm:flex-row flex-col"> + proudly powered by
<p class="text-sm text-gray-500 mt-4"> <a
Lauf für Kaya! Läufersystem - Copyright © 2020 + proudly powered by class="underline"
<a href="https://odit.services"
class="underline" rel="noopener,noreferrer"
href="https://odit.services" target="_blank">ODIT.Services</a>
rel="noopener,noreferrer" </p>
target="_blank">ODIT.Services</a> <p class="text-sm text-gray-500 mt-4">
</p> <a
</div> class="underline"
</footer> target="_blank"
</div> rel="noopener, noreferrer"
href="https://git.odit.services/lfk/frontend/">LfK!Frontend</a>@<a
class="underline"
target="_blank"
rel="noopener, noreferrer"
href="https://git.odit.services/lfk/frontend/src/tag/{releaseinfo}">{releaseinfo}</a>
</p>
</footer> </footer>

View File

@@ -1,23 +1,28 @@
<script> <script>
import { ApiError, AuthService } from "@odit/lfk-client-js";
import { _ } from "svelte-i18n"; import { _ } from "svelte-i18n";
import store from "../store.js";
store.init();
//
import { OpenAPI, AuthService } from "@odit/lfk-client-js";
import isEmail from "validator/es/lib/isEmail";
//
import Toastify from "toastify-js"; import Toastify from "toastify-js";
import "toastify-js/src/toastify.css"; import "toastify-js/src/toastify.css";
import isEmail from "validator/es/lib/isEmail";
let reset_mail_sent = false; let reset_mail_sent = false;
let usersEmail = ""; let usersEmail = "";
function reset() { function reset() {
if (isEmail(usersEmail)) { if (isEmail(usersEmail)) {
Toastify({ AuthService.authControllerGetResetToken({ email: usersEmail })
text: $_("mail-validation-in-progress"), .then((resp) => {
duration: 3500, console.log(resp);
}).showToast(); console.log(resp.resetToken);
reset_mail_sent = true; Toastify({
text: $_("mail-validation-in-progress"),
duration: 3500,
}).showToast();
reset_mail_sent = true;
})
.catch((err) => {
console.log(err.body.name);
console.log(err.body.message);
});
} else { } else {
Toastify({ Toastify({
text: $_("invalid-mail-reset"), text: $_("invalid-mail-reset"),
@@ -30,11 +35,7 @@
{#if reset_mail_sent} {#if reset_mail_sent}
<div class="min-h-screen flex items-center justify-center bg-gray-100"> <div class="min-h-screen flex items-center justify-center bg-gray-100">
<div class="max-w-md w-full py-12 px-6"> <div class="max-w-md w-full py-12 px-6">
<img <img style="height:10rem;" class="mx-auto" src="/lfk-logo.png" alt="" />
style="height:10rem;"
class="mx-auto"
src="https://lauf-fuer-kaya.de/Bilder/kaya-logo-quadrat.png"
alt="" />
<p class="mt-6 text-lg text-center font-bold text-gray-900"> <p class="mt-6 text-lg text-center font-bold text-gray-900">
{$_('application_name')} {$_('application_name')}
</p> </p>
@@ -57,11 +58,7 @@
{:else} {:else}
<div class="min-h-screen flex items-center justify-center bg-gray-100"> <div class="min-h-screen flex items-center justify-center bg-gray-100">
<div class="max-w-md w-full py-12 px-6"> <div class="max-w-md w-full py-12 px-6">
<img <img style="height:10rem;" class="mx-auto" src="/lfk-logo.png" alt="" />
style="height:10rem;"
class="mx-auto"
src="https://lauf-fuer-kaya.de/Bilder/kaya-logo-quadrat.png"
alt="" />
<p class="mt-6 text-lg text-center font-bold text-gray-900"> <p class="mt-6 text-lg text-center font-bold text-gray-900">
{$_('application_name')} {$_('application_name')}
</p> </p>

View File

@@ -55,6 +55,7 @@
</div> </div>
<div> <div>
<!-- svelte-ignore a11y-label-has-associated-control -->
<label class="block text-sm font-medium text-gray-700"> <label class="block text-sm font-medium text-gray-700">
Photo Photo
</label> </label>
@@ -71,6 +72,7 @@
</div> </div>
<div> <div>
<!-- svelte-ignore a11y-label-has-associated-control -->
<label class="block text-sm font-medium text-gray-700"> <label class="block text-sm font-medium text-gray-700">
Cover photo Cover photo
</label> </label>

View File

@@ -4,12 +4,11 @@
import { _ } from "svelte-i18n"; import { _ } from "svelte-i18n";
store.init(); store.init();
import { OpenAPI, AuthService } from "@odit/lfk-client-js"; import { OpenAPI, AuthService } from "@odit/lfk-client-js";
OpenAPI.BASE = config.baseurl; import Footer from "./Footer.svelte";
import Toastify from "toastify-js"; import Toastify from "toastify-js";
import "toastify-js/src/toastify.css";
// ------ // ------
let usersUsername; let username = "demo";
let usersPassword = ""; let password = "demo";
let is_blocked_by_autologin = false; let is_blocked_by_autologin = false;
let last_loginclick_processed = true; let last_loginclick_processed = true;
@@ -19,7 +18,7 @@
is_blocked_by_autologin = true; is_blocked_by_autologin = true;
OpenAPI.TOKEN = value.access_token; OpenAPI.TOKEN = value.access_token;
const jwtinfo = JSON.parse(atob(OpenAPI.TOKEN.split(".")[1])); const jwtinfo = JSON.parse(atob(OpenAPI.TOKEN.split(".")[1]));
store.login(value.access_token, jwtinfo); store.login(value, jwtinfo);
Toastify({ Toastify({
text: $_("welcome_wavinghand"), text: $_("welcome_wavinghand"),
duration: 500, duration: 500,
@@ -37,14 +36,6 @@
text: $_("login_is_checked"), text: $_("login_is_checked"),
duration: 500, duration: 500,
}).showToast(); }).showToast();
let username = usersUsername;
let password = usersPassword;
// if ((usersUsername + "").length == 0) {
username = config.fallback_username || "demo";
// }
// if ((usersPassword + "").length == 0) {
password = config.fallback_password || "demo";
// }
AuthService.authControllerLogin({ AuthService.authControllerLogin({
username, username,
password, password,
@@ -54,7 +45,7 @@
OpenAPI.TOKEN = result.access_token; OpenAPI.TOKEN = result.access_token;
const jwtinfo = JSON.parse(atob(OpenAPI.TOKEN.split(".")[1])); const jwtinfo = JSON.parse(atob(OpenAPI.TOKEN.split(".")[1]));
store.login(result.access_token, jwtinfo); store.login(result.access_token, jwtinfo);
replace("/"); location.replace("/");
Toastify({ Toastify({
text: $_("welcome_wavinghand"), text: $_("welcome_wavinghand"),
duration: 500, duration: 500,
@@ -91,12 +82,8 @@
<div <div
class="min-h-screen flex items-center justify-center bg-gray-100 text-gray-900"> class="min-h-screen flex items-center justify-center bg-gray-100 text-gray-900">
<div class="max-w-md w-full py-12 px-6"> <div class="max-w-md w-full py-12 px-6" role="main">
<img <img style="height:10rem;" class="mx-auto" src="/lfk-logo.png" alt="" />
style="height:10rem;"
class="mx-auto"
src="https://lauf-fuer-kaya.de/Bilder/kaya-logo-quadrat.png"
alt="" />
<p class="mt-6 text-lg text-center font-bold">{$_('application_name')}</p> <p class="mt-6 text-lg text-center font-bold">{$_('application_name')}</p>
<p class="mt-6 text-sm text-center">{$_('log_in_to_your_account')}</p> <p class="mt-6 text-sm text-center">{$_('log_in_to_your_account')}</p>
<div> <div>
@@ -111,14 +98,14 @@
class="border-gray-300 placeholder-gray-500 appearance-none rounded-none relative block w-full px-3 py-2 border rounded-t-md focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 sm:text-sm" class="border-gray-300 placeholder-gray-500 appearance-none rounded-none relative block w-full px-3 py-2 border rounded-t-md focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 sm:text-sm"
on:keydown={handleKeydown} on:keydown={handleKeydown}
placeholder={$_('email_address_or_username')} placeholder={$_('email_address_or_username')}
bind:value={usersUsername} /> bind:value={username} />
</div> </div>
<div class="-mt-px relative"> <div class="-mt-px relative">
<input <input
aria-label={$_('password')} aria-label={$_('password')}
type="password" type="password"
required="" required=""
bind:value={usersPassword} bind:value={password}
class="border-gray-300 placeholder-gray-500 appearance-none rounded-none relative block w-full px-3 py-2 border rounded-b-md focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 sm:text-sm" class="border-gray-300 placeholder-gray-500 appearance-none rounded-none relative block w-full px-3 py-2 border rounded-b-md focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 sm:text-sm"
on:keydown={handleKeydown} on:keydown={handleKeydown}
placeholder={$_('password')} /> placeholder={$_('password')} />
@@ -154,3 +141,4 @@
</div> </div>
</div> </div>
</div> </div>
<Footer />

View File

@@ -12,7 +12,7 @@
<div> <div>
<img <img
class="mx-auto h-12 w-auto" class="mx-auto h-12 w-auto"
src="https://lauf-fuer-kaya.de/Bilder/kaya-logo-quadrat.png" src="/lfk-logo.png"
alt="" /> alt="" />
<h2 class="mt-6 text-center text-3xl font-extrabold text-gray-900"> <h2 class="mt-6 text-center text-3xl font-extrabold text-gray-900">
Sign in to your account Sign in to your account

View File

@@ -1,15 +1,8 @@
<script> <script>
import { _ } from "svelte-i18n"; import { _ } from "svelte-i18n";
import BreadcrumbNav from "./BreadcrumbNav.svelte";
import FileUpload from "./FileUpload.svelte";
import FormLayout from "./FormLayout.svelte";
import Pagination from "./Pagination.svelte";
import StatCards from "./StatCards.svelte"; import StatCards from "./StatCards.svelte";
import Tabs from "./Tabs.svelte";
import Tags from "./Tags.svelte";
import Badges from "./Badges.svelte";
import Avatars from "./Avatars.svelte";
import store from "../store"; import store from "../store";
import ComponentDump from "./ComponentDump.svelte";
let navOpen = false; let navOpen = false;
</script> </script>
@@ -20,80 +13,13 @@
}}> }}>
<!-- <div class="border-4 border-dashed rounded h-96" /> --> <!-- <div class="border-4 border-dashed rounded h-96" /> -->
<h1 class="text-3xl leading-tight"> <h1 class="text-3xl leading-tight">
<span class="font-bold">Dashboard</span><span> <span class="font-extrabold">{$_('dashboard-title')}</span> <span>
- hello there, -
{$_('dashboard-greeting')},
<span <span
class="text-blue-500">{store.state.jwtinfo.userdetails.firstname}</span> class="text-blue-500">{store.state.jwtinfo.userdetails.firstname}</span>
👋</span> 👋</span>
</h1> </h1>
<div class="shadow px-6 pt-4 pb-1">
<BreadcrumbNav />
</div>
<StatCards /> <StatCards />
<div class="mb-8"> <ComponentDump />
<FileUpload />
</div>
<div class="mb-8">
<!-- <DataTable /> -->
</div>
<div class="mb-8">
<Tabs />
</div>
<div class="mb-8">
<Tags />
</div>
<div class="mb-8">
<Badges />
</div>
<div class="mb-8">
<Avatars />
</div>
<Pagination />
<div class="mb-8">
<!-- <Table /> -->
</div>
<div
class="widget w-full p-4 mb-4 rounded-lg bg-white border border-grey-100 dark:bg-grey-895 dark:border-grey-890">
<div class="flex flex-row items-center justify-between mb-6">
<div class="flex flex-col">
<div class="text-sm font-light text-grey-500">Regular</div>
<div class="text-sm font-bold"><span>Text inputs</span></div>
</div>
</div>
<div class="flex flex-col lg:flex-row lg:flex-wrap w-full lg:space-x-4">
<div class="w-full lg:w-1/4">
<div class="form-element ">
<div class="form-label">Label</div><input
name="name"
type="text"
class="form-input"
placeholder="Enter something..." />
<div class="form-hint">This is a hint</div>
</div>
</div>
<div class="w-full lg:w-1/4">
<div class="form-element ">
<div class="form-label">First name</div><input
name="name"
type="text"
class="form-input form-input-invalid"
placeholder="john@example.com" />
<div class="form-error">First name is required</div>
</div>
</div>
<div class="w-full lg:w-1/4">
<div class="form-element ">
<div class="form-label">First name</div><input
name="name"
type="text"
class="form-input form-input-valid"
placeholder="john@example.com" />
<div class="form-success">First name is valid</div>
</div>
</div>
</div>
</div>
<div class="mb-8">
<FormLayout />
</div>
</div> </div>

View File

@@ -0,0 +1,83 @@
<script>
export let params;
</script>
<section class="container p-5">
<span class="mb-1 text-3xl font-extrabold leading-tight">
Orgs
</span>
<p class="mb-8 text-lg text-gray-500">
configure the tracks & minimum lap times
</p>
<div class="flex flex-row mb-4">
<div class="w-full">
<nav class="w-full flex">
<ol class="list-none flex flex-row items-center justify-start">
<li class="mr-2 flex items-center">
<svg
stroke="currentColor"
fill="none"
stroke-width="2"
viewBox="0 0 24 24"
stroke-linecap="round"
stroke-linejoin="round"
class="h-3 w-3 stroke-current"
height="1em"
width="1em"
xmlns="http://www.w3.org/2000/svg"><path
d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
<polyline points="9 22 9 12 15 12 15 22" /></svg>
</li>
<li class="flex items-center">
<a class="mr-2" href="/">Home</a><svg
stroke="currentColor"
fill="none"
stroke-width="2"
viewBox="0 0 24 24"
stroke-linecap="round"
stroke-linejoin="round"
class="h-3 w-3 mr-2 stroke-current"
height="1em"
width="1em"
xmlns="http://www.w3.org/2000/svg"><line
x1="5"
y1="12"
x2="19"
y2="12" />
<polyline points="12 5 19 12 12 19" /></svg>
</li>
<li class="mr-2 flex items-center">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="24"
height="24"><path fill="none" d="M0 0h24v24H0z" />
<path
d="M21 20h2v2H1v-2h2V3a1 1 0 0 1 1-1h16a1 1 0 0 1 1 1v17zm-2 0V4H5v16h14zM8 11h3v2H8v-2zm0-4h3v2H8V7zm0 8h3v2H8v-2zm5 0h3v2h-3v-2zm0-4h3v2h-3v-2zm0-4h3v2h-3V7z" /></svg>
</li>
<li class="flex items-center">
<a class="mr-2" href="./">Orgs</a><svg
stroke="currentColor"
fill="none"
stroke-width="2"
viewBox="0 0 24 24"
stroke-linecap="round"
stroke-linejoin="round"
class="h-3 w-3 mr-2 stroke-current"
height="1em"
width="1em"
xmlns="http://www.w3.org/2000/svg"><line
x1="5"
y1="12"
x2="19"
y2="12" />
<polyline points="12 5 19 12 12 19" /></svg>
</li>
<li class="flex items-center">
<span class="mr-2">Org-Details #{params.orgid}</span>
</li>
</ol>
</nav>
</div>
</div>
</section>

View File

@@ -2,18 +2,12 @@
import { _ } from "svelte-i18n"; import { _ } from "svelte-i18n";
</script> </script>
<div class="flex min-h-screen"> <section class="container p-5">
<div class="w-full bg-white flex items-center justify-center "> <span class="mb-1 text-3xl font-extrabold leading-tight">
<div class="max-w-sm m-8"> Orgs
<div class="text-black text-5xl md:text-15xl font-black">Orgs</div> </span>
<div class="w-16 h-1 bg-purple-light my-3 md:my-6" /> <p class="mb-8 text-lg text-gray-500">
<p add, delete, edit organizations
class="text-grey-darker text-2xl md:text-3xl font-light mb-8 leading-normal"> </p>
bla <nav><a class="underline" href="./1">Org 1</a></nav>
</p> </section>
<a
href="/"
class="bg-transparent text-grey-darkest font-bold uppercase tracking-wide py-3 px-6 border-2 border-grey-light hover:border-grey rounded-lg">{$_('goback')}</a>
</div>
</div>
</div>

View File

@@ -0,0 +1,11 @@
<script>
import { _ } from "svelte-i18n";
export let error;
</script>
<div class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500">
<span class="inline-block align-middle mr-8">
<b class="capitalize">{$_('general_promise_error')}</b>
{error}
</span>
</div>

View File

@@ -2,22 +2,9 @@
import { _ } from "svelte-i18n"; import { _ } from "svelte-i18n";
</script> </script>
<body class="antialiased font-sans"> <section class="container p-5">
<div class="flex min-h-screen"> <span class="mb-1 text-3xl font-extrabold leading-tight">
<div class="w-full bg-white flex items-center justify-center "> {$_('runners')}
<div class="max-w-sm m-8"> </span>
<div class="text-black text-5xl md:text-15xl font-black"> <p class="mb-8 text-lg text-gray-500">läuft bei ihnen</p>
Runners </section>
</div>
<div class="w-16 h-1 bg-purple-light my-3 md:my-6" />
<p
class="text-grey-darker text-2xl md:text-3xl font-light mb-8 leading-normal">
bla
</p>
<a
href="/"
class="bg-transparent text-grey-darkest font-bold uppercase tracking-wide py-3 px-6 border-2 border-grey-light hover:border-grey rounded-lg">{$_('goback')}</a>
</div>
</div>
</div>
</body>

View File

@@ -1,23 +1,13 @@
<script> <script>
import { _ } from "svelte-i18n"; import { _ } from "svelte-i18n";
import FormLayout from "./FormLayout.svelte";
</script> </script>
<style>
* {
font-family: "Agave", sans-serif;
}
</style>
<svelte:head>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@xz/fonts@1/serve/agave.min.css" />
</svelte:head>
<div class="pt-12 px-4 sm:px-6 lg:px-8 lg:pt-20 bg-gray-900 pb-12"> <div class="pt-12 px-4 sm:px-6 lg:px-8 lg:pt-20 bg-gray-900 pb-12">
<div class="text-center mb-8"> <div class="text-center mb-8">
<h1 <h1
class="mt-9 font-display text-4xl leading-none font-semibold text-white sm:text-5xl lg:text-6xl"> class="mt-9 font-display text-4xl leading-none font-semibold text-white sm:text-5xl lg:text-6xl">
🔨<br />Settings 🔨<br />{$_('settings')}
</h1> </h1>
<p <p
class="mt-2 max-w-xl mx-auto text-xl lg:max-w-3xl lg:text-2xl text-gray-300"> class="mt-2 max-w-xl mx-auto text-xl lg:max-w-3xl lg:text-2xl text-gray-300">
@@ -28,11 +18,11 @@
<div class="pt-0 pb-16 bg-gray-50 overflow-hidden lg:pt-12 lg:py-24"> <div class="pt-0 pb-16 bg-gray-50 overflow-hidden lg:pt-12 lg:py-24">
<div class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8"> <div class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
<h2 class="text-4xl font-display font-semibold text-gray-900 md:text-5xl"> <!-- <h2 class="text-4xl font-display font-semibold text-gray-900 md:text-5xl">
General General
</h2> </h2> -->
<div <div
class="max-w-3xl mx-auto text-xl leading-8 font-medium text-gray-900 mt-8"> class="max-w-3xl mx-auto text-xl leading-8 font-medium text-gray-900 mb-16">
<p class="text-center"> <p class="text-center">
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Temporibus et Lorem ipsum dolor sit amet consectetur, adipisicing elit. Temporibus et
amet voluptate nulla accusantium vero blanditiis nobis facere veritatis. amet voluptate nulla accusantium vero blanditiis nobis facere veritatis.
@@ -40,5 +30,6 @@
fugit iusto dolorem? fugit iusto dolorem?
</p> </p>
</div> </div>
<FormLayout />
</div> </div>
</div> </div>

View File

@@ -1,27 +1,24 @@
<script> <script>
import { StatsService } from "@odit/lfk-client-js";
import { _ } from "svelte-i18n"; import { _ } from "svelte-i18n";
import { TrackService, StatsService } from "@odit/lfk-client-js";
const stats_promise = StatsService.statsControllerGet(); const stats_promise = StatsService.statsControllerGet();
stats_promise.then((res) => {
console.log(res);
});
</script> </script>
<!-- --> <!-- -->
<h1>Allgemeine Statistiken</h1> <h1>{$_('general-stats')}</h1>
{#await stats_promise} {#await stats_promise}
<div <div
class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2" class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
role="alert"> role="alert">
<p class="font-bold">stats are being loaded...</p> <p class="font-bold">{$_('stats-are-being-loaded')}</p>
<p class="text-sm">This might take a moment 👀</p> <p class="text-sm">{$_('this-might-take-a-moment')}</p>
</div> </div>
{:then stats} {:then stats}
<div <div
class="flex flex-col lg:flex-row w-full lg:space-x-2 space-y-2 lg:space-y-0 mb-2 lg:mb-4"> class="flex flex-col lg:flex-row w-full lg:space-x-2 space-y-2 lg:space-y-0 mb-2 lg:mb-4">
<div class="w-full lg:w-1/4"> <a href="/runners/" class="w-full lg:w-1/4">
<div <div
class="widget w-full p-4 rounded-lg bg-white border border-grey-100 dark:bg-grey-895 dark:border-grey-890"> class="widget w-full p-4 rounded-lg bg-white border border-grey-100 dark:bg-grey-895 dark:border-grey-890 dark:bg-gray-900 dark:text-white">
<div class="flex flex-row items-center justify-between"> <div class="flex flex-row items-center justify-between">
<div class="flex flex-col"> <div class="flex flex-col">
<div class="text-xs uppercase font-light text-grey-500"> <div class="text-xs uppercase font-light text-grey-500">
@@ -32,16 +29,17 @@
<svg <svg
height="24" height="24"
width="24" width="24"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none" /> viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none" />
<path <path
d="M13.49 5.48c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm-3.6 13.9l1-4.4 2.1 2v6h2v-7.5l-2.1-2 .6-3c1.3 1.5 3.3 2.5 5.5 2.5v-2c-1.9 0-3.5-1-4.3-2.4l-1-1.6c-.4-.6-1-1-1.7-1-.3 0-.5.1-.8.1l-5.2 2.2v4.7h2v-3.4l1.8-.7-1.6 8.1-4.9-1-.4 2 7 1.4z" /></svg> d="M13.49 5.48c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm-3.6 13.9l1-4.4 2.1 2v6h2v-7.5l-2.1-2 .6-3c1.3 1.5 3.3 2.5 5.5 2.5v-2c-1.9 0-3.5-1-4.3-2.4l-1-1.6c-.4-.6-1-1-1.7-1-.3 0-.5.1-.8.1l-5.2 2.2v4.7h2v-3.4l1.8-.7-1.6 8.1-4.9-1-.4 2 7 1.4z" /></svg>
</div> </div>
</div> </div>
</div> </a>
<div class="w-full lg:w-1/4"> <div class="w-full lg:w-1/4">
<div <div
class="widget w-full p-4 rounded-lg bg-white border border-grey-100 dark:bg-grey-895 dark:border-grey-890"> class="widget w-full p-4 rounded-lg bg-white border border-grey-100 dark:bg-grey-895 dark:border-grey-890 dark:bg-gray-900 dark:text-white">
<div class="flex flex-row items-center justify-between"> <div class="flex flex-row items-center justify-between">
<div class="flex flex-col"> <div class="flex flex-col">
<div class="text-xs uppercase font-light text-grey-500"> <div class="text-xs uppercase font-light text-grey-500">
@@ -50,7 +48,7 @@
<div class="text-xl font-bold">{stats.total_scans}</div> <div class="text-xl font-bold">{stats.total_scans}</div>
</div><svg </div><svg
stroke="currentColor" stroke="currentColor"
fill="none" fill="currentColor"
stroke-width="2" stroke-width="2"
viewBox="0 0 24 24" viewBox="0 0 24 24"
stroke-linecap="round" stroke-linecap="round"
@@ -66,7 +64,7 @@
</div> </div>
<div class="w-full lg:w-1/4"> <div class="w-full lg:w-1/4">
<div <div
class="widget w-full p-4 rounded-lg bg-white border border-grey-100 dark:bg-grey-895 dark:border-grey-890"> class="widget w-full p-4 rounded-lg bg-white border border-grey-100 dark:bg-grey-895 dark:border-grey-890 dark:bg-gray-900 dark:text-white">
<div class="flex flex-row items-center justify-between"> <div class="flex flex-row items-center justify-between">
<div class="flex flex-col"> <div class="flex flex-col">
<div class="text-xs uppercase font-light text-grey-500"> <div class="text-xs uppercase font-light text-grey-500">
@@ -76,6 +74,7 @@
</div><svg </div><svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
height="24" height="24"
fill="currentColor"
width="24"><path d="M0 0h24v24H0z" fill="none" /> width="24"><path d="M0 0h24v24H0z" fill="none" />
<path <path
d="M15 18.5A6.48 6.48 0 019.24 15H15v-2H8.58c-.05-.33-.08-.66-.08-1s.03-.67.08-1H15V9H9.24A6.491 6.491 0 0115 5.5c1.61 0 3.09.59 4.23 1.57L21 5.3A8.955 8.955 0 0015 3c-3.92 0-7.24 2.51-8.48 6H3v2h3.06a8.262 8.262 0 000 2H3v2h3.52c1.24 3.49 4.56 6 8.48 6 2.31 0 4.41-.87 6-2.3l-1.78-1.77c-1.13.98-2.6 1.57-4.22 1.57z" /></svg> d="M15 18.5A6.48 6.48 0 019.24 15H15v-2H8.58c-.05-.33-.08-.66-.08-1s.03-.67.08-1H15V9H9.24A6.491 6.491 0 0115 5.5c1.61 0 3.09.59 4.23 1.57L21 5.3A8.955 8.955 0 0015 3c-3.92 0-7.24 2.51-8.48 6H3v2h3.06a8.262 8.262 0 000 2H3v2h3.52c1.24 3.49 4.56 6 8.48 6 2.31 0 4.41-.87 6-2.3l-1.78-1.77c-1.13.98-2.6 1.57-4.22 1.57z" /></svg>
@@ -84,7 +83,7 @@
</div> </div>
<div class="w-full lg:w-1/4"> <div class="w-full lg:w-1/4">
<div <div
class="widget w-full p-4 rounded-lg bg-white border border-grey-100 dark:bg-grey-895 dark:border-grey-890"> class="widget w-full p-4 rounded-lg bg-white border border-grey-100 dark:bg-grey-895 dark:border-grey-890 dark:bg-gray-900 dark:text-white">
<div class="flex flex-row items-center justify-between"> <div class="flex flex-row items-center justify-between">
<div class="flex flex-col"> <div class="flex flex-col">
<div class="text-xs uppercase font-light text-grey-500"> <div class="text-xs uppercase font-light text-grey-500">
@@ -95,17 +94,19 @@
km km
</div> </div>
</div> </div>
<svg xmlns="http://www.w3.org/2000/svg" height="24" width="24"><path <svg
d="M0 0h24v24H0z" fill="currentColor"
fill="none" /> xmlns="http://www.w3.org/2000/svg"
height="24"
width="24"><path d="M0 0h24v24H0z" fill="none" />
<path <path
d="M21 6H3c-1.1 0-2 .9-2 2v8c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 10H3V8h2v4h2V8h2v4h2V8h2v4h2V8h2v4h2V8h2v8z" /></svg> d="M21 6H3c-1.1 0-2 .9-2 2v8c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 10H3V8h2v4h2V8h2v4h2V8h2v4h2V8h2v4h2V8h2v8z" /></svg>
</div> </div>
</div> </div>
</div> </div>
<div class="w-full lg:w-1/4"> <a href="/teams/" class="w-full lg:w-1/4">
<div <div
class="widget w-full p-4 rounded-lg bg-white border border-grey-100 dark:bg-grey-895 dark:border-grey-890"> class="widget w-full p-4 rounded-lg bg-white border border-grey-100 dark:bg-grey-895 dark:border-grey-890 dark:bg-gray-900 dark:text-white">
<div class="flex flex-row items-center justify-between"> <div class="flex flex-row items-center justify-between">
<div class="flex flex-col"> <div class="flex flex-col">
<div class="text-xs uppercase font-light text-grey-500"> <div class="text-xs uppercase font-light text-grey-500">
@@ -131,10 +132,10 @@
<path d="M16 3.13a4 4 0 0 1 0 7.75" /></svg> <path d="M16 3.13a4 4 0 0 1 0 7.75" /></svg>
</div> </div>
</div> </div>
</div> </a>
<div class="w-full lg:w-1/4"> <a href="/orgs/" class="w-full lg:w-1/4">
<div <div
class="widget w-full p-4 rounded-lg bg-white border border-grey-100 dark:bg-grey-895 dark:border-grey-890"> class="widget w-full p-4 rounded-lg bg-white border border-grey-100 dark:bg-grey-895 dark:border-grey-890 dark:bg-gray-900 dark:text-white">
<div class="flex flex-row items-center justify-between"> <div class="flex flex-row items-center justify-between">
<div class="flex flex-col"> <div class="flex flex-col">
<div class="text-xs uppercase font-light text-grey-500"> <div class="text-xs uppercase font-light text-grey-500">
@@ -144,6 +145,7 @@
</div> </div>
<svg <svg
height="24" height="24"
fill="currentColor"
width="24" width="24"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z" /> viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z" />
@@ -151,7 +153,7 @@
d="M17 11V3H7v4H3v14h8v-4h2v4h8V11h-4zM7 19H5v-2h2v2zm0-4H5v-2h2v2zm0-4H5V9h2v2zm4 4H9v-2h2v2zm0-4H9V9h2v2zm0-4H9V5h2v2zm4 8h-2v-2h2v2zm0-4h-2V9h2v2zm0-4h-2V5h2v2zm4 12h-2v-2h2v2zm0-4h-2v-2h2v2z" /></svg> d="M17 11V3H7v4H3v14h8v-4h2v4h8V11h-4zM7 19H5v-2h2v2zm0-4H5v-2h2v2zm0-4H5V9h2v2zm4 4H9v-2h2v2zm0-4H9V9h2v2zm0-4H9V5h2v2zm4 8h-2v-2h2v2zm0-4h-2V9h2v2zm0-4h-2V5h2v2zm4 12h-2v-2h2v2zm0-4h-2v-2h2v2z" /></svg>
</div> </div>
</div> </div>
</div> </a>
</div> </div>
{:catch error} {:catch error}
<div class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500"> <div class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500">

View File

@@ -32,7 +32,7 @@
</th> </th>
</tr> </tr>
</thead> </thead>
<tbody class="bg-white divide-y divide-gray-200"> <tbody class="divide-y divide-gray-200">
<tr> <tr>
<td class="px-6 py-4 whitespace-nowrap"> <td class="px-6 py-4 whitespace-nowrap">
<div class="flex items-center"> <div class="flex items-center">

View File

@@ -0,0 +1,10 @@
<script>
import { _ } from "svelte-i18n";
</script>
<section class="container p-5">
<span class="mb-1 text-3xl font-extrabold leading-tight">
{$_('teams')}
</span>
<p class="mb-8 text-lg text-gray-500">everything is more fun together 🏃‍♂️🏃‍♀️🏃‍♂️</p>
</section>

View File

@@ -1,63 +1,182 @@
<script> <script>
import { _, json } from "svelte-i18n"; import { _, json } from "svelte-i18n";
import Toastify from "toastify-js";
import TracksEmptyState from "./TracksEmptyState.svelte"; import TracksEmptyState from "./TracksEmptyState.svelte";
import store from "../store.js";
import { TrackService } from "@odit/lfk-client-js"; import { TrackService } from "@odit/lfk-client-js";
let tracks_promise = TrackService.trackControllerGetAll(); const tracks_promise = TrackService.trackControllerGetAll();
//
import { getlang } from "./datatable_i18n"; import { getlang } from "./datatable_i18n";
import { Grid } from "gridjs"; import { Grid, html } from "gridjs";
import "gridjs/dist/theme/mermaid.css"; import "gridjs/dist/theme/mermaid.css";
// import { tracks as tracksstore } from "../store.js";
$: trackscache = [];
$: blocked = [];
let table; let table;
tracks_promise.then((data) => { let datatable;
let tabledata = []; let datatable_inited = false;
data.forEach((track) => { tracksstore.subscribe((val) => {
tabledata.push([track.name, track.distance, "blablub"]); trackscache = val;
});
console.log(tabledata);
// console.log(data);
const datatable = new Grid({
columns: ["Name", "Track Length in m", "Action"],
language: getlang($json("datatable")),
sort: true,
search: { enabled: true },
data: tabledata,
pagination: {
enabled: true,
limit: 25,
summary: false,
},
});
setTimeout(() => { setTimeout(() => {
datatable.render(table); if (val.length > 0) {
}, 150); renderdatatable();
table_visible = true; }
}, 100);
}); });
let table_visible = false; tracks_promise.then((data) => {
tracksstore.set(data);
});
window.track__edit_cancel = () => renderdatatable();
window.track__edit_save = () => {
const trackid = parseInt(window.event.target.getAttribute("data-trackid"));
if (blocked.includes(trackid)) {
//
} else {
blocked.push(trackid);
const elem = document.querySelector(
`[data-id="triggered_table_actions_${trackid}"]`
).parentNode.parentNode.parentNode;
Toastify({
text: "Track is being updated...",
duration: 500,
}).showToast();
TrackService.trackControllerPut(trackid, {
id: trackid,
name: elem.childNodes[0].childNodes[0].value,
distance: parseInt(elem.childNodes[1].childNodes[0].value),
minimumLapTime: parseInt(elem.childNodes[2].childNodes[0].value),
})
.then((r) => {
Toastify({
text: "Track was updated!",
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
duration: 1000,
}).showToast();
blocked = blocked.filter((e) => e !== trackid);
document
.querySelector(`[data-id="default_table_actions_${trackid}"]`)
.classList.remove("hidden");
document
.querySelector(`[data-id="triggered_table_actions_${trackid}"]`)
.classList.add("hidden");
//
elem.childNodes[0].innerHTML = `<td data-column-id="trackName" class="gridjs-td">${elem.childNodes[0].childNodes[0].value}</td>`;
elem.childNodes[1].innerHTML = `<td data-column-id="trackName" class="gridjs-td">${elem.childNodes[1].childNodes[0].value}</td>`;
elem.childNodes[2].innerHTML = `<td data-column-id="trackName" class="gridjs-td">${elem.childNodes[2].childNodes[0].value}</td>`;
})
.catch((err) => {
console.error(err);
});
}
};
window.track__delete_handler = () => {
const trackid = parseInt(window.event.target.getAttribute("data-trackid"));
document
.querySelector(`[data-id="default_table_actions_${trackid}"]`)
.classList.add("hidden");
document
.querySelector(`[data-id="deleteconfirmation_table_actions_${trackid}"]`)
.classList.remove("hidden");
};
window.track__delete_cancel = () => {
const trackid = parseInt(window.event.target.getAttribute("data-trackid"));
document
.querySelector(`[data-id="default_table_actions_${trackid}"]`)
.classList.remove("hidden");
document
.querySelector(`[data-id="deleteconfirmation_table_actions_${trackid}"]`)
.classList.add("hidden");
};
window.track__delete_confirm = () => {
const trackid = parseInt(window.event.target.getAttribute("data-trackid"));
TrackService.trackControllerRemove(trackid)
.then(() => {
const newStoreVal = trackscache.filter((obj) => obj.id !== trackid);
tracksstore.set(newStoreVal);
renderdatatable();
})
.catch((err) => {
console.log(err);
});
};
window.track__edit_handler = () => {
const trackid = parseInt(window.event.target.getAttribute("data-trackid"));
document
.querySelector(`[data-id="default_table_actions_${trackid}"]`)
.classList.add("hidden");
document
.querySelector(`[data-id="triggered_table_actions_${trackid}"]`)
.classList.remove("hidden");
const elem = document.querySelector(
`[data-id="triggered_table_actions_${trackid}"]`
).parentNode.parentNode.parentNode;
const trackname = elem.childNodes[0].textContent;
const tracklength = parseInt(elem.childNodes[1].textContent);
const trackmintime = parseInt(elem.childNodes[2].textContent);
elem.childNodes[0].innerHTML = `<input type="text" value="${trackname}" name="trackname" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2">`;
elem.childNodes[1].innerHTML = `<input type="text" value="${tracklength}" name="tracklength" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2">`;
elem.childNodes[2].innerHTML = `<input type="text" value="${trackmintime}" name="trackmintime" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2">`;
};
//
function renderdatatable() {
let tabledata = [];
trackscache.forEach((track) => {
tabledata.push([
track.name,
track.distance,
track.minimumLapTime || 0,
html(`
<div class="hidden" data-id="triggered_table_actions_${track.id}">
<button class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-green-400 text-base font-medium text-white sm:w-auto sm:text-sm" data-trackid="${track.id}" onclick="track__edit_save()">Save</button>
<button class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-500 text-base font-medium text-white sm:w-auto sm:text-sm" data-trackid="${track.id}" onclick="track__edit_cancel()">Cancel</button>
</div>
<div data-id="default_table_actions_${track.id}">
<button class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-gray-400 text-base font-medium text-white sm:w-auto sm:text-sm" data-trackid="${track.id}" onclick="track__edit_handler()">Edit</button>
<button class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-500 text-base font-medium text-white sm:w-auto sm:text-sm" data-trackid="${track.id}" onclick="track__delete_handler()">Delete</button>
</div>
<div class="hidden" data-id="deleteconfirmation_table_actions_${track.id}">
<button class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-gray-400 text-base font-medium text-white sm:w-auto sm:text-sm" data-trackid="${track.id}" onclick="track__delete_cancel()">Cancel</button>
<button class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-500 text-base font-medium text-white sm:w-auto sm:text-sm" data-trackid="${track.id}" onclick="track__delete_confirm()">Confirm</button>
</div>
`),
]);
});
if (datatable_inited === false) {
datatable = new Grid({
columns: [
$_("track-name"),
$_("track-length-in-m"),
$_("minimum-lap-time-in-s"),
$_("action"),
],
language: getlang($json("datatable")),
sort: true,
search: { enabled: true },
data: tabledata,
pagination: {
enabled: true,
limit: 25,
summary: false,
},
}).render(table);
datatable_inited = true;
} else {
datatable.updateConfig({ data: tabledata }).forceRender();
}
}
</script> </script>
{#if table_visible} {#if trackscache.length > 0}
<div bind:this={table} /> <div bind:this={table} />
{/if} {/if}
{#await tracks_promise} {#await tracks_promise}
<div <div
class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2" class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
role="alert"> role="alert">
<p class="font-bold">track data is being loaded...</p> <p class="font-bold">{$_('track-data-is-being-loaded')}</p>
<p class="text-sm">This might take a moment 👀</p> <p class="text-sm">{$_('this-might-take-a-moment')}</p>
</div> </div>
{:then tracks} {:then}
{#if tracks.length > 0} {#if trackscache.length === 0}
<h4>{tracks.length}</h4>
<hr />
<ul>
{#each tracks as item}
<li>{item.name}</li>
<li>{item.distance}</li>
{/each}
</ul>
{:else}
<TracksEmptyState /> <TracksEmptyState />
{/if} {/if}
{:catch error} {:catch error}

View File

@@ -1,14 +1,7 @@
<script> <script>
import { _ } from "svelte-i18n"; import { _ } from "svelte-i18n";
import store from "../store.js";
import { TrackService } from "@odit/lfk-client-js";
import AddTrackModal from "./AddTrackModal.svelte"; import AddTrackModal from "./AddTrackModal.svelte";
let tracks_promise = TrackService.trackControllerGetAll();
let modal_open = false; let modal_open = false;
function getNewID() {
console.log("got new id");
return Date.now();
}
</script> </script>
<div class="text-center items-center justify-center"> <div class="text-center items-center justify-center">
@@ -260,17 +253,7 @@
d="M714.88 703.47l18.16-4.26v4.26l-18.16 4.26v-4.26zM931.72 628.54l18.16-4.26v4.26l-18.16 4.25v-4.25z" /></svg> d="M714.88 703.47l18.16-4.26v4.26l-18.16 4.26v-4.26zM931.72 628.54l18.16-4.26v4.26l-18.16 4.25v-4.25z" /></svg>
<p class="mb-16 text-lg text-gray-500"> <p class="mb-16 text-lg text-gray-500">
<span class="font-bold">{$_('no-tracks-added-yet')}</span><br /> <span class="font-bold">{$_('no-tracks-added-yet')}</span><br />
<span <span>{$_('add-your-first-track')}</span>
on:click={() => {
modal_open = true;
}}
class="underline text-blue-500 cursor-pointer">{$_('add-your-first-track')}</span>
<br />
<span
on:click={() => {
modal_open = true;
}}
class="cursor-pointer inline-flex items-center px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">{$_('add-your-first-track')}</span>
</p> </p>
</div> </div>

View File

@@ -1,14 +1,25 @@
<script> <script>
import { _ } from "svelte-i18n"; import { _ } from "svelte-i18n";
import AddTrackModal from "./AddTrackModal.svelte";
let modal_open = false;
import Tracks from "./Tracks.svelte"; import Tracks from "./Tracks.svelte";
</script> </script>
<section class="container py-10 mx-auto sm:px-2"> <section class="container p-5">
<span class="mb-1 text-3xl font-extrabold leading-tight text-gray-900"> <span class="mb-1 text-3xl font-extrabold leading-tight">
Tracks Tracks
<button
on:click={() => {
modal_open = true;
}}
type="button"
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">
Create Track
</button>
</span> </span>
<p class="mb-16 text-lg text-gray-500"> <p class="mb-8 text-lg text-gray-500">
configure the tracks/ min-max lap times configure the tracks & minimum lap times
</p> </p>
<Tracks /> <Tracks />
</section> </section>
<AddTrackModal bind:modal_open />

View File

@@ -0,0 +1,171 @@
<script>
import { _ } from "svelte-i18n";
import lodashIsEqual from "lodash.isequal";
import { UserService } from "@odit/lfk-client-js";
import "gridjs/dist/theme/mermaid.css";
import PromiseError from "./PromiseError.svelte";
export let params;
const user_promise = UserService.userControllerGetOne(params.userid);
let data_loaded = false;
let original_data = undefined;
$: editable_userdata = undefined;
user_promise.then((data) => {
data_loaded = true;
original_data = data;
editable_userdata = data;
});
// $: changes_performed = lodashIsEqual(original_data, editable_userdata);
$: changes_performed = !lodashIsEqual({ test: 1 }, { test: 1 });
function submit() {
if (data_loaded === true && changes_performed === true) {
console.log("ok, submitting...");
} else {
console.log("no changes performed");
}
}
</script>
{#await user_promise}
<!-- -->
{:then user}
<section class="container p-5 select-none">
<div class="flex flex-row mb-4">
<div class="w-full">
<nav class="w-full flex">
<ol class="list-none flex flex-row items-center justify-start">
<li class="flex items-center">
<svg
class="flex-shrink-0 w-5 h-5 mr-2"
fill="currentColor"
width="24"
height="24"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 640 512"><path
fill="currentColor"
d="M610.5 341.3c2.6-14.1 2.6-28.5 0-42.6l25.8-14.9c3-1.7 4.3-5.2 3.3-8.5-6.7-21.6-18.2-41.2-33.2-57.4-2.3-2.5-6-3.1-9-1.4l-25.8 14.9c-10.9-9.3-23.4-16.5-36.9-21.3v-29.8c0-3.4-2.4-6.4-5.7-7.1-22.3-5-45-4.8-66.2 0-3.3.7-5.7 3.7-5.7 7.1v29.8c-13.5 4.8-26 12-36.9 21.3l-25.8-14.9c-2.9-1.7-6.7-1.1-9 1.4-15 16.2-26.5 35.8-33.2 57.4-1 3.3.4 6.8 3.3 8.5l25.8 14.9c-2.6 14.1-2.6 28.5 0 42.6l-25.8 14.9c-3 1.7-4.3 5.2-3.3 8.5 6.7 21.6 18.2 41.1 33.2 57.4 2.3 2.5 6 3.1 9 1.4l25.8-14.9c10.9 9.3 23.4 16.5 36.9 21.3v29.8c0 3.4 2.4 6.4 5.7 7.1 22.3 5 45 4.8 66.2 0 3.3-.7 5.7-3.7 5.7-7.1v-29.8c13.5-4.8 26-12 36.9-21.3l25.8 14.9c2.9 1.7 6.7 1.1 9-1.4 15-16.2 26.5-35.8 33.2-57.4 1-3.3-.4-6.8-3.3-8.5l-25.8-14.9zM496 368.5c-26.8 0-48.5-21.8-48.5-48.5s21.8-48.5 48.5-48.5 48.5 21.8 48.5 48.5-21.7 48.5-48.5 48.5zM96 224c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm224 32c1.9 0 3.7-.5 5.6-.6 8.3-21.7 20.5-42.1 36.3-59.2 7.4-8 17.9-12.6 28.9-12.6 6.9 0 13.7 1.8 19.6 5.3l7.9 4.6c.8-.5 1.6-.9 2.4-1.4 7-14.6 11.2-30.8 11.2-48 0-61.9-50.1-112-112-112S208 82.1 208 144c0 61.9 50.1 112 112 112zm105.2 194.5c-2.3-1.2-4.6-2.6-6.8-3.9-8.2 4.8-15.3 9.8-27.5 9.8-10.9 0-21.4-4.6-28.9-12.6-18.3-19.8-32.3-43.9-40.2-69.6-10.7-34.5 24.9-49.7 25.8-50.3-.1-2.6-.1-5.2 0-7.8l-7.9-4.6c-3.8-2.2-7-5-9.8-8.1-3.3.2-6.5.6-9.8.6-24.6 0-47.6-6-68.5-16h-8.3C179.6 288 128 339.6 128 403.2V432c0 26.5 21.5 48 48 48h255.4c-3.7-6-6.2-12.8-6.2-20.3v-9.2zM173.1 274.6C161.5 263.1 145.6 256 128 256H64c-35.3 0-64 28.7-64 64v32c0 17.7 14.3 32 32 32h65.9c6.3-47.4 34.9-87.3 75.2-109.4z" /></svg>
</li>
<li class="flex items-center">
<a class="mr-2" href="./">{$_('users')}</a><svg
stroke="currentColor"
fill="none"
stroke-width="2"
viewBox="0 0 24 24"
stroke-linecap="round"
stroke-linejoin="round"
class="h-3 w-3 mr-2 stroke-current"
height="1em"
width="1em"
xmlns="http://www.w3.org/2000/svg"><line
x1="5"
y1="12"
x2="19"
y2="12" />
<polyline points="12 5 19 12 12 19" /></svg>
</li>
<li class="flex items-center">
<span class="mr-2">{user.firstname}
{user.middlename || ''}
{user.lastname}</span>
</li>
</ol>
</nav>
</div>
</div>
<div class="mb-8 text-3xl font-extrabold leading-tight">
{user.firstname}
{user.middlename || ''}
{user.lastname}
<span data-id="user_actions_${user.id}">
<button
class="hidden w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-green-400 text-base font-medium text-white sm:w-auto sm:text-sm"
data-userid="${user.id}"
onclick="user__delete_cancel()">{$_('cancel')}</button>
<button
class="hidden w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-500 text-base font-medium text-white sm:w-auto sm:text-sm"
data-userid="${user.id}"
onclick="user__delete_confirm()">{$_('confirm-delete')}</button>
<button
type="button"
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm">{$_('delete-user')}</button>
<button
disabled={!changes_performed}
class:opacity-50={!changes_performed}
type="button"
on:click={submit}
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">{$_('save-changes')}</button>
</span>
</div>
<!-- -->
<div class="mt-2 flex items-center">
<img
alt={$_('profile-picture')}
class="inline-block h-20 w-20 rounded-full overflow-hidden bg-gray-100"
src={user.profilePic} />
<!-- <span
class="inline-block h-12 w-12 rounded-full overflow-hidden bg-gray-100"><svg
class="h-full w-full text-gray-300"
fill="currentColor"
viewBox="0 0 24 24"><path
d="M24 20.993V24H0v-2.996A14.977 14.977 0 0112.004 15c4.904 0 9.26 2.354 11.996 5.993zM16.002 8.999a4 4 0 11-8 0 4 4 0 018 0z" /></svg></span> -->
<button
type="button"
class="ml-5 bg-white py-2 px-3 border border-gray-300 rounded-md shadow-sm text-sm leading-4 font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">Change</button>
</div>
<!-- -->
<div class="mt-3 text-sm w-full">
<input
id="enabled"
on:change={() => {
editable_userdata.enabled = !editable_userdata.enabled;
// TODO: this reactive set does not work?
}}
name="enabled"
type="checkbox"
checked={editable_userdata.enabled}
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded" />
<label
for="enabled"
class="ml-1 font-medium text-gray-700">Active?</label>
<p class="text-gray-500">set the user active/ inactive</p>
</div>
<div class="text-sm w-full">
<label
for="firstname"
class="font-medium text-gray-700">{$_('first-name')}</label>
<input
autocomplete="off"
placeholder={$_('first-name')}
type="text"
bind:value={editable_userdata.firstname}
name="firstname"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 dark:bg-gray-900 dark:text-gray-100 rounded-md p-2" />
</div>
<div class="text-sm w-full">
<label
for="middlename"
class="font-medium text-gray-700">{$_('middle-name')}</label>
<input
autocomplete="off"
placeholder={$_('middle-name')}
type="text"
bind:value={editable_userdata.middlename}
name="middlename"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 dark:bg-gray-900 dark:text-gray-100 rounded-md p-2" />
</div>
<div class="text-sm w-full">
<label
for="lastname"
class="font-medium text-gray-700">{$_('last-name')}</label>
<input
autocomplete="off"
placeholder={$_('last-name')}
type="text"
bind:value={editable_userdata.lastname}
name="lastname"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 dark:bg-gray-900 dark:text-gray-100 rounded-md p-2" />
</div>
</section>
{:catch error}
<PromiseError {error} />
{/await}

View File

@@ -1,23 +1,23 @@
<script> <script>
import { _ } from "svelte-i18n"; import { _ } from "svelte-i18n";
import AddUserModal from "./AddUserModal.svelte";
export let modal_open = false;
import UsersOverview from "./UsersOverview.svelte";
</script> </script>
<body class="antialiased font-sans"> <section class="container p-5">
<div class="flex min-h-screen"> <span class="mb-1 text-3xl font-extrabold leading-tight">
<div class="w-full bg-white flex items-center justify-center "> {$_('users')}
<div class="max-w-sm m-8"> <button
<div class="text-black text-5xl md:text-15xl font-black"> on:click={() => {
Users modal_open = true;
</div> }}
<div class="w-16 h-1 bg-purple-light my-3 md:my-6" /> type="button"
<p class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">
class="text-grey-darker text-2xl md:text-3xl font-light mb-8 leading-normal"> {$_('create-user')}
bla </button>
</p> </span>
<a <p class="mb-8 text-lg text-gray-500">{$_('manage-admin-users')}</p>
href="/" <UsersOverview />
class="bg-transparent text-grey-darkest font-bold uppercase tracking-wide py-3 px-6 border-2 border-grey-light hover:border-grey rounded-lg">{$_('goback')}</a> </section>
</div> <AddUserModal bind:modal_open />
</div>
</div>
</body>

View File

@@ -0,0 +1,14 @@
<script>
import { _ } from "svelte-i18n";
import AddUserModal from "./AddUserModal.svelte";
let modal_open = false;
</script>
<div class="text-center items-center justify-center">
<p class="mb-16 text-lg text-gray-500">
<span class="font-bold">There are no users added yet.</span><br />
<span>Add your first user</span>
</p>
</div>
<AddUserModal bind:modal_open />

View File

@@ -0,0 +1,147 @@
<script>
import { _ } from "svelte-i18n";
import Toastify from "toastify-js";
import { UserService } from "@odit/lfk-client-js";
const users_promise = UserService.userControllerGetAll();
import "gridjs/dist/theme/mermaid.css";
import { users as usersstore } from "../store.js";
import UsersEmptyState from "./UsersEmptyState.svelte";
$: searchvalue = "";
$: userscache = [];
$: advanced_search = false;
usersstore.subscribe((val) => {
userscache = val;
});
users_promise.then((data) => {
console.log(data);
usersstore.set(data);
});
</script>
{#await users_promise}
<div
class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
role="alert">
<p class="font-bold">users are being loaded...</p>
<p class="text-sm">{$_('this-might-take-a-moment')}</p>
</div>
{:then users}
{#if userscache.length === 0}
<UsersEmptyState />
{:else}
{#if advanced_search}
advanced search
{:else}
<input
type="search"
bind:value={searchvalue}
placeholder={$_('datatable.search')}
aria-label={$_('datatable.search')}
class="gridjs-input gridjs-search-input mb-4" />
{/if}
<button
on:click={() => {
advanced_search = !advanced_search;
}}
type="button"
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-gray-600 text-base font-medium text-white hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 sm:ml-3 sm:w-auto sm:text-sm">
{#if advanced_search}
toggle simple search
{:else}toggle advanced search{/if}
</button>
<div
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll">
<table class="divide-y divide-gray-200 w-full">
<thead class="bg-gray-50">
<tr>
<th
scope="col"
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Name
</th>
<th
scope="col"
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Status
</th>
<th
scope="col"
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Groups
</th>
<th scope="col" class="relative px-6 py-3">
<span class="sr-only">Action</span>
</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200">
{#each users as u}
{#if Object.values(u)
.toString()
.toLowerCase()
.includes(searchvalue)}
<tr>
<td class="px-6 py-4 whitespace-nowrap">
<div class="flex items-center">
{#if u.profilePic}
<div class="flex-shrink-0 h-10 w-10">
<img
class="h-10 w-10 rounded-full"
src={u.profilePic}
alt="" />
</div>
{/if}
<div class="ml-4">
<div
class="text-sm font-medium text-gray-900 dark:text-gray-100">
{u.firstname}
{u.middlename || ''}
{u.lastname}
</div>
<div class="text-sm text-gray-500">
{u.email || u.username}
</div>
</div>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
{#if u.enabled}
<span
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">Active</span>
{:else}
<span
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800">Inactive</span>
{/if}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
{#each u.groups as g}
<a
href="../groups/{g.id}"
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800">{g.name}</a>
{/each}
</td>
<td
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
<a
href="./{u.id}"
class="text-indigo-600 hover:text-indigo-900">Edit</a>
<span
tabindex="0"
href="#"
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">Delete</span>
</td>
</tr>
{/if}
{/each}
</tbody>
</table>
</div>
{/if}
{:catch error}
<div class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500">
<span class="inline-block align-middle mr-8">
<b class="capitalize">{$_('general_promise_error')}</b>
{error}
</span>
</div>
{/await}

View File

@@ -0,0 +1,10 @@
/** Dispatch event on click outside of node */
export function clickOutside(node) {
const handleClick = (event) => {
if (event.target.getAttribute('data-id') === 'modal_backdrop') {
node.dispatchEvent(new CustomEvent('click_outside', node));
}
};
document.removeEventListener('click', handleClick, true);
document.addEventListener('click', handleClick, true);
}

View File

@@ -1,43 +1,47 @@
{ {
"forgot_password?": "Passwort vergessen?", "404message": "Die gesuchte Seite wurde leider nicht gefunden.",
"log_in": "Anmelden", "404title": "Fehler 404",
"log_in_to_your_account": "Bitte melde dich an", "about": "Über",
"login_is_checked": "Login wird überprüft", "application_name": "Lauf für Kaya! \n- Admin",
"welcome_wavinghand": "Willkommen 👋", "by": "von",
"error_on_login": "😢Fehler beim Login", "cannot-reset-your-password-directly": "Schade. \nWir können das Passwort leider nicht direkt zurücksetzen.\nBitte sende uns eine Mail in der du deine Identität bestätigst.",
"settings": "Einstellungen", "credits": "",
"your_profile": "Dein Profil", "dashboard-greeting": "Moin",
"password": "Passwort", "datatable": {
"email_address_or_username": "E-Mail-Addresse/ Benutzername", "search": "🔍 Suche ...",
"signout": "Abmelden", "an_error_happened_while_fetching_the_data": "Beim Abrufen der Daten ist ein Fehler aufgetreten",
"404message": "Die gesuchte Seite wurde leider nicht gefunden.", "loading": "Wird geladen...",
"404title": "Fehler 404", "next": "Nächste",
"application_name": "Lauf für Kaya! \n- Admin", "of": "von",
"goback": "Zur Startseite", "previous": "Vorherige",
"cannot-reset-your-password-directly": "Schade. \nWir können das Passwort leider nicht direkt zurücksetzen.\nBitte sende uns eine Mail in der du deine Identität bestätigst.", "to": "bis",
"register": "Registrieren", "showing": "Zeige"
"send-a-mail-to-lfk-odit-services": "Sende eine Mail an lfk@odit.services", },
"dont-panic-were-resetting-it": "Keine Panik, wir setzen es zurück ✌", "dont-have-your-email-connected": "Deine E-Mail ist nicht verknüpft?",
"dont-have-your-email-connected": "Deine E-Mail ist nicht verknüpft?", "dont-panic-were-resetting-it": "Keine Panik, wir setzen es zurück ✌",
"reset-my-password": "Passwort zurücksetzen", "e-mail-adress": "E-Mail-Adresse",
"e-mail-adress": "E-Mail-Adresse", "email_address_or_username": "E-Mail-Addresse/ Benutzername",
"invalid-mail-reset": "Das ist keine gültige E-Mail", "error_on_login": "😢Fehler beim Login",
"datatable": { "forgot_password?": "Passwort vergessen?",
"search": "🔍 Suche ...", "general-stats": "Allgemeine Statistiken",
"an_error_happened_while_fetching_the_data": "Beim Abrufen der Daten ist ein Fehler aufgetreten", "goback": "Zur Startseite",
"loading": "Wird geladen...", "hallo": "hallo",
"next": "Nächste", "invalid-mail-reset": "Das ist keine gültige E-Mail",
"of": "von", "lfk-is-os": "Das \"Lauf für Kaya!\" Frontend ist (wie alle anderen Projekte für den \"LfK!\" auch) ein OpenSource Projekt.",
"previous": "Vorherige" "log_in": "Anmelden",
}, "log_in_to_your_account": "Bitte melde dich an",
"lfk-is-os": "Das \"Lauf für Kaya!\" Frontend ist (wie alle anderen Projekte für den \"LfK!\" auch) ein OpenSource Projekt.", "login_is_checked": "Login wird überprüft",
"oss_credit_description": "Wir verwenden eine Menge Open Source-Software bei diesen Projekten und möchten uns bei den folgenden Projekten und Mitwirkenden bedanken, die dazu beitragen, Open Source großartig zu machen!", "oss_credit_description": "Wir verwenden eine Menge Open Source-Software bei diesen Projekten und möchten uns bei den folgenden Projekten und Mitwirkenden bedanken, die dazu beitragen, Open Source großartig zu machen!",
"about": "Über", "password": "Passwort",
"by": "von", "register": "Registrieren",
"hallo": "hallo", "reset-my-password": "Passwort zurücksetzen",
"total-scans": "gesamte Scans", "runners": "Läufer",
"total-donations": "Spendensumme", "send-a-mail-to-lfk-odit-services": "Sende eine Mail an lfk@odit.services",
"credits": "", "settings": "Einstellungen",
"runners": "Läufer", "signout": "Abmelden",
"total-distance": "gelaufene Strecke" "total-distance": "gelaufene Strecke",
} "total-donations": "Spendensumme",
"total-scans": "gesamte Scans",
"welcome_wavinghand": "Willkommen 👋",
"your_profile": "Dein Profil"
}

View File

@@ -1,61 +1,123 @@
{ {
"forgot_password?": "Forgot your password?", "404message": "Sorry, the page you are looking for could not be found.",
"register": "Register", "404title": "Error 404",
"log_in": "Log in", "about": "About",
"password": "Password", "action": "Action",
"log_in_to_your_account": "Log in to your account", "add-your-first-track": "Add your first track",
"welcome_wavinghand": "Welcome 👋", "application_name": "Lauf für Kaya! - Admin",
"login_is_checked": "Login is being checked...", "author": "Author",
"error_on_login": "Error on login", "browse": "Browse",
"settings": "Settings", "by": "by",
"your_profile": "Your Profile", "cancel": "Cancel",
"email_address_or_username": "Email / username", "cannot-reset-your-password-directly": "Bummer. We unfortunately cannot reset your password directly. Please send us a mail and confirm your identity",
"tracks": "Tracks", "changelog": "Changelog",
"signout": "Sign out", "close": "Close",
"hallo": "hello", "confirm-delete": "Confirm Delete",
"404message": "Sorry, the page you are looking for could not be found.", "count_organizations": "# Organizations",
"404title": "Error 404", "count_teams": "# Teams",
"goback": "Go Home", "create": "Create",
"application_name": "Lauf für Kaya! - Admin", "create-a-new-track": "Create a new Track",
"reset-my-password": "Reset my password", "create-user": "Create User",
"cannot-reset-your-password-directly": "Bummer. We unfortunately cannot reset your password directly. Please send us a mail and confirm your identity", "credits": "Credits",
"send-a-mail-to-lfk-odit-services": "send a mail to lfk@odit.services", "dashboard-greeting": "hello there",
"dont-have-your-email-connected": "Don't have your email connected?", "dashboard-title": "Dashboard",
"dont-panic-were-resetting-it": "Don't panic, we're resetting it ✌", "datatable": {
"e-mail-adress": "E-Mail Adress", "search": "🔍 Search...",
"mail-validation-in-progress": "mail validation in progress...", "sort_column_ascending": "Sort column ascending",
"invalid-mail-reset": "the provided email is invalid", "sort_column_descending": "Sort column descending",
"runners": "runners", "previous": "Previous",
"total-scans": "total scans", "next": "Next",
"total-donations": "total donations", "page": "Page",
"total-distance": "total distance", "showing": "Showing",
"datatable": { "records": "Records",
"search": "🔍 Search...", "of": "of",
"sort_column_ascending": "Sort column ascending", "to": "to",
"sort_column_descending": "Sort column descending", "loading": "Loading...",
"previous": "Previous", "no_matching_records_found": "No matching records found",
"next": "Next", "an_error_happened_while_fetching_the_data": "An error happened while fetching the data"
"page": "Page", },
"showing": "Showing", "delete-user": "Delete User",
"records": "Records", "dependency_name": "Name",
"of": "of", "dont-have-your-email-connected": "Don't have your email connected?",
"to": "to", "dont-panic-were-resetting-it": "Don't panic, we're resetting it ✌",
"loading": "Loading...", "drag-and-drop-your-files-or": "Drag & Drop your files or",
"no_matching_records_found": "No matching records found", "e-mail-adress": "E-Mail Adress",
"an_error_happened_while_fetching_the_data": "An error happened while fetching the data" "email_address_or_username": "Email / username",
}, "error_on_login": "Error on login",
"about": "About", "faq": "FAQ",
"by": "by", "filepond__abort": "Abort",
"lfk-is-os": "The \"Lauf für Kaya!\" Frontend is (like all other projects for the \"LfK!\" Also) an open source project.", "filepond__cancel": "Cancel",
"oss_credit_description": "We use a lot of open source software on these projects, and would like to thank the following projects and contributors who help make open source great!", "filepond__error-during-load": "Error during load",
"credits": "Credits", "filepond__error-during-remove": "Error during remove",
"count_organizations": "# Organizations", "filepond__error-during-revert": "Error during revert",
"count_teams": "# Teams", "filepond__error-during-upload": "Error during upload",
"general_promise_error": "😢 Error", "filepond__field-contains-invalid-files": "Field contains invalid files",
"add-your-first-track": "Add your first track", "filepond__loading": "Loading",
"no-tracks-added-yet": "there are no tracks added yet.", "filepond__remove": "Remove",
"track-length-in-m": "Track length in m", "filepond__retry": "Retry",
"track-name": "Track name", "filepond__size-not-available": "Size not available",
"please-provide-the-required-information-to-add-a-new-track": "Please provide the required information to add a new track.", "filepond__tap-to-cancel": "tap to cancel",
"create-a-new-track": "Create a new Track" "filepond__tap-to-retry": "tap to retry",
} "filepond__tap-to-undo": "tap to undo",
"filepond__undo": "Undo",
"filepond__upload": "Upload",
"filepond__upload-cancelled": "Upload cancelled",
"filepond__upload-complete": "Upload complete",
"filepond__uploading": "Uploading",
"filepond__waiting-for-size": "Waiting for size",
"first-name": "First name",
"first-name-is-required": "First Name is required",
"forgot_password?": "Forgot your password?",
"general-stats": "General Stats",
"general_promise_error": "😢 Error",
"goback": "Go Home",
"hallo": "hello",
"installed-version": "Installed version",
"invalid-mail-reset": "the provided email is invalid",
"last-name": "Last name",
"last-name-is-required": "Last Name is required",
"lfk-is-os": "The \"Lauf für Kaya!\" Frontend is (like all other projects for the \"LfK!\" Also) an open source project.",
"license": "License",
"licenses-are-being-loaded": "Licenses are being loaded...",
"log_in": "Log in",
"log_in_to_your_account": "Log in to your account",
"login_is_checked": "Login is being checked...",
"logout": "Logout",
"mail-validation-in-progress": "mail validation in progress...",
"manage-admin-users": "manage admin users",
"middle-name": "Middle name",
"minimum-lap-time-in-s": "minimum lap time in s",
"no-license-text-could-be-found": "No license text could be found 😢",
"no-tracks-added-yet": "there are no tracks added yet.",
"orgs": "Orgs",
"oss_credit_description": "We use a lot of open source software on these projects, and would like to thank the following projects and contributors who help make open source great!",
"password": "Password",
"password-is-required": "Password is required",
"please-provide-the-required-information-to-add-a-new-track": "Please provide the required information to add a new track.",
"profile-picture": "Profile Picture",
"read-license": "Read License",
"register": "Register",
"repo_link": "Link",
"reset-my-password": "Reset my password",
"runners": "Runners",
"save-changes": "Save Changes",
"send-a-mail-to-lfk-odit-services": "send a mail to lfk@odit.services",
"settings": "Settings",
"signout": "Sign out",
"stats-are-being-loaded": "stats are being loaded...",
"teams": "Teams",
"this-might-take-a-moment": "This might take a moment 👀",
"total-distance": "total distance",
"total-donations": "total donations",
"total-scans": "total scans",
"track-added": "Track added",
"track-data-is-being-loaded": "Track data is being loaded",
"track-is-being-added": "Track is being added...",
"track-length-in-m": "Track Length in m",
"track-name": "Track name",
"tracks": "Tracks",
"users": "Users",
"valid-email-is-required": "valid email is required",
"welcome_wavinghand": "Welcome 👋",
"your_profile": "Your Profile"
}

View File

@@ -1,34 +1,57 @@
import { writable } from 'svelte/store'; import { writable } from 'svelte/store';
import { OpenAPI, AuthService } from '@odit/lfk-client-js';
import localForage from 'localforage';
export let users = writable([]);
export let tracks = writable([]);
const store = () => { const store = () => {
const state = { const state = {
auth: undefined,
access_token: undefined, access_token: undefined,
jwtinfo: undefined, jwtinfo: undefined,
isLoggedIn: false isLoggedIn: false,
refreshInterval: undefined
}; };
const { subscribe, set, update } = writable(state); const { subscribe, set, update } = writable(state);
const methods = { const methods = {
init() { init() {
console.log('*: playerStore -> init()');
update((state) => { update((state) => {
state.isLoggedIn = false; state.isLoggedIn = false;
return state; return state;
}); });
}, },
login(access_token, jwtinfo) { refreshAuth() {
console.log('refreshing auth');
AuthService.authControllerRefresh({ token: state.auth.refresh_token }).then((auth) => {
console.log('got new auth');
OpenAPI.TOKEN = auth.access_token;
localForage.setItem('logindata', auth);
});
},
login(auth, jwtinfo) {
update((state) => { update((state) => {
state.access_token = access_token; state.auth = auth;
state.access_token = auth.access_token;
state.jwtinfo = jwtinfo; state.jwtinfo = jwtinfo;
state.isLoggedIn = true; state.isLoggedIn = true;
console.log('login performed'); //
state.refreshInterval = setInterval(() => {
this.refreshAuth();
// 4min
}, 4 * 60000);
//
return state; return state;
}); });
}, },
logout() { logout() {
update((state) => { update((state) => {
state.isLoggedIn = false; state.isLoggedIn = false;
//
clearInterval(state.refreshInterval);
state.refreshInterval = undefined;
//
return state; return state;
}); });
} }
@@ -42,5 +65,4 @@ const store = () => {
...methods ...methods
}; };
}; };
export default store(); export default store();

14
src/swmodule.js Normal file
View File

@@ -0,0 +1,14 @@
export const register = () => {
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js').then(
(registration) => {
// console.log(`sw successful with scope: ${registration.scope}`);
},
(err) => {
// console.log(`sw failed: ${err}`);
}
);
});
}
};

View File

@@ -1,9 +1,9 @@
const sveltePreprocess = require('svelte-preprocess'); const sveltePreprocess = require('svelte-preprocess');
const preprocess = sveltePreprocess({ const preprocess = sveltePreprocess({
// postcss: { postcss: {
// plugins: [ require('tailwindcss'), require('autoprefixer') ] plugins: [ require('tailwindcss'), require('autoprefixer') ]
// } }
}); });
module.exports = { module.exports = {

5
versionbuilder.js Normal file
View File

@@ -0,0 +1,5 @@
const fs = require('fs');
const package = JSON.parse(fs.readFileSync(`./package.json`, { encoding: 'utf-8' }));
const original = fs.readFileSync(`./public/index.html`, { encoding: 'utf-8' });
let out = original.replace(/RELEASE_INFO-(\S)+-RELEASE_INFO/gi, 'RELEASE_INFO-' + package.version + '-RELEASE_INFO');
fs.writeFileSync(`./public/index.html`, out);

View File

@@ -1,7 +1,6 @@
module.exports = { module.exports = {
"globDirectory": "public/", globDirectory: 'public',
"globPatterns": [ globPatterns: [ '**/*.{js,ico,png,svg,html,webmanifest,txt}' ],
"**/*.{js,ico,png,svg,html,txt}" globIgnores: [ 'env.js', 'env.sample.js', 'licenses.json' ],
], swDest: 'public/sw.js'
"swDest": "public/sw.js" };
};