Better feedback when auto-updating and improve handling of disconnects and restarts
This commit is contained in:
parent
4057e18755
commit
468e105adf
12 changed files with 378 additions and 255 deletions
11
src/lib/components/Placeholder.svelte
Normal file
11
src/lib/components/Placeholder.svelte
Normal 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>
|
|
@ -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';
|
||||
|
|
|
@ -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": {
|
||||
|
|
|
@ -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": {
|
||||
|
|
|
@ -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": {
|
||||
|
|
|
@ -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": {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,8 @@
|
|||
|
||||
let settings = writable({
|
||||
fgColor: '0',
|
||||
bgColor: '0'
|
||||
bgColor: '0',
|
||||
isLoaded: false
|
||||
});
|
||||
|
||||
let status = writable({
|
||||
|
@ -25,34 +26,45 @@
|
|||
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) => {
|
||||
status.set(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) => {
|
||||
data.fgColor = String(data.fgColor);
|
||||
data.bgColor = String(data.bgColor);
|
||||
data.timePerScreen = data.timerSeconds / 60;
|
||||
const fetchSettingsData = async () => {
|
||||
const res = await fetch(PUBLIC_BASE_URL + `/api/settings`, { credentials: 'same-origin' });
|
||||
|
||||
if (data.fgColor > 65535) {
|
||||
data.fgColor = '65535';
|
||||
}
|
||||
if (!res.ok) {
|
||||
console.error('Error fetching settings data:', res.statusText);
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.bgColor > 65535) {
|
||||
data.bgColor = '65535';
|
||||
}
|
||||
settings.set(data);
|
||||
});
|
||||
const data = await res.json();
|
||||
|
||||
data.fgColor = String(data.fgColor);
|
||||
data.bgColor = String(data.bgColor);
|
||||
data.timePerScreen = data.timerSeconds / 60;
|
||||
|
||||
if (data.fgColor > 65535) {
|
||||
data.fgColor = '65535';
|
||||
}
|
||||
|
||||
if (data.bgColor > 65535) {
|
||||
data.bgColor = '65535';
|
||||
}
|
||||
settings.set(data);
|
||||
};
|
||||
|
||||
let sections: (HTMLElement | null)[];
|
||||
|
@ -89,18 +101,45 @@
|
|||
}
|
||||
};
|
||||
|
||||
onMount(() => {
|
||||
onMount(async () => {
|
||||
setupObserver();
|
||||
|
||||
fetchSettingsData();
|
||||
fetchStatusData();
|
||||
const connectEventSource = () => {
|
||||
console.log('Connecting to EventSource');
|
||||
const evtSource = new EventSource(`${PUBLIC_BASE_URL}/events`);
|
||||
|
||||
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('status', (e) => {
|
||||
let dataObj = JSON.parse(e.data);
|
||||
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) {
|
||||
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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}
|
||||
{$_('section.firmwareUpdater.swUpdateAvailable')} -
|
||||
<a href="/" on:click={onAutoUpdate}>{$_('section.firmwareUpdater.autoUpdate')}</a>.
|
||||
{#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,57 +223,59 @@
|
|||
{:else}
|
||||
<p>Loading...</p>
|
||||
{/if}
|
||||
<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>
|
||||
<input
|
||||
type="file"
|
||||
id="firmwareFile"
|
||||
on:change={(e) => handleFileChange(e, (file) => (firmwareUploadFile = file))}
|
||||
name="update"
|
||||
class="form-control"
|
||||
accept=".bin"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex-fill">
|
||||
<Button block on:click={uploadFirmwareFile} color="primary" disabled={!firmwareUploadFile}
|
||||
>Update firmware</Button
|
||||
{#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>
|
||||
<input
|
||||
type="file"
|
||||
id="firmwareFile"
|
||||
on:change={(e) => handleFileChange(e, (file) => (firmwareUploadFile = file))}
|
||||
name="update"
|
||||
class="form-control"
|
||||
accept=".bin"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex-fill">
|
||||
<Button block on:click={uploadFirmwareFile} color="primary" disabled={!firmwareUploadFile}
|
||||
>Update firmware</Button
|
||||
>
|
||||
</div>
|
||||
<div class="col flex-fill">
|
||||
<label for="webuiFile" class="form-label">WebUI file ({getWebUiBinaryName()})</label>
|
||||
<input
|
||||
type="file"
|
||||
id="webuiFile"
|
||||
name="update"
|
||||
class="form-control"
|
||||
placeholder="littlefs.bin"
|
||||
on:change={(e) => handleFileChange(e, (file) => (firmwareWebUiFile = file))}
|
||||
accept=".bin"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex-fill">
|
||||
<Button block on:click={uploadWebUiFile} color="secondary" disabled={!firmwareWebUiFile}
|
||||
>Update WebUI</Button
|
||||
>
|
||||
</div>
|
||||
</section>
|
||||
{#if firmwareUploadProgress > 0}
|
||||
<Progress striped value={firmwareUploadProgress} class="progress" id="firmwareUploadProgress"
|
||||
>{$_('section.firmwareUpdater.uploading')}... {firmwareUploadProgress}%</Progress
|
||||
>
|
||||
</div>
|
||||
<div class="col flex-fill">
|
||||
<label for="webuiFile" class="form-label">WebUI file ({getWebUiBinaryName()})</label>
|
||||
<input
|
||||
type="file"
|
||||
id="webuiFile"
|
||||
name="update"
|
||||
class="form-control"
|
||||
placeholder="littlefs.bin"
|
||||
on:change={(e) => handleFileChange(e, (file) => (firmwareWebUiFile = file))}
|
||||
accept=".bin"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex-fill">
|
||||
<Button block on:click={uploadWebUiFile} color="secondary" disabled={!firmwareWebUiFile}
|
||||
>Update WebUI</Button
|
||||
>
|
||||
</div>
|
||||
</section>
|
||||
{#if firmwareUploadProgress > 0}
|
||||
<Progress striped value={firmwareUploadProgress} class="progress" id="firmwareUploadProgress"
|
||||
>{$_('section.firmwareUpdater.uploading')}... {firmwareUploadProgress}%</Progress
|
||||
>
|
||||
{/if}
|
||||
{#if firmwareUploadSuccess}
|
||||
<Alert color="success" class="firmwareUploadStatusAlert"
|
||||
>{$_('section.firmwareUpdater.fileUploadSuccess', { values: { countdown: $countdown } })}
|
||||
</Alert>
|
||||
{/if}
|
||||
{/if}
|
||||
{#if firmwareUploadSuccess}
|
||||
<Alert color="success" class="firmwareUploadStatusAlert"
|
||||
>{$_('section.firmwareUpdater.fileUploadSuccess', { values: { countdown: $countdown } })}
|
||||
</Alert>
|
||||
{/if}
|
||||
|
||||
{#if firmwareUploadError}
|
||||
<Alert color="danger" class="firmwareUploadStatusAlert"
|
||||
>{$_('section.firmwareUpdater.fileUploadFailed')}</Alert
|
||||
{#if firmwareUploadError}
|
||||
<Alert color="danger" class="firmwareUploadStatusAlert"
|
||||
>{$_('section.firmwareUpdater.fileUploadFailed')}</Alert
|
||||
>
|
||||
{/if}
|
||||
<small
|
||||
>⚠️ <strong>{$_('warning')}</strong>: {$_('section.firmwareUpdater.firmwareUpdateText')}</small
|
||||
>
|
||||
{/if}
|
||||
<small
|
||||
>⚠️ <strong>{$_('warning')}</strong>: {$_('section.firmwareUpdater.firmwareUpdateText')}</small
|
||||
>
|
||||
|
|
|
@ -122,29 +122,36 @@
|
|||
<CardTitle>{$_('section.settings.title')}</CardTitle>
|
||||
</CardHeader>
|
||||
<CardBody>
|
||||
<Form on:submit={onSave}>
|
||||
<ScreenSpecificSettings {settings} bind:isOpen={screenSettingsIsOpen} />
|
||||
<DisplaySettings {settings} bind:isOpen={displaySettingsIsOpen} />
|
||||
<DataSourceSettings {settings} bind:isOpen={dataSourceIsOpen} on:showToast />
|
||||
<ExtraFeaturesSettings
|
||||
{settings}
|
||||
bind:isOpen={extraFeaturesIsOpen}
|
||||
{miningPoolMap}
|
||||
on:showToast
|
||||
/>
|
||||
<SystemSettings {settings} bind:isOpen={systemIsOpen} />
|
||||
{#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} />
|
||||
<DataSourceSettings {settings} bind:isOpen={dataSourceIsOpen} on:showToast />
|
||||
<ExtraFeaturesSettings
|
||||
{settings}
|
||||
bind:isOpen={extraFeaturesIsOpen}
|
||||
{miningPoolMap}
|
||||
on:showToast
|
||||
/>
|
||||
<SystemSettings {settings} bind:isOpen={systemIsOpen} />
|
||||
|
||||
<Row class="mt-4">
|
||||
<Col>
|
||||
<Button type="submit" color="primary" class="me-2">
|
||||
{$_('button.save')}
|
||||
</Button>
|
||||
<Button type="button" color="secondary" on:click={handleReset}>
|
||||
{$_('button.reset')}
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</Form>
|
||||
<Row class="mt-4">
|
||||
<Col>
|
||||
<Button type="submit" color="primary" class="me-2">
|
||||
{$_('button.save')}
|
||||
</Button>
|
||||
<Button type="button" color="secondary" on:click={handleReset}>
|
||||
{$_('button.reset')}
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</Form>
|
||||
{/if}
|
||||
</CardBody>
|
||||
</Card>
|
||||
</Col>
|
||||
|
|
|
@ -111,11 +111,29 @@
|
|||
<CardTitle>{$_('section.status.title', { default: 'Status' })}</CardTitle>
|
||||
</CardHeader>
|
||||
<CardBody>
|
||||
{#if $settings.screens}
|
||||
<div class=" d-block d-sm-none mx-auto text-center">
|
||||
{#each buttonChunks as chunk}
|
||||
<ButtonGroup size="sm" class="mx-auto mb-1">
|
||||
{#each chunk as s}
|
||||
{#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}
|
||||
<ButtonGroup size="sm" class="mx-auto mb-1">
|
||||
{#each chunk as s}
|
||||
<Button
|
||||
color="outline-primary"
|
||||
active={$status.currentScreen == s.id}
|
||||
on:click={setScreen(s.id)}>{s.name}</Button
|
||||
>
|
||||
{/each}
|
||||
</ButtonGroup>
|
||||
{/each}
|
||||
</div>
|
||||
<div class="d-flex justify-content-center d-none d-sm-flex">
|
||||
<ButtonGroup size="sm">
|
||||
{#each $settings.screens as s}
|
||||
<Button
|
||||
color="outline-primary"
|
||||
active={$status.currentScreen == s.id}
|
||||
|
@ -123,148 +141,149 @@
|
|||
>
|
||||
{/each}
|
||||
</ButtonGroup>
|
||||
{/each}
|
||||
</div>
|
||||
<div class="d-flex justify-content-center d-none d-sm-flex">
|
||||
<ButtonGroup size="sm">
|
||||
{#each $settings.screens as s}
|
||||
<Button
|
||||
color="outline-primary"
|
||||
active={$status.currentScreen == s.id}
|
||||
on:click={setScreen(s.id)}>{s.name}</Button
|
||||
>
|
||||
{/each}
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
{#if $settings.actCurrencies && $settings.ownDataSource}
|
||||
<div class="d-flex justify-content-center d-sm-flex mt-2">
|
||||
<ButtonGroup size="sm">
|
||||
{#each $settings.actCurrencies as c}
|
||||
<Button
|
||||
color="outline-success"
|
||||
active={$status.currency == c}
|
||||
on:click={setCurrency(c)}>{c}</Button
|
||||
>
|
||||
{/each}
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
{/if}
|
||||
<hr />
|
||||
{#if $status.data}
|
||||
<section class={lightMode ? 'lightMode' : 'darkMode'}>
|
||||
<Rendered
|
||||
status={$status}
|
||||
className="btclock-wrapper"
|
||||
verticalDesc={$settings.verticalDesc}
|
||||
></Rendered>
|
||||
</section>
|
||||
{$_('section.status.screenCycle')}:
|
||||
<a
|
||||
id="timerStatusText"
|
||||
href={'#'}
|
||||
style="cursor: pointer"
|
||||
tabindex="0"
|
||||
role="button"
|
||||
aria-pressed="false"
|
||||
on:click={toggleTimer($status.timerRunning)}
|
||||
>{#if $status.timerRunning}⏵ {$_('timer.running')}{:else}⏸ {$_(
|
||||
'timer.stopped'
|
||||
)}{/if}</a
|
||||
>
|
||||
{/if}
|
||||
{/if}
|
||||
<hr />
|
||||
{#if !$settings.disableLeds}
|
||||
<Row class="justify-content-evenly">
|
||||
{#if $status.leds}
|
||||
{#each $status.leds as led}
|
||||
<Col>
|
||||
<Input
|
||||
type="color"
|
||||
id="ledColorPicker"
|
||||
bind:value={led.hex}
|
||||
class="mx-auto"
|
||||
disabled
|
||||
/>
|
||||
</Col>
|
||||
{/each}
|
||||
{#if $settings.actCurrencies && $settings.ownDataSource}
|
||||
<div class="d-flex justify-content-center d-sm-flex mt-2">
|
||||
<ButtonGroup size="sm">
|
||||
{#each $settings.actCurrencies as c}
|
||||
<Button
|
||||
color="outline-success"
|
||||
active={$status.currency == c}
|
||||
on:click={setCurrency(c)}>{c}</Button
|
||||
>
|
||||
{/each}
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
{/if}
|
||||
</Row>
|
||||
<hr />
|
||||
{#if $status.data}
|
||||
<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"
|
||||
verticalDesc={$settings.verticalDesc}
|
||||
></Rendered>
|
||||
</section>
|
||||
{$_('section.status.screenCycle')}:
|
||||
<a
|
||||
id="timerStatusText"
|
||||
href={'#'}
|
||||
style="cursor: pointer"
|
||||
tabindex="0"
|
||||
role="button"
|
||||
aria-pressed="false"
|
||||
on:click={toggleTimer($status.timerRunning)}
|
||||
>{#if $status.timerRunning}⏵ {$_('timer.running')}{:else}⏸ {$_(
|
||||
'timer.stopped'
|
||||
)}{/if}</a
|
||||
>
|
||||
{/if}
|
||||
{/if}
|
||||
<hr />
|
||||
{/if}
|
||||
<Progress striped value={memoryFreePercent}>{memoryFreePercent}%</Progress>
|
||||
<div class="d-flex justify-content-between">
|
||||
<div>{$_('section.status.memoryFree')}</div>
|
||||
<div>
|
||||
{Math.round($status.espFreeHeap / 1024)} / {Math.round($status.espHeapSize / 1024)} KiB
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
{#if $settings.hasLightLevel}
|
||||
{$_('section.status.lightSensor')}: {Number(Math.round($status.lightLevel))} lux
|
||||
<hr />
|
||||
{/if}
|
||||
<Progress striped id="rssiBar" color={wifiStrengthColor} value={rssiPercent}
|
||||
>{rssiPercent}%</Progress
|
||||
>
|
||||
<Tooltip target="rssiBar" placement="bottom">{$_('rssiBar.tooltip')}</Tooltip>
|
||||
|
||||
<div class="d-flex justify-content-between">
|
||||
<div>{$_('section.status.wifiSignalStrength')}</div>
|
||||
<div>
|
||||
{$status.rssi} dBm
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
{$_('section.status.uptime')}: {toUptimestring($status.espUptime)}
|
||||
<br />
|
||||
<p>
|
||||
{#if $settings.dataSource == DataSourceType.NOSTR_SOURCE || $settings.nostrZapNotify}
|
||||
{$_('section.status.nostrConnection')}:
|
||||
<span>
|
||||
{#if $status.connectionStatus && $status.connectionStatus.nostr}
|
||||
✅
|
||||
{:else}
|
||||
❌
|
||||
{#if !$settings.disableLeds}
|
||||
<Row class="justify-content-evenly">
|
||||
{#if $status.leds}
|
||||
{#each $status.leds as led}
|
||||
<Col>
|
||||
<Input
|
||||
type="color"
|
||||
id="ledColorPicker"
|
||||
bind:value={led.hex}
|
||||
class="mx-auto"
|
||||
disabled
|
||||
/>
|
||||
</Col>
|
||||
{/each}
|
||||
{/if}
|
||||
</span>
|
||||
</Row>
|
||||
<hr />
|
||||
{/if}
|
||||
{#if $settings.dataSource != DataSourceType.NOSTR_SOURCE}
|
||||
{#if $settings.dataSource == DataSourceType.THIRD_PARTY_SOURCE}
|
||||
{$_('section.status.wsPriceConnection')}:
|
||||
<Progress striped value={memoryFreePercent}>{memoryFreePercent}%</Progress>
|
||||
<div class="d-flex justify-content-between">
|
||||
<div>{$_('section.status.memoryFree')}</div>
|
||||
<div>
|
||||
{Math.round($status.espFreeHeap / 1024)} / {Math.round($status.espHeapSize / 1024)} KiB
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
{#if $settings.hasLightLevel}
|
||||
{$_('section.status.lightSensor')}: {Number(Math.round($status.lightLevel))} lux
|
||||
<hr />
|
||||
{/if}
|
||||
<Progress striped id="rssiBar" color={wifiStrengthColor} value={rssiPercent}
|
||||
>{rssiPercent}%</Progress
|
||||
>
|
||||
<Tooltip target="rssiBar" placement="bottom">{$_('rssiBar.tooltip')}</Tooltip>
|
||||
|
||||
<div class="d-flex justify-content-between">
|
||||
<div>{$_('section.status.wifiSignalStrength')}</div>
|
||||
<div>
|
||||
{$status.rssi} dBm
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
{$_('section.status.uptime')}: {toUptimestring($status.espUptime)}
|
||||
<br />
|
||||
<p>
|
||||
{#if $settings.dataSource == DataSourceType.NOSTR_SOURCE || $settings.nostrZapNotify}
|
||||
{$_('section.status.nostrConnection')}:
|
||||
<span>
|
||||
{#if $status.connectionStatus && $status.connectionStatus.price}
|
||||
✅
|
||||
{:else}
|
||||
❌
|
||||
{/if}
|
||||
</span>
|
||||
-
|
||||
{$_('section.status.wsMempoolConnection', {
|
||||
values: { instance: $settings.mempoolInstance }
|
||||
})}:
|
||||
<span>
|
||||
{#if $status.connectionStatus && $status.connectionStatus.blocks}
|
||||
✅
|
||||
{:else}
|
||||
❌
|
||||
{/if}
|
||||
</span><br />
|
||||
{:else}
|
||||
{$_('section.status.wsDataConnection')}:
|
||||
<span>
|
||||
{#if $status.connectionStatus && $status.connectionStatus.V2}
|
||||
{#if $status.connectionStatus && $status.connectionStatus.nostr}
|
||||
✅
|
||||
{:else}
|
||||
❌
|
||||
{/if}
|
||||
</span>
|
||||
{/if}
|
||||
{/if}
|
||||
{#if $settings.fetchEurPrice}
|
||||
<small>{$_('section.status.fetchEuroNote')}</small>
|
||||
{/if}
|
||||
</p>
|
||||
{#if $settings.dataSource != DataSourceType.NOSTR_SOURCE}
|
||||
{#if $settings.dataSource == DataSourceType.THIRD_PARTY_SOURCE}
|
||||
{$_('section.status.wsPriceConnection')}:
|
||||
<span>
|
||||
{#if $status.connectionStatus && $status.connectionStatus.price}
|
||||
✅
|
||||
{:else}
|
||||
❌
|
||||
{/if}
|
||||
</span>
|
||||
-
|
||||
{$_('section.status.wsMempoolConnection', {
|
||||
values: { instance: $settings.mempoolInstance }
|
||||
})}:
|
||||
<span>
|
||||
{#if $status.connectionStatus && $status.connectionStatus.blocks}
|
||||
✅
|
||||
{:else}
|
||||
❌
|
||||
{/if}
|
||||
</span><br />
|
||||
{:else}
|
||||
{$_('section.status.wsDataConnection')}:
|
||||
<span>
|
||||
{#if $status.connectionStatus && $status.connectionStatus.V2}
|
||||
✅
|
||||
{:else}
|
||||
❌
|
||||
{/if}
|
||||
</span>
|
||||
{/if}
|
||||
{/if}
|
||||
{#if $settings.fetchEurPrice}
|
||||
<small>{$_('section.status.fetchEuroNote')}</small>
|
||||
{/if}
|
||||
</p>
|
||||
{/if}
|
||||
</CardBody>
|
||||
</Card>
|
||||
</Col>
|
||||
|
||||
<style lang="scss">
|
||||
</style>
|
||||
|
|
Loading…
Reference in a new issue