diff --git a/src/Tests/Grand.Mapping.Tests/AdminShared/ContentMappingTests.Page_ToModel.verified.txt b/src/Tests/Grand.Mapping.Tests/AdminShared/ContentMappingTests.Page_ToModel.verified.txt index de87b088d..495b64b26 100644 --- a/src/Tests/Grand.Mapping.Tests/AdminShared/ContentMappingTests.Page_ToModel.verified.txt +++ b/src/Tests/Grand.Mapping.Tests/AdminShared/ContentMappingTests.Page_ToModel.verified.txt @@ -16,5 +16,6 @@ MetaDescription: About us, MetaTitle: About Us, SeName: about-us, + ShowCopyButton: false, Id: page-001 } \ No newline at end of file diff --git a/src/Tests/Grand.Web.Store.Tests/Controllers/ShippingControllerTests.cs b/src/Tests/Grand.Web.Store.Tests/Controllers/ShippingControllerTests.cs index a49a2cde4..fbf89ff47 100644 --- a/src/Tests/Grand.Web.Store.Tests/Controllers/ShippingControllerTests.cs +++ b/src/Tests/Grand.Web.Store.Tests/Controllers/ShippingControllerTests.cs @@ -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 { @@ -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); @@ -142,7 +142,7 @@ 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()); @@ -150,4 +150,25 @@ public async Task RestrictionSave_NoChanges_NotUpdateShippingMethod() Assert.IsInstanceOfType(result); _shippingMethodServiceMock.Verify(s => s.UpdateShippingMethod(It.IsAny()), 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 { + [$"restrict_{globalShippingMethod.Id}"] = ["countryId"] + }; + + var result = await _controller.RestrictionSave(form); + + Assert.IsInstanceOfType(result); + Assert.IsFalse(globalShippingMethod.RestrictedCountries.Any(c => c.Id == "countryId")); + _shippingMethodServiceMock.Verify(s => s.UpdateShippingMethod(It.IsAny()), Times.Never); + } } diff --git a/src/Web/Grand.Web.AdminShared/Models/Orders/OrderModel.cs b/src/Web/Grand.Web.AdminShared/Models/Orders/OrderModel.cs index a5e8aff0d..6ae91032a 100644 --- a/src/Web/Grand.Web.AdminShared/Models/Orders/OrderModel.cs +++ b/src/Web/Grand.Web.AdminShared/Models/Orders/OrderModel.cs @@ -345,6 +345,11 @@ public class UploadLicenseModel : BaseModel public string OrderItemId { get; set; } [UIHint("Download")] public string LicenseDownloadId { get; set; } + + /// + /// Set by the controller after a successful save, so the popup view can signal the parent page to refresh. + /// + public bool RefreshPage { get; set; } } public class AddOrderProductModel : BaseModel diff --git a/src/Web/Grand.Web.AdminShared/Models/Orders/PaymentTransactionModel.cs b/src/Web/Grand.Web.AdminShared/Models/Orders/PaymentTransactionModel.cs index b0b91dc00..886229e52 100644 --- a/src/Web/Grand.Web.AdminShared/Models/Orders/PaymentTransactionModel.cs +++ b/src/Web/Grand.Web.AdminShared/Models/Orders/PaymentTransactionModel.cs @@ -95,4 +95,10 @@ public class PaymentTransactionModel : BaseEntityModel [GrandResourceDisplayName("Admin.PaymentTransaction.Fields.PartialRefund.AmountToPaid")] public double AmountToPaid { get; set; } + + /// + /// Set by the controller after a successful partial refund/paid, so the popup view can signal + /// the parent page to refresh. + /// + public bool RefreshPage { get; set; } } \ No newline at end of file diff --git a/src/Web/Grand.Web.AdminShared/Models/Pages/PageModel.cs b/src/Web/Grand.Web.AdminShared/Models/Pages/PageModel.cs index c8320b104..21daa7c8e 100644 --- a/src/Web/Grand.Web.AdminShared/Models/Pages/PageModel.cs +++ b/src/Web/Grand.Web.AdminShared/Models/Pages/PageModel.cs @@ -96,6 +96,12 @@ public class PageModel : BaseEntityModel, ILocalizedModel, I [GrandResourceDisplayName("Admin.Content.Pages.Fields.LimitedToStores")] [UIHint("Stores")] public string[] Stores { get; set; } + + /// + /// 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. + /// + public bool ShowCopyButton { get; set; } } public class PageLocalizedModel : ILocalizedModelLocal, ISlugModelLocal diff --git a/src/Web/Grand.Web.Store/Areas/Store/Views/Blog/Comments.cshtml b/src/Web/Grand.Web.Store/Areas/Store/Views/Blog/Comments.cshtml index 16f1e41a0..6a3b380f9 100644 --- a/src/Web/Grand.Web.Store/Areas/Store/Views/Blog/Comments.cshtml +++ b/src/Web/Grand.Web.Store/Areas/Store/Views/Blog/Comments.cshtml @@ -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; }
diff --git a/src/Web/Grand.Web.Store/Areas/Store/Views/MessageTemplate/Edit.cshtml b/src/Web/Grand.Web.Store/Areas/Store/Views/MessageTemplate/Edit.cshtml index e47a3d174..24a98da06 100644 --- a/src/Web/Grand.Web.Store/Areas/Store/Views/MessageTemplate/Edit.cshtml +++ b/src/Web/Grand.Web.Store/Areas/Store/Views/MessageTemplate/Edit.cshtml @@ -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; }
diff --git a/src/Web/Grand.Web.Store/Areas/Store/Views/Order/UploadLicenseFilePopup.cshtml b/src/Web/Grand.Web.Store/Areas/Store/Views/Order/UploadLicenseFilePopup.cshtml index 3b6571398..5ed1dfa16 100644 --- a/src/Web/Grand.Web.Store/Areas/Store/Views/Order/UploadLicenseFilePopup.cshtml +++ b/src/Web/Grand.Web.Store/Areas/Store/Views/Order/UploadLicenseFilePopup.cshtml @@ -27,7 +27,7 @@
- @if (ViewBag.RefreshPage == true) + @if (Model.RefreshPage) {