mirror of https://github.com/abpframework/abp.git
Browse Source
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
87 changed files with 10988 additions and 262 deletions
@ -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: |
|||
|
|||
 |
|||
|
|||
|
|||
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. |
|||
|
|||
 |
|||
|
|||
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** |
|||
|
|||
|
After Width: | Height: | Size: 7.3 KiB |
|
After Width: | Height: | Size: 483 KiB |
@ -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); |
|||
} |
|||
} |
|||
@ -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); |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
using Volo.CmsKit.Web.Icons; |
|||
|
|||
namespace Volo.CmsKit.Web.MarkedItems; |
|||
|
|||
public class MarkedItemIconDictionary : LocalizableIconDictionaryBase |
|||
{ |
|||
} |
|||
@ -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); |
|||
} |
|||
} |
|||
|
|||
@ -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(); |
|||
} |
|||
} |
|||
@ -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." |
|||
} |
|||
} |
|||
@ -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"; |
|||
} |
|||
@ -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; |
|||
} |
|||
@ -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(); |
|||
} |
|||
@ -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); |
|||
} |
|||
} |
|||
@ -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; } |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
using System.Threading.Tasks; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.CmsKit.MarkedItems; |
|||
|
|||
public interface IMarkedItemDefinitionStore : IEntityTypeDefinitionStore<MarkedItemEntityTypeDefinition> |
|||
{ |
|||
} |
|||
@ -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 |
|||
); |
|||
} |
|||
@ -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; |
|||
} |
|||
} |
|||
@ -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); |
|||
} |
|||
} |
|||
@ -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; |
|||
} |
|||
} |
|||
@ -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; |
|||
} |
|||
} |
|||
@ -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; |
|||
} |
|||
} |
|||
@ -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); |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
using System; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.CmsKit.Public.MarkedItems; |
|||
|
|||
[Serializable] |
|||
public class MarkedItemDto |
|||
{ |
|||
[NotNull] |
|||
public string IconName { get; set; } |
|||
} |
|||
@ -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; } |
|||
} |
|||
@ -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 |
|||
}; |
|||
} |
|||
|
|||
} |
|||
@ -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; } |
|||
} |
|||
@ -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; } |
|||
} |
|||
@ -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); |
|||
} |
|||
@ -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; } |
|||
} |
|||
@ -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; } |
|||
} |
|||
@ -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; } |
|||
} |
|||
@ -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; } |
|||
} |
|||
@ -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); |
|||
} |
|||
@ -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; } |
|||
} |
|||
@ -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; } |
|||
} |
|||
@ -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(); |
|||
} |
|||
@ -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); |
|||
} |
|||
@ -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; } |
|||
} |
|||
@ -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 } |
|||
}); |
|||
} |
|||
} |
|||
@ -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 |
|||
{ |
|||
} |
|||
@ -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; } |
|||
} |
|||
@ -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(); |
|||
} |
|||
@ -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(); |
|||
} |
|||
@ -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; } |
|||
} |
|||
@ -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); |
|||
} |
|||
@ -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; } |
|||
} |
|||
@ -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; } |
|||
} |
|||
@ -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); |
|||
} |
|||
@ -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; } |
|||
} |
|||
@ -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; } |
|||
} |
|||
@ -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); |
|||
} |
|||
File diff suppressed because it is too large
@ -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); |
|||
} |
|||
} |
|||
@ -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> |
|||
@ -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"); |
|||
} |
|||
} |
|||
@ -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"); |
|||
} |
|||
} |
|||
@ -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; } |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
body { |
|||
} |
|||
|
|||
.cms-markedItem-area i { |
|||
font-size: 1.5em; |
|||
cursor: pointer; |
|||
} |
|||
@ -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); |
|||
@ -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> |
|||
@ -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; } |
|||
} |
|||
@ -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(); |
|||
} |
|||
} |
|||
@ -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); |
|||
} |
|||
} |
|||
@ -0,0 +1,6 @@ |
|||
using Volo.CmsKit.MarkedItems; |
|||
|
|||
namespace Volo.CmsKit.EntityFrameworkCore.MarkedItems; |
|||
public class UserMarkedItemRepository_Tests : UserMarkedItemRepository_Tests<CmsKitEntityFrameworkCoreTestModule> |
|||
{ |
|||
} |
|||
@ -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> |
|||
{ |
|||
} |
|||
@ -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…
Reference in new issue