Compare commits
	
		
			59 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 04494d2a2a | |||
| e2d6fbb513 | |||
| 477c650f3f | |||
| fc15c68cba | |||
| 32b5f5420b | |||
| ee87f82799 | |||
| 7c08f522aa | |||
| e211554579 | |||
| 7ba890dfd7 | |||
| 68b4309164 | |||
| d803f3d490 | |||
| 5468766d87 | |||
| e967d8d20c | |||
| ad4db882f0 | |||
| 84aa846b87 | |||
| 3532968b33 | |||
| 6bb49db4ee | |||
| 38fb111f7a | |||
| a50447f457 | |||
| b1a2044631 | |||
| c883920caa | |||
| 21453ef272 | |||
| 10182433f8 | |||
| b338f33a63 | |||
| cb82200481 | |||
| 9abf74d6d2 | |||
| 50e81a6cb5 | |||
| 8fae1fb6b3 | |||
| 372fa110ec | |||
| 35bec9fe58 | |||
| 93d67bdba9 | |||
| a5e72a18e3 | |||
| 91d2f46b93 | |||
| c60bae4533 | |||
| 43ac878d44 | |||
| ceabd06a43 | |||
| 9bfc0c5338 | |||
| fb8206ff13 | |||
| dceb0ef461 | |||
| 88bc1982ca | |||
| e741a9d7e7 | |||
| 65f1d22205 | |||
| d867c08aba | |||
| 6193eff38e | |||
| f1929e7cf9 | |||
| 373484c242 | |||
| f77460bb0c | |||
| 574e0dcb05 | |||
| 7b19a0aa08 | |||
| 08642d7618 | |||
| c3e9c27cd3 | |||
| 29a2854671 | |||
| 8e6786e722 | |||
| 6ad40564e3 | |||
| 776973bfe9 | |||
| 6025e43baa | |||
| d9a47f882c | |||
| 4235758a6d | |||
| 59fe2dfabb | 
| @@ -1,2 +1,4 @@ | |||||||
| public/env.sample.js | public/env.sample.js | ||||||
| .pnpm-store | .pnpm-store | ||||||
|  | .yarn | ||||||
|  | .pnp.* | ||||||
							
								
								
									
										101
									
								
								.drone.yml
									
									
									
									
									
								
							
							
						
						
									
										101
									
								
								.drone.yml
									
									
									
									
									
								
							| @@ -1,101 +0,0 @@ | |||||||
| --- |  | ||||||
| kind: secret |  | ||||||
| name: docker_username |  | ||||||
| get: |  | ||||||
|   path: odit-registry-builder |  | ||||||
|   name: username |  | ||||||
|  |  | ||||||
| --- |  | ||||||
| kind: secret |  | ||||||
| name: docker_password |  | ||||||
| get: |  | ||||||
|   path: odit-registry-builder |  | ||||||
|   name: password |  | ||||||
|  |  | ||||||
| --- |  | ||||||
| kind: secret |  | ||||||
| name: git_ssh |  | ||||||
| get: |  | ||||||
|   path: odit-git-bot |  | ||||||
|   name: sshkey |  | ||||||
|  |  | ||||||
| --- |  | ||||||
| kind: secret |  | ||||||
| name: npm_url |  | ||||||
| get: |  | ||||||
|   path: odit-npm-cache |  | ||||||
|   name: url |  | ||||||
|  |  | ||||||
| --- |  | ||||||
| kind: pipeline |  | ||||||
| type: kubernetes |  | ||||||
| name: build:dev |  | ||||||
|  |  | ||||||
| steps: |  | ||||||
|   - name: run full license export |  | ||||||
|     depends_on: ["clone"] |  | ||||||
|     image: registry.odit.services/hub/library/node:19.7.0-alpine3.16 |  | ||||||
|     commands: |  | ||||||
|       - npm config set registry $NPM_REGISTRY_URL && npm i -g pnpm@8 |  | ||||||
|       - pnpm i |  | ||||||
|       - pnpm licenses:export |  | ||||||
|     environment: |  | ||||||
|       NPM_REGISTRY_URL: |  | ||||||
|         from_secret: npm_url |  | ||||||
|   - name: push new licenses file to repo |  | ||||||
|     depends_on: ["run full license export"] |  | ||||||
|     image: appleboy/drone-git-push |  | ||||||
|     settings: |  | ||||||
|       branch: dev |  | ||||||
|       commit: true |  | ||||||
|       commit_message: new license file version [CI SKIP] |  | ||||||
|       author_email: bot@odit.services |  | ||||||
|       remote: git@git.odit.services:lfk/frontend.git |  | ||||||
|       ssh_key: |  | ||||||
|         from_secret: git_ssh |  | ||||||
|   - name: build dev |  | ||||||
|     depends_on: ["clone"] |  | ||||||
|     image: registry.odit.services/library/drone-kaniko |  | ||||||
|     settings: |  | ||||||
|       username: |  | ||||||
|         from_secret: docker_username |  | ||||||
|       password: |  | ||||||
|         from_secret: docker_password |  | ||||||
|       build_args: |  | ||||||
|         - NPM_REGISTRY_URL: |  | ||||||
|           from_secret: npm_url |  | ||||||
|       repo: lfk/frontend |  | ||||||
|       tags: |  | ||||||
|         - dev |  | ||||||
|       cache: true |  | ||||||
|       registry: registry.odit.services |  | ||||||
| trigger: |  | ||||||
|   branch: |  | ||||||
|     - dev |  | ||||||
|   event: |  | ||||||
|     - push |  | ||||||
|  |  | ||||||
| --- |  | ||||||
| kind: pipeline |  | ||||||
| type: kubernetes |  | ||||||
| name: build:tags |  | ||||||
| steps: |  | ||||||
|   - name: build $DRONE_TAG |  | ||||||
|     depends_on: ["clone"] |  | ||||||
|     image: registry.odit.services/library/drone-kaniko |  | ||||||
|     settings: |  | ||||||
|       username: |  | ||||||
|         from_secret: docker_username |  | ||||||
|       password: |  | ||||||
|         from_secret: docker_password |  | ||||||
|       build_args: |  | ||||||
|         - NPM_REGISTRY_URL: |  | ||||||
|           from_secret: npm_url |  | ||||||
|       repo: lfk/frontend |  | ||||||
|       tags: |  | ||||||
|         - "${DRONE_TAG}" |  | ||||||
|       cache: true |  | ||||||
|       registry: registry.odit.services |  | ||||||
| trigger: |  | ||||||
|   event: |  | ||||||
|     - tag |  | ||||||
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -3,4 +3,6 @@ node_modules | |||||||
| public/env.js | public/env.js | ||||||
| public/index.html | public/index.html | ||||||
| /dist | /dist | ||||||
| .pnpm-store | .pnpm-store | ||||||
|  | .yarn | ||||||
|  | .pnp.* | ||||||
							
								
								
									
										26
									
								
								.woodpecker/build.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								.woodpecker/build.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | steps: | ||||||
|  |   - name: run full license export | ||||||
|  |     image: registry.odit.services/hub/library/node:19.7.0-alpine3.16 | ||||||
|  |     commands: | ||||||
|  |       - npm i -g pnpm@8 | ||||||
|  |       - pnpm i | ||||||
|  |       - pnpm licenses:export | ||||||
|  |   - name: build dev | ||||||
|  |     image: woodpeckerci/plugin-docker-buildx | ||||||
|  |     settings: | ||||||
|  |       repo: registry.odit.services/lfk/frontend | ||||||
|  |       tags: | ||||||
|  |         - dev | ||||||
|  |         - latest | ||||||
|  |       registry: registry.odit.services | ||||||
|  |       platforms: linux/amd64,linux/arm64 | ||||||
|  |       cache_from: registry.odit.services/lfk/frontend:dev | ||||||
|  |       username: | ||||||
|  |         from_secret: odit-registry-builder-username | ||||||
|  |       password: | ||||||
|  |         from_secret: odit-registry-builder-password | ||||||
|  | when: | ||||||
|  |   event: | ||||||
|  |     - push | ||||||
|  |   branch: | ||||||
|  |     - dev | ||||||
							
								
								
									
										17
									
								
								.woodpecker/release.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								.woodpecker/release.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | |||||||
|  | steps: | ||||||
|  |   - name: build tag | ||||||
|  |     image: woodpeckerci/plugin-docker-buildx | ||||||
|  |     settings: | ||||||
|  |       repo: registry.odit.services/lfk/frontend | ||||||
|  |       tags: | ||||||
|  |         - "${CI_COMMIT_TAG}" | ||||||
|  |       registry: registry.odit.services | ||||||
|  |       platforms: linux/amd64,linux/arm64 | ||||||
|  |       cache_from: registry.odit.services/lfk/frontend:latest | ||||||
|  |       username: | ||||||
|  |         from_secret: odit-registry-builder-username | ||||||
|  |       password: | ||||||
|  |         from_secret: odit-registry-builder-password | ||||||
|  | when: | ||||||
|  |   event: | ||||||
|  |     - tag | ||||||
							
								
								
									
										105
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										105
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @@ -2,10 +2,115 @@ | |||||||
|  |  | ||||||
| All notable changes to this project will be documented in this file. Dates are displayed in UTC. | All notable changes to this project will be documented in this file. Dates are displayed in UTC. | ||||||
|  |  | ||||||
|  | #### [1.5.3](https://git.odit.services/lfk/frontend/compare/1.5.2...1.5.3) | ||||||
|  |  | ||||||
|  | - feat(dx): Yarn support [`fc15c68`](https://git.odit.services/lfk/frontend/commit/fc15c68cba0d1986563eaf63da3a68784a685a9e) | ||||||
|  | - feat(about): cleanup ui [`84aa846`](https://git.odit.services/lfk/frontend/commit/84aa846b87186b52a2f8632724d4f2cb70af062b) | ||||||
|  | - feat(dashboard): reorder menu items [`e967d8d`](https://git.odit.services/lfk/frontend/commit/e967d8d20c6972b64b0096594a09043553e9c7e5) | ||||||
|  | - fix: unexpected/ missing props [`d803f3d`](https://git.odit.services/lfk/frontend/commit/d803f3d4905d6f792b77d17025467ac13c29068b) | ||||||
|  | - chore(deps): bump some [`68b4309`](https://git.odit.services/lfk/frontend/commit/68b4309164eac40b6fda969b60a7e238985d49f8) | ||||||
|  | - fix(ci): Switch over to new woodpecker version [`7ba890d`](https://git.odit.services/lfk/frontend/commit/7ba890dfd7ba908ebef0338f6faa5e7d804cb5ef) | ||||||
|  | - refactor(ci): Only build licences, don't export [`32b5f54`](https://git.odit.services/lfk/frontend/commit/32b5f5420bf9ff656b713d61b3a0113b9d6cb69f) | ||||||
|  | - feat: cleanup random page toasts [`ad4db88`](https://git.odit.services/lfk/frontend/commit/ad4db882f0f4d00a80ae5e0072e09c071c07ffa2) | ||||||
|  | - fix(ci): Update git pushb settings [`ee87f82`](https://git.odit.services/lfk/frontend/commit/ee87f82799ce559fd43d671ab412f2643eafeac6) | ||||||
|  | - fix(ci): Update relase machanism [`7c08f52`](https://git.odit.services/lfk/frontend/commit/7c08f522aa4b2986544a4c0e5d3261c4c7296121) | ||||||
|  | - fix(ci): Install pnpm [`e211554`](https://git.odit.services/lfk/frontend/commit/e211554579b1f27d13194eff4aad76f6f030141e) | ||||||
|  | - fix(orgs): ImportRunnerModal props [`5468766`](https://git.odit.services/lfk/frontend/commit/5468766d875a6278f01ed1fd9573688374befdd5) | ||||||
|  |  | ||||||
|  | #### [1.5.2](https://git.odit.services/lfk/frontend/compare/1.5.1...1.5.2) | ||||||
|  |  | ||||||
|  | > 21 November 2024 | ||||||
|  |  | ||||||
|  | - feat: improved dashboard titles ui + a11y [`21453ef`](https://git.odit.services/lfk/frontend/commit/21453ef272665c0b7c7b04009b7b74e110fbd988) | ||||||
|  | - feat: improved dashboard titles ui + a11y [`c883920`](https://git.odit.services/lfk/frontend/commit/c883920caaaaef30a8e54dd0e7eecd68943f3041) | ||||||
|  | - feat(dashboard): improved a11y of active sidebar menu item [`a50447f`](https://git.odit.services/lfk/frontend/commit/a50447f457ecc045995efb7b952b07ea09c91373) | ||||||
|  | - feat: improved mobile buttons + search ui [`38fb111`](https://git.odit.services/lfk/frontend/commit/38fb111f7a2b5a1a01b17b00e89ee081e4b91bd9) | ||||||
|  | - feat(i18n/de): rename "Track" to "Laufstrecke" [`1018243`](https://git.odit.services/lfk/frontend/commit/10182433f825968ee55298399b231173698a795c) | ||||||
|  | - 🚀RELEASE v1.5.2 [`3532968`](https://git.odit.services/lfk/frontend/commit/3532968b3399b985b1ed28ba6b89a13f35f9289b) | ||||||
|  | - feat(dashboard): improved mobile ui hamburger button [`b338f33`](https://git.odit.services/lfk/frontend/commit/b338f33a63ad8e98ab44deff2f80dbd5fe2a0fc2) | ||||||
|  | - feat(dashboard): match greeting style with rest of titles [`b1a2044`](https://git.odit.services/lfk/frontend/commit/b1a20446314d1b25e9f653bd2767b072fd629f97) | ||||||
|  | - feat(dashboard): add lfk icon and app name to mobile nav bar [`6bb49db`](https://git.odit.services/lfk/frontend/commit/6bb49db4eee95486f5a947d708b80a7a94d36933) | ||||||
|  | - feat(users/UsersOverview): improve ui by adding borders to badges [`cb82200`](https://git.odit.services/lfk/frontend/commit/cb82200481c629a0dd8b235821115ae4276948ca) | ||||||
|  |  | ||||||
|  | #### [1.5.1](https://git.odit.services/lfk/frontend/compare/1.5.0...1.5.1) | ||||||
|  |  | ||||||
|  | > 21 November 2024 | ||||||
|  |  | ||||||
|  | - chore(deps): pnpm@9 [`35bec9f`](https://git.odit.services/lfk/frontend/commit/35bec9fe584b93cd52e8bab4e469713468a67f70) | ||||||
|  | - chore(deps): bump some [`8fae1fb`](https://git.odit.services/lfk/frontend/commit/8fae1fb6b3e033f789d2568cbd2640c0d163dc53) | ||||||
|  | - fix(scanstations): CopyScanStationTokenModal open after create [`372fa11`](https://git.odit.services/lfk/frontend/commit/372fa110ec402dae166a302f2209c79353983148) | ||||||
|  | - 🚀RELEASE v1.5.1 [`9abf74d`](https://git.odit.services/lfk/frontend/commit/9abf74d6d217e7745c1055bdbfbe97de7b14572f) | ||||||
|  | - fix(config): add explicit window.config [`91d2f46`](https://git.odit.services/lfk/frontend/commit/91d2f46b934bcba1429bd1d96e772c25c42a3e28) | ||||||
|  | - fix(dockerfile): AS casing [`50e81a6`](https://git.odit.services/lfk/frontend/commit/50e81a6cb5773381e153cbec3bed7db820ced84a) | ||||||
|  | - refactor(scanstations/CopyScanStationTokenModal): drop dispatch [`a5e72a1`](https://git.odit.services/lfk/frontend/commit/a5e72a18e368b5a7ee7b4e1894de613ecb767f28) | ||||||
|  | - chore(deps): node:23.2.0 [`93d67bd`](https://git.odit.services/lfk/frontend/commit/93d67bdba90a67b45d8895d9facaf66e908d53d6) | ||||||
|  | - fix(tracks/AddTrackModal): i18n [`c60bae4`](https://git.odit.services/lfk/frontend/commit/c60bae45334c2aa90d8931da07691c196469da46) | ||||||
|  | - fix: tailwind config [`43ac878`](https://git.odit.services/lfk/frontend/commit/43ac878d44b556c6d7811610f6fe0c9a5eff305f) | ||||||
|  |  | ||||||
|  | #### [1.5.0](https://git.odit.services/lfk/frontend/compare/1.4.13...1.5.0) | ||||||
|  |  | ||||||
|  | > 20 November 2024 | ||||||
|  |  | ||||||
|  | - feat(ci)!: Switch to woodpecker [`fb8206f`](https://git.odit.services/lfk/frontend/commit/fb8206ff130f4f65dcf619a2a786e7d5895b77a1) | ||||||
|  | - 🚀RELEASE v1.5.0 [`ceabd06`](https://git.odit.services/lfk/frontend/commit/ceabd06a4319c3c9ffab680f909730d5bd789540) | ||||||
|  | - fix(components): Add missing toast imports [`9bfc0c5`](https://git.odit.services/lfk/frontend/commit/9bfc0c5338933e832d5df50457c7978c026d8df6) | ||||||
|  |  | ||||||
|  | #### [1.4.13](https://git.odit.services/lfk/frontend/compare/1.4.12...1.4.13) | ||||||
|  |  | ||||||
|  | > 31 July 2023 | ||||||
|  |  | ||||||
|  | - 🚀RELEASE v1.4.13 [`dceb0ef`](https://git.odit.services/lfk/frontend/commit/dceb0ef46197dc56e29c5f52a5bd8f9fe9b70b27) | ||||||
|  | - Show donations as euro in export [`88bc198`](https://git.odit.services/lfk/frontend/commit/88bc1982cab4481e2e9245f81eff27e095b66a0f) | ||||||
|  | - new license file version [CI SKIP] [`6193eff`](https://git.odit.services/lfk/frontend/commit/6193eff38e1a9d5726bc7d572ab36b921de843d0) | ||||||
|  |  | ||||||
|  | #### [1.4.12](https://git.odit.services/lfk/frontend/compare/1.4.11...1.4.12) | ||||||
|  |  | ||||||
|  | > 18 May 2023 | ||||||
|  |  | ||||||
|  | - 🚀RELEASE v1.4.12 [`65f1d22`](https://git.odit.services/lfk/frontend/commit/65f1d222050b0dec81fc847c1921b6135a55ce50) | ||||||
|  | - fix(donation/payment): Funny javascript number to float conversion where integers were needed [`d867c08`](https://git.odit.services/lfk/frontend/commit/d867c08aba234d3a7fe9e2311d37dc5e96fc2afc) | ||||||
|  | - new license file version [CI SKIP] [`08642d7`](https://git.odit.services/lfk/frontend/commit/08642d7618faeae31f0acfe776642c9fa156e5ff) | ||||||
|  |  | ||||||
|  | #### [1.4.11](https://git.odit.services/lfk/frontend/compare/1.4.10...1.4.11) | ||||||
|  |  | ||||||
|  | > 10 May 2023 | ||||||
|  |  | ||||||
|  | - chore(deps): Lockfile [`f77460b`](https://git.odit.services/lfk/frontend/commit/f77460bb0c8ce6d0f3d83a077017d5fc7bf55af7) | ||||||
|  | - 🚀RELEASE v1.4.11 [`373484c`](https://git.odit.services/lfk/frontend/commit/373484c2424bea7ae0d70d342e0ae2076aab1b6a) | ||||||
|  | - feat(orgs): Show total distance [`574e0dc`](https://git.odit.services/lfk/frontend/commit/574e0dcb051305bde2fc76d8456a35baec0cf309) | ||||||
|  | - chore(deps): More bumps [`7b19a0a`](https://git.odit.services/lfk/frontend/commit/7b19a0aa08bb6c89c51d27c0d05777e8fcfdad17) | ||||||
|  |  | ||||||
|  | #### [1.4.10](https://git.odit.services/lfk/frontend/compare/1.4.9...1.4.10) | ||||||
|  |  | ||||||
|  | > 10 May 2023 | ||||||
|  |  | ||||||
|  | - chore(deps): Bumped svelte-table [`29a2854`](https://git.odit.services/lfk/frontend/commit/29a2854671b3af5b85ea96d050a9076f47b6575d) | ||||||
|  | - 🚀RELEASE v1.4.10 [`c3e9c27`](https://git.odit.services/lfk/frontend/commit/c3e9c27cd3d4b916f1661d4958cabab038918587) | ||||||
|  | - chore(deps): Pin and bump [`8e6786e`](https://git.odit.services/lfk/frontend/commit/8e6786e72227b3f07cc805f0957d5b7fd123ec13) | ||||||
|  | - chore(deps): Bumped scanclientjs [`6ad4056`](https://git.odit.services/lfk/frontend/commit/6ad40564e3e342046f6ee19fab9e455ec3bbff9b) | ||||||
|  |  | ||||||
|  | #### [1.4.9](https://git.odit.services/lfk/frontend/compare/1.4.8...1.4.9) | ||||||
|  |  | ||||||
|  | > 9 May 2023 | ||||||
|  |  | ||||||
|  | - 🚀RELEASE v1.4.9 [`776973b`](https://git.odit.services/lfk/frontend/commit/776973bfe9b34c26a1c80d5e458cc2644dd9036b) | ||||||
|  | - Changed the in table replacement method [`d9a47f8`](https://git.odit.services/lfk/frontend/commit/d9a47f882c1c6bcf98ef85d50d70c010d54b326e) | ||||||
|  | - Fixed empty return [`6025e43`](https://git.odit.services/lfk/frontend/commit/6025e43baa8516657a60a1de9a82c2189221c6ac) | ||||||
|  |  | ||||||
|  | #### [1.4.8](https://git.odit.services/lfk/frontend/compare/1.4.7...1.4.8) | ||||||
|  |  | ||||||
|  | > 9 May 2023 | ||||||
|  |  | ||||||
|  | - Switched donor loading to non-paginated [`59fe2df`](https://git.odit.services/lfk/frontend/commit/59fe2dfabb224863876c4db31a965c34a51a9369) | ||||||
|  | - 🚀RELEASE v1.4.8 [`4235758`](https://git.odit.services/lfk/frontend/commit/4235758a6d1499715287d6ab193cc87c68d5742e) | ||||||
|  |  | ||||||
| #### [1.4.7](https://git.odit.services/lfk/frontend/compare/1.4.6...1.4.7) | #### [1.4.7](https://git.odit.services/lfk/frontend/compare/1.4.6...1.4.7) | ||||||
|  |  | ||||||
|  | > 4 May 2023 | ||||||
|  |  | ||||||
| - Paginated modal data loading [`a8a7711`](https://git.odit.services/lfk/frontend/commit/a8a771114df6eb57d5b1d5497a5be49e619d4102) | - Paginated modal data loading [`a8a7711`](https://git.odit.services/lfk/frontend/commit/a8a771114df6eb57d5b1d5497a5be49e619d4102) | ||||||
| - Moved loading to onmount [`4e0a2c8`](https://git.odit.services/lfk/frontend/commit/4e0a2c83015bde5e360c5fb2c0babbeaa03dc2b5) | - Moved loading to onmount [`4e0a2c8`](https://git.odit.services/lfk/frontend/commit/4e0a2c83015bde5e360c5fb2c0babbeaa03dc2b5) | ||||||
|  | - 🚀RELEASE v1.4.7 [`6364536`](https://git.odit.services/lfk/frontend/commit/6364536dcd840c71f7cb6afb31bbc4f160ac4f73) | ||||||
|  |  | ||||||
| #### [1.4.6](https://git.odit.services/lfk/frontend/compare/1.4.5...1.4.6) | #### [1.4.6](https://git.odit.services/lfk/frontend/compare/1.4.5...1.4.6) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,9 +1,9 @@ | |||||||
| FROM registry.odit.services/hub/library/node:20.0.0-alpine3.17 as build | FROM registry.odit.services/hub/library/node:23.2.0-alpine3.20 AS build | ||||||
| ARG NPM_REGISTRY_URL=https://registry.npmjs.org | ARG NPM_REGISTRY_URL=https://registry.npmjs.org | ||||||
| WORKDIR /app | WORKDIR /app | ||||||
|  |  | ||||||
| COPY package.json pnpm-lock.yaml vite.config.js tailwind.config.js postcss.config.cjs index.html ./ | COPY package.json pnpm-lock.yaml vite.config.js tailwind.config.cjs postcss.config.cjs index.html ./ | ||||||
| RUN npm config set registry $NPM_REGISTRY_URL && npm i -g pnpm@8 | RUN npm config set registry $NPM_REGISTRY_URL && npm i -g pnpm@9 | ||||||
| RUN mkdir /pnpm && pnpm config set store-dir /pnpm && pnpm i | RUN mkdir /pnpm && pnpm config set store-dir /pnpm && pnpm i | ||||||
|  |  | ||||||
| COPY src ./src | COPY src ./src | ||||||
| @@ -11,6 +11,6 @@ COPY public ./public | |||||||
| RUN pnpm build | RUN pnpm build | ||||||
|  |  | ||||||
| # final image | # final image | ||||||
| FROM registry.odit.services/library/nginx-brotli:3.15 as final | FROM registry.odit.services/library/nginx-brotli:3.15 AS final | ||||||
| COPY --from=build /app/dist /usr/share/nginx/html | COPY --from=build /app/dist /usr/share/nginx/html | ||||||
| COPY ./nginx.conf /etc/nginx/nginx.conf | COPY ./nginx.conf /etc/nginx/nginx.conf | ||||||
| @@ -13,7 +13,7 @@ | |||||||
|  |  | ||||||
|   <body> |   <body> | ||||||
|     <span style="display: none; visibility: hidden" id="buildinfo" |     <span style="display: none; visibility: hidden" id="buildinfo" | ||||||
|       >RELEASE_INFO-1.4.7-RELEASE_INFO</span |       >RELEASE_INFO-1.5.3-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> | ||||||
|   | |||||||
							
								
								
									
										32
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								package.json
									
									
									
									
									
								
							| @@ -1,6 +1,6 @@ | |||||||
| { | { | ||||||
|   "name": "@odit/lfk-frontend", |   "name": "@odit/lfk-frontend", | ||||||
|   "version": "1.4.7", |   "version": "1.6.0", | ||||||
|   "type": "module", |   "type": "module", | ||||||
|   "scripts": { |   "scripts": { | ||||||
|     "i18n-order": "node order.js", |     "i18n-order": "node order.js", | ||||||
| @@ -12,16 +12,16 @@ | |||||||
|   }, |   }, | ||||||
|   "license": "CC-BY-NC-SA-4.0", |   "license": "CC-BY-NC-SA-4.0", | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|     "@odit/license-exporter": "0.0.12", |     "@odit/license-exporter": "0.2.0", | ||||||
|     "@sveltejs/vite-plugin-svelte": "2.1.1", |     "@sveltejs/vite-plugin-svelte": "2.1.1", | ||||||
|     "auto-changelog": "2.4.0", |     "auto-changelog": "2.5.0", | ||||||
|     "autoprefixer": "10.4.14", |     "autoprefixer": "10.4.20", | ||||||
|     "postcss": "8.4.23", |     "postcss": "8.4.49", | ||||||
|     "prettier": "^2.8.8", |     "prettier": "3.3.3", | ||||||
|     "prettier-plugin-svelte": "^2.10.0", |     "prettier-plugin-svelte": "3.2.8", | ||||||
|     "release-it": "15.10.1", |     "release-it": "17.10.0", | ||||||
|     "svelte-select": "3.17.0", |     "svelte-select": "3.17.0", | ||||||
|     "tailwindcss": "3.3.2", |     "tailwindcss": "3.4.15", | ||||||
|     "vite": "4.3.3" |     "vite": "4.3.3" | ||||||
|   }, |   }, | ||||||
|   "release-it": { |   "release-it": { | ||||||
| @@ -42,19 +42,19 @@ | |||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "@odit/lfk-client-js": "1.1.1", |     "@odit/lfk-client-js": "1.1.3", | ||||||
|     "@paralleldrive/cuid2": "^2.2.0", |     "@paralleldrive/cuid2": "2.2.2", | ||||||
|     "@tanstack/svelte-table": "^8.8.6", |     "@tanstack/svelte-table": "8.9.1", | ||||||
|     "bwip-js": "^3.4.0", |     "bwip-js": "3.4.0", | ||||||
|     "check-password-strength": "2.0.7", |     "check-password-strength": "2.0.10", | ||||||
|     "csvtojson": "2.0.10", |     "csvtojson": "2.0.10", | ||||||
|     "localforage": "1.10.0", |     "localforage": "1.10.0", | ||||||
|     "marked": "4.3.0", |     "marked": "4.3.0", | ||||||
|     "svelte": "3.58.0", |     "svelte": "3.58.0", | ||||||
|     "svelte-french-toast": "1.0.4-beta.0", |     "svelte-french-toast": "1.2.0", | ||||||
|     "svelte-i18n": "3.6.0", |     "svelte-i18n": "3.6.0", | ||||||
|     "tinro": "0.6.12", |     "tinro": "0.6.12", | ||||||
|     "validator": "13.9.0", |     "validator": "13.12.0", | ||||||
|     "xlsx": "0.18.5" |     "xlsx": "0.18.5" | ||||||
|   }, |   }, | ||||||
|   "volta": { |   "volta": { | ||||||
|   | |||||||
							
								
								
									
										5575
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										5575
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,10 +1,12 @@ | |||||||
| const config = { | const config = { | ||||||
|   baseurl: "http://localhost:4010", | 	baseurl: "http://localhost:4010", | ||||||
|   baseurl_documentserver: "http://localhost:4010/documents", | 	baseurl_selfservice: "http://localhost:5174", | ||||||
|   documentserver_key: | 	baseurl_documentserver: "http://localhost:4010/documents", | ||||||
|     "NqZSYTy5AFQ7MppbLW5moqpTk7u7YrNUHKYhKYuThnnya2WpCOIU694hIZT1FzYe", | 	documentserver_key: | ||||||
|   // optional | 		"NqZSYTy5AFQ7MppbLW5moqpTk7u7YrNUHKYhKYuThnnya2WpCOIU694hIZT1FzYe", | ||||||
|   default_username: "demo", | 	// optional | ||||||
|   default_password: "demo", | 	default_username: "demo", | ||||||
|   prefersHashRouting: true, | 	default_password: "demo", | ||||||
|  | 	prefersHashRouting: true, | ||||||
| }; | }; | ||||||
|  | window.config = config; | ||||||
|   | |||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -20,7 +20,6 @@ | |||||||
|         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, jwtinfo); |         store.login(value, jwtinfo); | ||||||
|         toast($_("welcome_wavinghand")); |  | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   }); |   }); | ||||||
| @@ -50,7 +49,6 @@ | |||||||
|           store.login(result.access_token, jwtinfo); |           store.login(result.access_token, jwtinfo); | ||||||
|           location.replace("/"); |           location.replace("/"); | ||||||
|           toast.dismiss(); |           toast.dismiss(); | ||||||
|           toast($_("welcome_wavinghand")); |  | ||||||
|         }) |         }) | ||||||
|         .catch((err) => { |         .catch((err) => { | ||||||
|           toast.dismiss(); |           toast.dismiss(); | ||||||
|   | |||||||
| @@ -11,29 +11,29 @@ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <section class="container p-5"> | <section class="container p-5"> | ||||||
|   <span class="mb-1 text-3xl font-extrabold leading-tight"> |   <h4 class="mb-1 text-3xl font-extrabold leading-tight font-mono"> | ||||||
|     {$_("cards")} |     {$_("cards")} | ||||||
|     {#if store.state.jwtinfo.userdetails.permissions.includes("CARD:CREATE")} |   </h4> | ||||||
|       <button |   {#if store.state.jwtinfo.userdetails.permissions.includes("CARD: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" | ||||||
|       > |       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:w-auto sm:text-sm mt-1 sm:mt-0" | ||||||
|         {$_("add-card")} |     > | ||||||
|       </button> |       {$_("add-card")} | ||||||
|       <button |     </button> | ||||||
|         on:click={() => { |     <button | ||||||
|           bulk_modal_open = true; |       on:click={() => { | ||||||
|         }} |         bulk_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" | ||||||
|       > |       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:w-auto sm:text-sm mt-1 sm:mt-0" | ||||||
|         {$_("create-bulk-cards")} |     > | ||||||
|       </button> |       {$_("create-bulk-cards")} | ||||||
|     {/if} |     </button> | ||||||
|   </span> |   {/if} | ||||||
|   <CardsOverview bind:current_cards bind:addCards /> |   <CardsOverview bind:current_cards bind:addCards /> | ||||||
| </section> | </section> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
|  |  | ||||||
| <div class="text-center items-center justify-center"> | <div class="text-center items-center justify-center"> | ||||||
|   <p class="mb-16 text-lg text-gray-500"> |   <p class="mb-16 text-lg text-gray-500"> | ||||||
|     <img class="m-auto" style="height:15rem" src={cards_empty} alt="" /> |     <img class="m-auto mt-2" style="height:15rem" src={cards_empty} alt="" /> | ||||||
|     <span class="font-bold">{$_("there-are-no-cards-yet")}</span><br /> |     <span class="font-bold">{$_("there-are-no-cards-yet")}</span><br /> | ||||||
|     <span>{$_("add-your-first-card")}</span> |     <span>{$_("add-your-first-card")}</span> | ||||||
|   </p> |   </p> | ||||||
|   | |||||||
| @@ -151,7 +151,6 @@ | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   onMount(async () => { |   onMount(async () => { | ||||||
|     toast.loading($_("loading-cards")); |  | ||||||
|     let page = 0; |     let page = 0; | ||||||
|     let pagesize = 500; |     let pagesize = 500; | ||||||
|     while (page >= 0) { |     while (page >= 0) { | ||||||
| @@ -172,8 +171,6 @@ | |||||||
|       dataLoaded = true; |       dataLoaded = true; | ||||||
|       page++; |       page++; | ||||||
|     } |     } | ||||||
|     toast.dismiss(); |  | ||||||
|     toast.success($_("all-cards-loaded")); |  | ||||||
|   }); |   }); | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| @@ -219,7 +216,7 @@ | |||||||
|       {#if selected.length > 0} |       {#if selected.length > 0} | ||||||
|         <button |         <button | ||||||
|           type="button" |           type="button" | ||||||
|           class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm inline-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:w-auto sm:text-sm inline-flex" | ||||||
|           id="options-menu" |           id="options-menu" | ||||||
|           on:click={async () => { |           on:click={async () => { | ||||||
|             const prom = []; |             const prom = []; | ||||||
|   | |||||||
| @@ -152,7 +152,7 @@ | |||||||
|           {#if delete_triggered} |           {#if delete_triggered} | ||||||
|             <button |             <button | ||||||
|               on:click={deleteContact} |               on:click={deleteContact} | ||||||
|               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" |               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:w-auto sm:text-sm" | ||||||
|               >{$_("confirm-deletion")}</button |               >{$_("confirm-deletion")}</button | ||||||
|             > |             > | ||||||
|             <button |             <button | ||||||
| @@ -169,7 +169,7 @@ | |||||||
|                 delete_triggered = true; |                 delete_triggered = true; | ||||||
|               }} |               }} | ||||||
|               type="button" |               type="button" | ||||||
|               class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm" |               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:w-auto sm:text-sm" | ||||||
|               >{$_("delete-contact")}</button |               >{$_("delete-contact")}</button | ||||||
|             > |             > | ||||||
|           {/if} |           {/if} | ||||||
| @@ -180,7 +180,7 @@ | |||||||
|             class:opacity-50={!save_enabled} |             class:opacity-50={!save_enabled} | ||||||
|             type="button" |             type="button" | ||||||
|             on:click={submit} |             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" |             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:w-auto sm:text-sm" | ||||||
|             >{$_("save-changes")}</button |             >{$_("save-changes")}</button | ||||||
|           > |           > | ||||||
|         {/if} |         {/if} | ||||||
|   | |||||||
| @@ -8,20 +8,20 @@ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <section class="container p-5"> | <section class="container p-5"> | ||||||
|   <span class="mb-1 text-3xl font-extrabold leading-tight"> |   <h4 class="mb-1 text-3xl font-extrabold leading-tight font-mono"> | ||||||
|     {$_("contacts")} |     {$_("contacts")} | ||||||
|     {#if store.state.jwtinfo.userdetails.permissions.includes("CONTACT:CREATE")} |   </h4> | ||||||
|       <button |   {#if store.state.jwtinfo.userdetails.permissions.includes("CONTACT: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" | ||||||
|       > |       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:w-auto sm:text-sm" | ||||||
|         {$_("create-a-new-contact")} |     > | ||||||
|       </button> |       {$_("create-a-new-contact")} | ||||||
|     {/if} |     </button> | ||||||
|   </span> |   {/if} | ||||||
|   <ContactsOverview bind:current_contacts /> |   <ContactsOverview bind:current_contacts /> | ||||||
| </section> | </section> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -32,7 +32,7 @@ | |||||||
|         bind:value={searchvalue} |         bind:value={searchvalue} | ||||||
|         placeholder={$_("datatable.search")} |         placeholder={$_("datatable.search")} | ||||||
|         aria-label={$_("datatable.search")} |         aria-label={$_("datatable.search")} | ||||||
|         class="mb-4" |         class="mb-2 w-full sm:w-auto mt-1 sm:mt-0 p-2 rounded-md border" | ||||||
|       /> |       /> | ||||||
|       <div |       <div | ||||||
|         class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll" |         class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll" | ||||||
|   | |||||||
| @@ -24,12 +24,12 @@ | |||||||
|     </a> |     </a> | ||||||
|     <nav class="text-sm font-medium text-gray-600" aria-label="Main Navigation"> |     <nav class="text-sm font-medium text-gray-600" aria-label="Main Navigation"> | ||||||
|       <a |       <a | ||||||
|         class:bg-gray-100={$router.path === "/"} |         class:activenav={$router.path === "/"} | ||||||
|         class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900" |         class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900" | ||||||
|         href="/" |         href="/" | ||||||
|       > |       > | ||||||
|         <svg |         <svg | ||||||
|           class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600" |           class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
|           xmlns="http://www.w3.org/2000/svg" |           xmlns="http://www.w3.org/2000/svg" | ||||||
|           viewBox="0 0 20 20" |           viewBox="0 0 20 20" | ||||||
|           fill="currentColor" |           fill="currentColor" | ||||||
| @@ -40,79 +40,16 @@ | |||||||
|         </svg> |         </svg> | ||||||
|         <span>{$_("dashboard-title")}</span> |         <span>{$_("dashboard-title")}</span> | ||||||
|       </a> |       </a> | ||||||
|       {#if store.state.jwtinfo.userdetails.permissions.includes("ORGANIZATION:GET")} |  | ||||||
|         <a |  | ||||||
|           class:bg-gray-100={$router.path.includes("/orgs/")} |  | ||||||
|           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900" |  | ||||||
|           href="/orgs/" |  | ||||||
|         > |  | ||||||
|           <svg |  | ||||||
|             class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600" |  | ||||||
|             fill="currentColor" |  | ||||||
|             xmlns="http://www.w3.org/2000/svg" |  | ||||||
|             viewBox="0 0 24 24" |  | ||||||
|             width="24" |  | ||||||
|             height="24" |  | ||||||
|             ><path fill="none" d="M0 0h24v24H0z" /> |  | ||||||
|             <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 |  | ||||||
|           > |  | ||||||
|           <span>{$_("orgs")}</span> |  | ||||||
|         </a> |  | ||||||
|       {/if} |  | ||||||
|       {#if store.state.jwtinfo.userdetails.permissions.includes("USER:GET")} |  | ||||||
|         <a |  | ||||||
|           class:bg-gray-100={$router.path === "/users/"} |  | ||||||
|           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900" |  | ||||||
|           href="/users/" |  | ||||||
|         > |  | ||||||
|           <svg |  | ||||||
|             xmlns="http://www.w3.org/2000/svg" |  | ||||||
|             width="24" |  | ||||||
|             height="24" |  | ||||||
|             class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600" |  | ||||||
|             fill="currentColor" |  | ||||||
|             viewBox="0 0 24 24" |  | ||||||
|             ><path fill="none" d="M0 0h24v24H0z" /> |  | ||||||
|             <path |  | ||||||
|               d="M12 14v8H4a8 8 0 018-8zm0-1a6 6 0 110-12 6 6 0 010 12zm2.6 5.81a3.51 3.51 0 010-1.62l-1-.57 1-1.74 1 .58a3.5 3.5 0 011.4-.82V13.5h2v1.15a3.5 3.5 0 011.4.8l1-.57 1 1.74-1 .57a3.51 3.51 0 010 1.62l1 .57-1 1.74-1-.58a3.5 3.5 0 01-1.4.82v1.14h-2v-1.15a3.5 3.5 0 01-1.4-.8l-1 .57-1-1.74 1-.57zM18 17a1 1 0 100 2 1 1 0 000-2z" |  | ||||||
|             /></svg |  | ||||||
|           > |  | ||||||
|           <span>{$_("users")}</span> |  | ||||||
|         </a> |  | ||||||
|       {/if} |  | ||||||
|       {#if store.state.jwtinfo.userdetails.permissions.includes("USERGROUP:GET")} |  | ||||||
|         <a |  | ||||||
|           class:bg-gray-100={$router.path === "/groups/"} |  | ||||||
|           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900" |  | ||||||
|           href="/groups/" |  | ||||||
|         > |  | ||||||
|           <svg |  | ||||||
|             class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600" |  | ||||||
|             fill="currentColor" |  | ||||||
|             width="24" |  | ||||||
|             height="24" |  | ||||||
|             xmlns="http://www.w3.org/2000/svg" |  | ||||||
|             viewBox="0 0 640 512" |  | ||||||
|             ><path |  | ||||||
|               fill="currentColor" |  | ||||||
|               d="M610.5 341.3c2.6-14.1 2.6-28.5 0-42.6l25.8-14.9c3-1.7 4.3-5.2 3.3-8.5-6.7-21.6-18.2-41.2-33.2-57.4-2.3-2.5-6-3.1-9-1.4l-25.8 14.9c-10.9-9.3-23.4-16.5-36.9-21.3v-29.8c0-3.4-2.4-6.4-5.7-7.1-22.3-5-45-4.8-66.2 0-3.3.7-5.7 3.7-5.7 7.1v29.8c-13.5 4.8-26 12-36.9 21.3l-25.8-14.9c-2.9-1.7-6.7-1.1-9 1.4-15 16.2-26.5 35.8-33.2 57.4-1 3.3.4 6.8 3.3 8.5l25.8 14.9c-2.6 14.1-2.6 28.5 0 42.6l-25.8 14.9c-3 1.7-4.3 5.2-3.3 8.5 6.7 21.6 18.2 41.1 33.2 57.4 2.3 2.5 6 3.1 9 1.4l25.8-14.9c10.9 9.3 23.4 16.5 36.9 21.3v29.8c0 3.4 2.4 6.4 5.7 7.1 22.3 5 45 4.8 66.2 0 3.3-.7 5.7-3.7 5.7-7.1v-29.8c13.5-4.8 26-12 36.9-21.3l25.8 14.9c2.9 1.7 6.7 1.1 9-1.4 15-16.2 26.5-35.8 33.2-57.4 1-3.3-.4-6.8-3.3-8.5l-25.8-14.9zM496 368.5c-26.8 0-48.5-21.8-48.5-48.5s21.8-48.5 48.5-48.5 48.5 21.8 48.5 48.5-21.7 48.5-48.5 48.5zM96 224c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm224 32c1.9 0 3.7-.5 5.6-.6 8.3-21.7 20.5-42.1 36.3-59.2 7.4-8 17.9-12.6 28.9-12.6 6.9 0 13.7 1.8 19.6 5.3l7.9 4.6c.8-.5 1.6-.9 2.4-1.4 7-14.6 11.2-30.8 11.2-48 0-61.9-50.1-112-112-112S208 82.1 208 144c0 61.9 50.1 112 112 112zm105.2 194.5c-2.3-1.2-4.6-2.6-6.8-3.9-8.2 4.8-15.3 9.8-27.5 9.8-10.9 0-21.4-4.6-28.9-12.6-18.3-19.8-32.3-43.9-40.2-69.6-10.7-34.5 24.9-49.7 25.8-50.3-.1-2.6-.1-5.2 0-7.8l-7.9-4.6c-3.8-2.2-7-5-9.8-8.1-3.3.2-6.5.6-9.8.6-24.6 0-47.6-6-68.5-16h-8.3C179.6 288 128 339.6 128 403.2V432c0 26.5 21.5 48 48 48h255.4c-3.7-6-6.2-12.8-6.2-20.3v-9.2zM173.1 274.6C161.5 263.1 145.6 256 128 256H64c-35.3 0-64 28.7-64 64v32c0 17.7 14.3 32 32 32h65.9c6.3-47.4 34.9-87.3 75.2-109.4z" |  | ||||||
|             /></svg |  | ||||||
|           > |  | ||||||
|           <span>{$_("user-groups")}</span> |  | ||||||
|         </a> |  | ||||||
|       {/if} |  | ||||||
|       {#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:GET")} |       {#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:GET")} | ||||||
|         <a |         <a | ||||||
|           class:bg-gray-100={$router.path === "/runners/"} |           class:activenav={$router.path === "/runners/"} | ||||||
|           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900" |           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900" | ||||||
|           href="/runners/" |           href="/runners/" | ||||||
|         > |         > | ||||||
|           <svg |           <svg | ||||||
|             xmlns="http://www.w3.org/2000/svg" |             xmlns="http://www.w3.org/2000/svg" | ||||||
|             viewBox="0 0 24 24" |             viewBox="0 0 24 24" | ||||||
|             class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600" |             class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
|             fill="currentColor" |             fill="currentColor" | ||||||
|             width="24" |             width="24" | ||||||
|             height="24" |             height="24" | ||||||
| @@ -126,12 +63,12 @@ | |||||||
|       {/if} |       {/if} | ||||||
|       {#if store.state.jwtinfo.userdetails.permissions.includes("TEAM:GET")} |       {#if store.state.jwtinfo.userdetails.permissions.includes("TEAM:GET")} | ||||||
|         <a |         <a | ||||||
|           class:bg-gray-100={$router.path === "/teams/"} |           class:activenav={$router.path === "/teams/"} | ||||||
|           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900" |           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900" | ||||||
|           href="/teams/" |           href="/teams/" | ||||||
|         > |         > | ||||||
|           <svg |           <svg | ||||||
|             class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600" |             class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
|             fill="currentColor" |             fill="currentColor" | ||||||
|             width="24" |             width="24" | ||||||
|             height="24" |             height="24" | ||||||
| @@ -145,14 +82,35 @@ | |||||||
|           <span>{$_("teams")}</span> |           <span>{$_("teams")}</span> | ||||||
|         </a> |         </a> | ||||||
|       {/if} |       {/if} | ||||||
|  |       {#if store.state.jwtinfo.userdetails.permissions.includes("ORGANIZATION:GET")} | ||||||
|  |         <a | ||||||
|  |           class:activenav={$router.path.includes("/orgs/")} | ||||||
|  |           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900" | ||||||
|  |           href="/orgs/" | ||||||
|  |         > | ||||||
|  |           <svg | ||||||
|  |             class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
|  |             fill="currentColor" | ||||||
|  |             xmlns="http://www.w3.org/2000/svg" | ||||||
|  |             viewBox="0 0 24 24" | ||||||
|  |             width="24" | ||||||
|  |             height="24" | ||||||
|  |             ><path fill="none" d="M0 0h24v24H0z" /> | ||||||
|  |             <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 | ||||||
|  |           > | ||||||
|  |           <span>{$_("orgs")}</span> | ||||||
|  |         </a> | ||||||
|  |       {/if} | ||||||
|       {#if store.state.jwtinfo.userdetails.permissions.includes("DONOR:GET")} |       {#if store.state.jwtinfo.userdetails.permissions.includes("DONOR:GET")} | ||||||
|         <a |         <a | ||||||
|           class:bg-gray-100={$router.path.includes("/donors/")} |           class:activenav={$router.path.includes("/donors/")} | ||||||
|           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900" |           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900" | ||||||
|           href="/donors/" |           href="/donors/" | ||||||
|         > |         > | ||||||
|           <svg |           <svg | ||||||
|             class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600" |             class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
|             fill="currentColor" |             fill="currentColor" | ||||||
|             xmlns="http://www.w3.org/2000/svg" |             xmlns="http://www.w3.org/2000/svg" | ||||||
|             viewBox="0 0 24 24" |             viewBox="0 0 24 24" | ||||||
| @@ -168,12 +126,12 @@ | |||||||
|       {/if} |       {/if} | ||||||
|       {#if store.state.jwtinfo.userdetails.permissions.includes("DONATION:GET")} |       {#if store.state.jwtinfo.userdetails.permissions.includes("DONATION:GET")} | ||||||
|         <a |         <a | ||||||
|           class:bg-gray-100={$router.path.includes("/donations/")} |           class:activenav={$router.path.includes("/donations/")} | ||||||
|           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900" |           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900" | ||||||
|           href="/donations/" |           href="/donations/" | ||||||
|         > |         > | ||||||
|           <svg |           <svg | ||||||
|             class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600" |             class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
|             fill="currentColor" |             fill="currentColor" | ||||||
|             xmlns="http://www.w3.org/2000/svg" |             xmlns="http://www.w3.org/2000/svg" | ||||||
|             viewBox="0 0 24 24" |             viewBox="0 0 24 24" | ||||||
| @@ -189,12 +147,12 @@ | |||||||
|       {/if} |       {/if} | ||||||
|       {#if store.state.jwtinfo.userdetails.permissions.includes("TRACK:GET")} |       {#if store.state.jwtinfo.userdetails.permissions.includes("TRACK:GET")} | ||||||
|         <a |         <a | ||||||
|           class:bg-gray-100={$router.path === "/tracks/"} |           class:activenav={$router.path === "/tracks/"} | ||||||
|           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900" |           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900" | ||||||
|           href="/tracks/" |           href="/tracks/" | ||||||
|         > |         > | ||||||
|           <svg |           <svg | ||||||
|             class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600" |             class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
|             fill="currentColor" |             fill="currentColor" | ||||||
|             width="24" |             width="24" | ||||||
|             height="24" |             height="24" | ||||||
| @@ -210,12 +168,12 @@ | |||||||
|       {/if} |       {/if} | ||||||
|       {#if store.state.jwtinfo.userdetails.permissions.includes("CARD:GET")} |       {#if store.state.jwtinfo.userdetails.permissions.includes("CARD:GET")} | ||||||
|         <a |         <a | ||||||
|           class:bg-gray-100={$router.path === "/cards/"} |           class:activenav={$router.path === "/cards/"} | ||||||
|           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900" |           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900" | ||||||
|           href="/cards/" |           href="/cards/" | ||||||
|         > |         > | ||||||
|           <svg |           <svg | ||||||
|             class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600" |             class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
|             fill="currentColor" |             fill="currentColor" | ||||||
|             width="24" |             width="24" | ||||||
|             height="24" |             height="24" | ||||||
| @@ -233,12 +191,12 @@ | |||||||
|       {/if} |       {/if} | ||||||
|       {#if store.state.jwtinfo.userdetails.permissions.includes("SCAN:GET")} |       {#if store.state.jwtinfo.userdetails.permissions.includes("SCAN:GET")} | ||||||
|         <a |         <a | ||||||
|           class:bg-gray-100={$router.path === "/scans/"} |           class:activenav={$router.path === "/scans/"} | ||||||
|           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900" |           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900" | ||||||
|           href="/scans/" |           href="/scans/" | ||||||
|         > |         > | ||||||
|           <svg |           <svg | ||||||
|             class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600" |             class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
|             fill="currentColor" |             fill="currentColor" | ||||||
|             width="24" |             width="24" | ||||||
|             height="24" |             height="24" | ||||||
| @@ -255,13 +213,13 @@ | |||||||
|       {/if} |       {/if} | ||||||
|       {#if store.state.jwtinfo.userdetails.permissions.includes("CONTACT:GET")} |       {#if store.state.jwtinfo.userdetails.permissions.includes("CONTACT:GET")} | ||||||
|         <a |         <a | ||||||
|           class:bg-gray-100={$router.path === "/contacts/"} |           class:activenav={$router.path === "/contacts/"} | ||||||
|           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900" |           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900" | ||||||
|           href="/contacts/" |           href="/contacts/" | ||||||
|         > |         > | ||||||
|           <svg |           <svg | ||||||
|             fill="currentColor" |             fill="currentColor" | ||||||
|             class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600" |             class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
|             xmlns="http://www.w3.org/2000/svg" |             xmlns="http://www.w3.org/2000/svg" | ||||||
|             viewBox="0 0 24 24" |             viewBox="0 0 24 24" | ||||||
|             width="24" |             width="24" | ||||||
| @@ -276,12 +234,12 @@ | |||||||
|       {/if} |       {/if} | ||||||
|       {#if store.state.jwtinfo.userdetails.permissions.includes("STATION:GET")} |       {#if store.state.jwtinfo.userdetails.permissions.includes("STATION:GET")} | ||||||
|         <a |         <a | ||||||
|           class:bg-gray-100={$router.path === "/scanstations/"} |           class:activenav={$router.path === "/scanstations/"} | ||||||
|           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900" |           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900" | ||||||
|           href="/scanstations/" |           href="/scanstations/" | ||||||
|         > |         > | ||||||
|           <svg |           <svg | ||||||
|             class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600" |             class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
|             fill="currentColor" |             fill="currentColor" | ||||||
|             width="24" |             width="24" | ||||||
|             height="24" |             height="24" | ||||||
| @@ -298,12 +256,12 @@ | |||||||
|       {/if} |       {/if} | ||||||
|       {#if store.state.jwtinfo.userdetails.permissions.includes("STATSCLIENT:GET")} |       {#if store.state.jwtinfo.userdetails.permissions.includes("STATSCLIENT:GET")} | ||||||
|         <a |         <a | ||||||
|           class:bg-gray-100={$router.path === "/statsclients/"} |           class:activenav={$router.path === "/statsclients/"} | ||||||
|           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900" |           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900" | ||||||
|           href="/statsclients/" |           href="/statsclients/" | ||||||
|         > |         > | ||||||
|           <svg |           <svg | ||||||
|             class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600" |             class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
|             fill="currentColor" |             fill="currentColor" | ||||||
|             width="24" |             width="24" | ||||||
|             height="24" |             height="24" | ||||||
| @@ -318,13 +276,55 @@ | |||||||
|           <span>{$_("statsclients")}</span> |           <span>{$_("statsclients")}</span> | ||||||
|         </a> |         </a> | ||||||
|       {/if} |       {/if} | ||||||
|  |       {#if store.state.jwtinfo.userdetails.permissions.includes("USER:GET")} | ||||||
|  |         <a | ||||||
|  |           class:activenav={$router.path === "/users/"} | ||||||
|  |           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900" | ||||||
|  |           href="/users/" | ||||||
|  |         > | ||||||
|  |           <svg | ||||||
|  |             xmlns="http://www.w3.org/2000/svg" | ||||||
|  |             width="24" | ||||||
|  |             height="24" | ||||||
|  |             class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
|  |             fill="currentColor" | ||||||
|  |             viewBox="0 0 24 24" | ||||||
|  |             ><path fill="none" d="M0 0h24v24H0z" /> | ||||||
|  |             <path | ||||||
|  |               d="M12 14v8H4a8 8 0 018-8zm0-1a6 6 0 110-12 6 6 0 010 12zm2.6 5.81a3.51 3.51 0 010-1.62l-1-.57 1-1.74 1 .58a3.5 3.5 0 011.4-.82V13.5h2v1.15a3.5 3.5 0 011.4.8l1-.57 1 1.74-1 .57a3.51 3.51 0 010 1.62l1 .57-1 1.74-1-.58a3.5 3.5 0 01-1.4.82v1.14h-2v-1.15a3.5 3.5 0 01-1.4-.8l-1 .57-1-1.74 1-.57zM18 17a1 1 0 100 2 1 1 0 000-2z" | ||||||
|  |             /></svg | ||||||
|  |           > | ||||||
|  |           <span>{$_("users")}</span> | ||||||
|  |         </a> | ||||||
|  |       {/if} | ||||||
|  |       {#if store.state.jwtinfo.userdetails.permissions.includes("USERGROUP:GET")} | ||||||
|  |         <a | ||||||
|  |           class:activenav={$router.path === "/groups/"} | ||||||
|  |           class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900" | ||||||
|  |           href="/groups/" | ||||||
|  |         > | ||||||
|  |           <svg | ||||||
|  |             class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
|  |             fill="currentColor" | ||||||
|  |             width="24" | ||||||
|  |             height="24" | ||||||
|  |             xmlns="http://www.w3.org/2000/svg" | ||||||
|  |             viewBox="0 0 640 512" | ||||||
|  |             ><path | ||||||
|  |               fill="currentColor" | ||||||
|  |               d="M610.5 341.3c2.6-14.1 2.6-28.5 0-42.6l25.8-14.9c3-1.7 4.3-5.2 3.3-8.5-6.7-21.6-18.2-41.2-33.2-57.4-2.3-2.5-6-3.1-9-1.4l-25.8 14.9c-10.9-9.3-23.4-16.5-36.9-21.3v-29.8c0-3.4-2.4-6.4-5.7-7.1-22.3-5-45-4.8-66.2 0-3.3.7-5.7 3.7-5.7 7.1v29.8c-13.5 4.8-26 12-36.9 21.3l-25.8-14.9c-2.9-1.7-6.7-1.1-9 1.4-15 16.2-26.5 35.8-33.2 57.4-1 3.3.4 6.8 3.3 8.5l25.8 14.9c-2.6 14.1-2.6 28.5 0 42.6l-25.8 14.9c-3 1.7-4.3 5.2-3.3 8.5 6.7 21.6 18.2 41.1 33.2 57.4 2.3 2.5 6 3.1 9 1.4l25.8-14.9c10.9 9.3 23.4 16.5 36.9 21.3v29.8c0 3.4 2.4 6.4 5.7 7.1 22.3 5 45 4.8 66.2 0 3.3-.7 5.7-3.7 5.7-7.1v-29.8c13.5-4.8 26-12 36.9-21.3l25.8 14.9c2.9 1.7 6.7 1.1 9-1.4 15-16.2 26.5-35.8 33.2-57.4 1-3.3-.4-6.8-3.3-8.5l-25.8-14.9zM496 368.5c-26.8 0-48.5-21.8-48.5-48.5s21.8-48.5 48.5-48.5 48.5 21.8 48.5 48.5-21.7 48.5-48.5 48.5zM96 224c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm224 32c1.9 0 3.7-.5 5.6-.6 8.3-21.7 20.5-42.1 36.3-59.2 7.4-8 17.9-12.6 28.9-12.6 6.9 0 13.7 1.8 19.6 5.3l7.9 4.6c.8-.5 1.6-.9 2.4-1.4 7-14.6 11.2-30.8 11.2-48 0-61.9-50.1-112-112-112S208 82.1 208 144c0 61.9 50.1 112 112 112zm105.2 194.5c-2.3-1.2-4.6-2.6-6.8-3.9-8.2 4.8-15.3 9.8-27.5 9.8-10.9 0-21.4-4.6-28.9-12.6-18.3-19.8-32.3-43.9-40.2-69.6-10.7-34.5 24.9-49.7 25.8-50.3-.1-2.6-.1-5.2 0-7.8l-7.9-4.6c-3.8-2.2-7-5-9.8-8.1-3.3.2-6.5.6-9.8.6-24.6 0-47.6-6-68.5-16h-8.3C179.6 288 128 339.6 128 403.2V432c0 26.5 21.5 48 48 48h255.4c-3.7-6-6.2-12.8-6.2-20.3v-9.2zM173.1 274.6C161.5 263.1 145.6 256 128 256H64c-35.3 0-64 28.7-64 64v32c0 17.7 14.3 32 32 32h65.9c6.3-47.4 34.9-87.3 75.2-109.4z" | ||||||
|  |             /></svg | ||||||
|  |           > | ||||||
|  |           <span>{$_("user-groups")}</span> | ||||||
|  |         </a> | ||||||
|  |       {/if} | ||||||
|       <a |       <a | ||||||
|         class:bg-gray-100={$router.path === "/settings/"} |         class:activenav={$router.path === "/settings/"} | ||||||
|         class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900" |         class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900" | ||||||
|         href="/settings/" |         href="/settings/" | ||||||
|       > |       > | ||||||
|         <svg |         <svg | ||||||
|           class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600" |           class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
|           xmlns="http://www.w3.org/2000/svg" |           xmlns="http://www.w3.org/2000/svg" | ||||||
|           viewBox="0 0 20 20" |           viewBox="0 0 20 20" | ||||||
|           fill="currentColor" |           fill="currentColor" | ||||||
| @@ -338,12 +338,12 @@ | |||||||
|         <span>{$_("settings")}</span> |         <span>{$_("settings")}</span> | ||||||
|       </a> |       </a> | ||||||
|       <a |       <a | ||||||
|         class:bg-gray-100={$router.path === "/about/"} |         class:activenav={$router.path === "/about/"} | ||||||
|         class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900" |         class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900" | ||||||
|         href="/about/" |         href="/about/" | ||||||
|       > |       > | ||||||
|         <svg |         <svg | ||||||
|           class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600" |           class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
|           xmlns="http://www.w3.org/2000/svg" |           xmlns="http://www.w3.org/2000/svg" | ||||||
|           fill="none" |           fill="none" | ||||||
|           stroke="currentColor" |           stroke="currentColor" | ||||||
| @@ -358,14 +358,14 @@ | |||||||
|       </a> |       </a> | ||||||
|       <button |       <button | ||||||
|         tabindex="0" |         tabindex="0" | ||||||
|         class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900" |         class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900" | ||||||
|         on:click={() => { |         on:click={() => { | ||||||
|           AuthService.authControllerLogout(); |           AuthService.authControllerLogout(); | ||||||
|           logout(); |           logout(); | ||||||
|         }} |         }} | ||||||
|       > |       > | ||||||
|         <svg |         <svg | ||||||
|           class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600" |           class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600" | ||||||
|           fill="currentColor" |           fill="currentColor" | ||||||
|           width="24" |           width="24" | ||||||
|           height="24" |           height="24" | ||||||
| @@ -382,7 +382,7 @@ | |||||||
|   </div> |   </div> | ||||||
|   <div class="ml-0 transition md:ml-60"> |   <div class="ml-0 transition md:ml-60"> | ||||||
|     <header |     <header | ||||||
|       class="flex items-center justify-between w-full px-4 bg-white border-b h-14 md:hidden" |       class="flex items-center w-full px-4 bg-white border-b h-14 md:hidden" | ||||||
|     > |     > | ||||||
|       <button |       <button | ||||||
|         on:click={() => { |         on:click={() => { | ||||||
| @@ -390,18 +390,15 @@ | |||||||
|         }} |         }} | ||||||
|         class="block btn btn-light md:hidden" |         class="block btn btn-light md:hidden" | ||||||
|       > |       > | ||||||
|         <span class="sr-only">Menu</span><svg |         <span class="sr-only">Menu</span><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6"> | ||||||
|           class="w-4 h-4" |           <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" /> | ||||||
|           xmlns="http://www.w3.org/2000/svg" |         </svg> | ||||||
|           viewBox="0 0 20 20" |         </button | ||||||
|           fill="currentcolor" |  | ||||||
|           ><path |  | ||||||
|             fill-rule="evenodd" |  | ||||||
|             d="M3 5a1 1 0 011-1h12a1 1 0 110 2H4A1 1 0 013 5zm0 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zm0 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1z" |  | ||||||
|             clip-rule="evenodd" |  | ||||||
|           /></svg |  | ||||||
|         ></button |  | ||||||
|       > |       > | ||||||
|  |       <span class="inline-block"> | ||||||
|  |         <img src="/lfk-logo.png" alt="Logo" class="h-8 inline-block" /> | ||||||
|  |         <span class="text-lg font-bold">LfK!Admin</span> | ||||||
|  |       </span> | ||||||
|     </header> |     </header> | ||||||
|     <Toaster position="top-right" /> |     <Toaster position="top-right" /> | ||||||
|     <slot> |     <slot> | ||||||
|   | |||||||
| @@ -3,18 +3,16 @@ | |||||||
|   import { StatsService } from "@odit/lfk-client-js"; |   import { StatsService } from "@odit/lfk-client-js"; | ||||||
|   import store from "../../store"; |   import store from "../../store"; | ||||||
|   import StatCard from "./StatCard.svelte"; |   import StatCard from "./StatCard.svelte"; | ||||||
|   let navOpen = false; |  | ||||||
|   const stats_promise = StatsService.statsControllerGet(); |   const stats_promise = StatsService.statsControllerGet(); | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <div class="p-2 md:p-5 overflow-x-hidden"> | <div class="p-2 md:p-5 overflow-x-hidden"> | ||||||
|   <h1 class="text-3xl leading-tight mb-4"> |   <h4 class="mb-1 text-3xl font-extrabold leading-tight font-mono"> | ||||||
|     {$_("dashboard-greeting")}, |     {$_("dashboard-greeting")} <span class="text-blue-500" | ||||||
|     <span class="text-blue-500" |  | ||||||
|       >{store.state.jwtinfo.userdetails.firstname} |       >{store.state.jwtinfo.userdetails.firstname} | ||||||
|       {store.state.jwtinfo.userdetails.lastname}</span |       {store.state.jwtinfo.userdetails.lastname}</span | ||||||
|     > |     > | ||||||
|   </h1> |   </h4> | ||||||
|   {#await stats_promise} |   {#await stats_promise} | ||||||
|     <div |     <div | ||||||
|       class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2" |       class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2" | ||||||
| @@ -25,7 +23,7 @@ | |||||||
|     </div> |     </div> | ||||||
|   {:then stats} |   {:then stats} | ||||||
|     <div |     <div | ||||||
|       class="grid gap-2 grid-cols-2 lg:grid-cols-3 xl:grid-cols-5 2xl:grid-cols-6 sm:gap-4" |       class="grid gap-1 grid-cols-2 lg:grid-cols-3 xl:grid-cols-5 2xl:grid-cols-6 sm:gap-4" | ||||||
|     > |     > | ||||||
|       <StatCard |       <StatCard | ||||||
|         title={$_("runners")} |         title={$_("runners")} | ||||||
|   | |||||||
| @@ -7,13 +7,13 @@ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <a {href}> | <a {href}> | ||||||
|   <div class="p-4 rounded-lg bg-white border border-grey-100"> |   <div class="p-3 py-4 sm:p-4 rounded-lg bg-white border border-grey-100"> | ||||||
|     <div class="flex flex-row items-center justify-between"> |     <div class="flex flex-row items-center justify-between"> | ||||||
|       <div class="flex flex-col"> |       <div class="flex flex-col"> | ||||||
|         <div class="text-xs uppercase font-normal text-grey-500"> |         <div class="text-md sm:text-xs uppercase font-normal text-grey-500"> | ||||||
|           {title} |           {title} | ||||||
|         </div> |         </div> | ||||||
|         <div class="text-xl font-bold font-mono">{value}</div> |         <div class="text-2xl sm:text-xl font-bold font-mono">{value}</div> | ||||||
|       </div> |       </div> | ||||||
|       <slot /> |       <slot /> | ||||||
|     </div> |     </div> | ||||||
|   | |||||||
| @@ -98,35 +98,19 @@ | |||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   onMount(()=>{ |  | ||||||
|     loadDonorsAndRunnersPaginated(); |  | ||||||
|   }) |  | ||||||
|  |  | ||||||
|   async function loadDonorsAndRunnersPaginated() { |   onMount(async () => { | ||||||
|     let page = 0; |     donors = (await DonorService.donorControllerGetAll()).map( | ||||||
|     let pagesize = 500; |       (r) => { | ||||||
|     while (page >= 0) { |         return { label: getDonorLabel(r), value: r }; | ||||||
|       const don = await DonorService.donorControllerGetAll(page, pagesize); |  | ||||||
|       const run = await RunnerService.runnerControllerGetAll(page, pagesize); |  | ||||||
|       if (don.length == 0 && run.length == 0) { |  | ||||||
|         page = -2; |  | ||||||
|       } |       } | ||||||
|  |     ); | ||||||
|       donors = donors.concat( |     runners = (await RunnerService.runnerControllerGetAll()).map( | ||||||
|         ...run.map((r) => { |       (r) => { | ||||||
|           return { label: getDonorLabel(r), value: r }; |         return { label: getDonorLabel(r), value: r }; | ||||||
|         }) |       } | ||||||
|       ); |     ); | ||||||
|       runners = runners.concat( |   }); | ||||||
|         ...run.map((r) => { |  | ||||||
|           return { label: getDonorLabel(r), value: r }; |  | ||||||
|         }) |  | ||||||
|       ); |  | ||||||
|  |  | ||||||
|       dataLoaded = true; |  | ||||||
|       page++; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| {#if modal_open} | {#if modal_open} | ||||||
|   | |||||||
| @@ -33,7 +33,7 @@ | |||||||
|       toast.loading($_("updating-donation")); |       toast.loading($_("updating-donation")); | ||||||
|       const editable = Object.assign({}, original_data); |       const editable = Object.assign({}, original_data); | ||||||
|       editable.donor = editable.donor.id; |       editable.donor = editable.donor.id; | ||||||
|       editable.paidAmount = paid_amount_input * 100; |       editable.paidAmount = Math.round(paid_amount_input * 100); | ||||||
|       if (editable.responseType == "DISTANCEDONATION" || editable.runner) { |       if (editable.responseType == "DISTANCEDONATION" || editable.runner) { | ||||||
|         editable.runner = editable.runner.id; |         editable.runner = editable.runner.id; | ||||||
|         DonationService.donationControllerPutDistance( |         DonationService.donationControllerPutDistance( | ||||||
| @@ -46,7 +46,7 @@ | |||||||
|             toast.dismiss(); |             toast.dismiss(); | ||||||
|  |  | ||||||
|             toast.success($_("donation-updated")); |             toast.success($_("donation-updated")); | ||||||
|             dispatch("created", { donation: response }); |             dispatch("created", { donation: result }); | ||||||
|           }) |           }) | ||||||
|           .catch((err) => { |           .catch((err) => { | ||||||
|             // |             // | ||||||
| @@ -61,7 +61,7 @@ | |||||||
|             // |             // | ||||||
|             toast.dismiss(); |             toast.dismiss(); | ||||||
|             toast.success($_("donation-updated")); |             toast.success($_("donation-updated")); | ||||||
|             dispatch("created", { donation: response }); |             dispatch("created", { donation: result }); | ||||||
|           }) |           }) | ||||||
|           .catch((err) => { |           .catch((err) => { | ||||||
|             // |             // | ||||||
|   | |||||||
| @@ -6,6 +6,7 @@ | |||||||
|     DonorService, |     DonorService, | ||||||
|     RunnerService, |     RunnerService, | ||||||
|   } from "@odit/lfk-client-js"; |   } from "@odit/lfk-client-js"; | ||||||
|  |   import toast from 'svelte-french-toast' | ||||||
|  |  | ||||||
|   import PromiseError from "../base/PromiseError.svelte"; |   import PromiseError from "../base/PromiseError.svelte"; | ||||||
|   import Select from "svelte-select"; |   import Select from "svelte-select"; | ||||||
|   | |||||||
| @@ -9,20 +9,20 @@ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <section class="container p-5"> | <section class="container p-5"> | ||||||
|   <span class="mb-1 text-3xl font-extrabold leading-tight"> |   <h4 class="mb-1 text-3xl font-extrabold leading-tight font-mono"> | ||||||
|     {$_("donations")} |     {$_("donations")} | ||||||
|     {#if store.state.jwtinfo.userdetails.permissions.includes("DONATION:CREATE")} |   </h4> | ||||||
|       <button |   {#if store.state.jwtinfo.userdetails.permissions.includes("DONATION: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" | ||||||
|       > |       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:w-auto sm:text-sm" | ||||||
|         {$_("add-donation")} |     > | ||||||
|       </button> |       {$_("add-donation")} | ||||||
|     {/if} |     </button> | ||||||
|   </span> |   {/if} | ||||||
|   <DonationsOverview bind:current_donations bind:addDonations /> |   <DonationsOverview bind:current_donations bind:addDonations /> | ||||||
| </section> | </section> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
|  |  | ||||||
| <div class="text-center items-center justify-center"> | <div class="text-center items-center justify-center"> | ||||||
|   <p class="mb-16 text-lg text-gray-500"> |   <p class="mb-16 text-lg text-gray-500"> | ||||||
|     <img class="m-auto" style="height:15rem" src={donations_empty} alt="" /> |     <img class="m-auto mt-2" style="height:15rem" src={donations_empty} alt="" /> | ||||||
|     <span class="font-bold">{$_("there-are-no-donations-yet")}</span><br /> |     <span class="font-bold">{$_("there-are-no-donations-yet")}</span><br /> | ||||||
|     <span>{$_("add-your-fist-donation")}</span> |     <span>{$_("add-your-fist-donation")}</span> | ||||||
|   </p> |   </p> | ||||||
|   | |||||||
| @@ -195,9 +195,12 @@ | |||||||
|   payment_modal_open={active_edits.length > 0} |   payment_modal_open={active_edits.length > 0} | ||||||
|   paid_amount_input={(active_edits[0]?.paidAmount || 0) / 100} |   paid_amount_input={(active_edits[0]?.paidAmount || 0) / 100} | ||||||
|   on:created={(event) => { |   on:created={(event) => { | ||||||
|     current_donations[ |     current_donations = current_donations.map((d)=>{ | ||||||
|       current_donations.findIndex((d) => d.id === event.detail.donation.id) |       if(d.id === event.detail.donation.id){ | ||||||
|     ].paidAmount = event.detail.donation.paidAmount; |         d.paidAmount = event.detail.donation.paidAmount; | ||||||
|  |       } | ||||||
|  |       return d; | ||||||
|  |     }) | ||||||
|     options.update((options) => ({ |     options.update((options) => ({ | ||||||
|       ...options, |       ...options, | ||||||
|       data: current_donations, |       data: current_donations, | ||||||
| @@ -228,7 +231,7 @@ | |||||||
|       bind:value={searchvalue} |       bind:value={searchvalue} | ||||||
|       placeholder={$_("datatable.search")} |       placeholder={$_("datatable.search")} | ||||||
|       aria-label={$_("datatable.search")} |       aria-label={$_("datatable.search")} | ||||||
|       class="mb-4" |       class="mb-2 w-full sm:w-auto mt-1 sm:mt-0 p-2 rounded-md border" | ||||||
|     /> |     /> | ||||||
|     <div |     <div | ||||||
|       class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll" |       class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll" | ||||||
|   | |||||||
| @@ -9,61 +9,61 @@ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <section class="container p-5"> | <section class="container p-5"> | ||||||
|   <span class="mb-1 text-3xl font-extrabold leading-tight"> |   <h4 class="mb-1 text-3xl font-extrabold leading-tight font-mono"> | ||||||
|     {$_("donors")} |     {$_("donors")} | ||||||
|     {#if store.state.jwtinfo.userdetails.permissions.includes("DONOR:CREATE")} |   </h4> | ||||||
|       <button |   {#if store.state.jwtinfo.userdetails.permissions.includes("DONOR: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" | ||||||
|       > |       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:w-auto sm:text-sm mt-1 sm:mt-0" | ||||||
|         {$_("add-donor")} |     > | ||||||
|       </button> |       {$_("add-donor")} | ||||||
|     {/if} |     </button> | ||||||
|     {#if store.state.jwtinfo.userdetails.permissions.includes("DONOR:GET")} |   {/if} | ||||||
|       <button |   {#if store.state.jwtinfo.userdetails.permissions.includes("DONOR:GET")} | ||||||
|         on:click={() => { |     <button | ||||||
|           const data = current_donors |       on:click={() => { | ||||||
|             .filter((d) => d.receiptNeeded === true) |         const data = current_donors | ||||||
|             .map(function (d) { |           .filter((d) => d.receiptNeeded === true) | ||||||
|               d.address.address2 = |           .map(function (d) { | ||||||
|                 d.address.address2 === "" ? "" : " " + d.address.address2; |             d.address.address2 = | ||||||
|               const address = `${d.address.address1}${d.address.address2}, ${d.address.postalcode} ${d.address.city}, ${d.address.country}`; |               d.address.address2 === "" ? "" : " " + d.address.address2; | ||||||
|               return [ |             const address = `${d.address.address1}${d.address.address2}, ${d.address.postalcode} ${d.address.city}, ${d.address.country}`; | ||||||
|                 d.firstname, |             return [ | ||||||
|                 d.middlename, |               d.firstname, | ||||||
|                 d.lastname, |               d.middlename, | ||||||
|                 d.paidDonationAmount, |               d.lastname, | ||||||
|                 address, |               (d.paidDonationAmount/100).toFixed(2), | ||||||
|               ]; |               address, | ||||||
|             }); |             ]; | ||||||
|           let csv = `${$_("csv_import__firstname")};${$_( |  | ||||||
|             "csv_import__middlename" |  | ||||||
|           )};${$_("csv_import__lastname")};${$_( |  | ||||||
|             "total_donation_amount_in_eur" |  | ||||||
|           )};${$_("address")}\n`; |  | ||||||
|           data.forEach(function (row) { |  | ||||||
|             csv += row.join(";"); |  | ||||||
|             csv += "\n"; |  | ||||||
|           }); |           }); | ||||||
|           let hiddenElement = document.createElement("a"); |         let csv = `${$_("csv_import__firstname")};${$_( | ||||||
|           hiddenElement.href = "data:text/csv;charset=utf-8," + encodeURI(csv); |           "csv_import__middlename" | ||||||
|           hiddenElement.target = "_blank"; |         )};${$_("csv_import__lastname")};${$_( | ||||||
|           hiddenElement.download = `${$_( |           "total_donation_amount_in_eur" | ||||||
|             "filename_sponsoringquittungsliste" |         )};${$_("address")}\n`; | ||||||
|           )}.csv`; |         data.forEach(function (row) { | ||||||
|           hiddenElement.click(); |           csv += row.join(";"); | ||||||
|           hiddenElement.remove(); |           csv += "\n"; | ||||||
|         }} |         }); | ||||||
|         type="button" |         let hiddenElement = document.createElement("a"); | ||||||
|         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" |         hiddenElement.href = "data:text/csv;charset=utf-8," + encodeURI(csv); | ||||||
|       > |         hiddenElement.target = "_blank"; | ||||||
|         {$_("sponsoring-quittungs-liste_herunterladen")} |         hiddenElement.download = `${$_( | ||||||
|       </button> |           "filename_sponsoringquittungsliste" | ||||||
|     {/if} |         )}.csv`; | ||||||
|   </span> |         hiddenElement.click(); | ||||||
|  |         hiddenElement.remove(); | ||||||
|  |       }} | ||||||
|  |       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:w-auto sm:text-sm mt-1 sm:mt-0" | ||||||
|  |     > | ||||||
|  |       {$_("sponsoring-quittungs-liste_herunterladen")} | ||||||
|  |     </button> | ||||||
|  |   {/if} | ||||||
|   <DonorsOverview bind:current_donors bind:addDonors /> |   <DonorsOverview bind:current_donors bind:addDonors /> | ||||||
| </section> | </section> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -202,7 +202,7 @@ | |||||||
|       bind:value={searchvalue} |       bind:value={searchvalue} | ||||||
|       placeholder={$_("datatable.search")} |       placeholder={$_("datatable.search")} | ||||||
|       aria-label={$_("datatable.search")} |       aria-label={$_("datatable.search")} | ||||||
|       class="mb-4" |       class="mb-2 w-full sm:w-auto mt-1 sm:mt-0 p-2 rounded-md border" | ||||||
|     /> |     /> | ||||||
|     <div |     <div | ||||||
|       class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll" |       class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll" | ||||||
|   | |||||||
| @@ -1,210 +1,196 @@ | |||||||
| <script> | <script> | ||||||
|   import { _ } from "svelte-i18n"; | 	import { _ } from "svelte-i18n"; | ||||||
|   import { clickOutside } from "../base/outsideclick"; | 	import { clickOutside } from "../base/outsideclick"; | ||||||
|  |  | ||||||
|   export let modal_open; | 	let modal_open = false; | ||||||
|   (function () { | 	(function () { | ||||||
|     document.onkeydown = function (e) { | 		document.onkeydown = function (e) { | ||||||
|       e = e || window.event; | 			e = e || window.event; | ||||||
|       if (e.key === "Escape") { | 			if (e.key === "Escape") { | ||||||
|         modal_open = false; | 				modal_open = false; | ||||||
|       } | 			} | ||||||
|     }; | 		}; | ||||||
|   })(); | 	})(); | ||||||
|   const license_promise = fetch("/licenses.json"); | 	const license_promise = fetch("/licenses.json"); | ||||||
|   let licenses = []; | 	let licenses = []; | ||||||
|   $: currentlicense = ""; | 	$: currentlicense = ""; | ||||||
|   $: licensetext = ""; | 	$: licensetext = ""; | ||||||
|   license_promise | 	license_promise | ||||||
|     .then((response) => response.json()) | 		.then((response) => response.json()) | ||||||
|     .then((json) => { | 		.then((json) => { | ||||||
|       licenses = json; | 			licenses = json; | ||||||
|     }); | 		}); | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| {#if modal_open} | {#if modal_open} | ||||||
|   <div | 	<div | ||||||
|     class="fixed z-10 inset-0 overflow-y-auto" | 		class="fixed z-10 inset-0 overflow-y-auto" | ||||||
|     use:clickOutside | 		use:clickOutside | ||||||
|     on:click_outside={() => { | 		on:click_outside={() => { | ||||||
|       modal_open = false; | 			modal_open = false; | ||||||
|     }} | 		}} | ||||||
|   > | 	> | ||||||
|     <div | 		<div | ||||||
|       class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0" | 			class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 sm:block sm:p-0" | ||||||
|     > | 		> | ||||||
|       <div class="fixed inset-0 transition-opacity" aria-hidden="true"> | 			<div class="fixed inset-0 transition-opacity" aria-hidden="true"> | ||||||
|         <div | 				<div | ||||||
|           class="absolute inset-0 bg-gray-500 opacity-75" | 					class="absolute inset-0 bg-gray-500 opacity-75" | ||||||
|           data-id="modal_backdrop" | 					data-id="modal_backdrop" | ||||||
|         /> | 				/> | ||||||
|       </div> | 			</div> | ||||||
|       <span | 			<span | ||||||
|         class="hidden sm:inline-block sm:align-middle sm:h-screen" | 				class="hidden sm:inline-block sm:align-middle sm:h-screen" | ||||||
|         aria-hidden="true">​</span | 				aria-hidden="true">​</span | ||||||
|       > | 			> | ||||||
|       <div | 			<div | ||||||
|         class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full" | 				class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full" | ||||||
|         role="dialog" | 				role="dialog" | ||||||
|         aria-modal="true" | 				aria-modal="true" | ||||||
|         aria-labelledby="modal-headline" | 				aria-labelledby="modal-headline" | ||||||
|       > | 			> | ||||||
|         <div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4"> | 				<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="sm:flex sm:items-start"> | ||||||
|             <div | 						<div | ||||||
|               class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10" | 							class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10" | ||||||
|             > | 						> | ||||||
|               <svg | 							<svg | ||||||
|                 fill="currentColor" | 								fill="currentColor" | ||||||
|                 class="h-6 w-6 text-blue-600" | 								class="h-6 w-6 text-blue-600" | ||||||
|                 xmlns="http://www.w3.org/2000/svg" | 								xmlns="http://www.w3.org/2000/svg" | ||||||
|                 viewBox="0 0 24 24" | 								viewBox="0 0 24 24" | ||||||
|                 width="24" | 								width="24" | ||||||
|                 height="24" | 								height="24" | ||||||
|                 ><path fill="none" d="M0 0h24v24H0z" /> | 								><path fill="none" d="M0 0h24v24H0z" /> | ||||||
|                 <path | 								<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" | 									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 | 								/></svg | ||||||
|               > | 							> | ||||||
|             </div> | 						</div> | ||||||
|             <div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left"> | 						<div class="mt-3 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"> | ||||||
|                 {$_("read-license")} | 								{$_("read-license")} | ||||||
|               </h3> | 							</h3> | ||||||
|               <div class="mt-2 mb-6"> | 							<div class="mt-2 mb-6"> | ||||||
|                 <p class="text-sm text-gray-500">{currentlicense}</p> | 								<p class="text-sm text-gray-500">{currentlicense}</p> | ||||||
|               </div> | 							</div> | ||||||
|               <div class="mt-2 mb-6"> | 							<div class="mt-2 mb-6"> | ||||||
|                 <p class="text-sm text-gray-500">{licensetext}</p> | 								<p class="text-sm text-gray-500">{licensetext}</p> | ||||||
|               </div> | 							</div> | ||||||
|             </div> | 						</div> | ||||||
|           </div> | 					</div> | ||||||
|         </div> | 				</div> | ||||||
|         <div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse"> | 				<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse"> | ||||||
|           <button | 					<button | ||||||
|             on:click={() => { | 						on:click={() => { | ||||||
|               modal_open = false; | 							modal_open = false; | ||||||
|             }} | 						}} | ||||||
|             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:w-auto sm:text-sm" | ||||||
|           > | 					> | ||||||
|             {$_("close")} | 						{$_("close")} | ||||||
|           </button> | 					</button> | ||||||
|         </div> | 				</div> | ||||||
|       </div> | 			</div> | ||||||
|     </div> | 		</div> | ||||||
|   </div> | 	</div> | ||||||
| {/if} | {/if} | ||||||
| <!-- /// --> | <!-- /// --> | ||||||
| <div class="pt-12 px-4 sm:px-6 lg:px-8 lg:pt-20 bg-gray-900 pb-12"> | <section class="container p-5"> | ||||||
|   <div class="text-center mb-8"> | 	<h4 class="mb-1 text-3xl font-extrabold leading-tight font-mono"> | ||||||
|     <h1 | 		{$_("about")} | ||||||
|       class="mt-9 font-display text-4xl leading-none font-semibold text-white sm:text-5xl lg:text-6xl" | 	</h4> | ||||||
|     > | 	<p class="mt-2 mb-2"> | ||||||
|       {$_("about")} | 		Lauf für Kaya! | ||||||
|       🧾 | 		<strong class="font-medium"> | ||||||
|     </h1> | 			{$_("by")} | ||||||
|     <p | 			<a href="https://odit.services" class="underline">ODIT.Services</a> | ||||||
|       class="mt-2 max-w-xl mx-auto text-xl lg:max-w-3xl lg:text-2xl text-gray-300" | 		</strong> | ||||||
|     > | 		<br /> | ||||||
|       Lauf für Kaya! | 		<span>{$_("lfk-is-os")}</span> | ||||||
|       <strong class="text-white font-medium"> | 	</p> | ||||||
|         {$_("by")} | 	<h4 class="mb-1 text-3xl font-extrabold leading-tight font-mono"> | ||||||
|         <a href="https://odit.services" class="underline">ODIT.Services</a> | 		{$_("credits")} | ||||||
|       </strong> | 	</h4> | ||||||
|       <br /> | 	<p class="text-left">{$_("oss_credit_description")}</p> | ||||||
|       <span class="text-lg">{$_("lfk-is-os")}</span> | 	<div class="mt-5 overflow-x-auto"> | ||||||
|     </p> | 		{#await license_promise} | ||||||
|   </div> | 			<p>{$_("licenses-are-being-loaded")}</p> | ||||||
| </div> | 		{:then} | ||||||
|  | 			<table class="font-mono"> | ||||||
| <div class="pt-0 pb-16 overflow-hidden lg:pt-12 lg:py-24"> | 				<thead class="border-b border-gray-400"> | ||||||
|   <div class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8"> | 					<tr class="odd:bg-white even:bg-gray-100"> | ||||||
|     <h2 class="text-4xl font-display font-semibold md:text-5xl"> | 						<th>{$_("dependency_name")}</th> | ||||||
|       {$_("credits")} | 						<th>{$_("license")}</th> | ||||||
|     </h2> | 						<th>{$_("repo_link")}</th> | ||||||
|     <div class="max-w-3xl mx-auto text-xl leading-8 font-medium mt-8"> | 						<th>{$_("installed-version")}</th> | ||||||
|       <p class="text-center">{$_("oss_credit_description")}</p> | 						<th>{$_("author")}</th> | ||||||
|     </div> | 					</tr> | ||||||
|     <div class="w-screen leading-8 pl-5 mt-5"> | 				</thead> | ||||||
|       {#await license_promise} | 				<tbody> | ||||||
|         <p class="text-center w-full">{$_("licenses-are-being-loaded")}</p> | 					{#each licenses as l} | ||||||
|       {:then} | 						<tr class="odd:bg-white even:bg-gray-100 *:p-2"> | ||||||
|         <table> | 							<td>{l.name}</td> | ||||||
|           <thead class="border-b border-gray-400"> | 							<td> | ||||||
|             <tr class="odd:bg-white even:bg-gray-100"> | 								<button | ||||||
|               <th>{$_("dependency_name")}</th> | 									class="underline cursor-pointer" | ||||||
|               <th>{$_("license")}</th> | 									on:click={() => { | ||||||
|               <th>{$_("repo_link")}</th> | 										modal_open = true; | ||||||
|               <th>{$_("installed-version")}</th> | 										currentlicense = l.name + "@" + l.version; | ||||||
|               <th>{$_("author")}</th> | 										licensetext = | ||||||
|             </tr> | 											l.licensetext || $_("no-license-text-could-be-found"); | ||||||
|           </thead> | 									}}>{l.license || "?"}</button | ||||||
|           <tbody> | 								> | ||||||
|             {#each licenses as l} | 							</td> | ||||||
|               <tr class="odd:bg-white even:bg-gray-100"> | 							<td> | ||||||
|                 <td>{l.name}</td> | 								{(l.repo?.url || l.repo) | ||||||
|                 <td> | 									.replace("git+", "") | ||||||
|                   {l.license || "?"}<br /><button | 									.replace("git://", "")} | ||||||
|                     class="underline cursor-pointer" | 							</td> | ||||||
|                     on:click={() => { | 							<td>{l.version || "?"}</td> | ||||||
|                       modal_open = true; | 							<td>{l.author?.name || l.author || "?"}</td> | ||||||
|                       currentlicense = l.name + "@" + l.version; | 						</tr> | ||||||
|                       licensetext = | 					{/each} | ||||||
|                         l.licensetext || $_("no-license-text-could-be-found"); | 				</tbody> | ||||||
|                     }}>{$_("read-license")}</button | 			</table> | ||||||
|                   > | 		{:catch error} | ||||||
|                 </td> | 			<div | ||||||
|                 <td> | 				class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500" | ||||||
|                   {(l.repo?.url || l.repo) | 			> | ||||||
|                     .replace("git+", "") | 				<span class="inline-block align-middle mr-8"> | ||||||
|                     .replace("git://", "")} | 					<b class="capitalize">{$_("general_promise_error")}</b> | ||||||
|                 </td> | 					{error} | ||||||
|                 <td>{l.version || "?"}</td> | 				</span> | ||||||
|                 <td>{l.author?.name || l.author || "?"}</td> | 			</div> | ||||||
|               </tr> | 		{/await} | ||||||
|             {/each} | 	</div> | ||||||
|           </tbody> | 	<div class="w-full mt-8"> | ||||||
|         </table> | 		<p class="font-medium">{$_("icon-image-credits")}</p> | ||||||
|       {:catch error} | 		<ul class="list-disc ml-6"> | ||||||
|         <div | 			<li> | ||||||
|           class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500" | 				<a | ||||||
|         > | 					class="underline" | ||||||
|           <span class="inline-block align-middle mr-8"> | 					target="_blank" | ||||||
|             <b class="capitalize">{$_("general_promise_error")}</b> | 					rel="noopener noreferrer" | ||||||
|             {error} | 					href="https://storyset.com">https://storyset.com</a | ||||||
|           </span> | 				> | ||||||
|         </div> | 			</li> | ||||||
|       {/await} | 			<li> | ||||||
|     </div> | 				<a | ||||||
|     <div class="w-full leading-8 mt-8"> | 					class="underline" | ||||||
|       <p class="text-xl font-medium">{$_("icon-image-credits")}</p> | 					target="_blank" | ||||||
|       <ul class="list-disc"> | 					rel="noopener noreferrer" | ||||||
|         <li> | 					href="https://undraw.co">https://undraw.co</a | ||||||
|           <a | 				> | ||||||
|             class="underline" | 			</li> | ||||||
|             target="_blank" | 			<li> | ||||||
|             rel="noopener noreferrer" | 				<a | ||||||
|             href="https://storyset.com">https://storyset.com</a | 					class="underline" | ||||||
|           > | 					target="_blank" | ||||||
|         </li> | 					rel="noopener noreferrer" | ||||||
|         <li> | 					href="https://remixicon.com">https://remixicon.com</a | ||||||
|           <a | 				> | ||||||
|             class="underline" | 			</li> | ||||||
|             target="_blank" | 		</ul> | ||||||
|             rel="noopener noreferrer" | 	</div> | ||||||
|             href="https://undraw.co">https://undraw.co</a | </section> | ||||||
|           > |  | ||||||
|         </li> |  | ||||||
|         <li> |  | ||||||
|           <a |  | ||||||
|             class="underline" |  | ||||||
|             target="_blank" |  | ||||||
|             rel="noopener noreferrer" |  | ||||||
|             href="https://remixicon.com">https://remixicon.com</a |  | ||||||
|           > |  | ||||||
|         </li> |  | ||||||
|       </ul> |  | ||||||
|     </div> |  | ||||||
|   </div> |  | ||||||
| </div> |  | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ | |||||||
|   import { _ } from "svelte-i18n"; |   import { _ } from "svelte-i18n"; | ||||||
|   import store from "../../store"; |   import store from "../../store"; | ||||||
|   import { UserGroupService } from "@odit/lfk-client-js"; |   import { UserGroupService } from "@odit/lfk-client-js"; | ||||||
|  |   import toast from 'svelte-french-toast' | ||||||
|  |  | ||||||
|   import PromiseError from "../base/PromiseError.svelte"; |   import PromiseError from "../base/PromiseError.svelte"; | ||||||
|   let data_loaded = false; |   let data_loaded = false; | ||||||
| @@ -131,7 +132,7 @@ | |||||||
|           {#if delete_triggered} |           {#if delete_triggered} | ||||||
|             <button |             <button | ||||||
|               on:click={deleteGroup} |               on:click={deleteGroup} | ||||||
|               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" |               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:w-auto sm:text-sm" | ||||||
|               >{$_("confirm-deletion")}</button |               >{$_("confirm-deletion")}</button | ||||||
|             > |             > | ||||||
|             <button |             <button | ||||||
| @@ -148,7 +149,7 @@ | |||||||
|                 delete_triggered = true; |                 delete_triggered = true; | ||||||
|               }} |               }} | ||||||
|               type="button" |               type="button" | ||||||
|               class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm" |               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:w-auto sm:text-sm" | ||||||
|               >{$_("delete-group")}</button |               >{$_("delete-group")}</button | ||||||
|             > |             > | ||||||
|           {/if} |           {/if} | ||||||
| @@ -159,7 +160,7 @@ | |||||||
|             class:opacity-50={!save_enabled} |             class:opacity-50={!save_enabled} | ||||||
|             type="button" |             type="button" | ||||||
|             on:click={submit} |             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" |             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:w-auto sm:text-sm" | ||||||
|             >{$_("save-changes")}</button |             >{$_("save-changes")}</button | ||||||
|           > |           > | ||||||
|         {/if} |         {/if} | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ | |||||||
|     CreatePermission, |     CreatePermission, | ||||||
|     UserGroupService, |     UserGroupService, | ||||||
|   } from "@odit/lfk-client-js"; |   } from "@odit/lfk-client-js"; | ||||||
|  |   import toast from 'svelte-french-toast' | ||||||
|  |  | ||||||
|   import PromiseError from "../base/PromiseError.svelte"; |   import PromiseError from "../base/PromiseError.svelte"; | ||||||
|   export let params; |   export let params; | ||||||
| @@ -142,13 +143,13 @@ | |||||||
|             class:opacity-50={save_enabled} |             class:opacity-50={save_enabled} | ||||||
|             type="button" |             type="button" | ||||||
|             on:click={submit} |             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" |             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:w-auto sm:text-sm" | ||||||
|             >{$_("save-changes")}</button |             >{$_("save-changes")}</button | ||||||
|           > |           > | ||||||
|         {:else} |         {:else} | ||||||
|           <button |           <button | ||||||
|             type="button" |             type="button" | ||||||
|             class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-yellow-600 text-base font-medium text-white hover:bg-yellow-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-yellow-500 sm:ml-3 sm:w-auto sm:text-sm" |             class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-yellow-600 text-base font-medium text-white hover:bg-yellow-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-yellow-500 sm:w-auto sm:text-sm" | ||||||
|             >{$_("applying-changes")}</button |             >{$_("applying-changes")}</button | ||||||
|           > |           > | ||||||
|         {/if} |         {/if} | ||||||
| @@ -192,7 +193,7 @@ | |||||||
|                       } |                       } | ||||||
|                     }} |                     }} | ||||||
|                     type="button" |                     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" |                     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:w-auto sm:text-sm" | ||||||
|                     >+</button |                     >+</button | ||||||
|                   > |                   > | ||||||
|                 </p> |                 </p> | ||||||
| @@ -232,7 +233,7 @@ | |||||||
|                     } |                     } | ||||||
|                   }} |                   }} | ||||||
|                   type="button" |                   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" |                   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:w-auto sm:text-sm" | ||||||
|                   >-</button |                   >-</button | ||||||
|                 > |                 > | ||||||
|               </p> |               </p> | ||||||
|   | |||||||
| @@ -8,20 +8,20 @@ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <section class="container p-5"> | <section class="container p-5"> | ||||||
|   <span class="mb-1 text-3xl font-extrabold leading-tight"> |   <h4 class="mb-1 text-3xl font-extrabold leading-tight font-mono"> | ||||||
|     {$_("user-groups")} |     {$_("user-groups")} | ||||||
|     {#if store.state.jwtinfo.userdetails.permissions.includes("USERGROUP:CREATE")} |   </h4> | ||||||
|       <button |   {#if store.state.jwtinfo.userdetails.permissions.includes("USERGROUP: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" | ||||||
|       > |       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:w-auto sm:text-sm" | ||||||
|         {$_("add-user-group")} |     > | ||||||
|       </button> |       {$_("add-user-group")} | ||||||
|     {/if} |     </button> | ||||||
|   </span> |   {/if} | ||||||
|   <UserGroupsOverview bind:current_groups /> |   <UserGroupsOverview bind:current_groups /> | ||||||
| </section> | </section> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -31,7 +31,7 @@ | |||||||
|         bind:value={searchvalue} |         bind:value={searchvalue} | ||||||
|         placeholder={$_("datatable.search")} |         placeholder={$_("datatable.search")} | ||||||
|         aria-label={$_("datatable.search")} |         aria-label={$_("datatable.search")} | ||||||
|         class="mb-4" |         class="mb-2 w-full sm:w-auto mt-1 sm:mt-0 p-2 rounded-md border" | ||||||
|       /> |       /> | ||||||
|       <div |       <div | ||||||
|         class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll" |         class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll" | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ | |||||||
|     RunnerOrganizationService, |     RunnerOrganizationService, | ||||||
|   } from "@odit/lfk-client-js"; |   } from "@odit/lfk-client-js"; | ||||||
|   import { getLocaleFromNavigator, _ } from "svelte-i18n"; |   import { getLocaleFromNavigator, _ } from "svelte-i18n"; | ||||||
|  |   import toast from 'svelte-french-toast' | ||||||
|  |  | ||||||
|   import store from "../../store"; |   import store from "../../store"; | ||||||
|   import ConfirmOrgDeletion from "./ConfirmOrgDeletion.svelte"; |   import ConfirmOrgDeletion from "./ConfirmOrgDeletion.svelte"; | ||||||
| @@ -37,7 +38,7 @@ | |||||||
|   $: cards_show = true; |   $: cards_show = true; | ||||||
|   $: certificates_show = true; |   $: certificates_show = true; | ||||||
|   $: generate_orgs = [original_object]; |   $: generate_orgs = [original_object]; | ||||||
|   $: registrationLink = `${config.baseurl}/selfservice/register/${editable.registrationKey}`; |   $: registrationLink = `${config.baseurl_selfservice}/register/${editable.registrationKey}`; | ||||||
|   const getContactLabel = (option) => |   const getContactLabel = (option) => | ||||||
|     option.firstname + " " + (option.middlename || "") + " " + option.lastname; |     option.firstname + " " + (option.middlename || "") + " " + option.lastname; | ||||||
|   const promise = RunnerOrganizationService.runnerOrganizationControllerGetOne( |   const promise = RunnerOrganizationService.runnerOrganizationControllerGetOne( | ||||||
| @@ -162,7 +163,7 @@ | |||||||
|               import_modal_open = true; |               import_modal_open = true; | ||||||
|             }} |             }} | ||||||
|             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:w-auto sm:text-sm" | ||||||
|           > |           > | ||||||
|             {$_("import-runners")} |             {$_("import-runners")} | ||||||
|           </button> |           </button> | ||||||
| @@ -171,7 +172,7 @@ | |||||||
|           {#if delete_triggered} |           {#if delete_triggered} | ||||||
|             <button |             <button | ||||||
|               on:click={deleteOrganization} |               on:click={deleteOrganization} | ||||||
|               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" |               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:w-auto sm:text-sm" | ||||||
|               >{$_("confirm-delete")}</button |               >{$_("confirm-delete")}</button | ||||||
|             > |             > | ||||||
|             <button |             <button | ||||||
| @@ -188,7 +189,7 @@ | |||||||
|                 delete_triggered = true; |                 delete_triggered = true; | ||||||
|               }} |               }} | ||||||
|               type="button" |               type="button" | ||||||
|               class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm" |               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:w-auto sm:text-sm" | ||||||
|               >{$_("delete-organization")}</button |               >{$_("delete-organization")}</button | ||||||
|             > |             > | ||||||
|           {/if} |           {/if} | ||||||
| @@ -199,7 +200,7 @@ | |||||||
|             disabled={!save_enabled} |             disabled={!save_enabled} | ||||||
|             class:opacity-50={!save_enabled} |             class:opacity-50={!save_enabled} | ||||||
|             type="button" |             type="button" | ||||||
|             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" |             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:w-auto sm:text-sm" | ||||||
|             >{$_("save-changes")}</button |             >{$_("save-changes")}</button | ||||||
|           > |           > | ||||||
|         {/if} |         {/if} | ||||||
| @@ -470,6 +471,11 @@ | |||||||
|             {/if} |             {/if} | ||||||
|           </div> |           </div> | ||||||
|         {/if} |         {/if} | ||||||
|  |         <div class="text-sm w-full"> | ||||||
|  |           <span class="font-medium text-gray-700">{$_("distance")}</span> | ||||||
|  |           <br /> | ||||||
|  |           <span class="text-gray-700">{(original_object.total_distance / 1000).toFixed(2)} km</span> | ||||||
|  |         </div> | ||||||
|       </div> |       </div> | ||||||
|     </div> |     </div> | ||||||
|   </section> |   </section> | ||||||
|   | |||||||
| @@ -58,7 +58,7 @@ | |||||||
|         bind:value={searchvalue} |         bind:value={searchvalue} | ||||||
|         placeholder={$_("datatable.search")} |         placeholder={$_("datatable.search")} | ||||||
|         aria-label={$_("datatable.search")} |         aria-label={$_("datatable.search")} | ||||||
|         class="mb-4" |         class="mb-2 w-full sm:w-auto mt-1 sm:mt-0 p-2 rounded-md border" | ||||||
|       /> |       /> | ||||||
|       <div class="h-12"> |       <div class="h-12"> | ||||||
|         <GenerateSponsoringContracts |         <GenerateSponsoringContracts | ||||||
|   | |||||||
| @@ -10,31 +10,31 @@ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <section class="container p-5"> | <section class="container p-5"> | ||||||
|   <span class="mb-1 text-3xl font-extrabold leading-tight"> |   <h4 class="mb-1 text-3xl font-extrabold leading-tight font-mono"> | ||||||
|     {$_("organizations")} |     {$_("organizations")} | ||||||
|     {#if store.state.jwtinfo.userdetails.permissions.includes("ORGANIZATION:CREATE")} |   </h4> | ||||||
|       <button |   {#if store.state.jwtinfo.userdetails.permissions.includes("ORGANIZATION: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" | ||||||
|       > |       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:w-auto sm:text-sm mt-1 sm:mt-0" | ||||||
|         {$_("create-organization")} |     > | ||||||
|       </button> |       {$_("create-organization")} | ||||||
|     {/if} |     </button> | ||||||
|     {#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:IMPORT")} |   {/if} | ||||||
|       <button |   {#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:IMPORT")} | ||||||
|         on:click={() => { |     <button | ||||||
|           import_modal_open = true; |       on:click={() => { | ||||||
|         }} |         import_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" | ||||||
|       > |       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:w-auto sm:text-sm mt-1 sm:mt-0" | ||||||
|         {$_("import-runners")} |     > | ||||||
|       </button> |       {$_("import-runners")} | ||||||
|     {/if} |     </button> | ||||||
|   </span> |   {/if} | ||||||
|   <OrgOverview bind:current_organizations /> |   <OrgOverview bind:current_organizations /> | ||||||
| </section> | </section> | ||||||
|  |  | ||||||
| @@ -48,7 +48,6 @@ | |||||||
|     passed_org={{}} |     passed_org={{}} | ||||||
|     passed_orgs={current_organizations} |     passed_orgs={current_organizations} | ||||||
|     opened_from="OrgOverview" |     opened_from="OrgOverview" | ||||||
|     current_runners={[]} |  | ||||||
|     bind:import_modal_open |     bind:import_modal_open | ||||||
|   /> |   /> | ||||||
| {/if} | {/if} | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ | |||||||
|     RunnerOrganizationService, |     RunnerOrganizationService, | ||||||
|     RunnerTeamService, |     RunnerTeamService, | ||||||
|   } from "@odit/lfk-client-js"; |   } from "@odit/lfk-client-js"; | ||||||
|  |   import toast from 'svelte-french-toast' | ||||||
|  |  | ||||||
|   import { init } from "@paralleldrive/cuid2"; |   import { init } from "@paralleldrive/cuid2"; | ||||||
|   const createId = init({ length: 10, fingerprint: "lfk-frontend" }); |   const createId = init({ length: 10, fingerprint: "lfk-frontend" }); | ||||||
|   | |||||||
| @@ -12,6 +12,7 @@ | |||||||
|   import Select from "svelte-select"; |   import Select from "svelte-select"; | ||||||
|   import { createEventDispatcher } from "svelte"; |   import { createEventDispatcher } from "svelte"; | ||||||
|   const dispatch = createEventDispatcher(); |   const dispatch = createEventDispatcher(); | ||||||
|  |   import toast from 'svelte-french-toast' | ||||||
|  |  | ||||||
|   export let modal_open; |   export let modal_open; | ||||||
|   $: selected_team = undefined; |   $: selected_team = undefined; | ||||||
|   | |||||||
| @@ -149,7 +149,7 @@ | |||||||
|           {#if delete_triggered} |           {#if delete_triggered} | ||||||
|             <button |             <button | ||||||
|               on:click={deleteRunner} |               on:click={deleteRunner} | ||||||
|               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" |               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:w-auto sm:text-sm" | ||||||
|               >{$_("confirm-deletion")}</button |               >{$_("confirm-deletion")}</button | ||||||
|             > |             > | ||||||
|             <button |             <button | ||||||
| @@ -175,7 +175,7 @@ | |||||||
|                 delete_triggered = true; |                 delete_triggered = true; | ||||||
|               }} |               }} | ||||||
|               type="button" |               type="button" | ||||||
|               class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm" |               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:w-auto sm:text-sm" | ||||||
|               >{$_("delete-runner")}</button |               >{$_("delete-runner")}</button | ||||||
|             > |             > | ||||||
|           {/if} |           {/if} | ||||||
| @@ -186,7 +186,7 @@ | |||||||
|             class:opacity-50={!save_enabled} |             class:opacity-50={!save_enabled} | ||||||
|             type="button" |             type="button" | ||||||
|             on:click={submit} |             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" |             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:w-auto sm:text-sm" | ||||||
|             >{$_("save-changes")}</button |             >{$_("save-changes")}</button | ||||||
|           > |           > | ||||||
|         {/if} |         {/if} | ||||||
|   | |||||||
| @@ -11,29 +11,29 @@ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <section class="container p-5"> | <section class="container p-5"> | ||||||
|   <span class="mb-1 text-3xl font-extrabold leading-tight"> |   <h4 class="mb-1 text-3xl font-extrabold leading-tight font-mono"> | ||||||
|     {$_("runners")} |     {$_("runners")} | ||||||
|     {#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:CREATE")} |   </h4> | ||||||
|       <button |   {#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER: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" | ||||||
|       > |       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:w-auto sm:text-sm mt-1 sm:mt-0" | ||||||
|         {$_("laeufer-hinzufuegen")} |     > | ||||||
|       </button> |       {$_("laeufer-hinzufuegen")} | ||||||
|       <button |     </button> | ||||||
|         on:click={() => { |     <button | ||||||
|           import_modal_open = true; |       on:click={() => { | ||||||
|         }} |         import_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" | ||||||
|       > |       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:w-auto sm:text-sm mt-1 sm:mt-0" | ||||||
|         {$_("import-runners")} |     > | ||||||
|       </button> |       {$_("import-runners")} | ||||||
|     {/if} |     </button> | ||||||
|   </span> |   {/if} | ||||||
|   <RunnersOverview bind:current_runners bind:addRunners /> |   <RunnersOverview bind:current_runners bind:addRunners /> | ||||||
| </section> | </section> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -9,20 +9,20 @@ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <section class="container p-5"> | <section class="container p-5"> | ||||||
|   <span class="mb-1 text-3xl font-extrabold leading-tight"> |   <h4 class="mb-1 text-3xl font-extrabold leading-tight font-mono"> | ||||||
|     {$_("scans")} |     {$_("scans")} | ||||||
|     {#if store.state.jwtinfo.userdetails.permissions.includes("SCAN:CREATE")} |   </h4> | ||||||
|       <button |   {#if store.state.jwtinfo.userdetails.permissions.includes("SCAN: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" | ||||||
|       > |       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:w-auto sm:text-sm" | ||||||
|         {$_("add-scan")} |     > | ||||||
|       </button> |       {$_("add-scan")} | ||||||
|     {/if} |     </button> | ||||||
|   </span> |   {/if} | ||||||
|   <ScansOverview bind:current_scans bind:addScans /> |   <ScansOverview bind:current_scans bind:addScans /> | ||||||
| </section> | </section> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
|  |  | ||||||
| <div class="text-center items-center justify-center"> | <div class="text-center items-center justify-center"> | ||||||
|   <p class="mb-16 text-lg text-gray-500"> |   <p class="mb-16 text-lg text-gray-500"> | ||||||
|     <img class="m-auto" style="height:15rem" src={scans_empty} alt="" /> |     <img class="m-auto mt-2" style="height:15rem" src={scans_empty} alt="" /> | ||||||
|     <span class="font-bold">{$_("there-are-no-scans-yet")}</span><br /> |     <span class="font-bold">{$_("there-are-no-scans-yet")}</span><br /> | ||||||
|     <span>{$_("add-your-fist-scan")}</span> |     <span>{$_("add-your-fist-scan")}</span> | ||||||
|   </p> |   </p> | ||||||
|   | |||||||
| @@ -220,7 +220,7 @@ | |||||||
|     {#if selected.length > 0} |     {#if selected.length > 0} | ||||||
|       <button |       <button | ||||||
|         type="button" |         type="button" | ||||||
|         class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm inline-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:w-auto sm:text-sm inline-flex" | ||||||
|         id="options-menu" |         id="options-menu" | ||||||
|         on:click={async () => { |         on:click={async () => { | ||||||
|           const prom = []; |           const prom = []; | ||||||
|   | |||||||
| @@ -1,200 +1,199 @@ | |||||||
| <script> | <script> | ||||||
|   import { _ } from "svelte-i18n"; | 	import { _ } from "svelte-i18n"; | ||||||
|  | 	import { tick } from "svelte"; | ||||||
|  | 	import bwipjs from "bwip-js"; | ||||||
|  | 	import toast from "svelte-french-toast"; | ||||||
|  |  | ||||||
|   import { tick, createEventDispatcher } from "svelte"; | 	export let copy_modal_open; | ||||||
|   import bwipjs from "bwip-js"; | 	export let new_station; | ||||||
|  | 	let valueCopy = null; | ||||||
|  | 	let areaDom; | ||||||
|  | 	let copied = false; | ||||||
|  | 	$: is_qrcode = false; | ||||||
|  | 	$: barcode = textToBase64Barcode(new_station.key, is_qrcode); | ||||||
|  |  | ||||||
|   export let copy_modal_open; | 	function close() { | ||||||
|   export let new_station; | 		copy_modal_open = false; | ||||||
|   const dispatch = createEventDispatcher(); | 	} | ||||||
|   let valueCopy = null; | 	async function copy() { | ||||||
|   let areaDom; | 		valueCopy = new_station.key; | ||||||
|   let copied = false; | 		await tick(); | ||||||
|   $: is_qrcode = false; | 		areaDom.focus(); | ||||||
|   $: barcode = textToBase64Barcode(new_station.key, is_qrcode); | 		areaDom.select(); | ||||||
|  | 		try { | ||||||
|  | 			const successful = document.execCommand("copy"); | ||||||
|  | 			if (!successful) { | ||||||
|  | 				throw new Error(); | ||||||
|  | 			} | ||||||
|  | 			toast($_("copied-token-to-clipboard")); | ||||||
|  | 			copied = true; | ||||||
|  | 		} catch (err) { | ||||||
|  | 			toast.Error($_("error-whyile-copying-to-clipboard")); | ||||||
|  | 		} | ||||||
|  | 		// we can notify by event or storage about copy status | ||||||
|  | 		valueCopy = null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|   function close() { | 	function textToBase64Barcode(text, is_qrcode) { | ||||||
|     copy_modal_open = false; | 		const canvas = document.createElement("canvas"); | ||||||
|   } | 		let bcid = "code128"; | ||||||
|   async function copy() { | 		if (is_qrcode) { | ||||||
|     valueCopy = new_station.key; | 			bcid = "qrcode"; | ||||||
|     await tick(); | 		} | ||||||
|     areaDom.focus(); | 		let codeconfig = { | ||||||
|     areaDom.select(); | 			bcid, | ||||||
|     try { | 			text: `${text}`, | ||||||
|       const successful = document.execCommand("copy"); | 			scale: 4, | ||||||
|       if (!successful) { | 			includetext: true, | ||||||
|         throw new Error(); | 			textxalign: "center", | ||||||
|       } | 			backgroundcolor: "ffffff", | ||||||
|       toast($_("copied-token-to-clipboard")); | 		}; | ||||||
|       copied = true; | 		if (bcid == "code128") { | ||||||
|     } catch (err) { | 			codeconfig.height = 10; | ||||||
|       toast.Error($_("error-whyile-copying-to-clipboard")); | 		} | ||||||
|     } | 		bwipjs.toCanvas(canvas, codeconfig); | ||||||
|     // we can notify by event or storage about copy status | 		return canvas.toDataURL("image/png"); | ||||||
|     valueCopy = null; | 	} | ||||||
|   } |  | ||||||
|  |  | ||||||
|   function textToBase64Barcode(text, is_qrcode) { |  | ||||||
|     const canvas = document.createElement("canvas"); |  | ||||||
|     let bcid = "code128"; |  | ||||||
|     if (is_qrcode) { |  | ||||||
|       bcid = "qrcode"; |  | ||||||
|     } |  | ||||||
|     let codeconfig = { |  | ||||||
|       bcid, |  | ||||||
|       text: `${text}`, |  | ||||||
|       scale: 4, |  | ||||||
|       includetext: true, |  | ||||||
|       textxalign: "center", |  | ||||||
|       backgroundcolor: "ffffff", |  | ||||||
|     }; |  | ||||||
|     if (bcid == "code128") { |  | ||||||
|       codeconfig.height = 10; |  | ||||||
|     } |  | ||||||
|     bwipjs.toCanvas(canvas, codeconfig); |  | ||||||
|     return canvas.toDataURL("image/png"); |  | ||||||
|   } |  | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| {#if copy_modal_open} | {#if copy_modal_open} | ||||||
|   {#if valueCopy != null} | 	{#if valueCopy != null} | ||||||
|     <textarea bind:this={areaDom}>{valueCopy}</textarea> | 		<textarea bind:this={areaDom}>{valueCopy}</textarea> | ||||||
|   {/if} | 	{/if} | ||||||
|   <div class="fixed z-10 inset-0 overflow-y-auto"> | 	<div class="fixed z-10 inset-0 overflow-y-auto"> | ||||||
|     <div | 		<div | ||||||
|       class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0" | 			class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0" | ||||||
|     > | 		> | ||||||
|       <div class="fixed inset-0 transition-opacity" aria-hidden="true"> | 			<div class="fixed inset-0 transition-opacity" aria-hidden="true"> | ||||||
|         <div | 				<div | ||||||
|           class="absolute inset-0 bg-gray-500 opacity-75" | 					class="absolute inset-0 bg-gray-500 opacity-75" | ||||||
|           data-id="modal_backdrop" | 					data-id="modal_backdrop" | ||||||
|         /> | 				/> | ||||||
|       </div> | 			</div> | ||||||
|       <span | 			<span | ||||||
|         class="hidden sm:inline-block sm:align-middle sm:h-screen" | 				class="hidden sm:inline-block sm:align-middle sm:h-screen" | ||||||
|         aria-hidden="true">​</span | 				aria-hidden="true">​</span | ||||||
|       > | 			> | ||||||
|       <div | 			<div | ||||||
|         class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full" | 				class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full" | ||||||
|         role="dialog" | 				role="dialog" | ||||||
|         aria-modal="true" | 				aria-modal="true" | ||||||
|         aria-labelledby="modal-headline" | 				aria-labelledby="modal-headline" | ||||||
|       > | 			> | ||||||
|         <div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4"> | 				<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="sm:flex sm:items-start"> | ||||||
|             <div | 						<div | ||||||
|               class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10" | 							class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10" | ||||||
|             > | 						> | ||||||
|               <svg | 							<svg | ||||||
|                 class="h-6 w-6 text-blue-600" | 								class="h-6 w-6 text-blue-600" | ||||||
|                 fill="currentColor" | 								fill="currentColor" | ||||||
|                 xmlns="http://www.w3.org/2000/svg" | 								xmlns="http://www.w3.org/2000/svg" | ||||||
|                 viewBox="0 0 24 24" | 								viewBox="0 0 24 24" | ||||||
|                 ><path fill="none" d="M0 0h24v24H0z" /> | 								><path fill="none" d="M0 0h24v24H0z" /> | ||||||
|                 <path | 								<path | ||||||
|                   d="M4 5v11h16V5H4zM2 4a1 1 0 011-1h18a1 1 0 011 1v14H2V4zM1 19h22v2H1v-2z" | 									d="M4 5v11h16V5H4zM2 4a1 1 0 011-1h18a1 1 0 011 1v14H2V4zM1 19h22v2H1v-2z" | ||||||
|                 /></svg | 								/></svg | ||||||
|               > | 							> | ||||||
|             </div> | 						</div> | ||||||
|             <div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left"> | 						<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left"> | ||||||
|               <h3 class="text-lg leading-6 font-medium text-gray-900"> | 							<h3 class="text-lg leading-6 font-medium text-gray-900"> | ||||||
|                 {$_("token")} | 								{$_("token")} | ||||||
|               </h3> | 							</h3> | ||||||
|               <div class="mt-2 mb-6"> | 							<div class="mt-2 mb-6"> | ||||||
|                 <p class="text-sm text-gray-500"> | 								<p class="text-sm text-gray-500"> | ||||||
|                   {$_( | 									{$_( | ||||||
|                     "the-scanstations-api-token-will-only-get-displayed-once-you-wont-be-able-to-change-or-view-it-again" | 										"the-scanstations-api-token-will-only-get-displayed-once-you-wont-be-able-to-change-or-view-it-again" | ||||||
|                   )} | 									)} | ||||||
|                   <br /> | 									<br /> | ||||||
|                   {$_("please-copy-the-token-and-store-it-somewhere-save")} | 									{$_("please-copy-the-token-and-store-it-somewhere-save")} | ||||||
|                 </p> | 								</p> | ||||||
|               </div> | 							</div> | ||||||
|               <div class="mt-2 mb-6"> | 							<div class="mt-2 mb-6"> | ||||||
|                 <label | 								<label | ||||||
|                   for="token" | 									for="token" | ||||||
|                   class="block text-sm font-medium text-gray-700" | 									class="block text-sm font-medium text-gray-700" | ||||||
|                   >{$_("token")}</label | 									>{$_("token")}</label | ||||||
|                 > | 								> | ||||||
|                 <button on:click={copy} class="inline-flex"> | 								<button on:click={copy} class="inline-flex"> | ||||||
|                   <p | 									<p | ||||||
|                     name="token" | 										name="token" | ||||||
|                     class:bg-green-200={copied} | 										class:bg-green-200={copied} | ||||||
|                     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 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 p-2" | ||||||
|                   > | 									> | ||||||
|                     {new_station.key} | 										{new_station.key} | ||||||
|                   </p> | 									</p> | ||||||
|                   <div | 									<div | ||||||
|                     class="bg-gray-200 border-gray-300 border-t border-b border-r text-black rounded-r-md sm:text-sm p-2 mt-1 cursor-pointer" | 										class="bg-gray-200 border-gray-300 border-t border-b border-r text-black rounded-r-md sm:text-sm p-2 mt-1 cursor-pointer" | ||||||
|                   > | 									> | ||||||
|                     <svg | 										<svg | ||||||
|                       xmlns="http://www.w3.org/2000/svg" | 											xmlns="http://www.w3.org/2000/svg" | ||||||
|                       viewBox="0 0 24 24" | 											viewBox="0 0 24 24" | ||||||
|                       width="24" | 											width="24" | ||||||
|                       height="24" | 											height="24" | ||||||
|                       ><path fill="none" d="M0 0h24v24H0z" /> | 											><path fill="none" d="M0 0h24v24H0z" /> | ||||||
|                       <path | 											<path | ||||||
|                         fill="currentColor" | 												fill="currentColor" | ||||||
|                         d="M7 4V2h10v2h3l1 1v16a1 1 0 01-1 1H4a1 1 0 01-1-1V5l1-1h3zm0 2H5v14h14V6h-2v2H7V6zm2-2v2h6V4H9z" | 												d="M7 4V2h10v2h3l1 1v16a1 1 0 01-1 1H4a1 1 0 01-1-1V5l1-1h3zm0 2H5v14h14V6h-2v2H7V6zm2-2v2h6V4H9z" | ||||||
|                       /></svg | 											/></svg | ||||||
|                     > | 										> | ||||||
|                   </div> | 									</div> | ||||||
|                 </button> | 								</button> | ||||||
|                 <p class="text-gray-500 text-xs"> | 								<p class="text-gray-500 text-xs"> | ||||||
|                   {$_("click-to-copy-token-to-clipboard")} | 									{$_("click-to-copy-token-to-clipboard")} | ||||||
|                 </p> | 								</p> | ||||||
|               </div> | 							</div> | ||||||
|             </div> | 						</div> | ||||||
|           </div> | 					</div> | ||||||
|           <div class="mx-auto text-center items-center"> | 					<div class="mx-auto text-center items-center"> | ||||||
|             <h2 class="text-lg leading-6 font-medium text-gray-900"> | 						<h2 class="text-lg leading-6 font-medium text-gray-900"> | ||||||
|               {$_("config-codes")} | 							{$_("config-codes")} | ||||||
|             </h2> | 						</h2> | ||||||
|             <span class="flex items-center text-center"> | 						<span class="flex items-center text-center"> | ||||||
|               <p class="text-md text-gray-900 mr-3">Format:</p> | 							<p class="text-md text-gray-900 mr-3">Format:</p> | ||||||
|               <label for="codeswitch" class="text-md text-gray-900 mr-3" | 							<label for="codeswitch" class="text-md text-gray-900 mr-3" | ||||||
|                 >Code128</label | 								>Code128</label | ||||||
|               > | 							> | ||||||
|               <input | 							<input | ||||||
|                 id="codeswitch" | 								id="codeswitch" | ||||||
|                 type="checkbox" | 								type="checkbox" | ||||||
|                 bind:checked={is_qrcode} | 								bind:checked={is_qrcode} | ||||||
|                 class="relative shrink-0 w-[3.25rem] h-7 bg-gray-100 checked:bg-none checked:bg-blue-600 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 ring-1 ring-transparent focus:border-blue-600 focus:ring-blue-600 ring-offset-white focus:outline-none appearance-none before:inline-block before:w-6 before:h-6 before:bg-white checked:before:bg-blue-200 before:translate-x-0 checked:before:translate-x-full before:shadow before:rounded-full before:transform before:ring-0 before:transition before:ease-in-out before:duration-200" | 								class="relative shrink-0 w-[3.25rem] h-7 bg-gray-100 checked:bg-none checked:bg-blue-600 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 ring-1 ring-transparent focus:border-blue-600 focus:ring-blue-600 ring-offset-white focus:outline-none appearance-none before:inline-block before:w-6 before:h-6 before:bg-white checked:before:bg-blue-200 before:translate-x-0 checked:before:translate-x-full before:shadow before:rounded-full before:transform before:ring-0 before:transition before:ease-in-out before:duration-200" | ||||||
|               /> | 							/> | ||||||
|               <label for="codeswitch" class="text-md text-gray-900 ml-3" | 							<label for="codeswitch" class="text-md text-gray-900 ml-3" | ||||||
|                 >QR-Code</label | 								>QR-Code</label | ||||||
|               > | 							> | ||||||
|             </span> | 						</span> | ||||||
|             <h3 class="leading-6 font-medium text-gray-900"> | 						<h3 class="leading-6 font-medium text-gray-900"> | ||||||
|               {$_("api-endpoint")} | 							{$_("api-endpoint")} | ||||||
|             </h3> | 						</h3> | ||||||
|             <img | 						<img | ||||||
|               class:w-[50%]={is_qrcode} | 							class:w-[50%]={is_qrcode} | ||||||
|               class:w-full={!is_qrcode} | 							class:w-full={!is_qrcode} | ||||||
|               class="md:w-auto mb-2 mx-auto" | 							class="md:w-auto mb-2 mx-auto" | ||||||
|               alt="Registrierungscode" | 							alt="Registrierungscode" | ||||||
|               src={textToBase64Barcode(window.config.baseurl, is_qrcode)} | 							src={textToBase64Barcode(window.config.baseurl, is_qrcode)} | ||||||
|             /> | 						/> | ||||||
|             <h3 class="leading-6 font-medium text-gray-900">{$_("token")}</h3> | 						<h3 class="leading-6 font-medium text-gray-900">{$_("token")}</h3> | ||||||
|             <img | 						<img | ||||||
|               class:w-[50%]={is_qrcode} | 							class:w-[50%]={is_qrcode} | ||||||
|               class:w-full={!is_qrcode} | 							class:w-full={!is_qrcode} | ||||||
|               class="md:w-auto mb-2 mx-auto" | 							class="md:w-auto mb-2 mx-auto" | ||||||
|               alt="Registrierungscode" | 							alt="Registrierungscode" | ||||||
|               src={barcode} | 							src={barcode} | ||||||
|             /> | 						/> | ||||||
|           </div> | 					</div> | ||||||
|         </div> | 				</div> | ||||||
|         <div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse"> | 				<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse"> | ||||||
|           <button | 					<button | ||||||
|             on:click={close} | 						on:click={close} | ||||||
|             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-green-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-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-green-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm" | ||||||
|           > | 					> | ||||||
|             {$_("yes-i-copied-the-token")} | 						{$_("yes-i-copied-the-token")} | ||||||
|           </button> | 					</button> | ||||||
|         </div> | 				</div> | ||||||
|       </div> | 			</div> | ||||||
|     </div> | 		</div> | ||||||
|   </div> | 	</div> | ||||||
| {/if} | {/if} | ||||||
|   | |||||||
| @@ -111,7 +111,7 @@ | |||||||
|           {#if delete_triggered} |           {#if delete_triggered} | ||||||
|             <button |             <button | ||||||
|               on:click={deleteStation} |               on:click={deleteStation} | ||||||
|               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" |               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:w-auto sm:text-sm" | ||||||
|               >{$_("confirm-deletion")}</button |               >{$_("confirm-deletion")}</button | ||||||
|             > |             > | ||||||
|             <button |             <button | ||||||
| @@ -128,7 +128,7 @@ | |||||||
|                 delete_triggered = true; |                 delete_triggered = true; | ||||||
|               }} |               }} | ||||||
|               type="button" |               type="button" | ||||||
|               class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm" |               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:w-auto sm:text-sm" | ||||||
|               >{$_("delete-station")}</button |               >{$_("delete-station")}</button | ||||||
|             > |             > | ||||||
|           {/if} |           {/if} | ||||||
| @@ -139,7 +139,7 @@ | |||||||
|             class:opacity-50={!save_enabled} |             class:opacity-50={!save_enabled} | ||||||
|             type="button" |             type="button" | ||||||
|             on:click={submit} |             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" |             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:w-auto sm:text-sm" | ||||||
|             >{$_("save-changes")}</button |             >{$_("save-changes")}</button | ||||||
|           > |           > | ||||||
|         {/if} |         {/if} | ||||||
|   | |||||||
| @@ -1,44 +1,229 @@ | |||||||
| <script> | <script> | ||||||
|   import { _ } from "svelte-i18n"; | 	import { _ } from "svelte-i18n"; | ||||||
|   import store from "../../store"; | 	import store from "../../store"; | ||||||
|   import AddScanStationModal from "./AddScanStationModal.svelte"; | 	import { ScanStationService } from "@odit/lfk-client-js"; | ||||||
|   import CopyScanStationTokenModal from "./CopyScanStationTokenModal.svelte"; | 	import AddScanStationModal from "./AddScanStationModal.svelte"; | ||||||
|   import ScanStationsOverview from "./ScanStationsOverview.svelte"; | 	import CopyScanStationTokenModal from "./CopyScanStationTokenModal.svelte"; | ||||||
|   export let modal_open = false; | 	import ScanStationsEmptyState from "./ScanStationsEmptyState.svelte"; | ||||||
|   export let copy_modal_open = false; | 	import ConfirmScanStationDeletion from "./ConfirmScanStationDeletion.svelte"; | ||||||
|   export let new_station = {}; | 	import toast from "svelte-french-toast"; | ||||||
|   let current_stations = []; | 	// | ||||||
|  | 	export let modal_open = false; | ||||||
|  | 	export let copy_modal_open = false; | ||||||
|  | 	export let new_station = {}; | ||||||
|  | 	// | ||||||
|  | 	const promise = ScanStationService.scanStationControllerGetAll().then( | ||||||
|  | 		(result) => { | ||||||
|  | 			current_stations = result; | ||||||
|  | 		} | ||||||
|  | 	); | ||||||
|  | 	$: searchvalue = ""; | ||||||
|  | 	$: active_deletes = []; | ||||||
|  | 	let delete_station = {}; | ||||||
|  | 	let current_stations = []; | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <section class="container p-5"> | <section class="container p-5"> | ||||||
|   <span class="mb-1 text-3xl font-extrabold leading-tight"> | 	<h4 class="mb-1 text-3xl font-extrabold leading-tight font-mono"> | ||||||
|     {$_("scanstations")} | 		{$_("scanstations")} | ||||||
|     {#if store.state.jwtinfo.userdetails.permissions.includes("STATION:CREATE")} | 	</h4> | ||||||
|       <button | 	{#if store.state.jwtinfo.userdetails.permissions.includes("STATION: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" | ||||||
|       > | 			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:w-auto sm:text-sm" | ||||||
|         {$_("create-a-new-scanstation")} | 		> | ||||||
|       </button> | 			{$_("create-a-new-scanstation")} | ||||||
|     {/if} | 		</button> | ||||||
|   </span> | 	{/if} | ||||||
|   <ScanStationsOverview | 	<ConfirmScanStationDeletion | ||||||
|     bind:current_stations | 		on:cancelDelete={(event) => { | ||||||
|     bind:modal_open | 			modal_open = false; | ||||||
|     bind:new_station | 			active_deletes[event.detail.id] = false; | ||||||
|     bind:copy_modal_open | 		}} | ||||||
|   /> | 		bind:modal_open | ||||||
|  | 		bind:delete_station | ||||||
|  | 	/> | ||||||
|  | 	{#if store.state.jwtinfo.userdetails.permissions.includes("STATION: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">{$_("scanstations-are-being-loaded")}</p> | ||||||
|  | 				<p class="text-sm">{$_("this-might-take-a-moment")}</p> | ||||||
|  | 			</div> | ||||||
|  | 		{:then} | ||||||
|  | 			{#if current_stations.length === 0} | ||||||
|  | 				<ScanStationsEmptyState /> | ||||||
|  | 			{:else} | ||||||
|  | 				<input | ||||||
|  | 					type="search" | ||||||
|  | 					bind:value={searchvalue} | ||||||
|  | 					placeholder={$_("datatable.search")} | ||||||
|  | 					aria-label={$_("datatable.search")} | ||||||
|  | 					class="mb-2 w-full sm:w-auto mt-1 sm:mt-0 p-2 rounded-md border" | ||||||
|  | 				/> | ||||||
|  | 				<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 class="odd:bg-white even:bg-gray-100"> | ||||||
|  | 								<th | ||||||
|  | 									scope="col" | ||||||
|  | 									class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" | ||||||
|  | 								> | ||||||
|  | 									{$_("track")} | ||||||
|  | 								</th> | ||||||
|  | 								<th | ||||||
|  | 									scope="col" | ||||||
|  | 									class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" | ||||||
|  | 								> | ||||||
|  | 									{$_("description")} | ||||||
|  | 								</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="relative px-6 py-3"> | ||||||
|  | 									<span class="sr-only">{$_("action")}</span> | ||||||
|  | 								</th> | ||||||
|  | 							</tr> | ||||||
|  | 						</thead> | ||||||
|  | 						<tbody class="divide-y divide-gray-200"> | ||||||
|  | 							{#each current_stations as s} | ||||||
|  | 								{#if Object.values(s) | ||||||
|  | 									.toString() | ||||||
|  | 									.toLowerCase() | ||||||
|  | 									.includes(searchvalue)} | ||||||
|  | 									<tr | ||||||
|  | 										class="odd:bg-white even:bg-gray-100" | ||||||
|  | 										data-rowid="station_{s.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"> | ||||||
|  | 														<a | ||||||
|  | 															href="../tracks" | ||||||
|  | 															class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800" | ||||||
|  | 														> | ||||||
|  | 															{s.track.name || s.track.distance + "m"}</a | ||||||
|  | 														> | ||||||
|  | 													</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"> | ||||||
|  | 														{s.description} | ||||||
|  | 													</div> | ||||||
|  | 												</div> | ||||||
|  | 											</div> | ||||||
|  | 										</td> | ||||||
|  | 										<td class="px-6 py-4 whitespace-nowrap"> | ||||||
|  | 											<div class="flex items-center"> | ||||||
|  | 												{#if s.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} | ||||||
|  | 											</div> | ||||||
|  | 										</td> | ||||||
|  | 										{#if active_deletes[s.id] === true} | ||||||
|  | 											<td | ||||||
|  | 												class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium" | ||||||
|  | 											> | ||||||
|  | 												<button | ||||||
|  | 													on:click={() => { | ||||||
|  | 														active_deletes[s.id] = false; | ||||||
|  | 													}} | ||||||
|  | 													tabindex="0" | ||||||
|  | 													class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer" | ||||||
|  | 													>{$_("cancel-delete")}</button | ||||||
|  | 												> | ||||||
|  | 												<button | ||||||
|  | 													on:click={() => { | ||||||
|  | 														ScanStationService.scanStationControllerRemove( | ||||||
|  | 															s.id, | ||||||
|  | 															false | ||||||
|  | 														) | ||||||
|  | 															.then((resp) => { | ||||||
|  | 																current_stations = current_stations.filter( | ||||||
|  | 																	(obj) => obj.id !== s.id | ||||||
|  | 																); | ||||||
|  | 																toast($_("station-deleted")); | ||||||
|  | 															}) | ||||||
|  | 															.catch((err) => { | ||||||
|  | 																modal_open = true; | ||||||
|  | 																delete_station = s; | ||||||
|  | 															}); | ||||||
|  | 													}} | ||||||
|  | 													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="/scanstations/{s.id}" | ||||||
|  | 													class="text-indigo-600 hover:text-indigo-900" | ||||||
|  | 													>{$_("details")}</a | ||||||
|  | 												> | ||||||
|  | 												{#if store.state.jwtinfo.userdetails.permissions.includes("STATION:DELETE")} | ||||||
|  | 													<button | ||||||
|  | 														on:click={() => { | ||||||
|  | 															active_deletes[s.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} | ||||||
| </section> | </section> | ||||||
|  |  | ||||||
| {#if store.state.jwtinfo.userdetails.permissions.includes("STATION:CREATE")} | {#if store.state.jwtinfo.userdetails.permissions.includes("STATION:CREATE")} | ||||||
|   <AddScanStationModal | 	<AddScanStationModal | ||||||
|     bind:modal_open | 		bind:modal_open | ||||||
|     bind:current_stations | 		bind:current_stations | ||||||
|     bind:new_station | 		bind:new_station | ||||||
|     bind:copy_modal_open | 		bind:copy_modal_open | ||||||
|   /> | 	/> | ||||||
|   <CopyScanStationTokenModal bind:copy_modal_open bind:new_station /> | 	<CopyScanStationTokenModal bind:copy_modal_open bind:new_station /> | ||||||
| {/if} | {/if} | ||||||
|   | |||||||
| @@ -1,195 +0,0 @@ | |||||||
| <script> |  | ||||||
|   import { _ } from "svelte-i18n"; |  | ||||||
|   import { ScanStationService } from "@odit/lfk-client-js"; |  | ||||||
|   const promise = ScanStationService.scanStationControllerGetAll().then( |  | ||||||
|     (result) => { |  | ||||||
|       current_stations = result; |  | ||||||
|     } |  | ||||||
|   ); |  | ||||||
|   import store from "../../store"; |  | ||||||
|   import ScanStationsEmptyState from "./ScanStationsEmptyState.svelte"; |  | ||||||
|   import ConfirmScanStationDeletion from "./ConfirmScanStationDeletion.svelte"; |  | ||||||
|   import toast from "svelte-french-toast"; |  | ||||||
|   $: searchvalue = ""; |  | ||||||
|   $: active_deletes = []; |  | ||||||
|   let delete_station = {}; |  | ||||||
|   let modal_open = false; |  | ||||||
|   export let current_stations = []; |  | ||||||
| </script> |  | ||||||
|  |  | ||||||
| <ConfirmScanStationDeletion |  | ||||||
|   on:cancelDelete={(event) => { |  | ||||||
|     modal_open = false; |  | ||||||
|     active_deletes[event.detail.id] = false; |  | ||||||
|   }} |  | ||||||
|   bind:modal_open |  | ||||||
|   bind:delete_station |  | ||||||
| /> |  | ||||||
| {#if store.state.jwtinfo.userdetails.permissions.includes("STATION: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">{$_("scanstations-are-being-loaded")}</p> |  | ||||||
|       <p class="text-sm">{$_("this-might-take-a-moment")}</p> |  | ||||||
|     </div> |  | ||||||
|   {:then} |  | ||||||
|     {#if current_stations.length === 0} |  | ||||||
|       <ScanStationsEmptyState /> |  | ||||||
|     {:else} |  | ||||||
|       <input |  | ||||||
|         type="search" |  | ||||||
|         bind:value={searchvalue} |  | ||||||
|         placeholder={$_("datatable.search")} |  | ||||||
|         aria-label={$_("datatable.search")} |  | ||||||
|         class="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 class="odd:bg-white even:bg-gray-100"> |  | ||||||
|               <th |  | ||||||
|                 scope="col" |  | ||||||
|                 class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" |  | ||||||
|               > |  | ||||||
|                 {$_("track")} |  | ||||||
|               </th> |  | ||||||
|               <th |  | ||||||
|                 scope="col" |  | ||||||
|                 class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" |  | ||||||
|               > |  | ||||||
|                 {$_("description")} |  | ||||||
|               </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="relative px-6 py-3"> |  | ||||||
|                 <span class="sr-only">{$_("action")}</span> |  | ||||||
|               </th> |  | ||||||
|             </tr> |  | ||||||
|           </thead> |  | ||||||
|           <tbody class="divide-y divide-gray-200"> |  | ||||||
|             {#each current_stations as s} |  | ||||||
|               {#if Object.values(s) |  | ||||||
|                 .toString() |  | ||||||
|                 .toLowerCase() |  | ||||||
|                 .includes(searchvalue)} |  | ||||||
|                 <tr |  | ||||||
|                   class="odd:bg-white even:bg-gray-100" |  | ||||||
|                   data-rowid="station_{s.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"> |  | ||||||
|                           <a |  | ||||||
|                             href="../tracks" |  | ||||||
|                             class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800" |  | ||||||
|                           > |  | ||||||
|                             {s.track.name || s.track.distance + "m"}</a |  | ||||||
|                           > |  | ||||||
|                         </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"> |  | ||||||
|                           {s.description} |  | ||||||
|                         </div> |  | ||||||
|                       </div> |  | ||||||
|                     </div> |  | ||||||
|                   </td> |  | ||||||
|                   <td class="px-6 py-4 whitespace-nowrap"> |  | ||||||
|                     <div class="flex items-center"> |  | ||||||
|                       {#if s.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} |  | ||||||
|                     </div> |  | ||||||
|                   </td> |  | ||||||
|                   {#if active_deletes[s.id] === true} |  | ||||||
|                     <td |  | ||||||
|                       class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium" |  | ||||||
|                     > |  | ||||||
|                       <button |  | ||||||
|                         on:click={() => { |  | ||||||
|                           active_deletes[s.id] = false; |  | ||||||
|                         }} |  | ||||||
|                         tabindex="0" |  | ||||||
|                         class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer" |  | ||||||
|                         >{$_("cancel-delete")}</button |  | ||||||
|                       > |  | ||||||
|                       <button |  | ||||||
|                         on:click={() => { |  | ||||||
|                           ScanStationService.scanStationControllerRemove( |  | ||||||
|                             s.id, |  | ||||||
|                             false |  | ||||||
|                           ) |  | ||||||
|                             .then((resp) => { |  | ||||||
|                               current_stations = current_stations.filter( |  | ||||||
|                                 (obj) => obj.id !== s.id |  | ||||||
|                               ); |  | ||||||
|                               toast($_("station-deleted")); |  | ||||||
|                             }) |  | ||||||
|                             .catch((err) => { |  | ||||||
|                               modal_open = true; |  | ||||||
|                               delete_station = s; |  | ||||||
|                             }); |  | ||||||
|                         }} |  | ||||||
|                         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="/scanstations/{s.id}" |  | ||||||
|                         class="text-indigo-600 hover:text-indigo-900" |  | ||||||
|                         >{$_("details")}</a |  | ||||||
|                       > |  | ||||||
|                       {#if store.state.jwtinfo.userdetails.permissions.includes("STATION:DELETE")} |  | ||||||
|                         <button |  | ||||||
|                           on:click={() => { |  | ||||||
|                             active_deletes[s.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} |  | ||||||
| @@ -2,6 +2,7 @@ | |||||||
|   import { _ } from "svelte-i18n"; |   import { _ } from "svelte-i18n"; | ||||||
|   import isEmail from "validator/es/lib/isEmail"; |   import isEmail from "validator/es/lib/isEmail"; | ||||||
|   import { MeService } from "@odit/lfk-client-js"; |   import { MeService } from "@odit/lfk-client-js"; | ||||||
|  |   import toast from 'svelte-french-toast' | ||||||
|  |  | ||||||
|   import ConfirmProfileDeletion from "./ConfirmProfileDeletion.svelte"; |   import ConfirmProfileDeletion from "./ConfirmProfileDeletion.svelte"; | ||||||
|   import PasswordStrength, { |   import PasswordStrength, { | ||||||
| @@ -168,7 +169,7 @@ | |||||||
|                   disabled={!save_enabled} |                   disabled={!save_enabled} | ||||||
|                   class:opacity-50={!save_enabled} |                   class:opacity-50={!save_enabled} | ||||||
|                   on:click={submit} |                   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" |                   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:w-auto sm:text-sm" | ||||||
|                 > |                 > | ||||||
|                   {$_("save-changes")} |                   {$_("save-changes")} | ||||||
|                 </button> |                 </button> | ||||||
| @@ -232,7 +233,7 @@ | |||||||
|                   disabled={!update_password_enabled} |                   disabled={!update_password_enabled} | ||||||
|                   class:opacity-50={!update_password_enabled} |                   class:opacity-50={!update_password_enabled} | ||||||
|                   on:click={changePassword} |                   on:click={changePassword} | ||||||
|                   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" |                   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:w-auto sm:text-sm" | ||||||
|                 > |                 > | ||||||
|                   {$_("update-password")} |                   {$_("update-password")} | ||||||
|                 </button> |                 </button> | ||||||
|   | |||||||
| @@ -1,26 +1,26 @@ | |||||||
| <script> | <script> | ||||||
|   import { _ } from "svelte-i18n"; | 	import { _ } from "svelte-i18n"; | ||||||
|  |  | ||||||
|   export let detailsLink; | 	export let detailsLink = null; | ||||||
|   export let detailsAction; | 	export let detailsAction = null; | ||||||
|   export let deleteEnabled; | 	export let deleteEnabled; | ||||||
|   export let deleteAction; | 	export let deleteAction; | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| {#if detailsLink} | {#if detailsLink} | ||||||
|   <a href={detailsLink} class="text-indigo-600 hover:text-indigo-900" | 	<a href={detailsLink} class="text-indigo-600 hover:text-indigo-900" | ||||||
|     >{$_("details")}</a | 		>{$_("details")}</a | ||||||
|   > | 	> | ||||||
| {:else if detailsAction} | {:else if detailsAction} | ||||||
|   <button on:click={detailsAction} class="text-indigo-600 hover:text-indigo-900" | 	<button on:click={detailsAction} class="text-indigo-600 hover:text-indigo-900" | ||||||
|     >{$_("details")}</button | 		>{$_("details")}</button | ||||||
|   > | 	> | ||||||
| {/if} | {/if} | ||||||
| {#if deleteEnabled} | {#if deleteEnabled} | ||||||
|   <button | 	<button | ||||||
|     tabindex="0" | 		tabindex="0" | ||||||
|     on:click={deleteAction} | 		on:click={deleteAction} | ||||||
|     class="ml-4 text-red-600 hover:text-red-900 cursor-pointer" | 		class="ml-4 text-red-600 hover:text-red-900 cursor-pointer" | ||||||
|     >{$_("delete")}</button | 		>{$_("delete")}</button | ||||||
|   > | 	> | ||||||
| {/if} | {/if} | ||||||
|   | |||||||
| @@ -5,14 +5,14 @@ | |||||||
|   import { createEventDispatcher } from "svelte"; |   import { createEventDispatcher } from "svelte"; | ||||||
|   import toast from "svelte-french-toast"; |   import toast from "svelte-french-toast"; | ||||||
|   export let modal_open; |   export let modal_open; | ||||||
|   export let delete_station; |   export let delete_client; | ||||||
|   const dispatch = createEventDispatcher(); |   const dispatch = createEventDispatcher(); | ||||||
|   function cancelDelete() { |   function cancelDelete() { | ||||||
|     modal_open = false; |     modal_open = false; | ||||||
|     dispatch("cancelDelete", { id: delete_station.id }); |     dispatch("cancelDelete", { id: delete_client.id }); | ||||||
|   } |   } | ||||||
|   function deleteClient() { |   function deleteClient() { | ||||||
|     StatsClientService.statsClientControllerRemove(delete_station.id, true) |     StatsClientService.statsClientControllerRemove(delete_client.id, true) | ||||||
|       .then((resp) => { |       .then((resp) => { | ||||||
|         toast($_("statsclient-deleted")); |         toast($_("statsclient-deleted")); | ||||||
|         location.replace("./"); |         location.replace("./"); | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ | |||||||
|   import { tick, createEventDispatcher } from "svelte"; |   import { tick, createEventDispatcher } from "svelte"; | ||||||
|   export let copy_modal_open; |   export let copy_modal_open; | ||||||
|   export let new_client; |   export let new_client; | ||||||
|  |   import toast from 'svelte-french-toast' | ||||||
|   const dispatch = createEventDispatcher(); |   const dispatch = createEventDispatcher(); | ||||||
|   let valueCopy = null; |   let valueCopy = null; | ||||||
|   let areaDom; |   let areaDom; | ||||||
|   | |||||||
| @@ -82,7 +82,7 @@ | |||||||
|           {#if delete_triggered} |           {#if delete_triggered} | ||||||
|             <button |             <button | ||||||
|               on:click={deleteClient} |               on:click={deleteClient} | ||||||
|               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" |               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:w-auto sm:text-sm" | ||||||
|               >{$_("confirm-deletion")}</button |               >{$_("confirm-deletion")}</button | ||||||
|             > |             > | ||||||
|             <button |             <button | ||||||
| @@ -99,7 +99,7 @@ | |||||||
|                 delete_triggered = true; |                 delete_triggered = true; | ||||||
|               }} |               }} | ||||||
|               type="button" |               type="button" | ||||||
|               class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm" |               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:w-auto sm:text-sm" | ||||||
|               >{$_("delete-statsclient")}</button |               >{$_("delete-statsclient")}</button | ||||||
|             > |             > | ||||||
|           {/if} |           {/if} | ||||||
|   | |||||||
| @@ -1,44 +1,39 @@ | |||||||
| <script> | <script> | ||||||
|   import { _ } from "svelte-i18n"; | 	import { _ } from "svelte-i18n"; | ||||||
|   import store from "../../store"; | 	import store from "../../store"; | ||||||
|   import AddStatsClientModal from "./AddStatsClientModal.svelte"; | 	import AddStatsClientModal from "./AddStatsClientModal.svelte"; | ||||||
|   import CopyStatsClientTokenModal from "./CopyStatsClientTokenModal.svelte"; | 	import CopyStatsClientTokenModal from "./CopyStatsClientTokenModal.svelte"; | ||||||
|   import StatsClientsOverview from "./StatsClientsOverview.svelte"; | 	import StatsClientsOverview from "./StatsClientsOverview.svelte"; | ||||||
|   export let modal_open = false; | 	export let modal_open = false; | ||||||
|   export let copy_modal_open = false; | 	export let copy_modal_open = false; | ||||||
|   export let new_client = {}; | 	export let new_client = {}; | ||||||
|   let current_clients = []; | 	let current_clients = []; | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <section class="container p-5"> | <section class="container p-5"> | ||||||
|   <span class="mb-1 text-3xl font-extrabold leading-tight"> | 	<h4 class="mb-1 text-3xl font-extrabold leading-tight font-mono"> | ||||||
|     {$_("statsclients")} | 		{$_("statsclients")} | ||||||
|     {#if store.state.jwtinfo.userdetails.permissions.includes("STATSCLIENT:CREATE")} | 	</h4> | ||||||
|       <button | 	{#if store.state.jwtinfo.userdetails.permissions.includes("STATSCLIENT: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" | ||||||
|       > | 			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:w-auto sm:text-sm" | ||||||
|         {$_("create-a-new-statsclient")} | 		> | ||||||
|       </button> | 			{$_("create-a-new-statsclient")} | ||||||
|     {/if} | 		</button> | ||||||
|   </span> | 	{/if} | ||||||
|   <StatsClientsOverview | 	<StatsClientsOverview bind:current_clients /> | ||||||
|     bind:current_clients |  | ||||||
|     bind:modal_open |  | ||||||
|     bind:new_client |  | ||||||
|     bind:copy_modal_open |  | ||||||
|   /> |  | ||||||
| </section> | </section> | ||||||
|  |  | ||||||
| {#if store.state.jwtinfo.userdetails.permissions.includes("STATSCLIENT:CREATE")} | {#if store.state.jwtinfo.userdetails.permissions.includes("STATSCLIENT:CREATE")} | ||||||
|   <AddStatsClientModal | 	<AddStatsClientModal | ||||||
|     bind:modal_open | 		bind:modal_open | ||||||
|     bind:current_clients | 		bind:current_clients | ||||||
|     bind:new_client | 		bind:new_client | ||||||
|     bind:copy_modal_open | 		bind:copy_modal_open | ||||||
|   /> | 	/> | ||||||
|   <CopyStatsClientTokenModal bind:copy_modal_open bind:new_client /> | 	<CopyStatsClientTokenModal bind:copy_modal_open bind:new_client /> | ||||||
| {/if} | {/if} | ||||||
|   | |||||||
| @@ -43,7 +43,7 @@ | |||||||
|         bind:value={searchvalue} |         bind:value={searchvalue} | ||||||
|         placeholder={$_("datatable.search")} |         placeholder={$_("datatable.search")} | ||||||
|         aria-label={$_("datatable.search")} |         aria-label={$_("datatable.search")} | ||||||
|         class="mb-4" |         class="mb-2 w-full sm:w-auto mt-1 sm:mt-0 p-2 rounded-md border" | ||||||
|       /> |       /> | ||||||
|       <div |       <div | ||||||
|         class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll" |         class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll" | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ | |||||||
|     RunnerTeamService, |     RunnerTeamService, | ||||||
|   } from "@odit/lfk-client-js"; |   } from "@odit/lfk-client-js"; | ||||||
|   import { getLocaleFromNavigator, _ } from "svelte-i18n"; |   import { getLocaleFromNavigator, _ } from "svelte-i18n"; | ||||||
|  |   import toast from 'svelte-french-toast' | ||||||
|  |  | ||||||
|   import store from "../../store"; |   import store from "../../store"; | ||||||
|   import Select from "svelte-select"; |   import Select from "svelte-select"; | ||||||
| @@ -125,7 +126,7 @@ | |||||||
|               import_modal_open = true; |               import_modal_open = true; | ||||||
|             }} |             }} | ||||||
|             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:w-auto sm:text-sm" | ||||||
|           > |           > | ||||||
|             {$_("import-runners")} |             {$_("import-runners")} | ||||||
|           </button> |           </button> | ||||||
| @@ -134,7 +135,7 @@ | |||||||
|           {#if delete_triggered} |           {#if delete_triggered} | ||||||
|             <button |             <button | ||||||
|               on:click={deleteTeam} |               on:click={deleteTeam} | ||||||
|               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" |               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:w-auto sm:text-sm" | ||||||
|               >{$_("confirm-delete")}</button |               >{$_("confirm-delete")}</button | ||||||
|             > |             > | ||||||
|             <button |             <button | ||||||
| @@ -151,7 +152,7 @@ | |||||||
|                 delete_triggered = true; |                 delete_triggered = true; | ||||||
|               }} |               }} | ||||||
|               type="button" |               type="button" | ||||||
|               class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm" |               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:w-auto sm:text-sm" | ||||||
|               >{$_("delete-team")}</button |               >{$_("delete-team")}</button | ||||||
|             > |             > | ||||||
|           {/if} |           {/if} | ||||||
| @@ -162,7 +163,7 @@ | |||||||
|             disabled={!save_enabled} |             disabled={!save_enabled} | ||||||
|             class:opacity-50={!save_enabled} |             class:opacity-50={!save_enabled} | ||||||
|             type="button" |             type="button" | ||||||
|             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" |             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:w-auto sm:text-sm" | ||||||
|             >{$_("save-changes")}</button |             >{$_("save-changes")}</button | ||||||
|           > |           > | ||||||
|         {/if} |         {/if} | ||||||
| @@ -290,6 +291,13 @@ | |||||||
|         on:clear={() => (teamdata.parentGroup = null)} |         on:clear={() => (teamdata.parentGroup = null)} | ||||||
|       /> |       /> | ||||||
|     </div> |     </div> | ||||||
|  |     <div class="text-sm w-full"> | ||||||
|  |       <span class="font-medium text-gray-700">{$_("distance")}</span> | ||||||
|  |       <br /> | ||||||
|  |       <span class="text-gray-700" | ||||||
|  |         >{(original.total_distance / 1000).toFixed(2)} km</span | ||||||
|  |       > | ||||||
|  |     </div> | ||||||
|   </section> |   </section> | ||||||
| {:else} | {:else} | ||||||
|   {#await promise} |   {#await promise} | ||||||
|   | |||||||
| @@ -8,20 +8,20 @@ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <section class="container p-5"> | <section class="container p-5"> | ||||||
|   <span class="mb-1 text-3xl font-extrabold leading-tight"> |   <h4 class="mb-1 text-3xl font-extrabold leading-tight font-mono"> | ||||||
|     {$_("teams")} |     {$_("teams")} | ||||||
|     {#if store.state.jwtinfo.userdetails.permissions.includes("TEAM:CREATE")} |   </h4> | ||||||
|       <button |   {#if store.state.jwtinfo.userdetails.permissions.includes("TEAM: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" | ||||||
|       > |       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:w-auto sm:text-sm" | ||||||
|         {$_("create-team")} |     > | ||||||
|       </button> |       {$_("create-team")} | ||||||
|     {/if} |     </button> | ||||||
|   </span> |   {/if} | ||||||
|   <TeamsOverview bind:current_teams /> |   <TeamsOverview bind:current_teams /> | ||||||
| </section> | </section> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -54,7 +54,7 @@ | |||||||
|         bind:value={searchvalue} |         bind:value={searchvalue} | ||||||
|         placeholder={$_("datatable.search")} |         placeholder={$_("datatable.search")} | ||||||
|         aria-label={$_("datatable.search")} |         aria-label={$_("datatable.search")} | ||||||
|         class="mb-4" |         class="mb-2 w-full sm:w-auto mt-1 sm:mt-0 p-2 rounded-md border" | ||||||
|       /> |       /> | ||||||
|       <div class="h-12"> |       <div class="h-12"> | ||||||
|         <GenerateSponsoringContracts |         <GenerateSponsoringContracts | ||||||
|   | |||||||
| @@ -223,7 +223,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" | ||||||
|           > |           > | ||||||
|             Create |             {$_("create")} | ||||||
|           </button> |           </button> | ||||||
|           <button |           <button | ||||||
|             on:click={() => { |             on:click={() => { | ||||||
|   | |||||||
| @@ -19,18 +19,18 @@ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <section class="container p-5"> | <section class="container p-5"> | ||||||
|   <span class="mb-1 text-3xl font-extrabold leading-tight"> |   <h4 class="mb-1 text-3xl font-extrabold leading-tight font-mono"> | ||||||
|     Tracks |     {$_("tracks")} | ||||||
|     <button |   </h4> | ||||||
|       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" | ||||||
|     > |     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:w-auto sm:text-sm" | ||||||
|       {$_("create-track")} |   > | ||||||
|     </button> |     {$_("create-track")} | ||||||
|   </span> |   </button> | ||||||
|   {#await tracks_promise} |   {#await tracks_promise} | ||||||
|     <div |     <div | ||||||
|       class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2" |       class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2" | ||||||
|   | |||||||
| @@ -162,7 +162,7 @@ | |||||||
|           {#if delete_triggered} |           {#if delete_triggered} | ||||||
|             <button |             <button | ||||||
|               on:click={deleteUser} |               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" |               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:w-auto sm:text-sm" | ||||||
|               >{$_("confirm-delete")}</button |               >{$_("confirm-delete")}</button | ||||||
|             > |             > | ||||||
|             <button |             <button | ||||||
| @@ -179,7 +179,7 @@ | |||||||
|                 delete_triggered = true; |                 delete_triggered = true; | ||||||
|               }} |               }} | ||||||
|               type="button" |               type="button" | ||||||
|               class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm" |               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:w-auto sm:text-sm" | ||||||
|               >{$_("delete-user")}</button |               >{$_("delete-user")}</button | ||||||
|             > |             > | ||||||
|           {/if} |           {/if} | ||||||
| @@ -190,7 +190,7 @@ | |||||||
|             class:opacity-50={!save_enabled} |             class:opacity-50={!save_enabled} | ||||||
|             type="button" |             type="button" | ||||||
|             on:click={submit} |             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" |             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:w-auto sm:text-sm" | ||||||
|             >{$_("save-changes")}</button |             >{$_("save-changes")}</button | ||||||
|           > |           > | ||||||
|         {/if} |         {/if} | ||||||
|   | |||||||
| @@ -150,13 +150,13 @@ | |||||||
|             class:opacity-50={save_enabled} |             class:opacity-50={save_enabled} | ||||||
|             type="button" |             type="button" | ||||||
|             on:click={submit} |             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" |             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:w-auto sm:text-sm" | ||||||
|             >{$_("save-changes")}</button |             >{$_("save-changes")}</button | ||||||
|           > |           > | ||||||
|         {:else} |         {:else} | ||||||
|           <button |           <button | ||||||
|             type="button" |             type="button" | ||||||
|             class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-yellow-600 text-base font-medium text-white hover:bg-yellow-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-yellow-500 sm:ml-3 sm:w-auto sm:text-sm" |             class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-yellow-600 text-base font-medium text-white hover:bg-yellow-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-yellow-500 sm:w-auto sm:text-sm" | ||||||
|             >{$_("applying-changes")}</button |             >{$_("applying-changes")}</button | ||||||
|           > |           > | ||||||
|         {/if} |         {/if} | ||||||
| @@ -203,7 +203,7 @@ | |||||||
|                       } |                       } | ||||||
|                     }} |                     }} | ||||||
|                     type="button" |                     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" |                     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:w-auto sm:text-sm" | ||||||
|                     >+</button |                     >+</button | ||||||
|                   > |                   > | ||||||
|                 </p> |                 </p> | ||||||
| @@ -243,7 +243,7 @@ | |||||||
|                     } |                     } | ||||||
|                   }} |                   }} | ||||||
|                   type="button" |                   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" |                   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:w-auto sm:text-sm" | ||||||
|                   >-</button |                   >-</button | ||||||
|                 > |                 > | ||||||
|               </p> |               </p> | ||||||
|   | |||||||
| @@ -8,20 +8,20 @@ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <section class="container p-5"> | <section class="container p-5"> | ||||||
|   <span class="mb-1 text-3xl font-extrabold leading-tight"> |   <h4 class="mb-1 text-3xl font-extrabold leading-tight font-mono"> | ||||||
|     {$_("users")} |     {$_("users")} | ||||||
|     {#if store.state.jwtinfo.userdetails.permissions.includes("USER:CREATE")} |   </h4> | ||||||
|       <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" | ||||||
|       > |       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:w-auto sm:text-sm" | ||||||
|         {$_("create-user")} |     > | ||||||
|       </button> |       {$_("create-user")} | ||||||
|     {/if} |     </button> | ||||||
|   </span> |   {/if} | ||||||
|   <UsersOverview bind:current_users /> |   <UsersOverview bind:current_users /> | ||||||
| </section> | </section> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -37,7 +37,7 @@ | |||||||
|         bind:value={searchvalue} |         bind:value={searchvalue} | ||||||
|         placeholder={$_("datatable.search")} |         placeholder={$_("datatable.search")} | ||||||
|         aria-label={$_("datatable.search")} |         aria-label={$_("datatable.search")} | ||||||
|         class="mb-4" |         class="mb-2 w-full sm:w-auto mt-1 sm:mt-0 p-2 rounded-md border" | ||||||
|       /> |       /> | ||||||
|       <!-- {/if} --> |       <!-- {/if} --> | ||||||
|       <!-- <button |       <!-- <button | ||||||
| @@ -45,7 +45,7 @@ | |||||||
|           advanced_search = !advanced_search; |           advanced_search = !advanced_search; | ||||||
|         }} |         }} | ||||||
|         type="button" |         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"> |         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:w-auto sm:text-sm"> | ||||||
|         {#if advanced_search} |         {#if advanced_search} | ||||||
|           toggle simple search |           toggle simple search | ||||||
|         {:else}toggle advanced search{/if} |         {:else}toggle advanced search{/if} | ||||||
| @@ -105,12 +105,12 @@ | |||||||
|                   <td class="px-6 py-4 whitespace-nowrap"> |                   <td class="px-6 py-4 whitespace-nowrap"> | ||||||
|                     {#if u.enabled} |                     {#if u.enabled} | ||||||
|                       <span |                       <span | ||||||
|                         class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800" |                         class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full border bg-green-100 text-green-800" | ||||||
|                         >{$_("active")}</span |                         >{$_("active")}</span | ||||||
|                       > |                       > | ||||||
|                     {:else} |                     {:else} | ||||||
|                       <span |                       <span | ||||||
|                         class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800" |                         class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full border bg-red-100 text-red-800" | ||||||
|                         >{$_("inactive")}</span |                         >{$_("inactive")}</span | ||||||
|                       > |                       > | ||||||
|                     {/if} |                     {/if} | ||||||
| @@ -119,7 +119,7 @@ | |||||||
|                     {#each u.groups as g} |                     {#each u.groups as g} | ||||||
|                       <a |                       <a | ||||||
|                         href="../groups/{g.id}" |                         href="../groups/{g.id}" | ||||||
|                         class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800" |                         class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full border bg-gray-100 text-gray-800" | ||||||
|                         >{g.name}</a |                         >{g.name}</a | ||||||
|                       > |                       > | ||||||
|                     {/each} |                     {/each} | ||||||
|   | |||||||
| @@ -37,6 +37,7 @@ | |||||||
|     "all-associated-scans-will-get-deleted-as-well": "Alle Scans dieser Station werden ebenfalls gelöscht", |     "all-associated-scans-will-get-deleted-as-well": "Alle Scans dieser Station werden ebenfalls gelöscht", | ||||||
|     "all-associated-teams-and-runners-will-be-deleted-too": "Alle assoziierten Teams und Läufer werden auch gelöscht!", |     "all-associated-teams-and-runners-will-be-deleted-too": "Alle assoziierten Teams und Läufer werden auch gelöscht!", | ||||||
|     "all-cards-loaded": "Alle Karten geladen", |     "all-cards-loaded": "Alle Karten geladen", | ||||||
|  |     "all-donors-loaded": "Alle Sponsoren geladen", | ||||||
|     "already-paid": "Bereits bezahlt", |     "already-paid": "Bereits bezahlt", | ||||||
|     "amount": "Anzahl", |     "amount": "Anzahl", | ||||||
|     "amount-per-kilometer": "Betrag pro Kilometer", |     "amount-per-kilometer": "Betrag pro Kilometer", | ||||||
| @@ -111,7 +112,7 @@ | |||||||
|     "create-a-new-scanstation": "Neue Station erstellen", |     "create-a-new-scanstation": "Neue Station erstellen", | ||||||
|     "create-a-new-statsclient": "Neuen Statsclient erstellen", |     "create-a-new-statsclient": "Neuen Statsclient erstellen", | ||||||
|     "create-a-new-team": "Erstelle ein neues Team", |     "create-a-new-team": "Erstelle ein neues Team", | ||||||
|     "create-a-new-track": "Neuen Track erstellen", |     "create-a-new-track": "Neue Laufstrecke erstellen", | ||||||
|     "create-a-new-user": "Neuen Benutzer anlegen", |     "create-a-new-user": "Neuen Benutzer anlegen", | ||||||
|     "create-a-new-user-group": "Erstelle eine neue Gruppe", |     "create-a-new-user-group": "Erstelle eine neue Gruppe", | ||||||
|     "create-and-generate-pdf": "Erstellen und PDF herunterladen", |     "create-and-generate-pdf": "Erstellen und PDF herunterladen", | ||||||
| @@ -119,7 +120,7 @@ | |||||||
|     "create-bulk-cards": "Blankokarten erstellen", |     "create-bulk-cards": "Blankokarten erstellen", | ||||||
|     "create-organization": "Organisation erstellen", |     "create-organization": "Organisation erstellen", | ||||||
|     "create-team": "Team erstellen", |     "create-team": "Team erstellen", | ||||||
|     "create-track": "Track erstellen", |     "create-track": "Laufstrecke erstellen", | ||||||
|     "create-user": "Benutzer anlegen", |     "create-user": "Benutzer anlegen", | ||||||
|     "create-without-pdf": "Ohne PDF erstellen", |     "create-without-pdf": "Ohne PDF erstellen", | ||||||
|     "created-blanco-cards": "Blankokarten wurden erstellt", |     "created-blanco-cards": "Blankokarten wurden erstellt", | ||||||
| @@ -270,6 +271,7 @@ | |||||||
|     "loading-contact-details": "Kontaktdaten werden geladen ...", |     "loading-contact-details": "Kontaktdaten werden geladen ...", | ||||||
|     "loading-donation-details": "Lade Sponsoringdetails", |     "loading-donation-details": "Lade Sponsoringdetails", | ||||||
|     "loading-donor-details": "Lade Details", |     "loading-donor-details": "Lade Details", | ||||||
|  |     "loading-donors": "Sponsoren werden geladen", | ||||||
|     "loading-group-detail": "Lade Gruppendetails...", |     "loading-group-detail": "Lade Gruppendetails...", | ||||||
|     "loading-profile-data": "Lade Profildaten", |     "loading-profile-data": "Lade Profildaten", | ||||||
|     "loading-runners": "Läufer werden geladen...", |     "loading-runners": "Läufer werden geladen...", | ||||||
| @@ -452,20 +454,20 @@ | |||||||
|     "total-paid-amount": "Gezahlt", |     "total-paid-amount": "Gezahlt", | ||||||
|     "total-scans": "Scans", |     "total-scans": "Scans", | ||||||
|     "total_donation_amount_in_eur": "Gesamtbetrag in €", |     "total_donation_amount_in_eur": "Gesamtbetrag in €", | ||||||
|     "track": "Track", |     "track": "Laufstrecke", | ||||||
|     "track-added": "Track hinzugefügt", |     "track-added": "Laufstrecke hinzugefügt", | ||||||
|     "track-data-is-being-loaded": "Trackdaten werden geladen", |     "track-data-is-being-loaded": "Laufstrecke wird geladen", | ||||||
|     "track-deleted": "Track gelöscht", |     "track-deleted": "Laufstrecke gelöscht", | ||||||
|     "track-is-being-added": "Track wird hinzugefügt...", |     "track-is-being-added": "Laufstrecke wird hinzugefügt...", | ||||||
|     "track-is-being-deleted": "Track wird gelöscht", |     "track-is-being-deleted": "Laufstrecke wird gelöscht", | ||||||
|     "track-is-being-updated": "Track wird aktualisiert...", |     "track-is-being-updated": "Laufstrecke wird aktualisiert...", | ||||||
|     "track-length-in-m": "Tracklänge (in Metern)", |     "track-length-in-m": "Laufstrecke in Metern", | ||||||
|     "track-length-must-be-greater-than-0": "Die Länge muss größer als 0 (Meter) sein", |     "track-length-must-be-greater-than-0": "Die Länge muss größer als 0 (Meter) sein", | ||||||
|     "track-name": "Trackname", |     "track-name": "Name der Laufstrecke", | ||||||
|     "track-name-must-not-be-empty": "Der Name muss angegeben werden", |     "track-name-must-not-be-empty": "Der Name muss angegeben werden", | ||||||
|     "track-updated": "Track aktualisiert", |     "track-updated": "Laufstrecke aktualisiert", | ||||||
|     "track-was-updated": "Track wurde aktualisiert", |     "track-was-updated": "Laufstrecke wurde aktualisiert", | ||||||
|     "tracks": "Tracks", |     "tracks": "Laufstrecken", | ||||||
|     "unpaid": "Offen", |     "unpaid": "Offen", | ||||||
|     "update-card": "Karte aktualisieren", |     "update-card": "Karte aktualisieren", | ||||||
|     "update-password": "Passwort ändern", |     "update-password": "Passwort ändern", | ||||||
|   | |||||||
| @@ -37,6 +37,7 @@ | |||||||
|     "all-associated-scans-will-get-deleted-as-well": "All associated scans will get deleted as well", |     "all-associated-scans-will-get-deleted-as-well": "All associated scans will get deleted as well", | ||||||
|     "all-associated-teams-and-runners-will-be-deleted-too": "All associated teams and runners will be deleted too!", |     "all-associated-teams-and-runners-will-be-deleted-too": "All associated teams and runners will be deleted too!", | ||||||
|     "all-cards-loaded": "All cards loaded", |     "all-cards-loaded": "All cards loaded", | ||||||
|  |     "all-donors-loaded": "All donors loaded", | ||||||
|     "already-paid": "Already paid", |     "already-paid": "Already paid", | ||||||
|     "amount": "Amount", |     "amount": "Amount", | ||||||
|     "amount-per-kilometer": "Amount per kilometer", |     "amount-per-kilometer": "Amount per kilometer", | ||||||
| @@ -270,6 +271,7 @@ | |||||||
|     "loading-contact-details": "Loading contact details...", |     "loading-contact-details": "Loading contact details...", | ||||||
|     "loading-donation-details": "Loading donation details", |     "loading-donation-details": "Loading donation details", | ||||||
|     "loading-donor-details": "Loading donor details", |     "loading-donor-details": "Loading donor details", | ||||||
|  |     "loading-donors": "Loading donors", | ||||||
|     "loading-group-detail": "Loading group detail...", |     "loading-group-detail": "Loading group detail...", | ||||||
|     "loading-profile-data": "Loading profile data", |     "loading-profile-data": "Loading profile data", | ||||||
|     "loading-runners": "loading runners...", |     "loading-runners": "loading runners...", | ||||||
|   | |||||||
| @@ -1,3 +1,7 @@ | |||||||
| @tailwind base; | @tailwind base; | ||||||
| @tailwind components; | @tailwind components; | ||||||
|  | .activenav { | ||||||
|  |     @apply bg-gray-300; | ||||||
|  |     @apply text-black; | ||||||
|  | } | ||||||
| @tailwind utilities; | @tailwind utilities; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user