Previously a user idling past the 30-minute cookie expiry stayed parked on a stale page until they tried to navigate. The auth cookie's UTC expiry is now also stamped onto an expires_at claim at sign-in, and a SessionExpiry component mounted in MainLayout schedules a delay until expiry + 2s grace, then force-loads /login — at which point the standard cookie middleware confirms the session is gone and serves the login page.
30 lines
980 B
Plaintext
30 lines
980 B
Plaintext
@inherits LayoutComponentBase
|
|
|
|
<div class="d-flex flex-column flex-lg-row" style="min-height: 100vh;">
|
|
@* Hamburger toggle: visible only on viewports <lg.
|
|
Bootstrap collapse JS lives in bootstrap.bundle.min.js (loaded in App.razor). *@
|
|
<button class="btn btn-outline-secondary btn-sm d-lg-none m-2 align-self-start"
|
|
type="button"
|
|
data-bs-toggle="collapse"
|
|
data-bs-target="#sidebar-collapse"
|
|
aria-controls="sidebar-collapse"
|
|
aria-expanded="false"
|
|
aria-label="Toggle navigation">
|
|
☰
|
|
</button>
|
|
|
|
<div class="collapse d-lg-block" id="sidebar-collapse">
|
|
<NavMenu />
|
|
</div>
|
|
|
|
<main class="flex-grow-1 p-3" style="background-color: #f8f9fa;">
|
|
@Body
|
|
</main>
|
|
</div>
|
|
|
|
@* Global host for IDialogService. One instance per layout renders all confirm/prompt
|
|
dialogs raised via IDialogService.ConfirmAsync / PromptAsync. *@
|
|
<DialogHost />
|
|
|
|
<SessionExpiry />
|