Browse Source

Introduce client-side baskets.

pull/137/head
gdlcf88 4 years ago
parent
commit
7cb04de499
  1. 4
      modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Web/Pages/EShop/Stores/Transactions/Transaction/index.js
  2. 77
      plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/ClientSideBasketItemModel.cs
  3. 1
      plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/CreateBasketItemDto.cs
  4. 9
      plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/GenerateClientSideDataInput.cs
  5. 45
      plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/GenerateClientSideDataItemInput.cs
  6. 3
      plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/GetBasketItemListDto.cs
  7. 4
      plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/IBasketItemAppService.cs
  8. 0
      plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/ProductDataModel.cs
  9. 3
      plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/Permissions/BasketsPermissionDefinitionProvider.cs
  10. 3
      plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/Permissions/BasketsPermissions.cs
  11. 55
      plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItemAppService.cs
  12. 26
      plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/BasketItems/IBasketItem.cs
  13. 0
      plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/BasketItems/IProductData.cs
  14. 7
      plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItem.cs
  15. 4
      plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/Settings/BasketsSettingDefinitionProvider.cs
  16. 2
      plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/Settings/BasketsSettings.cs
  17. 13
      plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.HttpApi/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItemController.cs
  18. 6
      plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/BasketsWebAutoMapperProfile.cs
  19. 2
      plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/EShopPluginsBasketsWebModule.cs
  20. 4
      plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Menus/BasketsMenuContributor.cs
  21. 63
      plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/CreateModal.cshtml
  22. 13
      plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/CreateModal.cshtml.cs
  23. 52
      plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/EditModal.cshtml
  24. 19
      plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/EditModal.cshtml.cs
  25. 5
      plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/Index.cshtml
  26. 8
      plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/ViewModels/CreateBasketItemViewModel.cs
  27. 89
      plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/index.js

4
modules/EasyAbp.EShop.Stores/src/EasyAbp.EShop.Stores.Web/Pages/EShop/Stores/Transactions/Transaction/index.js

@ -24,14 +24,14 @@ $(function () {
[
{
text: l('Edit'),
visible: abp.auth.isGranted('Stores.Transaction.Update'),
visible: abp.auth.isGranted('EasyAbp.EShop.Stores.Transaction.Update'),
action: function (data) {
editModal.open({ id: data.record.id });
}
},
{
text: l('Delete'),
visible: abp.auth.isGranted('Stores.Transaction.Delete'),
visible: abp.auth.isGranted('EasyAbp.EShop.Stores.Transaction.Delete'),
confirmMessage: function (data) {
return l('TransactionDeletionConfirmationMessage', data.record.id);
},

77
plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/ClientSideBasketItemModel.cs

@ -0,0 +1,77 @@
using System;
using JetBrains.Annotations;
namespace EasyAbp.EShop.Plugins.Baskets.BasketItems.Dtos;
[Serializable]
public class ClientSideBasketItemModel : IBasketItem
{
public Guid Id { get; set; }
public string BasketName { get; set; }
public int Quantity { get; set; }
public Guid StoreId { get; set; }
public Guid ProductId { get; set; }
public string ProductUniqueName { get; set; }
public string ProductDisplayName { get; set; }
public Guid ProductSkuId { get; set; }
public string SkuName { get; set; }
public string SkuDescription { get; set; }
public string MediaResources { get; set; }
public string Currency { get; set; }
public decimal UnitPrice { get; set; }
public decimal TotalPrice { get; set; }
public decimal TotalDiscount { get; set; }
public int Inventory { get; set; }
public bool IsInvalid { get; set; }
public ClientSideBasketItemModel(
Guid id,
[NotNull] string basketName,
Guid storeId,
Guid productId,
Guid productSkuId)
{
Id = id;
BasketName = basketName;
StoreId = storeId;
ProductId = productId;
ProductSkuId = productSkuId;
}
public void SetIsInvalid(bool isInvalid)
{
IsInvalid = isInvalid;
}
public void UpdateProductData(int quantity, IProductData productData)
{
Quantity = quantity;
MediaResources = productData.MediaResources;
ProductUniqueName = productData.ProductUniqueName;
ProductDisplayName = productData.ProductDisplayName;
SkuName = productData.SkuName;
SkuDescription = productData.SkuDescription;
Currency = productData.Currency;
UnitPrice = productData.UnitPrice;
TotalPrice = productData.TotalPrice;
TotalDiscount = productData.TotalDiscount;
Inventory = productData.Inventory;
}
}

1
plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/CreateBasketItemDto.cs

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.ObjectExtending;

9
plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/GenerateClientSideDataInput.cs

@ -0,0 +1,9 @@
using System.Collections.Generic;
using Volo.Abp.ObjectExtending;
namespace EasyAbp.EShop.Plugins.Baskets.BasketItems.Dtos;
public class GenerateClientSideDataInput : ExtensibleObject
{
public List<GenerateClientSideDataItemInput> Items { get; set; } = new();
}

45
plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/GenerateClientSideDataItemInput.cs

@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.ObjectExtending;
namespace EasyAbp.EShop.Plugins.Baskets.BasketItems.Dtos
{
[Serializable]
public class GenerateClientSideDataItemInput : ExtensibleObject
{
/// <summary>
/// Reuse Id if set.
/// </summary>
public Guid? Id { get; set; }
public string BasketName { get; set; } = BasketsConsts.DefaultBasketName;
public Guid ProductId { get; set; }
public Guid ProductSkuId { get; set; }
public int Quantity { get; set; }
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
base.Validate(validationContext);
if (Quantity <= 0)
{
yield return new ValidationResult(
"Quantity should be greater than 0.",
new[] { "Quantity" }
);
}
if (BasketName.IsNullOrWhiteSpace())
{
yield return new ValidationResult(
"BasketName should not be empty.",
new[] { "BasketName" }
);
}
}
}
}

3
plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/Dtos/GetBasketItemListDto.cs

@ -1,11 +1,10 @@
using System;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Application.Dtos;
namespace EasyAbp.EShop.Plugins.Baskets.BasketItems.Dtos
{
[Serializable]
public class GetBasketItemListDto : PagedAndSortedResultRequestDto
public class GetBasketItemListDto
{
[Required]
public string BasketName { get; set; }

4
plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/IBasketItemAppService.cs

@ -15,6 +15,8 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems
CreateBasketItemDto,
UpdateBasketItemDto>
{
Task DeleteInBulkAsync(IEnumerable<Guid> ids);
Task BatchDeleteAsync(IEnumerable<Guid> ids);
Task<ListResultDto<ClientSideBasketItemModel>> GenerateClientSideDataAsync(GenerateClientSideDataInput input);
}
}

0
plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/BasketItems/ProductDataModel.cs → plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/BasketItems/ProductDataModel.cs

3
plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/Permissions/BasketsPermissionDefinitionProvider.cs

@ -12,9 +12,6 @@ namespace EasyAbp.EShop.Plugins.Baskets.Permissions
var basketItemPermission = myGroup.AddPermission(BasketsPermissions.BasketItem.Default, L("Permission:BasketItem"));
basketItemPermission.AddChild(BasketsPermissions.BasketItem.Manage, L("Permission:Manage"));
basketItemPermission.AddChild(BasketsPermissions.BasketItem.Create, L("Permission:Create"));
basketItemPermission.AddChild(BasketsPermissions.BasketItem.Update, L("Permission:Update"));
basketItemPermission.AddChild(BasketsPermissions.BasketItem.Delete, L("Permission:Delete"));
}
private static LocalizableString L(string name)

3
plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application.Contracts/EasyAbp/EShop/Plugins/Baskets/Permissions/BasketsPermissions.cs

@ -15,9 +15,6 @@ namespace EasyAbp.EShop.Plugins.Baskets.Permissions
{
public const string Default = GroupName + ".BasketItem";
public const string Manage = Default + ".Manage";
public const string Update = Default + ".Update";
public const string Create = Default + ".Create";
public const string Delete = Default + ".Delete";
}
}

55
plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Application/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItemAppService.cs

@ -5,14 +5,12 @@ using System.Threading.Tasks;
using EasyAbp.EShop.Plugins.Baskets.Permissions;
using EasyAbp.EShop.Plugins.Baskets.BasketItems.Dtos;
using EasyAbp.EShop.Plugins.Baskets.ProductUpdates;
using EasyAbp.EShop.Products.ProductInventories;
using EasyAbp.EShop.Products.Products;
using EasyAbp.EShop.Products.Products.Dtos;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Authorization;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Users;
namespace EasyAbp.EShop.Plugins.Baskets.BasketItems
@ -22,9 +20,9 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems
{
protected override string GetPolicyName { get; set; } = BasketsPermissions.BasketItem.Default;
protected override string GetListPolicyName { get; set; } = BasketsPermissions.BasketItem.Default;
protected override string CreatePolicyName { get; set; } = BasketsPermissions.BasketItem.Create;
protected override string UpdatePolicyName { get; set; } = BasketsPermissions.BasketItem.Update;
protected override string DeletePolicyName { get; set; } = BasketsPermissions.BasketItem.Delete;
protected override string CreatePolicyName { get; set; } = BasketsPermissions.BasketItem.Default;
protected override string UpdatePolicyName { get; set; } = BasketsPermissions.BasketItem.Default;
protected override string DeletePolicyName { get; set; } = BasketsPermissions.BasketItem.Default;
private readonly IBasketItemRepository _repository;
private readonly IProductUpdateRepository _productUpdateRepository;
@ -85,11 +83,6 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems
var query = await CreateFilteredQueryAsync(input);
var totalCount = await AsyncExecuter.CountAsync(query);
query = ApplySorting(query, input);
query = ApplyPaging(query, input);
var items = await AsyncExecuter.ToListAsync(query);
var productSkuIds = items.Select(item => item.ProductSkuId).ToList();
@ -127,12 +120,12 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems
}
return new PagedResultDto<BasketItemDto>(
totalCount,
items.Count,
await MapToGetListOutputDtosAsync(items)
);
}
protected virtual async Task UpdateProductDataAsync(int quantity, BasketItem item, ProductDto productDto)
protected virtual async Task UpdateProductDataAsync(int quantity, IBasketItem item, ProductDto productDto)
{
item.SetIsInvalid(false);
@ -254,7 +247,7 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems
await _repository.DeleteAsync(item, true);
}
public virtual async Task DeleteInBulkAsync(IEnumerable<Guid> ids)
public virtual async Task BatchDeleteAsync(IEnumerable<Guid> ids)
{
await CheckDeletePolicyAsync();
@ -273,6 +266,42 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems
}
}
public virtual async Task<ListResultDto<ClientSideBasketItemModel>> GenerateClientSideDataAsync(
GenerateClientSideDataInput input)
{
var itemList = new List<ClientSideBasketItemModel>();
var products = new Dictionary<Guid, ProductDto>();
foreach (var dto in input.Items)
{
if (!products.ContainsKey(dto.ProductId))
{
products[dto.ProductId] = await _productAppService.GetAsync(dto.ProductId);
}
var productDto = products[dto.ProductId];
var productSkuDto = productDto.FindSkuById(dto.ProductSkuId);
if (productSkuDto == null)
{
throw new ProductSkuNotFoundException(dto.ProductId, dto.ProductSkuId);
}
var id = dto.Id ?? GuidGenerator.Create();
var item = new ClientSideBasketItemModel(id, dto.BasketName, productDto.StoreId,
dto.ProductId, dto.ProductSkuId);
await UpdateProductDataAsync(dto.Quantity, item, productDto);
itemList.Add(item);
}
return new ListResultDto<ClientSideBasketItemModel>(itemList);
}
protected virtual async Task<bool> IsCurrentUserManagerAsync()
{
return await AuthorizationService.IsGrantedAsync(BasketsPermissions.BasketItem.Manage);

26
plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/BasketItems/IBasketItem.cs

@ -0,0 +1,26 @@
using System;
using JetBrains.Annotations;
namespace EasyAbp.EShop.Plugins.Baskets.BasketItems;
public interface IBasketItem : IProductData
{
Guid Id { get; }
[NotNull]
string BasketName { get; }
Guid StoreId { get; }
Guid ProductId { get; }
Guid ProductSkuId { get; }
int Quantity { get; }
bool IsInvalid { get; }
void SetIsInvalid(bool isInvalid);
void UpdateProductData(int quantity, IProductData productData);
}

0
plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/BasketItems/IProductData.cs → plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain.Shared/EasyAbp/EShop/Plugins/Baskets/BasketItems/IProductData.cs

7
plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItem.cs

@ -5,11 +5,10 @@ using Volo.Abp.MultiTenancy;
namespace EasyAbp.EShop.Plugins.Baskets.BasketItems
{
public class BasketItem : AuditedAggregateRoot<Guid>, IProductData, IMultiTenant
public class BasketItem : AuditedAggregateRoot<Guid>, IBasketItem, IMultiTenant
{
public virtual Guid? TenantId { get; protected set; }
[NotNull]
public virtual string BasketName { get; protected set; }
public virtual Guid UserId { get; protected set; }
@ -87,9 +86,9 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems
Inventory = productData.Inventory;
}
public void SetIsInvalid(bool isForSale)
public void SetIsInvalid(bool isInvalid)
{
IsInvalid = isForSale;
IsInvalid = isInvalid;
}
}
}

4
plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/Settings/BasketsSettingDefinitionProvider.cs

@ -9,6 +9,10 @@ namespace EasyAbp.EShop.Plugins.Baskets.Settings
/* Define module settings here.
* Use names from BasketsSettings class.
*/
context.Add(new SettingDefinition(
BasketsSettings.EnableServerSideBasketsName,
true.ToString(),
isVisibleToClients: true));
}
}
}

2
plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Domain/EasyAbp/EShop/Plugins/Baskets/Settings/BasketsSettings.cs

@ -7,5 +7,7 @@
/* Add constants for setting names. Example:
* public const string MySettingName = GroupName + ".MySettingName";
*/
public const string EnableServerSideBasketsName = GroupName + ".EnableServerSideBaskets";
}
}

13
plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.HttpApi/EasyAbp/EShop/Plugins/Baskets/BasketItems/BasketItemController.cs

@ -53,10 +53,17 @@ namespace EasyAbp.EShop.Plugins.Baskets.BasketItems
}
[HttpDelete]
[Route("in-bulk")]
public Task DeleteInBulkAsync(IEnumerable<Guid> ids)
[Route("batch")]
public Task BatchDeleteAsync(IEnumerable<Guid> ids)
{
return _service.DeleteInBulkAsync(ids);
return _service.BatchDeleteAsync(ids);
}
[HttpPost]
[Route("generate-client-side-data")]
public Task<ListResultDto<ClientSideBasketItemModel>> GenerateClientSideDataAsync(GenerateClientSideDataInput input)
{
return _service.GenerateClientSideDataAsync(input);
}
}
}

6
plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/BasketsWebAutoMapperProfile.cs

@ -1,5 +1,6 @@
using EasyAbp.EShop.Plugins.Baskets.BasketItems.Dtos;
using AutoMapper;
using EasyAbp.EShop.Plugins.Baskets.BasketItems;
using EasyAbp.EShop.Plugins.Baskets.Web.Pages.EShop.Plugins.Baskets.BasketItems.BasketItem.ViewModels;
using Volo.Abp.AutoMapper;
@ -12,8 +13,11 @@ namespace EasyAbp.EShop.Plugins.Baskets.Web
/* You can configure your AutoMapper mapping configuration here.
* Alternatively, you can split your mapping configurations
* into multiple profile classes for a better organization. */
CreateMap<BasketItemDto, EditBasketItemViewModel>();
CreateMap<ClientSideBasketItemModel, GenerateClientSideDataItemInput>()
.Ignore(dto => dto.ExtraProperties);
CreateMap<IBasketItem, EditBasketItemViewModel>();
CreateMap<CreateBasketItemViewModel, CreateBasketItemDto>()
.Ignore(dto => dto.UserId)
.Ignore(dto => dto.ExtraProperties);
CreateMap<EditBasketItemViewModel, UpdateBasketItemDto>()
.Ignore(dto => dto.ExtraProperties);

2
plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/EShopPluginsBasketsWebModule.cs

@ -8,7 +8,6 @@ using Volo.Abp.AutoMapper;
using Volo.Abp.Modularity;
using Volo.Abp.UI.Navigation;
using Volo.Abp.VirtualFileSystem;
using EasyAbp.EShop.Plugins.Baskets.Permissions;
namespace EasyAbp.EShop.Plugins.Baskets.Web
{
@ -45,6 +44,7 @@ namespace EasyAbp.EShop.Plugins.Baskets.Web
});
context.Services.AddAutoMapperObjectMapper<EShopPluginsBasketsWebModule>();
Configure<AbpAutoMapperOptions>(options =>
{
options.AddMaps<EShopPluginsBasketsWebModule>(validate: true);

4
plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Menus/BasketsMenuContributor.cs

@ -1,7 +1,9 @@
using System.Collections.Generic;
using System.Security.Principal;
using System.Threading.Tasks;
using EasyAbp.EShop.Plugins.Baskets.Localization;
using EasyAbp.EShop.Plugins.Baskets.Permissions;
using Volo.Abp;
using Volo.Abp.UI.Navigation;
namespace EasyAbp.EShop.Plugins.Baskets.Web.Menus
@ -22,7 +24,7 @@ namespace EasyAbp.EShop.Plugins.Baskets.Web.Menus
var basketManagementMenuItem = new ApplicationMenuItem(BasketsMenus.Prefix, l["Menu:BasketManagement"]);
if (await context.IsGrantedAsync(BasketsPermissions.BasketItem.Default))
if (context.GetHttpContext().User.Identity.FindUserId() == null || await context.IsGrantedAsync(BasketsPermissions.BasketItem.Default))
{
basketManagementMenuItem.AddItem(
new ApplicationMenuItem(BasketsMenus.BasketItem, l["Menu:BasketItem"], $"/EShop/Plugins/Baskets/BasketItems/BasketItem?basketName={BasketsConsts.DefaultBasketName}&userId=")

63
plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/CreateModal.cshtml

@ -1,12 +1,18 @@
@page
@using EasyAbp.EShop.Plugins.Baskets.Localization
@using EasyAbp.EShop.Plugins.Baskets.Permissions
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal
@using Volo.Abp.Settings
@inject IHtmlLocalizer<BasketsResource> L
@inject IAuthorizationService _authorizationService
@inject ISettingProvider _settingProvider
@model EasyAbp.EShop.Plugins.Baskets.Web.Pages.EShop.Plugins.Baskets.BasketItems.BasketItem.CreateModalModel
@{
Layout = null;
}
<abp-dynamic-form abp-model="ViewModel" data-ajaxForm="true" asp-page="CreateModal">
<abp-modal>
<abp-modal-header title="@L["CreateBasketItem"].Value"></abp-modal-header>
@ -15,4 +21,59 @@
</abp-modal-body>
<abp-modal-footer buttons="@(AbpModalButtons.Cancel|AbpModalButtons.Save)"></abp-modal-footer>
</abp-modal>
</abp-dynamic-form>
</abp-dynamic-form>
<script>
var localStorageItemKey = localStorageItemKey || "EShopBasket:" + basketName;
$(document).ready(function() {
if (@(Model.ServerSide ? "true" : "false")) return;
var $form = $("form");
$form.off('submit');
$form.on('submit', function(e){
e.preventDefault();
var service = easyAbp.eShop.plugins.baskets.basketItems.basketItem;
service.generateClientSideData({ items: [ getFormData() ] }, {
success: function (responseText, statusText, xhr, form) {
var basketItems = JSON.parse(localStorage.getItem(localStorageItemKey)) || [];
basketItems = pushOrUpdateBasketItem(basketItems, responseText.items[0])
localStorage.setItem(localStorageItemKey, JSON.stringify(basketItems));
$form.trigger('abp-ajax-success',
{
responseText: responseText,
statusText: statusText,
xhr: xhr,
$form: form
})
}
});
});
});
String.prototype.toCamelCase = function() {
return this.replace(/^([A-Z])|\s(\w)/g, function(match, p1, p2, offset) {
if (p2) return p2.toUpperCase();
return p1.toLowerCase();
});
};
function getFormData() {
const PREFIX = "ViewModel.";
return $('form').serializeArray().reduce(function(obj, item) {
obj[item.name.slice(PREFIX.length).toCamelCase()] = item.value;
return obj;
}, {});
}
function pushOrUpdateBasketItem(basketItems, item) {
var index = basketItems.findIndex(x => x.storeId === item.storeId && x.productId === item.productId && x.productSkuId === item.productSkuId);
if (index >= 0) {
basketItems[index].quantity += item.quantity;
} else {
basketItems.push(item);
}
return basketItems;
}
</script>

13
plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/CreateModal.cshtml.cs

@ -2,14 +2,19 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using EasyAbp.EShop.Plugins.Baskets.BasketItems;
using EasyAbp.EShop.Plugins.Baskets.BasketItems.Dtos;
using EasyAbp.EShop.Plugins.Baskets.Permissions;
using EasyAbp.EShop.Plugins.Baskets.Web.Pages.EShop.Plugins.Baskets.BasketItems.BasketItem.ViewModels;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp.Settings;
namespace EasyAbp.EShop.Plugins.Baskets.Web.Pages.EShop.Plugins.Baskets.BasketItems.BasketItem
{
public class CreateModalModel : BasketsPageModel
{
[BindProperty]
public CreateBasketItemViewModel ViewModel { get; set; } = new CreateBasketItemViewModel();
public CreateBasketItemViewModel ViewModel { get; set; } = new();
public bool ServerSide { get; set; }
private readonly IBasketItemAppService _service;
@ -18,6 +23,12 @@ namespace EasyAbp.EShop.Plugins.Baskets.Web.Pages.EShop.Plugins.Baskets.BasketIt
_service = service;
}
public virtual async Task OnGetAsync()
{
ServerSide = await SettingProvider.GetAsync<bool>("EasyAbp.EShop.Plugins.Baskets.EnableServerSideBaskets")
&& await AuthorizationService.IsGrantedAsync(BasketsPermissions.BasketItem.Default);
}
public virtual async Task<IActionResult> OnPostAsync()
{
var dto = ObjectMapper.Map<CreateBasketItemViewModel, CreateBasketItemDto>(ViewModel);

52
plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/EditModal.cshtml

@ -1,8 +1,13 @@
@page
@using EasyAbp.EShop.Plugins.Baskets.Localization
@using EasyAbp.EShop.Plugins.Baskets.Permissions
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal
@using Volo.Abp.Settings
@inject IHtmlLocalizer<BasketsResource> L
@inject IAuthorizationService _authorizationService
@inject ISettingProvider _settingProvider
@model EasyAbp.EShop.Plugins.Baskets.Web.Pages.EShop.Plugins.Baskets.BasketItems.BasketItem.EditModalModel
@{
Layout = null;
@ -16,4 +21,49 @@
</abp-modal-body>
<abp-modal-footer buttons="@(AbpModalButtons.Cancel|AbpModalButtons.Save)"></abp-modal-footer>
</abp-modal>
</abp-dynamic-form>
</abp-dynamic-form>
<script>
var localStorageItemKey = localStorageItemKey || "EShopBasket:" + basketName;
$(document).ready(function() {
if (@(Model.ServerSide ? "true" : "false")) return;
var $form = $("form");
$form.off('submit');
$form.on('submit', function(e){
e.preventDefault();
var service = easyAbp.eShop.plugins.baskets.basketItems.basketItem;
var basketItems = JSON.parse(localStorage.getItem(localStorageItemKey)) || [];
var index = basketItems.findIndex(x => x.id === '@Model.Id');
basketItems[index].quantity = parseInt(getFormData()['quantity']);
service.generateClientSideData({ items: [ basketItems[index] ] }, {
success: function (responseText, statusText, xhr, form) {
localStorage.setItem(localStorageItemKey, JSON.stringify(basketItems));
$form.trigger('abp-ajax-success',
{
responseText: responseText,
statusText: statusText,
xhr: xhr,
$form: form
})
}
});
});
});
String.prototype.toCamelCase = function() {
return this.replace(/^([A-Z])|\s(\w)/g, function(match, p1, p2, offset) {
if (p2) return p2.toUpperCase();
return p1.toLowerCase();
});
};
function getFormData() {
const PREFIX = "ViewModel.";
return $('form').serializeArray().reduce(function(obj, item) {
obj[item.name.slice(PREFIX.length).toCamelCase()] = item.value;
return obj;
}, {});
}
</script>

19
plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/EditModal.cshtml.cs

@ -1,17 +1,28 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using EasyAbp.EShop.Plugins.Baskets.BasketItems;
using EasyAbp.EShop.Plugins.Baskets.BasketItems.Dtos;
using EasyAbp.EShop.Plugins.Baskets.Permissions;
using EasyAbp.EShop.Plugins.Baskets.Web.Pages.EShop.Plugins.Baskets.BasketItems.BasketItem.ViewModels;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp.Settings;
namespace EasyAbp.EShop.Plugins.Baskets.Web.Pages.EShop.Plugins.Baskets.BasketItems.BasketItem
{
public class EditModalModel : BasketsPageModel
{
[Required]
[HiddenInput]
[BindProperty(SupportsGet = true)]
public string BasketName { get; set; }
[HiddenInput]
[BindProperty(SupportsGet = true)]
public Guid Id { get; set; }
public bool ServerSide { get; set; }
[BindProperty]
public EditBasketItemViewModel ViewModel { get; set; }
@ -25,6 +36,14 @@ namespace EasyAbp.EShop.Plugins.Baskets.Web.Pages.EShop.Plugins.Baskets.BasketIt
public virtual async Task OnGetAsync()
{
ServerSide = await SettingProvider.GetAsync<bool>("EasyAbp.EShop.Plugins.Baskets.EnableServerSideBaskets")
&& await AuthorizationService.IsGrantedAsync(BasketsPermissions.BasketItem.Default);
if (!ServerSide)
{
return;
}
var dto = await _service.GetAsync(Id);
ViewModel = ObjectMapper.Map<BasketItemDto, EditBasketItemViewModel>(dto);
}

5
plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/Index.cshtml

@ -1,4 +1,5 @@
@page
@using System.Security.Principal
@using EasyAbp.EShop.Plugins.Baskets.Permissions
@using EasyAbp.EShop.Plugins.Baskets.Web.Pages.EShop.Plugins.Baskets.BasketItems.BasketItem
@using EasyAbp.EShop.Plugins.Baskets.Localization
@ -36,13 +37,10 @@
<abp-card-title>@L["BasketItem"]</abp-card-title>
</abp-column>
<abp-column size-md="_6" class="text-end">
@if (await Authorization.IsGrantedAsync(BasketsPermissions.BasketItem.Create))
{
<abp-button id="NewBasketItemButton"
text="@L["CreateBasketItem"].Value"
icon="plus"
button-type="Primary" />
}
</abp-column>
</abp-row>
</abp-card-header>
@ -52,7 +50,6 @@
<tr>
<th>@L["Actions"]</th>
<th>@L["BasketItemBasketName"]</th>
<th>@L["BasketItemUserId"]</th>
<th>@L["BasketItemStoreId"]</th>
<th>@L["BasketItemProductId"]</th>
<th>@L["BasketItemProductSkuId"]</th>

8
plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/ViewModels/CreateBasketItemViewModel.cs

@ -8,13 +8,7 @@ namespace EasyAbp.EShop.Plugins.Baskets.Web.Pages.EShop.Plugins.Baskets.BasketIt
{
[Display(Name = "BasketItemBasketName")]
public string BasketName { get; set; } = BasketsConsts.DefaultBasketName;
/// <summary>
/// Specify the basket item owner user ID. Use current user ID if this property is null.
/// </summary>
[Display(Name = "BasketItemUserId")]
public Guid? UserId { get; set; }
[Display(Name = "BasketItemStoreId")]
public Guid StoreId { get; set; }

89
plugins/Baskets/src/EasyAbp.EShop.Plugins.Baskets.Web/Pages/EShop/Plugins/Baskets/BasketItems/BasketItem/index.js

@ -1,22 +1,23 @@
$(function () {
var localStorageItemKey = "EShopBasket:" + basketName;
var l = abp.localization.getResource('EasyAbpEShopPluginsBaskets');
var serverSide = abp.setting.getBoolean('EasyAbp.EShop.Plugins.Baskets.EnableServerSideBaskets')
&& abp.auth.isGranted('EasyAbp.EShop.Plugins.Baskets.BasketItem');
var service = easyAbp.eShop.plugins.baskets.basketItems.basketItem;
var createModal = new abp.ModalManager(abp.appPath + 'EShop/Plugins/Baskets/BasketItems/BasketItem/CreateModal');
var editModal = new abp.ModalManager(abp.appPath + 'EShop/Plugins/Baskets/BasketItems/BasketItem/EditModal');
var dataTable = $('#BasketItemTable').DataTable(abp.libs.datatables.normalizeConfiguration({
var configuration = {
processing: true,
serverSide: true,
paging: true,
searching: false,
autoWidth: false,
scrollCollapse: true,
order: [[1, "asc"]],
ajax: abp.libs.datatables.createAjax(service.getList, function () {
return { basketName: basketName, userId: userId }
}),
columnDefs: [
{
rowAction: {
@ -24,30 +25,34 @@ $(function () {
[
{
text: l('Edit'),
visible: abp.auth.isGranted('EasyAbp.EShop.Plugins.Baskets.BasketItem.Update'),
action: function (data) {
editModal.open({ id: data.record.id });
editModal.open({ basketName: basketName, id: data.record.id });
}
},
{
text: l('Delete'),
visible: abp.auth.isGranted('EasyAbp.EShop.Plugins.Baskets.BasketItem.Delete'),
confirmMessage: function (data) {
return l('BasketItemDeletionConfirmationMessage', data.record.id);
},
action: function (data) {
if (serverSide) {
service.delete(data.record.id)
.then(function () {
abp.notify.info(l('SuccessfullyDeleted'));
dataTable.ajax.reload();
});
.then(function () {
abp.notify.info(l('SuccessfullyDeleted'));
dataTable.ajax.reload();
});
} else {
var cachedItems = JSON.parse(localStorage.getItem(localStorageItemKey)) || [];
cachedItems.splice(cachedItems.findIndex(x => x.id === data.record.id), 1);
localStorage.setItem(localStorageItemKey, JSON.stringify(cachedItems));
location.reload();
}
}
}
]
}
},
{ data: "basketName" },
{ data: "userId" },
{ data: "storeId" },
{ data: "productId" },
{ data: "productSkuId" },
@ -64,15 +69,67 @@ $(function () {
{ data: "inventory" },
{ data: "isInvalid" },
]
}));
};
var dataTable;
if (serverSide) {
configuration.serverSide = true;
configuration.ajax = abp.libs.datatables.createAjax(service.getList, function () {
return { basketName: basketName, userId: userId }
});
var clientSideItems = JSON.parse(localStorage.getItem(localStorageItemKey)) || [];
// Move client-side basket items to server-side.
if (clientSideItems.length > 0) {
localStorage.setItem(localStorageItemKey, JSON.stringify([]));
createManyServerSideBasketItems(clientSideItems);
}
dataTable = $('#BasketItemTable').DataTable(abp.libs.datatables.normalizeConfiguration(configuration));
} else {
configuration.serverSide = false;
var cachedItems = JSON.parse(localStorage.getItem(localStorageItemKey)) || [];
if (cachedItems.length > 0) {
service.generateClientSideData({ items: cachedItems }).then(function (result) {
configuration.data = result.items
dataTable = $('#BasketItemTable').DataTable(abp.libs.datatables.normalizeConfiguration(configuration));
});
} else {
configuration.data = [];
dataTable = $('#BasketItemTable').DataTable(abp.libs.datatables.normalizeConfiguration(configuration));
}
}
createModal.onResult(function () {
dataTable.ajax.reload();
if (serverSide) {
dataTable.ajax.reload();
} else {
location.reload();
}
});
editModal.onResult(function () {
dataTable.ajax.reload();
if (serverSide) {
dataTable.ajax.reload();
} else {
location.reload();
}
});
function createManyServerSideBasketItems(items, autoReloadDataTable = true) {
var item = items.shift();
service.create(item, {
success: function () {
if (items.length > 0) {
createManyServerSideBasketItems(items);
} else if (autoReloadDataTable) {
dataTable.ajax.reload();
}
}
})
}
$('#NewBasketItemButton').click(function (e) {
e.preventDefault();

Loading…
Cancel
Save