Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@
MetaDescription: About us,
MetaTitle: About Us,
SeName: about-us,
ShowCopyButton: false,
Id: page-001
}
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public async Task RestrictionSave_AddRestriction_UpdateShippingMethod()
{
var country = new Country { Id = "countryId", Name = "Poland" };
var customerGroup = new CustomerGroup { Name = "Guests" };
var shippingMethod = new ShippingMethod { Name = "Ground" };
var shippingMethod = new ShippingMethod { Name = "Ground", StoreId = StoreId };
SetupCommonData(country, shippingMethod, customerGroup);

var form = new Dictionary<string, string[]> {
Expand All @@ -124,7 +124,7 @@ public async Task RestrictionSave_NoFormValues_ClearExistingRestrictions()
{
var country = new Country { Id = "countryId", Name = "Poland" };
var customerGroup = new CustomerGroup { Name = "Guests" };
var shippingMethod = new ShippingMethod { Name = "Ground" };
var shippingMethod = new ShippingMethod { Name = "Ground", StoreId = StoreId };
shippingMethod.RestrictedCountries.Add(country);
shippingMethod.RestrictedGroups.Add(customerGroup.Id);
SetupCommonData(country, shippingMethod, customerGroup);
Expand All @@ -142,12 +142,33 @@ public async Task RestrictionSave_NoChanges_NotUpdateShippingMethod()
{
var country = new Country { Id = "countryId", Name = "Poland" };
var customerGroup = new CustomerGroup { Name = "Guests" };
var shippingMethod = new ShippingMethod { Name = "Ground" };
var shippingMethod = new ShippingMethod { Name = "Ground", StoreId = StoreId };
SetupCommonData(country, shippingMethod, customerGroup);

var result = await _controller.RestrictionSave(new Dictionary<string, string[]>());

Assert.IsInstanceOfType<RedirectToActionResult>(result);
_shippingMethodServiceMock.Verify(s => s.UpdateShippingMethod(It.IsAny<ShippingMethod>()), Times.Never);
}

[TestMethod]
public async Task RestrictionSave_GlobalShippingMethod_NotUpdated()
{
// GetAllShippingMethods(storeId) also returns global (StoreId=="") shipping methods, shared by
// every store - RestrictionSave must not mutate restrictions on a method it doesn't exclusively own.
var country = new Country { Id = "countryId", Name = "Poland" };
var customerGroup = new CustomerGroup { Name = "Guests" };
var globalShippingMethod = new ShippingMethod { Name = "Ground", StoreId = "" };
SetupCommonData(country, globalShippingMethod, customerGroup);

var form = new Dictionary<string, string[]> {
[$"restrict_{globalShippingMethod.Id}"] = ["countryId"]
};

var result = await _controller.RestrictionSave(form);

Assert.IsInstanceOfType<RedirectToActionResult>(result);
Assert.IsFalse(globalShippingMethod.RestrictedCountries.Any(c => c.Id == "countryId"));
_shippingMethodServiceMock.Verify(s => s.UpdateShippingMethod(It.IsAny<ShippingMethod>()), Times.Never);
}
}
5 changes: 5 additions & 0 deletions src/Web/Grand.Web.AdminShared/Models/Orders/OrderModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,11 @@ public class UploadLicenseModel : BaseModel
public string OrderItemId { get; set; }

[UIHint("Download")] public string LicenseDownloadId { get; set; }

/// <summary>
/// Set by the controller after a successful save, so the popup view can signal the parent page to refresh.
/// </summary>
public bool RefreshPage { get; set; }
}

public class AddOrderProductModel : BaseModel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,10 @@ public class PaymentTransactionModel : BaseEntityModel

[GrandResourceDisplayName("Admin.PaymentTransaction.Fields.PartialRefund.AmountToPaid")]
public double AmountToPaid { get; set; }

/// <summary>
/// Set by the controller after a successful partial refund/paid, so the popup view can signal
/// the parent page to refresh.
/// </summary>
public bool RefreshPage { get; set; }
}
6 changes: 6 additions & 0 deletions src/Web/Grand.Web.AdminShared/Models/Pages/PageModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,12 @@ public class PageModel : BaseEntityModel, ILocalizedModel<PageLocalizedModel>, I
[GrandResourceDisplayName("Admin.Content.Pages.Fields.LimitedToStores")]
[UIHint("Stores")]
public string[] Stores { get; set; }

/// <summary>
/// True when the page is global or shared with more than one store, so a store manager may copy it
/// into their own store instead of editing it directly.
/// </summary>
public bool ShowCopyButton { get; set; }
}

public class PageLocalizedModel : ILocalizedModelLocal, ISlugModelLocal
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
@inject AdminAreaSettings adminAreaSettings
@using Grand.Web.Store.Models.Blogs
@model BlogCommentListModel
@inject AdminAreaSettings adminAreaSettings
@{
//page title
ViewBag.Title = Loc["Admin.Content.Blog.Comments"];
string filterByBlogPostId = ViewBag.FilterByBlogPostId;
var filterByBlogPostId = Model.FilterByBlogPostId;
}

<div class="row">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
@model MessageTemplateModel
@model MessageTemplateStoreModel
@{
ViewBag.Title = Loc["Admin.Content.MessageTemplates.EditMessageTemplateDetails"];
Layout = Constants.LayoutStore;
var isReadOnly = (bool)(ViewBag.IsReadOnly ?? false);
var isReadOnly = Model.IsReadOnly;
}
<form asp-area="@Constants.AreaStore" asp-controller="MessageTemplate" asp-action="Edit" method="post">

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
</div>
</div>
<div asp-validation-summary="All"></div>
@if (ViewBag.RefreshPage == true)
@if (Model.RefreshPage)
{
<script>
try {
Expand Down
4 changes: 2 additions & 2 deletions src/Web/Grand.Web.Store/Areas/Store/Views/Page/Edit.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
<button class="btn btn-success" type="submit" name="save-continue">
<i class="fa fa-check-circle"></i> @Loc["Admin.Common.SaveContinue"]
</button>
@if (ViewBag.ShowCopyButton == true)
@if (Model.ShowCopyButton)
{
<button type="submit" form="page-copy-form" class="btn blue">
<i class="fa fa-copy"></i> @Loc["Admin.Common.Copy"]
Expand All @@ -52,7 +52,7 @@
</div>
</form>
<admin-delete-confirmation button-id="page-delete"/>
@if (ViewBag.ShowCopyButton == true)
@if (Model.ShowCopyButton)
{
<form id="page-copy-form" asp-area="@Constants.AreaStore" asp-controller="Page" asp-action="Copy" method="post">
<input type="hidden" name="id" value="@Model.Id"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
</div>

<div asp-validation-summary="All"></div>
@if (ViewBag.RefreshPage == true)
@if (Model.RefreshPage)
{
<script>
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
</div>

<div asp-validation-summary="All"></div>
@if (ViewBag.RefreshPage == true)
@if (Model.RefreshPage)
{
<script>
try {
Expand Down
13 changes: 3 additions & 10 deletions src/Web/Grand.Web.Store/Controllers/BlogController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using Grand.Web.Common.DataSource;
using Grand.Web.Common.Filters;
using Grand.Web.Common.Security.Authorization;
using Grand.Web.Store.Models.Blogs;
using Microsoft.AspNetCore.Mvc;

namespace Grand.Web.Store.Controllers;
Expand Down Expand Up @@ -92,7 +93,6 @@ public async Task<IActionResult> List(DataSourceRequest command)
[PermissionAuthorizeAction(PermissionActionName.Create)]
public async Task<IActionResult> Create()
{
ViewBag.AllLanguages = await _languageService.GetAllLanguages(true);
var model = new BlogPostModel {
//default values
AllowComments = true,
Expand All @@ -118,7 +118,6 @@ public async Task<IActionResult> Create(BlogPostModel model, bool continueEditin
}

//If we got this far, something failed, redisplay form
ViewBag.AllLanguages = await _languageService.GetAllLanguages(true);
return View(model);
}

Expand All @@ -142,7 +141,6 @@ public async Task<IActionResult> Edit(string id)
return RedirectToAction("List");
}

ViewBag.AllLanguages = await _languageService.GetAllLanguages(true);
var model = blogPost.ToModel(_dateTimeService);

//locales
Expand Down Expand Up @@ -188,7 +186,6 @@ public async Task<IActionResult> Edit(BlogPostModel model, bool continueEditing)
}

//If we got this far, something failed, redisplay form
ViewBag.AllLanguages = await _languageService.GetAllLanguages(true);
return View(model);
}

Expand Down Expand Up @@ -285,8 +282,8 @@ public async Task<IActionResult> PicturePopup(PictureModel model)

public IActionResult Comments(string filterByBlogPostId)
{
ViewBag.FilterByBlogPostId = filterByBlogPostId;
return View();
var model = new BlogCommentListModel { FilterByBlogPostId = filterByBlogPostId };
return View(model);
}

[PermissionAuthorizeAction(PermissionActionName.List)]
Expand Down Expand Up @@ -450,7 +447,6 @@ public async Task<IActionResult> CategoryList(DataSourceRequest command)
[PermissionAuthorizeAction(PermissionActionName.Create)]
public async Task<IActionResult> CategoryCreate()
{
ViewBag.AllLanguages = await _languageService.GetAllLanguages(true);
var model = new BlogCategoryModel();
//locales
await AddLocales(_languageService, model.Locales);
Expand Down Expand Up @@ -480,7 +476,6 @@ public async Task<IActionResult> CategoryCreate(BlogCategoryModel model, bool co
}

//If we got this far, something failed, redisplay form
ViewBag.AllLanguages = await _languageService.GetAllLanguages(true);
//locales
await AddLocales(_languageService, model.Locales);
return View(model);
Expand All @@ -497,7 +492,6 @@ public async Task<IActionResult> CategoryEdit(string id)
if (!blogCategory.AccessToEntityByStore(_contextAccessor.WorkContext.CurrentCustomer.StaffStoreId))
return RedirectToAction(CategoryListAction);

ViewBag.AllLanguages = await _languageService.GetAllLanguages(true);
var model = blogCategory.ToModel();
//locales
await AddLocales(_languageService, model.Locales, (locale, languageId) =>
Expand Down Expand Up @@ -542,7 +536,6 @@ public async Task<IActionResult> CategoryEdit(BlogCategoryModel model, bool cont
}

//If we got this far, something failed, redisplay form
ViewBag.AllLanguages = await _languageService.GetAllLanguages(true);

//locales
await AddLocales(_languageService, model.Locales, (locale, languageId) =>
Expand Down
33 changes: 31 additions & 2 deletions src/Web/Grand.Web.Store/Controllers/CategoryController.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Grand.Business.Core.Extensions;
using Grand.Business.Core.Interfaces.Catalog.Categories;
using Grand.Business.Core.Interfaces.Catalog.Products;
using Grand.Business.Core.Interfaces.Common.Localization;
using Grand.Domain.Permissions;
using Grand.Infrastructure;
Expand All @@ -26,14 +27,16 @@ public CategoryController(
ILanguageService languageService,
ITranslationService translationService,
IContextAccessor contextAccessor,
IPictureViewModelService pictureViewModelService)
IPictureViewModelService pictureViewModelService,
IProductService productService)
{
_categoryService = categoryService;
_categoryViewModelService = categoryViewModelService;
_languageService = languageService;
_translationService = translationService;
_contextAccessor = contextAccessor;
_pictureViewModelService = pictureViewModelService;
_productService = productService;
}

#endregion
Expand All @@ -46,6 +49,7 @@ public CategoryController(
private readonly ITranslationService _translationService;
private readonly IContextAccessor _contextAccessor;
private readonly IPictureViewModelService _pictureViewModelService;
private readonly IProductService _productService;

#endregion

Expand Down Expand Up @@ -276,6 +280,10 @@ public async Task<IActionResult> ProductList(DataSourceRequest command, string c
[PermissionAuthorizeAction(PermissionActionName.Edit)]
public async Task<IActionResult> ProductUpdate(CategoryModel.CategoryProductModel model)
{
var product = await _productService.GetProductById(model.ProductId);
if (product == null || !product.AccessToEntityByStore(_contextAccessor.WorkContext.CurrentCustomer.StaffStoreId))
return ErrorForKendoGridJson("This is not your product");

if (ModelState.IsValid)
{
await _categoryViewModelService.UpdateProductCategoryModel(model);
Expand All @@ -288,6 +296,10 @@ public async Task<IActionResult> ProductUpdate(CategoryModel.CategoryProductMode
[PermissionAuthorizeAction(PermissionActionName.Edit)]
public async Task<IActionResult> ProductDelete(CategoryModel.CategoryProductModel model)
{
var product = await _productService.GetProductById(model.ProductId);
if (product == null || !product.AccessToEntityByStore(_contextAccessor.WorkContext.CurrentCustomer.StaffStoreId))
return ErrorForKendoGridJson("This is not your product");

if (ModelState.IsValid)
{
await _categoryViewModelService.DeleteProductCategoryModel(model.Id, model.ProductId);
Expand Down Expand Up @@ -322,9 +334,26 @@ public async Task<IActionResult> ProductAddPopupList(DataSourceRequest command,
[HttpPost]
public async Task<IActionResult> ProductAddPopup(CategoryModel.AddCategoryProductModel model)
{
var category = await _categoryService.GetCategoryById(model.CategoryId);
if (category == null || !category.AccessToEntityByStore(_contextAccessor.WorkContext.CurrentCustomer.StaffStoreId))
return Content("This is not your category");

if (ModelState.IsValid)
{
if (model.SelectedProductIds != null) await _categoryViewModelService.InsertCategoryProductModel(model);
//InsertCategoryProductModel mutates each selected product's ProductCategories collection,
//so every selected id must also belong to the current store.
if (model.SelectedProductIds != null)
{
var validIds = new List<string>();
foreach (var id in model.SelectedProductIds)
{
var selected = await _productService.GetProductById(id);
if (selected != null && selected.AccessToEntityByStore(_contextAccessor.WorkContext.CurrentCustomer.StaffStoreId))
validIds.Add(id);
}
model.SelectedProductIds = validIds.ToArray();
if (validIds.Any()) await _categoryViewModelService.InsertCategoryProductModel(model);
}

return Content("");
}
Expand Down
Loading
Loading