Compare commits
	
		
			64 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 2bbaa500f4 | |||
| 722a20e141 | |||
| 041c24a837 | |||
| 39a3baa00b | |||
| f7acbb1eaa | |||
| e6fbf7aa5b | |||
| 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 | |||
| b9aa00e8de | |||
| ded31980bf | |||
| 264e0d7ed9 | 
							
								
								
									
										92
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										92
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @@ -2,8 +2,100 @@ | ||||
|  | ||||
| All notable changes to this project will be documented in this file. Dates are displayed in UTC. | ||||
|  | ||||
| #### [0.2.1](https://git.odit.services/lfk/frontend/compare/0.2.0...0.2.1) | ||||
|  | ||||
| - 🔒 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) | ||||
| - 💬 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) | ||||
|   | ||||
| @@ -9,7 +9,7 @@ http { | ||||
|         location / { | ||||
|             try_files $uri $uri/ /index.html; | ||||
|         } | ||||
|         location ~* \.(?:ico|css|js|gif|jpe?g|png)$ { | ||||
|         location ~* \.(?:ico|css|gif|jpe?g|png)$ { | ||||
|             expires 1y; | ||||
|             add_header Pragma public; | ||||
|             add_header Cache-Control "public"; | ||||
|   | ||||
| @@ -1,20 +1,20 @@ | ||||
| { | ||||
| 	"name": "@odit/lfk-frontend", | ||||
| 	"version": "0.1.2-1", | ||||
| 	"version": "0.2.1", | ||||
| 	"scripts": { | ||||
| 		"i18n-order": "node order.js", | ||||
| 		"dev": "snowpack dev", | ||||
| 		"build": "snowpack build", | ||||
| 		"build:sw": "workbox generateSW workbox-config.js", | ||||
| 		"release": "release-it", | ||||
| 		"changelog": "npx auto-changelog --commit-limit false --template https://raw.githubusercontent.com/release-it/release-it/master/templates/changelog-compact.hbs", | ||||
| 		"licenses:export": "license-exporter --json -o public" | ||||
| 	}, | ||||
| 	"dependencies": { | ||||
| 		"@odit/lfk-client-js": "0.0.10", | ||||
| 		"@odit/lfk-client-js": "0.0.11", | ||||
| 		"filepond": "4.25.1", | ||||
| 		"gridjs": "3.2.1", | ||||
| 		"localforage": "1.9.0", | ||||
| 		"lodash.isequal": "^4.5.0", | ||||
| 		"svelte-filepond": "0.0.1", | ||||
| 		"svelte-focus-trap": "1.0.1", | ||||
| 		"svelte-i18n": "3.3.0", | ||||
| @@ -50,7 +50,7 @@ | ||||
| 			"publish": false | ||||
| 		}, | ||||
| 		"hooks": { | ||||
| 			"after:bump": "npx auto-changelog --commit-limit false -p -u --hide-credit  && git add CHANGELOG.md" | ||||
| 			"after:bump": "npx auto-changelog --commit-limit false -p -u --hide-credit && git add CHANGELOG.md && node versionbuilder.js  && git add public/index.html && node order.js  && git add src/locales" | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -13,6 +13,7 @@ | ||||
| </head> | ||||
|  | ||||
| <body> | ||||
|   <span style="display: none;visibility: hidden;" id="buildinfo">RELEASE_INFO-0.2.1-RELEASE_INFO</span> | ||||
|   <noscript>You need to enable JavaScript to run this app.</noscript> | ||||
|   <script src="/env.js"></script> | ||||
|   <script defer type="module" src="/_dist_/index.js"></script> | ||||
|   | ||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -49,7 +49,7 @@ | ||||
|   OpenAPI.BASE = config.baseurl; | ||||
|   import { register as registerSW } from "./swmodule"; | ||||
|   store.init(); | ||||
|   // registerSW(); | ||||
|   registerSW(); | ||||
| </script> | ||||
|  | ||||
| <Route> | ||||
|   | ||||
| @@ -50,14 +50,14 @@ | ||||
|             <div | ||||
|               class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"> | ||||
|               <svg | ||||
|                 class="h-6 w-6 text-blue-600" | ||||
|                 fill="none" | ||||
|                 width="24" | ||||
|                 height="24" | ||||
|                 xmlns="http://www.w3.org/2000/svg" | ||||
|                 viewBox="0 0 640 512"><path | ||||
|                 fill="currentColor" | ||||
|                   d="M635.7 167.2L556.1 31.7c-8.8-15-28.3-20.1-43.5-11.5l-69 39.1L503.3 161c2.2 3.8.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9L416 75l-55.2 31.3 27.9 47.4c2.2 3.8.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9L333.2 122 278 153.3 337.8 255c2.2 3.7.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9l-59.7-101.7-55.2 31.3 27.9 47.4c2.2 3.8.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9l-27.9-47.5-55.2 31.3 59.7 101.7c2.2 3.7.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9L84.9 262.9l-69 39.1C.7 310.7-4.6 329.8 4.2 344.8l79.6 135.6c8.8 15 28.3 20.1 43.5 11.5L624.1 210c15.2-8.6 20.4-27.8 11.6-42.8z" /></svg> | ||||
|                 class="h-6 w-6 text-blue-600" | ||||
|                 xmlns="http://www.w3.org/2000/svg" | ||||
|                 viewBox="0 0 24 24" | ||||
|                 width="24" | ||||
|                 height="24"><path fill="none" d="M0 0h24v24H0z" /> | ||||
|                 <path | ||||
|                   d="M14 20v2H2v-2h12zM14.586.686l7.778 7.778L20.95 9.88l-1.06-.354L17.413 12l5.657 5.657-1.414 1.414L16 13.414l-2.404 2.404.283 1.132-1.415 1.414-7.778-7.778 1.415-1.414 1.13.282 6.294-6.293-.353-1.06L14.586.686z" /></svg> | ||||
|             </div> | ||||
|             <div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left"> | ||||
|               <h3 class="text-lg leading-6 font-medium"> | ||||
| @@ -79,7 +79,7 @@ | ||||
|             }} | ||||
|             type="button" | ||||
|             class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"> | ||||
|             Close | ||||
|             {$_('close')} | ||||
|           </button> | ||||
|         </div> | ||||
|       </div> | ||||
| @@ -112,13 +112,12 @@ | ||||
|     <h2 class="text-4xl font-display font-semibold md:text-5xl"> | ||||
|       {$_('credits')} | ||||
|     </h2> | ||||
|     <div | ||||
|       class="max-w-3xl mx-auto text-xl leading-8 font-medium mt-8"> | ||||
|     <div class="max-w-3xl mx-auto text-xl leading-8 font-medium mt-8"> | ||||
|       <p class="text-center">{$_('oss_credit_description')}</p> | ||||
|     </div> | ||||
|     <div class="w-screen leading-8 pl-5 mt-5"> | ||||
|       {#await license_promise} | ||||
|         <p class="text-center w-full">Licenses are being loaded...</p> | ||||
|         <p class="text-center w-full">{$_('licenses-are-being-loaded')}</p> | ||||
|       {:then} | ||||
|         <table> | ||||
|           <thead> | ||||
| @@ -164,9 +163,7 @@ | ||||
|         </div> | ||||
|       {/await} | ||||
|     </div> | ||||
|     <h2 class="text-4xl font-display font-semibold md:text-5xl"> | ||||
|       Fragen | ||||
|     </h2> | ||||
|     <h2 class="text-4xl font-display font-semibold md:text-5xl">{$_('faq')}</h2> | ||||
|     <div class="mt-6 border-t-2 border-gray-100 pt-10"> | ||||
|       <dl class="md:grid md:grid-cols-2 md:gap-8"> | ||||
|         <div> | ||||
|   | ||||
| @@ -2,34 +2,33 @@ | ||||
|   import { _ } from "svelte-i18n"; | ||||
|   import { clickOutside } from "./outsideclick"; | ||||
|   import { focusTrap } from "svelte-focus-trap"; | ||||
|   import { tracks as tracksstore } from "../store.js"; | ||||
|   import { TrackService, UserService } from "@odit/lfk-client-js"; | ||||
|   import { UserService } from "@odit/lfk-client-js"; | ||||
|   import isEmail from "validator/es/lib/isEmail"; | ||||
|   import Toastify from "toastify-js"; | ||||
|   import "toastify-js/src/toastify.css"; | ||||
|   import About from "./About.svelte"; | ||||
|   export let modal_open; | ||||
|   export let current_users; | ||||
|   let firstname_input; | ||||
|   let lastname_input; | ||||
|   let middlename_input; | ||||
|   let username_input; | ||||
|   let password_input; | ||||
|   let email_input; | ||||
|   function focus(el) { | ||||
|     el.focus(); | ||||
|   } | ||||
|   $: username_input_value = ""; | ||||
|   $: middlename_input_value = ""; | ||||
|   $: password_input_value = ""; | ||||
|   $: email_input_value = ""; | ||||
|   $: lastname_input_value = ""; | ||||
|   $: firstname_input_value = ""; | ||||
|   $: track_min_duration = 0; | ||||
|   $: tracklength = 0; | ||||
|   $: processed_last_submit = true; | ||||
|   $: isPasswordValid = password_input_value.trim().length === 0; | ||||
|   $: isPasswordValid = password_input_value.trim().length !== 0; | ||||
|   $: isEmailValid = isEmail(email_input_value); | ||||
|   $: isLastnameValid = lastname_input_value.trim().length === 0; | ||||
|   $: isFirstnameValid = firstname_input_value.trim().length === 0; | ||||
|   $: createbtnenabled = !isFirstnameValid && !isLastnameValid; | ||||
|   $: isLastnameValid = lastname_input_value.trim().length !== 0; | ||||
|   $: isFirstnameValid = firstname_input_value.trim().length !== 0; | ||||
|   $: createbtnenabled = | ||||
|     isFirstnameValid && isLastnameValid && isEmailValid && isPasswordValid; | ||||
|   (function () { | ||||
|     document.onkeydown = function (e) { | ||||
|       e = e || window.event; | ||||
| @@ -51,16 +50,25 @@ | ||||
|         text: "User is being added...", | ||||
|         duration: -1, | ||||
|       }).showToast(); | ||||
|       UserService.userControllerPost({ | ||||
|       let postdata={ | ||||
|         firstname: firstname_input_value, | ||||
|         lastname: lastname_input_value, | ||||
|         middlename: middlename_input_value, | ||||
|         email:email_input_value,password:password_input_value | ||||
|       }) | ||||
|         password: password_input_value | ||||
|       }; | ||||
|       if(email_input_value!==""){ | ||||
|         postdata.email=email_input_value; | ||||
|       } | ||||
|       if(username_input_value!==""){ | ||||
|         postdata.username=username_input_value; | ||||
|       } | ||||
|       UserService.userControllerPost(postdata) | ||||
|         .then((result) => { | ||||
|           firstname_input_value = ""; | ||||
|           lastname_input_value = ""; | ||||
|           middlename_input_value = ""; | ||||
|           email_input_value = ""; | ||||
|           username_input_value = ""; | ||||
|           modal_open = false; | ||||
|           // | ||||
|           Toastify({ | ||||
| @@ -68,12 +76,8 @@ | ||||
|             duration: 500, | ||||
|             backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)", | ||||
|           }).showToast(); | ||||
|           let storeval = []; | ||||
|           tracksstore.subscribe((val) => { | ||||
|             storeval = val; | ||||
|           }); | ||||
|           storeval.push(result); | ||||
|           tracksstore.set(storeval); | ||||
|           current_users.push(result); | ||||
|           current_users=current_users; | ||||
|         }) | ||||
|         .catch((err) => { | ||||
|           // | ||||
| @@ -137,33 +141,33 @@ | ||||
|                 <div class="col-span-6"> | ||||
|                   <label | ||||
|                     for="firstname" | ||||
|                     class="block text-sm font-medium text-gray-700">First Name</label> | ||||
|                     class="block text-sm font-medium text-gray-700">{$_('first-name')}</label> | ||||
|                   <input | ||||
|                     use:focus | ||||
|                     autocomplete="off" | ||||
|                     placeholder="First Name" | ||||
|                     class:border-red-500={isFirstnameValid} | ||||
|                     class:focus:border-red-500={isFirstnameValid} | ||||
|                     class:focus:ring-red-500={isFirstnameValid} | ||||
|                     placeholder={$_('first-name')} | ||||
|                     class:border-red-500={!isFirstnameValid} | ||||
|                     class:focus:border-red-500={!isFirstnameValid} | ||||
|                     class:focus:ring-red-500={!isFirstnameValid} | ||||
|                     bind:value={firstname_input_value} | ||||
|                     bind:this={firstname_input} | ||||
|                     type="text" | ||||
|                     name="firstname" | ||||
|                     class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" /> | ||||
|                   {#if isFirstnameValid} | ||||
|                   {#if !isFirstnameValid} | ||||
|                     <span | ||||
|                       class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"> | ||||
|                       First Name is required | ||||
|                       {$_('first-name-is-required')} | ||||
|                     </span> | ||||
|                   {/if} | ||||
|                 </div> | ||||
|                 <div class="col-span-6"> | ||||
|                   <label | ||||
|                     for="trackname" | ||||
|                     class="block text-sm font-medium text-gray-700">Middle Name</label> | ||||
|                     class="block text-sm font-medium text-gray-700">{$_('middle-name')}</label> | ||||
|                   <input | ||||
|                     autocomplete="off" | ||||
|                     placeholder="Middle Name" | ||||
|                     placeholder={$_('middle-name')} | ||||
|                     bind:value={middlename_input_value} | ||||
|                     bind:this={middlename_input} | ||||
|                     type="text" | ||||
| @@ -177,50 +181,63 @@ | ||||
|                   <input | ||||
|                     autocomplete="off" | ||||
|                     placeholder="Last Name" | ||||
|                     class:border-red-500={isLastnameValid} | ||||
|                     class:focus:border-red-500={isLastnameValid} | ||||
|                     class:focus:ring-red-500={isLastnameValid} | ||||
|                     class:border-red-500={!isLastnameValid} | ||||
|                     class:focus:border-red-500={!isLastnameValid} | ||||
|                     class:focus:ring-red-500={!isLastnameValid} | ||||
|                     bind:value={lastname_input_value} | ||||
|                     bind:this={lastname_input} | ||||
|                     type="text" | ||||
|                     name="lastname" | ||||
|                     class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" /> | ||||
|                   {#if isLastnameValid} | ||||
|                   {#if !isLastnameValid} | ||||
|                     <span | ||||
|                       class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"> | ||||
|                       Last Name is required | ||||
|                       {$_('last-name-is-required')} | ||||
|                     </span> | ||||
|                   {/if} | ||||
|                 </div> | ||||
|                 <div class="col-span-6"> | ||||
|                   <label | ||||
|                     for="password" | ||||
|                     class="block text-sm font-medium text-gray-700">Password</label> | ||||
|                     class="block text-sm font-medium text-gray-700">{$_('password')}</label> | ||||
|                   <input | ||||
|                     autocomplete="off" | ||||
|                     placeholder="Password" | ||||
|                     class:border-red-500={isPasswordValid} | ||||
|                     class:focus:border-red-500={isPasswordValid} | ||||
|                     class:focus:ring-red-500={isPasswordValid} | ||||
|                     placeholder={$_('password')} | ||||
|                     class:border-red-500={!isPasswordValid} | ||||
|                     class:focus:border-red-500={!isPasswordValid} | ||||
|                     class:focus:ring-red-500={!isPasswordValid} | ||||
|                     bind:value={password_input_value} | ||||
|                     bind:this={password_input} | ||||
|                     type="password" | ||||
|                     name="password" | ||||
|                     class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" /> | ||||
|                   {#if isPasswordValid} | ||||
|                   {#if !isPasswordValid} | ||||
|                     <span | ||||
|                       class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"> | ||||
|                       Password is required | ||||
|                       {$_('password-is-required')} | ||||
|                     </span> | ||||
|                   {/if} | ||||
|                 </div> | ||||
|                 <div class="col-span-6"> | ||||
|                   <label | ||||
|                     for="email" | ||||
|                     class="block text-sm font-medium text-gray-700">E-Mail</label> | ||||
|                     for="trackname" | ||||
|                     class="block text-sm font-medium text-gray-700">{$_('username')}</label> | ||||
|                   <input | ||||
|                     autocomplete="off" | ||||
|                     placeholder="E-Mail" | ||||
|                     placeholder={$_('username')} | ||||
|                     bind:value={username_input_value} | ||||
|                     bind:this={username_input} | ||||
|                     type="text" | ||||
|                     name="trackname" | ||||
|                     class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" /> | ||||
|                 </div> | ||||
|                 <div class="col-span-6"> | ||||
|                   <label | ||||
|                     for="email" | ||||
|                     class="block text-sm font-medium text-gray-700">{$_('e-mail-adress')}</label> | ||||
|                   <input | ||||
|                     autocomplete="off" | ||||
|                     placeholder={$_('e-mail-adress')} | ||||
|                     class:border-red-500={!isEmailValid} | ||||
|                     class:focus:border-red-500={!isEmailValid} | ||||
|                     class:focus:ring-red-500={!isEmailValid} | ||||
| @@ -232,7 +249,7 @@ | ||||
|                   {#if !isEmailValid} | ||||
|                     <span | ||||
|                       class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"> | ||||
|                       valid email is required | ||||
|                       {$_('valid-email-is-required')} | ||||
|                     </span> | ||||
|                   {/if} | ||||
|                 </div> | ||||
| @@ -247,7 +264,7 @@ | ||||
|             on:click={submit} | ||||
|             type="button" | ||||
|             class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"> | ||||
|             Create | ||||
|             {$_('create')} | ||||
|           </button> | ||||
|           <button | ||||
|             on:click={() => { | ||||
| @@ -255,7 +272,7 @@ | ||||
|             }} | ||||
|             type="button" | ||||
|             class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm"> | ||||
|             Cancel | ||||
|             {$_('cancel')} | ||||
|           </button> | ||||
|         </div> | ||||
|       </div> | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| <script> | ||||
|   import "filepond/dist/filepond.css"; | ||||
|   import FilePond from "svelte-filepond"; | ||||
|   import { _ } from "svelte-i18n"; | ||||
|   let pond; | ||||
|   // pond.getFiles() will return the active files | ||||
|   // the name to use for the internal file input | ||||
| @@ -11,12 +12,60 @@ | ||||
|   function handleAddFile(err, fileItem) { | ||||
|     // console.log("A file has been added", fileItem); | ||||
|   } | ||||
|   const labelInvalidField = $_("filepond__field-contains-invalid-files"); | ||||
|   const labelFileWaitingForSize = $_("filepond__waiting-for-size"); | ||||
|   const labelFileSizeNotAvailable = $_("filepond__size-not-available"); | ||||
|   const labelFileLoading = $_("filepond__loading"); | ||||
|   const labelFileLoadError = $_("filepond__error-during-load"); | ||||
|   const labelFileProcessing = $_("filepond__uploading"); | ||||
|   const labelFileProcessingComplete = $_("filepond__upload-complete"); | ||||
|   const labelFileProcessingAborted = $_("filepond__upload-cancelled"); | ||||
|   const labelFileProcessingError = $_("filepond__error-during-upload"); | ||||
|   const labelFileProcessingRevertError = $_("filepond__error-during-revert"); | ||||
|   const labelFileRemoveError = $_("filepond__error-during-remove"); | ||||
|   const labelTapToCancel = $_("filepond__tap-to-cancel"); | ||||
|   const labelTapToRetry = $_("filepond__tap-to-retry"); | ||||
|   const labelTapToUndo = $_("filepond__tap-to-undo"); | ||||
|   const labelButtonRemoveItem = $_("filepond__remove"); | ||||
|   const labelButtonAbortItemLoad = $_("filepond__abort"); | ||||
|   const labelButtonRetryItemLoad = $_("filepond__retry"); | ||||
|   const labelButtonAbortItemProcessing = $_("filepond__cancel"); | ||||
|   const labelButtonUndoItemProcessing = $_("filepond__undo"); | ||||
|   const labelButtonRetryItemProcessing = $_("filepond__retry"); | ||||
|   const labelButtonProcessItem = $_("filepond__upload"); | ||||
|   const labelIdle = | ||||
|     $_("drag-and-drop-your-files-or") + | ||||
|     ` <span class="filepond--label-action"> ` + | ||||
|     $_("browse") + | ||||
|     ` </span>`; | ||||
| </script> | ||||
|  | ||||
| <div class="app"> | ||||
|   <FilePond | ||||
|     bind:this={pond} | ||||
|     {name} | ||||
|     {labelFileWaitingForSize} | ||||
|     {labelFileSizeNotAvailable} | ||||
|     {labelFileLoading} | ||||
|     {labelFileLoadError} | ||||
|     {labelFileProcessing} | ||||
|     {labelFileProcessingComplete} | ||||
|     {labelFileProcessingAborted} | ||||
|     {labelFileProcessingError} | ||||
|     {labelFileProcessingRevertError} | ||||
|     {labelFileRemoveError} | ||||
|     {labelTapToCancel} | ||||
|     {labelTapToRetry} | ||||
|     {labelTapToUndo} | ||||
|     {labelButtonRemoveItem} | ||||
|     {labelButtonAbortItemLoad} | ||||
|     {labelButtonRetryItemLoad} | ||||
|     {labelButtonAbortItemProcessing} | ||||
|     {labelButtonUndoItemProcessing} | ||||
|     {labelButtonRetryItemProcessing} | ||||
|     {labelButtonProcessItem} | ||||
|     {labelIdle} | ||||
|     {labelInvalidField} | ||||
|     server="/api" | ||||
|     allowMultiple={false} | ||||
|     credits={false} | ||||
|   | ||||
| @@ -1,15 +1,35 @@ | ||||
| <script> | ||||
|   import { _ } from "svelte-i18n"; | ||||
|   $: releaseinfo = ""; | ||||
|   setTimeout(() => { | ||||
|     releaseinfo = document | ||||
|       .getElementById("buildinfo") | ||||
|       .textContent.replace("RELEASE_INFO-", "") | ||||
|       .replace("-RELEASE_INFO", ""); | ||||
|   }, 1500); | ||||
|   const year = new Date().getFullYear(); | ||||
| </script> | ||||
|  | ||||
| <footer class="container"> | ||||
|   <hr class="mt-2 mb-4 border-b-1 border-gray-300" /> | ||||
| <footer class="p-5 w-full"> | ||||
|   <p class="text-sm text-gray-500 mt-4"> | ||||
|     Lauf für Kaya! Läufersystem - Copyright © 2020 + proudly powered by | ||||
|     Lauf für Kaya! Läufersystem - Copyright © | ||||
|     {year} | ||||
|     + proudly powered by | ||||
|     <a | ||||
|       class="underline" | ||||
|       href="https://odit.services" | ||||
|       rel="noopener,noreferrer" | ||||
|       target="_blank">ODIT.Services</a> | ||||
|   </p> | ||||
|   <p class="text-sm text-gray-500 mt-4"> | ||||
|     <a | ||||
|       class="underline" | ||||
|       target="_blank" | ||||
|       rel="noopener, noreferrer" | ||||
|       href="https://git.odit.services/lfk/frontend/">LfK!Frontend</a>@<a | ||||
|       class="underline" | ||||
|       target="_blank" | ||||
|       rel="noopener, noreferrer" | ||||
|       href="https://git.odit.services/lfk/frontend/src/tag/{releaseinfo}">{releaseinfo}</a> | ||||
|   </p> | ||||
| </footer> | ||||
|   | ||||
| @@ -4,6 +4,7 @@ | ||||
|   import { _ } from "svelte-i18n"; | ||||
|   store.init(); | ||||
|   import { OpenAPI, AuthService } from "@odit/lfk-client-js"; | ||||
|   import Footer from "./Footer.svelte"; | ||||
|   import Toastify from "toastify-js"; | ||||
|   // ------ | ||||
|   let username = "demo"; | ||||
| @@ -17,7 +18,7 @@ | ||||
|         is_blocked_by_autologin = true; | ||||
|         OpenAPI.TOKEN = value.access_token; | ||||
|         const jwtinfo = JSON.parse(atob(OpenAPI.TOKEN.split(".")[1])); | ||||
|         store.login(value.access_token, jwtinfo); | ||||
|         store.login(value, jwtinfo); | ||||
|         Toastify({ | ||||
|           text: $_("welcome_wavinghand"), | ||||
|           duration: 500, | ||||
| @@ -140,3 +141,4 @@ | ||||
|     </div> | ||||
|   </div> | ||||
| </div> | ||||
| <Footer /> | ||||
|   | ||||
| @@ -1,15 +1,93 @@ | ||||
| <script> | ||||
|   import { _ } from "svelte-i18n"; | ||||
|   import { UserService } from "@odit/lfk-client-js"; | ||||
|   import lodashIsEqual from "lodash.isequal"; | ||||
|   import store from "../store"; | ||||
|   import { | ||||
|     UserService, | ||||
|     UserGroupService, | ||||
|     PermissionService, | ||||
|   } from "@odit/lfk-client-js"; | ||||
|   import "gridjs/dist/theme/mermaid.css"; | ||||
|   import { tracks as tracksstore } from "../store.js"; | ||||
|   import Toastify from "toastify-js"; | ||||
|   import PromiseError from "./PromiseError.svelte"; | ||||
|   export let params; | ||||
|   const user_promise = UserService.userControllerGetOne(params.userid); | ||||
|   let data_loaded = false; | ||||
|   $: delete_triggered = false; | ||||
|   $: original_data = {}; | ||||
|   $: editable_userdata = {}; | ||||
|   $: allpermissions = []; | ||||
|   $: allgroups = []; | ||||
|   $: allgroups_ids = []; | ||||
|   $: usergroups_array_objects = []; | ||||
|   $: usergroups_array = []; | ||||
|   let usergroups_array_original = []; | ||||
|   user_promise.then((data) => { | ||||
|     console.log(data); | ||||
|     tracksstore.set(data); | ||||
|     data_loaded = true; | ||||
|     original_data = Object.assign(original_data, data); | ||||
|     editable_userdata = data; | ||||
|     data.groups.forEach((g) => { | ||||
|       usergroups_array=usergroups_array.concat([g.id]); | ||||
|     }); | ||||
|     usergroups_array_original = usergroups_array; | ||||
|     allgroups.forEach((g) => { | ||||
|       allgroups_ids.push(g.id); | ||||
|     }); | ||||
|   }); | ||||
|   UserGroupService.userGroupControllerGetAll().then((data) => { | ||||
|     allgroups = data; | ||||
|   }); | ||||
|   const permissions_promise = PermissionService.permissionControllerGetAll(); | ||||
|   permissions_promise.then((data) => { | ||||
|     data.forEach((p) => { | ||||
|       allpermissions=allpermissions.concat([p.target + ":" + p.action]) | ||||
|     }); | ||||
|   }); | ||||
|   $: changes_performed = !lodashIsEqual(original_data, editable_userdata); | ||||
|   $: groups_changed = JSON.stringify(usergroups_array)===JSON.stringify(usergroups_array_original); | ||||
|   $: save_enabled = changes_performed||!groups_changed; | ||||
|   function submit() { | ||||
|     if ( | ||||
|       !lodashIsEqual(original_data.permissions, editable_userdata.permissions) | ||||
|     ) { | ||||
|       // TODO: add+delete permissions | ||||
|     } | ||||
|     if (data_loaded === true && save_enabled) { | ||||
|       let tmp=[]; | ||||
|       usergroups_array.forEach(g => { | ||||
|         const group=allgroups.find(obj=>obj.id===g); | ||||
|         tmp.push(group); | ||||
|       }); | ||||
|       editable_userdata.groups=tmp; | ||||
|       Toastify({ | ||||
|         text: $_("updating-user"), | ||||
|         duration: 2500, | ||||
|       }).showToast(); | ||||
|       UserService.userControllerPut(original_data.id, editable_userdata) | ||||
|         .then((resp) => { | ||||
|           Object.assign(original_data, editable_userdata); | ||||
|           original_data = editable_userdata; | ||||
|           Object.assign(original_data, editable_userdata); | ||||
|           // | ||||
|           Toastify({ | ||||
|             text: $_("user-updated"), | ||||
|             duration: 2500, | ||||
|             backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)", | ||||
|           }).showToast(); | ||||
|         }) | ||||
|         .catch((err) => { | ||||
|         }); | ||||
|     } else { | ||||
|     } | ||||
|   } | ||||
|   function deleteUser() { | ||||
|     UserService.userControllerRemove(original_data.id, true) | ||||
|       .then((resp) => { | ||||
|         location.replace("./"); | ||||
|       }) | ||||
|       .catch((err) => { | ||||
|       }); | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| {#await user_promise} | ||||
| @@ -50,34 +128,54 @@ | ||||
|                 <polyline points="12 5 19 12 12 19" /></svg> | ||||
|             </li> | ||||
|             <li class="flex items-center"> | ||||
|               <span class="mr-2">{user.firstname} | ||||
|                 {user.middlename || ''} | ||||
|                 {user.lastname}</span> | ||||
|               <span class="mr-2">{original_data.firstname} | ||||
|                 {original_data.middlename || ''} | ||||
|                 {original_data.lastname}</span> | ||||
|             </li> | ||||
|           </ol> | ||||
|         </nav> | ||||
|       </div> | ||||
|     </div> | ||||
|     <span | ||||
|       class="mb-4 text-3xl font-extrabold leading-tight">{user.firstname} | ||||
|       {user.middlename || ''} | ||||
|       {user.lastname} | ||||
|     <div class="mb-8 text-3xl font-extrabold leading-tight"> | ||||
|       {original_data.firstname} | ||||
|       {original_data.middlename || ''} | ||||
|       {original_data.lastname} | ||||
|       <span data-id="user_actions_${editable_userdata.id}"> | ||||
|         {#if store.state.jwtinfo.userdetails.permissions.includes('USER:DELETE')} | ||||
|           {#if delete_triggered} | ||||
|             <button | ||||
|               on:click={deleteUser} | ||||
|               class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm">{$_('confirm-delete')}</button> | ||||
|             <button | ||||
|               on:click={() => { | ||||
|                 delete_triggered = !delete_triggered; | ||||
|               }} | ||||
|               class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-400 text-base font-medium text-white sm:w-auto sm:text-sm">{$_('cancel')}</button> | ||||
|           {/if} | ||||
|           {#if !delete_triggered} | ||||
|             <button | ||||
|               on:click={() => { | ||||
|                 delete_triggered = true; | ||||
|               }} | ||||
|               type="button" | ||||
|         class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm">Delete | ||||
|         User</button></span> | ||||
|     <!--  --> | ||||
|               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"> | ||||
|       <img | ||||
|         alt={$_('profile-picture')} | ||||
|         class="inline-block h-20 w-20 rounded-full overflow-hidden bg-gray-100" | ||||
|         src={user.profilePic} /> | ||||
|       <!-- <span | ||||
|         class="inline-block h-12 w-12 rounded-full overflow-hidden bg-gray-100"><svg | ||||
|           class="h-full w-full text-gray-300" | ||||
|           fill="currentColor" | ||||
|           viewBox="0 0 24 24"><path | ||||
|             d="M24 20.993V24H0v-2.996A14.977 14.977 0 0112.004 15c4.904 0 9.26 2.354 11.996 5.993zM16.002 8.999a4 4 0 11-8 0 4 4 0 018 0z" /></svg></span> --> | ||||
|         src={editable_userdata.profilePic} /> | ||||
|       <button | ||||
|         type="button" | ||||
|         class="ml-5 bg-white py-2 px-3 border border-gray-300 rounded-md shadow-sm text-sm leading-4 font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">Change</button> | ||||
| @@ -86,8 +184,13 @@ | ||||
|     <div class="mt-3 text-sm w-full"> | ||||
|       <input | ||||
|         id="enabled" | ||||
|         on:change={() => { | ||||
|           editable_userdata.enabled = !editable_userdata.enabled; | ||||
|           // TODO: this reactive set does not work? | ||||
|         }} | ||||
|         name="enabled" | ||||
|         type="checkbox" | ||||
|         checked={editable_userdata.enabled} | ||||
|         class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded" /> | ||||
|       <label | ||||
|         for="enabled" | ||||
| @@ -95,34 +198,138 @@ | ||||
|       <p class="text-gray-500">set the user active/ inactive</p> | ||||
|     </div> | ||||
|     <div class="text-sm w-full"> | ||||
|       <label for="firstname" class="font-medium text-gray-700">First name</label> | ||||
|       <label | ||||
|         for="firstname" | ||||
|         class="font-medium text-gray-700">{$_('first-name')}</label> | ||||
|       <input | ||||
|         autocomplete="off" | ||||
|         placeholder="First name" | ||||
|         placeholder={$_('first-name')} | ||||
|         type="text" | ||||
|         bind:value={editable_userdata.firstname} | ||||
|         name="firstname" | ||||
|         class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 dark:bg-gray-900 dark:text-gray-100 rounded-md p-2" /> | ||||
|     </div> | ||||
|     <div class="text-sm w-full"> | ||||
|       <label for="middlename" class="font-medium text-gray-700">Middle name</label> | ||||
|       <label | ||||
|         for="middlename" | ||||
|         class="font-medium text-gray-700">{$_('middle-name')}</label> | ||||
|       <input | ||||
|         autocomplete="off" | ||||
|         placeholder="Middle name" | ||||
|         placeholder={$_('middle-name')} | ||||
|         type="text" | ||||
|         bind:value={editable_userdata.middlename} | ||||
|         name="middlename" | ||||
|         class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 dark:bg-gray-900 dark:text-gray-100 rounded-md p-2" /> | ||||
|     </div> | ||||
|     <div class="text-sm w-full"> | ||||
|       <label for="lastname" class="font-medium text-gray-700">Last name</label> | ||||
|       <label | ||||
|         for="lastname" | ||||
|         class="font-medium text-gray-700">{$_('last-name')}</label> | ||||
|       <input | ||||
|         autocomplete="off" | ||||
|         placeholder="Last name" | ||||
|         placeholder={$_('last-name')} | ||||
|         type="text" | ||||
|         bind:value={editable_userdata.lastname} | ||||
|         name="lastname" | ||||
|         class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 dark:bg-gray-900 dark:text-gray-100 rounded-md p-2" /> | ||||
|     </div> | ||||
|     <div class="text-sm w-full"> | ||||
|       <label | ||||
|         for="email" | ||||
|         class="font-medium text-gray-700">{$_('e-mail-adress')}</label> | ||||
|       <input | ||||
|         autocomplete="off" | ||||
|         placeholder={$_('e-mail-adress')} | ||||
|         type="email" | ||||
|         bind:value={editable_userdata.email} | ||||
|         name="email" | ||||
|         class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 dark:bg-gray-900 dark:text-gray-100 rounded-md p-2" /> | ||||
|     </div> | ||||
|     <div class="text-sm w-full"> | ||||
|       <label | ||||
|         for="username" | ||||
|         class="font-medium text-gray-700">{$_('username')}</label> | ||||
|       <input | ||||
|         autocomplete="off" | ||||
|         placeholder={$_('username')} | ||||
|         type="text" | ||||
|         bind:value={editable_userdata.username} | ||||
|         name="username" | ||||
|         class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 dark:bg-gray-900 dark:text-gray-100 rounded-md p-2" /> | ||||
|     </div> | ||||
|     <div class="text-sm w-full"> | ||||
|       <span class="font-medium">{$_('groups')}</span> | ||||
|       <!-- svelte-ignore a11y-no-onchange --> | ||||
|       <select | ||||
|         bind:value={usergroups_array} | ||||
|         class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 dark:bg-gray-900 dark:text-gray-100 rounded-md p-2" | ||||
|         multiple> | ||||
|         {#each allgroups as g} | ||||
|           {#if usergroups_array.includes(g.id)} | ||||
|             <option selected value={g.id}>{g.name}</option> | ||||
|           {:else} | ||||
|             <option value={g.id}>{g.name}</option> | ||||
|           {/if} | ||||
|         {/each} | ||||
|       </select> | ||||
|     </div> | ||||
|     <div class="text-sm w-full"> | ||||
|       <span class="font-medium">Permissions</span> | ||||
|       <div class="border-4 border-dashed rounded mb-4 p-5 text-lg text-center"> | ||||
|         <!--  --> | ||||
|         <div class="flex flex-wrap -mx-1 overflow-hidden"> | ||||
|           <div class="my-1 px-1 w-full overflow-hidden sm:w-1/2"> | ||||
|             verfügbare | ||||
|           </div> | ||||
|           <div class="my-1 px-1 w-full overflow-hidden sm:w-1/2">erteilte</div> | ||||
|         </div> | ||||
|         <!--  --> | ||||
|         <div class="flex flex-wrap -mx-1 overflow-hidden"> | ||||
|           {#if allpermissions.length > 0} | ||||
|             <div class="my-1 px-1 w-full overflow-hidden sm:w-1/2"> | ||||
|               <div | ||||
|                 class="border-4 border-dashed rounded mb-4 p-5 text-lg text-center"> | ||||
|                 {#each allpermissions as p} | ||||
|                   {#if !editable_userdata.permissions.includes(p)} | ||||
|                     <p | ||||
|                       class="block w-full mt-1 text-sm dark:border-gray-600 dark:bg-gray-700 bg-gray-200 p-2 focus:border-purple-400 focus:outline-none focus:shadow-outline-purple dark:text-gray-300 dark:focus:shadow-outline-gray form-input"> | ||||
|                       {p} | ||||
|                       <button | ||||
|                         on:click={() => { | ||||
|                           editable_userdata.permissions.push(p); | ||||
|                           editable_userdata.permissions = editable_userdata.permissions; | ||||
|                         }} | ||||
|                         type="button" | ||||
|                         class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-green-200 text-base font-medium text-black hover:bg-green-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 sm:ml-3 sm:w-auto sm:text-sm">+</button> | ||||
|                     </p> | ||||
|                   {/if} | ||||
|                 {/each} | ||||
|               </div> | ||||
|             </div> | ||||
|             <div class="my-1 px-1 w-full overflow-hidden sm:w-1/2"> | ||||
|               <div | ||||
|                 class="border-4 border-dashed rounded mb-4 p-5 text-lg text-center"> | ||||
|                 {#each allpermissions as p} | ||||
|                   {#if editable_userdata.permissions.includes(p)} | ||||
|                     <p | ||||
|                       class="block w-full mt-1 text-sm dark:border-gray-600 dark:bg-gray-700 bg-gray-200 p-2 focus:border-purple-400 focus:outline-none focus:shadow-outline-purple dark:text-gray-300 dark:focus:shadow-outline-gray form-input"> | ||||
|                       {p} | ||||
|                       <button | ||||
|                         on:click={() => { | ||||
|                           editable_userdata.permissions = editable_userdata.permissions.filter((obj) => obj !== p); | ||||
|                         }} | ||||
|                         type="button" | ||||
|                         class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-300 text-base font-medium text-black hover:bg-red-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 sm:ml-3 sm:w-auto sm:text-sm">-</button> | ||||
|                     </p> | ||||
|                   {/if} | ||||
|                 {/each} | ||||
|               </div> | ||||
|             </div> | ||||
|           {/if} | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|   </section> | ||||
| {:catch error} | ||||
|   <!-- promise was rejected --> | ||||
|   <PromiseError {error} /> | ||||
| {/await} | ||||
|   | ||||
| @@ -1,25 +1,31 @@ | ||||
| <script> | ||||
|   import { _ } from "svelte-i18n"; | ||||
|   import store from "../store"; | ||||
|   import AddUserModal from "./AddUserModal.svelte"; | ||||
|   export let modal_open = false; | ||||
|   import UsersOverview from "./UsersOverview.svelte"; | ||||
|   console.log(store.state.jwtinfo.userdetails.permissions); | ||||
|   let current_users=[]; | ||||
| </script> | ||||
|  | ||||
| <section class="container p-5"> | ||||
|   <span class="mb-1 text-3xl font-extrabold leading-tight"> | ||||
|     Users | ||||
|     {$_('users')} | ||||
|     {#if store.state.jwtinfo.userdetails.permissions.includes('USER:CREATE')} | ||||
|       <button | ||||
|         on:click={() => { | ||||
|           modal_open = true; | ||||
|         }} | ||||
|         type="button" | ||||
|         class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"> | ||||
|       Create User | ||||
|         {$_('create-user')} | ||||
|       </button> | ||||
|     {/if} | ||||
|   </span> | ||||
|   <p class="mb-8 text-lg text-gray-500"> | ||||
|     manage admin users | ||||
|   </p> | ||||
|   <UsersOverview /> | ||||
|   <p class="mb-8 text-lg text-gray-500">{$_('manage-admin-users')}</p> | ||||
|   <UsersOverview bind:current_users /> | ||||
| </section> | ||||
| <AddUserModal bind:modal_open /> | ||||
|  | ||||
| {#if store.state.jwtinfo.userdetails.permissions.includes('USER:CREATE')} | ||||
|   <AddUserModal bind:current_users bind:modal_open /> | ||||
| {/if} | ||||
|   | ||||
| @@ -1,39 +1,58 @@ | ||||
| <script> | ||||
|   import { _, json } from "svelte-i18n"; | ||||
|   import { _ } from "svelte-i18n"; | ||||
|   import Toastify from "toastify-js"; | ||||
|   import TracksEmptyState from "./TracksEmptyState.svelte"; | ||||
|   import { TrackService, UserService } from "@odit/lfk-client-js"; | ||||
|   import { UserService } from "@odit/lfk-client-js"; | ||||
|   const users_promise = UserService.userControllerGetAll(); | ||||
|   import { getlang } from "./datatable_i18n"; | ||||
|   import { Grid, html } from "gridjs"; | ||||
|   import "gridjs/dist/theme/mermaid.css"; | ||||
|   import { tracks as tracksstore } from "../store.js"; | ||||
|   import { users as usersstore } from "../store.js"; | ||||
|   import store from "../store"; | ||||
|   import UsersEmptyState from "./UsersEmptyState.svelte"; | ||||
|   $: searchvalue = ""; | ||||
|   $: active_deletes = []; | ||||
|   export let current_users=[]; | ||||
|   $: userscache = []; | ||||
|   $: blocked = []; | ||||
|   let table; | ||||
|   let datatable; | ||||
|   let datatable_inited = false; | ||||
|   tracksstore.subscribe((val) => { | ||||
|   $: advanced_search = false; | ||||
|   usersstore.subscribe((val) => { | ||||
|     userscache = val; | ||||
|     current_users=val; | ||||
|   }); | ||||
|   users_promise.then((data) => { | ||||
|     console.log(data); | ||||
|     tracksstore.set(data); | ||||
|     usersstore.set(data); | ||||
|   }); | ||||
| </script> | ||||
|  | ||||
| {#await users_promise} | ||||
| {#if store.state.jwtinfo.userdetails.permissions.includes('USER:GET')} | ||||
|   {#await users_promise} | ||||
|     <div | ||||
|       class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2" | ||||
|       role="alert"> | ||||
|       <p class="font-bold">users are being loaded...</p> | ||||
|       <p class="text-sm">{$_('this-might-take-a-moment')}</p> | ||||
|     </div> | ||||
| {:then users} | ||||
|   {#if userscache.length === 0} | ||||
|   {:then} | ||||
|     {#if current_users.length === 0} | ||||
|       <UsersEmptyState /> | ||||
|     {:else} | ||||
|       {#if advanced_search} | ||||
|         advanced search | ||||
|       {:else} | ||||
|         <input | ||||
|           type="search" | ||||
|           bind:value={searchvalue} | ||||
|           placeholder={$_('datatable.search')} | ||||
|           aria-label={$_('datatable.search')} | ||||
|           class="gridjs-input gridjs-search-input mb-4" /> | ||||
|       {/if} | ||||
|       <button | ||||
|         on:click={() => { | ||||
|           advanced_search = !advanced_search; | ||||
|         }} | ||||
|         type="button" | ||||
|         class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-gray-600 text-base font-medium text-white hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 sm:ml-3 sm:w-auto sm:text-sm"> | ||||
|         {#if advanced_search} | ||||
|           toggle simple search | ||||
|         {:else}toggle advanced search{/if} | ||||
|       </button> | ||||
|       <div | ||||
|         class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll"> | ||||
|         <table class="divide-y divide-gray-200 w-full"> | ||||
| @@ -44,11 +63,6 @@ | ||||
|                 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"> | ||||
| @@ -65,8 +79,12 @@ | ||||
|             </tr> | ||||
|           </thead> | ||||
|           <tbody class="divide-y divide-gray-200"> | ||||
|           {#each users as u} | ||||
|             <tr> | ||||
|             {#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} | ||||
| @@ -90,12 +108,6 @@ | ||||
|                       </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 | ||||
| @@ -112,106 +124,59 @@ | ||||
|                         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> | ||||
|                 <span | ||||
|                       {#if store.state.jwtinfo.userdetails.permissions.includes('USER:DELETE')} | ||||
|                         <button | ||||
|                           on:click={() => { | ||||
|                             active_deletes[u.id] = true; | ||||
|                           }} | ||||
|                           tabindex="0" | ||||
|                   href="#" | ||||
|                   class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">Delete</span> | ||||
|                           class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">Delete</button> | ||||
|                       {/if} | ||||
|                     </td> | ||||
|                   {/if} | ||||
|                 </tr> | ||||
|               {/if} | ||||
|             {/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> | ||||
|     {/if} | ||||
| {:catch error} | ||||
|   {: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} | ||||
|   {/await} | ||||
| {/if} | ||||
|   | ||||
| @@ -6,12 +6,18 @@ | ||||
|     "add-your-first-track": "Add your first track", | ||||
|     "application_name": "Lauf für Kaya! - Admin", | ||||
|     "author": "Author", | ||||
|     "browse": "Browse", | ||||
|     "by": "by", | ||||
|     "cancel": "Cancel", | ||||
|     "cannot-reset-your-password-directly": "Bummer. We unfortunately cannot reset your password directly. Please send us a mail and confirm your identity", | ||||
|     "changelog": "Changelog", | ||||
|     "close": "Close", | ||||
|     "confirm-delete": "Confirm Delete", | ||||
|     "count_organizations": "# Organizations", | ||||
|     "count_teams": "# Teams", | ||||
|     "create": "Create", | ||||
|     "create-a-new-track": "Create a new Track", | ||||
|     "create-user": "Create User", | ||||
|     "credits": "Credits", | ||||
|     "dashboard-greeting": "hello there", | ||||
|     "dashboard-title": "Dashboard", | ||||
| @@ -30,33 +36,64 @@ | ||||
|         "no_matching_records_found": "No matching records found", | ||||
|         "an_error_happened_while_fetching_the_data": "An error happened while fetching the data" | ||||
|     }, | ||||
|     "delete-user": "Delete User", | ||||
|     "dependency_name": "Name", | ||||
|     "dont-have-your-email-connected": "Don't have your email connected?", | ||||
|     "dont-panic-were-resetting-it": "Don't panic, we're resetting it ✌", | ||||
|     "drag-and-drop-your-files-or": "Drag & Drop your files or", | ||||
|     "e-mail-adress": "E-Mail Adress", | ||||
|     "email_address_or_username": "Email / username", | ||||
|     "error_on_login": "Error on login", | ||||
|     "faq": "FAQ", | ||||
|     "filepond__abort": "Abort", | ||||
|     "filepond__cancel": "Cancel", | ||||
|     "filepond__error-during-load": "Error during load", | ||||
|     "filepond__error-during-remove": "Error during remove", | ||||
|     "filepond__error-during-revert": "Error during revert", | ||||
|     "filepond__error-during-upload": "Error during upload", | ||||
|     "filepond__field-contains-invalid-files": "Field contains invalid files", | ||||
|     "filepond__loading": "Loading", | ||||
|     "filepond__remove": "Remove", | ||||
|     "filepond__retry": "Retry", | ||||
|     "filepond__size-not-available": "Size not available", | ||||
|     "filepond__tap-to-cancel": "tap to cancel", | ||||
|     "filepond__tap-to-retry": "tap to retry", | ||||
|     "filepond__tap-to-undo": "tap to undo", | ||||
|     "filepond__undo": "Undo", | ||||
|     "filepond__upload": "Upload", | ||||
|     "filepond__upload-cancelled": "Upload cancelled", | ||||
|     "filepond__upload-complete": "Upload complete", | ||||
|     "filepond__uploading": "Uploading", | ||||
|     "filepond__waiting-for-size": "Waiting for size", | ||||
|     "first-name": "First name", | ||||
|     "first-name-is-required": "First Name is required", | ||||
|     "forgot_password?": "Forgot your password?", | ||||
|     "general-stats": "General Stats", | ||||
|     "general_promise_error": "😢 Error", | ||||
|     "goback": "Go Home", | ||||
|     "groups": "Groups", | ||||
|     "hallo": "hello", | ||||
|     "installed-version": "Installed version", | ||||
|     "invalid-mail-reset": "the provided email is invalid", | ||||
|     "last-name": "Last name", | ||||
|     "last-name-is-required": "Last Name is required", | ||||
|     "lfk-is-os": "The \"Lauf für Kaya!\" Frontend is (like all other projects for the \"LfK!\" Also) an open source project.", | ||||
|     "license": "License", | ||||
|     "licenses-are-being-loaded": "Licenses are being loaded...", | ||||
|     "log_in": "Log in", | ||||
|     "log_in_to_your_account": "Log in to your account", | ||||
|     "login_is_checked": "Login is being checked...", | ||||
|     "logout": "Logout", | ||||
|     "mail-validation-in-progress": "mail validation in progress...", | ||||
|     "manage-admin-users": "manage admin users", | ||||
|     "middle-name": "Middle name", | ||||
|     "minimum-lap-time-in-s": "minimum lap time in s", | ||||
|     "no-license-text-could-be-found": "No license text could be found 😢", | ||||
|     "no-tracks-added-yet": "there are no tracks added yet.", | ||||
|     "orgs": "Orgs", | ||||
|     "oss_credit_description": "We use a lot of open source software on these projects, and would like to thank the following projects and contributors who help make open source great!", | ||||
|     "password": "Password", | ||||
|     "password-is-required": "Password is required", | ||||
|     "please-provide-the-required-information-to-add-a-new-track": "Please provide the required information to add a new track.", | ||||
|     "profile-picture": "Profile Picture", | ||||
|     "read-license": "Read License", | ||||
| @@ -64,6 +101,7 @@ | ||||
|     "repo_link": "Link", | ||||
|     "reset-my-password": "Reset my password", | ||||
|     "runners": "Runners", | ||||
|     "save-changes": "Save Changes", | ||||
|     "send-a-mail-to-lfk-odit-services": "send a mail to lfk@odit.services", | ||||
|     "settings": "Settings", | ||||
|     "signout": "Sign out", | ||||
| @@ -79,7 +117,11 @@ | ||||
|     "track-length-in-m": "Track Length in m", | ||||
|     "track-name": "Track name", | ||||
|     "tracks": "Tracks", | ||||
|     "updating-user": "updating user...", | ||||
|     "user-updated": "User updated", | ||||
|     "username": "Username", | ||||
|     "users": "Users", | ||||
|     "valid-email-is-required": "valid email is required", | ||||
|     "welcome_wavinghand": "Welcome 👋", | ||||
|     "your_profile": "Your Profile" | ||||
| } | ||||
							
								
								
									
										31
									
								
								src/store.js
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								src/store.js
									
									
									
									
									
								
							| @@ -1,12 +1,16 @@ | ||||
| import { writable } from 'svelte/store'; | ||||
| import { OpenAPI, AuthService } from '@odit/lfk-client-js'; | ||||
| import localForage from 'localforage'; | ||||
|  | ||||
| export let users = writable([]); | ||||
| export let tracks = writable([]); | ||||
| const store = () => { | ||||
| 	const state = { | ||||
| 		auth: undefined, | ||||
| 		access_token: undefined, | ||||
| 		jwtinfo: undefined, | ||||
| 		isLoggedIn: false | ||||
| 		isLoggedIn: false, | ||||
| 		refreshInterval: undefined | ||||
| 	}; | ||||
|  | ||||
| 	const { subscribe, set, update } = writable(state); | ||||
| @@ -18,17 +22,38 @@ const store = () => { | ||||
| 				return state; | ||||
| 			}); | ||||
| 		}, | ||||
| 		login(access_token, jwtinfo) { | ||||
| 		refreshAuth() { | ||||
| 			console.log('refreshing auth'); | ||||
| 			AuthService.authControllerRefresh({ token: state.auth.refresh_token }).then((auth) => { | ||||
| 				console.log('got new auth'); | ||||
| 				OpenAPI.TOKEN = auth.access_token; | ||||
| 				const jwtinfo = JSON.parse(atob(auth.access_token.split('.')[1])); | ||||
| 				state.jwtinfo = jwtinfo; | ||||
| 				localForage.setItem('logindata', auth); | ||||
| 			}); | ||||
| 		}, | ||||
| 		login(auth, jwtinfo) { | ||||
| 			update((state) => { | ||||
| 				state.access_token = access_token; | ||||
| 				state.auth = auth; | ||||
| 				state.access_token = auth.access_token; | ||||
| 				state.jwtinfo = jwtinfo; | ||||
| 				state.isLoggedIn = true; | ||||
| 				// | ||||
| 				state.refreshInterval = setInterval(() => { | ||||
| 					this.refreshAuth(); | ||||
| 					// 2min | ||||
| 				}, 2 * 60000); | ||||
| 				// | ||||
| 				return state; | ||||
| 			}); | ||||
| 		}, | ||||
| 		logout() { | ||||
| 			update((state) => { | ||||
| 				state.isLoggedIn = false; | ||||
| 				// | ||||
| 				clearInterval(state.refreshInterval); | ||||
| 				state.refreshInterval = undefined; | ||||
| 				// | ||||
| 				return state; | ||||
| 			}); | ||||
| 		} | ||||
|   | ||||
| @@ -2,7 +2,7 @@ module.exports = { | ||||
| 	purge: { | ||||
| 		content: [ './src/**/*.svelte' ] | ||||
| 	}, | ||||
| 	darkMode: 'media', | ||||
| 	// darkMode: 'media', | ||||
| 	variants: {}, | ||||
| 	plugins: [], | ||||
| 	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