Merge pull request 'Added release config+pipelines feature/14-release_config' (#16) from feature/14-release_config into main

Reviewed-on: #16
This commit is contained in:
Nicolai Ort 2021-04-07 17:26:56 +00:00
commit bb473027af
13 changed files with 249 additions and 96 deletions

View File

@ -4,13 +4,20 @@ name: gitea_token
get: get:
path: odit-git-bot path: odit-git-bot
name: apikey name: apikey
---
kind: secret
name: ci_token
get:
path: odit-ci-bot
name: apikey
--- ---
kind: pipeline kind: pipeline
type: kubernetes type: kubernetes
name: build name: build:tag
steps: steps:
- name: run build - name: run build
depends_on: ["clone"]
image: node:15.11.0-alpine3.13 image: node:15.11.0-alpine3.13
commands: commands:
- apk add git zip -f - apk add git zip -f
@ -18,8 +25,7 @@ steps:
- yarn build - yarn build
- mkdir out - mkdir out
- zip -r out/dist.zip dist - zip -r out/dist.zip dist
- name: gitea_release - name: gitea add packages to build
depends_on: ["run build"]
image: plugins/gitea-release image: plugins/gitea-release
settings: settings:
api_key: api_key:
@ -33,8 +39,12 @@ steps:
- sha512 - sha512
- adler32 - adler32
- crc32 - crc32
when: - name: trigger electron build
event: tag image: idcooldi/drone-webhook
settings:
urls: https://ci.odit.services/api/repos/lfk/scanclient-electron/builds?SOURCE_TAG=${DRONE_TAG}
bearer:
from_secret: ci_token
trigger: trigger:
event: event:
- tag - tag

View File

@ -9,7 +9,6 @@
</head> </head>
<body class="bg-white font-family-karla h-screen"> <body class="bg-white font-family-karla h-screen">
<script src="./env.js"></script>
<script type="module" src="./src/main.js"></script> <script type="module" src="./src/main.js"></script>
</body> </body>
</html> </html>

View File

@ -222,6 +222,35 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
# release-it
**Author**: Lars Kappert
**Repo**: https://github.com/release-it/release-it
**License**: MIT
**Description**: Generic CLI tool to automate versioning and package publishing related tasks.
## License Text
MIT License
Copyright (c) 2018 Lars Kappert
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# svelte # svelte
**Author**: Rich Harris **Author**: Rich Harris
**Repo**: https://github.com/sveltejs/svelte **Repo**: https://github.com/sveltejs/svelte
@ -237,6 +266,21 @@ The above copyright notice and this permission notice shall be included in all c
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# svelte-i18n
**Author**: Christian Kaisermann <christian@kaisermann.me>
**Repo**: https://github.com/kaisermann/svelte-i18n
**License**: MIT
**Description**: Internationalization library for Svelte
## License Text
Copyright 2017 Christian Kaisermann <christian@kaisermann.me>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# svelte-preprocess # svelte-preprocess
**Author**: Christian Kaisermann <christian@kaisermann.me> **Author**: Christian Kaisermann <christian@kaisermann.me>
**Repo**: https://github.com/sveltejs/svelte-preprocess **Repo**: https://github.com/sveltejs/svelte-preprocess
@ -4987,18 +5031,3 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
# svelte-i18n
**Author**: Christian Kaisermann <christian@kaisermann.me>
**Repo**: https://github.com/kaisermann/svelte-i18n
**License**: MIT
**Description**: Internationalization library for Svelte
## License Text
Copyright 2017 Christian Kaisermann <christian@kaisermann.me>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -1,12 +1,13 @@
{ {
"name": "@lfk/scanclient", "name": "@lfk/scanclient",
"version": "0.0.0", "version": "0.1.1",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"build": "vite build", "build": "vite build",
"format": "prettier --write --plugin-search-dir=. ./**/*.html ./**/*.svelte", "format": "prettier --write --plugin-search-dir=. ./**/*.html ./**/*.svelte",
"prepare": "husky install", "prepare": "husky install",
"license:export": "license-exporter --markdown && git stage licenses.md" "license:export": "license-exporter --markdown && git stage licenses.md",
"release": "release-it --only-version"
}, },
"devDependencies": { "devDependencies": {
"@odit/license-exporter": "^0.0.11", "@odit/license-exporter": "^0.0.11",
@ -18,10 +19,29 @@
"husky": "^5.1.3", "husky": "^5.1.3",
"prettier": "^2.2.1", "prettier": "^2.2.1",
"prettier-plugin-svelte": "^2.2.0", "prettier-plugin-svelte": "^2.2.0",
"release-it": "^14.5.1",
"svelte": "^3.35.0", "svelte": "^3.35.0",
"svelte-i18n": "^3.3.7",
"svelte-preprocess": "^4.6.9", "svelte-preprocess": "^4.6.9",
"vite": "^2.1.2", "vite": "^2.1.2",
"vite-plugin-windicss": "^0.9.2", "vite-plugin-windicss": "^0.9.2"
"svelte-i18n": "^3.3.7" },
"release-it": {
"git": {
"commit": true,
"requireCleanWorkingDir": false,
"commitMessage": "🚀Bumped version to ${version}",
"requireBranch": "dev",
"push": false,
"tag": true,
"tagName": null,
"tagAnnotation": "${version}"
},
"npm": {
"publish": false
},
"hooks": {
"after:bump": "npx auto-changelog --commit-limit false -p -u --hide-credit && git add CHANGELOG.md && node order.js && git add src/locales"
}
} }
} }

View File

@ -1,3 +0,0 @@
const config = {
endpoint: 'https://dev.lauf-fuer-kaya.de/'
};

View File

@ -1,3 +0,0 @@
const config = {
endpoint: 'https://dev.lauf-fuer-kaya.de/'
};

View File

@ -1,5 +1,5 @@
<script> <script>
console.log("app started with base url " + config.endpoint); import { apikey, api_endpoint, lang, page } from "./store.js";
import { addMessages, init } from "svelte-i18n"; import { addMessages, init } from "svelte-i18n";
import en from "./locales/en.json"; import en from "./locales/en.json";
import de from "./locales/de.json"; import de from "./locales/de.json";
@ -11,13 +11,13 @@
import Scanner from "./Scanner.svelte"; import Scanner from "./Scanner.svelte";
import Login from "./Login.svelte"; import Login from "./Login.svelte";
import Settings from "./Settings.svelte"; import Settings from "./Settings.svelte";
import { apikey, lang, page } from "./store.js";
$: is_configured = $apikey && $apikey !== "null" && $apikey !== ""; $: is_configured = $apikey && $apikey !== "null" && $apikey !== "";
$: settings_open = $page === "settings"; $: settings_open = $page === "settings";
init({ init({
fallbackLocale: "en-US", fallbackLocale: "en-US",
initialLocale: $lang, initialLocale: $lang,
}); });
console.log("app started with base url " + $api_endpoint);
</script> </script>
{#if settings_open && is_configured} {#if settings_open && is_configured}

View File

@ -1,16 +1,27 @@
<script> <script>
import { apikey, lang, stationinfo } from "./store.js"; import { apikey, lang, stationinfo, api_endpoint } from "./store.js";
import axios from "axios"; import axios from "axios";
import { _, locale } from "svelte-i18n"; import { _, locale } from "svelte-i18n";
let token; let token;
let api_endpoint_input;
$: error = false; $: error = false;
$: errormessage = ""; $: errormessage = "";
$: isTokenValid = $: isTokenValid =
token?.length === 44 && token?.length === 44 &&
token.split(".")[0].length === 7 && token.split(".")[0].length === 7 &&
isUUID(token.split(".")[1]); isUUID(token.split(".")[1]);
function isLocale(l) { $: isEndpointValid = validURL(api_endpoint_input);
return $locale == l; function validURL(str) {
var pattern = new RegExp(
"^(https?:\\/\\/)?" + // protocol
"((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|" + // domain name
"((\\d{1,3}\\.){3}\\d{1,3}))" + // OR ip (v4) address
"(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*" + // port and path
"(\\?[;&a-z\\d%_.~+=-]*)?" + // query string
"(\\#[-a-z\\d_]*)?$",
"i"
); // fragment locator
return !!pattern.test(str);
} }
function isUUID(uuid) { function isUUID(uuid) {
let s = "" + uuid; let s = "" + uuid;
@ -71,57 +82,99 @@
</div> </div>
{/if} {/if}
{/if} {/if}
{#if $api_endpoint}
<form <form
class="flex flex-col pt-3 md:pt-8" class="flex flex-col pt-3 md:pt-8"
onsubmit="event.preventDefault();" onsubmit="event.preventDefault();"
on:submit={() => { on:submit={() => {
axios axios
.request({ .request({
method: "GET", method: "GET",
url: config.endpoint + "api/stations/me", url: $api_endpoint + "api/stations/me",
headers: { Authorization: "Bearer " + token }, headers: { Authorization: "Bearer " + token },
}) })
.then(function (response) { .then(function (response) {
error = false; error = false;
errormessage = ""; errormessage = "";
apikey.set(token); apikey.set(token);
stationinfo.set(JSON.stringify(response.data)); stationinfo.set(JSON.stringify(response.data));
}) })
.catch(function (e) { .catch(function (e) {
error = true; error = true;
errormessage = e.response.data.short; errormessage = e.response.data.short;
}); });
}} }}
>
<div class="flex flex-col pt-4">
<label for="token" class="text-lg">{$_("client_token")}</label>
<input
type="text"
id="token"
placeholder={$_("client_token")}
bind:value={token}
class:border-red-500={!isTokenValid}
class:border-solid={!isTokenValid}
class:border-3={!isTokenValid}
class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 mt-1 leading-tight focus:outline-none focus:shadow-outline"
/>
</div>
{#if !isTokenValid}
<span class="text-sm"
>{$_("please_provide_a_valid_client_token")}</span
>
{/if}
<button
disabled={!isTokenValid}
class:cursor-pointer={isTokenValid}
class:opacity-50={!isTokenValid}
id="configure"
type="submit"
class="bg-black text-white font-bold text-lg hover:bg-gray-700 p-2 mt-8 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-black"
>{$_("configure")}</button
> >
</form> <div class="flex flex-col pt-4">
<label for="token" class="text-lg">{$_("client_token")}</label>
<input
type="text"
id="token"
placeholder={$_("client_token")}
bind:value={token}
class:border-red-500={!isTokenValid}
class:border-solid={!isTokenValid}
class:border-3={!isTokenValid}
class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 mt-1 leading-tight focus:outline-none focus:shadow-outline"
/>
</div>
{#if !isTokenValid}
<span class="text-sm"
>{$_("please_provide_a_valid_client_token")}</span
>
{/if}
<button
disabled={!isTokenValid}
class:cursor-pointer={isTokenValid}
class:opacity-50={!isTokenValid}
id="configure"
type="submit"
class="bg-black text-white font-bold text-lg hover:bg-gray-700 p-2 mt-8 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-black"
>{$_("configure")}</button
>
</form>
{:else}
<form
class="flex flex-col pt-3 md:pt-8"
onsubmit="event.preventDefault();"
on:submit={() => {
if (api_endpoint_input.substr(-1) !== "/") {
api_endpoint_input = api_endpoint_input + "/";
}
api_endpoint.set(api_endpoint_input);
}}
>
<div class="flex flex-col pt-4">
<label for="api_endpoint" class="text-lg"
>{$_("api_endpoint")}</label
>
<input
type="text"
id="api_endpoint"
placeholder={$_("api_endpoint")}
bind:value={api_endpoint_input}
class:border-red-500={!isEndpointValid}
class:border-solid={!isEndpointValid}
class:border-3={!isEndpointValid}
class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 mt-1 leading-tight focus:outline-none focus:shadow-outline"
/>
</div>
{#if !isEndpointValid}
<span class="text-sm"
>{$_("please_provide_a_valid_client_api_endpoint")}</span
>
{/if}
<button
disabled={!isEndpointValid}
class:cursor-pointer={isEndpointValid}
class:opacity-50={!isEndpointValid}
id="configure"
type="submit"
class="bg-black text-white font-bold text-lg hover:bg-gray-700 p-2 mt-8 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-black"
>{$_("configure")}</button
>
</form>
{/if}
<div class="text-center pt-12 pb-12"> <div class="text-center pt-12 pb-12">
<p> <p>
<svg <svg

View File

@ -1,7 +1,7 @@
<script> <script>
import axios from "axios"; import axios from "axios";
import { _ } from "svelte-i18n"; import { _ } from "svelte-i18n";
import { apikey, page, stationinfo } from "./store.js"; import { apikey, api_endpoint, page, stationinfo } from "./store.js";
function init(el) { function init(el) {
el.focus(); el.focus();
} }
@ -9,6 +9,7 @@
let lastscan_time = ""; let lastscan_time = "";
let lastscan_laptime = ""; let lastscan_laptime = "";
let lastscan_totaldistance = ""; let lastscan_totaldistance = "";
let lastscan_valid = true;
let card = ""; let card = "";
// live clock at the top // live clock at the top
let time = new Date(); let time = new Date();
@ -64,7 +65,7 @@
axios axios
.request({ .request({
method: "POST", method: "POST",
url: config.endpoint + "api/scans/trackscans", url: $api_endpoint + "api/scans/trackscans",
headers: { Authorization: "Bearer " + $apikey }, headers: { Authorization: "Bearer " + $apikey },
data: { card }, data: { card },
}) })
@ -83,6 +84,7 @@
) + ) +
"s"; "s";
lastscan_laptime = response.data.lapTime; lastscan_laptime = response.data.lapTime;
lastscan_valid = response.data.valid;
lastscan_totaldistance = lastscan_totaldistance =
Math.floor(response.data.runner.distance / 1000) + Math.floor(response.data.runner.distance / 1000) +
"km " + "km " +
@ -112,14 +114,44 @@
/> />
</label> </label>
{#if lastscan_totaldistance} {#if lastscan_totaldistance}
<h1 class="text-3xl font-bold text-center">last scan</h1> {#if !lastscan_valid || lastscan_error}
<h1 class="text-5xl font-bold text-center">{lastscan_time}</h1> <svg
<h1 class="text-3xl font-bold text-center">total distance</h1> xmlns="http://www.w3.org/2000/svg"
<h1 class="text-8xl font-bold text-center"> width="20rem"
height="20rem"
class="ml-auto mr-auto"
version="1.0"
title="Invalid"
viewBox="0 0 100 100"
><g fill="none" stroke="red"
><path d="M6 6l88 88" stroke-width="18.1" /><path
d="M6 94L94 6"
stroke-width="17.8"
/></g
></svg
>
{:else}
<svg
xmlns="http://www.w3.org/2000/svg"
width="20rem"
height="20rem"
class="ml-auto mr-auto"
title="Valid"
viewBox="0 0 600 600"
><path
d="M8 405s115 129 138 182h99c41-126 203-429 341-535 28-37-43-52-102-27-87 36-252 317-283 384-44 12-90-74-90-74z"
fill="#181"
/></svg
>
{/if}
<h1 class="text-2xl font-bold text-center">{$_("total-distance")}</h1>
<h1 class="text-6xl font-bold text-center">
{lastscan_totaldistance} {lastscan_totaldistance}
</h1> </h1>
<h1 class="text-3xl font-bold text-center">lap time</h1> <h1 class="text-2xl font-bold text-center">{$_("lap-time")}</h1>
<h1 class="text-8xl font-bold text-center">{lastscan_laptime}</h1> <h1 class="text-6xl font-bold text-center">{lastscan_laptime}</h1>
<h1 class="text-2xl font-bold text-center">{$_("last-scan")}</h1>
<h1 class="text-5xl font-bold text-center">{lastscan_time}</h1>
{:else} {:else}
<h1 class="text-3xl font-bold text-center"> <h1 class="text-3xl font-bold text-center">
{$_("please_scan_a_card")} {$_("please_scan_a_card")}

View File

@ -1,7 +1,7 @@
<script> <script>
import { _ } from "svelte-i18n"; import { _ } from "svelte-i18n";
import { apikey, lang, page, stationinfo } from "./store.js"; import { apikey, api_endpoint, lang, page, stationinfo } from "./store.js";
</script> </script>
<div class="p-5 min-h-screen"> <div class="p-5 min-h-screen">
@ -103,6 +103,7 @@
<button <button
on:click={() => { on:click={() => {
apikey.set(""); apikey.set("");
api_endpoint.set("");
page.set(""); page.set("");
}} }}
class="w-full py-3 bg-black text-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-black" class="w-full py-3 bg-black text-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-black"

View File

@ -1,4 +1,5 @@
{ {
"api_endpoint": "API-Endpunkt",
"api_key": "API Key", "api_key": "API Key",
"back_to_scanner": "Zurück zum Scanner", "back_to_scanner": "Zurück zum Scanner",
"client_token": "Client Token", "client_token": "Client Token",
@ -6,9 +7,12 @@
"configure": "Konfigurieren", "configure": "Konfigurieren",
"error": "Error!", "error": "Error!",
"language": "Sprache", "language": "Sprache",
"lap-time": "Rundenzeit",
"last-scan": "Letzter Scan um",
"log_out_from_this_client": "Von diesem Scanner abmelden", "log_out_from_this_client": "Von diesem Scanner abmelden",
"minimum_lap_time": "minimale Rundenzeit", "minimum_lap_time": "minimale Rundenzeit",
"please_check_your_token_and_try_again": "Bitte überprüfe den Token und versuche es erneut...", "please_check_your_token_and_try_again": "Bitte überprüfe den Token und versuche es erneut...",
"please_provide_a_valid_client_api_endpoint": "Bitte gebe einen gültigen API-Endpunkt an ...",
"please_provide_a_valid_client_token": "Bitte gebe einen gültigen Client-Token an ...", "please_provide_a_valid_client_token": "Bitte gebe einen gültigen Client-Token an ...",
"please_provide_the_scan_client_token": "Bitte gebe den Scan-Client-Token an.", "please_provide_the_scan_client_token": "Bitte gebe den Scan-Client-Token an.",
"please_scan_a_card": "Bitte scanne eine Karte ...", "please_scan_a_card": "Bitte scanne eine Karte ...",
@ -20,6 +24,7 @@
"station_id": "Scanstations-ID", "station_id": "Scanstations-ID",
"the_provided_scan_station_is_disabled": "Die angegebene Scanstation ist deaktiviert.", "the_provided_scan_station_is_disabled": "Die angegebene Scanstation ist deaktiviert.",
"the_provided_scan_station_token_is_invalid": "Der angegebene Scanstation-Token ist ungültig.", "the_provided_scan_station_token_is_invalid": "Der angegebene Scanstation-Token ist ungültig.",
"total-distance": "Gesamtdistanz",
"track_distance": "Länge des Tracks", "track_distance": "Länge des Tracks",
"track_id": "Track ID", "track_id": "Track ID",
"track_name": "Track Name" "track_name": "Track Name"

View File

@ -1,4 +1,5 @@
{ {
"api_endpoint": "API Endpoint",
"api_key": "API Key", "api_key": "API Key",
"back_to_scanner": "Back to Scanner", "back_to_scanner": "Back to Scanner",
"client_token": "Client Token", "client_token": "Client Token",
@ -6,9 +7,12 @@
"configure": "Configure", "configure": "Configure",
"error": "Error!", "error": "Error!",
"language": "Language", "language": "Language",
"lap-time": "lap time",
"last-scan": "last scan",
"log_out_from_this_client": "Log Out from this Client", "log_out_from_this_client": "Log Out from this Client",
"minimum_lap_time": "minimum lap time", "minimum_lap_time": "minimum lap time",
"please_check_your_token_and_try_again": "Please check your token and try again...", "please_check_your_token_and_try_again": "Please check your token and try again...",
"please_provide_a_valid_client_api_endpoint": "Please provide a valid api endpoint...",
"please_provide_a_valid_client_token": "Please provide a valid client token...", "please_provide_a_valid_client_token": "Please provide a valid client token...",
"please_provide_the_scan_client_token": "Please provide the scan client token.", "please_provide_the_scan_client_token": "Please provide the scan client token.",
"please_scan_a_card": "please scan a card...", "please_scan_a_card": "please scan a card...",
@ -20,6 +24,7 @@
"station_id": "Scanstation ID", "station_id": "Scanstation ID",
"the_provided_scan_station_is_disabled": "The provided scan station is disabled.", "the_provided_scan_station_is_disabled": "The provided scan station is disabled.",
"the_provided_scan_station_token_is_invalid": "The provided scan station token is invalid.", "the_provided_scan_station_token_is_invalid": "The provided scan station token is invalid.",
"total-distance": "total distance",
"track_distance": "Track Distance", "track_distance": "Track Distance",
"track_id": "Track ID", "track_id": "Track ID",
"track_name": "Track Name" "track_name": "Track Name"

View File

@ -1,5 +1,10 @@
import { writable } from 'svelte/store'; import { writable } from 'svelte/store';
const stored_api_endpoint = localStorage.getItem('api_endpoint')||"";
export const api_endpoint = writable(stored_api_endpoint);
api_endpoint.subscribe((value) => {
localStorage.setItem('api_endpoint', value);
});
const stored_apikey = localStorage.getItem('apikey'); const stored_apikey = localStorage.getItem('apikey');
export const apikey = writable(stored_apikey); export const apikey = writable(stored_apikey);
apikey.subscribe((value) => { apikey.subscribe((value) => {