Better feedback when auto-updating and improve handling of disconnects and restarts
All checks were successful
/ build (push) Successful in 4m41s
/ check-changes (push) Successful in 7s

This commit is contained in:
Djuri 2024-12-28 20:45:10 +01:00
parent 4057e18755
commit 468e105adf
12 changed files with 378 additions and 255 deletions

View file

@ -0,0 +1,11 @@
<script lang="ts">
export let value: unknown;
export let checkValue: unknown = null;
export let width: number = 25;
$: valueToCheck = checkValue === null ? value : checkValue;
</script>
<span class:placeholder={!valueToCheck} class={!valueToCheck ? `w-${width}` : ''}>
{valueToCheck ? value : ''}
</span>

View file

@ -3,3 +3,4 @@ export { default as SettingsInput } from './SettingsInput.svelte';
export { default as SettingsSelect } from './SettingsSelect.svelte';
export { default as ToggleHeader } from './ToggleHeader.svelte';
export { default as ColorSchemeSwitcher } from './ColorSchemeSwitcher.svelte';
export { default as Placeholder } from './Placeholder.svelte';

View file

@ -107,7 +107,8 @@
"latestVersion": "Letzte Version",
"releaseDate": "Veröffentlichungsdatum",
"viewRelease": "Veröffentlichung anzeigen",
"autoUpdate": "Update installieren (experimentell)"
"autoUpdate": "Update installieren (experimentell)",
"autoUpdateInProgress": "Automatische Aktualisierung läuft, bitte warten..."
}
},
"colors": {

View file

@ -126,7 +126,8 @@
"latestVersion": "Latest Version",
"releaseDate": "Release Date",
"viewRelease": "View Release",
"autoUpdate": "Install update (experimental)"
"autoUpdate": "Install update (experimental)",
"autoUpdateInProgress": "Auto-update in progress, please wait..."
}
},
"colors": {

View file

@ -106,7 +106,8 @@
"latestVersion": "Ultima versión",
"releaseDate": "Fecha de lanzamiento",
"viewRelease": "Ver lanzamiento",
"autoUpdate": "Instalar actualización (experimental)"
"autoUpdate": "Instalar actualización (experimental)",
"autoUpdateInProgress": "Actualización automática en progreso, espere..."
}
},
"button": {

View file

@ -97,7 +97,8 @@
"latestVersion": "Laatste versie",
"releaseDate": "Datum van publicatie",
"viewRelease": "Bekijk publicatie",
"autoUpdate": "Update installeren (experimenteel)"
"autoUpdate": "Update installeren (experimenteel)",
"autoUpdateInProgress": "Automatische update wordt uitgevoerd. Even geduld a.u.b...."
}
},
"colors": {

View file

@ -53,6 +53,8 @@ $input-font-size-sm: $font-size-base * 0.875;
@import '../node_modules/bootstrap/scss/tooltip';
@import '../node_modules/bootstrap/scss/toasts';
@import '../node_modules/bootstrap/scss/alert';
@import '../node_modules/bootstrap/scss/placeholders';
@import '../node_modules/bootstrap/scss/spinners';
@import '../node_modules/bootstrap/scss/helpers';
@import '../node_modules/bootstrap/scss/utilities/api';
@ -317,3 +319,34 @@ input[type='number'] {
.lightMode .bitaxelogo {
filter: brightness(0) saturate(100%);
}
.connection-lost-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.75);
z-index: 1050;
display: flex;
justify-content: center;
align-items: center;
.overlay-content {
background-color: rgba(255, 255, 255, 0.75);
padding: 0.5rem;
border-radius: 0.5rem;
text-align: center;
i {
font-size: 1rem;
color: $danger;
margin-bottom: 1rem;
}
h4 {
margin-bottom: 0.5rem;
}
}
}

View file

@ -14,7 +14,8 @@
let settings = writable({
fgColor: '0',
bgColor: '0'
bgColor: '0',
isLoaded: false
});
let status = writable({
@ -25,21 +26,33 @@
price: false,
blocks: false
},
leds: []
leds: [],
isUpdating: false
});
const fetchStatusData = () => {
fetch(`${PUBLIC_BASE_URL}/api/status`, { credentials: 'same-origin' })
.then((res) => res.json())
.then((data) => {
const fetchStatusData = async () => {
const res = await fetch(`${PUBLIC_BASE_URL}/api/status`, { credentials: 'same-origin' });
if (!res.ok) {
console.error('Error fetching status data:', res.statusText);
return false;
}
const data = await res.json();
status.set(data);
});
return true;
};
const fetchSettingsData = () => {
fetch(PUBLIC_BASE_URL + `/api/settings`, { credentials: 'same-origin' })
.then((res) => res.json())
.then((data) => {
const fetchSettingsData = async () => {
const res = await fetch(PUBLIC_BASE_URL + `/api/settings`, { credentials: 'same-origin' });
if (!res.ok) {
console.error('Error fetching settings data:', res.statusText);
return;
}
const data = await res.json();
data.fgColor = String(data.fgColor);
data.bgColor = String(data.bgColor);
data.timePerScreen = data.timerSeconds / 60;
@ -52,7 +65,6 @@
data.bgColor = '65535';
}
settings.set(data);
});
};
let sections: (HTMLElement | null)[];
@ -89,19 +101,46 @@
}
};
onMount(() => {
onMount(async () => {
setupObserver();
fetchSettingsData();
fetchStatusData();
const connectEventSource = () => {
console.log('Connecting to EventSource');
const evtSource = new EventSource(`${PUBLIC_BASE_URL}/events`);
evtSource.addEventListener('status', (e) => {
let dataObj = JSON.parse(e.data);
status.update((s) => ({ ...s, isUpdating: true }));
status.set(dataObj);
});
evtSource.addEventListener('message', (e) => {
if (e.data == 'closing') {
console.log('EventSource closing');
status.update((s) => ({ ...s, isUpdating: false }));
evtSource.close(); // Close the current connection
setTimeout(connectEventSource, 5000);
}
});
evtSource.addEventListener('error', (e) => {
console.error('EventSource failed:', e);
status.update((s) => ({ ...s, isUpdating: false }));
evtSource.close(); // Close the current connection
setTimeout(connectEventSource, 1000);
});
};
try {
await fetchSettingsData();
if (await fetchStatusData()) {
settings.update((s) => ({ ...s, isLoaded: true }));
connectEventSource();
}
} catch (error) {
console.log('Error fetching data:', error);
}
function handleResize() {
if (observer) {
observer.disconnect();
@ -159,7 +198,7 @@
</svelte:head>
<Container fluid>
<Row>
<Row class="placeholder-glow">
<Control bind:settings on:showToast={showToast} bind:status lg="3" xxl="4"></Control>
<Status bind:settings bind:status lg="6" xxl="4"></Status>

View file

@ -17,6 +17,7 @@
} from '@sveltestrap/sveltestrap';
import FirmwareUpdater from './FirmwareUpdater.svelte';
import { uiSettings } from '$lib/uiSettings';
import { Placeholder } from '$lib/components';
export let settings = {};
@ -214,15 +215,16 @@
</li>
{/if}
<li>
{$_('section.control.buildTime')}: {new Date(
$settings.lastBuildTime * 1000
).toLocaleString()}
{$_('section.control.buildTime')}: <Placeholder
value={new Date($settings.lastBuildTime * 1000).toLocaleString()}
checkValue={$settings.lastBuildTime}
/>
</li>
<li>IP: {$settings.ip}</li>
<li>HW revision: {$settings.hwRev}</li>
<li>{$_('section.control.fwCommit')}: {$settings.gitRev}</li>
<li>WebUI commit: {$settings.fsRev}</li>
<li>{$_('section.control.hostname')}: {$settings.hostname}</li>
<li>IP: <Placeholder value={$settings.ip} /></li>
<li>HW revision: <Placeholder value={$settings.hwRev} /></li>
<li>{$_('section.control.fwCommit')}: <Placeholder value={$settings.gitRev} /></li>
<li>WebUI commit: <Placeholder value={$settings.fsRev} /></li>
<li>{$_('section.control.hostname')}: <Placeholder value={$settings.hostname} /></li>
</ul>
<Row>
<Col class="d-flex justify-content-end">
@ -239,7 +241,7 @@
{#if $settings.otaEnabled}
<hr />
<h3>{$_('section.control.firmwareUpdate')}</h3>
<FirmwareUpdater on:showToast bind:settings />
<FirmwareUpdater on:showToast bind:settings bind:status />
{/if}
</CardBody>
</Card>

View file

@ -4,11 +4,12 @@
import { _ } from 'svelte-i18n';
import { writable } from 'svelte/store';
import { Progress, Alert, Button } from '@sveltestrap/sveltestrap';
import HourglassSplitIcon from 'svelte-bootstrap-icons/lib/HourglassSplit.svelte';
const dispatch = createEventDispatcher();
export let settings = { hwRev: '' };
export let status = writable({ isOTAUpdating: false });
let currentVersion: string = $settings.gitTag; // Replace with your current version
let latestVersion: string = '';
@ -207,8 +208,12 @@
)}: {releaseDate} -
<a href={releaseUrl} target="_blank">{$_('section.firmwareUpdater.viewRelease')}</a><br />
{#if isNewerVersionAvailable}
{#if !$status.isOTAUpdating}
{$_('section.firmwareUpdater.swUpdateAvailable')} -
<a href="/" on:click={onAutoUpdate}>{$_('section.firmwareUpdater.autoUpdate')}</a>.
{:else}
<HourglassSplitIcon /> {$_('section.firmwareUpdater.autoUpdateInProgress')}
{/if}
{:else}
{$_('section.firmwareUpdater.swUpToDate')}
{/if}
@ -218,6 +223,7 @@
{:else}
<p>Loading...</p>
{/if}
{#if !$status.isOTAUpdating}
<section class="row row-cols-lg-auto align-items-end">
<div class="col flex-fill">
<label for="firmwareFile" class="form-label">Firmware file ({getFirmwareBinaryName()})</label>
@ -272,3 +278,4 @@
<small
>⚠️ <strong>{$_('warning')}</strong>: {$_('section.firmwareUpdater.firmwareUpdateText')}</small
>
{/if}

View file

@ -122,6 +122,12 @@
<CardTitle>{$_('section.settings.title')}</CardTitle>
</CardHeader>
<CardBody>
{#if $settings.isLoaded === false}
<div class="d-flex align-items-center">
<strong role="status">Loading...</strong>
<div class="spinner-border ms-auto" aria-hidden="true"></div>
</div>
{:else}
<Form on:submit={onSave}>
<ScreenSpecificSettings {settings} bind:isOpen={screenSettingsIsOpen} />
<DisplaySettings {settings} bind:isOpen={displaySettingsIsOpen} />
@ -145,6 +151,7 @@
</Col>
</Row>
</Form>
{/if}
</CardBody>
</Card>
</Col>

View file

@ -111,6 +111,12 @@
<CardTitle>{$_('section.status.title', { default: 'Status' })}</CardTitle>
</CardHeader>
<CardBody>
{#if $settings.isLoaded === false}
<div class="d-flex align-items-center">
<strong role="status">Loading...</strong>
<div class="spinner-border ms-auto" aria-hidden="true"></div>
</div>
{:else}
{#if $settings.screens}
<div class=" d-block d-sm-none mx-auto text-center">
{#each buttonChunks as chunk}
@ -151,7 +157,16 @@
{/if}
<hr />
{#if $status.data}
<section class={lightMode ? 'lightMode' : 'darkMode'}>
<section class={lightMode ? 'lightMode' : 'darkMode'} style="position: relative;">
{#if $status.isUpdating === false}
<div class="connection-lost-overlay">
<div class="overlay-content">
<i class="bi bi-wifi-off"></i>
<h4>Lost connection</h4>
<p>Trying to reconnect...</p>
</div>
</div>
{/if}
<Rendered
status={$status}
className="btclock-wrapper"
@ -265,6 +280,10 @@
<small>{$_('section.status.fetchEuroNote')}</small>
{/if}
</p>
{/if}
</CardBody>
</Card>
</Col>
<style lang="scss">
</style>