Files
AI-Studio/app/MindWork AI Studio/Assistants/BeyondFactsLab/BeyondFactsLabAssistant.razor
T

143 lines
9.0 KiB
Plaintext

@attribute [Route(Routes.ASSISTANT_BEYOND_FACTS_LAB)]
@inherits MSGComponentBase
<CascadingValue Value="Components.BEYOND_FACTS_LAB_ASSISTANT">
@* The lab does not inherit AssistantBase, so it sets up the inner scrolling itself, the way the
Visual Briefing assistant does. *@
<div class="inner-scrolling-context">
<PreviewPrototype ApplyInnerScrollingFix="true"/>
<MudStack Row="true" AlignItems="AlignItems.Center" Class="mb-3 mr-3" StretchItems="StretchItems.Start">
<MudText Typo="Typo.h3">@T("BeyondFacts Lab")</MudText>
<MudSpacer/>
<MudIconButton Variant="Variant.Text" Icon="@Icons.Material.Filled.Settings" OnClick="@this.OpenSettingsDialogAsync"/>
</MudStack>
<InnerScrolling>
<MudText Typo="Typo.body1" Class="mb-3 mr-3">
@TA("Prepare a challenging appearance as a researcher step by step, e.g., a panel discussion, an interview, or a hearing. Each preparation belongs to one event and has its own steps, chats, and work states.")
</MudText>
<MudText Typo="Typo.h5" Class="mb-1">@TA("Your preparations")</MudText>
@if (this.projects.Count == 0)
{
<MudText Typo="Typo.body2" Class="mb-3">@TA("You have no preparations yet. Create one for the event you want to prepare for.")</MudText>
}
else
{
<MudList T="Guid"
Color="Color.Primary"
Class="mb-1"
SelectedValue="@(this.selectedProject?.ProjectId ?? Guid.Empty)"
SelectedValueChanged="@this.SelectProjectAsync">
@foreach (var project in this.projects)
{
<MudListItem T="Guid" @key="project.ProjectId" Value="@project.ProjectId" Icon="@ProjectIcon(project)">
<MudStack Spacing="0">
<MudText Typo="Typo.body1">@this.ProjectDisplayName(project)</MudText>
<MudText Typo="Typo.caption">@this.ProjectCaption(project)</MudText>
@if (this.projectsWithMissingDetails.Contains(project.ProjectId))
{
<MudText Typo="Typo.caption" Color="Color.Warning">@T("Details missing")</MudText>
}
@if (!project.IsAvailable)
{
<MudText Typo="Typo.caption" Color="Color.Error">@this.ProjectStatusName(project.Status)</MudText>
}
</MudStack>
</MudListItem>
}
</MudList>
}
<MudButton Variant="Variant.Filled" Color="Color.Primary" StartIcon="@Icons.Material.Filled.Add" OnClick="@this.CreateProjectAsync" Disabled="@this.isBusy" Class="mt-1">
@T("New preparation")
</MudButton>
<MudDivider Style="height: 0.25ch; margin: 1rem 0;" Class="mt-6"/>
@if (this.selectedProject is { IsAvailable: false } unavailableProject)
{
<MudPaper Outlined="true" Class="pa-6 mr-3">
<MudStack Spacing="3">
<MudText Typo="Typo.h4">@this.ProjectDisplayName(unavailableProject)</MudText>
<MudAlert Severity="Severity.Error" Variant="Variant.Outlined">
@this.ProjectRecoveryMessage(unavailableProject.Status)
</MudAlert>
<MudText Typo="Typo.body1">@T("AI Studio has left the files of this preparation unchanged. A future update may make it accessible again.")</MudText>
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="1" Wrap="Wrap.Wrap">
<MudText Typo="Typo.body2"><strong>@T("Preparation ID"):</strong> @unavailableProject.ProjectId.ToString("D")</MudText>
<MudCopyClipboardButton TooltipMessage="@T("Copy preparation ID")" StringContent="@unavailableProject.ProjectId.ToString("D")"/>
</MudStack>
<MudStack Row="true" Spacing="1" Wrap="Wrap.Wrap">
<MudButton Variant="Variant.Filled" StartIcon="@Icons.Material.Filled.DeleteForever" Color="Color.Error" OnClick="@this.DeleteProjectAsync" Disabled="@this.isBusy">@T("Delete")</MudButton>
</MudStack>
</MudStack>
</MudPaper>
}
else if (this.selectedProject?.Project is { } project)
{
@* Stays at the top while the person scrolls, like the header of the workspaces: the preparation, its
provider, and the steps remain in view, and only the list of preparations scrolls away. The empty
anchor before it marks where the header sits in the flow, to scroll back there for another step. *@
<div @ref="@this.stickyHeaderAnchor"></div>
<div class="mr-3" style="position: sticky; top: 0; z-index: 2; background-color: var(--mud-palette-background);">
<MudStack Row="true" Justify="Justify.SpaceBetween" AlignItems="AlignItems.Center" Wrap="Wrap.Wrap" Class="mb-3">
<MudStack Spacing="0">
<MudText Typo="Typo.h4">@project.Name</MudText>
@if (project.HappenedAtUtc is { } happenedAtUtc)
{
<MudText Typo="Typo.caption">@string.Format(Culture, T("Marked on {0}."), happenedAtUtc.ToLocalTime().ToString("d", Culture))</MudText>
}
</MudStack>
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="1" Wrap="Wrap.Wrap">
<MudSwitch T="bool" Value="@(project.HappenedAtUtc is not null)" ValueChanged="@this.SetHappenedAsync" Disabled="@this.isBusy" Color="Color.Primary" Class="mr-2">
@T("The event has taken place")
</MudSwitch>
<MudButton StartIcon="@Icons.Material.Filled.DriveFileRenameOutline" OnClick="@this.RenameProjectAsync" Disabled="@this.isBusy">@T("Rename")</MudButton>
<MudButton StartIcon="@Icons.Material.Filled.DeleteForever" Color="Color.Error" OnClick="@this.DeleteProjectAsync" Disabled="@this.isBusy">@T("Delete")</MudButton>
</MudStack>
</MudStack>
<ProviderSelection ProviderSettings="@this.providerSettings" ProviderSettingsChanged="@this.SelectProviderAsync" ValidateProvider="@this.ValidateProvider" Disabled="@this.isBusy"/>
@* The steps have no content of their own: only the navigation of the stepper stays in view, and the
step shown follows below. *@
<MudStepperWithoutActions NonLinear="@true" ActiveIndex="@this.ActiveStepIndex" ActiveIndexChanged="@this.SelectStepAsync">
<ChildContent>
@foreach (var step in BflStep.All)
{
<MudStep @key="step" Title="@step.Title" SecondaryText="@this.StepSecondaryText(step)"/>
}
</ChildContent>
</MudStepperWithoutActions>
</div>
<div @key="@this.activeStep" class="mr-3 px-6">
<MudText Typo="Typo.h5" Class="mt-2">@this.activeStep.Title</MudText>
<MudText Typo="Typo.body2" Class="mb-4">@this.activeStep.Description</MudText>
<MudText Typo="Typo.h6" Class="mb-2">@TA("Your details")</MudText>
@if (this.forms.TryGetValue(this.activeStep, out var form))
{
var step = this.activeStep;
<BflStepForm Step="@step" Form="@form" FormChanged="@(() => this.SaveFormAsync(step))"/>
}
else
{
<MudAlert Severity="Severity.Error" Variant="Variant.Outlined">
@TA("AI Studio cannot open your details for this step. Their file may be damaged, or a newer version of AI Studio stored it. AI Studio leaves the file unchanged.")
</MudAlert>
}
<BflStepChat Location="@(new BflThreadLocation(project.ProjectId, this.activeStep))" Provider="@this.providerSettings" ProviderIssue="@this.ValidateProvider(this.providerSettings)"/>
</div>
}
else
{
<MudPaper Outlined="true" Class="pa-6 mr-3">
<MudText Typo="Typo.h5">@TA("Create a preparation to begin.")</MudText>
</MudPaper>
}
</InnerScrolling>
</div>
</CascadingValue>