Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add layout name selection for improved CMS page customization. #20911

Merged
merged 6 commits into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions docs/en/modules/cms-kit/marked-items.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<string> 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ public class PageDto : ExtensibleAuditedEntityDto<Guid>, IHasConcurrencyStamp

public string Slug { get; set; }

public string LayoutName { get; set; }

public string Content { get; set; }

public string Script { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public virtual async Task<PagedResultDto<PageDto>> GetListAsync(GetPagesInputDto
[Authorize(CmsKitAdminPermissions.Pages.Create)]
public virtual async Task<PageDto> 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);

Expand All @@ -88,6 +88,7 @@ public virtual async Task<PageDto> 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);

Expand Down
Original file line number Diff line number Diff line change
@@ -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<string> { Account, Public, Empty, Application }, Application);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -61,6 +62,8 @@

<abp-input asp-for="ViewModel.Slug" label-tooltip-icon="fa fa-info-circle" label-tooltip="@L["PageSlugInformation"]" />

<abp-select id="Layout" asp-for="ViewModel.LayoutName" asp-items="@LayoutConstants.GetLayoutsSelectList()" label="@L["SelectLayout"]"></abp-select>

<abp-input asp-for="@Model.ViewModel.Content" />

<abp-tabs tab-style="Tab">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -66,6 +67,8 @@

<abp-input asp-for="ViewModel.Slug" label-tooltip-icon="fa fa-info-circle" label-tooltip="@L["PageSlugInformation"]" />

<abp-select id="Layout" asp-for="ViewModel.LayoutName" asp-items="@LayoutConstants.GetLayoutsSelectList()" label="@L["SelectLayout"]"></abp-select>

<abp-input asp-for="@Model.ViewModel.Content" />

<abp-tabs tab-style="Tab">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ public class PageDto : ExtensibleEntityDto<Guid>

public string Slug { get; set; }

public string LayoutName { get; set; }

public string Content { get; set; }

public string Script { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ public class Page : FullAuditedAggregateRoot<Guid>, IMultiTenant, IHasEntityVers

public virtual int EntityVersion { get; protected set; }

public virtual string LayoutName { get; protected set; }

protected Page()
{
}
Expand All @@ -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;
Expand All @@ -45,6 +48,7 @@ internal Page(
SetContent(content);
SetScript(script);
SetStyle(style);
SetLayoutName(layoutName);
}

public virtual void SetTitle(string title)
Expand Down Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ public virtual async Task<Page> 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));
Expand All @@ -34,6 +35,7 @@ public virtual async Task<Page> CreateAsync(
content,
script,
style,
layoutName,
CurrentTenant.Id);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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<string, Func<ITheme, string>> 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
}
}
Original file line number Diff line number Diff line change
@@ -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{

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ public class PageViewModel

public string Title { get; set; }

public string LayoutName { get; set; }

public List<ContentFragment> ContentFragments { get; set; }

public string Script { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ await _commentAppService.CreateAsync(
}

[Theory]
[InlineData("[ABP Community](https://community.abp.io/)")]
[InlineData("<a href='https://docs.abp.io/en/abp/latest'>docs.abp.io</a>")]
[InlineData("[ABP Community](https://community.abp.io/)")] //not allowed URL
[InlineData("<a href='https://docs.abp.io/en/abp/latest'>docs.abp.io</a>")] //not allowed URL
public async Task CreateAsync_ShouldThrowUserFriendlyException_If_Url_UnAllowed(string text)
{
_currentUser.Id.Returns(_cmsKitTestData.User2Id);
Expand Down
Loading