Compare commits
	
		
			90 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 7cd24cd51d | |||
| c81b34c1d0 | |||
| 7b1acc494d | |||
| 6ff90694e2 | |||
| 157c7c66b5 | |||
| 93249258c6 | |||
| 01c01a46fa | |||
| 0e2a10fe94 | |||
| 0b9f3de47c | |||
| bc239eead1 | |||
| 7a09869b0c | |||
| bdc0de6ada | |||
| b497cebe76 | |||
| 0fa107a75b | |||
| 35b18d72fd | |||
| 4b80f30afb | |||
| ad34e455ce | |||
| 01fdd0bee2 | |||
| 32ffa345cd | |||
| 6fc3c16073 | |||
| 7d58657c80 | |||
| fcd657c10e | |||
| 4ab77c5557 | |||
| 2bbaa500f4 | |||
| 722a20e141 | |||
| 041c24a837 | |||
| 39a3baa00b | |||
| f7acbb1eaa | |||
| e6fbf7aa5b | |||
| 87926e69db | |||
| 36a084eab6 | |||
| a9e319e0c0 | |||
| ea23b97231 | |||
| 7df76f9642 | |||
| f6db117a5e | |||
| 23c3cd605d | |||
| 77690702c0 | |||
| e0093480d9 | |||
| c7679b7a67 | |||
| e6ac34bde8 | |||
| 8c4b595c30 | |||
| be629e5c6b | |||
| 63569684a3 | |||
| 5937a0d7ce | |||
| 4512272c1c | |||
| ce1f3842e0 | |||
| ee01c3a059 | |||
| 81c1537bad | |||
| 98ecfab032 | |||
| b948b8c1a4 | |||
| f856c6ae37 | |||
| 2dd2580530 | |||
| 330755c63e | |||
| 9cf0174b41 | |||
| 16f572480a | |||
| b8a9e4f272 | |||
| c089bb3929 | |||
| 3caa1fc277 | |||
| 43b406592e | |||
| 1dd6674faa | |||
| 4674b52717 | |||
| cd5831251a | |||
| 45ec97066f | |||
| b08c0f145a | |||
| f0c100aee4 | |||
| 0e31ba212f | |||
| 692c906cd2 | |||
| 4f3837ac45 | |||
| ccb5125a48 | |||
| 1c356a41f5 | |||
| 6012d0577e | |||
| 5ec1dfa8b0 | |||
| 3754f09b2f | |||
| b9e0be4483 | |||
| e1d5d54cfb | |||
| e97c5c3b7e | |||
| 242b5afbe9 | |||
| 12e5835360 | |||
| 4af3cd158d | |||
| 2a37dfafa4 | |||
| 2cbb431acc | |||
| d92c6c0de9 | |||
| 19887c8f96 | |||
| 519ba79e1d | |||
| 4ccd18ca9f | |||
| 5810b4ec43 | |||
| 52aa99681b | |||
| b9aa00e8de | |||
| ded31980bf | |||
| 264e0d7ed9 | 
							
								
								
									
										24
									
								
								.drone.yml
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								.drone.yml
									
									
									
									
									
								
							| @@ -4,18 +4,6 @@ type: docker | |||||||
| name: build:dev | name: build:dev | ||||||
|  |  | ||||||
| steps: | 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 |   - name: run full license export | ||||||
|     depends_on: ["clone"] |     depends_on: ["clone"] | ||||||
|     image: node:alpine |     image: node:alpine | ||||||
| @@ -33,6 +21,18 @@ steps: | |||||||
|       remote: git@git.odit.services:lfk/frontend.git |       remote: git@git.odit.services:lfk/frontend.git | ||||||
|       ssh_key: |       ssh_key: | ||||||
|         from_secret: GITLAB_SSHKEY |         from_secret: GITLAB_SSHKEY | ||||||
|  |   - 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 | ||||||
|  |  | ||||||
| trigger: | trigger: | ||||||
|   branch: |   branch: | ||||||
|   | |||||||
							
								
								
									
										341
									
								
								CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										341
									
								
								CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,341 @@ | |||||||
|  | ### Changelog | ||||||
|  |  | ||||||
|  | All notable changes to this project will be documented in this file. Dates are displayed in UTC. | ||||||
|  |  | ||||||
|  | #### [0.3.0](https://git.odit.services/lfk/frontend/compare/0.2.1...0.3.0) | ||||||
|  |  | ||||||
|  | - Merge pull request 'feature/16-org-management' (#32) from feature/16-org-management into dev [`#16`](https://git.odit.services/lfk/frontend/issues/16) | ||||||
|  | - Merge commit 'fcd657c10ea14290455cfb0bf2de89375a664143' into dev [`#31`](https://git.odit.services/lfk/frontend/issues/31) | ||||||
|  | - ✨ added Org base components [`bdc0de6`](https://git.odit.services/lfk/frontend/commit/bdc0de6adab2db95e6075a993bd50317e9e36eb5) | ||||||
|  | - 🏬 OrgDetail ui [`7a09869`](https://git.odit.services/lfk/frontend/commit/7a09869b0ca9d5dd38cf0c0010b71ab9ce6c6f40) | ||||||
|  | - 🏁 finish basic functionality of AddOrgModal + OrgDetail [`9324925`](https://git.odit.services/lfk/frontend/commit/93249258c6b0f34da22f0ed5d290b437d221a8fd) | ||||||
|  | - ✨ basic functionality in OrgDetail [`0e2a10f`](https://git.odit.services/lfk/frontend/commit/0e2a10fe94075b3cda8ef3ebae6a6159a2e6bbf9) | ||||||
|  | - 🐞 fix sidebar mobile-md scaling [`fcd657c`](https://git.odit.services/lfk/frontend/commit/fcd657c10ea14290455cfb0bf2de89375a664143) | ||||||
|  | - 🔨 reorder CI build order for correct license exporting [`7d58657`](https://git.odit.services/lfk/frontend/commit/7d58657c800e9e494c1d1f098ad0dc34d1f0cd8d) | ||||||
|  | - 💬 AddOrgModal bindings [`bc239ee`](https://git.odit.services/lfk/frontend/commit/bc239eead1d1a29c9662d94db797c6bf23e43166) | ||||||
|  | - ✨ improvements in OrgOverview [`0b9f3de`](https://git.odit.services/lfk/frontend/commit/0b9f3de47c0c8b750c38da07e53927ba55ef3499) | ||||||
|  | - 🔨 config compatibility for new Snowpack V3 bundler [`32ffa34`](https://git.odit.services/lfk/frontend/commit/32ffa345cde67b1affe2750add620522c0a24577) | ||||||
|  | - 🧹 general component cleanup [`157c7c6`](https://git.odit.services/lfk/frontend/commit/157c7c66b57c3a5053c780682402d3615fbc046a) | ||||||
|  | - ⏫ basic dependency bump [`6fc3c16`](https://git.odit.services/lfk/frontend/commit/6fc3c16073555fffd55773218c5c2eed361f076b) | ||||||
|  | - 🌎 i18n [`01c01a4`](https://git.odit.services/lfk/frontend/commit/01c01a46faa9332a2e437861fdb42afe962da833) | ||||||
|  | - ⏫ bump gridjs to 3.2.2 [`6ff9069`](https://git.odit.services/lfk/frontend/commit/6ff90694e288356e16f5226a6e0a054e6fec8b3f) | ||||||
|  | - [tmp] - disable serviceworker [`0fa107a`](https://git.odit.services/lfk/frontend/commit/0fa107a75bc33046758bc42523262a566da9f60f) | ||||||
|  | - new license file version [CI SKIP] [`ad34e45`](https://git.odit.services/lfk/frontend/commit/ad34e455ceedc0e0ccca5ccd86f7f011a7667873) | ||||||
|  | - ⏫ Bump Dockerfile builder to 15.5.1-alpine3.12 [`01fdd0b`](https://git.odit.services/lfk/frontend/commit/01fdd0bee2199bb58373aecc9942591a2d45011a) | ||||||
|  | - new license file version [CI SKIP] [`87926e6`](https://git.odit.services/lfk/frontend/commit/87926e69dbd5b93b2c98cd68fb31913259e3cc00) | ||||||
|  | - 🐳 Dockerfile - drop js sourcemaps [`4b80f30`](https://git.odit.services/lfk/frontend/commit/4b80f30afbfb8c16b9395fb310f309c516c48a17) | ||||||
|  |  | ||||||
|  | #### [0.2.1](https://git.odit.services/lfk/frontend/compare/0.2.0...0.2.1) | ||||||
|  |  | ||||||
|  | > 13 January 2021 | ||||||
|  |  | ||||||
|  | - 🔒 UserDetail - WIP on Permissions [`36a084e`](https://git.odit.services/lfk/frontend/commit/36a084eab6bd0c922da29ebb2d260ba803bf9675) | ||||||
|  | - 👪 UserDetail - group edit support [`a9e319e`](https://git.odit.services/lfk/frontend/commit/a9e319e0c0f2bfaba42bc3af875462e394489dc2) | ||||||
|  | - 🙋♂️ UserDetails - group updating [`041c24a`](https://git.odit.services/lfk/frontend/commit/041c24a837d58ff46362699b54e8088f22ba2daa) | ||||||
|  | - ⚡ shared state reactivity - AddUserModal-Users-UsersOverview [`f7acbb1`](https://git.odit.services/lfk/frontend/commit/f7acbb1eaa14ddf41e29ff1db631520123218289) | ||||||
|  | - ✨ AddUserModal + UserDetail - optional username field [`7df76f9`](https://git.odit.services/lfk/frontend/commit/7df76f9642b528586fd654f27148b5502400ffdf) | ||||||
|  | - UserDetail - fixed group updating [`e6fbf7a`](https://git.odit.services/lfk/frontend/commit/e6fbf7aa5b230733ffd92fdfe851b9f86001c859) | ||||||
|  | - 🚀RELEASE v0.2.1 [`2bbaa50`](https://git.odit.services/lfk/frontend/commit/2bbaa500f4ca56e41613cac12228f4e3327180ab) | ||||||
|  | - 💬 UserDetail - info Toasts [`ea23b97`](https://git.odit.services/lfk/frontend/commit/ea23b972315db39e1f800366d52e3bacf9eaf58b) | ||||||
|  | - 🔨 optimized release script [`23c3cd6`](https://git.odit.services/lfk/frontend/commit/23c3cd605db950a5620ea709748216f7ea034385) | ||||||
|  | - 🐞 fix package release script: locales directory [`722a20e`](https://git.odit.services/lfk/frontend/commit/722a20e141079302da8876be1ccc55026c588048) | ||||||
|  | - ⏫ bump @odit/lfk-client-js to 0.0.11 [`f6db117`](https://git.odit.services/lfk/frontend/commit/f6db117a5eca5c9692a4c5d83159917a712a0e63) | ||||||
|  | - 🐞 UserDetail - fix permission reactivity by assignments [`39a3baa`](https://git.odit.services/lfk/frontend/commit/39a3baa00b0575ee3150c7ae26f32995e2e857d9) | ||||||
|  |  | ||||||
|  | #### [0.2.0](https://git.odit.services/lfk/frontend/compare/0.1.6...0.2.0) | ||||||
|  |  | ||||||
|  | > 11 January 2021 | ||||||
|  |  | ||||||
|  | - 🔒 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) | ||||||
|  | - 🚀RELEASE v0.2.0 [`7769070`](https://git.odit.services/lfk/frontend/commit/77690702c0461b71ff1b65a44bfdc331d5a42c3e) | ||||||
|  | - [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) | ||||||
|  |  | ||||||
|  | > 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) | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| FROM node:15.4.0-alpine3.12 | FROM node:15.5.1-alpine3.12 | ||||||
| WORKDIR /app | WORKDIR /app | ||||||
| RUN npm i -g pnpm | RUN npm i -g pnpm | ||||||
| COPY package.json ./ | COPY package.json ./ | ||||||
| @@ -11,6 +11,7 @@ RUN pnpm run build | |||||||
| # final image | # final image | ||||||
| FROM alpine | FROM alpine | ||||||
| COPY --from=0 /app/build /app | COPY --from=0 /app/build /app | ||||||
|  | RUN rm -rf build/sw.js.map build/workbox-*.js.map | ||||||
| RUN rm -rf /app/build/_dist_/components | RUN rm -rf /app/build/_dist_/components | ||||||
| RUN rm -rf /app/build/_dist_/locales | RUN rm -rf /app/build/_dist_/locales | ||||||
| RUN rm -rf /app/build-manifest.json | RUN rm -rf /app/build-manifest.json | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ http { | |||||||
|         location / { |         location / { | ||||||
|             try_files $uri $uri/ /index.html; |             try_files $uri $uri/ /index.html; | ||||||
|         } |         } | ||||||
|         location ~* \.(?:ico|css|js|gif|jpe?g|png)$ { |         location ~* \.(?:ico|css|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"; | ||||||
|   | |||||||
							
								
								
									
										14
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								package.json
									
									
									
									
									
								
							| @@ -1,20 +1,20 @@ | |||||||
| { | { | ||||||
| 	"name": "@odit/lfk-frontend", | 	"name": "@odit/lfk-frontend", | ||||||
| 	"version": "0.1.2-0", | 	"version": "0.3.0", | ||||||
| 	"scripts": { | 	"scripts": { | ||||||
| 		"i18n-order": "node order.js", | 		"i18n-order": "node order.js", | ||||||
| 		"dev": "snowpack dev", | 		"dev": "snowpack dev", | ||||||
| 		"build": "snowpack build", | 		"build": "snowpack build", | ||||||
| 		"build:sw": "workbox generateSW workbox-config.js", | 		"build:sw": "workbox generateSW workbox-config.js", | ||||||
| 		"release": "release-it", | 		"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" | 		"licenses:export": "license-exporter --json -o public" | ||||||
| 	}, | 	}, | ||||||
| 	"dependencies": { | 	"dependencies": { | ||||||
| 		"@odit/lfk-client-js": "0.0.10", | 		"@odit/lfk-client-js": "0.0.12", | ||||||
| 		"filepond": "4.25.1", | 		"filepond": "4.25.1", | ||||||
| 		"gridjs": "3.2.1", | 		"gridjs": "3.2.2", | ||||||
| 		"localforage": "1.9.0", | 		"localforage": "1.9.0", | ||||||
|  | 		"lodash.isequal": "^4.5.0", | ||||||
| 		"svelte-filepond": "0.0.1", | 		"svelte-filepond": "0.0.1", | ||||||
| 		"svelte-focus-trap": "1.0.1", | 		"svelte-focus-trap": "1.0.1", | ||||||
| 		"svelte-i18n": "3.3.0", | 		"svelte-i18n": "3.3.0", | ||||||
| @@ -25,13 +25,13 @@ | |||||||
| 	}, | 	}, | ||||||
| 	"devDependencies": { | 	"devDependencies": { | ||||||
| 		"@odit/license-exporter": "0.0.9", | 		"@odit/license-exporter": "0.0.9", | ||||||
| 		"@snowpack/plugin-svelte": "3.4.1", | 		"@snowpack/plugin-svelte": "3.5.1", | ||||||
| 		"auto-changelog": "^2.2.1", | 		"auto-changelog": "^2.2.1", | ||||||
| 		"autoprefixer": "10.2.1", | 		"autoprefixer": "10.2.1", | ||||||
| 		"postcss": "8.2.4", | 		"postcss": "8.2.4", | ||||||
| 		"postcss-load-config": "3.0.0", | 		"postcss-load-config": "3.0.0", | ||||||
| 		"release-it": "^14.2.2", | 		"release-it": "^14.2.2", | ||||||
| 		"snowpack": "3.0.0-rc.2", | 		"snowpack": "3.0.10", | ||||||
| 		"svelte": "3.31.2", | 		"svelte": "3.31.2", | ||||||
| 		"svelte-preprocess": "4.6.1", | 		"svelte-preprocess": "4.6.1", | ||||||
| 		"workbox-cli": "6.0.2" | 		"workbox-cli": "6.0.2" | ||||||
| @@ -50,7 +50,7 @@ | |||||||
| 			"publish": false | 			"publish": false | ||||||
| 		}, | 		}, | ||||||
| 		"hooks": { | 		"hooks": { | ||||||
| 			"after:bump": "npx auto-changelog -p" | 			"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 src/locales" | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -13,6 +13,7 @@ | |||||||
| </head> | </head> | ||||||
|  |  | ||||||
| <body> | <body> | ||||||
|  |   <span style="display: none;visibility: hidden;" id="buildinfo">RELEASE_INFO-0.3.0-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> | ||||||
|   | |||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -5,10 +5,11 @@ module.exports = { | |||||||
| 		src: '/_dist_' | 		src: '/_dist_' | ||||||
| 	}, | 	}, | ||||||
| 	plugins: [ '@snowpack/plugin-svelte' ], | 	plugins: [ '@snowpack/plugin-svelte' ], | ||||||
| 	install: [ | 	routes: [ | ||||||
| 		/* ... */ | 		/* Enable an SPA Fallback in development: */ | ||||||
|  | 		{ match: 'routes', src: '.*', dest: '/index.html' } | ||||||
| 	], | 	], | ||||||
| 	installOptions: { | 	packageOptions: { | ||||||
| 		/* ... */ | 		/* ... */ | ||||||
| 		sourceMap: false | 		sourceMap: false | ||||||
| 	}, | 	}, | ||||||
| @@ -18,13 +19,8 @@ module.exports = { | |||||||
| 	buildOptions: { | 	buildOptions: { | ||||||
| 		/* ... */ | 		/* ... */ | ||||||
| 	}, | 	}, | ||||||
| 	proxy: { |  | ||||||
| 		/* ... */ |  | ||||||
| 	}, |  | ||||||
| 	alias: { | 	alias: { | ||||||
| 		/* ... */ | 		/* ... */ | ||||||
| 	}, | 	}, | ||||||
| 	experiments: { | 	optimize: { bundle: true, minify: true } | ||||||
| 		optimize: { bundle: true, minify: true } |  | ||||||
| 	} |  | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| <script> | <script> | ||||||
|   import "./TailwindStyles.svelte"; |   import "./TailwindStyles.svelte"; | ||||||
|   import "toastify-js/src/toastify.css"; |   import "toastify-js/src/toastify.css"; | ||||||
|  |   import "gridjs/dist/theme/mermaid.css"; | ||||||
|   import { Route, router } from "tinro"; |   import { Route, router } from "tinro"; | ||||||
|   router.subscribe((routeInfo) => { |   router.subscribe((routeInfo) => { | ||||||
|     window.scrollTo(0, 0); |     window.scrollTo(0, 0); | ||||||
|   | |||||||
| @@ -50,14 +50,14 @@ | |||||||
|             <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"> | ||||||
|               <svg |               <svg | ||||||
|  |                 fill="currentColor" | ||||||
|                 class="h-6 w-6 text-blue-600" |                 class="h-6 w-6 text-blue-600" | ||||||
|                 fill="none" |  | ||||||
|                 width="24" |  | ||||||
|                 height="24" |  | ||||||
|                 xmlns="http://www.w3.org/2000/svg" |                 xmlns="http://www.w3.org/2000/svg" | ||||||
|                 viewBox="0 0 640 512"><path |                 viewBox="0 0 24 24" | ||||||
|                   fill="currentColor" |                 width="24" | ||||||
|                   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> |                 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> | ||||||
|             <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"> |               <h3 class="text-lg leading-6 font-medium"> | ||||||
| @@ -79,7 +79,7 @@ | |||||||
|             }} |             }} | ||||||
|             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"> | ||||||
|             Close |             {$_('close')} | ||||||
|           </button> |           </button> | ||||||
|         </div> |         </div> | ||||||
|       </div> |       </div> | ||||||
| @@ -112,13 +112,12 @@ | |||||||
|     <h2 class="text-4xl font-display font-semibold 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 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} |       {#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} |       {:then} | ||||||
|         <table> |         <table> | ||||||
|           <thead> |           <thead> | ||||||
| @@ -164,9 +163,7 @@ | |||||||
|         </div> |         </div> | ||||||
|       {/await} |       {/await} | ||||||
|     </div> |     </div> | ||||||
|     <h2 class="text-4xl font-display font-semibold 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> | ||||||
|   | |||||||
							
								
								
									
										162
									
								
								src/components/AddOrgModal.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								src/components/AddOrgModal.svelte
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,162 @@ | |||||||
|  | <script> | ||||||
|  |   import { _ } from "svelte-i18n"; | ||||||
|  |   import { clickOutside } from "./outsideclick"; | ||||||
|  |   import { focusTrap } from "svelte-focus-trap"; | ||||||
|  |   import { RunnerOrganisationService } from "@odit/lfk-client-js"; | ||||||
|  |   import Toastify from "toastify-js"; | ||||||
|  |   export let modal_open; | ||||||
|  |   export let current_organizations; | ||||||
|  |   let name_input_dom; | ||||||
|  |   function focus(el) { | ||||||
|  |     el.focus(); | ||||||
|  |   } | ||||||
|  |   $: name = ""; | ||||||
|  |   $: processed_last_submit = true; | ||||||
|  |   $: isOrgnameValid = name.trim().length !== 0; | ||||||
|  |   $: createbtnenabled = isOrgnameValid; | ||||||
|  |   (() => { | ||||||
|  |     document.onkeydown = (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: "Organization is being added...", | ||||||
|  |         duration: -1, | ||||||
|  |       }).showToast(); | ||||||
|  |       RunnerOrganisationService.runnerOrganisationControllerPost({ | ||||||
|  |         name, | ||||||
|  |         address: undefined, | ||||||
|  |         contact: undefined, | ||||||
|  |       }) | ||||||
|  |         .then((result) => { | ||||||
|  |           console.log(result); | ||||||
|  |           name = ""; | ||||||
|  |           modal_open = false; | ||||||
|  |           // | ||||||
|  |           Toastify({ | ||||||
|  |             text: "Organization added", | ||||||
|  |             duration: 500, | ||||||
|  |             backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)", | ||||||
|  |           }).showToast(); | ||||||
|  |           current_organizations = current_organizations.concat([result]); | ||||||
|  |         }) | ||||||
|  |         .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">​</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" | ||||||
|  |                 xmlns="http://www.w3.org/2000/svg" | ||||||
|  |                 viewBox="0 0 24 24" | ||||||
|  |                 width="24" | ||||||
|  |                 height="24"><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> | ||||||
|  |             </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 Organization | ||||||
|  |               </h3> | ||||||
|  |               <div class="mt-2 mb-6"> | ||||||
|  |                 <p class="text-sm text-gray-500"> | ||||||
|  |                   Please provide the required information to add a new | ||||||
|  |                   organization. | ||||||
|  |                 </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">Name</label> | ||||||
|  |                   <input | ||||||
|  |                     use:focus | ||||||
|  |                     autocomplete="off" | ||||||
|  |                     placeholder="Name" | ||||||
|  |                     class:border-red-500={!isOrgnameValid} | ||||||
|  |                     class:focus:border-red-500={!isOrgnameValid} | ||||||
|  |                     class:focus:ring-red-500={!isOrgnameValid} | ||||||
|  |                     bind:value={name} | ||||||
|  |                     bind:this={name_input_dom} | ||||||
|  |                     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 !isOrgnameValid} | ||||||
|  |                     <span | ||||||
|  |                       class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"> | ||||||
|  |                       Organization name 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} | ||||||
| @@ -2,34 +2,33 @@ | |||||||
|   import { _ } from "svelte-i18n"; |   import { _ } from "svelte-i18n"; | ||||||
|   import { clickOutside } from "./outsideclick"; |   import { clickOutside } from "./outsideclick"; | ||||||
|   import { focusTrap } from "svelte-focus-trap"; |   import { focusTrap } from "svelte-focus-trap"; | ||||||
|   import { tracks as tracksstore } from "../store.js"; |   import { UserService } from "@odit/lfk-client-js"; | ||||||
|   import { TrackService, UserService } from "@odit/lfk-client-js"; |  | ||||||
|   import isEmail from "validator/es/lib/isEmail"; |   import isEmail from "validator/es/lib/isEmail"; | ||||||
|   import Toastify from "toastify-js"; |   import Toastify from "toastify-js"; | ||||||
|   import "toastify-js/src/toastify.css"; |  | ||||||
|   import About from "./About.svelte"; |  | ||||||
|   export let modal_open; |   export let modal_open; | ||||||
|  |   export let current_users; | ||||||
|   let firstname_input; |   let firstname_input; | ||||||
|   let lastname_input; |   let lastname_input; | ||||||
|   let middlename_input; |   let middlename_input; | ||||||
|  |   let username_input; | ||||||
|   let password_input; |   let password_input; | ||||||
|   let email_input; |   let email_input; | ||||||
|   function focus(el) { |   function focus(el) { | ||||||
|     el.focus(); |     el.focus(); | ||||||
|   } |   } | ||||||
|  |   $: username_input_value = ""; | ||||||
|   $: middlename_input_value = ""; |   $: middlename_input_value = ""; | ||||||
|   $: password_input_value = ""; |   $: password_input_value = ""; | ||||||
|   $: email_input_value = ""; |   $: email_input_value = ""; | ||||||
|   $: lastname_input_value = ""; |   $: lastname_input_value = ""; | ||||||
|   $: firstname_input_value = ""; |   $: firstname_input_value = ""; | ||||||
|   $: track_min_duration = 0; |  | ||||||
|   $: tracklength = 0; |  | ||||||
|   $: processed_last_submit = true; |   $: processed_last_submit = true; | ||||||
|   $: isPasswordValid = password_input_value.trim().length === 0; |   $: isPasswordValid = password_input_value.trim().length !== 0; | ||||||
|   $: isEmailValid = isEmail(email_input_value); |   $: isEmailValid = isEmail(email_input_value); | ||||||
|   $: isLastnameValid = lastname_input_value.trim().length === 0; |   $: isLastnameValid = lastname_input_value.trim().length !== 0; | ||||||
|   $: isFirstnameValid = firstname_input_value.trim().length === 0; |   $: isFirstnameValid = firstname_input_value.trim().length !== 0; | ||||||
|   $: createbtnenabled = !isFirstnameValid && !isLastnameValid; |   $: createbtnenabled = | ||||||
|  |     isFirstnameValid && isLastnameValid && isEmailValid && isPasswordValid; | ||||||
|   (function () { |   (function () { | ||||||
|     document.onkeydown = function (e) { |     document.onkeydown = function (e) { | ||||||
|       e = e || window.event; |       e = e || window.event; | ||||||
| @@ -51,16 +50,25 @@ | |||||||
|         text: "User is being added...", |         text: "User is being added...", | ||||||
|         duration: -1, |         duration: -1, | ||||||
|       }).showToast(); |       }).showToast(); | ||||||
|       UserService.userControllerPost({ |       let postdata={ | ||||||
|         firstname: firstname_input_value, |         firstname: firstname_input_value, | ||||||
|         lastname: lastname_input_value, |         lastname: lastname_input_value, | ||||||
|         middlename: middlename_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) => { |         .then((result) => { | ||||||
|           firstname_input_value = ""; |           firstname_input_value = ""; | ||||||
|           lastname_input_value = ""; |           lastname_input_value = ""; | ||||||
|           middlename_input_value = ""; |           middlename_input_value = ""; | ||||||
|  |           email_input_value = ""; | ||||||
|  |           username_input_value = ""; | ||||||
|           modal_open = false; |           modal_open = false; | ||||||
|           // |           // | ||||||
|           Toastify({ |           Toastify({ | ||||||
| @@ -68,12 +76,8 @@ | |||||||
|             duration: 500, |             duration: 500, | ||||||
|             backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)", |             backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)", | ||||||
|           }).showToast(); |           }).showToast(); | ||||||
|           let storeval = []; |           current_users.push(result); | ||||||
|           tracksstore.subscribe((val) => { |           current_users=current_users; | ||||||
|             storeval = val; |  | ||||||
|           }); |  | ||||||
|           storeval.push(result); |  | ||||||
|           tracksstore.set(storeval); |  | ||||||
|         }) |         }) | ||||||
|         .catch((err) => { |         .catch((err) => { | ||||||
|           // |           // | ||||||
| @@ -137,33 +141,33 @@ | |||||||
|                 <div class="col-span-6"> |                 <div class="col-span-6"> | ||||||
|                   <label |                   <label | ||||||
|                     for="firstname" |                     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 |                   <input | ||||||
|                     use:focus |                     use:focus | ||||||
|                     autocomplete="off" |                     autocomplete="off" | ||||||
|                     placeholder="First Name" |                     placeholder={$_('first-name')} | ||||||
|                     class:border-red-500={isFirstnameValid} |                     class:border-red-500={!isFirstnameValid} | ||||||
|                     class:focus:border-red-500={isFirstnameValid} |                     class:focus:border-red-500={!isFirstnameValid} | ||||||
|                     class:focus:ring-red-500={isFirstnameValid} |                     class:focus:ring-red-500={!isFirstnameValid} | ||||||
|                     bind:value={firstname_input_value} |                     bind:value={firstname_input_value} | ||||||
|                     bind:this={firstname_input} |                     bind:this={firstname_input} | ||||||
|                     type="text" |                     type="text" | ||||||
|                     name="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 rounded-md p-2" /> |                     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 |                     <span | ||||||
|                       class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"> |                       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> |                     </span> | ||||||
|                   {/if} |                   {/if} | ||||||
|                 </div> |                 </div> | ||||||
|                 <div class="col-span-6"> |                 <div class="col-span-6"> | ||||||
|                   <label |                   <label | ||||||
|                     for="trackname" |                     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 |                   <input | ||||||
|                     autocomplete="off" |                     autocomplete="off" | ||||||
|                     placeholder="Middle Name" |                     placeholder={$_('middle-name')} | ||||||
|                     bind:value={middlename_input_value} |                     bind:value={middlename_input_value} | ||||||
|                     bind:this={middlename_input} |                     bind:this={middlename_input} | ||||||
|                     type="text" |                     type="text" | ||||||
| @@ -177,50 +181,63 @@ | |||||||
|                   <input |                   <input | ||||||
|                     autocomplete="off" |                     autocomplete="off" | ||||||
|                     placeholder="Last Name" |                     placeholder="Last Name" | ||||||
|                     class:border-red-500={isLastnameValid} |                     class:border-red-500={!isLastnameValid} | ||||||
|                     class:focus:border-red-500={isLastnameValid} |                     class:focus:border-red-500={!isLastnameValid} | ||||||
|                     class:focus:ring-red-500={isLastnameValid} |                     class:focus:ring-red-500={!isLastnameValid} | ||||||
|                     bind:value={lastname_input_value} |                     bind:value={lastname_input_value} | ||||||
|                     bind:this={lastname_input} |                     bind:this={lastname_input} | ||||||
|                     type="text" |                     type="text" | ||||||
|                     name="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 rounded-md p-2" /> |                     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 |                     <span | ||||||
|                       class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"> |                       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> |                     </span> | ||||||
|                   {/if} |                   {/if} | ||||||
|                 </div> |                 </div> | ||||||
|                 <div class="col-span-6"> |                 <div class="col-span-6"> | ||||||
|                   <label |                   <label | ||||||
|                     for="password" |                     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 |                   <input | ||||||
|                     autocomplete="off" |                     autocomplete="off" | ||||||
|                     placeholder="Password" |                     placeholder={$_('password')} | ||||||
|                     class:border-red-500={isPasswordValid} |                     class:border-red-500={!isPasswordValid} | ||||||
|                     class:focus:border-red-500={isPasswordValid} |                     class:focus:border-red-500={!isPasswordValid} | ||||||
|                     class:focus:ring-red-500={isPasswordValid} |                     class:focus:ring-red-500={!isPasswordValid} | ||||||
|                     bind:value={password_input_value} |                     bind:value={password_input_value} | ||||||
|                     bind:this={password_input} |                     bind:this={password_input} | ||||||
|                     type="password" |                     type="password" | ||||||
|                     name="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" /> |                     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 |                     <span | ||||||
|                       class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"> |                       class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"> | ||||||
|                       Password is required |                       {$_('password-is-required')} | ||||||
|                     </span> |                     </span> | ||||||
|                   {/if} |                   {/if} | ||||||
|                 </div> |                 </div> | ||||||
|                 <div class="col-span-6"> |                 <div class="col-span-6"> | ||||||
|                   <label |                   <label | ||||||
|                     for="email" |                     for="trackname" | ||||||
|                     class="block text-sm font-medium text-gray-700">E-Mail</label> |                     class="block text-sm font-medium text-gray-700">{$_('username')}</label> | ||||||
|                   <input |                   <input | ||||||
|                     autocomplete="off" |                     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:border-red-500={!isEmailValid} | ||||||
|                     class:focus:border-red-500={!isEmailValid} |                     class:focus:border-red-500={!isEmailValid} | ||||||
|                     class:focus:ring-red-500={!isEmailValid} |                     class:focus:ring-red-500={!isEmailValid} | ||||||
| @@ -232,7 +249,7 @@ | |||||||
|                   {#if !isEmailValid} |                   {#if !isEmailValid} | ||||||
|                     <span |                     <span | ||||||
|                       class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"> |                       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> |                     </span> | ||||||
|                   {/if} |                   {/if} | ||||||
|                 </div> |                 </div> | ||||||
| @@ -247,7 +264,7 @@ | |||||||
|             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"> | ||||||
|             Create |             {$_('create')} | ||||||
|           </button> |           </button> | ||||||
|           <button |           <button | ||||||
|             on:click={() => { |             on:click={() => { | ||||||
| @@ -255,7 +272,7 @@ | |||||||
|             }} |             }} | ||||||
|             type="button" |             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"> |             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> |           </button> | ||||||
|         </div> |         </div> | ||||||
|       </div> |       </div> | ||||||
|   | |||||||
| @@ -24,19 +24,40 @@ | |||||||
|       ) |       ) | ||||||
|         check = true; |         check = true; | ||||||
|     })(navigator.userAgent || navigator.vendor || window.opera); |     })(navigator.userAgent || navigator.vendor || window.opera); | ||||||
|  |     const aspectratio=window.innerWidth/window.innerHeight; | ||||||
|  |     if(aspectratio<=0.765){ | ||||||
|  |       check=true; | ||||||
|  |     } | ||||||
|     return check; |     return check; | ||||||
|   } |   } | ||||||
|   $: mobile = ismobile(); |   $: mobile = ismobile(); | ||||||
|  |   window.addEventListener('resize', function(){ | ||||||
|  |     const aspectratio=window.innerWidth/window.innerHeight; | ||||||
|  |     if(aspectratio<=0.765){ | ||||||
|  |       navOpen=false; | ||||||
|  |       mobile=true; | ||||||
|  |     }else{ | ||||||
|  |       navOpen=true; | ||||||
|  |       mobile=false; | ||||||
|  |  | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | //   $: if (mobile===true) { | ||||||
|  | //     console.log("changed to mobile"); | ||||||
|  | // } | ||||||
|  | //   $: if (mobile===false) { | ||||||
|  | //     console.log("changed to md"); | ||||||
|  | // } | ||||||
|   function logout() { |   function logout() { | ||||||
|     localForage.clear(); |     localForage.clear(); | ||||||
|     location.replace("/"); |     location.replace("/"); | ||||||
|   } |   } | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <section class="min-h-screen bg-gray-50 dark:bg-black dark:text-gray-100"> | <section class="min-h-screen bg-gray-50"> | ||||||
|   <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 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 bg-gray-50"> | ||||||
|     <a href="/" class="flex items-center px-4 py-5"> |     <a href="/" class="flex items-center px-4 py-5"> | ||||||
|       <img |       <img | ||||||
|         src="/lfk-logo.png" |         src="/lfk-logo.png" | ||||||
|   | |||||||
| @@ -2,7 +2,6 @@ | |||||||
|   import { _, json } from "svelte-i18n"; |   import { _, json } from "svelte-i18n"; | ||||||
|   import { getlang } from "./datatable_i18n"; |   import { getlang } from "./datatable_i18n"; | ||||||
|   import { Grid } from "gridjs"; |   import { Grid } from "gridjs"; | ||||||
|   import "gridjs/dist/theme/mermaid.css"; |  | ||||||
|   // |   // | ||||||
|   let table; |   let table; | ||||||
|   const datatable = new Grid({ |   const datatable = new Grid({ | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| <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 | ||||||
| @@ -11,12 +12,60 @@ | |||||||
|   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} | ||||||
|   | |||||||
| @@ -1,15 +1,35 @@ | |||||||
| <script> | <script> | ||||||
|   import { _ } from "svelte-i18n"; |   import { _ } from "svelte-i18n"; | ||||||
|  |   $: releaseinfo = ""; | ||||||
|  |   setTimeout(() => { | ||||||
|  |     releaseinfo = document | ||||||
|  |       .getElementById("buildinfo") | ||||||
|  |       .textContent.replace("RELEASE_INFO-", "") | ||||||
|  |       .replace("-RELEASE_INFO", ""); | ||||||
|  |   }, 1500); | ||||||
|  |   const year = new Date().getFullYear(); | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <footer class="container"> | <footer class="p-5 w-full"> | ||||||
|   <hr class="mt-2 mb-4 border-b-1 border-gray-300" /> |  | ||||||
|   <p class="text-sm text-gray-500 mt-4"> |   <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 |     <a | ||||||
|       class="underline" |       class="underline" | ||||||
|       href="https://odit.services" |       href="https://odit.services" | ||||||
|       rel="noopener,noreferrer" |       rel="noopener,noreferrer" | ||||||
|       target="_blank">ODIT.Services</a> |       target="_blank">ODIT.Services</a> | ||||||
|   </p> |   </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> | </footer> | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ | |||||||
|   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"; | ||||||
|  |   import Footer from "./Footer.svelte"; | ||||||
|   import Toastify from "toastify-js"; |   import Toastify from "toastify-js"; | ||||||
|   // ------ |   // ------ | ||||||
|   let username = "demo"; |   let username = "demo"; | ||||||
| @@ -17,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, | ||||||
| @@ -140,3 +141,4 @@ | |||||||
|     </div> |     </div> | ||||||
|   </div> |   </div> | ||||||
| </div> | </div> | ||||||
|  | <Footer /> | ||||||
|   | |||||||
| @@ -1,83 +1,205 @@ | |||||||
| <script> | <script> | ||||||
|  |   import { RunnerOrganisationService } from "@odit/lfk-client-js"; | ||||||
|  |   import { _ } from "svelte-i18n"; | ||||||
|  |   import Toastify from "toastify-js"; | ||||||
|  |   import store from "../store"; | ||||||
|  |   import PromiseError from "./PromiseError.svelte"; | ||||||
|  |   $: delete_triggered = false; | ||||||
|  |   $: save_enabled = !data_changed; | ||||||
|   export let params; |   export let params; | ||||||
|  |   let orgdata = {}; | ||||||
|  |   let original = {}; | ||||||
|  |   $: data_loaded = false; | ||||||
|  |   $: data_changed = JSON.stringify(orgdata) === JSON.stringify(original); | ||||||
|  |   const promise = RunnerOrganisationService.runnerOrganisationControllerGetOne( | ||||||
|  |     params.orgid | ||||||
|  |   ).then((value) => { | ||||||
|  |     data_loaded = true; | ||||||
|  |     orgdata = Object.assign(orgdata, value); | ||||||
|  |     original = Object.assign(original, value); | ||||||
|  |   }); | ||||||
|  |   function deleteOrganisation() { | ||||||
|  |     RunnerOrganisationService.runnerOrganisationControllerRemove( | ||||||
|  |       original.id, | ||||||
|  |       true | ||||||
|  |     ) | ||||||
|  |       .then((resp) => { | ||||||
|  |         location.replace("./"); | ||||||
|  |       }) | ||||||
|  |       .catch((err) => {}); | ||||||
|  |   } | ||||||
|  |   function submit() { | ||||||
|  |     if (data_loaded === true && save_enabled) { | ||||||
|  |       Toastify({ | ||||||
|  |         text: "updating organization", | ||||||
|  |         duration: 2500, | ||||||
|  |       }).showToast(); | ||||||
|  |       RunnerOrganisationService.runnerOrganisationControllerPut( | ||||||
|  |         original.id, | ||||||
|  |         orgdata | ||||||
|  |       ) | ||||||
|  |         .then((resp) => { | ||||||
|  |           Object.assign(original, orgdata); | ||||||
|  |           original = orgdata; | ||||||
|  |           Object.assign(original, orgdata); | ||||||
|  |           // | ||||||
|  |           Toastify({ | ||||||
|  |             text: "updated organization", | ||||||
|  |             duration: 2500, | ||||||
|  |             backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)", | ||||||
|  |           }).showToast(); | ||||||
|  |         }) | ||||||
|  |         .catch((err) => {}); | ||||||
|  |     } else { | ||||||
|  |     } | ||||||
|  |   } | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <section class="container p-5"> | {#if data_loaded} | ||||||
|   <span class="mb-1 text-3xl font-extrabold leading-tight"> |   <section class="container p-5"> | ||||||
|     Orgs |     <div class="mb-8 text-3xl font-extrabold leading-tight"> | ||||||
|   </span> |       {original.name} | ||||||
|   <p class="mb-8 text-lg text-gray-500"> |       <span data-id="org_actions_${orgdata.id}"> | ||||||
|     configure the tracks & minimum lap times |         {#if store.state.jwtinfo.userdetails.permissions.includes('USER:DELETE')} | ||||||
|   </p> |           {#if delete_triggered} | ||||||
|   <div class="flex flex-row mb-4"> |             <button | ||||||
|     <div class="w-full"> |               on:click={deleteOrganisation} | ||||||
|       <nav class="w-full flex"> |               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> | ||||||
|         <ol class="list-none flex flex-row items-center justify-start"> |             <button | ||||||
|           <li class="mr-2 flex items-center"> |               on:click={() => { | ||||||
|             <svg |                 delete_triggered = !delete_triggered; | ||||||
|               stroke="currentColor" |               }} | ||||||
|               fill="none" |               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> | ||||||
|               stroke-width="2" |           {/if} | ||||||
|               viewBox="0 0 24 24" |           {#if !delete_triggered} | ||||||
|               stroke-linecap="round" |             <button | ||||||
|               stroke-linejoin="round" |               on:click={() => { | ||||||
|               class="h-3 w-3 stroke-current" |                 delete_triggered = true; | ||||||
|               height="1em" |               }} | ||||||
|               width="1em" |               type="button" | ||||||
|               xmlns="http://www.w3.org/2000/svg"><path |               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-organization')}</button> | ||||||
|                 d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" /> |           {/if} | ||||||
|               <polyline points="9 22 9 12 15 12 15 22" /></svg> |         {/if} | ||||||
|           </li> |         {#if !delete_triggered} | ||||||
|           <li class="flex items-center"> |           <button | ||||||
|             <a class="mr-2" href="/">Home</a><svg |             on:click={submit} | ||||||
|               stroke="currentColor" |             disabled={!save_enabled} | ||||||
|               fill="none" |             class:opacity-50={!save_enabled} | ||||||
|               stroke-width="2" |             type="button" | ||||||
|               viewBox="0 0 24 24" |             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> | ||||||
|               stroke-linecap="round" |         {/if} | ||||||
|               stroke-linejoin="round" |       </span> | ||||||
|               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> |     <div class="flex flex-row mb-4"> | ||||||
| </section> |       <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 class="text-sm w-full"> | ||||||
|  |       <label for="name" class="font-medium text-gray-700">Name</label> | ||||||
|  |       <input | ||||||
|  |         autocomplete="off" | ||||||
|  |         placeholder="Name" | ||||||
|  |         type="text" | ||||||
|  |         bind:value={orgdata.name} | ||||||
|  |         name="name" | ||||||
|  |         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="contact" | ||||||
|  |         class="font-medium text-gray-700">{$_('contact')}</label> | ||||||
|  |       <input | ||||||
|  |         autocomplete="off" | ||||||
|  |         placeholder={$_('contact')} | ||||||
|  |         type="text" | ||||||
|  |         bind:value={orgdata.contact} | ||||||
|  |         name="contact" | ||||||
|  |         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="address" | ||||||
|  |         class="font-medium text-gray-700">{$_('address')}</label> | ||||||
|  |       <input | ||||||
|  |         autocomplete="off" | ||||||
|  |         placeholder={$_('address')} | ||||||
|  |         type="text" | ||||||
|  |         bind:value={orgdata.address} | ||||||
|  |         name="address" | ||||||
|  |         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> | ||||||
|  | {:else} | ||||||
|  |   {#await promise} | ||||||
|  |     organization detail is being loaded... | ||||||
|  |   {:catch error} | ||||||
|  |     <PromiseError /> | ||||||
|  |   {/await} | ||||||
|  | {/if} | ||||||
|   | |||||||
							
								
								
									
										157
									
								
								src/components/OrgOverview.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								src/components/OrgOverview.svelte
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,157 @@ | |||||||
|  | <script> | ||||||
|  |   import { _ } from "svelte-i18n"; | ||||||
|  |   import { RunnerOrganisationService } from "@odit/lfk-client-js"; | ||||||
|  |   import "gridjs/dist/theme/mermaid.css"; | ||||||
|  |   import store from "../store"; | ||||||
|  |   import OrgsEmptyState from "./OrgsEmptyState.svelte"; | ||||||
|  |   $: searchvalue = ""; | ||||||
|  |   $: active_deletes = []; | ||||||
|  |   export let current_organizations = []; | ||||||
|  |  | ||||||
|  |   const promise = RunnerOrganisationService.runnerOrganisationControllerGetAll().then( | ||||||
|  |     (val) => { | ||||||
|  |       current_organizations = val; | ||||||
|  |     } | ||||||
|  |   ); | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | {#if store.state.jwtinfo.userdetails.permissions.includes('ORGANISATION:GET')} | ||||||
|  |   {#await 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">organizations are being loaded...</p> | ||||||
|  |       <p class="text-sm">{$_('this-might-take-a-moment')}</p> | ||||||
|  |     </div> | ||||||
|  |   {:then} | ||||||
|  |     {#if current_organizations.length === 0} | ||||||
|  |       <OrgsEmptyState /> | ||||||
|  |     {:else} | ||||||
|  |       <input | ||||||
|  |         type="search" | ||||||
|  |         bind:value={searchvalue} | ||||||
|  |         placeholder={$_('datatable.search')} | ||||||
|  |         aria-label={$_('datatable.search')} | ||||||
|  |         class="gridjs-input gridjs-search-input mb-4" /> | ||||||
|  |       <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"> | ||||||
|  |                 Address | ||||||
|  |               </th> | ||||||
|  |               <th | ||||||
|  |                 scope="col" | ||||||
|  |                 class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"> | ||||||
|  |                 Contact | ||||||
|  |               </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_organizations as o} | ||||||
|  |               {#if Object.values(o) | ||||||
|  |                 .toString() | ||||||
|  |                 .toLowerCase() | ||||||
|  |                 .includes(searchvalue)} | ||||||
|  |                 <tr data-rowid="org_{o.id}"> | ||||||
|  |                   <td class="px-6 py-4 whitespace-nowrap"> | ||||||
|  |                     <div class="flex items-center"> | ||||||
|  |                       <div class="ml-4"> | ||||||
|  |                         <div | ||||||
|  |                           class="text-sm font-medium text-gray-900 dark:text-gray-100"> | ||||||
|  |                           {o.name} | ||||||
|  |                         </div> | ||||||
|  |                       </div> | ||||||
|  |                     </div> | ||||||
|  |                   </td> | ||||||
|  |                   <td class="px-6 py-4 whitespace-nowrap"> | ||||||
|  |                     <div class="flex items-center"> | ||||||
|  |                       <div class="ml-4"> | ||||||
|  |                         <div | ||||||
|  |                           class="text-sm font-medium text-gray-900 dark:text-gray-100"> | ||||||
|  |                           {#if o.address} | ||||||
|  |                             {JSON.stringify(o.address)} | ||||||
|  |                           {:else}no address specified{/if} | ||||||
|  |                         </div> | ||||||
|  |                       </div> | ||||||
|  |                     </div> | ||||||
|  |                   </td> | ||||||
|  |                   <td class="px-6 py-4 whitespace-nowrap"> | ||||||
|  |                     <div class="flex items-center"> | ||||||
|  |                       <div class="ml-4"> | ||||||
|  |                         <div | ||||||
|  |                           class="text-sm font-medium text-gray-900 dark:text-gray-100"> | ||||||
|  |                           {#if o.contact} | ||||||
|  |                             {JSON.stringify(o.contact)} | ||||||
|  |                           {:else}no contact specified{/if} | ||||||
|  |                         </div> | ||||||
|  |                       </div> | ||||||
|  |                     </div> | ||||||
|  |                   </td> | ||||||
|  |                   {#if active_deletes[o.id] === true} | ||||||
|  |                     <td | ||||||
|  |                       class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium"> | ||||||
|  |                       <button | ||||||
|  |                         on:click={() => { | ||||||
|  |                           active_deletes[o.id] = false; | ||||||
|  |                         }} | ||||||
|  |                         tabindex="0" | ||||||
|  |                         class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer">Cancel | ||||||
|  |                         Delete</button> | ||||||
|  |                       <button | ||||||
|  |                         on:click={() => { | ||||||
|  |                           RunnerOrganisationService.runnerOrganisationControllerRemove(o.id, true) | ||||||
|  |                             .then((resp) => { | ||||||
|  |                               current_organizations = current_organizations.filter((obj) => obj.id !== o.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="./{o.id}" | ||||||
|  |                         class="text-indigo-600 hover:text-indigo-900">Edit</a> | ||||||
|  |                       {#if store.state.jwtinfo.userdetails.permissions.includes('ORGANISATION:DELETE')} | ||||||
|  |                         <button | ||||||
|  |                           on:click={() => { | ||||||
|  |                             active_deletes[o.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} | ||||||
| @@ -1,13 +1,31 @@ | |||||||
| <script> | <script> | ||||||
|   import { _ } from "svelte-i18n"; |   import { _ } from "svelte-i18n"; | ||||||
|  |   import store from "../store"; | ||||||
|  |   import AddOrgModal from "./AddOrgModal.svelte"; | ||||||
|  |   export let modal_open = false; | ||||||
|  |   import OrgOverview from "./OrgOverview.svelte"; | ||||||
|  |   console.log(store.state.jwtinfo.userdetails.permissions); | ||||||
|  |   let current_organizations = []; | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <section class="container p-5"> | <section class="container p-5"> | ||||||
|   <span class="mb-1 text-3xl font-extrabold leading-tight"> |   <span class="mb-1 text-3xl font-extrabold leading-tight"> | ||||||
|     Orgs |     {$_('organizations')} | ||||||
|  |     {#if store.state.jwtinfo.userdetails.permissions.includes('ORGANISATION: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-organization')} | ||||||
|  |       </button> | ||||||
|  |     {/if} | ||||||
|   </span> |   </span> | ||||||
|   <p class="mb-8 text-lg text-gray-500"> |   <p class="mb-8 text-lg text-gray-500">manage runner organizations</p> | ||||||
|     add, delete, edit organizations |   <OrgOverview bind:current_organizations /> | ||||||
|   </p> |  | ||||||
|   <nav><a class="underline" href="./1">Org 1</a></nav> |  | ||||||
| </section> | </section> | ||||||
|  |  | ||||||
|  | {#if store.state.jwtinfo.userdetails.permissions.includes('ORGANISATION:CREATE')} | ||||||
|  |   <AddOrgModal bind:current_organizations bind:modal_open /> | ||||||
|  | {/if} | ||||||
|   | |||||||
							
								
								
									
										15
									
								
								src/components/OrgsEmptyState.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/components/OrgsEmptyState.svelte
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | |||||||
|  | <script> | ||||||
|  |   import { _ } from "svelte-i18n"; | ||||||
|  |   import AddOrgModal from "./AddOrgModal.svelte"; | ||||||
|  |   let modal_open = false; | ||||||
|  |   let current_organizations = []; | ||||||
|  | </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 organizations added yet.</span><br /> | ||||||
|  |     <span>Add your first organization</span> | ||||||
|  |   </p> | ||||||
|  | </div> | ||||||
|  |  | ||||||
|  | <AddOrgModal bind:modal_open bind:current_organizations /> | ||||||
| @@ -6,7 +6,6 @@ | |||||||
|   const tracks_promise = TrackService.trackControllerGetAll(); |   const tracks_promise = TrackService.trackControllerGetAll(); | ||||||
|   import { getlang } from "./datatable_i18n"; |   import { getlang } from "./datatable_i18n"; | ||||||
|   import { Grid, html } from "gridjs"; |   import { Grid, html } from "gridjs"; | ||||||
|   import "gridjs/dist/theme/mermaid.css"; |  | ||||||
|   import { tracks as tracksstore } from "../store.js"; |   import { tracks as tracksstore } from "../store.js"; | ||||||
|   $: trackscache = []; |   $: trackscache = []; | ||||||
|   $: blocked = []; |   $: blocked = []; | ||||||
|   | |||||||
| @@ -1,15 +1,92 @@ | |||||||
| <script> | <script> | ||||||
|   import { _ } from "svelte-i18n"; |   import { _ } from "svelte-i18n"; | ||||||
|   import { UserService } from "@odit/lfk-client-js"; |   import lodashIsEqual from "lodash.isequal"; | ||||||
|   import "gridjs/dist/theme/mermaid.css"; |   import store from "../store"; | ||||||
|   import { tracks as tracksstore } from "../store.js"; |   import { | ||||||
|  |     UserService, | ||||||
|  |     UserGroupService, | ||||||
|  |     PermissionService, | ||||||
|  |   } from "@odit/lfk-client-js"; | ||||||
|  |   import Toastify from "toastify-js"; | ||||||
|   import PromiseError from "./PromiseError.svelte"; |   import PromiseError from "./PromiseError.svelte"; | ||||||
|   export let params; |   export let params; | ||||||
|   const user_promise = UserService.userControllerGetOne(params.userid); |   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) => { |   user_promise.then((data) => { | ||||||
|     console.log(data); |     data_loaded = true; | ||||||
|     tracksstore.set(data); |     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> | </script> | ||||||
|  |  | ||||||
| {#await user_promise} | {#await user_promise} | ||||||
| @@ -50,34 +127,54 @@ | |||||||
|                 <polyline points="12 5 19 12 12 19" /></svg> |                 <polyline points="12 5 19 12 12 19" /></svg> | ||||||
|             </li> |             </li> | ||||||
|             <li class="flex items-center"> |             <li class="flex items-center"> | ||||||
|               <span class="mr-2">{user.firstname} |               <span class="mr-2">{original_data.firstname} | ||||||
|                 {user.middlename || ''} |                 {original_data.middlename || ''} | ||||||
|                 {user.lastname}</span> |                 {original_data.lastname}</span> | ||||||
|             </li> |             </li> | ||||||
|           </ol> |           </ol> | ||||||
|         </nav> |         </nav> | ||||||
|       </div> |       </div> | ||||||
|     </div> |     </div> | ||||||
|     <span |     <div class="mb-8 text-3xl font-extrabold leading-tight"> | ||||||
|       class="mb-4 text-3xl font-extrabold leading-tight">{user.firstname} |       {original_data.firstname} | ||||||
|       {user.middlename || ''} |       {original_data.middlename || ''} | ||||||
|       {user.lastname} |       {original_data.lastname} | ||||||
|       <button |       <span data-id="user_actions_${editable_userdata.id}"> | ||||||
|         type="button" |         {#if store.state.jwtinfo.userdetails.permissions.includes('USER:DELETE')} | ||||||
|         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 |           {#if delete_triggered} | ||||||
|         User</button></span> |             <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-2 flex items-center"> |     <div class="mt-2 flex items-center"> | ||||||
|       <img |       <img | ||||||
|         alt={$_('profile-picture')} |         alt={$_('profile-picture')} | ||||||
|         class="inline-block h-20 w-20 rounded-full overflow-hidden bg-gray-100" |         class="inline-block h-20 w-20 rounded-full overflow-hidden bg-gray-100" | ||||||
|         src={user.profilePic} /> |         src={editable_userdata.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 |       <button | ||||||
|         type="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> | ||||||
| @@ -86,8 +183,13 @@ | |||||||
|     <div class="mt-3 text-sm w-full"> |     <div class="mt-3 text-sm w-full"> | ||||||
|       <input |       <input | ||||||
|         id="enabled" |         id="enabled" | ||||||
|  |         on:change={() => { | ||||||
|  |           editable_userdata.enabled = !editable_userdata.enabled; | ||||||
|  |           // TODO: this reactive set does not work? | ||||||
|  |         }} | ||||||
|         name="enabled" |         name="enabled" | ||||||
|         type="checkbox" |         type="checkbox" | ||||||
|  |         checked={editable_userdata.enabled} | ||||||
|         class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded" /> |         class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded" /> | ||||||
|       <label |       <label | ||||||
|         for="enabled" |         for="enabled" | ||||||
| @@ -95,34 +197,138 @@ | |||||||
|       <p class="text-gray-500">set the user active/ inactive</p> |       <p class="text-gray-500">set the user active/ inactive</p> | ||||||
|     </div> |     </div> | ||||||
|     <div class="text-sm w-full"> |     <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 |       <input | ||||||
|         autocomplete="off" |         autocomplete="off" | ||||||
|         placeholder="First name" |         placeholder={$_('first-name')} | ||||||
|         type="text" |         type="text" | ||||||
|  |         bind:value={editable_userdata.firstname} | ||||||
|         name="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" /> |         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> | ||||||
|     <div class="text-sm w-full"> |     <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 |       <input | ||||||
|         autocomplete="off" |         autocomplete="off" | ||||||
|         placeholder="Middle name" |         placeholder={$_('middle-name')} | ||||||
|         type="text" |         type="text" | ||||||
|  |         bind:value={editable_userdata.middlename} | ||||||
|         name="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" /> |         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> | ||||||
|     <div class="text-sm w-full"> |     <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 |       <input | ||||||
|         autocomplete="off" |         autocomplete="off" | ||||||
|         placeholder="Last name" |         placeholder={$_('last-name')} | ||||||
|         type="text" |         type="text" | ||||||
|  |         bind:value={editable_userdata.lastname} | ||||||
|         name="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" /> |         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> | ||||||
|  |     <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> |   </section> | ||||||
| {:catch error} | {:catch error} | ||||||
|   <!-- promise was rejected --> |  | ||||||
|   <PromiseError {error} /> |   <PromiseError {error} /> | ||||||
| {/await} | {/await} | ||||||
|   | |||||||
| @@ -1,25 +1,31 @@ | |||||||
| <script> | <script> | ||||||
|   import { _ } from "svelte-i18n"; |   import { _ } from "svelte-i18n"; | ||||||
|  |   import store from "../store"; | ||||||
|   import AddUserModal from "./AddUserModal.svelte"; |   import AddUserModal from "./AddUserModal.svelte"; | ||||||
|   export let modal_open = false; |   export let modal_open = false; | ||||||
|   import UsersOverview from "./UsersOverview.svelte"; |   import UsersOverview from "./UsersOverview.svelte"; | ||||||
|  |   console.log(store.state.jwtinfo.userdetails.permissions); | ||||||
|  |   let current_users=[]; | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <section class="container p-5"> | <section class="container p-5"> | ||||||
|   <span class="mb-1 text-3xl font-extrabold leading-tight"> |   <span class="mb-1 text-3xl font-extrabold leading-tight"> | ||||||
|     Users |     {$_('users')} | ||||||
|     <button |     {#if store.state.jwtinfo.userdetails.permissions.includes('USER:CREATE')} | ||||||
|       on:click={() => { |       <button | ||||||
|         modal_open = true; |         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"> |         type="button" | ||||||
|       Create User |         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"> | ||||||
|     </button> |         {$_('create-user')} | ||||||
|  |       </button> | ||||||
|  |     {/if} | ||||||
|   </span> |   </span> | ||||||
|   <p class="mb-8 text-lg text-gray-500"> |   <p class="mb-8 text-lg text-gray-500">{$_('manage-admin-users')}</p> | ||||||
|     manage admin users |   <UsersOverview bind:current_users /> | ||||||
|   </p> |  | ||||||
|   <UsersOverview /> |  | ||||||
| </section> | </section> | ||||||
| <AddUserModal bind:modal_open /> |  | ||||||
|  | {#if store.state.jwtinfo.userdetails.permissions.includes('USER:CREATE')} | ||||||
|  |   <AddUserModal bind:current_users bind:modal_open /> | ||||||
|  | {/if} | ||||||
|   | |||||||
| @@ -1,217 +1,179 @@ | |||||||
| <script> | <script> | ||||||
|   import { _, json } from "svelte-i18n"; |   import { _ } from "svelte-i18n"; | ||||||
|   import Toastify from "toastify-js"; |   import { UserService } from "@odit/lfk-client-js"; | ||||||
|   import TracksEmptyState from "./TracksEmptyState.svelte"; |  | ||||||
|   import { TrackService, UserService } from "@odit/lfk-client-js"; |  | ||||||
|   const users_promise = UserService.userControllerGetAll(); |   const users_promise = UserService.userControllerGetAll(); | ||||||
|   import { getlang } from "./datatable_i18n"; |   import { users as usersstore } from "../store.js"; | ||||||
|   import { Grid, html } from "gridjs"; |   import store from "../store"; | ||||||
|   import "gridjs/dist/theme/mermaid.css"; |  | ||||||
|   import { tracks as tracksstore } from "../store.js"; |  | ||||||
|   import UsersEmptyState from "./UsersEmptyState.svelte"; |   import UsersEmptyState from "./UsersEmptyState.svelte"; | ||||||
|   $: userscache = []; |   $: searchvalue = ""; | ||||||
|   $: blocked = []; |   $: active_deletes = []; | ||||||
|   let table; |   export let current_users=[]; | ||||||
|   let datatable; |   $: advanced_search = false; | ||||||
|   let datatable_inited = false; |   usersstore.subscribe((val) => { | ||||||
|   tracksstore.subscribe((val) => { |  | ||||||
|     userscache = val; |     userscache = val; | ||||||
|  |     current_users=val; | ||||||
|   }); |   }); | ||||||
|   users_promise.then((data) => { |   users_promise.then((data) => { | ||||||
|     console.log(data); |     usersstore.set(data); | ||||||
|     tracksstore.set(data); |  | ||||||
|   }); |   }); | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| {#await users_promise} | {#if store.state.jwtinfo.userdetails.permissions.includes('USER:GET')} | ||||||
|   <div |   {#await users_promise} | ||||||
|     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} |  | ||||||
|     <div |     <div | ||||||
|       class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll"> |       class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2" | ||||||
|       <table class="divide-y divide-gray-200 w-full"> |       role="alert"> | ||||||
|         <thead class="bg-gray-50"> |       <p class="font-bold">users are being loaded...</p> | ||||||
|           <tr> |       <p class="text-sm">{$_('this-might-take-a-moment')}</p> | ||||||
|             <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> |  | ||||||
|     </div> |     </div> | ||||||
|   {/if} |   {:then} | ||||||
| {:catch error} |     {#if current_users.length === 0} | ||||||
|   <div class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500"> |       <UsersEmptyState /> | ||||||
|     <span class="inline-block align-middle mr-8"> |     {:else} | ||||||
|       <b class="capitalize">{$_('general_promise_error')}</b> |       {#if advanced_search} | ||||||
|       {error} |         advanced search | ||||||
|     </span> |       {:else} | ||||||
|   </div> |         <input | ||||||
| {/await} |           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} | ||||||
|   | |||||||
| @@ -4,14 +4,23 @@ | |||||||
|     "about": "About", |     "about": "About", | ||||||
|     "action": "Action", |     "action": "Action", | ||||||
|     "add-your-first-track": "Add your first track", |     "add-your-first-track": "Add your first track", | ||||||
|  |     "address": "Address", | ||||||
|     "application_name": "Lauf für Kaya! - Admin", |     "application_name": "Lauf für Kaya! - Admin", | ||||||
|     "author": "Author", |     "author": "Author", | ||||||
|  |     "browse": "Browse", | ||||||
|     "by": "by", |     "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", |     "cannot-reset-your-password-directly": "Bummer. We unfortunately cannot reset your password directly. Please send us a mail and confirm your identity", | ||||||
|     "changelog": "Changelog", |     "changelog": "Changelog", | ||||||
|  |     "close": "Close", | ||||||
|  |     "confirm-delete": "Confirm Delete", | ||||||
|  |     "contact": "Contact", | ||||||
|     "count_organizations": "# Organizations", |     "count_organizations": "# Organizations", | ||||||
|     "count_teams": "# Teams", |     "count_teams": "# Teams", | ||||||
|  |     "create": "Create", | ||||||
|     "create-a-new-track": "Create a new Track", |     "create-a-new-track": "Create a new Track", | ||||||
|  |     "create-organization": "Create Organization", | ||||||
|  |     "create-user": "Create User", | ||||||
|     "credits": "Credits", |     "credits": "Credits", | ||||||
|     "dashboard-greeting": "hello there", |     "dashboard-greeting": "hello there", | ||||||
|     "dashboard-title": "Dashboard", |     "dashboard-title": "Dashboard", | ||||||
| @@ -30,33 +39,66 @@ | |||||||
|         "no_matching_records_found": "No matching records found", |         "no_matching_records_found": "No matching records found", | ||||||
|         "an_error_happened_while_fetching_the_data": "An error happened while fetching the data" |         "an_error_happened_while_fetching_the_data": "An error happened while fetching the data" | ||||||
|     }, |     }, | ||||||
|  |     "delete-organization": "Delete Organization", | ||||||
|  |     "delete-user": "Delete User", | ||||||
|     "dependency_name": "Name", |     "dependency_name": "Name", | ||||||
|     "dont-have-your-email-connected": "Don't have your email connected?", |     "dont-have-your-email-connected": "Don't have your email connected?", | ||||||
|     "dont-panic-were-resetting-it": "Don't panic, we're resetting it ✌", |     "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", |     "e-mail-adress": "E-Mail Adress", | ||||||
|     "email_address_or_username": "Email / username", |     "email_address_or_username": "Email / username", | ||||||
|     "error_on_login": "Error on login", |     "error_on_login": "Error on login", | ||||||
|     "faq": "FAQ", |     "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?", |     "forgot_password?": "Forgot your password?", | ||||||
|     "general-stats": "General Stats", |     "general-stats": "General Stats", | ||||||
|     "general_promise_error": "😢 Error", |     "general_promise_error": "😢 Error", | ||||||
|     "goback": "Go Home", |     "goback": "Go Home", | ||||||
|  |     "groups": "Groups", | ||||||
|     "hallo": "hello", |     "hallo": "hello", | ||||||
|     "installed-version": "Installed version", |     "installed-version": "Installed version", | ||||||
|     "invalid-mail-reset": "the provided email is invalid", |     "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.", |     "lfk-is-os": "The \"Lauf für Kaya!\" Frontend is (like all other projects for the \"LfK!\" Also) an open source project.", | ||||||
|     "license": "License", |     "license": "License", | ||||||
|  |     "licenses-are-being-loaded": "Licenses are being loaded...", | ||||||
|     "log_in": "Log in", |     "log_in": "Log in", | ||||||
|     "log_in_to_your_account": "Log in to your account", |     "log_in_to_your_account": "Log in to your account", | ||||||
|     "login_is_checked": "Login is being checked...", |     "login_is_checked": "Login is being checked...", | ||||||
|     "logout": "Logout", |     "logout": "Logout", | ||||||
|     "mail-validation-in-progress": "mail validation in progress...", |     "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", |     "minimum-lap-time-in-s": "minimum lap time in s", | ||||||
|     "no-license-text-could-be-found": "No license text could be found 😢", |     "no-license-text-could-be-found": "No license text could be found 😢", | ||||||
|     "no-tracks-added-yet": "there are no tracks added yet.", |     "no-tracks-added-yet": "there are no tracks added yet.", | ||||||
|  |     "organizations": "Organizations", | ||||||
|     "orgs": "Orgs", |     "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!", |     "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": "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.", |     "please-provide-the-required-information-to-add-a-new-track": "Please provide the required information to add a new track.", | ||||||
|     "profile-picture": "Profile Picture", |     "profile-picture": "Profile Picture", | ||||||
|     "read-license": "Read License", |     "read-license": "Read License", | ||||||
| @@ -64,6 +106,7 @@ | |||||||
|     "repo_link": "Link", |     "repo_link": "Link", | ||||||
|     "reset-my-password": "Reset my password", |     "reset-my-password": "Reset my password", | ||||||
|     "runners": "Runners", |     "runners": "Runners", | ||||||
|  |     "save-changes": "Save Changes", | ||||||
|     "send-a-mail-to-lfk-odit-services": "send a mail to lfk@odit.services", |     "send-a-mail-to-lfk-odit-services": "send a mail to lfk@odit.services", | ||||||
|     "settings": "Settings", |     "settings": "Settings", | ||||||
|     "signout": "Sign out", |     "signout": "Sign out", | ||||||
| @@ -79,7 +122,11 @@ | |||||||
|     "track-length-in-m": "Track Length in m", |     "track-length-in-m": "Track Length in m", | ||||||
|     "track-name": "Track name", |     "track-name": "Track name", | ||||||
|     "tracks": "Tracks", |     "tracks": "Tracks", | ||||||
|  |     "updating-user": "updating user...", | ||||||
|  |     "user-updated": "User updated", | ||||||
|  |     "username": "Username", | ||||||
|     "users": "Users", |     "users": "Users", | ||||||
|  |     "valid-email-is-required": "valid email is required", | ||||||
|     "welcome_wavinghand": "Welcome 👋", |     "welcome_wavinghand": "Welcome 👋", | ||||||
|     "your_profile": "Your Profile" |     "your_profile": "Your Profile" | ||||||
| } | } | ||||||
							
								
								
									
										31
									
								
								src/store.js
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								src/store.js
									
									
									
									
									
								
							| @@ -1,12 +1,16 @@ | |||||||
| 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 users = writable([]); | ||||||
| export let tracks = 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); | ||||||
| @@ -18,17 +22,38 @@ const store = () => { | |||||||
| 				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; | ||||||
|  | 				const jwtinfo = JSON.parse(atob(auth.access_token.split('.')[1])); | ||||||
|  | 				state.jwtinfo = jwtinfo; | ||||||
|  | 				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; | ||||||
|  | 				// | ||||||
|  | 				state.refreshInterval = setInterval(() => { | ||||||
|  | 					this.refreshAuth(); | ||||||
|  | 					// 2min | ||||||
|  | 				}, 2 * 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; | ||||||
| 			}); | 			}); | ||||||
| 		} | 		} | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ module.exports = { | |||||||
| 	purge: { | 	purge: { | ||||||
| 		content: [ './src/**/*.svelte' ] | 		content: [ './src/**/*.svelte' ] | ||||||
| 	}, | 	}, | ||||||
| 	darkMode: 'media', | 	// darkMode: 'media', | ||||||
| 	variants: {}, | 	variants: {}, | ||||||
| 	plugins: [], | 	plugins: [], | ||||||
| 	theme: { | 	theme: { | ||||||
|   | |||||||
							
								
								
									
										5
									
								
								versionbuilder.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								versionbuilder.js
									
									
									
									
									
										Normal 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); | ||||||
		Reference in New Issue
	
	Block a user