Replace Home with Samples in menu; add ReceiverLayout
- Update NavMenu to show "Samples" instead of "Home" - Add ReceiverLayout.razor for receiver-facing pages: - Includes main content, sticky footer, and privacy link - Implements cookie consent banner using localStorage - Adds language switcher with LocalizationService integration - Handles event disposal and JS interop for SSR/client scenarios
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<DxMenu Orientation="@Orientation.Vertical" CssClass="menu">
|
<DxMenu Orientation="@Orientation.Vertical" CssClass="menu">
|
||||||
<Items>
|
<Items>
|
||||||
<DxMenuItem NavigateUrl="/" Text="Home" CssClass="@MenuItemCssClass("/")" IconCssClass="icon icon-home"></DxMenuItem>
|
<DxMenuItem NavigateUrl="/samples" Text="Samples" CssClass="@MenuItemCssClass("/samples")" IconCssClass="icon icon-home"></DxMenuItem>
|
||||||
<DxMenuItem NavigateUrl="/counter" Text="Counter" CssClass="@MenuItemCssClass("/counter")" IconCssClass="icon icon-counter"></DxMenuItem>
|
<DxMenuItem NavigateUrl="/counter" Text="Counter" CssClass="@MenuItemCssClass("/counter")" IconCssClass="icon icon-counter"></DxMenuItem>
|
||||||
<DxMenuItem NavigateUrl="/weather" Text="Weather" CssClass="@MenuItemCssClass("/weather")" IconCssClass="icon icon-weather"></DxMenuItem>
|
<DxMenuItem NavigateUrl="/weather" Text="Weather" CssClass="@MenuItemCssClass("/weather")" IconCssClass="icon icon-weather"></DxMenuItem>
|
||||||
<DxMenuItem NavigateUrl="/pdfviewer" Text="PDF Viewer" CssClass="@MenuItemCssClass("/pdfviewer")" IconCssClass="icon icon-pdf-viewer"></DxMenuItem>
|
<DxMenuItem NavigateUrl="/pdfviewer" Text="PDF Viewer" CssClass="@MenuItemCssClass("/pdfviewer")" IconCssClass="icon icon-pdf-viewer"></DxMenuItem>
|
||||||
|
|||||||
@@ -0,0 +1,116 @@
|
|||||||
|
@inherits LayoutComponentBase
|
||||||
|
@implements IDisposable
|
||||||
|
@inject LocalizationService Loc
|
||||||
|
@inject NavigationManager Nav
|
||||||
|
@inject IJSRuntime JS
|
||||||
|
|
||||||
|
@*
|
||||||
|
Layout for the receiver-facing pages migrated from EnvelopeGenerator.Web.
|
||||||
|
Mirrors the legacy MVC <body> structure: page content + sticky footer
|
||||||
|
with copyright link, language switcher and privacy link.
|
||||||
|
|
||||||
|
Cookie consent is reimplemented in Blazor (localStorage-backed) because
|
||||||
|
ASP.NET Core's <ITrackingConsentFeature> only works on the server side
|
||||||
|
and is awkward to integrate with InteractiveAuto rendering.
|
||||||
|
*@
|
||||||
|
|
||||||
|
<div class="receiver-shell">
|
||||||
|
|
||||||
|
@* Main page content *@
|
||||||
|
<main role="main" class="flex-grow-1">
|
||||||
|
@Body
|
||||||
|
</main>
|
||||||
|
|
||||||
|
@* Cookie consent banner (Blazor counterpart of _CookieConsentPartial). *@
|
||||||
|
@if (_consentVisible)
|
||||||
|
{
|
||||||
|
<div class="receiver-cookie-banner" role="alertdialog" aria-live="polite">
|
||||||
|
<span>@Loc["CookieConsentMessage"]</span>
|
||||||
|
<DxButton Text="@Loc["Accept"]"
|
||||||
|
RenderStyle="ButtonRenderStyle.Primary"
|
||||||
|
Click="AcceptCookiesAsync" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
@* Footer (copyright + language switcher + privacy). *@
|
||||||
|
<footer class="receiver-footer">
|
||||||
|
<span>
|
||||||
|
© SignFlow 2023-@DateTime.Now.Year
|
||||||
|
<a href="https://digitaldata.works" target="_blank" rel="noopener">Digital Data GmbH</a>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<select class="language-switcher" value="@_currentLang" @onchange="OnLanguageChangedAsync">
|
||||||
|
@foreach (var (lang, native, _) in LocalizationService.SupportedLanguages)
|
||||||
|
{
|
||||||
|
<option value="@lang" selected="@(lang == _currentLang)">@native</option>
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a href="@($"/privacy-policy.{_currentLang}.html")" target="_blank" rel="noopener">
|
||||||
|
@Loc["Privacy"]
|
||||||
|
</a>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
private string _currentLang = "de";
|
||||||
|
private bool _consentVisible;
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
Loc.Changed += OnLocChanged;
|
||||||
|
await Loc.EnsureLoadedAsync();
|
||||||
|
_currentLang = Loc.CurrentLanguage ?? "de";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
|
{
|
||||||
|
if (!firstRender) return;
|
||||||
|
// Probe localStorage on the client only — InteractiveAuto means
|
||||||
|
// the server prerender runs without a browser, so JS interop is
|
||||||
|
// unavailable until the first client render.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var accepted = await JS.InvokeAsync<string?>("localStorage.getItem", "receiver.cookie-consent");
|
||||||
|
_consentVisible = accepted != "1";
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// No-op: server prerender (JS unavailable) keeps the banner hidden.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task AcceptCookiesAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await JS.InvokeVoidAsync("localStorage.setItem", "receiver.cookie-consent", "1");
|
||||||
|
}
|
||||||
|
catch { /* ignore */ }
|
||||||
|
_consentVisible = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OnLanguageChangedAsync(ChangeEventArgs e)
|
||||||
|
{
|
||||||
|
var code = e.Value?.ToString();
|
||||||
|
if (string.IsNullOrEmpty(code) || code == _currentLang)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_currentLang = code;
|
||||||
|
await Loc.ChangeLanguageAsync(code);
|
||||||
|
// Force a full reload so ASP.NET Core localization middleware
|
||||||
|
// picks up the new culture for any subsequent SSR / API calls.
|
||||||
|
Nav.NavigateTo(Nav.Uri, forceLoad: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnLocChanged()
|
||||||
|
{
|
||||||
|
_currentLang = Loc.CurrentLanguage ?? _currentLang;
|
||||||
|
InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose() => Loc.Changed -= OnLocChanged;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user