diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index f24ba57949..5c464400cc 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -2,8 +2,12 @@ name: Pull request labeler on: schedule: - cron: '0 12 */1 * *' +permissions: + contents: read jobs: labeler: + permissions: + pull-requests: write runs-on: ubuntu-latest steps: - uses: paulfantom/periodic-labeler@master diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json index 98f6ed0820..b0555bfe32 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json @@ -177,6 +177,8 @@ "CheckAllCommunityTalks": "Check All Community Posts", "ReadMore": "Read More", "Post": "Post", - "ExploreTheContentsCreatedByTheCoreABPTeamAndTheABPCommunity": "Explore the contents created by the core ABP team and the ABP community." + "ExploreTheContentsCreatedByTheCoreABPTeamAndTheABPCommunity": "Explore the contents created by the core ABP team and the ABP community.", + "WelcomeFallCampaign": "Welcome Fall Campaign!", + "GiveAwayForNewPurchases": "Application Development Classroom Training will be given away for the new purchases!" } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/tr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/tr.json index 818b4cab5e..1eedb98c61 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/tr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/tr.json @@ -39,6 +39,8 @@ "TrialLicensePeriodHasExpired": "Deneme lisansınızın süresi {0} gün önce sona erdi.", "TrialLicensePeriodWillExpire": "Deneme lisansınızın süresi {0} gün içinde dolacak.", "TrialLicensePeriodExpireToday": "Deneme lisans süreniz bugün sona erecek.", - "PurchaseNow": "Şimdi satın al!" + "PurchaseNow": "Şimdi satın al!", + "WelcomeFallCampaign": "Hoş Geldin Sonbahar Kampanyası!", + "GiveAwayForNewPurchases": "Yeni alımlar için Uygulama Geliştirme Sınıfı Eğitimi hediye edilecektir!" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hans.json index 4ba89108ce..e1ad37704f 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hans.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hans.json @@ -174,6 +174,8 @@ "CheckAllCommunityTalks": "检查所有社区帖子", "ReadMore": "阅读更多", "Post": "邮政", - "ExploreTheContentsCreatedByTheCoreABPTeamAndTheABPCommunity": "探索核心 ABP 团队和 ABP 社区创建的内容。" + "ExploreTheContentsCreatedByTheCoreABPTeamAndTheABPCommunity": "探索核心 ABP 团队和 ABP 社区创建的内容。", + "WelcomeFallCampaign": "欢迎秋季活动!", + "GiveAwayForNewPurchases": "新购买将赠送应用程序开发课堂培训!" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hant.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hant.json index dbf04ae25b..f55f4a7f85 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hant.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hant.json @@ -39,6 +39,8 @@ "TrialLicensePeriodHasExpired": "您的試用許可期限已於 {0} 天前到期。", "TrialLicensePeriodWillExpire": "您的試用許可期限將在 {0} 天后到期。", "TrialLicensePeriodExpireToday": "您的試用許可期將於今天到期。", - "PurchaseNow": "現在買!" + "PurchaseNow": "現在買!", + "WelcomeFallCampaign": "欢迎秋季活动!", + "GiveAwayForNewPurchases": "新购买将赠送应用程序开发课堂培训!" } } \ No newline at end of file diff --git a/docs/en/Apps/VoloDocs.md b/docs/en/Apps/VoloDocs.md index f85aa78bbd..9fe8ff2507 100644 --- a/docs/en/Apps/VoloDocs.md +++ b/docs/en/Apps/VoloDocs.md @@ -23,13 +23,13 @@ https://github.com/abpframework/abp/tree/master/modules/docs You can download the VoloDocs release from the following links: -http://apps.abp.io/VoloDocs/VoloDocs.win-x64.zip - **Windows 64 bit** +https://apps.abp.io/VoloDocs/VoloDocs.win-x64.zip - **Windows 64 bit** -http://apps.abp.io/VoloDocs/VoloDocs.win-x86.zip - **Windows 32 bit** +https://apps.abp.io/VoloDocs/VoloDocs.win-x86.zip - **Windows 32 bit** -http://apps.abp.io/VoloDocs/VoloDocs.osx-x64.zip - **MacOS** +https://apps.abp.io/VoloDocs/VoloDocs.osx-x64.zip - **MacOS** -http://apps.abp.io/VoloDocs/VoloDocs.linux-x64.zip - **Linux** +https://apps.abp.io/VoloDocs/VoloDocs.linux-x64.zip - **Linux** Notice that, all installations are self-contained deployments. It means all the required third-party dependencies along with the version of .NET Core is included. So you don't need to install any .NET Core SDK / Runtime. diff --git a/docs/en/Dependency-Injection.md b/docs/en/Dependency-Injection.md index 668eac6644..a0ad342c4c 100644 --- a/docs/en/Dependency-Injection.md +++ b/docs/en/Dependency-Injection.md @@ -244,25 +244,35 @@ One restriction of property injection is that you cannot use the dependency in y Property injection is also useful when you want to design a base class that has some common services injected by default. If you're going to use constructor injection, all derived classes should also inject depended services into their own constructors which makes development harder. However, be very careful using property injection for non-optional services as it makes it harder to clearly see the requirements of a class. -### Resolve Service from IServiceProvider +#### DisablePropertyInjectionAttribute -You may want to resolve a service directly from ``IServiceProvider``. In that case, you can inject IServiceProvider into your class and use ``GetService`` method as shown below: +You can use `[DisablePropertyInjection]` attribute on class or properties to disable property injection for the whole class or some specific properties. ````C# +[DisablePropertyInjection] public class MyService : ITransientDependency { - private readonly IServiceProvider _serviceProvider; + public ITaxCalculator TaxCalculator { get; set; } +} - public MyService(IServiceProvider serviceProvider) - { - _serviceProvider = serviceProvider; - } +public class MyService : ITransientDependency +{ + public ILogger Logger { get; set; } - public void DoSomething() - { - var taxCalculator = _serviceProvider.GetService(); - //... - } + [DisablePropertyInjection] + public ITaxCalculator TaxCalculator { get; set; } +} + +```` + +### Resolve Service from IServiceProvider + +You may want to resolve a service directly from ``IServiceProvider``. In that case, you can inject IServiceProvider into your class and use ``GetService`` method as shown below: + +````C# +public class MyService : ITransientDependency +{ + public ILogger Logger { get; set; } } ```` diff --git a/docs/en/Distributed-Event-Bus-RabbitMQ-Integration.md b/docs/en/Distributed-Event-Bus-RabbitMQ-Integration.md index 1961726b8f..4823cbaae9 100644 --- a/docs/en/Distributed-Event-Bus-RabbitMQ-Integration.md +++ b/docs/en/Distributed-Event-Bus-RabbitMQ-Integration.md @@ -86,7 +86,7 @@ Defining multiple connections is allowed. In this case, you can specify the conn This allows you to use multiple RabbitMQ server in your application, but select one of them for the event bus. -You can use any of the [ConnectionFactry](http://rabbitmq.github.io/rabbitmq-dotnet-client/api/RabbitMQ.Client.ConnectionFactory.html#properties) properties as the connection properties. +You can use any of the [ConnectionFactory](http://rabbitmq.github.io/rabbitmq-dotnet-client/api/RabbitMQ.Client.ConnectionFactory.html#properties) properties as the connection properties. **Example: Specify the connection port** @@ -152,4 +152,4 @@ Configure(options => }); ```` -Using these options classes can be combined with the `appsettings.json` way. Configuring an option property in the code overrides the value in the configuration file. \ No newline at end of file +Using these options classes can be combined with the `appsettings.json` way. Configuring an option property in the code overrides the value in the configuration file. diff --git a/docs/en/Getting-Started-Running-Solution.md b/docs/en/Getting-Started-Running-Solution.md index 66230c7aef..44fbd3eb03 100644 --- a/docs/en/Getting-Started-Running-Solution.md +++ b/docs/en/Getting-Started-Running-Solution.md @@ -163,6 +163,8 @@ You can see the application APIs and test them here. Get [more info](https://swa ### Running the Blazor Application (Client Side) +Go to the Blazor project folder, open a command line terminal, type the `abp bundle -f` command (If the project was created by ABP Cli tool, you don't need to do this). + Ensure that the `.Blazor` project is the startup project and run the application. > Use Ctrl+F5 in Visual Studio (instead of F5) to run the application without debugging. If you don't have a debug purpose, this will be faster. diff --git a/docs/en/Migration-Guides/OpenIddict-Step-by-Step.md b/docs/en/Migration-Guides/OpenIddict-Step-by-Step.md index e8c0f65c7c..3567ea5c06 100644 --- a/docs/en/Migration-Guides/OpenIddict-Step-by-Step.md +++ b/docs/en/Migration-Guides/OpenIddict-Step-by-Step.md @@ -76,6 +76,8 @@ Use the `abp update` command to update your existing application. See [Upgrading - Create a folder named *OpenIddict* under the Domain project and copy the [OpenIddictDataSeedContributor.cs](https://github.com/abpframework/abp-samples/blob/master/Ids2OpenId/src/Ids2OpenId.Domain/OpenIddict/OpenIddictDataSeedContributor.cs) under this folder. Rename all the `Ids2OpenId` with your project name. - Delete *IdentityServer* folder that contains `IdentityServerDataSeedContributor.cs` which is no longer needed. +You can also create a project with the same name and copy the `OpenIddict` folder of the new project into your project. + ### EntityFrameworkCore Layer If you are using MongoDB, skip this step and check the *MongoDB* layer section. @@ -226,4 +228,4 @@ for creating the host builder. ## See Also -* [ABP Version 6.0 Migration Guide](Abp-6_0.md) \ No newline at end of file +* [ABP Version 6.0 Migration Guide](Abp-6_0.md) diff --git a/docs/en/Modules/OpenIddict.md b/docs/en/Modules/OpenIddict.md index 2c8ae7572e..22cb22bf55 100644 --- a/docs/en/Modules/OpenIddict.md +++ b/docs/en/Modules/OpenIddict.md @@ -330,7 +330,19 @@ public class MyClaimDestinationsProvider : IAbpOpenIddictClaimDestinationsProvid { public virtual Task SetDestinationsAsync(AbpOpenIddictClaimDestinationsProviderContext context) { - // ... + foreach (var claim in context.Claims) + { + if (claim.Type == MyClaims.MyClaimsType) + { + claim.SetDestinations(OpenIddictConstants.Destinations.AccessToken, OpenIddictConstants.Destinations.IdentityToken); + } + + if (claim.Type == MyClaims.MyClaimsType2) + { + claim.SetDestinations(OpenIddictConstants.Destinations.AccessToken); + } + } + return Task.CompletedTask; } } diff --git a/docs/en/Startup-Templates/Application.md b/docs/en/Startup-Templates/Application.md index ec89f479ab..6a47363e8c 100644 --- a/docs/en/Startup-Templates/Application.md +++ b/docs/en/Startup-Templates/Application.md @@ -78,7 +78,7 @@ Based on the options you've specified, you will get a slightly different solutio If you don't specify any additional options, you will have a solution as shown below: -![bookstore-visual-studio-solution-v3](../images/bookstore-visual-studio-solution-v3.png) +![bookstore-rider-solution-v6](../images/solution-structure-solution-explorer-rider.png) Projects are organized in `src` and `test` folders. `src` folder contains the actual application which is layered based on [DDD](../Domain-Driven-Design.md) principles as mentioned before. @@ -225,7 +225,7 @@ So, the resulting solution allows a 4-tiered deployment, by comparing to 3-tiere The solution structure is shown below: -![bookstore-visual-studio-solution-v3](../images/bookstore-visual-studio-solution-tiered.png) +![bookstore-rider-solution-v6](../images/bookstore-rider-solution-tiered.png) As different from the default structure, two new projects come into play: `.AuthServer` & `.HttpApi.Host`. @@ -233,9 +233,9 @@ As different from the default structure, two new projects come into play: `.Auth This project is used as an authentication server for other projects. `.Web` project uses OpenId Connect Authentication to get identity and access tokens for the current user from the AuthServer. Then uses the access token to call the HTTP API server. HTTP API server uses bearer token authentication to obtain claims from the access token to authorize the current user. -![tiered-solution-applications](../images/tiered-solution-applications.png) +![tiered-solution-applications](../images/tiered-solution-applications-authserver.png) -ABP uses the open source [OpenIddcit](https://github.com/openiddict/openiddict-core) framework for the authentication between applications. See [OpenIddcit documentation](https://documentation.openiddict.com/) for details about the OpenIddict and OpenID Connect protocol. +ABP uses the [OpenIddict Module](../Modules/OpenIddict.md) that uses the open-source [OpenIddict-core](https://github.com/openiddict/openiddict-core) library for the authentication between applications. See [OpenIddict documentation](https://documentation.openiddict.com/) for details about the OpenIddict and OpenID Connect protocol. It has its own `appsettings.json` that contains database connection and other configurations. diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index b919955c6e..14c584d376 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -851,6 +851,10 @@ "text": "Page Header", "path": "UI/Blazor/Page-Header.md" }, + { + "text": "Page Layout", + "path": "UI/Blazor/Page-Layout.md" + }, { "text": "Toolbars", "path": "UI/Blazor/Toolbars.md" diff --git a/docs/en/images/bookstore-rider-solution-tiered.png b/docs/en/images/bookstore-rider-solution-tiered.png new file mode 100644 index 0000000000..25114bc51c Binary files /dev/null and b/docs/en/images/bookstore-rider-solution-tiered.png differ diff --git a/docs/en/images/solution-structure-solution-explorer-rider.png b/docs/en/images/solution-structure-solution-explorer-rider.png new file mode 100644 index 0000000000..8a09cec74e Binary files /dev/null and b/docs/en/images/solution-structure-solution-explorer-rider.png differ diff --git a/docs/en/images/tiered-solution-applications-authserver.png b/docs/en/images/tiered-solution-applications-authserver.png new file mode 100644 index 0000000000..6d96bf31b4 Binary files /dev/null and b/docs/en/images/tiered-solution-applications-authserver.png differ diff --git a/docs/pt-BR/Validation.md b/docs/pt-BR/Validation.md index 5818566cdd..662235431a 100644 --- a/docs/pt-BR/Validation.md +++ b/docs/pt-BR/Validation.md @@ -1,3 +1,182 @@ -## Validation +# Validação -Façam \ No newline at end of file +O sistema de validação é utilizado para validar a entrada do usuário ou a requisição do cliente para uma ação de um controller ou por um serviço. + +O ABP é compatível com o sistema de Validação de Modelos do ASP.NET Core e tudo escrito na [sua documentação](https://docs.microsoft.com/en-us/aspnet/core/mvc/models/validation) é válido para aplicações baseadas no ABP. Logo, esse documento foca nas funcionalidades do ABP ao invés de repetir a documentação da Microsoft. + +Além disso, o ABP adiciona os seguintes benefícios: + +* Define `IValidationEnabled` para adicionar validação automática para uma classe qualquer. Como todos os [serviços de aplicação](Application-Services.md) já o implementam, eles também são validados automaticamente. +* Automaticamente traduz os erros de validação para os atributos de anotação de dados. +* Provê serviços extensíveis para validar a chamada de um método ou o estado de um objeto. +* Provê integração com o [FluentValidation](https://fluentvalidation.net/) + +## Validando DTOs + +Essa seção introduz brevemente o sistema de validação. Para mais detalhes, veja a [Documentação da Validação de Modelo em ASP.NET Core](https://docs.microsoft.com/en-us/aspnet/core/mvc/models/validation). + +### Atributos de anotação de dados + +Utilizar anotações de dados é uma maneira simples de implementar uma validação formal para um [DTO](Data-Transfer-Objects.md) de uma forma declarativa. Exemplo: + +````csharp +public class CreateBookDto +{ + [Required] + [StringLength(100)] + public string Name { get; set; } + + [Required] + [StringLength(1000)] + public string Description { get; set; } + + [Range(0, 999.99)] + public decimal Price { get; set; } +} +```` +Quando você utilizar essa classe como parâmetro para um [serviço da aplicação](Application-Services.md) ou um controller, ele será automaticamente validado e a validação traduzida será lançada ([e tratada](Exception-Handling.md) pelo ABP framework). + +### IValidatableObject + +`IValidatableObject` pode ser implementado por um DTO para executar uma lógica customizada de validação. O `CreateBookDto` no exemplo a seguir implementa essa interface e verifica se o `Name` é igual a `Description` e retorna um erro de validação nesse caso. + +````csharp +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; + +namespace Acme.BookStore +{ + public class CreateBookDto : IValidatableObject + { + [Required] + [StringLength(100)] + public string Name { get; set; } + + [Required] + [StringLength(1000)] + public string Description { get; set; } + + [Range(0, 999.99)] + public decimal Price { get; set; } + + public IEnumerable Validate( + ValidationContext validationContext) + { + if (Name == Description) + { + yield return new ValidationResult( + "Name and Description can not be the same!", + new[] { "Name", "Description" } + ); + } + } + } +} +```` + +#### Resolvendo um serviço. + +Se você precisar resolver um serviço do [sistema de injeção de dependências](Dependency-Injection.md), você pode utilizar o objeto `ValidationContext`. + +````csharp +var myService = validationContext.GetRequiredService(); +```` + +> Enquanto resolver os serviços no método `Validate` permite várias possibilidades, não é um boa prática implementar sua lógica de validação do domínio nos DTOs. Mantenha os DTOs simples. Seu propósito é transferir dados (DTO: Data Transfer Object, ou Objeto de Transferência de Dados). + +## Infraestrutura de Validação. + +Essa seção explica alguns serviços adicionais fornecidos pelo ABP Framework. + +### Interface IValidationEnabled + +`IValidationEnabled` é um marcador vazio de interface que pode ser implementado por qualquer classe (registrada e resolvida a partir do [DI](Dependency-Injection.md)) para permitir que o ABP framework realize o sistema de validação para os métodos da classe. Por exemplo: + +````csharp +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Validation; + +namespace Acme.BookStore +{ + public class MyService : ITransientDependency, IValidationEnabled + { + public virtual async Task DoItAsync(MyInput input) + { + //... + } + } +} +```` + +> O ABP framework utiliza o sistema de [Proxying Dinâmico / Interceptadores](Dynamic-Proxying-Interceptors.md) para realizar a validação. Para fazê-lo funcionar, seu método deve ser **virtual** ou seu serviço deve ser injetado e utilizado através de uma **interface** (como `IMyService`). + +#### Habilitando e Desabilitando Validações + +Você pode utilizar o `[DisableValidation]` e desabilitar a validação para métodos, classes e propriedades. + +````csharp +[DisableValidation] +public Void MyMethod() +{ +} + +[DisableValidation] +public class InputClass +{ + public string MyProperty { get; set; } +} + +public class InputClass +{ + [DisableValidation] + public string MyProperty { get; set; } +} +```` + +### AbpValidationException + +Uma vez que o ABP determina um erro de validação, é lançada uma validação do tipo `AbpValidationException`. O código da sua aplicação poderá lançar o `AbpValidationException`, mas na maioria das vezes não será necessário. + +* A propriedade `ValidationErrors` do `AbpValidationException` contem a lista com os erros de validação. +* O nível de log do `AbpValidationException` é definido como `Warning`. Todos os erros de validação são logados no [Sistema de Logging](Logging.md). +* `AbpValidationException` é tratado automaticamente pelo ABP framework e é convertido em um erro utilizável com o código de status HTTP 400. Veja a documentação de [Manipulação de Exceção](Exception-Handling.md) para mais informações. + +## Tópicos Avançados + +### IObjectValidator + +Além da validação automática, você pode querer validar um objeto manualmente. Nesse caso, [injete](Dependency-Injection.md) e use o serviço `IObjectValidator`: + +* O método `ValidateAsync` valida o objeto informado baseado nas regras de validação e lança uma `AbpValidationException` se não estiver em um estado válido. + +* `GetErrorsAsync` não lança uma exceção, somente retorna os erros de validação. + +`IObjectValidator` é implementado pelo `ObjectValidator` por padrão. `ObjectValidator` é extensível; você pode implementar a interface `IObjectValidationContributor` para contribuir com uma lógica customizada. Exemplo: + +````csharp +public class MyObjectValidationContributor + : IObjectValidationContributor, ITransientDependency +{ + public Task AddErrorsAsync(ObjectValidationContext context) + { + //Get the validating object + var obj = context.ValidatingObject; + + //Add the validation errors if available + context.Errors.Add(...); + return Task.CompletedTask; + } +} +```` + +* Lembre-se de registrar sua classe no [DI](Dependency-Injection.md) (implementar `ITransientDependency` faz isso no exemplo anterior) +* ABP vai automaticamente descobrir sua classe e utilizá-la em qualquer tipo de validação de objetos (incluindo chamadas de métodos de validação automáticas). + +### IMethodInvocationValidator + +`IMethodInvocationValidator` é utilizado para validar a chamada de um método. Ele utiliza internamente o `IObjectValidator` para validar os objetos passados na chamada do método. Você normalmente não precisa deste serviço, já que ele é utilizado automaticamente pelo framework, mas você pode querer reutilizar ou substituir na sua aplicação em alguns casos raros. + +## Integração com FluentValidation + +O pacote Volo.Abp.FluentValidation integra a biblioteca FluentValidation com o sistema de validação (implementando o `IObjectValidationContributor`). Veja o [documento de Integração com o FluentValidation](FluentValidation.md) para mais informações. diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Components/LayoutHooks/LayoutHook.razor b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Components/LayoutHooks/LayoutHook.razor new file mode 100644 index 0000000000..f512232b86 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Components/LayoutHooks/LayoutHook.razor @@ -0,0 +1,7 @@ +@if (LayoutHookViewModel.Hooks.Any()) +{ + foreach (var hook in LayoutHookViewModel.Hooks) + { + + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Components/LayoutHooks/LayoutHook.razor.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Components/LayoutHooks/LayoutHook.razor.cs new file mode 100644 index 0000000000..18fbcd89c2 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Components/LayoutHooks/LayoutHook.razor.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Components; +using Microsoft.Extensions.Options; +using Volo.Abp.Ui.LayoutHooks; + +namespace Volo.Abp.AspNetCore.Components.Web.Theming.Components.LayoutHooks; + +public partial class LayoutHook : ComponentBase +{ + [Parameter] + public string Name { get; set; } + + [Parameter] + public string Layout { get; set; } + + [Inject] + protected IOptions LayoutHookOptions { get; set; } + + protected LayoutHookViewModel LayoutHookViewModel { get; private set; } + + protected override Task OnInitializedAsync() + { + if (LayoutHookOptions.Value.Hooks.TryGetValue(Name, out var layoutHooks)) + { + layoutHooks = layoutHooks + .WhereIf(string.IsNullOrWhiteSpace(Layout), x => x.Layout == Layout) + .ToList(); + } + + layoutHooks ??= new List(); + + LayoutHookViewModel = new LayoutHookViewModel(layoutHooks.ToArray(), Layout); + + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Layout/StandardLayouts.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Layout/StandardLayouts.cs new file mode 100644 index 0000000000..ea73a5673f --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Layout/StandardLayouts.cs @@ -0,0 +1,6 @@ +namespace Volo.Abp.AspNetCore.Components.Web.Theming.Layout; + +public static class StandardLayouts +{ + public const string Application = "Application"; +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/AbpAspNetCoreMvcClientModule.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/AbpAspNetCoreMvcClientModule.cs index 7c21b9fe09..ae5421d947 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/AbpAspNetCoreMvcClientModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/AbpAspNetCoreMvcClientModule.cs @@ -1,8 +1,5 @@ -using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; using Volo.Abp.EventBus; using Volo.Abp.Modularity; -using Volo.Abp.Threading; namespace Volo.Abp.AspNetCore.Mvc.Client; @@ -12,13 +9,5 @@ namespace Volo.Abp.AspNetCore.Mvc.Client; )] public class AbpAspNetCoreMvcClientModule : AbpModule { - public override void OnApplicationInitialization(ApplicationInitializationContext context) - { - AsyncHelper.RunSync(() => OnApplicationInitializationAsync(context)); - } - - public async override Task OnApplicationInitializationAsync(ApplicationInitializationContext context) - { - await context.ServiceProvider.GetRequiredService().InitializeAsync(); - } + } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClient.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClient.cs index 59690b2d03..7bb2e67b49 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClient.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClient.cs @@ -30,11 +30,6 @@ public class MvcCachedApplicationConfigurationClient : ICachedApplicationConfigu Cache = cache; } - public async Task InitializeAsync() - { - await GetAsync(); - } - public async Task GetAsync() { var cacheKey = CreateCacheKey(); @@ -45,7 +40,6 @@ public class MvcCachedApplicationConfigurationClient : ICachedApplicationConfigu return configuration; } - configuration = await Cache.GetOrAddAsync( cacheKey, async () => await ApplicationConfigurationAppService.GetAsync(), diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalSize.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalSize.cs index f022dacce5..452a616365 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalSize.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalSize.cs @@ -5,5 +5,11 @@ public enum AbpModalSize Default, Small, Large, - ExtraLarge + ExtraLarge, + Fullscreen, + FullscreenSmDown, + FullscreenMdDown, + FullscreenLgDown, + FullscreenXlDown, + FullscreenXxlDown } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalSizeExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalSizeExtensions.cs index 7b0de7a595..9477783557 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalSizeExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalSizeExtensions.cs @@ -14,6 +14,18 @@ public static class AbpModalSizeExtensions return "modal-xl"; case AbpModalSize.Default: return ""; + case AbpModalSize.Fullscreen: + return "modal-fullscreen"; + case AbpModalSize.FullscreenSmDown: + return "modal-fullscreen-sm-down"; + case AbpModalSize.FullscreenMdDown: + return "modal-fullscreen-md-down"; + case AbpModalSize.FullscreenLgDown: + return "modal-fullscreen-lg-down"; + case AbpModalSize.FullscreenXlDown: + return "modal-fullscreen-xl-down"; + case AbpModalSize.FullscreenXxlDown: + return "modal-fullscreen-xxl-down"; default: throw new AbpException($"Unknown {nameof(AbpModalSize)}: {size}"); } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/Default.cshtml b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/Default.cshtml index 61e9afbf6e..34536ec373 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/Default.cshtml +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/Default.cshtml @@ -1,5 +1,4 @@ -@using Volo.Abp.AspNetCore.Mvc.UI.Components.LayoutHook -@model LayoutHookViewModel +@model Volo.Abp.Ui.LayoutHooks.LayoutHookViewModel @if (Model.Hooks.Any()) { foreach (var hook in Model.Hooks) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHookViewComponent.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHookViewComponent.cs index 45eaa2b6a3..5bd18e4c31 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHookViewComponent.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHookViewComponent.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; +using Volo.Abp.Ui.LayoutHooks; namespace Volo.Abp.AspNetCore.Mvc.UI.Components.LayoutHook; diff --git a/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs b/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs index 868ecb3fa5..03084d8351 100644 --- a/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs +++ b/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using Autofac.Core; using Autofac.Extras.DynamicProxy; +using Volo.Abp.Autofac; using Volo.Abp.Castle.DynamicProxy; using Volo.Abp.DependencyInjection; using Volo.Abp.Modularity; @@ -67,10 +68,11 @@ public static class AbpRegistrationBuilderExtensions Type implementationType) where TActivatorData : ReflectionActivatorData { - //Enable Property Injection only for types in an assembly containing an AbpModule - if (moduleContainer.Modules.Any(m => m.Assembly == implementationType.Assembly)) + // Enable Property Injection only for types in an assembly containing an AbpModule and without a DisablePropertyInjection attribute on class or properties. + if (moduleContainer.Modules.Any(m => m.Assembly == implementationType.Assembly) && + implementationType.GetCustomAttributes(typeof(DisablePropertyInjectionAttribute), true).IsNullOrEmpty()) { - registrationBuilder = registrationBuilder.PropertiesAutowired(); + registrationBuilder = registrationBuilder.PropertiesAutowired(new AbpPropertySelector(false)); } return registrationBuilder; diff --git a/framework/src/Volo.Abp.Autofac/Volo/Abp/Autofac/AbpPropertySelector.cs b/framework/src/Volo.Abp.Autofac/Volo/Abp/Autofac/AbpPropertySelector.cs new file mode 100644 index 0000000000..00d20e9bca --- /dev/null +++ b/framework/src/Volo.Abp.Autofac/Volo/Abp/Autofac/AbpPropertySelector.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using System.Reflection; +using Autofac.Core; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Autofac; + +public class AbpPropertySelector : DefaultPropertySelector +{ + public AbpPropertySelector(bool preserveSetValues) + : base(preserveSetValues) + { + } + + public override bool InjectProperty(PropertyInfo propertyInfo, object instance) + { + return propertyInfo.GetCustomAttributes(typeof(DisablePropertyInjectionAttribute), true).IsNullOrEmpty() && + base.InjectProperty(propertyInfo, instance); + } + +} diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Auth/AuthService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Auth/AuthService.cs index c3ce0afb54..cc198e877b 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Auth/AuthService.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Auth/AuthService.cs @@ -74,9 +74,9 @@ public class AuthService : IAuthService, ITransientDependency { var configuration = new IdentityClientConfiguration( CliUrls.AccountAbpIo, - "role email abpio abpio_www abpio_commercial offline_access", + "abpio offline_access", "abp-cli", - "1q2w3e*", + null, OidcConstants.GrantTypes.Password, userName, password @@ -96,9 +96,9 @@ public class AuthService : IAuthService, ITransientDependency { var configuration = new IdentityClientConfiguration( CliUrls.AccountAbpIo, - "role email abpio abpio_www abpio_commercial openid offline_access", + "abpio offline_access", "abp-cli", - "1q2w3e*", + null, OidcConstants.GrantTypes.DeviceCode ); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs index cc64d73ff2..b0927cbcc9 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.Cli.Args; +using Volo.Abp.Cli.Bundling; using Volo.Abp.Cli.Commands.Services; using Volo.Abp.Cli.LIbs; using Volo.Abp.Cli.ProjectBuilding; @@ -26,23 +27,35 @@ public class NewCommand : ProjectCreationCommandBase, IConsoleCommand, ITransien protected TemplateProjectBuilder TemplateProjectBuilder { get; } public ITemplateInfoProvider TemplateInfoProvider { get; } - - public NewCommand(TemplateProjectBuilder templateProjectBuilder - , ITemplateInfoProvider templateInfoProvider, - ConnectionStringProvider connectionStringProvider, + + public NewCommand( + ConnectionStringProvider connectionStringProvider, SolutionPackageVersionFinder solutionPackageVersionFinder, ICmdHelper cmdHelper, - IInstallLibsService installLibsService, - AngularPwaSupportAdder angularPwaSupportAdder, + IInstallLibsService installLibsService, + CliService cliService, + AngularPwaSupportAdder angularPwaSupportAdder, InitialMigrationCreator initialMigrationCreator, - ThemePackageAdder themePackageAdder, - ILocalEventBus eventBus) - : base(connectionStringProvider, solutionPackageVersionFinder, cmdHelper, installLibsService, angularPwaSupportAdder, initialMigrationCreator, themePackageAdder, eventBus) + ThemePackageAdder themePackageAdder, + ILocalEventBus eventBus, + IBundlingService bundlingService, + ITemplateInfoProvider templateInfoProvider, + TemplateProjectBuilder templateProjectBuilder) : + base(connectionStringProvider, + solutionPackageVersionFinder, + cmdHelper, + installLibsService, + cliService, + angularPwaSupportAdder, + initialMigrationCreator, + themePackageAdder, + eventBus, + bundlingService) { - TemplateProjectBuilder = templateProjectBuilder; TemplateInfoProvider = templateInfoProvider; + TemplateProjectBuilder = templateProjectBuilder; } - + public async Task ExecuteAsync(CommandLineArgs commandLineArgs) { var projectName = NamespaceHelper.NormalizeNamespace(commandLineArgs.Target); @@ -72,7 +85,7 @@ public class NewCommand : ProjectCreationCommandBase, IConsoleCommand, ITransien Logger.LogInformation("Tiered: yes"); } - var projectArgs = GetProjectBuildArgs(commandLineArgs, template, projectName); + var projectArgs = await GetProjectBuildArgsAsync(commandLineArgs, template, projectName); var result = await TemplateProjectBuilder.BuildAsync( projectArgs @@ -92,6 +105,8 @@ public class NewCommand : ProjectCreationCommandBase, IConsoleCommand, ITransien await RunInstallLibsForWebTemplateAsync(projectArgs); } + await RunBundleForBlazorWasmTemplateAsync(projectArgs); + await ConfigurePwaSupportForAngular(projectArgs); OpenRelatedWebPage(projectArgs, template, isTiered, commandLineArgs); @@ -155,5 +170,4 @@ public class NewCommand : ProjectCreationCommandBase, IConsoleCommand, ITransien { return "Generate a new solution based on the ABP startup templates."; } - } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProjectCreationCommandBase.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProjectCreationCommandBase.cs index 6bd8a78cc8..813900ba18 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProjectCreationCommandBase.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProjectCreationCommandBase.cs @@ -10,6 +10,7 @@ using NuGet.Versioning; using NUglify.Helpers; using Volo.Abp.Cli.ProjectModification; using Volo.Abp.Cli.Args; +using Volo.Abp.Cli.Bundling; using Volo.Abp.Cli.Commands.Services; using Volo.Abp.Cli.LIbs; using Volo.Abp.Cli.ProjectBuilding; @@ -25,10 +26,12 @@ namespace Volo.Abp.Cli.Commands; public abstract class ProjectCreationCommandBase { + private readonly IBundlingService _bundlingService; public ConnectionStringProvider ConnectionStringProvider { get; } public SolutionPackageVersionFinder SolutionPackageVersionFinder { get; } public ICmdHelper CmdHelper { get; } public IInstallLibsService InstallLibsService { get; } + public CliService CliService { get; } public AngularPwaSupportAdder AngularPwaSupportAdder { get; } public InitialMigrationCreator InitialMigrationCreator { get; } public ILocalEventBus EventBus { get; } @@ -41,15 +44,19 @@ public abstract class ProjectCreationCommandBase SolutionPackageVersionFinder solutionPackageVersionFinder, ICmdHelper cmdHelper, IInstallLibsService installLibsService, + CliService cliService, AngularPwaSupportAdder angularPwaSupportAdder, InitialMigrationCreator initialMigrationCreator, ThemePackageAdder themePackageAdder, - ILocalEventBus eventBus) + ILocalEventBus eventBus, + IBundlingService bundlingService) { + _bundlingService = bundlingService; ConnectionStringProvider = connectionStringProvider; SolutionPackageVersionFinder = solutionPackageVersionFinder; CmdHelper = cmdHelper; InstallLibsService = installLibsService; + CliService = cliService; AngularPwaSupportAdder = angularPwaSupportAdder; InitialMigrationCreator = initialMigrationCreator; EventBus = eventBus; @@ -58,7 +65,7 @@ public abstract class ProjectCreationCommandBase Logger = NullLogger.Instance; } - protected ProjectBuildArgs GetProjectBuildArgs(CommandLineArgs commandLineArgs, string template, string projectName) + protected async Task GetProjectBuildArgsAsync(CommandLineArgs commandLineArgs, string template, string projectName) { var version = commandLineArgs.Options.GetOrNull(Options.Version.Short, Options.Version.Long); @@ -71,6 +78,15 @@ public abstract class ProjectCreationCommandBase if (preview) { Logger.LogInformation("Preview: yes"); + + var cliVersion = await CliService.GetCurrentCliVersionAsync(typeof(CliService).Assembly); + + if (!cliVersion.IsPrerelease) + { + throw new CliUsageException( + "You can only create a new preview solution with preview CLI version." + + " Update your ABP CLI to the preview version."); + } } var pwa = commandLineArgs.Options.ContainsKey(Options.ProgressiveWebApp.Short); @@ -317,14 +333,14 @@ public abstract class ProjectCreationCommandBase var tieredYesNo = tiered ? "yes" : "no"; var url = $"https://{urlPrefix}.abp.io/project-created-success?ui={uiFramework:g}&db={databaseProvider:g}&tiered={tieredYesNo}"; - CmdHelper.OpenWebPage(url); + CmdHelper.Open(url); } protected void OpenMicroserviceDocumentPage() { var url = "https://docs.abp.io/en/commercial/latest/startup-templates/microservice/index"; - CmdHelper.OpenWebPage(url); + CmdHelper.Open(url); } protected bool GetCreateSolutionFolderPreference(CommandLineArgs commandLineArgs) @@ -392,6 +408,25 @@ public abstract class ProjectCreationCommandBase } } + protected async Task RunBundleForBlazorWasmTemplateAsync(ProjectBuildArgs projectArgs) + { + if (AppTemplateBase.IsAppTemplate(projectArgs.TemplateName) && projectArgs.UiFramework == UiFramework.Blazor) + { + Logger.LogInformation("Generating bundles for Blazor Wasm..."); + + await EventBus.PublishAsync(new ProjectCreationProgressEvent + { + Message = "Generating bundles for Blazor Wasm" + }, false); + + var directory = Path.GetDirectoryName( + Directory.GetFiles(projectArgs.OutputFolder, "*.Blazor.csproj", SearchOption.AllDirectories).First() + ); + + await _bundlingService.BundleAsync(directory, true); + } + } + protected async Task CreateInitialMigrationsAsync(ProjectBuildArgs projectArgs) { if (projectArgs.DatabaseProvider == DatabaseProvider.MongoDb) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/NuGet/CommercialPackages.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/NuGet/CommercialPackages.cs index 97003287bb..096fe9f314 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/NuGet/CommercialPackages.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/NuGet/CommercialPackages.cs @@ -14,6 +14,16 @@ internal static class CommercialPackages public static bool IsCommercial(string packageId) { - return Packages.Contains(packageId.ToLowerInvariant()); + return Packages.Contains(packageId.ToLowerInvariant()) || IsLeptonXPackage(packageId); + } + + private static bool IsLeptonXPackage(string packageId) + { + return !IsLeptonXLitePackage(packageId) && packageId.Contains("LeptonX"); + } + + private static bool IsLeptonXLitePackage(string packageId) + { + return packageId.Contains("LeptonXLite"); } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/CreateAppSettingsSecretsStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/CreateAppSettingsSecretsStep.cs index 20e4f8fca6..f0ba4044d1 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/CreateAppSettingsSecretsStep.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/CreateAppSettingsSecretsStep.cs @@ -11,7 +11,7 @@ public class CreateAppSettingsSecretsStep : ProjectBuildPipelineStep public override void Execute(ProjectBuildContext context) { var appSettingsFiles = context.Files - .Where(x => x.Name.EndsWith(CliConsts.AppSettingsJsonFileName) && NotBlazorWasmProject(x.Name)) + .Where(x => x.Name.EndsWith(CliConsts.AppSettingsJsonFileName) && NotBlazorWasmProject(x.Name) && NotInDockerFiles(x.Name)) .ToList(); if (!appSettingsFiles.Any()) @@ -66,6 +66,11 @@ public class CreateAppSettingsSecretsStep : ProjectBuildPipelineStep return !fileName.Contains("Blazor/wwwroot") && !fileName.Contains("Blazor.Host/wwwroot"); } + private static bool NotInDockerFiles(string fileName) + { + return !fileName.Contains("etc/docker/"); + } + private static string ReplaceAppSettingsSecretsPlaceholder(string content) { var path = string.Empty; diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs index 515bb98a56..16bea2740f 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs @@ -37,6 +37,7 @@ public abstract class AppTemplateBase : TemplateInfo ConfigureTieredArchitecture(context, steps); ConfigurePublicWebSite(context, steps); ConfigureTheme(context, steps); + ConfigureVersion(context, steps); RemoveUnnecessaryPorts(context, steps); RandomizeSslPorts(context, steps); RandomizeStringEncryption(context, steps); @@ -193,12 +194,16 @@ public abstract class AppTemplateBase : TemplateInfo return; } + if (context.BuildArgs.Theme != Theme.NotSpecified) + { + context.Symbols.Add(context.BuildArgs.Theme.Value.ToString().ToUpper()); + } + if (context.BuildArgs.Theme == Theme.LeptonX) { - context.Symbols.Add("LEPTONX"); steps.Add(new ChangeThemeStyleStep()); } - + if (IsDefaultThemeForTemplate(context.BuildArgs.Theme.Value)) { return; @@ -489,6 +494,14 @@ public abstract class AppTemplateBase : TemplateInfo steps.Add(new RemoveUnnecessaryPortsStep()); } + protected void ConfigureVersion(ProjectBuildContext context, List steps) + { + if (context.BuildArgs.Version == null || SemanticVersion.Parse(context.BuildArgs.Version) >= SemanticVersion.Parse("6.0.0-rc.1")) + { + context.Symbols.Add("newer-than-6.0"); + } + } + protected void RandomizeSslPorts(ProjectBuildContext context, List steps) { if (context.BuildArgs.ExtraProperties.ContainsKey("no-random-port")) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceTemplateBase.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceTemplateBase.cs index c6a15389ef..319326f3d4 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceTemplateBase.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceTemplateBase.cs @@ -35,10 +35,14 @@ public abstract class MicroserviceTemplateBase : TemplateInfo { return; } + + if (context.BuildArgs.Theme != Theme.NotSpecified) + { + context.Symbols.Add(context.BuildArgs.Theme.Value.ToString().ToUpper()); + } if (context.BuildArgs.Theme == Theme.LeptonX) { - context.Symbols.Add("LEPTONX"); steps.Add(new ChangeThemeStyleStep()); return; } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs index 7f2831351a..ed90d16cfd 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs @@ -153,7 +153,7 @@ public class SolutionModuleAdder : ITransientDependency var documentationLink = module.GetFirstDocumentationLinkOrNull(); if (documentationLink != null) { - CmdHelper.OpenWebPage(documentationLink); + CmdHelper.Open(documentationLink); } return module; diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/CmdHelper.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/CmdHelper.cs index 95eaa8136c..32c1acf5be 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/CmdHelper.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/CmdHelper.cs @@ -18,20 +18,20 @@ public class CmdHelper : ICmdHelper, ITransientDependency CliOptions = cliOptions.Value; } - public void OpenWebPage(string url) + public void Open(string pathOrUrl) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - url = url.Replace("&", "^&"); - Process.Start(new ProcessStartInfo("cmd", $"/c start {url}") { CreateNoWindow = true }); + pathOrUrl = pathOrUrl.Replace("&", "^&"); + Process.Start(new ProcessStartInfo("cmd", $"/c start {pathOrUrl}") { CreateNoWindow = true }); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { - Process.Start("xdg-open", url); + Process.Start("xdg-open", pathOrUrl); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { - Process.Start("open", url); + Process.Start("open", pathOrUrl); } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/ICmdHelper.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/ICmdHelper.cs index f96697b1cc..2f71bda7b5 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/ICmdHelper.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/ICmdHelper.cs @@ -4,7 +4,7 @@ namespace Volo.Abp.Cli.Utils; public interface ICmdHelper { - void OpenWebPage(string url); + void Open(string pathOrUrl); void Run(string file, string arguments); diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/DisablePropertyInjectionAttribute.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/DisablePropertyInjectionAttribute.cs new file mode 100644 index 0000000000..fad0d7334a --- /dev/null +++ b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/DisablePropertyInjectionAttribute.cs @@ -0,0 +1,9 @@ +using System; + +namespace Volo.Abp.DependencyInjection; + +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property)] +public class DisablePropertyInjectionAttribute : Attribute +{ + +} diff --git a/framework/src/Volo.Abp.Kafka/Volo/Abp/Kafka/ConsumerPool.cs b/framework/src/Volo.Abp.Kafka/Volo/Abp/Kafka/ConsumerPool.cs index 7147c81271..7c73df0d51 100644 --- a/framework/src/Volo.Abp.Kafka/Volo/Abp/Kafka/ConsumerPool.cs +++ b/framework/src/Volo.Abp.Kafka/Volo/Abp/Kafka/ConsumerPool.cs @@ -37,7 +37,7 @@ public class ConsumerPool : IConsumerPool, ISingletonDependency return Consumers.GetOrAdd( connectionName, connection => new Lazy>(() => { - var config = new ConsumerConfig(Options.Connections.GetOrDefault(connection)) + var config = new ConsumerConfig(Options.Connections.GetOrDefault(connection).ToDictionary(k => k.Key, v => v.Value)) { GroupId = groupId, EnableAutoCommit = false diff --git a/framework/src/Volo.Abp.Kafka/Volo/Abp/Kafka/ProducerPool.cs b/framework/src/Volo.Abp.Kafka/Volo/Abp/Kafka/ProducerPool.cs index 691a29c1d2..ac2edf31a7 100644 --- a/framework/src/Volo.Abp.Kafka/Volo/Abp/Kafka/ProducerPool.cs +++ b/framework/src/Volo.Abp.Kafka/Volo/Abp/Kafka/ProducerPool.cs @@ -39,7 +39,7 @@ public class ProducerPool : IProducerPool, ISingletonDependency return Producers.GetOrAdd( connectionName, connection => new Lazy>(() => { - var producerConfig = new ProducerConfig(Options.Connections.GetOrDefault(connection)); + var producerConfig = new ProducerConfig(Options.Connections.GetOrDefault(connection).ToDictionary(k => k.Key, v => v.Value)); Options.ConfigureProducer?.Invoke(producerConfig); return new ProducerBuilder(producerConfig).Build(); diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/AbpLayoutHookOptions.cs b/framework/src/Volo.Abp.UI/Volo/Abp/Ui/LayoutHooks/AbpLayoutHookOptions.cs similarity index 89% rename from framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/AbpLayoutHookOptions.cs rename to framework/src/Volo.Abp.UI/Volo/Abp/Ui/LayoutHooks/AbpLayoutHookOptions.cs index 68851c1860..d5ba4aa239 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/AbpLayoutHookOptions.cs +++ b/framework/src/Volo.Abp.UI/Volo/Abp/Ui/LayoutHooks/AbpLayoutHookOptions.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace Volo.Abp.AspNetCore.Mvc.UI.Components.LayoutHook; +namespace Volo.Abp.Ui.LayoutHooks; public class AbpLayoutHookOptions { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHookInfo.cs b/framework/src/Volo.Abp.UI/Volo/Abp/Ui/LayoutHooks/LayoutHookInfo.cs similarity index 84% rename from framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHookInfo.cs rename to framework/src/Volo.Abp.UI/Volo/Abp/Ui/LayoutHooks/LayoutHookInfo.cs index e2bb26dac5..db4ca39466 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHookInfo.cs +++ b/framework/src/Volo.Abp.UI/Volo/Abp/Ui/LayoutHooks/LayoutHookInfo.cs @@ -1,11 +1,11 @@ using System; -namespace Volo.Abp.AspNetCore.Mvc.UI.Components.LayoutHook; +namespace Volo.Abp.Ui.LayoutHooks; public class LayoutHookInfo { /// - /// ViewComponent type. + /// Component type. /// public Type ComponentType { get; } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHookViewModel.cs b/framework/src/Volo.Abp.UI/Volo/Abp/Ui/LayoutHooks/LayoutHookViewModel.cs similarity index 79% rename from framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHookViewModel.cs rename to framework/src/Volo.Abp.UI/Volo/Abp/Ui/LayoutHooks/LayoutHookViewModel.cs index fbc73d8dad..107ad6990a 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHookViewModel.cs +++ b/framework/src/Volo.Abp.UI/Volo/Abp/Ui/LayoutHooks/LayoutHookViewModel.cs @@ -1,4 +1,4 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Components.LayoutHook; +namespace Volo.Abp.Ui.LayoutHooks; public class LayoutHookViewModel { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHooks.cs b/framework/src/Volo.Abp.UI/Volo/Abp/Ui/LayoutHooks/LayoutHooks.cs similarity index 88% rename from framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHooks.cs rename to framework/src/Volo.Abp.UI/Volo/Abp/Ui/LayoutHooks/LayoutHooks.cs index 588872c46b..fafab40161 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHooks.cs +++ b/framework/src/Volo.Abp.UI/Volo/Abp/Ui/LayoutHooks/LayoutHooks.cs @@ -1,4 +1,4 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Components.LayoutHook; +namespace Volo.Abp.Ui.LayoutHooks; public static class LayoutHooks { diff --git a/framework/test/Volo.Abp.Core.Tests/Microsoft/Extensions/DependencyInjection/DependencyInjection_Tests.cs b/framework/test/Volo.Abp.Core.Tests/Microsoft/Extensions/DependencyInjection/DependencyInjection_Tests.cs index 5d77c6a00e..52f07620fb 100644 --- a/framework/test/Volo.Abp.Core.Tests/Microsoft/Extensions/DependencyInjection/DependencyInjection_Tests.cs +++ b/framework/test/Volo.Abp.Core.Tests/Microsoft/Extensions/DependencyInjection/DependencyInjection_Tests.cs @@ -47,19 +47,36 @@ public abstract class DependencyInjection_Standard_Tests : AbpIntegratedTest().ProperyInjectedService.ShouldNotBeNull(); + GetRequiredService().PropertyInjectedService.ShouldNotBeNull(); } [Fact] public void Should_Inject_Services_As_Properties_For_Generic_Classes() { - GetRequiredService>().ProperyInjectedService.ShouldNotBeNull(); + GetRequiredService>().PropertyInjectedService.ShouldNotBeNull(); } [Fact] public void Should_Inject_Services_As_Properties_For_Generic_Concrete_Classes() { - GetRequiredService().ProperyInjectedService.ShouldNotBeNull(); + GetRequiredService().PropertyInjectedService.ShouldNotBeNull(); + } + + [Fact] + public void Should_Not_Inject_Services_As_Properties_When_Class_With_DisablePropertyInjection() + { + GetRequiredService().PropertyInjectedService.ShouldBeNull(); + GetRequiredService>().PropertyInjectedService.ShouldBeNull(); + } + + [Fact] + public void Should_Not_Inject_Services_As_Properties_When_Property_With_DisablePropertyInjection() + { + GetRequiredService().PropertyInjectedService.ShouldNotBeNull(); + GetRequiredService().DisablePropertyInjectionService.ShouldBeNull(); + + GetRequiredService>().PropertyInjectedService.ShouldNotBeNull(); + GetRequiredService>().DisablePropertyInjectionService.ShouldBeNull(); } [Fact] @@ -145,18 +162,19 @@ public abstract class DependencyInjection_Standard_Tests : AbpIntegratedTest(); context.Services.AddType(); context.Services.AddTransient(typeof(GenericServiceWithPropertyInject<>)); - context.Services.AddTransient(typeof(ConcreteGenericServiceWithPropertyInject)); + context.Services.AddTransient(typeof(GenericServiceWithDisablePropertyInjectionOnClass<>)); + context.Services.AddTransient(typeof(GenericServiceWithDisablePropertyInjectionOnProperty<>)); } } public class ServiceWithPropertyInject : ITransientDependency { - public MyEmptyTransientService ProperyInjectedService { get; set; } + public MyEmptyTransientService PropertyInjectedService { get; set; } } public class GenericServiceWithPropertyInject : ITransientDependency { - public MyEmptyTransientService ProperyInjectedService { get; set; } + public MyEmptyTransientService PropertyInjectedService { get; set; } public T Value { get; set; } } @@ -165,4 +183,36 @@ public abstract class DependencyInjection_Standard_Tests : AbpIntegratedTest : ITransientDependency + { + public MyEmptyTransientService PropertyInjectedService { get; set; } + + public T Value { get; set; } + } + + public class GenericServiceWithDisablePropertyInjectionOnProperty : ITransientDependency + { + public MyEmptyTransientService PropertyInjectedService { get; set; } + + [DisablePropertyInjection] + public MyEmptyTransientService DisablePropertyInjectionService { get; set; } + + public T Value { get; set; } + } } diff --git a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/MainLayout.razor b/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/MainLayout.razor index 01500c8801..3565d6add5 100644 --- a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/MainLayout.razor +++ b/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/MainLayout.razor @@ -1,4 +1,5 @@ -@using Volo.Abp.AspNetCore.Components.Web.Theming.Components; +@using Volo.Abp.Ui.LayoutHooks +@using Volo.Abp.AspNetCore.Components.Web.Theming.Layout @inherits LayoutComponentBase
+ @Body + diff --git a/modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Account.cshtml b/modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Account.cshtml index f71171912c..5e2ca98ba7 100644 --- a/modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Account.cshtml +++ b/modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Account.cshtml @@ -12,6 +12,7 @@ @using Volo.Abp.MultiTenancy @using Volo.Abp.Localization @using Volo.Abp.Ui.Branding +@using Volo.Abp.Ui.LayoutHooks @inject IBrandingProvider BrandingProvider @inject IOptions MultiTenancyOptions @inject ICurrentTenant CurrentTenant diff --git a/modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Application.cshtml b/modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Application.cshtml index 23c19c077d..42f2b2ead2 100644 --- a/modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Application.cshtml +++ b/modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Application.cshtml @@ -8,6 +8,7 @@ @using Volo.Abp.AspNetCore.Mvc.UI.Widgets.Components.WidgetStyles @using Volo.Abp.Localization @using Volo.Abp.Ui.Branding +@using Volo.Abp.Ui.LayoutHooks @inject IBrandingProvider BrandingProvider @inject IPageLayout PageLayout @{ diff --git a/modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Empty.cshtml b/modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Empty.cshtml index 70c7d5e1e8..6d3461be43 100644 --- a/modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Empty.cshtml +++ b/modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Empty.cshtml @@ -7,6 +7,7 @@ @using Volo.Abp.AspNetCore.Mvc.UI.Widgets.Components.WidgetStyles @using Volo.Abp.Localization @using Volo.Abp.Ui.Branding +@using Volo.Abp.Ui.LayoutHooks @inject IBrandingProvider BrandingProvider @inject IPageLayout PageLayout @{ diff --git a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/CmsKitWebUnifiedModule.cs b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/CmsKitWebUnifiedModule.cs index 801cc2dd41..0343a3bc58 100644 --- a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/CmsKitWebUnifiedModule.cs +++ b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/CmsKitWebUnifiedModule.cs @@ -36,7 +36,6 @@ using Volo.Abp.Threading; using Volo.Abp.VirtualFileSystem; using Volo.CmsKit.Admin.Web; using Volo.CmsKit.Comments; -using Volo.CmsKit.Contents; using Volo.CmsKit.EntityFrameworkCore; using Volo.CmsKit.MediaDescriptors; using Volo.CmsKit.MultiTenancy; @@ -45,6 +44,7 @@ using Volo.CmsKit.Ratings; using Volo.CmsKit.Reactions; using Volo.CmsKit.Tags; using Volo.CmsKit.Web; +using Volo.CmsKit.Web.Contents; namespace Volo.CmsKit; diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Contents/IContentAdminAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Contents/IContentAdminAppService.cs deleted file mode 100644 index 28a1e7d992..0000000000 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Contents/IContentAdminAppService.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Threading.Tasks; -using Volo.Abp.Application.Dtos; -using Volo.Abp.Application.Services; - -namespace Volo.CmsKit.Admin.Contents; -public interface IContentAdminAppService : IApplicationService -{ - Task> GetWidgetsAsync(); -} diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo.CmsKit.Admin.Application.csproj b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo.CmsKit.Admin.Application.csproj index be0f0d9184..31b472d7ee 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo.CmsKit.Admin.Application.csproj +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo.CmsKit.Admin.Application.csproj @@ -13,4 +13,8 @@ + + + + diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Contents/ContentAdminAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Contents/ContentAdminAppService.cs deleted file mode 100644 index 8d06586e29..0000000000 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Contents/ContentAdminAppService.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Linq; -using System.Threading.Tasks; -using Microsoft.Extensions.Options; -using Volo.Abp.Application.Dtos; -using Volo.CmsKit.Contents; - -namespace Volo.CmsKit.Admin.Contents; - -public class ContentAdminAppService : CmsKitAdminAppServiceBase, IContentAdminAppService -{ - private readonly CmsKitContentWidgetOptions _options; - - public ContentAdminAppService(IOptions options) - { - _options = options.Value; - } - - public virtual Task> GetWidgetsAsync() - { - return Task.FromResult(new ListResultDto() - { - Items = _options.WidgetConfigs - .Select(n => - new ContentWidgetDto - { - Key = n.Key, - Details = new WidgetDetailDto() { EditorComponentName = n.Value.EditorComponentName, Name = n.Value.Name }, - - }).ToList() - }); - } -} \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi.Client/ClientProxies/ContentAdminClientProxy.Generated.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi.Client/ClientProxies/ContentAdminClientProxy.Generated.cs deleted file mode 100644 index 30c6052af3..0000000000 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi.Client/ClientProxies/ContentAdminClientProxy.Generated.cs +++ /dev/null @@ -1,22 +0,0 @@ -// This file is automatically generated by ABP framework to use MVC Controllers from CSharp -using System; -using System.Threading.Tasks; -using Volo.Abp.Application.Dtos; -using Volo.Abp.Http.Client; -using Volo.Abp.Http.Modeling; -using Volo.Abp.DependencyInjection; -using Volo.Abp.Http.Client.ClientProxying; -using Volo.CmsKit.Admin.Contents; - -// ReSharper disable once CheckNamespace -namespace Volo.CmsKit.Admin.Contents.ClientProxies; - -[Dependency(ReplaceServices = true)] -[ExposeServices(typeof(IContentAdminAppService), typeof(ContentAdminClientProxy))] -public partial class ContentAdminClientProxy : ClientProxyBase, IContentAdminAppService -{ - public virtual async Task> GetWidgetsAsync() - { - return await RequestAsync>(nameof(GetWidgetsAsync)); - } -} diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi.Client/ClientProxies/ContentAdminClientProxy.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi.Client/ClientProxies/ContentAdminClientProxy.cs deleted file mode 100644 index d2caea5777..0000000000 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi.Client/ClientProxies/ContentAdminClientProxy.cs +++ /dev/null @@ -1,7 +0,0 @@ -// This file is part of ContentAdminClientProxy, you can customize it here -// ReSharper disable once CheckNamespace -namespace Volo.CmsKit.Admin.Contents.ClientProxies; - -public partial class ContentAdminClientProxy -{ -} diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi.Client/ClientProxies/cms-kit-admin-generate-proxy.json b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi.Client/ClientProxies/cms-kit-admin-generate-proxy.json index 32a833e884..8a9e38e4f9 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi.Client/ClientProxies/cms-kit-admin-generate-proxy.json +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi.Client/ClientProxies/cms-kit-admin-generate-proxy.json @@ -1191,35 +1191,6 @@ } } }, - "Volo.CmsKit.Admin.Contents.ContentAdminController": { - "controllerName": "ContentAdmin", - "controllerGroupName": "ContentAdmin", - "isRemoteService": true, - "apiVersion": null, - "type": "Volo.CmsKit.Admin.Contents.ContentAdminController", - "interfaces": [ - { - "type": "Volo.CmsKit.Admin.Contents.IContentAdminAppService" - } - ], - "actions": { - "GetWidgetsAsync": { - "uniqueName": "GetWidgetsAsync", - "name": "GetWidgetsAsync", - "httpMethod": "GET", - "url": "api/cms-kit-admin/contents", - "supportedVersions": [], - "parametersOnMethod": [], - "parameters": [], - "returnValue": { - "type": "Volo.Abp.Application.Dtos.ListResultDto", - "typeSimple": "Volo.Abp.Application.Dtos.ListResultDto" - }, - "allowAnonymous": null, - "implementFrom": "Volo.CmsKit.Admin.Contents.IContentAdminAppService" - } - } - }, "Volo.CmsKit.Admin.Comments.CommentAdminController": { "controllerName": "CommentAdmin", "controllerGroupName": "CommentAdmin", diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Contents/ContentAdminController.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Contents/ContentAdminController.cs deleted file mode 100644 index 83bfcde600..0000000000 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Contents/ContentAdminController.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc; -using Volo.Abp; -using Volo.Abp.Application.Dtos; - -namespace Volo.CmsKit.Admin.Contents; - -[RemoteService(Name = CmsKitAdminRemoteServiceConsts.RemoteServiceName)] -[Area(CmsKitAdminRemoteServiceConsts.ModuleName)] -[Route("api/cms-kit-admin/contents")] -public class ContentAdminController : CmsKitAdminController, IContentAdminAppService -{ - protected IContentAdminAppService ContentAdminAppService { get; } - - public ContentAdminController(IContentAdminAppService contentAdminAppService) - { - ContentAdminAppService = contentAdminAppService; - } - - [HttpGet] - public virtual Task> GetWidgetsAsync() - { - return ContentAdminAppService.GetWidgetsAsync(); - } -} diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/AddWidgetModal.cshtml b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/AddWidgetModal.cshtml index be33dc698e..6af4cb0a90 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/AddWidgetModal.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/AddWidgetModal.cshtml @@ -14,34 +14,39 @@ @section scripts { } +@{ + bool isDefinedWidget = Model.Widgets.Count() > 1; +} + + + +
+ @if (isDefinedWidget) + { + - - - -
- @if (Model.Widgets.Count() > 1) + foreach (var item in Model.ViewModel.Details) { - - - foreach (var item in Model.ViewModel.Details) + if (item.EditorComponentName is not null) { - if (item.EditorComponentName is not null) - { - - } + } } - else - { -

@L["PleaseConfigureWidgets"].Value

- } + } + else + { +

@L["PleaseConfigureWidgets"].Value

+ }
- + @if (isDefinedWidget) + { + + }
diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/AddWidgetModal.cshtml.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/AddWidgetModal.cshtml.cs index 5b1e8e5ea7..135e9d9257 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/AddWidgetModal.cshtml.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Contents/AddWidgetModal.cshtml.cs @@ -3,38 +3,48 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Rendering; +using Microsoft.Extensions.Options; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form; using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; using Volo.CmsKit.Admin.Contents; using Volo.CmsKit.Contents; +using Volo.CmsKit.Web.Contents; namespace Volo.CmsKit.Admin.Web.Pages.CmsKit.Contents; public class AddWidgetModal : AbpPageModel { - protected IContentAdminAppService ContentAdminAppService { get; } [BindProperty] public ContentViewModel ViewModel { get; set; } public List Widgets { get; set; } = new(); - public AddWidgetModal(IContentAdminAppService contentAdminAppService) + private readonly CmsKitContentWidgetOptions _options; + + public AddWidgetModal(IOptions options) { - ContentAdminAppService = contentAdminAppService; + _options = options.Value; } public async Task OnGetAsync() { - var widgets = await ContentAdminAppService.GetWidgetsAsync(); + var widgets = _options.WidgetConfigs + .Select(n => + new ContentWidgetDto + { + Key = n.Key, + Details = new WidgetDetailDto() { EditorComponentName = n.Value.EditorComponentName, Name = n.Value.Name }, + + }).ToList(); + ViewModel = new ContentViewModel() { - Details = widgets.Items.Select(p => p.Details).ToList() + Details = widgets.Select(p => p.Details).ToList() }; Widgets = new List() { new(string.Empty, string.Empty) }; Widgets.AddRange(widgets - .Items .Select(w => new SelectListItem(w.Key, w.Details.Name)) .ToList()); } diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/wwwroot/client-proxies/cms-kit-admin-proxy.js b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/wwwroot/client-proxies/cms-kit-admin-proxy.js index 94017ec7e2..3a61ef6a78 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/wwwroot/client-proxies/cms-kit-admin-proxy.js +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/wwwroot/client-proxies/cms-kit-admin-proxy.js @@ -247,21 +247,6 @@ })(); - // controller volo.cmsKit.admin.contents.contentAdmin - - (function(){ - - abp.utils.createNamespace(window, 'volo.cmsKit.admin.contents.contentAdmin'); - - volo.cmsKit.admin.contents.contentAdmin.getWidgets = function(ajaxParams) { - return abp.ajax($.extend(true, { - url: abp.appPath + 'api/cms-kit-admin/contents', - type: 'GET' - }, ajaxParams)); - }; - - })(); - // controller volo.cmsKit.admin.comments.commentAdmin (function(){ diff --git a/modules/cms-kit/src/Volo.CmsKit.Common.Application.Contracts/Volo/CmsKit/Contents/BlogPostCommonDto.cs b/modules/cms-kit/src/Volo.CmsKit.Common.Application.Contracts/Volo/CmsKit/Contents/BlogPostCommonDto.cs index c2b2373d9c..a7bc27d713 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Common.Application.Contracts/Volo/CmsKit/Contents/BlogPostCommonDto.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Common.Application.Contracts/Volo/CmsKit/Contents/BlogPostCommonDto.cs @@ -1,12 +1,11 @@ using System; -using System.Collections.Generic; using Volo.Abp.Application.Dtos; using Volo.CmsKit.Users; namespace Volo.CmsKit.Contents; [Serializable] -public class BlogPostCommonDto : AuditedEntityDto, IContent +public class BlogPostCommonDto : AuditedEntityDto { public Guid BlogId { get; set; } @@ -16,8 +15,6 @@ public class BlogPostCommonDto : AuditedEntityDto, IContent public string ShortDescription { get; set; } - public List ContentFragments { get; set; } - public string Content { get; set; } public Guid? CoverImageMediaId { get; set; } diff --git a/modules/cms-kit/src/Volo.CmsKit.Common.Application.Contracts/Volo/CmsKit/Contents/IContentAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Common.Application.Contracts/Volo/CmsKit/Contents/IContentAppService.cs deleted file mode 100644 index ec2b9bcf42..0000000000 --- a/modules/cms-kit/src/Volo.CmsKit.Common.Application.Contracts/Volo/CmsKit/Contents/IContentAppService.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using Volo.Abp.Application.Services; - -namespace Volo.CmsKit.Contents; - -public interface IContentAppService : IApplicationService -{ - Task> ParseAsync(string content); -} diff --git a/modules/cms-kit/src/Volo.CmsKit.Common.Application.Contracts/Volo/CmsKit/Contents/PageDto.cs b/modules/cms-kit/src/Volo.CmsKit.Common.Application.Contracts/Volo/CmsKit/Contents/PageDto.cs index 0b573be372..d495c5de20 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Common.Application.Contracts/Volo/CmsKit/Contents/PageDto.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Common.Application.Contracts/Volo/CmsKit/Contents/PageDto.cs @@ -5,7 +5,7 @@ using Volo.Abp.Application.Dtos; namespace Volo.CmsKit.Contents; [Serializable] -public class PageDto : EntityDto, IContent +public class PageDto : EntityDto { public string Title { get; set; } @@ -13,8 +13,6 @@ public class PageDto : EntityDto, IContent public string Content { get; set; } - public List ContentFragments { get; set; } - public string Script { get; set; } public string Style { get; set; } diff --git a/modules/cms-kit/src/Volo.CmsKit.Common.Application/Volo/CmsKit/Contents/ContentAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Common.Application/Volo/CmsKit/Contents/ContentAppService.cs deleted file mode 100644 index a227f31e18..0000000000 --- a/modules/cms-kit/src/Volo.CmsKit.Common.Application/Volo/CmsKit/Contents/ContentAppService.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using Volo.Abp.GlobalFeatures; -using Volo.CmsKit.GlobalFeatures; - -namespace Volo.CmsKit.Contents; - -[RequiresGlobalFeature(typeof(PagesFeature))] -public class ContentAppService : CmsKitAppServiceBase, IContentAppService -{ - protected ContentParser ContentParser { get; } - - public ContentAppService(ContentParser contentParser) - { - ContentParser = contentParser; - } - - public async Task> ParseAsync(string content) - { - return await ContentParser.ParseAsync(content); - } -} diff --git a/modules/cms-kit/src/Volo.CmsKit.Common.Web/Pages/CmsKit/Components/ContentPreview/ContentPreviewViewComponent.cs b/modules/cms-kit/src/Volo.CmsKit.Common.Web/Pages/CmsKit/Components/ContentPreview/ContentPreviewViewComponent.cs index 987c404e31..2251f6d0cd 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Common.Web/Pages/CmsKit/Components/ContentPreview/ContentPreviewViewComponent.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Common.Web/Pages/CmsKit/Components/ContentPreview/ContentPreviewViewComponent.cs @@ -6,21 +6,22 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Volo.Abp.AspNetCore.Mvc; using Volo.CmsKit.Contents; +using Volo.CmsKit.Web.Contents; namespace Volo.CmsKit.Web.Pages.CmsKit.Components.ContentPreview; public class ContentPreviewViewComponent : AbpViewComponent { - protected IContentAppService ContentAppService { get; } + protected ContentParser ContentParser { get; } - public ContentPreviewViewComponent(IContentAppService contentAppService) + public ContentPreviewViewComponent(ContentParser contentParser) { - ContentAppService = contentAppService; + ContentParser = contentParser; } public virtual async Task InvokeAsync(string content) { - var fragments = await ContentAppService.ParseAsync(content); + var fragments = await ContentParser.ParseAsync(content); return View("~/Pages/CmsKit/Components/ContentPreview/Default.cshtml", new DefaultContentDto { diff --git a/modules/cms-kit/src/Volo.CmsKit.Common.Application/Volo/CmsKit/Contents/CmsKitContentWidgetOptions.cs b/modules/cms-kit/src/Volo.CmsKit.Common.Web/Pages/CmsKit/Components/Contents/CmsKitContentWidgetOptions.cs similarity index 92% rename from modules/cms-kit/src/Volo.CmsKit.Common.Application/Volo/CmsKit/Contents/CmsKitContentWidgetOptions.cs rename to modules/cms-kit/src/Volo.CmsKit.Common.Web/Pages/CmsKit/Components/Contents/CmsKitContentWidgetOptions.cs index 34eb41d3a0..ad643f7770 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Common.Application/Volo/CmsKit/Contents/CmsKitContentWidgetOptions.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Common.Web/Pages/CmsKit/Components/Contents/CmsKitContentWidgetOptions.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace Volo.CmsKit.Contents; +namespace Volo.CmsKit.Web.Contents; public class CmsKitContentWidgetOptions { diff --git a/modules/cms-kit/src/Volo.CmsKit.Common.Application/Volo/CmsKit/Contents/ContentParser.cs b/modules/cms-kit/src/Volo.CmsKit.Common.Web/Pages/CmsKit/Components/Contents/ContentParser.cs similarity index 98% rename from modules/cms-kit/src/Volo.CmsKit.Common.Application/Volo/CmsKit/Contents/ContentParser.cs rename to modules/cms-kit/src/Volo.CmsKit.Common.Web/Pages/CmsKit/Components/Contents/ContentParser.cs index aea5cc2a82..290222a376 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Common.Application/Volo/CmsKit/Contents/ContentParser.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Common.Web/Pages/CmsKit/Components/Contents/ContentParser.cs @@ -5,9 +5,10 @@ using System.Threading.Tasks; using Microsoft.Extensions.Options; using Volo.Abp.Data; using Volo.Abp.DependencyInjection; +using Volo.CmsKit.Contents; using static Volo.CmsKit.Contents.ContentConsts; -namespace Volo.CmsKit.Contents; +namespace Volo.CmsKit.Web.Contents; public class ContentParser : ITransientDependency { diff --git a/modules/cms-kit/src/Volo.CmsKit.Common.Application/Volo/CmsKit/Contents/ContentWidgetConfig.cs b/modules/cms-kit/src/Volo.CmsKit.Common.Web/Pages/CmsKit/Components/Contents/ContentWidgetConfig.cs similarity index 87% rename from modules/cms-kit/src/Volo.CmsKit.Common.Application/Volo/CmsKit/Contents/ContentWidgetConfig.cs rename to modules/cms-kit/src/Volo.CmsKit.Common.Web/Pages/CmsKit/Components/Contents/ContentWidgetConfig.cs index e14c1888ac..69be0703fa 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Common.Application/Volo/CmsKit/Contents/ContentWidgetConfig.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Common.Web/Pages/CmsKit/Components/Contents/ContentWidgetConfig.cs @@ -1,4 +1,4 @@ -namespace Volo.CmsKit.Contents; +namespace Volo.CmsKit.Web.Contents; public class ContentWidgetConfig { diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Blogs/BlogPostPublicAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Blogs/BlogPostPublicAppService.cs index 87e851431d..5041406bd0 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Blogs/BlogPostPublicAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Blogs/BlogPostPublicAppService.cs @@ -6,6 +6,7 @@ using Volo.Abp.Application.Dtos; using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; using Volo.CmsKit.Blogs; + using Volo.CmsKit.Contents; using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; @@ -20,16 +21,13 @@ public class BlogPostPublicAppService : CmsKitPublicAppServiceBase, IBlogPostPub protected IBlogRepository BlogRepository { get; } protected IBlogPostRepository BlogPostRepository { get; } - protected ContentParser ContentParser { get; } public BlogPostPublicAppService( IBlogRepository blogRepository, - IBlogPostRepository blogPostRepository, - ContentParser contentParser) + IBlogPostRepository blogPostRepository) { BlogRepository = blogRepository; BlogPostRepository = blogPostRepository; - ContentParser = contentParser; } public virtual async Task GetAsync( @@ -39,10 +37,7 @@ public class BlogPostPublicAppService : CmsKitPublicAppServiceBase, IBlogPostPub var blogPost = await BlogPostRepository.GetBySlugAsync(blog.Id, blogPostSlug); - var blogPostDto = ObjectMapper.Map(blogPost); - blogPostDto.ContentFragments = await ContentParser.ParseAsync(blogPost.Content); - - return blogPostDto; + return ObjectMapper.Map(blogPost); } public virtual async Task> GetListAsync([NotNull] string blogSlug, BlogPostGetListInput input) diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Pages/PagePublicAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Pages/PagePublicAppService.cs index f20a181e9b..c93adcd5a7 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Pages/PagePublicAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Pages/PagePublicAppService.cs @@ -13,12 +13,10 @@ namespace Volo.CmsKit.Public.Pages; public class PagePublicAppService : CmsKitPublicAppServiceBase, IPagePublicAppService { protected IPageRepository PageRepository { get; } - protected ContentParser ContentParser { get; } - public PagePublicAppService(IPageRepository pageRepository, ContentParser contentParser) + public PagePublicAppService(IPageRepository pageRepository) { PageRepository = pageRepository; - ContentParser = contentParser; } public virtual async Task FindBySlugAsync(string slug) @@ -30,8 +28,6 @@ public class PagePublicAppService : CmsKitPublicAppServiceBase, IPagePublicAppSe return null; } - var pageDto = ObjectMapper.Map(page); - pageDto.ContentFragments = await ContentParser.ParseAsync(page.Content); - return pageDto; + return ObjectMapper.Map(page); } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/PublicApplicationAutoMapperProfile.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/PublicApplicationAutoMapperProfile.cs index bd0c6d5e6c..92620743ff 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/PublicApplicationAutoMapperProfile.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/PublicApplicationAutoMapperProfile.cs @@ -30,11 +30,9 @@ public class PublicApplicationAutoMapperProfile : Profile CreateMap(); - CreateMap() - .Ignore(x => x.ContentFragments); - - CreateMap() - .Ignore(x => x.ContentFragments); + CreateMap(); + + CreateMap(); CreateMap(); diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/CmsKitPublicWebModule.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Web/CmsKitPublicWebModule.cs index 88b01c8ae9..3ce96f1a86 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/CmsKitPublicWebModule.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/CmsKitPublicWebModule.cs @@ -2,7 +2,7 @@ using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.AspNetCore.Mvc.Localization; -using Volo.Abp.AspNetCore.Mvc.UI.Components.LayoutHook; +using Volo.Abp.Ui.LayoutHooks; using Volo.Abp.AutoMapper; using Volo.Abp.GlobalFeatures; using Volo.Abp.Http.ProxyScripting.Generators.JQuery; diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPost.cshtml b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPost.cshtml index fe9227f194..d5dc5a0be8 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPost.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPost.cshtml @@ -9,9 +9,9 @@ @using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.ReactionSelection @using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Rating @using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Tags +@using Volo.CmsKit.Web.Renderers @using Volo.Abp.AspNetCore.Mvc.UI.Packages.HighlightJs @using Volo.CmsKit.Contents -@using Volo.CmsKit.Web.Renderers @inherits CmsKitPublicPageBase @@ -21,7 +21,7 @@ @{ - string dummyImageSource = "https://dummyimage.com/1280x720/a3a3a3/fff.png?text=" + Model.BlogPost.Title; + string dummyImageSource = "https://dummyimage.com/1280x720/a3a3a3/fff.png?text=" + Model.ViewModel.Title; var isScrollIndexEnabled = GlobalFeatureManager.Instance.IsEnabled() && Model.BlogPostScrollIndexFeature?.IsEnabled == true; } @@ -32,14 +32,13 @@ } - } -@section scripts{ + @section scripts{ @if (isScrollIndexEnabled) { @@ -55,41 +54,51 @@ } -
-
- - - - -
-

@Model.BlogPost.Title

-

- - @@@Model.BlogPost.Author?.UserName - - @Model.BlogPost.CreationTime -

- @await Component.InvokeAsync("ContentFragment", new { contentDto = Model.BlogPost }) -

- @if (Model.BlogPost.LastModificationTime != null) +

+
+ + + + +
+

@Model.ViewModel.Title

+

+ + @@@Model.ViewModel.Author?.UserName + + @Model.ViewModel.CreationTime +

+ @foreach (var contentFragment in Model.ViewModel.ContentFragments) { - @L["LastModification"].Value : @Model.BlogPost.LastModificationTime + if (contentFragment.Type == ContentConsts.Markdown) + { + @Html.Raw(await MarkdownRenderer.RenderAsync(contentFragment.GetProperty("Content"), allowHtmlTags: true, preventXSS: true)) + } + else if (contentFragment.Type == ContentConsts.Widget) + { + @await Component.InvokeAsync(contentFragment.GetProperty("Type"), contentFragment.ExtraProperties.ConvertToDynamicObject()) + } } -

-
+

+ @if (Model.ViewModel.LastModificationTime != null) + { + @L["LastModification"].Value : @Model.ViewModel.LastModificationTime + } +

+
- @if (GlobalFeatureManager.Instance.IsEnabled()) - { - if (Model.TagsFeature?.IsEnabled == true) + @if (GlobalFeatureManager.Instance.IsEnabled()) { - @await Component.InvokeAsync(typeof(TagViewComponent), new + if (Model.TagsFeature?.IsEnabled == true) { - entityType = Volo.CmsKit.Blogs.BlogPostConsts.EntityType, - entityId = Model.BlogPost.Id.ToString(), - urlFormat = $"/blogs/{Model.BlogSlug}?tagId={{TagId}}" - }) + @await Component.InvokeAsync(typeof(TagViewComponent), new + { + entityType = Volo.CmsKit.Blogs.BlogPostConsts.EntityType, + entityId = Model.ViewModel.Id.ToString(), + urlFormat = $"/blogs/{Model.BlogSlug}?tagId={{TagId}}" + }) + } } - }
@@ -100,10 +109,10 @@ if (Model.ReactionsFeature?.IsEnabled == true) { @await Component.InvokeAsync(typeof(ReactionSelectionViewComponent), new - { - entityType = Volo.CmsKit.Blogs.BlogPostConsts.EntityType, - entityId = Model.BlogPost.Id.ToString() - }) + { + entityType = Volo.CmsKit.Blogs.BlogPostConsts.EntityType, + entityId = Model.ViewModel.Id.ToString() + }) } } @@ -113,10 +122,10 @@ if (Model.RatingsFeature?.IsEnabled == true) { @await Component.InvokeAsync(typeof(RatingViewComponent), new - { - entityType = Volo.CmsKit.Blogs.BlogPostConsts.EntityType, - entityId = Model.BlogPost.Id.ToString() - }) + { + entityType = Volo.CmsKit.Blogs.BlogPostConsts.EntityType, + entityId = Model.ViewModel.Id.ToString() + }) } } @@ -124,7 +133,6 @@
- @if (isScrollIndexEnabled) {
@@ -132,7 +140,7 @@
@L["InThisDocument"]
- +
@@ -153,7 +161,7 @@ @await Component.InvokeAsync(typeof(DefaultBlogPostCommentViewComponent), new { entityType = Volo.CmsKit.Blogs.BlogPostConsts.EntityType, - entityId = Model.BlogPost.Id.ToString() + entityId = Model.ViewModel.Id.ToString() }) } } \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPost.cshtml.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPost.cshtml.cs index e1d9a3b0f7..87630f9bd0 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPost.cshtml.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPost.cshtml.cs @@ -1,10 +1,12 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Volo.Abp.GlobalFeatures; +using Volo.Abp.ObjectMapping; using Volo.CmsKit.Blogs; using Volo.CmsKit.Contents; using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.Public.Blogs; +using Volo.CmsKit.Web.Contents; namespace Volo.CmsKit.Public.Web.Pages.Public.CmsKit.Blogs; @@ -16,7 +18,7 @@ public class BlogPostModel : CmsKitPublicPageModelBase [BindProperty(SupportsGet = true)] public string BlogPostSlug { get; set; } - public BlogPostCommonDto BlogPost { get; private set; } + public BlogPostViewModel ViewModel { get; private set; } public BlogFeatureDto CommentsFeature { get; private set; } @@ -25,48 +27,61 @@ public class BlogPostModel : CmsKitPublicPageModelBase public BlogFeatureDto RatingsFeature { get; private set; } public BlogFeatureDto TagsFeature { get; private set; } - + public BlogFeatureDto BlogPostScrollIndexFeature { get; private set; } protected IBlogPostPublicAppService BlogPostPublicAppService { get; } protected IBlogFeatureAppService BlogFeatureAppService { get; } + protected ContentParser ContentParser { get; } + public BlogPostModel( IBlogPostPublicAppService blogPostPublicAppService, - IBlogFeatureAppService blogFeaturePublicAppService) + IBlogFeatureAppService blogFeaturePublicAppService, + ContentParser contentParser) { BlogPostPublicAppService = blogPostPublicAppService; BlogFeatureAppService = blogFeaturePublicAppService; + ContentParser = contentParser; } - public virtual async Task OnGetAsync() + public virtual async Task OnGetAsync() { - BlogPost = await BlogPostPublicAppService.GetAsync(BlogSlug, BlogPostSlug); + var blogPostPublicDto = await BlogPostPublicAppService.GetAsync(BlogSlug, BlogPostSlug); + ViewModel = ObjectMapper.Map(blogPostPublicDto); + if (ViewModel == null) + { + return NotFound(); + } + + ViewModel.ContentFragments = await ContentParser.ParseAsync(blogPostPublicDto.Content); if (GlobalFeatureManager.Instance.IsEnabled()) { - CommentsFeature = await BlogFeatureAppService.GetOrDefaultAsync(BlogPost.BlogId, GlobalFeatures.CommentsFeature.Name); + CommentsFeature = await BlogFeatureAppService.GetOrDefaultAsync(ViewModel.BlogId, GlobalFeatures.CommentsFeature.Name); } if (GlobalFeatureManager.Instance.IsEnabled()) { - ReactionsFeature = await BlogFeatureAppService.GetOrDefaultAsync(BlogPost.BlogId, GlobalFeatures.ReactionsFeature.Name); + ReactionsFeature = await BlogFeatureAppService.GetOrDefaultAsync(ViewModel.BlogId, GlobalFeatures.ReactionsFeature.Name); } if (GlobalFeatureManager.Instance.IsEnabled()) { - RatingsFeature = await BlogFeatureAppService.GetOrDefaultAsync(BlogPost.BlogId, GlobalFeatures.RatingsFeature.Name); + RatingsFeature = await BlogFeatureAppService.GetOrDefaultAsync(ViewModel.BlogId, GlobalFeatures.RatingsFeature.Name); } if (GlobalFeatureManager.Instance.IsEnabled()) { - TagsFeature = await BlogFeatureAppService.GetOrDefaultAsync(BlogPost.BlogId, GlobalFeatures.TagsFeature.Name); + TagsFeature = await BlogFeatureAppService.GetOrDefaultAsync(ViewModel.BlogId, GlobalFeatures.TagsFeature.Name); } if (GlobalFeatureManager.Instance.IsEnabled()) { - BlogPostScrollIndexFeature = await BlogFeatureAppService.GetOrDefaultAsync(BlogPost.BlogId, GlobalFeatures.BlogPostScrollIndexFeature.Name); + BlogPostScrollIndexFeature = await BlogFeatureAppService.GetOrDefaultAsync(ViewModel.BlogId, GlobalFeatures.BlogPostScrollIndexFeature.Name); } + + return Page(); } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPostViewModel.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPostViewModel.cs new file mode 100644 index 0000000000..789d2687fc --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPostViewModel.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using AutoMapper; +using Volo.Abp.Application.Dtos; +using Volo.CmsKit.Contents; +using Volo.CmsKit.Users; + +namespace Volo.CmsKit.Public.Web.Pages.Public.CmsKit.Blogs; + +[AutoMap(typeof(BlogPostCommonDto), ReverseMap = true)] +public class BlogPostViewModel : AuditedEntityDto +{ + public Guid BlogId { get; set; } + + public string Title { get; set; } + + public string Slug { get; set; } + + public string ShortDescription { get; set; } + + public string Content { get; set; } + + public List ContentFragments { get; set; } + + public Guid? CoverImageMediaId { get; set; } + + public CmsUserDto Author { get; set; } +} diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Pages/Index.cshtml b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Pages/Index.cshtml index 250303177b..e14733695a 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Pages/Index.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Pages/Index.cshtml @@ -5,27 +5,39 @@ @using Volo.Abp.Data @using Volo.Abp.AspNetCore.Mvc.UI.Packages.HighlightJs; @using Volo.Abp.AspNetCore.Mvc.UI.Widgets; - +@using Volo.CmsKit.Web.Renderers @model Volo.CmsKit.Public.Web.Pages.Public.CmsKit.Pages.IndexModel +@inject IMarkdownToHtmlRenderer MarkdownRenderer + @section styles{ } @section scripts{ } - @await Component.InvokeAsync("ContentFragment", new { contentDto = Model.PageDto }) + @foreach (ContentFragment contentFragment in Model.ViewModel.ContentFragments) + { + if (contentFragment.Type == ContentConsts.Markdown) + { + @Html.Raw(await MarkdownRenderer.RenderAsync(contentFragment.GetProperty("Content"), allowHtmlTags: true, preventXSS: true)) + } + else if (contentFragment.Type == ContentConsts.Widget) + { + @await Component.InvokeAsync(contentFragment.GetProperty("Type"), contentFragment.ExtraProperties.ConvertToDynamicObject()) + } + } diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Pages/Index.cshtml.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Pages/Index.cshtml.cs index 7ae92d7016..18eb184742 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Pages/Index.cshtml.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Pages/Index.cshtml.cs @@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Mvc; using Volo.CmsKit.Contents; using Volo.CmsKit.Public.Pages; +using Volo.CmsKit.Web.Contents; using Volo.CmsKit.Web.Pages; namespace Volo.CmsKit.Public.Web.Pages.Public.CmsKit.Pages; @@ -13,21 +14,26 @@ public class IndexModel : CommonPageModel protected IPagePublicAppService PagePublicAppService { get; } - public PageDto PageDto { get; private set; } + protected ContentParser ContentParser { get; } - public IndexModel(IPagePublicAppService pagePublicAppService) + public PageViewModel ViewModel { get; private set; } + + public IndexModel(IPagePublicAppService pagePublicAppService, ContentParser contentParser) { PagePublicAppService = pagePublicAppService; + ContentParser = contentParser; } - public async Task OnGetAsync() + public virtual async Task OnGetAsync() { - PageDto = await PagePublicAppService.FindBySlugAsync(Slug); - - if (PageDto == null) + var pageDto = await PagePublicAppService.FindBySlugAsync(Slug); + ViewModel = ObjectMapper.Map(pageDto); + if (ViewModel == null) { return NotFound(); } + + ViewModel.ContentFragments = await ContentParser.ParseAsync(pageDto.Content); return Page(); } diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Pages/PageViewModel.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Pages/PageViewModel.cs index 5e5df3e917..3195826093 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Pages/PageViewModel.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Pages/PageViewModel.cs @@ -1,9 +1,12 @@ using System; using System.Collections.Generic; +using AutoMapper; using Volo.CmsKit.Contents; +using Volo.CmsKit.Public.Pages; namespace Volo.CmsKit.Public.Web.Pages.Public.CmsKit.Pages; +[AutoMap(typeof(PageDto), ReverseMap = true)] public class PageViewModel { public Guid Id { get; set; } @@ -11,4 +14,8 @@ public class PageViewModel public string Title { get; set; } public List ContentFragments { get; set; } + + public string Script { get; set; } + + public string Style { get; set; } } \ No newline at end of file diff --git a/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Contents/ContentAdminAppService_Tests.cs b/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Contents/ContentAdminAppService_Tests.cs deleted file mode 100644 index f338d3d7d1..0000000000 --- a/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Contents/ContentAdminAppService_Tests.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System.Linq; -using System.Threading.Tasks; -using Shouldly; -using Volo.CmsKit.Admin.Contents; -using Xunit; - -namespace Volo.CmsKit.Contents; - -public class ContentAdminAppService_Tests : CmsKitApplicationTestBase -{ - private readonly IContentAdminAppService _contentAdminAppService; - - public ContentAdminAppService_Tests() - { - _contentAdminAppService = GetRequiredService(); - } - - [Fact] - public async Task ShouldGet_PagedListAsync() - { - var widgets = await _contentAdminAppService.GetWidgetsAsync(); - - widgets.Items.Count.ShouldBe(0); - widgets.Items.Any().ShouldBeFalse(); - } - -} diff --git a/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Contents/ContentParser_Test.cs b/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Contents/ContentParser_Test.cs deleted file mode 100644 index b08a127111..0000000000 --- a/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Contents/ContentParser_Test.cs +++ /dev/null @@ -1,138 +0,0 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using Microsoft.Extensions.Options; -using Shouldly; -using Xunit; - -namespace Volo.CmsKit.Contents; -public class ContentParser_Test : CmsKitDomainTestBase -{ - private readonly CmsKitTestData testData; - private readonly IOptions _options; - private ContentParser contentParser; - - public ContentParser_Test() - { - testData = GetRequiredService(); - _options = GetRequiredService>(); - } - - [Fact] - public async Task ParseAsync_ShouldWorkWithDifferentWidgetTypes() - { - _options.Value.AddWidget(testData.PollName, testData.WidgetName, string.Empty); - _options.Value.AddWidget("ImageGallery", "ImageGallery", string.Empty); - contentParser = new ContentParser(_options); - - var content = @"**ABP Framework** is completely open source and developed in a community-driven manner. - [Widget Type=""Poll"" Code=""poll-name""] - Thanks _for_ *your * feedback. - [Widget GalleryName=""Xyz"" Type=""ImageGallery"" Source=""GoogleDrive""]"; - - var widgets = await contentParser.ParseAsync(content); - - widgets.ShouldNotBeNull(); - widgets.Count.ShouldBe(4); - widgets[1].ExtraProperties.Count.ShouldBe(2); - widgets[3].ExtraProperties.Count.ShouldBe(3); - } - - [Fact] - public async Task ParseAsync_ShouldWorkWithoutConfigOptions() - { - var content = @"**ABP Framework** is completely open source and developed in a community-driven manner. - [Widget Type= ""Poll"" Code =""poll-name""] - Thanks _for_ *your * feedback."; - - contentParser = new ContentParser(_options); - var widgets = await contentParser.ParseAsync(content); - - widgets.ShouldNotBeNull(); - widgets.Count.ShouldBe(1);//Ignored Widget - } - - [Fact] - public async Task ParseAsync_ShouldWorkWithWrongConfigOptions() - { - _options.Value.AddWidget(testData.WidgetName, testData.PollName, string.Empty); - contentParser = new ContentParser(_options); - - var content = @"**ABP Framework** is completely open source and developed in a community-driven manner. - [Widget Type= ""Poll"" Code =""poll-name""] - Thanks _for_ *your * feedback."; - - var widgets = await contentParser.ParseAsync(content); - - widgets.ShouldNotBeNull(); - widgets.Count.ShouldBe(2); - } - - [Fact] - public async Task ParseAsync_ShouldWorkWithWrongWidgetType() - { - _options.Value.AddWidget(testData.PollName, testData.WidgetName, string.Empty); - contentParser = new ContentParser(_options); - - var content = @"**ABP Framework** is completely open source and developed in a community-driven manner. - [Widget Wrong Type= ""Poll"" Code =""poll-name""] - Thanks _for_ *your * feedback."; - - var widgets = await contentParser.ParseAsync(content); - - widgets.ShouldNotBeNull(); - widgets.Count.ShouldBe(2); - } - - [Fact] - public async Task ParseAsync_ShouldWorkWithWrongPollName() - { - _options.Value.AddWidget(testData.PollName, testData.WidgetName, string.Empty); - contentParser = new ContentParser(_options); - - var content = @"**ABP Framework** is completely open source and developed in a community-driven manner. - [Widget Type= ""Poll"" PollWrongName =""poll-name""] - Thanks _for_ *your * feedback."; - - var widgets = await contentParser.ParseAsync(content); - - widgets.ShouldNotBeNull(); - widgets.Count.ShouldBe(3); - } - - [Theory] - [MemberData(nameof(ExampleData))] - public async Task ParseAsync_ShouldWorkProperlyWithCorrectInputs(string content, int expectedLine) - { - _options.Value.AddWidget(testData.PollName, testData.WidgetName, string.Empty); - contentParser = new ContentParser(_options); - - var widgets = await contentParser.ParseAsync(content); - - widgets.ShouldNotBeNull(); - widgets.Count.ShouldBe(expectedLine); - } - - public static IEnumerable ExampleData => - new List - { - new object[] { @"**ABP Framework** is completely open source and developed in a community-driven manner. - [Widget Type=""Poll"" Code=""poll-name""] - Thanks _for_ *your * feedback.", 3}, - - new object[] { @"**ABP Framework** is completely open source and developed in a community-driven manner. - [Widget Type=""Poll"" Code=""poll-name""] - Thanks _for_ *your * feedback. - [Widget Type=""Poll"" Code=""poll-name1""]", 4 }, - - new object[] { @"**ABP Framework** is completely open source and developed in a community-driven manner. - Thanks _for_ *your * feedback. - [Widget Type=""Poll"" Code=""poll-name""]", 2 }, - - new object[] { @"[Widget Type=""Poll"" Code=""poll-name""] gg [Widget Type=""Poll"" Code=""poll-name1""]**ABP Framework** is completely open source and developed in a community-driven manner. - Thanks _for_ *your * feedback. - Thanks _for_ *your * feedback.", 4}, - - new object[] { @"Thanks _for_ *your * feedback. - Thanks _for_ *your * feedback.", 1} - }; -} diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Documents/DocumentDto.cs b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Documents/DocumentDto.cs index c415efa860..b574870fd8 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Documents/DocumentDto.cs +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Documents/DocumentDto.cs @@ -8,6 +8,8 @@ namespace Volo.Docs.Admin.Documents public class DocumentDto : EntityDto { public virtual Guid ProjectId { get; set; } + + public virtual string ProjectName { get; set; } public virtual string Name { get; set; } diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Documents/DocumentInfoDto.cs b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Documents/DocumentInfoDto.cs new file mode 100644 index 0000000000..545e665869 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Documents/DocumentInfoDto.cs @@ -0,0 +1,11 @@ +using System; + +namespace Volo.Docs.Admin.Documents; + +public class DocumentInfoDto +{ + public string Version { get; set; } + public string Format { get; set; } + public string LanguageCode { get; set; } + public Guid ProjectId { get; set; } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Documents/IDocumentAdminAppService.cs b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Documents/IDocumentAdminAppService.cs index 0770ec5d72..12bdbc87be 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Documents/IDocumentAdminAppService.cs +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Documents/IDocumentAdminAppService.cs @@ -19,5 +19,7 @@ namespace Volo.Docs.Admin.Documents Task RemoveFromCacheAsync(Guid documentId); Task ReindexAsync(Guid documentId); + + Task> GetFilterItemsAsync(); } } diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/tr.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/tr.json index cfd58936d7..dade32b970 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/tr.json +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/tr.json @@ -48,7 +48,7 @@ "Search": "Arama", "StartDate": "Başlangıç tarihi", "EndDate": "Bitiş tarihi", - "CreationTime": "oluşturma zamanı", + "CreationTime": "Oluşturma Zamanı", "LastUpdateTime": "Son Güncelleme", "LastSignificantUpdateTime": "Son önemli güncelleme", "Version": "Sürüm", diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Projects/IProjectAdminAppService.cs b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Projects/IProjectAdminAppService.cs index 9b832165d1..6f3d503f44 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Projects/IProjectAdminAppService.cs +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Projects/IProjectAdminAppService.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Threading.Tasks; using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Services; @@ -20,5 +21,6 @@ namespace Volo.Docs.Admin.Projects Task ReindexAsync(ReindexInput input); Task ReindexAllAsync(); + Task> GetListWithoutDetailsAsync(); } } diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Projects/ProjectWithoutDetailsDto.cs b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Projects/ProjectWithoutDetailsDto.cs new file mode 100644 index 0000000000..b6e6a301cb --- /dev/null +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Projects/ProjectWithoutDetailsDto.cs @@ -0,0 +1,9 @@ +using System; + +namespace Volo.Docs.Admin.Projects; + +public class ProjectWithoutDetailsDto +{ + public Guid Id { get; set; } + public string Name { get; set; } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/DocsAdminApplicationAutoMapperProfile.cs b/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/DocsAdminApplicationAutoMapperProfile.cs index 86e6d46e0c..01a7250ce5 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/DocsAdminApplicationAutoMapperProfile.cs +++ b/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/DocsAdminApplicationAutoMapperProfile.cs @@ -1,4 +1,5 @@ using AutoMapper; +using Volo.Abp.AutoMapper; using Volo.Docs.Admin.Documents; using Volo.Docs.Admin.Projects; using Volo.Docs.Documents; @@ -11,8 +12,10 @@ namespace Volo.Docs.Admin public DocsAdminApplicationAutoMapperProfile() { CreateMap(); - CreateMap(); + CreateMap().Ignore(x => x.ProjectName); CreateMap(); + CreateMap(); + CreateMap(); } } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Documents/DocumentAdminAppService.cs b/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Documents/DocumentAdminAppService.cs index af515b4be7..7d68681b1d 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Documents/DocumentAdminAppService.cs +++ b/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Documents/DocumentAdminAppService.cs @@ -5,7 +5,6 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.Logging; using Volo.Abp; -using Volo.Abp.Uow; using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Services; using Volo.Abp.Caching; @@ -217,6 +216,13 @@ namespace Volo.Docs.Admin.Documents await _elasticSearchService.AddOrUpdateAsync(document); } + public async Task> GetFilterItemsAsync() + { + var documents = await _documentRepository.GetUniqueListDocumentInfoAsync(); + return ObjectMapper.Map, List>(documents); + } + + private async Task UpdateDocumentUpdateInfoCache(Document document) { var cacheKey = $"DocumentUpdateInfo{document.ProjectId}#{document.Name}#{document.LanguageCode}#{document.Version}"; diff --git a/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Projects/ProjectAdminAppService.cs b/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Projects/ProjectAdminAppService.cs index 14833cd3e4..540ecfe275 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Projects/ProjectAdminAppService.cs +++ b/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Projects/ProjectAdminAppService.cs @@ -156,5 +156,11 @@ namespace Volo.Docs.Admin.Projects await ReindexProjectAsync(project.Id); } } + + public async Task> GetListWithoutDetailsAsync() + { + var projects = await _projectRepository.GetListWithoutDetailsAsync(); + return ObjectMapper.Map, List>(projects); + } } } diff --git a/modules/docs/src/Volo.Docs.Admin.HttpApi.Client/ClientProxies/DocumentsAdminClientProxy.Generated.cs b/modules/docs/src/Volo.Docs.Admin.HttpApi.Client/ClientProxies/DocumentsAdminClientProxy.Generated.cs index 7bb1ef0e87..e2b9fa2783 100644 --- a/modules/docs/src/Volo.Docs.Admin.HttpApi.Client/ClientProxies/DocumentsAdminClientProxy.Generated.cs +++ b/modules/docs/src/Volo.Docs.Admin.HttpApi.Client/ClientProxies/DocumentsAdminClientProxy.Generated.cs @@ -7,6 +7,7 @@ using Volo.Abp.Http.Modeling; using Volo.Abp.DependencyInjection; using Volo.Abp.Http.Client.ClientProxying; using Volo.Docs.Admin.Documents; +using System.Collections.Generic; // ReSharper disable once CheckNamespace namespace Volo.Docs.Admin.ClientProxies; @@ -62,4 +63,9 @@ public partial class DocumentsAdminClientProxy : ClientProxyBase> GetFilterItemsAsync() + { + return await RequestAsync>(nameof(GetFilterItemsAsync)); + } } diff --git a/modules/docs/src/Volo.Docs.Admin.HttpApi.Client/ClientProxies/ProjectsAdminClientProxy.Generated.cs b/modules/docs/src/Volo.Docs.Admin.HttpApi.Client/ClientProxies/ProjectsAdminClientProxy.Generated.cs index cb8d5c3947..072106df0e 100644 --- a/modules/docs/src/Volo.Docs.Admin.HttpApi.Client/ClientProxies/ProjectsAdminClientProxy.Generated.cs +++ b/modules/docs/src/Volo.Docs.Admin.HttpApi.Client/ClientProxies/ProjectsAdminClientProxy.Generated.cs @@ -7,6 +7,7 @@ using Volo.Abp.Http.Modeling; using Volo.Abp.DependencyInjection; using Volo.Abp.Http.Client.ClientProxying; using Volo.Docs.Admin.Projects; +using System.Collections.Generic; // ReSharper disable once CheckNamespace namespace Volo.Docs.Admin.ClientProxies; @@ -61,6 +62,11 @@ public partial class ProjectsAdminClientProxy : ClientProxyBase> GetListWithoutDetailsAsync() + { + return await RequestAsync>(nameof(GetListWithoutDetailsAsync)); + } + public virtual async Task ReindexAsync(ReindexInput input) { await RequestAsync(nameof(ReindexAsync), new ClientProxyRequestTypeValue diff --git a/modules/docs/src/Volo.Docs.Admin.HttpApi.Client/ClientProxies/docs-admin-generate-proxy.json b/modules/docs/src/Volo.Docs.Admin.HttpApi.Client/ClientProxies/docs-admin-generate-proxy.json index e85e6fbb43..c6cf885b09 100644 --- a/modules/docs/src/Volo.Docs.Admin.HttpApi.Client/ClientProxies/docs-admin-generate-proxy.json +++ b/modules/docs/src/Volo.Docs.Admin.HttpApi.Client/ClientProxies/docs-admin-generate-proxy.json @@ -7,6 +7,8 @@ "Volo.Docs.Admin.DocumentsAdminController": { "controllerName": "DocumentsAdmin", "controllerGroupName": "DocumentsAdmin", + "isRemoteService": true, + "apiVersion": null, "type": "Volo.Docs.Admin.DocumentsAdminController", "interfaces": [ { @@ -427,12 +429,29 @@ }, "allowAnonymous": null, "implementFrom": "Volo.Docs.Admin.Documents.IDocumentAdminAppService" + }, + "GetFilterItemsAsync": { + "uniqueName": "GetFilterItemsAsync", + "name": "GetFilterItemsAsync", + "httpMethod": "GET", + "url": "api/docs/admin/documents/GetFilterItems", + "supportedVersions": [], + "parametersOnMethod": [], + "parameters": [], + "returnValue": { + "type": "System.Collections.Generic.List", + "typeSimple": "[Volo.Docs.Admin.Documents.DocumentInfoDto]" + }, + "allowAnonymous": null, + "implementFrom": "Volo.Docs.Admin.Documents.IDocumentAdminAppService" } } }, "Volo.Docs.Admin.ProjectsAdminController": { "controllerName": "ProjectsAdmin", "controllerGroupName": "ProjectsAdmin", + "isRemoteService": true, + "apiVersion": null, "type": "Volo.Docs.Admin.ProjectsAdminController", "interfaces": [ { @@ -684,6 +703,21 @@ "allowAnonymous": null, "implementFrom": "Volo.Docs.Admin.Projects.IProjectAdminAppService" }, + "GetListWithoutDetailsAsync": { + "uniqueName": "GetListWithoutDetailsAsync", + "name": "GetListWithoutDetailsAsync", + "httpMethod": "GET", + "url": "api/docs/admin/projects/GetListProjectWithoutDetailsAsync", + "supportedVersions": [], + "parametersOnMethod": [], + "parameters": [], + "returnValue": { + "type": "System.Collections.Generic.List", + "typeSimple": "[Volo.Docs.Admin.Projects.ProjectWithoutDetailsDto]" + }, + "allowAnonymous": null, + "implementFrom": "Volo.Docs.Admin.Projects.IProjectAdminAppService" + }, "ReindexAsyncByInput": { "uniqueName": "ReindexAsyncByInput", "name": "ReindexAsync", diff --git a/modules/docs/src/Volo.Docs.Admin.HttpApi/Volo/Docs/Admin/DocumentsAdminController.cs b/modules/docs/src/Volo.Docs.Admin.HttpApi/Volo/Docs/Admin/DocumentsAdminController.cs index 9404ac0bde..c0586ed699 100644 --- a/modules/docs/src/Volo.Docs.Admin.HttpApi/Volo/Docs/Admin/DocumentsAdminController.cs +++ b/modules/docs/src/Volo.Docs.Admin.HttpApi/Volo/Docs/Admin/DocumentsAdminController.cs @@ -63,5 +63,12 @@ namespace Volo.Docs.Admin { await _documentAdminAppService.ReindexAsync(documentId); } + + [HttpGet] + [Route("GetFilterItems")] + public async Task> GetFilterItemsAsync() + { + return await _documentAdminAppService.GetFilterItemsAsync(); + } } } diff --git a/modules/docs/src/Volo.Docs.Admin.HttpApi/Volo/Docs/Admin/ProjectsAdminController.cs b/modules/docs/src/Volo.Docs.Admin.HttpApi/Volo/Docs/Admin/ProjectsAdminController.cs index 1696229bf8..ea0c7f1afd 100644 --- a/modules/docs/src/Volo.Docs.Admin.HttpApi/Volo/Docs/Admin/ProjectsAdminController.cs +++ b/modules/docs/src/Volo.Docs.Admin.HttpApi/Volo/Docs/Admin/ProjectsAdminController.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Volo.Abp; @@ -61,6 +62,13 @@ namespace Volo.Docs.Admin return _projectAppService.ReindexAllAsync(); } + [HttpGet] + [Route("GetListProjectWithoutDetailsAsync")] + public Task> GetListWithoutDetailsAsync() + { + return _projectAppService.GetListWithoutDetailsAsync(); + } + [HttpPost] [Route("Reindex")] public Task ReindexAsync(ReindexInput input) diff --git a/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Documents/Index.cshtml b/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Documents/Index.cshtml index 738327def9..9e846f24a9 100644 --- a/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Documents/Index.cshtml +++ b/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Documents/Index.cshtml @@ -34,50 +34,60 @@ - +
@L["Project"].Value
- +
- +
-
@L["Name"].Value
+
@L["Version"].Value
- +
- - + +
-
@L["Version"].Value
+
@L["Name"].Value
- - + +
@L["LanguageCode"].Value
- +
- + + +
@L["AdvancedFilters"] @@ -85,7 +95,7 @@