mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-10-13 17:13:48 +00:00
Keep data sources selectable only when their index can answer
This commit is contained in:
11 files changed
+391
-47
No files matched your search
@@ -1,6 +1,37 @@
|
||||
@using AIStudio.Settings
|
||||
@using AIStudio.Provider
|
||||
@inherits MSGComponentBase
|
||||
@*
|
||||
One row of the data source lists below. A data source waiting for its index stays in the list
|
||||
instead of disappearing from it, but cannot be picked, and the tooltip says why. The tool
|
||||
selection next to this one in the chat answers the same question the same way.
|
||||
|
||||
The tooltip sits around the list item rather than inside it: a disabled item has its pointer
|
||||
events switched off and would swallow the hover.
|
||||
*@
|
||||
@{
|
||||
RenderFragment<IDataSource> dataSourceRow = source =>
|
||||
@<MudTooltip Text="@T("This data source is waiting to be indexed again. Until that is finished, it cannot be searched.")" Disabled="@(!this.IsAwaitingReindex(source))" RootStyle="display: block;" Placement="Placement.Top">
|
||||
<MudListItem Value="@source" Disabled="@this.IsAwaitingReindex(source)">
|
||||
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="1" Style="min-width: 0; width: 100%;">
|
||||
<MudText Typo="Typo.body2" Style="min-width: 0; white-space: normal; overflow-wrap: anywhere;">
|
||||
@source.Name
|
||||
</MudText>
|
||||
@if (source is IInternalDataSource internalSource)
|
||||
{
|
||||
<MudSpacer/>
|
||||
@if (this.IsAwaitingReindex(source))
|
||||
{
|
||||
<MudIcon Icon="@Icons.Material.Filled.HourglassTop" Size="Size.Small" Color="Color.Warning" Style="flex-shrink: 0;"/>
|
||||
}
|
||||
<MudTooltip Text="@internalSource.ConfidenceLevel.GetName()">
|
||||
<MudIcon Icon="@Icons.Material.Filled.Security" Size="Size.Small" Class="confidence-icon" Style="@this.GetConfidenceIconStyle(internalSource)"/>
|
||||
</MudTooltip>
|
||||
}
|
||||
</MudStack>
|
||||
</MudListItem>
|
||||
</MudTooltip>;
|
||||
}
|
||||
@if (this.SelectionMode is DataSourceSelectionMode.SELECTION_MODE)
|
||||
{
|
||||
<div class="d-flex">
|
||||
@@ -69,7 +100,7 @@
|
||||
|
||||
@switch (this.aiBasedSourceSelection)
|
||||
{
|
||||
case true when this.availableDataSources.Count == 0:
|
||||
case true when this.GetListedDataSources().Count == 0:
|
||||
<MudText Typo="Typo.body2" Class="mb-2">
|
||||
@T("Your data sources cannot be used with the selected providers due to data privacy or confidence-level requirements, or they are currently unavailable.")
|
||||
</MudText>
|
||||
@@ -81,7 +112,7 @@
|
||||
</MudText>
|
||||
break;
|
||||
|
||||
case false when this.availableDataSources.Count == 0:
|
||||
case false when this.GetListedDataSources().Count == 0:
|
||||
<MudText Typo="Typo.body2" Class="mb-2">
|
||||
@T("Your data sources cannot be used with the selected providers due to data privacy or confidence-level requirements, or they are currently unavailable.")
|
||||
</MudText>
|
||||
@@ -90,22 +121,9 @@
|
||||
case false:
|
||||
<MudField Label="@T("Available Data Sources")" Variant="Variant.Outlined" Class="mb-2" Disabled="@this.aiBasedSourceSelection">
|
||||
<MudList T="IDataSource" Dense="@true" Class="data-source-rows" SelectionMode="@this.GetListSelectionMode()" @bind-SelectedValues:get="@this.selectedDataSources" @bind-SelectedValues:set="@this.SelectionChanged" Style="max-height: 14em;">
|
||||
@foreach (var source in this.availableDataSources)
|
||||
@foreach (var source in this.GetListedDataSources())
|
||||
{
|
||||
<MudListItem Value="@source">
|
||||
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="1" Style="min-width: 0; width: 100%;">
|
||||
<MudText Typo="Typo.body2" Style="min-width: 0; white-space: normal; overflow-wrap: anywhere;">
|
||||
@source.Name
|
||||
</MudText>
|
||||
@if (source is IInternalDataSource internalSource)
|
||||
{
|
||||
<MudSpacer/>
|
||||
<MudTooltip Text="@internalSource.ConfidenceLevel.GetName()">
|
||||
<MudIcon Icon="@Icons.Material.Filled.Security" Size="Size.Small" Class="confidence-icon" Style="@this.GetConfidenceIconStyle(internalSource)"/>
|
||||
</MudTooltip>
|
||||
}
|
||||
</MudStack>
|
||||
</MudListItem>
|
||||
@dataSourceRow(source)
|
||||
}
|
||||
</MudList>
|
||||
</MudField>
|
||||
@@ -115,22 +133,9 @@
|
||||
<MudExpansionPanels MultiExpansion="@false" Class="mt-3" Style="max-height: 14em;">
|
||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.TouchApp" IconSize="Size.Small" HeaderTypo="Typo.subtitle1" HeaderClass="expansion-panel-header-compact" HeaderText="@T("Available Data Sources")">
|
||||
<MudList T="IDataSource" Dense="@true" Class="data-source-rows" SelectionMode="MudBlazor.SelectionMode.SingleSelection" SelectedValues="@this.selectedDataSources" Style="max-height: 14em;">
|
||||
@foreach (var source in this.availableDataSources)
|
||||
@foreach (var source in this.GetListedDataSources())
|
||||
{
|
||||
<MudListItem Value="@source">
|
||||
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="1" Style="min-width: 0; width: 100%;">
|
||||
<MudText Typo="Typo.body2" Style="min-width: 0; white-space: normal; overflow-wrap: anywhere;">
|
||||
@source.Name
|
||||
</MudText>
|
||||
@if (source is IInternalDataSource internalSource)
|
||||
{
|
||||
<MudSpacer/>
|
||||
<MudTooltip Text="@internalSource.ConfidenceLevel.GetName()">
|
||||
<MudIcon Icon="@Icons.Material.Filled.Security" Size="Size.Small" Class="confidence-icon" Style="@this.GetConfidenceIconStyle(internalSource)"/>
|
||||
</MudTooltip>
|
||||
}
|
||||
</MudStack>
|
||||
</MudListItem>
|
||||
@dataSourceRow(source)
|
||||
}
|
||||
</MudList>
|
||||
</ExpansionPanel>
|
||||
@@ -166,13 +171,13 @@
|
||||
break;
|
||||
}
|
||||
|
||||
@if (!this.aiBasedSourceSelection && this.GetUnavailablePreselectedDataSources().Count > 0)
|
||||
@if (!this.aiBasedSourceSelection && this.GetUnavailablePreselectedDataSourcesToList().Count > 0)
|
||||
{
|
||||
<MudJustifiedText Typo="Typo.body2" Color="Color.Warning">
|
||||
@T("These data sources are preselected, but cannot be used right now, either due to data privacy or confidence-level requirements, or because they are unavailable:")
|
||||
</MudJustifiedText>
|
||||
<ul class="unavailable-data-sources mb-3 mt-1">
|
||||
@foreach (var source in this.GetUnavailablePreselectedDataSources())
|
||||
@foreach (var source in this.GetUnavailablePreselectedDataSourcesToList())
|
||||
{
|
||||
<li>@source.Name</li>
|
||||
}
|
||||
|
||||
@@ -49,6 +49,8 @@ public partial class DataSourceSelection : MSGComponentBase
|
||||
private bool showDataSourceSelection;
|
||||
private bool waitingForDataSources = true;
|
||||
private IReadOnlyList<IDataSource> availableDataSources = [];
|
||||
private IReadOnlyList<IDataSource> dataSourcesAwaitingReindex = [];
|
||||
private HashSet<string> dataSourceIdsAwaitingReindex = new(StringComparer.Ordinal);
|
||||
private IReadOnlyCollection<IDataSource> selectedDataSources = [];
|
||||
private bool aiBasedSourceSelection;
|
||||
private bool aiBasedValidation;
|
||||
@@ -226,10 +228,42 @@ public partial class DataSourceSelection : MSGComponentBase
|
||||
return;
|
||||
|
||||
this.availableDataSources = sources.AllowedDataSources;
|
||||
this.dataSourcesAwaitingReindex = sources.DataSourcesAwaitingReindex;
|
||||
this.dataSourceIdsAwaitingReindex = sources.DataSourcesAwaitingReindex.Select(source => source.Id).ToHashSet(StringComparer.Ordinal);
|
||||
this.selectedDataSources = sources.SelectedDataSources;
|
||||
this.waitingForDataSources = false;
|
||||
this.StateHasChanged();
|
||||
}
|
||||
|
||||
private bool IsAwaitingReindex(IDataSource dataSource) => this.dataSourceIdsAwaitingReindex.Contains(dataSource.Id);
|
||||
|
||||
/// <summary>
|
||||
/// The data sources the list shows: the usable ones, plus the ones waiting for their index.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Kept in the order the data sources were configured in, rather than usable ones first. A row
|
||||
/// which jumps to another place the moment its data source starts being re-indexed is a row the
|
||||
/// user has to find again.
|
||||
/// </remarks>
|
||||
private IReadOnlyList<IDataSource> GetListedDataSources()
|
||||
{
|
||||
if (this.dataSourcesAwaitingReindex.Count == 0)
|
||||
return this.availableDataSources;
|
||||
|
||||
var listedIds = this.availableDataSources.Select(source => source.Id).ToHashSet(StringComparer.Ordinal);
|
||||
listedIds.UnionWith(this.dataSourceIdsAwaitingReindex);
|
||||
return this.GetConfiguredDataSourcesSnapshot().Where(source => listedIds.Contains(source.Id)).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The preselected but unusable data sources the warning box lists.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The ones waiting for their index are left out: they have a row of their own in the list
|
||||
/// above, which says the same thing in the place the user is already looking.
|
||||
/// </remarks>
|
||||
private IReadOnlyList<IDataSource> GetUnavailablePreselectedDataSourcesToList() =>
|
||||
this.GetUnavailablePreselectedDataSources().Where(source => !this.IsAwaitingReindex(source)).ToList();
|
||||
|
||||
private async Task EnabledChanged(bool state)
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user