Files
agent/apps/web/src/features/auth/ServerLogin.svelte

64 lines
1.9 KiB
Svelte
Raw Normal View History

2026-07-18 16:40:09 +08:00
<script lang="ts">
export let apiBase: string;
2026-07-19 19:01:27 +08:00
export let onLogin: (detail: { apiBase: string; account: string }) => void = () => {};
2026-07-18 16:40:09 +08:00
let server = apiBase;
2026-07-19 19:01:27 +08:00
let account = '';
let password = '';
let error = '';
2026-07-18 16:40:09 +08:00
function normalizeServer(value: string) {
const trimmed = value.trim();
if (trimmed.startsWith('http://') || trimmed.startsWith('https://')) {
return trimmed;
}
return `http://${trimmed}`;
}
2026-07-19 19:01:27 +08:00
function submitLogin() {
error = '';
if (!account.trim() || !password.trim()) {
error = 'Enter an account and password.';
return;
}
const normalized = normalizeServer(server);
server = normalized;
onLogin({ apiBase: normalized, account: account.trim() });
}
2026-07-18 16:40:09 +08:00
</script>
2026-07-19 19:01:27 +08:00
<main class="login-page">
<section class="login-panel" aria-labelledby="login-title">
<div class="login-brand" aria-hidden="true">SA</div>
<div class="login-heading">
<p>Private workbench</p>
<h1 id="login-title">SenlinAI Workbench</h1>
</div>
<form class="server-login" aria-label="Server login" on:submit|preventDefault={submitLogin}>
<label for="server-address">Server IP or domain</label>
<input id="server-address" name="server" bind:value={server} placeholder="http://localhost:8080" />
<label for="login-account">Email or username</label>
<input id="login-account" name="account" bind:value={account} autocomplete="username" />
<label for="login-password">Password</label>
<input
id="login-password"
name="password"
type="password"
bind:value={password}
autocomplete="current-password"
/>
{#if error}
<p class="form-error" aria-live="polite">{error}</p>
{/if}
<button type="submit">Log in</button>
<p class="login-note">The server address is remembered on this device.</p>
</form>
</section>
</main>