using AIStudio.Components; using AIStudio.Dialogs.Settings; using Microsoft.AspNetCore.Components; using DialogOptions = AIStudio.Dialogs.DialogOptions; namespace AIStudio.Assistants.BeyondFactsLab; /// /// The page of the BeyondFacts Lab, which guides researchers through the preparation of a challenging appearance. /// /// /// The lab keeps several preparations, each with steps of their own, so it does not inherit AssistantBase, /// which knows one input and one result. Like the Visual Briefing assistant, it checks by itself whether it /// may be opened. /// public partial class BeyondFactsLabAssistant : MSGComponentBase { [Inject] private IDialogService DialogService { get; init; } = null!; [Inject] private NavigationManager NavigationManager { get; init; } = null!; [Inject] private BeyondFactsLabStore Store { get; init; } = null!; [Inject] private BflConversationService ConversationService { get; init; } = null!; [Inject] private ILogger Logger { get; init; } = null!; [Inject] private IJSRuntime JsRuntime { get; init; } = null!; /// /// Whether the person may open the lab, so that the page did not send them away. /// private bool mayOpen; /// /// The empty element right before the header of the preparation, which marks where the header sits in the flow. /// private ElementReference stickyHeaderAnchor; /// /// Whether the next render shows another step, which then starts at the top. /// private bool scrollToActiveStep; /// protected override async Task OnInitializedAsync() { await base.OnInitializedAsync(); if (!BflAccess.CanOpen(this.SettingsManager, T("BeyondFacts Lab"))) { this.NavigationManager.NavigateTo(Routes.ASSISTANTS); return; } this.ApplyFilters([], [Event.CONFIGURATION_CHANGED]); this.mayOpen = true; await this.RunStoreActionAsync(() => this.ReloadProjectsAsync(null)); } /// protected override async Task OnAfterRenderAsync(bool firstRender) { await base.OnAfterRenderAsync(firstRender); if (this.scrollToActiveStep) { // The person scrolled down in one step and chose another one; it starts right under the header: this.scrollToActiveStep = false; await this.stickyHeaderAnchor.ScrollToStickyHeaderAsync(this.JsRuntime); } if (firstRender && this.mayOpen) await this.ShowNoticeIfNeededAsync(); } /// /// Shows the notes of the lab, unless the person confirmed them as they are now. /// private async Task ShowNoticeIfNeededAsync() { var notice = BflNotice.Text; var currentHash = BflNotice.ComputeHash(notice); if (BflNotice.IsAccepted(this.SettingsManager.ConfigurationData.BeyondFactsLab.AcceptedNoticeHash, currentHash)) return; var parameters = new DialogParameters { { dialog => dialog.Notice, notice } }; var reference = await this.DialogService.ShowAsync(T("BeyondFacts Lab"), parameters, DialogOptions.BLOCKING_FULLSCREEN); var result = await reference.Result; if (result is null || result.Canceled) return; this.SettingsManager.ConfigurationData.BeyondFactsLab.AcceptedNoticeHash = currentHash; await this.SettingsManager.StoreSettings(); } /// protected override async Task ProcessIncomingMessage(ComponentBase? sendingComponent, Event triggeredEvent, T? data) where T : default { if (triggeredEvent is Event.CONFIGURATION_CHANGED) { // An organization may hide the lab, or the person may switch its preview feature off, while the page is open: if (!BflAccess.CanOpen(this.SettingsManager)) { this.NavigationManager.NavigateTo(Routes.ASSISTANTS); return; } // A changed option, such as the form of address in the options of the lab, shows right away: this.StateHasChanged(); } await base.ProcessIncomingMessage(sendingComponent, triggeredEvent, data); } private async Task OpenSettingsDialogAsync() => await this.DialogService.ShowAsync(null, new DialogParameters(), DialogOptions.FULLSCREEN); }