Compare commits
	
		
			21 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 9abf74d6d2 | |||
| 50e81a6cb5 | |||
| 8fae1fb6b3 | |||
| 372fa110ec | |||
| 35bec9fe58 | |||
| 93d67bdba9 | |||
| a5e72a18e3 | |||
| 91d2f46b93 | |||
| c60bae4533 | |||
| 43ac878d44 | |||
| ceabd06a43 | |||
| 9bfc0c5338 | |||
| fb8206ff13 | |||
| dceb0ef461 | |||
| 88bc1982ca | |||
| e741a9d7e7 | |||
| 65f1d22205 | |||
| d867c08aba | |||
| 6193eff38e | |||
| f1929e7cf9 | |||
| 08642d7618 | 
							
								
								
									
										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 | ||||
							
								
								
									
										42
									
								
								.woodpecker/build.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								.woodpecker/build.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| steps: | ||||
|   - name: run full license export | ||||
|     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 | ||||
|     secrets: | ||||
|       - source: odit-npm-cache-url | ||||
|         target: NPM_REGISTRY_URL | ||||
|   - name: push new licenses file to repo | ||||
|     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: odit-git-bot-sshkey | ||||
|   - name: build edge | ||||
|     image: woodpeckerci/plugin-docker-buildx | ||||
|     settings: | ||||
|       repo: registry.odit.services/odit/website | ||||
|       tags: | ||||
|         - edge | ||||
|       registry: registry.odit.services | ||||
|       platforms: linux/amd64,linux/arm64 | ||||
|       cache_from: registry.odit.services/odit/website:edge | ||||
|       username: | ||||
|         from_secret: odit-registry-builder-username | ||||
|       password: | ||||
|         from_secret: odit-registry-builder-password | ||||
|     secrets: | ||||
|       - source: odit-npm-cache-url | ||||
|         target: NPM_REGISTRY_URL | ||||
|  | ||||
| when: | ||||
|   event: | ||||
|     - push | ||||
|   branch: | ||||
|     - dev | ||||
							
								
								
									
										20
									
								
								.woodpecker/release.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								.woodpecker/release.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| 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 | ||||
|     secrets: | ||||
|       - source: odit-npm-cache-url | ||||
|         target: NPM_REGISTRY_URL | ||||
| when: | ||||
|   event: | ||||
|     - tag | ||||
							
								
								
									
										39
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @@ -2,9 +2,48 @@ | ||||
|  | ||||
| All notable changes to this project will be documented in this file. Dates are displayed in UTC. | ||||
|  | ||||
| #### [1.5.1](https://git.odit.services/lfk/frontend/compare/1.5.0...1.5.1) | ||||
|  | ||||
| - 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) | ||||
| - 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,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 | ||||
| WORKDIR /app | ||||
|  | ||||
| COPY package.json pnpm-lock.yaml vite.config.js tailwind.config.js postcss.config.cjs index.html ./ | ||||
| RUN npm config set registry $NPM_REGISTRY_URL && npm i -g pnpm@8 | ||||
| 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@9 | ||||
| RUN mkdir /pnpm && pnpm config set store-dir /pnpm && pnpm i | ||||
|  | ||||
| COPY src ./src | ||||
| @@ -11,6 +11,6 @@ COPY public ./public | ||||
| RUN pnpm build | ||||
|  | ||||
| # 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 ./nginx.conf /etc/nginx/nginx.conf | ||||
| @@ -13,7 +13,7 @@ | ||||
|  | ||||
|   <body> | ||||
|     <span style="display: none; visibility: hidden" id="buildinfo" | ||||
|       >RELEASE_INFO-1.4.11-RELEASE_INFO</span | ||||
|       >RELEASE_INFO-1.5.1-RELEASE_INFO</span | ||||
|     > | ||||
|     <noscript>You need to enable JavaScript to run this app.</noscript> | ||||
|     <script src="/env.js"></script> | ||||
|   | ||||
							
								
								
									
										22
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								package.json
									
									
									
									
									
								
							| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|   "name": "@odit/lfk-frontend", | ||||
|   "version": "1.4.11", | ||||
|   "version": "1.5.1", | ||||
|   "type": "module", | ||||
|   "scripts": { | ||||
|     "i18n-order": "node order.js", | ||||
| @@ -14,14 +14,14 @@ | ||||
|   "devDependencies": { | ||||
|     "@odit/license-exporter": "0.2.0", | ||||
|     "@sveltejs/vite-plugin-svelte": "2.1.1", | ||||
|     "auto-changelog": "2.4.0", | ||||
|     "autoprefixer": "10.4.14", | ||||
|     "postcss": "8.4.23", | ||||
|     "prettier": "2.8.8", | ||||
|     "prettier-plugin-svelte": "2.10.0", | ||||
|     "release-it": "15.10.3", | ||||
|     "auto-changelog": "2.5.0", | ||||
|     "autoprefixer": "10.4.20", | ||||
|     "postcss": "8.4.49", | ||||
|     "prettier": "3.3.3", | ||||
|     "prettier-plugin-svelte": "3.2.8", | ||||
|     "release-it": "17.10.0", | ||||
|     "svelte-select": "3.17.0", | ||||
|     "tailwindcss": "3.3.2", | ||||
|     "tailwindcss": "3.4.15", | ||||
|     "vite": "4.3.3" | ||||
|   }, | ||||
|   "release-it": { | ||||
| @@ -42,11 +42,11 @@ | ||||
|     } | ||||
|   }, | ||||
|   "dependencies": { | ||||
|     "@odit/lfk-client-js": "1.1.2", | ||||
|     "@paralleldrive/cuid2": "2.2.0", | ||||
|     "@odit/lfk-client-js": "1.1.3", | ||||
|     "@paralleldrive/cuid2": "2.2.2", | ||||
|     "@tanstack/svelte-table": "8.9.1", | ||||
|     "bwip-js": "3.4.0", | ||||
|     "check-password-strength": "2.0.7", | ||||
|     "check-password-strength": "2.0.10", | ||||
|     "csvtojson": "2.0.10", | ||||
|     "localforage": "1.10.0", | ||||
|     "marked": "4.3.0", | ||||
|   | ||||
							
								
								
									
										5447
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										5447
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -8,3 +8,4 @@ const config = { | ||||
| 	default_password: "demo", | ||||
| 	prefersHashRouting: true, | ||||
| }; | ||||
| window.config = config; | ||||
|   | ||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -33,7 +33,7 @@ | ||||
|       toast.loading($_("updating-donation")); | ||||
|       const editable = Object.assign({}, original_data); | ||||
|       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) { | ||||
|         editable.runner = editable.runner.id; | ||||
|         DonationService.donationControllerPutDistance( | ||||
|   | ||||
| @@ -6,6 +6,7 @@ | ||||
|     DonorService, | ||||
|     RunnerService, | ||||
|   } from "@odit/lfk-client-js"; | ||||
|   import toast from 'svelte-french-toast' | ||||
|  | ||||
|   import PromiseError from "../base/PromiseError.svelte"; | ||||
|   import Select from "svelte-select"; | ||||
|   | ||||
| @@ -35,7 +35,7 @@ | ||||
|                 d.firstname, | ||||
|                 d.middlename, | ||||
|                 d.lastname, | ||||
|                 d.paidDonationAmount, | ||||
|                 (d.paidDonationAmount/100).toFixed(2), | ||||
|                 address, | ||||
|               ]; | ||||
|             }); | ||||
|   | ||||
| @@ -2,6 +2,7 @@ | ||||
|   import { _ } from "svelte-i18n"; | ||||
|   import store from "../../store"; | ||||
|   import { UserGroupService } from "@odit/lfk-client-js"; | ||||
|   import toast from 'svelte-french-toast' | ||||
|  | ||||
|   import PromiseError from "../base/PromiseError.svelte"; | ||||
|   let data_loaded = false; | ||||
|   | ||||
| @@ -5,6 +5,7 @@ | ||||
|     CreatePermission, | ||||
|     UserGroupService, | ||||
|   } from "@odit/lfk-client-js"; | ||||
|   import toast from 'svelte-french-toast' | ||||
|  | ||||
|   import PromiseError from "../base/PromiseError.svelte"; | ||||
|   export let params; | ||||
|   | ||||
| @@ -4,6 +4,7 @@ | ||||
|     RunnerOrganizationService, | ||||
|   } from "@odit/lfk-client-js"; | ||||
|   import { getLocaleFromNavigator, _ } from "svelte-i18n"; | ||||
|   import toast from 'svelte-french-toast' | ||||
|  | ||||
|   import store from "../../store"; | ||||
|   import ConfirmOrgDeletion from "./ConfirmOrgDeletion.svelte"; | ||||
|   | ||||
| @@ -5,6 +5,7 @@ | ||||
|     RunnerOrganizationService, | ||||
|     RunnerTeamService, | ||||
|   } from "@odit/lfk-client-js"; | ||||
|   import toast from 'svelte-french-toast' | ||||
|  | ||||
|   import { init } from "@paralleldrive/cuid2"; | ||||
|   const createId = init({ length: 10, fingerprint: "lfk-frontend" }); | ||||
|   | ||||
| @@ -12,6 +12,7 @@ | ||||
|   import Select from "svelte-select"; | ||||
|   import { createEventDispatcher } from "svelte"; | ||||
|   const dispatch = createEventDispatcher(); | ||||
|   import toast from 'svelte-french-toast' | ||||
|  | ||||
|   export let modal_open; | ||||
|   $: selected_team = undefined; | ||||
|   | ||||
| @@ -1,12 +1,11 @@ | ||||
| <script> | ||||
| 	import { _ } from "svelte-i18n"; | ||||
|  | ||||
|   import { tick, createEventDispatcher } from "svelte"; | ||||
| 	import { tick } from "svelte"; | ||||
| 	import bwipjs from "bwip-js"; | ||||
| 	import toast from "svelte-french-toast"; | ||||
|  | ||||
| 	export let copy_modal_open; | ||||
| 	export let new_station; | ||||
|   const dispatch = createEventDispatcher(); | ||||
| 	let valueCopy = null; | ||||
| 	let areaDom; | ||||
| 	let copied = false; | ||||
|   | ||||
| @@ -1,12 +1,25 @@ | ||||
| <script> | ||||
| 	import { _ } from "svelte-i18n"; | ||||
| 	import store from "../../store"; | ||||
| 	import { ScanStationService } from "@odit/lfk-client-js"; | ||||
| 	import AddScanStationModal from "./AddScanStationModal.svelte"; | ||||
| 	import CopyScanStationTokenModal from "./CopyScanStationTokenModal.svelte"; | ||||
|   import ScanStationsOverview from "./ScanStationsOverview.svelte"; | ||||
| 	import ScanStationsEmptyState from "./ScanStationsEmptyState.svelte"; | ||||
| 	import ConfirmScanStationDeletion from "./ConfirmScanStationDeletion.svelte"; | ||||
| 	import toast from "svelte-french-toast"; | ||||
| 	// | ||||
| 	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> | ||||
|  | ||||
| @@ -25,12 +38,184 @@ | ||||
| 			</button> | ||||
| 		{/if} | ||||
| 	</span> | ||||
|   <ScanStationsOverview | ||||
|     bind:current_stations | ||||
| 	<ConfirmScanStationDeletion | ||||
| 		on:cancelDelete={(event) => { | ||||
| 			modal_open = false; | ||||
| 			active_deletes[event.detail.id] = false; | ||||
| 		}} | ||||
| 		bind:modal_open | ||||
|     bind:new_station | ||||
|     bind:copy_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} | ||||
| </section> | ||||
|  | ||||
| {#if store.state.jwtinfo.userdetails.permissions.includes("STATION:CREATE")} | ||||
|   | ||||
| @@ -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 isEmail from "validator/es/lib/isEmail"; | ||||
|   import { MeService } from "@odit/lfk-client-js"; | ||||
|   import toast from 'svelte-french-toast' | ||||
|  | ||||
|   import ConfirmProfileDeletion from "./ConfirmProfileDeletion.svelte"; | ||||
|   import PasswordStrength, { | ||||
|   | ||||
| @@ -4,6 +4,7 @@ | ||||
|   import { tick, createEventDispatcher } from "svelte"; | ||||
|   export let copy_modal_open; | ||||
|   export let new_client; | ||||
|   import toast from 'svelte-french-toast' | ||||
|   const dispatch = createEventDispatcher(); | ||||
|   let valueCopy = null; | ||||
|   let areaDom; | ||||
|   | ||||
| @@ -5,6 +5,7 @@ | ||||
|     RunnerTeamService, | ||||
|   } from "@odit/lfk-client-js"; | ||||
|   import { getLocaleFromNavigator, _ } from "svelte-i18n"; | ||||
|   import toast from 'svelte-french-toast' | ||||
|  | ||||
|   import store from "../../store"; | ||||
|   import Select from "svelte-select"; | ||||
|   | ||||
| @@ -223,7 +223,7 @@ | ||||
|             type="button" | ||||
|             class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm" | ||||
|           > | ||||
|             Create | ||||
|             {$_("create")} | ||||
|           </button> | ||||
|           <button | ||||
|             on:click={() => { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user