diff --git a/.github/workflows/dotnetcore.pr.yml b/.github/workflows/dotnetcore.pr.yml index fb9e832f..c1a014ca 100644 --- a/.github/workflows/dotnetcore.pr.yml +++ b/.github/workflows/dotnetcore.pr.yml @@ -11,11 +11,16 @@ jobs: steps: - uses: actions/checkout@v1 - - name: Setup .NET Core + - name: Setup .NET uses: actions/setup-dotnet@v1 with: dotnet-version: '6.0.x' include-prerelease: true + - name: Setup .NET + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '8.0.x' + include-prerelease: true - name: Build Api Core run: dotnet build --configuration Release ./src/RapidCMS.Api.Core/RapidCMS.Api.Core.csproj - name: Build Api Functions @@ -24,15 +29,9 @@ jobs: run: dotnet build --configuration Release ./src/RapidCMS.Api.WebApi/RapidCMS.Api.WebApi.csproj - name: Build Core run: dotnet build --configuration Release ./src/RapidCMS.Core/RapidCMS.Core.csproj - - name: Build ModelMaker - run: dotnet build --configuration Release ./src/RapidCMS.ModelMaker/RapidCMS.ModelMaker.csproj - - name: Build ModelMaker SourceGenerator EFCore - run: dotnet build --configuration Release ./src/RapidCMS.ModelMaker.SourceGenerator.EFCore/RapidCMS.ModelMaker.SourceGenerator.EFCore.csproj - name: Build Repositories run: dotnet build --configuration Release ./src/RapidCMS.Repositories/RapidCMS.Repositories.csproj - name: Build UI run: dotnet build --configuration Release ./src/RapidCMS.UI/RapidCMS.UI.csproj - name: Run Core Tests run: dotnet test ./src/RapidCMS.Core.Tests/RapidCMS.Core.Tests.csproj - - name: Run Model Maker Tests - run: dotnet test ./src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests.csproj diff --git a/.github/workflows/dotnetcore.yml b/.github/workflows/dotnetcore.yml index 0ad97247..d34e0cba 100644 --- a/.github/workflows/dotnetcore.yml +++ b/.github/workflows/dotnetcore.yml @@ -14,11 +14,16 @@ jobs: - name: Get tag id: tag uses: dawidd6/action-get-tag@v1 - - name: Setup .NET Core + - name: Setup .NET uses: actions/setup-dotnet@v1 with: dotnet-version: '6.0.x' include-prerelease: true + - name: Setup .NET + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '8.0.x' + include-prerelease: true - uses: nuget/setup-nuget@v1 with: nuget-api-key: ${{ secrets.NUGET_APIKEY }} @@ -31,10 +36,6 @@ jobs: run: dotnet build -p:PackageVersion=${{steps.tag.outputs.tag}} --configuration Release ./src/RapidCMS.Api.WebApi/RapidCMS.Api.WebApi.csproj - name: Build Core run: dotnet build -p:PackageVersion=${{steps.tag.outputs.tag}} --configuration Release ./src/RapidCMS.Core/RapidCMS.Core.csproj - - name: Build ModelMaker - run: dotnet build -p:PackageVersion=${{steps.tag.outputs.tag}} --configuration Release ./src/RapidCMS.ModelMaker/RapidCMS.ModelMaker.csproj - - name: Build ModelMaker SourceGenerator EFCore - run: dotnet build -p:PackageVersion=${{steps.tag.outputs.tag}} --configuration Release ./src/RapidCMS.ModelMaker.SourceGenerator.EFCore/RapidCMS.ModelMaker.SourceGenerator.EFCore.csproj - name: Build Repositories run: dotnet build -p:PackageVersion=${{steps.tag.outputs.tag}} --configuration Release ./src/RapidCMS.Repositories/RapidCMS.Repositories.csproj - name: Build UI @@ -47,10 +48,6 @@ jobs: run: dotnet nuget push .\src\RapidCMS.Api.WebApi\bin\Release\*.nupkg -k ${{ secrets.NUGET_APIKEY }} -s https://api.nuget.org/v3/index.json --skip-duplicate - name: Publish Core run: dotnet nuget push .\src\RapidCMS.Core\bin\Release\*.nupkg -k ${{ secrets.NUGET_APIKEY }} -s https://api.nuget.org/v3/index.json --skip-duplicate - - name: Publish ModelMaker - run: dotnet nuget push .\src\RapidCMS.ModelMaker\bin\Release\*.nupkg -k ${{ secrets.NUGET_APIKEY }} -s https://api.nuget.org/v3/index.json --skip-duplicate - - name: Publish ModelMaker SourceGenerator EFCore - run: dotnet nuget push .\src\RapidCMS.ModelMaker.SourceGenerator.EFCore\bin\Release\*.nupkg -k ${{ secrets.NUGET_APIKEY }} -s https://api.nuget.org/v3/index.json --skip-duplicate - name: Publish Repositories run: dotnet nuget push .\src\RapidCMS.Repositories\bin\Release\*.nupkg -k ${{ secrets.NUGET_APIKEY }} -s https://api.nuget.org/v3/index.json --skip-duplicate - name: Publish UI diff --git a/README.md b/README.md index fcf4f1b6..ffba991e 100644 --- a/README.md +++ b/README.md @@ -38,18 +38,12 @@ Since RapidCMS can be used in various ways, please pick a deployment mode. And r - [Server-side RapidCMS](SETUP_SERVERSIDE.md) - requires an ASP.NET Core web server. - [Client-side RapidCMS](SETUP_CLIENTSIDE.md) - can be statically hosted. - [Companion API for client-side RapidCMS](SETUP_COMPANION.md) - requires an ASP.NET Core web server or Azure Function App. -- [MAUI RapidCMS](SETUP_MAUI.md). ### Authentication - [Add authentication to Server-side](AUTHserver.md) - [Add authentication to Client-side + Companion API](AUTHclient.md) -## How to setup RapidCMS Model Maker - -- [Plugin into server-side RapidCMS](SETUP_MMSERVERSIDE.md). -- [Plugin into client-side RapidCMS with Companion API](SETUP_MMCLIENTSIDE.md). - ## Quick starts - [RapidCMS](QUICKSTART.md) diff --git a/SETUP_MAUI.md b/SETUP_MAUI.md deleted file mode 100644 index d1e9f4fc..00000000 --- a/SETUP_MAUI.md +++ /dev/null @@ -1,9 +0,0 @@ -# Install RapidCMS MAUI - -1. Create new MAUI Blazor WebAssembly project. -2. Install NuGet-package: `RapidCMS.UI`. -3. Add `builder.Services.AddAuthorizationCore();` and `builder.Services.AddRapidCMSWebAssembly(config => { config.AllowAnonymousUser(); })` before `builder.Build()` of `CreateMauiApp` in `MauiProgram.cs`. -4. Replace the contents of `Main.razor` with ``. -5. Replace the `` tags in `index.html` with `` and remove any other css. Add `` at the end of the body tag. -6. Hit `F5`: you're now running a completely empty RapidCMS instance. -7. Start building your CMS by expanding `config => {}`. For reference, browse the [Examples](https://github.com/ThomasBleijendaal/RapidCMS/tree/master/examples) to see all the options. diff --git a/SETUP_MMCLIENTSIDE.md b/SETUP_MMCLIENTSIDE.md deleted file mode 100644 index e7c7c895..00000000 --- a/SETUP_MMCLIENTSIDE.md +++ /dev/null @@ -1,40 +0,0 @@ -# Install Model Maker in RapidCMS client-side - -Model Maker is currently not supported in RapidCMS client-side (WebAssembly), but the -generated models and repositories can easily be integrated in a client-side RapidCMS instance. - -1. Create a .NET 5.0 class library. -2. Install NuGet-package: `RapidCMS.ModelMaker`. -2. Install NuGet-package: `RapidCMS.ModelMaker.SourceGenerator.EFCore`. -3. Install NuGet-package: `Microsoft.EntityFrameworkCore.SqlServer`. -4. Install NuGet-package: `Microsoft.EntityFrameworkCore.Design`. -5. Install NuGet-package: `Microsoft.EntityFrameworkCore.Tools`. -6. [Create a RapidCMS server-side project](SETUP_SERVERSIDE.md) next to the class library. -7. Install NuGet-package: `RapidCMS.ModelMaker` in the RapidCMS server-side project. -8. Use `config.SetModelFolder` via `.AddModelMaker(configure: config => {})` to save the generated JSON files into the class library's RapidModels folder. -9. Run the Model Maker and create all appropriate models. -10. Make sure all JSON files inside the Model Folder are marked as "C# analyzer additional file". -11. Setup an `IDesignTimeDbContextFactory` in the class library to setup `ModelMakerDbContext` construction during design time (See below). -11. Generate and apply migrations to create database. -12. [Create a RapidCMS client-side project](SETUP_CLIENTSIDE.md) next to the class library. -13. [Create a RapidCMS API companion project](SETUP_COMPANION.md) next to the class library. -14. Add collections, validators and ApiRepositories for all models in the client-side project. -15. Add validators, repositories and DbContext for all models in the api companion project. -16. Add CORS settings so the WebAssembly app can access the API. -17. Run the client-side and companion project to use the generated code for Model Maker models. - -The [RapidCMS.Example.ModelMaker.WebAssembly](https://github.com/ThomasBleijendaal/RapidCMS/tree/master/examples/RapidCMS.Example.ModelMaker.WebAssembly) and [RapidCMS.Example.ModelMaker.WebAssembly.API](https://github.com/ThomasBleijendaal/RapidCMS/tree/master/examples/RapidCMS.Example.ModelMaker.WebAssembly.API) demonstrate this setup. - - -## Design-time DbContext factory - -```c# -public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory -{ - public ModelMakerDbContext CreateDbContext(string[] args) - => new ModelMakerDbContext( - new DbContextOptionsBuilder() - .UseSqlServer("{connection string}") - .Options); -} -``` \ No newline at end of file diff --git a/SETUP_MMSERVERSIDE.md b/SETUP_MMSERVERSIDE.md deleted file mode 100644 index 66df3dd4..00000000 --- a/SETUP_MMSERVERSIDE.md +++ /dev/null @@ -1,19 +0,0 @@ -# Install Model Maker in RapidCMS server-side - -1. [Create a RapidCMS server-side project](SETUP_SERVERSIDE.md). -2. Install NuGet-package: `RapidCMS.ModelMaker`. -3. Add `services.AddModelMaker()` before the `AddRapidCMSServer` call. -4. Add `config.AddModelMakerPlugin()` to `AddRapidCMSServer(config => {})`. -5. Hit `F5`: you're now running a RapidCMS instance with Model Maker plugin. -6. Start building your CMS by configuring collections. - -## Install Model Maker Entity Framework Generator - -1. Install NuGet-package: `RapidCMS.ModelMaker.SourceGenerator.EFCore`. -2. Install NuGet-package: `Microsoft.EntityFrameworkCore.SqlServer`. -3. Install NuGet-package: `Microsoft.EntityFrameworkCore.Tools`. -4. Make sure all Model Maker JSON files are marked as "C# analyzer additional file". -5. Look under Dependencies > Analyzers > RapidCMS.ModelMaker.SourceGenerator.EFCore to discover all the generated classes. -6. Add generated code to DI and RapidCMS config to finalize CMS. -7. Generate and apply migrations to create database. -8. Hit `F5`: you're now running a RapidCMS instance with generated collections and models. diff --git a/examples/RapidCMS.Example.Github/Attributes/BioValidationAttribute.cs b/examples/RapidCMS.Example.Github/Attributes/BioValidationAttribute.cs index 3c6b895b..1a17df9c 100644 --- a/examples/RapidCMS.Example.Github/Attributes/BioValidationAttribute.cs +++ b/examples/RapidCMS.Example.Github/Attributes/BioValidationAttribute.cs @@ -1,22 +1,21 @@ using System.ComponentModel.DataAnnotations; -namespace RapidCMS.Example.Github.Attributes +namespace RapidCMS.Example.Github.Attributes; + +internal class BioValidationAttribute : ValidationAttribute { - internal class BioValidationAttribute : ValidationAttribute - { - public override bool RequiresValidationContext => true; + public override bool RequiresValidationContext => true; - protected override ValidationResult IsValid(object? value, ValidationContext validationContext) + protected override ValidationResult IsValid(object? value, ValidationContext validationContext) + { + if (value is string bio) { - if (value is string bio) + if (bio.Contains("fdsa")) { - if (bio.Contains("fdsa")) - { - return new ValidationResult("Bio's cannot contain 'fdsa'.", validationContext.MemberName == null ? null : new[] { validationContext.MemberName }); - } + return new ValidationResult("Bio's cannot contain 'fdsa'.", validationContext.MemberName == null ? null : new[] { validationContext.MemberName }); } - - return ValidationResult.Success!; } + + return ValidationResult.Success!; } } diff --git a/examples/RapidCMS.Example.Github/DataViewBuilders/CountryDataViewBuilder.cs b/examples/RapidCMS.Example.Github/DataViewBuilders/CountryDataViewBuilder.cs index caa2ea5d..b9eff925 100644 --- a/examples/RapidCMS.Example.Github/DataViewBuilders/CountryDataViewBuilder.cs +++ b/examples/RapidCMS.Example.Github/DataViewBuilders/CountryDataViewBuilder.cs @@ -5,13 +5,12 @@ using RapidCMS.Core.Models.Data; using RapidCMS.Example.Github.Entities; -namespace RapidCMS.Example.Github.DataViewBuilders -{ - internal class CountryDataViewBuilder : DataViewBuilder - { - public override Task>> GetDataViewsAsync() - { - return Task.FromResult(Enumerable.Range(1, 10).Select(index => new DataView(index, $"{index}-letter country", x => x.Name != null && x.Name.Length == index))); - } +namespace RapidCMS.Example.Github.DataViewBuilders; + +internal class CountryDataViewBuilder : DataViewBuilder +{ + public override Task>> GetDataViewsAsync() + { + return Task.FromResult(Enumerable.Range(1, 10).Select(index => new DataView(index, $"{index}-letter country", x => x.Name != null && x.Name.Length == index))); } } diff --git a/examples/RapidCMS.Example.Github/Entities/ConventionPerson.cs b/examples/RapidCMS.Example.Github/Entities/ConventionPerson.cs index 74987d2e..75245e41 100644 --- a/examples/RapidCMS.Example.Github/Entities/ConventionPerson.cs +++ b/examples/RapidCMS.Example.Github/Entities/ConventionPerson.cs @@ -2,33 +2,32 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Attributes; -namespace RapidCMS.Example.Github.Entities +namespace RapidCMS.Example.Github.Entities; + +internal class ConventionPerson : IEntity, ICloneable { - internal class ConventionPerson : IEntity, ICloneable - { - public string? Id { get; set; } + public string? Id { get; set; } - [Field(Name = "Name", ListName = "Name")] - public string? Name { get; set; } + [Field(Name = "Name", ListName = "Name")] + public string? Name { get; set; } - [Field(Name = "Email")] - public string? Email { get; set; } + [Field(Name = "Email")] + public string? Email { get; set; } - [Field(Name = "Bio", Description = "If this field gets longer than 50, the summary on the ListView will get truncated.")] - public string? Bio { get; set; } + [Field(Name = "Bio", Description = "If this field gets longer than 50, the summary on the ListView will get truncated.")] + public string? Bio { get; set; } - [Field(ListName = "Bio summary")] - public string? ShortBio => Bio?.Substring(0, Math.Min(Bio?.Length ?? 0, 50)); + [Field(ListName = "Bio summary")] + public string? ShortBio => Bio?.Substring(0, Math.Min(Bio?.Length ?? 0, 50)); - public object Clone() + public object Clone() + { + return new ConventionPerson { - return new ConventionPerson - { - Bio = Bio, - Email = Email, - Id = Id, - Name = Name - }; - } + Bio = Bio, + Email = Email, + Id = Id, + Name = Name + }; } } diff --git a/examples/RapidCMS.Example.Github/Entities/Country.cs b/examples/RapidCMS.Example.Github/Entities/Country.cs index 234c09f8..98e8e289 100644 --- a/examples/RapidCMS.Example.Github/Entities/Country.cs +++ b/examples/RapidCMS.Example.Github/Entities/Country.cs @@ -1,20 +1,19 @@ using System; using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Example.Github.Entities +namespace RapidCMS.Example.Github.Entities; + +internal class Country : IEntity, ICloneable { - internal class Country : IEntity, ICloneable - { - public string? Id { get; set; } - public string? Name { get; set; } + public string? Id { get; set; } + public string? Name { get; set; } - public object Clone() + public object Clone() + { + return new Country { - return new Country - { - Id = Id, - Name = Name - }; - } + Id = Id, + Name = Name + }; } } diff --git a/examples/RapidCMS.Example.Github/Entities/CountryPerson.cs b/examples/RapidCMS.Example.Github/Entities/CountryPerson.cs index 6babe775..69799323 100644 --- a/examples/RapidCMS.Example.Github/Entities/CountryPerson.cs +++ b/examples/RapidCMS.Example.Github/Entities/CountryPerson.cs @@ -1,29 +1,28 @@ using System; using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Example.Github.Entities +namespace RapidCMS.Example.Github.Entities; + +internal class CountryPerson : IEntity, ICloneable { - internal class CountryPerson : IEntity, ICloneable - { - public string? Id { get; set; } - public string? Name { get; set; } - public string? Email { get; set; } - public string? Bio { get; set; } + public string? Id { get; set; } + public string? Name { get; set; } + public string? Email { get; set; } + public string? Bio { get; set; } - public string? FavouriteCountryId1 { get; set; } - public string? FavouriteCountryId2 { get; set; } + public string? FavouriteCountryId1 { get; set; } + public string? FavouriteCountryId2 { get; set; } - public object Clone() + public object Clone() + { + return new CountryPerson { - return new CountryPerson - { - Bio = Bio, - Email = Email, - Id = Id, - Name = Name, - FavouriteCountryId1 = FavouriteCountryId1, - FavouriteCountryId2 = FavouriteCountryId2 - }; - } + Bio = Bio, + Email = Email, + Id = Id, + Name = Name, + FavouriteCountryId1 = FavouriteCountryId1, + FavouriteCountryId2 = FavouriteCountryId2 + }; } } diff --git a/examples/RapidCMS.Example.Github/Entities/Person.cs b/examples/RapidCMS.Example.Github/Entities/Person.cs index 8eca2b00..328788e2 100644 --- a/examples/RapidCMS.Example.Github/Entities/Person.cs +++ b/examples/RapidCMS.Example.Github/Entities/Person.cs @@ -1,24 +1,23 @@ using System; using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Example.Github.Entities +namespace RapidCMS.Example.Github.Entities; + +internal class Person : IEntity, ICloneable { - internal class Person : IEntity, ICloneable - { - public string? Id { get; set; } - public string? Name { get; set; } - public string? Email { get; set; } - public string? Bio { get; set; } + public string? Id { get; set; } + public string? Name { get; set; } + public string? Email { get; set; } + public string? Bio { get; set; } - public object Clone() + public object Clone() + { + return new Person { - return new Person - { - Bio = Bio, - Email = Email, - Id = Id, - Name = Name - }; - } + Bio = Bio, + Email = Email, + Id = Id, + Name = Name + }; } } diff --git a/examples/RapidCMS.Example.Github/Entities/Relatable2Person.cs b/examples/RapidCMS.Example.Github/Entities/Relatable2Person.cs index 2a638a81..f658f67a 100644 --- a/examples/RapidCMS.Example.Github/Entities/Relatable2Person.cs +++ b/examples/RapidCMS.Example.Github/Entities/Relatable2Person.cs @@ -2,26 +2,25 @@ using System.Collections.Generic; using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Example.Github.Entities +namespace RapidCMS.Example.Github.Entities; + +internal class Relatable2Person : IEntity, ICloneable { - internal class Relatable2Person : IEntity, ICloneable - { - public string? Id { get; set; } - public string? Name { get; set; } - public string? Email { get; set; } - public string? Bio { get; set; } + public string? Id { get; set; } + public string? Name { get; set; } + public string? Email { get; set; } + public string? Bio { get; set; } - public List Countries { get; } = new List(); + public List Countries { get; } = new List(); - public object Clone() + public object Clone() + { + return new Relatable2Person { - return new Relatable2Person - { - Bio = Bio, - Email = Email, - Id = Id, - Name = Name - }; - } + Bio = Bio, + Email = Email, + Id = Id, + Name = Name + }; } } diff --git a/examples/RapidCMS.Example.Github/Entities/RelatablePerson.cs b/examples/RapidCMS.Example.Github/Entities/RelatablePerson.cs index a9ccfec4..a5a0c3f9 100644 --- a/examples/RapidCMS.Example.Github/Entities/RelatablePerson.cs +++ b/examples/RapidCMS.Example.Github/Entities/RelatablePerson.cs @@ -4,27 +4,26 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Extensions; -namespace RapidCMS.Example.Github.Entities +namespace RapidCMS.Example.Github.Entities; + +internal class RelatablePerson : IEntity, ICloneable { - internal class RelatablePerson : IEntity, ICloneable - { - public string? Id { get; set; } - public string? Name { get; set; } - public string? Email { get; set; } - public string? Bio { get; set; } + public string? Id { get; set; } + public string? Name { get; set; } + public string? Email { get; set; } + public string? Bio { get; set; } - public List Countries { get; set; } = new List(); + public List Countries { get; set; } = new List(); - public object Clone() + public object Clone() + { + return new RelatablePerson { - return new RelatablePerson - { - Bio = Bio, - Email = Email, - Id = Id, - Name = Name, - Countries = Countries.ToList(x => (Country)x.Clone()) - }; - } + Bio = Bio, + Email = Email, + Id = Id, + Name = Name, + Countries = Countries.ToList(x => (Country)x.Clone()) + }; } } diff --git a/examples/RapidCMS.Example.Github/Entities/ValidationPerson.cs b/examples/RapidCMS.Example.Github/Entities/ValidationPerson.cs index 0b6962ca..128f8a5f 100644 --- a/examples/RapidCMS.Example.Github/Entities/ValidationPerson.cs +++ b/examples/RapidCMS.Example.Github/Entities/ValidationPerson.cs @@ -3,33 +3,32 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Example.Github.Attributes; -namespace RapidCMS.Example.Github.Entities +namespace RapidCMS.Example.Github.Entities; + +internal class ValidationPerson : IEntity, ICloneable { - internal class ValidationPerson : IEntity, ICloneable - { - public string? Id { get; set; } + public string? Id { get; set; } - [Required] - [MinLength(10)] - public string? Name { get; set; } + [Required] + [MinLength(10)] + public string? Name { get; set; } - [EmailAddress] - [Required] - public string? Email { get; set; } + [EmailAddress] + [Required] + public string? Email { get; set; } - [Required] - [BioValidation] - public string? Bio { get; set; } + [Required] + [BioValidation] + public string? Bio { get; set; } - public object Clone() + public object Clone() + { + return new ValidationPerson { - return new ValidationPerson - { - Bio = Bio, - Email = Email, - Id = Id, - Name = Name - }; - } + Bio = Bio, + Email = Email, + Id = Id, + Name = Name + }; } } diff --git a/examples/RapidCMS.Example.Github/Program.cs b/examples/RapidCMS.Example.Github/Program.cs index 04616c23..fc7e2b2c 100644 --- a/examples/RapidCMS.Example.Github/Program.cs +++ b/examples/RapidCMS.Example.Github/Program.cs @@ -10,534 +10,533 @@ using RapidCMS.Example.Github.Entities; using RapidCMS.Repositories; -namespace RapidCMS.Example.Github +namespace RapidCMS.Example.Github; + +public class Program { - public class Program + public static async Task Main(string[] args) { - public static async Task Main(string[] args) - { - var builder = WebAssemblyHostBuilder.CreateDefault(args); - builder.RootComponents.Add("#app"); + var builder = WebAssemblyHostBuilder.CreateDefault(args); + builder.RootComponents.Add("#app"); - builder.Services.AddAuthorizationCore(); + builder.Services.AddAuthorizationCore(); - builder.Services.AddBlazoredLocalStorage(); - builder.Services.AddScoped>(); - builder.Services.AddScoped>(); - builder.Services.AddScoped>(); - builder.Services.AddScoped>(); - builder.Services.AddScoped>(); - builder.Services.AddScoped>(); - builder.Services.AddScoped>(); + builder.Services.AddBlazoredLocalStorage(); + builder.Services.AddScoped>(); + builder.Services.AddScoped>(); + builder.Services.AddScoped>(); + builder.Services.AddScoped>(); + builder.Services.AddScoped>(); + builder.Services.AddScoped>(); + builder.Services.AddScoped>(); - builder.Services.AddScoped(); - - builder.Services.AddRapidCMSWebAssembly(config => - { - config.AllowAnonymousUser(); + builder.Services.AddScoped(); - config.Dashboard.AddSection(typeof(Dashboard)); + builder.Services.AddRapidCMSWebAssembly(config => + { + config.AllowAnonymousUser(); - config.AddCollection>("person", "FabricUserFolder", "Red10", "Person", collection => - { - collection - .SetTreeView(x => x.Name) - .SetListView(view => - { - view.AddDefaultButton(DefaultButtonType.New); + config.Dashboard.AddSection(typeof(Dashboard)); - view.AddRow(row => - { - row.AddField(p => p.Id).SetName("ID"); - row.AddField(p => p.Name); + config.AddCollection>("person", "FabricUserFolder", "Red10", "Person", collection => + { + collection + .SetTreeView(x => x.Name) + .SetListView(view => + { + view.AddDefaultButton(DefaultButtonType.New); - row.AddDefaultButton(DefaultButtonType.Edit); - }); - }) - .SetNodeEditor(editor => + view.AddRow(row => { - editor.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true); - editor.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true); - - editor.AddDefaultButton(DefaultButtonType.Delete); + row.AddField(p => p.Id).SetName("ID"); + row.AddField(p => p.Name); - editor.AddSection(section => - { - section.AddField(x => x.Id).SetType(EditorType.Readonly); - section.AddField(x => x.Name); - section.AddField(x => x.Email); - }); + row.AddDefaultButton(DefaultButtonType.Edit); + }); + }) + .SetNodeEditor(editor => + { + editor.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true); + editor.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true); - editor.AddSection(section => - { - section.AddField(x => x.Bio).SetType(EditorType.TextArea); - }); + editor.AddDefaultButton(DefaultButtonType.Delete); - editor.AddSection(typeof(SimplePersonCollection)); + editor.AddSection(section => + { + section.AddField(x => x.Id).SetType(EditorType.Readonly); + section.AddField(x => x.Name); + section.AddField(x => x.Email); }); - }); - config.AddCollection>("sort-person", "Sort", "Green10", "Sortable Person", collection => - { - collection - .SetTreeView(x => x.Name) - .SetListView(view => + editor.AddSection(section => { - view.AddDefaultButton(DefaultButtonType.New); + section.AddField(x => x.Bio).SetType(EditorType.TextArea); + }); - view.AddRow(row => - { - row.AddField(p => p.Id).SetName("ID"); - row.AddField(p => p.Name).SetOrderByExpression(x => x.Name, OrderByType.Descending); - row.AddField(p => p.Email).SetOrderByExpression(x => x.Email); + editor.AddSection(typeof(SimplePersonCollection)); + }); + }); - row.AddDefaultButton(DefaultButtonType.Edit); - }); - }) - .SetNodeEditor(editor => - { - editor.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true); - editor.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true); + config.AddCollection>("sort-person", "Sort", "Green10", "Sortable Person", collection => + { + collection + .SetTreeView(x => x.Name) + .SetListView(view => + { + view.AddDefaultButton(DefaultButtonType.New); - editor.AddDefaultButton(DefaultButtonType.Delete); + view.AddRow(row => + { + row.AddField(p => p.Id).SetName("ID"); + row.AddField(p => p.Name).SetOrderByExpression(x => x.Name, OrderByType.Descending); + row.AddField(p => p.Email).SetOrderByExpression(x => x.Email); - editor.AddSection(section => - { - section.AddField(x => x.Id).SetType(EditorType.Readonly); - section.AddField(x => x.Name); - section.AddField(x => x.Email); - }); + row.AddDefaultButton(DefaultButtonType.Edit); + }); + }) + .SetNodeEditor(editor => + { + editor.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true); + editor.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true); - editor.AddSection(section => - { - section.AddField(x => x.Bio).SetType(EditorType.TextArea); - }); + editor.AddDefaultButton(DefaultButtonType.Delete); - editor.AddSection(typeof(SortPersonCollection)); + editor.AddSection(section => + { + section.AddField(x => x.Id).SetType(EditorType.Readonly); + section.AddField(x => x.Name); + section.AddField(x => x.Email); }); - }); - config.AddCollection>("country", "MapPin", "GreenCyan10", "Countries", collection => - { - collection - .SetTreeView(EntityVisibilty.Hidden, x => x.Name) - .SetListEditor(editor => + editor.AddSection(section => { - editor.AllowReordering(true); + section.AddField(x => x.Bio).SetType(EditorType.TextArea); + }); - editor.AddDefaultButton(DefaultButtonType.New); - editor.AddDefaultButton(DefaultButtonType.Return); - editor.AddDefaultButton(DefaultButtonType.SaveExisting); + editor.AddSection(typeof(SortPersonCollection)); + }); + }); - editor.AddSection(row => - { - row.AddField(p => p.Id).SetType(DisplayType.Label); - row.AddField(p => p.Name); + config.AddCollection>("country", "MapPin", "GreenCyan10", "Countries", collection => + { + collection + .SetTreeView(EntityVisibilty.Hidden, x => x.Name) + .SetListEditor(editor => + { + editor.AllowReordering(true); - row.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true); - row.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true); - row.AddDefaultButton(DefaultButtonType.View, "View code"); - row.AddDefaultButton(DefaultButtonType.Delete); - }); + editor.AddDefaultButton(DefaultButtonType.New); + editor.AddDefaultButton(DefaultButtonType.Return); + editor.AddDefaultButton(DefaultButtonType.SaveExisting); - }) - .SetNodeView(view => + editor.AddSection(row => { - view.AddDefaultButton(DefaultButtonType.Up); + row.AddField(p => p.Id).SetType(DisplayType.Label); + row.AddField(p => p.Name); - view.AddSection(typeof(SimpleCountryCollection)); + row.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true); + row.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true); + row.AddDefaultButton(DefaultButtonType.View, "View code"); + row.AddDefaultButton(DefaultButtonType.Delete); }); - }); - config.AddCollection>("validation-person", "UserFollowed", "Magenta10", "Validation Person", collection => - { - collection - .SetTreeView(x => x.Name) - .SetListView(view => - { - view.AddDefaultButton(DefaultButtonType.New); + }) + .SetNodeView(view => + { + view.AddDefaultButton(DefaultButtonType.Up); - view.AddRow(row => - { - row.AddField(p => p.Id).SetName("ID"); - row.AddField(p => p.Name); + view.AddSection(typeof(SimpleCountryCollection)); + }); + }); - row.AddDefaultButton(DefaultButtonType.Edit); - }); - }) - .SetNodeEditor(editor => - { - editor.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true); - editor.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true); + config.AddCollection>("validation-person", "UserFollowed", "Magenta10", "Validation Person", collection => + { + collection + .SetTreeView(x => x.Name) + .SetListView(view => + { + view.AddDefaultButton(DefaultButtonType.New); - editor.AddDefaultButton(DefaultButtonType.Delete); + view.AddRow(row => + { + row.AddField(p => p.Id).SetName("ID"); + row.AddField(p => p.Name); - editor.AddSection(section => - { - section.AddField(x => x.Id).SetType(EditorType.Readonly); - section.AddField(x => x.Name); - section.AddField(x => x.Email); - }); + row.AddDefaultButton(DefaultButtonType.Edit); + }); + }) + .SetNodeEditor(editor => + { + editor.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true); + editor.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true); - editor.AddSection(section => - { - section.AddField(x => x.Bio).SetType(EditorType.TextArea); - }); + editor.AddDefaultButton(DefaultButtonType.Delete); - editor.AddSection(typeof(SimplePersonCollection)); + editor.AddSection(section => + { + section.AddField(x => x.Id).SetType(EditorType.Readonly); + section.AddField(x => x.Name); + section.AddField(x => x.Email); }); - }); - config.AddCollection>("person-with-inline-countries", "FabricUserFolder", "RedOrange10", "Person With Inline Countries", collection => - { - collection - .SetTreeView(x => x.Name) - .SetListView(view => + editor.AddSection(section => { - view.AddDefaultButton(DefaultButtonType.New); + section.AddField(x => x.Bio).SetType(EditorType.TextArea); + }); - view.AddRow(row => - { - row.AddField(p => p.Id).SetName("ID"); - row.AddField(p => p.Name); + editor.AddSection(typeof(SimplePersonCollection)); + }); + }); - row.AddDefaultButton(DefaultButtonType.Edit); - }); - }) - .SetNodeEditor(editor => + config.AddCollection>("person-with-inline-countries", "FabricUserFolder", "RedOrange10", "Person With Inline Countries", collection => + { + collection + .SetTreeView(x => x.Name) + .SetListView(view => + { + view.AddDefaultButton(DefaultButtonType.New); + + view.AddRow(row => { - editor.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true); - editor.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true); + row.AddField(p => p.Id).SetName("ID"); + row.AddField(p => p.Name); - editor.AddDefaultButton(DefaultButtonType.Delete); + row.AddDefaultButton(DefaultButtonType.Edit); + }); + }) + .SetNodeEditor(editor => + { + editor.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true); + editor.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true); - editor.AddSection(section => - { - section.AddField(x => x.Id).SetType(EditorType.Readonly); - section.AddField(x => x.Name); - section.AddField(x => x.Email); - }); + editor.AddDefaultButton(DefaultButtonType.Delete); - editor.AddSection(section => - { - section.AddField(x => x.Bio).SetType(EditorType.TextArea); - }); + editor.AddSection(section => + { + section.AddField(x => x.Id).SetType(EditorType.Readonly); + section.AddField(x => x.Name); + section.AddField(x => x.Email); + }); - editor.AddSection(section => - { - section.VisibleWhen((person, state) => state == EntityState.IsExisting); + editor.AddSection(section => + { + section.AddField(x => x.Bio).SetType(EditorType.TextArea); + }); + + editor.AddSection(section => + { + section.VisibleWhen((person, state) => state == EntityState.IsExisting); - section.AddSubCollectionList>(subCollection => + section.AddSubCollectionList>(subCollection => + { + subCollection.SetListEditor(listEditor => { - subCollection.SetListEditor(listEditor => + listEditor.AddDefaultButton(DefaultButtonType.New); + listEditor.AddDefaultButton(DefaultButtonType.Return); + + listEditor.AddSection(row => { - listEditor.AddDefaultButton(DefaultButtonType.New); - listEditor.AddDefaultButton(DefaultButtonType.Return); - - listEditor.AddSection(row => - { - row.AddField(p => p.Id).SetType(DisplayType.Label); - row.AddField(p => p.Name); - - row.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true); - row.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true); - row.AddDefaultButton(DefaultButtonType.Delete); - }); + row.AddField(p => p.Id).SetType(DisplayType.Label); + row.AddField(p => p.Name); + + row.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true); + row.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true); + row.AddDefaultButton(DefaultButtonType.Delete); }); }); }); - - editor.AddSection(typeof(PersonCountryCollection)); }); - }); - config.AddCollection>("recursive-person", "UserSync", "Cyan30", "Recursive Person - By Convention", collection => - { - collection - .SetTreeView(x => x.Name) - .ConfigureByConvention(CollectionConvention.ListViewNodeEditor); + editor.AddSection(typeof(PersonCountryCollection)); + }); + }); - collection.AddSelfAsRecursiveCollection(); - }); + config.AddCollection>("recursive-person", "UserSync", "Cyan30", "Recursive Person - By Convention", collection => + { + collection + .SetTreeView(x => x.Name) + .ConfigureByConvention(CollectionConvention.ListViewNodeEditor); - config.AddCollection>("recursive-person-view", "UserSync", "YellowGreen10", "Recursive Person (read-only)", collection => - { - collection - .SetTreeView(x => x.Name) - .ConfigureByConvention(CollectionConvention.ListViewNodeView); + collection.AddSelfAsRecursiveCollection(); + }); - collection.AddSelfAsRecursiveCollection(); - }); + config.AddCollection>("recursive-person-view", "UserSync", "YellowGreen10", "Recursive Person (read-only)", collection => + { + collection + .SetTreeView(x => x.Name) + .ConfigureByConvention(CollectionConvention.ListViewNodeView); - config.AddCollection>("person-with-countries", "FabricUserFolder", "Cyan10", "Person With Countries", collection => - { - collection - .SetTreeView(x => x.Name) - .SetListView(view => - { - view.AddDefaultButton(DefaultButtonType.New); + collection.AddSelfAsRecursiveCollection(); + }); - view.AddRow(row => - { - row.AddField(p => p.Id).SetName("ID"); - row.AddField(p => p.Name); + config.AddCollection>("person-with-countries", "FabricUserFolder", "Cyan10", "Person With Countries", collection => + { + collection + .SetTreeView(x => x.Name) + .SetListView(view => + { + view.AddDefaultButton(DefaultButtonType.New); - row.AddDefaultButton(DefaultButtonType.Edit); - }); - }) - .SetNodeEditor(editor => + view.AddRow(row => { - editor.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true); - editor.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true); + row.AddField(p => p.Id).SetName("ID"); + row.AddField(p => p.Name); - editor.AddDefaultButton(DefaultButtonType.Delete); + row.AddDefaultButton(DefaultButtonType.Edit); + }); + }) + .SetNodeEditor(editor => + { + editor.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true); + editor.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true); - editor.AddSection(section => - { - section.AddField(x => x.Id).SetType(EditorType.Readonly); - section.AddField(x => x.Name); - section.AddField(x => x.Email); - - section.AddField(x => x.FavouriteCountryId1) - .SetName("Favorite country (based on sub collection)") - .SetType(EditorType.Select) - .SetCollectionRelation>(field => - { - field.SetElementDisplayProperties(x => x.Name); - field.SetElementIdProperty(x => x.Id); - field.SetEntityAsParent(); - }); + editor.AddDefaultButton(DefaultButtonType.Delete); - section.AddField(x => x.FavouriteCountryId2) - .SetName("Favorite country (based on country collection)") - .SetType(EditorType.Select) - .SetCollectionRelation>(field => - { - field.SetElementDisplayProperties(x => x.Name); - field.SetElementIdProperty(x => x.Id); - }); - }); + editor.AddSection(section => + { + section.AddField(x => x.Id).SetType(EditorType.Readonly); + section.AddField(x => x.Name); + section.AddField(x => x.Email); + + section.AddField(x => x.FavouriteCountryId1) + .SetName("Favorite country (based on sub collection)") + .SetType(EditorType.Select) + .SetCollectionRelation>(field => + { + field.SetElementDisplayProperties(x => x.Name); + field.SetElementIdProperty(x => x.Id); + field.SetEntityAsParent(); + }); - editor.AddSection(section => - { - section.AddField(x => x.Bio).SetType(EditorType.TextArea); - }); + section.AddField(x => x.FavouriteCountryId2) + .SetName("Favorite country (based on country collection)") + .SetType(EditorType.Select) + .SetCollectionRelation>(field => + { + field.SetElementDisplayProperties(x => x.Name); + field.SetElementIdProperty(x => x.Id); + }); + }); - editor.AddSection(section => - { - section.VisibleWhen((person, state) => state == EntityState.IsExisting); + editor.AddSection(section => + { + section.AddField(x => x.Bio).SetType(EditorType.TextArea); + }); - section.AddSubCollectionList("countries-under-person"); - }); + editor.AddSection(section => + { + section.VisibleWhen((person, state) => state == EntityState.IsExisting); - editor.AddSection(typeof(PersonCountry2Collection)); + section.AddSubCollectionList("countries-under-person"); }); - collection.AddSubCollection>("countries-under-person", "Countries", config => + editor.AddSection(typeof(PersonCountry2Collection)); + }); + + collection.AddSubCollection>("countries-under-person", "Countries", config => + { + config.SetTreeView(EntityVisibilty.Hidden, x => x.Name); + + config.SetListEditor(listEditor => { - config.SetTreeView(EntityVisibilty.Hidden, x => x.Name); + listEditor.AddDefaultButton(DefaultButtonType.New); + listEditor.AddDefaultButton(DefaultButtonType.Return); - config.SetListEditor(listEditor => + listEditor.AddSection(row => { - listEditor.AddDefaultButton(DefaultButtonType.New); - listEditor.AddDefaultButton(DefaultButtonType.Return); + row.AddField(p => p.Id).SetType(DisplayType.Label); + row.AddField(p => p.Name); - listEditor.AddSection(row => - { - row.AddField(p => p.Id).SetType(DisplayType.Label); - row.AddField(p => p.Name); - - row.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true); - row.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true); - row.AddDefaultButton(DefaultButtonType.Delete); - }); + row.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true); + row.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true); + row.AddDefaultButton(DefaultButtonType.Delete); }); }); }); + }); - config.AddCollection>("static-data-view-country", "TabTwoColumn", "PinkRed10", "Countries With Static Data Views", collection => - { - collection - .SetTreeView(EntityVisibilty.Hidden, x => x.Name) - .AddDataView("Countries A-K", x => Regex.IsMatch(x.Name ?? string.Empty, "^[A-K]", RegexOptions.IgnoreCase)) - .AddDataView("Countries L-Z", x => Regex.IsMatch(x.Name ?? string.Empty, "^[L-Z]", RegexOptions.IgnoreCase)) - .SetListEditor(editor => - { - editor.AddDefaultButton(DefaultButtonType.New); - editor.AddDefaultButton(DefaultButtonType.Return); - - editor.AddSection(row => - { - row.AddField(p => p.Id).SetType(DisplayType.Label); - row.AddField(p => p.Name); - - row.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true); - row.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true); - row.AddDefaultButton(DefaultButtonType.View, "View code"); - row.AddDefaultButton(DefaultButtonType.Delete); - }); + config.AddCollection>("static-data-view-country", "TabTwoColumn", "PinkRed10", "Countries With Static Data Views", collection => + { + collection + .SetTreeView(EntityVisibilty.Hidden, x => x.Name) + .AddDataView("Countries A-K", x => Regex.IsMatch(x.Name ?? string.Empty, "^[A-K]", RegexOptions.IgnoreCase)) + .AddDataView("Countries L-Z", x => Regex.IsMatch(x.Name ?? string.Empty, "^[L-Z]", RegexOptions.IgnoreCase)) + .SetListEditor(editor => + { + editor.AddDefaultButton(DefaultButtonType.New); + editor.AddDefaultButton(DefaultButtonType.Return); - }) - .SetNodeView(view => + editor.AddSection(row => { - view.AddDefaultButton(DefaultButtonType.Up); + row.AddField(p => p.Id).SetType(DisplayType.Label); + row.AddField(p => p.Name); - view.AddSection(typeof(StaticDataViewCountryCollection)); + row.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true); + row.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true); + row.AddDefaultButton(DefaultButtonType.View, "View code"); + row.AddDefaultButton(DefaultButtonType.Delete); }); - }); - config.AddCollection>("dynamic-data-view-country", "TabThreeColumn", "Red20", "Countries With Dynamic Data Views", collection => - { - collection - .SetTreeView(EntityVisibilty.Hidden, x => x.Name) - .SetDataViewBuilder() - .SetListEditor(editor => - { - editor.AddDefaultButton(DefaultButtonType.New); - editor.AddDefaultButton(DefaultButtonType.Return); + }) + .SetNodeView(view => + { + view.AddDefaultButton(DefaultButtonType.Up); - editor.AddSection(row => - { - row.AddField(p => p.Id).SetType(DisplayType.Label); - row.AddField(p => p.Name); + view.AddSection(typeof(StaticDataViewCountryCollection)); + }); + }); - row.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true); - row.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true); - row.AddDefaultButton(DefaultButtonType.View, "View code"); - row.AddDefaultButton(DefaultButtonType.Delete); - }); + config.AddCollection>("dynamic-data-view-country", "TabThreeColumn", "Red20", "Countries With Dynamic Data Views", collection => + { + collection + .SetTreeView(EntityVisibilty.Hidden, x => x.Name) + .SetDataViewBuilder() + .SetListEditor(editor => + { + editor.AddDefaultButton(DefaultButtonType.New); + editor.AddDefaultButton(DefaultButtonType.Return); - }) - .SetNodeView(view => + editor.AddSection(row => { - view.AddDefaultButton(DefaultButtonType.Up); + row.AddField(p => p.Id).SetType(DisplayType.Label); + row.AddField(p => p.Name); - view.AddSection(typeof(DynamicDataViewCountryCollection)); + row.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true); + row.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true); + row.AddDefaultButton(DefaultButtonType.View, "View code"); + row.AddDefaultButton(DefaultButtonType.Delete); }); - }); - config.AddCollection>("person-relation", "Relationship", "BlueMagenta30", "Person With Relations", collection => - { - collection - .SetTreeView(x => x.Name) - .SetListView(view => - { - view.AddDefaultButton(DefaultButtonType.New); + }) + .SetNodeView(view => + { + view.AddDefaultButton(DefaultButtonType.Up); - view.AddRow(row => - { - row.AddField(p => p.Id).SetName("ID"); - row.AddField(p => p.Name); + view.AddSection(typeof(DynamicDataViewCountryCollection)); + }); + }); - row.AddDefaultButton(DefaultButtonType.Edit); - }); - }) - .SetNodeEditor(editor => - { - editor.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true); - editor.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true); + config.AddCollection>("person-relation", "Relationship", "BlueMagenta30", "Person With Relations", collection => + { + collection + .SetTreeView(x => x.Name) + .SetListView(view => + { + view.AddDefaultButton(DefaultButtonType.New); - editor.AddDefaultButton(DefaultButtonType.Delete); + view.AddRow(row => + { + row.AddField(p => p.Id).SetName("ID"); + row.AddField(p => p.Name); - editor.AddSection(section => - { - section.AddField(x => x.Id).SetType(EditorType.Readonly); - section.AddField(x => x.Name); - section.AddField(x => x.Email); - }); + row.AddDefaultButton(DefaultButtonType.Edit); + }); + }) + .SetNodeEditor(editor => + { + editor.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true); + editor.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true); - editor.AddSection(section => - { - section.AddField(x => x.Bio).SetType(EditorType.TextArea); - }); + editor.AddDefaultButton(DefaultButtonType.Delete); - editor.AddSection(section => - { - section.VisibleWhen((entity, state) => state == EntityState.IsExisting); - - section.AddField(x => x.Countries) - .SetType(EditorType.MultiSelect) - .SetCollectionRelation( - countries => countries.Select(x => x.Id ?? string.Empty), - "country", - relation => - { - relation.SetElementDisplayProperties(x => x.Name); - relation.SetElementIdProperty(x => x.Id); - }); - }); + editor.AddSection(section => + { + section.AddField(x => x.Id).SetType(EditorType.Readonly); + section.AddField(x => x.Name); + section.AddField(x => x.Email); + }); - editor.AddSection(typeof(PersonCountry3Collection)); + editor.AddSection(section => + { + section.AddField(x => x.Bio).SetType(EditorType.TextArea); }); - }); - config.AddCollection>("person-relation-collection", "Relationship", "Magenta20", "Person With Relations Collection", collection => - { - collection - .SetTreeView(x => x.Name) - .SetListView(view => + editor.AddSection(section => { - view.AddDefaultButton(DefaultButtonType.New); + section.VisibleWhen((entity, state) => state == EntityState.IsExisting); + + section.AddField(x => x.Countries) + .SetType(EditorType.MultiSelect) + .SetCollectionRelation( + countries => countries.Select(x => x.Id ?? string.Empty), + "country", + relation => + { + relation.SetElementDisplayProperties(x => x.Name); + relation.SetElementIdProperty(x => x.Id); + }); + }); - view.AddRow(row => - { - row.AddField(p => p.Id).SetName("ID"); - row.AddField(p => p.Name); + editor.AddSection(typeof(PersonCountry3Collection)); + }); + }); - row.AddDefaultButton(DefaultButtonType.Edit); - }); - }) - .SetNodeEditor(editor => + config.AddCollection>("person-relation-collection", "Relationship", "Magenta20", "Person With Relations Collection", collection => + { + collection + .SetTreeView(x => x.Name) + .SetListView(view => + { + view.AddDefaultButton(DefaultButtonType.New); + + view.AddRow(row => { - editor.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true); - editor.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true); + row.AddField(p => p.Id).SetName("ID"); + row.AddField(p => p.Name); - editor.AddDefaultButton(DefaultButtonType.Delete); + row.AddDefaultButton(DefaultButtonType.Edit); + }); + }) + .SetNodeEditor(editor => + { + editor.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true); + editor.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true); - editor.AddSection(section => - { - section.AddField(x => x.Id).SetType(EditorType.Readonly); - section.AddField(x => x.Name); - section.AddField(x => x.Email); - }); + editor.AddDefaultButton(DefaultButtonType.Delete); - editor.AddSection(section => - { - section.AddField(x => x.Bio).SetType(EditorType.TextArea); - }); + editor.AddSection(section => + { + section.AddField(x => x.Id).SetType(EditorType.Readonly); + section.AddField(x => x.Name); + section.AddField(x => x.Email); + }); + + editor.AddSection(section => + { + section.AddField(x => x.Bio).SetType(EditorType.TextArea); + }); - editor.AddSection(section => + editor.AddSection(section => + { + section.VisibleWhen((entity, state) => state == EntityState.IsExisting); + section.AddRelatedCollectionList>(relation => { - section.VisibleWhen((entity, state) => state == EntityState.IsExisting); - section.AddRelatedCollectionList>(relation => + relation.SetListEditor(listEditor => { - relation.SetListEditor(listEditor => + listEditor.AddDefaultButton(DefaultButtonType.Return); + listEditor.AddDefaultButton(DefaultButtonType.Add); + listEditor.AddDefaultButton(DefaultButtonType.New); + + listEditor.AddSection(row => { - listEditor.AddDefaultButton(DefaultButtonType.Return); - listEditor.AddDefaultButton(DefaultButtonType.Add); - listEditor.AddDefaultButton(DefaultButtonType.New); - - listEditor.AddSection(row => - { - row.AddField(p => p.Id).SetType(DisplayType.Label); - row.AddField(p => p.Name); - - row.AddDefaultButton(DefaultButtonType.Pick, isPrimary: true); - row.AddDefaultButton(DefaultButtonType.Remove, isPrimary: true); - row.AddDefaultButton(DefaultButtonType.SaveExisting); - row.AddDefaultButton(DefaultButtonType.SaveNew); - row.AddDefaultButton(DefaultButtonType.Delete); - }); + row.AddField(p => p.Id).SetType(DisplayType.Label); + row.AddField(p => p.Name); + + row.AddDefaultButton(DefaultButtonType.Pick, isPrimary: true); + row.AddDefaultButton(DefaultButtonType.Remove, isPrimary: true); + row.AddDefaultButton(DefaultButtonType.SaveExisting); + row.AddDefaultButton(DefaultButtonType.SaveNew); + row.AddDefaultButton(DefaultButtonType.Delete); }); }); }); - - editor.AddSection(typeof(PersonCountry4Collection)); }); - }); + + editor.AddSection(typeof(PersonCountry4Collection)); + }); }); + }); - await builder.Build().RunAsync(); - } + await builder.Build().RunAsync(); } } diff --git a/examples/RapidCMS.Example.Github/RapidCMS.Example.Github.csproj b/examples/RapidCMS.Example.Github/RapidCMS.Example.Github.csproj index 13feb9df..fa74324d 100644 --- a/examples/RapidCMS.Example.Github/RapidCMS.Example.Github.csproj +++ b/examples/RapidCMS.Example.Github/RapidCMS.Example.Github.csproj @@ -1,11 +1,10 @@  - net6.0 + net8.0 enable Blazor WebAssembly true - 10.0 @@ -27,6 +26,17 @@ + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + diff --git a/examples/RapidCMS.Example.Maui/App.xaml b/examples/RapidCMS.Example.Maui/App.xaml deleted file mode 100644 index d0fa7392..00000000 --- a/examples/RapidCMS.Example.Maui/App.xaml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - #512bdf - White - - - - - - - - \ No newline at end of file diff --git a/examples/RapidCMS.Example.Maui/App.xaml.cs b/examples/RapidCMS.Example.Maui/App.xaml.cs deleted file mode 100644 index d8ae1177..00000000 --- a/examples/RapidCMS.Example.Maui/App.xaml.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Microsoft.Maui; -using Microsoft.Maui.Controls; -using Microsoft.Maui.Controls.PlatformConfiguration.WindowsSpecific; -using Application = Microsoft.Maui.Controls.Application; - -namespace RapidCMS.Example.Maui -{ - public partial class App : Application - { - public App() - { - InitializeComponent(); - - MainPage = new MainPage(); - } - } -} diff --git a/examples/RapidCMS.Example.Maui/Main.razor b/examples/RapidCMS.Example.Maui/Main.razor deleted file mode 100644 index b92e6f5f..00000000 --- a/examples/RapidCMS.Example.Maui/Main.razor +++ /dev/null @@ -1 +0,0 @@ - diff --git a/examples/RapidCMS.Example.Maui/MainPage.xaml b/examples/RapidCMS.Example.Maui/MainPage.xaml deleted file mode 100644 index 132b7901..00000000 --- a/examples/RapidCMS.Example.Maui/MainPage.xaml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/examples/RapidCMS.Example.Maui/MainPage.xaml.cs b/examples/RapidCMS.Example.Maui/MainPage.xaml.cs deleted file mode 100644 index 80da1c99..00000000 --- a/examples/RapidCMS.Example.Maui/MainPage.xaml.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Microsoft.Maui.Controls; -using System; - -namespace RapidCMS.Example.Maui -{ - public partial class MainPage : ContentPage - { - public MainPage() - { - InitializeComponent(); - } - } -} diff --git a/examples/RapidCMS.Example.Maui/MauiProgram.cs b/examples/RapidCMS.Example.Maui/MauiProgram.cs deleted file mode 100644 index e8c6ee41..00000000 --- a/examples/RapidCMS.Example.Maui/MauiProgram.cs +++ /dev/null @@ -1,117 +0,0 @@ -using System; -using Blazored.LocalStorage; -using Microsoft.AspNetCore.Components.WebView.Maui; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Maui.Controls.Hosting; -using Microsoft.Maui.Hosting; -using RapidCMS.Core.Repositories; -using RapidCMS.Example.Shared.Collections; -using RapidCMS.Example.Shared.Components; -using RapidCMS.Example.Shared.Data; -using RapidCMS.Example.Shared.DataViews; -using RapidCMS.Example.Shared.Handlers; -using RapidCMS.Example.Shared.Validators; -using RapidCMS.Repositories; -using RapidCMS.Repositories.ApiBridge; - -namespace RapidCMS.Example.Maui -{ - public static class MauiProgram - { - // web api (run this project along with RapidCMS.Example.WebAssembly.API) - private static readonly Uri BaseUri = new Uri("https://localhost:5003/api/"); - - public static MauiApp CreateMauiApp() - { - var builder = MauiApp.CreateBuilder(); - builder - .UseMauiApp(); - - builder.Services.AddMauiBlazorWebView(); - - builder.Services.AddAuthorizationCore(); - - - // with LocalStorageRepository collections can store their data in the local storage of - // the user, making personalization quite easy - builder.Services.AddBlazoredLocalStorage(); - builder.Services.AddScoped, LocalStorageRepository>(); - - builder.Services.AddRapidCMSApiRepository, ApiRepository>(BaseUri); - builder.Services.AddRapidCMSApiRepository, ApiRepository
>(BaseUri); - builder.Services.AddRapidCMSApiRepository, ApiRepository>(BaseUri); - builder.Services.AddRapidCMSApiRepository, ApiRepository>(BaseUri); - builder.Services.AddRapidCMSApiRepository, ApiRepository>(BaseUri); - builder.Services.AddRapidCMSApiRepository, ApiRepository>(BaseUri); - builder.Services.AddRapidCMSApiRepository, ApiRepository>(BaseUri); - - builder.Services.AddSingleton(); - builder.Services.AddScoped, CounterRepository>(); - - builder.Services.AddSingleton(); - builder.Services.AddSingleton(); - - builder.Services.AddTransient(); - builder.Services.AddTransient(); - - // the country entity is validated by a FluentValidator - builder.Services.AddSingleton(); - - builder.Services.AddRapidCMSFileUploadApiHttpClient(BaseUri); - builder.Services.AddRapidCMSFileUploadApiHttpClient(BaseUri); - - // api repositories can also be mapped - builder.Services.AddRapidCMSApiRepository< - BaseMappedRepository, - ApiMappedRepository>(BaseUri); - - builder.Services.AddRapidCMSWebAssembly(config => - { - config.AllowAnonymousUser(); - - // configure 5 as number of concurrent HTTP requests to the backend API - config.Advanced.SemaphoreCount = 5; - - // CRUD editor for simple POCO with recursive sub collections - // --> see Collections/PersonCollection for the basics of this CMS - config.AddPersonCollection(); - - // CRUD editor with support for one-to-many relation + validation - // --> see Collections/CountryCollection for one-to-many relation with validation - config.AddCountryCollection(); - - // Custom page with either custom Blazor components, or ListViews or ListEditors of collections - config.AddPage("TestBeakerSolid", "Green10", "Some random page", config => - { - config.AddSection(typeof(CustomSection)); - config.AddSection("country", edit: false); - }); - - // CRUD editor with validation attributes, custom editor and custom button panes - // --> see Collections/UserCollection - config.AddUserCollection(); - - // CRUD editor with nested collection - // --> see Collections/TagCollection - config.AddTagCollection(); - - // CRUD editor with entity mapping - config.AddMappedCollection(); - - // CRUD editor based on conventions for even more rapid development - config.AddConventionCollection(); - - // CRUD editor with entity variants, so multiple types of entities can be mixed in a single collection - config.AddEntityVariantCollection(); - - // CRUD editor displaying live data, an external process updates the data every second - config.AddActiveCollection(); - - //config.Dashboard.AddSection(typeof(DashboardSection)); - config.Dashboard.AddSection("user", edit: true); - }); - - return builder.Build(); - } - } -} diff --git a/examples/RapidCMS.Example.Maui/Platforms/Android/AndroidManifest.xml b/examples/RapidCMS.Example.Maui/Platforms/Android/AndroidManifest.xml deleted file mode 100644 index 7570ff62..00000000 --- a/examples/RapidCMS.Example.Maui/Platforms/Android/AndroidManifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/examples/RapidCMS.Example.Maui/Platforms/Android/MainActivity.cs b/examples/RapidCMS.Example.Maui/Platforms/Android/MainActivity.cs deleted file mode 100644 index e5b6c8ba..00000000 --- a/examples/RapidCMS.Example.Maui/Platforms/Android/MainActivity.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Android.App; -using Android.Content.PM; -using Microsoft.Maui; - -namespace RapidCMS.Example.Maui -{ - [Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize)] - public class MainActivity : MauiAppCompatActivity - { - } -} \ No newline at end of file diff --git a/examples/RapidCMS.Example.Maui/Platforms/Android/MainApplication.cs b/examples/RapidCMS.Example.Maui/Platforms/Android/MainApplication.cs deleted file mode 100644 index 39766249..00000000 --- a/examples/RapidCMS.Example.Maui/Platforms/Android/MainApplication.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Android.App; -using Android.Runtime; -using Microsoft.Maui; -using Microsoft.Maui.Hosting; -using System; - -namespace RapidCMS.Example.Maui -{ - [Application] - public class MainApplication : MauiApplication - { - public MainApplication(IntPtr handle, JniHandleOwnership ownership) - : base(handle, ownership) - { - } - - protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); - } -} \ No newline at end of file diff --git a/examples/RapidCMS.Example.Maui/Platforms/Android/Resources/values/colors.xml b/examples/RapidCMS.Example.Maui/Platforms/Android/Resources/values/colors.xml deleted file mode 100644 index c04d7492..00000000 --- a/examples/RapidCMS.Example.Maui/Platforms/Android/Resources/values/colors.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - #512BD4 - #2B0B98 - #2B0B98 - \ No newline at end of file diff --git a/examples/RapidCMS.Example.Maui/Platforms/MacCatalyst/AppDelegate.cs b/examples/RapidCMS.Example.Maui/Platforms/MacCatalyst/AppDelegate.cs deleted file mode 100644 index 61450b9e..00000000 --- a/examples/RapidCMS.Example.Maui/Platforms/MacCatalyst/AppDelegate.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Foundation; -using Microsoft.Maui; -using Microsoft.Maui.Hosting; - -namespace RapidCMS.Example.Maui -{ - [Register("AppDelegate")] - public class AppDelegate : MauiUIApplicationDelegate - { - protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); - } -} \ No newline at end of file diff --git a/examples/RapidCMS.Example.Maui/Platforms/MacCatalyst/Info.plist b/examples/RapidCMS.Example.Maui/Platforms/MacCatalyst/Info.plist deleted file mode 100644 index c96dd0a2..00000000 --- a/examples/RapidCMS.Example.Maui/Platforms/MacCatalyst/Info.plist +++ /dev/null @@ -1,30 +0,0 @@ - - - - - UIDeviceFamily - - 1 - 2 - - UIRequiredDeviceCapabilities - - arm64 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - XSAppIconAssets - Assets.xcassets/appicon.appiconset - - diff --git a/examples/RapidCMS.Example.Maui/Platforms/MacCatalyst/Program.cs b/examples/RapidCMS.Example.Maui/Platforms/MacCatalyst/Program.cs deleted file mode 100644 index 3c384d7a..00000000 --- a/examples/RapidCMS.Example.Maui/Platforms/MacCatalyst/Program.cs +++ /dev/null @@ -1,15 +0,0 @@ -using UIKit; - -namespace RapidCMS.Example.Maui -{ - public class Program - { - // This is the main entry point of the application. - static void Main(string[] args) - { - // if you want to use a different Application Delegate class from "AppDelegate" - // you can specify it here. - UIApplication.Main(args, null, typeof(AppDelegate)); - } - } -} \ No newline at end of file diff --git a/examples/RapidCMS.Example.Maui/Platforms/Windows/App.xaml b/examples/RapidCMS.Example.Maui/Platforms/Windows/App.xaml deleted file mode 100644 index 0b3290b5..00000000 --- a/examples/RapidCMS.Example.Maui/Platforms/Windows/App.xaml +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/examples/RapidCMS.Example.Maui/Platforms/Windows/App.xaml.cs b/examples/RapidCMS.Example.Maui/Platforms/Windows/App.xaml.cs deleted file mode 100644 index c88893df..00000000 --- a/examples/RapidCMS.Example.Maui/Platforms/Windows/App.xaml.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Microsoft.Maui; -using Microsoft.Maui.Hosting; -using Microsoft.UI.Xaml; - -// To learn more about WinUI, the WinUI project structure, -// and more about our project templates, see: http://aka.ms/winui-project-info. - -namespace RapidCMS.Example.Maui.WinUI -{ - /// - /// Provides application-specific behavior to supplement the default Application class. - /// - public partial class App : MauiWinUIApplication - { - /// - /// Initializes the singleton application object. This is the first line of authored code - /// executed, and as such is the logical equivalent of main() or WinMain(). - /// - public App() - { - InitializeComponent(); - } - - protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); - - protected override void OnLaunched(LaunchActivatedEventArgs args) - { - base.OnLaunched(args); - } - } -} diff --git a/examples/RapidCMS.Example.Maui/Platforms/Windows/Package.appxmanifest b/examples/RapidCMS.Example.Maui/Platforms/Windows/Package.appxmanifest deleted file mode 100644 index 6e685a01..00000000 --- a/examples/RapidCMS.Example.Maui/Platforms/Windows/Package.appxmanifest +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - RapidCMS.Example.Maui - Microsoft - Assets\appiconStoreLogo.png - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/RapidCMS.Example.Maui/Platforms/Windows/app.manifest b/examples/RapidCMS.Example.Maui/Platforms/Windows/app.manifest deleted file mode 100644 index 3fa78124..00000000 --- a/examples/RapidCMS.Example.Maui/Platforms/Windows/app.manifest +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - true/PM - PerMonitorV2, PerMonitor - - - diff --git a/examples/RapidCMS.Example.Maui/Platforms/iOS/AppDelegate.cs b/examples/RapidCMS.Example.Maui/Platforms/iOS/AppDelegate.cs deleted file mode 100644 index 61450b9e..00000000 --- a/examples/RapidCMS.Example.Maui/Platforms/iOS/AppDelegate.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Foundation; -using Microsoft.Maui; -using Microsoft.Maui.Hosting; - -namespace RapidCMS.Example.Maui -{ - [Register("AppDelegate")] - public class AppDelegate : MauiUIApplicationDelegate - { - protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); - } -} \ No newline at end of file diff --git a/examples/RapidCMS.Example.Maui/Platforms/iOS/Info.plist b/examples/RapidCMS.Example.Maui/Platforms/iOS/Info.plist deleted file mode 100644 index 0004a4fd..00000000 --- a/examples/RapidCMS.Example.Maui/Platforms/iOS/Info.plist +++ /dev/null @@ -1,32 +0,0 @@ - - - - - LSRequiresIPhoneOS - - UIDeviceFamily - - 1 - 2 - - UIRequiredDeviceCapabilities - - arm64 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - XSAppIconAssets - Assets.xcassets/appicon.appiconset - - diff --git a/examples/RapidCMS.Example.Maui/Platforms/iOS/Program.cs b/examples/RapidCMS.Example.Maui/Platforms/iOS/Program.cs deleted file mode 100644 index 3c384d7a..00000000 --- a/examples/RapidCMS.Example.Maui/Platforms/iOS/Program.cs +++ /dev/null @@ -1,15 +0,0 @@ -using UIKit; - -namespace RapidCMS.Example.Maui -{ - public class Program - { - // This is the main entry point of the application. - static void Main(string[] args) - { - // if you want to use a different Application Delegate class from "AppDelegate" - // you can specify it here. - UIApplication.Main(args, null, typeof(AppDelegate)); - } - } -} \ No newline at end of file diff --git a/examples/RapidCMS.Example.Maui/Platforms/iOS/Resources/LaunchScreen.xib b/examples/RapidCMS.Example.Maui/Platforms/iOS/Resources/LaunchScreen.xib deleted file mode 100644 index 3e5075f7..00000000 --- a/examples/RapidCMS.Example.Maui/Platforms/iOS/Resources/LaunchScreen.xib +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/RapidCMS.Example.Maui/RapidCMS.Example.Maui.csproj b/examples/RapidCMS.Example.Maui/RapidCMS.Example.Maui.csproj deleted file mode 100644 index 609e6bfc..00000000 --- a/examples/RapidCMS.Example.Maui/RapidCMS.Example.Maui.csproj +++ /dev/null @@ -1,60 +0,0 @@ - - - - net6.0-maccatalyst - $(TargetFrameworks);net6.0-windows10.0.19041 - enable - Maui + Blazor WebAssembly - 10.0 - Exe - RapidCMS.Example.Maui - true - true - true - false - - - RapidCMS.Example.Maui - - - com.companyname.RapidCMS.Example.Maui - - - 1 - - - True - - 14.0 - 10.0.17763.0 - 10.0.17763.0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/RapidCMS.Example.Maui/Resources/appicon.svg b/examples/RapidCMS.Example.Maui/Resources/appicon.svg deleted file mode 100644 index 9d63b651..00000000 --- a/examples/RapidCMS.Example.Maui/Resources/appicon.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/examples/RapidCMS.Example.Maui/Resources/appiconfg.svg b/examples/RapidCMS.Example.Maui/Resources/appiconfg.svg deleted file mode 100644 index 21dfb25f..00000000 --- a/examples/RapidCMS.Example.Maui/Resources/appiconfg.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/examples/RapidCMS.Example.Maui/_Imports.razor b/examples/RapidCMS.Example.Maui/_Imports.razor deleted file mode 100644 index aa8bc458..00000000 --- a/examples/RapidCMS.Example.Maui/_Imports.razor +++ /dev/null @@ -1,7 +0,0 @@ -@using System.Net.Http -@using Microsoft.AspNetCore.Components.Forms -@using Microsoft.AspNetCore.Components.Routing -@using Microsoft.AspNetCore.Components.Web -@using Microsoft.AspNetCore.Components.Web.Virtualization -@using Microsoft.JSInterop -@using RapidCMS.Example.Maui diff --git a/examples/RapidCMS.Example.Maui/wwwroot/index.html b/examples/RapidCMS.Example.Maui/wwwroot/index.html deleted file mode 100644 index 90c6c85a..00000000 --- a/examples/RapidCMS.Example.Maui/wwwroot/index.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - RapidCMS.Example.Maui - - - - - -
Loading...
- - - - - - - - diff --git a/examples/RapidCMS.Example.ModelMaker.Models/DesignTimeDbContextFactory.cs b/examples/RapidCMS.Example.ModelMaker.Models/DesignTimeDbContextFactory.cs deleted file mode 100644 index e35cfdd0..00000000 --- a/examples/RapidCMS.Example.ModelMaker.Models/DesignTimeDbContextFactory.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Design; -using RapidCMS.ModelMaker; - -namespace RapidCMS.Example.ModelMaker.Models -{ - public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory - { - public ModelMakerDbContext CreateDbContext(string[] args) - => new ModelMakerDbContext( - new DbContextOptionsBuilder() - .UseSqlServer("server=localhost\\sqlexpress;database=ModelMaker;integrated security=true;") - .Options); - } -} diff --git a/examples/RapidCMS.Example.ModelMaker.Models/Enums/ContentType.cs b/examples/RapidCMS.Example.ModelMaker.Models/Enums/ContentType.cs deleted file mode 100644 index e9d1e153..00000000 --- a/examples/RapidCMS.Example.ModelMaker.Models/Enums/ContentType.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace RapidCMS.Example.ModelMaker.Models.Enums -{ - public enum ContentType - { - Article, - Product, - News - } -} diff --git a/examples/RapidCMS.Example.ModelMaker.Models/Migrations/20211025050556_Initial.Designer.cs b/examples/RapidCMS.Example.ModelMaker.Models/Migrations/20211025050556_Initial.Designer.cs deleted file mode 100644 index 571b2487..00000000 --- a/examples/RapidCMS.Example.ModelMaker.Models/Migrations/20211025050556_Initial.Designer.cs +++ /dev/null @@ -1,300 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using RapidCMS.ModelMaker; - -#nullable disable - -namespace RapidCMS.Example.ModelMaker.Models.Migrations -{ - [DbContext(typeof(ModelMakerDbContext))] - [Migration("20211025050556_Initial")] - partial class Initial - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "6.0.0-rc.2.21480.5") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); - - modelBuilder.Entity("BlogCategory", b => - { - b.Property("BlogBlogCategoriesId") - .HasColumnType("int"); - - b.Property("BlogCategoriesId") - .HasColumnType("int"); - - b.HasKey("BlogBlogCategoriesId", "BlogCategoriesId"); - - b.HasIndex("BlogCategoriesId"); - - b.ToTable("BlogCategory"); - }); - - modelBuilder.Entity("ManytoManyManyAManytoManyManyB", b => - { - b.Property("AsId") - .HasColumnType("int"); - - b.Property("BsId") - .HasColumnType("int"); - - b.HasKey("AsId", "BsId"); - - b.HasIndex("BsId"); - - b.ToTable("ManytoManyManyAManytoManyManyB"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.Blog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Content") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("IsPublished") - .HasColumnType("bit"); - - b.Property("MainCategoryId") - .HasColumnType("int"); - - b.Property("PublishDate") - .HasColumnType("datetime2"); - - b.Property("Title") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Type") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("MainCategoryId"); - - b.ToTable("Blogs"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.Category", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Categories"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.ManytoManyManyA", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("ManytoManyManyAs"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.ManytoManyManyB", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("ManytoManyManyBs"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.OnetoManyMany", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("OnetoManyManys"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.OnetoManyOne", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("OneId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("OneId"); - - b.ToTable("OnetoManyOnes"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.OnetoOneOneA", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("BId") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("BId") - .IsUnique() - .HasFilter("[BId] IS NOT NULL"); - - b.ToTable("OnetoOneOneAs"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.OnetoOneOneB", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("OnetoOneOneBs"); - }); - - modelBuilder.Entity("BlogCategory", b => - { - b.HasOne("RapidCMS.ModelMaker.Blog", null) - .WithMany() - .HasForeignKey("BlogBlogCategoriesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("RapidCMS.ModelMaker.Category", null) - .WithMany() - .HasForeignKey("BlogCategoriesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("ManytoManyManyAManytoManyManyB", b => - { - b.HasOne("RapidCMS.ModelMaker.ManytoManyManyA", null) - .WithMany() - .HasForeignKey("AsId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("RapidCMS.ModelMaker.ManytoManyManyB", null) - .WithMany() - .HasForeignKey("BsId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.Blog", b => - { - b.HasOne("RapidCMS.ModelMaker.Category", "MainCategory") - .WithMany("BlogMainCategory") - .HasForeignKey("MainCategoryId") - .OnDelete(DeleteBehavior.NoAction); - - b.Navigation("MainCategory"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.OnetoManyOne", b => - { - b.HasOne("RapidCMS.ModelMaker.OnetoManyMany", "One") - .WithMany("Many") - .HasForeignKey("OneId") - .OnDelete(DeleteBehavior.NoAction); - - b.Navigation("One"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.OnetoOneOneA", b => - { - b.HasOne("RapidCMS.ModelMaker.OnetoOneOneB", "B") - .WithOne("A") - .HasForeignKey("RapidCMS.ModelMaker.OnetoOneOneA", "BId") - .OnDelete(DeleteBehavior.NoAction); - - b.Navigation("B"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.Category", b => - { - b.Navigation("BlogMainCategory"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.OnetoManyMany", b => - { - b.Navigation("Many"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.OnetoOneOneB", b => - { - b.Navigation("A"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/examples/RapidCMS.Example.ModelMaker.Models/Migrations/20211025050556_Initial.cs b/examples/RapidCMS.Example.ModelMaker.Models/Migrations/20211025050556_Initial.cs deleted file mode 100644 index 893482e9..00000000 --- a/examples/RapidCMS.Example.ModelMaker.Models/Migrations/20211025050556_Initial.cs +++ /dev/null @@ -1,247 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace RapidCMS.Example.ModelMaker.Models.Migrations -{ - public partial class Initial : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "Categories", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Name = table.Column(type: "nvarchar(max)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Categories", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "ManytoManyManyAs", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Name = table.Column(type: "nvarchar(max)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ManytoManyManyAs", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "ManytoManyManyBs", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Name = table.Column(type: "nvarchar(max)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ManytoManyManyBs", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "OnetoManyManys", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Name = table.Column(type: "nvarchar(max)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_OnetoManyManys", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "OnetoOneOneBs", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Name = table.Column(type: "nvarchar(max)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_OnetoOneOneBs", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "Blogs", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Title = table.Column(type: "nvarchar(max)", nullable: false), - Content = table.Column(type: "nvarchar(max)", nullable: false), - Type = table.Column(type: "int", nullable: false), - IsPublished = table.Column(type: "bit", nullable: false), - PublishDate = table.Column(type: "datetime2", nullable: false), - MainCategoryId = table.Column(type: "int", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Blogs", x => x.Id); - table.ForeignKey( - name: "FK_Blogs_Categories_MainCategoryId", - column: x => x.MainCategoryId, - principalTable: "Categories", - principalColumn: "Id"); - }); - - migrationBuilder.CreateTable( - name: "ManytoManyManyAManytoManyManyB", - columns: table => new - { - AsId = table.Column(type: "int", nullable: false), - BsId = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ManytoManyManyAManytoManyManyB", x => new { x.AsId, x.BsId }); - table.ForeignKey( - name: "FK_ManytoManyManyAManytoManyManyB_ManytoManyManyAs_AsId", - column: x => x.AsId, - principalTable: "ManytoManyManyAs", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_ManytoManyManyAManytoManyManyB_ManytoManyManyBs_BsId", - column: x => x.BsId, - principalTable: "ManytoManyManyBs", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "OnetoManyOnes", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Name = table.Column(type: "nvarchar(max)", nullable: false), - OneId = table.Column(type: "int", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_OnetoManyOnes", x => x.Id); - table.ForeignKey( - name: "FK_OnetoManyOnes_OnetoManyManys_OneId", - column: x => x.OneId, - principalTable: "OnetoManyManys", - principalColumn: "Id"); - }); - - migrationBuilder.CreateTable( - name: "OnetoOneOneAs", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Name = table.Column(type: "nvarchar(max)", nullable: false), - BId = table.Column(type: "int", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_OnetoOneOneAs", x => x.Id); - table.ForeignKey( - name: "FK_OnetoOneOneAs_OnetoOneOneBs_BId", - column: x => x.BId, - principalTable: "OnetoOneOneBs", - principalColumn: "Id"); - }); - - migrationBuilder.CreateTable( - name: "BlogCategory", - columns: table => new - { - BlogBlogCategoriesId = table.Column(type: "int", nullable: false), - BlogCategoriesId = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_BlogCategory", x => new { x.BlogBlogCategoriesId, x.BlogCategoriesId }); - table.ForeignKey( - name: "FK_BlogCategory_Blogs_BlogBlogCategoriesId", - column: x => x.BlogBlogCategoriesId, - principalTable: "Blogs", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_BlogCategory_Categories_BlogCategoriesId", - column: x => x.BlogCategoriesId, - principalTable: "Categories", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_BlogCategory_BlogCategoriesId", - table: "BlogCategory", - column: "BlogCategoriesId"); - - migrationBuilder.CreateIndex( - name: "IX_Blogs_MainCategoryId", - table: "Blogs", - column: "MainCategoryId"); - - migrationBuilder.CreateIndex( - name: "IX_ManytoManyManyAManytoManyManyB_BsId", - table: "ManytoManyManyAManytoManyManyB", - column: "BsId"); - - migrationBuilder.CreateIndex( - name: "IX_OnetoManyOnes_OneId", - table: "OnetoManyOnes", - column: "OneId"); - - migrationBuilder.CreateIndex( - name: "IX_OnetoOneOneAs_BId", - table: "OnetoOneOneAs", - column: "BId", - unique: true, - filter: "[BId] IS NOT NULL"); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "BlogCategory"); - - migrationBuilder.DropTable( - name: "ManytoManyManyAManytoManyManyB"); - - migrationBuilder.DropTable( - name: "OnetoManyOnes"); - - migrationBuilder.DropTable( - name: "OnetoOneOneAs"); - - migrationBuilder.DropTable( - name: "Blogs"); - - migrationBuilder.DropTable( - name: "ManytoManyManyAs"); - - migrationBuilder.DropTable( - name: "ManytoManyManyBs"); - - migrationBuilder.DropTable( - name: "OnetoManyManys"); - - migrationBuilder.DropTable( - name: "OnetoOneOneBs"); - - migrationBuilder.DropTable( - name: "Categories"); - } - } -} diff --git a/examples/RapidCMS.Example.ModelMaker.Models/Migrations/20211025050653_OneToOneFix.Designer.cs b/examples/RapidCMS.Example.ModelMaker.Models/Migrations/20211025050653_OneToOneFix.Designer.cs deleted file mode 100644 index 4b250129..00000000 --- a/examples/RapidCMS.Example.ModelMaker.Models/Migrations/20211025050653_OneToOneFix.Designer.cs +++ /dev/null @@ -1,300 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using RapidCMS.ModelMaker; - -#nullable disable - -namespace RapidCMS.Example.ModelMaker.Models.Migrations -{ - [DbContext(typeof(ModelMakerDbContext))] - [Migration("20211025050653_OneToOneFix")] - partial class OneToOneFix - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "6.0.0-rc.2.21480.5") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); - - modelBuilder.Entity("BlogCategory", b => - { - b.Property("BlogBlogCategoriesId") - .HasColumnType("int"); - - b.Property("BlogCategoriesId") - .HasColumnType("int"); - - b.HasKey("BlogBlogCategoriesId", "BlogCategoriesId"); - - b.HasIndex("BlogCategoriesId"); - - b.ToTable("BlogCategory"); - }); - - modelBuilder.Entity("ManytoManyManyAManytoManyManyB", b => - { - b.Property("AsId") - .HasColumnType("int"); - - b.Property("BsId") - .HasColumnType("int"); - - b.HasKey("AsId", "BsId"); - - b.HasIndex("BsId"); - - b.ToTable("ManytoManyManyAManytoManyManyB"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.Blog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Content") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("IsPublished") - .HasColumnType("bit"); - - b.Property("MainCategoryId") - .HasColumnType("int"); - - b.Property("PublishDate") - .HasColumnType("datetime2"); - - b.Property("Title") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Type") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("MainCategoryId"); - - b.ToTable("Blogs"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.Category", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Categories"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.ManytoManyManyA", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("ManytoManyManyAs"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.ManytoManyManyB", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("ManytoManyManyBs"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.OnetoManyMany", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("OnetoManyManys"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.OnetoManyOne", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("OneId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("OneId"); - - b.ToTable("OnetoManyOnes"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.OnetoOneOneA", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("BId") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("BId") - .IsUnique() - .HasFilter("[BId] IS NOT NULL"); - - b.ToTable("OnetoOneOneAs"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.OnetoOneOneB", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("OnetoOneOneBs"); - }); - - modelBuilder.Entity("BlogCategory", b => - { - b.HasOne("RapidCMS.ModelMaker.Blog", null) - .WithMany() - .HasForeignKey("BlogBlogCategoriesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("RapidCMS.ModelMaker.Category", null) - .WithMany() - .HasForeignKey("BlogCategoriesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("ManytoManyManyAManytoManyManyB", b => - { - b.HasOne("RapidCMS.ModelMaker.ManytoManyManyA", null) - .WithMany() - .HasForeignKey("AsId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("RapidCMS.ModelMaker.ManytoManyManyB", null) - .WithMany() - .HasForeignKey("BsId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.Blog", b => - { - b.HasOne("RapidCMS.ModelMaker.Category", "MainCategory") - .WithMany("BlogMainCategory") - .HasForeignKey("MainCategoryId") - .OnDelete(DeleteBehavior.NoAction); - - b.Navigation("MainCategory"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.OnetoManyOne", b => - { - b.HasOne("RapidCMS.ModelMaker.OnetoManyMany", "One") - .WithMany("Many") - .HasForeignKey("OneId") - .OnDelete(DeleteBehavior.NoAction); - - b.Navigation("One"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.OnetoOneOneA", b => - { - b.HasOne("RapidCMS.ModelMaker.OnetoOneOneB", "B") - .WithOne("A") - .HasForeignKey("RapidCMS.ModelMaker.OnetoOneOneA", "BId") - .OnDelete(DeleteBehavior.NoAction); - - b.Navigation("B"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.Category", b => - { - b.Navigation("BlogMainCategory"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.OnetoManyMany", b => - { - b.Navigation("Many"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.OnetoOneOneB", b => - { - b.Navigation("A"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/examples/RapidCMS.Example.ModelMaker.Models/Migrations/20211025050653_OneToOneFix.cs b/examples/RapidCMS.Example.ModelMaker.Models/Migrations/20211025050653_OneToOneFix.cs deleted file mode 100644 index 18793817..00000000 --- a/examples/RapidCMS.Example.ModelMaker.Models/Migrations/20211025050653_OneToOneFix.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace RapidCMS.Example.ModelMaker.Models.Migrations -{ - public partial class OneToOneFix : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - - } - } -} diff --git a/examples/RapidCMS.Example.ModelMaker.Models/Migrations/20211025050720_ContentType.Designer.cs b/examples/RapidCMS.Example.ModelMaker.Models/Migrations/20211025050720_ContentType.Designer.cs deleted file mode 100644 index 29efdfea..00000000 --- a/examples/RapidCMS.Example.ModelMaker.Models/Migrations/20211025050720_ContentType.Designer.cs +++ /dev/null @@ -1,300 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using RapidCMS.ModelMaker; - -#nullable disable - -namespace RapidCMS.Example.ModelMaker.Models.Migrations -{ - [DbContext(typeof(ModelMakerDbContext))] - [Migration("20211025050720_ContentType")] - partial class ContentType - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "6.0.0-rc.2.21480.5") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); - - modelBuilder.Entity("BlogCategory", b => - { - b.Property("BlogBlogCategoriesId") - .HasColumnType("int"); - - b.Property("BlogCategoriesId") - .HasColumnType("int"); - - b.HasKey("BlogBlogCategoriesId", "BlogCategoriesId"); - - b.HasIndex("BlogCategoriesId"); - - b.ToTable("BlogCategory"); - }); - - modelBuilder.Entity("ManytoManyManyAManytoManyManyB", b => - { - b.Property("AsId") - .HasColumnType("int"); - - b.Property("BsId") - .HasColumnType("int"); - - b.HasKey("AsId", "BsId"); - - b.HasIndex("BsId"); - - b.ToTable("ManytoManyManyAManytoManyManyB"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.Blog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Content") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("IsPublished") - .HasColumnType("bit"); - - b.Property("MainCategoryId") - .HasColumnType("int"); - - b.Property("PublishDate") - .HasColumnType("datetime2"); - - b.Property("Title") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Type") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("MainCategoryId"); - - b.ToTable("Blogs"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.Category", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Categories"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.ManytoManyManyA", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("ManytoManyManyAs"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.ManytoManyManyB", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("ManytoManyManyBs"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.OnetoManyMany", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("OnetoManyManys"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.OnetoManyOne", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("OneId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("OneId"); - - b.ToTable("OnetoManyOnes"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.OnetoOneOneA", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("BId") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("BId") - .IsUnique() - .HasFilter("[BId] IS NOT NULL"); - - b.ToTable("OnetoOneOneAs"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.OnetoOneOneB", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("OnetoOneOneBs"); - }); - - modelBuilder.Entity("BlogCategory", b => - { - b.HasOne("RapidCMS.ModelMaker.Blog", null) - .WithMany() - .HasForeignKey("BlogBlogCategoriesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("RapidCMS.ModelMaker.Category", null) - .WithMany() - .HasForeignKey("BlogCategoriesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("ManytoManyManyAManytoManyManyB", b => - { - b.HasOne("RapidCMS.ModelMaker.ManytoManyManyA", null) - .WithMany() - .HasForeignKey("AsId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("RapidCMS.ModelMaker.ManytoManyManyB", null) - .WithMany() - .HasForeignKey("BsId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.Blog", b => - { - b.HasOne("RapidCMS.ModelMaker.Category", "MainCategory") - .WithMany("BlogMainCategory") - .HasForeignKey("MainCategoryId") - .OnDelete(DeleteBehavior.NoAction); - - b.Navigation("MainCategory"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.OnetoManyOne", b => - { - b.HasOne("RapidCMS.ModelMaker.OnetoManyMany", "One") - .WithMany("Many") - .HasForeignKey("OneId") - .OnDelete(DeleteBehavior.NoAction); - - b.Navigation("One"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.OnetoOneOneA", b => - { - b.HasOne("RapidCMS.ModelMaker.OnetoOneOneB", "B") - .WithOne("A") - .HasForeignKey("RapidCMS.ModelMaker.OnetoOneOneA", "BId") - .OnDelete(DeleteBehavior.NoAction); - - b.Navigation("B"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.Category", b => - { - b.Navigation("BlogMainCategory"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.OnetoManyMany", b => - { - b.Navigation("Many"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.OnetoOneOneB", b => - { - b.Navigation("A"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/examples/RapidCMS.Example.ModelMaker.Models/Migrations/20211025050720_ContentType.cs b/examples/RapidCMS.Example.ModelMaker.Models/Migrations/20211025050720_ContentType.cs deleted file mode 100644 index 591d3cb8..00000000 --- a/examples/RapidCMS.Example.ModelMaker.Models/Migrations/20211025050720_ContentType.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace RapidCMS.Example.ModelMaker.Models.Migrations -{ - public partial class ContentType : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - - } - } -} diff --git a/examples/RapidCMS.Example.ModelMaker.Models/Migrations/ModelMakerDbContextModelSnapshot.cs b/examples/RapidCMS.Example.ModelMaker.Models/Migrations/ModelMakerDbContextModelSnapshot.cs deleted file mode 100644 index d7d58cd9..00000000 --- a/examples/RapidCMS.Example.ModelMaker.Models/Migrations/ModelMakerDbContextModelSnapshot.cs +++ /dev/null @@ -1,298 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using RapidCMS.ModelMaker; - -#nullable disable - -namespace RapidCMS.Example.ModelMaker.Models.Migrations -{ - [DbContext(typeof(ModelMakerDbContext))] - partial class ModelMakerDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "6.0.0-rc.2.21480.5") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); - - modelBuilder.Entity("BlogCategory", b => - { - b.Property("BlogBlogCategoriesId") - .HasColumnType("int"); - - b.Property("BlogCategoriesId") - .HasColumnType("int"); - - b.HasKey("BlogBlogCategoriesId", "BlogCategoriesId"); - - b.HasIndex("BlogCategoriesId"); - - b.ToTable("BlogCategory"); - }); - - modelBuilder.Entity("ManytoManyManyAManytoManyManyB", b => - { - b.Property("AsId") - .HasColumnType("int"); - - b.Property("BsId") - .HasColumnType("int"); - - b.HasKey("AsId", "BsId"); - - b.HasIndex("BsId"); - - b.ToTable("ManytoManyManyAManytoManyManyB"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.Blog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Content") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("IsPublished") - .HasColumnType("bit"); - - b.Property("MainCategoryId") - .HasColumnType("int"); - - b.Property("PublishDate") - .HasColumnType("datetime2"); - - b.Property("Title") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Type") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("MainCategoryId"); - - b.ToTable("Blogs"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.Category", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Categories"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.ManytoManyManyA", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("ManytoManyManyAs"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.ManytoManyManyB", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("ManytoManyManyBs"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.OnetoManyMany", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("OnetoManyManys"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.OnetoManyOne", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("OneId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("OneId"); - - b.ToTable("OnetoManyOnes"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.OnetoOneOneA", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("BId") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("BId") - .IsUnique() - .HasFilter("[BId] IS NOT NULL"); - - b.ToTable("OnetoOneOneAs"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.OnetoOneOneB", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("OnetoOneOneBs"); - }); - - modelBuilder.Entity("BlogCategory", b => - { - b.HasOne("RapidCMS.ModelMaker.Blog", null) - .WithMany() - .HasForeignKey("BlogBlogCategoriesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("RapidCMS.ModelMaker.Category", null) - .WithMany() - .HasForeignKey("BlogCategoriesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("ManytoManyManyAManytoManyManyB", b => - { - b.HasOne("RapidCMS.ModelMaker.ManytoManyManyA", null) - .WithMany() - .HasForeignKey("AsId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("RapidCMS.ModelMaker.ManytoManyManyB", null) - .WithMany() - .HasForeignKey("BsId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.Blog", b => - { - b.HasOne("RapidCMS.ModelMaker.Category", "MainCategory") - .WithMany("BlogMainCategory") - .HasForeignKey("MainCategoryId") - .OnDelete(DeleteBehavior.NoAction); - - b.Navigation("MainCategory"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.OnetoManyOne", b => - { - b.HasOne("RapidCMS.ModelMaker.OnetoManyMany", "One") - .WithMany("Many") - .HasForeignKey("OneId") - .OnDelete(DeleteBehavior.NoAction); - - b.Navigation("One"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.OnetoOneOneA", b => - { - b.HasOne("RapidCMS.ModelMaker.OnetoOneOneB", "B") - .WithOne("A") - .HasForeignKey("RapidCMS.ModelMaker.OnetoOneOneA", "BId") - .OnDelete(DeleteBehavior.NoAction); - - b.Navigation("B"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.Category", b => - { - b.Navigation("BlogMainCategory"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.OnetoManyMany", b => - { - b.Navigation("Many"); - }); - - modelBuilder.Entity("RapidCMS.ModelMaker.OnetoOneOneB", b => - { - b.Navigation("A"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/examples/RapidCMS.Example.ModelMaker.Models/RapidCMS.Example.ModelMaker.Models.csproj b/examples/RapidCMS.Example.ModelMaker.Models/RapidCMS.Example.ModelMaker.Models.csproj deleted file mode 100644 index 40f53db6..00000000 --- a/examples/RapidCMS.Example.ModelMaker.Models/RapidCMS.Example.ModelMaker.Models.csproj +++ /dev/null @@ -1,46 +0,0 @@ - - - - net6.0 - enable - - - - - - - - - - - - - - - - - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - - - - diff --git a/examples/RapidCMS.Example.ModelMaker.Models/RapidModels/modelmaker.blogs.json b/examples/RapidCMS.Example.ModelMaker.Models/RapidModels/modelmaker.blogs.json deleted file mode 100644 index ebee4abb..00000000 --- a/examples/RapidCMS.Example.ModelMaker.Models/RapidModels/modelmaker.blogs.json +++ /dev/null @@ -1,284 +0,0 @@ -{ - "$type": "RapidCMS.ModelMaker.Models.Entities.ModelEntity, RapidCMS.ModelMaker", - "Id": "blogs", - "ParentId": null, - "Name": "Blog", - "PluralName": "Blogs", - "IconColor": "Cyan30", - "Icon": "Blog", - "Alias": "blogs", - "Output": "Entity, Collection, Repository, Context, Validation", - "Properties": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "a613c87e-1d94-4a93-b8c3-afc7f93ceeec", - "Name": "Title", - "IsTitle": true, - "IncludeInListView": false, - "IsRequired": false, - "PropertyAlias": "shortstring", - "EditorAlias": "textbox", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.MinLengthDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "bc3a23e2-6be8-4e9e-ae99-1737fc365868", - "Alias": "minlength", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.MinLengthDetailConfig, RapidCMS.ModelMaker", - "MinLength": 1, - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": "MinimumLength", - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.MaxLengthDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "267dedbb-7667-4dab-a3c4-18c1d63dc6d2", - "Alias": "maxlength", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.MaxLengthDetailConfig, RapidCMS.ModelMaker", - "MaxLength": 127, - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": "MaximumLength", - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.Example.ModelMaker.Models.Validators.BannedContentValidationConfig, RapidCMS.Example.ModelMaker.Models]], RapidCMS.ModelMaker", - "Id": "3c3a802f-0b1a-48de-9d73-426b96178a84", - "Alias": "bannedContent", - "Config": { - "$type": "RapidCMS.Example.ModelMaker.Models.Validators.BannedContentValidationConfig, RapidCMS.Example.ModelMaker.Models", - "BannedWords": { - "$type": "System.Collections.Generic.List`1[[System.String, System.Private.CoreLib]], System.Private.CoreLib", - "$values": [ - "a", - "b", - "c" - ] - }, - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "DataCollectionExpression": null, - "ValidationMethodName": "BannedContent", - "DataCollectionType": null - } - } - ] - }, - "Type": "System.String", - "IsRelationToOne": false, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.TextBoxEditor" - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "bdc39e0c-53ec-4106-b373-babe19d5202d", - "Name": "Content", - "IsTitle": false, - "IncludeInListView": true, - "IsRequired": false, - "PropertyAlias": "longstring", - "EditorAlias": "textarea", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [] - }, - "Type": "System.String", - "IsRelationToOne": false, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.TextAreaEditor" - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "f048d0f0-4d82-48a1-86b2-2d98d98c4a0f", - "Name": "Type", - "IsTitle": false, - "IncludeInListView": false, - "IsRequired": false, - "PropertyAlias": "contentType", - "EditorAlias": "dropdown", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.DataCollectionConfig`1[[RapidCMS.Core.Providers.EnumDataProvider`1[[RapidCMS.Example.ModelMaker.Models.Enums.ContentType, RapidCMS.Example.ModelMaker.Models]], RapidCMS.Core]], RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "2f38b24e-a1ea-43e7-a134-83b1dca3311a", - "Alias": "contentTypeValidator", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.DataCollectionConfig`1[[RapidCMS.Core.Providers.EnumDataProvider`1[[RapidCMS.Example.ModelMaker.Models.Enums.ContentType, RapidCMS.Example.ModelMaker.Models]], RapidCMS.Core]], RapidCMS.ModelMaker", - "IsEnabled": true, - "AlwaysIncluded": true, - "RelatedCollectionAlias": null, - "ValidationMethodName": null, - "DataCollectionType": "RapidCMS.Core.Providers.EnumDataProvider`1[[RapidCMS.Example.ModelMaker.Models.Enums.ContentType, RapidCMS.Example.ModelMaker.Models, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]" - } - } - ] - }, - "Type": "RapidCMS.Example.ModelMaker.Models.Enums.ContentType", - "IsRelationToOne": false, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.DropdownEditor" - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "0ac86254-34f7-4d9d-96d8-e60acb888837", - "Name": "Is Published", - "IsTitle": false, - "IncludeInListView": false, - "IsRequired": true, - "PropertyAlias": "boolean", - "EditorAlias": "dropdown", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.BooleanLabelDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "ab61dc5d-ed1c-4cc5-a9f3-c05f557ffbb0", - "Alias": "booleanLabels", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.BooleanLabelDetailConfig, RapidCMS.ModelMaker", - "Labels": { - "$type": "RapidCMS.ModelMaker.Validation.Config.BooleanLabelDetailConfig+LabelsConfig, RapidCMS.ModelMaker", - "TrueLabel": "True", - "FalseLabel": "False" - }, - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "DataCollectionType": "RapidCMS.ModelMaker.DataCollections.BooleanLabelDataCollection", - "ValidationMethodName": null - } - } - ] - }, - "Type": "System.Boolean", - "IsRelationToOne": false, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.DropdownEditor" - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "363423fe-3e3c-4ca3-b458-ea3255699357", - "Name": "Publish Date", - "IsTitle": false, - "IncludeInListView": false, - "IsRequired": true, - "PropertyAlias": "date", - "EditorAlias": "date", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [] - }, - "Type": "System.DateTime", - "IsRelationToOne": false, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.DateEditor" - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "6f0e59b0-6331-4c82-8af0-3daa5cf149b8", - "Name": "Main Category", - "IsTitle": false, - "IncludeInListView": false, - "IsRequired": true, - "PropertyAlias": "linkedentity", - "EditorAlias": "entitypicker", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.LinkedEntityDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "d2cf374d-0ce8-433c-a2b4-398baaa24f5c", - "Alias": "linkedEntity", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.LinkedEntityDetailConfig, RapidCMS.ModelMaker", - "LinkedEntityCollectionAlias": "categories", - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": "categories", - "ValidationMethodName": null, - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "f204aaa6-9158-403d-83d6-ed35a03dca1f", - "Alias": "reciprocal", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker", - "RelatedPropertyName": null, - "IsEnabled": false, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": null, - "DataCollectionType": null - } - } - ] - }, - "Type": "RapidCMS.ModelMaker.Category", - "IsRelationToOne": true, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.EntityPicker" - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "80221276-0404-44f3-ad4b-524b73fa81ac", - "Name": "Blog Categories", - "IsTitle": false, - "IncludeInListView": false, - "IsRequired": false, - "PropertyAlias": "linkedentities", - "EditorAlias": "entitiespicker", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.LinkedEntitiesDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "2855b532-bbe7-4173-b08d-7001db04b9bf", - "Alias": "linkedEntities", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.LinkedEntitiesDetailConfig, RapidCMS.ModelMaker", - "LinkedEntitiesCollectionAlias": "categories", - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": "categories", - "ValidationMethodName": null, - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "f426387c-5fd1-46b6-9fc4-14e2808685e3", - "Alias": "reciprocal", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker", - "RelatedPropertyName": null, - "IsEnabled": false, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": null, - "DataCollectionType": null - } - } - ] - }, - "Type": "RapidCMS.ModelMaker.Category", - "IsRelationToOne": false, - "IsRelationToMany": true, - "EditorType": "RapidCMS.UI.Components.Editors.EntitiesPicker" - } - ] - } -} \ No newline at end of file diff --git a/examples/RapidCMS.Example.ModelMaker.Models/RapidModels/modelmaker.categories.json b/examples/RapidCMS.Example.ModelMaker.Models/RapidModels/modelmaker.categories.json deleted file mode 100644 index 8899daa1..00000000 --- a/examples/RapidCMS.Example.ModelMaker.Models/RapidModels/modelmaker.categories.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "$type": "RapidCMS.ModelMaker.Models.Entities.ModelEntity, RapidCMS.ModelMaker", - "Id": "categories", - "ParentId": null, - "Name": "Category", - "PluralName": "Categories", - "IconColor": "RedOrange10", - "Icon": "Tag", - "Alias": "categories", - "Output": "Entity, Collection, Repository, Context, Validation", - "Properties": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "a7493699-0e57-43da-bb58-a505b779a8fc", - "Name": "Name", - "IsTitle": true, - "IncludeInListView": false, - "IsRequired": true, - "PropertyAlias": "shortstring", - "EditorAlias": "textbox", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.MinLengthDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "817858b0-708a-4d99-b28a-0098a2c0b180", - "Alias": "minlength", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.MinLengthDetailConfig, RapidCMS.ModelMaker", - "MinLength": 1, - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": "MinimumLength", - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.MaxLengthDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "b164d80b-0f48-44f9-9ff5-ff732204bf05", - "Alias": "maxlength", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.MaxLengthDetailConfig, RapidCMS.ModelMaker", - "MaxLength": 30, - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": "MaximumLength", - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.Example.ModelMaker.Models.Validators.BannedContentValidationConfig, RapidCMS.Example.ModelMaker.Models]], RapidCMS.ModelMaker", - "Id": "7c98b180-9c72-4d66-b753-b24868b8d9b8", - "Alias": "bannedContent", - "Config": { - "$type": "RapidCMS.Example.ModelMaker.Models.Validators.BannedContentValidationConfig, RapidCMS.Example.ModelMaker.Models", - "BannedWords": { - "$type": "System.Collections.Generic.List`1[[System.String, System.Private.CoreLib]], System.Private.CoreLib", - "$values": [] - }, - "IsEnabled": false, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "DataCollectionExpression": null, - "ValidationMethodName": "BannedContent", - "DataCollectionType": null - } - } - ] - }, - "Type": "System.String", - "IsRelationToOne": false, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.TextBoxEditor" - } - ] - } -} \ No newline at end of file diff --git a/examples/RapidCMS.Example.ModelMaker.Models/RapidModels/modelmaker.many-to-many-many-as.json b/examples/RapidCMS.Example.ModelMaker.Models/RapidModels/modelmaker.many-to-many-many-as.json deleted file mode 100644 index 674e7ca1..00000000 --- a/examples/RapidCMS.Example.ModelMaker.Models/RapidModels/modelmaker.many-to-many-many-as.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "$type": "RapidCMS.ModelMaker.Models.Entities.ModelEntity, RapidCMS.ModelMaker", - "Id": "many-to-many-many-as", - "ParentId": null, - "Name": "Many to Many - Many A", - "PluralName": "Many to Many - Many As", - "IconColor": "PinkRed10", - "Icon": "Database", - "Alias": "many-to-many-many-as", - "Output": "Entity, Collection, Repository, Context, Validation", - "Properties": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "c410ac52-7c6e-45db-9170-976c1b48ba94", - "Name": "Name", - "IsTitle": true, - "IncludeInListView": false, - "IsRequired": false, - "PropertyAlias": "shortstring", - "EditorAlias": "textbox", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [] - }, - "Type": "System.String", - "IsRelationToOne": false, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.TextBoxEditor" - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "f863a088-40cf-4646-be17-b01382de82ea", - "Name": "Bs", - "IsTitle": false, - "IncludeInListView": false, - "IsRequired": false, - "PropertyAlias": "linkedentities", - "EditorAlias": "entitiespicker", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.LinkedEntitiesDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "7e5c1c5b-ace4-4e02-bbc8-1a010d73549c", - "Alias": "linkedEntities", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.LinkedEntitiesDetailConfig, RapidCMS.ModelMaker", - "LinkedEntitiesCollectionAlias": "many-to-many-many-bs", - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": "many-to-many-many-bs", - "ValidationMethodName": null, - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "0e5fb6fc-f17c-4c3b-adb9-fa50085dcd32", - "Alias": "reciprocal", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker", - "RelatedPropertyName": "As", - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": null, - "DataCollectionType": null - } - } - ] - }, - "Type": "RapidCMS.ModelMaker.ManytoManyManyB", - "IsRelationToOne": false, - "IsRelationToMany": true, - "EditorType": "RapidCMS.UI.Components.Editors.EntitiesPicker" - } - ] - } -} \ No newline at end of file diff --git a/examples/RapidCMS.Example.ModelMaker.Models/RapidModels/modelmaker.many-to-many-many-bs.json b/examples/RapidCMS.Example.ModelMaker.Models/RapidModels/modelmaker.many-to-many-many-bs.json deleted file mode 100644 index d4571845..00000000 --- a/examples/RapidCMS.Example.ModelMaker.Models/RapidModels/modelmaker.many-to-many-many-bs.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "$type": "RapidCMS.ModelMaker.Models.Entities.ModelEntity, RapidCMS.ModelMaker", - "Id": "many-to-many-many-bs", - "ParentId": null, - "Name": "Many to Many - Many B", - "PluralName": "Many to Many - Many Bs", - "IconColor": "PinkRed10", - "Icon": "Database", - "Alias": "many-to-many-many-bs", - "Output": "Entity, Collection, Repository, Context, Validation", - "Properties": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "ed05c762-82f4-450f-8195-2dc8410d3d16", - "Name": "Name", - "IsTitle": true, - "IncludeInListView": false, - "IsRequired": false, - "PropertyAlias": "shortstring", - "EditorAlias": "textbox", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [] - }, - "Type": "System.String", - "IsRelationToOne": false, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.TextBoxEditor" - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "d4f4a864-f7d9-4898-badc-f559163cb5bd", - "Name": "As", - "IsTitle": false, - "IncludeInListView": false, - "IsRequired": false, - "PropertyAlias": "linkedentities", - "EditorAlias": "entitiespicker", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.LinkedEntitiesDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "5748822c-8c5c-47d1-af1a-f85cbe32cd8c", - "Alias": "linkedEntities", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.LinkedEntitiesDetailConfig, RapidCMS.ModelMaker", - "LinkedEntitiesCollectionAlias": "many-to-many-many-as", - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": "many-to-many-many-as", - "ValidationMethodName": null, - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "d6ac3b46-d528-4a39-bac3-1e7bee0a7a3d", - "Alias": "reciprocal", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker", - "RelatedPropertyName": "Bs", - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": null, - "DataCollectionType": null - } - } - ] - }, - "Type": "RapidCMS.ModelMaker.ManytoManyManyA", - "IsRelationToOne": false, - "IsRelationToMany": true, - "EditorType": "RapidCMS.UI.Components.Editors.EntitiesPicker" - } - ] - } -} \ No newline at end of file diff --git a/examples/RapidCMS.Example.ModelMaker.Models/RapidModels/modelmaker.one-to-many-manys.json b/examples/RapidCMS.Example.ModelMaker.Models/RapidModels/modelmaker.one-to-many-manys.json deleted file mode 100644 index 54d7fe5a..00000000 --- a/examples/RapidCMS.Example.ModelMaker.Models/RapidModels/modelmaker.one-to-many-manys.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "$type": "RapidCMS.ModelMaker.Models.Entities.ModelEntity, RapidCMS.ModelMaker", - "Id": "one-to-many-manys", - "ParentId": null, - "Name": "One to Many - Many", - "PluralName": "One to Many - Manys", - "IconColor": "Cyan30", - "Icon": "Database", - "Alias": "one-to-many-manys", - "Output": "Entity, Collection, Repository, Context, Validation", - "Properties": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "bc7cf265-78b8-40d9-9a32-956296ec903f", - "Name": "Name", - "IsTitle": true, - "IncludeInListView": false, - "IsRequired": false, - "PropertyAlias": "shortstring", - "EditorAlias": "textbox", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [] - }, - "Type": "System.String", - "IsRelationToOne": false, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.TextBoxEditor" - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "506b2bf3-1cb9-4a6f-b256-08ee0587eff9", - "Name": "Many", - "IsTitle": false, - "IncludeInListView": false, - "IsRequired": false, - "PropertyAlias": "linkedentities", - "EditorAlias": "entitiespicker", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.LinkedEntitiesDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "27cd54c8-f4da-4a61-ab83-3a53c8dc6a27", - "Alias": "linkedEntities", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.LinkedEntitiesDetailConfig, RapidCMS.ModelMaker", - "LinkedEntitiesCollectionAlias": "one-to-many-ones", - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": "one-to-many-ones", - "ValidationMethodName": null, - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "3efbf6bd-43c1-46dc-8b6d-9b7505b20955", - "Alias": "reciprocal", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker", - "RelatedPropertyName": "One", - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": null, - "DataCollectionType": null - } - } - ] - }, - "Type": "RapidCMS.ModelMaker.OnetoManyOne", - "IsRelationToOne": false, - "IsRelationToMany": true, - "EditorType": "RapidCMS.UI.Components.Editors.EntitiesPicker" - } - ] - } -} \ No newline at end of file diff --git a/examples/RapidCMS.Example.ModelMaker.Models/RapidModels/modelmaker.one-to-many-ones.json b/examples/RapidCMS.Example.ModelMaker.Models/RapidModels/modelmaker.one-to-many-ones.json deleted file mode 100644 index a7c39dfa..00000000 --- a/examples/RapidCMS.Example.ModelMaker.Models/RapidModels/modelmaker.one-to-many-ones.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "$type": "RapidCMS.ModelMaker.Models.Entities.ModelEntity, RapidCMS.ModelMaker", - "Id": "one-to-many-ones", - "ParentId": null, - "Name": "One to Many - One", - "PluralName": "One to Many - Ones", - "IconColor": "Cyan30", - "Icon": "Database", - "Alias": "one-to-many-ones", - "Output": "Entity, Collection, Repository, Context, Validation", - "Properties": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "bba63203-9d39-42a7-9b3e-80778d386ac3", - "Name": "Name", - "IsTitle": true, - "IncludeInListView": false, - "IsRequired": false, - "PropertyAlias": "shortstring", - "EditorAlias": "textbox", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [] - }, - "Type": "System.String", - "IsRelationToOne": false, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.TextBoxEditor" - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "8a605348-8956-4d97-a907-fa6a6e89f686", - "Name": "One", - "IsTitle": false, - "IncludeInListView": false, - "IsRequired": false, - "PropertyAlias": "linkedentity", - "EditorAlias": "entitypicker", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.LinkedEntityDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "f3fd7215-458d-46fd-a308-82f04b188432", - "Alias": "linkedEntity", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.LinkedEntityDetailConfig, RapidCMS.ModelMaker", - "LinkedEntityCollectionAlias": "one-to-many-manys", - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": "one-to-many-manys", - "ValidationMethodName": null, - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "de861ea1-89d8-42a9-986d-6f5b172123b8", - "Alias": "reciprocal", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker", - "RelatedPropertyName": "Many", - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": null, - "DataCollectionType": null - } - } - ] - }, - "Type": "RapidCMS.ModelMaker.OnetoManyMany", - "IsRelationToOne": true, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.EntityPicker" - } - ] - } -} \ No newline at end of file diff --git a/examples/RapidCMS.Example.ModelMaker.Models/RapidModels/modelmaker.one-to-one-one-as.json b/examples/RapidCMS.Example.ModelMaker.Models/RapidModels/modelmaker.one-to-one-one-as.json deleted file mode 100644 index 3b46b7ff..00000000 --- a/examples/RapidCMS.Example.ModelMaker.Models/RapidModels/modelmaker.one-to-one-one-as.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "$type": "RapidCMS.ModelMaker.Models.Entities.ModelEntity, RapidCMS.ModelMaker", - "Id": "one-to-one-one-as", - "ParentId": null, - "Name": "One to One - One A", - "PluralName": "One to One - One As", - "IconColor": "Orange10", - "Icon": "Database", - "Alias": "one-to-one-one-as", - "Output": "Entity, Collection, Repository, Context, Validation", - "Properties": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "eee6a34d-dca5-4546-9267-cc00d255099a", - "Name": "Name", - "IsTitle": true, - "IncludeInListView": false, - "IsRequired": false, - "PropertyAlias": "shortstring", - "EditorAlias": "textbox", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [] - }, - "Type": "System.String", - "IsRelationToOne": false, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.TextBoxEditor" - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "e818066b-ceb3-4313-8dae-9b535caed9bc", - "Name": "B", - "IsTitle": false, - "IncludeInListView": false, - "IsRequired": false, - "PropertyAlias": "linkedentity", - "EditorAlias": "entitypicker", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.LinkedEntityDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "822dc83e-6817-4b6f-8e82-d15026db1e9a", - "Alias": "linkedEntity", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.LinkedEntityDetailConfig, RapidCMS.ModelMaker", - "LinkedEntityCollectionAlias": "one-to-one-one-bs", - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": "one-to-one-one-bs", - "ValidationMethodName": null, - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "d9f7abe8-80f4-413c-beab-5517e06e6b0e", - "Alias": "reciprocal", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker", - "RelatedPropertyName": "A", - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": null, - "DataCollectionType": null - } - } - ] - }, - "Type": "RapidCMS.ModelMaker.OnetoOneOneB", - "IsRelationToOne": true, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.EntityPicker" - } - ] - } -} \ No newline at end of file diff --git a/examples/RapidCMS.Example.ModelMaker.Models/RapidModels/modelmaker.one-to-one-one-bs.json b/examples/RapidCMS.Example.ModelMaker.Models/RapidModels/modelmaker.one-to-one-one-bs.json deleted file mode 100644 index 4c0139d9..00000000 --- a/examples/RapidCMS.Example.ModelMaker.Models/RapidModels/modelmaker.one-to-one-one-bs.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "$type": "RapidCMS.ModelMaker.Models.Entities.ModelEntity, RapidCMS.ModelMaker", - "Id": "one-to-one-one-bs", - "ParentId": null, - "Name": "One to One - One B", - "PluralName": "One to One - One Bs", - "IconColor": "Orange10", - "Icon": "Database", - "Alias": "one-to-one-one-bs", - "Output": "Entity, Collection, Repository, Context, Validation", - "Properties": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "08824942-4c3a-404e-b0cd-7c0adce66a2c", - "Name": "Name", - "IsTitle": true, - "IncludeInListView": false, - "IsRequired": false, - "PropertyAlias": "shortstring", - "EditorAlias": "textbox", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [] - }, - "Type": "System.String", - "IsRelationToOne": false, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.TextBoxEditor" - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "525f29ce-6a74-4c08-b471-3ece78d90fb1", - "Name": "A", - "IsTitle": false, - "IncludeInListView": false, - "IsRequired": false, - "PropertyAlias": "linkedentity", - "EditorAlias": "entitypicker", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.LinkedEntityDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "72a6fc06-d85f-4324-bbf8-e51544ff3ea7", - "Alias": "linkedEntity", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.LinkedEntityDetailConfig, RapidCMS.ModelMaker", - "LinkedEntityCollectionAlias": "one-to-one-one-as", - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": "one-to-one-one-as", - "ValidationMethodName": null, - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "cc85f918-792c-4abe-b52c-03218b0987bc", - "Alias": "reciprocal", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker", - "RelatedPropertyName": "B", - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": null, - "DataCollectionType": null - } - } - ] - }, - "Type": "RapidCMS.ModelMaker.OnetoOneOneA", - "IsRelationToOne": true, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.EntityPicker" - } - ] - } -} \ No newline at end of file diff --git a/examples/RapidCMS.Example.ModelMaker.Models/Validators/BannedContentValidationConfig.cs b/examples/RapidCMS.Example.ModelMaker.Models/Validators/BannedContentValidationConfig.cs deleted file mode 100644 index b3796096..00000000 --- a/examples/RapidCMS.Example.ModelMaker.Models/Validators/BannedContentValidationConfig.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using FluentValidation; -using RapidCMS.Core.Extensions; -using RapidCMS.ModelMaker; -using RapidCMS.ModelMaker.Abstractions.Detail; -using RapidCMS.ModelMaker.Models.Entities; - -namespace RapidCMS.Example.ModelMaker.Models.Validators -{ - public class BannedContentValidationConfig : IDetailConfig - { - public List BannedWords { get; set; } = new List(); - - public bool IsEnabled => BannedWords.Any(); - - public bool AlwaysIncluded => false; - - public bool IsApplicable(PropertyModel model) - => model.EditorAlias.In(Constants.Editors.TextBox, Constants.Editors.TextArea); - - public string RelatedCollectionAlias => default; - - public string DataCollectionExpression => default; - - public string ValidationMethodName => "BannedContent"; - - public string DataCollectionType => default; - } - - public static class BannedContentValidator - { - public static IRuleBuilderOptions BannedContent(this IRuleBuilder ruleBuilder, BannedContentValidationConfig config) - { - return ruleBuilder - .Must(value => !config.BannedWords.Any(value.Contains)) - // this error message will be quite offensive if all banned words are displayed like this - .WithMessage($"The value may not contain these words: {string.Join(",", config.BannedWords)}."); - } - } -} diff --git a/examples/RapidCMS.Example.ModelMaker.WebAssembly.API/Program.cs b/examples/RapidCMS.Example.ModelMaker.WebAssembly.API/Program.cs deleted file mode 100644 index 8ac80909..00000000 --- a/examples/RapidCMS.Example.ModelMaker.WebAssembly.API/Program.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Hosting; - -namespace RapidCMS.Example.ModelMaker.WebAssembly.API -{ - public class Program - { - public static void Main(string[] args) - { - CreateHostBuilder(args).Build().Run(); - } - - public static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => - { - webBuilder.UseStartup(); - }); - } -} diff --git a/examples/RapidCMS.Example.ModelMaker.WebAssembly.API/RapidCMS.Example.ModelMaker.WebAssembly.API.csproj b/examples/RapidCMS.Example.ModelMaker.WebAssembly.API/RapidCMS.Example.ModelMaker.WebAssembly.API.csproj deleted file mode 100644 index c7c741f4..00000000 --- a/examples/RapidCMS.Example.ModelMaker.WebAssembly.API/RapidCMS.Example.ModelMaker.WebAssembly.API.csproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - net6.0 - enable - ASP.NET Core 6.0 - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - diff --git a/examples/RapidCMS.Example.ModelMaker.WebAssembly.API/Startup.cs b/examples/RapidCMS.Example.ModelMaker.WebAssembly.API/Startup.cs deleted file mode 100644 index 8b4ec2b4..00000000 --- a/examples/RapidCMS.Example.ModelMaker.WebAssembly.API/Startup.cs +++ /dev/null @@ -1,78 +0,0 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using RapidCMS.ModelMaker; - -namespace RapidCMS.Example.ModelMaker.WebAssembly.API -{ - public class Startup - { - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } - - public IConfiguration Configuration { get; } - - // This method gets called by the runtime. Use this method to add services to the container. - public void ConfigureServices(IServiceCollection services) - { - services.AddScoped(); - services.AddScoped(); - - services.AddTransient(); - services.AddTransient(); - - services.AddDbContext( - builder => builder.UseSqlServer(Configuration.GetConnectionString("SqlConnectionString")), - ServiceLifetime.Transient, - ServiceLifetime.Transient); - - services.AddRapidCMSWebApi(config => - { - config.AllowAnonymousUser(); - - config.RegisterEntityValidator(); - config.RegisterEntityValidator(); - - config.RegisterRepository(); - config.RegisterRepository(); - }); - - services.AddCors(); - - services.AddRapidCMSControllers(config => - { - }); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - - app.UseHttpsRedirection(); - app.UseCors(builder => builder - .WithOrigins("https://localhost:5001") - .AllowAnyMethod() - .AllowAnyHeader() - .AllowCredentials()); - - app.UseRouting(); - - app.UseAuthorization(); - - app.UseEndpoints(endpoints => - { - endpoints.MapControllers(); - }); - } - } -} - diff --git a/examples/RapidCMS.Example.ModelMaker.WebAssembly.API/appsettings.Development.json b/examples/RapidCMS.Example.ModelMaker.WebAssembly.API/appsettings.Development.json deleted file mode 100644 index 8983e0fc..00000000 --- a/examples/RapidCMS.Example.ModelMaker.WebAssembly.API/appsettings.Development.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" - } - } -} diff --git a/examples/RapidCMS.Example.ModelMaker.WebAssembly.API/appsettings.json b/examples/RapidCMS.Example.ModelMaker.WebAssembly.API/appsettings.json deleted file mode 100644 index d6168445..00000000 --- a/examples/RapidCMS.Example.ModelMaker.WebAssembly.API/appsettings.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" - } - }, - "AllowedHosts": "*", - "ConnectionStrings": { - "SqlConnectionString": "server=localhost\\sqlexpress;database=ModelMaker;integrated security=true;" - - } -} diff --git a/examples/RapidCMS.Example.ModelMaker.WebAssembly/App.razor b/examples/RapidCMS.Example.ModelMaker.WebAssembly/App.razor deleted file mode 100644 index f47dc967..00000000 --- a/examples/RapidCMS.Example.ModelMaker.WebAssembly/App.razor +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/examples/RapidCMS.Example.ModelMaker.WebAssembly/Program.cs b/examples/RapidCMS.Example.ModelMaker.WebAssembly/Program.cs deleted file mode 100644 index faa66b0d..00000000 --- a/examples/RapidCMS.Example.ModelMaker.WebAssembly/Program.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Components.WebAssembly.Hosting; -using Microsoft.Extensions.DependencyInjection; -using RapidCMS.Core.Repositories; -using RapidCMS.ModelMaker; -using RapidCMS.Repositories.ApiBridge; - -namespace RapidCMS.Example.ModelMaker.WebAssembly -{ - public class Program - { - private static readonly Uri BaseUri = new Uri("https://localhost:5003/api/"); - - public static async Task Main(string[] args) - { - var builder = WebAssemblyHostBuilder.CreateDefault(args); - builder.RootComponents.Add("#app"); - - builder.Services.AddAuthorizationCore(); - - builder.Services.AddModelMakerCoreCollections(); - - builder.Services.AddRapidCMSApiRepository, ApiRepository>(BaseUri); - builder.Services.AddRapidCMSApiRepository, ApiRepository>(BaseUri); - - builder.Services.AddTransient(); - builder.Services.AddTransient(); - - builder.Services.AddRapidCMSWebAssembly(config => - { - config.AllowAnonymousUser(); - - config.Advanced.SemaphoreCount = 5; - - config.AddBlogCollection(); - config.AddCategoryCollection(); - }); - - await builder.Build().RunAsync(); - } - } -} - diff --git a/examples/RapidCMS.Example.ModelMaker.WebAssembly/RapidCMS.Example.ModelMaker.WebAssembly.csproj b/examples/RapidCMS.Example.ModelMaker.WebAssembly/RapidCMS.Example.ModelMaker.WebAssembly.csproj deleted file mode 100644 index f8dc1363..00000000 --- a/examples/RapidCMS.Example.ModelMaker.WebAssembly/RapidCMS.Example.ModelMaker.WebAssembly.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - net6.0 - enable - Blazor WebAssembly - - - - - - - - - - - - - diff --git a/examples/RapidCMS.Example.ModelMaker.WebAssembly/_Imports.razor b/examples/RapidCMS.Example.ModelMaker.WebAssembly/_Imports.razor deleted file mode 100644 index 8a817714..00000000 --- a/examples/RapidCMS.Example.ModelMaker.WebAssembly/_Imports.razor +++ /dev/null @@ -1,9 +0,0 @@ -@using System.Net.Http -@using System.Net.Http.Json -@using Microsoft.AspNetCore.Components.Forms -@using Microsoft.AspNetCore.Components.Routing -@using Microsoft.AspNetCore.Components.Web -@using Microsoft.AspNetCore.Components.Web.Virtualization -@using Microsoft.AspNetCore.Components.WebAssembly.Http -@using Microsoft.JSInterop -@using RapidCMS.Example.ModelMaker.WebAssembly diff --git a/examples/RapidCMS.Example.ModelMaker.WebAssembly/wwwroot/index.html b/examples/RapidCMS.Example.ModelMaker.WebAssembly/wwwroot/index.html deleted file mode 100644 index 356dd118..00000000 --- a/examples/RapidCMS.Example.ModelMaker.WebAssembly/wwwroot/index.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - RapidCMS.Example.ModelMaker.WebAssembly - - - - - -
Loading...
- - - - - - diff --git a/examples/RapidCMS.Example.ModelMaker/App.razor b/examples/RapidCMS.Example.ModelMaker/App.razor deleted file mode 100644 index b92e6f5f..00000000 --- a/examples/RapidCMS.Example.ModelMaker/App.razor +++ /dev/null @@ -1 +0,0 @@ - diff --git a/examples/RapidCMS.Example.ModelMaker/Components/CustomTextAreaEditor.razor b/examples/RapidCMS.Example.ModelMaker/Components/CustomTextAreaEditor.razor deleted file mode 100644 index a5e57034..00000000 --- a/examples/RapidCMS.Example.ModelMaker/Components/CustomTextAreaEditor.razor +++ /dev/null @@ -1,15 +0,0 @@ -@inherits BasePropertyEditor - - - -@foreach (var message in GetValidationMessages()) -{ -
- @message -
-} \ No newline at end of file diff --git a/examples/RapidCMS.Example.ModelMaker/Pages/_Host.cshtml b/examples/RapidCMS.Example.ModelMaker/Pages/_Host.cshtml deleted file mode 100644 index c2fb58f8..00000000 --- a/examples/RapidCMS.Example.ModelMaker/Pages/_Host.cshtml +++ /dev/null @@ -1,21 +0,0 @@ -@page "/" -@namespace RapidCMS.Example.ModelMaker -@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers - - - - - - - RapidCMS.Example.ModelMaker - - - - - - @(await Html.RenderComponentAsync(RenderMode.ServerPrerendered)) - - - - - diff --git a/examples/RapidCMS.Example.ModelMaker/Program.cs b/examples/RapidCMS.Example.ModelMaker/Program.cs deleted file mode 100644 index 4811ac04..00000000 --- a/examples/RapidCMS.Example.ModelMaker/Program.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Hosting; - -namespace RapidCMS.Example.ModelMaker -{ - public class Program - { - public static void Main(string[] args) - { - CreateHostBuilder(args).Build().Run(); - } - - public static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => - { - webBuilder.UseStartup(); - }); - } -} diff --git a/examples/RapidCMS.Example.ModelMaker/RapidCMS.Example.ModelMaker.csproj b/examples/RapidCMS.Example.ModelMaker/RapidCMS.Example.ModelMaker.csproj deleted file mode 100644 index 32af0098..00000000 --- a/examples/RapidCMS.Example.ModelMaker/RapidCMS.Example.ModelMaker.csproj +++ /dev/null @@ -1,32 +0,0 @@ - - - - net6.0 - enable - ASP.NET Core 6.0 - 10.0 - - - - - - - - - - - - - - true - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - diff --git a/examples/RapidCMS.Example.ModelMaker/Startup.cs b/examples/RapidCMS.Example.ModelMaker/Startup.cs deleted file mode 100644 index e841b6cf..00000000 --- a/examples/RapidCMS.Example.ModelMaker/Startup.cs +++ /dev/null @@ -1,158 +0,0 @@ -using System.Collections.Generic; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using RapidCMS.Core.Enums; -using RapidCMS.Core.Providers; -using RapidCMS.Core.Repositories; -using RapidCMS.Example.ModelMaker.Components; -using RapidCMS.Example.ModelMaker.Models.Enums; -using RapidCMS.Example.ModelMaker.Models.Validators; -using RapidCMS.Example.Shared.Collections; -using RapidCMS.Example.Shared.Data; -using RapidCMS.ModelMaker; -using RapidCMS.Repositories; - -namespace RapidCMS.Example.ModelMaker -{ - public class Startup - { - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } - - public IConfiguration Configuration { get; } - - public void ConfigureServices(IServiceCollection services) - { - services.AddRazorPages(); - services.AddServerSideBlazor(); - - services.AddModelMaker( - // this flag adds the default properties and validators covering most of the use cases - // each of the features added can also be added manually, to fully control the feature set of the model maker - // (see ConfigurationExtensions.cs of RapidCMS.ModelMaker to see what is added when this flag is true) - addDefaultPropertiesAndValidators: true, - config => - { - config.SetModelFolder("../RapidCMS.Example.ModelMaker.Models/RapidModels/"); - - // extra editors can be inserted easily - var customTextAreaEditor = config.AddPropertyEditor("ctae", "Big textarea"); - - // adding new editors to existing properties is possible - config.GetProperty(Constants.Properties.ShortString)?.Editors.Add(customTextAreaEditor); - - // custom editor validators can be inserted easily - var customTextValidator = config.AddPropertyDetail>( - "bannedContent", - "Banned Content", - "The content is not allowed contain the following words.", - EditorType.ListEditor, - property => property.Config.BannedWords); - - // adding extra validations to existing properties is possible - config.GetProperty(Constants.Properties.ShortString)?.Details.Add(customTextValidator); - config.GetProperty(Constants.Properties.LongString)?.Details.Add(customTextValidator); - - // adding custom properties is also possible - var enumDropdownDetail = config.AddPropertyDetail>( - "contentTypeValidator", - "Content Type", - "Content Type"); - - config.AddProperty( - "contentType", - "Content Type", - "Tag", - new[] { Constants.Editors.Dropdown, Constants.Editors.Select }, - new[] { enumDropdownDetail.Alias }); - }); - - services.AddScoped, JsonRepository>(); - services.AddScoped, JsonRepository
>(); - - services.AddScoped, BlogRepository>(); - services.AddScoped, CategoryRepository>(); - - services.AddScoped, OnetoManyManyRepository>(); - services.AddScoped, OnetoManyOneRepository>(); - - services.AddScoped, ManytoManyManyARepository>(); - services.AddScoped, ManytoManyManyBRepository>(); - - services.AddScoped, OnetoOneOneARepository>(); - services.AddScoped, OnetoOneOneBRepository>(); - - // TODO: add generator to automatically add this to DI - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - - services.AddDbContext( - builder => builder.UseSqlServer(Configuration.GetConnectionString("SqlConnectionString")), - ServiceLifetime.Transient, - ServiceLifetime.Transient); - - services.AddRapidCMSServer(config => - { - config.AllowAnonymousUser(); - - config.SetSiteName("Model maker"); - - config.AddBlogCollection(); - config.AddCategoryCollection(); - - config.AddOnetoManyManyCollection(); - config.AddOnetoManyOneCollection(); - - config.AddManytoManyManyACollection(); - config.AddManytoManyManyBCollection(); - - config.AddOnetoOneOneACollection(); - config.AddOnetoOneOneBCollection(); - - config.AddPersonCollection(); - - config.AddModelMakerPlugin(); - }); - } - - public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ModelMakerDbContext context) - { - context.Database.Migrate(); - - app.UseRapidCMS(isDevelopment: env.IsDevelopment()); - - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - else - { - app.UseExceptionHandler("/Error"); - app.UseHsts(); - } - - app.UseHttpsRedirection(); - app.UseStaticFiles(); - - app.UseRouting(); - - app.UseEndpoints(endpoints => - { - endpoints.MapBlazorHub(); - endpoints.MapFallbackToPage("/_Host"); - }); - } - } -} diff --git a/examples/RapidCMS.Example.ModelMaker/_Imports.razor b/examples/RapidCMS.Example.ModelMaker/_Imports.razor deleted file mode 100644 index 41c0836d..00000000 --- a/examples/RapidCMS.Example.ModelMaker/_Imports.razor +++ /dev/null @@ -1,23 +0,0 @@ -@using System.Net.Http -@using Microsoft.AspNetCore.Http -@using Microsoft.AspNetCore.Components -@using Microsoft.AspNetCore.Components.Authorization -@using Microsoft.AspNetCore.Components.Forms -@using Microsoft.AspNetCore.Components.Routing -@using Microsoft.AspNetCore.Components.Web -@using Microsoft.JSInterop - -@using RapidCMS.Core.Abstractions.Forms -@using RapidCMS.Core.Abstractions.Repositories -@using RapidCMS.Core.Enums -@using RapidCMS.Core.Models.Data - -@using RapidCMS.Repositories - -@using RapidCMS.UI.Components.Displays -@using RapidCMS.UI.Components.Editors -@using RapidCMS.UI.Components.Icons -@using RapidCMS.UI.Components.Panes -@using RapidCMS.UI.Components.Preview -@using RapidCMS.UI.Components.Router -@using RapidCMS.UI.Helpers diff --git a/examples/RapidCMS.Example.ModelMaker/appsettings.Development.json b/examples/RapidCMS.Example.ModelMaker/appsettings.Development.json deleted file mode 100644 index 51737579..00000000 --- a/examples/RapidCMS.Example.ModelMaker/appsettings.Development.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "DetailedErrors": true, - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" - } - } -} diff --git a/examples/RapidCMS.Example.ModelMaker/appsettings.json b/examples/RapidCMS.Example.ModelMaker/appsettings.json deleted file mode 100644 index 81e16b7a..00000000 --- a/examples/RapidCMS.Example.ModelMaker/appsettings.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" - } - }, - "AllowedHosts": "*", - "ConnectionStrings": { - "SqlConnectionString": "server=localhost\\sqlexpress;database=ModelMaker;integrated security=true;" - } -} diff --git a/examples/RapidCMS.Example.Server/Pages/SignIn.cshtml.cs b/examples/RapidCMS.Example.Server/Pages/SignIn.cshtml.cs index 3d7c8ce1..e9acb79b 100644 --- a/examples/RapidCMS.Example.Server/Pages/SignIn.cshtml.cs +++ b/examples/RapidCMS.Example.Server/Pages/SignIn.cshtml.cs @@ -2,16 +2,15 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; -namespace RapidCMS.Example.Server.Pages +namespace RapidCMS.Example.Server.Pages; + +public class SignInModel : PageModel { - public class SignInModel : PageModel + public IActionResult OnGet() { - public IActionResult OnGet() + return Challenge(new AuthenticationProperties { - return Challenge(new AuthenticationProperties - { - RedirectUri = Url.Content("~/") - }, "OpenIdConnect"); - } + RedirectUri = Url.Content("~/") + }, "OpenIdConnect"); } } diff --git a/examples/RapidCMS.Example.Server/Pages/SignOut.cshtml.cs b/examples/RapidCMS.Example.Server/Pages/SignOut.cshtml.cs index c07ddc41..7ccbd0f7 100644 --- a/examples/RapidCMS.Example.Server/Pages/SignOut.cshtml.cs +++ b/examples/RapidCMS.Example.Server/Pages/SignOut.cshtml.cs @@ -2,16 +2,15 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; -namespace RapidCMS.Example.Server.Pages +namespace RapidCMS.Example.Server.Pages; + +public class SignOutModel : PageModel { - public class SignOutModel : PageModel + public IActionResult OnGet() { - public IActionResult OnGet() + return SignOut(new AuthenticationProperties { - return SignOut(new AuthenticationProperties - { - RedirectUri = Url.Content("~/") - }, "Cookies", "OpenIdConnect"); - } + RedirectUri = Url.Content("~/") + }, "Cookies", "OpenIdConnect"); } } diff --git a/examples/RapidCMS.Example.Server/Program.cs b/examples/RapidCMS.Example.Server/Program.cs index 13203a95..dc58e52a 100644 --- a/examples/RapidCMS.Example.Server/Program.cs +++ b/examples/RapidCMS.Example.Server/Program.cs @@ -1,20 +1,19 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Hosting; -namespace RapidCMS.Example.Server +namespace RapidCMS.Example.Server; + +public class Program { - public class Program + public static void Main(string[] args) { - public static void Main(string[] args) - { - CreateHostBuilder(args).Build().Run(); - } - - public static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => - { - webBuilder.UseStartup(); - }); + CreateHostBuilder(args).Build().Run(); } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); } diff --git a/examples/RapidCMS.Example.Server/RapidCMS.Example.Server.csproj b/examples/RapidCMS.Example.Server/RapidCMS.Example.Server.csproj index 0f682efa..76354dcf 100644 --- a/examples/RapidCMS.Example.Server/RapidCMS.Example.Server.csproj +++ b/examples/RapidCMS.Example.Server/RapidCMS.Example.Server.csproj @@ -1,9 +1,9 @@  - net6.0 + net8.0 enable - ASP.NET Core 6.0 Razor Pages + ASP.NET Core 8.0 Razor Pages 10.0 @@ -11,6 +11,10 @@ + + + + diff --git a/examples/RapidCMS.Example.Server/Startup.cs b/examples/RapidCMS.Example.Server/Startup.cs index c34fc772..6d3a50de 100644 --- a/examples/RapidCMS.Example.Server/Startup.cs +++ b/examples/RapidCMS.Example.Server/Startup.cs @@ -17,170 +17,168 @@ using RapidCMS.Example.Shared.Validators; using RapidCMS.Repositories; -namespace RapidCMS.Example.Server +namespace RapidCMS.Example.Server; + +public class Startup { - public class Startup + private const bool ConfigureAuthentication = false; + + public Startup(IConfiguration configuration) { - private const bool ConfigureAuthentication = false; + Configuration = configuration; + } - public Startup(IConfiguration configuration) + public IConfiguration Configuration { get; } + + // This method gets called by the runtime. Use this method to add services to the container. + // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 + public void ConfigureServices(IServiceCollection services) + { + services.AddRazorPages(); + services.AddServerSideBlazor(); + + // it's not required to add your repositories under the base repository + // but this allows the Server and the WebAssembly examples to share the collection configuration + services.AddScoped, JsonRepository>(); + services.AddScoped, JsonRepository
>(); + services.AddScoped, JsonRepository>(); + services.AddScoped, JsonRepository>(); + services.AddScoped, JsonRepository>(); + services.AddScoped, JsonRepository>(); + services.AddScoped, JsonRepository>(); + services.AddScoped, InMemoryRepository>(); + services.AddScoped, CounterRepository>(); + + services.AddScoped, MappedInMemoryRepository>(); + services.AddSingleton, Mapper>(); + services.AddSingleton(); + + services.AddSingleton(); + services.AddScoped(); + services.AddTransient(); + + // the country entity is validated by a FluentValidator + services.AddSingleton(); + + // although it's not required to add your own interfaces to the upload handlers, the Server and WebAssembly examples use the + // same collection configuration, so the DI configuration dictates what handler is used in each case + services.AddSingleton(); + services.AddSingleton(); + + if (ConfigureAuthentication) { - Configuration = configuration; + ConfigureOpenIDConnectAuthentication(services); + services.AddSingleton(); } - public IConfiguration Configuration { get; } - - // This method gets called by the runtime. Use this method to add services to the container. - // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 - public void ConfigureServices(IServiceCollection services) + services.AddRapidCMSServer(config => { - services.AddRazorPages(); - services.AddServerSideBlazor(); - - // it's not required to add your repositories under the base repository - // but this allows the Server and the WebAssembly examples to share the collection configuration - services.AddScoped, JsonRepository>(); - services.AddScoped, JsonRepository
>(); - services.AddScoped, JsonRepository>(); - services.AddScoped, JsonRepository>(); - services.AddScoped, JsonRepository>(); - services.AddScoped, JsonRepository>(); - services.AddScoped, JsonRepository>(); - services.AddScoped, InMemoryRepository>(); - services.AddScoped, CounterRepository>(); - - services.AddScoped, MappedInMemoryRepository>(); - services.AddSingleton, Mapper>(); - services.AddSingleton(); - - services.AddSingleton(); - services.AddScoped(); - services.AddTransient(); - - // the country entity is validated by a FluentValidator - services.AddSingleton(); - - // although it's not required to add your own interfaces to the upload handlers, the Server and WebAssembly examples use the - // same collection configuration, so the DI configuration dictates what handler is used in each case - services.AddSingleton(); - services.AddSingleton(); - - if (ConfigureAuthentication) + if (!ConfigureAuthentication) { - ConfigureOpenIDConnectAuthentication(services); - services.AddSingleton(); + config.AllowAnonymousUser(); } - - services.AddRapidCMSServer(config => + else { - if (!ConfigureAuthentication) - { - config.AllowAnonymousUser(); - } - else - { - config.SetCustomLoginStatus(typeof(LoginStatus)); - config.SetCustomLoginScreen(typeof(LoginScreen)); + config.SetCustomLoginStatus(typeof(LoginStatus)); + config.SetCustomLoginScreen(typeof(LoginScreen)); - // this landing page will be rendered on the dashboard when the dashboard because the user does - // not have access to all of the sections and no other sections are defined on the dashboard - config.SetEmptyLandingPage(typeof(LandingPage)); - } + // this landing page will be rendered on the dashboard when the dashboard because the user does + // not have access to all of the sections and no other sections are defined on the dashboard + config.SetEmptyLandingPage(typeof(LandingPage)); + } + config.EnableDevelopmentLogging(true); - // CRUD editor for simple POCO with recursive sub collections - // --> see Collections/PersonCollection for the basics of this CMS - config.AddPersonCollection(); + // CRUD editor for simple POCO with recursive sub collections + // --> see Collections/PersonCollection for the basics of this CMS + config.AddPersonCollection(); - // CRUD editor with support for one-to-many relation + validation - // --> see Collections/CountryCollection for one-to-many relation with validation - config.AddCountryCollection(); + // CRUD editor with support for one-to-many relation + validation + // --> see Collections/CountryCollection for one-to-many relation with validation + config.AddCountryCollection(); - // Custom page with either custom Blazor components, or ListViews or ListEditors of collections - config.AddPage("TestBeakerSolid", "Green10", "Some random page", config => - { - config.AddSection(typeof(CustomSection)); - config.AddSection("country", edit: false); - }); + // Custom page with either custom Blazor components, or ListViews or ListEditors of collections + config.AddPage("TestBeakerSolid", "Green10", "Some random page", config => + { + config.AddSection(typeof(CustomSection)); + config.AddSection("country", edit: false); + }); - // CRUD editor with validation attributes, custom editor and custom button panes - // --> see Collections/UserCollection - config.AddUserCollection(); + // CRUD editor with validation attributes, custom editor and custom button panes + // --> see Collections/UserCollection + config.AddUserCollection(); - // CRUD editor with nested collection - // --> see Collections/TagCollection - config.AddTagCollection(); + // CRUD editor with nested collection + // --> see Collections/TagCollection + config.AddTagCollection(); - // CRUD editor with entity mapping - config.AddMappedCollection(); + // CRUD editor with entity mapping + config.AddMappedCollection(); - // CRUD editor based on conventions for even more rapid development - config.AddConventionCollection(); + // CRUD editor based on conventions for even more rapid development + config.AddConventionCollection(); - // CRUD editor with entity variants, so multiple types of entities can be mixed in a single collection - config.AddEntityVariantCollection(); + // CRUD editor with entity variants, so multiple types of entities can be mixed in a single collection + config.AddEntityVariantCollection(); - // CRUD editor displaying live data, an external process updates the data every second - config.AddActiveCollection(); + // CRUD editor displaying live data, an external process updates the data every second + config.AddActiveCollection(); - // the dashboard can be build up of custom Blazor components, or the ListViews or ListEditors of collections - config.Dashboard.AddSection(typeof(DashboardSection)); - config.Dashboard.AddSection("user", edit: true); - }); - } + // the dashboard can be build up of custom Blazor components, or the ListViews or ListEditors of collections + config.Dashboard.AddSection(typeof(DashboardSection)); + config.Dashboard.AddSection("user", edit: true); + }); + } - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + else { - app.UseRapidCMS(isDevelopment: env.IsDevelopment()); + app.UseExceptionHandler("/Home/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(); + } - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - else - { - app.UseExceptionHandler("/Home/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.UseHttpsRedirection(); + app.UseStaticFiles(); - app.UseHttpsRedirection(); - app.UseStaticFiles(); + app.UseRouting(); - app.UseRouting(); + app.UseAuthentication(); + app.UseAuthorization(); - app.UseAuthentication(); - app.UseAuthorization(); + app.UseEndpoints(endpoints => + { + endpoints.MapBlazorHub(); + endpoints.MapFallbackToPage("/_Host"); + }); + } - app.UseEndpoints(endpoints => + private void ConfigureOpenIDConnectAuthentication(IServiceCollection services) + { + services + .AddAuthentication(options => { - endpoints.MapBlazorHub(); - endpoints.MapFallbackToPage("/_Host"); - }); - } - - private void ConfigureOpenIDConnectAuthentication(IServiceCollection services) - { - services - .AddAuthentication(options => - { - options.DefaultScheme = "Cookies"; - options.DefaultChallengeScheme = "OpenIdConnect"; - }) - .AddCookie("Cookies") - .AddOpenIdConnect("OpenIdConnect", options => - { - Configuration.Bind("AzureAd", options); + options.DefaultScheme = "Cookies"; + options.DefaultChallengeScheme = "OpenIdConnect"; + }) + .AddCookie("Cookies") + .AddOpenIdConnect("OpenIdConnect", options => + { + Configuration.Bind("AzureAd", options); - IdentityModelEventSource.ShowPII = true; + IdentityModelEventSource.ShowPII = true; - options.Events.OnSignedOutCallbackRedirect = (ctx) => - { - ctx.HandleResponse(); - ctx.Response.Redirect("/"); - return Task.CompletedTask; - }; - }); - } + options.Events.OnSignedOutCallbackRedirect = (ctx) => + { + ctx.HandleResponse(); + ctx.Response.Redirect("/"); + return Task.CompletedTask; + }; + }); } } diff --git a/examples/RapidCMS.Example.Shared/AuthorizationHandlers/VeryPermissiveAuthorizationHandler.cs b/examples/RapidCMS.Example.Shared/AuthorizationHandlers/VeryPermissiveAuthorizationHandler.cs index ebe2fe67..67a59cf6 100644 --- a/examples/RapidCMS.Example.Shared/AuthorizationHandlers/VeryPermissiveAuthorizationHandler.cs +++ b/examples/RapidCMS.Example.Shared/AuthorizationHandlers/VeryPermissiveAuthorizationHandler.cs @@ -3,15 +3,14 @@ using Microsoft.AspNetCore.Authorization.Infrastructure; using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Example.Shared.AuthorizationHandlers +namespace RapidCMS.Example.Shared.AuthorizationHandlers; + +public class VeryPermissiveAuthorizationHandler : AuthorizationHandler { - public class VeryPermissiveAuthorizationHandler : AuthorizationHandler + protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, OperationAuthorizationRequirement requirement, IEntity resource) { - protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, OperationAuthorizationRequirement requirement, IEntity resource) - { - context.Succeed(requirement); + context.Succeed(requirement); - return Task.CompletedTask; - } + return Task.CompletedTask; } } diff --git a/examples/RapidCMS.Example.Shared/Collections/ActiveCollection.cs b/examples/RapidCMS.Example.Shared/Collections/ActiveCollection.cs index c30911b9..27fb6a2e 100644 --- a/examples/RapidCMS.Example.Shared/Collections/ActiveCollection.cs +++ b/examples/RapidCMS.Example.Shared/Collections/ActiveCollection.cs @@ -9,43 +9,42 @@ using RapidCMS.Example.Shared.Data; using RapidCMS.Repositories; -namespace RapidCMS.Example.Shared.Collections +namespace RapidCMS.Example.Shared.Collections; + +public static class ActiveCollection { - public static class ActiveCollection + public static void AddActiveCollection(this ICmsConfig config) { - public static void AddActiveCollection(this ICmsConfig config) + config.AddCollection>("active", "CommentActive", "Cyan30", "Active Counter", collection => { - config.AddCollection>("active", "CommentActive", "Cyan30", "Active Counter", collection => - { - collection - .SetTreeView(x => x.CurrentCount.ToString()) - .ConfigureByConvention(CollectionConvention.ListViewNodeView); - }); - } + collection + .SetTreeView(x => x.CurrentCount.ToString()) + .ConfigureByConvention(CollectionConvention.ListViewNodeView); + }); } +} + +public class CounterRepository : InMemoryRepository +{ + private readonly IMediator _mediator; + private Timer _timer; - public class CounterRepository : InMemoryRepository + public CounterRepository(IMediator mediator, IServiceProvider serviceProvider) : base(mediator, serviceProvider) { - private readonly IMediator _mediator; - private Timer _timer; + GetListForParent(default).Add(new Counter { Id = "1", CurrentCount = 0 }); - public CounterRepository(IMediator mediator, IServiceProvider serviceProvider) : base(mediator, serviceProvider) + _timer = new Timer(x => { - GetListForParent(default).Add(new Counter { Id = "1", CurrentCount = 0 }); + Increase(); - _timer = new Timer(x => - { - Increase(); - - }, default, 400, 400); - _mediator = mediator; - } + }, default, 400, 400); + _mediator = mediator; + } - public void Increase() - { - GetListForParent(default).First().CurrentCount++; + public void Increase() + { + GetListForParent(default).First().CurrentCount++; - _mediator.NotifyEvent(this, new RepositoryEventArgs(GetType(), default, "1", CrudType.Update)); - } + _mediator.NotifyEvent(this, new RepositoryEventArgs(GetType(), default, "1", CrudType.Update)); } } diff --git a/examples/RapidCMS.Example.Shared/Collections/ConventionCollection.cs b/examples/RapidCMS.Example.Shared/Collections/ConventionCollection.cs index 437c1c82..93e1fe32 100644 --- a/examples/RapidCMS.Example.Shared/Collections/ConventionCollection.cs +++ b/examples/RapidCMS.Example.Shared/Collections/ConventionCollection.cs @@ -3,48 +3,47 @@ using RapidCMS.Core.Repositories; using RapidCMS.Example.Shared.Data; -namespace RapidCMS.Example.Shared.Collections +namespace RapidCMS.Example.Shared.Collections; + +public static class ConventionCollection { - public static class ConventionCollection + // CRUD editor for simple POCO based on conventions + public static void AddConventionCollection(this ICmsConfig config) { - // CRUD editor for simple POCO based on conventions - public static void AddConventionCollection(this ICmsConfig config) + config.AddCollection>("person-convention", "Settings", "Green20", "People (by convention)", collection => { - config.AddCollection>("person-convention", "Settings", "Green20", "People (by convention)", collection => - { - collection.SetTreeView(EntityVisibilty.Visible, x => x.Name); - - // The convention system resolves the configuration based on the [Field]-attributes placed on the properties of the model of this collection. - // It uses the EditorTypeHelper.TryFindDefaultEditorType to resolve the best matching editor for the property. - // - // - The ListEditor will display a list editor with columns for every column with a [Field] attribute and use its Name and Description - // for displaying the name and description. - // - // - The ListView+NodeEditor will display a list view with columns for each column with a [Field] attribute with a defined ShortName. - // The corresponding node editor will display an editor with fields for each the properties that sport a [Field] attribute, and uses - // the Name and Description of said attribute. - // - // - The ListView will only display a read only list view without edit options. - collection.ConfigureByConvention(CollectionConvention.ListEditorNodeEditor); - - // There are these combo's that should be used: - - // - collection.SetTreeView(EntityVisibilty.Visible, x => x.Property); - // - collection.ConfigureByConvention(CollectionConvention.ListViewNodeEditor); - - // - collection.SetTreeView(EntityVisibilty.Hidden, x => x.Property); - // - collection.ConfigureByConvention(CollectionConvention.ListView); - - // - collection.SetTreeView(EntityVisibilty.Visible, x => x.Property); - // - collection.ConfigureByConvention(CollectionConvention.ListViewNodeView); - - // - collection.SetTreeView(EntityVisibilty.Hidden, x => x.Property); - // - collection.ConfigureByConvention(CollectionConvention.ListEditor); - - - // Sub collections are added to the node view / node editor when there are collections. - collection.AddSelfAsRecursiveCollection(); - }); - } + collection.SetTreeView(EntityVisibilty.Visible, x => x.Name); + + // The convention system resolves the configuration based on the [Field]-attributes placed on the properties of the model of this collection. + // It uses the EditorTypeHelper.TryFindDefaultEditorType to resolve the best matching editor for the property. + // + // - The ListEditor will display a list editor with columns for every column with a [Field] attribute and use its Name and Description + // for displaying the name and description. + // + // - The ListView+NodeEditor will display a list view with columns for each column with a [Field] attribute with a defined ShortName. + // The corresponding node editor will display an editor with fields for each the properties that sport a [Field] attribute, and uses + // the Name and Description of said attribute. + // + // - The ListView will only display a read only list view without edit options. + collection.ConfigureByConvention(CollectionConvention.ListEditorNodeEditor); + + // There are these combo's that should be used: + + // - collection.SetTreeView(EntityVisibilty.Visible, x => x.Property); + // - collection.ConfigureByConvention(CollectionConvention.ListViewNodeEditor); + + // - collection.SetTreeView(EntityVisibilty.Hidden, x => x.Property); + // - collection.ConfigureByConvention(CollectionConvention.ListView); + + // - collection.SetTreeView(EntityVisibilty.Visible, x => x.Property); + // - collection.ConfigureByConvention(CollectionConvention.ListViewNodeView); + + // - collection.SetTreeView(EntityVisibilty.Hidden, x => x.Property); + // - collection.ConfigureByConvention(CollectionConvention.ListEditor); + + + // Sub collections are added to the node view / node editor when there are collections. + collection.AddSelfAsRecursiveCollection(); + }); } } diff --git a/examples/RapidCMS.Example.Shared/Collections/CountryCollection.cs b/examples/RapidCMS.Example.Shared/Collections/CountryCollection.cs index af95c15d..a2938c2d 100644 --- a/examples/RapidCMS.Example.Shared/Collections/CountryCollection.cs +++ b/examples/RapidCMS.Example.Shared/Collections/CountryCollection.cs @@ -7,144 +7,143 @@ using RapidCMS.Example.Shared.Handlers; using RapidCMS.Example.Shared.Validators; -namespace RapidCMS.Example.Shared.Collections +namespace RapidCMS.Example.Shared.Collections; + +public static class CountryCollection { - public static class CountryCollection + // CRUD editor with support for one-to-many relation + validation + public static void AddCountryCollection(this ICmsConfig config) { - // CRUD editor with support for one-to-many relation + validation - public static void AddCountryCollection(this ICmsConfig config) + config.AddCollection>("country", "Nav2DMapView", "Blue10", "Countries", collection => { - config.AddCollection>("country", "Nav2DMapView", "Blue10", "Countries", collection => - { - // this collection uses a custom validator next to the data annotation validation - collection.AddEntityValidator( - new CountryValidator.Config - { - ForbiddenContinentName = "fdsafdsa", - ForbiddenCountryName = "fdsa" - }); - - collection - // Set showEntities to true to have this collection to fold open on default - .SetTreeView(x => x.Name, showEntitiesOnStartup: false) - .SetListView(view => - { - view.AddDefaultButton(DefaultButtonType.New); - - view.SetPageSize(10); - - view - .AddRow(row => - { - row.AddField(p => p.Id.ToString()) - .SetName("ID").SetType(DisplayType.Pre); + // this collection uses a custom validator next to the data annotation validation + collection.AddEntityValidator( + new CountryValidator.Config + { + ForbiddenContinentName = "fdsafdsa", + ForbiddenCountryName = "fdsa" + }); + + collection + // Set showEntities to true to have this collection to fold open on default + .SetTreeView(x => x.Name, showEntitiesOnStartup: false) + .SetListView(view => + { + view.AddDefaultButton(DefaultButtonType.New); + + view.SetPageSize(10); + + view + .AddRow(row => + { + row.AddField(p => p.Id.ToString()) + .SetName("ID").SetType(DisplayType.Pre); - // by specifying SetOrderExpression you can allow the user to sort the data on that column - // giving it a default order will cause this column to be ordered when the user opens the view - row.AddField(p => p.Name) - .SetOrderByExpression(p => p.Name, OrderByType.Ascending); + // by specifying SetOrderExpression you can allow the user to sort the data on that column + // giving it a default order will cause this column to be ordered when the user opens the view + row.AddField(p => p.Name) + .SetOrderByExpression(p => p.Name, OrderByType.Ascending); - // multiple columns can be ordered at once, and the OrderBys stack from left to right, - // so the Countries in this example will always be first ordered by Name, then by Metadata.Continent - row.AddField(p => p.Metadata.Continent) - .SetOrderByExpression(p => p.Metadata.Continent); + // multiple columns can be ordered at once, and the OrderBys stack from left to right, + // so the Countries in this example will always be first ordered by Name, then by Metadata.Continent + row.AddField(p => p.Metadata.Continent) + .SetOrderByExpression(p => p.Metadata.Continent); - row.AddDefaultButton(DefaultButtonType.Edit); - }); - }) - .SetNodeEditor(editor => + row.AddDefaultButton(DefaultButtonType.Edit); + }); + }) + .SetNodeEditor(editor => + { + editor + // the Up button allows users to get one level up (based upon the tree) + .AddDefaultButton(DefaultButtonType.Up, "Back to list", "Back") + .AddDefaultButton(DefaultButtonType.SaveExisting) + .AddDefaultButton(DefaultButtonType.SaveNew) + .AddDefaultButton(DefaultButtonType.Delete) + + // using navigation buttons can help the user to other pages quickly + .AddNavigationButton("Create new person", "FollowUser", isVisible: (country, state) => state == EntityState.IsExisting); + + editor.AddSection(section => { - editor - // the Up button allows users to get one level up (based upon the tree) - .AddDefaultButton(DefaultButtonType.Up, "Back to list", "Back") - .AddDefaultButton(DefaultButtonType.SaveExisting) - .AddDefaultButton(DefaultButtonType.SaveNew) - .AddDefaultButton(DefaultButtonType.Delete) + section.AddField(x => x.Name); + + section.AddField(x => x.Metadata.Continent); + section.AddField(x => x.Metadata.Tag) + .SetType(EditorType.Dropdown) + // the FixedOptionsDataProvider allows for adding hard-coded options, without requiring a Enum + .SetDataCollection(new FixedOptionsDataProvider( + new[] + { + "Tag A", + "Tag B", + "Tab C" + })); + + // this property contains a list of people it is related to + // you can see it as a ICollection property in EF Core + + // because this property has an RelationValidationAttribute, the CMS first checks if the + // selected values are valid, before allowing the user to save this entity. + // in this example, the user may only select up to two People per Country + + section.AddField(x => x.People) + // a multi-select is a list of checkboxes + .SetType(EditorType.MultiSelect) + // this binds the PersonCollection to this collection + // the CMS must know what the foreign entity and key is, you need to specify it + .SetCollectionRelation( + // this selects which values are used as selected values + people => people.Select(p => p.Id), + // alias of the related collection + "person", + // this callback allows you to specify how the multi-select should look like + relation => + { + relation + // when the user selects an element, the value that is used as Id is used + // to set the value of the property + .SetElementIdProperty(x => x.Id) + + // multiple display properties can be used to display the dropdown, even + // with nested properties + .SetElementDisplayProperties(x => x.Name, x => x.Details.Email); + }); - // using navigation buttons can help the user to other pages quickly - .AddNavigationButton("Create new person", "FollowUser", isVisible: (country, state) => state == EntityState.IsExisting); + section.AddField(x => x.FlagColors) + // a multi-select is a list of checkboxes + .SetType(EditorType.MultiSelect) + // this bind the multi-select to a relation data provider that + // is used as storage for the multi-select editor + .SetCollectionRelation>(); + }); - editor.AddSection(section => - { - section.AddField(x => x.Name); - - section.AddField(x => x.Metadata.Continent); - section.AddField(x => x.Metadata.Tag) - .SetType(EditorType.Dropdown) - // the FixedOptionsDataProvider allows for adding hard-coded options, without requiring a Enum - .SetDataCollection(new FixedOptionsDataProvider( - new[] - { - "Tag A", - "Tag B", - "Tab C" - })); - - // this property contains a list of people it is related to - // you can see it as a ICollection property in EF Core - - // because this property has an RelationValidationAttribute, the CMS first checks if the - // selected values are valid, before allowing the user to save this entity. - // in this example, the user may only select up to two People per Country - - section.AddField(x => x.People) - // a multi-select is a list of checkboxes - .SetType(EditorType.MultiSelect) - // this binds the PersonCollection to this collection - // the CMS must know what the foreign entity and key is, you need to specify it - .SetCollectionRelation( - // this selects which values are used as selected values - people => people.Select(p => p.Id), - // alias of the related collection - "person", - // this callback allows you to specify how the multi-select should look like - relation => - { - relation - // when the user selects an element, the value that is used as Id is used - // to set the value of the property - .SetElementIdProperty(x => x.Id) - - // multiple display properties can be used to display the dropdown, even - // with nested properties - .SetElementDisplayProperties(x => x.Name, x => x.Details.Email); - }); - - section.AddField(x => x.FlagColors) - // a multi-select is a list of checkboxes - .SetType(EditorType.MultiSelect) - // this bind the multi-select to a relation data provider that - // is used as storage for the multi-select editor - .SetCollectionRelation>(); - }); + editor.AddSection(section => + { + section.SetLabel("Related people"); - editor.AddSection(section => + section.AddRelatedCollectionList>(relation => { - section.SetLabel("Related people"); - - section.AddRelatedCollectionList>(relation => + relation.SetListEditor(editor => { - relation.SetListEditor(editor => + editor.AddDefaultButton(DefaultButtonType.Return); + editor.AddDefaultButton(DefaultButtonType.Add); + editor.AddDefaultButton(DefaultButtonType.New); + + editor.AddSection(row => { - editor.AddDefaultButton(DefaultButtonType.Return); - editor.AddDefaultButton(DefaultButtonType.Add); - editor.AddDefaultButton(DefaultButtonType.New); - - editor.AddSection(row => - { - row.AddField(x => x.Name); - - row.AddDefaultButton(DefaultButtonType.Pick); - row.AddDefaultButton(DefaultButtonType.Remove); - row.AddDefaultButton(DefaultButtonType.SaveExisting); - row.AddDefaultButton(DefaultButtonType.SaveNew); - row.AddDefaultButton(DefaultButtonType.Delete); - }); + row.AddField(x => x.Name); + + row.AddDefaultButton(DefaultButtonType.Pick); + row.AddDefaultButton(DefaultButtonType.Remove); + row.AddDefaultButton(DefaultButtonType.SaveExisting); + row.AddDefaultButton(DefaultButtonType.SaveNew); + row.AddDefaultButton(DefaultButtonType.Delete); }); }); }); }); - }); - } + }); + }); } } diff --git a/examples/RapidCMS.Example.Shared/Collections/EntityVariantCollection.cs b/examples/RapidCMS.Example.Shared/Collections/EntityVariantCollection.cs index 7c33c3d3..26b9fd07 100644 --- a/examples/RapidCMS.Example.Shared/Collections/EntityVariantCollection.cs +++ b/examples/RapidCMS.Example.Shared/Collections/EntityVariantCollection.cs @@ -3,120 +3,119 @@ using RapidCMS.Core.Repositories; using RapidCMS.Example.Shared.Data; -namespace RapidCMS.Example.Shared.Collections +namespace RapidCMS.Example.Shared.Collections; + +public static class EntityVariantCollection { - public static class EntityVariantCollection + // CRUD editor with support for + public static void AddEntityVariantCollection(this ICmsConfig config) { - // CRUD editor with support for - public static void AddEntityVariantCollection(this ICmsConfig config) + config.AddCollection>("variants", "ProductVariant", "OrangeYellow20", "Entity Variants", collection => { - config.AddCollection>("variants", "ProductVariant", "OrangeYellow20", "Entity Variants", collection => - { - collection - // Set showEntities to true to have this collection to fold open on default - .SetTreeView(x => x.Name, showEntitiesOnStartup: true) - - // entity variants must be based of the same base type, but can introduce form elements for specialized cases - .AddEntityVariant("Variant A", "a") - .AddEntityVariant("Variant B", "b") - .AddEntityVariant("Variant C", "c") - .SetListEditor(view => - { - view.AddDefaultButton(DefaultButtonType.New, label: "New {0}"); - view.AddDefaultButton(DefaultButtonType.Return); - - view.SetColumnVisibility(EmptyVariantColumnVisibility.Collapse); - - view.SetPageSize(10); - - view - .AddSection(section => - { - section.AddField(p => p.Id); - - section.AddField(p => p.Name) - .SetOrderByExpression(p => p.Name, OrderByType.Ascending); - }) - .AddSection(section => - { - section.AddField(p => p.Id); - - section.AddField(p => p.Name) - .SetOrderByExpression(p => p.Name, OrderByType.Ascending); - - section.AddField(p => p.NameA1); - - section.AddDefaultButton(DefaultButtonType.SaveExisting); - section.AddDefaultButton(DefaultButtonType.SaveNew); - section.AddDefaultButton(DefaultButtonType.Edit); - }) - .AddSection(section => - { - section.AddField(p => p.Id); - - section.AddField(p => p.Name) - .SetOrderByExpression(p => p.Name, OrderByType.Ascending); - - section.AddField(p => p.NameB1); - section.AddField(p => p.NameB2); - - section.AddDefaultButton(DefaultButtonType.SaveExisting); - section.AddDefaultButton(DefaultButtonType.SaveNew); - section.AddDefaultButton(DefaultButtonType.Edit); - }) - .AddSection(section => - { - section.AddField(p => p.Id); - - section.AddField(p => p.Name) - .SetOrderByExpression(p => p.Name, OrderByType.Ascending); - - section.AddField(p => p.NameC1); - section.AddField(p => p.NameC2); - section.AddField(p => p.NameC3); - - section.AddDefaultButton(DefaultButtonType.SaveExisting); - section.AddDefaultButton(DefaultButtonType.SaveNew); - section.AddDefaultButton(DefaultButtonType.Edit); - }); - }) - .SetNodeEditor(editor => - { - editor.AddDefaultButton(DefaultButtonType.Up); - editor.AddDefaultButton(DefaultButtonType.SaveNew); - editor.AddDefaultButton(DefaultButtonType.SaveExisting); - - editor - .AddSection(generic => - { - generic.SetLabel("Generics"); - - generic.AddField(x => x.Id).SetType(DisplayType.Pre); - generic.AddField(x => x.Name); - }) - .AddSection(a => - { - a.SetLabel("Variant A specifics"); - - a.AddField(x => x.NameA1); - }) - .AddSection(b => - { - b.SetLabel("Variant B specifics"); - - b.AddField(x => x.NameB1); - b.AddField(x => x.NameB2); - }) - .AddSection(c => - { - c.SetLabel("Variant C specifics"); - - c.AddField(x => x.NameC1); - c.AddField(x => x.NameC2); - c.AddField(x => x.NameC3); - }); - }); - }); - } + collection + // Set showEntities to true to have this collection to fold open on default + .SetTreeView(x => x.Name, showEntitiesOnStartup: true) + + // entity variants must be based of the same base type, but can introduce form elements for specialized cases + .AddEntityVariant("Variant A", "a") + .AddEntityVariant("Variant B", "b") + .AddEntityVariant("Variant C", "c") + .SetListEditor(view => + { + view.AddDefaultButton(DefaultButtonType.New, label: "New {0}"); + view.AddDefaultButton(DefaultButtonType.Return); + + view.SetColumnVisibility(EmptyVariantColumnVisibility.Collapse); + + view.SetPageSize(10); + + view + .AddSection(section => + { + section.AddField(p => p.Id); + + section.AddField(p => p.Name) + .SetOrderByExpression(p => p.Name, OrderByType.Ascending); + }) + .AddSection(section => + { + section.AddField(p => p.Id); + + section.AddField(p => p.Name) + .SetOrderByExpression(p => p.Name, OrderByType.Ascending); + + section.AddField(p => p.NameA1); + + section.AddDefaultButton(DefaultButtonType.SaveExisting); + section.AddDefaultButton(DefaultButtonType.SaveNew); + section.AddDefaultButton(DefaultButtonType.Edit); + }) + .AddSection(section => + { + section.AddField(p => p.Id); + + section.AddField(p => p.Name) + .SetOrderByExpression(p => p.Name, OrderByType.Ascending); + + section.AddField(p => p.NameB1); + section.AddField(p => p.NameB2); + + section.AddDefaultButton(DefaultButtonType.SaveExisting); + section.AddDefaultButton(DefaultButtonType.SaveNew); + section.AddDefaultButton(DefaultButtonType.Edit); + }) + .AddSection(section => + { + section.AddField(p => p.Id); + + section.AddField(p => p.Name) + .SetOrderByExpression(p => p.Name, OrderByType.Ascending); + + section.AddField(p => p.NameC1); + section.AddField(p => p.NameC2); + section.AddField(p => p.NameC3); + + section.AddDefaultButton(DefaultButtonType.SaveExisting); + section.AddDefaultButton(DefaultButtonType.SaveNew); + section.AddDefaultButton(DefaultButtonType.Edit); + }); + }) + .SetNodeEditor(editor => + { + editor.AddDefaultButton(DefaultButtonType.Up); + editor.AddDefaultButton(DefaultButtonType.SaveNew); + editor.AddDefaultButton(DefaultButtonType.SaveExisting); + + editor + .AddSection(generic => + { + generic.SetLabel("Generics"); + + generic.AddField(x => x.Id).SetType(DisplayType.Pre); + generic.AddField(x => x.Name); + }) + .AddSection(a => + { + a.SetLabel("Variant A specifics"); + + a.AddField(x => x.NameA1); + }) + .AddSection(b => + { + b.SetLabel("Variant B specifics"); + + b.AddField(x => x.NameB1); + b.AddField(x => x.NameB2); + }) + .AddSection(c => + { + c.SetLabel("Variant C specifics"); + + c.AddField(x => x.NameC1); + c.AddField(x => x.NameC2); + c.AddField(x => x.NameC3); + }); + }); + }); } } diff --git a/examples/RapidCMS.Example.Shared/Collections/MappedCollection.cs b/examples/RapidCMS.Example.Shared/Collections/MappedCollection.cs index 85d47492..6c11bd0d 100644 --- a/examples/RapidCMS.Example.Shared/Collections/MappedCollection.cs +++ b/examples/RapidCMS.Example.Shared/Collections/MappedCollection.cs @@ -4,42 +4,41 @@ using RapidCMS.Example.Shared.Data; using RapidCMS.Example.Shared.DataViews; -namespace RapidCMS.Example.Shared.Collections +namespace RapidCMS.Example.Shared.Collections; + +public static class MappedCollection { - public static class MappedCollection + // CRUD editor using a mapped repository + public static void AddMappedCollection(this ICmsConfig config) { - // CRUD editor using a mapped repository - public static void AddMappedCollection(this ICmsConfig config) + config.AddCollection>("mapped", "MicrosoftTranslatorLogo", "MagentaPink10", "Mapped entities", collection => { - config.AddCollection>("mapped", "MicrosoftTranslatorLogo", "MagentaPink10", "Mapped entities", collection => - { - collection - .SetTreeView(EntityVisibilty.Hidden, x => x.Name) + collection + .SetTreeView(EntityVisibilty.Hidden, x => x.Name) - // adding a data view builder allows you to have multiple tabs in the list editor, each with a different - // query associated with it - .SetDataViewBuilder() - .SetListEditor(editor => - { - editor.AddDefaultButton(DefaultButtonType.Return); - editor.AddDefaultButton(DefaultButtonType.New); + // adding a data view builder allows you to have multiple tabs in the list editor, each with a different + // query associated with it + .SetDataViewBuilder() + .SetListEditor(editor => + { + editor.AddDefaultButton(DefaultButtonType.Return); + editor.AddDefaultButton(DefaultButtonType.New); - editor - .AddSection(section => - { - // since the repository is mapped, the OrderBy query send to the IQueryable of the repository - // is based on DatabaseEntity, and not MappedEntity. because of this, the overload of SetOrderByExpression - // is used by which you can specify the type of entity - section.AddField(x => x.Name) - .SetOrderByExpression(x => x.Name); - section.AddField(x => x.Description) - .SetOrderByExpression(x => x.Description); + editor + .AddSection(section => + { + // since the repository is mapped, the OrderBy query send to the IQueryable of the repository + // is based on DatabaseEntity, and not MappedEntity. because of this, the overload of SetOrderByExpression + // is used by which you can specify the type of entity + section.AddField(x => x.Name) + .SetOrderByExpression(x => x.Name); + section.AddField(x => x.Description) + .SetOrderByExpression(x => x.Description); - section.AddDefaultButton(DefaultButtonType.SaveExisting); - section.AddDefaultButton(DefaultButtonType.SaveNew); - }); - }); - }); - } + section.AddDefaultButton(DefaultButtonType.SaveExisting); + section.AddDefaultButton(DefaultButtonType.SaveNew); + }); + }); + }); } } diff --git a/examples/RapidCMS.Example.Shared/Collections/PersonCollection.cs b/examples/RapidCMS.Example.Shared/Collections/PersonCollection.cs index 29222eb5..bb6a0055 100644 --- a/examples/RapidCMS.Example.Shared/Collections/PersonCollection.cs +++ b/examples/RapidCMS.Example.Shared/Collections/PersonCollection.cs @@ -7,238 +7,237 @@ using RapidCMS.Example.Shared.Components; using RapidCMS.Example.Shared.Data; -namespace RapidCMS.Example.Shared.Collections +namespace RapidCMS.Example.Shared.Collections; + +public static class PersonCollection { - public static class PersonCollection + // CRUD editor for simple POCO with recursive sub collections + public static void AddPersonCollection(this ICmsConfig config) { - // CRUD editor for simple POCO with recursive sub collections - public static void AddPersonCollection(this ICmsConfig config) + config.AddCollection>("person", "Contact", "Red20", "People", collection => { - config.AddCollection>("person", "Contact", "Red20", "People", collection => - { - collection - .SetTreeView(x => x.Name) - .SetElementConfiguration( - x => x.Id, - x => x.Name, - x => x.Details != null ? x.Details.Email : "") - // this repository handles all the CRUD for this collection - // a list view is a table that displays a row (or multiple rows) of info per entity - .SetListView(view => + collection + .SetTreeView(x => x.Name) + .SetElementConfiguration( + x => x.Id, + x => x.Name, + x => x.Details != null ? x.Details.Email : "") + // this repository handles all the CRUD for this collection + // a list view is a table that displays a row (or multiple rows) of info per entity + .SetListView(view => + { + // if new entities can be made using the CMS, include a New button so users can insert new entities + view.AddDefaultButton(DefaultButtonType.New); + + // multiple rows can be added to display even more data + // only the first row will be used to generate headers + view.AddRow(row => { - // if new entities can be made using the CMS, include a New button so users can insert new entities - view.AddDefaultButton(DefaultButtonType.New); - - // multiple rows can be added to display even more data - // only the first row will be used to generate headers - view.AddRow(row => - { - // views always require you to specify strings, so the Id (an int) must be .ToString-ed. - // since this messes up the name of the column, you can set it to a nice name - row.AddField(p => p.Id.ToString()).SetName("ID"); - row.AddField(p => p.Name); - - // if an entity can be edited, include an Edit button so users can start editing entities - // the edit button in a list will always direct the user to the NodeEditor - row.AddDefaultButton(DefaultButtonType.Edit); - }); - }) - // a list editor is similar to a list view, but every column contains an editor so multiple entities can be edited in one go - // a list editor takes precedence over a list view, so when navigating to the Person collection, this view will be displayed - .SetListEditor(editor => + // views always require you to specify strings, so the Id (an int) must be .ToString-ed. + // since this messes up the name of the column, you can set it to a nice name + row.AddField(p => p.Id.ToString()).SetName("ID"); + row.AddField(p => p.Name); + + // if an entity can be edited, include an Edit button so users can start editing entities + // the edit button in a list will always direct the user to the NodeEditor + row.AddDefaultButton(DefaultButtonType.Edit); + }); + }) + // a list editor is similar to a list view, but every column contains an editor so multiple entities can be edited in one go + // a list editor takes precedence over a list view, so when navigating to the Person collection, this view will be displayed + .SetListEditor(editor => + { + editor.SetPageSize(20); + + // adding Up to the button bar allows the user to get to the level above the current page (base upon the tree) + // this button will be hidden automatically when the user is at the root + editor.AddDefaultButton(DefaultButtonType.Up); + + // in a list editor a New allows the user to add entities, within the list editor + editor.AddDefaultButton(DefaultButtonType.New); + editor.AddDefaultButton(DefaultButtonType.Return); + + // adding a SaveExisting button to the ListEditor allows the user to bulk-save the entire list + // (only modified entities are touched) + editor.AddDefaultButton(DefaultButtonType.SaveExisting); + + // allowing reordering so the user can shuffle the entities around and save them in a new order. + // the Repository must implement ReorderAsync + editor.AllowReordering(true); + + // a list editor can be in the shape of a table, or a set of blocks, so these sections are either rows or blocks + editor.AddSection(row => { - editor.SetPageSize(20); - - // adding Up to the button bar allows the user to get to the level above the current page (base upon the tree) - // this button will be hidden automatically when the user is at the root - editor.AddDefaultButton(DefaultButtonType.Up); - - // in a list editor a New allows the user to add entities, within the list editor - editor.AddDefaultButton(DefaultButtonType.New); - editor.AddDefaultButton(DefaultButtonType.Return); - - // adding a SaveExisting button to the ListEditor allows the user to bulk-save the entire list - // (only modified entities are touched) - editor.AddDefaultButton(DefaultButtonType.SaveExisting); - - // allowing reordering so the user can shuffle the entities around and save them in a new order. - // the Repository must implement ReorderAsync - editor.AllowReordering(true); - - // a list editor can be in the shape of a table, or a set of blocks, so these sections are either rows or blocks - editor.AddSection(row => - { - // these fields will be the editors - row.AddField(p => p.Id).SetType(EditorType.Readonly); - row.AddField(p => p.Name); - - // the DisplayType Link requires an instance of Link to be configured to the editor. - // form elements can indicate that they want or require configuration by implementing either - // IWantConfiguration or INeedConfiguration. - row.AddField(p => p.Details.SocialUrl).SetName("Social account") - .SetType(DisplayType.Link) - .SetConfiguration(async (entity, state) => - { - // this method can be async, making it possible to do some custom logic here before - // passing it into the form element - await Task.Delay(1000); - - return new Link($"{entity.Name}'s account", false); - }); - - // the SaveExisting button is only displayed when an entity is edited - row.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true); - // the SaveNew button is only displayed when an entity is inserted - row.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true); - - // the View button always directs the user to the NodeView - row.AddDefaultButton(DefaultButtonType.View); - // the Edit button always directs the user to the NodeEdit - row.AddDefaultButton(DefaultButtonType.Edit); - }); - }) - .SetNodeEditor(editor => + // these fields will be the editors + row.AddField(p => p.Id).SetType(EditorType.Readonly); + row.AddField(p => p.Name); + + // the DisplayType Link requires an instance of Link to be configured to the editor. + // form elements can indicate that they want or require configuration by implementing either + // IWantConfiguration or INeedConfiguration. + row.AddField(p => p.Details.SocialUrl).SetName("Social account") + .SetType(DisplayType.Link) + .SetConfiguration(async (entity, state) => + { + // this method can be async, making it possible to do some custom logic here before + // passing it into the form element + await Task.Delay(1000); + + return new Link($"{entity.Name}'s account", false); + }); + + // the SaveExisting button is only displayed when an entity is edited + row.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true); + // the SaveNew button is only displayed when an entity is inserted + row.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true); + + // the View button always directs the user to the NodeView + row.AddDefaultButton(DefaultButtonType.View); + // the Edit button always directs the user to the NodeEdit + row.AddDefaultButton(DefaultButtonType.Edit); + }); + }) + .SetNodeEditor(editor => + { + // adding Up to the button bar allows the user to get to the level above the current page (base upon the tree) + editor.AddDefaultButton(DefaultButtonType.Up); + + // just as in the ListEditor, SaveExisting only shows when the user is editing an existing entity, + // and the SaveNew only when inserting an entity + editor.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true); + editor.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true); + + // if an entity can be deleted, add a button for it, so the user can delete the entity + editor.AddDefaultButton(DefaultButtonType.Delete); + + // an node editor can have multiple sections, which are displayed as separate blocks + editor.AddSection(section => { - // adding Up to the button bar allows the user to get to the level above the current page (base upon the tree) - editor.AddDefaultButton(DefaultButtonType.Up); - - // just as in the ListEditor, SaveExisting only shows when the user is editing an existing entity, - // and the SaveNew only when inserting an entity - editor.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true); - editor.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true); - - // if an entity can be deleted, add a button for it, so the user can delete the entity - editor.AddDefaultButton(DefaultButtonType.Delete); - - // an node editor can have multiple sections, which are displayed as separate blocks - editor.AddSection(section => - { - // the DisableWhen expression is evaluated every time any property of the entity is updated - // so this allows you to make response forms which show or hide parts based upon the entity and its state - section.AddField(x => x.Id).DisableWhen((person, state) => true); - - // it is allowed to use DisplayType fields in Editors, so some read only data can easily be displayed - section.AddField(x => x.Name); //.SetType(DisplayType.Label); - - // if properties are in nested objects (like owned entities in EF), the editors support those as well - // flagging such property with [ValidateObject] will have the nested object validated as well - section.AddField(x => x.Details.Email) - // by default, all the properties will be combined to form the Name of the property (DetailsEmail in this example) - // so using SetName this can be set to something more user friendly - .SetName("Email") - .SetDetails(new MarkupString("

An email adress looks like name@domain.tld.

")); - - section.AddField(x => x.Details.SocialUrl); - }); - - // you can even have sections specifically for an entity type. - // if the repository can return multiple types of entities (all derived from a shared base type), - // sections can be made specifically for a type - editor.AddSection(section => - { - // sections can have labels to make complex forms more understandable - section.SetLabel("Biography"); - - // sections can be hidden using VisibleWhen, based upon the entity or the state of that entity - // so users won't be confronted with editors that do not apply - section.VisibleWhen((person, state) => state == EntityState.IsExisting); - - // there are many types of editors available, and even custom types can be used - section.AddField(x => x.Details.Bio).SetType(EditorType.TextArea).SetName("Bio"); - }); - - editor.AddSection(section => - { - // relations with other entities, collections and repositories are first-class in RapidCMS - // so this field will allow the user to select an entity that is one level deeper in the person-tree - section.AddField(x => x.FavouriteChildId) - .SetName("Favorite child") - .SetType(EditorType.Select) - .VisibleWhen((person, state) => state == EntityState.IsExisting) - .SetCollectionRelation("person", config => - { - // this allows for configuring which property of the entity will make up the id for the element, and that value - // is set to FavouriteChildId when the user selects an element - config.SetElementIdProperty(x => x.Id); - - // because a single label is often not enough, you can add more properties to make the labels for each option - config.SetElementDisplayProperties(x => x.Name, x => $"{x.Id} - {x.Details.Email}"); - - // sets the entity that is currently edited as parent for the repository to get elements for this field - config.SetEntityAsParent(); - - // any level from the tree can be picked: - // Favorite sibling: config.SetRepositoryParent(x => x); - // Favorite parent: config.SetRepositoryParent(x => x.Parent); - // Favorite grand parent: config.SetRepositoryParent(x => x.Parent != null ? x.Parent.Parent : default); // ?. is not yet supported in expressions.. - }); - }); - - // add the sub collection as element to the node editor - editor.AddSection(section => - { - section.AddSubCollectionList("person"); - }); - }) - .SetNodeView(view => + // the DisableWhen expression is evaluated every time any property of the entity is updated + // so this allows you to make response forms which show or hide parts based upon the entity and its state + section.AddField(x => x.Id).DisableWhen((person, state) => true); + + // it is allowed to use DisplayType fields in Editors, so some read only data can easily be displayed + section.AddField(x => x.Name); //.SetType(DisplayType.Label); + + // if properties are in nested objects (like owned entities in EF), the editors support those as well + // flagging such property with [ValidateObject] will have the nested object validated as well + section.AddField(x => x.Details.Email) + // by default, all the properties will be combined to form the Name of the property (DetailsEmail in this example) + // so using SetName this can be set to something more user friendly + .SetName("Email") + .SetDetails(new MarkupString("

An email adress looks like name@domain.tld.

")); + + section.AddField(x => x.Details.SocialUrl); + }); + + // you can even have sections specifically for an entity type. + // if the repository can return multiple types of entities (all derived from a shared base type), + // sections can be made specifically for a type + editor.AddSection(section => { - view.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true); - view.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true); - - view.AddDefaultButton(DefaultButtonType.Delete); - - view.AddSection(section => - { - // views also allow for customization of how the data should be displayed - // you can use the available DisplayType's, or create your own Razor components (must be derived from BaseDisplay) - section.AddField(x => x.Id.ToString()).SetName("ID").SetType(DisplayType.Pre); - section.AddField(x => x.Name).SetType(DisplayType.Label); - section.AddField(x => x.Details.Email).SetType(typeof(EmailDisplay)); - }); - - view.AddSection(section => - { - section.AddField(x => x.Details.Bio); - }); + // sections can have labels to make complex forms more understandable + section.SetLabel("Biography"); + + // sections can be hidden using VisibleWhen, based upon the entity or the state of that entity + // so users won't be confronted with editors that do not apply + section.VisibleWhen((person, state) => state == EntityState.IsExisting); + + // there are many types of editors available, and even custom types can be used + section.AddField(x => x.Details.Bio).SetType(EditorType.TextArea).SetName("Bio"); }); - collection.AddSelfAsRecursiveCollection(); + editor.AddSection(section => + { + // relations with other entities, collections and repositories are first-class in RapidCMS + // so this field will allow the user to select an entity that is one level deeper in the person-tree + section.AddField(x => x.FavouriteChildId) + .SetName("Favorite child") + .SetType(EditorType.Select) + .VisibleWhen((person, state) => state == EntityState.IsExisting) + .SetCollectionRelation("person", config => + { + // this allows for configuring which property of the entity will make up the id for the element, and that value + // is set to FavouriteChildId when the user selects an element + config.SetElementIdProperty(x => x.Id); + + // because a single label is often not enough, you can add more properties to make the labels for each option + config.SetElementDisplayProperties(x => x.Name, x => $"{x.Id} - {x.Details.Email}"); + + // sets the entity that is currently edited as parent for the repository to get elements for this field + config.SetEntityAsParent(); + + // any level from the tree can be picked: + // Favorite sibling: config.SetRepositoryParent(x => x); + // Favorite parent: config.SetRepositoryParent(x => x.Parent); + // Favorite grand parent: config.SetRepositoryParent(x => x.Parent != null ? x.Parent.Parent : default); // ?. is not yet supported in expressions.. + }); + }); - // if the regular node editor of an entity is getting too cluttered, or if you want to move some of the functionality - // to a separate page, a detail page can be quite useful. - // a detail page is always a NodeEditor, and is only visible on existing entity. - // the repository it fetches its data from can have its own entity type, but the ID that is used to query for the data - // is the same as the entity the page is part of. - // it is also possible to create a navigation button to navigate to a details page, by building a INavigationHandler that - // calls NavigationRequest.NavigateToDetails (see NavigateToPersonHandler) - collection.AddDetailPage>("person-details", "Settings", "Red20", "Details", config => + // add the sub collection as element to the node editor + editor.AddSection(section => + { + section.AddSubCollectionList("person"); + }); + }) + .SetNodeView(view => { - config.AddDefaultButton(DefaultButtonType.SaveExisting, "Save"); + view.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true); + view.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true); - config.AddSection(section => + view.AddDefaultButton(DefaultButtonType.Delete); + + view.AddSection(section => { - section.AddField(x => x.Title); - section.AddField(x => x.History); - - // when a model has a sub class which has a few simple properties, it's possible to group those properties - // into a single editor using the ModelEditor type. this editor uses the same rules as the convention based - // approach (see ConventionCollection), but groups the editors together of this property. - // - // to validate the properties of the nested object, the Nested property must be attributed with [ValidateObjectAsProperty] - // to instruct the data annotation validator to validate NestedDetails and use that validation as validation result - // for Nested. - section.AddField(x => x.Nested) - .SetType(EditorType.ModelEditor); + // views also allow for customization of how the data should be displayed + // you can use the available DisplayType's, or create your own Razor components (must be derived from BaseDisplay) + section.AddField(x => x.Id.ToString()).SetName("ID").SetType(DisplayType.Pre); + section.AddField(x => x.Name).SetType(DisplayType.Label); + section.AddField(x => x.Details.Email).SetType(typeof(EmailDisplay)); + }); + + view.AddSection(section => + { + section.AddField(x => x.Details.Bio); }); }); - // adds a custom page in the tree under the Person. The CustomPageSection has access to the entity - // making these custom pages ideal to create custom pages that are not limited by the features of RapidCMS - collection.AddPage("TestBeakerSolid", "Green10", "Nested page", config => + collection.AddSelfAsRecursiveCollection(); + + // if the regular node editor of an entity is getting too cluttered, or if you want to move some of the functionality + // to a separate page, a detail page can be quite useful. + // a detail page is always a NodeEditor, and is only visible on existing entity. + // the repository it fetches its data from can have its own entity type, but the ID that is used to query for the data + // is the same as the entity the page is part of. + // it is also possible to create a navigation button to navigate to a details page, by building a INavigationHandler that + // calls NavigationRequest.NavigateToDetails (see NavigateToPersonHandler) + collection.AddDetailPage>("person-details", "Settings", "Red20", "Details", config => + { + config.AddDefaultButton(DefaultButtonType.SaveExisting, "Save"); + + config.AddSection(section => { - config.AddSection(typeof(CustomPageSection)); + section.AddField(x => x.Title); + section.AddField(x => x.History); + + // when a model has a sub class which has a few simple properties, it's possible to group those properties + // into a single editor using the ModelEditor type. this editor uses the same rules as the convention based + // approach (see ConventionCollection), but groups the editors together of this property. + // + // to validate the properties of the nested object, the Nested property must be attributed with [ValidateObjectAsProperty] + // to instruct the data annotation validator to validate NestedDetails and use that validation as validation result + // for Nested. + section.AddField(x => x.Nested) + .SetType(EditorType.ModelEditor); }); }); - } + + // adds a custom page in the tree under the Person. The CustomPageSection has access to the entity + // making these custom pages ideal to create custom pages that are not limited by the features of RapidCMS + collection.AddPage("TestBeakerSolid", "Green10", "Nested page", config => + { + config.AddSection(typeof(CustomPageSection)); + }); + }); } } diff --git a/examples/RapidCMS.Example.Shared/Collections/TagCollection.cs b/examples/RapidCMS.Example.Shared/Collections/TagCollection.cs index 26b99434..797efb02 100644 --- a/examples/RapidCMS.Example.Shared/Collections/TagCollection.cs +++ b/examples/RapidCMS.Example.Shared/Collections/TagCollection.cs @@ -5,118 +5,117 @@ using RapidCMS.Example.Shared.Data; using RapidCMS.Example.Shared.Handlers; -namespace RapidCMS.Example.Shared.Collections +namespace RapidCMS.Example.Shared.Collections; + +public static class TagCollection { - public static class TagCollection + public static void AddTagCollection(this ICmsConfig config) { - public static void AddTagCollection(this ICmsConfig config) + config.AddCollection>("taggroup", "Tag", "Gray30", "Tag groups", collection => { - config.AddCollection>("taggroup", "Tag", "Gray30", "Tag groups", collection => - { - collection - .SetTreeView(EntityVisibilty.Hidden, x => x.Name) - .SetListEditor(editor => - { - editor.SetListType(ListType.Block); + collection + .SetTreeView(EntityVisibilty.Hidden, x => x.Name) + .SetListEditor(editor => + { + editor.SetListType(ListType.Block); - editor.SetSearchBarVisibility(false); + editor.SetSearchBarVisibility(false); - editor.AddDefaultButton(DefaultButtonType.Return); - editor.AddDefaultButton(DefaultButtonType.New); + editor.AddDefaultButton(DefaultButtonType.Return); + editor.AddDefaultButton(DefaultButtonType.New); - editor - .AddSection(section => - { - section.AddDefaultButton(DefaultButtonType.SaveExisting); - section.AddDefaultButton(DefaultButtonType.SaveNew); - section.AddDefaultButton(DefaultButtonType.Delete); + editor + .AddSection(section => + { + section.AddDefaultButton(DefaultButtonType.SaveExisting); + section.AddDefaultButton(DefaultButtonType.SaveNew); + section.AddDefaultButton(DefaultButtonType.Delete); - section.AddField(x => x.Name); + section.AddField(x => x.Name); - section.AddField(x => x.DefaultTagId).SetName("Default tag") - .SetType(EditorType.Dropdown) - .SetCollectionRelation>(config => - { - // this allows for configuring which property of the entity will make up the id for the element, and that value - // is set to FavouriteChildId when the user selects an element - config.SetElementIdProperty(x => x.Id); + section.AddField(x => x.DefaultTagId).SetName("Default tag") + .SetType(EditorType.Dropdown) + .SetCollectionRelation>(config => + { + // this allows for configuring which property of the entity will make up the id for the element, and that value + // is set to FavouriteChildId when the user selects an element + config.SetElementIdProperty(x => x.Id); - // because a single label is often not enough, you can add more properties to make the labels for each option - config.SetElementDisplayProperties(x => x.Name, x => $"{x.Id} - {x.Name}"); + // because a single label is often not enough, you can add more properties to make the labels for each option + config.SetElementDisplayProperties(x => x.Name, x => $"{x.Id} - {x.Name}"); - // sets the entity that is currently edited as parent for the repository to get elements for this field - config.SetEntityAsParent(); + // sets the entity that is currently edited as parent for the repository to get elements for this field + config.SetEntityAsParent(); - // the data in this dropdown will refresh automatically when the repository on which the data - // is based flags that the data has been updated - }); + // the data in this dropdown will refresh automatically when the repository on which the data + // is based flags that the data has been updated + }); - // it is possible to view or edit an subcollection from the parent - // when adding a subcollection in an Editor will have to be a ListEditor while - // adding a subcollection in a View will be a ListView. + // it is possible to view or edit an subcollection from the parent + // when adding a subcollection in an Editor will have to be a ListEditor while + // adding a subcollection in a View will be a ListView. - // the entity of this editor will be passed in as IParent in the repository of the - // sub collection, making it possible to access the parents properties in the child repository - section.AddSubCollectionList>(config => + // the entity of this editor will be passed in as IParent in the repository of the + // sub collection, making it possible to access the parents properties in the child repository + section.AddSubCollectionList>(config => + { + config.SetListEditor(editor => { - config.SetListEditor(editor => - { - editor.SetSearchBarVisibility(false); + editor.SetSearchBarVisibility(false); - editor.AddDefaultButton(DefaultButtonType.Return); - editor.AddDefaultButton(DefaultButtonType.New); - editor.AddDefaultButton(DefaultButtonType.SaveExisting, "Update all"); + editor.AddDefaultButton(DefaultButtonType.Return); + editor.AddDefaultButton(DefaultButtonType.New); + editor.AddDefaultButton(DefaultButtonType.SaveExisting, "Update all"); - editor.AddSection(section => - { - section.AddDefaultButton(DefaultButtonType.SaveExisting); - section.AddDefaultButton(DefaultButtonType.SaveNew); + editor.AddSection(section => + { + section.AddDefaultButton(DefaultButtonType.SaveExisting); + section.AddDefaultButton(DefaultButtonType.SaveNew); - // add custom buttons and action handlers using the following handler - section.AddCustomButton(typeof(CustomButton), "Create name", "AddTo"); + // add custom buttons and action handlers using the following handler + section.AddCustomButton(typeof(CustomButton), "Create name", "AddTo"); - section.AddField(x => x.Name); - }); + section.AddField(x => x.Name); }); }); + }); - // if you want to reuse a collection in multiple views, you can also reference it by alias - // if you comment out the AddSubCollectionList above this comment, and enable the AddSubCollectionList below, - // the editor will work identical, but now the collection with alias "tag" can be used for multiple things + // if you want to reuse a collection in multiple views, you can also reference it by alias + // if you comment out the AddSubCollectionList above this comment, and enable the AddSubCollectionList below, + // the editor will work identical, but now the collection with alias "tag" can be used for multiple things - // section.AddSubCollectionList("tag"); - }); - }); - - // any collection can be added as subcollection, even collections based upon totally difference repositories - // this lets you mix repositories which are based upon totally different databases easily - collection - .AddSubCollection>("tag", "Tags", subCollection => - { - subCollection - .SetListEditor(editor => - { - editor.SetListType(ListType.Table); + // section.AddSubCollectionList("tag"); + }); + }); - editor.SetSearchBarVisibility(false); + // any collection can be added as subcollection, even collections based upon totally difference repositories + // this lets you mix repositories which are based upon totally different databases easily + collection + .AddSubCollection>("tag", "Tags", subCollection => + { + subCollection + .SetListEditor(editor => + { + editor.SetListType(ListType.Table); - editor.AddDefaultButton(DefaultButtonType.Return); - editor.AddDefaultButton(DefaultButtonType.New); - editor.AddDefaultButton(DefaultButtonType.SaveExisting); + editor.SetSearchBarVisibility(false); - editor.AddSection(section => - { - section.AddDefaultButton(DefaultButtonType.SaveExisting); - section.AddDefaultButton(DefaultButtonType.SaveNew); + editor.AddDefaultButton(DefaultButtonType.Return); + editor.AddDefaultButton(DefaultButtonType.New); + editor.AddDefaultButton(DefaultButtonType.SaveExisting); - // add custom buttons and action handlers using the following handler - section.AddCustomButton(typeof(CustomButton), "Create name", "add-circle"); + editor.AddSection(section => + { + section.AddDefaultButton(DefaultButtonType.SaveExisting); + section.AddDefaultButton(DefaultButtonType.SaveNew); - section.AddField(x => x.Name); - }); + // add custom buttons and action handlers using the following handler + section.AddCustomButton(typeof(CustomButton), "Create name", "add-circle"); + + section.AddField(x => x.Name); }); - }); - }); - } + }); + }); + }); } } diff --git a/examples/RapidCMS.Example.Shared/Collections/UserCollection.cs b/examples/RapidCMS.Example.Shared/Collections/UserCollection.cs index 6d0dd314..e8e6a931 100644 --- a/examples/RapidCMS.Example.Shared/Collections/UserCollection.cs +++ b/examples/RapidCMS.Example.Shared/Collections/UserCollection.cs @@ -9,92 +9,91 @@ using RapidCMS.UI.Components.Editors; using RapidCMS.UI.Components.Preview; -namespace RapidCMS.Example.Shared.Collections +namespace RapidCMS.Example.Shared.Collections; + +public static class UserCollection { - public static class UserCollection + // CRUD editor with validation attributes, custom editor and custom button panes + public static void AddUserCollection(this ICmsConfig config) { - // CRUD editor with validation attributes, custom editor and custom button panes - public static void AddUserCollection(this ICmsConfig config) + // the CMS users https://ionicons.com/, so use the name of any Ion Icon as icon for a collection + config.AddCollection>("user", "UserFollowed", "BlueMagenta30", "Users", collection => { - // the CMS users https://ionicons.com/, so use the name of any Ion Icon as icon for a collection - config.AddCollection>("user", "UserFollowed", "BlueMagenta30", "Users", collection => - { - collection - .SetTreeView(EntityVisibilty.Hidden, x => x.Name) - .SetListEditor(editor => - { - editor.AllowReordering(true); - - // you can control the number of entities on a single page - editor.SetPageSize(20); - - editor.AddDefaultButton(DefaultButtonType.Return); - editor.AddDefaultButton(DefaultButtonType.New); - // this pane button opens a sidepane displaying the ResetAllPane Razor component. - // this component must inherit BaseSidePane and allows for more complex flows and confirmations. - editor.AddPaneButton(typeof(ResetAllPane), "Reset all passwords (via pane)", "LockSolid"); - - // custom buttons are also allowed: - editor.AddCustomButton(typeof(DefaultButton), "Reset all passwords (via handler)", "LockSolid"); - // they must reference a BaseButton derived Razor component, as well as a ActionHandler which handles - // the click from the user. - // if your custom button does not require anything special, you can also use DefaultButton - - editor - .AddSection(section => - { - section.AddField(x => x.Name); - - // this field uses a custom editor, which must inherit BaseEditor - section.AddField(x => x.Password).SetType(typeof(PasswordEditor)); - - // even though some properties on User are required, saving a User with only its Name set is allowed - // since this editor cannot touch those required properties. - // if all displayed properties on a model are valid, the whole model is considered valid, as the user - // will be unable to make the model valid otherwise. - section.AddDefaultButton(DefaultButtonType.SaveExisting); - section.AddDefaultButton(DefaultButtonType.SaveNew); - - section.AddDefaultButton(DefaultButtonType.Edit); - }); - }) - .SetNodeEditor(editor => - { - editor - .AddSection(section => - { - section.AddDefaultButton(DefaultButtonType.SaveExisting); - section.AddDefaultButton(DefaultButtonType.SaveNew); - - section.AddField(x => x.Name); - section.AddField(x => x.StartDate).SetType(EditorType.Date); - - // this field uses the EnumFlagPicker, which will set or unset flags of the Role enum - section.AddField(x => x.Role).SetType(EditorType.EnumFlagPicker).SetDataCollection>(); - - // this field uses a custom editor, which must inherit BaseEditor - section.AddField(x => x.Password).SetType(typeof(PasswordEditor)); - - // some default editors (like FileUploadEditor) require custom components, so they must be added using their full classname - // NoPreview is a default component indicating this upload editor has no preview of the file - - // the file upload handler is different between ServerSide and WebAssembly, so only its interface is added here - // and via DI the correct handler is resolved. it's also allowed to reference the correct handler here (for example: Base64TextFileUploadHandler) - // to allow for per input configuration - // AND dependency injection in Blazor has trouble resolving generic types (like ApiFileUploadHandler) so it's better - // to reference simple interfaces or types - section.AddField(x => x.FileBase64).SetType(typeof(FileUploadEditor)) - .SetName("User file"); - - // ImagePreview is a custom component derived from BasePreview to display the uploaded image - section.AddField(x => x.ProfilePictureBase64).SetType(typeof(FileUploadEditor)) - .SetName("User picture"); - - section.AddField(x => x.Integer).SetType(EditorType.Numeric); - section.AddField(x => x.Double).SetType(EditorType.Numeric); - }); - }); - }); - } + collection + .SetTreeView(EntityVisibilty.Hidden, x => x.Name) + .SetListEditor(editor => + { + editor.AllowReordering(true); + + // you can control the number of entities on a single page + editor.SetPageSize(20); + + editor.AddDefaultButton(DefaultButtonType.Return); + editor.AddDefaultButton(DefaultButtonType.New); + // this pane button opens a sidepane displaying the ResetAllPane Razor component. + // this component must inherit BaseSidePane and allows for more complex flows and confirmations. + editor.AddPaneButton(typeof(ResetAllPane), "Reset all passwords (via pane)", "LockSolid"); + + // custom buttons are also allowed: + editor.AddCustomButton(typeof(DefaultButton), "Reset all passwords (via handler)", "LockSolid"); + // they must reference a BaseButton derived Razor component, as well as a ActionHandler which handles + // the click from the user. + // if your custom button does not require anything special, you can also use DefaultButton + + editor + .AddSection(section => + { + section.AddField(x => x.Name); + + // this field uses a custom editor, which must inherit BaseEditor + section.AddField(x => x.Password).SetType(typeof(PasswordEditor)); + + // even though some properties on User are required, saving a User with only its Name set is allowed + // since this editor cannot touch those required properties. + // if all displayed properties on a model are valid, the whole model is considered valid, as the user + // will be unable to make the model valid otherwise. + section.AddDefaultButton(DefaultButtonType.SaveExisting); + section.AddDefaultButton(DefaultButtonType.SaveNew); + + section.AddDefaultButton(DefaultButtonType.Edit); + }); + }) + .SetNodeEditor(editor => + { + editor + .AddSection(section => + { + section.AddDefaultButton(DefaultButtonType.SaveExisting); + section.AddDefaultButton(DefaultButtonType.SaveNew); + + section.AddField(x => x.Name); + section.AddField(x => x.StartDate).SetType(EditorType.Date); + + // this field uses the EnumFlagPicker, which will set or unset flags of the Role enum + section.AddField(x => x.Role).SetType(EditorType.EnumFlagPicker).SetDataCollection>(); + + // this field uses a custom editor, which must inherit BaseEditor + section.AddField(x => x.Password).SetType(typeof(PasswordEditor)); + + // some default editors (like FileUploadEditor) require custom components, so they must be added using their full classname + // NoPreview is a default component indicating this upload editor has no preview of the file + + // the file upload handler is different between ServerSide and WebAssembly, so only its interface is added here + // and via DI the correct handler is resolved. it's also allowed to reference the correct handler here (for example: Base64TextFileUploadHandler) + // to allow for per input configuration + // AND dependency injection in Blazor has trouble resolving generic types (like ApiFileUploadHandler) so it's better + // to reference simple interfaces or types + section.AddField(x => x.FileBase64).SetType(typeof(FileUploadEditor)) + .SetName("User file"); + + // ImagePreview is a custom component derived from BasePreview to display the uploaded image + section.AddField(x => x.ProfilePictureBase64).SetType(typeof(FileUploadEditor)) + .SetName("User picture"); + + section.AddField(x => x.Integer).SetType(EditorType.Numeric); + section.AddField(x => x.Double).SetType(EditorType.Numeric); + }); + }); + }); } } diff --git a/examples/RapidCMS.Example.Shared/Data/ConventionalPerson.cs b/examples/RapidCMS.Example.Shared/Data/ConventionalPerson.cs index ab4a1d72..302c3aa7 100644 --- a/examples/RapidCMS.Example.Shared/Data/ConventionalPerson.cs +++ b/examples/RapidCMS.Example.Shared/Data/ConventionalPerson.cs @@ -5,33 +5,32 @@ using RapidCMS.Core.Enums; using RapidCMS.UI.Components.Editors; -namespace RapidCMS.Example.Shared.Data +namespace RapidCMS.Example.Shared.Data; + +public class ConventionalPerson : IEntity, ICloneable { - public class ConventionalPerson : IEntity, ICloneable - { - public int Id { get; set; } + public int Id { get; set; } - [Field(Name = "Email", Description = "The email of the person", ListName = "Email", OrderByType = OrderByType.Descending)] - public string? Email { get; set; } - - [Field(Name = "Name", Description = "The name of the person", ListName = "Name", OrderByType = OrderByType.Ascending)] - [Required] - public string? Name { get; set; } + [Field(Name = "Email", Description = "The email of the person", ListName = "Email", OrderByType = OrderByType.Descending)] + public string? Email { get; set; } + + [Field(Name = "Name", Description = "The name of the person", ListName = "Name", OrderByType = OrderByType.Ascending)] + [Required] + public string? Name { get; set; } - [Field(Name = "Biography", Description = "The biography of the person", EditorType = typeof(TextAreaEditor))] - public string? Bio { get; set; } + [Field(Name = "Biography", Description = "The biography of the person", EditorType = typeof(TextAreaEditor))] + public string? Bio { get; set; } - string? IEntity.Id { get => Id.ToString(); set => Id = int.Parse(value ?? "0"); } + string? IEntity.Id { get => Id.ToString(); set => Id = int.Parse(value ?? "0"); } - public object Clone() + public object Clone() + { + return new ConventionalPerson { - return new ConventionalPerson - { - Bio = Bio, - Email = Email, - Id = Id, - Name = Name - }; - } + Bio = Bio, + Email = Email, + Id = Id, + Name = Name + }; } } diff --git a/examples/RapidCMS.Example.Shared/Data/Counter.cs b/examples/RapidCMS.Example.Shared/Data/Counter.cs index 4c6711ae..b445b5a6 100644 --- a/examples/RapidCMS.Example.Shared/Data/Counter.cs +++ b/examples/RapidCMS.Example.Shared/Data/Counter.cs @@ -2,22 +2,21 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Attributes; -namespace RapidCMS.Example.Shared.Data +namespace RapidCMS.Example.Shared.Data; + +public class Counter : IEntity, ICloneable { - public class Counter : IEntity, ICloneable - { - public string? Id { get; set; } + public string? Id { get; set; } - [Field(Name = "Current count", ListName = "Current count")] - public int CurrentCount { get; set; } + [Field(Name = "Current count", ListName = "Current count")] + public int CurrentCount { get; set; } - public object Clone() + public object Clone() + { + return new Counter() { - return new Counter() - { - CurrentCount = CurrentCount, - Id = Id - }; - } + CurrentCount = CurrentCount, + Id = Id + }; } } diff --git a/examples/RapidCMS.Example.Shared/Data/Country.cs b/examples/RapidCMS.Example.Shared/Data/Country.cs index 4e377301..341e700d 100644 --- a/examples/RapidCMS.Example.Shared/Data/Country.cs +++ b/examples/RapidCMS.Example.Shared/Data/Country.cs @@ -4,53 +4,52 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Attributes; -namespace RapidCMS.Example.Shared.Data +namespace RapidCMS.Example.Shared.Data; + +// this entity is validated by the CountryValidator +public class Country : IEntity, ICloneable { - // this entity is validated by the CountryValidator - public class Country : IEntity, ICloneable - { - public int Id { get; set; } + public int Id { get; set; } - public string? Name { get; set; } + public string? Name { get; set; } - public List FlagColors { get; set; } = new List(); + public List FlagColors { get; set; } = new List(); - public List People { get; set; } = new List(); + public List People { get; set; } = new List(); - string? IEntity.Id { get => Id.ToString(); set => Id = int.Parse(value ?? "0"); } + string? IEntity.Id { get => Id.ToString(); set => Id = int.Parse(value ?? "0"); } - public object Clone() + public object Clone() + { + return new Country { - return new Country + Id = Id, + Name = Name, + People = People.ToList(), + FlagColors = FlagColors.ToList(), + Metadata = new CountryMetadata { - Id = Id, - Name = Name, - People = People.ToList(), - FlagColors = FlagColors.ToList(), - Metadata = new CountryMetadata - { - Continent = Metadata.Continent, - Tag = Metadata.Tag - } - }; - } - - // to enable nested properties to be correctly validated, ValidateObject is required, even if the model is validated by EntityValidators - [ValidateObject] - public CountryMetadata Metadata { get; set; } = new CountryMetadata(); - - public class CountryMetadata - { - public string? Continent { get; set; } + Continent = Metadata.Continent, + Tag = Metadata.Tag + } + }; + } - public string? Tag { get; set; } - } + // to enable nested properties to be correctly validated, ValidateObject is required, even if the model is validated by EntityValidators + [ValidateObject] + public CountryMetadata Metadata { get; set; } = new CountryMetadata(); - public enum Color - { - Red, - Green, - Blue - } + public class CountryMetadata + { + public string? Continent { get; set; } + + public string? Tag { get; set; } + } + + public enum Color + { + Red, + Green, + Blue } } diff --git a/examples/RapidCMS.Example.Shared/Data/DatabaseEntity.cs b/examples/RapidCMS.Example.Shared/Data/DatabaseEntity.cs index 8051a257..e5afa0cb 100644 --- a/examples/RapidCMS.Example.Shared/Data/DatabaseEntity.cs +++ b/examples/RapidCMS.Example.Shared/Data/DatabaseEntity.cs @@ -1,22 +1,21 @@ using System; using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Example.Shared.Data +namespace RapidCMS.Example.Shared.Data; + +public class DatabaseEntity : IEntity, ICloneable { - public class DatabaseEntity : IEntity, ICloneable - { - public string? Id { get; set; } - public string? Name { get; set; } - public string? Description { get; set; } + public string? Id { get; set; } + public string? Name { get; set; } + public string? Description { get; set; } - public object Clone() + public object Clone() + { + return new DatabaseEntity { - return new DatabaseEntity - { - Id = Id, - Description = Description, - Name = Name - }; - } + Id = Id, + Description = Description, + Name = Name + }; } } diff --git a/examples/RapidCMS.Example.Shared/Data/Details.cs b/examples/RapidCMS.Example.Shared/Data/Details.cs index 038ed495..ea9c1700 100644 --- a/examples/RapidCMS.Example.Shared/Data/Details.cs +++ b/examples/RapidCMS.Example.Shared/Data/Details.cs @@ -5,49 +5,48 @@ using RapidCMS.Core.Attributes; using RapidCMS.UI.Components.Editors; -namespace RapidCMS.Example.Shared.Data +namespace RapidCMS.Example.Shared.Data; + +public class Details : IEntity, ICloneable { - public class Details : IEntity, ICloneable - { - public string? Id { get; set; } + public string? Id { get; set; } - [Required(AllowEmptyStrings = false)] - public string Title { get; set; } = default!; + [Required(AllowEmptyStrings = false)] + public string Title { get; set; } = default!; - [Required(AllowEmptyStrings = false)] - public string History { get; set; } = default!; + [Required(AllowEmptyStrings = false)] + public string History { get; set; } = default!; - [Required] - [ValidateObjectAsProperty] - public NestedDetails Nested { get; set; } = new NestedDetails(); + [Required] + [ValidateObjectAsProperty] + public NestedDetails Nested { get; set; } = new NestedDetails(); - public object Clone() + public object Clone() + { + return new Details { - return new Details + History = History, + Id = Id, + Title = Title, + Nested = new NestedDetails { - History = History, - Id = Id, - Title = Title, - Nested = new NestedDetails - { - Description = Nested.Description, - Tags = Nested.Tags - } - }; - } - - public class NestedDetails : IEntity - { - [MinLength(2)] - [Field(Name = "Tags", EditorType = typeof(ListEditor))] - public List Tags { get; set; } = new List(); + Description = Nested.Description, + Tags = Nested.Tags + } + }; + } + + public class NestedDetails : IEntity + { + [MinLength(2)] + [Field(Name = "Tags", EditorType = typeof(ListEditor))] + public List Tags { get; set; } = new List(); - [Required] - [MinLength(10)] - [Field(Name = "Description")] - public string? Description { get; set; } + [Required] + [MinLength(10)] + [Field(Name = "Description")] + public string? Description { get; set; } - string? IEntity.Id { get; set; } - } + string? IEntity.Id { get; set; } } } diff --git a/examples/RapidCMS.Example.Shared/Data/EntityVariants.cs b/examples/RapidCMS.Example.Shared/Data/EntityVariants.cs index 8fc5a4ec..0203fd5a 100644 --- a/examples/RapidCMS.Example.Shared/Data/EntityVariants.cs +++ b/examples/RapidCMS.Example.Shared/Data/EntityVariants.cs @@ -2,66 +2,65 @@ using System.ComponentModel.DataAnnotations; using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Example.Shared.Data +namespace RapidCMS.Example.Shared.Data; + +public class EntityVariantBase : IEntity, ICloneable { - public class EntityVariantBase : IEntity, ICloneable - { - public int Id { get; set; } - - [Required] - public string? Name { get; set; } + public int Id { get; set; } + + [Required] + public string? Name { get; set; } - string? IEntity.Id { get => Id.ToString(); set => Id = int.Parse(value ?? "0"); } + string? IEntity.Id { get => Id.ToString(); set => Id = int.Parse(value ?? "0"); } - public object Clone() + public object Clone() + { + return this switch { - return this switch + EntityVariantA a => new EntityVariantA + { + Id = a.Id, + Name = a.Name, + NameA1 = a.NameA1 + }, + EntityVariantB b => new EntityVariantB + { + Id = b.Id, + Name = b.Name, + NameB1 = b.NameB1, + NameB2 = b.NameB2 + }, + EntityVariantC c => new EntityVariantC { - EntityVariantA a => new EntityVariantA - { - Id = a.Id, - Name = a.Name, - NameA1 = a.NameA1 - }, - EntityVariantB b => new EntityVariantB - { - Id = b.Id, - Name = b.Name, - NameB1 = b.NameB1, - NameB2 = b.NameB2 - }, - EntityVariantC c => new EntityVariantC - { - Id = c.Id, - Name = c.Name, - NameC1 = c.NameC1, - NameC2 = c.NameC2, - NameC3 = c.NameC3 - }, - EntityVariantBase @base => new EntityVariantBase - { - Id = @base.Id, - Name = @base.Name - } - }; - } + Id = c.Id, + Name = c.Name, + NameC1 = c.NameC1, + NameC2 = c.NameC2, + NameC3 = c.NameC3 + }, + EntityVariantBase @base => new EntityVariantBase + { + Id = @base.Id, + Name = @base.Name + } + }; } +} - public class EntityVariantA : EntityVariantBase - { - public string? NameA1 { get; set; } - } +public class EntityVariantA : EntityVariantBase +{ + public string? NameA1 { get; set; } +} - public class EntityVariantB : EntityVariantBase - { - public string? NameB1 { get; set; } - public string? NameB2 { get; set; } - } +public class EntityVariantB : EntityVariantBase +{ + public string? NameB1 { get; set; } + public string? NameB2 { get; set; } +} - public class EntityVariantC : EntityVariantBase - { - public string? NameC1 { get; set; } - public string? NameC2 { get; set; } - public string? NameC3 { get; set; } - } +public class EntityVariantC : EntityVariantBase +{ + public string? NameC1 { get; set; } + public string? NameC2 { get; set; } + public string? NameC3 { get; set; } } diff --git a/examples/RapidCMS.Example.Shared/Data/MappedEntity.cs b/examples/RapidCMS.Example.Shared/Data/MappedEntity.cs index 1ad34699..e7645c93 100644 --- a/examples/RapidCMS.Example.Shared/Data/MappedEntity.cs +++ b/examples/RapidCMS.Example.Shared/Data/MappedEntity.cs @@ -1,20 +1,19 @@ using System.ComponentModel.DataAnnotations; using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Example.Shared.Data +namespace RapidCMS.Example.Shared.Data; + +public class MappedEntity : IEntity { - public class MappedEntity : IEntity - { - public string? Id { get; set; } + public string? Id { get; set; } - [Required] - [MinLength(5)] - [MaxLength(20)] - public string? Name { get; set; } + [Required] + [MinLength(5)] + [MaxLength(20)] + public string? Name { get; set; } - [Required] - [MinLength(10)] - [MaxLength(1000)] - public string? Description { get; set; } - } + [Required] + [MinLength(10)] + [MaxLength(1000)] + public string? Description { get; set; } } diff --git a/examples/RapidCMS.Example.Shared/Data/Mapper.cs b/examples/RapidCMS.Example.Shared/Data/Mapper.cs index 91b9605e..a0534f26 100644 --- a/examples/RapidCMS.Example.Shared/Data/Mapper.cs +++ b/examples/RapidCMS.Example.Shared/Data/Mapper.cs @@ -1,27 +1,26 @@ using RapidCMS.Repositories; -namespace RapidCMS.Example.Shared.Data +namespace RapidCMS.Example.Shared.Data; + +public class Mapper : IConverter { - public class Mapper : IConverter + public MappedEntity Convert(DatabaseEntity obj) { - public MappedEntity Convert(DatabaseEntity obj) + return new MappedEntity { - return new MappedEntity - { - Description = obj.Description, - Id = obj.Id, - Name = obj.Name - }; - } + Description = obj.Description, + Id = obj.Id, + Name = obj.Name + }; + } - public DatabaseEntity Convert(MappedEntity obj) + public DatabaseEntity Convert(MappedEntity obj) + { + return new DatabaseEntity { - return new DatabaseEntity - { - Description = obj.Description, - Id = obj.Id, - Name = obj.Name - }; - } + Description = obj.Description, + Id = obj.Id, + Name = obj.Name + }; } } diff --git a/examples/RapidCMS.Example.Shared/Data/Person.cs b/examples/RapidCMS.Example.Shared/Data/Person.cs index fb302413..ce430765 100644 --- a/examples/RapidCMS.Example.Shared/Data/Person.cs +++ b/examples/RapidCMS.Example.Shared/Data/Person.cs @@ -3,49 +3,48 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Attributes; -namespace RapidCMS.Example.Shared.Data +namespace RapidCMS.Example.Shared.Data; + +public class Person : IEntity, ICloneable { - public class Person : IEntity, ICloneable - { - public int Id { get; set; } + public int Id { get; set; } - [Required(AllowEmptyStrings = false)] - public string Name { get; set; } = default!; + [Required(AllowEmptyStrings = false)] + public string Name { get; set; } = default!; - // use validate object to instruct validation to also validate PersonDetails - [ValidateObject] - public PersonDetails Details { get; set; } = new PersonDetails(); + // use validate object to instruct validation to also validate PersonDetails + [ValidateObject] + public PersonDetails Details { get; set; } = new PersonDetails(); - public int FavouriteChildId { get; set; } + public int FavouriteChildId { get; set; } - string? IEntity.Id { get => Id.ToString(); set => Id = int.Parse(value ?? "0"); } + string? IEntity.Id { get => Id.ToString(); set => Id = int.Parse(value ?? "0"); } - public object Clone() + public object Clone() + { + return new Person { - return new Person + Id = Id, + Name = Name, + FavouriteChildId = FavouriteChildId, + Details = new PersonDetails { - Id = Id, - Name = Name, - FavouriteChildId = FavouriteChildId, - Details = new PersonDetails - { - Bio = Details.Bio, - Email = Details.Email, - SocialUrl = Details.SocialUrl - } - }; - } - - public class PersonDetails - { - [Required] - [MinLength(5)] - public string Email { get; set; } = default!; + Bio = Details.Bio, + Email = Details.Email, + SocialUrl = Details.SocialUrl + } + }; + } + + public class PersonDetails + { + [Required] + [MinLength(5)] + public string Email { get; set; } = default!; - [Url] - public string? SocialUrl { get; set; } + [Url] + public string? SocialUrl { get; set; } - public string? Bio { get; set; } - } + public string? Bio { get; set; } } } diff --git a/examples/RapidCMS.Example.Shared/Data/TagGroup.cs b/examples/RapidCMS.Example.Shared/Data/TagGroup.cs index 78ef31c1..13755914 100644 --- a/examples/RapidCMS.Example.Shared/Data/TagGroup.cs +++ b/examples/RapidCMS.Example.Shared/Data/TagGroup.cs @@ -3,41 +3,40 @@ using System.Linq; using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Example.Shared.Data +namespace RapidCMS.Example.Shared.Data; + +public class TagGroup : IEntity, ICloneable { - public class TagGroup : IEntity, ICloneable - { - public string? Id { get; set; } - public string? Name { get; set; } + public string? Id { get; set; } + public string? Name { get; set; } - public string? DefaultTagId { get; set; } + public string? DefaultTagId { get; set; } - public List Tags { get; set; } = new List(); + public List Tags { get; set; } = new List(); - public object Clone() + public object Clone() + { + return new TagGroup() { - return new TagGroup() - { - Id = Id, - DefaultTagId = DefaultTagId, - Name = Name, - Tags = Tags.Select(x => (Tag)x.Clone()).ToList() - }; - } + Id = Id, + DefaultTagId = DefaultTagId, + Name = Name, + Tags = Tags.Select(x => (Tag)x.Clone()).ToList() + }; } +} - public class Tag : IEntity, ICloneable - { - public string? Id { get; set; } - public string? Name { get; set; } +public class Tag : IEntity, ICloneable +{ + public string? Id { get; set; } + public string? Name { get; set; } - public object Clone() + public object Clone() + { + return new Tag { - return new Tag - { - Id = Id, - Name = Name - }; - } + Id = Id, + Name = Name + }; } } diff --git a/examples/RapidCMS.Example.Shared/Data/User.cs b/examples/RapidCMS.Example.Shared/Data/User.cs index 9994e97a..4e8b0f8a 100644 --- a/examples/RapidCMS.Example.Shared/Data/User.cs +++ b/examples/RapidCMS.Example.Shared/Data/User.cs @@ -2,55 +2,54 @@ using System.ComponentModel.DataAnnotations; using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Example.Shared.Data +namespace RapidCMS.Example.Shared.Data; + +public class User : IEntity, ICloneable { - public class User : IEntity, ICloneable - { - public int Id { get; set; } - public string? Name { get; set; } - public DateTime? StartDate { get; set; } + public int Id { get; set; } + public string? Name { get; set; } + public DateTime? StartDate { get; set; } - [Required] - // the horror - [RegularExpression("^((?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])|(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[^a-zA-Z0-9])|(?=.*?[A-Z])(?=.*?[0-9])(?=.*?[^a-zA-Z0-9])|(?=.*?[a-z])(?=.*?[0-9])(?=.*?[^a-zA-Z0-9])).{8,}$", - ErrorMessage = "Passwords must be at least 8 characters and contain at 3 of 4 of the following: upper case (A-Z), lower case (a-z), number (0-9) and special character (e.g. !@#$%^&*)")] - public string? Password { get; set; } + [Required] + // the horror + [RegularExpression("^((?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])|(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[^a-zA-Z0-9])|(?=.*?[A-Z])(?=.*?[0-9])(?=.*?[^a-zA-Z0-9])|(?=.*?[a-z])(?=.*?[0-9])(?=.*?[^a-zA-Z0-9])).{8,}$", + ErrorMessage = "Passwords must be at least 8 characters and contain at 3 of 4 of the following: upper case (A-Z), lower case (a-z), number (0-9) and special character (e.g. !@#$%^&*)")] + public string? Password { get; set; } - [Required] - public string? FileBase64 { get; set; } + [Required] + public string? FileBase64 { get; set; } - public string? ProfilePictureBase64 { get; set; } + public string? ProfilePictureBase64 { get; set; } - public int Integer { get; set; } - public double Double { get; set; } + public int Integer { get; set; } + public double Double { get; set; } - public UserRole Role { get; set; } + public UserRole Role { get; set; } - string? IEntity.Id { get => Id.ToString(); set => Id = int.Parse(value ?? "0"); } + string? IEntity.Id { get => Id.ToString(); set => Id = int.Parse(value ?? "0"); } - public object Clone() - { - return new User - { - Id = Id, - Name = Name, - Password = Password, - Double = Double, - FileBase64 = FileBase64, - ProfilePictureBase64 = ProfilePictureBase64, - Integer = Integer, - StartDate = StartDate, - Role = Role - }; - } - - [Flags] - public enum UserRole + public object Clone() + { + return new User { - Viewer = 1, - Editor = 2, - Publisher = 4, - Admin = 8 - } + Id = Id, + Name = Name, + Password = Password, + Double = Double, + FileBase64 = FileBase64, + ProfilePictureBase64 = ProfilePictureBase64, + Integer = Integer, + StartDate = StartDate, + Role = Role + }; + } + + [Flags] + public enum UserRole + { + Viewer = 1, + Editor = 2, + Publisher = 4, + Admin = 8 } } diff --git a/examples/RapidCMS.Example.Shared/DataViews/DatabaseEntityDataViewBuilder.cs b/examples/RapidCMS.Example.Shared/DataViews/DatabaseEntityDataViewBuilder.cs index b3a86da3..aeaadb54 100644 --- a/examples/RapidCMS.Example.Shared/DataViews/DatabaseEntityDataViewBuilder.cs +++ b/examples/RapidCMS.Example.Shared/DataViews/DatabaseEntityDataViewBuilder.cs @@ -7,26 +7,25 @@ using RapidCMS.Core.Models.Data; using RapidCMS.Example.Shared.Data; -namespace RapidCMS.Example.Shared.DataViews +namespace RapidCMS.Example.Shared.DataViews; + +// a DataViewBuilder allows you to create multiple dataviews - views in the same list editor / list views that +// allow the user to more easily find entities +public class DatabaseEntityDataViewBuilder : DataViewBuilder { - // a DataViewBuilder allows you to create multiple dataviews - views in the same list editor / list views that - // allow the user to more easily find entities - public class DatabaseEntityDataViewBuilder : DataViewBuilder + public override Task>> GetDataViewsAsync() { - public override Task>> GetDataViewsAsync() + var list = new List> { - var list = new List> - { - // when the user selects this dataview (by clicking on the corresponding tab) - // the expression is given to the repository, so it can use that expression to perform the correct query - new DataView(1, "[A-K]", x => Regex.IsMatch(x.Name ?? string.Empty, "^[A-K]")) - .SetOrderByExpression(x => x.Name, OrderByType.Descending), - new DataView(2, "[L-Z]", x => Regex.IsMatch(x.Name ?? string.Empty, "^[L-Z]")) - .SetOrderByExpression(x => x.Name, OrderByType.Ascending), - new DataView(3, "[other]", x => Regex.IsMatch(x.Name ?? string.Empty, "^[^A-Z]")) - }; + // when the user selects this dataview (by clicking on the corresponding tab) + // the expression is given to the repository, so it can use that expression to perform the correct query + new DataView(1, "[A-K]", x => Regex.IsMatch(x.Name ?? string.Empty, "^[A-K]")) + .SetOrderByExpression(x => x.Name, OrderByType.Descending), + new DataView(2, "[L-Z]", x => Regex.IsMatch(x.Name ?? string.Empty, "^[L-Z]")) + .SetOrderByExpression(x => x.Name, OrderByType.Ascending), + new DataView(3, "[other]", x => Regex.IsMatch(x.Name ?? string.Empty, "^[^A-Z]")) + }; - return Task.FromResult(list.AsEnumerable()); - } + return Task.FromResult(list.AsEnumerable()); } } diff --git a/examples/RapidCMS.Example.Shared/Handlers/Base64ApiImageUploadHandler.cs b/examples/RapidCMS.Example.Shared/Handlers/Base64ApiImageUploadHandler.cs index bc0e80fc..1400ae4f 100644 --- a/examples/RapidCMS.Example.Shared/Handlers/Base64ApiImageUploadHandler.cs +++ b/examples/RapidCMS.Example.Shared/Handlers/Base64ApiImageUploadHandler.cs @@ -1,12 +1,11 @@ using System.Net.Http; using RapidCMS.Core.Handlers; -namespace RapidCMS.Example.Shared.Handlers +namespace RapidCMS.Example.Shared.Handlers; + +public class Base64ApiImageUploadHandler : ApiFileUploadHandler, IImageUploadHandler { - public class Base64ApiImageUploadHandler : ApiFileUploadHandler, IImageUploadHandler + public Base64ApiImageUploadHandler(IHttpClientFactory httpClientFactory) : base(httpClientFactory) { - public Base64ApiImageUploadHandler(IHttpClientFactory httpClientFactory) : base(httpClientFactory) - { - } } } diff --git a/examples/RapidCMS.Example.Shared/Handlers/Base64ApiTextUploadHandler.cs b/examples/RapidCMS.Example.Shared/Handlers/Base64ApiTextUploadHandler.cs index 8cc0c551..9ef764f9 100644 --- a/examples/RapidCMS.Example.Shared/Handlers/Base64ApiTextUploadHandler.cs +++ b/examples/RapidCMS.Example.Shared/Handlers/Base64ApiTextUploadHandler.cs @@ -1,12 +1,11 @@ using System.Net.Http; using RapidCMS.Core.Handlers; -namespace RapidCMS.Example.Shared.Handlers +namespace RapidCMS.Example.Shared.Handlers; + +public class Base64ApiTextUploadHandler : ApiFileUploadHandler, ITextUploadHandler { - public class Base64ApiTextUploadHandler : ApiFileUploadHandler, ITextUploadHandler + public Base64ApiTextUploadHandler(IHttpClientFactory httpClientFactory) : base(httpClientFactory) { - public Base64ApiTextUploadHandler(IHttpClientFactory httpClientFactory) : base(httpClientFactory) - { - } } } diff --git a/examples/RapidCMS.Example.Shared/Handlers/Base64ImageUploadHandler.cs b/examples/RapidCMS.Example.Shared/Handlers/Base64ImageUploadHandler.cs index 7a5669a9..537b309f 100644 --- a/examples/RapidCMS.Example.Shared/Handlers/Base64ImageUploadHandler.cs +++ b/examples/RapidCMS.Example.Shared/Handlers/Base64ImageUploadHandler.cs @@ -4,41 +4,40 @@ using System.Threading.Tasks; using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Example.Shared.Handlers +namespace RapidCMS.Example.Shared.Handlers; + +public class Base64ImageUploadHandler : IImageUploadHandler { - public class Base64ImageUploadHandler : IImageUploadHandler + public async Task SaveFileAsync(IFileInfo fileInfo, Stream stream) { - public async Task SaveFileAsync(IFileInfo fileInfo, Stream stream) + using (stream) { - using (stream) - { - var buffer = new Memory(new byte[stream.Length]); - await stream.ReadAsync(buffer); + var buffer = new Memory(new byte[stream.Length]); + await stream.ReadAsync(buffer); - // you'd probably don't want to save the base64 string as property in the model - // it's better to upload it to some external storage (Azure Blob Storage) and save it's blob name in the model - // but for this example, it's good enough + // you'd probably don't want to save the base64 string as property in the model + // it's better to upload it to some external storage (Azure Blob Storage) and save it's blob name in the model + // but for this example, it's good enough - return Convert.ToBase64String(buffer.ToArray()); - } + return Convert.ToBase64String(buffer.ToArray()); } + } - public Task> ValidateFileAsync(IFileInfo fileInfo) - { - var errors = new List(); - - // you'd probably want to make this check more thorough as it's trusting completely trusting the user input - if (fileInfo.Type != "image/png") - { - errors.Add("Only .png files are allowed."); - } + public Task> ValidateFileAsync(IFileInfo fileInfo) + { + var errors = new List(); - if (fileInfo.Size > 100 * 1024) - { - errors.Add("Max upload size is 100KB."); - } + // you'd probably want to make this check more thorough as it's trusting completely trusting the user input + if (fileInfo.Type != "image/png") + { + errors.Add("Only .png files are allowed."); + } - return Task.FromResult((IEnumerable)errors); + if (fileInfo.Size > 100 * 1024) + { + errors.Add("Max upload size is 100KB."); } + + return Task.FromResult((IEnumerable)errors); } } diff --git a/examples/RapidCMS.Example.Shared/Handlers/Base64TextFileUploadHandler.cs b/examples/RapidCMS.Example.Shared/Handlers/Base64TextFileUploadHandler.cs index 679c2d53..81592b7d 100644 --- a/examples/RapidCMS.Example.Shared/Handlers/Base64TextFileUploadHandler.cs +++ b/examples/RapidCMS.Example.Shared/Handlers/Base64TextFileUploadHandler.cs @@ -4,40 +4,39 @@ using System.Threading.Tasks; using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Example.Shared.Handlers +namespace RapidCMS.Example.Shared.Handlers; + +public class Base64TextFileUploadHandler : ITextUploadHandler { - public class Base64TextFileUploadHandler : ITextUploadHandler + public async Task SaveFileAsync(IFileInfo fileInfo, Stream stream) { - public async Task SaveFileAsync(IFileInfo fileInfo, Stream stream) + using (stream) { - using (stream) - { - var buffer = new Memory(new byte[stream.Length]); - await stream.ReadAsync(buffer); + var buffer = new Memory(new byte[stream.Length]); + await stream.ReadAsync(buffer); - // you'd probably don't want to save the base64 string as property in the model - // it's better to upload it to some external storage (Azure Blob Storage) and save it's blob name in the model - // but for this example, it's good enough - return Convert.ToBase64String(buffer.ToArray()); - } + // you'd probably don't want to save the base64 string as property in the model + // it's better to upload it to some external storage (Azure Blob Storage) and save it's blob name in the model + // but for this example, it's good enough + return Convert.ToBase64String(buffer.ToArray()); } + } - public Task> ValidateFileAsync(IFileInfo fileInfo) - { - var errors = new List(); - - // you'd probably want to make this check more thorough as it's trusting completely trusting the user input - if (fileInfo.Type != "text/plain") - { - errors.Add("Only .txt files are allowed."); - } + public Task> ValidateFileAsync(IFileInfo fileInfo) + { + var errors = new List(); - if (fileInfo.Size > 10 * 1024) - { - errors.Add("Max upload size is 10KB."); - } + // you'd probably want to make this check more thorough as it's trusting completely trusting the user input + if (fileInfo.Type != "text/plain") + { + errors.Add("Only .txt files are allowed."); + } - return Task.FromResult((IEnumerable)errors); + if (fileInfo.Size > 10 * 1024) + { + errors.Add("Max upload size is 10KB."); } + + return Task.FromResult((IEnumerable)errors); } } diff --git a/examples/RapidCMS.Example.Shared/Handlers/IImageUploadHandler.cs b/examples/RapidCMS.Example.Shared/Handlers/IImageUploadHandler.cs index ed29d4c7..32336c40 100644 --- a/examples/RapidCMS.Example.Shared/Handlers/IImageUploadHandler.cs +++ b/examples/RapidCMS.Example.Shared/Handlers/IImageUploadHandler.cs @@ -1,9 +1,8 @@ using RapidCMS.Core.Abstractions.Handlers; -namespace RapidCMS.Example.Shared.Handlers +namespace RapidCMS.Example.Shared.Handlers; + +public interface IImageUploadHandler : IFileUploadHandler { - public interface IImageUploadHandler : IFileUploadHandler - { - } } diff --git a/examples/RapidCMS.Example.Shared/Handlers/ITextUploadHandler.cs b/examples/RapidCMS.Example.Shared/Handlers/ITextUploadHandler.cs index 7e1bff98..70236727 100644 --- a/examples/RapidCMS.Example.Shared/Handlers/ITextUploadHandler.cs +++ b/examples/RapidCMS.Example.Shared/Handlers/ITextUploadHandler.cs @@ -1,9 +1,8 @@ using RapidCMS.Core.Abstractions.Handlers; -namespace RapidCMS.Example.Shared.Handlers +namespace RapidCMS.Example.Shared.Handlers; + +public interface ITextUploadHandler : IFileUploadHandler { - public interface ITextUploadHandler : IFileUploadHandler - { - } } diff --git a/examples/RapidCMS.Example.Shared/Handlers/NavigateToPersonHandler.cs b/examples/RapidCMS.Example.Shared/Handlers/NavigateToPersonHandler.cs index b55c9910..de6fd20c 100644 --- a/examples/RapidCMS.Example.Shared/Handlers/NavigateToPersonHandler.cs +++ b/examples/RapidCMS.Example.Shared/Handlers/NavigateToPersonHandler.cs @@ -5,15 +5,14 @@ using RapidCMS.Core.Models.Request; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Example.Shared.Handlers +namespace RapidCMS.Example.Shared.Handlers; + +public class NavigateToPersonHandler : INavigationHandler { - public class NavigateToPersonHandler : INavigationHandler + public Task CreateNavigationRequestAsync(ButtonSetup button, FormEditContext editContext) { - public Task CreateNavigationRequestAsync(ButtonSetup button, FormEditContext editContext) - { - // this method can return a NavigationRequest to instruct the CMS to go to that page - // if null is returned, the action is canceled. - return Task.FromResult(NavigationRequest.NavigateToCreateNewEntity("person", default))!; - } + // this method can return a NavigationRequest to instruct the CMS to go to that page + // if null is returned, the action is canceled. + return Task.FromResult(NavigationRequest.NavigateToCreateNewEntity("person", default))!; } } diff --git a/examples/RapidCMS.Example.Shared/Handlers/RandomNameActionHandler.cs b/examples/RapidCMS.Example.Shared/Handlers/RandomNameActionHandler.cs index fdadf87a..17b51c78 100644 --- a/examples/RapidCMS.Example.Shared/Handlers/RandomNameActionHandler.cs +++ b/examples/RapidCMS.Example.Shared/Handlers/RandomNameActionHandler.cs @@ -8,52 +8,51 @@ using RapidCMS.Core.Models.Setup; using RapidCMS.Example.Shared.Data; -namespace RapidCMS.Example.Shared.Handlers +namespace RapidCMS.Example.Shared.Handlers; + +public class RandomNameActionHandler : IButtonActionHandler { - public class RandomNameActionHandler : IButtonActionHandler + // this method is called just before the IRepository action is performed, based upon the CrudType this button returns + public Task ButtonClickBeforeRepositoryActionAsync(ButtonSetup button, FormEditContext editContext, ButtonContext context) { - // this method is called just before the IRepository action is performed, based upon the CrudType this button returns - public Task ButtonClickBeforeRepositoryActionAsync(ButtonSetup button, FormEditContext editContext, ButtonContext context) + if (editContext.Entity is Tag tag) { - if (editContext.Entity is Tag tag) - { - tag.Name = Guid.NewGuid().ToString()[0..6]; - } - - return Task.FromResult(CrudType.None); + tag.Name = Guid.NewGuid().ToString()[0..6]; } - // this method is called after the IRepository action - public Task ButtonClickAfterRepositoryActionAsync(ButtonSetup button, FormEditContext editContext, ButtonContext context) - { - return Task.CompletedTask; - } + return Task.FromResult(CrudType.None); + } - // this method should return any of the Operations defined in RapidCMS.Common.Authorization which - // is used to determine whether the user is allow to perform the action this handler does - public OperationAuthorizationRequirement GetOperation(ButtonSetup button, FormEditContext editContext) - { - return Operations.Read; - } + // this method is called after the IRepository action + public Task ButtonClickAfterRepositoryActionAsync(ButtonSetup button, FormEditContext editContext, ButtonContext context) + { + return Task.CompletedTask; + } - // returning false from this method will hide the button, even if it is specified to be drawn on the form - public bool IsCompatible(ButtonSetup button, FormEditContext editContext) - { - return editContext.Entity is Tag; - } + // this method should return any of the Operations defined in RapidCMS.Common.Authorization which + // is used to determine whether the user is allow to perform the action this handler does + public OperationAuthorizationRequirement GetOperation(ButtonSetup button, FormEditContext editContext) + { + return Operations.Read; + } - // returning true from this method will trigger validation before the click is propagated. if the form is not valid, - // the click is ignored - public bool RequiresValidForm(ButtonSetup button, FormEditContext editContext) - { - return false; - } + // returning false from this method will hide the button, even if it is specified to be drawn on the form + public bool IsCompatible(ButtonSetup button, FormEditContext editContext) + { + return editContext.Entity is Tag; + } - // returning true form this method will trigger an confirm dialog before the click is propagated. this allows the user - // to cancel the action if it is a destructive action - public bool ShouldAskForConfirmation(ButtonSetup button, FormEditContext editContext) - { - return false; - } + // returning true from this method will trigger validation before the click is propagated. if the form is not valid, + // the click is ignored + public bool RequiresValidForm(ButtonSetup button, FormEditContext editContext) + { + return false; + } + + // returning true form this method will trigger an confirm dialog before the click is propagated. this allows the user + // to cancel the action if it is a destructive action + public bool ShouldAskForConfirmation(ButtonSetup button, FormEditContext editContext) + { + return false; } } diff --git a/examples/RapidCMS.Example.Shared/Handlers/ResetAllPasswordsButtonHandler.cs b/examples/RapidCMS.Example.Shared/Handlers/ResetAllPasswordsButtonHandler.cs index cd5dd835..70ccc106 100644 --- a/examples/RapidCMS.Example.Shared/Handlers/ResetAllPasswordsButtonHandler.cs +++ b/examples/RapidCMS.Example.Shared/Handlers/ResetAllPasswordsButtonHandler.cs @@ -7,48 +7,47 @@ using RapidCMS.Core.Forms; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Example.Shared.Handlers +namespace RapidCMS.Example.Shared.Handlers; + +public class ResetAllPasswordsButtonHandler : IButtonActionHandler { - public class ResetAllPasswordsButtonHandler : IButtonActionHandler + public OperationAuthorizationRequirement GetOperation(ButtonSetup button, FormEditContext editContext) + { + // use the RapidCMS.Core.Authorization.Operations to define what action this button represents + // and how the authorization handler must challenge the current logged in user with to see whether they + // can actually perform this action + return Operations.Delete; + } + + public bool IsCompatible(ButtonSetup button, FormEditContext editContext) + { + // check if the button is compatible with the current view and hide it when it is not compatible + return true; + } + + public bool RequiresValidForm(ButtonSetup button, FormEditContext editContext) + { + // enables this button to block the action when the form associated with the button is not valid + return false; + } + + public bool ShouldAskForConfirmation(ButtonSetup button, FormEditContext editContext) + { + // triggers a confirm + return false; + } + + public async Task ButtonClickBeforeRepositoryActionAsync(ButtonSetup button, FormEditContext editContext, ButtonContext context) + { + await Task.Delay(1000); + + // this dictates how the repository must interpret the button action as after the button has been clicked + return CrudType.Refresh; + } + + public Task ButtonClickAfterRepositoryActionAsync(ButtonSetup button, FormEditContext editContext, ButtonContext context) { - public OperationAuthorizationRequirement GetOperation(ButtonSetup button, FormEditContext editContext) - { - // use the RapidCMS.Core.Authorization.Operations to define what action this button represents - // and how the authorization handler must challenge the current logged in user with to see whether they - // can actually perform this action - return Operations.Delete; - } - - public bool IsCompatible(ButtonSetup button, FormEditContext editContext) - { - // check if the button is compatible with the current view and hide it when it is not compatible - return true; - } - - public bool RequiresValidForm(ButtonSetup button, FormEditContext editContext) - { - // enables this button to block the action when the form associated with the button is not valid - return false; - } - - public bool ShouldAskForConfirmation(ButtonSetup button, FormEditContext editContext) - { - // triggers a confirm - return false; - } - - public async Task ButtonClickBeforeRepositoryActionAsync(ButtonSetup button, FormEditContext editContext, ButtonContext context) - { - await Task.Delay(1000); - - // this dictates how the repository must interpret the button action as after the button has been clicked - return CrudType.Refresh; - } - - public Task ButtonClickAfterRepositoryActionAsync(ButtonSetup button, FormEditContext editContext, ButtonContext context) - { - // this method is invoked after the repository has performed their action - return Task.CompletedTask; - } + // this method is invoked after the repository has performed their action + return Task.CompletedTask; } } diff --git a/examples/RapidCMS.Example.Shared/RapidCMS.Example.Shared.csproj b/examples/RapidCMS.Example.Shared/RapidCMS.Example.Shared.csproj index a60c16ae..cacbc360 100644 --- a/examples/RapidCMS.Example.Shared/RapidCMS.Example.Shared.csproj +++ b/examples/RapidCMS.Example.Shared/RapidCMS.Example.Shared.csproj @@ -1,8 +1,7 @@  - net6.0 - 10.0 + net6.0;net8.0 enable @@ -16,6 +15,13 @@ + + + + + + + diff --git a/examples/RapidCMS.Example.Shared/Validators/AbstractValidatorAdapter.cs b/examples/RapidCMS.Example.Shared/Validators/AbstractValidatorAdapter.cs index 85b0a082..2a91fe28 100644 --- a/examples/RapidCMS.Example.Shared/Validators/AbstractValidatorAdapter.cs +++ b/examples/RapidCMS.Example.Shared/Validators/AbstractValidatorAdapter.cs @@ -5,33 +5,32 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Abstractions.Validators; -namespace RapidCMS.Example.Shared.Validators +namespace RapidCMS.Example.Shared.Validators; + +/// +/// This adapter adapts FluentValidation's AbstractValidator to TEntity part of IEntityValidator +/// +/// Since the context is saved as property these validators must be added as transient services. +/// +/// +public class AbstractValidatorAdapter : AbstractValidator, IEntityValidator + where TEntity : IEntity { - /// - /// This adapter adapts FluentValidation's AbstractValidator to TEntity part of IEntityValidator - /// - /// Since the context is saved as property these validators must be added as transient services. - /// - /// - public class AbstractValidatorAdapter : AbstractValidator, IEntityValidator - where TEntity : IEntity - { - protected IValidatorContext _context = default!; + protected IValidatorContext _context = default!; - IEnumerable IEntityValidator.Validate(IValidatorContext context) - { - _context = context; + IEnumerable IEntityValidator.Validate(IValidatorContext context) + { + _context = context; - var result = Validate((TEntity)context.Entity); + var result = Validate((TEntity)context.Entity); - if (result.IsValid) - { - return Enumerable.Empty(); - } - else - { - return result.Errors.Select(error => new ValidationResult(error.ErrorMessage, new[] { error.PropertyName })); - } + if (result.IsValid) + { + return Enumerable.Empty(); + } + else + { + return result.Errors.Select(error => new ValidationResult(error.ErrorMessage, new[] { error.PropertyName })); } } } diff --git a/examples/RapidCMS.Example.Shared/Validators/CountryValidator.cs b/examples/RapidCMS.Example.Shared/Validators/CountryValidator.cs index 5b432b92..1f19a90c 100644 --- a/examples/RapidCMS.Example.Shared/Validators/CountryValidator.cs +++ b/examples/RapidCMS.Example.Shared/Validators/CountryValidator.cs @@ -2,36 +2,35 @@ using FluentValidation; using RapidCMS.Example.Shared.Data; -namespace RapidCMS.Example.Shared.Validators +namespace RapidCMS.Example.Shared.Validators; + +public class CountryValidator : AbstractValidatorAdapter { - public class CountryValidator : AbstractValidatorAdapter + public CountryValidator() { - public CountryValidator() - { - RuleFor(x => x.Name) - .NotEmpty() - .Must(x => x != (_context.Configuration as Config)?.ForbiddenCountryName) - .WithMessage(x => $"The name cannot be '{(_context.Configuration as Config)?.ForbiddenCountryName}'."); - RuleFor(x => x.Metadata.Continent) - .NotEmpty() - .MinimumLength(8) - .MaximumLength(10) - .Must(x => x != (_context.Configuration as Config)?.ForbiddenContinentName) - .WithMessage(x => $"The continent cannot be '{(_context.Configuration as Config)?.ForbiddenContinentName}'."); - RuleFor(x => x.People) - .Must(original => - { - var selectedPeople = _context.RelationContainer.GetRelatedElementIdsFor, int>(x => x.People); + RuleFor(x => x.Name) + .NotEmpty() + .Must(x => x != (_context.Configuration as Config)?.ForbiddenCountryName) + .WithMessage(x => $"The name cannot be '{(_context.Configuration as Config)?.ForbiddenCountryName}'."); + RuleFor(x => x.Metadata.Continent) + .NotEmpty() + .MinimumLength(8) + .MaximumLength(10) + .Must(x => x != (_context.Configuration as Config)?.ForbiddenContinentName) + .WithMessage(x => $"The continent cannot be '{(_context.Configuration as Config)?.ForbiddenContinentName}'."); + RuleFor(x => x.People) + .Must(original => + { + var selectedPeople = _context.RelationContainer.GetRelatedElementIdsFor, int>(x => x.People); - return selectedPeople?.Count <= 2; - }) - .WithMessage("Only two items can be selected."); - } + return selectedPeople?.Count <= 2; + }) + .WithMessage("Only two items can be selected."); + } - public class Config - { - public string? ForbiddenCountryName { get; set; } - public string? ForbiddenContinentName { get; set; } - } + public class Config + { + public string? ForbiddenCountryName { get; set; } + public string? ForbiddenContinentName { get; set; } } } diff --git a/examples/RapidCMS.Example.WebAssembly.API/Program.cs b/examples/RapidCMS.Example.WebAssembly.API/Program.cs index eed05c6a..babe3d67 100644 --- a/examples/RapidCMS.Example.WebAssembly.API/Program.cs +++ b/examples/RapidCMS.Example.WebAssembly.API/Program.cs @@ -7,20 +7,19 @@ using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; -namespace RapidCMS.Example.WebAssembly.API +namespace RapidCMS.Example.WebAssembly.API; + +public class Program { - public class Program + public static void Main(string[] args) { - public static void Main(string[] args) - { - CreateHostBuilder(args).Build().Run(); - } - - public static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => - { - webBuilder.UseStartup(); - }); + CreateHostBuilder(args).Build().Run(); } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); } diff --git a/examples/RapidCMS.Example.WebAssembly.API/RapidCMS.Example.WebAssembly.API.csproj b/examples/RapidCMS.Example.WebAssembly.API/RapidCMS.Example.WebAssembly.API.csproj index 391a3701..05b58175 100644 --- a/examples/RapidCMS.Example.WebAssembly.API/RapidCMS.Example.WebAssembly.API.csproj +++ b/examples/RapidCMS.Example.WebAssembly.API/RapidCMS.Example.WebAssembly.API.csproj @@ -1,9 +1,8 @@  - net6.0 - ASP.NET Core 6.0 - 10.0 + net8.0 + ASP.NET Core 8.0 enable @@ -12,6 +11,11 @@ + + + + + diff --git a/examples/RapidCMS.Example.WebAssembly.API/Startup.cs b/examples/RapidCMS.Example.WebAssembly.API/Startup.cs index e9972684..0c16460e 100644 --- a/examples/RapidCMS.Example.WebAssembly.API/Startup.cs +++ b/examples/RapidCMS.Example.WebAssembly.API/Startup.cs @@ -13,136 +13,135 @@ using RapidCMS.Example.Shared.Validators; using RapidCMS.Repositories; -namespace RapidCMS.Example.WebAssembly.API +namespace RapidCMS.Example.WebAssembly.API; + +public class Startup { - public class Startup + private const bool ConfigureAuthentication = false; + + public Startup(IConfiguration configuration) { - private const bool ConfigureAuthentication = false; + Configuration = configuration; + } - public Startup(IConfiguration configuration) + public IConfiguration Configuration { get; } + + public void ConfigureServices(IServiceCollection services) + { + // first, add the repositories to the DI + services.AddScoped>(); + services.AddScoped>(); + services.AddScoped>(); + services.AddScoped>(); + services.AddScoped>(); + services.AddScoped>(); + services.AddScoped>(); + services.AddScoped>(); + services.AddScoped>(); + services.AddSingleton, Mapper>(); + services.AddSingleton(); + + services.AddTransient(); + services.AddTransient(); + + // the country entity is validated by a FluentValidator + services.AddSingleton(); + + if (ConfigureAuthentication) { - Configuration = configuration; + ConfigureOpenIDConnectAuthentication(services); + services.AddSingleton(); } - public IConfiguration Configuration { get; } - - public void ConfigureServices(IServiceCollection services) + services.AddRapidCMSWebApi(config => { - // first, add the repositories to the DI - services.AddScoped>(); - services.AddScoped>(); - services.AddScoped>(); - services.AddScoped>(); - services.AddScoped>(); - services.AddScoped>(); - services.AddScoped>(); - services.AddScoped>(); - services.AddScoped>(); - services.AddSingleton, Mapper>(); - services.AddSingleton(); - - services.AddTransient(); - services.AddTransient(); - - // the country entity is validated by a FluentValidator - services.AddSingleton(); - - if (ConfigureAuthentication) + if (!ConfigureAuthentication) { - ConfigureOpenIDConnectAuthentication(services); - services.AddSingleton(); + // it is highly recommended that you add authentication to your API, but for starting + // quickly the AllowAnonymousUser is also supported in the API. + config.AllowAnonymousUser(); } - services.AddRapidCMSWebApi(config => - { - if (!ConfigureAuthentication) - { - // it is highly recommended that you add authentication to your API, but for starting - // quickly the AllowAnonymousUser is also supported in the API. - config.AllowAnonymousUser(); - } - - // then register the repositories to RapidCMS API, so it can create controllers for them - config.RegisterRepository>(); - config.RegisterRepository>(); - config.RegisterRepository>(); - config.RegisterRepository>(); - config.RegisterRepository>(); - config.RegisterRepository>(); - config.RegisterRepository>(); - config.RegisterRepository>(); - - // if collections use data view builders, they can also be backed by an API - // if a collection uses a ApiRepository, then it's data view builder must also be API backed - config.RegisterDataViewBuilder("mapped"); - - config.RegisterFileUploadHandler(); - config.RegisterFileUploadHandler(); - - config.RegisterEntityValidator(new CountryValidator.Config - { - ForbiddenContinentName = "fdsafdsa", - ForbiddenCountryName = "fdsa" - }); - }); + // then register the repositories to RapidCMS API, so it can create controllers for them + config.RegisterRepository>(); + config.RegisterRepository>(); + config.RegisterRepository>(); + config.RegisterRepository>(); + config.RegisterRepository>(); + config.RegisterRepository>(); + config.RegisterRepository>(); + config.RegisterRepository>(); + + // if collections use data view builders, they can also be backed by an API + // if a collection uses a ApiRepository, then it's data view builder must also be API backed + config.RegisterDataViewBuilder("mapped"); + + config.RegisterFileUploadHandler(); + config.RegisterFileUploadHandler(); - services.AddCors(); - // this lines the generic repository controllers up for use by your mvc application, but still gives - // you access to the IMvcBuilder and MvcOptions for extra configuration like authentication - services.AddRapidCMSControllers(config => + config.RegisterEntityValidator(new CountryValidator.Config { - if (ConfigureAuthentication) - { - config.Filters.Add(new AuthorizeFilter("default")); - } + ForbiddenContinentName = "fdsafdsa", + ForbiddenCountryName = "fdsa" }); - } + }); - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + services.AddCors(); + // this lines the generic repository controllers up for use by your mvc application, but still gives + // you access to the IMvcBuilder and MvcOptions for extra configuration like authentication + services.AddRapidCMSControllers(config => { - if (env.IsDevelopment()) + if (ConfigureAuthentication) { - app.UseDeveloperExceptionPage(); + config.Filters.Add(new AuthorizeFilter("default")); } + }); + } - app.UseHttpsRedirection(); - app.UseCors(builder => builder - .WithOrigins("https://localhost:5001") - .AllowAnyMethod() - .AllowAnyHeader() - .AllowCredentials()); + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } - app.UseRouting(); + app.UseHttpsRedirection(); + app.UseCors(builder => builder + .WithOrigins("https://localhost:5001") + .AllowAnyMethod() + .AllowAnyHeader() + .AllowCredentials()); - app.UseAuthentication(); - app.UseAuthorization(); + app.UseRouting(); - app.UseEndpoints(endpoints => - { - endpoints.MapControllers(); - }); - } + app.UseAuthentication(); + app.UseAuthorization(); - private void ConfigureOpenIDConnectAuthentication(IServiceCollection services) + app.UseEndpoints(endpoints => { - services - .AddAuthorization(options => - { - options.AddPolicy("default", builder => - { - builder.RequireAuthenticatedUser(); - }); - }); + endpoints.MapControllers(); + }); + } - services - .AddAuthentication(options => - { - options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; - }) - .AddJwtBearer(options => + private void ConfigureOpenIDConnectAuthentication(IServiceCollection services) + { + services + .AddAuthorization(options => + { + options.AddPolicy("default", builder => { - Configuration.Bind("AzureAd", options); + builder.RequireAuthenticatedUser(); }); - } + }); + + services + .AddAuthentication(options => + { + options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; + }) + .AddJwtBearer(options => + { + Configuration.Bind("AzureAd", options); + }); } } diff --git a/examples/RapidCMS.Example.WebAssembly.FunctionAPI/Authentication/AuthenticationConfig.cs b/examples/RapidCMS.Example.WebAssembly.FunctionAPI/Authentication/AuthenticationConfig.cs index edfd480f..b41962cc 100644 --- a/examples/RapidCMS.Example.WebAssembly.FunctionAPI/Authentication/AuthenticationConfig.cs +++ b/examples/RapidCMS.Example.WebAssembly.FunctionAPI/Authentication/AuthenticationConfig.cs @@ -1,11 +1,10 @@ using System; -namespace RapidCMS.Example.WebAssembly.FunctionAPI.Authentication +namespace RapidCMS.Example.WebAssembly.FunctionAPI.Authentication; + +public class AuthenticationConfig { - public class AuthenticationConfig - { - public Uri Authority { get; set; } = default!; - public string ValidAudience { get; set; } = default!; - public string ValidIssuer { get; set; } = default!; - } + public Uri Authority { get; set; } = default!; + public string ValidAudience { get; set; } = default!; + public string ValidIssuer { get; set; } = default!; } diff --git a/examples/RapidCMS.Example.WebAssembly.FunctionAPI/Authentication/AuthenticationMiddleware.cs b/examples/RapidCMS.Example.WebAssembly.FunctionAPI/Authentication/AuthenticationMiddleware.cs index b2e91505..d062eb2c 100644 --- a/examples/RapidCMS.Example.WebAssembly.FunctionAPI/Authentication/AuthenticationMiddleware.cs +++ b/examples/RapidCMS.Example.WebAssembly.FunctionAPI/Authentication/AuthenticationMiddleware.cs @@ -13,124 +13,123 @@ using Microsoft.IdentityModel.Protocols.OpenIdConnect; using Microsoft.IdentityModel.Tokens; -namespace RapidCMS.Example.WebAssembly.FunctionAPI.Authentication +namespace RapidCMS.Example.WebAssembly.FunctionAPI.Authentication; + +// PREVIEW: this middleware is temporary and should be replaced with something first party when Azure Functions on .NET 5.0 supports better middleware +public class AuthenticationMiddleware { - // PREVIEW: this middleware is temporary and should be replaced with something first party when Azure Functions on .NET 5.0 supports better middleware - public class AuthenticationMiddleware - { - private readonly AuthenticationConfig _authenticationConfig; + private readonly AuthenticationConfig _authenticationConfig; - public AuthenticationMiddleware(IOptions authenticationConfig) - { - _authenticationConfig = authenticationConfig.Value; - } + public AuthenticationMiddleware(IOptions authenticationConfig) + { + _authenticationConfig = authenticationConfig.Value; + } - public async Task InvokeAsync(FunctionContext context, FunctionExecutionDelegate next) + public async Task InvokeAsync(FunctionContext context, FunctionExecutionDelegate next) + { + if (GetRequestData(context) is HttpRequestData request) { - if (GetRequestData(context) is HttpRequestData request) + try { - try + var authorizationHeader = request.Headers.FirstOrDefault(x => x.Key.Equals("authorization", StringComparison.InvariantCultureIgnoreCase)); + if (authorizationHeader.Value is IEnumerable headerValue) { - var authorizationHeader = request.Headers.FirstOrDefault(x => x.Key.Equals("authorization", StringComparison.InvariantCultureIgnoreCase)); - if (authorizationHeader.Value is IEnumerable headerValue) + var user = await GetValidUserAsync(headerValue.FirstOrDefault()); + if (user != null) { - var user = await GetValidUserAsync(headerValue.FirstOrDefault()); - if (user != null) - { - context.Items.Add("User", user); - await next(context); - return; - } + context.Items.Add("User", user); + await next(context); + return; } } - catch { } - - // NOTE: this middleware requires an authenticated user - SetRequestResponse(context, request.CreateResponse(HttpStatusCode.Unauthorized)); - return; } + catch { } - await next(context); + // NOTE: this middleware requires an authenticated user + SetRequestResponse(context, request.CreateResponse(HttpStatusCode.Unauthorized)); + return; } - // PREVIEW: getting stuff via Reflection is bad. - private static HttpRequestData? GetRequestData(FunctionContext context) - { - // Use reflection to grab HttpRequestData - var keyValuePair = context.Features.SingleOrDefault(f => f.Key.Name == "IFunctionBindingsFeature"); - var functionBindingsFeature = keyValuePair.Value; - var type = functionBindingsFeature.GetType(); - var inputData = type.GetProperties().Single(p => p.Name == "InputData").GetValue(functionBindingsFeature) as IReadOnlyDictionary; - return inputData?.Values.SingleOrDefault(o => o is HttpRequestData) as HttpRequestData; - } + await next(context); + } - // PREVIEW: setting stuff via Reflection is bad. - private static void SetRequestResponse(FunctionContext context, HttpResponseData response) - { - var keyValuePair = context.Features.SingleOrDefault(f => f.Key.Name == "IFunctionBindingsFeature"); - var functionBindingsFeature = keyValuePair.Value; - var type = functionBindingsFeature.GetType(); - var result = type.GetProperties().Single(p => p.Name == "InvocationResult"); - result.SetValue(functionBindingsFeature, response); - } + // PREVIEW: getting stuff via Reflection is bad. + private static HttpRequestData? GetRequestData(FunctionContext context) + { + // Use reflection to grab HttpRequestData + var keyValuePair = context.Features.SingleOrDefault(f => f.Key.Name == "IFunctionBindingsFeature"); + var functionBindingsFeature = keyValuePair.Value; + var type = functionBindingsFeature.GetType(); + var inputData = type.GetProperties().Single(p => p.Name == "InputData").GetValue(functionBindingsFeature) as IReadOnlyDictionary; + return inputData?.Values.SingleOrDefault(o => o is HttpRequestData) as HttpRequestData; + } - public async Task GetValidUserAsync(string? authorizationHeader) - { - var configurationManager = BuildConfigurationManager(_authenticationConfig.Authority); - var accessToken = GetAccessToken(authorizationHeader); + // PREVIEW: setting stuff via Reflection is bad. + private static void SetRequestResponse(FunctionContext context, HttpResponseData response) + { + var keyValuePair = context.Features.SingleOrDefault(f => f.Key.Name == "IFunctionBindingsFeature"); + var functionBindingsFeature = keyValuePair.Value; + var type = functionBindingsFeature.GetType(); + var result = type.GetProperties().Single(p => p.Name == "InvocationResult"); + result.SetValue(functionBindingsFeature, response); + } - try - { - IdentityModelEventSource.ShowPII = true; + public async Task GetValidUserAsync(string? authorizationHeader) + { + var configurationManager = BuildConfigurationManager(_authenticationConfig.Authority); + var accessToken = GetAccessToken(authorizationHeader); - var oidcWellknownEndpoints = await configurationManager.GetConfigurationAsync(); + try + { + IdentityModelEventSource.ShowPII = true; - var tokenValidator = new JwtSecurityTokenHandler - { - MapInboundClaims = _authenticationConfig.Authority.AbsoluteUri.Contains("microsoft") - }; + var oidcWellknownEndpoints = await configurationManager.GetConfigurationAsync(); - var validationParameters = new TokenValidationParameters - { - RequireSignedTokens = true, - ValidateAudience = true, - ValidAudience = _authenticationConfig.ValidAudience, - ValidateLifetime = true, - ValidateIssuer = true, - ValidateIssuerSigningKey = true, - IssuerSigningKeys = oidcWellknownEndpoints.SigningKeys, - ValidIssuer = _authenticationConfig.ValidIssuer - }; - - return tokenValidator.ValidateToken(accessToken, validationParameters, out var securityToken); - } - catch (Exception ex) when (ex is not UnauthorizedAccessException) + var tokenValidator = new JwtSecurityTokenHandler { - throw new UnauthorizedAccessException(ex.Message); - } - } - - private static Microsoft.IdentityModel.Protocols.ConfigurationManager BuildConfigurationManager(Uri instanceUri) - { - var wellKnownEndpoint = $"{instanceUri}/.well-known/openid-configuration"; + MapInboundClaims = _authenticationConfig.Authority.AbsoluteUri.Contains("microsoft") + }; - var documentRetriever = new Microsoft.IdentityModel.Protocols.HttpDocumentRetriever() + var validationParameters = new TokenValidationParameters { - RequireHttps = instanceUri.Scheme == "https" + RequireSignedTokens = true, + ValidateAudience = true, + ValidAudience = _authenticationConfig.ValidAudience, + ValidateLifetime = true, + ValidateIssuer = true, + ValidateIssuerSigningKey = true, + IssuerSigningKeys = oidcWellknownEndpoints.SigningKeys, + ValidIssuer = _authenticationConfig.ValidIssuer }; - return new Microsoft.IdentityModel.Protocols.ConfigurationManager(wellKnownEndpoint, new OpenIdConnectConfigurationRetriever(), documentRetriever); + return tokenValidator.ValidateToken(accessToken, validationParameters, out var securityToken); + } + catch (Exception ex) when (ex is not UnauthorizedAccessException) + { + throw new UnauthorizedAccessException(ex.Message); } + } + + private static Microsoft.IdentityModel.Protocols.ConfigurationManager BuildConfigurationManager(Uri instanceUri) + { + var wellKnownEndpoint = $"{instanceUri}/.well-known/openid-configuration"; - private static string GetAccessToken(string? authorizationHeader) + var documentRetriever = new Microsoft.IdentityModel.Protocols.HttpDocumentRetriever() { - if (string.IsNullOrEmpty(authorizationHeader) || !authorizationHeader.Contains("Bearer ")) - { - throw new UnauthorizedAccessException(); - } + RequireHttps = instanceUri.Scheme == "https" + }; - var accessToken = authorizationHeader["Bearer ".Length..]; - return accessToken; + return new Microsoft.IdentityModel.Protocols.ConfigurationManager(wellKnownEndpoint, new OpenIdConnectConfigurationRetriever(), documentRetriever); + } + + private static string GetAccessToken(string? authorizationHeader) + { + if (string.IsNullOrEmpty(authorizationHeader) || !authorizationHeader.Contains("Bearer ")) + { + throw new UnauthorizedAccessException(); } + + var accessToken = authorizationHeader["Bearer ".Length..]; + return accessToken; } } diff --git a/examples/RapidCMS.Example.WebAssembly.FunctionAPI/Authentication/FunctionsWorkerApplicationBuilderExtensions.cs b/examples/RapidCMS.Example.WebAssembly.FunctionAPI/Authentication/FunctionsWorkerApplicationBuilderExtensions.cs index a5bd4a7e..0e584a2e 100644 --- a/examples/RapidCMS.Example.WebAssembly.FunctionAPI/Authentication/FunctionsWorkerApplicationBuilderExtensions.cs +++ b/examples/RapidCMS.Example.WebAssembly.FunctionAPI/Authentication/FunctionsWorkerApplicationBuilderExtensions.cs @@ -1,23 +1,22 @@ using Microsoft.Azure.Functions.Worker; using Microsoft.Extensions.DependencyInjection; -namespace RapidCMS.Example.WebAssembly.FunctionAPI.Authentication +namespace RapidCMS.Example.WebAssembly.FunctionAPI.Authentication; + +public static class FunctionsWorkerApplicationBuilderExtensions { - public static class FunctionsWorkerApplicationBuilderExtensions + // PREVIEW: this class is temporary + public static IFunctionsWorkerApplicationBuilder UseAuthorization(this IFunctionsWorkerApplicationBuilder builder) { - // PREVIEW: this class is temporary - public static IFunctionsWorkerApplicationBuilder UseAuthorization(this IFunctionsWorkerApplicationBuilder builder) - { - builder.Services.AddSingleton(); + builder.Services.AddSingleton(); - return builder.Use(next => + return builder.Use(next => + { + return context => { - return context => - { - var middleware = context.InstanceServices.GetRequiredService(); - return middleware.InvokeAsync(context, next); - }; - }); - } + var middleware = context.InstanceServices.GetRequiredService(); + return middleware.InvokeAsync(context, next); + }; + }); } } diff --git a/examples/RapidCMS.Example.WebAssembly.FunctionAPI/Program.cs b/examples/RapidCMS.Example.WebAssembly.FunctionAPI/Program.cs index 9247c716..fbff8ade 100644 --- a/examples/RapidCMS.Example.WebAssembly.FunctionAPI/Program.cs +++ b/examples/RapidCMS.Example.WebAssembly.FunctionAPI/Program.cs @@ -2,33 +2,32 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; -namespace RapidCMS.Example.WebAssembly.FunctionAPI +namespace RapidCMS.Example.WebAssembly.FunctionAPI; + +class Program { - class Program + static async Task Main(string[] args) { - static async Task Main(string[] args) - { - Startup? startup = null; + Startup? startup = null; - var host = new HostBuilder() - .ConfigureAppConfiguration(config => - { - config.AddCommandLine(args); - config.AddEnvironmentVariables(); - }) - .ConfigureFunctionsWorkerDefaults((context, builder) => - { - startup ??= new Startup(context.Configuration); - startup.ConfigureWorker(builder); - }) - .ConfigureServices((context, services) => - { - startup ??= new Startup(context.Configuration); - startup.ConfigureServices(services); - }) - .Build(); + var host = new HostBuilder() + .ConfigureAppConfiguration(config => + { + config.AddCommandLine(args); + config.AddEnvironmentVariables(); + }) + .ConfigureFunctionsWorkerDefaults((context, builder) => + { + startup ??= new Startup(context.Configuration); + startup.ConfigureWorker(builder); + }) + .ConfigureServices((context, services) => + { + startup ??= new Startup(context.Configuration); + startup.ConfigureServices(services); + }) + .Build(); - await host.RunAsync(); - } + await host.RunAsync(); } } diff --git a/examples/RapidCMS.Example.WebAssembly.FunctionAPI/RapidCMS.Example.WebAssembly.FunctionAPI.csproj b/examples/RapidCMS.Example.WebAssembly.FunctionAPI/RapidCMS.Example.WebAssembly.FunctionAPI.csproj index 7133da8e..955bc024 100644 --- a/examples/RapidCMS.Example.WebAssembly.FunctionAPI/RapidCMS.Example.WebAssembly.FunctionAPI.csproj +++ b/examples/RapidCMS.Example.WebAssembly.FunctionAPI/RapidCMS.Example.WebAssembly.FunctionAPI.csproj @@ -2,7 +2,6 @@ false net6.0 - preview v4 Azure Functions .NET 6.0 Isolated Exe diff --git a/examples/RapidCMS.Example.WebAssembly.FunctionAPI/Startup.cs b/examples/RapidCMS.Example.WebAssembly.FunctionAPI/Startup.cs index 7c204408..2d6f8309 100644 --- a/examples/RapidCMS.Example.WebAssembly.FunctionAPI/Startup.cs +++ b/examples/RapidCMS.Example.WebAssembly.FunctionAPI/Startup.cs @@ -11,75 +11,74 @@ using RapidCMS.Example.WebAssembly.FunctionAPI.Authentication; using RapidCMS.Repositories; -namespace RapidCMS.Example.WebAssembly.FunctionAPI +namespace RapidCMS.Example.WebAssembly.FunctionAPI; + +public class Startup { - public class Startup - { - private const bool ConfigureAuthentication = false; + private const bool ConfigureAuthentication = false; - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } - public IConfiguration Configuration { get; } + public IConfiguration Configuration { get; } - public void ConfigureServices(IServiceCollection services) - { - services.AddScoped>(); - services.AddScoped>(); - services.AddScoped>(); - services.AddScoped>(); - services.AddScoped>(); - services.AddScoped>(); - services.AddScoped>(); - services.AddScoped>(); - services.AddScoped>(); - services.AddSingleton, Mapper>(); - services.AddSingleton(); + public void ConfigureServices(IServiceCollection services) + { + services.AddScoped>(); + services.AddScoped>(); + services.AddScoped>(); + services.AddScoped>(); + services.AddScoped>(); + services.AddScoped>(); + services.AddScoped>(); + services.AddScoped>(); + services.AddScoped>(); + services.AddSingleton, Mapper>(); + services.AddSingleton(); - services.AddTransient(); - services.AddTransient(); + services.AddTransient(); + services.AddTransient(); - services.AddOptions().Bind(Configuration.GetSection("AzureAd")); + services.AddOptions().Bind(Configuration.GetSection("AzureAd")); - services.AddAuthorizationCore(); - services.AddSingleton(); + services.AddAuthorizationCore(); + services.AddSingleton(); - // the country entity is validated by a FluentValidator - services.AddSingleton(); + // the country entity is validated by a FluentValidator + services.AddSingleton(); - services.AddRapidCMSFunctions(config => + services.AddRapidCMSFunctions(config => + { + if (!ConfigureAuthentication) { - if (!ConfigureAuthentication) - { - config.AllowAnonymousUser(); - } + config.AllowAnonymousUser(); + } - config.RegisterRepository>(); - config.RegisterRepository>(); - config.RegisterRepository>(); - config.RegisterRepository>(); - config.RegisterRepository>(); - config.RegisterRepository>(); - config.RegisterRepository>(); - config.RegisterRepository>(); + config.RegisterRepository>(); + config.RegisterRepository>(); + config.RegisterRepository>(); + config.RegisterRepository>(); + config.RegisterRepository>(); + config.RegisterRepository>(); + config.RegisterRepository>(); + config.RegisterRepository>(); - config.RegisterDataViewBuilder("mapped"); + config.RegisterDataViewBuilder("mapped"); - config.RegisterFileUploadHandler(); - config.RegisterFileUploadHandler(); - }); - } + config.RegisterFileUploadHandler(); + config.RegisterFileUploadHandler(); + }); + } - public void ConfigureWorker(IFunctionsWorkerApplicationBuilder builder) + public void ConfigureWorker(IFunctionsWorkerApplicationBuilder builder) + { + if (ConfigureAuthentication) { - if (ConfigureAuthentication) - { - builder.UseAuthorization(); - } - - builder.UseFunctionExecutionMiddleware(); + builder.UseAuthorization(); } + + builder.UseFunctionExecutionMiddleware(); } } diff --git a/examples/RapidCMS.Example.WebAssembly/Program.cs b/examples/RapidCMS.Example.WebAssembly/Program.cs index 91b4db9b..9166eab1 100644 --- a/examples/RapidCMS.Example.WebAssembly/Program.cs +++ b/examples/RapidCMS.Example.WebAssembly/Program.cs @@ -17,186 +17,185 @@ using RapidCMS.Repositories; using RapidCMS.Repositories.ApiBridge; -namespace RapidCMS.Example.WebAssembly +namespace RapidCMS.Example.WebAssembly; + +public class Program { - public class Program - { - private const bool ConfigureAuthentication = false; - // web api (run this project along with RapidCMS.Example.WebAssembly.API) - private static readonly Uri BaseUri = new Uri("https://localhost:5003/api/"); - // function api (run this project along with RapidCMS.Example.WebAssembly.FunctionAPI) - // private static readonly Uri BaseUri = new Uri("http://localhost:7071/api/"); + private const bool ConfigureAuthentication = false; + // web api (run this project along with RapidCMS.Example.WebAssembly.API) + private static readonly Uri BaseUri = new Uri("https://localhost:5003/api/"); + // function api (run this project along with RapidCMS.Example.WebAssembly.FunctionAPI) + // private static readonly Uri BaseUri = new Uri("http://localhost:7071/api/"); - public static async Task Main(string[] args) - { - var builder = WebAssemblyHostBuilder.CreateDefault(args); - builder.RootComponents.Add("#app"); + public static async Task Main(string[] args) + { + var builder = WebAssemblyHostBuilder.CreateDefault(args); + builder.RootComponents.Add("#app"); - builder.Services.AddAuthorizationCore(); + builder.Services.AddAuthorizationCore(); - if (ConfigureAuthentication) + if (ConfigureAuthentication) + { + // the builder given to AddRapidCMSApiTokenAuthorization is used to build all message handlers + // for each of the repositories http client. + builder.Services.AddRapidCMSApiTokenAuthorization(sp => { - // the builder given to AddRapidCMSApiTokenAuthorization is used to build all message handlers - // for each of the repositories http client. - builder.Services.AddRapidCMSApiTokenAuthorization(sp => - { - var handler = sp.GetRequiredService(); - handler.ConfigureHandler(new[] { BaseUri.AbsoluteUri }); - return handler; - }); - } - - // with LocalStorageRepository collections can store their data in the local storage of - // the user, making personalization quite easy - builder.Services.AddBlazoredLocalStorage(); - builder.Services.AddScoped, LocalStorageRepository>(); + var handler = sp.GetRequiredService(); + handler.ConfigureHandler(new[] { BaseUri.AbsoluteUri }); + return handler; + }); + } - // it's not required to add your repositories under the base repository - // but this allows the Server and the WebAssembly examples to share the collection configuration + // with LocalStorageRepository collections can store their data in the local storage of + // the user, making personalization quite easy + builder.Services.AddBlazoredLocalStorage(); + builder.Services.AddScoped, LocalStorageRepository>(); - // AddRapidCMSApiRepository allows you to add ApiRepositories which are lined up with a correct HttpClient to - // work seamlessly with a repository on the API side of things (See RapidCMS.Example.WebAssembly.API) - if (!ConfigureAuthentication) - { - builder.Services.AddRapidCMSApiRepository, ApiRepository>(BaseUri); - builder.Services.AddRapidCMSApiRepository, ApiRepository
>(BaseUri); - builder.Services.AddRapidCMSApiRepository, ApiRepository>(BaseUri); - builder.Services.AddRapidCMSApiRepository, ApiRepository>(BaseUri); - builder.Services.AddRapidCMSApiRepository, ApiRepository>(BaseUri); - builder.Services.AddRapidCMSApiRepository, ApiRepository>(BaseUri); - builder.Services.AddRapidCMSApiRepository, ApiRepository>(BaseUri); - - // api repositories can also be mapped - builder.Services.AddRapidCMSApiRepository< - BaseMappedRepository, - ApiMappedRepository>(BaseUri); - } - else - { - // The AuthorizationMessageHandler forwards the auth token from the frontend to the backend, allowing you to validate the user easily - builder.Services.AddRapidCMSAuthenticatedApiRepository, ApiRepository, AuthorizationMessageHandler>(BaseUri); - builder.Services.AddRapidCMSAuthenticatedApiRepository, ApiRepository
, AuthorizationMessageHandler>(BaseUri); - builder.Services.AddRapidCMSAuthenticatedApiRepository, ApiRepository, AuthorizationMessageHandler>(BaseUri); - builder.Services.AddRapidCMSAuthenticatedApiRepository, ApiRepository, AuthorizationMessageHandler>(BaseUri); - builder.Services.AddRapidCMSAuthenticatedApiRepository, ApiRepository, AuthorizationMessageHandler>(BaseUri); - builder.Services.AddRapidCMSAuthenticatedApiRepository, ApiRepository, AuthorizationMessageHandler>(BaseUri); - builder.Services.AddRapidCMSAuthenticatedApiRepository, ApiRepository, AuthorizationMessageHandler>(BaseUri); - - // api repositories can also be mapped - builder.Services.AddRapidCMSAuthenticatedApiRepository< - BaseMappedRepository, - ApiMappedRepository, - AuthorizationMessageHandler>(BaseUri); - builder.Services.AddSingleton(); - } + // it's not required to add your repositories under the base repository + // but this allows the Server and the WebAssembly examples to share the collection configuration + // AddRapidCMSApiRepository allows you to add ApiRepositories which are lined up with a correct HttpClient to + // work seamlessly with a repository on the API side of things (See RapidCMS.Example.WebAssembly.API) + if (!ConfigureAuthentication) + { + builder.Services.AddRapidCMSApiRepository, ApiRepository>(BaseUri); + builder.Services.AddRapidCMSApiRepository, ApiRepository
>(BaseUri); + builder.Services.AddRapidCMSApiRepository, ApiRepository>(BaseUri); + builder.Services.AddRapidCMSApiRepository, ApiRepository>(BaseUri); + builder.Services.AddRapidCMSApiRepository, ApiRepository>(BaseUri); + builder.Services.AddRapidCMSApiRepository, ApiRepository>(BaseUri); + builder.Services.AddRapidCMSApiRepository, ApiRepository>(BaseUri); + + // api repositories can also be mapped + builder.Services.AddRapidCMSApiRepository< + BaseMappedRepository, + ApiMappedRepository>(BaseUri); + } + else + { + // The AuthorizationMessageHandler forwards the auth token from the frontend to the backend, allowing you to validate the user easily + builder.Services.AddRapidCMSAuthenticatedApiRepository, ApiRepository, AuthorizationMessageHandler>(BaseUri); + builder.Services.AddRapidCMSAuthenticatedApiRepository, ApiRepository
, AuthorizationMessageHandler>(BaseUri); + builder.Services.AddRapidCMSAuthenticatedApiRepository, ApiRepository, AuthorizationMessageHandler>(BaseUri); + builder.Services.AddRapidCMSAuthenticatedApiRepository, ApiRepository, AuthorizationMessageHandler>(BaseUri); + builder.Services.AddRapidCMSAuthenticatedApiRepository, ApiRepository, AuthorizationMessageHandler>(BaseUri); + builder.Services.AddRapidCMSAuthenticatedApiRepository, ApiRepository, AuthorizationMessageHandler>(BaseUri); + builder.Services.AddRapidCMSAuthenticatedApiRepository, ApiRepository, AuthorizationMessageHandler>(BaseUri); + + // api repositories can also be mapped + builder.Services.AddRapidCMSAuthenticatedApiRepository< + BaseMappedRepository, + ApiMappedRepository, + AuthorizationMessageHandler>(BaseUri); builder.Services.AddSingleton(); - builder.Services.AddScoped, CounterRepository>(); + } + + builder.Services.AddSingleton(); + builder.Services.AddScoped, CounterRepository>(); - builder.Services.AddSingleton(); - builder.Services.AddSingleton(); - builder.Services.AddTransient(); + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); + builder.Services.AddTransient(); - builder.Services.AddTransient(); - builder.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddTransient(); - // the country entity is validated by a FluentValidator - builder.Services.AddSingleton(); + // the country entity is validated by a FluentValidator + builder.Services.AddSingleton(); + if (!ConfigureAuthentication) + { + // just like the repositories, the file uploads are also forwarded to the backend API + // the handler should also be registered on the API side + builder.Services.AddRapidCMSFileUploadApiHttpClient(BaseUri); + builder.Services.AddRapidCMSFileUploadApiHttpClient(BaseUri); + } + else + { + // when authentication is enabled, the auth token from the frontend should be forwarded to the file upload API + builder.Services.AddRapidCMSAuthenticatedFileUploadApiHttpClient(BaseUri); + builder.Services.AddRapidCMSAuthenticatedFileUploadApiHttpClient(BaseUri); + } + + if (ConfigureAuthentication) + { + ConfigureOpenIDConnectAuthentication(builder); + } + + builder.Services.AddRapidCMSWebAssembly(config => + { if (!ConfigureAuthentication) { - // just like the repositories, the file uploads are also forwarded to the backend API - // the handler should also be registered on the API side - builder.Services.AddRapidCMSFileUploadApiHttpClient(BaseUri); - builder.Services.AddRapidCMSFileUploadApiHttpClient(BaseUri); + config.AllowAnonymousUser(); } else - { - // when authentication is enabled, the auth token from the frontend should be forwarded to the file upload API - builder.Services.AddRapidCMSAuthenticatedFileUploadApiHttpClient(BaseUri); - builder.Services.AddRapidCMSAuthenticatedFileUploadApiHttpClient(BaseUri); - } - - if (ConfigureAuthentication) - { - ConfigureOpenIDConnectAuthentication(builder); + { + config.SetCustomLoginStatus(typeof(LoginStatus)); + config.SetCustomLoginScreen(typeof(LoginScreen)); } - builder.Services.AddRapidCMSWebAssembly(config => + // configure 5 as number of concurrent HTTP requests to the backend API + config.Advanced.SemaphoreCount = 5; + + // CRUD editor for simple POCO with recursive sub collections + // --> see Collections/PersonCollection for the basics of this CMS + config.AddPersonCollection(); + + // CRUD editor with support for one-to-many relation + validation + // --> see Collections/CountryCollection for one-to-many relation with validation + config.AddCountryCollection(); + + // Custom page with either custom Blazor components, or ListViews or ListEditors of collections + config.AddPage("TestBeakerSolid", "Green10", "Some random page", config => { - if (!ConfigureAuthentication) - { - config.AllowAnonymousUser(); - } - else - { - config.SetCustomLoginStatus(typeof(LoginStatus)); - config.SetCustomLoginScreen(typeof(LoginScreen)); - } - - // configure 5 as number of concurrent HTTP requests to the backend API - config.Advanced.SemaphoreCount = 5; - - // CRUD editor for simple POCO with recursive sub collections - // --> see Collections/PersonCollection for the basics of this CMS - config.AddPersonCollection(); - - // CRUD editor with support for one-to-many relation + validation - // --> see Collections/CountryCollection for one-to-many relation with validation - config.AddCountryCollection(); - - // Custom page with either custom Blazor components, or ListViews or ListEditors of collections - config.AddPage("TestBeakerSolid", "Green10", "Some random page", config => - { - config.AddSection(typeof(CustomSection)); - config.AddSection("country", edit: false); - }); - - // CRUD editor with validation attributes, custom editor and custom button panes - // --> see Collections/UserCollection - config.AddUserCollection(); - - // CRUD editor with nested collection - // --> see Collections/TagCollection - config.AddTagCollection(); - - // CRUD editor with entity mapping - config.AddMappedCollection(); - - // CRUD editor based on conventions for even more rapid development - config.AddConventionCollection(); - - // CRUD editor with entity variants, so multiple types of entities can be mixed in a single collection - config.AddEntityVariantCollection(); - - // CRUD editor displaying live data, an external process updates the data every second - config.AddActiveCollection(); - - //config.Dashboard.AddSection(typeof(DashboardSection)); - config.Dashboard.AddSection("user", edit: true); + config.AddSection(typeof(CustomSection)); + config.AddSection("country", edit: false); }); - var host = builder.Build(); + // CRUD editor with validation attributes, custom editor and custom button panes + // --> see Collections/UserCollection + config.AddUserCollection(); - var cmsOptions = host.Services.GetRequiredService(); - cmsOptions.IsDevelopment = true; + // CRUD editor with nested collection + // --> see Collections/TagCollection + config.AddTagCollection(); - await host.RunAsync(); - } + // CRUD editor with entity mapping + config.AddMappedCollection(); + + // CRUD editor based on conventions for even more rapid development + config.AddConventionCollection(); - private static void ConfigureOpenIDConnectAuthentication(WebAssemblyHostBuilder builder) + // CRUD editor with entity variants, so multiple types of entities can be mixed in a single collection + config.AddEntityVariantCollection(); + + // CRUD editor displaying live data, an external process updates the data every second + config.AddActiveCollection(); + + //config.Dashboard.AddSection(typeof(DashboardSection)); + config.Dashboard.AddSection("user", edit: true); + }); + + var host = builder.Build(); + + var cmsOptions = host.Services.GetRequiredService(); + cmsOptions.IsDevelopment = true; + + await host.RunAsync(); + } + + private static void ConfigureOpenIDConnectAuthentication(WebAssemblyHostBuilder builder) + { + // For OIDC + //builder.Services.AddOidcAuthentication(config => + //{ + // builder.Configuration.Bind("DevOIDC", config); + //}); + + // For AD + builder.Services.AddMsalAuthentication(options => { - // For OIDC - //builder.Services.AddOidcAuthentication(config => - //{ - // builder.Configuration.Bind("DevOIDC", config); - //}); - - // For AD - builder.Services.AddMsalAuthentication(options => - { - builder.Configuration.Bind("AzureAd", options.ProviderOptions); - }); - } + builder.Configuration.Bind("AzureAd", options.ProviderOptions); + }); } } diff --git a/examples/RapidCMS.Example.WebAssembly/RapidCMS.Example.WebAssembly.csproj b/examples/RapidCMS.Example.WebAssembly/RapidCMS.Example.WebAssembly.csproj index 403320cf..ff10f5e4 100644 --- a/examples/RapidCMS.Example.WebAssembly/RapidCMS.Example.WebAssembly.csproj +++ b/examples/RapidCMS.Example.WebAssembly/RapidCMS.Example.WebAssembly.csproj @@ -1,9 +1,8 @@  - net6.0 + net8.0 Blazor WebAssembly - 10.0 enable @@ -13,6 +12,12 @@ + + + + + + diff --git a/src/RapidCMS.Api.Core/Abstractions/IApiHandler.cs b/src/RapidCMS.Api.Core/Abstractions/IApiHandler.cs index 3c38b7ce..ca4abc87 100644 --- a/src/RapidCMS.Api.Core/Abstractions/IApiHandler.cs +++ b/src/RapidCMS.Api.Core/Abstractions/IApiHandler.cs @@ -1,22 +1,21 @@ using System.Threading.Tasks; using RapidCMS.Api.Core.Models; -namespace RapidCMS.Api.Core.Abstractions +namespace RapidCMS.Api.Core.Abstractions; + +public interface IApiHandler { - public interface IApiHandler - { - string RepositoryAlias { get; } + string RepositoryAlias { get; } - Task GetByIdAsync(ApiRequestModel request); - Task GetAllAsync(ApiRequestModel request); - Task GetAllRelatedAsync(ApiRequestModel request); - Task GetAllNonRelatedAsync(ApiRequestModel request); - Task NewAsync(ApiRequestModel request); - Task InsertAsync(ApiRequestModel request); - Task UpdateAsync(ApiRequestModel request); - Task DeleteAsync(ApiRequestModel request); - Task AddRelationAsync(ApiRequestModel request); - Task RemoveRelationAsync(ApiRequestModel request); - Task ReorderAsync(ApiRequestModel request); - } + Task GetByIdAsync(ApiRequestModel request); + Task GetAllAsync(ApiRequestModel request); + Task GetAllRelatedAsync(ApiRequestModel request); + Task GetAllNonRelatedAsync(ApiRequestModel request); + Task NewAsync(ApiRequestModel request); + Task InsertAsync(ApiRequestModel request); + Task UpdateAsync(ApiRequestModel request); + Task DeleteAsync(ApiRequestModel request); + Task AddRelationAsync(ApiRequestModel request); + Task RemoveRelationAsync(ApiRequestModel request); + Task ReorderAsync(ApiRequestModel request); } diff --git a/src/RapidCMS.Api.Core/Abstractions/IApiHandlerResolver.cs b/src/RapidCMS.Api.Core/Abstractions/IApiHandlerResolver.cs index b9385dff..d9a5ffd9 100644 --- a/src/RapidCMS.Api.Core/Abstractions/IApiHandlerResolver.cs +++ b/src/RapidCMS.Api.Core/Abstractions/IApiHandlerResolver.cs @@ -1,7 +1,6 @@ -namespace RapidCMS.Api.Core.Abstractions +namespace RapidCMS.Api.Core.Abstractions; + +public interface IApiHandlerResolver { - public interface IApiHandlerResolver - { - IApiHandler GetApiHandler(string repositoryAlias); - } + IApiHandler GetApiHandler(string repositoryAlias); } diff --git a/src/RapidCMS.Api.Core/Abstractions/IFileHandler.cs b/src/RapidCMS.Api.Core/Abstractions/IFileHandler.cs index 2ed50e14..dad9cd0a 100644 --- a/src/RapidCMS.Api.Core/Abstractions/IFileHandler.cs +++ b/src/RapidCMS.Api.Core/Abstractions/IFileHandler.cs @@ -3,11 +3,10 @@ using RapidCMS.Api.Core.Models; using RapidCMS.Core.Models.ApiBridge.Request; -namespace RapidCMS.Api.Core.Abstractions +namespace RapidCMS.Api.Core.Abstractions; + +public interface IFileHandler { - public interface IFileHandler - { - Task ValidateFileAsync(UploadFileModel request); - Task SaveFileAsync(UploadFileModel request, Stream fileStream); - } + Task ValidateFileAsync(UploadFileModel request); + Task SaveFileAsync(UploadFileModel request, Stream fileStream); } diff --git a/src/RapidCMS.Api.Core/Abstractions/IFileHandlerResolver.cs b/src/RapidCMS.Api.Core/Abstractions/IFileHandlerResolver.cs index 22bd89cd..bbd741c4 100644 --- a/src/RapidCMS.Api.Core/Abstractions/IFileHandlerResolver.cs +++ b/src/RapidCMS.Api.Core/Abstractions/IFileHandlerResolver.cs @@ -1,7 +1,6 @@ -namespace RapidCMS.Api.Core.Abstractions +namespace RapidCMS.Api.Core.Abstractions; + +public interface IFileHandlerResolver { - public interface IFileHandlerResolver - { - IFileHandler GetFileHandler(string uploadHandlerAlias); - } + IFileHandler GetFileHandler(string uploadHandlerAlias); } diff --git a/src/RapidCMS.Api.Core/General.cs b/src/RapidCMS.Api.Core/General.cs index 203e08b1..c39e8d80 100644 --- a/src/RapidCMS.Api.Core/General.cs +++ b/src/RapidCMS.Api.Core/General.cs @@ -3,6 +3,4 @@ [assembly: InternalsVisibleTo("RapidCMS.Api.Functions")] [assembly: InternalsVisibleTo("RapidCMS.Api.WebApi")] -namespace RapidCMS.Api.Core -{ -} +namespace RapidCMS.Api.Core; diff --git a/src/RapidCMS.Api.Core/Handlers/ApiHandler.cs b/src/RapidCMS.Api.Core/Handlers/ApiHandler.cs index d1e5762f..2b22e117 100644 --- a/src/RapidCMS.Api.Core/Handlers/ApiHandler.cs +++ b/src/RapidCMS.Api.Core/Handlers/ApiHandler.cs @@ -18,440 +18,439 @@ using RapidCMS.Core.Models.Request.Api; using RapidCMS.Core.Models.Response; -namespace RapidCMS.Api.Core.Handlers +namespace RapidCMS.Api.Core.Handlers; + +internal class ApiHandler : IApiHandler + where TEntity : class, IEntity + where TDatabaseEntity : class + where TRepository : IRepository { - internal class ApiHandler : IApiHandler - where TEntity : class, IEntity - where TDatabaseEntity : class - where TRepository : IRepository + private readonly IPresentationService _presentationService; + private readonly IInteractionService _interactionService; + private readonly ILogger> _logger; + private readonly JsonSerializerSettings _jsonSerializerSettings; + + public ApiHandler( + IPresentationService presentationService, + IInteractionService interactionService, + ILogger> logger) { - private readonly IPresentationService _presentationService; - private readonly IInteractionService _interactionService; - private readonly ILogger> _logger; - private readonly JsonSerializerSettings _jsonSerializerSettings; - - public ApiHandler( - IPresentationService presentationService, - IInteractionService interactionService, - ILogger> logger) - { - _presentationService = presentationService; - _interactionService = interactionService; - _logger = logger; - _jsonSerializerSettings = new JsonSerializerSettings(); - - if (Activator.CreateInstance(typeof(EntityModelJsonConverter<>).MakeGenericType(typeof(TEntity))) is JsonConverter jsonConverter) - { - _jsonSerializerSettings.Converters.Add(jsonConverter); - } - else - { - throw new InvalidOperationException($"Could not create {nameof(EntityModelJsonConverter)} for {typeof(TEntity).Name}"); - } + _presentationService = presentationService; + _interactionService = interactionService; + _logger = logger; + _jsonSerializerSettings = new JsonSerializerSettings(); + + if (Activator.CreateInstance(typeof(EntityModelJsonConverter<>).MakeGenericType(typeof(TEntity))) is JsonConverter jsonConverter) + { + _jsonSerializerSettings.Converters.Add(jsonConverter); + } + else + { + throw new InvalidOperationException($"Could not create {nameof(EntityModelJsonConverter)} for {typeof(TEntity).Name}"); } + } - public string RepositoryAlias => AliasHelper.GetRepositoryAlias(typeof(TRepository)); + public string RepositoryAlias => AliasHelper.GetRepositoryAlias(typeof(TRepository)); - public async Task AddRelationAsync(ApiRequestModel request) + public async Task AddRelationAsync(ApiRequestModel request) + { + try { - try + var relate = JsonConvert.DeserializeObject(request.Body ?? "", _jsonSerializerSettings); + if (relate == null) { - var relate = JsonConvert.DeserializeObject(request.Body ?? "", _jsonSerializerSettings); - if (relate == null) - { - return new ApiResponseModel(HttpStatusCode.BadRequest); - } - - await _interactionService.InteractAsync(new PersistRelatedEntityRequestModel - { - Related = new EntityDescriptor(relate.Related.Id, relate.Related.RepositoryAlias, relate.Related.ParentPath, default), - Subject = new EntityDescriptor(relate.Id, RepositoryAlias, default, default), - Action = PersistRelatedEntityRequestModel.Actions.Add - }); - - return new ApiResponseModel(HttpStatusCode.OK); - } - catch (NotFoundException) - { - return new ApiResponseModel(HttpStatusCode.NotFound); - } - catch (UnauthorizedAccessException) - { - return new ApiResponseModel(HttpStatusCode.Forbidden); + return new ApiResponseModel(HttpStatusCode.BadRequest); } - catch (Exception ex) + + await _interactionService.InteractAsync(new PersistRelatedEntityRequestModel { - _logger.LogError(ex, $"Error in {nameof(AddRelationAsync)}."); + Related = new EntityDescriptor(relate.Related.Id, relate.Related.RepositoryAlias, relate.Related.ParentPath, default), + Subject = new EntityDescriptor(relate.Id, RepositoryAlias, default, default), + Action = PersistRelatedEntityRequestModel.Actions.Add + }); - return new ApiResponseModel(HttpStatusCode.InternalServerError); - } + return new ApiResponseModel(HttpStatusCode.OK); + } + catch (NotFoundException) + { + return new ApiResponseModel(HttpStatusCode.NotFound); + } + catch (UnauthorizedAccessException) + { + return new ApiResponseModel(HttpStatusCode.Forbidden); } + catch (Exception ex) + { + _logger.LogError(ex, $"Error in {nameof(AddRelationAsync)}."); + + return new ApiResponseModel(HttpStatusCode.InternalServerError); + } + } - public async Task DeleteAsync(ApiRequestModel request) + public async Task DeleteAsync(ApiRequestModel request) + { + try { - try + var delete = JsonConvert.DeserializeObject(request.Body ?? "", _jsonSerializerSettings); + if (delete == null) { - var delete = JsonConvert.DeserializeObject(request.Body ?? "", _jsonSerializerSettings); - if (delete == null) - { - return new ApiResponseModel(HttpStatusCode.BadRequest); - } - - await _interactionService.InteractAsync(new DeleteEntityRequestModel - { - Descriptor = new EntityDescriptor(request.Id, RepositoryAlias, delete.ParentPath, default) - }); - - return new ApiResponseModel(HttpStatusCode.OK); - } - catch (NotFoundException) - { - return new ApiResponseModel(HttpStatusCode.NotFound); - } - catch (UnauthorizedAccessException) - { - return new ApiResponseModel(HttpStatusCode.Forbidden); + return new ApiResponseModel(HttpStatusCode.BadRequest); } - catch (Exception ex) + + await _interactionService.InteractAsync(new DeleteEntityRequestModel { - _logger.LogError(ex, $"Error in {nameof(DeleteAsync)}."); + Descriptor = new EntityDescriptor(request.Id, RepositoryAlias, delete.ParentPath, default) + }); - return new ApiResponseModel(HttpStatusCode.InternalServerError); - } + return new ApiResponseModel(HttpStatusCode.OK); + } + catch (NotFoundException) + { + return new ApiResponseModel(HttpStatusCode.NotFound); } + catch (UnauthorizedAccessException) + { + return new ApiResponseModel(HttpStatusCode.Forbidden); + } + catch (Exception ex) + { + _logger.LogError(ex, $"Error in {nameof(DeleteAsync)}."); - public async Task GetAllAsync(ApiRequestModel request) + return new ApiResponseModel(HttpStatusCode.InternalServerError); + } + } + + public async Task GetAllAsync(ApiRequestModel request) + { + try { - try + var query = JsonConvert.DeserializeObject(request.Body ?? "", _jsonSerializerSettings); + if (query == null) { - var query = JsonConvert.DeserializeObject(request.Body ?? "", _jsonSerializerSettings); - if (query == null) - { - return new ApiResponseModel(HttpStatusCode.BadRequest); - } - - var response = await _presentationService.GetEntitiesAsync(new GetEntitiesOfParentRequestModel - { - RepositoryAlias = RepositoryAlias, - ParentPath = query.ParentPath, - UsageType = UsageType.List | UsageType.Edit, - View = query.GetView() - }); - - return new ApiResponseModel(HttpStatusCode.OK, new EntitiesModel - { - Entities = EntityModel.Create(response.Entities), - MoreDataAvailable = response.MoreDataAvailable - }); + return new ApiResponseModel(HttpStatusCode.BadRequest); } - catch (UnauthorizedAccessException) + + var response = await _presentationService.GetEntitiesAsync(new GetEntitiesOfParentRequestModel { - return new ApiResponseModel(HttpStatusCode.Forbidden); - } - catch (Exception ex) + RepositoryAlias = RepositoryAlias, + ParentPath = query.ParentPath, + UsageType = UsageType.List | UsageType.Edit, + View = query.GetView() + }); + + return new ApiResponseModel(HttpStatusCode.OK, new EntitiesModel { - _logger.LogError(ex, $"Error in {nameof(GetAllAsync)}."); + Entities = EntityModel.Create(response.Entities), + MoreDataAvailable = response.MoreDataAvailable + }); + } + catch (UnauthorizedAccessException) + { + return new ApiResponseModel(HttpStatusCode.Forbidden); + } + catch (Exception ex) + { + _logger.LogError(ex, $"Error in {nameof(GetAllAsync)}."); - return new ApiResponseModel(HttpStatusCode.InternalServerError); - } + return new ApiResponseModel(HttpStatusCode.InternalServerError); } + } - public async Task GetAllNonRelatedAsync(ApiRequestModel request) + public async Task GetAllNonRelatedAsync(ApiRequestModel request) + { + try { - try + var query = JsonConvert.DeserializeObject(request.Body ?? "", _jsonSerializerSettings); + if (query == null) { - var query = JsonConvert.DeserializeObject(request.Body ?? "", _jsonSerializerSettings); - if (query == null) - { - return new ApiResponseModel(HttpStatusCode.BadRequest); - } - - var response = await _presentationService.GetEntitiesAsync(new GetEntitiesOfRelationRequestModel - { - RepositoryAlias = RepositoryAlias, - UsageType = UsageType.List | UsageType.Add, - View = query.GetView(), - Related = new EntityDescriptor(query.Related.Id, query.Related.RepositoryAlias, query.Related.ParentPath, default) - }); - - return new ApiResponseModel(HttpStatusCode.OK, new EntitiesModel - { - Entities = EntityModel.Create(response.Entities), - MoreDataAvailable = response.MoreDataAvailable - }); + return new ApiResponseModel(HttpStatusCode.BadRequest); } - catch (UnauthorizedAccessException) + + var response = await _presentationService.GetEntitiesAsync(new GetEntitiesOfRelationRequestModel { - return new ApiResponseModel(HttpStatusCode.Forbidden); - } - catch (Exception ex) + RepositoryAlias = RepositoryAlias, + UsageType = UsageType.List | UsageType.Add, + View = query.GetView(), + Related = new EntityDescriptor(query.Related.Id, query.Related.RepositoryAlias, query.Related.ParentPath, default) + }); + + return new ApiResponseModel(HttpStatusCode.OK, new EntitiesModel { - _logger.LogError(ex, $"Error in {nameof(GetAllNonRelatedAsync)}."); + Entities = EntityModel.Create(response.Entities), + MoreDataAvailable = response.MoreDataAvailable + }); + } + catch (UnauthorizedAccessException) + { + return new ApiResponseModel(HttpStatusCode.Forbidden); + } + catch (Exception ex) + { + _logger.LogError(ex, $"Error in {nameof(GetAllNonRelatedAsync)}."); - return new ApiResponseModel(HttpStatusCode.InternalServerError); - } + return new ApiResponseModel(HttpStatusCode.InternalServerError); } + } - public async Task GetAllRelatedAsync(ApiRequestModel request) + public async Task GetAllRelatedAsync(ApiRequestModel request) + { + try { - try + var query = JsonConvert.DeserializeObject(request.Body ?? "", _jsonSerializerSettings); + if (query == null) { - var query = JsonConvert.DeserializeObject(request.Body ?? "", _jsonSerializerSettings); - if (query == null) - { - return new ApiResponseModel(HttpStatusCode.BadRequest); - } - - var response = await _presentationService.GetEntitiesAsync(new GetEntitiesOfRelationRequestModel - { - RepositoryAlias = RepositoryAlias, - UsageType = UsageType.List | UsageType.Edit, - View = query.GetView(), - Related = new EntityDescriptor(query.Related.Id, query.Related.RepositoryAlias, query.Related.ParentPath, default) - }); - - return new ApiResponseModel(HttpStatusCode.OK, new EntitiesModel - { - Entities = EntityModel.Create(response.Entities), - MoreDataAvailable = response.MoreDataAvailable - }); + return new ApiResponseModel(HttpStatusCode.BadRequest); } - catch (UnauthorizedAccessException) + + var response = await _presentationService.GetEntitiesAsync(new GetEntitiesOfRelationRequestModel { - return new ApiResponseModel(HttpStatusCode.Forbidden); - } - catch (Exception ex) + RepositoryAlias = RepositoryAlias, + UsageType = UsageType.List | UsageType.Edit, + View = query.GetView(), + Related = new EntityDescriptor(query.Related.Id, query.Related.RepositoryAlias, query.Related.ParentPath, default) + }); + + return new ApiResponseModel(HttpStatusCode.OK, new EntitiesModel { - _logger.LogError(ex, $"Error in {nameof(GetAllRelatedAsync)}."); + Entities = EntityModel.Create(response.Entities), + MoreDataAvailable = response.MoreDataAvailable + }); + } + catch (UnauthorizedAccessException) + { + return new ApiResponseModel(HttpStatusCode.Forbidden); + } + catch (Exception ex) + { + _logger.LogError(ex, $"Error in {nameof(GetAllRelatedAsync)}."); - return new ApiResponseModel(HttpStatusCode.InternalServerError); - } + return new ApiResponseModel(HttpStatusCode.InternalServerError); } + } - public async Task GetByIdAsync(ApiRequestModel request) + public async Task GetByIdAsync(ApiRequestModel request) + { + try { - try + var query = JsonConvert.DeserializeObject(request.Body ?? "", _jsonSerializerSettings); + if (query == null) { - var query = JsonConvert.DeserializeObject(request.Body ?? "", _jsonSerializerSettings); - if (query == null) - { - return new ApiResponseModel(HttpStatusCode.BadRequest); - } - - var entity = await _presentationService.GetEntityAsync(new GetEntityRequestModel - { - Subject = new EntityDescriptor(request.Id, RepositoryAlias, query.ParentPath, query.VariantAlias), - UsageType = UsageType.Node | UsageType.Edit - }); - - return new ApiResponseModel(HttpStatusCode.OK, EntityModel.Create(entity)); - } - catch (NotFoundException) - { - return new ApiResponseModel(HttpStatusCode.NotFound); - } - catch (UnauthorizedAccessException) - { - return new ApiResponseModel(HttpStatusCode.Forbidden); + return new ApiResponseModel(HttpStatusCode.BadRequest); } - catch (Exception ex) + + var entity = await _presentationService.GetEntityAsync(new GetEntityRequestModel { - _logger.LogError(ex, $"Error in {nameof(GetByIdAsync)}."); + Subject = new EntityDescriptor(request.Id, RepositoryAlias, query.ParentPath, query.VariantAlias), + UsageType = UsageType.Node | UsageType.Edit + }); - return new ApiResponseModel(HttpStatusCode.InternalServerError); - } + return new ApiResponseModel(HttpStatusCode.OK, EntityModel.Create(entity)); + } + catch (NotFoundException) + { + return new ApiResponseModel(HttpStatusCode.NotFound); + } + catch (UnauthorizedAccessException) + { + return new ApiResponseModel(HttpStatusCode.Forbidden); } + catch (Exception ex) + { + _logger.LogError(ex, $"Error in {nameof(GetByIdAsync)}."); + + return new ApiResponseModel(HttpStatusCode.InternalServerError); + } + } - public async Task InsertAsync(ApiRequestModel request) + public async Task InsertAsync(ApiRequestModel request) + { + try { - try - { - var editContextModel = JsonConvert.DeserializeObject>(request.Body ?? "", _jsonSerializerSettings); - if (editContextModel == null) - { - return new ApiResponseModel(HttpStatusCode.BadRequest); - } - - var response = await _interactionService.InteractAsync(new PersistEntityRequestModel - { - Descriptor = new EntityDescriptor(default, RepositoryAlias, editContextModel.ParentPath, editContextModel.EntityModel.VariantAlias), - Entity = editContextModel.EntityModel.Entity, - EntityState = EntityState.IsNew, - Relations = editContextModel.GetRelations() - }); - - return response switch - { - ApiPersistEntityResponseModel persistResponse when persistResponse.ValidationErrors != null => new ApiResponseModel(HttpStatusCode.BadRequest, persistResponse.ValidationErrors), - ApiPersistEntityResponseModel insertResponse when insertResponse.NewEntity != null => new ApiResponseModel(HttpStatusCode.OK, EntityModel.Create(insertResponse.NewEntity)), - _ => new ApiResponseModel(HttpStatusCode.OK) - }; - } - catch (InvalidEntityException) + var editContextModel = JsonConvert.DeserializeObject>(request.Body ?? "", _jsonSerializerSettings); + if (editContextModel == null) { return new ApiResponseModel(HttpStatusCode.BadRequest); } - catch (NotFoundException) - { - return new ApiResponseModel(HttpStatusCode.NotFound); - } - catch (UnauthorizedAccessException) + + var response = await _interactionService.InteractAsync(new PersistEntityRequestModel { - return new ApiResponseModel(HttpStatusCode.Forbidden); - } - catch (Exception ex) + Descriptor = new EntityDescriptor(default, RepositoryAlias, editContextModel.ParentPath, editContextModel.EntityModel.VariantAlias), + Entity = editContextModel.EntityModel.Entity, + EntityState = EntityState.IsNew, + Relations = editContextModel.GetRelations() + }); + + return response switch { - _logger.LogError(ex, $"Error in {nameof(InsertAsync)}."); + ApiPersistEntityResponseModel persistResponse when persistResponse.ValidationErrors != null => new ApiResponseModel(HttpStatusCode.BadRequest, persistResponse.ValidationErrors), + ApiPersistEntityResponseModel insertResponse when insertResponse.NewEntity != null => new ApiResponseModel(HttpStatusCode.OK, EntityModel.Create(insertResponse.NewEntity)), + _ => new ApiResponseModel(HttpStatusCode.OK) + }; + } + catch (InvalidEntityException) + { + return new ApiResponseModel(HttpStatusCode.BadRequest); + } + catch (NotFoundException) + { + return new ApiResponseModel(HttpStatusCode.NotFound); + } + catch (UnauthorizedAccessException) + { + return new ApiResponseModel(HttpStatusCode.Forbidden); + } + catch (Exception ex) + { + _logger.LogError(ex, $"Error in {nameof(InsertAsync)}."); - return new ApiResponseModel(HttpStatusCode.InternalServerError); - } + return new ApiResponseModel(HttpStatusCode.InternalServerError); } + } - public async Task NewAsync(ApiRequestModel request) + public async Task NewAsync(ApiRequestModel request) + { + try { - try - { - var query = JsonConvert.DeserializeObject(request.Body ?? "", _jsonSerializerSettings); - if (query == null) - { - return new ApiResponseModel(HttpStatusCode.BadRequest); - } - - var entity = await _presentationService.GetEntityAsync(new GetEntityRequestModel - { - Subject = new EntityDescriptor(default, RepositoryAlias, query.ParentPath, query.VariantAlias), - UsageType = UsageType.Node | UsageType.New - }); - - return new ApiResponseModel(HttpStatusCode.OK, EntityModel.Create(entity)); - } - catch (NotFoundException) + var query = JsonConvert.DeserializeObject(request.Body ?? "", _jsonSerializerSettings); + if (query == null) { - return new ApiResponseModel(HttpStatusCode.NotFound); - } - catch (UnauthorizedAccessException) - { - return new ApiResponseModel(HttpStatusCode.Forbidden); + return new ApiResponseModel(HttpStatusCode.BadRequest); } - catch (Exception ex) + + var entity = await _presentationService.GetEntityAsync(new GetEntityRequestModel { - _logger.LogError(ex, $"Error in {nameof(NewAsync)}."); + Subject = new EntityDescriptor(default, RepositoryAlias, query.ParentPath, query.VariantAlias), + UsageType = UsageType.Node | UsageType.New + }); - return new ApiResponseModel(HttpStatusCode.InternalServerError); - } + return new ApiResponseModel(HttpStatusCode.OK, EntityModel.Create(entity)); + } + catch (NotFoundException) + { + return new ApiResponseModel(HttpStatusCode.NotFound); + } + catch (UnauthorizedAccessException) + { + return new ApiResponseModel(HttpStatusCode.Forbidden); + } + catch (Exception ex) + { + _logger.LogError(ex, $"Error in {nameof(NewAsync)}."); + + return new ApiResponseModel(HttpStatusCode.InternalServerError); } + } - public async Task RemoveRelationAsync(ApiRequestModel request) + public async Task RemoveRelationAsync(ApiRequestModel request) + { + try { - try + var relate = JsonConvert.DeserializeObject(request.Body ?? "", _jsonSerializerSettings); + if (relate == null) { - var relate = JsonConvert.DeserializeObject(request.Body ?? "", _jsonSerializerSettings); - if (relate == null) - { - return new ApiResponseModel(HttpStatusCode.BadRequest); - } - - await _interactionService.InteractAsync(new PersistRelatedEntityRequestModel - { - Related = new EntityDescriptor(relate.Related.Id, relate.Related.RepositoryAlias, relate.Related.ParentPath, default), - Subject = new EntityDescriptor(relate.Id, RepositoryAlias, default, default), - Action = PersistRelatedEntityRequestModel.Actions.Remove - }); - - return new ApiResponseModel(HttpStatusCode.OK); - } - catch (NotFoundException) - { - return new ApiResponseModel(HttpStatusCode.NotFound); - } - catch (UnauthorizedAccessException) - { - return new ApiResponseModel(HttpStatusCode.Forbidden); + return new ApiResponseModel(HttpStatusCode.BadRequest); } - catch (Exception ex) + + await _interactionService.InteractAsync(new PersistRelatedEntityRequestModel { - _logger.LogError(ex, $"Error in {nameof(RemoveRelationAsync)}."); + Related = new EntityDescriptor(relate.Related.Id, relate.Related.RepositoryAlias, relate.Related.ParentPath, default), + Subject = new EntityDescriptor(relate.Id, RepositoryAlias, default, default), + Action = PersistRelatedEntityRequestModel.Actions.Remove + }); - return new ApiResponseModel(HttpStatusCode.InternalServerError); - } + return new ApiResponseModel(HttpStatusCode.OK); + } + catch (NotFoundException) + { + return new ApiResponseModel(HttpStatusCode.NotFound); + } + catch (UnauthorizedAccessException) + { + return new ApiResponseModel(HttpStatusCode.Forbidden); } + catch (Exception ex) + { + _logger.LogError(ex, $"Error in {nameof(RemoveRelationAsync)}."); - public async Task ReorderAsync(ApiRequestModel request) + return new ApiResponseModel(HttpStatusCode.InternalServerError); + } + } + + public async Task ReorderAsync(ApiRequestModel request) + { + try { - try + var reorder = JsonConvert.DeserializeObject(request.Body ?? "", _jsonSerializerSettings); + if (reorder == null) { - var reorder = JsonConvert.DeserializeObject(request.Body ?? "", _jsonSerializerSettings); - if (reorder == null) - { - return new ApiResponseModel(HttpStatusCode.BadRequest); - } - - await _interactionService.InteractAsync(new PersistReorderRequestModel - { - BeforeId = reorder.BeforeId, - Subject = new EntityDescriptor(reorder.Subject.Id, RepositoryAlias, reorder.Subject.ParentPath, default) - }); - - return new ApiResponseModel(HttpStatusCode.OK); - } - catch (NotFoundException) - { - return new ApiResponseModel(HttpStatusCode.NotFound); - } - catch (UnauthorizedAccessException) - { - return new ApiResponseModel(HttpStatusCode.Forbidden); + return new ApiResponseModel(HttpStatusCode.BadRequest); } - catch (Exception ex) + + await _interactionService.InteractAsync(new PersistReorderRequestModel { - _logger.LogError(ex, $"Error in {nameof(ReorderAsync)}."); + BeforeId = reorder.BeforeId, + Subject = new EntityDescriptor(reorder.Subject.Id, RepositoryAlias, reorder.Subject.ParentPath, default) + }); - return new ApiResponseModel(HttpStatusCode.InternalServerError); - } + return new ApiResponseModel(HttpStatusCode.OK); + } + catch (NotFoundException) + { + return new ApiResponseModel(HttpStatusCode.NotFound); + } + catch (UnauthorizedAccessException) + { + return new ApiResponseModel(HttpStatusCode.Forbidden); } + catch (Exception ex) + { + _logger.LogError(ex, $"Error in {nameof(ReorderAsync)}."); + + return new ApiResponseModel(HttpStatusCode.InternalServerError); + } + } - public async Task UpdateAsync(ApiRequestModel request) + public async Task UpdateAsync(ApiRequestModel request) + { + try { - try - { - var editContextModel = JsonConvert.DeserializeObject>(request.Body ?? "", _jsonSerializerSettings); - if (editContextModel == null) - { - return new ApiResponseModel(HttpStatusCode.BadRequest); - } - - var response = await _interactionService.InteractAsync(new PersistEntityRequestModel - { - Descriptor = new EntityDescriptor(request.Id, RepositoryAlias, editContextModel.ParentPath, editContextModel.EntityModel.VariantAlias), - Entity = editContextModel.EntityModel.Entity, - EntityState = EntityState.IsExisting, - Relations = editContextModel.GetRelations() - }); - - return response switch - { - ApiPersistEntityResponseModel persistResponse when persistResponse.ValidationErrors != null => new ApiResponseModel(HttpStatusCode.BadRequest, persistResponse.ValidationErrors), - _ => new ApiResponseModel(HttpStatusCode.OK) - }; - } - catch (InvalidEntityException) + var editContextModel = JsonConvert.DeserializeObject>(request.Body ?? "", _jsonSerializerSettings); + if (editContextModel == null) { return new ApiResponseModel(HttpStatusCode.BadRequest); } - catch (NotFoundException) - { - return new ApiResponseModel(HttpStatusCode.NotFound); - } - catch (UnauthorizedAccessException) + + var response = await _interactionService.InteractAsync(new PersistEntityRequestModel { - return new ApiResponseModel(HttpStatusCode.Forbidden); - } - catch (Exception ex) + Descriptor = new EntityDescriptor(request.Id, RepositoryAlias, editContextModel.ParentPath, editContextModel.EntityModel.VariantAlias), + Entity = editContextModel.EntityModel.Entity, + EntityState = EntityState.IsExisting, + Relations = editContextModel.GetRelations() + }); + + return response switch { - _logger.LogError(ex, $"Error in {nameof(UpdateAsync)}."); + ApiPersistEntityResponseModel persistResponse when persistResponse.ValidationErrors != null => new ApiResponseModel(HttpStatusCode.BadRequest, persistResponse.ValidationErrors), + _ => new ApiResponseModel(HttpStatusCode.OK) + }; + } + catch (InvalidEntityException) + { + return new ApiResponseModel(HttpStatusCode.BadRequest); + } + catch (NotFoundException) + { + return new ApiResponseModel(HttpStatusCode.NotFound); + } + catch (UnauthorizedAccessException) + { + return new ApiResponseModel(HttpStatusCode.Forbidden); + } + catch (Exception ex) + { + _logger.LogError(ex, $"Error in {nameof(UpdateAsync)}."); - return new ApiResponseModel(HttpStatusCode.InternalServerError); - } + return new ApiResponseModel(HttpStatusCode.InternalServerError); } } } diff --git a/src/RapidCMS.Api.Core/Handlers/FileHandler.cs b/src/RapidCMS.Api.Core/Handlers/FileHandler.cs index 7f300e4f..a1e2940b 100644 --- a/src/RapidCMS.Api.Core/Handlers/FileHandler.cs +++ b/src/RapidCMS.Api.Core/Handlers/FileHandler.cs @@ -8,52 +8,51 @@ using RapidCMS.Core.Models.ApiBridge.Request; using RapidCMS.Core.Models.Response; -namespace RapidCMS.Api.Core.Handlers +namespace RapidCMS.Api.Core.Handlers; + +internal class FileHandler : IFileHandler + where THandler : IFileUploadHandler { - internal class FileHandler : IFileHandler - where THandler : IFileUploadHandler - { - private readonly THandler _handler; + private readonly THandler _handler; - public FileHandler(THandler handler) - { - _handler = handler; - } + public FileHandler(THandler handler) + { + _handler = handler; + } - public async Task SaveFileAsync(UploadFileModel request, Stream fileStream) + public async Task SaveFileAsync(UploadFileModel request, Stream fileStream) + { + // TODO: this validation can be better + if (fileStream.Length == request.Size) { - // TODO: this validation can be better - if (fileStream.Length == request.Size) + var messages = await _handler.ValidateFileAsync(request); + if (messages.Any()) { - var messages = await _handler.ValidateFileAsync(request); - if (messages.Any()) - { - return new ApiResponseModel(HttpStatusCode.BadRequest, new FileUploadValidationResponseModel { ErrorMessages = messages }); - } + return new ApiResponseModel(HttpStatusCode.BadRequest, new FileUploadValidationResponseModel { ErrorMessages = messages }); + } - using (fileStream) + using (fileStream) + { + try { - try - { - var result = await _handler.SaveFileAsync(request, fileStream); - return new ApiResponseModel(HttpStatusCode.OK, new FileUploadResponseModel { Result = result }); - } - catch { } + var result = await _handler.SaveFileAsync(request, fileStream); + return new ApiResponseModel(HttpStatusCode.OK, new FileUploadResponseModel { Result = result }); } + catch { } } - - return new ApiResponseModel(HttpStatusCode.BadRequest); } - public async Task ValidateFileAsync(UploadFileModel request) - { - var messages = await _handler.ValidateFileAsync(request); - if (messages.Any()) - { - return new ApiResponseModel(HttpStatusCode.OK, new FileUploadValidationResponseModel { ErrorMessages = messages }); - } + return new ApiResponseModel(HttpStatusCode.BadRequest); + } - return new ApiResponseModel(HttpStatusCode.NoContent); + public async Task ValidateFileAsync(UploadFileModel request) + { + var messages = await _handler.ValidateFileAsync(request); + if (messages.Any()) + { + return new ApiResponseModel(HttpStatusCode.OK, new FileUploadValidationResponseModel { ErrorMessages = messages }); } + + return new ApiResponseModel(HttpStatusCode.NoContent); } } diff --git a/src/RapidCMS.Api.Core/Models/ApiRequestModel.cs b/src/RapidCMS.Api.Core/Models/ApiRequestModel.cs index 34e8cc4d..63c9e775 100644 --- a/src/RapidCMS.Api.Core/Models/ApiRequestModel.cs +++ b/src/RapidCMS.Api.Core/Models/ApiRequestModel.cs @@ -1,8 +1,7 @@ -namespace RapidCMS.Api.Core.Models +namespace RapidCMS.Api.Core.Models; + +public class ApiRequestModel { - public class ApiRequestModel - { - public string? Id { get; set; } - public string? Body { get; set; } - } + public string? Id { get; set; } + public string? Body { get; set; } } diff --git a/src/RapidCMS.Api.Core/Models/ApiResponseModel.cs b/src/RapidCMS.Api.Core/Models/ApiResponseModel.cs index e79d4bf9..76be8826 100644 --- a/src/RapidCMS.Api.Core/Models/ApiResponseModel.cs +++ b/src/RapidCMS.Api.Core/Models/ApiResponseModel.cs @@ -1,25 +1,24 @@ using System.Net; using Newtonsoft.Json; -namespace RapidCMS.Api.Core.Models +namespace RapidCMS.Api.Core.Models; + +public class ApiResponseModel { - public class ApiResponseModel + public ApiResponseModel(HttpStatusCode statusCode) { - public ApiResponseModel(HttpStatusCode statusCode) - { - StatusCode = statusCode; - } + StatusCode = statusCode; + } - public ApiResponseModel(HttpStatusCode statusCode, object responseBody) : this(statusCode) + public ApiResponseModel(HttpStatusCode statusCode, object responseBody) : this(statusCode) + { + ResponseBody = JsonConvert.SerializeObject(responseBody, new JsonSerializerSettings { - ResponseBody = JsonConvert.SerializeObject(responseBody, new JsonSerializerSettings - { - ReferenceLoopHandling = ReferenceLoopHandling.Ignore, - PreserveReferencesHandling = PreserveReferencesHandling.All - }); - } - - public HttpStatusCode StatusCode { get; set; } - public string? ResponseBody { get; set; } + ReferenceLoopHandling = ReferenceLoopHandling.Ignore, + PreserveReferencesHandling = PreserveReferencesHandling.All + }); } + + public HttpStatusCode StatusCode { get; set; } + public string? ResponseBody { get; set; } } diff --git a/src/RapidCMS.Api.Core/RapidCMS.Api.Core.csproj b/src/RapidCMS.Api.Core/RapidCMS.Api.Core.csproj index 2d6e1348..ed29be1e 100644 --- a/src/RapidCMS.Api.Core/RapidCMS.Api.Core.csproj +++ b/src/RapidCMS.Api.Core/RapidCMS.Api.Core.csproj @@ -1,8 +1,7 @@  - net6.0 - 10.0 + net6.0;net8.0 enable Thomas Bleijendaal Thomas Bleijendaal @@ -35,12 +34,13 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - + + + + + diff --git a/src/RapidCMS.Api.Core/RapidCMSApiMiddlewareBase.cs b/src/RapidCMS.Api.Core/RapidCMSApiMiddlewareBase.cs index 5050493c..592184bd 100644 --- a/src/RapidCMS.Api.Core/RapidCMSApiMiddlewareBase.cs +++ b/src/RapidCMS.Api.Core/RapidCMSApiMiddlewareBase.cs @@ -32,90 +32,89 @@ using RapidCMS.Core.Services.Presentation; using RapidCMS.Core.Validators; -namespace RapidCMS.Api.Core +namespace RapidCMS.Api.Core; + +internal static class RapidCMSApiMiddlewareBase { - internal static class RapidCMSApiMiddlewareBase + public static IServiceCollection AddRapidCMSApiCore(this IServiceCollection services, ApiConfig config) { - public static IServiceCollection AddRapidCMSApiCore(this IServiceCollection services, ApiConfig config) - { - services.AddSingleton(config); - services.AddTransient(); - services.AddTransient(); + services.AddSingleton(config); + services.AddTransient(); + services.AddTransient(); - services.AddHttpContextAccessor(); + //services.AddHttpContextAccessor(); - if (config.AllowAnonymousUsage) - { - services.AddSingleton(); - services.AddSingleton(); - } + if (config.AllowAnonymousUsage) + { + services.AddSingleton(); + services.AddSingleton(); + } - services.AddSingleton, GlobalEntityVariantSetupResolver>(); + services.AddSingleton, GlobalEntityVariantSetupResolver>(); - services.AddTransient(); - services.AddTransient(); - services.AddSingleton(); + services.AddTransient(); + services.AddTransient(); + services.AddSingleton(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddSingleton(serviceProvider => new SemaphoreSlim(5, 5)); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddSingleton(serviceProvider => new SemaphoreSlim(5, 5)); - services.AddScoped(); + services.AddScoped(); - services.AddTransient(); + services.AddTransient(); - var apiHandlers = config.Repositories.ToList( - repository => repository.DatabaseType == default - ? typeof(ApiHandler<,,>).MakeGenericType(repository.EntityType, repository.EntityType, repository.ApiRepositoryType) - : typeof(ApiHandler<,,>).MakeGenericType(repository.EntityType, repository.DatabaseType, repository.ApiRepositoryType)); + var apiHandlers = config.Repositories.ToList( + repository => repository.DatabaseType == default + ? typeof(ApiHandler<,,>).MakeGenericType(repository.EntityType, repository.EntityType, repository.ApiRepositoryType) + : typeof(ApiHandler<,,>).MakeGenericType(repository.EntityType, repository.DatabaseType, repository.ApiRepositoryType)); - foreach (var apiHandler in apiHandlers) - { - services.AddTransient(apiHandler); - } + foreach (var apiHandler in apiHandlers) + { + services.AddTransient(apiHandler); + } - var entityVariants = config.Repositories.ToDictionary(x => x.Alias, x => - { - var entityTypes = new[] { x.EntityType } - .Union(x.EntityType.GetSubTypes()) - .ToList(); - return (entityType: x.EntityType, variants: (IReadOnlyList)entityTypes); - }); + var entityVariants = config.Repositories.ToDictionary(x => x.Alias, x => + { + var entityTypes = new[] { x.EntityType } + .Union(x.EntityType.GetSubTypes()) + .ToList(); + return (entityType: x.EntityType, variants: (IReadOnlyList)entityTypes); + }); - services.AddSingleton(new EntityVariantResolver(entityVariants)); + services.AddSingleton(new EntityVariantResolver(entityVariants)); - foreach (var fileHandler in config.FileUploadHandlers.ToList(fileHandler => typeof(FileHandler<>).MakeGenericType(fileHandler.HandlerType))) - { - services.AddTransient(fileHandler); - } - if (!config.AdvancedConfig.RemoveDataAnnotationEntityValidator) - { - services.AddSingleton(); + foreach (var fileHandler in config.FileUploadHandlers.ToList(fileHandler => typeof(FileHandler<>).MakeGenericType(fileHandler.HandlerType))) + { + services.AddTransient(fileHandler); + } + if (!config.AdvancedConfig.RemoveDataAnnotationEntityValidator) + { + services.AddSingleton(); - foreach (var variant in entityVariants.SelectMany(x => x.Value.variants)) - { - config.EntityValidationConfig.Add((AliasHelper.GetEntityVariantAlias(variant), new ValidationConfig(typeof(DataAnnotationEntityValidator), default))); - } + foreach (var variant in entityVariants.SelectMany(x => x.Value.variants)) + { + config.EntityValidationConfig.Add((AliasHelper.GetEntityVariantAlias(variant), new ValidationConfig(typeof(DataAnnotationEntityValidator), default))); } + } - var validations = config.EntityValidationConfig - .GroupBy(x => x.entity) - .ToDictionary(x => x.Key, x => x.ToList(x => new ValidationSetup(x.validation.Type, x.validation.Configuration) as ValidationSetup) as IReadOnlyList); + var validations = config.EntityValidationConfig + .GroupBy(x => x.entity) + .ToDictionary(x => x.Key, x => x.ToList(x => new ValidationSetup(x.validation.Type, x.validation.Configuration) as ValidationSetup) as IReadOnlyList); - services.AddSingleton>>(new ValidationSetupResolver(validations)); + services.AddSingleton>>(new ValidationSetupResolver(validations)); - return services; - } + return services; } } diff --git a/src/RapidCMS.Api.Core/Resolvers/AnonymousUserResolver.cs b/src/RapidCMS.Api.Core/Resolvers/AnonymousUserResolver.cs index 1bb59b39..dc9c5021 100644 --- a/src/RapidCMS.Api.Core/Resolvers/AnonymousUserResolver.cs +++ b/src/RapidCMS.Api.Core/Resolvers/AnonymousUserResolver.cs @@ -1,16 +1,15 @@ using System.Security.Claims; using RapidCMS.Core.Abstractions.Resolvers; -namespace RapidCMS.Api.Core.Resolvers +namespace RapidCMS.Api.Core.Resolvers; + +internal class AnonymousUserResolver : IUserResolver { - internal class AnonymousUserResolver : IUserResolver + public ClaimsPrincipal? GetUser() { - public ClaimsPrincipal? GetUser() - { - var id = new ClaimsIdentity("anonymous"); - id.AddClaim(new Claim(ClaimTypes.Name, "Anonymous")); + var id = new ClaimsIdentity("anonymous"); + id.AddClaim(new Claim(ClaimTypes.Name, "Anonymous")); - return new ClaimsPrincipal(id); - } + return new ClaimsPrincipal(id); } } diff --git a/src/RapidCMS.Api.Core/Resolvers/ApiHandlerResolver.cs b/src/RapidCMS.Api.Core/Resolvers/ApiHandlerResolver.cs index 615e2a89..8b83a0fd 100644 --- a/src/RapidCMS.Api.Core/Resolvers/ApiHandlerResolver.cs +++ b/src/RapidCMS.Api.Core/Resolvers/ApiHandlerResolver.cs @@ -5,42 +5,41 @@ using RapidCMS.Core.Abstractions.Config; using RapidCMS.Core.Extensions; -namespace RapidCMS.Api.Core.Resolvers +namespace RapidCMS.Api.Core.Resolvers; + +internal class ApiHandlerResolver : IApiHandlerResolver { - internal class ApiHandlerResolver : IApiHandlerResolver + private readonly IServiceProvider _serviceProvider; + private readonly IApiConfig _config; + + public ApiHandlerResolver( + IServiceProvider serviceProvider, + IApiConfig config) { - private readonly IServiceProvider _serviceProvider; - private readonly IApiConfig _config; + _serviceProvider = serviceProvider; + _config = config; + } - public ApiHandlerResolver( - IServiceProvider serviceProvider, - IApiConfig config) + public IApiHandler GetApiHandler(string repositoryAlias) + { + var repoConfig = _config.Repositories.FirstOrDefault(x => x.Alias == repositoryAlias); + if (repoConfig == null) { - _serviceProvider = serviceProvider; - _config = config; + throw new InvalidOperationException($"Could not find repository with alias {repositoryAlias}. Available: {string.Join(",", _config.Repositories.Select(x => $"[{x.ApiRepositoryType}: {x.Alias}]"))}."); } - public IApiHandler GetApiHandler(string repositoryAlias) + Type repoType; + if (repoConfig.DatabaseType == default) { - var repoConfig = _config.Repositories.FirstOrDefault(x => x.Alias == repositoryAlias); - if (repoConfig == null) - { - throw new InvalidOperationException($"Could not find repository with alias {repositoryAlias}. Available: {string.Join(",", _config.Repositories.Select(x => $"[{x.ApiRepositoryType}: {x.Alias}]"))}."); - } - - Type repoType; - if (repoConfig.DatabaseType == default) - { - repoType = typeof(ApiHandler<,,>) - .MakeGenericType(repoConfig.EntityType, repoConfig.EntityType, repoConfig.ApiRepositoryType); - } - else - { - repoType = typeof(ApiHandler<,,>) - .MakeGenericType(repoConfig.EntityType, repoConfig.DatabaseType, repoConfig.ApiRepositoryType); - } - - return _serviceProvider.GetService(repoType); + repoType = typeof(ApiHandler<,,>) + .MakeGenericType(repoConfig.EntityType, repoConfig.EntityType, repoConfig.ApiRepositoryType); + } + else + { + repoType = typeof(ApiHandler<,,>) + .MakeGenericType(repoConfig.EntityType, repoConfig.DatabaseType, repoConfig.ApiRepositoryType); } + + return _serviceProvider.GetService(repoType); } } diff --git a/src/RapidCMS.Api.Core/Resolvers/EntityValidatorsResolver.cs b/src/RapidCMS.Api.Core/Resolvers/EntityValidatorsResolver.cs index 388f95a9..1c42d7aa 100644 --- a/src/RapidCMS.Api.Core/Resolvers/EntityValidatorsResolver.cs +++ b/src/RapidCMS.Api.Core/Resolvers/EntityValidatorsResolver.cs @@ -4,21 +4,20 @@ using RapidCMS.Core.Abstractions.Resolvers; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Api.Core.Resolvers +namespace RapidCMS.Api.Core.Resolvers; + +internal class ValidationSetupResolver : ISetupResolver> { - internal class ValidationSetupResolver : ISetupResolver> - { - private readonly Dictionary> _validations; + private readonly Dictionary> _validations; - public ValidationSetupResolver(Dictionary> validations) - { - _validations = validations; - } + public ValidationSetupResolver(Dictionary> validations) + { + _validations = validations; + } - public Task> ResolveSetupAsync() - => Task.FromResult>(_validations.Values.SelectMany(x => x).ToList()); + public Task> ResolveSetupAsync() + => Task.FromResult>(_validations.Values.SelectMany(x => x).ToList()); - public Task> ResolveSetupAsync(string alias) - => Task.FromResult(_validations.TryGetValue(alias, out var list) ? list : new List()); - } + public Task> ResolveSetupAsync(string alias) + => Task.FromResult(_validations.TryGetValue(alias, out var list) ? list : new List()); } diff --git a/src/RapidCMS.Api.Core/Resolvers/FileHandlerResolver.cs b/src/RapidCMS.Api.Core/Resolvers/FileHandlerResolver.cs index 3dbaf6d9..abb7cc0f 100644 --- a/src/RapidCMS.Api.Core/Resolvers/FileHandlerResolver.cs +++ b/src/RapidCMS.Api.Core/Resolvers/FileHandlerResolver.cs @@ -5,32 +5,31 @@ using RapidCMS.Core.Abstractions.Config; using RapidCMS.Core.Extensions; -namespace RapidCMS.Api.Core.Resolvers +namespace RapidCMS.Api.Core.Resolvers; + +internal class FileHandlerResolver : IFileHandlerResolver { - internal class FileHandlerResolver : IFileHandlerResolver + private readonly IServiceProvider _serviceProvider; + private readonly IApiConfig _config; + + public FileHandlerResolver( + IServiceProvider serviceProvider, + IApiConfig config) { - private readonly IServiceProvider _serviceProvider; - private readonly IApiConfig _config; + _serviceProvider = serviceProvider; + _config = config; + } - public FileHandlerResolver( - IServiceProvider serviceProvider, - IApiConfig config) + public IFileHandler GetFileHandler(string uploadHandlerAlias) + { + var handlerConfig = _config.FileUploadHandlers.FirstOrDefault(x => x.Alias == uploadHandlerAlias); + if (handlerConfig == null) { - _serviceProvider = serviceProvider; - _config = config; + throw new InvalidOperationException(); } - public IFileHandler GetFileHandler(string uploadHandlerAlias) - { - var handlerConfig = _config.FileUploadHandlers.FirstOrDefault(x => x.Alias == uploadHandlerAlias); - if (handlerConfig == null) - { - throw new InvalidOperationException(); - } - - var handlerType = typeof(FileHandler<>).MakeGenericType(handlerConfig.HandlerType); + var handlerType = typeof(FileHandler<>).MakeGenericType(handlerConfig.HandlerType); - return _serviceProvider.GetService(handlerType); - } + return _serviceProvider.GetService(handlerType); } } diff --git a/src/RapidCMS.Api.Core/Services/ApiAuthService.cs b/src/RapidCMS.Api.Core/Services/ApiAuthService.cs index 7bf1fc71..5a2d96a4 100644 --- a/src/RapidCMS.Api.Core/Services/ApiAuthService.cs +++ b/src/RapidCMS.Api.Core/Services/ApiAuthService.cs @@ -10,66 +10,65 @@ using RapidCMS.Core.Forms; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Api.Core.Services +namespace RapidCMS.Api.Core.Services; + +internal class ApiAuthService : IAuthService { - internal class ApiAuthService : IAuthService + private readonly IUserResolver _userResolver; + private readonly IAuthorizationService _authorizationService; + + public ApiAuthService( + IUserResolver userResolver, + IAuthorizationService authorizationService) { - private readonly IUserResolver _userResolver; - private readonly IAuthorizationService _authorizationService; + _userResolver = userResolver; + _authorizationService = authorizationService; + } - public ApiAuthService( - IUserResolver userResolver, - IAuthorizationService authorizationService) - { - _userResolver = userResolver; - _authorizationService = authorizationService; - } + public Task IsUserAuthorizedAsync(UsageType usageType, IEntity entity) + { + return IsUserAuthorizedAsync(Operations.GetOperationForUsageType(usageType), entity); + } - public Task IsUserAuthorizedAsync(UsageType usageType, IEntity entity) + public async Task EnsureAuthorizedUserAsync(UsageType usageType, IEntity entity) + { + if (!await IsUserAuthorizedAsync(usageType, entity)) { - return IsUserAuthorizedAsync(Operations.GetOperationForUsageType(usageType), entity); + throw new UnauthorizedAccessException(); } + } - public async Task EnsureAuthorizedUserAsync(UsageType usageType, IEntity entity) + public async Task IsUserAuthorizedAsync(OperationAuthorizationRequirement operation, IEntity entity) + { + var user = _userResolver.GetUser(); + if (user == null) { - if (!await IsUserAuthorizedAsync(usageType, entity)) - { - throw new UnauthorizedAccessException(); - } + return false; } - public async Task IsUserAuthorizedAsync(OperationAuthorizationRequirement operation, IEntity entity) - { - var user = _userResolver.GetUser(); - if (user == null) - { - return false; - } + var authorizationChallenge = await _authorizationService.AuthorizeAsync(user, entity, operation); - var authorizationChallenge = await _authorizationService.AuthorizeAsync(user, entity, operation); - - return authorizationChallenge.Succeeded; - } + return authorizationChallenge.Succeeded; + } - public async Task EnsureAuthorizedUserAsync(OperationAuthorizationRequirement operation, IEntity entity) + public async Task EnsureAuthorizedUserAsync(OperationAuthorizationRequirement operation, IEntity entity) + { + if (!await IsUserAuthorizedAsync(operation, entity)) { - if (!await IsUserAuthorizedAsync(operation, entity)) - { - throw new UnauthorizedAccessException(); - } + throw new UnauthorizedAccessException(); } + } - public Task IsUserAuthorizedAsync(FormEditContext editContext, ButtonSetup button) - { - throw new NotImplementedException("This method is not implemented in ApiAuthService as it makes no sense here."); - } + public Task IsUserAuthorizedAsync(FormEditContext editContext, ButtonSetup button) + { + throw new NotImplementedException("This method is not implemented in ApiAuthService as it makes no sense here."); + } - public async Task EnsureAuthorizedUserAsync(FormEditContext editContext, ButtonSetup button) + public async Task EnsureAuthorizedUserAsync(FormEditContext editContext, ButtonSetup button) + { + if (!await IsUserAuthorizedAsync(editContext, button)) { - if (!await IsUserAuthorizedAsync(editContext, button)) - { - throw new UnauthorizedAccessException(); - } + throw new UnauthorizedAccessException(); } } } diff --git a/src/RapidCMS.Api.Functions/Abstractions/IFunctionContextAccessor.cs b/src/RapidCMS.Api.Functions/Abstractions/IFunctionContextAccessor.cs index 3ae1aaaa..989312b4 100644 --- a/src/RapidCMS.Api.Functions/Abstractions/IFunctionContextAccessor.cs +++ b/src/RapidCMS.Api.Functions/Abstractions/IFunctionContextAccessor.cs @@ -1,12 +1,11 @@ using Microsoft.Azure.Functions.Worker; -namespace RapidCMS.Api.Functions.Abstractions +namespace RapidCMS.Api.Functions.Abstractions; + +/// +/// PREVIEW: This class should be replaced by something first-party. +/// +public interface IFunctionContextAccessor { - /// - /// PREVIEW: This class should be replaced by something first-party. - /// - public interface IFunctionContextAccessor - { - FunctionContext? FunctionExecutionContext { get; set; } - } + FunctionContext? FunctionExecutionContext { get; set; } } diff --git a/src/RapidCMS.Api.Functions/Accessors/FunctionContextAccessor.cs b/src/RapidCMS.Api.Functions/Accessors/FunctionContextAccessor.cs index 4ac77b71..dfcd1698 100644 --- a/src/RapidCMS.Api.Functions/Accessors/FunctionContextAccessor.cs +++ b/src/RapidCMS.Api.Functions/Accessors/FunctionContextAccessor.cs @@ -2,38 +2,37 @@ using Microsoft.Azure.Functions.Worker; using RapidCMS.Api.Functions.Abstractions; -namespace RapidCMS.Api.Functions.Accessors +namespace RapidCMS.Api.Functions.Accessors; + +// PREVIEW: this accessor is temporary and should be replaced with something first party +// TODO: test this accessor in concurrent function requests +internal class FunctionContextAccessor : IFunctionContextAccessor { - // PREVIEW: this accessor is temporary and should be replaced with something first party - // TODO: test this accessor in concurrent function requests - internal class FunctionContextAccessor : IFunctionContextAccessor - { - private static AsyncLocal _contextCurrent = new AsyncLocal(); + private static AsyncLocal _contextCurrent = new AsyncLocal(); - FunctionContext? IFunctionContextAccessor.FunctionExecutionContext + FunctionContext? IFunctionContextAccessor.FunctionExecutionContext + { + get { - get + return _contextCurrent.Value?.Context; + } + set + { + var holder = _contextCurrent.Value; + if (holder != null) { - return _contextCurrent.Value?.Context; + holder.Context = null!; } - set - { - var holder = _contextCurrent.Value; - if (holder != null) - { - holder.Context = null!; - } - if (value != null) - { - _contextCurrent.Value = new ContextHolder { Context = value }; - } + if (value != null) + { + _contextCurrent.Value = new ContextHolder { Context = value }; } } + } - private class ContextHolder - { - public FunctionContext Context = default!; - } + private class ContextHolder + { + public FunctionContext Context = default!; } } diff --git a/src/RapidCMS.Api.Functions/Extensions/HttpRequestDataExtensions.cs b/src/RapidCMS.Api.Functions/Extensions/HttpRequestDataExtensions.cs index a6fa5ef4..f35b9524 100644 --- a/src/RapidCMS.Api.Functions/Extensions/HttpRequestDataExtensions.cs +++ b/src/RapidCMS.Api.Functions/Extensions/HttpRequestDataExtensions.cs @@ -3,18 +3,17 @@ using Microsoft.Azure.Functions.Worker.Http; using RapidCMS.Api.Core.Models; -namespace RapidCMS.Api.Functions.Extensions +namespace RapidCMS.Api.Functions.Extensions; + +internal static class HttpRequestDataExtensions { - internal static class HttpRequestDataExtensions + public static HttpResponseData CreateResponse(this HttpRequestData request, ApiResponseModel model) { - public static HttpResponseData CreateResponse(this HttpRequestData request, ApiResponseModel model) + var response = request.CreateResponse(model.StatusCode); + if (!string.IsNullOrEmpty(model.ResponseBody)) { - var response = request.CreateResponse(model.StatusCode); - if (!string.IsNullOrEmpty(model.ResponseBody)) - { - response.Body = new MemoryStream(Encoding.UTF8.GetBytes(model.ResponseBody)); - } - return response; + response.Body = new MemoryStream(Encoding.UTF8.GetBytes(model.ResponseBody)); } + return response; } } diff --git a/src/RapidCMS.Api.Functions/Functions/ApiFunctions.cs b/src/RapidCMS.Api.Functions/Functions/ApiFunctions.cs index e9259503..9233a37a 100644 --- a/src/RapidCMS.Api.Functions/Functions/ApiFunctions.cs +++ b/src/RapidCMS.Api.Functions/Functions/ApiFunctions.cs @@ -6,154 +6,153 @@ using RapidCMS.Api.Functions.Abstractions; using RapidCMS.Api.Functions.Extensions; -namespace RapidCMS.Api.Functions.Functions +namespace RapidCMS.Api.Functions.Functions; + +public class ApiFunctions { - public class ApiFunctions + private readonly IApiHandlerResolver _apiHandlerResolver; + private readonly IFunctionContextAccessor _functionExecutionContextAccessor; + + public ApiFunctions( + IApiHandlerResolver apiHandlerResolver, + IFunctionContextAccessor functionExecutionContextAccessor) + { + _apiHandlerResolver = apiHandlerResolver; + _functionExecutionContextAccessor = functionExecutionContextAccessor; + } + + [Function(nameof(GetByIdAsync))] + public async Task GetByIdAsync( + [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "_rapidcms/{repositoryAlias}/entity/{id}")] HttpRequestData req, + string repositoryAlias, + string id, + FunctionContext context) + { + _functionExecutionContextAccessor.FunctionExecutionContext = context; + + var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).GetByIdAsync(new ApiRequestModel { Id = id, Body = await req.ReadAsStringAsync() }); + return req.CreateResponse(response); + } + + [Function(nameof(GetAllAsync))] + public async Task GetAllAsync( + [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "_rapidcms/{repositoryAlias}/all")] HttpRequestData req, + string repositoryAlias, + FunctionContext context) + { + _functionExecutionContextAccessor.FunctionExecutionContext = context; + + var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).GetAllAsync(new ApiRequestModel { Body = await req.ReadAsStringAsync() }); + return req.CreateResponse(response); + } + + [Function(nameof(GetAllRelatedAsync))] + public async Task GetAllRelatedAsync( + [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "_rapidcms/{repositoryAlias}/all/related")] HttpRequestData req, + string repositoryAlias, + FunctionContext context) + { + _functionExecutionContextAccessor.FunctionExecutionContext = context; + + var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).GetAllRelatedAsync(new ApiRequestModel { Body = await req.ReadAsStringAsync() }); + return req.CreateResponse(response); + } + + [Function(nameof(GetAllNonRelatedAsync))] + public async Task GetAllNonRelatedAsync( + [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "_rapidcms/{repositoryAlias}/all/nonrelated")] HttpRequestData req, + string repositoryAlias, + FunctionContext context) + { + _functionExecutionContextAccessor.FunctionExecutionContext = context; + + var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).GetAllNonRelatedAsync(new ApiRequestModel { Body = await req.ReadAsStringAsync() }); + return req.CreateResponse(response); + } + + [Function(nameof(NewAsync))] + public async Task NewAsync( + [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "_rapidcms/{repositoryAlias}/new")] HttpRequestData req, + string repositoryAlias, + FunctionContext context) + { + _functionExecutionContextAccessor.FunctionExecutionContext = context; + + var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).NewAsync(new ApiRequestModel { Body = await req.ReadAsStringAsync() }); + return req.CreateResponse(response); + } + + [Function(nameof(InsertAsync))] + public async Task InsertAsync( + [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "_rapidcms/{repositoryAlias}/entity")] HttpRequestData req, + string repositoryAlias, + FunctionContext context) + { + _functionExecutionContextAccessor.FunctionExecutionContext = context; + + var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).InsertAsync(new ApiRequestModel { Body = await req.ReadAsStringAsync() }); + return req.CreateResponse(response); + } + + [Function(nameof(UpdateAsync))] + public async Task UpdateAsync( + [HttpTrigger(AuthorizationLevel.Anonymous, "put", Route = "_rapidcms/{repositoryAlias}/entity/{id}")] HttpRequestData req, + string repositoryAlias, + string id, + FunctionContext context) { - private readonly IApiHandlerResolver _apiHandlerResolver; - private readonly IFunctionContextAccessor _functionExecutionContextAccessor; - - public ApiFunctions( - IApiHandlerResolver apiHandlerResolver, - IFunctionContextAccessor functionExecutionContextAccessor) - { - _apiHandlerResolver = apiHandlerResolver; - _functionExecutionContextAccessor = functionExecutionContextAccessor; - } - - [Function(nameof(GetByIdAsync))] - public async Task GetByIdAsync( - [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "_rapidcms/{repositoryAlias}/entity/{id}")] HttpRequestData req, - string repositoryAlias, - string id, - FunctionContext context) - { - _functionExecutionContextAccessor.FunctionExecutionContext = context; - - var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).GetByIdAsync(new ApiRequestModel { Id = id, Body = await req.ReadAsStringAsync() }); - return req.CreateResponse(response); - } - - [Function(nameof(GetAllAsync))] - public async Task GetAllAsync( - [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "_rapidcms/{repositoryAlias}/all")] HttpRequestData req, - string repositoryAlias, - FunctionContext context) - { - _functionExecutionContextAccessor.FunctionExecutionContext = context; - - var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).GetAllAsync(new ApiRequestModel { Body = await req.ReadAsStringAsync() }); - return req.CreateResponse(response); - } - - [Function(nameof(GetAllRelatedAsync))] - public async Task GetAllRelatedAsync( - [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "_rapidcms/{repositoryAlias}/all/related")] HttpRequestData req, - string repositoryAlias, - FunctionContext context) - { - _functionExecutionContextAccessor.FunctionExecutionContext = context; - - var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).GetAllRelatedAsync(new ApiRequestModel { Body = await req.ReadAsStringAsync() }); - return req.CreateResponse(response); - } - - [Function(nameof(GetAllNonRelatedAsync))] - public async Task GetAllNonRelatedAsync( - [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "_rapidcms/{repositoryAlias}/all/nonrelated")] HttpRequestData req, - string repositoryAlias, - FunctionContext context) - { - _functionExecutionContextAccessor.FunctionExecutionContext = context; - - var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).GetAllNonRelatedAsync(new ApiRequestModel { Body = await req.ReadAsStringAsync() }); - return req.CreateResponse(response); - } - - [Function(nameof(NewAsync))] - public async Task NewAsync( - [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "_rapidcms/{repositoryAlias}/new")] HttpRequestData req, - string repositoryAlias, - FunctionContext context) - { - _functionExecutionContextAccessor.FunctionExecutionContext = context; - - var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).NewAsync(new ApiRequestModel { Body = await req.ReadAsStringAsync() }); - return req.CreateResponse(response); - } - - [Function(nameof(InsertAsync))] - public async Task InsertAsync( - [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "_rapidcms/{repositoryAlias}/entity")] HttpRequestData req, - string repositoryAlias, - FunctionContext context) - { - _functionExecutionContextAccessor.FunctionExecutionContext = context; - - var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).InsertAsync(new ApiRequestModel { Body = await req.ReadAsStringAsync() }); - return req.CreateResponse(response); - } - - [Function(nameof(UpdateAsync))] - public async Task UpdateAsync( - [HttpTrigger(AuthorizationLevel.Anonymous, "put", Route = "_rapidcms/{repositoryAlias}/entity/{id}")] HttpRequestData req, - string repositoryAlias, - string id, - FunctionContext context) - { - _functionExecutionContextAccessor.FunctionExecutionContext = context; - - var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).UpdateAsync(new ApiRequestModel { Id = id, Body = await req.ReadAsStringAsync() }); - return req.CreateResponse(response); - } - - [Function(nameof(DeleteAsync))] - public async Task DeleteAsync( - [HttpTrigger(AuthorizationLevel.Anonymous, "delete", Route = "_rapidcms/{repositoryAlias}/entity/{id}")] HttpRequestData req, - string repositoryAlias, - string id, - FunctionContext context) - { - _functionExecutionContextAccessor.FunctionExecutionContext = context; - - var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).DeleteAsync(new ApiRequestModel { Id = id, Body = await req.ReadAsStringAsync() }); - return req.CreateResponse(response); - } - - [Function(nameof(AddRelationAsync))] - public async Task AddRelationAsync( - [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "_rapidcms/{repositoryAlias}/relate")] HttpRequestData req, - string repositoryAlias, - FunctionContext context) - { - _functionExecutionContextAccessor.FunctionExecutionContext = context; - - var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).AddRelationAsync(new ApiRequestModel { Body = await req.ReadAsStringAsync() }); - return req.CreateResponse(response); - } - - [Function(nameof(RemoveRelationAsync))] - public async Task RemoveRelationAsync( - [HttpTrigger(AuthorizationLevel.Anonymous, "delete", Route = "_rapidcms/{repositoryAlias}/relate")] HttpRequestData req, - string repositoryAlias, - FunctionContext context) - { - _functionExecutionContextAccessor.FunctionExecutionContext = context; - - var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).RemoveRelationAsync(new ApiRequestModel { Body = await req.ReadAsStringAsync() }); - return req.CreateResponse(response); - } - - [Function(nameof(ReorderAsync))] - public async Task ReorderAsync( - [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "_rapidcms/{repositoryAlias}/reorder")] HttpRequestData req, - string repositoryAlias, - FunctionContext context) - { - _functionExecutionContextAccessor.FunctionExecutionContext = context; - - var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).ReorderAsync(new ApiRequestModel { Body = await req.ReadAsStringAsync() }); - return req.CreateResponse(response); - } + _functionExecutionContextAccessor.FunctionExecutionContext = context; + + var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).UpdateAsync(new ApiRequestModel { Id = id, Body = await req.ReadAsStringAsync() }); + return req.CreateResponse(response); + } + + [Function(nameof(DeleteAsync))] + public async Task DeleteAsync( + [HttpTrigger(AuthorizationLevel.Anonymous, "delete", Route = "_rapidcms/{repositoryAlias}/entity/{id}")] HttpRequestData req, + string repositoryAlias, + string id, + FunctionContext context) + { + _functionExecutionContextAccessor.FunctionExecutionContext = context; + + var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).DeleteAsync(new ApiRequestModel { Id = id, Body = await req.ReadAsStringAsync() }); + return req.CreateResponse(response); + } + + [Function(nameof(AddRelationAsync))] + public async Task AddRelationAsync( + [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "_rapidcms/{repositoryAlias}/relate")] HttpRequestData req, + string repositoryAlias, + FunctionContext context) + { + _functionExecutionContextAccessor.FunctionExecutionContext = context; + + var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).AddRelationAsync(new ApiRequestModel { Body = await req.ReadAsStringAsync() }); + return req.CreateResponse(response); + } + + [Function(nameof(RemoveRelationAsync))] + public async Task RemoveRelationAsync( + [HttpTrigger(AuthorizationLevel.Anonymous, "delete", Route = "_rapidcms/{repositoryAlias}/relate")] HttpRequestData req, + string repositoryAlias, + FunctionContext context) + { + _functionExecutionContextAccessor.FunctionExecutionContext = context; + + var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).RemoveRelationAsync(new ApiRequestModel { Body = await req.ReadAsStringAsync() }); + return req.CreateResponse(response); + } + + [Function(nameof(ReorderAsync))] + public async Task ReorderAsync( + [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "_rapidcms/{repositoryAlias}/reorder")] HttpRequestData req, + string repositoryAlias, + FunctionContext context) + { + _functionExecutionContextAccessor.FunctionExecutionContext = context; + + var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).ReorderAsync(new ApiRequestModel { Body = await req.ReadAsStringAsync() }); + return req.CreateResponse(response); } } diff --git a/src/RapidCMS.Api.Functions/Functions/FileFunctions.cs b/src/RapidCMS.Api.Functions/Functions/FileFunctions.cs index d302ffb8..2426c2a4 100644 --- a/src/RapidCMS.Api.Functions/Functions/FileFunctions.cs +++ b/src/RapidCMS.Api.Functions/Functions/FileFunctions.cs @@ -12,83 +12,82 @@ using RapidCMS.Api.Functions.Extensions; using RapidCMS.Core.Models.ApiBridge.Request; -namespace RapidCMS.Api.Functions.Functions +namespace RapidCMS.Api.Functions.Functions; + +public class FileUploadFunctions { - public class FileUploadFunctions + private readonly IFileHandlerResolver _fileHandlerResolver; + private readonly IFunctionContextAccessor _functionExecutionContextAccessor; + + public FileUploadFunctions( + IFileHandlerResolver fileHandlerResolver, + IFunctionContextAccessor functionExecutionContextAccessor) { - private readonly IFileHandlerResolver _fileHandlerResolver; - private readonly IFunctionContextAccessor _functionExecutionContextAccessor; + _fileHandlerResolver = fileHandlerResolver; + _functionExecutionContextAccessor = functionExecutionContextAccessor; + } - public FileUploadFunctions( - IFileHandlerResolver fileHandlerResolver, - IFunctionContextAccessor functionExecutionContextAccessor) - { - _fileHandlerResolver = fileHandlerResolver; - _functionExecutionContextAccessor = functionExecutionContextAccessor; - } + [Function(nameof(ValidateFileAsync))] + public async Task ValidateFileAsync( + [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "_rapidcms/{fileHandlerAlias}/file/validate")] HttpRequestData req, + string fileHandlerAlias, + FunctionContext context) + { + _functionExecutionContextAccessor.FunctionExecutionContext = context; - [Function(nameof(ValidateFileAsync))] - public async Task ValidateFileAsync( - [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "_rapidcms/{fileHandlerAlias}/file/validate")] HttpRequestData req, - string fileHandlerAlias, - FunctionContext context) + try { - _functionExecutionContextAccessor.FunctionExecutionContext = context; - - try + var (model, file) = await ReadBodyAsFormDataAsync(req); + if (file != null) { - var (model, file) = await ReadBodyAsFormDataAsync(req); - if (file != null) - { - throw new InvalidOperationException(); - } - - var response = await _fileHandlerResolver.GetFileHandler(fileHandlerAlias).ValidateFileAsync(model); - return req.CreateResponse(response); + throw new InvalidOperationException(); } - catch { } - return req.CreateResponse(HttpStatusCode.BadRequest); + var response = await _fileHandlerResolver.GetFileHandler(fileHandlerAlias).ValidateFileAsync(model); + return req.CreateResponse(response); } + catch { } - [Function(nameof(SaveFileAsync))] - public async Task SaveFileAsync( - [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "_rapidcms/{fileHandlerAlias}/file")] HttpRequestData req, - string fileHandlerAlias, - FunctionContext context) - { - _functionExecutionContextAccessor.FunctionExecutionContext = context; + return req.CreateResponse(HttpStatusCode.BadRequest); + } - try - { - var (model, file) = await ReadBodyAsFormDataAsync(req); - if (file == null) - { - throw new InvalidOperationException(); - } + [Function(nameof(SaveFileAsync))] + public async Task SaveFileAsync( + [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "_rapidcms/{fileHandlerAlias}/file")] HttpRequestData req, + string fileHandlerAlias, + FunctionContext context) + { + _functionExecutionContextAccessor.FunctionExecutionContext = context; - var response = await _fileHandlerResolver.GetFileHandler(fileHandlerAlias).SaveFileAsync(model, file); - return req.CreateResponse(response); + try + { + var (model, file) = await ReadBodyAsFormDataAsync(req); + if (file == null) + { + throw new InvalidOperationException(); } - catch { } - return req.CreateResponse(HttpStatusCode.BadRequest); + var response = await _fileHandlerResolver.GetFileHandler(fileHandlerAlias).SaveFileAsync(model, file); + return req.CreateResponse(response); } + catch { } - private static async Task<(UploadFileModel model, Stream? file)> ReadBodyAsFormDataAsync(HttpRequestData req) + return req.CreateResponse(HttpStatusCode.BadRequest); + } + + private static async Task<(UploadFileModel model, Stream? file)> ReadBodyAsFormDataAsync(HttpRequestData req) + { + var result = await MultipartFormDataParser.ParseAsync(req.Body); + var model = new UploadFileModel() { - var result = await MultipartFormDataParser.ParseAsync(req.Body); - var model = new UploadFileModel() - { - Name = result.Parameters.FirstOrDefault(x => x.Name == nameof(UploadFileModel.Name))?.Data!, - Size = long.Parse(result.Parameters.FirstOrDefault(x => x.Name == nameof(UploadFileModel.Size))?.Data!), - Type = result.Parameters.FirstOrDefault(x => x.Name == nameof(UploadFileModel.Type))?.Data!, - LastModified = long.Parse(result.Parameters.FirstOrDefault(x => x.Name == nameof(UploadFileModel.LastModified))?.Data!) - }; + Name = result.Parameters.FirstOrDefault(x => x.Name == nameof(UploadFileModel.Name))?.Data!, + Size = long.Parse(result.Parameters.FirstOrDefault(x => x.Name == nameof(UploadFileModel.Size))?.Data!), + Type = result.Parameters.FirstOrDefault(x => x.Name == nameof(UploadFileModel.Type))?.Data!, + LastModified = long.Parse(result.Parameters.FirstOrDefault(x => x.Name == nameof(UploadFileModel.LastModified))?.Data!) + }; - Validator.ValidateObject(model, new ValidationContext(model)); + Validator.ValidateObject(model, new ValidationContext(model)); - return (model, result.Files.FirstOrDefault(x => x.Name == "file")?.Data); - } + return (model, result.Files.FirstOrDefault(x => x.Name == "file")?.Data); } } diff --git a/src/RapidCMS.Api.Functions/RapidCMS.Api.Functions.csproj b/src/RapidCMS.Api.Functions/RapidCMS.Api.Functions.csproj index 4f020f00..856c6806 100644 --- a/src/RapidCMS.Api.Functions/RapidCMS.Api.Functions.csproj +++ b/src/RapidCMS.Api.Functions/RapidCMS.Api.Functions.csproj @@ -2,7 +2,6 @@ net6.0 - 10.0 enable Thomas Bleijendaal Thomas Bleijendaal diff --git a/src/RapidCMS.Api.Functions/RapidCMSMiddlewareFunctions.cs b/src/RapidCMS.Api.Functions/RapidCMSMiddlewareFunctions.cs index a2a52af8..bc77c739 100644 --- a/src/RapidCMS.Api.Functions/RapidCMSMiddlewareFunctions.cs +++ b/src/RapidCMS.Api.Functions/RapidCMSMiddlewareFunctions.cs @@ -7,33 +7,32 @@ using RapidCMS.Core.Abstractions.Resolvers; using RapidCMS.Core.Models.Config.Api; -namespace Microsoft.Extensions.DependencyInjection -{ - public static class RapidCMSMiddlewareFunctions - { - private static ApiConfig? _rootConfig; +namespace Microsoft.Extensions.DependencyInjection; - public static IServiceCollection AddRapidCMSFunctions(this IServiceCollection services, Action? config = null) - { - _rootConfig = GetRootConfig(config); +public static class RapidCMSMiddlewareFunctions +{ + private static ApiConfig? _rootConfig; - services.AddRapidCMSApiCore(_rootConfig); + public static IServiceCollection AddRapidCMSFunctions(this IServiceCollection services, Action? config = null) + { + _rootConfig = GetRootConfig(config); - services.AddSingleton(); + services.AddRapidCMSApiCore(_rootConfig); - if (!_rootConfig.AllowAnonymousUsage) - { - services.AddSingleton(); - } + services.AddSingleton(); - return services; - } - - private static ApiConfig GetRootConfig(Action? config = null) + if (!_rootConfig.AllowAnonymousUsage) { - var rootConfig = new ApiConfig(); - config?.Invoke(rootConfig); - return rootConfig; + services.AddSingleton(); } + + return services; + } + + private static ApiConfig GetRootConfig(Action? config = null) + { + var rootConfig = new ApiConfig(); + config?.Invoke(rootConfig); + return rootConfig; } } diff --git a/src/RapidCMS.Api.Functions/Resolvers/UserResolver.cs b/src/RapidCMS.Api.Functions/Resolvers/UserResolver.cs index b4f9b02e..222a018e 100644 --- a/src/RapidCMS.Api.Functions/Resolvers/UserResolver.cs +++ b/src/RapidCMS.Api.Functions/Resolvers/UserResolver.cs @@ -2,23 +2,22 @@ using RapidCMS.Api.Functions.Abstractions; using RapidCMS.Core.Abstractions.Resolvers; -namespace RapidCMS.Api.Functions.Resolvers -{ - internal class UserResolver : IUserResolver - { - private readonly IFunctionContextAccessor _functionExecutionContextAccessor; +namespace RapidCMS.Api.Functions.Resolvers; - public UserResolver( - IFunctionContextAccessor functionExecutionContextAccessor) - { - _functionExecutionContextAccessor = functionExecutionContextAccessor; - } +internal class UserResolver : IUserResolver +{ + private readonly IFunctionContextAccessor _functionExecutionContextAccessor; - public ClaimsPrincipal? GetUser() - => _functionExecutionContextAccessor.FunctionExecutionContext != null && - _functionExecutionContextAccessor.FunctionExecutionContext.Items.TryGetValue("User", out var userObject) && - userObject is ClaimsPrincipal user - ? user - : default; + public UserResolver( + IFunctionContextAccessor functionExecutionContextAccessor) + { + _functionExecutionContextAccessor = functionExecutionContextAccessor; } + + public ClaimsPrincipal? GetUser() + => _functionExecutionContextAccessor.FunctionExecutionContext != null && + _functionExecutionContextAccessor.FunctionExecutionContext.Items.TryGetValue("User", out var userObject) && + userObject is ClaimsPrincipal user + ? user + : default; } diff --git a/src/RapidCMS.Api.WebApi/Controllers/ApiFileUploadController.cs b/src/RapidCMS.Api.WebApi/Controllers/ApiFileUploadController.cs index 6aa5dd87..6f6ba2f3 100644 --- a/src/RapidCMS.Api.WebApi/Controllers/ApiFileUploadController.cs +++ b/src/RapidCMS.Api.WebApi/Controllers/ApiFileUploadController.cs @@ -6,42 +6,41 @@ using RapidCMS.Core.Models.ApiBridge.Request; using RapidCMS.Core.Models.Response; -namespace RapidCMS.Api.WebApi.Controllers +namespace RapidCMS.Api.WebApi.Controllers; + +[ApiController] +public class ApiFileUploadController : ControllerBase { - [ApiController] - public class ApiFileUploadController : ControllerBase + private readonly IFileHandlerResolver _fileHandlerResolver; + + public ApiFileUploadController(IFileHandlerResolver fileHandlerResolver) { - private readonly IFileHandlerResolver _fileHandlerResolver; + _fileHandlerResolver = fileHandlerResolver; + } - public ApiFileUploadController(IFileHandlerResolver fileHandlerResolver) + [HttpPost("_rapidcms/{fileHandlerAlias}/file/validate")] + public async Task> ValidateFileAsync(string fileHandlerAlias, [FromForm] UploadFileModel model) + { + try { - _fileHandlerResolver = fileHandlerResolver; + var response = await _fileHandlerResolver.GetFileHandler(fileHandlerAlias).ValidateFileAsync(model); + return response.ToContentResult(); } + catch { } - [HttpPost("_rapidcms/{fileHandlerAlias}/file/validate")] - public async Task> ValidateFileAsync(string fileHandlerAlias, [FromForm] UploadFileModel model) - { - try - { - var response = await _fileHandlerResolver.GetFileHandler(fileHandlerAlias).ValidateFileAsync(model); - return response.ToContentResult(); - } - catch { } - - return BadRequest(); - } + return BadRequest(); + } - [HttpPost("_rapidcms/{fileHandlerAlias}/file")] - public async Task> SaveFileAsync(string fileHandlerAlias, [FromForm] UploadFileModel model, [FromForm(Name = "file")] IFormFile file) + [HttpPost("_rapidcms/{fileHandlerAlias}/file")] + public async Task> SaveFileAsync(string fileHandlerAlias, [FromForm] UploadFileModel model, [FromForm(Name = "file")] IFormFile file) + { + try { - try - { - var response = await _fileHandlerResolver.GetFileHandler(fileHandlerAlias).SaveFileAsync(model, file.OpenReadStream()); - return response.ToContentResult(); - } - catch { } - - return BadRequest(); + var response = await _fileHandlerResolver.GetFileHandler(fileHandlerAlias).SaveFileAsync(model, file.OpenReadStream()); + return response.ToContentResult(); } + catch { } + + return BadRequest(); } } diff --git a/src/RapidCMS.Api.WebApi/Controllers/ApiRepositoryController.cs b/src/RapidCMS.Api.WebApi/Controllers/ApiRepositoryController.cs index 157b517c..f6cf8538 100644 --- a/src/RapidCMS.Api.WebApi/Controllers/ApiRepositoryController.cs +++ b/src/RapidCMS.Api.WebApi/Controllers/ApiRepositoryController.cs @@ -8,165 +8,164 @@ using RapidCMS.Core.Models.ApiBridge; using RapidCMS.Core.Models.ApiBridge.Response; -namespace RapidCMS.Api.WebApi.Controllers +namespace RapidCMS.Api.WebApi.Controllers; + +[ApiController] +public class ApiRepositoryController : ControllerBase { - [ApiController] - public class ApiRepositoryController : ControllerBase + private readonly IApiHandlerResolver _apiHandlerResolver; + + public ApiRepositoryController(IApiHandlerResolver apiHandlerResolver) { - private readonly IApiHandlerResolver _apiHandlerResolver; + _apiHandlerResolver = apiHandlerResolver; + } - public ApiRepositoryController(IApiHandlerResolver apiHandlerResolver) + [HttpPost("_rapidcms/{repositoryAlias}/entity/{id}")] + public async Task>> GetByIdAsync(string repositoryAlias, string id) + { + try { - _apiHandlerResolver = apiHandlerResolver; + var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).GetByIdAsync(new ApiRequestModel { Id = id, Body = await ReadBodyAsStringAsync() }); + return response.ToContentResult(); } + catch { } - [HttpPost("_rapidcms/{repositoryAlias}/entity/{id}")] - public async Task>> GetByIdAsync(string repositoryAlias, string id) - { - try - { - var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).GetByIdAsync(new ApiRequestModel { Id = id, Body = await ReadBodyAsStringAsync() }); - return response.ToContentResult(); - } - catch { } - - return BadRequest(); - } + return BadRequest(); + } - [HttpPost("_rapidcms/{repositoryAlias}/all")] - public async Task>> GetAllAsync(string repositoryAlias) + [HttpPost("_rapidcms/{repositoryAlias}/all")] + public async Task>> GetAllAsync(string repositoryAlias) + { + try { - try - { - var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).GetAllAsync(new ApiRequestModel { Body = await ReadBodyAsStringAsync() }); - return response.ToContentResult(); - } - catch { } - - return BadRequest(); + var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).GetAllAsync(new ApiRequestModel { Body = await ReadBodyAsStringAsync() }); + return response.ToContentResult(); } + catch { } - [HttpPost("_rapidcms/{repositoryAlias}/all/related")] - public async Task>> GetAllRelatedAsync(string repositoryAlias) - { - try - { - var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).GetAllRelatedAsync(new ApiRequestModel { Body = await ReadBodyAsStringAsync() }); - return response.ToContentResult(); - } - catch { } - - return BadRequest(); - } + return BadRequest(); + } - [HttpPost("_rapidcms/{repositoryAlias}/all/nonrelated")] - public async Task>> GetAllNonRelatedAsync(string repositoryAlias) + [HttpPost("_rapidcms/{repositoryAlias}/all/related")] + public async Task>> GetAllRelatedAsync(string repositoryAlias) + { + try { - try - { - var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).GetAllNonRelatedAsync(new ApiRequestModel { Body = await ReadBodyAsStringAsync() }); - return response.ToContentResult(); - } - catch { } - - return BadRequest(); + var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).GetAllRelatedAsync(new ApiRequestModel { Body = await ReadBodyAsStringAsync() }); + return response.ToContentResult(); } + catch { } - [HttpPost("_rapidcms/{repositoryAlias}/new")] - public async Task>> NewAsync(string repositoryAlias) + return BadRequest(); + } + + [HttpPost("_rapidcms/{repositoryAlias}/all/nonrelated")] + public async Task>> GetAllNonRelatedAsync(string repositoryAlias) + { + try { - try - { - var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).NewAsync(new ApiRequestModel { Body = await ReadBodyAsStringAsync() }); - return response.ToContentResult(); - } - catch { } - - return BadRequest(); + var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).GetAllNonRelatedAsync(new ApiRequestModel { Body = await ReadBodyAsStringAsync() }); + return response.ToContentResult(); } + catch { } - [HttpPost("_rapidcms/{repositoryAlias}/entity")] - public async Task?>> InsertAsync(string repositoryAlias) + return BadRequest(); + } + + [HttpPost("_rapidcms/{repositoryAlias}/new")] + public async Task>> NewAsync(string repositoryAlias) + { + try { - try - { - var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).InsertAsync(new ApiRequestModel { Body = await ReadBodyAsStringAsync() }); - return response.ToContentResult(); - } - catch { } - - return BadRequest(); + var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).NewAsync(new ApiRequestModel { Body = await ReadBodyAsStringAsync() }); + return response.ToContentResult(); } + catch { } + + return BadRequest(); + } - [HttpPut("_rapidcms/{repositoryAlias}/entity/{id}")] - public async Task UpdateAsync(string repositoryAlias, string id) + [HttpPost("_rapidcms/{repositoryAlias}/entity")] + public async Task?>> InsertAsync(string repositoryAlias) + { + try { - try - { - var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).UpdateAsync(new ApiRequestModel { Id = id, Body = await ReadBodyAsStringAsync() }); - return response.ToContentResult(); - } - catch { } - - return BadRequest(); + var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).InsertAsync(new ApiRequestModel { Body = await ReadBodyAsStringAsync() }); + return response.ToContentResult(); } + catch { } + + return BadRequest(); + } - [HttpDelete("_rapidcms/{repositoryAlias}/entity/{id}")] - public async Task DeleteAsync(string repositoryAlias, string id) + [HttpPut("_rapidcms/{repositoryAlias}/entity/{id}")] + public async Task UpdateAsync(string repositoryAlias, string id) + { + try { - try - { - var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).DeleteAsync(new ApiRequestModel { Id = id, Body = await ReadBodyAsStringAsync() }); - return response.ToContentResult(); - } - catch { } - - return BadRequest(); + var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).UpdateAsync(new ApiRequestModel { Id = id, Body = await ReadBodyAsStringAsync() }); + return response.ToContentResult(); } + catch { } + + return BadRequest(); + } - [HttpPost("_rapidcms/{repositoryAlias}/relate")] - public async Task AddRelationAsync(string repositoryAlias) + [HttpDelete("_rapidcms/{repositoryAlias}/entity/{id}")] + public async Task DeleteAsync(string repositoryAlias, string id) + { + try { - try - { - var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).AddRelationAsync(new ApiRequestModel { Body = await ReadBodyAsStringAsync() }); - return response.ToContentResult(); - } - catch { } - - return BadRequest(); + var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).DeleteAsync(new ApiRequestModel { Id = id, Body = await ReadBodyAsStringAsync() }); + return response.ToContentResult(); } + catch { } - [HttpDelete("_rapidcms/{repositoryAlias}/relate")] - public async Task RemoveRelationAsync(string repositoryAlias) + return BadRequest(); + } + + [HttpPost("_rapidcms/{repositoryAlias}/relate")] + public async Task AddRelationAsync(string repositoryAlias) + { + try { - try - { - var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).RemoveRelationAsync(new ApiRequestModel { Body = await ReadBodyAsStringAsync() }); - return response.ToContentResult(); - } - catch { } - - return BadRequest(); + var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).AddRelationAsync(new ApiRequestModel { Body = await ReadBodyAsStringAsync() }); + return response.ToContentResult(); } + catch { } - [HttpPost("_rapidcms/{repositoryAlias}/reorder")] - public async Task ReorderAsync(string repositoryAlias) + return BadRequest(); + } + + [HttpDelete("_rapidcms/{repositoryAlias}/relate")] + public async Task RemoveRelationAsync(string repositoryAlias) + { + try { - try - { - var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).ReorderAsync(new ApiRequestModel { Body = await ReadBodyAsStringAsync() }); - return response.ToContentResult(); - } - catch { } - - return BadRequest(); + var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).RemoveRelationAsync(new ApiRequestModel { Body = await ReadBodyAsStringAsync() }); + return response.ToContentResult(); } + catch { } + + return BadRequest(); + } - private async Task ReadBodyAsStringAsync() + [HttpPost("_rapidcms/{repositoryAlias}/reorder")] + public async Task ReorderAsync(string repositoryAlias) + { + try { - using var streamReader = new StreamReader(Request.Body); - return await streamReader.ReadToEndAsync(); + var response = await _apiHandlerResolver.GetApiHandler(repositoryAlias).ReorderAsync(new ApiRequestModel { Body = await ReadBodyAsStringAsync() }); + return response.ToContentResult(); } + catch { } + + return BadRequest(); + } + + private async Task ReadBodyAsStringAsync() + { + using var streamReader = new StreamReader(Request.Body); + return await streamReader.ReadToEndAsync(); } } diff --git a/src/RapidCMS.Api.WebApi/Controllers/IFunctionExecutionContextAccessor.cs b/src/RapidCMS.Api.WebApi/Controllers/IFunctionExecutionContextAccessor.cs index 3cf470dc..5177d336 100644 --- a/src/RapidCMS.Api.WebApi/Controllers/IFunctionExecutionContextAccessor.cs +++ b/src/RapidCMS.Api.WebApi/Controllers/IFunctionExecutionContextAccessor.cs @@ -1,6 +1,5 @@ -namespace RapidCMS.Api.WebApi.Controllers +namespace RapidCMS.Api.WebApi.Controllers; + +public interface IFunctionExecutionContextAccessor { - public interface IFunctionExecutionContextAccessor - { - } } \ No newline at end of file diff --git a/src/RapidCMS.Api.WebApi/Conventions/CollectionControllerRouteConvention.cs b/src/RapidCMS.Api.WebApi/Conventions/CollectionControllerRouteConvention.cs index c6345fc9..259bd007 100644 --- a/src/RapidCMS.Api.WebApi/Conventions/CollectionControllerRouteConvention.cs +++ b/src/RapidCMS.Api.WebApi/Conventions/CollectionControllerRouteConvention.cs @@ -2,24 +2,23 @@ using RapidCMS.Api.WebApi.Controllers; using RapidCMS.Core.Extensions; -namespace RapidCMS.Api.WebApi.Conventions +namespace RapidCMS.Api.WebApi.Conventions; + +public class CollectionControllerRouteConvention : IControllerModelConvention { - public class CollectionControllerRouteConvention : IControllerModelConvention + public const string RouteTemplatePrefix = "/api/"; + + public void Apply(ControllerModel controller) { - public const string RouteTemplatePrefix = "/api/"; - - public void Apply(ControllerModel controller) + if (controller.ControllerType.In(typeof(ApiRepositoryController), typeof(ApiFileUploadController))) { - if (controller.ControllerType.In(typeof(ApiRepositoryController), typeof(ApiFileUploadController))) + controller.Selectors.Add(new SelectorModel { - controller.Selectors.Add(new SelectorModel + AttributeRouteModel = new AttributeRouteModel { - AttributeRouteModel = new AttributeRouteModel - { - Template = RouteTemplatePrefix - } - }); - } + Template = RouteTemplatePrefix + } + }); } } } diff --git a/src/RapidCMS.Api.WebApi/Extensions/ApiResponseModelExtensions.cs b/src/RapidCMS.Api.WebApi/Extensions/ApiResponseModelExtensions.cs index a8fd181c..21373c82 100644 --- a/src/RapidCMS.Api.WebApi/Extensions/ApiResponseModelExtensions.cs +++ b/src/RapidCMS.Api.WebApi/Extensions/ApiResponseModelExtensions.cs @@ -1,26 +1,25 @@ using Microsoft.AspNetCore.Mvc; using RapidCMS.Api.Core.Models; -namespace RapidCMS.Api.WebApi.Extensions +namespace RapidCMS.Api.WebApi.Extensions; + +public static class ApiResponseModelExtensions { - public static class ApiResponseModelExtensions + public static ContentResult ToContentResult(this ApiResponseModel model) { - public static ContentResult ToContentResult(this ApiResponseModel model) + if (model.ResponseBody == null) { - if (model.ResponseBody == null) - { - return new ContentResult - { - StatusCode = (int)model.StatusCode - }; - } - return new ContentResult { - Content = model.ResponseBody, - ContentType = "application/json", StatusCode = (int)model.StatusCode }; } + + return new ContentResult + { + Content = model.ResponseBody, + ContentType = "application/json", + StatusCode = (int)model.StatusCode + }; } } diff --git a/src/RapidCMS.Api.WebApi/Providers/CollectionControllerFeatureProvider.cs b/src/RapidCMS.Api.WebApi/Providers/CollectionControllerFeatureProvider.cs index 772c718f..824db283 100644 --- a/src/RapidCMS.Api.WebApi/Providers/CollectionControllerFeatureProvider.cs +++ b/src/RapidCMS.Api.WebApi/Providers/CollectionControllerFeatureProvider.cs @@ -4,14 +4,13 @@ using Microsoft.AspNetCore.Mvc.Controllers; using RapidCMS.Api.WebApi.Controllers; -namespace RapidCMS.Api.WebApi.Providers +namespace RapidCMS.Api.WebApi.Providers; + +public class CollectionControllerFeatureProvider : IApplicationFeatureProvider { - public class CollectionControllerFeatureProvider : IApplicationFeatureProvider + public void PopulateFeature(IEnumerable parts, ControllerFeature feature) { - public void PopulateFeature(IEnumerable parts, ControllerFeature feature) - { - feature.Controllers.Add(typeof(ApiRepositoryController).GetTypeInfo()); - feature.Controllers.Add(typeof(ApiFileUploadController).GetTypeInfo()); - } + feature.Controllers.Add(typeof(ApiRepositoryController).GetTypeInfo()); + feature.Controllers.Add(typeof(ApiFileUploadController).GetTypeInfo()); } } diff --git a/src/RapidCMS.Api.WebApi/RapidCMS.Api.WebApi.csproj b/src/RapidCMS.Api.WebApi/RapidCMS.Api.WebApi.csproj index 75909e14..6c420431 100644 --- a/src/RapidCMS.Api.WebApi/RapidCMS.Api.WebApi.csproj +++ b/src/RapidCMS.Api.WebApi/RapidCMS.Api.WebApi.csproj @@ -1,8 +1,7 @@  - net6.0 - 10.0 + net8.0 enable Thomas Bleijendaal Thomas Bleijendaal @@ -34,11 +33,15 @@ - + + + + + diff --git a/src/RapidCMS.Api.WebApi/RapidCMSMiddlewareWebApi.cs b/src/RapidCMS.Api.WebApi/RapidCMSMiddlewareWebApi.cs index c42f862f..abfb229c 100644 --- a/src/RapidCMS.Api.WebApi/RapidCMSMiddlewareWebApi.cs +++ b/src/RapidCMS.Api.WebApi/RapidCMSMiddlewareWebApi.cs @@ -12,73 +12,72 @@ using RapidCMS.Core.Converters; using RapidCMS.Core.Models.Config.Api; -namespace Microsoft.Extensions.DependencyInjection +namespace Microsoft.Extensions.DependencyInjection; + +public static class RapidCMSMiddlewareWebApi { - public static class RapidCMSMiddlewareWebApi + private static IControllerModelConvention? _routeConvention; + private static ApiConfig? _rootConfig; + + /// + /// Use this method to setup the Repository APIs to support RapidCMS WebAssenbly on a separate server. + /// + /// + /// + /// + public static IServiceCollection AddRapidCMSWebApi(this IServiceCollection services, Action? config = null) { - private static IControllerModelConvention? _routeConvention; - private static ApiConfig? _rootConfig; + _rootConfig = GetRootConfig(config); - /// - /// Use this method to setup the Repository APIs to support RapidCMS WebAssenbly on a separate server. - /// - /// - /// - /// - public static IServiceCollection AddRapidCMSWebApi(this IServiceCollection services, Action? config = null) - { - _rootConfig = GetRootConfig(config); + services.AddRapidCMSApiCore(_rootConfig); - services.AddRapidCMSApiCore(_rootConfig); + if (!_rootConfig.AllowAnonymousUsage) + { + services.AddSingleton(); + } - if (!_rootConfig.AllowAnonymousUsage) - { - services.AddSingleton(); - } + _routeConvention = new CollectionControllerRouteConvention(); - _routeConvention = new CollectionControllerRouteConvention(); + return services; + } - return services; + public static IMvcBuilder AddRapidCMSControllers(this IServiceCollection services, Action? extraConfig = default) + { + if (_rootConfig == null || _routeConvention == null) + { + throw new InvalidOperationException("Call AddRapidCMSApi() before calling this method."); } - public static IMvcBuilder AddRapidCMSControllers(this IServiceCollection services, Action? extraConfig = default) - { - if (_rootConfig == null || _routeConvention == null) + var builder = services + .AddControllers(config => { - throw new InvalidOperationException("Call AddRapidCMSApi() before calling this method."); - } + config.Conventions.Add(_routeConvention); - var builder = services - .AddControllers(config => - { - config.Conventions.Add(_routeConvention); - - extraConfig?.Invoke(config); - }) - .AddNewtonsoftJson(options => + extraConfig?.Invoke(config); + }) + .AddNewtonsoftJson(options => + { + // these settings are for reading json only + foreach (var entityType in _rootConfig.Repositories.Select(x => x.EntityType)) { - // these settings are for reading json only - foreach (var entityType in _rootConfig.Repositories.Select(x => x.EntityType)) + if (Activator.CreateInstance(typeof(EntityModelJsonConverter<>).MakeGenericType(entityType)) is JsonConverter jsonConverter) + { + options.SerializerSettings.Converters.Add(jsonConverter); + } + else { - if (Activator.CreateInstance(typeof(EntityModelJsonConverter<>).MakeGenericType(entityType)) is JsonConverter jsonConverter) - { - options.SerializerSettings.Converters.Add(jsonConverter); - } - else - { - throw new InvalidOperationException($"Could not create {nameof(EntityModelJsonConverter)} for {entityType.Name}"); - } + throw new InvalidOperationException($"Could not create {nameof(EntityModelJsonConverter)} for {entityType.Name}"); } - }); + } + }); - return builder; - } + return builder; + } - private static ApiConfig GetRootConfig(Action? config = null) - { - var rootConfig = new ApiConfig(); - config?.Invoke(rootConfig); - return rootConfig; - } + private static ApiConfig GetRootConfig(Action? config = null) + { + var rootConfig = new ApiConfig(); + config?.Invoke(rootConfig); + return rootConfig; } } diff --git a/src/RapidCMS.Api.WebApi/Resolvers/UserResolver.cs b/src/RapidCMS.Api.WebApi/Resolvers/UserResolver.cs index 698738b2..7f96f5cf 100644 --- a/src/RapidCMS.Api.WebApi/Resolvers/UserResolver.cs +++ b/src/RapidCMS.Api.WebApi/Resolvers/UserResolver.cs @@ -2,18 +2,17 @@ using Microsoft.AspNetCore.Http; using RapidCMS.Core.Abstractions.Resolvers; -namespace RapidCMS.Api.WebApi.Resolvers -{ - internal class UserResolver : IUserResolver - { - private readonly IHttpContextAccessor _httpContextAccessor; +namespace RapidCMS.Api.WebApi.Resolvers; - public UserResolver(IHttpContextAccessor httpContextAccessor) - { - _httpContextAccessor = httpContextAccessor; - } +internal class UserResolver : IUserResolver +{ + private readonly IHttpContextAccessor _httpContextAccessor; - public ClaimsPrincipal? GetUser() - => _httpContextAccessor.HttpContext?.User; + public UserResolver(IHttpContextAccessor httpContextAccessor) + { + _httpContextAccessor = httpContextAccessor; } + + public ClaimsPrincipal? GetUser() + => _httpContextAccessor.HttpContext?.User; } diff --git a/src/RapidCMS.Core.Tests/Forms/EditContextCustomValidationConfigurationTests.cs b/src/RapidCMS.Core.Tests/Forms/EditContextCustomValidationConfigurationTests.cs index bab7711b..b5f9e711 100644 --- a/src/RapidCMS.Core.Tests/Forms/EditContextCustomValidationConfigurationTests.cs +++ b/src/RapidCMS.Core.Tests/Forms/EditContextCustomValidationConfigurationTests.cs @@ -12,90 +12,89 @@ using System.Linq; using System.Threading.Tasks; -namespace RapidCMS.Core.Tests.Forms +namespace RapidCMS.Core.Tests.Forms; + +public class EditContextCustomValidationConfigurationTests { - public class EditContextCustomValidationConfigurationTests - { - private FormEditContext _subject = default!; - private ServiceCollection _serviceCollection = new ServiceCollection(); + private FormEditContext _subject = default!; + private ServiceCollection _serviceCollection = new ServiceCollection(); - [Test] - public async Task WhenInvalidEntityIsValidated_ThenIsValidShouldReturnFalseAsync() - { - _serviceCollection.AddSingleton(); + [Test] + public async Task WhenInvalidEntityIsValidated_ThenIsValidShouldReturnFalseAsync() + { + _serviceCollection.AddSingleton(); - _subject = new FormEditContext( - "alias", - "repoAlias", - "variantAlias", - new Entity { Id = "abc" }, - default, - UsageType.Edit, - new List - { - new ValidationSetup(typeof(ConfigurableEntityValidator), new ConfigurableEntityValidator.Config { InvalidId = "abc" }) - }, - _serviceCollection.BuildServiceProvider()); + _subject = new FormEditContext( + "alias", + "repoAlias", + "variantAlias", + new Entity { Id = "abc" }, + default, + UsageType.Edit, + new List + { + new ValidationSetup(typeof(ConfigurableEntityValidator), new ConfigurableEntityValidator.Config { InvalidId = "abc" }) + }, + _serviceCollection.BuildServiceProvider()); - _subject.NotifyPropertyIncludedInForm(PropertyMetadataHelper.GetPropertyMetadata(x => x.Id)); + _subject.NotifyPropertyIncludedInForm(PropertyMetadataHelper.GetPropertyMetadata(x => x.Id)); - // assert - Assert.IsFalse(await _subject.IsValidAsync()); - Assert.AreEqual("Id is null", _subject.GetPropertyState("Id").GetValidationMessages().First()); - } + // assert + Assert.IsFalse(await _subject.IsValidAsync()); + Assert.AreEqual("Id is null", _subject.GetPropertyState("Id").GetValidationMessages().First()); + } - [Test] - public async Task WhenValidEntityIsValidated_ThenIsValidShouldReturnTrueAsync() - { - _serviceCollection.AddSingleton(); + [Test] + public async Task WhenValidEntityIsValidated_ThenIsValidShouldReturnTrueAsync() + { + _serviceCollection.AddSingleton(); - _subject = new FormEditContext( - "alias", - "repoAlias", - "variantAlias", - new Entity - { - Id = "abcd" - }, - default, - UsageType.Edit, - new List - { - new ValidationSetup(typeof(ConfigurableEntityValidator), new ConfigurableEntityValidator.Config { InvalidId = "abc" }) - }, - _serviceCollection.BuildServiceProvider()); + _subject = new FormEditContext( + "alias", + "repoAlias", + "variantAlias", + new Entity + { + Id = "abcd" + }, + default, + UsageType.Edit, + new List + { + new ValidationSetup(typeof(ConfigurableEntityValidator), new ConfigurableEntityValidator.Config { InvalidId = "abc" }) + }, + _serviceCollection.BuildServiceProvider()); - _subject.NotifyPropertyIncludedInForm(PropertyMetadataHelper.GetPropertyMetadata(x => x.Id)); + _subject.NotifyPropertyIncludedInForm(PropertyMetadataHelper.GetPropertyMetadata(x => x.Id)); - // assert - Assert.IsTrue(await _subject.IsValidAsync()); - } + // assert + Assert.IsTrue(await _subject.IsValidAsync()); + } - public class Entity : IEntity - { - public string Id { get; set; } + public class Entity : IEntity + { + public string Id { get; set; } - public int X { get; set; } - } + public int X { get; set; } + } - public class ConfigurableEntityValidator : BaseEntityValidator + public class ConfigurableEntityValidator : BaseEntityValidator + { + public override IEnumerable Validate(IValidatorContext context) { - public override IEnumerable Validate(IValidatorContext context) + if (!string.IsNullOrEmpty(context.Entity.Id) && context.Entity.Id != (context.Configuration as Config)?.InvalidId) { - if (!string.IsNullOrEmpty(context.Entity.Id) && context.Entity.Id != (context.Configuration as Config)?.InvalidId) - { - yield break; - } - else - { - yield return new ValidationResult("Id is null", new[] { nameof(context.Entity.Id) }); - } + yield break; } - - public class Config + else { - public string InvalidId { get; set; } + yield return new ValidationResult("Id is null", new[] { nameof(context.Entity.Id) }); } } + + public class Config + { + public string InvalidId { get; set; } + } } } diff --git a/src/RapidCMS.Core.Tests/Forms/EditContextCustomValidationTests.cs b/src/RapidCMS.Core.Tests/Forms/EditContextCustomValidationTests.cs index 5f12feb3..03c86f20 100644 --- a/src/RapidCMS.Core.Tests/Forms/EditContextCustomValidationTests.cs +++ b/src/RapidCMS.Core.Tests/Forms/EditContextCustomValidationTests.cs @@ -12,84 +12,83 @@ using System.Linq; using System.Threading.Tasks; -namespace RapidCMS.Core.Tests.Forms +namespace RapidCMS.Core.Tests.Forms; + +public class EditContextCustomValidationTests { - public class EditContextCustomValidationTests - { - private FormEditContext _subject = default!; - private ServiceCollection _serviceCollection = new ServiceCollection(); + private FormEditContext _subject = default!; + private ServiceCollection _serviceCollection = new ServiceCollection(); - [Test] - public async Task WhenInvalidEntityIsValidated_ThenIsValidShouldReturnFalseAsync() - { - _serviceCollection.AddSingleton(); + [Test] + public async Task WhenInvalidEntityIsValidated_ThenIsValidShouldReturnFalseAsync() + { + _serviceCollection.AddSingleton(); - _subject = new FormEditContext( - "alias", - "repoAlias", - "variantAlias", - new Entity(), - default, - UsageType.Edit, - new List - { - (ValidationSetup)new ValidationSetup(typeof(EntityValidator), default) - }, - _serviceCollection.BuildServiceProvider()); + _subject = new FormEditContext( + "alias", + "repoAlias", + "variantAlias", + new Entity(), + default, + UsageType.Edit, + new List + { + (ValidationSetup)new ValidationSetup(typeof(EntityValidator), default) + }, + _serviceCollection.BuildServiceProvider()); - _subject.NotifyPropertyIncludedInForm(PropertyMetadataHelper.GetPropertyMetadata(x => x.Id)); + _subject.NotifyPropertyIncludedInForm(PropertyMetadataHelper.GetPropertyMetadata(x => x.Id)); - // assert - Assert.IsFalse(await _subject.IsValidAsync()); - Assert.AreEqual("Id is null", _subject.GetPropertyState("Id").GetValidationMessages().First()); - } + // assert + Assert.IsFalse(await _subject.IsValidAsync()); + Assert.AreEqual("Id is null", _subject.GetPropertyState("Id").GetValidationMessages().First()); + } - [Test] - public async Task WhenValidEntityIsValidated_ThenIsValidShouldReturnTrueAsync() - { - _serviceCollection.AddSingleton(); + [Test] + public async Task WhenValidEntityIsValidated_ThenIsValidShouldReturnTrueAsync() + { + _serviceCollection.AddSingleton(); - _subject = new FormEditContext( - "alias", - "repoAlias", - "variantAlias", - new Entity - { - Id = "valid" - }, - default, - UsageType.Edit, - new List - { - (ValidationSetup)new ValidationSetup(typeof(EntityValidator), default) - }, - _serviceCollection.BuildServiceProvider()); + _subject = new FormEditContext( + "alias", + "repoAlias", + "variantAlias", + new Entity + { + Id = "valid" + }, + default, + UsageType.Edit, + new List + { + (ValidationSetup)new ValidationSetup(typeof(EntityValidator), default) + }, + _serviceCollection.BuildServiceProvider()); - _subject.NotifyPropertyIncludedInForm(PropertyMetadataHelper.GetPropertyMetadata(x => x.Id)); + _subject.NotifyPropertyIncludedInForm(PropertyMetadataHelper.GetPropertyMetadata(x => x.Id)); - // assert - Assert.IsTrue(await _subject.IsValidAsync()); - } + // assert + Assert.IsTrue(await _subject.IsValidAsync()); + } - public class Entity : IEntity - { - public string Id { get; set; } + public class Entity : IEntity + { + public string Id { get; set; } - public int X { get; set; } - } + public int X { get; set; } + } - public class EntityValidator : BaseEntityValidator + public class EntityValidator : BaseEntityValidator + { + public override IEnumerable Validate(IValidatorContext context) { - public override IEnumerable Validate(IValidatorContext context) + if (!string.IsNullOrEmpty(context.Entity.Id)) + { + yield break; + } + else { - if (!string.IsNullOrEmpty(context.Entity.Id)) - { - yield break; - } - else - { - yield return new ValidationResult("Id is null", new[] { nameof(context.Entity.Id) }); - } + yield return new ValidationResult("Id is null", new[] { nameof(context.Entity.Id) }); } } } diff --git a/src/RapidCMS.Core.Tests/Forms/EditContextCustomValidationVariantsTests.cs b/src/RapidCMS.Core.Tests/Forms/EditContextCustomValidationVariantsTests.cs index 1fd047a1..7c3c9d97 100644 --- a/src/RapidCMS.Core.Tests/Forms/EditContextCustomValidationVariantsTests.cs +++ b/src/RapidCMS.Core.Tests/Forms/EditContextCustomValidationVariantsTests.cs @@ -12,244 +12,243 @@ using System.Linq; using System.Threading.Tasks; -namespace RapidCMS.Core.Tests.Forms +namespace RapidCMS.Core.Tests.Forms; + +public class EditContextCustomValidationVariantsTests { - public class EditContextCustomValidationVariantsTests + private FormEditContext _subject = default!; + private ServiceCollection _serviceCollection = new ServiceCollection(); + + [Test] + public async Task WhenInvalidEntityIsValidated_ThenIsValidShouldReturnFalseAsync() { - private FormEditContext _subject = default!; - private ServiceCollection _serviceCollection = new ServiceCollection(); + _serviceCollection.AddSingleton(); + _serviceCollection.AddSingleton(); + _serviceCollection.AddSingleton(); + + _subject = new FormEditContext( + "alias", + "repoAlias", + "variantAlias", + new Entity(), + default, + UsageType.Edit, + new List + { + new ValidationSetup(typeof(EntityValidator), default), + new ValidationSetup(typeof(EntityVariantAValidator), default), + new ValidationSetup(typeof(EntityVariantBValidator), default) + }, + _serviceCollection.BuildServiceProvider()); - [Test] - public async Task WhenInvalidEntityIsValidated_ThenIsValidShouldReturnFalseAsync() - { - _serviceCollection.AddSingleton(); - _serviceCollection.AddSingleton(); - _serviceCollection.AddSingleton(); - - _subject = new FormEditContext( - "alias", - "repoAlias", - "variantAlias", - new Entity(), - default, - UsageType.Edit, - new List - { - new ValidationSetup(typeof(EntityValidator), default), - new ValidationSetup(typeof(EntityVariantAValidator), default), - new ValidationSetup(typeof(EntityVariantBValidator), default) - }, - _serviceCollection.BuildServiceProvider()); - - _subject.NotifyPropertyIncludedInForm(PropertyMetadataHelper.GetPropertyMetadata(x => x.Id)); - - // assert - Assert.IsFalse(await _subject.IsValidAsync()); - Assert.AreEqual("Id is null", _subject.GetPropertyState("Id").GetValidationMessages().First()); - } + _subject.NotifyPropertyIncludedInForm(PropertyMetadataHelper.GetPropertyMetadata(x => x.Id)); - [Test] - public async Task WhenInvalidEntityVariantAIsValidated_ThenIsValidShouldReturnFalseAsync() - { - _serviceCollection.AddSingleton(); - _serviceCollection.AddSingleton(); - _serviceCollection.AddSingleton(); - - _subject = new FormEditContext( - "alias", - "repoAlias", - "variantAlias", - new EntityVariantA { Id = "A" }, - default, - UsageType.Edit, - new List - { - new ValidationSetup(typeof(EntityValidator), default), - new ValidationSetup(typeof(EntityVariantAValidator), default), - new ValidationSetup(typeof(EntityVariantBValidator), default) - }, - _serviceCollection.BuildServiceProvider()); - - _subject.NotifyPropertyIncludedInForm(PropertyMetadataHelper.GetPropertyMetadata(x => x.Id)); - - // assert - Assert.IsFalse(await _subject.IsValidAsync()); - Assert.AreEqual("Id of A-variant cannot be A", _subject.GetPropertyState("Id").GetValidationMessages().First()); - } + // assert + Assert.IsFalse(await _subject.IsValidAsync()); + Assert.AreEqual("Id is null", _subject.GetPropertyState("Id").GetValidationMessages().First()); + } - [Test] - public async Task WhenInvalidEntityVariantBIsValidated_ThenIsValidShouldReturnFalseAsync() - { - _serviceCollection.AddSingleton(); - _serviceCollection.AddSingleton(); - _serviceCollection.AddSingleton(); - - _subject = new FormEditContext( - "alias", - "repoAlias", - "variantAlias", - new EntityVariantB { Id = "B" }, - default, - UsageType.Edit, - new List - { - new ValidationSetup(typeof(EntityValidator), default), - new ValidationSetup(typeof(EntityVariantAValidator), default), - new ValidationSetup(typeof(EntityVariantBValidator), default) - }, - _serviceCollection.BuildServiceProvider()); - - _subject.NotifyPropertyIncludedInForm(PropertyMetadataHelper.GetPropertyMetadata(x => x.Id)); - - // assert - Assert.IsFalse(await _subject.IsValidAsync()); - Assert.AreEqual("Id of B-variant cannot be B", _subject.GetPropertyState("Id").GetValidationMessages().First()); - } + [Test] + public async Task WhenInvalidEntityVariantAIsValidated_ThenIsValidShouldReturnFalseAsync() + { + _serviceCollection.AddSingleton(); + _serviceCollection.AddSingleton(); + _serviceCollection.AddSingleton(); + + _subject = new FormEditContext( + "alias", + "repoAlias", + "variantAlias", + new EntityVariantA { Id = "A" }, + default, + UsageType.Edit, + new List + { + new ValidationSetup(typeof(EntityValidator), default), + new ValidationSetup(typeof(EntityVariantAValidator), default), + new ValidationSetup(typeof(EntityVariantBValidator), default) + }, + _serviceCollection.BuildServiceProvider()); - [Test] - public async Task WhenValidEntityIsValidated_ThenIsValidShouldReturnTrueAsync() - { - _serviceCollection.AddSingleton(); - _serviceCollection.AddSingleton(); - _serviceCollection.AddSingleton(); - - _subject = new FormEditContext( - "alias", - "repoAlias", - "variantAlias", - new Entity - { - Id = "valid" - }, - default, - UsageType.Edit, - new List - { - new ValidationSetup(typeof(EntityValidator), default), - new ValidationSetup(typeof(EntityVariantAValidator), default), - new ValidationSetup(typeof(EntityVariantBValidator), default) - }, - _serviceCollection.BuildServiceProvider()); - - _subject.NotifyPropertyIncludedInForm(PropertyMetadataHelper.GetPropertyMetadata(x => x.Id)); - - // assert - Assert.IsTrue(await _subject.IsValidAsync()); - } + _subject.NotifyPropertyIncludedInForm(PropertyMetadataHelper.GetPropertyMetadata(x => x.Id)); - [Test] - public async Task WhenValidEntityVariantAIsValidated_ThenIsValidShouldReturnTrueAsync() - { - _serviceCollection.AddSingleton(); - _serviceCollection.AddSingleton(); - _serviceCollection.AddSingleton(); - - _subject = new FormEditContext( - "alias", - "repoAlias", - "variantAlias", - new EntityVariantA { Id = "B" }, - default, - UsageType.Edit, - new List - { - new ValidationSetup(typeof(EntityValidator), default), - new ValidationSetup(typeof(EntityVariantAValidator), default), - new ValidationSetup(typeof(EntityVariantBValidator), default) - }, - _serviceCollection.BuildServiceProvider()); - - _subject.NotifyPropertyIncludedInForm(PropertyMetadataHelper.GetPropertyMetadata(x => x.Id)); - - // assert - Assert.IsTrue(await _subject.IsValidAsync()); - } + // assert + Assert.IsFalse(await _subject.IsValidAsync()); + Assert.AreEqual("Id of A-variant cannot be A", _subject.GetPropertyState("Id").GetValidationMessages().First()); + } - [Test] - public async Task WhenValidEntityVariantBIsValidated_ThenIsValidShouldReturnTrueAsync() - { - _serviceCollection.AddSingleton(); - _serviceCollection.AddSingleton(); - _serviceCollection.AddSingleton(); - - _subject = new FormEditContext( - "alias", - "repoAlias", - "variantAlias", - new EntityVariantB { Id = "A" }, - default, - UsageType.Edit, - new List - { - new ValidationSetup(typeof(EntityValidator), default), - new ValidationSetup(typeof(EntityVariantAValidator), default), - new ValidationSetup(typeof(EntityVariantBValidator), default) - }, - _serviceCollection.BuildServiceProvider()); - - _subject.NotifyPropertyIncludedInForm(PropertyMetadataHelper.GetPropertyMetadata(x => x.Id)); - - // assert - Assert.IsTrue(await _subject.IsValidAsync()); - } + [Test] + public async Task WhenInvalidEntityVariantBIsValidated_ThenIsValidShouldReturnFalseAsync() + { + _serviceCollection.AddSingleton(); + _serviceCollection.AddSingleton(); + _serviceCollection.AddSingleton(); + + _subject = new FormEditContext( + "alias", + "repoAlias", + "variantAlias", + new EntityVariantB { Id = "B" }, + default, + UsageType.Edit, + new List + { + new ValidationSetup(typeof(EntityValidator), default), + new ValidationSetup(typeof(EntityVariantAValidator), default), + new ValidationSetup(typeof(EntityVariantBValidator), default) + }, + _serviceCollection.BuildServiceProvider()); - public class Entity : IEntity - { - public string Id { get; set; } - } + _subject.NotifyPropertyIncludedInForm(PropertyMetadataHelper.GetPropertyMetadata(x => x.Id)); - public class EntityVariantA : Entity - { + // assert + Assert.IsFalse(await _subject.IsValidAsync()); + Assert.AreEqual("Id of B-variant cannot be B", _subject.GetPropertyState("Id").GetValidationMessages().First()); + } - } + [Test] + public async Task WhenValidEntityIsValidated_ThenIsValidShouldReturnTrueAsync() + { + _serviceCollection.AddSingleton(); + _serviceCollection.AddSingleton(); + _serviceCollection.AddSingleton(); + + _subject = new FormEditContext( + "alias", + "repoAlias", + "variantAlias", + new Entity + { + Id = "valid" + }, + default, + UsageType.Edit, + new List + { + new ValidationSetup(typeof(EntityValidator), default), + new ValidationSetup(typeof(EntityVariantAValidator), default), + new ValidationSetup(typeof(EntityVariantBValidator), default) + }, + _serviceCollection.BuildServiceProvider()); - public class EntityVariantB : Entity - { + _subject.NotifyPropertyIncludedInForm(PropertyMetadataHelper.GetPropertyMetadata(x => x.Id)); - } + // assert + Assert.IsTrue(await _subject.IsValidAsync()); + } + + [Test] + public async Task WhenValidEntityVariantAIsValidated_ThenIsValidShouldReturnTrueAsync() + { + _serviceCollection.AddSingleton(); + _serviceCollection.AddSingleton(); + _serviceCollection.AddSingleton(); + + _subject = new FormEditContext( + "alias", + "repoAlias", + "variantAlias", + new EntityVariantA { Id = "B" }, + default, + UsageType.Edit, + new List + { + new ValidationSetup(typeof(EntityValidator), default), + new ValidationSetup(typeof(EntityVariantAValidator), default), + new ValidationSetup(typeof(EntityVariantBValidator), default) + }, + _serviceCollection.BuildServiceProvider()); + + _subject.NotifyPropertyIncludedInForm(PropertyMetadataHelper.GetPropertyMetadata(x => x.Id)); + + // assert + Assert.IsTrue(await _subject.IsValidAsync()); + } + + [Test] + public async Task WhenValidEntityVariantBIsValidated_ThenIsValidShouldReturnTrueAsync() + { + _serviceCollection.AddSingleton(); + _serviceCollection.AddSingleton(); + _serviceCollection.AddSingleton(); + + _subject = new FormEditContext( + "alias", + "repoAlias", + "variantAlias", + new EntityVariantB { Id = "A" }, + default, + UsageType.Edit, + new List + { + new ValidationSetup(typeof(EntityValidator), default), + new ValidationSetup(typeof(EntityVariantAValidator), default), + new ValidationSetup(typeof(EntityVariantBValidator), default) + }, + _serviceCollection.BuildServiceProvider()); + + _subject.NotifyPropertyIncludedInForm(PropertyMetadataHelper.GetPropertyMetadata(x => x.Id)); - public class EntityValidator : BaseEntityValidator + // assert + Assert.IsTrue(await _subject.IsValidAsync()); + } + + public class Entity : IEntity + { + public string Id { get; set; } + } + + public class EntityVariantA : Entity + { + + } + + public class EntityVariantB : Entity + { + + } + + public class EntityValidator : BaseEntityValidator + { + public override IEnumerable Validate(IValidatorContext context) { - public override IEnumerable Validate(IValidatorContext context) + if (!string.IsNullOrEmpty(context.Entity.Id)) + { + yield break; + } + else { - if (!string.IsNullOrEmpty(context.Entity.Id)) - { - yield break; - } - else - { - yield return new ValidationResult("Id is null", new[] { nameof(context.Entity.Id) }); - } + yield return new ValidationResult("Id is null", new[] { nameof(context.Entity.Id) }); } } + } - public class EntityVariantAValidator : BaseEntityValidator + public class EntityVariantAValidator : BaseEntityValidator + { + public override IEnumerable Validate(IValidatorContext context) { - public override IEnumerable Validate(IValidatorContext context) + if (context.Entity.Id != "A") + { + yield break; + } + else { - if (context.Entity.Id != "A") - { - yield break; - } - else - { - yield return new ValidationResult("Id of A-variant cannot be A", new[] { nameof(context.Entity.Id) }); - } + yield return new ValidationResult("Id of A-variant cannot be A", new[] { nameof(context.Entity.Id) }); } } + } - public class EntityVariantBValidator : BaseEntityValidator + public class EntityVariantBValidator : BaseEntityValidator + { + public override IEnumerable Validate(IValidatorContext context) { - public override IEnumerable Validate(IValidatorContext context) + if (context.Entity.Id != "B") + { + yield break; + } + else { - if (context.Entity.Id != "B") - { - yield break; - } - else - { - yield return new ValidationResult("Id of B-variant cannot be B", new[] { nameof(context.Entity.Id) }); - } + yield return new ValidationResult("Id of B-variant cannot be B", new[] { nameof(context.Entity.Id) }); } } } diff --git a/src/RapidCMS.Core.Tests/Forms/EditContextTests.cs b/src/RapidCMS.Core.Tests/Forms/EditContextTests.cs index 5e351c29..23747b47 100644 --- a/src/RapidCMS.Core.Tests/Forms/EditContextTests.cs +++ b/src/RapidCMS.Core.Tests/Forms/EditContextTests.cs @@ -16,298 +16,297 @@ using System.Linq.Expressions; using System.Threading.Tasks; -namespace RapidCMS.Core.Tests.Forms +namespace RapidCMS.Core.Tests.Forms; + +public class EditContextTests { - public class EditContextTests + private FormEditContext _subject = default!; + private ServiceCollection _serviceCollection = new ServiceCollection(); + + [SetUp] + public void Setup() { - private FormEditContext _subject = default!; - private ServiceCollection _serviceCollection = new ServiceCollection(); + _serviceCollection.AddSingleton(); + + _subject = new FormEditContext( + "alias", + "repoAlias", + "variantAlias", + new Entity { Id = "1" }, + default, + UsageType.Edit, + new List { new ValidationSetup(typeof(DataAnnotationEntityValidator), default) }, + _serviceCollection.BuildServiceProvider()); + } - [SetUp] - public void Setup() - { - _serviceCollection.AddSingleton(); - - _subject = new FormEditContext( - "alias", - "repoAlias", - "variantAlias", - new Entity { Id = "1" }, - default, - UsageType.Edit, - new List { new ValidationSetup(typeof(DataAnnotationEntityValidator), default) }, - _serviceCollection.BuildServiceProvider()); - } + [Test] + public async Task WhenPropertyIsModifiedViaMetadata_ThenFieldEventIsTriggeredAsync() + { + // arrange + var called = false; + _subject.OnFieldChanged += (o, e) => called = true; - [Test] - public async Task WhenPropertyIsModifiedViaMetadata_ThenFieldEventIsTriggeredAsync() - { - // arrange - var called = false; - _subject.OnFieldChanged += (o, e) => called = true; + // act + await _subject.NotifyPropertyChangedAsync(_property); - // act - await _subject.NotifyPropertyChangedAsync(_property); + // assert + Assert.IsTrue(called); + } - // assert - Assert.IsTrue(called); - } + [Test] + public void WhenPropertyIsBusyViaMetadata_ThenValidationStateEventIsTriggered() + { + // arrange + var called = false; + _subject.OnValidationStateChanged += (o, e) => called = true; - [Test] - public void WhenPropertyIsBusyViaMetadata_ThenValidationStateEventIsTriggered() - { - // arrange - var called = false; - _subject.OnValidationStateChanged += (o, e) => called = true; + // act + _subject.NotifyPropertyBusy(_property); - // act - _subject.NotifyPropertyBusy(_property); + // assert + Assert.IsTrue(called); + } - // assert - Assert.IsTrue(called); - } + [Test] + public void WhenPropertyIsFinishedViaMetadata_ThenValidationStateEventIsTriggered() + { + // arrange + var called = false; + _subject.OnValidationStateChanged += (o, e) => called = true; - [Test] - public void WhenPropertyIsFinishedViaMetadata_ThenValidationStateEventIsTriggered() - { - // arrange - var called = false; - _subject.OnValidationStateChanged += (o, e) => called = true; + // act + _subject.NotifyPropertyFinished(_property); - // act - _subject.NotifyPropertyFinished(_property); + // assert + Assert.IsTrue(called); + } - // assert - Assert.IsTrue(called); - } + [Test] + public async Task WhenEntityIsInvalidButNotTouched_ThenEditContextIsValidAsync() + { + // arrange + _subject = new FormEditContext( + "alias", + "repoAlias", + "variantAlias", + new Entity { }, + default, + UsageType.Edit, + new List { new ValidationSetup(typeof(DataAnnotationEntityValidator), default) }, + _serviceCollection.BuildServiceProvider()); + + // act & assert + Assert.IsTrue(await _subject.IsValidAsync()); + } - [Test] - public async Task WhenEntityIsInvalidButNotTouched_ThenEditContextIsValidAsync() - { - // arrange - _subject = new FormEditContext( - "alias", - "repoAlias", - "variantAlias", - new Entity { }, - default, - UsageType.Edit, - new List { new ValidationSetup(typeof(DataAnnotationEntityValidator), default) }, - _serviceCollection.BuildServiceProvider()); - - // act & assert - Assert.IsTrue(await _subject.IsValidAsync()); - } + [Test] + public async Task WhenEntityIsInvalidButTouched_ThenEditContextIsInvalidAsync() + { + // arrange + _subject = new FormEditContext( + "alias", + "repoAlias", + "variantAlias", + new Entity { }, + default, + UsageType.Edit, + new List { new ValidationSetup(typeof(DataAnnotationEntityValidator), default) }, + _serviceCollection.BuildServiceProvider()); + _subject.NotifyPropertyIncludedInForm(_property); + + // act & assert + Assert.IsFalse(await _subject.IsValidAsync()); + } - [Test] - public async Task WhenEntityIsInvalidButTouched_ThenEditContextIsInvalidAsync() - { - // arrange - _subject = new FormEditContext( - "alias", - "repoAlias", - "variantAlias", - new Entity { }, - default, - UsageType.Edit, - new List { new ValidationSetup(typeof(DataAnnotationEntityValidator), default) }, - _serviceCollection.BuildServiceProvider()); - _subject.NotifyPropertyIncludedInForm(_property); - - // act & assert - Assert.IsFalse(await _subject.IsValidAsync()); - } + [Test] + public async Task WhenEntityIsValidAndTouched_ThenEditContextIsValidAsync() + { + // arrange + _subject = new FormEditContext( + "alias", + "repoAlias", + "variantAlias", + new Entity { Id = "123" }, + default, + UsageType.Edit, + new List { new ValidationSetup(typeof(DataAnnotationEntityValidator), default) }, + _serviceCollection.BuildServiceProvider()); + + await _subject.NotifyPropertyChangedAsync(_property); + + // act & assert + Assert.IsTrue(await _subject.IsValidAsync()); + } - [Test] - public async Task WhenEntityIsValidAndTouched_ThenEditContextIsValidAsync() - { - // arrange - _subject = new FormEditContext( - "alias", - "repoAlias", - "variantAlias", - new Entity { Id = "123" }, - default, - UsageType.Edit, - new List { new ValidationSetup(typeof(DataAnnotationEntityValidator), default) }, - _serviceCollection.BuildServiceProvider()); - - await _subject.NotifyPropertyChangedAsync(_property); - - // act & assert - Assert.IsTrue(await _subject.IsValidAsync()); - } + [Test] + public void WhenPropertyIsInvalidButNotTouched_ThenEditContextIsValid() + { + // arrange + _subject = new FormEditContext( + "alias", + "repoAlias", + "variantAlias", + new Entity { }, + default, + UsageType.Edit, + new List { new ValidationSetup(typeof(DataAnnotationEntityValidator), default) }, + _serviceCollection.BuildServiceProvider()); + + // act & assert + Assert.IsTrue(_subject.IsValid(_property)); + } - [Test] - public void WhenPropertyIsInvalidButNotTouched_ThenEditContextIsValid() - { - // arrange - _subject = new FormEditContext( - "alias", - "repoAlias", - "variantAlias", - new Entity { }, - default, - UsageType.Edit, - new List { new ValidationSetup(typeof(DataAnnotationEntityValidator), default) }, - _serviceCollection.BuildServiceProvider()); - - // act & assert - Assert.IsTrue(_subject.IsValid(_property)); - } + [Test] + public async Task WhenPropertyIsInvalidButTouched_ThenEditContextIsInvalidAsync() + { + // arrange + _subject = new FormEditContext( + "alias", + "repoAlias", + "variantAlias", + new Entity { }, + default, + UsageType.Edit, + new List { new ValidationSetup(typeof(DataAnnotationEntityValidator), default) }, + _serviceCollection.BuildServiceProvider()); + + await _subject.NotifyPropertyChangedAsync(_property); + + // act & assert + Assert.IsFalse(_subject.IsValid(_property)); + } - [Test] - public async Task WhenPropertyIsInvalidButTouched_ThenEditContextIsInvalidAsync() - { - // arrange - _subject = new FormEditContext( - "alias", - "repoAlias", - "variantAlias", - new Entity { }, - default, - UsageType.Edit, - new List { new ValidationSetup(typeof(DataAnnotationEntityValidator), default) }, - _serviceCollection.BuildServiceProvider()); - - await _subject.NotifyPropertyChangedAsync(_property); - - // act & assert - Assert.IsFalse(_subject.IsValid(_property)); - } + [Test] + public void WhenPropertyIsValidAndTouched_ThenEditContextIsValid() + { + // arrange + _subject = new FormEditContext( + "alias", + "repoAlias", + "variantAlias", + new Entity { Id = "123" }, + default, + UsageType.Edit, + new List { new ValidationSetup(typeof(DataAnnotationEntityValidator), default) }, + _serviceCollection.BuildServiceProvider()); + _subject.NotifyPropertyIncludedInForm(_property); + + // act & assert + Assert.IsTrue(_subject.IsValid(_property)); + } - [Test] - public void WhenPropertyIsValidAndTouched_ThenEditContextIsValid() - { - // arrange - _subject = new FormEditContext( - "alias", - "repoAlias", - "variantAlias", - new Entity { Id = "123" }, - default, - UsageType.Edit, - new List { new ValidationSetup(typeof(DataAnnotationEntityValidator), default) }, - _serviceCollection.BuildServiceProvider()); - _subject.NotifyPropertyIncludedInForm(_property); - - // act & assert - Assert.IsTrue(_subject.IsValid(_property)); - } + [Test] + public void WhenEntityIsNotTouched_ThenEditContextIsNotModified() + { + // act & assert + Assert.IsFalse(_subject.IsModified()); + } - [Test] - public void WhenEntityIsNotTouched_ThenEditContextIsNotModified() - { - // act & assert - Assert.IsFalse(_subject.IsModified()); - } + [Test] + public async Task WhenEntityIsTouched_ThenEditContextIsModifiedAsync() + { + // arrange + await _subject.NotifyPropertyChangedAsync(_property); - [Test] - public async Task WhenEntityIsTouched_ThenEditContextIsModifiedAsync() - { - // arrange - await _subject.NotifyPropertyChangedAsync(_property); + // act & assert + Assert.IsTrue(_subject.IsModified()); + } - // act & assert - Assert.IsTrue(_subject.IsModified()); - } + [Test] + public void WhenPropertyIsNotTouched_ThenPropertyIsNotValidated() + { + // act & assert + Assert.IsFalse(_subject.WasValidated(_property)); + } - [Test] - public void WhenPropertyIsNotTouched_ThenPropertyIsNotValidated() - { - // act & assert - Assert.IsFalse(_subject.WasValidated(_property)); - } + [Test] + public async Task WhenPropertyIsTouched_ThenPropertyIsValidatedAsync() + { + // arrange + await _subject.NotifyPropertyChangedAsync(_property); - [Test] - public async Task WhenPropertyIsTouched_ThenPropertyIsValidatedAsync() - { - // arrange - await _subject.NotifyPropertyChangedAsync(_property); + // act & assert + Assert.IsTrue(_subject.WasValidated(_property)); + } - // act & assert - Assert.IsTrue(_subject.WasValidated(_property)); - } + [Test] + public void WhenValidationMessageIsAddedToProperty_ThenPropertyIsInvalid() + { + // act + _subject.AddValidationMessage(_property, "Error"); - [Test] - public void WhenValidationMessageIsAddedToProperty_ThenPropertyIsInvalid() - { - // act - _subject.AddValidationMessage(_property, "Error"); + // assert + Assert.IsTrue(_subject.WasValidated(_property)); + Assert.IsFalse(_subject.IsValid(_property)); + } - // assert - Assert.IsTrue(_subject.WasValidated(_property)); - Assert.IsFalse(_subject.IsValid(_property)); - } + [Test] + public void WhenValidationMessageIsAddedToProperty_ThenPropertyHasValidationMessage() + { + // act + _subject.AddValidationMessage(_property, "Error"); - [Test] - public void WhenValidationMessageIsAddedToProperty_ThenPropertyHasValidationMessage() - { - // act - _subject.AddValidationMessage(_property, "Error"); + // assert + Assert.AreEqual("Error", _subject.GetValidationMessages(_property).First()); + } - // assert - Assert.AreEqual("Error", _subject.GetValidationMessages(_property).First()); - } + [Test] + public async Task WhenNestedPropertyIsTouched_ThenPropertyIsValidatedAsync() + { + // act + await _subject.NotifyPropertyChangedAsync(_nestedProperty); - [Test] - public async Task WhenNestedPropertyIsTouched_ThenPropertyIsValidatedAsync() - { - // act - await _subject.NotifyPropertyChangedAsync(_nestedProperty); + // assert + Assert.IsTrue(_subject.WasValidated(_nestedProperty)); + Assert.IsFalse(_subject.IsValid(_nestedProperty)); + } - // assert - Assert.IsTrue(_subject.WasValidated(_nestedProperty)); - Assert.IsFalse(_subject.IsValid(_nestedProperty)); - } + [Test] + public async Task WhenNestedPropertyIsTouchedAndValid_ThenPropertyIsValidatedAndValidAsync() + { + // arrange + _subject = new FormEditContext( + "alias", + "repoAlias", + "variantAlias", + new Entity { Id = "123", Nested = new Entity.NestedObject { Data = "456" } }, + default, + UsageType.Edit, + new List { new ValidationSetup(typeof(DataAnnotationEntityValidator), default) }, + _serviceCollection.BuildServiceProvider()); + + // act + await _subject.NotifyPropertyChangedAsync(_nestedProperty); + + // assert + Assert.IsTrue(_subject.WasValidated(_nestedProperty)); + Assert.IsTrue(_subject.IsValid(_nestedProperty)); + } - [Test] - public async Task WhenNestedPropertyIsTouchedAndValid_ThenPropertyIsValidatedAndValidAsync() - { - // arrange - _subject = new FormEditContext( - "alias", - "repoAlias", - "variantAlias", - new Entity { Id = "123", Nested = new Entity.NestedObject { Data = "456" } }, - default, - UsageType.Edit, - new List { new ValidationSetup(typeof(DataAnnotationEntityValidator), default) }, - _serviceCollection.BuildServiceProvider()); - - // act - await _subject.NotifyPropertyChangedAsync(_nestedProperty); - - // assert - Assert.IsTrue(_subject.WasValidated(_nestedProperty)); - Assert.IsTrue(_subject.IsValid(_nestedProperty)); - } + [Test] + public void WhenNestedPropertyIsNotTouched_ThenPropertyIsNotValidated() + { + // assert + Assert.IsFalse(_subject.WasValidated(_nestedProperty)); + Assert.IsTrue(_subject.IsValid(_nestedProperty)); + } - [Test] - public void WhenNestedPropertyIsNotTouched_ThenPropertyIsNotValidated() - { - // assert - Assert.IsFalse(_subject.WasValidated(_nestedProperty)); - Assert.IsTrue(_subject.IsValid(_nestedProperty)); - } + private readonly Expression> _getId = x => x.Id; + private readonly Expression> _getNestedData = x => x.Nested.Data; + private IPropertyMetadata _property => PropertyMetadataHelper.GetPropertyMetadata(_getId)!; + private IPropertyMetadata _nestedProperty => PropertyMetadataHelper.GetPropertyMetadata(_getNestedData)!; + public class Entity : IEntity + { + [Required] + public string Id { get; set; } + + [ValidateObject] + public NestedObject Nested { get; set; } = new NestedObject(); - private readonly Expression> _getId = x => x.Id; - private readonly Expression> _getNestedData = x => x.Nested.Data; - private IPropertyMetadata _property => PropertyMetadataHelper.GetPropertyMetadata(_getId)!; - private IPropertyMetadata _nestedProperty => PropertyMetadataHelper.GetPropertyMetadata(_getNestedData)!; - public class Entity : IEntity + public class NestedObject { [Required] - public string Id { get; set; } - - [ValidateObject] - public NestedObject Nested { get; set; } = new NestedObject(); - - public class NestedObject - { - [Required] - public string Data { get; set; } - } + public string Data { get; set; } } } } diff --git a/src/RapidCMS.Core.Tests/Interactions/ButtonInteractionButtonTests.cs b/src/RapidCMS.Core.Tests/Interactions/ButtonInteractionButtonTests.cs index cf75e623..ad5158e9 100644 --- a/src/RapidCMS.Core.Tests/Interactions/ButtonInteractionButtonTests.cs +++ b/src/RapidCMS.Core.Tests/Interactions/ButtonInteractionButtonTests.cs @@ -12,127 +12,126 @@ using System; using System.Collections.Generic; -namespace RapidCMS.Core.Tests.Interactions +namespace RapidCMS.Core.Tests.Interactions; + +public class ButtonInteractionButtonTests { - public class ButtonInteractionButtonTests - { - private IButtonInteraction _subject = default!; + private IButtonInteraction _subject = default!; - private Mock> _collectionResolver = default!; - private Mock _buttonActionHandlerResolver = default!; - private Mock _authService = default!; - private Mock _serviceProvider = default!; + private Mock> _collectionResolver = default!; + private Mock _buttonActionHandlerResolver = default!; + private Mock _authService = default!; + private Mock _serviceProvider = default!; - private CollectionSetup _collection = default!; + private CollectionSetup _collection = default!; - [SetUp] - public void Setup() + [SetUp] + public void Setup() + { + _collection = new CollectionSetup("icon", "color", "name", "alias", "repo") { - _collection = new CollectionSetup("icon", "color", "name", "alias", "repo") - { - ListEditor = new ListSetup( - null, - null, - null, - ListType.Table, - EmptyVariantColumnVisibility.Visible, - new List(), - new List + ListEditor = new ListSetup( + null, + null, + null, + ListType.Table, + EmptyVariantColumnVisibility.Visible, + new List(), + new List + { + new ButtonSetup { - new ButtonSetup - { - ButtonId = "abc", - Buttons = new List() - }, - new ButtonSetup - { - ButtonId = "def", - Buttons = new List() - } - }) - }; - - _collectionResolver = new Mock>(); - _collectionResolver - .Setup(x => x.ResolveSetupAsync(It.IsAny())) - .ReturnsAsync(_collection); - - _buttonActionHandlerResolver = new Mock(); - - _authService = new Mock(); - _serviceProvider = new Mock(); - - _subject = new ButtonInteraction(_collectionResolver.Object, _buttonActionHandlerResolver.Object, _authService.Object); - } - - [TestCase("abc")] - [TestCase("def")] - public void WhenUsedEditorButtonCanBeFound_ThenAuthServiceShouldBeConsulted(string buttonId) + ButtonId = "abc", + Buttons = new List() + }, + new ButtonSetup + { + ButtonId = "def", + Buttons = new List() + } + }) + }; + + _collectionResolver = new Mock>(); + _collectionResolver + .Setup(x => x.ResolveSetupAsync(It.IsAny())) + .ReturnsAsync(_collection); + + _buttonActionHandlerResolver = new Mock(); + + _authService = new Mock(); + _serviceProvider = new Mock(); + + _subject = new ButtonInteraction(_collectionResolver.Object, _buttonActionHandlerResolver.Object, _authService.Object); + } + + [TestCase("abc")] + [TestCase("def")] + public void WhenUsedEditorButtonCanBeFound_ThenAuthServiceShouldBeConsulted(string buttonId) + { + // arrange + var editContext = new FormEditContext("alias", "repo", "entity", new DefaultEntityVariant(), default, UsageType.Edit, new List(), _serviceProvider.Object); + var request = new PersistEntityRequestModel() { - // arrange - var editContext = new FormEditContext("alias", "repo", "entity", new DefaultEntityVariant(), default, UsageType.Edit, new List(), _serviceProvider.Object); - var request = new PersistEntityRequestModel() - { - ActionId = buttonId, - EditContext = editContext - }; - - // act - _subject.ValidateButtonInteractionAsync(request); - - // assert - _authService.Verify(x => x.EnsureAuthorizedUserAsync(It.Is(x => x == editContext), It.Is(x => x.ButtonId == buttonId))); - } - - [TestCase("abc")] - [TestCase("def")] - public void WhenUsedEditorInListButtonCanBeFound_ThenAuthServiceShouldBeConsulted(string buttonId) + ActionId = buttonId, + EditContext = editContext + }; + + // act + _subject.ValidateButtonInteractionAsync(request); + + // assert + _authService.Verify(x => x.EnsureAuthorizedUserAsync(It.Is(x => x == editContext), It.Is(x => x.ButtonId == buttonId))); + } + + [TestCase("abc")] + [TestCase("def")] + public void WhenUsedEditorInListButtonCanBeFound_ThenAuthServiceShouldBeConsulted(string buttonId) + { + // arrange + var editContext = new FormEditContext("alias", "repo", "entity", new DefaultEntityVariant(), default, UsageType.Edit, new List(), _serviceProvider.Object); + var request = new PersistEntityCollectionRequestModel() { - // arrange - var editContext = new FormEditContext("alias", "repo", "entity", new DefaultEntityVariant(), default, UsageType.Edit, new List(), _serviceProvider.Object); - var request = new PersistEntityCollectionRequestModel() - { - ActionId = buttonId, - EditContext = editContext, - ListContext = new ListContext( - "alias", - new FormEditContext("alias", "repo", "entity", new DefaultEntityVariant(), default, UsageType.Edit, new List(), _serviceProvider.Object), - default, - UsageType.Edit, - default, - _serviceProvider.Object) - }; - - // act - _subject.ValidateButtonInteractionAsync(request); - - // assert - _authService.Verify(x => x.EnsureAuthorizedUserAsync(It.Is(x => x == editContext), It.Is(x => x.ButtonId == buttonId))); - } - - [TestCase("abc")] - [TestCase("def")] - public void WhenUsedListButtonCanBeFound_ThenAuthServiceShouldBeConsulted(string buttonId) + ActionId = buttonId, + EditContext = editContext, + ListContext = new ListContext( + "alias", + new FormEditContext("alias", "repo", "entity", new DefaultEntityVariant(), default, UsageType.Edit, new List(), _serviceProvider.Object), + default, + UsageType.Edit, + default, + _serviceProvider.Object) + }; + + // act + _subject.ValidateButtonInteractionAsync(request); + + // assert + _authService.Verify(x => x.EnsureAuthorizedUserAsync(It.Is(x => x == editContext), It.Is(x => x.ButtonId == buttonId))); + } + + [TestCase("abc")] + [TestCase("def")] + public void WhenUsedListButtonCanBeFound_ThenAuthServiceShouldBeConsulted(string buttonId) + { + // arrange + var editContext = new FormEditContext("alias", "repo", "entity", new DefaultEntityVariant(), default, UsageType.Edit, new List(), _serviceProvider.Object); + var request = new PersistEntitiesRequestModel() { - // arrange - var editContext = new FormEditContext("alias", "repo", "entity", new DefaultEntityVariant(), default, UsageType.Edit, new List(), _serviceProvider.Object); - var request = new PersistEntitiesRequestModel() - { - ActionId = buttonId, - ListContext = new ListContext( - "alias", - editContext, - default, - UsageType.Edit, - default, - _serviceProvider.Object) - }; - - // act - _subject.ValidateButtonInteractionAsync(request); - - // assert - _authService.Verify(x => x.EnsureAuthorizedUserAsync(It.Is(x => x == editContext), It.Is(x => x.ButtonId == buttonId))); - } + ActionId = buttonId, + ListContext = new ListContext( + "alias", + editContext, + default, + UsageType.Edit, + default, + _serviceProvider.Object) + }; + + // act + _subject.ValidateButtonInteractionAsync(request); + + // assert + _authService.Verify(x => x.EnsureAuthorizedUserAsync(It.Is(x => x == editContext), It.Is(x => x.ButtonId == buttonId))); } } diff --git a/src/RapidCMS.Core.Tests/Interactions/ButtonInteractionCollectionTests.cs b/src/RapidCMS.Core.Tests/Interactions/ButtonInteractionCollectionTests.cs index 3307a25c..d3dbaecc 100644 --- a/src/RapidCMS.Core.Tests/Interactions/ButtonInteractionCollectionTests.cs +++ b/src/RapidCMS.Core.Tests/Interactions/ButtonInteractionCollectionTests.cs @@ -12,137 +12,136 @@ using System; using System.Collections.Generic; -namespace RapidCMS.Core.Tests.Interactions -{ - public class ButtonInteractionCollectionTests - { - private IButtonInteraction _subject = default!; +namespace RapidCMS.Core.Tests.Interactions; - private Mock> _collectionResolver = default!; - private Mock _buttonActionHandlerResolver = default!; - private Mock _authService = default!; - private Mock _serviceProvider = default!; - - [SetUp] - public void Setup() - { - _collectionResolver = new Mock>(); - _collectionResolver - .Setup(x => x.ResolveSetupAsync(It.IsAny())) - .ReturnsAsync((string alias) => - new CollectionSetup(default, - default, - "name", - alias, - default) - { - EntityVariant = new EntityVariantSetup("default", default, typeof(DefaultEntityVariant), "alias") - }); - - _buttonActionHandlerResolver = new Mock(); - - _authService = new Mock(); - _serviceProvider = new Mock(); - - _subject = new ButtonInteraction(_collectionResolver.Object, _buttonActionHandlerResolver.Object, _authService.Object); - } - - [Test] - public void WhenValidationOfEditorButtonIsRequested_ThenCorrespondingCollectionShouldBeFetched() - { - // arrange - var request = new PersistEntityRequestModel() - { - EditContext = new FormEditContext("alias", "repo", "entity", new DefaultEntityVariant(), default, UsageType.Edit, new List(), _serviceProvider.Object) - }; +public class ButtonInteractionCollectionTests +{ + private IButtonInteraction _subject = default!; - // act - _subject.ValidateButtonInteractionAsync(request); + private Mock> _collectionResolver = default!; + private Mock _buttonActionHandlerResolver = default!; + private Mock _authService = default!; + private Mock _serviceProvider = default!; - // assert - _collectionResolver.Verify(x => x.ResolveSetupAsync(It.Is(x => x == "alias")), Times.Once()); - } + [SetUp] + public void Setup() + { + _collectionResolver = new Mock>(); + _collectionResolver + .Setup(x => x.ResolveSetupAsync(It.IsAny())) + .ReturnsAsync((string alias) => + new CollectionSetup(default, + default, + "name", + alias, + default) + { + EntityVariant = new EntityVariantSetup("default", default, typeof(DefaultEntityVariant), "alias") + }); - [Test] - public void WhenInteractionCompletionOfEditorButtonIsRequested_ThenCorrespondingCollectionShouldBeFetched() - { - // arrange - var request = new PersistEntityRequestModel() - { - EditContext = new FormEditContext("alias", "repo", "entity", new DefaultEntityVariant(), default, UsageType.Edit, new List(), _serviceProvider.Object) - }; + _buttonActionHandlerResolver = new Mock(); - // act - _subject.CompleteButtonInteractionAsync(request); + _authService = new Mock(); + _serviceProvider = new Mock(); - // assert - _collectionResolver.Verify(x => x.ResolveSetupAsync(It.Is(x => x == "alias")), Times.Once()); - } + _subject = new ButtonInteraction(_collectionResolver.Object, _buttonActionHandlerResolver.Object, _authService.Object); + } - [Test] - public void WhenValidationOfEditorInListButtonIsRequested_ThenCorrespondingCollectionShouldBeFetched() + [Test] + public void WhenValidationOfEditorButtonIsRequested_ThenCorrespondingCollectionShouldBeFetched() + { + // arrange + var request = new PersistEntityRequestModel() { - // arrange - var request = new PersistEntityCollectionRequestModel() - { - ListContext = new ListContext( - "alias", - new FormEditContext("alias", "repo", "entity", new DefaultEntityVariant(), default, UsageType.Edit, new List(), _serviceProvider.Object), - default, - UsageType.Edit, - default, - _serviceProvider.Object) - }; + EditContext = new FormEditContext("alias", "repo", "entity", new DefaultEntityVariant(), default, UsageType.Edit, new List(), _serviceProvider.Object) + }; - // act - _subject.ValidateButtonInteractionAsync(request); + // act + _subject.ValidateButtonInteractionAsync(request); - // assert - _collectionResolver.Verify(x => x.ResolveSetupAsync(It.Is(x => x == "alias")), Times.Once()); - } + // assert + _collectionResolver.Verify(x => x.ResolveSetupAsync(It.Is(x => x == "alias")), Times.Once()); + } - [Test] - public void WhenValidationOfListButtonIsRequested_ThenCorrespondingCollectionShouldBeFetched() + [Test] + public void WhenInteractionCompletionOfEditorButtonIsRequested_ThenCorrespondingCollectionShouldBeFetched() + { + // arrange + var request = new PersistEntityRequestModel() { - // arrange - var request = new PersistEntitiesRequestModel() - { - ListContext = new ListContext( - "alias", - new FormEditContext("alias", "repo", "entity", new DefaultEntityVariant(), default, UsageType.Edit, new List(), _serviceProvider.Object), - default, - UsageType.Edit, - default, - _serviceProvider.Object) - }; + EditContext = new FormEditContext("alias", "repo", "entity", new DefaultEntityVariant(), default, UsageType.Edit, new List(), _serviceProvider.Object) + }; - // act - _subject.ValidateButtonInteractionAsync(request); + // act + _subject.CompleteButtonInteractionAsync(request); - // assert - _collectionResolver.Verify(x => x.ResolveSetupAsync(It.Is(x => x == "alias")), Times.Once()); - } + // assert + _collectionResolver.Verify(x => x.ResolveSetupAsync(It.Is(x => x == "alias")), Times.Once()); + } - [Test] - public void WhenInteractionCompletionOfListButtonIsRequested_ThenCorrespondingCollectionShouldBeFetched() + [Test] + public void WhenValidationOfEditorInListButtonIsRequested_ThenCorrespondingCollectionShouldBeFetched() + { + // arrange + var request = new PersistEntityCollectionRequestModel() { - // arrange - var request = new PersistEntitiesRequestModel() - { - ListContext = new ListContext( - "alias", - new FormEditContext("alias", "repo", "entity", new DefaultEntityVariant(), default, UsageType.Edit, new List(), _serviceProvider.Object), - default, - UsageType.Edit, - default, - _serviceProvider.Object) - }; + ListContext = new ListContext( + "alias", + new FormEditContext("alias", "repo", "entity", new DefaultEntityVariant(), default, UsageType.Edit, new List(), _serviceProvider.Object), + default, + UsageType.Edit, + default, + _serviceProvider.Object) + }; + + // act + _subject.ValidateButtonInteractionAsync(request); + + // assert + _collectionResolver.Verify(x => x.ResolveSetupAsync(It.Is(x => x == "alias")), Times.Once()); + } - // act - _subject.CompleteButtonInteractionAsync(request); + [Test] + public void WhenValidationOfListButtonIsRequested_ThenCorrespondingCollectionShouldBeFetched() + { + // arrange + var request = new PersistEntitiesRequestModel() + { + ListContext = new ListContext( + "alias", + new FormEditContext("alias", "repo", "entity", new DefaultEntityVariant(), default, UsageType.Edit, new List(), _serviceProvider.Object), + default, + UsageType.Edit, + default, + _serviceProvider.Object) + }; + + // act + _subject.ValidateButtonInteractionAsync(request); + + // assert + _collectionResolver.Verify(x => x.ResolveSetupAsync(It.Is(x => x == "alias")), Times.Once()); + } - // assert - _collectionResolver.Verify(x => x.ResolveSetupAsync(It.Is(x => x == "alias")), Times.Once()); - } + [Test] + public void WhenInteractionCompletionOfListButtonIsRequested_ThenCorrespondingCollectionShouldBeFetched() + { + // arrange + var request = new PersistEntitiesRequestModel() + { + ListContext = new ListContext( + "alias", + new FormEditContext("alias", "repo", "entity", new DefaultEntityVariant(), default, UsageType.Edit, new List(), _serviceProvider.Object), + default, + UsageType.Edit, + default, + _serviceProvider.Object) + }; + + // act + _subject.CompleteButtonInteractionAsync(request); + + // assert + _collectionResolver.Verify(x => x.ResolveSetupAsync(It.Is(x => x == "alias")), Times.Once()); } } diff --git a/src/RapidCMS.Core.Tests/Interactions/ButtonInteractionHandlerTests.cs b/src/RapidCMS.Core.Tests/Interactions/ButtonInteractionHandlerTests.cs index 0121b10d..a5c1e9a2 100644 --- a/src/RapidCMS.Core.Tests/Interactions/ButtonInteractionHandlerTests.cs +++ b/src/RapidCMS.Core.Tests/Interactions/ButtonInteractionHandlerTests.cs @@ -18,251 +18,250 @@ using System.Collections.Generic; using System.Linq.Expressions; -namespace RapidCMS.Core.Tests.Interactions +namespace RapidCMS.Core.Tests.Interactions; + +public class ButtonInteractionHandlerTests { - public class ButtonInteractionHandlerTests + private IButtonInteraction _subject = default!; + + private Mock> _collectionResolver = default!; + private Mock _buttonActionHandler = default!; + private Mock _buttonActionHandlerResolver = default!; + private Mock _authService = default!; + private ButtonSetup _button = default!; + private CollectionSetup _collection = default!; + private IServiceProvider _serviceProvider = default!; + + [SetUp] + public void Setup() { - private IButtonInteraction _subject = default!; - - private Mock> _collectionResolver = default!; - private Mock _buttonActionHandler = default!; - private Mock _buttonActionHandlerResolver = default!; - private Mock _authService = default!; - private ButtonSetup _button = default!; - private CollectionSetup _collection = default!; - private IServiceProvider _serviceProvider = default!; - - [SetUp] - public void Setup() + _button = new ButtonSetup + { + ButtonId = "123", + Buttons = new List() + }; + + _collection = new CollectionSetup("icon", "color", "name", "alias", "repo") { - _button = new ButtonSetup - { - ButtonId = "123", - Buttons = new List() - }; - - _collection = new CollectionSetup("icon", "color", "name", "alias", "repo") - { - ListEditor = new ListSetup( - null, - null, - null, - ListType.Table, - EmptyVariantColumnVisibility.Visible, - new List(), - new List - { - _button - }) - }; - - _collectionResolver = new Mock>(); - _collectionResolver - .Setup(x => x.ResolveSetupAsync(It.IsAny())) - .ReturnsAsync(_collection); - - _buttonActionHandler = new Mock(); - _buttonActionHandlerResolver = new Mock(); - _buttonActionHandlerResolver - .Setup(x => x.GetButtonActionHandler(It.IsAny())) - .Returns(_buttonActionHandler.Object); - - _authService = new Mock(); - _serviceProvider = new ServiceCollection().AddTransient().BuildServiceProvider(); - - _subject = new ButtonInteraction(_collectionResolver.Object, _buttonActionHandlerResolver.Object, _authService.Object); - } - - [TestCase(true)] - [TestCase(false)] - public void WhenValidationOfEditorButtonIsRequested_ThenValidityOfEditContextIsTested(bool requiresTesting) + ListEditor = new ListSetup( + null, + null, + null, + ListType.Table, + EmptyVariantColumnVisibility.Visible, + new List(), + new List + { + _button + }) + }; + + _collectionResolver = new Mock>(); + _collectionResolver + .Setup(x => x.ResolveSetupAsync(It.IsAny())) + .ReturnsAsync(_collection); + + _buttonActionHandler = new Mock(); + _buttonActionHandlerResolver = new Mock(); + _buttonActionHandlerResolver + .Setup(x => x.GetButtonActionHandler(It.IsAny())) + .Returns(_buttonActionHandler.Object); + + _authService = new Mock(); + _serviceProvider = new ServiceCollection().AddTransient().BuildServiceProvider(); + + _subject = new ButtonInteraction(_collectionResolver.Object, _buttonActionHandlerResolver.Object, _authService.Object); + } + + [TestCase(true)] + [TestCase(false)] + public void WhenValidationOfEditorButtonIsRequested_ThenValidityOfEditContextIsTested(bool requiresTesting) + { + // arrange + _buttonActionHandler.Setup(x => x.RequiresValidForm(It.IsAny(), It.IsAny())).Returns(requiresTesting); + var editContext = new FormEditContext("alias", "repo", "entity", new ValidEntity(), default, UsageType.Edit, new List { new ValidationSetup(typeof(DataAnnotationEntityValidator), default) }, _serviceProvider); + Expression> property = x => x.Name; + editContext.NotifyPropertyIncludedInForm(PropertyMetadataHelper.GetPropertyMetadata(property)!); + var request = new PersistEntityRequestModel() { - // arrange - _buttonActionHandler.Setup(x => x.RequiresValidForm(It.IsAny(), It.IsAny())).Returns(requiresTesting); - var editContext = new FormEditContext("alias", "repo", "entity", new ValidEntity(), default, UsageType.Edit, new List { new ValidationSetup(typeof(DataAnnotationEntityValidator), default) }, _serviceProvider); - Expression> property = x => x.Name; - editContext.NotifyPropertyIncludedInForm(PropertyMetadataHelper.GetPropertyMetadata(property)!); - var request = new PersistEntityRequestModel() - { - ActionId = "123", - EditContext = editContext - }; - - // act - _subject.ValidateButtonInteractionAsync(request); - - // assert - _buttonActionHandler.Verify(x => x.RequiresValidForm(It.IsAny(), It.IsAny()), Times.Once()); - Assert.AreEqual(requiresTesting, editContext.WasValidated(PropertyMetadataHelper.GetPropertyMetadata(property)!)); - } - - [Test] - public void WhenValidationOfEditorButtonIsRequested_ThenExceptionIsThrownIfFormIsInvalid() + ActionId = "123", + EditContext = editContext + }; + + // act + _subject.ValidateButtonInteractionAsync(request); + + // assert + _buttonActionHandler.Verify(x => x.RequiresValidForm(It.IsAny(), It.IsAny()), Times.Once()); + Assert.AreEqual(requiresTesting, editContext.WasValidated(PropertyMetadataHelper.GetPropertyMetadata(property)!)); + } + + [Test] + public void WhenValidationOfEditorButtonIsRequested_ThenExceptionIsThrownIfFormIsInvalid() + { + // arrange + _buttonActionHandler.Setup(x => x.RequiresValidForm(It.IsAny(), It.IsAny())).Returns(true); + var editContext = new FormEditContext("alias", "repo", "entity", new InvalidEntity(), default, UsageType.Edit, new List { new ValidationSetup(typeof(DataAnnotationEntityValidator), default) }, _serviceProvider); + Expression> property = x => x.Name; + editContext.NotifyPropertyIncludedInForm(PropertyMetadataHelper.GetPropertyMetadata(property)!); + var request = new PersistEntityRequestModel() { - // arrange - _buttonActionHandler.Setup(x => x.RequiresValidForm(It.IsAny(), It.IsAny())).Returns(true); - var editContext = new FormEditContext("alias", "repo", "entity", new InvalidEntity(), default, UsageType.Edit, new List { new ValidationSetup(typeof(DataAnnotationEntityValidator), default) }, _serviceProvider); - Expression> property = x => x.Name; - editContext.NotifyPropertyIncludedInForm(PropertyMetadataHelper.GetPropertyMetadata(property)!); - var request = new PersistEntityRequestModel() - { - ActionId = "123", - EditContext = editContext - }; - - // act & assert - Assert.ThrowsAsync(typeof(InvalidEntityException), () => _subject.ValidateButtonInteractionAsync(request)); - } - - [Test] - public void WhenValidationOfEditorButtonIsRequested_ThenHandlerOfButtonIsInvoked() + ActionId = "123", + EditContext = editContext + }; + + // act & assert + Assert.ThrowsAsync(typeof(InvalidEntityException), () => _subject.ValidateButtonInteractionAsync(request)); + } + + [Test] + public void WhenValidationOfEditorButtonIsRequested_ThenHandlerOfButtonIsInvoked() + { + // arrange + var customData = new object(); + var editContext = new FormEditContext("alias", "repo", "entity", new DefaultEntityVariant(), default, UsageType.Edit, new List { new ValidationSetup(typeof(DataAnnotationEntityValidator), default) }, _serviceProvider); + var request = new PersistEntityRequestModel() { - // arrange - var customData = new object(); - var editContext = new FormEditContext("alias", "repo", "entity", new DefaultEntityVariant(), default, UsageType.Edit, new List { new ValidationSetup(typeof(DataAnnotationEntityValidator), default) }, _serviceProvider); - var request = new PersistEntityRequestModel() - { - ActionId = "123", - CustomData = customData, - EditContext = editContext - }; - - // act - _subject.ValidateButtonInteractionAsync(request); - - // assert - _buttonActionHandler.Verify(x => x.ButtonClickBeforeRepositoryActionAsync(It.IsAny(), It.Is(x => x == editContext), It.Is(x => x.CustomData == customData)), Times.Once()); - } - - [Test] - public void WhenInteractionCompletionOfEditorButtonIsRequested_ThenHandlerOfButtonIsInvoked() + ActionId = "123", + CustomData = customData, + EditContext = editContext + }; + + // act + _subject.ValidateButtonInteractionAsync(request); + + // assert + _buttonActionHandler.Verify(x => x.ButtonClickBeforeRepositoryActionAsync(It.IsAny(), It.Is(x => x == editContext), It.Is(x => x.CustomData == customData)), Times.Once()); + } + + [Test] + public void WhenInteractionCompletionOfEditorButtonIsRequested_ThenHandlerOfButtonIsInvoked() + { + // arrange + var customData = new object(); + var editContext = new FormEditContext("alias", "repo", "entity", new DefaultEntityVariant(), default, UsageType.Edit, new List { new ValidationSetup(typeof(DataAnnotationEntityValidator), default) }, _serviceProvider); + + var request = new PersistEntityRequestModel() { - // arrange - var customData = new object(); - var editContext = new FormEditContext("alias", "repo", "entity", new DefaultEntityVariant(), default, UsageType.Edit, new List { new ValidationSetup(typeof(DataAnnotationEntityValidator), default) }, _serviceProvider); - - var request = new PersistEntityRequestModel() - { - ActionId = "123", - CustomData = customData, - EditContext = editContext - }; - - // act - _subject.CompleteButtonInteractionAsync(request); - - // assert - _buttonActionHandler.Verify(x => x.ButtonClickAfterRepositoryActionAsync(It.IsAny(), It.Is(x => x == editContext), It.Is(x => x.CustomData == customData)), Times.Once()); - } - - [TestCase(true)] - [TestCase(false)] - public void WhenValidationOfEditorInListButtonIsRequested_ThenValidityOfEditContextIsTested(bool requiresTesting) + ActionId = "123", + CustomData = customData, + EditContext = editContext + }; + + // act + _subject.CompleteButtonInteractionAsync(request); + + // assert + _buttonActionHandler.Verify(x => x.ButtonClickAfterRepositoryActionAsync(It.IsAny(), It.Is(x => x == editContext), It.Is(x => x.CustomData == customData)), Times.Once()); + } + + [TestCase(true)] + [TestCase(false)] + public void WhenValidationOfEditorInListButtonIsRequested_ThenValidityOfEditContextIsTested(bool requiresTesting) + { + // arrange + _buttonActionHandler.Setup(x => x.RequiresValidForm(It.IsAny(), It.IsAny())).Returns(requiresTesting); + var editContext = new FormEditContext("alias", "repo", "entity", new ValidEntity(), default, UsageType.Edit, new List { new ValidationSetup(typeof(DataAnnotationEntityValidator), default) }, _serviceProvider); + var listContext = new ListContext("alias", editContext, default, UsageType.Edit, default, _serviceProvider); + Expression> property = x => x.Name; + editContext.NotifyPropertyIncludedInForm(PropertyMetadataHelper.GetPropertyMetadata(property)!); + var request = new PersistEntityCollectionRequestModel() { - // arrange - _buttonActionHandler.Setup(x => x.RequiresValidForm(It.IsAny(), It.IsAny())).Returns(requiresTesting); - var editContext = new FormEditContext("alias", "repo", "entity", new ValidEntity(), default, UsageType.Edit, new List { new ValidationSetup(typeof(DataAnnotationEntityValidator), default) }, _serviceProvider); - var listContext = new ListContext("alias", editContext, default, UsageType.Edit, default, _serviceProvider); - Expression> property = x => x.Name; - editContext.NotifyPropertyIncludedInForm(PropertyMetadataHelper.GetPropertyMetadata(property)!); - var request = new PersistEntityCollectionRequestModel() - { - ActionId = "123", - ListContext = listContext, - EditContext = editContext - }; - - // act - _subject.ValidateButtonInteractionAsync(request); - - // assert - _buttonActionHandler.Verify(x => x.RequiresValidForm(It.IsAny(), It.IsAny()), Times.Once()); - Assert.AreEqual(requiresTesting, editContext.WasValidated(PropertyMetadataHelper.GetPropertyMetadata(property)!)); - } - - [Test] - public void WhenValidationOfEditorInListButtonIsRequested_ThenExceptionIsThrownIfFormIsInvalid() + ActionId = "123", + ListContext = listContext, + EditContext = editContext + }; + + // act + _subject.ValidateButtonInteractionAsync(request); + + // assert + _buttonActionHandler.Verify(x => x.RequiresValidForm(It.IsAny(), It.IsAny()), Times.Once()); + Assert.AreEqual(requiresTesting, editContext.WasValidated(PropertyMetadataHelper.GetPropertyMetadata(property)!)); + } + + [Test] + public void WhenValidationOfEditorInListButtonIsRequested_ThenExceptionIsThrownIfFormIsInvalid() + { + // arrange + _buttonActionHandler.Setup(x => x.RequiresValidForm(It.IsAny(), It.IsAny())).Returns(true); + var editContext = new FormEditContext("alias", "repo", "entity", new InvalidEntity(), default, UsageType.Edit, new List { new ValidationSetup(typeof(DataAnnotationEntityValidator), default) }, _serviceProvider); + var listContext = new ListContext("alias", editContext, default, UsageType.Edit, default, _serviceProvider); + Expression> property = x => x.Name; + editContext.NotifyPropertyIncludedInForm(PropertyMetadataHelper.GetPropertyMetadata(property)!); + var request = new PersistEntityCollectionRequestModel() { - // arrange - _buttonActionHandler.Setup(x => x.RequiresValidForm(It.IsAny(), It.IsAny())).Returns(true); - var editContext = new FormEditContext("alias", "repo", "entity", new InvalidEntity(), default, UsageType.Edit, new List { new ValidationSetup(typeof(DataAnnotationEntityValidator), default) }, _serviceProvider); - var listContext = new ListContext("alias", editContext, default, UsageType.Edit, default, _serviceProvider); - Expression> property = x => x.Name; - editContext.NotifyPropertyIncludedInForm(PropertyMetadataHelper.GetPropertyMetadata(property)!); - var request = new PersistEntityCollectionRequestModel() - { - ActionId = "123", - ListContext = listContext, - EditContext = editContext - }; - - // act & assert - Assert.ThrowsAsync(typeof(InvalidEntityException), () => _subject.ValidateButtonInteractionAsync(request)); - } - - [Test] - public void WhenValidationOfEditorInListButtonIsRequested_ThenHandlerOfButtonIsInvoked() + ActionId = "123", + ListContext = listContext, + EditContext = editContext + }; + + // act & assert + Assert.ThrowsAsync(typeof(InvalidEntityException), () => _subject.ValidateButtonInteractionAsync(request)); + } + + [Test] + public void WhenValidationOfEditorInListButtonIsRequested_ThenHandlerOfButtonIsInvoked() + { + // arrange + var customData = new object(); + var editContext = new FormEditContext("alias", "repo", "entity", new DefaultEntityVariant(), default, UsageType.Edit, new List { new ValidationSetup(typeof(DataAnnotationEntityValidator), default) }, _serviceProvider); + var listContext = new ListContext("alias", editContext, default, UsageType.Edit, default, _serviceProvider); + var request = new PersistEntityCollectionRequestModel() { - // arrange - var customData = new object(); - var editContext = new FormEditContext("alias", "repo", "entity", new DefaultEntityVariant(), default, UsageType.Edit, new List { new ValidationSetup(typeof(DataAnnotationEntityValidator), default) }, _serviceProvider); - var listContext = new ListContext("alias", editContext, default, UsageType.Edit, default, _serviceProvider); - var request = new PersistEntityCollectionRequestModel() - { - ActionId = "123", - CustomData = customData, - ListContext = listContext, - EditContext = editContext - }; - - // act - _subject.ValidateButtonInteractionAsync(request); - - // assert - _buttonActionHandler.Verify(x => x.ButtonClickBeforeRepositoryActionAsync(It.IsAny(), It.Is(x => x == editContext), It.Is(x => x.CustomData == customData)), Times.Once()); - } - - [Test] - public void WhenValidationOfListButtonIsRequested_ThenHandlerOfButtonIsInvoked() + ActionId = "123", + CustomData = customData, + ListContext = listContext, + EditContext = editContext + }; + + // act + _subject.ValidateButtonInteractionAsync(request); + + // assert + _buttonActionHandler.Verify(x => x.ButtonClickBeforeRepositoryActionAsync(It.IsAny(), It.Is(x => x == editContext), It.Is(x => x.CustomData == customData)), Times.Once()); + } + + [Test] + public void WhenValidationOfListButtonIsRequested_ThenHandlerOfButtonIsInvoked() + { + // arrange + var customData = new object(); + var editContext = new FormEditContext("alias", "repo", "entity", new DefaultEntityVariant(), default, UsageType.Edit, new List { new ValidationSetup(typeof(DataAnnotationEntityValidator), default) }, _serviceProvider); + var listContext = new ListContext("alias", editContext, default, UsageType.Edit, default, _serviceProvider); + var request = new PersistEntitiesRequestModel() { - // arrange - var customData = new object(); - var editContext = new FormEditContext("alias", "repo", "entity", new DefaultEntityVariant(), default, UsageType.Edit, new List { new ValidationSetup(typeof(DataAnnotationEntityValidator), default) }, _serviceProvider); - var listContext = new ListContext("alias", editContext, default, UsageType.Edit, default, _serviceProvider); - var request = new PersistEntitiesRequestModel() - { - ActionId = "123", - CustomData = customData, - ListContext = listContext - }; - - // act - _subject.ValidateButtonInteractionAsync(request); - - // assert - _buttonActionHandler.Verify(x => x.ButtonClickBeforeRepositoryActionAsync(It.IsAny(), It.Is(x => x == editContext), It.Is(x => x.CustomData == customData)), Times.Once()); - } - - [Test] - public void WhenInteractionCompletionOfListButtonIsRequested_ThenHandlerOfButtonIsInvoked() + ActionId = "123", + CustomData = customData, + ListContext = listContext + }; + + // act + _subject.ValidateButtonInteractionAsync(request); + + // assert + _buttonActionHandler.Verify(x => x.ButtonClickBeforeRepositoryActionAsync(It.IsAny(), It.Is(x => x == editContext), It.Is(x => x.CustomData == customData)), Times.Once()); + } + + [Test] + public void WhenInteractionCompletionOfListButtonIsRequested_ThenHandlerOfButtonIsInvoked() + { + // arrange + var customData = new object(); + var editContext = new FormEditContext("alias", "repo", "entity", new DefaultEntityVariant(), default, UsageType.Edit, new List { new ValidationSetup(typeof(DataAnnotationEntityValidator), default) }, _serviceProvider); + var listContext = new ListContext("alias", editContext, default, UsageType.Edit, default, _serviceProvider); + + var request = new PersistEntitiesRequestModel() { - // arrange - var customData = new object(); - var editContext = new FormEditContext("alias", "repo", "entity", new DefaultEntityVariant(), default, UsageType.Edit, new List { new ValidationSetup(typeof(DataAnnotationEntityValidator), default) }, _serviceProvider); - var listContext = new ListContext("alias", editContext, default, UsageType.Edit, default, _serviceProvider); - - var request = new PersistEntitiesRequestModel() - { - ActionId = "123", - CustomData = customData, - ListContext = listContext - }; - - // act - _subject.CompleteButtonInteractionAsync(request); - - // assert - _buttonActionHandler.Verify(x => x.ButtonClickAfterRepositoryActionAsync(It.IsAny(), It.Is(x => x == editContext), It.Is(x => x.CustomData == customData)), Times.Once()); - } + ActionId = "123", + CustomData = customData, + ListContext = listContext + }; + + // act + _subject.CompleteButtonInteractionAsync(request); + + // assert + _buttonActionHandler.Verify(x => x.ButtonClickAfterRepositoryActionAsync(It.IsAny(), It.Is(x => x == editContext), It.Is(x => x.CustomData == customData)), Times.Once()); } } diff --git a/src/RapidCMS.Core.Tests/JsonConverters/EntityModelJsonConverter.cs b/src/RapidCMS.Core.Tests/JsonConverters/EntityModelJsonConverter.cs index 5f7cd5da..31d1c51f 100644 --- a/src/RapidCMS.Core.Tests/JsonConverters/EntityModelJsonConverter.cs +++ b/src/RapidCMS.Core.Tests/JsonConverters/EntityModelJsonConverter.cs @@ -4,52 +4,51 @@ using RapidCMS.Core.Converters; using RapidCMS.Core.Models.ApiBridge; -namespace RapidCMS.Core.Tests.JsonConverters +namespace RapidCMS.Core.Tests.JsonConverters; + +public class EntityModelJsonConverter { - public class EntityModelJsonConverter - { - private JsonSerializerSettings _jsonSerializerSettings; + private JsonSerializerSettings _jsonSerializerSettings; - [SetUp] - public void Setup() - { - _jsonSerializerSettings = new JsonSerializerSettings(); - _jsonSerializerSettings.Converters.Add(new EntityModelJsonConverter()); - } + [SetUp] + public void Setup() + { + _jsonSerializerSettings = new JsonSerializerSettings(); + _jsonSerializerSettings.Converters.Add(new EntityModelJsonConverter()); + } - [Test] - public void WhenEntityIsGivenToJsonConverter_EntityIsDeserialized() - { - var model = EntityModel.Create(new Entity()); + [Test] + public void WhenEntityIsGivenToJsonConverter_EntityIsDeserialized() + { + var model = EntityModel.Create(new Entity()); - var json = JsonConvert.SerializeObject(model, _jsonSerializerSettings); + var json = JsonConvert.SerializeObject(model, _jsonSerializerSettings); - var deserializedModel = JsonConvert.DeserializeObject>(json, _jsonSerializerSettings); + var deserializedModel = JsonConvert.DeserializeObject>(json, _jsonSerializerSettings); - Assert.AreEqual(model.Entity.GetType(), deserializedModel.Entity.GetType()); - Assert.AreEqual(model.VariantAlias, deserializedModel.VariantAlias); - } + Assert.AreEqual(model.Entity.GetType(), deserializedModel.Entity.GetType()); + Assert.AreEqual(model.VariantAlias, deserializedModel.VariantAlias); + } - [Test] - public void WhenSubEntityIsGivenToJsonConverter_SubEntityIsDeserialized() - { - var model = EntityModel.Create(new SubEntity()); + [Test] + public void WhenSubEntityIsGivenToJsonConverter_SubEntityIsDeserialized() + { + var model = EntityModel.Create(new SubEntity()); - var json = JsonConvert.SerializeObject(model, _jsonSerializerSettings); + var json = JsonConvert.SerializeObject(model, _jsonSerializerSettings); - var deserializedModel = JsonConvert.DeserializeObject>(json, _jsonSerializerSettings); + var deserializedModel = JsonConvert.DeserializeObject>(json, _jsonSerializerSettings); - Assert.AreEqual(model.Entity.GetType(), deserializedModel.Entity.GetType()); - Assert.AreEqual(model.VariantAlias, deserializedModel.VariantAlias); - } + Assert.AreEqual(model.Entity.GetType(), deserializedModel.Entity.GetType()); + Assert.AreEqual(model.VariantAlias, deserializedModel.VariantAlias); + } - class Entity : IEntity - { - public string Id { get; set; } - } + class Entity : IEntity + { + public string Id { get; set; } + } - class SubEntity : Entity - { - } + class SubEntity : Entity + { } } diff --git a/src/RapidCMS.Core.Tests/Navigation/NavigationStateTests.cs b/src/RapidCMS.Core.Tests/Navigation/NavigationStateTests.cs index adce84c4..9aeff534 100644 --- a/src/RapidCMS.Core.Tests/Navigation/NavigationStateTests.cs +++ b/src/RapidCMS.Core.Tests/Navigation/NavigationStateTests.cs @@ -4,77 +4,76 @@ using RapidCMS.Core.Navigation; using System.Collections; -namespace RapidCMS.Core.Tests.Navigation +namespace RapidCMS.Core.Tests.Navigation; + +public class NavigationStateTests { - public class NavigationStateTests + [TestCaseSource(typeof(NavigationStateTestCases))] + public void WhenUrlIsGiven_ThenUrlIsParsed(string url, string query, NavigationState expectedState) { - [TestCaseSource(typeof(NavigationStateTestCases))] - public void WhenUrlIsGiven_ThenUrlIsParsed(string url, string query, NavigationState expectedState) - { - var state = new NavigationState(url, query); + var state = new NavigationState(url, query); - Assert.IsTrue(expectedState.Equals(state)); - } + Assert.IsTrue(expectedState.Equals(state)); + } - private class NavigationStateTestCases : IEnumerable + private class NavigationStateTestCases : IEnumerable + { + public IEnumerator GetEnumerator() { - public IEnumerator GetEnumerator() - { - yield return new object[] { - "/collection/edit/person/", - "", - new NavigationState("person", default(ParentPath), UsageType.Edit) - }; - - yield return new object[] { - "/collection/edit/person/", - "?p=1", - new NavigationState("person", default(ParentPath), UsageType.Edit) - { - CollectionState = new CollectionState(null, null, 1, null) - } - }; + yield return new object[] { + "/collection/edit/person/", + "", + new NavigationState("person", default(ParentPath), UsageType.Edit) + }; - yield return new object[] + yield return new object[] { + "/collection/edit/person/", + "?p=1", + new NavigationState("person", default(ParentPath), UsageType.Edit) { - "/node/edit/person-convention/VNRDry/-/428281356/", - "", - new NavigationState("person-convention", default(ParentPath), "VNRDry", "428281356", UsageType.Edit) - }; + CollectionState = new CollectionState(null, null, 1, null) + } + }; - yield return new object[] - { - "/node/edit/person-convention/VNRDry/fdsa:123/428281356/", - "", - new NavigationState("person-convention", ParentPath.TryParse("fdsa:123"), "VNRDry", "428281356", UsageType.Edit) - }; + yield return new object[] + { + "/node/edit/person-convention/VNRDry/-/428281356/", + "", + new NavigationState("person-convention", default(ParentPath), "VNRDry", "428281356", UsageType.Edit) + }; - yield return new object[] - { - "/node/edit/person-convention/VNRDry/fdsa:123;fdsafdsa:12345/428281356/", - "", - new NavigationState("person-convention", ParentPath.TryParse("fdsa:123;fdsafdsa:12345"), "VNRDry", "428281356", UsageType.Edit) - }; + yield return new object[] + { + "/node/edit/person-convention/VNRDry/fdsa:123/428281356/", + "", + new NavigationState("person-convention", ParentPath.TryParse("fdsa:123"), "VNRDry", "428281356", UsageType.Edit) + }; - yield return new object[] - { - "node/new/variants/aOkLV_", - "", - new NavigationState("variants", default(ParentPath), "aOkLV_", default(string), UsageType.New) - }; + yield return new object[] + { + "/node/edit/person-convention/VNRDry/fdsa:123;fdsafdsa:12345/428281356/", + "", + new NavigationState("person-convention", ParentPath.TryParse("fdsa:123;fdsafdsa:12345"), "VNRDry", "428281356", UsageType.Edit) + }; - yield return new object[] - { - "/node/new/person/yY4Nc6/Da9Ic3-Sv5oVVgQDwmEuxhfvCEs7j6maatAe46OuNgA:439326248;Da9Ic3-Sv5oVVgQDwmEuxhfvCEs7j6maatAe46OuNgA:654154684;Da9Ic3-Sv5oVVgQDwmEuxhfvCEs7j6maatAe46OuNgA:1594109173/", - "", - new NavigationState( - "person", - ParentPath.TryParse("Da9Ic3-Sv5oVVgQDwmEuxhfvCEs7j6maatAe46OuNgA:439326248;Da9Ic3-Sv5oVVgQDwmEuxhfvCEs7j6maatAe46OuNgA:654154684;Da9Ic3-Sv5oVVgQDwmEuxhfvCEs7j6maatAe46OuNgA:1594109173"), - "yY4Nc6", - default(string), - UsageType.New) - }; - } + yield return new object[] + { + "node/new/variants/aOkLV_", + "", + new NavigationState("variants", default(ParentPath), "aOkLV_", default(string), UsageType.New) + }; + + yield return new object[] + { + "/node/new/person/yY4Nc6/Da9Ic3-Sv5oVVgQDwmEuxhfvCEs7j6maatAe46OuNgA:439326248;Da9Ic3-Sv5oVVgQDwmEuxhfvCEs7j6maatAe46OuNgA:654154684;Da9Ic3-Sv5oVVgQDwmEuxhfvCEs7j6maatAe46OuNgA:1594109173/", + "", + new NavigationState( + "person", + ParentPath.TryParse("Da9Ic3-Sv5oVVgQDwmEuxhfvCEs7j6maatAe46OuNgA:439326248;Da9Ic3-Sv5oVVgQDwmEuxhfvCEs7j6maatAe46OuNgA:654154684;Da9Ic3-Sv5oVVgQDwmEuxhfvCEs7j6maatAe46OuNgA:1594109173"), + "yY4Nc6", + default(string), + UsageType.New) + }; } } } diff --git a/src/RapidCMS.Core.Tests/ParentPathTests/ParentEntityPathTests.cs b/src/RapidCMS.Core.Tests/ParentPathTests/ParentEntityPathTests.cs index 7c680353..0928cbaa 100644 --- a/src/RapidCMS.Core.Tests/ParentPathTests/ParentEntityPathTests.cs +++ b/src/RapidCMS.Core.Tests/ParentPathTests/ParentEntityPathTests.cs @@ -2,63 +2,62 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Models.Data; -namespace RapidCMS.Core.Tests.ParentPathTests +namespace RapidCMS.Core.Tests.ParentPathTests; + +public class ParentEntityPathTests { - public class ParentEntityPathTests + [SetUp] + public void Setup() { - [SetUp] - public void Setup() - { - } - - [Test] - public void BasicPath() - { - // arrange - var parent = new ParentEntity(default, new Entity { Id = "1" }, "test1"); - - // act - var path = parent.GetParentPath(); + } - // assert - Assert.AreEqual("test1:1", path!.ToPathString()); - } + [Test] + public void BasicPath() + { + // arrange + var parent = new ParentEntity(default, new Entity { Id = "1" }, "test1"); - [Test] - public void NestedPath() - { - // arrange - var parent = new ParentEntity( - new ParentEntity(default, new Entity { Id = "2" }, "test2"), - new Entity { Id = "1" }, "test1"); + // act + var path = parent.GetParentPath(); - // act - var path = parent.GetParentPath(); + // assert + Assert.AreEqual("test1:1", path!.ToPathString()); + } - // assert - Assert.AreEqual("test2:2;test1:1", path!.ToPathString()); - } + [Test] + public void NestedPath() + { + // arrange + var parent = new ParentEntity( + new ParentEntity(default, new Entity { Id = "2" }, "test2"), + new Entity { Id = "1" }, "test1"); - [Test] - public void DeepNestedPath() - { - // arrange - var parent = new ParentEntity( - new ParentEntity( - new ParentEntity(default, new Entity { Id = "3" }, "test3"), - new Entity { Id = "2" }, "test2"), - new Entity { Id = "1" }, "test1"); + // act + var path = parent.GetParentPath(); - // act - var path = parent.GetParentPath(); + // assert + Assert.AreEqual("test2:2;test1:1", path!.ToPathString()); + } - // assert - Assert.AreEqual("test3:3;test2:2;test1:1", path!.ToPathString()); - } + [Test] + public void DeepNestedPath() + { + // arrange + var parent = new ParentEntity( + new ParentEntity( + new ParentEntity(default, new Entity { Id = "3" }, "test3"), + new Entity { Id = "2" }, "test2"), + new Entity { Id = "1" }, "test1"); + + // act + var path = parent.GetParentPath(); + + // assert + Assert.AreEqual("test3:3;test2:2;test1:1", path!.ToPathString()); + } - public class Entity : IEntity - { - public string Id { get; set; } - } + public class Entity : IEntity + { + public string Id { get; set; } } } diff --git a/src/RapidCMS.Core.Tests/ParentPathTests/ParentPathTests.cs b/src/RapidCMS.Core.Tests/ParentPathTests/ParentPathTests.cs index 7d10ead3..8001bf4c 100644 --- a/src/RapidCMS.Core.Tests/ParentPathTests/ParentPathTests.cs +++ b/src/RapidCMS.Core.Tests/ParentPathTests/ParentPathTests.cs @@ -1,101 +1,100 @@ using NUnit.Framework; using RapidCMS.Core.Models.Data; -namespace RapidCMS.Core.Tests.ParentPathTests +namespace RapidCMS.Core.Tests.ParentPathTests; + +public class ParentPathTests { - public class ParentPathTests + [SetUp] + public void Setup() + { + } + + [Test] + public void BasicPath() { - [SetUp] - public void Setup() - { - } - - [Test] - public void BasicPath() - { - // arrange - - // act - var path = ParentPath.TryParse("test:123"); - - // assert - Assert.AreEqual("test:123", path!.ToPathString()); - } - - [Test] - public void AppendPath() - { - // arrange - - // act - var path = ParentPath.TryParse("test:123"); - var newPath = ParentPath.AddLevel(path, "test2", "1234"); - - // assert - Assert.AreEqual("test:123", path!.ToPathString()); - Assert.AreEqual("test:123;test2:1234", newPath.ToPathString()); - } - - [Test] - public void AppendPathFromNull() - { - // arrange - - // act - var path = default(ParentPath); - var newPath = ParentPath.AddLevel(path, "test2", "1234"); - - // assert - Assert.AreEqual("test2:1234", newPath.ToPathString()); - } - - [Test] - public void RemoveLevel() - { - // arrange - - // act - var path = ParentPath.TryParse("test:123;test2:1234"); - var (newPath, collectionAlias, id) = ParentPath.RemoveLevel(path); - - // assert - Assert.AreEqual("test:123;test2:1234", path!.ToPathString()); - Assert.AreEqual("test:123", newPath.ToPathString()); - Assert.AreEqual("test2", collectionAlias); - Assert.AreEqual("1234", id); - } - - [Test] - public void RemoveLevelRemoveLevel() - { - // arrange - - // act - var path = ParentPath.TryParse("test:123;test2:1234"); - var (intPath, _, _) = ParentPath.RemoveLevel(path); - var (newPath, collectionAlias, id) = ParentPath.RemoveLevel(intPath); - - // assert - Assert.AreEqual("test:123;test2:1234", path!.ToPathString()); - Assert.AreEqual(null, newPath); - Assert.AreEqual("test", collectionAlias); - Assert.AreEqual("123", id); - } - - [Test] - public void RemoveLevelFromNull() - { - // arrange - - // act - var path = ParentPath.TryParse(null); - var (newPath, collectionAlias, id) = ParentPath.RemoveLevel(path); - - // assert - Assert.AreEqual(null, path?.ToPathString()); - Assert.AreEqual("", newPath?.ToPathString()); - Assert.AreEqual(null, collectionAlias); - Assert.AreEqual(null, id); - } + // arrange + + // act + var path = ParentPath.TryParse("test:123"); + + // assert + Assert.AreEqual("test:123", path!.ToPathString()); + } + + [Test] + public void AppendPath() + { + // arrange + + // act + var path = ParentPath.TryParse("test:123"); + var newPath = ParentPath.AddLevel(path, "test2", "1234"); + + // assert + Assert.AreEqual("test:123", path!.ToPathString()); + Assert.AreEqual("test:123;test2:1234", newPath.ToPathString()); + } + + [Test] + public void AppendPathFromNull() + { + // arrange + + // act + var path = default(ParentPath); + var newPath = ParentPath.AddLevel(path, "test2", "1234"); + + // assert + Assert.AreEqual("test2:1234", newPath.ToPathString()); + } + + [Test] + public void RemoveLevel() + { + // arrange + + // act + var path = ParentPath.TryParse("test:123;test2:1234"); + var (newPath, collectionAlias, id) = ParentPath.RemoveLevel(path); + + // assert + Assert.AreEqual("test:123;test2:1234", path!.ToPathString()); + Assert.AreEqual("test:123", newPath.ToPathString()); + Assert.AreEqual("test2", collectionAlias); + Assert.AreEqual("1234", id); + } + + [Test] + public void RemoveLevelRemoveLevel() + { + // arrange + + // act + var path = ParentPath.TryParse("test:123;test2:1234"); + var (intPath, _, _) = ParentPath.RemoveLevel(path); + var (newPath, collectionAlias, id) = ParentPath.RemoveLevel(intPath); + + // assert + Assert.AreEqual("test:123;test2:1234", path!.ToPathString()); + Assert.AreEqual(null, newPath); + Assert.AreEqual("test", collectionAlias); + Assert.AreEqual("123", id); + } + + [Test] + public void RemoveLevelFromNull() + { + // arrange + + // act + var path = ParentPath.TryParse(null); + var (newPath, collectionAlias, id) = ParentPath.RemoveLevel(path); + + // assert + Assert.AreEqual(null, path?.ToPathString()); + Assert.AreEqual("", newPath?.ToPathString()); + Assert.AreEqual(null, collectionAlias); + Assert.AreEqual(null, id); } } diff --git a/src/RapidCMS.Core.Tests/PropertyMetadata/PropertyMetadataTests.cs b/src/RapidCMS.Core.Tests/PropertyMetadata/PropertyMetadataTests.cs index d23d1b15..c34f2f67 100644 --- a/src/RapidCMS.Core.Tests/PropertyMetadata/PropertyMetadataTests.cs +++ b/src/RapidCMS.Core.Tests/PropertyMetadata/PropertyMetadataTests.cs @@ -7,629 +7,628 @@ using RapidCMS.Core.Helpers; using RapidCMS.Core.Models; -namespace RapidCMS.Core.Tests.PropertyMetadata +namespace RapidCMS.Core.Tests.PropertyMetadata; + +public class PropertyMetadataTests { - public class PropertyMetadataTests + [Test] + public void BasicProperty() + { + var instance = new BasicClass { Test = "Test Value" }; + Expression> func = (BasicClass x) => x.Test; + + var data = PropertyMetadataHelper.GetPropertyMetadata(func) as IFullPropertyMetadata; + + Assert.IsNotNull(data); + Assert.AreEqual("Test", data.PropertyName); + Assert.AreEqual("Test Value", data.Getter(instance)); + Assert.AreEqual(typeof(string), data.PropertyType); + Assert.AreEqual(typeof(BasicClass), data.ObjectType); + + data.Setter(instance, "New Value"); + + Assert.AreEqual("New Value", instance.Test); + } + + [Test] + public void BasicNonStringProperty() + { + var instance = new BasicClass { Test = "Test Value", Id = 1 }; + Expression> func = (BasicClass x) => x.Id; + + var data = PropertyMetadataHelper.GetPropertyMetadata(func) as IFullPropertyMetadata; + + Assert.IsNotNull(data); + Assert.AreEqual("Id", data.PropertyName); + Assert.AreEqual(1, data.Getter(instance)); + Assert.AreEqual(typeof(int), data.PropertyType); + Assert.AreEqual(typeof(BasicClass), data.ObjectType); + + data.Setter(instance, 2); + + Assert.AreEqual(2, instance.Id); + } + + [Test] + public void NestedProperty() { - [Test] - public void BasicProperty() - { - var instance = new BasicClass { Test = "Test Value" }; - Expression> func = (BasicClass x) => x.Test; + var instance = new ParentClass { Basic = new BasicClass { Test = "Test Value" } }; + Expression> func = (ParentClass x) => x.Basic.Test; - var data = PropertyMetadataHelper.GetPropertyMetadata(func) as IFullPropertyMetadata; + var data = PropertyMetadataHelper.GetPropertyMetadata(func) as IFullPropertyMetadata; - Assert.IsNotNull(data); - Assert.AreEqual("Test", data.PropertyName); - Assert.AreEqual("Test Value", data.Getter(instance)); - Assert.AreEqual(typeof(string), data.PropertyType); - Assert.AreEqual(typeof(BasicClass), data.ObjectType); + Assert.IsNotNull(data); + Assert.AreEqual("Basic.Test", data.PropertyName); + Assert.AreEqual("Test Value", data.Getter(instance)); + Assert.AreEqual(typeof(string), data.PropertyType); + Assert.AreEqual(typeof(ParentClass), data.ObjectType); - data.Setter(instance, "New Value"); + data.Setter(instance, "New Value"); - Assert.AreEqual("New Value", instance.Test); - } + Assert.AreEqual("New Value", instance.Basic.Test); + } - [Test] - public void BasicNonStringProperty() - { - var instance = new BasicClass { Test = "Test Value", Id = 1 }; - Expression> func = (BasicClass x) => x.Id; + [Test] + public void NestedNonStringProperty() + { + var instance = new ParentClass { Basic = new BasicClass { Test = "Test Value", Id = 1 } }; + Expression> func = (ParentClass x) => x.Basic.Id; - var data = PropertyMetadataHelper.GetPropertyMetadata(func) as IFullPropertyMetadata; + var data = PropertyMetadataHelper.GetPropertyMetadata(func) as IFullPropertyMetadata; - Assert.IsNotNull(data); - Assert.AreEqual("Id", data.PropertyName); - Assert.AreEqual(1, data.Getter(instance)); - Assert.AreEqual(typeof(int), data.PropertyType); - Assert.AreEqual(typeof(BasicClass), data.ObjectType); + Assert.IsNotNull(data); + Assert.AreEqual("Basic.Id", data.PropertyName); + Assert.AreEqual(1, data.Getter(instance)); + Assert.AreEqual(typeof(int), data.PropertyType); + Assert.AreEqual(typeof(ParentClass), data.ObjectType); - data.Setter(instance, 2); + data.Setter(instance, 2); - Assert.AreEqual(2, instance.Id); - } + Assert.AreEqual(2, instance.Basic.Id); + } - [Test] - public void NestedProperty() - { - var instance = new ParentClass { Basic = new BasicClass { Test = "Test Value" } }; - Expression> func = (ParentClass x) => x.Basic.Test; + [Test] + public void BasicStringExpression() + { + var instance = new BasicClass { Test = "Test Value" }; + Expression> func = (BasicClass x) => $"{x.Test} - Blub"; - var data = PropertyMetadataHelper.GetPropertyMetadata(func) as IFullPropertyMetadata; + var data = PropertyMetadataHelper.GetExpressionMetadata(func); - Assert.IsNotNull(data); - Assert.AreEqual("Basic.Test", data.PropertyName); - Assert.AreEqual("Test Value", data.Getter(instance)); - Assert.AreEqual(typeof(string), data.PropertyType); - Assert.AreEqual(typeof(ParentClass), data.ObjectType); + Assert.IsNotNull(data); + Assert.AreEqual("Test Value - Blub", data.StringGetter(instance)); - data.Setter(instance, "New Value"); + var propertyData = PropertyMetadataHelper.GetPropertyMetadata(func); - Assert.AreEqual("New Value", instance.Basic.Test); - } + Assert.IsNotNull(propertyData); + Assert.IsNull(propertyData as IFullPropertyMetadata); + Assert.AreEqual("x => Format(\"{0} - Blub\", x.Test)", propertyData.PropertyName); + Assert.AreEqual("Test Value - Blub", propertyData.Getter(instance)); + Assert.AreEqual(typeof(string), propertyData.PropertyType); + } + + [Test] + public void BasicNullStringExpression() + { + var instance = new BasicClass { Test = null }; + Expression> func = (BasicClass x) => x.Test; - [Test] - public void NestedNonStringProperty() - { - var instance = new ParentClass { Basic = new BasicClass { Test = "Test Value", Id = 1 } }; - Expression> func = (ParentClass x) => x.Basic.Id; + var data = PropertyMetadataHelper.GetExpressionMetadata(func); - var data = PropertyMetadataHelper.GetPropertyMetadata(func) as IFullPropertyMetadata; + Assert.IsNotNull(data); + Assert.AreEqual("", data.StringGetter(instance)); - Assert.IsNotNull(data); - Assert.AreEqual("Basic.Id", data.PropertyName); - Assert.AreEqual(1, data.Getter(instance)); - Assert.AreEqual(typeof(int), data.PropertyType); - Assert.AreEqual(typeof(ParentClass), data.ObjectType); + var propertyData = PropertyMetadataHelper.GetPropertyMetadata(func); - data.Setter(instance, 2); + Assert.IsNotNull(propertyData as IFullPropertyMetadata); + Assert.AreEqual("Test", propertyData.PropertyName); + Assert.AreEqual(null, propertyData.Getter(instance)); + Assert.AreEqual(typeof(string), propertyData.PropertyType); + } - Assert.AreEqual(2, instance.Basic.Id); - } + [Test] + public void BasicNullNullableStringExpression() + { + var instance = new BasicClass { NullableTest = null }; + Expression> func = (BasicClass x) => x.NullableTest; - [Test] - public void BasicStringExpression() - { - var instance = new BasicClass { Test = "Test Value" }; - Expression> func = (BasicClass x) => $"{x.Test} - Blub"; + var data = PropertyMetadataHelper.GetExpressionMetadata(func); - var data = PropertyMetadataHelper.GetExpressionMetadata(func); + Assert.IsNotNull(data); + Assert.AreEqual(string.Empty, data.StringGetter(instance)); + } - Assert.IsNotNull(data); - Assert.AreEqual("Test Value - Blub", data.StringGetter(instance)); + [Test] + public void BasicNotNullNullableStringExpression() + { + var instance = new BasicClass { NullableTest = "test" }; + Expression> func = (BasicClass x) => x.NullableTest; - var propertyData = PropertyMetadataHelper.GetPropertyMetadata(func); + var data = PropertyMetadataHelper.GetExpressionMetadata(func); - Assert.IsNotNull(propertyData); - Assert.IsNull(propertyData as IFullPropertyMetadata); - Assert.AreEqual("x => Format(\"{0} - Blub\", x.Test)", propertyData.PropertyName); - Assert.AreEqual("Test Value - Blub", propertyData.Getter(instance)); - Assert.AreEqual(typeof(string), propertyData.PropertyType); - } + Assert.IsNotNull(data); + Assert.AreEqual("test", data.StringGetter(instance)); + } - [Test] - public void BasicNullStringExpression() - { - var instance = new BasicClass { Test = null }; - Expression> func = (BasicClass x) => x.Test; + [Test] + public void BasicStringExpression2() + { + var instance = new BasicClass { Test = "Test Value" }; + Expression> func = (BasicClass x) => $"Blaat"; - var data = PropertyMetadataHelper.GetExpressionMetadata(func); + var data = PropertyMetadataHelper.GetExpressionMetadata(func); - Assert.IsNotNull(data); - Assert.AreEqual("", data.StringGetter(instance)); + Assert.IsNotNull(data); + Assert.AreEqual("Blaat", data.StringGetter(instance)); - var propertyData = PropertyMetadataHelper.GetPropertyMetadata(func); + var propertyData = PropertyMetadataHelper.GetPropertyMetadata(func); - Assert.IsNotNull(propertyData as IFullPropertyMetadata); - Assert.AreEqual("Test", propertyData.PropertyName); - Assert.AreEqual(null, propertyData.Getter(instance)); - Assert.AreEqual(typeof(string), propertyData.PropertyType); - } + Assert.IsNotNull(propertyData); + Assert.IsNull(propertyData as IFullPropertyMetadata); + Assert.AreEqual("x => \"Blaat\"", propertyData.PropertyName); + Assert.AreEqual("Blaat", propertyData.Getter(instance)); + Assert.AreEqual(typeof(string), propertyData.PropertyType); + } - [Test] - public void BasicNullNullableStringExpression() - { - var instance = new BasicClass { NullableTest = null }; - Expression> func = (BasicClass x) => x.NullableTest; + [Test] + public void BasicStringExpression3() + { + var instance = new BasicClass { Test = "Test Value" }; + Expression> func = (BasicClass x) => string.Join(' ', x.Test.ToCharArray()); - var data = PropertyMetadataHelper.GetExpressionMetadata(func); + var data = PropertyMetadataHelper.GetExpressionMetadata(func); - Assert.IsNotNull(data); - Assert.AreEqual(string.Empty, data.StringGetter(instance)); - } + Assert.IsNotNull(data); + Assert.AreEqual("T e s t V a l u e", data.StringGetter(instance)); - [Test] - public void BasicNotNullNullableStringExpression() - { - var instance = new BasicClass { NullableTest = "test" }; - Expression> func = (BasicClass x) => x.NullableTest; + var propertyData = PropertyMetadataHelper.GetPropertyMetadata(func); - var data = PropertyMetadataHelper.GetExpressionMetadata(func); + Assert.IsNotNull(propertyData); + Assert.IsNull(propertyData as IFullPropertyMetadata); + Assert.AreEqual("x => Join( , x.Test.ToCharArray())", propertyData.PropertyName); + Assert.AreEqual("T e s t V a l u e", propertyData.Getter(instance)); + } - Assert.IsNotNull(data); - Assert.AreEqual("test", data.StringGetter(instance)); - } + [Test] + public void BasicStringExpressionConverted() + { + var instance = new BasicClass { Test = "Test Value" }; + Expression> func = (BasicClass x) => string.Join(' ', x.Test.ToCharArray()); - [Test] - public void BasicStringExpression2() - { - var instance = new BasicClass { Test = "Test Value" }; - Expression> func = (BasicClass x) => $"Blaat"; + var propertyData = PropertyMetadataHelper.GetPropertyMetadata(func); - var data = PropertyMetadataHelper.GetExpressionMetadata(func); + Assert.IsNotNull(propertyData); + Assert.IsNull(propertyData as IFullPropertyMetadata); + Assert.AreEqual("x => Join( , x.Test.ToCharArray())", propertyData.PropertyName); + Assert.AreEqual("T e s t V a l u e", propertyData.Getter(instance)); - Assert.IsNotNull(data); - Assert.AreEqual("Blaat", data.StringGetter(instance)); + var data = PropertyMetadataHelper.GetExpressionMetadata(propertyData); - var propertyData = PropertyMetadataHelper.GetPropertyMetadata(func); + Assert.IsNotNull(data); + Assert.AreEqual("T e s t V a l u e", data.StringGetter(instance)); + } - Assert.IsNotNull(propertyData); - Assert.IsNull(propertyData as IFullPropertyMetadata); - Assert.AreEqual("x => \"Blaat\"", propertyData.PropertyName); - Assert.AreEqual("Blaat", propertyData.Getter(instance)); - Assert.AreEqual(typeof(string), propertyData.PropertyType); - } + [Test] + public void BasicNonStringExpression() + { + var instance = new BasicClass { Test = "Test Value", Id = 3 }; + Expression> func = (BasicClass x) => x.Id; - [Test] - public void BasicStringExpression3() - { - var instance = new BasicClass { Test = "Test Value" }; - Expression> func = (BasicClass x) => string.Join(' ', x.Test.ToCharArray()); + var data = PropertyMetadataHelper.GetExpressionMetadata(func); - var data = PropertyMetadataHelper.GetExpressionMetadata(func); + Assert.IsNull(data); - Assert.IsNotNull(data); - Assert.AreEqual("T e s t V a l u e", data.StringGetter(instance)); + var propertyData = PropertyMetadataHelper.GetPropertyMetadata(func); - var propertyData = PropertyMetadataHelper.GetPropertyMetadata(func); + Assert.IsNotNull(propertyData); + Assert.AreEqual("Id", propertyData.PropertyName); + Assert.AreEqual(3, propertyData.Getter(instance)); + Assert.AreEqual(typeof(int), propertyData.PropertyType); + } - Assert.IsNotNull(propertyData); - Assert.IsNull(propertyData as IFullPropertyMetadata); - Assert.AreEqual("x => Join( , x.Test.ToCharArray())", propertyData.PropertyName); - Assert.AreEqual("T e s t V a l u e", propertyData.Getter(instance)); - } + [Test] + public void NestedStringExpression() + { + var instance = new ParentClass { Basic = new BasicClass { Test = "Test Value" } }; + Expression> func = (ParentClass x) => $"{x.Basic} {x.Basic.Test}"; - [Test] - public void BasicStringExpressionConverted() - { - var instance = new BasicClass { Test = "Test Value" }; - Expression> func = (BasicClass x) => string.Join(' ', x.Test.ToCharArray()); + var data = PropertyMetadataHelper.GetExpressionMetadata(func); - var propertyData = PropertyMetadataHelper.GetPropertyMetadata(func); + Assert.IsNotNull(data); + Assert.AreEqual("RapidCMS.Core.Tests.PropertyMetadata.PropertyMetadataTests+BasicClass Test Value", data.StringGetter(instance)); - Assert.IsNotNull(propertyData); - Assert.IsNull(propertyData as IFullPropertyMetadata); - Assert.AreEqual("x => Join( , x.Test.ToCharArray())", propertyData.PropertyName); - Assert.AreEqual("T e s t V a l u e", propertyData.Getter(instance)); - - var data = PropertyMetadataHelper.GetExpressionMetadata(propertyData); + var propertyData = PropertyMetadataHelper.GetPropertyMetadata(func); - Assert.IsNotNull(data); - Assert.AreEqual("T e s t V a l u e", data.StringGetter(instance)); - } + Assert.IsNotNull(propertyData); + Assert.IsNull(propertyData as IFullPropertyMetadata); + Assert.AreEqual("x => Format(\"{0} {1}\", x.Basic, x.Basic.Test)", propertyData.PropertyName); + Assert.AreEqual("RapidCMS.Core.Tests.PropertyMetadata.PropertyMetadataTests+BasicClass Test Value", propertyData.Getter(instance)); + Assert.AreEqual(typeof(string), propertyData.PropertyType); + } - [Test] - public void BasicNonStringExpression() - { - var instance = new BasicClass { Test = "Test Value", Id = 3 }; - Expression> func = (BasicClass x) => x.Id; + [Test] + public void BasicReadonlyProperty() + { + var instance = new BasicClass { Test = "Test Value" }; + Expression> func = (BasicClass x) => x.Test.ToLower(); - var data = PropertyMetadataHelper.GetExpressionMetadata(func); + var data = PropertyMetadataHelper.GetPropertyMetadata(func); - Assert.IsNull(data); + Assert.IsNotNull(data); + Assert.AreEqual("x => x.Test.ToLower()", data.PropertyName); + Assert.AreEqual("test value", data.Getter(instance)); + Assert.AreEqual(typeof(string), data.PropertyType); + Assert.AreEqual(typeof(BasicClass), data.ObjectType); - var propertyData = PropertyMetadataHelper.GetPropertyMetadata(func); + Assert.IsNull(data as IFullPropertyMetadata); + } - Assert.IsNotNull(propertyData); - Assert.AreEqual("Id", propertyData.PropertyName); - Assert.AreEqual(3, propertyData.Getter(instance)); - Assert.AreEqual(typeof(int), propertyData.PropertyType); - } + [Test] + public void BasicReadonlyNonStringProperty() + { + var instance = new BasicClass { Test = "Test Value", Id = 1 }; + Expression> func = (BasicClass x) => x.Id * 2; - [Test] - public void NestedStringExpression() - { - var instance = new ParentClass { Basic = new BasicClass { Test = "Test Value" } }; - Expression> func = (ParentClass x) => $"{x.Basic} {x.Basic.Test}"; + var data = PropertyMetadataHelper.GetPropertyMetadata(func); - var data = PropertyMetadataHelper.GetExpressionMetadata(func); + Assert.IsNotNull(data); + Assert.AreEqual("x => (x.Id * 2)", data.PropertyName); + Assert.AreEqual(2, data.Getter(instance)); + Assert.AreEqual(typeof(int), data.PropertyType); + Assert.AreEqual(typeof(BasicClass), data.ObjectType); - Assert.IsNotNull(data); - Assert.AreEqual("RapidCMS.Core.Tests.PropertyMetadata.PropertyMetadataTests+BasicClass Test Value", data.StringGetter(instance)); + Assert.IsNull(data as IFullPropertyMetadata); + } - var propertyData = PropertyMetadataHelper.GetPropertyMetadata(func); + [Test] + public void NestedReadonlyProperty() + { + var instance = new ParentClass { Basic = new BasicClass { Test = "Test Value" } }; + Expression> func = (ParentClass x) => x.Basic.Test.ToLower(); - Assert.IsNotNull(propertyData); - Assert.IsNull(propertyData as IFullPropertyMetadata); - Assert.AreEqual("x => Format(\"{0} {1}\", x.Basic, x.Basic.Test)", propertyData.PropertyName); - Assert.AreEqual("RapidCMS.Core.Tests.PropertyMetadata.PropertyMetadataTests+BasicClass Test Value", propertyData.Getter(instance)); - Assert.AreEqual(typeof(string), propertyData.PropertyType); - } + var data = PropertyMetadataHelper.GetPropertyMetadata(func); - [Test] - public void BasicReadonlyProperty() - { - var instance = new BasicClass { Test = "Test Value" }; - Expression> func = (BasicClass x) => x.Test.ToLower(); - - var data = PropertyMetadataHelper.GetPropertyMetadata(func); + Assert.IsNotNull(data); + Assert.AreEqual("x => x.Basic.Test.ToLower()", data.PropertyName); + Assert.AreEqual("test value", data.Getter(instance)); + Assert.AreEqual(typeof(string), data.PropertyType); + Assert.AreEqual(typeof(ParentClass), data.ObjectType); - Assert.IsNotNull(data); - Assert.AreEqual("x => x.Test.ToLower()", data.PropertyName); - Assert.AreEqual("test value", data.Getter(instance)); - Assert.AreEqual(typeof(string), data.PropertyType); - Assert.AreEqual(typeof(BasicClass), data.ObjectType); - - Assert.IsNull(data as IFullPropertyMetadata); - } - - [Test] - public void BasicReadonlyNonStringProperty() - { - var instance = new BasicClass { Test = "Test Value", Id = 1 }; - Expression> func = (BasicClass x) => x.Id * 2; - - var data = PropertyMetadataHelper.GetPropertyMetadata(func); - - Assert.IsNotNull(data); - Assert.AreEqual("x => (x.Id * 2)", data.PropertyName); - Assert.AreEqual(2, data.Getter(instance)); - Assert.AreEqual(typeof(int), data.PropertyType); - Assert.AreEqual(typeof(BasicClass), data.ObjectType); + Assert.IsNull(data as IFullPropertyMetadata); + } - Assert.IsNull(data as IFullPropertyMetadata); - } + [Test] + public void NestedReadonlyNonStringProperty() + { + var instance = new ParentClass { Basic = new BasicClass { Test = "Test Value", Id = 1 } }; + Expression> func = (ParentClass x) => x.Basic.Id * 2; - [Test] - public void NestedReadonlyProperty() - { - var instance = new ParentClass { Basic = new BasicClass { Test = "Test Value" } }; - Expression> func = (ParentClass x) => x.Basic.Test.ToLower(); - - var data = PropertyMetadataHelper.GetPropertyMetadata(func); - - Assert.IsNotNull(data); - Assert.AreEqual("x => x.Basic.Test.ToLower()", data.PropertyName); - Assert.AreEqual("test value", data.Getter(instance)); - Assert.AreEqual(typeof(string), data.PropertyType); - Assert.AreEqual(typeof(ParentClass), data.ObjectType); + var data = PropertyMetadataHelper.GetPropertyMetadata(func); - Assert.IsNull(data as IFullPropertyMetadata); - } - - [Test] - public void NestedReadonlyNonStringProperty() - { - var instance = new ParentClass { Basic = new BasicClass { Test = "Test Value", Id = 1 } }; - Expression> func = (ParentClass x) => x.Basic.Id * 2; - - var data = PropertyMetadataHelper.GetPropertyMetadata(func); - - Assert.IsNotNull(data); - Assert.AreEqual("x => (x.Basic.Id * 2)", data.PropertyName); - Assert.AreEqual(2, data.Getter(instance)); - Assert.AreEqual(typeof(int), data.PropertyType); - Assert.AreEqual(typeof(ParentClass), data.ObjectType); - - Assert.IsNull(data as IFullPropertyMetadata); - } - - [Test] - public void BasicNullableProperty() - { - var instance = new BasicClass { NullableTest = "Test Value" }; - Expression> func = (BasicClass x) => x.NullableTest; - - var data = PropertyMetadataHelper.GetPropertyMetadata(func); - - Assert.IsNotNull(data); - Assert.AreEqual("NullableTest", data.PropertyName); - Assert.AreEqual("Test Value", data.Getter(instance)); - Assert.AreEqual(typeof(string), data.PropertyType); - Assert.AreEqual(typeof(BasicClass), data.ObjectType); - - Assert.IsNotNull(data as IFullPropertyMetadata); - } - - [Test] - public void BasicNullableNonStringProperty() - { - var instance = new BasicClass { NullableTest = "Test Value", Id = 1 }; - Expression> func = (BasicClass x) => x.NullableTest == null ? default(int?) : x.NullableTest.Length; - - var data = PropertyMetadataHelper.GetPropertyMetadata(func); - - Assert.IsNotNull(data); - Assert.AreEqual(10, data.Getter(instance)); - Assert.AreEqual(typeof(int?), data.PropertyType); - Assert.AreEqual(typeof(BasicClass), data.ObjectType); - - Assert.IsNull(data as IFullPropertyMetadata); - } - - [Test] - public void NestedNullableProperty() - { - var instance = new ParentClass { Basic = new BasicClass { NullableTest = "Test Value" } }; - Expression> func = (ParentClass x) => x.Basic.NullableTest; - - var data = PropertyMetadataHelper.GetPropertyMetadata(func); - - Assert.IsNotNull(data); - Assert.AreEqual("Basic.NullableTest", data.PropertyName); - Assert.AreEqual("Test Value", data.Getter(instance)); - Assert.AreEqual(typeof(string), data.PropertyType); - Assert.AreEqual(typeof(ParentClass), data.ObjectType); - - Assert.IsNotNull(data as IFullPropertyMetadata); - } - - [Test] - public void NestedNullableNonStringProperty() - { - var instance = new ParentClass { Basic = new BasicClass { NullableTest = "Test Value", Id = 1 } }; - Expression> func = (ParentClass x) => x.Basic == null ? default(int?) : x.Basic.NullableTest == null ? default : x.Basic.NullableTest.Length; - - var data = PropertyMetadataHelper.GetPropertyMetadata(func); - - Assert.IsNotNull(data); - Assert.AreEqual(10, data.Getter(instance)); - Assert.AreEqual(typeof(int?), data.PropertyType); - Assert.AreEqual(typeof(ParentClass), data.ObjectType); - - Assert.IsNull(data as IFullPropertyMetadata); - } - - [Test] - public void PropertyFingerprintDifference() - { - Expression> func1 = (ParentClass x) => x.Basic.Id * 2; - var data1 = PropertyMetadataHelper.GetPropertyMetadata(func1); - - Expression>> func2 = (ParentCollectionClass x) => x.Basics.Select(x => x.Id); - var data2 = PropertyMetadataHelper.GetPropertyMetadata(func2); - - Assert.IsNotNull(data1.Fingerprint); - Assert.IsNotNull(data2.Fingerprint); - Assert.AreNotEqual(data1.Fingerprint, data2.Fingerprint); - } - - [Test] - public void PropertyFingerprintEquality() - { - Expression>> func1 = (ParentCollectionClass z) => z.Basics.Select(q => q.Id); - var data1 = PropertyMetadataHelper.GetPropertyMetadata(func1); - - Expression>> func2 = (ParentCollectionClass x) => x.Basics.Select(x => x.Id); - var data2 = PropertyMetadataHelper.GetPropertyMetadata(func2); - - Assert.IsNotNull(data1.Fingerprint); - Assert.IsNotNull(data2.Fingerprint); - Assert.AreEqual(data1.Fingerprint, data2.Fingerprint); - } - - [Test] - public void PropertyFingerprintEquality2() - { - Expression>> func1 = (ParentCollectionClass z) => z.Basics.Select(q => q.Id); - var data1 = PropertyMetadataHelper.GetPropertyMetadata(func1); - - Expression>> func2 = (ParentCollectionClass x) => x.Basics2.Select(x => x.Id); - var data2 = PropertyMetadataHelper.GetPropertyMetadata(func2); - - Assert.IsNotNull(data1.Fingerprint); - Assert.IsNotNull(data2.Fingerprint); - Assert.AreNotEqual(data1.Fingerprint, data2.Fingerprint); - } - - [Test] - public void PropertyFingerprintEquality3() - { - Expression>> func1 = (ParentCollectionClass z) => z.Basics.Select(q => q.Id); - var data1 = PropertyMetadataHelper.GetPropertyMetadata(func1); - - Expression>> func2 = (ParentCollectionClass x) => x.Basics.Select(x => 1); - var data2 = PropertyMetadataHelper.GetPropertyMetadata(func2); - - Assert.IsNotNull(data1.Fingerprint); - Assert.IsNotNull(data2.Fingerprint); - Assert.AreNotEqual(data1.Fingerprint, data2.Fingerprint); - } - - [Test] - public void PropertyFingerprintEquality4() - { - Expression> func1 = (ParentClass z) => z.Basic.Test; - var data1 = PropertyMetadataHelper.GetPropertyMetadata(func1); - - var data2 = PropertyMetadataHelper.GetPropertyMetadata(typeof(ParentClass), - new[] { typeof(ParentClass).GetProperty(nameof(ParentClass.Basic)) }, typeof(BasicClass).GetProperty(nameof(BasicClass.Test))); - - var data3 = PropertyMetadataHelper.GetPropertyMetadata(typeof(ParentClass), "Basic.Test"); - - Assert.IsNotNull(data1.Fingerprint); - Assert.IsNotNull(data2.Fingerprint); - Assert.IsNotNull(data3.Fingerprint); - Assert.AreEqual(data1.Fingerprint, data2.Fingerprint); - Assert.AreEqual(data2.Fingerprint, data3.Fingerprint); - Assert.AreEqual(data1.Fingerprint, data3.Fingerprint); - } - - [Test] - public void SelfAsProperty() - { - var instance = new RecursiveClass { Name = "Self" }; - - Expression> func = x => x; - var data = PropertyMetadataHelper.GetPropertyMetadata(func); - - Assert.IsNotNull(data); - Assert.AreEqual("Self", ((RecursiveClass)data.Getter(instance)).Name); - } - - [Test] - public void ParentAsProperty() - { - var instance = new RecursiveClass { Name = "Self", Parent = new RecursiveClass { Name = "Parent" } }; - - Expression> func = x => x.Parent; - var data = PropertyMetadataHelper.GetPropertyMetadata(func); - - Assert.IsNotNull(data); - Assert.AreEqual("Parent", ((RecursiveClass)data.Getter(instance)).Name); - } - - [Test] - public void ParentAsPropertyViaInterface() - { - IRecursiveClass instance = new RecursiveClass { Name = "Self", Parent = new RecursiveClass { Name = "Parent" } }; - - Expression> func = x => x.Parent; - var data = PropertyMetadataHelper.GetPropertyMetadata(func); - - Assert.IsNotNull(data); - Assert.AreEqual("Parent", ((RecursiveClass)data.Getter(instance)).Name); - } - - [Test] - public void PropertyFromProperty() - { - var expected = "string"; - var instance = new BasicClass { Test = expected }; - - var property = typeof(BasicClass).GetProperty(nameof(BasicClass.Test)); - - var data = PropertyMetadataHelper.GetPropertyMetadata(instance.GetType(), property); - - Assert.IsNotNull(data); - Assert.AreEqual(nameof(BasicClass.Test), data.PropertyName); - Assert.AreEqual(expected, data.Getter(instance)); - } - - [Test] - public void PropertyFromProperties() - { - var expected = "string"; - var instance = new ParentClass { Basic = new BasicClass { Test = expected } }; - - var property1 = typeof(ParentClass).GetProperty(nameof(ParentClass.Basic)); - var property2 = typeof(BasicClass).GetProperty(nameof(BasicClass.Test)); - - var data = PropertyMetadataHelper.GetPropertyMetadata(instance.GetType(), new[] { property1 }, property2); - - Assert.IsNotNull(data); - Assert.AreEqual($"{nameof(ParentClass.Basic)}.{nameof(BasicClass.Test)}", data.PropertyName); - Assert.AreEqual(expected, data.Getter(instance)); - } - - [Test] - public void PropertyFromPropertyName() - { - var expected = "string"; - var instance = new BasicClass { Test = expected }; - - var data = PropertyMetadataHelper.GetPropertyMetadata(instance.GetType(), "Test"); - - Assert.IsNotNull(data); - Assert.AreEqual(nameof(BasicClass.Test), data.PropertyName); - Assert.AreEqual(expected, data.Getter(instance)); - } - - [Test] - public void PropertyFromNestedPropertyName() - { - var expected = "string"; - var instance = new ParentClass { Basic = new BasicClass { Test = expected } }; - - var data = PropertyMetadataHelper.GetPropertyMetadata(instance.GetType(), "Basic.Test"); - - Assert.IsNotNull(data); - Assert.AreEqual($"{nameof(ParentClass.Basic)}.{nameof(BasicClass.Test)}", data.PropertyName); - Assert.AreEqual(expected, data.Getter(instance)); - } - - [Test] - public void ReferenceTypePropertyCanHandleNull() - { - var instance = new ReferenceType { Data = "x" }; - - var dataProperty = (IFullPropertyMetadata)PropertyMetadataHelper.GetPropertyMetadata(x => x.Data); - - Assert.IsNotNull(dataProperty); - Assert.DoesNotThrow(() => dataProperty.Setter(instance, null)); - Assert.IsNull(instance.Data); - } - - [Test] - public void ValueTypePropertyCanHandleNull() - { - var instance = new ValueType { Data = 1 }; - - var dataProperty = (IFullPropertyMetadata)PropertyMetadataHelper.GetPropertyMetadata(x => x.Data); - - Assert.IsNotNull(dataProperty); - Assert.DoesNotThrow(() => dataProperty.Setter(instance, null)); - Assert.AreEqual(0, instance.Data); - } - - [Test] - public void NullableValueTypePropertyCanHandleNull() - { - var instance = new NullableValueType { Data = 1 }; - - var dataProperty = (IFullPropertyMetadata)PropertyMetadataHelper.GetPropertyMetadata(x => x.Data); - - Assert.IsNotNull(dataProperty); - Assert.DoesNotThrow(() => dataProperty.Setter(instance, null)); - Assert.IsNull(instance.Data); - } - - class BasicClass - { - public string Test { get; set; } - public int Id { get; set; } - public string? NullableTest { get; set; } - } - - - class ParentClass - { - public BasicClass Basic { get; set; } - } - - interface IRecursiveClass - { - public IRecursiveClass? Parent { get; } - } - - class RecursiveClass : IRecursiveClass - { - public RecursiveClass? Parent { get; set; } - public string Name { get; set; } - public string? NullableTest { get; set; } - - IRecursiveClass IRecursiveClass.Parent => Parent; - } - - class ParentCollectionClass - { - public ICollection Basics { get; set; } - public ICollection Basics2 { get; set; } - } - - class ReferenceType - { - public string Data { get; set; } - } - - class ValueType - { - public int Data { get; set; } - } - - class NullableValueType - { - public int? Data { get; set; } - } + Assert.IsNotNull(data); + Assert.AreEqual("x => (x.Basic.Id * 2)", data.PropertyName); + Assert.AreEqual(2, data.Getter(instance)); + Assert.AreEqual(typeof(int), data.PropertyType); + Assert.AreEqual(typeof(ParentClass), data.ObjectType); + + Assert.IsNull(data as IFullPropertyMetadata); + } + + [Test] + public void BasicNullableProperty() + { + var instance = new BasicClass { NullableTest = "Test Value" }; + Expression> func = (BasicClass x) => x.NullableTest; + + var data = PropertyMetadataHelper.GetPropertyMetadata(func); + + Assert.IsNotNull(data); + Assert.AreEqual("NullableTest", data.PropertyName); + Assert.AreEqual("Test Value", data.Getter(instance)); + Assert.AreEqual(typeof(string), data.PropertyType); + Assert.AreEqual(typeof(BasicClass), data.ObjectType); + + Assert.IsNotNull(data as IFullPropertyMetadata); + } + + [Test] + public void BasicNullableNonStringProperty() + { + var instance = new BasicClass { NullableTest = "Test Value", Id = 1 }; + Expression> func = (BasicClass x) => x.NullableTest == null ? default(int?) : x.NullableTest.Length; + + var data = PropertyMetadataHelper.GetPropertyMetadata(func); + + Assert.IsNotNull(data); + Assert.AreEqual(10, data.Getter(instance)); + Assert.AreEqual(typeof(int?), data.PropertyType); + Assert.AreEqual(typeof(BasicClass), data.ObjectType); + + Assert.IsNull(data as IFullPropertyMetadata); + } + + [Test] + public void NestedNullableProperty() + { + var instance = new ParentClass { Basic = new BasicClass { NullableTest = "Test Value" } }; + Expression> func = (ParentClass x) => x.Basic.NullableTest; + + var data = PropertyMetadataHelper.GetPropertyMetadata(func); + + Assert.IsNotNull(data); + Assert.AreEqual("Basic.NullableTest", data.PropertyName); + Assert.AreEqual("Test Value", data.Getter(instance)); + Assert.AreEqual(typeof(string), data.PropertyType); + Assert.AreEqual(typeof(ParentClass), data.ObjectType); + + Assert.IsNotNull(data as IFullPropertyMetadata); + } + + [Test] + public void NestedNullableNonStringProperty() + { + var instance = new ParentClass { Basic = new BasicClass { NullableTest = "Test Value", Id = 1 } }; + Expression> func = (ParentClass x) => x.Basic == null ? default(int?) : x.Basic.NullableTest == null ? default : x.Basic.NullableTest.Length; + + var data = PropertyMetadataHelper.GetPropertyMetadata(func); + + Assert.IsNotNull(data); + Assert.AreEqual(10, data.Getter(instance)); + Assert.AreEqual(typeof(int?), data.PropertyType); + Assert.AreEqual(typeof(ParentClass), data.ObjectType); + + Assert.IsNull(data as IFullPropertyMetadata); + } + + [Test] + public void PropertyFingerprintDifference() + { + Expression> func1 = (ParentClass x) => x.Basic.Id * 2; + var data1 = PropertyMetadataHelper.GetPropertyMetadata(func1); + + Expression>> func2 = (ParentCollectionClass x) => x.Basics.Select(x => x.Id); + var data2 = PropertyMetadataHelper.GetPropertyMetadata(func2); + + Assert.IsNotNull(data1.Fingerprint); + Assert.IsNotNull(data2.Fingerprint); + Assert.AreNotEqual(data1.Fingerprint, data2.Fingerprint); + } + + [Test] + public void PropertyFingerprintEquality() + { + Expression>> func1 = (ParentCollectionClass z) => z.Basics.Select(q => q.Id); + var data1 = PropertyMetadataHelper.GetPropertyMetadata(func1); + + Expression>> func2 = (ParentCollectionClass x) => x.Basics.Select(x => x.Id); + var data2 = PropertyMetadataHelper.GetPropertyMetadata(func2); + + Assert.IsNotNull(data1.Fingerprint); + Assert.IsNotNull(data2.Fingerprint); + Assert.AreEqual(data1.Fingerprint, data2.Fingerprint); + } + + [Test] + public void PropertyFingerprintEquality2() + { + Expression>> func1 = (ParentCollectionClass z) => z.Basics.Select(q => q.Id); + var data1 = PropertyMetadataHelper.GetPropertyMetadata(func1); + + Expression>> func2 = (ParentCollectionClass x) => x.Basics2.Select(x => x.Id); + var data2 = PropertyMetadataHelper.GetPropertyMetadata(func2); + + Assert.IsNotNull(data1.Fingerprint); + Assert.IsNotNull(data2.Fingerprint); + Assert.AreNotEqual(data1.Fingerprint, data2.Fingerprint); + } + + [Test] + public void PropertyFingerprintEquality3() + { + Expression>> func1 = (ParentCollectionClass z) => z.Basics.Select(q => q.Id); + var data1 = PropertyMetadataHelper.GetPropertyMetadata(func1); + + Expression>> func2 = (ParentCollectionClass x) => x.Basics.Select(x => 1); + var data2 = PropertyMetadataHelper.GetPropertyMetadata(func2); + + Assert.IsNotNull(data1.Fingerprint); + Assert.IsNotNull(data2.Fingerprint); + Assert.AreNotEqual(data1.Fingerprint, data2.Fingerprint); + } + + [Test] + public void PropertyFingerprintEquality4() + { + Expression> func1 = (ParentClass z) => z.Basic.Test; + var data1 = PropertyMetadataHelper.GetPropertyMetadata(func1); + + var data2 = PropertyMetadataHelper.GetPropertyMetadata(typeof(ParentClass), + new[] { typeof(ParentClass).GetProperty(nameof(ParentClass.Basic)) }, typeof(BasicClass).GetProperty(nameof(BasicClass.Test))); + + var data3 = PropertyMetadataHelper.GetPropertyMetadata(typeof(ParentClass), "Basic.Test"); + + Assert.IsNotNull(data1.Fingerprint); + Assert.IsNotNull(data2.Fingerprint); + Assert.IsNotNull(data3.Fingerprint); + Assert.AreEqual(data1.Fingerprint, data2.Fingerprint); + Assert.AreEqual(data2.Fingerprint, data3.Fingerprint); + Assert.AreEqual(data1.Fingerprint, data3.Fingerprint); + } + + [Test] + public void SelfAsProperty() + { + var instance = new RecursiveClass { Name = "Self" }; + + Expression> func = x => x; + var data = PropertyMetadataHelper.GetPropertyMetadata(func); + + Assert.IsNotNull(data); + Assert.AreEqual("Self", ((RecursiveClass)data.Getter(instance)).Name); + } + + [Test] + public void ParentAsProperty() + { + var instance = new RecursiveClass { Name = "Self", Parent = new RecursiveClass { Name = "Parent" } }; + + Expression> func = x => x.Parent; + var data = PropertyMetadataHelper.GetPropertyMetadata(func); + + Assert.IsNotNull(data); + Assert.AreEqual("Parent", ((RecursiveClass)data.Getter(instance)).Name); + } + + [Test] + public void ParentAsPropertyViaInterface() + { + IRecursiveClass instance = new RecursiveClass { Name = "Self", Parent = new RecursiveClass { Name = "Parent" } }; + + Expression> func = x => x.Parent; + var data = PropertyMetadataHelper.GetPropertyMetadata(func); + + Assert.IsNotNull(data); + Assert.AreEqual("Parent", ((RecursiveClass)data.Getter(instance)).Name); + } + + [Test] + public void PropertyFromProperty() + { + var expected = "string"; + var instance = new BasicClass { Test = expected }; + + var property = typeof(BasicClass).GetProperty(nameof(BasicClass.Test)); + + var data = PropertyMetadataHelper.GetPropertyMetadata(instance.GetType(), property); + + Assert.IsNotNull(data); + Assert.AreEqual(nameof(BasicClass.Test), data.PropertyName); + Assert.AreEqual(expected, data.Getter(instance)); + } + + [Test] + public void PropertyFromProperties() + { + var expected = "string"; + var instance = new ParentClass { Basic = new BasicClass { Test = expected } }; + + var property1 = typeof(ParentClass).GetProperty(nameof(ParentClass.Basic)); + var property2 = typeof(BasicClass).GetProperty(nameof(BasicClass.Test)); + + var data = PropertyMetadataHelper.GetPropertyMetadata(instance.GetType(), new[] { property1 }, property2); + + Assert.IsNotNull(data); + Assert.AreEqual($"{nameof(ParentClass.Basic)}.{nameof(BasicClass.Test)}", data.PropertyName); + Assert.AreEqual(expected, data.Getter(instance)); + } + + [Test] + public void PropertyFromPropertyName() + { + var expected = "string"; + var instance = new BasicClass { Test = expected }; + + var data = PropertyMetadataHelper.GetPropertyMetadata(instance.GetType(), "Test"); + + Assert.IsNotNull(data); + Assert.AreEqual(nameof(BasicClass.Test), data.PropertyName); + Assert.AreEqual(expected, data.Getter(instance)); + } + + [Test] + public void PropertyFromNestedPropertyName() + { + var expected = "string"; + var instance = new ParentClass { Basic = new BasicClass { Test = expected } }; + + var data = PropertyMetadataHelper.GetPropertyMetadata(instance.GetType(), "Basic.Test"); + + Assert.IsNotNull(data); + Assert.AreEqual($"{nameof(ParentClass.Basic)}.{nameof(BasicClass.Test)}", data.PropertyName); + Assert.AreEqual(expected, data.Getter(instance)); + } + + [Test] + public void ReferenceTypePropertyCanHandleNull() + { + var instance = new ReferenceType { Data = "x" }; + + var dataProperty = (IFullPropertyMetadata)PropertyMetadataHelper.GetPropertyMetadata(x => x.Data); + + Assert.IsNotNull(dataProperty); + Assert.DoesNotThrow(() => dataProperty.Setter(instance, null)); + Assert.IsNull(instance.Data); + } + + [Test] + public void ValueTypePropertyCanHandleNull() + { + var instance = new ValueType { Data = 1 }; + + var dataProperty = (IFullPropertyMetadata)PropertyMetadataHelper.GetPropertyMetadata(x => x.Data); + + Assert.IsNotNull(dataProperty); + Assert.DoesNotThrow(() => dataProperty.Setter(instance, null)); + Assert.AreEqual(0, instance.Data); + } + + [Test] + public void NullableValueTypePropertyCanHandleNull() + { + var instance = new NullableValueType { Data = 1 }; + + var dataProperty = (IFullPropertyMetadata)PropertyMetadataHelper.GetPropertyMetadata(x => x.Data); + + Assert.IsNotNull(dataProperty); + Assert.DoesNotThrow(() => dataProperty.Setter(instance, null)); + Assert.IsNull(instance.Data); + } + + class BasicClass + { + public string Test { get; set; } + public int Id { get; set; } + public string? NullableTest { get; set; } + } + + + class ParentClass + { + public BasicClass Basic { get; set; } + } + + interface IRecursiveClass + { + public IRecursiveClass? Parent { get; } + } + + class RecursiveClass : IRecursiveClass + { + public RecursiveClass? Parent { get; set; } + public string Name { get; set; } + public string? NullableTest { get; set; } + + IRecursiveClass IRecursiveClass.Parent => Parent; + } + + class ParentCollectionClass + { + public ICollection Basics { get; set; } + public ICollection Basics2 { get; set; } + } + + class ReferenceType + { + public string Data { get; set; } + } + + class ValueType + { + public int Data { get; set; } + } + + class NullableValueType + { + public int? Data { get; set; } } } diff --git a/src/RapidCMS.Core.Tests/RapidCMS.Core.Tests.csproj b/src/RapidCMS.Core.Tests/RapidCMS.Core.Tests.csproj index 564e77f3..a46cf74a 100644 --- a/src/RapidCMS.Core.Tests/RapidCMS.Core.Tests.csproj +++ b/src/RapidCMS.Core.Tests/RapidCMS.Core.Tests.csproj @@ -1,25 +1,37 @@  - - net6.0 - false - 10.0 - + + net6.0;net8.0 + false + 10.0 + - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + - - - + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + diff --git a/src/RapidCMS.Core.Tests/Services/Auth/AuthServiceTests.cs b/src/RapidCMS.Core.Tests/Services/Auth/AuthServiceTests.cs index 0949f7f8..7ef61ac2 100644 --- a/src/RapidCMS.Core.Tests/Services/Auth/AuthServiceTests.cs +++ b/src/RapidCMS.Core.Tests/Services/Auth/AuthServiceTests.cs @@ -17,126 +17,125 @@ using System.Linq; using System.Security.Claims; -namespace RapidCMS.Core.Tests.Services.Auth +namespace RapidCMS.Core.Tests.Services.Auth; + +public class AuthServiceTests { - public class AuthServiceTests + private IAuthService _subject = default!; + + private Mock _authorizationService = default!; + private Mock _buttonActionHandler = default!; + private Mock _buttonActionHandlerResolver = default!; + private Mock _authenticationStateProvider = default!; + private readonly ClaimsPrincipal _user = new ClaimsPrincipal(); + + [SetUp] + public void Setup() + { + _authorizationService = new Mock(); + + _buttonActionHandler = new Mock(); + _buttonActionHandlerResolver = new Mock(); + _buttonActionHandlerResolver + .Setup(x => x.GetButtonActionHandler(It.IsAny())) + .Returns(_buttonActionHandler.Object); + + var state = new AuthenticationState(_user); + + _authenticationStateProvider = new Mock(); + _authenticationStateProvider.Setup(x => x.GetAuthenticationStateAsync()).ReturnsAsync(state); + + _subject = new ServerSideAuthService( + _buttonActionHandlerResolver.Object, + _authorizationService.Object, + _authenticationStateProvider.Object); + } + + [TestCase(UsageType.Add, "Add")] + [TestCase(UsageType.Edit, "Update")] + [TestCase(UsageType.New, "Create")] + [TestCase(UsageType.Pick, "Add")] + [TestCase(UsageType.View, "Read")] + public void WhenCheckingIfUsageTypeIsAllowedOnEntity_AuthorizationServiceShouldBeConsulted(UsageType usageType, string requirement) + { + // arrange + var entity = new Mock(); + + // act + _subject.EnsureAuthorizedUserAsync(usageType, entity.Object); + + // assert + _authenticationStateProvider.Verify(x => x.GetAuthenticationStateAsync(), Times.Once()); + _authenticationStateProvider.VerifyNoOtherCalls(); + _authorizationService.Verify(x => x.AuthorizeAsync( + It.Is(x => x == _user), + It.Is(x => x == entity.Object), + It.Is>(x => (x.First() as OperationAuthorizationRequirement)!.Name == requirement))); + _authorizationService.VerifyNoOtherCalls(); + } + + [TestCase(UsageType.Add, "Add")] + [TestCase(UsageType.Edit, "Update")] + [TestCase(UsageType.New, "Create")] + [TestCase(UsageType.Pick, "Add")] + [TestCase(UsageType.View, "Read")] + public void WhenUsageTypeIsNotAllowed_AuthServiceShouldThrowUnauthorizedAccessException(UsageType usageType, string requirement) + { + // arrange + var entity = new Mock(); + _authorizationService + .Setup(x => x.AuthorizeAsync(It.IsAny(), It.IsAny(), It.IsAny>())) + .ReturnsAsync(AuthorizationResult.Failed()); + + // act & assert + Assert.ThrowsAsync(typeof(UnauthorizedAccessException), () => _subject.EnsureAuthorizedUserAsync(usageType, entity.Object)); + } + + [TestCase(UsageType.Add, "Add")] + [TestCase(UsageType.Edit, "Update")] + [TestCase(UsageType.New, "Create")] + [TestCase(UsageType.Pick, "Add")] + [TestCase(UsageType.View, "Read")] + public void WhenCheckingButtonIsAllowed_AuthorizationServiceShouldBeConsulted(UsageType usageType, string requirement) + { + // arrange + _buttonActionHandler.Setup(x => x.GetOperation(It.IsAny(), It.IsAny())).Returns(Operations.GetOperationForUsageType(usageType)); + var serviceProvider = new Mock(); + var entity = new Mock(); + var editContext = new FormEditContext("alias", "repo", "entity", entity.Object, default, usageType, new List(), serviceProvider.Object); + var button = new ButtonSetup(); + + // act + _subject.EnsureAuthorizedUserAsync(editContext, button); + + // assert + _authenticationStateProvider.Verify(x => x.GetAuthenticationStateAsync(), Times.Once()); + _authenticationStateProvider.VerifyNoOtherCalls(); + _authorizationService.Verify(x => x.AuthorizeAsync( + It.Is(x => x == _user), + It.Is(x => x == entity.Object), + It.Is>(x => (x.First() as OperationAuthorizationRequirement)!.Name == requirement))); + _authorizationService.VerifyNoOtherCalls(); + } + + [TestCase(UsageType.Add, "Add")] + [TestCase(UsageType.Edit, "Update")] + [TestCase(UsageType.New, "Create")] + [TestCase(UsageType.Pick, "Add")] + [TestCase(UsageType.View, "Read")] + public void WhenButtonIsNotAllowed_AuthServiceShouldThrowUnauthorizedAccessException(UsageType usageType, string requirement) { - private IAuthService _subject = default!; - - private Mock _authorizationService = default!; - private Mock _buttonActionHandler = default!; - private Mock _buttonActionHandlerResolver = default!; - private Mock _authenticationStateProvider = default!; - private readonly ClaimsPrincipal _user = new ClaimsPrincipal(); - - [SetUp] - public void Setup() - { - _authorizationService = new Mock(); - - _buttonActionHandler = new Mock(); - _buttonActionHandlerResolver = new Mock(); - _buttonActionHandlerResolver - .Setup(x => x.GetButtonActionHandler(It.IsAny())) - .Returns(_buttonActionHandler.Object); - - var state = new AuthenticationState(_user); - - _authenticationStateProvider = new Mock(); - _authenticationStateProvider.Setup(x => x.GetAuthenticationStateAsync()).ReturnsAsync(state); - - _subject = new ServerSideAuthService( - _buttonActionHandlerResolver.Object, - _authorizationService.Object, - _authenticationStateProvider.Object); - } - - [TestCase(UsageType.Add, "Add")] - [TestCase(UsageType.Edit, "Update")] - [TestCase(UsageType.New, "Create")] - [TestCase(UsageType.Pick, "Add")] - [TestCase(UsageType.View, "Read")] - public void WhenCheckingIfUsageTypeIsAllowedOnEntity_AuthorizationServiceShouldBeConsulted(UsageType usageType, string requirement) - { - // arrange - var entity = new Mock(); - - // act - _subject.EnsureAuthorizedUserAsync(usageType, entity.Object); - - // assert - _authenticationStateProvider.Verify(x => x.GetAuthenticationStateAsync(), Times.Once()); - _authenticationStateProvider.VerifyNoOtherCalls(); - _authorizationService.Verify(x => x.AuthorizeAsync( - It.Is(x => x == _user), - It.Is(x => x == entity.Object), - It.Is>(x => (x.First() as OperationAuthorizationRequirement)!.Name == requirement))); - _authorizationService.VerifyNoOtherCalls(); - } - - [TestCase(UsageType.Add, "Add")] - [TestCase(UsageType.Edit, "Update")] - [TestCase(UsageType.New, "Create")] - [TestCase(UsageType.Pick, "Add")] - [TestCase(UsageType.View, "Read")] - public void WhenUsageTypeIsNotAllowed_AuthServiceShouldThrowUnauthorizedAccessException(UsageType usageType, string requirement) - { - // arrange - var entity = new Mock(); - _authorizationService - .Setup(x => x.AuthorizeAsync(It.IsAny(), It.IsAny(), It.IsAny>())) - .ReturnsAsync(AuthorizationResult.Failed()); - - // act & assert - Assert.ThrowsAsync(typeof(UnauthorizedAccessException), () => _subject.EnsureAuthorizedUserAsync(usageType, entity.Object)); - } - - [TestCase(UsageType.Add, "Add")] - [TestCase(UsageType.Edit, "Update")] - [TestCase(UsageType.New, "Create")] - [TestCase(UsageType.Pick, "Add")] - [TestCase(UsageType.View, "Read")] - public void WhenCheckingButtonIsAllowed_AuthorizationServiceShouldBeConsulted(UsageType usageType, string requirement) - { - // arrange - _buttonActionHandler.Setup(x => x.GetOperation(It.IsAny(), It.IsAny())).Returns(Operations.GetOperationForUsageType(usageType)); - var serviceProvider = new Mock(); - var entity = new Mock(); - var editContext = new FormEditContext("alias", "repo", "entity", entity.Object, default, usageType, new List(), serviceProvider.Object); - var button = new ButtonSetup(); - - // act - _subject.EnsureAuthorizedUserAsync(editContext, button); - - // assert - _authenticationStateProvider.Verify(x => x.GetAuthenticationStateAsync(), Times.Once()); - _authenticationStateProvider.VerifyNoOtherCalls(); - _authorizationService.Verify(x => x.AuthorizeAsync( - It.Is(x => x == _user), - It.Is(x => x == entity.Object), - It.Is>(x => (x.First() as OperationAuthorizationRequirement)!.Name == requirement))); - _authorizationService.VerifyNoOtherCalls(); - } - - [TestCase(UsageType.Add, "Add")] - [TestCase(UsageType.Edit, "Update")] - [TestCase(UsageType.New, "Create")] - [TestCase(UsageType.Pick, "Add")] - [TestCase(UsageType.View, "Read")] - public void WhenButtonIsNotAllowed_AuthServiceShouldThrowUnauthorizedAccessException(UsageType usageType, string requirement) - { - // arrange - _buttonActionHandler.Setup(x => x.GetOperation(It.IsAny(), It.IsAny())).Returns(Operations.GetOperationForUsageType(usageType)); - var serviceProvider = new Mock(); - var entity = new Mock(); - var editContext = new FormEditContext("alias", "repo", "entity", entity.Object, default, usageType, new List(), serviceProvider.Object); - var button = new ButtonSetup(); - _authorizationService - .Setup(x => x.AuthorizeAsync(It.IsAny(), It.IsAny(), It.IsAny>())) - .ReturnsAsync(AuthorizationResult.Failed()); - - // act & assert - Assert.ThrowsAsync(typeof(UnauthorizedAccessException), () => _subject.EnsureAuthorizedUserAsync(editContext, button)); - } + // arrange + _buttonActionHandler.Setup(x => x.GetOperation(It.IsAny(), It.IsAny())).Returns(Operations.GetOperationForUsageType(usageType)); + var serviceProvider = new Mock(); + var entity = new Mock(); + var editContext = new FormEditContext("alias", "repo", "entity", entity.Object, default, usageType, new List(), serviceProvider.Object); + var button = new ButtonSetup(); + _authorizationService + .Setup(x => x.AuthorizeAsync(It.IsAny(), It.IsAny(), It.IsAny>())) + .ReturnsAsync(AuthorizationResult.Failed()); + + // act & assert + Assert.ThrowsAsync(typeof(UnauthorizedAccessException), () => _subject.EnsureAuthorizedUserAsync(editContext, button)); } } diff --git a/src/RapidCMS.Core.Tests/Services/Dispatchers/EntitiesInteractionDispatcherTests.cs b/src/RapidCMS.Core.Tests/Services/Dispatchers/EntitiesInteractionDispatcherTests.cs index 804de43f..adbd9fcd 100644 --- a/src/RapidCMS.Core.Tests/Services/Dispatchers/EntitiesInteractionDispatcherTests.cs +++ b/src/RapidCMS.Core.Tests/Services/Dispatchers/EntitiesInteractionDispatcherTests.cs @@ -19,122 +19,121 @@ using System.Collections.Generic; using System.Threading; -namespace RapidCMS.Core.Tests.Services.Dispatchers +namespace RapidCMS.Core.Tests.Services.Dispatchers; + +public class EntitiesInteractionDispatcherTests { - public class EntitiesInteractionDispatcherTests + private IInteractionDispatcher _subject = default!; + + private Mock _serviceProviderMock = default!; + + private Mock _navigationStateProvider = default!; + private Mock> _collectionResolver = default!; + private CollectionSetup _collection = default!; + private EntityVariantSetup _entityVariant = default!; + private Mock _repositoryResolver = default!; + private IConcurrencyService _concurrencyService = default!; + private Mock _buttonInteraction = default!; + private Mock _editContextFactory = default!; + private Mock _mediator = default!; + + [SetUp] + public void Setup() { - private IInteractionDispatcher _subject = default!; - - private Mock _serviceProviderMock = default!; - - private Mock _navigationStateProvider = default!; - private Mock> _collectionResolver = default!; - private CollectionSetup _collection = default!; - private EntityVariantSetup _entityVariant = default!; - private Mock _repositoryResolver = default!; - private IConcurrencyService _concurrencyService = default!; - private Mock _buttonInteraction = default!; - private Mock _editContextFactory = default!; - private Mock _mediator = default!; - - [SetUp] - public void Setup() + _serviceProviderMock = new Mock(); + + _navigationStateProvider = new Mock(); + _entityVariant = new EntityVariantSetup("ev", "icon", typeof(IEntity), "alias"); + _collection = new CollectionSetup("icon", "color", "name", "alias", "repo") { - _serviceProviderMock = new Mock(); - - _navigationStateProvider = new Mock(); - _entityVariant = new EntityVariantSetup("ev", "icon", typeof(IEntity), "alias"); - _collection = new CollectionSetup("icon", "color", "name", "alias", "repo") - { - EntityVariant = _entityVariant - }; - _collectionResolver = new Mock>(); - _collectionResolver - .Setup(x => x.ResolveSetupAsync(It.IsAny())) - .ReturnsAsync(_collection); - - _repositoryResolver = new Mock(); - _concurrencyService = new ConcurrencyService(new SemaphoreSlim(1, 1)); - _buttonInteraction = new Mock(); - _editContextFactory = new Mock(); - _mediator = new Mock(); - - _subject = new EntitiesInteractionDispatcher( - _navigationStateProvider.Object, - _collectionResolver.Object, - _repositoryResolver.Object, - _concurrencyService, - _buttonInteraction.Object, - _editContextFactory.Object, - _mediator.Object); - } - - [TestCase("alias1")] - [TestCase("alias2")] - public void WhenInvokingInteraction_ThenCollectionShouldBeResolvedUsingGivenCollectionAlias(string alias) + EntityVariant = _entityVariant + }; + _collectionResolver = new Mock>(); + _collectionResolver + .Setup(x => x.ResolveSetupAsync(It.IsAny())) + .ReturnsAsync(_collection); + + _repositoryResolver = new Mock(); + _concurrencyService = new ConcurrencyService(new SemaphoreSlim(1, 1)); + _buttonInteraction = new Mock(); + _editContextFactory = new Mock(); + _mediator = new Mock(); + + _subject = new EntitiesInteractionDispatcher( + _navigationStateProvider.Object, + _collectionResolver.Object, + _repositoryResolver.Object, + _concurrencyService, + _buttonInteraction.Object, + _editContextFactory.Object, + _mediator.Object); + } + + [TestCase("alias1")] + [TestCase("alias2")] + public void WhenInvokingInteraction_ThenCollectionShouldBeResolvedUsingGivenCollectionAlias(string alias) + { + // arrange + var request = new PersistEntitiesRequestModel { - // arrange - var request = new PersistEntitiesRequestModel - { - ListContext = new ListContext(alias, new FormEditContext(alias, alias, alias, new DefaultEntityVariant(), default, UsageType.Add, new List(), _serviceProviderMock.Object), default, UsageType.Add, default, _serviceProviderMock.Object) - }; - - // act - _subject.InvokeAsync(request); - - // assert - _collectionResolver.Verify(x => x.ResolveSetupAsync(It.Is(x => x == alias))); - } - - [TestCase("alias1")] - [TestCase("alias2")] - public void WhenInvokingInteraction_ThenRepositoryShouldBeResolvedByGivenCollection(string alias) + ListContext = new ListContext(alias, new FormEditContext(alias, alias, alias, new DefaultEntityVariant(), default, UsageType.Add, new List(), _serviceProviderMock.Object), default, UsageType.Add, default, _serviceProviderMock.Object) + }; + + // act + _subject.InvokeAsync(request); + + // assert + _collectionResolver.Verify(x => x.ResolveSetupAsync(It.Is(x => x == alias))); + } + + [TestCase("alias1")] + [TestCase("alias2")] + public void WhenInvokingInteraction_ThenRepositoryShouldBeResolvedByGivenCollection(string alias) + { + // arrange + var request = new PersistEntitiesRequestModel { - // arrange - var request = new PersistEntitiesRequestModel - { - ListContext = new ListContext(alias, new FormEditContext(alias, alias, alias, new DefaultEntityVariant(), default, UsageType.Add, new List(), _serviceProviderMock.Object), default, UsageType.Add, default, _serviceProviderMock.Object) - }; - - // act - _subject.InvokeAsync(request); - - // assert - _repositoryResolver.Verify(x => x.GetRepository(It.Is(x => x == _collection))); - } - - [TestCase("alias1")] - [TestCase("alias2")] - public void WhenInvokingInteraction_ThenCrudTypeShouldBeDeterminedUsingButtonInteraction(string alias) + ListContext = new ListContext(alias, new FormEditContext(alias, alias, alias, new DefaultEntityVariant(), default, UsageType.Add, new List(), _serviceProviderMock.Object), default, UsageType.Add, default, _serviceProviderMock.Object) + }; + + // act + _subject.InvokeAsync(request); + + // assert + _repositoryResolver.Verify(x => x.GetRepository(It.Is(x => x == _collection))); + } + + [TestCase("alias1")] + [TestCase("alias2")] + public void WhenInvokingInteraction_ThenCrudTypeShouldBeDeterminedUsingButtonInteraction(string alias) + { + // arrange + var request = new PersistEntitiesRequestModel { - // arrange - var request = new PersistEntitiesRequestModel - { - ListContext = new ListContext(alias, new FormEditContext(alias, alias, alias, new DefaultEntityVariant(), default, UsageType.Add, new List(), _serviceProviderMock.Object), default, UsageType.Add, default, _serviceProviderMock.Object) - }; - - // act - _subject.InvokeAsync(request); - - // assert - _buttonInteraction.Verify(x => x.ValidateButtonInteractionAsync(It.Is(x => x == request))); - } - - [TestCase("alias1")] - [TestCase("alias2")] - public void WhenInvokingInteraction_ThenCompletedInteractionShouldBeFlaggedToButtonInteraction(string alias) + ListContext = new ListContext(alias, new FormEditContext(alias, alias, alias, new DefaultEntityVariant(), default, UsageType.Add, new List(), _serviceProviderMock.Object), default, UsageType.Add, default, _serviceProviderMock.Object) + }; + + // act + _subject.InvokeAsync(request); + + // assert + _buttonInteraction.Verify(x => x.ValidateButtonInteractionAsync(It.Is(x => x == request))); + } + + [TestCase("alias1")] + [TestCase("alias2")] + public void WhenInvokingInteraction_ThenCompletedInteractionShouldBeFlaggedToButtonInteraction(string alias) + { + // arrange + var request = new PersistEntitiesRequestModel { - // arrange - var request = new PersistEntitiesRequestModel - { - ListContext = new ListContext(alias, new FormEditContext(alias, alias, alias, new DefaultEntityVariant(), default, UsageType.Add, new List(), _serviceProviderMock.Object), default, UsageType.Add, default, _serviceProviderMock.Object) - }; - - // act - _subject.InvokeAsync(request); - - // assert - _buttonInteraction.Verify(x => x.CompleteButtonInteractionAsync(It.Is(x => x == request))); - } + ListContext = new ListContext(alias, new FormEditContext(alias, alias, alias, new DefaultEntityVariant(), default, UsageType.Add, new List(), _serviceProviderMock.Object), default, UsageType.Add, default, _serviceProviderMock.Object) + }; + + // act + _subject.InvokeAsync(request); + + // assert + _buttonInteraction.Verify(x => x.CompleteButtonInteractionAsync(It.Is(x => x == request))); } } diff --git a/src/RapidCMS.Core.Tests/Services/Dispatchers/EntityInteractionDispatcherTests.cs b/src/RapidCMS.Core.Tests/Services/Dispatchers/EntityInteractionDispatcherTests.cs index 0f25632f..f705910e 100644 --- a/src/RapidCMS.Core.Tests/Services/Dispatchers/EntityInteractionDispatcherTests.cs +++ b/src/RapidCMS.Core.Tests/Services/Dispatchers/EntityInteractionDispatcherTests.cs @@ -20,145 +20,144 @@ using System.Collections.Generic; using System.Threading; -namespace RapidCMS.Core.Tests.Services.Dispatchers +namespace RapidCMS.Core.Tests.Services.Dispatchers; + +public class EntityInteractionDispatcherTests { - public class EntityInteractionDispatcherTests + private IInteractionDispatcher _subject = default!; + + private Mock _serviceProviderMock = default!; + + private Mock _navigationStateProvider = default!; + private Mock> _collectionResolver = default!; + private CollectionSetup _collection = default!; + private EntityVariantSetup _entityVariant = default!; + private Mock _repositoryResolver = default!; + private IConcurrencyService _concurrencyService = default!; + private Mock _buttonInteraction = default!; + private Mock _editContextFactory = default!; + private Mock _mediator = default!; + + [SetUp] + public void Setup() { - private IInteractionDispatcher _subject = default!; - - private Mock _serviceProviderMock = default!; - - private Mock _navigationStateProvider = default!; - private Mock> _collectionResolver = default!; - private CollectionSetup _collection = default!; - private EntityVariantSetup _entityVariant = default!; - private Mock _repositoryResolver = default!; - private IConcurrencyService _concurrencyService = default!; - private Mock _buttonInteraction = default!; - private Mock _editContextFactory = default!; - private Mock _mediator = default!; - - [SetUp] - public void Setup() + _serviceProviderMock = new Mock(); + + _navigationStateProvider = new Mock(); + + _entityVariant = new EntityVariantSetup("ev", "icon", typeof(IEntity), "alias"); + _collection = new CollectionSetup("icon", "color", "name", "alias", "repo") { - _serviceProviderMock = new Mock(); - - _navigationStateProvider = new Mock(); - - _entityVariant = new EntityVariantSetup("ev", "icon", typeof(IEntity), "alias"); - _collection = new CollectionSetup("icon", "color", "name", "alias", "repo") - { - EntityVariant = _entityVariant - }; - _collectionResolver = new Mock>(); - _collectionResolver - .Setup(x => x.ResolveSetupAsync(It.IsAny())) - .ReturnsAsync(_collection); - - _repositoryResolver = new Mock(); - _concurrencyService = new ConcurrencyService(new SemaphoreSlim(1, 1)); - _buttonInteraction = new Mock(); - _editContextFactory = new Mock(); - _mediator = new Mock(); - - _subject = new EntityInteractionDispatcher( - _navigationStateProvider.Object, - _collectionResolver.Object, - _repositoryResolver.Object, - _concurrencyService, - _buttonInteraction.Object, - _editContextFactory.Object, - _mediator.Object); - } - - [TestCase("alias1")] - [TestCase("alias2")] - public void WhenInvokingInteraction_ThenCollectionShouldBeResolvedUsingGivenCollectionAlias(string alias) + EntityVariant = _entityVariant + }; + _collectionResolver = new Mock>(); + _collectionResolver + .Setup(x => x.ResolveSetupAsync(It.IsAny())) + .ReturnsAsync(_collection); + + _repositoryResolver = new Mock(); + _concurrencyService = new ConcurrencyService(new SemaphoreSlim(1, 1)); + _buttonInteraction = new Mock(); + _editContextFactory = new Mock(); + _mediator = new Mock(); + + _subject = new EntityInteractionDispatcher( + _navigationStateProvider.Object, + _collectionResolver.Object, + _repositoryResolver.Object, + _concurrencyService, + _buttonInteraction.Object, + _editContextFactory.Object, + _mediator.Object); + } + + [TestCase("alias1")] + [TestCase("alias2")] + public void WhenInvokingInteraction_ThenCollectionShouldBeResolvedUsingGivenCollectionAlias(string alias) + { + // arrange + var request = new PersistEntityRequestModel { - // arrange - var request = new PersistEntityRequestModel - { - EditContext = new FormEditContext(alias, alias, alias, new DefaultEntityVariant(), default, UsageType.Add, new List(), _serviceProviderMock.Object) - }; - - // act - _subject.InvokeAsync(request); - - // assert - _collectionResolver.Verify(x => x.ResolveSetupAsync(It.Is(x => x == alias))); - } - - [TestCase("alias1")] - [TestCase("alias2")] - public void WhenInvokingInteraction_ThenRepositoryShouldBeResolvedByGivenCollection(string alias) + EditContext = new FormEditContext(alias, alias, alias, new DefaultEntityVariant(), default, UsageType.Add, new List(), _serviceProviderMock.Object) + }; + + // act + _subject.InvokeAsync(request); + + // assert + _collectionResolver.Verify(x => x.ResolveSetupAsync(It.Is(x => x == alias))); + } + + [TestCase("alias1")] + [TestCase("alias2")] + public void WhenInvokingInteraction_ThenRepositoryShouldBeResolvedByGivenCollection(string alias) + { + // arrange + var request = new PersistEntityRequestModel { - // arrange - var request = new PersistEntityRequestModel - { - EditContext = new FormEditContext(alias, alias, alias, new DefaultEntityVariant(), default, UsageType.Add, new List(), _serviceProviderMock.Object) - }; - - // act - _subject.InvokeAsync(request); - - // assert - _repositoryResolver.Verify(x => x.GetRepository(It.Is(x => x == _collection))); - } - - [TestCase("alias1")] - [TestCase("alias2")] - public void WhenInvokingInteraction_ThenCrudTypeShouldBeDeterminedUsingButtonInteraction(string alias) + EditContext = new FormEditContext(alias, alias, alias, new DefaultEntityVariant(), default, UsageType.Add, new List(), _serviceProviderMock.Object) + }; + + // act + _subject.InvokeAsync(request); + + // assert + _repositoryResolver.Verify(x => x.GetRepository(It.Is(x => x == _collection))); + } + + [TestCase("alias1")] + [TestCase("alias2")] + public void WhenInvokingInteraction_ThenCrudTypeShouldBeDeterminedUsingButtonInteraction(string alias) + { + // arrange + var request = new PersistEntityRequestModel { - // arrange - var request = new PersistEntityRequestModel - { - EditContext = new FormEditContext(alias, alias, alias, new DefaultEntityVariant(), default, UsageType.Add, new List(), _serviceProviderMock.Object) - }; - - // act - _subject.InvokeAsync(request); - - // assert - _buttonInteraction.Verify(x => x.ValidateButtonInteractionAsync(It.Is(x => x == request))); - } - - [TestCase("alias1")] - [TestCase("alias2")] - public void WhenInvokingInteraction_ThenCompletedInteractionShouldBeFlaggedToButtonInteraction(string alias) + EditContext = new FormEditContext(alias, alias, alias, new DefaultEntityVariant(), default, UsageType.Add, new List(), _serviceProviderMock.Object) + }; + + // act + _subject.InvokeAsync(request); + + // assert + _buttonInteraction.Verify(x => x.ValidateButtonInteractionAsync(It.Is(x => x == request))); + } + + [TestCase("alias1")] + [TestCase("alias2")] + public void WhenInvokingInteraction_ThenCompletedInteractionShouldBeFlaggedToButtonInteraction(string alias) + { + // arrange + var request = new PersistEntityRequestModel { - // arrange - var request = new PersistEntityRequestModel - { - EditContext = new FormEditContext(alias, alias, alias, new DefaultEntityVariant(), default, UsageType.Add, new List(), _serviceProviderMock.Object) - }; - - // act - _subject.InvokeAsync(request); - - // assert - _buttonInteraction.Verify(x => x.CompleteButtonInteractionAsync(It.Is(x => x == request))); - } - - [TestCase(CrudType.View, PageType.Node, UsageType.View)] - [TestCase(CrudType.Edit, PageType.Node, UsageType.Edit)] - public void WhenInvokingInteraction_ThenNavigationStateShouldBeDeterminedByButtonCrudType(CrudType crudType, PageType pageType, UsageType usageType) + EditContext = new FormEditContext(alias, alias, alias, new DefaultEntityVariant(), default, UsageType.Add, new List(), _serviceProviderMock.Object) + }; + + // act + _subject.InvokeAsync(request); + + // assert + _buttonInteraction.Verify(x => x.CompleteButtonInteractionAsync(It.Is(x => x == request))); + } + + [TestCase(CrudType.View, PageType.Node, UsageType.View)] + [TestCase(CrudType.Edit, PageType.Node, UsageType.Edit)] + public void WhenInvokingInteraction_ThenNavigationStateShouldBeDeterminedByButtonCrudType(CrudType crudType, PageType pageType, UsageType usageType) + { + // arrange + var request = new PersistEntityRequestModel { - // arrange - var request = new PersistEntityRequestModel - { - EditContext = new FormEditContext("alias", "alias", "alias", new DefaultEntityVariant(), default, UsageType.Add, new List(), _serviceProviderMock.Object) - }; - _buttonInteraction.Setup(x => x.ValidateButtonInteractionAsync(It.IsAny())).ReturnsAsync(crudType); - - // act - _subject.InvokeAsync(request); - - // assert - _navigationStateProvider.Verify( - x => x.AppendNavigationState(null, - It.Is(state => - state.PageType == pageType && - state.UsageType == usageType))); - } + EditContext = new FormEditContext("alias", "alias", "alias", new DefaultEntityVariant(), default, UsageType.Add, new List(), _serviceProviderMock.Object) + }; + _buttonInteraction.Setup(x => x.ValidateButtonInteractionAsync(It.IsAny())).ReturnsAsync(crudType); + + // act + _subject.InvokeAsync(request); + + // assert + _navigationStateProvider.Verify( + x => x.AppendNavigationState(null, + It.Is(state => + state.PageType == pageType && + state.UsageType == usageType))); } } diff --git a/src/RapidCMS.Core.Tests/Services/Dispatchers/GetEntitiesDispatcherTests.cs b/src/RapidCMS.Core.Tests/Services/Dispatchers/GetEntitiesDispatcherTests.cs index 0a427c7c..a3416769 100644 --- a/src/RapidCMS.Core.Tests/Services/Dispatchers/GetEntitiesDispatcherTests.cs +++ b/src/RapidCMS.Core.Tests/Services/Dispatchers/GetEntitiesDispatcherTests.cs @@ -19,247 +19,246 @@ using System.Threading; using System.Threading.Tasks; -namespace RapidCMS.Core.Tests.Services.Dispatchers +namespace RapidCMS.Core.Tests.Services.Dispatchers; + +public class GetEntitiesDispatcherTests { - public class GetEntitiesDispatcherTests + private IPresentationDispatcher _subject = default!; + + private Mock> _collectionResolver = default!; + private Mock _repository = default!; + private Mock _repositoryResolver = default!; + private Mock _dataViewResolver = default!; + private Mock _parentService = default!; + private IConcurrencyService _concurrencyService = default!; + private Mock _authService = default!; + private Mock _serviceProvider = default!; + + private IEntity _protoEntity = new DefaultEntityVariant(); + private IEnumerable _entities = new List { - private IPresentationDispatcher _subject = default!; - - private Mock> _collectionResolver = default!; - private Mock _repository = default!; - private Mock _repositoryResolver = default!; - private Mock _dataViewResolver = default!; - private Mock _parentService = default!; - private IConcurrencyService _concurrencyService = default!; - private Mock _authService = default!; - private Mock _serviceProvider = default!; - - private IEntity _protoEntity = new DefaultEntityVariant(); - private IEnumerable _entities = new List - { - new DefaultEntityVariant(), - new DefaultEntityVariant(), - new DefaultEntityVariant() - }; - - [SetUp] - public void Setup() - { - _collectionResolver = new Mock>(); - _collectionResolver - .Setup(x => x.ResolveSetupAsync(It.IsAny())) - .ReturnsAsync((string alias) => - new CollectionSetup(default, - default, - "name", - alias, - $"repo-{alias}") - { - EntityVariant = new EntityVariantSetup("default", default, typeof(DefaultEntityVariant), "alias"), - SubEntityVariants = new List - { - new EntityVariantSetup("sub1", default, typeof(SubEntityVariant1), "sub1"), - new EntityVariantSetup("sub3", default, typeof(SubEntityVariant3), "sub2"), - new EntityVariantSetup("sub2", default, typeof(SubEntityVariant2), "sub3") - } - }); - - _repository = new Mock(); - _repository.Setup(x => x.NewAsync(It.IsAny(), It.IsAny())).ReturnsAsync(_protoEntity); - _repository.Setup(x => x.GetAllAsync(It.IsAny(), It.IsAny())).ReturnsAsync(_entities); - _repository.Setup(x => x.GetAllNonRelatedAsync(It.IsAny(), It.IsAny())).ReturnsAsync(_entities); - _repository.Setup(x => x.GetAllRelatedAsync(It.IsAny(), It.IsAny())).ReturnsAsync(_entities); - - _repositoryResolver = new Mock(); - _repositoryResolver - .Setup(x => x.GetRepository(It.IsAny())) - .Returns(_repository.Object); - - _dataViewResolver = new Mock(); - - _parentService = new Mock(); - _parentService - .Setup(x => x.GetParentAsync(It.IsAny())) - .ReturnsAsync((ParentPath path) => + new DefaultEntityVariant(), + new DefaultEntityVariant(), + new DefaultEntityVariant() + }; + + [SetUp] + public void Setup() + { + _collectionResolver = new Mock>(); + _collectionResolver + .Setup(x => x.ResolveSetupAsync(It.IsAny())) + .ReturnsAsync((string alias) => + new CollectionSetup(default, + default, + "name", + alias, + $"repo-{alias}") { - var mock = new Mock(); - mock.Setup(x => x.GetParentPath()).Returns(path); - return mock.Object; + EntityVariant = new EntityVariantSetup("default", default, typeof(DefaultEntityVariant), "alias"), + SubEntityVariants = new List + { + new EntityVariantSetup("sub1", default, typeof(SubEntityVariant1), "sub1"), + new EntityVariantSetup("sub3", default, typeof(SubEntityVariant3), "sub2"), + new EntityVariantSetup("sub2", default, typeof(SubEntityVariant2), "sub3") + } }); - _concurrencyService = new ConcurrencyService(new SemaphoreSlim(1, 1)); - - _authService = new Mock(); - _serviceProvider = new Mock(); - - - _subject = new GetEntitiesDispatcher( - _collectionResolver.Object, - _repositoryResolver.Object, - _dataViewResolver.Object, - _parentService.Object, - _concurrencyService, - _authService.Object, - _serviceProvider.Object); - } - - [TestCase("collectionAlias1")] - [TestCase("collectionAlias2")] - public void WhenRequestHasCollectionAlias_ThenCollectionResolverIsUsedToFetchCollectionWithThatAlias(string alias) - { - // act - _subject.GetAsync(new GetEntitiesRequestModel { UsageType = UsageType.New, CollectionAlias = alias }); - - // assert - _collectionResolver.Verify(x => x.ResolveSetupAsync(It.Is(x => x == alias))); - } - - [TestCase("collectionAlias1")] - [TestCase("collectionAlias2")] - public void WhenRequestHasCollectionAlias_ThenRepositoryResolverIsUsedToFetchRepositoryWithCollectionThatHasThatAlias(string alias) - { - // act - _subject.GetAsync(new GetEntitiesRequestModel { UsageType = UsageType.New, CollectionAlias = alias }); - - // assert - _repositoryResolver.Verify(x => x.GetRepository(It.Is(x => x.Alias == alias))); - } - - [TestCase(default(string))] - [TestCase("test:1")] - public void WhenRequestHasParent_ThenParentServiceShouldBeUsedToFetchParent(string path) - { - // act - _subject.GetAsync(new GetEntitiesOfParentRequestModel { UsageType = UsageType.New, CollectionAlias = "", ParentPath = ParentPath.TryParse(path) }); - - // assert - _parentService.Verify(x => x.GetParentAsync(It.Is(x => (x == null && path == null) || x!.ToPathString() == path)), Times.Once()); - } - - [Test] - public void WhenRequestMade_ThenRepositoryShouldBeUsedToFetchProtoEntity() - { - // act - _subject.GetAsync(new GetEntitiesRequestModel { CollectionAlias = "name" }); - - // assert - _repository.Verify(x => x.NewAsync(It.IsAny(), It.IsAny())); - } - - [TestCase(UsageType.Add)] - [TestCase(UsageType.Edit)] - [TestCase(UsageType.List)] - [TestCase(UsageType.New)] - [TestCase(UsageType.Node)] - [TestCase(UsageType.Pick)] - [TestCase(UsageType.Reordered)] - [TestCase(UsageType.View)] - public void WhenRequestMade_ThenAuthServiceShouldBeUsedToValidateActionAgainstProtoEntity(UsageType usageType) - { - // act - _subject.GetAsync(new GetEntitiesRequestModel { CollectionAlias = "name", UsageType = usageType }); - - // assert - _authService.Verify(x => x.EnsureAuthorizedUserAsync(It.Is(x => x == usageType), It.Is(x => x == _protoEntity))); - } - - [TestCase(UsageType.Edit)] - [TestCase(UsageType.New)] - [TestCase(UsageType.Node)] - [TestCase(UsageType.Pick)] - [TestCase(UsageType.Reordered)] - [TestCase(UsageType.View)] - public void WhenRequestingToGetEntitiesOfParent_ThenRepositoryShouldBeQueriedToGetEntities(UsageType usageType) - { - // act - var parentPath = ParentPath.TryParse("path:123"); - var view = new View(); - _subject.GetAsync(new GetEntitiesOfParentRequestModel { UsageType = usageType, View = view, CollectionAlias = "alias", ParentPath = parentPath }); - - // assert - _repository.Verify(x => x.GetAllAsync(It.Is(x => x.Parent.GetParentPath()!.ToPathString() == parentPath!.ToPathString()), It.Is(x => x == view))); - } - - [TestCase(UsageType.Add)] - public void WhenRequestingToGetEntitiesToAddToTheRelatedEntity_ThenRepositoryShouldBeQueriedToGetNonRelatedEntities(UsageType usageType) - { - // act - var related = new RelatedEntity(default, new DefaultEntityVariant(), "alias"); - var view = new View(); - _subject.GetAsync(new GetEntitiesOfRelationRequestModel { UsageType = usageType, View = view, CollectionAlias = "alias", Related = related }); - - // assert - _repository.Verify(x => x.GetAllNonRelatedAsync(It.Is(x => x.Related == related), It.Is(x => x == view))); - } - - [TestCase(UsageType.Edit)] - [TestCase(UsageType.New)] - [TestCase(UsageType.Node)] - [TestCase(UsageType.Pick)] - [TestCase(UsageType.Reordered)] - [TestCase(UsageType.View)] - public void WhenRequestingToGetEntitiesRelatedToRelatedEntity_ThenRepositoryShouldBeQueriedToGetNonRelatedEntities(UsageType usageType) - { - // act - var related = new RelatedEntity(default, new DefaultEntityVariant(), "alias"); - var view = new View(); - _subject.GetAsync(new GetEntitiesOfRelationRequestModel { UsageType = usageType, View = view, CollectionAlias = "alias", Related = related }); - - // assert - _repository.Verify(x => x.GetAllRelatedAsync(It.Is(x => x.Related == related), It.Is(x => x == view))); - } - - [TestCase(UsageType.List)] - [TestCase(UsageType.NotRoot)] - [TestCase(UsageType.Root)] - public void WhenRequestingToPerformUnsupportedAction_ThenInvalidOperationShouldBeThrown(UsageType usageType) - { - // act & assert - Assert.ThrowsAsync(typeof(InvalidOperationException), () => _subject.GetAsync(new GetEntitiesRequestModel { UsageType = usageType, CollectionAlias = "alias" })); - } - - [TestCase(UsageType.Edit, UsageType.Node | UsageType.Edit, UsageType.Node | UsageType.Edit, UsageType.Node | UsageType.Edit, null)] - [TestCase(UsageType.New, UsageType.Node | UsageType.New, UsageType.Node | UsageType.Edit, UsageType.Node | UsageType.Edit, UsageType.Node | UsageType.Edit)] - [TestCase(UsageType.View, UsageType.Node | UsageType.View, UsageType.Node | UsageType.View, UsageType.Node | UsageType.View, null)] - public async Task WhenRequestingToGetEntitiesOfParent_ThenListOfEntitiesShouldBeReturnedWithCorrectUsageTypesAsync(UsageType usageType, UsageType expectedUsageTypes1, UsageType expectedUsageTypes2, UsageType expectedUsageTypes3, UsageType expectedUsageTypes4) - { - // act - var parentPath = ParentPath.TryParse("path:123"); - var view = new View(); - var response = await _subject.GetAsync(new GetEntitiesOfParentRequestModel { UsageType = usageType, View = view, CollectionAlias = "alias", ParentPath = parentPath }); - - // assert - Assert.AreEqual(expectedUsageTypes1, response.EditContexts.ElementAtOrDefault(0)?.UsageType ?? 0); - Assert.AreEqual(expectedUsageTypes2, response.EditContexts.ElementAtOrDefault(1)?.UsageType ?? 0); - Assert.AreEqual(expectedUsageTypes3, response.EditContexts.ElementAtOrDefault(2)?.UsageType ?? 0); - Assert.AreEqual(expectedUsageTypes4, response.EditContexts.ElementAtOrDefault(3)?.UsageType ?? 0); - } - - [TestCase(UsageType.Add, UsageType.Node | UsageType.Pick, UsageType.Node | UsageType.Pick, UsageType.Node | UsageType.Pick, null)] - public async Task WhenRequestingToGetEntitiesRelatedToRelatedEntity_ThenListOfEntitiesShouldBeReturnedWithCorrectUsageTypesAsync(UsageType usageType, UsageType expectedUsageTypes1, UsageType expectedUsageTypes2, UsageType expectedUsageTypes3, UsageType expectedUsageTypes4) - { - // act - var related = new RelatedEntity(default, new DefaultEntityVariant(), "alias"); - var view = new View(); - var response = await _subject.GetAsync(new GetEntitiesOfRelationRequestModel { UsageType = usageType, View = view, CollectionAlias = "alias", Related = related }); - - // assert - Assert.AreEqual(expectedUsageTypes1, response.EditContexts.ElementAtOrDefault(0)?.UsageType ?? 0); - Assert.AreEqual(expectedUsageTypes2, response.EditContexts.ElementAtOrDefault(1)?.UsageType ?? 0); - Assert.AreEqual(expectedUsageTypes3, response.EditContexts.ElementAtOrDefault(2)?.UsageType ?? 0); - Assert.AreEqual(expectedUsageTypes4, response.EditContexts.ElementAtOrDefault(3)?.UsageType ?? 0); - } - - [TestCase(UsageType.List)] - [TestCase(UsageType.Node)] - [TestCase(UsageType.NotRoot)] - [TestCase(UsageType.Reordered)] - [TestCase(UsageType.Root)] - public void WhenRequestingUnsupportedUsage_ThenExceptionShouldBeThrown(UsageType usageType) - { - // act & assert - var view = new View(); - Assert.ThrowsAsync(typeof(InvalidOperationException), () => _subject.GetAsync(new GetEntitiesRequestModel { UsageType = usageType, View = view, CollectionAlias = "alias" })); - } + _repository = new Mock(); + _repository.Setup(x => x.NewAsync(It.IsAny(), It.IsAny())).ReturnsAsync(_protoEntity); + _repository.Setup(x => x.GetAllAsync(It.IsAny(), It.IsAny())).ReturnsAsync(_entities); + _repository.Setup(x => x.GetAllNonRelatedAsync(It.IsAny(), It.IsAny())).ReturnsAsync(_entities); + _repository.Setup(x => x.GetAllRelatedAsync(It.IsAny(), It.IsAny())).ReturnsAsync(_entities); + + _repositoryResolver = new Mock(); + _repositoryResolver + .Setup(x => x.GetRepository(It.IsAny())) + .Returns(_repository.Object); + + _dataViewResolver = new Mock(); + + _parentService = new Mock(); + _parentService + .Setup(x => x.GetParentAsync(It.IsAny())) + .ReturnsAsync((ParentPath path) => + { + var mock = new Mock(); + mock.Setup(x => x.GetParentPath()).Returns(path); + return mock.Object; + }); + + _concurrencyService = new ConcurrencyService(new SemaphoreSlim(1, 1)); + + _authService = new Mock(); + _serviceProvider = new Mock(); + + + _subject = new GetEntitiesDispatcher( + _collectionResolver.Object, + _repositoryResolver.Object, + _dataViewResolver.Object, + _parentService.Object, + _concurrencyService, + _authService.Object, + _serviceProvider.Object); + } + + [TestCase("collectionAlias1")] + [TestCase("collectionAlias2")] + public void WhenRequestHasCollectionAlias_ThenCollectionResolverIsUsedToFetchCollectionWithThatAlias(string alias) + { + // act + _subject.GetAsync(new GetEntitiesRequestModel { UsageType = UsageType.New, CollectionAlias = alias }); + + // assert + _collectionResolver.Verify(x => x.ResolveSetupAsync(It.Is(x => x == alias))); + } + + [TestCase("collectionAlias1")] + [TestCase("collectionAlias2")] + public void WhenRequestHasCollectionAlias_ThenRepositoryResolverIsUsedToFetchRepositoryWithCollectionThatHasThatAlias(string alias) + { + // act + _subject.GetAsync(new GetEntitiesRequestModel { UsageType = UsageType.New, CollectionAlias = alias }); + + // assert + _repositoryResolver.Verify(x => x.GetRepository(It.Is(x => x.Alias == alias))); + } + + [TestCase(default(string))] + [TestCase("test:1")] + public void WhenRequestHasParent_ThenParentServiceShouldBeUsedToFetchParent(string path) + { + // act + _subject.GetAsync(new GetEntitiesOfParentRequestModel { UsageType = UsageType.New, CollectionAlias = "", ParentPath = ParentPath.TryParse(path) }); + + // assert + _parentService.Verify(x => x.GetParentAsync(It.Is(x => (x == null && path == null) || x!.ToPathString() == path)), Times.Once()); + } + + [Test] + public void WhenRequestMade_ThenRepositoryShouldBeUsedToFetchProtoEntity() + { + // act + _subject.GetAsync(new GetEntitiesRequestModel { CollectionAlias = "name" }); + + // assert + _repository.Verify(x => x.NewAsync(It.IsAny(), It.IsAny())); + } + + [TestCase(UsageType.Add)] + [TestCase(UsageType.Edit)] + [TestCase(UsageType.List)] + [TestCase(UsageType.New)] + [TestCase(UsageType.Node)] + [TestCase(UsageType.Pick)] + [TestCase(UsageType.Reordered)] + [TestCase(UsageType.View)] + public void WhenRequestMade_ThenAuthServiceShouldBeUsedToValidateActionAgainstProtoEntity(UsageType usageType) + { + // act + _subject.GetAsync(new GetEntitiesRequestModel { CollectionAlias = "name", UsageType = usageType }); + + // assert + _authService.Verify(x => x.EnsureAuthorizedUserAsync(It.Is(x => x == usageType), It.Is(x => x == _protoEntity))); + } + + [TestCase(UsageType.Edit)] + [TestCase(UsageType.New)] + [TestCase(UsageType.Node)] + [TestCase(UsageType.Pick)] + [TestCase(UsageType.Reordered)] + [TestCase(UsageType.View)] + public void WhenRequestingToGetEntitiesOfParent_ThenRepositoryShouldBeQueriedToGetEntities(UsageType usageType) + { + // act + var parentPath = ParentPath.TryParse("path:123"); + var view = new View(); + _subject.GetAsync(new GetEntitiesOfParentRequestModel { UsageType = usageType, View = view, CollectionAlias = "alias", ParentPath = parentPath }); + + // assert + _repository.Verify(x => x.GetAllAsync(It.Is(x => x.Parent.GetParentPath()!.ToPathString() == parentPath!.ToPathString()), It.Is(x => x == view))); + } + + [TestCase(UsageType.Add)] + public void WhenRequestingToGetEntitiesToAddToTheRelatedEntity_ThenRepositoryShouldBeQueriedToGetNonRelatedEntities(UsageType usageType) + { + // act + var related = new RelatedEntity(default, new DefaultEntityVariant(), "alias"); + var view = new View(); + _subject.GetAsync(new GetEntitiesOfRelationRequestModel { UsageType = usageType, View = view, CollectionAlias = "alias", Related = related }); + + // assert + _repository.Verify(x => x.GetAllNonRelatedAsync(It.Is(x => x.Related == related), It.Is(x => x == view))); + } + + [TestCase(UsageType.Edit)] + [TestCase(UsageType.New)] + [TestCase(UsageType.Node)] + [TestCase(UsageType.Pick)] + [TestCase(UsageType.Reordered)] + [TestCase(UsageType.View)] + public void WhenRequestingToGetEntitiesRelatedToRelatedEntity_ThenRepositoryShouldBeQueriedToGetNonRelatedEntities(UsageType usageType) + { + // act + var related = new RelatedEntity(default, new DefaultEntityVariant(), "alias"); + var view = new View(); + _subject.GetAsync(new GetEntitiesOfRelationRequestModel { UsageType = usageType, View = view, CollectionAlias = "alias", Related = related }); + + // assert + _repository.Verify(x => x.GetAllRelatedAsync(It.Is(x => x.Related == related), It.Is(x => x == view))); + } + + [TestCase(UsageType.List)] + [TestCase(UsageType.NotRoot)] + [TestCase(UsageType.Root)] + public void WhenRequestingToPerformUnsupportedAction_ThenInvalidOperationShouldBeThrown(UsageType usageType) + { + // act & assert + Assert.ThrowsAsync(typeof(InvalidOperationException), () => _subject.GetAsync(new GetEntitiesRequestModel { UsageType = usageType, CollectionAlias = "alias" })); + } + + [TestCase(UsageType.Edit, UsageType.Node | UsageType.Edit, UsageType.Node | UsageType.Edit, UsageType.Node | UsageType.Edit, null)] + [TestCase(UsageType.New, UsageType.Node | UsageType.New, UsageType.Node | UsageType.Edit, UsageType.Node | UsageType.Edit, UsageType.Node | UsageType.Edit)] + [TestCase(UsageType.View, UsageType.Node | UsageType.View, UsageType.Node | UsageType.View, UsageType.Node | UsageType.View, null)] + public async Task WhenRequestingToGetEntitiesOfParent_ThenListOfEntitiesShouldBeReturnedWithCorrectUsageTypesAsync(UsageType usageType, UsageType expectedUsageTypes1, UsageType expectedUsageTypes2, UsageType expectedUsageTypes3, UsageType expectedUsageTypes4) + { + // act + var parentPath = ParentPath.TryParse("path:123"); + var view = new View(); + var response = await _subject.GetAsync(new GetEntitiesOfParentRequestModel { UsageType = usageType, View = view, CollectionAlias = "alias", ParentPath = parentPath }); + + // assert + Assert.AreEqual(expectedUsageTypes1, response.EditContexts.ElementAtOrDefault(0)?.UsageType ?? 0); + Assert.AreEqual(expectedUsageTypes2, response.EditContexts.ElementAtOrDefault(1)?.UsageType ?? 0); + Assert.AreEqual(expectedUsageTypes3, response.EditContexts.ElementAtOrDefault(2)?.UsageType ?? 0); + Assert.AreEqual(expectedUsageTypes4, response.EditContexts.ElementAtOrDefault(3)?.UsageType ?? 0); + } + + [TestCase(UsageType.Add, UsageType.Node | UsageType.Pick, UsageType.Node | UsageType.Pick, UsageType.Node | UsageType.Pick, null)] + public async Task WhenRequestingToGetEntitiesRelatedToRelatedEntity_ThenListOfEntitiesShouldBeReturnedWithCorrectUsageTypesAsync(UsageType usageType, UsageType expectedUsageTypes1, UsageType expectedUsageTypes2, UsageType expectedUsageTypes3, UsageType expectedUsageTypes4) + { + // act + var related = new RelatedEntity(default, new DefaultEntityVariant(), "alias"); + var view = new View(); + var response = await _subject.GetAsync(new GetEntitiesOfRelationRequestModel { UsageType = usageType, View = view, CollectionAlias = "alias", Related = related }); + + // assert + Assert.AreEqual(expectedUsageTypes1, response.EditContexts.ElementAtOrDefault(0)?.UsageType ?? 0); + Assert.AreEqual(expectedUsageTypes2, response.EditContexts.ElementAtOrDefault(1)?.UsageType ?? 0); + Assert.AreEqual(expectedUsageTypes3, response.EditContexts.ElementAtOrDefault(2)?.UsageType ?? 0); + Assert.AreEqual(expectedUsageTypes4, response.EditContexts.ElementAtOrDefault(3)?.UsageType ?? 0); + } + + [TestCase(UsageType.List)] + [TestCase(UsageType.Node)] + [TestCase(UsageType.NotRoot)] + [TestCase(UsageType.Reordered)] + [TestCase(UsageType.Root)] + public void WhenRequestingUnsupportedUsage_ThenExceptionShouldBeThrown(UsageType usageType) + { + // act & assert + var view = new View(); + Assert.ThrowsAsync(typeof(InvalidOperationException), () => _subject.GetAsync(new GetEntitiesRequestModel { UsageType = usageType, View = view, CollectionAlias = "alias" })); } } diff --git a/src/RapidCMS.Core.Tests/Services/Dispatchers/GetEntityDispatcherTests.cs b/src/RapidCMS.Core.Tests/Services/Dispatchers/GetEntityDispatcherTests.cs index 8dc166ce..3326e91f 100644 --- a/src/RapidCMS.Core.Tests/Services/Dispatchers/GetEntityDispatcherTests.cs +++ b/src/RapidCMS.Core.Tests/Services/Dispatchers/GetEntityDispatcherTests.cs @@ -18,232 +18,231 @@ using System.Threading; using System.Threading.Tasks; -namespace RapidCMS.Core.Tests.Services.Dispatchers +namespace RapidCMS.Core.Tests.Services.Dispatchers; + +public class GetEntityDispatcherTests { - public class GetEntityDispatcherTests + private IPresentationDispatcher _subject = default!; + + private Mock> _collectionResolver = default!; + private Mock _repository = default!; + private Mock _repositoryResolver = default!; + private Mock _parentService = default!; + private IConcurrencyService _concurrencyService = default!; + private Mock _authService = default!; + private Mock _serviceProvider = default!; + + private readonly IEntity _entity = new DefaultEntityVariant(); + + [SetUp] + public void Setup() { - private IPresentationDispatcher _subject = default!; - - private Mock> _collectionResolver = default!; - private Mock _repository = default!; - private Mock _repositoryResolver = default!; - private Mock _parentService = default!; - private IConcurrencyService _concurrencyService = default!; - private Mock _authService = default!; - private Mock _serviceProvider = default!; - - private readonly IEntity _entity = new DefaultEntityVariant(); - - [SetUp] - public void Setup() - { - _collectionResolver = new Mock>(); - _collectionResolver - .Setup(x => x.ResolveSetupAsync(It.IsAny())) - .ReturnsAsync((string alias) => - new CollectionSetup(default, - default, - "name", - alias, - $"repo-{alias}") + _collectionResolver = new Mock>(); + _collectionResolver + .Setup(x => x.ResolveSetupAsync(It.IsAny())) + .ReturnsAsync((string alias) => + new CollectionSetup(default, + default, + "name", + alias, + $"repo-{alias}") + { + EntityVariant = new EntityVariantSetup("default", default, typeof(DefaultEntityVariant), "defaultentityvariant"), + SubEntityVariants = new List { - EntityVariant = new EntityVariantSetup("default", default, typeof(DefaultEntityVariant), "defaultentityvariant"), - SubEntityVariants = new List - { - new EntityVariantSetup("sub1", default, typeof(SubEntityVariant1), "subentityvariant1"), - new EntityVariantSetup("sub3", default, typeof(SubEntityVariant3), "subentityvariant3"), - new EntityVariantSetup("sub2", default, typeof(SubEntityVariant2), "subentityvariant2") - } - }); - - _repository = new Mock(); - _repository.Setup(x => x.NewAsync(It.IsAny(), It.IsAny())).ReturnsAsync(_entity); - _repository.Setup(x => x.GetByIdAsync(It.IsAny(), It.IsAny())).ReturnsAsync(_entity); - - _repositoryResolver = new Mock(); - _repositoryResolver - .Setup(x => x.GetRepository(It.IsAny())) - .Returns(_repository.Object); - _parentService = new Mock(); - - _concurrencyService = new ConcurrencyService(new SemaphoreSlim(1, 1)); - - _authService = new Mock(); - _serviceProvider = new Mock(); - - _subject = new GetEntityDispatcher( - _collectionResolver.Object, - _repositoryResolver.Object, - _parentService.Object, - _concurrencyService, - _authService.Object, - _serviceProvider.Object); - } - - [TestCase(UsageType.View)] - [TestCase(UsageType.Edit)] - public void WhenRequestHasNoIdWhenRequired_ThenExceptionIsThrown(UsageType usageType) - { - // act && assert - Assert.ThrowsAsync(typeof(InvalidOperationException), () => _subject.GetAsync(new GetEntityRequestModel { UsageType = usageType })); - } - - [TestCase(UsageType.New)] - public void WhenRequestHasIdWhenNotRequired_ThenExceptionIsThrown(UsageType usageType) - { - // act && assert - Assert.ThrowsAsync(typeof(InvalidOperationException), () => _subject.GetAsync(new GetEntityRequestModel { Id = "something", UsageType = usageType })); - } - - [TestCase("collectionAlias1")] - [TestCase("collectionAlias2")] - public void WhenRequestHasCollectionAlias_ThenCollectionResolverIsUsedToFetchCollectionWithThatAlias(string alias) - { - // act - _subject.GetAsync(new GetEntityRequestModel { UsageType = UsageType.New, CollectionAlias = alias }); - - // assert - _collectionResolver.Verify(x => x.ResolveSetupAsync(It.Is(x => x == alias))); - } - - [TestCase("collectionAlias1")] - [TestCase("collectionAlias2")] - public void WhenRequestHasCollectionAlias_ThenRepositoryResolverIsUsedToFetchRepositoryWithCollectionThatHasThatAlias(string alias) - { - // act - _subject.GetAsync(new GetEntityRequestModel { UsageType = UsageType.New, CollectionAlias = alias }); - - // assert - _repositoryResolver.Verify(x => x.GetRepository(It.Is(x => x.Alias == alias))); - } - - [TestCase(default(string))] - [TestCase("test:1")] - public void WhenRequestHasParent_ThenParentServiceShouldBeUsedToFetchParent(string? path) - { - // act - _subject.GetAsync(new GetEntityRequestModel { UsageType = UsageType.New, CollectionAlias = "", ParentPath = ParentPath.TryParse(path) }); - - // assert - _parentService.Verify(x => x.GetParentAsync(It.Is(x => (x == null && path == null) || x!.ToPathString() == path)), Times.Once()); - } - - [TestCase(UsageType.View, "1")] - [TestCase(UsageType.View, "fdsa")] - [TestCase(UsageType.Edit, "1")] - [TestCase(UsageType.Edit, "fdsa")] - public void WhenRequestingToGetEntity_ThenRepositoryShouldBeQueriedToGetEntityById(UsageType usageType, string id) - { - // act - _subject.GetAsync(new GetEntityRequestModel { UsageType = usageType, CollectionAlias = "alias", Id = id }); - - // assert - _repository.Verify(x => x.GetByIdAsync(It.Is(x => x == id), It.IsAny()), Times.Once()); - _repository.VerifyNoOtherCalls(); - } - - [TestCase(UsageType.Add, "1")] - [TestCase(UsageType.List, "fdsa")] - [TestCase(UsageType.Pick, "1")] - [TestCase(UsageType.Reordered, "fdsa")] - public void WhenRequestingToPerformUnsupportedAction_ThenInvalidOperationShouldBeThrown(UsageType usageType, string id) - { - // act & assert - Assert.ThrowsAsync(typeof(InvalidOperationException), () => _subject.GetAsync(new GetEntityRequestModel { UsageType = usageType, CollectionAlias = "alias", Id = id })); - } - - [TestCase(UsageType.New, "defaultentityvariant", typeof(DefaultEntityVariant))] - [TestCase(UsageType.New, "subentityvariant1", typeof(SubEntityVariant1))] - [TestCase(UsageType.New, "subentityvariant2", typeof(SubEntityVariant2))] - [TestCase(UsageType.New, "subentityvariant3", typeof(SubEntityVariant3))] - public void WhenRequestingToGetNewEntity_ThenRepositoryShouldBeQueriedToGetNewEntity(UsageType usageType, string variantAlias, Type type) - { - // act - _subject.GetAsync(new GetEntityRequestModel { UsageType = usageType, CollectionAlias = "alias", VariantAlias = variantAlias }); - - // assert - _repository.Verify(x => x.NewAsync(It.IsAny(), It.Is(x => x == type)), Times.Once()); - _repository.VerifyNoOtherCalls(); - } - - [TestCase(UsageType.View, "1")] - [TestCase(UsageType.View, "fdsa")] - [TestCase(UsageType.Edit, "1")] - [TestCase(UsageType.Edit, "fdsa")] - public void WhenRequestingToGetEntity_ThenAuthServiceShouldBeConsulted(UsageType usageType, string id) - { - // act - _subject.GetAsync(new GetEntityRequestModel { UsageType = usageType, CollectionAlias = "alias", Id = id }); - - // assert - _authService.Verify(x => x.EnsureAuthorizedUserAsync(It.Is(x => x == usageType), It.Is(x => x == _entity))); - _authService.VerifyNoOtherCalls(); - } - - [TestCase(UsageType.New, "defaultentityvariant", typeof(DefaultEntityVariant))] - [TestCase(UsageType.New, "subentityvariant1", typeof(SubEntityVariant1))] - [TestCase(UsageType.New, "subentityvariant2", typeof(SubEntityVariant2))] - [TestCase(UsageType.New, "subentityvariant3", typeof(SubEntityVariant3))] - public void WhenRequestingToGetNewEntity_ThenAuthServiceShouldBeConsulted(UsageType usageType, string variantAlias, Type type) - { - // act - _subject.GetAsync(new GetEntityRequestModel { UsageType = usageType, CollectionAlias = "alias", VariantAlias = variantAlias }); - - // assert - _authService.Verify(x => x.EnsureAuthorizedUserAsync(It.Is(x => x == usageType), It.Is(x => x == _entity))); - _authService.VerifyNoOtherCalls(); - } - - [TestCase(UsageType.View, "1")] - [TestCase(UsageType.View, "fdsa")] - [TestCase(UsageType.Edit, "1")] - [TestCase(UsageType.Edit, "fdsa")] - public async Task WhenRequestingToGetEntity_ThenEditContextShouldBeReturned(UsageType usageType, string id) - { - // act - var context = await _subject.GetAsync(new GetEntityRequestModel { UsageType = usageType, CollectionAlias = "alias", Id = id, VariantAlias = "defaultentityvariant" }); - - // assert - Assert.AreEqual(context.Entity, _entity); - } - - [TestCase(UsageType.New, "defaultentityvariant", typeof(DefaultEntityVariant))] - [TestCase(UsageType.New, "subentityvariant1", typeof(SubEntityVariant1))] - [TestCase(UsageType.New, "subentityvariant2", typeof(SubEntityVariant2))] - [TestCase(UsageType.New, "subentityvariant3", typeof(SubEntityVariant3))] - public async Task WhenRequestingToGetNewEntity_ThenEditContextShouldBeReturned(UsageType usageType, string variantAlias, Type type) - { - // act - var context = await _subject.GetAsync(new GetEntityRequestModel { UsageType = usageType, CollectionAlias = "alias", VariantAlias = variantAlias }); - - // assert - Assert.AreEqual(context.Entity, _entity); - } - - [TestCase(UsageType.View, "1")] - [TestCase(UsageType.View, "fdsa")] - [TestCase(UsageType.Edit, "1")] - [TestCase(UsageType.Edit, "fdsa")] - public void WhenRequestingToGetEntityAndEntityCannotBeFound_ThenExceptionShouldBeThrown(UsageType usageType, string id) - { - // arrange - _repository.Reset(); - - // act && assert - Assert.ThrowsAsync(typeof(Exception), () => _subject.GetAsync(new GetEntityRequestModel { UsageType = usageType, CollectionAlias = "alias", Id = id })); - } - - [TestCase(UsageType.New, "defaultentityvariant", typeof(DefaultEntityVariant))] - [TestCase(UsageType.New, "subentityvariant1", typeof(SubEntityVariant1))] - [TestCase(UsageType.New, "subentityvariant2", typeof(SubEntityVariant2))] - [TestCase(UsageType.New, "subentityvariant3", typeof(SubEntityVariant3))] - public async Task WhenRequestingToGetNewEntityAndEntityCannotBeCreated_ThenExceptionShouldBeThrown(UsageType usageType, string variantAlias, Type type) - { - // act - var context = await _subject.GetAsync(new GetEntityRequestModel { UsageType = usageType, CollectionAlias = "alias", VariantAlias = variantAlias }); - - // assert - Assert.AreEqual(context.Entity, _entity); - } + new EntityVariantSetup("sub1", default, typeof(SubEntityVariant1), "subentityvariant1"), + new EntityVariantSetup("sub3", default, typeof(SubEntityVariant3), "subentityvariant3"), + new EntityVariantSetup("sub2", default, typeof(SubEntityVariant2), "subentityvariant2") + } + }); + + _repository = new Mock(); + _repository.Setup(x => x.NewAsync(It.IsAny(), It.IsAny())).ReturnsAsync(_entity); + _repository.Setup(x => x.GetByIdAsync(It.IsAny(), It.IsAny())).ReturnsAsync(_entity); + + _repositoryResolver = new Mock(); + _repositoryResolver + .Setup(x => x.GetRepository(It.IsAny())) + .Returns(_repository.Object); + _parentService = new Mock(); + + _concurrencyService = new ConcurrencyService(new SemaphoreSlim(1, 1)); + + _authService = new Mock(); + _serviceProvider = new Mock(); + + _subject = new GetEntityDispatcher( + _collectionResolver.Object, + _repositoryResolver.Object, + _parentService.Object, + _concurrencyService, + _authService.Object, + _serviceProvider.Object); + } + + [TestCase(UsageType.View)] + [TestCase(UsageType.Edit)] + public void WhenRequestHasNoIdWhenRequired_ThenExceptionIsThrown(UsageType usageType) + { + // act && assert + Assert.ThrowsAsync(typeof(InvalidOperationException), () => _subject.GetAsync(new GetEntityRequestModel { UsageType = usageType })); + } + + [TestCase(UsageType.New)] + public void WhenRequestHasIdWhenNotRequired_ThenExceptionIsThrown(UsageType usageType) + { + // act && assert + Assert.ThrowsAsync(typeof(InvalidOperationException), () => _subject.GetAsync(new GetEntityRequestModel { Id = "something", UsageType = usageType })); + } + + [TestCase("collectionAlias1")] + [TestCase("collectionAlias2")] + public void WhenRequestHasCollectionAlias_ThenCollectionResolverIsUsedToFetchCollectionWithThatAlias(string alias) + { + // act + _subject.GetAsync(new GetEntityRequestModel { UsageType = UsageType.New, CollectionAlias = alias }); + + // assert + _collectionResolver.Verify(x => x.ResolveSetupAsync(It.Is(x => x == alias))); + } + + [TestCase("collectionAlias1")] + [TestCase("collectionAlias2")] + public void WhenRequestHasCollectionAlias_ThenRepositoryResolverIsUsedToFetchRepositoryWithCollectionThatHasThatAlias(string alias) + { + // act + _subject.GetAsync(new GetEntityRequestModel { UsageType = UsageType.New, CollectionAlias = alias }); + + // assert + _repositoryResolver.Verify(x => x.GetRepository(It.Is(x => x.Alias == alias))); + } + + [TestCase(default(string))] + [TestCase("test:1")] + public void WhenRequestHasParent_ThenParentServiceShouldBeUsedToFetchParent(string? path) + { + // act + _subject.GetAsync(new GetEntityRequestModel { UsageType = UsageType.New, CollectionAlias = "", ParentPath = ParentPath.TryParse(path) }); + + // assert + _parentService.Verify(x => x.GetParentAsync(It.Is(x => (x == null && path == null) || x!.ToPathString() == path)), Times.Once()); + } + + [TestCase(UsageType.View, "1")] + [TestCase(UsageType.View, "fdsa")] + [TestCase(UsageType.Edit, "1")] + [TestCase(UsageType.Edit, "fdsa")] + public void WhenRequestingToGetEntity_ThenRepositoryShouldBeQueriedToGetEntityById(UsageType usageType, string id) + { + // act + _subject.GetAsync(new GetEntityRequestModel { UsageType = usageType, CollectionAlias = "alias", Id = id }); + + // assert + _repository.Verify(x => x.GetByIdAsync(It.Is(x => x == id), It.IsAny()), Times.Once()); + _repository.VerifyNoOtherCalls(); + } + + [TestCase(UsageType.Add, "1")] + [TestCase(UsageType.List, "fdsa")] + [TestCase(UsageType.Pick, "1")] + [TestCase(UsageType.Reordered, "fdsa")] + public void WhenRequestingToPerformUnsupportedAction_ThenInvalidOperationShouldBeThrown(UsageType usageType, string id) + { + // act & assert + Assert.ThrowsAsync(typeof(InvalidOperationException), () => _subject.GetAsync(new GetEntityRequestModel { UsageType = usageType, CollectionAlias = "alias", Id = id })); + } + + [TestCase(UsageType.New, "defaultentityvariant", typeof(DefaultEntityVariant))] + [TestCase(UsageType.New, "subentityvariant1", typeof(SubEntityVariant1))] + [TestCase(UsageType.New, "subentityvariant2", typeof(SubEntityVariant2))] + [TestCase(UsageType.New, "subentityvariant3", typeof(SubEntityVariant3))] + public void WhenRequestingToGetNewEntity_ThenRepositoryShouldBeQueriedToGetNewEntity(UsageType usageType, string variantAlias, Type type) + { + // act + _subject.GetAsync(new GetEntityRequestModel { UsageType = usageType, CollectionAlias = "alias", VariantAlias = variantAlias }); + + // assert + _repository.Verify(x => x.NewAsync(It.IsAny(), It.Is(x => x == type)), Times.Once()); + _repository.VerifyNoOtherCalls(); + } + + [TestCase(UsageType.View, "1")] + [TestCase(UsageType.View, "fdsa")] + [TestCase(UsageType.Edit, "1")] + [TestCase(UsageType.Edit, "fdsa")] + public void WhenRequestingToGetEntity_ThenAuthServiceShouldBeConsulted(UsageType usageType, string id) + { + // act + _subject.GetAsync(new GetEntityRequestModel { UsageType = usageType, CollectionAlias = "alias", Id = id }); + + // assert + _authService.Verify(x => x.EnsureAuthorizedUserAsync(It.Is(x => x == usageType), It.Is(x => x == _entity))); + _authService.VerifyNoOtherCalls(); + } + + [TestCase(UsageType.New, "defaultentityvariant", typeof(DefaultEntityVariant))] + [TestCase(UsageType.New, "subentityvariant1", typeof(SubEntityVariant1))] + [TestCase(UsageType.New, "subentityvariant2", typeof(SubEntityVariant2))] + [TestCase(UsageType.New, "subentityvariant3", typeof(SubEntityVariant3))] + public void WhenRequestingToGetNewEntity_ThenAuthServiceShouldBeConsulted(UsageType usageType, string variantAlias, Type type) + { + // act + _subject.GetAsync(new GetEntityRequestModel { UsageType = usageType, CollectionAlias = "alias", VariantAlias = variantAlias }); + + // assert + _authService.Verify(x => x.EnsureAuthorizedUserAsync(It.Is(x => x == usageType), It.Is(x => x == _entity))); + _authService.VerifyNoOtherCalls(); + } + + [TestCase(UsageType.View, "1")] + [TestCase(UsageType.View, "fdsa")] + [TestCase(UsageType.Edit, "1")] + [TestCase(UsageType.Edit, "fdsa")] + public async Task WhenRequestingToGetEntity_ThenEditContextShouldBeReturned(UsageType usageType, string id) + { + // act + var context = await _subject.GetAsync(new GetEntityRequestModel { UsageType = usageType, CollectionAlias = "alias", Id = id, VariantAlias = "defaultentityvariant" }); + + // assert + Assert.AreEqual(context.Entity, _entity); + } + + [TestCase(UsageType.New, "defaultentityvariant", typeof(DefaultEntityVariant))] + [TestCase(UsageType.New, "subentityvariant1", typeof(SubEntityVariant1))] + [TestCase(UsageType.New, "subentityvariant2", typeof(SubEntityVariant2))] + [TestCase(UsageType.New, "subentityvariant3", typeof(SubEntityVariant3))] + public async Task WhenRequestingToGetNewEntity_ThenEditContextShouldBeReturned(UsageType usageType, string variantAlias, Type type) + { + // act + var context = await _subject.GetAsync(new GetEntityRequestModel { UsageType = usageType, CollectionAlias = "alias", VariantAlias = variantAlias }); + + // assert + Assert.AreEqual(context.Entity, _entity); + } + + [TestCase(UsageType.View, "1")] + [TestCase(UsageType.View, "fdsa")] + [TestCase(UsageType.Edit, "1")] + [TestCase(UsageType.Edit, "fdsa")] + public void WhenRequestingToGetEntityAndEntityCannotBeFound_ThenExceptionShouldBeThrown(UsageType usageType, string id) + { + // arrange + _repository.Reset(); + + // act && assert + Assert.ThrowsAsync(typeof(Exception), () => _subject.GetAsync(new GetEntityRequestModel { UsageType = usageType, CollectionAlias = "alias", Id = id })); + } + + [TestCase(UsageType.New, "defaultentityvariant", typeof(DefaultEntityVariant))] + [TestCase(UsageType.New, "subentityvariant1", typeof(SubEntityVariant1))] + [TestCase(UsageType.New, "subentityvariant2", typeof(SubEntityVariant2))] + [TestCase(UsageType.New, "subentityvariant3", typeof(SubEntityVariant3))] + public async Task WhenRequestingToGetNewEntityAndEntityCannotBeCreated_ThenExceptionShouldBeThrown(UsageType usageType, string variantAlias, Type type) + { + // act + var context = await _subject.GetAsync(new GetEntityRequestModel { UsageType = usageType, CollectionAlias = "alias", VariantAlias = variantAlias }); + + // assert + Assert.AreEqual(context.Entity, _entity); } } diff --git a/src/RapidCMS.Core.Tests/Services/Dispatchers/TestClasses.cs b/src/RapidCMS.Core.Tests/Services/Dispatchers/TestClasses.cs index 3d170102..1f0d7ed6 100644 --- a/src/RapidCMS.Core.Tests/Services/Dispatchers/TestClasses.cs +++ b/src/RapidCMS.Core.Tests/Services/Dispatchers/TestClasses.cs @@ -1,35 +1,34 @@ using RapidCMS.Core.Abstractions.Data; using System.ComponentModel.DataAnnotations; -namespace RapidCMS.Core.Tests.Services.Dispatchers +namespace RapidCMS.Core.Tests.Services.Dispatchers; + +public class DefaultEntityVariant : IEntity +{ + public string? Id { get; set; } +} +public class SubEntityVariant1 : DefaultEntityVariant { - public class DefaultEntityVariant : IEntity - { - public string? Id { get; set; } - } - public class SubEntityVariant1 : DefaultEntityVariant - { - } - public class SubEntityVariant2 : DefaultEntityVariant - { - } - public class SubEntityVariant3 : DefaultEntityVariant - { - } +} +public class SubEntityVariant2 : DefaultEntityVariant +{ +} +public class SubEntityVariant3 : DefaultEntityVariant +{ +} - public class ValidEntity : IEntity - { - public string? Id { get; set; } +public class ValidEntity : IEntity +{ + public string? Id { get; set; } - [Required] - public string Name { get; set; } = "Something"; - } + [Required] + public string Name { get; set; } = "Something"; +} - public class InvalidEntity : IEntity - { - public string? Id { get; set; } +public class InvalidEntity : IEntity +{ + public string? Id { get; set; } - [Required] - public string Name { get; set; } = default!; - } + [Required] + public string Name { get; set; } = default!; } diff --git a/src/RapidCMS.Core.Tests/Services/Parent/ParentServiceTests.cs b/src/RapidCMS.Core.Tests/Services/Parent/ParentServiceTests.cs index e7ea0b33..4c8600a9 100644 --- a/src/RapidCMS.Core.Tests/Services/Parent/ParentServiceTests.cs +++ b/src/RapidCMS.Core.Tests/Services/Parent/ParentServiceTests.cs @@ -11,57 +11,56 @@ using System.Threading; using System.Threading.Tasks; -namespace RapidCMS.Core.Tests.Services.Parent +namespace RapidCMS.Core.Tests.Services.Parent; + +public class ParentServiceTests { - public class ParentServiceTests - { - private Mock _repository = default!; - private Mock _repositoryResolver = default!; - private IConcurrencyService _concurrencyService = default!; - private IParentService _subject = default!; + private Mock _repository = default!; + private Mock _repositoryResolver = default!; + private IConcurrencyService _concurrencyService = default!; + private IParentService _subject = default!; - [SetUp] - public void Setup() - { - _repository = new Mock(); - _repository - .Setup(x => x.GetByIdAsync(It.IsAny(), It.IsAny())) - .ReturnsAsync((string id, IViewContext context) => - { - var mock = new Mock(); - mock.Setup(x => x.Id).Returns(id); - return mock.Object; - }); - _repositoryResolver = new Mock(); + [SetUp] + public void Setup() + { + _repository = new Mock(); + _repository + .Setup(x => x.GetByIdAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync((string id, IViewContext context) => + { + var mock = new Mock(); + mock.Setup(x => x.Id).Returns(id); + return mock.Object; + }); + _repositoryResolver = new Mock(); - _concurrencyService = new ConcurrencyService(new SemaphoreSlim(1, 1)); - _subject = new ParentService(_repositoryResolver.Object, _concurrencyService); - } + _concurrencyService = new ConcurrencyService(new SemaphoreSlim(1, 1)); + _subject = new ParentService(_repositoryResolver.Object, _concurrencyService); + } - [Test] - public async Task WhenParentPathIsEmpty_NoParentsAreReturned() - { - // arrange + [Test] + public async Task WhenParentPathIsEmpty_NoParentsAreReturned() + { + // arrange - // act - var parents = await _subject.GetParentAsync(default); + // act + var parents = await _subject.GetParentAsync(default); - // assert - Assert.IsNull(parents); - } + // assert + Assert.IsNull(parents); + } - [Test] - public async Task WhenParentPathContainsOneLevel_OneParentIsReturned() - { - // arrange - _repositoryResolver.Setup(x => x.GetRepository("alias")).Returns(_repository.Object); + [Test] + public async Task WhenParentPathContainsOneLevel_OneParentIsReturned() + { + // arrange + _repositoryResolver.Setup(x => x.GetRepository("alias")).Returns(_repository.Object); - // act - var parents = await _subject.GetParentAsync(ParentPath.TryParse("alias:123")); + // act + var parents = await _subject.GetParentAsync(ParentPath.TryParse("alias:123")); - // assert - Assert.NotNull(parents!.Entity); - Assert.AreEqual("alias:123", parents.GetParentPath()!.ToPathString()); - } + // assert + Assert.NotNull(parents!.Entity); + Assert.AreEqual("alias:123", parents.GetParentPath()!.ToPathString()); } } diff --git a/src/RapidCMS.Core/Abstractions/Config/IAdvancedApiConfig.cs b/src/RapidCMS.Core/Abstractions/Config/IAdvancedApiConfig.cs index 68bb2c1e..61b56674 100644 --- a/src/RapidCMS.Core/Abstractions/Config/IAdvancedApiConfig.cs +++ b/src/RapidCMS.Core/Abstractions/Config/IAdvancedApiConfig.cs @@ -1,10 +1,9 @@ -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface IAdvancedApiConfig { - public interface IAdvancedApiConfig - { - /// - /// Setting this true prevents DataAnnotationEntityValidator from being added to all repositories automatically. - /// - bool RemoveDataAnnotationEntityValidator { get; set; } - } + /// + /// Setting this true prevents DataAnnotationEntityValidator from being added to all repositories automatically. + /// + bool RemoveDataAnnotationEntityValidator { get; set; } } diff --git a/src/RapidCMS.Core/Abstractions/Config/IAdvancedCmsConfig.cs b/src/RapidCMS.Core/Abstractions/Config/IAdvancedCmsConfig.cs index 2919c4fe..9b96a058 100644 --- a/src/RapidCMS.Core/Abstractions/Config/IAdvancedCmsConfig.cs +++ b/src/RapidCMS.Core/Abstractions/Config/IAdvancedCmsConfig.cs @@ -1,17 +1,16 @@ -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface IAdvancedCmsConfig { - public interface IAdvancedCmsConfig - { - /// - /// This count controls the amount of concurrent repository calls that can be - /// performed at the same time. For some scenarios (like server-side blazor with EF without MARS), - /// this number should be strictly 1, but can be higher for other scenarios. - /// - int SemaphoreCount { get; set; } + /// + /// This count controls the amount of concurrent repository calls that can be + /// performed at the same time. For some scenarios (like server-side blazor with EF without MARS), + /// this number should be strictly 1, but can be higher for other scenarios. + /// + int SemaphoreCount { get; set; } - /// - /// Setting this true prevents DataAnnotationEntityValidator from being added to all collections automatically. - /// - bool RemoveDataAnnotationEntityValidator { get; set; } - } + /// + /// Setting this true prevents DataAnnotationEntityValidator from being added to all collections automatically. + /// + bool RemoveDataAnnotationEntityValidator { get; set; } } diff --git a/src/RapidCMS.Core/Abstractions/Config/IApiConfig.cs b/src/RapidCMS.Core/Abstractions/Config/IApiConfig.cs index 747a2dfa..76926afd 100644 --- a/src/RapidCMS.Core/Abstractions/Config/IApiConfig.cs +++ b/src/RapidCMS.Core/Abstractions/Config/IApiConfig.cs @@ -4,83 +4,82 @@ using RapidCMS.Core.Abstractions.Repositories; using RapidCMS.Core.Abstractions.Validators; -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface IApiConfig { - public interface IApiConfig - { - /// - /// Use this to allow anonymous users to fully use your Api. This adds a very permissive AuthorizationHandler that allows everything by anyone. - /// - /// - IApiConfig AllowAnonymousUser(); + /// + /// Use this to allow anonymous users to fully use your Api. This adds a very permissive AuthorizationHandler that allows everything by anyone. + /// + /// + IApiConfig AllowAnonymousUser(); - /// - /// Registers a repository and creates a Controller for it - /// - /// - /// - /// - IApiRepositoryConfig RegisterRepository() - where TEntity : class, IEntity - where TRepository : IRepository; + /// + /// Registers a repository and creates a Controller for it + /// + /// + /// + /// + IApiRepositoryConfig RegisterRepository() + where TEntity : class, IEntity + where TRepository : IRepository; - /// - /// Registers a mapped repository and creates a Controller for it - /// - /// - /// - /// - /// - IApiRepositoryConfig RegisterRepository() - where TEntity : class, IEntity - where TMappedEntity : class - where TRepository : IRepository; + /// + /// Registers a mapped repository and creates a Controller for it + /// + /// + /// + /// + /// + IApiRepositoryConfig RegisterRepository() + where TEntity : class, IEntity + where TMappedEntity : class + where TRepository : IRepository; - /// - /// Registers a file handler and creates a Controller for it - /// - /// - /// - IApiConfig RegisterFileUploadHandler() - where THandler : IFileUploadHandler; + /// + /// Registers a file handler and creates a Controller for it + /// + /// + /// + IApiConfig RegisterFileUploadHandler() + where THandler : IFileUploadHandler; - /// - /// Adds a data view builder under the collectionAlias. Data view builders allow for creating dynamic data views. - /// - /// - /// - IApiConfig RegisterDataViewBuilder(string collectionAlias) - where TDataViewBuilder : IDataViewBuilder; + /// + /// Adds a data view builder under the collectionAlias. Data view builders allow for creating dynamic data views. + /// + /// + /// + IApiConfig RegisterDataViewBuilder(string collectionAlias) + where TDataViewBuilder : IDataViewBuilder; - /// - /// Adds an entity validator for the given entity. - /// - /// - /// - /// - /// - IApiConfig RegisterEntityValidator(object? config = default) - where TEntity : IEntity - where TEntityValidator: IEntityValidator; + /// + /// Adds an entity validator for the given entity. + /// + /// + /// + /// + /// + IApiConfig RegisterEntityValidator(object? config = default) + where TEntity : IEntity + where TEntityValidator: IEntityValidator; - /// - /// Returns the registered repositories - /// - IEnumerable Repositories { get; } + /// + /// Returns the registered repositories + /// + IEnumerable Repositories { get; } - /// - /// Returns the registered data views - /// - IEnumerable DataViews { get; } + /// + /// Returns the registered data views + /// + IEnumerable DataViews { get; } - /// - /// Returns the registered file upload handlers - /// - IEnumerable FileUploadHandlers { get; } + /// + /// Returns the registered file upload handlers + /// + IEnumerable FileUploadHandlers { get; } - /// - /// These settings are for advanced or debugging scenarios. - /// - IAdvancedApiConfig Advanced { get; } - } + /// + /// These settings are for advanced or debugging scenarios. + /// + IAdvancedApiConfig Advanced { get; } } diff --git a/src/RapidCMS.Core/Abstractions/Config/IApiDataViewBuilderConfig.cs b/src/RapidCMS.Core/Abstractions/Config/IApiDataViewBuilderConfig.cs index 1a52415f..74c5dfec 100644 --- a/src/RapidCMS.Core/Abstractions/Config/IApiDataViewBuilderConfig.cs +++ b/src/RapidCMS.Core/Abstractions/Config/IApiDataViewBuilderConfig.cs @@ -1,10 +1,9 @@ using System; -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface IApiDataViewBuilderConfig { - public interface IApiDataViewBuilderConfig - { - string Alias { get; } - Type DataViewBuilder { get; } - } + string Alias { get; } + Type DataViewBuilder { get; } } diff --git a/src/RapidCMS.Core/Abstractions/Config/IApiRepositoryConfig.cs b/src/RapidCMS.Core/Abstractions/Config/IApiRepositoryConfig.cs index 554680e5..559e91ea 100644 --- a/src/RapidCMS.Core/Abstractions/Config/IApiRepositoryConfig.cs +++ b/src/RapidCMS.Core/Abstractions/Config/IApiRepositoryConfig.cs @@ -1,14 +1,13 @@ using System; using RapidCMS.Core.Abstractions.Validators; -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface IApiRepositoryConfig { - public interface IApiRepositoryConfig - { - string Alias { get; } - Type EntityType { get; } - Type? DatabaseType { get; } - Type RepositoryType { get; } - Type ApiRepositoryType { get; } - } + string Alias { get; } + Type EntityType { get; } + Type? DatabaseType { get; } + Type RepositoryType { get; } + Type ApiRepositoryType { get; } } diff --git a/src/RapidCMS.Core/Abstractions/Config/ICmsConfig.cs b/src/RapidCMS.Core/Abstractions/Config/ICmsConfig.cs index bed61ed2..f91d7b8d 100644 --- a/src/RapidCMS.Core/Abstractions/Config/ICmsConfig.cs +++ b/src/RapidCMS.Core/Abstractions/Config/ICmsConfig.cs @@ -5,136 +5,142 @@ using RapidCMS.Core.Abstractions.Repositories; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface ICmsConfig : ICollectionConfig { - public interface ICmsConfig : ICollectionConfig - { - /// - /// Adds a collection to the CMS. - /// - /// Type of the entity of this collection - /// Type of the repository this collection will use - /// Alias of the collection - /// Human readable name of this collection - /// - /// - ICollectionConfig AddCollection(string alias, string name, Action> configure) - where TEntity : class, IEntity - where TRepository : IRepository; - - /// - /// Adds a collection to the CMS. - /// - /// Type of the entity of this collection - /// Type of the repository this collection will use - /// Alias of the collection - /// Icon for this collection (https://developer.microsoft.com/en-us/fluentui#/styles/web/icons) - /// Human readable name of this collection - /// - /// - ICollectionConfig AddCollection(string alias, string? icon, string name, Action> configure) - where TEntity : class, IEntity - where TRepository : IRepository; - - /// - /// Adds a collection to the CMS. - /// - /// Type of the entity of this collection - /// Type of the repository this collection will use - /// Alias of the collection - /// Icon for this collection (https://developer.microsoft.com/en-us/fluentui#/styles/web/icons) - /// The color of this collection (https://developer.microsoft.com/en-us/fluentui#/styles/web/colors/personas) - /// Human readable name of this collection - /// - /// - ICollectionConfig AddCollection(string alias, string? icon, string? color, string name, Action> configure) - where TEntity : class, IEntity - where TRepository : IRepository; - - /// - /// Adds a page to the CMS. - /// - /// Human readable name of this page - /// - /// - ICmsConfig AddPage(string name, Action configure); - - /// - /// Add a page to the CMS. - /// - /// Icon for this page (https://developer.microsoft.com/en-us/fluentui#/styles/web/icons) - /// Human readable name of this page - /// - /// - ICmsConfig AddPage(string icon, string name, Action configure); - - /// - /// Add a page to the CMS. - /// - /// Icon for this page (https://developer.microsoft.com/en-us/fluentui#/styles/web/icons) - /// Color of the icon - /// Human readable name of this page - /// - /// - ICmsConfig AddPage(string icon, string color, string name, Action configure); - - /// - /// Install plugin - /// - /// - /// - public ICmsConfig AddPlugin() - where TPlugin : IPlugin; - - /// - /// List of plugins - /// - IEnumerable Plugins { get; } - - /// - /// The CMS homepage. - /// - IPageConfig Dashboard { get; } - - /// - /// Use this to allow anonymous users to fully use your CMS. This adds a very permissive AuthorizationHandler that allows everything by anyone. - /// - /// Do not use in production. - /// - /// - ICmsConfig AllowAnonymousUser(); - - /// - /// Draws the given razor component as login screen. - /// - /// Type of razor component. - /// - ICmsConfig SetCustomLoginScreen(Type loginType); - - /// - /// Draws the given razor component in the top bar of the CMS. Use this to display the status of the currently signed in user, and the possibility to sign out. - /// - /// Type of razor component. - /// - ICmsConfig SetCustomLoginStatus(Type loginType); - - /// - /// Draws the given razor component when user has no items to display (no user rights). - /// - /// Type of razor component. - /// - ICmsConfig SetEmptyLandingPage(Type loginType); - - /// - /// Sets the name of title in the top left bar of the CMS. Defaults to RapidCMS. - /// - /// Name of your CMS - /// - ICmsConfig SetSiteName(string siteName); - - /// - /// These settings are for advanced or debugging scenarios. - /// - IAdvancedCmsConfig Advanced { get; } - } + /// + /// Adds a collection to the CMS. + /// + /// Type of the entity of this collection + /// Type of the repository this collection will use + /// Alias of the collection + /// Human readable name of this collection + /// + /// + ICollectionConfig AddCollection(string alias, string name, Action> configure) + where TEntity : class, IEntity + where TRepository : IRepository; + + /// + /// Adds a collection to the CMS. + /// + /// Type of the entity of this collection + /// Type of the repository this collection will use + /// Alias of the collection + /// Icon for this collection (https://developer.microsoft.com/en-us/fluentui#/styles/web/icons) + /// Human readable name of this collection + /// + /// + ICollectionConfig AddCollection(string alias, string? icon, string name, Action> configure) + where TEntity : class, IEntity + where TRepository : IRepository; + + /// + /// Adds a collection to the CMS. + /// + /// Type of the entity of this collection + /// Type of the repository this collection will use + /// Alias of the collection + /// Icon for this collection (https://developer.microsoft.com/en-us/fluentui#/styles/web/icons) + /// The color of this collection (https://developer.microsoft.com/en-us/fluentui#/styles/web/colors/personas) + /// Human readable name of this collection + /// + /// + ICollectionConfig AddCollection(string alias, string? icon, string? color, string name, Action> configure) + where TEntity : class, IEntity + where TRepository : IRepository; + + /// + /// Adds a page to the CMS. + /// + /// Human readable name of this page + /// + /// + ICmsConfig AddPage(string name, Action configure); + + /// + /// Add a page to the CMS. + /// + /// Icon for this page (https://developer.microsoft.com/en-us/fluentui#/styles/web/icons) + /// Human readable name of this page + /// + /// + ICmsConfig AddPage(string icon, string name, Action configure); + + /// + /// Add a page to the CMS. + /// + /// Icon for this page (https://developer.microsoft.com/en-us/fluentui#/styles/web/icons) + /// Color of the icon + /// Human readable name of this page + /// + /// + ICmsConfig AddPage(string icon, string color, string name, Action configure); + + /// + /// Install plugin + /// + /// + /// + public ICmsConfig AddPlugin() + where TPlugin : IPlugin; + + /// + /// List of plugins + /// + IEnumerable Plugins { get; } + + /// + /// The CMS homepage. + /// + IPageConfig Dashboard { get; } + + /// + /// Use this to allow anonymous users to fully use your CMS. This adds a very permissive AuthorizationHandler that allows everything by anyone. + /// + /// Do not use in production. + /// + /// + ICmsConfig AllowAnonymousUser(); + + /// + /// Enables outputting exceptions via the error page. + /// + /// + /// + ICmsConfig EnableDevelopmentLogging(bool enabled); + + /// + /// Draws the given razor component as login screen. + /// + /// Type of razor component. + /// + ICmsConfig SetCustomLoginScreen(Type loginType); + + /// + /// Draws the given razor component in the top bar of the CMS. Use this to display the status of the currently signed in user, and the possibility to sign out. + /// + /// Type of razor component. + /// + ICmsConfig SetCustomLoginStatus(Type loginType); + + /// + /// Draws the given razor component when user has no items to display (no user rights). + /// + /// Type of razor component. + /// + ICmsConfig SetEmptyLandingPage(Type loginType); + + /// + /// Sets the name of title in the top left bar of the CMS. Defaults to RapidCMS. + /// + /// Name of your CMS + /// + ICmsConfig SetSiteName(string siteName); + + /// + /// These settings are for advanced or debugging scenarios. + /// + IAdvancedCmsConfig Advanced { get; } } diff --git a/src/RapidCMS.Core/Abstractions/Config/ICollectionConfig.cs b/src/RapidCMS.Core/Abstractions/Config/ICollectionConfig.cs index 8a1d0585..24db32a2 100644 --- a/src/RapidCMS.Core/Abstractions/Config/ICollectionConfig.cs +++ b/src/RapidCMS.Core/Abstractions/Config/ICollectionConfig.cs @@ -6,301 +6,300 @@ using RapidCMS.Core.Abstractions.Validators; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface ICollectionConfig : ITreeElementConfig { - public interface ICollectionConfig : ITreeElementConfig - { - string? ParentAlias { get; } - IEnumerable CollectionsAndPages { get; } + string? ParentAlias { get; } + IEnumerable CollectionsAndPages { get; } - Type RepositoryType { get; } - IEnumerable RepositoryTypes { get; } - } + Type RepositoryType { get; } + IEnumerable RepositoryTypes { get; } +} - public interface ICollectionConfig : ICollectionConfig - where TEntity : IEntity - { - /// - /// Adds the given collection as sub collection to the current collection. - /// - /// Because it's referenced only by alias, no configuration can be added to this sub collection. - /// - /// NOTE: The reference between this sub collection and it's parent collection is weak and the sub collection will not be able to determine it is nested here. (see #101) - /// - /// - /// - ICollectionConfig AddSubCollection(string alias); +public interface ICollectionConfig : ICollectionConfig + where TEntity : IEntity +{ + /// + /// Adds the given collection as sub collection to the current collection. + /// + /// Because it's referenced only by alias, no configuration can be added to this sub collection. + /// + /// NOTE: The reference between this sub collection and it's parent collection is weak and the sub collection will not be able to determine it is nested here. (see #101) + /// + /// + /// + ICollectionConfig AddSubCollection(string alias); - /// - /// Adds a sub collection to the current collection. - /// - /// Type of the entity of this sub collection - /// Type of the repository this sub collection will use - /// Alias of the sub collection - /// Human readable name of this sub collection - /// - /// - ICollectionConfig AddSubCollection(string alias, string name, Action> configure) - where TSubEntity : class, IEntity - where TRepository : IRepository; + /// + /// Adds a sub collection to the current collection. + /// + /// Type of the entity of this sub collection + /// Type of the repository this sub collection will use + /// Alias of the sub collection + /// Human readable name of this sub collection + /// + /// + ICollectionConfig AddSubCollection(string alias, string name, Action> configure) + where TSubEntity : class, IEntity + where TRepository : IRepository; - /// - /// Adds a sub collection to the current collection. - /// - /// Type of the entity of this sub collection - /// Type of the repository this sub collection will use - /// Alias of the sub collection - /// Icon for this sub collection (https://developer.microsoft.com/en-us/fluentui#/styles/web/icons) - /// Human readable name of this sub collection - /// - /// - ICollectionConfig AddSubCollection(string alias, string? icon, string name, Action> configure) - where TSubEntity : class, IEntity - where TRepository : IRepository; + /// + /// Adds a sub collection to the current collection. + /// + /// Type of the entity of this sub collection + /// Type of the repository this sub collection will use + /// Alias of the sub collection + /// Icon for this sub collection (https://developer.microsoft.com/en-us/fluentui#/styles/web/icons) + /// Human readable name of this sub collection + /// + /// + ICollectionConfig AddSubCollection(string alias, string? icon, string name, Action> configure) + where TSubEntity : class, IEntity + where TRepository : IRepository; - /// - /// Adds a sub collection to the current collection. - /// - /// Type of the entity of this sub collection - /// Type of the repository this sub collection will use - /// Alias of the sub collection - /// Icon for this sub collection (https://developer.microsoft.com/en-us/fluentui#/styles/web/icons) - /// The color of this sub collection (https://developer.microsoft.com/en-us/fluentui#/styles/web/colors/personas) - /// Human readable name of this sub collection - /// - /// - ICollectionConfig AddSubCollection(string alias, string? icon, string? color, string name, Action> configure) - where TSubEntity : class, IEntity - where TRepository : IRepository; + /// + /// Adds a sub collection to the current collection. + /// + /// Type of the entity of this sub collection + /// Type of the repository this sub collection will use + /// Alias of the sub collection + /// Icon for this sub collection (https://developer.microsoft.com/en-us/fluentui#/styles/web/icons) + /// The color of this sub collection (https://developer.microsoft.com/en-us/fluentui#/styles/web/colors/personas) + /// Human readable name of this sub collection + /// + /// + ICollectionConfig AddSubCollection(string alias, string? icon, string? color, string name, Action> configure) + where TSubEntity : class, IEntity + where TRepository : IRepository; - /// - /// Adds itself as sub collection. - /// - /// Because this is a self-reference, no configuration can be added to this sub collection. - /// - ICollectionConfig AddSelfAsRecursiveCollection(); + /// + /// Adds itself as sub collection. + /// + /// Because this is a self-reference, no configuration can be added to this sub collection. + /// + ICollectionConfig AddSelfAsRecursiveCollection(); - /// - /// Add a detail page to the current collection. A detail page is a NodeEditor with its own entity type and repository, and allow - /// for creating specialized editors. - /// - /// - /// - /// Alias of the detail page - /// Human readable name of this detail page - /// - /// - ICollectionDetailPageEditorConfig AddDetailPage(string alias, string name, Action> configure) - where TDetailEntity : IEntity - where TDetailRepository : IRepository; + /// + /// Add a detail page to the current collection. A detail page is a NodeEditor with its own entity type and repository, and allow + /// for creating specialized editors. + /// + /// + /// + /// Alias of the detail page + /// Human readable name of this detail page + /// + /// + ICollectionDetailPageEditorConfig AddDetailPage(string alias, string name, Action> configure) + where TDetailEntity : IEntity + where TDetailRepository : IRepository; - /// - /// Add a detail page to the current collection. A detail page is a NodeEditor with its own entity type and repository, and allow - /// for creating specialized editors. - /// - /// - /// - /// Alias of the detail page - /// Icon for this sub collection (https://developer.microsoft.com/en-us/fluentui#/styles/web/icons) - /// Human readable name of this detail page - /// - /// - ICollectionDetailPageEditorConfig AddDetailPage(string alias, string? icon, string name, Action> configure) - where TDetailEntity : IEntity - where TDetailRepository : IRepository; + /// + /// Add a detail page to the current collection. A detail page is a NodeEditor with its own entity type and repository, and allow + /// for creating specialized editors. + /// + /// + /// + /// Alias of the detail page + /// Icon for this sub collection (https://developer.microsoft.com/en-us/fluentui#/styles/web/icons) + /// Human readable name of this detail page + /// + /// + ICollectionDetailPageEditorConfig AddDetailPage(string alias, string? icon, string name, Action> configure) + where TDetailEntity : IEntity + where TDetailRepository : IRepository; - /// - /// Add a detail page to the current collection. A detail page is a NodeEditor with its own entity type and repository, and allow - /// for creating specialized editors. - /// - /// - /// - /// Alias of the detail page - /// Icon for this sub collection (https://developer.microsoft.com/en-us/fluentui#/styles/web/icons) - /// The color of this sub collection (https://developer.microsoft.com/en-us/fluentui#/styles/web/colors/personas) - /// Human readable name of this detail page - /// - /// - ICollectionDetailPageEditorConfig AddDetailPage(string alias, string? icon, string? color, string name, Action> configure) - where TDetailEntity : IEntity - where TDetailRepository : IRepository; + /// + /// Add a detail page to the current collection. A detail page is a NodeEditor with its own entity type and repository, and allow + /// for creating specialized editors. + /// + /// + /// + /// Alias of the detail page + /// Icon for this sub collection (https://developer.microsoft.com/en-us/fluentui#/styles/web/icons) + /// The color of this sub collection (https://developer.microsoft.com/en-us/fluentui#/styles/web/colors/personas) + /// Human readable name of this detail page + /// + /// + ICollectionDetailPageEditorConfig AddDetailPage(string alias, string? icon, string? color, string name, Action> configure) + where TDetailEntity : IEntity + where TDetailRepository : IRepository; - /// - /// Adds a page to the CMS. - /// - /// Human readable name of this page - /// - /// - ICollectionConfig AddPage(string name, Action configure); + /// + /// Adds a page to the CMS. + /// + /// Human readable name of this page + /// + /// + ICollectionConfig AddPage(string name, Action configure); - /// - /// Add a page to the CMS. - /// - /// Icon for this page (https://developer.microsoft.com/en-us/fluentui#/styles/web/icons) - /// Human readable name of this page - /// - /// - ICollectionConfig AddPage(string icon, string name, Action configure); + /// + /// Add a page to the CMS. + /// + /// Icon for this page (https://developer.microsoft.com/en-us/fluentui#/styles/web/icons) + /// Human readable name of this page + /// + /// + ICollectionConfig AddPage(string icon, string name, Action configure); - /// - /// Add a page to the CMS. - /// - /// Icon for this page (https://developer.microsoft.com/en-us/fluentui#/styles/web/icons) - /// Color of the icon - /// Human readable name of this page - /// - /// - ICollectionConfig AddPage(string icon, string color, string name, Action configure); + /// + /// Add a page to the CMS. + /// + /// Icon for this page (https://developer.microsoft.com/en-us/fluentui#/styles/web/icons) + /// Color of the icon + /// Human readable name of this page + /// + /// + ICollectionConfig AddPage(string icon, string color, string name, Action configure); - /// - /// Adds a data view to the collection. Data views are displayed as separate tabs on the collection, and allow - /// the user to filter the collection data easily. - /// - /// Human readable label of this data view - /// Query defining this data view - /// Order by expressions for this data view - /// - ICollectionConfig AddDataView(string label, Expression> queryExpression, Action>? orderByExpressions = null); + /// + /// Adds a data view to the collection. Data views are displayed as separate tabs on the collection, and allow + /// the user to filter the collection data easily. + /// + /// Human readable label of this data view + /// Query defining this data view + /// Order by expressions for this data view + /// + ICollectionConfig AddDataView(string label, Expression> queryExpression, Action>? orderByExpressions = null); - /// - /// Adds an entity variant to the collection. Entity variants are derivatives of TEntity. - /// - /// - /// Human readable name of this variant - /// Name of ion icon. (https://developer.microsoft.com/en-us/fluentui#/styles/web/icons) - /// - ICollectionConfig AddEntityVariant(string name, string icon) - where TDerivedEntity : TEntity; + /// + /// Adds an entity variant to the collection. Entity variants are derivatives of TEntity. + /// + /// + /// Human readable name of this variant + /// Name of ion icon. (https://developer.microsoft.com/en-us/fluentui#/styles/web/icons) + /// + ICollectionConfig AddEntityVariant(string name, string icon) + where TDerivedEntity : TEntity; - /// - /// Adds a data view builder to the collection. Data view builders allow for creating dynamic data views. - /// - /// - /// - ICollectionConfig SetDataViewBuilder() - where TDataViewBuilder : IDataViewBuilder; + /// + /// Adds a data view builder to the collection. Data view builders allow for creating dynamic data views. + /// + /// + /// + ICollectionConfig SetDataViewBuilder() + where TDataViewBuilder : IDataViewBuilder; - /// - /// Sets the ListEditor of this collection - /// - /// Action used to configure the ListEditor - /// - ICollectionConfig SetListEditor(Action> configure); + /// + /// Sets the ListEditor of this collection + /// + /// Action used to configure the ListEditor + /// + ICollectionConfig SetListEditor(Action> configure); - /// - /// Sets the ListView of this collection - /// - /// Action used to configure the ListView - /// - ICollectionConfig SetListView(Action> configure); + /// + /// Sets the ListView of this collection + /// + /// Action used to configure the ListView + /// + ICollectionConfig SetListView(Action> configure); - /// - /// Sets the NodeEditor of this collection - /// - /// Action used to configure the NodeEditor - /// - ICollectionConfig SetNodeEditor(Action> configure); + /// + /// Sets the NodeEditor of this collection + /// + /// Action used to configure the NodeEditor + /// + ICollectionConfig SetNodeEditor(Action> configure); - /// - /// Sets the NodeView of this collection - /// - /// Action used to configure the NodeView - /// - ICollectionConfig SetNodeView(Action> configure); + /// + /// Sets the NodeView of this collection + /// + /// Action used to configure the NodeView + /// + ICollectionConfig SetNodeView(Action> configure); - /// - /// Sets the UI of this collection by convention - /// - /// The resulting UI will be based on what DisplayAttribute - /// s on primitive properties are configured on the model. - /// The Name and Description property of - /// - /// Type of convention to use. - /// - ICollectionConfig ConfigureByConvention(CollectionConvention convention = CollectionConvention.ListViewNodeEditor); + /// + /// Sets the UI of this collection by convention + /// + /// The resulting UI will be based on what DisplayAttribute + /// s on primitive properties are configured on the model. + /// The Name and Description property of + /// + /// Type of convention to use. + /// + ICollectionConfig ConfigureByConvention(CollectionConvention convention = CollectionConvention.ListViewNodeEditor); - /// - /// Sets how the collection should be displayed in the tree. - /// - /// Controls whether the entities of this collection are visible in the tree - /// Expression used to display entities of this collection - /// When set to true, the tree will open the collection open on default. - /// When set to true, the tree will open the entities open on default. - /// - ICollectionConfig SetTreeView(EntityVisibilty entityVisibility, Expression>? entityNameExpression = null, bool showEntitiesOnStartup = false, bool showCollectionsOnStartup = false); + /// + /// Sets how the collection should be displayed in the tree. + /// + /// Controls whether the entities of this collection are visible in the tree + /// Expression used to display entities of this collection + /// When set to true, the tree will open the collection open on default. + /// When set to true, the tree will open the entities open on default. + /// + ICollectionConfig SetTreeView(EntityVisibilty entityVisibility, Expression>? entityNameExpression = null, bool showEntitiesOnStartup = false, bool showCollectionsOnStartup = false); - /// - /// Sets how the collection should be displayed in the tree. - /// - /// Controls whether the entities of this collection are visible in the tree - /// Controls whether the root of this collection is visible in the tree - /// Expression used to display entities of this collection - /// When set to true, the tree will open the collection open on default. - /// When set to true, the tree will open the entities open on default. - /// - ICollectionConfig SetTreeView(EntityVisibilty entityVisibility, CollectionRootVisibility rootVisibility, Expression>? entityNameExpression = null, bool showEntitiesOnStartup = false, bool showCollectionsOnStartup = false); + /// + /// Sets how the collection should be displayed in the tree. + /// + /// Controls whether the entities of this collection are visible in the tree + /// Controls whether the root of this collection is visible in the tree + /// Expression used to display entities of this collection + /// When set to true, the tree will open the collection open on default. + /// When set to true, the tree will open the entities open on default. + /// + ICollectionConfig SetTreeView(EntityVisibilty entityVisibility, CollectionRootVisibility rootVisibility, Expression>? entityNameExpression = null, bool showEntitiesOnStartup = false, bool showCollectionsOnStartup = false); - /// - /// Sets how the collection should be displayed in the tree. - /// - /// Expression used to display entities of this collection - /// When set to true, the tree will open the collection open on default. - /// When set to true, the tree will open the entities open on default. - /// - ICollectionConfig SetTreeView(Expression> entityNameExpression, bool showEntitiesOnStartup = false, bool showCollectionsOnStartup = false); + /// + /// Sets how the collection should be displayed in the tree. + /// + /// Expression used to display entities of this collection + /// When set to true, the tree will open the collection open on default. + /// When set to true, the tree will open the entities open on default. + /// + ICollectionConfig SetTreeView(Expression> entityNameExpression, bool showEntitiesOnStartup = false, bool showCollectionsOnStartup = false); - /// - /// Sets how elements in dropdowns and entity pickers should be displayed when explicit configuration is not available. - /// - /// Expression used as Id for elements - /// Expressions used as Display labels from elements - /// - ICollectionConfig SetElementConfiguration( - Expression> elementIdExpression, - params Expression>[] elementDisplayExpressions); + /// + /// Sets how elements in dropdowns and entity pickers should be displayed when explicit configuration is not available. + /// + /// Expression used as Id for elements + /// Expressions used as Display labels from elements + /// + ICollectionConfig SetElementConfiguration( + Expression> elementIdExpression, + params Expression>[] elementDisplayExpressions); - /// - /// Adds a validator to the collection which will be used to validate the entity. - /// - /// Specific validators for entity variants are only used for that specific variant. - /// - /// - /// - ICollectionConfig AddEntityValidator() - where TEntityValidator : IEntityValidator; + /// + /// Adds a validator to the collection which will be used to validate the entity. + /// + /// Specific validators for entity variants are only used for that specific variant. + /// + /// + /// + ICollectionConfig AddEntityValidator() + where TEntityValidator : IEntityValidator; - /// - /// Adds a validator to the collection which will be used to validate the entity. - /// - /// Specific validators for entity variants are only used for that specific variant. - /// - /// The configuration will be passed in to the ValidatorContext. - /// - /// - /// - ICollectionConfig AddEntityValidator(object configuration) - where TEntityValidator : IEntityValidator; + /// + /// Adds a validator to the collection which will be used to validate the entity. + /// + /// Specific validators for entity variants are only used for that specific variant. + /// + /// The configuration will be passed in to the ValidatorContext. + /// + /// + /// + ICollectionConfig AddEntityValidator(object configuration) + where TEntityValidator : IEntityValidator; - /// - /// Adds an async validator to the collection which will be used to validate the entity. - /// - /// Specific validators for entity variants are only used for that specific variant. - /// - /// - /// - ICollectionConfig AddAsyncEntityValidator() - where TAsyncEntityValidator : IAsyncEntityValidator; + /// + /// Adds an async validator to the collection which will be used to validate the entity. + /// + /// Specific validators for entity variants are only used for that specific variant. + /// + /// + /// + ICollectionConfig AddAsyncEntityValidator() + where TAsyncEntityValidator : IAsyncEntityValidator; - /// - /// Adds an async validator to the collection which will be used to validate the entity. - /// - /// Specific validators for entity variants are only used for that specific variant. - /// - /// The configuration will be passed in to the ValidatorContext. - /// - /// - /// - ICollectionConfig AddAsyncEntityValidator(object configuration) - where TAsyncEntityValidator : IAsyncEntityValidator; - } + /// + /// Adds an async validator to the collection which will be used to validate the entity. + /// + /// Specific validators for entity variants are only used for that specific variant. + /// + /// The configuration will be passed in to the ValidatorContext. + /// + /// + /// + ICollectionConfig AddAsyncEntityValidator(object configuration) + where TAsyncEntityValidator : IAsyncEntityValidator; } diff --git a/src/RapidCMS.Core/Abstractions/Config/ICollectionDetailPageEditorConfig.cs b/src/RapidCMS.Core/Abstractions/Config/ICollectionDetailPageEditorConfig.cs index 6dc98390..876638b2 100644 --- a/src/RapidCMS.Core/Abstractions/Config/ICollectionDetailPageEditorConfig.cs +++ b/src/RapidCMS.Core/Abstractions/Config/ICollectionDetailPageEditorConfig.cs @@ -1,10 +1,9 @@ using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface ICollectionDetailPageEditorConfig : INodeEditorConfig + where TDetailEntity : IEntity { - public interface ICollectionDetailPageEditorConfig : INodeEditorConfig - where TDetailEntity : IEntity - { - } } diff --git a/src/RapidCMS.Core/Abstractions/Config/ICollectionRelationConfig.cs b/src/RapidCMS.Core/Abstractions/Config/ICollectionRelationConfig.cs index fdf20426..d5af5bfe 100644 --- a/src/RapidCMS.Core/Abstractions/Config/ICollectionRelationConfig.cs +++ b/src/RapidCMS.Core/Abstractions/Config/ICollectionRelationConfig.cs @@ -2,36 +2,35 @@ using System.Linq.Expressions; using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface ICollectionRelationConfig { - public interface ICollectionRelationConfig - { - /// - /// Sets the expression(s) that will be used as display label(s) for the relation. - /// - /// Expression(s) indicating how an entity should be displayed in the input / list - /// - ICollectionRelationConfig SetElementDisplayProperties(params Expression>[] propertyExpressions); + /// + /// Sets the expression(s) that will be used as display label(s) for the relation. + /// + /// Expression(s) indicating how an entity should be displayed in the input / list + /// + ICollectionRelationConfig SetElementDisplayProperties(params Expression>[] propertyExpressions); - /// - /// Sets the property that will be used as id for the relation. - /// - /// - /// Expression selecting the id-property - /// - ICollectionRelationConfig SetElementIdProperty(Expression> propertyExpression); + /// + /// Sets the property that will be used as id for the relation. + /// + /// + /// Expression selecting the id-property + /// + ICollectionRelationConfig SetElementIdProperty(Expression> propertyExpression); - /// - /// Sets the parent for the related collection. - /// - /// Expression selecting the parent - /// - ICollectionRelationConfig SetRepositoryParent(Expression> propertyExpression); + /// + /// Sets the parent for the related collection. + /// + /// Expression selecting the parent + /// + ICollectionRelationConfig SetRepositoryParent(Expression> propertyExpression); - /// - /// Sets the entity that will be used as parent for the related collection. - /// - /// - ICollectionRelationConfig SetEntityAsParent(); - } + /// + /// Sets the entity that will be used as parent for the related collection. + /// + /// + ICollectionRelationConfig SetEntityAsParent(); } diff --git a/src/RapidCMS.Core/Abstractions/Config/IConventionConfig.cs b/src/RapidCMS.Core/Abstractions/Config/IConventionConfig.cs index 59dbdf6f..71c6c299 100644 --- a/src/RapidCMS.Core/Abstractions/Config/IConventionConfig.cs +++ b/src/RapidCMS.Core/Abstractions/Config/IConventionConfig.cs @@ -1,10 +1,9 @@ using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface IConventionConfig + where TEntity : IEntity { - public interface IConventionConfig - where TEntity : IEntity - { - } } diff --git a/src/RapidCMS.Core/Abstractions/Config/IDisplayFieldConfig.cs b/src/RapidCMS.Core/Abstractions/Config/IDisplayFieldConfig.cs index aa7a3390..6d043877 100644 --- a/src/RapidCMS.Core/Abstractions/Config/IDisplayFieldConfig.cs +++ b/src/RapidCMS.Core/Abstractions/Config/IDisplayFieldConfig.cs @@ -2,33 +2,32 @@ using RapidCMS.Core.Enums; using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface IDisplayFieldConfig + : IHasOrderBy>, + IHasNameDescription>, + IHasConfigurability> + where TEntity : IEntity { - public interface IDisplayFieldConfig - : IHasOrderBy>, - IHasNameDescription>, - IHasConfigurability> - where TEntity : IEntity - { - /// - /// Sets the type of build-in display used for this field. - /// - /// - /// - IDisplayFieldConfig SetType(DisplayType type); + /// + /// Sets the type of build-in display used for this field. + /// + /// + /// + IDisplayFieldConfig SetType(DisplayType type); - /// - /// Sets the type of custom razor component used for this field. - /// - /// - /// - IDisplayFieldConfig SetType(Type type); + /// + /// Sets the type of custom razor component used for this field. + /// + /// + /// + IDisplayFieldConfig SetType(Type type); - /// - /// Sets an expression which determines whether this field should be visible. - /// - /// - /// - IDisplayFieldConfig VisibleWhen(Func predicate); - } + /// + /// Sets an expression which determines whether this field should be visible. + /// + /// + /// + IDisplayFieldConfig VisibleWhen(Func predicate); } diff --git a/src/RapidCMS.Core/Abstractions/Config/IDisplayPaneConfig.cs b/src/RapidCMS.Core/Abstractions/Config/IDisplayPaneConfig.cs index 0909148f..12824ce3 100644 --- a/src/RapidCMS.Core/Abstractions/Config/IDisplayPaneConfig.cs +++ b/src/RapidCMS.Core/Abstractions/Config/IDisplayPaneConfig.cs @@ -4,77 +4,76 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Abstractions.Repositories; -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface IDisplayPaneConfig : IHasButtons> + where TEntity : IEntity { - public interface IDisplayPaneConfig : IHasButtons> - where TEntity : IEntity - { - /// - /// Adds a field to the pane. - /// - /// Expression to display this field - /// Action to configure this field - /// - IDisplayFieldConfig AddField(Expression> displayExpression, Action>? configure = null); + /// + /// Adds a field to the pane. + /// + /// Expression to display this field + /// Action to configure this field + /// + IDisplayFieldConfig AddField(Expression> displayExpression, Action>? configure = null); - /// - /// Adds a sub collection to the pane. A sub collection is defined separately, and only referenced by alias. - /// - /// Not visible when EntityState is New. - /// - /// Alias of the sub collection - /// - IDisplayPaneConfig AddSubCollectionList(string collectionAlias); + /// + /// Adds a sub collection to the pane. A sub collection is defined separately, and only referenced by alias. + /// + /// Not visible when EntityState is New. + /// + /// Alias of the sub collection + /// + IDisplayPaneConfig AddSubCollectionList(string collectionAlias); - /// - /// Adds a sub collection to the pane. A sub collection is defined separately, and only referenced by alias. - /// - /// Not visible when EntityState is New. - /// - /// Type of the sub collections entity - /// Type of the sub repository - /// Action to configure the use of this sub collection - /// - IDisplayPaneConfig AddSubCollectionList(Action>? configure = null) - where TSubRepository : IRepository - where TSubEntity : IEntity; + /// + /// Adds a sub collection to the pane. A sub collection is defined separately, and only referenced by alias. + /// + /// Not visible when EntityState is New. + /// + /// Type of the sub collections entity + /// Type of the sub repository + /// Action to configure the use of this sub collection + /// + IDisplayPaneConfig AddSubCollectionList(Action>? configure = null) + where TSubRepository : IRepository + where TSubEntity : IEntity; - /// - /// Adds a collection to the pane which is used to view the many-to-many relation between the collection of this pane, and the related collection. - /// The related collection can by any collection. - /// - /// Not visible when EntityState is New. - /// - /// Alias of the related collection - /// - IDisplayPaneConfig AddRelatedCollectionList(string collectionAlias); + /// + /// Adds a collection to the pane which is used to view the many-to-many relation between the collection of this pane, and the related collection. + /// The related collection can by any collection. + /// + /// Not visible when EntityState is New. + /// + /// Alias of the related collection + /// + IDisplayPaneConfig AddRelatedCollectionList(string collectionAlias); - /// - /// Adds a collection to the pane which is used to view the many-to-many relation between the collection of this pane, and the related collection. - /// The related collection can by any collection. - /// - /// Not visible when EntityState is New. - /// - /// Type of the related collections entity - /// Repository for the related collections - /// Action to configure the related collection - /// - IDisplayPaneConfig AddRelatedCollectionList(Action>? configure = null) - where TRelatedRepository : IRepository - where TRelatedEntity : IEntity; + /// + /// Adds a collection to the pane which is used to view the many-to-many relation between the collection of this pane, and the related collection. + /// The related collection can by any collection. + /// + /// Not visible when EntityState is New. + /// + /// Type of the related collections entity + /// Repository for the related collections + /// Action to configure the related collection + /// + IDisplayPaneConfig AddRelatedCollectionList(Action>? configure = null) + where TRelatedRepository : IRepository + where TRelatedEntity : IEntity; - /// - /// Adds a label at the top of this pane. - /// - /// Text to display in the label - /// - IDisplayPaneConfig SetLabel(string label); + /// + /// Adds a label at the top of this pane. + /// + /// Text to display in the label + /// + IDisplayPaneConfig SetLabel(string label); - /// - /// Expression which determines whether this pane should be visible. - /// - /// - /// - IDisplayPaneConfig VisibleWhen(Func predicate); - } + /// + /// Expression which determines whether this pane should be visible. + /// + /// + /// + IDisplayPaneConfig VisibleWhen(Func predicate); } diff --git a/src/RapidCMS.Core/Abstractions/Config/IEditorFieldConfig.cs b/src/RapidCMS.Core/Abstractions/Config/IEditorFieldConfig.cs index 118d3f48..ccfd71a5 100644 --- a/src/RapidCMS.Core/Abstractions/Config/IEditorFieldConfig.cs +++ b/src/RapidCMS.Core/Abstractions/Config/IEditorFieldConfig.cs @@ -5,169 +5,168 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Abstractions.Repositories; -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface IEditorFieldConfig + : IHasOrderBy>, + IHasNameDescription>, + IHasPlaceholder>, + IHasConfigurability> + where TEntity : IEntity { - public interface IEditorFieldConfig - : IHasOrderBy>, - IHasNameDescription>, - IHasPlaceholder>, - IHasConfigurability> - where TEntity : IEntity - { - /// - /// Sets the type of build-in editor used for this field. - /// - /// - /// - IEditorFieldConfig SetType(EditorType type); - - /// - /// Sets the type of build-in display used for this field. - /// - /// - /// - IEditorFieldConfig SetType(DisplayType type); - - /// - /// Sets the type of custom razor component used for this field. - /// - /// - /// - IEditorFieldConfig SetType(Type type); - - /// - /// Binds a DataCollection to this field. This data collection is used by dropdowns and selects to display options. - /// - /// - /// - IEditorFieldConfig SetDataCollection() - where TDataCollection : IDataCollection; - - /// - /// Binds a DataCollection to this field. This data collection is used by dropdowns and selects to display options. - /// - /// - /// - IEditorFieldConfig SetDataCollection(TDataCollection dataCollection) - where TDataCollection : IDataCollection; - - /// - /// Binds a DataCollection to this field. This data collection is used by dropdowns and selects to display options. - /// - /// The TConfig object is passed into the data collection. - /// - /// - /// - /// - IEditorFieldConfig SetDataCollection(TConfig config) - where TDataCollection : IDataCollection; - - /// - /// Binds a DataCollection to this field. This collection is used by dropdowns and selects to display options. - /// - /// - /// - IEditorFieldConfig SetCollectionRelation() - where TDataCollection : IRelationDataCollection; - - /// - /// Binds a DataCollection to this field. This collection is used by dropdowns and selects to display options. - /// - /// - /// - /// - IEditorFieldConfig SetCollectionRelation(TDataCollection dataCollection) - where TDataCollection : IRelationDataCollection; - - /// - /// Binds a DataCollection to this field. This collection is used by dropdowns and selects to display options. - /// - /// - /// - /// - /// - IEditorFieldConfig SetCollectionRelation(TConfig config) - where TDataCollection : IRelationDataCollection; - - /// - /// Binds a Collection to this field. This collection is used by dropdowns and selects to display options. - /// - /// Uses the default Element configuration of the referenced collection to display the options. - /// - /// Alias of the collection to bind. - /// - IEditorFieldConfig SetCollectionRelation(string collectionAlias); - - /// - /// Binds a Collection to this field. This collection is used by dropdowns and selects to display options. - /// - /// Entity of the bound collection. - /// Alias of the collection to bind. - /// Action to configure relation. - /// - IEditorFieldConfig SetCollectionRelation( - string collectionAlias, - Action> configure); - - /// - /// Binds a Collection to this field. This collection is used by dropdowns and selects to display options. - /// - /// Entity of the bound collection. - /// Type of the repository. - /// Action to configure relation. - /// - IEditorFieldConfig SetCollectionRelation( - Action> configure) - where TRelatedRepository : IRepository; - - /// - /// Binds a Collection to this field. This collection is used by dropdowns and selects to display options. - /// - /// Use this overload to bind a collection for a many-to-many relation in EF Core backed repositories: - /// - Use the joining table as property for this editor. - /// - Use the relatedElements expression as selector for selected elements to display in the EditorType.MultiSelect or any other RelationAttribute(RelationType.Many) editor. - /// - /// Entity of the bound collection. - /// Type of the foreign key - /// Expression for selected entities. - /// Alias of the collection to bind. - /// Action to configure relation. - /// - IEditorFieldConfig SetCollectionRelation( - Expression>> relatedElements, - string collectionAlias, - Action> configure); - - /// - /// Binds a Collection to this field. This collection is used by dropdowns and selects to display options. - /// - /// Use this overload to bind a collection for a many-to-many relation in EF Core backed repositories: - /// - Use the joining table as property for this editor. - /// - Use the relatedElements expression as selector for selected elements to display in the EditorType.MultiSelect or any other RelationAttribute(RelationType.Many) editor. - /// - /// Entity of the bound collection. - /// Type of the foreign key - /// Type of the related repository - /// Expression for selected entities. - /// Action to configure relation. - /// - IEditorFieldConfig SetCollectionRelation( - Expression>> relatedElements, - Action> configure) - where TRelatedRepository : IRepository; - - /// - /// Sets an expression which determines whether this field should be visible. - /// - /// - /// - IEditorFieldConfig VisibleWhen(Func predicate); - - /// - /// Sets an expression which determine whether this field should be disabled. - /// - /// - /// - IEditorFieldConfig DisableWhen(Func predicate); - } + /// + /// Sets the type of build-in editor used for this field. + /// + /// + /// + IEditorFieldConfig SetType(EditorType type); + + /// + /// Sets the type of build-in display used for this field. + /// + /// + /// + IEditorFieldConfig SetType(DisplayType type); + + /// + /// Sets the type of custom razor component used for this field. + /// + /// + /// + IEditorFieldConfig SetType(Type type); + + /// + /// Binds a DataCollection to this field. This data collection is used by dropdowns and selects to display options. + /// + /// + /// + IEditorFieldConfig SetDataCollection() + where TDataCollection : IDataCollection; + + /// + /// Binds a DataCollection to this field. This data collection is used by dropdowns and selects to display options. + /// + /// + /// + IEditorFieldConfig SetDataCollection(TDataCollection dataCollection) + where TDataCollection : IDataCollection; + + /// + /// Binds a DataCollection to this field. This data collection is used by dropdowns and selects to display options. + /// + /// The TConfig object is passed into the data collection. + /// + /// + /// + /// + IEditorFieldConfig SetDataCollection(TConfig config) + where TDataCollection : IDataCollection; + + /// + /// Binds a DataCollection to this field. This collection is used by dropdowns and selects to display options. + /// + /// + /// + IEditorFieldConfig SetCollectionRelation() + where TDataCollection : IRelationDataCollection; + + /// + /// Binds a DataCollection to this field. This collection is used by dropdowns and selects to display options. + /// + /// + /// + /// + IEditorFieldConfig SetCollectionRelation(TDataCollection dataCollection) + where TDataCollection : IRelationDataCollection; + + /// + /// Binds a DataCollection to this field. This collection is used by dropdowns and selects to display options. + /// + /// + /// + /// + /// + IEditorFieldConfig SetCollectionRelation(TConfig config) + where TDataCollection : IRelationDataCollection; + + /// + /// Binds a Collection to this field. This collection is used by dropdowns and selects to display options. + /// + /// Uses the default Element configuration of the referenced collection to display the options. + /// + /// Alias of the collection to bind. + /// + IEditorFieldConfig SetCollectionRelation(string collectionAlias); + + /// + /// Binds a Collection to this field. This collection is used by dropdowns and selects to display options. + /// + /// Entity of the bound collection. + /// Alias of the collection to bind. + /// Action to configure relation. + /// + IEditorFieldConfig SetCollectionRelation( + string collectionAlias, + Action> configure); + + /// + /// Binds a Collection to this field. This collection is used by dropdowns and selects to display options. + /// + /// Entity of the bound collection. + /// Type of the repository. + /// Action to configure relation. + /// + IEditorFieldConfig SetCollectionRelation( + Action> configure) + where TRelatedRepository : IRepository; + + /// + /// Binds a Collection to this field. This collection is used by dropdowns and selects to display options. + /// + /// Use this overload to bind a collection for a many-to-many relation in EF Core backed repositories: + /// - Use the joining table as property for this editor. + /// - Use the relatedElements expression as selector for selected elements to display in the EditorType.MultiSelect or any other RelationAttribute(RelationType.Many) editor. + /// + /// Entity of the bound collection. + /// Type of the foreign key + /// Expression for selected entities. + /// Alias of the collection to bind. + /// Action to configure relation. + /// + IEditorFieldConfig SetCollectionRelation( + Expression>> relatedElements, + string collectionAlias, + Action> configure); + + /// + /// Binds a Collection to this field. This collection is used by dropdowns and selects to display options. + /// + /// Use this overload to bind a collection for a many-to-many relation in EF Core backed repositories: + /// - Use the joining table as property for this editor. + /// - Use the relatedElements expression as selector for selected elements to display in the EditorType.MultiSelect or any other RelationAttribute(RelationType.Many) editor. + /// + /// Entity of the bound collection. + /// Type of the foreign key + /// Type of the related repository + /// Expression for selected entities. + /// Action to configure relation. + /// + IEditorFieldConfig SetCollectionRelation( + Expression>> relatedElements, + Action> configure) + where TRelatedRepository : IRepository; + + /// + /// Sets an expression which determines whether this field should be visible. + /// + /// + /// + IEditorFieldConfig VisibleWhen(Func predicate); + + /// + /// Sets an expression which determine whether this field should be disabled. + /// + /// + /// + IEditorFieldConfig DisableWhen(Func predicate); } diff --git a/src/RapidCMS.Core/Abstractions/Config/IEditorPaneConfig.cs b/src/RapidCMS.Core/Abstractions/Config/IEditorPaneConfig.cs index 5d2b0ac4..9acf106a 100644 --- a/src/RapidCMS.Core/Abstractions/Config/IEditorPaneConfig.cs +++ b/src/RapidCMS.Core/Abstractions/Config/IEditorPaneConfig.cs @@ -4,77 +4,76 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Abstractions.Repositories; -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface IEditorPaneConfig : IHasButtons> + where TEntity : IEntity { - public interface IEditorPaneConfig : IHasButtons> - where TEntity : IEntity - { - /// - /// Adds a field to the pane. - /// - /// Expression to edit this field - /// Action to configure this field - /// - IEditorFieldConfig AddField(Expression> propertyExpression, Action>? configure = null); + /// + /// Adds a field to the pane. + /// + /// Expression to edit this field + /// Action to configure this field + /// + IEditorFieldConfig AddField(Expression> propertyExpression, Action>? configure = null); - /// - /// Adds a sub collection to the pane. A sub collection is defined separately, and only referenced by alias. - /// - /// Not visible when EntityState is New. - /// - /// Alias of the sub collection - /// - IEditorPaneConfig AddSubCollectionList(string collectionAlias); + /// + /// Adds a sub collection to the pane. A sub collection is defined separately, and only referenced by alias. + /// + /// Not visible when EntityState is New. + /// + /// Alias of the sub collection + /// + IEditorPaneConfig AddSubCollectionList(string collectionAlias); - /// - /// Adds a sub collection to the pane. A sub collection is defined separately, and only referenced by alias. - /// - /// Not visible when EntityState is New. - /// - /// Type of the sub collections entity - /// Type of the sub repository - /// Action to configure the use of this sub collection - /// - IEditorPaneConfig AddSubCollectionList(Action>? configure = null) - where TSubRepository : IRepository - where TSubEntity : IEntity; + /// + /// Adds a sub collection to the pane. A sub collection is defined separately, and only referenced by alias. + /// + /// Not visible when EntityState is New. + /// + /// Type of the sub collections entity + /// Type of the sub repository + /// Action to configure the use of this sub collection + /// + IEditorPaneConfig AddSubCollectionList(Action>? configure = null) + where TSubRepository : IRepository + where TSubEntity : IEntity; - /// - /// Adds a collection to the pane which is used to view the many-to-many relation between the collection of this pane, and the related collection. - /// The related collection can by any collection. - /// - /// Not visible when EntityState is New. - /// - /// Alias of the related collection - /// - IEditorPaneConfig AddRelatedCollectionList(string collectionAlias); + /// + /// Adds a collection to the pane which is used to view the many-to-many relation between the collection of this pane, and the related collection. + /// The related collection can by any collection. + /// + /// Not visible when EntityState is New. + /// + /// Alias of the related collection + /// + IEditorPaneConfig AddRelatedCollectionList(string collectionAlias); - /// - /// Adds a collection to the pane which is used to view the many-to-many relation between the collection of this pane, and the related collection. - /// The related collection can by any collection. - /// - /// Not visible when EntityState is New. - /// - /// Type of the related collections entity - /// Repository for the related collections - /// Action to configure the related collection - /// - IEditorPaneConfig AddRelatedCollectionList(Action>? configure = null) - where TRelatedRepository : IRepository - where TRelatedEntity : IEntity; + /// + /// Adds a collection to the pane which is used to view the many-to-many relation between the collection of this pane, and the related collection. + /// The related collection can by any collection. + /// + /// Not visible when EntityState is New. + /// + /// Type of the related collections entity + /// Repository for the related collections + /// Action to configure the related collection + /// + IEditorPaneConfig AddRelatedCollectionList(Action>? configure = null) + where TRelatedRepository : IRepository + where TRelatedEntity : IEntity; - /// - /// Adds a label at the top of this pane. - /// - /// Text to display in the label - /// - IEditorPaneConfig SetLabel(string label); + /// + /// Adds a label at the top of this pane. + /// + /// Text to display in the label + /// + IEditorPaneConfig SetLabel(string label); - /// - /// Expression which determines whether this pane should be visible. - /// - /// - /// - IEditorPaneConfig VisibleWhen(Func predicate); - } + /// + /// Expression which determines whether this pane should be visible. + /// + /// + /// + IEditorPaneConfig VisibleWhen(Func predicate); } diff --git a/src/RapidCMS.Core/Abstractions/Config/IFileUploadHandlerConfig.cs b/src/RapidCMS.Core/Abstractions/Config/IFileUploadHandlerConfig.cs index a013fef5..fb851e7f 100644 --- a/src/RapidCMS.Core/Abstractions/Config/IFileUploadHandlerConfig.cs +++ b/src/RapidCMS.Core/Abstractions/Config/IFileUploadHandlerConfig.cs @@ -1,10 +1,9 @@ using System; -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface IFileUploadHandlerConfig { - public interface IFileUploadHandlerConfig - { - string Alias { get; } - Type HandlerType { get; } - } + string Alias { get; } + Type HandlerType { get; } } diff --git a/src/RapidCMS.Core/Abstractions/Config/IHasButtons.cs b/src/RapidCMS.Core/Abstractions/Config/IHasButtons.cs index c9439dc6..970fe518 100644 --- a/src/RapidCMS.Core/Abstractions/Config/IHasButtons.cs +++ b/src/RapidCMS.Core/Abstractions/Config/IHasButtons.cs @@ -3,52 +3,51 @@ using RapidCMS.Core.Abstractions.Handlers; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface IHasButtons { - public interface IHasButtons - { - /// - /// Adds a default button. A default button is a simple button with a fixed CrudType. - /// - /// Type of button to add - /// Text to display on the button - /// Name of ion icon to use (https://developer.microsoft.com/en-us/fluentui#/styles/web/icons) - /// Set to true to make this button to stand out - /// Indicates whether the button should be visible or not - /// - TReturn AddDefaultButton(DefaultButtonType type, string? label = null, string? icon = null, bool isPrimary = false, Func? isVisible = null); + /// + /// Adds a default button. A default button is a simple button with a fixed CrudType. + /// + /// Type of button to add + /// Text to display on the button + /// Name of ion icon to use (https://developer.microsoft.com/en-us/fluentui#/styles/web/icons) + /// Set to true to make this button to stand out + /// Indicates whether the button should be visible or not + /// + TReturn AddDefaultButton(DefaultButtonType type, string? label = null, string? icon = null, bool isPrimary = false, Func? isVisible = null); - /// - /// Adds a custom button. A custom button is a razor component derived from BaseButton, and has a IButtonActionHandler that is invoked when the button is clicked. - /// - /// Type of the button action handler - /// Type of the razor component - /// Text to display on the button - /// Name of ion icon to use (https://developer.microsoft.com/en-us/fluentui#/styles/web/icons) - /// Indicates whether the button should be visible or not - /// - TReturn AddCustomButton(Type buttonType, string? label = null, string? icon = null, Func? isVisible = null) - where TActionHandler : IButtonActionHandler; + /// + /// Adds a custom button. A custom button is a razor component derived from BaseButton, and has a IButtonActionHandler that is invoked when the button is clicked. + /// + /// Type of the button action handler + /// Type of the razor component + /// Text to display on the button + /// Name of ion icon to use (https://developer.microsoft.com/en-us/fluentui#/styles/web/icons) + /// Indicates whether the button should be visible or not + /// + TReturn AddCustomButton(Type buttonType, string? label = null, string? icon = null, Func? isVisible = null) + where TActionHandler : IButtonActionHandler; - /// - /// Adds a pane button. A pane button is a default button that opens a modal which displays the given razor component in it. The razor component must be derived from BaseSideBar. - /// - /// Type of the razor component - /// Text to display on the button - /// Name of ion icon to use (https://developer.microsoft.com/en-us/fluentui#/styles/web/icons) - /// Indicates whether the button should be visible or not - /// - TReturn AddPaneButton(Type paneType, string? label = null, string? icon = null, Func? isVisible = null); + /// + /// Adds a pane button. A pane button is a default button that opens a modal which displays the given razor component in it. The razor component must be derived from BaseSideBar. + /// + /// Type of the razor component + /// Text to display on the button + /// Name of ion icon to use (https://developer.microsoft.com/en-us/fluentui#/styles/web/icons) + /// Indicates whether the button should be visible or not + /// + TReturn AddPaneButton(Type paneType, string? label = null, string? icon = null, Func? isVisible = null); - /// - /// Adds a navigation button. A navigation button uses a TNavigationHandler that instructs the CMS to navigate to a specific view. - /// - /// Type of the navigation handler - /// Text to display on the button - /// Name of ion icon to use (https://developer.microsoft.com/en-us/fluentui#/styles/web/icons) - /// Indicates whether the button should be visible or not - /// - TReturn AddNavigationButton(string? label = null, string? icon = null, Func? isVisible = null) - where TNavigationHandler : INavigationHandler; - } + /// + /// Adds a navigation button. A navigation button uses a TNavigationHandler that instructs the CMS to navigate to a specific view. + /// + /// Type of the navigation handler + /// Text to display on the button + /// Name of ion icon to use (https://developer.microsoft.com/en-us/fluentui#/styles/web/icons) + /// Indicates whether the button should be visible or not + /// + TReturn AddNavigationButton(string? label = null, string? icon = null, Func? isVisible = null) + where TNavigationHandler : INavigationHandler; } diff --git a/src/RapidCMS.Core/Abstractions/Config/IHasColumnVisibility.cs b/src/RapidCMS.Core/Abstractions/Config/IHasColumnVisibility.cs index 66d9c240..ca6aa2f7 100644 --- a/src/RapidCMS.Core/Abstractions/Config/IHasColumnVisibility.cs +++ b/src/RapidCMS.Core/Abstractions/Config/IHasColumnVisibility.cs @@ -1,16 +1,15 @@ using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface IHasColumnVisibility { - public interface IHasColumnVisibility - { - /// - /// Controls whether empty columns in the table should be collapsed. Only required when the - /// collection uses multiple EntityVariants, with separate sets of properties which are not shared between the variants. Collapsing - /// the empty cell will reduce the number of columns required, and makes the table more readable. - /// - /// - /// - TReturn SetColumnVisibility(EmptyVariantColumnVisibility columnVisibility); - } + /// + /// Controls whether empty columns in the table should be collapsed. Only required when the + /// collection uses multiple EntityVariants, with separate sets of properties which are not shared between the variants. Collapsing + /// the empty cell will reduce the number of columns required, and makes the table more readable. + /// + /// + /// + TReturn SetColumnVisibility(EmptyVariantColumnVisibility columnVisibility); } diff --git a/src/RapidCMS.Core/Abstractions/Config/IHasConfigurability.cs b/src/RapidCMS.Core/Abstractions/Config/IHasConfigurability.cs index 8cf13dbb..4539ac73 100644 --- a/src/RapidCMS.Core/Abstractions/Config/IHasConfigurability.cs +++ b/src/RapidCMS.Core/Abstractions/Config/IHasConfigurability.cs @@ -2,35 +2,34 @@ using System.Threading.Tasks; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface IHasConfigurability { - public interface IHasConfigurability - { - /// - /// Sets configuration for the field. This will be made available in the component as Configuration property. - /// Use IWantConfiguration and IRequireConfiguration interfaces to gain access to the GetConfig() extension method. - /// - /// - /// - /// - TReturn SetConfiguration(TConfig config) where TConfig : class; + /// + /// Sets configuration for the field. This will be made available in the component as Configuration property. + /// Use IWantConfiguration and IRequireConfiguration interfaces to gain access to the GetConfig() extension method. + /// + /// + /// + /// + TReturn SetConfiguration(TConfig config) where TConfig : class; - /// - /// Sets configuration for the field. This will be made available in the component as Configuration property. - /// Use IWantConfiguration and IRequireConfiguration interfaces to gain access to the GetConfig() extension method. - /// - /// - /// - /// - TReturn SetConfiguration(Func config) where TConfig : class; + /// + /// Sets configuration for the field. This will be made available in the component as Configuration property. + /// Use IWantConfiguration and IRequireConfiguration interfaces to gain access to the GetConfig() extension method. + /// + /// + /// + /// + TReturn SetConfiguration(Func config) where TConfig : class; - /// - /// Sets configuration for the field. This will be made available in the component as Configuration property. - /// Use IWantConfiguration and IRequireConfiguration interfaces to gain access to the GetConfig() extension method. - /// - /// - /// - /// - TReturn SetConfiguration(Func> config) where TConfig : class; - } + /// + /// Sets configuration for the field. This will be made available in the component as Configuration property. + /// Use IWantConfiguration and IRequireConfiguration interfaces to gain access to the GetConfig() extension method. + /// + /// + /// + /// + TReturn SetConfiguration(Func> config) where TConfig : class; } diff --git a/src/RapidCMS.Core/Abstractions/Config/IHasDisplayPanes.cs b/src/RapidCMS.Core/Abstractions/Config/IHasDisplayPanes.cs index 85af81e5..d9a6ac2c 100644 --- a/src/RapidCMS.Core/Abstractions/Config/IHasDisplayPanes.cs +++ b/src/RapidCMS.Core/Abstractions/Config/IHasDisplayPanes.cs @@ -1,43 +1,42 @@ using System; using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface IHasDisplayPanes + where TEntity : IEntity { - public interface IHasDisplayPanes - where TEntity : IEntity - { - /// - /// Adds a section to the current view. - /// - /// Action to configure the section. - /// - TReturn AddSection(Action> configure); + /// + /// Adds a section to the current view. + /// + /// Action to configure the section. + /// + TReturn AddSection(Action> configure); - /// - /// Adds a section to the current view. - /// - /// Custom razor component that will be used to render this section. Must be derived from BaseSection. - /// Action to configure the section. - /// - TReturn AddSection(Type customSectionType, Action>? configure = null); + /// + /// Adds a section to the current view. + /// + /// Custom razor component that will be used to render this section. Must be derived from BaseSection. + /// Action to configure the section. + /// + TReturn AddSection(Type customSectionType, Action>? configure = null); - /// - /// Adds a section to the current view, tailored for the specific TDerivedEntity EntityVariant. Only entities of that type will use this section. - /// - /// Type of the EntityVariant. - /// Action to configure the section. - /// - TReturn AddSection(Action> configure) - where TDerivedEntity : TEntity; + /// + /// Adds a section to the current view, tailored for the specific TDerivedEntity EntityVariant. Only entities of that type will use this section. + /// + /// Type of the EntityVariant. + /// Action to configure the section. + /// + TReturn AddSection(Action> configure) + where TDerivedEntity : TEntity; - /// - /// Adds a section to the current view, tailored for the specific TDerivedEntity. Only entities of that type will use this section. - /// - /// Type of the EntityVariant. - /// Custom razor component that will be used to render this section. Must be derived from BaseSection. - /// Action to configure the section. - /// - TReturn AddSection(Type? customSectionType, Action>? configure) - where TDerivedEntity : TEntity; - } + /// + /// Adds a section to the current view, tailored for the specific TDerivedEntity. Only entities of that type will use this section. + /// + /// Type of the EntityVariant. + /// Custom razor component that will be used to render this section. Must be derived from BaseSection. + /// Action to configure the section. + /// + TReturn AddSection(Type? customSectionType, Action>? configure) + where TDerivedEntity : TEntity; } diff --git a/src/RapidCMS.Core/Abstractions/Config/IHasDisplayTable.cs b/src/RapidCMS.Core/Abstractions/Config/IHasDisplayTable.cs index ee20c134..30c7c107 100644 --- a/src/RapidCMS.Core/Abstractions/Config/IHasDisplayTable.cs +++ b/src/RapidCMS.Core/Abstractions/Config/IHasDisplayTable.cs @@ -1,43 +1,42 @@ using System; using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface IHasDisplayTable + where TEntity : IEntity { - public interface IHasDisplayTable - where TEntity : IEntity - { - /// - /// Adds a row to the current table. - /// - /// Action to configure the section. - /// - TReturn AddRow(Action> configure); + /// + /// Adds a row to the current table. + /// + /// Action to configure the section. + /// + TReturn AddRow(Action> configure); - /// - /// Adds a row to the current table. - /// - /// Custom razor component that will be used to render this section. Must be derived from BaseSection. - /// Action to configure the section. - /// - TReturn AddRow(Type customSectionType, Action> configure); + /// + /// Adds a row to the current table. + /// + /// Custom razor component that will be used to render this section. Must be derived from BaseSection. + /// Action to configure the section. + /// + TReturn AddRow(Type customSectionType, Action> configure); - /// - /// Adds a row to the current table, tailored for the specific TDerivedEntity EntityVariant. Only entities of that type will use this row. - /// - /// Type of the EntityVariant. - /// Action to configure the section. - /// - TReturn AddRow(Action> configure) - where TDerivedEntity : TEntity; + /// + /// Adds a row to the current table, tailored for the specific TDerivedEntity EntityVariant. Only entities of that type will use this row. + /// + /// Type of the EntityVariant. + /// Action to configure the section. + /// + TReturn AddRow(Action> configure) + where TDerivedEntity : TEntity; - /// - /// Adds a row to the current table, tailored for the specific TDerivedEntity. Only entities of that type will use this section. - /// - /// Type of the EntityVariant. - /// Custom razor component that will be used to render this section. Must be derived from BaseSection. - /// Action to configure the section. - /// - TReturn AddRow(Type? customSectionType, Action> configure) - where TDerivedEntity : TEntity; - } + /// + /// Adds a row to the current table, tailored for the specific TDerivedEntity. Only entities of that type will use this section. + /// + /// Type of the EntityVariant. + /// Custom razor component that will be used to render this section. Must be derived from BaseSection. + /// Action to configure the section. + /// + TReturn AddRow(Type? customSectionType, Action> configure) + where TDerivedEntity : TEntity; } diff --git a/src/RapidCMS.Core/Abstractions/Config/IHasEditorPanes.cs b/src/RapidCMS.Core/Abstractions/Config/IHasEditorPanes.cs index d9c56063..5c1f4399 100644 --- a/src/RapidCMS.Core/Abstractions/Config/IHasEditorPanes.cs +++ b/src/RapidCMS.Core/Abstractions/Config/IHasEditorPanes.cs @@ -1,55 +1,54 @@ using System; using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface IHasEditorPanes + where TEntity : IEntity { - public interface IHasEditorPanes - where TEntity : IEntity - { - /// - /// Adds a section to the current editor. - /// - /// In a ListEditor, a section is a separate block. - /// In a TableEditor, a section is a row. - /// - /// Action to configure the section. - /// - TReturn AddSection(Action> configure); + /// + /// Adds a section to the current editor. + /// + /// In a ListEditor, a section is a separate block. + /// In a TableEditor, a section is a row. + /// + /// Action to configure the section. + /// + TReturn AddSection(Action> configure); - /// - /// Adds a section to the current editor. - /// - /// In a ListEditor, a section is a separate block. - /// In a TableEditor, a section is a row. - /// - /// Custom razor component that will be used to render this section. Must be derived from BaseSection. - /// Action to configure the section. - /// - TReturn AddSection(Type customSectionType, Action>? configure = null); + /// + /// Adds a section to the current editor. + /// + /// In a ListEditor, a section is a separate block. + /// In a TableEditor, a section is a row. + /// + /// Custom razor component that will be used to render this section. Must be derived from BaseSection. + /// Action to configure the section. + /// + TReturn AddSection(Type customSectionType, Action>? configure = null); - /// - /// Adds a section to the current editor, tailored for the specific TDerivedEntity EntityVariant. Only entities of that type will use this section. - /// - /// In a ListEditor, a section is a separate block. - /// In a TableEditor, a section is a row. - /// - /// Type of the EntityVariant. - /// Action to configure the section. - /// - TReturn AddSection(Action> configure) - where TDerivedEntity : TEntity; + /// + /// Adds a section to the current editor, tailored for the specific TDerivedEntity EntityVariant. Only entities of that type will use this section. + /// + /// In a ListEditor, a section is a separate block. + /// In a TableEditor, a section is a row. + /// + /// Type of the EntityVariant. + /// Action to configure the section. + /// + TReturn AddSection(Action> configure) + where TDerivedEntity : TEntity; - /// - /// Adds a section to the current editor, tailored for the specific TDerivedEntity. Only entities of that type will use this section. - /// - /// In a ListEditor, a section is a separate block. - /// In a TableEditor, a section is a row. - /// - /// Type of the EntityVariant. - /// Custom razor component that will be used to render this section. Must be derived from BaseSection. - /// Action to configure the section. - /// - TReturn AddSection(Type? customSectionType, Action>? configure) - where TDerivedEntity : TEntity; - } + /// + /// Adds a section to the current editor, tailored for the specific TDerivedEntity. Only entities of that type will use this section. + /// + /// In a ListEditor, a section is a separate block. + /// In a TableEditor, a section is a row. + /// + /// Type of the EntityVariant. + /// Custom razor component that will be used to render this section. Must be derived from BaseSection. + /// Action to configure the section. + /// + TReturn AddSection(Type? customSectionType, Action>? configure) + where TDerivedEntity : TEntity; } diff --git a/src/RapidCMS.Core/Abstractions/Config/IHasNameDescription.cs b/src/RapidCMS.Core/Abstractions/Config/IHasNameDescription.cs index 6cd00785..ece3e5a4 100644 --- a/src/RapidCMS.Core/Abstractions/Config/IHasNameDescription.cs +++ b/src/RapidCMS.Core/Abstractions/Config/IHasNameDescription.cs @@ -1,28 +1,27 @@ using Microsoft.AspNetCore.Components; -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface IHasNameDescription { - public interface IHasNameDescription - { - /// - /// Sets the name of this field, used in table and list views. - /// - /// - /// - TReturn SetName(string name); + /// + /// Sets the name of this field, used in table and list views. + /// + /// + /// + TReturn SetName(string name); - /// - /// Sets the description of this field, displayed under the name. - /// - /// - /// - TReturn SetDescription(string description); + /// + /// Sets the description of this field, displayed under the name. + /// + /// + /// + TReturn SetDescription(string description); - /// - /// Sets the details of this field, displayed under the control. - /// - /// - /// - TReturn SetDetails(MarkupString details); - } + /// + /// Sets the details of this field, displayed under the control. + /// + /// + /// + TReturn SetDetails(MarkupString details); } diff --git a/src/RapidCMS.Core/Abstractions/Config/IHasOrderBy.cs b/src/RapidCMS.Core/Abstractions/Config/IHasOrderBy.cs index 04b7751e..52bb74f1 100644 --- a/src/RapidCMS.Core/Abstractions/Config/IHasOrderBy.cs +++ b/src/RapidCMS.Core/Abstractions/Config/IHasOrderBy.cs @@ -1,9 +1,8 @@ -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface IHasOrderBy : + IHasOrderByEntity, + IHasOrderByDatabaseEntity { - public interface IHasOrderBy : - IHasOrderByEntity, - IHasOrderByDatabaseEntity - { - - } + } diff --git a/src/RapidCMS.Core/Abstractions/Config/IHasOrderByDatabaseEntity.cs b/src/RapidCMS.Core/Abstractions/Config/IHasOrderByDatabaseEntity.cs index b3e61f2e..c3eb79fb 100644 --- a/src/RapidCMS.Core/Abstractions/Config/IHasOrderByDatabaseEntity.cs +++ b/src/RapidCMS.Core/Abstractions/Config/IHasOrderByDatabaseEntity.cs @@ -2,23 +2,22 @@ using System.Linq.Expressions; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface IHasOrderByDatabaseEntity { - public interface IHasOrderByDatabaseEntity - { - /// - /// Sets an expression that is used for ordering data in a List. - /// - /// Can only be used in List views. - /// Can only be used in Collections with a MappedBaseRepository. TDatabaseEntity must be the same as the TDatabaseEntity used by MappedBaseRepository. - ///

- /// When using order by expressions in DataViews / DataViewBuilders, the List view must have a corresponding OrderByExpression set on the correct field. - ///
- /// Entity used by the Repository to access the data store - /// - /// Expression that is send to the IQueryable in the Repository. - /// Default order (used when user opens page) - /// - TReturn SetOrderByExpression(Expression> orderByExpression, OrderByType defaultOrder = OrderByType.None); - } + /// + /// Sets an expression that is used for ordering data in a List. + /// + /// Can only be used in List views. + /// Can only be used in Collections with a MappedBaseRepository. TDatabaseEntity must be the same as the TDatabaseEntity used by MappedBaseRepository. + ///

+ /// When using order by expressions in DataViews / DataViewBuilders, the List view must have a corresponding OrderByExpression set on the correct field. + ///
+ /// Entity used by the Repository to access the data store + /// + /// Expression that is send to the IQueryable in the Repository. + /// Default order (used when user opens page) + /// + TReturn SetOrderByExpression(Expression> orderByExpression, OrderByType defaultOrder = OrderByType.None); } diff --git a/src/RapidCMS.Core/Abstractions/Config/IHasOrderByEntity.cs b/src/RapidCMS.Core/Abstractions/Config/IHasOrderByEntity.cs index a83b9664..56599213 100644 --- a/src/RapidCMS.Core/Abstractions/Config/IHasOrderByEntity.cs +++ b/src/RapidCMS.Core/Abstractions/Config/IHasOrderByEntity.cs @@ -2,21 +2,20 @@ using System.Linq.Expressions; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface IHasOrderByEntity { - public interface IHasOrderByEntity - { - /// - /// Sets an expression that is used for ordering data in a List. - /// - /// Can only be used in List views. - ///

- /// When using order by expressions in DataViews / DataViewBuilders, the List view must have a corresponding OrderByExpression set on the correct field. - ///
- /// - /// Expression that is send to the IQueryable in the Repository. - /// Default order (used when user opens page) - /// - TReturn SetOrderByExpression(Expression> orderByExpression, OrderByType defaultOrder = OrderByType.None); - } + /// + /// Sets an expression that is used for ordering data in a List. + /// + /// Can only be used in List views. + ///

+ /// When using order by expressions in DataViews / DataViewBuilders, the List view must have a corresponding OrderByExpression set on the correct field. + ///
+ /// + /// Expression that is send to the IQueryable in the Repository. + /// Default order (used when user opens page) + /// + TReturn SetOrderByExpression(Expression> orderByExpression, OrderByType defaultOrder = OrderByType.None); } diff --git a/src/RapidCMS.Core/Abstractions/Config/IHasPageSize.cs b/src/RapidCMS.Core/Abstractions/Config/IHasPageSize.cs index e5ebe104..1532a9ee 100644 --- a/src/RapidCMS.Core/Abstractions/Config/IHasPageSize.cs +++ b/src/RapidCMS.Core/Abstractions/Config/IHasPageSize.cs @@ -1,12 +1,11 @@ -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface IHasPageSize { - public interface IHasPageSize - { - /// - /// Sets the pagesize of the ListEditor. - /// - /// - /// - TReturn SetPageSize(int pageSize); - } + /// + /// Sets the pagesize of the ListEditor. + /// + /// + /// + TReturn SetPageSize(int pageSize); } diff --git a/src/RapidCMS.Core/Abstractions/Config/IHasPlaceholder.cs b/src/RapidCMS.Core/Abstractions/Config/IHasPlaceholder.cs index 7be37e80..0fb0411a 100644 --- a/src/RapidCMS.Core/Abstractions/Config/IHasPlaceholder.cs +++ b/src/RapidCMS.Core/Abstractions/Config/IHasPlaceholder.cs @@ -1,12 +1,11 @@ -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface IHasPlaceholder { - public interface IHasPlaceholder - { - /// - /// Sets the placeholder of this field, displayed in the editor. - /// - /// - /// - TReturn SetPlaceholder(string placeholder); - } + /// + /// Sets the placeholder of this field, displayed in the editor. + /// + /// + /// + TReturn SetPlaceholder(string placeholder); } diff --git a/src/RapidCMS.Core/Abstractions/Config/IHasSearchBar.cs b/src/RapidCMS.Core/Abstractions/Config/IHasSearchBar.cs index e9242ca8..07895992 100644 --- a/src/RapidCMS.Core/Abstractions/Config/IHasSearchBar.cs +++ b/src/RapidCMS.Core/Abstractions/Config/IHasSearchBar.cs @@ -1,12 +1,11 @@ -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface IHasSearchBar { - public interface IHasSearchBar - { - /// - /// Sets the visibility of the search bar atop of the ListEditor. - /// - /// - /// - TReturn SetSearchBarVisibility(bool visible); - } + /// + /// Sets the visibility of the search bar atop of the ListEditor. + /// + /// + /// + TReturn SetSearchBarVisibility(bool visible); } diff --git a/src/RapidCMS.Core/Abstractions/Config/IIsConventionBased.cs b/src/RapidCMS.Core/Abstractions/Config/IIsConventionBased.cs index b580ea57..d53edb25 100644 --- a/src/RapidCMS.Core/Abstractions/Config/IIsConventionBased.cs +++ b/src/RapidCMS.Core/Abstractions/Config/IIsConventionBased.cs @@ -1,9 +1,8 @@ using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +internal interface IIsConventionBased { - internal interface IIsConventionBased - { - Features GetFeatures(); - } + Features GetFeatures(); } diff --git a/src/RapidCMS.Core/Abstractions/Config/IListEditorConfig.cs b/src/RapidCMS.Core/Abstractions/Config/IListEditorConfig.cs index a200a91f..5e4c7ba0 100644 --- a/src/RapidCMS.Core/Abstractions/Config/IListEditorConfig.cs +++ b/src/RapidCMS.Core/Abstractions/Config/IListEditorConfig.cs @@ -1,22 +1,21 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface IListEditorConfig + : IHasButtons>, + IHasPageSize>, + IHasSearchBar>, + IHasEditorPanes>, + ISupportReordering>, + IHasColumnVisibility> + where TEntity : IEntity { - public interface IListEditorConfig - : IHasButtons>, - IHasPageSize>, - IHasSearchBar>, - IHasEditorPanes>, - ISupportReordering>, - IHasColumnVisibility> - where TEntity : IEntity - { - /// - /// Controls how the ListEditor is displayed: each entity as a row in a table, or as a block in a list - /// - /// - /// - IListEditorConfig SetListType(ListType listType); - } + /// + /// Controls how the ListEditor is displayed: each entity as a row in a table, or as a block in a list + /// + /// + /// + IListEditorConfig SetListType(ListType listType); } diff --git a/src/RapidCMS.Core/Abstractions/Config/IListViewConfig.cs b/src/RapidCMS.Core/Abstractions/Config/IListViewConfig.cs index 91bab904..1079d6ec 100644 --- a/src/RapidCMS.Core/Abstractions/Config/IListViewConfig.cs +++ b/src/RapidCMS.Core/Abstractions/Config/IListViewConfig.cs @@ -1,14 +1,13 @@ using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface IListViewConfig + : IHasButtons>, + IHasPageSize>, + IHasSearchBar>, + IHasDisplayTable>, + IHasColumnVisibility> + where TEntity : IEntity { - public interface IListViewConfig - : IHasButtons>, - IHasPageSize>, - IHasSearchBar>, - IHasDisplayTable>, - IHasColumnVisibility> - where TEntity : IEntity - { - } } diff --git a/src/RapidCMS.Core/Abstractions/Config/INodeEditorConfig.cs b/src/RapidCMS.Core/Abstractions/Config/INodeEditorConfig.cs index ab13573e..c5b03c81 100644 --- a/src/RapidCMS.Core/Abstractions/Config/INodeEditorConfig.cs +++ b/src/RapidCMS.Core/Abstractions/Config/INodeEditorConfig.cs @@ -1,12 +1,11 @@ using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface INodeEditorConfig + : IHasButtons>, + IHasEditorPanes> + where TEntity : IEntity { - public interface INodeEditorConfig - : IHasButtons>, - IHasEditorPanes> - where TEntity : IEntity - { - } } diff --git a/src/RapidCMS.Core/Abstractions/Config/INodeViewConfig.cs b/src/RapidCMS.Core/Abstractions/Config/INodeViewConfig.cs index c713ec26..f9d5d382 100644 --- a/src/RapidCMS.Core/Abstractions/Config/INodeViewConfig.cs +++ b/src/RapidCMS.Core/Abstractions/Config/INodeViewConfig.cs @@ -1,12 +1,11 @@ using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface INodeViewConfig + : IHasButtons>, + IHasDisplayPanes> + where TEntity : IEntity { - public interface INodeViewConfig - : IHasButtons>, - IHasDisplayPanes> - where TEntity : IEntity - { - } } diff --git a/src/RapidCMS.Core/Abstractions/Config/IOrderByConfig.cs b/src/RapidCMS.Core/Abstractions/Config/IOrderByConfig.cs index 6b50882b..41822fa2 100644 --- a/src/RapidCMS.Core/Abstractions/Config/IOrderByConfig.cs +++ b/src/RapidCMS.Core/Abstractions/Config/IOrderByConfig.cs @@ -1,7 +1,6 @@ -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface IOrderByConfig : IHasOrderBy> { - public interface IOrderByConfig : IHasOrderBy> - { - } } diff --git a/src/RapidCMS.Core/Abstractions/Config/IPageConfig.cs b/src/RapidCMS.Core/Abstractions/Config/IPageConfig.cs index 777253fd..bbfc35c1 100644 --- a/src/RapidCMS.Core/Abstractions/Config/IPageConfig.cs +++ b/src/RapidCMS.Core/Abstractions/Config/IPageConfig.cs @@ -2,27 +2,26 @@ using System.Collections.Generic; using RapidCMS.Core.Models.Config; -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface IPageConfig : ITreeElementConfig { - public interface IPageConfig : ITreeElementConfig - { - /// - /// Adds a section to the list of components to draw on this page. - /// Use the edit flag to indicate whether this should be the editor or the view variant of the collection. - /// - /// Alias of a collection - /// Set to true to use the ListEditor, otherwise the ListView is used - /// - IPageConfig AddSection(string collectionAlias, bool edit = false); + /// + /// Adds a section to the list of components to draw on this page. + /// Use the edit flag to indicate whether this should be the editor or the view variant of the collection. + /// + /// Alias of a collection + /// Set to true to use the ListEditor, otherwise the ListView is used + /// + IPageConfig AddSection(string collectionAlias, bool edit = false); - /// - /// Adds a razor component to the list of components to draw on the dashboard, the homepage of the CMS. - /// - /// Type of the razor component to draw. - /// - IPageConfig AddSection(Type customSectionType); + /// + /// Adds a razor component to the list of components to draw on the dashboard, the homepage of the CMS. + /// + /// Type of the razor component to draw. + /// + IPageConfig AddSection(Type customSectionType); - string Icon { get; } - string Color { get; } - } + string Icon { get; } + string Color { get; } } diff --git a/src/RapidCMS.Core/Abstractions/Config/IRelatedCollectionListEditorConfig.cs b/src/RapidCMS.Core/Abstractions/Config/IRelatedCollectionListEditorConfig.cs index 03f3c29b..60cedb6b 100644 --- a/src/RapidCMS.Core/Abstractions/Config/IRelatedCollectionListEditorConfig.cs +++ b/src/RapidCMS.Core/Abstractions/Config/IRelatedCollectionListEditorConfig.cs @@ -2,17 +2,16 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Abstractions.Repositories; -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface IRelatedCollectionListEditorConfig + where TRelatedRepository : IRepository + where TRelatedEntity : IEntity { - public interface IRelatedCollectionListEditorConfig - where TRelatedRepository : IRepository - where TRelatedEntity : IEntity - { - /// - /// Sets the ListEditor of this related collection - /// - /// Action used to configure the ListEditor - /// - IRelatedCollectionListEditorConfig SetListEditor(Action> configure); - } + /// + /// Sets the ListEditor of this related collection + /// + /// Action used to configure the ListEditor + /// + IRelatedCollectionListEditorConfig SetListEditor(Action> configure); } diff --git a/src/RapidCMS.Core/Abstractions/Config/IRelatedCollectionListViewConfig.cs b/src/RapidCMS.Core/Abstractions/Config/IRelatedCollectionListViewConfig.cs index 6884e1da..ac72d6d4 100644 --- a/src/RapidCMS.Core/Abstractions/Config/IRelatedCollectionListViewConfig.cs +++ b/src/RapidCMS.Core/Abstractions/Config/IRelatedCollectionListViewConfig.cs @@ -2,17 +2,16 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Abstractions.Repositories; -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface IRelatedCollectionListViewConfig + where TRelatedRepository : IRepository + where TRelatedEntity : IEntity { - public interface IRelatedCollectionListViewConfig - where TRelatedRepository : IRepository - where TRelatedEntity : IEntity - { - /// - /// Sets the ListView of this related collection - /// - /// Action used to configure the ListView - /// - IRelatedCollectionListViewConfig SetListView(Action> configure); - } + /// + /// Sets the ListView of this related collection + /// + /// Action used to configure the ListView + /// + IRelatedCollectionListViewConfig SetListView(Action> configure); } diff --git a/src/RapidCMS.Core/Abstractions/Config/ISubCollectionListEditorConfig.cs b/src/RapidCMS.Core/Abstractions/Config/ISubCollectionListEditorConfig.cs index 992e734e..f26ddf58 100644 --- a/src/RapidCMS.Core/Abstractions/Config/ISubCollectionListEditorConfig.cs +++ b/src/RapidCMS.Core/Abstractions/Config/ISubCollectionListEditorConfig.cs @@ -2,17 +2,16 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Abstractions.Repositories; -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface ISubCollectionListEditorConfig + where TSubRepository : IRepository + where TSubEntity : IEntity { - public interface ISubCollectionListEditorConfig - where TSubRepository : IRepository - where TSubEntity : IEntity - { - /// - /// Sets the ListEditor of this related collection - /// - /// Action used to configure the ListEditor - /// - ISubCollectionListEditorConfig SetListEditor(Action> configure); - } + /// + /// Sets the ListEditor of this related collection + /// + /// Action used to configure the ListEditor + /// + ISubCollectionListEditorConfig SetListEditor(Action> configure); } diff --git a/src/RapidCMS.Core/Abstractions/Config/ISubCollectionListViewConfig.cs b/src/RapidCMS.Core/Abstractions/Config/ISubCollectionListViewConfig.cs index 5ba5317a..7217ea50 100644 --- a/src/RapidCMS.Core/Abstractions/Config/ISubCollectionListViewConfig.cs +++ b/src/RapidCMS.Core/Abstractions/Config/ISubCollectionListViewConfig.cs @@ -2,17 +2,16 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Abstractions.Repositories; -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface ISubCollectionListViewConfig + where TSubRepository : IRepository + where TSubEntity : IEntity { - public interface ISubCollectionListViewConfig - where TSubRepository : IRepository - where TSubEntity : IEntity - { - /// - /// Sets the ListView of this related collection - /// - /// Action used to configure the ListView - /// - ISubCollectionListViewConfig SetListView(Action> configure); - } + /// + /// Sets the ListView of this related collection + /// + /// Action used to configure the ListView + /// + ISubCollectionListViewConfig SetListView(Action> configure); } diff --git a/src/RapidCMS.Core/Abstractions/Config/ISupportReordering.cs b/src/RapidCMS.Core/Abstractions/Config/ISupportReordering.cs index e8804279..09f33ace 100644 --- a/src/RapidCMS.Core/Abstractions/Config/ISupportReordering.cs +++ b/src/RapidCMS.Core/Abstractions/Config/ISupportReordering.cs @@ -1,11 +1,10 @@ -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface ISupportReordering { - public interface ISupportReordering - { - /// - /// Allows entities to be reordered in the ListEditor. - /// - /// - TReturn AllowReordering(bool allowReordering); - } + /// + /// Allows entities to be reordered in the ListEditor. + /// + /// + TReturn AllowReordering(bool allowReordering); } diff --git a/src/RapidCMS.Core/Abstractions/Config/ITreeElementConfig.cs b/src/RapidCMS.Core/Abstractions/Config/ITreeElementConfig.cs index 58b411d4..76e198fe 100644 --- a/src/RapidCMS.Core/Abstractions/Config/ITreeElementConfig.cs +++ b/src/RapidCMS.Core/Abstractions/Config/ITreeElementConfig.cs @@ -1,8 +1,7 @@ -namespace RapidCMS.Core.Abstractions.Config +namespace RapidCMS.Core.Abstractions.Config; + +public interface ITreeElementConfig { - public interface ITreeElementConfig - { - string Alias { get; } - string Name { get; } - } + string Alias { get; } + string Name { get; } } diff --git a/src/RapidCMS.Core/Abstractions/Data/IDataCollection.cs b/src/RapidCMS.Core/Abstractions/Data/IDataCollection.cs index 158991d7..1a2798c8 100644 --- a/src/RapidCMS.Core/Abstractions/Data/IDataCollection.cs +++ b/src/RapidCMS.Core/Abstractions/Data/IDataCollection.cs @@ -4,35 +4,34 @@ using RapidCMS.Core.Abstractions.Metadata; using RapidCMS.Core.Forms; -namespace RapidCMS.Core.Abstractions.Data +namespace RapidCMS.Core.Abstractions.Data; + +public interface IDataCollection : IDisposable { - public interface IDataCollection : IDisposable - { - /// - /// This method is called after construction when a configuration object was provided using SetDataCollection<TDataCollection, TConfig>(TConfig). - /// - /// - void Configure(object configuration); + /// + /// This method is called after construction when a configuration object was provided using SetDataCollection<TDataCollection, TConfig>(TConfig). + /// + /// + void Configure(object configuration); - /// - /// Use this method to receive the EditContext for which this data collection is used. This allows for making the available elements contextual to the entity. - /// - /// EditContext for which this data collection is used. - /// Property for which this data collection is used. - /// The parent(s) of the entity. - /// - Task SetEntityAsync(FormEditContext editContext, IPropertyMetadata property, IParent? parent); + /// + /// Use this method to receive the EditContext for which this data collection is used. This allows for making the available elements contextual to the entity. + /// + /// EditContext for which this data collection is used. + /// Property for which this data collection is used. + /// The parent(s) of the entity. + /// + Task SetEntityAsync(FormEditContext editContext, IPropertyMetadata property, IParent? parent); - /// - /// This method is called when the editor which this data collection requests elements to display. - /// - /// A query for filtering the elements. Not all editors will issue meaningful queries. - /// - Task> GetAvailableElementsAsync(IView view); + /// + /// This method is called when the editor which this data collection requests elements to display. + /// + /// A query for filtering the elements. Not all editors will issue meaningful queries. + /// + Task> GetAvailableElementsAsync(IView view); - /// - /// The editor using this data collection will refresh its UI when this event is invoked. Use this to refresh the UI when the available elements changes. - /// - event EventHandler OnDataChange; - } + /// + /// The editor using this data collection will refresh its UI when this event is invoked. Use this to refresh the UI when the available elements changes. + /// + event EventHandler OnDataChange; } diff --git a/src/RapidCMS.Core/Abstractions/Data/IDataValidationProvider.cs b/src/RapidCMS.Core/Abstractions/Data/IDataValidationProvider.cs index b148c658..9c7c3ac8 100644 --- a/src/RapidCMS.Core/Abstractions/Data/IDataValidationProvider.cs +++ b/src/RapidCMS.Core/Abstractions/Data/IDataValidationProvider.cs @@ -1,9 +1,8 @@ using RapidCMS.Core.Abstractions.Metadata; -namespace RapidCMS.Core.Abstractions.Data +namespace RapidCMS.Core.Abstractions.Data; + +internal interface IDataValidationProvider { - internal interface IDataValidationProvider - { - IPropertyMetadata Property { get; } - } + IPropertyMetadata Property { get; } } diff --git a/src/RapidCMS.Core/Abstractions/Data/IDataView.cs b/src/RapidCMS.Core/Abstractions/Data/IDataView.cs index 4d82e9b5..5b0e5423 100644 --- a/src/RapidCMS.Core/Abstractions/Data/IDataView.cs +++ b/src/RapidCMS.Core/Abstractions/Data/IDataView.cs @@ -3,28 +3,27 @@ using RapidCMS.Core.Abstractions.Metadata; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Abstractions.Data +namespace RapidCMS.Core.Abstractions.Data; + +public interface IDataView { - public interface IDataView - { - /// - /// Id of the data view. - /// - int Id { get; } + /// + /// Id of the data view. + /// + int Id { get; } - /// - /// Display label of the data view. - /// - string Label { get; } + /// + /// Display label of the data view. + /// + string Label { get; } - /// - /// Associated query expression of this data view. - /// - LambdaExpression QueryExpression { get; } + /// + /// Associated query expression of this data view. + /// + LambdaExpression QueryExpression { get; } - /// - /// Default sorts for this data view. - /// - IEnumerable> DefaultOrderBys { get; } - } + /// + /// Default sorts for this data view. + /// + IEnumerable> DefaultOrderBys { get; } } diff --git a/src/RapidCMS.Core/Abstractions/Data/IDataViewBuilder.cs b/src/RapidCMS.Core/Abstractions/Data/IDataViewBuilder.cs index 1d5b7420..1eeb29d4 100644 --- a/src/RapidCMS.Core/Abstractions/Data/IDataViewBuilder.cs +++ b/src/RapidCMS.Core/Abstractions/Data/IDataViewBuilder.cs @@ -1,10 +1,9 @@ using System.Collections.Generic; using System.Threading.Tasks; -namespace RapidCMS.Core.Abstractions.Data +namespace RapidCMS.Core.Abstractions.Data; + +public interface IDataViewBuilder { - public interface IDataViewBuilder - { - Task> GetDataViewsAsync(); - } + Task> GetDataViewsAsync(); } diff --git a/src/RapidCMS.Core/Abstractions/Data/IElement.cs b/src/RapidCMS.Core/Abstractions/Data/IElement.cs index 9f03cd5f..b6662d81 100644 --- a/src/RapidCMS.Core/Abstractions/Data/IElement.cs +++ b/src/RapidCMS.Core/Abstractions/Data/IElement.cs @@ -1,11 +1,10 @@ using System.Collections.Generic; -namespace RapidCMS.Core.Abstractions.Data +namespace RapidCMS.Core.Abstractions.Data; + +public interface IElement { - public interface IElement - { - object Id { get; } + object Id { get; } - IEnumerable Labels { get; } - } + IEnumerable Labels { get; } } diff --git a/src/RapidCMS.Core/Abstractions/Data/IEntity.cs b/src/RapidCMS.Core/Abstractions/Data/IEntity.cs index 058dea61..8a1d82b2 100644 --- a/src/RapidCMS.Core/Abstractions/Data/IEntity.cs +++ b/src/RapidCMS.Core/Abstractions/Data/IEntity.cs @@ -1,7 +1,6 @@ -namespace RapidCMS.Core.Abstractions.Data +namespace RapidCMS.Core.Abstractions.Data; + +public interface IEntity { - public interface IEntity - { - string? Id { get; set; } - } + string? Id { get; set; } } diff --git a/src/RapidCMS.Core/Abstractions/Data/IFileInfo.cs b/src/RapidCMS.Core/Abstractions/Data/IFileInfo.cs index e677b504..31908a50 100644 --- a/src/RapidCMS.Core/Abstractions/Data/IFileInfo.cs +++ b/src/RapidCMS.Core/Abstractions/Data/IFileInfo.cs @@ -1,14 +1,13 @@ using System; using System.Collections.Generic; -namespace RapidCMS.Core.Abstractions.Data +namespace RapidCMS.Core.Abstractions.Data; + +public interface IFileInfo { - public interface IFileInfo - { - string Name { get; } - long Size { get; } - string Type { get; } - long? LastModified { get; } - DateTime? LastModifiedDate { get; } - } + string Name { get; } + long Size { get; } + string Type { get; } + long? LastModified { get; } + DateTime? LastModifiedDate { get; } } diff --git a/src/RapidCMS.Core/Abstractions/Data/IOrderBy.cs b/src/RapidCMS.Core/Abstractions/Data/IOrderBy.cs index d5a41e40..eb3d6823 100644 --- a/src/RapidCMS.Core/Abstractions/Data/IOrderBy.cs +++ b/src/RapidCMS.Core/Abstractions/Data/IOrderBy.cs @@ -1,28 +1,27 @@ using RapidCMS.Core.Abstractions.Metadata; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Abstractions.Data +namespace RapidCMS.Core.Abstractions.Data; + +public interface IOrderBy { - public interface IOrderBy - { - /// - /// Direction of this order by. - /// - OrderByType OrderByType { get; } + /// + /// Direction of this order by. + /// + OrderByType OrderByType { get; } - /// - /// Expression specifying how the sorting is done. - /// - IPropertyMetadata OrderByExpression { get; } + /// + /// Expression specifying how the sorting is done. + /// + IPropertyMetadata OrderByExpression { get; } - /// - /// Property to which this order by is applied (when used in Editor). - /// - IPropertyMetadata? Property { get; } + /// + /// Property to which this order by is applied (when used in Editor). + /// + IPropertyMetadata? Property { get; } - /// - /// Expression to which this order by is applied (when used in View). - /// - IExpressionMetadata? Expression { get; } - } + /// + /// Expression to which this order by is applied (when used in View). + /// + IExpressionMetadata? Expression { get; } } diff --git a/src/RapidCMS.Core/Abstractions/Data/IParent.cs b/src/RapidCMS.Core/Abstractions/Data/IParent.cs index b995c9a0..4dacc562 100644 --- a/src/RapidCMS.Core/Abstractions/Data/IParent.cs +++ b/src/RapidCMS.Core/Abstractions/Data/IParent.cs @@ -1,12 +1,11 @@ using RapidCMS.Core.Models.Data; -namespace RapidCMS.Core.Abstractions.Data +namespace RapidCMS.Core.Abstractions.Data; + +public interface IParent { - public interface IParent - { - IParent? Parent { get; } - IEntity Entity { get; } + IParent? Parent { get; } + IEntity Entity { get; } - ParentPath? GetParentPath(); - } + ParentPath? GetParentPath(); } diff --git a/src/RapidCMS.Core/Abstractions/Data/IRelated.cs b/src/RapidCMS.Core/Abstractions/Data/IRelated.cs index 38e63190..527069aa 100644 --- a/src/RapidCMS.Core/Abstractions/Data/IRelated.cs +++ b/src/RapidCMS.Core/Abstractions/Data/IRelated.cs @@ -1,10 +1,9 @@ -namespace RapidCMS.Core.Abstractions.Data +namespace RapidCMS.Core.Abstractions.Data; + +public interface IRelated { - public interface IRelated - { - IParent? Parent { get; } - IEntity Entity { get; } + IParent? Parent { get; } + IEntity Entity { get; } - string RepositoryAlias { get; } - } + string RepositoryAlias { get; } } diff --git a/src/RapidCMS.Core/Abstractions/Data/IRelation.cs b/src/RapidCMS.Core/Abstractions/Data/IRelation.cs index 3203d767..0764fdd6 100644 --- a/src/RapidCMS.Core/Abstractions/Data/IRelation.cs +++ b/src/RapidCMS.Core/Abstractions/Data/IRelation.cs @@ -2,13 +2,12 @@ using System.Collections.Generic; using RapidCMS.Core.Abstractions.Metadata; -namespace RapidCMS.Core.Abstractions.Data +namespace RapidCMS.Core.Abstractions.Data; + +public interface IRelation { - public interface IRelation - { - Type RelatedEntityType { get; } - IPropertyMetadata Property { get; } - IReadOnlyList RelatedElementIds { get; } - IReadOnlyList RelatedElementIdsAs(); - } + Type RelatedEntityType { get; } + IPropertyMetadata Property { get; } + IReadOnlyList RelatedElementIds { get; } + IReadOnlyList RelatedElementIdsAs(); } diff --git a/src/RapidCMS.Core/Abstractions/Data/IRelationDataCollection.cs b/src/RapidCMS.Core/Abstractions/Data/IRelationDataCollection.cs index 607a3cf3..3e7c682b 100644 --- a/src/RapidCMS.Core/Abstractions/Data/IRelationDataCollection.cs +++ b/src/RapidCMS.Core/Abstractions/Data/IRelationDataCollection.cs @@ -2,19 +2,18 @@ using System.Collections.Generic; using System.Threading.Tasks; -namespace RapidCMS.Core.Abstractions.Data +namespace RapidCMS.Core.Abstractions.Data; + +public interface IRelationDataCollection : IDataCollection { - public interface IRelationDataCollection : IDataCollection - { - Task> GetRelatedElementsAsync(); + Task> GetRelatedElementsAsync(); - void AddElement(object id); - void RemoveElement(object id); + void AddElement(object id); + void RemoveElement(object id); - bool IsRelated(object id); + bool IsRelated(object id); - IReadOnlyList GetCurrentRelatedElementIds(); + IReadOnlyList GetCurrentRelatedElementIds(); - Type GetRelatedEntityType(); - } + Type GetRelatedEntityType(); } diff --git a/src/RapidCMS.Core/Abstractions/Data/IView.cs b/src/RapidCMS.Core/Abstractions/Data/IView.cs index f58fc058..df4f3ecf 100644 --- a/src/RapidCMS.Core/Abstractions/Data/IView.cs +++ b/src/RapidCMS.Core/Abstractions/Data/IView.cs @@ -1,60 +1,59 @@ using System.Collections.Generic; using System.Linq; -namespace RapidCMS.Core.Abstractions.Data +namespace RapidCMS.Core.Abstractions.Data; + +public interface IView +{ + int Skip { get; } + int Take { get; } + string? SearchTerm { get; } + + int? ActiveTab { get; } + + /// + /// Call this method to indicate whether there is more data for the next page + /// + /// + void HasMoreData(bool hasMoreData); + + void SetDataView(IDataView dataView); + + /// + /// True when the repository has called HasModeData(true) + /// + bool MoreDataAvailable { get; } + + /// + /// Gets the active dataview selected by the user. Use ApplyDataView to apply the QueryExpression to your IQueryable. + /// + /// Use this property to determine what the active data view Id is, when your repository does not support IQueryable. + /// + IDataView? ActiveDataView { get; } + + /// + /// Gets the active order by instructions selected by the user. Use ApplyOrder to apply the ordering to your IQuerable. + /// + /// Use this property to determine what the active order by instructions are, when your repository does not support IQueryable. + /// + IEnumerable ActiveOrderBys { get; } + + string? CollectionAlias { get; set; } +} + +public interface IView : IView { - public interface IView - { - int Skip { get; } - int Take { get; } - string? SearchTerm { get; } - - int? ActiveTab { get; } - - /// - /// Call this method to indicate whether there is more data for the next page - /// - /// - void HasMoreData(bool hasMoreData); - - void SetDataView(IDataView dataView); - - /// - /// True when the repository has called HasModeData(true) - /// - bool MoreDataAvailable { get; } - - /// - /// Gets the active dataview selected by the user. Use ApplyDataView to apply the QueryExpression to your IQueryable. - /// - /// Use this property to determine what the active data view Id is, when your repository does not support IQueryable. - /// - IDataView? ActiveDataView { get; } - - /// - /// Gets the active order by instructions selected by the user. Use ApplyOrder to apply the ordering to your IQuerable. - /// - /// Use this property to determine what the active order by instructions are, when your repository does not support IQueryable. - /// - IEnumerable ActiveOrderBys { get; } - - string? CollectionAlias { get; set; } - } - - public interface IView : IView - { - /// - /// Method that applies the effective data view selected by the user. - /// - /// Queryable that will be returned with additional Where specified in DataViewBuilder. - /// - IQueryable ApplyDataView(IQueryable queryable); - - /// - /// Method that applies the effective ordering specified by the user. - /// - /// Queryable that will be returned with additional OrderBy(Descending)s and ThenBy(Descending)s. - /// - IQueryable ApplyOrder(IQueryable queryable); - } + /// + /// Method that applies the effective data view selected by the user. + /// + /// Queryable that will be returned with additional Where specified in DataViewBuilder. + /// + IQueryable ApplyDataView(IQueryable queryable); + + /// + /// Method that applies the effective ordering specified by the user. + /// + /// Queryable that will be returned with additional OrderBy(Descending)s and ThenBy(Descending)s. + /// + IQueryable ApplyOrder(IQueryable queryable); } diff --git a/src/RapidCMS.Core/Abstractions/Dispatchers/IInteractionDispatcher.cs b/src/RapidCMS.Core/Abstractions/Dispatchers/IInteractionDispatcher.cs index 05b427bd..ae75fd3d 100644 --- a/src/RapidCMS.Core/Abstractions/Dispatchers/IInteractionDispatcher.cs +++ b/src/RapidCMS.Core/Abstractions/Dispatchers/IInteractionDispatcher.cs @@ -1,13 +1,12 @@ using System.Threading.Tasks; -namespace RapidCMS.Core.Abstractions.Dispatchers +namespace RapidCMS.Core.Abstractions.Dispatchers; + +internal interface IInteractionDispatcher { - internal interface IInteractionDispatcher - { - } +} - internal interface IInteractionDispatcher : IInteractionDispatcher - { - Task InvokeAsync(TRequest request); - } +internal interface IInteractionDispatcher : IInteractionDispatcher +{ + Task InvokeAsync(TRequest request); } diff --git a/src/RapidCMS.Core/Abstractions/Dispatchers/IPresentationDispatcher.cs b/src/RapidCMS.Core/Abstractions/Dispatchers/IPresentationDispatcher.cs index 11a741a0..51b39611 100644 --- a/src/RapidCMS.Core/Abstractions/Dispatchers/IPresentationDispatcher.cs +++ b/src/RapidCMS.Core/Abstractions/Dispatchers/IPresentationDispatcher.cs @@ -1,15 +1,14 @@ using System.Threading.Tasks; -namespace RapidCMS.Core.Abstractions.Dispatchers +namespace RapidCMS.Core.Abstractions.Dispatchers; + +internal interface IPresentationDispatcher { - internal interface IPresentationDispatcher - { - } +} - internal interface IPresentationDispatcher : IPresentationDispatcher - where TResponse : class - { - Task GetAsync(TRequest request); - } +internal interface IPresentationDispatcher : IPresentationDispatcher + where TResponse : class +{ + Task GetAsync(TRequest request); } diff --git a/src/RapidCMS.Core/Abstractions/Factories/IEditContextResolver.cs b/src/RapidCMS.Core/Abstractions/Factories/IEditContextResolver.cs index d39122db..ef37f99a 100644 --- a/src/RapidCMS.Core/Abstractions/Factories/IEditContextResolver.cs +++ b/src/RapidCMS.Core/Abstractions/Factories/IEditContextResolver.cs @@ -6,19 +6,18 @@ using RapidCMS.Core.Enums; using RapidCMS.Core.Forms; -namespace RapidCMS.Core.Abstractions.Factories +namespace RapidCMS.Core.Abstractions.Factories; + +// TODO: this factory has too much parameters +internal interface IEditContextFactory { - // TODO: this factory has too much parameters - internal interface IEditContextFactory - { - Task GetEditContextWrapperAsync(FormEditContext editContext); - Task GetEditContextWrapperAsync( - UsageType usageType, - EntityState entityState, - Type repositoryEntityType, - IEntity updatedEntity, - IEntity referenceEntity, - IParent? parent, - IEnumerable<(string propertyName, string typeName, IEnumerable elements)> relations); - } + Task GetEditContextWrapperAsync(FormEditContext editContext); + Task GetEditContextWrapperAsync( + UsageType usageType, + EntityState entityState, + Type repositoryEntityType, + IEntity updatedEntity, + IEntity referenceEntity, + IParent? parent, + IEnumerable<(string propertyName, string typeName, IEnumerable elements)> relations); } diff --git a/src/RapidCMS.Core/Abstractions/Factories/IUIResolverFactory.cs b/src/RapidCMS.Core/Abstractions/Factories/IUIResolverFactory.cs index 2dfefc77..482dd07a 100644 --- a/src/RapidCMS.Core/Abstractions/Factories/IUIResolverFactory.cs +++ b/src/RapidCMS.Core/Abstractions/Factories/IUIResolverFactory.cs @@ -3,14 +3,13 @@ using RapidCMS.Core.Abstractions.Resolvers; using RapidCMS.Core.Navigation; -namespace RapidCMS.Core.Abstractions.Factories +namespace RapidCMS.Core.Abstractions.Factories; + +public interface IUIResolverFactory { - public interface IUIResolverFactory - { - Task GetNodeUIResolverAsync(NavigationState navigationState); + Task GetNodeUIResolverAsync(NavigationState navigationState); - Task GetListUIResolverAsync(NavigationState navigationState); + Task GetListUIResolverAsync(NavigationState navigationState); - Task GetConventionNodeUIResolverAsync(Type model); - } + Task GetConventionNodeUIResolverAsync(Type model); } diff --git a/src/RapidCMS.Core/Abstractions/Forms/IEditContext.cs b/src/RapidCMS.Core/Abstractions/Forms/IEditContext.cs index 6fe2c0a5..5d7bdefe 100644 --- a/src/RapidCMS.Core/Abstractions/Forms/IEditContext.cs +++ b/src/RapidCMS.Core/Abstractions/Forms/IEditContext.cs @@ -6,126 +6,125 @@ using RapidCMS.Core.Exceptions; using RapidCMS.Core.Forms; -namespace RapidCMS.Core.Abstractions.Forms +namespace RapidCMS.Core.Abstractions.Forms; + +public interface IEditContext { - public interface IEditContext - { - /// - /// Checks whether the given data is valid according to the model's validation attributes. - /// - /// IMPORTANT: - /// - /// In the case of using ServerSide/WebAssembly RapidCMS: The EditContext will only validate the properties - /// that were touched by the form and that were visible (included) on the form. - /// - /// In the case of using Api RapidCMS: The EditContext will only validate the properties that were - /// modified by the Api call, so [Required] parameters won't always be caught (the Api cannot be sure whether - /// the omitted property was included on the form. - /// - /// Use EnforceCompleteValidation to strictly validate the complete model, which will also check properties - /// that were not included on the form or in the Api call. - /// - /// - Task IsValidAsync(); + /// + /// Checks whether the given data is valid according to the model's validation attributes. + /// + /// IMPORTANT: + /// + /// In the case of using ServerSide/WebAssembly RapidCMS: The EditContext will only validate the properties + /// that were touched by the form and that were visible (included) on the form. + /// + /// In the case of using Api RapidCMS: The EditContext will only validate the properties that were + /// modified by the Api call, so [Required] parameters won't always be caught (the Api cannot be sure whether + /// the omitted property was included on the form. + /// + /// Use EnforceCompleteValidation to strictly validate the complete model, which will also check properties + /// that were not included on the form or in the Api call. + /// + /// + Task IsValidAsync(); - /// - /// Checks all the properties of the model (regardless of their inclusion) and will throw when the model is not valid. - /// - /// Thrown when the given entity has validation errors. - Task EnforceCompleteValidationAsync(); + /// + /// Checks all the properties of the model (regardless of their inclusion) and will throw when the model is not valid. + /// + /// Thrown when the given entity has validation errors. + Task EnforceCompleteValidationAsync(); - /// - /// Throws an exception when the entity is invalid. - /// - /// Thrown when the given entity has validation errors. - Task EnforceValidEntityAsync(); + /// + /// Throws an exception when the entity is invalid. + /// + /// Thrown when the given entity has validation errors. + Task EnforceValidEntityAsync(); - /// - /// Gets the ModelStateDirectory containing all validation errors, to be used in BadRequest() responses etc. - /// - ModelStateDictionary ValidationErrors { get; } + /// + /// Gets the ModelStateDirectory containing all validation errors, to be used in BadRequest() responses etc. + /// + ModelStateDictionary ValidationErrors { get; } - /// - /// Alias of the collection this edit context is used in - /// - string CollectionAlias { get; } + /// + /// Alias of the collection this edit context is used in + /// + string CollectionAlias { get; } - void AddValidationError(string propertyName, string message); - } + void AddValidationError(string propertyName, string message); +} - public interface IEditContext : IEditContext - where TEntity : IEntity - { - /// - /// Indicates how the entity was used. - /// - UsageType UsageType { get; } - /// - /// Indicates the state of the entity, new or existing. - /// - EntityState EntityState { get; } +public interface IEditContext : IEditContext + where TEntity : IEntity +{ + /// + /// Indicates how the entity was used. + /// + UsageType UsageType { get; } + /// + /// Indicates the state of the entity, new or existing. + /// + EntityState EntityState { get; } - /// - /// The subject - /// - TEntity Entity { get; } - /// - /// Possible parent(s) of the subject - /// - IParent? Parent { get; } + /// + /// The subject + /// + TEntity Entity { get; } + /// + /// Possible parent(s) of the subject + /// + IParent? Parent { get; } - IRelationContainer GetRelationContainer(); + IRelationContainer GetRelationContainer(); - /// - /// Checks whether the given property was modified by the form. - /// - /// - /// - /// - bool? IsModified(Expression> property); - /// - /// Checks whether the given property was modified by the form. - /// - /// Name of the direct property of TEntity. - /// - bool? IsModified(string propertyName); + /// + /// Checks whether the given property was modified by the form. + /// + /// + /// + /// + bool? IsModified(Expression> property); + /// + /// Checks whether the given property was modified by the form. + /// + /// Name of the direct property of TEntity. + /// + bool? IsModified(string propertyName); - /// - /// Checks whether the given property is valid. - /// - /// - /// - /// - bool? IsValid(Expression> property); - /// - /// Checks whether the given property is valid. - /// - /// Name of the direct property of TEntity. - /// - bool? IsValid(string propertyName); + /// + /// Checks whether the given property is valid. + /// + /// + /// + /// + bool? IsValid(Expression> property); + /// + /// Checks whether the given property is valid. + /// + /// Name of the direct property of TEntity. + /// + bool? IsValid(string propertyName); - /// - /// Checks whether the given property was validated by the EditContext. - /// - /// - /// - /// - bool? WasValidated(Expression> property); - /// - /// Checks whether the given property was validated by the EditContext. - /// - /// - /// - bool? WasValidated(string propertyName); + /// + /// Checks whether the given property was validated by the EditContext. + /// + /// + /// + /// + bool? WasValidated(Expression> property); + /// + /// Checks whether the given property was validated by the EditContext. + /// + /// + /// + bool? WasValidated(string propertyName); - /// - /// Validates the given property and returns whether this property was valid. - /// - /// - /// - /// - Task ValidateAsync(Expression> property); + /// + /// Validates the given property and returns whether this property was valid. + /// + /// + /// + /// + Task ValidateAsync(Expression> property); - void AddValidationError(Expression> property, string message); - } + void AddValidationError(Expression> property, string message); } diff --git a/src/RapidCMS.Core/Abstractions/Forms/IRelatedViewContext.cs b/src/RapidCMS.Core/Abstractions/Forms/IRelatedViewContext.cs index 468d11c7..9bbf25f2 100644 --- a/src/RapidCMS.Core/Abstractions/Forms/IRelatedViewContext.cs +++ b/src/RapidCMS.Core/Abstractions/Forms/IRelatedViewContext.cs @@ -1,12 +1,11 @@ using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Abstractions.Forms +namespace RapidCMS.Core.Abstractions.Forms; + +public interface IRelatedViewContext : IViewContext { - public interface IRelatedViewContext : IViewContext - { - /// - /// The related entity - /// - IRelated Related { get; } - } + /// + /// The related entity + /// + IRelated Related { get; } } diff --git a/src/RapidCMS.Core/Abstractions/Forms/IRelationContainer.cs b/src/RapidCMS.Core/Abstractions/Forms/IRelationContainer.cs index 7aa6d33f..8eeab5d2 100644 --- a/src/RapidCMS.Core/Abstractions/Forms/IRelationContainer.cs +++ b/src/RapidCMS.Core/Abstractions/Forms/IRelationContainer.cs @@ -3,16 +3,15 @@ using System.Linq.Expressions; using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Abstractions.Forms +namespace RapidCMS.Core.Abstractions.Forms; + +public interface IRelationContainer { - public interface IRelationContainer - { - IEnumerable Relations { get; } + IEnumerable Relations { get; } - IReadOnlyList? GetRelatedElementIdsFor(Expression> propertyExpression) - where TEntity : IEntity; + IReadOnlyList? GetRelatedElementIdsFor(Expression> propertyExpression) + where TEntity : IEntity; - IReadOnlyList? GetRelatedElementIdsFor() - where TRelatedEntity : IEntity; - } + IReadOnlyList? GetRelatedElementIdsFor() + where TRelatedEntity : IEntity; } diff --git a/src/RapidCMS.Core/Abstractions/Forms/IViewContext.cs b/src/RapidCMS.Core/Abstractions/Forms/IViewContext.cs index 94367a49..ce64daab 100644 --- a/src/RapidCMS.Core/Abstractions/Forms/IViewContext.cs +++ b/src/RapidCMS.Core/Abstractions/Forms/IViewContext.cs @@ -1,17 +1,16 @@ using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Abstractions.Forms +namespace RapidCMS.Core.Abstractions.Forms; + +public interface IViewContext { - public interface IViewContext - { - /// - /// Alias of the collection this view is used - /// - string? CollectionAlias { get; } + /// + /// Alias of the collection this view is used + /// + string? CollectionAlias { get; } - /// - /// Possible parent(s) of the subject - /// - IParent? Parent { get; } - } + /// + /// Possible parent(s) of the subject + /// + IParent? Parent { get; } } diff --git a/src/RapidCMS.Core/Abstractions/Handlers/IButtonActionHandler.cs b/src/RapidCMS.Core/Abstractions/Handlers/IButtonActionHandler.cs index a053e922..d8089d64 100644 --- a/src/RapidCMS.Core/Abstractions/Handlers/IButtonActionHandler.cs +++ b/src/RapidCMS.Core/Abstractions/Handlers/IButtonActionHandler.cs @@ -4,17 +4,16 @@ using RapidCMS.Core.Forms; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Abstractions.Handlers +namespace RapidCMS.Core.Abstractions.Handlers; + +public interface IButtonActionHandler { - public interface IButtonActionHandler - { - OperationAuthorizationRequirement GetOperation(ButtonSetup button, FormEditContext editContext); + OperationAuthorizationRequirement GetOperation(ButtonSetup button, FormEditContext editContext); - bool IsCompatible(ButtonSetup button, FormEditContext editContext); - bool ShouldAskForConfirmation(ButtonSetup button, FormEditContext editContext); - bool RequiresValidForm(ButtonSetup button, FormEditContext editContext); + bool IsCompatible(ButtonSetup button, FormEditContext editContext); + bool ShouldAskForConfirmation(ButtonSetup button, FormEditContext editContext); + bool RequiresValidForm(ButtonSetup button, FormEditContext editContext); - Task ButtonClickBeforeRepositoryActionAsync(ButtonSetup button, FormEditContext editContext, ButtonContext context); - Task ButtonClickAfterRepositoryActionAsync(ButtonSetup button, FormEditContext editContext, ButtonContext context); - } + Task ButtonClickBeforeRepositoryActionAsync(ButtonSetup button, FormEditContext editContext, ButtonContext context); + Task ButtonClickAfterRepositoryActionAsync(ButtonSetup button, FormEditContext editContext, ButtonContext context); } diff --git a/src/RapidCMS.Core/Abstractions/Handlers/IFileUploadHandler.cs b/src/RapidCMS.Core/Abstractions/Handlers/IFileUploadHandler.cs index fe1e9230..3f3c37f2 100644 --- a/src/RapidCMS.Core/Abstractions/Handlers/IFileUploadHandler.cs +++ b/src/RapidCMS.Core/Abstractions/Handlers/IFileUploadHandler.cs @@ -3,12 +3,11 @@ using System.Threading.Tasks; using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Abstractions.Handlers +namespace RapidCMS.Core.Abstractions.Handlers; + +public interface IFileUploadHandler { - public interface IFileUploadHandler - { - Task> ValidateFileAsync(IFileInfo fileInfo); + Task> ValidateFileAsync(IFileInfo fileInfo); - Task SaveFileAsync(IFileInfo fileInfo, Stream stream); - } + Task SaveFileAsync(IFileInfo fileInfo, Stream stream); } diff --git a/src/RapidCMS.Core/Abstractions/Handlers/INavigationHandler.cs b/src/RapidCMS.Core/Abstractions/Handlers/INavigationHandler.cs index bf9402bc..62eea6c5 100644 --- a/src/RapidCMS.Core/Abstractions/Handlers/INavigationHandler.cs +++ b/src/RapidCMS.Core/Abstractions/Handlers/INavigationHandler.cs @@ -3,10 +3,9 @@ using RapidCMS.Core.Models.Request; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Abstractions.Handlers +namespace RapidCMS.Core.Abstractions.Handlers; + +public interface INavigationHandler { - public interface INavigationHandler - { - Task CreateNavigationRequestAsync(ButtonSetup button, FormEditContext editContext); - } + Task CreateNavigationRequestAsync(ButtonSetup button, FormEditContext editContext); } diff --git a/src/RapidCMS.Core/Abstractions/Interactions/IButtonInteraction.cs b/src/RapidCMS.Core/Abstractions/Interactions/IButtonInteraction.cs index a121986c..cf29e23c 100644 --- a/src/RapidCMS.Core/Abstractions/Interactions/IButtonInteraction.cs +++ b/src/RapidCMS.Core/Abstractions/Interactions/IButtonInteraction.cs @@ -2,16 +2,15 @@ using RapidCMS.Core.Enums; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Abstractions.Interactions +namespace RapidCMS.Core.Abstractions.Interactions; + +internal interface IButtonInteraction { - internal interface IButtonInteraction - { - Task ValidateButtonInteractionAsync(IEditorButtonInteractionRequestModel request); - Task CompleteButtonInteractionAsync(IEditorButtonInteractionRequestModel request); + Task ValidateButtonInteractionAsync(IEditorButtonInteractionRequestModel request); + Task CompleteButtonInteractionAsync(IEditorButtonInteractionRequestModel request); - Task ValidateButtonInteractionAsync(IEditorInListInteractionRequestModel request); + Task ValidateButtonInteractionAsync(IEditorInListInteractionRequestModel request); - Task<(CrudType crudType, EntityVariantSetup? entityVariant)> ValidateButtonInteractionAsync(IListButtonInteractionRequestModel request); - Task CompleteButtonInteractionAsync(IListButtonInteractionRequestModel request); - } + Task<(CrudType crudType, EntityVariantSetup? entityVariant)> ValidateButtonInteractionAsync(IListButtonInteractionRequestModel request); + Task CompleteButtonInteractionAsync(IListButtonInteractionRequestModel request); } diff --git a/src/RapidCMS.Core/Abstractions/Interactions/IButtonInteractionRequestModel.cs b/src/RapidCMS.Core/Abstractions/Interactions/IButtonInteractionRequestModel.cs index a3c02b4a..e1713dc6 100644 --- a/src/RapidCMS.Core/Abstractions/Interactions/IButtonInteractionRequestModel.cs +++ b/src/RapidCMS.Core/Abstractions/Interactions/IButtonInteractionRequestModel.cs @@ -1,11 +1,10 @@ using RapidCMS.Core.Forms; -namespace RapidCMS.Core.Abstractions.Interactions +namespace RapidCMS.Core.Abstractions.Interactions; + +public interface IEditorButtonInteractionRequestModel { - public interface IEditorButtonInteractionRequestModel - { - string ActionId { get; } - FormEditContext EditContext { get; } - object? CustomData { get; } - } + string ActionId { get; } + FormEditContext EditContext { get; } + object? CustomData { get; } } diff --git a/src/RapidCMS.Core/Abstractions/Interactions/IDragInteraction.cs b/src/RapidCMS.Core/Abstractions/Interactions/IDragInteraction.cs index 8dba75c3..0ccd1235 100644 --- a/src/RapidCMS.Core/Abstractions/Interactions/IDragInteraction.cs +++ b/src/RapidCMS.Core/Abstractions/Interactions/IDragInteraction.cs @@ -2,22 +2,21 @@ using Microsoft.AspNetCore.Components.Web; using RapidCMS.Core.Models.EventArgs; -namespace RapidCMS.Core.Abstractions.Interactions +namespace RapidCMS.Core.Abstractions.Interactions; + +public interface IDragInteraction { - public interface IDragInteraction - { - void DragStart(DragEventArgs args, string id); - void DragEnd(DragEventArgs args); + void DragStart(DragEventArgs args, string id); + void DragEnd(DragEventArgs args); - void DragEnter(DragEventArgs args, string id); + void DragEnter(DragEventArgs args, string id); - void EndZoneDragEnter(DragEventArgs args, Guid guid); + void EndZoneDragEnter(DragEventArgs args, Guid guid); - bool IsDragged(string? id); - bool IsDraggedOver(string? id); - bool IsDraggedOverEndZone(Guid guid); + bool IsDragged(string? id); + bool IsDraggedOver(string? id); + bool IsDraggedOverEndZone(Guid guid); - event EventHandler DragCompletion; - event EventHandler DragStateChange; - } + event EventHandler DragCompletion; + event EventHandler DragStateChange; } diff --git a/src/RapidCMS.Core/Abstractions/Interactions/IEditorInListInteractionRequestModel.cs b/src/RapidCMS.Core/Abstractions/Interactions/IEditorInListInteractionRequestModel.cs index 6f7ba79e..f750f4c4 100644 --- a/src/RapidCMS.Core/Abstractions/Interactions/IEditorInListInteractionRequestModel.cs +++ b/src/RapidCMS.Core/Abstractions/Interactions/IEditorInListInteractionRequestModel.cs @@ -1,12 +1,11 @@ using RapidCMS.Core.Forms; -namespace RapidCMS.Core.Abstractions.Interactions +namespace RapidCMS.Core.Abstractions.Interactions; + +public interface IEditorInListInteractionRequestModel { - public interface IEditorInListInteractionRequestModel - { - string ActionId { get; } - FormEditContext EditContext { get; } - ListContext ListContext { get; } - object? CustomData { get; } - } + string ActionId { get; } + FormEditContext EditContext { get; } + ListContext ListContext { get; } + object? CustomData { get; } } diff --git a/src/RapidCMS.Core/Abstractions/Interactions/IListButtonInteractionRequestModel.cs b/src/RapidCMS.Core/Abstractions/Interactions/IListButtonInteractionRequestModel.cs index a367a16b..8560b03a 100644 --- a/src/RapidCMS.Core/Abstractions/Interactions/IListButtonInteractionRequestModel.cs +++ b/src/RapidCMS.Core/Abstractions/Interactions/IListButtonInteractionRequestModel.cs @@ -1,11 +1,10 @@ using RapidCMS.Core.Forms; -namespace RapidCMS.Core.Abstractions.Interactions +namespace RapidCMS.Core.Abstractions.Interactions; + +public interface IListButtonInteractionRequestModel { - public interface IListButtonInteractionRequestModel - { - string ActionId { get; } - ListContext ListContext { get; } - object? CustomData { get; } - } + string ActionId { get; } + ListContext ListContext { get; } + object? CustomData { get; } } diff --git a/src/RapidCMS.Core/Abstractions/Mediators/IMediator.cs b/src/RapidCMS.Core/Abstractions/Mediators/IMediator.cs index fd5c5e3f..97291006 100644 --- a/src/RapidCMS.Core/Abstractions/Mediators/IMediator.cs +++ b/src/RapidCMS.Core/Abstractions/Mediators/IMediator.cs @@ -1,20 +1,19 @@ using System; using System.Threading.Tasks; -namespace RapidCMS.Core.Abstractions.Mediators +namespace RapidCMS.Core.Abstractions.Mediators; + +public interface IMediator { - public interface IMediator - { - void NotifyEvent(object sender, IMediatorEventArgs @event); + void NotifyEvent(object sender, IMediatorEventArgs @event); - Task NotifyEventAsync(object sender, IMediatorRequestEventArgs @event); + Task NotifyEventAsync(object sender, IMediatorRequestEventArgs @event); - event EventHandler OnEvent; + event EventHandler OnEvent; - IDisposable RegisterCallback(Func callback) - where TMediatorEventArgs : IMediatorEventArgs; + IDisposable RegisterCallback(Func callback) + where TMediatorEventArgs : IMediatorEventArgs; - TMediatorEventArgs? GetLatestEventArgs() - where TMediatorEventArgs : IMediatorEventArgs; - } + TMediatorEventArgs? GetLatestEventArgs() + where TMediatorEventArgs : IMediatorEventArgs; } diff --git a/src/RapidCMS.Core/Abstractions/Mediators/IMediatorEventArgs.cs b/src/RapidCMS.Core/Abstractions/Mediators/IMediatorEventArgs.cs index 32c90891..6f570bbb 100644 --- a/src/RapidCMS.Core/Abstractions/Mediators/IMediatorEventArgs.cs +++ b/src/RapidCMS.Core/Abstractions/Mediators/IMediatorEventArgs.cs @@ -1,6 +1,5 @@ -namespace RapidCMS.Core.Abstractions.Mediators +namespace RapidCMS.Core.Abstractions.Mediators; + +public interface IMediatorEventArgs { - public interface IMediatorEventArgs - { - } } diff --git a/src/RapidCMS.Core/Abstractions/Mediators/IMediatorEventListener.cs b/src/RapidCMS.Core/Abstractions/Mediators/IMediatorEventListener.cs index 8813032b..f18866d1 100644 --- a/src/RapidCMS.Core/Abstractions/Mediators/IMediatorEventListener.cs +++ b/src/RapidCMS.Core/Abstractions/Mediators/IMediatorEventListener.cs @@ -1,9 +1,8 @@ using System; -namespace RapidCMS.Core.Abstractions.Mediators +namespace RapidCMS.Core.Abstractions.Mediators; + +public interface IMediatorEventListener : IDisposable { - public interface IMediatorEventListener : IDisposable - { - void RegisterListener(IMediator mediator); - } + void RegisterListener(IMediator mediator); } diff --git a/src/RapidCMS.Core/Abstractions/Mediators/IMediatorRequestEventArgs.cs b/src/RapidCMS.Core/Abstractions/Mediators/IMediatorRequestEventArgs.cs index de2bf800..464d9dcc 100644 --- a/src/RapidCMS.Core/Abstractions/Mediators/IMediatorRequestEventArgs.cs +++ b/src/RapidCMS.Core/Abstractions/Mediators/IMediatorRequestEventArgs.cs @@ -1,9 +1,8 @@ using System; -namespace RapidCMS.Core.Abstractions.Mediators +namespace RapidCMS.Core.Abstractions.Mediators; + +public interface IMediatorRequestEventArgs : IMediatorEventArgs { - public interface IMediatorRequestEventArgs : IMediatorEventArgs - { - Guid RequestId { get; set; } - } + Guid RequestId { get; set; } } diff --git a/src/RapidCMS.Core/Abstractions/Mediators/IMediatorResponseEventArgs.cs b/src/RapidCMS.Core/Abstractions/Mediators/IMediatorResponseEventArgs.cs index daf4d92f..d20ba8ef 100644 --- a/src/RapidCMS.Core/Abstractions/Mediators/IMediatorResponseEventArgs.cs +++ b/src/RapidCMS.Core/Abstractions/Mediators/IMediatorResponseEventArgs.cs @@ -1,10 +1,9 @@ using System; -namespace RapidCMS.Core.Abstractions.Mediators +namespace RapidCMS.Core.Abstractions.Mediators; + +public interface IMediatorResponseEventArgs : IMediatorEventArgs { - public interface IMediatorResponseEventArgs : IMediatorEventArgs - { - Guid RequestId { get; set; } - TResponse Response { get; set; } - } + Guid RequestId { get; set; } + TResponse Response { get; set; } } diff --git a/src/RapidCMS.Core/Abstractions/Metadata/IExpressionMetadata.cs b/src/RapidCMS.Core/Abstractions/Metadata/IExpressionMetadata.cs index 2d34953d..e2940bc0 100644 --- a/src/RapidCMS.Core/Abstractions/Metadata/IExpressionMetadata.cs +++ b/src/RapidCMS.Core/Abstractions/Metadata/IExpressionMetadata.cs @@ -1,10 +1,9 @@ using System; -namespace RapidCMS.Core.Abstractions.Metadata +namespace RapidCMS.Core.Abstractions.Metadata; + +public interface IExpressionMetadata { - public interface IExpressionMetadata - { - string PropertyName { get; } - Func StringGetter { get; } - } + string PropertyName { get; } + Func StringGetter { get; } } diff --git a/src/RapidCMS.Core/Abstractions/Metadata/IFullPropertyMetadata.cs b/src/RapidCMS.Core/Abstractions/Metadata/IFullPropertyMetadata.cs index cdb5ba32..01a1ca55 100644 --- a/src/RapidCMS.Core/Abstractions/Metadata/IFullPropertyMetadata.cs +++ b/src/RapidCMS.Core/Abstractions/Metadata/IFullPropertyMetadata.cs @@ -1,9 +1,8 @@ using System; -namespace RapidCMS.Core.Abstractions.Metadata +namespace RapidCMS.Core.Abstractions.Metadata; + +public interface IFullPropertyMetadata : IPropertyMetadata { - public interface IFullPropertyMetadata : IPropertyMetadata - { - Action Setter { get; } - } + Action Setter { get; } } diff --git a/src/RapidCMS.Core/Abstractions/Metadata/IPropertyMetadata.cs b/src/RapidCMS.Core/Abstractions/Metadata/IPropertyMetadata.cs index ae0de512..c0ae5015 100644 --- a/src/RapidCMS.Core/Abstractions/Metadata/IPropertyMetadata.cs +++ b/src/RapidCMS.Core/Abstractions/Metadata/IPropertyMetadata.cs @@ -1,17 +1,16 @@ using System; using System.Linq.Expressions; -namespace RapidCMS.Core.Abstractions.Metadata +namespace RapidCMS.Core.Abstractions.Metadata; + +public interface IPropertyMetadata { - public interface IPropertyMetadata - { - Type PropertyType { get; } - string PropertyName { get; } - Type ObjectType { get; } - Func Getter { get; } + Type PropertyType { get; } + string PropertyName { get; } + Type ObjectType { get; } + Func Getter { get; } - string Fingerprint { get; } + string Fingerprint { get; } - LambdaExpression OriginalExpression { get; } - } + LambdaExpression OriginalExpression { get; } } diff --git a/src/RapidCMS.Core/Abstractions/Navigation/INavigationStateProvider.cs b/src/RapidCMS.Core/Abstractions/Navigation/INavigationStateProvider.cs index 3615f567..bf2a4463 100644 --- a/src/RapidCMS.Core/Abstractions/Navigation/INavigationStateProvider.cs +++ b/src/RapidCMS.Core/Abstractions/Navigation/INavigationStateProvider.cs @@ -2,29 +2,28 @@ using RapidCMS.Core.Models.UI; using RapidCMS.Core.Navigation; -namespace RapidCMS.Core.Abstractions.Navigation +namespace RapidCMS.Core.Abstractions.Navigation; + +public interface INavigationStateProvider { - public interface INavigationStateProvider - { - NavigationState GetCurrentState(); + NavigationState GetCurrentState(); - bool IsRootState(NavigationState state); + bool IsRootState(NavigationState state); - NavigationState Initialize(string url, string queryString); + NavigationState Initialize(string url, string queryString); - void AppendNavigationState(NavigationState state); - void AppendNavigationState(NavigationState currentState, NavigationState state); + void AppendNavigationState(NavigationState state); + void AppendNavigationState(NavigationState currentState, NavigationState state); - void NestNavigationState(NavigationState currentState, NavigationState nestedState); + void NestNavigationState(NavigationState currentState, NavigationState nestedState); - void ReplaceNavigationState(NavigationState currentState, NavigationState state); + void ReplaceNavigationState(NavigationState currentState, NavigationState state); - bool RemoveNavigationState(NavigationState currentState); + bool RemoveNavigationState(NavigationState currentState); - void UpdateCollectionState(NavigationState currentState, CollectionState collectionState); + void UpdateCollectionState(NavigationState currentState, CollectionState collectionState); - IView GetCurrentView(NavigationState currentState, ListUI list, TabUI? activeTab); + IView GetCurrentView(NavigationState currentState, ListUI list, TabUI? activeTab); - bool TryProcessView(NavigationState currentState, IView view, bool hasSections); - } + bool TryProcessView(NavigationState currentState, IView view, bool hasSections); } diff --git a/src/RapidCMS.Core/Abstractions/Plugins/IPlugin.cs b/src/RapidCMS.Core/Abstractions/Plugins/IPlugin.cs index da1b74f0..7f56d362 100644 --- a/src/RapidCMS.Core/Abstractions/Plugins/IPlugin.cs +++ b/src/RapidCMS.Core/Abstractions/Plugins/IPlugin.cs @@ -4,16 +4,15 @@ using RapidCMS.Core.Abstractions.Resolvers; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Abstractions.Plugins +namespace RapidCMS.Core.Abstractions.Plugins; + +public interface IPlugin { - public interface IPlugin - { - Task> GetTreeElementsAsync(); + Task> GetTreeElementsAsync(); - Task?> GetCollectionAsync(string collectionAlias); + Task?> GetCollectionAsync(string collectionAlias); - Type? GetRepositoryType(string collectionAlias); + Type? GetRepositoryType(string collectionAlias); - string CollectionPrefix { get; } - } + string CollectionPrefix { get; } } diff --git a/src/RapidCMS.Core/Abstractions/Repositories/IRepository.cs b/src/RapidCMS.Core/Abstractions/Repositories/IRepository.cs index e42a21ac..046df4e7 100644 --- a/src/RapidCMS.Core/Abstractions/Repositories/IRepository.cs +++ b/src/RapidCMS.Core/Abstractions/Repositories/IRepository.cs @@ -4,29 +4,28 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Abstractions.Forms; -namespace RapidCMS.Core.Abstractions.Repositories +namespace RapidCMS.Core.Abstractions.Repositories; + +/// +/// This interface is used everywhere there is data needed. +/// +/// This is not the best starting point for custom developed repositories, it is better to see whether the repository can be developed using BaseRepository / BaseMappedRespository as base type. +/// +public interface IRepository { - /// - /// This interface is used everywhere there is data needed. - /// - /// This is not the best starting point for custom developed repositories, it is better to see whether the repository can be developed using BaseRepository / BaseMappedRespository as base type. - /// - public interface IRepository - { - Task GetByIdAsync(string id, IViewContext viewContext); - Task> GetAllAsync(IViewContext viewContext, IView view); + Task GetByIdAsync(string id, IViewContext viewContext); + Task> GetAllAsync(IViewContext viewContext, IView view); - Task> GetAllRelatedAsync(IRelatedViewContext viewContext, IView view); - Task> GetAllNonRelatedAsync(IRelatedViewContext viewContext, IView view); + Task> GetAllRelatedAsync(IRelatedViewContext viewContext, IView view); + Task> GetAllNonRelatedAsync(IRelatedViewContext viewContext, IView view); - Task NewAsync(IViewContext viewContext, Type? variantType); - Task InsertAsync(IEditContext editContext); - Task UpdateAsync(IEditContext editContext); - Task DeleteAsync(string id, IViewContext viewContext); + Task NewAsync(IViewContext viewContext, Type? variantType); + Task InsertAsync(IEditContext editContext); + Task UpdateAsync(IEditContext editContext); + Task DeleteAsync(string id, IViewContext viewContext); - Task AddAsync(IRelatedViewContext viewContext, string id); - Task RemoveAsync(IRelatedViewContext viewContext, string id); + Task AddAsync(IRelatedViewContext viewContext, string id); + Task RemoveAsync(IRelatedViewContext viewContext, string id); - Task ReorderAsync(string? beforeId, string id, IViewContext viewContext); - } + Task ReorderAsync(string? beforeId, string id, IViewContext viewContext); } diff --git a/src/RapidCMS.Core/Abstractions/Resolvers/IButtonActionHandlerResolver.cs b/src/RapidCMS.Core/Abstractions/Resolvers/IButtonActionHandlerResolver.cs index b026ab8e..6f471857 100644 --- a/src/RapidCMS.Core/Abstractions/Resolvers/IButtonActionHandlerResolver.cs +++ b/src/RapidCMS.Core/Abstractions/Resolvers/IButtonActionHandlerResolver.cs @@ -1,10 +1,9 @@ using RapidCMS.Core.Abstractions.Handlers; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Abstractions.Resolvers +namespace RapidCMS.Core.Abstractions.Resolvers; + +internal interface IButtonActionHandlerResolver { - internal interface IButtonActionHandlerResolver - { - IButtonActionHandler GetButtonActionHandler(ButtonSetup button); - } + IButtonActionHandler GetButtonActionHandler(ButtonSetup button); } diff --git a/src/RapidCMS.Core/Abstractions/Resolvers/ICollectionAliasResolver.cs b/src/RapidCMS.Core/Abstractions/Resolvers/ICollectionAliasResolver.cs index 9e2af7ff..08677dba 100644 --- a/src/RapidCMS.Core/Abstractions/Resolvers/ICollectionAliasResolver.cs +++ b/src/RapidCMS.Core/Abstractions/Resolvers/ICollectionAliasResolver.cs @@ -1,9 +1,8 @@ using System.Collections.Generic; -namespace RapidCMS.Core.Abstractions.Resolvers +namespace RapidCMS.Core.Abstractions.Resolvers; + +internal interface ICollectionAliasResolver { - internal interface ICollectionAliasResolver - { - public IReadOnlyList GetAlias(string repositoryAlias); - } + public IReadOnlyList GetAlias(string repositoryAlias); } diff --git a/src/RapidCMS.Core/Abstractions/Resolvers/IConventionBasedResolver.cs b/src/RapidCMS.Core/Abstractions/Resolvers/IConventionBasedResolver.cs index dde229e0..20b78ad3 100644 --- a/src/RapidCMS.Core/Abstractions/Resolvers/IConventionBasedResolver.cs +++ b/src/RapidCMS.Core/Abstractions/Resolvers/IConventionBasedResolver.cs @@ -3,10 +3,9 @@ using RapidCMS.Core.Enums; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Abstractions.Resolvers +namespace RapidCMS.Core.Abstractions.Resolvers; + +public interface IConventionBasedResolver { - public interface IConventionBasedResolver - { - Task ResolveByConventionAsync(Type subject, Features features, CollectionSetup? collection); - } + Task ResolveByConventionAsync(Type subject, Features features, CollectionSetup? collection); } diff --git a/src/RapidCMS.Core/Abstractions/Resolvers/IDataProviderResolver.cs b/src/RapidCMS.Core/Abstractions/Resolvers/IDataProviderResolver.cs index 86e8703f..8f7bdaf3 100644 --- a/src/RapidCMS.Core/Abstractions/Resolvers/IDataProviderResolver.cs +++ b/src/RapidCMS.Core/Abstractions/Resolvers/IDataProviderResolver.cs @@ -2,10 +2,9 @@ using RapidCMS.Core.Models.Setup; using RapidCMS.Core.Providers; -namespace RapidCMS.Core.Abstractions.Resolvers +namespace RapidCMS.Core.Abstractions.Resolvers; + +internal interface IDataProviderResolver { - internal interface IDataProviderResolver - { - Task GetDataProviderAsync(FieldSetup field); - } + Task GetDataProviderAsync(FieldSetup field); } diff --git a/src/RapidCMS.Core/Abstractions/Resolvers/IDataViewResolver.cs b/src/RapidCMS.Core/Abstractions/Resolvers/IDataViewResolver.cs index 12dad037..12a27ee4 100644 --- a/src/RapidCMS.Core/Abstractions/Resolvers/IDataViewResolver.cs +++ b/src/RapidCMS.Core/Abstractions/Resolvers/IDataViewResolver.cs @@ -3,11 +3,10 @@ using System.Threading.Tasks; using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Abstractions.Resolvers +namespace RapidCMS.Core.Abstractions.Resolvers; + +internal interface IDataViewResolver { - internal interface IDataViewResolver - { - Task> GetDataViewsAsync(string collectionAlias); - Task ApplyDataViewToViewAsync(IView view); - } + Task> GetDataViewsAsync(string collectionAlias); + Task ApplyDataViewToViewAsync(IView view); } diff --git a/src/RapidCMS.Core/Abstractions/Resolvers/IEntityVariantResolver.cs b/src/RapidCMS.Core/Abstractions/Resolvers/IEntityVariantResolver.cs index df19f5e9..5dcf468f 100644 --- a/src/RapidCMS.Core/Abstractions/Resolvers/IEntityVariantResolver.cs +++ b/src/RapidCMS.Core/Abstractions/Resolvers/IEntityVariantResolver.cs @@ -1,10 +1,9 @@ using System; using System.Collections.Generic; -namespace RapidCMS.Core.Abstractions.Resolvers +namespace RapidCMS.Core.Abstractions.Resolvers; + +public interface IEntityVariantResolver { - public interface IEntityVariantResolver - { - (Type? baseType, IReadOnlyList? derivedTypes) GetValidVariantsForRepository(string repositoryAlias); - } + (Type? baseType, IReadOnlyList? derivedTypes) GetValidVariantsForRepository(string repositoryAlias); } diff --git a/src/RapidCMS.Core/Abstractions/Resolvers/IFieldConfigResolver.cs b/src/RapidCMS.Core/Abstractions/Resolvers/IFieldConfigResolver.cs index 410f91ec..585c2f46 100644 --- a/src/RapidCMS.Core/Abstractions/Resolvers/IFieldConfigResolver.cs +++ b/src/RapidCMS.Core/Abstractions/Resolvers/IFieldConfigResolver.cs @@ -3,10 +3,9 @@ using RapidCMS.Core.Enums; using RapidCMS.Core.Models.Config; -namespace RapidCMS.Core.Abstractions.Resolvers +namespace RapidCMS.Core.Abstractions.Resolvers; + +internal interface IFieldConfigResolver { - internal interface IFieldConfigResolver - { - IEnumerable GetFields(Type subject, Features features); - } + IEnumerable GetFields(Type subject, Features features); } diff --git a/src/RapidCMS.Core/Abstractions/Resolvers/ILanguageResolver.cs b/src/RapidCMS.Core/Abstractions/Resolvers/ILanguageResolver.cs index 7169f123..5d08e539 100644 --- a/src/RapidCMS.Core/Abstractions/Resolvers/ILanguageResolver.cs +++ b/src/RapidCMS.Core/Abstractions/Resolvers/ILanguageResolver.cs @@ -1,7 +1,6 @@ -namespace RapidCMS.Core.Abstractions.Resolvers +namespace RapidCMS.Core.Abstractions.Resolvers; + +public interface ILanguageResolver { - public interface ILanguageResolver - { - string ResolveText(string originalText); - } + string ResolveText(string originalText); } diff --git a/src/RapidCMS.Core/Abstractions/Resolvers/IListUIResolver.cs b/src/RapidCMS.Core/Abstractions/Resolvers/IListUIResolver.cs index e9e4c250..cb271c67 100644 --- a/src/RapidCMS.Core/Abstractions/Resolvers/IListUIResolver.cs +++ b/src/RapidCMS.Core/Abstractions/Resolvers/IListUIResolver.cs @@ -4,13 +4,12 @@ using RapidCMS.Core.Models.UI; using RapidCMS.Core.Navigation; -namespace RapidCMS.Core.Abstractions.Resolvers +namespace RapidCMS.Core.Abstractions.Resolvers; + +public interface IListUIResolver { - public interface IListUIResolver - { - ListUI GetListDetails(); - Task> GetButtonsForEditContextAsync(FormEditContext editContext); - Task> GetSectionsForEditContextAsync(FormEditContext editContext, NavigationState navigationState); - Task?> GetTabsAsync(string collectionAlias); - } + ListUI GetListDetails(); + Task> GetButtonsForEditContextAsync(FormEditContext editContext); + Task> GetSectionsForEditContextAsync(FormEditContext editContext, NavigationState navigationState); + Task?> GetTabsAsync(string collectionAlias); } diff --git a/src/RapidCMS.Core/Abstractions/Resolvers/INodeUIResolver.cs b/src/RapidCMS.Core/Abstractions/Resolvers/INodeUIResolver.cs index fcdfb559..1f387c60 100644 --- a/src/RapidCMS.Core/Abstractions/Resolvers/INodeUIResolver.cs +++ b/src/RapidCMS.Core/Abstractions/Resolvers/INodeUIResolver.cs @@ -4,11 +4,10 @@ using RapidCMS.Core.Models.UI; using RapidCMS.Core.Navigation; -namespace RapidCMS.Core.Abstractions.Resolvers +namespace RapidCMS.Core.Abstractions.Resolvers; + +public interface INodeUIResolver { - public interface INodeUIResolver - { - Task> GetButtonsForEditContextAsync(FormEditContext editContext); - Task> GetSectionsForEditContextAsync(FormEditContext editContext, NavigationState navigationState); - } + Task> GetButtonsForEditContextAsync(FormEditContext editContext); + Task> GetSectionsForEditContextAsync(FormEditContext editContext, NavigationState navigationState); } diff --git a/src/RapidCMS.Core/Abstractions/Resolvers/IRepositoryResolver.cs b/src/RapidCMS.Core/Abstractions/Resolvers/IRepositoryResolver.cs index d96211f0..65d51be6 100644 --- a/src/RapidCMS.Core/Abstractions/Resolvers/IRepositoryResolver.cs +++ b/src/RapidCMS.Core/Abstractions/Resolvers/IRepositoryResolver.cs @@ -2,12 +2,11 @@ using RapidCMS.Core.Abstractions.Repositories; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Abstractions.Resolvers +namespace RapidCMS.Core.Abstractions.Resolvers; + +public interface IRepositoryResolver { - public interface IRepositoryResolver - { - internal IRepository GetRepository(CollectionSetup collection); - public IRepository GetRepository(string repositoryAlias); - public IRepository GetRepository(Type repositoryType); - } + internal IRepository GetRepository(CollectionSetup collection); + public IRepository GetRepository(string repositoryAlias); + public IRepository GetRepository(Type repositoryType); } diff --git a/src/RapidCMS.Core/Abstractions/Resolvers/IRepositoryTypeResolver.cs b/src/RapidCMS.Core/Abstractions/Resolvers/IRepositoryTypeResolver.cs index 83242234..7f677560 100644 --- a/src/RapidCMS.Core/Abstractions/Resolvers/IRepositoryTypeResolver.cs +++ b/src/RapidCMS.Core/Abstractions/Resolvers/IRepositoryTypeResolver.cs @@ -1,11 +1,10 @@ using System; -namespace RapidCMS.Core.Abstractions.Resolvers +namespace RapidCMS.Core.Abstractions.Resolvers; + +public interface IRepositoryTypeResolver { - public interface IRepositoryTypeResolver - { - public Type GetType(string repositoryAlias); - public (Type entityType, Type databaseType) GetEntityTypes(string repositoryAlias); - public string GetAlias(Type originallyRegisterdType); - } + public Type GetType(string repositoryAlias); + public (Type entityType, Type databaseType) GetEntityTypes(string repositoryAlias); + public string GetAlias(Type originallyRegisterdType); } diff --git a/src/RapidCMS.Core/Abstractions/Resolvers/IResolvedSetup.cs b/src/RapidCMS.Core/Abstractions/Resolvers/IResolvedSetup.cs index 6ef9bd57..c44740ed 100644 --- a/src/RapidCMS.Core/Abstractions/Resolvers/IResolvedSetup.cs +++ b/src/RapidCMS.Core/Abstractions/Resolvers/IResolvedSetup.cs @@ -1,8 +1,7 @@ -namespace RapidCMS.Core.Abstractions.Resolvers +namespace RapidCMS.Core.Abstractions.Resolvers; + +public interface IResolvedSetup { - public interface IResolvedSetup - { - T Setup { get; } - bool Cachable { get; } - } + T Setup { get; } + bool Cachable { get; } } diff --git a/src/RapidCMS.Core/Abstractions/Resolvers/ISetupResolver.cs b/src/RapidCMS.Core/Abstractions/Resolvers/ISetupResolver.cs index b47c59f2..09c62d07 100644 --- a/src/RapidCMS.Core/Abstractions/Resolvers/ISetupResolver.cs +++ b/src/RapidCMS.Core/Abstractions/Resolvers/ISetupResolver.cs @@ -1,17 +1,16 @@ using System.Threading.Tasks; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Abstractions.Resolvers +namespace RapidCMS.Core.Abstractions.Resolvers; + +public interface ISetupResolver { - public interface ISetupResolver - { - Task ResolveSetupAsync(); - Task ResolveSetupAsync(string alias); - } + Task ResolveSetupAsync(); + Task ResolveSetupAsync(string alias); +} - public interface ISetupResolver - where TConfig : notnull - { - Task> ResolveSetupAsync(TConfig config, CollectionSetup? collection = default); - } +public interface ISetupResolver + where TConfig : notnull +{ + Task> ResolveSetupAsync(TConfig config, CollectionSetup? collection = default); } diff --git a/src/RapidCMS.Core/Abstractions/Resolvers/IUserResolver.cs b/src/RapidCMS.Core/Abstractions/Resolvers/IUserResolver.cs index af6897ee..7032d63d 100644 --- a/src/RapidCMS.Core/Abstractions/Resolvers/IUserResolver.cs +++ b/src/RapidCMS.Core/Abstractions/Resolvers/IUserResolver.cs @@ -1,9 +1,8 @@ using System.Security.Claims; -namespace RapidCMS.Core.Abstractions.Resolvers +namespace RapidCMS.Core.Abstractions.Resolvers; + +internal interface IUserResolver { - internal interface IUserResolver - { - ClaimsPrincipal? GetUser(); - } + ClaimsPrincipal? GetUser(); } diff --git a/src/RapidCMS.Core/Abstractions/Services/IAuthService.cs b/src/RapidCMS.Core/Abstractions/Services/IAuthService.cs index 4d042002..c8a0d7f0 100644 --- a/src/RapidCMS.Core/Abstractions/Services/IAuthService.cs +++ b/src/RapidCMS.Core/Abstractions/Services/IAuthService.cs @@ -6,16 +6,15 @@ using RapidCMS.Core.Forms; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Abstractions.Services +namespace RapidCMS.Core.Abstractions.Services; + +public interface IAuthService { - public interface IAuthService - { - Task IsUserAuthorizedAsync(UsageType usageType, IEntity entity); - Task IsUserAuthorizedAsync(OperationAuthorizationRequirement operation, IEntity entity); - Task IsUserAuthorizedAsync(FormEditContext editContext, ButtonSetup button); + Task IsUserAuthorizedAsync(UsageType usageType, IEntity entity); + Task IsUserAuthorizedAsync(OperationAuthorizationRequirement operation, IEntity entity); + Task IsUserAuthorizedAsync(FormEditContext editContext, ButtonSetup button); - Task EnsureAuthorizedUserAsync(UsageType usageType, IEntity entity); - Task EnsureAuthorizedUserAsync(OperationAuthorizationRequirement operation, IEntity entity); - Task EnsureAuthorizedUserAsync(FormEditContext editContext, ButtonSetup button); - } + Task EnsureAuthorizedUserAsync(UsageType usageType, IEntity entity); + Task EnsureAuthorizedUserAsync(OperationAuthorizationRequirement operation, IEntity entity); + Task EnsureAuthorizedUserAsync(FormEditContext editContext, ButtonSetup button); } diff --git a/src/RapidCMS.Core/Abstractions/Services/IConcurrencyService.cs b/src/RapidCMS.Core/Abstractions/Services/IConcurrencyService.cs index ef92edab..6e9c3b19 100644 --- a/src/RapidCMS.Core/Abstractions/Services/IConcurrencyService.cs +++ b/src/RapidCMS.Core/Abstractions/Services/IConcurrencyService.cs @@ -1,11 +1,10 @@ using System; using System.Threading.Tasks; -namespace RapidCMS.Core.Abstractions.Services +namespace RapidCMS.Core.Abstractions.Services; + +public interface IConcurrencyService { - public interface IConcurrencyService - { - Task EnsureCorrectConcurrencyAsync(Func function); - Task EnsureCorrectConcurrencyAsync(Func> function); - } + Task EnsureCorrectConcurrencyAsync(Func function); + Task EnsureCorrectConcurrencyAsync(Func> function); } diff --git a/src/RapidCMS.Core/Abstractions/Services/IInteractionService.cs b/src/RapidCMS.Core/Abstractions/Services/IInteractionService.cs index b93f451b..ab69fe6c 100644 --- a/src/RapidCMS.Core/Abstractions/Services/IInteractionService.cs +++ b/src/RapidCMS.Core/Abstractions/Services/IInteractionService.cs @@ -1,9 +1,8 @@ using System.Threading.Tasks; -namespace RapidCMS.Core.Abstractions.Services +namespace RapidCMS.Core.Abstractions.Services; + +public interface IInteractionService { - public interface IInteractionService - { - Task InteractAsync(TRequest request); - } + Task InteractAsync(TRequest request); } diff --git a/src/RapidCMS.Core/Abstractions/Services/IParentService.cs b/src/RapidCMS.Core/Abstractions/Services/IParentService.cs index e50ac0cd..f96d1ab2 100644 --- a/src/RapidCMS.Core/Abstractions/Services/IParentService.cs +++ b/src/RapidCMS.Core/Abstractions/Services/IParentService.cs @@ -2,10 +2,9 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Models.Data; -namespace RapidCMS.Core.Abstractions.Services +namespace RapidCMS.Core.Abstractions.Services; + +public interface IParentService { - public interface IParentService - { - Task GetParentAsync(ParentPath? parentPath); - } + Task GetParentAsync(ParentPath? parentPath); } diff --git a/src/RapidCMS.Core/Abstractions/Services/IPresentationService.cs b/src/RapidCMS.Core/Abstractions/Services/IPresentationService.cs index d89d38f2..1285431d 100644 --- a/src/RapidCMS.Core/Abstractions/Services/IPresentationService.cs +++ b/src/RapidCMS.Core/Abstractions/Services/IPresentationService.cs @@ -2,13 +2,12 @@ using System.Threading.Tasks; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Abstractions.Services +namespace RapidCMS.Core.Abstractions.Services; + +public interface IPresentationService { - public interface IPresentationService - { - Task GetEntityAsync(TRequest request) where TResult : class; - Task GetEntitiesAsync(TRequest request) where TResult : class; + Task GetEntityAsync(TRequest request) where TResult : class; + Task GetEntitiesAsync(TRequest request) where TResult : class; - Task> GetPageAsync(string pageAlias); - } + Task> GetPageAsync(string pageAlias); } diff --git a/src/RapidCMS.Core/Abstractions/Services/ITreeService.cs b/src/RapidCMS.Core/Abstractions/Services/ITreeService.cs index 4ef262c9..c259f5a8 100644 --- a/src/RapidCMS.Core/Abstractions/Services/ITreeService.cs +++ b/src/RapidCMS.Core/Abstractions/Services/ITreeService.cs @@ -2,13 +2,12 @@ using RapidCMS.Core.Models.Data; using RapidCMS.Core.Models.UI; -namespace RapidCMS.Core.Abstractions.Services +namespace RapidCMS.Core.Abstractions.Services; + +public interface ITreeService { - public interface ITreeService - { - Task GetCollectionAsync(string alias, ParentPath? parentPath); - Task GetPageAsync(string alias, ParentPath? parentPath); - Task GetNodesAsync(string alias, ParentPath? parentPath, int pageNr, int pageSize); - Task GetRootAsync(); - } + Task GetCollectionAsync(string alias, ParentPath? parentPath); + Task GetPageAsync(string alias, ParentPath? parentPath); + Task GetNodesAsync(string alias, ParentPath? parentPath, int pageNr, int pageSize); + Task GetRootAsync(); } diff --git a/src/RapidCMS.Core/Abstractions/Setup/ICms.cs b/src/RapidCMS.Core/Abstractions/Setup/ICms.cs index 456761e4..e05b8018 100644 --- a/src/RapidCMS.Core/Abstractions/Setup/ICms.cs +++ b/src/RapidCMS.Core/Abstractions/Setup/ICms.cs @@ -1,8 +1,7 @@ -namespace RapidCMS.Core.Abstractions.Setup +namespace RapidCMS.Core.Abstractions.Setup; + +public interface ICms { - public interface ICms - { - string SiteName { get; } - bool IsDevelopment { get; set; } - } + string SiteName { get; } + bool IsDevelopment { get; set; } } diff --git a/src/RapidCMS.Core/Abstractions/Setup/ILogin.cs b/src/RapidCMS.Core/Abstractions/Setup/ILogin.cs index 499c11b9..85ccd89b 100644 --- a/src/RapidCMS.Core/Abstractions/Setup/ILogin.cs +++ b/src/RapidCMS.Core/Abstractions/Setup/ILogin.cs @@ -1,26 +1,25 @@ using System.Threading.Tasks; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Abstractions.Setup +namespace RapidCMS.Core.Abstractions.Setup; + +public interface ILogin { - public interface ILogin - { - /// - /// Gets the type registration for the custom login screen for unauthenticated users. - /// - /// - Task CustomLoginScreenRegistrationAsync(); + /// + /// Gets the type registration for the custom login screen for unauthenticated users. + /// + /// + Task CustomLoginScreenRegistrationAsync(); - /// - /// Gets the type registration for the custom login status for in the top bar. - /// - /// - Task CustomLoginStatusRegistrationAsync(); + /// + /// Gets the type registration for the custom login status for in the top bar. + /// + /// + Task CustomLoginStatusRegistrationAsync(); - /// - /// Gets the type registration for the custom landing page for when the user has no rights. - /// - /// - Task CustomLandingPageRegistrationAsync(); - } + /// + /// Gets the type registration for the custom landing page for when the user has no rights. + /// + /// + Task CustomLandingPageRegistrationAsync(); } diff --git a/src/RapidCMS.Core/Abstractions/Validators/IAsyncEntityValidator.cs b/src/RapidCMS.Core/Abstractions/Validators/IAsyncEntityValidator.cs index 50ea7285..17306df9 100644 --- a/src/RapidCMS.Core/Abstractions/Validators/IAsyncEntityValidator.cs +++ b/src/RapidCMS.Core/Abstractions/Validators/IAsyncEntityValidator.cs @@ -3,16 +3,15 @@ using System.Threading.Tasks; using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Abstractions.Validators +namespace RapidCMS.Core.Abstractions.Validators; + +public interface IAsyncEntityValidator { - public interface IAsyncEntityValidator - { - Task> ValidateAsync(IValidatorContext context); - } + Task> ValidateAsync(IValidatorContext context); +} - public interface IAsyncEntityValidator : IAsyncEntityValidator - where TEntity : IEntity - { - Task> ValidateAsync(IValidatorContext context); - } +public interface IAsyncEntityValidator : IAsyncEntityValidator + where TEntity : IEntity +{ + Task> ValidateAsync(IValidatorContext context); } diff --git a/src/RapidCMS.Core/Abstractions/Validators/IEntityValidator.cs b/src/RapidCMS.Core/Abstractions/Validators/IEntityValidator.cs index e5517ab0..8d7cc84a 100644 --- a/src/RapidCMS.Core/Abstractions/Validators/IEntityValidator.cs +++ b/src/RapidCMS.Core/Abstractions/Validators/IEntityValidator.cs @@ -2,16 +2,15 @@ using System.ComponentModel.DataAnnotations; using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Abstractions.Validators +namespace RapidCMS.Core.Abstractions.Validators; + +public interface IEntityValidator { - public interface IEntityValidator - { - IEnumerable Validate(IValidatorContext context); - } + IEnumerable Validate(IValidatorContext context); +} - public interface IEntityValidator : IEntityValidator - where TEntity : IEntity - { - IEnumerable Validate(IValidatorContext context); - } +public interface IEntityValidator : IEntityValidator + where TEntity : IEntity +{ + IEnumerable Validate(IValidatorContext context); } diff --git a/src/RapidCMS.Core/Abstractions/Validators/IValidatorContext.cs b/src/RapidCMS.Core/Abstractions/Validators/IValidatorContext.cs index 0c85ed1f..31817c4e 100644 --- a/src/RapidCMS.Core/Abstractions/Validators/IValidatorContext.cs +++ b/src/RapidCMS.Core/Abstractions/Validators/IValidatorContext.cs @@ -1,19 +1,18 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Abstractions.Forms; -namespace RapidCMS.Core.Abstractions.Validators +namespace RapidCMS.Core.Abstractions.Validators; + +public interface IValidatorContext { - public interface IValidatorContext - { - IEntity Entity { get; } - IRelationContainer RelationContainer { get; } - object? Configuration { get; } - } + IEntity Entity { get; } + IRelationContainer RelationContainer { get; } + object? Configuration { get; } +} - public interface IValidatorContext - { - TEntity Entity { get; } - IRelationContainer RelationContainer { get; } - object? Configuration { get; } - } +public interface IValidatorContext +{ + TEntity Entity { get; } + IRelationContainer RelationContainer { get; } + object? Configuration { get; } } diff --git a/src/RapidCMS.Core/Attributes/ActionsAttribute.cs b/src/RapidCMS.Core/Attributes/ActionsAttribute.cs index 9aa0b318..6db76a40 100644 --- a/src/RapidCMS.Core/Attributes/ActionsAttribute.cs +++ b/src/RapidCMS.Core/Attributes/ActionsAttribute.cs @@ -1,15 +1,14 @@ using RapidCMS.Core.Enums; using System; -namespace RapidCMS.Core.Attributes +namespace RapidCMS.Core.Attributes; + +internal class ActionsAttribute : Attribute { - internal class ActionsAttribute : Attribute + public ActionsAttribute(params UsageType[] usages) { - public ActionsAttribute(params UsageType[] usages) - { - Usages = usages; - } - - public UsageType[] Usages { get; private set; } + Usages = usages; } + + public UsageType[] Usages { get; private set; } } diff --git a/src/RapidCMS.Core/Attributes/ConfirmAttribute.cs b/src/RapidCMS.Core/Attributes/ConfirmAttribute.cs index a76add60..bec377f6 100644 --- a/src/RapidCMS.Core/Attributes/ConfirmAttribute.cs +++ b/src/RapidCMS.Core/Attributes/ConfirmAttribute.cs @@ -1,9 +1,8 @@ using System; -namespace RapidCMS.Core.Attributes +namespace RapidCMS.Core.Attributes; + +internal class ConfirmAttribute : Attribute { - internal class ConfirmAttribute : Attribute - { - } } diff --git a/src/RapidCMS.Core/Attributes/DefaultIconLabelAttribute.cs b/src/RapidCMS.Core/Attributes/DefaultIconLabelAttribute.cs index 9d76fe5e..6d535f6f 100644 --- a/src/RapidCMS.Core/Attributes/DefaultIconLabelAttribute.cs +++ b/src/RapidCMS.Core/Attributes/DefaultIconLabelAttribute.cs @@ -1,16 +1,15 @@ using System; -namespace RapidCMS.Core.Attributes +namespace RapidCMS.Core.Attributes; + +internal class DefaultIconLabelAttribute : Attribute { - internal class DefaultIconLabelAttribute : Attribute + public DefaultIconLabelAttribute(string icon, string label) { - public DefaultIconLabelAttribute(string icon, string label) - { - Icon = icon ?? throw new ArgumentNullException(nameof(icon)); - Label = label ?? throw new ArgumentNullException(nameof(label)); - } - - public string Icon { get; set; } - public string Label { get; set; } + Icon = icon ?? throw new ArgumentNullException(nameof(icon)); + Label = label ?? throw new ArgumentNullException(nameof(label)); } + + public string Icon { get; set; } + public string Label { get; set; } } diff --git a/src/RapidCMS.Core/Attributes/DefaultTypeAttribute.cs b/src/RapidCMS.Core/Attributes/DefaultTypeAttribute.cs index 9e141fdf..ed0b291a 100644 --- a/src/RapidCMS.Core/Attributes/DefaultTypeAttribute.cs +++ b/src/RapidCMS.Core/Attributes/DefaultTypeAttribute.cs @@ -1,15 +1,14 @@ using System; using System.Collections.Generic; -namespace RapidCMS.Core.Attributes +namespace RapidCMS.Core.Attributes; + +internal class DefaultTypeAttribute : Attribute { - internal class DefaultTypeAttribute : Attribute + public DefaultTypeAttribute(params Type[] types) { - public DefaultTypeAttribute(params Type[] types) - { - Types = types; - } - - public IEnumerable Types { get; private set; } + Types = types; } + + public IEnumerable Types { get; private set; } } diff --git a/src/RapidCMS.Core/Attributes/FieldAttribute.cs b/src/RapidCMS.Core/Attributes/FieldAttribute.cs index d343bde2..9de7e5e4 100644 --- a/src/RapidCMS.Core/Attributes/FieldAttribute.cs +++ b/src/RapidCMS.Core/Attributes/FieldAttribute.cs @@ -1,38 +1,37 @@ using System; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Attributes +namespace RapidCMS.Core.Attributes; + +[AttributeUsage(AttributeTargets.Property)] +public class FieldAttribute : Attribute { - [AttributeUsage(AttributeTargets.Property)] - public class FieldAttribute : Attribute - { - /// - /// Used as label for Node Editor - /// - public string? Name { get; set; } - - /// - /// Used as description for Node Editor - /// - public string? Description { get; set; } - - /// - /// Used as label in List View - /// - public string? ListName { get; set; } - - /// - /// Placeholder in editor - /// - public string? Placeholder { get; set; } - - /// - /// Order in which fields are displayed - /// - public int Index { get; set; } - - public Type? EditorType { get; set; } - - public OrderByType OrderByType { get; set; } - } + /// + /// Used as label for Node Editor + /// + public string? Name { get; set; } + + /// + /// Used as description for Node Editor + /// + public string? Description { get; set; } + + /// + /// Used as label in List View + /// + public string? ListName { get; set; } + + /// + /// Placeholder in editor + /// + public string? Placeholder { get; set; } + + /// + /// Order in which fields are displayed + /// + public int Index { get; set; } + + public Type? EditorType { get; set; } + + public OrderByType OrderByType { get; set; } } diff --git a/src/RapidCMS.Core/Attributes/RelationAttribute.cs b/src/RapidCMS.Core/Attributes/RelationAttribute.cs index e4d871e8..6f431892 100644 --- a/src/RapidCMS.Core/Attributes/RelationAttribute.cs +++ b/src/RapidCMS.Core/Attributes/RelationAttribute.cs @@ -1,15 +1,14 @@ using RapidCMS.Core.Enums; using System; -namespace RapidCMS.Core.Attributes +namespace RapidCMS.Core.Attributes; + +public class RelationAttribute : Attribute { - public class RelationAttribute : Attribute + public RelationAttribute(RelationType type) { - public RelationAttribute(RelationType type) - { - Type = type; - } - - public RelationType Type { get; } + Type = type; } + + public RelationType Type { get; } } diff --git a/src/RapidCMS.Core/Attributes/ValidFormAttribute.cs b/src/RapidCMS.Core/Attributes/ValidFormAttribute.cs index 183f3155..0ae35e39 100644 --- a/src/RapidCMS.Core/Attributes/ValidFormAttribute.cs +++ b/src/RapidCMS.Core/Attributes/ValidFormAttribute.cs @@ -1,9 +1,8 @@ using System; -namespace RapidCMS.Core.Attributes +namespace RapidCMS.Core.Attributes; + +internal class ValidFormAttribute : Attribute { - internal class ValidFormAttribute : Attribute - { - } } diff --git a/src/RapidCMS.Core/Attributes/ValidateEnumerableAttribute.cs b/src/RapidCMS.Core/Attributes/ValidateEnumerableAttribute.cs index dcdf760d..038c2d04 100644 --- a/src/RapidCMS.Core/Attributes/ValidateEnumerableAttribute.cs +++ b/src/RapidCMS.Core/Attributes/ValidateEnumerableAttribute.cs @@ -3,42 +3,41 @@ using System.ComponentModel.DataAnnotations; using RapidCMS.Core.Models; -namespace RapidCMS.Core.Attributes +namespace RapidCMS.Core.Attributes; + +/// +/// This attribute will instruct the entity validator to also validate each of the elements of this enumerable, instead of just the enumerable itself. +/// +public class ValidateEnumerableAttribute : ValidationAttribute { - /// - /// This attribute will instruct the entity validator to also validate each of the elements of this enumerable, instead of just the enumerable itself. - /// - public class ValidateEnumerableAttribute : ValidationAttribute + protected override ValidationResult IsValid(object? value, ValidationContext validationContext) { - protected override ValidationResult IsValid(object? value, ValidationContext validationContext) + if (value == null) { - if (value == null) - { - return ValidationResult.Success!; - } - - if (value is not IEnumerable enumerable) - { - return new ValidationResult($"{nameof(ValidateEnumerableAttribute)} can only be used on IEnumerable's"); - } + return ValidationResult.Success!; + } - var results = new List(); + if (value is not IEnumerable enumerable) + { + return new ValidationResult($"{nameof(ValidateEnumerableAttribute)} can only be used on IEnumerable's"); + } - foreach (var item in enumerable) - { - var context = new ValidationContext(item, validationContext, null); + var results = new List(); - Validator.TryValidateObject(item, context, results, true); - } + foreach (var item in enumerable) + { + var context = new ValidationContext(item, validationContext, null); - var compositeResults = new CompositeValidationResult($"Validation for {validationContext.DisplayName} failed!", validationContext.MemberName ?? "Unknown member"); - if (results.Count != 0) - { - results.ForEach(compositeResults.AddResult); - return compositeResults; - } + Validator.TryValidateObject(item, context, results, true); + } - return ValidationResult.Success!; + var compositeResults = new CompositeValidationResult($"Validation for {validationContext.DisplayName} failed!", validationContext.MemberName ?? "Unknown member"); + if (results.Count != 0) + { + results.ForEach(compositeResults.AddResult); + return compositeResults; } + + return ValidationResult.Success!; } } diff --git a/src/RapidCMS.Core/Attributes/ValidateObjectAsPropertyAttribute.cs b/src/RapidCMS.Core/Attributes/ValidateObjectAsPropertyAttribute.cs index c8ddb3d6..d87acef3 100644 --- a/src/RapidCMS.Core/Attributes/ValidateObjectAsPropertyAttribute.cs +++ b/src/RapidCMS.Core/Attributes/ValidateObjectAsPropertyAttribute.cs @@ -2,35 +2,34 @@ using System.ComponentModel.DataAnnotations; using System.Linq; -namespace RapidCMS.Core.Attributes +namespace RapidCMS.Core.Attributes; + +/// +/// This attribute will instruct the entity validator to validate the properties of this object, and use them as validation result of the object. +/// +/// Use this attribute when using a ModelEditor, or a custom editor which requires objects. +/// +public class ValidateObjectAsPropertyAttribute : ValidationAttribute { - /// - /// This attribute will instruct the entity validator to validate the properties of this object, and use them as validation result of the object. - /// - /// Use this attribute when using a ModelEditor, or a custom editor which requires objects. - /// - public class ValidateObjectAsPropertyAttribute : ValidationAttribute + protected override ValidationResult IsValid(object? value, ValidationContext validationContext) { - protected override ValidationResult IsValid(object? value, ValidationContext validationContext) + if (value == null) { - if (value == null) - { - return ValidationResult.Success!; - } - - var results = new List(); - var context = new ValidationContext(value, validationContext, null); + return ValidationResult.Success!; + } - Validator.TryValidateObject(value, context, results, true); + var results = new List(); + var context = new ValidationContext(value, validationContext, null); - if (results.Count != 0) - { - return new ValidationResult( - string.Join(" ", results.Select(x => x.ErrorMessage)), - !string.IsNullOrEmpty(validationContext.MemberName) ? new[] { validationContext.MemberName } : null); - } + Validator.TryValidateObject(value, context, results, true); - return ValidationResult.Success!; + if (results.Count != 0) + { + return new ValidationResult( + string.Join(" ", results.Select(x => x.ErrorMessage)), + !string.IsNullOrEmpty(validationContext.MemberName) ? new[] { validationContext.MemberName } : null); } + + return ValidationResult.Success!; } } diff --git a/src/RapidCMS.Core/Attributes/ValidateObjectAttribute.cs b/src/RapidCMS.Core/Attributes/ValidateObjectAttribute.cs index 83a62048..a7fc3e15 100644 --- a/src/RapidCMS.Core/Attributes/ValidateObjectAttribute.cs +++ b/src/RapidCMS.Core/Attributes/ValidateObjectAttribute.cs @@ -2,36 +2,35 @@ using System.ComponentModel.DataAnnotations; using RapidCMS.Core.Models; -namespace RapidCMS.Core.Attributes +namespace RapidCMS.Core.Attributes; + +/// +/// This attribute will instruct the entity validator to also validate the properties of this object, instead of just the object itself. +/// +/// Use this attribute when configuring nested properties, like: config.AddField(x => x.Object.Property). +/// +public class ValidateObjectAttribute : ValidationAttribute { - /// - /// This attribute will instruct the entity validator to also validate the properties of this object, instead of just the object itself. - /// - /// Use this attribute when configuring nested properties, like: config.AddField(x => x.Object.Property). - /// - public class ValidateObjectAttribute : ValidationAttribute + protected override ValidationResult IsValid(object? value, ValidationContext validationContext) { - protected override ValidationResult IsValid(object? value, ValidationContext validationContext) + if (value == null) { - if (value == null) - { - return ValidationResult.Success!; - } - - var results = new List(); - var context = new ValidationContext(value, validationContext, null); + return ValidationResult.Success!; + } - Validator.TryValidateObject(value, context, results, true); + var results = new List(); + var context = new ValidationContext(value, validationContext, null); - if (results.Count != 0) - { - var compositeResults = new CompositeValidationResult($"Validation for {validationContext.DisplayName} failed!", validationContext.MemberName ?? "Unknown member"); - results.ForEach(compositeResults.AddResult); + Validator.TryValidateObject(value, context, results, true); - return compositeResults; - } + if (results.Count != 0) + { + var compositeResults = new CompositeValidationResult($"Validation for {validationContext.DisplayName} failed!", validationContext.MemberName ?? "Unknown member"); + results.ForEach(compositeResults.AddResult); - return ValidationResult.Success!; + return compositeResults; } + + return ValidationResult.Success!; } } diff --git a/src/RapidCMS.Core/Authorization/AllowAllAuthorizationHandler.cs b/src/RapidCMS.Core/Authorization/AllowAllAuthorizationHandler.cs index fad2a7af..dc48b5d6 100644 --- a/src/RapidCMS.Core/Authorization/AllowAllAuthorizationHandler.cs +++ b/src/RapidCMS.Core/Authorization/AllowAllAuthorizationHandler.cs @@ -3,22 +3,21 @@ using Microsoft.AspNetCore.Authorization.Infrastructure; using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Authorization +namespace RapidCMS.Core.Authorization; + +internal class AllowAllAuthorizationHandler : AuthorizationHandler { - internal class AllowAllAuthorizationHandler : AuthorizationHandler + protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, OperationAuthorizationRequirement requirement, IEntity resource) { - protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, OperationAuthorizationRequirement requirement, IEntity resource) + if (context.User.Identity?.AuthenticationType == "anonymous") { - if (context.User.Identity?.AuthenticationType == "anonymous") - { - context.Succeed(requirement); - } - else - { - context.Fail(); - } - - return Task.CompletedTask; + context.Succeed(requirement); } + else + { + context.Fail(); + } + + return Task.CompletedTask; } } diff --git a/src/RapidCMS.Core/Authorization/AnonymousAuthenticationStateProvider.cs b/src/RapidCMS.Core/Authorization/AnonymousAuthenticationStateProvider.cs index 533bcc87..68136494 100644 --- a/src/RapidCMS.Core/Authorization/AnonymousAuthenticationStateProvider.cs +++ b/src/RapidCMS.Core/Authorization/AnonymousAuthenticationStateProvider.cs @@ -2,18 +2,17 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Components.Authorization; -namespace RapidCMS.Core.Authorization +namespace RapidCMS.Core.Authorization; + +internal class AnonymousAuthenticationStateProvider : AuthenticationStateProvider { - internal class AnonymousAuthenticationStateProvider : AuthenticationStateProvider + public override Task GetAuthenticationStateAsync() { - public override Task GetAuthenticationStateAsync() - { - var id = new ClaimsIdentity("anonymous"); - id.AddClaim(new Claim(ClaimTypes.Name, "Anonymous")); + var id = new ClaimsIdentity("anonymous"); + id.AddClaim(new Claim(ClaimTypes.Name, "Anonymous")); - var principal = new ClaimsPrincipal(id); + var principal = new ClaimsPrincipal(id); - return Task.FromResult(new AuthenticationState(principal)); - } + return Task.FromResult(new AuthenticationState(principal)); } } diff --git a/src/RapidCMS.Core/Authorization/Operations.cs b/src/RapidCMS.Core/Authorization/Operations.cs index 86b05c8c..e15ef6ad 100644 --- a/src/RapidCMS.Core/Authorization/Operations.cs +++ b/src/RapidCMS.Core/Authorization/Operations.cs @@ -2,49 +2,48 @@ using Microsoft.AspNetCore.Authorization.Infrastructure; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Authorization +namespace RapidCMS.Core.Authorization; + +public static class Operations { - public static class Operations - { - /// - /// Read-only viewing of entity - /// - public static OperationAuthorizationRequirement Read = new OperationAuthorizationRequirement { Name = nameof(Read) }; - - /// - /// Creating a new instance of entity - /// - public static OperationAuthorizationRequirement Create = new OperationAuthorizationRequirement { Name = nameof(Create) }; - - /// - /// Modifying an existing instance of entity - /// - public static OperationAuthorizationRequirement Update = new OperationAuthorizationRequirement { Name = nameof(Update) }; - - /// - /// Deleting an existing instance of entity - /// - public static OperationAuthorizationRequirement Delete = new OperationAuthorizationRequirement { Name = nameof(Delete) }; - - /// - /// Adding a relation to an existing entity - /// - public static OperationAuthorizationRequirement Add = new OperationAuthorizationRequirement { Name = nameof(Add) }; - - /// - /// Removing an existing relation to an existing entity - /// - public static OperationAuthorizationRequirement Remove = new OperationAuthorizationRequirement { Name = nameof(Remove) }; - - internal static OperationAuthorizationRequirement GetOperationForUsageType(UsageType type) - => (type & ~(UsageType.Node | UsageType.List)) switch - { - UsageType.Add => Add, - UsageType.Edit => Update, - UsageType.New => Create, - UsageType.Pick => Add, - UsageType.View => Read, - _ => throw new InvalidOperationException($"Operation of type {type} is not supported.") - }; - } + /// + /// Read-only viewing of entity + /// + public static OperationAuthorizationRequirement Read = new OperationAuthorizationRequirement { Name = nameof(Read) }; + + /// + /// Creating a new instance of entity + /// + public static OperationAuthorizationRequirement Create = new OperationAuthorizationRequirement { Name = nameof(Create) }; + + /// + /// Modifying an existing instance of entity + /// + public static OperationAuthorizationRequirement Update = new OperationAuthorizationRequirement { Name = nameof(Update) }; + + /// + /// Deleting an existing instance of entity + /// + public static OperationAuthorizationRequirement Delete = new OperationAuthorizationRequirement { Name = nameof(Delete) }; + + /// + /// Adding a relation to an existing entity + /// + public static OperationAuthorizationRequirement Add = new OperationAuthorizationRequirement { Name = nameof(Add) }; + + /// + /// Removing an existing relation to an existing entity + /// + public static OperationAuthorizationRequirement Remove = new OperationAuthorizationRequirement { Name = nameof(Remove) }; + + internal static OperationAuthorizationRequirement GetOperationForUsageType(UsageType type) + => (type & ~(UsageType.Node | UsageType.List)) switch + { + UsageType.Add => Add, + UsageType.Edit => Update, + UsageType.New => Create, + UsageType.Pick => Add, + UsageType.View => Read, + _ => throw new InvalidOperationException($"Operation of type {type} is not supported.") + }; } diff --git a/src/RapidCMS.Core/Converters/EntityModelJsonConverter.cs b/src/RapidCMS.Core/Converters/EntityModelJsonConverter.cs index f44326d3..5b7aeb9b 100644 --- a/src/RapidCMS.Core/Converters/EntityModelJsonConverter.cs +++ b/src/RapidCMS.Core/Converters/EntityModelJsonConverter.cs @@ -7,49 +7,48 @@ using RapidCMS.Core.Helpers; using RapidCMS.Core.Models.ApiBridge; -namespace RapidCMS.Core.Converters +namespace RapidCMS.Core.Converters; + +public class EntityModelJsonConverter : JsonConverter> + where TEntity : class, IEntity { - public class EntityModelJsonConverter : JsonConverter> - where TEntity : class, IEntity - { - private readonly IReadOnlyDictionary _typeDictionary; + private readonly IReadOnlyDictionary _typeDictionary; - public EntityModelJsonConverter() - { - var derivedTypes = typeof(TEntity).Assembly - .GetTypes() - .Where(x => !x.IsAbstract && x.IsSubclassOf(typeof(TEntity))); + public EntityModelJsonConverter() + { + var derivedTypes = typeof(TEntity).Assembly + .GetTypes() + .Where(x => !x.IsAbstract && x.IsSubclassOf(typeof(TEntity))); - _typeDictionary = derivedTypes.Append(typeof(TEntity)).ToDictionary(x => AliasHelper.GetEntityVariantAlias(x)); - } + _typeDictionary = derivedTypes.Append(typeof(TEntity)).ToDictionary(x => AliasHelper.GetEntityVariantAlias(x)); + } - public override bool CanRead => true; + public override bool CanRead => true; - public override EntityModel ReadJson(JsonReader reader, Type objectType, EntityModel? existingValue, bool hasExistingValue, JsonSerializer serializer) - { - var obj = JObject.Load(reader); + public override EntityModel ReadJson(JsonReader reader, Type objectType, EntityModel? existingValue, bool hasExistingValue, JsonSerializer serializer) + { + var obj = JObject.Load(reader); - var property = obj?.Property(nameof(EntityModel.VariantAlias), StringComparison.InvariantCultureIgnoreCase); - var alias = property?.Value.ToString(); + var property = obj?.Property(nameof(EntityModel.VariantAlias), StringComparison.InvariantCultureIgnoreCase); + var alias = property?.Value.ToString(); - if (obj != null && alias != null && _typeDictionary.TryGetValue(alias, out var type)) + if (obj != null && alias != null && _typeDictionary.TryGetValue(alias, out var type)) + { + var entityObject = obj.Property(nameof(EntityModel.Entity), StringComparison.InvariantCultureIgnoreCase)?.Value; + if (entityObject?.ToObject(type) is TEntity entity) { - var entityObject = obj.Property(nameof(EntityModel.Entity), StringComparison.InvariantCultureIgnoreCase)?.Value; - if (entityObject?.ToObject(type) is TEntity entity) - { - return EntityModel.Create(entity); - } + return EntityModel.Create(entity); } - - throw new InvalidOperationException($"Invalid json for {nameof(EntityModel)} given."); } + throw new InvalidOperationException($"Invalid json for {nameof(EntityModel)} given."); + } - public override bool CanWrite => false; - public override void WriteJson(JsonWriter writer, EntityModel? value, JsonSerializer serializer) - { - throw new NotImplementedException("The default serializer can do this perfectly well."); - } + public override bool CanWrite => false; + + public override void WriteJson(JsonWriter writer, EntityModel? value, JsonSerializer serializer) + { + throw new NotImplementedException("The default serializer can do this perfectly well."); } } diff --git a/src/RapidCMS.Core/Data/DataViewBuilder.cs b/src/RapidCMS.Core/Data/DataViewBuilder.cs index 553f352f..6b9d5d58 100644 --- a/src/RapidCMS.Core/Data/DataViewBuilder.cs +++ b/src/RapidCMS.Core/Data/DataViewBuilder.cs @@ -4,16 +4,15 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Models.Data; -namespace RapidCMS.Core.Data +namespace RapidCMS.Core.Data; + +public abstract class DataViewBuilder : IDataViewBuilder { - public abstract class DataViewBuilder : IDataViewBuilder - { - public abstract Task>> GetDataViewsAsync(); + public abstract Task>> GetDataViewsAsync(); - async Task> IDataViewBuilder.GetDataViewsAsync() - { - var elements = await GetDataViewsAsync(); - return elements.AsEnumerable(); - } + async Task> IDataViewBuilder.GetDataViewsAsync() + { + var elements = await GetDataViewsAsync(); + return elements.AsEnumerable(); } } diff --git a/src/RapidCMS.Core/Dispatchers/Api/DeleteEntityDispatcher.cs b/src/RapidCMS.Core/Dispatchers/Api/DeleteEntityDispatcher.cs index 64306dca..c099905b 100644 --- a/src/RapidCMS.Core/Dispatchers/Api/DeleteEntityDispatcher.cs +++ b/src/RapidCMS.Core/Dispatchers/Api/DeleteEntityDispatcher.cs @@ -10,43 +10,42 @@ using RapidCMS.Core.Models.Request.Api; using RapidCMS.Core.Models.Response; -namespace RapidCMS.Core.Dispatchers.Api +namespace RapidCMS.Core.Dispatchers.Api; + +internal class DeleteEntityDispatcher : IInteractionDispatcher { - internal class DeleteEntityDispatcher : IInteractionDispatcher + private readonly IAuthService _authService; + private readonly IRepositoryResolver _repositoryResolver; + private readonly IParentService _parentService; + + public DeleteEntityDispatcher( + IAuthService authService, + IRepositoryResolver repositoryResolver, + IParentService parentService) { - private readonly IAuthService _authService; - private readonly IRepositoryResolver _repositoryResolver; - private readonly IParentService _parentService; - - public DeleteEntityDispatcher( - IAuthService authService, - IRepositoryResolver repositoryResolver, - IParentService parentService) - { - _authService = authService; - _repositoryResolver = repositoryResolver; - _parentService = parentService; - } + _authService = authService; + _repositoryResolver = repositoryResolver; + _parentService = parentService; + } - public async Task InvokeAsync(DeleteEntityRequestModel request) + public async Task InvokeAsync(DeleteEntityRequestModel request) + { + if (string.IsNullOrWhiteSpace(request.Descriptor.RepositoryAlias) || + string.IsNullOrWhiteSpace(request.Descriptor.Id)) { - if (string.IsNullOrWhiteSpace(request.Descriptor.RepositoryAlias) || - string.IsNullOrWhiteSpace(request.Descriptor.Id)) - { - throw new ArgumentNullException(); - } + throw new ArgumentNullException(); + } - var parent = await _parentService.GetParentAsync(ParentPath.TryParse(request.Descriptor.ParentPath)); + var parent = await _parentService.GetParentAsync(ParentPath.TryParse(request.Descriptor.ParentPath)); - var subjectRepository = _repositoryResolver.GetRepository(request.Descriptor.RepositoryAlias); - var subjectEntity = await subjectRepository.GetByIdAsync(request.Descriptor.Id, new ViewContext(null, parent)) - ?? throw new NotFoundException("Could not find entity to delete"); + var subjectRepository = _repositoryResolver.GetRepository(request.Descriptor.RepositoryAlias); + var subjectEntity = await subjectRepository.GetByIdAsync(request.Descriptor.Id, new ViewContext(null, parent)) + ?? throw new NotFoundException("Could not find entity to delete"); - await _authService.EnsureAuthorizedUserAsync(Operations.Delete, subjectEntity); + await _authService.EnsureAuthorizedUserAsync(Operations.Delete, subjectEntity); - await subjectRepository.DeleteAsync(request.Descriptor.Id, new ViewContext(null, parent)); + await subjectRepository.DeleteAsync(request.Descriptor.Id, new ViewContext(null, parent)); - return new ApiCommandResponseModel(); - } + return new ApiCommandResponseModel(); } } diff --git a/src/RapidCMS.Core/Dispatchers/Api/GetEntitiesDispatcher.cs b/src/RapidCMS.Core/Dispatchers/Api/GetEntitiesDispatcher.cs index 57fed641..27f0abd8 100644 --- a/src/RapidCMS.Core/Dispatchers/Api/GetEntitiesDispatcher.cs +++ b/src/RapidCMS.Core/Dispatchers/Api/GetEntitiesDispatcher.cs @@ -12,70 +12,69 @@ using RapidCMS.Core.Models.Request.Api; using RapidCMS.Core.Models.Response; -namespace RapidCMS.Core.Dispatchers.Api +namespace RapidCMS.Core.Dispatchers.Api; + +internal class GetEntitiesDispatcher : IPresentationDispatcher { - internal class GetEntitiesDispatcher : IPresentationDispatcher + private readonly IRepositoryResolver _repositoryResolver; + private readonly IDataViewResolver _dataViewResolver; + private readonly IParentService _parentService; + private readonly IAuthService _authService; + + public GetEntitiesDispatcher( + IRepositoryResolver repositoryResolver, + IDataViewResolver dataViewResolver, + IParentService parentService, + IAuthService authService) { - private readonly IRepositoryResolver _repositoryResolver; - private readonly IDataViewResolver _dataViewResolver; - private readonly IParentService _parentService; - private readonly IAuthService _authService; + _repositoryResolver = repositoryResolver; + _dataViewResolver = dataViewResolver; + _parentService = parentService; + _authService = authService; + } - public GetEntitiesDispatcher( - IRepositoryResolver repositoryResolver, - IDataViewResolver dataViewResolver, - IParentService parentService, - IAuthService authService) - { - _repositoryResolver = repositoryResolver; - _dataViewResolver = dataViewResolver; - _parentService = parentService; - _authService = authService; - } + public async Task GetAsync(GetEntitiesRequestModel request) + { + var subjectRepository = _repositoryResolver.GetRepository(request.RepositoryAlias); - public async Task GetAsync(GetEntitiesRequestModel request) + var parentPath = request is GetEntitiesOfParentRequestModel parentRequest ? parentRequest.ParentPath + : request is GetEntitiesOfRelationRequestModel relationRequest ? relationRequest.Related.ParentPath + : default; + var parent = await _parentService.GetParentAsync(ParentPath.TryParse(parentPath)); + var related = default(IRelated); + if (request is GetEntitiesOfRelationRequestModel relatedRequest) { - var subjectRepository = _repositoryResolver.GetRepository(request.RepositoryAlias); - - var parentPath = request is GetEntitiesOfParentRequestModel parentRequest ? parentRequest.ParentPath - : request is GetEntitiesOfRelationRequestModel relationRequest ? relationRequest.Related.ParentPath - : default; - var parent = await _parentService.GetParentAsync(ParentPath.TryParse(parentPath)); - var related = default(IRelated); - if (request is GetEntitiesOfRelationRequestModel relatedRequest) - { - var relatedRepository = _repositoryResolver.GetRepository(relatedRequest.Related.RepositoryAlias ?? throw new ArgumentNullException()); - var relatedEntity = await relatedRepository.GetByIdAsync(relatedRequest.Related.Id ?? throw new ArgumentNullException(), new ViewContext(null, default)) - ?? throw new NotFoundException("Could not find related entity"); - related = new RelatedEntity(parent, relatedEntity, relatedRequest.Related.RepositoryAlias); - } + var relatedRepository = _repositoryResolver.GetRepository(relatedRequest.Related.RepositoryAlias ?? throw new ArgumentNullException()); + var relatedEntity = await relatedRepository.GetByIdAsync(relatedRequest.Related.Id ?? throw new ArgumentNullException(), new ViewContext(null, default)) + ?? throw new NotFoundException("Could not find related entity"); + related = new RelatedEntity(parent, relatedEntity, relatedRequest.Related.RepositoryAlias); + } - var protoEntity = await subjectRepository.NewAsync(new ViewContext(null, parent), default); + var protoEntity = await subjectRepository.NewAsync(new ViewContext(null, parent), default); - await _authService.EnsureAuthorizedUserAsync(request.UsageType, protoEntity); - await _dataViewResolver.ApplyDataViewToViewAsync(request.View); + await _authService.EnsureAuthorizedUserAsync(request.UsageType, protoEntity); + await _dataViewResolver.ApplyDataViewToViewAsync(request.View); - var action = (request.UsageType & ~(UsageType.List)) switch - { - UsageType.Add when related != null => async () => await subjectRepository.GetAllNonRelatedAsync(new RelatedViewContext(related, null, default), request.View), - _ when related != null => async () => await subjectRepository.GetAllRelatedAsync(new RelatedViewContext(related, null, default), request.View), - _ when related == null => async () => await subjectRepository.GetAllAsync(new ViewContext(null, parent), request.View), + var action = (request.UsageType & ~(UsageType.List)) switch + { + UsageType.Add when related != null => async () => await subjectRepository.GetAllNonRelatedAsync(new RelatedViewContext(related, null, default), request.View), + _ when related != null => async () => await subjectRepository.GetAllRelatedAsync(new RelatedViewContext(related, null, default), request.View), + _ when related == null => async () => await subjectRepository.GetAllAsync(new ViewContext(null, parent), request.View), - _ => default(Func>>) - }; + _ => default(Func>>) + }; - if (action == default) - { - throw new InvalidOperationException($"UsageType {request.UsageType} is invalid for this method"); - } + if (action == default) + { + throw new InvalidOperationException($"UsageType {request.UsageType} is invalid for this method"); + } - var entities = await action.Invoke(); + var entities = await action.Invoke(); - return new EntitiesResponseModel - { - Entities = entities, - MoreDataAvailable = request.View.MoreDataAvailable - }; - } + return new EntitiesResponseModel + { + Entities = entities, + MoreDataAvailable = request.View.MoreDataAvailable + }; } } diff --git a/src/RapidCMS.Core/Dispatchers/Api/GetEntityDispatcher.cs b/src/RapidCMS.Core/Dispatchers/Api/GetEntityDispatcher.cs index 55ecd814..08789736 100644 --- a/src/RapidCMS.Core/Dispatchers/Api/GetEntityDispatcher.cs +++ b/src/RapidCMS.Core/Dispatchers/Api/GetEntityDispatcher.cs @@ -11,66 +11,65 @@ using RapidCMS.Core.Models.Request.Api; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Dispatchers.Api +namespace RapidCMS.Core.Dispatchers.Api; + +internal class GetEntityDispatcher : IPresentationDispatcher { - internal class GetEntityDispatcher : IPresentationDispatcher + private readonly ISetupResolver _entityVariantResolver; + private readonly IRepositoryResolver _repositoryResolver; + private readonly IParentService _parentService; + private readonly IAuthService _authService; + + public GetEntityDispatcher( + ISetupResolver entityVariantResolver, + IRepositoryResolver repositoryResolver, + IParentService parentService, + IAuthService authService) { - private readonly ISetupResolver _entityVariantResolver; - private readonly IRepositoryResolver _repositoryResolver; - private readonly IParentService _parentService; - private readonly IAuthService _authService; + _entityVariantResolver = entityVariantResolver; + _repositoryResolver = repositoryResolver; + _parentService = parentService; + _authService = authService; + } - public GetEntityDispatcher( - ISetupResolver entityVariantResolver, - IRepositoryResolver repositoryResolver, - IParentService parentService, - IAuthService authService) + public async Task GetAsync(GetEntityRequestModel request) + { + if (string.IsNullOrWhiteSpace(request.Subject.Id) && (request.UsageType.HasFlag(UsageType.View) || request.UsageType.HasFlag(UsageType.Edit))) { - _entityVariantResolver = entityVariantResolver; - _repositoryResolver = repositoryResolver; - _parentService = parentService; - _authService = authService; + throw new InvalidOperationException($"Cannot View/Edit Node when id is null"); } - - public async Task GetAsync(GetEntityRequestModel request) + if (!string.IsNullOrWhiteSpace(request.Subject.Id) && request.UsageType.HasFlag(UsageType.New)) { - if (string.IsNullOrWhiteSpace(request.Subject.Id) && (request.UsageType.HasFlag(UsageType.View) || request.UsageType.HasFlag(UsageType.Edit))) - { - throw new InvalidOperationException($"Cannot View/Edit Node when id is null"); - } - if (!string.IsNullOrWhiteSpace(request.Subject.Id) && request.UsageType.HasFlag(UsageType.New)) - { - throw new InvalidOperationException($"Cannot New Node when id is not null"); - } + throw new InvalidOperationException($"Cannot New Node when id is not null"); + } - var repository = _repositoryResolver.GetRepository(request.Subject.RepositoryAlias ?? throw new ArgumentNullException()); + var repository = _repositoryResolver.GetRepository(request.Subject.RepositoryAlias ?? throw new ArgumentNullException()); - var parent = await _parentService.GetParentAsync(ParentPath.TryParse(request.Subject.ParentPath)); - var entityVariant = request.Subject.VariantAlias == null ? default : await _entityVariantResolver.ResolveSetupAsync(request.Subject.VariantAlias); + var parent = await _parentService.GetParentAsync(ParentPath.TryParse(request.Subject.ParentPath)); + var entityVariant = request.Subject.VariantAlias == null ? default : await _entityVariantResolver.ResolveSetupAsync(request.Subject.VariantAlias); - var action = (request.UsageType & ~(UsageType.Node)) switch - { - UsageType.View => () => repository.GetByIdAsync(request.Subject.Id!, new ViewContext(null, parent)), - UsageType.Edit => () => repository.GetByIdAsync(request.Subject.Id!, new ViewContext(null, parent)), - UsageType.New => () => repository.NewAsync(new ViewContext(null, parent), entityVariant?.Type)!, + var action = (request.UsageType & ~(UsageType.Node)) switch + { + UsageType.View => () => repository.GetByIdAsync(request.Subject.Id!, new ViewContext(null, parent)), + UsageType.Edit => () => repository.GetByIdAsync(request.Subject.Id!, new ViewContext(null, parent)), + UsageType.New => () => repository.NewAsync(new ViewContext(null, parent), entityVariant?.Type)!, - _ => default(Func>) - }; + _ => default(Func>) + }; - if (action == default) - { - throw new InvalidOperationException($"UsageType {request.UsageType} is invalid for this method"); - } + if (action == default) + { + throw new InvalidOperationException($"UsageType {request.UsageType} is invalid for this method"); + } - var entity = await action.Invoke(); - if (entity == null) - { - throw new NotFoundException("Failed to get entity for given id"); - } + var entity = await action.Invoke(); + if (entity == null) + { + throw new NotFoundException("Failed to get entity for given id"); + } - await _authService.EnsureAuthorizedUserAsync(request.UsageType, entity); + await _authService.EnsureAuthorizedUserAsync(request.UsageType, entity); - return entity; - } + return entity; } } diff --git a/src/RapidCMS.Core/Dispatchers/Api/PersistEntityDispatcher.cs b/src/RapidCMS.Core/Dispatchers/Api/PersistEntityDispatcher.cs index fcf54b32..9661d584 100644 --- a/src/RapidCMS.Core/Dispatchers/Api/PersistEntityDispatcher.cs +++ b/src/RapidCMS.Core/Dispatchers/Api/PersistEntityDispatcher.cs @@ -12,98 +12,97 @@ using RapidCMS.Core.Models.Request.Api; using RapidCMS.Core.Models.Response; -namespace RapidCMS.Core.Dispatchers.Api +namespace RapidCMS.Core.Dispatchers.Api; + +internal class PersistEntityDispatcher : IInteractionDispatcher { - internal class PersistEntityDispatcher : IInteractionDispatcher + private readonly IAuthService _authService; + private readonly IEntityVariantResolver _entityVariantResolver; + private readonly IRepositoryResolver _repositoryResolver; + private readonly IParentService _parentService; + private readonly IEditContextFactory _editContextFactory; + + public PersistEntityDispatcher( + IAuthService authService, + IEntityVariantResolver entityVariantResolver, + IRepositoryResolver repositoryResolver, + IParentService parentService, + IEditContextFactory editContextFactory) { - private readonly IAuthService _authService; - private readonly IEntityVariantResolver _entityVariantResolver; - private readonly IRepositoryResolver _repositoryResolver; - private readonly IParentService _parentService; - private readonly IEditContextFactory _editContextFactory; + _authService = authService; + _entityVariantResolver = entityVariantResolver; + _repositoryResolver = repositoryResolver; + _parentService = parentService; + _editContextFactory = editContextFactory; + } - public PersistEntityDispatcher( - IAuthService authService, - IEntityVariantResolver entityVariantResolver, - IRepositoryResolver repositoryResolver, - IParentService parentService, - IEditContextFactory editContextFactory) + public async Task InvokeAsync(PersistEntityRequestModel request) + { + if (string.IsNullOrWhiteSpace(request.Descriptor.RepositoryAlias)) { - _authService = authService; - _entityVariantResolver = entityVariantResolver; - _repositoryResolver = repositoryResolver; - _parentService = parentService; - _editContextFactory = editContextFactory; + throw new ArgumentNullException(); } - public async Task InvokeAsync(PersistEntityRequestModel request) - { - if (string.IsNullOrWhiteSpace(request.Descriptor.RepositoryAlias)) - { - throw new ArgumentNullException(); - } - - var parent = await _parentService.GetParentAsync(ParentPath.TryParse(request.Descriptor.ParentPath)); + var parent = await _parentService.GetParentAsync(ParentPath.TryParse(request.Descriptor.ParentPath)); - var (repositoryEntityType, entityVariants) = _entityVariantResolver.GetValidVariantsForRepository(request.Descriptor.RepositoryAlias); + var (repositoryEntityType, entityVariants) = _entityVariantResolver.GetValidVariantsForRepository(request.Descriptor.RepositoryAlias); - if (repositoryEntityType == null || !(entityVariants?.Contains(request.Entity.GetType()) ?? false)) - { - throw new InvalidOperationException("Invalid entity provided."); - } + if (repositoryEntityType == null || !(entityVariants?.Contains(request.Entity.GetType()) ?? false)) + { + throw new InvalidOperationException("Invalid entity provided."); + } - var subjectRepository = _repositoryResolver.GetRepository(request.Descriptor.RepositoryAlias); - var referenceEntity = (request.EntityState == EntityState.IsExisting) - ? await subjectRepository.GetByIdAsync(request.Descriptor.Id ?? throw new InvalidOperationException("Cannot modify entity without giving an Id."), new ViewContext(null, parent)) - : await subjectRepository.NewAsync(new ViewContext(null, parent), request.Entity.GetType()); + var subjectRepository = _repositoryResolver.GetRepository(request.Descriptor.RepositoryAlias); + var referenceEntity = (request.EntityState == EntityState.IsExisting) + ? await subjectRepository.GetByIdAsync(request.Descriptor.Id ?? throw new InvalidOperationException("Cannot modify entity without giving an Id."), new ViewContext(null, parent)) + : await subjectRepository.NewAsync(new ViewContext(null, parent), request.Entity.GetType()); - if (referenceEntity == null) - { - throw new NotFoundException("Reference entity is null"); - } + if (referenceEntity == null) + { + throw new NotFoundException("Reference entity is null"); + } - var usageType = UsageType.Node | (request.EntityState == EntityState.IsNew ? UsageType.New : UsageType.Edit); + var usageType = UsageType.Node | (request.EntityState == EntityState.IsNew ? UsageType.New : UsageType.Edit); - await _authService.EnsureAuthorizedUserAsync(usageType, request.Entity); + await _authService.EnsureAuthorizedUserAsync(usageType, request.Entity); - var editContext = await _editContextFactory.GetEditContextWrapperAsync( - usageType, - request.EntityState, - repositoryEntityType, - request.Entity, - referenceEntity, - parent, - request.Relations); + var editContext = await _editContextFactory.GetEditContextWrapperAsync( + usageType, + request.EntityState, + repositoryEntityType, + request.Entity, + referenceEntity, + parent, + request.Relations); - try + try + { + await editContext.EnforceCompleteValidationAsync(); + + if (request.EntityState == EntityState.IsNew) { - await editContext.EnforceCompleteValidationAsync(); - - if (request.EntityState == EntityState.IsNew) - { - return new ApiPersistEntityResponseModel - { - NewEntity = await subjectRepository.InsertAsync(editContext) - }; - } - else if (request.EntityState == EntityState.IsExisting) + return new ApiPersistEntityResponseModel { - await subjectRepository.UpdateAsync(editContext); + NewEntity = await subjectRepository.InsertAsync(editContext) + }; + } + else if (request.EntityState == EntityState.IsExisting) + { + await subjectRepository.UpdateAsync(editContext); - return new ApiCommandResponseModel(); - } - else - { - throw new InvalidOperationException("Invalid usage type"); - } + return new ApiCommandResponseModel(); } - catch (InvalidEntityException) + else { - return new ApiPersistEntityResponseModel - { - ValidationErrors = editContext.ValidationErrors - }; + throw new InvalidOperationException("Invalid usage type"); } } + catch (InvalidEntityException) + { + return new ApiPersistEntityResponseModel + { + ValidationErrors = editContext.ValidationErrors + }; + } } } diff --git a/src/RapidCMS.Core/Dispatchers/Api/RelateEntityDispatcher.cs b/src/RapidCMS.Core/Dispatchers/Api/RelateEntityDispatcher.cs index 7e8c05b9..dca2b228 100644 --- a/src/RapidCMS.Core/Dispatchers/Api/RelateEntityDispatcher.cs +++ b/src/RapidCMS.Core/Dispatchers/Api/RelateEntityDispatcher.cs @@ -10,57 +10,56 @@ using RapidCMS.Core.Models.Request.Api; using RapidCMS.Core.Models.Response; -namespace RapidCMS.Core.Dispatchers.Api +namespace RapidCMS.Core.Dispatchers.Api; + +internal class RelateEntityDispatcher : IInteractionDispatcher { - internal class RelateEntityDispatcher : IInteractionDispatcher + private readonly IRepositoryResolver _repositoryResolver; + private readonly IAuthService _authService; + private readonly IParentService _parentService; + + public RelateEntityDispatcher( + IRepositoryResolver repositoryResolver, + IAuthService authService, + IParentService parentService) { - private readonly IRepositoryResolver _repositoryResolver; - private readonly IAuthService _authService; - private readonly IParentService _parentService; + _repositoryResolver = repositoryResolver; + _authService = authService; + _parentService = parentService; + } - public RelateEntityDispatcher( - IRepositoryResolver repositoryResolver, - IAuthService authService, - IParentService parentService) + public async Task InvokeAsync(PersistRelatedEntityRequestModel request) + { + if (string.IsNullOrWhiteSpace(request.Subject.RepositoryAlias) || + string.IsNullOrWhiteSpace(request.Subject.Id) || + string.IsNullOrWhiteSpace(request.Related.RepositoryAlias) || + string.IsNullOrWhiteSpace(request.Related.Id)) { - _repositoryResolver = repositoryResolver; - _authService = authService; - _parentService = parentService; + throw new ArgumentNullException(); } - public async Task InvokeAsync(PersistRelatedEntityRequestModel request) - { - if (string.IsNullOrWhiteSpace(request.Subject.RepositoryAlias) || - string.IsNullOrWhiteSpace(request.Subject.Id) || - string.IsNullOrWhiteSpace(request.Related.RepositoryAlias) || - string.IsNullOrWhiteSpace(request.Related.Id)) - { - throw new ArgumentNullException(); - } - - var subjectRepository = _repositoryResolver.GetRepository(request.Subject.RepositoryAlias); - var relatedRepository = _repositoryResolver.GetRepository(request.Related.RepositoryAlias); + var subjectRepository = _repositoryResolver.GetRepository(request.Subject.RepositoryAlias); + var relatedRepository = _repositoryResolver.GetRepository(request.Related.RepositoryAlias); - var subjectEntity = await subjectRepository.GetByIdAsync(request.Subject.Id, new ViewContext(null, default)) - ?? throw new NotFoundException("Subject entity was not found"); - var relatedEntity = await relatedRepository.GetByIdAsync(request.Related.Id, new ViewContext(null, default)) - ?? throw new NotFoundException("Related entity was not found"); - var parent = await _parentService.GetParentAsync(ParentPath.TryParse(request.Related.ParentPath)); + var subjectEntity = await subjectRepository.GetByIdAsync(request.Subject.Id, new ViewContext(null, default)) + ?? throw new NotFoundException("Subject entity was not found"); + var relatedEntity = await relatedRepository.GetByIdAsync(request.Related.Id, new ViewContext(null, default)) + ?? throw new NotFoundException("Related entity was not found"); + var parent = await _parentService.GetParentAsync(ParentPath.TryParse(request.Related.ParentPath)); - var related = new RelatedEntity(parent, relatedEntity, request.Related.RepositoryAlias); + var related = new RelatedEntity(parent, relatedEntity, request.Related.RepositoryAlias); - if (request.Action == PersistRelatedEntityRequestModel.Actions.Add) - { - await _authService.EnsureAuthorizedUserAsync(Operations.Add, subjectEntity); - await subjectRepository.AddAsync(new RelatedViewContext(related, null, default), request.Subject.Id); - } - else if (request.Action == PersistRelatedEntityRequestModel.Actions.Remove) - { - await _authService.EnsureAuthorizedUserAsync(Operations.Remove, subjectEntity); - await subjectRepository.AddAsync(new RelatedViewContext(related, null, default), request.Subject.Id); - } - - return new ApiCommandResponseModel(); + if (request.Action == PersistRelatedEntityRequestModel.Actions.Add) + { + await _authService.EnsureAuthorizedUserAsync(Operations.Add, subjectEntity); + await subjectRepository.AddAsync(new RelatedViewContext(related, null, default), request.Subject.Id); } + else if (request.Action == PersistRelatedEntityRequestModel.Actions.Remove) + { + await _authService.EnsureAuthorizedUserAsync(Operations.Remove, subjectEntity); + await subjectRepository.AddAsync(new RelatedViewContext(related, null, default), request.Subject.Id); + } + + return new ApiCommandResponseModel(); } } diff --git a/src/RapidCMS.Core/Dispatchers/Api/ReorderEntityDispatcher.cs b/src/RapidCMS.Core/Dispatchers/Api/ReorderEntityDispatcher.cs index 315747f8..65605097 100644 --- a/src/RapidCMS.Core/Dispatchers/Api/ReorderEntityDispatcher.cs +++ b/src/RapidCMS.Core/Dispatchers/Api/ReorderEntityDispatcher.cs @@ -10,44 +10,43 @@ using RapidCMS.Core.Models.Request.Api; using RapidCMS.Core.Models.Response; -namespace RapidCMS.Core.Dispatchers.Api +namespace RapidCMS.Core.Dispatchers.Api; + +internal class ReorderEntityDispatcher : IInteractionDispatcher { - internal class ReorderEntityDispatcher : IInteractionDispatcher + private readonly IRepositoryResolver _repositoryResolver; + private readonly IParentService _parentService; + private readonly IAuthService _authService; + + public ReorderEntityDispatcher( + IRepositoryResolver repositoryResolver, + IParentService parentService, + IAuthService authService) { - private readonly IRepositoryResolver _repositoryResolver; - private readonly IParentService _parentService; - private readonly IAuthService _authService; - - public ReorderEntityDispatcher( - IRepositoryResolver repositoryResolver, - IParentService parentService, - IAuthService authService) - { - _repositoryResolver = repositoryResolver; - _parentService = parentService; - _authService = authService; - } + _repositoryResolver = repositoryResolver; + _parentService = parentService; + _authService = authService; + } - public async Task InvokeAsync(PersistReorderRequestModel request) + public async Task InvokeAsync(PersistReorderRequestModel request) + { + if (string.IsNullOrWhiteSpace(request.Subject.RepositoryAlias) || + string.IsNullOrWhiteSpace(request.Subject.Id)) { - if (string.IsNullOrWhiteSpace(request.Subject.RepositoryAlias) || - string.IsNullOrWhiteSpace(request.Subject.Id)) - { - throw new ArgumentNullException(); - } + throw new ArgumentNullException(); + } - var subjectRepository = _repositoryResolver.GetRepository(request.Subject.RepositoryAlias); - - var subjectParent = await _parentService.GetParentAsync(ParentPath.TryParse(request.Subject.ParentPath)); + var subjectRepository = _repositoryResolver.GetRepository(request.Subject.RepositoryAlias); + + var subjectParent = await _parentService.GetParentAsync(ParentPath.TryParse(request.Subject.ParentPath)); - var subjectEntity = await subjectRepository.GetByIdAsync(request.Subject.Id, new ViewContext(null, subjectParent)) - ?? throw new NotFoundException("Subject entity was not found"); + var subjectEntity = await subjectRepository.GetByIdAsync(request.Subject.Id, new ViewContext(null, subjectParent)) + ?? throw new NotFoundException("Subject entity was not found"); - await _authService.EnsureAuthorizedUserAsync(Operations.Update, subjectEntity); + await _authService.EnsureAuthorizedUserAsync(Operations.Update, subjectEntity); - await subjectRepository.ReorderAsync(request.BeforeId, request.Subject.Id, new ViewContext(null, subjectParent)); + await subjectRepository.ReorderAsync(request.BeforeId, request.Subject.Id, new ViewContext(null, subjectParent)); - return new ApiCommandResponseModel(); - } + return new ApiCommandResponseModel(); } } diff --git a/src/RapidCMS.Core/Dispatchers/Form/EntitiesInteractionDispatcher.cs b/src/RapidCMS.Core/Dispatchers/Form/EntitiesInteractionDispatcher.cs index 71335801..726dc92f 100644 --- a/src/RapidCMS.Core/Dispatchers/Form/EntitiesInteractionDispatcher.cs +++ b/src/RapidCMS.Core/Dispatchers/Form/EntitiesInteractionDispatcher.cs @@ -21,203 +21,202 @@ using RapidCMS.Core.Models.Setup; using RapidCMS.Core.Navigation; -namespace RapidCMS.Core.Dispatchers.Form +namespace RapidCMS.Core.Dispatchers.Form; + +internal class EntitiesInteractionDispatcher : + IInteractionDispatcher, + IInteractionDispatcher { - internal class EntitiesInteractionDispatcher : - IInteractionDispatcher, - IInteractionDispatcher + private readonly INavigationStateProvider _navigationStateProvider; + private readonly ISetupResolver _collectionResolver; + private readonly IRepositoryResolver _repositoryResolver; + private readonly IConcurrencyService _concurrencyService; + private readonly IButtonInteraction _buttonInteraction; + private readonly IEditContextFactory _editContextFactory; + private readonly IMediator _mediator; + + public EntitiesInteractionDispatcher( + INavigationStateProvider navigationStateProvider, + ISetupResolver collectionResolver, + IRepositoryResolver repositoryResolver, + IConcurrencyService concurrencyService, + IButtonInteraction buttonInteraction, + IEditContextFactory editContextFactory, + IMediator mediator) { - private readonly INavigationStateProvider _navigationStateProvider; - private readonly ISetupResolver _collectionResolver; - private readonly IRepositoryResolver _repositoryResolver; - private readonly IConcurrencyService _concurrencyService; - private readonly IButtonInteraction _buttonInteraction; - private readonly IEditContextFactory _editContextFactory; - private readonly IMediator _mediator; - - public EntitiesInteractionDispatcher( - INavigationStateProvider navigationStateProvider, - ISetupResolver collectionResolver, - IRepositoryResolver repositoryResolver, - IConcurrencyService concurrencyService, - IButtonInteraction buttonInteraction, - IEditContextFactory editContextFactory, - IMediator mediator) - { - _navigationStateProvider = navigationStateProvider; - _collectionResolver = collectionResolver; - _repositoryResolver = repositoryResolver; - _concurrencyService = concurrencyService; - _buttonInteraction = buttonInteraction; - _editContextFactory = editContextFactory; - _mediator = mediator; - } + _navigationStateProvider = navigationStateProvider; + _collectionResolver = collectionResolver; + _repositoryResolver = repositoryResolver; + _concurrencyService = concurrencyService; + _buttonInteraction = buttonInteraction; + _editContextFactory = editContextFactory; + _mediator = mediator; + } - Task IInteractionDispatcher.InvokeAsync(PersistEntitiesRequestModel request) - { - return InvokeAsync(request, new ListViewCommandResponseModel()); - } + Task IInteractionDispatcher.InvokeAsync(PersistEntitiesRequestModel request) + { + return InvokeAsync(request, new ListViewCommandResponseModel()); + } - Task IInteractionDispatcher.InvokeAsync(PersistEntitiesRequestModel request) - { - return InvokeAsync(request, new ListEditorCommandResponseModel()); - } + Task IInteractionDispatcher.InvokeAsync(PersistEntitiesRequestModel request) + { + return InvokeAsync(request, new ListEditorCommandResponseModel()); + } - private async Task InvokeAsync(PersistEntitiesRequestModel request, T response) - where T : ViewCommandResponseModel - { - var collection = await _collectionResolver.ResolveSetupAsync(request.ListContext.CollectionAlias); - var repository = _repositoryResolver.GetRepository(collection); + private async Task InvokeAsync(PersistEntitiesRequestModel request, T response) + where T : ViewCommandResponseModel + { + var collection = await _collectionResolver.ResolveSetupAsync(request.ListContext.CollectionAlias); + var repository = _repositoryResolver.GetRepository(collection); - var (crudType, entityVariant) = await _buttonInteraction.ValidateButtonInteractionAsync(request); + var (crudType, entityVariant) = await _buttonInteraction.ValidateButtonInteractionAsync(request); - switch (crudType) - { - case CrudType.Create: - if (entityVariant == null) - { - throw new InvalidOperationException($"Button of type {CrudType.Create} must have an EntityVariant."); - } + switch (crudType) + { + case CrudType.Create: + if (entityVariant == null) + { + throw new InvalidOperationException($"Button of type {CrudType.Create} must have an EntityVariant."); + } + + if (response is ListViewCommandResponseModel || ShouldFallbackToNavigatingToNodeEditor(collection)) + { + _navigationStateProvider.AppendNavigationState( + request.NavigationState, + new NavigationState( + request.ListContext.CollectionAlias, + request.ListContext.Parent?.GetParentPath(), + entityVariant.Alias, + request.Related, + UsageType.New)); + } + else + { + _navigationStateProvider.AppendNavigationState( + request.NavigationState, + new NavigationState( + request.ListContext.CollectionAlias, + request.ListContext.Parent?.GetParentPath(), + entityVariant.Alias, + request.Related, + UsageType.New, + PageType.Collection) + { + CollectionState = request.NavigationState.CollectionState + }); + } + break; + + case CrudType.Update: + var affectedEntities = new List(); - if (response is ListViewCommandResponseModel || ShouldFallbackToNavigatingToNodeEditor(collection)) + foreach (var editContext in request.ListContext.EditContexts.Where(f => f.IsModified() || f.IsReordered())) + { + var innerRequest = new PersistEntityCollectionRequestModel { - _navigationStateProvider.AppendNavigationState( - request.NavigationState, - new NavigationState( - request.ListContext.CollectionAlias, - request.ListContext.Parent?.GetParentPath(), - entityVariant.Alias, - request.Related, - UsageType.New)); - } - else + ActionId = request.ActionId, + CustomData = request.CustomData, + EditContext = editContext, + ListContext = request.ListContext + }; + if (!await editContext.IsValidAsync()) { - _navigationStateProvider.AppendNavigationState( - request.NavigationState, - new NavigationState( - request.ListContext.CollectionAlias, - request.ListContext.Parent?.GetParentPath(), - entityVariant.Alias, - request.Related, - UsageType.New, - PageType.Collection) - { - CollectionState = request.NavigationState.CollectionState - }); + throw new InvalidEntityException(); } - break; - case CrudType.Update: - var affectedEntities = new List(); + await _buttonInteraction.ValidateButtonInteractionAsync(innerRequest); - foreach (var editContext in request.ListContext.EditContexts.Where(f => f.IsModified() || f.IsReordered())) + if (editContext.IsModified()) { - var innerRequest = new PersistEntityCollectionRequestModel - { - ActionId = request.ActionId, - CustomData = request.CustomData, - EditContext = editContext, - ListContext = request.ListContext - }; - if (!await editContext.IsValidAsync()) - { - throw new InvalidEntityException(); - } - - await _buttonInteraction.ValidateButtonInteractionAsync(innerRequest); - - if (editContext.IsModified()) - { - var wrapper = await _editContextFactory.GetEditContextWrapperAsync(editContext); - await _concurrencyService.EnsureCorrectConcurrencyAsync(() => repository.UpdateAsync(wrapper)); - } - if (editContext.IsReordered()) - { - await _concurrencyService.EnsureCorrectConcurrencyAsync( - () => repository.ReorderAsync(editContext.ReorderedBeforeId, editContext.Entity.Id!, new ViewContext(null, editContext.Parent))); - } - - affectedEntities.Add(editContext.Entity); + var wrapper = await _editContextFactory.GetEditContextWrapperAsync(editContext); + await _concurrencyService.EnsureCorrectConcurrencyAsync(() => repository.UpdateAsync(wrapper)); } - - response.RefreshIds = affectedEntities.SelectNotNull(x => x.Id); - - _mediator.NotifyEvent(this, new CollectionRepositoryEventArgs( - collection.Alias, - collection.RepositoryAlias, - request.ListContext.ProtoEditContext.Parent?.GetParentPath(), - response.RefreshIds, - CrudType.Update)); - break; - - case CrudType.None: - response.NoOp = true; - break; - - case CrudType.Refresh: - break; - - case CrudType.Return: - if (!_navigationStateProvider.RemoveNavigationState(request.NavigationState)) + if (editContext.IsReordered()) { - var parentPath = request.ListContext.Parent?.GetParentPath(); - _navigationStateProvider.AppendNavigationState( - request.NavigationState, - new NavigationState( - request.ListContext.CollectionAlias, - parentPath, - null, - request.Related, - collection.ListEditor == null ? UsageType.View : UsageType.Edit, - PageType.Collection)); + await _concurrencyService.EnsureCorrectConcurrencyAsync( + () => repository.ReorderAsync(editContext.ReorderedBeforeId, editContext.Entity.Id!, new ViewContext(null, editContext.Parent))); } - break; - case CrudType.Up: - var (newParentPath, repositoryAlias, parentId) = ParentPath.RemoveLevel(request.ListContext.Parent?.GetParentPath()); + affectedEntities.Add(editContext.Entity); + } - if (repositoryAlias == null) - { - break; - } + response.RefreshIds = affectedEntities.SelectNotNull(x => x.Id); - var parentCollection = collection.Parent != null && collection.Parent.Type == PageType.Collection ? await _collectionResolver.ResolveSetupAsync(collection.Parent.Alias) : default; - if (parentCollection == null) - { - throw new InvalidOperationException("Cannot go Up on collection that is root."); - } + _mediator.NotifyEvent(this, new CollectionRepositoryEventArgs( + collection.Alias, + collection.RepositoryAlias, + request.ListContext.ProtoEditContext.Parent?.GetParentPath(), + response.RefreshIds, + CrudType.Update)); + break; - _navigationStateProvider.AppendNavigationState( - request.NavigationState, - new NavigationState( - request.ListContext.CollectionAlias, - newParentPath, - parentCollection.EntityVariant.Alias, - parentId, - collection.ListEditor == null ? UsageType.View : UsageType.Edit)); - break; + case CrudType.None: + response.NoOp = true; + break; - case CrudType.Add when request.Related != null: + case CrudType.Refresh: + break; + + case CrudType.Return: + if (!_navigationStateProvider.RemoveNavigationState(request.NavigationState)) + { + var parentPath = request.ListContext.Parent?.GetParentPath(); _navigationStateProvider.AppendNavigationState( request.NavigationState, new NavigationState( request.ListContext.CollectionAlias, + parentPath, + null, request.Related, - UsageType.Add)); - break; + collection.ListEditor == null ? UsageType.View : UsageType.Edit, + PageType.Collection)); + } + break; - default: - throw new InvalidOperationException(); - } + case CrudType.Up: + var (newParentPath, repositoryAlias, parentId) = ParentPath.RemoveLevel(request.ListContext.Parent?.GetParentPath()); - await _buttonInteraction.CompleteButtonInteractionAsync(request); - - return response; + if (repositoryAlias == null) + { + break; + } + + var parentCollection = collection.Parent != null && collection.Parent.Type == PageType.Collection ? await _collectionResolver.ResolveSetupAsync(collection.Parent.Alias) : default; + if (parentCollection == null) + { + throw new InvalidOperationException("Cannot go Up on collection that is root."); + } + + _navigationStateProvider.AppendNavigationState( + request.NavigationState, + new NavigationState( + request.ListContext.CollectionAlias, + newParentPath, + parentCollection.EntityVariant.Alias, + parentId, + collection.ListEditor == null ? UsageType.View : UsageType.Edit)); + break; + + case CrudType.Add when request.Related != null: + _navigationStateProvider.AppendNavigationState( + request.NavigationState, + new NavigationState( + request.ListContext.CollectionAlias, + request.Related, + UsageType.Add)); + break; + + default: + throw new InvalidOperationException(); } - private static bool ShouldFallbackToNavigatingToNodeEditor(CollectionSetup collection) - { - return collection.NodeEditor != null; - } + await _buttonInteraction.CompleteButtonInteractionAsync(request); + + return response; + } + + private static bool ShouldFallbackToNavigatingToNodeEditor(CollectionSetup collection) + { + return collection.NodeEditor != null; } } diff --git a/src/RapidCMS.Core/Dispatchers/Form/EntityInteractionDispatcher.cs b/src/RapidCMS.Core/Dispatchers/Form/EntityInteractionDispatcher.cs index c70da3e2..0b98d037 100644 --- a/src/RapidCMS.Core/Dispatchers/Form/EntityInteractionDispatcher.cs +++ b/src/RapidCMS.Core/Dispatchers/Form/EntityInteractionDispatcher.cs @@ -17,215 +17,214 @@ using RapidCMS.Core.Models.Setup; using RapidCMS.Core.Navigation; -namespace RapidCMS.Core.Dispatchers.Form +namespace RapidCMS.Core.Dispatchers.Form; + +internal class EntityInteractionDispatcher : + IInteractionDispatcher, + IInteractionDispatcher, + IInteractionDispatcher { - internal class EntityInteractionDispatcher : - IInteractionDispatcher, - IInteractionDispatcher, - IInteractionDispatcher + private readonly INavigationStateProvider _navigationStateProvider; + private readonly ISetupResolver _collectionResolver; + private readonly IRepositoryResolver _repositoryResolver; + private readonly IConcurrencyService _concurrencyService; + private readonly IButtonInteraction _buttonInteraction; + private readonly IEditContextFactory _editContextFactory; + private readonly IMediator _mediator; + + public EntityInteractionDispatcher( + INavigationStateProvider navigationStateProvider, + ISetupResolver collectionResolver, + IRepositoryResolver repositoryResolver, + IConcurrencyService concurrencyService, + IButtonInteraction buttonInteraction, + IEditContextFactory editContextFactory, + IMediator mediator) { - private readonly INavigationStateProvider _navigationStateProvider; - private readonly ISetupResolver _collectionResolver; - private readonly IRepositoryResolver _repositoryResolver; - private readonly IConcurrencyService _concurrencyService; - private readonly IButtonInteraction _buttonInteraction; - private readonly IEditContextFactory _editContextFactory; - private readonly IMediator _mediator; - - public EntityInteractionDispatcher( - INavigationStateProvider navigationStateProvider, - ISetupResolver collectionResolver, - IRepositoryResolver repositoryResolver, - IConcurrencyService concurrencyService, - IButtonInteraction buttonInteraction, - IEditContextFactory editContextFactory, - IMediator mediator) - { - _navigationStateProvider = navigationStateProvider; - _collectionResolver = collectionResolver; - _repositoryResolver = repositoryResolver; - _concurrencyService = concurrencyService; - _buttonInteraction = buttonInteraction; - _editContextFactory = editContextFactory; - _mediator = mediator; - } + _navigationStateProvider = navigationStateProvider; + _collectionResolver = collectionResolver; + _repositoryResolver = repositoryResolver; + _concurrencyService = concurrencyService; + _buttonInteraction = buttonInteraction; + _editContextFactory = editContextFactory; + _mediator = mediator; + } - Task IInteractionDispatcher.InvokeAsync(PersistEntityRequestModel request) - { - return InvokeAsync(request, new NodeViewCommandResponseModel()); - } + Task IInteractionDispatcher.InvokeAsync(PersistEntityRequestModel request) + { + return InvokeAsync(request, new NodeViewCommandResponseModel()); + } - Task IInteractionDispatcher.InvokeAsync(PersistEntityRequestModel request) - { - return InvokeAsync(request, new NodeInListViewCommandResponseModel()); - } + Task IInteractionDispatcher.InvokeAsync(PersistEntityRequestModel request) + { + return InvokeAsync(request, new NodeInListViewCommandResponseModel()); + } - Task IInteractionDispatcher.InvokeAsync(PersistRelatedEntityRequestModel request) - { - return InvokeAsync(request, new NodeInListViewCommandResponseModel()); - } + Task IInteractionDispatcher.InvokeAsync(PersistRelatedEntityRequestModel request) + { + return InvokeAsync(request, new NodeInListViewCommandResponseModel()); + } - private async Task InvokeAsync(PersistEntityRequestModel request, T response) - where T : ViewCommandResponseModel - { - var collection = await _collectionResolver.ResolveSetupAsync(request.EditContext.CollectionAlias); - var repository = _repositoryResolver.GetRepository(collection); + private async Task InvokeAsync(PersistEntityRequestModel request, T response) + where T : ViewCommandResponseModel + { + var collection = await _collectionResolver.ResolveSetupAsync(request.EditContext.CollectionAlias); + var repository = _repositoryResolver.GetRepository(collection); - var entityVariant = collection.GetEntityVariant(request.EditContext.Entity); + var entityVariant = collection.GetEntityVariant(request.EditContext.Entity); - var crudType = await _buttonInteraction.ValidateButtonInteractionAsync(request); + var crudType = await _buttonInteraction.ValidateButtonInteractionAsync(request); - switch (crudType) - { - case CrudType.View: - _navigationStateProvider.AppendNavigationState(request.NavigationState, new NavigationState( - request.EditContext.CollectionAlias, - request.EditContext.Parent?.GetParentPath(), - entityVariant.Alias, - request.EditContext.Entity.Id, - UsageType.View)); + switch (crudType) + { + case CrudType.View: + _navigationStateProvider.AppendNavigationState(request.NavigationState, new NavigationState( + request.EditContext.CollectionAlias, + request.EditContext.Parent?.GetParentPath(), + entityVariant.Alias, + request.EditContext.Entity.Id, + UsageType.View)); + break; + + case CrudType.Edit: + _navigationStateProvider.AppendNavigationState(request.NavigationState, new NavigationState( + request.EditContext.CollectionAlias, + request.EditContext.Parent?.GetParentPath(), + entityVariant.Alias, + request.EditContext.Entity.Id, + UsageType.Edit)); + break; + + case CrudType.Update: + var updateContext = await _editContextFactory.GetEditContextWrapperAsync(request.EditContext); + if (!await updateContext.IsValidAsync()) + { + throw new InvalidEntityException(); + } + + await _concurrencyService.EnsureCorrectConcurrencyAsync(() => repository.UpdateAsync(updateContext)); + + if (request.EditContext.IsReordered()) + { + await _concurrencyService.EnsureCorrectConcurrencyAsync( + () => repository.ReorderAsync(request.EditContext.ReorderedBeforeId, request.EditContext.Entity.Id!, new ViewContext(collection.Alias, request.EditContext.Parent))); + } + + response.RefreshIds = new[] { request.EditContext.Entity.Id! }; + + _mediator.NotifyEvent(this, new CollectionRepositoryEventArgs( + collection.Alias, + collection.RepositoryAlias, + request.EditContext.Parent?.GetParentPath(), + request.EditContext.Entity.Id, + CrudType.Update)); + + break; + + case CrudType.Insert: + var insertContext = await _editContextFactory.GetEditContextWrapperAsync(request.EditContext); + if (!await insertContext.IsValidAsync()) + { + throw new InvalidEntityException(); + } + + var newEntity = await _concurrencyService.EnsureCorrectConcurrencyAsync(() => repository.InsertAsync(insertContext)); + if (newEntity == null) + { + // add another break; + } - case CrudType.Edit: + if (request is PersistRelatedEntityRequestModel related) + { + await _concurrencyService.EnsureCorrectConcurrencyAsync(() => repository.AddAsync(new RelatedViewContext(related.Related, collection.Alias, default), request.EditContext.Entity.Id!)); + } + + if (response is NodeViewCommandResponseModel) + { _navigationStateProvider.AppendNavigationState(request.NavigationState, new NavigationState( request.EditContext.CollectionAlias, request.EditContext.Parent?.GetParentPath(), entityVariant.Alias, - request.EditContext.Entity.Id, + newEntity.Id, UsageType.Edit)); - break; - - case CrudType.Update: - var updateContext = await _editContextFactory.GetEditContextWrapperAsync(request.EditContext); - if (!await updateContext.IsValidAsync()) - { - throw new InvalidEntityException(); - } + } - await _concurrencyService.EnsureCorrectConcurrencyAsync(() => repository.UpdateAsync(updateContext)); + _mediator.NotifyEvent(this, new CollectionRepositoryEventArgs( + collection.Alias, + collection.RepositoryAlias, + request.EditContext.Parent?.GetParentPath(), + request.EditContext.Entity.Id, + CrudType.Insert)); - if (request.EditContext.IsReordered()) - { - await _concurrencyService.EnsureCorrectConcurrencyAsync( - () => repository.ReorderAsync(request.EditContext.ReorderedBeforeId, request.EditContext.Entity.Id!, new ViewContext(collection.Alias, request.EditContext.Parent))); - } + break; - response.RefreshIds = new[] { request.EditContext.Entity.Id! }; + case CrudType.Delete: + await _concurrencyService.EnsureCorrectConcurrencyAsync(() => repository.DeleteAsync(request.EditContext.Entity.Id!, new ViewContext(collection.Alias, request.EditContext.Parent))); - _mediator.NotifyEvent(this, new CollectionRepositoryEventArgs( - collection.Alias, - collection.RepositoryAlias, + if (response is NodeViewCommandResponseModel) + { + _navigationStateProvider.ReplaceNavigationState(request.NavigationState, new NavigationState( + request.EditContext.CollectionAlias, request.EditContext.Parent?.GetParentPath(), - request.EditContext.Entity.Id, - CrudType.Update)); + collection.ListEditor == null ? UsageType.View : UsageType.Edit)); + } - break; + _mediator.NotifyEvent(this, new CollectionRepositoryEventArgs( + collection.Alias, + collection.RepositoryAlias, + request.EditContext.Parent?.GetParentPath(), + request.EditContext.Entity.Id, + CrudType.Delete)); - case CrudType.Insert: - var insertContext = await _editContextFactory.GetEditContextWrapperAsync(request.EditContext); - if (!await insertContext.IsValidAsync()) - { - throw new InvalidEntityException(); - } - - var newEntity = await _concurrencyService.EnsureCorrectConcurrencyAsync(() => repository.InsertAsync(insertContext)); - if (newEntity == null) - { - // add another - break; - } - - if (request is PersistRelatedEntityRequestModel related) - { - await _concurrencyService.EnsureCorrectConcurrencyAsync(() => repository.AddAsync(new RelatedViewContext(related.Related, collection.Alias, default), request.EditContext.Entity.Id!)); - } - - if (response is NodeViewCommandResponseModel) - { - _navigationStateProvider.AppendNavigationState(request.NavigationState, new NavigationState( - request.EditContext.CollectionAlias, - request.EditContext.Parent?.GetParentPath(), - entityVariant.Alias, - newEntity.Id, - UsageType.Edit)); - } - - _mediator.NotifyEvent(this, new CollectionRepositoryEventArgs( - collection.Alias, - collection.RepositoryAlias, - request.EditContext.Parent?.GetParentPath(), - request.EditContext.Entity.Id, - CrudType.Insert)); + break; - break; + case CrudType.Pick when request is PersistRelatedEntityRequestModel relationRequest: - case CrudType.Delete: - await _concurrencyService.EnsureCorrectConcurrencyAsync(() => repository.DeleteAsync(request.EditContext.Entity.Id!, new ViewContext(collection.Alias, request.EditContext.Parent))); + await _concurrencyService.EnsureCorrectConcurrencyAsync(() => repository.AddAsync(new RelatedViewContext(relationRequest.Related, collection.Alias, default), request.EditContext.Entity.Id!)); - if (response is NodeViewCommandResponseModel) - { - _navigationStateProvider.ReplaceNavigationState(request.NavigationState, new NavigationState( - request.EditContext.CollectionAlias, - request.EditContext.Parent?.GetParentPath(), - collection.ListEditor == null ? UsageType.View : UsageType.Edit)); - } + _mediator.NotifyEvent(this, new CollectionRepositoryEventArgs( + collection.Alias, + collection.RepositoryAlias, + request.EditContext.Parent?.GetParentPath(), + request.EditContext.Entity.Id, + CrudType.Pick)); - _mediator.NotifyEvent(this, new CollectionRepositoryEventArgs( - collection.Alias, - collection.RepositoryAlias, - request.EditContext.Parent?.GetParentPath(), - request.EditContext.Entity.Id, - CrudType.Delete)); + break; - break; + case CrudType.Remove when request is PersistRelatedEntityRequestModel relationRequest: - case CrudType.Pick when request is PersistRelatedEntityRequestModel relationRequest: + await _concurrencyService.EnsureCorrectConcurrencyAsync(() => repository.RemoveAsync(new RelatedViewContext(relationRequest.Related, collection.Alias, default), request.EditContext.Entity.Id!)); - await _concurrencyService.EnsureCorrectConcurrencyAsync(() => repository.AddAsync(new RelatedViewContext(relationRequest.Related, collection.Alias, default), request.EditContext.Entity.Id!)); + _mediator.NotifyEvent(this, new CollectionRepositoryEventArgs( + collection.Alias, + collection.RepositoryAlias, + request.EditContext.Parent?.GetParentPath(), + request.EditContext.Entity.Id, + CrudType.Remove)); - _mediator.NotifyEvent(this, new CollectionRepositoryEventArgs( - collection.Alias, - collection.RepositoryAlias, - request.EditContext.Parent?.GetParentPath(), - request.EditContext.Entity.Id, - CrudType.Pick)); - - break; + break; - case CrudType.Remove when request is PersistRelatedEntityRequestModel relationRequest: + case CrudType.None: + response.NoOp = true; + break; - await _concurrencyService.EnsureCorrectConcurrencyAsync(() => repository.RemoveAsync(new RelatedViewContext(relationRequest.Related, collection.Alias, default), request.EditContext.Entity.Id!)); + case CrudType.Refresh: + break; - _mediator.NotifyEvent(this, new CollectionRepositoryEventArgs( - collection.Alias, - collection.RepositoryAlias, - request.EditContext.Parent?.GetParentPath(), - request.EditContext.Entity.Id, - CrudType.Remove)); - - break; + case CrudType.Up: + _navigationStateProvider.AppendNavigationState(request.NavigationState, new NavigationState( + request.EditContext.CollectionAlias, + request.EditContext.Parent?.GetParentPath(), + collection.ListEditor == null ? UsageType.View : UsageType.Edit)); + break; - case CrudType.None: - response.NoOp = true; - break; - - case CrudType.Refresh: - break; - - case CrudType.Up: - _navigationStateProvider.AppendNavigationState(request.NavigationState, new NavigationState( - request.EditContext.CollectionAlias, - request.EditContext.Parent?.GetParentPath(), - collection.ListEditor == null ? UsageType.View : UsageType.Edit)); - break; - - default: - throw new InvalidOperationException(); - } + default: + throw new InvalidOperationException(); + } - await _buttonInteraction.CompleteButtonInteractionAsync(request); + await _buttonInteraction.CompleteButtonInteractionAsync(request); - return response; - } + return response; } } diff --git a/src/RapidCMS.Core/Dispatchers/Form/GetEntitiesDispatcher.cs b/src/RapidCMS.Core/Dispatchers/Form/GetEntitiesDispatcher.cs index c559ab6d..2f155aeb 100644 --- a/src/RapidCMS.Core/Dispatchers/Form/GetEntitiesDispatcher.cs +++ b/src/RapidCMS.Core/Dispatchers/Form/GetEntitiesDispatcher.cs @@ -12,122 +12,121 @@ using RapidCMS.Core.Models.Request.Form; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Dispatchers.Form +namespace RapidCMS.Core.Dispatchers.Form; + +internal class GetEntitiesDispatcher : IPresentationDispatcher { - internal class GetEntitiesDispatcher : IPresentationDispatcher + private readonly ISetupResolver _collectionResolver; + private readonly IRepositoryResolver _repositoryResolver; + private readonly IDataViewResolver _dataViewResolver; + private readonly IParentService _parentService; + private readonly IConcurrencyService _concurrencyService; + private readonly IAuthService _authService; + private readonly IServiceProvider _serviceProvider; + + public GetEntitiesDispatcher( + ISetupResolver collectionResolver, + IRepositoryResolver repositoryResolver, + IDataViewResolver dataViewResolver, + IParentService parentService, + IConcurrencyService concurrencyService, + IAuthService authService, + IServiceProvider serviceProvider) { - private readonly ISetupResolver _collectionResolver; - private readonly IRepositoryResolver _repositoryResolver; - private readonly IDataViewResolver _dataViewResolver; - private readonly IParentService _parentService; - private readonly IConcurrencyService _concurrencyService; - private readonly IAuthService _authService; - private readonly IServiceProvider _serviceProvider; - - public GetEntitiesDispatcher( - ISetupResolver collectionResolver, - IRepositoryResolver repositoryResolver, - IDataViewResolver dataViewResolver, - IParentService parentService, - IConcurrencyService concurrencyService, - IAuthService authService, - IServiceProvider serviceProvider) - { - _collectionResolver = collectionResolver; - _repositoryResolver = repositoryResolver; - _dataViewResolver = dataViewResolver; - _parentService = parentService; - _concurrencyService = concurrencyService; - _authService = authService; - _serviceProvider = serviceProvider; - } + _collectionResolver = collectionResolver; + _repositoryResolver = repositoryResolver; + _dataViewResolver = dataViewResolver; + _parentService = parentService; + _concurrencyService = concurrencyService; + _authService = authService; + _serviceProvider = serviceProvider; + } - public async Task GetAsync(GetEntitiesRequestModel request) - { - var collection = await _collectionResolver.ResolveSetupAsync(request.CollectionAlias); - var variant = collection.GetEntityVariant(request.VariantAlias); - var repository = _repositoryResolver.GetRepository(collection); + public async Task GetAsync(GetEntitiesRequestModel request) + { + var collection = await _collectionResolver.ResolveSetupAsync(request.CollectionAlias); + var variant = collection.GetEntityVariant(request.VariantAlias); + var repository = _repositoryResolver.GetRepository(collection); - var requestedEntityVariantIsDefaultVariant = variant.Alias == collection.EntityVariant.Alias; + var requestedEntityVariantIsDefaultVariant = variant.Alias == collection.EntityVariant.Alias; - var parent = request is GetEntitiesOfParentRequestModel parentRequest ? await _parentService.GetParentAsync(parentRequest.ParentPath) : default; - var relatedEntity = (request as GetEntitiesOfRelationRequestModel)?.Related; + var parent = request is GetEntitiesOfParentRequestModel parentRequest ? await _parentService.GetParentAsync(parentRequest.ParentPath) : default; + var relatedEntity = (request as GetEntitiesOfRelationRequestModel)?.Related; - var protoEntity = await _concurrencyService.EnsureCorrectConcurrencyAsync(() => repository.NewAsync(new ViewContext(collection.Alias, parent), collection.EntityVariant.Type)); - var newEntity = requestedEntityVariantIsDefaultVariant - ? protoEntity - : await _concurrencyService.EnsureCorrectConcurrencyAsync(() => repository.NewAsync(new ViewContext(collection.Alias, parent), variant.Type)); + var protoEntity = await _concurrencyService.EnsureCorrectConcurrencyAsync(() => repository.NewAsync(new ViewContext(collection.Alias, parent), collection.EntityVariant.Type)); + var newEntity = requestedEntityVariantIsDefaultVariant + ? protoEntity + : await _concurrencyService.EnsureCorrectConcurrencyAsync(() => repository.NewAsync(new ViewContext(collection.Alias, parent), variant.Type)); - await _authService.EnsureAuthorizedUserAsync(request.UsageType, protoEntity); - await _dataViewResolver.ApplyDataViewToViewAsync(request.View); + await _authService.EnsureAuthorizedUserAsync(request.UsageType, protoEntity); + await _dataViewResolver.ApplyDataViewToViewAsync(request.View); - var action = (request.UsageType & ~(UsageType.List)) switch - { - UsageType.Add when relatedEntity != null => () => repository.GetAllNonRelatedAsync(new RelatedViewContext(relatedEntity!, collection.Alias, parent), request.View), - _ when relatedEntity != null => () => repository.GetAllRelatedAsync(new RelatedViewContext(relatedEntity!, collection.Alias, parent), request.View), - _ when relatedEntity == null => () => repository.GetAllAsync(new ViewContext(collection.Alias, parent), request.View), + var action = (request.UsageType & ~(UsageType.List)) switch + { + UsageType.Add when relatedEntity != null => () => repository.GetAllNonRelatedAsync(new RelatedViewContext(relatedEntity!, collection.Alias, parent), request.View), + _ when relatedEntity != null => () => repository.GetAllRelatedAsync(new RelatedViewContext(relatedEntity!, collection.Alias, parent), request.View), + _ when relatedEntity == null => () => repository.GetAllAsync(new ViewContext(collection.Alias, parent), request.View), - _ => default(Func>>) - }; + _ => default(Func>>) + }; - if (action == default) - { - throw new InvalidOperationException($"UsageType {request.UsageType} is invalid for this method"); - } + if (action == default) + { + throw new InvalidOperationException($"UsageType {request.UsageType} is invalid for this method"); + } - var isRoot = parent == null || request.IsEmbedded; + var isRoot = parent == null || request.IsEmbedded; - var protoEditContextUsage = request.UsageType | (isRoot ? UsageType.Root : UsageType.NotRoot); + var protoEditContextUsage = request.UsageType | (isRoot ? UsageType.Root : UsageType.NotRoot); - var protoEditContext = new FormEditContext(request.CollectionAlias, collection.RepositoryAlias, collection.EntityVariant.Alias, protoEntity, parent, protoEditContextUsage | UsageType.List, collection.Validators, _serviceProvider); - var newEditContext = new FormEditContext(request.CollectionAlias, collection.RepositoryAlias, variant.Alias, newEntity, parent, request.UsageType | UsageType.Node, collection.Validators, _serviceProvider); + var protoEditContext = new FormEditContext(request.CollectionAlias, collection.RepositoryAlias, collection.EntityVariant.Alias, protoEntity, parent, protoEditContextUsage | UsageType.List, collection.Validators, _serviceProvider); + var newEditContext = new FormEditContext(request.CollectionAlias, collection.RepositoryAlias, variant.Alias, newEntity, parent, request.UsageType | UsageType.Node, collection.Validators, _serviceProvider); - var existingEntities = await _concurrencyService.EnsureCorrectConcurrencyAsync(action); + var existingEntities = await _concurrencyService.EnsureCorrectConcurrencyAsync(action); - return new ListContext( - request.CollectionAlias, - protoEditContext, - parent, - request.UsageType, - ConvertEditContexts(request, protoEditContext, newEditContext, existingEntities), - _serviceProvider); - } + return new ListContext( + request.CollectionAlias, + protoEditContext, + parent, + request.UsageType, + ConvertEditContexts(request, protoEditContext, newEditContext, existingEntities), + _serviceProvider); + } - private List ConvertEditContexts( - GetEntitiesRequestModel request, - FormEditContext protoEditContext, - FormEditContext newEditContext, - IEnumerable existingEntities) + private List ConvertEditContexts( + GetEntitiesRequestModel request, + FormEditContext protoEditContext, + FormEditContext newEditContext, + IEnumerable existingEntities) + { + if (request.UsageType.HasFlag(UsageType.Add)) { - if (request.UsageType.HasFlag(UsageType.Add)) - { - return existingEntities - .Select(ent => new FormEditContext(protoEditContext, ent, UsageType.Node | UsageType.Pick, _serviceProvider)) - .ToList(); - } - else if (request.UsageType.HasFlag(UsageType.Edit) || request.UsageType.HasFlag(UsageType.New)) - { - var entities = existingEntities - .Select(ent => new FormEditContext(protoEditContext, ent, UsageType.Node | UsageType.Edit, _serviceProvider)) - .ToList(); - - if (request.UsageType.HasFlag(UsageType.New)) - { - entities.Insert(0, newEditContext); - } + return existingEntities + .Select(ent => new FormEditContext(protoEditContext, ent, UsageType.Node | UsageType.Pick, _serviceProvider)) + .ToList(); + } + else if (request.UsageType.HasFlag(UsageType.Edit) || request.UsageType.HasFlag(UsageType.New)) + { + var entities = existingEntities + .Select(ent => new FormEditContext(protoEditContext, ent, UsageType.Node | UsageType.Edit, _serviceProvider)) + .ToList(); - return entities; - } - else if (request.UsageType.HasFlag(UsageType.View)) + if (request.UsageType.HasFlag(UsageType.New)) { - return existingEntities - .Select(ent => new FormEditContext(protoEditContext, ent, UsageType.Node | UsageType.View, _serviceProvider)) - .ToList(); - } - else - { - throw new InvalidOperationException($"Failed to process {request.UsageType} for collection {request.CollectionAlias}"); + entities.Insert(0, newEditContext); } + + return entities; + } + else if (request.UsageType.HasFlag(UsageType.View)) + { + return existingEntities + .Select(ent => new FormEditContext(protoEditContext, ent, UsageType.Node | UsageType.View, _serviceProvider)) + .ToList(); + } + else + { + throw new InvalidOperationException($"Failed to process {request.UsageType} for collection {request.CollectionAlias}"); } } } diff --git a/src/RapidCMS.Core/Dispatchers/Form/GetEntityDispatcher.cs b/src/RapidCMS.Core/Dispatchers/Form/GetEntityDispatcher.cs index dce5a987..d57722a1 100644 --- a/src/RapidCMS.Core/Dispatchers/Form/GetEntityDispatcher.cs +++ b/src/RapidCMS.Core/Dispatchers/Form/GetEntityDispatcher.cs @@ -9,73 +9,72 @@ using RapidCMS.Core.Models.Request.Form; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Dispatchers.Form +namespace RapidCMS.Core.Dispatchers.Form; + +internal class GetEntityDispatcher : IPresentationDispatcher { - internal class GetEntityDispatcher : IPresentationDispatcher + private readonly ISetupResolver _collectionResolver; + private readonly IRepositoryResolver _repositoryResolver; + private readonly IParentService _parentService; + private readonly IConcurrencyService _concurrencyService; + private readonly IAuthService _authService; + private readonly IServiceProvider _serviceProvider; + + public GetEntityDispatcher( + ISetupResolver collectionResolver, + IRepositoryResolver repositoryResolver, + IParentService parentService, + IConcurrencyService concurrencyService, + IAuthService authService, + IServiceProvider serviceProvider) { - private readonly ISetupResolver _collectionResolver; - private readonly IRepositoryResolver _repositoryResolver; - private readonly IParentService _parentService; - private readonly IConcurrencyService _concurrencyService; - private readonly IAuthService _authService; - private readonly IServiceProvider _serviceProvider; + _collectionResolver = collectionResolver; + _repositoryResolver = repositoryResolver; + _parentService = parentService; + _concurrencyService = concurrencyService; + _authService = authService; + _serviceProvider = serviceProvider; + } - public GetEntityDispatcher( - ISetupResolver collectionResolver, - IRepositoryResolver repositoryResolver, - IParentService parentService, - IConcurrencyService concurrencyService, - IAuthService authService, - IServiceProvider serviceProvider) + public async Task GetAsync(GetEntityRequestModel request) + { + if (string.IsNullOrWhiteSpace(request.Id) && (request.UsageType.HasFlag(UsageType.View) || request.UsageType.HasFlag(UsageType.Edit))) { - _collectionResolver = collectionResolver; - _repositoryResolver = repositoryResolver; - _parentService = parentService; - _concurrencyService = concurrencyService; - _authService = authService; - _serviceProvider = serviceProvider; + throw new InvalidOperationException($"Cannot View/Edit Node when id is null"); } - - public async Task GetAsync(GetEntityRequestModel request) + if (!string.IsNullOrWhiteSpace(request.Id) && request.UsageType.HasFlag(UsageType.New)) { - if (string.IsNullOrWhiteSpace(request.Id) && (request.UsageType.HasFlag(UsageType.View) || request.UsageType.HasFlag(UsageType.Edit))) - { - throw new InvalidOperationException($"Cannot View/Edit Node when id is null"); - } - if (!string.IsNullOrWhiteSpace(request.Id) && request.UsageType.HasFlag(UsageType.New)) - { - throw new InvalidOperationException($"Cannot New Node when id is not null"); - } + throw new InvalidOperationException($"Cannot New Node when id is not null"); + } - var collection = await _collectionResolver.ResolveSetupAsync(request.CollectionAlias); - var variant = request.VariantAlias == null ? collection.EntityVariant : collection.GetEntityVariant(request.VariantAlias); - var repository = _repositoryResolver.GetRepository(collection); + var collection = await _collectionResolver.ResolveSetupAsync(request.CollectionAlias); + var variant = request.VariantAlias == null ? collection.EntityVariant : collection.GetEntityVariant(request.VariantAlias); + var repository = _repositoryResolver.GetRepository(collection); - var parent = await _parentService.GetParentAsync(request.ParentPath); + var parent = await _parentService.GetParentAsync(request.ParentPath); - var action = (request.UsageType & ~(UsageType.Node)) switch - { - UsageType.View => () => repository.GetByIdAsync(request.Id!, new ViewContext(collection.Alias, parent)), - UsageType.Edit => () => repository.GetByIdAsync(request.Id!, new ViewContext(collection.Alias, parent)), - UsageType.New => () => repository.NewAsync(new ViewContext(collection.Alias, parent), variant.Type)!, + var action = (request.UsageType & ~(UsageType.Node)) switch + { + UsageType.View => () => repository.GetByIdAsync(request.Id!, new ViewContext(collection.Alias, parent)), + UsageType.Edit => () => repository.GetByIdAsync(request.Id!, new ViewContext(collection.Alias, parent)), + UsageType.New => () => repository.NewAsync(new ViewContext(collection.Alias, parent), variant.Type)!, - _ => default(Func>) - }; + _ => default(Func>) + }; - if (action == default) - { - throw new InvalidOperationException($"UsageType {request.UsageType} is invalid for this method"); - } + if (action == default) + { + throw new InvalidOperationException($"UsageType {request.UsageType} is invalid for this method"); + } - var entity = await _concurrencyService.EnsureCorrectConcurrencyAsync(action); - if (entity == null) - { - throw new Exception("Failed to get entity for given id(s)"); - } + var entity = await _concurrencyService.EnsureCorrectConcurrencyAsync(action); + if (entity == null) + { + throw new Exception("Failed to get entity for given id(s)"); + } - await _authService.EnsureAuthorizedUserAsync(request.UsageType, entity); + await _authService.EnsureAuthorizedUserAsync(request.UsageType, entity); - return new FormEditContext(request.CollectionAlias, collection.RepositoryAlias, variant.Alias, entity, parent, request.UsageType | UsageType.Node, collection.Validators, _serviceProvider); - } + return new FormEditContext(request.CollectionAlias, collection.RepositoryAlias, variant.Alias, entity, parent, request.UsageType | UsageType.Node, collection.Validators, _serviceProvider); } } diff --git a/src/RapidCMS.Core/Dispatchers/Form/GetEntityOfPageDispatcher.cs b/src/RapidCMS.Core/Dispatchers/Form/GetEntityOfPageDispatcher.cs index 53d5f4ca..e2f8b8e0 100644 --- a/src/RapidCMS.Core/Dispatchers/Form/GetEntityOfPageDispatcher.cs +++ b/src/RapidCMS.Core/Dispatchers/Form/GetEntityOfPageDispatcher.cs @@ -8,49 +8,48 @@ using RapidCMS.Core.Models.Data; using RapidCMS.Core.Models.Request.Form; -namespace RapidCMS.Core.Dispatchers.Form +namespace RapidCMS.Core.Dispatchers.Form; + +internal class GetEntityOfPageDispatcher : IPresentationDispatcher { - internal class GetEntityOfPageDispatcher : IPresentationDispatcher + private readonly IRepositoryResolver _repositoryResolver; + private readonly IParentService _parentService; + private readonly IConcurrencyService _concurrencyService; + private readonly IAuthService _authService; + + public GetEntityOfPageDispatcher( + IRepositoryResolver repositoryResolver, + IParentService parentService, + IConcurrencyService concurrencyService, + IAuthService authService) { - private readonly IRepositoryResolver _repositoryResolver; - private readonly IParentService _parentService; - private readonly IConcurrencyService _concurrencyService; - private readonly IAuthService _authService; - - public GetEntityOfPageDispatcher( - IRepositoryResolver repositoryResolver, - IParentService parentService, - IConcurrencyService concurrencyService, - IAuthService authService) - { - _repositoryResolver = repositoryResolver; - _parentService = parentService; - _concurrencyService = concurrencyService; - _authService = authService; - } + _repositoryResolver = repositoryResolver; + _parentService = parentService; + _concurrencyService = concurrencyService; + _authService = authService; + } - public async Task GetAsync(GetEntityOfPageRequestModel request) - { - var (newParentPath, repositoryAlias, id) = ParentPath.RemoveLevel(request.ParentPath); + public async Task GetAsync(GetEntityOfPageRequestModel request) + { + var (newParentPath, repositoryAlias, id) = ParentPath.RemoveLevel(request.ParentPath); - if (repositoryAlias == null || id == null) - { - return new PageContext(request.PageAlias, null, null); - } + if (repositoryAlias == null || id == null) + { + return new PageContext(request.PageAlias, null, null); + } - var repository = _repositoryResolver.GetRepository(repositoryAlias); + var repository = _repositoryResolver.GetRepository(repositoryAlias); - var parent = await _parentService.GetParentAsync(newParentPath); + var parent = await _parentService.GetParentAsync(newParentPath); - var entity = await _concurrencyService.EnsureCorrectConcurrencyAsync(() => repository.GetByIdAsync(id, new ViewContext(request.PageAlias, parent))); - if (entity == null) - { - throw new Exception("Failed to get entity for given id(s)"); - } + var entity = await _concurrencyService.EnsureCorrectConcurrencyAsync(() => repository.GetByIdAsync(id, new ViewContext(request.PageAlias, parent))); + if (entity == null) + { + throw new Exception("Failed to get entity for given id(s)"); + } - await _authService.EnsureAuthorizedUserAsync(UsageType.View, entity); + await _authService.EnsureAuthorizedUserAsync(UsageType.View, entity); - return new PageContext(request.PageAlias, entity, parent); - } + return new PageContext(request.PageAlias, entity, parent); } } diff --git a/src/RapidCMS.Core/Dispatchers/GetPageDispatcher.cs b/src/RapidCMS.Core/Dispatchers/GetPageDispatcher.cs index 9986b47e..d8ae62de 100644 --- a/src/RapidCMS.Core/Dispatchers/GetPageDispatcher.cs +++ b/src/RapidCMS.Core/Dispatchers/GetPageDispatcher.cs @@ -10,79 +10,78 @@ using RapidCMS.Core.Models.Setup; using RapidCMS.Core.Navigation; -namespace RapidCMS.Core.Dispatchers +namespace RapidCMS.Core.Dispatchers; + +internal class GetPageDispatcher : IPresentationDispatcher> { - internal class GetPageDispatcher : IPresentationDispatcher> - { - private readonly ISetupResolver _collectionResolver; - private readonly IRepositoryResolver _repositoryResolver; - private readonly IAuthService _authService; - private readonly ILogin _loginRegistration; - private readonly ISetupResolver _pageResolver; - private readonly INavigationStateProvider _navigationStateProvider; + private readonly ISetupResolver _collectionResolver; + private readonly IRepositoryResolver _repositoryResolver; + private readonly IAuthService _authService; + private readonly ILogin _loginRegistration; + private readonly ISetupResolver _pageResolver; + private readonly INavigationStateProvider _navigationStateProvider; - public GetPageDispatcher( - ISetupResolver collectionResolver, - IRepositoryResolver repositoryResolver, - IAuthService authService, - ILogin loginRegistration, - ISetupResolver pageResolver, - INavigationStateProvider navigationStateProvider) - { - _collectionResolver = collectionResolver; - _repositoryResolver = repositoryResolver; - _authService = authService; - _loginRegistration = loginRegistration; - _pageResolver = pageResolver; - _navigationStateProvider = navigationStateProvider; - } + public GetPageDispatcher( + ISetupResolver collectionResolver, + IRepositoryResolver repositoryResolver, + IAuthService authService, + ILogin loginRegistration, + ISetupResolver pageResolver, + INavigationStateProvider navigationStateProvider) + { + _collectionResolver = collectionResolver; + _repositoryResolver = repositoryResolver; + _authService = authService; + _loginRegistration = loginRegistration; + _pageResolver = pageResolver; + _navigationStateProvider = navigationStateProvider; + } - public async Task> GetAsync(string request) - { - var currentNavigationState = _navigationStateProvider.GetCurrentState(); + public async Task> GetAsync(string request) + { + var currentNavigationState = _navigationStateProvider.GetCurrentState(); - var configuredSections = (await _pageResolver.ResolveSetupAsync(request)).Sections; - var sections = new List(); - var isAuthorized = default(bool?); + var configuredSections = (await _pageResolver.ResolveSetupAsync(request)).Sections; + var sections = new List(); + var isAuthorized = default(bool?); - foreach (var section in configuredSections) + foreach (var section in configuredSections) + { + if (section.Type == typeof(ICollectionConfig) && + section.Parameters != null && + section.Parameters.TryGetValue("InitialState", out var obj) && + obj is NavigationState state) { - if (section.Type == typeof(ICollectionConfig) && - section.Parameters != null && - section.Parameters.TryGetValue("InitialState", out var obj) && - obj is NavigationState state) - { - _navigationStateProvider.NestNavigationState(currentNavigationState, state); + _navigationStateProvider.NestNavigationState(currentNavigationState, state); - var collection = await _collectionResolver.ResolveSetupAsync(state.CollectionAlias); - var repository = _repositoryResolver.GetRepository(collection); + var collection = await _collectionResolver.ResolveSetupAsync(state.CollectionAlias); + var repository = _repositoryResolver.GetRepository(collection); - var entity = await repository.NewAsync(new ViewContext(section.Alias, default), default); + var entity = await repository.NewAsync(new ViewContext(section.Alias, default), default); - if (await _authService.IsUserAuthorizedAsync(state.UsageType, entity)) - { - isAuthorized = true; - sections.Add(section); - } - else - { - isAuthorized ??= false; - } - } - else + if (await _authService.IsUserAuthorizedAsync(state.UsageType, entity)) { + isAuthorized = true; sections.Add(section); } + else + { + isAuthorized ??= false; + } } - - if (isAuthorized == false && - sections.Count == 0 && - (await _loginRegistration.CustomLandingPageRegistrationAsync()) is TypeRegistrationSetup landingPage) + else { - sections.Insert(0, landingPage); + sections.Add(section); } + } - return sections; + if (isAuthorized == false && + sections.Count == 0 && + (await _loginRegistration.CustomLandingPageRegistrationAsync()) is TypeRegistrationSetup landingPage) + { + sections.Insert(0, landingPage); } + + return sections; } } diff --git a/src/RapidCMS.Core/Enums/CollectionConvention.cs b/src/RapidCMS.Core/Enums/CollectionConvention.cs index 912c03cf..15724aaa 100644 --- a/src/RapidCMS.Core/Enums/CollectionConvention.cs +++ b/src/RapidCMS.Core/Enums/CollectionConvention.cs @@ -1,12 +1,11 @@ -namespace RapidCMS.Core.Enums +namespace RapidCMS.Core.Enums; + +public enum CollectionConvention { - public enum CollectionConvention - { - ListView = 1, - ListViewNodeView = 2, - ListViewNodeEditor = 3, - ListEditor = 4, - ListBlockEditor = 5, - ListEditorNodeEditor = 6 - } + ListView = 1, + ListViewNodeView = 2, + ListViewNodeEditor = 3, + ListEditor = 4, + ListBlockEditor = 5, + ListEditorNodeEditor = 6 } diff --git a/src/RapidCMS.Core/Enums/CollectionRootVisibility.cs b/src/RapidCMS.Core/Enums/CollectionRootVisibility.cs index 414f2123..6e7cf312 100644 --- a/src/RapidCMS.Core/Enums/CollectionRootVisibility.cs +++ b/src/RapidCMS.Core/Enums/CollectionRootVisibility.cs @@ -1,9 +1,8 @@  -namespace RapidCMS.Core.Enums +namespace RapidCMS.Core.Enums; + +public enum CollectionRootVisibility { - public enum CollectionRootVisibility - { - Visible, - Hidden - } + Visible, + Hidden } diff --git a/src/RapidCMS.Core/Enums/CrudType.cs b/src/RapidCMS.Core/Enums/CrudType.cs index 570e2d53..dfcc550f 100644 --- a/src/RapidCMS.Core/Enums/CrudType.cs +++ b/src/RapidCMS.Core/Enums/CrudType.cs @@ -1,29 +1,28 @@ -namespace RapidCMS.Core.Enums +namespace RapidCMS.Core.Enums; + +public enum CrudType { - public enum CrudType - { - // none - None = 0, + // none + None = 0, - // viewers - View = 1, - List = 1, - Create = 2, - Edit = 3, + // viewers + View = 1, + List = 1, + Create = 2, + Edit = 3, - // modifiers - Insert = 4, - Update = 5, - Delete = 6, + // modifiers + Insert = 4, + Update = 5, + Delete = 6, - // list action - Add = 100, - Remove = 101, - Pick = 102, + // list action + Add = 100, + Remove = 101, + Pick = 102, - // navigation actions - Return = 1000, - Refresh = 1001, - Up = 1002 - } + // navigation actions + Return = 1000, + Refresh = 1001, + Up = 1002 } diff --git a/src/RapidCMS.Core/Enums/DefaultButtonType.cs b/src/RapidCMS.Core/Enums/DefaultButtonType.cs index 1dbede9d..574b1968 100644 --- a/src/RapidCMS.Core/Enums/DefaultButtonType.cs +++ b/src/RapidCMS.Core/Enums/DefaultButtonType.cs @@ -1,68 +1,67 @@ using RapidCMS.Core.Attributes; -namespace RapidCMS.Core.Enums +namespace RapidCMS.Core.Enums; + +public enum DefaultButtonType { - public enum DefaultButtonType - { - // Insert new Entity - [DefaultIconLabel(icon: "Add", label: "New")] - [Actions(UsageType.List | UsageType.View, UsageType.List | UsageType.Edit)] - New = 1, + // Insert new Entity + [DefaultIconLabel(icon: "Add", label: "New")] + [Actions(UsageType.List | UsageType.View, UsageType.List | UsageType.Edit)] + New = 1, - [DefaultIconLabel(icon: "Save", label: "Insert")] - [Actions(UsageType.New)] - [ValidForm] - SaveNew, + [DefaultIconLabel(icon: "Save", label: "Insert")] + [Actions(UsageType.New)] + [ValidForm] + SaveNew, - [DefaultIconLabel(icon: "Save", label: "Update")] - [Actions(UsageType.Edit | UsageType.Node, UsageType.Edit | UsageType.List)] - [ValidForm] - SaveExisting, + [DefaultIconLabel(icon: "Save", label: "Update")] + [Actions(UsageType.Edit | UsageType.Node, UsageType.Edit | UsageType.List)] + [ValidForm] + SaveExisting, - [DefaultIconLabel(icon: "Delete", label: "Delete")] - [Actions(UsageType.Edit | UsageType.Node, UsageType.View | UsageType.Node)] - [Confirm] - Delete, + [DefaultIconLabel(icon: "Delete", label: "Delete")] + [Actions(UsageType.Edit | UsageType.Node, UsageType.View | UsageType.Node)] + [Confirm] + Delete, - [DefaultIconLabel(icon: "Edit", label: "Edit")] - [Actions(UsageType.List | UsageType.View, UsageType.List | UsageType.Add, UsageType.Node | UsageType.Edit, UsageType.Node | UsageType.View)] - Edit, + [DefaultIconLabel(icon: "Edit", label: "Edit")] + [Actions(UsageType.List | UsageType.View, UsageType.List | UsageType.Add, UsageType.Node | UsageType.Edit, UsageType.Node | UsageType.View)] + Edit, - [DefaultIconLabel(icon: "View", label: "View")] - [Actions(UsageType.List, UsageType.Node | UsageType.Edit, UsageType.Node | UsageType.View)] - View, + [DefaultIconLabel(icon: "View", label: "View")] + [Actions(UsageType.List, UsageType.Node | UsageType.Edit, UsageType.Node | UsageType.View)] + View, - // Add existing Entity - [DefaultIconLabel(icon: "Add", label: "Add")] - [Actions(UsageType.List | UsageType.Edit, UsageType.List | UsageType.View)] - Add, + // Add existing Entity + [DefaultIconLabel(icon: "Add", label: "Add")] + [Actions(UsageType.List | UsageType.Edit, UsageType.List | UsageType.View)] + Add, - // Remove existing Entity - [DefaultIconLabel(icon: "Remove", label: "Remove")] - [Actions(UsageType.Node | UsageType.Edit, UsageType.Node | UsageType.View)] - Remove, + // Remove existing Entity + [DefaultIconLabel(icon: "Remove", label: "Remove")] + [Actions(UsageType.Node | UsageType.Edit, UsageType.Node | UsageType.View)] + Remove, - // Pick existing Entity to Add - [DefaultIconLabel(icon: "Add", label: "Pick")] - [Actions(UsageType.Node | UsageType.Pick)] - Pick, + // Pick existing Entity to Add + [DefaultIconLabel(icon: "Add", label: "Pick")] + [Actions(UsageType.Node | UsageType.Pick)] + Pick, - // return from New - [DefaultIconLabel(icon: "Back", label: "Return")] - [Actions(UsageType.List | UsageType.Add, UsageType.List | UsageType.New, UsageType.List | UsageType.Pick)] - Return, + // return from New + [DefaultIconLabel(icon: "Back", label: "Return")] + [Actions(UsageType.List | UsageType.Add, UsageType.List | UsageType.New, UsageType.List | UsageType.Pick)] + Return, - // move up in tree - [DefaultIconLabel(icon: "Up", label: "Up")] - [Actions(UsageType.List | UsageType.NotRoot, UsageType.Node)] - Up, + // move up in tree + [DefaultIconLabel(icon: "Up", label: "Up")] + [Actions(UsageType.List | UsageType.NotRoot, UsageType.Node)] + Up, - [DefaultIconLabel(icon: "OpenPane", label: "[open pane]")] - [Actions(UsageType.Node, UsageType.List)] - OpenPane = 9990, + [DefaultIconLabel(icon: "OpenPane", label: "[open pane]")] + [Actions(UsageType.Node, UsageType.List)] + OpenPane = 9990, - [DefaultIconLabel(icon: "NavigateForward", label: "[navigate]")] - [Actions(UsageType.Node, UsageType.List)] - Navigate = 9991 - } + [DefaultIconLabel(icon: "NavigateForward", label: "[navigate]")] + [Actions(UsageType.Node, UsageType.List)] + Navigate = 9991 } diff --git a/src/RapidCMS.Core/Enums/DisplayType.cs b/src/RapidCMS.Core/Enums/DisplayType.cs index e5492170..a23f61df 100644 --- a/src/RapidCMS.Core/Enums/DisplayType.cs +++ b/src/RapidCMS.Core/Enums/DisplayType.cs @@ -1,12 +1,11 @@ -namespace RapidCMS.Core.Enums +namespace RapidCMS.Core.Enums; + +public enum DisplayType { - public enum DisplayType - { - None = -99, - Custom = -1, + None = -99, + Custom = -1, - Label = 0, - Pre, - Link - } + Label = 0, + Pre, + Link } diff --git a/src/RapidCMS.Core/Enums/EditorType.cs b/src/RapidCMS.Core/Enums/EditorType.cs index 181100ca..b84d7e6e 100644 --- a/src/RapidCMS.Core/Enums/EditorType.cs +++ b/src/RapidCMS.Core/Enums/EditorType.cs @@ -2,113 +2,112 @@ using System.Collections.Generic; using RapidCMS.Core.Attributes; -namespace RapidCMS.Core.Enums +namespace RapidCMS.Core.Enums; + +public enum EditorType { - public enum EditorType - { - None = -99, - Custom = -1, - - /// - /// A simple textbox accepting a string - /// - TextBox = 0, - - /// - /// A simple textarea accepting a string - /// - TextArea, - - /// - /// A disabled textbox accepting a string - /// - Readonly, - - /// - /// A simple textbox accepting a number (with or without decimals), limiting the input to numbers only - /// - [DefaultType(typeof(int), typeof(long), typeof(uint), typeof(ulong), typeof(int?), typeof(long?), typeof(uint?), typeof(ulong?))] - Numeric, - - /// - /// A simple checkbox accepting a boolean - /// - [DefaultType(typeof(bool), typeof(bool?))] - Checkbox, - - /// - /// A simple textbox accepting a date, limiting the input to dates only - /// - [DefaultType(typeof(DateTime))] - Date, - - /// - /// A dropdown accepting a string, requires a data provider to provide the options. - /// - /// NOTE: Consider using EntityPicker. That control has better UX but is somewhat bigger. - /// - /// NOTE: This control will reset its value when the DataCollection data changes and the selected item is not available anymore. - /// - [Relation(RelationType.One)] - Dropdown, - - /// - /// A list of options accepting a string, requires a data provider to provide the options. - /// - /// NOTE: Consider using EntityPicker. That control has better UX but is somewhat bigger. - /// - /// NOTE: This control will reset its value when the DataCollection data changes and the selected item is not available anymore. - /// - [Relation(RelationType.One)] - Select, - - /// - /// A list of options accepting an array of strings, requires a data provider to provide the options, returning the selected items via the RelationContainer in EditContext - /// - /// NOTE: Consider using EntitiesPicker. That control has better UX but is somewhat bigger. - /// - /// NOTE: This control will reset its value when the DataCollection data changes and any of the selected items are not available anymore. - /// - [Relation(RelationType.Many)] - MultiSelect, - - /// - /// A list editor accepting an array of strings - /// - [DefaultType(typeof(IEnumerable), typeof(ICollection), typeof(IList), typeof(List))] - ListEditor, - - /// - /// A picker with search and navigation features for selecting an entity - /// - /// NOTE: This control will not reset its value when the DataCollection data changes. - /// - [Relation(RelationType.One)] - EntityPicker, - - /// - /// A picker with search and navigation features for selecting multiple entities - /// - /// NOTE: This control will not reset its value when the DataCollection data changes. - /// - [Relation(RelationType.Many)] - EntitiesPicker, - - /// - /// An editor that will render simple editors for each of the properties of the model it edits. - /// - /// Only creates basic editors for properties (TextBox, TextArea, Numeric, Checkbox, Date), use [DisplayAttribute] for customizations. - /// - /// Model property must be annotated with [ValidateObject] to enable validation. - /// - ModelEditor, - - /// - /// An editor that will allow the user to select or deselect flags of an enum. The value will be saved as the composite value of the enum. - /// - /// Requires to have the EnumDataProvider DataCollection attached and the enum must be an Int32 enum. - /// - [Relation(RelationType.One)] - EnumFlagPicker - } + None = -99, + Custom = -1, + + /// + /// A simple textbox accepting a string + /// + TextBox = 0, + + /// + /// A simple textarea accepting a string + /// + TextArea, + + /// + /// A disabled textbox accepting a string + /// + Readonly, + + /// + /// A simple textbox accepting a number (with or without decimals), limiting the input to numbers only + /// + [DefaultType(typeof(int), typeof(long), typeof(uint), typeof(ulong), typeof(int?), typeof(long?), typeof(uint?), typeof(ulong?))] + Numeric, + + /// + /// A simple checkbox accepting a boolean + /// + [DefaultType(typeof(bool), typeof(bool?))] + Checkbox, + + /// + /// A simple textbox accepting a date, limiting the input to dates only + /// + [DefaultType(typeof(DateTime))] + Date, + + /// + /// A dropdown accepting a string, requires a data provider to provide the options. + /// + /// NOTE: Consider using EntityPicker. That control has better UX but is somewhat bigger. + /// + /// NOTE: This control will reset its value when the DataCollection data changes and the selected item is not available anymore. + /// + [Relation(RelationType.One)] + Dropdown, + + /// + /// A list of options accepting a string, requires a data provider to provide the options. + /// + /// NOTE: Consider using EntityPicker. That control has better UX but is somewhat bigger. + /// + /// NOTE: This control will reset its value when the DataCollection data changes and the selected item is not available anymore. + /// + [Relation(RelationType.One)] + Select, + + /// + /// A list of options accepting an array of strings, requires a data provider to provide the options, returning the selected items via the RelationContainer in EditContext + /// + /// NOTE: Consider using EntitiesPicker. That control has better UX but is somewhat bigger. + /// + /// NOTE: This control will reset its value when the DataCollection data changes and any of the selected items are not available anymore. + /// + [Relation(RelationType.Many)] + MultiSelect, + + /// + /// A list editor accepting an array of strings + /// + [DefaultType(typeof(IEnumerable), typeof(ICollection), typeof(IList), typeof(List))] + ListEditor, + + /// + /// A picker with search and navigation features for selecting an entity + /// + /// NOTE: This control will not reset its value when the DataCollection data changes. + /// + [Relation(RelationType.One)] + EntityPicker, + + /// + /// A picker with search and navigation features for selecting multiple entities + /// + /// NOTE: This control will not reset its value when the DataCollection data changes. + /// + [Relation(RelationType.Many)] + EntitiesPicker, + + /// + /// An editor that will render simple editors for each of the properties of the model it edits. + /// + /// Only creates basic editors for properties (TextBox, TextArea, Numeric, Checkbox, Date), use [DisplayAttribute] for customizations. + /// + /// Model property must be annotated with [ValidateObject] to enable validation. + /// + ModelEditor, + + /// + /// An editor that will allow the user to select or deselect flags of an enum. The value will be saved as the composite value of the enum. + /// + /// Requires to have the EnumDataProvider DataCollection attached and the enum must be an Int32 enum. + /// + [Relation(RelationType.One)] + EnumFlagPicker } diff --git a/src/RapidCMS.Core/Enums/EmptyVariantColumnVisibility.cs b/src/RapidCMS.Core/Enums/EmptyVariantColumnVisibility.cs index 07f920f5..7bdc50d6 100644 --- a/src/RapidCMS.Core/Enums/EmptyVariantColumnVisibility.cs +++ b/src/RapidCMS.Core/Enums/EmptyVariantColumnVisibility.cs @@ -1,8 +1,7 @@ -namespace RapidCMS.Core.Enums +namespace RapidCMS.Core.Enums; + +public enum EmptyVariantColumnVisibility { - public enum EmptyVariantColumnVisibility - { - Collapse = 0, - Visible = 1 - } + Collapse = 0, + Visible = 1 } diff --git a/src/RapidCMS.Core/Enums/EntityState.cs b/src/RapidCMS.Core/Enums/EntityState.cs index 8a922a10..65fa3858 100644 --- a/src/RapidCMS.Core/Enums/EntityState.cs +++ b/src/RapidCMS.Core/Enums/EntityState.cs @@ -1,9 +1,8 @@  -namespace RapidCMS.Core.Enums +namespace RapidCMS.Core.Enums; + +public enum EntityState { - public enum EntityState - { - IsNew, - IsExisting - } + IsNew, + IsExisting } diff --git a/src/RapidCMS.Core/Enums/EntityVisibilty.cs b/src/RapidCMS.Core/Enums/EntityVisibilty.cs index 83075760..9e0d853e 100644 --- a/src/RapidCMS.Core/Enums/EntityVisibilty.cs +++ b/src/RapidCMS.Core/Enums/EntityVisibilty.cs @@ -1,9 +1,8 @@  -namespace RapidCMS.Core.Enums +namespace RapidCMS.Core.Enums; + +public enum EntityVisibilty { - public enum EntityVisibilty - { - Visible, - Hidden - } + Visible, + Hidden } diff --git a/src/RapidCMS.Core/Enums/Features.cs b/src/RapidCMS.Core/Enums/Features.cs index 010090c3..e78e7a87 100644 --- a/src/RapidCMS.Core/Enums/Features.cs +++ b/src/RapidCMS.Core/Enums/Features.cs @@ -1,15 +1,14 @@ using System; -namespace RapidCMS.Core.Enums +namespace RapidCMS.Core.Enums; + +[Flags] +public enum Features { - [Flags] - public enum Features - { - None = 0, - CanGoToView = 1, - CanGoToEdit = 2, - CanView = 4, - CanEdit = 8, - IsBlockList = 65536 - } + None = 0, + CanGoToView = 1, + CanGoToEdit = 2, + CanView = 4, + CanEdit = 8, + IsBlockList = 65536 } diff --git a/src/RapidCMS.Core/Enums/ListType.cs b/src/RapidCMS.Core/Enums/ListType.cs index 47159096..d866386a 100644 --- a/src/RapidCMS.Core/Enums/ListType.cs +++ b/src/RapidCMS.Core/Enums/ListType.cs @@ -1,8 +1,7 @@ -namespace RapidCMS.Core.Enums +namespace RapidCMS.Core.Enums; + +public enum ListType { - public enum ListType - { - Table = 0, - Block = 1 - } + Table = 0, + Block = 1 } diff --git a/src/RapidCMS.Core/Enums/MessageType.cs b/src/RapidCMS.Core/Enums/MessageType.cs index 2a2fb598..4b49b651 100644 --- a/src/RapidCMS.Core/Enums/MessageType.cs +++ b/src/RapidCMS.Core/Enums/MessageType.cs @@ -1,10 +1,9 @@ -namespace RapidCMS.Core.Enums +namespace RapidCMS.Core.Enums; + +public enum MessageType { - public enum MessageType - { - Information, - Success, - Warning, - Error - } + Information, + Success, + Warning, + Error } diff --git a/src/RapidCMS.Core/Enums/OrderByType.cs b/src/RapidCMS.Core/Enums/OrderByType.cs index cd0bab21..d24c2e77 100644 --- a/src/RapidCMS.Core/Enums/OrderByType.cs +++ b/src/RapidCMS.Core/Enums/OrderByType.cs @@ -1,10 +1,9 @@ -namespace RapidCMS.Core.Enums +namespace RapidCMS.Core.Enums; + +public enum OrderByType { - public enum OrderByType - { - Disabled = 0, - Ascending = 1, - Descending = 2, - None = 99 - } + Disabled = 0, + Ascending = 1, + Descending = 2, + None = 99 } diff --git a/src/RapidCMS.Core/Enums/PageType.cs b/src/RapidCMS.Core/Enums/PageType.cs index ca87fc65..5b30ae00 100644 --- a/src/RapidCMS.Core/Enums/PageType.cs +++ b/src/RapidCMS.Core/Enums/PageType.cs @@ -1,12 +1,11 @@ -namespace RapidCMS.Core.Enums +namespace RapidCMS.Core.Enums; + +public enum PageType { - public enum PageType - { - Node = 1, - Collection = 2, - Page = 3, - Dashboard = 4, - Error = 5, - Unauthorized = 6 - } + Node = 1, + Collection = 2, + Page = 3, + Dashboard = 4, + Error = 5, + Unauthorized = 6 } diff --git a/src/RapidCMS.Core/Enums/RelationType.cs b/src/RapidCMS.Core/Enums/RelationType.cs index 1afe8581..4e40d6a3 100644 --- a/src/RapidCMS.Core/Enums/RelationType.cs +++ b/src/RapidCMS.Core/Enums/RelationType.cs @@ -1,8 +1,7 @@ -namespace RapidCMS.Core.Enums +namespace RapidCMS.Core.Enums; + +public enum RelationType { - public enum RelationType - { - One, - Many - } + One, + Many } diff --git a/src/RapidCMS.Core/Enums/ReorderedState.cs b/src/RapidCMS.Core/Enums/ReorderedState.cs index 808a9dbe..51883d85 100644 --- a/src/RapidCMS.Core/Enums/ReorderedState.cs +++ b/src/RapidCMS.Core/Enums/ReorderedState.cs @@ -1,9 +1,8 @@  -namespace RapidCMS.Core.Enums +namespace RapidCMS.Core.Enums; + +public enum ReorderedState { - public enum ReorderedState - { - Unmodified, - Reordered - } + Unmodified, + Reordered } diff --git a/src/RapidCMS.Core/Enums/UsageType.cs b/src/RapidCMS.Core/Enums/UsageType.cs index 95a7bbf3..e65fa2a8 100644 --- a/src/RapidCMS.Core/Enums/UsageType.cs +++ b/src/RapidCMS.Core/Enums/UsageType.cs @@ -1,28 +1,27 @@ using System; -namespace RapidCMS.Core.Enums +namespace RapidCMS.Core.Enums; + +[Flags] +public enum UsageType { - [Flags] - public enum UsageType - { - None = 0, + None = 0, - View = 1, - New = 2, - Edit = 4, - Add = 8, - Pick = 16, - Reordered = 32, + View = 1, + New = 2, + Edit = 4, + Add = 8, + Pick = 16, + Reordered = 32, - List = 65536, - Node = 131072, - Details = 262144, + List = 65536, + Node = 131072, + Details = 262144, - // Root = root of page - Root = 2097152, - // NotRoot = embedded collection on a page - NotRoot = 4194304, + // Root = root of page + Root = 2097152, + // NotRoot = embedded collection on a page + NotRoot = 4194304, - ViewOrEdit = View | Edit - } + ViewOrEdit = View | Edit } diff --git a/src/RapidCMS.Core/Enums/ValidationState.cs b/src/RapidCMS.Core/Enums/ValidationState.cs index f67a7aaf..4deac37b 100644 --- a/src/RapidCMS.Core/Enums/ValidationState.cs +++ b/src/RapidCMS.Core/Enums/ValidationState.cs @@ -1,16 +1,15 @@ using System; -namespace RapidCMS.Core.Enums +namespace RapidCMS.Core.Enums; + +[Flags] +public enum ValidationState { - [Flags] - public enum ValidationState - { - None = 0, + None = 0, - NotValidated = 1, - Valid = 2, - Invalid = 4, + NotValidated = 1, + Valid = 2, + Invalid = 4, - Modified = 128 - } + Modified = 128 } diff --git a/src/RapidCMS.Core/EqualityComparers/FieldUIEqualityComparer.cs b/src/RapidCMS.Core/EqualityComparers/FieldUIEqualityComparer.cs index 978e3309..e4386802 100644 --- a/src/RapidCMS.Core/EqualityComparers/FieldUIEqualityComparer.cs +++ b/src/RapidCMS.Core/EqualityComparers/FieldUIEqualityComparer.cs @@ -1,18 +1,17 @@ using System.Collections.Generic; using RapidCMS.Core.Models.UI; -namespace RapidCMS.Core.EqualityComparers +namespace RapidCMS.Core.EqualityComparers; + +internal class FieldUIEqualityComparer : IEqualityComparer { - internal class FieldUIEqualityComparer : IEqualityComparer + public bool Equals(FieldUI? x, FieldUI? y) { - public bool Equals(FieldUI? x, FieldUI? y) - { - return x?.Name?.Equals(y?.Name) ?? false; - } + return x?.Name?.Equals(y?.Name) ?? false; + } - public int GetHashCode(FieldUI obj) - { - return obj.Name?.GetHashCode() ?? default; - } + public int GetHashCode(FieldUI obj) + { + return obj.Name?.GetHashCode() ?? default; } } diff --git a/src/RapidCMS.Core/Exceptions/InvalidEntityException.cs b/src/RapidCMS.Core/Exceptions/InvalidEntityException.cs index b96c30c4..a5cbab00 100644 --- a/src/RapidCMS.Core/Exceptions/InvalidEntityException.cs +++ b/src/RapidCMS.Core/Exceptions/InvalidEntityException.cs @@ -1,9 +1,8 @@ using System; -namespace RapidCMS.Core.Exceptions +namespace RapidCMS.Core.Exceptions; + +public class InvalidEntityException : Exception { - public class InvalidEntityException : Exception - { - } } diff --git a/src/RapidCMS.Core/Exceptions/InvalidExpressionException.cs b/src/RapidCMS.Core/Exceptions/InvalidExpressionException.cs index f8e51056..0c0bced3 100644 --- a/src/RapidCMS.Core/Exceptions/InvalidExpressionException.cs +++ b/src/RapidCMS.Core/Exceptions/InvalidExpressionException.cs @@ -1,11 +1,10 @@ using System; -namespace RapidCMS.Core.Exceptions +namespace RapidCMS.Core.Exceptions; + +public class InvalidExpressionException : Exception { - public class InvalidExpressionException : Exception + public InvalidExpressionException(string attribute) : base($"Cannot process expression in {attribute} to Func (StringGetter).") { - public InvalidExpressionException(string attribute) : base($"Cannot process expression in {attribute} to Func (StringGetter).") - { - } } } diff --git a/src/RapidCMS.Core/Exceptions/InvalidPropertyExpressionException.cs b/src/RapidCMS.Core/Exceptions/InvalidPropertyExpressionException.cs index c783d6a7..0d45255c 100644 --- a/src/RapidCMS.Core/Exceptions/InvalidPropertyExpressionException.cs +++ b/src/RapidCMS.Core/Exceptions/InvalidPropertyExpressionException.cs @@ -1,11 +1,10 @@ using System; -namespace RapidCMS.Core.Exceptions +namespace RapidCMS.Core.Exceptions; + +public class InvalidPropertyExpressionException : Exception { - public class InvalidPropertyExpressionException : Exception + public InvalidPropertyExpressionException(string attribute) : base($"Cannot process property expression in {attribute} to Func and Action (Getter and Setter).") { - public InvalidPropertyExpressionException(string attribute) : base($"Cannot process property expression in {attribute} to Func and Action (Getter and Setter).") - { - } } } diff --git a/src/RapidCMS.Core/Exceptions/NotFoundException.cs b/src/RapidCMS.Core/Exceptions/NotFoundException.cs index f2339737..81e8cfd4 100644 --- a/src/RapidCMS.Core/Exceptions/NotFoundException.cs +++ b/src/RapidCMS.Core/Exceptions/NotFoundException.cs @@ -1,11 +1,10 @@ using System; -namespace RapidCMS.Core.Exceptions +namespace RapidCMS.Core.Exceptions; + +public class NotFoundException : Exception { - public class NotFoundException : Exception + public NotFoundException(string message) : base(message) { - public NotFoundException(string message) : base(message) - { - } } } diff --git a/src/RapidCMS.Core/Exceptions/NotUniqueException.cs b/src/RapidCMS.Core/Exceptions/NotUniqueException.cs index 1158c5ff..181b0cd5 100644 --- a/src/RapidCMS.Core/Exceptions/NotUniqueException.cs +++ b/src/RapidCMS.Core/Exceptions/NotUniqueException.cs @@ -1,12 +1,11 @@ using System; -namespace RapidCMS.Core.Exceptions +namespace RapidCMS.Core.Exceptions; + +public class NotUniqueException : Exception { - public class NotUniqueException : Exception + public NotUniqueException(string attribute) : base($"Value of {attribute} is not globally unique in this context.") { - public NotUniqueException(string attribute) : base($"Value of {attribute} is not globally unique in this context.") - { - } } } diff --git a/src/RapidCMS.Core/Extensions/AsyncEnumerableExtensions.cs b/src/RapidCMS.Core/Extensions/AsyncEnumerableExtensions.cs index cb7728c9..cafbdcbc 100644 --- a/src/RapidCMS.Core/Extensions/AsyncEnumerableExtensions.cs +++ b/src/RapidCMS.Core/Extensions/AsyncEnumerableExtensions.cs @@ -2,56 +2,55 @@ using System.Collections.Generic; using System.Threading.Tasks; -namespace RapidCMS.Core.Extensions +namespace RapidCMS.Core.Extensions; + +public static class AsyncEnumerableExtensions { - public static class AsyncEnumerableExtensions + public static async IAsyncEnumerable WhereAsync(this IEnumerable source, Func> asyncPredicate) { - public static async IAsyncEnumerable WhereAsync(this IEnumerable source, Func> asyncPredicate) + foreach (var element in source) { - foreach (var element in source) + if (await asyncPredicate(element)) { - if (await asyncPredicate(element)) - { - yield return element; - } + yield return element; } } + } - public static async Task> ToListAsync(this IAsyncEnumerable source) - { - var result = new List(); - - await foreach (var element in source) - { - result.Add(element); - } + public static async Task> ToListAsync(this IAsyncEnumerable source) + { + var result = new List(); - return result; + await foreach (var element in source) + { + result.Add(element); } - public static async Task> ToListAsync(this IAsyncEnumerable source, Func selector) - { - var result = new List(); + return result; + } - await foreach (var element in source) - { - result.Add(selector(element)); - } + public static async Task> ToListAsync(this IAsyncEnumerable source, Func selector) + { + var result = new List(); - return result; + await foreach (var element in source) + { + result.Add(selector(element)); } - public static async Task> ToDictionaryAsync(this IEnumerable source, Func keySelector, Func> asyncValueSelector) - where TKey: notnull - { - var result = new Dictionary(); + return result; + } - foreach (var element in source) - { - result.Add(keySelector(element), await asyncValueSelector(element)); - } + public static async Task> ToDictionaryAsync(this IEnumerable source, Func keySelector, Func> asyncValueSelector) + where TKey: notnull + { + var result = new Dictionary(); - return result; + foreach (var element in source) + { + result.Add(keySelector(element), await asyncValueSelector(element)); } + + return result; } } diff --git a/src/RapidCMS.Core/Extensions/ButtonSetupExtensions.cs b/src/RapidCMS.Core/Extensions/ButtonSetupExtensions.cs index bff8bd25..9bad8c46 100644 --- a/src/RapidCMS.Core/Extensions/ButtonSetupExtensions.cs +++ b/src/RapidCMS.Core/Extensions/ButtonSetupExtensions.cs @@ -3,13 +3,12 @@ using RapidCMS.Core.Extensions; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Extensions +namespace RapidCMS.Core.Extensions; + +internal static class ButtonSetupExtensions { - internal static class ButtonSetupExtensions + public static IEnumerable GetAllButtons(this IEnumerable buttons) { - public static IEnumerable GetAllButtons(this IEnumerable buttons) - { - return buttons.SelectMany(x => x.Buttons.Any() ? x.Buttons.AsEnumerable() : new[] { x }).ToList(); - } + return buttons.SelectMany(x => x.Buttons.Any() ? x.Buttons.AsEnumerable() : new[] { x }).ToList(); } } diff --git a/src/RapidCMS.Core/Extensions/EnumExtensions.cs b/src/RapidCMS.Core/Extensions/EnumExtensions.cs index 1b02ee7e..c581774f 100644 --- a/src/RapidCMS.Core/Extensions/EnumExtensions.cs +++ b/src/RapidCMS.Core/Extensions/EnumExtensions.cs @@ -2,39 +2,38 @@ using System.Linq; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Extensions +namespace RapidCMS.Core.Extensions; + +internal static class EnumExtensions { - internal static class EnumExtensions + public static TAttribute? GetCustomAttribute(this Enum e) + where TAttribute : Attribute { - public static TAttribute? GetCustomAttribute(this Enum e) - where TAttribute : Attribute + var member = e.GetType().GetMember(e.ToString()).FirstOrDefault(); + + if (member != null) { - var member = e.GetType().GetMember(e.ToString()).FirstOrDefault(); + var attribute = member + .GetCustomAttributes(typeof(TAttribute), true) + ?.FirstOrDefault(); - if (member != null) - { - var attribute = member - .GetCustomAttributes(typeof(TAttribute), true) - ?.FirstOrDefault(); + return attribute as TAttribute; + } - return attribute as TAttribute; - } + return default; + } - return default; - } + public static UsageType FindSupportedUsageType(this UsageType supportsUsageType, UsageType requestedUsageType) + { + var supportedUsageType = (supportsUsageType & requestedUsageType) & UsageType.ViewOrEdit; - public static UsageType FindSupportedUsageType(this UsageType supportsUsageType, UsageType requestedUsageType) + if (supportedUsageType > 0) { - var supportedUsageType = (supportsUsageType & requestedUsageType) & UsageType.ViewOrEdit; - - if (supportedUsageType > 0) - { - return supportedUsageType; - } - else - { - return UsageType.View | (requestedUsageType & ~UsageType.ViewOrEdit); - } + return supportedUsageType; } + else + { + return UsageType.View | (requestedUsageType & ~UsageType.ViewOrEdit); + } } } diff --git a/src/RapidCMS.Core/Extensions/EnumerableExtensions.cs b/src/RapidCMS.Core/Extensions/EnumerableExtensions.cs index 6457d95c..df95c5c0 100644 --- a/src/RapidCMS.Core/Extensions/EnumerableExtensions.cs +++ b/src/RapidCMS.Core/Extensions/EnumerableExtensions.cs @@ -5,141 +5,140 @@ using System.Threading.Tasks; using RapidCMS.Core.Models.Config; -namespace RapidCMS.Core.Extensions +namespace RapidCMS.Core.Extensions; + +public static class EnumerableExtensions { - public static class EnumerableExtensions + public static List ToList(this IEnumerable source, Func selector) { - public static List ToList(this IEnumerable source, Func selector) - { - return source.Select(selector).ToList(); - } - - public static bool In(this TElement source, params TElement[] list) - { - return list?.Contains(source) ?? false; - } - - public static async Task> ToListAsync(this IEnumerable source, Func> asyncSelector) - { - var result = new List(); + return source.Select(selector).ToList(); + } - foreach (var element in source.Select(asyncSelector)) - { - result.Add(await element); - } + public static bool In(this TElement source, params TElement[] list) + { + return list?.Contains(source) ?? false; + } - return result; - } + public static async Task> ToListAsync(this IEnumerable source, Func> asyncSelector) + { + var result = new List(); - public static async Task> ToListAsync(this IEnumerable> source) + foreach (var element in source.Select(asyncSelector)) { - var result = new List(); + result.Add(await element); + } - foreach (var element in source) - { - result.Add(await element); - } + return result; + } - return result; - } + public static async Task> ToListAsync(this IEnumerable> source) + { + var result = new List(); - public static void ForEach(this IEnumerable source, Action action) + foreach (var element in source) { - foreach (var element in source) - { - action.Invoke(element); - } + result.Add(await element); } - public static IEnumerable GetCommonValues(this IDictionary> dictionary, IEqualityComparer equalityComparer) - where TKey : notnull - { - return dictionary.SelectMany(x => x.Value).Where(x => dictionary.Values.All(v => v.Contains(x, equalityComparer))).Distinct(equalityComparer); - } + return result; + } - public static IEnumerable SelectNotNull(this IEnumerable source, Func conditionalCast) - where TResult : class + public static void ForEach(this IEnumerable source, Action action) + { + foreach (var element in source) { - foreach (var element in source) - { - if (conditionalCast.Invoke(element) is TResult result) - { - yield return result; - } - } + action.Invoke(element); } + } - public static IEnumerable SelectManyNotNull(this IEnumerable source, Func?> predicate) - { - return source - .Select(x => predicate(x)) - .Where(x => x != null) - .SelectMany(x => x!) - .OfType(); - } + public static IEnumerable GetCommonValues(this IDictionary> dictionary, IEqualityComparer equalityComparer) + where TKey : notnull + { + return dictionary.SelectMany(x => x.Value).Where(x => dictionary.Values.All(v => v.Contains(x, equalityComparer))).Distinct(equalityComparer); + } - public static async IAsyncEnumerable SelectNotNullAsync(this IEnumerable source, Func> conditionalCast) - where TResult : class + public static IEnumerable SelectNotNull(this IEnumerable source, Func conditionalCast) + where TResult : class + { + foreach (var element in source) { - foreach (var element in source) + if (conditionalCast.Invoke(element) is TResult result) { - if (await conditionalCast.Invoke(element) is TResult result) - { - yield return result; - } + yield return result; } } + } - public static IEnumerable MergeAll(params IEnumerable?[] sources) - where T : class - { - return sources.Where(x => x != null).SelectMany(x => x!); - } + public static IEnumerable SelectManyNotNull(this IEnumerable source, Func?> predicate) + { + return source + .Select(x => predicate(x)) + .Where(x => x != null) + .SelectMany(x => x!) + .OfType(); + } - public static IEnumerable RecursiveSelect(this IEnumerable source, TSeed seed, Func walkFunction) + public static async IAsyncEnumerable SelectNotNullAsync(this IEnumerable source, Func> conditionalCast) + where TResult : class + { + foreach (var element in source) { - var previous = seed; - foreach (var element in source) + if (await conditionalCast.Invoke(element) is TResult result) { - var (newPrevious, result) = walkFunction.Invoke(element, previous); - previous = newPrevious; yield return result; } } + } - public static T? GetTypeFromList(this IEnumerable elements) - where T : class + public static IEnumerable MergeAll(params IEnumerable?[] sources) + where T : class + { + return sources.Where(x => x != null).SelectMany(x => x!); + } + + public static IEnumerable RecursiveSelect(this IEnumerable source, TSeed seed, Func walkFunction) + { + var previous = seed; + foreach (var element in source) { - return elements - .FirstOrDefault(x => x.GetType().GetInterfaces().Any(i => i == typeof(T))) as T; + var (newPrevious, result) = walkFunction.Invoke(element, previous); + previous = newPrevious; + yield return result; } + } + + public static T? GetTypeFromList(this IEnumerable elements) + where T : class + { + return elements + .FirstOrDefault(x => x.GetType().GetInterfaces().Any(i => i == typeof(T))) as T; + } - internal static IEnumerable GetRepositoryTypes(this IEnumerable panes) - => panes.SelectMany(x => x.Fields.Select(x => x.Relation).OfType().Select(x => x.RelatedRepositoryType)).OfType(); + internal static IEnumerable GetRepositoryTypes(this IEnumerable panes) + => panes.SelectMany(x => x.Fields.Select(x => x.Relation).OfType().Select(x => x.RelatedRepositoryType)).OfType(); - public static int? FindIndex(this IEnumerable source, Func predicate) - => source.Select((element, index) => new { element, index }).FirstOrDefault(x => predicate.Invoke(x.element))?.index; + public static int? FindIndex(this IEnumerable source, Func predicate) + => source.Select((element, index) => new { element, index }).FirstOrDefault(x => predicate.Invoke(x.element))?.index; - public class Group : IGrouping + public class Group : IGrouping + { + public Group(TKey key, List elements) { - public Group(TKey key, List elements) - { - Key = key; - Elements = elements ?? throw new ArgumentNullException(nameof(elements)); - } + Key = key; + Elements = elements ?? throw new ArgumentNullException(nameof(elements)); + } - public TKey Key { get; private set; } - public List Elements { get; set; } + public TKey Key { get; private set; } + public List Elements { get; set; } - public IEnumerator GetEnumerator() - { - return Elements.GetEnumerator(); - } + public IEnumerator GetEnumerator() + { + return Elements.GetEnumerator(); + } - IEnumerator IEnumerable.GetEnumerator() - { - return Elements.GetEnumerator(); - } + IEnumerator IEnumerable.GetEnumerator() + { + return Elements.GetEnumerator(); } } } diff --git a/src/RapidCMS.Core/Extensions/ObjectExtensions.cs b/src/RapidCMS.Core/Extensions/ObjectExtensions.cs index e91ceb53..dbf2ff90 100644 --- a/src/RapidCMS.Core/Extensions/ObjectExtensions.cs +++ b/src/RapidCMS.Core/Extensions/ObjectExtensions.cs @@ -1,14 +1,13 @@ using System; -namespace RapidCMS.Core.Extensions +namespace RapidCMS.Core.Extensions; + +public static class ObjectExtensions { - public static class ObjectExtensions + public static T If(this T subject, bool shouldDo, Func method) { - public static T If(this T subject, bool shouldDo, Func method) - { - return shouldDo - ? method.Invoke(subject) - : subject; - } + return shouldDo + ? method.Invoke(subject) + : subject; } } diff --git a/src/RapidCMS.Core/Extensions/ParentPathExtensions.cs b/src/RapidCMS.Core/Extensions/ParentPathExtensions.cs index 8ac9d7be..ff933ff9 100644 --- a/src/RapidCMS.Core/Extensions/ParentPathExtensions.cs +++ b/src/RapidCMS.Core/Extensions/ParentPathExtensions.cs @@ -1,41 +1,40 @@ using System.Linq; using RapidCMS.Core.Models.Data; -namespace RapidCMS.Core.Extensions +namespace RapidCMS.Core.Extensions; + +public static class ParentPathExtensions { - public static class ParentPathExtensions + public static bool IsBaseOf(this ParentPath? parentPath, ParentPath? parentPathToCompare, string repositoryAlias, string? id) { - public static bool IsBaseOf(this ParentPath? parentPath, ParentPath? parentPathToCompare, string repositoryAlias, string? id) + if (parentPathToCompare == null || parentPath?.Count >= parentPathToCompare.Count) { - if (parentPathToCompare == null || parentPath?.Count >= parentPathToCompare.Count) - { - return false; - } + return false; + } - if (parentPath == null) - { - var part = parentPathToCompare.ElementAtOrDefault(0); + if (parentPath == null) + { + var part = parentPathToCompare.ElementAtOrDefault(0); - return CompareWithPart(repositoryAlias, id, part); + return CompareWithPart(repositoryAlias, id, part); + } + else + { + if (parentPathToCompare.Take(parentPath.Count).Except(parentPath).Any()) + { + return false; } else { - if (parentPathToCompare.Take(parentPath.Count).Except(parentPath).Any()) - { - return false; - } - else - { - var part = parentPathToCompare.ElementAtOrDefault(parentPath.Count); + var part = parentPathToCompare.ElementAtOrDefault(parentPath.Count); - return CompareWithPart(repositoryAlias, id, part); - } - } + return CompareWithPart(repositoryAlias, id, part); + } } + } - private static bool CompareWithPart(string repositoryAlias, string? id, (string repositoryAlias, string id) part) - { - return id == null ? part.repositoryAlias == repositoryAlias : part == (repositoryAlias, id); - } + private static bool CompareWithPart(string repositoryAlias, string? id, (string repositoryAlias, string id) part) + { + return id == null ? part.repositoryAlias == repositoryAlias : part == (repositoryAlias, id); } } diff --git a/src/RapidCMS.Core/Extensions/PropertyMetadataExtensions.cs b/src/RapidCMS.Core/Extensions/PropertyMetadataExtensions.cs index f6d8123b..df9d7ea0 100644 --- a/src/RapidCMS.Core/Extensions/PropertyMetadataExtensions.cs +++ b/src/RapidCMS.Core/Extensions/PropertyMetadataExtensions.cs @@ -2,19 +2,18 @@ using System.Linq; using RapidCMS.Core.Abstractions.Metadata; -namespace RapidCMS.Core.Extensions +namespace RapidCMS.Core.Extensions; + +internal static class PropertyMetadataExtensions { - internal static class PropertyMetadataExtensions + public static IEnumerable GetAttributes(this IPropertyMetadata property) { - public static IEnumerable GetAttributes(this IPropertyMetadata property) - { - return property.ObjectType - .GetProperties() - .FirstOrDefault(x => x.Name == property.PropertyName) - ?.GetCustomAttributes(true) - .Where(x => x.GetType().IsSameTypeOrDerivedFrom(typeof(T))) - .Cast() - ?? Enumerable.Empty(); - } + return property.ObjectType + .GetProperties() + .FirstOrDefault(x => x.Name == property.PropertyName) + ?.GetCustomAttributes(true) + .Where(x => x.GetType().IsSameTypeOrDerivedFrom(typeof(T))) + .Cast() + ?? Enumerable.Empty(); } } diff --git a/src/RapidCMS.Core/Extensions/QueryableExtensions.cs b/src/RapidCMS.Core/Extensions/QueryableExtensions.cs index 4581dcf5..9e3fb462 100644 --- a/src/RapidCMS.Core/Extensions/QueryableExtensions.cs +++ b/src/RapidCMS.Core/Extensions/QueryableExtensions.cs @@ -2,46 +2,45 @@ using System.Linq; using System.Linq.Expressions; -namespace RapidCMS.Core.Extensions +namespace RapidCMS.Core.Extensions; + +public static class QueryableExtensions { - public static class QueryableExtensions + public static IQueryable WhereIfNotNull (this IQueryable queryable, Expression>? nullablePredicate) { - public static IQueryable WhereIfNotNull (this IQueryable queryable, Expression>? nullablePredicate) + if (nullablePredicate != null) + { + return queryable.Where(nullablePredicate); + } + else { - if (nullablePredicate != null) - { - return queryable.Where(nullablePredicate); - } - else - { - return queryable; - } + return queryable; } + } - public static IQueryable WhereIfNotNull(this IQueryable queryable, TNullable? nullable, Expression> predicate) - where TNullable : class + public static IQueryable WhereIfNotNull(this IQueryable queryable, TNullable? nullable, Expression> predicate) + where TNullable : class + { + if (nullable != null) { - if (nullable != null) - { - return queryable.Where(predicate); - } - else - { - return queryable; - } + return queryable.Where(predicate); } + else + { + return queryable; + } + } - public static IQueryable WhereIfNotNull(this IQueryable queryable, TValue? nullable, Expression> predicate) - where TValue : struct + public static IQueryable WhereIfNotNull(this IQueryable queryable, TValue? nullable, Expression> predicate) + where TValue : struct + { + if (nullable != null) + { + return queryable.Where(predicate); + } + else { - if (nullable != null) - { - return queryable.Where(predicate); - } - else - { - return queryable; - } + return queryable; } } } diff --git a/src/RapidCMS.Core/Extensions/ServiceProviderExtensions.cs b/src/RapidCMS.Core/Extensions/ServiceProviderExtensions.cs index 370b3164..6aed5abb 100644 --- a/src/RapidCMS.Core/Extensions/ServiceProviderExtensions.cs +++ b/src/RapidCMS.Core/Extensions/ServiceProviderExtensions.cs @@ -1,20 +1,19 @@ using System; -namespace RapidCMS.Core.Extensions +namespace RapidCMS.Core.Extensions; + +internal static class ServiceProviderExtensions { - internal static class ServiceProviderExtensions + public static T GetService(this IServiceProvider serviceProvider, Type type) + where T : class { - public static T GetService(this IServiceProvider serviceProvider, Type type) - where T : class - { - return (serviceProvider.GetService(type) ?? throw new InvalidOperationException($"Failed to resolve instance of type {type}")) - as T ?? throw new InvalidOperationException($"Resolved instance of type {type}, but failed to cast it as {typeof(T)}"); - } + return (serviceProvider.GetService(type) ?? throw new InvalidOperationException($"Failed to resolve instance of type {type}")) + as T ?? throw new InvalidOperationException($"Resolved instance of type {type}, but failed to cast it as {typeof(T)}"); + } - public static T GetService(this IServiceProvider serviceProvider) - where T : class - { - return serviceProvider.GetService(typeof(T)) as T ?? throw new InvalidOperationException($"Failed to resolve instance of type {typeof(T)}"); - } + public static T GetService(this IServiceProvider serviceProvider) + where T : class + { + return serviceProvider.GetService(typeof(T)) as T ?? throw new InvalidOperationException($"Failed to resolve instance of type {typeof(T)}"); } } diff --git a/src/RapidCMS.Core/Extensions/SetupResolverExtension.cs b/src/RapidCMS.Core/Extensions/SetupResolverExtension.cs index 52fe1e18..0f6cee40 100644 --- a/src/RapidCMS.Core/Extensions/SetupResolverExtension.cs +++ b/src/RapidCMS.Core/Extensions/SetupResolverExtension.cs @@ -3,23 +3,22 @@ using RapidCMS.Core.Abstractions.Resolvers; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Extensions +namespace RapidCMS.Core.Extensions; + +internal static class SetupResolverExtension { - internal static class SetupResolverExtension + public static async Task>> ResolveSetupAsync(this ISetupResolver resolver, IEnumerable configs, CollectionSetup? collection = default) + where TConfig : notnull { - public static async Task>> ResolveSetupAsync(this ISetupResolver resolver, IEnumerable configs, CollectionSetup? collection = default) - where TConfig : notnull - { - var allCachable = true; - return new ResolvedSetup>( - await configs.ToListAsync(async config => (await resolver.ResolveSetupAsync(config, collection)).CheckIfCachable(ref allCachable)), allCachable); - } + var allCachable = true; + return new ResolvedSetup>( + await configs.ToListAsync(async config => (await resolver.ResolveSetupAsync(config, collection)).CheckIfCachable(ref allCachable)), allCachable); + } - public static TSetup CheckIfCachable(this IResolvedSetup resolvedSetup, ref bool cachable) - { - cachable = cachable && resolvedSetup.Cachable; + public static TSetup CheckIfCachable(this IResolvedSetup resolvedSetup, ref bool cachable) + { + cachable = cachable && resolvedSetup.Cachable; - return resolvedSetup.Setup; - } + return resolvedSetup.Setup; } } diff --git a/src/RapidCMS.Core/Extensions/StringExtensions.cs b/src/RapidCMS.Core/Extensions/StringExtensions.cs index 08e70174..ff459578 100644 --- a/src/RapidCMS.Core/Extensions/StringExtensions.cs +++ b/src/RapidCMS.Core/Extensions/StringExtensions.cs @@ -4,205 +4,204 @@ using System.Text; using System.Diagnostics.CodeAnalysis; -namespace RapidCMS.Core.Extensions +namespace RapidCMS.Core.Extensions; + +public static class StringExtensions { - public static class StringExtensions + // https://stackoverflow.com/questions/25259/how-does-stack-overflow-generate-its-seo-friendly-urls + public static string ToUrlFriendlyString(this string title) { - // https://stackoverflow.com/questions/25259/how-does-stack-overflow-generate-its-seo-friendly-urls - public static string ToUrlFriendlyString(this string title) + if (title == null) { - if (title == null) - { - return ""; - } - - var len = title.Length; - var prevdash = false; - var sb = new StringBuilder(len); - char c; - - for (var i = 0; i < len; i++) - { - c = title[i]; - if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9')) - { - sb.Append(c); - prevdash = false; - } - else if (c >= 'A' && c <= 'Z') - { - // tricky way to convert to lowercase - sb.Append((char)(c | 32)); - prevdash = false; - } - else if (c == ' ' || c == ',' || c == '.' || c == '/' || - c == '\\' || c == '-' || c == '_' || c == '=') - { - if (!prevdash && sb.Length > 0) - { - sb.Append('-'); - prevdash = true; - } - } - else if (c >= 128) - { - var prevlen = sb.Length; - sb.Append(RemapInternationalCharToAscii(c)); - if (prevlen != sb.Length) - { - prevdash = false; - } - } - } - - return prevdash - ? sb.ToString().Substring(0, sb.Length - 1) - : sb.ToString(); + return ""; } - private static string RemapInternationalCharToAscii(char c) + var len = title.Length; + var prevdash = false; + var sb = new StringBuilder(len); + char c; + + for (var i = 0; i < len; i++) { - var s = c.ToString().ToLowerInvariant(); - if ("àåáâäãåą".Contains(s)) - { - return "a"; - } - else if ("èéêëę".Contains(s)) - { - return "e"; - } - else if ("ìíîïı".Contains(s)) - { - return "i"; - } - else if ("òóôõöøőð".Contains(s)) - { - return "o"; - } - else if ("ùúûüŭů".Contains(s)) - { - return "u"; - } - else if ("çćčĉ".Contains(s)) + c = title[i]; + if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9')) { - return "c"; + sb.Append(c); + prevdash = false; } - else if ("żźž".Contains(s)) + else if (c >= 'A' && c <= 'Z') { - return "z"; + // tricky way to convert to lowercase + sb.Append((char)(c | 32)); + prevdash = false; } - else if ("śşšŝ".Contains(s)) + else if (c == ' ' || c == ',' || c == '.' || c == '/' || + c == '\\' || c == '-' || c == '_' || c == '=') { - return "s"; - } - else if ("ñń".Contains(s)) - { - return "n"; - } - else if ("ýÿ".Contains(s)) - { - return "y"; - } - else if ("ğĝ".Contains(s)) - { - return "g"; - } - else if (c == 'ř') - { - return "r"; - } - else if (c == 'ł') - { - return "l"; - } - else if (c == 'đ') - { - return "d"; - } - else if (c == 'ß') - { - return "ss"; - } - else if (c == 'Þ') - { - return "th"; - } - else if (c == 'ĥ') - { - return "h"; - } - else if (c == 'ĵ') - { - return "j"; + if (!prevdash && sb.Length > 0) + { + sb.Append('-'); + prevdash = true; + } } - else + else if (c >= 128) { - return ""; + var prevlen = sb.Length; + sb.Append(RemapInternationalCharToAscii(c)); + if (prevlen != sb.Length) + { + prevdash = false; + } } } - private readonly static char[] Padding = { '=' }; + return prevdash + ? sb.ToString().Substring(0, sb.Length - 1) + : sb.ToString(); + } - internal static string ToSha256Base64String(this string text, string? salt = null) + private static string RemapInternationalCharToAscii(char c) + { + var s = c.ToString().ToLowerInvariant(); + if ("àåáâäãåą".Contains(s)) { - using var sha256 = SHA256.Create(); - var hashed = sha256.ComputeHash(Encoding.UTF8.GetBytes($"{text}{salt}")); - - return hashed.ToBase64String(); + return "a"; } - - public static string ToBase64String(this string text) + else if ("èéêëę".Contains(s)) { - return Convert.ToBase64String(Encoding.UTF8.GetBytes(text)) - .TrimEnd(Padding) - .Replace('+', '-') - .Replace('/', '_'); + return "e"; } - - private static string ToBase64String(this byte[] text) + else if ("ìíîïı".Contains(s)) { - return Convert.ToBase64String(text) - .TrimEnd(Padding) - .Replace('+', '-') - .Replace('/', '_'); + return "i"; } - - public static string FromBase64String(this string text) + else if ("òóôõöøőð".Contains(s)) + { + return "o"; + } + else if ("ùúûüŭů".Contains(s)) + { + return "u"; + } + else if ("çćčĉ".Contains(s)) + { + return "c"; + } + else if ("żźž".Contains(s)) + { + return "z"; + } + else if ("śşšŝ".Contains(s)) + { + return "s"; + } + else if ("ñń".Contains(s)) + { + return "n"; + } + else if ("ýÿ".Contains(s)) + { + return "y"; + } + else if ("ğĝ".Contains(s)) + { + return "g"; + } + else if (c == 'ř') + { + return "r"; + } + else if (c == 'ł') + { + return "l"; + } + else if (c == 'đ') + { + return "d"; + } + else if (c == 'ß') + { + return "ss"; + } + else if (c == 'Þ') + { + return "th"; + } + else if (c == 'ĥ') { - var preString = text?.Replace('-', '+').Replace('_', '/'); + return "h"; + } + else if (c == 'ĵ') + { + return "j"; + } + else + { + return ""; + } + } - if (string.IsNullOrWhiteSpace(preString)) - { - return string.Empty; - } + private readonly static char[] Padding = { '=' }; - var originalString = Encoding.UTF8.GetString( - Convert.FromBase64String($"{preString}{string.Join("", Enumerable.Repeat(Padding.First(), preString.Length % 4))}")); + internal static string ToSha256Base64String(this string text, string? salt = null) + { + using var sha256 = SHA256.Create(); + var hashed = sha256.ComputeHash(Encoding.UTF8.GetBytes($"{text}{salt}")); - return originalString; - } + return hashed.ToBase64String(); + } + + public static string ToBase64String(this string text) + { + return Convert.ToBase64String(Encoding.UTF8.GetBytes(text)) + .TrimEnd(Padding) + .Replace('+', '-') + .Replace('/', '_'); + } - - public static bool TryParseAsPluginAlias(this string? alias, [NotNullWhen(true)] out (string prefix, string collectionAlias) aliases) + private static string ToBase64String(this byte[] text) + { + return Convert.ToBase64String(text) + .TrimEnd(Padding) + .Replace('+', '-') + .Replace('/', '_'); + } + + public static string FromBase64String(this string text) + { + var preString = text?.Replace('-', '+').Replace('_', '/'); + + if (string.IsNullOrWhiteSpace(preString)) { - if (!string.IsNullOrWhiteSpace(alias) && - alias.Contains("::") && - alias.Split("::") is string[] parts) - { - aliases = (parts[0], alias); - return true; - } + return string.Empty; + } + + var originalString = Encoding.UTF8.GetString( + Convert.FromBase64String($"{preString}{string.Join("", Enumerable.Repeat(Padding.First(), preString.Length % 4))}")); + + return originalString; + } - aliases = (default!, default!); - return false; + + public static bool TryParseAsPluginAlias(this string? alias, [NotNullWhen(true)] out (string prefix, string collectionAlias) aliases) + { + if (!string.IsNullOrWhiteSpace(alias) && + alias.Contains("::") && + alias.Split("::") is string[] parts) + { + aliases = (parts[0], alias); + return true; } - public static string Truncate(this string? input, int maxLength) - => input switch { - _ when maxLength - 2 <= 0 => "", - string shortInput when shortInput.Length < maxLength => shortInput, - string longInput when longInput.Length > maxLength - 2 => $"{longInput.Substring(0, maxLength - 2)}..", - _ => "" - }; + aliases = (default!, default!); + return false; } + + public static string Truncate(this string? input, int maxLength) + => input switch { + _ when maxLength - 2 <= 0 => "", + string shortInput when shortInput.Length < maxLength => shortInput, + string longInput when longInput.Length > maxLength - 2 => $"{longInput.Substring(0, maxLength - 2)}..", + _ => "" + }; } diff --git a/src/RapidCMS.Core/Extensions/TypeExtensions.cs b/src/RapidCMS.Core/Extensions/TypeExtensions.cs index 61af4107..e502a476 100644 --- a/src/RapidCMS.Core/Extensions/TypeExtensions.cs +++ b/src/RapidCMS.Core/Extensions/TypeExtensions.cs @@ -2,34 +2,33 @@ using System.Collections.Generic; using System.Linq; -namespace RapidCMS.Core.Extensions +namespace RapidCMS.Core.Extensions; + +internal static class TypeExtensions { - internal static class TypeExtensions - { - public static bool IsSameTypeOrBaseTypeOf(this Type typeToTest, Type sameTypeOrSubClass) - => typeToTest == sameTypeOrSubClass || sameTypeOrSubClass.IsSubclassOf(typeToTest); - - public static bool IsSameTypeOrDerivedFrom(this Type typeToTest, Type sameTypeOrSuperClass) - => typeToTest == sameTypeOrSuperClass || typeToTest.IsSubclassOf(sameTypeOrSuperClass); - - public static bool HasInterface(this Type typeToTest, Type @interface) - => typeToTest.GetInterfaces().Any(x => x == @interface); - - public static bool HasGenericInterface(this Type typeToTest, Type @interface) - => @interface.IsGenericType && - @interface.IsGenericTypeDefinition && - typeToTest.GetInterfaces().Where(x => x.IsGenericType).Any(x => x.GetGenericTypeDefinition() == @interface); - - public static IEnumerable GetImplementingTypes(this Type typeToFindDerivativesOf) - => AppDomain.CurrentDomain.GetAssemblies() - .SelectMany(x => x.GetTypes()) - .Where(x => typeToFindDerivativesOf.IsAssignableFrom(x) && x.IsClass); - - public static TAttribute? GetCustomAttribute(this Type type) - where TAttribute : Attribute - => type.GetCustomAttributes(typeof(TAttribute), true)?.FirstOrDefault() as TAttribute; - - public static IEnumerable GetSubTypes(this Type type) - => type.Assembly.GetTypes().Where(t => !t.IsAbstract && t.IsSubclassOf(type)); - } + public static bool IsSameTypeOrBaseTypeOf(this Type typeToTest, Type sameTypeOrSubClass) + => typeToTest == sameTypeOrSubClass || sameTypeOrSubClass.IsSubclassOf(typeToTest); + + public static bool IsSameTypeOrDerivedFrom(this Type typeToTest, Type sameTypeOrSuperClass) + => typeToTest == sameTypeOrSuperClass || typeToTest.IsSubclassOf(sameTypeOrSuperClass); + + public static bool HasInterface(this Type typeToTest, Type @interface) + => typeToTest.GetInterfaces().Any(x => x == @interface); + + public static bool HasGenericInterface(this Type typeToTest, Type @interface) + => @interface.IsGenericType && + @interface.IsGenericTypeDefinition && + typeToTest.GetInterfaces().Where(x => x.IsGenericType).Any(x => x.GetGenericTypeDefinition() == @interface); + + public static IEnumerable GetImplementingTypes(this Type typeToFindDerivativesOf) + => AppDomain.CurrentDomain.GetAssemblies() + .SelectMany(x => x.GetTypes()) + .Where(x => typeToFindDerivativesOf.IsAssignableFrom(x) && x.IsClass); + + public static TAttribute? GetCustomAttribute(this Type type) + where TAttribute : Attribute + => type.GetCustomAttributes(typeof(TAttribute), true)?.FirstOrDefault() as TAttribute; + + public static IEnumerable GetSubTypes(this Type type) + => type.Assembly.GetTypes().Where(t => !t.IsAbstract && t.IsSubclassOf(type)); } diff --git a/src/RapidCMS.Core/Factories/ApiEditContextWrapperFactory.cs b/src/RapidCMS.Core/Factories/ApiEditContextWrapperFactory.cs index 28b9cec2..8b974c64 100644 --- a/src/RapidCMS.Core/Factories/ApiEditContextWrapperFactory.cs +++ b/src/RapidCMS.Core/Factories/ApiEditContextWrapperFactory.cs @@ -13,69 +13,68 @@ using RapidCMS.Core.Models.Data; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Factories +namespace RapidCMS.Core.Factories; + +internal class ApiEditContextWrapperFactory : IEditContextFactory { - internal class ApiEditContextWrapperFactory : IEditContextFactory - { - private readonly IServiceProvider _serviceProvider; - private readonly ISetupResolver _entityVariantResolver; - private readonly ISetupResolver> _validationResolver; + private readonly IServiceProvider _serviceProvider; + private readonly ISetupResolver _entityVariantResolver; + private readonly ISetupResolver> _validationResolver; - public ApiEditContextWrapperFactory( - IServiceProvider serviceProvider, - ISetupResolver entityVariantResolver, - ISetupResolver> validationResolver) - { - _serviceProvider = serviceProvider; - _entityVariantResolver = entityVariantResolver; - _validationResolver = validationResolver; - } + public ApiEditContextWrapperFactory( + IServiceProvider serviceProvider, + ISetupResolver entityVariantResolver, + ISetupResolver> validationResolver) + { + _serviceProvider = serviceProvider; + _entityVariantResolver = entityVariantResolver; + _validationResolver = validationResolver; + } - public Task GetEditContextWrapperAsync(FormEditContext editContext) - { - var contextType = typeof(FormEditContextWrapper<>).MakeGenericType(editContext.Entity.GetType()); - var instance = Activator.CreateInstance(contextType, editContext); + public Task GetEditContextWrapperAsync(FormEditContext editContext) + { + var contextType = typeof(FormEditContextWrapper<>).MakeGenericType(editContext.Entity.GetType()); + var instance = Activator.CreateInstance(contextType, editContext); - return Task.FromResult(instance as IEditContext - ?? throw new InvalidOperationException("Cannot create FormEditContextWrapper")); - } + return Task.FromResult(instance as IEditContext + ?? throw new InvalidOperationException("Cannot create FormEditContextWrapper")); + } - public async Task GetEditContextWrapperAsync( - UsageType usageType, - EntityState entityState, - Type repositoryEntityType, - IEntity updatedEntity, - IEntity referenceEntity, - IParent? parent, - IEnumerable<(string propertyName, string typeName, IEnumerable elements)> relations) + public async Task GetEditContextWrapperAsync( + UsageType usageType, + EntityState entityState, + Type repositoryEntityType, + IEntity updatedEntity, + IEntity referenceEntity, + IParent? parent, + IEnumerable<(string propertyName, string typeName, IEnumerable elements)> relations) + { + var container = new RelationContainer(await relations.SelectNotNullAsync(async r => { - var container = new RelationContainer(await relations.SelectNotNullAsync(async r => + var variant = await _entityVariantResolver.ResolveSetupAsync(r.typeName); + var property = PropertyMetadataHelper.GetPropertyMetadata(updatedEntity.GetType(), r.propertyName); + if (property == null) { - var variant = await _entityVariantResolver.ResolveSetupAsync(r.typeName); - var property = PropertyMetadataHelper.GetPropertyMetadata(updatedEntity.GetType(), r.propertyName); - if (property == null) - { - return null; - } + return null; + } - return new Relation(variant.Type, property, r.elements.ToList()); - }).ToListAsync()); + return new Relation(variant.Type, property, r.elements.ToList()); + }).ToListAsync()); - var entityVariantAlias = AliasHelper.GetEntityVariantAlias(updatedEntity.GetType()); - var validations = await _validationResolver.ResolveSetupAsync(entityVariantAlias); + var entityVariantAlias = AliasHelper.GetEntityVariantAlias(updatedEntity.GetType()); + var validations = await _validationResolver.ResolveSetupAsync(entityVariantAlias); - var contextType = typeof(ApiEditContextWrapper<>).MakeGenericType(repositoryEntityType); - var instance = Activator.CreateInstance(contextType, - usageType, - entityState, - updatedEntity, - referenceEntity, - parent, - container, - validations, - _serviceProvider); + var contextType = typeof(ApiEditContextWrapper<>).MakeGenericType(repositoryEntityType); + var instance = Activator.CreateInstance(contextType, + usageType, + entityState, + updatedEntity, + referenceEntity, + parent, + container, + validations, + _serviceProvider); - return instance as IEditContext ?? throw new InvalidOperationException("Cannot create ApiEditContextWrapper"); - } + return instance as IEditContext ?? throw new InvalidOperationException("Cannot create ApiEditContextWrapper"); } } diff --git a/src/RapidCMS.Core/Factories/FormEditContextWrapperFactory.cs b/src/RapidCMS.Core/Factories/FormEditContextWrapperFactory.cs index 74671ad8..43e052df 100644 --- a/src/RapidCMS.Core/Factories/FormEditContextWrapperFactory.cs +++ b/src/RapidCMS.Core/Factories/FormEditContextWrapperFactory.cs @@ -9,37 +9,36 @@ using RapidCMS.Core.Forms; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Factories +namespace RapidCMS.Core.Factories; + +internal class FormEditContextWrapperFactory : IEditContextFactory { - internal class FormEditContextWrapperFactory : IEditContextFactory - { - private readonly ISetupResolver _collectionResolver; + private readonly ISetupResolver _collectionResolver; - public FormEditContextWrapperFactory(ISetupResolver collectionResolver) - { - _collectionResolver = collectionResolver; - } + public FormEditContextWrapperFactory(ISetupResolver collectionResolver) + { + _collectionResolver = collectionResolver; + } - public async Task GetEditContextWrapperAsync(FormEditContext editContext) - { - var collection = await _collectionResolver.ResolveSetupAsync(editContext.CollectionAlias); + public async Task GetEditContextWrapperAsync(FormEditContext editContext) + { + var collection = await _collectionResolver.ResolveSetupAsync(editContext.CollectionAlias); - var contextType = typeof(FormEditContextWrapper<>).MakeGenericType(collection.EntityVariant.Type); - var instance = Activator.CreateInstance(contextType, editContext); + var contextType = typeof(FormEditContextWrapper<>).MakeGenericType(collection.EntityVariant.Type); + var instance = Activator.CreateInstance(contextType, editContext); - return instance as IEditContext ?? throw new InvalidOperationException("Cannot create FormEditContextWrapper"); - } + return instance as IEditContext ?? throw new InvalidOperationException("Cannot create FormEditContextWrapper"); + } - public Task GetEditContextWrapperAsync( - UsageType usageType, - EntityState entityState, - Type repositoryEntityType, - IEntity updatedEntity, - IEntity referenceEntity, - IParent? parent, - IEnumerable<(string propertyName, string typeName, IEnumerable elements)> relations) - { - throw new NotImplementedException(); - } + public Task GetEditContextWrapperAsync( + UsageType usageType, + EntityState entityState, + Type repositoryEntityType, + IEntity updatedEntity, + IEntity referenceEntity, + IParent? parent, + IEnumerable<(string propertyName, string typeName, IEnumerable elements)> relations) + { + throw new NotImplementedException(); } } diff --git a/src/RapidCMS.Core/Factories/UIResolverFactory.cs b/src/RapidCMS.Core/Factories/UIResolverFactory.cs index 17f7b5a4..1d62284b 100644 --- a/src/RapidCMS.Core/Factories/UIResolverFactory.cs +++ b/src/RapidCMS.Core/Factories/UIResolverFactory.cs @@ -9,75 +9,74 @@ using RapidCMS.Core.Navigation; using RapidCMS.Core.Resolvers.UI; -namespace RapidCMS.Core.Factories +namespace RapidCMS.Core.Factories; + +internal class UIResolverFactory : IUIResolverFactory { - internal class UIResolverFactory : IUIResolverFactory + private readonly ISetupResolver _collectionResolver; + private readonly IDataProviderResolver _dataProviderResolver; + private readonly IButtonActionHandlerResolver _buttonActionHandlerResolver; + private readonly IDataViewResolver _dataViewResolver; + private readonly IAuthService _authService; + private readonly IConventionBasedResolver _conventionBasedNodeSetupResolver; + private readonly INavigationStateProvider _navigationStateProvider; + + public UIResolverFactory( + ISetupResolver collectionResolver, + IDataProviderResolver dataProviderResolver, + IButtonActionHandlerResolver buttonActionHandlerResolver, + IDataViewResolver dataViewResolver, + IAuthService authService, + IConventionBasedResolver conventionBasedNodeSetupResolver, + INavigationStateProvider navigationStateProvider) { - private readonly ISetupResolver _collectionResolver; - private readonly IDataProviderResolver _dataProviderResolver; - private readonly IButtonActionHandlerResolver _buttonActionHandlerResolver; - private readonly IDataViewResolver _dataViewResolver; - private readonly IAuthService _authService; - private readonly IConventionBasedResolver _conventionBasedNodeSetupResolver; - private readonly INavigationStateProvider _navigationStateProvider; + _collectionResolver = collectionResolver; + _dataProviderResolver = dataProviderResolver; + _buttonActionHandlerResolver = buttonActionHandlerResolver; + _dataViewResolver = dataViewResolver; + _authService = authService; + _conventionBasedNodeSetupResolver = conventionBasedNodeSetupResolver; + _navigationStateProvider = navigationStateProvider; + } - public UIResolverFactory( - ISetupResolver collectionResolver, - IDataProviderResolver dataProviderResolver, - IButtonActionHandlerResolver buttonActionHandlerResolver, - IDataViewResolver dataViewResolver, - IAuthService authService, - IConventionBasedResolver conventionBasedNodeSetupResolver, - INavigationStateProvider navigationStateProvider) + public async Task GetNodeUIResolverAsync(NavigationState navigationState) + { + var collection = await _collectionResolver.ResolveSetupAsync(navigationState.CollectionAlias); + var node = navigationState.UsageType.HasFlag(UsageType.View) + ? collection.NodeView ?? collection.NodeEditor + : collection.NodeEditor ?? collection.NodeView; + if (node == null) { - _collectionResolver = collectionResolver; - _dataProviderResolver = dataProviderResolver; - _buttonActionHandlerResolver = buttonActionHandlerResolver; - _dataViewResolver = dataViewResolver; - _authService = authService; - _conventionBasedNodeSetupResolver = conventionBasedNodeSetupResolver; - _navigationStateProvider = navigationStateProvider; + throw new InvalidOperationException($"Failed to get UI configuration from collection {navigationState.CollectionAlias} for action {navigationState.UsageType}"); } - public async Task GetNodeUIResolverAsync(NavigationState navigationState) - { - var collection = await _collectionResolver.ResolveSetupAsync(navigationState.CollectionAlias); - var node = navigationState.UsageType.HasFlag(UsageType.View) - ? collection.NodeView ?? collection.NodeEditor - : collection.NodeEditor ?? collection.NodeView; - if (node == null) - { - throw new InvalidOperationException($"Failed to get UI configuration from collection {navigationState.CollectionAlias} for action {navigationState.UsageType}"); - } - - INodeUIResolver nodeUI = new NodeUIResolver(node, _dataProviderResolver, _buttonActionHandlerResolver, _navigationStateProvider, _authService); + INodeUIResolver nodeUI = new NodeUIResolver(node, _dataProviderResolver, _buttonActionHandlerResolver, _navigationStateProvider, _authService); - return nodeUI; - } + return nodeUI; + } - public async Task GetListUIResolverAsync(NavigationState navigationState) + public async Task GetListUIResolverAsync(NavigationState navigationState) + { + var collection = await _collectionResolver.ResolveSetupAsync(navigationState.CollectionAlias); + var list = navigationState.UsageType == UsageType.List + ? collection.ListView ?? collection.ListEditor + : collection.ListEditor ?? collection.ListView; + if (list == null) { - var collection = await _collectionResolver.ResolveSetupAsync(navigationState.CollectionAlias); - var list = navigationState.UsageType == UsageType.List - ? collection.ListView ?? collection.ListEditor - : collection.ListEditor ?? collection.ListView; - if (list == null) - { - throw new InvalidOperationException($"Failed to get UI configuration from collection {navigationState.CollectionAlias} for action {navigationState.UsageType}"); - } + throw new InvalidOperationException($"Failed to get UI configuration from collection {navigationState.CollectionAlias} for action {navigationState.UsageType}"); + } - IListUIResolver listUI = new ListUIResolver(list, _dataProviderResolver, _dataViewResolver, _buttonActionHandlerResolver, _navigationStateProvider, _authService); + IListUIResolver listUI = new ListUIResolver(list, _dataProviderResolver, _dataViewResolver, _buttonActionHandlerResolver, _navigationStateProvider, _authService); - return listUI; - } + return listUI; + } - public async Task GetConventionNodeUIResolverAsync(Type model) - { - var node = await _conventionBasedNodeSetupResolver.ResolveByConventionAsync(model, Features.CanEdit, new CollectionSetup(default, default, "Ad-Hoc", "adhoc", "adhoc")); + public async Task GetConventionNodeUIResolverAsync(Type model) + { + var node = await _conventionBasedNodeSetupResolver.ResolveByConventionAsync(model, Features.CanEdit, new CollectionSetup(default, default, "Ad-Hoc", "adhoc", "adhoc")); - INodeUIResolver nodeUI = new NodeUIResolver(node, _dataProviderResolver, _buttonActionHandlerResolver, _navigationStateProvider, _authService); + INodeUIResolver nodeUI = new NodeUIResolver(node, _dataProviderResolver, _buttonActionHandlerResolver, _navigationStateProvider, _authService); - return nodeUI; - } + return nodeUI; } } diff --git a/src/RapidCMS.Core/Forms/ApiEditContextWrapper.cs b/src/RapidCMS.Core/Forms/ApiEditContextWrapper.cs index 5d3de8b2..57033196 100644 --- a/src/RapidCMS.Core/Forms/ApiEditContextWrapper.cs +++ b/src/RapidCMS.Core/Forms/ApiEditContextWrapper.cs @@ -11,111 +11,110 @@ using RapidCMS.Core.Helpers; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Forms +namespace RapidCMS.Core.Forms; + +public class ApiEditContextWrapper : IEditContext + where TEntity : class, IEntity { - public class ApiEditContextWrapper : IEditContext - where TEntity : class, IEntity + private readonly FormState _formState; + private readonly IRelationContainer _relationContainer; + + public ApiEditContextWrapper( + UsageType usageType, + EntityState entityState, + TEntity entity, + TEntity referenceEntity, + IParent? parent, + IRelationContainer relationContainer, + IReadOnlyList validators, + IServiceProvider serviceProvider) { - private readonly FormState _formState; - private readonly IRelationContainer _relationContainer; - - public ApiEditContextWrapper( - UsageType usageType, - EntityState entityState, - TEntity entity, - TEntity referenceEntity, - IParent? parent, - IRelationContainer relationContainer, - IReadOnlyList validators, - IServiceProvider serviceProvider) - { - UsageType = usageType; - EntityState = entityState; - Entity = entity; - Parent = parent; - _relationContainer = relationContainer; - _formState = new FormState(entity, validators, serviceProvider); - _formState.PopulatePropertyStatesUsingReferenceEntity(referenceEntity); - } + UsageType = usageType; + EntityState = entityState; + Entity = entity; + Parent = parent; + _relationContainer = relationContainer; + _formState = new FormState(entity, validators, serviceProvider); + _formState.PopulatePropertyStatesUsingReferenceEntity(referenceEntity); + } - public UsageType UsageType { get; } - public EntityState EntityState { get; } - public TEntity Entity { get; } - public IParent? Parent { get; } - public string CollectionAlias => throw new NotSupportedException("The collection alias is unknown in API contexts"); + public UsageType UsageType { get; } + public EntityState EntityState { get; } + public TEntity Entity { get; } + public IParent? Parent { get; } + public string CollectionAlias => throw new NotSupportedException("The collection alias is unknown in API contexts"); - public ModelStateDictionary ValidationErrors => _formState.ModelState; + public ModelStateDictionary ValidationErrors => _formState.ModelState; - public IRelationContainer GetRelationContainer() => _relationContainer; + public IRelationContainer GetRelationContainer() => _relationContainer; - public bool? IsModified(Expression> property) - => GetPropertyState(GetMetadata(property))?.IsModified; + public bool? IsModified(Expression> property) + => GetPropertyState(GetMetadata(property))?.IsModified; - public bool? IsModified(string propertyName) - => GetPropertyState(propertyName)?.IsModified; + public bool? IsModified(string propertyName) + => GetPropertyState(propertyName)?.IsModified; - public async Task IsValidAsync() - { - await _formState.ValidateModelAsync(_relationContainer); + public async Task IsValidAsync() + { + await _formState.ValidateModelAsync(_relationContainer); - return !_formState.GetValidationMessages().Any(); - } + return !_formState.GetValidationMessages().Any(); + } - public bool? IsValid(Expression> property) - => GetPropertyState(GetMetadata(property))?.GetValidationMessages().Any(); + public bool? IsValid(Expression> property) + => GetPropertyState(GetMetadata(property))?.GetValidationMessages().Any(); - public bool? IsValid(string propertyName) - => GetPropertyState(propertyName)?.GetValidationMessages().Any(); + public bool? IsValid(string propertyName) + => GetPropertyState(propertyName)?.GetValidationMessages().Any(); - public bool? WasValidated(Expression> property) - => GetPropertyState(GetMetadata(property))?.WasValidated; + public bool? WasValidated(Expression> property) + => GetPropertyState(GetMetadata(property))?.WasValidated; - public bool? WasValidated(string propertyName) - => GetPropertyState(propertyName)?.WasValidated; + public bool? WasValidated(string propertyName) + => GetPropertyState(propertyName)?.WasValidated; - public void AddValidationError(Expression> property, string message) - => GetPropertyState(GetMetadata(property))?.AddMessage(message); + public void AddValidationError(Expression> property, string message) + => GetPropertyState(GetMetadata(property))?.AddMessage(message); - public void AddValidationError(string propertyName, string message) - => GetPropertyState(propertyName)?.AddMessage(message); + public void AddValidationError(string propertyName, string message) + => GetPropertyState(propertyName)?.AddMessage(message); - public async Task ValidateAsync(Expression> property) - { - var metadata = GetMetadata(property); + public async Task ValidateAsync(Expression> property) + { + var metadata = GetMetadata(property); - // force add property to the formState - _formState.GetPropertyState(metadata, createWhenNotFound: true); + // force add property to the formState + _formState.GetPropertyState(metadata, createWhenNotFound: true); - await _formState.ValidatePropertyAsync(metadata, _relationContainer); + await _formState.ValidatePropertyAsync(metadata, _relationContainer); - return _formState.GetPropertyState(metadata)?.GetValidationMessages().Any() - ?? throw new InvalidOperationException("Given expression could not be validated."); - } + return _formState.GetPropertyState(metadata)?.GetValidationMessages().Any() + ?? throw new InvalidOperationException("Given expression could not be validated."); + } - public async Task EnforceCompleteValidationAsync() - { - // add all properties to the form state - _formState.PopulateAllPropertyStates(); + public async Task EnforceCompleteValidationAsync() + { + // add all properties to the form state + _formState.PopulateAllPropertyStates(); - await EnforceValidEntityAsync(); - } + await EnforceValidEntityAsync(); + } - public async Task EnforceValidEntityAsync() + public async Task EnforceValidEntityAsync() + { + if (!await IsValidAsync()) { - if (!await IsValidAsync()) - { - throw new InvalidEntityException(); - } + throw new InvalidEntityException(); } + } - private PropertyState? GetPropertyState(IPropertyMetadata property) - => _formState.GetPropertyState(property, false); + private PropertyState? GetPropertyState(IPropertyMetadata property) + => _formState.GetPropertyState(property, false); - private PropertyState? GetPropertyState(string propertyName) - => _formState.GetPropertyState(propertyName); + private PropertyState? GetPropertyState(string propertyName) + => _formState.GetPropertyState(propertyName); - private IPropertyMetadata GetMetadata(Expression> property) - => PropertyMetadataHelper.GetPropertyMetadata(property) - ?? throw new InvalidOperationException("Given expression cannot be converted to PropertyMetadata"); - } + private IPropertyMetadata GetMetadata(Expression> property) + => PropertyMetadataHelper.GetPropertyMetadata(property) + ?? throw new InvalidOperationException("Given expression cannot be converted to PropertyMetadata"); } diff --git a/src/RapidCMS.Core/Forms/ButtonContext.cs b/src/RapidCMS.Core/Forms/ButtonContext.cs index 5648deba..d44bba4d 100644 --- a/src/RapidCMS.Core/Forms/ButtonContext.cs +++ b/src/RapidCMS.Core/Forms/ButtonContext.cs @@ -1,17 +1,16 @@ using System; using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Forms +namespace RapidCMS.Core.Forms; + +public sealed class ButtonContext { - public sealed class ButtonContext + public ButtonContext(IParent? parent, object? customData) { - public ButtonContext(IParent? parent, object? customData) - { - Parent = parent; - CustomData = customData; - } - - public IParent? Parent { get; set; } - public object? CustomData { get; set; } + Parent = parent; + CustomData = customData; } + + public IParent? Parent { get; set; } + public object? CustomData { get; set; } } diff --git a/src/RapidCMS.Core/Forms/FieldChangedEventArgs.cs b/src/RapidCMS.Core/Forms/FieldChangedEventArgs.cs index 05352c3c..24e6af2b 100644 --- a/src/RapidCMS.Core/Forms/FieldChangedEventArgs.cs +++ b/src/RapidCMS.Core/Forms/FieldChangedEventArgs.cs @@ -1,14 +1,13 @@ using RapidCMS.Core.Abstractions.Metadata; -namespace RapidCMS.Core.Forms +namespace RapidCMS.Core.Forms; + +public class FieldChangedEventArgs { - public class FieldChangedEventArgs + public FieldChangedEventArgs(IPropertyMetadata fullPropertyMetadata) { - public FieldChangedEventArgs(IPropertyMetadata fullPropertyMetadata) - { - FullPropertyMetadata = fullPropertyMetadata; - } - - public IPropertyMetadata FullPropertyMetadata { get; } + FullPropertyMetadata = fullPropertyMetadata; } + + public IPropertyMetadata FullPropertyMetadata { get; } } diff --git a/src/RapidCMS.Core/Forms/FormEditContext.cs b/src/RapidCMS.Core/Forms/FormEditContext.cs index 39ccdb4a..85c6c74f 100644 --- a/src/RapidCMS.Core/Forms/FormEditContext.cs +++ b/src/RapidCMS.Core/Forms/FormEditContext.cs @@ -11,188 +11,187 @@ using RapidCMS.Core.Models.Setup; using RapidCMS.Core.Providers; -namespace RapidCMS.Core.Forms +namespace RapidCMS.Core.Forms; + +public sealed class FormEditContext { - public sealed class FormEditContext + internal FormEditContext( + string collectionAlias, + string repositoryAlias, + string entityVariantAlias, + IEntity entity, + IParent? parent, + UsageType usageType, + IReadOnlyList validators, + IServiceProvider serviceProvider) { - internal FormEditContext( - string collectionAlias, - string repositoryAlias, - string entityVariantAlias, - IEntity entity, - IParent? parent, - UsageType usageType, - IReadOnlyList validators, - IServiceProvider serviceProvider) - { - CollectionAlias = collectionAlias ?? throw new ArgumentNullException(nameof(collectionAlias)); - RepositoryAlias = repositoryAlias ?? throw new ArgumentNullException(nameof(repositoryAlias)); - EntityVariantAlias = entityVariantAlias ?? throw new ArgumentNullException(nameof(entityVariantAlias)); - Entity = entity ?? throw new ArgumentNullException(nameof(entity)); - Parent = parent; - UsageType = usageType; - _validators = validators ?? throw new ArgumentNullException(nameof(validators)); - FormState = new FormState(Entity, validators, serviceProvider); - } + CollectionAlias = collectionAlias ?? throw new ArgumentNullException(nameof(collectionAlias)); + RepositoryAlias = repositoryAlias ?? throw new ArgumentNullException(nameof(repositoryAlias)); + EntityVariantAlias = entityVariantAlias ?? throw new ArgumentNullException(nameof(entityVariantAlias)); + Entity = entity ?? throw new ArgumentNullException(nameof(entity)); + Parent = parent; + UsageType = usageType; + _validators = validators ?? throw new ArgumentNullException(nameof(validators)); + FormState = new FormState(Entity, validators, serviceProvider); + } - private FormEditContext( - FormEditContext parentEditContext, - IPropertyMetadata property) : this( - parentEditContext.CollectionAlias, - parentEditContext.RepositoryAlias, - parentEditContext.EntityVariantAlias, - (IEntity)property.Getter(parentEditContext.Entity), - default, - UsageType.Edit | UsageType.Node, - parentEditContext._validators, - parentEditContext.FormState.ServiceProvider) - { - _parentEditContext = parentEditContext; - } + private FormEditContext( + FormEditContext parentEditContext, + IPropertyMetadata property) : this( + parentEditContext.CollectionAlias, + parentEditContext.RepositoryAlias, + parentEditContext.EntityVariantAlias, + (IEntity)property.Getter(parentEditContext.Entity), + default, + UsageType.Edit | UsageType.Node, + parentEditContext._validators, + parentEditContext.FormState.ServiceProvider) + { + _parentEditContext = parentEditContext; + } - internal FormEditContext( - FormEditContext protoEditContext, - IEntity entity, - UsageType usageType, - IServiceProvider serviceProvider) - { - CollectionAlias = protoEditContext.CollectionAlias; - RepositoryAlias = protoEditContext.RepositoryAlias; - EntityVariantAlias = protoEditContext.EntityVariantAlias; - Entity = entity ?? throw new ArgumentNullException(nameof(entity)); - Parent = protoEditContext.Parent; - UsageType = usageType; - _validators = protoEditContext._validators; - - FormState = new FormState(Entity, protoEditContext._validators, serviceProvider); - } + internal FormEditContext( + FormEditContext protoEditContext, + IEntity entity, + UsageType usageType, + IServiceProvider serviceProvider) + { + CollectionAlias = protoEditContext.CollectionAlias; + RepositoryAlias = protoEditContext.RepositoryAlias; + EntityVariantAlias = protoEditContext.EntityVariantAlias; + Entity = entity ?? throw new ArgumentNullException(nameof(entity)); + Parent = protoEditContext.Parent; + UsageType = usageType; + _validators = protoEditContext._validators; + + FormState = new FormState(Entity, protoEditContext._validators, serviceProvider); + } - internal readonly FormState FormState; - private readonly FormEditContext? _parentEditContext; - private readonly IReadOnlyList _validators; + internal readonly FormState FormState; + private readonly FormEditContext? _parentEditContext; + private readonly IReadOnlyList _validators; - public string CollectionAlias { get; private set; } - public string RepositoryAlias { get; private set; } - public string EntityVariantAlias { get; private set; } - public IEntity Entity { get; private set; } - public IParent? Parent { get; private set; } - public UsageType UsageType { get; private set; } + public string CollectionAlias { get; private set; } + public string RepositoryAlias { get; private set; } + public string EntityVariantAlias { get; private set; } + public IEntity Entity { get; private set; } + public IParent? Parent { get; private set; } + public UsageType UsageType { get; private set; } - public ReorderedState ReorderedState { get; private set; } - internal string? ReorderedBeforeId { get; private set; } - public EntityState EntityState => UsageType.HasFlag(UsageType.New) ? EntityState.IsNew : EntityState.IsExisting; + public ReorderedState ReorderedState { get; private set; } + internal string? ReorderedBeforeId { get; private set; } + public EntityState EntityState => UsageType.HasFlag(UsageType.New) ? EntityState.IsNew : EntityState.IsExisting; - internal List DataProviders { get; set; } = new List(); + internal List DataProviders { get; set; } = new List(); - public event EventHandler? OnFieldChanged; + public event EventHandler? OnFieldChanged; - public event EventHandler? OnValidationStateChanged; + public event EventHandler? OnValidationStateChanged; - public static implicit operator EditContext(FormEditContext editContext) - => new EditContext(editContext.Entity); + public static implicit operator EditContext(FormEditContext editContext) + => new EditContext(editContext.Entity); - public IRelationContainer GetRelationContainer() - => new RelationContainer(DataProviders.Select(x => x.GenerateRelation()).SelectNotNull(x => x)); + public IRelationContainer GetRelationContainer() + => new RelationContainer(DataProviders.Select(x => x.GenerateRelation()).SelectNotNull(x => x)); - public FormEditContext EntityProperty(IPropertyMetadata property) - => new FormEditContext(this, property); + public FormEditContext EntityProperty(IPropertyMetadata property) + => new FormEditContext(this, property); - public void NotifyReordered(string? beforeId) - { - ReorderedState = ReorderedState.Reordered; - ReorderedBeforeId = beforeId; - } + public void NotifyReordered(string? beforeId) + { + ReorderedState = ReorderedState.Reordered; + ReorderedBeforeId = beforeId; + } - public void NotifyPropertyIncludedInForm(IPropertyMetadata property) - => GetPropertyState(property); + public void NotifyPropertyIncludedInForm(IPropertyMetadata property) + => GetPropertyState(property); - public async Task NotifyPropertyChangedAsync(IPropertyMetadata property) - { - await ValidatePropertyAsync(property); + public async Task NotifyPropertyChangedAsync(IPropertyMetadata property) + { + await ValidatePropertyAsync(property); - GetPropertyState(property)!.IsModified = true; - OnFieldChanged?.Invoke(this, new FieldChangedEventArgs(property)); - } + GetPropertyState(property)!.IsModified = true; + OnFieldChanged?.Invoke(this, new FieldChangedEventArgs(property)); + } - public void NotifyPropertyBusy(IPropertyMetadata property) - { - GetPropertyState(property)!.IsBusy = true; - OnValidationStateChanged?.Invoke(this, new ValidationStateChangedEventArgs(false)); - } + public void NotifyPropertyBusy(IPropertyMetadata property) + { + GetPropertyState(property)!.IsBusy = true; + OnValidationStateChanged?.Invoke(this, new ValidationStateChangedEventArgs(false)); + } - public void NotifyPropertyFinished(IPropertyMetadata property) - { - GetPropertyState(property)!.IsBusy = false; - OnValidationStateChanged?.Invoke(this, new ValidationStateChangedEventArgs()); - } + public void NotifyPropertyFinished(IPropertyMetadata property) + { + GetPropertyState(property)!.IsBusy = false; + OnValidationStateChanged?.Invoke(this, new ValidationStateChangedEventArgs()); + } - public void NotifyValidationStateChanged() - { - OnValidationStateChanged?.Invoke(this, new ValidationStateChangedEventArgs(isValid: !FormState.GetValidationMessages().Any())); - } + public void NotifyValidationStateChanged() + { + OnValidationStateChanged?.Invoke(this, new ValidationStateChangedEventArgs(isValid: !FormState.GetValidationMessages().Any())); + } - public async Task IsValidAsync() - { - await ValidateModelAsync(); + public async Task IsValidAsync() + { + await ValidateModelAsync(); - return !FormState.GetValidationMessages().Any(); - } + return !FormState.GetValidationMessages().Any(); + } - public bool IsModified() - => FormState.GetPropertyStates().Any(x => x.IsModified); + public bool IsModified() + => FormState.GetPropertyStates().Any(x => x.IsModified); - public bool IsModified(IPropertyMetadata property) - => GetPropertyState(property)!.IsModified; + public bool IsModified(IPropertyMetadata property) + => GetPropertyState(property)!.IsModified; - public bool IsReordered() - => ReorderedState == ReorderedState.Reordered; + public bool IsReordered() + => ReorderedState == ReorderedState.Reordered; - public bool IsValid(IPropertyMetadata property) - => !GetPropertyState(property)!.GetValidationMessages().Any(); + public bool IsValid(IPropertyMetadata property) + => !GetPropertyState(property)!.GetValidationMessages().Any(); - public bool WasValidated(IPropertyMetadata property) - => GetPropertyState(property)!.WasValidated; + public bool WasValidated(IPropertyMetadata property) + => GetPropertyState(property)!.WasValidated; - public void AddValidationMessage(IPropertyMetadata property, string message) - { - GetPropertyState(property, true)!.AddMessage(message); - GetPropertyState(property, true)!.WasValidated = true; - } + public void AddValidationMessage(IPropertyMetadata property, string message) + { + GetPropertyState(property, true)!.AddMessage(message); + GetPropertyState(property, true)!.WasValidated = true; + } - public IEnumerable GetValidationMessages(IPropertyMetadata property) + public IEnumerable GetValidationMessages(IPropertyMetadata property) + { + var state = GetPropertyState(property, false); + if (state != null) { - var state = GetPropertyState(property, false); - if (state != null) + foreach (var message in state.GetValidationMessages()) { - foreach (var message in state.GetValidationMessages()) - { - yield return message; - } + yield return message; } } + } - public IEnumerable GetStrayValidationMessages() - => FormState.GetStrayValidationMessages(); + public IEnumerable GetStrayValidationMessages() + => FormState.GetStrayValidationMessages(); - internal PropertyState? GetPropertyState(IPropertyMetadata property, bool createWhenNotFound = true) - => FormState.GetPropertyState(property, createWhenNotFound); + internal PropertyState? GetPropertyState(IPropertyMetadata property, bool createWhenNotFound = true) + => FormState.GetPropertyState(property, createWhenNotFound); - internal PropertyState? GetPropertyState(string propertyName) - => FormState.GetPropertyState(propertyName); + internal PropertyState? GetPropertyState(string propertyName) + => FormState.GetPropertyState(propertyName); - private async Task ValidateModelAsync() - { - await FormState.ValidateModelAsync(GetRelationContainer()); + private async Task ValidateModelAsync() + { + await FormState.ValidateModelAsync(GetRelationContainer()); - NotifyValidationStateChanged(); - } + NotifyValidationStateChanged(); + } - private async Task ValidatePropertyAsync(IPropertyMetadata property) - { - await FormState.ValidatePropertyAsync(property, GetRelationContainer()); + private async Task ValidatePropertyAsync(IPropertyMetadata property) + { + await FormState.ValidatePropertyAsync(property, GetRelationContainer()); - NotifyValidationStateChanged(); - } + NotifyValidationStateChanged(); } } diff --git a/src/RapidCMS.Core/Forms/FormEditContextWrapper.cs b/src/RapidCMS.Core/Forms/FormEditContextWrapper.cs index fed9f68c..12d88cc7 100644 --- a/src/RapidCMS.Core/Forms/FormEditContextWrapper.cs +++ b/src/RapidCMS.Core/Forms/FormEditContextWrapper.cs @@ -10,95 +10,94 @@ using RapidCMS.Core.Extensions; using RapidCMS.Core.Helpers; -namespace RapidCMS.Core.Forms +namespace RapidCMS.Core.Forms; + +public class FormEditContextWrapper : IEditContext + where TEntity : IEntity { - public class FormEditContextWrapper : IEditContext - where TEntity : IEntity - { - private readonly FormEditContext _editContext; + private readonly FormEditContext _editContext; - public FormEditContextWrapper(FormEditContext editContext) - { - _editContext = editContext; - } + public FormEditContextWrapper(FormEditContext editContext) + { + _editContext = editContext; + } - public UsageType UsageType => _editContext.UsageType; + public UsageType UsageType => _editContext.UsageType; - public EntityState EntityState => _editContext.EntityState; + public EntityState EntityState => _editContext.EntityState; - public string CollectionAlias => _editContext.CollectionAlias; + public string CollectionAlias => _editContext.CollectionAlias; - public TEntity Entity => (TEntity)_editContext.Entity; + public TEntity Entity => (TEntity)_editContext.Entity; - public IParent? Parent => _editContext.Parent; + public IParent? Parent => _editContext.Parent; - public ModelStateDictionary ValidationErrors => _editContext.FormState.ModelState; + public ModelStateDictionary ValidationErrors => _editContext.FormState.ModelState; - public IRelationContainer GetRelationContainer() - => new RelationContainer(_editContext.DataProviders.Select(x => x.GenerateRelation()).SelectNotNull(x => x)); + public IRelationContainer GetRelationContainer() + => new RelationContainer(_editContext.DataProviders.Select(x => x.GenerateRelation()).SelectNotNull(x => x)); - public bool? IsModified(Expression> property) - => GetPropertyState(GetMetadata(property))?.IsModified; + public bool? IsModified(Expression> property) + => GetPropertyState(GetMetadata(property))?.IsModified; - public bool? IsModified(string propertyName) - => GetPropertyState(propertyName)?.IsModified; + public bool? IsModified(string propertyName) + => GetPropertyState(propertyName)?.IsModified; - public Task IsValidAsync() - => _editContext.IsValidAsync(); + public Task IsValidAsync() + => _editContext.IsValidAsync(); - public bool? IsValid(Expression> property) - => GetPropertyState(GetMetadata(property))?.GetValidationMessages().Any() == false; + public bool? IsValid(Expression> property) + => GetPropertyState(GetMetadata(property))?.GetValidationMessages().Any() == false; - public bool? IsValid(string propertyName) - => GetPropertyState(propertyName)?.GetValidationMessages().Any() == false; + public bool? IsValid(string propertyName) + => GetPropertyState(propertyName)?.GetValidationMessages().Any() == false; - public bool? WasValidated(Expression> property) - => GetPropertyState(GetMetadata(property))?.WasValidated; + public bool? WasValidated(Expression> property) + => GetPropertyState(GetMetadata(property))?.WasValidated; - public bool? WasValidated(string propertyName) - => GetPropertyState(propertyName)?.WasValidated; + public bool? WasValidated(string propertyName) + => GetPropertyState(propertyName)?.WasValidated; - public void AddValidationError(Expression> property, string message) - { - GetPropertyState(GetMetadata(property))?.AddMessage(message, isManual: true); - _editContext.NotifyValidationStateChanged(); - } + public void AddValidationError(Expression> property, string message) + { + GetPropertyState(GetMetadata(property))?.AddMessage(message, isManual: true); + _editContext.NotifyValidationStateChanged(); + } - public void AddValidationError(string propertyName, string message) - { - GetPropertyState(propertyName)?.AddMessage(message, isManual: true); - _editContext.NotifyValidationStateChanged(); - } + public void AddValidationError(string propertyName, string message) + { + GetPropertyState(propertyName)?.AddMessage(message, isManual: true); + _editContext.NotifyValidationStateChanged(); + } - public Task ValidateAsync(Expression> property) - { - // make sure it will be validated - _editContext.NotifyPropertyIncludedInForm(GetMetadata(property)); - return Task.FromResult(IsValid(property)); - } + public Task ValidateAsync(Expression> property) + { + // make sure it will be validated + _editContext.NotifyPropertyIncludedInForm(GetMetadata(property)); + return Task.FromResult(IsValid(property)); + } - public async Task EnforceCompleteValidationAsync() - { - // add all properties to the form state - _editContext.FormState.PopulateAllPropertyStates(); - await EnforceValidEntityAsync(); - } + public async Task EnforceCompleteValidationAsync() + { + // add all properties to the form state + _editContext.FormState.PopulateAllPropertyStates(); + await EnforceValidEntityAsync(); + } - public async Task EnforceValidEntityAsync() + public async Task EnforceValidEntityAsync() + { + if (!await IsValidAsync()) { - if (!await IsValidAsync()) - { - throw new InvalidEntityException(); - } + throw new InvalidEntityException(); } + } - private PropertyState? GetPropertyState(IPropertyMetadata property) - => _editContext.GetPropertyState(property, false); + private PropertyState? GetPropertyState(IPropertyMetadata property) + => _editContext.GetPropertyState(property, false); - private PropertyState? GetPropertyState(string propertyName) - => _editContext.GetPropertyState(propertyName); + private PropertyState? GetPropertyState(string propertyName) + => _editContext.GetPropertyState(propertyName); - private IPropertyMetadata GetMetadata(Expression> property) - => PropertyMetadataHelper.GetPropertyMetadata(property) ?? throw new InvalidOperationException("Given expression cannot be converted to PropertyMetadata"); - } + private IPropertyMetadata GetMetadata(Expression> property) + => PropertyMetadataHelper.GetPropertyMetadata(property) ?? throw new InvalidOperationException("Given expression cannot be converted to PropertyMetadata"); } diff --git a/src/RapidCMS.Core/Forms/FormState.cs b/src/RapidCMS.Core/Forms/FormState.cs index 99eb36d0..3c1aaa6e 100644 --- a/src/RapidCMS.Core/Forms/FormState.cs +++ b/src/RapidCMS.Core/Forms/FormState.cs @@ -13,204 +13,203 @@ using RapidCMS.Core.Models.Setup; using RapidCMS.Core.Validators; -namespace RapidCMS.Core.Forms +namespace RapidCMS.Core.Forms; + +internal class FormState { - internal class FormState - { - private readonly List _messages = new List(); - private readonly List _fieldStates = new List(); - private readonly IEntity _entity; - private readonly IReadOnlyList _validators; + private readonly List _messages = new List(); + private readonly List _fieldStates = new List(); + private readonly IEntity _entity; + private readonly IReadOnlyList _validators; - public FormState(IEntity entity, IReadOnlyList validators, IServiceProvider serviceProvider) - { - _entity = entity; - _validators = validators; - ServiceProvider = serviceProvider; - } + public FormState(IEntity entity, IReadOnlyList validators, IServiceProvider serviceProvider) + { + _entity = entity; + _validators = validators; + ServiceProvider = serviceProvider; + } - public IServiceProvider ServiceProvider { get; } + public IServiceProvider ServiceProvider { get; } - public IEnumerable GetValidationMessages() + public IEnumerable GetValidationMessages() + { + foreach (var message in _messages) { - foreach (var message in _messages) - { - yield return message; - } - foreach (var message in _fieldStates.SelectMany(x => x.GetValidationMessages())) - { - yield return message; - } + yield return message; } - - public IEnumerable GetStrayValidationMessages() + foreach (var message in _fieldStates.SelectMany(x => x.GetValidationMessages())) { - return _messages; + yield return message; } + } - public void AddMessage(string message) - { - _messages.Add(message); - } + public IEnumerable GetStrayValidationMessages() + { + return _messages; + } - public void ClearMessages() + public void AddMessage(string message) + { + _messages.Add(message); + } + + public void ClearMessages() + { + _messages.Clear(); + foreach (var fieldState in _fieldStates) { - _messages.Clear(); - foreach (var fieldState in _fieldStates) - { - fieldState.ClearMessages(); - } + fieldState.ClearMessages(); } + } - public ModelStateDictionary ModelState + public ModelStateDictionary ModelState + { + get { - get - { - var state = new ModelStateDictionary(); + var state = new ModelStateDictionary(); - _fieldStates.ForEach(fs => fs.GetValidationMessages().ForEach(message => state.Add(fs.Property.PropertyName, message))); - _messages.ForEach(m => state.Add(string.Empty, m)); + _fieldStates.ForEach(fs => fs.GetValidationMessages().ForEach(message => state.Add(fs.Property.PropertyName, message))); + _messages.ForEach(m => state.Add(string.Empty, m)); - return state; - } + return state; } + } - public void PopulatePropertyStatesUsingReferenceEntity(IEntity reference) + public void PopulatePropertyStatesUsingReferenceEntity(IEntity reference) + { + GetPropertyMetadatas(reference).ForEach(property => { - GetPropertyMetadatas(reference).ForEach(property => + if ((property.PropertyType.IsValueType || + property.PropertyType == typeof(string)) && + !Equals(property.Getter(reference), property.Getter(_entity))) { - if ((property.PropertyType.IsValueType || - property.PropertyType == typeof(string)) && - !Equals(property.Getter(reference), property.Getter(_entity))) - { - GetPropertyState(property)!.IsModified = true; - } - }); - } + GetPropertyState(property)!.IsModified = true; + } + }); + } + + public void PopulateAllPropertyStates() + { + GetPropertyMetadatas(_entity).ForEach(property => GetPropertyState(property, createWhenNotFound: true)); + } - public void PopulateAllPropertyStates() + private IEnumerable GetPropertyMetadatas(IEntity reference, IEnumerable? objectGetters = default) + { + Func getObject; + if (objectGetters == null) { - GetPropertyMetadatas(_entity).ForEach(property => GetPropertyState(property, createWhenNotFound: true)); + getObject = (root) => root; } - - private IEnumerable GetPropertyMetadatas(IEntity reference, IEnumerable? objectGetters = default) + else { - Func getObject; - if (objectGetters == null) - { - getObject = (root) => root; - } - else - { - getObject = (root) => objectGetters.Aggregate(root, (@obj, objectGetter) => objectGetter.GetValue(@obj)!); - } + getObject = (root) => objectGetters.Aggregate(root, (@obj, objectGetter) => objectGetter.GetValue(@obj)!); + } - var properties = getObject(reference).GetType().GetProperties(); + var properties = getObject(reference).GetType().GetProperties(); - foreach (var property in properties) + foreach (var property in properties) + { + var validateObjectAttribute = property.GetCustomAttribute(); + if (validateObjectAttribute != null) { - var validateObjectAttribute = property.GetCustomAttribute(); - if (validateObjectAttribute != null) - { - // only venture into nested objects when the model wants them validated - foreach (var nestedPropertyMetadata in GetPropertyMetadatas(reference, (objectGetters ?? new PropertyInfo[] { }).Union(new[] { property }))) - { - yield return nestedPropertyMetadata; - } - } - - var propertyMetadata = PropertyMetadataHelper.GetPropertyMetadata(reference.GetType(), objectGetters, property); - if (propertyMetadata == null) + // only venture into nested objects when the model wants them validated + foreach (var nestedPropertyMetadata in GetPropertyMetadatas(reference, (objectGetters ?? new PropertyInfo[] { }).Union(new[] { property }))) { - continue; + yield return nestedPropertyMetadata; } + } - yield return propertyMetadata; + var propertyMetadata = PropertyMetadataHelper.GetPropertyMetadata(reference.GetType(), objectGetters, property); + if (propertyMetadata == null) + { + continue; } - } - public IEnumerable GetPropertyStates() - { - return _fieldStates; + yield return propertyMetadata; } + } - public PropertyState? GetPropertyState(string propertyName) - { - return _fieldStates.SingleOrDefault(field => field.Property.PropertyName == propertyName); - } + public IEnumerable GetPropertyStates() + { + return _fieldStates; + } + + public PropertyState? GetPropertyState(string propertyName) + { + return _fieldStates.SingleOrDefault(field => field.Property.PropertyName == propertyName); + } - public PropertyState? GetPropertyState(IPropertyMetadata property, bool createWhenNotFound = true) + public PropertyState? GetPropertyState(IPropertyMetadata property, bool createWhenNotFound = true) + { + var fieldState = _fieldStates.SingleOrDefault(x => x.Property.Fingerprint == property.Fingerprint); + if (fieldState == null) { - var fieldState = _fieldStates.SingleOrDefault(x => x.Property.Fingerprint == property.Fingerprint); - if (fieldState == null) + if (!createWhenNotFound) { - if (!createWhenNotFound) - { - return default; - } - - fieldState = new PropertyState(property); - _fieldStates.Add(fieldState); + return default; } - return fieldState; + fieldState = new PropertyState(property); + _fieldStates.Add(fieldState); } - public async Task ValidateModelAsync(IRelationContainer relationContainer) - { - var results = await GetValidationResultsForModelAsync(relationContainer); + return fieldState; + } - foreach (var result in results) + public async Task ValidateModelAsync(IRelationContainer relationContainer) + { + var results = await GetValidationResultsForModelAsync(relationContainer); + + foreach (var result in results) + { + var strayError = true; + result.MemberNames.ForEach(name => { - var strayError = true; - result.MemberNames.ForEach(name => - { - GetPropertyState(name)?.AddMessage(result.ErrorMessage ?? "Unknown error"); - strayError = false; - }); + GetPropertyState(name)?.AddMessage(result.ErrorMessage ?? "Unknown error"); + strayError = false; + }); - if (strayError) - { - _messages.Add(result.ErrorMessage ?? "Unknown error"); - } + if (strayError) + { + _messages.Add(result.ErrorMessage ?? "Unknown error"); } - - _fieldStates.ForEach(x => x.WasValidated = true); } - public async Task ValidatePropertyAsync(IPropertyMetadata property, IRelationContainer relationContainer) - { - var results = await GetValidationResultsForPropertyAsync(property, relationContainer); + _fieldStates.ForEach(x => x.WasValidated = true); + } - var state = GetPropertyState(property)!; - state.ClearMessages(clearManualMessages: true); - state.WasValidated = true; + public async Task ValidatePropertyAsync(IPropertyMetadata property, IRelationContainer relationContainer) + { + var results = await GetValidationResultsForPropertyAsync(property, relationContainer); - foreach (var result in results) - { - state.AddMessage(result.ErrorMessage ?? "Unknown error"); - } - } + var state = GetPropertyState(property)!; + state.ClearMessages(clearManualMessages: true); + state.WasValidated = true; - private async Task> GetValidationResultsForPropertyAsync(IPropertyMetadata property, IRelationContainer relationContainer) + foreach (var result in results) { - var results = await EntityValidator.ValidateAsync(_validators, relationContainer, ServiceProvider, _entity, property.PropertyName).ToListAsync(); - return results; + state.AddMessage(result.ErrorMessage ?? "Unknown error"); } + } - private async Task> GetValidationResultsForModelAsync(IRelationContainer relationContainer) - { - var results = await EntityValidator.ValidateAsync(_validators, relationContainer, ServiceProvider, _entity).ToListAsync(); + private async Task> GetValidationResultsForPropertyAsync(IPropertyMetadata property, IRelationContainer relationContainer) + { + var results = await EntityValidator.ValidateAsync(_validators, relationContainer, ServiceProvider, _entity, property.PropertyName).ToListAsync(); + return results; + } - ClearMessages(); + private async Task> GetValidationResultsForModelAsync(IRelationContainer relationContainer) + { + var results = await EntityValidator.ValidateAsync(_validators, relationContainer, ServiceProvider, _entity).ToListAsync(); - _fieldStates - .Where(kv => kv.IsBusy) - .ForEach(kv => results.Add(new ValidationResult( - $"The {kv.Property.PropertyName} field indicates it is performing an asynchronous task which must be awaited.", - new[] { kv.Property.PropertyName }))); + ClearMessages(); - return results; - } + _fieldStates + .Where(kv => kv.IsBusy) + .ForEach(kv => results.Add(new ValidationResult( + $"The {kv.Property.PropertyName} field indicates it is performing an asynchronous task which must be awaited.", + new[] { kv.Property.PropertyName }))); + + return results; } } diff --git a/src/RapidCMS.Core/Forms/ListContext.cs b/src/RapidCMS.Core/Forms/ListContext.cs index 71377c98..f34b9739 100644 --- a/src/RapidCMS.Core/Forms/ListContext.cs +++ b/src/RapidCMS.Core/Forms/ListContext.cs @@ -3,26 +3,25 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Forms +namespace RapidCMS.Core.Forms; + +public sealed class ListContext { - public sealed class ListContext + public ListContext(string collectionAlias, FormEditContext protoEditContext, IParent? parent, UsageType usageType, List? editContexts, IServiceProvider serviceProvider) { - public ListContext(string collectionAlias, FormEditContext protoEditContext, IParent? parent, UsageType usageType, List? editContexts, IServiceProvider serviceProvider) - { - CollectionAlias = collectionAlias ?? throw new ArgumentNullException(nameof(collectionAlias)); - ProtoEditContext = protoEditContext ?? throw new ArgumentNullException(nameof(protoEditContext)); - Parent = parent; - UsageType = usageType; - EditContexts = editContexts ?? new List(); - ServiceProvider = serviceProvider; - } + CollectionAlias = collectionAlias ?? throw new ArgumentNullException(nameof(collectionAlias)); + ProtoEditContext = protoEditContext ?? throw new ArgumentNullException(nameof(protoEditContext)); + Parent = parent; + UsageType = usageType; + EditContexts = editContexts ?? new List(); + ServiceProvider = serviceProvider; + } - public string CollectionAlias { get; private set; } - public FormEditContext ProtoEditContext { get; private set; } - public IParent? Parent { get; private set; } - public UsageType UsageType { get; private set; } - public List EditContexts { get; private set; } + public string CollectionAlias { get; private set; } + public FormEditContext ProtoEditContext { get; private set; } + public IParent? Parent { get; private set; } + public UsageType UsageType { get; private set; } + public List EditContexts { get; private set; } - public IServiceProvider ServiceProvider { get; private set; } - } + public IServiceProvider ServiceProvider { get; private set; } } diff --git a/src/RapidCMS.Core/Forms/ModelStateDictionary.cs b/src/RapidCMS.Core/Forms/ModelStateDictionary.cs index d3a94ea0..bb75fa73 100644 --- a/src/RapidCMS.Core/Forms/ModelStateDictionary.cs +++ b/src/RapidCMS.Core/Forms/ModelStateDictionary.cs @@ -1,8 +1,7 @@ using System.Collections.Generic; -namespace RapidCMS.Core.Forms +namespace RapidCMS.Core.Forms; + +public class ModelStateDictionary : Dictionary { - public class ModelStateDictionary : Dictionary - { - } } diff --git a/src/RapidCMS.Core/Forms/PageContext.cs b/src/RapidCMS.Core/Forms/PageContext.cs index cad156f1..c7895a68 100644 --- a/src/RapidCMS.Core/Forms/PageContext.cs +++ b/src/RapidCMS.Core/Forms/PageContext.cs @@ -1,21 +1,20 @@ using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Forms +namespace RapidCMS.Core.Forms; + +public sealed class PageContext { - public sealed class PageContext + internal PageContext( + string pageAlias, + IEntity? entity, + IParent? parent) { - internal PageContext( - string pageAlias, - IEntity? entity, - IParent? parent) - { - PageAlias = pageAlias; - Entity = entity; - Parent = parent; - } - - public string PageAlias { get; private set; } - public IEntity? Entity { get; private set; } - public IParent? Parent { get; private set; } + PageAlias = pageAlias; + Entity = entity; + Parent = parent; } + + public string PageAlias { get; private set; } + public IEntity? Entity { get; private set; } + public IParent? Parent { get; private set; } } diff --git a/src/RapidCMS.Core/Forms/PropertyState.cs b/src/RapidCMS.Core/Forms/PropertyState.cs index 80fe5fe5..03ce12b3 100644 --- a/src/RapidCMS.Core/Forms/PropertyState.cs +++ b/src/RapidCMS.Core/Forms/PropertyState.cs @@ -2,57 +2,56 @@ using System.Collections.Generic; using RapidCMS.Core.Abstractions.Metadata; -namespace RapidCMS.Core.Forms +namespace RapidCMS.Core.Forms; + +internal class PropertyState { - internal class PropertyState - { - private readonly List _messages = new List(); - private readonly List _manualMessages = new List(); + private readonly List _messages = new List(); + private readonly List _manualMessages = new List(); - public PropertyState(IPropertyMetadata property) - { - Property = property ?? throw new ArgumentNullException(nameof(property)); - } + public PropertyState(IPropertyMetadata property) + { + Property = property ?? throw new ArgumentNullException(nameof(property)); + } - public bool WasValidated { get; set; } - public bool IsModified { get; set; } - public bool IsBusy { get; set; } + public bool WasValidated { get; set; } + public bool IsModified { get; set; } + public bool IsBusy { get; set; } - public IPropertyMetadata Property { get; } + public IPropertyMetadata Property { get; } - public IEnumerable GetValidationMessages() + public IEnumerable GetValidationMessages() + { + foreach (var message in _messages) { - foreach (var message in _messages) - { - yield return message; - } - foreach (var message in _manualMessages) - { - yield return message; - } + yield return message; } - - public void ClearMessages(bool clearManualMessages = false) + foreach (var message in _manualMessages) { - _messages.Clear(); - if (clearManualMessages) - { - _manualMessages.Clear(); - } + yield return message; } + } - public void AddMessage(string message, bool isManual = false) + public void ClearMessages(bool clearManualMessages = false) + { + _messages.Clear(); + if (clearManualMessages) + { + _manualMessages.Clear(); + } + } + + public void AddMessage(string message, bool isManual = false) + { + if (isManual) + { + _manualMessages.Add(message); + } + else { - if (isManual) - { - _manualMessages.Add(message); - } - else - { - _messages.Add(message); - } - - WasValidated = true; + _messages.Add(message); } + + WasValidated = true; } } diff --git a/src/RapidCMS.Core/Forms/RelatedViewContext.cs b/src/RapidCMS.Core/Forms/RelatedViewContext.cs index 11bb0d7d..031d486f 100644 --- a/src/RapidCMS.Core/Forms/RelatedViewContext.cs +++ b/src/RapidCMS.Core/Forms/RelatedViewContext.cs @@ -2,15 +2,14 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Abstractions.Forms; -namespace RapidCMS.Core.Forms +namespace RapidCMS.Core.Forms; + +internal class RelatedViewContext : ViewContext, IRelatedViewContext { - internal class RelatedViewContext : ViewContext, IRelatedViewContext + public RelatedViewContext(IRelated related, string? collectionAlias, IParent? parent) : base(collectionAlias, parent) { - public RelatedViewContext(IRelated related, string? collectionAlias, IParent? parent) : base(collectionAlias, parent) - { - Related = related ?? throw new ArgumentNullException(nameof(related)); - } - - public IRelated Related { get; } + Related = related ?? throw new ArgumentNullException(nameof(related)); } + + public IRelated Related { get; } } diff --git a/src/RapidCMS.Core/Forms/RelationContainer.cs b/src/RapidCMS.Core/Forms/RelationContainer.cs index 96f7a9ee..1e3f33b3 100644 --- a/src/RapidCMS.Core/Forms/RelationContainer.cs +++ b/src/RapidCMS.Core/Forms/RelationContainer.cs @@ -6,27 +6,26 @@ using RapidCMS.Core.Abstractions.Forms; using RapidCMS.Core.Helpers; -namespace RapidCMS.Core.Forms +namespace RapidCMS.Core.Forms; + +internal class RelationContainer : IRelationContainer { - internal class RelationContainer : IRelationContainer + public RelationContainer(IEnumerable relations) { - public RelationContainer(IEnumerable relations) - { - Relations = relations ?? throw new ArgumentNullException(nameof(relations)); - } + Relations = relations ?? throw new ArgumentNullException(nameof(relations)); + } - public IEnumerable Relations { get; private set; } + public IEnumerable Relations { get; private set; } - public IReadOnlyList? GetRelatedElementIdsFor(Expression> propertyExpression) where TEntity : IEntity - { - var property = PropertyMetadataHelper.GetPropertyMetadata(propertyExpression); + public IReadOnlyList? GetRelatedElementIdsFor(Expression> propertyExpression) where TEntity : IEntity + { + var property = PropertyMetadataHelper.GetPropertyMetadata(propertyExpression); - return Relations.FirstOrDefault(x => x.Property.Fingerprint == property?.Fingerprint)?.RelatedElementIdsAs() ?? default; - } + return Relations.FirstOrDefault(x => x.Property.Fingerprint == property?.Fingerprint)?.RelatedElementIdsAs() ?? default; + } - public IReadOnlyList? GetRelatedElementIdsFor() where TRelatedEntity : IEntity - { - return Relations.FirstOrDefault(x => x.RelatedEntityType == typeof(TRelatedEntity))?.RelatedElementIdsAs() ?? default; - } + public IReadOnlyList? GetRelatedElementIdsFor() where TRelatedEntity : IEntity + { + return Relations.FirstOrDefault(x => x.RelatedEntityType == typeof(TRelatedEntity))?.RelatedElementIdsAs() ?? default; } } diff --git a/src/RapidCMS.Core/Forms/ValidationStateChangedEventArgs.cs b/src/RapidCMS.Core/Forms/ValidationStateChangedEventArgs.cs index bcb1518c..57a2f646 100644 --- a/src/RapidCMS.Core/Forms/ValidationStateChangedEventArgs.cs +++ b/src/RapidCMS.Core/Forms/ValidationStateChangedEventArgs.cs @@ -1,12 +1,11 @@ -namespace RapidCMS.Core.Forms +namespace RapidCMS.Core.Forms; + +public class ValidationStateChangedEventArgs { - public class ValidationStateChangedEventArgs + public ValidationStateChangedEventArgs(bool? isValid = null) { - public ValidationStateChangedEventArgs(bool? isValid = null) - { - IsValid = isValid; - } - - public bool? IsValid { get; private set; } + IsValid = isValid; } + + public bool? IsValid { get; private set; } } diff --git a/src/RapidCMS.Core/Forms/ViewContext.cs b/src/RapidCMS.Core/Forms/ViewContext.cs index 34a3f95a..2347f522 100644 --- a/src/RapidCMS.Core/Forms/ViewContext.cs +++ b/src/RapidCMS.Core/Forms/ViewContext.cs @@ -2,20 +2,19 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Abstractions.Forms; -namespace RapidCMS.Core.Forms +namespace RapidCMS.Core.Forms; + +internal class ViewContext : IViewContext { - internal class ViewContext : IViewContext - { - public static ViewContext Default => new(null, default); + public static ViewContext Default => new(null, default); - public ViewContext(string? collectionAlias, IParent? parent) - { - CollectionAlias = collectionAlias; - Parent = parent; - } + public ViewContext(string? collectionAlias, IParent? parent) + { + CollectionAlias = collectionAlias; + Parent = parent; + } - public string? CollectionAlias { get; } + public string? CollectionAlias { get; } - public IParent? Parent { get; } - } + public IParent? Parent { get; } } diff --git a/src/RapidCMS.Core/General.cs b/src/RapidCMS.Core/General.cs index b7622ad1..5a059c35 100644 --- a/src/RapidCMS.Core/General.cs +++ b/src/RapidCMS.Core/General.cs @@ -10,14 +10,13 @@ [assembly: InternalsVisibleTo("RapidCMS.ModelMaker")] -namespace RapidCMS.Core +namespace RapidCMS.Core; + +public class Constants { - public class Constants - { - public const string Add = "add"; - public const string Edit = "edit"; - public const string New = "new"; - public const string Pick = "pick"; - public const string View = "view"; - } + public const string Add = "add"; + public const string Edit = "edit"; + public const string New = "new"; + public const string Pick = "pick"; + public const string View = "view"; } diff --git a/src/RapidCMS.Core/Handlers/ApiFileUploadHandler.cs b/src/RapidCMS.Core/Handlers/ApiFileUploadHandler.cs index d1e2d909..3adefcce 100644 --- a/src/RapidCMS.Core/Handlers/ApiFileUploadHandler.cs +++ b/src/RapidCMS.Core/Handlers/ApiFileUploadHandler.cs @@ -11,88 +11,87 @@ using RapidCMS.Core.Helpers; using RapidCMS.Core.Models.Response; -namespace RapidCMS.Core.Handlers +namespace RapidCMS.Core.Handlers; + +public class ApiFileUploadHandler : IFileUploadHandler + where THandler : IFileUploadHandler { - public class ApiFileUploadHandler : IFileUploadHandler - where THandler : IFileUploadHandler + private readonly IHttpClientFactory _httpClientFactory; + private readonly string _handlerAlias; + + public ApiFileUploadHandler( + IHttpClientFactory httpClientFactory) { - private readonly IHttpClientFactory _httpClientFactory; - private readonly string _handlerAlias; + _httpClientFactory = httpClientFactory; + _handlerAlias = AliasHelper.GetFileUploaderAlias(typeof(THandler)); + } - public ApiFileUploadHandler( - IHttpClientFactory httpClientFactory) - { - _httpClientFactory = httpClientFactory; - _handlerAlias = AliasHelper.GetFileUploaderAlias(typeof(THandler)); - } + public async Task SaveFileAsync(IFileInfo fileInfo, Stream stream) + { + var response = await DoRequestAsync(ApiFileUploadHandler.CreateRequest("file", fileInfo, stream)); + return response?.Result ?? new object(); + } - public async Task SaveFileAsync(IFileInfo fileInfo, Stream stream) + public async Task> ValidateFileAsync(IFileInfo fileInfo) + { + var response = await DoRequestAsync(ApiFileUploadHandler.CreateRequest("file/validate", fileInfo)); + return response?.ErrorMessages ?? Enumerable.Empty(); + } + + private static HttpRequestMessage CreateRequest(string url, IFileInfo fileInfo, Stream? stream = default) + { + var content = new MultipartFormDataContent { - var response = await DoRequestAsync(ApiFileUploadHandler.CreateRequest("file", fileInfo, stream)); - return response?.Result ?? new object(); - } + { new StringContent(fileInfo.LastModified?.ToString() ?? ""), nameof(IFileInfo.LastModified) }, + { new StringContent(fileInfo.Name?.ToString() ?? ""), nameof(IFileInfo.Name) }, + { new StringContent(fileInfo.Size.ToString() ?? ""), nameof(IFileInfo.Size) }, + { new StringContent(fileInfo.Type?.ToString() ?? ""), nameof(IFileInfo.Type) } + }; - public async Task> ValidateFileAsync(IFileInfo fileInfo) + if (stream != null) { - var response = await DoRequestAsync(ApiFileUploadHandler.CreateRequest("file/validate", fileInfo)); - return response?.ErrorMessages ?? Enumerable.Empty(); + content.Add(new StreamContent(stream), "file", fileInfo.Name ?? ""); } - private static HttpRequestMessage CreateRequest(string url, IFileInfo fileInfo, Stream? stream = default) + var request = new HttpRequestMessage(HttpMethod.Post, url) { - var content = new MultipartFormDataContent - { - { new StringContent(fileInfo.LastModified?.ToString() ?? ""), nameof(IFileInfo.LastModified) }, - { new StringContent(fileInfo.Name?.ToString() ?? ""), nameof(IFileInfo.Name) }, - { new StringContent(fileInfo.Size.ToString() ?? ""), nameof(IFileInfo.Size) }, - { new StringContent(fileInfo.Type?.ToString() ?? ""), nameof(IFileInfo.Type) } - }; - - if (stream != null) - { - content.Add(new StreamContent(stream), "file", fileInfo.Name ?? ""); - } + Content = content + }; - var request = new HttpRequestMessage(HttpMethod.Post, url) - { - Content = content - }; + return request; + } - return request; + private async Task DoRequestAsync(HttpRequestMessage request) + { + var httpClient = _httpClientFactory.CreateClient(_handlerAlias); + if (httpClient.BaseAddress == default) + { + throw new InvalidOperationException($"Please configure an HttpClient for the file handler '{_handlerAlias}' using " + + $".AddRapidCMSFileUploadApiHttpClient([..]) and configure its BaseAddress correctly."); } - private async Task DoRequestAsync(HttpRequestMessage request) + var response = await httpClient.SendAsync(request); + return response.StatusCode switch { - var httpClient = _httpClientFactory.CreateClient(_handlerAlias); - if (httpClient.BaseAddress == default) - { - throw new InvalidOperationException($"Please configure an HttpClient for the file handler '{_handlerAlias}' using " + - $".AddRapidCMSFileUploadApiHttpClient([..]) and configure its BaseAddress correctly."); - } - - var response = await httpClient.SendAsync(request); - return response.StatusCode switch - { - HttpStatusCode.OK => response, - HttpStatusCode.NoContent => response, - HttpStatusCode.Unauthorized => throw new UnauthorizedAccessException(), - HttpStatusCode.Forbidden => throw new UnauthorizedAccessException(), + HttpStatusCode.OK => response, + HttpStatusCode.NoContent => response, + HttpStatusCode.Unauthorized => throw new UnauthorizedAccessException(), + HttpStatusCode.Forbidden => throw new UnauthorizedAccessException(), - _ => throw new InvalidOperationException("Please configure the Api correctly.") - }; - } + _ => throw new InvalidOperationException("Please configure the Api correctly.") + }; + } - private async Task DoRequestAsync(HttpRequestMessage request) - where TResult : class + private async Task DoRequestAsync(HttpRequestMessage request) + where TResult : class + { + var response = await DoRequestAsync(request); + if (response.StatusCode == HttpStatusCode.NoContent) { - var response = await DoRequestAsync(request); - if (response.StatusCode == HttpStatusCode.NoContent) - { - return default; - } - - var json = await response.Content.ReadAsStringAsync(); - return JsonConvert.DeserializeObject(json); + return default; } + + var json = await response.Content.ReadAsStringAsync(); + return JsonConvert.DeserializeObject(json); } } diff --git a/src/RapidCMS.Core/Handlers/DefaultButtonActionHandler.cs b/src/RapidCMS.Core/Handlers/DefaultButtonActionHandler.cs index f8d90162..240f5635 100644 --- a/src/RapidCMS.Core/Handlers/DefaultButtonActionHandler.cs +++ b/src/RapidCMS.Core/Handlers/DefaultButtonActionHandler.cs @@ -9,79 +9,78 @@ using RapidCMS.Core.Forms; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Handlers +namespace RapidCMS.Core.Handlers; + +public class DefaultButtonActionHandler : IButtonActionHandler { - public class DefaultButtonActionHandler : IButtonActionHandler + public Task ButtonClickAfterRepositoryActionAsync(ButtonSetup button, FormEditContext editContext, ButtonContext context) { - public Task ButtonClickAfterRepositoryActionAsync(ButtonSetup button, FormEditContext editContext, ButtonContext context) - { - return Task.CompletedTask; - } + return Task.CompletedTask; + } - public virtual Task ButtonClickBeforeRepositoryActionAsync(ButtonSetup button, FormEditContext editContext, ButtonContext context) + public virtual Task ButtonClickBeforeRepositoryActionAsync(ButtonSetup button, FormEditContext editContext, ButtonContext context) + { + return button.DefaultButtonType switch { - return button.DefaultButtonType switch - { - DefaultButtonType.New => Task.FromResult(CrudType.Create), - DefaultButtonType.SaveNew => Task.FromResult(CrudType.Insert), - DefaultButtonType.SaveExisting => Task.FromResult(CrudType.Update), - DefaultButtonType.Delete => Task.FromResult(CrudType.Delete), - DefaultButtonType.Edit => Task.FromResult(CrudType.Edit), - DefaultButtonType.Remove => Task.FromResult(CrudType.Remove), - DefaultButtonType.Add => Task.FromResult(CrudType.Add), - DefaultButtonType.Pick => Task.FromResult(CrudType.Pick), - DefaultButtonType.Return => Task.FromResult(CrudType.Return), - DefaultButtonType.Up => Task.FromResult(CrudType.Up), - _ => Task.FromResult(CrudType.View), - }; - } + DefaultButtonType.New => Task.FromResult(CrudType.Create), + DefaultButtonType.SaveNew => Task.FromResult(CrudType.Insert), + DefaultButtonType.SaveExisting => Task.FromResult(CrudType.Update), + DefaultButtonType.Delete => Task.FromResult(CrudType.Delete), + DefaultButtonType.Edit => Task.FromResult(CrudType.Edit), + DefaultButtonType.Remove => Task.FromResult(CrudType.Remove), + DefaultButtonType.Add => Task.FromResult(CrudType.Add), + DefaultButtonType.Pick => Task.FromResult(CrudType.Pick), + DefaultButtonType.Return => Task.FromResult(CrudType.Return), + DefaultButtonType.Up => Task.FromResult(CrudType.Up), + _ => Task.FromResult(CrudType.View), + }; + } - public OperationAuthorizationRequirement GetOperation(ButtonSetup button, FormEditContext editContext) + public OperationAuthorizationRequirement GetOperation(ButtonSetup button, FormEditContext editContext) + { + switch (button.DefaultButtonType) { - switch (button.DefaultButtonType) - { - case DefaultButtonType.New: - case DefaultButtonType.SaveNew: - return Operations.Create; + case DefaultButtonType.New: + case DefaultButtonType.SaveNew: + return Operations.Create; - case DefaultButtonType.Edit: - case DefaultButtonType.SaveExisting: - return Operations.Update; + case DefaultButtonType.Edit: + case DefaultButtonType.SaveExisting: + return Operations.Update; - case DefaultButtonType.Delete: - return Operations.Delete; + case DefaultButtonType.Delete: + return Operations.Delete; - default: - case DefaultButtonType.View: - case DefaultButtonType.Return: - case DefaultButtonType.Up: - return Operations.Read; + default: + case DefaultButtonType.View: + case DefaultButtonType.Return: + case DefaultButtonType.Up: + return Operations.Read; - case DefaultButtonType.Remove: - return Operations.Remove; + case DefaultButtonType.Remove: + return Operations.Remove; - case DefaultButtonType.Add: - case DefaultButtonType.Pick: - return Operations.Add; - } + case DefaultButtonType.Add: + case DefaultButtonType.Pick: + return Operations.Add; } + } - public bool IsCompatible(ButtonSetup button, FormEditContext editContext) - { - var usages = button.DefaultButtonType.GetCustomAttribute()?.Usages; - var isCompatible = usages?.Any(x => editContext.UsageType.HasFlag(x)) ?? false; + public bool IsCompatible(ButtonSetup button, FormEditContext editContext) + { + var usages = button.DefaultButtonType.GetCustomAttribute()?.Usages; + var isCompatible = usages?.Any(x => editContext.UsageType.HasFlag(x)) ?? false; - return isCompatible; - } + return isCompatible; + } - public bool RequiresValidForm(ButtonSetup button, FormEditContext editContext) - { - return button.DefaultButtonType.GetCustomAttribute() != null; - } + public bool RequiresValidForm(ButtonSetup button, FormEditContext editContext) + { + return button.DefaultButtonType.GetCustomAttribute() != null; + } - public bool ShouldAskForConfirmation(ButtonSetup button, FormEditContext editContext) - { - return button.DefaultButtonType.GetCustomAttribute() != null; - } + public bool ShouldAskForConfirmation(ButtonSetup button, FormEditContext editContext) + { + return button.DefaultButtonType.GetCustomAttribute() != null; } } diff --git a/src/RapidCMS.Core/Handlers/NavigateButtonActionHandler.cs b/src/RapidCMS.Core/Handlers/NavigateButtonActionHandler.cs index b06139ec..42ebc381 100644 --- a/src/RapidCMS.Core/Handlers/NavigateButtonActionHandler.cs +++ b/src/RapidCMS.Core/Handlers/NavigateButtonActionHandler.cs @@ -7,55 +7,54 @@ using RapidCMS.Core.Models.Setup; using RapidCMS.Core.Navigation; -namespace RapidCMS.Core.Handlers +namespace RapidCMS.Core.Handlers; + +public class NavigateButtonActionHandler : DefaultButtonActionHandler + where TNavigationHandler : INavigationHandler { - public class NavigateButtonActionHandler : DefaultButtonActionHandler - where TNavigationHandler : INavigationHandler + private readonly TNavigationHandler _navigationHandler; + private readonly ISetupResolver _collectionResolver; + private readonly INavigationStateProvider _navigationStateProvider; + + public NavigateButtonActionHandler( + TNavigationHandler navigationHandler, + ISetupResolver collectionResolver, + INavigationStateProvider navigationStateProvider) { - private readonly TNavigationHandler _navigationHandler; - private readonly ISetupResolver _collectionResolver; - private readonly INavigationStateProvider _navigationStateProvider; - - public NavigateButtonActionHandler( - TNavigationHandler navigationHandler, - ISetupResolver collectionResolver, - INavigationStateProvider navigationStateProvider) - { - _navigationHandler = navigationHandler; - _collectionResolver = collectionResolver; - _navigationStateProvider = navigationStateProvider; - } + _navigationHandler = navigationHandler; + _collectionResolver = collectionResolver; + _navigationStateProvider = navigationStateProvider; + } - public override async Task ButtonClickBeforeRepositoryActionAsync(ButtonSetup button, FormEditContext editContext, ButtonContext context) + public override async Task ButtonClickBeforeRepositoryActionAsync(ButtonSetup button, FormEditContext editContext, ButtonContext context) + { + var request = await _navigationHandler.CreateNavigationRequestAsync(button, editContext); + if (request != null) { - var request = await _navigationHandler.CreateNavigationRequestAsync(button, editContext); - if (request != null) + var collection = request.IsPage ? null : await _collectionResolver.ResolveSetupAsync(request.CollectionAlias); + + var usageType = request.IsNew ? UsageType.New + : request.IsEdit ? UsageType.Edit + : UsageType.View; + + NavigationState navigationState; + + if (request.IsPage) + { + navigationState = new NavigationState(request.CollectionAlias, request.ParentPath); + } + else if (request.IsList) { - var collection = request.IsPage ? null : await _collectionResolver.ResolveSetupAsync(request.CollectionAlias); - - var usageType = request.IsNew ? UsageType.New - : request.IsEdit ? UsageType.Edit - : UsageType.View; - - NavigationState navigationState; - - if (request.IsPage) - { - navigationState = new NavigationState(request.CollectionAlias, request.ParentPath); - } - else if (request.IsList) - { - navigationState = new NavigationState(request.CollectionAlias, request.ParentPath, usageType); - } - else - { - navigationState = new NavigationState(request.CollectionAlias, request.ParentPath, request.VariantAlias ?? collection!.EntityVariant.Alias, request.Id, usageType); - } - - _navigationStateProvider.AppendNavigationState(navigationState); + navigationState = new NavigationState(request.CollectionAlias, request.ParentPath, usageType); + } + else + { + navigationState = new NavigationState(request.CollectionAlias, request.ParentPath, request.VariantAlias ?? collection!.EntityVariant.Alias, request.Id, usageType); } - return CrudType.None; + _navigationStateProvider.AppendNavigationState(navigationState); } + + return CrudType.None; } } diff --git a/src/RapidCMS.Core/Handlers/OpenPaneButtonActionHandler.cs b/src/RapidCMS.Core/Handlers/OpenPaneButtonActionHandler.cs index 609f0a36..53eb3f1e 100644 --- a/src/RapidCMS.Core/Handlers/OpenPaneButtonActionHandler.cs +++ b/src/RapidCMS.Core/Handlers/OpenPaneButtonActionHandler.cs @@ -5,18 +5,17 @@ using RapidCMS.Core.Models.EventArgs.Mediators; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Handlers -{ - public class OpenPaneButtonActionHandler : DefaultButtonActionHandler - { - private readonly IMediator _mediator; +namespace RapidCMS.Core.Handlers; - public OpenPaneButtonActionHandler(IMediator mediator) - { - _mediator = mediator; - } +public class OpenPaneButtonActionHandler : DefaultButtonActionHandler +{ + private readonly IMediator _mediator; - public override Task ButtonClickBeforeRepositoryActionAsync(ButtonSetup button, FormEditContext editContext, ButtonContext context) - => _mediator.NotifyEventAsync(this, new PaneRequestEventArgs(typeof(TSidePane), editContext, context)); + public OpenPaneButtonActionHandler(IMediator mediator) + { + _mediator = mediator; } + + public override Task ButtonClickBeforeRepositoryActionAsync(ButtonSetup button, FormEditContext editContext, ButtonContext context) + => _mediator.NotifyEventAsync(this, new PaneRequestEventArgs(typeof(TSidePane), editContext, context)); } diff --git a/src/RapidCMS.Core/Helpers/AliasHelper.cs b/src/RapidCMS.Core/Helpers/AliasHelper.cs index a535138f..05537c2d 100644 --- a/src/RapidCMS.Core/Helpers/AliasHelper.cs +++ b/src/RapidCMS.Core/Helpers/AliasHelper.cs @@ -2,33 +2,32 @@ using System.Linq; using RapidCMS.Core.Extensions; -namespace RapidCMS.Core.Helpers +namespace RapidCMS.Core.Helpers; + +public static class AliasHelper { - public static class AliasHelper + public static string GetFileUploaderAlias(Type handlerType) { - public static string GetFileUploaderAlias(Type handlerType) - { - var type = (handlerType.IsGenericType && handlerType.GetGenericTypeDefinition().Name.StartsWith("ApiFileUpload")) - ? handlerType.GetGenericArguments().FirstOrDefault() - : handlerType; + var type = (handlerType.IsGenericType && handlerType.GetGenericTypeDefinition().Name.StartsWith("ApiFileUpload")) + ? handlerType.GetGenericArguments().FirstOrDefault() + : handlerType; - return type?.Name.ToSha256Base64String("file-upload-handler") ?? "unknown-file-handler"; - } + return type?.Name.ToSha256Base64String("file-upload-handler") ?? "unknown-file-handler"; + } - public static string GetRepositoryAlias(Type repositoryType) - { - var name = repositoryType?.FullName; - var alias = name?.ToSha256Base64String("repo")[0..12] ?? "unknown-repository"; + public static string GetRepositoryAlias(Type repositoryType) + { + var name = repositoryType?.FullName; + var alias = name?.ToSha256Base64String("repo")[0..12] ?? "unknown-repository"; - return alias; - } + return alias; + } - public static string GetEntityVariantAlias(Type entityType) - { - var name = entityType?.FullName; - var alias = name?.ToSha256Base64String("entity")[0..6] ?? "unknown-entity"; + public static string GetEntityVariantAlias(Type entityType) + { + var name = entityType?.FullName; + var alias = name?.ToSha256Base64String("entity")[0..6] ?? "unknown-entity"; - return alias; - } + return alias; } } diff --git a/src/RapidCMS.Core/Helpers/ApiRepositoryHelper.cs b/src/RapidCMS.Core/Helpers/ApiRepositoryHelper.cs index abbfc8ac..44c0c8e1 100644 --- a/src/RapidCMS.Core/Helpers/ApiRepositoryHelper.cs +++ b/src/RapidCMS.Core/Helpers/ApiRepositoryHelper.cs @@ -9,92 +9,91 @@ using RapidCMS.Core.Exceptions; using RapidCMS.Core.Forms; -namespace RapidCMS.Core.Helpers +namespace RapidCMS.Core.Helpers; + +internal class ApiRepositoryHelper { - internal class ApiRepositoryHelper + private readonly IHttpClientFactory _httpClientFactory; + private readonly JsonSerializerSettings _jsonSerializerSettings; + private readonly string _repositoryAlias; + + public ApiRepositoryHelper( + IHttpClientFactory httpClientFactory, + JsonSerializerSettings jsonSerializerSettings, + string repositoryAlias) { - private readonly IHttpClientFactory _httpClientFactory; - private readonly JsonSerializerSettings _jsonSerializerSettings; - private readonly string _repositoryAlias; + _httpClientFactory = httpClientFactory; + _jsonSerializerSettings = jsonSerializerSettings; + _repositoryAlias = repositoryAlias; + } - public ApiRepositoryHelper( - IHttpClientFactory httpClientFactory, - JsonSerializerSettings jsonSerializerSettings, - string repositoryAlias) - { - _httpClientFactory = httpClientFactory; - _jsonSerializerSettings = jsonSerializerSettings; - _repositoryAlias = repositoryAlias; - } + private HttpRequestMessage CreateRequest(HttpMethod method, string url) + { + return new HttpRequestMessage(method, url); + } - private HttpRequestMessage CreateRequest(HttpMethod method, string url) + internal HttpRequestMessage CreateRequest(HttpMethod method, string url, T content) + { + if (method == HttpMethod.Get) { - return new HttpRequestMessage(method, url); + throw new InvalidOperationException(); } - internal HttpRequestMessage CreateRequest(HttpMethod method, string url, T content) - { - if (method == HttpMethod.Get) - { - throw new InvalidOperationException(); - } - - var request = CreateRequest(method, url); - var json = JsonConvert.SerializeObject(content, _jsonSerializerSettings); - request.Content = new StringContent(json, Encoding.UTF8, "application/json"); + var request = CreateRequest(method, url); + var json = JsonConvert.SerializeObject(content, _jsonSerializerSettings); + request.Content = new StringContent(json, Encoding.UTF8, "application/json"); - return request; - } + return request; + } - internal async Task DoRequestAsync(HttpRequestMessage request, IEditContext? editContext = default) + internal async Task DoRequestAsync(HttpRequestMessage request, IEditContext? editContext = default) + { + var httpClient = _httpClientFactory.CreateClient(_repositoryAlias); + if (httpClient.BaseAddress == default) { - var httpClient = _httpClientFactory.CreateClient(_repositoryAlias); - if (httpClient.BaseAddress == default) - { - throw new InvalidOperationException($"Please configure an HttpClient for the repository '{_repositoryAlias}' using " + - $".{nameof(RapidCMSMiddleware.AddRapidCMSApiRepository)}([..]) and configure its BaseAddress correctly."); - } + throw new InvalidOperationException($"Please configure an HttpClient for the repository '{_repositoryAlias}' using " + + $".{nameof(RapidCMSMiddleware.AddRapidCMSApiRepository)}([..]) and configure its BaseAddress correctly."); + } - var response = await httpClient.SendAsync(request); + var response = await httpClient.SendAsync(request); - if (response.StatusCode == HttpStatusCode.BadRequest && editContext != null && await response.Content.ReadAsStringAsync() is string json) + if (response.StatusCode == HttpStatusCode.BadRequest && editContext != null && await response.Content.ReadAsStringAsync() is string json) + { + var errors = JsonConvert.DeserializeObject(json, _jsonSerializerSettings); + if (errors != null) { - var errors = JsonConvert.DeserializeObject(json, _jsonSerializerSettings); - if (errors != null) + foreach (var error in errors) { - foreach (var error in errors) - { - editContext.AddValidationError(error.Key, error.Value); - } + editContext.AddValidationError(error.Key, error.Value); } } + } - return response.StatusCode switch - { - HttpStatusCode.OK => response, - HttpStatusCode.BadRequest => throw new InvalidEntityException(), - HttpStatusCode.Unauthorized => throw new UnauthorizedAccessException(), - HttpStatusCode.Forbidden => throw new UnauthorizedAccessException(), - HttpStatusCode.NotFound => throw new NotFoundException($"{request.RequestUri} not found."), + return response.StatusCode switch + { + HttpStatusCode.OK => response, + HttpStatusCode.BadRequest => throw new InvalidEntityException(), + HttpStatusCode.Unauthorized => throw new UnauthorizedAccessException(), + HttpStatusCode.Forbidden => throw new UnauthorizedAccessException(), + HttpStatusCode.NotFound => throw new NotFoundException($"{request.RequestUri} not found."), - _ => throw new InvalidOperationException() - }; - } + _ => throw new InvalidOperationException() + }; + } - internal async Task DoRequestAsync(HttpRequestMessage request, IEditContext? editContext = default) - where TResult : class + internal async Task DoRequestAsync(HttpRequestMessage request, IEditContext? editContext = default) + where TResult : class + { + try { - try - { - var response = await DoRequestAsync(request, editContext); - var json = await response.Content.ReadAsStringAsync(); - var result = JsonConvert.DeserializeObject(json, _jsonSerializerSettings); - return result; - } - catch (NotFoundException) - { - return default; - } + var response = await DoRequestAsync(request, editContext); + var json = await response.Content.ReadAsStringAsync(); + var result = JsonConvert.DeserializeObject(json, _jsonSerializerSettings); + return result; + } + catch (NotFoundException) + { + return default; } } } diff --git a/src/RapidCMS.Core/Helpers/EditorTypeHelper.cs b/src/RapidCMS.Core/Helpers/EditorTypeHelper.cs index 8b868a12..276c1e8c 100644 --- a/src/RapidCMS.Core/Helpers/EditorTypeHelper.cs +++ b/src/RapidCMS.Core/Helpers/EditorTypeHelper.cs @@ -4,26 +4,25 @@ using RapidCMS.Core.Enums; using RapidCMS.Core.Extensions; -namespace RapidCMS.Core.Helpers +namespace RapidCMS.Core.Helpers; + +internal static class EditorTypeHelper { - internal static class EditorTypeHelper + public static EditorType TryFindDefaultEditorType(Type editorType) { - public static EditorType TryFindDefaultEditorType(Type editorType) + foreach (var type in EnumHelper.GetValues()) { - foreach (var type in EnumHelper.GetValues()) - { - if (type.GetCustomAttribute()?.Types.Contains(editorType) ?? false) - { - return type; - } - } - - if (typeof(Enum).IsAssignableFrom(editorType)) + if (type.GetCustomAttribute()?.Types.Contains(editorType) ?? false) { - return EditorType.Select; + return type; } + } - return default; + if (typeof(Enum).IsAssignableFrom(editorType)) + { + return EditorType.Select; } + + return default; } } diff --git a/src/RapidCMS.Core/Helpers/EnumHelper.cs b/src/RapidCMS.Core/Helpers/EnumHelper.cs index 7d816cbf..1c6269c8 100644 --- a/src/RapidCMS.Core/Helpers/EnumHelper.cs +++ b/src/RapidCMS.Core/Helpers/EnumHelper.cs @@ -2,14 +2,13 @@ using System.Collections.Generic; using System.Linq; -namespace RapidCMS.Core.Helpers +namespace RapidCMS.Core.Helpers; + +internal static class EnumHelper { - internal static class EnumHelper + public static IEnumerable GetValues() + where TEnum : Enum { - public static IEnumerable GetValues() - where TEnum : Enum - { - return Enum.GetValues(typeof(TEnum)).Cast(); - } + return Enum.GetValues(typeof(TEnum)).Cast(); } } diff --git a/src/RapidCMS.Core/Helpers/PropertyMetadataHelper.cs b/src/RapidCMS.Core/Helpers/PropertyMetadataHelper.cs index a33e7918..5314b8c1 100644 --- a/src/RapidCMS.Core/Helpers/PropertyMetadataHelper.cs +++ b/src/RapidCMS.Core/Helpers/PropertyMetadataHelper.cs @@ -8,401 +8,400 @@ using RapidCMS.Core.Extensions; using RapidCMS.Core.Models.Metadata; -namespace RapidCMS.Core.Helpers +namespace RapidCMS.Core.Helpers; + +/// +/// Static helper for a lot of Expression magic +/// +internal static class PropertyMetadataHelper { /// - /// Static helper for a lot of Expression magic + /// Converts a given LambdaExpression containing MemberExpressions to getters and setters, and the name of each nested object plus the name of the property. + /// + /// (Person x) => x.Company.Owner.Name becomes: + /// getter: (object x) => (object)(((Person) x).get_Company().get_Owner().get_Name()) + /// setter: (object x, object y) => ((Person) x).get_Company().get_Owner().set_Name((string)y) + /// objectType: Person + /// propertyType: string + /// name: CompanyOwnerName /// - internal static class PropertyMetadataHelper + /// The LambdaExpression to be converted + /// IPropertyMetadata when successful, IFullPropertyMetadata if setter is available. Returns default when unsuccessful. + public static IPropertyMetadata? GetPropertyMetadata(LambdaExpression lambdaExpression) { - /// - /// Converts a given LambdaExpression containing MemberExpressions to getters and setters, and the name of each nested object plus the name of the property. - /// - /// (Person x) => x.Company.Owner.Name becomes: - /// getter: (object x) => (object)(((Person) x).get_Company().get_Owner().get_Name()) - /// setter: (object x, object y) => ((Person) x).get_Company().get_Owner().set_Name((string)y) - /// objectType: Person - /// propertyType: string - /// name: CompanyOwnerName - /// - /// The LambdaExpression to be converted - /// IPropertyMetadata when successful, IFullPropertyMetadata if setter is available. Returns default when unsuccessful. - public static IPropertyMetadata? GetPropertyMetadata(LambdaExpression lambdaExpression) - { - Type? parameterTType = null; - Type? parameterTPropertyType = null; + Type? parameterTType = null; + Type? parameterTPropertyType = null; - var parameterT = Expression.Parameter(typeof(object), "x"); - var parameterTProperty = Expression.Parameter(typeof(object), "y"); + var parameterT = Expression.Parameter(typeof(object), "x"); + var parameterTProperty = Expression.Parameter(typeof(object), "y"); - var x = lambdaExpression.Body; + var x = lambdaExpression.Body; - if (!(x is MemberExpression) && !(x is ParameterExpression)) - { - parameterTType = lambdaExpression.Parameters.First().Type; - var parameterTAsType = Expression.Convert(parameterT, parameterTType) as Expression; - - var getter = ConvertToGetterViaLambda(parameterT, lambdaExpression, parameterTAsType); - if (getter == null) - { - return default; - } + if (!(x is MemberExpression) && !(x is ParameterExpression)) + { + parameterTType = lambdaExpression.Parameters.First().Type; + var parameterTAsType = Expression.Convert(parameterT, parameterTType) as Expression; - return new PropertyMetadata(lambdaExpression, lambdaExpression.Body.Type, lambdaExpression.ToString(), getter, parameterTType, GetFingerprint(lambdaExpression)); - } - else + var getter = ConvertToGetterViaLambda(parameterT, lambdaExpression, parameterTAsType); + if (getter == null) { - var isAtTail = true; - var getNestedObjectMethods = new List(); - var names = new List(); - - MethodInfo? getValueMethod = null; - MethodInfo? setValueMethod = null; - - do - { - if (x is MemberExpression memberExpression) - { - var propertyInfo = memberExpression.Member as PropertyInfo; - - if (propertyInfo == null || propertyInfo.GetGetMethod() == null) - { - return default; - } - - if (isAtTail) - { - setValueMethod = propertyInfo.GetSetMethod(); - getValueMethod = propertyInfo.GetGetMethod(); - names.Add(propertyInfo.Name); + return default; + } - parameterTPropertyType = propertyInfo.PropertyType; + return new PropertyMetadata(lambdaExpression, lambdaExpression.Body.Type, lambdaExpression.ToString(), getter, parameterTType, GetFingerprint(lambdaExpression)); + } + else + { + var isAtTail = true; + var getNestedObjectMethods = new List(); + var names = new List(); - isAtTail = false; + MethodInfo? getValueMethod = null; + MethodInfo? setValueMethod = null; - x = memberExpression.Expression; - } - else - { - getNestedObjectMethods.Insert(0, propertyInfo.GetGetMethod()!); - names.Insert(0, propertyInfo.Name); + do + { + if (x is MemberExpression memberExpression) + { + var propertyInfo = memberExpression.Member as PropertyInfo; - x = memberExpression.Expression; - } + if (propertyInfo == null || propertyInfo.GetGetMethod() == null) + { + return default; } - else if (x is ParameterExpression parameterExpression) + + if (isAtTail) { - parameterTType = x.Type; + setValueMethod = propertyInfo.GetSetMethod(); + getValueMethod = propertyInfo.GetGetMethod(); + names.Add(propertyInfo.Name); + + parameterTPropertyType = propertyInfo.PropertyType; - // expression is x => x - if (getValueMethod == null && parameterExpression == lambdaExpression.Body) - { - return new PropertyMetadata(lambdaExpression, parameterTType, "Self", x => x, parameterTType, GetFingerprint(lambdaExpression)); - } + isAtTail = false; - // done, arrived at root - break; + x = memberExpression.Expression; } else { - return default; + getNestedObjectMethods.Insert(0, propertyInfo.GetGetMethod()!); + names.Insert(0, propertyInfo.Name); + + x = memberExpression.Expression; } } - while (true); - - if (getValueMethod == null || parameterTPropertyType == null) + else if (x is ParameterExpression parameterExpression) { - return default; - } - - var parameterTAsType = Expression.Convert(parameterT, parameterTType) as Expression; - var valueToObject = Expression.Convert(Expression.Parameter(parameterTPropertyType, "z"), typeof(object)); - - var valueToType = parameterTPropertyType.IsValueType && Nullable.GetUnderlyingType(parameterTPropertyType) == null - ? Expression.Convert(Expression.Coalesce(parameterTProperty, Expression.Default(parameterTPropertyType)), parameterTPropertyType) - : Expression.Convert(parameterTProperty, parameterTPropertyType) as Expression; + parameterTType = x.Type; - var instanceExpression = (getNestedObjectMethods.Count == 0) - ? parameterTAsType - : getNestedObjectMethods.Aggregate( - parameterTAsType, - (parameter, method) => Expression.Call(parameter, method)); - - var name = string.Join(".", names); - - var getter = ConvertToGetterViaMethod(parameterT, getValueMethod, instanceExpression); - if (getter == null) - { - return default; - } + // expression is x => x + if (getValueMethod == null && parameterExpression == lambdaExpression.Body) + { + return new PropertyMetadata(lambdaExpression, parameterTType, "Self", x => x, parameterTType, GetFingerprint(lambdaExpression)); + } - var setter = setValueMethod == null ? default : ConvertToSetter(parameterT, parameterTProperty, setValueMethod, valueToType, instanceExpression); - if (setter == null) - { - return new PropertyMetadata(lambdaExpression, parameterTPropertyType, name, getter, parameterTType, GetFingerprint(lambdaExpression)); + // done, arrived at root + break; } else { - return new FullPropertyMetadata(lambdaExpression, parameterTPropertyType, name, getter, setter, parameterTType, GetFingerprint(lambdaExpression)); + return default; } } - } + while (true); + + if (getValueMethod == null || parameterTPropertyType == null) + { + return default; + } - /// - /// Converts a given LambdaExpression containing expression to get value from an object. - /// - /// (Person x) => $"{x.FirstName} - {x.LastName}" becomes: - /// getter: (object x) => (object) - /// objectType: Person - /// propertyType: string - /// - /// The LambdaExpression to be converted - /// GetterAndSetter object when successful, default when not. - public static IExpressionMetadata? GetExpressionMetadata(LambdaExpression lambdaExpression) - { - var parameterT = Expression.Parameter(typeof(object), "x"); - var parameterTType = lambdaExpression.Parameters.First().Type; var parameterTAsType = Expression.Convert(parameterT, parameterTType) as Expression; + var valueToObject = Expression.Convert(Expression.Parameter(parameterTPropertyType, "z"), typeof(object)); + + var valueToType = parameterTPropertyType.IsValueType && Nullable.GetUnderlyingType(parameterTPropertyType) == null + ? Expression.Convert(Expression.Coalesce(parameterTProperty, Expression.Default(parameterTPropertyType)), parameterTPropertyType) + : Expression.Convert(parameterTProperty, parameterTPropertyType) as Expression; + + var instanceExpression = (getNestedObjectMethods.Count == 0) + ? parameterTAsType + : getNestedObjectMethods.Aggregate( + parameterTAsType, + (parameter, method) => Expression.Call(parameter, method)); - var name = ((lambdaExpression.Body as MemberExpression)?.Member as PropertyInfo)?.Name ?? lambdaExpression.ToString(); + var name = string.Join(".", names); - var getter = ConvertToStringGetterViaLambda(parameterT, lambdaExpression, parameterTAsType); + var getter = ConvertToGetterViaMethod(parameterT, getValueMethod, instanceExpression); if (getter == null) { return default; } - return new ExpressionMetadata(name, getter); + var setter = setValueMethod == null ? default : ConvertToSetter(parameterT, parameterTProperty, setValueMethod, valueToType, instanceExpression); + if (setter == null) + { + return new PropertyMetadata(lambdaExpression, parameterTPropertyType, name, getter, parameterTType, GetFingerprint(lambdaExpression)); + } + else + { + return new FullPropertyMetadata(lambdaExpression, parameterTPropertyType, name, getter, setter, parameterTType, GetFingerprint(lambdaExpression)); + } } + } - /// - /// Converts a given IPropertyMetadata to an IExpressionMetadata. - /// - /// - /// - public static IExpressionMetadata GetExpressionMetadata(IPropertyMetadata propertyMetadata) + /// + /// Converts a given LambdaExpression containing expression to get value from an object. + /// + /// (Person x) => $"{x.FirstName} - {x.LastName}" becomes: + /// getter: (object x) => (object) + /// objectType: Person + /// propertyType: string + /// + /// The LambdaExpression to be converted + /// GetterAndSetter object when successful, default when not. + public static IExpressionMetadata? GetExpressionMetadata(LambdaExpression lambdaExpression) + { + var parameterT = Expression.Parameter(typeof(object), "x"); + var parameterTType = lambdaExpression.Parameters.First().Type; + var parameterTAsType = Expression.Convert(parameterT, parameterTType) as Expression; + + var name = ((lambdaExpression.Body as MemberExpression)?.Member as PropertyInfo)?.Name ?? lambdaExpression.ToString(); + + var getter = ConvertToStringGetterViaLambda(parameterT, lambdaExpression, parameterTAsType); + if (getter == null) { - return new ExpressionMetadata(propertyMetadata.PropertyName, (x => propertyMetadata.Getter(x)?.ToString() ?? "")); + return default; } - /// - /// Converts a given subject and property info to PropertyMetadataHelper. - /// - /// Converts (obj, A) to (obj) => obj.A - /// - /// - /// - /// - public static IPropertyMetadata? GetPropertyMetadata(Type subject, PropertyInfo propertyInfo) - { - var parameter = Expression.Parameter(subject); - var property = Expression.Property(parameter, propertyInfo); - if (property == null) - { - throw new InvalidOperationException("Could not get property from subject"); - } + return new ExpressionMetadata(name, getter); + } - var delegateType = typeof(Func<,>).MakeGenericType(subject, propertyInfo.PropertyType); - var lambda = Expression.Lambda(delegateType, property, parameter); + /// + /// Converts a given IPropertyMetadata to an IExpressionMetadata. + /// + /// + /// + public static IExpressionMetadata GetExpressionMetadata(IPropertyMetadata propertyMetadata) + { + return new ExpressionMetadata(propertyMetadata.PropertyName, (x => propertyMetadata.Getter(x)?.ToString() ?? "")); + } - return GetPropertyMetadata(lambda); + /// + /// Converts a given subject and property info to PropertyMetadataHelper. + /// + /// Converts (obj, A) to (obj) => obj.A + /// + /// + /// + /// + public static IPropertyMetadata? GetPropertyMetadata(Type subject, PropertyInfo propertyInfo) + { + var parameter = Expression.Parameter(subject); + var property = Expression.Property(parameter, propertyInfo); + if (property == null) + { + throw new InvalidOperationException("Could not get property from subject"); } - /// - /// Converts a given subject and chained properties to PropertyMetadataHelper - /// - /// Converts (obj, [A,B], C) to (obj) => obj.A.B.C - /// - /// - /// - /// - /// - public static IPropertyMetadata? GetPropertyMetadata(Type subject, IEnumerable? objectProperties, PropertyInfo propertyInfo) - { - if (!(objectProperties?.Any() ?? false)) - { - return GetPropertyMetadata(subject, propertyInfo); - } + var delegateType = typeof(Func<,>).MakeGenericType(subject, propertyInfo.PropertyType); + var lambda = Expression.Lambda(delegateType, property, parameter); - // given infos: [A, B], C - // get to expression: C(B(A(subject))) + return GetPropertyMetadata(lambda); + } - var parameter = Expression.Parameter(subject); - if (!(objectProperties - .Union(new[] { propertyInfo }) - .Aggregate((Expression)parameter, (param, prop) => Expression.Property(param, prop)) is MemberExpression nestedProperty)) - { - throw new InvalidOperationException("Could not get nested property from subject"); - } + /// + /// Converts a given subject and chained properties to PropertyMetadataHelper + /// + /// Converts (obj, [A,B], C) to (obj) => obj.A.B.C + /// + /// + /// + /// + /// + public static IPropertyMetadata? GetPropertyMetadata(Type subject, IEnumerable? objectProperties, PropertyInfo propertyInfo) + { + if (!(objectProperties?.Any() ?? false)) + { + return GetPropertyMetadata(subject, propertyInfo); + } - var delegateType = typeof(Func<,>).MakeGenericType(subject, propertyInfo.PropertyType); - var lambda = Expression.Lambda(delegateType, nestedProperty, parameter); + // given infos: [A, B], C + // get to expression: C(B(A(subject))) - return GetPropertyMetadata(lambda); + var parameter = Expression.Parameter(subject); + if (!(objectProperties + .Union(new[] { propertyInfo }) + .Aggregate((Expression)parameter, (param, prop) => Expression.Property(param, prop)) is MemberExpression nestedProperty)) + { + throw new InvalidOperationException("Could not get nested property from subject"); } - /// - /// Converts a given subject and property name to PropertyMetadataHelper - /// - /// Converts (obj, "A.B.C") to (obj) => obj.A.B.C - /// - /// - /// - /// - public static IPropertyMetadata? GetPropertyMetadata(Type subject, string propertyName) - { - try - { - var properties = propertyName - .Split('.') - .RecursiveSelect(subject, (property, @object) => - { - var objectProperty = @object.GetProperty(property); - if (objectProperty == null) - { - throw new NotFoundException($"Property {property} not found on {@object}."); - } + var delegateType = typeof(Func<,>).MakeGenericType(subject, propertyInfo.PropertyType); + var lambda = Expression.Lambda(delegateType, nestedProperty, parameter); - return (objectProperty.PropertyType, objectProperty); - }) - .ToList(); + return GetPropertyMetadata(lambda); + } - if (properties == null || properties.Count == 0) + /// + /// Converts a given subject and property name to PropertyMetadataHelper + /// + /// Converts (obj, "A.B.C") to (obj) => obj.A.B.C + /// + /// + /// + /// + public static IPropertyMetadata? GetPropertyMetadata(Type subject, string propertyName) + { + try + { + var properties = propertyName + .Split('.') + .RecursiveSelect(subject, (property, @object) => { - return default; - } + var objectProperty = @object.GetProperty(property); + if (objectProperty == null) + { + throw new NotFoundException($"Property {property} not found on {@object}."); + } - return GetPropertyMetadata(subject, properties.SkipLast(1), properties.Last()); - } - catch + return (objectProperty.PropertyType, objectProperty); + }) + .ToList(); + + if (properties == null || properties.Count == 0) { return default; } + + return GetPropertyMetadata(subject, properties.SkipLast(1), properties.Last()); } + catch + { + return default; + } + } - /// - /// Converts a given LambdaExpression containing MemberExpressions to getters and setters, and the name of each nested object plus the name of the property. - /// - /// (Person x) => x.Company.Owner.Name becomes: - /// getter: (object x) => (object)(((Person) x).get_Company().get_Owner().get_Name()) - /// setter: (object x, object y) => ((Person) x).get_Company().get_Owner().set_Name((string)y) - /// objectType: Person - /// propertyType: string - /// name: CompanyOwnerName - /// - /// - /// - /// The lambda expression to be converted - /// IPropertyMetadata when successful, IFullPropertyMetadata if setter is available. Returns default when unsuccessful. - public static IPropertyMetadata? GetPropertyMetadata(Expression> expression) - => GetPropertyMetadata((LambdaExpression)expression); - - /// - /// Converts a given LambdaExpression containing MemberExpressions to getters and setters, and the name of each nested object plus the name of the property. - /// - /// (Person x) => x.Company.Owner.Name becomes: - /// getter: (object x) => (object)(((Person) x).get_Company().get_Owner().get_Name()) - /// setter: (object x, object y) => ((Person) x).get_Company().get_Owner().set_Name((string)y) - /// objectType: Person - /// propertyType: string - /// name: CompanyOwnerName - /// - /// - /// - /// The lambda expression to be converted - /// IFullPropertyMetadata - /// Failed to convert expression to IFullPropertyMetadata - public static IFullPropertyMetadata GetFullPropertyMetadata(Expression> expression) - => GetPropertyMetadata(expression) as IFullPropertyMetadata ?? throw new InvalidOperationException($"Could not convert expression to {nameof(IFullPropertyMetadata)}."); - - private static Func? ConvertToGetterViaMethod(ParameterExpression parameterT, MethodInfo getValueMethod, Expression instanceExpression) + /// + /// Converts a given LambdaExpression containing MemberExpressions to getters and setters, and the name of each nested object plus the name of the property. + /// + /// (Person x) => x.Company.Owner.Name becomes: + /// getter: (object x) => (object)(((Person) x).get_Company().get_Owner().get_Name()) + /// setter: (object x, object y) => ((Person) x).get_Company().get_Owner().set_Name((string)y) + /// objectType: Person + /// propertyType: string + /// name: CompanyOwnerName + /// + /// + /// + /// The lambda expression to be converted + /// IPropertyMetadata when successful, IFullPropertyMetadata if setter is available. Returns default when unsuccessful. + public static IPropertyMetadata? GetPropertyMetadata(Expression> expression) + => GetPropertyMetadata((LambdaExpression)expression); + + /// + /// Converts a given LambdaExpression containing MemberExpressions to getters and setters, and the name of each nested object plus the name of the property. + /// + /// (Person x) => x.Company.Owner.Name becomes: + /// getter: (object x) => (object)(((Person) x).get_Company().get_Owner().get_Name()) + /// setter: (object x, object y) => ((Person) x).get_Company().get_Owner().set_Name((string)y) + /// objectType: Person + /// propertyType: string + /// name: CompanyOwnerName + /// + /// + /// + /// The lambda expression to be converted + /// IFullPropertyMetadata + /// Failed to convert expression to IFullPropertyMetadata + public static IFullPropertyMetadata GetFullPropertyMetadata(Expression> expression) + => GetPropertyMetadata(expression) as IFullPropertyMetadata ?? throw new InvalidOperationException($"Could not convert expression to {nameof(IFullPropertyMetadata)}."); + + private static Func? ConvertToGetterViaMethod(ParameterExpression parameterT, MethodInfo getValueMethod, Expression instanceExpression) + { + try { - try - { - var getExpression = Expression.Lambda>( - Expression.Convert(Expression.Call(instanceExpression, getValueMethod), typeof(object)), - parameterT - ); + var getExpression = Expression.Lambda>( + Expression.Convert(Expression.Call(instanceExpression, getValueMethod), typeof(object)), + parameterT + ); - return getExpression.Compile(); - } - catch - { - return default; - } + return getExpression.Compile(); } + catch + { + return default; + } + } - private static Func? ConvertToGetterViaLambda(ParameterExpression parameterT, LambdaExpression lambdaExpression, Expression parameterExpression) + private static Func? ConvertToGetterViaLambda(ParameterExpression parameterT, LambdaExpression lambdaExpression, Expression parameterExpression) + { + try { - try - { - var getExpression = Expression.Lambda>( - Expression.Convert( - Expression.Invoke(lambdaExpression, parameterExpression), - typeof(object)), - parameterT); + var getExpression = Expression.Lambda>( + Expression.Convert( + Expression.Invoke(lambdaExpression, parameterExpression), + typeof(object)), + parameterT); - return getExpression.Compile(); - } - catch - { - return default; - } + return getExpression.Compile(); } + catch + { + return default; + } + } - private static Func? ConvertToStringGetterViaLambda(ParameterExpression parameterT, LambdaExpression lambdaExpression, Expression parameterExpression) + private static Func? ConvertToStringGetterViaLambda(ParameterExpression parameterT, LambdaExpression lambdaExpression, Expression parameterExpression) + { + if (lambdaExpression.ReturnType != typeof(string)) { - if (lambdaExpression.ReturnType != typeof(string)) - { - return default; - } + return default; + } - try - { - var getExpression = Expression.Lambda>( - Expression.Coalesce( - Expression.Invoke(lambdaExpression, parameterExpression), - Expression.Constant(string.Empty)), - parameterT); + try + { + var getExpression = Expression.Lambda>( + Expression.Coalesce( + Expression.Invoke(lambdaExpression, parameterExpression), + Expression.Constant(string.Empty)), + parameterT); - return getExpression.Compile(); - } - catch - { - return default; - } + return getExpression.Compile(); + } + catch + { + return default; } + } - private static Action? ConvertToSetter(ParameterExpression parameterT, ParameterExpression parameterTProperty, MethodInfo setValueMethod, Expression valueToType, Expression instanceExpression) + private static Action? ConvertToSetter(ParameterExpression parameterT, ParameterExpression parameterTProperty, MethodInfo setValueMethod, Expression valueToType, Expression instanceExpression) + { + try { - try - { - var setExpression = Expression.Lambda>( - Expression.Call(instanceExpression, setValueMethod, valueToType), - parameterT, - parameterTProperty - ); + var setExpression = Expression.Lambda>( + Expression.Call(instanceExpression, setValueMethod, valueToType), + parameterT, + parameterTProperty + ); - return setExpression.Compile(); - } - catch - { - return default; - } + return setExpression.Compile(); } - - private static string GetFingerprint(Expression expression) + catch { - var fingerprint = expression switch - { - LambdaExpression lambda => $"{GetFingerprint(lambda.Body)}{lambda.Body.Type}", - MethodCallExpression call => $"{string.Join("", call.Arguments.Select(x => GetFingerprint(x)))}{call.Type}", - ParameterExpression param => $"{param.IsByRef}{param.Type}", - MemberExpression member => $"{member.Member.Name}{(member.Expression == null ? "" : GetFingerprint(member.Expression))}", - _ => expression.Type.ToString(), - }; - - return fingerprint.ToSha256Base64String(); + return default; } } + + private static string GetFingerprint(Expression expression) + { + var fingerprint = expression switch + { + LambdaExpression lambda => $"{GetFingerprint(lambda.Body)}{lambda.Body.Type}", + MethodCallExpression call => $"{string.Join("", call.Arguments.Select(x => GetFingerprint(x)))}{call.Type}", + ParameterExpression param => $"{param.IsByRef}{param.Type}", + MemberExpression member => $"{member.Member.Name}{(member.Expression == null ? "" : GetFingerprint(member.Expression))}", + _ => expression.Type.ToString(), + }; + + return fingerprint.ToSha256Base64String(); + } } diff --git a/src/RapidCMS.Core/Helpers/UriHelper.cs b/src/RapidCMS.Core/Helpers/UriHelper.cs index ee001f06..d5ace2d6 100644 --- a/src/RapidCMS.Core/Helpers/UriHelper.cs +++ b/src/RapidCMS.Core/Helpers/UriHelper.cs @@ -2,19 +2,18 @@ using System.Web; using RapidCMS.Core.Extensions; -namespace RapidCMS.Core.Helpers +namespace RapidCMS.Core.Helpers; + +internal static class UriHelper { - internal static class UriHelper - { - public static string CombinePath(params string?[] elements) - => string.Join("/", elements.SelectNotNull(x => x)); + public static string CombinePath(params string?[] elements) + => string.Join("/", elements.SelectNotNull(x => x)); - public static string CombineQueryString(params (string key, string? value)[] elements) - => string.Join("&", elements - .Where(x => !string.IsNullOrWhiteSpace(x.value)) - .Select(x => $"{x.key}={HttpUtility.UrlEncode(x.value)}")) - is string query && !string.IsNullOrWhiteSpace(query) - ? $"?{query}" - : ""; - } + public static string CombineQueryString(params (string key, string? value)[] elements) + => string.Join("&", elements + .Where(x => !string.IsNullOrWhiteSpace(x.value)) + .Select(x => $"{x.key}={HttpUtility.UrlEncode(x.value)}")) + is string query && !string.IsNullOrWhiteSpace(query) + ? $"?{query}" + : ""; } diff --git a/src/RapidCMS.Core/Interactions/ButtonInteraction.cs b/src/RapidCMS.Core/Interactions/ButtonInteraction.cs index 16a0636c..e328ede1 100644 --- a/src/RapidCMS.Core/Interactions/ButtonInteraction.cs +++ b/src/RapidCMS.Core/Interactions/ButtonInteraction.cs @@ -9,96 +9,95 @@ using RapidCMS.Core.Forms; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Interactions +namespace RapidCMS.Core.Interactions; + +internal class ButtonInteraction : IButtonInteraction { - internal class ButtonInteraction : IButtonInteraction + private readonly ISetupResolver _collectionResolver; + private readonly IButtonActionHandlerResolver _buttonActionHandlerResolver; + private readonly IAuthService _authService; + + public ButtonInteraction( + ISetupResolver collectionResolver, + IButtonActionHandlerResolver buttonActionHandlerResolver, + IAuthService authService) { - private readonly ISetupResolver _collectionResolver; - private readonly IButtonActionHandlerResolver _buttonActionHandlerResolver; - private readonly IAuthService _authService; - - public ButtonInteraction( - ISetupResolver collectionResolver, - IButtonActionHandlerResolver buttonActionHandlerResolver, - IAuthService authService) - { - _collectionResolver = collectionResolver; - _buttonActionHandlerResolver = buttonActionHandlerResolver; - _authService = authService; - } - - public async Task ValidateButtonInteractionAsync(IEditorButtonInteractionRequestModel request) - { - var (handler, button) = await FindButtonHandlerAsync(request.EditContext.CollectionAlias, request.ActionId); - - await _authService.EnsureAuthorizedUserAsync(request.EditContext, button); + _collectionResolver = collectionResolver; + _buttonActionHandlerResolver = buttonActionHandlerResolver; + _authService = authService; + } - if (handler.RequiresValidForm(button, request.EditContext) && !await request.EditContext.IsValidAsync()) - { - throw new InvalidEntityException(); - } + public async Task ValidateButtonInteractionAsync(IEditorButtonInteractionRequestModel request) + { + var (handler, button) = await FindButtonHandlerAsync(request.EditContext.CollectionAlias, request.ActionId); - var context = new ButtonContext(request.EditContext.Parent, request.CustomData); + await _authService.EnsureAuthorizedUserAsync(request.EditContext, button); - return await handler.ButtonClickBeforeRepositoryActionAsync(button, request.EditContext, context); + if (handler.RequiresValidForm(button, request.EditContext) && !await request.EditContext.IsValidAsync()) + { + throw new InvalidEntityException(); } - public async Task CompleteButtonInteractionAsync(IEditorButtonInteractionRequestModel request) - { - var (handler, button) = await FindButtonHandlerAsync(request.EditContext.CollectionAlias, request.ActionId); - - var context = new ButtonContext(request.EditContext.Parent, request.CustomData); + var context = new ButtonContext(request.EditContext.Parent, request.CustomData); - await handler.ButtonClickAfterRepositoryActionAsync(button, request.EditContext, context); - } + return await handler.ButtonClickBeforeRepositoryActionAsync(button, request.EditContext, context); + } - public async Task ValidateButtonInteractionAsync(IEditorInListInteractionRequestModel request) - { - var (handler, button) = await FindButtonHandlerAsync(request.ListContext.CollectionAlias, request.ActionId); + public async Task CompleteButtonInteractionAsync(IEditorButtonInteractionRequestModel request) + { + var (handler, button) = await FindButtonHandlerAsync(request.EditContext.CollectionAlias, request.ActionId); + + var context = new ButtonContext(request.EditContext.Parent, request.CustomData); - await _authService.EnsureAuthorizedUserAsync(request.EditContext, button); + await handler.ButtonClickAfterRepositoryActionAsync(button, request.EditContext, context); + } - if (handler.RequiresValidForm(button, request.EditContext) && !await request.EditContext.IsValidAsync()) - { - throw new InvalidEntityException(); - } + public async Task ValidateButtonInteractionAsync(IEditorInListInteractionRequestModel request) + { + var (handler, button) = await FindButtonHandlerAsync(request.ListContext.CollectionAlias, request.ActionId); - var context = new ButtonContext(request.EditContext.Parent, request.CustomData); + await _authService.EnsureAuthorizedUserAsync(request.EditContext, button); - return await handler.ButtonClickBeforeRepositoryActionAsync(button, request.EditContext, context); + if (handler.RequiresValidForm(button, request.EditContext) && !await request.EditContext.IsValidAsync()) + { + throw new InvalidEntityException(); } - public async Task<(CrudType crudType, EntityVariantSetup? entityVariant)> ValidateButtonInteractionAsync(IListButtonInteractionRequestModel request) - { - var (handler, button) = await FindButtonHandlerAsync(request.ListContext.CollectionAlias, request.ActionId); + var context = new ButtonContext(request.EditContext.Parent, request.CustomData); - // NOTE: this might check too much or reject because of the wrong reasons. - await _authService.EnsureAuthorizedUserAsync(request.ListContext.ProtoEditContext, button); + return await handler.ButtonClickBeforeRepositoryActionAsync(button, request.EditContext, context); + } - var context = new ButtonContext(request.ListContext.Parent, request.CustomData); - return (await handler.ButtonClickBeforeRepositoryActionAsync(button, request.ListContext.ProtoEditContext, context), button.EntityVariant); - } + public async Task<(CrudType crudType, EntityVariantSetup? entityVariant)> ValidateButtonInteractionAsync(IListButtonInteractionRequestModel request) + { + var (handler, button) = await FindButtonHandlerAsync(request.ListContext.CollectionAlias, request.ActionId); - public async Task CompleteButtonInteractionAsync(IListButtonInteractionRequestModel request) - { - var (handler, button) = await FindButtonHandlerAsync(request.ListContext.CollectionAlias, request.ActionId); + // NOTE: this might check too much or reject because of the wrong reasons. + await _authService.EnsureAuthorizedUserAsync(request.ListContext.ProtoEditContext, button); - var context = new ButtonContext(request.ListContext.Parent, request.CustomData); + var context = new ButtonContext(request.ListContext.Parent, request.CustomData); + return (await handler.ButtonClickBeforeRepositoryActionAsync(button, request.ListContext.ProtoEditContext, context), button.EntityVariant); + } - await handler.ButtonClickAfterRepositoryActionAsync(button, request.ListContext.ProtoEditContext, context); - } + public async Task CompleteButtonInteractionAsync(IListButtonInteractionRequestModel request) + { + var (handler, button) = await FindButtonHandlerAsync(request.ListContext.CollectionAlias, request.ActionId); - private async Task<(IButtonActionHandler handler, ButtonSetup button)> FindButtonHandlerAsync(string collectionAlias, string buttonId) - { - var collection = await _collectionResolver.ResolveSetupAsync(collectionAlias); + var context = new ButtonContext(request.ListContext.Parent, request.CustomData); - var button = collection.FindButton(buttonId); - if (button == null) - { - throw new Exception($"Cannot determine which button triggered action for collection {collectionAlias}"); - } + await handler.ButtonClickAfterRepositoryActionAsync(button, request.ListContext.ProtoEditContext, context); + } - return (_buttonActionHandlerResolver.GetButtonActionHandler(button), button); + private async Task<(IButtonActionHandler handler, ButtonSetup button)> FindButtonHandlerAsync(string collectionAlias, string buttonId) + { + var collection = await _collectionResolver.ResolveSetupAsync(collectionAlias); + + var button = collection.FindButton(buttonId); + if (button == null) + { + throw new Exception($"Cannot determine which button triggered action for collection {collectionAlias}"); } + + return (_buttonActionHandlerResolver.GetButtonActionHandler(button), button); } } diff --git a/src/RapidCMS.Core/Interactions/DragInteraction.cs b/src/RapidCMS.Core/Interactions/DragInteraction.cs index 7b5f922e..2d3a9ad3 100644 --- a/src/RapidCMS.Core/Interactions/DragInteraction.cs +++ b/src/RapidCMS.Core/Interactions/DragInteraction.cs @@ -3,79 +3,78 @@ using RapidCMS.Core.Abstractions.Interactions; using RapidCMS.Core.Models.EventArgs; -namespace RapidCMS.Core.Interactions +namespace RapidCMS.Core.Interactions; + +internal class DragInteraction : IDragInteraction { - internal class DragInteraction : IDragInteraction - { - public event EventHandler? DragCompletion; - public event EventHandler? DragStateChange; + public event EventHandler? DragCompletion; + public event EventHandler? DragStateChange; - private string? _draggedId; - private string? _draggedOverId; - private Guid? _endZoneGuid; + private string? _draggedId; + private string? _draggedOverId; + private Guid? _endZoneGuid; - public void DragStart(DragEventArgs args, string id) - { - _draggedId = id; + public void DragStart(DragEventArgs args, string id) + { + _draggedId = id; - _draggedOverId = default; - _endZoneGuid = default; + _draggedOverId = default; + _endZoneGuid = default; - args.DataTransfer.EffectAllowed = "move"; - } + args.DataTransfer.EffectAllowed = "move"; + } - public void DragEnter(DragEventArgs args, string id) + public void DragEnter(DragEventArgs args, string id) + { + if (id == _draggedId) { - if (id == _draggedId) - { - return; - } + return; + } - _draggedOverId = id; - _endZoneGuid = default; + _draggedOverId = id; + _endZoneGuid = default; - DragStateChange?.Invoke(default, new EventArgs()); - } + DragStateChange?.Invoke(default, new EventArgs()); + } - public void EndZoneDragEnter(DragEventArgs args, Guid guid) - { - _draggedOverId = default; - _endZoneGuid = guid; + public void EndZoneDragEnter(DragEventArgs args, Guid guid) + { + _draggedOverId = default; + _endZoneGuid = guid; - DragStateChange?.Invoke(default, new EventArgs()); - } + DragStateChange?.Invoke(default, new EventArgs()); + } - public void DragEnd(DragEventArgs args) + public void DragEnd(DragEventArgs args) + { + if (!string.IsNullOrWhiteSpace(_draggedId) && !string.IsNullOrWhiteSpace(_draggedOverId)) { - if (!string.IsNullOrWhiteSpace(_draggedId) && !string.IsNullOrWhiteSpace(_draggedOverId)) - { - DragCompletion?.Invoke(default, new RowDragEventArgs(_draggedId, _draggedOverId)); - } - else if (!string.IsNullOrWhiteSpace(_draggedId) && _endZoneGuid != null) - { - DragCompletion?.Invoke(default, new RowDragEventArgs(_draggedId, default)); - } - - _draggedId = default; - _draggedOverId = default; - _endZoneGuid = default; - - DragStateChange?.Invoke(default, new EventArgs()); + DragCompletion?.Invoke(default, new RowDragEventArgs(_draggedId, _draggedOverId)); } - - public bool IsDraggedOver(string? id) + else if (!string.IsNullOrWhiteSpace(_draggedId) && _endZoneGuid != null) { - return id != null && _draggedOverId == id; + DragCompletion?.Invoke(default, new RowDragEventArgs(_draggedId, default)); } - public bool IsDragged(string? id) - { - return id != null && _draggedId == id; - } + _draggedId = default; + _draggedOverId = default; + _endZoneGuid = default; - public bool IsDraggedOverEndZone(Guid guid) - { - return _endZoneGuid == guid; - } + DragStateChange?.Invoke(default, new EventArgs()); + } + + public bool IsDraggedOver(string? id) + { + return id != null && _draggedOverId == id; + } + + public bool IsDragged(string? id) + { + return id != null && _draggedId == id; + } + + public bool IsDraggedOverEndZone(Guid guid) + { + return _endZoneGuid == guid; } } diff --git a/src/RapidCMS.Core/Mediators/Mediator.cs b/src/RapidCMS.Core/Mediators/Mediator.cs index 8af995e3..ec70fc10 100644 --- a/src/RapidCMS.Core/Mediators/Mediator.cs +++ b/src/RapidCMS.Core/Mediators/Mediator.cs @@ -4,66 +4,65 @@ using Microsoft.Extensions.Logging; using RapidCMS.Core.Abstractions.Mediators; -namespace RapidCMS.Core.Mediators +namespace RapidCMS.Core.Mediators; + +internal class Mediator : IMediator, IDisposable { - internal class Mediator : IMediator, IDisposable - { - private readonly Dictionary _cache = new(); - private readonly IEnumerable _listeners; - private bool _disposedValue; + private readonly Dictionary _cache = new(); + private readonly IEnumerable _listeners; + private bool _disposedValue; - public Mediator(IEnumerable listeners) + public Mediator(IEnumerable listeners) + { + _listeners = listeners; + foreach (var listener in _listeners) { - _listeners = listeners; - foreach (var listener in _listeners) - { - listener.RegisterListener(this); - } + listener.RegisterListener(this); } + } - public event EventHandler? OnEvent; + public event EventHandler? OnEvent; - public void NotifyEvent(object sender, IMediatorEventArgs @event) - { - _cache[@event.GetType()] = @event; + public void NotifyEvent(object sender, IMediatorEventArgs @event) + { + _cache[@event.GetType()] = @event; - OnEvent?.Invoke(sender, @event); - } + OnEvent?.Invoke(sender, @event); + } - public Task NotifyEventAsync(object sender, IMediatorRequestEventArgs @event) - { - var handler = new MediatorEventHandler(this); + public Task NotifyEventAsync(object sender, IMediatorRequestEventArgs @event) + { + var handler = new MediatorEventHandler(this); - return handler.HandleEventAsync(@event); - } + return handler.HandleEventAsync(@event); + } - public IDisposable RegisterCallback(Func callback) - where TMediatorEventArgs : IMediatorEventArgs - => new MediatorEventFilter(this, callback); + public IDisposable RegisterCallback(Func callback) + where TMediatorEventArgs : IMediatorEventArgs + => new MediatorEventFilter(this, callback); - public TMediatorEventArgs? GetLatestEventArgs() where TMediatorEventArgs : IMediatorEventArgs - => _cache.TryGetValue(typeof(TMediatorEventArgs), out var args) ? (TMediatorEventArgs)args : default; + public TMediatorEventArgs? GetLatestEventArgs() where TMediatorEventArgs : IMediatorEventArgs + => _cache.TryGetValue(typeof(TMediatorEventArgs), out var args) ? (TMediatorEventArgs)args : default; - protected virtual void Dispose(bool disposing) + protected virtual void Dispose(bool disposing) + { + if (!_disposedValue) { - if (!_disposedValue) + if (disposing) { - if (disposing) + foreach (var listener in _listeners) { - foreach (var listener in _listeners) - { - listener.Dispose(); - } + listener.Dispose(); } - - _disposedValue = true; } - } - public void Dispose() - { - Dispose(disposing: true); - GC.SuppressFinalize(this); + _disposedValue = true; } } + + public void Dispose() + { + Dispose(disposing: true); + GC.SuppressFinalize(this); + } } diff --git a/src/RapidCMS.Core/Mediators/MediatorEventFilter.cs b/src/RapidCMS.Core/Mediators/MediatorEventFilter.cs index e01f9a82..3a71ea85 100644 --- a/src/RapidCMS.Core/Mediators/MediatorEventFilter.cs +++ b/src/RapidCMS.Core/Mediators/MediatorEventFilter.cs @@ -2,32 +2,31 @@ using System.Threading.Tasks; using RapidCMS.Core.Abstractions.Mediators; -namespace RapidCMS.Core.Mediators +namespace RapidCMS.Core.Mediators; + +internal class MediatorEventFilter : IDisposable + where TMediatorEventArgs : IMediatorEventArgs { - internal class MediatorEventFilter : IDisposable - where TMediatorEventArgs : IMediatorEventArgs - { - private readonly IMediator _mediator; - private readonly Func _callback; + private readonly IMediator _mediator; + private readonly Func _callback; - public MediatorEventFilter(IMediator mediator, Func callback) - { - _mediator = mediator; - _callback = callback; - _mediator.OnEvent += Mediator_OnEventAsync; - } + public MediatorEventFilter(IMediator mediator, Func callback) + { + _mediator = mediator; + _callback = callback; + _mediator.OnEvent += Mediator_OnEventAsync; + } - private async void Mediator_OnEventAsync(object? sender, IMediatorEventArgs e) + private async void Mediator_OnEventAsync(object? sender, IMediatorEventArgs e) + { + if (e is TMediatorEventArgs typedEventArgs) { - if (e is TMediatorEventArgs typedEventArgs) - { - await _callback.Invoke(sender ?? _mediator, typedEventArgs); - } + await _callback.Invoke(sender ?? _mediator, typedEventArgs); } + } - public void Dispose() - { - _mediator.OnEvent -= Mediator_OnEventAsync; - } + public void Dispose() + { + _mediator.OnEvent -= Mediator_OnEventAsync; } } diff --git a/src/RapidCMS.Core/Mediators/MediatorEventHandler.cs b/src/RapidCMS.Core/Mediators/MediatorEventHandler.cs index 11a64ca8..d013d41a 100644 --- a/src/RapidCMS.Core/Mediators/MediatorEventHandler.cs +++ b/src/RapidCMS.Core/Mediators/MediatorEventHandler.cs @@ -2,38 +2,37 @@ using System.Threading.Tasks; using RapidCMS.Core.Abstractions.Mediators; -namespace RapidCMS.Core.Mediators +namespace RapidCMS.Core.Mediators; + +public class MediatorEventHandler { - public class MediatorEventHandler - { - private readonly TaskCompletionSource _tcs = new TaskCompletionSource(); - private readonly IDisposable _responseHandle; - private readonly IMediator _mediator; - private readonly Guid _handlerId = Guid.NewGuid(); + private readonly TaskCompletionSource _tcs = new TaskCompletionSource(); + private readonly IDisposable _responseHandle; + private readonly IMediator _mediator; + private readonly Guid _handlerId = Guid.NewGuid(); - public MediatorEventHandler(IMediator mediator) - { - _responseHandle = mediator.RegisterCallback>(HandleEventCallbackAsync); - _mediator = mediator; - } + public MediatorEventHandler(IMediator mediator) + { + _responseHandle = mediator.RegisterCallback>(HandleEventCallbackAsync); + _mediator = mediator; + } - public Task HandleEventAsync(IMediatorRequestEventArgs @event) - { - @event.RequestId = _handlerId; + public Task HandleEventAsync(IMediatorRequestEventArgs @event) + { + @event.RequestId = _handlerId; - _mediator.NotifyEvent(this, @event); - return _tcs.Task; - } + _mediator.NotifyEvent(this, @event); + return _tcs.Task; + } - private Task HandleEventCallbackAsync(object sender, IMediatorResponseEventArgs @event) + private Task HandleEventCallbackAsync(object sender, IMediatorResponseEventArgs @event) + { + if (@event.RequestId == _handlerId) { - if (@event.RequestId == _handlerId) - { - _responseHandle.Dispose(); - _tcs.SetResult(@event.Response); - } - - return Task.CompletedTask; + _responseHandle.Dispose(); + _tcs.SetResult(@event.Response); } + + return Task.CompletedTask; } } diff --git a/src/RapidCMS.Core/Mediators/RepositoryMediatorEventConverter.cs b/src/RapidCMS.Core/Mediators/RepositoryMediatorEventConverter.cs index 2da90589..56e10d8d 100644 --- a/src/RapidCMS.Core/Mediators/RepositoryMediatorEventConverter.cs +++ b/src/RapidCMS.Core/Mediators/RepositoryMediatorEventConverter.cs @@ -5,48 +5,47 @@ using RapidCMS.Core.Abstractions.Resolvers; using RapidCMS.Core.Models.EventArgs.Mediators; -namespace RapidCMS.Core.Mediators +namespace RapidCMS.Core.Mediators; + +internal class RepositoryMediatorEventConverter : IMediatorEventListener { - internal class RepositoryMediatorEventConverter : IMediatorEventListener + private IDisposable? _eventHander; + private IMediator? _mediator; + private readonly IRepositoryTypeResolver _repositoryTypeResolver; + private readonly ICollectionAliasResolver _collectionAliasResolver; + + public RepositoryMediatorEventConverter( + IRepositoryTypeResolver repositoryTypeResolver, + ICollectionAliasResolver collectionAliasResolver) { - private IDisposable? _eventHander; - private IMediator? _mediator; - private readonly IRepositoryTypeResolver _repositoryTypeResolver; - private readonly ICollectionAliasResolver _collectionAliasResolver; - - public RepositoryMediatorEventConverter( - IRepositoryTypeResolver repositoryTypeResolver, - ICollectionAliasResolver collectionAliasResolver) - { - _repositoryTypeResolver = repositoryTypeResolver; - _collectionAliasResolver = collectionAliasResolver; - } + _repositoryTypeResolver = repositoryTypeResolver; + _collectionAliasResolver = collectionAliasResolver; + } - public void RegisterListener(IMediator mediator) - { - _mediator = mediator; - _eventHander = mediator.RegisterCallback(ConvertRepositoryEventAsync); - } + public void RegisterListener(IMediator mediator) + { + _mediator = mediator; + _eventHander = mediator.RegisterCallback(ConvertRepositoryEventAsync); + } - private Task ConvertRepositoryEventAsync(object sender, RepositoryEventArgs args) + private Task ConvertRepositoryEventAsync(object sender, RepositoryEventArgs args) + { + if (_mediator != null) { - if (_mediator != null) - { - var repositoryAlias = _repositoryTypeResolver.GetAlias(args.RepositoryType); - var collectionAliases = _collectionAliasResolver.GetAlias(repositoryAlias); + var repositoryAlias = _repositoryTypeResolver.GetAlias(args.RepositoryType); + var collectionAliases = _collectionAliasResolver.GetAlias(repositoryAlias); - foreach (var collection in collectionAliases) - { - _mediator.NotifyEvent(sender, new CollectionRepositoryEventArgs(collection, repositoryAlias, args.ParentPath, args.Id, args.Action)); - } + foreach (var collection in collectionAliases) + { + _mediator.NotifyEvent(sender, new CollectionRepositoryEventArgs(collection, repositoryAlias, args.ParentPath, args.Id, args.Action)); } - - return Task.CompletedTask; } - public void Dispose() - { - _eventHander?.Dispose(); - } + return Task.CompletedTask; + } + + public void Dispose() + { + _eventHander?.Dispose(); } } diff --git a/src/RapidCMS.Core/Models/ApiBridge/EntityModel.cs b/src/RapidCMS.Core/Models/ApiBridge/EntityModel.cs index 9232aab4..cbd651bb 100644 --- a/src/RapidCMS.Core/Models/ApiBridge/EntityModel.cs +++ b/src/RapidCMS.Core/Models/ApiBridge/EntityModel.cs @@ -2,41 +2,40 @@ using System.Collections.Generic; using RapidCMS.Core.Helpers; -namespace RapidCMS.Core.Models.ApiBridge +namespace RapidCMS.Core.Models.ApiBridge; + +public static class EntityModel { - public static class EntityModel + public static EntityModel Create(T entity) { - public static EntityModel Create(T entity) + if (entity == null) { - if (entity == null) - { - throw new ArgumentNullException(nameof(entity)); - } - - return new EntityModel - { - Entity = entity, - VariantAlias = AliasHelper.GetEntityVariantAlias(entity.GetType()) - }; + throw new ArgumentNullException(nameof(entity)); } - public static IEnumerable> Create(IEnumerable entities) + return new EntityModel { - if (entities == null) - { - throw new ArgumentNullException(nameof(entities)); - } - - foreach (var entity in entities) - { - yield return Create(entity); - } - } + Entity = entity, + VariantAlias = AliasHelper.GetEntityVariantAlias(entity.GetType()) + }; } - public class EntityModel + public static IEnumerable> Create(IEnumerable entities) { - public TEntity Entity { get; set; } = default!; - public string VariantAlias { get; set; } = default!; + if (entities == null) + { + throw new ArgumentNullException(nameof(entities)); + } + + foreach (var entity in entities) + { + yield return Create(entity); + } } } + +public class EntityModel +{ + public TEntity Entity { get; set; } = default!; + public string VariantAlias { get; set; } = default!; +} diff --git a/src/RapidCMS.Core/Models/ApiBridge/Request/DeleteModel.cs b/src/RapidCMS.Core/Models/ApiBridge/Request/DeleteModel.cs index 74ad4658..7713860a 100644 --- a/src/RapidCMS.Core/Models/ApiBridge/Request/DeleteModel.cs +++ b/src/RapidCMS.Core/Models/ApiBridge/Request/DeleteModel.cs @@ -1,16 +1,15 @@ using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Models.ApiBridge.Request -{ - public class DeleteModel - { - public DeleteModel() { } +namespace RapidCMS.Core.Models.ApiBridge.Request; - public DeleteModel(IParent? parent) - { - ParentPath = parent?.GetParentPath()?.ToPathString(); - } +public class DeleteModel +{ + public DeleteModel() { } - public string? ParentPath { get; set; } + public DeleteModel(IParent? parent) + { + ParentPath = parent?.GetParentPath()?.ToPathString(); } + + public string? ParentPath { get; set; } } diff --git a/src/RapidCMS.Core/Models/ApiBridge/Request/EditContextModel.cs b/src/RapidCMS.Core/Models/ApiBridge/Request/EditContextModel.cs index 17f1952d..de7fe1c0 100644 --- a/src/RapidCMS.Core/Models/ApiBridge/Request/EditContextModel.cs +++ b/src/RapidCMS.Core/Models/ApiBridge/Request/EditContextModel.cs @@ -4,39 +4,38 @@ using RapidCMS.Core.Abstractions.Forms; using RapidCMS.Core.Helpers; -namespace RapidCMS.Core.Models.ApiBridge.Request +namespace RapidCMS.Core.Models.ApiBridge.Request; + +public class EditContextModel + where TEntity : IEntity { - public class EditContextModel - where TEntity : IEntity + public EditContextModel() { } + + public EditContextModel(IEditContext editContext) { - public EditContextModel() { } + EntityModel = ApiBridge.EntityModel.Create(editContext.Entity); + ParentPath = editContext.Parent?.GetParentPath()?.ToPathString(); - public EditContextModel(IEditContext editContext) + var container = editContext.GetRelationContainer(); + RelationContainer = new RelationContainerModel { - EntityModel = ApiBridge.EntityModel.Create(editContext.Entity); - ParentPath = editContext.Parent?.GetParentPath()?.ToPathString(); - - var container = editContext.GetRelationContainer(); - RelationContainer = new RelationContainerModel + Relations = container.Relations.Select(relation => { - Relations = container.Relations.Select(relation => + return new RelationModel { - return new RelationModel - { - Elements = relation.RelatedElementIds, - PropertyName = relation.Property.PropertyName, - VariantAlias = AliasHelper.GetEntityVariantAlias(relation.RelatedEntityType) - }; - }) - }; - } + Elements = relation.RelatedElementIds, + PropertyName = relation.Property.PropertyName, + VariantAlias = AliasHelper.GetEntityVariantAlias(relation.RelatedEntityType) + }; + }) + }; + } - public EntityModel EntityModel { get; set; } = default!; - public string? ParentPath { get; set; } + public EntityModel EntityModel { get; set; } = default!; + public string? ParentPath { get; set; } - public RelationContainerModel RelationContainer { get; set; } = default!; + public RelationContainerModel RelationContainer { get; set; } = default!; - public IEnumerable<(string propertyName, string variantAlias, IEnumerable elements)> GetRelations() - => RelationContainer.Relations.Select(r => (r.PropertyName, r.VariantAlias, r.Elements)); - } + public IEnumerable<(string propertyName, string variantAlias, IEnumerable elements)> GetRelations() + => RelationContainer.Relations.Select(r => (r.PropertyName, r.VariantAlias, r.Elements)); } diff --git a/src/RapidCMS.Core/Models/ApiBridge/Request/EntityDescriptorModel.cs b/src/RapidCMS.Core/Models/ApiBridge/Request/EntityDescriptorModel.cs index 0db61a44..f00658d9 100644 --- a/src/RapidCMS.Core/Models/ApiBridge/Request/EntityDescriptorModel.cs +++ b/src/RapidCMS.Core/Models/ApiBridge/Request/EntityDescriptorModel.cs @@ -1,9 +1,8 @@ -namespace RapidCMS.Core.Models.ApiBridge.Request +namespace RapidCMS.Core.Models.ApiBridge.Request; + +public class EntityDescriptorModel { - public class EntityDescriptorModel - { - public string? Id { get; set; } - public string? RepositoryAlias { get; set; } - public string? ParentPath { get; set; } - } + public string? Id { get; set; } + public string? RepositoryAlias { get; set; } + public string? ParentPath { get; set; } } diff --git a/src/RapidCMS.Core/Models/ApiBridge/Request/OrderByModel.cs b/src/RapidCMS.Core/Models/ApiBridge/Request/OrderByModel.cs index 2385bcc6..21ed3305 100644 --- a/src/RapidCMS.Core/Models/ApiBridge/Request/OrderByModel.cs +++ b/src/RapidCMS.Core/Models/ApiBridge/Request/OrderByModel.cs @@ -3,22 +3,21 @@ using RapidCMS.Core.Abstractions.Metadata; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Models.ApiBridge.Request +namespace RapidCMS.Core.Models.ApiBridge.Request; + +public class OrderByModel : IOrderBy { - public class OrderByModel : IOrderBy + public OrderByModel(OrderByType type, IPropertyMetadata property) { - public OrderByModel(OrderByType type, IPropertyMetadata property) - { - OrderByType = type; - OrderByExpression = property; - } + OrderByType = type; + OrderByExpression = property; + } - public OrderByType OrderByType { get; private set; } + public OrderByType OrderByType { get; private set; } - public IPropertyMetadata OrderByExpression { get; private set; } + public IPropertyMetadata OrderByExpression { get; private set; } - public IPropertyMetadata? Property => throw new InvalidOperationException("Cannot access this property when using in Api"); + public IPropertyMetadata? Property => throw new InvalidOperationException("Cannot access this property when using in Api"); - public IExpressionMetadata? Expression => throw new InvalidOperationException("Cannot access this property when using in Api"); - } + public IExpressionMetadata? Expression => throw new InvalidOperationException("Cannot access this property when using in Api"); } diff --git a/src/RapidCMS.Core/Models/ApiBridge/Request/OrderModel.cs b/src/RapidCMS.Core/Models/ApiBridge/Request/OrderModel.cs index 38ba9818..3bc5c32f 100644 --- a/src/RapidCMS.Core/Models/ApiBridge/Request/OrderModel.cs +++ b/src/RapidCMS.Core/Models/ApiBridge/Request/OrderModel.cs @@ -1,11 +1,10 @@ using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Models.ApiBridge.Request +namespace RapidCMS.Core.Models.ApiBridge.Request; + +public class OrderModel { - public class OrderModel - { - public string PropertyName { get; set; } = default!; - public string Fingerprint { get; set; } = default!; - public OrderByType OrderByType { get; set; } - } + public string PropertyName { get; set; } = default!; + public string Fingerprint { get; set; } = default!; + public OrderByType OrderByType { get; set; } } diff --git a/src/RapidCMS.Core/Models/ApiBridge/Request/ParentQueryModel.cs b/src/RapidCMS.Core/Models/ApiBridge/Request/ParentQueryModel.cs index 7f7831e9..53a199b1 100644 --- a/src/RapidCMS.Core/Models/ApiBridge/Request/ParentQueryModel.cs +++ b/src/RapidCMS.Core/Models/ApiBridge/Request/ParentQueryModel.cs @@ -3,45 +3,44 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Helpers; -namespace RapidCMS.Core.Models.ApiBridge.Request +namespace RapidCMS.Core.Models.ApiBridge.Request; + +public class ParentQueryModel : QueryModel { - public class ParentQueryModel : QueryModel + public ParentQueryModel() { } + + public ParentQueryModel(IParent? parent) + { + ParentPath = parent?.GetParentPath()?.ToPathString(); + } + + public ParentQueryModel(IParent? parent, IView view) : this(parent) + { + Skip = view.Skip; + Take = view.Take; + SearchTerm = view.SearchTerm; + ActiveTab = view.ActiveTab; + + CollectionAlias = view.CollectionAlias ?? throw new ArgumentNullException(nameof(CollectionAlias)); + + OrderBys = view.ActiveOrderBys + .Select(x => new OrderModel + { + PropertyName = x.OrderByExpression.PropertyName, + Fingerprint = x.OrderByExpression.Fingerprint, + OrderByType = x.OrderByType + }); + } + + public ParentQueryModel(IParent? parent, Type? variantType) : this(parent) + { + VariantAlias = variantType == null ? null : AliasHelper.GetEntityVariantAlias(variantType); + } + + public ParentQueryModel(IParent? parent, Type? variantType, IView query) : this(parent, query) { - public ParentQueryModel() { } - - public ParentQueryModel(IParent? parent) - { - ParentPath = parent?.GetParentPath()?.ToPathString(); - } - - public ParentQueryModel(IParent? parent, IView view) : this(parent) - { - Skip = view.Skip; - Take = view.Take; - SearchTerm = view.SearchTerm; - ActiveTab = view.ActiveTab; - - CollectionAlias = view.CollectionAlias ?? throw new ArgumentNullException(nameof(CollectionAlias)); - - OrderBys = view.ActiveOrderBys - .Select(x => new OrderModel - { - PropertyName = x.OrderByExpression.PropertyName, - Fingerprint = x.OrderByExpression.Fingerprint, - OrderByType = x.OrderByType - }); - } - - public ParentQueryModel(IParent? parent, Type? variantType) : this(parent) - { - VariantAlias = variantType == null ? null : AliasHelper.GetEntityVariantAlias(variantType); - } - - public ParentQueryModel(IParent? parent, Type? variantType, IView query) : this(parent, query) - { - VariantAlias = variantType == null ? null : AliasHelper.GetEntityVariantAlias(variantType); - } - - public string? ParentPath { get; set; } + VariantAlias = variantType == null ? null : AliasHelper.GetEntityVariantAlias(variantType); } + + public string? ParentPath { get; set; } } diff --git a/src/RapidCMS.Core/Models/ApiBridge/Request/QueryModel.cs b/src/RapidCMS.Core/Models/ApiBridge/Request/QueryModel.cs index af8202c3..8bffad30 100644 --- a/src/RapidCMS.Core/Models/ApiBridge/Request/QueryModel.cs +++ b/src/RapidCMS.Core/Models/ApiBridge/Request/QueryModel.cs @@ -5,49 +5,48 @@ using RapidCMS.Core.Helpers; using static RapidCMS.Core.Models.Data.View; -namespace RapidCMS.Core.Models.ApiBridge.Request +namespace RapidCMS.Core.Models.ApiBridge.Request; + +public class QueryModel { - public class QueryModel - { - public int Skip { get; set; } - public int Take { get; set; } - public string? SearchTerm { get; set; } + public int Skip { get; set; } + public int Take { get; set; } + public string? SearchTerm { get; set; } - public int? ActiveTab { get; set; } + public int? ActiveTab { get; set; } - public string? VariantAlias { get; set; } + public string? VariantAlias { get; set; } - public string? CollectionAlias { get; set; } + public string? CollectionAlias { get; set; } - public IEnumerable? OrderBys { get; set; } + public IEnumerable? OrderBys { get; set; } - public IView GetView() => GetView(typeof(TEntity)); + public IView GetView() => GetView(typeof(TEntity)); - public IView GetView(Type entityType) - { - var view = Create(Take, 1 + Skip / Math.Max(1, Take), SearchTerm, ActiveTab); + public IView GetView(Type entityType) + { + var view = Create(Take, 1 + Skip / Math.Max(1, Take), SearchTerm, ActiveTab); + + view.CollectionAlias = CollectionAlias; - view.CollectionAlias = CollectionAlias; + if (OrderBys != null) + { + view.SetOrderBys(OrderBys + .Select(x => + { + var property = PropertyMetadataHelper.GetPropertyMetadata(entityType, x.PropertyName); - if (OrderBys != null) - { - view.SetOrderBys(OrderBys - .Select(x => + if (property == null || x.Fingerprint != property.Fingerprint) { - var property = PropertyMetadataHelper.GetPropertyMetadata(entityType, x.PropertyName); - - if (property == null || x.Fingerprint != property.Fingerprint) - { - throw new InvalidOperationException("The used orderByExpression could not be converted back into IPropertyMetadata. " + - "Only properties are supported for conversion, so x.Property or x.Property.NestedProperty. More complicated expressions cannot " + - "be converted to and from strings easily and will not work with ApiRepositories. If these complex expressions are required, " + - "please convert to ServerSide RapidCMS."); - } - - return new OrderByModel(x.OrderByType, property); - })); - } - return view; + throw new InvalidOperationException("The used orderByExpression could not be converted back into IPropertyMetadata. " + + "Only properties are supported for conversion, so x.Property or x.Property.NestedProperty. More complicated expressions cannot " + + "be converted to and from strings easily and will not work with ApiRepositories. If these complex expressions are required, " + + "please convert to ServerSide RapidCMS."); + } + + return new OrderByModel(x.OrderByType, property); + })); } + return view; } } diff --git a/src/RapidCMS.Core/Models/ApiBridge/Request/RelateModel.cs b/src/RapidCMS.Core/Models/ApiBridge/Request/RelateModel.cs index 09c38977..c7236535 100644 --- a/src/RapidCMS.Core/Models/ApiBridge/Request/RelateModel.cs +++ b/src/RapidCMS.Core/Models/ApiBridge/Request/RelateModel.cs @@ -1,24 +1,23 @@ using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Models.ApiBridge.Request +namespace RapidCMS.Core.Models.ApiBridge.Request; + +public class RelateModel { - public class RelateModel - { - public RelateModel() { } + public RelateModel() { } - public RelateModel(IRelated related, string id) + public RelateModel(IRelated related, string id) + { + Id = id; + Related = new EntityDescriptorModel { - Id = id; - Related = new EntityDescriptorModel - { - RepositoryAlias = related.RepositoryAlias, - Id = related.Entity.Id!, - ParentPath = related.Parent?.GetParentPath()?.ToPathString() - }; - } + RepositoryAlias = related.RepositoryAlias, + Id = related.Entity.Id!, + ParentPath = related.Parent?.GetParentPath()?.ToPathString() + }; + } - public string Id { get; set; } = default!; + public string Id { get; set; } = default!; - public EntityDescriptorModel Related { get; set; } = default!; - } + public EntityDescriptorModel Related { get; set; } = default!; } diff --git a/src/RapidCMS.Core/Models/ApiBridge/Request/RelatedQueryModel.cs b/src/RapidCMS.Core/Models/ApiBridge/Request/RelatedQueryModel.cs index 3886cc0e..57559bf9 100644 --- a/src/RapidCMS.Core/Models/ApiBridge/Request/RelatedQueryModel.cs +++ b/src/RapidCMS.Core/Models/ApiBridge/Request/RelatedQueryModel.cs @@ -1,30 +1,29 @@ using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Models.ApiBridge.Request -{ - public class RelatedQueryModel : QueryModel - { - public RelatedQueryModel() { } +namespace RapidCMS.Core.Models.ApiBridge.Request; - public RelatedQueryModel(IRelated related) - { - Related = new EntityDescriptorModel - { - RepositoryAlias = related.RepositoryAlias, - Id = related.Entity.Id!, - ParentPath = related.Parent?.GetParentPath()?.ToPathString() - }; - } +public class RelatedQueryModel : QueryModel +{ + public RelatedQueryModel() { } - public RelatedQueryModel(IRelated related, IView view) : this(related) + public RelatedQueryModel(IRelated related) + { + Related = new EntityDescriptorModel { - Skip = view.Skip; - Take = view.Take; - SearchTerm = view.SearchTerm; + RepositoryAlias = related.RepositoryAlias, + Id = related.Entity.Id!, + ParentPath = related.Parent?.GetParentPath()?.ToPathString() + }; + } - CollectionAlias = view.CollectionAlias; - } + public RelatedQueryModel(IRelated related, IView view) : this(related) + { + Skip = view.Skip; + Take = view.Take; + SearchTerm = view.SearchTerm; - public EntityDescriptorModel Related { get; set; } = default!; + CollectionAlias = view.CollectionAlias; } + + public EntityDescriptorModel Related { get; set; } = default!; } diff --git a/src/RapidCMS.Core/Models/ApiBridge/Request/RelationContainerModel.cs b/src/RapidCMS.Core/Models/ApiBridge/Request/RelationContainerModel.cs index 01146b1e..713db837 100644 --- a/src/RapidCMS.Core/Models/ApiBridge/Request/RelationContainerModel.cs +++ b/src/RapidCMS.Core/Models/ApiBridge/Request/RelationContainerModel.cs @@ -1,10 +1,9 @@ using System.Collections.Generic; using System.Linq; -namespace RapidCMS.Core.Models.ApiBridge.Request +namespace RapidCMS.Core.Models.ApiBridge.Request; + +public class RelationContainerModel { - public class RelationContainerModel - { - public IEnumerable Relations { get; set; } = Enumerable.Empty(); - } + public IEnumerable Relations { get; set; } = Enumerable.Empty(); } diff --git a/src/RapidCMS.Core/Models/ApiBridge/Request/RelationModel.cs b/src/RapidCMS.Core/Models/ApiBridge/Request/RelationModel.cs index 9e058a3b..6c988a1e 100644 --- a/src/RapidCMS.Core/Models/ApiBridge/Request/RelationModel.cs +++ b/src/RapidCMS.Core/Models/ApiBridge/Request/RelationModel.cs @@ -1,12 +1,11 @@ using System.Collections.Generic; using System.Linq; -namespace RapidCMS.Core.Models.ApiBridge.Request +namespace RapidCMS.Core.Models.ApiBridge.Request; + +public class RelationModel { - public class RelationModel - { - public string VariantAlias { get; set; } = default!; - public string PropertyName { get; set; } = default!; - public IEnumerable Elements { get; set; } = Enumerable.Empty(); - } + public string VariantAlias { get; set; } = default!; + public string PropertyName { get; set; } = default!; + public IEnumerable Elements { get; set; } = Enumerable.Empty(); } diff --git a/src/RapidCMS.Core/Models/ApiBridge/Request/ReorderModel.cs b/src/RapidCMS.Core/Models/ApiBridge/Request/ReorderModel.cs index cf1ea45b..860540fc 100644 --- a/src/RapidCMS.Core/Models/ApiBridge/Request/ReorderModel.cs +++ b/src/RapidCMS.Core/Models/ApiBridge/Request/ReorderModel.cs @@ -1,23 +1,22 @@ using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Models.ApiBridge.Request +namespace RapidCMS.Core.Models.ApiBridge.Request; + +public class ReorderModel { - public class ReorderModel - { - public ReorderModel() { } + public ReorderModel() { } - public ReorderModel(string? beforeId, string id, IParent? parent) + public ReorderModel(string? beforeId, string id, IParent? parent) + { + BeforeId = beforeId; + Subject = new EntityDescriptorModel { - BeforeId = beforeId; - Subject = new EntityDescriptorModel - { - Id = id, - ParentPath = parent?.GetParentPath()?.ToPathString() - }; - } + Id = id, + ParentPath = parent?.GetParentPath()?.ToPathString() + }; + } - public string? BeforeId { get; set; } + public string? BeforeId { get; set; } - public EntityDescriptorModel Subject { get; set; } = default!; - } + public EntityDescriptorModel Subject { get; set; } = default!; } diff --git a/src/RapidCMS.Core/Models/ApiBridge/Request/UploadFileModel.cs b/src/RapidCMS.Core/Models/ApiBridge/Request/UploadFileModel.cs index 82f9843e..9609f36b 100644 --- a/src/RapidCMS.Core/Models/ApiBridge/Request/UploadFileModel.cs +++ b/src/RapidCMS.Core/Models/ApiBridge/Request/UploadFileModel.cs @@ -2,26 +2,25 @@ using System.ComponentModel.DataAnnotations; using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Models.ApiBridge.Request +namespace RapidCMS.Core.Models.ApiBridge.Request; + +public class UploadFileModel : IFileInfo { - public class UploadFileModel : IFileInfo - { - [Required] - public string Name { get; set; } = default!; + [Required] + public string Name { get; set; } = default!; - [Required] - [Range(1, long.MaxValue)] - public long Size { get; set; } + [Required] + [Range(1, long.MaxValue)] + public long Size { get; set; } - [Required] - public string Type { get; set; } = default!; + [Required] + public string Type { get; set; } = default!; - public long? LastModified { get; set; } + public long? LastModified { get; set; } - public DateTime? LastModifiedDate - { - get => DateTimeOffset.FromUnixTimeMilliseconds(LastModified ?? 0).UtcDateTime; - set => LastModified = !value.HasValue ? 0 : new DateTimeOffset(value.Value).ToUnixTimeMilliseconds(); - } + public DateTime? LastModifiedDate + { + get => DateTimeOffset.FromUnixTimeMilliseconds(LastModified ?? 0).UtcDateTime; + set => LastModified = !value.HasValue ? 0 : new DateTimeOffset(value.Value).ToUnixTimeMilliseconds(); } } diff --git a/src/RapidCMS.Core/Models/ApiBridge/Response/EntitiesModel.cs b/src/RapidCMS.Core/Models/ApiBridge/Response/EntitiesModel.cs index 3e16de49..f9d8e1b0 100644 --- a/src/RapidCMS.Core/Models/ApiBridge/Response/EntitiesModel.cs +++ b/src/RapidCMS.Core/Models/ApiBridge/Response/EntitiesModel.cs @@ -1,10 +1,9 @@ using System.Collections.Generic; -namespace RapidCMS.Core.Models.ApiBridge.Response +namespace RapidCMS.Core.Models.ApiBridge.Response; + +public class EntitiesModel { - public class EntitiesModel - { - public IEnumerable> Entities { get; set; } = default!; - public bool MoreDataAvailable { get; set; } - } + public IEnumerable> Entities { get; set; } = default!; + public bool MoreDataAvailable { get; set; } } diff --git a/src/RapidCMS.Core/Models/CompositeValidationResult.cs b/src/RapidCMS.Core/Models/CompositeValidationResult.cs index 01af48c4..cca91017 100644 --- a/src/RapidCMS.Core/Models/CompositeValidationResult.cs +++ b/src/RapidCMS.Core/Models/CompositeValidationResult.cs @@ -1,18 +1,17 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -namespace RapidCMS.Core.Models +namespace RapidCMS.Core.Models; + +public class CompositeValidationResult : ValidationResult { - public class CompositeValidationResult : ValidationResult - { - public string? MemberName { get; private set; } - public List Results { get; private set; } = new List(); + public string? MemberName { get; private set; } + public List Results { get; private set; } = new List(); - public CompositeValidationResult(string errorMessage, string? memberName = default) : base(errorMessage) { MemberName = memberName; } + public CompositeValidationResult(string errorMessage, string? memberName = default) : base(errorMessage) { MemberName = memberName; } - public void AddResult(ValidationResult validationResult) - { - Results.Add(validationResult); - } + public void AddResult(ValidationResult validationResult) + { + Results.Add(validationResult); } } diff --git a/src/RapidCMS.Core/Models/Config/Api/ApiAdvancedConfig.cs b/src/RapidCMS.Core/Models/Config/Api/ApiAdvancedConfig.cs index 854eb9c2..949aff92 100644 --- a/src/RapidCMS.Core/Models/Config/Api/ApiAdvancedConfig.cs +++ b/src/RapidCMS.Core/Models/Config/Api/ApiAdvancedConfig.cs @@ -1,9 +1,8 @@ using RapidCMS.Core.Abstractions.Config; -namespace RapidCMS.Core.Models.Config.Api +namespace RapidCMS.Core.Models.Config.Api; + +internal class ApiAdvancedConfig : IAdvancedApiConfig { - internal class ApiAdvancedConfig : IAdvancedApiConfig - { - public bool RemoveDataAnnotationEntityValidator { get; set; } - } + public bool RemoveDataAnnotationEntityValidator { get; set; } } diff --git a/src/RapidCMS.Core/Models/Config/Api/ApiConfig.cs b/src/RapidCMS.Core/Models/Config/Api/ApiConfig.cs index f75bf8e3..ff794cb9 100644 --- a/src/RapidCMS.Core/Models/Config/Api/ApiConfig.cs +++ b/src/RapidCMS.Core/Models/Config/Api/ApiConfig.cs @@ -10,118 +10,117 @@ using RapidCMS.Core.Helpers; using RapidCMS.Repositories.ApiBridge; -namespace RapidCMS.Core.Models.Config.Api +namespace RapidCMS.Core.Models.Config.Api; + +internal class ApiConfig : IApiConfig { - internal class ApiConfig : IApiConfig + internal ApiAdvancedConfig AdvancedConfig { get; set; } = new ApiAdvancedConfig(); + + internal bool AllowAnonymousUsage { get; set; } = false; + internal List Repositories { get; set; } = new List(); + internal List DataViews { get; set; } = new List(); + internal List FileUploadHandlers { get; set; } = new List(); + internal List<(string entity, ValidationConfig validation)> EntityValidationConfig { get; set; } = new List<(string, ValidationConfig)>(); + + IEnumerable IApiConfig.Repositories => Repositories; + IEnumerable IApiConfig.DataViews => DataViews; + IEnumerable IApiConfig.FileUploadHandlers => FileUploadHandlers; + + public IAdvancedApiConfig Advanced => AdvancedConfig; + + public IApiConfig AllowAnonymousUser() { - internal ApiAdvancedConfig AdvancedConfig { get; set; } = new ApiAdvancedConfig(); + AllowAnonymousUsage = true; + return this; + } - internal bool AllowAnonymousUsage { get; set; } = false; - internal List Repositories { get; set; } = new List(); - internal List DataViews { get; set; } = new List(); - internal List FileUploadHandlers { get; set; } = new List(); - internal List<(string entity, ValidationConfig validation)> EntityValidationConfig { get; set; } = new List<(string, ValidationConfig)>(); + public IApiConfig RegisterFileUploadHandler() where THandler : IFileUploadHandler + { + FileUploadHandlers.Add(new FileUploadHandlerConfig + { + Alias = AliasHelper.GetFileUploaderAlias(typeof(THandler)), + HandlerType = typeof(THandler) + }); - IEnumerable IApiConfig.Repositories => Repositories; - IEnumerable IApiConfig.DataViews => DataViews; - IEnumerable IApiConfig.FileUploadHandlers => FileUploadHandlers; + return this; + } - public IAdvancedApiConfig Advanced => AdvancedConfig; + public IApiRepositoryConfig RegisterRepository() + where TEntity : class, IEntity + where TRepository : IRepository + { + var fullType = typeof(ApiRepository); + var alias = AliasHelper.GetRepositoryAlias(fullType); - public IApiConfig AllowAnonymousUser() + if (Repositories.Any(x => x.Alias == alias)) { - AllowAnonymousUsage = true; - return this; + throw new NotUniqueException(nameof(TRepository)); } - public IApiConfig RegisterFileUploadHandler() where THandler : IFileUploadHandler + var config = new ApiRepositoryConfig { - FileUploadHandlers.Add(new FileUploadHandlerConfig - { - Alias = AliasHelper.GetFileUploaderAlias(typeof(THandler)), - HandlerType = typeof(THandler) - }); + Alias = alias, + EntityType = typeof(TEntity), + RepositoryType = typeof(TRepository), + ApiRepositoryType = fullType + }; + Repositories.Add(config); + return config; + } - return this; - } + public IApiRepositoryConfig RegisterRepository() + where TEntity : class, IEntity + where TMappedEntity : class + where TRepository : IRepository + { + var fullType = typeof(ApiMappedRepository); + var alias = AliasHelper.GetRepositoryAlias(fullType); - public IApiRepositoryConfig RegisterRepository() - where TEntity : class, IEntity - where TRepository : IRepository + if (Repositories.Any(x => x.Alias == alias)) { - var fullType = typeof(ApiRepository); - var alias = AliasHelper.GetRepositoryAlias(fullType); - - if (Repositories.Any(x => x.Alias == alias)) - { - throw new NotUniqueException(nameof(TRepository)); - } - - var config = new ApiRepositoryConfig - { - Alias = alias, - EntityType = typeof(TEntity), - RepositoryType = typeof(TRepository), - ApiRepositoryType = fullType - }; - Repositories.Add(config); - return config; + throw new NotUniqueException(nameof(TRepository)); } - public IApiRepositoryConfig RegisterRepository() - where TEntity : class, IEntity - where TMappedEntity : class - where TRepository : IRepository + var config = new ApiRepositoryConfig { - var fullType = typeof(ApiMappedRepository); - var alias = AliasHelper.GetRepositoryAlias(fullType); - - if (Repositories.Any(x => x.Alias == alias)) - { - throw new NotUniqueException(nameof(TRepository)); - } - - var config = new ApiRepositoryConfig - { - Alias = alias, - EntityType = typeof(TEntity), - DatabaseType = typeof(TMappedEntity), - RepositoryType = typeof(TRepository), - ApiRepositoryType = fullType - }; - Repositories.Add(config); - return config; - } + Alias = alias, + EntityType = typeof(TEntity), + DatabaseType = typeof(TMappedEntity), + RepositoryType = typeof(TRepository), + ApiRepositoryType = fullType + }; + Repositories.Add(config); + return config; + } - public IApiConfig RegisterDataViewBuilder(string collectionAlias) - where TDataViewBuilder : IDataViewBuilder + public IApiConfig RegisterDataViewBuilder(string collectionAlias) + where TDataViewBuilder : IDataViewBuilder + { + if (DataViews.Any(x => x.Alias == collectionAlias)) { - if (DataViews.Any(x => x.Alias == collectionAlias)) - { - throw new NotUniqueException(nameof(collectionAlias)); - } - - DataViews.Add(new ApiDataViewBuilderConfig - { - Alias = collectionAlias, - DataViewBuilder = typeof(TDataViewBuilder) - }); - - return this; + throw new NotUniqueException(nameof(collectionAlias)); } - public IApiConfig RegisterEntityValidator(object? config = default) - where TEntity : IEntity - where TEntityValidator : IEntityValidator + DataViews.Add(new ApiDataViewBuilderConfig { - EntityValidationConfig.Add((AliasHelper.GetEntityVariantAlias(typeof(TEntity)), new ValidationConfig(typeof(TEntityValidator), config))); + Alias = collectionAlias, + DataViewBuilder = typeof(TDataViewBuilder) + }); - foreach (var subType in typeof(TEntity).GetSubTypes()) - { - EntityValidationConfig.Add((AliasHelper.GetEntityVariantAlias(subType), new ValidationConfig(typeof(TEntityValidator), config))); - } + return this; + } + + public IApiConfig RegisterEntityValidator(object? config = default) + where TEntity : IEntity + where TEntityValidator : IEntityValidator + { + EntityValidationConfig.Add((AliasHelper.GetEntityVariantAlias(typeof(TEntity)), new ValidationConfig(typeof(TEntityValidator), config))); - return this; + foreach (var subType in typeof(TEntity).GetSubTypes()) + { + EntityValidationConfig.Add((AliasHelper.GetEntityVariantAlias(subType), new ValidationConfig(typeof(TEntityValidator), config))); } + + return this; } } diff --git a/src/RapidCMS.Core/Models/Config/Api/ApiDataViewBuilderConfig.cs b/src/RapidCMS.Core/Models/Config/Api/ApiDataViewBuilderConfig.cs index c8690b53..e6be631b 100644 --- a/src/RapidCMS.Core/Models/Config/Api/ApiDataViewBuilderConfig.cs +++ b/src/RapidCMS.Core/Models/Config/Api/ApiDataViewBuilderConfig.cs @@ -1,12 +1,11 @@ using System; using RapidCMS.Core.Abstractions.Config; -namespace RapidCMS.Core.Models.Config.Api +namespace RapidCMS.Core.Models.Config.Api; + +internal class ApiDataViewBuilderConfig : IApiDataViewBuilderConfig { - internal class ApiDataViewBuilderConfig : IApiDataViewBuilderConfig - { - public string Alias { get; set; } = default!; + public string Alias { get; set; } = default!; - public Type DataViewBuilder { get; set; } = default!; - } + public Type DataViewBuilder { get; set; } = default!; } diff --git a/src/RapidCMS.Core/Models/Config/Api/ApiRepositoryConfig.cs b/src/RapidCMS.Core/Models/Config/Api/ApiRepositoryConfig.cs index 0857f8c9..d2bcbd17 100644 --- a/src/RapidCMS.Core/Models/Config/Api/ApiRepositoryConfig.cs +++ b/src/RapidCMS.Core/Models/Config/Api/ApiRepositoryConfig.cs @@ -1,14 +1,13 @@ using System; using RapidCMS.Core.Abstractions.Config; -namespace RapidCMS.Core.Models.Config.Api +namespace RapidCMS.Core.Models.Config.Api; + +internal class ApiRepositoryConfig : IApiRepositoryConfig { - internal class ApiRepositoryConfig : IApiRepositoryConfig - { - public string Alias { get; set; } = default!; - public Type EntityType { get; set; } = default!; - public Type? DatabaseType { get; set; } - public Type RepositoryType { get; set; } = default!; - public Type ApiRepositoryType { get; set; } = default!; - } + public string Alias { get; set; } = default!; + public Type EntityType { get; set; } = default!; + public Type? DatabaseType { get; set; } + public Type RepositoryType { get; set; } = default!; + public Type ApiRepositoryType { get; set; } = default!; } diff --git a/src/RapidCMS.Core/Models/Config/Api/FileUploadHandlerConfig.cs b/src/RapidCMS.Core/Models/Config/Api/FileUploadHandlerConfig.cs index de5ec528..0bdf4825 100644 --- a/src/RapidCMS.Core/Models/Config/Api/FileUploadHandlerConfig.cs +++ b/src/RapidCMS.Core/Models/Config/Api/FileUploadHandlerConfig.cs @@ -1,11 +1,10 @@ using System; using RapidCMS.Core.Abstractions.Config; -namespace RapidCMS.Core.Models.Config.Api +namespace RapidCMS.Core.Models.Config.Api; + +internal class FileUploadHandlerConfig : IFileUploadHandlerConfig { - internal class FileUploadHandlerConfig : IFileUploadHandlerConfig - { - public string Alias { get; set; } = default!; - public Type HandlerType { get; set; } = default!; - } + public string Alias { get; set; } = default!; + public Type HandlerType { get; set; } = default!; } diff --git a/src/RapidCMS.Core/Models/Config/ButtonConfig.cs b/src/RapidCMS.Core/Models/Config/ButtonConfig.cs index bef87cfd..ecab0be6 100644 --- a/src/RapidCMS.Core/Models/Config/ButtonConfig.cs +++ b/src/RapidCMS.Core/Models/Config/ButtonConfig.cs @@ -2,24 +2,23 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Models.Config +namespace RapidCMS.Core.Models.Config; + +internal class ButtonConfig { - internal class ButtonConfig - { - internal string Id { get; set; } = Guid.NewGuid().ToString(); - internal string? Label { get; set; } - internal string? Icon { get; set; } - internal bool IsPrimary { get; set; } - internal Func? IsVisible { get; private set; } + internal string Id { get; set; } = Guid.NewGuid().ToString(); + internal string? Label { get; set; } + internal string? Icon { get; set; } + internal bool IsPrimary { get; set; } + internal Func? IsVisible { get; private set; } - internal ButtonConfig VisibleWhen(Func? predicate) + internal ButtonConfig VisibleWhen(Func? predicate) + { + if (predicate != null) { - if (predicate != null) - { - IsVisible = (entity, state) => predicate.Invoke((IEntity)entity, state); - } - - return this; + IsVisible = (entity, state) => predicate.Invoke((IEntity)entity, state); } + + return this; } } diff --git a/src/RapidCMS.Core/Models/Config/CmsAdvancedConfig.cs b/src/RapidCMS.Core/Models/Config/CmsAdvancedConfig.cs index 1a59aadc..3f7d97d4 100644 --- a/src/RapidCMS.Core/Models/Config/CmsAdvancedConfig.cs +++ b/src/RapidCMS.Core/Models/Config/CmsAdvancedConfig.cs @@ -1,10 +1,9 @@ using RapidCMS.Core.Abstractions.Config; -namespace RapidCMS.Core.Models.Config +namespace RapidCMS.Core.Models.Config; + +internal class CmsAdvancedConfig : IAdvancedCmsConfig { - internal class CmsAdvancedConfig : IAdvancedCmsConfig - { - public int SemaphoreCount { get; set; } - public bool RemoveDataAnnotationEntityValidator { get; set; } - } + public int SemaphoreCount { get; set; } + public bool RemoveDataAnnotationEntityValidator { get; set; } } diff --git a/src/RapidCMS.Core/Models/Config/CmsConfig.cs b/src/RapidCMS.Core/Models/Config/CmsConfig.cs index a4e3d829..0a720e36 100644 --- a/src/RapidCMS.Core/Models/Config/CmsConfig.cs +++ b/src/RapidCMS.Core/Models/Config/CmsConfig.cs @@ -8,182 +8,188 @@ using RapidCMS.Core.Exceptions; using RapidCMS.Core.Extensions; -namespace RapidCMS.Core.Models.Config +namespace RapidCMS.Core.Models.Config; + +internal class CmsConfig : ICmsConfig { - internal class CmsConfig : ICmsConfig + internal CmsAdvancedConfig AdvancedConfig { get; set; } = new CmsAdvancedConfig { - internal CmsAdvancedConfig AdvancedConfig { get; set; } = new CmsAdvancedConfig - { - SemaphoreCount = 1 - }; - internal string SiteName { get; set; } = "RapidCMS"; - internal bool IsDevelopment { get; set; } - internal bool AllowAnonymousUsage { get; set; } = false; + SemaphoreCount = 1 + }; + internal string SiteName { get; set; } = "RapidCMS"; + internal bool IsDevelopment { get; set; } + internal bool AllowAnonymousUsage { get; set; } = false; - public string Alias => "__root"; - public string Name => "Root"; - public string? ParentAlias => default; - public bool Recursive => throw new NotImplementedException(); - Type ICollectionConfig.RepositoryType => throw new NotImplementedException(); + public string Alias => "__root"; + public string Name => "Root"; + public string? ParentAlias => default; + public bool Recursive => throw new NotImplementedException(); + Type ICollectionConfig.RepositoryType => throw new NotImplementedException(); - internal static List CollectionAliases = new List(); + internal static List CollectionAliases = new List(); - internal CustomTypeRegistrationConfig? CustomLoginScreenRegistration { get; set; } - internal CustomTypeRegistrationConfig? CustomLoginStatusRegistration { get; set; } - internal CustomTypeRegistrationConfig? CustomLandingPageRegistration { get; set; } + internal CustomTypeRegistrationConfig? CustomLoginScreenRegistration { get; set; } + internal CustomTypeRegistrationConfig? CustomLoginStatusRegistration { get; set; } + internal CustomTypeRegistrationConfig? CustomLandingPageRegistration { get; set; } - IEnumerable ICollectionConfig.CollectionsAndPages => CollectionsAndPages; + IEnumerable ICollectionConfig.CollectionsAndPages => CollectionsAndPages; - IEnumerable ICmsConfig.Plugins => Plugins; - - IEnumerable ICollectionConfig.RepositoryTypes - => CollectionsAndPages.OfType().SelectMany(c => c.RepositoryTypes); + IEnumerable ICmsConfig.Plugins => Plugins; + + IEnumerable ICollectionConfig.RepositoryTypes + => CollectionsAndPages.OfType().SelectMany(c => c.RepositoryTypes); - public List CollectionsAndPages { get; set; } = new List - { - new PageConfig("Dashboard", "apps", "Gray30", "__dashboard") - }; + public List CollectionsAndPages { get; set; } = new List + { + new PageConfig("Dashboard", "apps", "Gray30", "__dashboard") + }; - public List Plugins { get; set; } = new List(); + public List Plugins { get; set; } = new List(); - public IAdvancedCmsConfig Advanced => AdvancedConfig; + public IAdvancedCmsConfig Advanced => AdvancedConfig; - public IPageConfig Dashboard => CollectionsAndPages.OfType().First(); + public IPageConfig Dashboard => CollectionsAndPages.OfType().First(); - public ICmsConfig SetCustomLoginScreen(Type loginType) + public ICmsConfig SetCustomLoginScreen(Type loginType) + { + if (!loginType.IsSameTypeOrDerivedFrom(typeof(ComponentBase))) { - if (!loginType.IsSameTypeOrDerivedFrom(typeof(ComponentBase))) - { - throw new InvalidOperationException($"{nameof(loginType)} must be derived of {nameof(ComponentBase)}."); - } + throw new InvalidOperationException($"{nameof(loginType)} must be derived of {nameof(ComponentBase)}."); + } - CustomLoginScreenRegistration = new CustomTypeRegistrationConfig(loginType); + CustomLoginScreenRegistration = new CustomTypeRegistrationConfig(loginType); - return this; - } + return this; + } - public ICmsConfig SetCustomLoginStatus(Type loginType) + public ICmsConfig SetCustomLoginStatus(Type loginType) + { + if (!loginType.IsSameTypeOrDerivedFrom(typeof(ComponentBase))) { - if (!loginType.IsSameTypeOrDerivedFrom(typeof(ComponentBase))) - { - throw new InvalidOperationException($"{nameof(loginType)} must be derived of {nameof(ComponentBase)}."); - } + throw new InvalidOperationException($"{nameof(loginType)} must be derived of {nameof(ComponentBase)}."); + } - CustomLoginStatusRegistration = new CustomTypeRegistrationConfig(loginType); + CustomLoginStatusRegistration = new CustomTypeRegistrationConfig(loginType); - return this; - } + return this; + } - public ICmsConfig SetEmptyLandingPage(Type loginType) + public ICmsConfig SetEmptyLandingPage(Type loginType) + { + if (!loginType.IsSameTypeOrDerivedFrom(typeof(ComponentBase))) { - if (!loginType.IsSameTypeOrDerivedFrom(typeof(ComponentBase))) - { - throw new InvalidOperationException($"{nameof(loginType)} must be derived of {nameof(ComponentBase)}."); - } + throw new InvalidOperationException($"{nameof(loginType)} must be derived of {nameof(ComponentBase)}."); + } - CustomLandingPageRegistration = new CustomTypeRegistrationConfig(loginType); + CustomLandingPageRegistration = new CustomTypeRegistrationConfig(loginType); - return this; - } + return this; + } - public ICmsConfig SetSiteName(string siteName) - { - SiteName = siteName; + public ICmsConfig SetSiteName(string siteName) + { + SiteName = siteName; - return this; - } + return this; + } - public ICmsConfig AllowAnonymousUser() - { - AllowAnonymousUsage = true; + public ICmsConfig AllowAnonymousUser() + { + AllowAnonymousUsage = true; - return this; - } + return this; + } - public ICollectionConfig AddCollection(string alias, string name, Action> configure) - where TEntity : class, IEntity - where TRepository : IRepository - { - return AddCollection(alias, default, default, name, configure); - } + public ICmsConfig EnableDevelopmentLogging(bool enabled) + { + IsDevelopment = enabled; - public ICollectionConfig AddCollection(string alias, string? icon, string name, Action> configure) - where TEntity : class, IEntity - where TRepository : IRepository - { - return AddCollection(alias, icon, default, name, configure); - } + return this; + } + + public ICollectionConfig AddCollection(string alias, string name, Action> configure) + where TEntity : class, IEntity + where TRepository : IRepository + { + return AddCollection(alias, default, default, name, configure); + } - public ICollectionConfig AddCollection(string alias, string? icon, string? color, string name, Action> configure) - where TEntity : class, IEntity - where TRepository : IRepository + public ICollectionConfig AddCollection(string alias, string? icon, string name, Action> configure) + where TEntity : class, IEntity + where TRepository : IRepository + { + return AddCollection(alias, icon, default, name, configure); + } + + public ICollectionConfig AddCollection(string alias, string? icon, string? color, string name, Action> configure) + where TEntity : class, IEntity + where TRepository : IRepository + { + if (configure == null) { - if (configure == null) - { - throw new ArgumentNullException(nameof(configure)); - } - if (alias != alias.ToUrlFriendlyString()) - { - throw new ArgumentException($"Use lowercase, hyphened strings as alias for collections, '{alias.ToUrlFriendlyString()}' instead of '{alias}'."); - } - if (CollectionAliases.Contains(alias)) - { - throw new NotUniqueException(nameof(alias)); - } - - CollectionAliases.Add(alias); - - var configReceiver = new CollectionConfig( - alias, - default, - icon, - color, - name, - typeof(TRepository), - new EntityVariantConfig(typeof(TEntity).Name, typeof(TEntity))); - - configure.Invoke(configReceiver); - - CollectionsAndPages.Add(configReceiver); - - return configReceiver; + throw new ArgumentNullException(nameof(configure)); } - - public ICmsConfig AddPage(string name, Action configure) + if (alias != alias.ToUrlFriendlyString()) { - return AddPage("Document", name, configure); + throw new ArgumentException($"Use lowercase, hyphened strings as alias for collections, '{alias.ToUrlFriendlyString()}' instead of '{alias}'."); } - - public ICmsConfig AddPage(string icon, string name, Action configure) + if (CollectionAliases.Contains(alias)) { - return AddPage(icon, "Green10", name, configure); + throw new NotUniqueException(nameof(alias)); } - public ICmsConfig AddPage(string icon, string color, string name, Action configure) - { - var alias = name.ToUrlFriendlyString(); + CollectionAliases.Add(alias); - if (CollectionAliases.Contains(alias)) - { - throw new NotUniqueException(nameof(alias)); - } + var configReceiver = new CollectionConfig( + alias, + default, + icon, + color, + name, + typeof(TRepository), + new EntityVariantConfig(typeof(TEntity).Name, typeof(TEntity))); - CollectionAliases.Add(alias); + configure.Invoke(configReceiver); - var page = new PageConfig(name, icon, color, alias); + CollectionsAndPages.Add(configReceiver); - configure.Invoke(page); + return configReceiver; + } - CollectionsAndPages.Add(page); + public ICmsConfig AddPage(string name, Action configure) + { + return AddPage("Document", name, configure); + } - return this; - } + public ICmsConfig AddPage(string icon, string name, Action configure) + { + return AddPage(icon, "Green10", name, configure); + } - ICmsConfig ICmsConfig.AddPlugin() - { - Plugins.Add(typeof(TPlugin)); + public ICmsConfig AddPage(string icon, string color, string name, Action configure) + { + var alias = name.ToUrlFriendlyString(); - return this; + if (CollectionAliases.Contains(alias)) + { + throw new NotUniqueException(nameof(alias)); } + + CollectionAliases.Add(alias); + + var page = new PageConfig(name, icon, color, alias); + + configure.Invoke(page); + + CollectionsAndPages.Add(page); + + return this; + } + + ICmsConfig ICmsConfig.AddPlugin() + { + Plugins.Add(typeof(TPlugin)); + + return this; } } diff --git a/src/RapidCMS.Core/Models/Config/CollectionConfig.cs b/src/RapidCMS.Core/Models/Config/CollectionConfig.cs index 0e10b1fc..692f76a4 100644 --- a/src/RapidCMS.Core/Models/Config/CollectionConfig.cs +++ b/src/RapidCMS.Core/Models/Config/CollectionConfig.cs @@ -14,398 +14,397 @@ using RapidCMS.Core.Models.Config.Convention; using RapidCMS.Core.Models.Data; -namespace RapidCMS.Core.Models.Config +namespace RapidCMS.Core.Models.Config; + +internal class CollectionConfig : ICollectionConfig { - internal class CollectionConfig : ICollectionConfig + protected List _collectionsAndPages = new List(); + + internal CollectionConfig(string alias, string? parentAlias, string? icon, string? color, string name, Type repositoryType, EntityVariantConfig entityVariant) { - protected List _collectionsAndPages = new List(); + Alias = alias ?? throw new ArgumentNullException(nameof(alias)); + ParentAlias = parentAlias; + Icon = icon; + Color = color; + Name = name ?? throw new ArgumentNullException(nameof(name)); + RepositoryType = repositoryType ?? throw new ArgumentNullException(nameof(repositoryType)); + EntityVariant = entityVariant ?? throw new ArgumentNullException(nameof(entityVariant)); + } - internal CollectionConfig(string alias, string? parentAlias, string? icon, string? color, string name, Type repositoryType, EntityVariantConfig entityVariant) - { - Alias = alias ?? throw new ArgumentNullException(nameof(alias)); - ParentAlias = parentAlias; - Icon = icon; - Color = color; - Name = name ?? throw new ArgumentNullException(nameof(name)); - RepositoryType = repositoryType ?? throw new ArgumentNullException(nameof(repositoryType)); - EntityVariant = entityVariant ?? throw new ArgumentNullException(nameof(entityVariant)); - } + public string Alias { get; internal set; } + internal string? Icon { get; set; } + internal string? Color { get; set; } + public string Name { get; set; } - public string Alias { get; internal set; } - internal string? Icon { get; set; } - internal string? Color { get; set; } - public string Name { get; set; } + public Type RepositoryType { get; set; } - public Type RepositoryType { get; set; } + public string? ParentAlias { get; set; } - public string? ParentAlias { get; set; } + public IEnumerable CollectionsAndPages + { + get => _collectionsAndPages.Union(InlineCollections); + } - public IEnumerable CollectionsAndPages + public IEnumerable RepositoryTypes + { + get { - get => _collectionsAndPages.Union(InlineCollections); + var repositoryTypesFromNodeEditor = NodeEditor?.Panes.GetRepositoryTypes() ?? Enumerable.Empty(); + var repositoryTypesFromListEditor = ListEditor?.Panes.GetRepositoryTypes() ?? Enumerable.Empty(); + + return new[] { RepositoryType } + .Union(CollectionsAndPages.OfType() + .SelectMany(x => x.RepositoryTypes)) + .Union(repositoryTypesFromNodeEditor) + .Union(repositoryTypesFromListEditor); } + } - public IEnumerable RepositoryTypes + private IEnumerable InlineCollections + { + get { - get - { - var repositoryTypesFromNodeEditor = NodeEditor?.Panes.GetRepositoryTypes() ?? Enumerable.Empty(); - var repositoryTypesFromListEditor = ListEditor?.Panes.GetRepositoryTypes() ?? Enumerable.Empty(); - - return new[] { RepositoryType } - .Union(CollectionsAndPages.OfType() - .SelectMany(x => x.RepositoryTypes)) - .Union(repositoryTypesFromNodeEditor) - .Union(repositoryTypesFromListEditor); - } - } + var referencedCollections = new[] { + ListEditor?.Panes.SelectMany(x => x.SubCollectionLists.Union(x.RelatedCollectionLists)), + ListView?.Panes.SelectMany(x => x.SubCollectionLists.Union(x.RelatedCollectionLists)), + NodeEditor?.Panes.SelectMany(x => x.SubCollectionLists.Union(x.RelatedCollectionLists)), + NodeView?.Panes.SelectMany(x => x.SubCollectionLists.Union(x.RelatedCollectionLists)), + }; - private IEnumerable InlineCollections - { - get - { - var referencedCollections = new[] { - ListEditor?.Panes.SelectMany(x => x.SubCollectionLists.Union(x.RelatedCollectionLists)), - ListView?.Panes.SelectMany(x => x.SubCollectionLists.Union(x.RelatedCollectionLists)), - NodeEditor?.Panes.SelectMany(x => x.SubCollectionLists.Union(x.RelatedCollectionLists)), - NodeView?.Panes.SelectMany(x => x.SubCollectionLists.Union(x.RelatedCollectionLists)), - }; - - var referencedInlineCollections = referencedCollections - .Where(x => x != null) - .SelectMany(x => x!) - .Where(x => x.RepositoryType != null); - - return referencedInlineCollections - .Select(collection => new CollectionConfig( - collection.CollectionAlias, - Alias, - default, - default, - $"{Name}-{collection.RepositoryType!.Name}", - collection.RepositoryType!, - new EntityVariantConfig(collection.EntityType!.Name, collection.EntityType, default)) - { - ListEditor = collection.ListEditor, - ListView = collection.ListView - }); - } + var referencedInlineCollections = referencedCollections + .Where(x => x != null) + .SelectMany(x => x!) + .Where(x => x.RepositoryType != null); + + return referencedInlineCollections + .Select(collection => new CollectionConfig( + collection.CollectionAlias, + Alias, + default, + default, + $"{Name}-{collection.RepositoryType!.Name}", + collection.RepositoryType!, + new EntityVariantConfig(collection.EntityType!.Name, collection.EntityType, default)) + { + ListEditor = collection.ListEditor, + ListView = collection.ListView + }); } + } + + internal List SubEntityVariants { get; set; } = new List(); + internal EntityVariantConfig EntityVariant { get; set; } - internal List SubEntityVariants { get; set; } = new List(); - internal EntityVariantConfig EntityVariant { get; set; } + internal List DataViews { get; set; } = new List(); + internal Type? DataViewBuilder { get; set; } - internal List DataViews { get; set; } = new List(); - internal Type? DataViewBuilder { get; set; } + internal TreeViewConfig? TreeView { get; set; } + internal ElementConfig? ElementConfig { get; set; } + internal ListConfig? ListView { get; set; } + internal ListConfig? ListEditor { get; set; } + internal NodeConfig? NodeView { get; set; } + internal NodeConfig? NodeEditor { get; set; } - internal TreeViewConfig? TreeView { get; set; } - internal ElementConfig? ElementConfig { get; set; } - internal ListConfig? ListView { get; set; } - internal ListConfig? ListEditor { get; set; } - internal NodeConfig? NodeView { get; set; } - internal NodeConfig? NodeEditor { get; set; } + internal List Validators { get; set; } = new List(); +} - internal List Validators { get; set; } = new List(); +internal class CollectionConfig : CollectionConfig, ICollectionConfig + where TEntity : IEntity +{ + internal CollectionConfig(string alias, string? parentAlias, string? icon, string? color, string name, Type repositoryType, EntityVariantConfig entityVariant) + : base(alias, parentAlias, icon, color, name, repositoryType, entityVariant) + { } - internal class CollectionConfig : CollectionConfig, ICollectionConfig - where TEntity : IEntity + public ICollectionConfig AddEntityVariant(string name, string icon) + where TDerivedEntity : TEntity { - internal CollectionConfig(string alias, string? parentAlias, string? icon, string? color, string name, Type repositoryType, EntityVariantConfig entityVariant) - : base(alias, parentAlias, icon, color, name, repositoryType, entityVariant) - { - } + SubEntityVariants.Add(new EntityVariantConfig(name, typeof(TDerivedEntity), icon)); - public ICollectionConfig AddEntityVariant(string name, string icon) - where TDerivedEntity : TEntity - { - SubEntityVariants.Add(new EntityVariantConfig(name, typeof(TDerivedEntity), icon)); + return this; + } - return this; - } + public ICollectionConfig AddDataView(string label, Expression> queryExpression, Action>? orderByExpressions = null) + { + var dataView = new DataView(DataViews.Count, label, queryExpression); - public ICollectionConfig AddDataView(string label, Expression> queryExpression, Action>? orderByExpressions = null) + if (orderByExpressions != null) { - var dataView = new DataView(DataViews.Count, label, queryExpression); - - if (orderByExpressions != null) - { - var config = new OrderByConfig(); - orderByExpressions.Invoke(config); - dataView.SetOrderBys(config.DefaultOrderBys); - } + var config = new OrderByConfig(); + orderByExpressions.Invoke(config); + dataView.SetOrderBys(config.DefaultOrderBys); + } - DataViews.Add(dataView); + DataViews.Add(dataView); - return this; - } + return this; + } - public ICollectionConfig SetDataViewBuilder() - where TDataViewBuilder : IDataViewBuilder - { - DataViewBuilder = typeof(TDataViewBuilder); + public ICollectionConfig SetDataViewBuilder() + where TDataViewBuilder : IDataViewBuilder + { + DataViewBuilder = typeof(TDataViewBuilder); - return this; - } + return this; + } - public ICollectionConfig SetTreeView(Expression> entityNameExpression, bool showEntities = false, bool showCollections = false) - { - return SetTreeView(default, default, entityNameExpression, showEntities, showCollections); - } + public ICollectionConfig SetTreeView(Expression> entityNameExpression, bool showEntities = false, bool showCollections = false) + { + return SetTreeView(default, default, entityNameExpression, showEntities, showCollections); + } - public ICollectionConfig SetTreeView(EntityVisibilty entityVisibility, Expression>? entityNameExpression = null, bool showEntities = false, bool showCollections = false) - { - return SetTreeView(entityVisibility, default, entityNameExpression, showEntities, showCollections); - } + public ICollectionConfig SetTreeView(EntityVisibilty entityVisibility, Expression>? entityNameExpression = null, bool showEntities = false, bool showCollections = false) + { + return SetTreeView(entityVisibility, default, entityNameExpression, showEntities, showCollections); + } - public ICollectionConfig SetTreeView(EntityVisibilty entityVisibility, CollectionRootVisibility rootVisibility, Expression>? entityNameExpression = null, bool showEntities = false, bool showCollections = false) + public ICollectionConfig SetTreeView(EntityVisibilty entityVisibility, CollectionRootVisibility rootVisibility, Expression>? entityNameExpression = null, bool showEntities = false, bool showCollections = false) + { + TreeView = new TreeViewConfig { - TreeView = new TreeViewConfig - { - EntityVisibilty = entityVisibility, - RootVisibility = rootVisibility, - DefaultOpenEntities = showEntities, - DefaultOpenCollections = showCollections, - Name = entityNameExpression == null ? null : PropertyMetadataHelper.GetExpressionMetadata(entityNameExpression) ?? throw new InvalidExpressionException(nameof(entityNameExpression)) - }; + EntityVisibilty = entityVisibility, + RootVisibility = rootVisibility, + DefaultOpenEntities = showEntities, + DefaultOpenCollections = showCollections, + Name = entityNameExpression == null ? null : PropertyMetadataHelper.GetExpressionMetadata(entityNameExpression) ?? throw new InvalidExpressionException(nameof(entityNameExpression)) + }; - var idExpression = PropertyMetadataHelper.GetPropertyMetadata(x => x.Id) ?? throw new InvalidOperationException("IEntity.Id expression failed"); - ElementConfig ??= new ElementConfig(idExpression, TreeView.Name ?? PropertyMetadataHelper.GetExpressionMetadata(idExpression)); + var idExpression = PropertyMetadataHelper.GetPropertyMetadata(x => x.Id) ?? throw new InvalidOperationException("IEntity.Id expression failed"); + ElementConfig ??= new ElementConfig(idExpression, TreeView.Name ?? PropertyMetadataHelper.GetExpressionMetadata(idExpression)); - return this; - } + return this; + } - public ICollectionConfig SetElementConfiguration(Expression> elementIdExpression, params Expression>[] elementDisplayExpressions) - { - ElementConfig = new ElementConfig( - PropertyMetadataHelper.GetPropertyMetadata(elementIdExpression) ?? throw new InvalidOperationException("Cannot convert elementIdExpression to IExpressionMetadata"), - elementDisplayExpressions.Select(PropertyMetadataHelper.GetExpressionMetadata).OfType().ToArray()); + public ICollectionConfig SetElementConfiguration(Expression> elementIdExpression, params Expression>[] elementDisplayExpressions) + { + ElementConfig = new ElementConfig( + PropertyMetadataHelper.GetPropertyMetadata(elementIdExpression) ?? throw new InvalidOperationException("Cannot convert elementIdExpression to IExpressionMetadata"), + elementDisplayExpressions.Select(PropertyMetadataHelper.GetExpressionMetadata).OfType().ToArray()); - return this; - } + return this; + } - public ICollectionConfig SetListView(Action> configure) - { - var config = new ListViewConfig(); + public ICollectionConfig SetListView(Action> configure) + { + var config = new ListViewConfig(); - configure.Invoke(config); + configure.Invoke(config); - ListView = config; + ListView = config; - return this; - } + return this; + } - public ICollectionConfig SetListEditor(Action> configure) - { - var config = new ListEditorConfig(); + public ICollectionConfig SetListEditor(Action> configure) + { + var config = new ListEditorConfig(); - configure.Invoke(config); + configure.Invoke(config); - ListEditor = config; + ListEditor = config; - return this; - } + return this; + } - public ICollectionConfig SetNodeView(Action> configure) - { - var config = new NodeViewConfig(); + public ICollectionConfig SetNodeView(Action> configure) + { + var config = new NodeViewConfig(); - configure.Invoke(config); + configure.Invoke(config); - NodeView = config; + NodeView = config; - return this; - } + return this; + } - public ICollectionConfig SetNodeEditor(Action> configure) - { - var config = new NodeEditorConfig(); + public ICollectionConfig SetNodeEditor(Action> configure) + { + var config = new NodeEditorConfig(); - configure.Invoke(config); + configure.Invoke(config); - NodeEditor = config; + NodeEditor = config; - return this; - } + return this; + } - public ICollectionConfig AddSubCollection(string alias) - { - var configReceiver = new ReferencedCollectionConfig(alias); + public ICollectionConfig AddSubCollection(string alias) + { + var configReceiver = new ReferencedCollectionConfig(alias); - _collectionsAndPages.Add(configReceiver); + _collectionsAndPages.Add(configReceiver); - return this; - } + return this; + } - public ICollectionConfig AddSubCollection(string alias, string name, Action> configure) - where TSubEntity : class, IEntity - where TRepository : IRepository - => AddSubCollection(alias, default, default, name, configure); + public ICollectionConfig AddSubCollection(string alias, string name, Action> configure) + where TSubEntity : class, IEntity + where TRepository : IRepository + => AddSubCollection(alias, default, default, name, configure); - public ICollectionConfig AddSubCollection(string alias, string? icon, string name, Action> configure) - where TSubEntity : class, IEntity - where TRepository : IRepository - => AddSubCollection(alias, icon, default, name, configure); + public ICollectionConfig AddSubCollection(string alias, string? icon, string name, Action> configure) + where TSubEntity : class, IEntity + where TRepository : IRepository + => AddSubCollection(alias, icon, default, name, configure); - public ICollectionConfig AddSubCollection(string alias, string? icon, string? color, string name, Action> configure) - where TSubEntity : class, IEntity - where TRepository : IRepository + public ICollectionConfig AddSubCollection(string alias, string? icon, string? color, string name, Action> configure) + where TSubEntity : class, IEntity + where TRepository : IRepository + { + if (configure == null) { - if (configure == null) - { - throw new ArgumentNullException(nameof(configure)); - } - if (alias != alias.ToUrlFriendlyString()) - { - throw new ArgumentException($"Use lowercase, hyphened strings as alias for collections, '{alias.ToUrlFriendlyString()}' instead of '{alias}'."); - } - if (CmsConfig.CollectionAliases.Contains(alias)) - { - throw new NotUniqueException(nameof(alias)); - } - - CmsConfig.CollectionAliases.Add(alias); - - var configReceiver = new CollectionConfig( - alias, - Alias, - icon, - color, - name, - typeof(TRepository), - new EntityVariantConfig(typeof(TSubEntity).Name, typeof(TSubEntity))); - - configure.Invoke(configReceiver); - - _collectionsAndPages.Add(configReceiver); - - return configReceiver; + throw new ArgumentNullException(nameof(configure)); } - - public ICollectionConfig AddSelfAsRecursiveCollection() + if (alias != alias.ToUrlFriendlyString()) { - var configReceiver = new ReferencedCollectionConfig(Alias); + throw new ArgumentException($"Use lowercase, hyphened strings as alias for collections, '{alias.ToUrlFriendlyString()}' instead of '{alias}'."); + } + if (CmsConfig.CollectionAliases.Contains(alias)) + { + throw new NotUniqueException(nameof(alias)); + } - ParentAlias = Alias; + CmsConfig.CollectionAliases.Add(alias); - _collectionsAndPages.Add(configReceiver); + var configReceiver = new CollectionConfig( + alias, + Alias, + icon, + color, + name, + typeof(TRepository), + new EntityVariantConfig(typeof(TSubEntity).Name, typeof(TSubEntity))); - return this; - } + configure.Invoke(configReceiver); - public ICollectionDetailPageEditorConfig AddDetailPage(string alias, string name, Action> configure) - where TDetailEntity : IEntity - where TDetailRepository : IRepository - => AddDetailPage(alias, default, default, name, configure); + _collectionsAndPages.Add(configReceiver); - public ICollectionDetailPageEditorConfig AddDetailPage(string alias, string? icon, string name, Action> configure) - where TDetailEntity : IEntity - where TDetailRepository : IRepository - => AddDetailPage(alias, icon, default, name, configure); + return configReceiver; + } - public ICollectionDetailPageEditorConfig AddDetailPage(string alias, string? icon, string? color, string name, Action> configure) - where TDetailEntity : IEntity - where TDetailRepository : IRepository - { - var configReceiver = new DetailPageConfig(alias, Alias, icon, color, name, typeof(TDetailRepository), new EntityVariantConfig(typeof(TDetailEntity).Name, typeof(TDetailEntity))); + public ICollectionConfig AddSelfAsRecursiveCollection() + { + var configReceiver = new ReferencedCollectionConfig(Alias); - configure?.Invoke(configReceiver); + ParentAlias = Alias; - _collectionsAndPages.Add(configReceiver); + _collectionsAndPages.Add(configReceiver); - return configReceiver; - } + return this; + } - public ICollectionConfig ConfigureByConvention(CollectionConvention convention = CollectionConvention.ListViewNodeEditor) - { - if (convention == CollectionConvention.ListView || - convention == CollectionConvention.ListViewNodeView || - convention == CollectionConvention.ListViewNodeEditor) - { - ListView = new ConventionListViewConfig( - canGoToNodeEditor: convention == CollectionConvention.ListViewNodeEditor, - canGoToNodeView: convention == CollectionConvention.ListViewNodeView); - } - - if (convention == CollectionConvention.ListEditor || - convention == CollectionConvention.ListBlockEditor || - convention == CollectionConvention.ListEditorNodeEditor) - { - ListEditor = new ConventionListEditorConfig( - canGoToNodeEditor: convention == CollectionConvention.ListEditorNodeEditor, - convention == CollectionConvention.ListBlockEditor ? ListType.Block : ListType.Table); - } - - if (convention == CollectionConvention.ListViewNodeView) - { - NodeView = new ConventionNodeViewConfig(); - } - - if (convention == CollectionConvention.ListViewNodeEditor || - convention == CollectionConvention.ListEditorNodeEditor) - { - NodeEditor = new ConventionNodeEditorConfig(); - } - - return this; - } + public ICollectionDetailPageEditorConfig AddDetailPage(string alias, string name, Action> configure) + where TDetailEntity : IEntity + where TDetailRepository : IRepository + => AddDetailPage(alias, default, default, name, configure); - public ICollectionConfig AddEntityValidator() where TEntityValidator : IEntityValidator - { - Validators.Add(new ValidationConfig(typeof(TEntityValidator), default)); + public ICollectionDetailPageEditorConfig AddDetailPage(string alias, string? icon, string name, Action> configure) + where TDetailEntity : IEntity + where TDetailRepository : IRepository + => AddDetailPage(alias, icon, default, name, configure); - return this; - } + public ICollectionDetailPageEditorConfig AddDetailPage(string alias, string? icon, string? color, string name, Action> configure) + where TDetailEntity : IEntity + where TDetailRepository : IRepository + { + var configReceiver = new DetailPageConfig(alias, Alias, icon, color, name, typeof(TDetailRepository), new EntityVariantConfig(typeof(TDetailEntity).Name, typeof(TDetailEntity))); - public ICollectionConfig AddEntityValidator(object configuration) where TEntityValidator : IEntityValidator - { - Validators.Add(new ValidationConfig(typeof(TEntityValidator), configuration)); + configure?.Invoke(configReceiver); - return this; - } + _collectionsAndPages.Add(configReceiver); - public ICollectionConfig AddAsyncEntityValidator() where TAsyncEntityValidator : IAsyncEntityValidator - { - Validators.Add(new ValidationConfig(typeof(TAsyncEntityValidator), default)); + return configReceiver; + } - return this; + public ICollectionConfig ConfigureByConvention(CollectionConvention convention = CollectionConvention.ListViewNodeEditor) + { + if (convention == CollectionConvention.ListView || + convention == CollectionConvention.ListViewNodeView || + convention == CollectionConvention.ListViewNodeEditor) + { + ListView = new ConventionListViewConfig( + canGoToNodeEditor: convention == CollectionConvention.ListViewNodeEditor, + canGoToNodeView: convention == CollectionConvention.ListViewNodeView); } - public ICollectionConfig AddAsyncEntityValidator(object configuration) where TAsyncEntityValidator : IAsyncEntityValidator + if (convention == CollectionConvention.ListEditor || + convention == CollectionConvention.ListBlockEditor || + convention == CollectionConvention.ListEditorNodeEditor) { - Validators.Add(new ValidationConfig(typeof(TAsyncEntityValidator), configuration)); - - return this; + ListEditor = new ConventionListEditorConfig( + canGoToNodeEditor: convention == CollectionConvention.ListEditorNodeEditor, + convention == CollectionConvention.ListBlockEditor ? ListType.Block : ListType.Table); } - public ICollectionConfig AddPage(string name, Action configure) + if (convention == CollectionConvention.ListViewNodeView) { - return AddPage("Document", name, configure); + NodeView = new ConventionNodeViewConfig(); } - public ICollectionConfig AddPage(string icon, string name, Action configure) + if (convention == CollectionConvention.ListViewNodeEditor || + convention == CollectionConvention.ListEditorNodeEditor) { - return AddPage(icon, "Green10", name, configure); + NodeEditor = new ConventionNodeEditorConfig(); } - public ICollectionConfig AddPage(string icon, string color, string name, Action configure) - { - var alias = name.ToUrlFriendlyString(); + return this; + } - if (CmsConfig.CollectionAliases.Contains(alias)) - { - throw new NotUniqueException(nameof(alias)); - } + public ICollectionConfig AddEntityValidator() where TEntityValidator : IEntityValidator + { + Validators.Add(new ValidationConfig(typeof(TEntityValidator), default)); - CmsConfig.CollectionAliases.Add(alias); + return this; + } - var page = new PageConfig(name, icon, color, alias); + public ICollectionConfig AddEntityValidator(object configuration) where TEntityValidator : IEntityValidator + { + Validators.Add(new ValidationConfig(typeof(TEntityValidator), configuration)); - configure.Invoke(page); + return this; + } - _collectionsAndPages.Add(page); + public ICollectionConfig AddAsyncEntityValidator() where TAsyncEntityValidator : IAsyncEntityValidator + { + Validators.Add(new ValidationConfig(typeof(TAsyncEntityValidator), default)); + + return this; + } + + public ICollectionConfig AddAsyncEntityValidator(object configuration) where TAsyncEntityValidator : IAsyncEntityValidator + { + Validators.Add(new ValidationConfig(typeof(TAsyncEntityValidator), configuration)); + + return this; + } - return this; + public ICollectionConfig AddPage(string name, Action configure) + { + return AddPage("Document", name, configure); + } + + public ICollectionConfig AddPage(string icon, string name, Action configure) + { + return AddPage(icon, "Green10", name, configure); + } + + public ICollectionConfig AddPage(string icon, string color, string name, Action configure) + { + var alias = name.ToUrlFriendlyString(); + + if (CmsConfig.CollectionAliases.Contains(alias)) + { + throw new NotUniqueException(nameof(alias)); } + + CmsConfig.CollectionAliases.Add(alias); + + var page = new PageConfig(name, icon, color, alias); + + configure.Invoke(page); + + _collectionsAndPages.Add(page); + + return this; } } diff --git a/src/RapidCMS.Core/Models/Config/CollectionListConfig.cs b/src/RapidCMS.Core/Models/Config/CollectionListConfig.cs index 53c7d449..90e0876d 100644 --- a/src/RapidCMS.Core/Models/Config/CollectionListConfig.cs +++ b/src/RapidCMS.Core/Models/Config/CollectionListConfig.cs @@ -1,21 +1,20 @@ using System; -namespace RapidCMS.Core.Models.Config +namespace RapidCMS.Core.Models.Config; + +internal class CollectionListConfig { - internal class CollectionListConfig + internal CollectionListConfig(string collectionAlias) { - internal CollectionListConfig(string collectionAlias) - { - CollectionAlias = collectionAlias ?? throw new ArgumentNullException(nameof(collectionAlias)); - } + CollectionAlias = collectionAlias ?? throw new ArgumentNullException(nameof(collectionAlias)); + } - internal int Index { get; set; } + internal int Index { get; set; } - internal string CollectionAlias { get; set; } + internal string CollectionAlias { get; set; } - internal Type? RepositoryType { get; set; } - internal Type? EntityType { get; set; } - internal ListConfig? ListEditor { get; set; } - internal ListConfig? ListView { get; set; } - } + internal Type? RepositoryType { get; set; } + internal Type? EntityType { get; set; } + internal ListConfig? ListEditor { get; set; } + internal ListConfig? ListView { get; set; } } diff --git a/src/RapidCMS.Core/Models/Config/ConcreteDataProviderRelationConfig.cs b/src/RapidCMS.Core/Models/Config/ConcreteDataProviderRelationConfig.cs index b53782d9..18b54d23 100644 --- a/src/RapidCMS.Core/Models/Config/ConcreteDataProviderRelationConfig.cs +++ b/src/RapidCMS.Core/Models/Config/ConcreteDataProviderRelationConfig.cs @@ -1,15 +1,14 @@ using System; using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Models.Config +namespace RapidCMS.Core.Models.Config; + +internal class ConcreteDataProviderRelationConfig : RelationConfig { - internal class ConcreteDataProviderRelationConfig : RelationConfig + internal ConcreteDataProviderRelationConfig(IDataCollection dataCollection) { - internal ConcreteDataProviderRelationConfig(IDataCollection dataCollection) - { - DataCollection = dataCollection ?? throw new ArgumentNullException(nameof(dataCollection)); - } - - internal IDataCollection DataCollection { get; set; } + DataCollection = dataCollection ?? throw new ArgumentNullException(nameof(dataCollection)); } + + internal IDataCollection DataCollection { get; set; } } diff --git a/src/RapidCMS.Core/Models/Config/Convention/ConventionListEditorConfig.cs b/src/RapidCMS.Core/Models/Config/Convention/ConventionListEditorConfig.cs index be2d4d43..da3a19b1 100644 --- a/src/RapidCMS.Core/Models/Config/Convention/ConventionListEditorConfig.cs +++ b/src/RapidCMS.Core/Models/Config/Convention/ConventionListEditorConfig.cs @@ -1,25 +1,24 @@ using RapidCMS.Core.Abstractions.Config; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Models.Config.Convention +namespace RapidCMS.Core.Models.Config.Convention; + +internal class ConventionListEditorConfig : ListConfig, IIsConventionBased { - internal class ConventionListEditorConfig : ListConfig, IIsConventionBased + public ConventionListEditorConfig(bool canGoToNodeEditor, ListType type) : base(typeof(TEntity)) { - public ConventionListEditorConfig(bool canGoToNodeEditor, ListType type) : base(typeof(TEntity)) - { - Type = type; - CanGoToNodeEditor = canGoToNodeEditor; - } + Type = type; + CanGoToNodeEditor = canGoToNodeEditor; + } - public ListType Type { get; } + public ListType Type { get; } - public bool CanGoToNodeEditor { get; } + public bool CanGoToNodeEditor { get; } - public Features GetFeatures() - { - return Features.CanEdit | - (CanGoToNodeEditor ? Features.CanGoToEdit : Features.None) | - ((Type == ListType.Block) ? Features.IsBlockList : Features.None); - } + public Features GetFeatures() + { + return Features.CanEdit | + (CanGoToNodeEditor ? Features.CanGoToEdit : Features.None) | + ((Type == ListType.Block) ? Features.IsBlockList : Features.None); } } diff --git a/src/RapidCMS.Core/Models/Config/Convention/ConventionListViewConfig.cs b/src/RapidCMS.Core/Models/Config/Convention/ConventionListViewConfig.cs index ad4eace4..38ab2540 100644 --- a/src/RapidCMS.Core/Models/Config/Convention/ConventionListViewConfig.cs +++ b/src/RapidCMS.Core/Models/Config/Convention/ConventionListViewConfig.cs @@ -2,23 +2,22 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Models.Config.Convention +namespace RapidCMS.Core.Models.Config.Convention; + +internal class ConventionListViewConfig : ListConfig, IIsConventionBased + where TEntity : IEntity { - internal class ConventionListViewConfig : ListConfig, IIsConventionBased - where TEntity : IEntity + public ConventionListViewConfig(bool canGoToNodeEditor, bool canGoToNodeView) : base(typeof(TEntity)) { - public ConventionListViewConfig(bool canGoToNodeEditor, bool canGoToNodeView) : base(typeof(TEntity)) - { - CanGoToNodeEditor = canGoToNodeEditor; - CanGoToNodeView = canGoToNodeView; - } + CanGoToNodeEditor = canGoToNodeEditor; + CanGoToNodeView = canGoToNodeView; + } - public bool CanGoToNodeEditor { get; } - public bool CanGoToNodeView { get; } + public bool CanGoToNodeEditor { get; } + public bool CanGoToNodeView { get; } - public Features GetFeatures() - { - return CanGoToNodeEditor ? Features.CanGoToEdit : CanGoToNodeView ? Features.CanGoToView : Features.None; - } - } + public Features GetFeatures() + { + return CanGoToNodeEditor ? Features.CanGoToEdit : CanGoToNodeView ? Features.CanGoToView : Features.None; + } } diff --git a/src/RapidCMS.Core/Models/Config/Convention/ConventionNodeEditorConfig.cs b/src/RapidCMS.Core/Models/Config/Convention/ConventionNodeEditorConfig.cs index 4a8844e2..88e88bdf 100644 --- a/src/RapidCMS.Core/Models/Config/Convention/ConventionNodeEditorConfig.cs +++ b/src/RapidCMS.Core/Models/Config/Convention/ConventionNodeEditorConfig.cs @@ -2,18 +2,17 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Models.Config.Convention +namespace RapidCMS.Core.Models.Config.Convention; + +internal class ConventionNodeEditorConfig : NodeConfig, IIsConventionBased + where TEntity : IEntity { - internal class ConventionNodeEditorConfig : NodeConfig, IIsConventionBased - where TEntity : IEntity - { - public ConventionNodeEditorConfig() : base(typeof(TEntity)) - { - } + public ConventionNodeEditorConfig() : base(typeof(TEntity)) + { + } - public Features GetFeatures() - { - return Features.CanEdit; - } + public Features GetFeatures() + { + return Features.CanEdit; } } diff --git a/src/RapidCMS.Core/Models/Config/Convention/ConventionNodeViewConfig.cs b/src/RapidCMS.Core/Models/Config/Convention/ConventionNodeViewConfig.cs index 7a6ed96f..2ba6e202 100644 --- a/src/RapidCMS.Core/Models/Config/Convention/ConventionNodeViewConfig.cs +++ b/src/RapidCMS.Core/Models/Config/Convention/ConventionNodeViewConfig.cs @@ -2,18 +2,17 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Models.Config.Convention +namespace RapidCMS.Core.Models.Config.Convention; + +internal class ConventionNodeViewConfig : NodeConfig, IIsConventionBased + where TEntity : IEntity { - internal class ConventionNodeViewConfig : NodeConfig, IIsConventionBased - where TEntity : IEntity + public ConventionNodeViewConfig() : base(typeof(TEntity)) { - public ConventionNodeViewConfig() : base(typeof(TEntity)) - { - } + } - public Features GetFeatures() - { - return Features.CanView; - } + public Features GetFeatures() + { + return Features.CanView; } } diff --git a/src/RapidCMS.Core/Models/Config/CustomButtonConfig.cs b/src/RapidCMS.Core/Models/Config/CustomButtonConfig.cs index aca9c1cf..4609420a 100644 --- a/src/RapidCMS.Core/Models/Config/CustomButtonConfig.cs +++ b/src/RapidCMS.Core/Models/Config/CustomButtonConfig.cs @@ -1,17 +1,16 @@ using System; using RapidCMS.Core.Models.Config; -namespace RapidCMS.Core.Models.Config +namespace RapidCMS.Core.Models.Config; + +internal class CustomButtonConfig : ButtonConfig { - internal class CustomButtonConfig : ButtonConfig + internal CustomButtonConfig(Type customButtonType, Type actionHandler) { - internal CustomButtonConfig(Type customButtonType, Type actionHandler) - { - CustomType = customButtonType ?? throw new ArgumentNullException(nameof(customButtonType)); - ActionHandler = actionHandler ?? throw new ArgumentNullException(nameof(actionHandler)); - } - - internal Type CustomType { get; set; } - internal Type ActionHandler { get; set; } + CustomType = customButtonType ?? throw new ArgumentNullException(nameof(customButtonType)); + ActionHandler = actionHandler ?? throw new ArgumentNullException(nameof(actionHandler)); } + + internal Type CustomType { get; set; } + internal Type ActionHandler { get; set; } } diff --git a/src/RapidCMS.Core/Models/Config/CustomTypeRegistrationConfig.cs b/src/RapidCMS.Core/Models/Config/CustomTypeRegistrationConfig.cs index 83f3a3fe..e5a73500 100644 --- a/src/RapidCMS.Core/Models/Config/CustomTypeRegistrationConfig.cs +++ b/src/RapidCMS.Core/Models/Config/CustomTypeRegistrationConfig.cs @@ -1,19 +1,18 @@ using System; using System.Collections.Generic; -namespace RapidCMS.Core.Models.Config +namespace RapidCMS.Core.Models.Config; + +public sealed class CustomTypeRegistrationConfig { - public sealed class CustomTypeRegistrationConfig + internal CustomTypeRegistrationConfig(Type type, Dictionary? parameters = null) { - internal CustomTypeRegistrationConfig(Type type, Dictionary? parameters = null) - { - Type = type ?? throw new ArgumentNullException(nameof(type)); - Alias = type.FullName ?? throw new InvalidOperationException($"The given type ({type}) must have a FullName"); - Parameters = parameters; - } - - public Type Type { get; set; } - public string Alias { get; set; } - public Dictionary? Parameters { get; set; } + Type = type ?? throw new ArgumentNullException(nameof(type)); + Alias = type.FullName ?? throw new InvalidOperationException($"The given type ({type}) must have a FullName"); + Parameters = parameters; } + + public Type Type { get; set; } + public string Alias { get; set; } + public Dictionary? Parameters { get; set; } } diff --git a/src/RapidCMS.Core/Models/Config/DataProviderRelationConfig.cs b/src/RapidCMS.Core/Models/Config/DataProviderRelationConfig.cs index b3fb9edf..a16a8738 100644 --- a/src/RapidCMS.Core/Models/Config/DataProviderRelationConfig.cs +++ b/src/RapidCMS.Core/Models/Config/DataProviderRelationConfig.cs @@ -1,17 +1,15 @@ using System; -namespace RapidCMS.Core.Models.Config +namespace RapidCMS.Core.Models.Config; + +internal class DataProviderRelationConfig : RelationConfig { - internal class DataProviderRelationConfig : RelationConfig + internal DataProviderRelationConfig(Type dataCollectionType, object? configuration) { - internal DataProviderRelationConfig(Type dataCollectionType, object? configuration) - { - DataCollectionType = dataCollectionType ?? throw new ArgumentNullException(nameof(dataCollectionType)); - Configuration = configuration; - } - - public Type DataCollectionType { get; } - public object? Configuration { get; } + DataCollectionType = dataCollectionType ?? throw new ArgumentNullException(nameof(dataCollectionType)); + Configuration = configuration; } + public Type DataCollectionType { get; } + public object? Configuration { get; } } diff --git a/src/RapidCMS.Core/Models/Config/DefaultButtonConfig.cs b/src/RapidCMS.Core/Models/Config/DefaultButtonConfig.cs index 69084c4b..4f65fd8d 100644 --- a/src/RapidCMS.Core/Models/Config/DefaultButtonConfig.cs +++ b/src/RapidCMS.Core/Models/Config/DefaultButtonConfig.cs @@ -1,9 +1,8 @@ using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Models.Config +namespace RapidCMS.Core.Models.Config; + +internal class DefaultButtonConfig : ButtonConfig { - internal class DefaultButtonConfig : ButtonConfig - { - internal DefaultButtonType ButtonType { get; set; } - } + internal DefaultButtonType ButtonType { get; set; } } diff --git a/src/RapidCMS.Core/Models/Config/DetailPageConfig.cs b/src/RapidCMS.Core/Models/Config/DetailPageConfig.cs index cf5142ef..7f0f5002 100644 --- a/src/RapidCMS.Core/Models/Config/DetailPageConfig.cs +++ b/src/RapidCMS.Core/Models/Config/DetailPageConfig.cs @@ -4,52 +4,51 @@ using RapidCMS.Core.Abstractions.Handlers; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Models.Config +namespace RapidCMS.Core.Models.Config; + +internal class DetailPageConfig : CollectionConfig, ICollectionDetailPageEditorConfig + where TDetailEntity : IEntity { - internal class DetailPageConfig : CollectionConfig, ICollectionDetailPageEditorConfig - where TDetailEntity : IEntity + private readonly NodeEditorConfig _detailNodeEditor; + + internal DetailPageConfig(string alias, string? parentAlias, string? icon, string? color, string name, Type repositoryType, EntityVariantConfig entityVariant) + : base(alias, parentAlias, icon, color, name, repositoryType, entityVariant) { - private readonly NodeEditorConfig _detailNodeEditor; + _detailNodeEditor = new NodeEditorConfig(); - internal DetailPageConfig(string alias, string? parentAlias, string? icon, string? color, string name, Type repositoryType, EntityVariantConfig entityVariant) - : base(alias, parentAlias, icon, color, name, repositoryType, entityVariant) + TreeView = new TreeViewConfig { - _detailNodeEditor = new NodeEditorConfig(); - - TreeView = new TreeViewConfig - { - EntityVisibilty = EntityVisibilty.Hidden, - RootVisibility = CollectionRootVisibility.Visible, - }; + EntityVisibilty = EntityVisibilty.Hidden, + RootVisibility = CollectionRootVisibility.Visible, + }; - NodeEditor = _detailNodeEditor; - } + NodeEditor = _detailNodeEditor; + } - public INodeEditorConfig AddCustomButton(Type buttonType, string? label = null, string? icon = null, Func? isVisible = null) - where TActionHandler : IButtonActionHandler - => _detailNodeEditor.AddCustomButton(buttonType, label, icon, isVisible); + public INodeEditorConfig AddCustomButton(Type buttonType, string? label = null, string? icon = null, Func? isVisible = null) + where TActionHandler : IButtonActionHandler + => _detailNodeEditor.AddCustomButton(buttonType, label, icon, isVisible); - public INodeEditorConfig AddDefaultButton(DefaultButtonType type, string? label = null, string? icon = null, bool isPrimary = false, Func? isVisible = null) - => _detailNodeEditor.AddDefaultButton(type, label, icon, isPrimary, isVisible); + public INodeEditorConfig AddDefaultButton(DefaultButtonType type, string? label = null, string? icon = null, bool isPrimary = false, Func? isVisible = null) + => _detailNodeEditor.AddDefaultButton(type, label, icon, isPrimary, isVisible); - public INodeEditorConfig AddPaneButton(Type paneType, string? label = null, string? icon = null, Func? isVisible = null) - => _detailNodeEditor.AddPaneButton(paneType, label, icon, isVisible); + public INodeEditorConfig AddPaneButton(Type paneType, string? label = null, string? icon = null, Func? isVisible = null) + => _detailNodeEditor.AddPaneButton(paneType, label, icon, isVisible); - public INodeEditorConfig AddNavigationButton(string? label = null, string? icon = null, Func? isVisible = null) - where TNavigationHandler : INavigationHandler - => _detailNodeEditor.AddNavigationButton(label, icon, isVisible); + public INodeEditorConfig AddNavigationButton(string? label = null, string? icon = null, Func? isVisible = null) + where TNavigationHandler : INavigationHandler + => _detailNodeEditor.AddNavigationButton(label, icon, isVisible); - public INodeEditorConfig AddSection(Action> configure) - => _detailNodeEditor.AddSection(configure); + public INodeEditorConfig AddSection(Action> configure) + => _detailNodeEditor.AddSection(configure); - public INodeEditorConfig AddSection(Type customSectionType, Action>? configure = null) - => _detailNodeEditor.AddSection(customSectionType, configure); + public INodeEditorConfig AddSection(Type customSectionType, Action>? configure = null) + => _detailNodeEditor.AddSection(customSectionType, configure); - public INodeEditorConfig AddSection(Action> configure) where TDerivedEntity : TDetailEntity - => _detailNodeEditor.AddSection(configure); + public INodeEditorConfig AddSection(Action> configure) where TDerivedEntity : TDetailEntity + => _detailNodeEditor.AddSection(configure); - public INodeEditorConfig AddSection(Type? customSectionType, Action>? configure) where TDerivedEntity : TDetailEntity - => _detailNodeEditor.AddSection(customSectionType, configure); - } + public INodeEditorConfig AddSection(Type? customSectionType, Action>? configure) where TDerivedEntity : TDetailEntity + => _detailNodeEditor.AddSection(customSectionType, configure); } diff --git a/src/RapidCMS.Core/Models/Config/ElementConfig.cs b/src/RapidCMS.Core/Models/Config/ElementConfig.cs index f0a77709..465d44b0 100644 --- a/src/RapidCMS.Core/Models/Config/ElementConfig.cs +++ b/src/RapidCMS.Core/Models/Config/ElementConfig.cs @@ -3,18 +3,17 @@ using System.Linq; using RapidCMS.Core.Abstractions.Metadata; -namespace RapidCMS.Core.Models.Config +namespace RapidCMS.Core.Models.Config; + +internal class ElementConfig { - internal class ElementConfig + public ElementConfig(IPropertyMetadata id, params IExpressionMetadata[] labels) { - public ElementConfig(IPropertyMetadata id, params IExpressionMetadata[] labels) - { - IdProperty = id ?? throw new ArgumentNullException(nameof(id)); - DisplayProperties = labels?.ToList() ?? throw new ArgumentNullException(nameof(labels)); - } + IdProperty = id ?? throw new ArgumentNullException(nameof(id)); + DisplayProperties = labels?.ToList() ?? throw new ArgumentNullException(nameof(labels)); + } - internal IPropertyMetadata IdProperty { get; set; } + internal IPropertyMetadata IdProperty { get; set; } - internal IReadOnlyList DisplayProperties { get; set; } - } + internal IReadOnlyList DisplayProperties { get; set; } } diff --git a/src/RapidCMS.Core/Models/Config/EntityVariantConfig.cs b/src/RapidCMS.Core/Models/Config/EntityVariantConfig.cs index 3352e2c7..9a14cbb0 100644 --- a/src/RapidCMS.Core/Models/Config/EntityVariantConfig.cs +++ b/src/RapidCMS.Core/Models/Config/EntityVariantConfig.cs @@ -1,18 +1,17 @@ using System; -namespace RapidCMS.Core.Models.Config +namespace RapidCMS.Core.Models.Config; + +internal class EntityVariantConfig { - internal class EntityVariantConfig + internal EntityVariantConfig(string name, Type type, string? icon = null) { - internal EntityVariantConfig(string name, Type type, string? icon = null) - { - Name = name ?? throw new ArgumentNullException(nameof(name)); - Type = type ?? throw new ArgumentNullException(nameof(type)); - Icon = icon; - } - - internal string Name { get; set; } - internal string? Icon { get; set; } - internal Type Type { get; set; } + Name = name ?? throw new ArgumentNullException(nameof(name)); + Type = type ?? throw new ArgumentNullException(nameof(type)); + Icon = icon; } + + internal string Name { get; set; } + internal string? Icon { get; set; } + internal Type Type { get; set; } } diff --git a/src/RapidCMS.Core/Models/Config/FieldConfig.cs b/src/RapidCMS.Core/Models/Config/FieldConfig.cs index f3e94895..9a1e24d6 100644 --- a/src/RapidCMS.Core/Models/Config/FieldConfig.cs +++ b/src/RapidCMS.Core/Models/Config/FieldConfig.cs @@ -12,370 +12,369 @@ using RapidCMS.Core.Extensions; using RapidCMS.Core.Helpers; -namespace RapidCMS.Core.Models.Config +namespace RapidCMS.Core.Models.Config; + +internal class FieldConfig { - internal class FieldConfig - { - internal int Index { get; set; } + internal int Index { get; set; } - internal string? Name { get; set; } - internal string? Description { get; set; } - internal MarkupString? Details { get; set; } - internal string? Placeholder { get; set; } + internal string? Name { get; set; } + internal string? Description { get; set; } + internal MarkupString? Details { get; set; } + internal string? Placeholder { get; set; } - internal Func IsVisible { get; set; } = (x, y) => true; - internal Func IsDisabled { get; set; } = (x, y) => false; + internal Func IsVisible { get; set; } = (x, y) => true; + internal Func IsDisabled { get; set; } = (x, y) => false; - internal IExpressionMetadata? Expression { get; set; } - internal IPropertyMetadata? Property { get; set; } + internal IExpressionMetadata? Expression { get; set; } + internal IPropertyMetadata? Property { get; set; } - internal RelationConfig? Relation { get; set; } + internal RelationConfig? Relation { get; set; } - internal EditorType EditorType { get; set; } - internal DisplayType DisplayType { get; set; } - internal Type? CustomType { get; set; } + internal EditorType EditorType { get; set; } + internal DisplayType DisplayType { get; set; } + internal Type? CustomType { get; set; } - internal IPropertyMetadata? OrderByExpression { get; set; } - internal OrderByType DefaultOrder { get; set; } + internal IPropertyMetadata? OrderByExpression { get; set; } + internal OrderByType DefaultOrder { get; set; } - internal Func>? Configuration { get; set; } - } + internal Func>? Configuration { get; set; } +} - internal class FieldConfig - : FieldConfig, - IDisplayFieldConfig, - IEditorFieldConfig - where TEntity : IEntity +internal class FieldConfig + : FieldConfig, + IDisplayFieldConfig, + IEditorFieldConfig + where TEntity : IEntity +{ + IDisplayFieldConfig IHasNameDescription>.SetName(string name) { - IDisplayFieldConfig IHasNameDescription>.SetName(string name) - { - Name = name; - return this; - } + Name = name; + return this; + } - IDisplayFieldConfig IHasNameDescription>.SetDescription(string description) - { - Description = description; - return this; - } + IDisplayFieldConfig IHasNameDescription>.SetDescription(string description) + { + Description = description; + return this; + } - IDisplayFieldConfig IHasNameDescription>.SetDetails(MarkupString details) - { - Details = details; - return this; - } + IDisplayFieldConfig IHasNameDescription>.SetDetails(MarkupString details) + { + Details = details; + return this; + } - IDisplayFieldConfig IHasConfigurability>.SetConfiguration(TConfig config) - where TConfig : class - { - Configuration = (entity, state) => Task.FromResult((object?)config); + IDisplayFieldConfig IHasConfigurability>.SetConfiguration(TConfig config) + where TConfig : class + { + Configuration = (entity, state) => Task.FromResult((object?)config); - return this; - } + return this; + } - IDisplayFieldConfig IHasConfigurability>.SetConfiguration(Func config) - where TConfig : class - { - Configuration = (entity, state) => Task.FromResult((object?)config.Invoke((TEntity)entity, state)); + IDisplayFieldConfig IHasConfigurability>.SetConfiguration(Func config) + where TConfig : class + { + Configuration = (entity, state) => Task.FromResult((object?)config.Invoke((TEntity)entity, state)); - return this; - } + return this; + } - IDisplayFieldConfig IHasConfigurability>.SetConfiguration(Func> config) - where TConfig : class - { - Configuration = async (entity, state) => await config.Invoke((TEntity)entity, state); + IDisplayFieldConfig IHasConfigurability>.SetConfiguration(Func> config) + where TConfig : class + { + Configuration = async (entity, state) => await config.Invoke((TEntity)entity, state); - return this; - } + return this; + } - IDisplayFieldConfig IDisplayFieldConfig.SetType(DisplayType type) - { - DisplayType = type; - EditorType = EditorType.None; - return this; - } + IDisplayFieldConfig IDisplayFieldConfig.SetType(DisplayType type) + { + DisplayType = type; + EditorType = EditorType.None; + return this; + } - IDisplayFieldConfig IDisplayFieldConfig.SetType(Type type) - { - DisplayType = DisplayType.Custom; - CustomType = type; - return this; - } + IDisplayFieldConfig IDisplayFieldConfig.SetType(Type type) + { + DisplayType = DisplayType.Custom; + CustomType = type; + return this; + } - IDisplayFieldConfig IDisplayFieldConfig.VisibleWhen(Func predicate) - { - IsVisible = (entity, state) => predicate.Invoke((TEntity)entity, state); - return this; - } + IDisplayFieldConfig IDisplayFieldConfig.VisibleWhen(Func predicate) + { + IsVisible = (entity, state) => predicate.Invoke((TEntity)entity, state); + return this; + } - IDisplayFieldConfig IHasOrderByEntity>.SetOrderByExpression(Expression> orderByExpression, OrderByType defaultOrder) - { - OrderByExpression = PropertyMetadataHelper.GetPropertyMetadata(orderByExpression); - DefaultOrder = defaultOrder; - return this; - } + IDisplayFieldConfig IHasOrderByEntity>.SetOrderByExpression(Expression> orderByExpression, OrderByType defaultOrder) + { + OrderByExpression = PropertyMetadataHelper.GetPropertyMetadata(orderByExpression); + DefaultOrder = defaultOrder; + return this; + } - IDisplayFieldConfig IHasOrderByDatabaseEntity>.SetOrderByExpression(Expression> orderByExpression, OrderByType defaultOrder) - { - OrderByExpression = PropertyMetadataHelper.GetPropertyMetadata(orderByExpression); - DefaultOrder = defaultOrder; - return this; - } + IDisplayFieldConfig IHasOrderByDatabaseEntity>.SetOrderByExpression(Expression> orderByExpression, OrderByType defaultOrder) + { + OrderByExpression = PropertyMetadataHelper.GetPropertyMetadata(orderByExpression); + DefaultOrder = defaultOrder; + return this; + } - IEditorFieldConfig IHasNameDescription>.SetName(string name) - { - Name = name; - return this; - } + IEditorFieldConfig IHasNameDescription>.SetName(string name) + { + Name = name; + return this; + } - IEditorFieldConfig IHasNameDescription>.SetDescription(string description) - { - Description = description; - return this; - } + IEditorFieldConfig IHasNameDescription>.SetDescription(string description) + { + Description = description; + return this; + } - IEditorFieldConfig IHasNameDescription>.SetDetails(MarkupString details) - { - Details = details; - return this; - } + IEditorFieldConfig IHasNameDescription>.SetDetails(MarkupString details) + { + Details = details; + return this; + } - IEditorFieldConfig IHasConfigurability>.SetConfiguration(TConfig config) - where TConfig : class - { - Configuration = (entity, state) => Task.FromResult((object?)config); + IEditorFieldConfig IHasConfigurability>.SetConfiguration(TConfig config) + where TConfig : class + { + Configuration = (entity, state) => Task.FromResult((object?)config); - return this; - } + return this; + } - IEditorFieldConfig IHasConfigurability>.SetConfiguration(Func config) - where TConfig : class - { - Configuration = (entity, state) => Task.FromResult((object?)config.Invoke((TEntity)entity, state)); + IEditorFieldConfig IHasConfigurability>.SetConfiguration(Func config) + where TConfig : class + { + Configuration = (entity, state) => Task.FromResult((object?)config.Invoke((TEntity)entity, state)); - return this; - } + return this; + } - IEditorFieldConfig IHasConfigurability>.SetConfiguration(Func> config) - where TConfig : class - { - Configuration = async (entity, state) => await config.Invoke((TEntity)entity, state); + IEditorFieldConfig IHasConfigurability>.SetConfiguration(Func> config) + where TConfig : class + { + Configuration = async (entity, state) => await config.Invoke((TEntity)entity, state); - return this; - } + return this; + } - IEditorFieldConfig IHasPlaceholder>.SetPlaceholder(string placeholder) - { - Placeholder = placeholder; - return this; - } + IEditorFieldConfig IHasPlaceholder>.SetPlaceholder(string placeholder) + { + Placeholder = placeholder; + return this; + } - IEditorFieldConfig IEditorFieldConfig.SetType(EditorType type) - { - EditorType = type; - DisplayType = DisplayType.None; - return this; - } + IEditorFieldConfig IEditorFieldConfig.SetType(EditorType type) + { + EditorType = type; + DisplayType = DisplayType.None; + return this; + } - IEditorFieldConfig IEditorFieldConfig.SetType(DisplayType type) - { - EditorType = EditorType.None; - DisplayType = type; - return this; - } + IEditorFieldConfig IEditorFieldConfig.SetType(DisplayType type) + { + EditorType = EditorType.None; + DisplayType = type; + return this; + } - IEditorFieldConfig IEditorFieldConfig.SetType(Type type) - { - EditorType = EditorType.Custom; - CustomType = type; - return this; - } + IEditorFieldConfig IEditorFieldConfig.SetType(Type type) + { + EditorType = EditorType.Custom; + CustomType = type; + return this; + } - IEditorFieldConfig IEditorFieldConfig.SetDataCollection() - => (this as IEditorFieldConfig).SetDataCollection(default); + IEditorFieldConfig IEditorFieldConfig.SetDataCollection() + => (this as IEditorFieldConfig).SetDataCollection(default); - IEditorFieldConfig IEditorFieldConfig.SetDataCollection(TConfig configuration) + IEditorFieldConfig IEditorFieldConfig.SetDataCollection(TConfig configuration) + { + var relationType = GetRelationType(); + if (relationType != RelationType.One) { - var relationType = GetRelationType(); - if (relationType != RelationType.One) - { - throw new InvalidOperationException("Cannot add DataRelation to Editor with no support for RelationType.One. Use an editor that has the attribute [Relation(RelationType.One)]."); - } + throw new InvalidOperationException("Cannot add DataRelation to Editor with no support for RelationType.One. Use an editor that has the attribute [Relation(RelationType.One)]."); + } - var config = new DataProviderRelationConfig(typeof(TDataCollection), configuration); + var config = new DataProviderRelationConfig(typeof(TDataCollection), configuration); - Relation = config; + Relation = config; - return this; - } + return this; + } - IEditorFieldConfig IEditorFieldConfig.SetDataCollection(TDataCollection dataCollection) + IEditorFieldConfig IEditorFieldConfig.SetDataCollection(TDataCollection dataCollection) + { + var relationType = GetRelationType(); + if (relationType != RelationType.One) { - var relationType = GetRelationType(); - if (relationType != RelationType.One) - { - throw new InvalidOperationException("Cannot add DataRelation to Editor with no support for RelationType.One. Use an editor that has the attribute [Relation(RelationType.One)]."); - } + throw new InvalidOperationException("Cannot add DataRelation to Editor with no support for RelationType.One. Use an editor that has the attribute [Relation(RelationType.One)]."); + } - var config = new ConcreteDataProviderRelationConfig(dataCollection); + var config = new ConcreteDataProviderRelationConfig(dataCollection); - Relation = config; + Relation = config; - return this; - } + return this; + } - IEditorFieldConfig IEditorFieldConfig.SetCollectionRelation() - => (this as IEditorFieldConfig).SetCollectionRelation(default); + IEditorFieldConfig IEditorFieldConfig.SetCollectionRelation() + => (this as IEditorFieldConfig).SetCollectionRelation(default); - IEditorFieldConfig IEditorFieldConfig.SetCollectionRelation(TConfig configuration) + IEditorFieldConfig IEditorFieldConfig.SetCollectionRelation(TConfig configuration) + { + var relationType = GetRelationType(); + if (!relationType.In(RelationType.One, RelationType.Many)) { - var relationType = GetRelationType(); - if (!relationType.In(RelationType.One, RelationType.Many)) - { - throw new InvalidOperationException("Cannot add RelationDataRelation to Editor with no support for RelationType.One / RelationType.Many. Use an editor that has the attribute [Relation(RelationType.One)] / [Relation(RelationType.Many)]."); - } + throw new InvalidOperationException("Cannot add RelationDataRelation to Editor with no support for RelationType.One / RelationType.Many. Use an editor that has the attribute [Relation(RelationType.One)] / [Relation(RelationType.Many)]."); + } - var config = new RelationDataProviderRelationConfig(typeof(TDataCollection), configuration); + var config = new RelationDataProviderRelationConfig(typeof(TDataCollection), configuration); - Relation = config; + Relation = config; - return this; - } + return this; + } - IEditorFieldConfig IEditorFieldConfig.SetCollectionRelation(TDataCollection dataCollection) + IEditorFieldConfig IEditorFieldConfig.SetCollectionRelation(TDataCollection dataCollection) + { + var relationType = GetRelationType(); + if (!relationType.In(RelationType.One, RelationType.Many)) { - var relationType = GetRelationType(); - if (!relationType.In(RelationType.One, RelationType.Many)) - { - throw new InvalidOperationException("Cannot add CollectionRelation to Editor with no support for RelationType.One / RelationType.Many. Use an editor that has the attribute [Relation(RelationType.One)] / [Relation(RelationType.Many)]."); - } + throw new InvalidOperationException("Cannot add CollectionRelation to Editor with no support for RelationType.One / RelationType.Many. Use an editor that has the attribute [Relation(RelationType.One)] / [Relation(RelationType.Many)]."); + } - var config = new ConcreteDataProviderRelationConfig(dataCollection); + var config = new ConcreteDataProviderRelationConfig(dataCollection); - Relation = config; + Relation = config; - return this; - } + return this; + } - IEditorFieldConfig IEditorFieldConfig.SetCollectionRelation( - string collectionAlias) + IEditorFieldConfig IEditorFieldConfig.SetCollectionRelation( + string collectionAlias) + { + var relationType = GetRelationType(); + if (!relationType.In(RelationType.One, RelationType.Many)) { - var relationType = GetRelationType(); - if (!relationType.In(RelationType.One, RelationType.Many)) - { - throw new InvalidOperationException("Cannot add DataRelation to Editor with no support for RelationType.One / RelationType.Many. Use an editor that has the attribute [Relation(RelationType.One)] / [Relation(RelationType.Many)]."); - } + throw new InvalidOperationException("Cannot add DataRelation to Editor with no support for RelationType.One / RelationType.Many. Use an editor that has the attribute [Relation(RelationType.One)] / [Relation(RelationType.Many)]."); + } - Relation = new RepositoryRelationConfig(collectionAlias, relationType == RelationType.Many); + Relation = new RepositoryRelationConfig(collectionAlias, relationType == RelationType.Many); - return this; - } + return this; + } - IEditorFieldConfig IEditorFieldConfig.SetCollectionRelation( - string collectionAlias, Action> configure) + IEditorFieldConfig IEditorFieldConfig.SetCollectionRelation( + string collectionAlias, Action> configure) + { + var relationType = GetRelationType(); + if (!relationType.In(RelationType.One, RelationType.Many)) { - var relationType = GetRelationType(); - if (!relationType.In(RelationType.One, RelationType.Many)) - { - throw new InvalidOperationException("Cannot add DataRelation to Editor with no support for RelationType.One / RelationType.Many. Use an editor that has the attribute [Relation(RelationType.One)] / [Relation(RelationType.Many)]."); - } + throw new InvalidOperationException("Cannot add DataRelation to Editor with no support for RelationType.One / RelationType.Many. Use an editor that has the attribute [Relation(RelationType.One)] / [Relation(RelationType.Many)]."); + } - var config = new RepositoryRelationConfig(collectionAlias, relationType == RelationType.Many); + var config = new RepositoryRelationConfig(collectionAlias, relationType == RelationType.Many); - configure.Invoke(config); + configure.Invoke(config); - Relation = config; + Relation = config; - return this; - } + return this; + } - IEditorFieldConfig IEditorFieldConfig.SetCollectionRelation( - Action> configure) + IEditorFieldConfig IEditorFieldConfig.SetCollectionRelation( + Action> configure) + { + var relationType = GetRelationType(); + if (!relationType.In(RelationType.One, RelationType.Many)) { - var relationType = GetRelationType(); - if (!relationType.In(RelationType.One, RelationType.Many)) - { - throw new InvalidOperationException("Cannot add DataRelation to Editor with no support for RelationType.One / RelationType.Many. Use an editor that has the attribute [Relation(RelationType.One)] / [Relation(RelationType.Many)]."); - } + throw new InvalidOperationException("Cannot add DataRelation to Editor with no support for RelationType.One / RelationType.Many. Use an editor that has the attribute [Relation(RelationType.One)] / [Relation(RelationType.Many)]."); + } - var config = new RepositoryRelationConfig(typeof(TRelatedRepository), relationType == RelationType.Many); + var config = new RepositoryRelationConfig(typeof(TRelatedRepository), relationType == RelationType.Many); - configure.Invoke(config); + configure.Invoke(config); - Relation = config; + Relation = config; - return this; - } + return this; + } - IEditorFieldConfig IEditorFieldConfig.SetCollectionRelation( - Expression>> relatedElements, string collectionAlias, Action> configure) + IEditorFieldConfig IEditorFieldConfig.SetCollectionRelation( + Expression>> relatedElements, string collectionAlias, Action> configure) + { + var relationType = GetRelationType(); + if (relationType != RelationType.Many) { - var relationType = GetRelationType(); - if (relationType != RelationType.Many) - { - throw new InvalidOperationException("Cannot add DataRelation to Editor with no support for RelationType.Many. Use an editor that has the attribute [Relation(RelationType.Many)]."); - } + throw new InvalidOperationException("Cannot add DataRelation to Editor with no support for RelationType.Many. Use an editor that has the attribute [Relation(RelationType.Many)]."); + } - var relatedElementsGetter = PropertyMetadataHelper.GetPropertyMetadata(relatedElements) ?? throw new InvalidExpressionException(nameof(relatedElements)); - var config = new RepositoryRelationConfig(collectionAlias, relatedElementsGetter); + var relatedElementsGetter = PropertyMetadataHelper.GetPropertyMetadata(relatedElements) ?? throw new InvalidExpressionException(nameof(relatedElements)); + var config = new RepositoryRelationConfig(collectionAlias, relatedElementsGetter); - configure.Invoke(config); + configure.Invoke(config); - Relation = config; + Relation = config; - return this; - } + return this; + } - IEditorFieldConfig IEditorFieldConfig.SetCollectionRelation( - Expression>> relatedElements, Action> configure) + IEditorFieldConfig IEditorFieldConfig.SetCollectionRelation( + Expression>> relatedElements, Action> configure) + { + if (EditorType != EditorType.Custom && !(EditorType.GetCustomAttribute()?.Type.In(RelationType.Many) ?? false)) { - if (EditorType != EditorType.Custom && !(EditorType.GetCustomAttribute()?.Type.In(RelationType.Many) ?? false)) - { - throw new InvalidOperationException("Cannot add CollectionRelation with relatedElements to Editor with no support for RelationType.Many"); - } - - var relatedElementsGetter = PropertyMetadataHelper.GetPropertyMetadata(relatedElements) ?? throw new InvalidExpressionException(nameof(relatedElements)); - var config = new RepositoryRelationConfig(typeof(TRelatedRepository), relatedElementsGetter); + throw new InvalidOperationException("Cannot add CollectionRelation with relatedElements to Editor with no support for RelationType.Many"); + } - configure.Invoke(config); + var relatedElementsGetter = PropertyMetadataHelper.GetPropertyMetadata(relatedElements) ?? throw new InvalidExpressionException(nameof(relatedElements)); + var config = new RepositoryRelationConfig(typeof(TRelatedRepository), relatedElementsGetter); - Relation = config; + configure.Invoke(config); - return this; - } + Relation = config; - IEditorFieldConfig IEditorFieldConfig.VisibleWhen(Func predicate) - { - IsVisible = (entity, state) => predicate.Invoke((TEntity)entity, state); - return this; - } + return this; + } - IEditorFieldConfig IEditorFieldConfig.DisableWhen(Func predicate) - { - IsDisabled = (entity, state) => predicate.Invoke((TEntity)entity, state); - return this; - } + IEditorFieldConfig IEditorFieldConfig.VisibleWhen(Func predicate) + { + IsVisible = (entity, state) => predicate.Invoke((TEntity)entity, state); + return this; + } - IEditorFieldConfig IHasOrderByEntity>.SetOrderByExpression(Expression> orderByExpression, OrderByType defaultOrder) - { - OrderByExpression = PropertyMetadataHelper.GetPropertyMetadata(orderByExpression); - DefaultOrder = defaultOrder; - return this; - } + IEditorFieldConfig IEditorFieldConfig.DisableWhen(Func predicate) + { + IsDisabled = (entity, state) => predicate.Invoke((TEntity)entity, state); + return this; + } - IEditorFieldConfig IHasOrderByDatabaseEntity>.SetOrderByExpression(Expression> orderByExpression, OrderByType defaultOrder) - { - OrderByExpression = PropertyMetadataHelper.GetPropertyMetadata(orderByExpression); - DefaultOrder = defaultOrder; - return this; - } + IEditorFieldConfig IHasOrderByEntity>.SetOrderByExpression(Expression> orderByExpression, OrderByType defaultOrder) + { + OrderByExpression = PropertyMetadataHelper.GetPropertyMetadata(orderByExpression); + DefaultOrder = defaultOrder; + return this; + } - private RelationType? GetRelationType() - => EditorType switch - { - EditorType.Custom => CustomType?.GetCustomAttribute()?.Type, - _ => EditorType.GetCustomAttribute()?.Type - }; + IEditorFieldConfig IHasOrderByDatabaseEntity>.SetOrderByExpression(Expression> orderByExpression, OrderByType defaultOrder) + { + OrderByExpression = PropertyMetadataHelper.GetPropertyMetadata(orderByExpression); + DefaultOrder = defaultOrder; + return this; } + + private RelationType? GetRelationType() + => EditorType switch + { + EditorType.Custom => CustomType?.GetCustomAttribute()?.Type, + _ => EditorType.GetCustomAttribute()?.Type + }; } diff --git a/src/RapidCMS.Core/Models/Config/ListConfig.cs b/src/RapidCMS.Core/Models/Config/ListConfig.cs index 8612b5a6..0bf1d2c6 100644 --- a/src/RapidCMS.Core/Models/Config/ListConfig.cs +++ b/src/RapidCMS.Core/Models/Config/ListConfig.cs @@ -2,22 +2,21 @@ using System.Collections.Generic; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Models.Config +namespace RapidCMS.Core.Models.Config; + +internal class ListConfig { - internal class ListConfig + public ListConfig(Type baseType) { - public ListConfig(Type baseType) - { - BaseType = baseType; - } - - public Type BaseType { get; } - internal int? PageSize { get; set; } - internal bool? SearchBarVisible { get; set; } - internal bool? ReorderingAllowed { get; set; } - internal ListType ListEditorType { get; set; } - internal EmptyVariantColumnVisibility EmptyVariantColumnVisibility { get; set; } - internal List Buttons { get; set; } = new List(); - internal List Panes { get; set; } = new List(); + BaseType = baseType; } + + public Type BaseType { get; } + internal int? PageSize { get; set; } + internal bool? SearchBarVisible { get; set; } + internal bool? ReorderingAllowed { get; set; } + internal ListType ListEditorType { get; set; } + internal EmptyVariantColumnVisibility EmptyVariantColumnVisibility { get; set; } + internal List Buttons { get; set; } = new List(); + internal List Panes { get; set; } = new List(); } diff --git a/src/RapidCMS.Core/Models/Config/ListEditorConfig.cs b/src/RapidCMS.Core/Models/Config/ListEditorConfig.cs index 716ffeb8..10a082e1 100644 --- a/src/RapidCMS.Core/Models/Config/ListEditorConfig.cs +++ b/src/RapidCMS.Core/Models/Config/ListEditorConfig.cs @@ -4,148 +4,147 @@ using RapidCMS.Core.Abstractions.Handlers; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Models.Config +namespace RapidCMS.Core.Models.Config; + +internal class ListEditorConfig : ListConfig, + IListEditorConfig + where TEntity : IEntity { - internal class ListEditorConfig : ListConfig, - IListEditorConfig - where TEntity : IEntity + public ListEditorConfig() : base(typeof(TEntity)) { - public ListEditorConfig() : base(typeof(TEntity)) - { - } + } - public IListEditorConfig SetPageSize(int pageSize) + public IListEditorConfig SetPageSize(int pageSize) + { + if (pageSize < 1) { - if (pageSize < 1) - { - throw new InvalidOperationException("Cannot have PageSize smaller than 1"); - } + throw new InvalidOperationException("Cannot have PageSize smaller than 1"); + } - PageSize = pageSize; + PageSize = pageSize; - return this; - } + return this; + } - public IListEditorConfig SetSearchBarVisibility(bool visible) - { - SearchBarVisible = visible; + public IListEditorConfig SetSearchBarVisibility(bool visible) + { + SearchBarVisible = visible; - return this; - } + return this; + } - public IListEditorConfig AllowReordering(bool allowReordering) - { - ReorderingAllowed = allowReordering; + public IListEditorConfig AllowReordering(bool allowReordering) + { + ReorderingAllowed = allowReordering; - return this; - } + return this; + } - public IListEditorConfig SetListType(ListType listType) - { - ListEditorType = listType; + public IListEditorConfig SetListType(ListType listType) + { + ListEditorType = listType; - return this; - } + return this; + } - public IListEditorConfig SetColumnVisibility(EmptyVariantColumnVisibility columnVisibility) - { - EmptyVariantColumnVisibility = columnVisibility; + public IListEditorConfig SetColumnVisibility(EmptyVariantColumnVisibility columnVisibility) + { + EmptyVariantColumnVisibility = columnVisibility; - return this; - } + return this; + } - public IListEditorConfig AddDefaultButton(DefaultButtonType type, string? label = null, string? icon = null, bool isPrimary = false, Func? isVisible = null) + public IListEditorConfig AddDefaultButton(DefaultButtonType type, string? label = null, string? icon = null, bool isPrimary = false, Func? isVisible = null) + { + var button = new DefaultButtonConfig { - var button = new DefaultButtonConfig - { - ButtonType = type, - Icon = icon, - Label = label, - IsPrimary = isPrimary - }; + ButtonType = type, + Icon = icon, + Label = label, + IsPrimary = isPrimary + }; - button.VisibleWhen(isVisible); + button.VisibleWhen(isVisible); - Buttons.Add(button); + Buttons.Add(button); - return this; - } + return this; + } - public IListEditorConfig AddCustomButton(Type buttonType, string? label = null, string? icon = null, Func? isVisible = null) - where TActionHandler : IButtonActionHandler + public IListEditorConfig AddCustomButton(Type buttonType, string? label = null, string? icon = null, Func? isVisible = null) + where TActionHandler : IButtonActionHandler + { + var button = new CustomButtonConfig(buttonType, typeof(TActionHandler)) { - var button = new CustomButtonConfig(buttonType, typeof(TActionHandler)) - { - Icon = icon, - Label = label - }; + Icon = icon, + Label = label + }; - button.VisibleWhen(isVisible); + button.VisibleWhen(isVisible); - Buttons.Add(button); + Buttons.Add(button); - return this; - } + return this; + } - public IListEditorConfig AddPaneButton(Type paneType, string? label = null, string? icon = null, Func? isVisible = null) + public IListEditorConfig AddPaneButton(Type paneType, string? label = null, string? icon = null, Func? isVisible = null) + { + var button = new PaneButtonConfig(paneType) { - var button = new PaneButtonConfig(paneType) - { - Icon = icon, - Label = label - }; + Icon = icon, + Label = label + }; - button.VisibleWhen(isVisible); + button.VisibleWhen(isVisible); - Buttons.Add(button); + Buttons.Add(button); - return this; - } + return this; + } - public IListEditorConfig AddNavigationButton(string? label = null, string? icon = null, Func? isVisible = null) - where TNavigationHandler : INavigationHandler + public IListEditorConfig AddNavigationButton(string? label = null, string? icon = null, Func? isVisible = null) + where TNavigationHandler : INavigationHandler + { + var button = new NavigationButtonConfig(typeof(TNavigationHandler)) { - var button = new NavigationButtonConfig(typeof(TNavigationHandler)) - { - Icon = icon, - Label = label - }; + Icon = icon, + Label = label + }; - button.VisibleWhen(isVisible); + button.VisibleWhen(isVisible); - Buttons.Add(button); + Buttons.Add(button); - return this; - } + return this; + } - public IListEditorConfig AddSection(Action> configure) - { - return AddSection(configure); - } + public IListEditorConfig AddSection(Action> configure) + { + return AddSection(configure); + } - public IListEditorConfig AddSection(Type customSectionType, Action>? configure = null) - { - return AddSection(customSectionType, configure); - } + public IListEditorConfig AddSection(Type customSectionType, Action>? configure = null) + { + return AddSection(customSectionType, configure); + } - public IListEditorConfig AddSection(Action> configure) - where TDerivedEntity : TEntity - { - return AddSection(null, configure); - } + public IListEditorConfig AddSection(Action> configure) + where TDerivedEntity : TEntity + { + return AddSection(null, configure); + } - public IListEditorConfig AddSection(Type? customSectionType, Action>? configure) - where TDerivedEntity : TEntity - { - var config = customSectionType == null - ? new PaneConfig(typeof(TDerivedEntity)) - : new PaneConfig(typeof(TDerivedEntity), customSectionType); + public IListEditorConfig AddSection(Type? customSectionType, Action>? configure) + where TDerivedEntity : TEntity + { + var config = customSectionType == null + ? new PaneConfig(typeof(TDerivedEntity)) + : new PaneConfig(typeof(TDerivedEntity), customSectionType); - configure?.Invoke(config); + configure?.Invoke(config); - Panes.Add(config); + Panes.Add(config); - return this; - } + return this; } } diff --git a/src/RapidCMS.Core/Models/Config/ListViewConfig.cs b/src/RapidCMS.Core/Models/Config/ListViewConfig.cs index 1646dc48..e6b6546c 100644 --- a/src/RapidCMS.Core/Models/Config/ListViewConfig.cs +++ b/src/RapidCMS.Core/Models/Config/ListViewConfig.cs @@ -4,128 +4,127 @@ using RapidCMS.Core.Abstractions.Handlers; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Models.Config +namespace RapidCMS.Core.Models.Config; + +internal class ListViewConfig : ListConfig, IListViewConfig + where TEntity : IEntity { - internal class ListViewConfig : ListConfig, IListViewConfig - where TEntity : IEntity + public ListViewConfig() : base(typeof(TEntity)) { - public ListViewConfig() : base(typeof(TEntity)) - { - } + } - public IListViewConfig SetPageSize(int pageSize) - { - PageSize = pageSize; + public IListViewConfig SetPageSize(int pageSize) + { + PageSize = pageSize; - return this; - } + return this; + } - public IListViewConfig SetSearchBarVisibility(bool visible) - { - SearchBarVisible = visible; + public IListViewConfig SetSearchBarVisibility(bool visible) + { + SearchBarVisible = visible; - return this; - } + return this; + } - public IListViewConfig SetColumnVisibility(EmptyVariantColumnVisibility columnVisibility) - { - EmptyVariantColumnVisibility = columnVisibility; + public IListViewConfig SetColumnVisibility(EmptyVariantColumnVisibility columnVisibility) + { + EmptyVariantColumnVisibility = columnVisibility; - return this; - } + return this; + } - public IListViewConfig AddDefaultButton(DefaultButtonType type, string? label = null, string? icon = null, bool isPrimary = false, Func? isVisible = null) + public IListViewConfig AddDefaultButton(DefaultButtonType type, string? label = null, string? icon = null, bool isPrimary = false, Func? isVisible = null) + { + var button = new DefaultButtonConfig { - var button = new DefaultButtonConfig - { - ButtonType = type, - Icon = icon, - Label = label, - IsPrimary = isPrimary - }; + ButtonType = type, + Icon = icon, + Label = label, + IsPrimary = isPrimary + }; - button.VisibleWhen(isVisible); + button.VisibleWhen(isVisible); - Buttons.Add(button); + Buttons.Add(button); - return this; - } + return this; + } - public IListViewConfig AddCustomButton(Type buttonType, string? label = null, string? icon = null, Func? isVisible = null) - where TActionHandler : IButtonActionHandler + public IListViewConfig AddCustomButton(Type buttonType, string? label = null, string? icon = null, Func? isVisible = null) + where TActionHandler : IButtonActionHandler + { + var button = new CustomButtonConfig(buttonType, typeof(TActionHandler)) { - var button = new CustomButtonConfig(buttonType, typeof(TActionHandler)) - { - Icon = icon, - Label = label - }; + Icon = icon, + Label = label + }; - button.VisibleWhen(isVisible); + button.VisibleWhen(isVisible); - Buttons.Add(button); + Buttons.Add(button); - return this; - } + return this; + } - public IListViewConfig AddPaneButton(Type paneType, string? label = null, string? icon = null, Func? isVisible = null) + public IListViewConfig AddPaneButton(Type paneType, string? label = null, string? icon = null, Func? isVisible = null) + { + var button = new PaneButtonConfig(paneType) { - var button = new PaneButtonConfig(paneType) - { - Icon = icon, - Label = label - }; + Icon = icon, + Label = label + }; - button.VisibleWhen(isVisible); + button.VisibleWhen(isVisible); - Buttons.Add(button); + Buttons.Add(button); - return this; - } + return this; + } - public IListViewConfig AddNavigationButton(string? label = null, string? icon = null, Func? isVisible = null) - where TNavigationHandler : INavigationHandler + public IListViewConfig AddNavigationButton(string? label = null, string? icon = null, Func? isVisible = null) + where TNavigationHandler : INavigationHandler + { + var button = new NavigationButtonConfig(typeof(TNavigationHandler)) { - var button = new NavigationButtonConfig(typeof(TNavigationHandler)) - { - Icon = icon, - Label = label - }; + Icon = icon, + Label = label + }; - button.VisibleWhen(isVisible); + button.VisibleWhen(isVisible); - Buttons.Add(button); + Buttons.Add(button); - return this; - } + return this; + } - public IListViewConfig AddRow(Action> configure) - { - return AddRow(configure); - } + public IListViewConfig AddRow(Action> configure) + { + return AddRow(configure); + } - public IListViewConfig AddRow(Type customSectionType, Action> configure) - { - return AddRow(customSectionType, configure); - } + public IListViewConfig AddRow(Type customSectionType, Action> configure) + { + return AddRow(customSectionType, configure); + } - public IListViewConfig AddRow(Action> configure) - where TDerivedEntity : TEntity - { - return AddRow(null, configure); - } + public IListViewConfig AddRow(Action> configure) + where TDerivedEntity : TEntity + { + return AddRow(null, configure); + } - public IListViewConfig AddRow(Type? customSectionType, Action> configure) - where TDerivedEntity : TEntity - { - var config = customSectionType == null - ? new PaneConfig(typeof(TDerivedEntity)) - : new PaneConfig(typeof(TDerivedEntity), customSectionType); + public IListViewConfig AddRow(Type? customSectionType, Action> configure) + where TDerivedEntity : TEntity + { + var config = customSectionType == null + ? new PaneConfig(typeof(TDerivedEntity)) + : new PaneConfig(typeof(TDerivedEntity), customSectionType); - configure?.Invoke(config); + configure?.Invoke(config); - Panes.Add(config); + Panes.Add(config); - return this; - } + return this; } } diff --git a/src/RapidCMS.Core/Models/Config/NavigationButtonConfig.cs b/src/RapidCMS.Core/Models/Config/NavigationButtonConfig.cs index ed723277..9bddb744 100644 --- a/src/RapidCMS.Core/Models/Config/NavigationButtonConfig.cs +++ b/src/RapidCMS.Core/Models/Config/NavigationButtonConfig.cs @@ -1,14 +1,13 @@ using System; -namespace RapidCMS.Core.Models.Config +namespace RapidCMS.Core.Models.Config; + +internal class NavigationButtonConfig : ButtonConfig { - internal class NavigationButtonConfig : ButtonConfig + internal NavigationButtonConfig(Type handlerType) { - internal NavigationButtonConfig(Type handlerType) - { - HandlerType = handlerType; - } - - internal Type HandlerType { get; } + HandlerType = handlerType; } + + internal Type HandlerType { get; } } diff --git a/src/RapidCMS.Core/Models/Config/NodeConfig.cs b/src/RapidCMS.Core/Models/Config/NodeConfig.cs index fa9f752f..63ee6570 100644 --- a/src/RapidCMS.Core/Models/Config/NodeConfig.cs +++ b/src/RapidCMS.Core/Models/Config/NodeConfig.cs @@ -1,17 +1,16 @@ using System; using System.Collections.Generic; -namespace RapidCMS.Core.Models.Config +namespace RapidCMS.Core.Models.Config; + +internal class NodeConfig { - internal class NodeConfig + internal NodeConfig(Type baseType) { - internal NodeConfig(Type baseType) - { - BaseType = baseType ?? throw new ArgumentNullException(nameof(baseType)); - } - - internal Type BaseType { get; set; } - internal List Buttons { get; set; } = new List(); - internal List Panes { get; set; } = new List(); + BaseType = baseType ?? throw new ArgumentNullException(nameof(baseType)); } + + internal Type BaseType { get; set; } + internal List Buttons { get; set; } = new List(); + internal List Panes { get; set; } = new List(); } diff --git a/src/RapidCMS.Core/Models/Config/NodeEditorConfig.cs b/src/RapidCMS.Core/Models/Config/NodeEditorConfig.cs index 96e904ac..3e7b1a37 100644 --- a/src/RapidCMS.Core/Models/Config/NodeEditorConfig.cs +++ b/src/RapidCMS.Core/Models/Config/NodeEditorConfig.cs @@ -4,101 +4,100 @@ using RapidCMS.Core.Abstractions.Handlers; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Models.Config +namespace RapidCMS.Core.Models.Config; + +internal class NodeEditorConfig : NodeConfig, INodeEditorConfig + where TEntity : IEntity { - internal class NodeEditorConfig : NodeConfig, INodeEditorConfig - where TEntity : IEntity + public NodeEditorConfig() : base(typeof(TEntity)) { - public NodeEditorConfig() : base(typeof(TEntity)) - { - } + } - public INodeEditorConfig AddDefaultButton(DefaultButtonType type, string? label = null, string? icon = null, bool isPrimary = false, Func? isVisible = null) + public INodeEditorConfig AddDefaultButton(DefaultButtonType type, string? label = null, string? icon = null, bool isPrimary = false, Func? isVisible = null) + { + var button = new DefaultButtonConfig { - var button = new DefaultButtonConfig - { - ButtonType = type, - Icon = icon, - Label = label, - IsPrimary = isPrimary - }; + ButtonType = type, + Icon = icon, + Label = label, + IsPrimary = isPrimary + }; - button.VisibleWhen(isVisible); + button.VisibleWhen(isVisible); - Buttons.Add(button); + Buttons.Add(button); - return this; - } + return this; + } - public INodeEditorConfig AddCustomButton(Type buttonType, string? label = null, string? icon = null, Func? isVisible = null) - where TActionHandler : IButtonActionHandler + public INodeEditorConfig AddCustomButton(Type buttonType, string? label = null, string? icon = null, Func? isVisible = null) + where TActionHandler : IButtonActionHandler + { + var button = new CustomButtonConfig(buttonType, typeof(TActionHandler)) { - var button = new CustomButtonConfig(buttonType, typeof(TActionHandler)) - { - Icon = icon, - Label = label - }; + Icon = icon, + Label = label + }; - button.VisibleWhen(isVisible); + button.VisibleWhen(isVisible); - Buttons.Add(button); + Buttons.Add(button); - return this; - } + return this; + } - public INodeEditorConfig AddPaneButton(Type paneType, string? label = null, string? icon = null, Func? isVisible = null) + public INodeEditorConfig AddPaneButton(Type paneType, string? label = null, string? icon = null, Func? isVisible = null) + { + var button = new PaneButtonConfig(paneType) { - var button = new PaneButtonConfig(paneType) - { - Icon = icon, - Label = label - }; + Icon = icon, + Label = label + }; - button.VisibleWhen(isVisible); + button.VisibleWhen(isVisible); - Buttons.Add(button); + Buttons.Add(button); - return this; - } + return this; + } - public INodeEditorConfig AddNavigationButton(string? label = null, string? icon = null, Func? isVisible = null) - where TNavigationHandler : INavigationHandler + public INodeEditorConfig AddNavigationButton(string? label = null, string? icon = null, Func? isVisible = null) + where TNavigationHandler : INavigationHandler + { + var button = new NavigationButtonConfig(typeof(TNavigationHandler)) { - var button = new NavigationButtonConfig(typeof(TNavigationHandler)) - { - Icon = icon, - Label = label - }; + Icon = icon, + Label = label + }; - button.VisibleWhen(isVisible); + button.VisibleWhen(isVisible); - Buttons.Add(button); + Buttons.Add(button); - return this; - } + return this; + } - public INodeEditorConfig AddSection(Action>? configure) - => AddSection(configure); + public INodeEditorConfig AddSection(Action>? configure) + => AddSection(configure); - public INodeEditorConfig AddSection(Type customSectionType, Action>? configure = null) - => AddSection(customSectionType, configure); + public INodeEditorConfig AddSection(Type customSectionType, Action>? configure = null) + => AddSection(customSectionType, configure); - public INodeEditorConfig AddSection(Action>? configure) - where TDerivedEntity : TEntity - => AddSection(null, configure); + public INodeEditorConfig AddSection(Action>? configure) + where TDerivedEntity : TEntity + => AddSection(null, configure); - public INodeEditorConfig AddSection(Type? customSectionType, Action>? configure) - where TDerivedEntity : TEntity - { - var config = customSectionType == null - ? new PaneConfig(typeof(TDerivedEntity)) - : new PaneConfig(typeof(TDerivedEntity), customSectionType); + public INodeEditorConfig AddSection(Type? customSectionType, Action>? configure) + where TDerivedEntity : TEntity + { + var config = customSectionType == null + ? new PaneConfig(typeof(TDerivedEntity)) + : new PaneConfig(typeof(TDerivedEntity), customSectionType); - configure?.Invoke(config); + configure?.Invoke(config); - Panes.Add(config); + Panes.Add(config); - return this; - } + return this; } } diff --git a/src/RapidCMS.Core/Models/Config/NodeViewConfig.cs b/src/RapidCMS.Core/Models/Config/NodeViewConfig.cs index 23a32d5e..9a653f6c 100644 --- a/src/RapidCMS.Core/Models/Config/NodeViewConfig.cs +++ b/src/RapidCMS.Core/Models/Config/NodeViewConfig.cs @@ -4,101 +4,100 @@ using RapidCMS.Core.Abstractions.Handlers; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Models.Config +namespace RapidCMS.Core.Models.Config; + +internal class NodeViewConfig : NodeConfig, INodeViewConfig + where TEntity : IEntity { - internal class NodeViewConfig : NodeConfig, INodeViewConfig - where TEntity : IEntity + public NodeViewConfig() : base(typeof(TEntity)) { - public NodeViewConfig() : base(typeof(TEntity)) - { - } + } - public INodeViewConfig AddDefaultButton(DefaultButtonType type, string? label = null, string? icon = null, bool isPrimary = false, Func? isVisible = null) + public INodeViewConfig AddDefaultButton(DefaultButtonType type, string? label = null, string? icon = null, bool isPrimary = false, Func? isVisible = null) + { + var button = new DefaultButtonConfig { - var button = new DefaultButtonConfig - { - ButtonType = type, - Icon = icon, - Label = label, - IsPrimary = isPrimary - }; + ButtonType = type, + Icon = icon, + Label = label, + IsPrimary = isPrimary + }; - button.VisibleWhen(isVisible); + button.VisibleWhen(isVisible); - Buttons.Add(button); + Buttons.Add(button); - return this; - } + return this; + } - public INodeViewConfig AddCustomButton(Type buttonType, string? label = null, string? icon = null, Func? isVisible = null) - where TActionHandler : IButtonActionHandler + public INodeViewConfig AddCustomButton(Type buttonType, string? label = null, string? icon = null, Func? isVisible = null) + where TActionHandler : IButtonActionHandler + { + var button = new CustomButtonConfig(buttonType, typeof(TActionHandler)) { - var button = new CustomButtonConfig(buttonType, typeof(TActionHandler)) - { - Icon = icon, - Label = label - }; + Icon = icon, + Label = label + }; - button.VisibleWhen(isVisible); + button.VisibleWhen(isVisible); - Buttons.Add(button); + Buttons.Add(button); - return this; - } + return this; + } - public INodeViewConfig AddPaneButton(Type paneType, string? label = null, string? icon = null, Func? isVisible = null) + public INodeViewConfig AddPaneButton(Type paneType, string? label = null, string? icon = null, Func? isVisible = null) + { + var button = new PaneButtonConfig(paneType) { - var button = new PaneButtonConfig(paneType) - { - Icon = icon, - Label = label - }; + Icon = icon, + Label = label + }; - button.VisibleWhen(isVisible); + button.VisibleWhen(isVisible); - Buttons.Add(button); + Buttons.Add(button); - return this; - } + return this; + } - public INodeViewConfig AddNavigationButton(string? label = null, string? icon = null, Func? isVisible = null) - where TNavigationHandler : INavigationHandler + public INodeViewConfig AddNavigationButton(string? label = null, string? icon = null, Func? isVisible = null) + where TNavigationHandler : INavigationHandler + { + var button = new NavigationButtonConfig(typeof(TNavigationHandler)) { - var button = new NavigationButtonConfig(typeof(TNavigationHandler)) - { - Icon = icon, - Label = label - }; + Icon = icon, + Label = label + }; - button.VisibleWhen(isVisible); + button.VisibleWhen(isVisible); - Buttons.Add(button); + Buttons.Add(button); - return this; - } + return this; + } - public INodeViewConfig AddSection(Action> configure) - => AddSection(configure); + public INodeViewConfig AddSection(Action> configure) + => AddSection(configure); - public INodeViewConfig AddSection(Type customSectionType, Action>? configure = null) - => AddSection(customSectionType, configure); + public INodeViewConfig AddSection(Type customSectionType, Action>? configure = null) + => AddSection(customSectionType, configure); - public INodeViewConfig AddSection(Action> configure) - where TDerivedEntity : TEntity - => AddSection(null, configure); + public INodeViewConfig AddSection(Action> configure) + where TDerivedEntity : TEntity + => AddSection(null, configure); - public INodeViewConfig AddSection(Type? customSectionType, Action>? configure) - where TDerivedEntity : TEntity - { - var config = customSectionType == null - ? new PaneConfig(typeof(TDerivedEntity)) - : new PaneConfig(typeof(TDerivedEntity), customSectionType); + public INodeViewConfig AddSection(Type? customSectionType, Action>? configure) + where TDerivedEntity : TEntity + { + var config = customSectionType == null + ? new PaneConfig(typeof(TDerivedEntity)) + : new PaneConfig(typeof(TDerivedEntity), customSectionType); - configure?.Invoke(config); + configure?.Invoke(config); - Panes.Add(config); + Panes.Add(config); - return this; - } + return this; } } diff --git a/src/RapidCMS.Core/Models/Config/OrderByConfig.cs b/src/RapidCMS.Core/Models/Config/OrderByConfig.cs index 49e24672..ebe2bebd 100644 --- a/src/RapidCMS.Core/Models/Config/OrderByConfig.cs +++ b/src/RapidCMS.Core/Models/Config/OrderByConfig.cs @@ -6,24 +6,23 @@ using RapidCMS.Core.Enums; using RapidCMS.Core.Helpers; -namespace RapidCMS.Core.Models.Config +namespace RapidCMS.Core.Models.Config; + +internal class OrderByConfig : IOrderByConfig { - internal class OrderByConfig : IOrderByConfig - { - public Dictionary DefaultOrderBys { get; set; } = new(); + public Dictionary DefaultOrderBys { get; set; } = new(); - public IOrderByConfig SetOrderByExpression(Expression> orderByExpression, OrderByType defaultOrder = OrderByType.None) - { - DefaultOrderBys[PropertyMetadataHelper.GetPropertyMetadata(orderByExpression) ?? throw new InvalidOperationException("Cannot determine orderByExpression")] = defaultOrder; + public IOrderByConfig SetOrderByExpression(Expression> orderByExpression, OrderByType defaultOrder = OrderByType.None) + { + DefaultOrderBys[PropertyMetadataHelper.GetPropertyMetadata(orderByExpression) ?? throw new InvalidOperationException("Cannot determine orderByExpression")] = defaultOrder; - return this; - } + return this; + } - public IOrderByConfig SetOrderByExpression(Expression> orderByExpression, OrderByType defaultOrder = OrderByType.None) - { - DefaultOrderBys[PropertyMetadataHelper.GetPropertyMetadata(orderByExpression) ?? throw new InvalidOperationException("Cannot determine orderByExpression")] = defaultOrder; + public IOrderByConfig SetOrderByExpression(Expression> orderByExpression, OrderByType defaultOrder = OrderByType.None) + { + DefaultOrderBys[PropertyMetadataHelper.GetPropertyMetadata(orderByExpression) ?? throw new InvalidOperationException("Cannot determine orderByExpression")] = defaultOrder; - return this; - } + return this; } } diff --git a/src/RapidCMS.Core/Models/Config/PageConfig.cs b/src/RapidCMS.Core/Models/Config/PageConfig.cs index 88228e20..999b3925 100644 --- a/src/RapidCMS.Core/Models/Config/PageConfig.cs +++ b/src/RapidCMS.Core/Models/Config/PageConfig.cs @@ -7,50 +7,49 @@ using RapidCMS.Core.Extensions; using RapidCMS.Core.Navigation; -namespace RapidCMS.Core.Models.Config +namespace RapidCMS.Core.Models.Config; + +internal class PageConfig : IPageConfig { - internal class PageConfig : IPageConfig + public PageConfig(string name, string icon, string color, string alias) { - public PageConfig(string name, string icon, string color, string alias) - { - Name = name ?? throw new ArgumentNullException(nameof(name)); - Icon = icon ?? throw new ArgumentNullException(nameof(icon)); - Color = color ?? throw new ArgumentNullException(nameof(color)); - Alias = alias ?? throw new ArgumentNullException(nameof(alias)); - } + Name = name ?? throw new ArgumentNullException(nameof(name)); + Icon = icon ?? throw new ArgumentNullException(nameof(icon)); + Color = color ?? throw new ArgumentNullException(nameof(color)); + Alias = alias ?? throw new ArgumentNullException(nameof(alias)); + } - public string Name { get; set; } - public string Icon { get; set; } - public string Color { get; set; } - public string Alias { get; set; } + public string Name { get; set; } + public string Icon { get; set; } + public string Color { get; set; } + public string Alias { get; set; } - internal List SectionRegistrations { get; set; } = new List(); + internal List SectionRegistrations { get; set; } = new List(); - public IPageConfig AddSection(string collectionAlias, bool edit = false) - { - SectionRegistrations.Add( - new CustomTypeRegistrationConfig( - typeof(ICollectionConfig), - new Dictionary { - { - "InitialState", - new NavigationState(collectionAlias, default(IRelated), edit ? UsageType.Edit : UsageType.View) - } - })); - - return this; - } + public IPageConfig AddSection(string collectionAlias, bool edit = false) + { + SectionRegistrations.Add( + new CustomTypeRegistrationConfig( + typeof(ICollectionConfig), + new Dictionary { + { + "InitialState", + new NavigationState(collectionAlias, default(IRelated), edit ? UsageType.Edit : UsageType.View) + } + })); + + return this; + } - public IPageConfig AddSection(Type customSectionType) + public IPageConfig AddSection(Type customSectionType) + { + if (!customSectionType.IsSameTypeOrDerivedFrom(typeof(ComponentBase))) { - if (!customSectionType.IsSameTypeOrDerivedFrom(typeof(ComponentBase))) - { - throw new InvalidOperationException($"{nameof(customSectionType)} must be derived of {nameof(ComponentBase)}."); - } + throw new InvalidOperationException($"{nameof(customSectionType)} must be derived of {nameof(ComponentBase)}."); + } - SectionRegistrations.Add(new CustomTypeRegistrationConfig(customSectionType)); + SectionRegistrations.Add(new CustomTypeRegistrationConfig(customSectionType)); - return this; - } + return this; } } diff --git a/src/RapidCMS.Core/Models/Config/PaneButtonConfig.cs b/src/RapidCMS.Core/Models/Config/PaneButtonConfig.cs index 8ae77511..cfbf4abb 100644 --- a/src/RapidCMS.Core/Models/Config/PaneButtonConfig.cs +++ b/src/RapidCMS.Core/Models/Config/PaneButtonConfig.cs @@ -1,14 +1,13 @@ using System; -namespace RapidCMS.Core.Models.Config +namespace RapidCMS.Core.Models.Config; + +internal class PaneButtonConfig : ButtonConfig { - internal class PaneButtonConfig : ButtonConfig + internal PaneButtonConfig(Type paneType) { - internal PaneButtonConfig(Type paneType) - { - PaneType = paneType ?? throw new ArgumentNullException(nameof(paneType)); - } - - internal Type PaneType { get; set; } + PaneType = paneType ?? throw new ArgumentNullException(nameof(paneType)); } + + internal Type PaneType { get; set; } } diff --git a/src/RapidCMS.Core/Models/Config/PaneConfig.cs b/src/RapidCMS.Core/Models/Config/PaneConfig.cs index e640906b..f74ba078 100644 --- a/src/RapidCMS.Core/Models/Config/PaneConfig.cs +++ b/src/RapidCMS.Core/Models/Config/PaneConfig.cs @@ -8,267 +8,266 @@ using RapidCMS.Core.Exceptions; using RapidCMS.Core.Helpers; -namespace RapidCMS.Core.Models.Config +namespace RapidCMS.Core.Models.Config; + +internal class PaneConfig { - internal class PaneConfig + internal PaneConfig(Type variantType) { - internal PaneConfig(Type variantType) - { - VariantType = variantType ?? throw new ArgumentNullException(nameof(variantType)); - } + VariantType = variantType ?? throw new ArgumentNullException(nameof(variantType)); + } - internal Type? CustomType { get; set; } - internal string? Label { get; set; } + internal Type? CustomType { get; set; } + internal string? Label { get; set; } - internal Func IsVisible { get; set; } = (x, y) => true; + internal Func IsVisible { get; set; } = (x, y) => true; - internal Type VariantType { get; set; } + internal Type VariantType { get; set; } - internal List Buttons { get; set; } = new List(); - internal List Fields { get; set; } = new List(); - internal List SubCollectionLists { get; set; } = new List(); - internal List RelatedCollectionLists { get; set; } = new List(); + internal List Buttons { get; set; } = new List(); + internal List Fields { get; set; } = new List(); + internal List SubCollectionLists { get; set; } = new List(); + internal List RelatedCollectionLists { get; set; } = new List(); - internal int FieldIndex { get; set; } = 0; - } + internal int FieldIndex { get; set; } = 0; +} - internal class PaneConfig : PaneConfig, IDisplayPaneConfig, IEditorPaneConfig - where TEntity : IEntity +internal class PaneConfig : PaneConfig, IDisplayPaneConfig, IEditorPaneConfig + where TEntity : IEntity +{ + internal PaneConfig(Type variantType) : base(variantType) { - internal PaneConfig(Type variantType) : base(variantType) - { - } + } - internal PaneConfig(Type variantType, Type customSectionType) : base(variantType) - { - CustomType = customSectionType; - } + internal PaneConfig(Type variantType, Type customSectionType) : base(variantType) + { + CustomType = customSectionType; + } - private PaneConfig AddDefaultButton(DefaultButtonType type, string? label, string? icon, bool isPrimary, Func? predicate) + private PaneConfig AddDefaultButton(DefaultButtonType type, string? label, string? icon, bool isPrimary, Func? predicate) + { + var button = new DefaultButtonConfig { - var button = new DefaultButtonConfig - { - ButtonType = type, - Icon = icon, - Label = label, - IsPrimary = isPrimary - }; + ButtonType = type, + Icon = icon, + Label = label, + IsPrimary = isPrimary + }; - button.VisibleWhen(predicate); + button.VisibleWhen(predicate); - Buttons.Add(button); + Buttons.Add(button); - return this; - } + return this; + } - private PaneConfig AddCustomButton(Type buttonType, string? label, string? icon, Func? predicate) + private PaneConfig AddCustomButton(Type buttonType, string? label, string? icon, Func? predicate) + { + var button = new CustomButtonConfig(buttonType, typeof(TActionHandler)) { - var button = new CustomButtonConfig(buttonType, typeof(TActionHandler)) - { - Icon = icon, - Label = label - }; + Icon = icon, + Label = label + }; - button.VisibleWhen(predicate); + button.VisibleWhen(predicate); - Buttons.Add(button); + Buttons.Add(button); - return this; - } + return this; + } - private PaneConfig AddPaneButton(Type paneType, string? label, string? icon, Func? predicate) + private PaneConfig AddPaneButton(Type paneType, string? label, string? icon, Func? predicate) + { + var button = new PaneButtonConfig(paneType) { - var button = new PaneButtonConfig(paneType) - { - Icon = icon, - Label = label - }; + Icon = icon, + Label = label + }; - button.VisibleWhen(predicate); + button.VisibleWhen(predicate); - Buttons.Add(button); + Buttons.Add(button); - return this; - } + return this; + } - public PaneConfig AddNavigationButton(string? label, string? icon, Func? predicate) + public PaneConfig AddNavigationButton(string? label, string? icon, Func? predicate) + { + var button = new NavigationButtonConfig(typeof(TNavigationHandler)) { - var button = new NavigationButtonConfig(typeof(TNavigationHandler)) - { - Icon = icon, - Label = label - }; + Icon = icon, + Label = label + }; - button.VisibleWhen(predicate); + button.VisibleWhen(predicate); - Buttons.Add(button); + Buttons.Add(button); - return this; - } + return this; + } - private PaneConfig SetLabel(string label) - { - Label = label; + private PaneConfig SetLabel(string label) + { + Label = label; - return this; - } + return this; + } - private PaneConfig AddSubCollectionList(string collectionAlias) + private PaneConfig AddSubCollectionList(string collectionAlias) + { + var config = new ReferencedCollectionListConfig(collectionAlias) { - var config = new ReferencedCollectionListConfig(collectionAlias) - { - Index = FieldIndex++ - }; + Index = FieldIndex++ + }; - SubCollectionLists.Add(config); + SubCollectionLists.Add(config); - return this; - } + return this; + } - private PaneConfig AddRelatedCollectionList(string collectionAlias) + private PaneConfig AddRelatedCollectionList(string collectionAlias) + { + var config = new ReferencedCollectionListConfig(collectionAlias) { - var config = new ReferencedCollectionListConfig(collectionAlias) - { - Index = FieldIndex++ - }; + Index = FieldIndex++ + }; - RelatedCollectionLists.Add(config); + RelatedCollectionLists.Add(config); - return this; - } + return this; + } - private PaneConfig AddSubCollectionList(Action>? configure = null) - where TSubEntity : IEntity - where TSubRepository : IRepository - { - var config = new SubCollectionListConfig(Guid.NewGuid().ToString()); + private PaneConfig AddSubCollectionList(Action>? configure = null) + where TSubEntity : IEntity + where TSubRepository : IRepository + { + var config = new SubCollectionListConfig(Guid.NewGuid().ToString()); - configure?.Invoke(config); + configure?.Invoke(config); - config.Index = FieldIndex++; + config.Index = FieldIndex++; - SubCollectionLists.Add(config); + SubCollectionLists.Add(config); - return this; - } + return this; + } - private PaneConfig AddRelatedCollectionList(Action>? configure = null) - where TRelatedEntity : IEntity - where TRelatedRepository : IRepository - { - var config = new RelatedCollectionListConfig(Guid.NewGuid().ToString()); + private PaneConfig AddRelatedCollectionList(Action>? configure = null) + where TRelatedEntity : IEntity + where TRelatedRepository : IRepository + { + var config = new RelatedCollectionListConfig(Guid.NewGuid().ToString()); - configure?.Invoke(config); + configure?.Invoke(config); - config.Index = FieldIndex++; + config.Index = FieldIndex++; - RelatedCollectionLists.Add(config); + RelatedCollectionLists.Add(config); - return this; - } + return this; + } - private PaneConfig VisibleWhen(Func predicate) - { - IsVisible = (entity, state) => predicate.Invoke((TEntity)entity, state); + private PaneConfig VisibleWhen(Func predicate) + { + IsVisible = (entity, state) => predicate.Invoke((TEntity)entity, state); - return this; - } + return this; + } - IDisplayFieldConfig IDisplayPaneConfig.AddField(Expression> displayExpression, Action>? configure) + IDisplayFieldConfig IDisplayPaneConfig.AddField(Expression> displayExpression, Action>? configure) + { + var config = new FieldConfig() { - var config = new FieldConfig() - { - Expression = PropertyMetadataHelper.GetExpressionMetadata(displayExpression) ?? throw new InvalidPropertyExpressionException(nameof(displayExpression)), - }; - config.Name = config.Expression.PropertyName; - config.DisplayType = default; + Expression = PropertyMetadataHelper.GetExpressionMetadata(displayExpression) ?? throw new InvalidPropertyExpressionException(nameof(displayExpression)), + }; + config.Name = config.Expression.PropertyName; + config.DisplayType = default; - configure?.Invoke(config); + configure?.Invoke(config); - config.Index = FieldIndex++; + config.Index = FieldIndex++; - Fields.Add(config); + Fields.Add(config); - return config; - } + return config; + } - IDisplayPaneConfig IHasButtons>.AddDefaultButton(DefaultButtonType type, string? label, string? icon, bool isPrimary, Func? isVisible) - => AddDefaultButton(type, label, icon, isPrimary, isVisible); + IDisplayPaneConfig IHasButtons>.AddDefaultButton(DefaultButtonType type, string? label, string? icon, bool isPrimary, Func? isVisible) + => AddDefaultButton(type, label, icon, isPrimary, isVisible); - IDisplayPaneConfig IHasButtons>.AddCustomButton(Type buttonType, string? label, string? icon, Func? isVisible) - => AddCustomButton(buttonType, label, icon, isVisible); + IDisplayPaneConfig IHasButtons>.AddCustomButton(Type buttonType, string? label, string? icon, Func? isVisible) + => AddCustomButton(buttonType, label, icon, isVisible); - IDisplayPaneConfig IHasButtons>.AddPaneButton(Type paneType, string? label, string? icon, Func? isVisible) - => AddPaneButton(paneType, label, icon, isVisible); + IDisplayPaneConfig IHasButtons>.AddPaneButton(Type paneType, string? label, string? icon, Func? isVisible) + => AddPaneButton(paneType, label, icon, isVisible); - IDisplayPaneConfig IHasButtons>.AddNavigationButton(string? label, string? icon, Func? isVisible) - => AddNavigationButton(label, icon, isVisible); + IDisplayPaneConfig IHasButtons>.AddNavigationButton(string? label, string? icon, Func? isVisible) + => AddNavigationButton(label, icon, isVisible); - IDisplayPaneConfig IDisplayPaneConfig.AddSubCollectionList(string collectionAlias) - => AddSubCollectionList(collectionAlias); + IDisplayPaneConfig IDisplayPaneConfig.AddSubCollectionList(string collectionAlias) + => AddSubCollectionList(collectionAlias); - IDisplayPaneConfig IDisplayPaneConfig.AddSubCollectionList(Action>? configure) - => AddSubCollectionList(configure); + IDisplayPaneConfig IDisplayPaneConfig.AddSubCollectionList(Action>? configure) + => AddSubCollectionList(configure); - IDisplayPaneConfig IDisplayPaneConfig.AddRelatedCollectionList(string collectionAlias) - => AddRelatedCollectionList(collectionAlias); + IDisplayPaneConfig IDisplayPaneConfig.AddRelatedCollectionList(string collectionAlias) + => AddRelatedCollectionList(collectionAlias); - IDisplayPaneConfig IDisplayPaneConfig.AddRelatedCollectionList(Action>? configure) - => AddRelatedCollectionList(configure); + IDisplayPaneConfig IDisplayPaneConfig.AddRelatedCollectionList(Action>? configure) + => AddRelatedCollectionList(configure); - IDisplayPaneConfig IDisplayPaneConfig.SetLabel(string label) - => SetLabel(label); + IDisplayPaneConfig IDisplayPaneConfig.SetLabel(string label) + => SetLabel(label); - IDisplayPaneConfig IDisplayPaneConfig.VisibleWhen(Func predicate) - => VisibleWhen(predicate); + IDisplayPaneConfig IDisplayPaneConfig.VisibleWhen(Func predicate) + => VisibleWhen(predicate); - IEditorFieldConfig IEditorPaneConfig.AddField(Expression> propertyExpression, Action>? configure) + IEditorFieldConfig IEditorPaneConfig.AddField(Expression> propertyExpression, Action>? configure) + { + var config = new FieldConfig() { - var config = new FieldConfig() - { - Property = PropertyMetadataHelper.GetPropertyMetadata(propertyExpression) ?? throw new InvalidPropertyExpressionException(nameof(propertyExpression)), - }; - config.Name = config.Property.PropertyName; - config.EditorType = EditorTypeHelper.TryFindDefaultEditorType(config.Property.PropertyType); + Property = PropertyMetadataHelper.GetPropertyMetadata(propertyExpression) ?? throw new InvalidPropertyExpressionException(nameof(propertyExpression)), + }; + config.Name = config.Property.PropertyName; + config.EditorType = EditorTypeHelper.TryFindDefaultEditorType(config.Property.PropertyType); - configure?.Invoke(config); + configure?.Invoke(config); - config.Index = FieldIndex++; + config.Index = FieldIndex++; - Fields.Add(config); + Fields.Add(config); - return config; - } + return config; + } - IEditorPaneConfig IHasButtons>.AddDefaultButton(DefaultButtonType type, string? label, string? icon, bool isPrimary, Func? isVisible) - => AddDefaultButton(type, label, icon, isPrimary, isVisible); + IEditorPaneConfig IHasButtons>.AddDefaultButton(DefaultButtonType type, string? label, string? icon, bool isPrimary, Func? isVisible) + => AddDefaultButton(type, label, icon, isPrimary, isVisible); - IEditorPaneConfig IHasButtons>.AddCustomButton(Type buttonType, string? label, string? icon, Func? isVisible) - => AddCustomButton(buttonType, label, icon, isVisible); + IEditorPaneConfig IHasButtons>.AddCustomButton(Type buttonType, string? label, string? icon, Func? isVisible) + => AddCustomButton(buttonType, label, icon, isVisible); - IEditorPaneConfig IHasButtons>.AddPaneButton(Type paneType, string? label, string? icon, Func? isVisible) - => AddPaneButton(paneType, label, icon, isVisible); + IEditorPaneConfig IHasButtons>.AddPaneButton(Type paneType, string? label, string? icon, Func? isVisible) + => AddPaneButton(paneType, label, icon, isVisible); - IEditorPaneConfig IHasButtons>.AddNavigationButton(string? label, string? icon, Func? isVisible) - => AddNavigationButton(label, icon, isVisible); + IEditorPaneConfig IHasButtons>.AddNavigationButton(string? label, string? icon, Func? isVisible) + => AddNavigationButton(label, icon, isVisible); - IEditorPaneConfig IEditorPaneConfig.AddSubCollectionList(string collectionAlias) - => AddSubCollectionList(collectionAlias); + IEditorPaneConfig IEditorPaneConfig.AddSubCollectionList(string collectionAlias) + => AddSubCollectionList(collectionAlias); - IEditorPaneConfig IEditorPaneConfig.AddSubCollectionList(Action>? configure) - => AddSubCollectionList(configure); + IEditorPaneConfig IEditorPaneConfig.AddSubCollectionList(Action>? configure) + => AddSubCollectionList(configure); - IEditorPaneConfig IEditorPaneConfig.AddRelatedCollectionList(string collectionAlias) - => AddRelatedCollectionList(collectionAlias); + IEditorPaneConfig IEditorPaneConfig.AddRelatedCollectionList(string collectionAlias) + => AddRelatedCollectionList(collectionAlias); - IEditorPaneConfig IEditorPaneConfig.AddRelatedCollectionList(Action>? configure) - => AddRelatedCollectionList(configure); + IEditorPaneConfig IEditorPaneConfig.AddRelatedCollectionList(Action>? configure) + => AddRelatedCollectionList(configure); - IEditorPaneConfig IEditorPaneConfig.SetLabel(string label) - => SetLabel(label); + IEditorPaneConfig IEditorPaneConfig.SetLabel(string label) + => SetLabel(label); - IEditorPaneConfig IEditorPaneConfig.VisibleWhen(Func predicate) - => VisibleWhen(predicate); - } + IEditorPaneConfig IEditorPaneConfig.VisibleWhen(Func predicate) + => VisibleWhen(predicate); } diff --git a/src/RapidCMS.Core/Models/Config/ReferencedCollectionConfig.cs b/src/RapidCMS.Core/Models/Config/ReferencedCollectionConfig.cs index 865a84ac..bf6092ad 100644 --- a/src/RapidCMS.Core/Models/Config/ReferencedCollectionConfig.cs +++ b/src/RapidCMS.Core/Models/Config/ReferencedCollectionConfig.cs @@ -1,13 +1,12 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Abstractions.Repositories; -namespace RapidCMS.Core.Models.Config +namespace RapidCMS.Core.Models.Config; + +internal class ReferencedCollectionConfig : CollectionConfig { - internal class ReferencedCollectionConfig : CollectionConfig + internal ReferencedCollectionConfig(string alias) + : base(alias, default, default, default, "reference", typeof(IRepository), new EntityVariantConfig("", typeof(IEntity))) { - internal ReferencedCollectionConfig(string alias) - : base(alias, default, default, default, "reference", typeof(IRepository), new EntityVariantConfig("", typeof(IEntity))) - { - } } } diff --git a/src/RapidCMS.Core/Models/Config/ReferencedCollectionListConfig.cs b/src/RapidCMS.Core/Models/Config/ReferencedCollectionListConfig.cs index 90a55650..283c7381 100644 --- a/src/RapidCMS.Core/Models/Config/ReferencedCollectionListConfig.cs +++ b/src/RapidCMS.Core/Models/Config/ReferencedCollectionListConfig.cs @@ -1,9 +1,8 @@ -namespace RapidCMS.Core.Models.Config +namespace RapidCMS.Core.Models.Config; + +internal class ReferencedCollectionListConfig : CollectionListConfig { - internal class ReferencedCollectionListConfig : CollectionListConfig + internal ReferencedCollectionListConfig(string collectionAlias) : base(collectionAlias) { - internal ReferencedCollectionListConfig(string collectionAlias) : base(collectionAlias) - { - } } } diff --git a/src/RapidCMS.Core/Models/Config/RelatedCollectionListConfig.cs b/src/RapidCMS.Core/Models/Config/RelatedCollectionListConfig.cs index 7851997a..97ac4d54 100644 --- a/src/RapidCMS.Core/Models/Config/RelatedCollectionListConfig.cs +++ b/src/RapidCMS.Core/Models/Config/RelatedCollectionListConfig.cs @@ -3,45 +3,44 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Abstractions.Repositories; -namespace RapidCMS.Core.Models.Config -{ - internal class RelatedCollectionListConfig : CollectionListConfig, - IRelatedCollectionListViewConfig, - IRelatedCollectionListEditorConfig +namespace RapidCMS.Core.Models.Config; + +internal class RelatedCollectionListConfig : CollectionListConfig, + IRelatedCollectionListViewConfig, + IRelatedCollectionListEditorConfig - where TRelatedEntity : IEntity - where TRelatedRepository : IRepository + where TRelatedEntity : IEntity + where TRelatedRepository : IRepository +{ + internal RelatedCollectionListConfig(string collectionAlias) : base(collectionAlias) { - internal RelatedCollectionListConfig(string collectionAlias) : base(collectionAlias) - { - } + } - public IRelatedCollectionListEditorConfig SetListEditor(Action> configure) - { - RepositoryType = typeof(TRelatedRepository); - EntityType = typeof(TRelatedEntity); + public IRelatedCollectionListEditorConfig SetListEditor(Action> configure) + { + RepositoryType = typeof(TRelatedRepository); + EntityType = typeof(TRelatedEntity); - var config = new ListEditorConfig(); + var config = new ListEditorConfig(); - configure.Invoke(config); + configure.Invoke(config); - ListEditor = config; + ListEditor = config; - return this; - } + return this; + } - public IRelatedCollectionListViewConfig SetListView(Action> configure) - { - RepositoryType = typeof(TRelatedRepository); - EntityType = typeof(TRelatedEntity); + public IRelatedCollectionListViewConfig SetListView(Action> configure) + { + RepositoryType = typeof(TRelatedRepository); + EntityType = typeof(TRelatedEntity); - var config = new ListViewConfig(); + var config = new ListViewConfig(); - configure.Invoke(config); + configure.Invoke(config); - ListView = config; + ListView = config; - return this; - } + return this; } } diff --git a/src/RapidCMS.Core/Models/Config/RelationConfig.cs b/src/RapidCMS.Core/Models/Config/RelationConfig.cs index d2046776..7ea326a2 100644 --- a/src/RapidCMS.Core/Models/Config/RelationConfig.cs +++ b/src/RapidCMS.Core/Models/Config/RelationConfig.cs @@ -1,7 +1,6 @@  -namespace RapidCMS.Core.Models.Config +namespace RapidCMS.Core.Models.Config; + +internal class RelationConfig { - internal class RelationConfig - { - } } diff --git a/src/RapidCMS.Core/Models/Config/RelationDataProviderRelationConfig.cs b/src/RapidCMS.Core/Models/Config/RelationDataProviderRelationConfig.cs index a865ff6a..659bfe94 100644 --- a/src/RapidCMS.Core/Models/Config/RelationDataProviderRelationConfig.cs +++ b/src/RapidCMS.Core/Models/Config/RelationDataProviderRelationConfig.cs @@ -1,16 +1,15 @@ using System; -namespace RapidCMS.Core.Models.Config +namespace RapidCMS.Core.Models.Config; + +internal class RelationDataProviderRelationConfig : RelationConfig { - internal class RelationDataProviderRelationConfig : RelationConfig + internal RelationDataProviderRelationConfig(Type relationDataCollectionType, object? configuration) { - internal RelationDataProviderRelationConfig(Type relationDataCollectionType, object? configuration) - { - RelationDataCollectionType = relationDataCollectionType ?? throw new ArgumentNullException(nameof(relationDataCollectionType)); - Configuration = configuration; - } - - public Type RelationDataCollectionType { get; } - public object? Configuration { get; } + RelationDataCollectionType = relationDataCollectionType ?? throw new ArgumentNullException(nameof(relationDataCollectionType)); + Configuration = configuration; } + + public Type RelationDataCollectionType { get; } + public object? Configuration { get; } } diff --git a/src/RapidCMS.Core/Models/Config/RepositoryRelationConfig.cs b/src/RapidCMS.Core/Models/Config/RepositoryRelationConfig.cs index 63c91c01..38a38089 100644 --- a/src/RapidCMS.Core/Models/Config/RepositoryRelationConfig.cs +++ b/src/RapidCMS.Core/Models/Config/RepositoryRelationConfig.cs @@ -8,93 +8,92 @@ using RapidCMS.Core.Exceptions; using RapidCMS.Core.Helpers; -namespace RapidCMS.Core.Models.Config +namespace RapidCMS.Core.Models.Config; + +internal class RepositoryRelationConfig : RelationConfig { - internal class RepositoryRelationConfig : RelationConfig + public RepositoryRelationConfig() + { + + } + + public RepositoryRelationConfig(string? collectionAlias, bool isRelationToMany) + { + CollectionAlias = collectionAlias; + IsRelationToMany = isRelationToMany; + } + + protected internal string? CollectionAlias { get; private set; } + protected internal Type? RepositoryType { get; protected set; } + internal Type? RelatedEntityType { get; set; } + protected internal Type? RelatedRepositoryType { get; protected set; } + internal IPropertyMetadata? RelatedElementsGetter { get; set; } + internal IPropertyMetadata? RepositoryParentProperty { get; set; } + internal bool EntityAsParent { get; set; } + internal IPropertyMetadata? IdProperty { get; set; } + internal List? DisplayProperties { get; set; } + internal bool IsRelationToMany { get; set; } +} + +internal class RepositoryRelationConfig : RepositoryRelationConfig, ICollectionRelationConfig + where TEntity : IEntity +{ + public RepositoryRelationConfig(string collectionAlias, bool isRelationToMany) : base(collectionAlias, isRelationToMany) + { + RelatedEntityType = typeof(TRelatedEntity); + } + + public RepositoryRelationConfig(Type relatedRepositoryType, bool isRelationToMany) + { + RepositoryType = relatedRepositoryType; + RelatedEntityType = typeof(TRelatedEntity); + RelatedRepositoryType = relatedRepositoryType; + IsRelationToMany = isRelationToMany; + } + + public RepositoryRelationConfig(string collectionAlias, IPropertyMetadata relatedElements) : base(collectionAlias, true) { - public RepositoryRelationConfig() - { - - } - - public RepositoryRelationConfig(string? collectionAlias, bool isRelationToMany) - { - CollectionAlias = collectionAlias; - IsRelationToMany = isRelationToMany; - } - - protected internal string? CollectionAlias { get; private set; } - protected internal Type? RepositoryType { get; protected set; } - internal Type? RelatedEntityType { get; set; } - protected internal Type? RelatedRepositoryType { get; protected set; } - internal IPropertyMetadata? RelatedElementsGetter { get; set; } - internal IPropertyMetadata? RepositoryParentProperty { get; set; } - internal bool EntityAsParent { get; set; } - internal IPropertyMetadata? IdProperty { get; set; } - internal List? DisplayProperties { get; set; } - internal bool IsRelationToMany { get; set; } + RelatedEntityType = typeof(TRelatedEntity); + RelatedElementsGetter = relatedElements; } - internal class RepositoryRelationConfig : RepositoryRelationConfig, ICollectionRelationConfig - where TEntity : IEntity + public RepositoryRelationConfig(Type relatedRepositoryType, IPropertyMetadata relatedElements) { - public RepositoryRelationConfig(string collectionAlias, bool isRelationToMany) : base(collectionAlias, isRelationToMany) - { - RelatedEntityType = typeof(TRelatedEntity); - } - - public RepositoryRelationConfig(Type relatedRepositoryType, bool isRelationToMany) - { - RepositoryType = relatedRepositoryType; - RelatedEntityType = typeof(TRelatedEntity); - RelatedRepositoryType = relatedRepositoryType; - IsRelationToMany = isRelationToMany; - } - - public RepositoryRelationConfig(string collectionAlias, IPropertyMetadata relatedElements) : base(collectionAlias, true) - { - RelatedEntityType = typeof(TRelatedEntity); - RelatedElementsGetter = relatedElements; - } - - public RepositoryRelationConfig(Type relatedRepositoryType, IPropertyMetadata relatedElements) - { - RepositoryType = relatedRepositoryType; - RelatedEntityType = typeof(TRelatedEntity); - RelatedRepositoryType = relatedRepositoryType; - RelatedElementsGetter = relatedElements; - IsRelationToMany = true; - } - - public ICollectionRelationConfig SetElementIdProperty(Expression> propertyExpression) - { - IdProperty = PropertyMetadataHelper.GetPropertyMetadata(propertyExpression) ?? throw new InvalidPropertyExpressionException(nameof(propertyExpression)); - - return this; - } - - public ICollectionRelationConfig SetElementDisplayProperties(params Expression>[] propertyExpressions) - { - DisplayProperties = propertyExpressions - .Select(propertyExpression => PropertyMetadataHelper.GetExpressionMetadata(propertyExpression) ?? throw new InvalidExpressionException(nameof(propertyExpression))) - .ToList(); - - return this; - } - - public ICollectionRelationConfig SetRepositoryParent(Expression> propertyExpression) - { - RepositoryParentProperty = PropertyMetadataHelper.GetPropertyMetadata(propertyExpression) ?? throw new InvalidPropertyExpressionException(nameof(propertyExpression)); - - return this; - } - - public ICollectionRelationConfig SetEntityAsParent() - { - EntityAsParent = true; - RepositoryParentProperty = null; - - return this; - } + RepositoryType = relatedRepositoryType; + RelatedEntityType = typeof(TRelatedEntity); + RelatedRepositoryType = relatedRepositoryType; + RelatedElementsGetter = relatedElements; + IsRelationToMany = true; + } + + public ICollectionRelationConfig SetElementIdProperty(Expression> propertyExpression) + { + IdProperty = PropertyMetadataHelper.GetPropertyMetadata(propertyExpression) ?? throw new InvalidPropertyExpressionException(nameof(propertyExpression)); + + return this; + } + + public ICollectionRelationConfig SetElementDisplayProperties(params Expression>[] propertyExpressions) + { + DisplayProperties = propertyExpressions + .Select(propertyExpression => PropertyMetadataHelper.GetExpressionMetadata(propertyExpression) ?? throw new InvalidExpressionException(nameof(propertyExpression))) + .ToList(); + + return this; + } + + public ICollectionRelationConfig SetRepositoryParent(Expression> propertyExpression) + { + RepositoryParentProperty = PropertyMetadataHelper.GetPropertyMetadata(propertyExpression) ?? throw new InvalidPropertyExpressionException(nameof(propertyExpression)); + + return this; + } + + public ICollectionRelationConfig SetEntityAsParent() + { + EntityAsParent = true; + RepositoryParentProperty = null; + + return this; } } diff --git a/src/RapidCMS.Core/Models/Config/SubCollectionListConfig.cs b/src/RapidCMS.Core/Models/Config/SubCollectionListConfig.cs index 39ad5d26..0f0f7cc6 100644 --- a/src/RapidCMS.Core/Models/Config/SubCollectionListConfig.cs +++ b/src/RapidCMS.Core/Models/Config/SubCollectionListConfig.cs @@ -3,44 +3,43 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Abstractions.Repositories; -namespace RapidCMS.Core.Models.Config +namespace RapidCMS.Core.Models.Config; + +internal class SubCollectionListConfig : CollectionListConfig, + ISubCollectionListEditorConfig, + ISubCollectionListViewConfig + where TSubEntity : IEntity + where TSubRepository : IRepository { - internal class SubCollectionListConfig : CollectionListConfig, - ISubCollectionListEditorConfig, - ISubCollectionListViewConfig - where TSubEntity : IEntity - where TSubRepository : IRepository + internal SubCollectionListConfig(string collectionAlias) : base(collectionAlias) { - internal SubCollectionListConfig(string collectionAlias) : base(collectionAlias) - { - } + } - public ISubCollectionListEditorConfig SetListEditor(Action> configure) - { - RepositoryType = typeof(TSubRepository); - EntityType = typeof(TSubEntity); + public ISubCollectionListEditorConfig SetListEditor(Action> configure) + { + RepositoryType = typeof(TSubRepository); + EntityType = typeof(TSubEntity); - var config = new ListEditorConfig(); + var config = new ListEditorConfig(); - configure.Invoke(config); + configure.Invoke(config); - ListEditor = config; + ListEditor = config; - return this; - } + return this; + } - public ISubCollectionListViewConfig SetListView(Action> configure) - { - RepositoryType = typeof(TSubRepository); - EntityType = typeof(TSubEntity); + public ISubCollectionListViewConfig SetListView(Action> configure) + { + RepositoryType = typeof(TSubRepository); + EntityType = typeof(TSubEntity); - var config = new ListViewConfig(); + var config = new ListViewConfig(); - configure.Invoke(config); + configure.Invoke(config); - ListView = config; + ListView = config; - return this; - } + return this; } } diff --git a/src/RapidCMS.Core/Models/Config/TreeViewConfig.cs b/src/RapidCMS.Core/Models/Config/TreeViewConfig.cs index aa82448f..151f65a4 100644 --- a/src/RapidCMS.Core/Models/Config/TreeViewConfig.cs +++ b/src/RapidCMS.Core/Models/Config/TreeViewConfig.cs @@ -1,14 +1,13 @@ using RapidCMS.Core.Abstractions.Metadata; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Models.Config +namespace RapidCMS.Core.Models.Config; + +internal class TreeViewConfig { - internal class TreeViewConfig - { - internal EntityVisibilty EntityVisibilty { get; set; } - internal CollectionRootVisibility RootVisibility { get; set; } - internal bool DefaultOpenEntities { get; set; } - internal bool DefaultOpenCollections { get; set; } - internal IExpressionMetadata? Name { get; set; } - } + internal EntityVisibilty EntityVisibilty { get; set; } + internal CollectionRootVisibility RootVisibility { get; set; } + internal bool DefaultOpenEntities { get; set; } + internal bool DefaultOpenCollections { get; set; } + internal IExpressionMetadata? Name { get; set; } } diff --git a/src/RapidCMS.Core/Models/Config/ValidationConfig.cs b/src/RapidCMS.Core/Models/Config/ValidationConfig.cs index 140248f3..50fc010f 100644 --- a/src/RapidCMS.Core/Models/Config/ValidationConfig.cs +++ b/src/RapidCMS.Core/Models/Config/ValidationConfig.cs @@ -1,16 +1,15 @@ using System; -namespace RapidCMS.Core.Models.Config +namespace RapidCMS.Core.Models.Config; + +internal class ValidationConfig { - internal class ValidationConfig + public ValidationConfig(Type type, object? configuration) { - public ValidationConfig(Type type, object? configuration) - { - Type = type ?? throw new ArgumentNullException(nameof(type)); - Configuration = configuration; - } - - public Type Type { get; set; } - public object? Configuration { get; set; } + Type = type ?? throw new ArgumentNullException(nameof(type)); + Configuration = configuration; } + + public Type Type { get; set; } + public object? Configuration { get; set; } } diff --git a/src/RapidCMS.Core/Models/Data/DataView.cs b/src/RapidCMS.Core/Models/Data/DataView.cs index 85dfbba5..c8e46d17 100644 --- a/src/RapidCMS.Core/Models/Data/DataView.cs +++ b/src/RapidCMS.Core/Models/Data/DataView.cs @@ -8,41 +8,40 @@ using RapidCMS.Core.Enums; using RapidCMS.Core.Helpers; -namespace RapidCMS.Core.Models.Data -{ - public class DataView : IDataView, IHasOrderByEntity> - { - private Dictionary? _defaultOrderBys; +namespace RapidCMS.Core.Models.Data; - public DataView(int id, string label, Expression> expression) - { - Id = id; - Label = label ?? throw new ArgumentNullException(nameof(label)); - Expression = expression ?? throw new ArgumentNullException(nameof(expression)); - } +public class DataView : IDataView, IHasOrderByEntity> +{ + private Dictionary? _defaultOrderBys; - public int Id { get; private set; } - public string Label { get; private set; } - public Expression> Expression { get; private set; } + public DataView(int id, string label, Expression> expression) + { + Id = id; + Label = label ?? throw new ArgumentNullException(nameof(label)); + Expression = expression ?? throw new ArgumentNullException(nameof(expression)); + } - int IDataView.Id => Id; + public int Id { get; private set; } + public string Label { get; private set; } + public Expression> Expression { get; private set; } - string IDataView.Label => Label; + int IDataView.Id => Id; - LambdaExpression IDataView.QueryExpression => Expression; + string IDataView.Label => Label; - IEnumerable> IDataView.DefaultOrderBys - => _defaultOrderBys ?? Enumerable.Empty>(); + LambdaExpression IDataView.QueryExpression => Expression; - public DataView SetOrderByExpression(Expression> orderByExpression, OrderByType defaultOrder = OrderByType.None) - { - _defaultOrderBys ??= new(); + IEnumerable> IDataView.DefaultOrderBys + => _defaultOrderBys ?? Enumerable.Empty>(); - _defaultOrderBys[PropertyMetadataHelper.GetPropertyMetadata(orderByExpression) ?? throw new InvalidOperationException("Cannot determine orderByExpression")] = defaultOrder; + public DataView SetOrderByExpression(Expression> orderByExpression, OrderByType defaultOrder = OrderByType.None) + { + _defaultOrderBys ??= new(); - return this; - } + _defaultOrderBys[PropertyMetadataHelper.GetPropertyMetadata(orderByExpression) ?? throw new InvalidOperationException("Cannot determine orderByExpression")] = defaultOrder; - public void SetOrderBys(Dictionary orderBys) => _defaultOrderBys = orderBys; + return this; } + + public void SetOrderBys(Dictionary orderBys) => _defaultOrderBys = orderBys; } diff --git a/src/RapidCMS.Core/Models/Data/Element.cs b/src/RapidCMS.Core/Models/Data/Element.cs index a8af0c53..8cfbec57 100644 --- a/src/RapidCMS.Core/Models/Data/Element.cs +++ b/src/RapidCMS.Core/Models/Data/Element.cs @@ -1,11 +1,10 @@ using System.Collections.Generic; using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Models.Data +namespace RapidCMS.Core.Models.Data; + +public class Element : IElement { - public class Element : IElement - { - public object Id { get; set; } = default!; - public IEnumerable Labels { get; set; } = default!; - } + public object Id { get; set; } = default!; + public IEnumerable Labels { get; set; } = default!; } diff --git a/src/RapidCMS.Core/Models/Data/FileInfo.cs b/src/RapidCMS.Core/Models/Data/FileInfo.cs index 6aa2c87d..c6f9041e 100644 --- a/src/RapidCMS.Core/Models/Data/FileInfo.cs +++ b/src/RapidCMS.Core/Models/Data/FileInfo.cs @@ -2,30 +2,29 @@ using System.Collections.Generic; using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Models.Data +namespace RapidCMS.Core.Models.Data; + +public class FileInfo : IFileInfo { - public class FileInfo : IFileInfo + public FileInfo(Tewr.Blazor.FileReader.IFileInfo fileInfo) { - public FileInfo(Tewr.Blazor.FileReader.IFileInfo fileInfo) - { - Name = fileInfo.Name; - NonStandardProperties = fileInfo.NonStandardProperties; - Size = fileInfo.Size; - Type = fileInfo.Type; - LastModified = fileInfo.LastModified; - LastModifiedDate = fileInfo.LastModifiedDate; - } + Name = fileInfo.Name; + NonStandardProperties = fileInfo.NonStandardProperties; + Size = fileInfo.Size; + Type = fileInfo.Type; + LastModified = fileInfo.LastModified; + LastModifiedDate = fileInfo.LastModifiedDate; + } - public string Name { get; internal set; } + public string Name { get; internal set; } - public Dictionary NonStandardProperties { get; internal set; } + public Dictionary NonStandardProperties { get; internal set; } - public long Size { get; internal set; } + public long Size { get; internal set; } - public string Type { get; internal set; } + public string Type { get; internal set; } - public long? LastModified { get; internal set; } + public long? LastModified { get; internal set; } - public DateTime? LastModifiedDate { get; internal set; } - } + public DateTime? LastModifiedDate { get; internal set; } } diff --git a/src/RapidCMS.Core/Models/Data/OrderBy.cs b/src/RapidCMS.Core/Models/Data/OrderBy.cs index ba905a8b..452eecfe 100644 --- a/src/RapidCMS.Core/Models/Data/OrderBy.cs +++ b/src/RapidCMS.Core/Models/Data/OrderBy.cs @@ -2,23 +2,22 @@ using RapidCMS.Core.Abstractions.Metadata; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Models.Data +namespace RapidCMS.Core.Models.Data; + +internal class OrderBy : IOrderBy { - internal class OrderBy : IOrderBy + public OrderBy(OrderByType orderByType, IPropertyMetadata orderByExpression, IPropertyMetadata? property, IExpressionMetadata? expression) { - public OrderBy(OrderByType orderByType, IPropertyMetadata orderByExpression, IPropertyMetadata? property, IExpressionMetadata? expression) - { - OrderByType = orderByType; - OrderByExpression = orderByExpression; - Expression = expression; - Property = property; - } + OrderByType = orderByType; + OrderByExpression = orderByExpression; + Expression = expression; + Property = property; + } - public OrderByType OrderByType { get; private set; } + public OrderByType OrderByType { get; private set; } - public IPropertyMetadata OrderByExpression { get; private set; } + public IPropertyMetadata OrderByExpression { get; private set; } - public IPropertyMetadata? Property { get; private set; } - public IExpressionMetadata? Expression { get; private set; } - } + public IPropertyMetadata? Property { get; private set; } + public IExpressionMetadata? Expression { get; private set; } } diff --git a/src/RapidCMS.Core/Models/Data/ParentEntity.cs b/src/RapidCMS.Core/Models/Data/ParentEntity.cs index 5fd9d024..fbdc81aa 100644 --- a/src/RapidCMS.Core/Models/Data/ParentEntity.cs +++ b/src/RapidCMS.Core/Models/Data/ParentEntity.cs @@ -1,24 +1,23 @@ using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Models.Data +namespace RapidCMS.Core.Models.Data; + +internal class ParentEntity : IParent { - internal class ParentEntity : IParent - { - private readonly string _repositoryAlias; + private readonly string _repositoryAlias; - public ParentEntity(IParent? parent, IEntity entity, string repositoryAlias) - { - Parent = parent; - Entity = entity; - _repositoryAlias = repositoryAlias; - } + public ParentEntity(IParent? parent, IEntity entity, string repositoryAlias) + { + Parent = parent; + Entity = entity; + _repositoryAlias = repositoryAlias; + } - public IParent? Parent { get; } - public IEntity Entity { get; private set; } + public IParent? Parent { get; } + public IEntity Entity { get; private set; } - public ParentPath? GetParentPath() - { - return ParentPath.AddLevel(Parent?.GetParentPath(), _repositoryAlias, Entity.Id!); - } + public ParentPath? GetParentPath() + { + return ParentPath.AddLevel(Parent?.GetParentPath(), _repositoryAlias, Entity.Id!); } } diff --git a/src/RapidCMS.Core/Models/Data/ParentPath.cs b/src/RapidCMS.Core/Models/Data/ParentPath.cs index e41574b2..0b652276 100644 --- a/src/RapidCMS.Core/Models/Data/ParentPath.cs +++ b/src/RapidCMS.Core/Models/Data/ParentPath.cs @@ -3,78 +3,77 @@ using System.Collections.Generic; using System.Linq; -namespace RapidCMS.Core.Models.Data +namespace RapidCMS.Core.Models.Data; + +public sealed class ParentPath : IReadOnlyCollection<(string repositoryAlias, string id)> { - public sealed class ParentPath : IReadOnlyCollection<(string repositoryAlias, string id)> + private readonly List<(string repositoryAlias, string id)> _path; + + private ParentPath(List<(string repositoryAlias, string id)> path) { - private readonly List<(string repositoryAlias, string id)> _path; + _path = path ?? throw new ArgumentNullException(nameof(path)); + } - private ParentPath(List<(string repositoryAlias, string id)> path) - { - _path = path ?? throw new ArgumentNullException(nameof(path)); - } + private void Add(string repositoryAlias, string id) + { + _path.Add((repositoryAlias, id)); + } - private void Add(string repositoryAlias, string id) - { - _path.Add((repositoryAlias, id)); - } + public static ParentPath? TryParse(string? path) + { + var list = path?.Split(";") + .Select(chunk => chunk.Split(':')) + .Where(x => x?.Count() == 2) + .Select(x => (repositoryAlias: x[0], id: x[1])) + .ToList(); - public static ParentPath? TryParse(string? path) + if (list == null || !list.Any()) { - var list = path?.Split(";") - .Select(chunk => chunk.Split(':')) - .Where(x => x?.Count() == 2) - .Select(x => (repositoryAlias: x[0], id: x[1])) - .ToList(); - - if (list == null || !list.Any()) - { - return default; - } - - return new ParentPath(list); + return default; } - public static ParentPath AddLevel(ParentPath? currentPath, string repositoryAlias, string id) - { - var path = currentPath?.ToPathString(); + return new ParentPath(list); + } - var newPath = TryParse(path) ?? new ParentPath(new List<(string repositoryAlias, string id)>()); + public static ParentPath AddLevel(ParentPath? currentPath, string repositoryAlias, string id) + { + var path = currentPath?.ToPathString(); - newPath.Add(repositoryAlias, id); + var newPath = TryParse(path) ?? new ParentPath(new List<(string repositoryAlias, string id)>()); - return newPath; - } + newPath.Add(repositoryAlias, id); - public static (ParentPath? newPath, string? repositoryAlias, string? id) RemoveLevel(ParentPath? currentPath) - { - if (currentPath == null) - { - return (new ParentPath(new List<(string repositoryAlias, string id)>()), null, null); - } - else - { - var remainingPath = currentPath._path.Take(currentPath._path.Count - 1).ToList(); - - return (remainingPath.Count == 0 ? null : new ParentPath(remainingPath), currentPath._path.Last().repositoryAlias, currentPath._path.Last().id); - } - } + return newPath; + } - public string ToPathString() + public static (ParentPath? newPath, string? repositoryAlias, string? id) RemoveLevel(ParentPath? currentPath) + { + if (currentPath == null) { - return string.Join(";", _path.Select(x => $"{x.repositoryAlias}:{x.id}")); + return (new ParentPath(new List<(string repositoryAlias, string id)>()), null, null); } - - public IEnumerator<(string repositoryAlias, string id)> GetEnumerator() + else { - return _path.GetEnumerator(); - } + var remainingPath = currentPath._path.Take(currentPath._path.Count - 1).ToList(); - IEnumerator IEnumerable.GetEnumerator() - { - return _path.GetEnumerator(); + return (remainingPath.Count == 0 ? null : new ParentPath(remainingPath), currentPath._path.Last().repositoryAlias, currentPath._path.Last().id); } + } - public int Count => _path.Count; + public string ToPathString() + { + return string.Join(";", _path.Select(x => $"{x.repositoryAlias}:{x.id}")); } + + public IEnumerator<(string repositoryAlias, string id)> GetEnumerator() + { + return _path.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return _path.GetEnumerator(); + } + + public int Count => _path.Count; } diff --git a/src/RapidCMS.Core/Models/Data/RelatedEntity.cs b/src/RapidCMS.Core/Models/Data/RelatedEntity.cs index d58373b1..bfd1ac36 100644 --- a/src/RapidCMS.Core/Models/Data/RelatedEntity.cs +++ b/src/RapidCMS.Core/Models/Data/RelatedEntity.cs @@ -1,24 +1,23 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Forms; -namespace RapidCMS.Core.Models.Data +namespace RapidCMS.Core.Models.Data; + +public class RelatedEntity : IRelated { - public class RelatedEntity : IRelated + public RelatedEntity(IParent? parent, IEntity relatedEntity, string repositoryAlias) { - public RelatedEntity(IParent? parent, IEntity relatedEntity, string repositoryAlias) - { - Parent = parent; - Entity = relatedEntity; - RepositoryAlias = repositoryAlias; - } - - public RelatedEntity(FormEditContext editContext) : this(editContext.Parent, editContext.Entity, editContext.RepositoryAlias) - { + Parent = parent; + Entity = relatedEntity; + RepositoryAlias = repositoryAlias; + } - } + public RelatedEntity(FormEditContext editContext) : this(editContext.Parent, editContext.Entity, editContext.RepositoryAlias) + { - public IParent? Parent { get; private set; } - public IEntity Entity { get; private set; } - public string RepositoryAlias { get; private set; } } + + public IParent? Parent { get; private set; } + public IEntity Entity { get; private set; } + public string RepositoryAlias { get; private set; } } diff --git a/src/RapidCMS.Core/Models/Data/Relation.cs b/src/RapidCMS.Core/Models/Data/Relation.cs index 4e24e9dd..b88e6377 100644 --- a/src/RapidCMS.Core/Models/Data/Relation.cs +++ b/src/RapidCMS.Core/Models/Data/Relation.cs @@ -4,34 +4,33 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Abstractions.Metadata; -namespace RapidCMS.Core.Models.Data +namespace RapidCMS.Core.Models.Data; + +internal class Relation : IRelation { - internal class Relation : IRelation + public Relation(Type relatedEntity, IPropertyMetadata property, IReadOnlyList relatedElementIds) { - public Relation(Type relatedEntity, IPropertyMetadata property, IReadOnlyList relatedElementIds) - { - RelatedEntityType = relatedEntity ?? throw new ArgumentNullException(nameof(relatedEntity)); - Property = property ?? throw new ArgumentNullException(nameof(property)); - RelatedElementIds = relatedElementIds ?? throw new ArgumentNullException(nameof(relatedElementIds)); - } + RelatedEntityType = relatedEntity ?? throw new ArgumentNullException(nameof(relatedEntity)); + Property = property ?? throw new ArgumentNullException(nameof(property)); + RelatedElementIds = relatedElementIds ?? throw new ArgumentNullException(nameof(relatedElementIds)); + } - public Type RelatedEntityType { get; private set; } + public Type RelatedEntityType { get; private set; } - public IPropertyMetadata Property { get; private set; } + public IPropertyMetadata Property { get; private set; } - public IReadOnlyList RelatedElementIds { get; private set; } + public IReadOnlyList RelatedElementIds { get; private set; } - public IReadOnlyList RelatedElementIdsAs() + public IReadOnlyList RelatedElementIdsAs() + { + if (typeof(T) == typeof(int)) + { + // edge case for getting int32 when list was deserialized to int64 + return RelatedElementIds.Select(Convert.ToInt32).OfType().ToList(); + } + else { - if (typeof(T) == typeof(int)) - { - // edge case for getting int32 when list was deserialized to int64 - return RelatedElementIds.Select(Convert.ToInt32).OfType().ToList(); - } - else - { - return RelatedElementIds.OfType().ToList(); - } + return RelatedElementIds.OfType().ToList(); } } } diff --git a/src/RapidCMS.Core/Models/Data/TypedView.cs b/src/RapidCMS.Core/Models/Data/TypedView.cs index 50986e73..a92db380 100644 --- a/src/RapidCMS.Core/Models/Data/TypedView.cs +++ b/src/RapidCMS.Core/Models/Data/TypedView.cs @@ -6,126 +6,125 @@ using RapidCMS.Core.Abstractions.Metadata; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Models.Data +namespace RapidCMS.Core.Models.Data; + +public class TypedView : IView { - internal class TypedView : IView, IView - { - private readonly View _query; + private readonly View _query; - public static IView Convert(IView query) + public static IView Convert(IView query) + { + return query switch { - return query switch - { - View v => new TypedView(v), - TypedView v => v, - _ => throw new InvalidOperationException() - }; - } + View v => new TypedView(v), + TypedView v => v, + _ => throw new InvalidOperationException() + }; + } - public TypedView(View query) - { - _query = query; - } + public TypedView(View query) + { + _query = query; + } - public int Skip => _query.Skip; + public int Skip => _query.Skip; - public int Take => _query.Take; + public int Take => _query.Take; - public string? SearchTerm => _query.SearchTerm; + public string? SearchTerm => _query.SearchTerm; - public int? ActiveTab => _query.ActiveTab; + public int? ActiveTab => _query.ActiveTab; - public bool MoreDataAvailable => _query.MoreDataAvailable; + public bool MoreDataAvailable => _query.MoreDataAvailable; - public Expression>? DataViewExpression => _query.DataView?.QueryExpression as Expression>; + public Expression>? DataViewExpression => _query.DataView?.QueryExpression as Expression>; - public void HasMoreData(bool hasMoreData) - { - _query.HasMoreData(hasMoreData); - } + public void HasMoreData(bool hasMoreData) + { + _query.HasMoreData(hasMoreData); + } + + public void SetDataView(IDataView dataView) + { + _query.SetDataView(dataView); + } - public void SetDataView(IDataView dataView) + public IQueryable ApplyDataView(IQueryable queryable) + { + if (_query.DataView?.QueryExpression is not Expression> validQueryExpression) { - _query.SetDataView(dataView); + return queryable; } - public IQueryable ApplyDataView(IQueryable queryable) - { - if (_query.DataView?.QueryExpression is not Expression> validQueryExpression) - { - return queryable; - } + return queryable.Where(validQueryExpression); + } - return queryable.Where(validQueryExpression); + public IQueryable ApplyOrder(IQueryable queryable) + { + if (_query.OrderBys == null) + { + return queryable; } - public IQueryable ApplyOrder(IQueryable queryable) + PreventLinkerToRemoveTheseMethodsFromQueryable(); + + var first = true; + foreach (var orderBy in _query.OrderBys) { - if (_query.OrderBys == null) + if (orderBy.OrderByType == OrderByType.None || orderBy.OrderByExpression == null) { - return queryable; + continue; } - PreventLinkerToRemoveTheseMethodsFromQueryable(); - - var first = true; - foreach (var orderBy in _query.OrderBys) - { - if (orderBy.OrderByType == OrderByType.None || orderBy.OrderByExpression == null) - { - continue; - } - - var method = first - ? orderBy.OrderByType == OrderByType.Descending ? nameof(Queryable.OrderByDescending) : nameof(Queryable.OrderBy) - : orderBy.OrderByType == OrderByType.Descending ? nameof(Queryable.ThenByDescending) : nameof(Queryable.ThenBy); + var method = first + ? orderBy.OrderByType == OrderByType.Descending ? nameof(Queryable.OrderByDescending) : nameof(Queryable.OrderBy) + : orderBy.OrderByType == OrderByType.Descending ? nameof(Queryable.ThenByDescending) : nameof(Queryable.ThenBy); - queryable = ApplyOrderBy(queryable, orderBy.OrderByExpression, method); + queryable = ApplyOrderBy(queryable, orderBy.OrderByExpression, method); - first = false; - } - - return queryable; + first = false; } - private static IQueryable ApplyOrderBy(IQueryable source, IPropertyMetadata ordering, string method) + return queryable; + } + + private static IQueryable ApplyOrderBy(IQueryable source, IPropertyMetadata ordering, string method) + { + if (typeof(T) != ordering.ObjectType) { - if (typeof(T) != ordering.ObjectType) - { - throw new InvalidOperationException($"The type of TEntity was not the same as the type used in the order expression (TEntity: {typeof(T)}, order expression: {ordering.ObjectType}). " + - $"Use the correct SetOrderByExpression overload when configuring."); - } + throw new InvalidOperationException($"The type of TEntity was not the same as the type used in the order expression (TEntity: {typeof(T)}, order expression: {ordering.ObjectType}). " + + $"Use the correct SetOrderByExpression overload when configuring."); + } - var resultExp = Expression.Call( - typeof(Queryable), - method, - new Type[] { ordering.ObjectType, ordering.PropertyType }, - source.Expression, - Expression.Quote(ordering.OriginalExpression)); + var resultExp = Expression.Call( + typeof(Queryable), + method, + new Type[] { ordering.ObjectType, ordering.PropertyType }, + source.Expression, + Expression.Quote(ordering.OriginalExpression)); - return source.Provider.CreateQuery(resultExp); - } + return source.Provider.CreateQuery(resultExp); + } - public IDataView? ActiveDataView => _query.DataView; + public IDataView? ActiveDataView => _query.DataView; - public IEnumerable ActiveOrderBys => _query.OrderBys ?? Enumerable.Empty(); + public IEnumerable ActiveOrderBys => _query.OrderBys ?? Enumerable.Empty(); - public string? CollectionAlias - { - get => _query.CollectionAlias; - set => _query.CollectionAlias = value; - } + public string? CollectionAlias + { + get => _query.CollectionAlias; + set => _query.CollectionAlias = value; + } - /// - /// The Linker incorrectly removes these methods from Queryable - /// - private static void PreventLinkerToRemoveTheseMethodsFromQueryable() - { - var query = new[] { "a" }.AsQueryable(); - var orderedQuery = Queryable.OrderBy(query, x => x); - orderedQuery = Queryable.OrderByDescending(orderedQuery, x => x); - orderedQuery = Queryable.ThenBy(orderedQuery, x => x); - orderedQuery = Queryable.ThenByDescending(orderedQuery, x => x); - } + /// + /// The Linker incorrectly removes these methods from Queryable + /// + private static void PreventLinkerToRemoveTheseMethodsFromQueryable() + { + var query = new[] { "a" }.AsQueryable(); + var orderedQuery = Queryable.OrderBy(query, x => x); + orderedQuery = Queryable.OrderByDescending(orderedQuery, x => x); + orderedQuery = Queryable.ThenBy(orderedQuery, x => x); + orderedQuery = Queryable.ThenByDescending(orderedQuery, x => x); } } diff --git a/src/RapidCMS.Core/Models/Data/View.cs b/src/RapidCMS.Core/Models/Data/View.cs index 9c7312fd..ea5b9a39 100644 --- a/src/RapidCMS.Core/Models/Data/View.cs +++ b/src/RapidCMS.Core/Models/Data/View.cs @@ -2,75 +2,74 @@ using System.Linq; using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Models.Data +namespace RapidCMS.Core.Models.Data; + +public sealed class View : IView { - public sealed class View : IView - { - internal IDataView? DataView; - internal IEnumerable? OrderBys; + internal IDataView? DataView; + internal IEnumerable? OrderBys; - public static View Default(string? collectionAlias = default) + public static View Default(string? collectionAlias = default) + { + return new View { - return new View - { - Skip = 0, - Take = 1000, - CollectionAlias = collectionAlias - }; - } + Skip = 0, + Take = 1000, + CollectionAlias = collectionAlias + }; + } - public static View Create(int pageSize, int pageNumber, string? searchTerm, int? activeTab, string? collectionAlias = default) + public static View Create(int pageSize, int pageNumber, string? searchTerm, int? activeTab, string? collectionAlias = default) + { + return new View { - return new View - { - Skip = pageSize * (pageNumber - 1), - Take = pageSize, - SearchTerm = searchTerm, - ActiveTab = activeTab, - CollectionAlias = collectionAlias - }; - } + Skip = pageSize * (pageNumber - 1), + Take = pageSize, + SearchTerm = searchTerm, + ActiveTab = activeTab, + CollectionAlias = collectionAlias + }; + } - public static View Create(IView view, string collectionAlias) + public static View Create(IView view, string collectionAlias) + { + return new View { - return new View - { - Skip = view.Skip, - Take = view.Take, - SearchTerm = view.SearchTerm, - ActiveTab = view.ActiveTab, - CollectionAlias = collectionAlias - }; - } + Skip = view.Skip, + Take = view.Take, + SearchTerm = view.SearchTerm, + ActiveTab = view.ActiveTab, + CollectionAlias = collectionAlias + }; + } - public void HasMoreData(bool hasMoreData) - { - MoreDataAvailable = hasMoreData; - } + public void HasMoreData(bool hasMoreData) + { + MoreDataAvailable = hasMoreData; + } - public void SetDataView(IDataView dataView) - { - DataView = dataView; - } + public void SetDataView(IDataView dataView) + { + DataView = dataView; + } - public void SetOrderBys(IEnumerable? orderBys) - { - OrderBys = orderBys; - } + public void SetOrderBys(IEnumerable? orderBys) + { + OrderBys = orderBys; + } - public int Skip { get; private set; } - public int Take { get; private set; } + public int Skip { get; private set; } + public int Take { get; private set; } - public string? SearchTerm { get; private set; } + public string? SearchTerm { get; private set; } - public int? ActiveTab { get; private set; } + public int? ActiveTab { get; private set; } - public bool MoreDataAvailable { get; private set; } = false; + public bool MoreDataAvailable { get; private set; } = false; - public IDataView? ActiveDataView => DataView; + public IDataView? ActiveDataView => DataView; - public IEnumerable ActiveOrderBys => OrderBys ?? Enumerable.Empty(); + public IEnumerable ActiveOrderBys => OrderBys ?? Enumerable.Empty(); - public string? CollectionAlias { get; set; } - } + public string? CollectionAlias { get; set; } } diff --git a/src/RapidCMS.Core/Models/EventArgs/Mediators/CollectionRepositoryEventArgs.cs b/src/RapidCMS.Core/Models/EventArgs/Mediators/CollectionRepositoryEventArgs.cs index edf8dcae..e62190f3 100644 --- a/src/RapidCMS.Core/Models/EventArgs/Mediators/CollectionRepositoryEventArgs.cs +++ b/src/RapidCMS.Core/Models/EventArgs/Mediators/CollectionRepositoryEventArgs.cs @@ -4,34 +4,33 @@ using RapidCMS.Core.Enums; using RapidCMS.Core.Models.Data; -namespace RapidCMS.Core.Models.EventArgs.Mediators +namespace RapidCMS.Core.Models.EventArgs.Mediators; + +public class CollectionRepositoryEventArgs : IMediatorEventArgs { - public class CollectionRepositoryEventArgs : IMediatorEventArgs + public CollectionRepositoryEventArgs(string collectionAlias, string repositoryAlias, ParentPath? parentPath, string? id, CrudType action) { - public CollectionRepositoryEventArgs(string collectionAlias, string repositoryAlias, ParentPath? parentPath, string? id, CrudType action) - { - CollectionAlias = collectionAlias ?? throw new ArgumentNullException(nameof(collectionAlias)); - RepositoryAlias = repositoryAlias ?? throw new ArgumentNullException(nameof(repositoryAlias)); - ParentPath = parentPath; - Id = id; - Action = action; - } + CollectionAlias = collectionAlias ?? throw new ArgumentNullException(nameof(collectionAlias)); + RepositoryAlias = repositoryAlias ?? throw new ArgumentNullException(nameof(repositoryAlias)); + ParentPath = parentPath; + Id = id; + Action = action; + } - public CollectionRepositoryEventArgs(string collectionAlias, string repositoryAlias, ParentPath? parentPath, IEnumerable? ids, CrudType action) - { - CollectionAlias = collectionAlias ?? throw new ArgumentNullException(nameof(collectionAlias)); - RepositoryAlias = repositoryAlias ?? throw new ArgumentNullException(nameof(repositoryAlias)); - ParentPath = parentPath; - Ids = ids; - Action = action; - } + public CollectionRepositoryEventArgs(string collectionAlias, string repositoryAlias, ParentPath? parentPath, IEnumerable? ids, CrudType action) + { + CollectionAlias = collectionAlias ?? throw new ArgumentNullException(nameof(collectionAlias)); + RepositoryAlias = repositoryAlias ?? throw new ArgumentNullException(nameof(repositoryAlias)); + ParentPath = parentPath; + Ids = ids; + Action = action; + } - public string CollectionAlias { get; set; } - public string RepositoryAlias { get; set; } - public ParentPath? ParentPath { get; set; } - public string? Id { get; set; } - public IEnumerable? Ids { get; set; } + public string CollectionAlias { get; set; } + public string RepositoryAlias { get; set; } + public ParentPath? ParentPath { get; set; } + public string? Id { get; set; } + public IEnumerable? Ids { get; set; } - public CrudType Action { get; set; } - } + public CrudType Action { get; set; } } diff --git a/src/RapidCMS.Core/Models/EventArgs/Mediators/ExceptionEventArgs.cs b/src/RapidCMS.Core/Models/EventArgs/Mediators/ExceptionEventArgs.cs index cccf7ded..bb562bef 100644 --- a/src/RapidCMS.Core/Models/EventArgs/Mediators/ExceptionEventArgs.cs +++ b/src/RapidCMS.Core/Models/EventArgs/Mediators/ExceptionEventArgs.cs @@ -1,15 +1,14 @@ using System; using RapidCMS.Core.Abstractions.Mediators; -namespace RapidCMS.Core.Models.EventArgs.Mediators +namespace RapidCMS.Core.Models.EventArgs.Mediators; + +public class ExceptionEventArgs : IMediatorEventArgs { - public class ExceptionEventArgs : IMediatorEventArgs + public ExceptionEventArgs(Exception exception) { - public ExceptionEventArgs(Exception exception) - { - Exception = exception; - } - - public Exception Exception { get; } + Exception = exception; } + + public Exception Exception { get; } } diff --git a/src/RapidCMS.Core/Models/EventArgs/Mediators/MessageEventArgs.cs b/src/RapidCMS.Core/Models/EventArgs/Mediators/MessageEventArgs.cs index d0ce6b22..987ac09a 100644 --- a/src/RapidCMS.Core/Models/EventArgs/Mediators/MessageEventArgs.cs +++ b/src/RapidCMS.Core/Models/EventArgs/Mediators/MessageEventArgs.cs @@ -2,17 +2,16 @@ using RapidCMS.Core.Abstractions.Mediators; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Models.EventArgs.Mediators +namespace RapidCMS.Core.Models.EventArgs.Mediators; + +public class MessageEventArgs : IMediatorEventArgs { - public class MessageEventArgs : IMediatorEventArgs + public MessageEventArgs(MessageType type, string content) { - public MessageEventArgs(MessageType type, string content) - { - Type = type; - Content = content ?? throw new ArgumentNullException(nameof(content)); - } - - public MessageType Type { get; set; } - public string Content { get; set; } + Type = type; + Content = content ?? throw new ArgumentNullException(nameof(content)); } + + public MessageType Type { get; set; } + public string Content { get; set; } } diff --git a/src/RapidCMS.Core/Models/EventArgs/Mediators/NavigationEventArgs.cs b/src/RapidCMS.Core/Models/EventArgs/Mediators/NavigationEventArgs.cs index b793768b..bfb8a3c6 100644 --- a/src/RapidCMS.Core/Models/EventArgs/Mediators/NavigationEventArgs.cs +++ b/src/RapidCMS.Core/Models/EventArgs/Mediators/NavigationEventArgs.cs @@ -2,17 +2,16 @@ using RapidCMS.Core.Abstractions.Mediators; using RapidCMS.Core.Navigation; -namespace RapidCMS.Core.Models.EventArgs.Mediators +namespace RapidCMS.Core.Models.EventArgs.Mediators; + +public class NavigationEventArgs : IMediatorEventArgs { - public class NavigationEventArgs : IMediatorEventArgs + internal NavigationEventArgs(NavigationState? oldState, NavigationState newState) { - internal NavigationEventArgs(NavigationState? oldState, NavigationState newState) - { - OldState = oldState; - NewState = newState ?? throw new ArgumentNullException(nameof(newState)); - } - - public NavigationState? OldState { get; set; } - public NavigationState NewState { get; set; } + OldState = oldState; + NewState = newState ?? throw new ArgumentNullException(nameof(newState)); } + + public NavigationState? OldState { get; set; } + public NavigationState NewState { get; set; } } diff --git a/src/RapidCMS.Core/Models/EventArgs/Mediators/PaneRequestEventArgs.cs b/src/RapidCMS.Core/Models/EventArgs/Mediators/PaneRequestEventArgs.cs index 46559024..56441bd0 100644 --- a/src/RapidCMS.Core/Models/EventArgs/Mediators/PaneRequestEventArgs.cs +++ b/src/RapidCMS.Core/Models/EventArgs/Mediators/PaneRequestEventArgs.cs @@ -3,21 +3,20 @@ using RapidCMS.Core.Enums; using RapidCMS.Core.Forms; -namespace RapidCMS.Core.Models.EventArgs.Mediators +namespace RapidCMS.Core.Models.EventArgs.Mediators; + +public class PaneRequestEventArgs : IMediatorRequestEventArgs { - public class PaneRequestEventArgs : IMediatorRequestEventArgs + public PaneRequestEventArgs(Type paneType, FormEditContext? editContext, ButtonContext buttonContext) { - public PaneRequestEventArgs(Type paneType, FormEditContext? editContext, ButtonContext buttonContext) - { - PaneType = paneType; - EditContext = editContext; - ButtonContext = buttonContext ?? throw new ArgumentNullException(nameof(buttonContext)); - } + PaneType = paneType; + EditContext = editContext; + ButtonContext = buttonContext ?? throw new ArgumentNullException(nameof(buttonContext)); + } - public Guid RequestId { get; set; } + public Guid RequestId { get; set; } - public Type PaneType { get; set; } - public FormEditContext? EditContext { get; set; } - public ButtonContext ButtonContext { get; set; } - } + public Type PaneType { get; set; } + public FormEditContext? EditContext { get; set; } + public ButtonContext ButtonContext { get; set; } } diff --git a/src/RapidCMS.Core/Models/EventArgs/Mediators/PaneResponseEventArgs.cs b/src/RapidCMS.Core/Models/EventArgs/Mediators/PaneResponseEventArgs.cs index 68b88a11..8230bd25 100644 --- a/src/RapidCMS.Core/Models/EventArgs/Mediators/PaneResponseEventArgs.cs +++ b/src/RapidCMS.Core/Models/EventArgs/Mediators/PaneResponseEventArgs.cs @@ -2,17 +2,16 @@ using RapidCMS.Core.Abstractions.Mediators; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Models.EventArgs.Mediators +namespace RapidCMS.Core.Models.EventArgs.Mediators; + +public class PaneResponseEventArgs : IMediatorResponseEventArgs { - public class PaneResponseEventArgs : IMediatorResponseEventArgs + public PaneResponseEventArgs(Guid requestId, CrudType response) { - public PaneResponseEventArgs(Guid requestId, CrudType response) - { - RequestId = requestId; - Response = response; - } - - public Guid RequestId { get; set; } - public CrudType Response { get; set; } + RequestId = requestId; + Response = response; } + + public Guid RequestId { get; set; } + public CrudType Response { get; set; } } diff --git a/src/RapidCMS.Core/Models/EventArgs/Mediators/RepositoryEventArgs.cs b/src/RapidCMS.Core/Models/EventArgs/Mediators/RepositoryEventArgs.cs index 567842ca..3260cd46 100644 --- a/src/RapidCMS.Core/Models/EventArgs/Mediators/RepositoryEventArgs.cs +++ b/src/RapidCMS.Core/Models/EventArgs/Mediators/RepositoryEventArgs.cs @@ -3,21 +3,20 @@ using RapidCMS.Core.Enums; using RapidCMS.Core.Models.Data; -namespace RapidCMS.Core.Models.EventArgs.Mediators +namespace RapidCMS.Core.Models.EventArgs.Mediators; + +public class RepositoryEventArgs : IMediatorEventArgs { - public class RepositoryEventArgs : IMediatorEventArgs + public RepositoryEventArgs(Type repositoryType, ParentPath? parentPath, string? id, CrudType action) { - public RepositoryEventArgs(Type repositoryType, ParentPath? parentPath, string? id, CrudType action) - { - RepositoryType = repositoryType ?? throw new ArgumentNullException(nameof(repositoryType)); - ParentPath = parentPath; - Id = id; - Action = action; - } - - public Type RepositoryType { get; set; } - public ParentPath? ParentPath { get; set; } - public string? Id { get; set; } - public CrudType Action { get; set; } + RepositoryType = repositoryType ?? throw new ArgumentNullException(nameof(repositoryType)); + ParentPath = parentPath; + Id = id; + Action = action; } + + public Type RepositoryType { get; set; } + public ParentPath? ParentPath { get; set; } + public string? Id { get; set; } + public CrudType Action { get; set; } } diff --git a/src/RapidCMS.Core/Models/EventArgs/RowDragEventArgs.cs b/src/RapidCMS.Core/Models/EventArgs/RowDragEventArgs.cs index dd54558b..bb1df39d 100644 --- a/src/RapidCMS.Core/Models/EventArgs/RowDragEventArgs.cs +++ b/src/RapidCMS.Core/Models/EventArgs/RowDragEventArgs.cs @@ -1,16 +1,15 @@ using System; -namespace RapidCMS.Core.Models.EventArgs +namespace RapidCMS.Core.Models.EventArgs; + +public sealed class RowDragEventArgs { - public sealed class RowDragEventArgs + public RowDragEventArgs(string subjectId, string? targetId) { - public RowDragEventArgs(string subjectId, string? targetId) - { - SubjectId = subjectId ?? throw new ArgumentNullException(nameof(subjectId)); - TargetId = targetId; - } - - public string SubjectId { get; } - public string? TargetId { get; } + SubjectId = subjectId ?? throw new ArgumentNullException(nameof(subjectId)); + TargetId = targetId; } + + public string SubjectId { get; } + public string? TargetId { get; } } diff --git a/src/RapidCMS.Core/Models/Metadata/ExpressionMetadata.cs b/src/RapidCMS.Core/Models/Metadata/ExpressionMetadata.cs index c26e3c76..bd8cac1f 100644 --- a/src/RapidCMS.Core/Models/Metadata/ExpressionMetadata.cs +++ b/src/RapidCMS.Core/Models/Metadata/ExpressionMetadata.cs @@ -1,17 +1,16 @@ using System; using RapidCMS.Core.Abstractions.Metadata; -namespace RapidCMS.Core.Models.Metadata +namespace RapidCMS.Core.Models.Metadata; + +internal class ExpressionMetadata : IExpressionMetadata { - internal class ExpressionMetadata : IExpressionMetadata + public ExpressionMetadata(string propertyName, Func stringGetter) { - public ExpressionMetadata(string propertyName, Func stringGetter) - { - PropertyName = propertyName ?? throw new ArgumentNullException(nameof(propertyName)); - StringGetter = stringGetter ?? throw new ArgumentNullException(nameof(stringGetter)); - } - - public string PropertyName { get; private set; } - public Func StringGetter { get; private set; } + PropertyName = propertyName ?? throw new ArgumentNullException(nameof(propertyName)); + StringGetter = stringGetter ?? throw new ArgumentNullException(nameof(stringGetter)); } + + public string PropertyName { get; private set; } + public Func StringGetter { get; private set; } } diff --git a/src/RapidCMS.Core/Models/Metadata/FullPropertyMetadata.cs b/src/RapidCMS.Core/Models/Metadata/FullPropertyMetadata.cs index 04e5bba7..83196e58 100644 --- a/src/RapidCMS.Core/Models/Metadata/FullPropertyMetadata.cs +++ b/src/RapidCMS.Core/Models/Metadata/FullPropertyMetadata.cs @@ -2,22 +2,21 @@ using System.Linq.Expressions; using RapidCMS.Core.Abstractions.Metadata; -namespace RapidCMS.Core.Models.Metadata +namespace RapidCMS.Core.Models.Metadata; + +internal class FullPropertyMetadata : PropertyMetadata, IFullPropertyMetadata { - internal class FullPropertyMetadata : PropertyMetadata, IFullPropertyMetadata + public FullPropertyMetadata( + LambdaExpression originalExpression, + Type propertyType, + string propertyName, + Func getter, + Action setter, + Type objectType, + string fingerprint) : base(originalExpression, propertyType, propertyName, getter, objectType, fingerprint) { - public FullPropertyMetadata( - LambdaExpression originalExpression, - Type propertyType, - string propertyName, - Func getter, - Action setter, - Type objectType, - string fingerprint) : base(originalExpression, propertyType, propertyName, getter, objectType, fingerprint) - { - Setter = setter ?? throw new ArgumentNullException(nameof(setter)); - } - - public Action Setter { get; private set; } + Setter = setter ?? throw new ArgumentNullException(nameof(setter)); } + + public Action Setter { get; private set; } } diff --git a/src/RapidCMS.Core/Models/Metadata/PropertyMetadata.cs b/src/RapidCMS.Core/Models/Metadata/PropertyMetadata.cs index 74ce9349..088437b5 100644 --- a/src/RapidCMS.Core/Models/Metadata/PropertyMetadata.cs +++ b/src/RapidCMS.Core/Models/Metadata/PropertyMetadata.cs @@ -2,33 +2,32 @@ using System.Linq.Expressions; using RapidCMS.Core.Abstractions.Metadata; -namespace RapidCMS.Core.Models.Metadata +namespace RapidCMS.Core.Models.Metadata; + +internal class PropertyMetadata : IPropertyMetadata { - internal class PropertyMetadata : IPropertyMetadata + public PropertyMetadata( + LambdaExpression originalExpression, + Type propertyType, + string propertyName, + Func getter, + Type objectType, + string fingerprint) { - public PropertyMetadata( - LambdaExpression originalExpression, - Type propertyType, - string propertyName, - Func getter, - Type objectType, - string fingerprint) - { - OriginalExpression = originalExpression ?? throw new ArgumentNullException(nameof(originalExpression)); - PropertyType = propertyType ?? throw new ArgumentNullException(nameof(propertyType)); - PropertyName = propertyName ?? throw new ArgumentNullException(nameof(propertyName)); - Getter = getter ?? throw new ArgumentNullException(nameof(getter)); - ObjectType = objectType ?? throw new ArgumentNullException(nameof(objectType)); - Fingerprint = fingerprint ?? throw new ArgumentNullException(nameof(fingerprint)); - } + OriginalExpression = originalExpression ?? throw new ArgumentNullException(nameof(originalExpression)); + PropertyType = propertyType ?? throw new ArgumentNullException(nameof(propertyType)); + PropertyName = propertyName ?? throw new ArgumentNullException(nameof(propertyName)); + Getter = getter ?? throw new ArgumentNullException(nameof(getter)); + ObjectType = objectType ?? throw new ArgumentNullException(nameof(objectType)); + Fingerprint = fingerprint ?? throw new ArgumentNullException(nameof(fingerprint)); + } - public Type PropertyType { get; private set; } - public string PropertyName { get; private set; } - public Func Getter { get; private set; } - public Type ObjectType { get; private set; } + public Type PropertyType { get; private set; } + public string PropertyName { get; private set; } + public Func Getter { get; private set; } + public Type ObjectType { get; private set; } - public string Fingerprint { get; private set; } + public string Fingerprint { get; private set; } - public LambdaExpression OriginalExpression { get; private set; } - } + public LambdaExpression OriginalExpression { get; private set; } } diff --git a/src/RapidCMS.Core/Models/Request/Api/DeleteEntityRequestModel.cs b/src/RapidCMS.Core/Models/Request/Api/DeleteEntityRequestModel.cs index 468cabf0..44cdeb03 100644 --- a/src/RapidCMS.Core/Models/Request/Api/DeleteEntityRequestModel.cs +++ b/src/RapidCMS.Core/Models/Request/Api/DeleteEntityRequestModel.cs @@ -1,7 +1,6 @@ -namespace RapidCMS.Core.Models.Request.Api +namespace RapidCMS.Core.Models.Request.Api; + +public class DeleteEntityRequestModel { - public class DeleteEntityRequestModel - { - public EntityDescriptor Descriptor { get; set; } = default!; - } + public EntityDescriptor Descriptor { get; set; } = default!; } diff --git a/src/RapidCMS.Core/Models/Request/Api/EntityDescriptor.cs b/src/RapidCMS.Core/Models/Request/Api/EntityDescriptor.cs index 670882e5..1897d60d 100644 --- a/src/RapidCMS.Core/Models/Request/Api/EntityDescriptor.cs +++ b/src/RapidCMS.Core/Models/Request/Api/EntityDescriptor.cs @@ -1,18 +1,17 @@ -namespace RapidCMS.Core.Models.Request.Api +namespace RapidCMS.Core.Models.Request.Api; + +public class EntityDescriptor { - public class EntityDescriptor + public EntityDescriptor(string? id, string? repositoryAlias, string? parentPath, string? variantAlias) { - public EntityDescriptor(string? id, string? repositoryAlias, string? parentPath, string? variantAlias) - { - Id = id; - RepositoryAlias = repositoryAlias; - ParentPath = parentPath; - VariantAlias = variantAlias; - } - - public string? Id { get; private set; } - public string? RepositoryAlias { get; private set; } - public string? ParentPath { get; private set; } - public string? VariantAlias { get; private set; } + Id = id; + RepositoryAlias = repositoryAlias; + ParentPath = parentPath; + VariantAlias = variantAlias; } + + public string? Id { get; private set; } + public string? RepositoryAlias { get; private set; } + public string? ParentPath { get; private set; } + public string? VariantAlias { get; private set; } } diff --git a/src/RapidCMS.Core/Models/Request/Api/GetEntitiesOfParentRequestModel.cs b/src/RapidCMS.Core/Models/Request/Api/GetEntitiesOfParentRequestModel.cs index ade6e2cd..15e85dc4 100644 --- a/src/RapidCMS.Core/Models/Request/Api/GetEntitiesOfParentRequestModel.cs +++ b/src/RapidCMS.Core/Models/Request/Api/GetEntitiesOfParentRequestModel.cs @@ -1,9 +1,8 @@ using RapidCMS.Core.Models.Data; -namespace RapidCMS.Core.Models.Request.Api +namespace RapidCMS.Core.Models.Request.Api; + +public class GetEntitiesOfParentRequestModel : GetEntitiesRequestModel { - public class GetEntitiesOfParentRequestModel : GetEntitiesRequestModel - { - public string? ParentPath { get; set; } - } + public string? ParentPath { get; set; } } diff --git a/src/RapidCMS.Core/Models/Request/Api/GetEntitiesOfRelationRequestModel.cs b/src/RapidCMS.Core/Models/Request/Api/GetEntitiesOfRelationRequestModel.cs index 5f572474..c10d34c7 100644 --- a/src/RapidCMS.Core/Models/Request/Api/GetEntitiesOfRelationRequestModel.cs +++ b/src/RapidCMS.Core/Models/Request/Api/GetEntitiesOfRelationRequestModel.cs @@ -1,9 +1,8 @@ using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Models.Request.Api +namespace RapidCMS.Core.Models.Request.Api; + +public class GetEntitiesOfRelationRequestModel : GetEntitiesRequestModel { - public class GetEntitiesOfRelationRequestModel : GetEntitiesRequestModel - { - public EntityDescriptor Related { get; set; } = default!; - } + public EntityDescriptor Related { get; set; } = default!; } diff --git a/src/RapidCMS.Core/Models/Request/Api/GetEntitiesRequestModel.cs b/src/RapidCMS.Core/Models/Request/Api/GetEntitiesRequestModel.cs index f16b5431..05ee65a1 100644 --- a/src/RapidCMS.Core/Models/Request/Api/GetEntitiesRequestModel.cs +++ b/src/RapidCMS.Core/Models/Request/Api/GetEntitiesRequestModel.cs @@ -1,12 +1,11 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Models.Request.Api +namespace RapidCMS.Core.Models.Request.Api; + +public class GetEntitiesRequestModel { - public class GetEntitiesRequestModel - { - public UsageType UsageType { get; set; } - public string RepositoryAlias { get; set; } = default!; - public IView View { get; set; } = default!; - } + public UsageType UsageType { get; set; } + public string RepositoryAlias { get; set; } = default!; + public IView View { get; set; } = default!; } diff --git a/src/RapidCMS.Core/Models/Request/Api/GetEntityRequestModel.cs b/src/RapidCMS.Core/Models/Request/Api/GetEntityRequestModel.cs index 519f25e2..bc502f73 100644 --- a/src/RapidCMS.Core/Models/Request/Api/GetEntityRequestModel.cs +++ b/src/RapidCMS.Core/Models/Request/Api/GetEntityRequestModel.cs @@ -1,10 +1,9 @@ using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Models.Request.Api +namespace RapidCMS.Core.Models.Request.Api; + +public class GetEntityRequestModel { - public class GetEntityRequestModel - { - public UsageType UsageType { get; set; } - public EntityDescriptor Subject { get; set; } = default!; - } + public UsageType UsageType { get; set; } + public EntityDescriptor Subject { get; set; } = default!; } diff --git a/src/RapidCMS.Core/Models/Request/Api/PersistEntityRequestModel.cs b/src/RapidCMS.Core/Models/Request/Api/PersistEntityRequestModel.cs index 2a7821ec..0fae9e37 100644 --- a/src/RapidCMS.Core/Models/Request/Api/PersistEntityRequestModel.cs +++ b/src/RapidCMS.Core/Models/Request/Api/PersistEntityRequestModel.cs @@ -2,13 +2,12 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Models.Request.Api +namespace RapidCMS.Core.Models.Request.Api; + +public class PersistEntityRequestModel { - public class PersistEntityRequestModel - { - public IEntity Entity { get; set; } = default!; - public EntityDescriptor Descriptor { get; set; } = default!; - public EntityState EntityState { get; set; } - public IEnumerable<(string propertyName, string variantAlias, IEnumerable elements)> Relations { get; set; } = default!; - } + public IEntity Entity { get; set; } = default!; + public EntityDescriptor Descriptor { get; set; } = default!; + public EntityState EntityState { get; set; } + public IEnumerable<(string propertyName, string variantAlias, IEnumerable elements)> Relations { get; set; } = default!; } diff --git a/src/RapidCMS.Core/Models/Request/Api/PersistRelatedEntityRequestModel.cs b/src/RapidCMS.Core/Models/Request/Api/PersistRelatedEntityRequestModel.cs index d5e0ab64..b5a0a7c9 100644 --- a/src/RapidCMS.Core/Models/Request/Api/PersistRelatedEntityRequestModel.cs +++ b/src/RapidCMS.Core/Models/Request/Api/PersistRelatedEntityRequestModel.cs @@ -1,16 +1,15 @@ -namespace RapidCMS.Core.Models.Request.Api +namespace RapidCMS.Core.Models.Request.Api; + +public class PersistRelatedEntityRequestModel { - public class PersistRelatedEntityRequestModel - { - public EntityDescriptor Subject { get; set; } = default!; - public EntityDescriptor Related { get; set; } = default!; + public EntityDescriptor Subject { get; set; } = default!; + public EntityDescriptor Related { get; set; } = default!; - public Actions Action { get; set; } + public Actions Action { get; set; } - public enum Actions - { - Add, - Remove - } + public enum Actions + { + Add, + Remove } } diff --git a/src/RapidCMS.Core/Models/Request/Api/PersistReorderRequestModel.cs b/src/RapidCMS.Core/Models/Request/Api/PersistReorderRequestModel.cs index 037dab4c..0ddf8f8a 100644 --- a/src/RapidCMS.Core/Models/Request/Api/PersistReorderRequestModel.cs +++ b/src/RapidCMS.Core/Models/Request/Api/PersistReorderRequestModel.cs @@ -1,8 +1,7 @@ -namespace RapidCMS.Core.Models.Request.Api +namespace RapidCMS.Core.Models.Request.Api; + +public class PersistReorderRequestModel { - public class PersistReorderRequestModel - { - public string? BeforeId { get; set; } - public EntityDescriptor Subject { get; set; } = default!; - } + public string? BeforeId { get; set; } + public EntityDescriptor Subject { get; set; } = default!; } diff --git a/src/RapidCMS.Core/Models/Request/Form/GetEntitiesOfParentRequestModel.cs b/src/RapidCMS.Core/Models/Request/Form/GetEntitiesOfParentRequestModel.cs index 6a6b35df..c0694b62 100644 --- a/src/RapidCMS.Core/Models/Request/Form/GetEntitiesOfParentRequestModel.cs +++ b/src/RapidCMS.Core/Models/Request/Form/GetEntitiesOfParentRequestModel.cs @@ -1,9 +1,8 @@ using RapidCMS.Core.Models.Data; -namespace RapidCMS.Core.Models.Request.Form +namespace RapidCMS.Core.Models.Request.Form; + +public class GetEntitiesOfParentRequestModel : GetEntitiesRequestModel { - public class GetEntitiesOfParentRequestModel : GetEntitiesRequestModel - { - public ParentPath? ParentPath { get; set; } - } + public ParentPath? ParentPath { get; set; } } diff --git a/src/RapidCMS.Core/Models/Request/Form/GetEntitiesOfRelationRequestModel.cs b/src/RapidCMS.Core/Models/Request/Form/GetEntitiesOfRelationRequestModel.cs index 1fea6d74..f32d6a73 100644 --- a/src/RapidCMS.Core/Models/Request/Form/GetEntitiesOfRelationRequestModel.cs +++ b/src/RapidCMS.Core/Models/Request/Form/GetEntitiesOfRelationRequestModel.cs @@ -1,9 +1,8 @@ using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Models.Request.Form +namespace RapidCMS.Core.Models.Request.Form; + +public class GetEntitiesOfRelationRequestModel : GetEntitiesRequestModel { - public class GetEntitiesOfRelationRequestModel : GetEntitiesRequestModel - { - public IRelated Related { get; set; } = default!; - } + public IRelated Related { get; set; } = default!; } diff --git a/src/RapidCMS.Core/Models/Request/Form/GetEntitiesRequestModel.cs b/src/RapidCMS.Core/Models/Request/Form/GetEntitiesRequestModel.cs index bd6b323f..43193136 100644 --- a/src/RapidCMS.Core/Models/Request/Form/GetEntitiesRequestModel.cs +++ b/src/RapidCMS.Core/Models/Request/Form/GetEntitiesRequestModel.cs @@ -1,14 +1,13 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Models.Request.Form +namespace RapidCMS.Core.Models.Request.Form; + +public class GetEntitiesRequestModel { - public class GetEntitiesRequestModel - { - public UsageType UsageType { get; set; } - public bool IsEmbedded { get; set; } - public string CollectionAlias { get; set; } = default!; - public string? VariantAlias { get; set; } - public IView View { get; set; } = default!; - } + public UsageType UsageType { get; set; } + public bool IsEmbedded { get; set; } + public string CollectionAlias { get; set; } = default!; + public string? VariantAlias { get; set; } + public IView View { get; set; } = default!; } diff --git a/src/RapidCMS.Core/Models/Request/Form/GetEntityOfPageRequestModel.cs b/src/RapidCMS.Core/Models/Request/Form/GetEntityOfPageRequestModel.cs index eaa97aa1..25710c01 100644 --- a/src/RapidCMS.Core/Models/Request/Form/GetEntityOfPageRequestModel.cs +++ b/src/RapidCMS.Core/Models/Request/Form/GetEntityOfPageRequestModel.cs @@ -1,10 +1,9 @@ using RapidCMS.Core.Models.Data; -namespace RapidCMS.Core.Models.Request.Form +namespace RapidCMS.Core.Models.Request.Form; + +public class GetEntityOfPageRequestModel { - public class GetEntityOfPageRequestModel - { - public string PageAlias { get; set; } - public ParentPath? ParentPath { get; set; } - } + public string PageAlias { get; set; } + public ParentPath? ParentPath { get; set; } } diff --git a/src/RapidCMS.Core/Models/Request/Form/GetEntityRequestModel.cs b/src/RapidCMS.Core/Models/Request/Form/GetEntityRequestModel.cs index 63380af2..44f1585f 100644 --- a/src/RapidCMS.Core/Models/Request/Form/GetEntityRequestModel.cs +++ b/src/RapidCMS.Core/Models/Request/Form/GetEntityRequestModel.cs @@ -1,14 +1,13 @@ using RapidCMS.Core.Enums; using RapidCMS.Core.Models.Data; -namespace RapidCMS.Core.Models.Request.Form +namespace RapidCMS.Core.Models.Request.Form; + +public class GetEntityRequestModel { - public class GetEntityRequestModel - { - public UsageType UsageType { get; set; } - public string CollectionAlias { get; set; } = default!; - public string? VariantAlias { get; set; } - public ParentPath? ParentPath { get; set; } - public string? Id { get; set; } - } + public UsageType UsageType { get; set; } + public string CollectionAlias { get; set; } = default!; + public string? VariantAlias { get; set; } + public ParentPath? ParentPath { get; set; } + public string? Id { get; set; } } diff --git a/src/RapidCMS.Core/Models/Request/Form/PersistEntitiesRequestModel.cs b/src/RapidCMS.Core/Models/Request/Form/PersistEntitiesRequestModel.cs index efa9cedc..65513e6d 100644 --- a/src/RapidCMS.Core/Models/Request/Form/PersistEntitiesRequestModel.cs +++ b/src/RapidCMS.Core/Models/Request/Form/PersistEntitiesRequestModel.cs @@ -3,14 +3,13 @@ using RapidCMS.Core.Forms; using RapidCMS.Core.Navigation; -namespace RapidCMS.Core.Models.Request.Form +namespace RapidCMS.Core.Models.Request.Form; + +public class PersistEntitiesRequestModel : IListButtonInteractionRequestModel { - public class PersistEntitiesRequestModel : IListButtonInteractionRequestModel - { - public ListContext ListContext { get; set; } = default!; - public NavigationState NavigationState { get; set; } = default!; - public string ActionId { get; set; } = default!; - public object? CustomData { get; set; } - public IRelated? Related { get; set; } = default!; - } + public ListContext ListContext { get; set; } = default!; + public NavigationState NavigationState { get; set; } = default!; + public string ActionId { get; set; } = default!; + public object? CustomData { get; set; } + public IRelated? Related { get; set; } = default!; } diff --git a/src/RapidCMS.Core/Models/Request/Form/PersistEntityCollectionRequestModel.cs b/src/RapidCMS.Core/Models/Request/Form/PersistEntityCollectionRequestModel.cs index 508bbc8b..d58ca45c 100644 --- a/src/RapidCMS.Core/Models/Request/Form/PersistEntityCollectionRequestModel.cs +++ b/src/RapidCMS.Core/Models/Request/Form/PersistEntityCollectionRequestModel.cs @@ -2,14 +2,13 @@ using RapidCMS.Core.Forms; using RapidCMS.Core.Navigation; -namespace RapidCMS.Core.Models.Request.Form +namespace RapidCMS.Core.Models.Request.Form; + +public class PersistEntityCollectionRequestModel : IEditorInListInteractionRequestModel { - public class PersistEntityCollectionRequestModel : IEditorInListInteractionRequestModel - { - public FormEditContext EditContext { get; set; } = default!; - public ListContext ListContext { get; set; } = default!; - public NavigationState NavigationState { get; set; } = default!; - public string ActionId { get; set; } = default!; - public object? CustomData { get; set; } - } + public FormEditContext EditContext { get; set; } = default!; + public ListContext ListContext { get; set; } = default!; + public NavigationState NavigationState { get; set; } = default!; + public string ActionId { get; set; } = default!; + public object? CustomData { get; set; } } diff --git a/src/RapidCMS.Core/Models/Request/Form/PersistEntityRequestModel.cs b/src/RapidCMS.Core/Models/Request/Form/PersistEntityRequestModel.cs index c1b0e022..c5d53a34 100644 --- a/src/RapidCMS.Core/Models/Request/Form/PersistEntityRequestModel.cs +++ b/src/RapidCMS.Core/Models/Request/Form/PersistEntityRequestModel.cs @@ -2,13 +2,12 @@ using RapidCMS.Core.Forms; using RapidCMS.Core.Navigation; -namespace RapidCMS.Core.Models.Request.Form +namespace RapidCMS.Core.Models.Request.Form; + +public class PersistEntityRequestModel : IEditorButtonInteractionRequestModel { - public class PersistEntityRequestModel : IEditorButtonInteractionRequestModel - { - public FormEditContext EditContext { get; set; } = default!; - public NavigationState NavigationState { get; set; } = default!; - public string ActionId { get; set; } = default!; - public object? CustomData { get; set; } - } + public FormEditContext EditContext { get; set; } = default!; + public NavigationState NavigationState { get; set; } = default!; + public string ActionId { get; set; } = default!; + public object? CustomData { get; set; } } diff --git a/src/RapidCMS.Core/Models/Request/Form/PersistRelatedEntityRequestModel.cs b/src/RapidCMS.Core/Models/Request/Form/PersistRelatedEntityRequestModel.cs index c3f57644..0d4eb52e 100644 --- a/src/RapidCMS.Core/Models/Request/Form/PersistRelatedEntityRequestModel.cs +++ b/src/RapidCMS.Core/Models/Request/Form/PersistRelatedEntityRequestModel.cs @@ -1,9 +1,8 @@ using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Models.Request.Form +namespace RapidCMS.Core.Models.Request.Form; + +public class PersistRelatedEntityRequestModel : PersistEntityRequestModel { - public class PersistRelatedEntityRequestModel : PersistEntityRequestModel - { - public IRelated Related { get; set; } = default!; - } + public IRelated Related { get; set; } = default!; } diff --git a/src/RapidCMS.Core/Models/Request/NavigationRequest.cs b/src/RapidCMS.Core/Models/Request/NavigationRequest.cs index 229e0390..7755d543 100644 --- a/src/RapidCMS.Core/Models/Request/NavigationRequest.cs +++ b/src/RapidCMS.Core/Models/Request/NavigationRequest.cs @@ -4,78 +4,77 @@ using RapidCMS.Core.Helpers; using RapidCMS.Core.Models.Data; -namespace RapidCMS.Core.Models.Request +namespace RapidCMS.Core.Models.Request; + +public class NavigationRequest { - public class NavigationRequest + public static NavigationRequest NavigateToEntity(string collectionAlias, string id, IParent? parent) { - public static NavigationRequest NavigateToEntity(string collectionAlias, string id, IParent? parent) + return new NavigationRequest(collectionAlias) { - return new NavigationRequest(collectionAlias) - { - Id = id, - ParentPath = parent?.GetParentPath(), - IsEdit = true - }; - } + Id = id, + ParentPath = parent?.GetParentPath(), + IsEdit = true + }; + } - public static NavigationRequest NavigateToCreateNewEntity(string collectionAlias, IParent? parent, Type? entityVariant = null) + public static NavigationRequest NavigateToCreateNewEntity(string collectionAlias, IParent? parent, Type? entityVariant = null) + { + return new NavigationRequest(collectionAlias) { - return new NavigationRequest(collectionAlias) - { - ParentPath = parent?.GetParentPath(), - IsEdit = true, - IsNew = true, - VariantAlias = entityVariant == null ? null : AliasHelper.GetEntityVariantAlias(entityVariant) - }; - } + ParentPath = parent?.GetParentPath(), + IsEdit = true, + IsNew = true, + VariantAlias = entityVariant == null ? null : AliasHelper.GetEntityVariantAlias(entityVariant) + }; + } - public static NavigationRequest NavigateToCollection(string collectionAlias, IParent? parent) + public static NavigationRequest NavigateToCollection(string collectionAlias, IParent? parent) + { + return new NavigationRequest(collectionAlias) { - return new NavigationRequest(collectionAlias) - { - ParentPath = parent?.GetParentPath(), - IsEdit = true, - IsList = true - }; - } + ParentPath = parent?.GetParentPath(), + IsEdit = true, + IsList = true + }; + } - public static NavigationRequest NavigateToDetails(string detailAlias, string id, IParent? parent) + public static NavigationRequest NavigateToDetails(string detailAlias, string id, IParent? parent) + { + return new NavigationRequest(detailAlias) { - return new NavigationRequest(detailAlias) - { - ParentPath = parent?.GetParentPath(), - Id = id, - IsEdit = true - }; - } + ParentPath = parent?.GetParentPath(), + Id = id, + IsEdit = true + }; + } - public static NavigationRequest NavigateToPage(string pageName) + public static NavigationRequest NavigateToPage(string pageName) + { + return new NavigationRequest(pageName.ToUrlFriendlyString()) { - return new NavigationRequest(pageName.ToUrlFriendlyString()) - { - IsPage = true - }; - } + IsPage = true + }; + } - private NavigationRequest(string collectionAlias) - { - CollectionAlias = collectionAlias; - } + private NavigationRequest(string collectionAlias) + { + CollectionAlias = collectionAlias; + } - internal string CollectionAlias { get; private set; } + internal string CollectionAlias { get; private set; } - internal string? VariantAlias { get; private set; } + internal string? VariantAlias { get; private set; } - internal string? Id { get; set; } + internal string? Id { get; set; } - internal ParentPath? ParentPath { get; set; } + internal ParentPath? ParentPath { get; set; } - internal bool IsEdit { get; set; } + internal bool IsEdit { get; set; } - internal bool IsNew { get; set; } + internal bool IsNew { get; set; } - internal bool IsList { get; set; } + internal bool IsList { get; set; } - internal bool IsPage { get; set; } - } + internal bool IsPage { get; set; } } diff --git a/src/RapidCMS.Core/Models/Response/ApiCommandResponseModel.cs b/src/RapidCMS.Core/Models/Response/ApiCommandResponseModel.cs index 8ed6375a..e5235838 100644 --- a/src/RapidCMS.Core/Models/Response/ApiCommandResponseModel.cs +++ b/src/RapidCMS.Core/Models/Response/ApiCommandResponseModel.cs @@ -1,6 +1,5 @@ -namespace RapidCMS.Core.Models.Response +namespace RapidCMS.Core.Models.Response; + +public class ApiCommandResponseModel { - public class ApiCommandResponseModel - { - } } diff --git a/src/RapidCMS.Core/Models/Response/ApiPersistEntityResponseModel.cs b/src/RapidCMS.Core/Models/Response/ApiPersistEntityResponseModel.cs index 09908875..d8587380 100644 --- a/src/RapidCMS.Core/Models/Response/ApiPersistEntityResponseModel.cs +++ b/src/RapidCMS.Core/Models/Response/ApiPersistEntityResponseModel.cs @@ -1,11 +1,10 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Forms; -namespace RapidCMS.Core.Models.Response +namespace RapidCMS.Core.Models.Response; + +public class ApiPersistEntityResponseModel : ApiCommandResponseModel { - public class ApiPersistEntityResponseModel : ApiCommandResponseModel - { - public IEntity? NewEntity { get; set; } - public ModelStateDictionary? ValidationErrors { get; set; } - } + public IEntity? NewEntity { get; set; } + public ModelStateDictionary? ValidationErrors { get; set; } } diff --git a/src/RapidCMS.Core/Models/Response/EntitiesResponseModel.cs b/src/RapidCMS.Core/Models/Response/EntitiesResponseModel.cs index c764f45c..5abd9022 100644 --- a/src/RapidCMS.Core/Models/Response/EntitiesResponseModel.cs +++ b/src/RapidCMS.Core/Models/Response/EntitiesResponseModel.cs @@ -1,12 +1,11 @@ using System.Collections.Generic; using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Models.Response +namespace RapidCMS.Core.Models.Response; + +public class EntitiesResponseModel { - public class EntitiesResponseModel - { - public IEnumerable Entities { get; set; } = default!; + public IEnumerable Entities { get; set; } = default!; - public bool MoreDataAvailable { get; set; } - } + public bool MoreDataAvailable { get; set; } } diff --git a/src/RapidCMS.Core/Models/Response/FileUploadResponseModel.cs b/src/RapidCMS.Core/Models/Response/FileUploadResponseModel.cs index 467e5c15..c6da4f24 100644 --- a/src/RapidCMS.Core/Models/Response/FileUploadResponseModel.cs +++ b/src/RapidCMS.Core/Models/Response/FileUploadResponseModel.cs @@ -1,7 +1,6 @@ -namespace RapidCMS.Core.Models.Response +namespace RapidCMS.Core.Models.Response; + +public class FileUploadResponseModel { - public class FileUploadResponseModel - { - public object Result { get; set; } = default!; - } + public object Result { get; set; } = default!; } diff --git a/src/RapidCMS.Core/Models/Response/FileUploadValidationResponseModel.cs b/src/RapidCMS.Core/Models/Response/FileUploadValidationResponseModel.cs index a7dc5ecf..44543bef 100644 --- a/src/RapidCMS.Core/Models/Response/FileUploadValidationResponseModel.cs +++ b/src/RapidCMS.Core/Models/Response/FileUploadValidationResponseModel.cs @@ -1,9 +1,8 @@ using System.Collections.Generic; -namespace RapidCMS.Core.Models.Response +namespace RapidCMS.Core.Models.Response; + +public class FileUploadValidationResponseModel { - public class FileUploadValidationResponseModel - { - public IEnumerable ErrorMessages { get; set; } = default!; - } + public IEnumerable ErrorMessages { get; set; } = default!; } diff --git a/src/RapidCMS.Core/Models/Response/ListEditorCommandResponseModel.cs b/src/RapidCMS.Core/Models/Response/ListEditorCommandResponseModel.cs index 455153be..1a17e0f4 100644 --- a/src/RapidCMS.Core/Models/Response/ListEditorCommandResponseModel.cs +++ b/src/RapidCMS.Core/Models/Response/ListEditorCommandResponseModel.cs @@ -1,7 +1,6 @@ -namespace RapidCMS.Core.Models.Response +namespace RapidCMS.Core.Models.Response; + +public class ListEditorCommandResponseModel : ViewCommandResponseModel { - public class ListEditorCommandResponseModel : ViewCommandResponseModel - { - } } diff --git a/src/RapidCMS.Core/Models/Response/ListViewCommandResponseModel.cs b/src/RapidCMS.Core/Models/Response/ListViewCommandResponseModel.cs index f7e76348..52b23f37 100644 --- a/src/RapidCMS.Core/Models/Response/ListViewCommandResponseModel.cs +++ b/src/RapidCMS.Core/Models/Response/ListViewCommandResponseModel.cs @@ -1,7 +1,6 @@ -namespace RapidCMS.Core.Models.Response +namespace RapidCMS.Core.Models.Response; + +public class ListViewCommandResponseModel : ViewCommandResponseModel { - public class ListViewCommandResponseModel : ViewCommandResponseModel - { - } } diff --git a/src/RapidCMS.Core/Models/Response/NodeInListViewCommandResponseModel.cs b/src/RapidCMS.Core/Models/Response/NodeInListViewCommandResponseModel.cs index 0f546064..d2a50b2f 100644 --- a/src/RapidCMS.Core/Models/Response/NodeInListViewCommandResponseModel.cs +++ b/src/RapidCMS.Core/Models/Response/NodeInListViewCommandResponseModel.cs @@ -1,7 +1,6 @@ -namespace RapidCMS.Core.Models.Response +namespace RapidCMS.Core.Models.Response; + +public class NodeInListViewCommandResponseModel : ViewCommandResponseModel { - public class NodeInListViewCommandResponseModel : ViewCommandResponseModel - { - } } diff --git a/src/RapidCMS.Core/Models/Response/NodeViewCommandResponseModel.cs b/src/RapidCMS.Core/Models/Response/NodeViewCommandResponseModel.cs index a1247f31..a9760469 100644 --- a/src/RapidCMS.Core/Models/Response/NodeViewCommandResponseModel.cs +++ b/src/RapidCMS.Core/Models/Response/NodeViewCommandResponseModel.cs @@ -1,7 +1,6 @@ -namespace RapidCMS.Core.Models.Response +namespace RapidCMS.Core.Models.Response; + +public class NodeViewCommandResponseModel : ViewCommandResponseModel { - public class NodeViewCommandResponseModel : ViewCommandResponseModel - { - } } diff --git a/src/RapidCMS.Core/Models/Response/ViewCommandResponseModel.cs b/src/RapidCMS.Core/Models/Response/ViewCommandResponseModel.cs index 63366dbf..88bad9c1 100644 --- a/src/RapidCMS.Core/Models/Response/ViewCommandResponseModel.cs +++ b/src/RapidCMS.Core/Models/Response/ViewCommandResponseModel.cs @@ -1,10 +1,9 @@ using System.Collections.Generic; -namespace RapidCMS.Core.Models.Response +namespace RapidCMS.Core.Models.Response; + +public class ViewCommandResponseModel { - public class ViewCommandResponseModel - { - public IEnumerable RefreshIds { get; internal set; } = new List(); - public bool NoOp { get; internal set; } - } + public IEnumerable RefreshIds { get; internal set; } = new List(); + public bool NoOp { get; internal set; } } diff --git a/src/RapidCMS.Core/Models/Setup/ButtonSetup.cs b/src/RapidCMS.Core/Models/Setup/ButtonSetup.cs index 72f17aa8..fda1ee36 100644 --- a/src/RapidCMS.Core/Models/Setup/ButtonSetup.cs +++ b/src/RapidCMS.Core/Models/Setup/ButtonSetup.cs @@ -2,24 +2,23 @@ using System.Collections.Generic; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Models.Setup +namespace RapidCMS.Core.Models.Setup; + +public class ButtonSetup { - public class ButtonSetup - { - public DefaultButtonType DefaultButtonType { get; set; } + public DefaultButtonType DefaultButtonType { get; set; } - public string ButtonId { get; set; } = default!; - public Type? CustomType { get; set; } - public Type ButtonHandlerType { get; set; } = default!; + public string ButtonId { get; set; } = default!; + public Type? CustomType { get; set; } + public Type ButtonHandlerType { get; set; } = default!; - public string Label { get; set; } = default!; - public string Icon { get; set; } = default!; - public bool IsPrimary { get; set; } + public string Label { get; set; } = default!; + public string Icon { get; set; } = default!; + public bool IsPrimary { get; set; } - public Func? IsVisible { get; set; } + public Func? IsVisible { get; set; } - public IEnumerable Buttons { get; set; } = default!; + public IEnumerable Buttons { get; set; } = default!; - public EntityVariantSetup? EntityVariant { get; set; } - } + public EntityVariantSetup? EntityVariant { get; set; } } diff --git a/src/RapidCMS.Core/Models/Setup/CmsSetup.cs b/src/RapidCMS.Core/Models/Setup/CmsSetup.cs index c8e15b87..507541a8 100644 --- a/src/RapidCMS.Core/Models/Setup/CmsSetup.cs +++ b/src/RapidCMS.Core/Models/Setup/CmsSetup.cs @@ -3,66 +3,65 @@ using RapidCMS.Core.Abstractions.Setup; using RapidCMS.Core.Models.Config; -namespace RapidCMS.Core.Models.Setup +namespace RapidCMS.Core.Models.Setup; + +internal class CmsSetup : ICms, ILogin { - internal class CmsSetup : ICms, ILogin + private readonly CmsConfig _config; + private readonly ISetupResolver _typeRegistrationSetupResolver; + + public CmsSetup( + CmsConfig config, + ISetupResolver typeRegistrationSetupResolver) { - private readonly CmsConfig _config; - private readonly ISetupResolver _typeRegistrationSetupResolver; + _config = config; + _typeRegistrationSetupResolver = typeRegistrationSetupResolver; - public CmsSetup( - CmsConfig config, - ISetupResolver typeRegistrationSetupResolver) - { - _config = config; - _typeRegistrationSetupResolver = typeRegistrationSetupResolver; + SiteName = config.SiteName; + IsDevelopment = config.IsDevelopment; + } - SiteName = config.SiteName; - IsDevelopment = config.IsDevelopment; - } + internal string SiteName { get; set; } + internal bool IsDevelopment { get; set; } - internal string SiteName { get; set; } - internal bool IsDevelopment { get; set; } + public TypeRegistrationSetup? CustomLoginScreenRegistration { get; internal set; } + public TypeRegistrationSetup? CustomLoginStatusRegistration { get; internal set; } + public TypeRegistrationSetup? CustomLandingPageRegistration { get; internal set; } - public TypeRegistrationSetup? CustomLoginScreenRegistration { get; internal set; } - public TypeRegistrationSetup? CustomLoginStatusRegistration { get; internal set; } - public TypeRegistrationSetup? CustomLandingPageRegistration { get; internal set; } + string ICms.SiteName => SiteName; + bool ICms.IsDevelopment + { + get => IsDevelopment; + set => IsDevelopment = value; + } - string ICms.SiteName => SiteName; - bool ICms.IsDevelopment + public async Task CustomLoginScreenRegistrationAsync() + { + if (_config.CustomLoginScreenRegistration != null) { - get => IsDevelopment; - set => IsDevelopment = value; + return (await _typeRegistrationSetupResolver.ResolveSetupAsync(_config.CustomLoginScreenRegistration)).Setup; } - public async Task CustomLoginScreenRegistrationAsync() - { - if (_config.CustomLoginScreenRegistration != null) - { - return (await _typeRegistrationSetupResolver.ResolveSetupAsync(_config.CustomLoginScreenRegistration)).Setup; - } - - return default; - } + return default; + } - public async Task CustomLoginStatusRegistrationAsync() + public async Task CustomLoginStatusRegistrationAsync() + { + if (_config.CustomLoginStatusRegistration != null) { - if (_config.CustomLoginStatusRegistration != null) - { - return (await _typeRegistrationSetupResolver.ResolveSetupAsync(_config.CustomLoginStatusRegistration)).Setup; - } - - return default; + return (await _typeRegistrationSetupResolver.ResolveSetupAsync(_config.CustomLoginStatusRegistration)).Setup; } - public async Task CustomLandingPageRegistrationAsync() - { - if (_config.CustomLandingPageRegistration != null) - { - return (await _typeRegistrationSetupResolver.ResolveSetupAsync(_config.CustomLandingPageRegistration)).Setup; - } + return default; + } - return default; + public async Task CustomLandingPageRegistrationAsync() + { + if (_config.CustomLandingPageRegistration != null) + { + return (await _typeRegistrationSetupResolver.ResolveSetupAsync(_config.CustomLandingPageRegistration)).Setup; } + + return default; } } diff --git a/src/RapidCMS.Core/Models/Setup/CollectionSetup.cs b/src/RapidCMS.Core/Models/Setup/CollectionSetup.cs index 9c9238e6..5fc83d81 100644 --- a/src/RapidCMS.Core/Models/Setup/CollectionSetup.cs +++ b/src/RapidCMS.Core/Models/Setup/CollectionSetup.cs @@ -5,77 +5,76 @@ using RapidCMS.Core.Enums; using RapidCMS.Core.Extensions; -namespace RapidCMS.Core.Models.Setup +namespace RapidCMS.Core.Models.Setup; + +public class CollectionSetup { - public class CollectionSetup + public CollectionSetup( + string? icon, + string? color, + string name, + string alias, + string repositoryAlias) { - public CollectionSetup( - string? icon, - string? color, - string name, - string alias, - string repositoryAlias) - { - Icon = icon; - Color = color; - Name = name ?? throw new ArgumentNullException(nameof(name)); - Alias = alias ?? throw new ArgumentNullException(nameof(alias)); - RepositoryAlias = repositoryAlias ?? throw new ArgumentNullException(nameof(repositoryAlias)); - Validators = new List(); - } + Icon = icon; + Color = color; + Name = name ?? throw new ArgumentNullException(nameof(name)); + Alias = alias ?? throw new ArgumentNullException(nameof(alias)); + RepositoryAlias = repositoryAlias ?? throw new ArgumentNullException(nameof(repositoryAlias)); + Validators = new List(); + } - public string? Icon { get; private set; } - public string? Color { get; private set; } - public string Name { get; private set; } - public string Alias { get; private set; } - public string RepositoryAlias { get; private set; } + public string? Icon { get; private set; } + public string? Color { get; private set; } + public string Name { get; private set; } + public string Alias { get; private set; } + public string RepositoryAlias { get; private set; } - public UsageType UsageType { get; set; } + public UsageType UsageType { get; set; } - public TreeElementSetup? Parent { get; set; } - public List Collections { get; set; } = new List(); + public TreeElementSetup? Parent { get; set; } + public List Collections { get; set; } = new List(); - public List? SubEntityVariants { get; set; } - public EntityVariantSetup EntityVariant { get; set; } = EntityVariantSetup.Undefined; + public List? SubEntityVariants { get; set; } + public EntityVariantSetup EntityVariant { get; set; } = EntityVariantSetup.Undefined; - public List? DataViews { get; set; } - public Type? DataViewBuilder { get; set; } + public List? DataViews { get; set; } + public Type? DataViewBuilder { get; set; } - public EntityVariantSetup GetEntityVariant(string? alias) + public EntityVariantSetup GetEntityVariant(string? alias) + { + if (string.IsNullOrWhiteSpace(alias) || SubEntityVariants == null || EntityVariant.Alias == alias) { - if (string.IsNullOrWhiteSpace(alias) || SubEntityVariants == null || EntityVariant.Alias == alias) - { - return EntityVariant; - } - else - { - return SubEntityVariants.FirstOrDefault(x => x.Alias == alias) ?? throw new InvalidOperationException($"Entity variant with alias {alias} does not exist."); - } + return EntityVariant; } - public EntityVariantSetup GetEntityVariant(IEntity entity) + else { - return SubEntityVariants?.FirstOrDefault(x => x.Type == entity.GetType()) - ?? EntityVariant; + return SubEntityVariants.FirstOrDefault(x => x.Alias == alias) ?? throw new InvalidOperationException($"Entity variant with alias {alias} does not exist."); } + } + public EntityVariantSetup GetEntityVariant(IEntity entity) + { + return SubEntityVariants?.FirstOrDefault(x => x.Type == entity.GetType()) + ?? EntityVariant; + } - public TreeViewSetup? TreeView { get; set; } - public ElementSetup? ElementSetup { get; set; } + public TreeViewSetup? TreeView { get; set; } + public ElementSetup? ElementSetup { get; set; } - public ListSetup? ListView { get; set; } - public ListSetup? ListEditor { get; set; } + public ListSetup? ListView { get; set; } + public ListSetup? ListEditor { get; set; } - public NodeSetup? NodeView { get; set; } - public NodeSetup? NodeEditor { get; set; } + public NodeSetup? NodeView { get; set; } + public NodeSetup? NodeEditor { get; set; } - public List Validators { get; set; } + public List Validators { get; set; } - public ButtonSetup? FindButton(string buttonId) - => EnumerableExtensions - .MergeAll( - ListView?.GetAllButtons(), - ListEditor?.GetAllButtons(), - NodeView?.GetAllButtons(), - NodeEditor?.GetAllButtons()) - .FirstOrDefault(x => x.ButtonId == buttonId); - } + public ButtonSetup? FindButton(string buttonId) + => EnumerableExtensions + .MergeAll( + ListView?.GetAllButtons(), + ListEditor?.GetAllButtons(), + NodeView?.GetAllButtons(), + NodeEditor?.GetAllButtons()) + .FirstOrDefault(x => x.ButtonId == buttonId); } diff --git a/src/RapidCMS.Core/Models/Setup/ConcreteDataProviderRelationSetup.cs b/src/RapidCMS.Core/Models/Setup/ConcreteDataProviderRelationSetup.cs index 125d3d41..c83c1717 100644 --- a/src/RapidCMS.Core/Models/Setup/ConcreteDataProviderRelationSetup.cs +++ b/src/RapidCMS.Core/Models/Setup/ConcreteDataProviderRelationSetup.cs @@ -1,15 +1,14 @@ using System; using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.Core.Models.Setup +namespace RapidCMS.Core.Models.Setup; + +public class ConcreteDataProviderRelationSetup : RelationSetup { - public class ConcreteDataProviderRelationSetup : RelationSetup + public ConcreteDataProviderRelationSetup(IDataCollection dataCollection) { - public ConcreteDataProviderRelationSetup(IDataCollection dataCollection) - { - DataCollection = dataCollection ?? throw new ArgumentNullException(nameof(dataCollection)); - } - - public IDataCollection DataCollection { get; set; } + DataCollection = dataCollection ?? throw new ArgumentNullException(nameof(dataCollection)); } + + public IDataCollection DataCollection { get; set; } } diff --git a/src/RapidCMS.Core/Models/Setup/CustomExpressionFieldSetup.cs b/src/RapidCMS.Core/Models/Setup/CustomExpressionFieldSetup.cs index aadc8baf..eff74b00 100644 --- a/src/RapidCMS.Core/Models/Setup/CustomExpressionFieldSetup.cs +++ b/src/RapidCMS.Core/Models/Setup/CustomExpressionFieldSetup.cs @@ -2,20 +2,19 @@ using RapidCMS.Core.Abstractions.Metadata; using RapidCMS.Core.Models.Config; -namespace RapidCMS.Core.Models.Setup +namespace RapidCMS.Core.Models.Setup; + +public class CustomExpressionFieldSetup : ExpressionFieldSetup { - public class CustomExpressionFieldSetup : ExpressionFieldSetup + internal CustomExpressionFieldSetup(FieldConfig field, IExpressionMetadata expression, Type customFieldType) : base(field, expression) { - internal CustomExpressionFieldSetup(FieldConfig field, IExpressionMetadata expression, Type customFieldType) : base(field, expression) - { - CustomType = customFieldType ?? throw new ArgumentNullException(nameof(customFieldType)); - } - - public CustomExpressionFieldSetup(Type customFieldType) : base() - { - CustomType = customFieldType ?? throw new ArgumentNullException(nameof(customFieldType)); - } + CustomType = customFieldType ?? throw new ArgumentNullException(nameof(customFieldType)); + } - public Type CustomType { get; set; } + public CustomExpressionFieldSetup(Type customFieldType) : base() + { + CustomType = customFieldType ?? throw new ArgumentNullException(nameof(customFieldType)); } + + public Type CustomType { get; set; } } diff --git a/src/RapidCMS.Core/Models/Setup/CustomPropertyFieldSetup.cs b/src/RapidCMS.Core/Models/Setup/CustomPropertyFieldSetup.cs index b9a9b5b2..dca029b0 100644 --- a/src/RapidCMS.Core/Models/Setup/CustomPropertyFieldSetup.cs +++ b/src/RapidCMS.Core/Models/Setup/CustomPropertyFieldSetup.cs @@ -1,20 +1,19 @@ using System; using RapidCMS.Core.Models.Config; -namespace RapidCMS.Core.Models.Setup +namespace RapidCMS.Core.Models.Setup; + +public class CustomPropertyFieldSetup : PropertyFieldSetup { - public class CustomPropertyFieldSetup : PropertyFieldSetup + internal CustomPropertyFieldSetup(FieldConfig field, Type customFieldType) : base(field) { - internal CustomPropertyFieldSetup(FieldConfig field, Type customFieldType) : base(field) - { - CustomType = customFieldType ?? throw new ArgumentNullException(nameof(customFieldType)); - } - - public CustomPropertyFieldSetup(Type customFieldType) : base() - { - CustomType = customFieldType ?? throw new ArgumentNullException(nameof(customFieldType)); - } + CustomType = customFieldType ?? throw new ArgumentNullException(nameof(customFieldType)); + } - public Type CustomType { get; set; } + public CustomPropertyFieldSetup(Type customFieldType) : base() + { + CustomType = customFieldType ?? throw new ArgumentNullException(nameof(customFieldType)); } + + public Type CustomType { get; set; } } diff --git a/src/RapidCMS.Core/Models/Setup/DataProviderRelationSetup.cs b/src/RapidCMS.Core/Models/Setup/DataProviderRelationSetup.cs index 8ea998b1..842135b4 100644 --- a/src/RapidCMS.Core/Models/Setup/DataProviderRelationSetup.cs +++ b/src/RapidCMS.Core/Models/Setup/DataProviderRelationSetup.cs @@ -1,16 +1,15 @@ using System; -namespace RapidCMS.Core.Models.Setup +namespace RapidCMS.Core.Models.Setup; + +public class DataProviderRelationSetup : RelationSetup { - public class DataProviderRelationSetup : RelationSetup + public DataProviderRelationSetup(Type dataCollectionType, object? configuration) { - public DataProviderRelationSetup(Type dataCollectionType, object? configuration) - { - DataCollectionType = dataCollectionType ?? throw new ArgumentNullException(nameof(dataCollectionType)); - Configuration = configuration; - } - - public Type DataCollectionType { get; } - public object? Configuration { get; } + DataCollectionType = dataCollectionType ?? throw new ArgumentNullException(nameof(dataCollectionType)); + Configuration = configuration; } + + public Type DataCollectionType { get; } + public object? Configuration { get; } } diff --git a/src/RapidCMS.Core/Models/Setup/ElementSetup.cs b/src/RapidCMS.Core/Models/Setup/ElementSetup.cs index 6070ecf9..8f209f53 100644 --- a/src/RapidCMS.Core/Models/Setup/ElementSetup.cs +++ b/src/RapidCMS.Core/Models/Setup/ElementSetup.cs @@ -2,17 +2,16 @@ using System.Collections.Generic; using RapidCMS.Core.Abstractions.Metadata; -namespace RapidCMS.Core.Models.Setup +namespace RapidCMS.Core.Models.Setup; + +public class ElementSetup { - public class ElementSetup + public ElementSetup(IPropertyMetadata id, IReadOnlyList labels) { - public ElementSetup(IPropertyMetadata id, IReadOnlyList labels) - { - IdProperty = id ?? throw new ArgumentNullException(nameof(id)); - DisplayProperties = labels ?? throw new ArgumentNullException(nameof(labels)); - } - - public IPropertyMetadata IdProperty { get; set; } - public IReadOnlyList DisplayProperties { get; set; } + IdProperty = id ?? throw new ArgumentNullException(nameof(id)); + DisplayProperties = labels ?? throw new ArgumentNullException(nameof(labels)); } + + public IPropertyMetadata IdProperty { get; set; } + public IReadOnlyList DisplayProperties { get; set; } } diff --git a/src/RapidCMS.Core/Models/Setup/EntityVariantSetup.cs b/src/RapidCMS.Core/Models/Setup/EntityVariantSetup.cs index 054f68b4..b94aae6b 100644 --- a/src/RapidCMS.Core/Models/Setup/EntityVariantSetup.cs +++ b/src/RapidCMS.Core/Models/Setup/EntityVariantSetup.cs @@ -1,29 +1,28 @@ using System; -namespace RapidCMS.Core.Models.Setup -{ - public class EntityVariantSetup - { - public static EntityVariantSetup Undefined = new EntityVariantSetup(); +namespace RapidCMS.Core.Models.Setup; - private EntityVariantSetup() - { - Name = ""; - Type = typeof(object); - Alias = ""; - } +public class EntityVariantSetup +{ + public static EntityVariantSetup Undefined = new EntityVariantSetup(); - public EntityVariantSetup(string name, string? icon, Type type, string alias) - { - Name = name ?? throw new ArgumentNullException(nameof(name)); - Icon = icon; - Type = type ?? throw new ArgumentNullException(nameof(type)); - Alias = alias ?? throw new ArgumentNullException(nameof(alias)); - } + private EntityVariantSetup() + { + Name = ""; + Type = typeof(object); + Alias = ""; + } - public string Name { get; internal set; } - public string? Icon { get; internal set; } - public Type Type { get; internal set; } - public string Alias { get; internal set; } + public EntityVariantSetup(string name, string? icon, Type type, string alias) + { + Name = name ?? throw new ArgumentNullException(nameof(name)); + Icon = icon; + Type = type ?? throw new ArgumentNullException(nameof(type)); + Alias = alias ?? throw new ArgumentNullException(nameof(alias)); } + + public string Name { get; internal set; } + public string? Icon { get; internal set; } + public Type Type { get; internal set; } + public string Alias { get; internal set; } } diff --git a/src/RapidCMS.Core/Models/Setup/ExpressionFieldSetup.cs b/src/RapidCMS.Core/Models/Setup/ExpressionFieldSetup.cs index e7375f18..b560e074 100644 --- a/src/RapidCMS.Core/Models/Setup/ExpressionFieldSetup.cs +++ b/src/RapidCMS.Core/Models/Setup/ExpressionFieldSetup.cs @@ -4,27 +4,26 @@ using RapidCMS.Core.Helpers; using RapidCMS.Core.Models.Config; -namespace RapidCMS.Core.Models.Setup +namespace RapidCMS.Core.Models.Setup; + +public class ExpressionFieldSetup : FieldSetup { - public class ExpressionFieldSetup : FieldSetup + internal ExpressionFieldSetup(FieldConfig field, IExpressionMetadata expression) : base(field) { - internal ExpressionFieldSetup(FieldConfig field, IExpressionMetadata expression) : base(field) - { - Expression = expression ?? throw new ArgumentNullException(nameof(expression)); - DisplayType = field.DisplayType; - } - - internal ExpressionFieldSetup(FieldConfig field, IPropertyMetadata expression) : base(field) - { - Expression = PropertyMetadataHelper.GetExpressionMetadata(expression ?? throw new ArgumentNullException(nameof(expression))); - DisplayType = field.DisplayType; - } + Expression = expression ?? throw new ArgumentNullException(nameof(expression)); + DisplayType = field.DisplayType; + } - public ExpressionFieldSetup() : base(default) - { + internal ExpressionFieldSetup(FieldConfig field, IPropertyMetadata expression) : base(field) + { + Expression = PropertyMetadataHelper.GetExpressionMetadata(expression ?? throw new ArgumentNullException(nameof(expression))); + DisplayType = field.DisplayType; + } - } + public ExpressionFieldSetup() : base(default) + { - public DisplayType DisplayType { get; set; } = DisplayType.Label; } + + public DisplayType DisplayType { get; set; } = DisplayType.Label; } diff --git a/src/RapidCMS.Core/Models/Setup/FieldSetup.cs b/src/RapidCMS.Core/Models/Setup/FieldSetup.cs index 20d2716e..83466cbe 100644 --- a/src/RapidCMS.Core/Models/Setup/FieldSetup.cs +++ b/src/RapidCMS.Core/Models/Setup/FieldSetup.cs @@ -5,48 +5,47 @@ using RapidCMS.Core.Enums; using RapidCMS.Core.Models.Config; -namespace RapidCMS.Core.Models.Setup +namespace RapidCMS.Core.Models.Setup; + +public class FieldSetup { - public class FieldSetup + internal FieldSetup(FieldConfig? field) { - internal FieldSetup(FieldConfig? field) + if (field == null) { - if (field == null) - { - IsVisible = (o, s) => true; - IsDisabled = (o, s) => true; - return; - } - - Index = field.Index; - Description = field.Description; - Details = field.Details; - Name = field.Name; - Placeholder = field.Placeholder; - Property = field.Property; - Expression = field.Expression; - OrderByExpression = field.OrderByExpression; - DefaultOrder = field.DefaultOrder; - IsVisible = field.IsVisible; - IsDisabled = field.IsDisabled; - Configuration = field.Configuration; - } - - public int Index { get; set; } - - public string? Name { get; set; } - public string? Description { get; set; } - public MarkupString? Details { get; set; } - public string? Placeholder { get; set; } - - public IPropertyMetadata? Property { get; set; } - public IExpressionMetadata? Expression { get; set; } - public IPropertyMetadata? OrderByExpression { get; set; } - public OrderByType DefaultOrder { get; set; } - - public Func IsVisible { get; set; } - public Func IsDisabled { get; set; } - - public Func>? Configuration { get; set; } + IsVisible = (o, s) => true; + IsDisabled = (o, s) => true; + return; + } + + Index = field.Index; + Description = field.Description; + Details = field.Details; + Name = field.Name; + Placeholder = field.Placeholder; + Property = field.Property; + Expression = field.Expression; + OrderByExpression = field.OrderByExpression; + DefaultOrder = field.DefaultOrder; + IsVisible = field.IsVisible; + IsDisabled = field.IsDisabled; + Configuration = field.Configuration; } + + public int Index { get; set; } + + public string? Name { get; set; } + public string? Description { get; set; } + public MarkupString? Details { get; set; } + public string? Placeholder { get; set; } + + public IPropertyMetadata? Property { get; set; } + public IExpressionMetadata? Expression { get; set; } + public IPropertyMetadata? OrderByExpression { get; set; } + public OrderByType DefaultOrder { get; set; } + + public Func IsVisible { get; set; } + public Func IsDisabled { get; set; } + + public Func>? Configuration { get; set; } } diff --git a/src/RapidCMS.Core/Models/Setup/ListSetup.cs b/src/RapidCMS.Core/Models/Setup/ListSetup.cs index 29e6c90b..1920e0b5 100644 --- a/src/RapidCMS.Core/Models/Setup/ListSetup.cs +++ b/src/RapidCMS.Core/Models/Setup/ListSetup.cs @@ -4,55 +4,54 @@ using RapidCMS.Core.Enums; using RapidCMS.Core.Extensions; -namespace RapidCMS.Core.Models.Setup +namespace RapidCMS.Core.Models.Setup; + +public class ListSetup { - public class ListSetup + public ListSetup( + int? pageSize, + bool? searchBarVisible, + bool? reorderingAllowed, + ListType listType, + EmptyVariantColumnVisibility emptyVariantColumnVisibility, + List panes, + List buttons) { - public ListSetup( - int? pageSize, - bool? searchBarVisible, - bool? reorderingAllowed, - ListType listType, - EmptyVariantColumnVisibility emptyVariantColumnVisibility, - List panes, - List buttons) - { - PageSize = pageSize; - SearchBarVisible = searchBarVisible; - ReorderingAllowed = reorderingAllowed; - ListType = listType; - EmptyVariantColumnVisibility = emptyVariantColumnVisibility; - Panes = panes ?? throw new ArgumentNullException(nameof(panes)); - Buttons = buttons ?? throw new ArgumentNullException(nameof(buttons)); - } + PageSize = pageSize; + SearchBarVisible = searchBarVisible; + ReorderingAllowed = reorderingAllowed; + ListType = listType; + EmptyVariantColumnVisibility = emptyVariantColumnVisibility; + Panes = panes ?? throw new ArgumentNullException(nameof(panes)); + Buttons = buttons ?? throw new ArgumentNullException(nameof(buttons)); + } - public int? PageSize { get; set; } - public bool? SearchBarVisible { get; set; } - public bool? ReorderingAllowed { get; set; } - public ListType ListType { get; set; } - public EmptyVariantColumnVisibility EmptyVariantColumnVisibility { get; set; } - public List Panes { get; set; } - public List Buttons { get; set; } + public int? PageSize { get; set; } + public bool? SearchBarVisible { get; set; } + public bool? ReorderingAllowed { get; set; } + public ListType ListType { get; set; } + public EmptyVariantColumnVisibility EmptyVariantColumnVisibility { get; set; } + public List Panes { get; set; } + public List Buttons { get; set; } - public ButtonSetup? FindButton(string buttonId) - { - return GetAllButtons()?.FirstOrDefault(x => x.ButtonId == buttonId); - } - public IEnumerable? GetAllButtons() + public ButtonSetup? FindButton(string buttonId) + { + return GetAllButtons()?.FirstOrDefault(x => x.ButtonId == buttonId); + } + public IEnumerable? GetAllButtons() + { + if (Buttons != null) { - if (Buttons != null) + foreach (var button in Buttons.GetAllButtons()) { - foreach (var button in Buttons.GetAllButtons()) - { - yield return button; - } + yield return button; } - if (Panes != null) + } + if (Panes != null) + { + foreach (var button in Panes.SelectMany(pane => pane.Buttons.GetAllButtons())) { - foreach (var button in Panes.SelectMany(pane => pane.Buttons.GetAllButtons())) - { - yield return button; - } + yield return button; } } } diff --git a/src/RapidCMS.Core/Models/Setup/NodeSetup.cs b/src/RapidCMS.Core/Models/Setup/NodeSetup.cs index f30d0b60..122b7b86 100644 --- a/src/RapidCMS.Core/Models/Setup/NodeSetup.cs +++ b/src/RapidCMS.Core/Models/Setup/NodeSetup.cs @@ -3,43 +3,42 @@ using System.Linq; using RapidCMS.Core.Extensions; -namespace RapidCMS.Core.Models.Setup +namespace RapidCMS.Core.Models.Setup; + +public class NodeSetup { - public class NodeSetup + public NodeSetup( + Type baseType, + List panes, + List buttons) { - public NodeSetup( - Type baseType, - List panes, - List buttons) - { - BaseType = baseType ?? throw new ArgumentNullException(nameof(baseType)); - Panes = panes ?? throw new ArgumentNullException(nameof(panes)); - Buttons = buttons ?? throw new ArgumentNullException(nameof(buttons)); - } + BaseType = baseType ?? throw new ArgumentNullException(nameof(baseType)); + Panes = panes ?? throw new ArgumentNullException(nameof(panes)); + Buttons = buttons ?? throw new ArgumentNullException(nameof(buttons)); + } - public Type BaseType { get; set; } - public List Panes { get; set; } - public List Buttons { get; set; } + public Type BaseType { get; set; } + public List Panes { get; set; } + public List Buttons { get; set; } - public ButtonSetup? FindButton(string buttonId) - { - return GetAllButtons()?.FirstOrDefault(x => x.ButtonId == buttonId); - } - public IEnumerable? GetAllButtons() + public ButtonSetup? FindButton(string buttonId) + { + return GetAllButtons()?.FirstOrDefault(x => x.ButtonId == buttonId); + } + public IEnumerable? GetAllButtons() + { + if (Buttons != null) { - if (Buttons != null) + foreach (var button in Buttons.GetAllButtons()) { - foreach (var button in Buttons.GetAllButtons()) - { - yield return button; - } + yield return button; } - if (Panes != null) + } + if (Panes != null) + { + foreach (var button in Panes.SelectMany(pane => pane.Buttons.GetAllButtons())) { - foreach (var button in Panes.SelectMany(pane => pane.Buttons.GetAllButtons())) - { - yield return button; - } + yield return button; } } } diff --git a/src/RapidCMS.Core/Models/Setup/PageSetup.cs b/src/RapidCMS.Core/Models/Setup/PageSetup.cs index a2bf5186..989c8367 100644 --- a/src/RapidCMS.Core/Models/Setup/PageSetup.cs +++ b/src/RapidCMS.Core/Models/Setup/PageSetup.cs @@ -1,13 +1,12 @@ using System.Collections.Generic; -namespace RapidCMS.Core.Models.Setup +namespace RapidCMS.Core.Models.Setup; + +internal class PageSetup { - internal class PageSetup - { - public string Name { get; set; } = default!; - public string Alias { get; set; } = default!; - public string Icon { get; set; } = default!; - public string Color { get; set; } = default!; - public List Sections { get; set; } = default!; - } + public string Name { get; set; } = default!; + public string Alias { get; set; } = default!; + public string Icon { get; set; } = default!; + public string Color { get; set; } = default!; + public List Sections { get; set; } = default!; } diff --git a/src/RapidCMS.Core/Models/Setup/PaneSetup.cs b/src/RapidCMS.Core/Models/Setup/PaneSetup.cs index 54dd7a9b..e66b76a5 100644 --- a/src/RapidCMS.Core/Models/Setup/PaneSetup.cs +++ b/src/RapidCMS.Core/Models/Setup/PaneSetup.cs @@ -2,37 +2,36 @@ using System.Collections.Generic; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Models.Setup +namespace RapidCMS.Core.Models.Setup; + +public class PaneSetup { - public class PaneSetup + public PaneSetup( + Type? customType, + string? label, + Func isVisible, + Type variantType, + List buttons, + List fields, + List subCollectionLists, + List relatedCollectionLists) { - public PaneSetup( - Type? customType, - string? label, - Func isVisible, - Type variantType, - List buttons, - List fields, - List subCollectionLists, - List relatedCollectionLists) - { - CustomType = customType; - Label = label; - IsVisible = isVisible ?? throw new ArgumentNullException(nameof(isVisible)); - VariantType = variantType ?? throw new ArgumentNullException(nameof(variantType)); - Buttons = buttons ?? throw new ArgumentNullException(nameof(buttons)); - Fields = fields ?? throw new ArgumentNullException(nameof(fields)); - SubCollectionLists = subCollectionLists ?? throw new ArgumentNullException(nameof(subCollectionLists)); - RelatedCollectionLists = relatedCollectionLists ?? throw new ArgumentNullException(nameof(relatedCollectionLists)); - } - - public Type? CustomType { get; set; } - public string? Label { get; set; } - public Func IsVisible { get; set; } - public Type VariantType { get; set; } - public List Buttons { get; set; } - public List Fields { get; set; } - public List SubCollectionLists { get; set; } - public List RelatedCollectionLists { get; set; } + CustomType = customType; + Label = label; + IsVisible = isVisible ?? throw new ArgumentNullException(nameof(isVisible)); + VariantType = variantType ?? throw new ArgumentNullException(nameof(variantType)); + Buttons = buttons ?? throw new ArgumentNullException(nameof(buttons)); + Fields = fields ?? throw new ArgumentNullException(nameof(fields)); + SubCollectionLists = subCollectionLists ?? throw new ArgumentNullException(nameof(subCollectionLists)); + RelatedCollectionLists = relatedCollectionLists ?? throw new ArgumentNullException(nameof(relatedCollectionLists)); } + + public Type? CustomType { get; set; } + public string? Label { get; set; } + public Func IsVisible { get; set; } + public Type VariantType { get; set; } + public List Buttons { get; set; } + public List Fields { get; set; } + public List SubCollectionLists { get; set; } + public List RelatedCollectionLists { get; set; } } diff --git a/src/RapidCMS.Core/Models/Setup/PropertyFieldSetup.cs b/src/RapidCMS.Core/Models/Setup/PropertyFieldSetup.cs index 7abd3c61..c5bc13c1 100644 --- a/src/RapidCMS.Core/Models/Setup/PropertyFieldSetup.cs +++ b/src/RapidCMS.Core/Models/Setup/PropertyFieldSetup.cs @@ -2,23 +2,22 @@ using RapidCMS.Core.Enums; using RapidCMS.Core.Models.Config; -namespace RapidCMS.Core.Models.Setup +namespace RapidCMS.Core.Models.Setup; + +public class PropertyFieldSetup : FieldSetup { - public class PropertyFieldSetup : FieldSetup + internal PropertyFieldSetup(FieldConfig field) : base(field) { - internal PropertyFieldSetup(FieldConfig field) : base(field) - { - Property = field.Property ?? throw new ArgumentNullException(nameof(field.Property)); - EditorType = field.EditorType; - } + Property = field.Property ?? throw new ArgumentNullException(nameof(field.Property)); + EditorType = field.EditorType; + } - public PropertyFieldSetup() : base(default) - { + public PropertyFieldSetup() : base(default) + { - } + } - public EditorType EditorType { get; set; } = EditorType.Readonly; + public EditorType EditorType { get; set; } = EditorType.Readonly; - public RelationSetup? Relation { get; set; } - } + public RelationSetup? Relation { get; set; } } diff --git a/src/RapidCMS.Core/Models/Setup/RelatedCollectionListSetup.cs b/src/RapidCMS.Core/Models/Setup/RelatedCollectionListSetup.cs index 0308afda..b5ef8054 100644 --- a/src/RapidCMS.Core/Models/Setup/RelatedCollectionListSetup.cs +++ b/src/RapidCMS.Core/Models/Setup/RelatedCollectionListSetup.cs @@ -1,19 +1,18 @@ using System; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Models.Setup +namespace RapidCMS.Core.Models.Setup; + +public class RelatedCollectionListSetup { - public class RelatedCollectionListSetup + public RelatedCollectionListSetup(int index, string collectionAlias) { - public RelatedCollectionListSetup(int index, string collectionAlias) - { - Index = index; - CollectionAlias = collectionAlias ?? throw new ArgumentNullException(nameof(collectionAlias)); - } + Index = index; + CollectionAlias = collectionAlias ?? throw new ArgumentNullException(nameof(collectionAlias)); + } - public int Index { get; set; } - public string CollectionAlias { get; set; } + public int Index { get; set; } + public string CollectionAlias { get; set; } - public UsageType SupportsUsageType { get; set; } - } + public UsageType SupportsUsageType { get; set; } } diff --git a/src/RapidCMS.Core/Models/Setup/RelationDataProviderRelationSetup.cs b/src/RapidCMS.Core/Models/Setup/RelationDataProviderRelationSetup.cs index 78448475..9a464faa 100644 --- a/src/RapidCMS.Core/Models/Setup/RelationDataProviderRelationSetup.cs +++ b/src/RapidCMS.Core/Models/Setup/RelationDataProviderRelationSetup.cs @@ -1,16 +1,15 @@ using System; -namespace RapidCMS.Core.Models.Setup +namespace RapidCMS.Core.Models.Setup; + +public class RelationDataProviderRelationSetup : RelationSetup { - public class RelationDataProviderRelationSetup : RelationSetup + public RelationDataProviderRelationSetup(Type relationDataCollectionType, object? configuration) { - public RelationDataProviderRelationSetup(Type relationDataCollectionType, object? configuration) - { - RelationDataCollectionType = relationDataCollectionType ?? throw new ArgumentNullException(nameof(relationDataCollectionType)); - Configuration = configuration; - } - - public Type RelationDataCollectionType { get; } - public object? Configuration { get; } + RelationDataCollectionType = relationDataCollectionType ?? throw new ArgumentNullException(nameof(relationDataCollectionType)); + Configuration = configuration; } + + public Type RelationDataCollectionType { get; } + public object? Configuration { get; } } diff --git a/src/RapidCMS.Core/Models/Setup/RelationSetup.cs b/src/RapidCMS.Core/Models/Setup/RelationSetup.cs index 24d4a471..ead87bd7 100644 --- a/src/RapidCMS.Core/Models/Setup/RelationSetup.cs +++ b/src/RapidCMS.Core/Models/Setup/RelationSetup.cs @@ -1,6 +1,5 @@ -namespace RapidCMS.Core.Models.Setup +namespace RapidCMS.Core.Models.Setup; + +public class RelationSetup { - public class RelationSetup - { - } } diff --git a/src/RapidCMS.Core/Models/Setup/RepositoryRelationSetup.cs b/src/RapidCMS.Core/Models/Setup/RepositoryRelationSetup.cs index 8b7ac8c4..e3de78c5 100644 --- a/src/RapidCMS.Core/Models/Setup/RepositoryRelationSetup.cs +++ b/src/RapidCMS.Core/Models/Setup/RepositoryRelationSetup.cs @@ -2,34 +2,33 @@ using System.Collections.Generic; using RapidCMS.Core.Abstractions.Metadata; -namespace RapidCMS.Core.Models.Setup +namespace RapidCMS.Core.Models.Setup; + +public class RepositoryRelationSetup : RelationSetup { - public class RepositoryRelationSetup : RelationSetup + public RepositoryRelationSetup( + string? repositoryAlias, + string? collectionAlias, + Type? relatedEntityType, + IPropertyMetadata? idProperty, + List? displayProperties, + bool isRelationToMany) { - public RepositoryRelationSetup( - string? repositoryAlias, - string? collectionAlias, - Type? relatedEntityType, - IPropertyMetadata? idProperty, - List? displayProperties, - bool isRelationToMany) - { - CollectionAlias = collectionAlias; - RepositoryAlias = repositoryAlias; - RelatedEntityType = relatedEntityType; - IdProperty = idProperty; - DisplayProperties = displayProperties; - IsRelationToMany = isRelationToMany; - } - - public string? CollectionAlias { get; set; } - public string? RepositoryAlias { get; set; } - public Type? RelatedEntityType { get; set; } - public IPropertyMetadata? RelatedElementsGetter { get; set; } - public IPropertyMetadata? RepositoryParentSelector { get; set; } - public bool EntityAsParent { get; set; } - public IPropertyMetadata? IdProperty { get; set; } - public List? DisplayProperties { get; set; } - public bool IsRelationToMany { get; } + CollectionAlias = collectionAlias; + RepositoryAlias = repositoryAlias; + RelatedEntityType = relatedEntityType; + IdProperty = idProperty; + DisplayProperties = displayProperties; + IsRelationToMany = isRelationToMany; } + + public string? CollectionAlias { get; set; } + public string? RepositoryAlias { get; set; } + public Type? RelatedEntityType { get; set; } + public IPropertyMetadata? RelatedElementsGetter { get; set; } + public IPropertyMetadata? RepositoryParentSelector { get; set; } + public bool EntityAsParent { get; set; } + public IPropertyMetadata? IdProperty { get; set; } + public List? DisplayProperties { get; set; } + public bool IsRelationToMany { get; } } diff --git a/src/RapidCMS.Core/Models/Setup/ResolvedSetup.cs b/src/RapidCMS.Core/Models/Setup/ResolvedSetup.cs index 2aa5ae40..c811f916 100644 --- a/src/RapidCMS.Core/Models/Setup/ResolvedSetup.cs +++ b/src/RapidCMS.Core/Models/Setup/ResolvedSetup.cs @@ -1,17 +1,16 @@ using RapidCMS.Core.Abstractions.Resolvers; -namespace RapidCMS.Core.Models.Setup +namespace RapidCMS.Core.Models.Setup; + +public struct ResolvedSetup : IResolvedSetup { - public struct ResolvedSetup : IResolvedSetup + public ResolvedSetup(T setup, bool cachable) { - public ResolvedSetup(T setup, bool cachable) - { - Setup = setup; - Cachable = cachable; - } + Setup = setup; + Cachable = cachable; + } - public T Setup { get; private set; } + public T Setup { get; private set; } - public bool Cachable { get; private set; } - } + public bool Cachable { get; private set; } } diff --git a/src/RapidCMS.Core/Models/Setup/SubCollectionListSetup.cs b/src/RapidCMS.Core/Models/Setup/SubCollectionListSetup.cs index 786abd04..e8f90e5e 100644 --- a/src/RapidCMS.Core/Models/Setup/SubCollectionListSetup.cs +++ b/src/RapidCMS.Core/Models/Setup/SubCollectionListSetup.cs @@ -2,19 +2,18 @@ using RapidCMS.Core.Abstractions.Setup; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Models.Setup +namespace RapidCMS.Core.Models.Setup; + +public class SubCollectionListSetup { - public class SubCollectionListSetup + public SubCollectionListSetup(int index, string collectionAlias) { - public SubCollectionListSetup(int index, string collectionAlias) - { - Index = index; - CollectionAlias = collectionAlias ?? throw new ArgumentNullException(nameof(collectionAlias)); - } + Index = index; + CollectionAlias = collectionAlias ?? throw new ArgumentNullException(nameof(collectionAlias)); + } - public int Index { get; set; } - public string CollectionAlias { get; set; } + public int Index { get; set; } + public string CollectionAlias { get; set; } - public UsageType SupportsUsageType { get; set; } - } + public UsageType SupportsUsageType { get; set; } } diff --git a/src/RapidCMS.Core/Models/Setup/TreeElementSetup.cs b/src/RapidCMS.Core/Models/Setup/TreeElementSetup.cs index 9c5996df..4a9b1aab 100644 --- a/src/RapidCMS.Core/Models/Setup/TreeElementSetup.cs +++ b/src/RapidCMS.Core/Models/Setup/TreeElementSetup.cs @@ -1,23 +1,22 @@ using System; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Models.Setup +namespace RapidCMS.Core.Models.Setup; + +public class TreeElementSetup { - public class TreeElementSetup + public TreeElementSetup(string alias, string name, PageType type) { - public TreeElementSetup(string alias, string name, PageType type) - { - Alias = alias ?? throw new ArgumentNullException(nameof(alias)); - Name = name ?? throw new ArgumentNullException(nameof(alias)); - Type = type; - } + Alias = alias ?? throw new ArgumentNullException(nameof(alias)); + Name = name ?? throw new ArgumentNullException(nameof(alias)); + Type = type; + } - public string Alias { get; } + public string Alias { get; } - public string Name { get; } + public string Name { get; } - public PageType Type { get; } + public PageType Type { get; } - public CollectionRootVisibility RootVisibility { get; internal set; } - } + public CollectionRootVisibility RootVisibility { get; internal set; } } diff --git a/src/RapidCMS.Core/Models/Setup/TreeViewSetup.cs b/src/RapidCMS.Core/Models/Setup/TreeViewSetup.cs index 538a6733..36cf6088 100644 --- a/src/RapidCMS.Core/Models/Setup/TreeViewSetup.cs +++ b/src/RapidCMS.Core/Models/Setup/TreeViewSetup.cs @@ -1,24 +1,23 @@ using RapidCMS.Core.Abstractions.Metadata; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Models.Setup +namespace RapidCMS.Core.Models.Setup; + +public class TreeViewSetup { - public class TreeViewSetup + public TreeViewSetup(EntityVisibilty entityVisibility, CollectionRootVisibility rootVisibility, bool defaultOpenEntities, bool defaultOpenCollections, IExpressionMetadata? name) { - public TreeViewSetup(EntityVisibilty entityVisibility, CollectionRootVisibility rootVisibility, bool defaultOpenEntities, bool defaultOpenCollections, IExpressionMetadata? name) - { - EntityVisibility = entityVisibility; - RootVisibility = rootVisibility; - DefaultOpenEntities = defaultOpenEntities; - DefaultOpenCollections = defaultOpenCollections; - Name = name; - } + EntityVisibility = entityVisibility; + RootVisibility = rootVisibility; + DefaultOpenEntities = defaultOpenEntities; + DefaultOpenCollections = defaultOpenCollections; + Name = name; + } - public EntityVisibilty EntityVisibility { get; set; } - public CollectionRootVisibility RootVisibility { get; set; } - public bool DefaultOpenEntities { get; set; } - public bool DefaultOpenCollections { get; set; } + public EntityVisibilty EntityVisibility { get; set; } + public CollectionRootVisibility RootVisibility { get; set; } + public bool DefaultOpenEntities { get; set; } + public bool DefaultOpenCollections { get; set; } - public IExpressionMetadata? Name { get; set; } - } + public IExpressionMetadata? Name { get; set; } } diff --git a/src/RapidCMS.Core/Models/Setup/TypeRegistrationSetup.cs b/src/RapidCMS.Core/Models/Setup/TypeRegistrationSetup.cs index dfdd0f71..1203b0c5 100644 --- a/src/RapidCMS.Core/Models/Setup/TypeRegistrationSetup.cs +++ b/src/RapidCMS.Core/Models/Setup/TypeRegistrationSetup.cs @@ -1,12 +1,11 @@ using System; using System.Collections.Generic; -namespace RapidCMS.Core.Models.Setup +namespace RapidCMS.Core.Models.Setup; + +public class TypeRegistrationSetup { - public class TypeRegistrationSetup - { - public Type Type { get; set; } = default!; - public string Alias { get; set; } = default!; - public Dictionary? Parameters { get; set; } = default!; - } + public Type Type { get; set; } = default!; + public string Alias { get; set; } = default!; + public Dictionary? Parameters { get; set; } = default!; } diff --git a/src/RapidCMS.Core/Models/Setup/ValidationSetup.cs b/src/RapidCMS.Core/Models/Setup/ValidationSetup.cs index b939000f..8b8ffc85 100644 --- a/src/RapidCMS.Core/Models/Setup/ValidationSetup.cs +++ b/src/RapidCMS.Core/Models/Setup/ValidationSetup.cs @@ -1,16 +1,15 @@ using System; -namespace RapidCMS.Core.Models.Setup +namespace RapidCMS.Core.Models.Setup; + +public class ValidationSetup { - public class ValidationSetup + public ValidationSetup(Type type, object? configuration) { - public ValidationSetup(Type type, object? configuration) - { - Type = type ?? throw new ArgumentNullException(nameof(type)); - Configuration = configuration; - } - - public Type Type { get; set; } - public object? Configuration { get; set; } + Type = type ?? throw new ArgumentNullException(nameof(type)); + Configuration = configuration; } + + public Type Type { get; set; } + public object? Configuration { get; set; } } diff --git a/src/RapidCMS.Core/Models/UI/ButtonUI.cs b/src/RapidCMS.Core/Models/UI/ButtonUI.cs index b352a072..d620d78b 100644 --- a/src/RapidCMS.Core/Models/UI/ButtonUI.cs +++ b/src/RapidCMS.Core/Models/UI/ButtonUI.cs @@ -4,31 +4,30 @@ using RapidCMS.Core.Forms; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Models.UI +namespace RapidCMS.Core.Models.UI; + +public class ButtonUI { - public class ButtonUI + internal ButtonUI(IButtonActionHandler handler, ButtonSetup button, FormEditContext editContext) { - internal ButtonUI(IButtonActionHandler handler, ButtonSetup button, FormEditContext editContext) - { - ButtonId = button.ButtonId ?? throw new ArgumentNullException(nameof(button.ButtonId)); + ButtonId = button.ButtonId ?? throw new ArgumentNullException(nameof(button.ButtonId)); - Icon = button.Icon; - Label = button.Label; - ShouldConfirm = handler.ShouldAskForConfirmation(button, editContext); - IsPrimary = button.IsPrimary; - RequiresValidForm = handler.RequiresValidForm(button, editContext); - IsVisible = button.IsVisible; - CustomType = button.CustomType; - } + Icon = button.Icon; + Label = button.Label; + ShouldConfirm = handler.ShouldAskForConfirmation(button, editContext); + IsPrimary = button.IsPrimary; + RequiresValidForm = handler.RequiresValidForm(button, editContext); + IsVisible = button.IsVisible; + CustomType = button.CustomType; + } - public string ButtonId { get; private set; } - public string? Label { get; private set; } - public string? Icon { get; private set; } - public bool ShouldConfirm { get; private set; } - public bool IsPrimary { get; private set; } - public bool RequiresValidForm { get; private set; } - public Func? IsVisible { get; set; } + public string ButtonId { get; private set; } + public string? Label { get; private set; } + public string? Icon { get; private set; } + public bool ShouldConfirm { get; private set; } + public bool IsPrimary { get; private set; } + public bool RequiresValidForm { get; private set; } + public Func? IsVisible { get; set; } - public Type? CustomType { get; private set; } - } + public Type? CustomType { get; private set; } } diff --git a/src/RapidCMS.Core/Models/UI/CustomExpressionFieldUI.cs b/src/RapidCMS.Core/Models/UI/CustomExpressionFieldUI.cs index 022d2a32..759b7700 100644 --- a/src/RapidCMS.Core/Models/UI/CustomExpressionFieldUI.cs +++ b/src/RapidCMS.Core/Models/UI/CustomExpressionFieldUI.cs @@ -1,15 +1,14 @@ using System; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Models.UI +namespace RapidCMS.Core.Models.UI; + +public class CustomExpressionFieldUI : ExpressionFieldUI { - public class CustomExpressionFieldUI : ExpressionFieldUI + internal CustomExpressionFieldUI(CustomExpressionFieldSetup field) : base(field) { - internal CustomExpressionFieldUI(CustomExpressionFieldSetup field) : base(field) - { - CustomType = field.CustomType; - } - - public Type CustomType { get; private set; } + CustomType = field.CustomType; } + + public Type CustomType { get; private set; } } diff --git a/src/RapidCMS.Core/Models/UI/CustomPropertyFieldUI.cs b/src/RapidCMS.Core/Models/UI/CustomPropertyFieldUI.cs index 73e6aecc..7509f5af 100644 --- a/src/RapidCMS.Core/Models/UI/CustomPropertyFieldUI.cs +++ b/src/RapidCMS.Core/Models/UI/CustomPropertyFieldUI.cs @@ -2,15 +2,14 @@ using RapidCMS.Core.Models.Setup; using RapidCMS.Core.Providers; -namespace RapidCMS.Core.Models.UI +namespace RapidCMS.Core.Models.UI; + +public class CustomPropertyFieldUI : PropertyFieldUI { - public class CustomPropertyFieldUI : PropertyFieldUI + internal CustomPropertyFieldUI(CustomPropertyFieldSetup field, FormDataProvider? dataProvider) : base(field, dataProvider) { - internal CustomPropertyFieldUI(CustomPropertyFieldSetup field, FormDataProvider? dataProvider) : base(field, dataProvider) - { - CustomType = field.CustomType; - } - - public Type CustomType { get; private set; } + CustomType = field.CustomType; } + + public Type CustomType { get; private set; } } diff --git a/src/RapidCMS.Core/Models/UI/ElementUI.cs b/src/RapidCMS.Core/Models/UI/ElementUI.cs index 16e17c15..e1b2a19b 100644 --- a/src/RapidCMS.Core/Models/UI/ElementUI.cs +++ b/src/RapidCMS.Core/Models/UI/ElementUI.cs @@ -1,17 +1,16 @@ using System; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Models.UI +namespace RapidCMS.Core.Models.UI; + +public class ElementUI { - public class ElementUI + internal ElementUI(Func isVisible, Func isDisabled) { - internal ElementUI(Func isVisible, Func isDisabled) - { - IsVisible = isVisible ?? throw new ArgumentNullException(nameof(isVisible)); - IsDisabled = isDisabled ?? throw new ArgumentNullException(nameof(isDisabled)); - } - - public Func IsVisible { get; private set; } - public Func IsDisabled { get; private set; } + IsVisible = isVisible ?? throw new ArgumentNullException(nameof(isVisible)); + IsDisabled = isDisabled ?? throw new ArgumentNullException(nameof(isDisabled)); } + + public Func IsVisible { get; private set; } + public Func IsDisabled { get; private set; } } diff --git a/src/RapidCMS.Core/Models/UI/ExpressionFieldUI.cs b/src/RapidCMS.Core/Models/UI/ExpressionFieldUI.cs index f02e95ee..4d02a119 100644 --- a/src/RapidCMS.Core/Models/UI/ExpressionFieldUI.cs +++ b/src/RapidCMS.Core/Models/UI/ExpressionFieldUI.cs @@ -1,16 +1,15 @@ using RapidCMS.Core.Enums; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Models.UI +namespace RapidCMS.Core.Models.UI; + +public class ExpressionFieldUI : FieldUI { - public class ExpressionFieldUI : FieldUI + internal ExpressionFieldUI(ExpressionFieldSetup field) : base(field) { - internal ExpressionFieldUI(ExpressionFieldSetup field) : base(field) - { - Expression = field.Expression; - Type = field.DisplayType; - } - - public DisplayType Type { get; private set; } + Expression = field.Expression; + Type = field.DisplayType; } + + public DisplayType Type { get; private set; } } diff --git a/src/RapidCMS.Core/Models/UI/FieldUI.cs b/src/RapidCMS.Core/Models/UI/FieldUI.cs index ce45912b..edb4aaa8 100644 --- a/src/RapidCMS.Core/Models/UI/FieldUI.cs +++ b/src/RapidCMS.Core/Models/UI/FieldUI.cs @@ -5,37 +5,36 @@ using RapidCMS.Core.Enums; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Models.UI +namespace RapidCMS.Core.Models.UI; + +public class FieldUI : ElementUI { - public class FieldUI : ElementUI + internal FieldUI(FieldSetup field) : base(field.IsVisible, field.IsDisabled) { - internal FieldUI(FieldSetup field) : base(field.IsVisible, field.IsDisabled) - { - Index = field.Index; - Description = field.Description; - Details = field.Details; - Name = field.Name; - Placeholder = field.Placeholder; - Expression = field.Expression; - Property = field.Property; - OrderByExpression = field.OrderByExpression; - SortDirection = field.DefaultOrder; - Configuration = field.Configuration; - } + Index = field.Index; + Description = field.Description; + Details = field.Details; + Name = field.Name; + Placeholder = field.Placeholder; + Expression = field.Expression; + Property = field.Property; + OrderByExpression = field.OrderByExpression; + SortDirection = field.DefaultOrder; + Configuration = field.Configuration; + } - public int Index { get; private set; } - public string? Name { get; private set; } - public string? Description { get; private set; } - public MarkupString? Details { get; private set; } - public string? Placeholder { get; private set; } + public int Index { get; private set; } + public string? Name { get; private set; } + public string? Description { get; private set; } + public MarkupString? Details { get; private set; } + public string? Placeholder { get; private set; } - public bool IsSortable() => OrderByExpression != null; + public bool IsSortable() => OrderByExpression != null; - public IPropertyMetadata? Property { get; internal set; } - public IExpressionMetadata? Expression { get; internal set; } - internal IPropertyMetadata? OrderByExpression { get; private set; } - public OrderByType SortDirection { get; private set; } + public IPropertyMetadata? Property { get; internal set; } + public IExpressionMetadata? Expression { get; internal set; } + internal IPropertyMetadata? OrderByExpression { get; private set; } + public OrderByType SortDirection { get; private set; } - public Func> Configuration { get; set; } - } + public Func> Configuration { get; set; } } diff --git a/src/RapidCMS.Core/Models/UI/ListUI.cs b/src/RapidCMS.Core/Models/UI/ListUI.cs index b4a1f460..8a535487 100644 --- a/src/RapidCMS.Core/Models/UI/ListUI.cs +++ b/src/RapidCMS.Core/Models/UI/ListUI.cs @@ -5,25 +5,24 @@ using RapidCMS.Core.Models.Data; using RapidCMS.Core.Navigation; -namespace RapidCMS.Core.Models.UI +namespace RapidCMS.Core.Models.UI; + +public class ListUI { - public class ListUI - { - public ListType ListType { get; internal set; } - public EmptyVariantColumnVisibility EmptyVariantColumnVisibility { get; internal set; } + public ListType ListType { get; internal set; } + public EmptyVariantColumnVisibility EmptyVariantColumnVisibility { get; internal set; } - public List? UniqueFields { get; internal set; } - public List? CommonFields { get; internal set; } - public int MaxUniqueFieldsInSingleEntity { get; internal set; } - public bool SectionsHaveButtons { get; internal set; } + public List? UniqueFields { get; internal set; } + public List? CommonFields { get; internal set; } + public int MaxUniqueFieldsInSingleEntity { get; internal set; } + public bool SectionsHaveButtons { get; internal set; } - public int PageSize { get; internal set; } - public bool SearchBarVisible { get; internal set; } - public bool Reorderable { get; internal set; } + public int PageSize { get; internal set; } + public bool SearchBarVisible { get; internal set; } + public bool Reorderable { get; internal set; } - public IEnumerable? GetOrderBys(SortBag? userSorts, SortBag? tabSorts) - => CommonFields? - .Where(x => x.OrderByExpression != null) - .Select(x => new OrderBy(userSorts?.Get(x.Index) ?? tabSorts?.Get(x.Index) ?? x.SortDirection, x.OrderByExpression!, x.Property, x.Expression)); - } + public IEnumerable? GetOrderBys(SortBag? userSorts, SortBag? tabSorts) + => CommonFields? + .Where(x => x.OrderByExpression != null) + .Select(x => new OrderBy(userSorts?.Get(x.Index) ?? tabSorts?.Get(x.Index) ?? x.SortDirection, x.OrderByExpression!, x.Property, x.Expression)); } diff --git a/src/RapidCMS.Core/Models/UI/PropertyFieldUI.cs b/src/RapidCMS.Core/Models/UI/PropertyFieldUI.cs index 7cac7984..65c9248d 100644 --- a/src/RapidCMS.Core/Models/UI/PropertyFieldUI.cs +++ b/src/RapidCMS.Core/Models/UI/PropertyFieldUI.cs @@ -3,19 +3,18 @@ using RapidCMS.Core.Models.Setup; using RapidCMS.Core.Providers; -namespace RapidCMS.Core.Models.UI +namespace RapidCMS.Core.Models.UI; + +public class PropertyFieldUI : FieldUI { - public class PropertyFieldUI : FieldUI + internal PropertyFieldUI(PropertyFieldSetup field, FormDataProvider? dataProvider) : base(field) { - internal PropertyFieldUI(PropertyFieldSetup field, FormDataProvider? dataProvider) : base(field) - { - Type = field.EditorType; - Property = field.Property; - DataCollection = dataProvider?.Collection; - } + Type = field.EditorType; + Property = field.Property; + DataCollection = dataProvider?.Collection; + } - public EditorType Type { get; internal set; } + public EditorType Type { get; internal set; } - public IDataCollection? DataCollection { get; internal set; } - } + public IDataCollection? DataCollection { get; internal set; } } diff --git a/src/RapidCMS.Core/Models/UI/RelatedCollectionUI.cs b/src/RapidCMS.Core/Models/UI/RelatedCollectionUI.cs index 4ee0521c..c08a9641 100644 --- a/src/RapidCMS.Core/Models/UI/RelatedCollectionUI.cs +++ b/src/RapidCMS.Core/Models/UI/RelatedCollectionUI.cs @@ -2,19 +2,18 @@ using RapidCMS.Core.Models.Setup; using RapidCMS.Core.Navigation; -namespace RapidCMS.Core.Models.UI +namespace RapidCMS.Core.Models.UI; + +public class RelatedCollectionUI : ElementUI { - public class RelatedCollectionUI : ElementUI + internal RelatedCollectionUI(RelatedCollectionListSetup relatedCollection, NavigationState nestedNavigationState) + : base((x, state) => state == EntityState.IsExisting, (x, y) => false) { - internal RelatedCollectionUI(RelatedCollectionListSetup relatedCollection, NavigationState nestedNavigationState) - : base((x, state) => state == EntityState.IsExisting, (x, y) => false) - { - CollectionAlias = relatedCollection.CollectionAlias; - NestedNavigationState = nestedNavigationState; - } + CollectionAlias = relatedCollection.CollectionAlias; + NestedNavigationState = nestedNavigationState; + } - public string CollectionAlias { get; private set; } + public string CollectionAlias { get; private set; } - public NavigationState? NestedNavigationState { get; internal set; } - } + public NavigationState? NestedNavigationState { get; internal set; } } diff --git a/src/RapidCMS.Core/Models/UI/SectionUI.cs b/src/RapidCMS.Core/Models/UI/SectionUI.cs index 0d523ae2..24857472 100644 --- a/src/RapidCMS.Core/Models/UI/SectionUI.cs +++ b/src/RapidCMS.Core/Models/UI/SectionUI.cs @@ -2,21 +2,20 @@ using System.Collections.Generic; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Models.UI +namespace RapidCMS.Core.Models.UI; + +public class SectionUI { - public class SectionUI + public SectionUI(Func isVisible) { - public SectionUI(Func isVisible) - { - IsVisible = isVisible ?? throw new ArgumentNullException(nameof(isVisible)); - } + IsVisible = isVisible ?? throw new ArgumentNullException(nameof(isVisible)); + } - public List? Buttons { get; internal set; } + public List? Buttons { get; internal set; } - public List? Elements { get; internal set; } - public Func IsVisible { get; private set; } - public string? Label { get; internal set; } + public List? Elements { get; internal set; } + public Func IsVisible { get; private set; } + public string? Label { get; internal set; } - public Type? CustomType { get; internal set; } - } + public Type? CustomType { get; internal set; } } diff --git a/src/RapidCMS.Core/Models/UI/SubCollectionUI.cs b/src/RapidCMS.Core/Models/UI/SubCollectionUI.cs index 2f85392a..f6f63afe 100644 --- a/src/RapidCMS.Core/Models/UI/SubCollectionUI.cs +++ b/src/RapidCMS.Core/Models/UI/SubCollectionUI.cs @@ -2,19 +2,18 @@ using RapidCMS.Core.Models.Setup; using RapidCMS.Core.Navigation; -namespace RapidCMS.Core.Models.UI +namespace RapidCMS.Core.Models.UI; + +public class SubCollectionUI : ElementUI { - public class SubCollectionUI : ElementUI + internal SubCollectionUI(SubCollectionListSetup subCollection, NavigationState nestedNavigationState) + : base((x, state) => state == EntityState.IsExisting, (x, y) => false) { - internal SubCollectionUI(SubCollectionListSetup subCollection, NavigationState nestedNavigationState) - : base((x, state) => state == EntityState.IsExisting, (x, y) => false) - { - CollectionAlias = subCollection.CollectionAlias; - NestedNavigationState = nestedNavigationState; - } + CollectionAlias = subCollection.CollectionAlias; + NestedNavigationState = nestedNavigationState; + } - public string CollectionAlias { get; private set; } + public string CollectionAlias { get; private set; } - public NavigationState? NestedNavigationState { get; private set; } - } + public NavigationState? NestedNavigationState { get; private set; } } diff --git a/src/RapidCMS.Core/Models/UI/TabUI.cs b/src/RapidCMS.Core/Models/UI/TabUI.cs index 43f9fa95..0e5ebc2e 100644 --- a/src/RapidCMS.Core/Models/UI/TabUI.cs +++ b/src/RapidCMS.Core/Models/UI/TabUI.cs @@ -1,16 +1,15 @@ using RapidCMS.Core.Navigation; -namespace RapidCMS.Core.Models.UI +namespace RapidCMS.Core.Models.UI; + +public class TabUI { - public class TabUI + public TabUI(int id) { - public TabUI(int id) - { - Id = id; - } - - public int Id { get; private set; } - public string? Label { get; internal set; } - public SortBag? DefaultSorts { get; internal set; } + Id = id; } + + public int Id { get; private set; } + public string? Label { get; internal set; } + public SortBag? DefaultSorts { get; internal set; } } diff --git a/src/RapidCMS.Core/Models/UI/TreeCollectionUI.cs b/src/RapidCMS.Core/Models/UI/TreeCollectionUI.cs index ac8d469a..fd975977 100644 --- a/src/RapidCMS.Core/Models/UI/TreeCollectionUI.cs +++ b/src/RapidCMS.Core/Models/UI/TreeCollectionUI.cs @@ -1,28 +1,27 @@ using System; using RapidCMS.Core.Navigation; -namespace RapidCMS.Core.Models.UI +namespace RapidCMS.Core.Models.UI; + +public class TreeCollectionUI { - public class TreeCollectionUI - { - public static TreeCollectionUI None = new TreeCollectionUI("empty", "empty", "empty"); + public static TreeCollectionUI None = new TreeCollectionUI("empty", "empty", "empty"); - public TreeCollectionUI(string alias, string repositoryAlias, string name) - { - Alias = alias ?? throw new ArgumentNullException(nameof(alias)); - Name = name ?? throw new ArgumentNullException(nameof(name)); - RepositoryAlias = repositoryAlias ?? throw new ArgumentNullException(nameof(RepositoryAlias)); - } + public TreeCollectionUI(string alias, string repositoryAlias, string name) + { + Alias = alias ?? throw new ArgumentNullException(nameof(alias)); + Name = name ?? throw new ArgumentNullException(nameof(name)); + RepositoryAlias = repositoryAlias ?? throw new ArgumentNullException(nameof(RepositoryAlias)); + } - public string Alias { get; private set; } - public string RepositoryAlias { get; private set; } - public string Name { get; private set; } - public string? Icon { get; internal set; } - public string? Color { get; internal set; } - public NavigationState? NavigateTo { get; internal set; } - public bool DefaultOpenEntities { get; internal set; } + public string Alias { get; private set; } + public string RepositoryAlias { get; private set; } + public string Name { get; private set; } + public string? Icon { get; internal set; } + public string? Color { get; internal set; } + public NavigationState? NavigateTo { get; internal set; } + public bool DefaultOpenEntities { get; internal set; } - public bool EntitiesVisible { get; internal set; } - public bool RootVisible { get; internal set; } - } + public bool EntitiesVisible { get; internal set; } + public bool RootVisible { get; internal set; } } diff --git a/src/RapidCMS.Core/Models/UI/TreeNodeUI.cs b/src/RapidCMS.Core/Models/UI/TreeNodeUI.cs index 4b8ae545..b2a081de 100644 --- a/src/RapidCMS.Core/Models/UI/TreeNodeUI.cs +++ b/src/RapidCMS.Core/Models/UI/TreeNodeUI.cs @@ -3,24 +3,23 @@ using RapidCMS.Core.Enums; using RapidCMS.Core.Navigation; -namespace RapidCMS.Core.Models.UI +namespace RapidCMS.Core.Models.UI; + +public class TreeNodeUI { - public class TreeNodeUI + public TreeNodeUI(string id, string repositoryAlias, string name, List<(string alias, PageType type)> collections) { - public TreeNodeUI(string id, string repositoryAlias, string name, List<(string alias, PageType type)> collections) - { - Id = id ?? throw new ArgumentNullException(nameof(id)); - RepositoryAlias = repositoryAlias ?? throw new ArgumentNullException(nameof(repositoryAlias)); - Name = name ?? throw new ArgumentNullException(nameof(name)); - Collections = collections ?? throw new ArgumentNullException(nameof(collections)); - } - - public string Id { get; private set; } - public string RepositoryAlias { get; private set; } - public string Name { get; private set; } - public NavigationState? NavigateTo { get; internal set; } - public bool RootVisibleOfCollections { get; internal set; } - public bool DefaultOpenCollections { get; internal set; } - public List<(string alias, PageType type)> Collections { get; private set; } + Id = id ?? throw new ArgumentNullException(nameof(id)); + RepositoryAlias = repositoryAlias ?? throw new ArgumentNullException(nameof(repositoryAlias)); + Name = name ?? throw new ArgumentNullException(nameof(name)); + Collections = collections ?? throw new ArgumentNullException(nameof(collections)); } + + public string Id { get; private set; } + public string RepositoryAlias { get; private set; } + public string Name { get; private set; } + public NavigationState? NavigateTo { get; internal set; } + public bool RootVisibleOfCollections { get; internal set; } + public bool DefaultOpenCollections { get; internal set; } + public List<(string alias, PageType type)> Collections { get; private set; } } diff --git a/src/RapidCMS.Core/Models/UI/TreeNodesUI.cs b/src/RapidCMS.Core/Models/UI/TreeNodesUI.cs index 69123182..c35a22ce 100644 --- a/src/RapidCMS.Core/Models/UI/TreeNodesUI.cs +++ b/src/RapidCMS.Core/Models/UI/TreeNodesUI.cs @@ -1,17 +1,16 @@ using System; using System.Collections.Generic; -namespace RapidCMS.Core.Models.UI +namespace RapidCMS.Core.Models.UI; + +public class TreeNodesUI { - public class TreeNodesUI + public TreeNodesUI(List nodes, bool moreDataAvailable) { - public TreeNodesUI(List nodes, bool moreDataAvailable) - { - Nodes = nodes ?? throw new ArgumentNullException(nameof(nodes)); - MoreDataAvailable = moreDataAvailable; - } - - public List Nodes { get; set; } - public bool MoreDataAvailable { get; set; } + Nodes = nodes ?? throw new ArgumentNullException(nameof(nodes)); + MoreDataAvailable = moreDataAvailable; } + + public List Nodes { get; set; } + public bool MoreDataAvailable { get; set; } } diff --git a/src/RapidCMS.Core/Models/UI/TreePageUI.cs b/src/RapidCMS.Core/Models/UI/TreePageUI.cs index 58c6878e..4c8a7cc4 100644 --- a/src/RapidCMS.Core/Models/UI/TreePageUI.cs +++ b/src/RapidCMS.Core/Models/UI/TreePageUI.cs @@ -1,21 +1,20 @@ using System; using RapidCMS.Core.Navigation; -namespace RapidCMS.Core.Models.UI +namespace RapidCMS.Core.Models.UI; + +public class TreePageUI { - public class TreePageUI + public TreePageUI(string name, string icon, string color, NavigationState navigateTo) { - public TreePageUI(string name, string icon, string color, NavigationState navigateTo) - { - Name = name ?? throw new ArgumentNullException(nameof(name)); - Icon = icon ?? throw new ArgumentNullException(nameof(icon)); - Color = color ?? throw new ArgumentNullException(nameof(color)); - NavigateTo = navigateTo ?? throw new ArgumentNullException(nameof(navigateTo)); - } - - public string Name { get; private set; } - public string Icon { get; private set; } - public string Color { get; private set; } - public NavigationState NavigateTo { get; private set; } + Name = name ?? throw new ArgumentNullException(nameof(name)); + Icon = icon ?? throw new ArgumentNullException(nameof(icon)); + Color = color ?? throw new ArgumentNullException(nameof(color)); + NavigateTo = navigateTo ?? throw new ArgumentNullException(nameof(navigateTo)); } + + public string Name { get; private set; } + public string Icon { get; private set; } + public string Color { get; private set; } + public NavigationState NavigateTo { get; private set; } } diff --git a/src/RapidCMS.Core/Models/UI/TreeRootUI.cs b/src/RapidCMS.Core/Models/UI/TreeRootUI.cs index 8bbf1349..12db584a 100644 --- a/src/RapidCMS.Core/Models/UI/TreeRootUI.cs +++ b/src/RapidCMS.Core/Models/UI/TreeRootUI.cs @@ -1,12 +1,11 @@ using System.Collections.Generic; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Models.UI +namespace RapidCMS.Core.Models.UI; + +public class TreeRootUI : TreeNodeUI { - public class TreeRootUI : TreeNodeUI + public TreeRootUI(string id, string repositoryAlias, string name, List<(string alias, PageType type)> collections) : base(id, repositoryAlias, name, collections) { - public TreeRootUI(string id, string repositoryAlias, string name, List<(string alias, PageType type)> collections) : base(id, repositoryAlias, name, collections) - { - } } } diff --git a/src/RapidCMS.Core/Navigation/CollectionState.cs b/src/RapidCMS.Core/Navigation/CollectionState.cs index 7f209e38..a6dc2376 100644 --- a/src/RapidCMS.Core/Navigation/CollectionState.cs +++ b/src/RapidCMS.Core/Navigation/CollectionState.cs @@ -1,21 +1,20 @@ using RapidCMS.Core.Helpers; -namespace RapidCMS.Core.Navigation +namespace RapidCMS.Core.Navigation; + +public record CollectionState( + int? ActiveTab = default, + string? SearchTerm = default, + int CurrentPage = 1, + int? MaxPage = default, + SortBag? Sorts = default) { - public record CollectionState( - int? ActiveTab = default, - string? SearchTerm = default, - int CurrentPage = 1, - int? MaxPage = default, - SortBag? Sorts = default) + public override string ToString() { - public override string ToString() - { - return UriHelper.CombineQueryString( - ("tab", ActiveTab?.ToString()), - ("q", SearchTerm), - ("p", CurrentPage == 1 ? null : CurrentPage.ToString()), - ("s", Sorts?.ToString())); - } + return UriHelper.CombineQueryString( + ("tab", ActiveTab?.ToString()), + ("q", SearchTerm), + ("p", CurrentPage == 1 ? null : CurrentPage.ToString()), + ("s", Sorts?.ToString())); } } diff --git a/src/RapidCMS.Core/Navigation/NavigationState.cs b/src/RapidCMS.Core/Navigation/NavigationState.cs index 20954f8e..fe6c059c 100644 --- a/src/RapidCMS.Core/Navigation/NavigationState.cs +++ b/src/RapidCMS.Core/Navigation/NavigationState.cs @@ -7,245 +7,244 @@ using RapidCMS.Core.Helpers; using RapidCMS.Core.Models.Data; -namespace RapidCMS.Core.Navigation +namespace RapidCMS.Core.Navigation; + +public class NavigationState : IEquatable, ICloneable { - public class NavigationState : IEquatable, ICloneable + private readonly string? _collectionAlias; + + public NavigationState(string url, string queryString) { - private readonly string? _collectionAlias; + var urlItems = url.Split('/', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); - public NavigationState(string url, string queryString) + if (urlItems.Length == 0) + { + PageType = PageType.Dashboard; + } + else { - var urlItems = url.Split('/', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); + PageType = Enum.TryParse(urlItems[0], true, out var pageType) ? pageType : PageType.Dashboard; - if (urlItems.Length == 0) + if (urlItems.Length > 1) { - PageType = PageType.Dashboard; - } - else - { - PageType = Enum.TryParse(urlItems[0], true, out var pageType) ? pageType : PageType.Dashboard; - - if (urlItems.Length > 1) + switch (PageType) { - switch (PageType) - { - case PageType.Collection: - - UsageType = Enum.TryParse(urlItems.ElementAtOrDefault(1), true, out var usageType1) ? usageType1 : UsageType.View; - _collectionAlias = urlItems.ElementAtOrDefault(2); - ParentPath = ParentPath.TryParse(urlItems.ElementAtOrDefault(3)); - break; - - case PageType.Node: - - UsageType = Enum.TryParse(urlItems.ElementAtOrDefault(1), true, out var usageType2) ? usageType2 : UsageType.View; - _collectionAlias = urlItems.ElementAtOrDefault(2); - VariantAlias = urlItems.ElementAtOrDefault(3); - ParentPath = ParentPath.TryParse(urlItems.ElementAtOrDefault(4)); - Id = urlItems.ElementAtOrDefault(5); - break; - - case PageType.Page: - UsageType = Enum.TryParse(urlItems.ElementAtOrDefault(1), true, out var usageType3) ? usageType3 : UsageType.View; - _collectionAlias = urlItems.ElementAtOrDefault(2); - ParentPath = ParentPath.TryParse(urlItems.ElementAtOrDefault(3)); - - break; - } - } - } + case PageType.Collection: + + UsageType = Enum.TryParse(urlItems.ElementAtOrDefault(1), true, out var usageType1) ? usageType1 : UsageType.View; + _collectionAlias = urlItems.ElementAtOrDefault(2); + ParentPath = ParentPath.TryParse(urlItems.ElementAtOrDefault(3)); + break; - var qs = HttpUtility.ParseQueryString(queryString); - var tab = int.TryParse(qs.Get("tab"), out var t) ? t : default(int?); - var searchTerm = qs.Get("q"); - var currentPage = int.TryParse(qs.Get("p"), out var p) ? p : 1; + case PageType.Node: - var sorts = qs.Get("s")?.Split("--") - .Select(x => x.Split("-")) - .Where(x => x.Length == 2) - .Select(x => int.TryParse(x[0], out var index) && Enum.TryParse(x[1], true, out var direction) - ? new KeyValuePair(index, direction) - : default(KeyValuePair?)) - .OfType>() - .Where(x => x.Value != OrderByType.Disabled); + UsageType = Enum.TryParse(urlItems.ElementAtOrDefault(1), true, out var usageType2) ? usageType2 : UsageType.View; + _collectionAlias = urlItems.ElementAtOrDefault(2); + VariantAlias = urlItems.ElementAtOrDefault(3); + ParentPath = ParentPath.TryParse(urlItems.ElementAtOrDefault(4)); + Id = urlItems.ElementAtOrDefault(5); + break; - var sortBag = sorts == null ? null : new SortBag(sorts); + case PageType.Page: + UsageType = Enum.TryParse(urlItems.ElementAtOrDefault(1), true, out var usageType3) ? usageType3 : UsageType.View; + _collectionAlias = urlItems.ElementAtOrDefault(2); + ParentPath = ParentPath.TryParse(urlItems.ElementAtOrDefault(3)); - CollectionState = new CollectionState(tab, searchTerm, currentPage, Sorts: sortBag); + break; + } + } } - public NavigationState() - { - PageType = PageType.Dashboard; + var qs = HttpUtility.ParseQueryString(queryString); + var tab = int.TryParse(qs.Get("tab"), out var t) ? t : default(int?); + var searchTerm = qs.Get("q"); + var currentPage = int.TryParse(qs.Get("p"), out var p) ? p : 1; - CollectionState = new CollectionState(); - } + var sorts = qs.Get("s")?.Split("--") + .Select(x => x.Split("-")) + .Where(x => x.Length == 2) + .Select(x => int.TryParse(x[0], out var index) && Enum.TryParse(x[1], true, out var direction) + ? new KeyValuePair(index, direction) + : default(KeyValuePair?)) + .OfType>() + .Where(x => x.Value != OrderByType.Disabled); - public NavigationState(PageType pageType) - { - PageType = pageType; + var sortBag = sorts == null ? null : new SortBag(sorts); - CollectionState = new CollectionState(); - } + CollectionState = new CollectionState(tab, searchTerm, currentPage, Sorts: sortBag); + } - public NavigationState(string pageAlias, ParentPath? parentPath) - { - PageType = PageType.Page; - UsageType = UsageType.View; - _collectionAlias = pageAlias; - ParentPath = parentPath; + public NavigationState() + { + PageType = PageType.Dashboard; - CollectionState = new CollectionState(); - } + CollectionState = new CollectionState(); + } - public NavigationState(string collectionAlias, ParentPath? parentPath, UsageType usageType) - { - PageType = PageType.Collection; - UsageType = usageType; - _collectionAlias = collectionAlias; - ParentPath = parentPath; + public NavigationState(PageType pageType) + { + PageType = pageType; - CollectionState = new CollectionState(); - } + CollectionState = new CollectionState(); + } - public NavigationState(string collectionAlias, IRelated? related, UsageType usageType) - { - PageType = PageType.Collection; - UsageType = usageType; - _collectionAlias = collectionAlias; - Related = related; + public NavigationState(string pageAlias, ParentPath? parentPath) + { + PageType = PageType.Page; + UsageType = UsageType.View; + _collectionAlias = pageAlias; + ParentPath = parentPath; - CollectionState = new CollectionState(); - } + CollectionState = new CollectionState(); + } - public NavigationState(string collectionAlias, ParentPath? parentPath, string? variantAlias, IRelated? related, UsageType usageType, PageType pageType) - { - PageType = pageType; - UsageType = usageType; - _collectionAlias = collectionAlias; - VariantAlias = variantAlias; - ParentPath = parentPath; - Related = related; - - CollectionState = new CollectionState(); - } + public NavigationState(string collectionAlias, ParentPath? parentPath, UsageType usageType) + { + PageType = PageType.Collection; + UsageType = usageType; + _collectionAlias = collectionAlias; + ParentPath = parentPath; - public NavigationState(string collectionAlias, ParentPath? parentPath, string variantAlias, IRelated? related, UsageType usageType) - { - PageType = PageType.Node; - UsageType = usageType; - _collectionAlias = collectionAlias; - VariantAlias = variantAlias; - ParentPath = parentPath; - Related = related; - - CollectionState = new CollectionState(); - } + CollectionState = new CollectionState(); + } - public NavigationState(string collectionAlias, ParentPath? parentPath, string variantAlias, string? id, UsageType usageType) - { - PageType = PageType.Node; - UsageType = usageType; - _collectionAlias = collectionAlias; - VariantAlias = variantAlias; - ParentPath = parentPath; - Id = id; - - CollectionState = new CollectionState(); - } + public NavigationState(string collectionAlias, IRelated? related, UsageType usageType) + { + PageType = PageType.Collection; + UsageType = usageType; + _collectionAlias = collectionAlias; + Related = related; - public NavigationState(string collectionAlias, ParentPath? parentPath, string variantAlias, IRelated? related, string? id, UsageType usageType) - { - PageType = PageType.Node; - UsageType = usageType; - _collectionAlias = collectionAlias; - VariantAlias = variantAlias; - ParentPath = parentPath; - Related = related; - Id = id; - - CollectionState = new CollectionState(); - } + CollectionState = new CollectionState(); + } - private NavigationState(string? collectionAlias, PageType pageType, UsageType usageType, string? variantAlias, ParentPath? parentPath, IRelated? related, string? id) - { - _collectionAlias = collectionAlias; - PageType = pageType; - UsageType = usageType; - VariantAlias = variantAlias; - ParentPath = parentPath; - Related = related; - Id = id; - - CollectionState = new CollectionState(); - } + public NavigationState(string collectionAlias, ParentPath? parentPath, string? variantAlias, IRelated? related, UsageType usageType, PageType pageType) + { + PageType = pageType; + UsageType = usageType; + _collectionAlias = collectionAlias; + VariantAlias = variantAlias; + ParentPath = parentPath; + Related = related; + + CollectionState = new CollectionState(); + } + + public NavigationState(string collectionAlias, ParentPath? parentPath, string variantAlias, IRelated? related, UsageType usageType) + { + PageType = PageType.Node; + UsageType = usageType; + _collectionAlias = collectionAlias; + VariantAlias = variantAlias; + ParentPath = parentPath; + Related = related; + + CollectionState = new CollectionState(); + } + + public NavigationState(string collectionAlias, ParentPath? parentPath, string variantAlias, string? id, UsageType usageType) + { + PageType = PageType.Node; + UsageType = usageType; + _collectionAlias = collectionAlias; + VariantAlias = variantAlias; + ParentPath = parentPath; + Id = id; + + CollectionState = new CollectionState(); + } + + public NavigationState(string collectionAlias, ParentPath? parentPath, string variantAlias, IRelated? related, string? id, UsageType usageType) + { + PageType = PageType.Node; + UsageType = usageType; + _collectionAlias = collectionAlias; + VariantAlias = variantAlias; + ParentPath = parentPath; + Related = related; + Id = id; + + CollectionState = new CollectionState(); + } - public PageType PageType { get; } - public UsageType UsageType { get; } - public string CollectionAlias => _collectionAlias ?? throw new InvalidOperationException("CollectionAlias is null"); - public string? VariantAlias { get; } - public ParentPath? ParentPath { get; } - public IRelated? Related { get; set; } - public string? Id { get; } + private NavigationState(string? collectionAlias, PageType pageType, UsageType usageType, string? variantAlias, ParentPath? parentPath, IRelated? related, string? id) + { + _collectionAlias = collectionAlias; + PageType = pageType; + UsageType = usageType; + VariantAlias = variantAlias; + ParentPath = parentPath; + Related = related; + Id = id; + + CollectionState = new CollectionState(); + } - public bool HasCollectionAlias => !string.IsNullOrEmpty(_collectionAlias); + public PageType PageType { get; } + public UsageType UsageType { get; } + public string CollectionAlias => _collectionAlias ?? throw new InvalidOperationException("CollectionAlias is null"); + public string? VariantAlias { get; } + public ParentPath? ParentPath { get; } + public IRelated? Related { get; set; } + public string? Id { get; } - public CollectionState CollectionState { get; set; } + public bool HasCollectionAlias => !string.IsNullOrEmpty(_collectionAlias); - // TODO: make dictionary with key resolvable to nested state (so a history back event restores search / page / sorting in nested collections) - public IList NestedStates { get; } = new List(); + public CollectionState CollectionState { get; set; } - public bool Equals(NavigationState? other) - { - return PageType == other?.PageType && - UsageType == other?.UsageType && - _collectionAlias == other?._collectionAlias && - VariantAlias == other?.VariantAlias && - ParentPath?.ToPathString() == other?.ParentPath?.ToPathString() && - Related == other?.Related && - Id == other?.Id && - CollectionState.ActiveTab == other?.CollectionState.ActiveTab && - CollectionState.CurrentPage == other?.CollectionState.CurrentPage; - } + // TODO: make dictionary with key resolvable to nested state (so a history back event restores search / page / sorting in nested collections) + public IList NestedStates { get; } = new List(); - public bool IsSimilar(NavigationState? other) - { - return PageType == other?.PageType && - // UsageType == other?.UsageType && - _collectionAlias == other?._collectionAlias && - VariantAlias == other?.VariantAlias && - ParentPath?.ToPathString() == other?.ParentPath?.ToPathString() && - Related == other?.Related && - Id == other?.Id; - } + public bool Equals(NavigationState? other) + { + return PageType == other?.PageType && + UsageType == other?.UsageType && + _collectionAlias == other?._collectionAlias && + VariantAlias == other?.VariantAlias && + ParentPath?.ToPathString() == other?.ParentPath?.ToPathString() && + Related == other?.Related && + Id == other?.Id && + CollectionState.ActiveTab == other?.CollectionState.ActiveTab && + CollectionState.CurrentPage == other?.CollectionState.CurrentPage; + } - public override string ToString() => ToString(false); + public bool IsSimilar(NavigationState? other) + { + return PageType == other?.PageType && + // UsageType == other?.UsageType && + _collectionAlias == other?._collectionAlias && + VariantAlias == other?.VariantAlias && + ParentPath?.ToPathString() == other?.ParentPath?.ToPathString() && + Related == other?.Related && + Id == other?.Id; + } - private string ToString(bool nested) - { - // TODO: when supporting nested states from urls this will become useful - // var nestedStates = NestedStates.Any() ? $"[{string.Join(";", NestedStates.Select(x => x.ToString(true)))}]" : null; + public override string ToString() => ToString(false); - var usageType = (UsageType.HasFlag(UsageType.Edit) ? UsageType.Edit : - UsageType.HasFlag(UsageType.New) ? UsageType.New : - UsageType.View).ToString().ToLower(); + private string ToString(bool nested) + { + // TODO: when supporting nested states from urls this will become useful + // var nestedStates = NestedStates.Any() ? $"[{string.Join(";", NestedStates.Select(x => x.ToString(true)))}]" : null; - return PageType switch - { - PageType.Collection => UriHelper.CombinePath("collection", usageType, _collectionAlias, ParentPath?.ToPathString(), nested ? default : CollectionState.ToString()), - PageType.Dashboard => "", - PageType.Error => "error", - PageType.Node => UriHelper.CombinePath("node", usageType, _collectionAlias, VariantAlias, ParentPath?.ToPathString() ?? "-", Id), - PageType.Page => UriHelper.CombinePath("page", usageType, _collectionAlias, ParentPath?.ToPathString() ?? "-"), - PageType.Unauthorized => "unauthorized", - _ => "" - }; - } + var usageType = (UsageType.HasFlag(UsageType.Edit) ? UsageType.Edit : + UsageType.HasFlag(UsageType.New) ? UsageType.New : + UsageType.View).ToString().ToLower(); - public object Clone() - => new NavigationState(_collectionAlias, PageType, UsageType, VariantAlias, ParentPath, Related, Id) - { - CollectionState = CollectionState - }; + return PageType switch + { + PageType.Collection => UriHelper.CombinePath("collection", usageType, _collectionAlias, ParentPath?.ToPathString(), nested ? default : CollectionState.ToString()), + PageType.Dashboard => "", + PageType.Error => "error", + PageType.Node => UriHelper.CombinePath("node", usageType, _collectionAlias, VariantAlias, ParentPath?.ToPathString() ?? "-", Id), + PageType.Page => UriHelper.CombinePath("page", usageType, _collectionAlias, ParentPath?.ToPathString() ?? "-"), + PageType.Unauthorized => "unauthorized", + _ => "" + }; } + + public object Clone() + => new NavigationState(_collectionAlias, PageType, UsageType, VariantAlias, ParentPath, Related, Id) + { + CollectionState = CollectionState + }; } diff --git a/src/RapidCMS.Core/Navigation/NavigationStateProvider.cs b/src/RapidCMS.Core/Navigation/NavigationStateProvider.cs index ec0d98f8..e449eaeb 100644 --- a/src/RapidCMS.Core/Navigation/NavigationStateProvider.cs +++ b/src/RapidCMS.Core/Navigation/NavigationStateProvider.cs @@ -10,271 +10,270 @@ using RapidCMS.Core.Models.EventArgs.Mediators; using RapidCMS.Core.Models.UI; -namespace RapidCMS.Core.Navigation +namespace RapidCMS.Core.Navigation; + +internal class NavigationStateProvider : INavigationStateProvider, IDisposable { - internal class NavigationStateProvider : INavigationStateProvider, IDisposable + private readonly IMediator _mediator; + private readonly NavigationManager _navigationManager; + + // TODO: if a list of states in the NestedStates of each NavigationStates is kept, then it would be possible to update the url also for nested collection navigation events + // this will restore the navigation state of collections via urls completely, but will be a bit hard when parsing the urls + // (and experimental -- perhaps hide it behind Advanced flag) + private List _states = new(); + + public NavigationStateProvider( + IMediator mediator, + NavigationManager navigationManager) { - private readonly IMediator _mediator; - private readonly NavigationManager _navigationManager; + _mediator = mediator; + _navigationManager = navigationManager; - // TODO: if a list of states in the NestedStates of each NavigationStates is kept, then it would be possible to update the url also for nested collection navigation events - // this will restore the navigation state of collections via urls completely, but will be a bit hard when parsing the urls - // (and experimental -- perhaps hide it behind Advanced flag) - private List _states = new(); + _navigationManager.LocationChanged += LocationChanged; + } - public NavigationStateProvider( - IMediator mediator, - NavigationManager navigationManager) + private void LocationChanged(object? sender, LocationChangedEventArgs e) + { + var uri = new Uri(e.Location); + var currentState = GetCurrentState(); + var locationState = new NavigationState(uri.LocalPath, uri.Query); + + if (!currentState.Equals(locationState)) { - _mediator = mediator; - _navigationManager = navigationManager; + var newState = Initialize(uri.LocalPath, uri.Query); - _navigationManager.LocationChanged += LocationChanged; + Notify(default, newState); } + } - private void LocationChanged(object? sender, LocationChangedEventArgs e) - { - var uri = new Uri(e.Location); - var currentState = GetCurrentState(); - var locationState = new NavigationState(uri.LocalPath, uri.Query); + public void AppendNavigationState(NavigationState newState) + { + var clonedState = (NavigationState)newState.Clone(); - if (!currentState.Equals(locationState)) - { - var newState = Initialize(uri.LocalPath, uri.Query); + _states.Add(clonedState); - Notify(default, newState); - } - } + Notify(default, newState); + UpdateUrl(newState); + } - public void AppendNavigationState(NavigationState newState) - { - var clonedState = (NavigationState)newState.Clone(); + public void AppendNavigationState(NavigationState currentState, NavigationState newState) + { + var clonedState = (NavigationState)newState.Clone(); + // top level state + if (_states.Contains(currentState)) + { _states.Add(clonedState); - Notify(default, newState); - UpdateUrl(newState); + Notify(currentState, clonedState); + UpdateUrl(clonedState); } - - public void AppendNavigationState(NavigationState currentState, NavigationState newState) + else { - var clonedState = (NavigationState)newState.Clone(); + var (parentState, foundState) = FindState(currentState); - // top level state - if (_states.Contains(currentState)) + if (parentState == null || foundState == null) { - _states.Add(clonedState); - - Notify(currentState, clonedState); - UpdateUrl(clonedState); + return; } - else - { - var (parentState, foundState) = FindState(currentState); - if (parentState == null || foundState == null) - { - return; - } + ReplaceState(parentState.NestedStates, foundState, clonedState); - ReplaceState(parentState.NestedStates, foundState, clonedState); - - Notify(foundState, clonedState); - } + Notify(foundState, clonedState); } + } - public void NestNavigationState(NavigationState currentState, NavigationState nestedState) - { - var (_, stateToAddNestedStateTo) = FindState(currentState); + public void NestNavigationState(NavigationState currentState, NavigationState nestedState) + { + var (_, stateToAddNestedStateTo) = FindState(currentState); - stateToAddNestedStateTo?.NestedStates.Add(nestedState); - } + stateToAddNestedStateTo?.NestedStates.Add(nestedState); + } - public NavigationState GetCurrentState() + public NavigationState GetCurrentState() + { + if (_states.Count == 0) { - if (_states.Count == 0) - { - _states.Add(new NavigationState()); - } - - return _states.Last(); + _states.Add(new NavigationState()); } - public bool IsRootState(NavigationState state) => _states.Any(x => x.Equals(state)); - - public NavigationState Initialize(string url, string queryString) - { - var newState = new NavigationState(url, queryString); - - _states.Clear(); + return _states.Last(); + } - _states.Add(newState); + public bool IsRootState(NavigationState state) => _states.Any(x => x.Equals(state)); - return newState; - } + public NavigationState Initialize(string url, string queryString) + { + var newState = new NavigationState(url, queryString); - public bool RemoveNavigationState(NavigationState currentState) - { - var hasRemovedState = RemoveLastState(currentState); - if (!hasRemovedState) - { - return false; - } - - var newState = GetCurrentState(); + _states.Clear(); - Notify(currentState, newState); - UpdateUrl(newState); + _states.Add(newState); - return true; - } + return newState; + } - public void ReplaceNavigationState(NavigationState currentState, NavigationState state) + public bool RemoveNavigationState(NavigationState currentState) + { + var hasRemovedState = RemoveLastState(currentState); + if (!hasRemovedState) { - var clonedState = (NavigationState)state.Clone(); + return false; + } - // top level state - if (_states.Contains(currentState)) - { - ReplaceState(_states, currentState, clonedState); + var newState = GetCurrentState(); - Notify(currentState, clonedState); - UpdateUrl(clonedState); - } - else - { - var (parentState, foundState) = FindState(currentState); + Notify(currentState, newState); + UpdateUrl(newState); - if (parentState == null || foundState == null) - { - return; - } + return true; + } - ReplaceState(parentState.NestedStates, foundState, clonedState); + public void ReplaceNavigationState(NavigationState currentState, NavigationState state) + { + var clonedState = (NavigationState)state.Clone(); - Notify(foundState, clonedState); - } - } + // top level state + if (_states.Contains(currentState)) + { + ReplaceState(_states, currentState, clonedState); - public void UpdateCollectionState(NavigationState currentState, CollectionState collectionState) + Notify(currentState, clonedState); + UpdateUrl(clonedState); + } + else { var (parentState, foundState) = FindState(currentState); - if (foundState == null) + if (parentState == null || foundState == null) { return; } - foundState.CollectionState = collectionState; + ReplaceState(parentState.NestedStates, foundState, clonedState); - Notify(currentState, foundState); + Notify(foundState, clonedState); + } + } - // if the found state is root state, then update url - if (_states.Contains(foundState)) - { - UpdateUrl(foundState); - } + public void UpdateCollectionState(NavigationState currentState, CollectionState collectionState) + { + var (parentState, foundState) = FindState(currentState); + + if (foundState == null) + { + return; } - public IView GetCurrentView(NavigationState currentState, ListUI list, TabUI? activeTab) + foundState.CollectionState = collectionState; + + Notify(currentState, foundState); + + // if the found state is root state, then update url + if (_states.Contains(foundState)) { - var (_, state) = FindState(currentState); + UpdateUrl(foundState); + } + } - state ??= currentState; + public IView GetCurrentView(NavigationState currentState, ListUI list, TabUI? activeTab) + { + var (_, state) = FindState(currentState); - var view = View.Create( - list.PageSize, - state.CollectionState.CurrentPage, - state.CollectionState.SearchTerm, - state.CollectionState.ActiveTab, - state.CollectionAlias); + state ??= currentState; - view.SetOrderBys(list.GetOrderBys(currentState.CollectionState.Sorts, activeTab?.DefaultSorts)); + var view = View.Create( + list.PageSize, + state.CollectionState.CurrentPage, + state.CollectionState.SearchTerm, + state.CollectionState.ActiveTab, + state.CollectionAlias); - return view; - } + view.SetOrderBys(list.GetOrderBys(currentState.CollectionState.Sorts, activeTab?.DefaultSorts)); - public bool TryProcessView(NavigationState currentState, IView view, bool hasSections) - { - var state = currentState.CollectionState; + return view; + } - var overTheEnd = !view.MoreDataAvailable && state.CurrentPage > 1 && !hasSections; - var atEnd = !view.MoreDataAvailable && !overTheEnd; - var notAtEnd = view.MoreDataAvailable && state.MaxPage == state.CurrentPage; + public bool TryProcessView(NavigationState currentState, IView view, bool hasSections) + { + var state = currentState.CollectionState; - currentState.CollectionState = state with - { - MaxPage = notAtEnd || overTheEnd ? null : atEnd ? state.CurrentPage : state.MaxPage, - CurrentPage = overTheEnd ? state.CurrentPage - 1 : state.CurrentPage - }; + var overTheEnd = !view.MoreDataAvailable && state.CurrentPage > 1 && !hasSections; + var atEnd = !view.MoreDataAvailable && !overTheEnd; + var notAtEnd = view.MoreDataAvailable && state.MaxPage == state.CurrentPage; + + currentState.CollectionState = state with + { + MaxPage = notAtEnd || overTheEnd ? null : atEnd ? state.CurrentPage : state.MaxPage, + CurrentPage = overTheEnd ? state.CurrentPage - 1 : state.CurrentPage + }; - return !overTheEnd; + return !overTheEnd; + } + + private void ReplaceState(IList currentStates, NavigationState currentState, NavigationState newState) + { + var index = currentStates.IndexOf(currentState); + if (index == -1) + { + return; } - private void ReplaceState(IList currentStates, NavigationState currentState, NavigationState newState) + currentStates[index] = newState; + } + + private bool RemoveLastState(NavigationState currentState) + { + if (_states.Contains(currentState)) { - var index = currentStates.IndexOf(currentState); - if (index == -1) + var itemToRemove = _states.LastOrDefault(); + + if (itemToRemove != null) { - return; + _states.Remove(itemToRemove); + return true; } - - currentStates[index] = newState; } - private bool RemoveLastState(NavigationState currentState) - { - if (_states.Contains(currentState)) - { - var itemToRemove = _states.LastOrDefault(); + return false; + } - if (itemToRemove != null) - { - _states.Remove(itemToRemove); - return true; - } - } + private void Notify(NavigationState? oldState, NavigationState newState) + { + _mediator.NotifyEvent(this, new NavigationEventArgs(oldState, newState)); + } - return false; - } + private void UpdateUrl(NavigationState state) + { + _navigationManager.NavigateTo(state.ToString()); + } - private void Notify(NavigationState? oldState, NavigationState newState) + private (NavigationState? parentState, NavigationState? foundState) FindState(NavigationState stateToFind) + { + if (_states.FirstOrDefault(x => x.Equals(stateToFind)) is NavigationState foundState) { - _mediator.NotifyEvent(this, new NavigationEventArgs(oldState, newState)); + return (default, foundState); } - - private void UpdateUrl(NavigationState state) + else { - _navigationManager.NavigateTo(state.ToString()); + return _states.Select(x => FindState(x, stateToFind)).Where(x => x.foundState != null).FirstOrDefault(); } + } - private (NavigationState? parentState, NavigationState? foundState) FindState(NavigationState stateToFind) + private (NavigationState? parentState, NavigationState? foundState) FindState(NavigationState parentState, NavigationState stateToFind) + { + if (parentState.NestedStates.FirstOrDefault(x => x.Equals(stateToFind)) is NavigationState foundState) { - if (_states.FirstOrDefault(x => x.Equals(stateToFind)) is NavigationState foundState) - { - return (default, foundState); - } - else - { - return _states.Select(x => FindState(x, stateToFind)).Where(x => x.foundState != null).FirstOrDefault(); - } + return (parentState, foundState); } - - private (NavigationState? parentState, NavigationState? foundState) FindState(NavigationState parentState, NavigationState stateToFind) + else { - if (parentState.NestedStates.FirstOrDefault(x => x.Equals(stateToFind)) is NavigationState foundState) - { - return (parentState, foundState); - } - else - { - return parentState.NestedStates.Select(x => FindState(x, stateToFind)).Where(x => x.foundState != null).FirstOrDefault(); - } + return parentState.NestedStates.Select(x => FindState(x, stateToFind)).Where(x => x.foundState != null).FirstOrDefault(); } + } - public void Dispose() - { - _navigationManager.LocationChanged -= LocationChanged; - } + public void Dispose() + { + _navigationManager.LocationChanged -= LocationChanged; } } diff --git a/src/RapidCMS.Core/Navigation/SortBag.cs b/src/RapidCMS.Core/Navigation/SortBag.cs index 94fda5e1..d3b409a5 100644 --- a/src/RapidCMS.Core/Navigation/SortBag.cs +++ b/src/RapidCMS.Core/Navigation/SortBag.cs @@ -2,31 +2,30 @@ using System.Linq; using RapidCMS.Core.Enums; -namespace RapidCMS.Core.Navigation +namespace RapidCMS.Core.Navigation; + +public class SortBag { - public class SortBag - { - private readonly Dictionary _sorts = new(); + private readonly Dictionary _sorts = new(); - public SortBag() - { + public SortBag() + { - } + } - public SortBag(IEnumerable> sorts) + public SortBag(IEnumerable> sorts) + { + foreach (var sort in sorts) { - foreach (var sort in sorts) - { - _sorts[sort.Key] = sort.Value; - } + _sorts[sort.Key] = sort.Value; } + } - public OrderByType? Get(int index) => _sorts.ContainsKey(index) ? _sorts[index] : null; + public OrderByType? Get(int index) => _sorts.ContainsKey(index) ? _sorts[index] : null; - public SortBag Clear() => new SortBag(); + public SortBag Clear() => new SortBag(); - public SortBag Add(int index, OrderByType direction) => new SortBag(_sorts.Append(new KeyValuePair(index, direction))); + public SortBag Add(int index, OrderByType direction) => new SortBag(_sorts.Append(new KeyValuePair(index, direction))); - public override string ToString() => $"{string.Join("--", _sorts.Select(x => $"{x.Key}-{x.Value}"))}".ToLower(); - } + public override string ToString() => $"{string.Join("--", _sorts.Select(x => $"{x.Key}-{x.Value}"))}".ToLower(); } diff --git a/src/RapidCMS.Core/Providers/CollectionDataProvider.cs b/src/RapidCMS.Core/Providers/CollectionDataProvider.cs index 90f16bc4..19464bb2 100644 --- a/src/RapidCMS.Core/Providers/CollectionDataProvider.cs +++ b/src/RapidCMS.Core/Providers/CollectionDataProvider.cs @@ -14,158 +14,157 @@ using RapidCMS.Core.Models.EventArgs.Mediators; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Providers +namespace RapidCMS.Core.Providers; + +internal class CollectionDataProvider : IRelationDataCollection, IDisposable { - internal class CollectionDataProvider : IRelationDataCollection, IDisposable + private readonly IRepository _repository; + private readonly IConcurrencyService _concurrencyService; + private readonly string? _repositoryAlias; + private readonly string? _collectionAlias; + private readonly IPropertyMetadata? _relatedElementsGetter; + private readonly bool _entityAsParent; + private readonly IPropertyMetadata? _repositoryParentSelector; + private readonly IPropertyMetadata _idProperty; + private readonly IReadOnlyList _displayProperties; + private readonly Type _relatedEntityType; + private readonly IPropertyMetadata _property; + private readonly IMediator _mediator; + + private FormEditContext? _editContext { get; set; } + private IParent? _parent; + + private readonly IDisposable? _eventHandle; + + private List _relatedIds = new List(); + + public CollectionDataProvider( + IRepository repository, + IConcurrencyService concurrencyService, + string? repositoryAlias, + string? collectionAlias, + IPropertyMetadata? relatedElementsGetter, + bool entityAsParent, + IPropertyMetadata? repositoryParentSelector, + IPropertyMetadata idProperty, + IReadOnlyList displayProperties, + Type relatedEntityType, + IPropertyMetadata property, + IMediator mediator) + { + _repository = repository ?? throw new ArgumentNullException(nameof(repository)); + _concurrencyService = concurrencyService; + _repositoryAlias = repositoryAlias; + _collectionAlias = collectionAlias; + _relatedElementsGetter = relatedElementsGetter; + _entityAsParent = entityAsParent; + _repositoryParentSelector = repositoryParentSelector; + _idProperty = idProperty ?? throw new ArgumentNullException(nameof(idProperty)); + _displayProperties = displayProperties ?? throw new ArgumentNullException(nameof(displayProperties)); + _relatedEntityType = relatedEntityType ?? throw new ArgumentNullException(nameof(relatedEntityType)); + _property = property ?? throw new ArgumentNullException(nameof(property)); + _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator)); + + _eventHandle = _mediator.RegisterCallback(OnRepositoryChangeAsync); + } + + public void Configure(object configuration) { } + + public event EventHandler? OnDataChange; + + private Task OnRepositoryChangeAsync(object? sender, CollectionRepositoryEventArgs args) { - private readonly IRepository _repository; - private readonly IConcurrencyService _concurrencyService; - private readonly string? _repositoryAlias; - private readonly string? _collectionAlias; - private readonly IPropertyMetadata? _relatedElementsGetter; - private readonly bool _entityAsParent; - private readonly IPropertyMetadata? _repositoryParentSelector; - private readonly IPropertyMetadata _idProperty; - private readonly IReadOnlyList _displayProperties; - private readonly Type _relatedEntityType; - private readonly IPropertyMetadata _property; - private readonly IMediator _mediator; - - private FormEditContext? _editContext { get; set; } - private IParent? _parent; - - private readonly IDisposable? _eventHandle; - - private List _relatedIds = new List(); - - public CollectionDataProvider( - IRepository repository, - IConcurrencyService concurrencyService, - string? repositoryAlias, - string? collectionAlias, - IPropertyMetadata? relatedElementsGetter, - bool entityAsParent, - IPropertyMetadata? repositoryParentSelector, - IPropertyMetadata idProperty, - IReadOnlyList displayProperties, - Type relatedEntityType, - IPropertyMetadata property, - IMediator mediator) + if ((!string.IsNullOrEmpty(_repositoryAlias) && args.RepositoryAlias == _repositoryAlias) || + (string.IsNullOrEmpty(_repositoryAlias) && args.CollectionAlias == _collectionAlias)) { - _repository = repository ?? throw new ArgumentNullException(nameof(repository)); - _concurrencyService = concurrencyService; - _repositoryAlias = repositoryAlias; - _collectionAlias = collectionAlias; - _relatedElementsGetter = relatedElementsGetter; - _entityAsParent = entityAsParent; - _repositoryParentSelector = repositoryParentSelector; - _idProperty = idProperty ?? throw new ArgumentNullException(nameof(idProperty)); - _displayProperties = displayProperties ?? throw new ArgumentNullException(nameof(displayProperties)); - _relatedEntityType = relatedEntityType ?? throw new ArgumentNullException(nameof(relatedEntityType)); - _property = property ?? throw new ArgumentNullException(nameof(property)); - _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator)); - - _eventHandle = _mediator.RegisterCallback(OnRepositoryChangeAsync); + OnDataChange?.Invoke(sender, EventArgs.Empty); } - public void Configure(object configuration) { } + return Task.CompletedTask; + } - public event EventHandler? OnDataChange; + public Task SetEntityAsync(FormEditContext editContext, IPropertyMetadata property, IParent? parent) + { + _editContext = editContext; + _parent = parent; - private Task OnRepositoryChangeAsync(object? sender, CollectionRepositoryEventArgs args) + var data = _relatedElementsGetter?.Getter(_property.Getter(_editContext.Entity)) ?? _property.Getter(_editContext.Entity); + if (data is IEnumerable entityCollection) { - if ((!string.IsNullOrEmpty(_repositoryAlias) && args.RepositoryAlias == _repositoryAlias) || - (string.IsNullOrEmpty(_repositoryAlias) && args.CollectionAlias == _collectionAlias)) - { - OnDataChange?.Invoke(sender, EventArgs.Empty); - } - - return Task.CompletedTask; + _relatedIds = entityCollection.Select(x => (object)x.Id!).ToList(); } - - public Task SetEntityAsync(FormEditContext editContext, IPropertyMetadata property, IParent? parent) + else if (data is IEnumerable objectCollection) { - _editContext = editContext; - _parent = parent; - - var data = _relatedElementsGetter?.Getter(_property.Getter(_editContext.Entity)) ?? _property.Getter(_editContext.Entity); - if (data is IEnumerable entityCollection) - { - _relatedIds = entityCollection.Select(x => (object)x.Id!).ToList(); - } - else if (data is IEnumerable objectCollection) - { - _relatedIds = objectCollection.ToList(); - } - else if (data is IEnumerable enumerable && data is not string) + _relatedIds = objectCollection.ToList(); + } + else if (data is IEnumerable enumerable && data is not string) + { + var list = new List(); + foreach (var element in enumerable) { - var list = new List(); - foreach (var element in enumerable) + if (element != null) { - if (element != null) - { - list.Add(element); - } + list.Add(element); } - _relatedIds = list; } - - return Task.CompletedTask; + _relatedIds = list; } - public async Task> GetAvailableElementsAsync(IView view) + return Task.CompletedTask; + } + + public async Task> GetAvailableElementsAsync(IView view) + { + if (_editContext == null) { - if (_editContext == null) - { - return new List(); - } + return new List(); + } - var parent = default(IParent?); + var parent = default(IParent?); - if (_entityAsParent && _editContext.EntityState != EntityState.IsNew) - { - parent = new ParentEntity(_editContext.Parent, _editContext.Entity, _editContext.RepositoryAlias); - } + if (_entityAsParent && _editContext.EntityState != EntityState.IsNew) + { + parent = new ParentEntity(_editContext.Parent, _editContext.Entity, _editContext.RepositoryAlias); + } - if (_repositoryParentSelector != null && _parent != null) - { - parent = _repositoryParentSelector.Getter.Invoke(_parent) as IParent; - } + if (_repositoryParentSelector != null && _parent != null) + { + parent = _repositoryParentSelector.Getter.Invoke(_parent) as IParent; + } - view.CollectionAlias = _editContext.CollectionAlias; + view.CollectionAlias = _editContext.CollectionAlias; - var entities = await _concurrencyService.EnsureCorrectConcurrencyAsync(() => _repository.GetAllAsync(new ViewContext(_editContext.CollectionAlias, parent), view)); + var entities = await _concurrencyService.EnsureCorrectConcurrencyAsync(() => _repository.GetAllAsync(new ViewContext(_editContext.CollectionAlias, parent), view)); - return entities - .Select(entity => (IElement)new Element - { - Id = _idProperty.Getter(entity), - Labels = _displayProperties.Select(x => x.StringGetter(entity)).ToList() - }) - .ToList(); - } + return entities + .Select(entity => (IElement)new Element + { + Id = _idProperty.Getter(entity), + Labels = _displayProperties.Select(x => x.StringGetter(entity)).ToList() + }) + .ToList(); + } - public async Task> GetRelatedElementsAsync() + public async Task> GetRelatedElementsAsync() + { + if (!_relatedIds.Any()) { - if (!_relatedIds.Any()) - { - return new List(); - } - - var elements = await GetAvailableElementsAsync(View.Default()); - return elements.Where(x => _relatedIds.Contains(x.Id)).ToList(); + return new List(); } - public void AddElement(object id) => _relatedIds.Add(id); + var elements = await GetAvailableElementsAsync(View.Default()); + return elements.Where(x => _relatedIds.Contains(x.Id)).ToList(); + } - public void RemoveElement(object id) => _relatedIds.Remove(id); + public void AddElement(object id) => _relatedIds.Add(id); - public bool IsRelated(object id) => _relatedIds.Any(x => x.Equals(id)); + public void RemoveElement(object id) => _relatedIds.Remove(id); - public IReadOnlyList GetCurrentRelatedElementIds() => _relatedIds; + public bool IsRelated(object id) => _relatedIds.Any(x => x.Equals(id)); - public Type GetRelatedEntityType() => _relatedEntityType ?? typeof(object); + public IReadOnlyList GetCurrentRelatedElementIds() => _relatedIds; - public void Dispose() => _eventHandle?.Dispose(); - } + public Type GetRelatedEntityType() => _relatedEntityType ?? typeof(object); + + public void Dispose() => _eventHandle?.Dispose(); } diff --git a/src/RapidCMS.Core/Providers/EnumDataProvider.cs b/src/RapidCMS.Core/Providers/EnumDataProvider.cs index f10c0dd3..de1119fe 100644 --- a/src/RapidCMS.Core/Providers/EnumDataProvider.cs +++ b/src/RapidCMS.Core/Providers/EnumDataProvider.cs @@ -9,56 +9,55 @@ using RapidCMS.Core.Forms; using RapidCMS.Core.Models.Data; -namespace RapidCMS.Core.Providers +namespace RapidCMS.Core.Providers; + +public class EnumDataProvider : IDataCollection + where TEnum : Enum { - public class EnumDataProvider : IDataCollection - where TEnum : Enum - { #pragma warning disable CS0067 - public event EventHandler? OnDataChange; + public event EventHandler? OnDataChange; #pragma warning restore CS0067 - public void Configure(object configuration) { } + public void Configure(object configuration) { } - public Task> GetAvailableElementsAsync(IView view) - { - var values = Enum.GetValues(typeof(TEnum)).Cast(); + public Task> GetAvailableElementsAsync(IView view) + { + var values = Enum.GetValues(typeof(TEnum)).Cast(); - var list = new List(); + var list = new List(); - foreach (var value in values) - { - var attribute = value.GetCustomAttribute(); + foreach (var value in values) + { + var attribute = value.GetCustomAttribute(); - if (attribute != null) + if (attribute != null) + { + list.Add(new Element { - list.Add(new Element - { - Id = value, - Labels = new[] { attribute.Name ?? string.Empty } - }); - } - else + Id = value, + Labels = new[] { attribute.Name ?? string.Empty } + }); + } + else + { + list.Add(new Element { - list.Add(new Element - { - Id = value, - Labels = new[] { value.ToString() } - }); - } + Id = value, + Labels = new[] { value.ToString() } + }); } - - return Task.FromResult>(list); } - public Task SetEntityAsync(FormEditContext editContext, IPropertyMetadata property, IParent? parent) - { - return Task.CompletedTask; - } + return Task.FromResult>(list); + } - public void Dispose() - { + public Task SetEntityAsync(FormEditContext editContext, IPropertyMetadata property, IParent? parent) + { + return Task.CompletedTask; + } + + public void Dispose() + { - } } } diff --git a/src/RapidCMS.Core/Providers/EnumRelationDataProvider.cs b/src/RapidCMS.Core/Providers/EnumRelationDataProvider.cs index 5b3d64d1..36035016 100644 --- a/src/RapidCMS.Core/Providers/EnumRelationDataProvider.cs +++ b/src/RapidCMS.Core/Providers/EnumRelationDataProvider.cs @@ -9,88 +9,87 @@ using RapidCMS.Core.Forms; using RapidCMS.Core.Models.Data; -namespace RapidCMS.Core.Providers +namespace RapidCMS.Core.Providers; + +public class EnumRelationDataProvider : IRelationDataCollection + where TEnum : Enum { - public class EnumRelationDataProvider : IRelationDataCollection - where TEnum : Enum + private readonly List _selectedEnums = new(); + private readonly List _elements; + + public EnumRelationDataProvider() { - private readonly List _selectedEnums = new(); - private readonly List _elements; + var values = Enum.GetValues(typeof(TEnum)).Cast(); - public EnumRelationDataProvider() - { - var values = Enum.GetValues(typeof(TEnum)).Cast(); + _elements = new List(); - _elements = new List(); + foreach (var value in values) + { + var attribute = value.GetCustomAttribute(); - foreach (var value in values) + if (attribute != null) { - var attribute = value.GetCustomAttribute(); - - if (attribute != null) + _elements.Add(new Element { - _elements.Add(new Element - { - Id = value, - Labels = new[] { attribute.Name ?? string.Empty } - }); - } - else + Id = value, + Labels = new[] { attribute.Name ?? string.Empty } + }); + } + else + { + _elements.Add(new Element { - _elements.Add(new Element - { - Id = value, - Labels = new[] { value.ToString() } - }); - } + Id = value, + Labels = new[] { value.ToString() } + }); } } + } #pragma warning disable CS0067 - public event EventHandler? OnDataChange; + public event EventHandler? OnDataChange; #pragma warning restore CS0067 - public void Configure(object configuration) { } + public void Configure(object configuration) { } - public Task> GetAvailableElementsAsync(IView view) - => Task.FromResult>(_elements); + public Task> GetAvailableElementsAsync(IView view) + => Task.FromResult>(_elements); - public Task SetEntityAsync(FormEditContext editContext, IPropertyMetadata property, IParent? parent) + public Task SetEntityAsync(FormEditContext editContext, IPropertyMetadata property, IParent? parent) + { + var data = property.Getter(editContext.Entity); + if (data is IEnumerable enumCollection) { - var data = property.Getter(editContext.Entity); - if (data is IEnumerable enumCollection) - { - _selectedEnums.AddRange(enumCollection); - } - else if (data is IEnumerable objectCollection) - { - _selectedEnums.AddRange(objectCollection.Cast()); - } - - return Task.CompletedTask; + _selectedEnums.AddRange(enumCollection); } - - public void Dispose() + else if (data is IEnumerable objectCollection) { - + _selectedEnums.AddRange(objectCollection.Cast()); } - public Task> GetRelatedElementsAsync() - => Task.FromResult>(_elements.Where(x => _selectedEnums.Contains((TEnum)x.Id)).ToList()); + return Task.CompletedTask; + } - public void AddElement(object id) - => _selectedEnums.Add((TEnum)id); + public void Dispose() + { - public void RemoveElement(object id) - => _selectedEnums.Remove((TEnum)id); + } - public bool IsRelated(object id) - => _selectedEnums.Contains((TEnum)id); + public Task> GetRelatedElementsAsync() + => Task.FromResult>(_elements.Where(x => _selectedEnums.Contains((TEnum)x.Id)).ToList()); - public IReadOnlyList GetCurrentRelatedElementIds() - => _selectedEnums.Cast().ToList(); + public void AddElement(object id) + => _selectedEnums.Add((TEnum)id); - public Type GetRelatedEntityType() - => typeof(TEnum); - } + public void RemoveElement(object id) + => _selectedEnums.Remove((TEnum)id); + + public bool IsRelated(object id) + => _selectedEnums.Contains((TEnum)id); + + public IReadOnlyList GetCurrentRelatedElementIds() + => _selectedEnums.Cast().ToList(); + + public Type GetRelatedEntityType() + => typeof(TEnum); } diff --git a/src/RapidCMS.Core/Providers/FixedOptionsDataProvider.cs b/src/RapidCMS.Core/Providers/FixedOptionsDataProvider.cs index 7132c3c0..ab40382c 100644 --- a/src/RapidCMS.Core/Providers/FixedOptionsDataProvider.cs +++ b/src/RapidCMS.Core/Providers/FixedOptionsDataProvider.cs @@ -7,47 +7,46 @@ using RapidCMS.Core.Forms; using RapidCMS.Core.Models.Data; -namespace RapidCMS.Core.Providers +namespace RapidCMS.Core.Providers; + +public class FixedOptionsDataProvider : IDataCollection { - public class FixedOptionsDataProvider : IDataCollection - { - private readonly IEnumerable<(object id, string label)> _options; + private readonly IEnumerable<(object id, string label)> _options; - public FixedOptionsDataProvider(IEnumerable? options) - { - _options = options?.Select(x => (x as object, x)) ?? Enumerable.Empty<(object, string)>(); - } + public FixedOptionsDataProvider(IEnumerable? options) + { + _options = options?.Select(x => (x as object, x)) ?? Enumerable.Empty<(object, string)>(); + } - public FixedOptionsDataProvider(IEnumerable<(object, string)>? options) - { - _options = options ?? Enumerable.Empty<(object, string)>(); - } + public FixedOptionsDataProvider(IEnumerable<(object, string)>? options) + { + _options = options ?? Enumerable.Empty<(object, string)>(); + } - public void Configure(object configuration) { } + public void Configure(object configuration) { } #pragma warning disable CS0067 - public event EventHandler? OnDataChange; + public event EventHandler? OnDataChange; #pragma warning restore CS0067 - public void Dispose() - { - } - - public Task> GetAvailableElementsAsync(IView view) - { - return Task.FromResult>( - _options - .Select(item => new Element - { - Id = item.id, - Labels = new[] { item.label } - }) - .ToList()); - } - - public Task SetEntityAsync(FormEditContext editContext, IPropertyMetadata property, IParent? parent) - { - return Task.CompletedTask; - } + public void Dispose() + { + } + + public Task> GetAvailableElementsAsync(IView view) + { + return Task.FromResult>( + _options + .Select(item => new Element + { + Id = item.id, + Labels = new[] { item.label } + }) + .ToList()); + } + + public Task SetEntityAsync(FormEditContext editContext, IPropertyMetadata property, IParent? parent) + { + return Task.CompletedTask; } } diff --git a/src/RapidCMS.Core/Providers/FormDataProvider.cs b/src/RapidCMS.Core/Providers/FormDataProvider.cs index 82fa1881..6422be34 100644 --- a/src/RapidCMS.Core/Providers/FormDataProvider.cs +++ b/src/RapidCMS.Core/Providers/FormDataProvider.cs @@ -3,29 +3,28 @@ using RapidCMS.Core.Abstractions.Metadata; using RapidCMS.Core.Models.Data; -namespace RapidCMS.Core.Providers +namespace RapidCMS.Core.Providers; + +internal class FormDataProvider : IDataValidationProvider { - internal class FormDataProvider : IDataValidationProvider + internal FormDataProvider(IPropertyMetadata property, IDataCollection collection) { - internal FormDataProvider(IPropertyMetadata property, IDataCollection collection) - { - Property = property ?? throw new ArgumentNullException(nameof(property)); - Collection = collection ?? throw new ArgumentNullException(nameof(collection)); - } + Property = property ?? throw new ArgumentNullException(nameof(property)); + Collection = collection ?? throw new ArgumentNullException(nameof(collection)); + } - public IPropertyMetadata Property { get; private set; } - public IDataCollection Collection { get; private set; } + public IPropertyMetadata Property { get; private set; } + public IDataCollection Collection { get; private set; } - internal IRelation? GenerateRelation() + internal IRelation? GenerateRelation() + { + if (Collection is IRelationDataCollection relationDataCollection) + { + return new Relation(relationDataCollection.GetRelatedEntityType(), Property, relationDataCollection.GetCurrentRelatedElementIds()); + } + else { - if (Collection is IRelationDataCollection relationDataCollection) - { - return new Relation(relationDataCollection.GetRelatedEntityType(), Property, relationDataCollection.GetCurrentRelatedElementIds()); - } - else - { - return default; - } + return default; } } } diff --git a/src/RapidCMS.Core/RapidCMS.Core.csproj b/src/RapidCMS.Core/RapidCMS.Core.csproj index a1a50cd2..bf41953b 100644 --- a/src/RapidCMS.Core/RapidCMS.Core.csproj +++ b/src/RapidCMS.Core/RapidCMS.Core.csproj @@ -1,8 +1,7 @@  - net6.0 - 10.0 + net6.0;net8.0 enable true Thomas Bleijendaal @@ -37,17 +36,30 @@ - - - - - + + + + - + + + + + + + + + + + + + + + True diff --git a/src/RapidCMS.Core/RapidCMSMiddleware.cs b/src/RapidCMS.Core/RapidCMSMiddleware.cs index d2cff74c..5dda0ce0 100644 --- a/src/RapidCMS.Core/RapidCMSMiddleware.cs +++ b/src/RapidCMS.Core/RapidCMSMiddleware.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Components.Authorization; using RapidCMS.Core.Abstractions.Config; using RapidCMS.Core.Abstractions.Dispatchers; @@ -39,164 +38,155 @@ using RapidCMS.Core.Services.Tree; using RapidCMS.Core.Validators; -namespace Microsoft.Extensions.DependencyInjection +namespace Microsoft.Extensions.DependencyInjection; + +public static partial class RapidCMSMiddleware { - public static partial class RapidCMSMiddleware + private static IServiceCollection AddRapidCMSCore(this IServiceCollection services, CmsConfig rootConfig) { - private static IServiceCollection AddRapidCMSCore(this IServiceCollection services, CmsConfig rootConfig) + services.AddSingleton(rootConfig); + services.AddSingleton(rootConfig); + + services.AddSingleton(); + services.AddSingleton(x => (ILogin)x.GetRequiredService(typeof(ICms))); + + services.AddSingleton, PageSetupResolver>(); + services.AddSingleton, CollectionSetupResolver>(); + services.AddSingleton(sp => new Lazy>(() => sp.GetRequiredService>())); + services.AddSingleton>, TreeElementsSetupResolver>(); + services.AddSingleton, IEnumerable>, TreeElementSetupResolver>(); + + services.AddSingleton, TypeRegistrationSetupResolver>(); + services.AddSingleton, EntityVariantSetupResolver>(); + services.AddSingleton, TreeViewSetupResolver>(); + services.AddSingleton, ElementSetupResolver>(); + services.AddSingleton, PaneSetupResolver>(); + services.AddSingleton, ListSetupResolver>(); + services.AddSingleton, NodeSetupResolver>(); + services.AddSingleton, FieldSetupResolver>(); + services.AddSingleton, ButtonSetupResolver>(); + services.AddSingleton, SubCollectionListSetupResolver>(); + services.AddSingleton, RelatedCollectionListSetupResolver>(); + + services.AddSingleton, ConventionBasedListConfigResolver>(); + services.AddSingleton, ConventionBasedNodeConfigResolver>(); + services.AddSingleton, ConventionBasedNodeSetupResolver>(); + services.AddSingleton(); + services.AddSingleton(); + + services.AddSingleton, IPlugin>, PluginTreeElementsSetupResolver>(); + + if (rootConfig.AllowAnonymousUsage) { - services.AddSingleton(rootConfig); - services.AddSingleton(rootConfig); - - services.AddSingleton(); - services.AddSingleton(x => (ILogin)x.GetRequiredService(typeof(ICms))); - - services.AddSingleton, PageSetupResolver>(); - services.AddSingleton, CollectionSetupResolver>(); - services.AddSingleton(sp => new Lazy>(() => sp.GetRequiredService>())); - services.AddSingleton>, TreeElementsSetupResolver>(); - services.AddSingleton, IEnumerable>, TreeElementSetupResolver>(); - - services.AddSingleton, TypeRegistrationSetupResolver>(); - services.AddSingleton, EntityVariantSetupResolver>(); - services.AddSingleton, TreeViewSetupResolver>(); - services.AddSingleton, ElementSetupResolver>(); - services.AddSingleton, PaneSetupResolver>(); - services.AddSingleton, ListSetupResolver>(); - services.AddSingleton, NodeSetupResolver>(); - services.AddSingleton, FieldSetupResolver>(); - services.AddSingleton, ButtonSetupResolver>(); - services.AddSingleton, SubCollectionListSetupResolver>(); - services.AddSingleton, RelatedCollectionListSetupResolver>(); - - services.AddSingleton, ConventionBasedListConfigResolver>(); - services.AddSingleton, ConventionBasedNodeConfigResolver>(); - services.AddSingleton, ConventionBasedNodeSetupResolver>(); - services.AddSingleton(); - services.AddSingleton(); - - services.AddSingleton, IPlugin>, PluginTreeElementsSetupResolver>(); - - if (rootConfig.AllowAnonymousUsage) - { - services.AddSingleton(); - services.AddSingleton(); - } + services.AddSingleton(); + services.AddSingleton(); + } - services.AddTransient(); - services.AddTransient(); + services.AddTransient(); + services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); - services.AddScoped(); + services.AddScoped(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); - services.AddScoped(); + services.AddScoped(); - services.AddScoped(); - services.AddScoped(typeof(OpenPaneButtonActionHandler<>)); - services.AddScoped(typeof(NavigateButtonActionHandler<>)); + services.AddScoped(); + services.AddScoped(typeof(OpenPaneButtonActionHandler<>)); + services.AddScoped(typeof(NavigateButtonActionHandler<>)); - services.AddScoped(typeof(EnumDataProvider<>), typeof(EnumDataProvider<>)); - services.AddTransient(typeof(EnumRelationDataProvider<>), typeof(EnumRelationDataProvider<>)); + services.AddScoped(typeof(EnumDataProvider<>), typeof(EnumDataProvider<>)); + services.AddTransient(typeof(EnumRelationDataProvider<>), typeof(EnumRelationDataProvider<>)); - services.AddTransient(); + services.AddTransient(); - AddServicesRequiringRepositories(services, rootConfig); + AddServicesRequiringRepositories(services, rootConfig); - services.AddScoped(); + services.AddScoped(); - // UI requirements - services.AddHttpContextAccessor(); - services.AddHttpClient(); + // UI requirements + services.AddHttpClient(); - services.AddMemoryCache(); + services.AddMemoryCache(); - return services; - } + return services; + } + + private static void AddServicesRequiringRepositories(IServiceCollection services, CmsConfig rootConfig) + { + var repositoryTypeDictionary = new Dictionary(); + var reverseRepositoryTypeDictionary = new Dictionary(); + var collectionAliasDictionary = new Dictionary>(); - private static void AddServicesRequiringRepositories(IServiceCollection services, CmsConfig rootConfig) + foreach (var collection in rootConfig.CollectionsAndPages.OfType()) { - var repositoryTypeDictionary = new Dictionary(); - var reverseRepositoryTypeDictionary = new Dictionary(); - var collectionAliasDictionary = new Dictionary>(); + ProcessCollection(collection); + } - foreach (var collection in rootConfig.CollectionsAndPages.OfType()) + services.AddSingleton(new CmsRepositoryTypeResolver(repositoryTypeDictionary, reverseRepositoryTypeDictionary)); + services.AddSingleton(new CollectionAliasResolver(collectionAliasDictionary)); + + void ProcessCollection(ICollectionConfig collection) + { + foreach (var repository in collection.RepositoryTypes) { - ProcessCollection(collection); - } + var descriptor = services.FirstOrDefault(x => x.ServiceType == repository); + if (descriptor == null) + { + continue; + } - services.AddSingleton(new CmsRepositoryTypeResolver(repositoryTypeDictionary, reverseRepositoryTypeDictionary)); - services.AddSingleton(new CollectionAliasResolver(collectionAliasDictionary)); + var implementationType = descriptor.ImplementationType; + if (implementationType == null) + { + continue; + } - void ProcessCollection(ICollectionConfig collection) - { - foreach (var repository in collection.RepositoryTypes) + var repositoryAlias = AliasHelper.GetRepositoryAlias(implementationType); + + repositoryTypeDictionary[repositoryAlias] = repository; + reverseRepositoryTypeDictionary[repository] = repositoryAlias; + if (implementationType != repository) { - var descriptor = services.FirstOrDefault(x => x.ServiceType == repository); - if (descriptor == null) - { - continue; - } - - var implementationType = descriptor.ImplementationType; - if (implementationType == null) - { - continue; - } - - var repositoryAlias = AliasHelper.GetRepositoryAlias(implementationType); - - repositoryTypeDictionary[repositoryAlias] = repository; - reverseRepositoryTypeDictionary[repository] = repositoryAlias; - if (implementationType != repository) - { - reverseRepositoryTypeDictionary[implementationType] = repositoryAlias; - } - - if (!collectionAliasDictionary.ContainsKey(repositoryAlias)) - { - collectionAliasDictionary.Add(repositoryAlias, new List()); - } - collectionAliasDictionary[repositoryAlias].Add(collection.Alias); + reverseRepositoryTypeDictionary[implementationType] = repositoryAlias; } - foreach (var subCollection in collection.CollectionsAndPages.OfType().Where(x => x is not ReferencedCollectionConfig)) + if (!collectionAliasDictionary.ContainsKey(repositoryAlias)) { - ProcessCollection(subCollection); + collectionAliasDictionary.Add(repositoryAlias, new List()); } + collectionAliasDictionary[repositoryAlias].Add(collection.Alias); } - } - - public static IApplicationBuilder UseRapidCMS(this IApplicationBuilder app, bool isDevelopment = false) - { - app.ApplicationServices.GetRequiredService().IsDevelopment = isDevelopment; - return app; + foreach (var subCollection in collection.CollectionsAndPages.OfType().Where(x => x is not ReferencedCollectionConfig)) + { + ProcessCollection(subCollection); + } } + } - private static CmsConfig GetRootConfig(Action? config = null) - { - var rootConfig = new CmsConfig(); - config?.Invoke(rootConfig); - return rootConfig; - } + private static CmsConfig GetRootConfig(Action? config = null) + { + var rootConfig = new CmsConfig(); + config?.Invoke(rootConfig); + return rootConfig; } } diff --git a/src/RapidCMS.Core/RapidCMSMiddlewareServer.cs b/src/RapidCMS.Core/RapidCMSMiddlewareServer.cs index fe923fa4..c48ee183 100644 --- a/src/RapidCMS.Core/RapidCMSMiddlewareServer.cs +++ b/src/RapidCMS.Core/RapidCMSMiddlewareServer.cs @@ -7,31 +7,30 @@ using RapidCMS.Core.Services.Auth; using Tewr.Blazor.FileReader; -namespace Microsoft.Extensions.DependencyInjection +namespace Microsoft.Extensions.DependencyInjection; + +// TODO: disable authentication/ route in server mode +public static partial class RapidCMSMiddleware { - // TODO: disable authentication/ route in server mode - public static partial class RapidCMSMiddleware + /// + /// Use this method to configure RapidCMS to run on a Blazor Server App, fully server side. + /// + /// + /// + /// + public static IServiceCollection AddRapidCMSServer(this IServiceCollection services, Action? config = null) { - /// - /// Use this method to configure RapidCMS to run on a Blazor Server App, fully server side. - /// - /// - /// - /// - public static IServiceCollection AddRapidCMSServer(this IServiceCollection services, Action? config = null) - { - var rootConfig = GetRootConfig(config); + var rootConfig = GetRootConfig(config); - services.AddTransient(); + services.AddTransient(); - services.AddTransient(); + services.AddTransient(); - services.AddFileReaderService(); + services.AddFileReaderService(); - // Semaphore for repositories - services.AddSingleton(serviceProvider => new SemaphoreSlim(rootConfig.Advanced.SemaphoreCount, rootConfig.Advanced.SemaphoreCount)); + // Semaphore for repositories + services.AddSingleton(serviceProvider => new SemaphoreSlim(rootConfig.Advanced.SemaphoreCount, rootConfig.Advanced.SemaphoreCount)); - return services.AddRapidCMSCore(rootConfig); - } + return services.AddRapidCMSCore(rootConfig); } } diff --git a/src/RapidCMS.Core/RapidCMSMiddlewareWebAssembly.cs b/src/RapidCMS.Core/RapidCMSMiddlewareWebAssembly.cs index d464e393..5e3f3019 100644 --- a/src/RapidCMS.Core/RapidCMSMiddlewareWebAssembly.cs +++ b/src/RapidCMS.Core/RapidCMSMiddlewareWebAssembly.cs @@ -11,170 +11,169 @@ using RapidCMS.Core.Services.Auth; using Tewr.Blazor.FileReader; -namespace Microsoft.Extensions.DependencyInjection +namespace Microsoft.Extensions.DependencyInjection; + +public static partial class RapidCMSMiddleware { - public static partial class RapidCMSMiddleware + /// + /// Use this method to configure RapidCMS to run on a Blazor WebAssembly App, fully client side. + /// + /// + /// + /// + public static IServiceCollection AddRapidCMSWebAssembly(this IServiceCollection services, Action? config = null) { - /// - /// Use this method to configure RapidCMS to run on a Blazor WebAssembly App, fully client side. - /// - /// - /// - /// - public static IServiceCollection AddRapidCMSWebAssembly(this IServiceCollection services, Action? config = null) - { - var rootConfig = GetRootConfig(config); + var rootConfig = GetRootConfig(config); - services.AddTransient(); - services.AddTransient(); + services.AddTransient(); + services.AddTransient(); - services.AddSingleton(serviceProvider => new SemaphoreSlim(rootConfig.Advanced.SemaphoreCount, rootConfig.Advanced.SemaphoreCount)); + services.AddSingleton(serviceProvider => new SemaphoreSlim(rootConfig.Advanced.SemaphoreCount, rootConfig.Advanced.SemaphoreCount)); - services.AddFileReaderService(); + services.AddFileReaderService(); - return services.AddRapidCMSCore(rootConfig); - } + return services.AddRapidCMSCore(rootConfig); + } - /// - /// Adds the repository as scoped service and adds a plain HttpClient for the given repository. - /// - /// - /// - /// - /// - public static IHttpClientBuilder AddRapidCMSApiRepository(this IServiceCollection services, Uri baseUri) - where TRepository : class - { - return services.AddRapidCMSApiRepository(baseUri); - } + /// + /// Adds the repository as scoped service and adds a plain HttpClient for the given repository. + /// + /// + /// + /// + /// + public static IHttpClientBuilder AddRapidCMSApiRepository(this IServiceCollection services, Uri baseUri) + where TRepository : class + { + return services.AddRapidCMSApiRepository(baseUri); + } - /// - /// Adds the repository as scoped service and adds a plain HttpClient for the given repository. - /// - /// - /// - /// - /// - /// - public static IHttpClientBuilder AddRapidCMSApiRepository(this IServiceCollection services, Uri baseUri) - where TIRepository : class - where TRepository : class, TIRepository - { - var alias = AliasHelper.GetRepositoryAlias(typeof(TRepository)); + /// + /// Adds the repository as scoped service and adds a plain HttpClient for the given repository. + /// + /// + /// + /// + /// + /// + public static IHttpClientBuilder AddRapidCMSApiRepository(this IServiceCollection services, Uri baseUri) + where TIRepository : class + where TRepository : class, TIRepository + { + var alias = AliasHelper.GetRepositoryAlias(typeof(TRepository)); - services.AddScoped(); + services.AddScoped(); - var builder = services.AddHttpClient(alias) - .ConfigureHttpClient(x => x.BaseAddress = new Uri(baseUri, $"_rapidcms/{alias}/")); + var builder = services.AddHttpClient(alias) + .ConfigureHttpClient(x => x.BaseAddress = new Uri(baseUri, $"_rapidcms/{alias}/")); - return builder; - } + return builder; + } - /// - /// Adds the repository as scoped service and adds an HttpClient with TDelegatingHandler for the given repository. - /// - /// - /// - /// - /// - /// - public static IHttpClientBuilder AddRapidCMSAuthenticatedApiRepository(this IServiceCollection services, Uri baseUri) - where TRepository : class - where TDelegatingHandler : DelegatingHandler - { - return services.AddRapidCMSAuthenticatedApiRepository(baseUri); - } + /// + /// Adds the repository as scoped service and adds an HttpClient with TDelegatingHandler for the given repository. + /// + /// + /// + /// + /// + /// + public static IHttpClientBuilder AddRapidCMSAuthenticatedApiRepository(this IServiceCollection services, Uri baseUri) + where TRepository : class + where TDelegatingHandler : DelegatingHandler + { + return services.AddRapidCMSAuthenticatedApiRepository(baseUri); + } - /// - /// Adds the repository as scoped service and adds an HttpClient with TDelegatingHandler for the given repository. - /// - /// - /// - /// - /// - /// - /// - public static IHttpClientBuilder AddRapidCMSAuthenticatedApiRepository(this IServiceCollection services, Uri baseUri) - where TIRepository : class - where TRepository : class, TIRepository - where TDelegatingHandler : DelegatingHandler - { - var builder = services.AddRapidCMSApiRepository(baseUri); - - if (_tokenMessageHandlerBuilder != null && _tokenMessageHandlerBuilder is Func messageHandlerBuilder) - { - builder = builder.AddHttpMessageHandler(sp => messageHandlerBuilder.Invoke(sp)); - } - else - { - builder = builder.AddHttpMessageHandler(); - } - - return builder; - } + /// + /// Adds the repository as scoped service and adds an HttpClient with TDelegatingHandler for the given repository. + /// + /// + /// + /// + /// + /// + /// + public static IHttpClientBuilder AddRapidCMSAuthenticatedApiRepository(this IServiceCollection services, Uri baseUri) + where TIRepository : class + where TRepository : class, TIRepository + where TDelegatingHandler : DelegatingHandler + { + var builder = services.AddRapidCMSApiRepository(baseUri); - private static Func? _tokenMessageHandlerBuilder = null; - - /// - /// Adds the MessageHandler which adds AccessTokens to HttClient-requests to ApiRepository-calls. - /// - /// NOTE: Set before calling AddRapidCMSApiRepository or AddRapidCMSFileUploadApiHttpClient - /// - /// - /// - /// - public static IServiceCollection AddRapidCMSApiTokenAuthorization(this IServiceCollection services, Func handlerBuilder) - where TDelegatingHandler : DelegatingHandler + if (_tokenMessageHandlerBuilder != null && _tokenMessageHandlerBuilder is Func messageHandlerBuilder) + { + builder = builder.AddHttpMessageHandler(sp => messageHandlerBuilder.Invoke(sp)); + } + else { - _tokenMessageHandlerBuilder = handlerBuilder; + builder = builder.AddHttpMessageHandler(); + } - return services; - } + return builder; + } - /// - /// Adds a plain HttpClient for the given file upload handler which is hosted at the given baseAddress. - /// The ApiFileHandler uses this HttpClient to communicate to the server. - /// - /// - /// - /// Base address of the api, for example: https://example.com - /// - public static IHttpClientBuilder AddRapidCMSFileUploadApiHttpClient(this IServiceCollection services, Uri baseUri) - where TFileHandler : IFileUploadHandler - { - var alias = AliasHelper.GetFileUploaderAlias(typeof(TFileHandler)); + private static Func? _tokenMessageHandlerBuilder = null; + + /// + /// Adds the MessageHandler which adds AccessTokens to HttClient-requests to ApiRepository-calls. + /// + /// NOTE: Set before calling AddRapidCMSApiRepository or AddRapidCMSFileUploadApiHttpClient + /// + /// + /// + /// + public static IServiceCollection AddRapidCMSApiTokenAuthorization(this IServiceCollection services, Func handlerBuilder) + where TDelegatingHandler : DelegatingHandler + { + _tokenMessageHandlerBuilder = handlerBuilder; - var builder = services.AddHttpClient>(alias) - .ConfigureHttpClient(x => x.BaseAddress = new Uri(baseUri, $"_rapidcms/{alias}/")); + return services; + } - return builder; - } + /// + /// Adds a plain HttpClient for the given file upload handler which is hosted at the given baseAddress. + /// The ApiFileHandler uses this HttpClient to communicate to the server. + /// + /// + /// + /// Base address of the api, for example: https://example.com + /// + public static IHttpClientBuilder AddRapidCMSFileUploadApiHttpClient(this IServiceCollection services, Uri baseUri) + where TFileHandler : IFileUploadHandler + { + var alias = AliasHelper.GetFileUploaderAlias(typeof(TFileHandler)); - /// - /// Adds a plain HttpClient for the given file upload handler which is hosted at the given baseAddress. - /// The ApiFileHandler uses this HttpClient to communicate to the server. - /// - /// - /// - /// - /// Base address of the api, for example: https://example.com - /// - public static IHttpClientBuilder AddRapidCMSAuthenticatedFileUploadApiHttpClient(this IServiceCollection services, Uri baseUri) - where TFileHandler : IFileUploadHandler - where TDelegatingHandler : DelegatingHandler + var builder = services.AddHttpClient>(alias) + .ConfigureHttpClient(x => x.BaseAddress = new Uri(baseUri, $"_rapidcms/{alias}/")); + + return builder; + } + + /// + /// Adds a plain HttpClient for the given file upload handler which is hosted at the given baseAddress. + /// The ApiFileHandler uses this HttpClient to communicate to the server. + /// + /// + /// + /// + /// Base address of the api, for example: https://example.com + /// + public static IHttpClientBuilder AddRapidCMSAuthenticatedFileUploadApiHttpClient(this IServiceCollection services, Uri baseUri) + where TFileHandler : IFileUploadHandler + where TDelegatingHandler : DelegatingHandler + { + var builder = services.AddRapidCMSFileUploadApiHttpClient(baseUri); + + if (_tokenMessageHandlerBuilder != null && _tokenMessageHandlerBuilder is Func messageHandlerBuilder) + { + builder = builder.AddHttpMessageHandler(sp => messageHandlerBuilder.Invoke(sp)); + } + else { - var builder = services.AddRapidCMSFileUploadApiHttpClient(baseUri); - - if (_tokenMessageHandlerBuilder != null && _tokenMessageHandlerBuilder is Func messageHandlerBuilder) - { - builder = builder.AddHttpMessageHandler(sp => messageHandlerBuilder.Invoke(sp)); - } - else - { - builder = builder.AddHttpMessageHandler(); - } - - return builder; + builder = builder.AddHttpMessageHandler(); } + + return builder; } } diff --git a/src/RapidCMS.Core/Repositories/ApiMappedRepository.cs b/src/RapidCMS.Core/Repositories/ApiMappedRepository.cs index 773b439d..037def6a 100644 --- a/src/RapidCMS.Core/Repositories/ApiMappedRepository.cs +++ b/src/RapidCMS.Core/Repositories/ApiMappedRepository.cs @@ -14,84 +14,83 @@ using RapidCMS.Core.Models.ApiBridge.Response; using RapidCMS.Core.Repositories; -namespace RapidCMS.Repositories.ApiBridge +namespace RapidCMS.Repositories.ApiBridge; + +public class ApiMappedRepository : BaseMappedRepository + where TEntity : class, IEntity + where TDatabaseEntity : class { - public class ApiMappedRepository : BaseMappedRepository - where TEntity : class, IEntity - where TDatabaseEntity : class - { - private readonly ApiRepositoryHelper _apiRepositoryHelper; + private readonly ApiRepositoryHelper _apiRepositoryHelper; - public ApiMappedRepository(IHttpClientFactory httpClientFactory) - { - var jsonSerializerSettings = new JsonSerializerSettings(); - jsonSerializerSettings.Converters.Add(new EntityModelJsonConverter()); - var repositoryAlias = AliasHelper.GetRepositoryAlias(typeof(ApiMappedRepository)); + public ApiMappedRepository(IHttpClientFactory httpClientFactory) + { + var jsonSerializerSettings = new JsonSerializerSettings(); + jsonSerializerSettings.Converters.Add(new EntityModelJsonConverter()); + var repositoryAlias = AliasHelper.GetRepositoryAlias(typeof(ApiMappedRepository)); - _apiRepositoryHelper = new ApiRepositoryHelper(httpClientFactory, jsonSerializerSettings, repositoryAlias); - } + _apiRepositoryHelper = new ApiRepositoryHelper(httpClientFactory, jsonSerializerSettings, repositoryAlias); + } - public override Task DeleteAsync(string id, IParent? parent) - => _apiRepositoryHelper.DoRequestAsync(_apiRepositoryHelper.CreateRequest(HttpMethod.Delete, $"entity/{id}", new DeleteModel(parent))); + public override Task DeleteAsync(string id, IParent? parent) + => _apiRepositoryHelper.DoRequestAsync(_apiRepositoryHelper.CreateRequest(HttpMethod.Delete, $"entity/{id}", new DeleteModel(parent))); - public override async Task> GetAllAsync(IParent? parent, IView view) + public override async Task> GetAllAsync(IParent? parent, IView view) + { + var results = await _apiRepositoryHelper.DoRequestAsync>(_apiRepositoryHelper.CreateRequest(HttpMethod.Post, "all", new ParentQueryModel(parent, view))); + if (results == default) { - var results = await _apiRepositoryHelper.DoRequestAsync>(_apiRepositoryHelper.CreateRequest(HttpMethod.Post, "all", new ParentQueryModel(parent, view))); - if (results == default) - { - return Enumerable.Empty(); - } + return Enumerable.Empty(); + } - view.HasMoreData(results.MoreDataAvailable); + view.HasMoreData(results.MoreDataAvailable); - return results.Entities.Select(x => x.Entity); - } + return results.Entities.Select(x => x.Entity); + } - public override async Task?> GetAllRelatedAsync(IRelated related, IView view) + public override async Task?> GetAllRelatedAsync(IRelated related, IView view) + { + var results = await _apiRepositoryHelper.DoRequestAsync>(_apiRepositoryHelper.CreateRequest(HttpMethod.Post, "all/related", new RelatedQueryModel(related, view))); + if (results == default) { - var results = await _apiRepositoryHelper.DoRequestAsync>(_apiRepositoryHelper.CreateRequest(HttpMethod.Post, "all/related", new RelatedQueryModel(related, view))); - if (results == default) - { - return Enumerable.Empty(); - } + return Enumerable.Empty(); + } - view.HasMoreData(results.MoreDataAvailable); + view.HasMoreData(results.MoreDataAvailable); - return results.Entities.Select(x => x.Entity); - } + return results.Entities.Select(x => x.Entity); + } - public override async Task?> GetAllNonRelatedAsync(IRelated related, IView view) + public override async Task?> GetAllNonRelatedAsync(IRelated related, IView view) + { + var results = await _apiRepositoryHelper.DoRequestAsync>(_apiRepositoryHelper.CreateRequest(HttpMethod.Post, "all/nonrelated", new RelatedQueryModel(related, view))); + if (results == default) { - var results = await _apiRepositoryHelper.DoRequestAsync>(_apiRepositoryHelper.CreateRequest(HttpMethod.Post, "all/nonrelated", new RelatedQueryModel(related, view))); - if (results == default) - { - return Enumerable.Empty(); - } + return Enumerable.Empty(); + } - view.HasMoreData(results.MoreDataAvailable); + view.HasMoreData(results.MoreDataAvailable); - return results.Entities.Select(x => x.Entity); - } + return results.Entities.Select(x => x.Entity); + } - public override async Task GetByIdAsync(string id, IParent? parent) - => (await _apiRepositoryHelper.DoRequestAsync>(_apiRepositoryHelper.CreateRequest(HttpMethod.Post, $"entity/{id}", new ParentQueryModel(parent))))?.Entity; + public override async Task GetByIdAsync(string id, IParent? parent) + => (await _apiRepositoryHelper.DoRequestAsync>(_apiRepositoryHelper.CreateRequest(HttpMethod.Post, $"entity/{id}", new ParentQueryModel(parent))))?.Entity; - public override async Task InsertAsync(IEditContext editContext) - => (await _apiRepositoryHelper.DoRequestAsync>(_apiRepositoryHelper.CreateRequest(HttpMethod.Post, "entity", new EditContextModel(editContext)), editContext))?.Entity; + public override async Task InsertAsync(IEditContext editContext) + => (await _apiRepositoryHelper.DoRequestAsync>(_apiRepositoryHelper.CreateRequest(HttpMethod.Post, "entity", new EditContextModel(editContext)), editContext))?.Entity; - public override async Task NewAsync(IParent? parent, Type? variantType = null) - => (await _apiRepositoryHelper.DoRequestAsync>(_apiRepositoryHelper.CreateRequest(HttpMethod.Post, "new", new ParentQueryModel(parent, variantType))))?.Entity ?? throw new NotFoundException("Could not create new entity."); + public override async Task NewAsync(IParent? parent, Type? variantType = null) + => (await _apiRepositoryHelper.DoRequestAsync>(_apiRepositoryHelper.CreateRequest(HttpMethod.Post, "new", new ParentQueryModel(parent, variantType))))?.Entity ?? throw new NotFoundException("Could not create new entity."); - public override Task UpdateAsync(IEditContext editContext) - => _apiRepositoryHelper.DoRequestAsync(_apiRepositoryHelper.CreateRequest(HttpMethod.Put, $"entity/{editContext.Entity.Id}", new EditContextModel(editContext)), editContext); + public override Task UpdateAsync(IEditContext editContext) + => _apiRepositoryHelper.DoRequestAsync(_apiRepositoryHelper.CreateRequest(HttpMethod.Put, $"entity/{editContext.Entity.Id}", new EditContextModel(editContext)), editContext); - public override Task AddAsync(IRelated related, string id) - => _apiRepositoryHelper.DoRequestAsync(_apiRepositoryHelper.CreateRequest(HttpMethod.Post, $"relate", new RelateModel(related, id))); + public override Task AddAsync(IRelated related, string id) + => _apiRepositoryHelper.DoRequestAsync(_apiRepositoryHelper.CreateRequest(HttpMethod.Post, $"relate", new RelateModel(related, id))); - public override Task RemoveAsync(IRelated related, string id) - => _apiRepositoryHelper.DoRequestAsync(_apiRepositoryHelper.CreateRequest(HttpMethod.Delete, $"relate", new RelateModel(related, id))); + public override Task RemoveAsync(IRelated related, string id) + => _apiRepositoryHelper.DoRequestAsync(_apiRepositoryHelper.CreateRequest(HttpMethod.Delete, $"relate", new RelateModel(related, id))); - public override Task ReorderAsync(string? beforeId, string id, IParent? parent) - => _apiRepositoryHelper.DoRequestAsync(_apiRepositoryHelper.CreateRequest(HttpMethod.Post, $"reorder", new ReorderModel(beforeId, id, parent))); - } + public override Task ReorderAsync(string? beforeId, string id, IParent? parent) + => _apiRepositoryHelper.DoRequestAsync(_apiRepositoryHelper.CreateRequest(HttpMethod.Post, $"reorder", new ReorderModel(beforeId, id, parent))); } diff --git a/src/RapidCMS.Core/Repositories/ApiRepository.cs b/src/RapidCMS.Core/Repositories/ApiRepository.cs index ca84f41f..ac0116ee 100644 --- a/src/RapidCMS.Core/Repositories/ApiRepository.cs +++ b/src/RapidCMS.Core/Repositories/ApiRepository.cs @@ -14,83 +14,82 @@ using RapidCMS.Core.Models.ApiBridge.Response; using RapidCMS.Core.Repositories; -namespace RapidCMS.Repositories.ApiBridge +namespace RapidCMS.Repositories.ApiBridge; + +public class ApiRepository : BaseRepository + where TEntity : class, IEntity { - public class ApiRepository : BaseRepository - where TEntity : class, IEntity - { - private readonly ApiRepositoryHelper _apiRepositoryHelper; + private readonly ApiRepositoryHelper _apiRepositoryHelper; - public ApiRepository(IHttpClientFactory httpClientFactory) - { - var jsonSerializerSettings = new JsonSerializerSettings(); - jsonSerializerSettings.Converters.Add(new EntityModelJsonConverter()); - var repositoryAlias = AliasHelper.GetRepositoryAlias(typeof(ApiRepository)); + public ApiRepository(IHttpClientFactory httpClientFactory) + { + var jsonSerializerSettings = new JsonSerializerSettings(); + jsonSerializerSettings.Converters.Add(new EntityModelJsonConverter()); + var repositoryAlias = AliasHelper.GetRepositoryAlias(typeof(ApiRepository)); - _apiRepositoryHelper = new ApiRepositoryHelper(httpClientFactory, jsonSerializerSettings, repositoryAlias); - } + _apiRepositoryHelper = new ApiRepositoryHelper(httpClientFactory, jsonSerializerSettings, repositoryAlias); + } - public override Task DeleteAsync(string id, IParent? parent) - => _apiRepositoryHelper.DoRequestAsync(_apiRepositoryHelper.CreateRequest(HttpMethod.Delete, $"entity/{id}", new DeleteModel(parent))); + public override Task DeleteAsync(string id, IParent? parent) + => _apiRepositoryHelper.DoRequestAsync(_apiRepositoryHelper.CreateRequest(HttpMethod.Delete, $"entity/{id}", new DeleteModel(parent))); - public override async Task> GetAllAsync(IParent? parent, IView view) + public override async Task> GetAllAsync(IParent? parent, IView view) + { + var results = await _apiRepositoryHelper.DoRequestAsync>(_apiRepositoryHelper.CreateRequest(HttpMethod.Post, "all", new ParentQueryModel(parent, view))); + if (results == default) { - var results = await _apiRepositoryHelper.DoRequestAsync>(_apiRepositoryHelper.CreateRequest(HttpMethod.Post, "all", new ParentQueryModel(parent, view))); - if (results == default) - { - return Enumerable.Empty(); - } + return Enumerable.Empty(); + } - view.HasMoreData(results.MoreDataAvailable); + view.HasMoreData(results.MoreDataAvailable); - return results.Entities.Select(x => x.Entity); - } + return results.Entities.Select(x => x.Entity); + } - public override async Task?> GetAllRelatedAsync(IRelated related, IView view) + public override async Task?> GetAllRelatedAsync(IRelated related, IView view) + { + var results = await _apiRepositoryHelper.DoRequestAsync>(_apiRepositoryHelper.CreateRequest(HttpMethod.Post, "all/related", new RelatedQueryModel(related, view))); + if (results == default) { - var results = await _apiRepositoryHelper.DoRequestAsync>(_apiRepositoryHelper.CreateRequest(HttpMethod.Post, "all/related", new RelatedQueryModel(related, view))); - if (results == default) - { - return Enumerable.Empty(); - } + return Enumerable.Empty(); + } - view.HasMoreData(results.MoreDataAvailable); + view.HasMoreData(results.MoreDataAvailable); - return results.Entities.Select(x => x.Entity); - } + return results.Entities.Select(x => x.Entity); + } - public override async Task?> GetAllNonRelatedAsync(IRelated related, IView view) + public override async Task?> GetAllNonRelatedAsync(IRelated related, IView view) + { + var results = await _apiRepositoryHelper.DoRequestAsync>(_apiRepositoryHelper.CreateRequest(HttpMethod.Post, "all/nonrelated", new RelatedQueryModel(related, view))); + if (results == default) { - var results = await _apiRepositoryHelper.DoRequestAsync>(_apiRepositoryHelper.CreateRequest(HttpMethod.Post, "all/nonrelated", new RelatedQueryModel(related, view))); - if (results == default) - { - return Enumerable.Empty(); - } + return Enumerable.Empty(); + } - view.HasMoreData(results.MoreDataAvailable); + view.HasMoreData(results.MoreDataAvailable); - return results.Entities.Select(x => x.Entity); - } + return results.Entities.Select(x => x.Entity); + } - public override async Task GetByIdAsync(string id, IParent? parent) - => (await _apiRepositoryHelper.DoRequestAsync>(_apiRepositoryHelper.CreateRequest(HttpMethod.Post, $"entity/{id}", new ParentQueryModel(parent))))?.Entity; + public override async Task GetByIdAsync(string id, IParent? parent) + => (await _apiRepositoryHelper.DoRequestAsync>(_apiRepositoryHelper.CreateRequest(HttpMethod.Post, $"entity/{id}", new ParentQueryModel(parent))))?.Entity; - public override async Task InsertAsync(IEditContext editContext) - => (await _apiRepositoryHelper.DoRequestAsync>(_apiRepositoryHelper.CreateRequest(HttpMethod.Post, "entity", new EditContextModel(editContext)), editContext))?.Entity; + public override async Task InsertAsync(IEditContext editContext) + => (await _apiRepositoryHelper.DoRequestAsync>(_apiRepositoryHelper.CreateRequest(HttpMethod.Post, "entity", new EditContextModel(editContext)), editContext))?.Entity; - public override async Task NewAsync(IParent? parent, Type? variantType = null) - => (await _apiRepositoryHelper.DoRequestAsync>(_apiRepositoryHelper.CreateRequest(HttpMethod.Post, "new", new ParentQueryModel(parent, variantType))))?.Entity ?? throw new NotFoundException("Could not create new entity."); + public override async Task NewAsync(IParent? parent, Type? variantType = null) + => (await _apiRepositoryHelper.DoRequestAsync>(_apiRepositoryHelper.CreateRequest(HttpMethod.Post, "new", new ParentQueryModel(parent, variantType))))?.Entity ?? throw new NotFoundException("Could not create new entity."); - public override Task UpdateAsync(IEditContext editContext) - => _apiRepositoryHelper.DoRequestAsync(_apiRepositoryHelper.CreateRequest(HttpMethod.Put, $"entity/{editContext.Entity.Id}", new EditContextModel(editContext)), editContext); + public override Task UpdateAsync(IEditContext editContext) + => _apiRepositoryHelper.DoRequestAsync(_apiRepositoryHelper.CreateRequest(HttpMethod.Put, $"entity/{editContext.Entity.Id}", new EditContextModel(editContext)), editContext); - public override Task AddAsync(IRelated related, string id) - => _apiRepositoryHelper.DoRequestAsync(_apiRepositoryHelper.CreateRequest(HttpMethod.Post, $"relate", new RelateModel(related, id))); + public override Task AddAsync(IRelated related, string id) + => _apiRepositoryHelper.DoRequestAsync(_apiRepositoryHelper.CreateRequest(HttpMethod.Post, $"relate", new RelateModel(related, id))); - public override Task RemoveAsync(IRelated related, string id) - => _apiRepositoryHelper.DoRequestAsync(_apiRepositoryHelper.CreateRequest(HttpMethod.Delete, $"relate", new RelateModel(related, id))); + public override Task RemoveAsync(IRelated related, string id) + => _apiRepositoryHelper.DoRequestAsync(_apiRepositoryHelper.CreateRequest(HttpMethod.Delete, $"relate", new RelateModel(related, id))); - public override Task ReorderAsync(string? beforeId, string id, IParent? parent) - => _apiRepositoryHelper.DoRequestAsync(_apiRepositoryHelper.CreateRequest(HttpMethod.Post, $"reorder", new ReorderModel(beforeId, id, parent))); - } + public override Task ReorderAsync(string? beforeId, string id, IParent? parent) + => _apiRepositoryHelper.DoRequestAsync(_apiRepositoryHelper.CreateRequest(HttpMethod.Post, $"reorder", new ReorderModel(beforeId, id, parent))); } diff --git a/src/RapidCMS.Core/Repositories/BaseMappedRepository.cs b/src/RapidCMS.Core/Repositories/BaseMappedRepository.cs index 707a6a06..e4e4ce40 100644 --- a/src/RapidCMS.Core/Repositories/BaseMappedRepository.cs +++ b/src/RapidCMS.Core/Repositories/BaseMappedRepository.cs @@ -7,158 +7,157 @@ using RapidCMS.Core.Abstractions.Repositories; using RapidCMS.Core.Models.Data; -namespace RapidCMS.Core.Repositories +namespace RapidCMS.Core.Repositories; + +/// +/// Base class of repository when backing store requires a mapping (the database entity cannot be used directly in the view). +/// +/// If TEntity == TQueryEntity, use BaseRepository +/// +/// Type of the entity used in the views +/// Type of the entity in the backing store +public abstract class BaseMappedRepository : IRepository + where TEntity : class, IEntity + where TDatabaseEntity : class { /// - /// Base class of repository when backing store requires a mapping (the database entity cannot be used directly in the view). + /// This method gets an entity belonging to the given id and parent(s). + /// + /// + /// + /// + public abstract Task GetByIdAsync(string id, IParent? parent); + + /// + /// This method gets all entities belonging to the given parent(s) and query instructions (paging / search). + /// + /// This query is based on the TDatabaseEntity, and not TEntity to allow for mapping. + /// + /// + /// + /// + public abstract Task> GetAllAsync(IParent? parent, IView view); + + /// + /// This method gets all entities that are related to the given entity and query instruction (paging / search). + /// + /// This query is based on the TDatabaseEntity, and not TEntity to allow for mapping. + /// + /// + /// + /// + public virtual Task?> GetAllRelatedAsync(IRelated related, IView view) + => throw new NotImplementedException($"In order to use many-to-many list editors, implement {nameof(GetAllRelatedAsync)} on the {GetType()}."); + + /// + /// This method gets all entities that match the given query instruction (paging / search) but are not related to the given entity. + /// + /// This query is based on the TDatabaseEntity, and not TEntity to allow for mapping. + /// + /// + /// + /// + public virtual Task?> GetAllNonRelatedAsync(IRelated related, IView view) + => throw new NotImplementedException($"In order to use many-to-many list editors, implement {nameof(GetAllNonRelatedAsync)} on the {GetType()}."); + + /// + /// This method creates a new entity in-memory, and does not affect the database. + /// + /// + /// + /// + public abstract Task NewAsync(IParent? parent, Type? variantType = null); + + /// + /// This method inserts a new entity in the database. + /// + /// The editContext parameter contains the state of the form at the time of saving, allowing to check which property was edited. + /// + /// The relations parameter contains all the relations that are set to this entity. + /// + /// + /// + public abstract Task InsertAsync(IEditContext editContext); + + /// + /// This method updates an existing entity in the database. /// - /// If TEntity == TQueryEntity, use BaseRepository + /// The editContext parameter contains the state of the form at the time of saving, allowing to check which property was edited. + /// + /// The relations parameter contains all the relations that are set to this entity. + /// + /// + /// + public abstract Task UpdateAsync(IEditContext editContext); + + /// + /// This method deletes an existing entity in the database. + /// + /// + /// + /// + public abstract Task DeleteAsync(string id, IParent? parent); + + /// + /// This methods adds an related entity to the entity that corresponds with the given id. + /// This method is used when an new many-to-many relation between two entities is made. + /// + /// + /// + /// + public virtual Task AddAsync(IRelated related, string id) + => throw new NotImplementedException($"In order to use many-to-many list editors, implement {nameof(AddAsync)} on the {GetType()}."); + + /// + /// This methods removes an related entity from the entity that corresponds with the given id. + /// This method is used when a many-to-many relation between two entities is removed. /// - /// Type of the entity used in the views - /// Type of the entity in the backing store - public abstract class BaseMappedRepository : IRepository - where TEntity : class, IEntity - where TDatabaseEntity : class - { - /// - /// This method gets an entity belonging to the given id and parent(s). - /// - /// - /// - /// - public abstract Task GetByIdAsync(string id, IParent? parent); - - /// - /// This method gets all entities belonging to the given parent(s) and query instructions (paging / search). - /// - /// This query is based on the TDatabaseEntity, and not TEntity to allow for mapping. - /// - /// - /// - /// - public abstract Task> GetAllAsync(IParent? parent, IView view); - - /// - /// This method gets all entities that are related to the given entity and query instruction (paging / search). - /// - /// This query is based on the TDatabaseEntity, and not TEntity to allow for mapping. - /// - /// - /// - /// - public virtual Task?> GetAllRelatedAsync(IRelated related, IView view) - => throw new NotImplementedException($"In order to use many-to-many list editors, implement {nameof(GetAllRelatedAsync)} on the {GetType()}."); - - /// - /// This method gets all entities that match the given query instruction (paging / search) but are not related to the given entity. - /// - /// This query is based on the TDatabaseEntity, and not TEntity to allow for mapping. - /// - /// - /// - /// - public virtual Task?> GetAllNonRelatedAsync(IRelated related, IView view) - => throw new NotImplementedException($"In order to use many-to-many list editors, implement {nameof(GetAllNonRelatedAsync)} on the {GetType()}."); - - /// - /// This method creates a new entity in-memory, and does not affect the database. - /// - /// - /// - /// - public abstract Task NewAsync(IParent? parent, Type? variantType = null); - - /// - /// This method inserts a new entity in the database. - /// - /// The editContext parameter contains the state of the form at the time of saving, allowing to check which property was edited. - /// - /// The relations parameter contains all the relations that are set to this entity. - /// - /// - /// - public abstract Task InsertAsync(IEditContext editContext); - - /// - /// This method updates an existing entity in the database. - /// - /// The editContext parameter contains the state of the form at the time of saving, allowing to check which property was edited. - /// - /// The relations parameter contains all the relations that are set to this entity. - /// - /// - /// - public abstract Task UpdateAsync(IEditContext editContext); - - /// - /// This method deletes an existing entity in the database. - /// - /// - /// - /// - public abstract Task DeleteAsync(string id, IParent? parent); - - /// - /// This methods adds an related entity to the entity that corresponds with the given id. - /// This method is used when an new many-to-many relation between two entities is made. - /// - /// - /// - /// - public virtual Task AddAsync(IRelated related, string id) - => throw new NotImplementedException($"In order to use many-to-many list editors, implement {nameof(AddAsync)} on the {GetType()}."); - - /// - /// This methods removes an related entity from the entity that corresponds with the given id. - /// This method is used when a many-to-many relation between two entities is removed. - /// - /// - /// - /// - public virtual Task RemoveAsync(IRelated related, string id) - => throw new NotImplementedException($"In order to use many-to-many list editors, implement {nameof(RemoveAsync)} on the {GetType()}."); - - /// - /// This method is called when an entity is reordered and put in before of the given beforeId. - /// If the beforeId is null, the entity is put in as last. - /// - /// - /// - /// - /// - public virtual Task ReorderAsync(string? beforeId, string id, IParent? parent) - => throw new NotImplementedException($"In order to use reordering in list editors, implement {nameof(ReorderAsync)} on the {GetType()}."); - - async Task IRepository.GetByIdAsync(string id, IViewContext viewContext) - => await GetByIdAsync(id, viewContext.Parent); - - async Task> IRepository.GetAllAsync(IViewContext viewContext, IView view) - => (await GetAllAsync(viewContext.Parent, TypedView.Convert(view))).Cast(); - - async Task> IRepository.GetAllRelatedAsync(IRelatedViewContext viewContext, IView view) - => (await GetAllRelatedAsync(viewContext.Related, TypedView.Convert(view)))?.Cast() ?? Enumerable.Empty(); - - async Task> IRepository.GetAllNonRelatedAsync(IRelatedViewContext viewContext, IView view) - => (await GetAllNonRelatedAsync(viewContext.Related, TypedView.Convert(view)))?.Cast() ?? Enumerable.Empty(); - - async Task IRepository.NewAsync(IViewContext viewContext, Type? variantType) - => await NewAsync(viewContext.Parent, variantType); - - async Task IRepository.InsertAsync(IEditContext editContext) - => await InsertAsync((IEditContext)editContext); - - async Task IRepository.UpdateAsync(IEditContext editContext) - => await UpdateAsync((IEditContext)editContext); - - async Task IRepository.DeleteAsync(string id, IViewContext viewContext) - => await DeleteAsync(id, viewContext.Parent); - - async Task IRepository.AddAsync(IRelatedViewContext viewContext, string id) - => await AddAsync(viewContext.Related, id); - async Task IRepository.RemoveAsync(IRelatedViewContext viewContext, string id) - => await RemoveAsync(viewContext.Related, id); - - async Task IRepository.ReorderAsync(string? beforeId, string id, IViewContext viewContext) - => await ReorderAsync(beforeId, id, viewContext.Parent); - } + /// + /// + /// + public virtual Task RemoveAsync(IRelated related, string id) + => throw new NotImplementedException($"In order to use many-to-many list editors, implement {nameof(RemoveAsync)} on the {GetType()}."); + + /// + /// This method is called when an entity is reordered and put in before of the given beforeId. + /// If the beforeId is null, the entity is put in as last. + /// + /// + /// + /// + /// + public virtual Task ReorderAsync(string? beforeId, string id, IParent? parent) + => throw new NotImplementedException($"In order to use reordering in list editors, implement {nameof(ReorderAsync)} on the {GetType()}."); + + async Task IRepository.GetByIdAsync(string id, IViewContext viewContext) + => await GetByIdAsync(id, viewContext.Parent); + + async Task> IRepository.GetAllAsync(IViewContext viewContext, IView view) + => (await GetAllAsync(viewContext.Parent, TypedView.Convert(view))).Cast(); + + async Task> IRepository.GetAllRelatedAsync(IRelatedViewContext viewContext, IView view) + => (await GetAllRelatedAsync(viewContext.Related, TypedView.Convert(view)))?.Cast() ?? Enumerable.Empty(); + + async Task> IRepository.GetAllNonRelatedAsync(IRelatedViewContext viewContext, IView view) + => (await GetAllNonRelatedAsync(viewContext.Related, TypedView.Convert(view)))?.Cast() ?? Enumerable.Empty(); + + async Task IRepository.NewAsync(IViewContext viewContext, Type? variantType) + => await NewAsync(viewContext.Parent, variantType); + + async Task IRepository.InsertAsync(IEditContext editContext) + => await InsertAsync((IEditContext)editContext); + + async Task IRepository.UpdateAsync(IEditContext editContext) + => await UpdateAsync((IEditContext)editContext); + + async Task IRepository.DeleteAsync(string id, IViewContext viewContext) + => await DeleteAsync(id, viewContext.Parent); + + async Task IRepository.AddAsync(IRelatedViewContext viewContext, string id) + => await AddAsync(viewContext.Related, id); + async Task IRepository.RemoveAsync(IRelatedViewContext viewContext, string id) + => await RemoveAsync(viewContext.Related, id); + + async Task IRepository.ReorderAsync(string? beforeId, string id, IViewContext viewContext) + => await ReorderAsync(beforeId, id, viewContext.Parent); } diff --git a/src/RapidCMS.Core/Repositories/BaseRepository.cs b/src/RapidCMS.Core/Repositories/BaseRepository.cs index 0c963add..8894b25d 100644 --- a/src/RapidCMS.Core/Repositories/BaseRepository.cs +++ b/src/RapidCMS.Core/Repositories/BaseRepository.cs @@ -7,154 +7,153 @@ using RapidCMS.Core.Abstractions.Repositories; using RapidCMS.Core.Models.Data; -namespace RapidCMS.Core.Repositories +namespace RapidCMS.Core.Repositories; + +/// +/// Base class of which most repositories should be derived. +/// +/// When backing store of this repository requires a mapping (the database entity cannot be used directly in the view), use MappedBaseRepository. +/// +/// Type of the entity used in views and in the backing store +public abstract class BaseRepository : IRepository + where TEntity : class, IEntity { /// - /// Base class of which most repositories should be derived. + /// This method gets an entity belonging to the given id and parent(s). + /// + /// + /// + /// + public abstract Task GetByIdAsync(string id, IParent? parent); + + /// + /// This method gets all entities belonging to the given parent(s) and query instructions (paging / search). + /// + /// + /// + /// + public abstract Task> GetAllAsync(IParent? parent, IView view); + + /// + /// This method gets all entities that are related to the given entity and query instruction (paging / search). + /// + /// + /// + /// + public virtual Task?> GetAllRelatedAsync(IRelated related, IView view) + => throw new NotImplementedException($"In order to use many-to-many list editors, implement {nameof(GetAllRelatedAsync)} on the {GetType()}."); + + /// + /// This method gets all entities that match the given query instruction (paging / search) but are not related to the given entity. + /// + /// + /// + /// + public virtual Task?> GetAllNonRelatedAsync(IRelated related, IView view) + => throw new NotImplementedException($"In order to use many-to-many list editors, implement {nameof(GetAllNonRelatedAsync)} on the {GetType()}."); + + /// + /// This method creates a new entity in-memory, and does not affect the database. + /// + /// This method is used frequently to create entities for use in Resource Based authorization. This authorization + /// is based on concrete objects and this method is used to create those concrete objects. This method must therefore + /// always be implemented, even if the repository does not support saving new entities. + /// + /// + /// + /// + public abstract Task NewAsync(IParent? parent, Type? variantType = null); + + /// + /// This method inserts a new entity in the database. + /// + /// The editContext parameter contains the state of the form at the time of saving, allowing to check which property was edited. + /// + /// The relations parameter contains all the relations that are set to this entity. + /// + /// + /// + public abstract Task InsertAsync(IEditContext editContext); + + /// + /// This method updates an existing entity in the database. + /// + /// The editContext parameter contains the state of the form at the time of saving, allowing to check which property was edited. /// - /// When backing store of this repository requires a mapping (the database entity cannot be used directly in the view), use MappedBaseRepository. + /// The relations parameter contains all the relations that are set to this entity. /// - /// Type of the entity used in views and in the backing store - public abstract class BaseRepository : IRepository - where TEntity : class, IEntity - { - /// - /// This method gets an entity belonging to the given id and parent(s). - /// - /// - /// - /// - public abstract Task GetByIdAsync(string id, IParent? parent); - - /// - /// This method gets all entities belonging to the given parent(s) and query instructions (paging / search). - /// - /// - /// - /// - public abstract Task> GetAllAsync(IParent? parent, IView view); - - /// - /// This method gets all entities that are related to the given entity and query instruction (paging / search). - /// - /// - /// - /// - public virtual Task?> GetAllRelatedAsync(IRelated related, IView view) - => throw new NotImplementedException($"In order to use many-to-many list editors, implement {nameof(GetAllRelatedAsync)} on the {GetType()}."); - - /// - /// This method gets all entities that match the given query instruction (paging / search) but are not related to the given entity. - /// - /// - /// - /// - public virtual Task?> GetAllNonRelatedAsync(IRelated related, IView view) - => throw new NotImplementedException($"In order to use many-to-many list editors, implement {nameof(GetAllNonRelatedAsync)} on the {GetType()}."); - - /// - /// This method creates a new entity in-memory, and does not affect the database. - /// - /// This method is used frequently to create entities for use in Resource Based authorization. This authorization - /// is based on concrete objects and this method is used to create those concrete objects. This method must therefore - /// always be implemented, even if the repository does not support saving new entities. - /// - /// - /// - /// - public abstract Task NewAsync(IParent? parent, Type? variantType = null); - - /// - /// This method inserts a new entity in the database. - /// - /// The editContext parameter contains the state of the form at the time of saving, allowing to check which property was edited. - /// - /// The relations parameter contains all the relations that are set to this entity. - /// - /// - /// - public abstract Task InsertAsync(IEditContext editContext); - - /// - /// This method updates an existing entity in the database. - /// - /// The editContext parameter contains the state of the form at the time of saving, allowing to check which property was edited. - /// - /// The relations parameter contains all the relations that are set to this entity. - /// - /// - /// - public abstract Task UpdateAsync(IEditContext editContext); - - /// - /// This method deletes an existing entity in the database. - /// - /// - /// - /// - public abstract Task DeleteAsync(string id, IParent? parent); - - /// - /// This methods adds an related entity to the entity that corresponds with the given id. - /// This method is used when an new many-to-many relation between two entities is made. - /// - /// - /// - /// - public virtual Task AddAsync(IRelated related, string id) - => throw new NotImplementedException($"In order to use many-to-many list editors, implement {nameof(AddAsync)} on the {GetType()}."); - - /// - /// This methods removes an related entity from the entity that corresponds with the given id. - /// This method is used when a many-to-many relation between two entities is removed. - /// - /// - /// - /// - public virtual Task RemoveAsync(IRelated related, string id) - => throw new NotImplementedException($"In order to use many-to-many list editors, implement {nameof(RemoveAsync)} on the {GetType()}."); - - /// - /// This method is called when an entity is reordered and put in before of the given beforeId. - /// If the beforeId is null, the entity is put in as last. - /// - /// - /// - /// - /// - public virtual Task ReorderAsync(string? beforeId, string id, IParent? parent) - => throw new NotImplementedException($"In order to use reordering in list editors, implement {nameof(ReorderAsync)} on the {GetType()}."); - - async Task IRepository.GetByIdAsync(string id, IViewContext viewContext) - => await GetByIdAsync(id, viewContext.Parent); - - async Task> IRepository.GetAllAsync(IViewContext viewContext, IView view) - => (await GetAllAsync(viewContext.Parent, TypedView.Convert(view))).Cast(); - - async Task> IRepository.GetAllRelatedAsync(IRelatedViewContext viewContext, IView view) - => (await GetAllRelatedAsync(viewContext.Related, TypedView.Convert(view)))?.Cast() ?? Enumerable.Empty(); - - async Task> IRepository.GetAllNonRelatedAsync(IRelatedViewContext viewContext, IView view) - => (await GetAllNonRelatedAsync(viewContext.Related, TypedView.Convert(view)))?.Cast() ?? Enumerable.Empty(); - - async Task IRepository.NewAsync(IViewContext viewContext, Type? variantType) - => await NewAsync(viewContext.Parent, variantType); - - async Task IRepository.InsertAsync(IEditContext editContext) - => await InsertAsync((IEditContext)editContext); - - async Task IRepository.UpdateAsync(IEditContext editContext) - => await UpdateAsync((IEditContext)editContext); - - async Task IRepository.DeleteAsync(string id, IViewContext viewContext) - => await DeleteAsync(id, viewContext.Parent); - - async Task IRepository.AddAsync(IRelatedViewContext viewContext, string id) - => await AddAsync(viewContext.Related, id); - async Task IRepository.RemoveAsync(IRelatedViewContext viewContext, string id) - => await RemoveAsync(viewContext.Related, id); - - async Task IRepository.ReorderAsync(string? beforeId, string id, IViewContext viewContext) - => await ReorderAsync(beforeId, id, viewContext.Parent); - } + /// + /// + public abstract Task UpdateAsync(IEditContext editContext); + + /// + /// This method deletes an existing entity in the database. + /// + /// + /// + /// + public abstract Task DeleteAsync(string id, IParent? parent); + + /// + /// This methods adds an related entity to the entity that corresponds with the given id. + /// This method is used when an new many-to-many relation between two entities is made. + /// + /// + /// + /// + public virtual Task AddAsync(IRelated related, string id) + => throw new NotImplementedException($"In order to use many-to-many list editors, implement {nameof(AddAsync)} on the {GetType()}."); + + /// + /// This methods removes an related entity from the entity that corresponds with the given id. + /// This method is used when a many-to-many relation between two entities is removed. + /// + /// + /// + /// + public virtual Task RemoveAsync(IRelated related, string id) + => throw new NotImplementedException($"In order to use many-to-many list editors, implement {nameof(RemoveAsync)} on the {GetType()}."); + + /// + /// This method is called when an entity is reordered and put in before of the given beforeId. + /// If the beforeId is null, the entity is put in as last. + /// + /// + /// + /// + /// + public virtual Task ReorderAsync(string? beforeId, string id, IParent? parent) + => throw new NotImplementedException($"In order to use reordering in list editors, implement {nameof(ReorderAsync)} on the {GetType()}."); + + async Task IRepository.GetByIdAsync(string id, IViewContext viewContext) + => await GetByIdAsync(id, viewContext.Parent); + + async Task> IRepository.GetAllAsync(IViewContext viewContext, IView view) + => (await GetAllAsync(viewContext.Parent, TypedView.Convert(view))).Cast(); + + async Task> IRepository.GetAllRelatedAsync(IRelatedViewContext viewContext, IView view) + => (await GetAllRelatedAsync(viewContext.Related, TypedView.Convert(view)))?.Cast() ?? Enumerable.Empty(); + + async Task> IRepository.GetAllNonRelatedAsync(IRelatedViewContext viewContext, IView view) + => (await GetAllNonRelatedAsync(viewContext.Related, TypedView.Convert(view)))?.Cast() ?? Enumerable.Empty(); + + async Task IRepository.NewAsync(IViewContext viewContext, Type? variantType) + => await NewAsync(viewContext.Parent, variantType); + + async Task IRepository.InsertAsync(IEditContext editContext) + => await InsertAsync((IEditContext)editContext); + + async Task IRepository.UpdateAsync(IEditContext editContext) + => await UpdateAsync((IEditContext)editContext); + + async Task IRepository.DeleteAsync(string id, IViewContext viewContext) + => await DeleteAsync(id, viewContext.Parent); + + async Task IRepository.AddAsync(IRelatedViewContext viewContext, string id) + => await AddAsync(viewContext.Related, id); + async Task IRepository.RemoveAsync(IRelatedViewContext viewContext, string id) + => await RemoveAsync(viewContext.Related, id); + + async Task IRepository.ReorderAsync(string? beforeId, string id, IViewContext viewContext) + => await ReorderAsync(beforeId, id, viewContext.Parent); } diff --git a/src/RapidCMS.Core/Resolvers/Buttons/ButtonActionHandlerResolver.cs b/src/RapidCMS.Core/Resolvers/Buttons/ButtonActionHandlerResolver.cs index a6c8e99a..479b2479 100644 --- a/src/RapidCMS.Core/Resolvers/Buttons/ButtonActionHandlerResolver.cs +++ b/src/RapidCMS.Core/Resolvers/Buttons/ButtonActionHandlerResolver.cs @@ -4,20 +4,19 @@ using RapidCMS.Core.Extensions; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Resolvers.Buttons +namespace RapidCMS.Core.Resolvers.Buttons; + +internal class ButtonActionHandlerResolver : IButtonActionHandlerResolver { - internal class ButtonActionHandlerResolver : IButtonActionHandlerResolver - { - private readonly IServiceProvider _serviceProvider; + private readonly IServiceProvider _serviceProvider; - public ButtonActionHandlerResolver(IServiceProvider serviceProvider) - { - _serviceProvider = serviceProvider; - } + public ButtonActionHandlerResolver(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } - public IButtonActionHandler GetButtonActionHandler(ButtonSetup button) - { - return _serviceProvider.GetService(button.ButtonHandlerType); - } + public IButtonActionHandler GetButtonActionHandler(ButtonSetup button) + { + return _serviceProvider.GetService(button.ButtonHandlerType); } } diff --git a/src/RapidCMS.Core/Resolvers/Convention/ConventionBasedListConfigResolver.cs b/src/RapidCMS.Core/Resolvers/Convention/ConventionBasedListConfigResolver.cs index 0d965f50..ba61813d 100644 --- a/src/RapidCMS.Core/Resolvers/Convention/ConventionBasedListConfigResolver.cs +++ b/src/RapidCMS.Core/Resolvers/Convention/ConventionBasedListConfigResolver.cs @@ -8,93 +8,92 @@ using RapidCMS.Core.Models.Config; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Resolvers.Convention +namespace RapidCMS.Core.Resolvers.Convention; + +internal class ConventionBasedListConfigResolver : IConventionBasedResolver { - internal class ConventionBasedListConfigResolver : IConventionBasedResolver + private readonly IFieldConfigResolver _fieldConfigResolver; + private readonly ILanguageResolver _languageResolver; + + public ConventionBasedListConfigResolver( + IFieldConfigResolver fieldConfigResolver, + ILanguageResolver languageResolver) { - private readonly IFieldConfigResolver _fieldConfigResolver; - private readonly ILanguageResolver _languageResolver; + _fieldConfigResolver = fieldConfigResolver; + _languageResolver = languageResolver; + } - public ConventionBasedListConfigResolver( - IFieldConfigResolver fieldConfigResolver, - ILanguageResolver languageResolver) + public Task ResolveByConventionAsync(Type subject, Features features, CollectionSetup? collection) + { + var listButtons = new List(); + + if (features.HasFlag(Features.CanEdit) || features.HasFlag(Features.CanGoToEdit)) { - _fieldConfigResolver = fieldConfigResolver; - _languageResolver = languageResolver; + listButtons.Add(new DefaultButtonConfig + { + ButtonType = DefaultButtonType.New, + Label = !(collection?.SubEntityVariants?.Any() ?? false) ? null : _languageResolver.ResolveText("New {0}") + }); + listButtons.Add(new DefaultButtonConfig + { + ButtonType = DefaultButtonType.Return + }); + listButtons.Add(new DefaultButtonConfig + { + ButtonType = DefaultButtonType.SaveExisting, + Label = _languageResolver.ResolveText("Update all") + }); + }; + var paneButtons = new List(); + if (features.HasFlag(Features.CanGoToView)) + { + paneButtons.Add(new DefaultButtonConfig + { + ButtonType = DefaultButtonType.View + }); } - - public Task ResolveByConventionAsync(Type subject, Features features, CollectionSetup? collection) + if (features.HasFlag(Features.CanGoToEdit)) { - var listButtons = new List(); - - if (features.HasFlag(Features.CanEdit) || features.HasFlag(Features.CanGoToEdit)) + paneButtons.Add(new DefaultButtonConfig { - listButtons.Add(new DefaultButtonConfig - { - ButtonType = DefaultButtonType.New, - Label = !(collection?.SubEntityVariants?.Any() ?? false) ? null : _languageResolver.ResolveText("New {0}") - }); - listButtons.Add(new DefaultButtonConfig - { - ButtonType = DefaultButtonType.Return - }); - listButtons.Add(new DefaultButtonConfig - { - ButtonType = DefaultButtonType.SaveExisting, - Label = _languageResolver.ResolveText("Update all") - }); - }; - var paneButtons = new List(); - if (features.HasFlag(Features.CanGoToView)) + ButtonType = DefaultButtonType.Edit + }); + } + if (features.HasFlag(Features.CanEdit)) + { + paneButtons.Add(new DefaultButtonConfig { - paneButtons.Add(new DefaultButtonConfig - { - ButtonType = DefaultButtonType.View - }); - } - if (features.HasFlag(Features.CanGoToEdit)) + ButtonType = DefaultButtonType.SaveExisting + }); + paneButtons.Add(new DefaultButtonConfig { - paneButtons.Add(new DefaultButtonConfig - { - ButtonType = DefaultButtonType.Edit - }); - } - if (features.HasFlag(Features.CanEdit)) + ButtonType = DefaultButtonType.SaveNew + }); + paneButtons.Add(new DefaultButtonConfig { - paneButtons.Add(new DefaultButtonConfig - { - ButtonType = DefaultButtonType.SaveExisting - }); - paneButtons.Add(new DefaultButtonConfig - { - ButtonType = DefaultButtonType.SaveNew - }); - paneButtons.Add(new DefaultButtonConfig - { - ButtonType = DefaultButtonType.Delete - }); - } + ButtonType = DefaultButtonType.Delete + }); + } - var result = new ListConfig(subject) + var result = new ListConfig(subject) + { + PageSize = 25, + Buttons = listButtons, + ListEditorType = features.HasFlag(Features.IsBlockList) ? ListType.Block : ListType.Table, + Panes = new List { - PageSize = 25, - Buttons = listButtons, - ListEditorType = features.HasFlag(Features.IsBlockList) ? ListType.Block : ListType.Table, - Panes = new List + new PaneConfig(subject) { - new PaneConfig(subject) - { - Buttons = paneButtons, - FieldIndex = 1, - Fields = _fieldConfigResolver.GetFields(subject, features).ToList(), - VariantType = subject - } - }, - ReorderingAllowed = false, - SearchBarVisible = true - }; + Buttons = paneButtons, + FieldIndex = 1, + Fields = _fieldConfigResolver.GetFields(subject, features).ToList(), + VariantType = subject + } + }, + ReorderingAllowed = false, + SearchBarVisible = true + }; - return Task.FromResult(result); - } + return Task.FromResult(result); } } diff --git a/src/RapidCMS.Core/Resolvers/Convention/ConventionBasedNodeConfigResolver.cs b/src/RapidCMS.Core/Resolvers/Convention/ConventionBasedNodeConfigResolver.cs index 102cf431..ae05f7bf 100644 --- a/src/RapidCMS.Core/Resolvers/Convention/ConventionBasedNodeConfigResolver.cs +++ b/src/RapidCMS.Core/Resolvers/Convention/ConventionBasedNodeConfigResolver.cs @@ -7,73 +7,72 @@ using RapidCMS.Core.Models.Config; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Resolvers.Convention +namespace RapidCMS.Core.Resolvers.Convention; + +internal class ConventionBasedNodeConfigResolver : IConventionBasedResolver { - internal class ConventionBasedNodeConfigResolver : IConventionBasedResolver + private readonly IFieldConfigResolver _fieldConfigResolver; + + public ConventionBasedNodeConfigResolver(IFieldConfigResolver fieldConfigResolver) { - private readonly IFieldConfigResolver _fieldConfigResolver; + _fieldConfigResolver = fieldConfigResolver; + } - public ConventionBasedNodeConfigResolver(IFieldConfigResolver fieldConfigResolver) - { - _fieldConfigResolver = fieldConfigResolver; - } + public Task ResolveByConventionAsync(Type subject, Features features, CollectionSetup? collection) + { + var result = new NodeConfig(subject); - public Task ResolveByConventionAsync(Type subject, Features features, CollectionSetup? collection) + if (features.HasFlag(Features.CanView) || features.HasFlag(Features.CanEdit)) { - var result = new NodeConfig(subject); + result.Buttons.Add(new DefaultButtonConfig + { + ButtonType = DefaultButtonType.Up + }); - if (features.HasFlag(Features.CanView) || features.HasFlag(Features.CanEdit)) + result.Panes = new List { - result.Buttons.Add(new DefaultButtonConfig + new PaneConfig(subject) { - ButtonType = DefaultButtonType.Up - }); + FieldIndex = 1, + Fields = _fieldConfigResolver.GetFields(subject, features).ToList(), + VariantType = subject + } + }; + } - result.Panes = new List + if (features.HasFlag(Features.CanEdit)) + { + result.Buttons.AddRange(new[] { + new DefaultButtonConfig { - new PaneConfig(subject) - { - FieldIndex = 1, - Fields = _fieldConfigResolver.GetFields(subject, features).ToList(), - VariantType = subject - } - }; - } + ButtonType = DefaultButtonType.SaveExisting + }, + new DefaultButtonConfig + { + ButtonType = DefaultButtonType.SaveNew + }, + new DefaultButtonConfig + { + ButtonType = DefaultButtonType.Delete + } + }); + } - if (features.HasFlag(Features.CanEdit)) + if (collection?.Collections.Any() ?? false) + { + foreach (var subCollection in collection.Collections) { - result.Buttons.AddRange(new[] { - new DefaultButtonConfig - { - ButtonType = DefaultButtonType.SaveExisting - }, - new DefaultButtonConfig - { - ButtonType = DefaultButtonType.SaveNew - }, - new DefaultButtonConfig + result.Panes.Add(new PaneConfig(subject) + { + IsVisible = (entity, state) => state == EntityState.IsExisting, + SubCollectionLists = new List { - ButtonType = DefaultButtonType.Delete + new ReferencedCollectionListConfig(subCollection.Alias) } }); } - - if (collection?.Collections.Any() ?? false) - { - foreach (var subCollection in collection.Collections) - { - result.Panes.Add(new PaneConfig(subject) - { - IsVisible = (entity, state) => state == EntityState.IsExisting, - SubCollectionLists = new List - { - new ReferencedCollectionListConfig(subCollection.Alias) - } - }); - } - } - - return Task.FromResult(result); } + + return Task.FromResult(result); } } diff --git a/src/RapidCMS.Core/Resolvers/Convention/ConventionBasedPaneSetupResolver.cs b/src/RapidCMS.Core/Resolvers/Convention/ConventionBasedPaneSetupResolver.cs index 4a7ea0ab..24ea8f12 100644 --- a/src/RapidCMS.Core/Resolvers/Convention/ConventionBasedPaneSetupResolver.cs +++ b/src/RapidCMS.Core/Resolvers/Convention/ConventionBasedPaneSetupResolver.cs @@ -5,27 +5,26 @@ using RapidCMS.Core.Models.Config; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Resolvers.Convention +namespace RapidCMS.Core.Resolvers.Convention; + +internal class ConventionBasedNodeSetupResolver : IConventionBasedResolver { - internal class ConventionBasedNodeSetupResolver : IConventionBasedResolver - { - private readonly IConventionBasedResolver _nodeResolver; - private readonly ISetupResolver _nodeSetupResolver; + private readonly IConventionBasedResolver _nodeResolver; + private readonly ISetupResolver _nodeSetupResolver; - public ConventionBasedNodeSetupResolver( - IConventionBasedResolver nodeResolver, - ISetupResolver nodeSetupResolver) - { - _nodeResolver = nodeResolver; - _nodeSetupResolver = nodeSetupResolver; - } + public ConventionBasedNodeSetupResolver( + IConventionBasedResolver nodeResolver, + ISetupResolver nodeSetupResolver) + { + _nodeResolver = nodeResolver; + _nodeSetupResolver = nodeSetupResolver; + } - public async Task ResolveByConventionAsync(Type subject, Features features, CollectionSetup? collection) - { - var node = await _nodeResolver.ResolveByConventionAsync(subject, features, collection); - var pane = await _nodeSetupResolver.ResolveSetupAsync(node, collection); + public async Task ResolveByConventionAsync(Type subject, Features features, CollectionSetup? collection) + { + var node = await _nodeResolver.ResolveByConventionAsync(subject, features, collection); + var pane = await _nodeSetupResolver.ResolveSetupAsync(node, collection); - return pane.Setup; - } + return pane.Setup; } } diff --git a/src/RapidCMS.Core/Resolvers/Convention/FieldConfigResolver.cs b/src/RapidCMS.Core/Resolvers/Convention/FieldConfigResolver.cs index 18a69f2c..2c75ad2a 100644 --- a/src/RapidCMS.Core/Resolvers/Convention/FieldConfigResolver.cs +++ b/src/RapidCMS.Core/Resolvers/Convention/FieldConfigResolver.cs @@ -11,73 +11,72 @@ using RapidCMS.Core.Models.Config; using RapidCMS.Core.Providers; -namespace RapidCMS.Core.Resolvers.Convention +namespace RapidCMS.Core.Resolvers.Convention; + +internal class FieldConfigResolver : IFieldConfigResolver { - internal class FieldConfigResolver : IFieldConfigResolver + public IEnumerable GetFields(Type subject, Features features) { - public IEnumerable GetFields(Type subject, Features features) - { - var properties = subject.GetProperties(); - return properties - .Select(property => + var properties = subject.GetProperties(); + return properties + .Select(property => + { + var fieldAttribute = property.GetCustomAttribute(); + if (fieldAttribute != null) { - var fieldAttribute = property.GetCustomAttribute(); - if (fieldAttribute != null) - { - var useListName = !features.HasFlag(Features.CanEdit) || features.HasFlag(Features.CanGoToEdit); - var useName = features.HasFlag(Features.CanEdit) && !useListName; + var useListName = !features.HasFlag(Features.CanEdit) || features.HasFlag(Features.CanGoToEdit); + var useName = features.HasFlag(Features.CanEdit) && !useListName; - if ((useName && !string.IsNullOrEmpty(fieldAttribute.Name)) || - (useListName && !string.IsNullOrEmpty(fieldAttribute.ListName))) - { - return (property, fieldAttribute); - } + if ((useName && !string.IsNullOrEmpty(fieldAttribute.Name)) || + (useListName && !string.IsNullOrEmpty(fieldAttribute.ListName))) + { + return (property, fieldAttribute); } + } - return default; - }) - .Where(x => x != default) - .Select((data, index) => + return default; + }) + .Where(x => x != default) + .Select((data, index) => + { + if (data.fieldAttribute.EditorType?.IsSameTypeOrDerivedFrom(typeof(ComponentBase)) == false) { - if (data.fieldAttribute.EditorType?.IsSameTypeOrDerivedFrom(typeof(ComponentBase)) == false) - { - throw new InvalidOperationException("ResourceType of [Display] must be a valid BaseEditor derived component."); - } + throw new InvalidOperationException("ResourceType of [Display] must be a valid BaseEditor derived component."); + } - var propertyMetadata = PropertyMetadataHelper.GetPropertyMetadata(subject, data.property); + var propertyMetadata = PropertyMetadataHelper.GetPropertyMetadata(subject, data.property); - var propertyType = data.property.PropertyType.IsGenericType && data.property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>) - ? Nullable.GetUnderlyingType(data.property.PropertyType)! - : data.property.PropertyType; + var propertyType = data.property.PropertyType.IsGenericType && data.property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>) + ? Nullable.GetUnderlyingType(data.property.PropertyType)! + : data.property.PropertyType; - var displayType = features.HasFlag(Features.CanEdit) ? DisplayType.None : DisplayType.Label; - var editorType = !features.HasFlag(Features.CanEdit) ? EditorType.None - : data.fieldAttribute.EditorType != null ? EditorType.Custom - : EditorTypeHelper.TryFindDefaultEditorType(propertyType); - var customType = editorType == EditorType.Custom ? data.fieldAttribute.EditorType : null; + var displayType = features.HasFlag(Features.CanEdit) ? DisplayType.None : DisplayType.Label; + var editorType = !features.HasFlag(Features.CanEdit) ? EditorType.None + : data.fieldAttribute.EditorType != null ? EditorType.Custom + : EditorTypeHelper.TryFindDefaultEditorType(propertyType); + var customType = editorType == EditorType.Custom ? data.fieldAttribute.EditorType : null; - var relationConfig = editorType != EditorType.Select ? null : - new DataProviderRelationConfig(typeof(EnumDataProvider<>).MakeGenericType(propertyType), default); + var relationConfig = editorType != EditorType.Select ? null : + new DataProviderRelationConfig(typeof(EnumDataProvider<>).MakeGenericType(propertyType), default); - return new FieldConfig - { - Description = features.HasFlag(Features.CanEdit) ? data.fieldAttribute.Description : default, - DefaultOrder = data.fieldAttribute.OrderByType, - CustomType = customType, - DisplayType = displayType, - EditorType = editorType, - Index = data.fieldAttribute.Index, - IsDisabled = (object x, EntityState y) => false, - IsVisible = (object x, EntityState y) => true, - Name = !features.HasFlag(Features.CanEdit) || !features.HasFlag(Features.CanGoToEdit) - ? data.fieldAttribute.ListName - : data.fieldAttribute.Name, - OrderByExpression = data.fieldAttribute.OrderByType == OrderByType.Disabled ? null : propertyMetadata, - Placeholder = data.fieldAttribute.Placeholder, - Property = propertyMetadata, - Relation = relationConfig - }; - }); - } + return new FieldConfig + { + Description = features.HasFlag(Features.CanEdit) ? data.fieldAttribute.Description : default, + DefaultOrder = data.fieldAttribute.OrderByType, + CustomType = customType, + DisplayType = displayType, + EditorType = editorType, + Index = data.fieldAttribute.Index, + IsDisabled = (object x, EntityState y) => false, + IsVisible = (object x, EntityState y) => true, + Name = !features.HasFlag(Features.CanEdit) || !features.HasFlag(Features.CanGoToEdit) + ? data.fieldAttribute.ListName + : data.fieldAttribute.Name, + OrderByExpression = data.fieldAttribute.OrderByType == OrderByType.Disabled ? null : propertyMetadata, + Placeholder = data.fieldAttribute.Placeholder, + Property = propertyMetadata, + Relation = relationConfig + }; + }); } } diff --git a/src/RapidCMS.Core/Resolvers/Data/ApiDataViewResolver.cs b/src/RapidCMS.Core/Resolvers/Data/ApiDataViewResolver.cs index 2dad469e..72d33c2a 100644 --- a/src/RapidCMS.Core/Resolvers/Data/ApiDataViewResolver.cs +++ b/src/RapidCMS.Core/Resolvers/Data/ApiDataViewResolver.cs @@ -8,47 +8,46 @@ using RapidCMS.Core.Abstractions.Resolvers; using RapidCMS.Core.Extensions; -namespace RapidCMS.Core.Resolvers.Data +namespace RapidCMS.Core.Resolvers.Data; + +internal class ApiDataViewResolver : IDataViewResolver { - internal class ApiDataViewResolver : IDataViewResolver + private readonly IReadOnlyDictionary _dataViewTypes; + private readonly IServiceProvider _serviceProvider; + + public ApiDataViewResolver( + IApiConfig apiConfig, + IServiceProvider serviceProvider) { - private readonly IReadOnlyDictionary _dataViewTypes; - private readonly IServiceProvider _serviceProvider; + _dataViewTypes = apiConfig.DataViews.ToDictionary(dataView => dataView.Alias, dataView => dataView.DataViewBuilder); + _serviceProvider = serviceProvider; + } - public ApiDataViewResolver( - IApiConfig apiConfig, - IServiceProvider serviceProvider) + public async Task ApplyDataViewToViewAsync(IView view) + { + if (string.IsNullOrEmpty(view.CollectionAlias)) { - _dataViewTypes = apiConfig.DataViews.ToDictionary(dataView => dataView.Alias, dataView => dataView.DataViewBuilder); - _serviceProvider = serviceProvider; + throw new ArgumentNullException($"{nameof(view)}.{nameof(view.CollectionAlias)}"); } + + var dataViews = await GetDataViewsAsync(view.CollectionAlias); + var dataView = dataViews.FirstOrDefault(x => x.Id == view.ActiveTab) + ?? dataViews.FirstOrDefault(); - public async Task ApplyDataViewToViewAsync(IView view) + if (dataView != null) { - if (string.IsNullOrEmpty(view.CollectionAlias)) - { - throw new ArgumentNullException($"{nameof(view)}.{nameof(view.CollectionAlias)}"); - } - - var dataViews = await GetDataViewsAsync(view.CollectionAlias); - var dataView = dataViews.FirstOrDefault(x => x.Id == view.ActiveTab) - ?? dataViews.FirstOrDefault(); - - if (dataView != null) - { - view.SetDataView(dataView); - } + view.SetDataView(dataView); } + } - public Task> GetDataViewsAsync(string collectionAlias) + public Task> GetDataViewsAsync(string collectionAlias) + { + if (!_dataViewTypes.TryGetValue(collectionAlias, out var dataView)) { - if (!_dataViewTypes.TryGetValue(collectionAlias, out var dataView)) - { - return Task.FromResult(Enumerable.Empty()); - } - - var builder = _serviceProvider.GetService(dataView); - return builder.GetDataViewsAsync(); + return Task.FromResult(Enumerable.Empty()); } + + var builder = _serviceProvider.GetService(dataView); + return builder.GetDataViewsAsync(); } } diff --git a/src/RapidCMS.Core/Resolvers/Data/DataProviderResolver.cs b/src/RapidCMS.Core/Resolvers/Data/DataProviderResolver.cs index 920c67e2..0946a3eb 100644 --- a/src/RapidCMS.Core/Resolvers/Data/DataProviderResolver.cs +++ b/src/RapidCMS.Core/Resolvers/Data/DataProviderResolver.cs @@ -12,111 +12,110 @@ using RapidCMS.Core.Models.Setup; using RapidCMS.Core.Providers; -namespace RapidCMS.Core.Resolvers.Data +namespace RapidCMS.Core.Resolvers.Data; + +internal class DataProviderResolver : IDataProviderResolver { - internal class DataProviderResolver : IDataProviderResolver + private readonly ISetupResolver _collectionSetupResolver; + private readonly IConcurrencyService _concurrencyService; + private readonly IRepositoryResolver _repositoryResolver; + private readonly IMediator _mediator; + private readonly IServiceProvider _serviceProvider; + + public DataProviderResolver( + ISetupResolver collectionSetupResolver, + IConcurrencyService concurrencyService, + IRepositoryResolver repositoryResolver, + IMediator mediator, + IServiceProvider serviceProvider) { - private readonly ISetupResolver _collectionSetupResolver; - private readonly IConcurrencyService _concurrencyService; - private readonly IRepositoryResolver _repositoryResolver; - private readonly IMediator _mediator; - private readonly IServiceProvider _serviceProvider; - - public DataProviderResolver( - ISetupResolver collectionSetupResolver, - IConcurrencyService concurrencyService, - IRepositoryResolver repositoryResolver, - IMediator mediator, - IServiceProvider serviceProvider) + _collectionSetupResolver = collectionSetupResolver; + _concurrencyService = concurrencyService; + _repositoryResolver = repositoryResolver; + _mediator = mediator; + _serviceProvider = serviceProvider; + } + + public async Task GetDataProviderAsync(FieldSetup field) + { + if (!(field is PropertyFieldSetup propertyField && propertyField.Relation != null)) { - _collectionSetupResolver = collectionSetupResolver; - _concurrencyService = concurrencyService; - _repositoryResolver = repositoryResolver; - _mediator = mediator; - _serviceProvider = serviceProvider; + return null; } - public async Task GetDataProviderAsync(FieldSetup field) + switch (propertyField.Relation) { - if (!(field is PropertyFieldSetup propertyField && propertyField.Relation != null)) - { - return null; - } - - switch (propertyField.Relation) - { - case RepositoryRelationSetup collectionRelation: - - var collectionSetup = collectionRelation.CollectionAlias == null - ? default - : await _collectionSetupResolver.ResolveSetupAsync(collectionRelation.CollectionAlias); - - var repo = (collectionRelation.RepositoryAlias != null - ? _repositoryResolver.GetRepository(collectionRelation.RepositoryAlias) - : collectionSetup != null - ? _repositoryResolver.GetRepository(collectionSetup) - : default) - ?? throw new InvalidOperationException($"Field {propertyField.Property!.PropertyName} has incorrectly configure relation, cannot find repository for alias {(collectionRelation.CollectionAlias ?? collectionRelation.RepositoryAlias)}."); - - // TODO: investigate whether this can be moved to Setup to allow for better caching - var idProperty = collectionRelation.IdProperty - ?? collectionSetup?.ElementSetup?.IdProperty - ?? throw new InvalidOperationException($"Field {propertyField.Property!.PropertyName} has incorrect Id property metadata."); - - var displayProperties = collectionRelation.DisplayProperties - ?? collectionSetup?.ElementSetup?.DisplayProperties - ?? throw new InvalidOperationException($"Field {propertyField.Property!.PropertyName} has incorrect display properties metadata."); - - var relatedElementGetter = collectionRelation.RelatedElementsGetter - ?? ((collectionRelation.IsRelationToMany && propertyField.Property != null && propertyField.Property.PropertyType.IsAssignableTo(typeof(IEnumerable))) - ? PropertyMetadataHelper.GetPropertyMetadata, IEnumerable>(x => x.Select(idProperty.Getter)) - : default); - - var provider = new CollectionDataProvider( - repo, - _concurrencyService, - collectionRelation.RepositoryAlias, - collectionRelation.CollectionAlias, - relatedElementGetter, - collectionRelation.EntityAsParent, - collectionRelation.RepositoryParentSelector, - idProperty, - displayProperties, - collectionRelation.RelatedEntityType ?? collectionSetup?.EntityVariant.Type ?? typeof(object), - propertyField.Property!, - _mediator); - - return new FormDataProvider( - propertyField.Property!, - provider); - - case DataProviderRelationSetup dataProviderRelation: - - var dataCollection = _serviceProvider.GetService(dataProviderRelation.DataCollectionType); - if (dataProviderRelation.Configuration != null) - { - dataCollection.Configure(dataProviderRelation.Configuration); - } - - return new FormDataProvider(propertyField.Property!, dataCollection); - - case RelationDataProviderRelationSetup relationDataProviderRelation: - - var relationDataCollection = _serviceProvider.GetService(relationDataProviderRelation.RelationDataCollectionType); - if (relationDataProviderRelation.Configuration != null) - { - relationDataCollection.Configure(relationDataProviderRelation.Configuration); - } - - return new FormDataProvider(propertyField.Property!, relationDataCollection); - - case ConcreteDataProviderRelationSetup concreteDataProvider: - - return new FormDataProvider(propertyField.Property!, concreteDataProvider.DataCollection); - - default: - throw new InvalidOperationException(); - }; - } + case RepositoryRelationSetup collectionRelation: + + var collectionSetup = collectionRelation.CollectionAlias == null + ? default + : await _collectionSetupResolver.ResolveSetupAsync(collectionRelation.CollectionAlias); + + var repo = (collectionRelation.RepositoryAlias != null + ? _repositoryResolver.GetRepository(collectionRelation.RepositoryAlias) + : collectionSetup != null + ? _repositoryResolver.GetRepository(collectionSetup) + : default) + ?? throw new InvalidOperationException($"Field {propertyField.Property!.PropertyName} has incorrectly configure relation, cannot find repository for alias {(collectionRelation.CollectionAlias ?? collectionRelation.RepositoryAlias)}."); + + // TODO: investigate whether this can be moved to Setup to allow for better caching + var idProperty = collectionRelation.IdProperty + ?? collectionSetup?.ElementSetup?.IdProperty + ?? throw new InvalidOperationException($"Field {propertyField.Property!.PropertyName} has incorrect Id property metadata."); + + var displayProperties = collectionRelation.DisplayProperties + ?? collectionSetup?.ElementSetup?.DisplayProperties + ?? throw new InvalidOperationException($"Field {propertyField.Property!.PropertyName} has incorrect display properties metadata."); + + var relatedElementGetter = collectionRelation.RelatedElementsGetter + ?? ((collectionRelation.IsRelationToMany && propertyField.Property != null && propertyField.Property.PropertyType.IsAssignableTo(typeof(IEnumerable))) + ? PropertyMetadataHelper.GetPropertyMetadata, IEnumerable>(x => x.Select(idProperty.Getter)) + : default); + + var provider = new CollectionDataProvider( + repo, + _concurrencyService, + collectionRelation.RepositoryAlias, + collectionRelation.CollectionAlias, + relatedElementGetter, + collectionRelation.EntityAsParent, + collectionRelation.RepositoryParentSelector, + idProperty, + displayProperties, + collectionRelation.RelatedEntityType ?? collectionSetup?.EntityVariant.Type ?? typeof(object), + propertyField.Property!, + _mediator); + + return new FormDataProvider( + propertyField.Property!, + provider); + + case DataProviderRelationSetup dataProviderRelation: + + var dataCollection = _serviceProvider.GetService(dataProviderRelation.DataCollectionType); + if (dataProviderRelation.Configuration != null) + { + dataCollection.Configure(dataProviderRelation.Configuration); + } + + return new FormDataProvider(propertyField.Property!, dataCollection); + + case RelationDataProviderRelationSetup relationDataProviderRelation: + + var relationDataCollection = _serviceProvider.GetService(relationDataProviderRelation.RelationDataCollectionType); + if (relationDataProviderRelation.Configuration != null) + { + relationDataCollection.Configure(relationDataProviderRelation.Configuration); + } + + return new FormDataProvider(propertyField.Property!, relationDataCollection); + + case ConcreteDataProviderRelationSetup concreteDataProvider: + + return new FormDataProvider(propertyField.Property!, concreteDataProvider.DataCollection); + + default: + throw new InvalidOperationException(); + }; } } diff --git a/src/RapidCMS.Core/Resolvers/Data/FormDataViewResolver.cs b/src/RapidCMS.Core/Resolvers/Data/FormDataViewResolver.cs index 3a6d99ec..45259577 100644 --- a/src/RapidCMS.Core/Resolvers/Data/FormDataViewResolver.cs +++ b/src/RapidCMS.Core/Resolvers/Data/FormDataViewResolver.cs @@ -7,60 +7,59 @@ using RapidCMS.Core.Extensions; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Resolvers.Data +namespace RapidCMS.Core.Resolvers.Data; + +internal class FormDataViewResolver : IDataViewResolver { - internal class FormDataViewResolver : IDataViewResolver + private readonly IServiceProvider _serviceProvider; + private readonly ISetupResolver _collectionResolver; + + public FormDataViewResolver( + IServiceProvider serviceProvider, + ISetupResolver collectionResolver) { - private readonly IServiceProvider _serviceProvider; - private readonly ISetupResolver _collectionResolver; + _serviceProvider = serviceProvider; + _collectionResolver = collectionResolver; + } - public FormDataViewResolver( - IServiceProvider serviceProvider, - ISetupResolver collectionResolver) + public async Task ApplyDataViewToViewAsync(IView view) + { + if (string.IsNullOrEmpty(view.CollectionAlias)) { - _serviceProvider = serviceProvider; - _collectionResolver = collectionResolver; + throw new ArgumentNullException($"{nameof(view)}.{nameof(view.CollectionAlias)}"); } - public async Task ApplyDataViewToViewAsync(IView view) - { - if (string.IsNullOrEmpty(view.CollectionAlias)) - { - throw new ArgumentNullException($"{nameof(view)}.{nameof(view.CollectionAlias)}"); - } + var collection = await _collectionResolver.ResolveSetupAsync(view.CollectionAlias); - var collection = await _collectionResolver.ResolveSetupAsync(view.CollectionAlias); + if (collection.DataViewBuilder != null || collection.DataViews?.Count > 0) + { + var dataViews = await GetDataViewsAsync(collection); + var dataView = dataViews.FirstOrDefault(x => x.Id == view.ActiveTab) + ?? dataViews.FirstOrDefault(); - if (collection.DataViewBuilder != null || collection.DataViews?.Count > 0) + if (dataView != null) { - var dataViews = await GetDataViewsAsync(collection); - var dataView = dataViews.FirstOrDefault(x => x.Id == view.ActiveTab) - ?? dataViews.FirstOrDefault(); - - if (dataView != null) - { - view.SetDataView(dataView); - } + view.SetDataView(dataView); } } + } - public async Task> GetDataViewsAsync(string collectionAlias) + public async Task> GetDataViewsAsync(string collectionAlias) + { + var collection = await _collectionResolver.ResolveSetupAsync(collectionAlias); + return await GetDataViewsAsync(collection); + } + + private Task> GetDataViewsAsync(CollectionSetup collection) + { + if (collection.DataViewBuilder == null) { - var collection = await _collectionResolver.ResolveSetupAsync(collectionAlias); - return await GetDataViewsAsync(collection); + return Task.FromResult(collection.DataViews ?? Enumerable.Empty()); } - - private Task> GetDataViewsAsync(CollectionSetup collection) + else { - if (collection.DataViewBuilder == null) - { - return Task.FromResult(collection.DataViews ?? Enumerable.Empty()); - } - else - { - var builder = _serviceProvider.GetService(collection.DataViewBuilder); - return builder.GetDataViewsAsync(); - } + var builder = _serviceProvider.GetService(collection.DataViewBuilder); + return builder.GetDataViewsAsync(); } } } diff --git a/src/RapidCMS.Core/Resolvers/Language/LanguageResolver.cs b/src/RapidCMS.Core/Resolvers/Language/LanguageResolver.cs index 93a0bc8b..67c5e758 100644 --- a/src/RapidCMS.Core/Resolvers/Language/LanguageResolver.cs +++ b/src/RapidCMS.Core/Resolvers/Language/LanguageResolver.cs @@ -1,12 +1,11 @@ using RapidCMS.Core.Abstractions.Resolvers; -namespace RapidCMS.Core.Resolvers.Language +namespace RapidCMS.Core.Resolvers.Language; + +internal class LanguageResolver : ILanguageResolver { - internal class LanguageResolver : ILanguageResolver + public string ResolveText(string originalText) { - public string ResolveText(string originalText) - { - return originalText; - } + return originalText; } } diff --git a/src/RapidCMS.Core/Resolvers/Repositories/ApiRepositoryTypeResolver.cs b/src/RapidCMS.Core/Resolvers/Repositories/ApiRepositoryTypeResolver.cs index 3e289e3f..f96ce0ae 100644 --- a/src/RapidCMS.Core/Resolvers/Repositories/ApiRepositoryTypeResolver.cs +++ b/src/RapidCMS.Core/Resolvers/Repositories/ApiRepositoryTypeResolver.cs @@ -5,29 +5,28 @@ using RapidCMS.Core.Abstractions.Resolvers; using RapidCMS.Core.Repositories; -namespace RapidCMS.Core.Resolvers.Repositories +namespace RapidCMS.Core.Resolvers.Repositories; + +internal class ApiRepositoryTypeResolver : RepositoryTypeResolverBase, IRepositoryTypeResolver { - internal class ApiRepositoryTypeResolver : RepositoryTypeResolverBase, IRepositoryTypeResolver - { - private readonly IReadOnlyDictionary _repositoryTypes; + private readonly IReadOnlyDictionary _repositoryTypes; - public ApiRepositoryTypeResolver(IApiConfig apiConfig) - { - _repositoryTypes = apiConfig.Repositories.ToDictionary(repo => repo.Alias, repo => repo.RepositoryType); - } + public ApiRepositoryTypeResolver(IApiConfig apiConfig) + { + _repositoryTypes = apiConfig.Repositories.ToDictionary(repo => repo.Alias, repo => repo.RepositoryType); + } - public Type GetType(string repositoryAlias) - => _repositoryTypes.TryGetValue(repositoryAlias, out var type) - ? type - : throw new InvalidOperationException($"Cannot find Repository for alias '{repositoryAlias}'. Make sure you register the concrete repository class and not an abstract or base class."); + public Type GetType(string repositoryAlias) + => _repositoryTypes.TryGetValue(repositoryAlias, out var type) + ? type + : throw new InvalidOperationException($"Cannot find Repository for alias '{repositoryAlias}'. Make sure you register the concrete repository class and not an abstract or base class."); - public (Type entityType, Type databaseType) GetEntityTypes(string repositoryAlias) - => !_repositoryTypes.TryGetValue(repositoryAlias, out var type) ? throw new InvalidOperationException($"Cannot find Repository for alias '{repositoryAlias}'.") - : GetGenericParametersOfBaseType(type, typeof(BaseRepository<>)) is Type[] entityType && entityType.Length == 1 ? (entityType[0], entityType[0]) - : GetGenericParametersOfBaseType(type, typeof(BaseMappedRepository<,>)) is Type[] entityTypes && entityTypes.Length == 2 ? (entityTypes[0], entityTypes[1]) - : throw new InvalidOperationException($"Cannot find entity types for Repository '{repositoryAlias}'."); + public (Type entityType, Type databaseType) GetEntityTypes(string repositoryAlias) + => !_repositoryTypes.TryGetValue(repositoryAlias, out var type) ? throw new InvalidOperationException($"Cannot find Repository for alias '{repositoryAlias}'.") + : GetGenericParametersOfBaseType(type, typeof(BaseRepository<>)) is Type[] entityType && entityType.Length == 1 ? (entityType[0], entityType[0]) + : GetGenericParametersOfBaseType(type, typeof(BaseMappedRepository<,>)) is Type[] entityTypes && entityTypes.Length == 2 ? (entityTypes[0], entityTypes[1]) + : throw new InvalidOperationException($"Cannot find entity types for Repository '{repositoryAlias}'."); - // the API does not handle repositories that were registered under their base class / interface etc. - public string GetAlias(Type originallyRegisterdType) => throw new InvalidOperationException("Use AliasHelper.GetRepositoryAlias in Api context."); - } + // the API does not handle repositories that were registered under their base class / interface etc. + public string GetAlias(Type originallyRegisterdType) => throw new InvalidOperationException("Use AliasHelper.GetRepositoryAlias in Api context."); } diff --git a/src/RapidCMS.Core/Resolvers/Repositories/CmsRepositoryTypeResolver.cs b/src/RapidCMS.Core/Resolvers/Repositories/CmsRepositoryTypeResolver.cs index e88cfcc6..6e00b2a2 100644 --- a/src/RapidCMS.Core/Resolvers/Repositories/CmsRepositoryTypeResolver.cs +++ b/src/RapidCMS.Core/Resolvers/Repositories/CmsRepositoryTypeResolver.cs @@ -3,35 +3,34 @@ using RapidCMS.Core.Abstractions.Resolvers; using RapidCMS.Core.Repositories; -namespace RapidCMS.Core.Resolvers.Repositories +namespace RapidCMS.Core.Resolvers.Repositories; + +internal class CmsRepositoryTypeResolver : RepositoryTypeResolverBase, IRepositoryTypeResolver { - internal class CmsRepositoryTypeResolver : RepositoryTypeResolverBase, IRepositoryTypeResolver - { - private readonly IReadOnlyDictionary _repositoryTypes; - private readonly IReadOnlyDictionary _originallyRegisterdRepositoriesToAlias; + private readonly IReadOnlyDictionary _repositoryTypes; + private readonly IReadOnlyDictionary _originallyRegisterdRepositoriesToAlias; - public CmsRepositoryTypeResolver( - IReadOnlyDictionary types, - IReadOnlyDictionary originals) - { - _repositoryTypes = types; - _originallyRegisterdRepositoriesToAlias = originals; - } + public CmsRepositoryTypeResolver( + IReadOnlyDictionary types, + IReadOnlyDictionary originals) + { + _repositoryTypes = types; + _originallyRegisterdRepositoriesToAlias = originals; + } - public Type GetType(string repositoryAlias) - => _repositoryTypes.TryGetValue(repositoryAlias, out var type) - ? type - : throw new InvalidOperationException($"Cannot find Repository for alias '{repositoryAlias}'."); + public Type GetType(string repositoryAlias) + => _repositoryTypes.TryGetValue(repositoryAlias, out var type) + ? type + : throw new InvalidOperationException($"Cannot find Repository for alias '{repositoryAlias}'."); - public string GetAlias(Type originallyRegisteredType) - => _originallyRegisterdRepositoriesToAlias.TryGetValue(originallyRegisteredType, out var alias) - ? alias - : throw new InvalidOperationException($"Cannot find alias for Repository '{originallyRegisteredType}'."); + public string GetAlias(Type originallyRegisteredType) + => _originallyRegisterdRepositoriesToAlias.TryGetValue(originallyRegisteredType, out var alias) + ? alias + : throw new InvalidOperationException($"Cannot find alias for Repository '{originallyRegisteredType}'."); - public (Type entityType, Type databaseType) GetEntityTypes(string repositoryAlias) - => !_repositoryTypes.TryGetValue(repositoryAlias, out var type) ? throw new InvalidOperationException($"Cannot find Repository for alias '{repositoryAlias}'.") - : GetGenericParametersOfBaseType(type, typeof(BaseRepository<>)) is Type[] entityType && entityType.Length == 1 ? (entityType[0], entityType[0]) - : GetGenericParametersOfBaseType(type, typeof(BaseMappedRepository<,>)) is Type[] entityTypes && entityTypes.Length == 2 ? (entityTypes[0], entityTypes[1]) - : throw new InvalidOperationException($"Cannot find entity types for Repository '{repositoryAlias}'."); - } + public (Type entityType, Type databaseType) GetEntityTypes(string repositoryAlias) + => !_repositoryTypes.TryGetValue(repositoryAlias, out var type) ? throw new InvalidOperationException($"Cannot find Repository for alias '{repositoryAlias}'.") + : GetGenericParametersOfBaseType(type, typeof(BaseRepository<>)) is Type[] entityType && entityType.Length == 1 ? (entityType[0], entityType[0]) + : GetGenericParametersOfBaseType(type, typeof(BaseMappedRepository<,>)) is Type[] entityTypes && entityTypes.Length == 2 ? (entityTypes[0], entityTypes[1]) + : throw new InvalidOperationException($"Cannot find entity types for Repository '{repositoryAlias}'."); } diff --git a/src/RapidCMS.Core/Resolvers/Repositories/CollectionAliasResolver.cs b/src/RapidCMS.Core/Resolvers/Repositories/CollectionAliasResolver.cs index 89e947c6..7d3cba47 100644 --- a/src/RapidCMS.Core/Resolvers/Repositories/CollectionAliasResolver.cs +++ b/src/RapidCMS.Core/Resolvers/Repositories/CollectionAliasResolver.cs @@ -1,18 +1,17 @@ using System.Collections.Generic; using RapidCMS.Core.Abstractions.Resolvers; -namespace RapidCMS.Core.Resolvers.Repositories -{ - internal class CollectionAliasResolver : ICollectionAliasResolver - { - private readonly IReadOnlyDictionary> _aliases; +namespace RapidCMS.Core.Resolvers.Repositories; - public CollectionAliasResolver(IReadOnlyDictionary> aliases) - { - _aliases = aliases; - } +internal class CollectionAliasResolver : ICollectionAliasResolver +{ + private readonly IReadOnlyDictionary> _aliases; - public IReadOnlyList GetAlias(string repositoryAlias) - => _aliases[repositoryAlias]; + public CollectionAliasResolver(IReadOnlyDictionary> aliases) + { + _aliases = aliases; } + + public IReadOnlyList GetAlias(string repositoryAlias) + => _aliases[repositoryAlias]; } diff --git a/src/RapidCMS.Core/Resolvers/Repositories/EntityVariantResolver.cs b/src/RapidCMS.Core/Resolvers/Repositories/EntityVariantResolver.cs index 634504e0..ec4d8410 100644 --- a/src/RapidCMS.Core/Resolvers/Repositories/EntityVariantResolver.cs +++ b/src/RapidCMS.Core/Resolvers/Repositories/EntityVariantResolver.cs @@ -2,18 +2,17 @@ using System.Collections.Generic; using RapidCMS.Core.Abstractions.Resolvers; -namespace RapidCMS.Core.Resolvers.Repositories -{ - internal class EntityVariantResolver : IEntityVariantResolver - { - private readonly IReadOnlyDictionary derivedTypes)> _entityVariants; +namespace RapidCMS.Core.Resolvers.Repositories; - public EntityVariantResolver(IReadOnlyDictionary derivedTypes)> entityVariants) - { - _entityVariants = entityVariants; - } +internal class EntityVariantResolver : IEntityVariantResolver +{ + private readonly IReadOnlyDictionary derivedTypes)> _entityVariants; - public (Type? baseType, IReadOnlyList? derivedTypes) GetValidVariantsForRepository(string repositoryAlias) - => _entityVariants.TryGetValue(repositoryAlias, out var value) ? value : default; + public EntityVariantResolver(IReadOnlyDictionary derivedTypes)> entityVariants) + { + _entityVariants = entityVariants; } + + public (Type? baseType, IReadOnlyList? derivedTypes) GetValidVariantsForRepository(string repositoryAlias) + => _entityVariants.TryGetValue(repositoryAlias, out var value) ? value : default; } diff --git a/src/RapidCMS.Core/Resolvers/Repositories/RepositoryResolver.cs b/src/RapidCMS.Core/Resolvers/Repositories/RepositoryResolver.cs index daef72c1..d68963c3 100644 --- a/src/RapidCMS.Core/Resolvers/Repositories/RepositoryResolver.cs +++ b/src/RapidCMS.Core/Resolvers/Repositories/RepositoryResolver.cs @@ -8,39 +8,38 @@ using RapidCMS.Core.Extensions; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Resolvers.Repositories +namespace RapidCMS.Core.Resolvers.Repositories; + +internal class RepositoryResolver : IRepositoryResolver { - internal class RepositoryResolver : IRepositoryResolver - { - private readonly IRepositoryTypeResolver _repositoryTypeResolver; - private readonly IServiceProvider _serviceProvider; - private readonly IEnumerable _plugins; + private readonly IRepositoryTypeResolver _repositoryTypeResolver; + private readonly IServiceProvider _serviceProvider; + private readonly IEnumerable _plugins; - public RepositoryResolver( - IRepositoryTypeResolver repositoryTypeResolver, - IServiceProvider serviceProvider, - IEnumerable plugins) - { - _repositoryTypeResolver = repositoryTypeResolver; - _serviceProvider = serviceProvider; - _plugins = plugins; - } + public RepositoryResolver( + IRepositoryTypeResolver repositoryTypeResolver, + IServiceProvider serviceProvider, + IEnumerable plugins) + { + _repositoryTypeResolver = repositoryTypeResolver; + _serviceProvider = serviceProvider; + _plugins = plugins; + } - IRepository IRepositoryResolver.GetRepository(CollectionSetup collection) - => (this as IRepositoryResolver).GetRepository(collection.RepositoryAlias); + IRepository IRepositoryResolver.GetRepository(CollectionSetup collection) + => (this as IRepositoryResolver).GetRepository(collection.RepositoryAlias); - IRepository IRepositoryResolver.GetRepository(string repositoryAlias) + IRepository IRepositoryResolver.GetRepository(string repositoryAlias) + { + if (repositoryAlias.TryParseAsPluginAlias(out var alias) && _plugins.FirstOrDefault(x => x.CollectionPrefix == alias.prefix) is IPlugin plugin) { - if (repositoryAlias.TryParseAsPluginAlias(out var alias) && _plugins.FirstOrDefault(x => x.CollectionPrefix == alias.prefix) is IPlugin plugin) - { - return (this as IRepositoryResolver).GetRepository(plugin.GetRepositoryType(alias.collectionAlias) - ?? throw new InvalidOperationException($"Cannot resolve plugin repository type with alias {repositoryAlias}.")); - } - - return (this as IRepositoryResolver).GetRepository(_repositoryTypeResolver.GetType(repositoryAlias)); + return (this as IRepositoryResolver).GetRepository(plugin.GetRepositoryType(alias.collectionAlias) + ?? throw new InvalidOperationException($"Cannot resolve plugin repository type with alias {repositoryAlias}.")); } - IRepository IRepositoryResolver.GetRepository(Type repositoryType) - => (IRepository)_serviceProvider.GetRequiredService(repositoryType); + return (this as IRepositoryResolver).GetRepository(_repositoryTypeResolver.GetType(repositoryAlias)); } + + IRepository IRepositoryResolver.GetRepository(Type repositoryType) + => (IRepository)_serviceProvider.GetRequiredService(repositoryType); } diff --git a/src/RapidCMS.Core/Resolvers/Repositories/RepositoryTypeResolverBase.cs b/src/RapidCMS.Core/Resolvers/Repositories/RepositoryTypeResolverBase.cs index 5a1a017e..510736fd 100644 --- a/src/RapidCMS.Core/Resolvers/Repositories/RepositoryTypeResolverBase.cs +++ b/src/RapidCMS.Core/Resolvers/Repositories/RepositoryTypeResolverBase.cs @@ -1,23 +1,22 @@ using System; -namespace RapidCMS.Core.Resolvers.Repositories +namespace RapidCMS.Core.Resolvers.Repositories; + +internal class RepositoryTypeResolverBase { - internal class RepositoryTypeResolverBase + protected Type[]? GetGenericParametersOfBaseType(Type type, Type baseTypeToFind) { - protected Type[]? GetGenericParametersOfBaseType(Type type, Type baseTypeToFind) + if (type.IsGenericType && type.GetGenericTypeDefinition() == baseTypeToFind) + { + return type.GetGenericArguments(); + } + else if (type.BaseType != null) + { + return GetGenericParametersOfBaseType(type.BaseType, baseTypeToFind); + } + else { - if (type.IsGenericType && type.GetGenericTypeDefinition() == baseTypeToFind) - { - return type.GetGenericArguments(); - } - else if (type.BaseType != null) - { - return GetGenericParametersOfBaseType(type.BaseType, baseTypeToFind); - } - else - { - return null; - } + return null; } } } diff --git a/src/RapidCMS.Core/Resolvers/Setup/ButtonSetupResolver.cs b/src/RapidCMS.Core/Resolvers/Setup/ButtonSetupResolver.cs index 8db80454..e4e432e5 100644 --- a/src/RapidCMS.Core/Resolvers/Setup/ButtonSetupResolver.cs +++ b/src/RapidCMS.Core/Resolvers/Setup/ButtonSetupResolver.cs @@ -10,87 +10,86 @@ using RapidCMS.Core.Models.Config; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Resolvers.Setup +namespace RapidCMS.Core.Resolvers.Setup; + +internal class ButtonSetupResolver : ISetupResolver { - internal class ButtonSetupResolver : ISetupResolver + private readonly ILanguageResolver _languageResolver; + + public ButtonSetupResolver(ILanguageResolver languageResolver) { - private readonly ILanguageResolver _languageResolver; + _languageResolver = languageResolver; + } - public ButtonSetupResolver(ILanguageResolver languageResolver) + public Task> ResolveSetupAsync(ButtonConfig config, CollectionSetup? collection = default) + { + if (collection == null) { - _languageResolver = languageResolver; + throw new ArgumentNullException(nameof(collection)); } - public Task> ResolveSetupAsync(ButtonConfig config, CollectionSetup? collection = default) - { - if (collection == null) - { - throw new ArgumentNullException(nameof(collection)); - } - - var @default = (config as DefaultButtonConfig)?.ButtonType.GetCustomAttribute(); + var @default = (config as DefaultButtonConfig)?.ButtonType.GetCustomAttribute(); - var button = new ButtonSetup - { - Buttons = Enumerable.Empty(), + var button = new ButtonSetup + { + Buttons = Enumerable.Empty(), - Label = _languageResolver.ResolveText(config.Label ?? @default?.Label ?? "Button"), - Icon = config.Icon ?? @default?.Icon ?? "", - IsPrimary = config.IsPrimary, - IsVisible = config.IsVisible, + Label = _languageResolver.ResolveText(config.Label ?? @default?.Label ?? "Button"), + Icon = config.Icon ?? @default?.Icon ?? "", + IsPrimary = config.IsPrimary, + IsVisible = config.IsVisible, - ButtonId = config.Id ?? throw new ArgumentNullException(nameof(config.Id)), - EntityVariant = collection.EntityVariant - }; + ButtonId = config.Id ?? throw new ArgumentNullException(nameof(config.Id)), + EntityVariant = collection.EntityVariant + }; - if (config is DefaultButtonConfig defaultButton) + if (config is DefaultButtonConfig defaultButton) + { + if (defaultButton.ButtonType == DefaultButtonType.OpenPane) { - if (defaultButton.ButtonType == DefaultButtonType.OpenPane) - { - throw new InvalidOperationException($"An {DefaultButtonType.OpenPane} button is not allowed to be used by DefaultButton"); - } + throw new InvalidOperationException($"An {DefaultButtonType.OpenPane} button is not allowed to be used by DefaultButton"); + } - button.DefaultButtonType = defaultButton.ButtonType; + button.DefaultButtonType = defaultButton.ButtonType; - button.ButtonHandlerType = typeof(DefaultButtonActionHandler); + button.ButtonHandlerType = typeof(DefaultButtonActionHandler); - if (defaultButton.ButtonType == DefaultButtonType.New && collection.SubEntityVariants != null) - { - button.Buttons = collection.SubEntityVariants.ToList(variant => - new ButtonSetup - { - Label = _languageResolver.ResolveText(string.Format(button.Label ?? variant.Name, variant.Name)), - Icon = variant.Icon ?? @default?.Icon ?? "", - IsPrimary = config.IsPrimary, - ButtonId = $"{config.Id}-{variant.Alias}", - EntityVariant = variant, - DefaultButtonType = DefaultButtonType.New, - ButtonHandlerType = typeof(DefaultButtonActionHandler), - Buttons = Enumerable.Empty() - }); - } - } - else if (config is CustomButtonConfig customButton) - { - button.CustomType = customButton.CustomType; - button.ButtonHandlerType = customButton.ActionHandler; - } - else if (config is PaneButtonConfig paneButton) + if (defaultButton.ButtonType == DefaultButtonType.New && collection.SubEntityVariants != null) { - button.DefaultButtonType = DefaultButtonType.OpenPane; - button.ButtonHandlerType = typeof(OpenPaneButtonActionHandler<>).MakeGenericType(paneButton.PaneType); + button.Buttons = collection.SubEntityVariants.ToList(variant => + new ButtonSetup + { + Label = _languageResolver.ResolveText(string.Format(button.Label ?? variant.Name, variant.Name)), + Icon = variant.Icon ?? @default?.Icon ?? "", + IsPrimary = config.IsPrimary, + ButtonId = $"{config.Id}-{variant.Alias}", + EntityVariant = variant, + DefaultButtonType = DefaultButtonType.New, + ButtonHandlerType = typeof(DefaultButtonActionHandler), + Buttons = Enumerable.Empty() + }); } - else if (config is NavigationButtonConfig navigationButton) - { - button.DefaultButtonType = DefaultButtonType.Navigate; - button.ButtonHandlerType = typeof(NavigateButtonActionHandler<>).MakeGenericType(navigationButton.HandlerType); - } - else - { - throw new InvalidOperationException(); - } - - return Task.FromResult>(new ResolvedSetup(button, true)); } + else if (config is CustomButtonConfig customButton) + { + button.CustomType = customButton.CustomType; + button.ButtonHandlerType = customButton.ActionHandler; + } + else if (config is PaneButtonConfig paneButton) + { + button.DefaultButtonType = DefaultButtonType.OpenPane; + button.ButtonHandlerType = typeof(OpenPaneButtonActionHandler<>).MakeGenericType(paneButton.PaneType); + } + else if (config is NavigationButtonConfig navigationButton) + { + button.DefaultButtonType = DefaultButtonType.Navigate; + button.ButtonHandlerType = typeof(NavigateButtonActionHandler<>).MakeGenericType(navigationButton.HandlerType); + } + else + { + throw new InvalidOperationException(); + } + + return Task.FromResult>(new ResolvedSetup(button, true)); } } diff --git a/src/RapidCMS.Core/Resolvers/Setup/CollectionListSetupResolverBase.cs b/src/RapidCMS.Core/Resolvers/Setup/CollectionListSetupResolverBase.cs index 706ab098..05080420 100644 --- a/src/RapidCMS.Core/Resolvers/Setup/CollectionListSetupResolverBase.cs +++ b/src/RapidCMS.Core/Resolvers/Setup/CollectionListSetupResolverBase.cs @@ -5,43 +5,42 @@ using RapidCMS.Core.Models.Config; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Resolvers.Setup +namespace RapidCMS.Core.Resolvers.Setup; + +internal class CollectionListSetupResolverBase { - internal class CollectionListSetupResolverBase - { - protected readonly Lazy> _setupResolver; + protected readonly Lazy> _setupResolver; - public CollectionListSetupResolverBase(Lazy> setupResolver) - { - _setupResolver = setupResolver; - } + public CollectionListSetupResolverBase(Lazy> setupResolver) + { + _setupResolver = setupResolver; + } - protected async Task GetUsageTypeAsync(CollectionListConfig config, CollectionSetup? collection) + protected async Task GetUsageTypeAsync(CollectionListConfig config, CollectionSetup? collection) + { + if (config is ReferencedCollectionListConfig referencedCollectionList) { - if (config is ReferencedCollectionListConfig referencedCollectionList) + if (referencedCollectionList.CollectionAlias == collection?.Alias) { - if (referencedCollectionList.CollectionAlias == collection?.Alias) - { - return (collection.ListEditor != null ? UsageType.Edit : 0) | - (collection.ListView != null ? UsageType.View : 0); - } - else - { - // TODO: this can trigger infinite loops / stack overflows.. - - var resolver = _setupResolver.Value; - - var referencedCollection = await resolver.ResolveSetupAsync(referencedCollectionList.CollectionAlias); - - return (referencedCollection?.ListEditor != null ? UsageType.Edit : 0) | - (referencedCollection?.ListView != null ? UsageType.View : 0); - } + return (collection.ListEditor != null ? UsageType.Edit : 0) | + (collection.ListView != null ? UsageType.View : 0); } else { - return (config?.ListEditor != null ? UsageType.Edit : 0) | - (config?.ListView != null ? UsageType.View : 0); + // TODO: this can trigger infinite loops / stack overflows.. + + var resolver = _setupResolver.Value; + + var referencedCollection = await resolver.ResolveSetupAsync(referencedCollectionList.CollectionAlias); + + return (referencedCollection?.ListEditor != null ? UsageType.Edit : 0) | + (referencedCollection?.ListView != null ? UsageType.View : 0); } } + else + { + return (config?.ListEditor != null ? UsageType.Edit : 0) | + (config?.ListView != null ? UsageType.View : 0); + } } } diff --git a/src/RapidCMS.Core/Resolvers/Setup/CollectionSetupResolver.cs b/src/RapidCMS.Core/Resolvers/Setup/CollectionSetupResolver.cs index 7be2fe03..4d31518b 100644 --- a/src/RapidCMS.Core/Resolvers/Setup/CollectionSetupResolver.cs +++ b/src/RapidCMS.Core/Resolvers/Setup/CollectionSetupResolver.cs @@ -11,173 +11,172 @@ using RapidCMS.Core.Models.Setup; using RapidCMS.Core.Validators; -namespace RapidCMS.Core.Resolvers.Setup +namespace RapidCMS.Core.Resolvers.Setup; + +internal class CollectionSetupResolver : ISetupResolver { - internal class CollectionSetupResolver : ISetupResolver + private readonly ICmsConfig _cmsConfig; + private readonly ISetupResolver, IEnumerable> _treeElementResolver; + private readonly ISetupResolver _entityVariantResolver; + private readonly ISetupResolver _treeViewResolver; + private readonly ISetupResolver _elementResolver; + private readonly ISetupResolver _listResolver; + private readonly ISetupResolver _nodeResolver; + private readonly IRepositoryTypeResolver _repositoryTypeResolver; + private readonly IEnumerable _plugins; + + private Dictionary _pluginMap { get; set; } = new Dictionary(); + private Dictionary _collectionMap { get; set; } = new Dictionary(); + private Dictionary _cachedCollectionMap { get; set; } = new Dictionary(); + + public CollectionSetupResolver(ICmsConfig cmsConfig, + ISetupResolver, IEnumerable> treeElementResolver, + ISetupResolver entityVariantResolver, + ISetupResolver treeViewResolver, + ISetupResolver elementResolver, + ISetupResolver listResolver, + ISetupResolver nodeResolver, + IRepositoryTypeResolver repositoryTypeResolver, + IEnumerable plugins) + { + _cmsConfig = cmsConfig; + _treeElementResolver = treeElementResolver; + _entityVariantResolver = entityVariantResolver; + _treeViewResolver = treeViewResolver; + _elementResolver = elementResolver; + _listResolver = listResolver; + _nodeResolver = nodeResolver; + _repositoryTypeResolver = repositoryTypeResolver; + _plugins = plugins; + Initialize(); + } + + private void Initialize() { - private readonly ICmsConfig _cmsConfig; - private readonly ISetupResolver, IEnumerable> _treeElementResolver; - private readonly ISetupResolver _entityVariantResolver; - private readonly ISetupResolver _treeViewResolver; - private readonly ISetupResolver _elementResolver; - private readonly ISetupResolver _listResolver; - private readonly ISetupResolver _nodeResolver; - private readonly IRepositoryTypeResolver _repositoryTypeResolver; - private readonly IEnumerable _plugins; - - private Dictionary _pluginMap { get; set; } = new Dictionary(); - private Dictionary _collectionMap { get; set; } = new Dictionary(); - private Dictionary _cachedCollectionMap { get; set; } = new Dictionary(); - - public CollectionSetupResolver(ICmsConfig cmsConfig, - ISetupResolver, IEnumerable> treeElementResolver, - ISetupResolver entityVariantResolver, - ISetupResolver treeViewResolver, - ISetupResolver elementResolver, - ISetupResolver listResolver, - ISetupResolver nodeResolver, - IRepositoryTypeResolver repositoryTypeResolver, - IEnumerable plugins) + MapCollections(_cmsConfig.CollectionsAndPages.OfType()); + + foreach (var plugin in _plugins) { - _cmsConfig = cmsConfig; - _treeElementResolver = treeElementResolver; - _entityVariantResolver = entityVariantResolver; - _treeViewResolver = treeViewResolver; - _elementResolver = elementResolver; - _listResolver = listResolver; - _nodeResolver = nodeResolver; - _repositoryTypeResolver = repositoryTypeResolver; - _plugins = plugins; - Initialize(); + _pluginMap.Add(plugin.CollectionPrefix, plugin); } - private void Initialize() + void MapCollections(IEnumerable collections) { - MapCollections(_cmsConfig.CollectionsAndPages.OfType()); - - foreach (var plugin in _plugins) + foreach (var collection in collections.Where(col => col is not ReferencedCollectionConfig)) { - _pluginMap.Add(plugin.CollectionPrefix, plugin); - } + if (!_collectionMap.TryAdd(collection.Alias, collection)) + { + throw new InvalidOperationException($"Duplicate collection alias '{collection.Alias}' not allowed."); + } - void MapCollections(IEnumerable collections) - { - foreach (var collection in collections.Where(col => col is not ReferencedCollectionConfig)) + var subCollections = collection.CollectionsAndPages.OfType(); + if (subCollections.Any()) { - if (!_collectionMap.TryAdd(collection.Alias, collection)) - { - throw new InvalidOperationException($"Duplicate collection alias '{collection.Alias}' not allowed."); - } - - var subCollections = collection.CollectionsAndPages.OfType(); - if (subCollections.Any()) - { - MapCollections(subCollections); - } + MapCollections(subCollections); } } } + } - Task ISetupResolver.ResolveSetupAsync() + Task ISetupResolver.ResolveSetupAsync() + { + throw new InvalidOperationException("Cannot resolve collection or page without alias."); + } + + async Task ISetupResolver.ResolveSetupAsync(string alias) + { + if (_cachedCollectionMap.TryGetValue(alias, out var collectionSetup)) { - throw new InvalidOperationException("Cannot resolve collection or page without alias."); + return collectionSetup; } - - async Task ISetupResolver.ResolveSetupAsync(string alias) + else if (_cachedCollectionMap.FirstOrDefault(x => x.Value.RepositoryAlias == alias).Value is CollectionSetup collection) { - if (_cachedCollectionMap.TryGetValue(alias, out var collectionSetup)) - { - return collectionSetup; - } - else if (_cachedCollectionMap.FirstOrDefault(x => x.Value.RepositoryAlias == alias).Value is CollectionSetup collection) - { - return collection; - } - - var resolvedSetup = default(IResolvedSetup); - if (_collectionMap.TryGetValue(alias, out var collectionConfig)) - { - resolvedSetup = await ConvertConfigAsync(collectionConfig); - - } - else if (alias.TryParseAsPluginAlias(out var pluginAlias) && - _pluginMap.TryGetValue(pluginAlias.prefix, out var plugin) && - await plugin.GetCollectionAsync(pluginAlias.collectionAlias) is ResolvedSetup collection) - { - resolvedSetup = collection; - } + return collection; + } - if (resolvedSetup == null) - { - throw new InvalidOperationException($"Cannot find collection with alias {alias}."); - } + var resolvedSetup = default(IResolvedSetup); + if (_collectionMap.TryGetValue(alias, out var collectionConfig)) + { + resolvedSetup = await ConvertConfigAsync(collectionConfig); + + } + else if (alias.TryParseAsPluginAlias(out var pluginAlias) && + _pluginMap.TryGetValue(pluginAlias.prefix, out var plugin) && + await plugin.GetCollectionAsync(pluginAlias.collectionAlias) is ResolvedSetup collection) + { + resolvedSetup = collection; + } - if (resolvedSetup.Cachable) - { - _cachedCollectionMap[alias] = resolvedSetup.Setup; - } + if (resolvedSetup == null) + { + throw new InvalidOperationException($"Cannot find collection with alias {alias}."); + } - return resolvedSetup.Setup; + if (resolvedSetup.Cachable) + { + _cachedCollectionMap[alias] = resolvedSetup.Setup; } - private async Task> ConvertConfigAsync(CollectionConfig config) + return resolvedSetup.Setup; + } + + private async Task> ConvertConfigAsync(CollectionConfig config) + { + var repositoryAlias = _repositoryTypeResolver.GetAlias(config.RepositoryType); + + var collection = new CollectionSetup( + config.Icon, + config.Color, + config.Name, + config.Alias, + repositoryAlias) { - var repositoryAlias = _repositoryTypeResolver.GetAlias(config.RepositoryType); - - var collection = new CollectionSetup( - config.Icon, - config.Color, - config.Name, - config.Alias, - repositoryAlias) - { - DataViews = config.DataViews, - DataViewBuilder = config.DataViewBuilder, - UsageType = GetCollectionUsage(config), - Validators = config.Validators.ToList(x => new ValidationSetup(x.Type, x.Configuration)) - }; + DataViews = config.DataViews, + DataViewBuilder = config.DataViewBuilder, + UsageType = GetCollectionUsage(config), + Validators = config.Validators.ToList(x => new ValidationSetup(x.Type, x.Configuration)) + }; - if (!_cmsConfig.Advanced.RemoveDataAnnotationEntityValidator) - { - collection.Validators.Insert(0, new ValidationSetup(typeof(DataAnnotationEntityValidator), default)); - } + if (!_cmsConfig.Advanced.RemoveDataAnnotationEntityValidator) + { + collection.Validators.Insert(0, new ValidationSetup(typeof(DataAnnotationEntityValidator), default)); + } - var cacheable = true; + var cacheable = true; - if (!string.IsNullOrWhiteSpace(config.ParentAlias) && _collectionMap.TryGetValue(config.ParentAlias, out var collectionConfig)) - { - collection.Parent = new TreeElementSetup(collectionConfig.Alias, collectionConfig.Name, PageType.Collection); // TODO: this assumes nesting is always with collections - } - collection.Collections = (await _treeElementResolver.ResolveSetupAsync(config.CollectionsAndPages, collection)).CheckIfCachable(ref cacheable).ToList(); + if (!string.IsNullOrWhiteSpace(config.ParentAlias) && _collectionMap.TryGetValue(config.ParentAlias, out var collectionConfig)) + { + collection.Parent = new TreeElementSetup(collectionConfig.Alias, collectionConfig.Name, PageType.Collection); // TODO: this assumes nesting is always with collections + } + collection.Collections = (await _treeElementResolver.ResolveSetupAsync(config.CollectionsAndPages, collection)).CheckIfCachable(ref cacheable).ToList(); - collection.EntityVariant = (await _entityVariantResolver.ResolveSetupAsync(config.EntityVariant, collection)).CheckIfCachable(ref cacheable); - if (config.SubEntityVariants.Any()) - { - collection.SubEntityVariants = (await _entityVariantResolver.ResolveSetupAsync(config.SubEntityVariants, collection)).CheckIfCachable(ref cacheable).ToList(); - } + collection.EntityVariant = (await _entityVariantResolver.ResolveSetupAsync(config.EntityVariant, collection)).CheckIfCachable(ref cacheable); + if (config.SubEntityVariants.Any()) + { + collection.SubEntityVariants = (await _entityVariantResolver.ResolveSetupAsync(config.SubEntityVariants, collection)).CheckIfCachable(ref cacheable).ToList(); + } - collection.TreeView = config.TreeView == null ? null : (await _treeViewResolver.ResolveSetupAsync(config.TreeView, collection)).CheckIfCachable(ref cacheable); + collection.TreeView = config.TreeView == null ? null : (await _treeViewResolver.ResolveSetupAsync(config.TreeView, collection)).CheckIfCachable(ref cacheable); - collection.ElementSetup = config.ElementConfig == null ? null : (await _elementResolver.ResolveSetupAsync(config.ElementConfig, collection)).CheckIfCachable(ref cacheable); + collection.ElementSetup = config.ElementConfig == null ? null : (await _elementResolver.ResolveSetupAsync(config.ElementConfig, collection)).CheckIfCachable(ref cacheable); - collection.ListView = config.ListView == null ? null : (await _listResolver.ResolveSetupAsync(config.ListView, collection)).CheckIfCachable(ref cacheable); - collection.ListEditor = config.ListEditor == null ? null : (await _listResolver.ResolveSetupAsync(config.ListEditor, collection)).CheckIfCachable(ref cacheable); + collection.ListView = config.ListView == null ? null : (await _listResolver.ResolveSetupAsync(config.ListView, collection)).CheckIfCachable(ref cacheable); + collection.ListEditor = config.ListEditor == null ? null : (await _listResolver.ResolveSetupAsync(config.ListEditor, collection)).CheckIfCachable(ref cacheable); - collection.NodeView = config.NodeView == null ? null : (await _nodeResolver.ResolveSetupAsync(config.NodeView, collection)).CheckIfCachable(ref cacheable); - collection.NodeEditor = config.NodeEditor == null ? null : (await _nodeResolver.ResolveSetupAsync(config.NodeEditor, collection)).CheckIfCachable(ref cacheable); + collection.NodeView = config.NodeView == null ? null : (await _nodeResolver.ResolveSetupAsync(config.NodeView, collection)).CheckIfCachable(ref cacheable); + collection.NodeEditor = config.NodeEditor == null ? null : (await _nodeResolver.ResolveSetupAsync(config.NodeEditor, collection)).CheckIfCachable(ref cacheable); - return new ResolvedSetup(collection, cacheable); - } + return new ResolvedSetup(collection, cacheable); + } - private static UsageType GetCollectionUsage(CollectionConfig config) - { - var hasDetailsPageUsage = config.GetType().IsGenericType && config.GetType().GetGenericTypeDefinition() == typeof(DetailPageConfig<>); - var hasNodeUsage = !hasDetailsPageUsage && (config.NodeEditor != null || config.NodeView != null); - var hasCollectionUsage = config.ListEditor != null || config.ListView != null; + private static UsageType GetCollectionUsage(CollectionConfig config) + { + var hasDetailsPageUsage = config.GetType().IsGenericType && config.GetType().GetGenericTypeDefinition() == typeof(DetailPageConfig<>); + var hasNodeUsage = !hasDetailsPageUsage && (config.NodeEditor != null || config.NodeView != null); + var hasCollectionUsage = config.ListEditor != null || config.ListView != null; - return (hasNodeUsage ? UsageType.Node : UsageType.None) | - (hasCollectionUsage ? UsageType.List : UsageType.None) | - (hasDetailsPageUsage ? UsageType.Details : UsageType.None); - } + return (hasNodeUsage ? UsageType.Node : UsageType.None) | + (hasCollectionUsage ? UsageType.List : UsageType.None) | + (hasDetailsPageUsage ? UsageType.Details : UsageType.None); } } diff --git a/src/RapidCMS.Core/Resolvers/Setup/ElementSetupResolver.cs b/src/RapidCMS.Core/Resolvers/Setup/ElementSetupResolver.cs index 6d977954..25cd6dbe 100644 --- a/src/RapidCMS.Core/Resolvers/Setup/ElementSetupResolver.cs +++ b/src/RapidCMS.Core/Resolvers/Setup/ElementSetupResolver.cs @@ -3,16 +3,15 @@ using RapidCMS.Core.Models.Config; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Resolvers.Setup +namespace RapidCMS.Core.Resolvers.Setup; + +internal class ElementSetupResolver : ISetupResolver { - internal class ElementSetupResolver : ISetupResolver + public Task> ResolveSetupAsync(ElementConfig config, CollectionSetup? collection = default) { - public Task> ResolveSetupAsync(ElementConfig config, CollectionSetup? collection = default) - { - return Task.FromResult>(new ResolvedSetup(new ElementSetup( - config.IdProperty, - config.DisplayProperties), - true)); - } + return Task.FromResult>(new ResolvedSetup(new ElementSetup( + config.IdProperty, + config.DisplayProperties), + true)); } } diff --git a/src/RapidCMS.Core/Resolvers/Setup/EntityVariantSetupResolver.cs b/src/RapidCMS.Core/Resolvers/Setup/EntityVariantSetupResolver.cs index c1ac7b1d..b3a7bcae 100644 --- a/src/RapidCMS.Core/Resolvers/Setup/EntityVariantSetupResolver.cs +++ b/src/RapidCMS.Core/Resolvers/Setup/EntityVariantSetupResolver.cs @@ -5,27 +5,26 @@ using RapidCMS.Core.Models.Config; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Resolvers.Setup +namespace RapidCMS.Core.Resolvers.Setup; + +internal class EntityVariantSetupResolver : ISetupResolver { - internal class EntityVariantSetupResolver : ISetupResolver + public Task> ResolveSetupAsync(EntityVariantConfig config, CollectionSetup? collection = default) { - public Task> ResolveSetupAsync(EntityVariantConfig config, CollectionSetup? collection = default) + if (collection == null) { - if (collection == null) - { - throw new ArgumentNullException(nameof(collection)); - } + throw new ArgumentNullException(nameof(collection)); + } - if (config == default) - { - return Task.FromResult>(new ResolvedSetup(EntityVariantSetup.Undefined, true)); - } - else - { - return Task.FromResult>(new ResolvedSetup( - new EntityVariantSetup(config.Name, config.Icon, config.Type, AliasHelper.GetEntityVariantAlias(config.Type)), - true)); - } + if (config == default) + { + return Task.FromResult>(new ResolvedSetup(EntityVariantSetup.Undefined, true)); + } + else + { + return Task.FromResult>(new ResolvedSetup( + new EntityVariantSetup(config.Name, config.Icon, config.Type, AliasHelper.GetEntityVariantAlias(config.Type)), + true)); } } } diff --git a/src/RapidCMS.Core/Resolvers/Setup/FieldSetupResolver.cs b/src/RapidCMS.Core/Resolvers/Setup/FieldSetupResolver.cs index c1aca834..8c9388c2 100644 --- a/src/RapidCMS.Core/Resolvers/Setup/FieldSetupResolver.cs +++ b/src/RapidCMS.Core/Resolvers/Setup/FieldSetupResolver.cs @@ -5,65 +5,64 @@ using RapidCMS.Core.Models.Config; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Resolvers.Setup +namespace RapidCMS.Core.Resolvers.Setup; + +internal class FieldSetupResolver : ISetupResolver { - internal class FieldSetupResolver : ISetupResolver + private readonly IRepositoryTypeResolver _repositoryTypeResolver; + + public FieldSetupResolver(IRepositoryTypeResolver repositoryTypeResolver) { - private readonly IRepositoryTypeResolver _repositoryTypeResolver; + _repositoryTypeResolver = repositoryTypeResolver; + } - public FieldSetupResolver(IRepositoryTypeResolver repositoryTypeResolver) + public Task> ResolveSetupAsync(FieldConfig config, CollectionSetup? collection = default) + { + if (collection == null) { - _repositoryTypeResolver = repositoryTypeResolver; + throw new ArgumentNullException(nameof(collection)); } - public Task> ResolveSetupAsync(FieldConfig config, CollectionSetup? collection = default) + var setup = config switch { - if (collection == null) - { - throw new ArgumentNullException(nameof(collection)); - } - - var setup = config switch - { - _ when config.EditorType == EditorType.Custom && config.Property != null => (FieldSetup)new CustomPropertyFieldSetup(config, config.CustomType!), - _ when config.EditorType != EditorType.None && config.Property != null => (FieldSetup)new PropertyFieldSetup(config), - _ when config.DisplayType != DisplayType.None && config.Property != null => (FieldSetup)new ExpressionFieldSetup(config, config.Property), - _ when config.DisplayType == DisplayType.Custom && config.Expression != null => (FieldSetup)new CustomExpressionFieldSetup(config, config.Expression, config.CustomType!), - _ when config.DisplayType != DisplayType.None && config.Expression != null => (FieldSetup)new ExpressionFieldSetup(config, config.Expression), - _ => throw new InvalidOperationException() - }; + _ when config.EditorType == EditorType.Custom && config.Property != null => (FieldSetup)new CustomPropertyFieldSetup(config, config.CustomType!), + _ when config.EditorType != EditorType.None && config.Property != null => (FieldSetup)new PropertyFieldSetup(config), + _ when config.DisplayType != DisplayType.None && config.Property != null => (FieldSetup)new ExpressionFieldSetup(config, config.Property), + _ when config.DisplayType == DisplayType.Custom && config.Expression != null => (FieldSetup)new CustomExpressionFieldSetup(config, config.Expression, config.CustomType!), + _ when config.DisplayType != DisplayType.None && config.Expression != null => (FieldSetup)new ExpressionFieldSetup(config, config.Expression), + _ => throw new InvalidOperationException() + }; - if (config.Relation != null && setup is PropertyFieldSetup propertySetup) + if (config.Relation != null && setup is PropertyFieldSetup propertySetup) + { + propertySetup.Relation = config.Relation switch { - propertySetup.Relation = config.Relation switch + RepositoryRelationConfig collectionConfig => (RelationSetup)new RepositoryRelationSetup( + collectionConfig.RepositoryType == null ? null : _repositoryTypeResolver.GetAlias(collectionConfig.RepositoryType), + collectionConfig.CollectionAlias, + collectionConfig.RelatedEntityType!, + collectionConfig.IdProperty, + collectionConfig.DisplayProperties, + collectionConfig.IsRelationToMany) { - RepositoryRelationConfig collectionConfig => (RelationSetup)new RepositoryRelationSetup( - collectionConfig.RepositoryType == null ? null : _repositoryTypeResolver.GetAlias(collectionConfig.RepositoryType), - collectionConfig.CollectionAlias, - collectionConfig.RelatedEntityType!, - collectionConfig.IdProperty, - collectionConfig.DisplayProperties, - collectionConfig.IsRelationToMany) - { - RepositoryParentSelector = collectionConfig.RepositoryParentProperty, - EntityAsParent = collectionConfig.EntityAsParent, - RelatedElementsGetter = collectionConfig.RelatedElementsGetter - }, + RepositoryParentSelector = collectionConfig.RepositoryParentProperty, + EntityAsParent = collectionConfig.EntityAsParent, + RelatedElementsGetter = collectionConfig.RelatedElementsGetter + }, - DataProviderRelationConfig dataProviderConfig => (RelationSetup)new DataProviderRelationSetup( - dataProviderConfig.DataCollectionType, dataProviderConfig.Configuration), + DataProviderRelationConfig dataProviderConfig => (RelationSetup)new DataProviderRelationSetup( + dataProviderConfig.DataCollectionType, dataProviderConfig.Configuration), - RelationDataProviderRelationConfig dataProviderConfig => (RelationSetup)new RelationDataProviderRelationSetup( - dataProviderConfig.RelationDataCollectionType, dataProviderConfig.Configuration), + RelationDataProviderRelationConfig dataProviderConfig => (RelationSetup)new RelationDataProviderRelationSetup( + dataProviderConfig.RelationDataCollectionType, dataProviderConfig.Configuration), - ConcreteDataProviderRelationConfig concreteDataProviderConfig => (RelationSetup)new ConcreteDataProviderRelationSetup - (concreteDataProviderConfig.DataCollection), + ConcreteDataProviderRelationConfig concreteDataProviderConfig => (RelationSetup)new ConcreteDataProviderRelationSetup + (concreteDataProviderConfig.DataCollection), - _ => throw new InvalidOperationException("Invalid RelationConfig") - }; - } - - return Task.FromResult>(new ResolvedSetup(setup, true)); + _ => throw new InvalidOperationException("Invalid RelationConfig") + }; } + + return Task.FromResult>(new ResolvedSetup(setup, true)); } } diff --git a/src/RapidCMS.Core/Resolvers/Setup/GlobalEntityVariantSetupResolver.cs b/src/RapidCMS.Core/Resolvers/Setup/GlobalEntityVariantSetupResolver.cs index eb8ea78b..9a95c7d3 100644 --- a/src/RapidCMS.Core/Resolvers/Setup/GlobalEntityVariantSetupResolver.cs +++ b/src/RapidCMS.Core/Resolvers/Setup/GlobalEntityVariantSetupResolver.cs @@ -9,30 +9,29 @@ using RapidCMS.Core.Helpers; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Resolvers.Setup +namespace RapidCMS.Core.Resolvers.Setup; + +internal class GlobalEntityVariantSetupResolver : ISetupResolver { - internal class GlobalEntityVariantSetupResolver : ISetupResolver + private readonly IReadOnlyDictionary _types; + + public GlobalEntityVariantSetupResolver() { - private readonly IReadOnlyDictionary _types; + _types = typeof(IEntity).GetImplementingTypes().ToDictionary(x => AliasHelper.GetEntityVariantAlias(x)); + } - public GlobalEntityVariantSetupResolver() - { - _types = typeof(IEntity).GetImplementingTypes().ToDictionary(x => AliasHelper.GetEntityVariantAlias(x)); - } + public Task ResolveSetupAsync() + { + throw new NotImplementedException(); + } - public Task ResolveSetupAsync() + public Task ResolveSetupAsync(string alias) + { + if (!_types.TryGetValue(alias, out var type)) { - throw new NotImplementedException(); + throw new InvalidOperationException($"Cannot find type with alias {alias}."); } - public Task ResolveSetupAsync(string alias) - { - if (!_types.TryGetValue(alias, out var type)) - { - throw new InvalidOperationException($"Cannot find type with alias {alias}."); - } - - return Task.FromResult(new EntityVariantSetup(alias, default, type, alias)); - } + return Task.FromResult(new EntityVariantSetup(alias, default, type, alias)); } } diff --git a/src/RapidCMS.Core/Resolvers/Setup/ListSetupResolver.cs b/src/RapidCMS.Core/Resolvers/Setup/ListSetupResolver.cs index 8372d9d0..05a9c7db 100644 --- a/src/RapidCMS.Core/Resolvers/Setup/ListSetupResolver.cs +++ b/src/RapidCMS.Core/Resolvers/Setup/ListSetupResolver.cs @@ -8,49 +8,48 @@ using RapidCMS.Core.Models.Config; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Resolvers.Setup +namespace RapidCMS.Core.Resolvers.Setup; + +internal class ListSetupResolver : ISetupResolver { - internal class ListSetupResolver : ISetupResolver + private readonly ISetupResolver _paneSetupResolver; + private readonly ISetupResolver _buttonSetupResolver; + private readonly IConventionBasedResolver _conventionListConfigResolver; + + public ListSetupResolver( + ISetupResolver paneSetupResolver, + ISetupResolver buttonSetupResolver, + IConventionBasedResolver conventionListConfigResolver) + { + _paneSetupResolver = paneSetupResolver; + _buttonSetupResolver = buttonSetupResolver; + _conventionListConfigResolver = conventionListConfigResolver; + } + + public async Task> ResolveSetupAsync(ListConfig config, CollectionSetup? collection = default) { - private readonly ISetupResolver _paneSetupResolver; - private readonly ISetupResolver _buttonSetupResolver; - private readonly IConventionBasedResolver _conventionListConfigResolver; - - public ListSetupResolver( - ISetupResolver paneSetupResolver, - ISetupResolver buttonSetupResolver, - IConventionBasedResolver conventionListConfigResolver) + if (collection == null) { - _paneSetupResolver = paneSetupResolver; - _buttonSetupResolver = buttonSetupResolver; - _conventionListConfigResolver = conventionListConfigResolver; + throw new ArgumentNullException(nameof(collection)); } - public async Task> ResolveSetupAsync(ListConfig config, CollectionSetup? collection = default) + if (config is IIsConventionBased isConventionBasedConfig) { - if (collection == null) - { - throw new ArgumentNullException(nameof(collection)); - } - - if (config is IIsConventionBased isConventionBasedConfig) - { - config = await _conventionListConfigResolver.ResolveByConventionAsync(config.BaseType, isConventionBasedConfig.GetFeatures(), collection); - } - - var cacheable = true; - - var panes = (await _paneSetupResolver.ResolveSetupAsync(config.Panes, collection)).CheckIfCachable(ref cacheable).ToList(); - var buttons = (await _buttonSetupResolver.ResolveSetupAsync(config.Buttons, collection)).CheckIfCachable(ref cacheable).ToList(); - - return new ResolvedSetup(new ListSetup( - config.PageSize, - config.SearchBarVisible, - config.ReorderingAllowed, - config.ListEditorType, - config.EmptyVariantColumnVisibility, - panes, - buttons), cacheable); + config = await _conventionListConfigResolver.ResolveByConventionAsync(config.BaseType, isConventionBasedConfig.GetFeatures(), collection); } + + var cacheable = true; + + var panes = (await _paneSetupResolver.ResolveSetupAsync(config.Panes, collection)).CheckIfCachable(ref cacheable).ToList(); + var buttons = (await _buttonSetupResolver.ResolveSetupAsync(config.Buttons, collection)).CheckIfCachable(ref cacheable).ToList(); + + return new ResolvedSetup(new ListSetup( + config.PageSize, + config.SearchBarVisible, + config.ReorderingAllowed, + config.ListEditorType, + config.EmptyVariantColumnVisibility, + panes, + buttons), cacheable); } } diff --git a/src/RapidCMS.Core/Resolvers/Setup/NodeSetupResolver.cs b/src/RapidCMS.Core/Resolvers/Setup/NodeSetupResolver.cs index b99f9669..2d35561d 100644 --- a/src/RapidCMS.Core/Resolvers/Setup/NodeSetupResolver.cs +++ b/src/RapidCMS.Core/Resolvers/Setup/NodeSetupResolver.cs @@ -8,46 +8,45 @@ using RapidCMS.Core.Models.Config; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Resolvers.Setup +namespace RapidCMS.Core.Resolvers.Setup; + +internal class NodeSetupResolver : ISetupResolver { - internal class NodeSetupResolver : ISetupResolver + private readonly ISetupResolver _paneSetupResolver; + private readonly ISetupResolver _buttonSetupResolver; + private readonly IConventionBasedResolver _conventionNodeConfigResolver; + + public NodeSetupResolver( + ISetupResolver paneSetupResolver, + ISetupResolver buttonSetupResolver, + IConventionBasedResolver conventionNodeConfigResolver) + { + _paneSetupResolver = paneSetupResolver; + _buttonSetupResolver = buttonSetupResolver; + _conventionNodeConfigResolver = conventionNodeConfigResolver; + } + + public async Task> ResolveSetupAsync(NodeConfig config, CollectionSetup? collection = default) { - private readonly ISetupResolver _paneSetupResolver; - private readonly ISetupResolver _buttonSetupResolver; - private readonly IConventionBasedResolver _conventionNodeConfigResolver; - - public NodeSetupResolver( - ISetupResolver paneSetupResolver, - ISetupResolver buttonSetupResolver, - IConventionBasedResolver conventionNodeConfigResolver) + if (collection == null) { - _paneSetupResolver = paneSetupResolver; - _buttonSetupResolver = buttonSetupResolver; - _conventionNodeConfigResolver = conventionNodeConfigResolver; + throw new ArgumentNullException(nameof(collection)); } - public async Task> ResolveSetupAsync(NodeConfig config, CollectionSetup? collection = default) + if (config is IIsConventionBased isConventionBasedConfig) { - if (collection == null) - { - throw new ArgumentNullException(nameof(collection)); - } - - if (config is IIsConventionBased isConventionBasedConfig) - { - config = await _conventionNodeConfigResolver.ResolveByConventionAsync(config.BaseType, isConventionBasedConfig.GetFeatures(), collection); - } - - var cacheable = true; - - var panes = (await _paneSetupResolver.ResolveSetupAsync(config.Panes, collection)).CheckIfCachable(ref cacheable).ToList(); - var buttons = (await _buttonSetupResolver.ResolveSetupAsync(config.Buttons, collection)).CheckIfCachable(ref cacheable).ToList(); - - return new ResolvedSetup(new NodeSetup( - config.BaseType, - panes, - buttons), - cacheable); + config = await _conventionNodeConfigResolver.ResolveByConventionAsync(config.BaseType, isConventionBasedConfig.GetFeatures(), collection); } + + var cacheable = true; + + var panes = (await _paneSetupResolver.ResolveSetupAsync(config.Panes, collection)).CheckIfCachable(ref cacheable).ToList(); + var buttons = (await _buttonSetupResolver.ResolveSetupAsync(config.Buttons, collection)).CheckIfCachable(ref cacheable).ToList(); + + return new ResolvedSetup(new NodeSetup( + config.BaseType, + panes, + buttons), + cacheable); } } diff --git a/src/RapidCMS.Core/Resolvers/Setup/PageSetupResolver.cs b/src/RapidCMS.Core/Resolvers/Setup/PageSetupResolver.cs index 977e2ac2..14c98bed 100644 --- a/src/RapidCMS.Core/Resolvers/Setup/PageSetupResolver.cs +++ b/src/RapidCMS.Core/Resolvers/Setup/PageSetupResolver.cs @@ -8,84 +8,83 @@ using RapidCMS.Core.Models.Config; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Resolvers.Setup +namespace RapidCMS.Core.Resolvers.Setup; + +internal class PageSetupResolver : ISetupResolver { - internal class PageSetupResolver : ISetupResolver + private readonly ICmsConfig _cmsConfig; + private readonly ISetupResolver _typeRegistrationSetupResolver; + private Dictionary _pageMap { get; set; } = new Dictionary(); + private readonly Dictionary _cache = new Dictionary(); + + public PageSetupResolver( + ICmsConfig cmsConfig, + ISetupResolver typeRegistrationSetupResolver) { - private readonly ICmsConfig _cmsConfig; - private readonly ISetupResolver _typeRegistrationSetupResolver; - private Dictionary _pageMap { get; set; } = new Dictionary(); - private readonly Dictionary _cache = new Dictionary(); + _cmsConfig = cmsConfig; + _typeRegistrationSetupResolver = typeRegistrationSetupResolver; - public PageSetupResolver( - ICmsConfig cmsConfig, - ISetupResolver typeRegistrationSetupResolver) - { - _cmsConfig = cmsConfig; - _typeRegistrationSetupResolver = typeRegistrationSetupResolver; + Initialize(); + } - Initialize(); - } + private void Initialize() + { + MapPages(_cmsConfig.CollectionsAndPages); - private void Initialize() + void MapPages(IEnumerable elements) { - MapPages(_cmsConfig.CollectionsAndPages); - - void MapPages(IEnumerable elements) + foreach (var page in elements.OfType()) { - foreach (var page in elements.OfType()) + if (!_pageMap.TryAdd(page.Alias, page)) { - if (!_pageMap.TryAdd(page.Alias, page)) - { - throw new InvalidOperationException($"Duplicate page alias '{page.Alias}' not allowed."); - } + throw new InvalidOperationException($"Duplicate page alias '{page.Alias}' not allowed."); } + } - foreach (var collection in elements.OfType().Where(col => col is not ReferencedCollectionConfig)) + foreach (var collection in elements.OfType().Where(col => col is not ReferencedCollectionConfig)) + { + var subElements = collection.CollectionsAndPages; + if (subElements.Any()) { - var subElements = collection.CollectionsAndPages; - if (subElements.Any()) - { - MapPages(subElements); - } + MapPages(subElements); } } } + } - Task ISetupResolver.ResolveSetupAsync() + Task ISetupResolver.ResolveSetupAsync() + { + throw new InvalidOperationException("Cannot resolve page without alias."); + } + + async Task ISetupResolver.ResolveSetupAsync(string alias) + { + if (_cache.TryGetValue(alias, out var pageSetup)) { - throw new InvalidOperationException("Cannot resolve page without alias."); + return pageSetup; } - async Task ISetupResolver.ResolveSetupAsync(string alias) + if (!_pageMap.TryGetValue(alias, out var config)) { - if (_cache.TryGetValue(alias, out var pageSetup)) - { - return pageSetup; - } - - if (!_pageMap.TryGetValue(alias, out var config)) - { - throw new InvalidOperationException($"Cannot find page with alias {alias}."); - } - - var cacheable = true; + throw new InvalidOperationException($"Cannot find page with alias {alias}."); + } - pageSetup = new PageSetup - { - Name = config.Name, - Alias = config.Alias, - Icon = config.Icon, - Color = config.Color, - Sections = (await _typeRegistrationSetupResolver.ResolveSetupAsync(config.SectionRegistrations)).CheckIfCachable(ref cacheable).ToList() - }; + var cacheable = true; - if (cacheable) - { - _cache[alias] = pageSetup; - } + pageSetup = new PageSetup + { + Name = config.Name, + Alias = config.Alias, + Icon = config.Icon, + Color = config.Color, + Sections = (await _typeRegistrationSetupResolver.ResolveSetupAsync(config.SectionRegistrations)).CheckIfCachable(ref cacheable).ToList() + }; - return pageSetup; + if (cacheable) + { + _cache[alias] = pageSetup; } + + return pageSetup; } } diff --git a/src/RapidCMS.Core/Resolvers/Setup/PaneSetupResolver.cs b/src/RapidCMS.Core/Resolvers/Setup/PaneSetupResolver.cs index 881a392d..bde0d56f 100644 --- a/src/RapidCMS.Core/Resolvers/Setup/PaneSetupResolver.cs +++ b/src/RapidCMS.Core/Resolvers/Setup/PaneSetupResolver.cs @@ -6,51 +6,50 @@ using RapidCMS.Core.Models.Config; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Resolvers.Setup +namespace RapidCMS.Core.Resolvers.Setup; + +internal class PaneSetupResolver : ISetupResolver { - internal class PaneSetupResolver : ISetupResolver + private readonly ISetupResolver _buttonSetupResolver; + private readonly ISetupResolver _fieldSetupResolver; + private readonly ISetupResolver _subCollectionSetupResolver; + private readonly ISetupResolver _relatedCollectionSetupResolver; + + public PaneSetupResolver( + ISetupResolver buttonSetupResolver, + ISetupResolver fieldSetupResolver, + ISetupResolver subCollectionSetupResolver, + ISetupResolver relatedCollectionSetupResolver) { - private readonly ISetupResolver _buttonSetupResolver; - private readonly ISetupResolver _fieldSetupResolver; - private readonly ISetupResolver _subCollectionSetupResolver; - private readonly ISetupResolver _relatedCollectionSetupResolver; + _buttonSetupResolver = buttonSetupResolver; + _fieldSetupResolver = fieldSetupResolver; + _subCollectionSetupResolver = subCollectionSetupResolver; + _relatedCollectionSetupResolver = relatedCollectionSetupResolver; + } - public PaneSetupResolver( - ISetupResolver buttonSetupResolver, - ISetupResolver fieldSetupResolver, - ISetupResolver subCollectionSetupResolver, - ISetupResolver relatedCollectionSetupResolver) + public async Task> ResolveSetupAsync(PaneConfig config, CollectionSetup? collection = default) + { + if (collection == null) { - _buttonSetupResolver = buttonSetupResolver; - _fieldSetupResolver = fieldSetupResolver; - _subCollectionSetupResolver = subCollectionSetupResolver; - _relatedCollectionSetupResolver = relatedCollectionSetupResolver; + throw new ArgumentNullException(nameof(collection)); } - public async Task> ResolveSetupAsync(PaneConfig config, CollectionSetup? collection = default) - { - if (collection == null) - { - throw new ArgumentNullException(nameof(collection)); - } - - var cacheable = true; + var cacheable = true; - var buttons = (await _buttonSetupResolver.ResolveSetupAsync(config.Buttons, collection)).CheckIfCachable(ref cacheable).ToList(); - var fields = (await _fieldSetupResolver.ResolveSetupAsync(config.Fields, collection)).CheckIfCachable(ref cacheable).ToList(); - var subCollectionLists = (await _subCollectionSetupResolver.ResolveSetupAsync(config.SubCollectionLists, collection)).CheckIfCachable(ref cacheable).ToList(); - var relatedCollectionLists = (await _relatedCollectionSetupResolver.ResolveSetupAsync(config.RelatedCollectionLists, collection)).CheckIfCachable(ref cacheable).ToList(); + var buttons = (await _buttonSetupResolver.ResolveSetupAsync(config.Buttons, collection)).CheckIfCachable(ref cacheable).ToList(); + var fields = (await _fieldSetupResolver.ResolveSetupAsync(config.Fields, collection)).CheckIfCachable(ref cacheable).ToList(); + var subCollectionLists = (await _subCollectionSetupResolver.ResolveSetupAsync(config.SubCollectionLists, collection)).CheckIfCachable(ref cacheable).ToList(); + var relatedCollectionLists = (await _relatedCollectionSetupResolver.ResolveSetupAsync(config.RelatedCollectionLists, collection)).CheckIfCachable(ref cacheable).ToList(); - return new ResolvedSetup(new PaneSetup( - config.CustomType, - config.Label, - config.IsVisible, - config.VariantType, - buttons, - fields, - subCollectionLists, - relatedCollectionLists), - cacheable); - } + return new ResolvedSetup(new PaneSetup( + config.CustomType, + config.Label, + config.IsVisible, + config.VariantType, + buttons, + fields, + subCollectionLists, + relatedCollectionLists), + cacheable); } } diff --git a/src/RapidCMS.Core/Resolvers/Setup/PluginTreeElementsSetupResolver.cs b/src/RapidCMS.Core/Resolvers/Setup/PluginTreeElementsSetupResolver.cs index 8d7ef6d3..0decd2af 100644 --- a/src/RapidCMS.Core/Resolvers/Setup/PluginTreeElementsSetupResolver.cs +++ b/src/RapidCMS.Core/Resolvers/Setup/PluginTreeElementsSetupResolver.cs @@ -4,14 +4,13 @@ using RapidCMS.Core.Abstractions.Resolvers; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Resolvers.Setup +namespace RapidCMS.Core.Resolvers.Setup; + +internal class PluginTreeElementsSetupResolver : ISetupResolver, IPlugin> { - internal class PluginTreeElementsSetupResolver : ISetupResolver, IPlugin> + public async Task>> ResolveSetupAsync(IPlugin config, CollectionSetup? collection = null) { - public async Task>> ResolveSetupAsync(IPlugin config, CollectionSetup? collection = null) - { - return new ResolvedSetup>(await config.GetTreeElementsAsync(), false); + return new ResolvedSetup>(await config.GetTreeElementsAsync(), false); - } } } diff --git a/src/RapidCMS.Core/Resolvers/Setup/RelatedCollectionListSetupResolver.cs b/src/RapidCMS.Core/Resolvers/Setup/RelatedCollectionListSetupResolver.cs index 1cd75688..ab8019f1 100644 --- a/src/RapidCMS.Core/Resolvers/Setup/RelatedCollectionListSetupResolver.cs +++ b/src/RapidCMS.Core/Resolvers/Setup/RelatedCollectionListSetupResolver.cs @@ -4,23 +4,22 @@ using RapidCMS.Core.Models.Config; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Resolvers.Setup +namespace RapidCMS.Core.Resolvers.Setup; + +internal class RelatedCollectionListSetupResolver : CollectionListSetupResolverBase, ISetupResolver { - internal class RelatedCollectionListSetupResolver : CollectionListSetupResolverBase, ISetupResolver + public RelatedCollectionListSetupResolver(Lazy> setupResolver) : base(setupResolver) { - public RelatedCollectionListSetupResolver(Lazy> setupResolver) : base(setupResolver) - { - } + } - public async Task> ResolveSetupAsync(CollectionListConfig config, CollectionSetup? collection = default) - { - var usageType = await GetUsageTypeAsync(config, collection); + public async Task> ResolveSetupAsync(CollectionListConfig config, CollectionSetup? collection = default) + { + var usageType = await GetUsageTypeAsync(config, collection); - return new ResolvedSetup( - new RelatedCollectionListSetup(config.Index, config.CollectionAlias) - { - SupportsUsageType = usageType - }, true); - } + return new ResolvedSetup( + new RelatedCollectionListSetup(config.Index, config.CollectionAlias) + { + SupportsUsageType = usageType + }, true); } } diff --git a/src/RapidCMS.Core/Resolvers/Setup/SubCollectionListSetupResolver.cs b/src/RapidCMS.Core/Resolvers/Setup/SubCollectionListSetupResolver.cs index f812424a..42214367 100644 --- a/src/RapidCMS.Core/Resolvers/Setup/SubCollectionListSetupResolver.cs +++ b/src/RapidCMS.Core/Resolvers/Setup/SubCollectionListSetupResolver.cs @@ -4,23 +4,22 @@ using RapidCMS.Core.Models.Config; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Resolvers.Setup +namespace RapidCMS.Core.Resolvers.Setup; + +internal class SubCollectionListSetupResolver : CollectionListSetupResolverBase, ISetupResolver { - internal class SubCollectionListSetupResolver : CollectionListSetupResolverBase, ISetupResolver + public SubCollectionListSetupResolver(Lazy> setupResolver) : base(setupResolver) { - public SubCollectionListSetupResolver(Lazy> setupResolver) : base(setupResolver) - { - } + } - public async Task> ResolveSetupAsync(CollectionListConfig config, CollectionSetup? collection = default) - { - var usageType = await GetUsageTypeAsync(config, collection); + public async Task> ResolveSetupAsync(CollectionListConfig config, CollectionSetup? collection = default) + { + var usageType = await GetUsageTypeAsync(config, collection); - return new ResolvedSetup( - new SubCollectionListSetup(config!.Index, config.CollectionAlias) - { - SupportsUsageType = usageType - }, true); - } + return new ResolvedSetup( + new SubCollectionListSetup(config!.Index, config.CollectionAlias) + { + SupportsUsageType = usageType + }, true); } } diff --git a/src/RapidCMS.Core/Resolvers/Setup/TreeElementSetupResolver.cs b/src/RapidCMS.Core/Resolvers/Setup/TreeElementSetupResolver.cs index 68c2501c..eb4b45af 100644 --- a/src/RapidCMS.Core/Resolvers/Setup/TreeElementSetupResolver.cs +++ b/src/RapidCMS.Core/Resolvers/Setup/TreeElementSetupResolver.cs @@ -7,29 +7,28 @@ using RapidCMS.Core.Models.Config; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Resolvers.Setup +namespace RapidCMS.Core.Resolvers.Setup; + +internal class TreeElementSetupResolver : ISetupResolver, IEnumerable> { - internal class TreeElementSetupResolver : ISetupResolver, IEnumerable> + public Task>> ResolveSetupAsync(IEnumerable config, CollectionSetup? collection = default) { - public Task>> ResolveSetupAsync(IEnumerable config, CollectionSetup? collection = default) - { - return Task.FromResult< IResolvedSetup>>( - new ResolvedSetup>( - config.Select(corp => + return Task.FromResult< IResolvedSetup>>( + new ResolvedSetup>( + config.Select(corp => + { + var type = corp switch { - var type = corp switch - { - IPageConfig page => PageType.Page, - _ => PageType.Collection - }; + IPageConfig page => PageType.Page, + _ => PageType.Collection + }; - return new TreeElementSetup(corp.Alias, corp.Name, type) - { - RootVisibility = (corp as CollectionConfig)?.TreeView?.RootVisibility ?? default - }; + return new TreeElementSetup(corp.Alias, corp.Name, type) + { + RootVisibility = (corp as CollectionConfig)?.TreeView?.RootVisibility ?? default + }; - }) ?? Enumerable.Empty(), - true)); - } + }) ?? Enumerable.Empty(), + true)); } } diff --git a/src/RapidCMS.Core/Resolvers/Setup/TreeElementsSetupResolver.cs b/src/RapidCMS.Core/Resolvers/Setup/TreeElementsSetupResolver.cs index be1d8ae9..ec1e910d 100644 --- a/src/RapidCMS.Core/Resolvers/Setup/TreeElementsSetupResolver.cs +++ b/src/RapidCMS.Core/Resolvers/Setup/TreeElementsSetupResolver.cs @@ -7,45 +7,44 @@ using RapidCMS.Core.Abstractions.Resolvers; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Resolvers.Setup +namespace RapidCMS.Core.Resolvers.Setup; + +internal class TreeElementsSetupResolver : ISetupResolver> { - internal class TreeElementsSetupResolver : ISetupResolver> + private readonly ICmsConfig _cmsConfig; + private readonly ISetupResolver, IEnumerable> _treeElementResolver; + private readonly ISetupResolver, IPlugin> _pluginTreeElementResolver; + private readonly IEnumerable _plugins; + + public TreeElementsSetupResolver(ICmsConfig cmsConfig, + ISetupResolver, IEnumerable> treeElementResolver, + ISetupResolver, IPlugin> pluginTreeElementResolver, + IEnumerable plugins) { - private readonly ICmsConfig _cmsConfig; - private readonly ISetupResolver, IEnumerable> _treeElementResolver; - private readonly ISetupResolver, IPlugin> _pluginTreeElementResolver; - private readonly IEnumerable _plugins; - - public TreeElementsSetupResolver(ICmsConfig cmsConfig, - ISetupResolver, IEnumerable> treeElementResolver, - ISetupResolver, IPlugin> pluginTreeElementResolver, - IEnumerable plugins) - { - _cmsConfig = cmsConfig; - _treeElementResolver = treeElementResolver; - _pluginTreeElementResolver = pluginTreeElementResolver; - _plugins = plugins; - } + _cmsConfig = cmsConfig; + _treeElementResolver = treeElementResolver; + _pluginTreeElementResolver = pluginTreeElementResolver; + _plugins = plugins; + } - async Task> ISetupResolver>.ResolveSetupAsync() - { - var results = new List(); + async Task> ISetupResolver>.ResolveSetupAsync() + { + var results = new List(); - foreach (var plugin in _plugins) - { - var treeElements = await _pluginTreeElementResolver.ResolveSetupAsync(plugin); + foreach (var plugin in _plugins) + { + var treeElements = await _pluginTreeElementResolver.ResolveSetupAsync(plugin); - results.AddRange(treeElements.Setup); - } + results.AddRange(treeElements.Setup); + } - results.AddRange((await _treeElementResolver.ResolveSetupAsync(_cmsConfig.CollectionsAndPages?.Skip(1) ?? Enumerable.Empty())).Setup); + results.AddRange((await _treeElementResolver.ResolveSetupAsync(_cmsConfig.CollectionsAndPages?.Skip(1) ?? Enumerable.Empty())).Setup); - return results; - } + return results; + } - Task> ISetupResolver>.ResolveSetupAsync(string alias) - { - throw new InvalidOperationException("Cannot resolve root collections with alias."); - } + Task> ISetupResolver>.ResolveSetupAsync(string alias) + { + throw new InvalidOperationException("Cannot resolve root collections with alias."); } } diff --git a/src/RapidCMS.Core/Resolvers/Setup/TreeViewSetupResolver.cs b/src/RapidCMS.Core/Resolvers/Setup/TreeViewSetupResolver.cs index 90504964..4b5ae380 100644 --- a/src/RapidCMS.Core/Resolvers/Setup/TreeViewSetupResolver.cs +++ b/src/RapidCMS.Core/Resolvers/Setup/TreeViewSetupResolver.cs @@ -3,19 +3,18 @@ using RapidCMS.Core.Models.Config; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Resolvers.Setup +namespace RapidCMS.Core.Resolvers.Setup; + +internal class TreeViewSetupResolver : ISetupResolver { - internal class TreeViewSetupResolver : ISetupResolver + public Task> ResolveSetupAsync(TreeViewConfig config, CollectionSetup? collection = default) { - public Task> ResolveSetupAsync(TreeViewConfig config, CollectionSetup? collection = default) - { - return Task.FromResult>(new ResolvedSetup(new TreeViewSetup( - config.EntityVisibilty, - config.RootVisibility, - config.DefaultOpenEntities, - config.DefaultOpenCollections, - config.Name), - true)); - } + return Task.FromResult>(new ResolvedSetup(new TreeViewSetup( + config.EntityVisibilty, + config.RootVisibility, + config.DefaultOpenEntities, + config.DefaultOpenCollections, + config.Name), + true)); } } diff --git a/src/RapidCMS.Core/Resolvers/Setup/TypeRegistrationSetupResolver.cs b/src/RapidCMS.Core/Resolvers/Setup/TypeRegistrationSetupResolver.cs index f5eed482..5d91f9f7 100644 --- a/src/RapidCMS.Core/Resolvers/Setup/TypeRegistrationSetupResolver.cs +++ b/src/RapidCMS.Core/Resolvers/Setup/TypeRegistrationSetupResolver.cs @@ -3,21 +3,20 @@ using RapidCMS.Core.Models.Config; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Resolvers.Setup +namespace RapidCMS.Core.Resolvers.Setup; + +internal class TypeRegistrationSetupResolver : ISetupResolver { - internal class TypeRegistrationSetupResolver : ISetupResolver + public Task> ResolveSetupAsync(CustomTypeRegistrationConfig config, CollectionSetup? collection = default) { - public Task> ResolveSetupAsync(CustomTypeRegistrationConfig config, CollectionSetup? collection = default) - { - return Task.FromResult>( - new ResolvedSetup( - new TypeRegistrationSetup - { - Type = config.Type == typeof(CollectionConfig) ? typeof(CollectionSetup) : config.Type, - Alias = config.Alias, - Parameters = config.Parameters - }, - true)); - } + return Task.FromResult>( + new ResolvedSetup( + new TypeRegistrationSetup + { + Type = config.Type == typeof(CollectionConfig) ? typeof(CollectionSetup) : config.Type, + Alias = config.Alias, + Parameters = config.Parameters + }, + true)); } } diff --git a/src/RapidCMS.Core/Resolvers/UI/BaseUIResolver.cs b/src/RapidCMS.Core/Resolvers/UI/BaseUIResolver.cs index baf18d7d..e4bc4477 100644 --- a/src/RapidCMS.Core/Resolvers/UI/BaseUIResolver.cs +++ b/src/RapidCMS.Core/Resolvers/UI/BaseUIResolver.cs @@ -14,121 +14,120 @@ using RapidCMS.Core.Navigation; using RapidCMS.Core.Providers; -namespace RapidCMS.Core.Resolvers.UI +namespace RapidCMS.Core.Resolvers.UI; + +internal class BaseUIResolver { - internal class BaseUIResolver + private readonly IDataProviderResolver _dataProviderResolver; + private readonly IButtonActionHandlerResolver _buttonActionHandlerResolver; + protected readonly IAuthService _authService; + private readonly INavigationStateProvider _navigationStateProvider; + + protected BaseUIResolver( + IDataProviderResolver dataProviderResolver, + IButtonActionHandlerResolver buttonActionHandlerResolver, + IAuthService authService, + INavigationStateProvider navigationStateProvider) { - private readonly IDataProviderResolver _dataProviderResolver; - private readonly IButtonActionHandlerResolver _buttonActionHandlerResolver; - protected readonly IAuthService _authService; - private readonly INavigationStateProvider _navigationStateProvider; - - protected BaseUIResolver( - IDataProviderResolver dataProviderResolver, - IButtonActionHandlerResolver buttonActionHandlerResolver, - IAuthService authService, - INavigationStateProvider navigationStateProvider) - { - _dataProviderResolver = dataProviderResolver; - _buttonActionHandlerResolver = buttonActionHandlerResolver; - _authService = authService; - _navigationStateProvider = navigationStateProvider; - } + _dataProviderResolver = dataProviderResolver; + _buttonActionHandlerResolver = buttonActionHandlerResolver; + _authService = authService; + _navigationStateProvider = navigationStateProvider; + } - protected async Task> GetButtonsAsync(IEnumerable buttons, FormEditContext editContext) - { - return await buttons - .GetAllButtons() - .SelectNotNullAsync(async button => - { - var handler = _buttonActionHandlerResolver.GetButtonActionHandler(button); - if (handler.IsCompatible(button, editContext) && - await _authService.IsUserAuthorizedAsync(editContext, button)) - { - return new ButtonUI(handler, button, editContext); - } - else - { - return default; - } - }) - .ToListAsync(); - } - - protected internal async Task GetSectionUIAsync(PaneSetup pane, FormEditContext editContext, NavigationState navigationState) - { - var fields = await pane.Fields.ToListAsync(async field => + protected async Task> GetButtonsAsync(IEnumerable buttons, FormEditContext editContext) + { + return await buttons + .GetAllButtons() + .SelectNotNullAsync(async button => { - var dataProvider = await _dataProviderResolver.GetDataProviderAsync(field); - if (dataProvider != null) + var handler = _buttonActionHandlerResolver.GetButtonActionHandler(button); + if (handler.IsCompatible(button, editContext) && + await _authService.IsUserAuthorizedAsync(editContext, button)) { - editContext.DataProviders.Add(dataProvider); + return new ButtonUI(handler, button, editContext); } - - return (index: field.Index, element: (ElementUI)GetField(field, dataProvider)); - }); - - var subCollections = pane.SubCollectionLists - .Where(subCollection => subCollection.SupportsUsageType.FindSupportedUsageType(editContext.UsageType) > UsageType.None) - .Select(subCollection => + else { - var parentPath = ParentPath.AddLevel(editContext.Parent?.GetParentPath(), editContext.RepositoryAlias, editContext.Entity.Id!); - - // TODO: this does not read back the state (needed when nested states are saved in url) - var nestedState = new NavigationState( - subCollection.CollectionAlias, - parentPath, - subCollection.SupportsUsageType.FindSupportedUsageType(editContext.UsageType) | UsageType.List); + return default; + } + }) + .ToListAsync(); + } - _navigationStateProvider.NestNavigationState(navigationState, nestedState); + protected internal async Task GetSectionUIAsync(PaneSetup pane, FormEditContext editContext, NavigationState navigationState) + { + var fields = await pane.Fields.ToListAsync(async field => + { + var dataProvider = await _dataProviderResolver.GetDataProviderAsync(field); + if (dataProvider != null) + { + editContext.DataProviders.Add(dataProvider); + } - return (index: subCollection.Index, element: (ElementUI)new SubCollectionUI(subCollection, nestedState)); - }); + return (index: field.Index, element: (ElementUI)GetField(field, dataProvider)); + }); - var relatedCollections = pane.RelatedCollectionLists - .Where(relatedCollection => relatedCollection.SupportsUsageType.FindSupportedUsageType(editContext.UsageType) > UsageType.None) - .Select(relatedCollection => - { - var parentPath = ParentPath.AddLevel(editContext.Parent?.GetParentPath(), editContext.RepositoryAlias, editContext.Entity.Id!); + var subCollections = pane.SubCollectionLists + .Where(subCollection => subCollection.SupportsUsageType.FindSupportedUsageType(editContext.UsageType) > UsageType.None) + .Select(subCollection => + { + var parentPath = ParentPath.AddLevel(editContext.Parent?.GetParentPath(), editContext.RepositoryAlias, editContext.Entity.Id!); - // TODO: this does not read back the state (needed when nested states are saved in url) - var nestedState = new NavigationState( - relatedCollection.CollectionAlias, - parentPath, - null, - new RelatedEntity(editContext), - relatedCollection.SupportsUsageType.FindSupportedUsageType(editContext.UsageType) | UsageType.List, - PageType.Collection); + // TODO: this does not read back the state (needed when nested states are saved in url) + var nestedState = new NavigationState( + subCollection.CollectionAlias, + parentPath, + subCollection.SupportsUsageType.FindSupportedUsageType(editContext.UsageType) | UsageType.List); - _navigationStateProvider.NestNavigationState(navigationState, nestedState); + _navigationStateProvider.NestNavigationState(navigationState, nestedState); - return (index: relatedCollection.Index, element: (ElementUI)new RelatedCollectionUI(relatedCollection, nestedState)); - }); + return (index: subCollection.Index, element: (ElementUI)new SubCollectionUI(subCollection, nestedState)); + }); - return new SectionUI(pane.IsVisible) - { - Buttons = await GetButtonsAsync(pane.Buttons, editContext), - CustomType = pane.CustomType, - Label = pane.Label, - - Elements = fields - .Union(subCollections) - .Union(relatedCollections) - .OrderBy(x => x.index) - .ToList(x => x.element) - }; - } - - protected static FieldUI GetField(FieldSetup field, FormDataProvider? dataProvider) - => field switch + var relatedCollections = pane.RelatedCollectionLists + .Where(relatedCollection => relatedCollection.SupportsUsageType.FindSupportedUsageType(editContext.UsageType) > UsageType.None) + .Select(relatedCollection => { - CustomExpressionFieldSetup x => new CustomExpressionFieldUI(x), - ExpressionFieldSetup x => new ExpressionFieldUI(x), + var parentPath = ParentPath.AddLevel(editContext.Parent?.GetParentPath(), editContext.RepositoryAlias, editContext.Entity.Id!); + + // TODO: this does not read back the state (needed when nested states are saved in url) + var nestedState = new NavigationState( + relatedCollection.CollectionAlias, + parentPath, + null, + new RelatedEntity(editContext), + relatedCollection.SupportsUsageType.FindSupportedUsageType(editContext.UsageType) | UsageType.List, + PageType.Collection); - CustomPropertyFieldSetup x => new CustomPropertyFieldUI(x, dataProvider), - PropertyFieldSetup x => new PropertyFieldUI(x, dataProvider), + _navigationStateProvider.NestNavigationState(navigationState, nestedState); - _ => throw new InvalidOperationException($"Cannot return FieldUI for given field of type {field?.GetType()}") - }; + return (index: relatedCollection.Index, element: (ElementUI)new RelatedCollectionUI(relatedCollection, nestedState)); + }); + + return new SectionUI(pane.IsVisible) + { + Buttons = await GetButtonsAsync(pane.Buttons, editContext), + CustomType = pane.CustomType, + Label = pane.Label, + + Elements = fields + .Union(subCollections) + .Union(relatedCollections) + .OrderBy(x => x.index) + .ToList(x => x.element) + }; } + + protected static FieldUI GetField(FieldSetup field, FormDataProvider? dataProvider) + => field switch + { + CustomExpressionFieldSetup x => new CustomExpressionFieldUI(x), + ExpressionFieldSetup x => new ExpressionFieldUI(x), + + CustomPropertyFieldSetup x => new CustomPropertyFieldUI(x, dataProvider), + PropertyFieldSetup x => new PropertyFieldUI(x, dataProvider), + + _ => throw new InvalidOperationException($"Cannot return FieldUI for given field of type {field?.GetType()}") + }; } diff --git a/src/RapidCMS.Core/Resolvers/UI/ListUIResolver.cs b/src/RapidCMS.Core/Resolvers/UI/ListUIResolver.cs index 585e1bc3..8f03dd7d 100644 --- a/src/RapidCMS.Core/Resolvers/UI/ListUIResolver.cs +++ b/src/RapidCMS.Core/Resolvers/UI/ListUIResolver.cs @@ -13,101 +13,100 @@ using RapidCMS.Core.Models.UI; using RapidCMS.Core.Navigation; -namespace RapidCMS.Core.Resolvers.UI -{ - internal class ListUIResolver : BaseUIResolver, IListUIResolver - { - private readonly ListSetup _list; - private readonly IDataViewResolver _dataViewResolver; - private readonly Dictionary> _fieldsPerType = new Dictionary>(); +namespace RapidCMS.Core.Resolvers.UI; - private readonly FieldUIEqualityComparer _equalityComparer = new FieldUIEqualityComparer(); +internal class ListUIResolver : BaseUIResolver, IListUIResolver +{ + private readonly ListSetup _list; + private readonly IDataViewResolver _dataViewResolver; + private readonly Dictionary> _fieldsPerType = new Dictionary>(); - public ListUIResolver( - ListSetup list, - IDataProviderResolver dataProviderService, - IDataViewResolver dataViewResolver, - IButtonActionHandlerResolver buttonActionHandlerResolver, - INavigationStateProvider navigationStateProvider, - IAuthService authService) : base(dataProviderService, buttonActionHandlerResolver, authService, navigationStateProvider) - { - _list = list; - _dataViewResolver = dataViewResolver; + private readonly FieldUIEqualityComparer _equalityComparer = new FieldUIEqualityComparer(); - _list.Panes?.ForEach(pane => - { - if (!_fieldsPerType.ContainsKey(pane.VariantType) && pane.Fields != null) - { - _fieldsPerType.Add(pane.VariantType, pane.Fields.Select(x => GetField(x, default))); - } - }); - } + public ListUIResolver( + ListSetup list, + IDataProviderResolver dataProviderService, + IDataViewResolver dataViewResolver, + IButtonActionHandlerResolver buttonActionHandlerResolver, + INavigationStateProvider navigationStateProvider, + IAuthService authService) : base(dataProviderService, buttonActionHandlerResolver, authService, navigationStateProvider) + { + _list = list; + _dataViewResolver = dataViewResolver; - public async Task> GetButtonsForEditContextAsync(FormEditContext editContext) + _list.Panes?.ForEach(pane => { - if (_list.Buttons == null) + if (!_fieldsPerType.ContainsKey(pane.VariantType) && pane.Fields != null) { - return Enumerable.Empty(); + _fieldsPerType.Add(pane.VariantType, pane.Fields.Select(x => GetField(x, default))); } + }); + } - return await GetButtonsAsync(_list.Buttons, editContext); - } - - public ListUI GetListDetails() + public async Task> GetButtonsForEditContextAsync(FormEditContext editContext) + { + if (_list.Buttons == null) { - return new ListUI - { - CommonFields = _fieldsPerType.GetCommonValues(_equalityComparer).ToList(), - EmptyVariantColumnVisibility = _list.EmptyVariantColumnVisibility, - ListType = _list.ListType, - MaxUniqueFieldsInSingleEntity = _fieldsPerType.Max(x => x.Value.Count()), - PageSize = _list.PageSize ?? 1000, - SearchBarVisible = _list.SearchBarVisible ?? true, - Reorderable = _list.ReorderingAllowed ?? false, - SectionsHaveButtons = _list.Panes.Any(x => x.Buttons.Any()), - UniqueFields = _fieldsPerType.SelectMany(x => x.Value).Distinct(_equalityComparer).ToList() - }; + return Enumerable.Empty(); } - public async Task> GetSectionsForEditContextAsync(FormEditContext editContext, NavigationState navigationState) + return await GetButtonsAsync(_list.Buttons, editContext); + } + + public ListUI GetListDetails() + { + return new ListUI { - var type = editContext.Entity.GetType(); - return await _list.Panes - .Where(pane => pane.VariantType.IsSameTypeOrDerivedFrom(type)) - .ToListAsync(pane => GetSectionUIAsync(pane, editContext, navigationState)); - } + CommonFields = _fieldsPerType.GetCommonValues(_equalityComparer).ToList(), + EmptyVariantColumnVisibility = _list.EmptyVariantColumnVisibility, + ListType = _list.ListType, + MaxUniqueFieldsInSingleEntity = _fieldsPerType.Max(x => x.Value.Count()), + PageSize = _list.PageSize ?? 1000, + SearchBarVisible = _list.SearchBarVisible ?? true, + Reorderable = _list.ReorderingAllowed ?? false, + SectionsHaveButtons = _list.Panes.Any(x => x.Buttons.Any()), + UniqueFields = _fieldsPerType.SelectMany(x => x.Value).Distinct(_equalityComparer).ToList() + }; + } + + public async Task> GetSectionsForEditContextAsync(FormEditContext editContext, NavigationState navigationState) + { + var type = editContext.Entity.GetType(); + return await _list.Panes + .Where(pane => pane.VariantType.IsSameTypeOrDerivedFrom(type)) + .ToListAsync(pane => GetSectionUIAsync(pane, editContext, navigationState)); + } - public async Task?> GetTabsAsync(string collectionAlias) + public async Task?> GetTabsAsync(string collectionAlias) + { + var commonFields = _fieldsPerType.GetCommonValues(_equalityComparer).ToList(); + + var data = await _dataViewResolver.GetDataViewsAsync(collectionAlias); + return data.ToList(x => { - var commonFields = _fieldsPerType.GetCommonValues(_equalityComparer).ToList(); + SortBag? sortBag = null; - var data = await _dataViewResolver.GetDataViewsAsync(collectionAlias); - return data.ToList(x => + if (x.DefaultOrderBys != null) { - SortBag? sortBag = null; + var commonSortFields = commonFields.Select(f => ( + field: f, + orderBy: x.DefaultOrderBys.FirstOrDefault(d => + f.OrderByExpression?.Fingerprint == d.Key.Fingerprint || + (f.OrderByExpression == null && f.Property?.Fingerprint == d.Key.Fingerprint)) + .Value)); - if (x.DefaultOrderBys != null) - { - var commonSortFields = commonFields.Select(f => ( - field: f, - orderBy: x.DefaultOrderBys.FirstOrDefault(d => - f.OrderByExpression?.Fingerprint == d.Key.Fingerprint || - (f.OrderByExpression == null && f.Property?.Fingerprint == d.Key.Fingerprint)) - .Value)); + var defaultSorts = commonSortFields + .Where(x => x.orderBy != OrderByType.Disabled) + .Select(x => new KeyValuePair(x.field.Index, x.orderBy)); - var defaultSorts = commonSortFields - .Where(x => x.orderBy != OrderByType.Disabled) - .Select(x => new KeyValuePair(x.field.Index, x.orderBy)); - - sortBag = new SortBag(defaultSorts); - } + sortBag = new SortBag(defaultSorts); + } - return new TabUI(x.Id) - { - Label = x.Label, - DefaultSorts = sortBag - }; - }); - } + return new TabUI(x.Id) + { + Label = x.Label, + DefaultSorts = sortBag + }; + }); } } diff --git a/src/RapidCMS.Core/Resolvers/UI/NodeUIResolver.cs b/src/RapidCMS.Core/Resolvers/UI/NodeUIResolver.cs index 69bf13ae..4b97d98d 100644 --- a/src/RapidCMS.Core/Resolvers/UI/NodeUIResolver.cs +++ b/src/RapidCMS.Core/Resolvers/UI/NodeUIResolver.cs @@ -10,48 +10,47 @@ using RapidCMS.Core.Models.UI; using RapidCMS.Core.Navigation; -namespace RapidCMS.Core.Resolvers.UI +namespace RapidCMS.Core.Resolvers.UI; + +internal class NodeUIResolver : BaseUIResolver, INodeUIResolver { - internal class NodeUIResolver : BaseUIResolver, INodeUIResolver + private readonly NodeSetup _node; + private readonly INavigationStateProvider _navigationStateProvider; + + public NodeUIResolver( + NodeSetup node, + IDataProviderResolver dataProviderService, + IButtonActionHandlerResolver buttonActionHandlerResolver, + INavigationStateProvider navigationStateProvider, + IAuthService authService) : base(dataProviderService, buttonActionHandlerResolver, authService, navigationStateProvider) { - private readonly NodeSetup _node; - private readonly INavigationStateProvider _navigationStateProvider; - - public NodeUIResolver( - NodeSetup node, - IDataProviderResolver dataProviderService, - IButtonActionHandlerResolver buttonActionHandlerResolver, - INavigationStateProvider navigationStateProvider, - IAuthService authService) : base(dataProviderService, buttonActionHandlerResolver, authService, navigationStateProvider) - { - _node = node; - _navigationStateProvider = navigationStateProvider; - } + _node = node; + _navigationStateProvider = navigationStateProvider; + } - public async Task> GetButtonsForEditContextAsync(FormEditContext editContext) + public async Task> GetButtonsForEditContextAsync(FormEditContext editContext) + { + if (_node.Buttons == null) { - if (_node.Buttons == null) - { - return Enumerable.Empty(); - } - - return await GetButtonsAsync(_node.Buttons, editContext); + return Enumerable.Empty(); } - public async Task> GetSectionsForEditContextAsync(FormEditContext editContext, NavigationState navigationState) + return await GetButtonsAsync(_node.Buttons, editContext); + } + + public async Task> GetSectionsForEditContextAsync(FormEditContext editContext, NavigationState navigationState) + { + if (_node.Panes == null) { - if (_node.Panes == null) - { - return Enumerable.Empty(); - } - - var type = editContext.Entity.GetType(); - - var panes = await _node.Panes - .Where(pane => pane.VariantType.IsSameTypeOrBaseTypeOf(type)) - .ToListAsync(pane => GetSectionUIAsync(pane, editContext, navigationState)); - - return panes; + return Enumerable.Empty(); } + + var type = editContext.Entity.GetType(); + + var panes = await _node.Panes + .Where(pane => pane.VariantType.IsSameTypeOrBaseTypeOf(type)) + .ToListAsync(pane => GetSectionUIAsync(pane, editContext, navigationState)); + + return panes; } } diff --git a/src/RapidCMS.Core/Services/Auth/ServerSideAuthService.cs b/src/RapidCMS.Core/Services/Auth/ServerSideAuthService.cs index fb1598d4..2d51371e 100644 --- a/src/RapidCMS.Core/Services/Auth/ServerSideAuthService.cs +++ b/src/RapidCMS.Core/Services/Auth/ServerSideAuthService.cs @@ -11,72 +11,71 @@ using RapidCMS.Core.Forms; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Services.Auth +namespace RapidCMS.Core.Services.Auth; + +internal class ServerSideAuthService : IAuthService { - internal class ServerSideAuthService : IAuthService + private readonly IButtonActionHandlerResolver _buttonActionHandlerResolver; + private readonly IAuthorizationService _authorizationService; + private readonly AuthenticationStateProvider _authenticationStateProvider; + + public ServerSideAuthService( + IButtonActionHandlerResolver buttonActionHandlerResolver, + IAuthorizationService authorizationService, + AuthenticationStateProvider authenticationStateProvider) { - private readonly IButtonActionHandlerResolver _buttonActionHandlerResolver; - private readonly IAuthorizationService _authorizationService; - private readonly AuthenticationStateProvider _authenticationStateProvider; + _buttonActionHandlerResolver = buttonActionHandlerResolver; + _authorizationService = authorizationService; + _authenticationStateProvider = authenticationStateProvider; + } - public ServerSideAuthService( - IButtonActionHandlerResolver buttonActionHandlerResolver, - IAuthorizationService authorizationService, - AuthenticationStateProvider authenticationStateProvider) - { - _buttonActionHandlerResolver = buttonActionHandlerResolver; - _authorizationService = authorizationService; - _authenticationStateProvider = authenticationStateProvider; - } + public Task IsUserAuthorizedAsync(UsageType usageType, IEntity entity) + { + return IsUserAuthorizedAsync(Operations.GetOperationForUsageType(usageType), entity); + } - public Task IsUserAuthorizedAsync(UsageType usageType, IEntity entity) + public async Task EnsureAuthorizedUserAsync(UsageType usageType, IEntity entity) + { + if (!await IsUserAuthorizedAsync(usageType, entity)) { - return IsUserAuthorizedAsync(Operations.GetOperationForUsageType(usageType), entity); + throw new UnauthorizedAccessException(); } + } - public async Task EnsureAuthorizedUserAsync(UsageType usageType, IEntity entity) + public async Task IsUserAuthorizedAsync(OperationAuthorizationRequirement operation, IEntity entity) + { + var state = await _authenticationStateProvider.GetAuthenticationStateAsync(); + var user = state.User; + if (user == null) { - if (!await IsUserAuthorizedAsync(usageType, entity)) - { - throw new UnauthorizedAccessException(); - } + return false; } - public async Task IsUserAuthorizedAsync(OperationAuthorizationRequirement operation, IEntity entity) - { - var state = await _authenticationStateProvider.GetAuthenticationStateAsync(); - var user = state.User; - if (user == null) - { - return false; - } + var authorizationChallenge = await _authorizationService.AuthorizeAsync(user, entity, operation); - var authorizationChallenge = await _authorizationService.AuthorizeAsync(user, entity, operation); - - return authorizationChallenge.Succeeded; - } + return authorizationChallenge.Succeeded; + } - public async Task EnsureAuthorizedUserAsync(OperationAuthorizationRequirement operation, IEntity entity) + public async Task EnsureAuthorizedUserAsync(OperationAuthorizationRequirement operation, IEntity entity) + { + if (!await IsUserAuthorizedAsync(operation, entity)) { - if (!await IsUserAuthorizedAsync(operation, entity)) - { - throw new UnauthorizedAccessException(); - } + throw new UnauthorizedAccessException(); } + } - public Task IsUserAuthorizedAsync(FormEditContext editContext, ButtonSetup button) - { - var handler = _buttonActionHandlerResolver.GetButtonActionHandler(button); + public Task IsUserAuthorizedAsync(FormEditContext editContext, ButtonSetup button) + { + var handler = _buttonActionHandlerResolver.GetButtonActionHandler(button); - return IsUserAuthorizedAsync(handler.GetOperation(button, editContext), editContext.Entity); - } + return IsUserAuthorizedAsync(handler.GetOperation(button, editContext), editContext.Entity); + } - public async Task EnsureAuthorizedUserAsync(FormEditContext editContext, ButtonSetup button) + public async Task EnsureAuthorizedUserAsync(FormEditContext editContext, ButtonSetup button) + { + if (!await IsUserAuthorizedAsync(editContext, button)) { - if (!await IsUserAuthorizedAsync(editContext, button)) - { - throw new UnauthorizedAccessException(); - } + throw new UnauthorizedAccessException(); } } } diff --git a/src/RapidCMS.Core/Services/Auth/WebAssemblyAuthService.cs b/src/RapidCMS.Core/Services/Auth/WebAssemblyAuthService.cs index 6dfc03bc..728a6436 100644 --- a/src/RapidCMS.Core/Services/Auth/WebAssemblyAuthService.cs +++ b/src/RapidCMS.Core/Services/Auth/WebAssemblyAuthService.cs @@ -6,38 +6,37 @@ using RapidCMS.Core.Forms; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Services.Auth +namespace RapidCMS.Core.Services.Auth; + +internal class WebAssemblyAuthService : IAuthService { - internal class WebAssemblyAuthService : IAuthService + public Task EnsureAuthorizedUserAsync(UsageType usageType, IEntity entity) { - public Task EnsureAuthorizedUserAsync(UsageType usageType, IEntity entity) - { - return Task.CompletedTask; - } + return Task.CompletedTask; + } - public Task EnsureAuthorizedUserAsync(OperationAuthorizationRequirement operation, IEntity entity) - { - return Task.CompletedTask; - } + public Task EnsureAuthorizedUserAsync(OperationAuthorizationRequirement operation, IEntity entity) + { + return Task.CompletedTask; + } - public Task EnsureAuthorizedUserAsync(FormEditContext editContext, ButtonSetup button) - { - return Task.CompletedTask; - } + public Task EnsureAuthorizedUserAsync(FormEditContext editContext, ButtonSetup button) + { + return Task.CompletedTask; + } - public Task IsUserAuthorizedAsync(UsageType usageType, IEntity entity) - { - return Task.FromResult(true); - } + public Task IsUserAuthorizedAsync(UsageType usageType, IEntity entity) + { + return Task.FromResult(true); + } - public Task IsUserAuthorizedAsync(OperationAuthorizationRequirement operation, IEntity entity) - { - return Task.FromResult(true); - } + public Task IsUserAuthorizedAsync(OperationAuthorizationRequirement operation, IEntity entity) + { + return Task.FromResult(true); + } - public Task IsUserAuthorizedAsync(FormEditContext editContext, ButtonSetup button) - { - return Task.FromResult(true); - } + public Task IsUserAuthorizedAsync(FormEditContext editContext, ButtonSetup button) + { + return Task.FromResult(true); } } diff --git a/src/RapidCMS.Core/Services/Concurrency/ConcurrencyService.cs b/src/RapidCMS.Core/Services/Concurrency/ConcurrencyService.cs index 5dfa3e6e..b9bc8adb 100644 --- a/src/RapidCMS.Core/Services/Concurrency/ConcurrencyService.cs +++ b/src/RapidCMS.Core/Services/Concurrency/ConcurrencyService.cs @@ -3,43 +3,42 @@ using System.Threading.Tasks; using RapidCMS.Core.Abstractions.Services; -namespace RapidCMS.Core.Services.Concurrency +namespace RapidCMS.Core.Services.Concurrency; + +internal class ConcurrencyService : IConcurrencyService { - internal class ConcurrencyService : IConcurrencyService + private readonly SemaphoreSlim _semaphore; + + public ConcurrencyService(SemaphoreSlim semaphore) { - private readonly SemaphoreSlim _semaphore; + _semaphore = semaphore; + } - public ConcurrencyService(SemaphoreSlim semaphore) + public async Task EnsureCorrectConcurrencyAsync(Func function) + { + await _semaphore.WaitAsync(); + + try { - _semaphore = semaphore; + await function.Invoke(); } - - public async Task EnsureCorrectConcurrencyAsync(Func function) + finally { - await _semaphore.WaitAsync(); - - try - { - await function.Invoke(); - } - finally - { - _semaphore.Release(); - } + _semaphore.Release(); } + } - public async Task EnsureCorrectConcurrencyAsync(Func> function) - { - await _semaphore.WaitAsync(); + public async Task EnsureCorrectConcurrencyAsync(Func> function) + { + await _semaphore.WaitAsync(); - try - { - return await function.Invoke(); - } - finally - { - _semaphore.Release(); - } + try + { + return await function.Invoke(); + } + finally + { + _semaphore.Release(); } } } diff --git a/src/RapidCMS.Core/Services/Interaction/InteractionService.cs b/src/RapidCMS.Core/Services/Interaction/InteractionService.cs index d0e2651b..19d1afbe 100644 --- a/src/RapidCMS.Core/Services/Interaction/InteractionService.cs +++ b/src/RapidCMS.Core/Services/Interaction/InteractionService.cs @@ -5,19 +5,18 @@ using RapidCMS.Core.Abstractions.Services; using RapidCMS.Core.Extensions; -namespace RapidCMS.Core.Services.Persistence -{ - internal class InteractionService : IInteractionService - { - private readonly IEnumerable _dispatchers; +namespace RapidCMS.Core.Services.Persistence; - public InteractionService(IEnumerable dispatchers) - { - _dispatchers = dispatchers; - } +internal class InteractionService : IInteractionService +{ + private readonly IEnumerable _dispatchers; - public Task InteractAsync(TRequest request) - => _dispatchers.GetTypeFromList>()?.InvokeAsync(request) - ?? throw new InvalidOperationException("Could not find the correct interaction dispatcher."); + public InteractionService(IEnumerable dispatchers) + { + _dispatchers = dispatchers; } + + public Task InteractAsync(TRequest request) + => _dispatchers.GetTypeFromList>()?.InvokeAsync(request) + ?? throw new InvalidOperationException("Could not find the correct interaction dispatcher."); } diff --git a/src/RapidCMS.Core/Services/Parent/ParentService.cs b/src/RapidCMS.Core/Services/Parent/ParentService.cs index 788082ab..8e9e2502 100644 --- a/src/RapidCMS.Core/Services/Parent/ParentService.cs +++ b/src/RapidCMS.Core/Services/Parent/ParentService.cs @@ -5,43 +5,42 @@ using RapidCMS.Core.Forms; using RapidCMS.Core.Models.Data; -namespace RapidCMS.Core.Services.Parent +namespace RapidCMS.Core.Services.Parent; + +internal class ParentService : IParentService { - internal class ParentService : IParentService + private readonly IRepositoryResolver _repositoryResolver; + private readonly IConcurrencyService _concurrencyService; + + public ParentService( + IRepositoryResolver repositoryResolver, + IConcurrencyService concurrencyService) + { + _repositoryResolver = repositoryResolver; + _concurrencyService = concurrencyService; + } + + public async Task GetParentAsync(ParentPath? parentPath) { - private readonly IRepositoryResolver _repositoryResolver; - private readonly IConcurrencyService _concurrencyService; + var parent = default(ParentEntity); - public ParentService( - IRepositoryResolver repositoryResolver, - IConcurrencyService concurrencyService) + if (parentPath == null) { - _repositoryResolver = repositoryResolver; - _concurrencyService = concurrencyService; + return parent; } - public async Task GetParentAsync(ParentPath? parentPath) + foreach (var (repositoryAlias, id) in parentPath) { - var parent = default(ParentEntity); - - if (parentPath == null) - { - return parent; - } - - foreach (var (repositoryAlias, id) in parentPath) + var repo = _repositoryResolver.GetRepository(repositoryAlias); + var entity = await _concurrencyService.EnsureCorrectConcurrencyAsync(() => repo.GetByIdAsync(id, new ViewContext(null, parent))); + if (entity == null) { - var repo = _repositoryResolver.GetRepository(repositoryAlias); - var entity = await _concurrencyService.EnsureCorrectConcurrencyAsync(() => repo.GetByIdAsync(id, new ViewContext(null, parent))); - if (entity == null) - { - break; - } - - parent = new ParentEntity(parent, entity, repositoryAlias); + break; } - return parent; + parent = new ParentEntity(parent, entity, repositoryAlias); } + + return parent; } } diff --git a/src/RapidCMS.Core/Services/Presentation/PresentationService.cs b/src/RapidCMS.Core/Services/Presentation/PresentationService.cs index f0321b03..8535b1bd 100644 --- a/src/RapidCMS.Core/Services/Presentation/PresentationService.cs +++ b/src/RapidCMS.Core/Services/Presentation/PresentationService.cs @@ -6,27 +6,26 @@ using RapidCMS.Core.Extensions; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Services.Presentation -{ - internal class PresentationService : IPresentationService - { - private readonly IEnumerable _dispatchers; +namespace RapidCMS.Core.Services.Presentation; - public PresentationService(IEnumerable dispatchers) - { - _dispatchers = dispatchers; - } +internal class PresentationService : IPresentationService +{ + private readonly IEnumerable _dispatchers; - public Task GetEntitiesAsync(TRequest request) where TResult : class - => _dispatchers.GetTypeFromList>()?.GetAsync(request) - ?? throw new InvalidOperationException(); + public PresentationService(IEnumerable dispatchers) + { + _dispatchers = dispatchers; + } - public Task GetEntityAsync(TRequest request) where TResult : class - => _dispatchers.GetTypeFromList>()?.GetAsync(request) - ?? throw new InvalidOperationException(); + public Task GetEntitiesAsync(TRequest request) where TResult : class + => _dispatchers.GetTypeFromList>()?.GetAsync(request) + ?? throw new InvalidOperationException(); - public Task> GetPageAsync(string pageAlias) - => _dispatchers.GetTypeFromList>>()?.GetAsync(pageAlias) + public Task GetEntityAsync(TRequest request) where TResult : class + => _dispatchers.GetTypeFromList>()?.GetAsync(request) ?? throw new InvalidOperationException(); - } + + public Task> GetPageAsync(string pageAlias) + => _dispatchers.GetTypeFromList>>()?.GetAsync(pageAlias) + ?? throw new InvalidOperationException(); } diff --git a/src/RapidCMS.Core/Services/Tree/TreeService.cs b/src/RapidCMS.Core/Services/Tree/TreeService.cs index 09353edf..d9abdb00 100644 --- a/src/RapidCMS.Core/Services/Tree/TreeService.cs +++ b/src/RapidCMS.Core/Services/Tree/TreeService.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; using RapidCMS.Core.Abstractions.Resolvers; using RapidCMS.Core.Abstractions.Services; using RapidCMS.Core.Abstractions.Setup; @@ -16,203 +15,197 @@ using RapidCMS.Core.Models.UI; using RapidCMS.Core.Navigation; -namespace RapidCMS.Core.Services.Tree +namespace RapidCMS.Core.Services.Tree; + +internal class TreeService : ITreeService { - internal class TreeService : ITreeService + private readonly ISetupResolver _collectionResolver; + private readonly ISetupResolver _pageResolver; + private readonly ISetupResolver> _treeElementResolver; + private readonly ICms _cms; + private readonly IRepositoryResolver _repositoryResolver; + private readonly IAuthService _authService; + private readonly IParentService _parentService; + private readonly IConcurrencyService _concurrencyService; + + public TreeService( + ISetupResolver collectionResolver, + ISetupResolver pageResolver, + ISetupResolver> treeElementResolver, + ICms cms, + IRepositoryResolver repositoryResolver, + IAuthService authService, + IParentService parentService, + IConcurrencyService concurrencyService) { - private readonly ISetupResolver _collectionResolver; - private readonly ISetupResolver _pageResolver; - private readonly ISetupResolver> _treeElementResolver; - private readonly ICms _cms; - private readonly IRepositoryResolver _repositoryResolver; - private readonly IAuthService _authService; - private readonly IParentService _parentService; - private readonly IConcurrencyService _concurrencyService; - private readonly IHttpContextAccessor _httpContextAccessor; - - public TreeService( - ISetupResolver collectionResolver, - ISetupResolver pageResolver, - ISetupResolver> treeElementResolver, - ICms cms, - IRepositoryResolver repositoryResolver, - IAuthService authService, - IParentService parentService, - IConcurrencyService concurrencyService, - IHttpContextAccessor httpContextAccessor) + _collectionResolver = collectionResolver; + _pageResolver = pageResolver; + _treeElementResolver = treeElementResolver; + _cms = cms; + _repositoryResolver = repositoryResolver; + _authService = authService; + _parentService = parentService; + _concurrencyService = concurrencyService; + } + + public async Task GetCollectionAsync(string alias, ParentPath? parentPath) + { + var collection = await _collectionResolver.ResolveSetupAsync(alias); + if (collection == null) { - _collectionResolver = collectionResolver; - _pageResolver = pageResolver; - _treeElementResolver = treeElementResolver; - _cms = cms; - _repositoryResolver = repositoryResolver; - _authService = authService; - _parentService = parentService; - _concurrencyService = concurrencyService; - _httpContextAccessor = httpContextAccessor; + throw new InvalidOperationException($"Failed to get collection for given alias ({alias})."); } - public async Task GetCollectionAsync(string alias, ParentPath? parentPath) - { - var collection = await _collectionResolver.ResolveSetupAsync(alias); - if (collection == null) - { - throw new InvalidOperationException($"Failed to get collection for given alias ({alias})."); - } + var parent = await _parentService.GetParentAsync(parentPath); - var parent = await _parentService.GetParentAsync(parentPath); + var isList = collection.UsageType.HasFlag(UsageType.List); + var isListEditor = collection.ListEditor != null; + var isListView = collection.ListView != null; + var isDetails = collection.UsageType.HasFlag(UsageType.Details) && parent?.Entity != null; - var isList = collection.UsageType.HasFlag(UsageType.List); - var isListEditor = collection.ListEditor != null; - var isListView = collection.ListView != null; - var isDetails = collection.UsageType.HasFlag(UsageType.Details) && parent?.Entity != null; + var respository = _repositoryResolver.GetRepository(collection); + var entity = await _concurrencyService.EnsureCorrectConcurrencyAsync(async () => isList + ? await respository.NewAsync(new ViewContext(collection.Alias, parent), collection.EntityVariant.Type) + : await respository.GetByIdAsync(parent!.Entity.Id!, new ViewContext(collection.Alias, parent)) + ?? throw new InvalidOperationException($"Failed to get detail entity for given alias ({alias}) -- a detail entity should always exist.")); - var respository = _repositoryResolver.GetRepository(collection); - var entity = await _concurrencyService.EnsureCorrectConcurrencyAsync(async () => isList - ? await respository.NewAsync(new ViewContext(collection.Alias, parent), collection.EntityVariant.Type) - : await respository.GetByIdAsync(parent!.Entity.Id!, new ViewContext(collection.Alias, parent)) - ?? throw new InvalidOperationException($"Failed to get detail entity for given alias ({alias}) -- a detail entity should always exist.")); + var canEdit = (isList && isListEditor && await _authService.IsUserAuthorizedAsync(Operations.Update, entity)) || + (isDetails && await _authService.IsUserAuthorizedAsync(Operations.Update, parent!.Entity)); + var canView = isList && isListView && await _authService.IsUserAuthorizedAsync(Operations.Read, entity); - var canEdit = (isList && isListEditor && await _authService.IsUserAuthorizedAsync(Operations.Update, entity)) || - (isDetails && await _authService.IsUserAuthorizedAsync(Operations.Update, parent!.Entity)); - var canView = isList && isListView && await _authService.IsUserAuthorizedAsync(Operations.Read, entity); + if (!canEdit && !canView) + { + return TreeCollectionUI.None; + } - if (!canEdit && !canView) + var tree = new TreeCollectionUI(collection.Alias, collection.RepositoryAlias, collection.Name) + { + EntitiesVisible = collection.TreeView?.EntityVisibility == EntityVisibilty.Visible, + RootVisible = collection.TreeView?.RootVisibility == CollectionRootVisibility.Visible, + Icon = collection.Icon ?? "Database", + Color = collection.Color, + DefaultOpenEntities = collection.TreeView?.DefaultOpenEntities ?? false + }; + + if (canEdit) + { + if (isList) { - return TreeCollectionUI.None; + tree.NavigateTo = new NavigationState( + collection.Alias, + parentPath, + UsageType.Edit); } - - var tree = new TreeCollectionUI(collection.Alias, collection.RepositoryAlias, collection.Name) + else if (isDetails) { - EntitiesVisible = collection.TreeView?.EntityVisibility == EntityVisibilty.Visible, - RootVisible = collection.TreeView?.RootVisibility == CollectionRootVisibility.Visible, - Icon = collection.Icon ?? "Database", - Color = collection.Color, - DefaultOpenEntities = collection.TreeView?.DefaultOpenEntities ?? false - }; - - if (canEdit) - { - if (isList) - { - tree.NavigateTo = new NavigationState( - collection.Alias, - parentPath, - UsageType.Edit); - } - else if (isDetails) - { - var entityVariant = collection.GetEntityVariant(entity); + var entityVariant = collection.GetEntityVariant(entity); - tree.NavigateTo = new NavigationState( - collection.Alias, parentPath, - entityVariant.Alias, - parent!.Entity.Id, - UsageType.Edit); - } - - } - else if (canView) - { tree.NavigateTo = new NavigationState( - collection.Alias, - parentPath, - UsageType.View); + collection.Alias, parentPath, + entityVariant.Alias, + parent!.Entity.Id, + UsageType.Edit); } - - return tree; + + } + else if (canView) + { + tree.NavigateTo = new NavigationState( + collection.Alias, + parentPath, + UsageType.View); } - public async Task GetPageAsync(string alias, ParentPath? parentPath) + return tree; + } + + public async Task GetPageAsync(string alias, ParentPath? parentPath) + { + var page = await _pageResolver.ResolveSetupAsync(alias); + if (page == null) { - var page = await _pageResolver.ResolveSetupAsync(alias); - if (page == null) - { - throw new InvalidOperationException($"Failed to get page for given alias ({alias})."); - } + throw new InvalidOperationException($"Failed to get page for given alias ({alias})."); + } - return new TreePageUI(page.Name, page.Icon, page.Color, new NavigationState(page.Alias, parentPath)); + return new TreePageUI(page.Name, page.Icon, page.Color, new NavigationState(page.Alias, parentPath)); + } + + public async Task GetNodesAsync(string alias, ParentPath? parentPath, int pageNr, int pageSize) + { + var collection = await _collectionResolver.ResolveSetupAsync(alias); + if (collection == null) + { + throw new InvalidOperationException($"Failed to get collection for given alias ({alias})."); } - public async Task GetNodesAsync(string alias, ParentPath? parentPath, int pageNr, int pageSize) + var parent = await _parentService.GetParentAsync(parentPath); + + if (collection.TreeView?.EntityVisibility == EntityVisibilty.Visible) { - var x = _httpContextAccessor.HttpContext; + var view = View.Create(pageSize, pageNr, default, default, collectionAlias: alias); + var respository = _repositoryResolver.GetRepository(collection); + var entities = await _concurrencyService.EnsureCorrectConcurrencyAsync(() => respository.GetAllAsync(new ViewContext(collection.Alias, parent), view)); - var collection = await _collectionResolver.ResolveSetupAsync(alias); - if (collection == null) + var list = await entities.SelectNotNullAsync(async entity => { - throw new InvalidOperationException($"Failed to get collection for given alias ({alias})."); - } + var canEdit = collection.NodeEditor != null && await _authService.IsUserAuthorizedAsync(Operations.Update, entity); + var canView = collection.ListView != null && await _authService.IsUserAuthorizedAsync(Operations.Read, entity); - var parent = await _parentService.GetParentAsync(parentPath); + if (!canEdit && !canView) + { + return null; + } - if (collection.TreeView?.EntityVisibility == EntityVisibilty.Visible) - { - var view = View.Create(pageSize, pageNr, default, default, collectionAlias: alias); - var respository = _repositoryResolver.GetRepository(collection); - var entities = await _concurrencyService.EnsureCorrectConcurrencyAsync(() => respository.GetAllAsync(new ViewContext(collection.Alias, parent), view)); + var entityVariant = collection.GetEntityVariant(entity); - var list = await entities.SelectNotNullAsync(async entity => + var node = new TreeNodeUI( + entity.Id!, + collection.RepositoryAlias, + collection.TreeView.Name!.StringGetter.Invoke(entity), + collection.Collections.ToList(subCollection => (subCollection.Alias, subCollection.Type))) { - var canEdit = collection.NodeEditor != null && await _authService.IsUserAuthorizedAsync(Operations.Update, entity); - var canView = collection.ListView != null && await _authService.IsUserAuthorizedAsync(Operations.Read, entity); - - if (!canEdit && !canView) - { - return null; - } - - var entityVariant = collection.GetEntityVariant(entity); - - var node = new TreeNodeUI( - entity.Id!, - collection.RepositoryAlias, - collection.TreeView.Name!.StringGetter.Invoke(entity), - collection.Collections.ToList(subCollection => (subCollection.Alias, subCollection.Type))) - { - RootVisibleOfCollections = collection.Collections.All(subCollection => subCollection.RootVisibility == CollectionRootVisibility.Visible), - DefaultOpenCollections = collection.TreeView?.DefaultOpenCollections ?? false - }; - - if (canEdit) - { - node.NavigateTo = new NavigationState( - collection.Alias, - parentPath, - entityVariant.Alias, - entity.Id, - UsageType.Edit); - } - else if (canView) - { - node.NavigateTo = new NavigationState( - collection.Alias, - parentPath, - entityVariant.Alias, - entity.Id, - UsageType.View); - } - - return node; - }).ToListAsync(); - - return new TreeNodesUI(list.Take(pageSize).ToList(), view.MoreDataAvailable); - } - else - { - return default; - } - } + RootVisibleOfCollections = collection.Collections.All(subCollection => subCollection.RootVisibility == CollectionRootVisibility.Visible), + DefaultOpenCollections = collection.TreeView?.DefaultOpenCollections ?? false + }; - public async Task GetRootAsync() - { - var collections = (await _treeElementResolver.ResolveSetupAsync()) - .ToList(x => (x.Alias, x.Type)); + if (canEdit) + { + node.NavigateTo = new NavigationState( + collection.Alias, + parentPath, + entityVariant.Alias, + entity.Id, + UsageType.Edit); + } + else if (canView) + { + node.NavigateTo = new NavigationState( + collection.Alias, + parentPath, + entityVariant.Alias, + entity.Id, + UsageType.View); + } - return new TreeRootUI("-1", AliasHelper.GetRepositoryAlias(typeof(object)), _cms.SiteName, collections) - { - NavigateTo = new NavigationState() - }; + return node; + }).ToListAsync(); + + return new TreeNodesUI(list.Take(pageSize).ToList(), view.MoreDataAvailable); + } + else + { + return default; } } + + public async Task GetRootAsync() + { + var collections = (await _treeElementResolver.ResolveSetupAsync()) + .ToList(x => (x.Alias, x.Type)); + + return new TreeRootUI("-1", AliasHelper.GetRepositoryAlias(typeof(object)), _cms.SiteName, collections) + { + NavigateTo = new NavigationState() + }; + } } diff --git a/src/RapidCMS.Core/Validators/AsyncEntityValidator.cs b/src/RapidCMS.Core/Validators/AsyncEntityValidator.cs index 5716bdcd..fe843a37 100644 --- a/src/RapidCMS.Core/Validators/AsyncEntityValidator.cs +++ b/src/RapidCMS.Core/Validators/AsyncEntityValidator.cs @@ -4,14 +4,13 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Abstractions.Validators; -namespace RapidCMS.Core.Validators +namespace RapidCMS.Core.Validators; + +public abstract class BaseAsyncEntityValidator : IAsyncEntityValidator, IAsyncEntityValidator + where TEntity : IEntity { - public abstract class BaseAsyncEntityValidator : IAsyncEntityValidator, IAsyncEntityValidator - where TEntity : IEntity - { - public abstract Task> ValidateAsync(IValidatorContext context); + public abstract Task> ValidateAsync(IValidatorContext context); - Task> IAsyncEntityValidator.ValidateAsync(IValidatorContext context) - => ValidateAsync(new ValidatorContext(context.Entity, context.RelationContainer, context.Configuration)); - } + Task> IAsyncEntityValidator.ValidateAsync(IValidatorContext context) + => ValidateAsync(new ValidatorContext(context.Entity, context.RelationContainer, context.Configuration)); } diff --git a/src/RapidCMS.Core/Validators/BaseEntityValidator.cs b/src/RapidCMS.Core/Validators/BaseEntityValidator.cs index 24947a99..69260ad3 100644 --- a/src/RapidCMS.Core/Validators/BaseEntityValidator.cs +++ b/src/RapidCMS.Core/Validators/BaseEntityValidator.cs @@ -3,14 +3,13 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Abstractions.Validators; -namespace RapidCMS.Core.Validators +namespace RapidCMS.Core.Validators; + +public abstract class BaseEntityValidator : IEntityValidator, IEntityValidator + where TEntity : IEntity { - public abstract class BaseEntityValidator : IEntityValidator, IEntityValidator - where TEntity : IEntity - { - public abstract IEnumerable Validate(IValidatorContext context); + public abstract IEnumerable Validate(IValidatorContext context); - IEnumerable IEntityValidator.Validate(IValidatorContext context) - => Validate(new ValidatorContext(context.Entity, context.RelationContainer, context.Configuration)); - } + IEnumerable IEntityValidator.Validate(IValidatorContext context) + => Validate(new ValidatorContext(context.Entity, context.RelationContainer, context.Configuration)); } diff --git a/src/RapidCMS.Core/Validators/DataAnnotationEntityValidator.cs b/src/RapidCMS.Core/Validators/DataAnnotationEntityValidator.cs index f0dd1114..9820e39a 100644 --- a/src/RapidCMS.Core/Validators/DataAnnotationEntityValidator.cs +++ b/src/RapidCMS.Core/Validators/DataAnnotationEntityValidator.cs @@ -4,30 +4,29 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Abstractions.Validators; -namespace RapidCMS.Core.Validators +namespace RapidCMS.Core.Validators; + +public class DataAnnotationEntityValidator : BaseEntityValidator { - public class DataAnnotationEntityValidator : BaseEntityValidator + private readonly IServiceProvider _serviceProvider; + + public DataAnnotationEntityValidator(IServiceProvider serviceProvider) { - private readonly IServiceProvider _serviceProvider; + _serviceProvider = serviceProvider; + } - public DataAnnotationEntityValidator(IServiceProvider serviceProvider) - { - _serviceProvider = serviceProvider; - } + public override IEnumerable Validate(IValidatorContext context) + { + var results = new List(); - public override IEnumerable Validate(IValidatorContext context) + try { - var results = new List(); - - try - { - var ctx = new ValidationContext(context.Entity, _serviceProvider, null); - // even though this says Try, and therefore it should not throw an error, IT DOES when a given property is not part of Entity - Validator.TryValidateObject(context.Entity, ctx, results, true); - } - catch { } - - return results; + var ctx = new ValidationContext(context.Entity, _serviceProvider, null); + // even though this says Try, and therefore it should not throw an error, IT DOES when a given property is not part of Entity + Validator.TryValidateObject(context.Entity, ctx, results, true); } + catch { } + + return results; } } diff --git a/src/RapidCMS.Core/Validators/EntityValidator.cs b/src/RapidCMS.Core/Validators/EntityValidator.cs index cfa64587..0a620975 100644 --- a/src/RapidCMS.Core/Validators/EntityValidator.cs +++ b/src/RapidCMS.Core/Validators/EntityValidator.cs @@ -9,70 +9,69 @@ using RapidCMS.Core.Models; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.Core.Validators +namespace RapidCMS.Core.Validators; + +internal static class EntityValidator { - internal static class EntityValidator + public static async IAsyncEnumerable ValidateAsync( + IReadOnlyList validators, + IRelationContainer relationContainer, + IServiceProvider serviceProvider, + IEntity entity, + string? propertyName = default) { - public static async IAsyncEnumerable ValidateAsync( - IReadOnlyList validators, - IRelationContainer relationContainer, - IServiceProvider serviceProvider, - IEntity entity, - string? propertyName = default) + foreach (var validatorSetup in validators) { - foreach (var validatorSetup in validators) - { - var isVariantValidator = validatorSetup.Type.HasInterface(typeof(IEntityValidator<>).MakeGenericType(entity.GetType())) || - validatorSetup.Type.HasInterface(typeof(IAsyncEntityValidator<>).MakeGenericType(entity.GetType())); + var isVariantValidator = validatorSetup.Type.HasInterface(typeof(IEntityValidator<>).MakeGenericType(entity.GetType())) || + validatorSetup.Type.HasInterface(typeof(IAsyncEntityValidator<>).MakeGenericType(entity.GetType())); - var isGenericVariantValidator = validatorSetup.Type.HasInterface(typeof(IEntityValidator)) || - validatorSetup.Type.HasInterface(typeof(IAsyncEntityValidator)); + var isGenericVariantValidator = validatorSetup.Type.HasInterface(typeof(IEntityValidator)) || + validatorSetup.Type.HasInterface(typeof(IAsyncEntityValidator)); - var isVariantValidatorForOtherEntity = validatorSetup.Type.HasGenericInterface(typeof(IEntityValidator<>)) || - validatorSetup.Type.HasGenericInterface(typeof(IAsyncEntityValidator<>)); + var isVariantValidatorForOtherEntity = validatorSetup.Type.HasGenericInterface(typeof(IEntityValidator<>)) || + validatorSetup.Type.HasGenericInterface(typeof(IAsyncEntityValidator<>)); - var isGenericValidator = validatorSetup.Type.HasInterface(typeof(IEntityValidator)) || - validatorSetup.Type.HasInterface(typeof(IAsyncEntityValidator)); + var isGenericValidator = validatorSetup.Type.HasInterface(typeof(IEntityValidator)) || + validatorSetup.Type.HasInterface(typeof(IAsyncEntityValidator)); - if (isVariantValidator || isGenericVariantValidator || (!isVariantValidator && !isVariantValidatorForOtherEntity && isGenericValidator)) + if (isVariantValidator || isGenericVariantValidator || (!isVariantValidator && !isVariantValidatorForOtherEntity && isGenericValidator)) + { + var validationResult = serviceProvider.GetService(validatorSetup.Type) switch { - var validationResult = serviceProvider.GetService(validatorSetup.Type) switch - { - IEntityValidator validator => validator.Validate(new ValidatorContext(entity, relationContainer, validatorSetup.Configuration)), - IAsyncEntityValidator asyncValidator => await asyncValidator.ValidateAsync(new ValidatorContext(entity, relationContainer, validatorSetup.Configuration)), - _ => throw new InvalidOperationException($"Invalid entity validator given. {validatorSetup.Type.Name} is not included in Service Collection or is not a {typeof(IEntityValidator).Name} or {typeof(IAsyncEntityValidator).Name}.") - }; + IEntityValidator validator => validator.Validate(new ValidatorContext(entity, relationContainer, validatorSetup.Configuration)), + IAsyncEntityValidator asyncValidator => await asyncValidator.ValidateAsync(new ValidatorContext(entity, relationContainer, validatorSetup.Configuration)), + _ => throw new InvalidOperationException($"Invalid entity validator given. {validatorSetup.Type.Name} is not included in Service Collection or is not a {typeof(IEntityValidator).Name} or {typeof(IAsyncEntityValidator).Name}.") + }; - foreach (var result in FlattenCompositeValidationResults(validationResult).Where(x => string.IsNullOrWhiteSpace(propertyName) || x.MemberNames.Contains(propertyName))) - { - yield return result; - } + foreach (var result in FlattenCompositeValidationResults(validationResult).Where(x => string.IsNullOrWhiteSpace(propertyName) || x.MemberNames.Contains(propertyName))) + { + yield return result; } } } + } - private static IEnumerable FlattenCompositeValidationResults(IEnumerable results, string? memberNamePrefix = null) + private static IEnumerable FlattenCompositeValidationResults(IEnumerable results, string? memberNamePrefix = null) + { + foreach (var result in results) { - foreach (var result in results) + // TODO: even after disabling the DataAnnotationValidator, entity validation is still dependent on some Attributes to work correctly + if (result is CompositeValidationResult composite) { - // TODO: even after disabling the DataAnnotationValidator, entity validation is still dependent on some Attributes to work correctly - if (result is CompositeValidationResult composite) - { - foreach (var nestedResult in FlattenCompositeValidationResults(composite.Results, composite.MemberName)) - { - yield return nestedResult; - } - } - else if (string.IsNullOrWhiteSpace(memberNamePrefix)) + foreach (var nestedResult in FlattenCompositeValidationResults(composite.Results, composite.MemberName)) { - yield return result; - } - else - { - yield return new ValidationResult(result.ErrorMessage, result.MemberNames.Select(x => $"{memberNamePrefix}.{x}")); + yield return nestedResult; } - } + else if (string.IsNullOrWhiteSpace(memberNamePrefix)) + { + yield return result; + } + else + { + yield return new ValidationResult(result.ErrorMessage, result.MemberNames.Select(x => $"{memberNamePrefix}.{x}")); + } + } } } diff --git a/src/RapidCMS.Core/Validators/ValidatorContext.cs b/src/RapidCMS.Core/Validators/ValidatorContext.cs index cb604ea9..685d8f91 100644 --- a/src/RapidCMS.Core/Validators/ValidatorContext.cs +++ b/src/RapidCMS.Core/Validators/ValidatorContext.cs @@ -3,37 +3,36 @@ using RapidCMS.Core.Abstractions.Forms; using RapidCMS.Core.Abstractions.Validators; -namespace RapidCMS.Core.Validators +namespace RapidCMS.Core.Validators; + +public class ValidatorContext : IValidatorContext { - public class ValidatorContext : IValidatorContext + public ValidatorContext(IEntity entity, IRelationContainer relationContainer, object? configuration) { - public ValidatorContext(IEntity entity, IRelationContainer relationContainer, object? configuration) - { - Entity = entity ?? throw new ArgumentNullException(nameof(entity)); - RelationContainer = relationContainer ?? throw new ArgumentNullException(nameof(relationContainer)); - Configuration = configuration; - } + Entity = entity ?? throw new ArgumentNullException(nameof(entity)); + RelationContainer = relationContainer ?? throw new ArgumentNullException(nameof(relationContainer)); + Configuration = configuration; + } - public IEntity Entity { get; } + public IEntity Entity { get; } - public IRelationContainer RelationContainer { get; } + public IRelationContainer RelationContainer { get; } - public object? Configuration { get; } - } + public object? Configuration { get; } +} - public class ValidatorContext : IValidatorContext +public class ValidatorContext : IValidatorContext +{ + public ValidatorContext(IEntity entity, IRelationContainer relationContainer, object? configuration) { - public ValidatorContext(IEntity entity, IRelationContainer relationContainer, object? configuration) - { - Entity = (TEntity)entity ?? throw new ArgumentNullException(nameof(entity)); - RelationContainer = relationContainer ?? throw new ArgumentNullException(nameof(relationContainer)); - Configuration = configuration; - } + Entity = (TEntity)entity ?? throw new ArgumentNullException(nameof(entity)); + RelationContainer = relationContainer ?? throw new ArgumentNullException(nameof(relationContainer)); + Configuration = configuration; + } - public TEntity Entity { get; } + public TEntity Entity { get; } - public IRelationContainer RelationContainer { get; } + public IRelationContainer RelationContainer { get; } - public object? Configuration { get; } - } + public object? Configuration { get; } } diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/EntityGeneratorTests.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/EntityGeneratorTests.cs deleted file mode 100644 index 7d5d396e..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/EntityGeneratorTests.cs +++ /dev/null @@ -1,31 +0,0 @@ -using NUnit.Framework; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests.Helpers; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests.SharedCode; - -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests -{ - public class EntityGeneratorTests - { - [Test] - public void WhenBasicBlogConfigurationIsRead_ThenBlogEntitiesAreGenerated() - { - GeneratorTestHelper.TestGeneratedCode( - new[] - { - "./modelmaker.category.json", - "./modelmaker.blog.json" - }, - CategoryCode.EntityWithBlog, - CategoryCode.EntityValidator, - CategoryCode.Collection, - BlogCode.Entity, - BlogCode.EntityValidator, - BlogCode.Collection, - ContextCode.BlogCategoryContext, - CategoryCode.EntityConfiguration, - CategoryCode.Repository, - BlogCode.EntityConfiguration, - BlogCode.Repository); - } - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/Helpers/GeneratorTestHelper.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/Helpers/GeneratorTestHelper.cs deleted file mode 100644 index 01c93e5f..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/Helpers/GeneratorTestHelper.cs +++ /dev/null @@ -1,69 +0,0 @@ -using System; -using System.Collections.Immutable; -using System.Diagnostics; -using System.IO; -using System.Linq; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using NUnit.Framework; - -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests.Helpers -{ - - public static class GeneratorTestHelper - { - private static (ImmutableArray, string[]) GetGeneratedOutput(string[] jsonFileNames) - { - var jsons = jsonFileNames.Select(File.ReadAllText); - - var references = AppDomain.CurrentDomain.GetAssemblies() - .Where(_ => !_.IsDynamic && !string.IsNullOrWhiteSpace(_.Location)) - .Select(_ => MetadataReference.CreateFromFile(_.Location)) - .Concat(new[] { MetadataReference.CreateFromFile(typeof(ModelMakerGenerator).Assembly.Location) }); - var compilation = CSharpCompilation.Create("generator", new SyntaxTree[] { }, - references, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); - - var generator = new ModelMakerGenerator(); - - var driver = CSharpGeneratorDriver.Create(ImmutableArray.Create(generator), jsons.Select(x => new JsonText(x))); - driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out var diagnostics); - - var trees = outputCompilation.SyntaxTrees.ToList(); - - return (diagnostics, trees.Select(x => x.ToString()).ToArray()); - } - - public static void TestGeneratedCode(string[] sourceTexts, params string[] expectedOutputSourceTexts) - { - var (diagnostics, output) = GetGeneratedOutput(sourceTexts); - - Assert.AreEqual(0, diagnostics.Length, string.Join(", ", diagnostics.Select(x => x.GetMessage()))); - - for (var i = 0; i < expectedOutputSourceTexts.Length; i++) - { - try - { - Assert.AreEqual(expectedOutputSourceTexts[i], output.ElementAtOrDefault(i) ?? "", $"Error in file index: {i}"); - } - catch - { - throw; - } - } - } - - public static void TestReportedDiagnostics(string[] sourceTexts, params string[] expectedDiagnosticErrors) - { - var (diagnostics, output) = GetGeneratedOutput(sourceTexts); - - var errorCodes = diagnostics.Select(x => x.Id).ToArray(); - - Assert.AreEqual(expectedDiagnosticErrors.Length, diagnostics.Length, $"Found messages: {string.Join(", ", errorCodes)}."); - - foreach (var diagnostic in expectedDiagnosticErrors) - { - Assert.Contains(diagnostic, errorCodes); - } - } - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/Helpers/JsonText.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/Helpers/JsonText.cs deleted file mode 100644 index 1a8a620e..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/Helpers/JsonText.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Threading; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Text; - -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests.Helpers -{ - public class JsonText : AdditionalText - { - private readonly string _json; - - public JsonText(string json) - { - _json = json; - } - - public override string Path => "./test.json"; - - public override SourceText GetText(CancellationToken cancellationToken = default) => SourceText.From(_json); - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/ManyToManyTests.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/ManyToManyTests.cs deleted file mode 100644 index c09fd3cc..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/ManyToManyTests.cs +++ /dev/null @@ -1,51 +0,0 @@ -using NUnit.Framework; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests.Helpers; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests.SharedCode; - -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests -{ - public class ManyToManyTests - { - [Test] - public void WhenManyToManyImplicitConfigurationIsRead_ThenManyToManyEntitiesAreGenerated() - { - GeneratorTestHelper.TestGeneratedCode( - new[] - { - // Corresponding property in A is not set, making this Many-to-Many implicit - "./modelmaker.many-to-many-many-as-implicit.json", - "./modelmaker.many-to-many-many-bs.json" - }, - ManyToManyManyACode.Entity, - ManyToManyManyACode.Collection, - ManyToManyManyBCode.Entity, - ManyToManyManyBCode.Collection, - ContextCode.ManyToManyContext, - ManyToManyManyACode.EntityTypeConfiguration, - ManyToManyManyACode.Repository, - ManyToManyManyBCode.EntityTypeConfiguration, - ManyToManyManyBCode.Repository); - } - - [Test] - public void WhenManyToManyExplicitConfigurationIsRead_ThenManyToManyEntitiesAreGenerated() - { - GeneratorTestHelper.TestGeneratedCode( - new[] - { - // Corresponding property in A is set to B, making this Many-to-Many explicit - "./modelmaker.many-to-many-many-as-explicit.json", - "./modelmaker.many-to-many-many-bs.json" - }, - ManyToManyManyACode.Entity, - ManyToManyManyACode.Collection, - ManyToManyManyBCode.Entity, - ManyToManyManyBCode.Collection, - ContextCode.ManyToManyContext, - ManyToManyManyACode.EntityTypeConfiguration, - ManyToManyManyACode.Repository, - ManyToManyManyBCode.EntityTypeConfiguration, - ManyToManyManyBCode.Repository); - } - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/OneToManyTests.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/OneToManyTests.cs deleted file mode 100644 index 2a8a9c69..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/OneToManyTests.cs +++ /dev/null @@ -1,29 +0,0 @@ -using NUnit.Framework; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests.Helpers; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests.SharedCode; - -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests -{ - public class OneToManyTests - { - [Test] - public void WhenOneToManyConfigurationIsRead_ThenOneToManyEntitiesAreGenerated() - { - GeneratorTestHelper.TestGeneratedCode( - new[] - { - "./modelmaker.one-to-many-manys.json", - "./modelmaker.one-to-many-ones.json" - }, - OneToManyManyCode.Entity, - OneToManyManyCode.Collection, - OneToManyOneCode.Entity, - OneToManyOneCode.Collection, - ContextCode.OneToManyContext, - OneToManyManyCode.EntityTypeConfiguration, - OneToManyManyCode.Repository, - OneToManyOneCode.EntityTypeConfiguration, - OneToManyOneCode.Repository); - } - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/OneToOneTests.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/OneToOneTests.cs deleted file mode 100644 index 9ba5da76..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/OneToOneTests.cs +++ /dev/null @@ -1,52 +0,0 @@ -using NUnit.Framework; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests.Helpers; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests.SharedCode; - -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests -{ - public class OneToOneTests - { - [Test] - public void WhenOneToOneImplicitConfigurationIsRead_ThenOneToOneEntitiesAreGenerated() - { - GeneratorTestHelper.TestGeneratedCode( - new[] - { - // corresponding property in A is set, making it the Depending side of the one-to-one relation between A & B - "./modelmaker.one-to-one-one-as.json", - "./modelmaker.one-to-one-one-bs-explicit.json" - }, - OneToOneOneACode.Entity, - OneToOneOneACode.Collection, - OneToOneOneBCode.Entity, - OneToOneOneBCode.Collection, - ContextCode.OneToOneContext, - OneToOneOneACode.EntityTypeConfiguration, - OneToOneOneACode.Repository, - OneToOneOneBCode.EntityTypeConfiguration, - OneToOneOneBCode.Repository); - } - - [Test] - public void WhenoneTooneExplicitConfigurationIsRead_ThenoneTooneEntitiesAreGenerated() - { - GeneratorTestHelper.TestGeneratedCode( - new[] - { - // corresponding property in A and B are set, making the Depending side not clear for the one-to-one relation. - // the lowest ranking entity name will be made Depending side - "./modelmaker.one-to-one-one-as.json", - "./modelmaker.one-to-one-one-bs-implicit.json" - }, - OneToOneOneACode.Entity, - OneToOneOneACode.Collection, - OneToOneOneBCode.Entity, - OneToOneOneBCode.Collection, - ContextCode.OneToOneContext, - OneToOneOneACode.EntityTypeConfiguration, - OneToOneOneACode.Repository, - OneToOneOneBCode.EntityTypeConfiguration, - OneToOneOneBCode.Repository); - } - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/OutputSelectionTests.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/OutputSelectionTests.cs deleted file mode 100644 index 86af43e1..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/OutputSelectionTests.cs +++ /dev/null @@ -1,39 +0,0 @@ -using NUnit.Framework; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests.Helpers; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests.SharedCode; - -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests -{ - public class OutputSelectionTests - { - [Test] - public void WhenOnlyCollectionsShouldBeGenerated_ThenOnlyCollectionsAreGenerated() - { - GeneratorTestHelper.TestGeneratedCode(new[] { "./modelmaker.category.collection-only.json" }, CategoryCode.Collection); - } - - [Test] - public void WhenOnlyContextShouldBeGenerated_ThenOnlyContextAreGenerated() - { - GeneratorTestHelper.TestGeneratedCode(new[] { "./modelmaker.category.context-only.json" }, ContextCode.CategoryContext, CategoryCode.EntityConfiguration); - } - - [Test] - public void WhenOnlyEntitiesShouldBeGenerated_ThenOnlyEntitiesAreGenerated() - { - GeneratorTestHelper.TestGeneratedCode(new[] { "./modelmaker.category.entity-only.json" }, CategoryCode.EntityWithoutBlog); - } - - [Test] - public void WhenOnlyRepositoriesShouldBeGenerated_ThenOnlyRepositoriesAreGenerated() - { - GeneratorTestHelper.TestGeneratedCode(new[] { "./modelmaker.category.repository-only.json" }, CategoryCode.Repository); - } - - [Test] - public void WhenOnlyValidationShouldBeGenerated_ThenOnlyValidationAreGenerated() - { - GeneratorTestHelper.TestGeneratedCode(new[] { "./modelmaker.category.validation-only.json" }, CategoryCode.EntityValidator); - } - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/PropertyParserTests.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/PropertyParserTests.cs deleted file mode 100644 index a0363a9c..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/PropertyParserTests.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Collections.Generic; -using NUnit.Framework; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Parsers; - -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests -{ - public class PropertyParserTests - { - [TestCase(typeof(string), "System.String")] - [TestCase(typeof(List), "System.Collections.Generic.List")] - [TestCase(typeof(Dictionary), "System.Collections.Generic.Dictionary")] - [TestCase(typeof(Dictionary, string>), "System.Collections.Generic.Dictionary, System.String>")] - [TestCase(typeof(Dictionary, List>), "System.Collections.Generic.Dictionary, System.Collections.Generic.List>")] - [TestCase(typeof(List, List>>), "System.Collections.Generic.List, System.Collections.Generic.List>>")] - [TestCase(typeof(Dictionary, List>>), "System.Collections.Generic.Dictionary, System.Collections.Generic.List>>")] - public void WhenTypeFullNameIsGivenToPropertyParse_ThenCorrectCSharpTypeNotationIsGenerated(Type type, string expectedNotation) - { - var notation = new PropertyParser().ParseTypeWithNamespace(type.FullName); - - Assert.AreEqual(expectedNotation, notation); - } - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests.csproj b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests.csproj deleted file mode 100644 index 688aa985..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests.csproj +++ /dev/null @@ -1,104 +0,0 @@ - - - - net6.0 - false - 10.0 - - - - - - - - - - - - - - - - - - - - - - - Always - - - Always - - - Always - - - Always - - - - - - Always - - - Always - - - Always - - - - - - Always - - - Always - - - - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/SharedCode/BlogCode.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/SharedCode/BlogCode.cs deleted file mode 100644 index 70a77a73..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/SharedCode/BlogCode.cs +++ /dev/null @@ -1,249 +0,0 @@ -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests.SharedCode -{ - public static class BlogCode - { - public const string Entity = @"using System.Collections.Generic; -using RapidCMS.Core.Abstractions.Data; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public partial class Blog : IEntity - { - public int Id { get; set; } - string? IEntity.Id { get => Id.ToString(); set => Id = int.Parse(value ?? ""0""); } - - public System.String Title { get; set; } - - public System.String Content { get; set; } - - public RapidCMS.Example.ModelMaker.Models.Enums.ContentType Type { get; set; } - - public System.Boolean IsPublished { get; set; } - - public System.DateTime PublishDate { get; set; } - - public int? MainCategoryId { get; set; } - public RapidCMS.ModelMaker.Category? MainCategory { get; set; } - - public ICollection BlogCategories { get; set; } = new List(); - } -} -"; - - public const string Collection = @"using System.Collections.Generic; -using RapidCMS.Core.Abstractions.Config; -using RapidCMS.Core.Enums; -using RapidCMS.Core.Extensions; -using RapidCMS.Core.Providers; -using RapidCMS.Core.Repositories; -using RapidCMS.Example.ModelMaker.Models.Validators; -using RapidCMS.ModelMaker.Validation.Config; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public static class BlogCollection - { - public static void AddBlogCollection(this ICmsConfig config) - { - config.AddCollection>( - ""blogs"", - ""Blog"", - ""Cyan30"", - ""Blogs"", - collection => - { - collection.SetTreeView(x => x.Title); - collection.SetElementConfiguration(x => x.Id, x => x.Title); - collection.AddEntityValidator(); - collection.SetListView(view => - { - view.AddDefaultButton(DefaultButtonType.New); - view.AddRow(row => - { - row.AddField(x => x.Id.ToString()).SetName(""Id""); - row.AddField(x => x.Title).SetName(""Title""); - row.AddField(x => x.Content == null ? """" : x.Content.ToString().Truncate(25)).SetName(""Content""); - row.AddDefaultButton(DefaultButtonType.Edit); - row.AddDefaultButton(DefaultButtonType.Delete); - }); - }); - collection.SetNodeEditor(editor => - { - editor.AddDefaultButton(DefaultButtonType.Up); - editor.AddDefaultButton(DefaultButtonType.SaveExisting); - editor.AddDefaultButton(DefaultButtonType.SaveNew); - editor.AddSection(section => - { - section.AddField(x => x.Title).SetType(typeof(RapidCMS.UI.Components.Editors.TextBoxEditor)).SetName(""Title""); - section.AddField(x => x.Content).SetType(typeof(RapidCMS.UI.Components.Editors.TextAreaEditor)).SetName(""Content""); - section.AddField(x => x.Type).SetType(typeof(RapidCMS.UI.Components.Editors.DropdownEditor)).SetDataCollection>().SetName(""Type""); - section.AddField(x => x.IsPublished).SetType(typeof(RapidCMS.UI.Components.Editors.DropdownEditor)).SetDataCollection(new BooleanLabelDetailConfig { Labels = new BooleanLabelDetailConfig.LabelsConfig { TrueLabel = ""True"", FalseLabel = ""False"" } }).SetName(""Is Published""); - section.AddField(x => x.PublishDate).SetType(typeof(RapidCMS.UI.Components.Editors.DateEditor)).SetName(""Publish Date""); - section.AddField(x => x.MainCategoryId).SetType(typeof(RapidCMS.UI.Components.Editors.EntityPicker)).SetCollectionRelation(""categories"").SetName(""Main Category""); - section.AddField(x => x.BlogCategories).SetType(typeof(RapidCMS.UI.Components.Editors.EntitiesPicker)).SetCollectionRelation(""categories"").SetName(""Blog Categories""); - }); - }); - }); - } - } -} -"; - - public const string EntityConfiguration = @"using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public class BlogConfiguration : IEntityTypeConfiguration - { - public void Configure(EntityTypeBuilder builder) - { - builder.HasOne(x => x.MainCategory).WithMany(x => x.BlogMainCategory).OnDelete(DeleteBehavior.NoAction); - builder.HasMany(x => x.BlogCategories).WithMany(x => x.BlogBlogCategories); - } - } -} -"; - - public const string Repository = @"using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; -using RapidCMS.Core.Abstractions.Data; -using RapidCMS.Core.Abstractions.Forms; -using RapidCMS.Core.Repositories; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public class BlogRepository : BaseRepository - { - private readonly ModelMakerDbContext _dbContext; - - public BlogRepository(ModelMakerDbContext dbContext) - { - _dbContext = dbContext; - } - - public override async Task DeleteAsync(string id, IParent? parent) - { - if (int.TryParse(id, out var intId)) - { - var entity = await _dbContext.Blogs.Include(x => x.BlogCategories).FirstOrDefaultAsync(x => x.Id == intId); - if (entity != null) - { - _dbContext.Blogs.Remove(entity); - await _dbContext.SaveChangesAsync(); - } - } - } - - public override async Task> GetAllAsync(IParent? parent, IView view) - { - return await view.ApplyOrder(view.ApplyDataView(_dbContext.Blogs)).Skip(view.Skip).Take(view.Take).AsNoTracking().ToListAsync(); - } - - public override async Task GetByIdAsync(string id, IParent? parent) - { - if (int.TryParse(id, out var intId)) - { - return await _dbContext.Blogs.Include(x => x.BlogCategories).AsNoTracking().FirstOrDefaultAsync(x => x.Id == intId); - } - return default; - } - - public override async Task InsertAsync(IEditContext editContext) - { - var entity = editContext.Entity; - - var relations = editContext.GetRelationContainer(); - await HandleBlogCategoriesAsync(entity, relations); - - var entry = _dbContext.Blogs.Add(entity); - await _dbContext.SaveChangesAsync(); - return entry.Entity; - } - - public override Task NewAsync(IParent? parent, Type? variantType = null) - { - return Task.FromResult(new Blog()); - } - - public override async Task UpdateAsync(IEditContext editContext) - { - var entity = await _dbContext.Blogs.Include(x => x.BlogCategories).FirstAsync(x => x.Id == editContext.Entity.Id); - - entity.Content = editContext.Entity.Content; - entity.IsPublished = editContext.Entity.IsPublished; - entity.MainCategoryId = editContext.Entity.MainCategoryId; - entity.PublishDate = editContext.Entity.PublishDate; - entity.Title = editContext.Entity.Title; - entity.Type = editContext.Entity.Type; - - var relations = editContext.GetRelationContainer(); - await HandleBlogCategoriesAsync(entity, relations); - - await _dbContext.SaveChangesAsync(); - } - - private async Task HandleBlogCategoriesAsync(Blog dbEntity, IRelationContainer relations) - { - var selectedIds = relations.GetRelatedElementIdsFor, int>(x => x.BlogCategories) ?? Enumerable.Empty(); - var existingIds = dbEntity.BlogCategories.Select(x => x.Id); - - var itemsToRemove = dbEntity.BlogCategories.Where(x => !selectedIds.Contains(x.Id)).ToList(); - var idsToAdd = selectedIds.Except(existingIds).ToList(); - - var itemsToAdd = await _dbContext.Categories.Where(x => idsToAdd.Contains(x.Id)).ToListAsync(); - - foreach (var itemToRemove in itemsToRemove) - { - dbEntity.BlogCategories.Remove(itemToRemove); - } - foreach (var itemToAdd in itemsToAdd) - { - dbEntity.BlogCategories.Add(itemToAdd); - } - } - } -} -"; - - public const string EntityValidator = @"using System.Collections.Generic; -using FluentValidation; -using RapidCMS.Example.ModelMaker.Models.Validators; -using RapidCMS.ModelMaker.Validation; -using RapidCMS.ModelMaker.Validation.Config; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public class BlogValidator : AbstractValidatorAdapter - { - public BlogValidator() - { - RuleFor(x => x.Title) - .MinimumLength(1) - .MaximumLength(127) - .BannedContent(new BannedContentValidationConfig { BannedWords = new List { ""a"", ""b"", ""c"" } }); - RuleFor(x => x.IsPublished) - .NotNull(); - RuleFor(x => x.PublishDate) - .NotNull(); - RuleFor(x => x.MainCategoryId) - .NotNull(); - } - } -} -"; - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/SharedCode/CategoryCode.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/SharedCode/CategoryCode.cs deleted file mode 100644 index b78b22a6..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/SharedCode/CategoryCode.cs +++ /dev/null @@ -1,205 +0,0 @@ -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests.SharedCode -{ - public static class CategoryCode - { - public const string EntityWithBlog = @"using System.Collections.Generic; -using RapidCMS.Core.Abstractions.Data; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public partial class Category : IEntity - { - public int Id { get; set; } - string? IEntity.Id { get => Id.ToString(); set => Id = int.Parse(value ?? ""0""); } - - public System.String Name { get; set; } - - public ICollection BlogMainCategory { get; set; } = new List(); - - public ICollection BlogBlogCategories { get; set; } = new List(); - } -} -"; - - public const string EntityWithoutBlog = @"using RapidCMS.Core.Abstractions.Data; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public partial class Category : IEntity - { - public int Id { get; set; } - string? IEntity.Id { get => Id.ToString(); set => Id = int.Parse(value ?? ""0""); } - - public System.String Name { get; set; } - } -} -"; - - public const string Collection = @"using RapidCMS.Core.Abstractions.Config; -using RapidCMS.Core.Enums; -using RapidCMS.Core.Extensions; -using RapidCMS.Core.Providers; -using RapidCMS.Core.Repositories; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public static class CategoryCollection - { - public static void AddCategoryCollection(this ICmsConfig config) - { - config.AddCollection>( - ""categories"", - ""Tag"", - ""RedOrange10"", - ""Categories"", - collection => - { - collection.SetTreeView(x => x.Name); - collection.SetElementConfiguration(x => x.Id, x => x.Name); - collection.AddEntityValidator(); - collection.SetListView(view => - { - view.AddDefaultButton(DefaultButtonType.New); - view.AddRow(row => - { - row.AddField(x => x.Id.ToString()).SetName(""Id""); - row.AddField(x => x.Name).SetName(""Name""); - row.AddDefaultButton(DefaultButtonType.Edit); - row.AddDefaultButton(DefaultButtonType.Delete); - }); - }); - collection.SetNodeEditor(editor => - { - editor.AddDefaultButton(DefaultButtonType.Up); - editor.AddDefaultButton(DefaultButtonType.SaveExisting); - editor.AddDefaultButton(DefaultButtonType.SaveNew); - editor.AddSection(section => - { - section.AddField(x => x.Name).SetType(typeof(RapidCMS.UI.Components.Editors.TextBoxEditor)).SetName(""Name""); - }); - }); - }); - } - } -} -"; - - public const string EntityConfiguration = @"using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public class CategoryConfiguration : IEntityTypeConfiguration - { - public void Configure(EntityTypeBuilder builder) - { - } - } -} -"; - - public const string Repository = @"using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; -using RapidCMS.Core.Abstractions.Data; -using RapidCMS.Core.Abstractions.Forms; -using RapidCMS.Core.Repositories; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public class CategoryRepository : BaseRepository - { - private readonly ModelMakerDbContext _dbContext; - - public CategoryRepository(ModelMakerDbContext dbContext) - { - _dbContext = dbContext; - } - - public override async Task DeleteAsync(string id, IParent? parent) - { - if (int.TryParse(id, out var intId)) - { - var entity = await _dbContext.Categories.FirstOrDefaultAsync(x => x.Id == intId); - if (entity != null) - { - _dbContext.Categories.Remove(entity); - await _dbContext.SaveChangesAsync(); - } - } - } - - public override async Task> GetAllAsync(IParent? parent, IView view) - { - return await view.ApplyOrder(view.ApplyDataView(_dbContext.Categories)).Skip(view.Skip).Take(view.Take).AsNoTracking().ToListAsync(); - } - - public override async Task GetByIdAsync(string id, IParent? parent) - { - if (int.TryParse(id, out var intId)) - { - return await _dbContext.Categories.AsNoTracking().FirstOrDefaultAsync(x => x.Id == intId); - } - return default; - } - - public override async Task InsertAsync(IEditContext editContext) - { - var entity = editContext.Entity; - - var entry = _dbContext.Categories.Add(entity); - await _dbContext.SaveChangesAsync(); - return entry.Entity; - } - - public override Task NewAsync(IParent? parent, Type? variantType = null) - { - return Task.FromResult(new Category()); - } - - public override async Task UpdateAsync(IEditContext editContext) - { - var entity = await _dbContext.Categories.FirstAsync(x => x.Id == editContext.Entity.Id); - - entity.Name = editContext.Entity.Name; - - await _dbContext.SaveChangesAsync(); - } - } -} -"; - - public const string EntityValidator = @"using FluentValidation; -using RapidCMS.ModelMaker.Validation; -using RapidCMS.ModelMaker.Validation.Config; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public class CategoryValidator : AbstractValidatorAdapter - { - public CategoryValidator() - { - RuleFor(x => x.Name) - .NotNull() - .MinimumLength(1) - .MaximumLength(30); - } - } -} -"; - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/SharedCode/ContextCode.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/SharedCode/ContextCode.cs deleted file mode 100644 index 1a0ddad9..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/SharedCode/ContextCode.cs +++ /dev/null @@ -1,142 +0,0 @@ -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests.SharedCode -{ - public static class ContextCode - { - public const string BlogCategoryContext = @"using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public partial class ModelMakerDbContext : DbContext - { - public ModelMakerDbContext(DbContextOptions options) : base(options) - { - } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - base.OnModelCreating(modelBuilder); - - modelBuilder.ApplyConfiguration(new CategoryConfiguration()); - modelBuilder.ApplyConfiguration(new BlogConfiguration()); - } - - public DbSet Categories { get; set; } = default!; - - public DbSet Blogs { get; set; } = default!; - } -} -"; - - public const string CategoryContext = @"using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public partial class ModelMakerDbContext : DbContext - { - public ModelMakerDbContext(DbContextOptions options) : base(options) - { - } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - base.OnModelCreating(modelBuilder); - - modelBuilder.ApplyConfiguration(new CategoryConfiguration()); - } - - public DbSet Categories { get; set; } = default!; - } -} -"; - - public const string OneToManyContext = @"using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public partial class ModelMakerDbContext : DbContext - { - public ModelMakerDbContext(DbContextOptions options) : base(options) - { - } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - base.OnModelCreating(modelBuilder); - - modelBuilder.ApplyConfiguration(new OnetoManyManyConfiguration()); - modelBuilder.ApplyConfiguration(new OnetoManyOneConfiguration()); - } - - public DbSet OnetoManyManys { get; set; } = default!; - - public DbSet OnetoManyOnes { get; set; } = default!; - } -} -"; - - public const string ManyToManyContext = @"using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public partial class ModelMakerDbContext : DbContext - { - public ModelMakerDbContext(DbContextOptions options) : base(options) - { - } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - base.OnModelCreating(modelBuilder); - - modelBuilder.ApplyConfiguration(new ManytoManyManyAConfiguration()); - modelBuilder.ApplyConfiguration(new ManytoManyManyBConfiguration()); - } - - public DbSet ManytoManyManyAs { get; set; } = default!; - - public DbSet ManytoManyManyBs { get; set; } = default!; - } -} -"; - - public const string OneToOneContext = @"using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public partial class ModelMakerDbContext : DbContext - { - public ModelMakerDbContext(DbContextOptions options) : base(options) - { - } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - base.OnModelCreating(modelBuilder); - - modelBuilder.ApplyConfiguration(new OnetoOneOneAConfiguration()); - modelBuilder.ApplyConfiguration(new OnetoOneOneBConfiguration()); - } - - public DbSet OnetoOneOneAs { get; set; } = default!; - - public DbSet OnetoOneOneBs { get; set; } = default!; - } -} -"; - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/SharedCode/ManyToManyManyACode.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/SharedCode/ManyToManyManyACode.cs deleted file mode 100644 index 1cbe3f22..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/SharedCode/ManyToManyManyACode.cs +++ /dev/null @@ -1,191 +0,0 @@ -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests.SharedCode -{ - public static class ManyToManyManyACode - { - public const string Collection = @"using RapidCMS.Core.Abstractions.Config; -using RapidCMS.Core.Enums; -using RapidCMS.Core.Extensions; -using RapidCMS.Core.Providers; -using RapidCMS.Core.Repositories; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public static class ManytoManyManyACollection - { - public static void AddManytoManyManyACollection(this ICmsConfig config) - { - config.AddCollection>( - ""many-to-many-many-as"", - ""Database"", - ""PinkRed10"", - ""Many to Many - Many As"", - collection => - { - collection.SetTreeView(x => x.Name); - collection.SetElementConfiguration(x => x.Id, x => x.Name); - collection.AddEntityValidator(); - collection.SetListView(view => - { - view.AddDefaultButton(DefaultButtonType.New); - view.AddRow(row => - { - row.AddField(x => x.Id.ToString()).SetName(""Id""); - row.AddField(x => x.Name).SetName(""Name""); - row.AddDefaultButton(DefaultButtonType.Edit); - row.AddDefaultButton(DefaultButtonType.Delete); - }); - }); - collection.SetNodeEditor(editor => - { - editor.AddDefaultButton(DefaultButtonType.Up); - editor.AddDefaultButton(DefaultButtonType.SaveExisting); - editor.AddDefaultButton(DefaultButtonType.SaveNew); - editor.AddSection(section => - { - section.AddField(x => x.Name).SetType(typeof(RapidCMS.UI.Components.Editors.TextBoxEditor)).SetName(""Name""); - section.AddField(x => x.Bs).SetType(typeof(RapidCMS.UI.Components.Editors.EntitiesPicker)).SetCollectionRelation(""many-to-many-many-bs"").SetName(""Bs""); - }); - }); - }); - } - } -} -"; - public const string EntityTypeConfiguration = @"using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public class ManytoManyManyAConfiguration : IEntityTypeConfiguration - { - public void Configure(EntityTypeBuilder builder) - { - builder.HasMany(x => x.Bs).WithMany(x => x.As); - } - } -} -"; - public const string Entity = @"using System.Collections.Generic; -using RapidCMS.Core.Abstractions.Data; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public partial class ManytoManyManyA : IEntity - { - public int Id { get; set; } - string? IEntity.Id { get => Id.ToString(); set => Id = int.Parse(value ?? ""0""); } - - public System.String Name { get; set; } - - public ICollection Bs { get; set; } = new List(); - } -} -"; - public const string Repository = @"using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; -using RapidCMS.Core.Abstractions.Data; -using RapidCMS.Core.Abstractions.Forms; -using RapidCMS.Core.Repositories; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public class ManytoManyManyARepository : BaseRepository - { - private readonly ModelMakerDbContext _dbContext; - - public ManytoManyManyARepository(ModelMakerDbContext dbContext) - { - _dbContext = dbContext; - } - - public override async Task DeleteAsync(string id, IParent? parent) - { - if (int.TryParse(id, out var intId)) - { - var entity = await _dbContext.ManytoManyManyAs.Include(x => x.Bs).FirstOrDefaultAsync(x => x.Id == intId); - if (entity != null) - { - _dbContext.ManytoManyManyAs.Remove(entity); - await _dbContext.SaveChangesAsync(); - } - } - } - - public override async Task> GetAllAsync(IParent? parent, IView view) - { - return await view.ApplyOrder(view.ApplyDataView(_dbContext.ManytoManyManyAs)).Skip(view.Skip).Take(view.Take).AsNoTracking().ToListAsync(); - } - - public override async Task GetByIdAsync(string id, IParent? parent) - { - if (int.TryParse(id, out var intId)) - { - return await _dbContext.ManytoManyManyAs.Include(x => x.Bs).AsNoTracking().FirstOrDefaultAsync(x => x.Id == intId); - } - return default; - } - - public override async Task InsertAsync(IEditContext editContext) - { - var entity = editContext.Entity; - - var relations = editContext.GetRelationContainer(); - await HandleBsAsync(entity, relations); - - var entry = _dbContext.ManytoManyManyAs.Add(entity); - await _dbContext.SaveChangesAsync(); - return entry.Entity; - } - - public override Task NewAsync(IParent? parent, Type? variantType = null) - { - return Task.FromResult(new ManytoManyManyA()); - } - - public override async Task UpdateAsync(IEditContext editContext) - { - var entity = await _dbContext.ManytoManyManyAs.Include(x => x.Bs).FirstAsync(x => x.Id == editContext.Entity.Id); - - entity.Name = editContext.Entity.Name; - - var relations = editContext.GetRelationContainer(); - await HandleBsAsync(entity, relations); - - await _dbContext.SaveChangesAsync(); - } - - private async Task HandleBsAsync(ManytoManyManyA dbEntity, IRelationContainer relations) - { - var selectedIds = relations.GetRelatedElementIdsFor, int>(x => x.Bs) ?? Enumerable.Empty(); - var existingIds = dbEntity.Bs.Select(x => x.Id); - - var itemsToRemove = dbEntity.Bs.Where(x => !selectedIds.Contains(x.Id)).ToList(); - var idsToAdd = selectedIds.Except(existingIds).ToList(); - - var itemsToAdd = await _dbContext.ManytoManyManyBs.Where(x => idsToAdd.Contains(x.Id)).ToListAsync(); - - foreach (var itemToRemove in itemsToRemove) - { - dbEntity.Bs.Remove(itemToRemove); - } - foreach (var itemToAdd in itemsToAdd) - { - dbEntity.Bs.Add(itemToAdd); - } - } - } -} -"; - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/SharedCode/ManyToManyManyBCode.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/SharedCode/ManyToManyManyBCode.cs deleted file mode 100644 index 48464b84..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/SharedCode/ManyToManyManyBCode.cs +++ /dev/null @@ -1,191 +0,0 @@ -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests.SharedCode -{ - public static class ManyToManyManyBCode - { - public const string Collection = @"using RapidCMS.Core.Abstractions.Config; -using RapidCMS.Core.Enums; -using RapidCMS.Core.Extensions; -using RapidCMS.Core.Providers; -using RapidCMS.Core.Repositories; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public static class ManytoManyManyBCollection - { - public static void AddManytoManyManyBCollection(this ICmsConfig config) - { - config.AddCollection>( - ""many-to-many-many-bs"", - ""Database"", - ""PinkRed10"", - ""Many to Many - Many Bs"", - collection => - { - collection.SetTreeView(x => x.Name); - collection.SetElementConfiguration(x => x.Id, x => x.Name); - collection.AddEntityValidator(); - collection.SetListView(view => - { - view.AddDefaultButton(DefaultButtonType.New); - view.AddRow(row => - { - row.AddField(x => x.Id.ToString()).SetName(""Id""); - row.AddField(x => x.Name).SetName(""Name""); - row.AddDefaultButton(DefaultButtonType.Edit); - row.AddDefaultButton(DefaultButtonType.Delete); - }); - }); - collection.SetNodeEditor(editor => - { - editor.AddDefaultButton(DefaultButtonType.Up); - editor.AddDefaultButton(DefaultButtonType.SaveExisting); - editor.AddDefaultButton(DefaultButtonType.SaveNew); - editor.AddSection(section => - { - section.AddField(x => x.Name).SetType(typeof(RapidCMS.UI.Components.Editors.TextBoxEditor)).SetName(""Name""); - section.AddField(x => x.As).SetType(typeof(RapidCMS.UI.Components.Editors.EntitiesPicker)).SetCollectionRelation(""many-to-many-many-as"").SetName(""As""); - }); - }); - }); - } - } -} -"; - public const string EntityTypeConfiguration = @"using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public class ManytoManyManyBConfiguration : IEntityTypeConfiguration - { - public void Configure(EntityTypeBuilder builder) - { - builder.HasMany(x => x.As).WithMany(x => x.Bs); - } - } -} -"; - public const string Entity = @"using System.Collections.Generic; -using RapidCMS.Core.Abstractions.Data; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public partial class ManytoManyManyB : IEntity - { - public int Id { get; set; } - string? IEntity.Id { get => Id.ToString(); set => Id = int.Parse(value ?? ""0""); } - - public System.String Name { get; set; } - - public ICollection As { get; set; } = new List(); - } -} -"; - public const string Repository = @"using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; -using RapidCMS.Core.Abstractions.Data; -using RapidCMS.Core.Abstractions.Forms; -using RapidCMS.Core.Repositories; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public class ManytoManyManyBRepository : BaseRepository - { - private readonly ModelMakerDbContext _dbContext; - - public ManytoManyManyBRepository(ModelMakerDbContext dbContext) - { - _dbContext = dbContext; - } - - public override async Task DeleteAsync(string id, IParent? parent) - { - if (int.TryParse(id, out var intId)) - { - var entity = await _dbContext.ManytoManyManyBs.Include(x => x.As).FirstOrDefaultAsync(x => x.Id == intId); - if (entity != null) - { - _dbContext.ManytoManyManyBs.Remove(entity); - await _dbContext.SaveChangesAsync(); - } - } - } - - public override async Task> GetAllAsync(IParent? parent, IView view) - { - return await view.ApplyOrder(view.ApplyDataView(_dbContext.ManytoManyManyBs)).Skip(view.Skip).Take(view.Take).AsNoTracking().ToListAsync(); - } - - public override async Task GetByIdAsync(string id, IParent? parent) - { - if (int.TryParse(id, out var intId)) - { - return await _dbContext.ManytoManyManyBs.Include(x => x.As).AsNoTracking().FirstOrDefaultAsync(x => x.Id == intId); - } - return default; - } - - public override async Task InsertAsync(IEditContext editContext) - { - var entity = editContext.Entity; - - var relations = editContext.GetRelationContainer(); - await HandleAsAsync(entity, relations); - - var entry = _dbContext.ManytoManyManyBs.Add(entity); - await _dbContext.SaveChangesAsync(); - return entry.Entity; - } - - public override Task NewAsync(IParent? parent, Type? variantType = null) - { - return Task.FromResult(new ManytoManyManyB()); - } - - public override async Task UpdateAsync(IEditContext editContext) - { - var entity = await _dbContext.ManytoManyManyBs.Include(x => x.As).FirstAsync(x => x.Id == editContext.Entity.Id); - - entity.Name = editContext.Entity.Name; - - var relations = editContext.GetRelationContainer(); - await HandleAsAsync(entity, relations); - - await _dbContext.SaveChangesAsync(); - } - - private async Task HandleAsAsync(ManytoManyManyB dbEntity, IRelationContainer relations) - { - var selectedIds = relations.GetRelatedElementIdsFor, int>(x => x.As) ?? Enumerable.Empty(); - var existingIds = dbEntity.As.Select(x => x.Id); - - var itemsToRemove = dbEntity.As.Where(x => !selectedIds.Contains(x.Id)).ToList(); - var idsToAdd = selectedIds.Except(existingIds).ToList(); - - var itemsToAdd = await _dbContext.ManytoManyManyAs.Where(x => idsToAdd.Contains(x.Id)).ToListAsync(); - - foreach (var itemToRemove in itemsToRemove) - { - dbEntity.As.Remove(itemToRemove); - } - foreach (var itemToAdd in itemsToAdd) - { - dbEntity.As.Add(itemToAdd); - } - } - } -} -"; - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/SharedCode/OneToManyManyCode.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/SharedCode/OneToManyManyCode.cs deleted file mode 100644 index 98487a48..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/SharedCode/OneToManyManyCode.cs +++ /dev/null @@ -1,191 +0,0 @@ -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests.SharedCode -{ - public static class OneToManyManyCode - { - public const string Collection = @"using RapidCMS.Core.Abstractions.Config; -using RapidCMS.Core.Enums; -using RapidCMS.Core.Extensions; -using RapidCMS.Core.Providers; -using RapidCMS.Core.Repositories; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public static class OnetoManyManyCollection - { - public static void AddOnetoManyManyCollection(this ICmsConfig config) - { - config.AddCollection>( - ""one-to-many-manys"", - ""Database"", - ""Cyan30"", - ""One to Many - Manys"", - collection => - { - collection.SetTreeView(x => x.Name); - collection.SetElementConfiguration(x => x.Id, x => x.Name); - collection.AddEntityValidator(); - collection.SetListView(view => - { - view.AddDefaultButton(DefaultButtonType.New); - view.AddRow(row => - { - row.AddField(x => x.Id.ToString()).SetName(""Id""); - row.AddField(x => x.Name).SetName(""Name""); - row.AddDefaultButton(DefaultButtonType.Edit); - row.AddDefaultButton(DefaultButtonType.Delete); - }); - }); - collection.SetNodeEditor(editor => - { - editor.AddDefaultButton(DefaultButtonType.Up); - editor.AddDefaultButton(DefaultButtonType.SaveExisting); - editor.AddDefaultButton(DefaultButtonType.SaveNew); - editor.AddSection(section => - { - section.AddField(x => x.Name).SetType(typeof(RapidCMS.UI.Components.Editors.TextBoxEditor)).SetName(""Name""); - section.AddField(x => x.Many).SetType(typeof(RapidCMS.UI.Components.Editors.EntitiesPicker)).SetCollectionRelation(""one-to-many-ones"").SetName(""Many""); - }); - }); - }); - } - } -} -"; - public const string EntityTypeConfiguration = @"using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public class OnetoManyManyConfiguration : IEntityTypeConfiguration - { - public void Configure(EntityTypeBuilder builder) - { - builder.HasMany(x => x.Many).WithOne(x => x.One).OnDelete(DeleteBehavior.NoAction); - } - } -} -"; - public const string Entity = @"using System.Collections.Generic; -using RapidCMS.Core.Abstractions.Data; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public partial class OnetoManyMany : IEntity - { - public int Id { get; set; } - string? IEntity.Id { get => Id.ToString(); set => Id = int.Parse(value ?? ""0""); } - - public System.String Name { get; set; } - - public ICollection Many { get; set; } = new List(); - } -} -"; - public const string Repository = @"using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; -using RapidCMS.Core.Abstractions.Data; -using RapidCMS.Core.Abstractions.Forms; -using RapidCMS.Core.Repositories; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public class OnetoManyManyRepository : BaseRepository - { - private readonly ModelMakerDbContext _dbContext; - - public OnetoManyManyRepository(ModelMakerDbContext dbContext) - { - _dbContext = dbContext; - } - - public override async Task DeleteAsync(string id, IParent? parent) - { - if (int.TryParse(id, out var intId)) - { - var entity = await _dbContext.OnetoManyManys.Include(x => x.Many).FirstOrDefaultAsync(x => x.Id == intId); - if (entity != null) - { - _dbContext.OnetoManyManys.Remove(entity); - await _dbContext.SaveChangesAsync(); - } - } - } - - public override async Task> GetAllAsync(IParent? parent, IView view) - { - return await view.ApplyOrder(view.ApplyDataView(_dbContext.OnetoManyManys)).Skip(view.Skip).Take(view.Take).AsNoTracking().ToListAsync(); - } - - public override async Task GetByIdAsync(string id, IParent? parent) - { - if (int.TryParse(id, out var intId)) - { - return await _dbContext.OnetoManyManys.Include(x => x.Many).AsNoTracking().FirstOrDefaultAsync(x => x.Id == intId); - } - return default; - } - - public override async Task InsertAsync(IEditContext editContext) - { - var entity = editContext.Entity; - - var relations = editContext.GetRelationContainer(); - await HandleManyAsync(entity, relations); - - var entry = _dbContext.OnetoManyManys.Add(entity); - await _dbContext.SaveChangesAsync(); - return entry.Entity; - } - - public override Task NewAsync(IParent? parent, Type? variantType = null) - { - return Task.FromResult(new OnetoManyMany()); - } - - public override async Task UpdateAsync(IEditContext editContext) - { - var entity = await _dbContext.OnetoManyManys.Include(x => x.Many).FirstAsync(x => x.Id == editContext.Entity.Id); - - entity.Name = editContext.Entity.Name; - - var relations = editContext.GetRelationContainer(); - await HandleManyAsync(entity, relations); - - await _dbContext.SaveChangesAsync(); - } - - private async Task HandleManyAsync(OnetoManyMany dbEntity, IRelationContainer relations) - { - var selectedIds = relations.GetRelatedElementIdsFor, int>(x => x.Many) ?? Enumerable.Empty(); - var existingIds = dbEntity.Many.Select(x => x.Id); - - var itemsToRemove = dbEntity.Many.Where(x => !selectedIds.Contains(x.Id)).ToList(); - var idsToAdd = selectedIds.Except(existingIds).ToList(); - - var itemsToAdd = await _dbContext.OnetoManyOnes.Where(x => idsToAdd.Contains(x.Id)).ToListAsync(); - - foreach (var itemToRemove in itemsToRemove) - { - dbEntity.Many.Remove(itemToRemove); - } - foreach (var itemToAdd in itemsToAdd) - { - dbEntity.Many.Add(itemToAdd); - } - } - } -} -"; - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/SharedCode/OneToManyOneCode.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/SharedCode/OneToManyOneCode.cs deleted file mode 100644 index 8c71f68f..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/SharedCode/OneToManyOneCode.cs +++ /dev/null @@ -1,166 +0,0 @@ -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests.SharedCode -{ - public static class OneToManyOneCode - { - public const string Collection = @"using RapidCMS.Core.Abstractions.Config; -using RapidCMS.Core.Enums; -using RapidCMS.Core.Extensions; -using RapidCMS.Core.Providers; -using RapidCMS.Core.Repositories; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public static class OnetoManyOneCollection - { - public static void AddOnetoManyOneCollection(this ICmsConfig config) - { - config.AddCollection>( - ""one-to-many-ones"", - ""Database"", - ""Cyan30"", - ""One to Many - Ones"", - collection => - { - collection.SetTreeView(x => x.Name); - collection.SetElementConfiguration(x => x.Id, x => x.Name); - collection.AddEntityValidator(); - collection.SetListView(view => - { - view.AddDefaultButton(DefaultButtonType.New); - view.AddRow(row => - { - row.AddField(x => x.Id.ToString()).SetName(""Id""); - row.AddField(x => x.Name).SetName(""Name""); - row.AddDefaultButton(DefaultButtonType.Edit); - row.AddDefaultButton(DefaultButtonType.Delete); - }); - }); - collection.SetNodeEditor(editor => - { - editor.AddDefaultButton(DefaultButtonType.Up); - editor.AddDefaultButton(DefaultButtonType.SaveExisting); - editor.AddDefaultButton(DefaultButtonType.SaveNew); - editor.AddSection(section => - { - section.AddField(x => x.Name).SetType(typeof(RapidCMS.UI.Components.Editors.TextBoxEditor)).SetName(""Name""); - section.AddField(x => x.OneId).SetType(typeof(RapidCMS.UI.Components.Editors.EntityPicker)).SetCollectionRelation(""one-to-many-manys"").SetName(""One""); - }); - }); - }); - } - } -} -"; - public const string EntityTypeConfiguration = @"using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public class OnetoManyOneConfiguration : IEntityTypeConfiguration - { - public void Configure(EntityTypeBuilder builder) - { - builder.HasOne(x => x.One).WithMany(x => x.Many).OnDelete(DeleteBehavior.NoAction); - } - } -} -"; - public const string Entity = @"using RapidCMS.Core.Abstractions.Data; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public partial class OnetoManyOne : IEntity - { - public int Id { get; set; } - string? IEntity.Id { get => Id.ToString(); set => Id = int.Parse(value ?? ""0""); } - - public System.String Name { get; set; } - - public int? OneId { get; set; } - public RapidCMS.ModelMaker.OnetoManyMany? One { get; set; } - } -} -"; - public const string Repository = @"using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; -using RapidCMS.Core.Abstractions.Data; -using RapidCMS.Core.Abstractions.Forms; -using RapidCMS.Core.Repositories; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public class OnetoManyOneRepository : BaseRepository - { - private readonly ModelMakerDbContext _dbContext; - - public OnetoManyOneRepository(ModelMakerDbContext dbContext) - { - _dbContext = dbContext; - } - - public override async Task DeleteAsync(string id, IParent? parent) - { - if (int.TryParse(id, out var intId)) - { - var entity = await _dbContext.OnetoManyOnes.FirstOrDefaultAsync(x => x.Id == intId); - if (entity != null) - { - _dbContext.OnetoManyOnes.Remove(entity); - await _dbContext.SaveChangesAsync(); - } - } - } - - public override async Task> GetAllAsync(IParent? parent, IView view) - { - return await view.ApplyOrder(view.ApplyDataView(_dbContext.OnetoManyOnes)).Skip(view.Skip).Take(view.Take).AsNoTracking().ToListAsync(); - } - - public override async Task GetByIdAsync(string id, IParent? parent) - { - if (int.TryParse(id, out var intId)) - { - return await _dbContext.OnetoManyOnes.AsNoTracking().FirstOrDefaultAsync(x => x.Id == intId); - } - return default; - } - - public override async Task InsertAsync(IEditContext editContext) - { - var entity = editContext.Entity; - - var entry = _dbContext.OnetoManyOnes.Add(entity); - await _dbContext.SaveChangesAsync(); - return entry.Entity; - } - - public override Task NewAsync(IParent? parent, Type? variantType = null) - { - return Task.FromResult(new OnetoManyOne()); - } - - public override async Task UpdateAsync(IEditContext editContext) - { - var entity = await _dbContext.OnetoManyOnes.FirstAsync(x => x.Id == editContext.Entity.Id); - - entity.Name = editContext.Entity.Name; - entity.OneId = editContext.Entity.OneId; - - await _dbContext.SaveChangesAsync(); - } - } -} -"; - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/SharedCode/OneToOneOneACode.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/SharedCode/OneToOneOneACode.cs deleted file mode 100644 index 976443e9..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/SharedCode/OneToOneOneACode.cs +++ /dev/null @@ -1,165 +0,0 @@ -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests.SharedCode -{ - public static class OneToOneOneACode - { - public const string Collection = @"using RapidCMS.Core.Abstractions.Config; -using RapidCMS.Core.Enums; -using RapidCMS.Core.Extensions; -using RapidCMS.Core.Providers; -using RapidCMS.Core.Repositories; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public static class OnetoOneOneACollection - { - public static void AddOnetoOneOneACollection(this ICmsConfig config) - { - config.AddCollection>( - ""one-to-one-one-as"", - ""Database"", - ""Orange10"", - ""One to One - One As"", - collection => - { - collection.SetTreeView(x => x.Name); - collection.SetElementConfiguration(x => x.Id, x => x.Name); - collection.AddEntityValidator(); - collection.SetListView(view => - { - view.AddDefaultButton(DefaultButtonType.New); - view.AddRow(row => - { - row.AddField(x => x.Id.ToString()).SetName(""Id""); - row.AddField(x => x.Name).SetName(""Name""); - row.AddDefaultButton(DefaultButtonType.Edit); - row.AddDefaultButton(DefaultButtonType.Delete); - }); - }); - collection.SetNodeEditor(editor => - { - editor.AddDefaultButton(DefaultButtonType.Up); - editor.AddDefaultButton(DefaultButtonType.SaveExisting); - editor.AddDefaultButton(DefaultButtonType.SaveNew); - editor.AddSection(section => - { - section.AddField(x => x.Name).SetType(typeof(RapidCMS.UI.Components.Editors.TextBoxEditor)).SetName(""Name""); - section.AddField(x => x.BId).SetType(typeof(RapidCMS.UI.Components.Editors.EntityPicker)).SetCollectionRelation(""one-to-one-one-bs"").SetName(""B""); - }); - }); - }); - } - } -} -"; - public const string EntityTypeConfiguration = @"using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public class OnetoOneOneAConfiguration : IEntityTypeConfiguration - { - public void Configure(EntityTypeBuilder builder) - { - } - } -} -"; - public const string Entity = @"using RapidCMS.Core.Abstractions.Data; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public partial class OnetoOneOneA : IEntity - { - public int Id { get; set; } - string? IEntity.Id { get => Id.ToString(); set => Id = int.Parse(value ?? ""0""); } - - public System.String Name { get; set; } - - public int? BId { get; set; } - public RapidCMS.ModelMaker.OnetoOneOneB? B { get; set; } - } -} -"; - public const string Repository = @"using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; -using RapidCMS.Core.Abstractions.Data; -using RapidCMS.Core.Abstractions.Forms; -using RapidCMS.Core.Repositories; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public class OnetoOneOneARepository : BaseRepository - { - private readonly ModelMakerDbContext _dbContext; - - public OnetoOneOneARepository(ModelMakerDbContext dbContext) - { - _dbContext = dbContext; - } - - public override async Task DeleteAsync(string id, IParent? parent) - { - if (int.TryParse(id, out var intId)) - { - var entity = await _dbContext.OnetoOneOneAs.FirstOrDefaultAsync(x => x.Id == intId); - if (entity != null) - { - _dbContext.OnetoOneOneAs.Remove(entity); - await _dbContext.SaveChangesAsync(); - } - } - } - - public override async Task> GetAllAsync(IParent? parent, IView view) - { - return await view.ApplyOrder(view.ApplyDataView(_dbContext.OnetoOneOneAs)).Skip(view.Skip).Take(view.Take).AsNoTracking().ToListAsync(); - } - - public override async Task GetByIdAsync(string id, IParent? parent) - { - if (int.TryParse(id, out var intId)) - { - return await _dbContext.OnetoOneOneAs.AsNoTracking().FirstOrDefaultAsync(x => x.Id == intId); - } - return default; - } - - public override async Task InsertAsync(IEditContext editContext) - { - var entity = editContext.Entity; - - var entry = _dbContext.OnetoOneOneAs.Add(entity); - await _dbContext.SaveChangesAsync(); - return entry.Entity; - } - - public override Task NewAsync(IParent? parent, Type? variantType = null) - { - return Task.FromResult(new OnetoOneOneA()); - } - - public override async Task UpdateAsync(IEditContext editContext) - { - var entity = await _dbContext.OnetoOneOneAs.FirstAsync(x => x.Id == editContext.Entity.Id); - - entity.BId = editContext.Entity.BId; - entity.Name = editContext.Entity.Name; - - await _dbContext.SaveChangesAsync(); - } - } -} -"; - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/SharedCode/OneToOneOneBCode.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/SharedCode/OneToOneOneBCode.cs deleted file mode 100644 index c846f358..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/SharedCode/OneToOneOneBCode.cs +++ /dev/null @@ -1,164 +0,0 @@ -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests.SharedCode -{ - public static class OneToOneOneBCode - { - public const string Collection = @"using RapidCMS.Core.Abstractions.Config; -using RapidCMS.Core.Enums; -using RapidCMS.Core.Extensions; -using RapidCMS.Core.Providers; -using RapidCMS.Core.Repositories; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public static class OnetoOneOneBCollection - { - public static void AddOnetoOneOneBCollection(this ICmsConfig config) - { - config.AddCollection>( - ""one-to-one-one-bs"", - ""Database"", - ""Orange10"", - ""One to One - One Bs"", - collection => - { - collection.SetTreeView(x => x.Name); - collection.SetElementConfiguration(x => x.Id, x => x.Name); - collection.AddEntityValidator(); - collection.SetListView(view => - { - view.AddDefaultButton(DefaultButtonType.New); - view.AddRow(row => - { - row.AddField(x => x.Id.ToString()).SetName(""Id""); - row.AddField(x => x.Name).SetName(""Name""); - row.AddDefaultButton(DefaultButtonType.Edit); - row.AddDefaultButton(DefaultButtonType.Delete); - }); - }); - collection.SetNodeEditor(editor => - { - editor.AddDefaultButton(DefaultButtonType.Up); - editor.AddDefaultButton(DefaultButtonType.SaveExisting); - editor.AddDefaultButton(DefaultButtonType.SaveNew); - editor.AddSection(section => - { - section.AddField(x => x.Name).SetType(typeof(RapidCMS.UI.Components.Editors.TextBoxEditor)).SetName(""Name""); - section.AddField(x => x.A == null ? 0 : x.A.Id).DisableWhen((e, s) => true).SetType(typeof(RapidCMS.UI.Components.Editors.EntityPicker)).SetCollectionRelation(""one-to-one-one-as"").SetName(""A""); - }); - }); - }); - } - } -} -"; - public const string EntityTypeConfiguration = @"using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public class OnetoOneOneBConfiguration : IEntityTypeConfiguration - { - public void Configure(EntityTypeBuilder builder) - { - builder.HasOne(x => x.A).WithOne(x => x.B).HasForeignKey(x => x.BId).OnDelete(DeleteBehavior.NoAction); - } - } -} -"; - public const string Entity = @"using RapidCMS.Core.Abstractions.Data; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public partial class OnetoOneOneB : IEntity - { - public int Id { get; set; } - string? IEntity.Id { get => Id.ToString(); set => Id = int.Parse(value ?? ""0""); } - - public System.String Name { get; set; } - - public RapidCMS.ModelMaker.OnetoOneOneA? A { get; set; } - } -} -"; - public const string Repository = @"using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; -using RapidCMS.Core.Abstractions.Data; -using RapidCMS.Core.Abstractions.Forms; -using RapidCMS.Core.Repositories; - -#nullable enable - -namespace RapidCMS.ModelMaker -{ - public class OnetoOneOneBRepository : BaseRepository - { - private readonly ModelMakerDbContext _dbContext; - - public OnetoOneOneBRepository(ModelMakerDbContext dbContext) - { - _dbContext = dbContext; - } - - public override async Task DeleteAsync(string id, IParent? parent) - { - if (int.TryParse(id, out var intId)) - { - var entity = await _dbContext.OnetoOneOneBs.Include(x => x.A).FirstOrDefaultAsync(x => x.Id == intId); - if (entity != null) - { - _dbContext.OnetoOneOneBs.Remove(entity); - await _dbContext.SaveChangesAsync(); - } - } - } - - public override async Task> GetAllAsync(IParent? parent, IView view) - { - return await view.ApplyOrder(view.ApplyDataView(_dbContext.OnetoOneOneBs)).Skip(view.Skip).Take(view.Take).AsNoTracking().ToListAsync(); - } - - public override async Task GetByIdAsync(string id, IParent? parent) - { - if (int.TryParse(id, out var intId)) - { - return await _dbContext.OnetoOneOneBs.Include(x => x.A).AsNoTracking().FirstOrDefaultAsync(x => x.Id == intId); - } - return default; - } - - public override async Task InsertAsync(IEditContext editContext) - { - var entity = editContext.Entity; - - var entry = _dbContext.OnetoOneOneBs.Add(entity); - await _dbContext.SaveChangesAsync(); - return entry.Entity; - } - - public override Task NewAsync(IParent? parent, Type? variantType = null) - { - return Task.FromResult(new OnetoOneOneB()); - } - - public override async Task UpdateAsync(IEditContext editContext) - { - var entity = await _dbContext.OnetoOneOneBs.Include(x => x.A).FirstAsync(x => x.Id == editContext.Entity.Id); - - entity.Name = editContext.Entity.Name; - - await _dbContext.SaveChangesAsync(); - } - } -} -"; - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.blog.json b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.blog.json deleted file mode 100644 index ebee4abb..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.blog.json +++ /dev/null @@ -1,284 +0,0 @@ -{ - "$type": "RapidCMS.ModelMaker.Models.Entities.ModelEntity, RapidCMS.ModelMaker", - "Id": "blogs", - "ParentId": null, - "Name": "Blog", - "PluralName": "Blogs", - "IconColor": "Cyan30", - "Icon": "Blog", - "Alias": "blogs", - "Output": "Entity, Collection, Repository, Context, Validation", - "Properties": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "a613c87e-1d94-4a93-b8c3-afc7f93ceeec", - "Name": "Title", - "IsTitle": true, - "IncludeInListView": false, - "IsRequired": false, - "PropertyAlias": "shortstring", - "EditorAlias": "textbox", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.MinLengthDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "bc3a23e2-6be8-4e9e-ae99-1737fc365868", - "Alias": "minlength", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.MinLengthDetailConfig, RapidCMS.ModelMaker", - "MinLength": 1, - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": "MinimumLength", - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.MaxLengthDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "267dedbb-7667-4dab-a3c4-18c1d63dc6d2", - "Alias": "maxlength", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.MaxLengthDetailConfig, RapidCMS.ModelMaker", - "MaxLength": 127, - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": "MaximumLength", - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.Example.ModelMaker.Models.Validators.BannedContentValidationConfig, RapidCMS.Example.ModelMaker.Models]], RapidCMS.ModelMaker", - "Id": "3c3a802f-0b1a-48de-9d73-426b96178a84", - "Alias": "bannedContent", - "Config": { - "$type": "RapidCMS.Example.ModelMaker.Models.Validators.BannedContentValidationConfig, RapidCMS.Example.ModelMaker.Models", - "BannedWords": { - "$type": "System.Collections.Generic.List`1[[System.String, System.Private.CoreLib]], System.Private.CoreLib", - "$values": [ - "a", - "b", - "c" - ] - }, - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "DataCollectionExpression": null, - "ValidationMethodName": "BannedContent", - "DataCollectionType": null - } - } - ] - }, - "Type": "System.String", - "IsRelationToOne": false, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.TextBoxEditor" - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "bdc39e0c-53ec-4106-b373-babe19d5202d", - "Name": "Content", - "IsTitle": false, - "IncludeInListView": true, - "IsRequired": false, - "PropertyAlias": "longstring", - "EditorAlias": "textarea", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [] - }, - "Type": "System.String", - "IsRelationToOne": false, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.TextAreaEditor" - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "f048d0f0-4d82-48a1-86b2-2d98d98c4a0f", - "Name": "Type", - "IsTitle": false, - "IncludeInListView": false, - "IsRequired": false, - "PropertyAlias": "contentType", - "EditorAlias": "dropdown", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.DataCollectionConfig`1[[RapidCMS.Core.Providers.EnumDataProvider`1[[RapidCMS.Example.ModelMaker.Models.Enums.ContentType, RapidCMS.Example.ModelMaker.Models]], RapidCMS.Core]], RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "2f38b24e-a1ea-43e7-a134-83b1dca3311a", - "Alias": "contentTypeValidator", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.DataCollectionConfig`1[[RapidCMS.Core.Providers.EnumDataProvider`1[[RapidCMS.Example.ModelMaker.Models.Enums.ContentType, RapidCMS.Example.ModelMaker.Models]], RapidCMS.Core]], RapidCMS.ModelMaker", - "IsEnabled": true, - "AlwaysIncluded": true, - "RelatedCollectionAlias": null, - "ValidationMethodName": null, - "DataCollectionType": "RapidCMS.Core.Providers.EnumDataProvider`1[[RapidCMS.Example.ModelMaker.Models.Enums.ContentType, RapidCMS.Example.ModelMaker.Models, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]" - } - } - ] - }, - "Type": "RapidCMS.Example.ModelMaker.Models.Enums.ContentType", - "IsRelationToOne": false, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.DropdownEditor" - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "0ac86254-34f7-4d9d-96d8-e60acb888837", - "Name": "Is Published", - "IsTitle": false, - "IncludeInListView": false, - "IsRequired": true, - "PropertyAlias": "boolean", - "EditorAlias": "dropdown", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.BooleanLabelDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "ab61dc5d-ed1c-4cc5-a9f3-c05f557ffbb0", - "Alias": "booleanLabels", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.BooleanLabelDetailConfig, RapidCMS.ModelMaker", - "Labels": { - "$type": "RapidCMS.ModelMaker.Validation.Config.BooleanLabelDetailConfig+LabelsConfig, RapidCMS.ModelMaker", - "TrueLabel": "True", - "FalseLabel": "False" - }, - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "DataCollectionType": "RapidCMS.ModelMaker.DataCollections.BooleanLabelDataCollection", - "ValidationMethodName": null - } - } - ] - }, - "Type": "System.Boolean", - "IsRelationToOne": false, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.DropdownEditor" - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "363423fe-3e3c-4ca3-b458-ea3255699357", - "Name": "Publish Date", - "IsTitle": false, - "IncludeInListView": false, - "IsRequired": true, - "PropertyAlias": "date", - "EditorAlias": "date", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [] - }, - "Type": "System.DateTime", - "IsRelationToOne": false, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.DateEditor" - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "6f0e59b0-6331-4c82-8af0-3daa5cf149b8", - "Name": "Main Category", - "IsTitle": false, - "IncludeInListView": false, - "IsRequired": true, - "PropertyAlias": "linkedentity", - "EditorAlias": "entitypicker", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.LinkedEntityDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "d2cf374d-0ce8-433c-a2b4-398baaa24f5c", - "Alias": "linkedEntity", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.LinkedEntityDetailConfig, RapidCMS.ModelMaker", - "LinkedEntityCollectionAlias": "categories", - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": "categories", - "ValidationMethodName": null, - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "f204aaa6-9158-403d-83d6-ed35a03dca1f", - "Alias": "reciprocal", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker", - "RelatedPropertyName": null, - "IsEnabled": false, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": null, - "DataCollectionType": null - } - } - ] - }, - "Type": "RapidCMS.ModelMaker.Category", - "IsRelationToOne": true, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.EntityPicker" - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "80221276-0404-44f3-ad4b-524b73fa81ac", - "Name": "Blog Categories", - "IsTitle": false, - "IncludeInListView": false, - "IsRequired": false, - "PropertyAlias": "linkedentities", - "EditorAlias": "entitiespicker", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.LinkedEntitiesDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "2855b532-bbe7-4173-b08d-7001db04b9bf", - "Alias": "linkedEntities", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.LinkedEntitiesDetailConfig, RapidCMS.ModelMaker", - "LinkedEntitiesCollectionAlias": "categories", - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": "categories", - "ValidationMethodName": null, - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "f426387c-5fd1-46b6-9fc4-14e2808685e3", - "Alias": "reciprocal", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker", - "RelatedPropertyName": null, - "IsEnabled": false, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": null, - "DataCollectionType": null - } - } - ] - }, - "Type": "RapidCMS.ModelMaker.Category", - "IsRelationToOne": false, - "IsRelationToMany": true, - "EditorType": "RapidCMS.UI.Components.Editors.EntitiesPicker" - } - ] - } -} \ No newline at end of file diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.category.collection-only.json b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.category.collection-only.json deleted file mode 100644 index 8bfef195..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.category.collection-only.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "$type": "RapidCMS.ModelMaker.Models.Entities.ModelEntity, RapidCMS.ModelMaker", - "Id": "categories", - "ParentId": null, - "Name": "Category", - "PluralName": "Categories", - "IconColor": "RedOrange10", - "Icon": "Tag", - "Alias": "categories", - "Output": "Collection", - "Properties": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "a7493699-0e57-43da-bb58-a505b779a8fc", - "Name": "Name", - "IsTitle": true, - "IncludeInListView": false, - "IsRequired": true, - "PropertyAlias": "shortstring", - "EditorAlias": "textbox", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.MinLengthDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "817858b0-708a-4d99-b28a-0098a2c0b180", - "Alias": "minlength", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.MinLengthDetailConfig, RapidCMS.ModelMaker", - "MinLength": 1, - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": "MinimumLength", - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.MaxLengthDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "b164d80b-0f48-44f9-9ff5-ff732204bf05", - "Alias": "maxlength", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.MaxLengthDetailConfig, RapidCMS.ModelMaker", - "MaxLength": 30, - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": "MaximumLength", - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.Example.ModelMaker.Models.Validators.BannedContentValidationConfig, RapidCMS.Example.ModelMaker.Models]], RapidCMS.ModelMaker", - "Id": "7c98b180-9c72-4d66-b753-b24868b8d9b8", - "Alias": "bannedContent", - "Config": { - "$type": "RapidCMS.Example.ModelMaker.Models.Validators.BannedContentValidationConfig, RapidCMS.Example.ModelMaker.Models", - "BannedWords": { - "$type": "System.Collections.Generic.List`1[[System.String, System.Private.CoreLib]], System.Private.CoreLib", - "$values": [] - }, - "IsEnabled": false, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "DataCollectionExpression": null, - "ValidationMethodName": "BannedContent", - "DataCollectionType": null - } - } - ] - }, - "Type": "System.String", - "IsRelationToOne": false, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.TextBoxEditor" - } - ] - } -} \ No newline at end of file diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.category.context-only.json b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.category.context-only.json deleted file mode 100644 index f28b7a5d..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.category.context-only.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "$type": "RapidCMS.ModelMaker.Models.Entities.ModelEntity, RapidCMS.ModelMaker", - "Id": "categories", - "ParentId": null, - "Name": "Category", - "PluralName": "Categories", - "IconColor": "RedOrange10", - "Icon": "Tag", - "Alias": "categories", - "Output": "Context", - "Properties": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "a7493699-0e57-43da-bb58-a505b779a8fc", - "Name": "Name", - "IsTitle": true, - "IncludeInListView": false, - "IsRequired": true, - "PropertyAlias": "shortstring", - "EditorAlias": "textbox", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.MinLengthDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "817858b0-708a-4d99-b28a-0098a2c0b180", - "Alias": "minlength", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.MinLengthDetailConfig, RapidCMS.ModelMaker", - "MinLength": 1, - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": "MinimumLength", - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.MaxLengthDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "b164d80b-0f48-44f9-9ff5-ff732204bf05", - "Alias": "maxlength", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.MaxLengthDetailConfig, RapidCMS.ModelMaker", - "MaxLength": 30, - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": "MaximumLength", - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.Example.ModelMaker.Models.Validators.BannedContentValidationConfig, RapidCMS.Example.ModelMaker.Models]], RapidCMS.ModelMaker", - "Id": "7c98b180-9c72-4d66-b753-b24868b8d9b8", - "Alias": "bannedContent", - "Config": { - "$type": "RapidCMS.Example.ModelMaker.Models.Validators.BannedContentValidationConfig, RapidCMS.Example.ModelMaker.Models", - "BannedWords": { - "$type": "System.Collections.Generic.List`1[[System.String, System.Private.CoreLib]], System.Private.CoreLib", - "$values": [] - }, - "IsEnabled": false, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "DataCollectionExpression": null, - "ValidationMethodName": "BannedContent", - "DataCollectionType": null - } - } - ] - }, - "Type": "System.String", - "IsRelationToOne": false, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.TextBoxEditor" - } - ] - } -} \ No newline at end of file diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.category.entity-only.json b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.category.entity-only.json deleted file mode 100644 index 2e115829..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.category.entity-only.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "$type": "RapidCMS.ModelMaker.Models.Entities.ModelEntity, RapidCMS.ModelMaker", - "Id": "categories", - "ParentId": null, - "Name": "Category", - "PluralName": "Categories", - "IconColor": "RedOrange10", - "Icon": "Tag", - "Alias": "categories", - "Output": "Entity", - "Properties": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "a7493699-0e57-43da-bb58-a505b779a8fc", - "Name": "Name", - "IsTitle": true, - "IncludeInListView": false, - "IsRequired": true, - "PropertyAlias": "shortstring", - "EditorAlias": "textbox", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.MinLengthDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "817858b0-708a-4d99-b28a-0098a2c0b180", - "Alias": "minlength", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.MinLengthDetailConfig, RapidCMS.ModelMaker", - "MinLength": 1, - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": "MinimumLength", - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.MaxLengthDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "b164d80b-0f48-44f9-9ff5-ff732204bf05", - "Alias": "maxlength", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.MaxLengthDetailConfig, RapidCMS.ModelMaker", - "MaxLength": 30, - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": "MaximumLength", - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.Example.ModelMaker.Models.Validators.BannedContentValidationConfig, RapidCMS.Example.ModelMaker.Models]], RapidCMS.ModelMaker", - "Id": "7c98b180-9c72-4d66-b753-b24868b8d9b8", - "Alias": "bannedContent", - "Config": { - "$type": "RapidCMS.Example.ModelMaker.Models.Validators.BannedContentValidationConfig, RapidCMS.Example.ModelMaker.Models", - "BannedWords": { - "$type": "System.Collections.Generic.List`1[[System.String, System.Private.CoreLib]], System.Private.CoreLib", - "$values": [] - }, - "IsEnabled": false, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "DataCollectionExpression": null, - "ValidationMethodName": "BannedContent", - "DataCollectionType": null - } - } - ] - }, - "Type": "System.String", - "IsRelationToOne": false, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.TextBoxEditor" - } - ] - } -} \ No newline at end of file diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.category.json b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.category.json deleted file mode 100644 index 8899daa1..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.category.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "$type": "RapidCMS.ModelMaker.Models.Entities.ModelEntity, RapidCMS.ModelMaker", - "Id": "categories", - "ParentId": null, - "Name": "Category", - "PluralName": "Categories", - "IconColor": "RedOrange10", - "Icon": "Tag", - "Alias": "categories", - "Output": "Entity, Collection, Repository, Context, Validation", - "Properties": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "a7493699-0e57-43da-bb58-a505b779a8fc", - "Name": "Name", - "IsTitle": true, - "IncludeInListView": false, - "IsRequired": true, - "PropertyAlias": "shortstring", - "EditorAlias": "textbox", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.MinLengthDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "817858b0-708a-4d99-b28a-0098a2c0b180", - "Alias": "minlength", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.MinLengthDetailConfig, RapidCMS.ModelMaker", - "MinLength": 1, - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": "MinimumLength", - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.MaxLengthDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "b164d80b-0f48-44f9-9ff5-ff732204bf05", - "Alias": "maxlength", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.MaxLengthDetailConfig, RapidCMS.ModelMaker", - "MaxLength": 30, - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": "MaximumLength", - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.Example.ModelMaker.Models.Validators.BannedContentValidationConfig, RapidCMS.Example.ModelMaker.Models]], RapidCMS.ModelMaker", - "Id": "7c98b180-9c72-4d66-b753-b24868b8d9b8", - "Alias": "bannedContent", - "Config": { - "$type": "RapidCMS.Example.ModelMaker.Models.Validators.BannedContentValidationConfig, RapidCMS.Example.ModelMaker.Models", - "BannedWords": { - "$type": "System.Collections.Generic.List`1[[System.String, System.Private.CoreLib]], System.Private.CoreLib", - "$values": [] - }, - "IsEnabled": false, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "DataCollectionExpression": null, - "ValidationMethodName": "BannedContent", - "DataCollectionType": null - } - } - ] - }, - "Type": "System.String", - "IsRelationToOne": false, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.TextBoxEditor" - } - ] - } -} \ No newline at end of file diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.category.repository-only.json b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.category.repository-only.json deleted file mode 100644 index 1779a5d0..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.category.repository-only.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "$type": "RapidCMS.ModelMaker.Models.Entities.ModelEntity, RapidCMS.ModelMaker", - "Id": "categories", - "ParentId": null, - "Name": "Category", - "PluralName": "Categories", - "IconColor": "RedOrange10", - "Icon": "Tag", - "Alias": "categories", - "Output": "Repository", - "Properties": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "a7493699-0e57-43da-bb58-a505b779a8fc", - "Name": "Name", - "IsTitle": true, - "IncludeInListView": false, - "IsRequired": true, - "PropertyAlias": "shortstring", - "EditorAlias": "textbox", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.MinLengthDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "817858b0-708a-4d99-b28a-0098a2c0b180", - "Alias": "minlength", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.MinLengthDetailConfig, RapidCMS.ModelMaker", - "MinLength": 1, - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": "MinimumLength", - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.MaxLengthDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "b164d80b-0f48-44f9-9ff5-ff732204bf05", - "Alias": "maxlength", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.MaxLengthDetailConfig, RapidCMS.ModelMaker", - "MaxLength": 30, - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": "MaximumLength", - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.Example.ModelMaker.Models.Validators.BannedContentValidationConfig, RapidCMS.Example.ModelMaker.Models]], RapidCMS.ModelMaker", - "Id": "7c98b180-9c72-4d66-b753-b24868b8d9b8", - "Alias": "bannedContent", - "Config": { - "$type": "RapidCMS.Example.ModelMaker.Models.Validators.BannedContentValidationConfig, RapidCMS.Example.ModelMaker.Models", - "BannedWords": { - "$type": "System.Collections.Generic.List`1[[System.String, System.Private.CoreLib]], System.Private.CoreLib", - "$values": [] - }, - "IsEnabled": false, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "DataCollectionExpression": null, - "ValidationMethodName": "BannedContent", - "DataCollectionType": null - } - } - ] - }, - "Type": "System.String", - "IsRelationToOne": false, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.TextBoxEditor" - } - ] - } -} \ No newline at end of file diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.category.validation-only.json b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.category.validation-only.json deleted file mode 100644 index ee87e770..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.category.validation-only.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "$type": "RapidCMS.ModelMaker.Models.Entities.ModelEntity, RapidCMS.ModelMaker", - "Id": "categories", - "ParentId": null, - "Name": "Category", - "PluralName": "Categories", - "IconColor": "RedOrange10", - "Icon": "Tag", - "Alias": "categories", - "Output": "Validation", - "Properties": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "a7493699-0e57-43da-bb58-a505b779a8fc", - "Name": "Name", - "IsTitle": true, - "IncludeInListView": false, - "IsRequired": true, - "PropertyAlias": "shortstring", - "EditorAlias": "textbox", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.MinLengthDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "817858b0-708a-4d99-b28a-0098a2c0b180", - "Alias": "minlength", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.MinLengthDetailConfig, RapidCMS.ModelMaker", - "MinLength": 1, - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": "MinimumLength", - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.MaxLengthDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "b164d80b-0f48-44f9-9ff5-ff732204bf05", - "Alias": "maxlength", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.MaxLengthDetailConfig, RapidCMS.ModelMaker", - "MaxLength": 30, - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": "MaximumLength", - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.Example.ModelMaker.Models.Validators.BannedContentValidationConfig, RapidCMS.Example.ModelMaker.Models]], RapidCMS.ModelMaker", - "Id": "7c98b180-9c72-4d66-b753-b24868b8d9b8", - "Alias": "bannedContent", - "Config": { - "$type": "RapidCMS.Example.ModelMaker.Models.Validators.BannedContentValidationConfig, RapidCMS.Example.ModelMaker.Models", - "BannedWords": { - "$type": "System.Collections.Generic.List`1[[System.String, System.Private.CoreLib]], System.Private.CoreLib", - "$values": [] - }, - "IsEnabled": false, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "DataCollectionExpression": null, - "ValidationMethodName": "BannedContent", - "DataCollectionType": null - } - } - ] - }, - "Type": "System.String", - "IsRelationToOne": false, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.TextBoxEditor" - } - ] - } -} \ No newline at end of file diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.many-to-many-many-as-explicit.json b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.many-to-many-many-as-explicit.json deleted file mode 100644 index c2fc0510..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.many-to-many-many-as-explicit.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "$type": "RapidCMS.ModelMaker.Models.Entities.ModelEntity, RapidCMS.ModelMaker", - "Id": "many-to-many-many-as", - "ParentId": null, - "Name": "Many to Many - Many A", - "PluralName": "Many to Many - Many As", - "IconColor": "PinkRed10", - "Icon": "Database", - "Alias": "many-to-many-many-as", - "Output": "Entity, Collection, Repository, Context", - "Properties": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "c410ac52-7c6e-45db-9170-976c1b48ba94", - "Name": "Name", - "IsTitle": true, - "IncludeInListView": false, - "IsRequired": false, - "PropertyAlias": "shortstring", - "EditorAlias": "textbox", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [] - }, - "Type": "System.String", - "IsRelationToOne": false, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.TextBoxEditor" - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "f863a088-40cf-4646-be17-b01382de82ea", - "Name": "Bs", - "IsTitle": false, - "IncludeInListView": false, - "IsRequired": false, - "PropertyAlias": "linkedentities", - "EditorAlias": "entitiespicker", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.LinkedEntitiesDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "7e5c1c5b-ace4-4e02-bbc8-1a010d73549c", - "Alias": "linkedEntities", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.LinkedEntitiesDetailConfig, RapidCMS.ModelMaker", - "LinkedEntitiesCollectionAlias": "many-to-many-many-bs", - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": "many-to-many-many-bs", - "ValidationMethodName": null, - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "0e5fb6fc-f17c-4c3b-adb9-fa50085dcd32", - "Alias": "reciprocal", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker", - "RelatedPropertyName": "As", - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": null, - "DataCollectionType": null - } - } - ] - }, - "Type": "RapidCMS.ModelMaker.ManytoManyManyB", - "IsRelationToOne": false, - "IsRelationToMany": true, - "EditorType": "RapidCMS.UI.Components.Editors.EntitiesPicker" - } - ] - } -} \ No newline at end of file diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.many-to-many-many-as-implicit.json b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.many-to-many-many-as-implicit.json deleted file mode 100644 index 8857bc4d..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.many-to-many-many-as-implicit.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "$type": "RapidCMS.ModelMaker.Models.Entities.ModelEntity, RapidCMS.ModelMaker", - "Id": "many-to-many-many-as", - "ParentId": null, - "Name": "Many to Many - Many A", - "PluralName": "Many to Many - Many As", - "IconColor": "PinkRed10", - "Icon": "Database", - "Alias": "many-to-many-many-as", - "Output": "Entity, Collection, Repository, Context", - "Properties": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "c410ac52-7c6e-45db-9170-976c1b48ba94", - "Name": "Name", - "IsTitle": true, - "IncludeInListView": false, - "IsRequired": false, - "PropertyAlias": "shortstring", - "EditorAlias": "textbox", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [] - }, - "Type": "System.String", - "IsRelationToOne": false, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.TextBoxEditor" - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "f863a088-40cf-4646-be17-b01382de82ea", - "Name": "Bs", - "IsTitle": false, - "IncludeInListView": false, - "IsRequired": false, - "PropertyAlias": "linkedentities", - "EditorAlias": "entitiespicker", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.LinkedEntitiesDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "7e5c1c5b-ace4-4e02-bbc8-1a010d73549c", - "Alias": "linkedEntities", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.LinkedEntitiesDetailConfig, RapidCMS.ModelMaker", - "LinkedEntitiesCollectionAlias": "many-to-many-many-bs", - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": "many-to-many-many-bs", - "ValidationMethodName": null, - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "0e5fb6fc-f17c-4c3b-adb9-fa50085dcd32", - "Alias": "reciprocal", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker", - "RelatedPropertyName": null, - "IsEnabled": false, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": null, - "DataCollectionType": null - } - } - ] - }, - "Type": "RapidCMS.ModelMaker.ManytoManyManyB", - "IsRelationToOne": false, - "IsRelationToMany": true, - "EditorType": "RapidCMS.UI.Components.Editors.EntitiesPicker" - } - ] - } -} \ No newline at end of file diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.many-to-many-many-bs.json b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.many-to-many-many-bs.json deleted file mode 100644 index 529fcfaf..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.many-to-many-many-bs.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "$type": "RapidCMS.ModelMaker.Models.Entities.ModelEntity, RapidCMS.ModelMaker", - "Id": "many-to-many-many-bs", - "ParentId": null, - "Name": "Many to Many - Many B", - "PluralName": "Many to Many - Many Bs", - "IconColor": "PinkRed10", - "Icon": "Database", - "Alias": "many-to-many-many-bs", - "Output": "Entity, Collection, Repository, Context", - "Properties": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "ed05c762-82f4-450f-8195-2dc8410d3d16", - "Name": "Name", - "IsTitle": true, - "IncludeInListView": false, - "IsRequired": false, - "PropertyAlias": "shortstring", - "EditorAlias": "textbox", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [] - }, - "Type": "System.String", - "IsRelationToOne": false, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.TextBoxEditor" - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "d4f4a864-f7d9-4898-badc-f559163cb5bd", - "Name": "As", - "IsTitle": false, - "IncludeInListView": false, - "IsRequired": false, - "PropertyAlias": "linkedentities", - "EditorAlias": "entitiespicker", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.LinkedEntitiesDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "5748822c-8c5c-47d1-af1a-f85cbe32cd8c", - "Alias": "linkedEntities", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.LinkedEntitiesDetailConfig, RapidCMS.ModelMaker", - "LinkedEntitiesCollectionAlias": "many-to-many-many-as", - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": "many-to-many-many-as", - "ValidationMethodName": null, - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "d6ac3b46-d528-4a39-bac3-1e7bee0a7a3d", - "Alias": "reciprocal", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker", - "RelatedPropertyName": "Bs", - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": null, - "DataCollectionType": null - } - } - ] - }, - "Type": "RapidCMS.ModelMaker.ManytoManyManyA", - "IsRelationToOne": false, - "IsRelationToMany": true, - "EditorType": "RapidCMS.UI.Components.Editors.EntitiesPicker" - } - ] - } -} \ No newline at end of file diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.one-to-many-manys.json b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.one-to-many-manys.json deleted file mode 100644 index 89cf2657..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.one-to-many-manys.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "$type": "RapidCMS.ModelMaker.Models.Entities.ModelEntity, RapidCMS.ModelMaker", - "Id": "one-to-many-manys", - "ParentId": null, - "Name": "One to Many - Many", - "PluralName": "One to Many - Manys", - "IconColor": "Cyan30", - "Icon": "Database", - "Alias": "one-to-many-manys", - "Output": "Entity, Collection, Repository, Context", - "Properties": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "bc7cf265-78b8-40d9-9a32-956296ec903f", - "Name": "Name", - "IsTitle": true, - "IncludeInListView": false, - "IsRequired": false, - "PropertyAlias": "shortstring", - "EditorAlias": "textbox", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [] - }, - "Type": "System.String", - "IsRelationToOne": false, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.TextBoxEditor" - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "506b2bf3-1cb9-4a6f-b256-08ee0587eff9", - "Name": "Many", - "IsTitle": false, - "IncludeInListView": false, - "IsRequired": false, - "PropertyAlias": "linkedentities", - "EditorAlias": "entitiespicker", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.LinkedEntitiesDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "27cd54c8-f4da-4a61-ab83-3a53c8dc6a27", - "Alias": "linkedEntities", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.LinkedEntitiesDetailConfig, RapidCMS.ModelMaker", - "LinkedEntitiesCollectionAlias": "one-to-many-ones", - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": "one-to-many-ones", - "ValidationMethodName": null, - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "3efbf6bd-43c1-46dc-8b6d-9b7505b20955", - "Alias": "reciprocal", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker", - "RelatedPropertyName": "One", - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": null, - "DataCollectionType": null - } - } - ] - }, - "Type": "RapidCMS.ModelMaker.OnetoManyOne", - "IsRelationToOne": false, - "IsRelationToMany": true, - "EditorType": "RapidCMS.UI.Components.Editors.EntitiesPicker" - } - ] - } -} \ No newline at end of file diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.one-to-many-ones.json b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.one-to-many-ones.json deleted file mode 100644 index 0240f9b9..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.one-to-many-ones.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "$type": "RapidCMS.ModelMaker.Models.Entities.ModelEntity, RapidCMS.ModelMaker", - "Id": "one-to-many-ones", - "ParentId": null, - "Name": "One to Many - One", - "PluralName": "One to Many - Ones", - "IconColor": "Cyan30", - "Icon": "Database", - "Alias": "one-to-many-ones", - "Output": "Entity, Collection, Repository, Context", - "Properties": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "bba63203-9d39-42a7-9b3e-80778d386ac3", - "Name": "Name", - "IsTitle": true, - "IncludeInListView": false, - "IsRequired": false, - "PropertyAlias": "shortstring", - "EditorAlias": "textbox", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [] - }, - "Type": "System.String", - "IsRelationToOne": false, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.TextBoxEditor" - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "8a605348-8956-4d97-a907-fa6a6e89f686", - "Name": "One", - "IsTitle": false, - "IncludeInListView": false, - "IsRequired": false, - "PropertyAlias": "linkedentity", - "EditorAlias": "entitypicker", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.LinkedEntityDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "f3fd7215-458d-46fd-a308-82f04b188432", - "Alias": "linkedEntity", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.LinkedEntityDetailConfig, RapidCMS.ModelMaker", - "LinkedEntityCollectionAlias": "one-to-many-manys", - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": "one-to-many-manys", - "ValidationMethodName": null, - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "de861ea1-89d8-42a9-986d-6f5b172123b8", - "Alias": "reciprocal", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker", - "RelatedPropertyName": "Many", - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": null, - "DataCollectionType": null - } - } - ] - }, - "Type": "RapidCMS.ModelMaker.OnetoManyMany", - "IsRelationToOne": true, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.EntityPicker" - } - ] - } -} \ No newline at end of file diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.one-to-one-one-as.json b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.one-to-one-one-as.json deleted file mode 100644 index c8a033da..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.one-to-one-one-as.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "$type": "RapidCMS.ModelMaker.Models.Entities.ModelEntity, RapidCMS.ModelMaker", - "Id": "one-to-one-one-as", - "ParentId": null, - "Name": "One to One - One A", - "PluralName": "One to One - One As", - "IconColor": "Orange10", - "Icon": "Database", - "Alias": "one-to-one-one-as", - "Output": "Entity, Collection, Repository, Context", - "Properties": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "eee6a34d-dca5-4546-9267-cc00d255099a", - "Name": "Name", - "IsTitle": true, - "IncludeInListView": false, - "IsRequired": false, - "PropertyAlias": "shortstring", - "EditorAlias": "textbox", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [] - }, - "Type": "System.String", - "IsRelationToOne": false, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.TextBoxEditor" - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "e818066b-ceb3-4313-8dae-9b535caed9bc", - "Name": "B", - "IsTitle": false, - "IncludeInListView": false, - "IsRequired": false, - "PropertyAlias": "linkedentity", - "EditorAlias": "entitypicker", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.LinkedEntityDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "822dc83e-6817-4b6f-8e82-d15026db1e9a", - "Alias": "linkedEntity", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.LinkedEntityDetailConfig, RapidCMS.ModelMaker", - "LinkedEntityCollectionAlias": "one-to-one-one-bs", - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": "one-to-one-one-bs", - "ValidationMethodName": null, - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "d9f7abe8-80f4-413c-beab-5517e06e6b0e", - "Alias": "reciprocal", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker", - "RelatedPropertyName": "A", - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": null, - "DataCollectionType": null - } - } - ] - }, - "Type": "RapidCMS.ModelMaker.OnetoOneOneB", - "IsRelationToOne": true, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.EntityPicker" - } - ] - } -} \ No newline at end of file diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.one-to-one-one-bs-explicit.json b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.one-to-one-one-bs-explicit.json deleted file mode 100644 index 7dc25625..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.one-to-one-one-bs-explicit.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "$type": "RapidCMS.ModelMaker.Models.Entities.ModelEntity, RapidCMS.ModelMaker", - "Id": "one-to-one-one-bs", - "ParentId": null, - "Name": "One to One - One B", - "PluralName": "One to One - One Bs", - "IconColor": "Orange10", - "Icon": "Database", - "Alias": "one-to-one-one-bs", - "Output": "Entity, Collection, Repository, Context", - "Properties": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "08824942-4c3a-404e-b0cd-7c0adce66a2c", - "Name": "Name", - "IsTitle": true, - "IncludeInListView": false, - "IsRequired": false, - "PropertyAlias": "shortstring", - "EditorAlias": "textbox", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [] - }, - "Type": "System.String", - "IsRelationToOne": false, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.TextBoxEditor" - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "525f29ce-6a74-4c08-b471-3ece78d90fb1", - "Name": "A", - "IsTitle": false, - "IncludeInListView": false, - "IsRequired": false, - "PropertyAlias": "linkedentity", - "EditorAlias": "entitypicker", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.LinkedEntityDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "72a6fc06-d85f-4324-bbf8-e51544ff3ea7", - "Alias": "linkedEntity", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.LinkedEntityDetailConfig, RapidCMS.ModelMaker", - "LinkedEntityCollectionAlias": "one-to-one-one-as", - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": "one-to-one-one-as", - "ValidationMethodName": null, - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "cc85f918-792c-4abe-b52c-03218b0987bc", - "Alias": "reciprocal", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker", - "RelatedPropertyName": null, - "IsEnabled": false, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": null, - "DataCollectionType": null - } - } - ] - }, - "Type": "RapidCMS.ModelMaker.OnetoOneOneA", - "IsRelationToOne": true, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.EntityPicker" - } - ] - } -} \ No newline at end of file diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.one-to-one-one-bs-implicit.json b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.one-to-one-one-bs-implicit.json deleted file mode 100644 index 73cec48c..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests/modelmaker.one-to-one-one-bs-implicit.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "$type": "RapidCMS.ModelMaker.Models.Entities.ModelEntity, RapidCMS.ModelMaker", - "Id": "one-to-one-one-bs", - "ParentId": null, - "Name": "One to One - One B", - "PluralName": "One to One - One Bs", - "IconColor": "Orange10", - "Icon": "Database", - "Alias": "one-to-one-one-bs", - "Output": "Entity, Collection, Repository, Context", - "Properties": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "08824942-4c3a-404e-b0cd-7c0adce66a2c", - "Name": "Name", - "IsTitle": true, - "IncludeInListView": false, - "IsRequired": false, - "PropertyAlias": "shortstring", - "EditorAlias": "textbox", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [] - }, - "Type": "System.String", - "IsRelationToOne": false, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.TextBoxEditor" - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyModel, RapidCMS.ModelMaker", - "Id": "525f29ce-6a74-4c08-b471-3ece78d90fb1", - "Name": "A", - "IsTitle": false, - "IncludeInListView": false, - "IsRequired": false, - "PropertyAlias": "linkedentity", - "EditorAlias": "entitypicker", - "Details": { - "$type": "System.Collections.Generic.List`1[[RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel, RapidCMS.ModelMaker]], System.Private.CoreLib", - "$values": [ - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.LinkedEntityDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "72a6fc06-d85f-4324-bbf8-e51544ff3ea7", - "Alias": "linkedEntity", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.LinkedEntityDetailConfig, RapidCMS.ModelMaker", - "LinkedEntityCollectionAlias": "one-to-one-one-as", - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": "one-to-one-one-as", - "ValidationMethodName": null, - "DataCollectionType": null - } - }, - { - "$type": "RapidCMS.ModelMaker.Models.Entities.PropertyDetailModel`1[[RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker]], RapidCMS.ModelMaker", - "Id": "cc85f918-792c-4abe-b52c-03218b0987bc", - "Alias": "reciprocal", - "Config": { - "$type": "RapidCMS.ModelMaker.Validation.Config.CorrespondingPropertyDetailConfig, RapidCMS.ModelMaker", - "RelatedPropertyName": "B", - "IsEnabled": true, - "AlwaysIncluded": false, - "RelatedCollectionAlias": null, - "ValidationMethodName": null, - "DataCollectionType": null - } - } - ] - }, - "Type": "RapidCMS.ModelMaker.OnetoOneOneA", - "IsRelationToOne": true, - "IsRelationToMany": false, - "EditorType": "RapidCMS.UI.Components.Editors.EntityPicker" - } - ] - } -} \ No newline at end of file diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Abstractions/IInformation.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Abstractions/IInformation.cs deleted file mode 100644 index 86f16c66..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Abstractions/IInformation.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Collections.Generic; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Enums; - -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Abstractions -{ - internal interface IInformation - { - bool IsValid(); - - IEnumerable NamespacesUsed(Use use); - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Builders/BuilderBase.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Builders/BuilderBase.cs deleted file mode 100644 index a4ce5f81..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Builders/BuilderBase.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System.CodeDom.Compiler; -using System.Collections.Generic; -using System.Linq; -using System.Text.RegularExpressions; - -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Builders -{ - internal abstract class BuilderBase - { - public void WriteUsingNamespaces(IndentedTextWriter indentWriter, IEnumerable usings) - { - var validUsings = usings - .Distinct() - .OrderBy(x => x.StartsWith("System") ? 1 : 2) - .ThenBy(x => x.Replace(".", "").Replace(";", "")) - .ToList(); - foreach (var usingStatement in validUsings) - { - indentWriter.WriteLine($"using {usingStatement};"); - } - - if (validUsings.Count > 0) - { - indentWriter.WriteLine(); - } - } - - protected void WriteOpenNamespace(IndentedTextWriter indentWriter, string nameSpace) - { - indentWriter.WriteLine("#nullable enable"); - indentWriter.WriteLine(); - indentWriter.WriteLine($"namespace {nameSpace}"); - indentWriter.WriteLine("{"); - indentWriter.Indent++; - } - - protected void WriteOpeningBracket(IndentedTextWriter indentWriter) - { - indentWriter.WriteLine("{"); - indentWriter.Indent++; - } - - protected void WriteClosingBracket(IndentedTextWriter indentWriter) - { - indentWriter.Indent--; - indentWriter.WriteLine("}"); - } - - protected void WriteClosingLambda(IndentedTextWriter indentWriter) - { - indentWriter.Indent--; - indentWriter.WriteLine("});"); - } - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Builders/CollectionBuilder.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Builders/CollectionBuilder.cs deleted file mode 100644 index 4f882e46..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Builders/CollectionBuilder.cs +++ /dev/null @@ -1,143 +0,0 @@ -using System.CodeDom.Compiler; -using System.IO; -using System.Linq; -using System.Text; -using Microsoft.CodeAnalysis.Text; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Contexts; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Enums; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Information; - -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Builders -{ - internal sealed class CollectionBuilder : BuilderBase - { - private readonly FieldBuilder _fieldBuilder; - - public CollectionBuilder(FieldBuilder fieldBuilder) - { - _fieldBuilder = fieldBuilder; - } - - public SourceText? BuildCollection(EntityInformation info, ModelMakerContext context) - { - if (!info.OutputItems.Contains(Constants.OutputCollection)) - { - return default; - } - - using var writer = new StringWriter(); - using var indentWriter = new IndentedTextWriter(writer, " "); - - var namespaces = info.NamespacesUsed(Use.Collection); - WriteUsingNamespaces(indentWriter, namespaces); - WriteOpenNamespace(indentWriter, context.Namespace); - - WriteOpenStaticClass(indentWriter, info); - - WriteTreeConfig(indentWriter, info); - WriteElementConfig(indentWriter, info); - WriteEntityValidator(indentWriter, info); - - WriteListView(indentWriter, info); - WriteNodeEditor(indentWriter, info); - - WriteClosingLambda(indentWriter); - indentWriter.Indent--; - - WriteClosingBracket(indentWriter); - WriteClosingBracket(indentWriter); - WriteClosingBracket(indentWriter); - - return SourceText.From(writer.ToString(), Encoding.UTF8); - } - - public void WriteOpenStaticClass(IndentedTextWriter indentWriter, EntityInformation info) - { - indentWriter.WriteLine($"public static class {info.PascalCaseName}Collection"); - indentWriter.WriteLine("{"); - indentWriter.Indent++; - - indentWriter.WriteLine($"public static void Add{info.PascalCaseName}Collection(this ICmsConfig config)"); - indentWriter.WriteLine("{"); - indentWriter.Indent++; - - indentWriter.WriteLine($"config.AddCollection<{info.PascalCaseName}, BaseRepository<{info.PascalCaseName}>>("); - indentWriter.Indent++; - - indentWriter.WriteLine($"\"{info.Alias}\","); - indentWriter.WriteLine($"\"{info.Icon ?? "Database"}\","); - indentWriter.WriteLine($"\"{info.IconColor ?? "Gray40"}\","); - indentWriter.WriteLine($"\"{info.PluralName}\","); - indentWriter.WriteLine("collection =>"); - indentWriter.WriteLine("{"); - indentWriter.Indent++; - } - - public void WriteTreeConfig(IndentedTextWriter indentWriter, EntityInformation info) - { - var titleProperty = info.Properties.Single(x => x.IsTitleOfEntity); - - indentWriter.WriteLine($"collection.SetTreeView(x => x.{titleProperty.PascalCaseName});"); - } - - public void WriteElementConfig(IndentedTextWriter indentWriter, EntityInformation info) - { - var titleProperty = info.Properties.Single(x => x.IsTitleOfEntity); - - indentWriter.WriteLine($"collection.SetElementConfiguration(x => x.Id, x => x.{titleProperty.PascalCaseName});"); - } - - public void WriteEntityValidator(IndentedTextWriter indentWriter, EntityInformation info) - { - indentWriter.WriteLine($"collection.AddEntityValidator<{info.PascalCaseName}Validator>();"); - } - - public void WriteListView(IndentedTextWriter indentWriter, EntityInformation info) - { - var titleProperty = info.Properties.Single(x => x.IsTitleOfEntity); - - indentWriter.WriteLine("collection.SetListView(view =>"); - indentWriter.WriteLine("{"); - indentWriter.Indent++; - - indentWriter.WriteLine("view.AddDefaultButton(DefaultButtonType.New);"); - indentWriter.WriteLine("view.AddRow(row =>"); - indentWriter.WriteLine("{"); - indentWriter.Indent++; - - indentWriter.WriteLine("row.AddField(x => x.Id.ToString()).SetName(\"Id\");"); - indentWriter.WriteLine($"row.AddField(x => x.{titleProperty.PascalCaseName}).SetName(\"{titleProperty.Name}\");"); - foreach (var listViewProperty in info.Properties.Where(x => x.IncludeInListView)) - { - indentWriter.WriteLine($"row.AddField(x => x.{listViewProperty.PascalCaseName} == null ? \"\" : x.{listViewProperty.PascalCaseName}.ToString().Truncate(25)).SetName(\"{listViewProperty.Name}\");"); - } - indentWriter.WriteLine("row.AddDefaultButton(DefaultButtonType.Edit);"); - indentWriter.WriteLine("row.AddDefaultButton(DefaultButtonType.Delete);"); - - WriteClosingLambda(indentWriter); - WriteClosingLambda(indentWriter); - } - - public void WriteNodeEditor(IndentedTextWriter indentWriter, EntityInformation info) - { - indentWriter.WriteLine("collection.SetNodeEditor(editor =>"); - indentWriter.WriteLine("{"); - indentWriter.Indent++; - - indentWriter.WriteLine("editor.AddDefaultButton(DefaultButtonType.Up);"); - indentWriter.WriteLine("editor.AddDefaultButton(DefaultButtonType.SaveExisting);"); - indentWriter.WriteLine("editor.AddDefaultButton(DefaultButtonType.SaveNew);"); - indentWriter.WriteLine("editor.AddSection(section =>"); - indentWriter.WriteLine("{"); - indentWriter.Indent++; - - foreach (var property in info.Properties.Where(x => x.Uses.HasFlag(Use.Collection))) - { - _fieldBuilder.WriteField(indentWriter, property); - } - - WriteClosingLambda(indentWriter); - WriteClosingLambda(indentWriter); - } - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Builders/ConfigObjectBuilder.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Builders/ConfigObjectBuilder.cs deleted file mode 100644 index 2864cda2..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Builders/ConfigObjectBuilder.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using System.CodeDom.Compiler; -using System.Linq; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Information; - -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Builders -{ - internal sealed class ConfigObjectBuilder : BuilderBase - { - public void WriteConfigObject(IndentedTextWriter indentWriter, PropertyDetailInformation detail) - { - if (detail.ConfigList != null || detail.ConfigProperties != null) - { - indentWriter.Write($"new {detail.ConfigType} {{ "); - - if (detail.ConfigList is not null) - { - indentWriter.Write($"{detail.PropertyName} = new List {{ "); - indentWriter.Write(string.Join(", ", detail.ConfigList.Select(x => $"\"{x}\""))); - indentWriter.Write(" }"); - } - else if (detail.ConfigProperties is not null) - { - indentWriter.Write($"{detail.PropertyName} = new {detail.ConfigSubType} {{ "); - indentWriter.Write(string.Join(", ", detail.ConfigProperties.Select(x => $"{x.Key} = {GeneratePrimitive(x.Value)}"))); - indentWriter.Write(" }"); - } - - indentWriter.Write(" }"); - } - else - { - indentWriter.Write(GeneratePrimitive(detail.Value)); - } - } - - private static string GeneratePrimitive(object? value) - => value switch - { - string stringValue => $"\"{stringValue}\"", - DateTime dateTimeValue => $"new System.DateTime({dateTimeValue.Ticks})", - object @object => @object.ToString(), - _ => "" - }; - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Builders/ContextBuilder.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Builders/ContextBuilder.cs deleted file mode 100644 index d61b8a1f..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Builders/ContextBuilder.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System.CodeDom.Compiler; -using System.IO; -using System.Linq; -using System.Text; -using Microsoft.CodeAnalysis.Text; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Contexts; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Enums; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Information; - -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Builders -{ - internal sealed class ContextBuilder : BuilderBase - { - public SourceText? BuildContext(ModelMakerContext context) - { - if (context.Entities.All(x => !x.OutputItems.Contains(Constants.OutputContext))) - { - return default; - } - - using var writer = new StringWriter(); - using var indentWriter = new IndentedTextWriter(writer, " "); - - var namespaces = context.Entities.SelectMany(x => x.NamespacesUsed(Use.Context)); - WriteUsingNamespaces(indentWriter, namespaces); - WriteOpenNamespace(indentWriter, context.Namespace); - - WriteDbContext(indentWriter); - WriteOnModelCreating(indentWriter, context); - - foreach (var entity in context.Entities.Where(x => x.OutputItems.Contains(Constants.OutputContext))) - { - WriteDbSet(indentWriter, entity); - } - - WriteClosingBracket(indentWriter); - - WriteClosingBracket(indentWriter); - - return SourceText.From(writer.ToString(), Encoding.UTF8); - } - - public void WriteDbContext(IndentedTextWriter indentWriter) - { - indentWriter.WriteLine($"public partial class ModelMakerDbContext : DbContext"); - WriteOpeningBracket(indentWriter); - - indentWriter.WriteLine($"public ModelMakerDbContext(DbContextOptions options) : base(options)"); - WriteOpeningBracket(indentWriter); - WriteClosingBracket(indentWriter); - } - - public void WriteOnModelCreating(IndentedTextWriter indentWriter, ModelMakerContext context) - { - indentWriter.WriteLine(); - indentWriter.WriteLine("protected override void OnModelCreating(ModelBuilder modelBuilder)"); - WriteOpeningBracket(indentWriter); - - indentWriter.WriteLine("base.OnModelCreating(modelBuilder);"); - indentWriter.WriteLine(); - - foreach (var entity in context.Entities.Where(x => x.OutputItems.Contains(Constants.OutputContext))) - { - indentWriter.WriteLine($"modelBuilder.ApplyConfiguration(new {entity.PascalCaseName}Configuration());"); - } - - WriteClosingBracket(indentWriter); - } - - public void WriteDbSet(IndentedTextWriter indentWriter, EntityInformation info) - { - indentWriter.WriteLine(); - indentWriter.WriteLine($"public DbSet<{info.PascalCaseName}> {info.PascalCasePluralName} {{ get; set; }} = default!;"); - } - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Builders/EntityBuilder.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Builders/EntityBuilder.cs deleted file mode 100644 index e7aa6631..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Builders/EntityBuilder.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System.CodeDom.Compiler; -using System.IO; -using System.Linq; -using System.Text; -using Microsoft.CodeAnalysis.Text; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Contexts; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Enums; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Information; - -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Builders -{ - internal sealed class EntityBuilder : BuilderBase - { - private readonly PropertyBuilder _propertyBuilder; - - public EntityBuilder(PropertyBuilder propertyBuilder) - { - _propertyBuilder = propertyBuilder; - } - - public SourceText? BuildEntity(EntityInformation info, ModelMakerContext context) - { - if (!info.OutputItems.Contains(Constants.OutputEntity)) - { - return default; - } - - using var writer = new StringWriter(); - using var indentWriter = new IndentedTextWriter(writer, " "); - - WriteUsingNamespaces(indentWriter, info.NamespacesUsed(Use.Entity)); - WriteOpenNamespace(indentWriter, context.Namespace); - - WriteOpenEntity(indentWriter, info); - - WriteIdProperties(indentWriter); - - foreach (var property in info.Properties.Where(x => x.Uses.HasFlag(Use.Entity))) - { - _propertyBuilder.WriteProperty(indentWriter, property); - } - - WriteClosingBracket(indentWriter); - WriteClosingBracket(indentWriter); - - return SourceText.From(writer.ToString(), Encoding.UTF8); - } - - private void WriteOpenEntity(IndentedTextWriter indentWriter, EntityInformation info) - { - indentWriter.WriteLine($"public partial class {info.PascalCaseName} : IEntity"); - indentWriter.WriteLine("{"); - indentWriter.Indent++; - } - - private void WriteIdProperties(IndentedTextWriter indentWriter) - { - indentWriter.WriteLine("public int Id { get; set; }"); - indentWriter.WriteLine("string? IEntity.Id { get => Id.ToString(); set => Id = int.Parse(value ?? \"0\"); }"); - } - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Builders/EntityTypeConfigurationBuilder.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Builders/EntityTypeConfigurationBuilder.cs deleted file mode 100644 index 9fb2e8b8..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Builders/EntityTypeConfigurationBuilder.cs +++ /dev/null @@ -1,92 +0,0 @@ -using System.CodeDom.Compiler; -using System.IO; -using System.Linq; -using System.Text; -using Microsoft.CodeAnalysis.Text; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Contexts; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Enums; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Information; - -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Builders -{ - internal sealed class EntityTypeConfigurationBuilder : BuilderBase - { - public SourceText? BuildEntityTypeConfiguration(EntityInformation info, ModelMakerContext context) - { - if (!info.OutputItems.Contains(Constants.OutputContext)) - { - return default; - } - - using var writer = new StringWriter(); - using var indentWriter = new IndentedTextWriter(writer, " "); - - var namespaces = context.Entities.SelectMany(x => x.NamespacesUsed(Use.Context)); - WriteUsingNamespaces(indentWriter, namespaces); - WriteOpenNamespace(indentWriter, context.Namespace); - - WriteEntityTypeConfiguration(indentWriter, info); - - WriteClosingBracket(indentWriter); - - return SourceText.From(writer.ToString(), Encoding.UTF8); - } - - public void WriteEntityTypeConfiguration(IndentedTextWriter indentWriter, EntityInformation info) - { - indentWriter.WriteLine($"public class {info.PascalCaseName}Configuration : IEntityTypeConfiguration<{info.PascalCaseName}>"); - WriteOpeningBracket(indentWriter); - - indentWriter.WriteLine($"public void Configure(EntityTypeBuilder<{info.PascalCaseName}> builder)"); - WriteOpeningBracket(indentWriter); - - foreach (var property in info.Properties.Where(x => !x.Hidden && x.Relation != Relation.None)) - { - WriteRelationConfig(indentWriter, info, property); - } - - WriteClosingBracket(indentWriter); - WriteClosingBracket(indentWriter); - } - - public void WriteRelationConfig(IndentedTextWriter indentWriter, EntityInformation entity, PropertyInformation property) - { - if (property.Relation.HasFlag(Relation.One | Relation.ToOne | Relation.DependentSide)) - { - return; - } - - indentWriter.Write("builder"); - - if (property.Relation.HasFlag(Relation.ToOne)) - { - indentWriter.Write($".HasOne(x => x.{property.PascalCaseName})"); - } - else - { - indentWriter.Write($".HasMany(x => x.{property.PascalCaseName})"); - } - - if (property.Relation.HasFlag(Relation.One)) - { - indentWriter.Write($".WithOne(x => x.{property.RelatedPropertyName})"); - } - else - { - indentWriter.Write($".WithMany(x => x.{property.RelatedPropertyName})"); - } - - if (property.Relation.HasFlag(Relation.One | Relation.ToOne)) - { - indentWriter.Write($".HasForeignKey<{property.Type}>(x => x.{property.RelatedPropertyName}Id)"); - } - - if (!property.Relation.HasFlag(Relation.Many | Relation.ToMany)) - { - indentWriter.Write(".OnDelete(DeleteBehavior.NoAction)"); - } - - indentWriter.WriteLine(";"); - } - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Builders/EntityValidationBuilder.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Builders/EntityValidationBuilder.cs deleted file mode 100644 index 1203e5d3..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Builders/EntityValidationBuilder.cs +++ /dev/null @@ -1,79 +0,0 @@ -using System; -using System.CodeDom.Compiler; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using Microsoft.CodeAnalysis.Text; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Contexts; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Enums; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Information; - -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Builders -{ - - internal sealed class EntityValidationBuilder : BuilderBase - { - private readonly ConfigObjectBuilder _configObjectBuilder; - - public EntityValidationBuilder(ConfigObjectBuilder configObjectBuilder) - { - _configObjectBuilder = configObjectBuilder; - } - - public SourceText? BuildValidation(EntityInformation info, ModelMakerContext context) - { - if (!info.OutputItems.Contains(Constants.OutputValidation)) - { - return default; - } - - using var writer = new StringWriter(); - using var indentWriter = new IndentedTextWriter(writer, " "); - - WriteUsingNamespaces(indentWriter, info.NamespacesUsed(Use.Validation)); - WriteOpenNamespace(indentWriter, context.Namespace); - - indentWriter.WriteLine($"public class {info.PascalCaseName}Validator : AbstractValidatorAdapter<{info.PascalCaseName}>"); - WriteOpeningBracket(indentWriter); - - indentWriter.WriteLine($"public {info.PascalCaseName}Validator()"); - WriteOpeningBracket(indentWriter); - - foreach (var property in info.Properties.Where(x => x.Details.Any(x => !string.IsNullOrWhiteSpace(x.ValidationMethodName)))) - { - WriteProperty(indentWriter, property, info, context); - } - - WriteClosingBracket(indentWriter); - WriteClosingBracket(indentWriter); - WriteClosingBracket(indentWriter); - - return SourceText.From(writer.ToString(), Encoding.UTF8); - } - - private void WriteProperty(IndentedTextWriter indentWriter, PropertyInformation property, EntityInformation entity, ModelMakerContext context) - { - indentWriter.Write($"RuleFor(x => x.{property.PascalCaseName}{(property.Relation.HasFlag(Relation.Many | Relation.ToOne) ? "Id" : "")})"); - indentWriter.Indent++; - - foreach (var detail in property.Details.Where(x => !string.IsNullOrWhiteSpace(x.ValidationMethodName))) - { - WriteValidation(indentWriter, detail, property, entity, context); - } - - indentWriter.WriteLine(";"); - indentWriter.Indent--; - } - - private void WriteValidation(IndentedTextWriter indentWriter, PropertyDetailInformation detail, PropertyInformation property, EntityInformation entity, ModelMakerContext context) - { - indentWriter.WriteLine(); - indentWriter.Write($".{detail.ValidationMethodName}("); - - _configObjectBuilder.WriteConfigObject(indentWriter, detail); - - indentWriter.Write(")"); - } - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Builders/FieldBuilder.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Builders/FieldBuilder.cs deleted file mode 100644 index 7b04fde1..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Builders/FieldBuilder.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System.CodeDom.Compiler; -using System.Linq; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Enums; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Information; - -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Builders -{ - internal sealed class FieldBuilder : BuilderBase - { - private readonly ConfigObjectBuilder _configObjectBuilder; - - public FieldBuilder(ConfigObjectBuilder configObjectBuilder) - { - _configObjectBuilder = configObjectBuilder; - } - - public void WriteField(IndentedTextWriter indentWriter, PropertyInformation info) - { - if (info.Relation.HasFlag(Relation.One | Relation.ToOne) && !info.Relation.HasFlag(Relation.DependentSide)) - { - indentWriter.Write($"section.AddField(x => x.{info.PascalCaseName} == null ? 0 : x.{info.PascalCaseName}.Id)"); - indentWriter.Write(".DisableWhen((e, s) => true)"); - } - else if (info.Relation.HasFlag(Relation.ToOne)) - { - indentWriter.Write($"section.AddField(x => x.{info.PascalCaseName}Id)"); - } - else - { - indentWriter.Write($"section.AddField(x => x.{info.PascalCaseName})"); - } - - indentWriter.Write($".SetType(typeof({info.EditorType}))"); - - if (info.Details.FirstOrDefault(x => !string.IsNullOrWhiteSpace(x.DataCollectionType)) is PropertyDetailInformation details) - { - indentWriter.Write($".SetDataCollection<{details.DataCollectionType}"); - - if (details.ConfigList != null || details.ConfigProperties != null) - { - - indentWriter.Write($", {details.ConfigType}>("); - - _configObjectBuilder.WriteConfigObject(indentWriter, details); - } - else - { - indentWriter.Write(">("); - } - - indentWriter.Write(")"); - } - else if (info.Relation.HasFlag(Relation.ToOne) && !string.IsNullOrEmpty(info.RelatedCollectionAlias)) - { - indentWriter.Write($".SetCollectionRelation(\"{info.RelatedCollectionAlias}\")"); - } - else if (info.Relation.HasFlag(Relation.ToMany) && !string.IsNullOrEmpty(info.RelatedCollectionAlias)) - { - indentWriter.Write($".SetCollectionRelation(\"{info.RelatedCollectionAlias}\")"); - } - - indentWriter.Write($".SetName(\"{info.Name}\")"); - - indentWriter.WriteLine(";"); - } - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Builders/PropertyBuilder.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Builders/PropertyBuilder.cs deleted file mode 100644 index b5fdf84e..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Builders/PropertyBuilder.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.CodeDom.Compiler; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Enums; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Information; - -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Builders -{ - internal sealed class PropertyBuilder : BuilderBase - { - public void WriteProperty(IndentedTextWriter indentWriter, PropertyInformation info) - { - indentWriter.WriteLine(); - - if (info.Relation.HasFlag(Relation.One | Relation.ToOne) && !info.Relation.HasFlag(Relation.DependentSide)) - { - indentWriter.WriteLine($"public {info.Type}? {info.PascalCaseName} {{ get; set; }}"); - } - else if (info.Relation.HasFlag(Relation.ToOne)) - { - indentWriter.WriteLine($"public int? {info.PascalCaseName}Id {{ get; set; }}"); // TODO: how to detect type of ForeignKey type? - indentWriter.WriteLine($"public {info.Type}? {info.PascalCaseName} {{ get; set; }}"); - } - else if (info.Relation.HasFlag(Relation.ToMany)) - { - indentWriter.WriteLine($"public ICollection<{info.Type}> {info.PascalCaseName} {{ get; set; }} = new List<{info.Type}>();"); - } - else - { - indentWriter.WriteLine($"public {info.Type} {info.PascalCaseName} {{ get; set; }}"); - } - } - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Builders/RepositoryBuilder.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Builders/RepositoryBuilder.cs deleted file mode 100644 index be52e799..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Builders/RepositoryBuilder.cs +++ /dev/null @@ -1,236 +0,0 @@ -using System.CodeDom.Compiler; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using Microsoft.CodeAnalysis.Text; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Contexts; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Enums; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Information; - -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Builders -{ - internal sealed class RepositoryBuilder : BuilderBase - { - public SourceText? BuildRepository(EntityInformation info, ModelMakerContext context) - { - if (!info.OutputItems.Contains(Constants.OutputRepository)) - { - return default; - } - - using var writer = new StringWriter(); - using var indentWriter = new IndentedTextWriter(writer, " "); - - var namespaces = context.Entities.SelectMany(x => x.NamespacesUsed(Use.Repository)); - WriteUsingNamespaces(indentWriter, namespaces); - WriteOpenNamespace(indentWriter, context.Namespace); - - WriteRepository(indentWriter, info); - - WriteDeleteAsync(indentWriter, info); - WriteGetAllAsync(indentWriter, info); - GetByIdAsync(indentWriter, info); - WriteInsertAsync(indentWriter, info); - WriteNewAsync(indentWriter, info); - WriteUpdateAsync(indentWriter, info); - - foreach (var relatedProperty in info.Properties.Where(x => x.Relation.HasFlag(Relation.ToMany) && !x.Hidden)) - { - WriteHandleRelationMethod(indentWriter, context, info, relatedProperty); - } - - WriteClosingBracket(indentWriter); - - WriteClosingBracket(indentWriter); - - return SourceText.From(writer.ToString(), Encoding.UTF8); - } - - public void WriteRepository(IndentedTextWriter indentWriter, EntityInformation info) - { - indentWriter.WriteLine($"public class {info.PascalCaseName}Repository : BaseRepository<{info.PascalCaseName}>"); - WriteOpeningBracket(indentWriter); - - indentWriter.WriteLine("private readonly ModelMakerDbContext _dbContext;"); - indentWriter.WriteLine(); - - indentWriter.WriteLine($"public {info.PascalCaseName}Repository(ModelMakerDbContext dbContext)"); - WriteOpeningBracket(indentWriter); - indentWriter.WriteLine("_dbContext = dbContext;"); - WriteClosingBracket(indentWriter); - } - - public void WriteDeleteAsync(IndentedTextWriter indentWriter, EntityInformation info) - { - indentWriter.WriteLine(); - indentWriter.WriteLine("public override async Task DeleteAsync(string id, IParent? parent)"); - WriteOpeningBracket(indentWriter); - indentWriter.WriteLine("if (int.TryParse(id, out var intId))"); - WriteOpeningBracket(indentWriter); - indentWriter.WriteLine($"var entity = await _dbContext.{info.PascalCasePluralName}{GetIncludes(info)}.FirstOrDefaultAsync(x => x.Id == intId);"); - indentWriter.WriteLine("if (entity != null)"); - WriteOpeningBracket(indentWriter); - indentWriter.WriteLine($"_dbContext.{info.PascalCasePluralName}.Remove(entity);"); - indentWriter.WriteLine("await _dbContext.SaveChangesAsync();"); - WriteClosingBracket(indentWriter); - WriteClosingBracket(indentWriter); - WriteClosingBracket(indentWriter); - } - - public void WriteGetAllAsync(IndentedTextWriter indentWriter, EntityInformation info) - { - indentWriter.WriteLine(); - indentWriter.WriteLine($"public override async Task> GetAllAsync(IParent? parent, IView<{info.PascalCaseName}> view)"); - WriteOpeningBracket(indentWriter); - indentWriter.Write($"return await view.ApplyOrder(view.ApplyDataView(_dbContext.{info.PascalCasePluralName}))"); - indentWriter.Write(".Skip(view.Skip)"); - indentWriter.Write(".Take(view.Take)"); - indentWriter.Write(".AsNoTracking()"); - indentWriter.WriteLine(".ToListAsync();"); - WriteClosingBracket(indentWriter); - } - - public void GetByIdAsync(IndentedTextWriter indentWriter, EntityInformation info) - { - indentWriter.WriteLine(); - indentWriter.WriteLine($"public override async Task<{info.PascalCaseName}?> GetByIdAsync(string id, IParent? parent)"); - WriteOpeningBracket(indentWriter); - indentWriter.WriteLine("if (int.TryParse(id, out var intId))"); - WriteOpeningBracket(indentWriter); - indentWriter.WriteLine($"return await _dbContext.{info.PascalCasePluralName}{GetIncludesAndAsNoTracking(info)}.FirstOrDefaultAsync(x => x.Id == intId);"); - WriteClosingBracket(indentWriter); - indentWriter.WriteLine("return default;"); - WriteClosingBracket(indentWriter); - } - - public void WriteInsertAsync(IndentedTextWriter indentWriter, EntityInformation info) - { - indentWriter.WriteLine(); - indentWriter.WriteLine($"public override async Task<{info.PascalCaseName}?> InsertAsync(IEditContext<{info.PascalCaseName}> editContext)"); - WriteOpeningBracket(indentWriter); - indentWriter.WriteLine("var entity = editContext.Entity;"); - WriteHandleRelations(indentWriter, info); - indentWriter.WriteLine(); - indentWriter.WriteLine($"var entry = _dbContext.{info.PascalCasePluralName}.Add(entity);"); - indentWriter.WriteLine("await _dbContext.SaveChangesAsync();"); - indentWriter.WriteLine("return entry.Entity;"); - WriteClosingBracket(indentWriter); - } - - public void WriteNewAsync(IndentedTextWriter indentWriter, EntityInformation info) - { - indentWriter.WriteLine(); - indentWriter.WriteLine($"public override Task<{info.PascalCaseName}> NewAsync(IParent? parent, Type? variantType = null)"); - WriteOpeningBracket(indentWriter); - indentWriter.WriteLine($"return Task.FromResult(new {info.PascalCaseName}());"); - WriteClosingBracket(indentWriter); - } - - public void WriteUpdateAsync(IndentedTextWriter indentWriter, EntityInformation info) - { - indentWriter.WriteLine(); - indentWriter.WriteLine($"public override async Task UpdateAsync(IEditContext<{info.PascalCaseName}> editContext)"); - WriteOpeningBracket(indentWriter); - indentWriter.WriteLine($"var entity = await _dbContext.{info.PascalCasePluralName}{GetIncludes(info)}.FirstAsync(x => x.Id == editContext.Entity.Id);"); - WritePropertyMap(indentWriter, info); - WriteHandleRelations(indentWriter, info); - indentWriter.WriteLine(); - indentWriter.WriteLine("await _dbContext.SaveChangesAsync();"); - WriteClosingBracket(indentWriter); - } - - private void WritePropertyMap(IndentedTextWriter indentWriter, EntityInformation info) - { - indentWriter.WriteLine(); - foreach (var property in info.Properties.Where(x => !x.Relation.HasFlag(Relation.ToMany) && !x.Hidden).OrderBy(x => x.Name)) - { - if (property.Relation.HasFlag(Relation.One | Relation.ToOne) && !property.Relation.HasFlag(Relation.DependentSide)) - { - // disabled editor - } - else if (property.Relation.HasFlag(Relation.ToOne)) - { - indentWriter.WriteLine($"entity.{property.PascalCaseName}Id = editContext.Entity.{property.PascalCaseName}Id;"); - } - else - { - indentWriter.WriteLine($"entity.{property.PascalCaseName} = editContext.Entity.{property.PascalCaseName};"); - } - } - } - - private void WriteHandleRelations(IndentedTextWriter indentWriter, EntityInformation info) - { - var relatedProperties = info.Properties.Where(x => x.Relation.HasFlag(Relation.ToMany) && !x.Hidden); - - if (!relatedProperties.Any()) - { - return; - } - - indentWriter.WriteLine(); - indentWriter.WriteLine("var relations = editContext.GetRelationContainer();"); - foreach (var relatedProperty in relatedProperties) - { - indentWriter.WriteLine($"await Handle{relatedProperty.PascalCaseName}Async(entity, relations);"); - } - } - - private void WriteHandleRelationMethod(IndentedTextWriter indentWriter, ModelMakerContext context, EntityInformation entity, PropertyInformation property) - { - var relatedDbContextName = context.Entities.FirstOrDefault(x => x.Alias == property.RelatedCollectionAlias)?.PascalCasePluralName; - - if (string.IsNullOrEmpty(relatedDbContextName)) - { - indentWriter.WriteLine(); - indentWriter.WriteLine($"protected virtual Task Handle{property.PascalCaseName}Async({entity.PascalCaseName} dbEntity, IRelationContainer relations)"); - WriteOpeningBracket(indentWriter); - indentWriter.WriteLine("return Task.CompletedTask;"); - WriteClosingBracket(indentWriter); - } - else - { - indentWriter.WriteLine(); - indentWriter.WriteLine($"private async Task Handle{property.PascalCaseName}Async({entity.PascalCaseName} dbEntity, IRelationContainer relations)"); - WriteOpeningBracket(indentWriter); - indentWriter.WriteLine($"var selectedIds = relations.GetRelatedElementIdsFor<{entity.PascalCaseName}, ICollection<{property.Type}>, int>(x => x.{property.PascalCaseName}) ?? Enumerable.Empty();"); - indentWriter.WriteLine($"var existingIds = dbEntity.{property.PascalCaseName}.Select(x => x.Id);"); - indentWriter.WriteLine(); - indentWriter.WriteLine($"var itemsToRemove = dbEntity.{property.PascalCaseName}.Where(x => !selectedIds.Contains(x.Id)).ToList();"); - indentWriter.WriteLine("var idsToAdd = selectedIds.Except(existingIds).ToList();"); - indentWriter.WriteLine(); - indentWriter.WriteLine($"var itemsToAdd = await _dbContext.{relatedDbContextName}.Where(x => idsToAdd.Contains(x.Id)).ToListAsync();"); - indentWriter.WriteLine(); - indentWriter.WriteLine($"foreach (var itemToRemove in itemsToRemove)"); - WriteOpeningBracket(indentWriter); - indentWriter.WriteLine($"dbEntity.{property.PascalCaseName}.Remove(itemToRemove);"); - WriteClosingBracket(indentWriter); - indentWriter.WriteLine($"foreach (var itemToAdd in itemsToAdd)"); - WriteOpeningBracket(indentWriter); - indentWriter.WriteLine($"dbEntity.{property.PascalCaseName}.Add(itemToAdd);"); - WriteClosingBracket(indentWriter); - WriteClosingBracket(indentWriter); - } - } - - private string GetIncludesAndAsNoTracking(EntityInformation info) - => $"{string.Join("", GetAllIncludes(info))}.AsNoTracking()"; - private string GetIncludes(EntityInformation info) - => $"{string.Join("", GetAllIncludes(info))}"; - - private IEnumerable GetAllIncludes(EntityInformation info) - { - foreach (var property in info.Properties.Where(RelatedEntities)) - { - yield return $".Include(x => x.{property.PascalCaseName})"; - } - } - - private static bool RelatedEntities(PropertyInformation x) - { - return (x.Relation.HasFlag(Relation.ToMany) && !x.Hidden) || - (x.Relation.HasFlag(Relation.One | Relation.ToOne) && !x.Relation.HasFlag(Relation.DependentSide)); - } - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Constants.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Constants.cs deleted file mode 100644 index ab11a6f9..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Constants.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests")] -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore -{ - internal static class Constants - { - public const string OutputCollection = "Collection"; - public const string OutputEntity = "Entity"; - public const string OutputContext = "Context"; - public const string OutputRepository = "Repository"; - public const string OutputValidation = "Validation"; - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Contexts/ModelMakerContext.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Contexts/ModelMakerContext.cs deleted file mode 100644 index 52057635..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Contexts/ModelMakerContext.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Information; - -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Contexts -{ - internal class ModelMakerContext - { - private readonly IReadOnlyList _entities; - - public ModelMakerContext(string @namespace, IReadOnlyList entities) - { - Namespace = @namespace; - _entities = entities ?? throw new ArgumentNullException(nameof(entities)); - } - - public IEnumerable Entities => _entities; - - public string Namespace { get; } - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Enums/Relation.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Enums/Relation.cs deleted file mode 100644 index 19347f86..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Enums/Relation.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; - -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Enums -{ - [Flags] - internal enum Relation - { - None = 0, - - One = 1, - Many = 2, - ToOne = 4, - ToMany = 8, - - DependentSide = 1024 - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Enums/Use.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Enums/Use.cs deleted file mode 100644 index f776c2aa..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Enums/Use.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; - -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Enums -{ - [Flags] - internal enum Use - { - Entity = 1, - Collection = 2, - Context = 4, - Repository = 8, - Validation = 16 - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Information/EntityInformation.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Information/EntityInformation.cs deleted file mode 100644 index 6b3abcab..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Information/EntityInformation.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Abstractions; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Enums; - -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Information -{ - internal sealed class EntityInformation : InformationBase, IInformation - { - private readonly List _properties = new(); - - public EntityInformation() - { - _namespaces.Add((Use.Entity | Use.Repository, "RapidCMS.Core.Abstractions.Data")); - _namespaces.Add((Use.Collection, "RapidCMS.Core.Abstractions.Config")); - _namespaces.Add((Use.Collection, "RapidCMS.Core.Extensions")); - _namespaces.Add((Use.Collection, "RapidCMS.Core.Enums")); - _namespaces.Add((Use.Collection, "RapidCMS.Core.Providers")); - _namespaces.Add((Use.Collection | Use.Repository, "RapidCMS.Core.Repositories")); - _namespaces.Add((Use.Context | Use.Repository, "Microsoft.EntityFrameworkCore")); - _namespaces.Add((Use.Context, "Microsoft.EntityFrameworkCore.Metadata.Builders")); - _namespaces.Add((Use.Repository, "System")); - _namespaces.Add((Use.Repository, "System.Collections.Generic")); - _namespaces.Add((Use.Repository, "System.Linq")); - _namespaces.Add((Use.Repository, "System.Threading.Tasks")); - _namespaces.Add((Use.Repository, "RapidCMS.Core.Abstractions.Forms")); - _namespaces.Add((Use.Validation, "FluentValidation")); - _namespaces.Add((Use.Validation, "RapidCMS.ModelMaker.Validation")); - } - - public string? Name { get; private set; } - public string? PascalCaseName => ValidPascalCaseName(Name); - public string? PluralName { get; private set; } - public string? PascalCasePluralName => ValidPascalCaseName(PluralName); - - public EntityInformation HasName(string name, string? pluralName) - { - Name = name; - PluralName = pluralName ?? name; - return this; - } - - public string? Alias { get; private set; } - - public EntityInformation HasAlias(string alias) - { - Alias = alias; - return this; - } - - public string? Icon { get; private set; } - public string? IconColor { get; private set; } - - public EntityInformation HasIcon(string icon, string? iconColor) - { - Icon = icon; - IconColor = iconColor; - - return this; - } - - public IReadOnlyList OutputItems { get; private set; } = new List(); - - public EntityInformation ShouldOutput(IEnumerable items) - { - OutputItems = items.ToList(); - - return this; - } - - public IReadOnlyList Properties => _properties; - - public EntityInformation AddProperty(PropertyInformation property) - { - _properties.Add(property); - return this; - } - - public bool IsValid() - { - return !string.IsNullOrEmpty(Name) && - !string.IsNullOrEmpty(Alias) && - _properties.Count(x => x.IsTitleOfEntity) == 1 && - _properties.All(x => x.IsValid()); - } - - public IEnumerable NamespacesUsed(Use use) - => _namespaces - .Where(x => x.use.HasFlag(use)) - .Select(x => x.@namespace) - .Union(_properties.SelectMany(x => x.NamespacesUsed(use))); - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Information/InformationBase.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Information/InformationBase.cs deleted file mode 100644 index 4f2f8059..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Information/InformationBase.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Collections.Generic; -using System.Text.RegularExpressions; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Enums; - -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Information -{ - internal abstract class InformationBase - { - protected readonly List<(Use use, string @namespace)> _namespaces = new(); - - protected string ValidPascalCaseName(string? name) - { - if (string.IsNullOrWhiteSpace(name)) - { - return ""; - } - else - { - var trimmedName = Regex.Replace(name?.Trim() ?? "", "[^A-Za-z0-9]*", ""); - - if (trimmedName.Length == 0) - { - return ""; - } - - if (trimmedName.Length == 1) - { - return char.ToUpper(trimmedName[0]).ToString(); - } - - return $"{char.ToUpper(trimmedName[0])}{trimmedName.Substring(1)}"; - } - } - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Information/PropertyDetailInformation.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Information/PropertyDetailInformation.cs deleted file mode 100644 index 19cb0a94..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Information/PropertyDetailInformation.cs +++ /dev/null @@ -1,106 +0,0 @@ -using System.Collections.Generic; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Abstractions; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Enums; - -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Information -{ - internal sealed class PropertyDetailInformation : InformationBase, IInformation - { - public PropertyDetailInformation(string validationMethodName) - { - ValidationMethodName = validationMethodName ?? throw new System.ArgumentNullException(nameof(validationMethodName)); - } - - public PropertyDetailInformation(string configType, string @namespace) - { - ConfigType = configType ?? throw new System.ArgumentNullException(nameof(configType)); - Namespace = @namespace ?? throw new System.ArgumentNullException(nameof(@namespace)); - } - - public bool IsValid() - { - return true; - } - - public IEnumerable NamespacesUsed(Use use) - { - if ((use != Use.Validation && use != Use.Collection) || - (use == Use.Validation && string.IsNullOrWhiteSpace(ValidationMethodName)) || - (use == Use.Collection && ConfigList == null && ConfigProperties == null)) - { - yield break; - } - - if (!string.IsNullOrWhiteSpace(Namespace)) - { - yield return Namespace!; - } - if (!string.IsNullOrWhiteSpace(ConfigSubNamespace)) - { - yield return ConfigSubNamespace!; - } - - if (ConfigList != null) - { - yield return "System.Collections.Generic"; - } - } - - public string? ConfigType { get; private set; } - public string? Namespace { get; private set; } - - public string? ValidationMethodName { get; private set; } - - public PropertyDetailInformation HasValidationMethod(string name) - { - ValidationMethodName = name; - - return this; - } - - public string? DataCollectionType { get; set; } - - public PropertyDetailInformation HasDataCollection(string type) - { - DataCollectionType = type; - - return this; - } - - public object? Value { get; set; } - - public PropertyDetailInformation HasConfigValue(object value) - { - Value = value; - - return this; - } - - public string? PropertyName { get; set; } - - public List? ConfigList { get; set; } - - public PropertyDetailInformation HasConfigList(string propertyName, List list) - { - PropertyName = propertyName; - ConfigList = list; - - return this; - } - - public string? ConfigSubType { get; private set; } - public string? ConfigSubNamespace { get; private set; } - - public IReadOnlyDictionary? ConfigProperties { get; private set; } - - public PropertyDetailInformation HasSubClass(string propertyName, string type, string? @namespace, Dictionary properties) - { - PropertyName = propertyName; - ConfigSubType = type; - ConfigSubNamespace = @namespace; - ConfigProperties = properties; - - return this; - } - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Information/PropertyInformation.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Information/PropertyInformation.cs deleted file mode 100644 index 635e2d0b..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Information/PropertyInformation.cs +++ /dev/null @@ -1,130 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Abstractions; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Enums; - -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Information -{ - internal sealed class PropertyInformation : InformationBase, IInformation - { - public PropertyInformation(bool hidden = false) - { - Hidden = hidden; - } - - public bool Hidden { get; } - - public string? Name { get; private set; } - - public string? PascalCaseName => ValidPascalCaseName(Name); - - public PropertyInformation HasName(string name) - { - Name = name; - return this; - } - - public string? Type { get; private set; } - - public PropertyInformation IsType(string type) - { - Type = type; - return this; - } - - public PropertyInformation IsRequired(bool isRequired) - { - if (isRequired) - { - Details.Add(new PropertyDetailInformation("NotNull")); - } - return this; - } - - public Relation Relation { get; set; } - public string? RelatedCollectionAlias { get; set; } - public string? RelatedPropertyName { get; set; } - - public PropertyInformation IsRelation( - Relation relation, - string? relatedCollectionAlias, - string? relatedPropertyName) - { - Relation = relation; - RelatedCollectionAlias = relatedCollectionAlias; - RelatedPropertyName = relatedPropertyName; - - return this; - } - - public bool IsTitleOfEntity { get; set; } - - public PropertyInformation IsTitle(bool isTitle) - { - IsTitleOfEntity = isTitle; - return this; - } - - public string? EditorType { get; private set; } - - public PropertyInformation UsesEditor(string type) - { - EditorType = type; - return this; - } - - public Use Uses { get; private set; } = Use.Collection | Use.Context | Use.Entity | Use.Repository; - - public PropertyInformation UseFor(Use use) - { - Uses = use; - return this; - } - - public bool IncludeInListView { get; private set; } - - public PropertyInformation ShouldBeDisplayedInListView(bool include) - { - IncludeInListView = include; - - return this; - } - - public List Details { get; private set; } = new List(); - - public PropertyInformation AddDetail(PropertyDetailInformation detail) - { - Details.Add(detail); - - return this; - } - - public bool IsValid() - { - return !string.IsNullOrEmpty(Name) && - !string.IsNullOrEmpty(Type) && - !string.IsNullOrEmpty(EditorType) && - Details.All(x => x.IsValid()); - } - - public IEnumerable NamespacesUsed(Use use) - { - if (use == Use.Entity && Relation.HasFlag(Relation.ToMany)) - { - yield return "System.Collections.Generic"; - } - - - foreach (var @namespace in _namespaces.Where(x => x.use.HasFlag(use)).Select(x => x.@namespace).Distinct()) - { - yield return @namespace; - } - - - foreach (var @namespace in Details.SelectMany(x => x.NamespacesUsed(use))) - { - yield return @namespace; - } - } - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/ModelMakerGenerator.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/ModelMakerGenerator.cs deleted file mode 100644 index 94897b27..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/ModelMakerGenerator.cs +++ /dev/null @@ -1,113 +0,0 @@ -using System.Collections.Generic; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Text; -using Newtonsoft.Json.Linq; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Builders; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Contexts; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Information; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Parsers; - -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore -{ - [Generator] - public class ModelMakerGenerator : ISourceGenerator - { - public void Initialize(GeneratorInitializationContext context) - { - - } - - public void Execute(GeneratorExecutionContext context) - { - var @namespace = "RapidCMS.ModelMaker"; // TODO: config? - - var propertyParser = new PropertyParser(); - var entityParser = new EntityParser(propertyParser); - - var propertyBuilder = new PropertyBuilder(); - var entityBuilder = new EntityBuilder(propertyBuilder); - var configObjectBuilder = new ConfigObjectBuilder(); - var entityValidatorBuilder = new EntityValidationBuilder(configObjectBuilder); - - var fieldBuilder = new FieldBuilder(configObjectBuilder); - var collectionBuilder = new CollectionBuilder(fieldBuilder); - - var contextBuilder = new ContextBuilder(); - var entityTypeConfigurationBuilder = new EntityTypeConfigurationBuilder(); - - var repositoryBuilder = new RepositoryBuilder(); - - var entities = new List(); - - foreach (var file in context.AdditionalFiles) - { - if (file.GetText() is SourceText text) - { - var jObject = JObject.Parse(text.ToString()); - - var entity = entityParser.ParseEntity(jObject); - - if (entity.IsValid()) // TODO: unit test - { - entities.Add(entity); - } - // context.ReportDiagnostic(Diagnostic.Create("RC0001", "", json.Value("$type"), DiagnosticSeverity.Warning, DiagnosticSeverity.Warning, true, 1)); - } - } - - var modelMakerContext = new ModelMakerContext(@namespace, entities); - - foreach (var entity in entities) - { - entityParser.NormalizeEntity(entity, modelMakerContext); - } - - foreach (var entity in entities) - { - entityParser.ExtendEntity(entity, modelMakerContext); - } - - foreach (var entity in entities) - { - var entitySourceText = entityBuilder.BuildEntity(entity, modelMakerContext); - if (entitySourceText != null) - { - context.AddSource($"ModelMaker_Entity_{entity.Name?.Replace(" ", "_")}.cs", entitySourceText); - } - - var validatorSourceText = entityValidatorBuilder.BuildValidation(entity, modelMakerContext); - if (validatorSourceText != null) - { - context.AddSource($"ModelMaker_EntityValidator_{entity.Name?.Replace(" ", "_")}.cs", validatorSourceText); - } - - var collectionSourceText = collectionBuilder.BuildCollection(entity, modelMakerContext); - if (collectionSourceText != null) - { - context.AddSource($"ModelMaker_Collection_{entity.Name?.Replace(" ", "_")}.cs", collectionSourceText); - } - } - - var contextSourceText = contextBuilder.BuildContext(modelMakerContext); - if (contextSourceText != null) - { - context.AddSource("ModelMaker_DbContext.cs", contextSourceText); - } - - foreach (var entity in entities) - { - var entityTypeConfigurationSourceText = entityTypeConfigurationBuilder.BuildEntityTypeConfiguration(entity, modelMakerContext); - if (entityTypeConfigurationSourceText != null) - { - context.AddSource($"ModelMaker_EntityTypeConfiguration_{entity.Name?.Replace(" ", "_")}.cs", entityTypeConfigurationSourceText); - } - - var repositorySourceText = repositoryBuilder.BuildRepository(entity, modelMakerContext); - if (repositorySourceText != null) - { - context.AddSource($"ModelMaker_Repository_{entity.Name?.Replace(" ", "_")}.cs", repositorySourceText); - } - } - } - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Parsers/EntityParser.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Parsers/EntityParser.cs deleted file mode 100644 index f4969365..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Parsers/EntityParser.cs +++ /dev/null @@ -1,192 +0,0 @@ -using System; -using System.Linq; -using Newtonsoft.Json.Linq; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Contexts; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Enums; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Information; - -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Parsers -{ - internal sealed class EntityParser - { - private readonly PropertyParser _propertyParser; - - public EntityParser(PropertyParser propertyParser) - { - _propertyParser = propertyParser; - } - - public EntityInformation ParseEntity(JObject entity) - { - var info = new EntityInformation(); - - if (entity.Value("Name") is string entityName) - { - info.HasName(entityName, entity.Value("PluralName")); - } - - if (entity.Value("Alias") is string alias) - { - info.HasAlias(alias); - } - - if (entity.Value("Icon") is string icon) - { - info.HasIcon(icon, entity.Value("IconColor")); - } - - if (entity.Value("Output") is string outputItems) - { - info.ShouldOutput(outputItems.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries)); - } - - if (entity.Value("Properties") is JObject propsRoot && - propsRoot.Value("$values") is JArray properties) - { - foreach (var property in properties.OfType()) - { - info.AddProperty(_propertyParser.ParseProperty(info, property)); - } - } - - return info; - } - - public void NormalizeEntity(EntityInformation info, ModelMakerContext context) - { - // both sides of the relation are configured with property names - var twoWayRelationsToThisEntity = context.Entities - .Where(entity => entity != info) - .SelectMany(entity => entity.Properties - .Where(x => x.Relation != Relation.None && - x.Type == $"{context.Namespace}.{info.PascalCaseName}" && - info.Properties.Any(p => p.PascalCaseName == x.RelatedPropertyName)) - .Select(property => new { Entity = entity, Property = property })) - .ToList(); - - foreach (var relation in twoWayRelationsToThisEntity) - { - try - { - var property = info.Properties.Single(x => x.PascalCaseName == relation.Property.RelatedPropertyName); - - var value = relation.Property.Relation & ~(Relation.One | Relation.Many); - - property.Relation |= value switch - { - Relation.ToOne => Relation.One, - Relation.ToMany => Relation.Many, - _ => Relation.None - }; - } - catch - { - continue; - } - } - - // only one side of the relation is configured with property names - var oneWayRelationsToThisEntity = context.Entities - .Where(entity => entity != info) - .SelectMany(entity => entity.Properties - .Where(x => x.Relation != Relation.None && - x.Type == $"{context.Namespace}.{info.PascalCaseName}" && - string.IsNullOrEmpty(x.RelatedPropertyName)) - .Select(property => new { Entity = entity, Property = property })) - .ToList(); - - foreach (var relation in oneWayRelationsToThisEntity) - { - try - { - var reciprocalProperty = info.Properties.SingleOrDefault(x => x.RelatedPropertyName == relation.Property.PascalCaseName); - if (reciprocalProperty != null) - { - relation.Property.RelatedPropertyName = reciprocalProperty.PascalCaseName; - - var value = relation.Property.Relation & ~(Relation.One | Relation.Many); - - reciprocalProperty.Relation |= value switch - { - Relation.ToOne => Relation.One, - Relation.ToMany => Relation.Many, - _ => Relation.None - }; - - if (reciprocalProperty.Relation.HasFlag(Relation.One | Relation.ToOne)) - { - reciprocalProperty.Relation |= Relation.DependentSide; - relation.Property.Relation |= Relation.One; - } - } - } - catch - { - continue; - } - } - } - - public void ExtendEntity(EntityInformation info, ModelMakerContext context) - { - // both sides of the relation are configured with property names - var twoWayOneToOneRelationsToThisEntity = context.Entities - .Where(entity => entity != info) - .SelectMany(entity => entity.Properties - .Where(x => x.Relation.HasFlag(Relation.One | Relation.ToOne) && - !x.Relation.HasFlag(Relation.DependentSide) && - x.Type == $"{context.Namespace}.{info.PascalCaseName}" && - info.Properties.Any(p => p.PascalCaseName == x.RelatedPropertyName && - p.Relation.HasFlag(Relation.One | Relation.ToOne) && - !p.Relation.HasFlag(Relation.DependentSide))) - .Select(property => new { Entity = entity, Property = property })) - .ToList(); - - foreach (var relation in twoWayOneToOneRelationsToThisEntity) - { - try - { - if (info.Name?.CompareTo(relation.Entity.Name) > 0) - { - relation.Property.Relation |= Relation.DependentSide; - } - } - catch - { - continue; - } - } - - // only one of the entities of this relation is configured - var oneWayRelationsToThisEntity = context.Entities - .Where(entity => entity != info) - .SelectMany(entity => entity.Properties - .Where(x => x.Relation != Relation.None && - x.Type == $"{context.Namespace}.{info.PascalCaseName}" && - string.IsNullOrEmpty(x.RelatedPropertyName)) - .Select(property => new { Entity = entity, Property = property })) - .ToList(); - - foreach (var relation in oneWayRelationsToThisEntity) - { - var reverseRelation = relation.Property.Relation switch - { - Relation.ToOne => Relation.One | Relation.ToMany, - Relation.ToMany => Relation.Many | Relation.ToMany, - _ => Relation.None - }; - - var adHocProperty = new PropertyInformation(true) - .UseFor(Use.Entity) - .HasName($"{relation.Entity.PascalCaseName}{relation.Property.PascalCaseName}") - .IsType($"{context.Namespace}.{relation.Entity.PascalCaseName}") - .IsRelation(reverseRelation, relation.Property.RelatedCollectionAlias, $"{relation.Entity.PascalCaseName}{relation.Property.PascalCaseName}"); - - relation.Property.RelatedPropertyName ??= $"{relation.Entity.PascalCaseName}{relation.Property.PascalCaseName}"; - relation.Property.Relation |= Relation.Many; - - info.AddProperty(adHocProperty); - } - } - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Parsers/PropertyParser.cs b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Parsers/PropertyParser.cs deleted file mode 100644 index c7346c87..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/Parsers/PropertyParser.cs +++ /dev/null @@ -1,179 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Text.RegularExpressions; -using Newtonsoft.Json.Linq; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Enums; -using RapidCMS.ModelMaker.SourceGenerator.EFCore.Information; - -namespace RapidCMS.ModelMaker.SourceGenerator.EFCore.Parsers -{ - internal sealed class PropertyParser - { - private readonly string[] _defaultConfigProperties = new[] - { - "IsEnabled", - "AlwaysIncluded", - "RelatedCollectionAlias", - "DataCollectionExpression", - "ValidiationMethodName", - "$type" - }; - - public PropertyInformation ParseProperty(EntityInformation entity, JObject property) - { - var info = new PropertyInformation(); - - if (property.Value("Name") is string propertyName) - { - info.HasName(propertyName); - } - - if (property.Value("Type") is string propertyType) - { - info.IsType(propertyType); - } - - if (property.Value("EditorType") is string editorType) - { - info.UsesEditor(editorType); - } - - if (property.Value("IsRequired") is bool required) - { - info.IsRequired(required); - } - - if (property.Value("IsTitle") is bool title) - { - info.IsTitle(title); - } - - if (property.Value("IncludeInListView") is bool include) - { - info.ShouldBeDisplayedInListView(include); - } - - var relatedCollectionAlias = default(string?); - var relatedPropertyName = default(string?); - - if (property.Value("Details") is JObject detailsRoot && - detailsRoot.Value("$values") is JArray details) - { - var enabledDetails = details - .OfType() - .Select(x => (validationModel: x, validationConfig: x.Value("Config"))) - .Where(x => x.validationConfig?.Value("IsEnabled") == true); - - foreach (var (detail, detailConfig) in enabledDetails) - { - if (ParseType(detailConfig.Value("$type")) is not (string @namespace, string typeName)) - { - continue; - } - - var detailInfo = new PropertyDetailInformation(typeName, @namespace); - - if (detailConfig.Value("DataCollectionType") is string dataCollection && - ParseTypeWithNamespace(dataCollection) is string dataCollectionType) - { - detailInfo.HasDataCollection(dataCollectionType); - } - - if (detailConfig.Value("RelatedCollectionAlias") is string related) - { - relatedCollectionAlias = related; - } - - if (detailConfig.Value("RelatedPropertyName") is string relatedPropName) - { - relatedPropertyName = relatedPropName; - } - - if (detailConfig.Value("ValidationMethodName") is string validationMethodName) - { - detailInfo.HasValidationMethod(validationMethodName); - } - - var configProperty = detailConfig.Properties().FirstOrDefault(x => !_defaultConfigProperties.Contains(x.Name)); - - if (configProperty?.Value is JValue value && - value.Value is object valueObject) - { - detailInfo.HasConfigValue(valueObject); - } - else if (configProperty?.Value is JObject listObject && - listObject.ContainsKey("$values") && - listObject.Value("$values") is JArray array && - array.Values() is IEnumerable list) - { - detailInfo.HasConfigList(configProperty.Name, list.Where(x => !string.IsNullOrWhiteSpace(x)).ToList()!); - } - else if (configProperty?.Value is JObject configObject && - configObject.ContainsKey("$type")) - { - if (ParseType(configObject.Value("$type")) is not (string configNamespace, string configType)) - { - continue; - } - - var dictionary = configObject.Properties() - .Where(x => x.Name != "$type") - .Where(x => x.Value is JValue value && value.Value is object valueObject) - .ToDictionary(x => x.Name, x => ((JValue)x.Value).Value!); - - detailInfo.HasSubClass(configProperty.Name, configType, configNamespace, dictionary); - } - - info.AddDetail(detailInfo); - } - } - - var relation = property.Value("IsRelationToOne") == true ? Relation.ToOne : - property.Value("IsRelationToMany") == true ? Relation.ToMany : - Relation.None; - - info.IsRelation( - relation, - relatedCollectionAlias, - relatedPropertyName); - - return info; - } - - public string? ParseTypeWithNamespace(string? type) - { - if (string.IsNullOrEmpty(type)) - { - return default; - } - - var replacedType = Regex.Replace(Regex.Replace(type! - .Replace("[[", "<") - .Replace("]]", ">") - .Replace("],[", ", "), - "`[0-9]+", - ""), - @"\,\s[a-zA-Z-0-9.]+\,\sVersion=[a-zA-Z0-9.]+\,\sCulture=[a-zA-Z0-9]+\,\sPublicKeyToken=[a-zA-Z0-9]+", - ""); - - return replacedType; - } - - private (string? @namespace, string? typeName) ParseType(string? type) - { - var parts = type?.Split(',').FirstOrDefault()?.Split('.').ToList(); - if (parts == null) - { - return default; - } - - var typeName = parts.Last().Replace("+", "."); - var @namespace = parts.Count < 2 ? string.Empty : string.Join(".", parts.Take(parts.Count - 1)); - - return (@namespace, typeName); - } - } -} diff --git a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/RapidCMS.ModelMaker.SourceGenerator.EFCore.csproj b/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/RapidCMS.ModelMaker.SourceGenerator.EFCore.csproj deleted file mode 100644 index 84356877..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator.EFCore/RapidCMS.ModelMaker.SourceGenerator.EFCore.csproj +++ /dev/null @@ -1,58 +0,0 @@ - - - - net6.0 - 10.0 - enable - Thomas Bleijendaal - Thomas Bleijendaal - - Entity Framework Core source generator for RapidCMS Model Maker. - - RapidCMS is a Blazor framework which allows you to build a responsive and flexible CMS purely from code. - - 2021 - true - https://github.com/ThomasBleijendaal/RapidCMS - Github - Blazor, CMS, EF Core, Entity Framework, Model Maker, Source Generator - LICENSE.md - true - true - snupkg - https://github.com/ThomasBleijendaal/RapidCMS - true - true - $(PackageVersion) - - - - 1701;1702;1591 - - - - 1701;1702;1591 - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - True - - - - - - - - - - - diff --git a/src/RapidCMS.ModelMaker.SourceGenerator/RapidCMS.ModelMaker.SourceGenerator.csproj b/src/RapidCMS.ModelMaker.SourceGenerator/RapidCMS.ModelMaker.SourceGenerator.csproj deleted file mode 100644 index 5c16636b..00000000 --- a/src/RapidCMS.ModelMaker.SourceGenerator/RapidCMS.ModelMaker.SourceGenerator.csproj +++ /dev/null @@ -1,50 +0,0 @@ - - - - net6.0 - 10.0 - enable - Thomas Bleijendaal - Thomas Bleijendaal - - Base library for specialized source generator addons for the RapidCMS Model Maker. - - RapidCMS is a Blazor framework which allows you to build a responsive and flexible CMS purely from code. - - 2021 - true - https://github.com/ThomasBleijendaal/RapidCMS - Github - Blazor, CMS - LICENSE.md - true - true - snupkg - https://github.com/ThomasBleijendaal/RapidCMS - true - $(PackageVersion) - - - - 1701;1702;1591 - - - - 1701;1702;1591 - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - True - - - - diff --git a/src/RapidCMS.ModelMaker/Abstractions/CommandHandlers/ICommandHandler.cs b/src/RapidCMS.ModelMaker/Abstractions/CommandHandlers/ICommandHandler.cs deleted file mode 100644 index 957e8c1d..00000000 --- a/src/RapidCMS.ModelMaker/Abstractions/CommandHandlers/ICommandHandler.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Threading.Tasks; - -namespace RapidCMS.ModelMaker.Abstractions.CommandHandlers -{ - public interface ICommandHandler - { - Task HandleAsync(TRequest request); - } -} diff --git a/src/RapidCMS.ModelMaker/Abstractions/Config/IModelMakerConfig.cs b/src/RapidCMS.ModelMaker/Abstractions/Config/IModelMakerConfig.cs deleted file mode 100644 index 95e4c1ba..00000000 --- a/src/RapidCMS.ModelMaker/Abstractions/Config/IModelMakerConfig.cs +++ /dev/null @@ -1,179 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq.Expressions; -using RapidCMS.Core.Abstractions.Data; -using RapidCMS.Core.Enums; -using RapidCMS.ModelMaker.Abstractions.Detail; -using RapidCMS.UI.Components.Editors; - -namespace RapidCMS.ModelMaker.Abstractions.Config -{ - public interface IModelMakerConfig - { - /// - /// Adds a property detail which can be added to one or more properties. Since no DetailConfig object is added, this detail is always active and not configurable by the user. - /// - /// - /// - /// - /// - /// - IPropertyDetailConfig AddPropertyDetail(string alias, string name, string? description) - where TDataCollection : IDataCollection; - - /// - /// Adds a property detail which can be added to one or more properties. An editor allows the user to configure the property detail. The TDetailConfig should set its Enabled flag high for its config to be applied to generated code. - /// - /// - /// - /// - /// - /// - /// - /// Expression to configure what property of TDetailConfig should be used for the editor. - /// - IPropertyDetailConfig AddPropertyDetail(string alias, string name, string? description, EditorType editorType, Expression, TValueForEditor>> configEditor) - where TDetailConfig : class, IDetailConfig; - - /// - /// Adds a property detail which can be added to one or more properties. An editor allows the user to configure the property detail. The TDetailConfig should set its Enabled flag high for its config to be applied to generated code. - /// - /// - /// - /// - /// - /// - /// - IPropertyDetailConfig AddPropertyDetail(string alias, string name, string? description) - where TDetailConfig : IDetailConfig - where TCustomEditor : BasePropertyEditor; - - /// - /// Adds a property detail which can be added to one or more properties. An editor allows the user to configure the property detail. The TDetailConfig should set its Enabled flag high for its config to be applied to generated code. - /// - /// - /// - /// - /// - /// - /// - /// - /// Expression to configure what property of TDetailConfig should be used for the editor. - /// - IPropertyDetailConfig AddPropertyDetail(string alias, string name, string? description, EditorType editorType, Expression, TValueForEditor>> configEditor) - where TDetailConfig : class, IDetailConfig - where TDataCollection : IDataCollection; - - /// - /// Adds a property detail which can be added to one or more properties. An editor allows the user to configure the property detail. The TDetailConfig should set its Enabled flag high for its config to be applied to generated code. - /// - /// - /// - /// - /// - /// - /// - /// - IPropertyDetailConfig AddPropertyDetail(string alias, string name, string? description) - where TDetailConfig : IDetailConfig - where TCustomEditor : BasePropertyEditor - where TDataCollection : IDataCollection; - - /// - /// Adds a property editor which can be added to one or more properties. - /// - /// - /// - /// - /// - IPropertyEditorConfig AddPropertyEditor(string alias, string name, EditorType editorType); - - /// - /// Adds a property editor which can be added to one or more properties. - /// - /// - /// - /// - /// - IPropertyEditorConfig AddPropertyEditor(string alias, string name) - where TCustomEditor : BasePropertyEditor; - - /// - /// Adds a property which can be added to models. Add editors and details to enrich the property. - /// - /// - /// - /// - /// - /// - /// - /// - IPropertyConfig AddProperty(string alias, string name, string icon, - IEnumerable editorAliases, - IEnumerable detailAliases); - - /// - /// Gets the current configuration for the given property editor type. - /// - /// - /// - IPropertyEditorConfig? GetPropertyEditor(EditorType editorType); - - /// - /// Gets the current configuration for the given property editor type. - /// - /// - /// - IPropertyEditorConfig? GetPropertyEditor(); - - /// - /// Gets the current configuration for the given property editor alias. - /// - /// - /// - IPropertyEditorConfig? GetPropertyEditor(string alias); - - /// - /// Gets the current configuration for the given property alias. - /// - /// - /// - IPropertyConfig? GetProperty(string alias); - - /// - /// Gets the available editors. - /// - IEnumerable Editors { get; } - - /// - /// Gets the available property details. - /// - IEnumerable PropertyDetails { get; } - - /// - /// Gets the available properties. - /// - IEnumerable Properties { get; } - - /// - /// Gets the current folder to save model jsons. - /// - string ModelFolder { get; } - - /// - /// Sets the folder to save model jsons. - /// - /// - void SetModelFolder(string folder); - - /// - /// Gets the type of the model repository - /// - Type ModelRespository { get; internal set; } - - /// - /// Gets the type of the property repository - /// - Type PropertyRepository { get; internal set; } - } -} diff --git a/src/RapidCMS.ModelMaker/Abstractions/Config/IPropertyConfig.cs b/src/RapidCMS.ModelMaker/Abstractions/Config/IPropertyConfig.cs deleted file mode 100644 index 27d05232..00000000 --- a/src/RapidCMS.ModelMaker/Abstractions/Config/IPropertyConfig.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace RapidCMS.ModelMaker.Abstractions.Config -{ - public interface IPropertyConfig - { - string Alias { get; } - string Name { get; } - string Icon { get; } - - Type Type { get; } - - bool UsableAsTitle { get; } - - bool IsRelationToOne { get; } - bool IsRelationToMany { get; } - - IList Details { get; } - IList Editors { get; } - - IPropertyConfig CanBeUsedAsTitle(bool usedAsTitle); - IPropertyConfig RelatesToOneEntity(bool isRelation); - IPropertyConfig RelatesToManyEntities(bool isRelation); - } -} diff --git a/src/RapidCMS.ModelMaker/Abstractions/Config/IPropertyDetailConfig.cs b/src/RapidCMS.ModelMaker/Abstractions/Config/IPropertyDetailConfig.cs deleted file mode 100644 index b85cb394..00000000 --- a/src/RapidCMS.ModelMaker/Abstractions/Config/IPropertyDetailConfig.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using RapidCMS.Core.Abstractions.Metadata; - -namespace RapidCMS.ModelMaker.Abstractions.Config -{ - public interface IPropertyDetailConfig - { - string Alias { get; } - string Name { get; } - string? Description { get; } - - Type? Editor { get; } - - Type Config { get; } - - IFullPropertyMetadata? ConfigToEditor { get; } - - Type? DataCollection { get; } - } -} diff --git a/src/RapidCMS.ModelMaker/Abstractions/Config/IPropertyEditorConfig.cs b/src/RapidCMS.ModelMaker/Abstractions/Config/IPropertyEditorConfig.cs deleted file mode 100644 index dc71737c..00000000 --- a/src/RapidCMS.ModelMaker/Abstractions/Config/IPropertyEditorConfig.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace RapidCMS.ModelMaker.Abstractions.Config -{ - public interface IPropertyEditorConfig - { - string Alias { get; } - string Name { get; } - Type Editor { get; } - } -} diff --git a/src/RapidCMS.ModelMaker/Abstractions/Detail/IDetailConfig.cs b/src/RapidCMS.ModelMaker/Abstractions/Detail/IDetailConfig.cs deleted file mode 100644 index d93c9dc1..00000000 --- a/src/RapidCMS.ModelMaker/Abstractions/Detail/IDetailConfig.cs +++ /dev/null @@ -1,39 +0,0 @@ -using RapidCMS.ModelMaker.Models.Entities; - -namespace RapidCMS.ModelMaker.Abstractions.Detail -{ - public interface IDetailConfig - { - /// - /// Indicates whether the config should be saved when saving the model. - /// - bool IsEnabled { get; } - - /// - /// Indicates whether the editor for this config is visible in the model editor. - /// - /// - /// - bool IsApplicable(PropertyModel model); - - /// - /// Indicates whether the config should always be saved when saving the model. - /// - bool AlwaysIncluded { get; } - - /// - /// Indicates the collection alias of the related entity / entities. - /// - string? RelatedCollectionAlias { get; } - - /// - /// Name of the FluentValidation validation extension method. - /// - string? ValidationMethodName { get; } - - /// - /// Type of data collection to be used from this property. - /// - string? DataCollectionType { get; } - } -} diff --git a/src/RapidCMS.ModelMaker/Abstractions/Detail/IPropertyDetailModel.cs b/src/RapidCMS.ModelMaker/Abstractions/Detail/IPropertyDetailModel.cs deleted file mode 100644 index 67829571..00000000 --- a/src/RapidCMS.ModelMaker/Abstractions/Detail/IPropertyDetailModel.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace RapidCMS.ModelMaker.Abstractions.Detail -{ - public interface IPropertyDetailModel - where TDetailConfig : IDetailConfig - { - TDetailConfig Config { get; } - } -} diff --git a/src/RapidCMS.ModelMaker/Collections/ModelCollection.cs b/src/RapidCMS.ModelMaker/Collections/ModelCollection.cs deleted file mode 100644 index e53a224b..00000000 --- a/src/RapidCMS.ModelMaker/Collections/ModelCollection.cs +++ /dev/null @@ -1,74 +0,0 @@ -using Microsoft.AspNetCore.Components; -using RapidCMS.Core.Abstractions.Config; -using RapidCMS.Core.Enums; -using RapidCMS.Core.Providers; -using RapidCMS.ModelMaker.Enums; -using RapidCMS.ModelMaker.Models.Entities; -using RapidCMS.ModelMaker.Repositories; - -namespace RapidCMS.ModelMaker.Collections -{ - internal static class ModelCollection - { - public static void AddModelCollection(this ICmsConfig cmsConfig) - { - var config = cmsConfig.AddCollection( - Constants.ModelMakerAdminCollectionAlias, - "Database", - "MagentaPink10", - "Models", - x => { }); - - config.SetTreeView(x => x.Name); - - config.SetListView(view => - { - view.AddDefaultButton(DefaultButtonType.New); - - view.AddRow(row => - { - row.AddField(x => x.Name); - row.AddField(x => x.PluralName).SetName("Plural name"); - - row.AddDefaultButton(DefaultButtonType.Edit); - }); - }); - - config.SetNodeEditor(editor => - { - editor.AddSection(section => - { - section.AddDefaultButton(DefaultButtonType.Up); - section.AddDefaultButton(DefaultButtonType.SaveExisting); - section.AddDefaultButton(DefaultButtonType.SaveNew); - section.AddDefaultButton(DefaultButtonType.Delete); - - section.AddField(x => x.Name); - - section.AddField(x => x.PluralName) - .SetName("Plural name"); - - section.AddField(x => x.IconColor) - .SetDetails(new MarkupString("See Shared Colors at https://developer.microsoft.com/en-us/fluentui#/styles/web/colors/shared.")) - .SetType(EditorType.Dropdown) - .SetDataCollection>(); - - section.AddField(x => x.Icon) - .SetDetails(new MarkupString("See Fabric Core icons at https://developer.microsoft.com/en-us/fluentui#/styles/web/icons#available-icons.")); - - section.AddField(x => x.Alias) - .SetName("Collection alias") - .SetType(EditorType.Readonly) - .VisibleWhen((m, s) => s == EntityState.IsExisting); - - section.AddField(x => x.Output) - .SetDescription("Code will be generated for these items") - .SetType(EditorType.EnumFlagPicker) - .SetDataCollection>(); - - section.AddSubCollectionList("modelmaker::property"); - }); - }); - } - } -} diff --git a/src/RapidCMS.ModelMaker/CommandHandlers/Base/BaseCommandHandler.cs b/src/RapidCMS.ModelMaker/CommandHandlers/Base/BaseCommandHandler.cs deleted file mode 100644 index ed64b703..00000000 --- a/src/RapidCMS.ModelMaker/CommandHandlers/Base/BaseCommandHandler.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; -using System.IO; -using System.Threading.Tasks; -using Newtonsoft.Json; -using RapidCMS.ModelMaker.Abstractions.Config; -using RapidCMS.ModelMaker.Models.Entities; - -namespace RapidCMS.ModelMaker.CommandHandlers.Base -{ - internal abstract class BaseCommandHandler - { - protected readonly IModelMakerConfig _config; - private readonly JsonSerializerSettings _jsonSerializerSettings = new() - { - Formatting = Formatting.Indented, - TypeNameHandling = TypeNameHandling.All - }; - - - public BaseCommandHandler(IModelMakerConfig config) - { - _config = config; - } - - protected string FileName(string id) => $"{_config.ModelFolder}modelmaker.{id}.json"; - - protected async Task ReadFileToModelAsync(string fileName) - { - if (!File.Exists(fileName)) - { - return default; - } - - // TODO: this should open the file without any locks - var json = await File.ReadAllTextAsync(fileName); - return JsonConvert.DeserializeObject(json, _jsonSerializerSettings); - } - - protected async Task WriteModelToFileAsync(ModelEntity entity) - { - var json = JsonConvert.SerializeObject(entity, _jsonSerializerSettings); - var fileName = FileName(entity.Id ?? throw new InvalidOperationException("Cannot save entity without Id")); - - await File.WriteAllTextAsync(fileName, json); - } - } -} diff --git a/src/RapidCMS.ModelMaker/CommandHandlers/GetAllModelEntitiesCommandHandler.cs b/src/RapidCMS.ModelMaker/CommandHandlers/GetAllModelEntitiesCommandHandler.cs deleted file mode 100644 index c74b7626..00000000 --- a/src/RapidCMS.ModelMaker/CommandHandlers/GetAllModelEntitiesCommandHandler.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using RapidCMS.ModelMaker.Abstractions.CommandHandlers; -using RapidCMS.ModelMaker.Abstractions.Config; -using RapidCMS.ModelMaker.CommandHandlers.Base; -using RapidCMS.ModelMaker.Models.Commands; -using RapidCMS.ModelMaker.Models.Entities; -using RapidCMS.ModelMaker.Models.Responses; - -namespace RapidCMS.ModelMaker.CommandHandlers -{ - internal class GetAllModelEntitiesCommandHandler : BaseCommandHandler, - ICommandHandler, EntitiesResponse> - { - public GetAllModelEntitiesCommandHandler(IModelMakerConfig config) : base(config) - { - } - - public async Task> HandleAsync(GetAllRequest request) - { - if (!Directory.Exists(_config.ModelFolder)) - { - Directory.CreateDirectory(_config.ModelFolder); - } - - var files = Directory.GetFiles(_config.ModelFolder, "*.json") - .OrderBy(x => x); - - var results = new List(); - - foreach (var fileName in files) - { - if (await ReadFileToModelAsync(fileName) is ModelEntity entity) - { - results.Add(entity); - } - } - - return new EntitiesResponse { Entities = results }; - } - } -} diff --git a/src/RapidCMS.ModelMaker/CommandHandlers/GetModelEntityCommandHandler.cs b/src/RapidCMS.ModelMaker/CommandHandlers/GetModelEntityCommandHandler.cs deleted file mode 100644 index 054c1608..00000000 --- a/src/RapidCMS.ModelMaker/CommandHandlers/GetModelEntityCommandHandler.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Threading.Tasks; -using RapidCMS.ModelMaker.Abstractions.CommandHandlers; -using RapidCMS.ModelMaker.Abstractions.Config; -using RapidCMS.ModelMaker.CommandHandlers.Base; -using RapidCMS.ModelMaker.Models.Commands; -using RapidCMS.ModelMaker.Models.Entities; -using RapidCMS.ModelMaker.Models.Responses; - -namespace RapidCMS.ModelMaker.CommandHandlers -{ - internal class GetModelEntityCommandHandler : BaseCommandHandler, - ICommandHandler, EntityResponse> - { - public GetModelEntityCommandHandler(IModelMakerConfig config) : base(config) - { - } - - public async Task> HandleAsync(GetByIdRequest request) - => new EntityResponse { Entity = await ReadFileToModelAsync(FileName(request.Id)) }; - } -} diff --git a/src/RapidCMS.ModelMaker/CommandHandlers/InsertModelEntityCommandHandler.cs b/src/RapidCMS.ModelMaker/CommandHandlers/InsertModelEntityCommandHandler.cs deleted file mode 100644 index 43ec5f3f..00000000 --- a/src/RapidCMS.ModelMaker/CommandHandlers/InsertModelEntityCommandHandler.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Threading.Tasks; -using RapidCMS.ModelMaker.Abstractions.CommandHandlers; -using RapidCMS.ModelMaker.Abstractions.Config; -using RapidCMS.ModelMaker.CommandHandlers.Base; -using RapidCMS.ModelMaker.Models.Commands; -using RapidCMS.ModelMaker.Models.Entities; -using RapidCMS.ModelMaker.Models.Responses; - -namespace RapidCMS.ModelMaker.CommandHandlers -{ - internal class InsertModelEntityCommandHandler : BaseCommandHandler, - ICommandHandler, EntityResponse> - { - public InsertModelEntityCommandHandler(IModelMakerConfig config) : base(config) - { - } - - public async Task> HandleAsync(InsertRequest request) - { - await WriteModelToFileAsync(request.Entity); - - return new EntityResponse { Entity = request.Entity }; - } - } -} diff --git a/src/RapidCMS.ModelMaker/CommandHandlers/PublishModelEntityCommandHandler.cs b/src/RapidCMS.ModelMaker/CommandHandlers/PublishModelEntityCommandHandler.cs deleted file mode 100644 index 5810ac9f..00000000 --- a/src/RapidCMS.ModelMaker/CommandHandlers/PublishModelEntityCommandHandler.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Threading.Tasks; -using RapidCMS.ModelMaker.Abstractions.CommandHandlers; -using RapidCMS.ModelMaker.Abstractions.Config; -using RapidCMS.ModelMaker.CommandHandlers.Base; -using RapidCMS.ModelMaker.Models.Commands; -using RapidCMS.ModelMaker.Models.Entities; -using RapidCMS.ModelMaker.Models.Responses; - -namespace RapidCMS.ModelMaker.CommandHandlers -{ - internal class PublishModelEntityCommandHandler : BaseCommandHandler, - ICommandHandler, ConfirmResponse> - { - private readonly ICommandHandler, EntityResponse> _commandHandler; - - public PublishModelEntityCommandHandler( - ICommandHandler, EntityResponse> commandHandler, - IModelMakerConfig config) : base(config) - { - _commandHandler = commandHandler; - } - - public async Task HandleAsync(PublishRequest request) - { - if (string.IsNullOrEmpty(request.Entity.Id)) - { - throw new InvalidOperationException(); - } - - await WriteModelToFileAsync(request.Entity); - - return new ConfirmResponse - { - Success = true - }; - } - } -} diff --git a/src/RapidCMS.ModelMaker/CommandHandlers/RemoveEntityCommandHandler.cs b/src/RapidCMS.ModelMaker/CommandHandlers/RemoveEntityCommandHandler.cs deleted file mode 100644 index f7d00899..00000000 --- a/src/RapidCMS.ModelMaker/CommandHandlers/RemoveEntityCommandHandler.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System.IO; -using System.Threading.Tasks; -using RapidCMS.ModelMaker.Abstractions.CommandHandlers; -using RapidCMS.ModelMaker.Abstractions.Config; -using RapidCMS.ModelMaker.CommandHandlers.Base; -using RapidCMS.ModelMaker.Models.Commands; -using RapidCMS.ModelMaker.Models.Entities; -using RapidCMS.ModelMaker.Models.Responses; - -namespace RapidCMS.ModelMaker.CommandHandlers -{ - internal class RemoveModelEntityCommandHandler : BaseCommandHandler, - ICommandHandler, ConfirmResponse> - { - public RemoveModelEntityCommandHandler(IModelMakerConfig config) : base(config) - { - } - - public Task HandleAsync(RemoveRequest request) - { - var fileName = FileName(request.Id); - - if (File.Exists(fileName)) - { - File.Delete(fileName); - } - - return Task.FromResult(new ConfirmResponse - { - Success = true - }); - } - } -} diff --git a/src/RapidCMS.ModelMaker/CommandHandlers/UpdateEntityCommandHandler.cs b/src/RapidCMS.ModelMaker/CommandHandlers/UpdateEntityCommandHandler.cs deleted file mode 100644 index d0aab7d2..00000000 --- a/src/RapidCMS.ModelMaker/CommandHandlers/UpdateEntityCommandHandler.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Threading.Tasks; -using RapidCMS.ModelMaker.Abstractions.CommandHandlers; -using RapidCMS.ModelMaker.Abstractions.Config; -using RapidCMS.ModelMaker.CommandHandlers.Base; -using RapidCMS.ModelMaker.Models.Commands; -using RapidCMS.ModelMaker.Models.Entities; -using RapidCMS.ModelMaker.Models.Responses; - -namespace RapidCMS.ModelMaker.CommandHandlers -{ - internal class UpdateModelEntityCommandHandler : BaseCommandHandler, - ICommandHandler, ConfirmResponse> - { - public UpdateModelEntityCommandHandler(IModelMakerConfig config) : base(config) - { - } - - - public async Task HandleAsync(UpdateRequest request) - { - await WriteModelToFileAsync(request.Entity); - - return new ConfirmResponse - { - Success = true - }; - } - } -} diff --git a/src/RapidCMS.ModelMaker/Components/_Imports.razor b/src/RapidCMS.ModelMaker/Components/_Imports.razor deleted file mode 100644 index e7b575fd..00000000 --- a/src/RapidCMS.ModelMaker/Components/_Imports.razor +++ /dev/null @@ -1,4 +0,0 @@ -@using RapidCMS.Core.Forms - -@using RapidCMS.UI.Components.Displays -@using RapidCMS.UI.Components.Sections diff --git a/src/RapidCMS.ModelMaker/ConfigurationExtensions.cs b/src/RapidCMS.ModelMaker/ConfigurationExtensions.cs deleted file mode 100644 index 3d5081e1..00000000 --- a/src/RapidCMS.ModelMaker/ConfigurationExtensions.cs +++ /dev/null @@ -1,225 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Microsoft.Extensions.DependencyInjection; -using RapidCMS.Core.Abstractions.Config; -using RapidCMS.Core.Abstractions.Plugins; -using RapidCMS.Core.Enums; -using RapidCMS.ModelMaker.Abstractions.CommandHandlers; -using RapidCMS.ModelMaker.Abstractions.Config; -using RapidCMS.ModelMaker.Collections; -using RapidCMS.ModelMaker.CommandHandlers; -using RapidCMS.ModelMaker.DataCollections; -using RapidCMS.ModelMaker.Models; -using RapidCMS.ModelMaker.Models.Commands; -using RapidCMS.ModelMaker.Models.Entities; -using RapidCMS.ModelMaker.Models.Responses; -using RapidCMS.ModelMaker.Repositories; -using RapidCMS.ModelMaker.Validation.Config; - -namespace RapidCMS.ModelMaker -{ - public static class ConfigurationExtensions - { - /// - /// This method adds the core functionalities for Model Maker. - /// - /// Use in RapidCMS WebAssembly. - /// - public static IServiceCollection AddModelMakerCoreCollections( - this IServiceCollection services) - { - services.AddTransient(); - - return services; - } - - /// - /// This method adds the core of Model Maker next to the repositories to save Model Maker Models in this project. - /// - /// - /// - /// - /// - public static IServiceCollection AddModelMaker( - this IServiceCollection services, - bool addDefaultPropertiesAndValidators = true, - Action? configure = null) - { - var config = new ModelMakerConfig(); - - if (addDefaultPropertiesAndValidators) - { - config.AddPropertyDetail( - Constants.PropertyDetails.MinLength, - "Minimum length", - "The value has to be at least this amount of characters.", - EditorType.Numeric, - x => x.Config.MinLength); - - config.AddPropertyDetail( - Constants.PropertyDetails.MaxLength, - "Maximum length", - "The value has to be at most this amount of characters.", - EditorType.Numeric, - x => x.Config.MaxLength); - - config.AddPropertyDetail>( - Constants.PropertyDetails.LimitedOptions, - "Limited options", - "The value has to be one of these items", - EditorType.ListEditor, - x => x.Config.Options); - - config.AddPropertyDetail( - Constants.PropertyDetails.LinkedEntity, - "Linked entity", - "The value has to be one of the entities of the linked collection", - EditorType.Dropdown, - x => x.Config.LinkedEntityCollectionAlias); - - config.AddPropertyDetail( - Constants.PropertyDetails.LinkedEntities, - "Linked entity", - "The value has to be one or more of the entities of the linked collection", - EditorType.Dropdown, - x => x.Config.LinkedEntitiesCollectionAlias); - - config.AddPropertyDetail( - Constants.PropertyDetails.ReciprocalProperty, - "Corresponding property", - "The property of the relation on the other model. If kept empty, a hidden corresponding property will be created.", - EditorType.Dropdown, - x => x.Config.RelatedPropertyName); - - config.AddPropertyDetail( - Constants.PropertyDetails.BooleanLabels, - "Labels", - "The editor will display a dropdown instead of a checkbox", - EditorType.ModelEditor, - x => x.Config.Labels); - - config.AddPropertyEditor(Constants.Editors.Checkbox, "Checkbox", EditorType.Checkbox); - config.AddPropertyEditor(Constants.Editors.Date, "Date", EditorType.Date); - config.AddPropertyEditor(Constants.Editors.Dropdown, "Dropdown", EditorType.Dropdown); - config.AddPropertyEditor(Constants.Editors.EntitiesPicker, "Entities Picker", EditorType.EntitiesPicker); - config.AddPropertyEditor(Constants.Editors.EntityPicker, "Enitity Picker", EditorType.EntityPicker); - config.AddPropertyEditor(Constants.Editors.MultiSelect, "Multi-select", EditorType.MultiSelect); - config.AddPropertyEditor(Constants.Editors.Numeric, "Numeric", EditorType.Numeric); - config.AddPropertyEditor(Constants.Editors.Select, "Select", EditorType.Select); - config.AddPropertyEditor(Constants.Editors.TextArea, "Text area", EditorType.TextArea); - config.AddPropertyEditor(Constants.Editors.TextBox, "Text box", EditorType.TextBox); - - config.AddProperty( - Constants.Properties.ShortString, - "Short string", - "Label", - new[] { Constants.Editors.TextBox, Constants.Editors.TextArea, Constants.Editors.Dropdown }, - new[] { Constants.PropertyDetails.MinLength, Constants.PropertyDetails.MaxLength, Constants.PropertyDetails.LimitedOptions }); - - config.AddProperty( - Constants.Properties.LongString, - "Long string", - "Label", - new[] { Constants.Editors.TextArea }, - new[] { Constants.PropertyDetails.MinLength }); - - config.AddProperty( - Constants.Properties.Boolean, - "Boolean", - "ToggleLeft", - new[] { Constants.Editors.Checkbox, Constants.Editors.Dropdown, Constants.Editors.Select }, - new[] { Constants.PropertyDetails.BooleanLabels }); - - config.AddProperty( - Constants.Properties.LinkedEntity, - "Linked entity", - "Link", - new[] { Constants.Editors.EntityPicker }, - new[] { Constants.PropertyDetails.LinkedEntity, Constants.PropertyDetails.ReciprocalProperty }) - .CanBeUsedAsTitle(false) - .RelatesToOneEntity(true); - - config.AddProperty>( - Constants.Properties.LinkedEntities, - "Linked entities", - "Link", - new[] { Constants.Editors.EntitiesPicker }, - new[] { Constants.PropertyDetails.LinkedEntities, Constants.PropertyDetails.ReciprocalProperty }) // TODO: min max linkedentities - .CanBeUsedAsTitle(false) - .RelatesToManyEntities(true); - - config.AddProperty( - Constants.Properties.Date, - "Date", - "Calendar", - new[] { Constants.Editors.Date }, - Enumerable.Empty()); // TODO: date validation (valid ranges etc) - - config.AddProperty( - Constants.Properties.Numeric, - "Number", - "NumberField", - new[] { Constants.Editors.Numeric }, - Enumerable.Empty()) - .CanBeUsedAsTitle(false); // TODO: min max limitedoptions - - // TODO: slug, media, reference(s) (model maker / external), markdown, JSON object, date, date time, time, rich text - } - - configure?.Invoke(config); - - services.AddSingleton(config); - - services.AddTransient(); - - services.AddModelMakerCoreCollections(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - - services.AddScoped(); - services.AddScoped(); - - services.AddTransient, ConfirmResponse>, RemoveModelEntityCommandHandler>(); - - services.AddTransient, EntitiesResponse>, GetAllModelEntitiesCommandHandler>(); - services.AddTransient, EntityResponse>, GetModelEntityCommandHandler>(); - - services.AddTransient, EntityResponse>, InsertModelEntityCommandHandler>(); - services.AddTransient, ConfirmResponse>, UpdateModelEntityCommandHandler>(); - services.AddTransient, ConfirmResponse>, PublishModelEntityCommandHandler>(); - - return services; - } - - /// - /// This method adds the Model Maker plugin to RapidCMS without the Model collection. - /// - /// Use this when the code runs in production. - /// - /// - /// - public static ICmsConfig AddModelMakerPluginCore(this ICmsConfig cmsConfig) - { - cmsConfig.AddPlugin(); - - return cmsConfig; - } - - /// - /// This method adds the Model Maker plugin and collection to RapidCMS. - /// - /// - /// - public static ICmsConfig AddModelMakerPlugin(this ICmsConfig cmsConfig) - { - cmsConfig.AddModelMakerPluginCore(); - - cmsConfig.AddModelCollection(); - - return cmsConfig; - } - } -} diff --git a/src/RapidCMS.ModelMaker/Constants.cs b/src/RapidCMS.ModelMaker/Constants.cs deleted file mode 100644 index e4a84bd5..00000000 --- a/src/RapidCMS.ModelMaker/Constants.cs +++ /dev/null @@ -1,44 +0,0 @@ -namespace RapidCMS.ModelMaker -{ - public static class Constants - { - public static class Editors - { - public const string Checkbox = "checkbox"; - public const string Date = "date"; - public const string Dropdown = "dropdown"; - public const string EntitiesPicker = "entitiespicker"; - public const string EntityPicker = "entitypicker"; - public const string MultiSelect = "multiselect"; - public const string Numeric = "numeric"; - public const string Select = "select"; - public const string TextArea = "textarea"; - public const string TextBox = "textbox"; - } - - public static class PropertyDetails - { - public const string LimitedOptions = "limitedOptions"; - public const string LinkedEntities = "linkedEntities"; - public const string LinkedEntity = "linkedEntity"; - public const string MaxLength = "maxlength"; - public const string MinLength = "minlength"; - public const string BooleanLabels = "booleanLabels"; - public const string ReciprocalProperty = "reciprocal"; - } - - public static class Properties - { - public const string Boolean = "boolean"; - public const string Date = "date"; - public const string LinkedEntities = "linkedentities"; - public const string LinkedEntity = "linkedentity"; - public const string LongString = "longstring"; - public const string Numeric = "double"; - public const string ShortString = "shortstring"; - } - - public const string CollectionPrefix = "modelmaker"; - public const string ModelMakerAdminCollectionAlias = "modelmakeradmin"; - } -} diff --git a/src/RapidCMS.ModelMaker/DataCollections/BooleanLabelDataCollection.cs b/src/RapidCMS.ModelMaker/DataCollections/BooleanLabelDataCollection.cs deleted file mode 100644 index e15adfba..00000000 --- a/src/RapidCMS.ModelMaker/DataCollections/BooleanLabelDataCollection.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using RapidCMS.Core.Abstractions.Data; -using RapidCMS.Core.Abstractions.Metadata; -using RapidCMS.Core.Forms; -using RapidCMS.Core.Models.Data; -using RapidCMS.ModelMaker.Validation.Config; - -namespace RapidCMS.ModelMaker.DataCollections -{ - public class BooleanLabelDataCollection : IDataCollection - { - private BooleanLabelDetailConfig? _config; - - public event EventHandler? OnDataChange; - - public void Configure(object configuration) - { - _config = configuration as BooleanLabelDetailConfig; - } - - public void Dispose() - { - - } - - public Task> GetAvailableElementsAsync(IView view) - => Task.FromResult>(new List - { - new Element - { - Id = true, - Labels = new[] { _config?.Labels.TrueLabel ?? "True" } - }, - new Element - { - Id = false, - Labels = new[] { _config?.Labels.FalseLabel ?? "False" } - } - }); - - public Task SetEntityAsync(FormEditContext editContext, IPropertyMetadata property, IParent? parent) - => Task.CompletedTask; - } -} diff --git a/src/RapidCMS.ModelMaker/DataCollections/CollectionsDataCollection.cs b/src/RapidCMS.ModelMaker/DataCollections/CollectionsDataCollection.cs deleted file mode 100644 index b59852c3..00000000 --- a/src/RapidCMS.ModelMaker/DataCollections/CollectionsDataCollection.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using RapidCMS.Core.Abstractions.Data; -using RapidCMS.Core.Abstractions.Metadata; -using RapidCMS.Core.Abstractions.Resolvers; -using RapidCMS.Core.Enums; -using RapidCMS.Core.Forms; -using RapidCMS.Core.Models.Data; -using RapidCMS.Core.Models.Setup; - -namespace RapidCMS.ModelMaker.DataCollections -{ - internal class CollectionsDataCollection : IDataCollection - { - private readonly ISetupResolver> _setupResolver; - - public CollectionsDataCollection(ISetupResolver> setupResolver) - { - _setupResolver = setupResolver; - } - - public void Configure(object configuration) { } - - public event EventHandler? OnDataChange; - - public void Dispose() - { - } - - public async Task> GetAvailableElementsAsync(IView view) - { - var treeElements = await _setupResolver.ResolveSetupAsync(); - - return treeElements - .Where(treeElement => treeElement.Type == PageType.Collection) - .Where(treeElement => treeElement.Alias != Constants.ModelMakerAdminCollectionAlias) - .Select(treeElement => new Element - { - Id = treeElement.Alias, - Labels = new[] { treeElement.Name } - }) - .ToList(); - } - - public Task SetEntityAsync(FormEditContext editContext, IPropertyMetadata property, IParent? parent) - { - return Task.CompletedTask; - } - } -} diff --git a/src/RapidCMS.ModelMaker/DataCollections/PropertyEditorDataCollection.cs b/src/RapidCMS.ModelMaker/DataCollections/PropertyEditorDataCollection.cs deleted file mode 100644 index e0fb99a4..00000000 --- a/src/RapidCMS.ModelMaker/DataCollections/PropertyEditorDataCollection.cs +++ /dev/null @@ -1,79 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using RapidCMS.Core.Abstractions.Data; -using RapidCMS.Core.Abstractions.Metadata; -using RapidCMS.Core.Forms; -using RapidCMS.Core.Models.Data; -using RapidCMS.ModelMaker.Abstractions.Config; -using RapidCMS.ModelMaker.Models.Entities; - -namespace RapidCMS.ModelMaker.DataCollections -{ - internal class PropertyEditorDataCollection : IDataCollection - { - private readonly IModelMakerConfig _config; - private PropertyModel? _property; - private FormEditContext? _editContext; - - public PropertyEditorDataCollection(IModelMakerConfig config) - { - _config = config; - } - - public void Configure(object configuration) { } - - public event EventHandler? OnDataChange; - - public void Dispose() - { - if (_editContext != null) - { - _editContext.OnFieldChanged -= EditContext_OnFieldChanged; - } - } - - public Task> GetAvailableElementsAsync(IView view) - { - var property = _config.Properties.FirstOrDefault(x => x.Alias == _property?.PropertyAlias); - - return Task.FromResult>( - _config.Editors - .Where(e => property?.Editors.Any(pe => pe.Alias == e.Alias) ?? false) - .Select(x => new Element - { - Id = x.Alias, - Labels = new[] - { - x.Name - } - }) - .ToList()); - } - - public Task SetEntityAsync(FormEditContext editContext, IPropertyMetadata property, IParent? parent) - { - if (_editContext != null) - { - _editContext.OnFieldChanged -= EditContext_OnFieldChanged; - } - - _editContext = editContext; - - if (_editContext.Entity is PropertyModel propertyModel) - { - _editContext.OnFieldChanged += EditContext_OnFieldChanged; - - _property = propertyModel; - } - - return Task.CompletedTask; - } - - private void EditContext_OnFieldChanged(object? sender, FieldChangedEventArgs e) - { - OnDataChange?.Invoke(this, new EventArgs()); - } - } -} diff --git a/src/RapidCMS.ModelMaker/DataCollections/PropertyTypeDataCollection.cs b/src/RapidCMS.ModelMaker/DataCollections/PropertyTypeDataCollection.cs deleted file mode 100644 index cd535d0d..00000000 --- a/src/RapidCMS.ModelMaker/DataCollections/PropertyTypeDataCollection.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using RapidCMS.Core.Abstractions.Data; -using RapidCMS.Core.Abstractions.Metadata; -using RapidCMS.Core.Forms; -using RapidCMS.Core.Models.Data; -using RapidCMS.ModelMaker.Abstractions.Config; - -namespace RapidCMS.ModelMaker.DataCollections -{ - internal class PropertyTypeDataCollection : IDataCollection - { - private readonly IModelMakerConfig _config; - - public PropertyTypeDataCollection(IModelMakerConfig config) - { - _config = config; - } - public void Configure(object configuration) { } - - - public event EventHandler? OnDataChange; - - public void Dispose() - { - } - - public Task> GetAvailableElementsAsync(IView view) - { - return Task.FromResult>( - _config.Properties.Select(x => new Element - { - Id = x.Alias, - Labels = new[] { x.Name } - }).ToList()); - } - - public Task SetEntityAsync(FormEditContext editContext, IPropertyMetadata property, IParent? parent) - { - return Task.CompletedTask; - } - } -} diff --git a/src/RapidCMS.ModelMaker/DataCollections/ReciprocalPropertyDataCollection.cs b/src/RapidCMS.ModelMaker/DataCollections/ReciprocalPropertyDataCollection.cs deleted file mode 100644 index 64e412bf..00000000 --- a/src/RapidCMS.ModelMaker/DataCollections/ReciprocalPropertyDataCollection.cs +++ /dev/null @@ -1,96 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using RapidCMS.Core.Abstractions.Data; -using RapidCMS.Core.Abstractions.Metadata; -using RapidCMS.Core.Abstractions.Resolvers; -using RapidCMS.Core.Extensions; -using RapidCMS.Core.Forms; -using RapidCMS.Core.Models.Data; -using RapidCMS.Core.Models.Setup; -using RapidCMS.ModelMaker.Abstractions.CommandHandlers; -using RapidCMS.ModelMaker.Models.Commands; -using RapidCMS.ModelMaker.Models.Entities; -using RapidCMS.ModelMaker.Models.Responses; - -namespace RapidCMS.ModelMaker.DataCollections -{ - internal class ReciprocalPropertyDataCollection : IDataCollection - { - private readonly ISetupResolver _collectionSetupResolver; - private readonly ICommandHandler, EntityResponse> _modelResolver; - private PropertyModel? _property; - private FormEditContext? _editContext; - - public ReciprocalPropertyDataCollection( - ISetupResolver collectionSetupResolver, - ICommandHandler, EntityResponse> modelResolver) - { - _collectionSetupResolver = collectionSetupResolver; - _modelResolver = modelResolver; - } - public void Configure(object configuration) { } - - - public event EventHandler? OnDataChange; - - public void Dispose() - { - if (_editContext != null) - { - _editContext.OnFieldChanged -= EditContext_OnFieldChanged; - } - } - - public async Task> GetAvailableElementsAsync(IView view) - { - if (_editContext?.Parent?.Entity is ModelEntity modelEntity) - { - var collection = await _collectionSetupResolver.ResolveSetupAsync(modelEntity.Alias); - - var relatedCollectionAlias = _property?.Details.SelectNotNull(x => x.Config?.RelatedCollectionAlias).FirstOrDefault(); - if (relatedCollectionAlias is string alias) - { - var model = await _modelResolver.HandleAsync(new GetByIdRequest(alias)); - if (model.Entity != null) - { - var possibleProperties = model.Entity.Properties.Where(x => (x.IsRelationToMany || x.IsRelationToOne) && x.Type == collection.EntityVariant.Type.FullName); - - return possibleProperties.Select(x => new Element - { - Id = x.Name, - Labels = new[] { x.Name } - }).ToList(); - } - } - } - - return new List(); - } - - public Task SetEntityAsync(FormEditContext editContext, IPropertyMetadata property, IParent? parent) - { - if (_editContext != null) - { - _editContext.OnFieldChanged -= EditContext_OnFieldChanged; - } - - _editContext = editContext; - - if (_editContext.Entity is PropertyModel propertyModel) - { - _editContext.OnFieldChanged += EditContext_OnFieldChanged; - - _property = propertyModel; - } - - return Task.CompletedTask; - } - - private void EditContext_OnFieldChanged(object? sender, FieldChangedEventArgs e) - { - OnDataChange?.Invoke(this, new EventArgs()); - } - } -} diff --git a/src/RapidCMS.ModelMaker/Enums/Color.cs b/src/RapidCMS.ModelMaker/Enums/Color.cs deleted file mode 100644 index 42a0ffbf..00000000 --- a/src/RapidCMS.ModelMaker/Enums/Color.cs +++ /dev/null @@ -1,37 +0,0 @@ -namespace RapidCMS.ModelMaker.Enums -{ - public enum Color - { - PinkRed10, - Red20, - Red10, - RedOrange10, - Orange30, - Orange20, - Orange10, - Yellow10, - OrangeYellow20, - OrangeYellow10, - YellowGreen10, - Green20, - Green10, - GreenCyan10, - Cyan30, - Cyan20, - Cyan10, - CyanBlue20, - CyanBlue10, - Blue10, - BlueMagenta30, - BlueMagenta20, - BlueMagenta10, - Magenta20, - Magenta10, - MagentaPink20, - MagentaPink10, - Gray40, - Gray30, - Gray20, - Gray10 - } -} diff --git a/src/RapidCMS.ModelMaker/Enums/OutputItems.cs b/src/RapidCMS.ModelMaker/Enums/OutputItems.cs deleted file mode 100644 index b9a3dbcc..00000000 --- a/src/RapidCMS.ModelMaker/Enums/OutputItems.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; - -namespace RapidCMS.ModelMaker.Enums -{ - [Flags] - public enum OutputItem - { - Entity = 1, - Collection = 2, - Repository = 4, - Context = 8, - Validation = 16 - } -} diff --git a/src/RapidCMS.ModelMaker/EqualityComparers/PropertyValidationModelEqualityComparer.cs b/src/RapidCMS.ModelMaker/EqualityComparers/PropertyValidationModelEqualityComparer.cs deleted file mode 100644 index 64db2b40..00000000 --- a/src/RapidCMS.ModelMaker/EqualityComparers/PropertyValidationModelEqualityComparer.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Collections.Generic; -using RapidCMS.ModelMaker.Models.Entities; - -namespace RapidCMS.ModelMaker.EqualityComparers -{ - internal class PropertyValidationModelEqualityComparer : IEqualityComparer - { - public bool Equals(PropertyDetailModel? x, PropertyDetailModel? y) => x?.Alias == y?.Alias; - - public int GetHashCode(PropertyDetailModel obj) => obj.Alias.GetHashCode(); - } -} diff --git a/src/RapidCMS.ModelMaker/Extenstions/PropertyMetadataExtensions.cs b/src/RapidCMS.ModelMaker/Extenstions/PropertyMetadataExtensions.cs deleted file mode 100644 index 5b3f99d5..00000000 --- a/src/RapidCMS.ModelMaker/Extenstions/PropertyMetadataExtensions.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using RapidCMS.Core.Abstractions.Metadata; -using RapidCMS.ModelMaker.Metadata; - -namespace RapidCMS.ModelMaker.Extenstions -{ - public static class PropertyMetadataExtensions - { - public static IFullPropertyMetadata Nest( - this IFullPropertyMetadata propertyMetadata, - Func parentGettter) - { - var propertyMetadataType = typeof(NestedPropertyMetadata<,,>) - .MakeGenericType(typeof(TParentEntity), typeof(TEntity), propertyMetadata.PropertyType); - - return Activator.CreateInstance(propertyMetadataType, parentGettter, propertyMetadata) as IFullPropertyMetadata - ?? throw new InvalidOperationException(); - } - } -} diff --git a/src/RapidCMS.ModelMaker/Extenstions/PropertyModelExtensions.cs b/src/RapidCMS.ModelMaker/Extenstions/PropertyModelExtensions.cs deleted file mode 100644 index ca33c8e8..00000000 --- a/src/RapidCMS.ModelMaker/Extenstions/PropertyModelExtensions.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Linq; -using RapidCMS.ModelMaker.Models.Entities; - -namespace RapidCMS.ModelMaker.Extenstions -{ - public static class PropertyModelExtensions - { - public static PropertyDetailModel GetValidation(this PropertyModel property, string alias) - => property.Details.First(x => x.Alias == alias); - - public static PropertyDetailModel? TryGetValidation(this PropertyModel property, string alias) - => property.Details?.FirstOrDefault(x => x.Alias == alias); - } -} diff --git a/src/RapidCMS.ModelMaker/Metadata/ExpressionMetadata.cs b/src/RapidCMS.ModelMaker/Metadata/ExpressionMetadata.cs deleted file mode 100644 index ad1c459f..00000000 --- a/src/RapidCMS.ModelMaker/Metadata/ExpressionMetadata.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using RapidCMS.Core.Abstractions.Metadata; - -namespace RapidCMS.ModelMaker.Metadata -{ - internal class ExpressionMetadata : IExpressionMetadata - { - public ExpressionMetadata(string name, Func getter) - { - PropertyName = name; - StringGetter = x => getter.Invoke((TEntity)x) ?? string.Empty; - } - - public string PropertyName { get; } - - public Func StringGetter { get; } - } -} diff --git a/src/RapidCMS.ModelMaker/Metadata/NestedPropertyMetadata.cs b/src/RapidCMS.ModelMaker/Metadata/NestedPropertyMetadata.cs deleted file mode 100644 index fa99a42b..00000000 --- a/src/RapidCMS.ModelMaker/Metadata/NestedPropertyMetadata.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System; -using System.Linq.Expressions; -using RapidCMS.Core.Abstractions.Metadata; - -namespace RapidCMS.ModelMaker.Metadata -{ - internal class NestedPropertyMetadata : IFullPropertyMetadata - { - public NestedPropertyMetadata( - Func parent, - IFullPropertyMetadata propertyMetadata) - { - PropertyType = propertyMetadata.PropertyType; - PropertyName = propertyMetadata.PropertyName; - Fingerprint = $"{propertyMetadata.Fingerprint}::{typeof(TParentEntity).Name}"; - - Getter = x => - { - if (parent.Invoke((TParentEntity)x) is object obj) - { - return propertyMetadata.Getter.Invoke(obj); - } - - return default!; - }; - Setter = (x, y) => - { - if (parent.Invoke((TParentEntity)x) is object obj) - { - propertyMetadata.Setter.Invoke(obj, y); - } - }; - - ObjectType = typeof(TParentEntity); - OriginalExpression = propertyMetadata.OriginalExpression; - } - - public Type PropertyType { get; } - - public string PropertyName { get; } - public Type ObjectType { get; } - - public Func Getter { get; } - public Action Setter { get; } - - public string Fingerprint { get; } - - public LambdaExpression OriginalExpression { get; } - } -} diff --git a/src/RapidCMS.ModelMaker/Metadata/PropertyMetadata.cs b/src/RapidCMS.ModelMaker/Metadata/PropertyMetadata.cs deleted file mode 100644 index 30a8541b..00000000 --- a/src/RapidCMS.ModelMaker/Metadata/PropertyMetadata.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Linq.Expressions; -using RapidCMS.Core.Abstractions.Metadata; - -namespace RapidCMS.ModelMaker.Metadata -{ - internal class PropertyMetadata : IFullPropertyMetadata - { - public PropertyMetadata( - string propertyName, - Type propertyType, - Func getter, - Action setter, - string fingerprint) - { - PropertyType = propertyType; - PropertyName = propertyName; - Fingerprint = fingerprint; - - Getter = x => getter.Invoke((TEntity)x)!; - Setter = (x, y) => setter.Invoke((TEntity)x, y); - - ObjectType = typeof(TEntity); - OriginalExpression = Expression.Lambda(Expression.Empty()); - } - - public Type PropertyType { get; } - - public string PropertyName { get; } - public Type ObjectType { get; } - - public Func Getter { get; } - public Action Setter { get; } - - public string Fingerprint { get; } - - public LambdaExpression OriginalExpression { get; } - } -} diff --git a/src/RapidCMS.ModelMaker/ModelMakerPlugin.cs b/src/RapidCMS.ModelMaker/ModelMakerPlugin.cs deleted file mode 100644 index b180d737..00000000 --- a/src/RapidCMS.ModelMaker/ModelMakerPlugin.cs +++ /dev/null @@ -1,333 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using RapidCMS.Core.Abstractions.Metadata; -using RapidCMS.Core.Abstractions.Plugins; -using RapidCMS.Core.Abstractions.Resolvers; -using RapidCMS.Core.Abstractions.Setup; -using RapidCMS.Core.Enums; -using RapidCMS.Core.Extensions; -using RapidCMS.Core.Handlers; -using RapidCMS.Core.Helpers; -using RapidCMS.Core.Models.Config; -using RapidCMS.Core.Models.Setup; -using RapidCMS.ModelMaker.Abstractions.Config; -using RapidCMS.ModelMaker.Abstractions.Detail; -using RapidCMS.ModelMaker.DataCollections; -using RapidCMS.ModelMaker.Extenstions; -using RapidCMS.ModelMaker.Metadata; -using RapidCMS.ModelMaker.Models.Entities; -using RapidCMS.UI.Components.Editors; - -namespace RapidCMS.ModelMaker -{ - internal class ModelMakerPlugin : IPlugin - { - private readonly IModelMakerConfig _config; - - public ModelMakerPlugin(IModelMakerConfig config) - { - _config = config; - } - - public string CollectionPrefix => Constants.CollectionPrefix; - - public async Task?> GetCollectionAsync(string collectionAlias) - { - if (collectionAlias.EndsWith("::property")) - { - return new ResolvedSetup(await PropertyConfigurationCollectionAsync(), true); - } - - return default; - } - - public Task> GetTreeElementsAsync() - => Task.FromResult(Enumerable.Empty()); - - public Type? GetRepositoryType(string collectionAlias) - { - if (collectionAlias.EndsWith("::models")) - { - return _config.ModelRespository; - } - else if (collectionAlias.EndsWith("::property")) - { - return _config.PropertyRepository; - } - - return default; - } - - private async Task PropertyConfigurationCollectionAsync() - { - var entityVariantSetup = new EntityVariantSetup("default", default, typeof(PropertyModel), "modelproperty"); - var collection = new CollectionSetup( - "Database", - "MagentaPink10", - "Properties", - "modelmaker::property", - "modelmaker::property") - { - EntityVariant = entityVariantSetup, - UsageType = UsageType.List, - TreeView = new TreeViewSetup( - EntityVisibilty.Visible, - CollectionRootVisibility.Visible, - false, - false, - new ExpressionMetadata("Name", x => x.Name ?? string.Empty)) - }; - collection.ListEditor = new ListSetup( - 100, - false, - true, - ListType.Table, - EmptyVariantColumnVisibility.Collapse, - new List - { - new PaneSetup( - default, - default, - (m, s) => true, - typeof(PropertyModel), - new List - { - await CreateButtonAsync(collection, DefaultButtonType.Edit, true) - }, - new List - { - CreateExpressionField(DisplayType.Label, EditorType.None, 1, "Property name", new ExpressionMetadata("Name", x => x.Name)) - }, - new List(), - new List()) - }, - new List - { - await CreateButtonAsync(collection, DefaultButtonType.Return, false, "Cancel", "Back"), - await CreateButtonAsync(collection, DefaultButtonType.New, true, "Add property", "Add"), - await CreateButtonAsync(collection, DefaultButtonType.SaveExisting, false, "Save order", "Save") - }); - - collection.NodeEditor = new NodeSetup( - typeof(PropertyModel), - PropertyPanes().ToList(), - new List - { - await CreateButtonAsync(collection, DefaultButtonType.Up, false, "Return", "Back"), - await CreateButtonAsync(collection, DefaultButtonType.SaveNew, true, "Insert"), - await CreateButtonAsync(collection, DefaultButtonType.SaveExisting, true, "Update"), - await CreateButtonAsync(collection, DefaultButtonType.Delete, false, "Delete") - }); - - return collection; - } - - private IEnumerable PropertyPanes() - { - var titleField = CreatePropertyField(EditorType.Checkbox, - 2, - "Use as entity title", - PropertyMetadataHelper.GetFullPropertyMetadata(x => x.IsTitle)); - - titleField.IsVisible = (m, s) - => m is PropertyModel property && !string.IsNullOrEmpty(property.PropertyAlias) - && (_config.GetProperty(property.PropertyAlias)?.UsableAsTitle ?? false); - - // TODO: hide when collection is ListEditor - var listViewField = CreatePropertyField(EditorType.Checkbox, - 3, - "Include in list view", - PropertyMetadataHelper.GetFullPropertyMetadata(x => x.IncludeInListView)); - - listViewField.IsVisible = (m, s) => m is not PropertyModel prop || !prop.IsTitle; - - yield return - new PaneSetup( - default, - default, - (m, s) => true, - typeof(PropertyModel), - new List - { - - }, - new List - { - CreatePropertyField(EditorType.Dropdown, - 0, - "Property type", - PropertyMetadataHelper.GetFullPropertyMetadata(x => x.PropertyAlias), - (m, s) => s == EntityState.IsExisting, - relation: new DataProviderRelationSetup(typeof(PropertyTypeDataCollection), default)), - - CreatePropertyField(EditorType.TextBox, - 1, - "Property name", - PropertyMetadataHelper.GetFullPropertyMetadata(x => x.Name)), - - titleField, - - listViewField, - - CreatePropertyField(EditorType.Checkbox, - 4, - "Required", - PropertyMetadataHelper.GetFullPropertyMetadata(x => x.IsRequired)), - - CreatePropertyField(EditorType.Dropdown, - 5, - "Property editor", - PropertyMetadataHelper.GetFullPropertyMetadata(x => x.EditorAlias), - relation: new DataProviderRelationSetup(typeof(PropertyEditorDataCollection), default)) - }, - new List - { - }, - new List - { - - }); - - yield return - new PaneSetup( - default, - default, - (m, s) => true, - typeof(PropertyModel), - new List - { - - }, - ValidationFields().ToList(), - new List(), - new List()); - } - - private IEnumerable ValidationFields() - { - foreach (var validationType in _config.PropertyDetails) - { - var relationSetup = default(RelationSetup); - - if (validationType.DataCollection != null) - { - relationSetup = new DataProviderRelationSetup(validationType.DataCollection, default); - } - - yield return new CustomPropertyFieldSetup(new FieldConfig - { - Description = validationType.Description, - EditorType = EditorType.Custom, - Index = 1, - Name = validationType.Name, - IsVisible = validationType.Editor == null - ? (m, s) => false - : (m, s) => m is PropertyModel property && - property.Details.FirstOrDefault(x => x.Alias == validationType.Alias) is PropertyDetailModel validation && - !string.IsNullOrEmpty(property.PropertyAlias) && - _config.Properties.First(x => x.Alias == property.PropertyAlias).Details.Any(x => x.Alias == validationType.Alias) && - (validation.Config?.IsApplicable(property) ?? false), - Property = - validationType.ConfigToEditor != null - ? validationType.ConfigToEditor.Nest(x => x.Details.FirstOrDefault(x => x.Alias == validationType.Alias)) - : new PropertyMetadata( - "Config", - typeof(IDetailConfig), - x => x.Details.FirstOrDefault(x => x.Alias == validationType.Alias)?.Config, - (x, v) => - { - if (x.Details.FirstOrDefault(x => x.Alias == validationType.Alias) is PropertyDetailModel validation) - { - validation.Config = v as IDetailConfig; - } - }, - "config"), - }, validationType.Editor ?? typeof(TextBoxEditor)) - { - Relation = relationSetup - }; - } - } - - // COMMON - - private static ExpressionFieldSetup CreateExpressionField( - DisplayType displayType, - EditorType editorType, - int index, - string name, - IExpressionMetadata expression) - => new ExpressionFieldSetup( - new FieldConfig - { - DisplayType = displayType, - EditorType = editorType, - Index = index, - Name = name - }, - expression); - - private static PropertyFieldSetup CreatePropertyField( - EditorType editorType, - int index, - string name, - IFullPropertyMetadata metadata, - Func? isDisabled = default, - Func? isVisible = default, - RelationSetup? relation = default) - { - return new PropertyFieldSetup(new FieldConfig - { - EditorType = editorType, - Index = index, - IsDisabled = isDisabled ?? ((m, s) => false), - IsVisible = isVisible ?? ((m, s) => true), - Name = name, - Property = metadata - }) - { - Relation = relation - }; - } - - private Task CreateButtonAsync( - CollectionSetup collection, - DefaultButtonType type, - bool isPrimary, - string? label = default, - string? icon = default) - { - var button = new ButtonSetup - { - Buttons = Enumerable.Empty(), - - Label = label ?? "Button", - Icon = icon ?? "", - IsPrimary = isPrimary, - - ButtonId = Guid.NewGuid().ToString(), - EntityVariant = collection.EntityVariant, - - DefaultButtonType = type, - - ButtonHandlerType = typeof(DefaultButtonActionHandler) - }; - - return Task.FromResult(button); - - //var response = await _buttonSetupResolver.ResolveSetupAsync(new DefaultButtonConfig - //{ - // ButtonType = type, - // Icon = icon, - // Id = $"{collection.Alias}::{type}", - // IsPrimary = isPrimary, - // Label = label, - - //}, collection); - - //return response.Setup; - } - } -} diff --git a/src/RapidCMS.ModelMaker/Models/Commands/GetAllRequest.cs b/src/RapidCMS.ModelMaker/Models/Commands/GetAllRequest.cs deleted file mode 100644 index 0018921b..00000000 --- a/src/RapidCMS.ModelMaker/Models/Commands/GetAllRequest.cs +++ /dev/null @@ -1,12 +0,0 @@ -using RapidCMS.Core.Abstractions.Data; - -namespace RapidCMS.ModelMaker.Models.Commands -{ - public class GetAllRequest - where TEntity : IEntity - { - public GetAllRequest() - { - } - } -} diff --git a/src/RapidCMS.ModelMaker/Models/Commands/GetByIdRequest.cs b/src/RapidCMS.ModelMaker/Models/Commands/GetByIdRequest.cs deleted file mode 100644 index 6cadfcbf..00000000 --- a/src/RapidCMS.ModelMaker/Models/Commands/GetByIdRequest.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using RapidCMS.Core.Abstractions.Data; - -namespace RapidCMS.ModelMaker.Models.Commands -{ - public class GetByIdRequest - where TEntity : IEntity - { - public GetByIdRequest(string id) - { - Id = id ?? throw new ArgumentNullException(nameof(id)); - } - - public string Id { get; private set; } - } -} diff --git a/src/RapidCMS.ModelMaker/Models/Commands/InsertRequest.cs b/src/RapidCMS.ModelMaker/Models/Commands/InsertRequest.cs deleted file mode 100644 index 5fcd02e3..00000000 --- a/src/RapidCMS.ModelMaker/Models/Commands/InsertRequest.cs +++ /dev/null @@ -1,15 +0,0 @@ -using RapidCMS.Core.Abstractions.Data; - -namespace RapidCMS.ModelMaker.Models.Commands -{ - public class InsertRequest - where TEntity : IEntity - { - public InsertRequest(TEntity entity) - { - Entity = entity; - } - - public TEntity Entity { get; set; } - } -} diff --git a/src/RapidCMS.ModelMaker/Models/Commands/PublishRequest.cs b/src/RapidCMS.ModelMaker/Models/Commands/PublishRequest.cs deleted file mode 100644 index f030bae8..00000000 --- a/src/RapidCMS.ModelMaker/Models/Commands/PublishRequest.cs +++ /dev/null @@ -1,15 +0,0 @@ -using RapidCMS.Core.Abstractions.Data; - -namespace RapidCMS.ModelMaker.Models.Commands -{ - public class PublishRequest - where TEntity : IEntity - { - public PublishRequest(TEntity entity) - { - Entity = entity; - } - - public TEntity Entity { get; set; } - } -} diff --git a/src/RapidCMS.ModelMaker/Models/Commands/RemoveRequest.cs b/src/RapidCMS.ModelMaker/Models/Commands/RemoveRequest.cs deleted file mode 100644 index 99ef2873..00000000 --- a/src/RapidCMS.ModelMaker/Models/Commands/RemoveRequest.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using RapidCMS.Core.Abstractions.Data; - -namespace RapidCMS.ModelMaker.Models.Commands -{ - public class RemoveRequest - where TEntity : IEntity - { - public RemoveRequest(string id, string alias) - { - Id = id ?? throw new ArgumentNullException(nameof(id)); - } - - public string Id { get; private set; } - } -} diff --git a/src/RapidCMS.ModelMaker/Models/Commands/UpdateRequest.cs b/src/RapidCMS.ModelMaker/Models/Commands/UpdateRequest.cs deleted file mode 100644 index c754251c..00000000 --- a/src/RapidCMS.ModelMaker/Models/Commands/UpdateRequest.cs +++ /dev/null @@ -1,15 +0,0 @@ -using RapidCMS.Core.Abstractions.Data; - -namespace RapidCMS.ModelMaker.Models.Commands -{ - public class UpdateRequest - where TEntity : IEntity - { - public UpdateRequest(TEntity entity) - { - Entity = entity; - } - - public TEntity Entity { get; set; } - } -} diff --git a/src/RapidCMS.ModelMaker/Models/Config/PropertyConfig.cs b/src/RapidCMS.ModelMaker/Models/Config/PropertyConfig.cs deleted file mode 100644 index b1b07214..00000000 --- a/src/RapidCMS.ModelMaker/Models/Config/PropertyConfig.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System; -using System.Collections.Generic; -using RapidCMS.ModelMaker.Abstractions.Config; - -namespace RapidCMS.ModelMaker.Models.Config -{ - internal class PropertyConfig : IPropertyConfig - { - public PropertyConfig(string alias, string name, string icon, Type type, IList details, IList editors) - { - Alias = alias ?? throw new ArgumentNullException(nameof(alias)); - Name = name ?? throw new ArgumentNullException(nameof(name)); - Icon = icon ?? throw new ArgumentNullException(nameof(icon)); - Type = type; - Details = details ?? throw new ArgumentNullException(nameof(details)); - Editors = editors ?? throw new ArgumentNullException(nameof(editors)); - } - - public string Alias { get; } - - public string Name { get; } - - public string Icon { get; } - public Type Type { get; } - - public bool UsableAsTitle { get; private set; } = true; - - public IList Details { get; } - - public IList Editors { get; } - - public bool IsRelationToOne { get; private set; } - - public bool IsRelationToMany { get; private set; } - - public IPropertyConfig CanBeUsedAsTitle(bool usedAsTitle) - { - UsableAsTitle = usedAsTitle; - - return this; - } - - public IPropertyConfig RelatesToOneEntity(bool isRelation) - { - IsRelationToOne = isRelation; - - return this; - } - - public IPropertyConfig RelatesToManyEntities(bool isRelation) - { - IsRelationToMany = isRelation; - - return this; - } - } -} diff --git a/src/RapidCMS.ModelMaker/Models/Config/PropertyEditorConfig.cs b/src/RapidCMS.ModelMaker/Models/Config/PropertyEditorConfig.cs deleted file mode 100644 index 456f582c..00000000 --- a/src/RapidCMS.ModelMaker/Models/Config/PropertyEditorConfig.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using RapidCMS.ModelMaker.Abstractions.Config; - -namespace RapidCMS.ModelMaker.Models.Config -{ - internal class PropertyEditorConfig : IPropertyEditorConfig - { - public PropertyEditorConfig(string alias, string name, Type editor) - { - Alias = alias ?? throw new ArgumentNullException(nameof(alias)); - Name = name ?? throw new ArgumentNullException(nameof(name)); - Editor = editor ?? throw new ArgumentNullException(nameof(editor)); - } - - public string Alias { get; } - - public string Name { get; } - - public Type Editor { get; } - } -} diff --git a/src/RapidCMS.ModelMaker/Models/Config/PropertyValidatorConfig.cs b/src/RapidCMS.ModelMaker/Models/Config/PropertyValidatorConfig.cs deleted file mode 100644 index 8a545ffc..00000000 --- a/src/RapidCMS.ModelMaker/Models/Config/PropertyValidatorConfig.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using RapidCMS.Core.Abstractions.Metadata; -using RapidCMS.ModelMaker.Abstractions.Config; - -namespace RapidCMS.ModelMaker.Models.Config -{ - internal class PropertyDetailConfig : IPropertyDetailConfig - { - public PropertyDetailConfig( - string alias, - string name, - string? description, - Type? editor, - Type config, - IFullPropertyMetadata? configToEditor = null, - Type? dataCollection = null) - { - Alias = alias ?? throw new ArgumentNullException(nameof(alias)); - Name = name ?? throw new ArgumentNullException(nameof(name)); - Description = description; - Editor = editor; - Config = config ?? throw new ArgumentNullException(nameof(config)); - - ConfigToEditor = configToEditor; - DataCollection = dataCollection; - } - - public string Alias { get; } - public string Name { get; } - public string? Description { get; } - - public Type? Editor { get; } - - public Type Config { get; } - - public IFullPropertyMetadata? ConfigToEditor { get; } - - public Type? DataCollection { get; } - } -} diff --git a/src/RapidCMS.ModelMaker/Models/Entities/ModelEntity.cs b/src/RapidCMS.ModelMaker/Models/Entities/ModelEntity.cs deleted file mode 100644 index a069cbd9..00000000 --- a/src/RapidCMS.ModelMaker/Models/Entities/ModelEntity.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; -using RapidCMS.Core.Abstractions.Data; -using RapidCMS.Core.Extensions; -using RapidCMS.ModelMaker.Enums; - -namespace RapidCMS.ModelMaker.Models.Entities -{ - public class ModelEntity : IEntity - { - public string? Id { get => Alias; set => Alias = value ?? Name?.ToUrlFriendlyString() ?? "noalias"; } - - public string? ParentId { get; set; } = default!; - - [Required] - [MinLength(1)] - public string Name { get; set; } = default!; - - [Required] - [MinLength(1)] - public string PluralName { get; set; } = default!; - - [JsonConverter(typeof(StringEnumConverter))] - public Color IconColor { get; set; } = Color.Gray40; - - public string? Icon { get; set; } - - [Required] - [MinLength(1)] - public string Alias { get; set; } = default!; - - [Required] - [JsonConverter(typeof(StringEnumConverter))] - public OutputItem Output { get; set; } = OutputItem.Collection | OutputItem.Context | OutputItem.Entity | OutputItem.Repository | OutputItem.Validation; - - public List Properties { get; set; } = new List(); - } -} diff --git a/src/RapidCMS.ModelMaker/Models/Entities/PropertyDetailModel.cs b/src/RapidCMS.ModelMaker/Models/Entities/PropertyDetailModel.cs deleted file mode 100644 index 24074e48..00000000 --- a/src/RapidCMS.ModelMaker/Models/Entities/PropertyDetailModel.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.ComponentModel.DataAnnotations; -using RapidCMS.Core.Abstractions.Data; -using RapidCMS.Core.Attributes; -using RapidCMS.ModelMaker.Abstractions.Detail; - -namespace RapidCMS.ModelMaker.Models.Entities -{ - public class PropertyDetailModel : IEntity - { - public string? Id { get; set; } - - [Required] - [MinLength(1)] - public string Alias { get; set; } = default!; - - [Required] - [ValidateObject] - public IDetailConfig? Config { get; set; } - } - - public class PropertyDetailModel : PropertyDetailModel, IPropertyDetailModel - where TValidatorConfig : class, IDetailConfig, new() - { - TValidatorConfig IPropertyDetailModel.Config => Config as TValidatorConfig ?? new TValidatorConfig(); - } -} diff --git a/src/RapidCMS.ModelMaker/Models/Entities/PropertyModel.cs b/src/RapidCMS.ModelMaker/Models/Entities/PropertyModel.cs deleted file mode 100644 index be380edd..00000000 --- a/src/RapidCMS.ModelMaker/Models/Entities/PropertyModel.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using RapidCMS.Core.Abstractions.Data; -using RapidCMS.Core.Attributes; - -namespace RapidCMS.ModelMaker.Models.Entities -{ - public class PropertyModel : IEntity - { - public string? Id { get; set; } - - [Required] - [MinLength(1)] - public string Name { get; set; } = default!; - - public bool IsTitle { get; set; } - - public bool IncludeInListView { get; set; } - - public bool IsRequired { get; set; } - - [Required] - public string? PropertyAlias { get; set; } - - [Required] - public string? EditorAlias { get; set; } - - [Required] - [ValidateEnumerable] - public List Details { get; set; } = new List(); - - public string? Type { get; set; } - - public bool IsRelationToOne { get; set; } - - public bool IsRelationToMany { get; set; } - - public string? EditorType { get; set; } - } -} diff --git a/src/RapidCMS.ModelMaker/Models/ModelMakerConfig.cs b/src/RapidCMS.ModelMaker/Models/ModelMakerConfig.cs deleted file mode 100644 index 439d7c3b..00000000 --- a/src/RapidCMS.ModelMaker/Models/ModelMakerConfig.cs +++ /dev/null @@ -1,188 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; -using RapidCMS.Core.Abstractions.Data; -using RapidCMS.Core.Abstractions.Metadata; -using RapidCMS.Core.Enums; -using RapidCMS.Core.Helpers; -using RapidCMS.ModelMaker.Abstractions.Config; -using RapidCMS.ModelMaker.Abstractions.Detail; -using RapidCMS.ModelMaker.Models.Config; -using RapidCMS.ModelMaker.Repositories; -using RapidCMS.ModelMaker.Validation.Config; -using RapidCMS.UI.Components.Editors; -using RapidCMS.UI.Extensions; - -namespace RapidCMS.ModelMaker.Models -{ - internal class ModelMakerConfig : IModelMakerConfig - { - private readonly List _editors = new List(); - private readonly List _details = new List(); - private readonly List _properties = new List(); - - public ModelMakerConfig() - { - ModelFolder = "./RapidModels/"; - } - - public IEnumerable Editors => _editors; - - public IEnumerable PropertyDetails => _details; - - public IEnumerable Properties => _properties; - - public IPropertyConfig AddProperty(string alias, string name, string icon, IEnumerable editorAliases, IEnumerable detailAliases) - { - var property = new PropertyConfig( - alias, - name, - icon, - typeof(TValue), - detailAliases.Select(x => _details.FirstOrDefault(v => v.Alias == x) ?? throw new InvalidOperationException($"Cannot find detail with alias {x}")).ToList(), - editorAliases.Select(x => _editors.FirstOrDefault(e => e.Alias == x) ?? throw new InvalidOperationException($"Cannot find editor with alias {x}")).ToList()); - - _properties.Add(property); - - return property; - } - - public IPropertyEditorConfig AddPropertyEditor(string alias, string name, EditorType editorType) - { - var editor = new PropertyEditorConfig(alias, name, GetEditorByEditorType(editorType)); - _editors.Add(editor); - return editor; - } - - public IPropertyEditorConfig AddPropertyEditor(string alias, string name) where TCustomEditor : BasePropertyEditor - { - var editor = new PropertyEditorConfig(alias, name, typeof(TCustomEditor)); - _editors.Add(editor); - return editor; - } - - public IPropertyDetailConfig AddPropertyDetail( - string alias, - string name, - string? description, - EditorType editorType, - Expression, TValueForEditor>> configEditor) - where TDetailConfig : class, IDetailConfig - { - var validator = new PropertyDetailConfig( - alias, - name, - description, - GetEditorByEditorType(editorType), - typeof(TDetailConfig), - PropertyMetadataHelper.GetPropertyMetadata(configEditor) as IFullPropertyMetadata); - - _details.Add(validator); - - return validator; - } - - public IPropertyDetailConfig AddPropertyDetail(string alias, string name, string? description) - where TDetailConfig : IDetailConfig - where TCustomEditor : BasePropertyEditor - { - var validator = new PropertyDetailConfig( - alias, - name, - description, - typeof(TCustomEditor), - typeof(TDetailConfig)); - - _details.Add(validator); - - return validator; - } - - public IPropertyDetailConfig AddPropertyDetail( - string alias, - string name, - string? description, - EditorType editorType, - Expression, TValueForEditor>> configEditor) - where TDetailConfig : class, IDetailConfig - where TDataCollection : IDataCollection - { - var validator = new PropertyDetailConfig( - alias, - name, - description, - GetEditorByEditorType(editorType), - typeof(TDetailConfig), - PropertyMetadataHelper.GetPropertyMetadata(configEditor) as IFullPropertyMetadata, - typeof(TDataCollection)); - - _details.Add(validator); - - return validator; - } - - public IPropertyDetailConfig AddPropertyDetail(string alias, string name, string? description) - where TDetailConfig : IDetailConfig - where TCustomEditor : BasePropertyEditor - where TDataCollection : IDataCollection - { - var validator = new PropertyDetailConfig( - alias, - name, - description, - typeof(TCustomEditor), - typeof(TDetailConfig), - dataCollection: typeof(TDataCollection)); - - _details.Add(validator); - - return validator; - } - - public IPropertyDetailConfig AddPropertyDetail(string alias, string name, string? description) - where TDataCollection : IDataCollection - { - var validator = new PropertyDetailConfig( - alias, - name, - description, - default, - typeof(DataCollectionConfig), - dataCollection: typeof(TDataCollection)); - - _details.Add(validator); - - return validator; - } - - public IPropertyConfig? GetProperty(string alias) - => _properties.FirstOrDefault(x => x.Alias == alias); - - public IPropertyEditorConfig? GetPropertyEditor(EditorType editorType) - { - var editor = GetEditorByEditorType(editorType); - - return _editors.FirstOrDefault(x => x.Editor == editor); - } - - public IPropertyEditorConfig? GetPropertyEditor() - => _editors.FirstOrDefault(x => x.Editor == typeof(TCustomEditor)); - public IPropertyEditorConfig? GetPropertyEditor(string alias) - => _editors.FirstOrDefault(x => x.Alias == alias); - - private static Type GetEditorByEditorType(EditorType editorType) - => editorType.GetEditor() ?? throw new InvalidOperationException($"EditorType.{editorType} is not a valid option."); - - public string ModelFolder { get; private set; } - - public void SetModelFolder(string folder) - { - ModelFolder = folder; - } - - Type IModelMakerConfig.ModelRespository { get; set; } = typeof(ModelRepository); - - Type IModelMakerConfig.PropertyRepository { get; set; } = typeof(PropertyRepository); - } -} diff --git a/src/RapidCMS.ModelMaker/Models/Responses/ConfirmResponse.cs b/src/RapidCMS.ModelMaker/Models/Responses/ConfirmResponse.cs deleted file mode 100644 index f4b9a8e9..00000000 --- a/src/RapidCMS.ModelMaker/Models/Responses/ConfirmResponse.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace RapidCMS.ModelMaker.Models.Responses -{ - public class ConfirmResponse - { - public bool Success { get; set; } - } -} diff --git a/src/RapidCMS.ModelMaker/Models/Responses/EntitiesResponse.cs b/src/RapidCMS.ModelMaker/Models/Responses/EntitiesResponse.cs deleted file mode 100644 index 2d9c5d51..00000000 --- a/src/RapidCMS.ModelMaker/Models/Responses/EntitiesResponse.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Collections.Generic; -using System.Linq; - -namespace RapidCMS.ModelMaker.Models.Responses -{ - public class EntitiesResponse - { - public IEnumerable Entities { get; set; } = Enumerable.Empty(); - } -} diff --git a/src/RapidCMS.ModelMaker/Models/Responses/EntityResponse.cs b/src/RapidCMS.ModelMaker/Models/Responses/EntityResponse.cs deleted file mode 100644 index c6477772..00000000 --- a/src/RapidCMS.ModelMaker/Models/Responses/EntityResponse.cs +++ /dev/null @@ -1,10 +0,0 @@ -using RapidCMS.Core.Abstractions.Data; - -namespace RapidCMS.ModelMaker.Models.Responses -{ - public class EntityResponse - where TEntity : IEntity - { - public TEntity? Entity { get; set; } - } -} diff --git a/src/RapidCMS.ModelMaker/PropertyDetails/AbstractValidatorAdapter.cs b/src/RapidCMS.ModelMaker/PropertyDetails/AbstractValidatorAdapter.cs deleted file mode 100644 index f11dbbe6..00000000 --- a/src/RapidCMS.ModelMaker/PropertyDetails/AbstractValidatorAdapter.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using FluentValidation; -using RapidCMS.Core.Abstractions.Data; -using RapidCMS.Core.Abstractions.Validators; - -namespace RapidCMS.ModelMaker.Validation -{ - /// - /// This adapter adapts FluentValidation's AbstractValidator to TEntity part of IEntityValidator - /// - /// Since the context is saved as property these validators must be added as transient services. - /// - /// - public abstract class AbstractValidatorAdapter : AbstractValidator, IEntityValidator - where TEntity : IEntity - { - protected IValidatorContext _context = default!; - - IEnumerable IEntityValidator.Validate(IValidatorContext context) - { - _context = context; - - var result = Validate((TEntity)context.Entity); - - if (result.IsValid) - { - return Enumerable.Empty(); - } - else - { - return result.Errors.Select(error => new ValidationResult(error.ErrorMessage, new[] { error.PropertyName })); - } - } - } -} diff --git a/src/RapidCMS.ModelMaker/PropertyDetails/Config/BooleanLabelDetailConfig.cs b/src/RapidCMS.ModelMaker/PropertyDetails/Config/BooleanLabelDetailConfig.cs deleted file mode 100644 index 30061672..00000000 --- a/src/RapidCMS.ModelMaker/PropertyDetails/Config/BooleanLabelDetailConfig.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System.ComponentModel.DataAnnotations; -using RapidCMS.Core.Abstractions.Data; -using RapidCMS.Core.Attributes; -using RapidCMS.Core.Extensions; -using RapidCMS.ModelMaker.Abstractions.Detail; -using RapidCMS.ModelMaker.DataCollections; -using RapidCMS.ModelMaker.Models.Entities; -using RapidCMS.UI.Components.Editors; - -namespace RapidCMS.ModelMaker.Validation.Config -{ - public class BooleanLabelDetailConfig : IDetailConfig - { - [Required] - [ValidateObjectAsProperty] - public LabelsConfig Labels { get; set; } = new LabelsConfig(); - - public bool IsEnabled => true; - public bool AlwaysIncluded => false; - - public bool IsApplicable(PropertyModel model) - => model.EditorAlias.In(Constants.Editors.Dropdown, Constants.Editors.Select); - - public string? RelatedCollectionAlias => default; - - public string? DataCollectionType => typeof(BooleanLabelDataCollection).FullName; - - public string? ValidationMethodName => default; - - public class LabelsConfig: IEntity - { - [Required] - [MinLength(1)] - [Field(Name = "True label", EditorType = typeof(TextBoxEditor))] - public string? TrueLabel { get; set; } - - [Required] - [MinLength(1)] - [Field(Name = "False label", EditorType = typeof(TextBoxEditor))] - public string? FalseLabel { get; set; } - - string? IEntity.Id { get; set; } - } - } -} diff --git a/src/RapidCMS.ModelMaker/PropertyDetails/Config/CorrespondingPropertyDetailConfig.cs b/src/RapidCMS.ModelMaker/PropertyDetails/Config/CorrespondingPropertyDetailConfig.cs deleted file mode 100644 index c87755a1..00000000 --- a/src/RapidCMS.ModelMaker/PropertyDetails/Config/CorrespondingPropertyDetailConfig.cs +++ /dev/null @@ -1,23 +0,0 @@ -using RapidCMS.Core.Extensions; -using RapidCMS.ModelMaker.Abstractions.Detail; -using RapidCMS.ModelMaker.Models.Entities; - -namespace RapidCMS.ModelMaker.Validation.Config -{ - public class CorrespondingPropertyDetailConfig : IDetailConfig - { - public string? RelatedPropertyName { get; set; } - - public bool IsEnabled => !string.IsNullOrWhiteSpace(RelatedPropertyName); - public bool AlwaysIncluded => false; - - public bool IsApplicable(PropertyModel model) - => model.EditorAlias.In(Constants.Editors.EntityPicker, Constants.Editors.EntitiesPicker); - - public string? RelatedCollectionAlias => default; - - public string? ValidationMethodName => default; - - public string? DataCollectionType => default; - } -} diff --git a/src/RapidCMS.ModelMaker/PropertyDetails/Config/DataCollectionConfig.cs b/src/RapidCMS.ModelMaker/PropertyDetails/Config/DataCollectionConfig.cs deleted file mode 100644 index e0778f02..00000000 --- a/src/RapidCMS.ModelMaker/PropertyDetails/Config/DataCollectionConfig.cs +++ /dev/null @@ -1,20 +0,0 @@ -using RapidCMS.ModelMaker.Abstractions.Detail; -using RapidCMS.ModelMaker.Models.Entities; - -namespace RapidCMS.ModelMaker.Validation.Config -{ - public class DataCollectionConfig : IDetailConfig - { - public bool IsEnabled => true; - - public bool AlwaysIncluded => true; - - public bool IsApplicable(PropertyModel model) => false; - - public string? RelatedCollectionAlias => default; - - public string? ValidationMethodName => default; - - public string? DataCollectionType => typeof(TDataCollection).FullName; - } -} diff --git a/src/RapidCMS.ModelMaker/PropertyDetails/Config/LimitedOptionsDetailConfig.cs b/src/RapidCMS.ModelMaker/PropertyDetails/Config/LimitedOptionsDetailConfig.cs deleted file mode 100644 index 1ef7d261..00000000 --- a/src/RapidCMS.ModelMaker/PropertyDetails/Config/LimitedOptionsDetailConfig.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using RapidCMS.Core.Extensions; -using RapidCMS.ModelMaker.Abstractions.Detail; -using RapidCMS.ModelMaker.Models.Entities; - -namespace RapidCMS.ModelMaker.Validation.Config -{ - public class LimitedOptionsDetailConfig : IDetailConfig - { - [Required] - [MinLength(1)] - public List Options { get; set; } = new List(); - - public bool IsEnabled => Options?.Any() == true; - public bool AlwaysIncluded => false; - - public bool IsApplicable(PropertyModel model) - => model.EditorAlias.In(Constants.Editors.Dropdown); - - public string? RelatedCollectionAlias => default; // TODO: wut: $"[RegularExpression(\"^[{string.Join("|", Options)}]\")]$"; - - public string? ValidationMethodName => default; - - public string? DataCollectionType => default; // TODO - } -} diff --git a/src/RapidCMS.ModelMaker/PropertyDetails/Config/LinkedEntitiesDetailConfig.cs b/src/RapidCMS.ModelMaker/PropertyDetails/Config/LinkedEntitiesDetailConfig.cs deleted file mode 100644 index a9d4d489..00000000 --- a/src/RapidCMS.ModelMaker/PropertyDetails/Config/LinkedEntitiesDetailConfig.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.ComponentModel.DataAnnotations; -using RapidCMS.Core.Extensions; -using RapidCMS.ModelMaker.Abstractions.Detail; -using RapidCMS.ModelMaker.Models.Entities; - -namespace RapidCMS.ModelMaker.Validation.Config -{ - public class LinkedEntitiesDetailConfig : IDetailConfig - { - [Required] - public string LinkedEntitiesCollectionAlias { get; set; } = string.Empty; - - public bool IsEnabled => !string.IsNullOrWhiteSpace(LinkedEntitiesCollectionAlias); - public bool AlwaysIncluded => false; - - public bool IsApplicable(PropertyModel model) - => model.EditorAlias.In(Constants.Editors.EntityPicker, Constants.Editors.EntitiesPicker); - - public string? RelatedCollectionAlias => IsEnabled ? LinkedEntitiesCollectionAlias : default; - - public string? ValidationMethodName => default; - - public string? DataCollectionType => default; - } -} diff --git a/src/RapidCMS.ModelMaker/PropertyDetails/Config/LinkedEntityDetailConfig.cs b/src/RapidCMS.ModelMaker/PropertyDetails/Config/LinkedEntityDetailConfig.cs deleted file mode 100644 index cdb67311..00000000 --- a/src/RapidCMS.ModelMaker/PropertyDetails/Config/LinkedEntityDetailConfig.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.ComponentModel.DataAnnotations; -using RapidCMS.Core.Extensions; -using RapidCMS.ModelMaker.Abstractions.Detail; -using RapidCMS.ModelMaker.Models.Entities; - -namespace RapidCMS.ModelMaker.Validation.Config -{ - public class LinkedEntityDetailConfig : IDetailConfig - { - [Required] - public string LinkedEntityCollectionAlias { get; set; } = string.Empty; - - public bool IsEnabled => !string.IsNullOrWhiteSpace(LinkedEntityCollectionAlias); - public bool AlwaysIncluded => false; - - public bool IsApplicable(PropertyModel model) - => model.EditorAlias.In(Constants.Editors.EntityPicker, Constants.Editors.EntitiesPicker); - - public string? RelatedCollectionAlias => IsEnabled ? LinkedEntityCollectionAlias : default; - - public string? ValidationMethodName => default; - - public string? DataCollectionType => default; - } -} diff --git a/src/RapidCMS.ModelMaker/PropertyDetails/Config/MaxLengthDetailConfig.cs b/src/RapidCMS.ModelMaker/PropertyDetails/Config/MaxLengthDetailConfig.cs deleted file mode 100644 index bbfa1cf9..00000000 --- a/src/RapidCMS.ModelMaker/PropertyDetails/Config/MaxLengthDetailConfig.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.ComponentModel.DataAnnotations; -using RapidCMS.Core.Extensions; -using RapidCMS.ModelMaker.Abstractions.Detail; -using RapidCMS.ModelMaker.Models.Entities; - -namespace RapidCMS.ModelMaker.Validation.Config -{ - public class MaxLengthDetailConfig : IDetailConfig - { - [Range(1, int.MaxValue)] - public int? MaxLength { get; set; } - - public bool IsEnabled => MaxLength.HasValue; - public bool AlwaysIncluded => false; - - public bool IsApplicable(PropertyModel model) - => model.EditorAlias.In(Constants.Editors.TextArea, Constants.Editors.TextBox); - - public string? RelatedCollectionAlias => default; - - public string? ValidationMethodName => "MaximumLength"; - - public string? DataCollectionType => default; - } -} diff --git a/src/RapidCMS.ModelMaker/PropertyDetails/Config/MinLengthDetailConfig.cs b/src/RapidCMS.ModelMaker/PropertyDetails/Config/MinLengthDetailConfig.cs deleted file mode 100644 index 65a47352..00000000 --- a/src/RapidCMS.ModelMaker/PropertyDetails/Config/MinLengthDetailConfig.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.ComponentModel.DataAnnotations; -using RapidCMS.Core.Extensions; -using RapidCMS.ModelMaker.Abstractions.Detail; -using RapidCMS.ModelMaker.Models.Entities; - -namespace RapidCMS.ModelMaker.Validation.Config -{ - public class MinLengthDetailConfig : IDetailConfig - { - [Range(1, int.MaxValue)] - public int? MinLength { get; set; } - - public bool IsEnabled => MinLength.HasValue; - public bool AlwaysIncluded => false; - - public bool IsApplicable(PropertyModel model) - => model.EditorAlias.In(Constants.Editors.TextArea, Constants.Editors.TextBox); - - public string? RelatedCollectionAlias => default; - - public string? ValidationMethodName => "MinimumLength"; - - public string? DataCollectionType => default; - } -} diff --git a/src/RapidCMS.ModelMaker/PropertyDetails/Config/NoConfig.cs b/src/RapidCMS.ModelMaker/PropertyDetails/Config/NoConfig.cs deleted file mode 100644 index e2273a07..00000000 --- a/src/RapidCMS.ModelMaker/PropertyDetails/Config/NoConfig.cs +++ /dev/null @@ -1,20 +0,0 @@ -using RapidCMS.ModelMaker.Abstractions.Detail; -using RapidCMS.ModelMaker.Models.Entities; - -namespace RapidCMS.ModelMaker.Validation.Config -{ - public class NoConfig : IDetailConfig - { - public bool IsEnabled => true; - - public bool AlwaysIncluded => true; - - public bool IsApplicable(PropertyModel model) => false; - - public string? RelatedCollectionAlias => default; - - public string? ValidationMethodName => default; - - public string? DataCollectionType => default; - } -} diff --git a/src/RapidCMS.ModelMaker/RapidCMS.ModelMaker.csproj b/src/RapidCMS.ModelMaker/RapidCMS.ModelMaker.csproj deleted file mode 100644 index 9f74b6d5..00000000 --- a/src/RapidCMS.ModelMaker/RapidCMS.ModelMaker.csproj +++ /dev/null @@ -1,55 +0,0 @@ - - - - net6.0 - 10.0 - enable - Thomas Bleijendaal - Thomas Bleijendaal - - Plugin for creating a dynamic model CMS inside RapidCMS. - - RapidCMS is a Blazor framework which allows you to build a responsive and flexible CMS purely from code. - - 2021 - true - https://github.com/ThomasBleijendaal/RapidCMS - Github - Blazor, CMS, Model Maker - LICENSE.md - true - true - snupkg - https://github.com/ThomasBleijendaal/RapidCMS - true - $(PackageVersion) - - - - 1701;1702;1591 - - - - 1701;1702;1591 - - - - - - - - - - - - - - - - - True - - - - - diff --git a/src/RapidCMS.ModelMaker/Repositories/ModelRepository.cs b/src/RapidCMS.ModelMaker/Repositories/ModelRepository.cs deleted file mode 100644 index fe411b6f..00000000 --- a/src/RapidCMS.ModelMaker/Repositories/ModelRepository.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using RapidCMS.Core.Abstractions.Data; -using RapidCMS.Core.Abstractions.Forms; -using RapidCMS.Core.Abstractions.Repositories; -using RapidCMS.Core.Extensions; -using RapidCMS.ModelMaker.Abstractions.CommandHandlers; -using RapidCMS.ModelMaker.Models.Commands; -using RapidCMS.ModelMaker.Models.Entities; -using RapidCMS.ModelMaker.Models.Responses; - -namespace RapidCMS.ModelMaker.Repositories -{ - internal class ModelRepository : IRepository - { - private readonly ICommandHandler, ConfirmResponse> _removeCommandHandler; - private readonly ICommandHandler, EntitiesResponse> _getAllEntitiesCommandHandler; - private readonly ICommandHandler, EntityResponse> _getEntityCommandHandler; - private readonly ICommandHandler, EntityResponse> _insertEntityCommandHandler; - private readonly ICommandHandler, ConfirmResponse> _publishEntityCommandHandler; - - public ModelRepository( - ICommandHandler, ConfirmResponse> removeCommandHandler, - ICommandHandler, EntitiesResponse> getAllEntitiesCommandHandler, - ICommandHandler, EntityResponse> getEntityCommandHandler, - ICommandHandler, EntityResponse> insertEntityCommandHandler, - ICommandHandler, ConfirmResponse> publishEntityCommandHandler) - { - _removeCommandHandler = removeCommandHandler; - _getAllEntitiesCommandHandler = getAllEntitiesCommandHandler; - _getEntityCommandHandler = getEntityCommandHandler; - _insertEntityCommandHandler = insertEntityCommandHandler; - _publishEntityCommandHandler = publishEntityCommandHandler; - } - - public Task AddAsync(IRelatedViewContext viewContext, string id) => throw new NotSupportedException(); - - public async Task DeleteAsync(string id, IViewContext viewContext) => await _removeCommandHandler.HandleAsync(new RemoveRequest(id, id)); - - public async Task> GetAllAsync(IViewContext viewContext, IView view) - { - var response = await _getAllEntitiesCommandHandler.HandleAsync(new GetAllRequest()); - - return response.Entities; - } - - public Task> GetAllNonRelatedAsync(IRelatedViewContext viewContext, IView view) => throw new NotSupportedException(); - - public Task> GetAllRelatedAsync(IRelatedViewContext viewContext, IView view) => throw new NotSupportedException(); - - public async Task GetByIdAsync(string id, IViewContext viewContext) - { - var response = await _getEntityCommandHandler.HandleAsync(new GetByIdRequest(id)); - - return response.Entity; - } - - public async Task InsertAsync(IEditContext editContext) - { - if (editContext is IEditContext typedEditContext) - { - var entity = typedEditContext.Entity; - entity.Alias = (entity.PluralName ?? entity.Name).ToUrlFriendlyString(); // TODO: ensure uniqueness - - var response = await _insertEntityCommandHandler.HandleAsync(new InsertRequest(entity)); - - return response.Entity; - } - - return default; - } - - public Task NewAsync(IViewContext viewContext, Type? variantType) => Task.FromResult(new ModelEntity()); - - public Task RemoveAsync(IRelatedViewContext viewContext, string id) => throw new NotSupportedException(); - - public Task ReorderAsync(string? beforeId, string id, IViewContext viewContext) => throw new NotSupportedException(); - - public async Task UpdateAsync(IEditContext editContext) - { - if (editContext is IEditContext typedEditContext) - { - await _publishEntityCommandHandler.HandleAsync(new PublishRequest(typedEditContext.Entity)); - } - } - } -} diff --git a/src/RapidCMS.ModelMaker/Repositories/PropertyRepository.cs b/src/RapidCMS.ModelMaker/Repositories/PropertyRepository.cs deleted file mode 100644 index d8983238..00000000 --- a/src/RapidCMS.ModelMaker/Repositories/PropertyRepository.cs +++ /dev/null @@ -1,290 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using RapidCMS.Core.Abstractions.Data; -using RapidCMS.Core.Abstractions.Forms; -using RapidCMS.Core.Abstractions.Mediators; -using RapidCMS.Core.Abstractions.Repositories; -using RapidCMS.Core.Abstractions.Resolvers; -using RapidCMS.Core.Enums; -using RapidCMS.Core.Extensions; -using RapidCMS.Core.Models.EventArgs.Mediators; -using RapidCMS.Core.Models.Setup; -using RapidCMS.ModelMaker.Abstractions.CommandHandlers; -using RapidCMS.ModelMaker.Abstractions.Config; -using RapidCMS.ModelMaker.Abstractions.Detail; -using RapidCMS.ModelMaker.EqualityComparers; -using RapidCMS.ModelMaker.Models.Commands; -using RapidCMS.ModelMaker.Models.Entities; -using RapidCMS.ModelMaker.Models.Responses; - -namespace RapidCMS.ModelMaker.Repositories -{ - internal class PropertyRepository : IRepository - { - private readonly IModelMakerConfig _config; - private readonly ICommandHandler, ConfirmResponse> _updateEntityCommandHandler; - private readonly ISetupResolver _collectionSetupResolver; - private readonly IMediator _mediator; - - public PropertyRepository( - IModelMakerConfig config, - ICommandHandler, ConfirmResponse> updateEntityCommandHandler, - ISetupResolver collectionSetupResolver, - IMediator mediator) - { - _config = config; - _updateEntityCommandHandler = updateEntityCommandHandler; - _collectionSetupResolver = collectionSetupResolver; - _mediator = mediator; - } - - public Task AddAsync(IRelatedViewContext viewContext, string id) => throw new NotSupportedException(); - - public async Task DeleteAsync(string id, IViewContext viewContext) - { - if (viewContext.Parent?.Entity is ModelEntity model) - { - model.Properties.RemoveAll(x => x.Id == id); - - await _updateEntityCommandHandler.HandleAsync(new UpdateRequest(model)); - } - } - - public Task> GetAllAsync(IViewContext viewContext, IView view) - { - if (viewContext.Parent?.Entity is ModelEntity model) - { - return Task.FromResult>(model.Properties); - } - - throw new InvalidOperationException(); - } - - public Task> GetAllNonRelatedAsync(IRelatedViewContext viewContext, IView view) => throw new NotSupportedException(); - - public Task> GetAllRelatedAsync(IRelatedViewContext viewContext, IView view) => throw new NotSupportedException(); - - public Task GetByIdAsync(string id, IViewContext viewContext) - { - if (viewContext.Parent?.Entity is ModelEntity model && - model.Properties.FirstOrDefault(x => x.Id == id) is PropertyModel property) - { - var allPropertyValidations = _config.Properties - .Single(prop => prop.Alias == property.PropertyAlias) - .Details - .Select(validation => - { - var config = Activator.CreateInstance(validation.Config) as IDetailConfig; - - var validationModel = Activator.CreateInstance(typeof(PropertyDetailModel<>).MakeGenericType(validation.Config)) as PropertyDetailModel - ?? throw new InvalidOperationException("Could not create correct PropertyValidationModel."); - - validationModel.Alias = validation.Alias; - validationModel.Config = config; - validationModel.Id = Guid.NewGuid().ToString(); - - return validationModel; - }) - .ToList(); - - property.Details = property.Details.Union(allPropertyValidations, new PropertyValidationModelEqualityComparer()).ToList(); - - return Task.FromResult(property); - } - - return Task.FromResult(default); - } - - public async Task InsertAsync(IEditContext editContext) - { - if (editContext is IEditContext typedEditContext && - typedEditContext.Parent?.Entity is ModelEntity model) - { - var newProperty = typedEditContext.Entity; - newProperty.Id = Guid.NewGuid().ToString(); - model.Properties.Add(newProperty); - - await SavePropertyConfigsAsync(model, typedEditContext.Entity); - - if (newProperty.IsTitle) - { - SetPropertyAsOnlyTitle(model, newProperty); - } - - ValidateProperty(typedEditContext, newProperty, model); - - await typedEditContext.EnforceValidEntityAsync(); - - await _updateEntityCommandHandler.HandleAsync(new UpdateRequest(model)); - - _mediator.NotifyEvent(this, new RepositoryEventArgs(_config.ModelRespository, default, model.Id, CrudType.Insert)); - - return newProperty; - } - - return default; - } - - public Task NewAsync(IViewContext viewContext, Type? variantType) - { - return Task.FromResult(new PropertyModel - { - Details = _config.Properties - .SelectMany(validation => validation.Details) - .GroupBy(validation => validation.Alias) - .Select(validation => validation.First()) - .Select(validation => - { - var config = Activator.CreateInstance(validation.Config) as IDetailConfig; - - var validationModel = Activator.CreateInstance(typeof(PropertyDetailModel<>).MakeGenericType(validation.Config)) as PropertyDetailModel - ?? throw new InvalidOperationException("Could not create correct PropertyValidationModel."); - - validationModel.Alias = validation.Alias; - validationModel.Config = config; - validationModel.Id = Guid.NewGuid().ToString(); - - return validationModel; - }) - .ToList() - }); - } - - public Task RemoveAsync(IRelatedViewContext viewContext, string id) => throw new NotSupportedException(); - - public async Task ReorderAsync(string? beforeId, string id, IViewContext viewContext) - { - if (viewContext.Parent?.Entity is ModelEntity model) - { - var property = model.Properties.FirstOrDefault(x => x.Id == id); - if (property == null) - { - return; - } - - model.Properties.Remove(property); - - var targetIndex = model.Properties.FindIndex(x => x.Id == beforeId); - if (targetIndex == -1) - { - model.Properties.Add(property); - } - else - { - model.Properties.Insert(targetIndex, property); - } - - await _updateEntityCommandHandler.HandleAsync(new UpdateRequest(model)); - - // TODO: this does not update its parent entity so when updating that one, the old order is restored - // if a mediator update is issued then multiple reorders get messed up as the refresh takes place after first update, while others should also be updated.. - } - } - - public async Task UpdateAsync(IEditContext editContext) - { - if (editContext is IEditContext typedEditContext && - typedEditContext.Parent?.Entity is ModelEntity model) - { - var index = model.Properties.FindIndex(x => x.Id == typedEditContext.Entity.Id); - - model.Properties[index] = typedEditContext.Entity; - - await SavePropertyConfigsAsync(model, typedEditContext.Entity); - if (typedEditContext.Entity.IsTitle) - { - SetPropertyAsOnlyTitle(model, typedEditContext.Entity); - } - - ValidateProperty(typedEditContext, typedEditContext.Entity, model); - - await typedEditContext .EnforceValidEntityAsync(); - - await _updateEntityCommandHandler.HandleAsync(new UpdateRequest(model)); - - _mediator.NotifyEvent(this, new RepositoryEventArgs(_config.ModelRespository, default, model.Id, CrudType.Update)); - } - } - - private static void ValidateProperty(IEditContext editContext, PropertyModel property, ModelEntity model) - { - if (model.Properties.Count(x => x.Name == property.Name) > 1) - { - editContext.AddValidationError("Alias", "Alias already used."); - } - } - - private async Task SavePropertyConfigsAsync(ModelEntity model, PropertyModel property) - { - var propertyConfig = _config.Properties.FirstOrDefault(x => x.Alias == property.PropertyAlias); - if (propertyConfig != null) - { - if (!propertyConfig.UsableAsTitle) - { - property.IsTitle = false; - property.IncludeInListView = false; - } - - if (property.IsTitle) - { - property.IncludeInListView = false; - } - - var editorConfig = _config.Editors.FirstOrDefault(x => x.Alias == property.EditorAlias); - - property.Type = propertyConfig.Type.FullName; - property.IsRelationToOne = propertyConfig.IsRelationToOne; - property.IsRelationToMany = propertyConfig.IsRelationToMany; - property.EditorType = editorConfig?.Editor.FullName; - - var validations = _config.PropertyDetails.Where(x => propertyConfig.Details.Any(v => v.Alias == x.Alias)); - - var newValidations = new List(); - - foreach (var validation in validations) - { - var config = property.Details.FirstOrDefault(x => x.Alias == validation.Alias)?.Config - ?? Activator.CreateInstance(validation.Config) as IDetailConfig; - - if (config?.IsApplicable(property) == true || config?.AlwaysIncluded == true) - { - var validationModel = Activator.CreateInstance(typeof(PropertyDetailModel<>).MakeGenericType(validation.Config)) as PropertyDetailModel - ?? throw new InvalidOperationException("Could not create correct PropertyValidationModel."); - - validationModel.Alias = validation.Alias; - validationModel.Config = config; - validationModel.Id = Guid.NewGuid().ToString(); - - newValidations.Add(validationModel); - } - } - - try - { - var relatedCollectionAlias = newValidations.Select(x => x.Config?.RelatedCollectionAlias).OfType().SingleOrDefault(); - - if (!string.IsNullOrWhiteSpace(relatedCollectionAlias)) - { - var relatedCollectionEntityVariant = (await _collectionSetupResolver.ResolveSetupAsync(relatedCollectionAlias)).EntityVariant; - - property.Type = relatedCollectionEntityVariant.Type.FullName; - } - } - catch (InvalidOperationException ex) - { - throw new InvalidOperationException("Cannot have 2 validation configs with RelatedCollectionAlias", ex); - } - - - property.Details = newValidations; - } - } - - private static void SetPropertyAsOnlyTitle(ModelEntity model, PropertyModel property) - { - model.Properties.Where(x => x.Name != property.Name).ForEach(x => x.IsTitle = false); - } - } -} diff --git a/src/RapidCMS.ModelMaker/wwwroot/css/modelmaker.css b/src/RapidCMS.ModelMaker/wwwroot/css/modelmaker.css deleted file mode 100644 index 5f282702..00000000 --- a/src/RapidCMS.ModelMaker/wwwroot/css/modelmaker.css +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/RapidCMS.Repositories/IConverter.cs b/src/RapidCMS.Repositories/IConverter.cs index eaf0f6c9..88960677 100644 --- a/src/RapidCMS.Repositories/IConverter.cs +++ b/src/RapidCMS.Repositories/IConverter.cs @@ -1,8 +1,7 @@ -namespace RapidCMS.Repositories +namespace RapidCMS.Repositories; + +public interface IConverter { - public interface IConverter - { - TA Convert(TB obj); - TB Convert(TA obj); - } + TA Convert(TB obj); + TB Convert(TA obj); } diff --git a/src/RapidCMS.Repositories/InMemoryRepository.cs b/src/RapidCMS.Repositories/InMemoryRepository.cs index 75ee2cf0..478d8ea0 100644 --- a/src/RapidCMS.Repositories/InMemoryRepository.cs +++ b/src/RapidCMS.Repositories/InMemoryRepository.cs @@ -14,276 +14,275 @@ using RapidCMS.Core.Models.EventArgs.Mediators; using RapidCMS.Core.Repositories; -namespace RapidCMS.Repositories +namespace RapidCMS.Repositories; + +/// +/// This generic repository saves TEntities in memory and has some basic support for one-to-many relations. +/// Use *only* List<TRelatedEntity> properties for relations. +/// +/// Entity to store +public class InMemoryRepository : BaseRepository + where TEntity : class, IEntity, ICloneable, new() { - /// - /// This generic repository saves TEntities in memory and has some basic support for one-to-many relations. - /// Use *only* List<TRelatedEntity> properties for relations. - /// - /// Entity to store - public class InMemoryRepository : BaseRepository - where TEntity : class, IEntity, ICloneable, new() + protected Dictionary> _data = new Dictionary>(); + protected Dictionary> _relations = new Dictionary>(); + private readonly IMediator _mediator; + private readonly IServiceProvider _serviceProvider; + + public InMemoryRepository(IMediator mediator, IServiceProvider serviceProvider) + { + _mediator = mediator; + _serviceProvider = serviceProvider; + } + + protected List GetListForParent(IParent? parent) { - protected Dictionary> _data = new Dictionary>(); - protected Dictionary> _relations = new Dictionary>(); - private readonly IMediator _mediator; - private readonly IServiceProvider _serviceProvider; + var pId = parent?.Entity.Id ?? string.Empty; - public InMemoryRepository(IMediator mediator, IServiceProvider serviceProvider) + if (!_data.ContainsKey(pId)) { - _mediator = mediator; - _serviceProvider = serviceProvider; + _data[pId] = new List(); } - protected List GetListForParent(IParent? parent) - { - var pId = parent?.Entity.Id ?? string.Empty; + return _data[pId]; + } - if (!_data.ContainsKey(pId)) - { - _data[pId] = new List(); - } + public override Task DeleteAsync(string id, IParent? parent) + { + GetListForParent(parent).RemoveAll(x => x.Id == id); - return _data[pId]; - } + _mediator.NotifyEvent(this, new MessageEventArgs(MessageType.Success, "Entity deleted.")); - public override Task DeleteAsync(string id, IParent? parent) - { - GetListForParent(parent).RemoveAll(x => x.Id == id); + return Task.CompletedTask; + } - _mediator.NotifyEvent(this, new MessageEventArgs(MessageType.Success, "Entity deleted.")); + public override Task> GetAllAsync(IParent? parent, IView view) + { + var dataQuery = GetListForParent(parent).AsQueryable(); - return Task.CompletedTask; - } + dataQuery = view.ApplyDataView(dataQuery); - public override Task> GetAllAsync(IParent? parent, IView view) + if (view.SearchTerm != null) { - var dataQuery = GetListForParent(parent).AsQueryable(); + var stringProperties = typeof(TEntity).GetProperties().Where(x => x.PropertyType == typeof(string)).ToList(); - dataQuery = view.ApplyDataView(dataQuery); - - if (view.SearchTerm != null) - { - var stringProperties = typeof(TEntity).GetProperties().Where(x => x.PropertyType == typeof(string)).ToList(); + // this is not a very fast or sensible search function, but it's just an example that works for all entities + dataQuery = dataQuery + .Where(x => stringProperties + .Any(property => (property.GetValue(x) as string) != null ? ((string)property.GetValue(x)!).Contains(view.SearchTerm, StringComparison.InvariantCultureIgnoreCase) : false)); + } - // this is not a very fast or sensible search function, but it's just an example that works for all entities - dataQuery = dataQuery - .Where(x => stringProperties - .Any(property => (property.GetValue(x) as string) != null ? ((string)property.GetValue(x)!).Contains(view.SearchTerm, StringComparison.InvariantCultureIgnoreCase) : false)); - } + dataQuery = view.ApplyOrder(dataQuery); - dataQuery = view.ApplyOrder(dataQuery); + var dataQueryResult = dataQuery + .Skip(view.Skip) + .Take(view.Take + 1) + .ToList(); - var dataQueryResult = dataQuery - .Skip(view.Skip) - .Take(view.Take + 1) - .ToList(); + var data = dataQueryResult + .Take(view.Take) + .Select(x => (TEntity)x.Clone()); - var data = dataQueryResult - .Take(view.Take) - .Select(x => (TEntity)x.Clone()); + view.HasMoreData(dataQueryResult.Count > view.Take); - view.HasMoreData(dataQueryResult.Count > view.Take); + return Task.FromResult(data); + } - return Task.FromResult(data); - } + public override Task?> GetAllRelatedAsync(IRelated related, IView view) + { + var ids = _relations.Where(x => x.Value.Contains(related.Entity.Id!)).Select(x => x.Key); - public override Task?> GetAllRelatedAsync(IRelated related, IView view) - { - var ids = _relations.Where(x => x.Value.Contains(related.Entity.Id!)).Select(x => x.Key); + return Task.FromResult(GetListForParent(related.Parent).Where(x => ids.Contains(x.Id!)))!; + } - return Task.FromResult(GetListForParent(related.Parent).Where(x => ids.Contains(x.Id!)))!; - } + public override Task?> GetAllNonRelatedAsync(IRelated related, IView view) + { + var ids = _relations.Where(x => x.Value.Contains(related.Entity.Id!)).Select(x => x.Key); - public override Task?> GetAllNonRelatedAsync(IRelated related, IView view) - { - var ids = _relations.Where(x => x.Value.Contains(related.Entity.Id!)).Select(x => x.Key); + return Task.FromResult(GetListForParent(related.Parent).Where(x => !ids.Contains(x.Id!)))!; + } - return Task.FromResult(GetListForParent(related.Parent).Where(x => !ids.Contains(x.Id!)))!; - } + public override async Task GetByIdAsync(string id, IParent? parent) + { + var entity = (TEntity?)GetListForParent(parent).FirstOrDefault(x => x.Id == id)?.Clone(); - public override async Task GetByIdAsync(string id, IParent? parent) + if (entity == null) { - var entity = (TEntity?)GetListForParent(parent).FirstOrDefault(x => x.Id == id)?.Clone(); + entity = (TEntity?)(await NewAsync(parent, default))?.Clone(); + entity!.Id = id; + } - if (entity == null) - { - entity = (TEntity?)(await NewAsync(parent, default))?.Clone(); - entity!.Id = id; - } + return entity; + } - return entity; - } + public override async Task InsertAsync(IEditContext editContext) + { + editContext.Entity.Id = new Random().Next(0, int.MaxValue).ToString(); - public override async Task InsertAsync(IEditContext editContext) - { - editContext.Entity.Id = new Random().Next(0, int.MaxValue).ToString(); + await HandleRelationsAsync(editContext.Entity, editContext.GetRelationContainer()); - await HandleRelationsAsync(editContext.Entity, editContext.GetRelationContainer()); + GetListForParent(editContext.Parent).Add(editContext.Entity); - GetListForParent(editContext.Parent).Add(editContext.Entity); + _mediator.NotifyEvent(this, new MessageEventArgs(MessageType.Success, "Entity created.")); - _mediator.NotifyEvent(this, new MessageEventArgs(MessageType.Success, "Entity created.")); + return (TEntity)editContext.Entity.Clone(); + } - return (TEntity)editContext.Entity.Clone(); + public override Task NewAsync(IParent? parent, Type? variantType = null) + { + if (variantType != null) + { + return Task.FromResult((TEntity)Activator.CreateInstance(variantType)!); } - public override Task NewAsync(IParent? parent, Type? variantType = null) - { - if (variantType != null) - { - return Task.FromResult((TEntity)Activator.CreateInstance(variantType)!); - } + return Task.FromResult(new TEntity()); + } - return Task.FromResult(new TEntity()); - } + // using editContext overload of UpdateAsync, you can access the state of the edit form + // with this, you can check whether fields were edited (using editContext.IsModified(..)) + public override async Task UpdateAsync(IEditContext editContext) + { + var list = GetListForParent(editContext.Parent); + + var newEntity = (TEntity)editContext.Entity.Clone(); - // using editContext overload of UpdateAsync, you can access the state of the edit form - // with this, you can check whether fields were edited (using editContext.IsModified(..)) - public override async Task UpdateAsync(IEditContext editContext) + var index = list.FindIndex(x => x.Id == editContext.Entity.Id); + if (index == -1) + { + list.Add(newEntity); + } + else { - var list = GetListForParent(editContext.Parent); - var newEntity = (TEntity)editContext.Entity.Clone(); + list.Insert(index, newEntity); + list.RemoveAt(index + 1); + } - var index = list.FindIndex(x => x.Id == editContext.Entity.Id); - if (index == -1) - { - list.Add(newEntity); - } - else - { + await HandleRelationsAsync(newEntity, editContext.GetRelationContainer()); - list.Insert(index, newEntity); - list.RemoveAt(index + 1); - } + _mediator.NotifyEvent(this, new MessageEventArgs(MessageType.Success, "Entity updated.")); + } - await HandleRelationsAsync(newEntity, editContext.GetRelationContainer()); + public override Task ReorderAsync(string? beforeId, string id, IParent? parent) + { + var parentId = parent?.Entity.Id ?? string.Empty; - _mediator.NotifyEvent(this, new MessageEventArgs(MessageType.Success, "Entity updated.")); + var entity = _data[parentId].FirstOrDefault(x => x.Id == id); + if (entity == null) + { + return Task.CompletedTask; } - public override Task ReorderAsync(string? beforeId, string id, IParent? parent) + _data[parentId].Remove(entity); + if (string.IsNullOrWhiteSpace(beforeId)) { - var parentId = parent?.Entity.Id ?? string.Empty; - - var entity = _data[parentId].FirstOrDefault(x => x.Id == id); - if (entity == null) - { - return Task.CompletedTask; - } + _data[parentId].Add(entity); + } + else + { + var index = _data[parentId].FindIndex(x => x.Id == beforeId); + _data[parentId].Insert(index, entity); + } - _data[parentId].Remove(entity); - if (string.IsNullOrWhiteSpace(beforeId)) - { - _data[parentId].Add(entity); - } - else - { - var index = _data[parentId].FindIndex(x => x.Id == beforeId); - _data[parentId].Insert(index, entity); - } + _mediator.NotifyEvent(this, new MessageEventArgs(MessageType.Success, "Entities reordered.")); - _mediator.NotifyEvent(this, new MessageEventArgs(MessageType.Success, "Entities reordered.")); + return Task.CompletedTask; + } - return Task.CompletedTask; + public override Task AddAsync(IRelated related, string id) + { + if (!_relations.ContainsKey(id)) + { + _relations.Add(id, new List()); } - public override Task AddAsync(IRelated related, string id) - { - if (!_relations.ContainsKey(id)) - { - _relations.Add(id, new List()); - } + _relations[id].Add(related.Entity.Id!); - _relations[id].Add(related.Entity.Id!); + _mediator.NotifyEvent(this, new MessageEventArgs(MessageType.Success, "Entity added.")); - _mediator.NotifyEvent(this, new MessageEventArgs(MessageType.Success, "Entity added.")); + return Task.CompletedTask; + } - return Task.CompletedTask; + public override Task RemoveAsync(IRelated related, string id) + { + if (!_relations.ContainsKey(id)) + { + _relations.Add(id, new List()); } - public override Task RemoveAsync(IRelated related, string id) - { - if (!_relations.ContainsKey(id)) - { - _relations.Add(id, new List()); - } + _relations[id].Remove(related.Entity.Id!); - _relations[id].Remove(related.Entity.Id!); + _mediator.NotifyEvent(this, new MessageEventArgs(MessageType.Success, "Entity removed.")); - _mediator.NotifyEvent(this, new MessageEventArgs(MessageType.Success, "Entity removed.")); + return Task.CompletedTask; + } - return Task.CompletedTask; - } + private async Task HandleRelationsAsync(TEntity entity, IRelationContainer? relations) + { + // this is some generic code to handle relations very generically + // please do not use in production (and you can't, since you cannot access IRepository) - private async Task HandleRelationsAsync(TEntity entity, IRelationContainer? relations) + if (relations != null) { - // this is some generic code to handle relations very generically - // please do not use in production (and you can't, since you cannot access IRepository) + // use relations to process one-to-many relations between collections / tables + // it contains a list of selected Ids, which should be used to update the relations - if (relations != null) + foreach (var relation in relations.Relations) { - // use relations to process one-to-many relations between collections / tables - // it contains a list of selected Ids, which should be used to update the relations - - foreach (var relation in relations.Relations) + try { - try + if (relation.Property is IFullPropertyMetadata fp) { - if (relation.Property is IFullPropertyMetadata fp) + // magic for enums + if (relation.RelatedEntityType.IsEnum && fp.Getter(entity) is IList current) { - // magic for enums - if (relation.RelatedEntityType.IsEnum && fp.Getter(entity) is IList current) + current.Clear(); + foreach (var enumValue in relation.RelatedElementIds) { - current.Clear(); - foreach (var enumValue in relation.RelatedElementIds) - { - current.Add(enumValue); - } + current.Add(enumValue); } - else - { - // this is pretty ugly - var inMemoryRepo = _serviceProvider.GetService(typeof(InMemoryRepository<>).MakeGenericType(relation.RelatedEntityType)) as IRepository; - var jsonRepo = _serviceProvider.GetService(typeof(JsonRepository<>).MakeGenericType(relation.RelatedEntityType)) as IRepository; - var lsRepo = _serviceProvider.GetService(typeof(LocalStorageRepository<>).MakeGenericType(relation.RelatedEntityType)) as IRepository; - var baseRepo = _serviceProvider.GetService(typeof(BaseRepository<>).MakeGenericType(relation.RelatedEntityType)) as IRepository; + } + else + { + // this is pretty ugly + var inMemoryRepo = _serviceProvider.GetService(typeof(InMemoryRepository<>).MakeGenericType(relation.RelatedEntityType)) as IRepository; + var jsonRepo = _serviceProvider.GetService(typeof(JsonRepository<>).MakeGenericType(relation.RelatedEntityType)) as IRepository; + var lsRepo = _serviceProvider.GetService(typeof(LocalStorageRepository<>).MakeGenericType(relation.RelatedEntityType)) as IRepository; + var baseRepo = _serviceProvider.GetService(typeof(BaseRepository<>).MakeGenericType(relation.RelatedEntityType)) as IRepository; - var repo = inMemoryRepo ?? jsonRepo ?? lsRepo ?? baseRepo; + var repo = inMemoryRepo ?? jsonRepo ?? lsRepo ?? baseRepo; - if (repo != null) - { - var relatedEntities = await relation.RelatedElementIds - .Select(x => x?.ToString()) - .OfType() - .ToListAsync(async id => - { - var entity = await repo.GetByIdAsync(id!, new ViewContext(null, default)); - return entity; - }); - - var orignalList = fp.Getter(entity); - - if (orignalList is IList list) + if (repo != null) + { + var relatedEntities = await relation.RelatedElementIds + .Select(x => x?.ToString()) + .OfType() + .ToListAsync(async id => { - list.Clear(); + var entity = await repo.GetByIdAsync(id!, new ViewContext(null, default)); + return entity; + }); + + var orignalList = fp.Getter(entity); - foreach (var relatedEntity in relatedEntities) - { - list.Add(relatedEntity); - } + if (orignalList is IList list) + { + list.Clear(); - fp.Setter(entity, list); + foreach (var relatedEntity in relatedEntities) + { + list.Add(relatedEntity); } + + fp.Setter(entity, list); } } } } - catch - { - // do not care - } + } + catch + { + // do not care } } } diff --git a/src/RapidCMS.Repositories/JsonRepository.cs b/src/RapidCMS.Repositories/JsonRepository.cs index 20b30a34..a9b9db80 100644 --- a/src/RapidCMS.Repositories/JsonRepository.cs +++ b/src/RapidCMS.Repositories/JsonRepository.cs @@ -7,117 +7,116 @@ using RapidCMS.Core.Abstractions.Forms; using RapidCMS.Core.Abstractions.Mediators; -namespace RapidCMS.Repositories +namespace RapidCMS.Repositories; + +/// +/// This generic repository loads TEntities when constructed and saves TEntities in json when deconstructed, and has some basic support for one-to-many relations. +/// Use *only* List<TRelatedEntity> properties for relations. +/// +/// Entity to store +public class JsonRepository : InMemoryRepository + where TEntity : class, IEntity, ICloneable, new() { - /// - /// This generic repository loads TEntities when constructed and saves TEntities in json when deconstructed, and has some basic support for one-to-many relations. - /// Use *only* List<TRelatedEntity> properties for relations. - /// - /// Entity to store - public class JsonRepository : InMemoryRepository - where TEntity : class, IEntity, ICloneable, new() + private readonly JsonSerializerSettings _jsonSerializerSettings = new JsonSerializerSettings { - private readonly JsonSerializerSettings _jsonSerializerSettings = new JsonSerializerSettings - { - TypeNameHandling = TypeNameHandling.All, - Formatting = Formatting.Indented - }; + TypeNameHandling = TypeNameHandling.All, + Formatting = Formatting.Indented + }; - public JsonRepository(IMediator mediator, IServiceProvider serviceProvider) : base(mediator, serviceProvider) + public JsonRepository(IMediator mediator, IServiceProvider serviceProvider) : base(mediator, serviceProvider) + { + try { - try + if (!Directory.Exists(Folder())) + { + Directory.CreateDirectory(Folder()); + } + + lock (_lock) { - if (!Directory.Exists(Folder())) + var dataFileContents = File.ReadAllText(DataJsonFileName()); + if (!string.IsNullOrWhiteSpace(dataFileContents)) { - Directory.CreateDirectory(Folder()); + _data = JsonConvert.DeserializeObject>>(dataFileContents, _jsonSerializerSettings) ?? new(); } - lock (_lock) + var relationsFileContents = File.ReadAllText(RelationsJsonFileName()); + if (!string.IsNullOrWhiteSpace(relationsFileContents)) { - var dataFileContents = File.ReadAllText(DataJsonFileName()); - if (!string.IsNullOrWhiteSpace(dataFileContents)) - { - _data = JsonConvert.DeserializeObject>>(dataFileContents, _jsonSerializerSettings) ?? new(); - } - - var relationsFileContents = File.ReadAllText(RelationsJsonFileName()); - if (!string.IsNullOrWhiteSpace(relationsFileContents)) - { - _relations = JsonConvert.DeserializeObject>>(relationsFileContents, _jsonSerializerSettings) ?? new(); - } + _relations = JsonConvert.DeserializeObject>>(relationsFileContents, _jsonSerializerSettings) ?? new(); } } - catch + } + catch + { + try { - try - { - File.Delete(DataJsonFileName()); - File.Delete(RelationsJsonFileName()); - } - catch { } + File.Delete(DataJsonFileName()); + File.Delete(RelationsJsonFileName()); } - - UpdateJson(); + catch { } } - private static string Folder() - { - return "./bin/"; - } + UpdateJson(); + } + + private static string Folder() + { + return "./bin/"; + } - private static string DataJsonFileName() => $"{Folder()}{typeof(TEntity).FullName}.json"; - private static string RelationsJsonFileName() => $"{Folder()}{typeof(TEntity).FullName}.relations.json"; + private static string DataJsonFileName() => $"{Folder()}{typeof(TEntity).FullName}.json"; + private static string RelationsJsonFileName() => $"{Folder()}{typeof(TEntity).FullName}.relations.json"; - private static object _lock = new object(); + private static object _lock = new object(); - private void UpdateJson() + private void UpdateJson() + { + try { - try + lock (_lock) { - lock (_lock) - { - File.WriteAllText(DataJsonFileName(), JsonConvert.SerializeObject(_data, _jsonSerializerSettings)); - File.WriteAllText(RelationsJsonFileName(), JsonConvert.SerializeObject(_relations, _jsonSerializerSettings)); - } + File.WriteAllText(DataJsonFileName(), JsonConvert.SerializeObject(_data, _jsonSerializerSettings)); + File.WriteAllText(RelationsJsonFileName(), JsonConvert.SerializeObject(_relations, _jsonSerializerSettings)); } - catch { } } + catch { } + } - public override async Task AddAsync(IRelated related, string id) - { - await base.AddAsync(related, id); - UpdateJson(); - } + public override async Task AddAsync(IRelated related, string id) + { + await base.AddAsync(related, id); + UpdateJson(); + } - public override async Task DeleteAsync(string id, IParent? parent) - { - await base.DeleteAsync(id, parent); - UpdateJson(); - } + public override async Task DeleteAsync(string id, IParent? parent) + { + await base.DeleteAsync(id, parent); + UpdateJson(); + } - public override async Task InsertAsync(IEditContext editContext) - { - var entity = await base.InsertAsync(editContext); - UpdateJson(); - return entity; - } + public override async Task InsertAsync(IEditContext editContext) + { + var entity = await base.InsertAsync(editContext); + UpdateJson(); + return entity; + } - public override async Task RemoveAsync(IRelated related, string id) - { - await base.RemoveAsync(related, id); - UpdateJson(); - } + public override async Task RemoveAsync(IRelated related, string id) + { + await base.RemoveAsync(related, id); + UpdateJson(); + } - public override async Task ReorderAsync(string? beforeId, string id, IParent? parent) - { - await base.ReorderAsync(beforeId, id, parent); - UpdateJson(); - } + public override async Task ReorderAsync(string? beforeId, string id, IParent? parent) + { + await base.ReorderAsync(beforeId, id, parent); + UpdateJson(); + } - public override async Task UpdateAsync(IEditContext editContext) - { - await base.UpdateAsync(editContext); - UpdateJson(); - } + public override async Task UpdateAsync(IEditContext editContext) + { + await base.UpdateAsync(editContext); + UpdateJson(); } } diff --git a/src/RapidCMS.Repositories/LocalStorageRepository.cs b/src/RapidCMS.Repositories/LocalStorageRepository.cs index c51399aa..b5acfed2 100644 --- a/src/RapidCMS.Repositories/LocalStorageRepository.cs +++ b/src/RapidCMS.Repositories/LocalStorageRepository.cs @@ -6,111 +6,110 @@ using RapidCMS.Core.Abstractions.Forms; using RapidCMS.Core.Abstractions.Mediators; -namespace RapidCMS.Repositories +namespace RapidCMS.Repositories; + +public class LocalStorageRepository : InMemoryRepository + where TEntity : class, IEntity, ICloneable, new() { - public class LocalStorageRepository : InMemoryRepository - where TEntity : class, IEntity, ICloneable, new() - { - private readonly ILocalStorageService _localStorage; + private readonly ILocalStorageService _localStorage; - private readonly Task _initializationTask; + private readonly Task _initializationTask; - public LocalStorageRepository( - ILocalStorageService localStorage, - IMediator mediator, - IServiceProvider serviceProvider) : base(mediator, serviceProvider) - { - _localStorage = localStorage; + public LocalStorageRepository( + ILocalStorageService localStorage, + IMediator mediator, + IServiceProvider serviceProvider) : base(mediator, serviceProvider) + { + _localStorage = localStorage; - _initializationTask = InitializationTaskAsync(); - } + _initializationTask = InitializationTaskAsync(); + } - private async Task InitializationTaskAsync() + private async Task InitializationTaskAsync() + { + var dataStorage = await _localStorage.GetItemAsync>>(GetType().FullName); + if (dataStorage != null) { - var dataStorage = await _localStorage.GetItemAsync>>(GetType().FullName); - if (dataStorage != null) - { - _data = dataStorage; - } - - var relationStorage = await _localStorage.GetItemAsync>>($"{GetType().FullName}-relation"); - if (relationStorage != null) - { - _relations = relationStorage; - } - - await UpdateStorageAsync(); + _data = dataStorage; } - private async Task UpdateStorageAsync() + var relationStorage = await _localStorage.GetItemAsync>>($"{GetType().FullName}-relation"); + if (relationStorage != null) { - try - { - await _localStorage.SetItemAsync(GetType().FullName, _data); - await _localStorage.SetItemAsync($"{GetType().FullName}-relation", _relations); - } - catch { } + _relations = relationStorage; } - public override async Task> GetAllAsync(IParent? parent, IView view) - { - await _initializationTask; - return await base.GetAllAsync(parent, view); - } + await UpdateStorageAsync(); + } - public override async Task?> GetAllNonRelatedAsync(IRelated related, IView view) + private async Task UpdateStorageAsync() + { + try { - await _initializationTask; - return await base.GetAllNonRelatedAsync(related, view); + await _localStorage.SetItemAsync(GetType().FullName, _data); + await _localStorage.SetItemAsync($"{GetType().FullName}-relation", _relations); } + catch { } + } - public override async Task?> GetAllRelatedAsync(IRelated related, IView view) - { - await _initializationTask; - return await base.GetAllRelatedAsync(related, view); - } + public override async Task> GetAllAsync(IParent? parent, IView view) + { + await _initializationTask; + return await base.GetAllAsync(parent, view); + } - public override async Task GetByIdAsync(string id, IParent? parent) - { - await _initializationTask; - return await base.GetByIdAsync(id, parent); - } + public override async Task?> GetAllNonRelatedAsync(IRelated related, IView view) + { + await _initializationTask; + return await base.GetAllNonRelatedAsync(related, view); + } - public override async Task AddAsync(IRelated related, string id) - { - await base.AddAsync(related, id); - await UpdateStorageAsync(); - } + public override async Task?> GetAllRelatedAsync(IRelated related, IView view) + { + await _initializationTask; + return await base.GetAllRelatedAsync(related, view); + } - public override async Task DeleteAsync(string id, IParent? parent) - { - await base.DeleteAsync(id, parent); - await UpdateStorageAsync(); - } + public override async Task GetByIdAsync(string id, IParent? parent) + { + await _initializationTask; + return await base.GetByIdAsync(id, parent); + } - public override async Task InsertAsync(IEditContext editContext) - { - var entity = await base.InsertAsync(editContext); - await UpdateStorageAsync(); - return entity; - } + public override async Task AddAsync(IRelated related, string id) + { + await base.AddAsync(related, id); + await UpdateStorageAsync(); + } - public override async Task RemoveAsync(IRelated related, string id) - { - await base.RemoveAsync(related, id); - await UpdateStorageAsync(); - } + public override async Task DeleteAsync(string id, IParent? parent) + { + await base.DeleteAsync(id, parent); + await UpdateStorageAsync(); + } - public override async Task ReorderAsync(string? beforeId, string id, IParent? parent) - { - await base.ReorderAsync(beforeId, id, parent); - await UpdateStorageAsync(); - } + public override async Task InsertAsync(IEditContext editContext) + { + var entity = await base.InsertAsync(editContext); + await UpdateStorageAsync(); + return entity; + } - public override async Task UpdateAsync(IEditContext editContext) - { - await base.UpdateAsync(editContext); - await UpdateStorageAsync(); - } + public override async Task RemoveAsync(IRelated related, string id) + { + await base.RemoveAsync(related, id); + await UpdateStorageAsync(); + } + + public override async Task ReorderAsync(string? beforeId, string id, IParent? parent) + { + await base.ReorderAsync(beforeId, id, parent); + await UpdateStorageAsync(); + } + + public override async Task UpdateAsync(IEditContext editContext) + { + await base.UpdateAsync(editContext); + await UpdateStorageAsync(); } } diff --git a/src/RapidCMS.Repositories/MappedInMemoryRepository.cs b/src/RapidCMS.Repositories/MappedInMemoryRepository.cs index 147eb8d1..8bed7e8b 100644 --- a/src/RapidCMS.Repositories/MappedInMemoryRepository.cs +++ b/src/RapidCMS.Repositories/MappedInMemoryRepository.cs @@ -9,124 +9,123 @@ using RapidCMS.Core.Models.EventArgs.Mediators; using RapidCMS.Core.Repositories; -namespace RapidCMS.Repositories +namespace RapidCMS.Repositories; + +/// +/// This generic repository saves TEntities in memory and has some basic support for one-to-many relations. +/// No support for relations. +/// +/// This MappedInMemoryRepository maps the objects to and from a different entity, allowing for using a different type of entity +/// to be used for the database than which is used in the CMS view. This is useful when the database entity is incompatible with +/// the CMS, or if validation attributes cannot be placed on the database entities. +/// +/// The IQuery's are not affected by this mapping, allowing you to define query expressions using the database entities, greatly +/// simplifying the use of data views in these repositories. +/// +/// Entity used in cms +/// Entity to store +public class MappedInMemoryRepository : BaseMappedRepository + where TCmsEntity : class, IEntity, new() + where TEntity : class, IEntity, ICloneable, new() { - /// - /// This generic repository saves TEntities in memory and has some basic support for one-to-many relations. - /// No support for relations. - /// - /// This MappedInMemoryRepository maps the objects to and from a different entity, allowing for using a different type of entity - /// to be used for the database than which is used in the CMS view. This is useful when the database entity is incompatible with - /// the CMS, or if validation attributes cannot be placed on the database entities. - /// - /// The IQuery's are not affected by this mapping, allowing you to define query expressions using the database entities, greatly - /// simplifying the use of data views in these repositories. - /// - /// Entity used in cms - /// Entity to store - public class MappedInMemoryRepository : BaseMappedRepository - where TCmsEntity : class, IEntity, new() - where TEntity : class, IEntity, ICloneable, new() + protected Dictionary> _data = new Dictionary>(); + private readonly IMediator _mediator; + private readonly IConverter _converter; + + public MappedInMemoryRepository(IMediator mediator, IConverter converter) + { + _mediator = mediator; + _converter = converter; + } + + private List GetListForParent(IParent? parent) { - protected Dictionary> _data = new Dictionary>(); - private readonly IMediator _mediator; - private readonly IConverter _converter; + var pId = parent?.Entity.Id ?? string.Empty; - public MappedInMemoryRepository(IMediator mediator, IConverter converter) + if (!_data.ContainsKey(pId)) { - _mediator = mediator; - _converter = converter; + _data[pId] = new List(); } - private List GetListForParent(IParent? parent) - { - var pId = parent?.Entity.Id ?? string.Empty; + return _data[pId]; + } - if (!_data.ContainsKey(pId)) - { - _data[pId] = new List(); - } + public override Task DeleteAsync(string id, IParent? parent) + { + GetListForParent(parent).RemoveAll(x => x.Id == id); - return _data[pId]; - } + _mediator.NotifyEvent(this, new MessageEventArgs(MessageType.Success, "Entity deleted.")); - public override Task DeleteAsync(string id, IParent? parent) - { - GetListForParent(parent).RemoveAll(x => x.Id == id); + return Task.CompletedTask; + } - _mediator.NotifyEvent(this, new MessageEventArgs(MessageType.Success, "Entity deleted.")); + public override Task> GetAllAsync(IParent? parent, IView view) + { + var dataQuery = GetListForParent(parent).AsQueryable(); - return Task.CompletedTask; - } + dataQuery = view.ApplyDataView(dataQuery); - public override Task> GetAllAsync(IParent? parent, IView view) + if (view.SearchTerm != null) { - var dataQuery = GetListForParent(parent).AsQueryable(); - - dataQuery = view.ApplyDataView(dataQuery); - - if (view.SearchTerm != null) - { - // this is not a very useful search function, but it's just an example - dataQuery = dataQuery.Where(x => x.Id == null ? false : x.Id.Contains(view.SearchTerm)); - } + // this is not a very useful search function, but it's just an example + dataQuery = dataQuery.Where(x => x.Id == null ? false : x.Id.Contains(view.SearchTerm)); + } - dataQuery = view.ApplyOrder(dataQuery); + dataQuery = view.ApplyOrder(dataQuery); - var data = dataQuery - .Skip(view.Skip) - .Take(view.Take) - .ToList() - .Select(x => _converter.Convert((TEntity)x.Clone())); + var data = dataQuery + .Skip(view.Skip) + .Take(view.Take) + .ToList() + .Select(x => _converter.Convert((TEntity)x.Clone())); - view.HasMoreData(GetListForParent(parent).Count > (view.Skip + view.Take)); + view.HasMoreData(GetListForParent(parent).Count > (view.Skip + view.Take)); - return Task.FromResult(data); - } + return Task.FromResult(data); + } - public override Task GetByIdAsync(string id, IParent? parent) + public override Task GetByIdAsync(string id, IParent? parent) + { + var entity = (TEntity?)GetListForParent(parent).FirstOrDefault(x => x.Id == id)?.Clone(); + if (entity == null) { - var entity = (TEntity?)GetListForParent(parent).FirstOrDefault(x => x.Id == id)?.Clone(); - if (entity == null) - { - return Task.FromResult(default(TCmsEntity)); - } - - return Task.FromResult(_converter.Convert(entity))!; + return Task.FromResult(default(TCmsEntity)); } + + return Task.FromResult(_converter.Convert(entity))!; + } - public override Task InsertAsync(IEditContext editContext) - { - editContext.Entity.Id = new Random().Next(0, int.MaxValue).ToString(); + public override Task InsertAsync(IEditContext editContext) + { + editContext.Entity.Id = new Random().Next(0, int.MaxValue).ToString(); - var entity = _converter.Convert(editContext.Entity); + var entity = _converter.Convert(editContext.Entity); - GetListForParent(editContext.Parent).Add(entity); + GetListForParent(editContext.Parent).Add(entity); - _mediator.NotifyEvent(this, new MessageEventArgs(MessageType.Success, "Entity inserted.")); + _mediator.NotifyEvent(this, new MessageEventArgs(MessageType.Success, "Entity inserted.")); - return Task.FromResult( _converter.Convert((TEntity)entity.Clone()))!; - } + return Task.FromResult( _converter.Convert((TEntity)entity.Clone()))!; + } - public override Task NewAsync(IParent? parent, Type? variantType = null) - { - return Task.FromResult(new TCmsEntity()); - } + public override Task NewAsync(IParent? parent, Type? variantType = null) + { + return Task.FromResult(new TCmsEntity()); + } - public override Task UpdateAsync(IEditContext editContext) - { - var list = GetListForParent(editContext.Parent); + public override Task UpdateAsync(IEditContext editContext) + { + var list = GetListForParent(editContext.Parent); - var index = list.FindIndex(x => x.Id == editContext.Entity.Id); + var index = list.FindIndex(x => x.Id == editContext.Entity.Id); - var newEntity = (TEntity)_converter.Convert(editContext.Entity).Clone(); + var newEntity = (TEntity)_converter.Convert(editContext.Entity).Clone(); - list.Insert(index, newEntity); - list.RemoveAt(index + 1); + list.Insert(index, newEntity); + list.RemoveAt(index + 1); - _mediator.NotifyEvent(this, new MessageEventArgs(MessageType.Success, "Entity updated.")); + _mediator.NotifyEvent(this, new MessageEventArgs(MessageType.Success, "Entity updated.")); - return Task.CompletedTask; - } + return Task.CompletedTask; } } diff --git a/src/RapidCMS.Repositories/RapidCMS.Repositories.csproj b/src/RapidCMS.Repositories/RapidCMS.Repositories.csproj index 6e72835b..14ea1205 100644 --- a/src/RapidCMS.Repositories/RapidCMS.Repositories.csproj +++ b/src/RapidCMS.Repositories/RapidCMS.Repositories.csproj @@ -1,8 +1,7 @@  - net6.0 - 10.0 + net6.0;net8.0 enable Thomas Bleijendaal Thomas Bleijendaal @@ -47,7 +46,6 @@ - all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -57,6 +55,17 @@ + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + diff --git a/src/RapidCMS.Repositories/TempTestInMemoryRepository.cs b/src/RapidCMS.Repositories/TempTestInMemoryRepository.cs index ce778bad..ce0bdc40 100644 --- a/src/RapidCMS.Repositories/TempTestInMemoryRepository.cs +++ b/src/RapidCMS.Repositories/TempTestInMemoryRepository.cs @@ -14,263 +14,262 @@ using RapidCMS.Core.Models.EventArgs.Mediators; using RapidCMS.Core.Repositories; -namespace RapidCMS.Repositories +namespace RapidCMS.Repositories; + +/// +/// This generic repository saves TEntities in memory and has some basic support for one-to-many relations. +/// Use *only* List<TRelatedEntity> properties for relations. +/// +/// NOTE: This repository messes up the lifetime of an entity so don't use this. +/// +/// Entity to store +public class TempTestInMemoryRepository : BaseRepository + where TEntity : class, IEntity, new() { - /// - /// This generic repository saves TEntities in memory and has some basic support for one-to-many relations. - /// Use *only* List<TRelatedEntity> properties for relations. - /// - /// NOTE: This repository messes up the lifetime of an entity so don't use this. - /// - /// Entity to store - public class TempTestInMemoryRepository : BaseRepository - where TEntity : class, IEntity, new() + protected Dictionary> _data = new Dictionary>(); + protected Dictionary> _relations = new Dictionary>(); + private readonly IMediator _mediator; + private readonly IServiceProvider _serviceProvider; + + public TempTestInMemoryRepository(IMediator mediator, IServiceProvider serviceProvider) + { + _mediator = mediator; + _serviceProvider = serviceProvider; + } + + protected List GetListForParent(IParent? parent) { - protected Dictionary> _data = new Dictionary>(); - protected Dictionary> _relations = new Dictionary>(); - private readonly IMediator _mediator; - private readonly IServiceProvider _serviceProvider; + var pId = parent?.Entity.Id ?? string.Empty; - public TempTestInMemoryRepository(IMediator mediator, IServiceProvider serviceProvider) + if (!_data.ContainsKey(pId)) { - _mediator = mediator; - _serviceProvider = serviceProvider; + _data[pId] = new List(); } - protected List GetListForParent(IParent? parent) - { - var pId = parent?.Entity.Id ?? string.Empty; + return _data[pId]; + } - if (!_data.ContainsKey(pId)) - { - _data[pId] = new List(); - } + public override Task DeleteAsync(string id, IParent? parent) + { + GetListForParent(parent).RemoveAll(x => x.Id == id); - return _data[pId]; - } + _mediator.NotifyEvent(this, new MessageEventArgs(MessageType.Success, "Entity deleted.")); - public override Task DeleteAsync(string id, IParent? parent) - { - GetListForParent(parent).RemoveAll(x => x.Id == id); + return Task.CompletedTask; + } - _mediator.NotifyEvent(this, new MessageEventArgs(MessageType.Success, "Entity deleted.")); + public override Task> GetAllAsync(IParent? parent, IView view) + { + var dataQuery = GetListForParent(parent).AsQueryable(); - return Task.CompletedTask; - } + dataQuery = view.ApplyDataView(dataQuery); - public override Task> GetAllAsync(IParent? parent, IView view) + if (view.SearchTerm != null) { - var dataQuery = GetListForParent(parent).AsQueryable(); - - dataQuery = view.ApplyDataView(dataQuery); + var stringProperties = typeof(TEntity).GetProperties().Where(x => x.PropertyType == typeof(string)).ToList(); - if (view.SearchTerm != null) - { - var stringProperties = typeof(TEntity).GetProperties().Where(x => x.PropertyType == typeof(string)).ToList(); + // this is not a very fast or sensible search function, but it's just an example that works for all entities + dataQuery = dataQuery + .Where(x => stringProperties + .Any(property => (property.GetValue(x) as string) != null ? ((string)property.GetValue(x)!).Contains(view.SearchTerm, StringComparison.InvariantCultureIgnoreCase) : false)); + } - // this is not a very fast or sensible search function, but it's just an example that works for all entities - dataQuery = dataQuery - .Where(x => stringProperties - .Any(property => (property.GetValue(x) as string) != null ? ((string)property.GetValue(x)!).Contains(view.SearchTerm, StringComparison.InvariantCultureIgnoreCase) : false)); - } + dataQuery = view.ApplyOrder(dataQuery); - dataQuery = view.ApplyOrder(dataQuery); + var dataQueryResult = dataQuery + .Skip(view.Skip) + .Take(view.Take + 1) + .ToList(); - var dataQueryResult = dataQuery - .Skip(view.Skip) - .Take(view.Take + 1) - .ToList(); + var data = dataQueryResult + .Take(view.Take); - var data = dataQueryResult - .Take(view.Take); + view.HasMoreData(dataQueryResult.Count > view.Take); - view.HasMoreData(dataQueryResult.Count > view.Take); + return Task.FromResult(data); + } - return Task.FromResult(data); - } + public override Task?> GetAllRelatedAsync(IRelated related, IView view) + { + var ids = _relations.Where(x => x.Value.Contains(related.Entity.Id!)).Select(x => x.Key); - public override Task?> GetAllRelatedAsync(IRelated related, IView view) - { - var ids = _relations.Where(x => x.Value.Contains(related.Entity.Id!)).Select(x => x.Key); + return Task.FromResult(GetListForParent(related.Parent).Where(x => ids.Contains(x.Id!)))!; + } - return Task.FromResult(GetListForParent(related.Parent).Where(x => ids.Contains(x.Id!)))!; - } + public override Task?> GetAllNonRelatedAsync(IRelated related, IView query) + { + var ids = _relations.Where(x => x.Value.Contains(related.Entity.Id!)).Select(x => x.Key); - public override Task?> GetAllNonRelatedAsync(IRelated related, IView query) - { - var ids = _relations.Where(x => x.Value.Contains(related.Entity.Id!)).Select(x => x.Key); + return Task.FromResult(GetListForParent(related.Parent).Where(x => !ids.Contains(x.Id!)))!; + } - return Task.FromResult(GetListForParent(related.Parent).Where(x => !ids.Contains(x.Id!)))!; - } + public override async Task GetByIdAsync(string id, IParent? parent) + { + var entity = (TEntity?)GetListForParent(parent).FirstOrDefault(x => x.Id == id); - public override async Task GetByIdAsync(string id, IParent? parent) + if (entity == null) { - var entity = (TEntity?)GetListForParent(parent).FirstOrDefault(x => x.Id == id); + entity = (TEntity?)(await NewAsync(parent, default)); + entity!.Id = id; + } - if (entity == null) - { - entity = (TEntity?)(await NewAsync(parent, default)); - entity!.Id = id; - } + return entity; + } - return entity; - } + public override async Task InsertAsync(IEditContext editContext) + { + editContext.Entity.Id = new Random().Next(0, int.MaxValue).ToString(); - public override async Task InsertAsync(IEditContext editContext) - { - editContext.Entity.Id = new Random().Next(0, int.MaxValue).ToString(); + await HandleRelationsAsync(editContext.Entity, editContext.GetRelationContainer()); - await HandleRelationsAsync(editContext.Entity, editContext.GetRelationContainer()); + GetListForParent(editContext.Parent).Add(editContext.Entity); - GetListForParent(editContext.Parent).Add(editContext.Entity); + _mediator.NotifyEvent(this, new MessageEventArgs(MessageType.Success, "Entity created.")); - _mediator.NotifyEvent(this, new MessageEventArgs(MessageType.Success, "Entity created.")); + return (TEntity)editContext.Entity; + } - return (TEntity)editContext.Entity; + public override Task NewAsync(IParent? parent, Type? variantType = null) + { + if (variantType != null) + { + return Task.FromResult((TEntity)Activator.CreateInstance(variantType)!); } - public override Task NewAsync(IParent? parent, Type? variantType = null) - { - if (variantType != null) - { - return Task.FromResult((TEntity)Activator.CreateInstance(variantType)!); - } + return Task.FromResult(new TEntity()); + } - return Task.FromResult(new TEntity()); - } + // using editContext overload of UpdateAsync, you can access the state of the edit form + // with this, you can check whether fields were edited (using editContext.IsModified(..)) + public override async Task UpdateAsync(IEditContext editContext) + { + var list = GetListForParent(editContext.Parent); - // using editContext overload of UpdateAsync, you can access the state of the edit form - // with this, you can check whether fields were edited (using editContext.IsModified(..)) - public override async Task UpdateAsync(IEditContext editContext) + var newEntity = (TEntity)editContext.Entity; + + var index = list.FindIndex(x => x.Id == editContext.Entity.Id); + if (index == -1) + { + list.Add(newEntity); + } + else { - var list = GetListForParent(editContext.Parent); - var newEntity = (TEntity)editContext.Entity; + list.Insert(index, newEntity); + list.RemoveAt(index + 1); + } - var index = list.FindIndex(x => x.Id == editContext.Entity.Id); - if (index == -1) - { - list.Add(newEntity); - } - else - { + await HandleRelationsAsync(newEntity, editContext.GetRelationContainer()); - list.Insert(index, newEntity); - list.RemoveAt(index + 1); - } + _mediator.NotifyEvent(this, new MessageEventArgs(MessageType.Success, "Entity updated.")); + } - await HandleRelationsAsync(newEntity, editContext.GetRelationContainer()); + public override Task ReorderAsync(string? beforeId, string id, IParent? parent) + { + var parentId = parent?.Entity.Id ?? string.Empty; - _mediator.NotifyEvent(this, new MessageEventArgs(MessageType.Success, "Entity updated.")); + var entity = _data[parentId].FirstOrDefault(x => x.Id == id); + if (entity == null) + { + return Task.CompletedTask; } - public override Task ReorderAsync(string? beforeId, string id, IParent? parent) + _data[parentId].Remove(entity); + if (string.IsNullOrWhiteSpace(beforeId)) { - var parentId = parent?.Entity.Id ?? string.Empty; - - var entity = _data[parentId].FirstOrDefault(x => x.Id == id); - if (entity == null) - { - return Task.CompletedTask; - } + _data[parentId].Add(entity); + } + else + { + var index = _data[parentId].FindIndex(x => x.Id == beforeId); + _data[parentId].Insert(index, entity); + } - _data[parentId].Remove(entity); - if (string.IsNullOrWhiteSpace(beforeId)) - { - _data[parentId].Add(entity); - } - else - { - var index = _data[parentId].FindIndex(x => x.Id == beforeId); - _data[parentId].Insert(index, entity); - } + _mediator.NotifyEvent(this, new MessageEventArgs(MessageType.Success, "Entities reordered.")); - _mediator.NotifyEvent(this, new MessageEventArgs(MessageType.Success, "Entities reordered.")); + return Task.CompletedTask; + } - return Task.CompletedTask; + public override Task AddAsync(IRelated related, string id) + { + if (!_relations.ContainsKey(id)) + { + _relations.Add(id, new List()); } - public override Task AddAsync(IRelated related, string id) - { - if (!_relations.ContainsKey(id)) - { - _relations.Add(id, new List()); - } + _relations[id].Add(related.Entity.Id!); - _relations[id].Add(related.Entity.Id!); + _mediator.NotifyEvent(this, new MessageEventArgs(MessageType.Success, "Entity added.")); - _mediator.NotifyEvent(this, new MessageEventArgs(MessageType.Success, "Entity added.")); + return Task.CompletedTask; + } - return Task.CompletedTask; + public override Task RemoveAsync(IRelated related, string id) + { + if (!_relations.ContainsKey(id)) + { + _relations.Add(id, new List()); } - public override Task RemoveAsync(IRelated related, string id) - { - if (!_relations.ContainsKey(id)) - { - _relations.Add(id, new List()); - } + _relations[id].Remove(related.Entity.Id!); - _relations[id].Remove(related.Entity.Id!); + _mediator.NotifyEvent(this, new MessageEventArgs(MessageType.Success, "Entity removed.")); - _mediator.NotifyEvent(this, new MessageEventArgs(MessageType.Success, "Entity removed.")); + return Task.CompletedTask; + } - return Task.CompletedTask; - } + private async Task HandleRelationsAsync(TEntity entity, IRelationContainer? relations) + { + // this is some generic code to handle relations very genericly + // please do not use in production (and you can't, since you cannot access IRepository) - private async Task HandleRelationsAsync(TEntity entity, IRelationContainer? relations) + if (relations != null) { - // this is some generic code to handle relations very genericly - // please do not use in production (and you can't, since you cannot access IRepository) + // use relations to process one-to-many relations between collections / tables + // it contains a list of selected Ids, which should be used to update the relations - if (relations != null) + foreach (var relation in relations.Relations) { - // use relations to process one-to-many relations between collections / tables - // it contains a list of selected Ids, which should be used to update the relations - - foreach (var relation in relations.Relations) + try { - try + if (relation.Property is IFullPropertyMetadata fp) { - if (relation.Property is IFullPropertyMetadata fp) - { - // this is pretty ugly - var baseRepo = _serviceProvider.GetService(typeof(BaseRepository<>).MakeGenericType(relation.RelatedEntityType)) as IRepository; - var inMemoryRepo = _serviceProvider.GetService(typeof(TempTestInMemoryRepository<>).MakeGenericType(relation.RelatedEntityType)) as IRepository; + // this is pretty ugly + var baseRepo = _serviceProvider.GetService(typeof(BaseRepository<>).MakeGenericType(relation.RelatedEntityType)) as IRepository; + var inMemoryRepo = _serviceProvider.GetService(typeof(TempTestInMemoryRepository<>).MakeGenericType(relation.RelatedEntityType)) as IRepository; - var repo = baseRepo ?? inMemoryRepo; + var repo = baseRepo ?? inMemoryRepo; - if (repo != null) - { - var relatedEntities = await relation.RelatedElementIds - .Select(x => x?.ToString()) - .OfType() - .ToListAsync(async id => - { - var entity = await repo.GetByIdAsync(id!, new ViewContext(null, default)); - return entity; - }); - - var orignalList = fp.Getter(entity); - - if (orignalList is IList list) + if (repo != null) + { + var relatedEntities = await relation.RelatedElementIds + .Select(x => x?.ToString()) + .OfType() + .ToListAsync(async id => { - list.Clear(); + var entity = await repo.GetByIdAsync(id!, new ViewContext(null, default)); + return entity; + }); + + var orignalList = fp.Getter(entity); - foreach (var relatedEntity in relatedEntities) - { - list.Add(relatedEntity); - } + if (orignalList is IList list) + { + list.Clear(); - fp.Setter(entity, list); + foreach (var relatedEntity in relatedEntities) + { + list.Add(relatedEntity); } + + fp.Setter(entity, list); } } } - catch - { - // do not care - } + } + catch + { + // do not care } } } diff --git a/src/RapidCMS.UI.PublishableEntity/Abstractions/IPublishableModelMakerEntity.cs b/src/RapidCMS.UI.PublishableEntity/Abstractions/IPublishableModelMakerEntity.cs deleted file mode 100644 index 67d34432..00000000 --- a/src/RapidCMS.UI.PublishableEntity/Abstractions/IPublishableModelMakerEntity.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using RapidCMS.Core.Abstractions.Data; -using RapidCMS.UI.PublishableEntity.Enums; - -namespace RapidCMS.UI.PublishableEntity.Abstractions -{ - public interface IPublishableModelMakerEntity : IEntity - { - PublishState State { get; set; } - - DateTime CreatedAt { get; set; } - - DateTime PublishedAt { get; set; } - - DateTime UpdatedAt { get; set; } - } -} diff --git a/src/RapidCMS.UI.PublishableEntity/Components/Displays/PublishStateDisplay.razor b/src/RapidCMS.UI.PublishableEntity/Components/Displays/PublishStateDisplay.razor deleted file mode 100644 index 4b7b7b65..00000000 --- a/src/RapidCMS.UI.PublishableEntity/Components/Displays/PublishStateDisplay.razor +++ /dev/null @@ -1,12 +0,0 @@ -@inherits BaseDisplay - -@state - -@code { - private PublishState state { get; set; } - - protected override void OnParametersSet() - { - state = Enum.Parse(GetValueAsString()); - } -} \ No newline at end of file diff --git a/src/RapidCMS.UI.PublishableEntity/Components/Sections/ModelDetailsSection.razor b/src/RapidCMS.UI.PublishableEntity/Components/Sections/ModelDetailsSection.razor deleted file mode 100644 index a990ca6f..00000000 --- a/src/RapidCMS.UI.PublishableEntity/Components/Sections/ModelDetailsSection.razor +++ /dev/null @@ -1,25 +0,0 @@ -@inherits BaseSection - -@if (modelMakerEntity != null) -{ -
- @modelMakerEntity.State - @* - TODO: creation publication and update times dependent on state - *@ -
-} - -@code -{ - [CascadingParameter(Name = "EditContext")] private FormEditContext? EditContext { get; set; } - - private IPublishableModelMakerEntity? modelMakerEntity; - - protected override Task OnInitializedAsync() - { - modelMakerEntity = EditContext?.Entity as IPublishableModelMakerEntity; - - return base.OnInitializedAsync(); - } -} diff --git a/src/RapidCMS.UI.PublishableEntity/Components/_Imports.razor b/src/RapidCMS.UI.PublishableEntity/Components/_Imports.razor deleted file mode 100644 index 9457b161..00000000 --- a/src/RapidCMS.UI.PublishableEntity/Components/_Imports.razor +++ /dev/null @@ -1,7 +0,0 @@ -@using RapidCMS.Core.Forms - -@using RapidCMS.UI.Components.Displays -@using RapidCMS.UI.Components.Sections - -@using RapidCMS.UI.PublishableEntity.Abstractions -@using RapidCMS.UI.PublishableEntity.Enums diff --git a/src/RapidCMS.UI.PublishableEntity/Enums/PublishState.cs b/src/RapidCMS.UI.PublishableEntity/Enums/PublishState.cs deleted file mode 100644 index bfdca56a..00000000 --- a/src/RapidCMS.UI.PublishableEntity/Enums/PublishState.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace RapidCMS.UI.PublishableEntity.Enums -{ - public enum PublishState - { - Draft, - Published, - Changed - } -} diff --git a/src/RapidCMS.UI.PublishableEntity/Extensions/PublishStateExtensions.cs b/src/RapidCMS.UI.PublishableEntity/Extensions/PublishStateExtensions.cs deleted file mode 100644 index 7ffb1182..00000000 --- a/src/RapidCMS.UI.PublishableEntity/Extensions/PublishStateExtensions.cs +++ /dev/null @@ -1,17 +0,0 @@ -using RapidCMS.UI.PublishableEntity.Enums; - -namespace RapidCMS.UI.PublishableEntity.Extensions -{ - public static class PublishStateExtensions - { - public static PublishState Modify(this PublishState state) - => state switch - { - PublishState.Draft => PublishState.Draft, - _ => PublishState.Changed - }; - - public static PublishState Publish(this PublishState state) - => PublishState.Published; - } -} diff --git a/src/RapidCMS.UI.PublishableEntity/RapidCMS.UI.PublishableEntity.csproj b/src/RapidCMS.UI.PublishableEntity/RapidCMS.UI.PublishableEntity.csproj deleted file mode 100644 index 02732b11..00000000 --- a/src/RapidCMS.UI.PublishableEntity/RapidCMS.UI.PublishableEntity.csproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - net6.0 - enable - - - - - - - - - - - - - - - - diff --git a/src/RapidCMS.UI.PublishableEntity/_Imports.razor b/src/RapidCMS.UI.PublishableEntity/_Imports.razor deleted file mode 100644 index 77285129..00000000 --- a/src/RapidCMS.UI.PublishableEntity/_Imports.razor +++ /dev/null @@ -1 +0,0 @@ -@using Microsoft.AspNetCore.Components.Web diff --git a/src/RapidCMS.UI.PublishableEntity/wwwroot/publishable-entity.css b/src/RapidCMS.UI.PublishableEntity/wwwroot/publishable-entity.css deleted file mode 100644 index d1bb8a35..00000000 --- a/src/RapidCMS.UI.PublishableEntity/wwwroot/publishable-entity.css +++ /dev/null @@ -1,40 +0,0 @@ -.publish-state { - display: inline-block; - background: #f3f2f1; - text-transform: lowercase; - font-variant: small-caps; - padding: .3rem 1rem .5rem 2.6rem; - position: relative; - line-height: 1.5; -} - - .publish-state::before { - content: ''; - display: block; - width: 12px; - background: #d2d0ce; - height: 12px; - position: absolute; - top: .8rem; - left: 1rem; - border-radius: 12px; - } - - .publish-state.publish-state-draft::before { - background: #ffaa44; - } - - .publish-state.publish-state-published::before { - background: #0b6a0b; - } - - .publish-state.publish-state-changed::before { - background: #e3008c; - } - -.entity-state { - display: block; - float: right; - width: 25rem; - text-align: right; -} diff --git a/src/RapidCMS.UI/Components/Buttons/BaseButton.cs b/src/RapidCMS.UI/Components/Buttons/BaseButton.cs index 2f4efba1..391b72de 100644 --- a/src/RapidCMS.UI/Components/Buttons/BaseButton.cs +++ b/src/RapidCMS.UI/Components/Buttons/BaseButton.cs @@ -5,66 +5,65 @@ using RapidCMS.Core.Forms; using RapidCMS.UI.Models; -namespace RapidCMS.UI.Components.Buttons +namespace RapidCMS.UI.Components.Buttons; + +public class BaseButton : EditContextComponentBase { - public class BaseButton : EditContextComponentBase - { - [Inject] private IJSRuntime JsRuntime { get; set; } = default!; + [Inject] private IJSRuntime JsRuntime { get; set; } = default!; - [Inject] private ILanguageResolver LanguageResolver { get; set; } = default!; + [Inject] private ILanguageResolver LanguageResolver { get; set; } = default!; - [Parameter] public ButtonViewModel Model { get; set; } = default!; + [Parameter] public ButtonViewModel Model { get; set; } = default!; - protected bool FormIsValid { get; private set; } + protected bool FormIsValid { get; private set; } - protected bool IsDisabled { get; set; } + protected bool IsDisabled { get; set; } - protected async Task ButtonClickAsync(object? customData = null) + protected async Task ButtonClickAsync(object? customData = null) + { + try { - try - { - IsDisabled = true; - StateHasChanged(); - - if (Model.RequiresValidForm && (EditContext == null || !await EditContext.IsValidAsync())) - { - return; - } + IsDisabled = true; + StateHasChanged(); - if (!Model.ShouldConfirm || await JsRuntime.InvokeAsync("confirm", LanguageResolver.ResolveText("Are you sure?"))) - { - await Model.NotifyClickAsync(EditContext!, customData); - } + if (Model.RequiresValidForm && (EditContext == null || !await EditContext.IsValidAsync())) + { + return; } - finally + + if (!Model.ShouldConfirm || await JsRuntime.InvokeAsync("confirm", LanguageResolver.ResolveText("Are you sure?"))) { - IsDisabled = false; - StateHasChanged(); + await Model.NotifyClickAsync(EditContext!, customData); } } - - private void ValidationStateChangeHandler(object? sender, ValidationStateChangedEventArgs e) + finally { - FormIsValid = e.IsValid != false; - + IsDisabled = false; StateHasChanged(); } + } - protected override void AttachListener() + private void ValidationStateChangeHandler(object? sender, ValidationStateChangedEventArgs e) + { + FormIsValid = e.IsValid != false; + + StateHasChanged(); + } + + protected override void AttachListener() + { + if (EditContext != null) { - if (EditContext != null) - { - EditContext.OnValidationStateChanged += ValidationStateChangeHandler; - FormIsValid = true; - } + EditContext.OnValidationStateChanged += ValidationStateChangeHandler; + FormIsValid = true; } + } - protected override void DetachListener() + protected override void DetachListener() + { + if (EditContext != null) { - if (EditContext != null) - { - EditContext.OnValidationStateChanged -= ValidationStateChangeHandler; - } + EditContext.OnValidationStateChanged -= ValidationStateChangeHandler; } } } diff --git a/src/RapidCMS.UI/Components/Displays/BaseDisplay.cs b/src/RapidCMS.UI/Components/Displays/BaseDisplay.cs index 767a16d5..9d28a97e 100644 --- a/src/RapidCMS.UI/Components/Displays/BaseDisplay.cs +++ b/src/RapidCMS.UI/Components/Displays/BaseDisplay.cs @@ -6,27 +6,26 @@ using RapidCMS.Core.Abstractions.UI; using RapidCMS.Core.Enums; -namespace RapidCMS.UI.Components.Displays +namespace RapidCMS.UI.Components.Displays; + +public class BaseDisplay : ComponentBase, IBaseUIElement { - public class BaseDisplay : ComponentBase, IBaseUIElement - { - [Parameter] public IEntity Entity { get; set; } = default!; - [Parameter] public IParent? Parent { get; set; } + [Parameter] public IEntity Entity { get; set; } = default!; + [Parameter] public IParent? Parent { get; set; } - [Parameter] public EntityState EntityState { get; set; } - [Parameter] public ListType DisplayType { get; set; } + [Parameter] public EntityState EntityState { get; set; } + [Parameter] public ListType DisplayType { get; set; } - [Parameter] public IExpressionMetadata Expression { get; set; } = default!; + [Parameter] public IExpressionMetadata Expression { get; set; } = default!; - /// - /// Implement the IWantConfiguration or IRequireConfiguration interfaces to - /// leverage the GetConfigAsync extension method so handling configuration is more easy. - /// - [Parameter] public Func>? Configuration { get; set; } + /// + /// Implement the IWantConfiguration or IRequireConfiguration interfaces to + /// leverage the GetConfigAsync extension method so handling configuration is more easy. + /// + [Parameter] public Func>? Configuration { get; set; } - protected string GetValueAsString() - { - return Expression.StringGetter(Entity); - } + protected string GetValueAsString() + { + return Expression.StringGetter(Entity); } } diff --git a/src/RapidCMS.UI/Components/DisposableComponent.cs b/src/RapidCMS.UI/Components/DisposableComponent.cs index 60f981f8..c5e5169b 100644 --- a/src/RapidCMS.UI/Components/DisposableComponent.cs +++ b/src/RapidCMS.UI/Components/DisposableComponent.cs @@ -2,46 +2,45 @@ using System.Collections.Generic; using Microsoft.AspNetCore.Components; -namespace RapidCMS.UI.Components +namespace RapidCMS.UI.Components; + +public class DisposableComponent : ComponentBase, IDisposable { - public class DisposableComponent : ComponentBase, IDisposable - { - private List? _disposables = new List(); + private List? _disposables = new List(); - protected void DisposeWhenDisposing(IDisposable disposable) + protected void DisposeWhenDisposing(IDisposable disposable) + { + if (_disposables == null) { - if (_disposables == null) - { - throw new ObjectDisposedException(nameof(disposable)); - } - - _disposables.Add(disposable); + throw new ObjectDisposedException(nameof(disposable)); } - void IDisposable.Dispose() - { - Dispose(); + _disposables.Add(disposable); + } - _disposables?.ForEach(x => x.Dispose()); - _disposables = null; - } + void IDisposable.Dispose() + { + Dispose(); - protected virtual void Dispose() - { + _disposables?.ForEach(x => x.Dispose()); + _disposables = null; + } - } + protected virtual void Dispose() + { - protected override void OnInitialized() - { - base.OnInitialized(); + } - if (_disposables == null) - { - throw new ObjectDisposedException($"{nameof(OnInitialized)} called on disposed {nameof(DisposableComponent)}."); - } + protected override void OnInitialized() + { + base.OnInitialized(); - _disposables.ForEach(x => x.Dispose()); - _disposables.Clear(); + if (_disposables == null) + { + throw new ObjectDisposedException($"{nameof(OnInitialized)} called on disposed {nameof(DisposableComponent)}."); } + + _disposables.ForEach(x => x.Dispose()); + _disposables.Clear(); } } diff --git a/src/RapidCMS.UI/Components/EditContextComponentBase.cs b/src/RapidCMS.UI/Components/EditContextComponentBase.cs index 3492becd..a4f43c4b 100644 --- a/src/RapidCMS.UI/Components/EditContextComponentBase.cs +++ b/src/RapidCMS.UI/Components/EditContextComponentBase.cs @@ -3,47 +3,46 @@ using Microsoft.AspNetCore.Components; using RapidCMS.Core.Forms; -namespace RapidCMS.UI.Components +namespace RapidCMS.UI.Components; + +// TODO: implement disposablecomponent instead of componentbase +public abstract class EditContextComponentBase : ComponentBase, IDisposable { - // TODO: implement disposablecomponent instead of componentbase - public abstract class EditContextComponentBase : ComponentBase, IDisposable + [CascadingParameter(Name = "EditContext")] private FormEditContext CascadedEditContext { get; set; } = default!; + protected FormEditContext EditContext { get; set; } = default!; + + public override Task SetParametersAsync(ParameterView parameters) { - [CascadingParameter(Name = "EditContext")] private FormEditContext CascadedEditContext { get; set; } = default!; - protected FormEditContext EditContext { get; set; } = default!; + parameters.SetParameterProperties(this); - public override Task SetParametersAsync(ParameterView parameters) + if (EditContext == null) { - parameters.SetParameterProperties(this); - - if (EditContext == null) + if (CascadedEditContext == null) { - if (CascadedEditContext == null) - { - throw new InvalidOperationException($"{GetType()} requires a CascadingParameter {nameof(EditContext)}."); - } - - EditContext = CascadedEditContext; - - AttachListener(); + throw new InvalidOperationException($"{GetType()} requires a CascadingParameter {nameof(EditContext)}."); } - else if (EditContext != CascadedEditContext) - { - DetachListener(); - - EditContext = CascadedEditContext; - AttachListener(); - } + EditContext = CascadedEditContext; - return base.SetParametersAsync(ParameterView.Empty); + AttachListener(); } - - protected abstract void AttachListener(); - protected abstract void DetachListener(); - - public virtual void Dispose() + else if (EditContext != CascadedEditContext) { DetachListener(); + + EditContext = CascadedEditContext; + + AttachListener(); } + + return base.SetParametersAsync(ParameterView.Empty); + } + + protected abstract void AttachListener(); + protected abstract void DetachListener(); + + public virtual void Dispose() + { + DetachListener(); } } diff --git a/src/RapidCMS.UI/Components/Editors/BaseDataEditor.cs b/src/RapidCMS.UI/Components/Editors/BaseDataEditor.cs index e100d8fd..954ec58d 100644 --- a/src/RapidCMS.UI/Components/Editors/BaseDataEditor.cs +++ b/src/RapidCMS.UI/Components/Editors/BaseDataEditor.cs @@ -1,18 +1,17 @@ using Microsoft.AspNetCore.Components; using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.UI.Components.Editors +namespace RapidCMS.UI.Components.Editors; + +public class BaseDataEditor : BasePropertyEditor { - public class BaseDataEditor : BasePropertyEditor - { - [Parameter] public IDataCollection? DataCollection { get; set; } + [Parameter] public IDataCollection? DataCollection { get; set; } - // TODO: check if this is needed - public override void Dispose() - { - base.Dispose(); + // TODO: check if this is needed + public override void Dispose() + { + base.Dispose(); - DataCollection?.Dispose(); - } + DataCollection?.Dispose(); } } diff --git a/src/RapidCMS.UI/Components/Editors/BaseEditor.cs b/src/RapidCMS.UI/Components/Editors/BaseEditor.cs index 89492ccc..78554956 100644 --- a/src/RapidCMS.UI/Components/Editors/BaseEditor.cs +++ b/src/RapidCMS.UI/Components/Editors/BaseEditor.cs @@ -9,94 +9,93 @@ using RapidCMS.Core.Enums; using RapidCMS.Core.Forms; -namespace RapidCMS.UI.Components.Editors +namespace RapidCMS.UI.Components.Editors; + +public class BaseEditor : EditContextComponentBase, IBaseUIElement { - public class BaseEditor : EditContextComponentBase, IBaseUIElement - { - protected ValidationState State { get; private set; } + protected ValidationState State { get; private set; } - [Parameter] public IEntity Entity { get; set; } = default!; - [Parameter] public IParent? Parent { get; set; } + [Parameter] public IEntity Entity { get; set; } = default!; + [Parameter] public IParent? Parent { get; set; } - [Parameter] public EntityState EntityState { get; set; } - [Parameter] public ListType DisplayType { get; set; } + [Parameter] public EntityState EntityState { get; set; } + [Parameter] public ListType DisplayType { get; set; } - [Parameter] public IPropertyMetadata Property { get; set; } = default!; + [Parameter] public IPropertyMetadata Property { get; set; } = default!; - [Parameter] public Func? IsDisabledFunc { get; set; } + [Parameter] public Func? IsDisabledFunc { get; set; } - [Parameter] public string? Placeholder { get; set; } + [Parameter] public string? Placeholder { get; set; } - /// - /// Implement the IWantConfiguration or IRequireConfiguration interfaces to - /// leverage the GetConfigAsync extension method so handling configuration is more easy. - /// - [Parameter] public Func>? Configuration { get; set; } + /// + /// Implement the IWantConfiguration or IRequireConfiguration interfaces to + /// leverage the GetConfigAsync extension method so handling configuration is more easy. + /// + [Parameter] public Func>? Configuration { get; set; } - protected bool IsDisabled => IsDisabledFunc?.Invoke(Entity, EntityState) ?? false; + protected bool IsDisabled => IsDisabledFunc?.Invoke(Entity, EntityState) ?? false; - protected object GetValueAsObject() - { - return Property.Getter(Entity); - } + protected object GetValueAsObject() + { + return Property.Getter(Entity); + } - protected string GetValueAsString() - { - return TypeDescriptor.GetConverter(Property.PropertyType).ConvertToString(GetValueAsObject()) ?? ""; - } + protected string GetValueAsString() + { + return TypeDescriptor.GetConverter(Property.PropertyType).ConvertToString(GetValueAsObject()) ?? ""; + } + + protected IEnumerable GetValidationMessages() + { + return EditContext.GetValidationMessages(Property); + } + + private void ValidationStateChangeHandler(object? sender, ValidationStateChangedEventArgs eventArgs) + { + var state = ValidationState.None; - protected IEnumerable GetValidationMessages() + if (!EditContext.WasValidated(Property)) { - return EditContext.GetValidationMessages(Property); + state |= ValidationState.NotValidated; } - - private void ValidationStateChangeHandler(object? sender, ValidationStateChangedEventArgs eventArgs) + else { - var state = ValidationState.None; - - if (!EditContext.WasValidated(Property)) + if (EditContext.IsValid(Property)) { - state |= ValidationState.NotValidated; + state |= ValidationState.Valid; } else { - if (EditContext.IsValid(Property)) - { - state |= ValidationState.Valid; - } - else - { - state |= ValidationState.Invalid; - } - } - - if (EditContext.IsModified()) - { - state |= ValidationState.Modified; + state |= ValidationState.Invalid; } + } - State = state; - - StateHasChanged(); + if (EditContext.IsModified()) + { + state |= ValidationState.Modified; } - protected override void AttachListener() + State = state; + + StateHasChanged(); + } + + protected override void AttachListener() + { + if (EditContext != null) { - if (EditContext != null) - { - EditContext.OnValidationStateChanged += ValidationStateChangeHandler; - EditContext.NotifyPropertyIncludedInForm(Property); + EditContext.OnValidationStateChanged += ValidationStateChangeHandler; + EditContext.NotifyPropertyIncludedInForm(Property); - State = ValidationState.NotValidated; - } + State = ValidationState.NotValidated; } + } - protected override void DetachListener() + protected override void DetachListener() + { + if (EditContext != null) { - if (EditContext != null) - { - EditContext.OnValidationStateChanged -= ValidationStateChangeHandler; - } + EditContext.OnValidationStateChanged -= ValidationStateChangeHandler; } } } diff --git a/src/RapidCMS.UI/Components/Editors/BaseMultiplePickerEditor.cs b/src/RapidCMS.UI/Components/Editors/BaseMultiplePickerEditor.cs index 3821cd55..7645b242 100644 --- a/src/RapidCMS.UI/Components/Editors/BaseMultiplePickerEditor.cs +++ b/src/RapidCMS.UI/Components/Editors/BaseMultiplePickerEditor.cs @@ -1,7 +1,6 @@ -namespace RapidCMS.UI.Components.Editors +namespace RapidCMS.UI.Components.Editors; + +public abstract class BaseMultiplePickerEditor : BasePicker { - public abstract class BaseMultiplePickerEditor : BasePicker - { - protected override bool IsMultiple { get; set; } = true; - } + protected override bool IsMultiple { get; set; } = true; } diff --git a/src/RapidCMS.UI/Components/Editors/BasePicker.cs b/src/RapidCMS.UI/Components/Editors/BasePicker.cs index 5c22a90a..a1af7648 100644 --- a/src/RapidCMS.UI/Components/Editors/BasePicker.cs +++ b/src/RapidCMS.UI/Components/Editors/BasePicker.cs @@ -8,169 +8,168 @@ using RapidCMS.Core.Abstractions.Data; using RapidCMS.Core.Models.Data; -namespace RapidCMS.UI.Components.Editors +namespace RapidCMS.UI.Components.Editors; + +public abstract class BasePicker : BaseDataEditor { - public abstract class BasePicker : BaseDataEditor - { - protected string? _searchTerm; - protected int _currentPage = 1; - protected int? _maxPage; + protected string? _searchTerm; + protected int _currentPage = 1; + protected int? _maxPage; - protected string _group = Guid.NewGuid().ToString("n"); - protected string ElementId => $"picker-{_group}"; + protected string _group = Guid.NewGuid().ToString("n"); + protected string ElementId => $"picker-{_group}"; - protected IEnumerable? _options; - protected List _selectedElements = new(); - protected CancellationTokenSource _cts = new(); + protected IEnumerable? _options; + protected List _selectedElements = new(); + protected CancellationTokenSource _cts = new(); - protected virtual bool IsMultiple { get; set; } + protected virtual bool IsMultiple { get; set; } - [Inject] - private IJSRuntime JsRuntime { get; set; } = null!; + [Inject] + private IJSRuntime JsRuntime { get; set; } = null!; - private IRelationDataCollection RelationDataCollection - => DataCollection as IRelationDataCollection - ?? throw new InvalidOperationException("Incorrect DataCollection assigned to Entity/iesPicker"); + private IRelationDataCollection RelationDataCollection + => DataCollection as IRelationDataCollection + ?? throw new InvalidOperationException("Incorrect DataCollection assigned to Entity/iesPicker"); - protected override async Task OnInitializedAsync() + protected override async Task OnInitializedAsync() + { + if (DataCollection != null) { - if (DataCollection != null) - { - DataCollection.OnDataChange += UpdateOptionsAsync; + DataCollection.OnDataChange += UpdateOptionsAsync; - await DataCollection.SetEntityAsync(EditContext, Property, Parent); - await UpdateOptionsAsync(); - } + await DataCollection.SetEntityAsync(EditContext, Property, Parent); + await UpdateOptionsAsync(); } + } - private async void UpdateOptionsAsync(object? sender, EventArgs args) + private async void UpdateOptionsAsync(object? sender, EventArgs args) + { + if (DataCollection == null) { - if (DataCollection == null) + return; + } + + await InvokeAsync(async () => + { + var currentValue = GetValueAsObject(); + + await UpdateOptionsAsync(); + + if (currentValue != null && _options != null && !_options.Any(x => x.Id.Equals(currentValue))) { - return; + await SetValueFromObjectAsync(default!); } - await InvokeAsync(async () => - { - var currentValue = GetValueAsObject(); + StateHasChanged(); + }); + } - await UpdateOptionsAsync(); + protected async Task PageChangedAsync(int page) + { + _currentPage = page; - if (currentValue != null && _options != null && !_options.Any(x => x.Id.Equals(currentValue))) - { - await SetValueFromObjectAsync(default!); - } + await UpdateOptionsAsync(); - StateHasChanged(); - }); - } + await JsRuntime.InvokeVoidAsync("RapidCMS.scrollToTop", ElementId); + } - protected async Task PageChangedAsync(int page) - { - _currentPage = page; + protected async Task ResetViewAsync() + { + _searchTerm = ""; + _currentPage = 1; + _maxPage = null; - await UpdateOptionsAsync(); + await UpdateOptionsAsync(); + } - await JsRuntime.InvokeVoidAsync("RapidCMS.scrollToTop", ElementId); + private async Task UpdateOptionsAsync() + { + if (DataCollection == null) + { + return; } - protected async Task ResetViewAsync() + var view = View.Create(25, _currentPage, _searchTerm, default); + _options = await DataCollection.GetAvailableElementsAsync(view); + + if (view.MoreDataAvailable) { - _searchTerm = ""; - _currentPage = 1; _maxPage = null; - - await UpdateOptionsAsync(); } - - private async Task UpdateOptionsAsync() + else { - if (DataCollection == null) - { - return; - } - - var view = View.Create(25, _currentPage, _searchTerm, default); - _options = await DataCollection.GetAvailableElementsAsync(view); - - if (view.MoreDataAvailable) - { - _maxPage = null; - } - else - { - _maxPage = _currentPage; - } + _maxPage = _currentPage; } + } - protected bool IsSelected(object id) + protected bool IsSelected(object id) + { + if (IsMultiple) { - if (IsMultiple) - { - return RelationDataCollection.IsRelated(id); - } - else - { - return GetValueAsObject()?.Equals(id) ?? false; - } + return RelationDataCollection.IsRelated(id); + } + else + { + return GetValueAsObject()?.Equals(id) ?? false; } + } - protected async Task SelectElementAsync(object id, bool? selected) + protected async Task SelectElementAsync(object id, bool? selected) + { + if (_options == null) { - if (_options == null) - { - return; - } + return; + } - if (IsMultiple) + if (IsMultiple) + { + if (!IsDisabled) { - if (!IsDisabled) + if (selected == true) { - if (selected == true) - { - RelationDataCollection.AddElement(id); - } - else - { - RelationDataCollection.RemoveElement(id); - } - - await EditContext.NotifyPropertyChangedAsync(Property); + RelationDataCollection.AddElement(id); } - } - else - { - await SetValueFromObjectAsync(id); + else + { + RelationDataCollection.RemoveElement(id); + } + + await EditContext.NotifyPropertyChangedAsync(Property); } } - - public override void Dispose() + else { - base.Dispose(); - - if (DataCollection != null) - { - DataCollection.OnDataChange -= UpdateOptionsAsync; - DataCollection.Dispose(); - } + await SetValueFromObjectAsync(id); } + } + + public override void Dispose() + { + base.Dispose(); - protected async void SearchAsync(string searchValue) + if (DataCollection != null) { - _cts.Cancel(); - _cts = new(); + DataCollection.OnDataChange -= UpdateOptionsAsync; + DataCollection.Dispose(); + } + } - await Task.Delay(300); + protected async void SearchAsync(string searchValue) + { + _cts.Cancel(); + _cts = new(); - if (!_cts.IsCancellationRequested) - { - _searchTerm = searchValue; - _currentPage = 1; + await Task.Delay(300); - await UpdateOptionsAsync(); + if (!_cts.IsCancellationRequested) + { + _searchTerm = searchValue; + _currentPage = 1; - StateHasChanged(); - } + await UpdateOptionsAsync(); + + StateHasChanged(); } } } diff --git a/src/RapidCMS.UI/Components/Editors/BasePropertyEditor.cs b/src/RapidCMS.UI/Components/Editors/BasePropertyEditor.cs index cdf5c5e3..07efa6eb 100644 --- a/src/RapidCMS.UI/Components/Editors/BasePropertyEditor.cs +++ b/src/RapidCMS.UI/Components/Editors/BasePropertyEditor.cs @@ -3,39 +3,38 @@ using System.Threading.Tasks; using RapidCMS.Core.Abstractions.Metadata; -namespace RapidCMS.UI.Components.Editors +namespace RapidCMS.UI.Components.Editors; + +public class BasePropertyEditor : BaseEditor { - public class BasePropertyEditor : BaseEditor + private new IFullPropertyMetadata Property { - private new IFullPropertyMetadata Property + get { - get - { - return base.Property as IFullPropertyMetadata ?? throw new InvalidOperationException($"{nameof(BasePropertyEditor)} requires usable Getter and Setter"); - } + return base.Property as IFullPropertyMetadata ?? throw new InvalidOperationException($"{nameof(BasePropertyEditor)} requires usable Getter and Setter"); } + } - protected async Task SetValueFromObjectAsync(object value) + protected async Task SetValueFromObjectAsync(object value) + { + if (!IsDisabled) { - if (!IsDisabled) - { - Property.Setter(Entity, value); - } - - await EditContext.NotifyPropertyChangedAsync(Property); + Property.Setter(Entity, value); } - protected async Task SetValueFromStringAsync(string value) + await EditContext.NotifyPropertyChangedAsync(Property); + } + + protected async Task SetValueFromStringAsync(string value) + { + if (Property.PropertyType == typeof(object)) + { + await SetValueFromObjectAsync(value); + } + else { - if (Property.PropertyType == typeof(object)) - { - await SetValueFromObjectAsync(value); - } - else - { - var obj = TypeDescriptor.GetConverter(Property.PropertyType).ConvertFromString(value); - await SetValueFromObjectAsync(obj!); - } + var obj = TypeDescriptor.GetConverter(Property.PropertyType).ConvertFromString(value); + await SetValueFromObjectAsync(obj!); } } } diff --git a/src/RapidCMS.UI/Components/Editors/BaseRelationEditor.cs b/src/RapidCMS.UI/Components/Editors/BaseRelationEditor.cs index e271cb5a..fa643c4b 100644 --- a/src/RapidCMS.UI/Components/Editors/BaseRelationEditor.cs +++ b/src/RapidCMS.UI/Components/Editors/BaseRelationEditor.cs @@ -1,12 +1,11 @@ using Microsoft.AspNetCore.Components; using RapidCMS.Core.Abstractions.Data; -namespace RapidCMS.UI.Components.Editors +namespace RapidCMS.UI.Components.Editors; + +public class BaseRelationEditor : BaseEditor { - public class BaseRelationEditor : BaseEditor - { - [Parameter] public IDataCollection? DataCollection { get; set; } + [Parameter] public IDataCollection? DataCollection { get; set; } - public IRelationDataCollection? RelationDataCollection => DataCollection as IRelationDataCollection; - } + public IRelationDataCollection? RelationDataCollection => DataCollection as IRelationDataCollection; } diff --git a/src/RapidCMS.UI/Components/Editors/FileUploadEditor.razor.cs b/src/RapidCMS.UI/Components/Editors/FileUploadEditor.razor.cs index b9d75fc7..f6e8c0d4 100644 --- a/src/RapidCMS.UI/Components/Editors/FileUploadEditor.razor.cs +++ b/src/RapidCMS.UI/Components/Editors/FileUploadEditor.razor.cs @@ -9,125 +9,124 @@ using Tewr.Blazor.FileReader; using FileInfoModel = RapidCMS.Core.Models.Data.FileInfo; -namespace RapidCMS.UI.Components.Editors +namespace RapidCMS.UI.Components.Editors; + +public partial class FileUploadEditor : BasePropertyEditor + where TFileUploadHandler : IFileUploadHandler + where TPreviewComponent : BasePreview { - public partial class FileUploadEditor : BasePropertyEditor - where TFileUploadHandler : IFileUploadHandler - where TPreviewComponent : BasePreview - { - protected ElementReference _fileInput; + protected ElementReference _fileInput; - protected double UploadCompletion { get; set; } = 0; + protected double UploadCompletion { get; set; } = 0; - [Inject] - protected TFileUploadHandler FileUploadHandler { get; set; } = default!; + [Inject] + protected TFileUploadHandler FileUploadHandler { get; set; } = default!; - [Inject] - protected IFileReaderService FileReaderService { get; set; } = default!; + [Inject] + protected IFileReaderService FileReaderService { get; set; } = default!; - protected virtual async Task OnFileSelectedAsync(ChangeEventArgs args) - { - EditContext.NotifyPropertyBusy(Property); + protected virtual async Task OnFileSelectedAsync(ChangeEventArgs args) + { + EditContext.NotifyPropertyBusy(Property); - UploadCompletion = 0.01; + UploadCompletion = 0.01; - var files = await FileReaderService.CreateReference(_fileInput).EnumerateFilesAsync(); - if (files.Count() > 1) - { - EditContext.AddValidationMessage(Property, "This editor only supports single files for now."); - } + var files = await FileReaderService.CreateReference(_fileInput).EnumerateFilesAsync(); + if (files.Count() > 1) + { + EditContext.AddValidationMessage(Property, "This editor only supports single files for now."); + } - var file = files.FirstOrDefault(); - if (file == null) - { - return; - } + var file = files.FirstOrDefault(); + if (file == null) + { + return; + } - var fileInfo = await file.ReadFileInfoAsync(); + var fileInfo = await file.ReadFileInfoAsync(); - IEnumerable validationMessages; - try - { - validationMessages = await FileUploadHandler.ValidateFileAsync(new FileInfoModel(fileInfo)); - } - catch - { - validationMessages = new[] { "Failed to validate file." }; - } + IEnumerable validationMessages; + try + { + validationMessages = await FileUploadHandler.ValidateFileAsync(new FileInfoModel(fileInfo)); + } + catch + { + validationMessages = new[] { "Failed to validate file." }; + } - if (!validationMessages.Any()) + if (!validationMessages.Any()) + { + try { - try + using var uploadedFile = await UploadFileToTempFileAsync(file, 8192, fileInfo.Size, (completion) => { - using var uploadedFile = await UploadFileToTempFileAsync(file, 8192, fileInfo.Size, (completion) => - { - Console.WriteLine(completion); + Console.WriteLine(completion); - if (completion - UploadCompletion > 1) - { - UploadCompletion = completion; - StateHasChanged(); - } - }); + if (completion - UploadCompletion > 1) + { + UploadCompletion = completion; + StateHasChanged(); + } + }); - UploadCompletion = 0.0; - StateHasChanged(); + UploadCompletion = 0.0; + StateHasChanged(); - var value = await FileUploadHandler.SaveFileAsync(new FileInfoModel(fileInfo), uploadedFile); + var value = await FileUploadHandler.SaveFileAsync(new FileInfoModel(fileInfo), uploadedFile); - await SetValueFromObjectAsync(value); + await SetValueFromObjectAsync(value); - EditContext.NotifyPropertyFinished(Property); - } - catch - { - validationMessages = new[] { "Failed to upload file." }; - } + EditContext.NotifyPropertyFinished(Property); } + catch + { + validationMessages = new[] { "Failed to upload file." }; + } + } - if (validationMessages.Any()) + if (validationMessages.Any()) + { + foreach (var message in validationMessages) { - foreach (var message in validationMessages) - { - EditContext.AddValidationMessage(Property, message); - } + EditContext.AddValidationMessage(Property, message); + } - EditContext.NotifyPropertyFinished(Property); + EditContext.NotifyPropertyFinished(Property); - UploadCompletion = 0.0; - StateHasChanged(); - return; - } + UploadCompletion = 0.0; + StateHasChanged(); + return; } + } - protected virtual async Task UploadFileToTempFileAsync( - IFileReference uploadedFile, - int bufferSize, - long fileSize, - Action progressCallback) - { - var bufferFileName = Path.GetTempFileName(); + protected virtual async Task UploadFileToTempFileAsync( + IFileReference uploadedFile, + int bufferSize, + long fileSize, + Action progressCallback) + { + var bufferFileName = Path.GetTempFileName(); - using (var fileHandle = File.OpenWrite(bufferFileName)) - { - using var fs = await uploadedFile.OpenReadAsync(); + using (var fileHandle = File.OpenWrite(bufferFileName)) + { + using var fs = await uploadedFile.OpenReadAsync(); - var buffer = new byte[bufferSize]; + var buffer = new byte[bufferSize]; - int count; - long totalCount = 0; - while ((count = await fs.ReadAsync(buffer, 0, buffer.Length)) != 0) - { - await fileHandle.WriteAsync(buffer, 0, count); + int count; + long totalCount = 0; + while ((count = await fs.ReadAsync(buffer, 0, buffer.Length)) != 0) + { + await fileHandle.WriteAsync(buffer, 0, count); - totalCount += count; + totalCount += count; - progressCallback.Invoke(100.0 * totalCount / fileSize); - } + progressCallback.Invoke(100.0 * totalCount / fileSize); } - - return File.OpenRead(bufferFileName); } + return File.OpenRead(bufferFileName); } + } diff --git a/src/RapidCMS.UI/Components/Editors/ModelEditor.razor.cs b/src/RapidCMS.UI/Components/Editors/ModelEditor.razor.cs index 8eb4d5cd..6ac22279 100644 --- a/src/RapidCMS.UI/Components/Editors/ModelEditor.razor.cs +++ b/src/RapidCMS.UI/Components/Editors/ModelEditor.razor.cs @@ -7,61 +7,60 @@ using RapidCMS.Core.Models.UI; using RapidCMS.Core.Navigation; -namespace RapidCMS.UI.Components.Editors -{ - public partial class ModelEditor - { - protected IEnumerable? Fields { get; set; } +namespace RapidCMS.UI.Components.Editors; - protected FormEditContext? PropertyEditContext { get; set; } +public partial class ModelEditor +{ + protected IEnumerable? Fields { get; set; } - [Inject] - private IUIResolverFactory UIResolverFactory { get; set; } = default!; + protected FormEditContext? PropertyEditContext { get; set; } - protected override async Task OnInitializedAsync() - { - PropertyEditContext = EditContext.EntityProperty(Property); + [Inject] + private IUIResolverFactory UIResolverFactory { get; set; } = default!; - var nodeUI = await UIResolverFactory.GetConventionNodeUIResolverAsync(Property.PropertyType); + protected override async Task OnInitializedAsync() + { + PropertyEditContext = EditContext.EntityProperty(Property); - var sections = await nodeUI.GetSectionsForEditContextAsync(PropertyEditContext, new NavigationState()); + var nodeUI = await UIResolverFactory.GetConventionNodeUIResolverAsync(Property.PropertyType); - Fields = sections.FirstOrDefault()?.Elements?.OfType(); + var sections = await nodeUI.GetSectionsForEditContextAsync(PropertyEditContext, new NavigationState()); - EditContext.OnValidationStateChanged += EditContext_OnValidationStateChangedAsync; - if (PropertyEditContext != null) - { - PropertyEditContext.OnValidationStateChanged += PropertyEditContext_OnValidationStateChangedAsync; - } + Fields = sections.FirstOrDefault()?.Elements?.OfType(); - await base.OnInitializedAsync(); + EditContext.OnValidationStateChanged += EditContext_OnValidationStateChangedAsync; + if (PropertyEditContext != null) + { + PropertyEditContext.OnValidationStateChanged += PropertyEditContext_OnValidationStateChangedAsync; } - protected override void DetachListener() - { - EditContext.OnValidationStateChanged -= EditContext_OnValidationStateChangedAsync; - if (PropertyEditContext != null) - { - PropertyEditContext.OnValidationStateChanged -= PropertyEditContext_OnValidationStateChangedAsync; - } + await base.OnInitializedAsync(); + } - base.DetachListener(); + protected override void DetachListener() + { + EditContext.OnValidationStateChanged -= EditContext_OnValidationStateChangedAsync; + if (PropertyEditContext != null) + { + PropertyEditContext.OnValidationStateChanged -= PropertyEditContext_OnValidationStateChangedAsync; } - private async void EditContext_OnValidationStateChangedAsync(object? sender, ValidationStateChangedEventArgs e) + base.DetachListener(); + } + + private async void EditContext_OnValidationStateChangedAsync(object? sender, ValidationStateChangedEventArgs e) + { + if (PropertyEditContext != null) { - if (PropertyEditContext != null) - { - await PropertyEditContext.IsValidAsync(); - } + await PropertyEditContext.IsValidAsync(); } + } - private async void PropertyEditContext_OnValidationStateChangedAsync(object? sender, ValidationStateChangedEventArgs e) + private async void PropertyEditContext_OnValidationStateChangedAsync(object? sender, ValidationStateChangedEventArgs e) + { + if (!EditContext.IsValid(Property) && e.IsValid == true) { - if (!EditContext.IsValid(Property) && e.IsValid == true) - { - await EditContext.IsValidAsync(); - } + await EditContext.IsValidAsync(); } } } diff --git a/src/RapidCMS.UI/Components/Pages/CmsPage.razor.cs b/src/RapidCMS.UI/Components/Pages/CmsPage.razor.cs index 44f1d18d..e027ba35 100644 --- a/src/RapidCMS.UI/Components/Pages/CmsPage.razor.cs +++ b/src/RapidCMS.UI/Components/Pages/CmsPage.razor.cs @@ -4,23 +4,22 @@ using RapidCMS.Core.Abstractions.Mediators; using RapidCMS.Core.Abstractions.Navigation; -namespace RapidCMS.UI.Components.Pages +namespace RapidCMS.UI.Components.Pages; + +[Authorize] +public partial class CmsPage { - [Authorize] - public partial class CmsPage - { - [Inject] private INavigationStateProvider NavigationState { get; set; } = default!; + [Inject] private INavigationStateProvider NavigationState { get; set; } = default!; - [Inject] private IMediator Mediator { get; set; } = default!; - [Inject] private NavigationManager NavigationManager { get; set; } = default!; - - [Parameter] public string? PageRoute { get; set; } + [Inject] private IMediator Mediator { get; set; } = default!; + [Inject] private NavigationManager NavigationManager { get; set; } = default!; + + [Parameter] public string? PageRoute { get; set; } - protected override void OnInitialized() - { - base.OnInitialized(); + protected override void OnInitialized() + { + base.OnInitialized(); - NavigationState.Initialize(PageRoute ?? "", new Uri(NavigationManager.Uri).Query); - } + NavigationState.Initialize(PageRoute ?? "", new Uri(NavigationManager.Uri).Query); } } diff --git a/src/RapidCMS.UI/Components/Panes/BaseSidePane.cs b/src/RapidCMS.UI/Components/Panes/BaseSidePane.cs index 47b2b079..c72e54bc 100644 --- a/src/RapidCMS.UI/Components/Panes/BaseSidePane.cs +++ b/src/RapidCMS.UI/Components/Panes/BaseSidePane.cs @@ -5,19 +5,18 @@ using RapidCMS.Core.Forms; using RapidCMS.Core.Models.EventArgs.Mediators; -namespace RapidCMS.UI.Components.Panes +namespace RapidCMS.UI.Components.Panes; + +public abstract class BaseSidePane : ComponentBase { - public abstract class BaseSidePane : ComponentBase - { - [Inject] private IMediator Mediator { get; set; } = default!; + [Inject] private IMediator Mediator { get; set; } = default!; - [Parameter] public FormEditContext? EditContext { get; set; } - [Parameter] public ButtonContext ButtonContext { get; set; } = default!; - [Parameter] public Guid RequestId { get; set; } = default!; + [Parameter] public FormEditContext? EditContext { get; set; } + [Parameter] public ButtonContext ButtonContext { get; set; } = default!; + [Parameter] public Guid RequestId { get; set; } = default!; - protected void ButtonClicked(CrudType crudType) - { - Mediator.NotifyEvent(this, new PaneResponseEventArgs(RequestId, crudType)); - } + protected void ButtonClicked(CrudType crudType) + { + Mediator.NotifyEvent(this, new PaneResponseEventArgs(RequestId, crudType)); } } diff --git a/src/RapidCMS.UI/Components/Panes/SidePane.razor.cs b/src/RapidCMS.UI/Components/Panes/SidePane.razor.cs index f5338e91..3d0047f9 100644 --- a/src/RapidCMS.UI/Components/Panes/SidePane.razor.cs +++ b/src/RapidCMS.UI/Components/Panes/SidePane.razor.cs @@ -3,47 +3,46 @@ using RapidCMS.Core.Abstractions.Mediators; using RapidCMS.Core.Models.EventArgs.Mediators; -namespace RapidCMS.UI.Components.Panes +namespace RapidCMS.UI.Components.Panes; + +public partial class SidePane { - public partial class SidePane - { - [Inject] private IMediator Mediator { get; set; } = default!; + [Inject] private IMediator Mediator { get; set; } = default!; - public RenderFragment? Component { get; set; } + public RenderFragment? Component { get; set; } - protected override void OnInitialized() - { - base.OnInitialized(); + protected override void OnInitialized() + { + base.OnInitialized(); - DisposeWhenDisposing(Mediator.RegisterCallback(OnPaneRequestedAsync)); - DisposeWhenDisposing(Mediator.RegisterCallback(OnPaneRespondedAsync)); - } + DisposeWhenDisposing(Mediator.RegisterCallback(OnPaneRequestedAsync)); + DisposeWhenDisposing(Mediator.RegisterCallback(OnPaneRespondedAsync)); + } - private async Task OnPaneRequestedAsync(object sender, PaneRequestEventArgs args) + private async Task OnPaneRequestedAsync(object sender, PaneRequestEventArgs args) + { + await InvokeAsync(() => { - await InvokeAsync(() => + Component = builder => { - Component = builder => - { - builder.OpenComponent(1, args.PaneType); - builder.AddAttribute(2, nameof(BaseSidePane.EditContext), args.EditContext); - builder.AddAttribute(3, nameof(BaseSidePane.ButtonContext), args.ButtonContext); - builder.AddAttribute(4, nameof(BaseSidePane.RequestId), args.RequestId); - builder.CloseComponent(); - }; - - StateHasChanged(); - }); - } - - private async Task OnPaneRespondedAsync(object sender, PaneResponseEventArgs args) + builder.OpenComponent(1, args.PaneType); + builder.AddAttribute(2, nameof(BaseSidePane.EditContext), args.EditContext); + builder.AddAttribute(3, nameof(BaseSidePane.ButtonContext), args.ButtonContext); + builder.AddAttribute(4, nameof(BaseSidePane.RequestId), args.RequestId); + builder.CloseComponent(); + }; + + StateHasChanged(); + }); + } + + private async Task OnPaneRespondedAsync(object sender, PaneResponseEventArgs args) + { + await InvokeAsync(() => { - await InvokeAsync(() => - { - Component = null; + Component = null; - StateHasChanged(); - }); - } + StateHasChanged(); + }); } } diff --git a/src/RapidCMS.UI/Components/Preview/BasePreview.cs b/src/RapidCMS.UI/Components/Preview/BasePreview.cs index dc35e778..272bcedb 100644 --- a/src/RapidCMS.UI/Components/Preview/BasePreview.cs +++ b/src/RapidCMS.UI/Components/Preview/BasePreview.cs @@ -3,11 +3,10 @@ using System.Text; using Microsoft.AspNetCore.Components; -namespace RapidCMS.UI.Components.Preview +namespace RapidCMS.UI.Components.Preview; + +public class BasePreview : ComponentBase { - public class BasePreview : ComponentBase - { - [Parameter] - public object? PreviewValue { get; set; } - } + [Parameter] + public object? PreviewValue { get; set; } } diff --git a/src/RapidCMS.UI/Components/Sections/BaseEditContextSection.cs b/src/RapidCMS.UI/Components/Sections/BaseEditContextSection.cs index 3257273b..ca551dc8 100644 --- a/src/RapidCMS.UI/Components/Sections/BaseEditContextSection.cs +++ b/src/RapidCMS.UI/Components/Sections/BaseEditContextSection.cs @@ -1,25 +1,24 @@ using Microsoft.AspNetCore.Components; using RapidCMS.Core.Models.UI; -namespace RapidCMS.UI.Components.Sections +namespace RapidCMS.UI.Components.Sections; + +public class BaseEditContextSection : EditContextComponentBase { - public class BaseEditContextSection : EditContextComponentBase - { - [Parameter] public SectionUI? Section { get; set; } + [Parameter] public SectionUI? Section { get; set; } - protected override void AttachListener() - { - EditContext.OnFieldChanged += EditContext_OnFieldChangedAsync; - } + protected override void AttachListener() + { + EditContext.OnFieldChanged += EditContext_OnFieldChangedAsync; + } - private async void EditContext_OnFieldChangedAsync(object? sender, Core.Forms.FieldChangedEventArgs e) - { - await InvokeAsync(() => StateHasChanged()); - } + private async void EditContext_OnFieldChangedAsync(object? sender, Core.Forms.FieldChangedEventArgs e) + { + await InvokeAsync(() => StateHasChanged()); + } - protected override void DetachListener() - { - EditContext.OnFieldChanged -= EditContext_OnFieldChangedAsync; - } + protected override void DetachListener() + { + EditContext.OnFieldChanged -= EditContext_OnFieldChangedAsync; } } diff --git a/src/RapidCMS.UI/Components/Sections/BasePageContextSection.cs b/src/RapidCMS.UI/Components/Sections/BasePageContextSection.cs index d0769ca6..e1f15b28 100644 --- a/src/RapidCMS.UI/Components/Sections/BasePageContextSection.cs +++ b/src/RapidCMS.UI/Components/Sections/BasePageContextSection.cs @@ -3,17 +3,16 @@ using RapidCMS.Core.Forms; using RapidCMS.Core.Models.UI; -namespace RapidCMS.UI.Components.Sections +namespace RapidCMS.UI.Components.Sections; + +/// +/// Use this section on pages nested in collections. +/// +public class BasePageContextSection : ComponentBase { - /// - /// Use this section on pages nested in collections. - /// - public class BasePageContextSection : ComponentBase - { - [Parameter] public SectionUI? Section { get; set; } + [Parameter] public SectionUI? Section { get; set; } - [CascadingParameter(Name = "PageContext")] public PageContext PageContext { get; set; } = default!; + [CascadingParameter(Name = "PageContext")] public PageContext PageContext { get; set; } = default!; - protected Guid SectionId { get; } = Guid.NewGuid(); - } + protected Guid SectionId { get; } = Guid.NewGuid(); } diff --git a/src/RapidCMS.UI/Components/Sections/BaseRootSection.cs b/src/RapidCMS.UI/Components/Sections/BaseRootSection.cs index 47a1b9f4..d3e295d4 100644 --- a/src/RapidCMS.UI/Components/Sections/BaseRootSection.cs +++ b/src/RapidCMS.UI/Components/Sections/BaseRootSection.cs @@ -20,174 +20,173 @@ using RapidCMS.Core.Models.UI; using RapidCMS.Core.Navigation; -namespace RapidCMS.UI.Components.Sections +namespace RapidCMS.UI.Components.Sections; + +public abstract partial class BaseRootSection : DisposableComponent { - public abstract partial class BaseRootSection : DisposableComponent - { - [Inject] protected ICms Cms { get; set; } = default!; - [Inject] protected IMediator Mediator { get; set; } = default!; - [Inject] private INavigationStateProvider NavigationStateProvider { get; set; } = default!; + [Inject] protected ICms Cms { get; set; } = default!; + [Inject] protected IMediator Mediator { get; set; } = default!; + [Inject] private INavigationStateProvider NavigationStateProvider { get; set; } = default!; - [Inject] protected IPresentationService PresentationService { get; set; } = default!; - [Inject] protected IInteractionService InteractionService { get; set; } = default!; - [Inject] protected IUIResolverFactory UIResolverFactory { get; set; } = default!; + [Inject] protected IPresentationService PresentationService { get; set; } = default!; + [Inject] protected IInteractionService InteractionService { get; set; } = default!; + [Inject] protected IUIResolverFactory UIResolverFactory { get; set; } = default!; - protected int Update { get; set; } = 0; + protected int Update { get; set; } = 0; - protected bool StateIsChanging { get; set; } = false; + protected bool StateIsChanging { get; set; } = false; - protected NavigationState CurrentNavigationState { get; private set; } = default!; + protected NavigationState CurrentNavigationState { get; private set; } = default!; - [Parameter] public NavigationState? InitialState { get; set; } + [Parameter] public NavigationState? InitialState { get; set; } - protected IEnumerable? Buttons { get; set; } - protected List<(FormEditContext editContext, IEnumerable sections)>? Sections { get; set; } - protected (PageContext? pageContext, IEnumerable? sections) PageContents { get; set; } + protected IEnumerable? Buttons { get; set; } + protected List<(FormEditContext editContext, IEnumerable sections)>? Sections { get; set; } + protected (PageContext? pageContext, IEnumerable? sections) PageContents { get; set; } - private CancellationTokenSource _loadCancellationTokenSource = new CancellationTokenSource(); + private CancellationTokenSource _loadCancellationTokenSource = new CancellationTokenSource(); - protected async Task HandleViewCommandAsync(Func> viewCommand) - where TViewCommandResponseModel : ViewCommandResponseModel + protected async Task HandleViewCommandAsync(Func> viewCommand) + where TViewCommandResponseModel : ViewCommandResponseModel + { + try { - try - { - StateIsChanging = true; + StateIsChanging = true; - var response = await viewCommand.Invoke(); + var response = await viewCommand.Invoke(); - if (response.NoOp) - { - return; - } - } - catch (Exception ex) - { - Mediator.NotifyEvent(this, new ExceptionEventArgs(ex)); - } - finally + if (response.NoOp) { - StateIsChanging = false; - StateHasChanged(); + return; } } - - protected override void OnInitialized() + catch (Exception ex) { - base.OnInitialized(); - - DisposeWhenDisposing(Mediator.RegisterCallback(OnRepositoryActionAsync)); - DisposeWhenDisposing(Mediator.RegisterCallback(OnExceptionAsync)); + Mediator.NotifyEvent(this, new ExceptionEventArgs(ex)); + } + finally + { + StateIsChanging = false; + StateHasChanged(); } + } + + protected override void OnInitialized() + { + base.OnInitialized(); - protected override async Task OnParametersSetAsync() + DisposeWhenDisposing(Mediator.RegisterCallback(OnRepositoryActionAsync)); + DisposeWhenDisposing(Mediator.RegisterCallback(OnExceptionAsync)); + } + + protected override async Task OnParametersSetAsync() + { + DisposeWhenDisposing(Mediator.RegisterCallback(OnNavigationAsync)); + + CurrentNavigationState = InitialState ?? NavigationStateProvider.GetCurrentState(); + + await LoadDataAsync(); + } + + protected async Task OnNavigationAsync(object sender, NavigationEventArgs args) + { + if ((InitialState == null && args.OldState == null) || CurrentNavigationState.Equals(args.OldState)) { - DisposeWhenDisposing(Mediator.RegisterCallback(OnNavigationAsync)); - - CurrentNavigationState = InitialState ?? NavigationStateProvider.GetCurrentState(); + CurrentNavigationState = args.NewState; await LoadDataAsync(); + + StateHasChanged(); } + } - protected async Task OnNavigationAsync(object sender, NavigationEventArgs args) - { - if ((InitialState == null && args.OldState == null) || CurrentNavigationState.Equals(args.OldState)) - { - CurrentNavigationState = args.NewState; + private async Task LoadDataAsync(IEnumerable? entityIds = null) + { + Update++; - await LoadDataAsync(); + CancelLoadAndRestart(); - StateHasChanged(); - } + if (CurrentNavigationState.PageType == PageType.Node) + { + await LoadNodeDataAsync(_loadCancellationTokenSource.Token); + } + else if (CurrentNavigationState.PageType == PageType.Collection) + { + await LoadCollectionDataAsync(_loadCancellationTokenSource.Token, entityIds); + } + else if (CurrentNavigationState.PageType == PageType.Page) + { + await LoadPageDataAsync(_loadCancellationTokenSource.Token); + } + else if (CurrentNavigationState.PageType == PageType.Dashboard) + { + await LoadPageDataAsync(_loadCancellationTokenSource.Token); } + } - private async Task LoadDataAsync(IEnumerable? entityIds = null) + private async Task OnRepositoryActionAsync(object sender, CollectionRepositoryEventArgs args) + { + if (!CurrentNavigationState.HasCollectionAlias || args.CollectionAlias != CurrentNavigationState.CollectionAlias) { - Update++; + return; + } - CancelLoadAndRestart(); + await InvokeAsync(() => LoadDataAsync()); + } - if (CurrentNavigationState.PageType == PageType.Node) + private async Task OnExceptionAsync(object sender, ExceptionEventArgs args) + { + await InvokeAsync(() => + { + if (args.Exception is UnauthorizedAccessException) { - await LoadNodeDataAsync(_loadCancellationTokenSource.Token); + NavigationStateProvider.ReplaceNavigationState(CurrentNavigationState, new NavigationState(PageType.Unauthorized)); } - else if (CurrentNavigationState.PageType == PageType.Collection) + else if (args.Exception is InvalidEntityException) { - await LoadCollectionDataAsync(_loadCancellationTokenSource.Token, entityIds); + Mediator.NotifyEvent(this, new MessageEventArgs(MessageType.Error, "Failed to perform action, Entity is in invalid state.")); } - else if (CurrentNavigationState.PageType == PageType.Page) + else if (!Cms.IsDevelopment) { - await LoadPageDataAsync(_loadCancellationTokenSource.Token); + Mediator.NotifyEvent(this, new MessageEventArgs(MessageType.Error, $"Failed to perform action: {args.Exception.Message}.")); } - else if (CurrentNavigationState.PageType == PageType.Dashboard) + else { - await LoadPageDataAsync(_loadCancellationTokenSource.Token); + NavigationStateProvider.ReplaceNavigationState(CurrentNavigationState, new NavigationState(PageType.Error)); } - } + }); + } - private async Task OnRepositoryActionAsync(object sender, CollectionRepositoryEventArgs args) + protected static RenderFragment RenderType(TypeRegistrationSetup section) + => builder => { - if (!CurrentNavigationState.HasCollectionAlias || args.CollectionAlias != CurrentNavigationState.CollectionAlias) - { - return; - } + var type = section.Type == typeof(ICollectionConfig) + ? typeof(RootSection) + : section.Type; - await InvokeAsync(() => LoadDataAsync()); - } + builder.OpenComponent(0, type); - private async Task OnExceptionAsync(object sender, ExceptionEventArgs args) - { - await InvokeAsync(() => + if (section.Parameters != null) { - if (args.Exception is UnauthorizedAccessException) - { - NavigationStateProvider.ReplaceNavigationState(CurrentNavigationState, new NavigationState(PageType.Unauthorized)); - } - else if (args.Exception is InvalidEntityException) + var index = 1; + section.Parameters.ForEach(kv => { - Mediator.NotifyEvent(this, new MessageEventArgs(MessageType.Error, "Failed to perform action, Entity is in invalid state.")); - } - else if (!Cms.IsDevelopment) - { - Mediator.NotifyEvent(this, new MessageEventArgs(MessageType.Error, $"Failed to perform action: {args.Exception.Message}.")); - } - else - { - NavigationStateProvider.ReplaceNavigationState(CurrentNavigationState, new NavigationState(PageType.Error)); - } - }); - } - - protected static RenderFragment RenderType(TypeRegistrationSetup section) - => builder => - { - var type = section.Type == typeof(ICollectionConfig) - ? typeof(RootSection) - : section.Type; - - builder.OpenComponent(0, type); - - if (section.Parameters != null) - { - var index = 1; - section.Parameters.ForEach(kv => - { - builder.AddAttribute(index++, kv.Key, kv.Value); - }); - } + builder.AddAttribute(index++, kv.Key, kv.Value); + }); + } - builder.CloseComponent(); - }; + builder.CloseComponent(); + }; - protected override bool ShouldRender() - { - return !StateIsChanging; - } + protected override bool ShouldRender() + { + return !StateIsChanging; + } - private void CancelLoadAndRestart() - { - var currentSource = _loadCancellationTokenSource; - _loadCancellationTokenSource = new CancellationTokenSource(); - currentSource.Cancel(); - } + private void CancelLoadAndRestart() + { + var currentSource = _loadCancellationTokenSource; + _loadCancellationTokenSource = new CancellationTokenSource(); + currentSource.Cancel(); } } diff --git a/src/RapidCMS.UI/Components/Sections/BaseRootSectionCollection.cs b/src/RapidCMS.UI/Components/Sections/BaseRootSectionCollection.cs index 30630b0a..57f4bcbb 100644 --- a/src/RapidCMS.UI/Components/Sections/BaseRootSectionCollection.cs +++ b/src/RapidCMS.UI/Components/Sections/BaseRootSectionCollection.cs @@ -15,327 +15,326 @@ using RapidCMS.Core.Navigation; using RapidCMS.UI.Models; -namespace RapidCMS.UI.Components.Sections +namespace RapidCMS.UI.Components.Sections; + +public abstract partial class BaseRootSection { - public abstract partial class BaseRootSection - { - protected ListContext? ListContext { get; set; } + protected ListContext? ListContext { get; set; } - protected IEnumerable? Tabs { get; set; } + protected IEnumerable? Tabs { get; set; } - protected ListUI? ListUI { get; set; } + protected ListUI? ListUI { get; set; } - private CollectionState CollectionState => CurrentNavigationState.CollectionState; + private CollectionState CollectionState => CurrentNavigationState.CollectionState; - protected async Task LoadCollectionDataAsync(CancellationToken cancellationToken, IEnumerable? reloadEntityIds = null) + protected async Task LoadCollectionDataAsync(CancellationToken cancellationToken, IEnumerable? reloadEntityIds = null) + { + var uiResolver = await UIResolverFactory.GetListUIResolverAsync(CurrentNavigationState); + + if (reloadEntityIds?.Any() == true) { - var uiResolver = await UIResolverFactory.GetListUIResolverAsync(CurrentNavigationState); + var sections = await ReloadSectionsAsync(reloadEntityIds, uiResolver); - if (reloadEntityIds?.Any() == true) + if (cancellationToken.IsCancellationRequested || ListContext == null) { - var sections = await ReloadSectionsAsync(reloadEntityIds, uiResolver); - - if (cancellationToken.IsCancellationRequested || ListContext == null) - { - return; - } - - ListContext.EditContexts.Clear(); - ListContext.EditContexts.AddRange(sections.Select(x => x.editContext)); - Sections = sections; + return; } - else - { - ListUI = null; - Buttons = null; - Tabs = null; - ListContext = null; - Sections = null; - var listUI = uiResolver.GetListDetails(); + ListContext.EditContexts.Clear(); + ListContext.EditContexts.AddRange(sections.Select(x => x.editContext)); + Sections = sections; + } + else + { + ListUI = null; + Buttons = null; + Tabs = null; + ListContext = null; + Sections = null; - var (listContext, sections, tabs) = await LoadSectionsAsync(listUI, uiResolver); + var listUI = uiResolver.GetListDetails(); - var buttons = await uiResolver.GetButtonsForEditContextAsync(listContext.ProtoEditContext); + var (listContext, sections, tabs) = await LoadSectionsAsync(listUI, uiResolver); - if (cancellationToken.IsCancellationRequested) - { - return; - } + var buttons = await uiResolver.GetButtonsForEditContextAsync(listContext.ProtoEditContext); - try - { - ListUI = listUI; - Buttons = buttons; - Tabs = tabs; - ListContext = listContext; - Sections = sections; - - PageContents = default; - } - catch - { - } + if (cancellationToken.IsCancellationRequested) + { + return; } - StateHasChanged(); - } + try + { + ListUI = listUI; + Buttons = buttons; + Tabs = tabs; + ListContext = listContext; + Sections = sections; - protected void SortChanged((int index, OrderByType direction) sort) - { - if (ListUI == null) + PageContents = default; + } + catch { - return; } + } - NavigationStateProvider.UpdateCollectionState(CurrentNavigationState, CollectionState with - { - CurrentPage = 1, - Sorts = (CollectionState.Sorts ?? new()).Add(sort.index, sort.direction) - }); + StateHasChanged(); + } + + protected void SortChanged((int index, OrderByType direction) sort) + { + if (ListUI == null) + { + return; } - protected void PageChanged(int page) + NavigationStateProvider.UpdateCollectionState(CurrentNavigationState, CollectionState with { - if (ListUI == null) - { - return; - } + CurrentPage = 1, + Sorts = (CollectionState.Sorts ?? new()).Add(sort.index, sort.direction) + }); + } - NavigationStateProvider.UpdateCollectionState(CurrentNavigationState, CollectionState with - { - CurrentPage = page - }); + protected void PageChanged(int page) + { + if (ListUI == null) + { + return; } - protected void Search(string? search) + NavigationStateProvider.UpdateCollectionState(CurrentNavigationState, CollectionState with { - if (ListUI == null) - { - return; - } + CurrentPage = page + }); + } - NavigationStateProvider.UpdateCollectionState(CurrentNavigationState, CollectionState with - { - CurrentPage = 1, - SearchTerm = search - }); + protected void Search(string? search) + { + if (ListUI == null) + { + return; } - protected void TabChange(int? tabId) + NavigationStateProvider.UpdateCollectionState(CurrentNavigationState, CollectionState with { - if (ListUI == null) - { - return; - } + CurrentPage = 1, + SearchTerm = search + }); + } - var tab = Tabs?.FirstOrDefault(x => x.Id == tabId); + protected void TabChange(int? tabId) + { + if (ListUI == null) + { + return; + } - NavigationStateProvider.UpdateCollectionState(CurrentNavigationState, CollectionState with + var tab = Tabs?.FirstOrDefault(x => x.Id == tabId); + + NavigationStateProvider.UpdateCollectionState(CurrentNavigationState, CollectionState with + { + ActiveTab = tabId, + CurrentPage = 1, + Sorts = tab?.DefaultSorts + }); + } + + protected async Task<(ListContext listContext, List<(FormEditContext editContext, IEnumerable sections)> sections, IEnumerable? tabs)> LoadSectionsAsync(ListUI listUI, IListUIResolver uiResolver) + { + var tabs = await uiResolver.GetTabsAsync(CurrentNavigationState.CollectionAlias); + if (tabs?.Count() > 0 && CollectionState.ActiveTab == null && tabs.First().DefaultSorts != null) + { + CurrentNavigationState.CollectionState = CurrentNavigationState.CollectionState with { - ActiveTab = tabId, + ActiveTab = tabs.First().Id, CurrentPage = 1, - Sorts = tab?.DefaultSorts - }); + Sorts = tabs.First().DefaultSorts + }; } - protected async Task<(ListContext listContext, List<(FormEditContext editContext, IEnumerable sections)> sections, IEnumerable? tabs)> LoadSectionsAsync(ListUI listUI, IListUIResolver uiResolver) - { - var tabs = await uiResolver.GetTabsAsync(CurrentNavigationState.CollectionAlias); - if (tabs?.Count() > 0 && CollectionState.ActiveTab == null && tabs.First().DefaultSorts != null) + var activeTab = tabs?.FirstOrDefault(x => x.Id == CollectionState.ActiveTab); + + var view = NavigationStateProvider.GetCurrentView(CurrentNavigationState, listUI, activeTab); + + var request = CurrentNavigationState.Related != null + ? (GetEntitiesRequestModel)new GetEntitiesOfRelationRequestModel { - CurrentNavigationState.CollectionState = CurrentNavigationState.CollectionState with - { - ActiveTab = tabs.First().Id, - CurrentPage = 1, - Sorts = tabs.First().DefaultSorts - }; + CollectionAlias = CurrentNavigationState.CollectionAlias, + View = view, + Related = CurrentNavigationState.Related, + UsageType = CurrentNavigationState.UsageType, + VariantAlias = CurrentNavigationState.VariantAlias, + IsEmbedded = !NavigationStateProvider.IsRootState(CurrentNavigationState) } + : (GetEntitiesRequestModel)new GetEntitiesOfParentRequestModel + { + CollectionAlias = CurrentNavigationState.CollectionAlias, + ParentPath = CurrentNavigationState.ParentPath, + View = view, + UsageType = CurrentNavigationState.UsageType, + VariantAlias = CurrentNavigationState.VariantAlias, + IsEmbedded = !NavigationStateProvider.IsRootState(CurrentNavigationState) + }; - var activeTab = tabs?.FirstOrDefault(x => x.Id == CollectionState.ActiveTab); + var listContext = await PresentationService.GetEntitiesAsync(request); - var view = NavigationStateProvider.GetCurrentView(CurrentNavigationState, listUI, activeTab); + var sections = await listContext.EditContexts.ToListAsync(async editContext => (editContext, await uiResolver.GetSectionsForEditContextAsync(editContext, CurrentNavigationState))); - var request = CurrentNavigationState.Related != null - ? (GetEntitiesRequestModel)new GetEntitiesOfRelationRequestModel - { - CollectionAlias = CurrentNavigationState.CollectionAlias, - View = view, - Related = CurrentNavigationState.Related, - UsageType = CurrentNavigationState.UsageType, - VariantAlias = CurrentNavigationState.VariantAlias, - IsEmbedded = !NavigationStateProvider.IsRootState(CurrentNavigationState) - } - : (GetEntitiesRequestModel)new GetEntitiesOfParentRequestModel - { - CollectionAlias = CurrentNavigationState.CollectionAlias, - ParentPath = CurrentNavigationState.ParentPath, - View = view, - UsageType = CurrentNavigationState.UsageType, - VariantAlias = CurrentNavigationState.VariantAlias, - IsEmbedded = !NavigationStateProvider.IsRootState(CurrentNavigationState) - }; + if (!NavigationStateProvider.TryProcessView(CurrentNavigationState, view, sections.Any() == true)) + { + return await LoadSectionsAsync(listUI, uiResolver); + } - var listContext = await PresentationService.GetEntitiesAsync(request); + return (listContext, sections, tabs); + } - var sections = await listContext.EditContexts.ToListAsync(async editContext => (editContext, await uiResolver.GetSectionsForEditContextAsync(editContext, CurrentNavigationState))); + protected async Task sections)>> ReloadSectionsAsync(IEnumerable reloadEntityIds, IListUIResolver uiResolver) + { + if (Sections == null) + { + return new List<(FormEditContext editContext, IEnumerable sections)>(); + } - if (!NavigationStateProvider.TryProcessView(CurrentNavigationState, view, sections.Any() == true)) + var newSections = await Sections.ToListAsync(async x => + { + if (reloadEntityIds.Contains(x.editContext.Entity.Id!)) + { + var reloadedEditContext = await PresentationService.GetEntityAsync(new GetEntityRequestModel + { + CollectionAlias = x.editContext.CollectionAlias, + Id = x.editContext.Entity.Id, + ParentPath = x.editContext.Parent?.GetParentPath(), + UsageType = x.editContext.UsageType, + VariantAlias = x.editContext.EntityVariantAlias + }); + + return (reloadedEditContext, await uiResolver.GetSectionsForEditContextAsync(reloadedEditContext, CurrentNavigationState)); + } + else { - return await LoadSectionsAsync(listUI, uiResolver); + return x; } + }); - return (listContext, sections, tabs); - } + return newSections; + } - protected async Task sections)>> ReloadSectionsAsync(IEnumerable reloadEntityIds, IListUIResolver uiResolver) + protected async Task ListButtonOnClickAsync(ButtonClickEventArgs args) + { + try { - if (Sections == null) + if (CurrentNavigationState == null) { - return new List<(FormEditContext editContext, IEnumerable sections)>(); + throw new InvalidOperationException(); } - var newSections = await Sections.ToListAsync(async x => + var request = new PersistEntitiesRequestModel { - if (reloadEntityIds.Contains(x.editContext.Entity.Id!)) - { - var reloadedEditContext = await PresentationService.GetEntityAsync(new GetEntityRequestModel - { - CollectionAlias = x.editContext.CollectionAlias, - Id = x.editContext.Entity.Id, - ParentPath = x.editContext.Parent?.GetParentPath(), - UsageType = x.editContext.UsageType, - VariantAlias = x.editContext.EntityVariantAlias - }); - - return (reloadedEditContext, await uiResolver.GetSectionsForEditContextAsync(reloadedEditContext, CurrentNavigationState)); - } - else - { - return x; - } - }); - - return newSections; + ActionId = args.ViewModel.ButtonId, + CustomData = args.Data, + ListContext = ListContext!, + Related = CurrentNavigationState.Related, + NavigationState = CurrentNavigationState + }; + + if (CurrentNavigationState.UsageType.HasFlag(UsageType.Edit)) + { + await HandleViewCommandAsync(() => InteractionService.InteractAsync(request)); + } + else + { + await HandleViewCommandAsync(() => InteractionService.InteractAsync(request)); + } } + catch (Exception ex) + { + Mediator.NotifyEvent(this, new ExceptionEventArgs(ex)); + } + } - protected async Task ListButtonOnClickAsync(ButtonClickEventArgs args) + protected async Task NodeButtonOnClickAsync(ButtonClickEventArgs args) + { + try { - try + if (CurrentNavigationState.Related != null) { - if (CurrentNavigationState == null) - { - throw new InvalidOperationException(); - } - - var request = new PersistEntitiesRequestModel + await HandleViewCommandAsync(() => InteractionService.InteractAsync(new PersistRelatedEntityRequestModel { ActionId = args.ViewModel.ButtonId, CustomData = args.Data, - ListContext = ListContext!, + EditContext = args.EditContext, Related = CurrentNavigationState.Related, NavigationState = CurrentNavigationState - }; - - if (CurrentNavigationState.UsageType.HasFlag(UsageType.Edit)) - { - await HandleViewCommandAsync(() => InteractionService.InteractAsync(request)); - } - else - { - await HandleViewCommandAsync(() => InteractionService.InteractAsync(request)); - } + })); } - catch (Exception ex) + else { - Mediator.NotifyEvent(this, new ExceptionEventArgs(ex)); + await HandleViewCommandAsync(() => InteractionService.InteractAsync(new PersistEntityRequestModel + { + ActionId = args.ViewModel.ButtonId, + CustomData = args.Data, + EditContext = args.EditContext, + NavigationState = CurrentNavigationState + })); } } - - protected async Task NodeButtonOnClickAsync(ButtonClickEventArgs args) + catch (Exception ex) { - try - { - if (CurrentNavigationState.Related != null) - { - await HandleViewCommandAsync(() => InteractionService.InteractAsync(new PersistRelatedEntityRequestModel - { - ActionId = args.ViewModel.ButtonId, - CustomData = args.Data, - EditContext = args.EditContext, - Related = CurrentNavigationState.Related, - NavigationState = CurrentNavigationState - })); - } - else - { - await HandleViewCommandAsync(() => InteractionService.InteractAsync(new PersistEntityRequestModel - { - ActionId = args.ViewModel.ButtonId, - CustomData = args.Data, - EditContext = args.EditContext, - NavigationState = CurrentNavigationState - })); - } - } - catch (Exception ex) - { - Mediator.NotifyEvent(this, new ExceptionEventArgs(ex)); - } + Mediator.NotifyEvent(this, new ExceptionEventArgs(ex)); } + } - protected void OnRowDragged(RowDragEventArgs args) + protected void OnRowDragged(RowDragEventArgs args) + { + try { - try + if (ListContext == null || Sections == null) { - if (ListContext == null || Sections == null) - { - throw new InvalidOperationException(); - } - - var beforeIds = ListContext.EditContexts.Select(x => x.Entity.Id).ToArray(); - var beforeSections = Sections.Select(x => x.editContext.Entity.Id).ToArray(); - - var subjectIndex = ListContext.EditContexts.FindIndex(x => x.Entity.Id == args.SubjectId); - var targetIndex = args.TargetId == null ? -1 : ListContext.EditContexts.FindIndex(x => x.Entity.Id == args.TargetId); - if (targetIndex > subjectIndex) - { - targetIndex--; - } + throw new InvalidOperationException(); + } - var editContext = ListContext.EditContexts.ElementAt(subjectIndex); - var section = Sections.ElementAt(subjectIndex); - if (editContext == null) - { - throw new InvalidOperationException(); - } + var beforeIds = ListContext.EditContexts.Select(x => x.Entity.Id).ToArray(); + var beforeSections = Sections.Select(x => x.editContext.Entity.Id).ToArray(); - editContext.NotifyReordered(args.TargetId); + var subjectIndex = ListContext.EditContexts.FindIndex(x => x.Entity.Id == args.SubjectId); + var targetIndex = args.TargetId == null ? -1 : ListContext.EditContexts.FindIndex(x => x.Entity.Id == args.TargetId); + if (targetIndex > subjectIndex) + { + targetIndex--; + } - ListContext.EditContexts.Remove(editContext); - Sections.Remove(section); + var editContext = ListContext.EditContexts.ElementAt(subjectIndex); + var section = Sections.ElementAt(subjectIndex); + if (editContext == null) + { + throw new InvalidOperationException(); + } - if (targetIndex == -1) - { - ListContext.EditContexts.Add(editContext); - Sections.Add(section); - } - else - { - ListContext.EditContexts.Insert(targetIndex, editContext); - Sections.Insert(targetIndex, section); - } + editContext.NotifyReordered(args.TargetId); - var afterIds = ListContext.EditContexts.Select(x => x.Entity.Id).ToArray(); - var afterSections = Sections.Select(x => x.editContext.Entity.Id).ToArray(); + ListContext.EditContexts.Remove(editContext); + Sections.Remove(section); - StateHasChanged(); + if (targetIndex == -1) + { + ListContext.EditContexts.Add(editContext); + Sections.Add(section); } - catch (Exception ex) + else { - Mediator.NotifyEvent(this, new ExceptionEventArgs(ex)); + ListContext.EditContexts.Insert(targetIndex, editContext); + Sections.Insert(targetIndex, section); } - } + var afterIds = ListContext.EditContexts.Select(x => x.Entity.Id).ToArray(); + var afterSections = Sections.Select(x => x.editContext.Entity.Id).ToArray(); + + StateHasChanged(); + } + catch (Exception ex) + { + Mediator.NotifyEvent(this, new ExceptionEventArgs(ex)); + } } + } diff --git a/src/RapidCMS.UI/Components/Sections/BaseRootSectionNode.cs b/src/RapidCMS.UI/Components/Sections/BaseRootSectionNode.cs index 450ff548..e0df579f 100644 --- a/src/RapidCMS.UI/Components/Sections/BaseRootSectionNode.cs +++ b/src/RapidCMS.UI/Components/Sections/BaseRootSectionNode.cs @@ -9,80 +9,79 @@ using RapidCMS.Core.Models.Response; using RapidCMS.UI.Models; -namespace RapidCMS.UI.Components.Sections +namespace RapidCMS.UI.Components.Sections; + +public abstract partial class BaseRootSection { - public abstract partial class BaseRootSection + protected async Task LoadNodeDataAsync(CancellationToken cancellationToken) { - protected async Task LoadNodeDataAsync(CancellationToken cancellationToken) + if (CurrentNavigationState == null) { - if (CurrentNavigationState == null) - { - throw new InvalidOperationException(); - } + throw new InvalidOperationException(); + } - Buttons = null; - Sections = null; + Buttons = null; + Sections = null; - var editContext = await PresentationService.GetEntityAsync(new GetEntityRequestModel - { - CollectionAlias = CurrentNavigationState.CollectionAlias, - Id = CurrentNavigationState.Id, - ParentPath = CurrentNavigationState.ParentPath, - UsageType = CurrentNavigationState.UsageType, - VariantAlias = CurrentNavigationState.VariantAlias - }); + var editContext = await PresentationService.GetEntityAsync(new GetEntityRequestModel + { + CollectionAlias = CurrentNavigationState.CollectionAlias, + Id = CurrentNavigationState.Id, + ParentPath = CurrentNavigationState.ParentPath, + UsageType = CurrentNavigationState.UsageType, + VariantAlias = CurrentNavigationState.VariantAlias + }); - var resolver = await UIResolverFactory.GetNodeUIResolverAsync(CurrentNavigationState); + var resolver = await UIResolverFactory.GetNodeUIResolverAsync(CurrentNavigationState); - var buttons = await resolver.GetButtonsForEditContextAsync(editContext); + var buttons = await resolver.GetButtonsForEditContextAsync(editContext); - var nodeSection = await resolver.GetSectionsForEditContextAsync(editContext, CurrentNavigationState); - var sections = new[] { (editContext, nodeSection) }.ToList(); + var nodeSection = await resolver.GetSectionsForEditContextAsync(editContext, CurrentNavigationState); + var sections = new[] { (editContext, nodeSection) }.ToList(); - if (cancellationToken.IsCancellationRequested) - { - return; - } - - try - { - Buttons = buttons; - Sections = sections; + if (cancellationToken.IsCancellationRequested) + { + return; + } - ListContext = null; - Tabs = null; - ListUI = null; - PageContents = default; - } - catch - { - } + try + { + Buttons = buttons; + Sections = sections; - StateHasChanged(); + ListContext = null; + Tabs = null; + ListUI = null; + PageContents = default; } - - protected async Task ButtonOnClickAsync(ButtonClickEventArgs args) + catch { - try - { - if (args.ViewModel == null) - { - throw new ArgumentException($"ViewModel required"); - } + } - await HandleViewCommandAsync( - () => InteractionService.InteractAsync(new PersistEntityRequestModel - { - ActionId = args.ViewModel.ButtonId, - CustomData = args.Data, - EditContext = args.EditContext, - NavigationState = CurrentNavigationState - })); - } - catch (Exception ex) + StateHasChanged(); + } + + protected async Task ButtonOnClickAsync(ButtonClickEventArgs args) + { + try + { + if (args.ViewModel == null) { - Mediator.NotifyEvent(this, new ExceptionEventArgs(ex)); + throw new ArgumentException($"ViewModel required"); } + + await HandleViewCommandAsync( + () => InteractionService.InteractAsync(new PersistEntityRequestModel + { + ActionId = args.ViewModel.ButtonId, + CustomData = args.Data, + EditContext = args.EditContext, + NavigationState = CurrentNavigationState + })); + } + catch (Exception ex) + { + Mediator.NotifyEvent(this, new ExceptionEventArgs(ex)); } } } diff --git a/src/RapidCMS.UI/Components/Sections/BaseRootSectionPage.cs b/src/RapidCMS.UI/Components/Sections/BaseRootSectionPage.cs index 27100f63..7ce9ed03 100644 --- a/src/RapidCMS.UI/Components/Sections/BaseRootSectionPage.cs +++ b/src/RapidCMS.UI/Components/Sections/BaseRootSectionPage.cs @@ -5,39 +5,38 @@ using RapidCMS.Core.Forms; using RapidCMS.Core.Models.Request.Form; -namespace RapidCMS.UI.Components.Sections +namespace RapidCMS.UI.Components.Sections; + +public abstract partial class BaseRootSection { - public abstract partial class BaseRootSection - { - protected async Task LoadPageDataAsync(CancellationToken cancellationToken) + protected async Task LoadPageDataAsync(CancellationToken cancellationToken) + { + if (CurrentNavigationState == null) { - if (CurrentNavigationState == null) - { - throw new InvalidOperationException(); - } - - PageContents = default; + throw new InvalidOperationException(); + } - var pageAlias = CurrentNavigationState.PageType == PageType.Dashboard - ? "__dashboard" - : CurrentNavigationState.CollectionAlias; + PageContents = default; - var pageContext = await PresentationService.GetEntityAsync(new GetEntityOfPageRequestModel - { - PageAlias = pageAlias, - ParentPath = CurrentNavigationState.ParentPath - }); + var pageAlias = CurrentNavigationState.PageType == PageType.Dashboard + ? "__dashboard" + : CurrentNavigationState.CollectionAlias; - var contents = await PresentationService.GetPageAsync(pageAlias); + var pageContext = await PresentationService.GetEntityAsync(new GetEntityOfPageRequestModel + { + PageAlias = pageAlias, + ParentPath = CurrentNavigationState.ParentPath + }); - if (cancellationToken.IsCancellationRequested) - { - return; - } + var contents = await PresentationService.GetPageAsync(pageAlias); - PageContents = (pageContext, contents); + if (cancellationToken.IsCancellationRequested) + { + return; } + + PageContents = (pageContext, contents); } } diff --git a/src/RapidCMS.UI/Components/Sections/BaseSection.cs b/src/RapidCMS.UI/Components/Sections/BaseSection.cs index 50173397..77280a46 100644 --- a/src/RapidCMS.UI/Components/Sections/BaseSection.cs +++ b/src/RapidCMS.UI/Components/Sections/BaseSection.cs @@ -2,15 +2,14 @@ using Microsoft.AspNetCore.Components; using RapidCMS.Core.Models.UI; -namespace RapidCMS.UI.Components.Sections +namespace RapidCMS.UI.Components.Sections; + +/// +/// Use this section on the dashboard and in pages nested in collections that do not require access to the entity. +/// +public class BaseSection : ComponentBase { - /// - /// Use this section on the dashboard and in pages nested in collections that do not require access to the entity. - /// - public class BaseSection : ComponentBase - { - [Parameter] public SectionUI? Section { get; set; } + [Parameter] public SectionUI? Section { get; set; } - protected Guid SectionId { get; } = Guid.NewGuid(); - } + protected Guid SectionId { get; } = Guid.NewGuid(); } diff --git a/src/RapidCMS.UI/Components/Sections/ErrorSection.razor b/src/RapidCMS.UI/Components/Sections/ErrorSection.razor index d9fc3e82..d78ddc0b 100644 --- a/src/RapidCMS.UI/Components/Sections/ErrorSection.razor +++ b/src/RapidCMS.UI/Components/Sections/ErrorSection.razor @@ -42,7 +42,7 @@ {

To enable exception view, set isDevelopment:

-
app.UseRapidCMS(isDevelopment: env.IsDevelopment());
+
services.AddRapidCMS(config => config.EnableDevelopmentLogging(true));
} } \ No newline at end of file diff --git a/src/RapidCMS.UI/Components/Sections/TableSection.razor b/src/RapidCMS.UI/Components/Sections/TableSection.razor index 968751a6..7d42f391 100644 --- a/src/RapidCMS.UI/Components/Sections/TableSection.razor +++ b/src/RapidCMS.UI/Components/Sections/TableSection.razor @@ -6,8 +6,6 @@ @{ if (CollapseEmptyCells && UI.CommonFields != null) { - var i = 0; - foreach (var field in UI.CommonFields) { diff --git a/src/RapidCMS.UI/Components/Shared/Tree/Collections.razor.cs b/src/RapidCMS.UI/Components/Shared/Tree/Collections.razor.cs index 9e2f1643..255733b4 100644 --- a/src/RapidCMS.UI/Components/Shared/Tree/Collections.razor.cs +++ b/src/RapidCMS.UI/Components/Shared/Tree/Collections.razor.cs @@ -8,71 +8,70 @@ using RapidCMS.Core.Models.EventArgs.Mediators; using RapidCMS.Core.Models.UI; -namespace RapidCMS.UI.Components.Shared.Tree +namespace RapidCMS.UI.Components.Shared.Tree; + +public partial class Collections { - public partial class Collections - { - [Inject] private ITreeService TreeService { get; set; } = default!; - [Inject] private IMediator Mediator { get; set; } = default!; + [Inject] private ITreeService TreeService { get; set; } = default!; + [Inject] private IMediator Mediator { get; set; } = default!; - [Parameter] public string CollectionAlias { get; set; } = default!; + [Parameter] public string CollectionAlias { get; set; } = default!; - [Parameter] public ParentPath? ParentPath { get; set; } = null; + [Parameter] public ParentPath? ParentPath { get; set; } = null; - private bool NodesVisible { get; set; } + private bool NodesVisible { get; set; } - private TreeCollectionUI? UI { get; set; } - private string? Error { get; set; } + private TreeCollectionUI? UI { get; set; } + private string? Error { get; set; } - protected override void OnInitialized() - { - base.OnInitialized(); + protected override void OnInitialized() + { + base.OnInitialized(); - DisposeWhenDisposing(Mediator.RegisterCallback(LocationChangedAsync)); - } + DisposeWhenDisposing(Mediator.RegisterCallback(LocationChangedAsync)); + } - protected override async Task OnParametersSetAsync() + protected override async Task OnParametersSetAsync() + { + try { - try - { - UI = await TreeService.GetCollectionAsync(CollectionAlias, ParentPath); + UI = await TreeService.GetCollectionAsync(CollectionAlias, ParentPath); - NodesVisible = NodesVisible || (UI?.DefaultOpenEntities ?? false); + NodesVisible = NodesVisible || (UI?.DefaultOpenEntities ?? false); - if (Mediator.GetLatestEventArgs() is NavigationEventArgs @event) - { - await LocationChangedAsync(this, @event); - } - } - catch (UnauthorizedAccessException) + if (Mediator.GetLatestEventArgs() is NavigationEventArgs @event) { - UI = TreeCollectionUI.None; + await LocationChangedAsync(this, @event); } - catch (Exception ex) - { - UI = null; - Error = ex.Message; - } - - StateHasChanged(); } + catch (UnauthorizedAccessException) + { + UI = TreeCollectionUI.None; + } + catch (Exception ex) + { + UI = null; + Error = ex.Message; + } + + StateHasChanged(); + } - private async Task LocationChangedAsync(object sender, NavigationEventArgs args) + private async Task LocationChangedAsync(object sender, NavigationEventArgs args) + { + if (sender is NavigationLink || UI == null || args.OldState != null || !args.NewState.HasCollectionAlias) { - if (sender is NavigationLink || UI == null || args.OldState != null || !args.NewState.HasCollectionAlias) - { - return; - } + return; + } - if ((ParentPath?.ToPathString() == args.NewState.ParentPath?.ToPathString() && args.NewState.CollectionAlias == CollectionAlias) || - ParentPath.IsBaseOf(args.NewState.ParentPath, UI.RepositoryAlias, default)) + if ((ParentPath?.ToPathString() == args.NewState.ParentPath?.ToPathString() && args.NewState.CollectionAlias == CollectionAlias) || + ParentPath.IsBaseOf(args.NewState.ParentPath, UI.RepositoryAlias, default)) + { + await InvokeAsync(() => { - await InvokeAsync(() => - { - NodesVisible = true; - StateHasChanged(); - }); - } + NodesVisible = true; + StateHasChanged(); + }); } } } diff --git a/src/RapidCMS.UI/Components/Shared/Tree/Nodes.razor.cs b/src/RapidCMS.UI/Components/Shared/Tree/Nodes.razor.cs index 26575b9e..82b81e71 100644 --- a/src/RapidCMS.UI/Components/Shared/Tree/Nodes.razor.cs +++ b/src/RapidCMS.UI/Components/Shared/Tree/Nodes.razor.cs @@ -10,111 +10,110 @@ using RapidCMS.Core.Models.EventArgs.Mediators; using RapidCMS.Core.Models.UI; -namespace RapidCMS.UI.Components.Shared.Tree +namespace RapidCMS.UI.Components.Shared.Tree; + +public partial class Nodes { - public partial class Nodes - { - private const int PageSize = 25; - private int _pageNr = 1; + private const int PageSize = 25; + private int _pageNr = 1; - private Dictionary? CollectionsVisible { get; set; } - private TreeNodesUI? UI { get; set; } - private string? Error { get; set; } - private bool Loading { get; set; } + private Dictionary? CollectionsVisible { get; set; } + private TreeNodesUI? UI { get; set; } + private string? Error { get; set; } + private bool Loading { get; set; } - [Inject] private ITreeService TreeService { get; set; } = default!; - [Inject] private IMediator Mediator { get; set; } = default!; + [Inject] private ITreeService TreeService { get; set; } = default!; + [Inject] private IMediator Mediator { get; set; } = default!; - [Parameter] public string CollectionAlias { get; set; } = default!; + [Parameter] public string CollectionAlias { get; set; } = default!; - [Parameter] public ParentPath? ParentPath { get; set; } = null; + [Parameter] public ParentPath? ParentPath { get; set; } = null; - protected override void OnInitialized() - { - base.OnInitialized(); + protected override void OnInitialized() + { + base.OnInitialized(); - DisposeWhenDisposing(Mediator.RegisterCallback(LocationChangedAsync)); - DisposeWhenDisposing(Mediator.RegisterCallback(RepositoryChangeAsync)); - } + DisposeWhenDisposing(Mediator.RegisterCallback(LocationChangedAsync)); + DisposeWhenDisposing(Mediator.RegisterCallback(RepositoryChangeAsync)); + } - protected override async Task OnParametersSetAsync() - { - await UpdateNodesAsync(); + protected override async Task OnParametersSetAsync() + { + await UpdateNodesAsync(); - if (Mediator.GetLatestEventArgs() is NavigationEventArgs @event) - { - await LocationChangedAsync(this, @event); - } + if (Mediator.GetLatestEventArgs() is NavigationEventArgs @event) + { + await LocationChangedAsync(this, @event); } + } - private async Task LocationChangedAsync(object sender, NavigationEventArgs args) + private async Task LocationChangedAsync(object sender, NavigationEventArgs args) + { + if (sender is NavigationLink || UI == null || CollectionsVisible == null || args.OldState != null || !args.NewState.HasCollectionAlias) { - if (sender is NavigationLink || UI == null || CollectionsVisible == null || args.OldState != null || !args.NewState.HasCollectionAlias) - { - return; - } - - foreach (var node in UI.Nodes) - { - if (ParentPath.IsBaseOf(args.NewState.ParentPath, node.RepositoryAlias, node.Id)) - { - await InvokeAsync(() => - { - CollectionsVisible[node.Id] = true; - StateHasChanged(); - }); - } - } + return; } - private async Task RepositoryChangeAsync(object sender, CollectionRepositoryEventArgs args) + foreach (var node in UI.Nodes) { - if (args.CollectionAlias == CollectionAlias) + if (ParentPath.IsBaseOf(args.NewState.ParentPath, node.RepositoryAlias, node.Id)) { - await InvokeAsync(async () => await UpdateNodesAsync()); + await InvokeAsync(() => + { + CollectionsVisible[node.Id] = true; + StateHasChanged(); + }); } } + } - private async Task OnPageChangeAsync(int delta) + private async Task RepositoryChangeAsync(object sender, CollectionRepositoryEventArgs args) + { + if (args.CollectionAlias == CollectionAlias) { - Loading = true; - _pageNr += delta; - await UpdateNodesAsync(); - Loading = false; + await InvokeAsync(async () => await UpdateNodesAsync()); } + } - private async Task UpdateNodesAsync() - { - var oldNodesVisible = CollectionsVisible; + private async Task OnPageChangeAsync(int delta) + { + Loading = true; + _pageNr += delta; + await UpdateNodesAsync(); + Loading = false; + } + + private async Task UpdateNodesAsync() + { + var oldNodesVisible = CollectionsVisible; - try + try + { + UI = await TreeService.GetNodesAsync(CollectionAlias, ParentPath, _pageNr, PageSize); + if (UI == null) { - UI = await TreeService.GetNodesAsync(CollectionAlias, ParentPath, _pageNr, PageSize); - if (UI == null) - { - return; - } + return; + } - CollectionsVisible = UI.Nodes.ToDictionary(x => x.Id, x => x.DefaultOpenCollections); + CollectionsVisible = UI.Nodes.ToDictionary(x => x.Id, x => x.DefaultOpenCollections); - // restore the view state with the new nodes - if (oldNodesVisible != null) + // restore the view state with the new nodes + if (oldNodesVisible != null) + { + foreach (var node in oldNodesVisible.Where(x => x.Value)) { - foreach (var node in oldNodesVisible.Where(x => x.Value)) + if (CollectionsVisible.ContainsKey(node.Key)) { - if (CollectionsVisible.ContainsKey(node.Key)) - { - CollectionsVisible[node.Key] = true; - } + CollectionsVisible[node.Key] = true; } } } - catch (Exception ex) - { - Error = ex.Message; - } - - StateHasChanged(); } + catch (Exception ex) + { + Error = ex.Message; + } + + StateHasChanged(); } } diff --git a/src/RapidCMS.UI/Components/Shared/Tree/Page.razor.cs b/src/RapidCMS.UI/Components/Shared/Tree/Page.razor.cs index 0373aabc..eb4aa1a4 100644 --- a/src/RapidCMS.UI/Components/Shared/Tree/Page.razor.cs +++ b/src/RapidCMS.UI/Components/Shared/Tree/Page.razor.cs @@ -4,29 +4,28 @@ using RapidCMS.Core.Models.Data; using RapidCMS.Core.Models.UI; -namespace RapidCMS.UI.Components.Shared.Tree +namespace RapidCMS.UI.Components.Shared.Tree; + +public partial class Page { - public partial class Page - { - [Parameter] public string PageAlias { get; set; } = default!; - [Parameter] public ParentPath? ParentPath { get; set; } = null; + [Parameter] public string PageAlias { get; set; } = default!; + [Parameter] public ParentPath? ParentPath { get; set; } = null; - private TreePageUI? UI { get; set; } - private string? Error { get; set; } + private TreePageUI? UI { get; set; } + private string? Error { get; set; } - protected override async Task OnParametersSetAsync() + protected override async Task OnParametersSetAsync() + { + try { - try - { - UI = await TreeService.GetPageAsync(PageAlias, ParentPath); - } - catch (Exception ex) - { - UI = null; - Error = ex.Message; - } - - StateHasChanged(); + UI = await TreeService.GetPageAsync(PageAlias, ParentPath); } + catch (Exception ex) + { + UI = null; + Error = ex.Message; + } + + StateHasChanged(); } } diff --git a/src/RapidCMS.UI/Extensions/ButtonUIExtensions.cs b/src/RapidCMS.UI/Extensions/ButtonUIExtensions.cs index 20a33127..9ac669e4 100644 --- a/src/RapidCMS.UI/Extensions/ButtonUIExtensions.cs +++ b/src/RapidCMS.UI/Extensions/ButtonUIExtensions.cs @@ -4,28 +4,27 @@ using RapidCMS.UI.Components.Buttons; using RapidCMS.UI.Models; -namespace RapidCMS.UI.Extensions +namespace RapidCMS.UI.Extensions; + +public static class ButtonUIExtensions { - public static class ButtonUIExtensions - { - public static ButtonViewModel ToViewModel(this ButtonUI button) - => new ButtonViewModel - { - ButtonId = button.ButtonId, - Icon = button.Icon ?? "", - Label = button.Label ?? "", - ShouldConfirm = button.ShouldConfirm, - IsPrimary = button.IsPrimary, - IsVisible = button.IsVisible ?? ((object o, EntityState s) => true), - RequiresValidForm = button.RequiresValidForm - }; + public static ButtonViewModel ToViewModel(this ButtonUI button) + => new ButtonViewModel + { + ButtonId = button.ButtonId, + Icon = button.Icon ?? "", + Label = button.Label ?? "", + ShouldConfirm = button.ShouldConfirm, + IsPrimary = button.IsPrimary, + IsVisible = button.IsVisible ?? ((object o, EntityState s) => true), + RequiresValidForm = button.RequiresValidForm + }; - public static RenderFragment ToRenderFragment(this ButtonUI button, ButtonViewModel model) - => builder => - { - builder.OpenComponent(0, button.CustomType ?? typeof(DefaultButton)); - builder.AddAttribute(1, nameof(DefaultButton.Model), model); - builder.CloseComponent(); - }; - } + public static RenderFragment ToRenderFragment(this ButtonUI button, ButtonViewModel model) + => builder => + { + builder.OpenComponent(0, button.CustomType ?? typeof(DefaultButton)); + builder.AddAttribute(1, nameof(DefaultButton.Model), model); + builder.CloseComponent(); + }; } diff --git a/src/RapidCMS.UI/Extensions/CustomRegistrationRenderFragmentExtensions.cs b/src/RapidCMS.UI/Extensions/CustomRegistrationRenderFragmentExtensions.cs index 2c92057a..0ad613f0 100644 --- a/src/RapidCMS.UI/Extensions/CustomRegistrationRenderFragmentExtensions.cs +++ b/src/RapidCMS.UI/Extensions/CustomRegistrationRenderFragmentExtensions.cs @@ -1,24 +1,23 @@ using Microsoft.AspNetCore.Components; using RapidCMS.Core.Models.Setup; -namespace RapidCMS.UI.Extensions +namespace RapidCMS.UI.Extensions; + +public static class CustomRegistrationRenderFragmentExtensions { - public static class CustomRegistrationRenderFragmentExtensions + public static RenderFragment? ToRenderFragment(this TypeRegistrationSetup? registration) { - public static RenderFragment? ToRenderFragment(this TypeRegistrationSetup? registration) + if (registration != null) { - if (registration != null) - { - return builder => - { - builder.OpenComponent(0, registration.Type); - builder.CloseComponent(); - }; - } - else + return builder => { - return default; - } + builder.OpenComponent(0, registration.Type); + builder.CloseComponent(); + }; + } + else + { + return default; } } } diff --git a/src/RapidCMS.UI/Extensions/DisplayTypeExtensions.cs b/src/RapidCMS.UI/Extensions/DisplayTypeExtensions.cs index 4d50ebef..4550d298 100644 --- a/src/RapidCMS.UI/Extensions/DisplayTypeExtensions.cs +++ b/src/RapidCMS.UI/Extensions/DisplayTypeExtensions.cs @@ -2,17 +2,16 @@ using RapidCMS.Core.Enums; using RapidCMS.UI.Components.Displays; -namespace RapidCMS.UI.Extensions +namespace RapidCMS.UI.Extensions; + +public static class DisplayTypeExtensions { - public static class DisplayTypeExtensions - { - public static Type? GetDisplay(this DisplayType displayType) - => displayType switch - { - DisplayType.Label => typeof(LabelDisplay), - DisplayType.Pre => typeof(PreDisplay), - DisplayType.Link => typeof(LinkDisplay), - _ => null - }; - } + public static Type? GetDisplay(this DisplayType displayType) + => displayType switch + { + DisplayType.Label => typeof(LabelDisplay), + DisplayType.Pre => typeof(PreDisplay), + DisplayType.Link => typeof(LinkDisplay), + _ => null + }; } diff --git a/src/RapidCMS.UI/Extensions/EditorTypeExtensions.cs b/src/RapidCMS.UI/Extensions/EditorTypeExtensions.cs index 755efe4c..03b56087 100644 --- a/src/RapidCMS.UI/Extensions/EditorTypeExtensions.cs +++ b/src/RapidCMS.UI/Extensions/EditorTypeExtensions.cs @@ -2,28 +2,27 @@ using RapidCMS.Core.Enums; using RapidCMS.UI.Components.Editors; -namespace RapidCMS.UI.Extensions +namespace RapidCMS.UI.Extensions; + +public static class EditorTypeExtensions { - public static class EditorTypeExtensions - { - public static Type? GetEditor(this EditorType editorType) - => editorType switch - { - EditorType.Checkbox => typeof(CheckboxEditor), - EditorType.Date => typeof(DateEditor), - EditorType.Dropdown => typeof(DropdownEditor), - EditorType.EnumFlagPicker => typeof(EnumFlagPicker), - EditorType.EntitiesPicker => typeof(EntitiesPicker), - EditorType.EntityPicker => typeof(EntityPicker), - EditorType.ListEditor => typeof(ListEditor), - EditorType.ModelEditor => typeof(ModelEditor), - EditorType.MultiSelect => typeof(MultiSelectEditor), - EditorType.Numeric => typeof(NumericEditor), - EditorType.Readonly => typeof(ReadonlyEditor), - EditorType.Select => typeof(SelectEditor), - EditorType.TextArea => typeof(TextAreaEditor), - EditorType.TextBox => typeof(TextBoxEditor), - _ => null - }; - } + public static Type? GetEditor(this EditorType editorType) + => editorType switch + { + EditorType.Checkbox => typeof(CheckboxEditor), + EditorType.Date => typeof(DateEditor), + EditorType.Dropdown => typeof(DropdownEditor), + EditorType.EnumFlagPicker => typeof(EnumFlagPicker), + EditorType.EntitiesPicker => typeof(EntitiesPicker), + EditorType.EntityPicker => typeof(EntityPicker), + EditorType.ListEditor => typeof(ListEditor), + EditorType.ModelEditor => typeof(ModelEditor), + EditorType.MultiSelect => typeof(MultiSelectEditor), + EditorType.Numeric => typeof(NumericEditor), + EditorType.Readonly => typeof(ReadonlyEditor), + EditorType.Select => typeof(SelectEditor), + EditorType.TextArea => typeof(TextAreaEditor), + EditorType.TextBox => typeof(TextBoxEditor), + _ => null + }; } diff --git a/src/RapidCMS.UI/Extensions/FieldUIExtensions.cs b/src/RapidCMS.UI/Extensions/FieldUIExtensions.cs index 0779e69d..fa9d0009 100644 --- a/src/RapidCMS.UI/Extensions/FieldUIExtensions.cs +++ b/src/RapidCMS.UI/Extensions/FieldUIExtensions.cs @@ -7,111 +7,110 @@ using RapidCMS.UI.Components.Displays; using RapidCMS.UI.Components.Editors; -namespace RapidCMS.UI.Extensions +namespace RapidCMS.UI.Extensions; + +public static class FieldUIExtensions { - public static class FieldUIExtensions + public static RenderFragment? ToRenderFragment(this FieldUI field, FormEditContext editContext, ListType usedInDisplayType) { - public static RenderFragment? ToRenderFragment(this FieldUI field, FormEditContext editContext, ListType usedInDisplayType) + if (field is CustomExpressionFieldUI customExpressionField) { - if (field is CustomExpressionFieldUI customExpressionField) + return builder => { - return builder => - { - var editorType = customExpressionField.CustomType; + var editorType = customExpressionField.CustomType; - builder.OpenComponent(0, editorType); + builder.OpenComponent(0, editorType); - builder.AddAttributes(editContext, customExpressionField, usedInDisplayType); + builder.AddAttributes(editContext, customExpressionField, usedInDisplayType); - builder.CloseComponent(); - }; - } - else if (field is ExpressionFieldUI expressionField) + builder.CloseComponent(); + }; + } + else if (field is ExpressionFieldUI expressionField) + { + var displayType = expressionField.Type.GetDisplay(); + if (displayType == null) { - var displayType = expressionField.Type.GetDisplay(); - if (displayType == null) - { - return null; - } + return null; + } - return builder => - { - builder.OpenComponent(0, displayType); + return builder => + { + builder.OpenComponent(0, displayType); - builder.AddAttributes(editContext, expressionField, usedInDisplayType); + builder.AddAttributes(editContext, expressionField, usedInDisplayType); - builder.CloseComponent(); - }; - } - else if (field is CustomPropertyFieldUI customPropertyField) + builder.CloseComponent(); + }; + } + else if (field is CustomPropertyFieldUI customPropertyField) + { + return builder => { - return builder => - { - var editorType = customPropertyField.CustomType; + var editorType = customPropertyField.CustomType; - builder.OpenComponent(0, editorType); + builder.OpenComponent(0, editorType); - builder.AddAttributes(editContext, customPropertyField, usedInDisplayType); + builder.AddAttributes(editContext, customPropertyField, usedInDisplayType); - if (editorType.IsSubclassOf(typeof(BaseDataEditor))) - { - builder.AddAttribute(9, nameof(BaseDataEditor.DataCollection), customPropertyField.DataCollection); - } + if (editorType.IsSubclassOf(typeof(BaseDataEditor))) + { + builder.AddAttribute(9, nameof(BaseDataEditor.DataCollection), customPropertyField.DataCollection); + } - builder.CloseComponent(); - }; + builder.CloseComponent(); + }; + } + else if (field is PropertyFieldUI propertyField) + { + var editorType = propertyField.Type.GetEditor(); + if (editorType == null) + { + return null; } - else if (field is PropertyFieldUI propertyField) + + return builder => { - var editorType = propertyField.Type.GetEditor(); - if (editorType == null) + builder.OpenComponent(0, editorType); + + builder.AddAttributes(editContext, propertyField, usedInDisplayType); + + if (editorType.IsSubclassOf(typeof(BaseDataEditor))) { - return null; + builder.AddAttribute(9, nameof(BaseDataEditor.DataCollection), propertyField.DataCollection); } - - return builder => + if (editorType.IsSubclassOf(typeof(BaseRelationEditor))) { - builder.OpenComponent(0, editorType); - - builder.AddAttributes(editContext, propertyField, usedInDisplayType); - - if (editorType.IsSubclassOf(typeof(BaseDataEditor))) - { - builder.AddAttribute(9, nameof(BaseDataEditor.DataCollection), propertyField.DataCollection); - } - if (editorType.IsSubclassOf(typeof(BaseRelationEditor))) - { - builder.AddAttribute(10, nameof(BaseRelationEditor.DataCollection), propertyField.DataCollection); - } - builder.CloseComponent(); - }; - } - else - { - throw new InvalidOperationException(); - } + builder.AddAttribute(10, nameof(BaseRelationEditor.DataCollection), propertyField.DataCollection); + } + builder.CloseComponent(); + }; } - - private static void AddAttributes(this RenderTreeBuilder builder, FormEditContext editContext, ExpressionFieldUI expressionField, ListType displayType) + else { - builder.AddAttribute(1, nameof(BaseDisplay.Entity), editContext.Entity); - builder.AddAttribute(2, nameof(BaseDisplay.EntityState), editContext.EntityState); - builder.AddAttribute(3, nameof(BaseDisplay.Parent), editContext.Parent); - builder.AddAttribute(4, nameof(BaseDisplay.Expression), expressionField.Expression); - builder.AddAttribute(5, nameof(BaseDisplay.DisplayType), displayType); - builder.AddAttribute(6, nameof(BaseDisplay.Configuration), expressionField.Configuration); + throw new InvalidOperationException(); } + } - private static void AddAttributes(this RenderTreeBuilder builder, FormEditContext editContext, PropertyFieldUI propertyField, ListType displayType) - { - builder.AddAttribute(1, nameof(BaseEditor.Entity), editContext.Entity); - builder.AddAttribute(2, nameof(BaseEditor.EntityState), editContext.EntityState); - builder.AddAttribute(3, nameof(BaseEditor.Parent), editContext.Parent); - builder.AddAttribute(4, nameof(BaseEditor.Property), propertyField.Property); - builder.AddAttribute(5, nameof(BaseEditor.IsDisabledFunc), propertyField.IsDisabled); - builder.AddAttribute(6, nameof(BaseEditor.Placeholder), propertyField.Placeholder); - builder.AddAttribute(7, nameof(BaseEditor.DisplayType), displayType); - builder.AddAttribute(8, nameof(BaseEditor.Configuration), propertyField.Configuration); - } + private static void AddAttributes(this RenderTreeBuilder builder, FormEditContext editContext, ExpressionFieldUI expressionField, ListType displayType) + { + builder.AddAttribute(1, nameof(BaseDisplay.Entity), editContext.Entity); + builder.AddAttribute(2, nameof(BaseDisplay.EntityState), editContext.EntityState); + builder.AddAttribute(3, nameof(BaseDisplay.Parent), editContext.Parent); + builder.AddAttribute(4, nameof(BaseDisplay.Expression), expressionField.Expression); + builder.AddAttribute(5, nameof(BaseDisplay.DisplayType), displayType); + builder.AddAttribute(6, nameof(BaseDisplay.Configuration), expressionField.Configuration); + } + + private static void AddAttributes(this RenderTreeBuilder builder, FormEditContext editContext, PropertyFieldUI propertyField, ListType displayType) + { + builder.AddAttribute(1, nameof(BaseEditor.Entity), editContext.Entity); + builder.AddAttribute(2, nameof(BaseEditor.EntityState), editContext.EntityState); + builder.AddAttribute(3, nameof(BaseEditor.Parent), editContext.Parent); + builder.AddAttribute(4, nameof(BaseEditor.Property), propertyField.Property); + builder.AddAttribute(5, nameof(BaseEditor.IsDisabledFunc), propertyField.IsDisabled); + builder.AddAttribute(6, nameof(BaseEditor.Placeholder), propertyField.Placeholder); + builder.AddAttribute(7, nameof(BaseEditor.DisplayType), displayType); + builder.AddAttribute(8, nameof(BaseEditor.Configuration), propertyField.Configuration); } } diff --git a/src/RapidCMS.UI/Extensions/SectionUIExtensions.cs b/src/RapidCMS.UI/Extensions/SectionUIExtensions.cs index 99a0cd78..ac2824db 100644 --- a/src/RapidCMS.UI/Extensions/SectionUIExtensions.cs +++ b/src/RapidCMS.UI/Extensions/SectionUIExtensions.cs @@ -2,26 +2,25 @@ using RapidCMS.Core.Models.UI; using RapidCMS.UI.Components.Sections; -namespace RapidCMS.UI.Extensions +namespace RapidCMS.UI.Extensions; + +public static class SectionUIExtensions { - public static class SectionUIExtensions + public static RenderFragment? ToRenderFragment(this SectionUI section) { - public static RenderFragment? ToRenderFragment(this SectionUI section) - { - if (section.CustomType == null) + if (section.CustomType == null) - { - return null; - } + { + return null; + } - return builder => - { - builder.OpenComponent(0, section.CustomType); + return builder => + { + builder.OpenComponent(0, section.CustomType); - builder.AddAttribute(1, nameof(BaseSection.Section), section); + builder.AddAttribute(1, nameof(BaseSection.Section), section); - builder.CloseComponent(); - }; - } + builder.CloseComponent(); + }; } } diff --git a/src/RapidCMS.UI/Helpers/CssHelper.cs b/src/RapidCMS.UI/Helpers/CssHelper.cs index 929307e6..416489a4 100644 --- a/src/RapidCMS.UI/Helpers/CssHelper.cs +++ b/src/RapidCMS.UI/Helpers/CssHelper.cs @@ -1,36 +1,35 @@ using RapidCMS.Core.Enums; -namespace RapidCMS.UI.Helpers +namespace RapidCMS.UI.Helpers; + +public static class CssHelper { - public static class CssHelper + public static string GetValidationClass(ValidationState state) { - public static string GetValidationClass(ValidationState state) - { - return $"{(state.HasFlag(ValidationState.Valid) ? "is-valid " : "")}" + - $"{(state.HasFlag(ValidationState.Invalid) ? "is-invalid " : "")}" + - $"{(state.HasFlag(ValidationState.Modified) ? "is-modified " : "")}"; - } + return $"{(state.HasFlag(ValidationState.Valid) ? "is-valid " : "")}" + + $"{(state.HasFlag(ValidationState.Invalid) ? "is-invalid " : "")}" + + $"{(state.HasFlag(ValidationState.Modified) ? "is-modified " : "")}"; + } - public static string GetMessageClass(MessageType type) + public static string GetMessageClass(MessageType type) + { + return "alert " + type switch { - return "alert " + type switch - { - MessageType.Error => "alert-danger", - MessageType.Information => "alert-info", - MessageType.Success => "alert-success", - MessageType.Warning => "alert-warning", - _ => "" - }; - } + MessageType.Error => "alert-danger", + MessageType.Information => "alert-info", + MessageType.Success => "alert-success", + MessageType.Warning => "alert-warning", + _ => "" + }; + } - public static string GetDisplayModifier(ListType type) + public static string GetDisplayModifier(ListType type) + { + return type switch { - return type switch - { - ListType.Block => "block", - ListType.Table => "table", - _ => "" - }; - } + ListType.Block => "block", + ListType.Table => "table", + _ => "" + }; } } diff --git a/src/RapidCMS.UI/Models/ButtonClickEventArgs.cs b/src/RapidCMS.UI/Models/ButtonClickEventArgs.cs index 50d95812..1c04d3e0 100644 --- a/src/RapidCMS.UI/Models/ButtonClickEventArgs.cs +++ b/src/RapidCMS.UI/Models/ButtonClickEventArgs.cs @@ -1,11 +1,10 @@ using RapidCMS.Core.Forms; -namespace RapidCMS.UI.Models +namespace RapidCMS.UI.Models; + +public class ButtonClickEventArgs { - public class ButtonClickEventArgs - { - public ButtonViewModel ViewModel { get; set; } = default!; - public FormEditContext EditContext { get; set; } = default!; - public object? Data { get; set; } - } + public ButtonViewModel ViewModel { get; set; } = default!; + public FormEditContext EditContext { get; set; } = default!; + public object? Data { get; set; } } diff --git a/src/RapidCMS.UI/Models/ButtonViewModel.cs b/src/RapidCMS.UI/Models/ButtonViewModel.cs index a42b9835..794575e7 100644 --- a/src/RapidCMS.UI/Models/ButtonViewModel.cs +++ b/src/RapidCMS.UI/Models/ButtonViewModel.cs @@ -5,34 +5,33 @@ using RapidCMS.Core.Enums; using RapidCMS.Core.Forms; -namespace RapidCMS.UI.Models +namespace RapidCMS.UI.Models; + +public class ButtonViewModel { - public class ButtonViewModel - { - public EventCallback? OnClick { get; set; } + public EventCallback? OnClick { get; set; } - public async Task NotifyClickAsync(FormEditContext editContext, object? customData) + public async Task NotifyClickAsync(FormEditContext editContext, object? customData) + { + var task = OnClick?.InvokeAsync(new ButtonClickEventArgs { - var task = OnClick?.InvokeAsync(new ButtonClickEventArgs - { - ViewModel = this, - EditContext = editContext, - Data = customData - }); + ViewModel = this, + EditContext = editContext, + Data = customData + }); - if (task != null) - { - await task; - } + if (task != null) + { + await task; } + } - public string Label { get; set; } = default!; - public string Icon { get; set; } = default!; - public string ButtonId { get; set; } = default!; + public string Label { get; set; } = default!; + public string Icon { get; set; } = default!; + public string ButtonId { get; set; } = default!; - public bool ShouldConfirm { get; set; } - public bool IsPrimary { get; set; } - public Func IsVisible { get; set; } = default!; - public bool RequiresValidForm { get; set; } - } + public bool ShouldConfirm { get; set; } + public bool IsPrimary { get; set; } + public Func IsVisible { get; set; } = default!; + public bool RequiresValidForm { get; set; } } diff --git a/src/RapidCMS.UI/RapidCMS.UI.csproj b/src/RapidCMS.UI/RapidCMS.UI.csproj index 1a2bd428..5480827b 100644 --- a/src/RapidCMS.UI/RapidCMS.UI.csproj +++ b/src/RapidCMS.UI/RapidCMS.UI.csproj @@ -1,8 +1,7 @@  - net6.0 - 10.0 + net6.0;net8.0 enable Thomas Bleijendaal Thomas Bleijendaal @@ -36,11 +35,17 @@ - + + + + + + + True diff --git a/src/RapidCMS.sln b/src/RapidCMS.sln index aad5dc7f..33d77de0 100644 --- a/src/RapidCMS.sln +++ b/src/RapidCMS.sln @@ -28,14 +28,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "misc", "misc", "{89191FB4-6 ..\.github\workflows\dotnetcore.pr.yml = ..\.github\workflows\dotnetcore.pr.yml ..\.github\workflows\dotnetcore.yml = ..\.github\workflows\dotnetcore.yml ..\LICENSE.md = ..\LICENSE.md - ..\MMQUICKSTART.md = ..\MMQUICKSTART.md ..\QUICKSTART.md = ..\QUICKSTART.md ..\README.md = ..\README.md ..\SETUP_CLIENTSIDE.md = ..\SETUP_CLIENTSIDE.md ..\SETUP_COMPANION.md = ..\SETUP_COMPANION.md - ..\SETUP_MAUI.md = ..\SETUP_MAUI.md - ..\SETUP_MMCLIENTSIDE.md = ..\SETUP_MMCLIENTSIDE.md - ..\SETUP_MMSERVERSIDE.md = ..\SETUP_MMSERVERSIDE.md ..\SETUP_SERVERSIDE.md = ..\SETUP_SERVERSIDE.md EndProjectSection EndProject @@ -51,30 +47,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RapidCMS.Api.Functions", "R EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RapidCMS.Api.Core", "RapidCMS.Api.Core\RapidCMS.Api.Core.csproj", "{5629643B-3CE9-4E1D-88E5-5874E505E2D0}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RapidCMS.Example.ModelMaker", "..\examples\RapidCMS.Example.ModelMaker\RapidCMS.Example.ModelMaker.csproj", "{3D93A843-1372-496E-8089-CE3EC52AB935}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RapidCMS.ModelMaker", "RapidCMS.ModelMaker\RapidCMS.ModelMaker.csproj", "{8C7D70C8-CAC6-4774-8C62-0684349E7D9F}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RapidCMS.ModelMaker.SourceGenerator", "RapidCMS.ModelMaker.SourceGenerator\RapidCMS.ModelMaker.SourceGenerator.csproj", "{FB68633B-94D5-4017-AD53-5A54518A1C9A}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RapidCMS.ModelMaker.SourceGenerator.EFCore", "RapidCMS.ModelMaker.SourceGenerator.EFCore\RapidCMS.ModelMaker.SourceGenerator.EFCore.csproj", "{DFE45154-AD85-44F8-9FBF-B463D969767B}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RapidCMS.UI.PublishableEntity", "RapidCMS.UI.PublishableEntity\RapidCMS.UI.PublishableEntity.csproj", "{ED772F90-7EB2-4B2D-B0CD-C28653DF2A8B}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RapidCMS.Example.ModelMaker.WebAssembly", "..\examples\RapidCMS.Example.ModelMaker.WebAssembly\RapidCMS.Example.ModelMaker.WebAssembly.csproj", "{9F9B0617-C168-4120-BBFB-F2C17538A7E6}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RapidCMS.Example.ModelMaker.WebAssembly.API", "..\examples\RapidCMS.Example.ModelMaker.WebAssembly.API\RapidCMS.Example.ModelMaker.WebAssembly.API.csproj", "{CF0ACFB8-FBDE-435D-BB01-D753A55B801A}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RapidCMS.Example.ModelMaker.Models", "..\examples\RapidCMS.Example.ModelMaker.Models\RapidCMS.Example.ModelMaker.Models.csproj", "{D2BFA04D-D422-48AB-8C67-B0E3F51655B9}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "demo", "demo", "{53A342E3-BC40-4721-9F8B-D259395607B6}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "rapidcms", "rapidcms", "{653FF181-27AD-43DB-98D7-E90CBD6F3734}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "modelmaker", "modelmaker", "{936CE7DE-29E7-49AE-981E-E4E11930F28A}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ModelMaker", "ModelMaker", "{AC86C3F3-93F9-4E87-AF88-2D045938E7AD}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "API", "API", "{A569FC39-2B72-4781-AFE3-D99B13D9A353}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UI", "UI", "{8976A00E-78C1-49F4-9B0A-EA0FA52E26A1}" @@ -83,10 +59,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CMS", "CMS", "{3D3FFBF3-B12 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RapidCMS.Core.Tests", "RapidCMS.Core.Tests\RapidCMS.Core.Tests.csproj", "{6B1E66A3-891B-45C4-A586-2A5DD82E8CD4}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests", "RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests\RapidCMS.ModelMaker.SourceGenerator.EFCore.Tests.csproj", "{C12B7DE5-75CB-49EA-B562-BC8431F934F1}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RapidCMS.Example.Maui", "..\examples\RapidCMS.Example.Maui\RapidCMS.Example.Maui.csproj", "{AB3CDC2A-D1AC-49DA-B1F2-10D8BB393C8B}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -141,51 +113,10 @@ Global {5629643B-3CE9-4E1D-88E5-5874E505E2D0}.Debug|Any CPU.Build.0 = Debug|Any CPU {5629643B-3CE9-4E1D-88E5-5874E505E2D0}.Release|Any CPU.ActiveCfg = Release|Any CPU {5629643B-3CE9-4E1D-88E5-5874E505E2D0}.Release|Any CPU.Build.0 = Release|Any CPU - {3D93A843-1372-496E-8089-CE3EC52AB935}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3D93A843-1372-496E-8089-CE3EC52AB935}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3D93A843-1372-496E-8089-CE3EC52AB935}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3D93A843-1372-496E-8089-CE3EC52AB935}.Release|Any CPU.Build.0 = Release|Any CPU - {8C7D70C8-CAC6-4774-8C62-0684349E7D9F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8C7D70C8-CAC6-4774-8C62-0684349E7D9F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8C7D70C8-CAC6-4774-8C62-0684349E7D9F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8C7D70C8-CAC6-4774-8C62-0684349E7D9F}.Release|Any CPU.Build.0 = Release|Any CPU - {FB68633B-94D5-4017-AD53-5A54518A1C9A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FB68633B-94D5-4017-AD53-5A54518A1C9A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FB68633B-94D5-4017-AD53-5A54518A1C9A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FB68633B-94D5-4017-AD53-5A54518A1C9A}.Release|Any CPU.Build.0 = Release|Any CPU - {DFE45154-AD85-44F8-9FBF-B463D969767B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DFE45154-AD85-44F8-9FBF-B463D969767B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DFE45154-AD85-44F8-9FBF-B463D969767B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DFE45154-AD85-44F8-9FBF-B463D969767B}.Release|Any CPU.Build.0 = Release|Any CPU - {ED772F90-7EB2-4B2D-B0CD-C28653DF2A8B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {ED772F90-7EB2-4B2D-B0CD-C28653DF2A8B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {ED772F90-7EB2-4B2D-B0CD-C28653DF2A8B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {ED772F90-7EB2-4B2D-B0CD-C28653DF2A8B}.Release|Any CPU.Build.0 = Release|Any CPU - {9F9B0617-C168-4120-BBFB-F2C17538A7E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9F9B0617-C168-4120-BBFB-F2C17538A7E6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9F9B0617-C168-4120-BBFB-F2C17538A7E6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9F9B0617-C168-4120-BBFB-F2C17538A7E6}.Release|Any CPU.Build.0 = Release|Any CPU - {CF0ACFB8-FBDE-435D-BB01-D753A55B801A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CF0ACFB8-FBDE-435D-BB01-D753A55B801A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CF0ACFB8-FBDE-435D-BB01-D753A55B801A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CF0ACFB8-FBDE-435D-BB01-D753A55B801A}.Release|Any CPU.Build.0 = Release|Any CPU - {D2BFA04D-D422-48AB-8C67-B0E3F51655B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D2BFA04D-D422-48AB-8C67-B0E3F51655B9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D2BFA04D-D422-48AB-8C67-B0E3F51655B9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D2BFA04D-D422-48AB-8C67-B0E3F51655B9}.Release|Any CPU.Build.0 = Release|Any CPU {6B1E66A3-891B-45C4-A586-2A5DD82E8CD4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6B1E66A3-891B-45C4-A586-2A5DD82E8CD4}.Debug|Any CPU.Build.0 = Debug|Any CPU {6B1E66A3-891B-45C4-A586-2A5DD82E8CD4}.Release|Any CPU.ActiveCfg = Release|Any CPU {6B1E66A3-891B-45C4-A586-2A5DD82E8CD4}.Release|Any CPU.Build.0 = Release|Any CPU - {C12B7DE5-75CB-49EA-B562-BC8431F934F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C12B7DE5-75CB-49EA-B562-BC8431F934F1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C12B7DE5-75CB-49EA-B562-BC8431F934F1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C12B7DE5-75CB-49EA-B562-BC8431F934F1}.Release|Any CPU.Build.0 = Release|Any CPU - {AB3CDC2A-D1AC-49DA-B1F2-10D8BB393C8B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AB3CDC2A-D1AC-49DA-B1F2-10D8BB393C8B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AB3CDC2A-D1AC-49DA-B1F2-10D8BB393C8B}.Debug|Any CPU.Deploy.0 = Debug|Any CPU - {AB3CDC2A-D1AC-49DA-B1F2-10D8BB393C8B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AB3CDC2A-D1AC-49DA-B1F2-10D8BB393C8B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -203,24 +134,12 @@ Global {2B04E2EB-14FB-4F24-AB21-77E84A8FB2D7} = {653FF181-27AD-43DB-98D7-E90CBD6F3734} {740B2F9E-7CA4-4539-95F3-1F9839C92C32} = {A569FC39-2B72-4781-AFE3-D99B13D9A353} {5629643B-3CE9-4E1D-88E5-5874E505E2D0} = {A569FC39-2B72-4781-AFE3-D99B13D9A353} - {3D93A843-1372-496E-8089-CE3EC52AB935} = {936CE7DE-29E7-49AE-981E-E4E11930F28A} - {8C7D70C8-CAC6-4774-8C62-0684349E7D9F} = {AC86C3F3-93F9-4E87-AF88-2D045938E7AD} - {FB68633B-94D5-4017-AD53-5A54518A1C9A} = {AC86C3F3-93F9-4E87-AF88-2D045938E7AD} - {DFE45154-AD85-44F8-9FBF-B463D969767B} = {AC86C3F3-93F9-4E87-AF88-2D045938E7AD} - {ED772F90-7EB2-4B2D-B0CD-C28653DF2A8B} = {8976A00E-78C1-49F4-9B0A-EA0FA52E26A1} - {9F9B0617-C168-4120-BBFB-F2C17538A7E6} = {936CE7DE-29E7-49AE-981E-E4E11930F28A} - {CF0ACFB8-FBDE-435D-BB01-D753A55B801A} = {936CE7DE-29E7-49AE-981E-E4E11930F28A} - {D2BFA04D-D422-48AB-8C67-B0E3F51655B9} = {936CE7DE-29E7-49AE-981E-E4E11930F28A} {53A342E3-BC40-4721-9F8B-D259395607B6} = {D5C8E316-AA29-4FB7-A99D-F1047DCC10BE} {653FF181-27AD-43DB-98D7-E90CBD6F3734} = {D5C8E316-AA29-4FB7-A99D-F1047DCC10BE} - {936CE7DE-29E7-49AE-981E-E4E11930F28A} = {D5C8E316-AA29-4FB7-A99D-F1047DCC10BE} - {AC86C3F3-93F9-4E87-AF88-2D045938E7AD} = {FAEBCE99-5CCB-4BBF-AAF3-9CE51FABD871} {A569FC39-2B72-4781-AFE3-D99B13D9A353} = {FAEBCE99-5CCB-4BBF-AAF3-9CE51FABD871} {8976A00E-78C1-49F4-9B0A-EA0FA52E26A1} = {FAEBCE99-5CCB-4BBF-AAF3-9CE51FABD871} {3D3FFBF3-B128-4738-A086-812392A81150} = {FAEBCE99-5CCB-4BBF-AAF3-9CE51FABD871} {6B1E66A3-891B-45C4-A586-2A5DD82E8CD4} = {A1ABBF0C-890B-43E6-AD6D-F1897CA205B6} - {C12B7DE5-75CB-49EA-B562-BC8431F934F1} = {A1ABBF0C-890B-43E6-AD6D-F1897CA205B6} - {AB3CDC2A-D1AC-49DA-B1F2-10D8BB393C8B} = {653FF181-27AD-43DB-98D7-E90CBD6F3734} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {A24D735F-6ECC-4089-B6BF-DB09B1FCB7D8}