diff --git a/docs/en/modules/cms-kit/marked-items.md b/docs/en/modules/cms-kit/marked-items.md index b6b0af41731..05b9dd9e06f 100644 --- a/docs/en/modules/cms-kit/marked-items.md +++ b/docs/en/modules/cms-kit/marked-items.md @@ -58,6 +58,32 @@ The marking system provides a toggle widget to allow users to add/remove the mar * `entityId` should be the unique id of the product, in this example. If you have a Product entity, you can use its Id here. * `needsConfirmation` An optional parameter to let the user confirm when removing the mark. +### Filtering on Marked Items + +Users can filter their marked items to easily find their favorites. Here's how to utilize the `GetEntityIdsFilteredByUserAsync` method to filter the user's marked items within your repository queries: + +```csharp +List entityIdFilters = null; +if (userId.HasValue) +{ + entityIdFilters = await UserMarkedItemRepository.GetEntityIdsFilteredByUserAsync( + userId.Value, + entityType, + cancellationToken: cancellationToken + ); +} + +var queryable = (await GetDbSetAsync()) + .WhereIf(entityIdFilters != null, x => entityIdFilters.Contains(x.Id.ToString())); + +// Additional query logic... +``` + +- `GetEntityIdsFilteredByUserAsync`: Retrieves a list of entity IDs marked by the user for the given entity type. +- `userId`: The ID of the user performing the filtering. +- `entityType`: The type of entity being filtered (e.g., "product"). +- `entityIdFilters`: A list of marked entity IDs that will be used to filter the items in the database. + # Internals ## Domain Layer diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Pages/CreatePageInputDto.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Pages/CreatePageInputDto.cs index a28d87d0c10..a62ede1f056 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Pages/CreatePageInputDto.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Pages/CreatePageInputDto.cs @@ -17,6 +17,9 @@ public class CreatePageInputDto: ExtensibleObject [DynamicMaxLength(typeof(PageConsts), nameof(PageConsts.MaxSlugLength))] public string Slug { get; set; } + [DynamicMaxLength(typeof(PageConsts), nameof(PageConsts.MaxLayoutNameLength))] + public string LayoutName { get; set; } + [DynamicMaxLength(typeof(PageConsts), nameof(PageConsts.MaxContentLength))] public string Content { get; set; } diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Pages/PageDto.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Pages/PageDto.cs index eeb73ba918f..6fbcbd18666 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Pages/PageDto.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Pages/PageDto.cs @@ -11,6 +11,8 @@ public class PageDto : ExtensibleAuditedEntityDto, IHasConcurrencyStamp public string Slug { get; set; } + public string LayoutName { get; set; } + public string Content { get; set; } public string Script { get; set; } diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Pages/UpdatePageInputDto.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Pages/UpdatePageInputDto.cs index 0e26b29de8e..9e47ce54f00 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Pages/UpdatePageInputDto.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Pages/UpdatePageInputDto.cs @@ -18,6 +18,9 @@ public class UpdatePageInputDto : ExtensibleObject, IHasConcurrencyStamp [DynamicMaxLength(typeof(PageConsts), nameof(PageConsts.MaxSlugLength))] public string Slug { get; set; } + [DynamicMaxLength(typeof(PageConsts), nameof(PageConsts.MaxLayoutNameLength))] + public string LayoutName { get; set; } + [DynamicMaxLength(typeof(PageConsts), nameof(PageConsts.MaxContentLength))] public string Content { get; set; } diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Pages/PageAdminAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Pages/PageAdminAppService.cs index 4585077a490..1f5194c2005 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Pages/PageAdminAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Pages/PageAdminAppService.cs @@ -62,7 +62,7 @@ public virtual async Task> GetListAsync(GetPagesInputDto [Authorize(CmsKitAdminPermissions.Pages.Create)] public virtual async Task CreateAsync(CreatePageInputDto input) { - var page = await PageManager.CreateAsync(input.Title, input.Slug, input.Content, input.Script, input.Style); + var page = await PageManager.CreateAsync(input.Title, input.Slug, input.Content, input.Script, input.Style, input.LayoutName); input.MapExtraPropertiesTo(page); await PageRepository.InsertAsync(page); @@ -88,6 +88,7 @@ public virtual async Task UpdateAsync(Guid id, UpdatePageInputDto input page.SetContent(input.Content); page.SetScript(input.Script); page.SetStyle(input.Style); + page.SetLayoutName(input.LayoutName); page.SetConcurrencyStampIfNotNull(input.ConcurrencyStamp); input.MapExtraPropertiesTo(page); diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Layouts/LayoutConstants.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Layouts/LayoutConstants.cs new file mode 100644 index 00000000000..a5938900149 --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Layouts/LayoutConstants.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; +using Microsoft.AspNetCore.Mvc.Rendering; +using Volo.Abp.AspNetCore.Mvc.UI.Theming; + +namespace Volo.CmsKit.Admin.Web.Layouts; + +public static class LayoutConstants +{ + public const string Account = StandardLayouts.Account; + public const string Public = StandardLayouts.Public; + public const string Empty = StandardLayouts.Empty; + public const string Application = StandardLayouts.Application; + public static SelectList GetLayoutsSelectList() + { + return new SelectList(new List { Account, Public, Empty, Application }, Application); + } +} 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 afef4bdad5c..6ddbae58833 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 @@ -11,6 +11,7 @@ @using Volo.Abp.AspNetCore.Mvc.UI.Packages.Codemirror @using Volo.Abp.AspNetCore.Mvc.UI.Packages.TuiEditor @using Volo.Abp.AspNetCore.Mvc.UI.Packages.Uppy +@using Volo.CmsKit.Admin.Web.Layouts @using Volo.CmsKit.Admin.Web.Pages @using Volo.CmsKit.Admin.Web.Menus @using Volo.Abp.AspNetCore.Mvc.UI.Packages.Slugify @@ -61,6 +62,8 @@ + + diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Create.cshtml.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Create.cshtml.cs index de694056908..9a8369ad600 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Create.cshtml.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Create.cshtml.cs @@ -39,6 +39,10 @@ public class CreatePageViewModel : ExtensibleObject [DynamicMaxLength(typeof(PageConsts), nameof(PageConsts.MaxTitleLength))] public string Title { get; set; } + [Required] + [DynamicMaxLength(typeof(PageConsts), nameof(PageConsts.MaxLayoutNameLength))] + public string LayoutName { get; set; } + [Required] [DynamicMaxLength(typeof(PageConsts), nameof(PageConsts.MaxSlugLength))] public string Slug { get; set; } 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 08fc0642264..4d4c9d9454f 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 @@ -15,6 +15,7 @@ @using Volo.Abp.Data @using Volo.Abp.Localization @using Volo.Abp.ObjectExtending +@using Volo.CmsKit.Admin.Web.Layouts @using Volo.CmsKit.Admin.Web.Menus @using Volo.CmsKit.Admin.Web.Pages @using Volo.CmsKit.Admin.Web.Pages.CmsKit.Pages @@ -66,6 +67,8 @@ + + diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Update.cshtml.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Update.cshtml.cs index 078e0d760db..44c48a31c06 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Update.cshtml.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Pages/Update.cshtml.cs @@ -56,6 +56,10 @@ public class UpdatePageViewModel : ExtensibleObject, IHasConcurrencyStamp [DynamicMaxLength(typeof(PageConsts), nameof(PageConsts.MaxSlugLength))] public string Slug { get; set; } + [Required] + [DynamicMaxLength(typeof(PageConsts), nameof(PageConsts.MaxLayoutNameLength))] + public string LayoutName { get; set; } + [HiddenInput] [DynamicMaxLength(typeof(PageConsts), nameof(PageConsts.MaxSlugLength))] public string Content { get; set; } 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 817d06d967c..e81a882baa1 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 @@ -9,6 +9,8 @@ public class PageDto : ExtensibleEntityDto public string Slug { get; set; } + public string LayoutName { get; set; } + public string Content { get; set; } public string Script { get; set; } 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 7be776daa3d..149f1072bfe 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 @@ -140,6 +140,7 @@ "SamplePageMessage": "A sample page for the Pro module", "SaveChanges": "Save changes", "Script": "Script", + "SelectLayout": "Select Layout", "SelectAll": "Select all", "Send": "Send", "SendMessage": "Send Message", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Pages/PageConsts.cs b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Pages/PageConsts.cs index f703fbac435..8b0fbb087c9 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Pages/PageConsts.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Pages/PageConsts.cs @@ -10,6 +10,8 @@ public static class PageConsts public static int MaxSlugLength { get; set; } = 256; + public static int MaxLayoutNameLength { get; set; } = 256; + public static int MaxContentLength { get; set; } = int.MaxValue; public static int MaxScriptLength { get; set; } = int.MaxValue; diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Pages/Page.cs b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Pages/Page.cs index 1ed89ff7f64..b1f611abc67 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Pages/Page.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Pages/Page.cs @@ -25,6 +25,8 @@ public class Page : FullAuditedAggregateRoot, IMultiTenant, IHasEntityVers public virtual int EntityVersion { get; protected set; } + public virtual string LayoutName { get; protected set; } + protected Page() { } @@ -36,6 +38,7 @@ internal Page( string content = null, string script = null, string style = null, + string layoutName = null, Guid? tenantId = null) : base(id) { TenantId = tenantId; @@ -45,6 +48,7 @@ internal Page( SetContent(content); SetScript(script); SetStyle(style); + SetLayoutName(layoutName); } public virtual void SetTitle(string title) @@ -72,6 +76,11 @@ public virtual void SetStyle(string style) Style = Check.Length(style, nameof(style), PageConsts.MaxStyleLength); } + public virtual void SetLayoutName(string layoutName) + { + LayoutName = Check.Length(layoutName, nameof(layoutName), PageConsts.MaxLayoutNameLength); + } + internal void SetIsHomePage(bool isHomePage) { IsHomePage = isHomePage; diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Pages/PageCacheItem.cs b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Pages/PageCacheItem.cs index 4dadd04e8eb..d4f79251603 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Pages/PageCacheItem.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Pages/PageCacheItem.cs @@ -11,6 +11,8 @@ public class PageCacheItem : ExtensibleObject public string Slug { get; set; } + public string LayoutName { get; set; } + public string Content { get; set; } public string Script { get; set; } diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Pages/PageManager.cs b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Pages/PageManager.cs index 587ae911444..a94602c54ad 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Pages/PageManager.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Pages/PageManager.cs @@ -20,7 +20,8 @@ public virtual async Task CreateAsync( [NotNull] string slug, [CanBeNull] string content = null, [CanBeNull] string script = null, - [CanBeNull] string style = null) + [CanBeNull] string style = null, + [CanBeNull] string layoutName = null) { Check.NotNullOrEmpty(title, nameof(title)); Check.NotNullOrEmpty(slug, nameof(slug)); @@ -34,6 +35,7 @@ public virtual async Task CreateAsync( content, script, style, + layoutName, CurrentTenant.Id); } diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Layouts/LayoutExtensions.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Layouts/LayoutExtensions.cs new file mode 100644 index 00000000000..5916db2a3ec --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Layouts/LayoutExtensions.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using Volo.Abp.AspNetCore.Mvc.UI.Theming; + +namespace Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Layouts; + +public static class LayoutExtensions +{ + private static readonly Dictionary> LayoutFunctions = new() + { + [StandardLayouts.Account] = theme => theme.GetAccountLayout(), + [StandardLayouts.Public] = theme => theme.GetPublicLayout(), + [StandardLayouts.Empty] = theme => theme.GetEmptyLayout(), + }; + + public static string GetLayoutByKey(this ITheme theme, string layoutKey) + { + return !string.IsNullOrWhiteSpace(layoutKey) && LayoutFunctions.TryGetValue(layoutKey, out var layoutFunc) + ? layoutFunc(theme) + : theme.GetApplicationLayout(); // Application layout is the default + } +} \ No newline at end of file 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 79e2dad802c..a9cb4d4ad91 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 @@ -1,9 +1,16 @@ @page "/cmskit/page" @addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bootstrap +@using Volo.Abp.AspNetCore.Mvc.UI.Theming @using Volo.CmsKit.Contents +@using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Layouts @using Volo.CmsKit.Web.Pages.CmsKit.Components.Contents @model Volo.CmsKit.Public.Web.Pages.Public.CmsKit.Pages.IndexModel +@inject ITheme ThemeManager + +@{ + Layout = ThemeManager.GetLayoutByKey(Model.ViewModel.LayoutName); +} @section styles{ 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 31958260932..27432305fe1 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 @@ -13,6 +13,8 @@ public class PageViewModel public string Title { get; set; } + public string LayoutName { get; set; } + public List ContentFragments { get; set; } public string Script { get; set; } diff --git a/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Comments/CommentPublicAppService_Tests.cs b/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Comments/CommentPublicAppService_Tests.cs index adf650c2ba3..a60c57c7257 100644 --- a/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Comments/CommentPublicAppService_Tests.cs +++ b/modules/cms-kit/test/Volo.CmsKit.Application.Tests/Comments/CommentPublicAppService_Tests.cs @@ -84,8 +84,8 @@ await _commentAppService.CreateAsync( } [Theory] - [InlineData("[ABP Community](https://community.abp.io/)")] - [InlineData("docs.abp.io")] + [InlineData("[ABP Community](https://community.abp.io/)")] //not allowed URL + [InlineData("docs.abp.io")] //not allowed URL public async Task CreateAsync_ShouldThrowUserFriendlyException_If_Url_UnAllowed(string text) { _currentUser.Id.Returns(_cmsKitTestData.User2Id);