Lint and format all files

This commit is contained in:
Djuri Baars 2023-11-19 20:27:22 +01:00
parent 3eaf897dbb
commit d25284e3a4
22 changed files with 1357 additions and 1280 deletions

View File

@ -18,6 +18,9 @@ module.exports = {
es2017: true, es2017: true,
node: true node: true
}, },
rules: {
'no-empty': ['error', { allowEmptyCatch: true }]
},
overrides: [ overrides: [
{ {
files: ['*.svelte'], files: ['*.svelte'],

View File

@ -3,7 +3,7 @@ name: BTClock WebUI CI
on: [push] on: [push]
env: env:
PUBLIC_BASE_URL: "" PUBLIC_BASE_URL: ''
jobs: jobs:
check-changes: check-changes:
@ -12,13 +12,13 @@ jobs:
all_changed_and_modified_files_count: ${{ steps.changed-files.outputs.all_changed_and_modified_files_count }} all_changed_and_modified_files_count: ${{ steps.changed-files.outputs.all_changed_and_modified_files_count }}
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v2 uses: actions/checkout@v4
- name: Get changed files count - name: Get changed files count
id: changed-files id: changed-files
uses: tj-actions/changed-files@v40.1.1 uses: tj-actions/changed-files@v40.1.1
with: with:
files_ignore: "doc/**,README.md,Dockerfile,.*" files_ignore: 'doc/**,README.md,Dockerfile,.*'
files_ignore_separator: ',' files_ignore_separator: ','
- name: Print changed files count - name: Print changed files count
run: > run: >
@ -33,7 +33,7 @@ jobs:
contents: write contents: write
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
with: with:
submodules: recursive submodules: recursive
- uses: actions/setup-node@v3 - uses: actions/setup-node@v3
@ -84,7 +84,7 @@ jobs:
tag: ${{ steps.getBlockHeight.outputs.blockHeight }} tag: ${{ steps.getBlockHeight.outputs.blockHeight }}
commit: main commit: main
name: release-${{ steps.getBlockHeight.outputs.blockHeight }} name: release-${{ steps.getBlockHeight.outputs.blockHeight }}
artifacts: "littlefs.bin,webui.tgz" artifacts: 'littlefs.bin,webui.tgz'
allowUpdates: true allowUpdates: true
removeArtifacts: true removeArtifacts: true
makeLatest: true makeLatest: true

View File

@ -8,7 +8,7 @@ node_modules
!.env.example !.env.example
dist/ dist/
build_gz build_gz
dist/**
# Ignore files for PNPM, NPM and YARN # Ignore files for PNPM, NPM and YARN
pnpm-lock.yaml pnpm-lock.yaml

View File

@ -1,10 +1,10 @@
import type { Handle } from '@sveltejs/kit' import type { Handle } from '@sveltejs/kit';
import { locale } from 'svelte-i18n' import { locale } from 'svelte-i18n';
export const handle: Handle = async ({ event, resolve }) => { export const handle: Handle = async ({ event, resolve }) => {
const lang = event.request.headers.get('accept-language')?.split(',')[0] const lang = event.request.headers.get('accept-language')?.split(',')[0];
if (lang) { if (lang) {
locale.set(lang) locale.set(lang);
} }
return resolve(event) return resolve(event);
} };

View File

@ -1,13 +1,17 @@
import { browser } from '$app/environment' import { browser } from '$app/environment';
import { init, register } from 'svelte-i18n' import { init, register } from 'svelte-i18n';
const defaultLocale = 'en' const defaultLocale = 'en';
register('en', () => import('../locales/en.json')) register('en', () => import('../locales/en.json'));
register('nl', () => import('../locales/nl.json')) register('nl', () => import('../locales/nl.json'));
register('es', () => import('../locales/es.json')) register('es', () => import('../locales/es.json'));
init({ init({
fallbackLocale: defaultLocale, fallbackLocale: defaultLocale,
initialLocale: browser ? browser && localStorage.getItem('locale') ? localStorage.getItem('locale') : window.navigator.language : defaultLocale, initialLocale: browser
}) ? browser && localStorage.getItem('locale')
? localStorage.getItem('locale')
: window.navigator.language
: defaultLocale
});

View File

@ -1,46 +1,46 @@
@import "../node_modules/bootstrap/scss/functions"; @import '../node_modules/bootstrap/scss/functions';
@import "../node_modules/bootstrap/scss/variables"; @import '../node_modules/bootstrap/scss/variables';
@import "../node_modules/bootstrap/scss/variables-dark"; @import '../node_modules/bootstrap/scss/variables-dark';
//@import "@fontsource/antonio/latin-400.css"; //@import "@fontsource/antonio/latin-400.css";
@import "@fontsource/ubuntu/latin-400.css"; @import '@fontsource/ubuntu/latin-400.css';
@import "@fontsource/oswald/latin-400.css"; @import '@fontsource/oswald/latin-400.css';
$form-range-track-bg: #fff; $form-range-track-bg: #fff;
$color-mode-type: media-query; $color-mode-type: media-query;
$font-family-base: "Ubuntu"; $font-family-base: 'Ubuntu';
$font-size-base: 0.9rem; $font-size-base: 0.9rem;
//$font-size-sm: $font-size-base * .875 !default; //$font-size-sm: $font-size-base * .875 !default;
//$form-label-font-size: $font-size-base * .575 !default; //$form-label-font-size: $font-size-base * .575 !default;
//$input-btn-font-size-sm: 0.4rem; //$input-btn-font-size-sm: 0.4rem;
//$form-label-font-size: 0.4rem; //$form-label-font-size: 0.4rem;
$input-font-size-sm: $font-size-base * .875; $input-font-size-sm: $font-size-base * 0.875;
// $border-radius: .675rem; // $border-radius: .675rem;
@import "../node_modules/bootstrap/scss/mixins"; @import '../node_modules/bootstrap/scss/mixins';
@import "../node_modules/bootstrap/scss/maps"; @import '../node_modules/bootstrap/scss/maps';
@import "../node_modules/bootstrap/scss/utilities"; @import '../node_modules/bootstrap/scss/utilities';
@import "../node_modules/bootstrap/scss/root"; @import '../node_modules/bootstrap/scss/root';
@import "../node_modules/bootstrap/scss/reboot"; @import '../node_modules/bootstrap/scss/reboot';
@import "../node_modules/bootstrap/scss/type"; @import '../node_modules/bootstrap/scss/type';
@import "../node_modules/bootstrap/scss/containers"; @import '../node_modules/bootstrap/scss/containers';
@import "../node_modules/bootstrap/scss/grid"; @import '../node_modules/bootstrap/scss/grid';
@import "../node_modules/bootstrap/scss/forms"; @import '../node_modules/bootstrap/scss/forms';
@import "../node_modules/bootstrap/scss/buttons"; @import '../node_modules/bootstrap/scss/buttons';
@import "../node_modules/bootstrap/scss/button-group"; @import '../node_modules/bootstrap/scss/button-group';
@import "../node_modules/bootstrap/scss/pagination"; @import '../node_modules/bootstrap/scss/pagination';
@import "../node_modules/bootstrap/scss/dropdown"; @import '../node_modules/bootstrap/scss/dropdown';
@import "../node_modules/bootstrap/scss/navbar"; @import '../node_modules/bootstrap/scss/navbar';
@import "../node_modules/bootstrap/scss/nav"; @import '../node_modules/bootstrap/scss/nav';
@import "../node_modules/bootstrap/scss/card"; @import '../node_modules/bootstrap/scss/card';
@import "../node_modules/bootstrap/scss/progress"; @import '../node_modules/bootstrap/scss/progress';
@import "../node_modules/bootstrap/scss/helpers"; @import '../node_modules/bootstrap/scss/helpers';
@import "../node_modules/bootstrap/scss/utilities/api"; @import '../node_modules/bootstrap/scss/utilities/api';
@include media-breakpoint-down(xl) { @include media-breakpoint-down(xl) {
html { html {
@ -48,10 +48,15 @@ $input-font-size-sm: $font-size-base * .875;
} }
button.btn, button.btn,
input[type="button"].btn, input[type='button'].btn,
input[type="submit"].btn, input[type='submit'].btn,
input[type="reset"].btn { input[type='reset'].btn {
@include button-size($btn-padding-y-sm, $btn-padding-x-sm, $font-size-sm, $btn-border-radius-sm); @include button-size(
$btn-padding-y-sm,
$btn-padding-x-sm,
$font-size-sm,
$btn-border-radius-sm
);
} }
} }
@ -61,7 +66,6 @@ $input-font-size-sm: $font-size-base * .875;
} }
} }
nav { nav {
margin-bottom: 15px; margin-bottom: 15px;
} }
@ -93,7 +97,7 @@ nav {
align-content: stretch; align-content: stretch;
font-family: 'Oswald', sans-serif; font-family: 'Oswald', sans-serif;
>div { > div {
padding: 5px; padding: 5px;
} }
@ -116,26 +120,26 @@ nav {
} }
} }
.darkMode .btclock>div { .darkMode .btclock > div {
color: #fff; color: #fff;
border-color: #fff; border-color: #fff;
} }
.lightMode .btclock>div { .lightMode .btclock > div {
background: #fff; background: #fff;
} }
.lightMode .btclock>div { .lightMode .btclock > div {
color: #000; color: #000;
} }
.darkMode .btclock>div { .darkMode .btclock > div {
background: #000; background: #000;
} }
.splitText { .splitText {
@include media-breakpoint-up(sm) { @include media-breakpoint-up(sm) {
font-size: 1.0rem; font-size: 1rem;
padding-top: 8px !important; padding-top: 8px !important;
padding-bottom: 9px !important; padding-bottom: 9px !important;
} }
@ -169,7 +173,7 @@ nav {
} }
.digit-blank { .digit-blank {
content: "abc"; content: 'abc';
} }
#customText { #customText {

View File

@ -1,21 +1,19 @@
<script lang="ts"> <script lang="ts">
import { import {
Navbar, Collapse,
NavbarBrand, Dropdown,
DropdownItem,
DropdownMenu,
DropdownToggle,
Nav, Nav,
NavItem, NavItem,
NavLink, NavLink,
Collapse, Navbar,
Dropdown, NavbarBrand
DropdownMenu,
DropdownItem,
DropdownToggle
} from 'sveltestrap'; } from 'sveltestrap';
import { locale, locales, waitLocale } from 'svelte-i18n';
import type { LayoutLoad } from './$types';
import { browser } from '$app/environment';
import { page } from '$app/stores'; import { page } from '$app/stores';
import { locale, locales } from 'svelte-i18n';
export const setLocale = (lang: string) => () => { export const setLocale = (lang: string) => () => {
locale.set(lang); locale.set(lang);
@ -33,7 +31,7 @@
const lowercaseCode = languageCode.toLowerCase(); const lowercaseCode = languageCode.toLowerCase();
// Check if the language code is in the flagMap // Check if the language code is in the flagMap
if (flagMap.hasOwnProperty(lowercaseCode)) { if (Object.prototype.hasOwnProperty.call(flagMap, lowercaseCode)) {
return flagMap[lowercaseCode]; return flagMap[lowercaseCode];
} else { } else {
// Return null for unsupported language codes // Return null for unsupported language codes
@ -50,7 +48,7 @@
const lowercaseCode = languageCode.toLowerCase(); const lowercaseCode = languageCode.toLowerCase();
return languageNames.hasOwnProperty(lowercaseCode) return Object.prototype.hasOwnProperty.call(languageNames, lowercaseCode)
? languageNames[lowercaseCode][lowercaseCode] ? languageNames[lowercaseCode][lowercaseCode]
: null; : null;
}; };
@ -71,7 +69,9 @@
<DropdownToggle nav caret>{getFlagEmoji($locale)} {getLanguageName($locale)}</DropdownToggle> <DropdownToggle nav caret>{getFlagEmoji($locale)} {getLanguageName($locale)}</DropdownToggle>
<DropdownMenu end> <DropdownMenu end>
{#each $locales as locale} {#each $locales as locale}
<DropdownItem on:click={setLocale(locale)}>{getFlagEmoji(locale)} {getLanguageName(locale)}</DropdownItem> <DropdownItem on:click={setLocale(locale)}
>{getFlagEmoji(locale)} {getLanguageName(locale)}</DropdownItem
>
{/each} {/each}
</DropdownMenu> </DropdownMenu>
</Dropdown> </Dropdown>

View File

@ -1,19 +1,18 @@
import "$lib/style/app.scss"; import '$lib/style/app.scss';
import { browser } from '$app/environment';
import { browser } from '$app/environment' import '$lib/i18n'; // Import to initialize. Important :)
import '$lib/i18n' // Import to initialize. Important :) import { locale, waitLocale } from 'svelte-i18n';
import { locale, waitLocale } from 'svelte-i18n' import type { LayoutLoad } from './$types';
import type { LayoutLoad } from './$types'
export const load: LayoutLoad = async () => { export const load: LayoutLoad = async () => {
if (browser && localStorage.getItem('locale')) { if (browser && localStorage.getItem('locale')) {
locale.set(localStorage.getItem('locale')); locale.set(localStorage.getItem('locale'));
} else if (browser) { } else if (browser) {
locale.set(window.navigator.language) locale.set(window.navigator.language);
} }
await waitLocale(); await waitLocale();
} };
export const prerender = true; export const prerender = true;
export const ssr = false; export const ssr = false;

View File

@ -1,44 +1,43 @@
<script lang="ts"> <script lang="ts">
import { PUBLIC_BASE_URL } from '$env/static/public'; import { PUBLIC_BASE_URL } from '$env/static/public';
import { _ } from 'svelte-i18n'; import { Container, Row } from 'sveltestrap';
import { Col, Container, Row } from 'sveltestrap';
import Control from './Control.svelte';
import Status from './Status.svelte';
import Settings from './Settings.svelte';
import { writable } from 'svelte/store';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import { writable } from 'svelte/store';
import Control from './Control.svelte';
import Settings from './Settings.svelte';
import Status from './Status.svelte';
let settings = writable({ let settings = writable({
fgColor: "0" fgColor: '0'
}); });
let status = writable({ let status = writable({
data: ["L", "O", "A", "D", "I", "N", "G"], data: ['L', 'O', 'A', 'D', 'I', 'N', 'G'],
espFreeHeap: 0, espFreeHeap: 0,
espHeapSize: 0, espHeapSize: 0,
connectionStatus: { connectionStatus: {
"price": false, price: false,
"blocks": false blocks: false
}, },
leds: [] leds: []
}); });
onMount(() => { onMount(() => {
fetch( PUBLIC_BASE_URL + `/api/settings`) fetch(PUBLIC_BASE_URL + `/api/settings`)
.then((res) => res.json()) .then((res) => res.json())
.then((data) => { .then((data) => {
data.fgColor = String(data.fgColor); data.fgColor = String(data.fgColor);
data.bgColor = String(data.bgColor); data.bgColor = String(data.bgColor);
data.timePerScreen = data.timerSeconds / 60; data.timePerScreen = data.timerSeconds / 60;
if (data.fgColor> 65535) { if (data.fgColor > 65535) {
data.fgColor = "65535"; data.fgColor = '65535';
} }
if (data.bgColor> 65535) { if (data.bgColor > 65535) {
data.bgColor = "65535"; data.bgColor = '65535';
} }
settings.set(data); settings.set(data);
}); });
@ -52,7 +51,7 @@
const evtSource = new EventSource(`${PUBLIC_BASE_URL}/events`); const evtSource = new EventSource(`${PUBLIC_BASE_URL}/events`);
evtSource.addEventListener('status', (e) => { evtSource.addEventListener('status', (e) => {
let dataObj = (JSON.parse(e.data)); let dataObj = JSON.parse(e.data);
status.set(dataObj); status.set(dataObj);
}); });
}); });

View File

@ -1,36 +1,33 @@
<script lang="ts"> <script lang="ts">
import { PUBLIC_BASE_URL } from '$env/static/public'; import { PUBLIC_BASE_URL } from '$env/static/public';
import { onDestroy } from 'svelte'; import { onDestroy } from 'svelte';
import { _ } from 'svelte-i18n'; import { _ } from 'svelte-i18n';
import type { Subscriber, Unsubscriber } from 'svelte/motion';
import type { Writable } from 'svelte/store'; import type { Writable } from 'svelte/store';
import { import {
Button, Button,
ButtonGroup,
Card, Card,
CardTitle,
CardBody, CardBody,
CardHeader, CardHeader,
CardTitle,
Col, Col,
Container,
Form, Form,
Input, Input,
Label, Label,
Row Row
} from 'sveltestrap'; } from 'sveltestrap';
export let settings = {}; export let settings = {};
export let customText:String; export let customText: string;
export let ledColor:String = "#FFCC00"; export let ledColor: string = '#FFCC00';
export let status:Writable<{leds:[]}>; export let status: Writable<{ leds: [] }>;
let ledStatus = []; let ledStatus = [];
let keepLedsSameColor = false; let keepLedsSameColor = false;
const setCustomText = () => { const setCustomText = () => {
fetch(`${PUBLIC_BASE_URL}/api/show/text/${customText}`).catch(err => { }); fetch(`${PUBLIC_BASE_URL}/api/show/text/${customText}`).catch(() => {});
}; };
const checkSyncLeds = (e:Event) => { const checkSyncLeds = (e: Event) => {
console.log('checksyncleds', keepLedsSameColor); console.log('checksyncleds', keepLedsSameColor);
if (keepLedsSameColor) { if (keepLedsSameColor) {
console.log(e.target.value); console.log(e.target.value);
@ -41,9 +38,9 @@ const checkSyncLeds = (e:Event) => {
} }
}); });
} }
} };
const setLEDcolor = () => { const setLEDcolor = () => {
console.log(`${PUBLIC_BASE_URL}/api/lights/${ledColor}`); console.log(`${PUBLIC_BASE_URL}/api/lights/${ledColor}`);
fetch(`${PUBLIC_BASE_URL}/api/lights`, { fetch(`${PUBLIC_BASE_URL}/api/lights`, {
headers: { headers: {
@ -51,32 +48,31 @@ const setLEDcolor = () => {
}, },
method: 'PATCH', method: 'PATCH',
body: JSON.stringify(ledStatus) body: JSON.stringify(ledStatus)
} }).catch(() => {});
).catch(err => { }); };
};
const turnOffLeds = () => { const turnOffLeds = () => {
fetch(`${PUBLIC_BASE_URL}/api/lights/off`).catch(err => { }); fetch(`${PUBLIC_BASE_URL}/api/lights/off`).catch(() => {});
}; };
const restartClock = () => { const restartClock = () => {
fetch(`${PUBLIC_BASE_URL}/api/restart`).catch(err => { }); fetch(`${PUBLIC_BASE_URL}/api/restart`).catch(() => {});
} };
const forceFullRefresh = () => { const forceFullRefresh = () => {
fetch(`${PUBLIC_BASE_URL}/api/full_refresh`).catch(err => { }); fetch(`${PUBLIC_BASE_URL}/api/full_refresh`).catch(() => {});
} };
let firstLedDataSubscription = () => {}; let firstLedDataSubscription = () => {};
firstLedDataSubscription = status.subscribe(async(val) => { firstLedDataSubscription = status.subscribe(async (val) => {
if (val && val.leds) { if (val && val.leds) {
ledStatus = val.leds.map((obj) => ({ ["hex"]: obj["hex"] })); ledStatus = val.leds.map((obj) => ({ ['hex']: obj['hex'] }));
firstLedDataSubscription(); firstLedDataSubscription();
} }
}) });
onDestroy(firstLedDataSubscription); onDestroy(firstLedDataSubscription);
</script> </script>
<Col> <Col>
@ -87,48 +83,72 @@ onDestroy(firstLedDataSubscription);
<CardBody> <CardBody>
<Form> <Form>
<Row> <Row>
<Label md={6} for="customText">{ $_('section.control.text') }</Label> <Label md={6} for="customText">{$_('section.control.text')}</Label>
<Col md="6"> <Col md="6">
<Input type="text" id="customText" bind:value={customText} bsSize="sm" maxLength="{$settings.numScreens}" /> <Input
type="text"
id="customText"
bind:value={customText}
bsSize="sm"
maxLength={$settings.numScreens}
/>
</Col> </Col>
</Row> </Row>
<Button color="primary" on:click={setCustomText}>{ $_('section.control.showText') }</Button> <Button color="primary" on:click={setCustomText}>{$_('section.control.showText')}</Button>
</Form> </Form>
<hr /> <hr />
<h3>LEDs</h3> <h3>LEDs</h3>
<Form> <Form>
<Row> <Row>
<Label md={6} for="ledColorPicker" size="sm">{ $_('section.control.ledColor') }</Label> <Label md={6} for="ledColorPicker" size="sm">{$_('section.control.ledColor')}</Label>
<Col md="6"> <Col md="6">
<Row class="justify-content-between"> <Row class="justify-content-between">
{#if ledStatus} {#if ledStatus}
{#each ledStatus as led, i } {#each ledStatus as led, i}
<Col> <Col>
<Input type="color" id="ledColorPicker[{i}]" bind:value="{led.hex}" class="mx-auto" on:change="{checkSyncLeds}" /> <Input
type="color"
id="ledColorPicker[{i}]"
bind:value={led.hex}
class="mx-auto"
on:change={checkSyncLeds}
/>
</Col> </Col>
{/each} {/each}
{/if} {/if}
<Col> <Col>
<Input bind:checked={keepLedsSameColor} type="switch" class="mx-auto" label="{ $_('sections.control.keepSameColor') }" /> <Input
bind:checked={keepLedsSameColor}
type="switch"
class="mx-auto"
label={$_('sections.control.keepSameColor')}
/>
</Col> </Col>
</Row> </Row>
</Col> </Col>
</Row> </Row>
<Button color="secondary" id="turnOffLedsBtn" on:click={turnOffLeds}>{ $_('section.control.turnOff') }</Button> <Button color="secondary" id="turnOffLedsBtn" on:click={turnOffLeds}
<Button color="primary" on:click={setLEDcolor}>{ $_('section.control.setColor') }</Button> >{$_('section.control.turnOff')}</Button
>
<Button color="primary" on:click={setLEDcolor}>{$_('section.control.setColor')}</Button>
</Form> </Form>
<hr /> <hr />
<h3>{ $_('section.control.systemInfo') }</h3> <h3>{$_('section.control.systemInfo')}</h3>
<ul class="small system_info"> <ul class="small system_info">
<li>{ $_('section.control.version') }: {$settings.gitRev}</li> <li>{$_('section.control.version')}: {$settings.gitRev}</li>
<li>{ $_('section.control.buildTime') }: {new Date(($settings.lastBuildTime * 1000)).toLocaleString()}</li> <li>
{$_('section.control.buildTime')}: {new Date(
$settings.lastBuildTime * 1000
).toLocaleString()}
</li>
<li>IP: {$settings.ip}</li> <li>IP: {$settings.ip}</li>
<li>{ $_('section.control.hostname') }: {$settings.hostname}</li> <li>{$_('section.control.hostname')}: {$settings.hostname}</li>
</ul> </ul>
<Button color="danger" id="restartBtn" on:click="{restartClock}">{ $_('button.restart') }</Button> <Button color="danger" id="restartBtn" on:click={restartClock}>{$_('button.restart')}</Button>
<Button color="warning" id="forceFullRefresh" on:click="{forceFullRefresh}">{ $_('button.forceFullRefresh') }</Button> <Button color="warning" id="forceFullRefresh" on:click={forceFullRefresh}
>{$_('button.forceFullRefresh')}</Button
>
</CardBody> </CardBody>
</Card> </Card>
</Col> </Col>

View File

@ -1,9 +1,9 @@
<script lang="ts"> <script lang="ts">
export let status = {}; export let status = {};
const isSplitText = (str:String) => { const isSplitText = (str: string) => {
return str.includes("/"); return str.includes('/');
} };
</script> </script>
<div class="btcclock-wrapper" id="btcclock-wrapper"> <div class="btcclock-wrapper" id="btcclock-wrapper">
@ -11,11 +11,11 @@
{#each status.data as char} {#each status.data as char}
{#if isSplitText(char)} {#if isSplitText(char)}
<div class="splitText"> <div class="splitText">
{#each char.split("/") as part} {#each char.split('/') as part}
<div class="flex-items">{part}</div> <div class="flex-items">{part}</div>
{/each} {/each}
</div> </div>
{:else if char.length === 0 || char === " "} {:else if char.length === 0 || char === ' '}
<div class="digit">&nbsp;&nbsp;</div> <div class="digit">&nbsp;&nbsp;</div>
{:else} {:else}
<div class="digit">{char}</div> <div class="digit">{char}</div>

View File

@ -1,46 +1,41 @@
<script lang="ts"> <script lang="ts">
import { PUBLIC_BASE_URL } from '$env/static/public'; import { PUBLIC_BASE_URL } from '$env/static/public';
import { onMount } from 'svelte';
import { readonly, writable } from 'svelte/store';
import { _ } from 'svelte-i18n'; import { _ } from 'svelte-i18n';
import { import {
Col, Button,
Container,
Row,
Card, Card,
CardTitle,
CardHeader,
CardBody, CardBody,
CardHeader,
CardTitle,
Col,
Form, Form,
FormGroup,
FormText, FormText,
Label,
Input, Input,
InputGroup, InputGroup,
InputGroupText, InputGroupText,
Button Label,
Row
} from 'sveltestrap'; } from 'sveltestrap';
export let settings; export let settings;
const onSave = async(e:Event) => { const onSave = async (e: Event) => {
e.preventDefault(); e.preventDefault();
let formSettings = $settings; let formSettings = $settings;
delete formSettings["gitRev"]; delete formSettings['gitRev'];
delete formSettings["ip"]; delete formSettings['ip'];
delete formSettings["lastBuildTime"]; delete formSettings['lastBuildTime'];
const res = await fetch(`${PUBLIC_BASE_URL}/api/json/settings`, { await fetch(`${PUBLIC_BASE_URL}/api/json/settings`, {
method: 'PATCH', method: 'PATCH',
headers: { headers: {
"Content-Type": "application/json", 'Content-Type': 'application/json'
}, },
body: JSON.stringify(formSettings) body: JSON.stringify(formSettings)
}) });
} };
</script> </script>
<Col> <Col>
@ -51,7 +46,9 @@
<CardBody> <CardBody>
<Form on:submit={onSave}> <Form on:submit={onSave}>
<Row> <Row>
<Label md={6} for="fgColor" size="sm">{$_('section.settings.textColor', { default: 'Text color' })}</Label> <Label md={6} for="fgColor" size="sm"
>{$_('section.settings.textColor', { default: 'Text color' })}</Label
>
<Col md="6"> <Col md="6">
<Input <Input
type="select" type="select"
@ -61,13 +58,13 @@
bsSize="sm" bsSize="sm"
class="form-select-sm" class="form-select-sm"
> >
<option value="0">{ $_('colors.black') }</option> <option value="0">{$_('colors.black')}</option>
<option value="65535">{ $_('colors.white') }</option> <option value="65535">{$_('colors.white')}</option>
</Input> </Input>
</Col> </Col>
</Row> </Row>
<Row> <Row>
<Label md={6} for="bgColor" size="sm">{ $_('section.settings.backgroundColor') }</Label> <Label md={6} for="bgColor" size="sm">{$_('section.settings.backgroundColor')}</Label>
<Col md="6"> <Col md="6">
<Input <Input
type="select" type="select"
@ -77,41 +74,45 @@
bsSize="sm" bsSize="sm"
class="form-select-sm" class="form-select-sm"
> >
<option value="0">{ $_('colors.black') }</option> <option value="0">{$_('colors.black')}</option>
<option value="65535">{ $_('colors.white') }</option> <option value="65535">{$_('colors.white')}</option>
</Input> </Input>
</Col> </Col>
</Row> </Row>
<Row> <Row>
<Label md={6} for="timePerScreen" size="sm">{ $_('section.settings.timePerScreen') }</Label> <Label md={6} for="timePerScreen" size="sm">{$_('section.settings.timePerScreen')}</Label>
<Col md="6"> <Col md="6">
<InputGroup size="sm"> <InputGroup size="sm">
<Input type="number" min={1} step="1" bind:value={$settings.timePerScreen} /> <Input type="number" min={1} step="1" bind:value={$settings.timePerScreen} />
<InputGroupText>{ $_('time.minutes') }</InputGroupText> <InputGroupText>{$_('time.minutes')}</InputGroupText>
</InputGroup> </InputGroup>
</Col> </Col>
</Row> </Row>
<Row> <Row>
<Label md={6} for="fullRefreshMin" size="sm">{ $_('section.settings.fullRefreshEvery') }</Label> <Label md={6} for="fullRefreshMin" size="sm"
>{$_('section.settings.fullRefreshEvery')}</Label
>
<Col md="6"> <Col md="6">
<InputGroup size="sm"> <InputGroup size="sm">
<Input type="number" min={1} step="1" bind:value={$settings.fullRefreshMin} /> <Input type="number" min={1} step="1" bind:value={$settings.fullRefreshMin} />
<InputGroupText>{ $_('time.minutes') }</InputGroupText> <InputGroupText>{$_('time.minutes')}</InputGroupText>
</InputGroup> </InputGroup>
</Col> </Col>
</Row> </Row>
<Row> <Row>
<Label md={6} for="minSecPriceUpd" size="sm">{ $_('section.settings.timeBetweenPriceUpdates') }</Label> <Label md={6} for="minSecPriceUpd" size="sm"
>{$_('section.settings.timeBetweenPriceUpdates')}</Label
>
<Col md="6"> <Col md="6">
<InputGroup size="sm"> <InputGroup size="sm">
<Input type="number" min={1} step="1" bind:value={$settings.minSecPriceUpd} /> <Input type="number" min={1} step="1" bind:value={$settings.minSecPriceUpd} />
<InputGroupText>{ $_('time.seconds') }</InputGroupText> <InputGroupText>{$_('time.seconds')}</InputGroupText>
</InputGroup> </InputGroup>
<FormText>{ $_('section.settings.shortAmountsWarning') }</FormText> <FormText>{$_('section.settings.shortAmountsWarning')}</FormText>
</Col> </Col>
</Row> </Row>
<Row> <Row>
<Label md={6} for="tzOffset" size="sm">{ $_('section.settings.timezoneOffset') }</Label> <Label md={6} for="tzOffset" size="sm">{$_('section.settings.timezoneOffset')}</Label>
<Col md="6"> <Col md="6">
<InputGroup size="sm"> <InputGroup size="sm">
<Input <Input
@ -122,13 +123,13 @@
id="tzOffset" id="tzOffset"
bind:value={$settings.tzOffset} bind:value={$settings.tzOffset}
/> />
<InputGroupText>{ $_('time.minutes') }</InputGroupText> <InputGroupText>{$_('time.minutes')}</InputGroupText>
</InputGroup> </InputGroup>
<FormText>{ $_('section.settings.tzOffsetHelpText') }</FormText> <FormText>{$_('section.settings.tzOffsetHelpText')}</FormText>
</Col> </Col>
</Row> </Row>
<Row> <Row>
<Label md={6} for="ledBrightness" size="sm">{ $_('section.settings.ledBrightness') }</Label> <Label md={6} for="ledBrightness" size="sm">{$_('section.settings.ledBrightness')}</Label>
<Col md="6"> <Col md="6">
<Input <Input
type="range" type="range"
@ -142,7 +143,9 @@
</Col> </Col>
</Row> </Row>
<Row> <Row>
<Label md={6} for="mempoolInstance" size="sm">{ $_('section.settings.mempoolnstance') }</Label> <Label md={6} for="mempoolInstance" size="sm"
>{$_('section.settings.mempoolnstance')}</Label
>
<Col md="6"> <Col md="6">
<Input <Input
type="text" type="text"
@ -150,12 +153,13 @@
name="mempoolInstance" name="mempoolInstance"
id="mempoolInstance" id="mempoolInstance"
bsSize="sm" bsSize="sm"
> ></Input>
</Input>
</Col> </Col>
</Row> </Row>
<Row> <Row>
<Label md={6} for="hostnamePrefix" size="sm">{ $_('section.settings.hostnamePrefix') }</Label> <Label md={6} for="hostnamePrefix" size="sm"
>{$_('section.settings.hostnamePrefix')}</Label
>
<Col md="6"> <Col md="6">
<Input <Input
type="text" type="text"
@ -163,46 +167,93 @@
name="hostnamePrefix" name="hostnamePrefix"
id="hostnamePrefix" id="hostnamePrefix"
bsSize="sm" bsSize="sm"
> ></Input>
</Input>
</Col> </Col>
</Row> </Row>
<Row> <Row>
<Col md="6"> <Col md="6">
<Input id="ledTestOnPower" bind:checked={$settings.ledTestOnPower} type="switch" bsSize="sm" label="{ $_('section.settings.ledPowerOnTest') }" /> <Input
id="ledTestOnPower"
bind:checked={$settings.ledTestOnPower}
type="switch"
bsSize="sm"
label={$_('section.settings.ledPowerOnTest')}
/>
</Col> </Col>
<Col md="6"> <Col md="6">
<Input id="ledFlashOnUpd" bind:checked={$settings.ledFlashOnUpd} type="switch" bsSize="sm" label="{ $_('section.settings.ledFlashOnBlock') }" /> <Input
id="ledFlashOnUpd"
bind:checked={$settings.ledFlashOnUpd}
type="switch"
bsSize="sm"
label={$_('section.settings.ledFlashOnBlock')}
/>
</Col> </Col>
<Col md="6"> <Col md="6">
<Input id="stealFocus" bind:checked={$settings.stealFocus} type="switch" bsSize="sm" label="{ $_('section.settings.StealFocusOnNewBlock') }" /> <Input
id="stealFocus"
bind:checked={$settings.stealFocus}
type="switch"
bsSize="sm"
label={$_('section.settings.StealFocusOnNewBlock')}
/>
</Col> </Col>
<Col md="6"> <Col md="6">
<Input id="mcapBigChar" bind:checked={$settings.mcapBigChar} type="switch" bsSize="sm" label="{ $_('section.settings.useBigCharsMcap') }" /> <Input
id="mcapBigChar"
bind:checked={$settings.mcapBigChar}
type="switch"
bsSize="sm"
label={$_('section.settings.useBigCharsMcap')}
/>
</Col> </Col>
<Col md="6"> <Col md="6">
<Input id="otaEnabled" bind:checked={$settings.otaEnabled} type="switch" bsSize="sm" label="{ $_('section.settings.otaUpdates') } ({ $_('restartRequired') })" /> <Input
id="otaEnabled"
bind:checked={$settings.otaEnabled}
type="switch"
bsSize="sm"
label="{$_('section.settings.otaUpdates')} ({$_('restartRequired')})"
/>
</Col> </Col>
<Col md="6"> <Col md="6">
<Input id="mdnsEnabled" bind:checked={$settings.mdnsEnabled} type="switch" bsSize="sm" label="{ $_('section.settings.enableMdns') } ({ $_('restartRequired') })" /> <Input
id="mdnsEnabled"
bind:checked={$settings.mdnsEnabled}
type="switch"
bsSize="sm"
label="{$_('section.settings.enableMdns')} ({$_('restartRequired')})"
/>
</Col> </Col>
<Col md="6"> <Col md="6">
<Input id="fetchEurPrice" bind:checked={$settings.fetchEurPrice} type="switch" bsSize="sm" label="{ $_('section.settings.fetchEuroPrice') } ({ $_('restartRequired') })" /> <Input
id="fetchEurPrice"
bind:checked={$settings.fetchEurPrice}
type="switch"
bsSize="sm"
label="{$_('section.settings.fetchEuroPrice')} ({$_('restartRequired')})"
/>
</Col> </Col>
</Row> </Row>
<Row> <Row>
<h3>{ $_('section.settings.screens') }</h3> <h3>{$_('section.settings.screens')}</h3>
{#if $settings.screens} {#if $settings.screens}
{#each $settings.screens as s} {#each $settings.screens as s}
<Col md="6"> <Col md="6">
<Input id="screens_{s.id}" bind:checked={s.enabled} type="switch" bsSize="sm" label="{s.name}" /> <Input
id="screens_{s.id}"
bind:checked={s.enabled}
type="switch"
bsSize="sm"
label={s.name}
/>
</Col> </Col>
{/each} {/each}
{/if} {/if}
</Row> </Row>
<Button type="reset" color="secondary">{ $_('button.reset') }</Button> <Button type="reset" color="secondary">{$_('button.reset')}</Button>
<Button color="primary">{ $_('button.save') }</Button> <Button color="primary">{$_('button.save')}</Button>
</Form> </Form>
</CardBody> </CardBody>
</Card> </Card>

View File

@ -1,16 +1,26 @@
<script lang="ts"> <script lang="ts">
import { PUBLIC_BASE_URL } from '$env/static/public'; import { PUBLIC_BASE_URL } from '$env/static/public';
import { onMount } from 'svelte';
import { _ } from 'svelte-i18n'; import { _ } from 'svelte-i18n';
import { writable, type Writable } from 'svelte/store'; import { writable } from 'svelte/store';
import { Row, Input, Button, ButtonGroup, Card, CardBody, CardHeader, Col, Progress,CardTitle } from 'sveltestrap'; import {
Button,
ButtonGroup,
Card,
CardBody,
CardHeader,
CardTitle,
Col,
Input,
Progress,
Row
} from 'sveltestrap';
import Rendered from './Rendered.svelte'; import Rendered from './Rendered.svelte';
export let settings; export let settings;
export let status:Writable<{}>; export let status: writable<object>;
const toTime = (secs:Number) => { const toTime = (secs: number) => {
var hours = Math.floor(secs / (60 * 60)); var hours = Math.floor(secs / (60 * 60));
var divisor_for_minutes = secs % (60 * 60); var divisor_for_minutes = secs % (60 * 60);
@ -20,46 +30,42 @@
var seconds = Math.ceil(divisor_for_seconds); var seconds = Math.ceil(divisor_for_seconds);
var obj = { var obj = {
"h": hours, h: hours,
"m": minutes, m: minutes,
"s": seconds s: seconds
}; };
return obj; return obj;
} };
const toUptimeString = (secs:Number):String => { const toUptimestring = (secs: number): string => {
let time = toTime(secs); let time = toTime(secs);
return `${time.h}h ${time.m}m ${time.s}s`; return `${time.h}h ${time.m}m ${time.s}s`;
} };
let memoryFreePercent:number = 50; let memoryFreePercent: number = 50;
let lightMode:boolean = false; let lightMode: boolean = false;
status.subscribe((value: {}) => { status.subscribe((value: object) => {
memoryFreePercent = Math.round(value.espFreeHeap / value.espHeapSize * 100); memoryFreePercent = Math.round((value.espFreeHeap / value.espHeapSize) * 100);
}); });
settings.subscribe((value: {}) => { settings.subscribe((value: object) => {
lightMode = value.bgColor > value.fgColor; lightMode = value.bgColor > value.fgColor;
}); });
const setScreen = (id:number) => () => { const setScreen = (id: number) => () => {
fetch(`${PUBLIC_BASE_URL}/api/show/screen/${id}`).catch(err => { }); fetch(`${PUBLIC_BASE_URL}/api/show/screen/${id}`).catch(() => {});
} };
const toggleTimer = (currentStatus:boolean) => () => { const toggleTimer = (currentStatus: boolean) => (e: Event) => {
e.preventDefault();
if (currentStatus) { if (currentStatus) {
fetch(`${PUBLIC_BASE_URL}/api/action/pause`); fetch(`${PUBLIC_BASE_URL}/api/action/pause`);
} else { } else {
fetch(`${PUBLIC_BASE_URL}/api/action/timer_restart`); fetch(`${PUBLIC_BASE_URL}/api/action/timer_restart`);
} }
} };
const isLightMode = () => {
return $settings.bgColor > $settings.fgColor;
}
</script> </script>
<Col> <Col>
@ -72,39 +78,62 @@
<div class="d-flex justify-content-center"> <div class="d-flex justify-content-center">
<ButtonGroup size="sm"> <ButtonGroup size="sm">
{#each $settings.screens as s} {#each $settings.screens as s}
<Button color="outline-primary" active={$status.currentScreen == s.id} on:click={setScreen(s.id)}>{s.name}</Button> <Button
color="outline-primary"
active={$status.currentScreen == s.id}
on:click={setScreen(s.id)}>{s.name}</Button
>
{/each} {/each}
</ButtonGroup> </ButtonGroup>
</div> </div>
<hr> <hr />
{#if $status.data} {#if $status.data}
<section class={lightMode ? 'lightMode': ''}> <section class={lightMode ? 'lightMode' : ''}>
<Rendered status="{$status}"></Rendered> <Rendered status={$status}></Rendered>
</section> </section>
{ $_('section.status.screenCycle') }: <a style="cursor: pointer" on:click="{toggleTimer($status.timerRunning)}">{#if $status.timerRunning}&#9205; { $_('timer.running') }{:else}&#9208; { $_('timer.stopped') }{/if}</a> {$_('section.status.screenCycle')}:
<a
href={'#'}
style="cursor: pointer"
tabindex="0"
role="button"
aria-pressed="false"
on:click={toggleTimer($status.timerRunning)}
>{#if $status.timerRunning}&#9205; {$_('timer.running')}{:else}&#9208; {$_(
'timer.stopped'
)}{/if}</a
>
{/if} {/if}
{/if} {/if}
<hr> <hr />
<Row class="justify-content-evenly"> <Row class="justify-content-evenly">
{#if $status.leds} {#if $status.leds}
{#each $status.leds as led} {#each $status.leds as led}
<Col> <Col>
<Input type="color" id="ledColorPicker" bind:value="{led.hex}" class="mx-auto" disabled /> <Input
type="color"
id="ledColorPicker"
bind:value={led.hex}
class="mx-auto"
disabled
/>
</Col> </Col>
{/each} {/each}
{/if} {/if}
</Row> </Row>
<hr> <hr />
<Progress striped value={memoryFreePercent}>{ memoryFreePercent }%</Progress> <Progress striped value={memoryFreePercent}>{memoryFreePercent}%</Progress>
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
<div>{ $_('section.status.memoryFree') } </div> <div>{$_('section.status.memoryFree')}</div>
<div>{ Math.round($status.espFreeHeap / 1024) } / { Math.round($status.espHeapSize / 1024) } KiB</div> <div>
{Math.round($status.espFreeHeap / 1024)} / {Math.round($status.espHeapSize / 1024)} KiB
</div> </div>
<hr> </div>
{ $_('section.status.uptime') }: {toUptimeString($status.espUptime)} <hr />
<br> {$_('section.status.uptime')}: {toUptimestring($status.espUptime)}
<br />
<p> <p>
{ $_('section.status.wsPriceConnection') }: {$_('section.status.wsPriceConnection')}:
<span> <span>
{#if $status.connectionStatus && $status.connectionStatus.price} {#if $status.connectionStatus && $status.connectionStatus.price}
&#9989; &#9989;
@ -113,19 +142,18 @@
{/if} {/if}
</span> </span>
- -
{ $_('section.status.wsMempoolConnection') }: {$_('section.status.wsMempoolConnection')}:
<span> <span>
{#if $status.connectionStatus && $status.connectionStatus.blocks} {#if $status.connectionStatus && $status.connectionStatus.blocks}
&#9989; &#9989;
{:else} {:else}
&#10060; &#10060;
{/if} {/if}
</span><br> </span><br />
{#if $settings.fetchEurPrice} {#if $settings.fetchEurPrice}
<small>{ $_('section.status.fetchEuroNote') }</small> <small>{$_('section.status.fetchEuroNote')}</small>
{/if} {/if}
</p> </p>
</CardBody> </CardBody>
</Card> </Card>
</Col> </Col>

View File

@ -1,36 +1,31 @@
<script lang="ts"> <script lang="ts">
import { _ } from 'svelte-i18n'; import { Button, Container } from 'sveltestrap';
import { Col, Container, Row, Button } from 'sveltestrap';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
//import * as swaggerJson from '../../../static/swagger.json'; let swaggerLoaded: boolean = false;
// import SwaggerUI from 'swagger-ui';
import 'swagger-ui/dist/swagger-ui.css';
let swaggerLoaded:boolean = false;
onMount(async () => { onMount(async () => {
// @ts-ignore
loadSwagger(); loadSwagger();
}); });
const loadSwagger = () => { const loadSwagger = () => {
if (!SwaggerUIBundle) // @ts-expect-error: SwaggerUIBundle is loaded from external script from CDN
return; if (!SwaggerUIBundle) return; // eslint-disable-line
swaggerLoaded = true; swaggerLoaded = true;
// @ts-expect-error: SwaggerUIBundle is loaded from external script from CDN
// eslint-disable-next-line
window.ui = SwaggerUIBundle({ window.ui = SwaggerUIBundle({
url: '/swagger.json', url: '/swagger.json',
dom_id: '#swagger-ui-container', dom_id: '#swagger-ui-container',
presets: [ presets: [
// @ts-ignore // @ts-expect-error: SwaggerUIBundle is loaded from external script from CDN
SwaggerUIBundle.presets.apis, SwaggerUIBundle.presets.apis, // eslint-disable-line
// @ts-ignore // @ts-expect-error: SwaggerUIStandalonePreset is loaded from external script from CDN
SwaggerUIStandalonePreset SwaggerUIStandalonePreset // eslint-disable-line
], ]
// layout: "StandaloneLayout", // layout: "StandaloneLayout",
}); });
} };
</script> </script>
<svelte:head> <svelte:head>
@ -54,11 +49,9 @@
crossorigin="anonymous" crossorigin="anonymous"
referrerpolicy="no-referrer" referrerpolicy="no-referrer"
/> />
</svelte:head> </svelte:head>
<Container fluid class="bg-light"> <Container fluid class="bg-light">
<section class:invisible={swaggerLoaded}><Button on:click="{loadSwagger}">Load</Button></section> <section class:invisible={swaggerLoaded}><Button on:click={loadSwagger}>Load</Button></section>
<div id="swagger-ui-container" /> <div id="swagger-ui-container" />
</Container> </Container>

View File

@ -13,9 +13,7 @@
"paths": { "paths": {
"/status": { "/status": {
"get": { "get": {
"tags": [ "tags": ["system"],
"system"
],
"summary": "Get current status", "summary": "Get current status",
"responses": { "responses": {
"200": { "200": {
@ -26,9 +24,7 @@
}, },
"/system_status": { "/system_status": {
"get": { "get": {
"tags": [ "tags": ["system"],
"system"
],
"summary": "Get system status", "summary": "Get system status",
"responses": { "responses": {
"200": { "200": {
@ -39,9 +35,7 @@
}, },
"/settings": { "/settings": {
"get": { "get": {
"tags": [ "tags": ["system"],
"system"
],
"summary": "Get current settings", "summary": "Get current settings",
"responses": { "responses": {
"200": { "200": {
@ -57,9 +51,7 @@
} }
}, },
"post": { "post": {
"tags": [ "tags": ["system"],
"system"
],
"summary": "Save current settings", "summary": "Save current settings",
"requestBody": { "requestBody": {
"content": { "content": {
@ -77,9 +69,7 @@
} }
}, },
"patch": { "patch": {
"tags": [ "tags": ["system"],
"system"
],
"summary": "Save current settings", "summary": "Save current settings",
"requestBody": { "requestBody": {
"content": { "content": {
@ -99,9 +89,7 @@
}, },
"/action/pause": { "/action/pause": {
"get": { "get": {
"tags": [ "tags": ["timer"],
"timer"
],
"summary": "Pause screen rotation", "summary": "Pause screen rotation",
"responses": { "responses": {
"200": { "200": {
@ -112,9 +100,7 @@
}, },
"/action/timer_restart": { "/action/timer_restart": {
"get": { "get": {
"tags": [ "tags": ["timer"],
"timer"
],
"summary": "Restart screen rotation", "summary": "Restart screen rotation",
"responses": { "responses": {
"200": { "200": {
@ -125,9 +111,7 @@
}, },
"/show/screen/{id}": { "/show/screen/{id}": {
"get": { "get": {
"tags": [ "tags": ["screens"],
"screens"
],
"summary": "Set screen to show", "summary": "Set screen to show",
"parameters": [ "parameters": [
{ {
@ -150,9 +134,7 @@
}, },
"/show/text/{text}": { "/show/text/{text}": {
"get": { "get": {
"tags": [ "tags": ["screens"],
"screens"
],
"summary": "Set text to show", "summary": "Set text to show",
"parameters": [ "parameters": [
{ {
@ -175,9 +157,7 @@
}, },
"/show/custom": { "/show/custom": {
"post": { "post": {
"tags": [ "tags": ["screens"],
"screens"
],
"summary": "Set text to show (advanced)", "summary": "Set text to show (advanced)",
"requestBody": { "requestBody": {
"content": { "content": {
@ -197,9 +177,7 @@
}, },
"/full_refresh": { "/full_refresh": {
"get": { "get": {
"tags": [ "tags": ["system"],
"system"
],
"summary": "Force full refresh of all displays", "summary": "Force full refresh of all displays",
"responses": { "responses": {
"200": { "200": {
@ -210,9 +188,7 @@
}, },
"/lights": { "/lights": {
"get": { "get": {
"tags": [ "tags": ["lights"],
"lights"
],
"summary": "Get LEDs status", "summary": "Get LEDs status",
"responses": { "responses": {
"200": { "200": {
@ -228,9 +204,7 @@
} }
}, },
"patch": { "patch": {
"tags": [ "tags": ["lights"],
"lights"
],
"summary": "Set individual LEDs", "summary": "Set individual LEDs",
"requestBody": { "requestBody": {
"content": { "content": {
@ -253,9 +227,7 @@
}, },
"/lights/{color}": { "/lights/{color}": {
"get": { "get": {
"tags": [ "tags": ["lights"],
"lights"
],
"summary": "Turn on LEDs with specific color", "summary": "Turn on LEDs with specific color",
"parameters": [ "parameters": [
{ {
@ -278,9 +250,7 @@
}, },
"/lights/off": { "/lights/off": {
"get": { "get": {
"tags": [ "tags": ["lights"],
"lights"
],
"summary": "Turn LEDs off", "summary": "Turn LEDs off",
"responses": { "responses": {
"200": { "200": {
@ -291,9 +261,7 @@
}, },
"/restart": { "/restart": {
"get": { "get": {
"tags": [ "tags": ["system"],
"system"
],
"summary": "Restart BTClock", "summary": "Restart BTClock",
"responses": { "responses": {
"200": { "200": {

View File

@ -149,9 +149,9 @@ paths:
schema: schema:
$ref: '#/components/schemas/ArrayOfLedsInput' $ref: '#/components/schemas/ArrayOfLedsInput'
responses: responses:
"200": '200':
description: succesful operation description: succesful operation
"400": '400':
description: invalid colors or wrong amount of LEDs description: invalid colors or wrong amount of LEDs
/lights/{color}: /lights/{color}:
get: get:
@ -211,7 +211,7 @@ components:
hex: hex:
type: string type: string
pattern: ^#(?:[0-9a-fA-F]{3}){1,2}$ pattern: ^#(?:[0-9a-fA-F]{3}){1,2}$
example: "#FFCC00" example: '#FFCC00'
RgbColorValueAndHex: RgbColorValueAndHex:
allOf: allOf:
- $ref: '#/components/schemas/RgbColorValues' - $ref: '#/components/schemas/RgbColorValues'

View File

@ -5,16 +5,14 @@ import { vitePreprocess } from '@sveltejs/kit/vite';
const config = { const config = {
// Consult https://kit.svelte.dev/docs/integrations#preprocessors // Consult https://kit.svelte.dev/docs/integrations#preprocessors
// for more information about preprocessors // for more information about preprocessors
preprocess: vitePreprocess({ preprocess: vitePreprocess({}),
build: {
}),
build: {
rollupOptions: { rollupOptions: {
output: { output: {
assetFilenames: '[hash]' assetFilenames: '[hash]'
} }
} }
}, },
kit: { kit: {
// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list. // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
// If your environment is not supported or you settled on a specific environment, switch out the adapter. // If your environment is not supported or you settled on a specific environment, switch out the adapter.
@ -24,11 +22,11 @@ build: {
// these options are set automatically — see below // these options are set automatically — see below
pages: 'dist', pages: 'dist',
assets: 'dist', assets: 'dist',
fallback: "bundle.html", fallback: 'bundle.html',
precompress: false, precompress: false,
strict: true strict: true
}), }),
appDir: "build", appDir: 'build'
// inlineStyleThreshold: 9999999999 // inlineStyleThreshold: 9999999999
} }
}; };

View File

@ -1,61 +1,71 @@
import { sveltekit } from '@sveltejs/kit/vite'; import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite'; import { defineConfig } from 'vite';
import * as fs from 'fs' import * as fs from 'fs';
import * as path from 'path' import * as path from 'path';
const doRewrap = ({ cssClass }) => { const doRewrap = ({ cssClass }) => {
try { try {
if (fs.existsSync(path.resolve(__dirname, 'dist/bundle.js'))) { if (fs.existsSync(path.resolve(__dirname, 'dist/bundle.js'))) {
return return;
} }
} catch(e) {} } catch (e) {}
console.log("\nStart re-wrapping...") console.log('\nStart re-wrapping...');
fs.readFile(path.resolve(__dirname, 'dist/bundle.html'), 'utf8', function(err, data){ fs.readFile(path.resolve(__dirname, 'dist/bundle.html'), 'utf8', function (err, data) {
if (!data) { if (!data) {
console.log(`[Error]: No bundle.html generated, check svelte.config.js -> config.kit.adapter -> fallback: "bundle.html"`) console.log(
return `[Error]: No bundle.html generated, check svelte.config.js -> config.kit.adapter -> fallback: "bundle.html"`
);
return;
} }
let matchData = data.match(/(?<=<script\b[^>]*>)([\s\S]*?)(?=<\/script>)/gm) const matchData = data.match(/(?<=<script\b[^>]*>)([\s\S]*?)(?=<\/script>)/gm);
if (matchData) { if (matchData) {
let cleanData = matchData[0].trim() const cleanData = matchData[0]
.replace(`document.querySelector('[data-sveltekit-hydrate="45h"]').parentNode`, `document.querySelector(".${cssClass}")`) .trim()
.replace(
`document.querySelector('[data-sveltekit-hydrate="45h"]').parentNode`,
`document.querySelector(".${cssClass}")`
);
fs.writeFile(path.resolve(__dirname, 'dist/bundle.js'), cleanData, (err) => { fs.writeFile(path.resolve(__dirname, 'dist/bundle.js'), cleanData, (err) => {
if (err) if (err) console.log(err);
console.log(err)
else { else {
try { try {
fs.rename(path.resolve(__dirname,'dist/index.page'), path.resolve(__dirname, 'dist/index.html'), (err) => { }) fs.rename(
} catch (e) { } path.resolve(__dirname, 'dist/index.page'),
path.resolve(__dirname, 'dist/index.html'),
() => {}
);
} catch (e) {}
try { try {
fs.unlinkSync(path.resolve(__dirname, 'dist/bundle.html')) fs.unlinkSync(path.resolve(__dirname, 'dist/bundle.html'));
} catch (e) { } } catch (e) {}
console.log("Finished: bundle.js + index.html have been regenerated.\n") console.log('Finished: bundle.js + index.html have been regenerated.\n');
} }
}) });
} else } else console.log(`[Error]: No proper <script> tag found in bundle.html`);
console.log(`[Error]: No proper <script> tag found in bundle.html`) });
}) };
}
export default defineConfig({ export default defineConfig({
plugins: [sveltekit(), { plugins: [
sveltekit(),
{
name: 'postbuild-command', name: 'postbuild-command',
closeBundle: { closeBundle: {
order: 'post', order: 'post',
handler() { handler() {
setTimeout(() => doRewrap({ cssClass: "overlay" }), Math.random()*500+500) setTimeout(() => doRewrap({ cssClass: 'overlay' }), Math.random() * 500 + 500);
} }
} }
}], }
],
build: { build: {
minify: true, minify: true,
cssCodeSplit: false, cssCodeSplit: false,
rollupOptions: { rollupOptions: {
output: { output: {
manualChunks: () => 'app', manualChunks: () => 'app',
assetFileNames: "[name][extname]" assetFileNames: '[name][extname]'
} }
} }
} }