ODIAN Launcher: hub, installer, local stack and remembered sign-in (M2)
- Tauri 2 + Svelte 5 hub in ODIAN dark: patch notes and roadmap, install and update progress, local stack status, settings with DHP and MCP addresses. - crates/odian-packs: Rust installer for pack format v1 (signed manifests, resumable verified downloads from a DHP or an ODIAN drive), byte-compatible with ODIAN_MCP_Server's Python odian_packs. - Local stack on 127.0.0.1: Postgres -> Engine API -> tile server -> Odian.exe, one Job Object, clean shutdown; database snapshot restore on a fresh PC only. - Keycloak sign-in through the DHP's MCP, remembered until Sign out with a launcher session that renews the Engine token silently. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
<script lang="ts">
|
||||
import StateDot, { type DotTone } from "./StateDot.svelte";
|
||||
import { COMPONENT_DETAIL, COMPONENT_LABEL, STACK_STATE_LABEL } from "../lib/format";
|
||||
import { STACK_ORDER, type StackMap } from "../lib/launcher.svelte";
|
||||
import type { Phase, StackComponent, StackState } from "../lib/types";
|
||||
|
||||
interface Props {
|
||||
stack: StackMap;
|
||||
phase: Phase;
|
||||
}
|
||||
|
||||
let { stack, phase }: Props = $props();
|
||||
|
||||
type Shown = StackState | "waiting";
|
||||
|
||||
const TONE: Record<Shown, DotTone> = {
|
||||
waiting: "idle",
|
||||
starting: "warn",
|
||||
ready: "ok",
|
||||
stopped: "idle",
|
||||
failed: "danger",
|
||||
};
|
||||
|
||||
function shownState(component: StackComponent): Shown {
|
||||
const event = stack[component];
|
||||
if (event) return event.state;
|
||||
// No event seen yet (e.g. the UI reloaded while ODIAN was already open).
|
||||
return phase === "running" ? "ready" : "waiting";
|
||||
}
|
||||
</script>
|
||||
|
||||
<ol class="stack" aria-label="Local stack">
|
||||
{#each STACK_ORDER as component, index (component)}
|
||||
{@const state = shownState(component)}
|
||||
{@const message = stack[component]?.message}
|
||||
<li class="row {state}">
|
||||
<span class="index mono" aria-hidden="true">{String(index + 1).padStart(2, "0")}</span>
|
||||
<span class="dot-cell"><StateDot tone={TONE[state]} pulse={state === "starting"} /></span>
|
||||
<span class="name">
|
||||
{COMPONENT_LABEL[component]}
|
||||
<span class="detail mono">{COMPONENT_DETAIL[component]}</span>
|
||||
</span>
|
||||
<span class="state mono">{STACK_STATE_LABEL[state]}</span>
|
||||
{#if message}
|
||||
<span class="message mono selectable" title={message}>{message}</span>
|
||||
{/if}
|
||||
</li>
|
||||
{/each}
|
||||
</ol>
|
||||
|
||||
<style>
|
||||
.stack {
|
||||
display: grid;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
border-top: 1px solid var(--line);
|
||||
}
|
||||
|
||||
.row {
|
||||
position: relative;
|
||||
display: grid;
|
||||
grid-template-columns: 22px 20px minmax(0, 1fr) auto;
|
||||
align-items: center;
|
||||
column-gap: 8px;
|
||||
min-height: 44px;
|
||||
padding: 8px 0;
|
||||
border-bottom: 1px solid var(--line);
|
||||
}
|
||||
|
||||
.index {
|
||||
color: var(--muted);
|
||||
font-size: var(--text-xs);
|
||||
}
|
||||
|
||||
.dot-cell {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
}
|
||||
|
||||
.name {
|
||||
overflow: hidden;
|
||||
color: var(--ink-2);
|
||||
font-size: var(--text-sm);
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.detail {
|
||||
margin-left: 6px;
|
||||
color: var(--muted);
|
||||
font-size: var(--text-xs);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.state {
|
||||
color: var(--muted);
|
||||
font-size: var(--text-xs);
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.message {
|
||||
grid-column: 3 / 5;
|
||||
overflow: hidden;
|
||||
color: var(--muted);
|
||||
font-size: var(--text-xs);
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.ready .state {
|
||||
color: var(--ok);
|
||||
}
|
||||
.starting .state {
|
||||
color: var(--warn);
|
||||
}
|
||||
.failed .state,
|
||||
.failed .message {
|
||||
color: var(--danger);
|
||||
}
|
||||
.ready .name,
|
||||
.starting .name {
|
||||
color: var(--ink);
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user