Refresh nav on auth changes and show session info

This commit is contained in:
2026-04-06 17:20:47 +02:00
parent a0da39b697
commit 76d8180f41
5 changed files with 58 additions and 9 deletions
+22
View File
@@ -6,6 +6,7 @@ import { APP_NAME } from './config.js';
import { createRouter, navigate } from './router.js';
import { createAppStore } from './store.js';
import { appShell } from '../components/app-shell.js';
import { navBar } from '../components/nav-bar.js';
import { registerFeatureData } from '../features/register.js';
async function installServiceWorker() {
@@ -23,6 +24,20 @@ export function bootstrapApp() {
const appRoot = document.querySelector('#app');
appRoot.innerHTML = appShell(APP_NAME);
Alpine.initTree(appRoot);
const navRoot = document.querySelector('#app-nav');
function renderNav() {
if (!navRoot) {
return;
}
if (typeof Alpine.destroyTree === 'function') {
Alpine.destroyTree(navRoot);
}
navRoot.innerHTML = navBar(APP_NAME);
Alpine.initTree(navRoot);
}
const router = createRouter({
Alpine,
@@ -35,6 +50,7 @@ export function bootstrapApp() {
if (!store.activeKitchen && kitchens.length) {
store.setActiveKitchen(kitchens[0]);
}
renderNav();
return kitchens;
}
@@ -51,7 +67,9 @@ export function bootstrapApp() {
} else if (store.isConnected) {
await window.__loncApp.refreshKitchens();
}
renderNav();
} catch (error) {
renderNav();
if (window.location.hash !== '#/login') {
navigate('/login');
}
@@ -64,10 +82,12 @@ export function bootstrapApp() {
} else if (store.isConnected) {
await window.__loncApp.refreshKitchens();
}
renderNav();
return result;
},
async logout() {
await logout(store);
renderNav();
navigate('/login');
},
router,
@@ -89,6 +109,8 @@ export function bootstrapApp() {
.finally(() => router.start())
.catch(() => router.start());
renderNav();
installServiceWorker().catch(() => {
store.addAlert({
type: 'warning',
+2
View File
@@ -3,7 +3,9 @@ import { navBar } from './nav-bar.js';
export function appShell(appName) {
return `
<div class="app-shell d-flex flex-column min-vh-100">
<div id="app-nav">
${navBar(appName)}
</div>
<main id="route-view" class="flex-grow-1"></main>
<div class="toast-stack" x-data="alertsData()">
<template x-for="alert in alerts" :key="alert.id">
+13 -7
View File
@@ -1,6 +1,6 @@
export function navBar(appName) {
return `
<nav class="navbar navbar-expand-lg bg-white border-bottom sticky-top shadow-sm">
<nav class="navbar navbar-expand-lg bg-white border-bottom sticky-top shadow-sm" x-data>
<div class="container-xxl">
<a class="navbar-brand d-flex align-items-center gap-2 fw-semibold" href="#/">
<span class="brand-mark">L</span>
@@ -11,19 +11,25 @@ export function navBar(appName) {
</button>
<div id="main-nav" class="collapse navbar-collapse">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item"><a class="nav-link" href="#/">Dashboard</a></li>
<li class="nav-item"><a class="nav-link" href="#/labels/new">New Label</a></li>
<li class="nav-item"><a class="nav-link" href="#/stock">Stock</a></li>
<li class="nav-item" x-show="$store.app.session?.state === 'connected'">
<a class="nav-link" href="#/">Dashboard</a>
</li>
<li class="nav-item" x-show="$store.app.session?.state === 'connected'">
<a class="nav-link" href="#/labels/new">New Label</a>
</li>
<li class="nav-item" x-show="$store.app.session?.state === 'connected'">
<a class="nav-link" href="#/stock">Stock</a>
</li>
<li class="nav-item"><a class="nav-link" href="#/settings">Settings</a></li>
</ul>
<div class="d-flex flex-column flex-lg-row align-items-lg-center gap-2" x-data>
<template x-if="$store.app.activeKitchen">
<div class="d-flex flex-column flex-lg-row align-items-lg-center gap-2">
<template x-if="$store.app.session?.state === 'connected' && $store.app.activeKitchen">
<div class="small text-body-secondary">
Kitchen:
<span class="fw-semibold text-body" x-text="$store.app.activeKitchen?.name"></span>
</div>
</template>
<template x-if="$store.app.isAuthenticated">
<template x-if="$store.app.session?.applicationKey">
<button class="btn btn-outline-secondary btn-sm" @click="window.__loncApp.logout()">Logout</button>
</template>
</div>
+2 -1
View File
@@ -173,8 +173,9 @@ export function loginPageData(store) {
return;
}
const status = error?.cause?.status || error?.status;
const isPendingValidation = !store.session?.hasValidated;
this.verifyState.error =
status === 403
status === 403 || isPendingValidation
? 'Failed to verify connection. Please verify the application key in Tryton first.'
: (error?.message || this.verifyState.error || 'Failed to verify connection.');
});
+18
View File
@@ -27,6 +27,17 @@ export function renderSettingsPage() {
<label class="form-label">Database name</label>
<input class="form-control" type="text" x-model="form.database" required />
</div>
<div>
<label class="form-label">User login</label>
<input class="form-control" type="text" :value="userLogin" readonly />
</div>
<div>
<label class="form-label">Application key</label>
<input class="form-control font-monospace" type="text" :value="maskedApplicationKey" readonly />
<div class="form-text">
Only the first 16 characters are shown for identification.
</div>
</div>
<button class="btn btn-primary align-self-start" type="submit">Save settings</button>
</form>
</div>
@@ -57,6 +68,13 @@ export function settingsPageData(store) {
baseUrl: store.config.baseUrl || '',
database: store.config.database || '',
},
get userLogin() {
return store.session?.userLogin || '';
},
get maskedApplicationKey() {
const key = store.session?.applicationKey || '';
return key ? `${key.slice(0, 16)}...` : '';
},
save() {
store.setConfig({
baseUrl: this.form.baseUrl.trim(),