Refactored tree data structure

This commit is contained in:
Thorsten Sommer 2024-07-11 08:54:03 +02:00
parent 9f954274ff
commit 32af4211db
No known key found for this signature in database
GPG Key ID: B0B7E2FC074BF1F5
6 changed files with 37 additions and 37 deletions

View File

@ -1,3 +1,3 @@
namespace AIStudio.Components.Blocks; namespace AIStudio.Components.Blocks;
public interface ITreeItem<out T>; public interface ITreeItem;

View File

@ -1,3 +1,3 @@
namespace AIStudio.Components.Blocks; namespace AIStudio.Components.Blocks;
public readonly record struct TreeButton<T>(WorkspaceBranch Branch, int Depth, string Text, string Icon) : ITreeItem<T>; public readonly record struct TreeButton(WorkspaceBranch Branch, int Depth, string Text, string Icon) : ITreeItem;

View File

@ -1,3 +1,3 @@
namespace AIStudio.Components.Blocks; namespace AIStudio.Components.Blocks;
public readonly record struct TreeDivider<T> : ITreeItem<T>; public readonly record struct TreeDivider : ITreeItem;

View File

@ -1,6 +1,6 @@
namespace AIStudio.Components.Blocks; namespace AIStudio.Components.Blocks;
public class TreeItemData<T> : ITreeItem<T> public class TreeItemData : ITreeItem
{ {
public WorkspaceBranch Branch { get; init; } = WorkspaceBranch.NONE; public WorkspaceBranch Branch { get; init; } = WorkspaceBranch.NONE;
@ -12,9 +12,9 @@ public class TreeItemData<T> : ITreeItem<T>
public bool IsChat { get; init; } public bool IsChat { get; init; }
public T? Value { get; init; } public string Path { get; init; } = string.Empty;
public bool Expandable { get; init; } = true; public bool Expandable { get; init; } = true;
public HashSet<ITreeItem<T>> Children { get; init; } = []; public HashSet<ITreeItem> Children { get; init; } = [];
} }

View File

@ -1,17 +1,17 @@
<MudTreeView T="ITreeItem<string>" Items="@this.treeItems" MultiSelection="@false" Hover="@true" ExpandOnClick="@true"> <MudTreeView T="ITreeItem" Items="@this.treeItems" MultiSelection="@false" Hover="@true" ExpandOnClick="@true">
<ItemTemplate Context="item"> <ItemTemplate Context="item">
@switch (item) @switch (item)
{ {
case TreeDivider<string>: case TreeDivider:
<li style="min-height: 1em;"> <li style="min-height: 1em;">
<MudDivider Style="margin-top: 1em; width: 90%; border-width: 3pt;"/> <MudDivider Style="margin-top: 1em; width: 90%; border-width: 3pt;"/>
</li> </li>
break; break;
case TreeItemData<string> treeItem: case TreeItemData treeItem:
@if (treeItem.IsChat) @if (treeItem.IsChat)
{ {
<MudTreeViewItem T="ITreeItem<string>" Icon="@treeItem.Icon" Value="@item" LoadingIconColor="@Color.Info" CanExpand="@treeItem.Expandable" Items="@treeItem.Children" OnClick="() => this.LoadChat(treeItem.Value)"> <MudTreeViewItem T="ITreeItem" Icon="@treeItem.Icon" Value="@item" LoadingIconColor="@Color.Info" CanExpand="@treeItem.Expandable" Items="@treeItem.Children" OnClick="() => this.LoadChat(treeItem.Path, true)">
<BodyContent> <BodyContent>
<div style="display: grid; grid-template-columns: 1fr auto; align-items: center; width: 100%"> <div style="display: grid; grid-template-columns: 1fr auto; align-items: center; width: 100%">
<MudText Style="justify-self: start;">@treeItem.Text</MudText> <MudText Style="justify-self: start;">@treeItem.Text</MudText>
@ -25,7 +25,7 @@
} }
else else
{ {
<MudTreeViewItem T="ITreeItem<string>" Icon="@treeItem.Icon" Value="@item" LoadingIconColor="@Color.Info" CanExpand="@treeItem.Expandable" Items="@treeItem.Children"> <MudTreeViewItem T="ITreeItem" Icon="@treeItem.Icon" Value="@item" LoadingIconColor="@Color.Info" CanExpand="@treeItem.Expandable" Items="@treeItem.Children">
<BodyContent> <BodyContent>
<div style="display: grid; grid-template-columns: 1fr auto; align-items: center; width: 100%"> <div style="display: grid; grid-template-columns: 1fr auto; align-items: center; width: 100%">
<MudText Style="justify-self: start;">@treeItem.Text</MudText> <MudText Style="justify-self: start;">@treeItem.Text</MudText>
@ -35,7 +35,7 @@
} }
break; break;
case TreeButton<string> treeButton: case TreeButton treeButton:
<li> <li>
<div class="mud-treeview-item-content" style="background-color: unset;"> <div class="mud-treeview-item-content" style="background-color: unset;">
<div class="mud-treeview-item-arrow"></div> <div class="mud-treeview-item-arrow"></div>

View File

@ -33,7 +33,7 @@ public partial class Workspaces : ComponentBase
} }
}; };
private readonly HashSet<ITreeItem<string>> treeItems = new(); private readonly HashSet<ITreeItem> treeItems = new();
#region Overrides of ComponentBase #region Overrides of ComponentBase
@ -55,33 +55,33 @@ public partial class Workspaces : ComponentBase
private async Task LoadTreeItems() private async Task LoadTreeItems()
{ {
this.treeItems.Clear(); this.treeItems.Clear();
this.treeItems.Add(new TreeItemData<string> this.treeItems.Add(new TreeItemData
{ {
Depth = 0, Depth = 0,
Branch = WorkspaceBranch.WORKSPACES, Branch = WorkspaceBranch.WORKSPACES,
Text = "Workspaces", Text = "Workspaces",
Icon = Icons.Material.Filled.Folder, Icon = Icons.Material.Filled.Folder,
Expandable = true, Expandable = true,
Value = "root", Path = "root",
Children = await this.LoadWorkspaces(), Children = await this.LoadWorkspaces(),
}); });
this.treeItems.Add(new TreeDivider<string>()); this.treeItems.Add(new TreeDivider());
this.treeItems.Add(new TreeItemData<string> this.treeItems.Add(new TreeItemData
{ {
Depth = 0, Depth = 0,
Branch = WorkspaceBranch.TEMPORARY_CHATS, Branch = WorkspaceBranch.TEMPORARY_CHATS,
Text = "Temporary chats", Text = "Temporary chats",
Icon = Icons.Material.Filled.Timer, Icon = Icons.Material.Filled.Timer,
Expandable = true, Expandable = true,
Value = "temp", Path = "temp",
Children = await this.LoadTemporaryChats(), Children = await this.LoadTemporaryChats(),
}); });
} }
private async Task<HashSet<ITreeItem<string>>> LoadTemporaryChats() private async Task<HashSet<ITreeItem>> LoadTemporaryChats()
{ {
var tempChildren = new HashSet<ITreeItem<string>>(); var tempChildren = new HashSet<ITreeItem>();
// //
// Search for workspace folders in the data directory: // Search for workspace folders in the data directory:
@ -100,7 +100,7 @@ public partial class Workspaces : ComponentBase
var chatNamePath = Path.Join(tempChatDirPath, "name"); var chatNamePath = Path.Join(tempChatDirPath, "name");
var chatName = await File.ReadAllTextAsync(chatNamePath, Encoding.UTF8); var chatName = await File.ReadAllTextAsync(chatNamePath, Encoding.UTF8);
tempChildren.Add(new TreeItemData<string> tempChildren.Add(new TreeItemData
{ {
IsChat = true, IsChat = true,
Depth = 1, Depth = 1,
@ -108,7 +108,7 @@ public partial class Workspaces : ComponentBase
Text = chatName, Text = chatName,
Icon = Icons.Material.Filled.Timer, Icon = Icons.Material.Filled.Timer,
Expandable = false, Expandable = false,
Value = tempChatDirPath, Path = tempChatDirPath,
}); });
} }
@ -117,7 +117,7 @@ public partial class Workspaces : ComponentBase
private async Task<HashSet<ITreeItem<string>>> LoadWorkspaces() private async Task<HashSet<ITreeItem<string>>> LoadWorkspaces()
{ {
var workspaces = new HashSet<ITreeItem<string>>(); var workspaces = new HashSet<ITreeItem>();
// //
// Search for workspace folders in the data directory: // Search for workspace folders in the data directory:
@ -136,7 +136,7 @@ public partial class Workspaces : ComponentBase
var workspaceNamePath = Path.Join(workspaceDirPath, "name"); var workspaceNamePath = Path.Join(workspaceDirPath, "name");
var workspaceName = await File.ReadAllTextAsync(workspaceNamePath, Encoding.UTF8); var workspaceName = await File.ReadAllTextAsync(workspaceNamePath, Encoding.UTF8);
workspaces.Add(new TreeItemData<string> workspaces.Add(new TreeItemData
{ {
IsChat = false, IsChat = false,
Depth = 1, Depth = 1,
@ -144,18 +144,18 @@ public partial class Workspaces : ComponentBase
Text = workspaceName, Text = workspaceName,
Icon = Icons.Material.Filled.Description, Icon = Icons.Material.Filled.Description,
Expandable = true, Expandable = true,
Value = workspaceDirPath, Path = workspaceDirPath,
Children = await this.LoadWorkspaceChats(workspaceDirPath), Children = await this.LoadWorkspaceChats(workspaceDirPath),
}); });
} }
workspaces.Add(new TreeButton<string>(WorkspaceBranch.WORKSPACES, 1, "Add workspace",Icons.Material.Filled.Add)); workspaces.Add(new TreeButton(WorkspaceBranch.WORKSPACES, 1, "Add workspace",Icons.Material.Filled.Add));
return workspaces; return workspaces;
} }
private async Task<HashSet<ITreeItem<string>>> LoadWorkspaceChats(string workspacePath) private async Task<HashSet<ITreeItem>> LoadWorkspaceChats(string workspacePath)
{ {
var workspaceChats = new HashSet<ITreeItem<string>>(); var workspaceChats = new HashSet<ITreeItem>();
// Enumerate the workspace directory: // Enumerate the workspace directory:
foreach (var chatPath in Directory.EnumerateDirectories(workspacePath)) foreach (var chatPath in Directory.EnumerateDirectories(workspacePath))
@ -164,7 +164,7 @@ public partial class Workspaces : ComponentBase
var chatNamePath = Path.Join(chatPath, "name"); var chatNamePath = Path.Join(chatPath, "name");
var chatName = await File.ReadAllTextAsync(chatNamePath, Encoding.UTF8); var chatName = await File.ReadAllTextAsync(chatNamePath, Encoding.UTF8);
workspaceChats.Add(new TreeItemData<string> workspaceChats.Add(new TreeItemData
{ {
IsChat = true, IsChat = true,
Depth = 2, Depth = 2,
@ -172,32 +172,32 @@ public partial class Workspaces : ComponentBase
Text = chatName, Text = chatName,
Icon = Icons.Material.Filled.Chat, Icon = Icons.Material.Filled.Chat,
Expandable = false, Expandable = false,
Value = chatPath, Path = chatPath,
}); });
} }
workspaceChats.Add(new TreeButton<string>(WorkspaceBranch.WORKSPACES, 2, "Add chat",Icons.Material.Filled.Add)); workspaceChats.Add(new TreeButton(WorkspaceBranch.WORKSPACES, 2, "Add chat",Icons.Material.Filled.Add));
return workspaceChats; return workspaceChats;
} }
public async Task StoreChat(ChatThread thread) public async Task StoreChat(ChatThread chat)
{ {
string chatDirectory; string chatDirectory;
if (thread.WorkspaceId == Guid.Empty) if (chat.WorkspaceId == Guid.Empty)
chatDirectory = Path.Join(SettingsManager.DataDirectory, "tempChats", thread.ChatId.ToString()); chatDirectory = Path.Join(SettingsManager.DataDirectory, "tempChats", chat.ChatId.ToString());
else else
chatDirectory = Path.Join(SettingsManager.DataDirectory, "workspaces", thread.WorkspaceId.ToString(), thread.ChatId.ToString()); chatDirectory = Path.Join(SettingsManager.DataDirectory, "workspaces", chat.WorkspaceId.ToString(), chat.ChatId.ToString());
// Ensure the directory exists: // Ensure the directory exists:
Directory.CreateDirectory(chatDirectory); Directory.CreateDirectory(chatDirectory);
// Save the chat name: // Save the chat name:
var chatNamePath = Path.Join(chatDirectory, "name"); var chatNamePath = Path.Join(chatDirectory, "name");
await File.WriteAllTextAsync(chatNamePath, thread.Name); await File.WriteAllTextAsync(chatNamePath, chat.Name);
// Save the thread as thread.json: // Save the thread as thread.json:
var chatPath = Path.Join(chatDirectory, "thread.json"); var chatPath = Path.Join(chatDirectory, "thread.json");
await File.WriteAllTextAsync(chatPath, JsonSerializer.Serialize(thread, JSON_OPTIONS), Encoding.UTF8); await File.WriteAllTextAsync(chatPath, JsonSerializer.Serialize(chat, JSON_OPTIONS), Encoding.UTF8);
// Reload the tree items: // Reload the tree items:
await this.LoadTreeItems(); await this.LoadTreeItems();