From ab8320ced203de50441e7419793b2a5fe3b96e14 Mon Sep 17 00:00:00 2001 From: Jordan Fiset Date: Mon, 23 Sep 2024 22:52:04 -0400 Subject: [PATCH 01/13] Added ProjectProviderService and ProjectToolbar - Moved the toolbar into its own component. - Added a project provider singleton which keep track of the current project. --- .../Components/ProjectToolbar.razor | 84 +++++++++++++++++++ src/NodeDev.Blazor/Index.razor | 63 +++----------- .../Services/ProjectProviderService.cs | 24 ++++++ .../Services/ServicesExtension.cs | 7 +- src/NodeDev.sln | 4 +- 5 files changed, 125 insertions(+), 57 deletions(-) create mode 100644 src/NodeDev.Blazor/Components/ProjectToolbar.razor create mode 100644 src/NodeDev.Blazor/Services/ProjectProviderService.cs diff --git a/src/NodeDev.Blazor/Components/ProjectToolbar.razor b/src/NodeDev.Blazor/Components/ProjectToolbar.razor new file mode 100644 index 0000000..fe4b748 --- /dev/null +++ b/src/NodeDev.Blazor/Components/ProjectToolbar.razor @@ -0,0 +1,84 @@ +@using Microsoft.AspNetCore.Components.Forms +@using NodeDev.Blazor.Services +@using NodeDev.Core +@inject ProjectProviderService ProjectProviderService +@inject ISnackbar Snackbar + + + + Open Project + + +New Project +Save +Add node +Run +@(Project.IsLiveDebuggingEnabled ? "Stop Live Debugging" : "Start Live Debugging") + + + + +@code { + + private Project Project => ProjectProviderService.Project; + + [Parameter] + public EventCallback OnProjectChanged { get; set; } + + + private IBrowserFile? File; + private string? FileContent; + + + private async Task Open(IBrowserFile file) + { + File = file; + if (File != null) + { + using var stream = File.OpenReadStream(); + using var reader = new StreamReader(stream); + var json = await reader.ReadToEndAsync(); + + ProjectProviderService.Project = Core.Project.Deserialize(json); + + await OnProjectChanged.InvokeAsync(); + } + } + + private void Save() + { + // Until we have a proper save dialog, we just save the project to a file + string content = Project.Serialize(); + System.IO.File.WriteAllText("project.json", content); + + Snackbar.Add("Project saved", Severity.Success); + } + + private async Task NewProject() + { + ProjectProviderService.Project = Core.Project.CreateNewDefaultProject(); + + await OnProjectChanged.InvokeAsync(); + } + + private void Add() + { + //GraphCanvas?.ShowAddNode(); + } + + public void Run() + { + new Thread(() => + { + Project.Run(Project.IsLiveDebuggingEnabled ? Core.BuildOptions.Debug : Core.BuildOptions.Release); + }).Start(); + } + + private void SwitchLiveDebugging() + { + if (Project.IsLiveDebuggingEnabled) + Project.StopLiveDebugging(); + else + Project.StartLiveDebugging(); + } +} diff --git a/src/NodeDev.Blazor/Index.razor b/src/NodeDev.Blazor/Index.razor index ab0749e..d02c1d5 100644 --- a/src/NodeDev.Blazor/Index.razor +++ b/src/NodeDev.Blazor/Index.razor @@ -1,6 +1,8 @@ -@inject Services.DebuggedPathService DebuggedPathService +@using NodeDev.Blazor.Services +@inject Services.DebuggedPathService DebuggedPathService @inject NavigationManager NavigationManager @inject ISnackbar Snackbar +@inject ProjectProviderService ProjectProviderService @@ -9,13 +11,7 @@ - New Project - Save - Add node - Run - @(Project.IsLiveDebuggingEnabled ? "Stop Live Debugging" : "Start Live Debugging") - - + @@ -83,8 +79,7 @@ @code { - - private Core.Project Project { get; set; } = null!; + private Core.Project Project => ProjectProviderService.Project; private Core.Class.NodeClass? SelectedClass { get; set; } @@ -104,14 +99,16 @@ protected override void OnInitialized() { - if (File.Exists("project.json")) - Project = Core.Project.Deserialize(File.ReadAllText("project.json")); - else - Project = Core.Project.CreateNewDefaultProject(); DebuggedPathService.ChangeProject(Project); } + private void OnProjectChanged() + { + DebuggedPathService.ChangeProject(Project); + NavigationManager.Refresh(true); + } + private void SwitchSourceViewerGraph() { if (SourceViewerGraphPercentage <= SourceViewer_OpenedGraphPercentage) @@ -162,42 +159,4 @@ ActivePanelIndex = OpenedMethods.IndexOf(method); StateHasChanged(); } - - private void Save() - { - var content = Project.Serialize(); - File.WriteAllText("project.json", content); - - Snackbar.Add("Project saved", Severity.Success); - } - - private void NewProject() - { - if (File.Exists("project.json")) - File.Move("project.json", "project_backup.json", true); - - - NavigationManager.Refresh(true); - } - - private void Add() - { - //GraphCanvas?.ShowAddNode(); - } - - public void Run() - { - new Thread(() => - { - Project.Run(Project.IsLiveDebuggingEnabled ? Core.BuildOptions.Debug : Core.BuildOptions.Release); - }).Start(); - } - - private void SwitchLiveDebugging() - { - if (Project.IsLiveDebuggingEnabled) - Project.StopLiveDebugging(); - else - Project.StartLiveDebugging(); - } } \ No newline at end of file diff --git a/src/NodeDev.Blazor/Services/ProjectProviderService.cs b/src/NodeDev.Blazor/Services/ProjectProviderService.cs new file mode 100644 index 0000000..16e611f --- /dev/null +++ b/src/NodeDev.Blazor/Services/ProjectProviderService.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NodeDev.Blazor.Services +{ + internal class ProjectProviderService + { + private Core.Project _project; + + public Core.Project Project + { + get => _project; + set => _project = value; + } + + public ProjectProviderService() + { + _project = Core.Project.CreateNewDefaultProject(); + } + } +} diff --git a/src/NodeDev.Blazor/Services/ServicesExtension.cs b/src/NodeDev.Blazor/Services/ServicesExtension.cs index ed460ca..1b41eea 100644 --- a/src/NodeDev.Blazor/Services/ServicesExtension.cs +++ b/src/NodeDev.Blazor/Services/ServicesExtension.cs @@ -13,11 +13,12 @@ public static class ServicesExtension public static IServiceCollection AddNodeDev(this IServiceCollection services) { - services + services .AddMudServices() - .AddScoped(); + .AddScoped() + .AddSingleton(); - return services; + return services; } } diff --git a/src/NodeDev.sln b/src/NodeDev.sln index a5bd891..0aec5a2 100644 --- a/src/NodeDev.sln +++ b/src/NodeDev.sln @@ -27,9 +27,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blazor.Diagrams.Core", "Bla EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Dependencies", "Dependencies", "{F19EB03F-8DAD-4553-B7BA-863B6B2F155F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dis2Msil", "Dis2Msil\Dis2Msil\Dis2Msil.csproj", "{9873F12D-9C5B-4756-B31C-B514664638CE}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dis2Msil", "Dis2Msil\Dis2Msil\Dis2Msil.csproj", "{9873F12D-9C5B-4756-B31C-B514664638CE}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NodeDev.EndToEndTests", "NodeDev.EndToEndTests\NodeDev.EndToEndTests.csproj", "{DFA6D765-BFC3-407F-9330-B92B89310DCA}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NodeDev.EndToEndTests", "NodeDev.EndToEndTests\NodeDev.EndToEndTests.csproj", "{DFA6D765-BFC3-407F-9330-B92B89310DCA}" ProjectSection(ProjectDependencies) = postProject {A73FFB19-1791-4E6E-829C-A6B85E1BD8F2} = {A73FFB19-1791-4E6E-829C-A6B85E1BD8F2} EndProjectSection From 2ca620a08bcf666dd256297862ab79599a217d39 Mon Sep 17 00:00:00 2001 From: Jordan Fiset Date: Wed, 25 Sep 2024 21:09:46 -0400 Subject: [PATCH 02/13] Changed name and added a project changed notification. --- .../Components/ProjectToolbar.razor | 17 +++---- src/NodeDev.Blazor/Index.razor | 13 +++--- .../Services/ProjectProviderService.cs | 24 ---------- src/NodeDev.Blazor/Services/ProjectService.cs | 46 +++++++++++++++++++ .../Services/ServicesExtension.cs | 2 +- 5 files changed, 60 insertions(+), 42 deletions(-) delete mode 100644 src/NodeDev.Blazor/Services/ProjectProviderService.cs create mode 100644 src/NodeDev.Blazor/Services/ProjectService.cs diff --git a/src/NodeDev.Blazor/Components/ProjectToolbar.razor b/src/NodeDev.Blazor/Components/ProjectToolbar.razor index fe4b748..1f8ac2a 100644 --- a/src/NodeDev.Blazor/Components/ProjectToolbar.razor +++ b/src/NodeDev.Blazor/Components/ProjectToolbar.razor @@ -1,15 +1,15 @@ @using Microsoft.AspNetCore.Components.Forms @using NodeDev.Blazor.Services @using NodeDev.Core -@inject ProjectProviderService ProjectProviderService +@inject ProjectService ProjectService @inject ISnackbar Snackbar - Open Project + Open Project -New Project +New Project Save Add node Run @@ -20,26 +20,23 @@ @code { - private Project Project => ProjectProviderService.Project; + private Project Project => ProjectService.Project; [Parameter] public EventCallback OnProjectChanged { get; set; } - private IBrowserFile? File; - private string? FileContent; - private async Task Open(IBrowserFile file) { File = file; if (File != null) { - using var stream = File.OpenReadStream(); + using var stream = file.OpenReadStream(); using var reader = new StreamReader(stream); var json = await reader.ReadToEndAsync(); - ProjectProviderService.Project = Core.Project.Deserialize(json); + ProjectService.ChangeProject(Core.Project.Deserialize(json)); await OnProjectChanged.InvokeAsync(); } @@ -56,7 +53,7 @@ private async Task NewProject() { - ProjectProviderService.Project = Core.Project.CreateNewDefaultProject(); + ProjectService.ChangeProject(Core.Project.CreateNewDefaultProject()); await OnProjectChanged.InvokeAsync(); } diff --git a/src/NodeDev.Blazor/Index.razor b/src/NodeDev.Blazor/Index.razor index d02c1d5..d7ad2e6 100644 --- a/src/NodeDev.Blazor/Index.razor +++ b/src/NodeDev.Blazor/Index.razor @@ -2,7 +2,7 @@ @inject Services.DebuggedPathService DebuggedPathService @inject NavigationManager NavigationManager @inject ISnackbar Snackbar -@inject ProjectProviderService ProjectProviderService +@inject ProjectService ProjectService @@ -19,7 +19,7 @@ - + @if (SelectedClass != null) @@ -56,7 +56,7 @@ - + @@ -79,7 +79,6 @@ @code { - private Core.Project Project => ProjectProviderService.Project; private Core.Class.NodeClass? SelectedClass { get; set; } @@ -100,12 +99,12 @@ protected override void OnInitialized() { - DebuggedPathService.ChangeProject(Project); + DebuggedPathService.ChangeProject(ProjectService.Project); } private void OnProjectChanged() { - DebuggedPathService.ChangeProject(Project); + DebuggedPathService.ChangeProject(ProjectService.Project); NavigationManager.Refresh(true); } @@ -140,7 +139,7 @@ if (method == null) { // Find the main method - var program = Project.Classes.FirstOrDefault(x => x.Name == "Program"); + var program = ProjectService.Project.Classes.FirstOrDefault(x => x.Name == "Program"); // Find the main method in the program class method = program?.Methods.FirstOrDefault(x => x.Name == "Main"); diff --git a/src/NodeDev.Blazor/Services/ProjectProviderService.cs b/src/NodeDev.Blazor/Services/ProjectProviderService.cs deleted file mode 100644 index 16e611f..0000000 --- a/src/NodeDev.Blazor/Services/ProjectProviderService.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace NodeDev.Blazor.Services -{ - internal class ProjectProviderService - { - private Core.Project _project; - - public Core.Project Project - { - get => _project; - set => _project = value; - } - - public ProjectProviderService() - { - _project = Core.Project.CreateNewDefaultProject(); - } - } -} diff --git a/src/NodeDev.Blazor/Services/ProjectService.cs b/src/NodeDev.Blazor/Services/ProjectService.cs new file mode 100644 index 0000000..b43aa1c --- /dev/null +++ b/src/NodeDev.Blazor/Services/ProjectService.cs @@ -0,0 +1,46 @@ +using NodeDev.Core; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NodeDev.Blazor.Services +{ + /// + /// Service used to keep a singleton of the project throughout the application. + /// + internal class ProjectService + { + private Project _project; + + public Project Project + { + get => _project; + } + + public delegate void ProjectChangedHandler(); + /// + /// Event used to notify subscribers when the current project has changed. + /// + public event ProjectChangedHandler? ProjectChanged; + + /// + /// Instanciates a default project as the current project. + /// + public ProjectService() + { + _project = Project.CreateNewDefaultProject(); + } + + /// + /// Changes the current project and notifies all subscribers of that the project has changed. + /// + /// + public void ChangeProject(Project project) + { + _project = project; + ProjectChanged?.Invoke(); + } + } +} diff --git a/src/NodeDev.Blazor/Services/ServicesExtension.cs b/src/NodeDev.Blazor/Services/ServicesExtension.cs index 1b41eea..059484e 100644 --- a/src/NodeDev.Blazor/Services/ServicesExtension.cs +++ b/src/NodeDev.Blazor/Services/ServicesExtension.cs @@ -16,7 +16,7 @@ public static IServiceCollection AddNodeDev(this IServiceCollection services) services .AddMudServices() .AddScoped() - .AddSingleton(); + .AddSingleton(); return services; } From 71a31409579b8224b4c37ebf64c3ff4b4d131571 Mon Sep 17 00:00:00 2001 From: Jordan Fiset Date: Thu, 26 Sep 2024 20:37:26 -0400 Subject: [PATCH 03/13] Added tests for ProjectService --- src/Blazor.Diagrams | 2 +- src/NodeDev.Blazor/Services/ProjectService.cs | 2 +- src/NodeDev.Tests/ProjectServiceTest.cs | 38 +++++++++++++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 src/NodeDev.Tests/ProjectServiceTest.cs diff --git a/src/Blazor.Diagrams b/src/Blazor.Diagrams index 88224f9..b67372c 160000 --- a/src/Blazor.Diagrams +++ b/src/Blazor.Diagrams @@ -1 +1 @@ -Subproject commit 88224f96d67d2faa9088068e5acc57db53365a28 +Subproject commit b67372cc530d6ae3612b82b70076d4c075c265a8 diff --git a/src/NodeDev.Blazor/Services/ProjectService.cs b/src/NodeDev.Blazor/Services/ProjectService.cs index b43aa1c..e7c7ae2 100644 --- a/src/NodeDev.Blazor/Services/ProjectService.cs +++ b/src/NodeDev.Blazor/Services/ProjectService.cs @@ -10,7 +10,7 @@ namespace NodeDev.Blazor.Services /// /// Service used to keep a singleton of the project throughout the application. /// - internal class ProjectService + public class ProjectService { private Project _project; diff --git a/src/NodeDev.Tests/ProjectServiceTest.cs b/src/NodeDev.Tests/ProjectServiceTest.cs new file mode 100644 index 0000000..15c191f --- /dev/null +++ b/src/NodeDev.Tests/ProjectServiceTest.cs @@ -0,0 +1,38 @@ +using NodeDev.Core; +using NodeDev.Blazor.Services; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using NodeDev.Core.Class; + +namespace NodeDev.Tests; + +public class ProjectServiceTest +{ + [Fact] + public void TestsChangeProject() + { + var project = new Project(Guid.NewGuid()); + var projectService = new ProjectService(); + + projectService.ChangeProject(project); + + Assert.Equal(project, projectService.Project); + } + + [Fact] + public void TestsProjectChangedEvent() + { + var project = new Project(Guid.NewGuid()); + var projectService = new ProjectService(); + bool isEventTriggered = false; + + projectService.ProjectChanged += () => isEventTriggered = true; + projectService.ChangeProject(project); + + Assert.True(isEventTriggered); + } +} + From c5476098e29f484f42ab46590eeb64e0bc9f7c2d Mon Sep 17 00:00:00 2001 From: Jordan Fiset Date: Thu, 26 Sep 2024 20:56:09 -0400 Subject: [PATCH 04/13] CI update for .net9 --- .github/workflows/dotnet.yml | 6 +++--- .gitignore | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 0dd8a9b..9468742 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -22,7 +22,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v4 with: - dotnet-version: 8.0.x + dotnet-version: 9.0.x - name: Restore .NET dependencies working-directory: ./src @@ -48,7 +48,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v4 with: - dotnet-version: 8.0.x + dotnet-version: 9.0.x - uses: actions/download-artifact@v4 with: @@ -68,7 +68,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v4 with: - dotnet-version: 8.0.x + dotnet-version: 9.0.x - uses: actions/download-artifact@master with: diff --git a/.gitignore b/.gitignore index 59589dc..a52639e 100644 --- a/.gitignore +++ b/.gitignore @@ -26,5 +26,6 @@ /src/NodeDev.Core.Types.Tests/obj /src/NodeDev.Core.Types/bin /src/NodeDev.EndToEndTests/bin/Debug/net8.0 +/src/NodeDev.EndToEndTests/bin/Release/net8.0 /src/NodeDev.EndToEndTests/obj /src/NodeDev.Blazor.Server/project_backup.json \ No newline at end of file From a6f4c85ed9ea242ee69acd58efd3e64837f55940 Mon Sep 17 00:00:00 2001 From: snakex64 Date: Thu, 26 Sep 2024 21:20:39 -0400 Subject: [PATCH 05/13] Update Dis2Msil submodule version to support .net 8 --- src/Dis2Msil | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Dis2Msil b/src/Dis2Msil index 59810e6..c6882fd 160000 --- a/src/Dis2Msil +++ b/src/Dis2Msil @@ -1 +1 @@ -Subproject commit 59810e63804bf7d7aad523248dbd17398f36ca6b +Subproject commit c6882fdbe501a905abd66b88412291dc3de5e55b From 46f8ed21cc245d958bca3c0252680dd1a9d8eb49 Mon Sep 17 00:00:00 2001 From: JordanFiset <162237862+JordanFiset@users.noreply.github.com> Date: Fri, 27 Sep 2024 07:36:06 -0400 Subject: [PATCH 06/13] Apply suggestions from code review Co-authored-by: snakex64 <39806655+snakex64@users.noreply.github.com> --- src/NodeDev.Blazor/Components/ProjectToolbar.razor | 4 ++-- src/NodeDev.Blazor/Index.razor | 1 - src/NodeDev.Blazor/Services/ProjectService.cs | 11 +++-------- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/NodeDev.Blazor/Components/ProjectToolbar.razor b/src/NodeDev.Blazor/Components/ProjectToolbar.razor index 1f8ac2a..5fada8d 100644 --- a/src/NodeDev.Blazor/Components/ProjectToolbar.razor +++ b/src/NodeDev.Blazor/Components/ProjectToolbar.razor @@ -32,8 +32,8 @@ File = file; if (File != null) { - using var stream = file.OpenReadStream(); - using var reader = new StreamReader(stream); + await using var stream = file.OpenReadStream(); + await using var reader = new StreamReader(stream); var json = await reader.ReadToEndAsync(); ProjectService.ChangeProject(Core.Project.Deserialize(json)); diff --git a/src/NodeDev.Blazor/Index.razor b/src/NodeDev.Blazor/Index.razor index d7ad2e6..6711ece 100644 --- a/src/NodeDev.Blazor/Index.razor +++ b/src/NodeDev.Blazor/Index.razor @@ -98,7 +98,6 @@ protected override void OnInitialized() { - DebuggedPathService.ChangeProject(ProjectService.Project); } diff --git a/src/NodeDev.Blazor/Services/ProjectService.cs b/src/NodeDev.Blazor/Services/ProjectService.cs index e7c7ae2..99fef6e 100644 --- a/src/NodeDev.Blazor/Services/ProjectService.cs +++ b/src/NodeDev.Blazor/Services/ProjectService.cs @@ -12,12 +12,7 @@ namespace NodeDev.Blazor.Services /// public class ProjectService { - private Project _project; - - public Project Project - { - get => _project; - } + public Project Project { get; private set; } public delegate void ProjectChangedHandler(); /// @@ -30,7 +25,7 @@ public Project Project /// public ProjectService() { - _project = Project.CreateNewDefaultProject(); + Project = Project.CreateNewDefaultProject(); } /// @@ -39,7 +34,7 @@ public ProjectService() /// public void ChangeProject(Project project) { - _project = project; + Project = project; ProjectChanged?.Invoke(); } } From 4e522a0831562a9f9852f8ff49d4823308d552c9 Mon Sep 17 00:00:00 2001 From: JordanFiset <162237862+JordanFiset@users.noreply.github.com> Date: Fri, 27 Sep 2024 07:37:31 -0400 Subject: [PATCH 07/13] Removed File field --- .../Components/ProjectToolbar.razor | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/NodeDev.Blazor/Components/ProjectToolbar.razor b/src/NodeDev.Blazor/Components/ProjectToolbar.razor index 5fada8d..aaf8987 100644 --- a/src/NodeDev.Blazor/Components/ProjectToolbar.razor +++ b/src/NodeDev.Blazor/Components/ProjectToolbar.razor @@ -25,21 +25,15 @@ [Parameter] public EventCallback OnProjectChanged { get; set; } - private IBrowserFile? File; - private async Task Open(IBrowserFile file) { - File = file; - if (File != null) - { - await using var stream = file.OpenReadStream(); - await using var reader = new StreamReader(stream); - var json = await reader.ReadToEndAsync(); + await using var stream = file.OpenReadStream(); + await using var reader = new StreamReader(stream); + var json = await reader.ReadToEndAsync(); - ProjectService.ChangeProject(Core.Project.Deserialize(json)); + ProjectService.ChangeProject(Core.Project.Deserialize(json)); - await OnProjectChanged.InvokeAsync(); - } + await OnProjectChanged.InvokeAsync(); } private void Save() From 1121693652f60c171dcfb13c1e07e9cc9a1a3a75 Mon Sep 17 00:00:00 2001 From: Jordan Fiset Date: Fri, 27 Sep 2024 08:18:39 -0400 Subject: [PATCH 08/13] Fixed issues and used the ProjectChanged event instead of the toolbar callback in inedx. StreamReader doesn't implement IDisposableAsync. --- src/Dis2Msil | 2 +- src/NodeDev.Blazor/Components/ProjectToolbar.razor | 11 ++--------- src/NodeDev.Blazor/Index.razor | 10 +++++++++- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/Dis2Msil b/src/Dis2Msil index c6882fd..59810e6 160000 --- a/src/Dis2Msil +++ b/src/Dis2Msil @@ -1 +1 @@ -Subproject commit c6882fdbe501a905abd66b88412291dc3de5e55b +Subproject commit 59810e63804bf7d7aad523248dbd17398f36ca6b diff --git a/src/NodeDev.Blazor/Components/ProjectToolbar.razor b/src/NodeDev.Blazor/Components/ProjectToolbar.razor index aaf8987..7eaa7ad 100644 --- a/src/NodeDev.Blazor/Components/ProjectToolbar.razor +++ b/src/NodeDev.Blazor/Components/ProjectToolbar.razor @@ -22,18 +22,13 @@ private Project Project => ProjectService.Project; - [Parameter] - public EventCallback OnProjectChanged { get; set; } - private async Task Open(IBrowserFile file) { await using var stream = file.OpenReadStream(); - await using var reader = new StreamReader(stream); + using var reader = new StreamReader(stream); var json = await reader.ReadToEndAsync(); ProjectService.ChangeProject(Core.Project.Deserialize(json)); - - await OnProjectChanged.InvokeAsync(); } private void Save() @@ -45,11 +40,9 @@ Snackbar.Add("Project saved", Severity.Success); } - private async Task NewProject() + private void NewProject() { ProjectService.ChangeProject(Core.Project.CreateNewDefaultProject()); - - await OnProjectChanged.InvokeAsync(); } private void Add() diff --git a/src/NodeDev.Blazor/Index.razor b/src/NodeDev.Blazor/Index.razor index 6711ece..7eac1f9 100644 --- a/src/NodeDev.Blazor/Index.razor +++ b/src/NodeDev.Blazor/Index.razor @@ -3,6 +3,7 @@ @inject NavigationManager NavigationManager @inject ISnackbar Snackbar @inject ProjectService ProjectService +@implements IDisposable @@ -11,7 +12,7 @@ - + @@ -98,6 +99,8 @@ protected override void OnInitialized() { + ProjectService.ProjectChanged += OnProjectChanged; + DebuggedPathService.ChangeProject(ProjectService.Project); } @@ -157,4 +160,9 @@ ActivePanelIndex = OpenedMethods.IndexOf(method); StateHasChanged(); } + + public void Dispose() + { + ProjectService.ProjectChanged -= OnProjectChanged; + } } \ No newline at end of file From 09ac20c2fe0a9928fdcef3af74431bcbdd9d9347 Mon Sep 17 00:00:00 2001 From: snakex64 Date: Sun, 29 Sep 2024 12:56:49 -0400 Subject: [PATCH 09/13] Added ViewportSize to fix e2e error --- src/NodeDev.EndToEndTests/Hooks/Hooks.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/NodeDev.EndToEndTests/Hooks/Hooks.cs b/src/NodeDev.EndToEndTests/Hooks/Hooks.cs index f7564c2..cadf193 100644 --- a/src/NodeDev.EndToEndTests/Hooks/Hooks.cs +++ b/src/NodeDev.EndToEndTests/Hooks/Hooks.cs @@ -84,10 +84,13 @@ public async Task RegisterSingleInstancePractitioner() //Initialise a browser - 'Chromium' can be changed to 'Firefox' or 'Webkit' var browser = await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions { - Headless = Environment.GetEnvironmentVariable("HEADLESS") == "true" // -> Use this option to be able to see your test running + Headless = Environment.GetEnvironmentVariable("HEADLESS") == "true", // -> Use this option to be able to see your test running }); //Setup a browser context - var context1 = await browser.NewContextAsync(); + var context1 = await browser.NewContextAsync(new() + { + ViewportSize = new() { Width = 1900, Height = 1000 } + }); //Initialise a page on the browser context. User = await context1.NewPageAsync(); From b77acb6238b8aae2e49f6ef6d152d59545e63f60 Mon Sep 17 00:00:00 2001 From: Jordan Fiset Date: Thu, 21 Nov 2024 20:08:11 -0500 Subject: [PATCH 10/13] Added an option container to save persistent configuration --- .gitignore | 3 +- src/NodeDev.Blazor/AppOptions.cs | 15 ++++++ src/NodeDev.Blazor/AppOptionsContainer.cs | 46 +++++++++++++++++++ .../Components/OptionsDialog.razor | 38 +++++++++++++++ .../Services/ServicesExtension.cs | 3 +- 5 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 src/NodeDev.Blazor/AppOptions.cs create mode 100644 src/NodeDev.Blazor/AppOptionsContainer.cs create mode 100644 src/NodeDev.Blazor/Components/OptionsDialog.razor diff --git a/.gitignore b/.gitignore index a52639e..bc4c702 100644 --- a/.gitignore +++ b/.gitignore @@ -28,4 +28,5 @@ /src/NodeDev.EndToEndTests/bin/Debug/net8.0 /src/NodeDev.EndToEndTests/bin/Release/net8.0 /src/NodeDev.EndToEndTests/obj -/src/NodeDev.Blazor.Server/project_backup.json \ No newline at end of file +/src/NodeDev.Blazor.Server/project_backup.json +/src/NodeDev.Blazor.Server/AppOptions.json diff --git a/src/NodeDev.Blazor/AppOptions.cs b/src/NodeDev.Blazor/AppOptions.cs new file mode 100644 index 0000000..313d5f8 --- /dev/null +++ b/src/NodeDev.Blazor/AppOptions.cs @@ -0,0 +1,15 @@ +using Microsoft.Extensions.Configuration; +using NodeDev.Core; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; + +namespace NodeDev.Blazor; + +public class AppOptions +{ + public string? ProjectsDirectory { get; set; } = null; +} diff --git a/src/NodeDev.Blazor/AppOptionsContainer.cs b/src/NodeDev.Blazor/AppOptionsContainer.cs new file mode 100644 index 0000000..d936433 --- /dev/null +++ b/src/NodeDev.Blazor/AppOptionsContainer.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; + +namespace NodeDev.Blazor; + +public class AppOptionsContainer +{ + private readonly string OptionsFileName; + + private AppOptions appOptions = new AppOptions(); + public AppOptions AppOptions + { + get => appOptions; + set + { + appOptions = value; + SaveOptions(); + } + } + + public AppOptionsContainer(string optionFileName) + { + OptionsFileName = optionFileName; + LoadOptions(); + } + + public void SaveOptions() + { + File.WriteAllText(OptionsFileName, JsonSerializer.Serialize(appOptions, new JsonSerializerOptions() + { + WriteIndented = true + })); + } + + public void LoadOptions() + { + if (File.Exists(OptionsFileName)) + { + appOptions = JsonSerializer.Deserialize(File.ReadAllText(OptionsFileName)) ?? new AppOptions(); + } + } +} diff --git a/src/NodeDev.Blazor/Components/OptionsDialog.razor b/src/NodeDev.Blazor/Components/OptionsDialog.razor new file mode 100644 index 0000000..03ec330 --- /dev/null +++ b/src/NodeDev.Blazor/Components/OptionsDialog.razor @@ -0,0 +1,38 @@ +@inject IDialogService DialogService +@inject AppOptionsContainer AppOptionsContainer + + + + Options + + + + + + Cancel + Ok + + + +@code { + [CascadingParameter] + private MudDialogInstance MudDialog { get; set; } = null!; + + private AppOptions AppOptions { get; set; } = null!; + + protected override void OnInitialized() + { + base.OnInitialized(); + + AppOptions = AppOptionsContainer.AppOptions; + } + + private void Accept() + { + AppOptionsContainer.AppOptions = AppOptions; + MudDialog.Close(); + } + + private void Close() => MudDialog.Close(); + +} \ No newline at end of file diff --git a/src/NodeDev.Blazor/Services/ServicesExtension.cs b/src/NodeDev.Blazor/Services/ServicesExtension.cs index 059484e..e19b677 100644 --- a/src/NodeDev.Blazor/Services/ServicesExtension.cs +++ b/src/NodeDev.Blazor/Services/ServicesExtension.cs @@ -16,7 +16,8 @@ public static IServiceCollection AddNodeDev(this IServiceCollection services) services .AddMudServices() .AddScoped() - .AddSingleton(); + .AddSingleton() + .AddSingleton(new AppOptionsContainer ("AppOptions.json")); return services; } From b13e570f26235cc766f237d6db1faa79c3bbfbe6 Mon Sep 17 00:00:00 2001 From: Jordan Fiset Date: Thu, 21 Nov 2024 20:11:01 -0500 Subject: [PATCH 11/13] Added dialogs to open and save project on disk. Instead of using the file upload, which uses Ibrowser file which doesn't gives the complete path of the file. --- src/Dis2Msil | 2 +- .../Components/OpenProjectDialog.razor | 85 +++++++++++++++++++ .../Components/ProjectToolbar.razor | 55 ++++++++---- .../Components/SaveAsProjectDialog.razor | 48 +++++++++++ src/NodeDev.Blazor/NodeDev.Blazor.csproj | 1 + src/NodeDev.Blazor/Services/ProjectService.cs | 26 +++++- src/NodeDev.Core/ProjectSettings.cs | 4 +- 7 files changed, 200 insertions(+), 21 deletions(-) create mode 100644 src/NodeDev.Blazor/Components/OpenProjectDialog.razor create mode 100644 src/NodeDev.Blazor/Components/SaveAsProjectDialog.razor diff --git a/src/Dis2Msil b/src/Dis2Msil index 59810e6..c6882fd 160000 --- a/src/Dis2Msil +++ b/src/Dis2Msil @@ -1 +1 @@ -Subproject commit 59810e63804bf7d7aad523248dbd17398f36ca6b +Subproject commit c6882fdbe501a905abd66b88412291dc3de5e55b diff --git a/src/NodeDev.Blazor/Components/OpenProjectDialog.razor b/src/NodeDev.Blazor/Components/OpenProjectDialog.razor new file mode 100644 index 0000000..bc5a39f --- /dev/null +++ b/src/NodeDev.Blazor/Components/OpenProjectDialog.razor @@ -0,0 +1,85 @@ +@using System.Text.Json +@using NodeDev.Blazor.Services +@using NodeDev.Core +@inject AppOptionsContainer AppOptionsContainer +@inject IDialogService DialogService +@inject ProjectService ProjectService +@inject ISnackbar Snackbar + + + + + + + @if (RecentProjects is not null) + { + @foreach (var item in RecentProjects) + { + + } + } + + + + + + Open + Cancel + + + +@code { + [CascadingParameter] + private MudDialogInstance MudDialog { get; set; } = null!; + + public string? ProjectName { get; set; } + public List RecentProjects { get; set; } = new List(); + + private void Close() => MudDialog.Close(DialogResult.Ok(true)); + + protected override void OnInitialized() + { + base.OnInitialized(); + RecentProjects = ListRecentProjects(); + } + + private List ListRecentProjects() + { + List recentProjects = new List(); + if (AppOptionsContainer.AppOptions.ProjectsDirectory is null) + { + return recentProjects; + } + if (!Directory.Exists(AppOptionsContainer.AppOptions.ProjectsDirectory)) + { + return recentProjects; + } + recentProjects = Directory.GetFiles(AppOptionsContainer.AppOptions.ProjectsDirectory, "*.ndproj").Select(x => Path.GetFileNameWithoutExtension(x)).ToList(); + return recentProjects; + } + + private async Task LoadProject() + { + if (string.IsNullOrWhiteSpace(ProjectName)) + { + return; + } + try + { + var projectPath = Path.Combine(AppOptionsContainer.AppOptions.ProjectsDirectory!, $"{ProjectName}.ndproj"); + await ProjectService.LoadProjectFromFileAsync(projectPath); + } + catch (Exception ex) + { + Snackbar.Configuration.VisibleStateDuration = 10000; + Snackbar.Configuration.PositionClass = Defaults.Classes.Position.TopCenter; + Snackbar.Add(ex.Message, Severity.Error); + } + MudDialog.Close(DialogResult.Ok(ProjectName)); + } + + private void SelectProject(string projectName) + { + ProjectName = projectName; + } +} diff --git a/src/NodeDev.Blazor/Components/ProjectToolbar.razor b/src/NodeDev.Blazor/Components/ProjectToolbar.razor index 7eaa7ad..f2fed10 100644 --- a/src/NodeDev.Blazor/Components/ProjectToolbar.razor +++ b/src/NodeDev.Blazor/Components/ProjectToolbar.razor @@ -3,18 +3,19 @@ @using NodeDev.Core @inject ProjectService ProjectService @inject ISnackbar Snackbar +@inject AppOptionsContainer AppOptionsContainer +@inject IDialogService DialogService - - - Open Project - - + +Open New Project -Save +Save +Save As Add node Run @(Project.IsLiveDebuggingEnabled ? "Stop Live Debugging" : "Start Live Debugging") +Options @@ -22,24 +23,39 @@ private Project Project => ProjectService.Project; - private async Task Open(IBrowserFile file) - { - await using var stream = file.OpenReadStream(); - using var reader = new StreamReader(stream); - var json = await reader.ReadToEndAsync(); + private DialogOptions DialogOptions => new DialogOptions { MaxWidth = MaxWidth.Medium, FullWidth = true }; - ProjectService.ChangeProject(Core.Project.Deserialize(json)); + private Task Open() + { + return DialogService.ShowAsync("Open Project", DialogOptions); } - private void Save() + private Task Save() { - // Until we have a proper save dialog, we just save the project to a file - string content = Project.Serialize(); - System.IO.File.WriteAllText("project.json", content); + if (string.IsNullOrWhiteSpace(Project.Settings.ProjectName)) + { + return SaveAs(); + } - Snackbar.Add("Project saved", Severity.Success); + var projectPath = Path.Combine(AppOptionsContainer.AppOptions.ProjectsDirectory!, $"{Project.Settings.ProjectName}.ndproj"); + try + { + ProjectService.SaveProjectToFile(projectPath); + Snackbar.Add("Project saved", Severity.Success); + } + catch (Exception ex) + { + Snackbar.Add(ex.Message, Severity.Error); + } + + return Task.CompletedTask; } + private Task SaveAs() + { + return DialogService.ShowAsync("Save As Project", DialogOptions); + } + private void NewProject() { ProjectService.ChangeProject(Core.Project.CreateNewDefaultProject()); @@ -65,4 +81,9 @@ else Project.StartLiveDebugging(); } + + private Task OpenOptionsDialogAsync() + { + return DialogService.ShowAsync("Options", DialogOptions); + } } diff --git a/src/NodeDev.Blazor/Components/SaveAsProjectDialog.razor b/src/NodeDev.Blazor/Components/SaveAsProjectDialog.razor new file mode 100644 index 0000000..3c9890d --- /dev/null +++ b/src/NodeDev.Blazor/Components/SaveAsProjectDialog.razor @@ -0,0 +1,48 @@ +@using System.Text.Json +@using NodeDev.Blazor.Services +@using NodeDev.Core +@inject AppOptionsContainer AppOptionsContainer +@inject IDialogService DialogService +@inject ProjectService ProjectService +@inject ISnackbar Snackbar + + + + + + + Save + Cancel + + + +@code { + [CascadingParameter] + private MudDialogInstance MudDialog { get; set; } = null!; + + public string? ProjectName { get; set; } + + private void Close() => MudDialog.Close(DialogResult.Ok(true)); + + protected override void OnInitialized() + { + base.OnInitialized(); + ProjectName = ProjectService.Project.Settings.ProjectName; + } + + private void SaveProject() + { + try + { + var projectPath = Path.Combine(AppOptionsContainer.AppOptions.ProjectsDirectory!, $"{ProjectName}.ndproj"); + ProjectService.SaveProjectToFile(projectPath); + Snackbar.Add("Project saved", Severity.Success); + MudDialog.Close(DialogResult.Ok(ProjectName)); + } + catch (Exception ex) + { + Snackbar.Add(ex.Message, Severity.Error); + } + } + +} diff --git a/src/NodeDev.Blazor/NodeDev.Blazor.csproj b/src/NodeDev.Blazor/NodeDev.Blazor.csproj index 9a54d6d..d051cc2 100644 --- a/src/NodeDev.Blazor/NodeDev.Blazor.csproj +++ b/src/NodeDev.Blazor/NodeDev.Blazor.csproj @@ -14,6 +14,7 @@ + diff --git a/src/NodeDev.Blazor/Services/ProjectService.cs b/src/NodeDev.Blazor/Services/ProjectService.cs index 99fef6e..f332e51 100644 --- a/src/NodeDev.Blazor/Services/ProjectService.cs +++ b/src/NodeDev.Blazor/Services/ProjectService.cs @@ -1,8 +1,10 @@ -using NodeDev.Core; +using MudBlazor; +using NodeDev.Core; using System; using System.Collections.Generic; using System.Linq; using System.Text; +using System.Text.Json; using System.Threading.Tasks; namespace NodeDev.Blazor.Services @@ -26,10 +28,11 @@ public class ProjectService public ProjectService() { Project = Project.CreateNewDefaultProject(); + } /// - /// Changes the current project and notifies all subscribers of that the project has changed. + /// Changes the current project and notifies all subscribers of . /// /// public void ChangeProject(Project project) @@ -37,5 +40,24 @@ public void ChangeProject(Project project) Project = project; ProjectChanged?.Invoke(); } + + public async Task LoadProjectFromFileAsync(string file) + { + ArgumentNullException.ThrowIfNullOrWhiteSpace(file); + + var json = await File.ReadAllTextAsync(file); + var project = Project.Deserialize(json); + project.Settings.ProjectName = Path.GetFileNameWithoutExtension(file); + ChangeProject(project); + } + + public void SaveProjectToFile(string file) + { + ArgumentNullException.ThrowIfNullOrWhiteSpace(file); + + string content = Project.Serialize(); + File.WriteAllText(file, content); + + } } } diff --git a/src/NodeDev.Core/ProjectSettings.cs b/src/NodeDev.Core/ProjectSettings.cs index 2f7dcc3..935c1a9 100644 --- a/src/NodeDev.Core/ProjectSettings.cs +++ b/src/NodeDev.Core/ProjectSettings.cs @@ -1,6 +1,8 @@ namespace NodeDev.Core; -public record class ProjectSettings() +public class ProjectSettings() { + public string ProjectName { get; set; } = string.Empty; public static ProjectSettings Default { get; } = new(); + } From f5aff0361bb357b894df1d706c6228d72f501cca Mon Sep 17 00:00:00 2001 From: Jordan Fiset Date: Thu, 21 Nov 2024 22:02:54 -0500 Subject: [PATCH 12/13] Fixes after review --- src/NodeDev.Blazor.Server/Program.cs | 6 +- src/NodeDev.Blazor/AppOptions.cs | 15 --- src/NodeDev.Blazor/AppOptionsContainer.cs | 46 ------- .../Components/OpenProjectDialog.razor | 28 ++--- .../Components/OptionsDialog.razor | 8 +- .../Components/ProjectToolbar.razor | 3 +- .../Components/SaveAsProjectDialog.razor | 4 +- src/NodeDev.Blazor/Index.razor | 7 +- src/NodeDev.Blazor/Services/AppOptions.cs | 6 + .../Services/AppOptionsContainer.cs | 44 +++++++ src/NodeDev.Blazor/Services/ProjectService.cs | 113 +++++++++--------- .../Services/ServicesExtension.cs | 6 +- src/NodeDev.Core/ProjectSettings.cs | 6 +- src/NodeDev.Tests/ProjectServiceTest.cs | 46 ++++--- 14 files changed, 154 insertions(+), 184 deletions(-) delete mode 100644 src/NodeDev.Blazor/AppOptions.cs delete mode 100644 src/NodeDev.Blazor/AppOptionsContainer.cs create mode 100644 src/NodeDev.Blazor/Services/AppOptions.cs create mode 100644 src/NodeDev.Blazor/Services/AppOptionsContainer.cs diff --git a/src/NodeDev.Blazor.Server/Program.cs b/src/NodeDev.Blazor.Server/Program.cs index 6dc07cf..16895fc 100644 --- a/src/NodeDev.Blazor.Server/Program.cs +++ b/src/NodeDev.Blazor.Server/Program.cs @@ -14,9 +14,9 @@ // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { - app.UseExceptionHandler("/Error"); - // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. - app.UseHsts(); + app.UseExceptionHandler("/Error"); + // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. + app.UseHsts(); } app.UseAntiforgery(); diff --git a/src/NodeDev.Blazor/AppOptions.cs b/src/NodeDev.Blazor/AppOptions.cs deleted file mode 100644 index 313d5f8..0000000 --- a/src/NodeDev.Blazor/AppOptions.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Microsoft.Extensions.Configuration; -using NodeDev.Core; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Text.Json; -using System.Threading.Tasks; - -namespace NodeDev.Blazor; - -public class AppOptions -{ - public string? ProjectsDirectory { get; set; } = null; -} diff --git a/src/NodeDev.Blazor/AppOptionsContainer.cs b/src/NodeDev.Blazor/AppOptionsContainer.cs deleted file mode 100644 index d936433..0000000 --- a/src/NodeDev.Blazor/AppOptionsContainer.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Text.Json; -using System.Threading.Tasks; - -namespace NodeDev.Blazor; - -public class AppOptionsContainer -{ - private readonly string OptionsFileName; - - private AppOptions appOptions = new AppOptions(); - public AppOptions AppOptions - { - get => appOptions; - set - { - appOptions = value; - SaveOptions(); - } - } - - public AppOptionsContainer(string optionFileName) - { - OptionsFileName = optionFileName; - LoadOptions(); - } - - public void SaveOptions() - { - File.WriteAllText(OptionsFileName, JsonSerializer.Serialize(appOptions, new JsonSerializerOptions() - { - WriteIndented = true - })); - } - - public void LoadOptions() - { - if (File.Exists(OptionsFileName)) - { - appOptions = JsonSerializer.Deserialize(File.ReadAllText(OptionsFileName)) ?? new AppOptions(); - } - } -} diff --git a/src/NodeDev.Blazor/Components/OpenProjectDialog.razor b/src/NodeDev.Blazor/Components/OpenProjectDialog.razor index bc5a39f..05860dd 100644 --- a/src/NodeDev.Blazor/Components/OpenProjectDialog.razor +++ b/src/NodeDev.Blazor/Components/OpenProjectDialog.razor @@ -10,13 +10,10 @@ - - @if (RecentProjects is not null) + + @foreach (var item in RecentProjects) { - @foreach (var item in RecentProjects) - { - - } + } @@ -32,8 +29,8 @@ [CascadingParameter] private MudDialogInstance MudDialog { get; set; } = null!; - public string? ProjectName { get; set; } - public List RecentProjects { get; set; } = new List(); + private string? ProjectName { get; set; } + private List RecentProjects { get; set; } = new List(); private void Close() => MudDialog.Close(DialogResult.Ok(true)); @@ -45,17 +42,15 @@ private List ListRecentProjects() { - List recentProjects = new List(); if (AppOptionsContainer.AppOptions.ProjectsDirectory is null) { - return recentProjects; + return []; } if (!Directory.Exists(AppOptionsContainer.AppOptions.ProjectsDirectory)) { - return recentProjects; + return []; } - recentProjects = Directory.GetFiles(AppOptionsContainer.AppOptions.ProjectsDirectory, "*.ndproj").Select(x => Path.GetFileNameWithoutExtension(x)).ToList(); - return recentProjects; + return Directory.EnumerateFiles(AppOptionsContainer.AppOptions.ProjectsDirectory, "*.ndproj").Select(Path.GetFileNameWithoutExtension).ToList()!; } private async Task LoadProject() @@ -75,11 +70,6 @@ Snackbar.Configuration.PositionClass = Defaults.Classes.Position.TopCenter; Snackbar.Add(ex.Message, Severity.Error); } - MudDialog.Close(DialogResult.Ok(ProjectName)); - } - - private void SelectProject(string projectName) - { - ProjectName = projectName; + MudDialog.Close(DialogResult.Ok(true)); } } diff --git a/src/NodeDev.Blazor/Components/OptionsDialog.razor b/src/NodeDev.Blazor/Components/OptionsDialog.razor index 03ec330..d715562 100644 --- a/src/NodeDev.Blazor/Components/OptionsDialog.razor +++ b/src/NodeDev.Blazor/Components/OptionsDialog.razor @@ -1,5 +1,6 @@ -@inject IDialogService DialogService -@inject AppOptionsContainer AppOptionsContainer +@using NodeDev.Blazor.Services +@inject IDialogService DialogService +@inject Services.AppOptionsContainer AppOptionsContainer @@ -23,8 +24,7 @@ protected override void OnInitialized() { base.OnInitialized(); - - AppOptions = AppOptionsContainer.AppOptions; + AppOptions = AppOptionsContainer.AppOptions with { }; } private void Accept() diff --git a/src/NodeDev.Blazor/Components/ProjectToolbar.razor b/src/NodeDev.Blazor/Components/ProjectToolbar.razor index f2fed10..c2e720d 100644 --- a/src/NodeDev.Blazor/Components/ProjectToolbar.razor +++ b/src/NodeDev.Blazor/Components/ProjectToolbar.razor @@ -37,10 +37,9 @@ return SaveAs(); } - var projectPath = Path.Combine(AppOptionsContainer.AppOptions.ProjectsDirectory!, $"{Project.Settings.ProjectName}.ndproj"); try { - ProjectService.SaveProjectToFile(projectPath); + ProjectService.SaveProjectToFile(); Snackbar.Add("Project saved", Severity.Success); } catch (Exception ex) diff --git a/src/NodeDev.Blazor/Components/SaveAsProjectDialog.razor b/src/NodeDev.Blazor/Components/SaveAsProjectDialog.razor index 3c9890d..832ff82 100644 --- a/src/NodeDev.Blazor/Components/SaveAsProjectDialog.razor +++ b/src/NodeDev.Blazor/Components/SaveAsProjectDialog.razor @@ -34,8 +34,8 @@ { try { - var projectPath = Path.Combine(AppOptionsContainer.AppOptions.ProjectsDirectory!, $"{ProjectName}.ndproj"); - ProjectService.SaveProjectToFile(projectPath); + ProjectService.Project.Settings.ProjectName = ProjectName!; + ProjectService.SaveProjectToFile(); Snackbar.Add("Project saved", Severity.Success); MudDialog.Close(DialogResult.Ok(ProjectName)); } diff --git a/src/NodeDev.Blazor/Index.razor b/src/NodeDev.Blazor/Index.razor index e84e7f1..038194e 100644 --- a/src/NodeDev.Blazor/Index.razor +++ b/src/NodeDev.Blazor/Index.razor @@ -105,8 +105,11 @@ private void OnProjectChanged() { - DebuggedPathService.ChangeProject(ProjectService.Project); - NavigationManager.Refresh(true); + _ = InvokeAsync(() => + { + DebuggedPathService.ChangeProject(ProjectService.Project); + NavigationManager.Refresh(true); + }); } private void SwitchSourceViewerGraph() diff --git a/src/NodeDev.Blazor/Services/AppOptions.cs b/src/NodeDev.Blazor/Services/AppOptions.cs new file mode 100644 index 0000000..046ba50 --- /dev/null +++ b/src/NodeDev.Blazor/Services/AppOptions.cs @@ -0,0 +1,6 @@ +namespace NodeDev.Blazor.Services; + +public record class AppOptions +{ + public string ProjectsDirectory { get; set; } = string.Empty; +} diff --git a/src/NodeDev.Blazor/Services/AppOptionsContainer.cs b/src/NodeDev.Blazor/Services/AppOptionsContainer.cs new file mode 100644 index 0000000..426b514 --- /dev/null +++ b/src/NodeDev.Blazor/Services/AppOptionsContainer.cs @@ -0,0 +1,44 @@ +using System.Text.Json; + +namespace NodeDev.Blazor.Services; + +public class AppOptionsContainer +{ + private readonly string OptionsFileName; + + private AppOptions appOptions = new AppOptions(); + public AppOptions AppOptions + { + get => appOptions; + set + { + appOptions = value; + SaveOptions(); + } + } + + public AppOptionsContainer(string optionFileName) + { + OptionsFileName = optionFileName; + if (!string.IsNullOrWhiteSpace(OptionsFileName)) + { + LoadOptions(); + } + } + + public void SaveOptions() + { + File.WriteAllText(OptionsFileName, JsonSerializer.Serialize(appOptions, new JsonSerializerOptions() + { + WriteIndented = true + })); + } + + public void LoadOptions() + { + if (File.Exists(OptionsFileName)) + { + appOptions = JsonSerializer.Deserialize(File.ReadAllText(OptionsFileName)) ?? new AppOptions(); + } + } +} diff --git a/src/NodeDev.Blazor/Services/ProjectService.cs b/src/NodeDev.Blazor/Services/ProjectService.cs index f332e51..4bfa531 100644 --- a/src/NodeDev.Blazor/Services/ProjectService.cs +++ b/src/NodeDev.Blazor/Services/ProjectService.cs @@ -1,63 +1,58 @@ -using MudBlazor; -using NodeDev.Core; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Text.Json; -using System.Threading.Tasks; +using NodeDev.Core; namespace NodeDev.Blazor.Services { - /// - /// Service used to keep a singleton of the project throughout the application. - /// - public class ProjectService - { - public Project Project { get; private set; } - - public delegate void ProjectChangedHandler(); - /// - /// Event used to notify subscribers when the current project has changed. - /// - public event ProjectChangedHandler? ProjectChanged; - - /// - /// Instanciates a default project as the current project. - /// - public ProjectService() - { - Project = Project.CreateNewDefaultProject(); - - } - - /// - /// Changes the current project and notifies all subscribers of . - /// - /// - public void ChangeProject(Project project) - { - Project = project; - ProjectChanged?.Invoke(); - } - - public async Task LoadProjectFromFileAsync(string file) - { - ArgumentNullException.ThrowIfNullOrWhiteSpace(file); - - var json = await File.ReadAllTextAsync(file); - var project = Project.Deserialize(json); - project.Settings.ProjectName = Path.GetFileNameWithoutExtension(file); - ChangeProject(project); - } - - public void SaveProjectToFile(string file) - { - ArgumentNullException.ThrowIfNullOrWhiteSpace(file); - - string content = Project.Serialize(); - File.WriteAllText(file, content); - - } - } + /// + /// Service used to keep a singleton of the project throughout the application. + /// + public class ProjectService + { + public Project Project { get; private set; } + + private readonly AppOptionsContainer AppOptionsContainer; + + public delegate void ProjectChangedHandler(); + /// + /// Event used to notify subscribers when the current project has changed. + /// + public event ProjectChangedHandler? ProjectChanged; + + /// + /// Instanciates a default project as the current project. + /// + public ProjectService(AppOptionsContainer appOptionsContainer) + { + Project = Project.CreateNewDefaultProject(); + AppOptionsContainer = appOptionsContainer; + } + + /// + /// Changes the current project and notifies all subscribers of . + /// + /// + public void ChangeProject(Project project) + { + Project = project; + ProjectChanged?.Invoke(); + } + + public async Task LoadProjectFromFileAsync(string file) + { + ArgumentNullException.ThrowIfNullOrWhiteSpace(file); + + var json = await File.ReadAllTextAsync(file); + var project = Project.Deserialize(json); + project.Settings.ProjectName = Path.GetFileNameWithoutExtension(file); + ChangeProject(project); + } + + public void SaveProjectToFile() + { + ArgumentNullException.ThrowIfNullOrWhiteSpace(Project.Settings.ProjectName); + var projectPath = Path.Combine(AppOptionsContainer.AppOptions.ProjectsDirectory!, $"{Project.Settings.ProjectName}.ndproj"); + string content = Project.Serialize(); + File.WriteAllText(projectPath, content); + + } + } } diff --git a/src/NodeDev.Blazor/Services/ServicesExtension.cs b/src/NodeDev.Blazor/Services/ServicesExtension.cs index 45b9a60..e08d725 100644 --- a/src/NodeDev.Blazor/Services/ServicesExtension.cs +++ b/src/NodeDev.Blazor/Services/ServicesExtension.cs @@ -8,13 +8,13 @@ public static class ServicesExtension public static IServiceCollection AddNodeDev(this IServiceCollection services) { - services + services .AddMudServices() .AddScoped() .AddSingleton() - .AddSingleton(new AppOptionsContainer ("AppOptions.json")); + .AddSingleton(new AppOptionsContainer("AppOptions.json")); - return services; + return services; } } diff --git a/src/NodeDev.Core/ProjectSettings.cs b/src/NodeDev.Core/ProjectSettings.cs index 1b8d34a..ce2c687 100644 --- a/src/NodeDev.Core/ProjectSettings.cs +++ b/src/NodeDev.Core/ProjectSettings.cs @@ -1,7 +1,7 @@ namespace NodeDev.Core; -public class ProjectSettings() +public record class ProjectSettings() { - public string ProjectName { get; set; } = string.Empty; - public static ProjectSettings Default { get; } = new(); + public string ProjectName { get; set; } = string.Empty; + public static ProjectSettings Default { get; } = new(); } diff --git a/src/NodeDev.Tests/ProjectServiceTest.cs b/src/NodeDev.Tests/ProjectServiceTest.cs index 15c191f..a9b46f0 100644 --- a/src/NodeDev.Tests/ProjectServiceTest.cs +++ b/src/NodeDev.Tests/ProjectServiceTest.cs @@ -1,38 +1,32 @@ -using NodeDev.Core; -using NodeDev.Blazor.Services; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using NodeDev.Core.Class; +using NodeDev.Blazor.Services; +using NodeDev.Core; namespace NodeDev.Tests; public class ProjectServiceTest { - [Fact] - public void TestsChangeProject() - { - var project = new Project(Guid.NewGuid()); - var projectService = new ProjectService(); + [Fact] + public void TestsChangeProject() + { + var project = new Project(Guid.NewGuid()); + var projectService = new ProjectService(new AppOptionsContainer("")); - projectService.ChangeProject(project); + projectService.ChangeProject(project); - Assert.Equal(project, projectService.Project); - } + Assert.Equal(project, projectService.Project); + } - [Fact] - public void TestsProjectChangedEvent() - { - var project = new Project(Guid.NewGuid()); - var projectService = new ProjectService(); - bool isEventTriggered = false; + [Fact] + public void TestsProjectChangedEvent() + { + var project = new Project(Guid.NewGuid()); + var projectService = new ProjectService(new AppOptionsContainer("")); + bool isEventTriggered = false; - projectService.ProjectChanged += () => isEventTriggered = true; - projectService.ChangeProject(project); + projectService.ProjectChanged += () => isEventTriggered = true; + projectService.ChangeProject(project); - Assert.True(isEventTriggered); - } + Assert.True(isEventTriggered); + } } From f41407bf73e6a3bc6fd43c7fd0d7055ac67f14e5 Mon Sep 17 00:00:00 2001 From: Jordan Fiset Date: Sat, 23 Nov 2024 15:39:50 -0500 Subject: [PATCH 13/13] Changed SaveProject e2e test to use the Save As button --- src/Blazor.Diagrams | 2 +- .../Components/OptionsDialog.razor | 6 +-- .../Components/ProjectToolbar.razor | 2 +- .../Components/SaveAsProjectDialog.razor | 6 +-- .../Features/SaveProject.feature | 2 +- .../Features/SaveProject.feature.cs | 2 +- src/NodeDev.EndToEndTests/Pages/HomePage.cs | 47 +++++++++++++++++-- .../MainPageStepDefinitions.cs | 17 +++++++ 8 files changed, 71 insertions(+), 13 deletions(-) diff --git a/src/Blazor.Diagrams b/src/Blazor.Diagrams index b67372c..d9c7b48 160000 --- a/src/Blazor.Diagrams +++ b/src/Blazor.Diagrams @@ -1 +1 @@ -Subproject commit b67372cc530d6ae3612b82b70076d4c075c265a8 +Subproject commit d9c7b48eaf20713b3859f15bed7a7cbb0b242c04 diff --git a/src/NodeDev.Blazor/Components/OptionsDialog.razor b/src/NodeDev.Blazor/Components/OptionsDialog.razor index d715562..66314c8 100644 --- a/src/NodeDev.Blazor/Components/OptionsDialog.razor +++ b/src/NodeDev.Blazor/Components/OptionsDialog.razor @@ -7,11 +7,11 @@ Options - + - Cancel - Ok + Cancel + Ok diff --git a/src/NodeDev.Blazor/Components/ProjectToolbar.razor b/src/NodeDev.Blazor/Components/ProjectToolbar.razor index c2e720d..76b5c4d 100644 --- a/src/NodeDev.Blazor/Components/ProjectToolbar.razor +++ b/src/NodeDev.Blazor/Components/ProjectToolbar.razor @@ -15,7 +15,7 @@ Run @(Project.IsLiveDebuggingEnabled ? "Stop Live Debugging" : "Start Live Debugging") -Options +Options diff --git a/src/NodeDev.Blazor/Components/SaveAsProjectDialog.razor b/src/NodeDev.Blazor/Components/SaveAsProjectDialog.razor index 832ff82..70de910 100644 --- a/src/NodeDev.Blazor/Components/SaveAsProjectDialog.razor +++ b/src/NodeDev.Blazor/Components/SaveAsProjectDialog.razor @@ -8,11 +8,11 @@ - + - Save - Cancel + Save + Cancel diff --git a/src/NodeDev.EndToEndTests/Features/SaveProject.feature b/src/NodeDev.EndToEndTests/Features/SaveProject.feature index be229fc..110d219 100644 --- a/src/NodeDev.EndToEndTests/Features/SaveProject.feature +++ b/src/NodeDev.EndToEndTests/Features/SaveProject.feature @@ -4,5 +4,5 @@ Scenario: Save empty project Given I load the default project Then The 'Main' method in the 'Program' class should exist - Given I save the current project + Given I save the current project as 'EmptyProject' Then Snackbar should contain 'Project saved' \ No newline at end of file diff --git a/src/NodeDev.EndToEndTests/Features/SaveProject.feature.cs b/src/NodeDev.EndToEndTests/Features/SaveProject.feature.cs index 916f927..b2aa478 100644 --- a/src/NodeDev.EndToEndTests/Features/SaveProject.feature.cs +++ b/src/NodeDev.EndToEndTests/Features/SaveProject.feature.cs @@ -105,7 +105,7 @@ public async System.Threading.Tasks.Task SaveEmptyProject() await testRunner.ThenAsync("The \'Main\' method in the \'Program\' class should exist", ((string)(null)), ((global::Reqnroll.Table)(null)), "Then "); #line hidden #line 7 - await testRunner.GivenAsync("I save the current project", ((string)(null)), ((global::Reqnroll.Table)(null)), "Given "); + await testRunner.GivenAsync("I save the current project as \'EmptyProject\'", ((string)(null)), ((global::Reqnroll.Table)(null)), "Given "); #line hidden #line 8 await testRunner.ThenAsync("Snackbar should contain \'Project saved\'", ((string)(null)), ((global::Reqnroll.Table)(null)), "Then "); diff --git a/src/NodeDev.EndToEndTests/Pages/HomePage.cs b/src/NodeDev.EndToEndTests/Pages/HomePage.cs index a5f0801..bdb248c 100644 --- a/src/NodeDev.EndToEndTests/Pages/HomePage.cs +++ b/src/NodeDev.EndToEndTests/Pages/HomePage.cs @@ -18,6 +18,10 @@ public HomePage(Hooks.Hooks hooks) private ILocator SearchProjectExplorerTabsHeader => _user.Locator("[data-test-id='ProjectExplorerSection'] .mud-tabs-tabbar"); private ILocator SearchClassExplorer => _user.Locator("[data-test-id='classExplorer']"); private ILocator SearchSnackBarContainer => _user.Locator("#mud-snackbar-container"); + private ILocator SearchOptionsButton => SearchAppBar.Locator("[data-test-id='options']"); + private ILocator SearchSaveButton => SearchAppBar.Locator("[data-test-id='save']"); + private ILocator SearchSaveAsButton => SearchAppBar.Locator("[data-test-id='saveAs']"); + public async Task CreateNewProject() { @@ -69,11 +73,48 @@ public async Task HasMethodByName(string name) public async Task SaveProject() { - var saveBtn = SearchAppBar.Locator("[data-test-id='Save']"); + await SearchSaveButton.WaitForVisible(); + await SearchSaveButton.ClickAsync(); + } - await saveBtn.WaitForVisible(); + public async Task OpenOptionsDialog() + { + await SearchOptionsButton.WaitForVisible(); + await SearchOptionsButton.ClickAsync(); + } - await saveBtn.ClickAsync(); + public async Task SetProjectsDirectory(string directory) + { + var projectsDirectoryInput = _user.Locator("[data-test-id='optionsProjectDirectory']"); + await projectsDirectoryInput.WaitForVisible(); + await projectsDirectoryInput.FillAsync(directory); + } + + public async Task AcceptOptions() + { + var acceptButton = _user.Locator("[data-test-id='optionsAccept']"); + await acceptButton.WaitForVisible(); + await acceptButton.ClickAsync(); + } + + public async Task OpenSaveAsDialog() + { + await SearchSaveAsButton.WaitForVisible(); + await SearchSaveAsButton.ClickAsync(); + } + + public async Task SetProjectNameAs(string projectName) + { + var projectNameInput = _user.Locator("[data-test-id='saveAsProjectName']"); + await projectNameInput.WaitForVisible(); + await projectNameInput.FillAsync(projectName); + } + + public async Task AcceptSaveAs() + { + var saveButton = _user.Locator("[data-test-id='saveAsSave']"); + await saveButton.WaitForVisible(); + await saveButton.ClickAsync(); } public async Task SnackBarHasByText(string text) diff --git a/src/NodeDev.EndToEndTests/StepDefinitions/MainPageStepDefinitions.cs b/src/NodeDev.EndToEndTests/StepDefinitions/MainPageStepDefinitions.cs index 5258535..9099f7b 100644 --- a/src/NodeDev.EndToEndTests/StepDefinitions/MainPageStepDefinitions.cs +++ b/src/NodeDev.EndToEndTests/StepDefinitions/MainPageStepDefinitions.cs @@ -46,4 +46,21 @@ public async Task ThenSnackbarShouldContain(string text) { await HomePage.SnackBarHasByText(text); } + + [Given("I set the projects directory to {string}")] + public async Task GivenISetTheProjectsDirectoryTo(string directory) + { + await HomePage.OpenOptionsDialog(); + await HomePage.SetProjectsDirectory(directory); + await HomePage.AcceptOptions(); + } + + [Given("I save the current project as {string}")] + public async Task GivenISaveTheCurrentProjectAs(string projectName) + { + await HomePage.OpenSaveAsDialog(); + await HomePage.SetProjectNameAs(projectName); + await HomePage.AcceptSaveAs(); + } + }