diff --git a/app/MindWork AI Studio/Components/DataSourceSelection.razor b/app/MindWork AI Studio/Components/DataSourceSelection.razor
new file mode 100644
index 00000000..f9dff17b
--- /dev/null
+++ b/app/MindWork AI Studio/Components/DataSourceSelection.razor
@@ -0,0 +1,93 @@
+@using AIStudio.Settings
+
+@if (this.SelectionMode is DataSourceSelectionMode.SELECTION_MODE)
+{
+
+
+ @if (this.PopoverTriggerMode is PopoverTriggerMode.ICON)
+ {
+
+ }
+ else
+ {
+
+ Select data sources
+
+ }
+
+
+
+
+
+
+
+ Data Source Selection
+
+
+
+ @if (this.waitingForDataSources)
+ {
+
+
+
+ }
+ else if (this.showDataSourceSelection)
+ {
+
+ @if (this.areDataSourcesEnabled)
+ {
+
+
+
+ this.SelectionChanged(x))" Style="max-height: 14em;">
+ @foreach (var source in this.availableDataSources)
+ {
+
+ @source.Name
+
+ }
+
+
+ }
+ }
+
+
+
+ Close
+
+
+
+
+
+}
+else if (this.SelectionMode is DataSourceSelectionMode.CONFIGURATION_MODE)
+{
+
+
+ Data Source Selection
+
+ @if (!string.IsNullOrWhiteSpace(this.ConfigurationHeaderMessage))
+ {
+
+ @this.ConfigurationHeaderMessage
+
+ }
+
+
+ @if (this.areDataSourcesEnabled)
+ {
+
+
+
+ this.SelectionChanged(x))">
+ @foreach (var source in this.availableDataSources)
+ {
+
+ @source.Name
+
+ }
+
+
+ }
+
+}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Components/DataSourceSelection.razor.cs b/app/MindWork AI Studio/Components/DataSourceSelection.razor.cs
new file mode 100644
index 00000000..031de0d1
--- /dev/null
+++ b/app/MindWork AI Studio/Components/DataSourceSelection.razor.cs
@@ -0,0 +1,251 @@
+using AIStudio.Settings;
+using AIStudio.Settings.DataModel;
+using AIStudio.Tools.Services;
+
+using Microsoft.AspNetCore.Components;
+
+namespace AIStudio.Components;
+
+public partial class DataSourceSelection : ComponentBase, IMessageBusReceiver, IDisposable
+{
+ [Parameter]
+ public DataSourceSelectionMode SelectionMode { get; set; } = DataSourceSelectionMode.SELECTION_MODE;
+
+ [Parameter]
+ public PopoverTriggerMode PopoverTriggerMode { get; set; } = PopoverTriggerMode.BUTTON;
+
+ [Parameter]
+ public string PopoverButtonClasses { get; set; } = string.Empty;
+
+ [Parameter]
+ public required AIStudio.Settings.Provider LLMProvider { get; set; }
+
+ [Parameter]
+ public required DataSourceOptions DataSourceOptions { get; set; }
+
+ [Parameter]
+ public EventCallback DataSourceOptionsChanged { get; set; }
+
+ [Parameter]
+ public string ConfigurationHeaderMessage { get; set; } = string.Empty;
+
+ [Parameter]
+ public bool AutoSaveAppSettings { get; set; }
+
+ [Inject]
+ private SettingsManager SettingsManager { get; init; } = null!;
+
+ [Inject]
+ private MessageBus MessageBus { get; init; } = null!;
+
+ [Inject]
+ private DataSourceService DataSourceService { get; init; } = null!;
+
+ [Inject]
+ private ILogger Logger { get; init; } = null!;
+
+ private bool internalChange;
+ private bool showDataSourceSelection;
+ private bool waitingForDataSources = true;
+ private IReadOnlyList availableDataSources = [];
+ private IReadOnlyCollection selectedDataSources = [];
+ private bool aiBasedSourceSelection;
+ private bool aiBasedValidation;
+ private bool areDataSourcesEnabled;
+
+ #region Overrides of ComponentBase
+
+ protected override async Task OnInitializedAsync()
+ {
+ this.MessageBus.RegisterComponent(this);
+ this.MessageBus.ApplyFilters(this, [], [ Event.COLOR_THEME_CHANGED ]);
+
+ //
+ // Load the settings:
+ //
+ this.aiBasedSourceSelection = this.DataSourceOptions.AutomaticDataSourceSelection;
+ this.aiBasedValidation = this.DataSourceOptions.AutomaticValidation;
+ this.areDataSourcesEnabled = !this.DataSourceOptions.DisableDataSources;
+ this.waitingForDataSources = this.areDataSourcesEnabled;
+
+ //
+ // Preselect the data sources. Right now, we cannot filter
+ // the data sources. Later, when the component is shown, we
+ // will filter the data sources.
+ //
+ // Right before the preselection would be used to kick off the
+ // RAG process, we will filter the data sources as well.
+ //
+ var preselectedSources = new List(this.DataSourceOptions.PreselectedDataSourceIds.Count);
+ foreach (var preselectedDataSourceId in this.DataSourceOptions.PreselectedDataSourceIds)
+ {
+ var dataSource = this.SettingsManager.ConfigurationData.DataSources.FirstOrDefault(ds => ds.Id == preselectedDataSourceId);
+ if (dataSource is not null)
+ preselectedSources.Add(dataSource);
+ }
+
+ this.selectedDataSources = preselectedSources;
+ await base.OnInitializedAsync();
+ }
+
+ protected override async Task OnParametersSetAsync()
+ {
+ if (!this.internalChange)
+ {
+ this.aiBasedSourceSelection = this.DataSourceOptions.AutomaticDataSourceSelection;
+ this.aiBasedValidation = this.DataSourceOptions.AutomaticValidation;
+ this.areDataSourcesEnabled = !this.DataSourceOptions.DisableDataSources;
+ }
+
+ switch (this.SelectionMode)
+ {
+ //
+ // In selection mode, we have to load & filter the data sources
+ // when the component is shown:
+ //
+ case DataSourceSelectionMode.SELECTION_MODE:
+
+ //
+ // For external changes, we have to reload & filter
+ // the data sources:
+ //
+ if (this.showDataSourceSelection && !this.internalChange)
+ await this.LoadAndApplyFilters();
+ else
+ this.internalChange = false;
+
+ break;
+
+ //
+ // In configuration mode, we have to load all data sources:
+ //
+ case DataSourceSelectionMode.CONFIGURATION_MODE:
+ this.availableDataSources = this.SettingsManager.ConfigurationData.DataSources;
+ break;
+ }
+
+ await base.OnParametersSetAsync();
+ }
+
+ #endregion
+
+ public void ChangeOptionWithoutSaving(DataSourceOptions options)
+ {
+ this.DataSourceOptions = options;
+ this.aiBasedSourceSelection = this.DataSourceOptions.AutomaticDataSourceSelection;
+ this.aiBasedValidation = this.DataSourceOptions.AutomaticValidation;
+ this.areDataSourcesEnabled = !this.DataSourceOptions.DisableDataSources;
+ this.selectedDataSources = this.SettingsManager.ConfigurationData.DataSources.Where(ds => this.DataSourceOptions.PreselectedDataSourceIds.Contains(ds.Id)).ToList();
+
+ //
+ // Remark: We do not apply the filters here. This is done later
+ // when either the parameters are changed or just before the
+ // RAG process is started (outside of this component).
+ //
+ // In fact, when we apply the filters here, multiple calls
+ // to the filter method would be made. We would get conflicts.
+ //
+ }
+
+ private async Task LoadAndApplyFilters()
+ {
+ if(this.DataSourceOptions.DisableDataSources)
+ return;
+
+ this.waitingForDataSources = true;
+ this.StateHasChanged();
+
+ // Load the data sources:
+ var sources = await this.DataSourceService.GetDataSources(this.LLMProvider, this.selectedDataSources);
+ this.availableDataSources = sources.AllowedDataSources;
+ this.selectedDataSources = sources.SelectedDataSources;
+ this.waitingForDataSources = false;
+ this.StateHasChanged();
+ }
+
+ private async Task EnabledChanged(bool state)
+ {
+ this.areDataSourcesEnabled = state;
+ this.DataSourceOptions.DisableDataSources = !this.areDataSourcesEnabled;
+
+ await this.LoadAndApplyFilters();
+ await this.OptionsChanged();
+ this.StateHasChanged();
+ }
+
+ private async Task AutoModeChanged(bool state)
+ {
+ this.aiBasedSourceSelection = state;
+ this.DataSourceOptions.AutomaticDataSourceSelection = this.aiBasedSourceSelection;
+
+ await this.OptionsChanged();
+ }
+
+ private async Task ValidationModeChanged(bool state)
+ {
+ this.aiBasedValidation = state;
+ this.DataSourceOptions.AutomaticValidation = this.aiBasedValidation;
+
+ await this.OptionsChanged();
+ }
+
+ private async Task SelectionChanged(IReadOnlyCollection? chosenDataSources)
+ {
+ this.selectedDataSources = chosenDataSources ?? [];
+ this.DataSourceOptions.PreselectedDataSourceIds = this.selectedDataSources.Select(ds => ds.Id).ToList();
+
+ await this.OptionsChanged();
+ }
+
+ private async Task OptionsChanged()
+ {
+ this.internalChange = true;
+
+ await this.DataSourceOptionsChanged.InvokeAsync(this.DataSourceOptions);
+
+ if(this.AutoSaveAppSettings)
+ await this.SettingsManager.StoreSettings();
+ }
+
+ private async Task ToggleDataSourceSelection()
+ {
+ this.showDataSourceSelection = !this.showDataSourceSelection;
+ if (this.showDataSourceSelection)
+ await this.LoadAndApplyFilters();
+ }
+
+ private void HideDataSourceSelection() => this.showDataSourceSelection = false;
+
+ #region Implementation of IMessageBusReceiver
+
+ public string ComponentName => nameof(ConfidenceInfo);
+
+ public Task ProcessMessage(ComponentBase? sendingComponent, Event triggeredEvent, T? data)
+ {
+ switch (triggeredEvent)
+ {
+ case Event.COLOR_THEME_CHANGED:
+ this.showDataSourceSelection = false;
+ this.StateHasChanged();
+ break;
+ }
+
+ return Task.CompletedTask;
+ }
+
+ public Task ProcessMessageWithResult(ComponentBase? sendingComponent, Event triggeredEvent, TPayload? data)
+ {
+ return Task.FromResult(default);
+ }
+
+ #endregion
+
+ #region Implementation of IDisposable
+
+ public void Dispose()
+ {
+ this.MessageBus.Unregister(this);
+ }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Components/DataSourceSelectionMode.cs b/app/MindWork AI Studio/Components/DataSourceSelectionMode.cs
new file mode 100644
index 00000000..e10a0136
--- /dev/null
+++ b/app/MindWork AI Studio/Components/DataSourceSelectionMode.cs
@@ -0,0 +1,23 @@
+namespace AIStudio.Components;
+
+public enum DataSourceSelectionMode
+{
+ ///
+ /// The user is selecting data sources for, e.g., the chat.
+ ///
+ ///
+ /// In this case, we have to filter the data sources based on the
+ /// selected provider and check security requirements.
+ ///
+ SELECTION_MODE,
+
+ ///
+ /// The user is configuring the default data sources, e.g., for the chat.
+ ///
+ ///
+ /// In this case, all data sources are available for selection.
+ /// They get filtered later based on the selected provider and
+ /// security requirements.
+ ///
+ CONFIGURATION_MODE,
+}
\ No newline at end of file