diff --git a/app/MindWork AI Studio/Dialogs/DataSourceLocalDirectoryDialog.razor b/app/MindWork AI Studio/Dialogs/DataSourceLocalDirectoryDialog.razor
index 327350bb..22d1c984 100644
--- a/app/MindWork AI Studio/Dialogs/DataSourceLocalDirectoryDialog.razor
+++ b/app/MindWork AI Studio/Dialogs/DataSourceLocalDirectoryDialog.razor
@@ -10,7 +10,7 @@
MaxLength="40"
Counter="40"
Immediate="@true"
- Validation="@this.ValidateName"
+ Validation="@this.dataSourceValidation.ValidatingName"
Adornment="Adornment.Start"
AdornmentIcon="@Icons.Material.Filled.Lightbulb"
AdornmentColor="Color.Info"
@@ -21,13 +21,13 @@
Select a root directory for this data source. All data in this directory and all
its subdirectories will be processed for this data source.
-
+
In order for the AI to be able to determine the appropriate data at any time, you must
choose an embedding method.
-
+
@foreach (var embedding in this.AvailableEmbeddings)
{
@embedding.Name
@@ -51,7 +51,7 @@
@: confirm that you have read and understood this.
}
-
+
}
else
{
diff --git a/app/MindWork AI Studio/Dialogs/DataSourceLocalDirectoryDialog.razor.cs b/app/MindWork AI Studio/Dialogs/DataSourceLocalDirectoryDialog.razor.cs
index 2210e908..9f1b4f1f 100644
--- a/app/MindWork AI Studio/Dialogs/DataSourceLocalDirectoryDialog.razor.cs
+++ b/app/MindWork AI Studio/Dialogs/DataSourceLocalDirectoryDialog.razor.cs
@@ -1,5 +1,6 @@
using AIStudio.Settings;
using AIStudio.Settings.DataModel;
+using AIStudio.Tools.Validation;
using Microsoft.AspNetCore.Components;
@@ -24,6 +25,8 @@ public partial class DataSourceLocalDirectoryDialog : ComponentBase
private static readonly Dictionary SPELLCHECK_ATTRIBUTES = new();
+ private readonly DataSourceValidation dataSourceValidation;
+
///
/// The list of used data source names. We need this to check for uniqueness.
///
@@ -42,7 +45,17 @@ public partial class DataSourceLocalDirectoryDialog : ComponentBase
// We get the form reference from Blazor code to validate it manually:
private MudForm form = null!;
-
+
+ public DataSourceLocalDirectoryDialog()
+ {
+ this.dataSourceValidation = new()
+ {
+ GetSelectedCloudEmbedding = () => this.SelectedCloudEmbedding,
+ GetPreviousDataSourceName = () => this.dataEditingPreviousInstanceName,
+ GetUsedDataSourceNames = () => this.UsedDataSourcesNames,
+ };
+ }
+
#region Overrides of ComponentBase
protected override async Task OnInitializedAsync()
@@ -79,45 +92,6 @@ public partial class DataSourceLocalDirectoryDialog : ComponentBase
#endregion
- private string? ValidateName(string value)
- {
- if(string.IsNullOrWhiteSpace(value))
- return "The name must not be empty.";
-
- if (value.Length > 40)
- return "The name must not exceed 40 characters.";
-
- var lowerName = value.ToLowerInvariant();
- if(lowerName != this.dataEditingPreviousInstanceName && this.UsedDataSourcesNames.Contains(lowerName))
- return "The name is already used by another data source. Please choose a different name.";
-
- return null;
- }
-
- private string? ValidatePath(string value)
- {
- if(string.IsNullOrWhiteSpace(value))
- return "The path must not be empty. Please select a directory.";
-
- return null;
- }
-
- private string? ValidateEmbeddingId(string value)
- {
- if(string.IsNullOrWhiteSpace(value))
- return "Please select an embedding provider.";
-
- return null;
- }
-
- private string? ValidateUserAcknowledgedCloudEmbedding(bool value)
- {
- if(this.SelectedCloudEmbedding && !value)
- return "Please acknowledge that you are aware of the cloud embedding implications.";
-
- return null;
- }
-
private bool SelectedCloudEmbedding => !this.SettingsManager.ConfigurationData.EmbeddingProviders.FirstOrDefault(x => x.Id == this.dataEmbeddingId).IsSelfHosted;
private DataSourceLocalDirectory CreateDataSource() => new()
diff --git a/app/MindWork AI Studio/Dialogs/DataSourceLocalFileDialog.razor b/app/MindWork AI Studio/Dialogs/DataSourceLocalFileDialog.razor
index edc56f60..c60d32dc 100644
--- a/app/MindWork AI Studio/Dialogs/DataSourceLocalFileDialog.razor
+++ b/app/MindWork AI Studio/Dialogs/DataSourceLocalFileDialog.razor
@@ -10,7 +10,7 @@
MaxLength="40"
Counter="40"
Immediate="@true"
- Validation="@this.ValidateName"
+ Validation="@this.dataSourceValidation.ValidatingName"
Adornment="Adornment.Start"
AdornmentIcon="@Icons.Material.Filled.Lightbulb"
AdornmentColor="Color.Info"
@@ -20,13 +20,13 @@
Select a file for this data source. The content of this file will be processed for the data source.
-
+
In order for the AI to be able to determine the appropriate data at any time, you must
choose an embedding method.
-
+
@foreach (var embedding in this.AvailableEmbeddings)
{
@embedding.Name
@@ -50,7 +50,7 @@
@: and understood this.
}
-
+
}
else
{
diff --git a/app/MindWork AI Studio/Dialogs/DataSourceLocalFileDialog.razor.cs b/app/MindWork AI Studio/Dialogs/DataSourceLocalFileDialog.razor.cs
index 4edea086..feaf5a79 100644
--- a/app/MindWork AI Studio/Dialogs/DataSourceLocalFileDialog.razor.cs
+++ b/app/MindWork AI Studio/Dialogs/DataSourceLocalFileDialog.razor.cs
@@ -1,5 +1,6 @@
using AIStudio.Settings;
using AIStudio.Settings.DataModel;
+using AIStudio.Tools.Validation;
using Microsoft.AspNetCore.Components;
@@ -25,6 +26,8 @@ public partial class DataSourceLocalFileDialog : ComponentBase
private static readonly Dictionary SPELLCHECK_ATTRIBUTES = new();
+ private readonly DataSourceValidation dataSourceValidation;
+
///
/// The list of used data source names. We need this to check for uniqueness.
///
@@ -43,6 +46,16 @@ public partial class DataSourceLocalFileDialog : ComponentBase
// We get the form reference from Blazor code to validate it manually:
private MudForm form = null!;
+
+ public DataSourceLocalFileDialog()
+ {
+ this.dataSourceValidation = new()
+ {
+ GetSelectedCloudEmbedding = () => this.SelectedCloudEmbedding,
+ GetPreviousDataSourceName = () => this.dataEditingPreviousInstanceName,
+ GetUsedDataSourceNames = () => this.UsedDataSourcesNames,
+ };
+ }
#region Overrides of ComponentBase
@@ -80,45 +93,6 @@ public partial class DataSourceLocalFileDialog : ComponentBase
#endregion
- private string? ValidateName(string value)
- {
- if(string.IsNullOrWhiteSpace(value))
- return "The name must not be empty.";
-
- if (value.Length > 40)
- return "The name must not exceed 40 characters.";
-
- var lowerName = value.ToLowerInvariant();
- if(lowerName != this.dataEditingPreviousInstanceName && this.UsedDataSourcesNames.Contains(lowerName))
- return "The name is already used by another data source. Please choose a different name.";
-
- return null;
- }
-
- private string? ValidateFilePath(string value)
- {
- if(string.IsNullOrWhiteSpace(value))
- return "The file path must not be empty. Please select a file.";
-
- return null;
- }
-
- private string? ValidateEmbeddingId(string value)
- {
- if(string.IsNullOrWhiteSpace(value))
- return "Please select an embedding provider.";
-
- return null;
- }
-
- private string? ValidateUserAcknowledgedCloudEmbedding(bool value)
- {
- if(this.SelectedCloudEmbedding && !value)
- return "Please acknowledge that you are aware of the cloud embedding implications.";
-
- return null;
- }
-
private bool SelectedCloudEmbedding => !this.SettingsManager.ConfigurationData.EmbeddingProviders.FirstOrDefault(x => x.Id == this.dataEmbeddingId).IsSelfHosted;
private DataSourceLocalFile CreateDataSource() => new()
diff --git a/app/MindWork AI Studio/Tools/Validation/DataSourceValidation.cs b/app/MindWork AI Studio/Tools/Validation/DataSourceValidation.cs
new file mode 100644
index 00000000..1fdd359a
--- /dev/null
+++ b/app/MindWork AI Studio/Tools/Validation/DataSourceValidation.cs
@@ -0,0 +1,105 @@
+using ERI_Client.V1;
+
+namespace AIStudio.Tools.Validation;
+
+public sealed class DataSourceValidation
+{
+ public Func GetSecretStorageIssue { get; init; } = () => string.Empty;
+
+ public Func GetPreviousDataSourceName { get; init; } = () => string.Empty;
+
+ public Func> GetUsedDataSourceNames { get; init; } = () => [];
+
+ public Func GetAuthMethod { get; init; } = () => AuthMethod.NONE;
+
+ public Func GetSelectedCloudEmbedding { get; init; } = () => false;
+
+ public string? ValidatingHostname(string hostname)
+ {
+ if(string.IsNullOrWhiteSpace(hostname))
+ return "Please enter a hostname, e.g., http://localhost:1234";
+
+ if(!hostname.StartsWith("http://", StringComparison.InvariantCultureIgnoreCase) && !hostname.StartsWith("https://", StringComparison.InvariantCultureIgnoreCase))
+ return "The hostname must start with either http:// or https://";
+
+ if(!Uri.TryCreate(hostname, UriKind.Absolute, out _))
+ return "The hostname is not a valid HTTP(S) URL.";
+
+ return null;
+ }
+
+ public string? ValidatingSecret(string secret)
+ {
+ var authMethod = this.GetAuthMethod();
+ if(authMethod is AuthMethod.NONE or AuthMethod.KERBEROS)
+ return null;
+
+ var secretStorageIssue = this.GetSecretStorageIssue();
+ if(!string.IsNullOrWhiteSpace(secretStorageIssue))
+ return secretStorageIssue;
+
+ if (string.IsNullOrWhiteSpace(secret))
+ return authMethod switch
+ {
+ AuthMethod.TOKEN => "Please enter your secure token.",
+ AuthMethod.USERNAME_PASSWORD => "Please enter your password.",
+
+ _ => "Please enter the secret necessary for authentication."
+ };
+
+ return null;
+ }
+
+ public string? ValidatingName(string dataSourceName)
+ {
+ if(string.IsNullOrWhiteSpace(dataSourceName))
+ return "The name must not be empty.";
+
+ if (dataSourceName.Length > 40)
+ return "The name must not exceed 40 characters.";
+
+ var lowerName = dataSourceName.ToLowerInvariant();
+ if(lowerName != this.GetPreviousDataSourceName() && this.GetUsedDataSourceNames().Contains(lowerName))
+ return "The name is already used by another data source. Please choose a different name.";
+
+ return null;
+ }
+
+ public string? ValidatePath(string path)
+ {
+ if(string.IsNullOrWhiteSpace(path))
+ return "The path must not be empty. Please select a directory.";
+
+ if(!Directory.Exists(path))
+ return "The path does not exist. Please select a valid directory.";
+
+ return null;
+ }
+
+ public string? ValidateFilePath(string filePath)
+ {
+ if(string.IsNullOrWhiteSpace(filePath))
+ return "The file path must not be empty. Please select a file.";
+
+ if(!File.Exists(filePath))
+ return "The file does not exist. Please select a valid file.";
+
+ return null;
+ }
+
+ public string? ValidateEmbeddingId(string embeddingId)
+ {
+ if(string.IsNullOrWhiteSpace(embeddingId))
+ return "Please select an embedding provider.";
+
+ return null;
+ }
+
+ public string? ValidateUserAcknowledgedCloudEmbedding(bool value)
+ {
+ if(this.GetSelectedCloudEmbedding() && !value)
+ return "Please acknowledge that you are aware of the cloud embedding implications.";
+
+ return null;
+ }
+}
\ No newline at end of file