Compare commits

..
65 Commits
Author SHA1 Message Date
philipp b34e3aeed0 👀 UsersOverview - disable advanced search
ref #12
2021-01-14 18:24:37 +01:00
philipp 86c54e04a8 🙋‍♂️ UserDetail - active/inactive user state edit
ref #12
2021-01-14 18:22:09 +01:00
philipp ef9fc596f5 🙋‍♂️ UserDetail - disable profile picture edit
ref #12
2021-01-14 18:21:48 +01:00
philipp 041c24a837 🙋‍♂️ UserDetails - group updating
ref #12
2021-01-13 21:05:03 +01:00
philipp 39a3baa00b 🐞 UserDetail - fix permission reactivity by assignments
ref #12
2021-01-13 18:17:34 +01:00
philipp f7acbb1eaa ⚡ shared state reactivity - AddUserModal-Users-UsersOverview
ref #12
2021-01-13 17:49:01 +01:00
philipp e6fbf7aa5b UserDetail - fixed group updating
ref #12
2021-01-12 21:19:12 +01:00
philipp 36a084eab6 🔒 UserDetail - WIP on Permissions
ref #12
2021-01-12 21:04:12 +01:00
philipp a9e319e0c0 👪 UserDetail - group edit support
ref #12
2021-01-12 20:16:16 +01:00
philipp ea23b97231 💬 UserDetail - info Toasts
ref #12
2021-01-12 19:30:54 +01:00
philipp 7df76f9642 ✨ AddUserModal + UserDetail - optional username field
ref #12
2021-01-12 19:30:06 +01:00
philipp f6db117a5e ⏫ bump @odit/lfk-client-js to 0.0.11
continuous-integration/drone/push Build is passing
2021-01-11 21:21:49 +01:00
philipp 23c3cd605d 🔨 optimized release script 2021-01-11 21:21:12 +01:00
philipp 77690702c0 🚀RELEASE v0.2.0
continuous-integration/drone/push Build is passing
2021-01-11 21:17:35 +01:00
philipp e0093480d9 Merge branch 'feature/12-user-management' into dev 2021-01-11 21:17:12 +01:00
philipp c7679b7a67 [tmp] - disable darkmode + re-enable sw 2021-01-11 21:17:05 +01:00
philipp e6ac34bde8 🐞 [tmp] - nginx.conf - disable .js file caching
continuous-integration/drone/push Build was killed
2021-01-11 21:10:40 +01:00
philipp 8c4b595c30 Merge branch 'dev' into feature/12-user-management 2021-01-11 21:08:44 +01:00
philipp be629e5c6b 🕕 set manual refresh time to 2min
continuous-integration/drone/push Build was killed
2021-01-11 21:08:39 +01:00
philipp 63569684a3 ℹ update jwtinfo store on token refresh 2021-01-11 21:08:14 +01:00
philipp 5937a0d7ce 🔒 added rendering based on permission level
ref #12
2021-01-11 21:07:30 +01:00
philipp 4512272c1c ❌ UserDetail - delete
ref #12
2021-01-11 21:06:47 +01:00
philipp ce1f3842e0 🖊 UserDetail - reactivity on edit + update functionality
ref #12
2021-01-11 20:41:57 +01:00
philipp ee01c3a059 🚀RELEASE v0.1.6
continuous-integration/drone/push Build is passing
2021-01-10 18:19:45 +01:00
philipp 81c1537bad 🔒 UserDetail - added basic layout for permission change
ref #12
2021-01-10 18:14:11 +01:00
philipp 98ecfab032 ✨ UserDetail multiselect layout for groups
ref #12
2021-01-10 18:02:36 +01:00
philipp b948b8c1a4 UserDetail - placeholder for permission picker 🔒
ref #12
2021-01-10 17:55:13 +01:00
philipp f856c6ae37 📧 UserDetail - email input
ref #12
2021-01-10 17:54:50 +01:00
philipp 2dd2580530 Merge branch 'dev' into feature/12-user-management 2021-01-10 17:34:12 +01:00
philipp 330755c63e 🚀RELEASE v0.1.5
continuous-integration/drone/push Build is passing
2021-01-10 17:18:55 +01:00
philipp 9cf0174b41 Merge commit '16f572480ad55425890061f9dad65fe85f2f39ad' into dev
close #30
2021-01-10 17:18:33 +01:00
philipp 16f572480a ⚡ add versionbuilder script to release hook
ref #30
2021-01-10 17:18:16 +01:00
philipp b8a9e4f272 📅 dynamic copyright year in Footer component
ref #30
2021-01-10 17:17:07 +01:00
philipp c089bb3929 ⤵ load dynamic build info in Footer component
ref #30
2021-01-10 17:16:51 +01:00
philipp 3caa1fc277 🔨 sample build of index.html with versionbuilder script
ref #30
2021-01-10 17:16:07 +01:00
philipp 43b406592e 👀 improved Footer layout + display on Login component
ref #30
2021-01-10 17:15:46 +01:00
philipp 1dd6674faa ✨ added versionbuilder.js script
ref #30
2021-01-10 17:15:01 +01:00
philipp 4674b52717 🚀RELEASE v0.1.4
continuous-integration/drone/push Build is passing
2021-01-10 15:30:59 +01:00
philipp cd5831251a Merge commit '45ec97066f425ac2ac66914be649cbd5a1038e10' into dev
close #20
2021-01-10 15:30:42 +01:00
philipp 45ec97066f 🌎 add remaining translation keys for filepond
ref #20
2021-01-10 15:30:13 +01:00
philipp b08c0f145a add basic i18n logic to filepond
ref #20
2021-01-10 15:26:52 +01:00
philipp f0c100aee4 ✨ UsersOverview - user delete
ref #12
2021-01-10 15:16:02 +01:00
philipp 0e31ba212f ✨ About - change license modal icon to "legal"
continuous-integration/drone/push Build was killed
2021-01-10 15:04:05 +01:00
philipp 692c906cd2 🌎 About - i18n 2021-01-10 15:03:32 +01:00
philipp 4f3837ac45 new license file version [CI SKIP] 2021-01-10 13:47:30 +00:00
philipp ccb5125a48 🚀RELEASE v0.1.3
continuous-integration/drone/push Build is passing
2021-01-10 14:46:31 +01:00
philipp 1c356a41f5 🌎 improved i18n for AddUserModal and UserDetail
ref #12
2021-01-10 14:45:34 +01:00
philipp 6012d0577e 🖊 add basic UserDetail editing reactivity
ref #12
2021-01-10 14:26:52 +01:00
philipp 5ec1dfa8b0 ✨ sample layout for advanced search
ref #12
2021-01-10 13:35:46 +01:00
philipp 3754f09b2f 🌎 added i18n for UsersOverview
ref #12
2021-01-10 13:31:46 +01:00
philipp b9e0be4483 🔍 UsersOverview table - basic fuzzy search
ref #12
2021-01-10 13:30:26 +01:00
philipp e1d5d54cfb 🧹 simplified UsersOverview table
ref #12
2021-01-10 13:30:04 +01:00
philipp e97c5c3b7e Merge branch 'dev' into feature/12-user-management 2021-01-10 13:09:42 +01:00
philipp 242b5afbe9 🚀RELEASE v0.1.2
continuous-integration/drone/push Build is passing
2021-01-10 13:08:24 +01:00
philipp 12e5835360 Merge branch 'dev' of https://git.odit.services/lfk/frontend into dev 2021-01-10 13:07:50 +01:00
philipp 4af3cd158d Merge commit '2a37dfafa426e070aa136d171a1a01aa7f609d18' into dev
close #29
2021-01-10 13:07:43 +01:00
philipp 2a37dfafa4 dropped redundant console.log
ref #29
2021-01-10 13:06:48 +01:00
philipp 2cbb431acc 💾 save new auth data to localstorage
ref#29
2021-01-10 13:06:01 +01:00
philipp d92c6c0de9 🔒 added basic manual refresh every 4mins
ref #29
2021-01-10 13:03:48 +01:00
philipp 19887c8f96 Merge branch 'dev' into feature/12-user-management 2021-01-10 12:37:18 +01:00
philipp 519ba79e1d new license file version [CI SKIP] 2021-01-10 11:36:40 +00:00
philipp 4ccd18ca9f Merge commit '5810b4ec4396ad650d90493fb48e2a8320865b42' into dev
continuous-integration/drone/push Build is passing
close #4
2021-01-10 12:35:44 +01:00
philipp b9aa00e8de Merge branch 'dev' into feature/12-user-management 2021-01-10 11:42:35 +01:00
philipp ded31980bf userdetail - dynamic buttons
ref #12
2021-01-09 19:11:46 +01:00
philipp 264e0d7ed9 AddUserModal - data validation
ref #12
2021-01-09 18:55:54 +01:00
18 changed files with 744 additions and 331 deletions

No files matched your search

+75
View File
@@ -2,8 +2,83 @@
All notable changes to this project will be documented in this file. Dates are displayed in UTC.
#### [0.2.0](https://git.odit.services/lfk/frontend/compare/0.1.6...0.2.0)
- 🔒 added rendering based on permission level [`5937a0d`](https://git.odit.services/lfk/frontend/commit/5937a0d7ce970d38ddb0e4c6a02d11f8c8b53e9b)
- ❌ UserDetail - delete [`4512272`](https://git.odit.services/lfk/frontend/commit/4512272c1c2a5c861d8ac4c9908244df125dc3d9)
- 🖊 UserDetail - reactivity on edit + update functionality [`ce1f384`](https://git.odit.services/lfk/frontend/commit/ce1f3842e0f581d9e94ea6079cf223d945f7465d)
- [tmp] - disable darkmode + re-enable sw [`c7679b7`](https://git.odit.services/lfk/frontend/commit/c7679b7a67b362a7fbf796f612892bdfac50731c)
- 🕕 set manual refresh time to 2min [`be629e5`](https://git.odit.services/lfk/frontend/commit/be629e5c6b076bf9a28dcc953e97478d244d8413)
- 🐞 [tmp] - nginx.conf - disable .js file caching [`e6ac34b`](https://git.odit.services/lfk/frontend/commit/e6ac34bde8d288a45e83fc6723a2bbe952f2622a)
- ℹ update jwtinfo store on token refresh [`6356968`](https://git.odit.services/lfk/frontend/commit/63569684a392bf0c24c9c2efd7945114d1a230a5)
#### [0.1.6](https://git.odit.services/lfk/frontend/compare/0.1.5...0.1.6)
> 10 January 2021
- ✨ UsersOverview - user delete [`f0c100a`](https://git.odit.services/lfk/frontend/commit/f0c100aee47d6a5aeb0995db79b268f33bf316e9)
- 🔒 UserDetail - added basic layout for permission change [`81c1537`](https://git.odit.services/lfk/frontend/commit/81c1537bada2c87127385d9110d48459cd1b505f)
- 🚀RELEASE v0.1.6 [`ee01c3a`](https://git.odit.services/lfk/frontend/commit/ee01c3a059c435add68938657955cbd2c5851c50)
- 📧 UserDetail - email input [`f856c6a`](https://git.odit.services/lfk/frontend/commit/f856c6ae3792c93aee148339d89e3978db6e9293)
- ✨ UserDetail multiselect layout for groups [`98ecfab`](https://git.odit.services/lfk/frontend/commit/98ecfab0325e35c5418775f7162049b56e5f332f)
- UserDetail - placeholder for permission picker 🔒 [`b948b8c`](https://git.odit.services/lfk/frontend/commit/b948b8c1a48e5b4bc6a083139d26100ef4499970)
#### [0.1.5](https://git.odit.services/lfk/frontend/compare/0.1.4...0.1.5)
> 10 January 2021
- Merge commit '16f572480ad55425890061f9dad65fe85f2f39ad' into dev [`#30`](https://git.odit.services/lfk/frontend/issues/30)
- 🚀RELEASE v0.1.5 [`330755c`](https://git.odit.services/lfk/frontend/commit/330755c63e3405533a5da79c84ef4f379eb43e1c)
- ⤵ 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)
+1 -1
View File
@@ -9,7 +9,7 @@ http {
location / {
try_files $uri $uri/ /index.html;
}
location ~* \.(?:ico|css|js|gif|jpe?g|png)$ {
location ~* \.(?:ico|css|gif|jpe?g|png)$ {
expires 1y;
add_header Pragma public;
add_header Cache-Control "public";
+4 -4
View File
@@ -1,20 +1,20 @@
{
"name": "@odit/lfk-frontend",
"version": "0.1.2-1",
"version": "0.2.0",
"scripts": {
"i18n-order": "node order.js",
"dev": "snowpack dev",
"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": {
"@odit/lfk-client-js": "0.0.10",
"@odit/lfk-client-js": "0.0.11",
"filepond": "4.25.1",
"gridjs": "3.2.1",
"localforage": "1.9.0",
"lodash.isequal": "^4.5.0",
"svelte-filepond": "0.0.1",
"svelte-focus-trap": "1.0.1",
"svelte-i18n": "3.3.0",
@@ -50,7 +50,7 @@
"publish": false
},
"hooks": {
"after:bump": "npx auto-changelog --commit-limit false -p -u --hide-credit && git add CHANGELOG.md"
"after:bump": "npx auto-changelog --commit-limit false -p -u --hide-credit && git add CHANGELOG.md && node versionbuilder.js && git add public/index.html && node order.js && git add public/locales"
}
}
}
+1
View File
@@ -13,6 +13,7 @@
</head>
<body>
<span style="display: none;visibility: hidden;" id="buildinfo">RELEASE_INFO-0.2.0-RELEASE_INFO</span>
<noscript>You need to enable JavaScript to run this app.</noscript>
<script src="/env.js"></script>
<script defer type="module" src="/_dist_/index.js"></script>
+1 -1
View File
@@ -1 +1 @@
[{"author":"ODIT.Services","repo":{"type":"git","url":"git+https://git.odit.services/lfk/lfk-client-js"},"description":"A lib to interact with https://git.odit.services/lfk/backend. Use this version for native JS applications.","name":"@odit/lfk-client-js","license":"CC-BY-NC-SA-4.0","version":"0.0.10","licensetext":"Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Creative\r\nCommons Corporation (\"Creative Commons\") is not a law firm and does not provide\r\nlegal services or legal advice. Distribution of Creative Commons public licenses\r\ndoes not create a lawyer-client or other relationship. Creative Commons makes\r\nits licenses and related information available on an \"as-is\" basis. Creative\r\nCommons gives no warranties regarding its licenses, any material licensed\r\nunder their terms and conditions, or any related information. Creative Commons\r\ndisclaims all liability for damages resulting from their use to the fullest\r\nextent possible.\r\n\r\nUsing Creative Commons Public Licenses\r\n\r\nCreative Commons public licenses provide a standard set of terms and conditions\r\nthat creators and other rights holders may use to share original works of\r\nauthorship and other material subject to copyright and certain other rights\r\nspecified in the public license below. The following considerations are for\r\ninformational purposes only, are not exhaustive, and do not form part of our\r\nlicenses.\r\n\r\nConsiderations for licensors: Our public licenses are intended for use by\r\nthose authorized to give the public permission to use material in ways otherwise\r\nrestricted by copyright and certain other rights. Our licenses are irrevocable.\r\nLicensors should read and understand the terms and conditions of the license\r\nthey choose before applying it. Licensors should also secure all rights necessary\r\nbefore applying our licenses so that the public can reuse the material as\r\nexpected. Licensors should clearly mark any material not subject to the license.\r\nThis includes other CC-licensed material, or material used under an exception\r\nor limitation to copyright. More considerations for licensors : wiki.creativecommons.org/Considerations_for_licensors\r\n\r\nConsiderations for the public: By using one of our public licenses, a licensor\r\ngrants the public permission to use the licensed material under specified\r\nterms and conditions. If the licensor's permission is not necessary for any\r\nreason–for example, because of any applicable exception or limitation to copyright–then\r\nthat use is not regulated by the license. Our licenses grant only permissions\r\nunder copyright and certain other rights that a licensor has authority to\r\ngrant. Use of the licensed material may still be restricted for other reasons,\r\nincluding because others have copyright or other rights in the material. A\r\nlicensor may make special requests, such as asking that all changes be marked\r\nor described. Although not required by our licenses, you are encouraged to\r\nrespect those requests where reasonable. More considerations for the public\r\n: wiki.creativecommons.org/Considerations_for_licensees\r\n\r\nCreative Commons Attribution-NonCommercial-ShareAlike 4.0 International Public\r\nLicense\r\n\r\nBy exercising the Licensed Rights (defined below), You accept and agree to\r\nbe bound by the terms and conditions of this Creative Commons Attribution-NonCommercial-ShareAlike\r\n4.0 International Public License (\"Public License\"). To the extent this Public\r\nLicense may be interpreted as a contract, You are granted the Licensed Rights\r\nin consideration of Your acceptance of these terms and conditions, and the\r\nLicensor grants You such rights in consideration of benefits the Licensor\r\nreceives from making the Licensed Material available under these terms and\r\nconditions.\r\n\r\nSection 1 – Definitions.\r\n\r\na. Adapted Material means material subject to Copyright and Similar Rights\r\nthat is derived from or based upon the Licensed Material and in which the\r\nLicensed Material is translated, altered, arranged, transformed, or otherwise\r\nmodified in a manner requiring permission under the Copyright and Similar\r\nRights held by the Licensor. For purposes of this Public License, where the\r\nLicensed Material is a musical work, performance, or sound recording, Adapted\r\nMaterial is always produced where the Licensed Material is synched in timed\r\nrelation with a moving image.\r\n\r\nb. Adapter's License means the license You apply to Your Copyright and Similar\r\nRights in Your contributions to Adapted Material in accordance with the terms\r\nand conditions of this Public License.\r\n\r\nc. BY-NC-SA Compatible License means a license listed at creativecommons.org/compatiblelicenses,\r\napproved by Creative Commons as essentially the equivalent of this Public\r\nLicense.\r\n\r\nd. Copyright and Similar Rights means copyright and/or similar rights closely\r\nrelated to coLine truncated
[{"author":"ODIT.Services","repo":{"type":"git","url":"git+https://git.odit.services/lfk/lfk-client-js"},"description":"A lib to interact with https://git.odit.services/lfk/backend. Use this version for native JS applications.","name":"@odit/lfk-client-js","license":"CC-BY-NC-SA-4.0","version":"0.0.10","licensetext":"Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Creative\r\nCommons Corporation (\"Creative Commons\") is not a law firm and does not provide\r\nlegal services or legal advice. Distribution of Creative Commons public licenses\r\ndoes not create a lawyer-client or other relationship. Creative Commons makes\r\nits licenses and related information available on an \"as-is\" basis. Creative\r\nCommons gives no warranties regarding its licenses, any material licensed\r\nunder their terms and conditions, or any related information. Creative Commons\r\ndisclaims all liability for damages resulting from their use to the fullest\r\nextent possible.\r\n\r\nUsing Creative Commons Public Licenses\r\n\r\nCreative Commons public licenses provide a standard set of terms and conditions\r\nthat creators and other rights holders may use to share original works of\r\nauthorship and other material subject to copyright and certain other rights\r\nspecified in the public license below. The following considerations are for\r\ninformational purposes only, are not exhaustive, and do not form part of our\r\nlicenses.\r\n\r\nConsiderations for licensors: Our public licenses are intended for use by\r\nthose authorized to give the public permission to use material in ways otherwise\r\nrestricted by copyright and certain other rights. Our licenses are irrevocable.\r\nLicensors should read and understand the terms and conditions of the license\r\nthey choose before applying it. Licensors should also secure all rights necessary\r\nbefore applying our licenses so that the public can reuse the material as\r\nexpected. Licensors should clearly mark any material not subject to the license.\r\nThis includes other CC-licensed material, or material used under an exception\r\nor limitation to copyright. More considerations for licensors : wiki.creativecommons.org/Considerations_for_licensors\r\n\r\nConsiderations for the public: By using one of our public licenses, a licensor\r\ngrants the public permission to use the licensed material under specified\r\nterms and conditions. If the licensor's permission is not necessary for any\r\nreason–for example, because of any applicable exception or limitation to copyright–then\r\nthat use is not regulated by the license. Our licenses grant only permissions\r\nunder copyright and certain other rights that a licensor has authority to\r\ngrant. Use of the licensed material may still be restricted for other reasons,\r\nincluding because others have copyright or other rights in the material. A\r\nlicensor may make special requests, such as asking that all changes be marked\r\nor described. Although not required by our licenses, you are encouraged to\r\nrespect those requests where reasonable. More considerations for the public\r\n: wiki.creativecommons.org/Considerations_for_licensees\r\n\r\nCreative Commons Attribution-NonCommercial-ShareAlike 4.0 International Public\r\nLicense\r\n\r\nBy exercising the Licensed Rights (defined below), You accept and agree to\r\nbe bound by the terms and conditions of this Creative Commons Attribution-NonCommercial-ShareAlike\r\n4.0 International Public License (\"Public License\"). To the extent this Public\r\nLicense may be interpreted as a contract, You are granted the Licensed Rights\r\nin consideration of Your acceptance of these terms and conditions, and the\r\nLicensor grants You such rights in consideration of benefits the Licensor\r\nreceives from making the Licensed Material available under these terms and\r\nconditions.\r\n\r\nSection 1 – Definitions.\r\n\r\na. Adapted Material means material subject to Copyright and Similar Rights\r\nthat is derived from or based upon the Licensed Material and in which the\r\nLicensed Material is translated, altered, arranged, transformed, or otherwise\r\nmodified in a manner requiring permission under the Copyright and Similar\r\nRights held by the Licensor. For purposes of this Public License, where the\r\nLicensed Material is a musical work, performance, or sound recording, Adapted\r\nMaterial is always produced where the Licensed Material is synched in timed\r\nrelation with a moving image.\r\n\r\nb. Adapter's License means the license You apply to Your Copyright and Similar\r\nRights in Your contributions to Adapted Material in accordance with the terms\r\nand conditions of this Public License.\r\n\r\nc. BY-NC-SA Compatible License means a license listed at creativecommons.org/compatiblelicenses,\r\napproved by Creative Commons as essentially the equivalent of this Public\r\nLicense.\r\n\r\nd. Copyright and Similar Rights means copyright and/or similar rights closely\r\nrelated to coLine truncated
+1 -1
View File
@@ -49,7 +49,7 @@
OpenAPI.BASE = config.baseurl;
import { register as registerSW } from "./swmodule";
store.init();
// registerSW();
registerSW();
</script>
<Route>
+10 -13
View File
@@ -50,14 +50,14 @@
<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"
fill="none"
width="24"
height="24"
xmlns="http://www.w3.org/2000/svg"
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>
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">
@@ -79,7 +79,7 @@
}}
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
{$_('close')}
</button>
</div>
</div>
@@ -112,13 +112,12 @@
<h2 class="text-4xl font-display font-semibold md:text-5xl">
{$_('credits')}
</h2>
<div
class="max-w-3xl mx-auto text-xl leading-8 font-medium mt-8">
<div class="max-w-3xl mx-auto text-xl leading-8 font-medium mt-8">
<p class="text-center">{$_('oss_credit_description')}</p>
</div>
<div class="w-screen leading-8 pl-5 mt-5">
{#await license_promise}
<p class="text-center w-full">Licenses are being loaded...</p>
<p class="text-center w-full">{$_('licenses-are-being-loaded')}</p>
{:then}
<table>
<thead>
@@ -164,9 +163,7 @@
</div>
{/await}
</div>
<h2 class="text-4xl font-display font-semibold md:text-5xl">
Fragen
</h2>
<h2 class="text-4xl font-display font-semibold md:text-5xl">{$_('faq')}</h2>
<div class="mt-6 border-t-2 border-gray-100 pt-10">
<dl class="md:grid md:grid-cols-2 md:gap-8">
<div>
+63 -46
View File
@@ -2,34 +2,33 @@
import { _ } from "svelte-i18n";
import { clickOutside } from "./outsideclick";
import { focusTrap } from "svelte-focus-trap";
import { tracks as tracksstore } from "../store.js";
import { TrackService, UserService } from "@odit/lfk-client-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";
import About from "./About.svelte";
export let modal_open;
export let current_users;
let firstname_input;
let lastname_input;
let middlename_input;
let username_input;
let password_input;
let email_input;
function focus(el) {
el.focus();
}
$: username_input_value = "";
$: middlename_input_value = "";
$: password_input_value = "";
$: email_input_value = "";
$: lastname_input_value = "";
$: firstname_input_value = "";
$: track_min_duration = 0;
$: tracklength = 0;
$: processed_last_submit = true;
$: isPasswordValid = password_input_value.trim().length === 0;
$: 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;
$: 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;
@@ -51,16 +50,25 @@
text: "User is being added...",
duration: -1,
}).showToast();
UserService.userControllerPost({
let postdata={
firstname: firstname_input_value,
lastname: lastname_input_value,
middlename: middlename_input_value,
email:email_input_value,password:password_input_value
})
password: password_input_value
};
if(email_input_value!==""){
postdata.email=email_input_value;
}
if(username_input_value!==""){
postdata.username=username_input_value;
}
UserService.userControllerPost(postdata)
.then((result) => {
firstname_input_value = "";
lastname_input_value = "";
middlename_input_value = "";
email_input_value = "";
username_input_value = "";
modal_open = false;
//
Toastify({
@@ -68,12 +76,8 @@
duration: 500,
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
}).showToast();
let storeval = [];
tracksstore.subscribe((val) => {
storeval = val;
});
storeval.push(result);
tracksstore.set(storeval);
current_users.push(result);
current_users=current_users;
})
.catch((err) => {
//
@@ -137,33 +141,33 @@
<div class="col-span-6">
<label
for="firstname"
class="block text-sm font-medium text-gray-700">First Name</label>
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}
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}
{#if !isFirstnameValid}
<span
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
First Name is required
{$_('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>
class="block text-sm font-medium text-gray-700">{$_('middle-name')}</label>
<input
autocomplete="off"
placeholder="Middle Name"
placeholder={$_('middle-name')}
bind:value={middlename_input_value}
bind:this={middlename_input}
type="text"
@@ -177,50 +181,63 @@
<input
autocomplete="off"
placeholder="Last Name"
class:border-red-500={isLastnameValid}
class:focus:border-red-500={isLastnameValid}
class:focus:ring-red-500={isLastnameValid}
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}
{#if !isLastnameValid}
<span
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
Last Name is required
{$_('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>
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}
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}
{#if !isPasswordValid}
<span
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
Password is required
{$_('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</label>
for="trackname"
class="block text-sm font-medium text-gray-700">{$_('username')}</label>
<input
autocomplete="off"
placeholder="E-Mail"
placeholder={$_('username')}
bind:value={username_input_value}
bind:this={username_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="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}
@@ -232,7 +249,7 @@
{#if !isEmailValid}
<span
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
valid email is required
{$_('valid-email-is-required')}
</span>
{/if}
</div>
@@ -247,7 +264,7 @@
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
{$_('create')}
</button>
<button
on:click={() => {
@@ -255,7 +272,7 @@
}}
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
{$_('cancel')}
</button>
</div>
</div>
+49
View File
@@ -1,6 +1,7 @@
<script>
import "filepond/dist/filepond.css";
import FilePond from "svelte-filepond";
import { _ } from "svelte-i18n";
let pond;
// pond.getFiles() will return the active files
// the name to use for the internal file input
@@ -11,12 +12,60 @@
function handleAddFile(err, 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>
<div class="app">
<FilePond
bind:this={pond}
{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"
allowMultiple={false}
credits={false}
+23 -3
View File
@@ -1,15 +1,35 @@
<script>
import { _ } from "svelte-i18n";
$: releaseinfo = "";
setTimeout(() => {
releaseinfo = document
.getElementById("buildinfo")
.textContent.replace("RELEASE_INFO-", "")
.replace("-RELEASE_INFO", "");
}, 1500);
const year = new Date().getFullYear();
</script>
<footer class="container">
<hr class="mt-2 mb-4 border-b-1 border-gray-300" />
<footer class="p-5 w-full">
<p class="text-sm text-gray-500 mt-4">
Lauf für Kaya! Läufersystem - Copyright © 2020 + proudly powered by
Lauf für Kaya! Läufersystem - Copyright ©
{year}
+ proudly powered by
<a
class="underline"
href="https://odit.services"
rel="noopener,noreferrer"
target="_blank">ODIT.Services</a>
</p>
<p class="text-sm text-gray-500 mt-4">
<a
class="underline"
target="_blank"
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>
+3 -1
View File
@@ -4,6 +4,7 @@
import { _ } from "svelte-i18n";
store.init();
import { OpenAPI, AuthService } from "@odit/lfk-client-js";
import Footer from "./Footer.svelte";
import Toastify from "toastify-js";
// ------
let username = "demo";
@@ -17,7 +18,7 @@
is_blocked_by_autologin = true;
OpenAPI.TOKEN = value.access_token;
const jwtinfo = JSON.parse(atob(OpenAPI.TOKEN.split(".")[1]));
store.login(value.access_token, jwtinfo);
store.login(value, jwtinfo);
Toastify({
text: $_("welcome_wavinghand"),
duration: 500,
@@ -140,3 +141,4 @@
</div>
</div>
</div>
<Footer />
+249 -40
View File
@@ -1,15 +1,93 @@
<script>
import { _ } from "svelte-i18n";
import { UserService } from "@odit/lfk-client-js";
import lodashIsEqual from "lodash.isequal";
import store from "../store";
import {
UserService,
UserGroupService,
PermissionService,
} from "@odit/lfk-client-js";
import "gridjs/dist/theme/mermaid.css";
import { tracks as tracksstore } from "../store.js";
import Toastify from "toastify-js";
import PromiseError from "./PromiseError.svelte";
export let params;
const user_promise = UserService.userControllerGetOne(params.userid);
let data_loaded = false;
$: delete_triggered = false;
$: original_data = {};
$: editable_userdata = {};
$: allpermissions = [];
$: allgroups = [];
$: allgroups_ids = [];
$: usergroups_array_objects = [];
$: usergroups_array = [];
let usergroups_array_original = [];
user_promise.then((data) => {
console.log(data);
tracksstore.set(data);
data_loaded = true;
original_data = Object.assign(original_data, data);
editable_userdata = data;
data.groups.forEach((g) => {
usergroups_array=usergroups_array.concat([g.id]);
});
usergroups_array_original = usergroups_array;
allgroups.forEach((g) => {
allgroups_ids.push(g.id);
});
});
UserGroupService.userGroupControllerGetAll().then((data) => {
allgroups = data;
});
const permissions_promise = PermissionService.permissionControllerGetAll();
permissions_promise.then((data) => {
data.forEach((p) => {
allpermissions=allpermissions.concat([p.target + ":" + p.action])
});
});
$: changes_performed = !lodashIsEqual(original_data, editable_userdata);
$: groups_changed = JSON.stringify(usergroups_array)===JSON.stringify(usergroups_array_original);
$: save_enabled = changes_performed||!groups_changed;
function submit() {
if (
!lodashIsEqual(original_data.permissions, editable_userdata.permissions)
) {
// TODO: add+delete permissions
}
if (data_loaded === true && save_enabled) {
let tmp=[];
usergroups_array.forEach(g => {
const group=allgroups.find(obj=>obj.id===g);
tmp.push(group);
});
editable_userdata.groups=tmp;
Toastify({
text: $_("updating-user"),
duration: 2500,
}).showToast();
UserService.userControllerPut(original_data.id, editable_userdata)
.then((resp) => {
Object.assign(original_data, editable_userdata);
original_data = editable_userdata;
Object.assign(original_data, editable_userdata);
//
Toastify({
text: $_("user-updated"),
duration: 2500,
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
}).showToast();
})
.catch((err) => {
});
} else {
}
}
function deleteUser() {
UserService.userControllerRemove(original_data.id, true)
.then((resp) => {
location.replace("./");
})
.catch((err) => {
});
}
</script>
{#await user_promise}
@@ -50,79 +128,210 @@
<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>
<span class="mr-2">{original_data.firstname}
{original_data.middlename || ''}
{original_data.lastname}</span>
</li>
</ol>
</nav>
</div>
</div>
<span
class="mb-4 text-3xl font-extrabold leading-tight">{user.firstname}
{user.middlename || ''}
{user.lastname}
<button
type="button"
class="w-full inline-flex 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></span>
<!-- -->
<div class="mt-2 flex items-center">
<div class="mb-8 text-3xl font-extrabold leading-tight">
{original_data.firstname}
{original_data.middlename || ''}
{original_data.lastname}
<span data-id="user_actions_${editable_userdata.id}">
{#if store.state.jwtinfo.userdetails.permissions.includes('USER:DELETE')}
{#if delete_triggered}
<button
on:click={deleteUser}
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">{$_('confirm-delete')}</button>
<button
on:click={() => {
delete_triggered = !delete_triggered;
}}
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-400 text-base font-medium text-white sm:w-auto sm:text-sm">{$_('cancel')}</button>
{/if}
{#if !delete_triggered}
<button
on:click={() => {
delete_triggered = true;
}}
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>
{/if}
{/if}
{#if !delete_triggered}
<button
disabled={!save_enabled}
class:opacity-50={!save_enabled}
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>
{/if}
</span>
</div>
<div class="mt-3 text-sm w-full">
<p
class="ml-1 font-medium text-gray-700">Profile Picture</p>
<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
class="h-20 w-20 rounded-full overflow-hidden bg-gray-100"
src={editable_userdata.profilePic} />
<!-- <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>
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"
name="enabled"
type="checkbox"
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>
<br>
<p class="text-gray-500"> <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" /> 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>
<label
for="firstname"
class="font-medium text-gray-700">{$_('first-name')}</label>
<input
autocomplete="off"
placeholder="First name"
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>
<label
for="middlename"
class="font-medium text-gray-700">{$_('middle-name')}</label>
<input
autocomplete="off"
placeholder="Middle name"
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>
<label
for="lastname"
class="font-medium text-gray-700">{$_('last-name')}</label>
<input
autocomplete="off"
placeholder="Last name"
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>
<div class="text-sm w-full">
<label
for="email"
class="font-medium text-gray-700">{$_('e-mail-adress')}</label>
<input
autocomplete="off"
placeholder={$_('e-mail-adress')}
type="email"
bind:value={editable_userdata.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 dark:bg-gray-900 dark:text-gray-100 rounded-md p-2" />
</div>
<div class="text-sm w-full">
<label
for="username"
class="font-medium text-gray-700">{$_('username')}</label>
<input
autocomplete="off"
placeholder={$_('username')}
type="text"
bind:value={editable_userdata.username}
name="username"
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">
<span class="font-medium">{$_('groups')}</span>
<!-- svelte-ignore a11y-no-onchange -->
<select
bind:value={usergroups_array}
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"
multiple>
{#each allgroups as g}
{#if usergroups_array.includes(g.id)}
<option selected value={g.id}>{g.name}</option>
{:else}
<option value={g.id}>{g.name}</option>
{/if}
{/each}
</select>
</div>
<div class="text-sm w-full">
<span class="font-medium">Permissions</span>
<div class="border-4 border-dashed rounded mb-4 p-5 text-lg text-center">
<!-- -->
<div class="flex flex-wrap -mx-1 overflow-hidden">
<div class="my-1 px-1 w-full overflow-hidden sm:w-1/2">
verfügbare
</div>
<div class="my-1 px-1 w-full overflow-hidden sm:w-1/2">erteilte</div>
</div>
<!-- -->
<div class="flex flex-wrap -mx-1 overflow-hidden">
{#if allpermissions.length > 0}
<div class="my-1 px-1 w-full overflow-hidden sm:w-1/2">
<div
class="border-4 border-dashed rounded mb-4 p-5 text-lg text-center">
{#each allpermissions as p}
{#if !editable_userdata.permissions.includes(p)}
<p
class="block w-full mt-1 text-sm dark:border-gray-600 dark:bg-gray-700 bg-gray-200 p-2 focus:border-purple-400 focus:outline-none focus:shadow-outline-purple dark:text-gray-300 dark:focus:shadow-outline-gray form-input">
{p}
<button
on:click={() => {
editable_userdata.permissions.push(p);
editable_userdata.permissions = editable_userdata.permissions;
}}
type="button"
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-green-200 text-base font-medium text-black hover:bg-green-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 sm:ml-3 sm:w-auto sm:text-sm">+</button>
</p>
{/if}
{/each}
</div>
</div>
<div class="my-1 px-1 w-full overflow-hidden sm:w-1/2">
<div
class="border-4 border-dashed rounded mb-4 p-5 text-lg text-center">
{#each allpermissions as p}
{#if editable_userdata.permissions.includes(p)}
<p
class="block w-full mt-1 text-sm dark:border-gray-600 dark:bg-gray-700 bg-gray-200 p-2 focus:border-purple-400 focus:outline-none focus:shadow-outline-purple dark:text-gray-300 dark:focus:shadow-outline-gray form-input">
{p}
<button
on:click={() => {
editable_userdata.permissions = editable_userdata.permissions.filter((obj) => obj !== p);
}}
type="button"
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-300 text-base font-medium text-black hover:bg-red-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 sm:ml-3 sm:w-auto sm:text-sm">-</button>
</p>
{/if}
{/each}
</div>
</div>
{/if}
</div>
</div>
</div>
</section>
{:catch error}
<!-- promise was rejected -->
<PromiseError {error} />
{/await}
+20 -14
View File
@@ -1,25 +1,31 @@
<script>
import { _ } from "svelte-i18n";
import store from "../store";
import AddUserModal from "./AddUserModal.svelte";
export let modal_open = false;
import UsersOverview from "./UsersOverview.svelte";
console.log(store.state.jwtinfo.userdetails.permissions);
let current_users=[];
</script>
<section class="container p-5">
<span class="mb-1 text-3xl font-extrabold leading-tight">
Users
<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 User
</button>
{$_('users')}
{#if store.state.jwtinfo.userdetails.permissions.includes('USER:CREATE')}
<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-user')}
</button>
{/if}
</span>
<p class="mb-8 text-lg text-gray-500">
manage admin users
</p>
<UsersOverview />
<p class="mb-8 text-lg text-gray-500">{$_('manage-admin-users')}</p>
<UsersOverview bind:current_users />
</section>
<AddUserModal bind:modal_open />
{#if store.state.jwtinfo.userdetails.permissions.includes('USER:CREATE')}
<AddUserModal bind:current_users bind:modal_open />
{/if}
+168 -203
View File
@@ -1,217 +1,182 @@
<script>
import { _, json } from "svelte-i18n";
import { _ } from "svelte-i18n";
import Toastify from "toastify-js";
import TracksEmptyState from "./TracksEmptyState.svelte";
import { TrackService, UserService } from "@odit/lfk-client-js";
import { UserService } from "@odit/lfk-client-js";
const users_promise = UserService.userControllerGetAll();
import { getlang } from "./datatable_i18n";
import { Grid, html } from "gridjs";
import "gridjs/dist/theme/mermaid.css";
import { tracks as tracksstore } from "../store.js";
import { users as usersstore } from "../store.js";
import store from "../store";
import UsersEmptyState from "./UsersEmptyState.svelte";
$: searchvalue = "";
$: active_deletes = [];
export let current_users=[];
$: userscache = [];
$: blocked = [];
let table;
let datatable;
let datatable_inited = false;
tracksstore.subscribe((val) => {
$: advanced_search = false;
usersstore.subscribe((val) => {
userscache = val;
current_users=val;
});
users_promise.then((data) => {
console.log(data);
tracksstore.set(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 store.state.jwtinfo.userdetails.permissions.includes('USER:GET')}
{#await users_promise}
<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">
Title
</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}
<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">
<div class="text-sm text-gray-900 dark:text-gray-100">
Regional Paradigm Technician
</div>
<div class="text-sm text-gray-500">Optimization</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>
{/each}
</tbody>
</table>
<div
class="grid px-4 py-3 text-xs font-semibold tracking-wide text-gray-500 uppercase border-t dark:border-gray-700 bg-gray-50 sm:grid-cols-9 dark:text-gray-400 dark:bg-gray-900">
<span class="flex items-center col-span-3"> Showing 21-30 of 100 </span>
<span class="col-span-2" />
<!-- Pagination -->
<span class="flex col-span-4 mt-2 sm:mt-auto sm:justify-end">
<nav aria-label="Table navigation">
<ul class="inline-flex items-center">
<li>
<button
class="px-3 py-1 rounded-md rounded-l-lg focus:outline-none focus:shadow-outline-purple"
aria-label="Previous">
<svg
aria-hidden="true"
class="w-4 h-4 fill-current"
viewBox="0 0 20 20">
<path
d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z"
clip-rule="evenodd"
fill-rule="evenodd" />
</svg>
</button>
</li>
<li>
<button
class="px-3 py-1 rounded-md focus:outline-none focus:shadow-outline-purple">
1
</button>
</li>
<li>
<button
class="px-3 py-1 rounded-md focus:outline-none focus:shadow-outline-purple">
2
</button>
</li>
<li>
<button
class="px-3 py-1 text-white transition-colors duration-150 bg-purple-600 border border-r-0 border-purple-600 rounded-md focus:outline-none focus:shadow-outline-purple">
3
</button>
</li>
<li>
<button
class="px-3 py-1 rounded-md focus:outline-none focus:shadow-outline-purple">
4
</button>
</li>
<li><span class="px-3 py-1">...</span></li>
<li>
<button
class="px-3 py-1 rounded-md focus:outline-none focus:shadow-outline-purple">
8
</button>
</li>
<li>
<button
class="px-3 py-1 rounded-md focus:outline-none focus:shadow-outline-purple">
9
</button>
</li>
<li>
<button
class="px-3 py-1 rounded-md rounded-r-lg focus:outline-none focus:shadow-outline-purple"
aria-label="Next">
<svg
class="w-4 h-4 fill-current"
aria-hidden="true"
viewBox="0 0 20 20">
<path
d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
clip-rule="evenodd"
fill-rule="evenodd" />
</svg>
</button>
</li>
</ul>
</nav>
</span>
</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>
{/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}
{:then}
{#if current_users.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 current_users as u}
{#if Object.values(u)
.toString()
.toLowerCase()
.includes(searchvalue)}
<tr data-rowid="user_{u.id}">
<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>
{#if active_deletes[u.id] === true}
<td
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
<button
on:click={() => {
active_deletes[u.id] = false;
}}
tabindex="0"
class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer">Cancel
Delete</button>
<button
on:click={() => {
UserService.userControllerRemove(u.id, true)
.then((resp) => {
current_users=current_users.filter(obj=>obj.id!==u.id);
})
.catch((err) => {
// error deleting user
});
}}
tabindex="0"
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">Confirm
Delete</button>
</td>
{:else}
<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>
{#if store.state.jwtinfo.userdetails.permissions.includes('USER:DELETE')}
<button
on:click={() => {
active_deletes[u.id] = true;
}}
tabindex="0"
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">Delete</button>
{/if}
</td>
{/if}
</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}
{/if}
+42
View File
@@ -6,12 +6,18 @@
"add-your-first-track": "Add your first track",
"application_name": "Lauf für Kaya! - Admin",
"author": "Author",
"browse": "Browse",
"by": "by",
"cancel": "Cancel",
"cannot-reset-your-password-directly": "Bummer. We unfortunately cannot reset your password directly. Please send us a mail and confirm your identity",
"changelog": "Changelog",
"close": "Close",
"confirm-delete": "Confirm Delete",
"count_organizations": "# Organizations",
"count_teams": "# Teams",
"create": "Create",
"create-a-new-track": "Create a new Track",
"create-user": "Create User",
"credits": "Credits",
"dashboard-greeting": "hello there",
"dashboard-title": "Dashboard",
@@ -30,33 +36,64 @@
"no_matching_records_found": "No matching records found",
"an_error_happened_while_fetching_the_data": "An error happened while fetching the data"
},
"delete-user": "Delete User",
"dependency_name": "Name",
"dont-have-your-email-connected": "Don't have your email connected?",
"dont-panic-were-resetting-it": "Don't panic, we're resetting it ✌",
"drag-and-drop-your-files-or": "Drag & Drop your files or",
"e-mail-adress": "E-Mail Adress",
"email_address_or_username": "Email / username",
"error_on_login": "Error on login",
"faq": "FAQ",
"filepond__abort": "Abort",
"filepond__cancel": "Cancel",
"filepond__error-during-load": "Error during load",
"filepond__error-during-remove": "Error during remove",
"filepond__error-during-revert": "Error during revert",
"filepond__error-during-upload": "Error during upload",
"filepond__field-contains-invalid-files": "Field contains invalid files",
"filepond__loading": "Loading",
"filepond__remove": "Remove",
"filepond__retry": "Retry",
"filepond__size-not-available": "Size not available",
"filepond__tap-to-cancel": "tap to cancel",
"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",
"groups": "Groups",
"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",
@@ -64,6 +101,7 @@
"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",
@@ -79,7 +117,11 @@
"track-length-in-m": "Track Length in m",
"track-name": "Track name",
"tracks": "Tracks",
"updating-user": "updating user...",
"user-updated": "User updated",
"username": "Username",
"users": "Users",
"valid-email-is-required": "valid email is required",
"welcome_wavinghand": "Welcome 👋",
"your_profile": "Your Profile"
}
+28 -3
View File
@@ -1,12 +1,16 @@
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 state = {
auth: undefined,
access_token: undefined,
jwtinfo: undefined,
isLoggedIn: false
isLoggedIn: false,
refreshInterval: undefined
};
const { subscribe, set, update } = writable(state);
@@ -18,17 +22,38 @@ const store = () => {
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;
const jwtinfo = JSON.parse(atob(auth.access_token.split('.')[1]));
state.jwtinfo = jwtinfo;
localForage.setItem('logindata', auth);
});
},
login(auth, jwtinfo) {
update((state) => {
state.access_token = access_token;
state.auth = auth;
state.access_token = auth.access_token;
state.jwtinfo = jwtinfo;
state.isLoggedIn = true;
//
state.refreshInterval = setInterval(() => {
this.refreshAuth();
// 2min
}, 2 * 60000);
//
return state;
});
},
logout() {
update((state) => {
state.isLoggedIn = false;
//
clearInterval(state.refreshInterval);
state.refreshInterval = undefined;
//
return state;
});
}
+1 -1
View File
@@ -2,7 +2,7 @@ module.exports = {
purge: {
content: [ './src/**/*.svelte' ]
},
darkMode: 'media',
// darkMode: 'media',
variants: {},
plugins: [],
theme: {
+5
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);