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