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:
path: odit-git-bot
name: apikey
---
kind: secret
name: ci_token
get:
path: odit-ci-bot
name: apikey
---
kind: pipeline
type: kubernetes
name: build
name: build:tag
steps:
- name: run build
depends_on: ["clone"]
image: node:15.11.0-alpine3.13
commands:
- apk add git zip -f
@ -18,8 +25,7 @@ steps:
- yarn build
- mkdir out
- zip -r out/dist.zip dist
- name: gitea_release
depends_on: ["run build"]
- name: gitea add packages to build
image: plugins/gitea-release
settings:
api_key:
@ -33,8 +39,12 @@ steps:
- sha512
- adler32
- crc32
when:
event: tag
- name: trigger electron build
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:
event:
- tag

View File

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

View File

@ -222,6 +222,35 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
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
**Author**: Rich Harris
**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.
# 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
**Author**: Christian Kaisermann <christian@kaisermann.me>
**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.
# 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",
"version": "0.0.0",
"version": "0.1.1",
"scripts": {
"dev": "vite",
"build": "vite build",
"format": "prettier --write --plugin-search-dir=. ./**/*.html ./**/*.svelte",
"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": {
"@odit/license-exporter": "^0.0.11",
@ -18,10 +19,29 @@
"husky": "^5.1.3",
"prettier": "^2.2.1",
"prettier-plugin-svelte": "^2.2.0",
"release-it": "^14.5.1",
"svelte": "^3.35.0",
"svelte-i18n": "^3.3.7",
"svelte-preprocess": "^4.6.9",
"vite": "^2.1.2",
"vite-plugin-windicss": "^0.9.2",
"svelte-i18n": "^3.3.7"
"vite-plugin-windicss": "^0.9.2"
},
"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>
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 en from "./locales/en.json";
import de from "./locales/de.json";
@ -11,13 +11,13 @@
import Scanner from "./Scanner.svelte";
import Login from "./Login.svelte";
import Settings from "./Settings.svelte";
import { apikey, lang, page } from "./store.js";
$: is_configured = $apikey && $apikey !== "null" && $apikey !== "";
$: settings_open = $page === "settings";
init({
fallbackLocale: "en-US",
initialLocale: $lang,
});
console.log("app started with base url " + $api_endpoint);
</script>
{#if settings_open && is_configured}

View File

@ -1,16 +1,27 @@
<script>
import { apikey, lang, stationinfo } from "./store.js";
import { apikey, lang, stationinfo, api_endpoint } from "./store.js";
import axios from "axios";
import { _, locale } from "svelte-i18n";
let token;
let api_endpoint_input;
$: error = false;
$: errormessage = "";
$: isTokenValid =
token?.length === 44 &&
token.split(".")[0].length === 7 &&
isUUID(token.split(".")[1]);
function isLocale(l) {
return $locale == l;
$: isEndpointValid = validURL(api_endpoint_input);
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) {
let s = "" + uuid;
@ -71,57 +82,99 @@
</div>
{/if}
{/if}
<form
class="flex flex-col pt-3 md:pt-8"
onsubmit="event.preventDefault();"
on:submit={() => {
axios
.request({
method: "GET",
url: config.endpoint + "api/stations/me",
headers: { Authorization: "Bearer " + token },
})
.then(function (response) {
error = false;
errormessage = "";
apikey.set(token);
stationinfo.set(JSON.stringify(response.data));
})
.catch(function (e) {
error = true;
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
{#if $api_endpoint}
<form
class="flex flex-col pt-3 md:pt-8"
onsubmit="event.preventDefault();"
on:submit={() => {
axios
.request({
method: "GET",
url: $api_endpoint + "api/stations/me",
headers: { Authorization: "Bearer " + token },
})
.then(function (response) {
error = false;
errormessage = "";
apikey.set(token);
stationinfo.set(JSON.stringify(response.data));
})
.catch(function (e) {
error = true;
errormessage = e.response.data.short;
});
}}
>
</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">
<p>
<svg

View File

@ -1,7 +1,7 @@
<script>
import axios from "axios";
import { _ } from "svelte-i18n";
import { apikey, page, stationinfo } from "./store.js";
import { apikey, api_endpoint, page, stationinfo } from "./store.js";
function init(el) {
el.focus();
}
@ -9,6 +9,7 @@
let lastscan_time = "";
let lastscan_laptime = "";
let lastscan_totaldistance = "";
let lastscan_valid = true;
let card = "";
// live clock at the top
let time = new Date();
@ -64,7 +65,7 @@
axios
.request({
method: "POST",
url: config.endpoint + "api/scans/trackscans",
url: $api_endpoint + "api/scans/trackscans",
headers: { Authorization: "Bearer " + $apikey },
data: { card },
})
@ -83,6 +84,7 @@
) +
"s";
lastscan_laptime = response.data.lapTime;
lastscan_valid = response.data.valid;
lastscan_totaldistance =
Math.floor(response.data.runner.distance / 1000) +
"km " +
@ -112,14 +114,44 @@
/>
</label>
{#if lastscan_totaldistance}
<h1 class="text-3xl font-bold text-center">last scan</h1>
<h1 class="text-5xl font-bold text-center">{lastscan_time}</h1>
<h1 class="text-3xl font-bold text-center">total distance</h1>
<h1 class="text-8xl font-bold text-center">
{#if !lastscan_valid || lastscan_error}
<svg
xmlns="http://www.w3.org/2000/svg"
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}
</h1>
<h1 class="text-3xl font-bold text-center">lap time</h1>
<h1 class="text-8xl font-bold text-center">{lastscan_laptime}</h1>
<h1 class="text-2xl font-bold text-center">{$_("lap-time")}</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}
<h1 class="text-3xl font-bold text-center">
{$_("please_scan_a_card")}

View File

@ -1,7 +1,7 @@
<script>
import { _ } from "svelte-i18n";
import { apikey, lang, page, stationinfo } from "./store.js";
import { apikey, api_endpoint, lang, page, stationinfo } from "./store.js";
</script>
<div class="p-5 min-h-screen">
@ -103,6 +103,7 @@
<button
on:click={() => {
apikey.set("");
api_endpoint.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"

View File

@ -1,4 +1,5 @@
{
"api_endpoint": "API-Endpunkt",
"api_key": "API Key",
"back_to_scanner": "Zurück zum Scanner",
"client_token": "Client Token",
@ -6,9 +7,12 @@
"configure": "Konfigurieren",
"error": "Error!",
"language": "Sprache",
"lap-time": "Rundenzeit",
"last-scan": "Letzter Scan um",
"log_out_from_this_client": "Von diesem Scanner abmelden",
"minimum_lap_time": "minimale Rundenzeit",
"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_the_scan_client_token": "Bitte gebe den Scan-Client-Token an.",
"please_scan_a_card": "Bitte scanne eine Karte ...",
@ -20,6 +24,7 @@
"station_id": "Scanstations-ID",
"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.",
"total-distance": "Gesamtdistanz",
"track_distance": "Länge des Tracks",
"track_id": "Track ID",
"track_name": "Track Name"

View File

@ -1,4 +1,5 @@
{
"api_endpoint": "API Endpoint",
"api_key": "API Key",
"back_to_scanner": "Back to Scanner",
"client_token": "Client Token",
@ -6,9 +7,12 @@
"configure": "Configure",
"error": "Error!",
"language": "Language",
"lap-time": "lap time",
"last-scan": "last scan",
"log_out_from_this_client": "Log Out from this Client",
"minimum_lap_time": "minimum lap time",
"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_the_scan_client_token": "Please provide the scan client token.",
"please_scan_a_card": "please scan a card...",
@ -20,6 +24,7 @@
"station_id": "Scanstation ID",
"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.",
"total-distance": "total distance",
"track_distance": "Track Distance",
"track_id": "Track ID",
"track_name": "Track Name"

View File

@ -1,5 +1,10 @@
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');
export const apikey = writable(stored_apikey);
apikey.subscribe((value) => {