mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2025-04-28 21:39:46 +00:00
Added possibility that the user selects a file
This commit is contained in:
parent
0c5417ad31
commit
cb744064d5
17
app/MindWork AI Studio/Components/SelectFile.razor
Normal file
17
app/MindWork AI Studio/Components/SelectFile.razor
Normal file
@ -0,0 +1,17 @@
|
||||
<MudStack Row="@true" Spacing="3" Class="mb-3" StretchItems="StretchItems.None" AlignItems="AlignItems.Center">
|
||||
<MudTextField
|
||||
T="string"
|
||||
Text="@this.File"
|
||||
Label="@this.Label"
|
||||
ReadOnly="@true"
|
||||
Validation="@this.Validation"
|
||||
Adornment="Adornment.Start"
|
||||
AdornmentIcon="@Icons.Material.Filled.AttachFile"
|
||||
UserAttributes="@SPELLCHECK_ATTRIBUTES"
|
||||
Variant="Variant.Outlined"
|
||||
/>
|
||||
|
||||
<MudButton StartIcon="@Icons.Material.Filled.FolderOpen" Variant="Variant.Outlined" Color="Color.Primary" Disabled="this.Disabled" OnClick="@this.OpenFileDialog">
|
||||
Choose File
|
||||
</MudButton>
|
||||
</MudStack>
|
63
app/MindWork AI Studio/Components/SelectFile.razor.cs
Normal file
63
app/MindWork AI Studio/Components/SelectFile.razor.cs
Normal file
@ -0,0 +1,63 @@
|
||||
using AIStudio.Settings;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace AIStudio.Components;
|
||||
|
||||
public partial class SelectFile : ComponentBase
|
||||
{
|
||||
[Parameter]
|
||||
public string File { get; set; } = string.Empty;
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<string> FileChanged { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public bool Disabled { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string Label { get; set; } = string.Empty;
|
||||
|
||||
[Parameter]
|
||||
public string FileDialogTitle { get; set; } = "Select File";
|
||||
|
||||
[Parameter]
|
||||
public Func<string, string?> Validation { get; set; } = _ => null;
|
||||
|
||||
[Inject]
|
||||
private SettingsManager SettingsManager { get; init; } = null!;
|
||||
|
||||
[Inject]
|
||||
public RustService RustService { get; set; } = null!;
|
||||
|
||||
[Inject]
|
||||
protected ILogger<SelectDirectory> Logger { get; init; } = null!;
|
||||
|
||||
private static readonly Dictionary<string, object?> SPELLCHECK_ATTRIBUTES = new();
|
||||
|
||||
#region Overrides of ComponentBase
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
// Configure the spellchecking for the instance name input:
|
||||
this.SettingsManager.InjectSpellchecking(SPELLCHECK_ATTRIBUTES);
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private void InternalFileChanged(string file)
|
||||
{
|
||||
this.File = file;
|
||||
this.FileChanged.InvokeAsync(file);
|
||||
}
|
||||
|
||||
private async Task OpenFileDialog()
|
||||
{
|
||||
var response = await this.RustService.SelectFile(this.FileDialogTitle, string.IsNullOrWhiteSpace(this.File) ? null : this.File);
|
||||
this.Logger.LogInformation($"The user selected the file '{response.SelectedFilePath}'.");
|
||||
|
||||
if (!response.UserCancelled)
|
||||
this.InternalFileChanged(response.SelectedFilePath);
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
namespace AIStudio.Tools.Rust;
|
||||
|
||||
/// <summary>
|
||||
/// Data structure for selecting a file.
|
||||
/// </summary>
|
||||
/// <param name="UserCancelled">Was the file selection canceled?</param>
|
||||
/// <param name="SelectedFilePath">The selected file, if any.</param>
|
||||
public readonly record struct FileSelectionResponse(bool UserCancelled, string SelectedFilePath);
|
7
app/MindWork AI Studio/Tools/Rust/PreviousFile.cs
Normal file
7
app/MindWork AI Studio/Tools/Rust/PreviousFile.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace AIStudio.Tools.Rust;
|
||||
|
||||
/// <summary>
|
||||
/// Data structure for selecting a file when a previous file was selected.
|
||||
/// </summary>
|
||||
/// <param name="FilePath">The path of the previous file.</param>
|
||||
public readonly record struct PreviousFile(string FilePath);
|
@ -16,4 +16,17 @@ public sealed partial class RustService
|
||||
|
||||
return await result.Content.ReadFromJsonAsync<DirectorySelectionResponse>(this.jsonRustSerializerOptions);
|
||||
}
|
||||
|
||||
public async Task<FileSelectionResponse> SelectFile(string title, string? initialFile = null)
|
||||
{
|
||||
PreviousFile? previousFile = initialFile is null ? null : new (initialFile);
|
||||
var result = await this.http.PostAsJsonAsync($"/select/file?title={title}", previousFile, this.jsonRustSerializerOptions);
|
||||
if (!result.IsSuccessStatusCode)
|
||||
{
|
||||
this.logger!.LogError($"Failed to select a file: '{result.StatusCode}'");
|
||||
return new FileSelectionResponse(true, string.Empty);
|
||||
}
|
||||
|
||||
return await result.Content.ReadFromJsonAsync<FileSelectionResponse>(this.jsonRustSerializerOptions);
|
||||
}
|
||||
}
|
@ -271,3 +271,52 @@ pub struct DirectorySelectionResponse {
|
||||
user_cancelled: bool,
|
||||
selected_directory: String,
|
||||
}
|
||||
|
||||
/// Let the user select a file.
|
||||
#[post("/select/file?<title>", data = "<previous_file>")]
|
||||
pub fn select_file(_token: APIToken, title: &str, previous_file: Option<Json<PreviousFile>>) -> Json<FileSelectionResponse> {
|
||||
let file_path = match previous_file {
|
||||
Some(previous) => {
|
||||
let previous_path = previous.file_path.as_str();
|
||||
FileDialogBuilder::new()
|
||||
.set_title(title)
|
||||
.set_directory(previous_path)
|
||||
.pick_file()
|
||||
},
|
||||
|
||||
None => {
|
||||
FileDialogBuilder::new()
|
||||
.set_title(title)
|
||||
.pick_file()
|
||||
},
|
||||
};
|
||||
|
||||
match file_path {
|
||||
Some(path) => {
|
||||
info!("User selected file: {path:?}");
|
||||
Json(FileSelectionResponse {
|
||||
user_cancelled: false,
|
||||
selected_file_path: path.to_str().unwrap().to_string(),
|
||||
})
|
||||
},
|
||||
|
||||
None => {
|
||||
info!("User cancelled file selection.");
|
||||
Json(FileSelectionResponse {
|
||||
user_cancelled: true,
|
||||
selected_file_path: String::from(""),
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize)]
|
||||
pub struct PreviousFile {
|
||||
file_path: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct FileSelectionResponse {
|
||||
user_cancelled: bool,
|
||||
selected_file_path: String,
|
||||
}
|
@ -85,6 +85,7 @@ pub fn start_runtime_api() {
|
||||
crate::app_window::check_for_update,
|
||||
crate::app_window::install_update,
|
||||
crate::app_window::select_directory,
|
||||
crate::app_window::select_file,
|
||||
crate::secret::get_secret,
|
||||
crate::secret::store_secret,
|
||||
crate::secret::delete_secret,
|
||||
|
Loading…
Reference in New Issue
Block a user