fix(oxibadge): accept hostnames and FQDNs for the time clock address
Check, format and test / build (push) Successful in 11m10s
Check, format and test / build (push) Successful in 11m10s
The "Edit address" field in Settings only accepted an IPv4 address (IPV4.test), rejecting a bare hostname (e.g. "timbratore") or FQDN (e.g. "timbratore.lan") even though the underlying connection (Rust's ToSocketAddrs) already resolves those fine. Onboarding had no such restriction. Replaced the IPv4-only check with isValidHost (IPv4 OR a standard DNS hostname), dropped the numeric-only keyboard hint on that field, and reworded the labels/placeholder error to not imply IP-only. Also makes "Edit address" test the connection before accepting it, instead of saving unconditionally: ActionButton gained a `disabled` prop so the confirm/cancel buttons can be locked (with a spinner on confirm) while the test is in flight, and the edit form now only closes on a successful test, staying open with the raw error shown otherwise. Assisted-by: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -10,7 +10,7 @@
|
||||
import ActionButton from '../ActionButton.svelte';
|
||||
import PillButton from '../PillButton.svelte';
|
||||
import EmployeesDrawer from './EmployeesDrawer.svelte';
|
||||
import { IPV4 } from './logic';
|
||||
import { isValidHost } from './logic';
|
||||
|
||||
let { host, port, onsave }: { host: string; port: number; onsave: (host: string, port: number) => void } =
|
||||
$props();
|
||||
@@ -19,6 +19,7 @@
|
||||
let draftHost = $state('');
|
||||
let draftPort = $state(0);
|
||||
let ipError = $state(false);
|
||||
let confirming = $state(false);
|
||||
|
||||
let status = $state<'' | 'testing' | 'ok'>('');
|
||||
|
||||
@@ -79,20 +80,25 @@
|
||||
|
||||
async function confirmEdit() {
|
||||
const v = draftHost.trim();
|
||||
if (!IPV4.test(v)) {
|
||||
if (!isValidHost(v)) {
|
||||
ipError = true;
|
||||
return;
|
||||
}
|
||||
const nextPort = draftPort || 5005;
|
||||
editing = false;
|
||||
status = '';
|
||||
confirming = true;
|
||||
clearError();
|
||||
try {
|
||||
await invoke('test_connection', { host: v, port: nextPort });
|
||||
const settings = await invoke<Settings>('load_settings');
|
||||
await invoke('save_settings', { settings: { ...settings, readers: [{ host: v, port: nextPort }] } });
|
||||
editing = false;
|
||||
status = 'ok';
|
||||
onsave(v, nextPort);
|
||||
} catch (err) {
|
||||
status = '';
|
||||
setError(err);
|
||||
} finally {
|
||||
confirming = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,7 +122,7 @@
|
||||
}
|
||||
|
||||
function onKey(e: KeyboardEvent) {
|
||||
if (e.key === 'Escape' && editing) cancelEdit();
|
||||
if (e.key === 'Escape' && editing && !confirming) cancelEdit();
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -194,7 +200,6 @@
|
||||
id="dev-ip"
|
||||
label={$_('settings.ip_label')}
|
||||
bind:value={draftHost}
|
||||
inputmode="decimal"
|
||||
placeholder="192.168.1.100"
|
||||
err={ipError}
|
||||
oninput={() => (ipError = false)}
|
||||
@@ -212,8 +217,17 @@
|
||||
/>
|
||||
</div>
|
||||
<div class="row-end">
|
||||
<ActionButton onclick={cancelEdit}>{$_('settings.cancel')}</ActionButton>
|
||||
<ActionButton primary onclick={confirmEdit}>{$_('settings.confirm')}</ActionButton>
|
||||
<ActionButton disabled={confirming} onclick={cancelEdit}>{$_('settings.cancel')}</ActionButton>
|
||||
<ActionButton primary disabled={confirming} onclick={confirmEdit}>
|
||||
{#snippet icon()}
|
||||
{#if confirming}
|
||||
<svg class="spin" width="16" height="16" viewBox="0 0 24 24" aria-hidden="true" style="stroke-width: 2.4"
|
||||
><path d="M12 3a9 9 0 1 0 9 9" /></svg
|
||||
>
|
||||
{/if}
|
||||
{/snippet}
|
||||
{confirming ? $_('settings.status_testing') : $_('settings.confirm')}
|
||||
</ActionButton>
|
||||
</div>
|
||||
</form>
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user