Implemented move to workspace feature

This commit is contained in:
Thorsten Sommer 2024-07-12 13:08:57 +02:00
parent 718beb85ac
commit 10367c86fe
Signed by: tsommer
GPG Key ID: 371BBA77A02C0108
5 changed files with 139 additions and 20 deletions

View File

@ -248,27 +248,31 @@ public partial class Workspaces : ComponentBase
return null;
}
private async Task DeleteChat(string? chatPath)
public async Task DeleteChat(string? chatPath, bool askForConfirmation = true, bool unloadChat = true)
{
var chat = await this.LoadChat(chatPath, false);
if (chat is null)
return;
var workspaceName = await this.LoadWorkspaceName(chat.WorkspaceId);
var dialogParameters = new DialogParameters
if (askForConfirmation)
{
{ "Message", (chat.WorkspaceId == Guid.Empty) switch
var workspaceName = await this.LoadWorkspaceName(chat.WorkspaceId);
var dialogParameters = new DialogParameters
{
{
true => $"Are you sure you want to delete the temporary chat '{chat.Name}'?",
false => $"Are you sure you want to delete the chat '{chat.Name}' in the workspace '{workspaceName}'?",
}
},
};
"Message", (chat.WorkspaceId == Guid.Empty) switch
{
true => $"Are you sure you want to delete the temporary chat '{chat.Name}'?",
false => $"Are you sure you want to delete the chat '{chat.Name}' in the workspace '{workspaceName}'?",
}
},
};
var dialogReference = await this.DialogService.ShowAsync<ConfirmDialog>("Delete Chat", dialogParameters, DialogOptions.FULLSCREEN);
var dialogResult = await dialogReference.Result;
if (dialogResult.Canceled)
return;
var dialogReference = await this.DialogService.ShowAsync<ConfirmDialog>("Delete Chat", dialogParameters, DialogOptions.FULLSCREEN);
var dialogResult = await dialogReference.Result;
if (dialogResult.Canceled)
return;
}
string chatDirectory;
if (chat.WorkspaceId == Guid.Empty)
@ -279,7 +283,7 @@ public partial class Workspaces : ComponentBase
Directory.Delete(chatDirectory, true);
await this.LoadTreeItems();
if(this.CurrentChatThread?.ChatId == chat.ChatId)
if(unloadChat && this.CurrentChatThread?.ChatId == chat.ChatId)
{
this.CurrentChatThread = null;
await this.CurrentChatThreadChanged.InvokeAsync(this.CurrentChatThread);

View File

@ -0,0 +1,15 @@
<MudDialog>
<DialogContent>
<MudText Typo="Typo.body1">@this.Message</MudText>
<MudList Clickable="@true" @bind-SelectedValue="@this.selectedWorkspace">
@foreach (var (workspaceName, workspaceId) in this.workspaces)
{
<MudListItem Text="@workspaceName" Icon="@Icons.Material.Filled.Description" Value="@workspaceId" />
}
</MudList>
</DialogContent>
<DialogActions>
<MudButton OnClick="@this.Cancel" Variant="Variant.Filled">Cancel</MudButton>
<MudButton OnClick="@this.Confirm" Variant="Variant.Filled" Color="Color.Info">@this.ConfirmText</MudButton>
</DialogActions>
</MudDialog>

View File

@ -0,0 +1,60 @@
using System.Text;
using AIStudio.Settings;
using Microsoft.AspNetCore.Components;
namespace AIStudio.Components.CommonDialogs;
public partial class WorkspaceSelectionDialog : ComponentBase
{
[CascadingParameter]
private MudDialogInstance MudDialog { get; set; } = null!;
[Parameter]
public string Message { get; set; } = string.Empty;
[Parameter]
public Guid SelectedWorkspace { get; set; } = Guid.Empty;
[Parameter]
public string ConfirmText { get; set; } = "OK";
private readonly Dictionary<string, Guid> workspaces = new();
private object? selectedWorkspace;
#region Overrides of ComponentBase
protected override async Task OnInitializedAsync()
{
this.selectedWorkspace = this.SelectedWorkspace;
// Get the workspace root directory:
var workspaceDirectories = Path.Join(SettingsManager.DataDirectory, "workspaces");
if(!Directory.Exists(workspaceDirectories))
{
await base.OnInitializedAsync();
return;
}
// Enumerate the workspace directories:
foreach (var workspaceDirPath in Directory.EnumerateDirectories(workspaceDirectories))
{
// Read the `name` file:
var workspaceNamePath = Path.Join(workspaceDirPath, "name");
var workspaceName = await File.ReadAllTextAsync(workspaceNamePath, Encoding.UTF8);
// Add the workspace to the list:
this.workspaces.Add(workspaceName, Guid.Parse(Path.GetFileName(workspaceDirPath)));
}
this.StateHasChanged();
await base.OnInitializedAsync();
}
#endregion
private void Cancel() => this.MudDialog.Cancel();
private void Confirm() => this.MudDialog.Close(DialogResult.Ok(this.selectedWorkspace is Guid workspaceId ? workspaceId : default));
}

View File

@ -48,7 +48,7 @@
</MudTooltip>
<MudTooltip Text="Move chat to workspace" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
<MudIconButton Icon="@Icons.Material.Filled.MoveToInbox" Disabled="@(!this.CanThreadBeSaved)"/>
<MudIconButton Icon="@Icons.Material.Filled.MoveToInbox" Disabled="@(!this.CanThreadBeSaved)" OnClick="() => this.MoveChatToWorkspace()"/>
</MudTooltip>
</MudToolBar>
</MudPaper>

View File

@ -62,7 +62,7 @@ public partial class Chat : ComponentBase, IAsyncDisposable
private string InputLabel => this.IsProviderSelected ? $"Your Prompt (use selected instance '{this.selectedProvider.InstanceName}', provider '{this.selectedProvider.UsedProvider.ToName()}')" : "Select a provider first";
private bool CanThreadBeSaved => this.IsProviderSelected && this.chatThread is not null && this.chatThread.Blocks.Count > 0;
private bool CanThreadBeSaved => this.chatThread is not null && this.chatThread.Blocks.Count > 0;
private async Task SendMessage()
{
@ -229,6 +229,46 @@ public partial class Chat : ComponentBase, IAsyncDisposable
await this.inputField.Clear();
}
private async Task MoveChatToWorkspace()
{
if(this.chatThread is null)
return;
if(this.workspaces is null)
return;
var dialogParameters = new DialogParameters
{
{ "Message", "Please select the workspace where you want to move the chat to." },
{ "SelectedWorkspace", this.chatThread?.WorkspaceId },
{ "ConfirmText", "Move chat" },
};
var dialogReference = await this.DialogService.ShowAsync<WorkspaceSelectionDialog>("Move Chat to Workspace", dialogParameters, DialogOptions.FULLSCREEN);
var dialogResult = await dialogReference.Result;
if (dialogResult.Canceled)
return;
var workspaceId = dialogResult.Data is Guid id ? id : default;
if (workspaceId == Guid.Empty)
return;
// Delete the chat from the current workspace or the temporary storage:
if (this.chatThread!.WorkspaceId == Guid.Empty)
{
// Case: The chat is stored in the temporary storage:
await this.workspaces.DeleteChat(Path.Join(SettingsManager.DataDirectory, "tempChats", this.chatThread.ChatId.ToString()), askForConfirmation: false, unloadChat: false);
}
else
{
// Case: The chat is stored in a workspace.
await this.workspaces.DeleteChat(Path.Join(SettingsManager.DataDirectory, "workspaces", this.chatThread.WorkspaceId.ToString(), this.chatThread.ChatId.ToString()), askForConfirmation: false, unloadChat: false);
}
this.chatThread!.WorkspaceId = workspaceId;
await this.SaveThread();
}
#region Implementation of IAsyncDisposable
public async ValueTask DisposeAsync()