diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json index df24b24c13..faf7c0b36d 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json @@ -227,7 +227,8 @@ "Articles": "Articles", "Organizations": "Organizations", "ManageAccount": "Manage Account", - "ABPProfile": "ABP Profile", + "CommunityProfile": "Community Profile", + "BlogProfile": "Blog Profile", "Tickets": "Tickets" } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json index 26f88a81ab..3889b5ec77 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json @@ -249,6 +249,9 @@ "ShareOnLinkedIn": "Share on LinkedIn", "MoreFrom{0}": "More from {0}", "SeeAllFrom{0}": "See all from {0}", - "MostWatched": "Most Watched" + "MostWatched": "Most Watched", + "Articles({0})": "Articles ({0})", + "Videos({0})": "Videos ({0})", + "LatestArticles": "Latest Articles" } } diff --git a/docs/en/Community-Articles/2023-10-23-NET-8-Feature-containers/POST.md b/docs/en/Community-Articles/2023-10-23-NET-8-Feature-containers/POST.md new file mode 100644 index 0000000000..dc0f96e726 --- /dev/null +++ b/docs/en/Community-Articles/2023-10-23-NET-8-Feature-containers/POST.md @@ -0,0 +1,30 @@ +# New Containers feature with NET 8.0 + +This article will show you the new feature of containers with NET 8.0. + +## Non-root user + +The `Non-root user` feature on net 8 is a security measure that allows users to have limited access to the system without having full administrative privileges. Hosting containers as `non-root` aligns with the principle of least privilege. +It’s free security provided by the operating system. If you run your app as root, your app process can do anything in the container, like modify files, install packages, or run arbitrary executables. +That’s a concern if your app is ever attacked. If you run your app as non-root, your app process cannot do much, greatly limiting what a bad actor could accomplish. + +## Default ASP.NET Core port changed from 80 to 8080 + +In .NET 8, there has been a change in the default port used by ASP.NET Core applications. Previously, the default port assigned to ASP.NET Core applications was `80`. However, starting from .NET 8, the default port has been changed to `8080`. +This change was made to avoid conflicts with other applications and services that commonly use port 80, such as web servers like IIS or Apache. By using port 8080 as the default, there is less potential for clashes and easier deployment of ASP.NET Core applications alongside other services. + +It's important to note that this change only affects the default port used when an ASP.NET Core application is run without explicitly specifying a port. + +If you want your application to continue using port 80, you can still specify it during the application launch or configure it in the application settings. + +* Recommended: Explicitly set the `ASPNETCORE_HTTP_PORTS`, `ASPNETCORE_HTTPS_PORTS``, and `ASPNETCORE_URLS` environment variables to the desired port. Example: `docker run --rm -it -p 9999:80 -e ASPNETCORE_HTTP_PORTS=80 `` +* Update existing commands and configuration that rely on the expected default port of port 80 to reference port 8080 instead. Example: `docker run --rm -it -p 9999:8080 `` + +> The `dockerfile` of ABP templates has been updated to use port `80`. + +## References + +- [Secure your .NET cloud apps with rootless Linux Containers](https://devblogs.microsoft.com/dotnet/securing-containers-with-rootless/) +- [Containers breaking changes](https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8#containers) +- [ASP.NET Core apps use port 8080 by default](https://learn.microsoft.com/en-us/dotnet/core/compatibility/8.0#containers) +- [Docker images for ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/docker/building-net-docker-images?view=aspnetcore-8.0) diff --git a/docs/en/Community-Articles/2023-10-23-NET-8-Feature-raw-sql-queries-for-unmapped-types/POST.md b/docs/en/Community-Articles/2023-10-23-NET-8-Feature-raw-sql-queries-for-unmapped-types/POST.md new file mode 100644 index 0000000000..11d8e67563 --- /dev/null +++ b/docs/en/Community-Articles/2023-10-23-NET-8-Feature-raw-sql-queries-for-unmapped-types/POST.md @@ -0,0 +1,53 @@ +# New Raw SQL queries for unmapped types feature with EF Core 8.0 + +## Introduction + +I would love to talk about the new feature in EF Core 8.0, specifically the `raw SQL queries for unmapped types`. +This feature was recently introduced by Microsoft and is aimed at providing more flexibility and customization in database queries. + +## What is the raw SQL queries for the unmapped types feature? + +To give you a better understanding, let's look at a sample repository method with the ABP framework. +Here is an example of a raw SQL query using the new feature: + +````csharp +public interface IAuthorRepository : IRepository +{ + Task> GetAllAuthorNamesAsync(); +} + +public class AuthorIdWithNames +{ + public Guid Id { get; set; } + + public string Name { get; set; } +} + +public class EfCoreAuthorRepository : EfCoreRepository, IAuthorRepository +{ + public EfCoreAuthorRepository(IDbContextProvider dbContextProvider) + : base(dbContextProvider) + { + } + + public virtual async Task> GetAllAuthorNamesAsync() + { + return await (await GetDbContextAsync()).Database.SqlQuery(@$"SELECT Id, Name FROM Authors").ToListAsync(); + } +} +```` + +In this code, we can see that we are using the `SqlQuery` method to execute a raw SQL query on a custom type, `AuthorIdWithNames` in this case. This allows us to retrieve data that may not be mapped to any of our entity classes in the context. + +## In summary + +This feature can be particularly useful in scenarios where we need to access data from tables or views that are not directly mapped to our entities. It also provides an alternative to using stored procedures for querying data. + +However, it's important to note that using raw SQL queries can increase the risk of SQL injection attacks. So, it's recommended to use parameterized queries to prevent this. Additionally, this feature may not work with certain database providers, so it's important to check for compatibility before implementing it. + +In conclusion, the raw SQL queries for unmapped types feature in EF Core 8.0 is a great addition for developers looking for more flexibility in database queries. It allows us to work with data that may not be directly mapped to our entities and can be a useful tool in certain scenarios. Just remember to use parameterized queries and check for compatibility before implementing it. + +## References + +- [Raw SQL queries for unmapped types](https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-8.0/whatsnew#raw-sql-queries-for-unmapped-types) +- [SQL Queries](https://learn.microsoft.com/en-us/ef/core/querying/sql-queries#querying-scalar-(non-entity)-types) diff --git a/docs/en/Community-Articles/2023-11-05-EF-Core-8-Complex-Types/POST.MD b/docs/en/Community-Articles/2023-11-05-EF-Core-8-Complex-Types/POST.MD new file mode 100644 index 0000000000..06289387e5 --- /dev/null +++ b/docs/en/Community-Articles/2023-11-05-EF-Core-8-Complex-Types/POST.MD @@ -0,0 +1,189 @@ +# Using Complex Types as Value Objects with Entity Framework Core 8.0 + +Entity Framework Core 8.0 is being shipped in a week as a part of .NET 8.0. In this article, I will introduce the new **[Complex Types](https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-8.0/whatsnew#value-objects-using-complex-types)** feature of EF Core 8 and show some examples of how you can use it in your projects built with ABP Framework. + +## What is a Value Object? + +A [Value Object](https://docs.abp.io/en/abp/latest/Value-Objects) is a simple object that has no conceptual identity (Id). Instead, a Value Object is identified by its properties. + +A Value Object is typically owned by a parent [Entity](https://docs.abp.io/en/abp/latest/Entities) object. Using [Complex Types](https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-8.0/whatsnew#value-objects-using-complex-types) with EF Core 8 is the best way to create Value Objects that are stored as a part of your main entity. + +## Creating an ABP Project + +> **WARNING**: ABP Framework has not a .NET 8.0 compatible version yet. It is planned to be released on November 15, 2023. I created this project with ABP 7.4.1 (based on .NET 7.0), then manually changed the `TargetFramework` (in the `csproj`) to `net8.0` and added the `Microsoft.EntityFrameworkCore.SqlServer` package with version `8.0.0-rc.2.23480.1`. After that, the project is being compiled, but some parts of this article may not work as expected until ABP Framework 8.0-RC.1 is released. +> +> **I will update the article once ABP Framework 8.0-RC.1 is released.** + +I will show code examples, so I am creating a new ABP project using the following [ABP CLI](https://docs.abp.io/en/abp/latest/CLI) command: + +````bash +abp new ComplexTypeDemo -t app-nolayers +```` + +> I prefer a non-layered project to keep the things simple. If you are new to ABP Framework, follow the [Getting Started](https://docs.abp.io/en/abp/latest/Getting-Started-Overall) tutorial to learn how to create a new project from scratch. + +Once I created the solution, I am running the following command to execute the database migrations in order to create the initial database: + +````bash +dotnet run --project ComplexTypeDemo --migrate-database +```` + +> We could also execute the `migrate-database.ps1` (that is coming as a part of the solution) as a shortcut. + +## Creating a Complex Type + +Assume that we have a `Customer` [entity](https://docs.abp.io/en/abp/latest/Entities) as shown below: + +````csharp +public class Customer : BasicAggregateRoot +{ + public string Name { get; set; } + public Address HomeAddress { get; set; } + public Address BusinessAddress { get; set; } +} +```` + +Here, we have two address properties, one for home and the other one for business. Since an address is a multi-values property, we can define it as a separate object: + +````csharp +public class Address +{ + public string City { get; set; } + public string Line1 { get; set; } + public string? Line2 { get; set; } + public string PostCode { get; set; } +} +```` + +`Address` is a typical complex object. It is actually a part of the `Customer` object, but we wanted to collect its parts into a dedicated class to make it a domain concept and easily manage its properties together. + +## Configure EF Core Mappings + +We should set the `Address` class as a Complex Type in our EF Core mapping configuration. There are two ways of it. + +As the first way, we can add the `ComplexType` attribute on top of the `Address` class: + +````csharp +[ComplexType] // Added this line +public class Address +{ + ... +} +```` + +As an alternative, we can configure the mapping using the fluent mapping API. You can write the following code into the `OnModelCreating` method of your `DbContext` class: + +````csharp +builder.Entity(b => +{ + b.ToTable("Customers"); + b.ComplexProperty(x => x.HomeAddress); // Mapping a Complex Type + b.ComplexProperty(x => x.BusinessAddress); // Mapping another Complex Type + //... configure other properties +}); + +```` + +You can further configure the properties of the `Address` class: + +````csharp +b.ComplexProperty(x => x.HomeAddress, a => +{ + a.Property(x => x.City).HasMaxLength(50).IsRequired(); +}); +```` + +Once you configure the mappings, you can use the [EF Core command-line tool](https://learn.microsoft.com/en-us/ef/core/cli/dotnet) to create a database migration: + +````bash +dotnet ef migrations add "Added_Customer_And_Address" +```` + +And update the database: + +````bash +dotnet ef database update +```` + +If you check the fields of the `Customers` table in your dayabase, you will see the following fields: + +* `Id` +* `Name` +* `HomeAddress_City` +* `HomeAddress_Line1` +* `HomeAddress_Line2` +* `HomeAddress_PostCode` +* `BusinessAddress_City` +* `BusinessAddress_Line1` +* `BusinessAddress_Line2` +* `BusinessAddress_PostCode` + +As you see, EF Core stores the `Address` properties as a part of your main entity. + +## Querying Objects + +You can query entities from database using the properties of a complex type as same as you query by the properties of the main entity. + +**Example: Find customers by `BusinessAddress.PostCode`:** + +````csharp +public class MyService : ITransientDependency +{ + private readonly IRepository _customerRepository; + + public MyService(IRepository customerRepository) + { + _customerRepository = customerRepository; + } + + public async Task DemoAsync() + { + var customers = await _customerRepository.GetListAsync( + c => c.BusinessAddress.PostCode == "12345" + ); + + //... + } +} +```` + +## Mutable vs Immutable + +Entity Framework Core Complex Types can work with mutable and immutable types. In the `Address` example above, I've shown a simple mutable class - that means you can change an individual property of an `Address` object after creating it (or after querying from database). However, designing Value Objects as immutable is a highly common approach. + +For example, you can use C#'s `struct` type to define an immutable `Address` type: + +````csharp +public readonly struct Address(string line1, string? line2, string city, string postCode) +{ + public string City { get; } = city; + public string Line1 { get; } = line1; + public string? Line2 { get; } = line2; + public string PostCode { get; } = postCode; +} +```` + +See the [Microsoft's documentation](https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-8.0/whatsnew#mutability) for more examples and different usages. + +## Final Notes + +There are more details about using Complex Types in your applications. I want to mention some of them here: + +* You can have nested complex types. For example, `Address` may have one or more `PhoneNumber` objects as its properties. Everything will work seamlessly. +* A single instance of a Complex Type can be set to multiple properties (of the same or different entities). In that case, changing the Complex object's properties will affect all of the properties. However, try to avoid that since it may create unnecessary complexities in your code that is hard to understand. +* You can manipulate mutable complex object properties just as another property in your entity. EF Core change tracking system will track them as you expect. +* Currently, EF Core doesn't support to have a collection of complex objects in an entity. It works only for properties. + +For more details and examples, see the Microsoft's document in the *References* section. + +## Source Code + +You can find the sample project here: + +https://github.com/hikalkan/samples/tree/master/EfCoreComplexTypeDemo + +## References + +* [Value objects using Complex Types](https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-8.0/whatsnew#value-objects-using-complex-types) in [What's new with EF Core 8.0](https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-8.0/whatsnew) document by Microsoft. +* [ABP Entity Framework Core integration document](https://docs.abp.io/en/abp/latest/Entity-Framework-Core) + diff --git a/docs/en/Modules/Cms-Kit/Blogging.md b/docs/en/Modules/Cms-Kit/Blogging.md index d45598be52..eb6619a4bc 100644 --- a/docs/en/Modules/Cms-Kit/Blogging.md +++ b/docs/en/Modules/Cms-Kit/Blogging.md @@ -29,7 +29,16 @@ A screenshot from the new blog creation modal: ![blogs-edit](../../images/cmskit-module-blogs-edit.png) -**Slug** is the URL part of the blog. For this example, the root URL of the blog becomes *https://your-domain.com/blogs/technical-blog/*. +**Slug** is the URL part of the blog. For this example, the root URL of the blog becomes `your-domain.com/blogs/technical-blog/`. + +- You can change the default slug by using `CmsBlogsWebConsts.BlogRoutePrefix` constant. For example, if you set it to `foo`, the root URL of the blog becomes `your-domain.com/foo/technical-blog/`. + + ```csharp + public override void PreConfigureServices(ServiceConfigurationContext context) + { + CmsBlogsWebConsts.BlogsRoutePrefix = "foo"; + } + ``` #### Blog Features diff --git a/docs/en/Modules/Cms-Kit/Comments.md b/docs/en/Modules/Cms-Kit/Comments.md index cc8d01249b..ddd39fc675 100644 --- a/docs/en/Modules/Cms-Kit/Comments.md +++ b/docs/en/Modules/Cms-Kit/Comments.md @@ -53,6 +53,7 @@ The comment system provides a commenting [widget](../../UI/AspNetCore/Widgets.md { entityType = "Product", entityId = "...", + isReadOnly = false, referralLinks = new [] {"nofollow"} }) ``` diff --git a/docs/en/Modules/Cms-Kit/Ratings.md b/docs/en/Modules/Cms-Kit/Ratings.md index db58602c15..e6a2ba97fd 100644 --- a/docs/en/Modules/Cms-Kit/Ratings.md +++ b/docs/en/Modules/Cms-Kit/Ratings.md @@ -41,7 +41,8 @@ The ratings system provides a rating widget to allow users send ratings to resou @await Component.InvokeAsync(typeof(RatingViewComponent), new { entityType = "Product", - entityId = "entityId" + entityId = "entityId", + isReadOnly = false }) ``` diff --git a/modules/cms-kit/README.md b/modules/cms-kit/README.md new file mode 100644 index 0000000000..0f04a38ab8 --- /dev/null +++ b/modules/cms-kit/README.md @@ -0,0 +1,24 @@ +# CMS Kit + +## Updating Client Proxies + +This project have 3 types of client proxies. Before updating client proxies, make sure `Volo.CmsKit.Web.Unified` project is running. +Then you can update Client proxies in 3 different projects. Execute the following commands in the directory of the each project. + +- CMS Kit Public (**Volo.CmsKit.Public.HttpApi.Client**) + ```bash + abp generate-proxy -t csharp -url https://localhost:44349 -m cms-kit --without-contracts + ``` + +- CMS Kit Common (**Volo.CmsKit.Common.HttpApi.Client**) + + ```bash + abp generate-proxy -t csharp -url https://localhost:44349 -m cms-kit-common --without-contracts + ``` + +- CMS Kit Admin (**Volo.CmsKit.Admin.HttpApi.Client**) + + ```bash + abp generate-proxy -t csharp -url https://localhost:44349 -m cms-kit-admin --without-contracts + ``` + diff --git a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/Pages/Index.cshtml b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/Pages/Index.cshtml index 1b3f3ff94c..5302289fb3 100644 --- a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/Pages/Index.cshtml +++ b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/Pages/Index.cshtml @@ -48,7 +48,12 @@ @if (GlobalFeatureManager.Instance.IsEnabled()) { - @await Component.InvokeAsync(typeof(RatingViewComponent), new {entityType = "quote", entityId = "1"}) + @await Component.InvokeAsync(typeof(RatingViewComponent), new + { + entityType = "quote", + entityId = "1", + isReadOnly = false + }) } @@ -60,7 +65,13 @@ @if (GlobalFeatureManager.Instance.IsEnabled()) { - @await Component.InvokeAsync(typeof(CommentingViewComponent), new {entityType = "quote", entityId = "1", referralLinks = new [] {"nofollow"}}) + @await Component.InvokeAsync(typeof(CommentingViewComponent), new + { + entityType = "quote", + entityId = "1", + isReadOnly = false, + referralLinks = new [] {"nofollow"} + }) } 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 73b1e7dfd4..cbb5992ebd 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 @@ -2873,8 +2873,8 @@ "nameOnMethod": "input", "name": "Status", "jsonName": null, - "type": "Volo.CmsKit.Blogs.BlogPostStatus?", - "typeSimple": "Volo.CmsKit.Blogs.BlogPostStatus?", + "type": "System.String", + "typeSimple": "string", "isOptional": false, "defaultValue": null, "constraintTypes": null, diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/CreateModal.cshtml b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/CreateModal.cshtml index 5aba4f2431..b348a63115 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/CreateModal.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/CreateModal.cshtml @@ -9,6 +9,7 @@ @using Volo.Abp.Data @using Volo.Abp.Localization @using Volo.Abp.ObjectExtending +@using Volo.CmsKit.Web @inject IStringLocalizerFactory StringLocalizerFactory @inherits CmsKitAdminPageBase @@ -25,7 +26,7 @@ - + @foreach (var propertyInfo in ObjectExtensionManager.Instance.GetProperties()) { diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/UpdateModal.cshtml b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/UpdateModal.cshtml index 65eccddef5..e3385e929b 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/UpdateModal.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/UpdateModal.cshtml @@ -8,6 +8,7 @@ @using Volo.Abp.Data @using Volo.Abp.Localization @using Volo.Abp.ObjectExtending +@using Volo.CmsKit.Web @inject IStringLocalizerFactory StringLocalizerFactory @inherits CmsKitAdminPageBase @@ -26,7 +27,7 @@ - + @foreach (var propertyInfo in ObjectExtensionManager.Instance.GetProperties()) { diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Create.cshtml b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Create.cshtml index e674c08600..afef4bdad5 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Create.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Create.cshtml @@ -59,7 +59,7 @@
- + diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Update.cshtml b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Update.cshtml index f1bd33d212..08fc064226 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Update.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Update.cshtml @@ -64,7 +64,7 @@ - + diff --git a/modules/cms-kit/src/Volo.CmsKit.Common.HttpApi.Client/ClientProxies/Volo/CmsKit/Blogs/BlogFeatureClientProxy.Generated.cs b/modules/cms-kit/src/Volo.CmsKit.Common.HttpApi.Client/ClientProxies/Volo/CmsKit/Blogs/BlogFeatureClientProxy.Generated.cs new file mode 100644 index 0000000000..77485c92db --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Common.HttpApi.Client/ClientProxies/Volo/CmsKit/Blogs/BlogFeatureClientProxy.Generated.cs @@ -0,0 +1,28 @@ +// This file is automatically generated by ABP framework to use MVC Controllers from CSharp +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.Application.Dtos; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Http.Client; +using Volo.Abp.Http.Client.ClientProxying; +using Volo.Abp.Http.Modeling; +using Volo.CmsKit.Blogs; + +// ReSharper disable once CheckNamespace +namespace Volo.CmsKit.Blogs; + +[Dependency(ReplaceServices = true)] +[ExposeServices(typeof(IBlogFeatureAppService), typeof(BlogFeatureClientProxy))] +public partial class BlogFeatureClientProxy : ClientProxyBase, IBlogFeatureAppService +{ + public virtual async Task GetOrDefaultAsync(Guid blogId, string featureName) + { + return await RequestAsync(nameof(GetOrDefaultAsync), new ClientProxyRequestTypeValue + { + { typeof(Guid), blogId }, + { typeof(string), featureName } + }); + } +} diff --git a/modules/cms-kit/src/Volo.CmsKit.Common.HttpApi.Client/ClientProxies/Volo/CmsKit/Blogs/BlogFeatureClientProxy.cs b/modules/cms-kit/src/Volo.CmsKit.Common.HttpApi.Client/ClientProxies/Volo/CmsKit/Blogs/BlogFeatureClientProxy.cs new file mode 100644 index 0000000000..e9752dfcc9 --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Common.HttpApi.Client/ClientProxies/Volo/CmsKit/Blogs/BlogFeatureClientProxy.cs @@ -0,0 +1,7 @@ +// This file is part of BlogFeatureClientProxy, you can customize it here +// ReSharper disable once CheckNamespace +namespace Volo.CmsKit.Blogs; + +public partial class BlogFeatureClientProxy +{ +} diff --git a/modules/cms-kit/src/Volo.CmsKit.Common.HttpApi.Client/ClientProxies/Volo/CmsKit/MediaDescriptors/MediaDescriptorClientProxy.Generated.cs b/modules/cms-kit/src/Volo.CmsKit.Common.HttpApi.Client/ClientProxies/Volo/CmsKit/MediaDescriptors/MediaDescriptorClientProxy.Generated.cs new file mode 100644 index 0000000000..67eaa76785 --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Common.HttpApi.Client/ClientProxies/Volo/CmsKit/MediaDescriptors/MediaDescriptorClientProxy.Generated.cs @@ -0,0 +1,28 @@ +// This file is automatically generated by ABP framework to use MVC Controllers from CSharp +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Content; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Http.Client; +using Volo.Abp.Http.Client.ClientProxying; +using Volo.Abp.Http.Modeling; +using Volo.CmsKit.MediaDescriptors; + +// ReSharper disable once CheckNamespace +namespace Volo.CmsKit.MediaDescriptors; + +[Dependency(ReplaceServices = true)] +[ExposeServices(typeof(IMediaDescriptorAppService), typeof(MediaDescriptorClientProxy))] +public partial class MediaDescriptorClientProxy : ClientProxyBase, IMediaDescriptorAppService +{ + public virtual async Task DownloadAsync(Guid id) + { + return await RequestAsync(nameof(DownloadAsync), new ClientProxyRequestTypeValue + { + { typeof(Guid), id } + }); + } +} diff --git a/modules/cms-kit/src/Volo.CmsKit.Common.HttpApi.Client/ClientProxies/Volo/CmsKit/MediaDescriptors/MediaDescriptorClientProxy.cs b/modules/cms-kit/src/Volo.CmsKit.Common.HttpApi.Client/ClientProxies/Volo/CmsKit/MediaDescriptors/MediaDescriptorClientProxy.cs new file mode 100644 index 0000000000..028ccff1a2 --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Common.HttpApi.Client/ClientProxies/Volo/CmsKit/MediaDescriptors/MediaDescriptorClientProxy.cs @@ -0,0 +1,7 @@ +// This file is part of MediaDescriptorClientProxy, you can customize it here +// ReSharper disable once CheckNamespace +namespace Volo.CmsKit.MediaDescriptors; + +public partial class MediaDescriptorClientProxy +{ +} diff --git a/modules/cms-kit/src/Volo.CmsKit.Common.HttpApi.Client/ClientProxies/cms-kit-common-generate-proxy.json b/modules/cms-kit/src/Volo.CmsKit.Common.HttpApi.Client/ClientProxies/cms-kit-common-generate-proxy.json index 6b7b45220a..07e4bf762c 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Common.HttpApi.Client/ClientProxies/cms-kit-common-generate-proxy.json +++ b/modules/cms-kit/src/Volo.CmsKit.Common.HttpApi.Client/ClientProxies/cms-kit-common-generate-proxy.json @@ -8,11 +8,32 @@ "controllerName": "MediaDescriptor", "controllerGroupName": "MediaDescriptor", "isRemoteService": true, + "isIntegrationService": false, "apiVersion": null, "type": "Volo.CmsKit.MediaDescriptors.MediaDescriptorController", "interfaces": [ { - "type": "Volo.CmsKit.MediaDescriptors.IMediaDescriptorAppService" + "type": "Volo.CmsKit.MediaDescriptors.IMediaDescriptorAppService", + "name": "IMediaDescriptorAppService", + "methods": [ + { + "name": "DownloadAsync", + "parametersOnMethod": [ + { + "name": "id", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "Volo.Abp.Content.RemoteStreamContent", + "typeSimple": "Volo.Abp.Content.RemoteStreamContent" + } + } + ] } ], "actions": { @@ -59,11 +80,40 @@ "controllerName": "BlogFeature", "controllerGroupName": "BlogFeature", "isRemoteService": true, + "isIntegrationService": false, "apiVersion": null, "type": "Volo.CmsKit.Blogs.BlogFeatureController", "interfaces": [ { - "type": "Volo.CmsKit.Blogs.IBlogFeatureAppService" + "type": "Volo.CmsKit.Blogs.IBlogFeatureAppService", + "name": "IBlogFeatureAppService", + "methods": [ + { + "name": "GetOrDefaultAsync", + "parametersOnMethod": [ + { + "name": "blogId", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null + }, + { + "name": "featureName", + "typeAsString": "System.String, System.Private.CoreLib", + "type": "System.String", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "Volo.CmsKit.Blogs.BlogFeatureDto", + "typeSimple": "Volo.CmsKit.Blogs.BlogFeatureDto" + } + } + ] } ], "actions": { diff --git a/modules/cms-kit/src/Volo.CmsKit.Common.Web/CmsBlogsWebConsts.cs b/modules/cms-kit/src/Volo.CmsKit.Common.Web/CmsBlogsWebConsts.cs new file mode 100644 index 0000000000..7793856414 --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Common.Web/CmsBlogsWebConsts.cs @@ -0,0 +1,6 @@ +namespace Volo.CmsKit.Web; + +public static class CmsBlogsWebConsts +{ + public static string BlogsRoutePrefix { get; set; } = "blogs"; +} diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ar.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ar.json index b26a1fe2a8..9ef0948c80 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ar.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ar.json @@ -77,6 +77,7 @@ "PageId": "صفحة", "Pages": "الصفحات", "PageSlugInformation": "سبيكة تستخدم على url. سيكون عنوان url الخاص بك هو \"/{slug}}\".", + "BlogSlugInformation": "سبيكة تستخدم على url. سيكون عنوان url الخاص بك هو \"/{0}/{slug}}\".", "Permission:BlogManagement": "إدارة المدونة", "Permission:BlogManagement.Create": "إنشاء", "Permission:BlogManagement.Delete": "حذف", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/cs.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/cs.json index 8344a53ee2..383ba53bfc 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/cs.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/cs.json @@ -77,6 +77,7 @@ "PageId": "Strana", "Pages": "stránky", "PageSlugInformation": "Na adrese URL je použit Slug. Vaše adresa URL bude '/{{slug}}'.", + "BlogSlugInformation": "Na adrese URL je použit Slug. Vaše adresa URL bude '/{0}/{{slug}}'.", "Permission:BlogManagement": "Správa blogu", "Permission:BlogManagement.Create": "Vytvořit", "Permission:BlogManagement.Delete": "Vymazat", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/de-DE.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/de-DE.json index 3a4b0a5569..8a34408bab 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/de-DE.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/de-DE.json @@ -77,6 +77,7 @@ "PageId": "Buchseite", "Pages": "Seiten", "PageSlugInformation": "Slug wird auf URL verwendet. Ihre URL lautet '/{{slug}}'.", + "BlogSlugInformation": "Slug wird auf URL verwendet. Ihre URL lautet '/{0}/{{slug}}'.", "Permission:BlogManagement": "Blog-Verwaltung", "Permission:BlogManagement.Create": "Schaffen", "Permission:BlogManagement.Delete": "Löschen", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/el.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/el.json index c686723d33..7155c127a3 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/el.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/el.json @@ -77,6 +77,7 @@ "PageId": "Σελίδα", "Pages": "Σελίδες", "PageSlugInformation": "Το Slug χρησιμοποιείται στο url. Το url σας θα είναι '/{{slug}}'.", + "BlogSlugInformation": "Το Slug χρησιμοποιείται στο url. Το url σας θα είναι '/{0}/{{slug}}'.", "Permission:BlogManagement": "Διαχείριση ιστολογίου", "Permission:BlogManagement.Create": "Δημιουργώ", "Permission:BlogManagement.Delete": "Διαγράφω", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json index e879b7e339..0169f42b7e 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json @@ -76,6 +76,7 @@ "PageId": "Page", "Pages": "Pages", "PageSlugInformation": "Slug is used on url. Your url will be '/{{slug}}'.", + "BlogSlugInformation": "Slug is used on url. Your url will be '/{0}/{{slug}}'.", "Permission:BlogManagement": "Blog Management", "Permission:BlogManagement.Create": "Create", "Permission:BlogManagement.Delete": "Delete", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/es.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/es.json index ea9b318b93..fb8e963115 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/es.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/es.json @@ -77,6 +77,7 @@ "PageId": "Página", "Pages": "Paginas", "PageSlugInformation": "Slug se usa en la URL. Su URL será '/{{slug}}'.", + "BlogSlugInformation": "Slug se usa en la URL. Su URL será '/{0}/{{slug}}'.", "Permission:BlogManagement": "Gestión de blogs", "Permission:BlogManagement.Create": "Crear", "Permission:BlogManagement.Delete": "Borrar", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/fi.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/fi.json index 1ead360d61..54a0ea97a4 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/fi.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/fi.json @@ -76,6 +76,7 @@ "PageId": "Sivu", "Pages": "Sivut", "PageSlugInformation": "Etanaa käytetään URL-osoitteessa. URL-osoitteesi on '/{{slug}}'.", + "BlogSlugInformation": "Etanaa käytetään URL-osoitteessa. URL-osoitteesi on '/{0}/{{slug}}'.", "Permission:BlogManagement": "Blogin hallinta", "Permission:BlogManagement.Create": "Luonti", "Permission:BlogManagement.Delete": "Poisto", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/fr.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/fr.json index 445c7b3578..bbd4f67955 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/fr.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/fr.json @@ -77,6 +77,7 @@ "PageId": "Page", "Pages": "Pages", "PageSlugInformation": "Slug est utilisé sur l'url. Votre URL sera '/{{slug}}'.", + "BlogSlugInformation": "Slug est utilisé sur l'url. Votre URL sera '/{0}/{{slug}}'.", "Permission:BlogManagement": "Gestion de blog", "Permission:BlogManagement.Create": "Créer", "Permission:BlogManagement.Delete": "Effacer", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/hi.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/hi.json index fffe151260..b251ac8c18 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/hi.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/hi.json @@ -77,6 +77,7 @@ "PageId": "पृष्ठ", "Pages": "पृष्ठों", "PageSlugInformation": "स्लग का उपयोग url पर किया जाता है। आपका url '/{{slug}}' होगा।", + "BlogSlugInformation": "स्लग का उपयोग url पर किया जाता है। आपका url '/{0}/{{slug}}' होगा।", "Permission:BlogManagement": "ब्लॉग प्रबंधन", "Permission:BlogManagement.Create": "सृजन करना", "Permission:BlogManagement.Delete": "हटाएं", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/hu.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/hu.json index 4c1047e178..43afc9575c 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/hu.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/hu.json @@ -76,6 +76,7 @@ "PageId": "oldal", "Pages": "Oldalak", "PageSlugInformation": "A Slug az url-en használatos. Az Ön URL-je a következő lesz: '/{{slug}}'.", + "BlogSlugInformation": "A Slug az url-en használatos. Az Ön URL-je a következő lesz: '/{0}/{{slug}}'.", "Permission:BlogManagement": "Blogkezelés", "Permission:BlogManagement.Create": "Teremt", "Permission:BlogManagement.Delete": "Töröl", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/is.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/is.json index 43c98adcc2..8b7bebc1ea 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/is.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/is.json @@ -76,7 +76,8 @@ "PageDeletionConfirmationMessage": "Ertu viss um að eyða þessari síðu?", "PageId": "Síða", "Pages": "Síður", - "PageSlugInformation": "Snigill er notaður á slóð. Slóðin þín verður '/síður/{{slug}}'.", + "PageSlugInformation": "Snigill er notaður á slóð. Slóðin þín verður '/{{slug}}'.", + "BlogSlugInformation": "Snigill er notaður á slóð. Slóðin þín verður '/{0}/{{slug}}'.", "Permission:BlogManagement": "Bloggstjórnun", "Permission:BlogManagement.Create": "Búa til", "Permission:BlogManagement.Delete": "Eyða", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/it.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/it.json index bddf4affc2..3575754a8c 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/it.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/it.json @@ -77,6 +77,7 @@ "PageId": "Pagina", "Pages": "Pagine", "PageSlugInformation": "Lo slug viene utilizzato sull'URL. Il tuo URL sarà '/{{slug}}'.", + "BlogSlugInformation": "Lo slug viene utilizzato sull'URL. Il tuo URL sarà '/{0}/{{slug}}'.", "Permission:BlogManagement": "Gestione del blog", "Permission:BlogManagement.Create": "Crea", "Permission:BlogManagement.Delete": "Elimina", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/nl.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/nl.json index d06ba78bf4..ef370edf26 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/nl.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/nl.json @@ -77,6 +77,7 @@ "PageId": "Bladzijde", "Pages": "Pagina's", "PageSlugInformation": "Slug wordt gebruikt voor de url. Uw url wordt '/{{slug}}'.", + "BlogSlugInformation": "Slug wordt gebruikt voor de url. Uw url wordt '/{0}/{{slug}}'.", "Permission:BlogManagement": "Blogbeheer", "Permission:BlogManagement.Create": "Toevoegen", "Permission:BlogManagement.Delete": "Verwijderen", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/pl-PL.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/pl-PL.json index a775020f7a..0bdef5d26b 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/pl-PL.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/pl-PL.json @@ -77,6 +77,7 @@ "PageId": "Strona", "Pages": "Strony", "PageSlugInformation": "Slug jest używany na adresie URL. Twój adres URL to „/{{slug}}”.", + "BlogSlugInformation": "Slug jest używany na adresie URL. Twój adres URL to „/{0}/{{slug}}”.", "Permission:BlogManagement": "Zarządzanie blogiem", "Permission:BlogManagement.Create": "Tworzyć", "Permission:BlogManagement.Delete": "Kasować", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/pt-BR.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/pt-BR.json index c306e6f58c..9510e2a67d 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/pt-BR.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/pt-BR.json @@ -77,6 +77,7 @@ "PageId": "Página", "Pages": "Páginas", "PageSlugInformation": "Slug é usado na url. Sua url será '/{{slug}}'.", + "BlogSlugInformation": "Slug é usado na url. Sua url será '/{0}/{{slug}}'.", "Permission:BlogManagement": "Gerenciamento de blogs", "Permission:BlogManagement.Create": "Criar", "Permission:BlogManagement.Delete": "Excluir", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ro-RO.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ro-RO.json index 7712530ee7..21b9ac5a24 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ro-RO.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ro-RO.json @@ -77,6 +77,7 @@ "PageId": "Pagina", "Pages": "Pagini", "PageSlugInformation": "Slug este folosit pe url. Url-ul dumneavoastră va fi '/{{slug}}'.", + "BlogSlugInformation": "Slug este folosit pe url. Url-ul dumneavoastră va fi '/{0}/{{slug}}'.", "Permission:BlogManagement": "Administrare Blog", "Permission:BlogManagement.Create": "Creează", "Permission:BlogManagement.Delete": "Şterge", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ru.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ru.json index e30641ce50..a1a809f9fa 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ru.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ru.json @@ -77,6 +77,7 @@ "PageId": "Страница", "Pages": "Страницы", "PageSlugInformation": "Слаг используется для URL. Ваш URL-адрес будет '/{{slug}}'.", + "BlogSlugInformation": "Слаг используется для URL. Ваш URL-адрес будет '/{0}/{{slug}}'.", "Permission:BlogManagement": "Управление блогом", "Permission:BlogManagement.Create": "Создавать", "Permission:BlogManagement.Delete": "Удалить", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/sk.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/sk.json index 7fc0e7c254..af320c8a19 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/sk.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/sk.json @@ -77,6 +77,7 @@ "PageId": "Stránka", "Pages": "Stránky", "PageSlugInformation": "Slug sa používa v URL. Vaša URL bude '/{{slug}}'.", + "BlogSlugInformation": "Slug sa používa v URL. Vaša URL bude '/{0}/{{slug}}'.", "Permission:BlogManagement": "Správa blogov", "Permission:BlogManagement.Create": "Vytvoriť", "Permission:BlogManagement.Delete": "Zmazať", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/sl.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/sl.json index 0e0d12e2e6..972b7da430 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/sl.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/sl.json @@ -77,6 +77,7 @@ "PageId": "stran", "Pages": "strani", "PageSlugInformation": "Slug se uporablja na url-ju. Vaš url bo '/{{slug}}'.", + "BlogSlugInformation": "Slug se uporablja na url-ju. Vaš url bo '/{0}/{{slug}}'.", "Permission:BlogManagement": "Upravljanje blogov", "Permission:BlogManagement.Create": "Ustvari", "Permission:BlogManagement.Delete": "Izbriši", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json index c84cdc6312..78c5f9341e 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json @@ -76,6 +76,7 @@ "PageId": "Sayfa", "Pages": "Sayfalar", "PageSlugInformation": "Etiket URL'de kullanılır. Url şöyle görünür: '/{{slug}}'.", + "BlogSlugInformation": "Etiket URL'de kullanılır. Url şöyle görünür: '/{0}/{{slug}}'.", "Permission:BlogManagement": "Blog Yönetimi", "Permission:BlogManagement.Create": "Oluşturma", "Permission:BlogManagement.Delete": "Silme", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/vi.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/vi.json index 3e0f36578d..09ae8f3a9c 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/vi.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/vi.json @@ -77,6 +77,7 @@ "PageId": "Trang", "Pages": "Các trang", "PageSlugInformation": "Slug được sử dụng trên url. Url của bạn sẽ là '/{{slug}}'.", + "BlogSlugInformation": "Slug được sử dụng trên url. Url của bạn sẽ là '/{0}/{{slug}}'.", "Permission:BlogManagement": "Quản lý blog", "Permission:BlogManagement.Create": "Tạo ra", "Permission:BlogManagement.Delete": "Xóa bỏ", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/zh-Hans.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/zh-Hans.json index 7e9089d426..516c57eefd 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/zh-Hans.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/zh-Hans.json @@ -76,6 +76,7 @@ "PageId": "页", "Pages": "页面", "PageSlugInformation": "Slug用于url. 你的url将是 '/{{slug}}'.", + "BlogSlugInformation": "Slug用于url. 你的url将是 '/{0}/{{slug}}'.", "Permission:BlogManagement": "博客管理", "Permission:BlogManagement.Create": "创建", "Permission:BlogManagement.Delete": "删除", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/zh-Hant.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/zh-Hant.json index e6dd053052..5d3d2621fb 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/zh-Hant.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/zh-Hant.json @@ -77,6 +77,7 @@ "PageId": "頁", "Pages": "頁面", "PageSlugInformation": "Slug用於網址. 你的網址將是 '/{{slug}}'.", + "BlogSlugInformation": "Slug用於網址. 你的網址將是 '/{0}/{{slug}}'.", "Permission:BlogManagement": "部落格管理", "Permission:BlogManagement.Create": "創建", "Permission:BlogManagement.Delete": "刪除", diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/Blogs/IBlogPostPublicAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/Blogs/IBlogPostPublicAppService.cs index dd21e2c903..c679420902 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/Blogs/IBlogPostPublicAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/Blogs/IBlogPostPublicAppService.cs @@ -17,5 +17,8 @@ public interface IBlogPostPublicAppService : IApplicationService Task> GetAuthorsHasBlogPostsAsync(BlogPostFilteredPagedAndSortedResultRequestDto input); Task GetAuthorHasBlogPostAsync(Guid id); + Task DeleteAsync(Guid id); + + Task GetTagNameAsync([NotNull] Guid tagId); } 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 cd346f9a21..4a9875990d 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 @@ -12,6 +12,7 @@ using Volo.CmsKit.Blogs; using Volo.CmsKit.Contents; using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; +using Volo.CmsKit.Tags; using Volo.CmsKit.Users; namespace Volo.CmsKit.Public.Blogs; @@ -24,12 +25,16 @@ public class BlogPostPublicAppService : CmsKitPublicAppServiceBase, IBlogPostPub protected IBlogPostRepository BlogPostRepository { get; } + protected ITagRepository TagRepository { get; } + public BlogPostPublicAppService( IBlogRepository blogRepository, - IBlogPostRepository blogPostRepository) + IBlogPostRepository blogPostRepository, + ITagRepository tagRepository) { BlogRepository = blogRepository; BlogPostRepository = blogPostRepository; + TagRepository = tagRepository; } public virtual async Task GetAsync( @@ -85,4 +90,11 @@ public class BlogPostPublicAppService : CmsKitPublicAppServiceBase, IBlogPostPub await BlogPostRepository.DeleteAsync(id); } + + public async Task GetTagNameAsync([NotNull] Guid tagId) + { + var tag = await TagRepository.GetAsync(tagId); + + return tag.Name; + } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Blogs/BlogPostPublicClientProxy.Generated.cs b/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Blogs/BlogPostPublicClientProxy.Generated.cs index f269125676..d185f22a27 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Blogs/BlogPostPublicClientProxy.Generated.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Blogs/BlogPostPublicClientProxy.Generated.cs @@ -60,4 +60,12 @@ public partial class BlogPostPublicClientProxy : ClientProxyBase GetTagNameAsync(Guid tagId) + { + return await RequestAsync(nameof(GetTagNameAsync), new ClientProxyRequestTypeValue + { + { typeof(Guid), tagId } + }); + } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/cms-kit-generate-proxy.json b/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/cms-kit-generate-proxy.json index 477938b6de..31e3fb52f8 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/cms-kit-generate-proxy.json +++ b/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/cms-kit-generate-proxy.json @@ -1512,6 +1512,23 @@ "type": "System.Void", "typeSimple": "System.Void" } + }, + { + "name": "GetTagNameAsync", + "parametersOnMethod": [ + { + "name": "tagId", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "System.String", + "typeSimple": "string" + } } ] } @@ -1825,6 +1842,55 @@ }, "allowAnonymous": null, "implementFrom": "Volo.CmsKit.Public.Blogs.IBlogPostPublicAppService" + }, + "GetTagNameAsyncByTagId": { + "uniqueName": "GetTagNameAsyncByTagId", + "name": "GetTagNameAsync", + "httpMethod": "GET", + "url": "api/cms-kit-public/blog-posts/tags/{id}", + "supportedVersions": [], + "parametersOnMethod": [ + { + "name": "tagId", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null + } + ], + "parameters": [ + { + "nameOnMethod": "tagId", + "name": "tagId", + "jsonName": null, + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "" + }, + { + "nameOnMethod": "id", + "name": "id", + "jsonName": null, + "type": null, + "typeSimple": null, + "isOptional": false, + "defaultValue": null, + "constraintTypes": [], + "bindingSourceId": "Path", + "descriptorName": "" + } + ], + "returnValue": { + "type": "System.String", + "typeSimple": "string" + }, + "allowAnonymous": null, + "implementFrom": "Volo.CmsKit.Public.Blogs.IBlogPostPublicAppService" } } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Blogs/BlogPostPublicController.cs b/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Blogs/BlogPostPublicController.cs index 4d2a336fca..d5b5768d34 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Blogs/BlogPostPublicController.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Blogs/BlogPostPublicController.cs @@ -1,5 +1,6 @@ using System; using System.Threading.Tasks; +using JetBrains.Annotations; using Microsoft.AspNetCore.Mvc; using Volo.Abp; using Volo.Abp.Application.Dtos; @@ -60,4 +61,11 @@ public class BlogPostPublicController : CmsKitPublicControllerBase, IBlogPostPub { return BlogPostPublicAppService.DeleteAsync(id); } + + [HttpGet] + [Route("tags/{id}")] + public Task GetTagNameAsync([NotNull] Guid tagId) + { + return BlogPostPublicAppService.GetTagNameAsync(tagId); + } } \ No newline at end of file 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 93a61efe2f..c7078acd98 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/CmsKitPublicWebModule.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/CmsKitPublicWebModule.cs @@ -1,4 +1,5 @@ -using Microsoft.AspNetCore.Mvc.RazorPages; +using System; +using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.AspNetCore.Mvc.Localization; @@ -91,8 +92,13 @@ public class CmsKitPublicWebModule : AbpModule { Configure(options => { - options.Conventions.AddPageRoute("/Public/CmsKit/Blogs/Index", @"/blogs/{blogSlug:minlength(1)}"); - options.Conventions.AddPageRoute("/Public/CmsKit/Blogs/BlogPost", @"/blogs/{blogSlug}/{blogPostSlug:minlength(1)}"); + options.Conventions.AddPageRoute( + "/Public/CmsKit/Blogs/Index", + CmsBlogsWebConsts.BlogsRoutePrefix.EnsureStartsWith('/') + @"/{blogSlug:minlength(1)}"); + + options.Conventions.AddPageRoute( + "/Public/CmsKit/Blogs/BlogPost", + CmsBlogsWebConsts.BlogsRoutePrefix.EnsureStartsWith('/') + @"/{blogSlug}/{blogPostSlug:minlength(1)}"); }); } diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/CommentingViewComponent.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/CommentingViewComponent.cs index 5810103ea9..32503ceab7 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/CommentingViewComponent.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/CommentingViewComponent.cs @@ -60,6 +60,7 @@ public class CommentingViewComponent : AbpViewComponent public virtual async Task InvokeAsync( string entityType, string entityId, + bool isReadOnly, IEnumerable referralLinks = null) { referralLinks ??= Enumerable.Empty(); @@ -74,7 +75,8 @@ public class CommentingViewComponent : AbpViewComponent EntityType = entityType, ReferralLinks = referralLinks, LoginUrl = loginUrl, - Comments = comments.OrderByDescending(i => i.CreationTime).ToList() + IsReadOnly = isReadOnly, + Comments = comments.OrderByDescending(i => i.CreationTime).ToList(), }; await ConvertMarkdownTextsToHtml(viewModel); @@ -144,6 +146,8 @@ public class CommentingViewComponent : AbpViewComponent public string Captcha { get; set; } public string CaptchaImageBase64 { get; set; } + + public bool IsReadOnly { get; set; } } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/Default.cshtml b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/Default.cshtml index c1171d8ba6..1b86ade0a8 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/Default.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/Default.cshtml @@ -20,16 +20,16 @@ @ @((string.IsNullOrWhiteSpace(author.Name) - ? author.UserName - : author.Name + " " + author.Surname).Trim()) + ? author.UserName + : author.Name + " " + author.Surname).Trim()) @creationTime.ToString() ; } @{ Func GetCommentArea(Guid? repliedCommentId, bool cancelButton = false) => @
+ data-reply-id="@(repliedCommentId?.ToString() ?? "")" + style="@(string.IsNullOrEmpty(repliedCommentId?.ToString() ?? "") ? "" : "display:none")"> @@ -44,31 +44,31 @@
@if (CmsKitCommentOptions.Value.IsRecaptchaEnabled) - { -
- -
-
- -
-
- -
- + { +
+ +
+
+ +
+
+
+
- } +
+ }
@L["Send"] @if (cancelButton) - { - - @L["Cancel"] - - } + { + + @L["Cancel"] + + }
@@ -87,32 +87,32 @@ Func GetCommentActionArea(Guid id, Guid authorId, bool isReply) => @
@if (!isReply) - { - @if (CurrentUser.IsAuthenticated) - { - - @L["Reply"] - + { + @if (CurrentUser.IsAuthenticated) + { + + @L["Reply"] + + + + @L["Delete"] + + } + else + { + + @L["LoginToReply"] + + } + } + - - @L["Delete"] - - } - else - { - - @L["LoginToReply"] - - } - } - - @if (authorId == CurrentUser.Id) - { - - @L["Edit"] - - } + { + + @L["Edit"] + + }
; } @{ @@ -129,26 +129,26 @@
- @L["MarkdownSupported"] + @L["MarkdownSupported"]
@if (CmsKitCommentOptions.Value.IsRecaptchaEnabled) - { - var output = await Model.GenerateCaptchaAsync(); + { + var output = await Model.GenerateCaptchaAsync(); -
- -
-
- -
-
- -
- +
+ +
+
+ +
+
+
+
- } +
+ }
@L["Update"] @@ -184,22 +184,25 @@ @GetCommentContentArea(comment.Id, comment.Text).Invoke(null) -
-
-
- @GetCommentActionArea(comment.Id, comment.Author.Id, false).Invoke(null) + @if (!Model.Input.IsReadOnly) + { +
+
+
+ @GetCommentActionArea(comment.Id, comment.Author.Id, false).Invoke(null) +
-
-
-
- @if (cmsKitUiOptions.Value.CommentsOptions.IsReactionsEnabled && GlobalFeatureManager.Instance.IsEnabled()) - { - @await Component.InvokeAsync(typeof(ReactionSelectionViewComponent), new { entityType = "comment", entityId = comment.Id.ToString() }) - } +
+
+ @if (cmsKitUiOptions.Value.CommentsOptions.IsReactionsEnabled && GlobalFeatureManager.Instance.IsEnabled()) + { + @await Component.InvokeAsync(typeof(ReactionSelectionViewComponent), new { entityType = "comment", entityId = comment.Id.ToString() }) + } +
-
- @GetEditArea(comment.Id, Model.Input.RawCommentTexts[comment.Id], comment.ConcurrencyStamp).Invoke(null) + @GetEditArea(comment.Id, Model.Input.RawCommentTexts[comment.Id], comment.ConcurrencyStamp).Invoke(null) + } @if (comment.Replies.Any()) { @@ -213,23 +216,26 @@ @GetCommentContentArea(reply.Id, reply.Text).Invoke(null) -
-
-
- @GetCommentActionArea(reply.Id, reply.Author.Id, true).Invoke(null) + @if (!Model.Input.IsReadOnly) + { +
+
+
+ @GetCommentActionArea(reply.Id, reply.Author.Id, true).Invoke(null) +
-
-
-
- @if (cmsKitUiOptions.Value.CommentsOptions.IsReactionsEnabled && GlobalFeatureManager.Instance.IsEnabled()) - { - @await Component.InvokeAsync(typeof(ReactionSelectionViewComponent), new { entityType = "comment", entityId = reply.Id.ToString() }) - } +
+
+ @if (cmsKitUiOptions.Value.CommentsOptions.IsReactionsEnabled && GlobalFeatureManager.Instance.IsEnabled()) + { + @await Component.InvokeAsync(typeof(ReactionSelectionViewComponent), new { entityType = "comment", entityId = reply.Id.ToString() }) + } +
-
- @GetEditArea(reply.Id, Model.Input.RawCommentTexts[reply.Id], reply.ConcurrencyStamp).Invoke(null) + @GetEditArea(reply.Id, Model.Input.RawCommentTexts[reply.Id], reply.ConcurrencyStamp).Invoke(null) + }
} diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Rating/Default.cshtml b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Rating/Default.cshtml index 9b7f6e24f7..95879128a7 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Rating/Default.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Rating/Default.cshtml @@ -6,58 +6,59 @@ @inject IHtmlLocalizer L
-
-
- @if (CurrentUser.IsAuthenticated) +
+
+ + @if (CurrentUser.IsAuthenticated) + { + @if (!Model.IsReadOnly && Model.CurrentRating != null) { - @if (Model.CurrentRating != null) - { - - @L["Undo"] - - } - if (Model.Ratings != null) - { - - - + + @L["Undo"] + + } + if (Model.Ratings != null) + { + + + - "> + + }
-
\ No newline at end of file +
+
\ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Rating/RatingViewComponent.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Rating/RatingViewComponent.cs index b928f7e2af..7ab1df47b8 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Rating/RatingViewComponent.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Rating/RatingViewComponent.cs @@ -31,7 +31,7 @@ public class RatingViewComponent : AbpViewComponent CurrentUser = currentUser; } - public virtual async Task InvokeAsync(string entityType, string entityId) + public virtual async Task InvokeAsync(string entityType, string entityId, bool isReadOnly = false) { var ratings = await RatingPublicAppService.GetGroupedStarCountsAsync(entityType, entityId); var totalRating = ratings.Sum(x => x.Count); @@ -52,7 +52,8 @@ public class RatingViewComponent : AbpViewComponent LoginUrl = loginUrl, Ratings = ratings, CurrentRating = currentUserRating, - TotalRating = totalRating + TotalRating = totalRating, + IsReadOnly = isReadOnly }; return View("~/Pages/CmsKit/Shared/Components/Rating/Default.cshtml", viewModel); @@ -72,4 +73,6 @@ public class RatingViewModel public short? CurrentRating { get; set; } public int TotalRating { get; set; } + + public bool IsReadOnly { get; set; } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Rating/default.js b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Rating/default.js index 22531b47f3..69bb1bac4f 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Rating/default.js +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Rating/default.js @@ -15,6 +15,7 @@ function registerCreateOfNewRating() { $widget.find(".my-rating").each(function () { var authenticated = $(this).attr("data-authenticated"); + var readonly = $(this).attr("data-readonly"); $(this).starRating({ initialRating: 0, @@ -26,7 +27,7 @@ strokeWidth: 0, disableAfterRate: true, useFullStars: true, - readOnly: authenticated === "True", + readOnly: authenticated === "True" || readonly === "True", onHover: function (currentIndex, currentRating, $el) { $widget.find(".live-rating").text(currentIndex); }, diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Tags/Default.cshtml b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Tags/Default.cshtml index e9567b8b3e..baa68ff0f4 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Tags/Default.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Tags/Default.cshtml @@ -10,14 +10,14 @@ { if (Model.UrlFormat.IsNullOrWhiteSpace()) { - + @tag.Name } else { var formattedUrl = Model.UrlFormat.Replace("{TagId}", tag.Id.ToString()).Replace("{TagName}", tag.Name); - @tag.Name + @tag.Name } } } 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 319d6ad2f2..da11b0e9a7 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 @@ -10,6 +10,7 @@ @using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Tags @using Volo.Abp.AspNetCore.Mvc.UI.Packages.HighlightJs @using Volo.CmsKit.Contents +@using Volo.CmsKit.Web @using Volo.CmsKit.Web.Pages.CmsKit.Components.Contents @inherits CmsKitPublicPageBase @@ -62,7 +63,7 @@

@Model.ViewModel.Title

- + @@@Model.ViewModel.Author?.UserName @Model.ViewModel.CreationTime @@ -89,7 +90,7 @@ { entityType = Volo.CmsKit.Blogs.BlogPostConsts.EntityType, entityId = Model.ViewModel.Id.ToString(), - urlFormat = $"/blogs/{Model.BlogSlug}?tagId={{TagId}}" + urlFormat = $"/{CmsBlogsWebConsts.BlogsRoutePrefix}/{Model.BlogSlug}?tagId={{TagId}}" }) } } @@ -133,9 +134,11 @@ { + +


} @if (isScrollIndexEnabled) { diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/Index.cshtml b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/Index.cshtml index 060f0c5c95..6f2a82e220 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/Index.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/Index.cshtml @@ -2,18 +2,19 @@ @using Volo.CmsKit.Public.Web.Pages @using Volo.CmsKit.Public.Web.Pages.Public.CmsKit.Blogs +@using Volo.CmsKit.Web @inherits CmsKitPublicPageBase @model IndexModel -@section styles{ - +@section styles { + } @section scripts { - + } @@ -21,29 +22,43 @@ const string dummyImageSource = "https://dummyimage.com/320x180/a3a3a3/fff.png"; } - - -
- +@if (Model.AuthorId.HasValue) +{ + + +
+ - + + @if (Model.SelectedAuthor != null) + { + + } + +
+
+
+
+} + +@if (Model.TagId.HasValue) +{ +

@L["Tags"]

+ @Model.FilteredTagName + + +
+} - @if(Model.SelectedAuthor != null) - { - - } - -
-
-
@foreach (var blog in Model.Blogs.Items) { @@ -51,11 +66,11 @@ @if (blog.CoverImageMediaId != null) { - + } else { - + }
@blog.Title
@@ -65,7 +80,7 @@

@blog.ShortDescription

@@ -76,6 +91,6 @@
- + diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/Index.cshtml.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/Index.cshtml.cs index 7feab76946..e47dd40816 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/Index.cshtml.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/Index.cshtml.cs @@ -31,6 +31,8 @@ public class IndexModel : CmsKitPublicPageModelBase public CmsUserDto SelectedAuthor { get; protected set; } + public string FilteredTagName { get; protected set; } + protected IBlogPostPublicAppService BlogPostPublicAppService { get; } public IndexModel(IBlogPostPublicAppService blogPostPublicAppService) @@ -54,7 +56,12 @@ public class IndexModel : CmsKitPublicPageModelBase { SelectedAuthor = await BlogPostPublicAppService.GetAuthorHasBlogPostAsync(AuthorId.Value); } - + + if (TagId is not null) + { + FilteredTagName = await BlogPostPublicAppService.GetTagNameAsync(TagId.Value); + } + return Page(); } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/bootstrap-toc.css b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/bootstrap-toc.css index b15e18ee85..8599b9146d 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/bootstrap-toc.css +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/bootstrap-toc.css @@ -20,15 +20,17 @@ nav[data-toggle='toc'] .nav > li > a:focus { text-decoration: none; background-color: transparent; border-left: 1px solid #563d7c; + border-radius: 0; } nav[data-toggle='toc'] .nav-link.active, nav[data-toggle='toc'] .nav-link.active:hover, nav[data-toggle='toc'] .nav-link.active:focus { - padding-left: 18px; + padding-left: 8px; font-weight: bold; color: #563d7c; background-color: transparent; border-left: 2px solid #563d7c; + border-radius: 0; } /* Nav: second level (shown on .active) */ @@ -40,18 +42,16 @@ nav[data-toggle='toc'] .nav-link + ul { nav[data-toggle='toc'] .nav .nav > li > a { padding-top: 1px; padding-bottom: 1px; - padding-left: 30px; + padding-left: 8px; + margin-left: 8px; font-size: 12px; font-weight: normal; } -nav[data-toggle='toc'] .nav .nav > li > a:hover, -nav[data-toggle='toc'] .nav .nav > li > a:focus { - padding-left: 29px; -} + nav[data-toggle='toc'] .nav .nav > li > .active, nav[data-toggle='toc'] .nav .nav > li > .active:hover, nav[data-toggle='toc'] .nav .nav > li > .active:focus { - padding-left: 28px; + padding-left: 8px; font-weight: 500; } diff --git a/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Blogs/BlogPostPublicAppService_Tests.cs b/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Blogs/BlogPostPublicAppService_Tests.cs index 677e1ac086..edbbe3e8de 100644 --- a/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Blogs/BlogPostPublicAppService_Tests.cs +++ b/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Blogs/BlogPostPublicAppService_Tests.cs @@ -179,4 +179,19 @@ public class BlogPostPublicAppService_Tests : CmsKitApplicationTestBase allItemsFromRepository.Any(x => x.Id == draftBlogPost2.Id).ShouldBeTrue(); allItemsFromRepository.Any(x => x.Id == publishedBlogPost1.Id).ShouldBeTrue(); } + + [Fact] + public async Task GetTagNameAsync_ShouldReturnCorrectName() + { + var tagName = await blogPostAppService.GetTagNameAsync(cmsKitTestData.TagId_1); + + tagName.ShouldBe(cmsKitTestData.TagName_1); + } + + [Fact] + public async Task GetTagNameAsync_WithNonExistingIdShouldReturnCorrectName() + { + await Should.ThrowAsync( + blogPostAppService.GetTagNameAsync(Guid.NewGuid())); + } }