Presenter till kaffeälskeren
Hitta den perfekta presenten till den som föredrar sitt kaffe rykande varmt eller isande kallt – tillsammans med en bok i soffan eller på språng..
Error executing template "/Designs/Swift/Paragraph/Swift_ProductHeader_Custom_v2.cshtml" System.NullReferenceException: Object reference not set to an instance of an object. at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.CreateView(ProductViewModelSettings settings, ProductFieldValue pfv) at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.GetProductFieldValues(ProductViewModelSettings settings, Product product) at System.Lazy`1.CreateValue() at System.Lazy`1.LazyInitValue() at CompiledRazorTemplates.Dynamic.RazorEngine_a54ea8a4f1074c649f86f0e8463ffd4c.Execute() in E:\Solutions\Eva Solo\Files\Templates\Designs\Swift\Paragraph\Swift_ProductHeader_Custom_v2.cshtml:line 41 at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader) at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer) at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter) at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template) at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template) at Dynamicweb.Rendering.Template.RenderRazorTemplate()
1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 2 @using Dynamicweb.Ecommerce.ProductCatalog 3 @using Dynamicweb.Core @* CUSTOM *@ 4 5 @* CUSTOMIZED STANDARD SWIFT (v1.25.0) TEMPLATE *@ 6 7 @{ 8 ProductViewModel product = null; 9 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 10 { 11 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 12 } 13 else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode) 14 { 15 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 16 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 17 18 if (productList?.Products is object) 19 { 20 product = productList.Products[0]; 21 } 22 } 23 } 24 25 @if (product is object) 26 { 27 string titleFontSize = Model.Item.GetRawValueString("FontSize", "fs-6"); 28 string horizontalAlign = Model.Item.GetRawValueString("HorizontalAlignment", ""); 29 horizontalAlign = horizontalAlign == "center" ? "text-center" : horizontalAlign; 30 horizontalAlign = horizontalAlign == "end" ? "text-end" : horizontalAlign; 31 32 string headingLevel = Model.Item.GetString("HeadingLevel", "h2"); 33 string headingLevelStart = $"<{headingLevel} class=\"{titleFontSize} {horizontalAlign} m-0 item_{Model.Item.SystemName.ToLower()}\" itemprop=\"name\">"; 34 string headingLevelStop = $"</{headingLevel}>"; 35 36 // CUSTOM 37 string brandLogo = Model.Item.GetString("Custom_BrandLogo"); 38 string brandLogoKey = Model.Item.GetString("Custom_BrandLogoKey"); 39 string brandLogoAltText = Model.Item.GetString("Custom_BrandAltText"); 40 int brandLogoWidth = Model.Item.GetInt32("Custom_BrandLogoWidth") > 0 ? Model.Item.GetInt32("Custom_BrandLogoWidth") : 70; 41 string productBrand = product.ProductFields.ContainsKey("Custom_Brand") ? Converter.ToString(product.ProductFields["Custom_Brand"].Value) : ""; 42 bool enableBrandLogo = !string.IsNullOrEmpty(brandLogo) && !string.IsNullOrEmpty(brandLogoKey) && brandLogoKey == productBrand; 43 44 if (enableBrandLogo) 45 { 46 <img src="@Dynamicweb.Core.Encoders.HtmlEncoder.HtmlAttributeEncode(brandLogo)" 47 alt="@Dynamicweb.Core.Encoders.HtmlEncoder.HtmlAttributeEncode(brandLogoAltText)" 48 width="@Dynamicweb.Core.Encoders.HtmlEncoder.HtmlAttributeEncode(brandLogoWidth.ToString())" /> 49 } 50 // CUSTOM END 51 52 @headingLevelStart 53 @product.Name 54 @headingLevelStop 55 } 56 else if (Pageview.IsVisualEditorMode) 57 { 58 <div class="alert alert-dark m-0">@Translate("No products available")</div> 59 } 60
Error executing template "Designs/Swift/Paragraph/Swift_ProductBadges_Custom.cshtml" System.NullReferenceException: Object reference not set to an instance of an object. at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.CreateView(ProductViewModelSettings settings, ProductFieldValue pfv) at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.GetProductFieldValues(ProductViewModelSettings settings, Product product) at System.Lazy`1.CreateValue() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Lazy`1.get_Value() at CompiledRazorTemplates.Dynamic.RazorEngine_fe4e63c166214874a0bcb86da4f14f88.Execute() in E:\Solutions\Eva Solo\Files\Templates\Designs\Swift\Paragraph\Swift_ProductBadges_Custom.cshtml:line 27 at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader) at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer) at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter) at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template) at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template) at Dynamicweb.Rendering.Template.RenderRazorTemplate()
1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 2 @using System 3 @using System.Collections.Generic 4 @using System.Linq 5 @using Dynamicweb.Frontend 6 @using Dynamicweb.Content 7 @using Dynamicweb.Core 8 @using Dynamicweb.Ecommerce.ProductCatalog 9 10 @{ 11 ProductViewModel product = null; 12 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 13 { 14 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 15 } 16 else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode) 17 { 18 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 19 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 20 21 if (productList?.Products is object) 22 { 23 product = productList.Products[0]; 24 } 25 } 26 27 DateTime launchDate = product.ProductFields.ContainsKey("Custom_LaunchDate") ? Converter.ToDateTime(product.ProductFields["Custom_LaunchDate"].Value) : DateTime.MinValue; 28 DateTime currentDate = DateTime.Today; 29 bool showComingSoonBadge = currentDate < launchDate && string.Equals( Model.Item.GetRawValueString("NewBadgeDesign"), "comingsoon", StringComparison.InvariantCultureIgnoreCase ); 30 } 31 32 @if (product is object) 33 { 34 var badgeParms = new Dictionary<string, object>(); 35 badgeParms.Add("size", "h7"); 36 badgeParms.Add("saleBadgeType", Model.Item.GetRawValue("SaleBadgeType")); 37 badgeParms.Add("saleBadgeCssClassName", Model.Item.GetRawValue("SaleBadgeDesign")); 38 badgeParms.Add("newBadgeCssClassName", Model.Item.GetRawValue("NewBadgeDesign")); 39 badgeParms.Add("newPublicationDays", Model.Item.GetInt32("NewPublicationDays")); 40 badgeParms.Add("campaignBadgesValues", Model.Item.GetRawValueString("CampaignBadges")); 41 42 string badgeSize = Model.Item.GetRawValueString("BadgeSize", "fs-2"); 43 string horizontalAlign = Model.Item.GetRawValueString("HorizontalAlignment", ""); 44 horizontalAlign = horizontalAlign == "center" ? "text-center" : horizontalAlign; 45 horizontalAlign = horizontalAlign == "end" ? "text-end" : horizontalAlign; 46 47 Dictionary<string, ParagraphInfoViewModel> badgeConfigurations; 48 List<string> campaignBadgesValues = Model.Item.GetRawValueString("CampaignBadges") != null ? Model.Item.GetRawValueString("CampaignBadges").Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() : new List<string>(); 49 50 if (Dynamicweb.Context.Current.Items.Contains("badgeConfigurations")) 51 { 52 badgeConfigurations = (Dictionary<string, ParagraphInfoViewModel>)Dynamicweb.Context.Current.Items["badgeConfigurations"]; 53 } 54 else 55 { 56 var badgesPage = Pageview.AreaSettings.GetLink("EcommerceBadgesPage") != null ? Pageview.AreaSettings.GetLink("EcommerceBadgesPage").PageId : 0; 57 var allBadges = badgesPage != 0 ? Dynamicweb.Content.Services.Paragraphs.GetParagraphsByPageId(badgesPage) : null; 58 59 badgeConfigurations = new Dictionary<string, ParagraphInfoViewModel>(); 60 61 if ( allBadges != null ) 62 { 63 foreach ( Paragraph badge in allBadges ) 64 { 65 var paragraphviewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreateParagraphInfoViewModel( badge ); 66 string cssClassName = paragraphviewModel.Item.GetString( "CssClassName" )?.Trim().ToLower() ?? string.Empty;; 67 if ( !badgeConfigurations.ContainsKey( cssClassName ) ) 68 { 69 badgeConfigurations.Add( cssClassName, paragraphviewModel ); 70 } 71 } 72 } 73 74 Dynamicweb.Context.Current.Items.Add("badgeConfigurations", badgeConfigurations); 75 } 76 77 int badgesCount = 0; 78 if (badgeConfigurations.Any()) 79 { 80 foreach (string campaign in campaignBadgesValues) 81 { 82 if (!string.IsNullOrEmpty(campaign)) 83 { 84 FieldValueViewModel availableCampaignsObject; 85 product.ProductFields.TryGetValue("Campaign", out availableCampaignsObject); 86 87 if (availableCampaignsObject != null) 88 { 89 string campaignType = string.Empty; 90 91 if (badgeConfigurations.ContainsKey(campaign)) 92 { 93 ParagraphInfoViewModel paragraphviewModel; 94 if (badgeConfigurations.TryGetValue(campaign, out paragraphviewModel)) 95 { 96 campaignType = paragraphviewModel.Item.GetRawValueString("CampaignType"); 97 } 98 } 99 100 List<FieldOptionValueViewModel> availableCampaigns = (List<FieldOptionValueViewModel>)availableCampaignsObject.Value; 101 102 foreach (FieldOptionValueViewModel availableOption in availableCampaigns) 103 { 104 if (campaignType == availableOption.Value) 105 { 106 badgesCount++; 107 break; 108 } 109 } 110 } 111 } 112 } 113 } 114 115 bool saleBadgeEnabled = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("SaleBadgeDesign")) && Model.Item.GetRawValueString("SaleBadgeDesign") != "none" ? true : false; 116 bool newBadgeEnabled = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("NewBadgeDesign")) && Model.Item.GetRawValueString("NewBadgeDesign") != "none" ? true : false; 117 DateTime createdDate = product.Created.Value; 118 bool showBadges = saleBadgeEnabled && product.Discount.Price != 0 ? true : false; 119 showBadges = (newBadgeEnabled && Model.Item.GetInt32("NewPublicationDays") == 0) || (newBadgeEnabled && (createdDate.AddDays(Model.Item.GetInt32("NewPublicationDays")) > DateTime.Now)) ? true : showBadges; 120 showBadges = (!string.IsNullOrEmpty(Model.Item.GetRawValueString("CampaignBadges")) && badgesCount != 0) || showComingSoonBadge || showBadges; 121 122 if (showBadges) 123 { 124 <div class="@badgeSize @horizontalAlign item_@Model.Item.SystemName.ToLower()"> 125 @RenderPartial("Components/EcommerceBadge_Custom.cshtml", product, badgeParms) @*//CUSTOM*@ 126 </div> 127 } 128 else if (Pageview.IsVisualEditorMode) 129 { 130 <span class="badge bg-success text-light rounded-0">@Translate("Badge example")</span> 131 } 132 } 133 else if (Pageview.IsVisualEditorMode) 134 { 135 <span class="badge bg-success text-light rounded-0">@Translate("Badge example")</span> 136 } 137 138
Error executing template "/Designs/Swift/Paragraph/Swift_Custom_ProductFacts.cshtml" System.NullReferenceException: Object reference not set to an instance of an object. at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.CreateView(ProductViewModelSettings settings, ProductFieldValue pfv) at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.GetProductFieldValues(ProductViewModelSettings settings, Product product) at System.Lazy`1.CreateValue() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Lazy`1.get_Value() at CompiledRazorTemplates.Dynamic.RazorEngine_1a53976adc1341c7bf928b5d5d9b625c.Execute() in E:\Solutions\Eva Solo\Files\Templates\Designs\Swift\Paragraph\Swift_Custom_ProductFacts.cshtml:line 90 at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader) at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer) at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter) at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template) at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template) at Dynamicweb.Rendering.Template.RenderRazorTemplate()
1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 2 @using System 3 @using System.Collections.Generic 4 @using System.Linq 5 @using Dynamicweb.Ecommerce.ProductCatalog 6 7 @* CUSTOM TEMPLATE SUPPORTED BY SWIFT (v1.25.0) - NOTE: THIS TEMPLATE IS NOT SUPPORTED IN DW10 *@ 8 9 @{ 10 bool isVisualEditor = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("VisualEdit")) ? Convert.ToBoolean(Dynamicweb.Context.Current.Request.QueryString.Get("VisualEdit")) : false; 11 12 ProductViewModel product = new ProductViewModel(); 13 14 ProductViewModelSettings productSetting = new ProductViewModelSettings 15 { 16 LanguageId = Dynamicweb.Ecommerce.Common.Context.LanguageID, 17 CurrencyCode = Dynamicweb.Ecommerce.Common.Context.Currency.Code, 18 CountryCode = Dynamicweb.Ecommerce.Common.Context.Country.Code2, 19 ShopId = Pageview.Area.EcomShopId 20 }; 21 22 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 23 { 24 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 25 } 26 else if (Pageview.Item["DummyProduct"] != null) 27 { 28 29 string dummyProductId = ""; 30 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 31 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 32 if (productList.Products != null) 33 { 34 foreach (var p in productList.Products) { dummyProductId = p.Id; } 35 ProductViewModel dummyProduct = dummyProductId != "" ? ViewModelFactory.CreateView(productSetting, dummyProductId) : new ProductViewModel(); 36 product = dummyProduct; 37 } 38 else 39 { 40 product = ViewModelFactory.CreateView(productSetting, Dynamicweb.Ecommerce.Services.Products.GetLastActiveProducts(1, Dynamicweb.Ecommerce.Common.Context.LanguageID, false).FirstOrDefault().Id); 41 } 42 } 43 else if (Pageview.Item["DummyProduct"] == null) 44 { 45 product = ViewModelFactory.CreateView(productSetting, Dynamicweb.Ecommerce.Services.Products.GetLastActiveProducts(1, Dynamicweb.Ecommerce.Common.Context.LanguageID, false).FirstOrDefault().Id); 46 } 47 } 48 49 @if (product?.Id != null) 50 { 51 IEnumerable<string> selectedDisplayGroupIds = Model.Item.GetRawValueString("DisplayGroups").Split(',').ToList(); 52 List<CategoryFieldViewModel> displayGroups = new List<CategoryFieldViewModel>(); 53 54 foreach (var selection in selectedDisplayGroupIds) 55 { 56 foreach (CategoryFieldViewModel group in product.FieldDisplayGroups.Values) 57 { 58 if (selection == group.Id) 59 { 60 displayGroups.Add(group); 61 } 62 } 63 } 64 65 bool showProductFields = Model.Item.GetBoolean("ProductFields"); 66 67 bool hideTitle = Model.Item.GetBoolean("HideTitle"); 68 69 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 70 71 string titleFontSize = Model.Item.GetRawValueString("TitleFontSize", "display-4"); 72 73 string contentPadding = Model.Item.GetRawValueString("ContentPadding", ""); 74 contentPadding = contentPadding == "small" ? "p-2 p-md-3" : contentPadding; 75 contentPadding = contentPadding == "large" ? "p-4 p-md-5" : contentPadding; 76 77 string layout = Model.Item.GetRawValueString("Layout", "list"); 78 string size = Model.Item.GetRawValueString("Size", "full"); 79 80 if (Pageview.IsVisualEditorMode && displayGroups.Count() == 0) 81 { 82 product.ProductFields.Clear(); 83 product.ProductFields.Add(Translate("Width"), new FieldValueViewModel { Name = Translate("Width"), Value = "99cm" }); 84 product.ProductFields.Add(Translate("Height"), new FieldValueViewModel { Name = Translate("Height"), Value = "195cm" }); 85 showProductFields = true; 86 } 87 88 <div class="@(theme) h-100 item_@Model.Item.SystemName.ToLower()" id="specifications"> 89 <div class="@contentPadding"> 90 @if ((product.ProductFields != null && Model.Item.GetBoolean("ProductFields")) || (product.ProductCategories != null && Model.Item.GetBoolean("CategoryFields")) || (displayGroups.Count != 0)) 91 { 92 if (!hideTitle) 93 { 94 <div class="text-start pb-2 pb-lg-4"> 95 <h2 class="@titleFontSize">@Model.Item.GetString("Title")</h2> 96 </div> 97 } 98 } 99 100 @if (displayGroups.Count != 0) 101 { 102 foreach (var group in displayGroups) 103 { 104 <div class="order-5 order-lg-0"> 105 <dl class="grid gap-0"> 106 @foreach (var field in group.Fields) 107 { 108 @RenderField(field.Value, layout) 109 } 110 </dl> 111 </div> 112 } 113 } 114 115 @if (product.ProductFields != null && showProductFields) 116 { 117 if (product.ProductFields.Count > 0) 118 { 119 @RenderFieldsFromList(product.ProductFields, layout); 120 } 121 } 122 123 @if (product.ProductCategories != null && Model.Item.GetBoolean("CategoryFields")) 124 { 125 if (product.ProductCategories.Count > 0) 126 { 127 foreach (var group in product.ProductCategories) 128 { 129 CategoryFieldViewModel category = group.Value; 130 bool hideHeader = Model.Item.GetBoolean("HideGroupHeaders"); 131 132 if (!hideHeader) 133 { 134 <h4 class="h4 mb-4">@group.Value.Name</h4> 135 } 136 137 @RenderFieldsFromList(category.Fields, layout); 138 } 139 } 140 } 141 </div> 142 </div> 143 } 144 else if (Pageview.IsVisualEditorMode) 145 { 146 <div class="alert alert-warning m-0">@Translate("No products available")</div> 147 } 148 149 150 @helper RenderFieldsFromList(Dictionary<string, FieldValueViewModel> fields, string layout) 151 { 152 string size = Model.Item.GetRawValueString("Size", "full"); 153 string extraMargin = size == "full" ? "mb-3" : ""; 154 bool hideFieldLabels = Model.Item.GetBoolean("HideFieldLabels"); 155 156 <div class="@extraMargin"> 157 @if (layout == "columns") 158 { 159 string gaps = size == "full" ? "gap-0" : "gap-2"; 160 161 <div class="grid @gaps"> 162 @foreach (var field in fields) 163 { 164 @RenderField(field.Value, layout) 165 } 166 </div> 167 } 168 @if (layout == "list") 169 { 170 <dl class="grid gap-0"> 171 @foreach (var field in fields) 172 { 173 @RenderField(field.Value, layout) 174 } 175 </dl> 176 } 177 @if (layout == "table") 178 { 179 string tableSize = size == "full" ? "" : "table-sm"; 180 181 <table class="table table-striped @tableSize"> 182 @foreach (var field in fields) 183 { 184 @RenderField(field.Value, layout) 185 } 186 </table> 187 } 188 @if (layout == "bullets") 189 { 190 string listSize = size == "full" ? "" : "m-0 p-0 lh-1 fs-7 opacity-75"; 191 string listStyle = size == "full" ? "" : "style=\"list-style-position: inside\""; 192 193 <ul class="@listSize" @listStyle> 194 @foreach (var field in fields) 195 { 196 @RenderField(field.Value, layout) 197 } 198 </ul> 199 } 200 @if (layout == "commas") 201 { 202 List<string> featuresList = new List<string>(); 203 204 foreach (var field in fields) 205 { 206 if (field.Value.Value.GetType() == typeof(System.Collections.Generic.List<FieldOptionValueViewModel>)) 207 { 208 List<string> options = new List<string>(); 209 foreach (FieldOptionValueViewModel option in field.Value.Value as System.Collections.Generic.List<FieldOptionValueViewModel>) 210 { 211 if (!string.IsNullOrWhiteSpace(option.Value)) 212 { 213 if (option.Value.ToString().Contains("#") && (Translate(field.Value.Name) == Translate("Color") || Translate(field.Value.Name) == Translate("Colour"))) 214 { 215 string colorSpan = "<span class=\"colorbox-sm\" style=\"background-color: " + option.Value + "\"></span>"; 216 options.Add(colorSpan); 217 } 218 else if (!string.IsNullOrEmpty(option.Value)) 219 { 220 options.Add(option.Name); 221 } 222 } 223 } 224 string optionsString = (string.Join(", ", options.Select(x => x.ToString()).ToArray())); 225 if ((Translate(field.Value.Name) == Translate("Color") || Translate(field.Value.Name) == Translate("Colour"))) 226 { 227 optionsString = (string.Join(" ", options.Select(x => x.ToString()).ToArray())); 228 } 229 230 if (!hideFieldLabels) 231 { 232 featuresList.Add(field.Value.Name + ": " + optionsString); 233 } 234 else 235 { 236 featuresList.Add(optionsString); 237 } 238 } 239 else 240 { 241 if (!string.IsNullOrWhiteSpace(field.Value.Value.ToString())) 242 { 243 if (field.Value.Value.ToString().Contains("#") && (Translate(field.Value.Name) == Translate("Color") || Translate(field.Value.Name) == Translate("Colour"))) 244 { 245 string colorSpan = "<span class=\"colorbox-sm\" style=\"background-color: " + field.Value.Value + "\"></span>"; 246 247 if (!hideFieldLabels) 248 { 249 featuresList.Add(field.Value.Name + ": " + colorSpan); 250 } 251 else 252 { 253 featuresList.Add(colorSpan); 254 } 255 } 256 else 257 { 258 if (!hideFieldLabels) 259 { 260 featuresList.Add(field.Value.Name + ": " + field.Value.Value.ToString()); 261 } 262 else 263 { 264 featuresList.Add(field.Value.Value.ToString()); 265 } 266 } 267 } 268 } 269 } 270 271 string featuresString = (string.Join(", ", featuresList.Select(x => x.ToString()).ToArray())); 272 273 <div class="opacity-75 fs-7">@featuresString</div> 274 } 275 </div> 276 } 277 278 @helper RenderField(FieldValueViewModel field, string layout) 279 { 280 string size = Model.Item.GetRawValueString("Size", "full"); 281 string fieldValue = field?.Value != null ? field.Value.ToString() : ""; 282 bool hideFieldLabels = Model.Item.GetBoolean("HideFieldLabels"); 283 bool noValues = false; 284 285 if (!string.IsNullOrEmpty(fieldValue)) 286 { 287 if (field.Value.GetType() == typeof(System.Collections.Generic.List<FieldOptionValueViewModel>)) 288 { 289 System.Collections.Generic.List<FieldOptionValueViewModel> values = field.Value as System.Collections.Generic.List<FieldOptionValueViewModel>; 290 noValues = values.Count > 0 ? false : true; 291 } 292 } 293 294 if (!string.IsNullOrEmpty(fieldValue) && noValues == false) 295 { 296 if (layout == "columns") 297 { 298 <div class="grid g-col-6 g-col-lg-4"> 299 @if (!hideFieldLabels) 300 { 301 <dt class="g-col-4 py-2 fw-bold">@field.Name</dt> 302 } 303 <dd class="g-col-8 py-2 mb-0">@RenderFieldValue(field)</dd> 304 </div> 305 } 306 if (layout == "list") 307 { 308 string extraPadding = size == "full" ? "py-2" : ""; 309 310 if (!hideFieldLabels) 311 { 312 <dt class="g-col-4 @extraPadding fw-bold">@field.Name</dt> 313 } 314 <dd class="g-col-8 @extraPadding mb-0"> 315 @RenderFieldValue(field) 316 </dd> 317 } 318 if (layout == "table") 319 { 320 <tr> 321 @if (!hideFieldLabels) 322 { 323 <th class="fw-bold" scope="row">@field.Name</th> 324 } 325 <td>@RenderFieldValue(field)</td> 326 </tr> 327 } 328 if (layout == "bullets") 329 { 330 <dt class="g-col-12 g-col-sm-4 g-col-lg-12 fw-bold m-0">@field.Name</dt> 331 <dd class="g-col-12 g-col-sm-8 g-col-lg-12 mb-3"> 332 @RenderFieldValue(field) 333 </dd> 334 } 335 } 336 } 337 338 @helper RenderFieldValue(FieldValueViewModel field) 339 { 340 string fieldValue = field?.Value != null ? field.Value.ToString() : ""; 341 342 bool isLink = field?.Type == "Link"; 343 bool isColor = false; 344 bool isBrandName = field?.SystemName == "Brand_name"; 345 346 fieldValue = fieldValue == "False" ? Translate("No") : fieldValue; 347 fieldValue = fieldValue == "True" ? Translate("Yes") : fieldValue; 348 349 350 if (field.Value.GetType() == typeof(System.Collections.Generic.List<Dynamicweb.Ecommerce.ProductCatalog.FieldOptionValueViewModel>)) 351 { 352 int valueCount = 0; 353 System.Collections.Generic.List<FieldOptionValueViewModel> values = field.Value as System.Collections.Generic.List<FieldOptionValueViewModel>; 354 int totalValues = values.Count; 355 356 foreach (FieldOptionValueViewModel option in values) 357 { 358 if (option.Value.Substring(0, 1) == "#") 359 { 360 isColor = true; 361 } 362 363 if (!isColor) 364 { 365 @option.Name 366 } 367 else 368 { 369 <span class="colorbox-sm" style="background-color: @option.Value" title="@option.Name"></span> 370 } 371 372 if (valueCount != totalValues && valueCount < (totalValues - 1)) 373 { 374 if (isColor) 375 { 376 <text> </text> 377 } 378 else 379 { 380 <text>, </text> 381 } 382 } 383 valueCount++; 384 } 385 } 386 else 387 { 388 if (fieldValue.Substring(0, 1) == "#") 389 { 390 isColor = true; 391 } 392 393 if (!isColor) 394 { 395 if (isLink) 396 { 397 string linktTitle = !fieldValue.Contains("aspx") ? fieldValue : Translate("Go to link"); 398 string target = Pageview.AreaSettings.GetBoolean("OpenLinksInNewTab") && fieldValue.Contains("http") ? "target=\"_blank\"" : string.Empty; 399 string rel = Pageview.AreaSettings.GetBoolean("OpenLinksInNewTab") && fieldValue.Contains("http") ? "rel=\"noopener\"" : string.Empty; 400 401 <a href="@field.Value" title="@field.Name" @target @rel>@linktTitle</a> 402 } 403 else if (isBrandName) 404 { 405 <span itemprop="brand" itemtype="https://schema.org/Brand" itemscope> 406 <span itemprop="name">@fieldValue</span> 407 </span> 408 } 409 else 410 { 411 @fieldValue 412 } 413 414 } 415 else 416 { 417 <span class="colorbox-sm" style="background-color: @fieldValue" title="@fieldValue"></span> 418 } 419 } 420 } 421
Error executing template "Designs/Swift/Paragraph/Swift_ProductVariantSelector_Custom.cshtml" System.NullReferenceException: Object reference not set to an instance of an object. at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.CreateView(ProductViewModelSettings settings, ProductFieldValue pfv) at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.GetProductFieldValues(ProductViewModelSettings settings, Product product) at System.Lazy`1.CreateValue() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Lazy`1.get_Value() at CompiledRazorTemplates.Dynamic.RazorEngine_11e29021130040f29b7bbffac9d1407d.Execute() in E:\Solutions\Eva Solo\Files\Templates\Designs\Swift\Paragraph\Swift_ProductVariantSelector_Custom.cshtml:line 88 at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader) at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer) at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter) at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template) at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template) at Dynamicweb.Rendering.Template.RenderRazorTemplate()
1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 2 @using System 3 @using System.Collections.Generic 4 @using Dynamicweb.Ecommerce.ProductCatalog 5 @using Dynamicweb.Core 6 @using System.Web 7 @using System.Globalization 8 @using System.Linq 9 @using System.Text.RegularExpressions 10 11 @* TODO: REFACTURE/UPGRADE TO SWIFT (v1.25.0) *@ 12 13 @functions { 14 15 //Find contrast color (white, black) 16 public static string GetContrastColor(string hexString) 17 { 18 System.Drawing.Color bg = System.Drawing.ColorTranslator.FromHtml(hexString); 19 20 int nThreshold = 105; 21 int bgDelta = Convert.ToInt32((bg.R * 0.299) + (bg.G * 0.587) + (bg.B * 0.114)); 22 23 string foreColor = (255 - bgDelta < nThreshold) ? "#333" : "#fff"; 24 return foreColor; 25 } 26 27 public bool TryExtractDouble(string input, out double result) 28 { 29 result = 0; 30 if (string.IsNullOrWhiteSpace(input)) 31 return false; 32 33 Match match = Regex.Match(input, @"(\d+[\,\. ])+", RegexOptions.IgnoreCase, 34 TimeSpan.FromMilliseconds(5000)); 35 if (match.Success) 36 { 37 string numberStr = match.Value.Trim(); 38 return double.TryParse(numberStr, NumberStyles.Any, new CultureInfo("en-US").NumberFormat, out result); 39 } 40 41 return false; 42 } 43 44 } 45 46 @{ 47 bool isVisualEditor = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("VisualEdit")) ? Convert.ToBoolean(Dynamicweb.Context.Current.Request.QueryString.Get("VisualEdit")) : false; 48 49 ProductViewModel product = new ProductViewModel(); 50 51 ProductViewModelSettings productSetting = new ProductViewModelSettings 52 { 53 LanguageId = Dynamicweb.Ecommerce.Common.Context.LanguageID, 54 CurrencyCode = Dynamicweb.Ecommerce.Common.Context.Currency.Code, 55 CountryCode = Dynamicweb.Ecommerce.Common.Context.Country.Code2, 56 ShopId = Pageview.Area.EcomShopId 57 }; 58 59 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 60 { 61 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 62 } 63 else if (Pageview.Item["DummyProduct"] != null) 64 { 65 string dummyProductId = ""; 66 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 67 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 68 if (productList.Products != null) 69 { 70 foreach (var p in productList.Products) 71 { 72 dummyProductId = p.Id; 73 } 74 75 ProductViewModel dummyProduct = dummyProductId != "" ? ViewModelFactory.CreateView(productSetting, dummyProductId) : new ProductViewModel(); 76 product = dummyProduct; 77 } 78 else 79 { 80 product = ViewModelFactory.CreateView(productSetting, Dynamicweb.Ecommerce.Services.Products.GetLastActiveProducts(1, Dynamicweb.Ecommerce.Common.Context.LanguageID, false).FirstOrDefault().Id); 81 } 82 } 83 else if (Pageview.Item["DummyProduct"] == null) 84 { 85 product = ViewModelFactory.CreateView(productSetting, Dynamicweb.Ecommerce.Services.Products.GetLastActiveProducts(1, Dynamicweb.Ecommerce.Common.Context.LanguageID, false).FirstOrDefault().Id); 86 } 87 88 bool isColorVariant = product.ProductFields.ContainsKey("Custom_ColorVariantOnWeb") ? Converter.ToBoolean(product.ProductFields["Custom_ColorVariantOnWeb"].Value) : false; 89 90 IEnumerable<ProductViewModel> relatedProducts = product.GetRelatedProducts(); 91 relatedProducts = Smartpage.EvaSolo.Assortment.Helpers.RelatedProducts.FilterOutNonAvailableRelatedProducts(relatedProducts); 92 string[] variantId = { }; 93 94 if (product?.VariantId != null) 95 { 96 variantId = product.VariantId.Split('.'); 97 } 98 99 if (relatedProducts.Any()) 100 { 101 relatedProducts = relatedProducts.Prepend(product); 102 103 bool hideVariantInfoOnProduct = Converter.ToBoolean(Pageview.AreaSettings.GetItem("CustomSettings").GetRawValueString("HideVariantInfoOnProduct_Custom")); 104 105 if (!hideVariantInfoOnProduct) 106 { 107 <div> 108 @if (isColorVariant) 109 { 110 string productFieldCustomColor = product.ProductFields.ContainsKey("Custom_Color") ? Converter.ToString(product.ProductFields["Custom_Color"].Value) : null; 111 <span>@Translate("Custom:Variant.Color.Info", "Farve"): <b>@productFieldCustomColor</b></span> 112 } 113 else 114 { 115 string productFieldCustomSize = product.ProductFields.ContainsKey("Custom_Size") ? Converter.ToString(product.ProductFields["Custom_Size"].Value) : null; 116 <span>@Translate("Custom:Variant.Size.Info", "Størrelse"): <b>@productFieldCustomSize</b></span> 117 } 118 </div> 119 } 120 121 <div class="p-0 mt-2"> @* container overflow-hidden*@ 122 @if (isColorVariant && Model.Item.GetRawValueString("Custom_ColorVariantLayout", "Slider") == "slider") 123 { 124 @RenderRelatedProductSliders(relatedProducts, product) 125 } 126 else 127 { 128 @RenderRelatedProducts(relatedProducts, product, isColorVariant) 129 } 130 </div> 131 } 132 133 if (product.VariantInfo.VariantInfo != null && !Model.Item.GetBoolean("HideVariantSelector")) 134 { 135 int groupNumber = 1; 136 137 <form class="js-variant-selector" data-combinations="@string.Join(",", product.VariantCombinations())"> 138 <input type="hidden" name="variantid"/> 139 140 @foreach (var variantGroup in product.VariantGroups()) 141 { 142 VariantGroupViewModel group = variantGroup; 143 144 <h3 class="h6">@group.Name</h3> 145 <div class="d-flex gap-2 flex-wrap js-variant-group" data-group-id="@groupNumber"> 146 @foreach (var option in group.Options) 147 { 148 string active = variantId.Contains(option.Id) ? "active" : ""; 149 150 if (!string.IsNullOrEmpty(option.Color)) 151 { 152 string contrastColor = GetContrastColor(option.Color); 153 <button type="button" 154 class="btn colorbox rounded-circle d-inline-block variant-option border js-variant-option @active" 155 style="background-color: @option.Color; --variantoption-check-color: @contrastColor" 156 onclick="swift.VariantSelector.OptionClick(event)" data-variant-id="@option.Id" 157 id="@(product.Id)_@(option.Id)_@Pageview.CurrentParagraph.ID"></button> 158 } 159 else if (!string.IsNullOrEmpty(option.Color) && !string.IsNullOrEmpty(option.Image.Value)) 160 { 161 <button type="button" 162 class="btn p-0 d-inline-block variant-option border js-variant-option @active" 163 onclick="swift.VariantSelector.OptionClick(event)" data-variant-id="@option.Id"> 164 <img 165 src="/Admin/Public/GetImage.ashx?image=@(option.Image.Value)&width=42&Format=WebP&Quality=70" /> 166 </button> 167 } 168 else 169 { 170 <button type="button" 171 class="btn btn-secondary d-inline-block variant-option js-variant-option @active" 172 onclick="swift.VariantSelector.OptionClick(event)" data-variant-id="@option.Id"> 173 @option.Name 174 </button> 175 } 176 } 177 </div> 178 179 groupNumber++; 180 } 181 </form> 182 } 183 } 184 185 186 @helper RenderRelatedProducts(IEnumerable<ProductViewModel> relatedProducts, ProductViewModel product, bool isColorVariant) 187 { 188 int variantsToShow = 100; 189 int counter = 1; 190 bool showMoreButton = true; 191 192 if (isColorVariant == false) 193 { 194 relatedProducts = relatedProducts.OrderBy(rp => 195 { 196 double size = double.MaxValue; // default if parse fails 197 if (rp.ProductFields.TryGetValue("Custom_Size", out var sizeFieldValue) && 198 TryExtractDouble(sizeFieldValue?.Value?.ToString(), out var parsed)) 199 { 200 size = parsed; 201 } 202 203 return size; 204 }); 205 } 206 207 <div class="js-related-products-wrapper"> 208 <div class="related-products-container js-related-products-container"> 209 @if (showMoreButton) 210 { 211 <button class="p-2 js-show-all btn-show-all text-center"> 212 <span>+</span><span class="js-hidden-variants-count"></span> 213 </button> 214 } 215 @foreach (ProductViewModel relatedProduct in relatedProducts) 216 { 217 bool isActive = product.Id == relatedProduct.Id; 218 @RenderRelatedProduct(relatedProduct, isActive, (counter > variantsToShow), isColorVariant) 219 counter++; 220 } 221 </div> 222 </div> 223 } 224 225 @helper RenderRelatedProduct(ProductViewModel relatedProduct, bool isActive, bool isHidden, bool isColorVariant = true) 226 { 227 var productListPageId = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("ProductListPage")) ? Model.Item.GetInt32("ProductListPage") : GetPageIdByNavigationTag("Shop"); 228 var relatedProductLink = relatedProduct.GetProductLink(productListPageId); 229 isHidden = isColorVariant ? isHidden : false; 230 string aCssClassesByType = isColorVariant ? string.Empty : "text-nowrap w-auto"; 231 232 <div class="related-product @(isActive ? "active" : "") @(aCssClassesByType) js-related-product"> 233 @if (isColorVariant) 234 { 235 var relatedProductFieldCustomColor = relatedProduct.ProductFields.ContainsKey("Custom_Color") ? Converter.ToString(relatedProduct.ProductFields["Custom_Color"].Value) : null; 236 var relatedProductImage = relatedProduct.DefaultImage.Value.StartsWith("/Files/") ? $"/Admin/Public/GetImage.ashx?image={relatedProduct.DefaultImage.Value}&width=180&format=webp" : relatedProduct.DefaultImage.Value; 237 238 <a href="@(relatedProductLink)" title="@HttpUtility.HtmlAttributeEncode(relatedProductFieldCustomColor ?? relatedProduct.Name)"> 239 <img src="@(relatedProductImage)" class="p-0 p-lg-1 w-100 h-100" style="object-fit:contain;" loading="lazy" decoding="async" alt="@HttpUtility.HtmlAttributeEncode(relatedProductFieldCustomColor ?? relatedProduct.Name)" /> 240 </a> 241 } 242 else 243 { 244 string relatedProductFieldCustomSize = relatedProduct.ProductFields.ContainsKey("Custom_Size") ? Converter.ToString(relatedProduct.ProductFields["Custom_Size"].Value) : null; 245 246 <a href="@(relatedProductLink)" class="d-block py-2 px-3 small text-center text-decoration-none" title="@HttpUtility.HtmlAttributeEncode(relatedProductFieldCustomSize ?? relatedProduct.Name)">@(relatedProductFieldCustomSize ?? relatedProduct.Name)</a> 247 } 248 </div> 249 } 250 251 @helper RenderRelatedProductSliders(IEnumerable<ProductViewModel> relatedProducts, ProductViewModel product) //NOTE: Only support color variants 252 { 253 <div class="swiffy-slider slider-item-show4 slider-item-show5-sm slider-item-show7-md slider-item-show4-lg slider-item-show5-xl slider-item-show7-xxl slider-item-snapstart slider-item-reveal slider-nav-square-small slider-indicators-hide js-swiffyslider" data-slider-nav-autoplay-interval="2500"> 254 <div class="slider-container"> 255 @foreach (ProductViewModel relatedProduct in relatedProducts) 256 { 257 @RenderRelatedProductSlider(relatedProduct, product) 258 } 259 </div> 260 </div> 261 } 262 263 @helper RenderRelatedProductSlider(ProductViewModel relatedProduct, ProductViewModel product) //NOTE: Only support color variants 264 { 265 var productListPageId = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("ProductListPage")) ? Model.Item.GetInt32("ProductListPage") : GetPageIdByNavigationTag("Shop"); 266 var relatedProductLink = relatedProduct.GetProductLink(productListPageId); 267 268 var relatedProductFieldCustomColor = relatedProduct.ProductFields.ContainsKey("Custom_Color") ? Converter.ToString(relatedProduct.ProductFields["Custom_Color"].Value) : null; 269 var relatedProductImage = relatedProduct.DefaultImage.Value.StartsWith("/Files/") ? $"/Admin/Public/GetImage.ashx?image={relatedProduct.DefaultImage.Value}&width=180&format=webp" : relatedProduct.DefaultImage.Value; 270 271 <div class="related-product @(relatedProduct.Id == product.Id ? "active" : "")"> 272 <a href="@(relatedProductLink)" title="@HttpUtility.HtmlAttributeEncode(relatedProductFieldCustomColor ?? relatedProduct.Name)"> 273 <img src="@(relatedProductImage)" class="p-0 p-lg-1 w-100 h-100" style="object-fit:contain;" loading="lazy" decoding="async" alt="@HttpUtility.HtmlAttributeEncode(relatedProductFieldCustomColor ?? relatedProduct.Name)" /> 274 </a> 275 </div> 276 } 277 278 <script> 279 function setVariantEnvironment() { 280 const container = document.querySelector('.js-related-products-wrapper'); 281 const innerContainer = document.querySelector('.js-related-products-container'); 282 if (container !== null) { 283 const items = container.querySelectorAll(".js-related-product"); 284 const btnShowAll = document.querySelector('.js-show-all'); 285 let hiddenCount = 0; 286 let firstRowTopPos = null; 287 innerContainer.classList.remove('flex-nowrap'); 288 289 btnShowAll.classList.remove('order-1'); 290 items.forEach(item => { 291 item.classList.remove('order-0', 'order-2', 'hidden'); 292 }); 293 294 items.forEach(item => { 295 const itemTop = item.getBoundingClientRect().top; 296 if (firstRowTopPos === null) { 297 firstRowTopPos = itemTop; 298 } 299 if (itemTop !== firstRowTopPos) { 300 item.classList.add('hidden'); 301 hiddenCount++; 302 } else { 303 item.classList.add('order-0'); 304 } 305 }); 306 307 if (hiddenCount === 1) { 308 innerContainer.classList.add('flex-nowrap'); 309 btnShowAll.classList.add('d-none'); 310 items.forEach(item => { 311 item.classList.remove('hidden'); 312 item.classList.add('order-0'); 313 }); 314 } else if (hiddenCount > 1) { 315 btnShowAll.classList.remove('d-none', 'order-0'); 316 btnShowAll.classList.add('order-1'); 317 btnShowAll.querySelector('.js-hidden-variants-count').textContent = hiddenCount; 318 } else { 319 btnShowAll.classList.add('d-none'); 320 } 321 } 322 } 323 324 window.addEventListener('DOMContentLoaded', () => { 325 setVariantEnvironment(); 326 327 }); 328 window.addEventListener("resize", () => { 329 setVariantEnvironment(); 330 }); 331 332 </script> 333
Error executing template "Designs/Swift/Paragraph/Swift_ProductBadges_Custom.cshtml" System.NullReferenceException: Object reference not set to an instance of an object. at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.CreateView(ProductViewModelSettings settings, ProductFieldValue pfv) at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.GetProductFieldValues(ProductViewModelSettings settings, Product product) at System.Lazy`1.CreateValue() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Lazy`1.get_Value() at CompiledRazorTemplates.Dynamic.RazorEngine_fe4e63c166214874a0bcb86da4f14f88.Execute() in E:\Solutions\Eva Solo\Files\Templates\Designs\Swift\Paragraph\Swift_ProductBadges_Custom.cshtml:line 27 at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader) at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer) at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter) at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template) at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template) at Dynamicweb.Rendering.Template.RenderRazorTemplate()
1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 2 @using System 3 @using System.Collections.Generic 4 @using System.Linq 5 @using Dynamicweb.Frontend 6 @using Dynamicweb.Content 7 @using Dynamicweb.Core 8 @using Dynamicweb.Ecommerce.ProductCatalog 9 10 @{ 11 ProductViewModel product = null; 12 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 13 { 14 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 15 } 16 else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode) 17 { 18 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 19 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 20 21 if (productList?.Products is object) 22 { 23 product = productList.Products[0]; 24 } 25 } 26 27 DateTime launchDate = product.ProductFields.ContainsKey("Custom_LaunchDate") ? Converter.ToDateTime(product.ProductFields["Custom_LaunchDate"].Value) : DateTime.MinValue; 28 DateTime currentDate = DateTime.Today; 29 bool showComingSoonBadge = currentDate < launchDate && string.Equals( Model.Item.GetRawValueString("NewBadgeDesign"), "comingsoon", StringComparison.InvariantCultureIgnoreCase ); 30 } 31 32 @if (product is object) 33 { 34 var badgeParms = new Dictionary<string, object>(); 35 badgeParms.Add("size", "h7"); 36 badgeParms.Add("saleBadgeType", Model.Item.GetRawValue("SaleBadgeType")); 37 badgeParms.Add("saleBadgeCssClassName", Model.Item.GetRawValue("SaleBadgeDesign")); 38 badgeParms.Add("newBadgeCssClassName", Model.Item.GetRawValue("NewBadgeDesign")); 39 badgeParms.Add("newPublicationDays", Model.Item.GetInt32("NewPublicationDays")); 40 badgeParms.Add("campaignBadgesValues", Model.Item.GetRawValueString("CampaignBadges")); 41 42 string badgeSize = Model.Item.GetRawValueString("BadgeSize", "fs-2"); 43 string horizontalAlign = Model.Item.GetRawValueString("HorizontalAlignment", ""); 44 horizontalAlign = horizontalAlign == "center" ? "text-center" : horizontalAlign; 45 horizontalAlign = horizontalAlign == "end" ? "text-end" : horizontalAlign; 46 47 Dictionary<string, ParagraphInfoViewModel> badgeConfigurations; 48 List<string> campaignBadgesValues = Model.Item.GetRawValueString("CampaignBadges") != null ? Model.Item.GetRawValueString("CampaignBadges").Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() : new List<string>(); 49 50 if (Dynamicweb.Context.Current.Items.Contains("badgeConfigurations")) 51 { 52 badgeConfigurations = (Dictionary<string, ParagraphInfoViewModel>)Dynamicweb.Context.Current.Items["badgeConfigurations"]; 53 } 54 else 55 { 56 var badgesPage = Pageview.AreaSettings.GetLink("EcommerceBadgesPage") != null ? Pageview.AreaSettings.GetLink("EcommerceBadgesPage").PageId : 0; 57 var allBadges = badgesPage != 0 ? Dynamicweb.Content.Services.Paragraphs.GetParagraphsByPageId(badgesPage) : null; 58 59 badgeConfigurations = new Dictionary<string, ParagraphInfoViewModel>(); 60 61 if ( allBadges != null ) 62 { 63 foreach ( Paragraph badge in allBadges ) 64 { 65 var paragraphviewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreateParagraphInfoViewModel( badge ); 66 string cssClassName = paragraphviewModel.Item.GetString( "CssClassName" )?.Trim().ToLower() ?? string.Empty;; 67 if ( !badgeConfigurations.ContainsKey( cssClassName ) ) 68 { 69 badgeConfigurations.Add( cssClassName, paragraphviewModel ); 70 } 71 } 72 } 73 74 Dynamicweb.Context.Current.Items.Add("badgeConfigurations", badgeConfigurations); 75 } 76 77 int badgesCount = 0; 78 if (badgeConfigurations.Any()) 79 { 80 foreach (string campaign in campaignBadgesValues) 81 { 82 if (!string.IsNullOrEmpty(campaign)) 83 { 84 FieldValueViewModel availableCampaignsObject; 85 product.ProductFields.TryGetValue("Campaign", out availableCampaignsObject); 86 87 if (availableCampaignsObject != null) 88 { 89 string campaignType = string.Empty; 90 91 if (badgeConfigurations.ContainsKey(campaign)) 92 { 93 ParagraphInfoViewModel paragraphviewModel; 94 if (badgeConfigurations.TryGetValue(campaign, out paragraphviewModel)) 95 { 96 campaignType = paragraphviewModel.Item.GetRawValueString("CampaignType"); 97 } 98 } 99 100 List<FieldOptionValueViewModel> availableCampaigns = (List<FieldOptionValueViewModel>)availableCampaignsObject.Value; 101 102 foreach (FieldOptionValueViewModel availableOption in availableCampaigns) 103 { 104 if (campaignType == availableOption.Value) 105 { 106 badgesCount++; 107 break; 108 } 109 } 110 } 111 } 112 } 113 } 114 115 bool saleBadgeEnabled = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("SaleBadgeDesign")) && Model.Item.GetRawValueString("SaleBadgeDesign") != "none" ? true : false; 116 bool newBadgeEnabled = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("NewBadgeDesign")) && Model.Item.GetRawValueString("NewBadgeDesign") != "none" ? true : false; 117 DateTime createdDate = product.Created.Value; 118 bool showBadges = saleBadgeEnabled && product.Discount.Price != 0 ? true : false; 119 showBadges = (newBadgeEnabled && Model.Item.GetInt32("NewPublicationDays") == 0) || (newBadgeEnabled && (createdDate.AddDays(Model.Item.GetInt32("NewPublicationDays")) > DateTime.Now)) ? true : showBadges; 120 showBadges = (!string.IsNullOrEmpty(Model.Item.GetRawValueString("CampaignBadges")) && badgesCount != 0) || showComingSoonBadge || showBadges; 121 122 if (showBadges) 123 { 124 <div class="@badgeSize @horizontalAlign item_@Model.Item.SystemName.ToLower()"> 125 @RenderPartial("Components/EcommerceBadge_Custom.cshtml", product, badgeParms) @*//CUSTOM*@ 126 </div> 127 } 128 else if (Pageview.IsVisualEditorMode) 129 { 130 <span class="badge bg-success text-light rounded-0">@Translate("Badge example")</span> 131 } 132 } 133 else if (Pageview.IsVisualEditorMode) 134 { 135 <span class="badge bg-success text-light rounded-0">@Translate("Badge example")</span> 136 } 137 138
Error executing template "/Designs/Swift/Paragraph/Swift_ProductPrice_Custom.cshtml" System.NullReferenceException: Object reference not set to an instance of an object. at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.CreateView(ProductViewModelSettings settings, ProductFieldValue pfv) at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.GetProductFieldValues(ProductViewModelSettings settings, Product product) at System.Lazy`1.CreateValue() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Lazy`1.get_Value() at CompiledRazorTemplates.Dynamic.RazorEngine_1fb0d18a1de944f3a468232b7643f0eb.Execute() in E:\Solutions\Eva Solo\Files\Templates\Designs\Swift\Paragraph\Swift_ProductPrice_Custom.cshtml:line 65 at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader) at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer) at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter) at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template) at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template) at Dynamicweb.Rendering.Template.RenderRazorTemplate()
1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 2 @using Dynamicweb.Configuration @*//CUSTOM*@ 3 @using Dynamicweb.Core.Encoders @*//CUSTOM*@ 4 @using Dynamicweb.Ecommerce.ProductCatalog 5 @using System.Globalization 6 @using System.IO @*//CUSTOM*@ 7 8 @* CUSTOMIZED STANDARD SWIFT (v1.25.0) TEMPLATE *@ 9 10 @{ 11 ProductViewModel product = null; 12 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 13 { 14 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 15 } 16 else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode) 17 { 18 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 19 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 20 21 if (productList?.Products is object) 22 { 23 product = productList.Products[0]; 24 } 25 } 26 27 string anonymousUsersLimitations = Pageview.AreaSettings.GetRawValueString("AnonymousUsers", ""); 28 bool anonymousUser = Pageview.User == null; 29 bool isErpConnectionDown = !Dynamicweb.Core.Converter.ToBoolean(Dynamicweb.Context.Current.Items["IsWebServiceConnectionAvailable"]); 30 bool hidePrice = anonymousUsersLimitations.Contains("price") && anonymousUser || Pageview.AreaSettings.GetBoolean("ErpDownHidePrices") && isErpConnectionDown; 31 32 bool productIsDiscontinued = product is object && product.Discontinued; 33 bool doNotShowPriceIfProductIsDiscontinued = Model.Item.GetBoolean("DoNotShowPriceIfProductIsDiscontinued"); 34 var isDiscontinued = productIsDiscontinued && doNotShowPriceIfProductIsDiscontinued; 35 } 36 37 @if (product is object && !hidePrice && !isDiscontinued) 38 { 39 bool showInformativePrice = Model.Item.GetBoolean("ShowInformativePrice"); 40 string unitId = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.Form.Get("UnitId")) ? Dynamicweb.Context.Current.Request.Form.Get("UnitId") : string.Empty; 41 42 string priceFontSize = Model.Item.GetRawValueString("PriceSize", "h6 justify-content-lg-start"); //CUSTOM 43 string horizontalAlign = Model.Item.GetRawValueString("HorizontalAlignment", ""); 44 string layout = Model.Item.GetRawValueString("Layout", "horizontal"); 45 string textAlign = horizontalAlign == "center" ? "text-center" : string.Empty; 46 textAlign = horizontalAlign == "end" ? "text-end" : textAlign; 47 48 horizontalAlign = horizontalAlign == "center" && layout == "horizontal" ? "justify-content-center" : horizontalAlign; 49 horizontalAlign = horizontalAlign == "end" && layout == "horizontal" ? "justify-content-end" : horizontalAlign; 50 horizontalAlign = horizontalAlign == "center" && layout == "vertical" ? "align-items-center" : horizontalAlign; 51 horizontalAlign = horizontalAlign == "end" && layout == "vertical" ? "align-items-end" : horizontalAlign; 52 53 string flexDirection = layout == "horizontal" ? string.Empty : "flex-column"; 54 string flexGap = layout == "horizontal" ? "gap-3" : string.Empty; 55 string order = layout == "horizontal" ? string.Empty : "order-2"; 56 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? "theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 57 theme = GetViewParameter("theme") != null ? GetViewParameterString("theme") : theme; 58 59 string contentPadding = Model.Item.GetRawValueString("ContentPadding", ""); 60 contentPadding = contentPadding == "none" ? "p-0" : contentPadding; 61 contentPadding = contentPadding == "small" ? "p-1 px-md-2 py-md-1" : contentPadding; 62 contentPadding = contentPadding == "large" ? "p-2 px-md-3 py-md-2" : contentPadding; 63 64 //CUSTOM 65 Dictionary<string, FieldValueViewModel> productFields = product.ProductFields; 66 var discountText = ""; 67 bool discountDiscontinued = false; 68 bool discountOnSale = false; 69 70 if (productFields.TryGetValue("Custom_Discontinued", out FieldValueViewModel discontinued)) 71 { 72 var firstValue = (discontinued.Value as List<FieldOptionValueViewModel>).FirstOrDefault()?.Value; 73 74 if (!string.IsNullOrWhiteSpace(firstValue)) 75 { 76 bool.TryParse(firstValue, out discountDiscontinued); 77 } 78 } 79 80 if (productFields.TryGetValue("Custom_OnSale", out FieldValueViewModel onsale)) 81 { 82 var firstValue = (onsale.Value as List<FieldOptionValueViewModel>).FirstOrDefault()?.Value; 83 84 if (!string.IsNullOrWhiteSpace(firstValue)) 85 { 86 bool.TryParse(firstValue, out discountOnSale); 87 } 88 } 89 90 if (discountDiscontinued && discountOnSale) 91 { 92 discountText = Translate("Outlet - tilbuddet gælder så længe lager haves"); 93 } 94 else 95 { 96 var discountInfo = Smartpage.EvaSolo.CampaignPrices.Helpers.DiscountHelper.GetDiscountInfo(product); 97 if (discountInfo != null) 98 { 99 discountText = string.Format(Translate(Model.Item.GetRawValueString("Custom_DiscountText", "Tilbuddet gælder {0} - {1}")), $"‌{discountInfo.ValidFromFormatted}‌", $"‌{discountInfo.ValidToFormatted}‌"); 100 } 101 } 102 string discountType = Model.Item.GetRawValueString("Custom_DiscountType", "none"); 103 string discountTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Custom_DiscountTheme")) ? "theme " + Model.Item.GetRawValueString("Custom_DiscountTheme").Replace(" ", "").Trim().ToLower() : string.Empty; 104 string discountIconColor = Model.Item.GetString("Custom_DiscountIconColor", "text-inherit"); 105 string discountIconSize = Model.Item.GetRawValueString("Custom_DiscountIconSize", "2"); 106 string discountImageSrc = !string.IsNullOrEmpty(Model.Item.GetString("Custom_DiscountImage")) ? Model.Item.GetFile("Custom_DiscountImage").Path : string.Empty; 107 string discountImagePath = discountImageSrc != string.Empty ? discountImageSrc : Model.Item.GetRawValueString("Custom_DiscountIcon", string.Empty); 108 discountImagePath = Path.GetExtension(discountImagePath).ToLower() != ".svg" ? "/Admin/Public/GetImage.ashx?image=" + discountImagePath + "&height=" + discountIconSize + "&width=" + discountIconSize + "&Crop=0&format=webp" : discountImagePath; 109 string discountImgAltText = Model.Item.GetRawValueString("FeatureAltText", string.Empty); 110 //--CUSTOM 111 112 string showPricesWithVat = Pageview.Area.EcomPricesWithVat.ToLower(); 113 bool neverShowVat = string.IsNullOrEmpty(showPricesWithVat); 114 115 string priceMin = ""; 116 string priceMax = ""; 117 118 string liveInfoClass = ""; 119 string productInfoFeed = ""; 120 bool isLazyLoadingForProductInfoEnabled = Dynamicweb.Core.Converter.ToBoolean(Dynamicweb.Context.Current.Items["IsLazyLoadingForProductInfoEnabled"]); 121 if (isLazyLoadingForProductInfoEnabled) 122 { 123 if (Dynamicweb.Context.Current.Items.Contains("ProductInfoFeed")) 124 { 125 productInfoFeed = Dynamicweb.Context.Current.Items["ProductInfoFeed"]?.ToString(); 126 if (!string.IsNullOrEmpty(productInfoFeed)) 127 { 128 productInfoFeed = $"data-product-info-feed=\"{productInfoFeed}\""; 129 } 130 } 131 liveInfoClass = "js-live-info"; 132 } 133 134 <div class="@textAlign @liveInfoClass item_@Model.Item.SystemName.ToLower()" data-product-id="@product.Id" data-variant-id="@product.VariantId" @productInfoFeed> 135 @if (showInformativePrice && product.PriceInformative.Price != 0) 136 { 137 <div class="opacity-50"> 138 <span>@Translate("RRP") </span> 139 <span class="text-decoration-line-through text-price">@product.PriceInformative.PriceFormatted</span> 140 </div> 141 } 142 <div class="@priceFontSize m-0 d-flex flex-wrap @flexDirection @flexGap @horizontalAlign" style="row-gap: 0 !important" itemprop="offers" itemscope itemtype="https://schema.org/Offer"> 143 <span itemprop="priceCurrency" content="@product.Price.CurrencyCode" class="d-none"></span> 144 145 @*//CUSTOM*@ 146 @if (showPricesWithVat == "false" && !neverShowVat) 147 { 148 if (isLazyLoadingForProductInfoEnabled && !Pageview.IsVisualEditorMode) 149 { 150 <span class="text-price js-text-price"> 151 <span class="spinner-border" role="status"></span> 152 </span> 153 } 154 else 155 { 156 string price = !string.IsNullOrEmpty(unitId) ? product.GetPrice(unitId).Price.PriceWithoutVatFormatted : product.Price.PriceWithoutVatFormatted; 157 158 if (product?.VariantInfo?.VariantInfo != null) 159 { 160 priceMin = product?.VariantInfo?.PriceMin?.PriceWithoutVatFormatted != null ? product.VariantInfo.PriceMin.PriceWithoutVatFormatted : ""; 161 priceMax = product?.VariantInfo?.PriceMax?.PriceWithoutVatFormatted != null ? product.VariantInfo.PriceMax.PriceWithoutVatFormatted : ""; 162 } 163 if (priceMin != priceMax) 164 { 165 price = priceMin + " - " + priceMax; 166 } 167 168 <span class="@theme"> 169 <span class="text-price">@price</span> 170 </span> 171 } 172 } 173 else 174 { 175 if (isLazyLoadingForProductInfoEnabled && !Pageview.IsVisualEditorMode) 176 { 177 <span class="text-price js-text-price"> 178 <span class="spinner-border" role="status"></span> 179 </span> 180 } 181 else 182 { 183 string price = !string.IsNullOrEmpty(unitId) ? product.GetPrice(unitId).Price.PriceFormatted : product.Price.PriceFormatted; 184 185 if (product?.VariantInfo?.VariantInfo != null) 186 { 187 priceMin = product?.VariantInfo?.PriceMin?.PriceFormatted != null ? product.VariantInfo.PriceMin.PriceFormatted : ""; 188 priceMax = product?.VariantInfo?.PriceMax?.PriceFormatted != null ? product.VariantInfo.PriceMax.PriceFormatted : ""; 189 } 190 if (priceMin != priceMax) 191 { 192 price = priceMin + " - " + priceMax; 193 } 194 195 <span class="@theme"> 196 <span class="text-price">@price</span> 197 </span> 198 } 199 } 200 201 @if (showPricesWithVat == "false" && !neverShowVat) 202 { 203 if (isLazyLoadingForProductInfoEnabled && !Pageview.IsVisualEditorMode) 204 { 205 <span itemprop="price" content="" class="d-none"></span> 206 <span class="text-decoration-line-through js-text-decoration-line-through opacity-75 me-3 text-price js-text-price d-none" data-show-if="LiveProductInfo.product.Price.Price != LiveProductInfo.product.PriceBeforeDiscount.Price"></span> 207 } 208 else 209 { 210 string beforePrice = !string.IsNullOrEmpty(unitId) ? product.GetPrice(unitId).PriceBeforeDiscount.PriceWithoutVatFormatted : product.PriceBeforeDiscount.PriceWithoutVatFormatted; 211 212 <span itemprop="price" content="@product.Price.PriceWithoutVat.ToString(CultureInfo.InvariantCulture)" class="d-none"></span> 213 214 if (product.Price.Price != product.PriceBeforeDiscount.Price) 215 { 216 <span class="opacity-75 @(order)"> 217 <span class="fs-7 text-price text-decoration-line-through">@beforePrice</span> 218 </span> 219 220 if (Model.Item.GetBoolean("Custom_ShowDiscountSavings")) 221 { 222 var currency = Dynamicweb.Ecommerce.Common.Context.Currency; 223 var priceInfo = new Dynamicweb.Ecommerce.Prices.PriceInfo(currency) 224 { 225 PriceWithoutVAT = (product.PriceBeforeDiscount.PriceWithoutVat - product.Price.PriceWithoutVat) 226 }; 227 228 <span class="d-none d-sm-inline opacity-75 @(order)"> 229 <span class="fs-7 text-price">@string.Format(Translate("Spar {0}"), priceInfo.PriceWithoutVATFormatted)</span> 230 </span> 231 } 232 } 233 } 234 } 235 else 236 { 237 if (isLazyLoadingForProductInfoEnabled && !Pageview.IsVisualEditorMode) 238 { 239 <span itemprop="price" content="" class="d-none"></span> 240 <span class="text-decoration-line-through js-text-decoration-line-through opacity-75 me-3 text-price js-text-price d-none" data-show-if="LiveProductInfo.product.Price.Price < LiveProductInfo.product.PriceBeforeDiscount.Price"></span> 241 } 242 else 243 { 244 string beforePrice = !string.IsNullOrEmpty(unitId) ? product.GetPrice(unitId).PriceBeforeDiscount.PriceFormatted : product.PriceBeforeDiscount.PriceFormatted; 245 246 <span itemprop="price" content="@product.Price.Price.ToString(CultureInfo.InvariantCulture)" class="d-none"></span> 247 248 if (product.Price.Price < product.PriceBeforeDiscount.Price) 249 { 250 <span class="opacity-75 @(order)"> 251 <span class="fs-7 text-price text-decoration-line-through">@beforePrice</span> 252 </span> 253 254 if (Model.Item.GetBoolean("Custom_ShowDiscountSavings")) 255 { 256 var currency = Dynamicweb.Ecommerce.Common.Context.Currency; 257 var priceInfo = new Dynamicweb.Ecommerce.Prices.PriceInfo(currency) 258 { 259 PriceWithVAT = (product.PriceBeforeDiscount.Price - product.Price.Price) 260 }; 261 262 <span class="d-none d-sm-inline opacity-75 @(order)"> 263 <span class="fs-7 text-price">@string.Format(Translate("Spar {0}"), priceInfo.PriceFormatted)</span> 264 </span> 265 } 266 } 267 } 268 } 269 @*//--CUSTOM*@ 270 271 @*//CUSTOM*@ 272 @if (discountType == "icon-tooltip" && product.Price.Price != product.PriceBeforeDiscount.Price && discountText != null) 273 { 274 if ((!string.IsNullOrEmpty(Model.Item.GetString("Custom_DiscountImage")) || !discountImagePath.ToLower().Contains("none")) && discountImagePath != string.Empty) 275 { 276 <span data-bs-toggle="tooltip" data-bs-custom-class="@(discountTheme)" data-bs-html="true" data-bs-title="@HtmlEncoder.HtmlAttributeEncode(discountText)" data-bs-custom-prevent-event="click" data-bs-custom-click-close-delay="2000"> 277 @if (Path.GetExtension(discountImagePath).ToLower() == ".svg") 278 { 279 <span class="icon-auto @(discountIconColor)" style="vertical-align:text-top;height:@(discountIconSize)px;width:@(discountIconSize)px;">@ReadFile(discountImagePath)</span> 280 } 281 else 282 { 283 <img loading="lazy" src="@(discountImagePath)" alt="@HtmlEncoder.HtmlAttributeEncode(discountImgAltText)" title="@HtmlEncoder.HtmlAttributeEncode(discountImgAltText)" style="height:@(discountIconSize)px;width:@(discountIconSize)px;"> 284 } 285 </span> 286 } 287 } 288 @*//--CUSTOM*@ 289 290 @* Stock state for Schema.org, start *@ 291 @{ 292 Uri url = Dynamicweb.Context.Current.Request.Url; 293 } 294 295 <link itemprop="url" href="@url"> 296 297 @{ 298 bool IsNeverOutOfStock = product.NeverOutOfstock; 299 } 300 301 @if (IsNeverOutOfStock) 302 { 303 <span itemprop="availability" class="d-none">@Translate("Available in stock")</span> 304 } 305 else 306 { 307 if (product.StockLevel > 0) 308 { 309 <span itemprop="availability" class="d-none">InStock</span> 310 } 311 else 312 { 313 <span itemprop="availability" class="d-none">OutOfStock</span> 314 } 315 } 316 @* Stock state for Schema.org, stop *@ 317 318 </div> 319 320 @if (showPricesWithVat == "false" && !neverShowVat) 321 { 322 if (isLazyLoadingForProductInfoEnabled && !Pageview.IsVisualEditorMode) 323 { 324 <small class="opacity-85 fst-normal js-text-price-with-vat d-none" data-suffix="@Translate("Incl. VAT")"></small> 325 } 326 else 327 { 328 string price = !string.IsNullOrEmpty(unitId) ? product.GetPrice(unitId).Price.PriceWithVatFormatted : product.Price.PriceWithVatFormatted; 329 330 if (product?.VariantInfo?.VariantInfo != null) 331 { 332 priceMin = product?.VariantInfo?.PriceMin?.PriceWithVatFormatted != null ? product.VariantInfo.PriceMin.PriceWithVatFormatted : ""; 333 priceMax = product?.VariantInfo?.PriceMax?.PriceWithVatFormatted != null ? product.VariantInfo.PriceMax.PriceWithVatFormatted : ""; 334 } 335 if (priceMin != priceMax) 336 { 337 price = priceMin + " - " + priceMax; 338 } 339 <small class="opacity-85 fst-normal">@price @Translate("Incl. VAT")</small> 340 } 341 } 342 343 @*//CUSTOM*@ 344 @if (discountType == "inline" && product.Price.Price != product.PriceBeforeDiscount.Price && !string.IsNullOrEmpty(discountText)) 345 { 346 var discountFontSize = priceFontSize.Contains("h6") ? priceFontSize.Replace("h6", "small") : "small"; 347 348 <div class="@(discountFontSize) mt-1 d-flex flex-wrap @(flexDirection) @(horizontalAlign)"> 349 @discountText 350 </div> 351 } 352 @*//--CUSTOM*@ 353 354 </div> 355 } 356 else if (Pageview.IsVisualEditorMode) 357 { 358 <div class="alert alert-dark m-0" role="alert"> 359 <span>@Translate("No products available")</span> 360 </div> 361 } 362
Error executing template "Designs/Swift/Paragraph/Swift_ProductBadges_Custom.cshtml" System.NullReferenceException: Object reference not set to an instance of an object. at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.CreateView(ProductViewModelSettings settings, ProductFieldValue pfv) at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.GetProductFieldValues(ProductViewModelSettings settings, Product product) at System.Lazy`1.CreateValue() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Lazy`1.get_Value() at CompiledRazorTemplates.Dynamic.RazorEngine_fe4e63c166214874a0bcb86da4f14f88.Execute() in E:\Solutions\Eva Solo\Files\Templates\Designs\Swift\Paragraph\Swift_ProductBadges_Custom.cshtml:line 27 at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader) at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer) at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter) at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template) at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template) at Dynamicweb.Rendering.Template.RenderRazorTemplate()
1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 2 @using System 3 @using System.Collections.Generic 4 @using System.Linq 5 @using Dynamicweb.Frontend 6 @using Dynamicweb.Content 7 @using Dynamicweb.Core 8 @using Dynamicweb.Ecommerce.ProductCatalog 9 10 @{ 11 ProductViewModel product = null; 12 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 13 { 14 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 15 } 16 else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode) 17 { 18 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 19 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 20 21 if (productList?.Products is object) 22 { 23 product = productList.Products[0]; 24 } 25 } 26 27 DateTime launchDate = product.ProductFields.ContainsKey("Custom_LaunchDate") ? Converter.ToDateTime(product.ProductFields["Custom_LaunchDate"].Value) : DateTime.MinValue; 28 DateTime currentDate = DateTime.Today; 29 bool showComingSoonBadge = currentDate < launchDate && string.Equals( Model.Item.GetRawValueString("NewBadgeDesign"), "comingsoon", StringComparison.InvariantCultureIgnoreCase ); 30 } 31 32 @if (product is object) 33 { 34 var badgeParms = new Dictionary<string, object>(); 35 badgeParms.Add("size", "h7"); 36 badgeParms.Add("saleBadgeType", Model.Item.GetRawValue("SaleBadgeType")); 37 badgeParms.Add("saleBadgeCssClassName", Model.Item.GetRawValue("SaleBadgeDesign")); 38 badgeParms.Add("newBadgeCssClassName", Model.Item.GetRawValue("NewBadgeDesign")); 39 badgeParms.Add("newPublicationDays", Model.Item.GetInt32("NewPublicationDays")); 40 badgeParms.Add("campaignBadgesValues", Model.Item.GetRawValueString("CampaignBadges")); 41 42 string badgeSize = Model.Item.GetRawValueString("BadgeSize", "fs-2"); 43 string horizontalAlign = Model.Item.GetRawValueString("HorizontalAlignment", ""); 44 horizontalAlign = horizontalAlign == "center" ? "text-center" : horizontalAlign; 45 horizontalAlign = horizontalAlign == "end" ? "text-end" : horizontalAlign; 46 47 Dictionary<string, ParagraphInfoViewModel> badgeConfigurations; 48 List<string> campaignBadgesValues = Model.Item.GetRawValueString("CampaignBadges") != null ? Model.Item.GetRawValueString("CampaignBadges").Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() : new List<string>(); 49 50 if (Dynamicweb.Context.Current.Items.Contains("badgeConfigurations")) 51 { 52 badgeConfigurations = (Dictionary<string, ParagraphInfoViewModel>)Dynamicweb.Context.Current.Items["badgeConfigurations"]; 53 } 54 else 55 { 56 var badgesPage = Pageview.AreaSettings.GetLink("EcommerceBadgesPage") != null ? Pageview.AreaSettings.GetLink("EcommerceBadgesPage").PageId : 0; 57 var allBadges = badgesPage != 0 ? Dynamicweb.Content.Services.Paragraphs.GetParagraphsByPageId(badgesPage) : null; 58 59 badgeConfigurations = new Dictionary<string, ParagraphInfoViewModel>(); 60 61 if ( allBadges != null ) 62 { 63 foreach ( Paragraph badge in allBadges ) 64 { 65 var paragraphviewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreateParagraphInfoViewModel( badge ); 66 string cssClassName = paragraphviewModel.Item.GetString( "CssClassName" )?.Trim().ToLower() ?? string.Empty;; 67 if ( !badgeConfigurations.ContainsKey( cssClassName ) ) 68 { 69 badgeConfigurations.Add( cssClassName, paragraphviewModel ); 70 } 71 } 72 } 73 74 Dynamicweb.Context.Current.Items.Add("badgeConfigurations", badgeConfigurations); 75 } 76 77 int badgesCount = 0; 78 if (badgeConfigurations.Any()) 79 { 80 foreach (string campaign in campaignBadgesValues) 81 { 82 if (!string.IsNullOrEmpty(campaign)) 83 { 84 FieldValueViewModel availableCampaignsObject; 85 product.ProductFields.TryGetValue("Campaign", out availableCampaignsObject); 86 87 if (availableCampaignsObject != null) 88 { 89 string campaignType = string.Empty; 90 91 if (badgeConfigurations.ContainsKey(campaign)) 92 { 93 ParagraphInfoViewModel paragraphviewModel; 94 if (badgeConfigurations.TryGetValue(campaign, out paragraphviewModel)) 95 { 96 campaignType = paragraphviewModel.Item.GetRawValueString("CampaignType"); 97 } 98 } 99 100 List<FieldOptionValueViewModel> availableCampaigns = (List<FieldOptionValueViewModel>)availableCampaignsObject.Value; 101 102 foreach (FieldOptionValueViewModel availableOption in availableCampaigns) 103 { 104 if (campaignType == availableOption.Value) 105 { 106 badgesCount++; 107 break; 108 } 109 } 110 } 111 } 112 } 113 } 114 115 bool saleBadgeEnabled = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("SaleBadgeDesign")) && Model.Item.GetRawValueString("SaleBadgeDesign") != "none" ? true : false; 116 bool newBadgeEnabled = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("NewBadgeDesign")) && Model.Item.GetRawValueString("NewBadgeDesign") != "none" ? true : false; 117 DateTime createdDate = product.Created.Value; 118 bool showBadges = saleBadgeEnabled && product.Discount.Price != 0 ? true : false; 119 showBadges = (newBadgeEnabled && Model.Item.GetInt32("NewPublicationDays") == 0) || (newBadgeEnabled && (createdDate.AddDays(Model.Item.GetInt32("NewPublicationDays")) > DateTime.Now)) ? true : showBadges; 120 showBadges = (!string.IsNullOrEmpty(Model.Item.GetRawValueString("CampaignBadges")) && badgesCount != 0) || showComingSoonBadge || showBadges; 121 122 if (showBadges) 123 { 124 <div class="@badgeSize @horizontalAlign item_@Model.Item.SystemName.ToLower()"> 125 @RenderPartial("Components/EcommerceBadge_Custom.cshtml", product, badgeParms) @*//CUSTOM*@ 126 </div> 127 } 128 else if (Pageview.IsVisualEditorMode) 129 { 130 <span class="badge bg-success text-light rounded-0">@Translate("Badge example")</span> 131 } 132 } 133 else if (Pageview.IsVisualEditorMode) 134 { 135 <span class="badge bg-success text-light rounded-0">@Translate("Badge example")</span> 136 } 137 138
Error executing template "Designs/Swift/Paragraph/Swift_BackInStockNotification_Custom.cshtml" System.NullReferenceException: Object reference not set to an instance of an object. at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.CreateView(ProductViewModelSettings settings, ProductFieldValue pfv) at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.GetProductFieldValues(ProductViewModelSettings settings, Product product) at System.Lazy`1.CreateValue() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Lazy`1.get_Value() at CompiledRazorTemplates.Dynamic.RazorEngine_bd2da2e1f84b497481c5a93d146ce59f.Execute() in E:\Solutions\Eva Solo\Files\Templates\Designs\Swift\Paragraph\Swift_BackInStockNotification_Custom.cshtml:line 48 at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader) at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer) at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter) at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template) at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template) at Dynamicweb.Rendering.Template.RenderRazorTemplate()
1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 2 @using System @*//CUSTOM*@ 3 @using System.Linq 4 @using Dynamicweb.Ecommerce 5 @using Dynamicweb.Ecommerce.ProductCatalog 6 @using Dynamicweb.Ecommerce.Products 7 @using Dynamicweb.Ecommerce.Stocks 8 @using Dynamicweb.Core @*//CUSTOM*@ 9 10 @* CUSTOMIZED STANDARD SWIFT (v1.25.0) TEMPLATE *@ 11 12 @functions 13 { 14 private static bool BackInStockRegisteredForUser(ProductViewModel product, string unitId = "", long stocklocationId = 0) 15 { 16 if (!Dynamicweb.Security.UserManagement.User.IsExtranetUserLoggedIn()) return false; 17 18 Product productObject = Services.Products.GetProductById(product.Id, product.VariantId, product.LanguageId); 19 StockLocation stockLocation = Services.StockService.GetStockLocation(stocklocationId); 20 double unitStock = productObject.GetUnitStock(stockLocation, unitId); 21 return unitStock <= 0d && ProductBackInStockNotification.BackInStockNotificationExists(productObject, unitId); 22 } 23 } 24 25 @{ 26 ProductViewModel product = null; 27 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 28 { 29 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 30 } 31 else if (Pageview.Page.Item["DummyProduct"] != null) 32 { 33 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 34 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 35 36 if (productList?.Products is object) 37 { 38 product = productList.Products[0]; 39 } 40 } 41 } 42 43 @if ((product is object)) 44 { 45 bool productInStock = product.StockLevel > 0 || product.NeverOutOfstock; 46 47 //CUSTOM 48 DateTime launchDate = product.ProductFields.ContainsKey("Custom_LaunchDate") ? Converter.ToDateTime(product.ProductFields["Custom_LaunchDate"].Value) : DateTime.MinValue; 49 DateTime currentDate = DateTime.Today; 50 bool beforeLaunchDate = currentDate < launchDate; 51 //--CUSTOM 52 53 if (!productInStock || beforeLaunchDate) //CUSTOM 54 { 55 string notifiedMessage = Model.Item.GetString("NotifiedMessage"); 56 string notifiedMessageId = $"NotifiedMessage_item_{Model.Item.SystemName.ToLower()}_{product.Id}_{product.VariantId.Replace(".", "_")}"; 57 58 string horizontalAlign = Model.Item.GetRawValueString("HorizontalAlignment", ""); 59 horizontalAlign = horizontalAlign == "center" ? "justify-content-center" : horizontalAlign; 60 horizontalAlign = horizontalAlign == "end" ? "justify-content-end" : horizontalAlign; 61 horizontalAlign = horizontalAlign == "full" ? "" : horizontalAlign; 62 63 string flexFill = Model.Item.GetRawValueString("HorizontalAlignment", "") == "full" ? "flex-fill" : ""; 64 string fullWidth = Model.Item.GetRawValueString("HorizontalAlignment", "") == "full" ? "w-100" : ""; 65 66 bool notificationRegisteredForUser = BackInStockRegisteredForUser(product); 67 68 <div class="d-flex flex-row w-100 @horizontalAlign @fullWidth item_@Model.Item.SystemName.ToLower()"> 69 <div class="@horizontalAlign @fullWidth @(notificationRegisteredForUser ? "" : "d-none")" id="@notifiedMessageId"> 70 @notifiedMessage 71 </div> 72 73 @if (!notificationRegisteredForUser) 74 { 75 76 string notifyIcon = Model.Item.GetString("Icon"); 77 string notifyLabel = !notifyIcon.Contains("_none") ? "<span class=\"icon-2\">" + ReadFile(notifyIcon) + "</span>" : ""; 78 notifyLabel += " " + Translate("Notify me when available"); 79 80 string buttonSize = Model.Item.GetRawValueString("ButtonSize", "regular"); 81 string inputSize = string.Empty; 82 83 switch (buttonSize) 84 { 85 case "small": 86 inputSize = " input-group-sm"; 87 buttonSize = " btn-sm"; 88 break; 89 case "regular": 90 buttonSize = string.Empty; 91 break; 92 case "large": 93 inputSize = " input-group-lg"; 94 buttonSize = " btn-lg"; 95 break; 96 } 97 98 string modalId = $"modal_item_{Model.Item.SystemName.ToLower()}_{product.Id}_{product.VariantId.Replace(".", "_")}"; 99 string formId = $"NotificationForm_item_{Model.Item.SystemName.ToLower()}_{product.Id}_{product.VariantId.Replace(".", "_")}"; 100 string notificationButtonId = $"NotificationButton_item_{Model.Item.SystemName.ToLower()}_{product.Id}_{product.VariantId.Replace(".", "_")}"; 101 string notificationOnClick = !Pageview.IsVisualEditorMode ? $"swift.BackInStockNotification.SubmitNotification('{formId}', '{modalId}', '{notifiedMessageId}', '{notificationButtonId}')" : ""; 102 103 string productPage = $"Default.aspx?ID={GetPageIdByNavigationTag("ProductDetailPage")}"; 104 105 <div class="d-flex @horizontalAlign @fullWidth js-input-group"> 106 <div class="input-group input-primary-button-group flex-nowrap@(inputSize)"> 107 <button type="button" class="btn btn-primary @(buttonSize) @flexFill" id="@notificationButtonId" data-bs-toggle="modal" data-bs-target="#@modalId"> 108 @notifyLabel @*//CUSTOM*@ 109 </button> 110 </div> 111 </div> 112 113 <div class="modal fade" id="@modalId" tabindex="-1" aria-labelledby="label_@modalId" aria-hidden="true"> 114 <div class="modal-dialog modal-dialog-centered"> 115 <div class="modal-content"> 116 <div class="modal-header"> 117 <h5 class="modal-title" id="label_@modalId">@Translate("Back in Stock")</h5> 118 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="@Dynamicweb.Core.Encoders.HtmlEncoder.HtmlAttributeEncode(Translate("Close"))"></button> @*//CUSTOM*@ 119 </div> 120 <div class="modal-body"> 121 <form name="@product.Id" id="@formId" method="post" action="@productPage"> 122 <input type="hidden" name="ProductID" value="@product.Id" /> 123 <input type="hidden" name="VariantID" value="@product.VariantId" /> 124 <input type="hidden" name="LanguageID" value="@product.LanguageId" /> 125 <input type="hidden" name="CartCmd" value="createnotificationforthisproduct" /> 126 <div class="m-2"> 127 @Translate("Send me an email when the product is in stock.") 128 </div> 129 <div class="form-floating m-2"> 130 <input class="form-control" type="text" id="NotificationEmail" value="@(Pageview.User != null ? Pageview.User.Email : "")" name="NotificationEmail" placeholder="@Dynamicweb.Core.Encoders.HtmlEncoder.HtmlAttributeEncode(Translate("Email"))" required="required" aria-required="true" /> @*//CUSTOM*@ 131 <label for="NotificationEmail" class="form-label">@Translate("Email")</label> 132 </div> 133 </form> 134 </div> 135 <div class="modal-footer"> 136 <button type="button" class="btn btn-primary" onclick="@notificationOnClick">@Translate("Submit")</button> 137 </div> 138 </div> 139 </div> 140 </div> 141 } 142 </div> 143 } 144 } 145 else if (Pageview.IsVisualEditorMode) 146 { 147 <div class="alert alert-dark m-0">@Translate("Back in stock notification will be shown here")</div> 148 } 149
![]()
![]()
![]()
![]()
Error executing template "/Designs/Swift/Paragraph/Swift_Custom_ProductDeliveryInfo.cshtml" System.NullReferenceException: Object reference not set to an instance of an object. at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.CreateView(ProductViewModelSettings settings, ProductFieldValue pfv) at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.GetProductFieldValues(ProductViewModelSettings settings, Product product) at System.Lazy`1.CreateValue() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Lazy`1.get_Value() at CompiledRazorTemplates.Dynamic.RazorEngine_fe16e453f9944c27ae3beb8384847c04.Execute() in E:\Solutions\Eva Solo\Files\Templates\Designs\Swift\Paragraph\Swift_Custom_ProductDeliveryInfo.cshtml:line 55 at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader) at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer) at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter) at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template) at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template) at Dynamicweb.Rendering.Template.RenderRazorTemplate()
1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 2 @using Dynamicweb.Ecommerce.ProductCatalog 3 @using Dynamicweb.Ecommerce.CustomerExperienceCenter.Favorites 4 @using Dynamicweb.Ecommerce.Products.FieldDisplayGroups 5 @using Dynamicweb.Frontend 6 @using Dynamicweb.Core 7 @using System.Drawing 8 @using System.Web 9 @using Dynamicweb.Environment 10 @using System.Globalization 11 12 @* CUSTOM TEMPLATE SUPPORTED BY SWIFT (v1.25.0) *@ 13 14 @{ 15 bool isVisualEditor = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("VisualEdit")) ? Convert.ToBoolean(Dynamicweb.Context.Current.Request.QueryString.Get("VisualEdit")) : false; 16 17 ProductViewModel product = new ProductViewModel(); 18 19 ProductViewModelSettings productSetting = new ProductViewModelSettings 20 { 21 LanguageId = Dynamicweb.Ecommerce.Common.Context.LanguageID, 22 CurrencyCode = Dynamicweb.Ecommerce.Common.Context.Currency.Code, 23 CountryCode = Dynamicweb.Ecommerce.Common.Context.Country.Code2, 24 ShopId = Pageview.Area.EcomShopId 25 }; 26 27 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 28 { 29 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 30 } 31 else if (Pageview.Item["DummyProduct"] != null) 32 { 33 34 string dummyProductId = ""; 35 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 36 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 37 if (productList.Products != null) 38 { 39 foreach (var p in productList.Products) { dummyProductId = p.Id; } 40 ProductViewModel dummyProduct = dummyProductId != "" ? ViewModelFactory.CreateView(productSetting, dummyProductId) : new ProductViewModel(); 41 product = dummyProduct; 42 } 43 else 44 { 45 product = ViewModelFactory.CreateView(productSetting, Dynamicweb.Ecommerce.Services.Products.GetLastActiveProducts(1, Dynamicweb.Ecommerce.Common.Context.LanguageID, false).FirstOrDefault().Id); 46 } 47 } 48 else if (Pageview.Item["DummyProduct"] == null) 49 { 50 product = ViewModelFactory.CreateView(productSetting, Dynamicweb.Ecommerce.Services.Products.GetLastActiveProducts(1, Dynamicweb.Ecommerce.Common.Context.LanguageID, false).FirstOrDefault().Id); 51 } 52 53 if (product is object) 54 { 55 bool requiresCustomCarrier = product.ProductFields.ContainsKey("Custom_Carrier") ? Converter.ToBoolean(product.ProductFields["Custom_Carrier"].Value) : false; 56 var isNotForSaleText = Pageview.AreaSettings.GetItem("CustomSettings").GetString("Custom_NotForSaleRichTxt"); 57 bool plytixIsNotForSale = product.ProductFields.ContainsKey("Custom_NotForSale") ? Converter.ToBoolean(product.ProductFields["Custom_NotForSale"].Value) : false; 58 59 if (!plytixIsNotForSale) 60 { 61 <div class="order-3 small mb-3 mb-lg-0"> 62 <ul class="list-unstyled"> 63 <li><span class="icon-2">@ReadFile("/Files/Templates/Designs/Swift/Assets/icons/check.svg")</span> <span class="ms-2">@Translate("Free delivery")</span></li> 64 <li><span class="icon-2">@ReadFile("/Files/Templates/Designs/Swift/Assets/icons/check.svg")</span> <span class="ms-2">@Translate("Delivery time: 1-3 business days")</span></li> 65 @if (requiresCustomCarrier) 66 { 67 <li class="mt-3"><span><strong>@Translate("This product requires a carrier")</strong></span></li> 68 } 69 </ul> 70 </div> 71 } 72 else 73 { 74 <div class="order-3 small mb-3 mb-lg-0"> 75 <div>@isNotForSaleText</div> 76 </div> 77 } 78 } 79 } 80
Error executing template "/Designs/Swift/Paragraph/Swift_ProductSpecification_Custom.cshtml" System.NullReferenceException: Object reference not set to an instance of an object. at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.CreateView(ProductViewModelSettings settings, ProductFieldValue pfv) at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.GetProductFieldValues(ProductViewModelSettings settings, Product product) at System.Lazy`1.CreateValue() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Lazy`1.get_Value() at CompiledRazorTemplates.Dynamic.RazorEngine_f0211c8aceb14a2580502254331340f9.Execute() in E:\Solutions\Eva Solo\Files\Templates\Designs\Swift\Paragraph\Swift_ProductSpecification_Custom.cshtml:line 89 at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader) at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer) at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter) at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template) at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template) at Dynamicweb.Rendering.Template.RenderRazorTemplate()
1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 2 @using Dynamicweb.Core @*//CUSTOM*@ 3 @using Dynamicweb.Ecommerce.ProductCatalog 4 5 @* CUSTOM TEMPLATE SUPPORTED BY SWIFT (v1.20.0) - NOTE: THIS TEMPLATE IS NOT SUPPORTED IN DW10 *@ 6 @* STANDARD TEMPLATE IS DEPRECATED IN SWIFT (1.25.0) *@ 7 8 @{ 9 bool isVisualEditor = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("VisualEdit")) ? Convert.ToBoolean(Dynamicweb.Context.Current.Request.QueryString.Get("VisualEdit")) : false; 10 11 ProductViewModel product = new ProductViewModel(); 12 13 ProductViewModelSettings productSetting = new ProductViewModelSettings 14 { 15 LanguageId = Dynamicweb.Ecommerce.Common.Context.LanguageID, 16 CurrencyCode = Dynamicweb.Ecommerce.Common.Context.Currency.Code, 17 CountryCode = Dynamicweb.Ecommerce.Common.Context.Country.Code2, 18 ShopId = Pageview.Area.EcomShopId 19 }; 20 21 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 22 { 23 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 24 } 25 else if (Pageview.Item["DummyProduct"] != null) 26 { 27 28 string dummyProductId = ""; 29 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 30 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 31 if (productList.Products != null) 32 { 33 foreach (var p in productList.Products) { dummyProductId = p.Id; } 34 ProductViewModel dummyProduct = dummyProductId != "" ? ViewModelFactory.CreateView(productSetting, dummyProductId) : new ProductViewModel(); 35 product = dummyProduct; 36 } 37 else 38 { 39 product = ViewModelFactory.CreateView(productSetting, Dynamicweb.Ecommerce.Services.Products.GetLastActiveProducts(1, Dynamicweb.Ecommerce.Common.Context.LanguageID, false).FirstOrDefault().Id); 40 } 41 } 42 else if (Pageview.Item["DummyProduct"] == null) 43 { 44 product = ViewModelFactory.CreateView(productSetting, Dynamicweb.Ecommerce.Services.Products.GetLastActiveProducts(1, Dynamicweb.Ecommerce.Common.Context.LanguageID, false).FirstOrDefault().Id); 45 } 46 } 47 48 @if (product?.Id != null) 49 { 50 IEnumerable<string> selectedDisplayGroupIds = Model.Item.GetRawValueString("DisplayGroups").Split(',').ToList(); 51 List<CategoryFieldViewModel> displayGroups = new List<CategoryFieldViewModel>(); 52 53 foreach (var selection in selectedDisplayGroupIds) 54 { 55 foreach (CategoryFieldViewModel group in product.FieldDisplayGroups.Values) 56 { 57 if (selection == group.Id) 58 { 59 displayGroups.Add(group); 60 } 61 } 62 } 63 64 bool showProductFields = Model.Item.GetBoolean("ProductFields"); 65 66 bool hideTitle = Model.Item.GetBoolean("HideTitle"); 67 68 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 69 70 string titleFontSize = Model.Item.GetRawValueString("TitleFontSize", "display-4"); 71 72 string contentPadding = Model.Item.GetRawValueString("ContentPadding", ""); 73 contentPadding = contentPadding == "small" ? "p-2 p-md-3" : contentPadding; 74 contentPadding = contentPadding == "large" ? "p-4 p-md-5" : contentPadding; 75 76 string layout = Model.Item.GetRawValueString("Layout", "list"); 77 string size = Model.Item.GetRawValueString("Size", "full"); 78 79 if (Pageview.IsVisualEditorMode && displayGroups.Count() == 0) 80 { 81 product.ProductFields.Clear(); 82 product.ProductFields.Add(Translate("Width"), new FieldValueViewModel { Name = Translate("Width"), Value = "99cm" }); 83 product.ProductFields.Add(Translate("Height"), new FieldValueViewModel { Name = Translate("Height"), Value = "195cm" }); 84 showProductFields = true; 85 } 86 87 <div class="@(theme) h-100 item_@Model.Item.SystemName.ToLower()" id="specifications"> 88 <div class="@contentPadding"> 89 @if ((product.ProductFields != null && Model.Item.GetBoolean("ProductFields")) || (product.ProductCategories != null && Model.Item.GetBoolean("CategoryFields")) || (displayGroups.Count != 0)) 90 { 91 if (!hideTitle) 92 { 93 <div class="text-start pb-2 pb-lg-4"> 94 <h2 class="@titleFontSize">@Model.Item.GetString("Title")</h2> 95 </div> 96 } 97 } 98 99 @if (displayGroups.Count != 0) 100 { 101 <div class="accordion-specifications-container col-12 col-lg-10 mx-auto"> 102 <div class="accordion accordion-flush" id="accordionSpecifications"> 103 104 @*//CUSTOM*@ 105 @if (product.LongDescription.IsNotNullOrEmpty()) 106 { 107 <div class="accordion-item"> 108 <div class="accordion-header" id="specifications-heading-longdescription"> 109 <button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#specifications-collapse-longdescription" aria-expanded="false" aria-controls="specifications-collapse-longdescription"> 110 <h4 class="h4 mb-0">@Translate("Custom:ProductSpecification.Description.Heading", "Beskrivelse")</h4> 111 </button> 112 </div> 113 <div id="specifications-collapse-longdescription" class="accordion-collapse collapse small show" aria-labelledby="specifications-heading-longdescription" data-bs-parent="#accordionSpecifications"> 114 <div class="grid"> 115 <div class="g-col-12 g-col-lg-8 mb-3 js-custom-ellipsis-readmore custom-ellipsis-readmore" data-ellipsis-readmore="5"> 116 <div class="custom-ellipsis-readmore__content">@product.LongDescription</div> 117 <div class="custom-ellipsis-readmore__readmore" onclick="this.parentNode.classList.add('show');"><u>@Translate("Custom:ProductSpecification.Description.ReadMore", "Læs mere")</u></div> 118 </div> 119 </div> 120 </div> 121 </div> 122 } 123 @*//--CUSTOM*@ 124 125 @*//CUSTOM*@ 126 @if (product.ProductCategories != null) 127 { 128 var productCategoryGroups = product.ProductCategories.Values 129 .SelectMany(category => category.Fields?.Where(i => i.Key == "Custom_DesignerArticles" || i.Key == "Custom_CaseArticles") ?? Enumerable.Empty<KeyValuePair<string, FieldValueViewModel>>()) 130 .GroupBy(i => i.Key) 131 .Select(g => new 132 { 133 Key = g.Key, 134 PageIds = g.SelectMany(j => j.Value.ToString().Split(',')).Select(j => int.TryParse(j, out int k) ? k : (int?)null).Where(j => j.HasValue).Select(j => j.Value).ToArray() 135 }) 136 .Where(g => g.PageIds.Any()) 137 .ToDictionary( 138 g => g.Key, 139 g => Dynamicweb.Content.Services.Pages.GetPages(g.PageIds).Select(p => Dynamicweb.Content.Services.Pages.GetPageOrLanguage(p.ID, Pageview.Area.ID)).Where(p => p != null && p.ItemType == "Swift_Article").ToList() 140 ); 141 142 foreach (var productCategoryGroup in productCategoryGroups) 143 { 144 if (productCategoryGroup.Value.Any()) 145 { 146 string groupId = productCategoryGroup.Key.Replace("_", "").ToLower(); 147 string groupKey = productCategoryGroup.Key.Replace("_", ""); 148 string groupName = productCategoryGroup.Key.Replace("Custom_", ""); 149 150 <div class="accordion-item"> 151 <div class="accordion-header" id="specifications-heading-@(groupId)"> 152 <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#specifications-collapse-@(groupId)" aria-expanded="false" aria-controls="specifications-collapse-@(groupId)"> 153 <h4 class="h4 mb-0">@Translate($"Custom:ProductSpecification.{groupKey}.Heading", groupName)</h4> 154 </button> 155 </div> 156 <div id="specifications-collapse-@(groupId)" class="accordion-collapse collapse small" aria-labelledby="specifications-heading-@(groupId)" data-bs-parent="#accordionSpecifications"> 157 <div class="mb-4"> 158 @foreach (Dynamicweb.Content.Page page in productCategoryGroup.Value) 159 { 160 <div class="grid mb-3"> 161 <div class="g-col-12 g-col-lg-5 g-col-xl-4 g-col-xxl-3"> 162 @if (page.Item.TryGetValue("CoverImage", out object coverImage)) 163 { 164 var coverImageUri = new Uri("http://dummy.com" + coverImage.ToString()); 165 var coverImagePathParams = System.Web.HttpUtility.ParseQueryString(coverImageUri.Query); 166 167 <figure class="overflow-hidden m-0 mx-auto ratio" style="--bs-aspect-ratio: 75%"> 168 @RenderPartial("Components/Image.cshtml", 169 new Dynamicweb.Frontend.FileViewModel 170 { 171 Path = System.Web.HttpUtility.UrlDecode(coverImageUri.AbsolutePath), 172 FocalX = Converter.ToInt32(coverImagePathParams["X"]), 173 FocalY = Converter.ToInt32(coverImagePathParams["Y"]) 174 }, 175 new Dictionary<string, object> 176 { 177 { "loading", "lazy" }, 178 { "alt", Converter.ToString(page.Item["Title"]) } 179 }) 180 </figure> 181 } 182 </div> 183 <div class="g-col-12 g-col-lg-7 g-col-xl-4 g-col-xxl-3"> 184 <div class="d-flex flex-column gap-2"> 185 @if (page.Item.TryGetValue("Title", out object title)) 186 { 187 <h2 class="h6 text-inherit opacity-100 mw-75ch m-0">@title</h2> 188 } 189 @if (page.Item.TryGetValue("Summary", out object summary)) 190 { 191 <div class="text-inherit opacity-100 mw-75ch"> 192 <p class="m-0">@summary</p> 193 </div> 194 } 195 <div class="d-flex flex-wrap gap-3"> 196 <a href="Default.aspx?ID=@(page.ID)" class="link">@Translate($"Custom:ProductSpecification.{groupKey}.ReadMore", "Read more »")</a> 197 </div> 198 </div> 199 </div> 200 </div> 201 } 202 </div> 203 </div> 204 </div> 205 } 206 } 207 } 208 @*//--CUSTOM*@ 209 210 @foreach (var group in displayGroups) 211 { 212 bool hideHeader = Model.Item.GetBoolean("HideGroupHeaders"); 213 string groupId = group.Id; 214 string buttonCollapsedState = Model.Item.GetBoolean("OpenDetailsAccordion") ? "" : "collapsed"; 215 string accordionShow = Model.Item.GetBoolean("OpenDetailsAccordion") ? "show" : ""; 216 217 @*//CUSTOM*@ 218 if (product.ProductType == Dynamicweb.Ecommerce.Products.ProductType.Bom && group.Id == "Product_details") 219 { 220 var apiProduct = Dynamicweb.Ecommerce.Services.Products.GetProductById(product.Id, product.VariantId, product.LanguageId, false); 221 var productNumbers = new List<string>(); 222 223 foreach (Dynamicweb.Ecommerce.Products.ProductItem item in apiProduct.Items) 224 { 225 foreach (Dynamicweb.Ecommerce.Products.Product productitem in item.Products) 226 { 227 productNumbers.Add(productitem.Number); 228 } 229 } 230 if (productNumbers.Any()) 231 { 232 string commaSeparatedNumbers = string.Join(", ", productNumbers); 233 FieldValueViewModel productNumberInBOM = new FieldValueViewModel(); 234 productNumberInBOM.Name = Translate("Custom:ProductSpecification.ProductNumbersInBOM", "Product numbers in BOM"); 235 productNumberInBOM.Value = commaSeparatedNumbers; 236 productNumberInBOM.Type = "Text"; 237 productNumberInBOM.SystemName = "ProductNumbersInBOM"; 238 group.Fields.Add("Product numbers in BOM", productNumberInBOM); 239 } 240 } 241 @*//--CUSTOM*@ 242 243 <div class="accordion-item"> 244 <div class="accordion-header" id="specifications-heading-@groupId"> 245 <button class="accordion-button @buttonCollapsedState" type="button" data-bs-toggle="collapse" data-bs-target="#specifications-collapse-@groupId" aria-expanded="false" aria-controls="specifications-collapse-@groupId"> 246 @if (!hideHeader) 247 { 248 <h4 class="h4 mb-0">@group.Name</h4> 249 } 250 </button> 251 </div> 252 <div id="specifications-collapse-@groupId" class="accordion-collapse collapse small @accordionShow" aria-labelledby="specifications-heading-@groupId" data-bs-parent="#accordionSpecifications"> 253 <div>@RenderFieldsFromList(group.Fields, layout)</div> 254 </div> 255 </div> 256 } 257 258 @if (!string.IsNullOrEmpty(Pageview.AreaSettings.GetItem("CustomSettings").GetString("FreightAndDeliveryText"))) 259 { 260 <div class="accordion-item"> 261 <div class="accordion-header" id="specifications-heading-DeliveryInfo"> 262 <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#specifications-collapse-DeliveryInfo" aria-expanded="false" aria-controls="specifications-collapse-DeliveryInfo"> 263 <h4 class="h4 mb-0">@Pageview.AreaSettings.GetItem("CustomSettings").GetString("FreightAndDeliveryHeading")</h4> 264 </button> 265 </div> 266 <div id="specifications-collapse-DeliveryInfo" class="accordion-collapse collapse small" aria-labelledby="specifications-heading-DeliveryInfo" data-bs-parent="#accordionSpecifications"> 267 <div class="mb-4">@Pageview.AreaSettings.GetItem("CustomSettings").GetString("FreightAndDeliveryText")</div> 268 </div> 269 </div> 270 } 271 272 </div> 273 </div> 274 } 275 276 @if (product.ProductFields != null && showProductFields) 277 { 278 if (product.ProductFields.Count > 0) 279 { 280 @RenderFieldsFromList(product.ProductFields, layout); 281 } 282 } 283 284 @if (product.ProductCategories != null && Model.Item.GetBoolean("CategoryFields")) 285 { 286 if (product.ProductCategories.Count > 0) 287 { 288 foreach (var group in product.ProductCategories) 289 { 290 CategoryFieldViewModel category = group.Value; 291 bool hideHeader = Model.Item.GetBoolean("HideGroupHeaders"); 292 293 if (!hideHeader) 294 { 295 <h4 class="h4 mb-4">@group.Value.Name</h4> 296 } 297 298 @RenderFieldsFromList(category.Fields, layout); 299 } 300 } 301 } 302 </div> 303 </div> 304 } 305 else if (Pageview.IsVisualEditorMode) 306 { 307 <div class="alert alert-warning m-0">@Translate("No products available")</div> 308 } 309 310 @helper RenderFieldsFromList(Dictionary<string, FieldValueViewModel> fields, string layout) 311 { 312 string size = Model.Item.GetRawValueString("Size", "full"); 313 string extraMargin = size == "full" ? "mb-3" : ""; 314 bool hideFieldLabels = Model.Item.GetBoolean("HideFieldLabels"); 315 316 <div class="@extraMargin"> 317 @if (layout == "columns") 318 { 319 string gaps = size == "full" ? "gap-0" : "gap-2"; 320 321 <div class="grid @gaps"> 322 @foreach (var field in fields) 323 { 324 @RenderField(field.Value, layout) 325 } 326 </div> 327 } 328 @if (layout == "list") 329 { 330 <dl class="grid gap-0"> 331 @foreach (var field in fields) 332 { 333 @RenderField(field.Value, layout) 334 } 335 </dl> 336 } 337 @if (layout == "table") 338 { 339 string tableSize = size == "full" ? "" : "table-sm"; 340 341 <table class="table table-striped @tableSize"> 342 @foreach (var field in fields) 343 { 344 @RenderField(field.Value, layout) 345 } 346 </table> 347 } 348 @if (layout == "bullets") 349 { 350 string listSize = size == "full" ? "" : "m-0 p-0 lh-1 fs-7 opacity-75"; 351 string listStyle = size == "full" ? "" : "style=\"list-style-position: inside\""; 352 353 <ul class="@listSize" @listStyle> 354 @foreach (var field in fields) 355 { 356 @RenderField(field.Value, layout) 357 } 358 </ul> 359 } 360 @if (layout == "commas") 361 { 362 List<string> featuresList = new List<string>(); 363 364 foreach (var field in fields) 365 { 366 if (field.Value.Value.GetType() == typeof(System.Collections.Generic.List<FieldOptionValueViewModel>)) 367 { 368 List<string> options = new List<string>(); 369 foreach (FieldOptionValueViewModel option in field.Value.Value as System.Collections.Generic.List<FieldOptionValueViewModel>) 370 { 371 if (!string.IsNullOrWhiteSpace(option.Value)) 372 { 373 if (option.Value.ToString().Contains("#") && (Translate(field.Value.Name) == Translate("Color") || Translate(field.Value.Name) == Translate("Colour"))) 374 { 375 string colorSpan = "<span class=\"colorbox-sm\" style=\"background-color: " + option.Value + "\"></span>"; 376 options.Add(colorSpan); 377 } 378 else if (!string.IsNullOrEmpty(option.Value)) 379 { 380 options.Add(option.Name); 381 } 382 } 383 } 384 string optionsString = (string.Join(", ", options.Select(x => x.ToString()).ToArray())); 385 if ((Translate(field.Value.Name) == Translate("Color") || Translate(field.Value.Name) == Translate("Colour"))) 386 { 387 optionsString = (string.Join(" ", options.Select(x => x.ToString()).ToArray())); 388 } 389 390 if (!hideFieldLabels) 391 { 392 featuresList.Add(field.Value.Name + ": " + optionsString); 393 } 394 else 395 { 396 featuresList.Add(optionsString); 397 } 398 } 399 else 400 { 401 if (!string.IsNullOrWhiteSpace(field.Value.Value.ToString())) 402 { 403 if (field.Value.Value.ToString().Contains("#") && (Translate(field.Value.Name) == Translate("Color") || Translate(field.Value.Name) == Translate("Colour"))) 404 { 405 string colorSpan = "<span class=\"colorbox-sm\" style=\"background-color: " + field.Value.Value + "\"></span>"; 406 407 if (!hideFieldLabels) 408 { 409 featuresList.Add(field.Value.Name + ": " + colorSpan); 410 } 411 else 412 { 413 featuresList.Add(colorSpan); 414 } 415 } 416 else 417 { 418 if (!hideFieldLabels) 419 { 420 featuresList.Add(field.Value.Name + ": " + field.Value.Value.ToString()); 421 } 422 else 423 { 424 featuresList.Add(field.Value.Value.ToString()); 425 } 426 } 427 } 428 } 429 } 430 431 string featuresString = (string.Join(", ", featuresList.Select(x => x.ToString()).ToArray())); 432 433 <div class="opacity-75 fs-7">@featuresString</div> 434 } 435 </div> 436 } 437 438 @helper RenderField(FieldValueViewModel field, string layout) 439 { 440 string size = Model.Item.GetRawValueString("Size", "full"); 441 string fieldValue = field?.Value != null ? field.Value.ToString() : ""; 442 bool hideFieldLabels = Model.Item.GetBoolean("HideFieldLabels"); 443 bool noValues = false; 444 445 if (!string.IsNullOrEmpty(fieldValue)) 446 { 447 if (field.Value.GetType() == typeof(System.Collections.Generic.List<FieldOptionValueViewModel>)) 448 { 449 System.Collections.Generic.List<FieldOptionValueViewModel> values = field.Value as System.Collections.Generic.List<FieldOptionValueViewModel>; 450 noValues = values.Count > 0 ? false : true; 451 } 452 } 453 454 if (!string.IsNullOrEmpty(fieldValue) && noValues == false) 455 { 456 if (layout == "columns") 457 { 458 <div class="grid g-col-6 g-col-lg-4"> 459 @if (!hideFieldLabels) 460 { 461 <dt class="g-col-4 py-2 fw-bold">@field.Name</dt> 462 } 463 <dd class="g-col-8 py-2 mb-0">@RenderFieldValue(field)</dd> 464 </div> 465 } 466 if (layout == "list") 467 { 468 string extraPadding = size == "full" ? "py-2" : ""; 469 470 if (!hideFieldLabels) 471 { 472 <dt class="g-col-4 @extraPadding fw-bold">@field.Name</dt> 473 } 474 <dd class="g-col-8 @extraPadding mb-0"> 475 @RenderFieldValue(field) 476 </dd> 477 } 478 if (layout == "table") 479 { 480 <tr> 481 @if (!hideFieldLabels) 482 { 483 <th class="fw-bold" scope="row">@field.Name</th> 484 } 485 <td>@RenderFieldValue(field)</td> 486 </tr> 487 } 488 if (layout == "bullets") 489 { 490 <li> 491 @if (!hideFieldLabels) 492 { 493 <strong>@field.Name</strong> 494 } 495 <span>@RenderFieldValue(field)</span> 496 </li> 497 } 498 } 499 } 500 501 @helper RenderFieldValue(FieldValueViewModel field) 502 { 503 string fieldValue = field?.Value != null ? field.Value.ToString() : ""; 504 505 bool isLink = field?.Type == "Link"; 506 bool isColor = false; 507 bool isBrandName = field?.SystemName == "Brand_name"; 508 509 fieldValue = fieldValue == "False" ? Translate("No") : fieldValue; 510 fieldValue = fieldValue == "True" ? Translate("Yes") : fieldValue; 511 512 513 if (field.Value.GetType() == typeof(System.Collections.Generic.List<Dynamicweb.Ecommerce.ProductCatalog.FieldOptionValueViewModel>)) 514 { 515 int valueCount = 0; 516 System.Collections.Generic.List<FieldOptionValueViewModel> values = field.Value as System.Collections.Generic.List<FieldOptionValueViewModel>; 517 int totalValues = values.Count; 518 519 foreach (FieldOptionValueViewModel option in values) 520 { 521 if (option.Value.Substring(0, 1) == "#") 522 { 523 isColor = true; 524 } 525 526 if (!isColor) 527 { 528 @option.Name 529 } 530 else 531 { 532 <span class="colorbox-sm" style="background-color: @option.Value" title="@option.Name"></span> 533 } 534 535 if (valueCount != totalValues && valueCount < (totalValues - 1)) 536 { 537 if (isColor) 538 { 539 <text> </text> 540 } 541 else 542 { 543 <text>, </text> 544 } 545 } 546 valueCount++; 547 } 548 } 549 else 550 { 551 if (fieldValue.Substring(0, 1) == "#") 552 { 553 isColor = true; 554 } 555 556 if (!isColor) 557 { 558 if (isLink) 559 { 560 string linktTitle = !fieldValue.Contains("aspx") ? fieldValue : Translate("Go to link"); 561 string target = Pageview.AreaSettings.GetBoolean("OpenLinksInNewTab") && fieldValue.Contains("http") ? "target=\"_blank\"" : string.Empty; 562 string rel = Pageview.AreaSettings.GetBoolean("OpenLinksInNewTab") && fieldValue.Contains("http") ? "rel=\"noopener\"" : string.Empty; 563 564 <a href="@field.Value" title="@field.Name" @target @rel>@linktTitle</a> 565 } 566 else if (isBrandName) 567 { 568 <span itemprop="brand" itemtype="https://schema.org/Brand" itemscope> 569 <span itemprop="name">@fieldValue</span> 570 </span> 571 } 572 else 573 { 574 //CUSTOM 575 if (!new string[] { "ProductNumber", "ProductEAN" }.Contains(field.SystemName)) 576 { 577 @Translate("Custom:FacetOption." + fieldValue, fieldValue) 578 } 579 else 580 { 581 @fieldValue 582 } 583 //--CUSTOM 584 } 585 } 586 else 587 { 588 <span class="colorbox-sm" style="background-color: @fieldValue" title="@fieldValue"></span> 589 } 590 } 591 } 592
Tagga oss i ditt instagram-inlägg för att synas i vår Eva Solo Community.
Använd en av följande taggar: @evasolo_official, #evasolo, #evatrio eller #evasolofurniture.
Error executing template "Designs/Swift/Paragraph/Swift_RelatedProducts_Custom.cshtml" System.NullReferenceException: Object reference not set to an instance of an object. at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.CreateView(ProductViewModelSettings settings, ProductFieldValue pfv) at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.GetProductFieldValues(ProductViewModelSettings settings, Product product) at System.Lazy`1.CreateValue() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Lazy`1.get_Value() at CompiledRazorTemplates.Dynamic.RazorEngine_690b0413c1064d38b404af0256a03660.Execute() in E:\Solutions\Eva Solo\Files\Templates\Designs\Swift\Paragraph\Swift_RelatedProducts_Custom.cshtml:line 153 at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader) at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer) at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter) at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template) at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template) at Dynamicweb.Rendering.Template.RenderRazorTemplate()
1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 2 @using System 3 @using System.Collections.Generic 4 @using System.Linq 5 @using Dynamicweb 6 @using Dynamicweb.Core 7 @using Dynamicweb.Core.Encoders 8 @using Dynamicweb.Environment 9 @using Dynamicweb.Ecommerce.ProductCatalog 10 @using Dynamicweb.Ecommerce.Products 11 @using Dynamicweb.Frontend 12 @using Custom.EvaSolo.Ecommerce.Helpers 13 @using Smartpage.EvaSolo.Clerk.Helpers 14 15 @* CUSTOMIZED STANDARD SWIFT (v1.25.0) TEMPLATE *@ 16 17 @{ 18 ProductViewModel product = null; 19 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 20 { 21 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 22 } 23 else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode) 24 { 25 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 26 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 27 28 if (productList?.Products is object) 29 { 30 product = productList.Products[0]; 31 } 32 } 33 34 string title = Model?.Item?.GetRawValueString("Title", Translate("Products")); 35 string campaignValues = Model.Item.GetRawValueString("CampaignBadges", string.Empty); 36 37 //Styling 38 string titleFontSize = Model.Item.GetRawValueString("TitleFontSize", "h3"); 39 string subtitleFontSize = Model.Item.GetRawValueString("SubtitleFontSize", "fs-5"); 40 string buttonStyle = Model.Item.GetRawValueString("ButtonStyle", ""); 41 buttonStyle = buttonStyle == "primary" ? " btn-primary" : buttonStyle; 42 buttonStyle = buttonStyle == "secondary" ? " btn-secondary" : buttonStyle; 43 buttonStyle = buttonStyle == "link" ? " btn-link" : buttonStyle; 44 string maxWidth = Model.Item.GetRawValueString("TextReadability", ""); 45 maxWidth = maxWidth == "max-width-on" ? " mw-75ch" : maxWidth; 46 maxWidth = maxWidth == "max-width-off" ? "" : maxWidth; 47 48 string generalTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("GeneralTheme")) ? " theme " + Model.Item.GetRawValueString("GeneralTheme").Replace(" ", "").Trim().ToLower() : ""; 49 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 50 string imageTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("ImageTheme")) ? " theme " + Model.Item.GetRawValueString("ImageTheme").Replace(" ", "").Trim().ToLower() : ""; 51 52 //Link generation 53 string pageId = !string.IsNullOrEmpty(Model.Item.GetRawValueString("ProductSliderServicePage")) ? Model.Item.GetLink("ProductSliderServicePage").PageId.ToString() : ""; 54 if (string.IsNullOrEmpty(pageId)) 55 { 56 pageId = GetPageIdByNavigationTag("ProductSliderService").ToString(); 57 } 58 59 string url = "/Default.aspx?ID=" + pageId; 60 if (!url.Contains("LayoutTemplate", StringComparison.OrdinalIgnoreCase)) 61 { 62 url += url.Contains("?") ? "&LayoutTemplate=Designs/Swift/Swift_PageClean.cshtml" : "?LayoutTemplate=Designs/Swift/Swift_PageClean.cshtml"; 63 } 64 65 if (Pageview.IsVisualEditorMode) 66 { 67 url += "&VisualEdit=True"; 68 } 69 70 bool isLazyLoadingForProductInfoEnabled = Dynamicweb.Core.Converter.ToBoolean(Dynamicweb.Context.Current.Items["IsLazyLoadingForProductInfoEnabled"]); 71 if (isLazyLoadingForProductInfoEnabled) 72 { 73 url += "&getproductinfo=true"; 74 } 75 76 //Source type 77 string sourceType = Model.Item.GetRawValueString("RelationType", "trending"); 78 IList<string> relateFromGroupIds = new List<string> { }; 79 IList<string> relateFromProductVariantIds = new List<string> { }; 80 IList<string> relateFromProductIds = new List<string> { }; 81 bool hasVariants = false; 82 83 //--- VARIANTS --- 84 if (sourceType == "variants" && Model.Item.GetValue<ProductListViewModel>("ProductsToRelateToVariants") is ProductListViewModel productsToRelateToVariants) 85 { 86 foreach (var productSelection in productsToRelateToVariants.Products) 87 { 88 relateFromProductIds.Add(productSelection.Id); 89 } 90 } 91 92 //--- MOST SOLD --- 93 if (sourceType == "most-sold" && Model.Item.GetValue<IList<ProductGroupViewModel>>("GroupsToRelateToMostSold") is IList<ProductGroupViewModel> groupsToRelateToMostSold) 94 { 95 foreach (var fromGroup in groupsToRelateToMostSold) 96 { 97 relateFromGroupIds.Add(fromGroup.Id); 98 } 99 } 100 101 //--- TRENDING --- 102 if (sourceType == "trending" && Model.Item.GetValue<IList<ProductGroupViewModel>>("GroupsToRelateToTrending") is IList<ProductGroupViewModel> groupsToRelateToTrending) 103 { 104 foreach (var fromGroup in groupsToRelateToTrending) 105 { 106 relateFromGroupIds.Add(fromGroup.Id); 107 } 108 } 109 110 //--- LATEST --- 111 if (sourceType == "latest" && Model.Item.GetValue<IList<ProductGroupViewModel>>("GroupsToRelateToLatest") is IList<ProductGroupViewModel> groupsToRelateToLatest) 112 { 113 foreach (var fromGroup in groupsToRelateToLatest) 114 { 115 relateFromGroupIds.Add(fromGroup.Id); 116 } 117 } 118 119 //--- FREQUENTLY BOUGHT --- 120 if (sourceType == "frequently" && Model.Item.GetValue<ProductListViewModel>("ProductsToRelateTo") is ProductListViewModel productsToRelateTo) 121 { 122 foreach (var fromProduct in productsToRelateTo.Products) 123 { 124 relateFromProductIds.Add(fromProduct.Id); 125 } 126 } 127 128 //--- SELECTED PRODUCTS --- 129 if ((sourceType == "selected" || sourceType == "frequently") && Model.Item.GetValue<ProductListViewModel>("Products") is ProductListViewModel products) 130 { 131 hasVariants = products.Products.Any(p => !string.IsNullOrEmpty(p.VariantId)); 132 foreach (var productSelection in products.Products) 133 { 134 if (hasVariants) 135 { 136 if (!string.IsNullOrEmpty(productSelection.VariantId)) 137 { 138 relateFromProductVariantIds.Add($"{productSelection.Id} {productSelection.VariantId}"); 139 } 140 else 141 { 142 relateFromProductVariantIds.Add($"{productSelection.Id}"); 143 } 144 } 145 146 relateFromProductIds.Add($"{productSelection.Id}"); 147 } 148 } 149 150 //--- UPSELL PRODUCTS --- 151 if (sourceType == "upsell-products") 152 { 153 string upSell = product.ProductFields.ContainsKey("Custom_UpSell") ? Converter.ToString(product.ProductFields["Custom_UpSell"].Value) : string.Empty; 154 List<Product> upSellProducts = GetActiveUpSellProducts(upSell); 155 relateFromProductIds = upSellProducts != null ? upSellProducts.Select(p => p.Id).ToList() : new List<string>(); 156 } 157 158 //--- RELATED PRODUCTS --- 159 if (sourceType == "related-products" && Model.Item.GetValue<ProductListViewModel>("ProductsToRelateTo2") is ProductListViewModel selectedRelationProduct) 160 { 161 if (selectedRelationProduct.Products.Any()) 162 { 163 product = selectedRelationProduct.Products.FirstOrDefault(); 164 } 165 166 if (product?.RelatedGroups != null) 167 { 168 foreach (var group in product.RelatedGroups) 169 { 170 foreach (var relatedProduct in group.Products) 171 { 172 if (!string.IsNullOrEmpty(relatedProduct.VariantId)) 173 { 174 relateFromProductVariantIds.Add($"{relatedProduct.ProductId} {relatedProduct.VariantId}"); 175 } 176 else 177 { 178 relateFromProductVariantIds.Add($"{relatedProduct.ProductId}"); 179 } 180 } 181 } 182 } 183 } 184 185 //Create group id collection and products id collection strings 186 string groupIds = product is object ? product.PrimaryOrDefaultGroup.Id : string.Join(",", relateFromGroupIds); 187 string productVariantIds = relateFromProductVariantIds.Count > 0 ? string.Join(",", relateFromProductVariantIds) : ""; 188 string productIds = product is object && relateFromProductIds.Count == 0 ? product.Id : string.Join(",", relateFromProductIds); 189 //Set the parameters to the url 190 string linkParameters = ""; 191 linkParameters += sourceType != "related-products" && sourceType != "frequently" && sourceType != "selected" ? "&GroupId=" + groupIds : ""; 192 linkParameters += !string.IsNullOrEmpty(productIds) && sourceType != "most-sold" && sourceType != "trending" && sourceType != "latest" && sourceType != "frequently" && sourceType != "related-products" ? "&MainProductId=" + productIds : ""; 193 linkParameters += !string.IsNullOrEmpty(productVariantIds) && sourceType == "related-products" ? "&ProductVariantId=" + productVariantIds : ""; 194 linkParameters += sourceType == "variants" ? "&IsVariant=true" : ""; 195 linkParameters += sourceType == "latest" ? "&SortBy=Created" : ""; 196 linkParameters += sourceType == "most-sold" ? "&SortBy=OrderCount" : ""; 197 linkParameters += sourceType == "trending" ? "&SortBy=OrderCountGrowth" : ""; 198 linkParameters += !string.IsNullOrEmpty(productIds) && sourceType == "frequently" ? $"&BoughtWithProductIds=[{productIds}]" : ""; 199 var productListPageId = GetPageIdByNavigationTag("Shop"); 200 string link = "/Default.aspx?ID=" + productListPageId + linkParameters; 201 202 // Slider settings (documentation: swiffyslider.com/configuration) 203 string navigationStyle = $"{Model.Item.GetRawValueString("NavigationStyle", "slider-nav-round")}"; 204 string navigationPlacement = $"{Model.Item.GetRawValueString("NavigationPlacement", "slider-nav-on-slides")}"; 205 string indicatorStyle = $"{Model.Item.GetRawValueString("IndicatorStyle", "slider-indicators-hidden")}"; 206 string revealSlides = Model.Item.GetRawValueString("RevealSlides", "no-reveal") == "reveal" ? "slider-item-reveal" : string.Empty; 207 string navigationAlwaysVisible = (Model.Item.GetBoolean("NavigationAlwaysVisible")) ? "slider-nav-visible" : string.Empty; 208 string navigationVisibleOnTouch = (Model.Item.GetBoolean("NavigationVisibleOnTouch")) ? "slider-nav-touch" : string.Empty; 209 string navigationShowScrollbar = (Model.Item.GetBoolean("NavigationShowScrollbar")) ? "slider-nav-scrollbar" : string.Empty; 210 string navigationSmall = (Model.Item.GetBoolean("NavigationSmall")) ? "slider-nav-sm" : string.Empty; 211 string navigationInvertColors = (Model.Item.GetBoolean("NavigationInvertColors")) ? "slider-nav-dark" : string.Empty; 212 string navigationSlideEntirePage = (Model.Item.GetBoolean("NavigationSlideEntirePage")) ? "slider-nav-page" : string.Empty; 213 string navigationNoLoop = (Model.Item.GetBoolean("NavigationNoLoop")) ? "slider-nav-noloop" : string.Empty; 214 string indicatorsOutsideSlider = (Model.Item.GetBoolean("IndicatorsOutsideSlider") && indicatorStyle != string.Empty) ? "slider-indicators-outside" : string.Empty; 215 string indicatorsHighlightActive = (Model.Item.GetBoolean("IndicatorsHighlightActive")) ? "slider-indicators-highlight" : string.Empty; 216 string indicatorsInvertColors = (Model.Item.GetBoolean("IndicatorsInvertedColors")) ? "slider-indicators-dark" : string.Empty; 217 string indicatorsVisibleOnSmallDevices = (Model.Item.GetBoolean("IndicatorsVisibleOnSmallDevices")) ? "slider-indicators-sm" : string.Empty; 218 219 bool productsFound = true; 220 if (sourceType != "clerk" && string.IsNullOrEmpty(groupIds) && string.IsNullOrEmpty(productIds) && string.IsNullOrEmpty(productVariantIds)) //CUSTOM 221 { 222 if (Pageview.IsVisualEditorMode && product != null) //CUSTOM 223 { 224 productIds = product.Id; 225 sourceType = "selected"; 226 } 227 else 228 { 229 productsFound = false; 230 } 231 } 232 else if (sourceType == "upsell-products") 233 { 234 productsFound = relateFromProductIds.Count > 0; 235 } 236 } 237 238 @*//CUSTOM*@ 239 @if (Pageview.IsVisualEditorMode == true && sourceType == "clerk" && PageView.Current().AreaSettings.GetItem("CustomSettings").GetRawValueString("ClerkPublicKey_Custom").IsNullOrEmpty()) 240 { 241 <div class="alert alert-danger" role="alert"> 242 <span>@Translate("Product slider: The Clerk integration requires a public key in the website settings")</span> 243 </div> 244 } 245 @*//--CUSTOM*@ 246 247 @*Container element for the request*@ 248 @if (productsFound) 249 { 250 <form method="post" action="@url" id="RelatedProductsForm_@Model.ID" data-response-target-element="RelatedProducts_@Model.ID" data-preloader="inline" data-update-url="false" class="item_@Model.Item.SystemName.ToLower()"> 251 <input type="hidden" name="ModelID" value="@Model.ID"> 252 <input type="hidden" name="SourceType" value="@sourceType"> 253 254 @*--- SLIDER SETTINGS ---*@ 255 <input type="hidden" name="NavigationStyle" value="@navigationStyle"> 256 <input type="hidden" name="NavigationPlacement" value="@navigationPlacement"> 257 <input type="hidden" name="IndicatorStyle" value="@indicatorStyle"> 258 <input type="hidden" name="RevealSlides" value="@revealSlides"> 259 <input type="hidden" name="NavigationAlwaysVisible" value="@(navigationAlwaysVisible)"> 260 <input type="hidden" name="NavigationVisibleOnTouch" value="@(navigationVisibleOnTouch)"> 261 <input type="hidden" name="NavigationShowScrollbar" value="@(navigationShowScrollbar)"> 262 <input type="hidden" name="NavigationSmall" value="@(navigationSmall)"> 263 <input type="hidden" name="NavigationInvertColors" value="@(navigationInvertColors)"> 264 <input type="hidden" name="NavigationNoLoop" value="@(navigationNoLoop)"> 265 <input type="hidden" name="NavigationSlideEntirePage" value="@(navigationSlideEntirePage)"> 266 <input type="hidden" name="IndicatorsOutsideSlider" value="@(indicatorsOutsideSlider)"> 267 <input type="hidden" name="IndicatorsHighlightActive" value="@(indicatorsHighlightActive)"> 268 <input type="hidden" name="IndicatorsInvertColors" value="@(indicatorsInvertColors)"> 269 <input type="hidden" name="IndicatorsVisibleOnSmallDevices" value="@(indicatorsVisibleOnSmallDevices)"> 270 271 @*--- VARIANTS ---*@ 272 @if (sourceType == "variants") 273 { 274 <input type="hidden" name="isVariant" value="true"> 275 <input type="hidden" name="MainProductID" id="MainProductID_@Model.ID" value="@productIds"> 276 } 277 278 @*--- MOST SOLD ---*@ 279 @if (sourceType == "most-sold") 280 { 281 <input type="hidden" name="SortBy" value="OrderCount"> 282 if (groupIds != "") 283 { 284 <input type="hidden" name="GroupId" value="@groupIds"> 285 } 286 } 287 288 @*--- TRENDING ---*@ 289 @if (sourceType == "trending") 290 { 291 <input type="hidden" name="SortBy" value="OrderCountGrowth"> 292 if (groupIds != "") 293 { 294 <input type="hidden" name="GroupId" value="@groupIds"> 295 } 296 } 297 298 @*--- FREQUENTLY BOUGHT ---*@ 299 @if (sourceType == "frequently" && !string.IsNullOrEmpty(productIds)) 300 { 301 <input type="hidden" name="BoughtWithProductIds" value="[@productIds]"> 302 } 303 @if (sourceType != "frequently" && hasVariants) 304 { 305 <input type="hidden" name="ProductVariantId" value="@productVariantIds"> 306 } 307 308 @*--- LATEST ---*@ 309 @if (sourceType == "latest") 310 { 311 <input type="hidden" name="SortBy" value="Created"> 312 <input type="hidden" name="GroupId" value="@groupIds"> 313 } 314 315 @*--- SELECTED PRODUCTS ---*@ 316 @if (sourceType == "selected" && !string.IsNullOrEmpty(productIds) && !hasVariants) 317 { 318 <input type="hidden" name="MainProductId" id="MainProductID_@Model.ID" value="@productIds"> 319 } 320 @if (sourceType == "selected" && hasVariants) 321 { 322 <input type="hidden" name="ProductVariantId" value="@productVariantIds"> 323 } 324 325 @*--- UPSELL PRODUCTS ---*@ 326 @if (sourceType == "upsell-products" && !string.IsNullOrEmpty(productIds) && !hasVariants) 327 { 328 <input type="hidden" name="MainProductId" id="MainProductID_@Model.ID" value="@productIds"> 329 } 330 @if (sourceType == "upsell-products" && hasVariants) 331 { 332 <input type="hidden" name="ProductVariantId" value="@productVariantIds"> 333 } 334 335 @*--- RELATED PRODUCTS ---*@ 336 @if (sourceType == "related-products") 337 { 338 <input type="hidden" name="ProductVariantId" id="MainProductID_@Model.ID" value="@productVariantIds"> 339 } 340 341 @*//CUSTOM*@ 342 @*--- CLERK ---*@ 343 @if (sourceType == "clerk") 344 { 345 // Doc.: https://docs.clerk.io/reference/recommendations-popular 346 347 var clerkEndPoint = Model.Item.GetString("ClerkEndpoint"); 348 var clerkKeywords = Model.Item.GetString("ClerkKeywords"); 349 var clerkQuery = new List<string>(); 350 var clerkFilter = new List<string>(); 351 352 if (!string.IsNullOrEmpty(clerkKeywords)) 353 { 354 switch (clerkEndPoint) 355 { 356 case "recommendations/keywords": 357 clerkQuery.Add("keywords=['" + clerkKeywords + "']"); 358 break; 359 } 360 } 361 362 if (product != null && !string.IsNullOrEmpty(product.Id)) 363 { 364 switch (clerkEndPoint) 365 { 366 case "recommendations/bundle": 367 clerkQuery.Add("product=" + product.Id); 368 break; 369 370 case "recommendations/complementary": 371 case "recommendations/substituting": 372 case "recommendations/most_sold_with": 373 clerkQuery.Add("products=[" + product.Id + "]"); // NOTE: Clerk format id as integer (Data Sync product feed is string) 374 break; 375 } 376 } 377 378 IList<ProductGroupViewModel> clerkGroupsToRelateTo = Model.Item.GetValue<IList<ProductGroupViewModel>>("ClerkGroupsToRelateTo"); 379 switch (clerkEndPoint) 380 { 381 case "recommendations/category/popular": 382 case "recommendations/category/trending": 383 case "recommendations/category/new": 384 if (clerkGroupsToRelateTo != null && clerkGroupsToRelateTo.Any()) 385 { 386 clerkQuery.Add("category=" + clerkGroupsToRelateTo.First().Id); 387 } 388 else if (Context.Current.Request.HasRequest("GroupID")) 389 { 390 clerkQuery.Add("category=" + Context.Current.Request.GetString("GroupID")); 391 } 392 393 break; 394 395 default: 396 if (clerkGroupsToRelateTo != null && clerkGroupsToRelateTo.Any()) 397 { 398 clerkFilter.Add("categories in ['" + string.Join("','", clerkGroupsToRelateTo.Select(i => i.Id)) + "']"); 399 } 400 401 break; 402 } 403 404 switch (clerkEndPoint) 405 { 406 case "recommendations/page/substituting": 407 case "recommendations/page/related_products": 408 case "recommendations/page/related_categories": 409 clerkQuery.Add("page=" + Model.PageID); 410 break; 411 } 412 413 IList<ItemViewModel> clerkFilters = Model.Item.GetItems("ClerkFilters"); 414 if (clerkFilters != null) 415 { 416 foreach (var i in clerkFilters) 417 { 418 switch (i.GetString("OperatorType")) 419 { 420 case "=": 421 case "!=": 422 case "contains": 423 case "contains not": 424 clerkFilter.Add($"{i.GetString("Field")} {i.GetString("OperatorType")} '{i.GetString("Value")}'"); 425 break; 426 427 case "in": 428 case "not in": 429 clerkFilter.Add($"{i.GetString("Field")} {i.GetString("OperatorType")} ['{i.GetString("Value").Replace(",", "','")}']"); 430 break; 431 432 case "= true": 433 case "= false": 434 clerkFilter.Add($"{i.GetString("Field")} {i.GetString("OperatorType")}"); 435 break; 436 437 default: 438 clerkFilter.Add($"{i.GetString("Field")} {i.GetString("OperatorType")} {i.GetString("Value")}"); 439 break; 440 } 441 } 442 } 443 444 <input type="hidden" name="ClerkEndpoint" value="@HtmlEncoder.HtmlAttributeEncode(clerkEndPoint)" /> 445 <input type="hidden" name="ClerkQuery" value="@HtmlEncoder.HtmlAttributeEncode(string.Join("&", clerkQuery))" /> 446 <input type="hidden" name="ClerkFilter" value="@HtmlEncoder.HtmlAttributeEncode(string.Join(" and ", clerkFilter))" /> 447 <input type="hidden" name="ClerkLabels" value="@HtmlEncoder.HtmlAttributeEncode(Model.Item.GetString("ClerkLabels"))" /> 448 <input type="hidden" name="ClerkLogArea" value="@HtmlEncoder.HtmlAttributeEncode($"{Pageview.Area.Name} (ID: {Pageview.Area.ID})")" /> 449 <input type="hidden" name="ClerkLogPage" value="@HtmlEncoder.HtmlAttributeEncode($"{Pageview.Page.MenuText} (ID: {Pageview.Page.ID})")" /> 450 <input type="hidden" name="ClerkLogParagraph" value="@HtmlEncoder.HtmlAttributeEncode($"{Pageview.CurrentParagraph.Header} (ID: {Pageview.CurrentParagraph.ID})")" /> 451 } 452 @*//--CUSTOM*@ 453 454 @* General parameters *@ 455 <input type="hidden" name="Link" value="@link"> 456 <input type="hidden" name="HideTitle" value="@Model.Item.GetString("HideTitle")"> 457 <input type="hidden" name="HidePrices" value="@Model.Item.GetString("CustomHidePrices")" /> @*//CUSTOM*@ 458 459 @if (Model.Item.GetInt32("ProductsCount") != 0) 460 { 461 <input type="hidden" name="PageSize" value="@Model.Item.GetInt32("ProductsCount")"> 462 } 463 <input type="hidden" name="HeadingTitle" id="RelatedProductsTitle_@Model.ID" value="@title"> 464 @if (!string.IsNullOrEmpty(Model.Item.GetString("Subtitle"))) 465 { 466 <input type="hidden" name="Subtitle" value="@Model.Item.GetString("Subtitle")"> 467 } 468 @if (!string.IsNullOrEmpty(Model.Item.GetString("LinkText"))) 469 { 470 <input type="hidden" name="LinkText" value="@Model.Item.GetString("LinkText")"> 471 } 472 @if (!string.IsNullOrEmpty(Model.Item.GetString("ImageAspectRatio"))) 473 { 474 string ratio = Model.Item.GetRawValueString("ImageAspectRatio", ""); 475 ratio = ratio != "0" ? ratio : ""; 476 <input type="hidden" name="ImageAspectRatio" value="@ratio"> 477 } 478 @if (!string.IsNullOrEmpty(Model.Item.GetString("Layout"))) 479 { 480 <input type="hidden" name="Layout" value="@Model.Item.GetRawValueString("Layout")"> 481 } 482 @if (titleFontSize != "") 483 { 484 <input type="hidden" name="TitleFontSize" value="@titleFontSize"> 485 } 486 @if (subtitleFontSize != "") 487 { 488 <input type="hidden" name="SubtitleFontSize" value="@subtitleFontSize"> 489 } 490 @if (buttonStyle != "") 491 { 492 <input type="hidden" name="ButtonStyle" value="@buttonStyle"> 493 } 494 @if (generalTheme != "") 495 { 496 <input type="hidden" name="GeneralTheme" value="@generalTheme"> 497 } 498 @if (theme != "") 499 { 500 <input type="hidden" name="Theme" value="@theme"> 501 } 502 @if (imageTheme != "") 503 { 504 <input type="hidden" name="ImageTheme" value="@imageTheme"> 505 } 506 @if (!string.IsNullOrEmpty(Model.Item.GetString("ContentPadding"))) 507 { 508 string contentPadding = Model.Item.GetRawValueString("ContentPadding"); 509 <input type="hidden" name="ContentPadding" value="@contentPadding"> 510 } 511 <input type="hidden" name="TextReadability" value="@maxWidth"> 512 <input type="hidden" name="ParentColumnSize" id="ParentColumnSize_@Model.ID" value="12"> 513 514 <input type="hidden" name="SaleBadgeType" value="@Model.Item.GetRawValue("SaleBadgeType")"> 515 <input type="hidden" name="SaleBadgeCssClassName" value="@Model.Item.GetRawValue("SaleBadgeDesign")"> 516 <input type="hidden" name="NewBadgeCssClassName" value="@Model.Item.GetRawValue("NewBadgeDesign")"> 517 <input type="hidden" name="NewPublicationDays" value="@Model.Item.GetInt32("NewPublicationDays")"> 518 519 @if (campaignValues != "") 520 { 521 <input type="hidden" name="CampaignBadgesValues" value="@campaignValues"> 522 } 523 </form> 524 525 <script type="module" src="/Files/Templates/Designs/Swift/Assets/js/swiffy-slider.js"></script> 526 <script> 527 window.addEventListener("load", () => { 528 swift.AssetLoader.Load('/Files/Templates/Designs/Swift/Assets/css/swiffy-slider.min.css', 'css'); 529 }); 530 </script> 531 532 if (Pageview.IsVisualEditorMode) 533 { 534 <div class="alert alert-info" role="alert"> 535 <span>@Translate("Product slider: Edit this column to configure")</span> 536 </div> 537 } 538 539 if (sourceType == "upsell-products") 540 { 541 <div class="w-100 h-100"> 542 <div id="@Model.ID" class="user-select-none" style="scroll-margin-top:var(--header-height,150px)"></div> 543 <div id="RelatedProducts_@Model.ID"></div> 544 </div> 545 } 546 else if (sourceType != "related-products") 547 { 548 <div class="w-100 h-100"> 549 <div id="@Model.ID" class="user-select-none" style="scroll-margin-top:var(--header-height,150px)"></div> 550 <div id="RelatedProducts_@Model.ID" class="h-100 swift_product_slider_container" data-product-count="@Model.Item.GetInt32("ProductsCount")"></div> @*//CUSTOM*@ 551 </div> 552 } 553 else if (product?.RelatedGroups != null) 554 { 555 @* Create multiple slider containers, if type is Product relation *@ 556 <div class="grid w-100 h-100@(generalTheme)" style="grid-row-gap: 4rem"> 557 <div id="@Model.ID" class="user-select-none" style="scroll-margin-top:var(--header-height,150px)"></div> 558 @foreach (var group in product.RelatedGroups) 559 { 560 <div id="RelatedProducts_@(Model.ID)_@group.Id" class="g-col-12 h-100 swift_product_slider_container"></div> 561 } 562 </div> 563 } 564 565 @* Initialize *@ 566 if (sourceType != "related-products") 567 { 568 <script type="module"> 569 if (document.querySelector("#RelatedProducts_@Model.ID").closest("[data-col-size]")) { 570 document.querySelector("#ParentColumnSize_@Model.ID").value = document.querySelector("#RelatedProducts_@Model.ID").closest("[data-col-size]").getAttribute("data-col-size"); 571 } 572 swift.PageUpdater.Update(document.querySelector("#RelatedProductsForm_@Model.ID")).then(function () { 573 setTimeout(function () { 574 const isVisualEditor = @(Converter.ToString(Pageview.IsVisualEditorMode).ToLowerInvariant()); 575 const productSliderContainer = document.querySelector(".swift_product_slider_container"); 576 577 if (productSliderContainer && productSliderContainer.innerHTML !== "") { 578 productSliderContainer.classList.remove("d-none"); 579 } else if (!isVisualEditor && productSliderContainer) { 580 productSliderContainer.closest("[class*=column]").classList.add("d-none"); 581 } 582 custom.UpsellProducts.bindEvents(); 583 }, 150); 584 }); 585 </script> 586 } 587 else if (product?.RelatedGroups != null) 588 { 589 @* Create multiple sliders, if type is Product relation *@ 590 foreach (var group in product.RelatedGroups) 591 { 592 IList<string> fromProductIds = new List<string> { }; 593 594 foreach (var relatedProduct in group.Products) 595 { 596 if (!string.IsNullOrEmpty(relatedProduct.VariantId)) 597 { 598 fromProductIds.Add($"{relatedProduct.ProductId} {relatedProduct.VariantId}"); 599 } 600 else 601 { 602 fromProductIds.Add($"{relatedProduct.ProductId}"); 603 } 604 } 605 606 <script type="module"> 607 document.querySelector("#ParentColumnSize_@Model.ID").value = document.querySelector("#RelatedProducts_@(Model.ID)_@group.Id").closest("[data-col-size]").getAttribute("data-col-size"); 608 document.querySelector("#MainProductID_@Model.ID").value = "@string.Join(",", fromProductIds)"; 609 document.querySelector("#RelatedProductsTitle_@Model.ID").value = "@group.Name"; 610 document.querySelector("#RelatedProductsForm_@Model.ID").setAttribute("data-response-target-element", "RelatedProducts_@(Model.ID)_@group.Id"); 611 612 swift.PageUpdater.Update(document.querySelector("#RelatedProductsForm_@Model.ID")); 613 </script> 614 } 615 } 616 } 617 618 @functions { 619 List<Product> GetActiveUpSellProducts(string productNumbers) 620 { 621 if (!string.IsNullOrEmpty(productNumbers)) 622 { 623 List<Product> upSellProducts = Product.GetProductsByProductIDs(productNumbers.Split(',').Select(x => x.Trim()).ToArray(), true).ToList(); 624 625 if (upSellProducts != null && upSellProducts.Any()) 626 { 627 List<Product> activeUpSellProducts = new List<Product>(); 628 629 foreach (Product upSellProduct in upSellProducts) 630 { 631 if (upSellProduct.Active && GetStock(upSellProduct) > 0 && !upSellProduct.InActive()) 632 { 633 activeUpSellProducts.Add(upSellProduct); 634 } 635 } 636 637 return activeUpSellProducts; 638 } 639 } 640 641 return null; 642 } 643 644 double GetStock(Product product) 645 { 646 double productStock = product.Stock; 647 648 if (Converter.ToBoolean(Dynamicweb.Ecommerce.Services.Products.GetProductFieldValue(product, "Custom_FurnitureWarehouse"))) 649 { 650 productStock = Converter.ToDouble(Dynamicweb.Ecommerce.Services.Products.GetProductFieldValue(product, "Custom_AlternativeStock")); 651 } 652 653 return productStock; 654 } 655 } 656