diff --git a/app/MindWork AI Studio/Components/AssistantBase.razor b/app/MindWork AI Studio/Components/AssistantBase.razor index e04bb34..175f792 100644 --- a/app/MindWork AI Studio/Components/AssistantBase.razor +++ b/app/MindWork AI Studio/Components/AssistantBase.razor @@ -20,7 +20,7 @@ { Issues - + @foreach (var issue in this.inputIssues) { diff --git a/app/MindWork AI Studio/Components/Blocks/ExpansionPanel.razor b/app/MindWork AI Studio/Components/Blocks/ExpansionPanel.razor index 548de0f..3a20189 100644 --- a/app/MindWork AI Studio/Components/Blocks/ExpansionPanel.razor +++ b/app/MindWork AI Studio/Components/Blocks/ExpansionPanel.razor @@ -1,4 +1,4 @@ - +
diff --git a/app/MindWork AI Studio/Components/Blocks/MudTextList.razor b/app/MindWork AI Studio/Components/Blocks/MudTextList.razor index 2c42cc2..bb70247 100644 --- a/app/MindWork AI Studio/Components/Blocks/MudTextList.razor +++ b/app/MindWork AI Studio/Components/Blocks/MudTextList.razor @@ -1,7 +1,7 @@ - + @foreach(var item in this.Items) { - + @item.Header: @item.Text } diff --git a/app/MindWork AI Studio/Components/Blocks/TreeItemData.cs b/app/MindWork AI Studio/Components/Blocks/TreeItemData.cs index aa96877..2ddedaf 100644 --- a/app/MindWork AI Studio/Components/Blocks/TreeItemData.cs +++ b/app/MindWork AI Studio/Components/Blocks/TreeItemData.cs @@ -18,5 +18,5 @@ public class TreeItemData : ITreeItem public bool Expandable { get; init; } = true; - public HashSet Children { get; init; } = []; + public IReadOnlyCollection> Children { get; init; } = []; } \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Blocks/Workspaces.razor b/app/MindWork AI Studio/Components/Blocks/Workspaces.razor index e45fea7..da8f503 100644 --- a/app/MindWork AI Studio/Components/Blocks/Workspaces.razor +++ b/app/MindWork AI Studio/Components/Blocks/Workspaces.razor @@ -1,6 +1,6 @@ - + - @switch (item) + @switch (item.Value) { case TreeDivider:
  • @@ -11,7 +11,7 @@ case TreeItemData treeItem: @if (treeItem.Type is TreeItemType.CHAT) { - +
    @@ -44,7 +44,7 @@ } else if (treeItem.Type is TreeItemType.WORKSPACE) { - +
    @treeItem.Text @@ -63,7 +63,7 @@ } else { - +
    @treeItem.Text diff --git a/app/MindWork AI Studio/Components/Blocks/Workspaces.razor.cs b/app/MindWork AI Studio/Components/Blocks/Workspaces.razor.cs index 6030470..02ef041 100644 --- a/app/MindWork AI Studio/Components/Blocks/Workspaces.razor.cs +++ b/app/MindWork AI Studio/Components/Blocks/Workspaces.razor.cs @@ -47,8 +47,8 @@ public partial class Workspaces : ComponentBase new JsonStringEnumConverter(JsonNamingPolicy.SnakeCaseUpper), } }; - - private readonly HashSet treeItems = new(); + + private readonly List> treeItems = new(); #region Overrides of ComponentBase @@ -70,33 +70,46 @@ public partial class Workspaces : ComponentBase private async Task LoadTreeItems() { this.treeItems.Clear(); - this.treeItems.Add(new TreeItemData + this.treeItems.Add(new TreeItemData { - Depth = 0, - Branch = WorkspaceBranch.WORKSPACES, - Text = "Workspaces", - Icon = Icons.Material.Filled.Folder, Expandable = true, - Path = "root", - Children = await this.LoadWorkspaces(), + Value = new TreeItemData + { + Depth = 0, + Branch = WorkspaceBranch.WORKSPACES, + Text = "Workspaces", + Icon = Icons.Material.Filled.Folder, + Expandable = true, + Path = "root", + Children = await this.LoadWorkspaces(), + }, }); - this.treeItems.Add(new TreeDivider()); - this.treeItems.Add(new TreeItemData + this.treeItems.Add(new TreeItemData + { + Expandable = false, + Value = new TreeDivider(), + }); + + this.treeItems.Add(new TreeItemData { - Depth = 0, - Branch = WorkspaceBranch.TEMPORARY_CHATS, - Text = "Temporary chats", - Icon = Icons.Material.Filled.Timer, Expandable = true, - Path = "temp", - Children = await this.LoadTemporaryChats(), + Value = new TreeItemData + { + Depth = 0, + Branch = WorkspaceBranch.TEMPORARY_CHATS, + Text = "Temporary chats", + Icon = Icons.Material.Filled.Timer, + Expandable = true, + Path = "temp", + Children = await this.LoadTemporaryChats(), + }, }); } - private async Task> LoadTemporaryChats() + private async Task>> LoadTemporaryChats() { - var tempChildren = new HashSet(); + var tempChildren = new List>(); // // Search for workspace folders in the data directory: @@ -115,15 +128,19 @@ public partial class Workspaces : ComponentBase var chatNamePath = Path.Join(tempChatDirPath, "name"); var chatName = await File.ReadAllTextAsync(chatNamePath, Encoding.UTF8); - tempChildren.Add(new TreeItemData + tempChildren.Add(new TreeItemData { - Type = TreeItemType.CHAT, - Depth = 1, - Branch = WorkspaceBranch.TEMPORARY_CHATS, - Text = chatName, - Icon = Icons.Material.Filled.Timer, Expandable = false, - Path = tempChatDirPath, + Value = new TreeItemData + { + Type = TreeItemType.CHAT, + Depth = 1, + Branch = WorkspaceBranch.TEMPORARY_CHATS, + Text = chatName, + Icon = Icons.Material.Filled.Timer, + Expandable = false, + Path = tempChatDirPath, + }, }); } @@ -140,9 +157,9 @@ public partial class Workspaces : ComponentBase return await File.ReadAllTextAsync(workspaceNamePath, Encoding.UTF8); } - private async Task> LoadWorkspaces() + private async Task>> LoadWorkspaces() { - var workspaces = new HashSet(); + var workspaces = new List>(); // // Search for workspace folders in the data directory: @@ -161,26 +178,34 @@ public partial class Workspaces : ComponentBase var workspaceNamePath = Path.Join(workspaceDirPath, "name"); var workspaceName = await File.ReadAllTextAsync(workspaceNamePath, Encoding.UTF8); - workspaces.Add(new TreeItemData + workspaces.Add(new TreeItemData { - Type = TreeItemType.WORKSPACE, - Depth = 1, - Branch = WorkspaceBranch.WORKSPACES, - Text = workspaceName, - Icon = Icons.Material.Filled.Description, Expandable = true, - Path = workspaceDirPath, - Children = await this.LoadWorkspaceChats(workspaceDirPath), + Value = new TreeItemData + { + Type = TreeItemType.WORKSPACE, + Depth = 1, + Branch = WorkspaceBranch.WORKSPACES, + Text = workspaceName, + Icon = Icons.Material.Filled.Description, + Expandable = true, + Path = workspaceDirPath, + Children = await this.LoadWorkspaceChats(workspaceDirPath), + }, }); } - workspaces.Add(new TreeButton(WorkspaceBranch.WORKSPACES, 1, "Add workspace",Icons.Material.Filled.LibraryAdd, this.AddWorkspace)); + workspaces.Add(new TreeItemData + { + Expandable = false, + Value = new TreeButton(WorkspaceBranch.WORKSPACES, 1, "Add workspace",Icons.Material.Filled.LibraryAdd, this.AddWorkspace), + }); return workspaces; } - private async Task> LoadWorkspaceChats(string workspacePath) + private async Task>> LoadWorkspaceChats(string workspacePath) { - var workspaceChats = new HashSet(); + var workspaceChats = new List>(); // Enumerate the workspace directory: foreach (var chatPath in Directory.EnumerateDirectories(workspacePath)) @@ -189,19 +214,28 @@ public partial class Workspaces : ComponentBase var chatNamePath = Path.Join(chatPath, "name"); var chatName = await File.ReadAllTextAsync(chatNamePath, Encoding.UTF8); - workspaceChats.Add(new TreeItemData + workspaceChats.Add(new TreeItemData { - Type = TreeItemType.CHAT, - Depth = 2, - Branch = WorkspaceBranch.WORKSPACES, - Text = chatName, - Icon = Icons.Material.Filled.Chat, Expandable = false, - Path = chatPath, + Value = new TreeItemData + { + Type = TreeItemType.CHAT, + Depth = 2, + Branch = WorkspaceBranch.WORKSPACES, + Text = chatName, + Icon = Icons.Material.Filled.Chat, + Expandable = false, + Path = chatPath, + }, }); } - workspaceChats.Add(new TreeButton(WorkspaceBranch.WORKSPACES, 2, "Add chat",Icons.Material.Filled.AddComment, () => this.AddChat(workspacePath))); + workspaceChats.Add(new TreeItemData + { + Expandable = false, + Value = new TreeButton(WorkspaceBranch.WORKSPACES, 2, "Add chat",Icons.Material.Filled.AddComment, () => this.AddChat(workspacePath)), + }); + return workspaceChats; } @@ -247,7 +281,7 @@ public partial class Workspaces : ComponentBase var dialogReference = await this.DialogService.ShowAsync("Load Chat", dialogParameters, DialogOptions.FULLSCREEN); var dialogResult = await dialogReference.Result; - if (dialogResult.Canceled) + if (dialogResult is null || dialogResult.Canceled) return null; } @@ -294,7 +328,7 @@ public partial class Workspaces : ComponentBase var dialogReference = await this.DialogService.ShowAsync("Delete Chat", dialogParameters, DialogOptions.FULLSCREEN); var dialogResult = await dialogReference.Result; - if (dialogResult.Canceled) + if (dialogResult is null || dialogResult.Canceled) return; } @@ -331,7 +365,7 @@ public partial class Workspaces : ComponentBase var dialogReference = await this.DialogService.ShowAsync("Rename Chat", dialogParameters, DialogOptions.FULLSCREEN); var dialogResult = await dialogReference.Result; - if (dialogResult.Canceled) + if (dialogResult is null || dialogResult.Canceled) return; chat.Name = (dialogResult.Data as string)!; @@ -356,7 +390,7 @@ public partial class Workspaces : ComponentBase var dialogReference = await this.DialogService.ShowAsync("Rename Workspace", dialogParameters, DialogOptions.FULLSCREEN); var dialogResult = await dialogReference.Result; - if (dialogResult.Canceled) + if (dialogResult is null || dialogResult.Canceled) return; var alteredWorkspaceName = (dialogResult.Data as string)!; @@ -377,7 +411,7 @@ public partial class Workspaces : ComponentBase var dialogReference = await this.DialogService.ShowAsync("Add Workspace", dialogParameters, DialogOptions.FULLSCREEN); var dialogResult = await dialogReference.Result; - if (dialogResult.Canceled) + if (dialogResult is null || dialogResult.Canceled) return; var workspaceId = Guid.NewGuid(); @@ -408,7 +442,7 @@ public partial class Workspaces : ComponentBase var dialogReference = await this.DialogService.ShowAsync("Delete Workspace", dialogParameters, DialogOptions.FULLSCREEN); var dialogResult = await dialogReference.Result; - if (dialogResult.Canceled) + if (dialogResult is null || dialogResult.Canceled) return; Directory.Delete(workspacePath, true); @@ -430,7 +464,7 @@ public partial class Workspaces : ComponentBase var dialogReference = await this.DialogService.ShowAsync("Move Chat to Workspace", dialogParameters, DialogOptions.FULLSCREEN); var dialogResult = await dialogReference.Result; - if (dialogResult.Canceled) + if (dialogResult is null || dialogResult.Canceled) return; var workspaceId = dialogResult.Data is Guid id ? id : default; @@ -475,7 +509,7 @@ public partial class Workspaces : ComponentBase var dialogReference = await this.DialogService.ShowAsync("Create Chat", dialogParameters, DialogOptions.FULLSCREEN); var dialogResult = await dialogReference.Result; - if (dialogResult.Canceled) + if (dialogResult is null || dialogResult.Canceled) return; } diff --git a/app/MindWork AI Studio/Components/ConfigurationBase.razor.cs b/app/MindWork AI Studio/Components/ConfigurationBase.razor.cs index 9f0f047..03dc7db 100644 --- a/app/MindWork AI Studio/Components/ConfigurationBase.razor.cs +++ b/app/MindWork AI Studio/Components/ConfigurationBase.razor.cs @@ -1,4 +1,5 @@ using AIStudio.Settings; +using AIStudio.Tools; using Microsoft.AspNetCore.Components; @@ -23,7 +24,12 @@ public partial class ConfigurationBase : ComponentBase public string OptionHelp { get; set; } = string.Empty; [Inject] - public SettingsManager SettingsManager { get; init; } = null!; + protected SettingsManager SettingsManager { get; init; } = null!; + + [Inject] + protected MessageBus MessageBus { get; init; } = null!; protected const string MARGIN_CLASS = "mb-6"; + + protected async Task InformAboutChange() => await this.MessageBus.SendMessage(this, Event.CONFIGURATION_CHANGED); } \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/ConfigurationOption.razor.cs b/app/MindWork AI Studio/Components/ConfigurationOption.razor.cs index f2c6593..b3bed55 100644 --- a/app/MindWork AI Studio/Components/ConfigurationOption.razor.cs +++ b/app/MindWork AI Studio/Components/ConfigurationOption.razor.cs @@ -35,5 +35,6 @@ public partial class ConfigurationOption : ConfigurationBase { this.StateUpdate(updatedState); await this.SettingsManager.StoreSettings(); + await this.InformAboutChange(); } } \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/ConfigurationSelect.razor.cs b/app/MindWork AI Studio/Components/ConfigurationSelect.razor.cs index 8a0f9a7..07c8abf 100644 --- a/app/MindWork AI Studio/Components/ConfigurationSelect.razor.cs +++ b/app/MindWork AI Studio/Components/ConfigurationSelect.razor.cs @@ -30,6 +30,7 @@ public partial class ConfigurationSelect : ConfigurationBase { this.SelectionUpdate(updatedValue); await this.SettingsManager.StoreSettings(); + await this.InformAboutChange(); } private static string GetClass => $"{MARGIN_CLASS} rounded-lg"; diff --git a/app/MindWork AI Studio/Components/ConfigurationSelectData.cs b/app/MindWork AI Studio/Components/ConfigurationSelectData.cs index 6ed436e..cdb9cf4 100644 --- a/app/MindWork AI Studio/Components/ConfigurationSelectData.cs +++ b/app/MindWork AI Studio/Components/ConfigurationSelectData.cs @@ -47,4 +47,12 @@ public static class ConfigurationSelectDataFactory yield return new("Delete temporary chats older than 180 days", WorkspaceStorageTemporaryMaintenancePolicy.DELETE_OLDER_THAN_180_DAYS); yield return new("Delete temporary chats older than 1 year", WorkspaceStorageTemporaryMaintenancePolicy.DELETE_OLDER_THAN_365_DAYS); } + + public static IEnumerable> GetNavBehaviorData() + { + yield return new("Navigation expands on mouse hover", NavBehavior.EXPAND_ON_HOVER); + yield return new("Navigation never expands, but there are tooltips", NavBehavior.NEVER_EXPAND_USE_TOOLTIPS); + yield return new("Navigation never expands, no tooltips", NavBehavior.NEVER_EXPAND_NO_TOOLTIPS); + yield return new("Always expand navigation", NavBehavior.ALWAYS_EXPAND); + } } \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Layout/MainLayout.razor b/app/MindWork AI Studio/Components/Layout/MainLayout.razor index 052ec94..1e6eb6a 100644 --- a/app/MindWork AI Studio/Components/Layout/MainLayout.razor +++ b/app/MindWork AI Studio/Components/Layout/MainLayout.razor @@ -1,36 +1,32 @@ -@inherits LayoutComponentBase +@using AIStudio.Settings +@inherits LayoutComponentBase @if (!this.performingUpdate) { - + - - Home - - - Chat - - - Assistants - - - Supporters - - - About - - - Settings - + @foreach (var navBarItem in NAV_ITEMS) + { + if (this.SettingsManager.ConfigurationData.NavigationBehavior is NavBehavior.NEVER_EXPAND_USE_TOOLTIPS) + { + + @navBarItem.Name + + } + else + { + @navBarItem.Name + } + } } - + @if (!this.performingUpdate && this.IsUpdateAlertVisible) { diff --git a/app/MindWork AI Studio/Components/Layout/MainLayout.razor.cs b/app/MindWork AI Studio/Components/Layout/MainLayout.razor.cs index 7c7f09d..6223b33 100644 --- a/app/MindWork AI Studio/Components/Layout/MainLayout.razor.cs +++ b/app/MindWork AI Studio/Components/Layout/MainLayout.razor.cs @@ -34,12 +34,30 @@ public partial class MainLayout : LayoutComponentBase, IMessageBusReceiver public string AdditionalHeight { get; private set; } = "0em"; + private string PaddingLeft => this.navBarOpen ? $"padding-left: {NAVBAR_EXPANDED_WIDTH_INT - NAVBAR_COLLAPSED_WIDTH_INT}em;" : "padding-left: 0em;"; + + private const int NAVBAR_COLLAPSED_WIDTH_INT = 4; + private const int NAVBAR_EXPANDED_WIDTH_INT = 10; + private static readonly string NAVBAR_COLLAPSED_WIDTH = $"{NAVBAR_COLLAPSED_WIDTH_INT}em"; + private static readonly string NAVBAR_EXPANDED_WIDTH = $"{NAVBAR_EXPANDED_WIDTH_INT}em"; + + private bool navBarOpen; private bool isUpdateAvailable; private bool performingUpdate; private bool userDismissedUpdate; private string updateToVersion = string.Empty; private UpdateResponse? currentUpdateResponse; + private static readonly IReadOnlyCollection NAV_ITEMS = new List + { + new("Home", Icons.Material.Filled.Home, Color.Default, "/", true), + new("Chat", Icons.Material.Filled.Chat, Color.Default, "/chat", false), + new("Assistants", Icons.Material.Filled.Apps, Color.Default ,"/assistants", false), + new("Supporters", Icons.Material.Filled.Favorite, Color.Error ,"/supporters", false), + new("About", Icons.Material.Filled.Info, Color.Default ,"/about", false), + new("Settings", Icons.Material.Filled.Settings, Color.Default ,"/settings", false), + }; + #region Overrides of ComponentBase protected override async Task OnInitializedAsync() @@ -63,12 +81,16 @@ public partial class MainLayout : LayoutComponentBase, IMessageBusReceiver // Register this component with the message bus: this.MessageBus.RegisterComponent(this); - this.MessageBus.ApplyFilters(this, [], [ Event.UPDATE_AVAILABLE, Event.USER_SEARCH_FOR_UPDATE ]); + this.MessageBus.ApplyFilters(this, [], [ Event.UPDATE_AVAILABLE, Event.USER_SEARCH_FOR_UPDATE, Event.CONFIGURATION_CHANGED ]); // Set the js runtime for the update service: UpdateService.SetBlazorDependencies(this.JsRuntime, this.Snackbar); TemporaryChatService.Initialize(); + // Should the navigation bar be open by default? + if(this.SettingsManager.ConfigurationData.NavigationBehavior is NavBehavior.ALWAYS_EXPAND) + this.navBarOpen = true; + await base.OnInitializedAsync(); } @@ -96,6 +118,15 @@ public partial class MainLayout : LayoutComponentBase, IMessageBusReceiver } break; + + case Event.CONFIGURATION_CHANGED: + if(this.SettingsManager.ConfigurationData.NavigationBehavior is NavBehavior.ALWAYS_EXPAND) + this.navBarOpen = true; + else + this.navBarOpen = false; + + this.StateHasChanged(); + break; } } @@ -105,7 +136,7 @@ public partial class MainLayout : LayoutComponentBase, IMessageBusReceiver } #endregion - + private async Task DismissUpdate() { this.userDismissedUpdate = true; @@ -151,7 +182,7 @@ public partial class MainLayout : LayoutComponentBase, IMessageBusReceiver var dialogReference = await this.DialogService.ShowAsync("Update", dialogParameters, DialogOptions.FULLSCREEN_NO_HEADER); var dialogResult = await dialogReference.Result; - if (dialogResult.Canceled) + if (dialogResult is null || dialogResult.Canceled) return; this.performingUpdate = true; @@ -170,7 +201,7 @@ public partial class MainLayout : LayoutComponentBase, IMessageBusReceiver var dialogReference = await this.DialogService.ShowAsync("Leave Chat Page", dialogParameters, DialogOptions.FULLSCREEN); var dialogResult = await dialogReference.Result; - if (dialogResult.Canceled) + if (dialogResult is null || dialogResult.Canceled) { context.PreventNavigation(); return; diff --git a/app/MindWork AI Studio/Components/Layout/NavBarItem.cs b/app/MindWork AI Studio/Components/Layout/NavBarItem.cs new file mode 100644 index 0000000..668634c --- /dev/null +++ b/app/MindWork AI Studio/Components/Layout/NavBarItem.cs @@ -0,0 +1,3 @@ +namespace AIStudio.Components.Layout; + +public record NavBarItem(string Name, string Icon, Color IconColor, string Path, bool MatchAll); \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Pages/About.razor b/app/MindWork AI Studio/Components/Pages/About.razor index a5cef1a..b03602a 100644 --- a/app/MindWork AI Studio/Components/Pages/About.razor +++ b/app/MindWork AI Studio/Components/Pages/About.razor @@ -9,14 +9,14 @@ The following list shows the versions of the MindWork AI Studio, the used compilers, build time, etc.: - - - - - - - - + + + + + + + + Check for updates diff --git a/app/MindWork AI Studio/Components/Pages/Chat.razor.cs b/app/MindWork AI Studio/Components/Pages/Chat.razor.cs index 09dd708..491053d 100644 --- a/app/MindWork AI Studio/Components/Pages/Chat.razor.cs +++ b/app/MindWork AI Studio/Components/Pages/Chat.razor.cs @@ -235,7 +235,7 @@ public partial class Chat : MSGComponentBase, IAsyncDisposable var dialogReference = await this.DialogService.ShowAsync("Delete Chat", dialogParameters, DialogOptions.FULLSCREEN); var dialogResult = await dialogReference.Result; - if (dialogResult.Canceled) + if (dialogResult is null || dialogResult.Canceled) return; } @@ -297,7 +297,7 @@ public partial class Chat : MSGComponentBase, IAsyncDisposable var confirmationDialogReference = await this.DialogService.ShowAsync("Unsaved Changes", confirmationDialogParameters, DialogOptions.FULLSCREEN); var confirmationDialogResult = await confirmationDialogReference.Result; - if (confirmationDialogResult.Canceled) + if (confirmationDialogResult is null || confirmationDialogResult.Canceled) return; } @@ -310,7 +310,7 @@ public partial class Chat : MSGComponentBase, IAsyncDisposable var dialogReference = await this.DialogService.ShowAsync("Move Chat to Workspace", dialogParameters, DialogOptions.FULLSCREEN); var dialogResult = await dialogReference.Result; - if (dialogResult.Canceled) + if (dialogResult is null || dialogResult.Canceled) return; var workspaceId = dialogResult.Data is Guid id ? id : default; diff --git a/app/MindWork AI Studio/Components/Pages/IconFinder/AssistantIconFinder.razor.cs b/app/MindWork AI Studio/Components/Pages/IconFinder/AssistantIconFinder.razor.cs index 96d06e9..a04398b 100644 --- a/app/MindWork AI Studio/Components/Pages/IconFinder/AssistantIconFinder.razor.cs +++ b/app/MindWork AI Studio/Components/Pages/IconFinder/AssistantIconFinder.razor.cs @@ -1,5 +1,3 @@ -using AIStudio.Provider; - namespace AIStudio.Components.Pages.IconFinder; public partial class AssistantIconFinder : AssistantBaseCore diff --git a/app/MindWork AI Studio/Components/Pages/Settings.razor b/app/MindWork AI Studio/Components/Pages/Settings.razor index 2becc03..9a11b04 100644 --- a/app/MindWork AI Studio/Components/Pages/Settings.razor +++ b/app/MindWork AI Studio/Components/Pages/Settings.razor @@ -73,5 +73,6 @@ + \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Pages/Settings.razor.cs b/app/MindWork AI Studio/Components/Pages/Settings.razor.cs index 23c14d3..868289f 100644 --- a/app/MindWork AI Studio/Components/Pages/Settings.razor.cs +++ b/app/MindWork AI Studio/Components/Pages/Settings.razor.cs @@ -1,6 +1,8 @@ using AIStudio.Components.CommonDialogs; using AIStudio.Provider; using AIStudio.Settings; +using AIStudio.Tools; + using Microsoft.AspNetCore.Components; using DialogOptions = AIStudio.Components.CommonDialogs.DialogOptions; @@ -19,6 +21,9 @@ public partial class Settings : ComponentBase [Inject] public IJSRuntime JsRuntime { get; init; } = null!; + + [Inject] + protected MessageBus MessageBus { get; init; } = null!; #region Provider related @@ -31,14 +36,15 @@ public partial class Settings : ComponentBase var dialogReference = await this.DialogService.ShowAsync("Add Provider", dialogParameters, DialogOptions.FULLSCREEN); var dialogResult = await dialogReference.Result; - if (dialogResult.Canceled) + if (dialogResult is null || dialogResult.Canceled) return; - var addedProvider = (AIStudio.Settings.Provider)dialogResult.Data; + var addedProvider = (AIStudio.Settings.Provider)dialogResult.Data!; addedProvider = addedProvider with { Num = this.SettingsManager.ConfigurationData.NextProviderNum++ }; this.SettingsManager.ConfigurationData.Providers.Add(addedProvider); await this.SettingsManager.StoreSettings(); + await this.MessageBus.SendMessage(this, Event.CONFIGURATION_CHANGED); } private async Task EditProvider(AIStudio.Settings.Provider provider) @@ -58,10 +64,10 @@ public partial class Settings : ComponentBase var dialogReference = await this.DialogService.ShowAsync("Edit Provider", dialogParameters, DialogOptions.FULLSCREEN); var dialogResult = await dialogReference.Result; - if (dialogResult.Canceled) + if (dialogResult is null || dialogResult.Canceled) return; - var editedProvider = (AIStudio.Settings.Provider)dialogResult.Data; + var editedProvider = (AIStudio.Settings.Provider)dialogResult.Data!; // Set the provider number if it's not set. This is important for providers // added before we started saving the provider number. @@ -70,6 +76,7 @@ public partial class Settings : ComponentBase this.SettingsManager.ConfigurationData.Providers[this.SettingsManager.ConfigurationData.Providers.IndexOf(provider)] = editedProvider; await this.SettingsManager.StoreSettings(); + await this.MessageBus.SendMessage(this, Event.CONFIGURATION_CHANGED); } private async Task DeleteProvider(AIStudio.Settings.Provider provider) @@ -81,7 +88,7 @@ public partial class Settings : ComponentBase var dialogReference = await this.DialogService.ShowAsync("Delete Provider", dialogParameters, DialogOptions.FULLSCREEN); var dialogResult = await dialogReference.Result; - if (dialogResult.Canceled) + if (dialogResult is null || dialogResult.Canceled) return; var providerInstance = provider.CreateProvider(); @@ -91,6 +98,8 @@ public partial class Settings : ComponentBase this.SettingsManager.ConfigurationData.Providers.Remove(provider); await this.SettingsManager.StoreSettings(); } + + await this.MessageBus.SendMessage(this, Event.CONFIGURATION_CHANGED); } private string GetProviderDashboardURL(Providers provider) => provider switch diff --git a/app/MindWork AI Studio/Components/Pages/TextSummarizer/AssistantTextSummarizer.razor.cs b/app/MindWork AI Studio/Components/Pages/TextSummarizer/AssistantTextSummarizer.razor.cs index 00e0742..1a15c90 100644 --- a/app/MindWork AI Studio/Components/Pages/TextSummarizer/AssistantTextSummarizer.razor.cs +++ b/app/MindWork AI Studio/Components/Pages/TextSummarizer/AssistantTextSummarizer.razor.cs @@ -1,4 +1,3 @@ -using AIStudio.Provider; using AIStudio.Tools; namespace AIStudio.Components.Pages.TextSummarizer; diff --git a/app/MindWork AI Studio/Components/Pages/Translator/AssistantTranslator.razor.cs b/app/MindWork AI Studio/Components/Pages/Translator/AssistantTranslator.razor.cs index 87c93f4..fcfcef3 100644 --- a/app/MindWork AI Studio/Components/Pages/Translator/AssistantTranslator.razor.cs +++ b/app/MindWork AI Studio/Components/Pages/Translator/AssistantTranslator.razor.cs @@ -1,4 +1,3 @@ -using AIStudio.Provider; using AIStudio.Tools; namespace AIStudio.Components.Pages.Translator; diff --git a/app/MindWork AI Studio/Components/Routes.razor b/app/MindWork AI Studio/Components/Routes.razor index 0d877c0..fca6735 100644 --- a/app/MindWork AI Studio/Components/Routes.razor +++ b/app/MindWork AI Studio/Components/Routes.razor @@ -7,4 +7,5 @@ + \ No newline at end of file diff --git a/app/MindWork AI Studio/MindWork AI Studio.csproj b/app/MindWork AI Studio/MindWork AI Studio.csproj index 61033b5..9d6605a 100644 --- a/app/MindWork AI Studio/MindWork AI Studio.csproj +++ b/app/MindWork AI Studio/MindWork AI Studio.csproj @@ -45,8 +45,8 @@ - - + + diff --git a/app/MindWork AI Studio/Settings/Data.cs b/app/MindWork AI Studio/Settings/Data.cs index ea77487..f18fd85 100644 --- a/app/MindWork AI Studio/Settings/Data.cs +++ b/app/MindWork AI Studio/Settings/Data.cs @@ -51,4 +51,9 @@ public sealed class Data /// The chat storage maintenance behavior. /// public WorkspaceStorageTemporaryMaintenancePolicy WorkspaceStorageTemporaryMaintenancePolicy { get; set; } = WorkspaceStorageTemporaryMaintenancePolicy.DELETE_OLDER_THAN_90_DAYS; + + /// + /// The navigation behavior. + /// + public NavBehavior NavigationBehavior { get; set; } = NavBehavior.EXPAND_ON_HOVER; } \ No newline at end of file diff --git a/app/MindWork AI Studio/Settings/NavBehavior.cs b/app/MindWork AI Studio/Settings/NavBehavior.cs new file mode 100644 index 0000000..70170a1 --- /dev/null +++ b/app/MindWork AI Studio/Settings/NavBehavior.cs @@ -0,0 +1,9 @@ +namespace AIStudio.Settings; + +public enum NavBehavior +{ + EXPAND_ON_HOVER, + NEVER_EXPAND_USE_TOOLTIPS, + NEVER_EXPAND_NO_TOOLTIPS, + ALWAYS_EXPAND, +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Settings/ProviderDialog.razor b/app/MindWork AI Studio/Settings/ProviderDialog.razor index e83740e..d90e435 100644 --- a/app/MindWork AI Studio/Settings/ProviderDialog.razor +++ b/app/MindWork AI Studio/Settings/ProviderDialog.razor @@ -79,10 +79,10 @@ { Issues - + @foreach (var issue in this.dataIssues) { - + @issue } diff --git a/app/MindWork AI Studio/Tools/Event.cs b/app/MindWork AI Studio/Tools/Event.cs index 62a6ae9..3d124d7 100644 --- a/app/MindWork AI Studio/Tools/Event.cs +++ b/app/MindWork AI Studio/Tools/Event.cs @@ -6,6 +6,7 @@ public enum Event // Common events: STATE_HAS_CHANGED, + CONFIGURATION_CHANGED, // Update events: USER_SEARCH_FOR_UPDATE, diff --git a/app/MindWork AI Studio/packages.lock.json b/app/MindWork AI Studio/packages.lock.json index ef66cf4..5e2d927 100644 --- a/app/MindWork AI Studio/packages.lock.json +++ b/app/MindWork AI Studio/packages.lock.json @@ -4,9 +4,9 @@ "net8.0": { "Microsoft.Extensions.FileProviders.Embedded": { "type": "Direct", - "requested": "[8.0.6, )", - "resolved": "8.0.6", - "contentHash": "hQlf5+YxiUbKdpaPBf/zdMGItnWF8ai9ToPjeZ6gnxT10V4RGDKvChl5MSdc838+2SRHLAC0cdJwG0+L7dqR0g==", + "requested": "[8.0.7, )", + "resolved": "8.0.7", + "contentHash": "ABsn0T09b5lzVNbOcuRc10+kNZkO+RGtZWfzqVay0Ah+/ouhEvG7JrXc+9+7zFgoPuH4E4N6+uWfTp+pJqMeGw==", "dependencies": { "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0" } @@ -19,13 +19,13 @@ }, "MudBlazor": { "type": "Direct", - "requested": "[6.20.0, )", - "resolved": "6.20.0", - "contentHash": "2MqW/E1OLszSqDhW06rpRTN4OpIRJU0iVzeiZLPzymckrKJH1Hg09St+O3kaEnsbXRcjcdM9iE5cSKzCgxvySQ==", + "requested": "[7.4.0, )", + "resolved": "7.4.0", + "contentHash": "dm8ZD6OhyI6icE3Si0V3BJvwPZp8fEspPFq4/iQXU8/i7L39/ny2bPgQqPnQmIojppd9cR/H4RdsaBlSLe6rIw==", "dependencies": { - "Microsoft.AspNetCore.Components": "8.0.3", - "Microsoft.AspNetCore.Components.Web": "8.0.3", - "Microsoft.Extensions.Localization": "8.0.3" + "Microsoft.AspNetCore.Components": "8.0.6", + "Microsoft.AspNetCore.Components.Web": "8.0.6", + "Microsoft.Extensions.Localization": "8.0.6" } }, "MudBlazor.Markdown": { @@ -45,53 +45,53 @@ }, "Microsoft.AspNetCore.Authorization": { "type": "Transitive", - "resolved": "8.0.3", - "contentHash": "9Nic17acgZbysUlhGc+TEd9F8jI01kC6+V31sC7/xI5v2OSWGL8NhdYaB/Iu4KnDRoQEolg6qvepGsVfeYpIYA==", + "resolved": "8.0.6", + "contentHash": "H1CSbD7UeSPsrJSUpvbms6SqWMa5y8ch4Rw+gyHh2uztOEb20fTP2r0AUnStn1Q9WYghikiDO5wzkgV+n6KC2Q==", "dependencies": { - "Microsoft.AspNetCore.Metadata": "8.0.3", + "Microsoft.AspNetCore.Metadata": "8.0.6", "Microsoft.Extensions.Logging.Abstractions": "8.0.1", "Microsoft.Extensions.Options": "8.0.2" } }, "Microsoft.AspNetCore.Components": { "type": "Transitive", - "resolved": "8.0.3", - "contentHash": "q1Da8sfxG+B+BSYpc/3RKNEdzGcLbDTXkTUqekY65kXMMVCTqTAQ0Zs4csmB7FNVTFSjwaw1dGMFD0bQ+erlBw==", + "resolved": "8.0.6", + "contentHash": "Je2l+rd5i8gB+ZWsN5wBHOsnyAh81h6+a5vNq6rjfQhM2ZYxH+BVsmanCYa+F8BFy6rmd+ZL61SEiNaAyAOgtg==", "dependencies": { - "Microsoft.AspNetCore.Authorization": "8.0.3", - "Microsoft.AspNetCore.Components.Analyzers": "8.0.3" + "Microsoft.AspNetCore.Authorization": "8.0.6", + "Microsoft.AspNetCore.Components.Analyzers": "8.0.6" } }, "Microsoft.AspNetCore.Components.Analyzers": { "type": "Transitive", - "resolved": "8.0.3", - "contentHash": "iERLuYM+YFI/K1jkinr1YeAkJYHUcijPiPCKgmgs2ZhJLqiIVJRT08vUtIsfhiFtGiI5MIzK0R1BZHyS3yAQng==" + "resolved": "8.0.6", + "contentHash": "SEL0CN1jJdJkCDwRox3kSY1ffMnahlOCDJZYrYWfQ6ftjqRuuiPtwyvI3VIeVHLcpT3VP1AXww8wzKDK3oeFxg==" }, "Microsoft.AspNetCore.Components.Forms": { "type": "Transitive", - "resolved": "8.0.3", - "contentHash": "OxY5NDmePnn6FMb+Fum57YL7LCHk3u2Wg0qSln3uZSayo+oIxYuoGnqH2dUMp1P5vOPfq17NKCIIEbxfU2dirQ==", + "resolved": "8.0.6", + "contentHash": "49wIE1ns3ZGDU4NPMcKCSTC716IxujUeaynsUyflM5Qmb2WlF6M6m4pMcJ6UET1Ixmn027nZjMEc8J7pU4BLBg==", "dependencies": { - "Microsoft.AspNetCore.Components": "8.0.3" + "Microsoft.AspNetCore.Components": "8.0.6" } }, "Microsoft.AspNetCore.Components.Web": { "type": "Transitive", - "resolved": "8.0.3", - "contentHash": "bHWJiz/JhjptK3iYzha0Rm73chjFcbMAOD9DdDq2tn1rp4rQa/K7O/zdnZpSYAT3nI33Q0aY6ts6t0PUVu5hCA==", + "resolved": "8.0.6", + "contentHash": "xxYlTpcTEWsxaWUscDLN32mM32ysslLFtNQBS6wJOxaKJ9LCvusXDyBVEKL2DPbB8PZdereNvyrVr0deHkuOEw==", "dependencies": { - "Microsoft.AspNetCore.Components": "8.0.3", - "Microsoft.AspNetCore.Components.Forms": "8.0.3", + "Microsoft.AspNetCore.Components": "8.0.6", + "Microsoft.AspNetCore.Components.Forms": "8.0.6", "Microsoft.Extensions.DependencyInjection": "8.0.0", "Microsoft.Extensions.Primitives": "8.0.0", - "Microsoft.JSInterop": "8.0.3", + "Microsoft.JSInterop": "8.0.6", "System.IO.Pipelines": "8.0.0" } }, "Microsoft.AspNetCore.Metadata": { "type": "Transitive", - "resolved": "8.0.3", - "contentHash": "MAdmICjtSckGDutLRMydRI0pvBcGw/WoC4UC+hZ999idVW96l5iJlhyrtakgYkF5Rp0ekNVNWA+onP2gJZUkpw==" + "resolved": "8.0.6", + "contentHash": "3e7S/kz1MGds8zDA8SfQiutqifyVcULs5P/8Bxpes0WIkJRMGkU/l+XlMllj9KrDfCGwHW8bgjRy/zxfoILgfg==" }, "Microsoft.Extensions.DependencyInjection": { "type": "Transitive", @@ -116,19 +116,19 @@ }, "Microsoft.Extensions.Localization": { "type": "Transitive", - "resolved": "8.0.3", - "contentHash": "EjHnIiEwNq9xl8S36hf0nj64IF3DTQ1l5PVK8Vo+QocYKDKpDPONHNJC8env0DPwod7T5oA1HYLLo2mdSTCgrQ==", + "resolved": "8.0.6", + "contentHash": "EXcSpQE6E80Qutej0ZShz1oRWBFocDzir/R3Gd1jAqZ5SnPpSr1Ep/tH5ha0cRXY22cWVuOb7I9rM32Ew+ju7g==", "dependencies": { "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.1", - "Microsoft.Extensions.Localization.Abstractions": "8.0.3", + "Microsoft.Extensions.Localization.Abstractions": "8.0.6", "Microsoft.Extensions.Logging.Abstractions": "8.0.1", "Microsoft.Extensions.Options": "8.0.2" } }, "Microsoft.Extensions.Localization.Abstractions": { "type": "Transitive", - "resolved": "8.0.3", - "contentHash": "k/kUPm1FQBxcs9/vsM1eF4qIOg2Sovqh/+KUGHur5Mc0Y3OFGuoz9ktBX7LA0gPz53SZhW3W3oaSaMFFcjgM6Q==" + "resolved": "8.0.6", + "contentHash": "oQdKQ4xlb+Qa4t1gWGj58cocLdWZynP+wLExIAxozh2SrvffEzTvTGI2IbRx4mBNgg9jbbyoPE8nNOwJ1Thddg==" }, "Microsoft.Extensions.Logging.Abstractions": { "type": "Transitive", @@ -154,8 +154,8 @@ }, "Microsoft.JSInterop": { "type": "Transitive", - "resolved": "8.0.3", - "contentHash": "Oi21Fa7KubCzafwXb2IOdSGg24+/ylYGwrJgAYdWmgXBj04Oj/1b8vr9hrcoFKjQ6K18ryHYh35ZO/CCIEhuzg==" + "resolved": "8.0.6", + "contentHash": "E1djWS3d41fcd++7sGlbYhOHde5Pb0oBpOcNvUbn+1ga/yCvsjzUfbd/tDRg1qacNKS0iwKWYOIqTZxJnh99dQ==" }, "System.IO.Pipelines": { "type": "Transitive", @@ -163,6 +163,6 @@ "contentHash": "FHNOatmUq0sqJOkTx+UF/9YK1f180cnW5FVqnQMvYUN0elp6wFzbtPSiqbo1/ru8ICp43JM1i7kKkk6GsNGHlA==" } }, - "net8.0/osx-x64": {} + "net8.0/osx-arm64": {} } } \ No newline at end of file