Browse Source

new feature(CmsKit): Marked Item

Add Marked Item feature to allow marking items as  favorite, starred, flagged, or bookmarked.

- Added Marked Toggling Component to mark items via pre-defined icons/emojis.
- Created Marked Item widget for toggling marks on items.

Documentation: Provided detailed usage and configuration instructions in the CMS Kit Module documentation.
pull/20056/head
Suhaib 2 years ago
parent
commit
21d5582123
  1. 1
      docs/en/Modules/Cms-Kit/Index.md
  2. 148
      docs/en/Modules/Cms-Kit/MarkedItems.md
  3. BIN
      docs/en/images/cmskit-module-markedItems.png
  4. BIN
      docs/en/images/cmskit-module-markedItemsFilter.gif
  5. 11
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/CmsKitWebUnifiedModule.cs
  6. 30
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/Pages/Index.cshtml
  7. 4
      modules/cms-kit/src/Volo.CmsKit.Common.Web/CmsKitUiOptions.cs
  8. 21
      modules/cms-kit/src/Volo.CmsKit.Common.Web/Icons/IconDictionaryHelper.cs
  9. 18
      modules/cms-kit/src/Volo.CmsKit.Common.Web/Icons/LocalizableIconDictionaryBase.cs
  10. 7
      modules/cms-kit/src/Volo.CmsKit.Common.Web/MarkedItems/MarkedItemIconDictionary.cs
  11. 16
      modules/cms-kit/src/Volo.CmsKit.Common.Web/Reactions/ReactionIconDictionary.cs
  12. 5
      modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/CmsKitErrorCodes.cs
  13. 9
      modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Features/CmsKitFeatureDefinitionProvider.cs
  14. 1
      modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Features/CmsKitFeatures.cs
  15. 3
      modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/GlobalFeatures/GlobalCmsKitFeatures.cs
  16. 27
      modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/GlobalFeatures/MarkedItemsFeature.cs
  17. 8
      modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ar.json
  18. 500
      modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json
  19. 9
      modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/MarkedItems/StandardMarkedItems.cs
  20. 9
      modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/MarkedItems/UserMarkedItemConsts.cs
  21. 10
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/MarkedItems/CmsKitMarkedItemOptions.cs
  22. 36
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/MarkedItems/DefaultMarkedItemDefinitionStore.cs
  23. 16
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/MarkedItems/EntityCannotBeMarkedException.cs
  24. 8
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/MarkedItems/IMarkedItemDefinitionStore.cs
  25. 31
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/MarkedItems/IUserMarkedItemRepository.cs
  26. 16
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/MarkedItems/MarkedItemEntityTypeDefinition.cs
  27. 58
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/MarkedItems/MarkedItemManager.cs
  28. 36
      modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/MarkedItems/UserMarkedItem.cs
  29. 2
      modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/EntityFrameworkCore/CmsKitDbContext.cs
  30. 23
      modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/EntityFrameworkCore/CmsKitDbContextModelCreatingExtensions.cs
  31. 2
      modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/EntityFrameworkCore/CmsKitEntityFrameworkCoreModule.cs
  32. 2
      modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/EntityFrameworkCore/ICmsKitDbContext.cs
  33. 67
      modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/MarkedItems/EfCoreUserMarkedItemRepository.cs
  34. 3
      modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/CmsKitMongoDbContext.cs
  35. 6
      modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/CmsKitMongoDbContextExtensions.cs
  36. 3
      modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/CmsKitMongoDbModule.cs
  37. 3
      modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/ICmsKitMongoDbContext.cs
  38. 67
      modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/MarkedItems/MongoUserMarkedItemRepository.cs
  39. 10
      modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/MarkedItems/IMarkedItemPublicAppService.cs
  40. 11
      modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/MarkedItems/MarkedItemDto.cs
  41. 11
      modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/MarkedItems/MarkedItemWithToggleDto.cs
  42. 69
      modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/MarkedItems/MarkedItemPublicAppService.cs
  43. 15
      modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Blogs/BlogPostFilteredPagedAndSortedResultRequestDto.cs
  44. 17
      modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Blogs/BlogPostGetListInput.cs
  45. 28
      modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Blogs/IBlogPostPublicAppService.cs
  46. 21
      modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Comments/CmsUserDto.cs
  47. 33
      modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Comments/CommentDto.cs
  48. 31
      modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Comments/CommentWithDetailsDto.cs
  49. 25
      modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Comments/CreateCommentInput.cs
  50. 22
      modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Comments/ICommentPublicAppService.cs
  51. 21
      modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Comments/UpdateCommentInput.cs
  52. 17
      modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/GlobalResources/GlobalResourceDto.cs
  53. 18
      modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/GlobalResources/IGlobalResourcePublicAppService.cs
  54. 18
      modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/MarkedItems/IMarkedItemPublicAppService.cs
  55. 15
      modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/MarkedItems/MarkedItemDto.cs
  56. 37
      modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/MarkedItems/MarkedItemPublicClientProxy.Generated.cs
  57. 7
      modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/MarkedItems/MarkedItemPublicClientProxy.cs
  58. 17
      modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/MarkedItems/MarkedItemWithToggleDto.cs
  59. 17
      modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Menus/IMenuItemPublicAppService.cs
  60. 21
      modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Pages/IPagePublicAppService.cs
  61. 15
      modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Ratings/CreateUpdateRatingInput.cs
  62. 20
      modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Ratings/IRatingPublicAppService.cs
  63. 25
      modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Ratings/RatingDto.cs
  64. 19
      modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Ratings/RatingWithStarCountDto.cs
  65. 20
      modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Reactions/IReactionPublicAppService.cs
  66. 17
      modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Reactions/ReactionDto.cs
  67. 19
      modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Reactions/ReactionWithSelectionDto.cs
  68. 18
      modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Tags/ITagAppService.cs
  69. 8838
      modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/cms-kit-generate-proxy.json
  70. 38
      modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/MarkedItems/MarkedItemPublicController.cs
  71. 10
      modules/cms-kit/src/Volo.CmsKit.Public.Web/CmsKitPublicWebModule.cs
  72. 6
      modules/cms-kit/src/Volo.CmsKit.Public.Web/Controllers/CmsKitPublicWidgetsController.cs
  73. 14
      modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/MarkedItemToggle/Default.cshtml
  74. 13
      modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/MarkedItemToggle/MarkedItemToggleScriptBundleContributor.cs
  75. 12
      modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/MarkedItemToggle/MarkedItemToggleStyleBundleContributor.cs
  76. 77
      modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/MarkedItemToggle/MarkedItemToggleViewComponent.cs
  77. 7
      modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/MarkedItemToggle/default.css
  78. 92
      modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/MarkedItemToggle/default.js
  79. 22
      modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Modals/Login/LoginModal.cshtml
  80. 32
      modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Modals/Login/LoginModal.cshtml.cs
  81. 22
      modules/cms-kit/src/Volo.CmsKit.Public.Web/wwwroot/client-proxies/cms-kit-proxy.js
  82. 65
      modules/cms-kit/test/Volo.CmsKit.Application.Tests/MarkedItems/MarkedItemPublicAppService_Tests.cs
  83. 45
      modules/cms-kit/test/Volo.CmsKit.Domain.Tests/MarkedItems/MarkedItemManager_Tests.cs
  84. 6
      modules/cms-kit/test/Volo.CmsKit.EntityFrameworkCore.Tests/EntityFrameworkCore/MarkedItems/UserMarkedItemRepository_Tests.cs
  85. 9
      modules/cms-kit/test/Volo.CmsKit.MongoDB.Tests/MongoDB/MarkedItems/UserMarkedItemRepository_Tests.cs
  86. 28
      modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs
  87. 64
      modules/cms-kit/test/Volo.CmsKit.TestBase/MarkedItems/UserMarkedItemRepository_Tests.cs

1
docs/en/Modules/Cms-Kit/Index.md

@ -17,6 +17,7 @@ The following features are currently available:
* Provides a [**menu**](Menus.md) system to manage public menus dynamically.
* Provides a [**global resources**](Global-Resources.md) system to add global styles and scripts dynamically.
* Provides a [**Dynamic Widget**](Dynamic-Widget.md) system to create dynamic widgets for page and blog posts.
* Provides a [**Marked Item**](MarkedItems.md) system to mark any kind of resource, like a blog post or a product, as a favorite, starred, flagged, or bookmarked.
> You can click on the any feature links above to understand and learn how to use it.

148
docs/en/Modules/Cms-Kit/MarkedItems.md

@ -0,0 +1,148 @@
# Marked Item System
CMS kit provides a marking system to mark any kind of resource, like a blog post or a product, as a favorite, starred, flagged, or bookmarked.
Marked toggling component allows users to mark your items via pre-defined icons/emojis. Here how the marked toggling components may look like:
![markedItems](../../images/cmskit-module-markedItems.png)
you can also customize the marking icons shown in the toggling components.
## Enabling the Marked Item Feature
By default, CMS Kit features are disabled. Therefore, you need to enable the features you want, before starting to use it. You can use the [Global Feature](../../Global-Features.md) system to enable/disable CMS Kit features on development time. Alternatively, you can use the ABP Framework's [Feature System](https://docs.abp.io/en/abp/latest/Features) to disable a CMS Kit feature on runtime.
> Check the ["How to Install" section of the CMS Kit Module documentation](Index.md#how-to-install) to see how to enable/disable CMS Kit features on development time.
## Options
Marking system provides a simple approach to define your entity type with mark types like favorite or starred. For example, if you want to use the marking system for products, you need to define an entity type named `product` with the icon name.
`CmsKitMarkedItemOptions` can be configured in YourModule.cs, in the `ConfigureServices` method of your [module](https://docs.abp.io/en/abp/latest/Module-Development-Basics). Example:
```csharp
Configure<CmsKitMarkedItemOptions>(options =>
{
options.EntityTypes.Add(
new MarkedItemEntityTypeDefinition(
"product",
StandardMarkedItems.Favorite
)
);
});
```
`CmsKitMarkedItemOptions` properties:
- `EntityTypes`: List of defined entity types (`CmsKitMarkedItemOptions`) in the marking system.
`MarkedItemEntityTypeDefinition` properties:
- `EntityType`: Name of the entity type.
- `IconName`: The name of the icon.
## The Marked Item widget
The marking system provides a toggle widget to allow users to add/remove the marks from an item. You can place the widget with the item as shown below:
``` csharp
@await Component.InvokeAsync(typeof (MarkedItemToggleViewComponent), new
{
entityId = "...",
entityType = "product",
needsConfirmation = true // (optional)
})
```
* `entityType` was explained in the previous section.
* `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.
# Filter on marked items
Filtering on marked items enhances the user experience by making it easier to search marked items.
![markedItemsFilter](../../images/cmskit-module-markedItemsFilter.gif)
There is an ability to utilize the marking system to let users filter on their marked items. The code below shows how you can filter on your query filter:
```csharp
protected async override Task<IQueryable<YourEntity>> CreateFilteredQueryAsync(YourEntityPagedAndSortedResultDto input)
{
IQueryable<YourEntity> query = await base.CreateFilteredQueryAsync(input);
if (input.FilterOnFavorites && CurrentUser.IsAuthenticated)
{
var markedQuery = await UserMarkedItemRepository.GetQueryForUserAsync("entityType", CurrentUser.GetId());
query = query.Where(e => markedQuery.Any(m => m.EntityId == e.Id));
}
// ...
return query;
}
```
# Internals
## Domain Layer
#### Aggregates
This module follows the [Entity Best Practices & Conventions](https://docs.abp.io/en/abp/latest/Best-Practices/Entities) guide.
##### UserMarkedItem
A user markedItem represents a user has marking on the item.
- `UserMarkedItem` (aggregate root): Represents a marked item in the system.
#### Repositories
This module follows the [Repository Best Practices & Conventions](https://docs.abp.io/en/abp/latest/Best-Practices/Repositories) guide.
Following custom repositories are defined for this feature:
- `IUserMarkedItemRepository`
#### Domain services
This module follows the [Domain Services Best Practices & Conventions](https://docs.abp.io/en/abp/latest/Best-Practices/Domain-Services) guide.
##### Marked Item Manager
`MarkedItemManager` is used to perform some operations for the `UserMarkedItem` aggregate root.
### Application layer
#### Application services
- `MarkedItemPublicAppService` (implements `IMarkedItemPublicAppService`): Implements the use cases of marking system.
### Database providers
#### Common
##### Table / collection prefix & schema
All tables/collections use the `Cms` prefix by default. Set static properties on the `CmsKitDbProperties` class if you need to change the table prefix or set a schema name (if supported by your database provider).
##### Connection string
This module uses `CmsKit` for the connection string name. If you don't define a connection string with this name, it fallbacks to the `Default` connection string.
See the [connection strings](https://docs.abp.io/en/abp/latest/Connection-Strings) documentation for details.
#### Entity Framework Core
##### Tables
- CmsUserMarkedItems
#### MongoDB
##### Collections
- **CmsUserMarkedItems**

BIN
docs/en/images/cmskit-module-markedItems.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

BIN
docs/en/images/cmskit-module-markedItemsFilter.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 KiB

11
modules/cms-kit/host/Volo.CmsKit.Web.Unified/CmsKitWebUnifiedModule.cs

@ -42,6 +42,7 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Volo.Abp.DependencyInjection;
using Volo.CmsKit.Public.Pages;
using Volo.CmsKit.MarkedItems;
#if EntityFrameworkCore
@ -234,6 +235,16 @@ public class CmsKitWebUnifiedModule : AbpModule
{
options.EntityTypes.Add(new RatingEntityTypeDefinition("quote"));
});
Configure<CmsKitMarkedItemOptions>(options =>
{
options.EntityTypes.Add(
new MarkedItemEntityTypeDefinition(
"product",
StandardMarkedItems.Favorite
)
);
});
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)

30
modules/cms-kit/host/Volo.CmsKit.Web.Unified/Pages/Index.cshtml

@ -8,6 +8,7 @@
@using Volo.CmsKit.GlobalFeatures
@using Volo.CmsKit.Pages
@using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Commenting
@using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.MarkedItemToggle
@using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Rating
@using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.ReactionSelection
@using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Tags
@ -118,3 +119,32 @@
}
</abp-column>
</abp-row>
<hr />
<abp-row>
@for (int i = 1; i <= 4; i++)
{
var name = $"Item {i}";
<abp-column>
<abp-card background="Light" text-color="Dark" border="Success" class="mb-3" style="max-width: 18rem;">
<abp-card-header class="d-flex justify-content-between">
<div>
Item
</div>
<div>
@await Component.InvokeAsync(typeof(MarkedItemToggleViewComponent), new
{
entityId = name,
entityType = "product",
needsConfirmation = true // (optional)
})
</div>
</abp-card-header>
<abp-card-body>
<abp-card-title>@name</abp-card-title>
</abp-card-body>
</abp-card>
</abp-column>
}
</abp-row>

4
modules/cms-kit/src/Volo.CmsKit.Common.Web/CmsKitUiOptions.cs

@ -1,4 +1,5 @@
using JetBrains.Annotations;
using Volo.CmsKit.Web.MarkedItems;
using Volo.CmsKit.Web.Reactions;
namespace Volo.CmsKit.Web;
@ -10,9 +11,12 @@ public class CmsKitUiOptions
public CmsKitUiCommentOptions CommentsOptions { get; }
public MarkedItemIconDictionary MarkedItemIcons { get; }
public CmsKitUiOptions()
{
ReactionIcons = new ReactionIconDictionary();
CommentsOptions = new CmsKitUiCommentOptions();
MarkedItemIcons = new MarkedItemIconDictionary();
}
}

21
modules/cms-kit/src/Volo.CmsKit.Common.Web/Icons/IconDictionaryHelper.cs

@ -0,0 +1,21 @@
using System.Collections.Generic;
using Volo.Abp;
namespace Volo.CmsKit.Web.Icons;
public static class IconDictionaryHelper
{
public static string GetLocalizedIcon(
Dictionary<string, LocalizableIconDictionary> dictionary,
string name,
string cultureName = null)
{
var icon = dictionary.GetOrDefault(name);
if (icon == null)
{
throw new AbpException($"No icon defined for the item with name '{name}'");
}
return icon.GetLocalizedIconOrDefault(cultureName);
}
}

18
modules/cms-kit/src/Volo.CmsKit.Common.Web/Icons/LocalizableIconDictionaryBase.cs

@ -0,0 +1,18 @@
using System.Collections.Generic;
using Volo.Abp;
namespace Volo.CmsKit.Web.Icons;
public class LocalizableIconDictionaryBase : Dictionary<string, LocalizableIconDictionary>
{
public string GetLocalizedIcon(string name, string cultureName = null)
{
var icon = this.GetOrDefault(name);
if (icon == null)
{
throw new AbpException($"No icon defined for the item with name '{name}'");
}
return icon.GetLocalizedIconOrDefault(cultureName);
}
}

7
modules/cms-kit/src/Volo.CmsKit.Common.Web/MarkedItems/MarkedItemIconDictionary.cs

@ -0,0 +1,7 @@
using Volo.CmsKit.Web.Icons;
namespace Volo.CmsKit.Web.MarkedItems;
public class MarkedItemIconDictionary : LocalizableIconDictionaryBase
{
}

16
modules/cms-kit/src/Volo.CmsKit.Common.Web/Reactions/ReactionIconDictionary.cs

@ -1,19 +1,7 @@
using System.Collections.Generic;
using Volo.Abp;
using Volo.CmsKit.Web.Icons;
using Volo.CmsKit.Web.Icons;
namespace Volo.CmsKit.Web.Reactions;
public class ReactionIconDictionary : Dictionary<string, LocalizableIconDictionary>
public class ReactionIconDictionary : LocalizableIconDictionaryBase
{
public string GetLocalizedIcon(string name, string cultureName = null)
{
var icon = this.GetOrDefault(name);
if (icon == null)
{
throw new AbpException($"No icon defined for the reaction with name '{name}'");
}
return icon.GetLocalizedIconOrDefault(cultureName);
}
}

5
modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/CmsKitErrorCodes.cs

@ -44,4 +44,9 @@ public static class CmsKitErrorCodes
public const string InvalidName = "CmsKit:Media:0001";
public const string EntityTypeDoesntExist = "CmsKit:Media:0002";
}
public static class MarkedItems
{
public const string EntityCannotBeMarked = "CmsKit:MarkedItem:0001";
}
}

9
modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Features/CmsKitFeatureDefinitionProvider.cs

@ -84,6 +84,15 @@ public class CmsKitFeatureDefinitionProvider : FeatureDefinitionProvider
L("Feature:TagEnableDescription"),
new ToggleStringValueType());
}
if (GlobalFeatureManager.Instance.IsEnabled<MarkedItemsFeature>())
{
group.AddFeature(CmsKitFeatures.MarkedItemEnable,
"true",
L("Feature:MarkedItemEnable"),
L("Feature:MarkedItemEnableDescription"),
new ToggleStringValueType());
}
}
private static LocalizableString L(string name)

1
modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Features/CmsKitFeatures.cs

@ -11,4 +11,5 @@ public static class CmsKitFeatures
public const string RatingEnable = GroupName + ".RatingEnable";
public const string ReactionEnable = GroupName + ".ReactionEnable";
public const string TagEnable = GroupName + ".TagEnable";
public const string MarkedItemEnable = GroupName + ".MarkedItemEnable";
}

3
modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/GlobalFeatures/GlobalCmsKitFeatures.cs

@ -29,6 +29,8 @@ public class GlobalCmsKitFeatures : GlobalModuleFeatures
public BlogPostScrollIndexFeature BlogPostScrollIndex => GetFeature<BlogPostScrollIndexFeature>();
public MarkedItemsFeature MarkedItemsFeature => GetFeature<MarkedItemsFeature>();
public GlobalCmsKitFeatures([NotNull] GlobalFeatureManager featureManager)
: base(featureManager)
{
@ -43,5 +45,6 @@ public class GlobalCmsKitFeatures : GlobalModuleFeatures
AddFeature(new MenuFeature(this));
AddFeature(new GlobalResourcesFeature(this));
AddFeature(new BlogPostScrollIndexFeature(this));
AddFeature(new MarkedItemsFeature(this));
}
}

27
modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/GlobalFeatures/MarkedItemsFeature.cs

@ -0,0 +1,27 @@
using JetBrains.Annotations;
using Volo.Abp.GlobalFeatures;
namespace Volo.CmsKit.GlobalFeatures;
[GlobalFeatureName(Name)]
public class MarkedItemsFeature : GlobalFeature
{
public const string Name = "CmsKit.MarkedItems";
internal MarkedItemsFeature(
[NotNull] GlobalCmsKitFeatures cmsKit
) : base(cmsKit)
{
}
public override void Enable()
{
var userFeature = FeatureManager.Modules.CmsKit().User;
if (!userFeature.IsEnabled)
{
userFeature.Enable();
}
base.Enable();
}
}

8
modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ar.json

@ -25,9 +25,15 @@
"CmsKit:Page:0001": "عنوان url المقدم ({Slug}) موجود بالفعل. يرجى المحاولة مع عنوان url مختلف.",
"CmsKit:Rating:0001": "لا يمكن تصنيف الكيان {EntityType}.",
"CmsKit:Reaction:0001": "لا يمكن أن يحتوي الكيان {EntityType} على ردود أفعال.",
"CmsKit:MarkedItem:0001": "لا يمكن أن تمييز الكيان {EntityType}.",
"CmsKit:Tag:0002": "الكيان غير قابل للوسم!",
"CommentAuthorizationExceptionMessage": "هذه التعليقات غير مسموح بها للعرض العام.",
"CommentDeletionConfirmationMessage": "سيتم حذف هذا التعليق وجميع الردود!",
"CmsKit:Modals:Login": "تسجيل الدخول",
"CmsKit:Modals:LoginModalDefaultMessage": "سجل الدخول لتتمكن من اجراء هذه العملية",
"CmsKit:Modals:YouAreNotAuthenticated": "انت غير مصرح",
"CmsKit:MarkedItem:LoginMessage": "الرجاء تسجيل الدخول لتحديد هذا العنصر.",
"CmsKit:MarkedItem:ToggleConfirmation": "هل أنت متأكد أنك تريد تغيير حالة العنصر المميز؟",
"Comments": "تعليقات",
"Content": "المحتوى",
"ContentDeletionConfirmationMessage": "هل أنت متأكد من حذف هذا المحتوى؟",
@ -212,6 +218,8 @@
"Feature:RatingEnableDescription": "نظام تصنيف CMS Kit الذي يسمح للمستخدمين بتقييم الكيانات مثل BlogPost.",
"Feature:ReactionEnable": "رد فعل",
"Feature:ReactionEnableDescription": "نظام التفاعل الخاص بـ CMS Kit الذي يسمح للمستخدمين بإرسال ردود أفعال إلى كيانات مثل BlogPost، والتعليقات، وما إلى ذلك.",
"Feature:MarkedItemEnable": "تمييز العنصر",
"Feature:MarkedItemEnableDescription": "نظام التفاعل الخاص بـ CMS Kit الذي يسمح للمستخدمين بتمييز الكيانات كجعلها مفضلة.",
"Feature:TagEnable": "وضع العلامات",
"Feature:TagEnableDescription": "نظام علامات CMS Kit الذي يسمح بوضع علامات على الكيانات مثل BlogPost.",
"DeleteBlogPostMessage": "سيتم حذف المدونة. هل أنت متأكد؟",

500
modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json

@ -1,249 +1,257 @@
{
"culture": "en",
"texts": {
"AddSubMenuItem": "Add Sub Menu Item",
"AreYouSure": "Are You Sure?",
"BlogDeletionConfirmationMessage": "The blog '{0}' will be deleted. Are you sure?",
"BlogFeatureNotAvailable": "This feature is not available now. Enable with 'GlobalFeatureManager' to use it.",
"BlogId": "Blog",
"BlogPostDeletionConfirmationMessage": "The blog post '{0}' will be deleted. Are you sure?",
"BlogPosts": "Blog posts",
"Blogs": "Blogs",
"ChoosePreference": "Choose Preference...",
"Cms": "CMS",
"CmsKit.Comments": "Comments",
"CmsKit.Ratings": "Ratings",
"CmsKit.Reactions": "Reactions",
"CmsKit.Tags": "Tags",
"CmsKit:0002": "Content already exists!",
"CmsKit:0003": "The entity {0} is not taggable.",
"CmsKit:Blog:0001": "The given slug ({Slug}) already exists!",
"CmsKit:BlogPost:0001": "The given slug already exists!",
"CmsKit:Comments:0001": "The entity {EntityType} is not commentable.",
"CmsKit:Media:0001": "'{Name}' is not a valid media name.",
"CmsKit:Media:0002": "The entity can't have media.",
"CmsKit:Page:0001": "The given url ({Slug}) already exists. Please try with different url.",
"CmsKit:Rating:0001": "The entity {EntityType} can't be rated.",
"CmsKit:Reaction:0001": "The entity {EntityType} can't have reactions.",
"CmsKit:Tag:0002": "The entity is not taggable!",
"CommentAuthorizationExceptionMessage": "Those comments are not allowed for public display.",
"CommentDeletionConfirmationMessage": "This comment and all replies will be deleted!",
"Comments": "Comments",
"Content": "Content",
"ContentDeletionConfirmationMessage": "Are you sure to delete this content?",
"Contents": "Contents",
"CoverImage": "Cover image",
"CreateBlogPostPage": "New blog post",
"CreationTime": "Creation time",
"Delete": "Delete",
"Detail": "Detail",
"Details": "Details",
"DisplayName": "Display name",
"DoYouPreferAdditionalEmails": "Do you prefer additional emails?",
"Edit": "Edit",
"EndDate": "End date",
"EntityId": "Entity Id",
"EntityType": "Entity type",
"ExportCSV": "Export CSV",
"Features": "Features",
"GenericDeletionConfirmationMessage": "Are you sure to delete '{0}'?",
"IsActive": "Active",
"LastModification": "Last Modification",
"LastModificationTime": "Last Modification Time",
"LoginToAddComment": "Login to add comment",
"LoginToRate": "Login to rate",
"LoginToReact": "Login to react",
"LoginToReply": "Login to reply",
"MainMenu": "Main Menu",
"MakeMainMenu": "Make main menu",
"Menu:CMS": "CMS",
"Menus": "Menus",
"MenuDeletionConfirmationMessage": "The menu '{0}' will be deleted. Are you sure?",
"MenuItemDeletionConfirmationMessage": "Are sure to delete this menu item?",
"MenuItemMoveConfirmMessage": "Are you sure you want to move '{0}' under '{1}'?",
"MenuItems": "Menu items",
"Message": "Message",
"MessageDeletionConfirmationMessage": "This comment will be deleted completely.",
"NewBlog": "New blog",
"NewBlogPost": "New blog post",
"NewMenu": "New menu",
"NewMenuItem": "New root menu item",
"NewPage": "New page",
"NewTag": "New tag",
"NoMenuItems": "There is no menu item yet!",
"OK": "OK",
"PageDeletionConfirmationMessage": "Are you sure to delete this page?",
"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",
"Permission:BlogManagement.Features": "Features",
"Permission:BlogManagement.Update": "Update",
"Permission:BlogPostManagement": "Blog post management",
"Permission:BlogPostManagement.Create": "Create",
"Permission:BlogPostManagement.Delete": "Delete",
"Permission:BlogPostManagement.Update": "Update",
"Permission:BlogPostManagement.Publish": "Publish",
"Permission:CmsKit": "CmsKit admin",
"Permission:Comments": "Comment management",
"Permission:Comments.Delete": "Delete",
"Permission:Contents": "Content management",
"Permission:Contents.Create": "Create content",
"Permission:Contents.Delete": "Delete content",
"Permission:Contents.Update": "Update content",
"Permission:MediaDescriptorManagement": "Media management",
"Permission:MediaDescriptorManagement:Create": "Create",
"Permission:MediaDescriptorManagement:Delete": "Delete",
"Permission:MenuItemManagement": "Menu item management",
"Permission:MenuItemManagement.Create": "Create",
"Permission:MenuItemManagement.Delete": "Delete",
"Permission:MenuItemManagement.Update": "Update",
"Permission:MenuManagement": "Menu management",
"Permission:MenuManagement.Create": "Create",
"Permission:MenuManagement.Delete": "Delete",
"Permission:MenuManagement.Update": "Update",
"Permission:Menus": "Menu management",
"Permission:Menus.Create": "Create",
"Permission:Menus.Delete": "Delete",
"Permission:Menus.Update": "Update",
"Permission:PageManagement": "Page management",
"Permission:PageManagement:Create": "Create",
"Permission:PageManagement:Delete": "Delete",
"Permission:PageManagement:Update": "Update",
"Permission:PageManagement:SetAsHomePage": "Set as home page",
"Permission:TagManagement": "Tag management",
"Permission:TagManagement.Create": "Create",
"Permission:TagManagement.Delete": "Delete",
"Permission:TagManagement.Update": "Update",
"Permission:GlobalResources": "Global resources",
"Permission:CmsKitPublic": "CmsKit public",
"Permission:Comments.DeleteAll": "Delete all",
"PickYourReaction": "Pick your reaction",
"Rating": "Rating",
"RatingUndoMessage": "Your rating will be undo.",
"Reactions": "Reactions",
"Read": "Read",
"RepliesToThisComment": "Replies to this comment",
"Reply": "Reply",
"ReplyTo": "Reply to",
"SamplePageMessage": "A sample page for the Pro module",
"SaveChanges": "Save changes",
"Script": "Script",
"SelectAll": "Select all",
"Send": "Send",
"SendMessage": "Send Message",
"SelectedAuthor": "Author",
"ShortDescription": "Short description",
"Slug": "Slug",
"Source": "Source",
"SourceUrl": "Source Url",
"Star": "Star",
"StartDate": "Start Date",
"Style": "Style",
"Subject": "Subject",
"SubjectPlaceholder": "Please type a subject",
"Submit": "Submit",
"Subscribe": "Subscribe",
"SavedSuccessfully": "Saved successfully!",
"TagDeletionConfirmationMessage": "Are you sure to delete '{0}' tag?",
"Tags": "Tags",
"Text": "Text",
"ThankYou": "Thank you",
"Title": "Title",
"Undo": "Undo",
"Update": "Update",
"UpdatePreferenceSuccessMessage": "Your preferences have been saved.",
"UpdateYourEmailPreferences": "Update your email preferences",
"UnMakeMainMenu": "Unmake Main Menu",
"UploadFailedMessage": "Upload failed.",
"UserId": "User Id",
"Username": "Username",
"YourComment": "Your comment",
"YourEmailAddress": "Your e-mail address",
"YourFullName": "Your full name",
"YourMessage": "Your Message",
"YourReply": "Your reply",
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> supported.",
"GlobalResources": "Global resources",
"CmsKit.BlogPost.Status.0": "Draft",
"CmsKit.BlogPost.Status.1": "Published",
"CmsKit.BlogPost.Status.2": "Waiting for review",
"BlogPostPublishConfirmationMessage": "Are you sure to publish the blog post \"{0}\"?",
"SuccessfullyPublished": "Successfully published!",
"Draft": "Draft",
"Publish": "Publish",
"BlogPostDraftConfirmationMessage": "Are you sure to set the blog post \"{0}\" as draft?",
"BlogPostSendToReviewConfirmationMessage": "Are you sure to send the blog post \"{0}\" to admin review for publishing?",
"SaveAsDraft": "Save as draft",
"SendToReview": "Send to review",
"SendToReviewToPublish": "Send to review to publish",
"BlogPostSendToReviewSuccessMessage": "The blog post \"{0}\" has been sent to admin review for publishing.",
"HasBlogPostWaitingForReviewMessage": "You have a blog post waiting for review. Click to list.",
"SelectAStatus": "Select a status",
"Status": "Status",
"CmsKit.BlogPost.ScrollIndex": "Quick navigation bar in blog posts",
"CmsKit.BlogPost.PreventXssFeature": "Prevent XSS",
"Add": "Add",
"AddWidget": "Add Widget",
"PleaseConfigureWidgets": "Please configure widgets",
"SelectAnAuthor": "Select an Author",
"InThisDocument": "In This Document",
"GoToTop": "Go To Top",
"SetAsHomePage": "Change Home Page Status",
"CompletedSettingAsHomePage": "Set as home page",
"IsHomePage": "Is Home Page",
"RemovedSettingAsHomePage": "Removed setting the home page",
"Feature:CmsKitGroup": "Cms kit",
"Feature:BlogEnable": "Blogpost",
"Feature:BlogEnableDescription": "CMS Kit's blogpost system that allows create blogs and posts dynamically in the application.",
"Feature:CommentEnable": "Commenting",
"Feature:CommentEnableDescription": "CMS Kit's comment system allows commenting on entities such as BlogPost.",
"Feature:GlobalResourceEnable": "Global resourcing",
"Feature:GlobalResourceEnableDescription": "CMS Kit's global resoruces feature that allows managing global styles & scripts.",
"Feature:MenuEnable": "Menu",
"Feature:MenuEnableDescription": "CMS Kit's dynamic menu system that allows adding/removing application menus dynamically.",
"Feature:PageEnable": "Paging",
"Feature:PageEnableDescription": "CMS Kit's page system that allows creating static pages with specific URL.",
"Feature:RatingEnable": "Rating",
"Feature:RatingEnableDescription": "CMS Kit's rating system that allows users to rate entities such as BlogPost.",
"Feature:ReactionEnable": "Reaction",
"Feature:ReactionEnableDescription": "CMS Kit's reaction system that allows users to send reactions to entities such as BlogPost, Comments, etc.",
"Feature:TagEnable": "Taging",
"Feature:TagEnableDescription": "CMS Kit's tag system that allows tagging entities such as BlogPost.",
"DeleteBlogPostMessage": "The blog will be deleted. Are you sure?",
"CaptchaCode": "Captcha code",
"CommentTextRequired": "Comment is required",
"CaptchaCodeErrorMessage": "The answer you entered for the CAPTCHA was not correct. Please try again",
"CaptchaCodeMissingMessage": "The captcha code is missing!",
"UnAllowedExternalUrlMessage": "You included an unallowed external URL. Please try again without the external URL.",
"URL": "URL",
"PopularTags": "Popular Tags",
"RemoveCoverImageConfirmationMessage": "Are you sure you want to remove the cover image?",
"RemoveCoverImage": "Remove cover image",
"CssClass": "CSS Class",
"TagsHelpText": "Tags should be comma-separated (e.g.: tag1, tag2, tag3)",
"ThisPartOfContentCouldntBeLoaded": "This part of content couldn't be loaded.",
"DuplicateCommentAttemptMessage": "Duplicate comment post attempt detected. Your comment has already been submitted.",
"NoBlogPostYet": "No blog post yet!",
"CmsKit:Comment": "Comment",
"CmsKitCommentOptions:RequireApprovement": "Require approval for comments",
"CmsKitCommentOptions:RequireApprovementDescription": "When enabled, comments will require approval before being published.",
"CommentFilter:ApproveState":"Approve State",
"ApproveState": "Approve State",
"CommentFilter:0":"All",
"CommentFilter:1":"Approved",
"CommentFilter:2":"Disapproved",
"CommentFilter:4":"Waiting",
"ApprovedSuccessfully":"Approved Successfully",
"ApprovalRevokedSuccessfully":"Approval Revoked Successfully",
"Approve":"Approve",
"Disapproved":"Disapproved",
"CommentAlertMessage":"There are {0} comments waiting for approval",
"Settings:Menu:CmsKit":"CMS",
"CommentsAwaitingApproval":"Comments Awaiting Approval",
"CommentSubmittedForApproval": "Your comment has been submitted for approval.",
}
"texts": {
"AddSubMenuItem": "Add Sub Menu Item",
"AreYouSure": "Are You Sure?",
"BlogDeletionConfirmationMessage": "The blog '{0}' will be deleted. Are you sure?",
"BlogFeatureNotAvailable": "This feature is not available now. Enable with 'GlobalFeatureManager' to use it.",
"BlogId": "Blog",
"BlogPostDeletionConfirmationMessage": "The blog post '{0}' will be deleted. Are you sure?",
"BlogPosts": "Blog posts",
"Blogs": "Blogs",
"ChoosePreference": "Choose Preference...",
"Cms": "CMS",
"CmsKit.Comments": "Comments",
"CmsKit.Ratings": "Ratings",
"CmsKit.Reactions": "Reactions",
"CmsKit.Tags": "Tags",
"CmsKit:0002": "Content already exists!",
"CmsKit:0003": "The entity {0} is not taggable.",
"CmsKit:Blog:0001": "The given slug ({Slug}) already exists!",
"CmsKit:BlogPost:0001": "The given slug already exists!",
"CmsKit:Comments:0001": "The entity {EntityType} is not commentable.",
"CmsKit:Media:0001": "'{Name}' is not a valid media name.",
"CmsKit:Media:0002": "The entity can't have media.",
"CmsKit:Page:0001": "The given url ({Slug}) already exists. Please try with different url.",
"CmsKit:Rating:0001": "The entity {EntityType} can't be rated.",
"CmsKit:Reaction:0001": "The entity {EntityType} can't have reactions.",
"CmsKit:Tag:0002": "The entity is not taggable!",
"CmsKit:MarkedItem:ToggleConfirmation": "Are you sure you want to toggle the marked item?",
"CommentAuthorizationExceptionMessage": "Those comments are not allowed for public display.",
"CmsKit:Modals:Login": "Login",
"CmsKit:Modals:LoginModalDefaultMessage": "Please login to continue!",
"CmsKit:Modals:YouAreNotAuthenticated": "This operation is not authorized for you.",
"CommentDeletionConfirmationMessage": "This comment and all replies will be deleted!",
"CmsKit:MarkedItem:0001": "The entity {EntityType} can't be marked.",
"CmsKit:MarkedItem:LoginMessage": "Please login to mark this item.",
"Comments": "Comments",
"Content": "Content",
"ContentDeletionConfirmationMessage": "Are you sure to delete this content?",
"Contents": "Contents",
"CoverImage": "Cover image",
"CreateBlogPostPage": "New blog post",
"CreationTime": "Creation time",
"Delete": "Delete",
"Detail": "Detail",
"Details": "Details",
"DisplayName": "Display name",
"DoYouPreferAdditionalEmails": "Do you prefer additional emails?",
"Edit": "Edit",
"EndDate": "End date",
"EntityId": "Entity Id",
"EntityType": "Entity type",
"ExportCSV": "Export CSV",
"Features": "Features",
"GenericDeletionConfirmationMessage": "Are you sure to delete '{0}'?",
"IsActive": "Active",
"LastModification": "Last Modification",
"LastModificationTime": "Last Modification Time",
"LoginToAddComment": "Login to add comment",
"LoginToRate": "Login to rate",
"LoginToReact": "Login to react",
"LoginToReply": "Login to reply",
"MainMenu": "Main Menu",
"MakeMainMenu": "Make main menu",
"Menu:CMS": "CMS",
"Menus": "Menus",
"MenuDeletionConfirmationMessage": "The menu '{0}' will be deleted. Are you sure?",
"MenuItemDeletionConfirmationMessage": "Are sure to delete this menu item?",
"MenuItemMoveConfirmMessage": "Are you sure you want to move '{0}' under '{1}'?",
"MenuItems": "Menu items",
"Message": "Message",
"MessageDeletionConfirmationMessage": "This comment will be deleted completely.",
"NewBlog": "New blog",
"NewBlogPost": "New blog post",
"NewMenu": "New menu",
"NewMenuItem": "New root menu item",
"NewPage": "New page",
"NewTag": "New tag",
"NoMenuItems": "There is no menu item yet!",
"OK": "OK",
"PageDeletionConfirmationMessage": "Are you sure to delete this page?",
"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",
"Permission:BlogManagement.Features": "Features",
"Permission:BlogManagement.Update": "Update",
"Permission:BlogPostManagement": "Blog post management",
"Permission:BlogPostManagement.Create": "Create",
"Permission:BlogPostManagement.Delete": "Delete",
"Permission:BlogPostManagement.Update": "Update",
"Permission:BlogPostManagement.Publish": "Publish",
"Permission:CmsKit": "CmsKit admin",
"Permission:Comments": "Comment management",
"Permission:Comments.Delete": "Delete",
"Permission:Contents": "Content management",
"Permission:Contents.Create": "Create content",
"Permission:Contents.Delete": "Delete content",
"Permission:Contents.Update": "Update content",
"Permission:MediaDescriptorManagement": "Media management",
"Permission:MediaDescriptorManagement:Create": "Create",
"Permission:MediaDescriptorManagement:Delete": "Delete",
"Permission:MenuItemManagement": "Menu item management",
"Permission:MenuItemManagement.Create": "Create",
"Permission:MenuItemManagement.Delete": "Delete",
"Permission:MenuItemManagement.Update": "Update",
"Permission:MenuManagement": "Menu management",
"Permission:MenuManagement.Create": "Create",
"Permission:MenuManagement.Delete": "Delete",
"Permission:MenuManagement.Update": "Update",
"Permission:Menus": "Menu management",
"Permission:Menus.Create": "Create",
"Permission:Menus.Delete": "Delete",
"Permission:Menus.Update": "Update",
"Permission:PageManagement": "Page management",
"Permission:PageManagement:Create": "Create",
"Permission:PageManagement:Delete": "Delete",
"Permission:PageManagement:Update": "Update",
"Permission:PageManagement:SetAsHomePage": "Set as home page",
"Permission:TagManagement": "Tag management",
"Permission:TagManagement.Create": "Create",
"Permission:TagManagement.Delete": "Delete",
"Permission:TagManagement.Update": "Update",
"Permission:GlobalResources": "Global resources",
"Permission:CmsKitPublic": "CmsKit public",
"Permission:Comments.DeleteAll": "Delete all",
"PickYourReaction": "Pick your reaction",
"Rating": "Rating",
"RatingUndoMessage": "Your rating will be undo.",
"Reactions": "Reactions",
"Read": "Read",
"RepliesToThisComment": "Replies to this comment",
"Reply": "Reply",
"ReplyTo": "Reply to",
"SamplePageMessage": "A sample page for the Pro module",
"SaveChanges": "Save changes",
"Script": "Script",
"SelectAll": "Select all",
"Send": "Send",
"SendMessage": "Send Message",
"SelectedAuthor": "Author",
"ShortDescription": "Short description",
"Slug": "Slug",
"Source": "Source",
"SourceUrl": "Source Url",
"Star": "Star",
"StartDate": "Start Date",
"Style": "Style",
"Subject": "Subject",
"SubjectPlaceholder": "Please type a subject",
"Submit": "Submit",
"Subscribe": "Subscribe",
"SavedSuccessfully": "Saved successfully!",
"TagDeletionConfirmationMessage": "Are you sure to delete '{0}' tag?",
"Tags": "Tags",
"Text": "Text",
"ThankYou": "Thank you",
"Title": "Title",
"Undo": "Undo",
"Update": "Update",
"UpdatePreferenceSuccessMessage": "Your preferences have been saved.",
"UpdateYourEmailPreferences": "Update your email preferences",
"UnMakeMainMenu": "Unmake Main Menu",
"UploadFailedMessage": "Upload failed.",
"UserId": "User Id",
"Username": "Username",
"YourComment": "Your comment",
"YourEmailAddress": "Your e-mail address",
"YourFullName": "Your full name",
"YourMessage": "Your Message",
"YourReply": "Your reply",
"MarkdownSupported": "<a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a> supported.",
"GlobalResources": "Global resources",
"CmsKit.BlogPost.Status.0": "Draft",
"CmsKit.BlogPost.Status.1": "Published",
"CmsKit.BlogPost.Status.2": "Waiting for review",
"BlogPostPublishConfirmationMessage": "Are you sure to publish the blog post \"{0}\"?",
"SuccessfullyPublished": "Successfully published!",
"Draft": "Draft",
"Publish": "Publish",
"BlogPostDraftConfirmationMessage": "Are you sure to set the blog post \"{0}\" as draft?",
"BlogPostSendToReviewConfirmationMessage": "Are you sure to send the blog post \"{0}\" to admin review for publishing?",
"SaveAsDraft": "Save as draft",
"SendToReview": "Send to review",
"SendToReviewToPublish": "Send to review to publish",
"BlogPostSendToReviewSuccessMessage": "The blog post \"{0}\" has been sent to admin review for publishing.",
"HasBlogPostWaitingForReviewMessage": "You have a blog post waiting for review. Click to list.",
"SelectAStatus": "Select a status",
"Status": "Status",
"CmsKit.BlogPost.ScrollIndex": "Quick navigation bar in blog posts",
"CmsKit.BlogPost.PreventXssFeature": "Prevent XSS",
"Add": "Add",
"AddWidget": "Add Widget",
"PleaseConfigureWidgets": "Please configure widgets",
"SelectAnAuthor": "Select an Author",
"InThisDocument": "In This Document",
"GoToTop": "Go To Top",
"SetAsHomePage": "Change Home Page Status",
"CompletedSettingAsHomePage": "Set as home page",
"IsHomePage": "Is Home Page",
"RemovedSettingAsHomePage": "Removed setting the home page",
"Feature:CmsKitGroup": "Cms kit",
"Feature:BlogEnable": "Blogpost",
"Feature:BlogEnableDescription": "CMS Kit's blogpost system that allows create blogs and posts dynamically in the application.",
"Feature:CommentEnable": "Commenting",
"Feature:CommentEnableDescription": "CMS Kit's comment system allows commenting on entities such as BlogPost.",
"Feature:GlobalResourceEnable": "Global resourcing",
"Feature:GlobalResourceEnableDescription": "CMS Kit's global resoruces feature that allows managing global styles & scripts.",
"Feature:MenuEnable": "Menu",
"Feature:MenuEnableDescription": "CMS Kit's dynamic menu system that allows adding/removing application menus dynamically.",
"Feature:PageEnable": "Paging",
"Feature:PageEnableDescription": "CMS Kit's page system that allows creating static pages with specific URL.",
"Feature:RatingEnable": "Rating",
"Feature:RatingEnableDescription": "CMS Kit's rating system that allows users to rate entities such as BlogPost.",
"Feature:ReactionEnable": "Reaction",
"Feature:ReactionEnableDescription": "CMS Kit's reaction system that allows users to send reactions to entities such as BlogPost, Comments, etc.",
"Feature:TagEnable": "Taging",
"Feature:TagEnableDescription": "CMS Kit's tag system that allows tagging entities such as BlogPost.",
"Feature:MarkedItemEnable": "Marked Item",
"Feature:MarkedItemEnableDescription": "The CMS Kit's marking system that allows users to mark entities as favorites.",
"DeleteBlogPostMessage": "The blog will be deleted. Are you sure?",
"CaptchaCode": "Captcha code",
"CommentTextRequired": "Comment is required",
"CaptchaCodeErrorMessage": "The answer you entered for the CAPTCHA was not correct. Please try again",
"CaptchaCodeMissingMessage": "The captcha code is missing!",
"UnAllowedExternalUrlMessage": "You included an unallowed external URL. Please try again without the external URL.",
"URL": "URL",
"PopularTags": "Popular Tags",
"RemoveCoverImageConfirmationMessage": "Are you sure you want to remove the cover image?",
"RemoveCoverImage": "Remove cover image",
"CssClass": "CSS Class",
"TagsHelpText": "Tags should be comma-separated (e.g.: tag1, tag2, tag3)",
"ThisPartOfContentCouldntBeLoaded": "This part of content couldn't be loaded.",
"DuplicateCommentAttemptMessage": "Duplicate comment post attempt detected. Your comment has already been submitted.",
"NoBlogPostYet": "No blog post yet!",
"CmsKit:Comment": "Comment",
"CmsKitCommentOptions:RequireApprovement": "Require approval for comments",
"CmsKitCommentOptions:RequireApprovementDescription": "When enabled, comments will require approval before being published.",
"CommentFilter:ApproveState": "Approve State",
"ApproveState": "Approve State",
"CommentFilter:0": "All",
"CommentFilter:1": "Approved",
"CommentFilter:2": "Disapproved",
"CommentFilter:4": "Waiting",
"ApprovedSuccessfully": "Approved Successfully",
"ApprovalRevokedSuccessfully": "Approval Revoked Successfully",
"Approve": "Approve",
"Disapproved": "Disapproved",
"CommentAlertMessage": "There are {0} comments waiting for approval",
"Settings:Menu:CmsKit": "CMS",
"CommentsAwaitingApproval": "Comments Awaiting Approval",
"CommentSubmittedForApproval": "Your comment has been submitted for approval."
}
}

9
modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/MarkedItems/StandardMarkedItems.cs

@ -0,0 +1,9 @@
namespace Volo.CmsKit.MarkedItems;
public static class StandardMarkedItems
{
public const string Favorite = "_FA";
public const string Flagged = "_FL";
public const string Bookmark = "_BO";
public const string Starred = "_ST";
}

9
modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/MarkedItems/UserMarkedItemConsts.cs

@ -0,0 +1,9 @@
using Volo.CmsKit.Entities;
namespace Volo.CmsKit.MarkedItems;
public static class UserMarkedItemConsts
{
public static int MaxEntityTypeLength { get; set; } = CmsEntityConsts.MaxEntityTypeLength;
public static int MaxEntityIdLength { get; set; } = CmsEntityConsts.MaxEntityIdLength;
}

10
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/MarkedItems/CmsKitMarkedItemOptions.cs

@ -0,0 +1,10 @@
using JetBrains.Annotations;
using System.Collections.Generic;
namespace Volo.CmsKit.MarkedItems;
public class CmsKitMarkedItemOptions
{
[NotNull]
public List<MarkedItemEntityTypeDefinition> EntityTypes { get; } = new();
}

36
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/MarkedItems/DefaultMarkedItemDefinitionStore.cs

@ -0,0 +1,36 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.Extensions.Options;
using Volo.Abp;
namespace Volo.CmsKit.MarkedItems;
public class DefaultMarkedItemDefinitionStore : IMarkedItemDefinitionStore
{
protected CmsKitMarkedItemOptions Options { get; }
public DefaultMarkedItemDefinitionStore(IOptions<CmsKitMarkedItemOptions> options)
{
Options = options.Value;
}
public virtual Task<bool> IsDefinedAsync([NotNull] string entityType)
{
Check.NotNullOrWhiteSpace(entityType, nameof(entityType));
var isDefined = Options.EntityTypes.Any(x => x.EntityType.Equals(entityType, StringComparison.InvariantCultureIgnoreCase));
return Task.FromResult(isDefined);
}
public virtual Task<MarkedItemEntityTypeDefinition> GetAsync([NotNull] string entityType)
{
Check.NotNullOrWhiteSpace(entityType, nameof(entityType));
var definition = Options.EntityTypes.SingleOrDefault(x => x.EntityType.Equals(entityType, StringComparison.InvariantCultureIgnoreCase));
return Task.FromResult(definition);
}
}

16
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/MarkedItems/EntityCannotBeMarkedException.cs

@ -0,0 +1,16 @@
using JetBrains.Annotations;
using Volo.Abp;
namespace Volo.CmsKit.MarkedItems;
public class EntityCannotBeMarkedException : BusinessException
{
public EntityCannotBeMarkedException([NotNull] string entityType)
{
EntityType = Check.NotNullOrEmpty(entityType, nameof(entityType));
Code = CmsKitErrorCodes.MarkedItems.EntityCannotBeMarked;
WithData(nameof(EntityType), EntityType);
}
public string EntityType { get; }
}

8
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/MarkedItems/IMarkedItemDefinitionStore.cs

@ -0,0 +1,8 @@
using System.Threading.Tasks;
using JetBrains.Annotations;
namespace Volo.CmsKit.MarkedItems;
public interface IMarkedItemDefinitionStore : IEntityTypeDefinitionStore<MarkedItemEntityTypeDefinition>
{
}

31
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/MarkedItems/IUserMarkedItemRepository.cs

@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Volo.Abp.Domain.Repositories;
namespace Volo.CmsKit.MarkedItems;
public interface IUserMarkedItemRepository : IBasicRepository<UserMarkedItem, Guid>
{
Task<UserMarkedItem> FindAsync(
Guid userId,
[NotNull] string entityType,
[NotNull] string entityId,
CancellationToken cancellationToken = default
);
Task<List<UserMarkedItem>> GetListForUserAsync(
Guid userId,
[NotNull] string entityType,
CancellationToken cancellationToken = default
);
Task<IQueryable<UserMarkedItem>> GetQueryForUserAsync(
[NotNull] string entityType,
[NotNull] Guid userId,
CancellationToken cancellationToken = default
);
}

16
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/MarkedItems/MarkedItemEntityTypeDefinition.cs

@ -0,0 +1,16 @@
using JetBrains.Annotations;
using Volo.Abp;
namespace Volo.CmsKit.MarkedItems;
public class MarkedItemEntityTypeDefinition : EntityTypeDefinition
{
public string IconName { get; set; }
public MarkedItemEntityTypeDefinition(
[NotNull] string entityType,
[NotNull] string iconName) : base(entityType)
{
Check.NotNull(iconName, nameof(iconName));
IconName = iconName;
}
}

58
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/MarkedItems/MarkedItemManager.cs

@ -0,0 +1,58 @@
using System;
using JetBrains.Annotations;
using System.Threading.Tasks;
using Volo.Abp;
namespace Volo.CmsKit.MarkedItems;
public class MarkedItemManager : CmsKitDomainServiceBase
{
IMarkedItemDefinitionStore MarkedItemDefinitionStore { get; set; }
IUserMarkedItemRepository UserMarkedItemRepository { get; set; }
public MarkedItemManager(
IUserMarkedItemRepository userMarkedItemRepository,
IMarkedItemDefinitionStore markedItemDefinitionStore)
{
UserMarkedItemRepository = userMarkedItemRepository;
MarkedItemDefinitionStore = markedItemDefinitionStore;
}
public virtual async Task<bool> ToggleAsync(
Guid creatorId,
[NotNull] string entityType,
[NotNull] string entityId)
{
Check.NotNullOrWhiteSpace(entityType, nameof(entityType));
Check.NotNullOrWhiteSpace(entityId, nameof(entityId));
var markedItem = await UserMarkedItemRepository.FindAsync(creatorId, entityType, entityId);
if (markedItem != null)
{
await UserMarkedItemRepository.DeleteAsync(markedItem);
return false;
}
if (!await MarkedItemDefinitionStore.IsDefinedAsync(entityType))
{
throw new EntityCannotBeMarkedException(entityType);
}
await UserMarkedItemRepository.InsertAsync(
new UserMarkedItem(
GuidGenerator.Create(),
entityType,
entityId,
creatorId,
CurrentTenant.Id
)
);
return true;
}
public virtual async Task<MarkedItemEntityTypeDefinition> GetAsync(
[NotNull] string entityType)
{
Check.NotNullOrWhiteSpace(entityType, nameof(entityType));
return await MarkedItemDefinitionStore.GetAsync(entityType);
}
}

36
modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/MarkedItems/UserMarkedItem.cs

@ -0,0 +1,36 @@
using System;
using Volo.Abp;
using Volo.Abp.Auditing;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
using Volo.Abp.MultiTenancy;
namespace Volo.CmsKit.MarkedItems;
public class UserMarkedItem : BasicAggregateRoot<Guid>, IHasCreationTime, IMustHaveCreator, IMultiTenant
{
public virtual Guid? TenantId { get; protected set; }
public virtual Guid CreatorId { get; set; }
public virtual DateTime CreationTime { get; set; }
public string EntityId { get; protected set; }
public string EntityType { get; protected set; }
protected UserMarkedItem() { }
internal UserMarkedItem(
Guid id,
[NotNull] string entityType,
[NotNull] string entityId,
Guid creatorId,
Guid? tenantId = null)
: base(id)
{
EntityType = Check.NotNullOrWhiteSpace(entityType, nameof(entityType));
EntityId = Check.NotNullOrWhiteSpace(entityId, nameof(entityId));
CreatorId = creatorId;
TenantId = tenantId;
}
}

2
modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/EntityFrameworkCore/CmsKitDbContext.cs

@ -4,6 +4,7 @@ using Volo.Abp.EntityFrameworkCore;
using Volo.CmsKit.Blogs;
using Volo.CmsKit.Comments;
using Volo.CmsKit.GlobalResources;
using Volo.CmsKit.MarkedItems;
using Volo.CmsKit.MediaDescriptors;
using Volo.CmsKit.Menus;
using Volo.CmsKit.Pages;
@ -30,6 +31,7 @@ public class CmsKitDbContext : AbpDbContext<CmsKitDbContext>, ICmsKitDbContext
public DbSet<MediaDescriptor> MediaDescriptors { get; set; }
public DbSet<MenuItem> MenuItems { get; set; }
public DbSet<GlobalResource> GlobalResources { get; set; }
public DbSet<UserMarkedItem> UserMarkedItems { get; set; }
public CmsKitDbContext(DbContextOptions<CmsKitDbContext> options)
: base(options)

23
modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/EntityFrameworkCore/CmsKitDbContextModelCreatingExtensions.cs

@ -7,6 +7,7 @@ using Volo.CmsKit.Blogs;
using Volo.CmsKit.Comments;
using Volo.CmsKit.GlobalFeatures;
using Volo.CmsKit.GlobalResources;
using Volo.CmsKit.MarkedItems;
using Volo.CmsKit.MediaDescriptors;
using Volo.CmsKit.Menus;
using Volo.CmsKit.Pages;
@ -285,6 +286,28 @@ public static class CmsKitDbContextModelCreatingExtensions
builder.Ignore<GlobalResource>();
}
if (GlobalFeatureManager.Instance.IsEnabled<MarkedItemsFeature>())
{
builder.Entity<UserMarkedItem>(b =>
{
b.ToTable(AbpCmsKitDbProperties.DbTablePrefix + "UserMarkedItems", AbpCmsKitDbProperties.DbSchema);
b.ConfigureByConvention();
b.Property(x => x.EntityType).IsRequired();
b.Property(x => x.EntityId).IsRequired();
b.HasIndex(x => new { x.TenantId, x.EntityType, x.EntityId });
b.HasIndex(x => new { x.TenantId, x.CreatorId, x.EntityType, x.EntityId });
b.ApplyObjectExtensionMappings();
});
}
else
{
builder.Ignore<UserMarkedItem>();
}
builder.TryConfigureObjectExtensions<CmsKitDbContext>();
}
}

2
modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/EntityFrameworkCore/CmsKitEntityFrameworkCoreModule.cs

@ -11,6 +11,7 @@ using Volo.CmsKit.Ratings;
using Volo.CmsKit.Reactions;
using Volo.CmsKit.Tags;
using Volo.CmsKit.Users;
using Volo.CmsKit.MarkedItems;
namespace Volo.CmsKit.EntityFrameworkCore;
@ -37,6 +38,7 @@ public class CmsKitEntityFrameworkCoreModule : AbpModule
options.AddRepository<BlogFeature, EfCoreBlogFeatureRepository>();
options.AddRepository<MediaDescriptor, EfCoreMediaDescriptorRepository>();
options.AddRepository<GlobalResource, EfCoreGlobalResourceRepository>();
options.AddRepository<UserMarkedItem, EfCoreUserMarkedItemRepository>();
});
}
}

2
modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/EntityFrameworkCore/ICmsKitDbContext.cs

@ -4,6 +4,7 @@ using Volo.Abp.EntityFrameworkCore;
using Volo.CmsKit.Blogs;
using Volo.CmsKit.Comments;
using Volo.CmsKit.GlobalResources;
using Volo.CmsKit.MarkedItems;
using Volo.CmsKit.MediaDescriptors;
using Volo.CmsKit.Menus;
using Volo.CmsKit.Pages;
@ -30,4 +31,5 @@ public interface ICmsKitDbContext : IEfCoreDbContext
DbSet<MediaDescriptor> MediaDescriptors { get; }
DbSet<MenuItem> MenuItems { get; }
DbSet<GlobalResource> GlobalResources { get; }
DbSet<UserMarkedItem> UserMarkedItems { get; }
}

67
modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/MarkedItems/EfCoreUserMarkedItemRepository.cs

@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore;
using Volo.Abp;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
using Volo.CmsKit.EntityFrameworkCore;
namespace Volo.CmsKit.MarkedItems;
public class EfCoreUserMarkedItemRepository : EfCoreRepository<ICmsKitDbContext, UserMarkedItem, Guid>, IUserMarkedItemRepository
{
public EfCoreUserMarkedItemRepository(IDbContextProvider<ICmsKitDbContext> dbContextProvider) : base(dbContextProvider)
{
}
public async Task<UserMarkedItem> FindAsync(Guid userId, [NotNull] string entityType, [NotNull] string entityId, CancellationToken cancellationToken = default)
{
Check.NotNull(userId, nameof(userId));
Check.NotNullOrWhiteSpace(entityType, nameof(entityType));
Check.NotNull(entityId, nameof(entityId));
var entity = await(await GetDbSetAsync())
.Where(x =>
x.CreatorId == userId &&
x.EntityType == entityType &&
x.EntityId == entityId)
.FirstOrDefaultAsync(GetCancellationToken(cancellationToken));
return entity;
}
public async Task<List<UserMarkedItem>> GetListForUserAsync(Guid userId, [NotNull] string entityType, CancellationToken cancellationToken = default)
{
Check.NotNull(userId, nameof(userId));
Check.NotNullOrWhiteSpace(entityType, nameof(entityType));
return await(await GetDbSetAsync())
.Where(x =>
x.CreatorId == userId &&
x.EntityType == entityType)
.ToListAsync(GetCancellationToken(cancellationToken));
}
/// <summary>
/// Retrieves an IQueryable representing the user's marked items based on the specified entity type and user ID.
/// </summary>
/// <param name="entityType">The type of entity to filter by.</param>
/// <param name="userId">The ID of the user whose marked items are being retrieved.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>An IQueryable representing the user's marked items filtered by the specified entity type and user ID.</returns>
public async Task<IQueryable<UserMarkedItem>> GetQueryForUserAsync([NotNull] string entityType, [NotNull] Guid userId, CancellationToken cancellationToken = default)
{
Check.NotNullOrWhiteSpace(entityType, nameof(entityType));
Check.NotNull(userId, nameof(userId));
var dbSet = await GetDbSetAsync();
var query = dbSet
.Where(x => x.EntityType == entityType && x.CreatorId == userId);
return query;
}
}

3
modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/CmsKitMongoDbContext.cs

@ -4,6 +4,7 @@ using Volo.Abp.MongoDB;
using Volo.CmsKit.Blogs;
using Volo.CmsKit.Comments;
using Volo.CmsKit.GlobalResources;
using Volo.CmsKit.MarkedItems;
using Volo.CmsKit.MediaDescriptors;
using Volo.CmsKit.Menus;
using Volo.CmsKit.Pages;
@ -44,6 +45,8 @@ public class CmsKitMongoDbContext : AbpMongoDbContext, ICmsKitMongoDbContext
public IMongoCollection<GlobalResource> GlobalResources => Collection<GlobalResource>();
public IMongoCollection<UserMarkedItem> UserMarkedItems => Collection<UserMarkedItem>();
protected override void CreateModel(IMongoModelBuilder modelBuilder)
{
base.CreateModel(modelBuilder);

6
modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/CmsKitMongoDbContextExtensions.cs

@ -3,6 +3,7 @@ using Volo.Abp.MongoDB;
using Volo.CmsKit.Blogs;
using Volo.CmsKit.Comments;
using Volo.CmsKit.GlobalResources;
using Volo.CmsKit.MarkedItems;
using Volo.CmsKit.MediaDescriptors;
using Volo.CmsKit.Menus;
using Volo.CmsKit.Pages;
@ -84,5 +85,10 @@ public static class CmsKitMongoDbContextExtensions
{
x.CollectionName = AbpCmsKitDbProperties.DbTablePrefix + "GlobalResources";
});
builder.Entity<UserMarkedItem>(x =>
{
x.CollectionName = AbpCmsKitDbProperties.DbTablePrefix + "UserMarkedItems";
});
}
}

3
modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/CmsKitMongoDbModule.cs

@ -5,11 +5,13 @@ using Volo.Abp.Users.MongoDB;
using Volo.CmsKit.Blogs;
using Volo.CmsKit.Comments;
using Volo.CmsKit.GlobalResources;
using Volo.CmsKit.MarkedItems;
using Volo.CmsKit.MediaDescriptors;
using Volo.CmsKit.Menus;
using Volo.CmsKit.MongoDB.Blogs;
using Volo.CmsKit.MongoDB.Comments;
using Volo.CmsKit.MongoDB.GlobalResources;
using Volo.CmsKit.MongoDB.MarkedItems;
using Volo.CmsKit.MongoDB.MediaDescriptors;
using Volo.CmsKit.MongoDB.Menus;
using Volo.CmsKit.MongoDB.Pages;
@ -48,6 +50,7 @@ public class CmsKitMongoDbModule : AbpModule
options.AddRepository<MediaDescriptor, MongoMediaDescriptorRepository>();
options.AddRepository<MenuItem, MongoMenuItemRepository>();
options.AddRepository<GlobalResource, MongoGlobalResourceRepository>();
options.AddRepository<UserMarkedItem, MongoUserMarkedItemRepository>();
});
}
}

3
modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/ICmsKitMongoDbContext.cs

@ -4,6 +4,7 @@ using Volo.Abp.MongoDB;
using Volo.CmsKit.Blogs;
using Volo.CmsKit.Comments;
using Volo.CmsKit.GlobalResources;
using Volo.CmsKit.MarkedItems;
using Volo.CmsKit.MediaDescriptors;
using Volo.CmsKit.Menus;
using Volo.CmsKit.Pages;
@ -43,4 +44,6 @@ public interface ICmsKitMongoDbContext : IAbpMongoDbContext
IMongoCollection<MenuItem> MenuItems { get; }
IMongoCollection<GlobalResource> GlobalResources { get; }
IMongoCollection<UserMarkedItem> UserMarkedItems { get; }
}

67
modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/MarkedItems/MongoUserMarkedItemRepository.cs

@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using JetBrains.Annotations;
using Volo.Abp;
using Volo.Abp.Domain.Repositories.MongoDB;
using Volo.Abp.MongoDB;
using Volo.CmsKit.MarkedItems;
namespace Volo.CmsKit.MongoDB.MarkedItems;
public class MongoUserMarkedItemRepository : MongoDbRepository<ICmsKitMongoDbContext, UserMarkedItem, Guid>, IUserMarkedItemRepository
{
public MongoUserMarkedItemRepository(IMongoDbContextProvider<ICmsKitMongoDbContext> dbContextProvider) : base(dbContextProvider)
{
}
public virtual async Task<UserMarkedItem> FindAsync(Guid userId, [NotNull] string entityType, [NotNull] string entityId, CancellationToken cancellationToken = default)
{
Check.NotNull(userId, nameof(userId));
Check.NotNullOrWhiteSpace(entityType, nameof(entityType));
Check.NotNull(entityId, nameof(entityId));
var entity = await (await GetMongoQueryableAsync(cancellationToken))
.Where(x =>
x.CreatorId == userId &&
x.EntityType == entityType &&
x.EntityId == entityId)
.FirstOrDefaultAsync(GetCancellationToken(cancellationToken));
return entity;
}
public virtual async Task<List<UserMarkedItem>> GetListForUserAsync(Guid userId, [NotNull] string entityType, CancellationToken cancellationToken = default)
{
Check.NotNull(userId, nameof(userId));
Check.NotNullOrWhiteSpace(entityType, nameof(entityType));
return await(await GetMongoQueryableAsync(cancellationToken))
.Where(x =>
x.CreatorId == userId &&
x.EntityType == entityType)
.ToListAsync(GetCancellationToken(cancellationToken));
}
/// <summary>
/// Retrieves an IQueryable representing the user's marked items based on the specified entity type and user ID.
/// </summary>
/// <param name="entityType">The type of entity to filter by.</param>
/// <param name="userId">The ID of the user whose marked items are being retrieved.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>An IQueryable representing the user's marked items filtered by the specified entity type and user ID.</returns>
public virtual async Task<IQueryable<UserMarkedItem>> GetQueryForUserAsync([NotNull] string entityType, [NotNull] Guid userId, CancellationToken cancellationToken = default)
{
Check.NotNullOrWhiteSpace(entityType, nameof(entityType));
Check.NotNull(userId, nameof(userId));
var queryable = await GetMongoQueryableAsync(cancellationToken);
var query = queryable
.Where(x => x.EntityType == entityType && x.CreatorId == userId);
return query;
}
}

10
modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/MarkedItems/IMarkedItemPublicAppService.cs

@ -0,0 +1,10 @@
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
namespace Volo.CmsKit.Public.MarkedItems;
public interface IMarkedItemPublicAppService : IApplicationService
{
Task<MarkedItemWithToggleDto> GetForToggleAsync(string entityType, string entityId);
Task<bool> ToggleAsync(string entityType, string entityId);
}

11
modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/MarkedItems/MarkedItemDto.cs

@ -0,0 +1,11 @@
using System;
using JetBrains.Annotations;
namespace Volo.CmsKit.Public.MarkedItems;
[Serializable]
public class MarkedItemDto
{
[NotNull]
public string IconName { get; set; }
}

11
modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/MarkedItems/MarkedItemWithToggleDto.cs

@ -0,0 +1,11 @@
using System;
namespace Volo.CmsKit.Public.MarkedItems;
[Serializable]
public class MarkedItemWithToggleDto
{
public MarkedItemDto MarkedItem { get; set; }
public bool IsMarkedByCurrentUser { get; set; }
}

69
modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/MarkedItems/MarkedItemPublicAppService.cs

@ -0,0 +1,69 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp.Application.Dtos;
using Volo.Abp.GlobalFeatures;
using Volo.Abp.Users;
using Volo.CmsKit.GlobalFeatures;
using Volo.CmsKit.MarkedItems;
namespace Volo.CmsKit.Public.MarkedItems;
[RequiresGlobalFeature(typeof(MarkedItemsFeature))]
public class MarkedItemPublicAppService : CmsKitPublicAppServiceBase, IMarkedItemPublicAppService
{
public IMarkedItemDefinitionStore MarkedItemDefinitionStore { get; }
public IUserMarkedItemRepository UserMarkedItemRepository { get; }
public MarkedItemManager MarkedItemManager { get; }
public MarkedItemPublicAppService(
IMarkedItemDefinitionStore markedItemDefinitionStore,
IUserMarkedItemRepository userMarkedItemRepository,
MarkedItemManager markedItemManager)
{
MarkedItemDefinitionStore = markedItemDefinitionStore;
UserMarkedItemRepository = userMarkedItemRepository;
MarkedItemManager = markedItemManager;
}
[AllowAnonymous]
public virtual async Task<MarkedItemWithToggleDto> GetForToggleAsync(string entityType, string entityId)
{
var markedItem = await MarkedItemManager.GetAsync(entityType);
var userMarkedItem = CurrentUser.IsAuthenticated
? (await UserMarkedItemRepository
.FindAsync(
CurrentUser.GetId(),
entityType,
entityId
))
: null;
return new MarkedItemWithToggleDto
{
MarkedItem = ConvertToMarkedItemDto(markedItem),
IsMarkedByCurrentUser = userMarkedItem != null
};
}
[Authorize]
public virtual async Task<bool> ToggleAsync(string entityType, string entityId)
{
return await MarkedItemManager.ToggleAsync(
CurrentUser.GetId(),
entityType,
entityId
);
}
private MarkedItemDto ConvertToMarkedItemDto(MarkedItemEntityTypeDefinition markedItemEntityTypeDefinition)
{
return new MarkedItemDto
{
IconName = markedItemEntityTypeDefinition.IconName
};
}
}

15
modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Blogs/BlogPostFilteredPagedAndSortedResultRequestDto.cs

@ -0,0 +1,15 @@
// This file is automatically generated by ABP framework to use MVC Controllers from CSharp
using System;
using System.Collections.Generic;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.ObjectExtending;
using Volo.CmsKit.Public.Blogs;
// ReSharper disable once CheckNamespace
namespace Volo.CmsKit.Public.Blogs;
public class BlogPostFilteredPagedAndSortedResultRequestDto : PagedAndSortedResultRequestDto
{
public string Filter { get; set; }
}

17
modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Blogs/BlogPostGetListInput.cs

@ -0,0 +1,17 @@
// This file is automatically generated by ABP framework to use MVC Controllers from CSharp
using System;
using System.Collections.Generic;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.ObjectExtending;
using Volo.CmsKit.Public.Blogs;
// ReSharper disable once CheckNamespace
namespace Volo.CmsKit.Public.Blogs;
public class BlogPostGetListInput : PagedAndSortedResultRequestDto
{
public Guid? AuthorId { get; set; }
public Guid? TagId { get; set; }
}

28
modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Blogs/IBlogPostPublicAppService.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.Application.Services;
using Volo.CmsKit.Contents;
using Volo.CmsKit.Public.Blogs;
using Volo.CmsKit.Users;
// ReSharper disable once CheckNamespace
namespace Volo.CmsKit.Public.Blogs;
public interface IBlogPostPublicAppService : IApplicationService
{
Task<PagedResultDto<BlogPostCommonDto>> GetListAsync(string blogSlug, BlogPostGetListInput input);
Task<BlogPostCommonDto> GetAsync(string blogSlug, string blogPostSlug);
Task<PagedResultDto<CmsUserDto>> GetAuthorsHasBlogPostsAsync(BlogPostFilteredPagedAndSortedResultRequestDto input);
Task<CmsUserDto> GetAuthorHasBlogPostAsync(Guid id);
Task DeleteAsync(Guid id);
Task<string> GetTagNameAsync(Guid tagId);
}

21
modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Comments/CmsUserDto.cs

@ -0,0 +1,21 @@
// This file is automatically generated by ABP framework to use MVC Controllers from CSharp
using System;
using System.Collections.Generic;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.ObjectExtending;
using Volo.CmsKit.Public.Comments;
// ReSharper disable once CheckNamespace
namespace Volo.CmsKit.Public.Comments;
public class CmsUserDto : ExtensibleObject
{
public Guid Id { get; set; }
public string UserName { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
}

33
modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Comments/CommentDto.cs

@ -0,0 +1,33 @@
// This file is automatically generated by ABP framework to use MVC Controllers from CSharp
using System;
using System.Collections.Generic;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.ObjectExtending;
using Volo.CmsKit.Public.Comments;
// ReSharper disable once CheckNamespace
namespace Volo.CmsKit.Public.Comments;
public class CommentDto : ExtensibleObject
{
public Guid Id { get; set; }
public string EntityType { get; set; }
public string EntityId { get; set; }
public string Text { get; set; }
public Guid? RepliedCommentId { get; set; }
public Guid CreatorId { get; set; }
public DateTime CreationTime { get; set; }
public CmsUserDto Author { get; set; }
public string ConcurrencyStamp { get; set; }
public string Url { get; set; }
}

31
modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Comments/CommentWithDetailsDto.cs

@ -0,0 +1,31 @@
// This file is automatically generated by ABP framework to use MVC Controllers from CSharp
using System;
using System.Collections.Generic;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.ObjectExtending;
using Volo.CmsKit.Public.Comments;
// ReSharper disable once CheckNamespace
namespace Volo.CmsKit.Public.Comments;
public class CommentWithDetailsDto : ExtensibleObject
{
public Guid Id { get; set; }
public string EntityType { get; set; }
public string EntityId { get; set; }
public string Text { get; set; }
public Guid CreatorId { get; set; }
public DateTime CreationTime { get; set; }
public CommentDto[] Replies { get; set; }
public CmsUserDto Author { get; set; }
public string ConcurrencyStamp { get; set; }
}

25
modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Comments/CreateCommentInput.cs

@ -0,0 +1,25 @@
// This file is automatically generated by ABP framework to use MVC Controllers from CSharp
using System;
using System.Collections.Generic;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.ObjectExtending;
using Volo.CmsKit.Public.Comments;
// ReSharper disable once CheckNamespace
namespace Volo.CmsKit.Public.Comments;
public class CreateCommentInput : ExtensibleObject
{
public string Text { get; set; }
public Guid? RepliedCommentId { get; set; }
public Guid? CaptchaToken { get; set; }
public int CaptchaAnswer { get; set; }
public string Url { get; set; }
public string IdempotencyToken { get; set; }
}

22
modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Comments/ICommentPublicAppService.cs

@ -0,0 +1,22 @@
// 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.Application.Services;
using Volo.CmsKit.Public.Comments;
// ReSharper disable once CheckNamespace
namespace Volo.CmsKit.Public.Comments;
public interface ICommentPublicAppService : IApplicationService
{
Task<ListResultDto<CommentWithDetailsDto>> GetListAsync(string entityType, string entityId);
Task<CommentDto> CreateAsync(string entityType, string entityId, CreateCommentInput input);
Task<CommentDto> UpdateAsync(Guid id, UpdateCommentInput input);
Task DeleteAsync(Guid id);
}

21
modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Comments/UpdateCommentInput.cs

@ -0,0 +1,21 @@
// This file is automatically generated by ABP framework to use MVC Controllers from CSharp
using System;
using System.Collections.Generic;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.ObjectExtending;
using Volo.CmsKit.Public.Comments;
// ReSharper disable once CheckNamespace
namespace Volo.CmsKit.Public.Comments;
public class UpdateCommentInput : ExtensibleObject
{
public string Text { get; set; }
public string ConcurrencyStamp { get; set; }
public Guid? CaptchaToken { get; set; }
public int CaptchaAnswer { get; set; }
}

17
modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/GlobalResources/GlobalResourceDto.cs

@ -0,0 +1,17 @@
// This file is automatically generated by ABP framework to use MVC Controllers from CSharp
using System;
using System.Collections.Generic;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.ObjectExtending;
using Volo.CmsKit.Public.GlobalResources;
// ReSharper disable once CheckNamespace
namespace Volo.CmsKit.Public.GlobalResources;
public class GlobalResourceDto : ExtensibleAuditedEntityDto
{
public string Name { get; set; }
public string Value { get; set; }
}

18
modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/GlobalResources/IGlobalResourcePublicAppService.cs

@ -0,0 +1,18 @@
// 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.Application.Services;
using Volo.CmsKit.Public.GlobalResources;
// ReSharper disable once CheckNamespace
namespace Volo.CmsKit.Public.GlobalResources;
public interface IGlobalResourcePublicAppService : IApplicationService
{
Task<GlobalResourceDto> GetGlobalScriptAsync();
Task<GlobalResourceDto> GetGlobalStyleAsync();
}

18
modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/MarkedItems/IMarkedItemPublicAppService.cs

@ -0,0 +1,18 @@
// 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.Application.Services;
using Volo.CmsKit.Public.MarkedItems;
// ReSharper disable once CheckNamespace
namespace Volo.CmsKit.Public.MarkedItems;
public interface IMarkedItemPublicAppService : IApplicationService
{
Task<MarkedItemWithToggleDto> GetForToggleAsync(string entityType, string entityId);
Task<bool> ToggleAsync(string entityType, string entityId);
}

15
modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/MarkedItems/MarkedItemDto.cs

@ -0,0 +1,15 @@
// This file is automatically generated by ABP framework to use MVC Controllers from CSharp
using System;
using System.Collections.Generic;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.ObjectExtending;
using Volo.CmsKit.Public.MarkedItems;
// ReSharper disable once CheckNamespace
namespace Volo.CmsKit.Public.MarkedItems;
public class MarkedItemDto
{
public string IconName { get; set; }
}

37
modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/MarkedItems/MarkedItemPublicClientProxy.Generated.cs

@ -0,0 +1,37 @@
// 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.Public.MarkedItems;
// ReSharper disable once CheckNamespace
namespace Volo.CmsKit.Public.MarkedItems;
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(IMarkedItemPublicAppService), typeof(MarkedItemPublicClientProxy))]
public partial class MarkedItemPublicClientProxy : ClientProxyBase<IMarkedItemPublicAppService>, IMarkedItemPublicAppService
{
public virtual async Task<MarkedItemWithToggleDto> GetForToggleAsync(string entityType, string entityId)
{
return await RequestAsync<MarkedItemWithToggleDto>(nameof(GetForToggleAsync), new ClientProxyRequestTypeValue
{
{ typeof(string), entityType },
{ typeof(string), entityId }
});
}
public virtual async Task<bool> ToggleAsync(string entityType, string entityId)
{
return await RequestAsync<bool>(nameof(ToggleAsync), new ClientProxyRequestTypeValue
{
{ typeof(string), entityType },
{ typeof(string), entityId }
});
}
}

7
modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/MarkedItems/MarkedItemPublicClientProxy.cs

@ -0,0 +1,7 @@
// This file is part of MarkedItemPublicClientProxy, you can customize it here
// ReSharper disable once CheckNamespace
namespace Volo.CmsKit.Public.MarkedItems;
public partial class MarkedItemPublicClientProxy
{
}

17
modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/MarkedItems/MarkedItemWithToggleDto.cs

@ -0,0 +1,17 @@
// This file is automatically generated by ABP framework to use MVC Controllers from CSharp
using System;
using System.Collections.Generic;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.ObjectExtending;
using Volo.CmsKit.Public.MarkedItems;
// ReSharper disable once CheckNamespace
namespace Volo.CmsKit.Public.MarkedItems;
public class MarkedItemWithToggleDto
{
public MarkedItemDto MarkedItem { get; set; }
public bool IsMarkedByCurrentUser { get; set; }
}

17
modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Menus/IMenuItemPublicAppService.cs

@ -0,0 +1,17 @@
// 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.Application.Services;
using Volo.CmsKit.Menus;
using Volo.CmsKit.Public.Menus;
// ReSharper disable once CheckNamespace
namespace Volo.CmsKit.Public.Menus;
public interface IMenuItemPublicAppService : IApplicationService
{
Task<List<MenuItemDto>> GetListAsync();
}

21
modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Pages/IPagePublicAppService.cs

@ -0,0 +1,21 @@
// 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.Application.Services;
using Volo.CmsKit.Contents;
using Volo.CmsKit.Public.Pages;
// ReSharper disable once CheckNamespace
namespace Volo.CmsKit.Public.Pages;
public interface IPagePublicAppService : IApplicationService
{
Task<PageDto> FindBySlugAsync(string slug);
Task<bool> DoesSlugExistAsync(string slug);
Task<PageDto> FindDefaultHomePageAsync();
}

15
modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Ratings/CreateUpdateRatingInput.cs

@ -0,0 +1,15 @@
// This file is automatically generated by ABP framework to use MVC Controllers from CSharp
using System;
using System.Collections.Generic;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.ObjectExtending;
using Volo.CmsKit.Public.Ratings;
// ReSharper disable once CheckNamespace
namespace Volo.CmsKit.Public.Ratings;
public class CreateUpdateRatingInput
{
public Int16 StarCount { get; set; }
}

20
modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Ratings/IRatingPublicAppService.cs

@ -0,0 +1,20 @@
// 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.Application.Services;
using Volo.CmsKit.Public.Ratings;
// ReSharper disable once CheckNamespace
namespace Volo.CmsKit.Public.Ratings;
public interface IRatingPublicAppService : IApplicationService
{
Task<RatingDto> CreateAsync(string entityType, string entityId, CreateUpdateRatingInput input);
Task DeleteAsync(string entityType, string entityId);
Task<List<RatingWithStarCountDto>> GetGroupedStarCountsAsync(string entityType, string entityId);
}

25
modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Ratings/RatingDto.cs

@ -0,0 +1,25 @@
// This file is automatically generated by ABP framework to use MVC Controllers from CSharp
using System;
using System.Collections.Generic;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.ObjectExtending;
using Volo.CmsKit.Public.Ratings;
// ReSharper disable once CheckNamespace
namespace Volo.CmsKit.Public.Ratings;
public class RatingDto
{
public Guid Id { get; set; }
public string EntityType { get; set; }
public string EntityId { get; set; }
public Int16 StarCount { get; set; }
public Guid CreatorId { get; set; }
public DateTime CreationTime { get; set; }
}

19
modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Ratings/RatingWithStarCountDto.cs

@ -0,0 +1,19 @@
// This file is automatically generated by ABP framework to use MVC Controllers from CSharp
using System;
using System.Collections.Generic;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.ObjectExtending;
using Volo.CmsKit.Public.Ratings;
// ReSharper disable once CheckNamespace
namespace Volo.CmsKit.Public.Ratings;
public class RatingWithStarCountDto
{
public Int16 StarCount { get; set; }
public int Count { get; set; }
public bool IsSelectedByCurrentUser { get; set; }
}

20
modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Reactions/IReactionPublicAppService.cs

@ -0,0 +1,20 @@
// 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.Application.Services;
using Volo.CmsKit.Public.Reactions;
// ReSharper disable once CheckNamespace
namespace Volo.CmsKit.Public.Reactions;
public interface IReactionPublicAppService : IApplicationService
{
Task<ListResultDto<ReactionWithSelectionDto>> GetForSelectionAsync(string entityType, string entityId);
Task CreateAsync(string entityType, string entityId, string reaction);
Task DeleteAsync(string entityType, string entityId, string reaction);
}

17
modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Reactions/ReactionDto.cs

@ -0,0 +1,17 @@
// This file is automatically generated by ABP framework to use MVC Controllers from CSharp
using System;
using System.Collections.Generic;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.ObjectExtending;
using Volo.CmsKit.Public.Reactions;
// ReSharper disable once CheckNamespace
namespace Volo.CmsKit.Public.Reactions;
public class ReactionDto
{
public string Name { get; set; }
public string DisplayName { get; set; }
}

19
modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Reactions/ReactionWithSelectionDto.cs

@ -0,0 +1,19 @@
// This file is automatically generated by ABP framework to use MVC Controllers from CSharp
using System;
using System.Collections.Generic;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.ObjectExtending;
using Volo.CmsKit.Public.Reactions;
// ReSharper disable once CheckNamespace
namespace Volo.CmsKit.Public.Reactions;
public class ReactionWithSelectionDto
{
public ReactionDto Reaction { get; set; }
public int Count { get; set; }
public bool IsSelectedByCurrentUser { get; set; }
}

18
modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/Volo/CmsKit/Public/Tags/ITagAppService.cs

@ -0,0 +1,18 @@
// 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.Application.Services;
using Volo.CmsKit.Tags;
// ReSharper disable once CheckNamespace
namespace Volo.CmsKit.Public.Tags;
public interface ITagAppService : IApplicationService
{
Task<List<TagDto>> GetAllRelatedTagsAsync(string entityType, string entityId);
Task<List<PopularTagDto>> GetPopularTagsAsync(string entityType, int maxCount);
}

8838
modules/cms-kit/src/Volo.CmsKit.Public.HttpApi.Client/ClientProxies/cms-kit-generate-proxy.json

File diff suppressed because it is too large

38
modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/MarkedItems/MarkedItemPublicController.cs

@ -0,0 +1,38 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp;
using Volo.Abp.Features;
using Volo.Abp.GlobalFeatures;
using Volo.CmsKit.Features;
using Volo.CmsKit.GlobalFeatures;
namespace Volo.CmsKit.Public.MarkedItems;
[RequiresFeature(CmsKitFeatures.MarkedItemEnable)]
[RequiresGlobalFeature(typeof(MarkedItemsFeature))]
[RemoteService(Name = CmsKitPublicRemoteServiceConsts.RemoteServiceName)]
[Area(CmsKitPublicRemoteServiceConsts.ModuleName)]
[Route("api/cms-kit-public/marked-items")]
public class MarkedItemPublicController : CmsKitPublicControllerBase, IMarkedItemPublicAppService
{
protected IMarkedItemPublicAppService MarkedItemPublicAppService { get; }
public MarkedItemPublicController(IMarkedItemPublicAppService markedItemPublicAppService)
{
MarkedItemPublicAppService = markedItemPublicAppService;
}
[HttpGet]
[Route("{entityType}/{entityId}")]
public virtual Task<MarkedItemWithToggleDto> GetForToggleAsync(string entityType, string entityId)
{
return MarkedItemPublicAppService.GetForToggleAsync(entityType, entityId);
}
[HttpPut]
[Route("{entityType}/{entityId}")]
public Task<bool> ToggleAsync(string entityType, string entityId)
{
return MarkedItemPublicAppService.ToggleAsync(entityType, entityId);
}
}

10
modules/cms-kit/src/Volo.CmsKit.Public.Web/CmsKitPublicWebModule.cs

@ -13,10 +13,12 @@ using Volo.Abp.UI.Navigation;
using Volo.Abp.VirtualFileSystem;
using Volo.CmsKit.GlobalFeatures;
using Volo.CmsKit.Localization;
using Volo.CmsKit.MarkedItems;
using Volo.CmsKit.Public.Web.Menus;
using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.GlobalResources.Script;
using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.GlobalResources.Style;
using Volo.CmsKit.Web;
using Volo.CmsKit.Web.Icons;
namespace Volo.CmsKit.Public.Web;
@ -46,6 +48,14 @@ public class CmsKitPublicWebModule : AbpModule
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<CmsKitUiOptions>(options =>
{
options.MarkedItemIcons[StandardMarkedItems.Favorite] = new LocalizableIconDictionary("fa fa-heart text-danger");
options.MarkedItemIcons[StandardMarkedItems.Flagged] = new LocalizableIconDictionary("fa fa-flag text-info");
options.MarkedItemIcons[StandardMarkedItems.Bookmark] = new LocalizableIconDictionary("fa fa-bookmark text-primary");
options.MarkedItemIcons[StandardMarkedItems.Starred] = new LocalizableIconDictionary("fa fa-star text-warning");
});
Configure<AbpNavigationOptions>(options =>
{
options.MenuContributors.Add(new CmsKitPublicMenuContributor());

6
modules/cms-kit/src/Volo.CmsKit.Public.Web/Controllers/CmsKitPublicWidgetsController.cs

@ -2,6 +2,7 @@
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc;
using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Commenting;
using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.MarkedItemToggle;
using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Rating;
using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.ReactionSelection;
@ -23,4 +24,9 @@ public class CmsKitPublicWidgetsController : CmsKitPublicControllerBase
{
return Task.FromResult((IActionResult)ViewComponent(typeof(RatingViewComponent), new { entityType, entityId }));
}
public Task<IActionResult> MarkedItem(string entityType, string entityId, bool needsConfirmation)
{
return Task.FromResult((IActionResult)ViewComponent(typeof(MarkedItemToggleViewComponent), new { entityType, entityId, needsConfirmation }));
}
}

14
modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/MarkedItemToggle/Default.cshtml

@ -0,0 +1,14 @@
@using Volo.Abp.Users
@inject ICurrentUser CurrentUser
@model Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.MarkedItemToggle.MarkedItemToggleViewComponent.MarkedItemToggleViewModel
@{
}
<div class="cms-markedItem-area"
data-entity-type="@Model.EntityType"
data-entity-id="@Model.EntityId"
data-needs-confirmation="@Model.NeedsConfirmation"
data-return-url="@(CurrentUser.IsAuthenticated ? "" : Model.ReturnUrl)">
<i class="cms-markedItem-icon @Model.MarkedItem.Icon @(Model.MarkedItem.IsMarkedByCurrentUser ? (Model.NeedsConfirmation ? "confirm" : "") : "unmarked")"
data-is-authenticated="@(CurrentUser.IsAuthenticated ? "true" : "false")"></i>
</div>

13
modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/MarkedItemToggle/MarkedItemToggleScriptBundleContributor.cs

@ -0,0 +1,13 @@
using System.Collections.Generic;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
namespace Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.MarkedItemToggle;
public class MarkedItemToggleScriptBundleContributor : BundleContributor
{
public override void ConfigureBundle(BundleConfigurationContext context)
{
context.Files.AddIfNotContains("/client-proxies/cms-kit-proxy.js");
context.Files.AddIfNotContains("/Pages/CmsKit/Shared/Components/MarkedItemToggle/default.js");
}
}

12
modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/MarkedItemToggle/MarkedItemToggleStyleBundleContributor.cs

@ -0,0 +1,12 @@
using System.Collections.Generic;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
namespace Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.MarkedItemToggle;
public class MarkedItemToggleStyleBundleContributor : BundleContributor
{
public override void ConfigureBundle(BundleConfigurationContext context)
{
context.Files.AddIfNotContains("/Pages/CmsKit/Shared/Components/MarkedItemToggle/default.css");
}
}

77
modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/MarkedItemToggle/MarkedItemToggleViewComponent.cs

@ -0,0 +1,77 @@
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.Widgets;
using Volo.CmsKit.Public.MarkedItems;
using Volo.CmsKit.Web;
namespace Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.MarkedItemToggle;
[ViewComponent(Name = "CmsMarkedItemToggle")]
[Widget(
ScriptTypes = new[] { typeof(MarkedItemToggleScriptBundleContributor) },
StyleTypes = new[] { typeof(MarkedItemToggleStyleBundleContributor) },
RefreshUrl = "/CmsKitPublicWidgets/MarkedItem",
AutoInitialize = true
)]
public class MarkedItemToggleViewComponent : AbpViewComponent
{
protected IMarkedItemPublicAppService MarkedItemPublicAppService { get; set; }
protected CmsKitUiOptions Options { get; }
public MarkedItemToggleViewComponent(
IMarkedItemPublicAppService markedItemPublicAppService,
IOptions<CmsKitUiOptions> options)
{
MarkedItemPublicAppService = markedItemPublicAppService;
Options = options.Value;
}
public virtual async Task<IViewComponentResult> InvokeAsync(
string entityType,
string entityId,
bool? needsConfirmation = false)
{
var result = await MarkedItemPublicAppService.GetForToggleAsync(entityType, entityId);
var returnUrl = HttpContext.Request.Path.ToString();
var viewModel = new MarkedItemToggleViewModel
{
EntityType = entityType,
EntityId = entityId,
NeedsConfirmation = needsConfirmation.GetValueOrDefault(),
MarkedItem = new MarkedItemViewModel()
{
Icon = Options.MarkedItemIcons.GetLocalizedIcon(result.MarkedItem.IconName),
IsMarkedByCurrentUser = result.IsMarkedByCurrentUser
},
ReturnUrl = returnUrl
};
return View("~/Pages/CmsKit/Shared/Components/MarkedItemToggle/Default.cshtml", viewModel);
}
public class MarkedItemToggleViewModel
{
public string EntityType { get; set; }
public string EntityId { get; set; }
public bool NeedsConfirmation { get; set; }
public MarkedItemViewModel MarkedItem { get; set; }
public string ReturnUrl { get; set; }
}
public class MarkedItemViewModel
{
[NotNull]
public string Icon { get; set; }
public bool IsMarkedByCurrentUser { get; set; }
}
}

7
modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/MarkedItemToggle/default.css

@ -0,0 +1,7 @@
body {
}
.cms-markedItem-area i {
font-size: 1.5em;
cursor: pointer;
}

92
modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/MarkedItemToggle/default.js

@ -0,0 +1,92 @@
(function ($) {
var l = abp.localization.getResource('CmsKit');
abp.widgets.CmsMarkedItemToggle = function ($widget) {
let widgetManager = $widget.data('abp-widget-manager');
let $markedItemArea = $widget.find('.cms-markedItem-area');
let loginModal = new abp.ModalManager(abp.appPath + 'CmsKit/Shared/Modals/Login/LoginModal');
function getFilters() {
return {
entityType: $markedItemArea.attr('data-entity-type'),
entityId: $markedItemArea.attr('data-entity-id'),
needsConfirmation: $markedItemArea.attr('data-needs-confirmation')
};
}
function setIconStyles($icon) {
var iconColor = $icon.css('color');
$icon.css({
'-webkit-text-stroke-color': iconColor,
'-webkit-text-stroke-width': '2px'
});
// Manually set the important rule for color
$icon[0].style.setProperty('color', 'transparent', 'important');
}
function isDoubleClicked(element) {
if (element.data("isclicked")) return true;
element.data("isclicked", true);
setTimeout(function () {
element.removeData("isclicked");
}, 500);
}
function handleUnauthenticated() {
loginModal.open({
message: l("CmsKit:MarkedItem:LoginMessage"),
returnUrl: $markedItemArea.attr('data-return-url')
});
}
function registerClickOfMarkedItemIcon($container) {
var $icon = $container.find('.cms-markedItem-icon');
if (isDoubleClicked($icon)) return;
$icon.click(async function () {
if ($icon.attr('data-is-authenticated') === 'false') {
handleUnauthenticated();
return;
}
if ($icon.hasClass('confirm') && !$icon.hasClass('unmarked')) {
const confirmed = await abp.message.confirm(l('CmsKit:MarkedItem:ToggleConfirmation'));
if (confirmed) {
toggleIcon($icon);
}
return;
}
else {
toggleIcon();
}
});
}
async function toggleIcon() {
await volo.cmsKit.public.markedItems.markedItemPublic.toggle(
$markedItemArea.attr('data-entity-type'),
$markedItemArea.attr('data-entity-id')
);
widgetManager.refresh($widget);
}
function init() {
var $unmarked = $widget.find('.unmarked');
if ($unmarked.length === 1) {
setIconStyles($unmarked);
}
registerClickOfMarkedItemIcon($widget);
}
return {
init: init,
getFilters: getFilters
};
};
})(jQuery);

22
modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Modals/Login/LoginModal.cshtml

@ -0,0 +1,22 @@
@page
@using Microsoft.Extensions.Localization
@using Volo.CmsKit.Localization
@inject IStringLocalizer<CmsKitResource> L
@model Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Modals.Login.LoginModalModel
@{
Layout = null;
var message = String.IsNullOrEmpty(Model.ViewModel.Message) ? L["CmsKit:Modals:LoginModalDefaultMessage"] : Model.ViewModel.Message;
}
<abp-modal centered="true">
<abp-modal-header title="@L["CmsKit:Modals:YouAreNotAuthenticated"]">
</abp-modal-header>
<abp-modal-body>
<div class="text-center">
<h4>
@message
</h4>
<br />
<a href="@Model.ViewModel.LoginUrl" class="btn btn-secondary">@L["CmsKit:Modals:Login"]</a>
</div>
</abp-modal-body>
</abp-modal>

32
modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Modals/Login/LoginModal.cshtml.cs

@ -0,0 +1,32 @@
using JetBrains.Annotations;
using Microsoft.Extensions.Options;
using Volo.Abp.AspNetCore.Mvc.UI;
namespace Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Modals.Login;
public class LoginModalModel : CmsKitPublicPageModelBase
{
public AbpMvcUiOptions AbpMvcUiOptions { get; }
public LoginModalViewModel ViewModel { get; set; }
public LoginModalModel(IOptions<AbpMvcUiOptions> abpMvcUiOptions)
{
AbpMvcUiOptions = abpMvcUiOptions.Value;
}
public void OnGet(string message, string? returnUrl = "")
{
ViewModel = new LoginModalViewModel
{
LoginUrl = $"{AbpMvcUiOptions.LoginUrl}?returnUrl={returnUrl}",
Message = message
};
}
}
public class LoginModalViewModel
{
[NotNull]
public string Message { get; set; }
public string LoginUrl { get; set; }
}

22
modules/cms-kit/src/Volo.CmsKit.Public.Web/wwwroot/client-proxies/cms-kit-proxy.js

@ -117,6 +117,28 @@
})();
// controller volo.cmsKit.public.markedItems.markedItemPublic
(function(){
abp.utils.createNamespace(window, 'volo.cmsKit.public.markedItems.markedItemPublic');
volo.cmsKit.public.markedItems.markedItemPublic.getForToggle = function(entityType, entityId, ajaxParams) {
return abp.ajax($.extend(true, {
url: abp.appPath + 'api/cms-kit-public/marked-items/' + entityType + '/' + entityId + '',
type: 'GET'
}, ajaxParams));
};
volo.cmsKit.public.markedItems.markedItemPublic.toggle = function(entityType, entityId, ajaxParams) {
return abp.ajax($.extend(true, {
url: abp.appPath + 'api/cms-kit-public/marked-items/' + entityType + '/' + entityId + '',
type: 'PUT'
}, ajaxParams));
};
})();
// controller volo.cmsKit.public.menus.menuItemPublic
(function(){

65
modules/cms-kit/test/Volo.CmsKit.Application.Tests/MarkedItems/MarkedItemPublicAppService_Tests.cs

@ -0,0 +1,65 @@
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using NSubstitute;
using Shouldly;
using Volo.Abp.Users;
using Volo.CmsKit.Public.MarkedItems;
using Xunit;
namespace Volo.CmsKit.MarkedItems;
public class MarkedItemPublicAppService_Tests : CmsKitApplicationTestBase
{
private readonly CmsKitTestData _cmsKitTestData;
private readonly MarkedItemPublicAppService _markedItemPublicAppService;
private ICurrentUser _currentUser;
public MarkedItemPublicAppService_Tests()
{
_cmsKitTestData = GetRequiredService<CmsKitTestData>();
_markedItemPublicAppService = GetRequiredService<MarkedItemPublicAppService>();
}
protected override void AfterAddApplication(IServiceCollection services)
{
_currentUser = Substitute.For<ICurrentUser>();
services.AddSingleton(_currentUser);
}
[Fact]
public async Task GetForToggleAsync()
{
_currentUser.Id.Returns(_cmsKitTestData.User1Id);
_currentUser.IsAuthenticated.Returns(true);
var firstMarkedItem = await _markedItemPublicAppService.GetForToggleAsync(
_cmsKitTestData.EntityType1,
_cmsKitTestData.EntityId1
);
var secondMarkedItem = await _markedItemPublicAppService.GetForToggleAsync(
_cmsKitTestData.EntityType2,
_cmsKitTestData.EntityId1
);
firstMarkedItem.IsMarkedByCurrentUser.ShouldBeTrue();
secondMarkedItem.IsMarkedByCurrentUser.ShouldBeFalse();
}
[Fact]
public async Task ToggleAsync()
{
_currentUser.Id.Returns(_cmsKitTestData.User1Id);
var firstToggleResult = await _markedItemPublicAppService.ToggleAsync(
_cmsKitTestData.EntityType1,
_cmsKitTestData.EntityId1
);
var secondToggleResult = await _markedItemPublicAppService.ToggleAsync(
_cmsKitTestData.EntityType2,
_cmsKitTestData.EntityId1
);
firstToggleResult.ShouldBeFalse();
secondToggleResult.ShouldBeTrue();
}
}

45
modules/cms-kit/test/Volo.CmsKit.Domain.Tests/MarkedItems/MarkedItemManager_Tests.cs

@ -0,0 +1,45 @@
using System.Threading.Tasks;
using Shouldly;
using Xunit;
namespace Volo.CmsKit.MarkedItems;
public class MarkedItemManager_Tests : CmsKitDomainTestBase
{
private readonly CmsKitTestData _cmsKitTestData;
private readonly MarkedItemManager _markedItemManager;
public MarkedItemManager_Tests()
{
_cmsKitTestData = GetRequiredService<CmsKitTestData>();
_markedItemManager = GetRequiredService<MarkedItemManager>();
}
[Fact]
public async Task ToggleAsync()
{
var firstToggleResult = await _markedItemManager.ToggleAsync(
_cmsKitTestData.User1Id,
_cmsKitTestData.EntityType2,
_cmsKitTestData.EntityId1
);
var secondToggleResult = await _markedItemManager.ToggleAsync(
_cmsKitTestData.User1Id,
_cmsKitTestData.EntityType2,
_cmsKitTestData.EntityId1
);
firstToggleResult.ShouldBeTrue();
secondToggleResult.ShouldBeFalse();
}
[Fact]
public async Task GetAsync()
{
var markedItem = await _markedItemManager.GetAsync(_cmsKitTestData.EntityType1);
markedItem.EntityType.ShouldBe(_cmsKitTestData.EntityType1);
markedItem.IconName.ShouldBe(StandardMarkedItems.Favorite);
}
}

6
modules/cms-kit/test/Volo.CmsKit.EntityFrameworkCore.Tests/EntityFrameworkCore/MarkedItems/UserMarkedItemRepository_Tests.cs

@ -0,0 +1,6 @@
using Volo.CmsKit.MarkedItems;
namespace Volo.CmsKit.EntityFrameworkCore.MarkedItems;
public class UserMarkedItemRepository_Tests : UserMarkedItemRepository_Tests<CmsKitEntityFrameworkCoreTestModule>
{
}

9
modules/cms-kit/test/Volo.CmsKit.MongoDB.Tests/MongoDB/MarkedItems/UserMarkedItemRepository_Tests.cs

@ -0,0 +1,9 @@
using Volo.CmsKit.MarkedItems;
using Xunit;
namespace Volo.CmsKit.MongoDB.MarkedItems;
[Collection(MongoTestCollection.Name)]
public class UserMarkedItemRepository_Tests : UserMarkedItemRepository_Tests<CmsKitMongoDbTestModule>
{
}

28
modules/cms-kit/test/Volo.CmsKit.TestBase/CmsKitDataSeedContributor.cs

@ -12,6 +12,7 @@ using Volo.Abp.MultiTenancy;
using Volo.Abp.Users;
using Volo.CmsKit.Blogs;
using Volo.CmsKit.Comments;
using Volo.CmsKit.MarkedItems;
using Volo.CmsKit.MediaDescriptors;
using Volo.CmsKit.Menus;
using Volo.CmsKit.Pages;
@ -49,6 +50,8 @@ public class CmsKitDataSeedContributor : IDataSeedContributor, ITransientDepende
private readonly IOptions<CmsKitCommentOptions> _commentsOptions;
private readonly IOptions<CmsKitRatingOptions> _ratingOptions;
private readonly IMenuItemRepository _menuItemRepository;
private readonly MarkedItemManager _markedItemManager;
private readonly IOptions<CmsKitMarkedItemOptions> _markedItemOptions;
public CmsKitDataSeedContributor(
IGuidGenerator guidGenerator,
@ -75,7 +78,9 @@ public class CmsKitDataSeedContributor : IDataSeedContributor, ITransientDepende
IOptions<CmsKitMediaOptions> cmsMediaOptions,
IOptions<CmsKitCommentOptions> commentsOptions,
IOptions<CmsKitRatingOptions> ratingOptions,
IMenuItemRepository menuItemRepository)
IMenuItemRepository menuItemRepository,
MarkedItemManager markedItemManager,
IOptions<CmsKitMarkedItemOptions> markedItemOptions)
{
_guidGenerator = guidGenerator;
_cmsUserRepository = cmsUserRepository;
@ -102,6 +107,8 @@ public class CmsKitDataSeedContributor : IDataSeedContributor, ITransientDepende
_commentsOptions = commentsOptions;
_ratingOptions = ratingOptions;
_menuItemRepository = menuItemRepository;
_markedItemManager = markedItemManager;
_markedItemOptions = markedItemOptions;
}
public async Task SeedAsync(DataSeedContext context)
@ -129,6 +136,8 @@ public class CmsKitDataSeedContributor : IDataSeedContributor, ITransientDepende
await SeedMediaAsync();
await SeedMenusAsync();
await SeedMarkedItemsAsync();
}
}
@ -171,6 +180,9 @@ public class CmsKitDataSeedContributor : IDataSeedContributor, ITransientDepende
_ratingOptions.Value.EntityTypes.Add(new RatingEntityTypeDefinition(_cmsKitTestData.EntityType1));
_ratingOptions.Value.EntityTypes.Add(new RatingEntityTypeDefinition(_cmsKitTestData.EntityType2));
_markedItemOptions.Value.EntityTypes.Add(new MarkedItemEntityTypeDefinition(_cmsKitTestData.EntityType1, StandardMarkedItems.Favorite));
_markedItemOptions.Value.EntityTypes.Add(new MarkedItemEntityTypeDefinition(_cmsKitTestData.EntityType2, StandardMarkedItems.Starred));
return Task.CompletedTask;
}
@ -442,4 +454,18 @@ public class CmsKitDataSeedContributor : IDataSeedContributor, ITransientDepende
menuItem4
});
}
private async Task SeedMarkedItemsAsync()
{
await _markedItemManager.ToggleAsync(
_cmsKitTestData.User1Id,
_cmsKitTestData.EntityType1,
_cmsKitTestData.EntityId1
);
await _markedItemManager.ToggleAsync(
_cmsKitTestData.User1Id,
_cmsKitTestData.EntityType1,
_cmsKitTestData.EntityId2
);
}
}

64
modules/cms-kit/test/Volo.CmsKit.TestBase/MarkedItems/UserMarkedItemRepository_Tests.cs

@ -0,0 +1,64 @@
using System.Linq;
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.Modularity;
using Xunit;
namespace Volo.CmsKit.MarkedItems;
public abstract class UserMarkedItemRepository_Tests<TStartupModule> : CmsKitTestBase<TStartupModule>
where TStartupModule : IAbpModule
{
private readonly CmsKitTestData _cmsKitTestData;
private readonly IUserMarkedItemRepository _userMarkedItemRepository;
protected UserMarkedItemRepository_Tests()
{
_cmsKitTestData = GetRequiredService<CmsKitTestData>();
_userMarkedItemRepository = GetRequiredService<IUserMarkedItemRepository>();
}
[Fact]
public async Task FindAsync()
{
var markedItem = await _userMarkedItemRepository.FindAsync(
_cmsKitTestData.User1Id,
_cmsKitTestData.EntityType1,
_cmsKitTestData.EntityId1
);
markedItem.ShouldNotBeNull();
markedItem.CreatorId.ShouldBe(_cmsKitTestData.User1Id);
markedItem.EntityId.ShouldBe(_cmsKitTestData.EntityId1);
markedItem.EntityType.ShouldBe(_cmsKitTestData.EntityType1);
}
[Fact]
public async Task GetListForUserAsync()
{
var markedItems = await _userMarkedItemRepository.GetListForUserAsync(
_cmsKitTestData.User1Id,
_cmsKitTestData.EntityType1
);
markedItems.Count.ShouldBe(2);
}
[Fact]
public async Task GetQueryForUserAsync()
{
await WithUnitOfWorkAsync(async () =>
{
var query = await _userMarkedItemRepository.GetQueryForUserAsync(
_cmsKitTestData.EntityType1,
_cmsKitTestData.User1Id
);
var markedItems = query.ToList();
markedItems.Count.ShouldBe(2);
markedItems.All(x => x.CreatorId == _cmsKitTestData.User1Id).ShouldBeTrue();
markedItems.All(x => x.EntityType == _cmsKitTestData.EntityType1).ShouldBeTrue();
});
}
}
Loading…
Cancel
Save