Error executing template "Designs/Rapido/eCom/Product/Product.cshtml"
System.NullReferenceException: Object reference not set to an instance of an object.
   at CompiledRazorTemplates.Dynamic.RazorEngine_d6ebddabb97d4aa2b04820b2a9db51e7.<>c__DisplayClass70_0.<RenderVariantStockAndShipping>b__0(TextWriter __razor_helper_writer) in D:\Sites\p-lindberg\Files\Templates\Designs\Rapido\eCom\Product\Product.cshtml:line 2958
   at RazorEngine.Templating.TemplateWriter.ToString()
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at CompiledRazorTemplates.Dynamic.RazorEngine_d6ebddabb97d4aa2b04820b2a9db51e7.<>c__DisplayClass3_0.<RenderBlock>b__0(TextWriter __razor_helper_writer) in D:\Sites\p-lindberg\Files\Templates\Designs\Rapido\eCom\Product\Product.cshtml:line 145
   at CompiledRazorTemplates.Dynamic.RazorEngine_d6ebddabb97d4aa2b04820b2a9db51e7.<>c__DisplayClass2_0.<RenderBlockList>b__0(TextWriter __razor_helper_writer) in D:\Sites\p-lindberg\Files\Templates\Designs\Rapido\eCom\Product\Product.cshtml:line 111
   at CompiledRazorTemplates.Dynamic.RazorEngine_d6ebddabb97d4aa2b04820b2a9db51e7.<>c__DisplayClass3_0.<RenderBlock>b__0(TextWriter __razor_helper_writer) in D:\Sites\p-lindberg\Files\Templates\Designs\Rapido\eCom\Product\Product.cshtml:line 152
   at CompiledRazorTemplates.Dynamic.RazorEngine_d6ebddabb97d4aa2b04820b2a9db51e7.<>c__DisplayClass2_0.<RenderBlockList>b__0(TextWriter __razor_helper_writer) in D:\Sites\p-lindberg\Files\Templates\Designs\Rapido\eCom\Product\Product.cshtml:line 129
   at CompiledRazorTemplates.Dynamic.RazorEngine_d6ebddabb97d4aa2b04820b2a9db51e7.<>c__DisplayClass3_0.<RenderBlock>b__0(TextWriter __razor_helper_writer) in D:\Sites\p-lindberg\Files\Templates\Designs\Rapido\eCom\Product\Product.cshtml:line 152
   at CompiledRazorTemplates.Dynamic.RazorEngine_d6ebddabb97d4aa2b04820b2a9db51e7.<>c__DisplayClass2_0.<RenderBlockList>b__0(TextWriter __razor_helper_writer) in D:\Sites\p-lindberg\Files\Templates\Designs\Rapido\eCom\Product\Product.cshtml:line 118
   at CompiledRazorTemplates.Dynamic.RazorEngine_d6ebddabb97d4aa2b04820b2a9db51e7.Execute() in D:\Sites\p-lindberg\Files\Templates\Designs\Rapido\eCom\Product\Product.cshtml:line 3168
   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.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 2 3 @using System.Web 4 @using Dynamicweb.Extensibility 5 @using Dynamicweb.Content 6 @using System 7 @using System.IO 8 @using Dynamicweb.Core 9 @using System.Web 10 @using System.Globalization 11 @using System.Web.UI.HtmlControls 12 @using Dynamicweb.Rapido.Blocks 13 14 @using PLindberg.Dynamicweb; 15 16 @functions { 17 BlocksPage productsPage = BlocksPage.GetBlockPage("Product"); 18 19 public static string ToPascalCase(string str) 20 { 21 return CultureInfo.InvariantCulture.TextInfo 22 .ToTitleCase(str.ToLowerInvariant()) 23 .Replace("-", "") 24 .Replace("_", "") 25 .Replace(" ", ""); 26 } 27 } 28 29 @{ 30 Block productTop = new Block() 31 { 32 Id = "Top", 33 SortId = 10, 34 Design = new Design 35 { 36 RenderType = RenderType.Row 37 } 38 }; 39 productsPage.Add(productTop); 40 41 Block productMainInfo = new Block() 42 { 43 Id = "MainInformation", 44 SortId = 10, 45 Design = new Design 46 { 47 Size = "auto", 48 RenderType = RenderType.Column 49 } 50 }; 51 productsPage.Add("Top", productMainInfo); 52 53 if (!String.IsNullOrWhiteSpace(Pageview.AreaSettings.GetItem("ProductPage").GetString("ImageSectionPosition"))) 54 { 55 productMainInfo.SortId = Pageview.AreaSettings.GetItem("ProductPage").GetList("ImageSectionPosition").SelectedValue == "left-left" || Pageview.AreaSettings.GetItem("ProductPage").GetList("ImageSectionPosition").SelectedValue == "left-right" ? 2 : 1; 56 } 57 58 @* custom *@ 59 //Optional mini tabs block 60 Block miniTabsBlock = new Block() 61 { 62 Id = "MiniTabs", 63 SortId = 40, 64 SkipRenderBlocksList = true 65 }; 66 productsPage.Add("MainInformation", miniTabsBlock); 67 //----- 68 69 @* custom *@ 70 Block productTabsBlock = new Block() 71 { 72 Id = "Tabs", 73 SortId = 30, 74 SkipRenderBlocksList = true 75 }; 76 productsPage.Add(productTabsBlock); 77 78 Block productDetailsBlock = new Block() 79 { 80 Id = "Section", 81 SortId = 30 82 }; 83 productsPage.Add(productDetailsBlock); 84 85 Block productSnippetsBlock = new Block() 86 { 87 Id = "Snippets", 88 SortId = 40 89 }; 90 productsPage.Add(productSnippetsBlock); 91 } 92 93 @* Include the required Grid builder (Contains the methods @RenderBlockList and @RenderBlock) *@ 94 @using System.Text.RegularExpressions 95 @using System.Collections.Generic 96 @using Dynamicweb.Rapido.Blocks 97 98 99 @*--- START: Base block renderers ---*@ 100 101 @helper RenderBlockList(List<Block> blocks) 102 { 103 blocks = blocks.OrderBy(item => item.SortId).ToList(); 104 105 foreach (Block item in blocks) 106 { 107 <!-- START: @item.Id --> 108 109 if (item.Design == null) 110 { 111 @RenderBlock(item) 112 } 113 else if (item.Design.RenderType != RenderType.Hide) 114 { 115 if (item.Design.RenderType == RenderType.Row) 116 { 117 <div class="grid grid--align-content-start"> 118 @RenderBlock(item) 119 </div> 120 } 121 122 if (item.Design.RenderType == RenderType.Column) 123 { 124 string hidePadding = item.Design.HidePadding ? "u-no-padding" : ""; 125 string size = item.Design.Size != null ? item.Design.Size : "12"; 126 size = Regex.IsMatch(size, @"\d") ? "md-" + item.Design.Size : item.Design.Size; 127 128 <div class="[email protected] [email protected] grid__col-sm-12 grid__col-xs-12 @hidePadding" id="[email protected]"> 129 @RenderBlock(item) 130 </div> 131 } 132 133 if (item.SkipRenderBlocksList == true) 134 { 135 @RenderBlock(item) 136 } 137 } 138 139 <!-- END: @item.Id --> 140 } 141 } 142 143 @helper RenderBlock(Block item) 144 { 145 if (item.Template != null) 146 { 147 @BlocksPage.RenderTemplate(item.Template) 148 } 149 150 if (item.BlocksList.Count > 0 && item.SkipRenderBlocksList == false) 151 { 152 @RenderBlockList(item.BlocksList) 153 } 154 } 155 156 @*--- END: Base block renderers ---*@ 157 158 159 @* Include the Blocks for the page *@ 160 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 161 @using Dynamicweb.Core 162 @using System 163 @using System.Web 164 @using System.Collections.Generic 165 @using Dynamicweb.Rapido.Blocks 166 @using RazorEngine.Text 167 168 @functions { 169 BlocksPage mainImagePage = BlocksPage.GetBlockPage("Product"); 170 //test 171 } 172 173 @{ 174 string imageBlockPosition = !String.IsNullOrEmpty(Pageview.AreaSettings.GetItem("ProductPage").GetString("ImageSectionPosition")) ? Pageview.AreaSettings.GetItem("ProductPage").GetList("ImageSectionPosition").SelectedValue : "right-right"; 175 string imageBlockWidth = !String.IsNullOrEmpty(Pageview.AreaSettings.GetItem("ProductPage").GetString("TopLayout")) ? Pageview.AreaSettings.GetItem("ProductPage").GetList("TopLayout").SelectedValue : "6"; 176 imageBlockWidth = imageBlockPosition == "left-left" || imageBlockPosition == "left-right" ? Converter.ToString(12 - Converter.ToInt32(imageBlockWidth)) : imageBlockWidth; 177 178 // custom 179 string playThumb = Pageview.AreaSettings.GetItem("Custom").GetItem("CustomSettings").GetField("VideoThumb").GetFile() != null ? 180 Pageview.AreaSettings.GetItem("Custom").GetItem("CustomSettings").GetField("VideoThumb").GetFile().Path : string.Empty; 181 182 Block mainImageBlock = new Block() 183 { 184 Id = "MainImage", 185 SortId = imageBlockPosition == "left-left" || imageBlockPosition == "left-right" ? 1 : 2, 186 Template = RenderMainImageContainer(), 187 Design = new Design 188 { 189 Size = imageBlockWidth, 190 RenderType = RenderType.Column 191 } 192 }; 193 194 mainImagePage.Add("Top", mainImageBlock); 195 196 197 } 198 199 @helper RenderModal() 200 { 201 // custom 202 Guid imageGuid = Guid.TryParse(GetString("Ecom:Product:Field.PerfionMainImage.Value.Clean"), out imageGuid) ? imageGuid : Guid.Empty; 203 204 <!-- Trigger for the gallery modal --> 205 <input type="checkbox" id="GalleryModalTrigger" class="modal-trigger" /> 206 207 <!-- custom --> 208 if (!String.IsNullOrEmpty(GetString("Ecom:Product:Field.PerfionMainImage"))) 209 { 210 <!-- Gallery modal --> 211 <div class="modal-container "> 212 <label for="GalleryModalTrigger" id="GalleryModalOverlay" class="modal-overlay"></label> 213 <div class="modal modal--full" id="GalleryModal"> 214 <div class="modal__body modal__body--full"> 215 <div class="gallery-slider"> 216 <div class="gallery-slider__image"> 217 <!-- custom --> 218 <img id="FullImage" src="~/Files/Images/placeholder.gif" @PerfionImageSrc(imageGuid, 800, 800, "data-src=") class="modal--full__img js-gallery-image" alt="@(new HtmlEncodedString(GetString("Ecom:Product.Name")).ToEncodedString())" /> 219 <iframe id="FullVideo" class="modal--full__img js-gallery-image pp__video" src="" frameborder="0" allowfullscreen></iframe> 220 </div> 221 <div class="gallery-slider__image-counter" id="FullImage_counter"></div> 222 <label class="gallery-slider__close-btn" for="GalleryModalTrigger"></label> 223 <button class="gallery-slider__previous-btn" id="FullImage_prev" onclick="Gallery.prevImage('FullImage')"></button> 224 <button class="gallery-slider__next-btn" id="FullImage_next" onclick="Gallery.nextImage('FullImage')"></button> 225 </div> 226 </div> 227 </div> 228 </div> 229 } 230 } 231 232 @helper RenderMainImageContainer() 233 { 234 string imageBlockPosition = !String.IsNullOrEmpty(Pageview.AreaSettings.GetItem("ProductPage").GetString("ImageSectionPosition")) ? Pageview.AreaSettings.GetItem("ProductPage").GetList("ImageSectionPosition").SelectedValue : "right-right"; 235 @RenderModal() 236 237 <div class="grid grid--bleed"> 238 @if (imageBlockPosition == "left-left" || imageBlockPosition == "right-left") 239 { 240 @RenderThumbnails() 241 @RenderImage() 242 } 243 else 244 { 245 @RenderImage() 246 @RenderThumbnails() 247 } 248 </div> 249 } 250 251 @helper RenderImage() 252 { 253 // custom 254 Guid imageGuid = Guid.TryParse(GetString("Ecom:Product:Field.PerfionMainImage.Value.Clean"), out imageGuid) ? imageGuid : Guid.Empty; 255 256 Pageview.Meta.AddTag("custom-og-image", "<meta property=\"og:image\" content=\"" + PerfionImageSrc(imageGuid)?.ToString() + "\" />"); 257 string productId = GetString("Ecom:Product.ID"); 258 bool pointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly") && Pageview.User == null; 259 260 <div class="grid__col-auto"> 261 <div class="stickers-container dw-mod"> 262 @{ 263 if (Pageview.AreaSettings.GetItem("Ecommerce").GetItem("SaleSticker").GetBoolean("Enable") && !pointShopOnly) 264 { 265 string contentType = Pageview.AreaSettings.GetItem("Ecommerce").GetItem("SaleSticker").GetString("ContentType"); 266 string text = ""; 267 var currency = Dynamicweb.Ecommerce.Services.Currencies.GetDefaultCurrency(); 268 269 switch (contentType) 270 { 271 case "Name": 272 foreach (LoopItem discount in GetLoop("ProductDiscounts").Where(p => p.GetString("Ecom:Product.Discount.ID") != "SALESDISCNT4").ToList()) 273 { 274 text = discount.GetString("Ecom:Product.Discount.Name"); 275 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 276 } 277 break; 278 case "Amount": 279 if (GetLoop("ProductDiscounts").Where(p => p.GetString("Ecom:Product.Discount.ID") != "SALESDISCNT4").ToList().Count > 0) 280 { 281 text = Dynamicweb.Ecommerce.Services.Currencies.Format(currency, GetDouble("Ecom:Product.Discount.Price.PriceWithoutVAT.Value") - GetDouble("Ecom:Product.Price.PriceWithoutVAT.Value")); 282 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 283 } 284 break; 285 case "Percents": 286 double percents = 0; 287 foreach (LoopItem discount in GetLoop("ProductDiscounts").Where(p => p.GetString("Ecom:Product.Discount.ID") != "SALESDISCNT4").ToList()) 288 { 289 percents += discount.GetDouble("Ecom:Product.Discount.PercentWithoutVAT"); 290 } 291 if (percents > 0) 292 { 293 text = Math.Round(percents, 0) + "%"; 294 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 295 } 296 break; 297 case "Amount and percents": 298 double amount = 0; 299 double percent = 0; 300 foreach (LoopItem discount in GetLoop("ProductDiscounts").Where(p => p.GetString("Ecom:Product.Discount.ID") != "SALESDISCNT4").ToList()) 301 { 302 if (discount.GetString("Ecom:Product.Discount.Type") == "PERCENT") 303 { 304 percent += discount.GetDouble("Ecom:Product.Discount.PercentWithoutVAT"); 305 } 306 else if (discount.GetString("Ecom:Product.Discount.Type") == "AMOUNT") 307 { 308 amount += discount.GetDouble("Ecom:Product.Discount.AmountWithVAT"); 309 } 310 } 311 if (percent > 0) 312 { 313 text = percent + "%"; 314 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 315 } 316 if (amount > 0) 317 { 318 text = Dynamicweb.Ecommerce.Services.Currencies.Format(currency, amount); 319 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 320 } 321 break; 322 default: 323 if (GetLoop("ProductDiscounts").Where(p => p.GetString("Ecom:Product.Discount.ID") != "SALESDISCNT4").ToList().Count > 0) 324 { 325 text = Translate("Sale!"); 326 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 327 } 328 break; 329 } 330 } 331 332 if (!pointShopOnly && Pageview.AreaSettings.GetItem("Ecommerce").GetItem("NewSticker").GetBoolean("Enable") && GetDate("Ecom:Product:Field.NewsStart.Value") < DateTime.Now && GetDate("Ecom:Product:Field.NewsEnd.Value") > DateTime.Now.AddDays(-1)) 333 { 334 <div class="stickers-container__tag stickers-container__tag--new dw-mod">@Translate("New!")</div> 335 } 336 337 // custom 338 #region Perfion sticker 339 var stickerName = GetString("Ecom:Product:Field.PerfionSticker.Value.Clean"); 340 if (!pointShopOnly) 341 { 342 if (!String.IsNullOrEmpty(GetString("Ecom:Product:Field.CustomSticker.Value"))) 343 { 344 <div class="stickers-container__tag stickers-container__tag--custom dw-mod">@GetString("Ecom:Product:Field.CustomSticker.Value")</div> 345 } 346 if (!string.IsNullOrEmpty(stickerName)) 347 { 348 <div class="stickers-container__tag stickers-container__tag--custom dw-mod">@stickerName</div> 349 } 350 } 351 #endregion 352 } 353 </div> 354 <label for="GalleryModalTrigger" class="product__image-container"> 355 <img class="thumb-image-view product__image-container__image dw-mod b-lazy" src="Files/Images/placeholder.gif" @PerfionImageSrc(imageGuid, 800, 800, "data-src=") alt="@(new HtmlEncodedString(GetString("Ecom:Product.Name")).ToEncodedString())" id="[email protected]" data-for="FullImage" data-number="0" onclick="Gallery.openImageByNum(this)" /> 356 </label> 357 </div> 358 } 359 360 @helper RenderThumbnails() 361 { 362 var technicalSpecificationsFeed = "/Default.aspx?ID=" + GetPageIdByNavigationTag("PerfionLiveFeed") + "&PerfionProductID=" + GetString("Ecom:Product:Field.PerfionProductId") + "&LanguageID=" + GetString("Ecom:Product.LanguageID") + "&PerfionMainImage=" + GetString("Ecom:Product:Field.PerfionMainImage"); 363 364 <div class="grid__col-2 dw-mod mobilethumbs"> 365 <div class="product__thumbs dw-mod js-handlebars-root" id="GalleryImages" data-template="GalleryImagesContainer" data-pre-render-template="GalleryImagesPreRenderContainer" data-json-feed="@technicalSpecificationsFeed" data-preloader="minimal"> 366 </div> 367 </div> 368 } 369 370 @helper RenderThumbnail(string image) 371 { 372 // custom 373 Guid imageGuid = Guid.TryParse(GetString("Ecom:Product:Field.PerfionMainImage.Value.Clean"), out imageGuid) ? imageGuid : Guid.Empty; 374 string productId = GetString("Ecom:Product.ID"); 375 376 <div class="carousel__slide carousel__slide--vertical dw-mod"> 377 <div class="thumb-list__item thumb-list__item--active dw-mod js-thumb js-gallery" data-for="[email protected]" @PerfionImageSrc(imageGuid, 800, 800, "data-image=") onmouseover="Gallery.openImage(this)"> 378 <label for="GalleryModalTrigger"> 379 <img src="Files/Images/placeholder.gif" @PerfionImageSrc(imageGuid, 200, 200, "data-src=") alt="@(new HtmlEncodedString(GetString("Ecom:Product.Name")).ToEncodedString())" class="js-gallery b-lazy" data-for="FullImage" @PerfionImageSrc(imageGuid, 800, 800, "data-image=") onclick="Gallery.openImage(this)"> 380 </label> 381 </div> 382 </div> 383 } 384 385 <script id="GalleryImagesPreRenderContainer" type="text/x-template"> 386 <div class="u-h600px u-full-width"> 387 <div class="grid"> 388 <div class="grid__col-12"> 389 <div class="pre-render-element pre-render-element--md"></div> 390 </div> 391 </div> 392 </div> 393 </script> 394 395 <script id="GalleryImagesContainer" type="text/x-template"> 396 <i class="fas fa-circle-notch fa-spin preloader js-remove-after-load"></i> <!--preloader--> 397 <div class="carousel js-carousel-container carousel--hidden dw-mod" id="leftCarousel"> 398 <div class="thumb-list carousel__container dw-mod"> 399 @* custom *@ 400 {{#videos}} 401 {{>RenderProductVideos link=link thumb="@playThumb"}} 402 {{/videos}} 403 @*Main image thumb*@ 404 @RenderThumbnail(GetString("Ecom:Product:Field.PerfionMainImage")) 405 {{#images}} 406 {{>GalleryImage}} 407 {{/images}} 408 </div> 409 <div class="js-carousel-data" data-carousel-slide-time="0" data-direction="vertical" data-sliding-type="items" data-slides-in-view="5"> 410 <div class="carousel-prev-btn carousel-prev-btn--vertical dw-mod" onclick="Carousel.GetPreviousSlide('leftCarousel')"></div> 411 <div class="carousel-next-btn carousel-next-btn--vertical dw-mod" onclick="Carousel.GetNextSlide('leftCarousel')"></div> 412 </div> 413 </div> 414 </script> 415 416 <script id="GalleryImage" type="text/x-template"> 417 <div class="carousel__slide carousel__slide--vertical dw-mod"> 418 <div class="thumb-list__item thumb-list__item--active dw-mod js-thumb js-gallery" data-for="[email protected]("Ecom:Product.ID")" data-image="{{PerfionImageSrc guid 800 800}}" onmouseover="Gallery.openImage(this)"> 419 <label for="GalleryModalTrigger"> 420 <img src="Files/Images/placeholder.gif" alt="@(new HtmlEncodedString(GetString("Ecom:Product.Name")).ToEncodedString())" class="js-gallery b-lazy" data-src="{{PerfionImageSrc guid 200 200}}" data-for="FullImage" data-image="{{PerfionImageSrc guid 800 800}}" onclick="Gallery.openImage(this)"> 421 </label> 422 </div> 423 </div> 424 </script> 425 426 @* custom *@ 427 <script id="RenderProductVideos" type="text/x-template"> 428 <div class="carousel__slide carousel__slide--vertical dw-mod"> 429 <div class="thumb-list__item thumb-list__item--active dw-mod js-thumb js-gallery" data-for="[email protected]("Ecom:Product.ID")" data-image="{{largeImage}}" data-video="{{link}}" onmouseover="Gallery.openImage(this)"> 430 <label for="GalleryModalTrigger"> 431 <img src="Files/Images/placeholder.gif" alt="@(new HtmlEncodedString(GetString("Ecom:Product.Name")).ToEncodedString())" class="js-gallery b-lazy" data-src="{{smallImage}}" data-image="{{largeImage}}" data-for="FullImage" data-video="{{link}}" onclick="Gallery.openImage(this)"> 432 {{#if thumb}} 433 <img src="Files/Images/placeholder.gif" data-src="{{thumb}}" class="play-thumb b-lazy" alt="@(new HtmlEncodedString(GetString("Ecom:Product.Name")).ToEncodedString())" onclick="Gallery.openImage(this.previousElementSibling)" /> 434 {{/if}} 435 </label> 436 </div> 437 </div> 438 </script> 439 440 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 441 @using Dynamicweb.Core 442 @using System 443 @using System.Linq; 444 @using System.Text; 445 @using System.Web 446 @using System.Collections.Generic 447 @using Dynamicweb.Rapido.Blocks 448 @using Group = Dynamicweb.Ecommerce.Products.Group; 449 450 @using PLindberg.Dynamicweb; 451 @functions { 452 bool useFacebookPixel; 453 bool useGoogleTagManager; 454 BlocksPage mainInfoPage = BlocksPage.GetBlockPage("Product"); 455 } 456 457 @{ 458 bool mainInfoRenderVariantsAsProducts = Pageview.AreaSettings.GetItem("ProductPage").GetString("RenderVariantsAsProductList") != null && GetInteger("Ecom:Product.VariantCount") > 1 ? Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("RenderVariantsAsProductList") : false; 459 bool mainPointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly"); 460 bool mainInfoOnlyPreview = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("OnlyPreviewForAnonymous") && Pageview.User == null; 461 string mainInfoVariantId = HttpContext.Current.Request.QueryString.Get("variantId") != null ? HttpContext.Current.Request.QueryString.Get("variantId") : ""; 462 string mainInfoFeedId = GetGlobalValue("Global:Page.ID").ToString() + "&ProductID=" + GetString("Ecom:Product.ID") + "&VariantID=" + mainInfoVariantId + "&Feed=True&redirect=false"; 463 string mainInfoCartIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetString("CartIcon") != null ? Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon").SelectedValue : "fas fa-shopping-cart"; 464 useFacebookPixel = !string.IsNullOrWhiteSpace(Pageview.AreaSettings.GetItem("Settings").GetString("FacebookPixelID")); 465 useGoogleTagManager = !string.IsNullOrEmpty(Pageview.AreaSettings.GetItem("Settings").GetString("GoogleTagManagerID")); 466 467 Block mainInfoHeader = new Block() 468 { 469 Id = "MainInfoHeader", 470 SortId = 10, 471 Template = RenderMainInfoHeader() 472 }; 473 mainInfoPage.Add("MainInformation", mainInfoHeader); 474 475 Block mainInfoDescription = new Block() 476 { 477 Id = "ShortDescription", 478 SortId = 30, 479 Template = RenderShortDescription() 480 }; 481 mainInfoPage.Add("MainInformation", mainInfoDescription); 482 483 if (!mainInfoRenderVariantsAsProducts) 484 { 485 Block mainInfoVariants = new Block() 486 { 487 Id = "Variants", 488 SortId = 50, 489 Template = RenderMainInfoVariants() 490 }; 491 mainInfoPage.Add("MainInformation", mainInfoVariants); 492 } 493 494 Block mainInfoBOM = new Block() 495 { 496 Id = "BOM", 497 SortId = 60, 498 Template = RenderMainInfoBOM() 499 }; 500 mainInfoPage.Add("MainInformation", mainInfoBOM); 501 502 if (!mainInfoRenderVariantsAsProducts) 503 { 504 Block mainInfoBuy = new Block() 505 { 506 Id = "Buy", 507 SortId = 80, 508 Template = RenderMainInfoBuy() 509 }; 510 mainInfoPage.Add("MainInformation", mainInfoBuy); 511 512 Block stockAndShipping = new Block() 513 { 514 Id = "StockAndShipping", 515 SortId = 90, 516 Template = RenderStockAndShipping() 517 }; 518 mainInfoPage.Add("MainInformation", stockAndShipping); 519 } 520 } 521 522 @* custom *@ 523 @using System; 524 @using System.Web; 525 526 @using PLindberg.Dynamicweb.Common; 527 @using PLindberg.Dynamicweb.Perfion; 528 529 @helper PerfionImageSrc(Guid imageGuid, int width, int height, string prefix = "src=") 530 { 531 <text>@prefix"@HttpUtility.HtmlEncode(string.Format("{0}/Perfion/Image.aspx?id={1}&size={2}x{3}&format=png", new PerfionSettings().PerfionWebApiUrl(), 532 imageGuid, width, height))"</text> 533 } 534 @helper PerfionImageSrc(Guid imageGuid) 535 { 536 <text>@string.Format("{0}/Perfion/Image.aspx?id={1}&format=png", new PerfionSettings().PerfionWebApiUrl(), 537 imageGuid)</text>} 538 539 @helper RenderMainInfoHeader() 540 { 541 bool renderVariantsAsProducts = GetInteger("Ecom:Product.VariantCount") > 1 ? Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("RenderVariantsAsProductList") : false; 542 string pageId = GetGlobalValue("Global:Page.ID").ToString(); 543 string currentPrice = GetString("Ecom:Product.Discount.Price.PriceFormatted") == GetString("Ecom:Product.Price.PriceFormatted") ? GetString("Ecom:Product.Price.PriceFormatted") : GetString("Ecom:Product.Discount.Price.PriceFormatted"); 544 bool hideProductNumber = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideProductNumber"); 545 546 double metaTagPrice = GetDouble("Ecom:Product.Discount.Price.PriceWithVAT.Value") == GetDouble("Ecom:Product.Price.PriceWithVAT.Value") ? GetDouble("Ecom:Product.Price.PriceWithVAT.Value") : GetDouble("Ecom:Product.Discount.Price.PriceWithVAT.Value"); 547 // main product 548 var variantsLoop = GetLoop("VariantCombinations"); 549 var lowestVariantPrice = variantsLoop.GetLowestVariantPrice(); 550 if (lowestVariantPrice != null && string.IsNullOrEmpty(GetString("Ecom:Product.SelectedVariantComboName"))) 551 { 552 metaTagPrice = lowestVariantPrice.PriceWithVat; 553 } 554 555 Pageview.Meta.AddTag("custom-og-type", "<meta property=\"og:type\" content=\"product\" />"); 556 Pageview.Meta.AddTag("custom-og-price", "<meta property=\"product:price:amount\" content=\"" + metaTagPrice.ToString("0.00", CultureInfo.InvariantCulture) + "\" />"); 557 Pageview.Meta.AddTag("custom-og-currency", "<meta property=\"product:price:currency\" content=\"" + Pageview.Area.EcomCurrencyId + "\" />"); 558 559 bool useFontAwesomePro = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetBoolean("UseFontAwesomePro"); 560 var selectedFavoriteIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("FavoriteIcon") != null ? Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("FavoriteIcon").SelectedValue : "star"; 561 string favoriteIcon = "fas fa-" + selectedFavoriteIcon; 562 string favoriteOutlineIcon = "far fa-" + selectedFavoriteIcon; 563 564 // custom 565 Guid imageGuid = Guid.TryParse(GetString("Ecom:Product:Field.PerfionLogo.Value.Clean"), out imageGuid) ? imageGuid : Guid.Empty; 566 bool isMainProduct = GetString("Ecom:Product.Number").Contains("-main"); 567 <div> 568 <div class="u-pull--left product__title dw-mod"> 569 @* Custom: removed variant combo name *@ 570 <h1 class="u-no-margin">@GetString("Ecom:Product.Name")</h1> 571 572 @if (!hideProductNumber && !isMainProduct) 573 { 574 <div class="item-number dw-mod">@Translate("Productno", "Varenr.") @GetString("Ecom:Product.Number")</div> 575 } 576 @* custom 577 show perfion logo 578 *@ 579 <div class="logo"> 580 <img class="b-lazy" src="/Files/Images/placeholder.gif" @PerfionImageSrc(imageGuid, 200, 200, "data-src=") /> 581 </div> 582 583 </div> 584 <div class="u-pull--right"> 585 @if (Dynamicweb.Core.Converter.ToBoolean(GetGlobalValue("Global:Extranet.UserName")) && !renderVariantsAsProducts) 586 { 587 string favoriteId = "Favorite" + GetString("Ecom:Product.ID"); 588 <div id="@favoriteId" class="favorites favorites--md u-pull--right js-favorite-btn dw-mod"> 589 <div> 590 @{ 591 string favorite = GetBoolean("Ecom:Product.IsProductInFavoriteList") ? favoriteIcon : favoriteOutlineIcon; 592 593 // custom (Zero Price) 594 string AddToWishlist = null; 595 596 if (GetDouble("Ecom:Product.Price.PriceWithoutVAT.Value") > 0) 597 { 598 AddToWishlist = "fbq('track', 'AddToWishlist', {" + 599 "content_name: '" + GetString("Ecom:Product.Name") + "'," + 600 "content_ids: ['" + GetString("Ecom:Product.Number") + "']," + 601 "value: " + GetDouble("Ecom:Product.Price.PriceWithVAT.Value") + "," + 602 "currency: '" + GetString("Ecom:Product.Price.Currency.Code") + "'" + 603 "});"; 604 } 605 } 606 <label for="FavoriteTrigger"><i class="@favorite fa-1_5x"></i></label> 607 </div> 608 <input type="checkbox" id="FavoriteTrigger" class="dropdown-trigger" /> 609 610 <div class="dropdown"> 611 <div class="dropdown__content dropdown__content--show-left dropdown__content--padding u-w220px dw-mod"> 612 <ul class="list list--clean dw-mod"> 613 @if (GetLoop("CustomerCenter.ListTypes").Count > 0) 614 { 615 foreach (LoopItem listType in GetLoop("CustomerCenter.ListTypes")) 616 { 617 foreach (LoopItem list in listType.GetLoop("CustomerCenter.ProductLists")) 618 { 619 string favLinkType = list.GetString("Ecom:Product.List.IsProductInThisList") == "True" ? list.GetString("Ecom:Product.RemoveFromThisList") : list.GetString("Ecom:Product.AddToThisListAction"); 620 string isInListIcon = list.GetString("Ecom:Product.List.IsProductInThisList") == "True" ? favoriteIcon : favoriteOutlineIcon; 621 <li> 622 <a href="@favLinkType" class="list__link u-no-underline dw-mod" onclick="@(list.GetString("Ecom:Product.List.IsProductInThisList") != "True" && useFacebookPixel ? AddToWishlist : "")"><i class="@isInListIcon"></i> @list.GetValue("Ecom:CustomerCenter.List.Name")</a> 623 </li> 624 } 625 } 626 } 627 else 628 { 629 string favLinkType = GetString("Ecom:Product.AddToFavorites") + "&CCListType=0&CCCreateNewList=" + Translate("My favorites"); 630 string isInListIcon = favoriteOutlineIcon; 631 <li> 632 <a href="@favLinkType" class="list__link u-no-underline dw-mod" onclick="@(useFacebookPixel ? AddToWishlist : "")"><i class="@isInListIcon"></i> @Translate("My favorites")</a> 633 </li> 634 } 635 </ul> 636 </div> 637 <label class="dropdown-trigger-off" for="FavoriteTrigger"></label> 638 </div> 639 </div> 640 } 641 @if (Dynamicweb.Core.Converter.ToBoolean(GetGlobalValue("Global:Extranet.UserName")) == false) 642 { 643 string favorite = GetBoolean("Ecom:Product.IsProductInFavoriteList") ? favoriteIcon : favoriteOutlineIcon; 644 645 <div class="favorites favorites--md u-pull--right js-favorite-btn dw-mod"> 646 647 <label for="FavoriteTrigger_{{id}}" class="u-no-margin js-favorite-btn"> 648 <label for="SignInModalTrigger" title='@Translate("OpretBruger","Opret bruger eller login således du kan bruge denne funktion")' onclick="setTimeout(function () { document.getElementById('LoginUsername').focus() }, 10)"> 649 <i class="@favorite fa-1_5x"></i> 650 </label> 651 </label> 652 </div> 653 } 654 </div> 655 </div> 656 } 657 658 @helper RenderStockAndShipping() 659 { 660 bool hideStockState = Pageview.AreaSettings.GetItem("ProductPage").GetString("HideStockState") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideStockState") : false; 661 bool hideDelivery = Pageview.AreaSettings.GetItem("ProductPage").GetString("HideShipping") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideShipping") : false; 662 bool onlyPreview = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("OnlyPreviewForAnonymous") && Pageview.User == null; 663 664 if (!onlyPreview && (!String.IsNullOrEmpty(GetString("Ecom:Product:Stock.Text")) || !String.IsNullOrEmpty(GetString("Ecom:Product:Stock.DeliveryText")))) 665 { 666 string stockIcon = GetInteger("Ecom:Product.Stock") > 0 ? GetInteger("Ecom:Product.Stock") < 5 ? "stock-icon--few" : "stock-icon--in" : "stock-icon--not"; 667 668 <div class="product__stock-delivery dw-mod"> 669 @if (!hideStockState) 670 { 671 672 673 } 674 675 @if (!String.IsNullOrEmpty(GetString("Ecom:Product:Stock.DeliveryText")) && !hideDelivery) 676 { 677 <span>@Translate("Shipping")</span> <span>@GetString("Ecom:Product:Stock.DeliveryText")</span> <span>@GetString("Ecom:Product:Stock.DeliveryUnit")</span> 678 } 679 </div> 680 } 681 } 682 683 @helper RenderShortDescription() 684 { 685 if (!String.IsNullOrEmpty(GetString("Ecom:Product.ShortDescription"))) 686 { 687 <div class="introduction-text"> 688 @GetString("Ecom:Product.ShortDescription") 689 </div> 690 } 691 } 692 693 @helper RenderMainInfoVariants() 694 { 695 string pageId = GetGlobalValue("Global:Page.ID").ToString(); 696 string productId = GetString("Ecom:Product.ID"); 697 string variantSelection = !String.IsNullOrEmpty(HttpContext.Current.Request.QueryString.Get("variantId")) ? HttpContext.Current.Request.QueryString.Get("variantId").Replace(".", ",") : ""; 698 string hideHelpText = ""; 699 700 var products = new Dynamicweb.Ecommerce.Products.ProductService().GetByProductIDs(new string[] { productId }, false, GetString("Ecom:Product.LanguageID"), false, false); 701 var activeVariantList = products.Where(x => x.VariantId != "" && x.Active).SelectMany(x => x.VariantId.Split('.')); 702 703 foreach (LoopItem variantgroup in GetLoop("VariantGroups")) 704 { 705 foreach (LoopItem variantoption in variantgroup.GetLoop("VariantAvailableOptions")) 706 { 707 if (variantoption.GetBoolean("Ecom:VariantOption.Selected")) 708 { 709 hideHelpText = "u-hidden"; 710 } 711 } 712 } 713 714 if (GetLoop("VariantGroups").Count > 0) 715 { 716 var variantCombinationsObject = new List<Array>(); 717 foreach (LoopItem variantcomb in GetLoop("VariantStockCombinations")) 718 { 719 string[] combinations = variantcomb.GetString("Ecom:VariantStockCombination.VariantID").Split('.'); 720 variantCombinationsObject.Add(combinations); 721 } 722 723 string combinationsJson = Newtonsoft.Json.JsonConvert.SerializeObject(variantCombinationsObject).Replace("\"", "\'"); 724 725 var variantGroupsObject = new List<List<String>>(); 726 foreach (LoopItem variantGroup in GetLoop("VariantGroups")) 727 { 728 var variantsObject = new List<String>(); 729 foreach (LoopItem variantOption in variantGroup.GetLoop("VariantAvailableOptions")) 730 { 731 variantsObject.Add(variantOption.GetString("Ecom:VariantOption.ID")); 732 } 733 variantGroupsObject.Add(variantsObject); 734 } 735 string variantsJson = Newtonsoft.Json.JsonConvert.SerializeObject(variantGroupsObject).Replace("\"", "\'"); 736 737 <div> 738 <div id="variant-options" class="js-variants" data-total-variant-groups="@GetLoop("VariantGroups").Count" data-combinations="@combinationsJson" data-variants="@variantsJson" data-variant-selections="@variantSelection" data-selection-complete="UpdatePage" data-page-id="@pageId" data-product-id="@productId"> 739 @foreach (LoopItem variantGroup in GetLoop("VariantGroups")) 740 { 741 string groupId = variantGroup.GetString("Ecom:VariantGroup.ID"); 742 743 <div> 744 <div class="u-bold">@variantGroup.GetString("Ecom:VariantGroup.Name")</div> 745 <div> 746 <select onchange="VariantHandling.SelectVariant(event)" id="[email protected]"> 747 <option class="js-variant-option" data-variant-id="@groupId-select" data-variant-group="@groupId">@Translate("Select variant")</option> 748 @foreach (LoopItem variantOption in variantGroup.GetLoop("VariantAvailableOptions").OrderBy(x=>x.GetString("Ecom:VariantOption.Name")).ThenBy(x=>x.GetString("Ecom:VariantOption.SortOrder"))) 749 { 750 var variantOptionId = variantOption.GetString("Ecom:VariantOption.ID"); 751 if (!activeVariantList.Contains(variantOptionId)) { continue; } 752 753 string selected = variantOption.GetBoolean("Ecom:VariantOption.Selected") ? "true" : ""; 754 //selected="@selected" 755 756 <option class="js-variant-option" data-variant-id="@variantOptionId" data-variant-group="@groupId"> 757 @variantOption.GetString("Ecom:VariantOption.Name") 758 </option> 759 } 760 </select> 761 </div> 762 </div> 763 } 764 765 </div> 766 767 @*<small class="js-help-text help-text @hideHelpText">@Translate("Please select variant!")</small>*@ 768 </div> 769 } 770 } 771 772 @helper RenderMainInfoBOM() 773 { 774 if (GetLoop("BOMProducts").Count > 0) 775 { 776 <h2 class="section-title">@Translate("Including products")</h2> 777 foreach (LoopItem BOMProductItem in GetLoop("BOMProducts")) 778 { 779 string link = "/" + BOMProductItem.GetString("Ecom:Product.LinkGroup.Clean") + (!String.IsNullOrEmpty(BOMProductItem.GetString("Ecom:Product.VariantID")) ? "&VariantID=" + BOMProductItem.GetString("Ecom:Product.VariantID") : ""); 780 <div class="grid__col--border grid"> 781 <div class="grid__cell grid__cell--align-middle-left"> 782 <a href="@link" class="u-pull--left u-margin-right"> 783 <img src="/Admin/Public/GetImage.ashx?width=50&[email protected]("Ecom:Product.ImageDefault.Default.Clean")&Compression=99" alt="@BOMProductItem.GetString("Ecom:Product.Name")" /> 784 </a> 785 <a href="@link">@BOMProductItem.GetString("Ecom:Product.Name")</a> 786 </div> 787 </div> 788 } 789 } 790 } 791 792 @helper RenderMainInfoBuy() 793 { 794 string pageId = GetGlobalValue("Global:Page.ID").ToString(); 795 string variantId = HttpContext.Current.Request.QueryString.Get("variantId"); 796 string productId = GetString("Ecom:Product.ID"); 797 string feedId = pageId + "&ProductID=" + productId + "&VariantID=" + variantId + "&Feed=True&redirect=false"; 798 799 <div class="product__price-actions js-handlebars-root dw-mod" id="PriceAndActions" data-template="PricesAndActionsTemplate" data-json-feed="/[email protected]" data-preloader="minimal"></div> 800 <input type="hidden" value="@GetString("Ecom:Product.VariantID.Extented")" name="Variant" id="[email protected]("Ecom:Product.ID")" /> 801 } 802 803 @* Handlebars templates *@ 804 <script id="PricesAndActionsTemplate" type="text/x-template"> 805 {{#.}} 806 {{#ifCond itemStatus "!==" "Z"}} 807 @if (!mainInfoOnlyPreview) 808 { 809 <div class="product__price-actions__price dw-mod u-margin-bottom--lg "> 810 @if (mainPointShopOnly) 811 { 812 <text> 813 {{#if havePointPrice}} 814 <div class="price price--product-page dw-mod">{{points}} @Translate("points")</div> 815 {{else}} 816 @Translate("Not available") 817 {{/if}} 818 </text> 819 } 820 else 821 { 822 @*Custom*@ 823 <text>{{#if showPrice}}</text> 824 <text>{{#if showinfoPrice}}</text> 825 <div class="before-price {{onSale}} dw-mod">{{discount}}</div> 826 <div class="price price--product-page dw-mod newprice"><span>@Translate("Nu", "Nu")</span>{{price}}</div> 827 <div class="price price--product-page dw-mod withoutvat">{{priceWithoutVat}} @Translate("EksMoms", "ex. moms")</div> 828 <div class="price price--product-page dw-mod withoutvat beforeprice"><span>@Translate("Beforeprice", "Før")</span> {{informativePrice.priceWithVat}}</div> 829 <div class="price price--product-page dw-mod withoutvat">{{informativePrice.price}} @Translate("EksMoms", "ex. moms")</div> 830 <text>{{else}}</text> 831 <div class="before-price {{onSale}} dw-mod">{{discount}}</div> 832 <div class="price price--product-page dw-mod">{{price}}</div> 833 <div class="price price--product-page dw-mod withoutvat">{{priceWithoutVat}} @Translate("EksMoms", "ex. moms")</div> 834 <text>{{/if}}</text> 835 <text>{{/if}}</text> 836 837 <text>{{#if showContactInfo}}</text> 838 string footeremail = Converter.ToString(Pageview.AreaSettings.GetItem("Settings").GetString("ContactEmail")); 839 string footerphone = Converter.ToString(Pageview.AreaSettings.GetItem("Settings").GetString("ContactNumber")).Replace(" ", ""); 840 <p class="">@Translate("ZeroPriceInfo", "Kontakt os og få oplyst pris.")</p> 841 <a class="btn btn--secondary btn--condensed u-no-margin dw-mod zeroprice" href="tel:@footerphone"><i class="fas fa-mobile-alt"></i> @Translate("ZeroPriceContactcustomservice", "Ring til kundeservice")</a> 842 <a class="btn btn--secondary btn--condensed u-no-margin dw-mod zeroprice" href="mailto:@footeremail"><i class="far fa-envelope"></i> @Translate("ZeroPriceContact-Email", "Skriv til kundeservice")</a> 843 <text>{{/if}}</text> 844 } 845 </div> 846 <div class="buttons-collection buttons-collection--right product__price-actions__actions dw-mod"> 847 <input type="checkbox" id="UnitOptions_{{id}}" class="dropdown-trigger" /> 848 <div class="dropdown u-w150px u-w80px--xs dw-mod {{hasUnits}}"> 849 <label class="dropdown__header dropdown__btn dw-mod" for="UnitOptions_{{id}}">{{unitName}}</label> 850 <div id="unitOptions" class="dropdown__content dw-mod"> 851 {{#unitOptions}} 852 {{>UnitOption}} 853 {{/unitOptions}} 854 </div> 855 <label class="dropdown-trigger-off" for="UnitOptions_{{id}}"></label> 856 </div> 857 <input type="hidden" value="{{unitId}}" name="Unit" id="Unit_{{id}}" /> 858 <text>{{#if showPrice}}</text> 859 @if (mainPointShopOnly) 860 { 861 <button type="button" id="CartButton_{{id}}" class="btn btn--primary btn--condensed u-no-margin dw-mod js-cart-btn {{disabledBuyButton}} {{#unless canBePurchasedWithPoints}}js-stay-disabled{{/unless}}" name="CartCmd" value="addWithPoints" 862 onclick="Cart.AddToCart(event, { 863 id: '{{productId}}', 864 variantId: '{{variantid}}', 865 unitId: '{{unitId}}', 866 quantity: 1, 867 buyForPoints: true, 868 productInfo: {{productInfo}} 869 }); {{facebookPixelAction}}"> 870 <i class="@mainInfoCartIcon"></i><span class="u-hidden-xs u-hidden-xxs"> @Translate("Buy with points")</span> 871 </button> 872 <text> 873 {{#unless canBePurchasedWithPoints}} 874 {{#if havePointPrice}} 875 <small class="help-text u-no-margin u-margin-top">@Translate("Not enough points to buy this")</small> 876 {{/if}} 877 {{/unless}} 878 </text> 879 } 880 else 881 { 882 <input type="number" class="u-w70px" id="Quantity_{{id}}" name="Quantity" value="1" min="1"> 883 <button type="button" id="CartButton_{{id}}" class="btn btn--primary btn--condensed u-no-margin dw-mod js-cart-btn" name="submit" 884 onclick="Cart.AddToCart(event, { 885 id: '{{productId}}', 886 variantId: '{{variantid}}', 887 unitId: '{{unitId}}', 888 quantity: document.getElementById('Quantity_{{id}}').value, 889 productInfo: {{productInfo}} 890 }); {{facebookPixelAction}}"> 891 <span class="u-hidden-xs u-hidden-xxs"> @Translate("Add to cart")</span><i class="@mainInfoCartIcon"></i> 892 </button> 893 } 894 <text>{{/if}}</text> 895 </div> 896 <text>{{#if showPrice}}</text> 897 <text>{{#if unitizedPrice}}</text> 898 <div class="product__unitizedPrice dw-mod"> 899 <div class="dw-mod ">{{#replace "[0]" unitizedPrice.Quantity}}{{#replace "[1]" unitizedPrice.PriceWithVatFormatted}}@Translate("Flerstykspris", "Ved køb af [0] stk. er prisen <span class=\"newprice\">[1]</span> pr. stk."){{/replace}}{{/replace}}</div> 900 <div class="price price--product-page dw-mod withoutvat">{{unitizedPrice.PriceWithoutVatFormatted}} @Translate("EksMoms", "ex. moms")</div> 901 </div> 902 <text>{{/if}}</text> 903 <text>{{/if}}</text> 904 905 906 if (Pageview.User != null && !mainPointShopOnly && Dynamicweb.Security.Licensing.LicenseManager.LicenseHasFeature("LoyaltyPoints")) 907 { 908 <text> 909 {{#if canBePurchasedWithPoints}} 910 <form method="post" role="form" class="u-no-margin u-margin-top"> 911 <input type="hidden" name="ProductID" value="{{id}}" /> 912 <button type="submit" class="btn btn--loyalty-points u-no-margin dw-mod pull-right u-no-margin js-cart-btn {{disabledBuyButton}}" name="CartCmd" value="addWithPoints">@Translate("Buy for") {{points}} @Translate("points")</button> 913 </form> 914 {{/if}} 915 </text> 916 } 917 } 918 else 919 { 920 <button type="button" id="CartButton_{{id}}" class="u-hidden"></button> 921 } 922 {{/ifCond}} 923 {{/.}} 924 </script> 925 926 <script id="Units" type="text/x-template"> 927 <div class="dropdown__item dw-mod" onclick="HandlebarsBolt.UpdateContent('PriceAndActions', '/[email protected]&UnitID={{value}}')">{{name}}</div> 928 </script> 929 930 <script id="UnitOption" type="text/x-template"> 931 <div class="dropdown__item dw-mod" onclick="HandlebarsBolt.UpdateContent('PriceAndActions', '{{link}}&feed=true&UnitID={{value}}&rid={{id}}')">{{name}}</div> 932 </script> 933 934 935 <script> 936 document.addEventListener("DOMContentLoaded", function () { 937 if (document.getElementById("PriceAndActions")) { 938 document.getElementById("PriceAndActions").addEventListener("contentLoaded", function (event) { 939 if (document.querySelector(".js-variants") != null) { 940 VariantHandling.Update(document.querySelector(".js-variants"), "DoNothing"); 941 } 942 }); 943 } 944 }); 945 </script> 946 947 @if (useGoogleTagManager) 948 { 949 var groupObject = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(GetString("Ecom:Product.PrimaryOrFirstGroupID")); 950 // find categoryPath 951 var categoryPath = ""; 952 953 954 var product = Dynamicweb.Ecommerce.Products.Product.GetProductById(GetString("Ecom:Product.ID")); 955 956 var primaryGroup = product.Groups.SingleOrDefault(g => g.Id == product.PrimaryGroupId); 957 958 959 if (primaryGroup != null) 960 { 961 var groupTextBuilder = new StringBuilder(primaryGroup.Id + "#" + primaryGroup.Id); 962 963 while (primaryGroup.ParentGroups.Count > 0) 964 { 965 var primaryGroupsText = primaryGroup.ParentGroups.Reverse() 966 .Aggregate<Group, string, string>(string.Empty, (g1, g2) => string.Format("{1};{0}", g1, g2.Id + "#" + g2.Id), result => result); 967 groupTextBuilder.Insert(0, primaryGroupsText); 968 969 primaryGroup = primaryGroup.ParentGroups[0]; 970 } 971 972 //while (!string.IsNullOrEmpty(primaryGroup.PrimaryParentGroupId)) 973 //{ 974 // primaryGroup = primaryGroup.ParentGroups.SingleOrDefault(g => g.Id == primaryGroup.PrimaryParentGroupId); 975 // groupTextBuilder.Insert(0, string.Format(" > {0}", primaryGroup.Name)); 976 //} 977 978 categoryPath = groupTextBuilder.ToString(); 979 } 980 else 981 { 982 var groupText = product.Groups.Reverse() 983 .Aggregate<Group, string, string>(string.Empty, (g1, g2) => string.Format("{1};{0}", g1, g2.Id + "#" + g2.Id), result => result); 984 var lastIndex = groupText.LastIndexOf(';'); 985 categoryPath = lastIndex == groupText.Length - 1 ? groupText.Remove(lastIndex - 1) : groupText; 986 } 987 988 <script> 989 // Measure a view of product details. This example assumes the detail view occurs on pageload, 990 // and also tracks a standard pageview of the details page. 991 (function () { 992 var data = { 993 'ecommerce': { 994 'detail': { 995 'actionField': {}, // 'detail' actions have an optional list property. 996 'products': [{ 997 'name': '@GetString("Ecom:Product.Name")', // Name or ID is required. 998 'id': '@GetString("Ecom:Product.Number")', 999 'price': '@(GetDouble("Ecom:Product.Discount.Price.PriceWithoutVAT.Value") != GetDouble("Ecom:Product.Price.PriceWithoutVAT.Value") ? GetDouble("Ecom:Product.Discount.Price.PriceWithoutVAT.Value") : GetDouble("Ecom:Product.Price.PriceWithoutVAT.Value"))', // Custom: price without VAT 1000 'brand': '@GetString("Ecom:Product:Field.brand.Value")', 1001 'category': '@(groupObject != null ? groupObject.Name : "")', 1002 'variant': '@(!string.IsNullOrEmpty(GetString("Ecom:Product.VariantID")) ? GetString("Ecom:Product.VariantID") : GetString("Ecom:Product.VariantID.Extented"))' 1003 }] 1004 }, 1005 'categoryPath': '@categoryPath' 1006 } 1007 }; 1008 1009 console.debug("GTM detail: ", data); 1010 1011 dataLayer.push(data); 1012 })(); 1013 </script> 1014 } 1015 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 1016 @using Dynamicweb.Core 1017 @using System 1018 @using System.Web 1019 @using System.Collections.Generic 1020 @using Dynamicweb.Rapido.Blocks 1021 1022 @functions { 1023 BlocksPage productDescriptionPage = BlocksPage.GetBlockPage("Product"); 1024 } 1025 1026 @{ 1027 string fullDesctiptionLayout = !String.IsNullOrEmpty(Pageview.AreaSettings.GetItem("ProductPage").GetString("FullDescriptionLayout")) ? Pageview.AreaSettings.GetItem("ProductPage").GetList("FullDescriptionLayout").SelectedValue : "Section"; 1028 fullDesctiptionLayout = fullDesctiptionLayout == "Ribbon" ? "Section" : fullDesctiptionLayout; 1029 1030 if (!string.IsNullOrEmpty(GetString("Ecom:Product.LongDescription")) && fullDesctiptionLayout != "hide") 1031 { 1032 Block detailsDescription = new Block() 1033 { 1034 Name = fullDesctiptionLayout != "MainInformation" ? Translate("Description") : "", 1035 Id = "FullDescription", 1036 SortId = 10, 1037 Template = RenderProductDescription(fullDesctiptionLayout), 1038 Design = new Design 1039 { 1040 Size = "12", 1041 RenderType = RenderType.Column, 1042 HidePadding = true 1043 } 1044 }; 1045 productDescriptionPage.Add(fullDesctiptionLayout, detailsDescription); 1046 } 1047 } 1048 1049 @helper RenderProductDescription(string layout) 1050 { 1051 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("FullDescriptionLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 1052 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("FullDescriptionLayout").SelectedValue == "Ribbon" ? "u-padding--lg" : ""; 1053 1054 <div class="product__section @ribbonClasses dw-mod"> 1055 <div class="product__description center-container @ribbonSubClasses dw-mod"> 1056 @if (layout == "Section") { 1057 <h2>@Translate("Description")</h2> 1058 } 1059 1060 @GetString("Ecom:Product.LongDescription") 1061 </div> 1062 </div> 1063 } 1064 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 1065 @using Dynamicweb.Core 1066 @using System 1067 @using System.Web 1068 @using System.Globalization; 1069 @using System.Collections.Generic 1070 @using Dynamicweb.Rapido.Blocks 1071 1072 @functions { 1073 BlocksPage productFieldsPage = BlocksPage.GetBlockPage("Product"); 1074 List<LoopItem> downloadDocuments = new List<LoopItem>(); 1075 1076 static string ConvertBytes(long bytes) 1077 { 1078 double size = bytes / 1024; //KB 1079 if (size > 1024) 1080 { 1081 size = (bytes / 1024f) / 1024f; //MB 1082 return string.Format("{0:n1} MB", size); 1083 } 1084 else 1085 { 1086 return string.Format("{0:n0} KB", size); 1087 } 1088 } 1089 1090 static bool isImage(string path) 1091 { 1092 return new List<string> { ".jpg", ".jpeg", ".gif", ".png", ".svg" }.Contains(Path.GetExtension(path).ToLower()); 1093 } 1094 1095 string getIconForFile(string fileName) 1096 { 1097 string ext = Path.GetExtension(fileName); 1098 string icon = ""; 1099 switch (ext.ToLower()) 1100 { 1101 case ".xls": 1102 case ".xlsx": 1103 icon = "fa-file-excel"; 1104 break; 1105 case ".ppt": 1106 case ".pptx": 1107 icon = "fa-file-powerpoint"; 1108 break; 1109 case ".doc": 1110 case ".docx": 1111 icon = "fa-file-word"; 1112 break; 1113 case ".jpg": 1114 case ".jpeg": 1115 case ".png": 1116 case ".gif": 1117 case ".pdf": 1118 return "<img class='product__document-img' alt='" + fileName + "' src='/Admin/Public/GetImage.ashx?crop=5&height=70&width=120&Compression=75&DoNotUpscale=true&image=" + fileName + "' />"; 1119 default: 1120 icon = "fa-file"; 1121 break; 1122 } 1123 return "<i class='product__document-icon far " + icon + "'></i> "; 1124 } 1125 } 1126 1127 @{ 1128 foreach (LoopItem customField in GetLoop("CustomFieldValues")) 1129 { 1130 if (!string.IsNullOrEmpty(customField.GetString("Product.CustomField.Name")) && !string.IsNullOrEmpty(customField.GetString("Product.CustomField.Value.Clean")) && customField.GetString("Product.CustomField.Name") != "Custom sticker") 1131 { 1132 if (!string.IsNullOrEmpty(customField.GetString("Document.FullPath"))) 1133 { 1134 downloadDocuments.Add(customField); 1135 } 1136 } 1137 } 1138 1139 foreach (LoopItem customField in GetLoop("ProductCategories")) 1140 { 1141 foreach (LoopItem field in customField.GetLoop("ProductCategoryFields")) 1142 { 1143 if (!string.IsNullOrEmpty(field.GetString("Ecom:Product.CategoryField.Label")) && !string.IsNullOrEmpty(field.GetString("Ecom:Product.CategoryField.Value"))) 1144 { 1145 if (field.GetString("Ecom:Product.CategoryField.TypeID") == "9") 1146 { 1147 downloadDocuments.Add(field); 1148 } 1149 } 1150 } 1151 } 1152 1153 string detailFieldsLayout = Pageview.AreaSettings.GetItem("ProductPage").GetList("DetailFieldsLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("DetailFieldsLayout").SelectedValue : "Section"; 1154 detailFieldsLayout = detailFieldsLayout == "Ribbon" || string.IsNullOrEmpty(detailFieldsLayout) ? "Section" : detailFieldsLayout; 1155 string categoryFieldsLayout = Pageview.AreaSettings.GetItem("ProductPage").GetList("CategoryFieldsLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("CategoryFieldsLayout").SelectedValue : "Section"; 1156 categoryFieldsLayout = categoryFieldsLayout == "Ribbon" || string.IsNullOrEmpty(categoryFieldsLayout) ? "Section" : categoryFieldsLayout; 1157 string downloadsFieldsLayout = Pageview.AreaSettings.GetItem("ProductPage").GetList("DownloadsLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("DownloadsLayout").SelectedValue : "Section"; 1158 downloadsFieldsLayout = downloadsFieldsLayout == "Ribbon" || string.IsNullOrEmpty(downloadsFieldsLayout) ? "Section" : downloadsFieldsLayout; 1159 1160 if (GetLoop("CustomFieldValues").Count > 0 && detailFieldsLayout != "hide") 1161 { 1162 // custom 1163 // dont render custom fields 1164 //Block detailsCustom = new Block() 1165 //{ 1166 // Name = detailFieldsLayout != "MainInformation" ? Translate("Details") : "", 1167 // Id = "CustomFields", 1168 // SortId = 30, 1169 // Template = RenderCustomData(detailFieldsLayout), 1170 // Design = new Design 1171 // { 1172 // Size = "12", 1173 // RenderType = RenderType.Column, 1174 // HidePadding = true 1175 // } 1176 //}; 1177 1178 //productFieldsPage.Add(detailFieldsLayout, detailsCustom); 1179 } 1180 1181 if (categoryFieldsLayout != "hide") { 1182 foreach (LoopItem categoryGroup in GetLoop("ProductCategories")) 1183 { 1184 bool hasFields = categoryGroup.GetLoop("ProductCategoryFields").FirstOrDefault(cf => !string.IsNullOrEmpty(cf.GetString("Ecom:Product.CategoryField.Value"))) != null; 1185 if (hasFields) 1186 { 1187 Block detailsCategoryFields = new Block() 1188 { 1189 Name = categoryFieldsLayout != "MainInformation" ? categoryGroup.GetString("Ecom:Product.Category.Name") : "", 1190 Id = ToPascalCase(categoryGroup.GetString("Ecom:Product.Category.Name")), 1191 SortId = 40, 1192 Template = RenderProductCategory(categoryGroup.GetString("Ecom:Product.Category.Name"), categoryGroup, categoryFieldsLayout), 1193 Design = new Design 1194 { 1195 Size = "12", 1196 RenderType = RenderType.Column, 1197 HidePadding = true 1198 } 1199 }; 1200 1201 productFieldsPage.Add(categoryFieldsLayout, detailsCategoryFields); 1202 } 1203 } 1204 } 1205 1206 if (downloadDocuments.Count > 0 && downloadsFieldsLayout != "hide") 1207 { 1208 Block detailsDownloads = new Block() 1209 { 1210 Name = downloadsFieldsLayout != "MainInformation" ? Translate("Downloads") : "", 1211 Id = "Downloads", 1212 SortId = 50, 1213 Template = RenderProductDownloads(downloadsFieldsLayout), 1214 Design = new Design 1215 { 1216 Size = "12", 1217 RenderType = RenderType.Column, 1218 HidePadding = true 1219 } 1220 }; 1221 1222 productFieldsPage.Add(downloadsFieldsLayout, detailsDownloads); 1223 } 1224 } 1225 1226 @helper RenderCustomData(string layout) 1227 { 1228 string viewType = Pageview.AreaSettings.GetItem("ProductPage").GetString("DetailFieldsView") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("DetailFieldsView").SelectedValue : "grid"; 1229 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("DetailFieldsLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 1230 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("DetailFieldsLayout").SelectedValue == "Ribbon" ? "u-padding--lg" : ""; 1231 1232 <div class="product__section @ribbonClasses dw-mod"> 1233 <div class="center-container @ribbonSubClasses dw-mod"> 1234 @if (layout == "Section") { 1235 <h2>@Translate("Information")</h2> 1236 } 1237 1238 @if (viewType != "table") { 1239 <div class="grid grid--external-bleed-x u-margin-bottom--lg"> 1240 @RenderCustomFields(GetLoop("CustomFieldValues"), viewType) 1241 </div> 1242 } else { 1243 string tableWidth = layout != "MainInformation" ? "grid__col-md-6" : "grid__col-md-12"; 1244 1245 <div class="grid grid--external-bleed-x u-margin-bottom--lg"> 1246 <div class="@tableWidth grid__col-sm-12 grid__col-xs-12"> 1247 <table class="table--no-top-border"> 1248 @RenderCustomFields(GetLoop("CustomFieldValues"), viewType) 1249 </table> 1250 </div> 1251 </div> 1252 } 1253 </div> 1254 </div> 1255 } 1256 1257 @helper RenderCustomFields(List<LoopItem> fieldsLoop, string viewType) 1258 { 1259 foreach (LoopItem customField in fieldsLoop) 1260 { 1261 string fieldValue = customField.GetString("Product.CustomField.Value.Clean"); 1262 fieldValue = fieldValue == "False" ? Translate("No") : fieldValue; 1263 fieldValue = fieldValue == "True" ? Translate("Yes") : fieldValue; 1264 1265 if (customField.GetLoop("Product.CustomField.Options").Count > 0) 1266 { 1267 fieldValue = customField.GetString("Product.CustomField.Label"); 1268 } 1269 1270 if (!string.IsNullOrEmpty(customField.GetString("Product.CustomField.Name")) && !string.IsNullOrEmpty(fieldValue) && customField.GetString("Product.CustomField.Name") != "Custom sticker") 1271 { 1272 if (string.IsNullOrEmpty(customField.GetString("Document.FullPath"))) 1273 { 1274 @RenderFieldItem(customField.GetString("Product.CustomField.Name"), fieldValue, viewType); 1275 } 1276 } 1277 } 1278 } 1279 1280 @helper RenderProductCategory(string name, LoopItem categoryGroup, string layout) 1281 { 1282 string viewType = Pageview.AreaSettings.GetItem("ProductPage").GetString("CategoryFieldsView") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("CategoryFieldsView").SelectedValue : "grid"; 1283 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("CategoryFieldsLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 1284 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("CategoryFieldsLayout").SelectedValue == "Ribbon" ? "u-padding--lg" : ""; 1285 1286 <div class="product__section @ribbonClasses dw-mod"> 1287 <div class="center-container @ribbonSubClasses dw-mod"> 1288 @if (layout == "Section") { 1289 <h2>@name</h2> 1290 } 1291 1292 @if (viewType != "table") { 1293 <div class="grid grid--external-bleed-x u-margin-bottom--lg"> 1294 @RenderProductCategoryFields(categoryGroup.GetLoop("ProductCategoryFields"), viewType) 1295 </div> 1296 } else { 1297 string tableWidth = layout != "MainInformation" ? "grid__col-md-6" : "grid__col-md-12"; 1298 1299 <div class="grid grid--external-bleed-x u-margin-bottom--lg"> 1300 <div class="@tableWidth grid__col-sm-12 grid__col-xs-12"> 1301 <table class="table--no-top-border"> 1302 @RenderProductCategoryFields(categoryGroup.GetLoop("ProductCategoryFields"), viewType) 1303 </table> 1304 </div> 1305 </div> 1306 } 1307 </div> 1308 </div> 1309 } 1310 1311 @helper RenderProductCategoryFields(List<LoopItem> fieldsLoop, string viewType) { 1312 foreach (LoopItem categoryField in fieldsLoop) 1313 { 1314 string fieldValue = categoryField.GetString("Ecom:Product.CategoryField.Value"); 1315 fieldValue = fieldValue == "False" ? Translate("No") : fieldValue; 1316 fieldValue = fieldValue == "True" ? Translate("Yes") : fieldValue; 1317 1318 if (!string.IsNullOrEmpty(categoryField.GetString("Ecom:Product.CategoryField.Label")) && !string.IsNullOrEmpty(fieldValue)) 1319 { 1320 if (categoryField.GetString("Ecom:Product.CategoryField.TypeID") != "9") { 1321 if (categoryField.GetString("Ecom:Product.CategoryField.TypeID") == "15") 1322 { 1323 @RenderFieldItem(categoryField.GetString("Ecom:Product.CategoryField.Label"), categoryField.GetString("Ecom:Product.CategoryField.OptionLabel"), viewType); 1324 } 1325 else if (categoryField.GetString("Ecom:Product.CategoryField.TypeID") == "8") 1326 { 1327 @RenderFieldItem(categoryField.GetString("Ecom:Product.CategoryField.Label"), fieldValue, viewType, "link"); 1328 } 1329 else 1330 { 1331 @RenderFieldItem(categoryField.GetString("Ecom:Product.CategoryField.Label"), fieldValue, viewType); 1332 } 1333 } 1334 } 1335 } 1336 } 1337 1338 @helper RenderProductDownloads(string layout) 1339 { 1340 string viewType = Pageview.AreaSettings.GetItem("ProductPage").GetString("DownloadsView") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("DownloadsView").SelectedValue : "grid"; 1341 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("DownloadsLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 1342 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("DownloadsLayout").SelectedValue == "Ribbon" ? "u-padding--lg" : ""; 1343 1344 <div class="product__section @ribbonClasses dw-mod"> 1345 <div class="center-container @ribbonSubClasses dw-mod"> 1346 @if (layout == "Section") { 1347 <h2>@Translate("Downloads")</h2> 1348 } 1349 1350 @if (viewType != "table") { 1351 <div class="grid grid--external-bleed-x u-margin-bottom--lg"> 1352 @RenderProductDownloadsFields(downloadDocuments, viewType) 1353 </div> 1354 } else { 1355 string tableWidth = layout != "MainInformation" ? "grid__col-md-6" : "grid__col-md-12"; 1356 1357 <div class="grid grid--external-bleed-x u-margin-bottom--lg"> 1358 <div class="@tableWidth grid__col-sm-12 grid__col-xs-12"> 1359 <table class="table--no-top-border"> 1360 @RenderProductDownloadsFields(downloadDocuments, viewType) 1361 </table> 1362 </div> 1363 </div> 1364 } 1365 </div> 1366 </div> 1367 } 1368 1369 @helper RenderProductDownloadsFields(List<LoopItem> fieldsLoop, string viewType) { 1370 foreach (LoopItem document in fieldsLoop) 1371 { 1372 string fieldValue; 1373 if (!string.IsNullOrEmpty(document.GetString("Document.FullPath"))) 1374 { 1375 fieldValue = document.GetString("Product.CustomField.Value.Clean"); 1376 @RenderFieldItem(fieldValue, document.GetString("Document.FullPath"), viewType, "download") 1377 } 1378 1379 if (document.GetString("Ecom:Product.CategoryField.TypeID") == "9") 1380 { 1381 fieldValue = document.GetString("Ecom:Product.CategoryField.Value"); 1382 @RenderFieldItem(fieldValue, fieldValue, viewType, "download") 1383 } 1384 } 1385 } 1386 1387 @helper RenderFieldItem(string name, string value, string viewType, string fieldType = "clean") 1388 { 1389 if (viewType != "table") { 1390 string fieldColumns = viewType == "list" ? "12" : "4"; 1391 <div class="[email protected] u-margin-bottom"> 1392 <div class="u-bold"> 1393 @name 1394 </div> 1395 <div> 1396 @RenderFieldItemContent(name, value, fieldType) 1397 </div> 1398 </div> 1399 } else { 1400 <tr> 1401 @if (fieldType == "download") { 1402 <td colspan="2"> 1403 @RenderFieldItemContent(name, value, fieldType) 1404 </td> 1405 } 1406 else 1407 { 1408 <td class="u-bold">@name</td> 1409 <td> 1410 @RenderFieldItemContent(name, value, fieldType) 1411 </td> 1412 } 1413 </tr> 1414 } 1415 } 1416 1417 @helper RenderFieldItemContent(string name, string value, string fieldType = "clean") 1418 { 1419 if (fieldType == "link") 1420 { 1421 <a target="_blank" href="@value"> 1422 @if (isImage(value)) { 1423 @getIconForFile(value) 1424 } else { 1425 @value 1426 } 1427 </a> 1428 } 1429 else if (fieldType == "download") 1430 { 1431 FileInfo info = new FileInfo(Dynamicweb.Core.SystemInformation.MapPath(value)); 1432 1433 if (info.Exists) { 1434 <div class="grid grid--no-wrap"> 1435 <a href="@name" download title="@Translate("Download")" class="product__document u-min-w120px u-ta-center dw-mod">@getIconForFile(value)</a> 1436 <div class="product__document-info dw-mod"> 1437 <a href="@name" download title="@Translate("Download")" class="product__document dw-mod">@Path.GetFileName(value)</a> 1438 <small class="u-block u-margin-top">@ConvertBytes(info.Length)</small> 1439 </div> 1440 </div> 1441 } 1442 } 1443 else 1444 { 1445 @value 1446 } 1447 } 1448 1449 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 1450 @using Dynamicweb.Core 1451 @using System 1452 @using System.Web 1453 @using System.Collections.Generic 1454 @using Dynamicweb.Rapido.Blocks 1455 1456 @functions { 1457 BlocksPage productVariantsPage = BlocksPage.GetBlockPage("Product"); 1458 } 1459 1460 @{ 1461 bool renderVariantsAsProducts = Pageview.AreaSettings.GetItem("ProductPage").GetString("RenderVariantsAsProductList") != null && GetInteger("Ecom:Product.VariantCount") > 1 ? Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("RenderVariantsAsProductList") : false; 1462 bool variantsOnlyPreview = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("OnlyPreviewForAnonymous") && Pageview.User == null; 1463 string variantsListPageSize = HttpContext.Current.Request.QueryString.Get("PageSize") != null ? HttpContext.Current.Request.QueryString.Get("PageSize") : "30"; 1464 string variantsFeedUrl = "/Default.aspx?ID=" + GetPageIdByNavigationTag("ProductsPage") + "&PageSize=" + variantsListPageSize + "&MainProductID=" + GetString("Ecom:Product.ID") + "&OnlyShowVariants=true&feed=true"; 1465 string variantsCartIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetString("CartIcon") != null ? Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon").SelectedValue : "fas fa-shopping-cart"; 1466 bool variantsPointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly"); 1467 1468 string variantsListLayout = Pageview.AreaSettings.GetItem("ProductPage").GetString("VariantsListLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("VariantsListLayout").SelectedValue : "Section"; 1469 variantsListLayout = variantsListLayout == "Ribbon" ? "Section" : variantsListLayout; 1470 1471 if (renderVariantsAsProducts && variantsListLayout != "hide") 1472 { 1473 Block detailsVariantsList = new Block() 1474 { 1475 Name = variantsListLayout != "MainInformation" ? Translate("Variants list") : "", 1476 Id = "VariantsList", 1477 SortId = 20, 1478 Template = RenderVariantsProductList(variantsListLayout), 1479 Design = new Design 1480 { 1481 Size = "12", 1482 RenderType = RenderType.Column, 1483 HidePadding = true 1484 } 1485 }; 1486 productVariantsPage.Add(variantsListLayout, detailsVariantsList); 1487 } 1488 } 1489 1490 @helper RenderVariantsProductList(string layout) 1491 { 1492 string variantsListPageSize = HttpContext.Current.Request.QueryString.Get("PageSize") != null ? HttpContext.Current.Request.QueryString.Get("PageSize") : "30"; 1493 string variantsFeedUrl = "/Default.aspx?ID=" + GetPageIdByNavigationTag("ProductsPage") + "&PageSize=" + variantsListPageSize + "&MainProductID=" + GetString("Ecom:Product.ID") + "&OnlyShowVariants=true&feed=true"; 1494 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("VariantsListLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 1495 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("VariantsListLayout").SelectedValue == "Ribbon" ? "u-padding--lg" : ""; 1496 1497 <div class="product__section @ribbonClasses dw-mod"> 1498 <div class="center-container @ribbonSubClasses dw-mod"> 1499 @if (layout == "Section") 1500 { 1501 <h2>@Translate("Variants")</h2> 1502 } 1503 1504 <div class="js-handlebars-root" id="VariantsListRoot" data-template="VariantProductsContainer" data-json-feed="@variantsFeedUrl" data-preloader="minimal"></div> 1505 </div> 1506 </div> 1507 } 1508 1509 1510 @* Script templates for variant products *@ 1511 1512 <script id="VariantProductsContainer" type="text/x-template"> 1513 {{#.}} 1514 <div class=""> 1515 <table id="VariantsProductsContainer" class="table u-position-relative dw-mod"> 1516 <thead> 1517 <tr> 1518 <td width="75">&nbsp;</td> 1519 <td>@Translate("Product")</td> 1520 {{#AvailableCustomFields}} 1521 {{>TableFieldNameTemplate}} 1522 {{/AvailableCustomFields}} 1523 @if (Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("RenderVariantGroupsInTable")) 1524 { 1525 foreach (LoopItem variantgroup in GetLoop("VariantGroups")) 1526 { 1527 <td>@variantgroup.GetString("Ecom:VariantGroup.Name")</td> 1528 } 1529 } 1530 <td width="360">&nbsp;</td> 1531 </tr> 1532 </thead> 1533 1534 <tbody id="VariantProductListContainer" data-template="VariantProductItemContainer" data-save-cookie="true"> 1535 {{#ProductsContainer}} 1536 {{>VariantProductItemContainer}} 1537 {{/ProductsContainer}} 1538 </tbody> 1539 </table> 1540 </div> 1541 1542 <div class="grid"> 1543 <div class="grid__col-12 grid__col--bleed-y"> 1544 <button type="button" id="LoadMoreButton" class="btn btn--secondary btn--full {{nextdisabled}} dw-mod" data-current="{{currentPage}}" data-page-size="{{pageSize}}" data-total="{{totalPages}}" data-container="VariantProductListContainer" data-feed-url="@variantsFeedUrl{{loadMoreFeedParams}}" onclick="LoadMore.Next(this)" {{nextdisabled}}>@Translate("Load") @Translate("more")</button> 1545 </div> 1546 </div> 1547 {{/.}} 1548 </script> 1549 1550 <script id="VariantProductItemContainer" type="text/x-template"> 1551 {{#.}} 1552 <tr id="VariantProduct{{id}}" data-template="VariantProductItem" data-preloader="overlay" style="z-index: {{zIndex}}"> 1553 {{#Product}} 1554 {{>VariantProductItem}} 1555 {{/Product}} 1556 </tr> 1557 {{/.}} 1558 </script> 1559 1560 <script id="VariantProductItem" type="text/x-template"> 1561 {{#.}} 1562 <td width="75"> 1563 <div class="lightbox u-hidden-xxs"> 1564 <a href="{{link}}" onclick="Scroll.SavePosition(event)"> 1565 <img class="lightbox__image {{noImage}}" src="{{PerfionImageSrc imageGuid 220 220}}" alt="{{name}}" /> 1566 <div class="u-margin-right {{noImage}}"> 1567 <img src="{{PerfionImageSrc imageGuid 75 55}}" alt="{{name}}" /> 1568 </div> 1569 </a> 1570 </div> 1571 </td> 1572 <td class="u-va-middle"> 1573 <a href="{{link}}" onclick="Scroll.SavePosition(event)" title="{{name}}"><h6 class="u-no-margin">{{name}}</h6></a> 1574 <div class="item-number item-number--compressed dw-mod"> 1575 {{#if showProductNumber}}{{number}}{{/if}} 1576 @if (!variantsOnlyPreview) 1577 { 1578 @* Custom *@ 1579 <div> 1580 <span class="stock-icon {{stockState}} u-no-margin dw-mod" title="{{stockText}}"></span>&nbsp;{{stockText}} 1581 <p>{{deliveryText}}</p> 1582 </div> 1583 } 1584 else 1585 { 1586 <div class="grid__cell-footer stickers-container stickers-container--block dw-mod"> 1587 {{#Stickers}} 1588 {{>MiniSticker}} 1589 {{/Stickers}} 1590 </div> 1591 } 1592 </div> 1593 </td> 1594 {{#CustomFields}} 1595 {{>TableFieldValueTemplate}} 1596 {{/CustomFields}} 1597 @if (Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("RenderVariantGroupsInTable")) 1598 { 1599 <text> 1600 {{#VariantSelectionNames}} 1601 {{>TableFieldNameTemplate}} 1602 {{/VariantSelectionNames}} 1603 </text> 1604 } 1605 <td width="320" class="u-va-middle"> 1606 @if (!variantsOnlyPreview) 1607 { 1608 <text>{{#if showPrice}}</text> 1609 <div class="u-hidden-sm"> 1610 <div class="u-full-width u-ta-right u-padding-right"> 1611 <div class="before-price {{onSale}} before-price--micro dw-mod">{{discount}}</div> 1612 <div class="price price--product-list price--micro dw-mod">{{price}}</div> 1613 </div> 1614 </div> 1615 <text>{{/if}}</text> 1616 <text>{{#if showContactInfo}}</text> 1617 <p class="pp__zeroprice-text">@Translate("ZeroPriceText", "Kontakt vores kundeservice for at få oplyst pris.")</p> 1618 <p class="pp__zeroprice-contact">@Translate("ZeroPriceContact", "Ring på tlf: 7021 2626 (kl. 8.00-16.00) eller skriv til [email protected]")</p> 1619 <text>{{/if}}</text> 1620 } 1621 else 1622 { 1623 <div class="grid grid--align-center grid--justify-end"> 1624 <div class="favorites u-margin-right {{hasVariants}} dw-mod" {{hasVariants}}> 1625 {{#Favorite}} 1626 {{>FavoriteTemplate}} 1627 {{/Favorite}} 1628 </div> 1629 <div class="u-margin-right"> 1630 <input type="checkbox" id="UnitOptions_{{id}}" class="dropdown-trigger" /> 1631 <div class="dropdown u-w120px {{hasUnits}} dw-mod"> 1632 <label class="dropdown__header dropdown__btn dw-mod" for="UnitOptions_{{id}}">{{unitName}}</label> 1633 <div id="unitOptions" class="dropdown__content dw-mod"> 1634 {{#unitOptions}} 1635 {{>UnitOption}} 1636 {{/unitOptions}} 1637 </div> 1638 <label class="dropdown-trigger-off" for="UnitOptions_{{id}}"></label> 1639 </div> 1640 <input type="hidden" value="{{unitId}}" name="Unit{{id}}" id="Unit_{{id}}" /> 1641 <input type="hidden" value="{{variantid}}" name="VariantID{{id}}" id="Variant_{{id}}" /> 1642 </div> 1643 <div class="u-margin-right u-hidden-xs u-hidden-xxs"> 1644 @if (variantsPointShopOnly) 1645 { 1646 <text> 1647 {{#if canBePurchasedWithPoints}} 1648 <div class="price price--product-list price--micro dw-mod">{{points}} @Translate("points")</div> 1649 {{else}} 1650 {{#if havePointPrice}} 1651 <small class="help-text u-no-margin u-margin-top">@Translate("Not enough points to buy this")</small> 1652 {{else}} 1653 <small class="help-text u-no-margin u-margin-top">@Translate("Not available")</small> 1654 {{/if}} 1655 {{/if}} 1656 </text> 1657 } 1658 else 1659 { 1660 <text>{{#if showPrice}}</text> 1661 <div class="before-price before-price--micro {{onSale}} dw-mod">{{discount}}</div> 1662 <div class="price price--condensed price--product-list dw-mod">{{price}}</div> 1663 <text>{{/if}}</text> 1664 <text>{{#if showContactInfo}}</text> 1665 <p class="pp__zeroprice-text">@Translate("ZeroPriceText", "Kontakt vores kundeservice for at få oplyst pris.")</p> 1666 <p class="pp__zeroprice-contact">@Translate("ZeroPriceContact", "Ring på tlf: 7021 2626 (kl. 8.00-16.00) eller skriv til [email protected]")</p> 1667 <text>{{/if}}</text> 1668 } 1669 </div> 1670 <text>{{#if showPrice}}</text> 1671 @if (variantsPointShopOnly) 1672 { 1673 <div> 1674 <button {{#unless canBePurchasedWithPoints}} disabled{{/unless}} type="button" 1675 id="CartButton_{{id}}" 1676 class="btn btn--primary btn--condensed u-no-margin dw-mod js-cart-btn {{#unless canBePurchasedWithPoints}}disabled js-stay-disabled{{/unless}}" 1677 name="CartCmd" 1678 value="addWithPoints" 1679 onclick="Cart.AddToCart(event, { 1680 id: '{{productId}}', 1681 variantId: '{{variantid}}', 1682 unitId: '{{unitId}}', 1683 quantity: 1, 1684 buyForPoints: true, 1685 productInfo: {{productInfo}} 1686 })"> 1687 <i class="@variantsCartIcon"></i> 1688 </button> 1689 </div> 1690 } 1691 else 1692 { 1693 <div> 1694 <input type="number" class="u-w80px u-no-margin u-margin-right" id="Quantity_{{id}}" name="Quantity{{id}}" value="1" min="1"> 1695 </div> 1696 <div> 1697 <button type="button" id="CartButton_{{id}}" class="btn btn--primary btn--condensed u-no-margin dw-mod" name="submit" 1698 onclick="Cart.AddToCart(event, { 1699 id: '{{productId}}', 1700 variantId: '{{variantid}}', 1701 unitId: '{{unitId}}', 1702 quantity: document.getElementById('Quantity_{{id}}').value, 1703 productInfo: {{productInfo}} 1704 });"> 1705 <i class="@variantsCartIcon"></i> 1706 </button> 1707 </div> 1708 } 1709 <text>{{/if}}</text> 1710 </div> 1711 } 1712 </td> 1713 {{/.}} 1714 </script> 1715 1716 <script id="TableFieldNameTemplate" type="text/x-template"> 1717 <td class="u-va-middle">{{name}}</td> 1718 </script> 1719 1720 <script id="TableFieldValueTemplate" type="text/x-template"> 1721 <td class="u-va-middle">{{value}}</td> 1722 </script> 1723 1724 <script id="MiniSticker" type="text/x-template"> 1725 <div class="stickers-container__tag stickers-container__tag--micro {{className}} dw-mod">{{text}}</div> 1726 </script> 1727 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 1728 @using Dynamicweb.Core 1729 @using System 1730 @using System.Web 1731 @using System.Collections.Generic 1732 @using Dynamicweb.Rapido.Blocks 1733 1734 @using PLindberg.Dynamicweb.Common; 1735 1736 @functions{ 1737 BlocksPage productRelatedPage = BlocksPage.GetBlockPage("Product"); 1738 } 1739 1740 @{ 1741 string relatedProductsLayout = Pageview.AreaSettings.GetItem("ProductPage").GetList("RelatedProductsLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("RelatedProductsLayout").SelectedValue : "Section"; 1742 relatedProductsLayout = relatedProductsLayout == "Ribbon" || string.IsNullOrEmpty(relatedProductsLayout) ? "Section" : relatedProductsLayout; 1743 bool relatedOnlyPreview = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("OnlyPreviewForAnonymous") && Pageview.User == null; 1744 bool relatedPointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly"); 1745 1746 int relatedProductsPageSize = 4; 1747 int relatedProductsColumnWidth = 3; 1748 1749 if (Pageview.Device.ToString() == "Mobile") 1750 { 1751 relatedProductsPageSize = 1; 1752 relatedProductsColumnWidth = 12; 1753 } 1754 1755 if (Pageview.Device.ToString() == "Tablet") 1756 { 1757 relatedProductsPageSize = 2; 1758 relatedProductsColumnWidth = 6; 1759 } 1760 1761 if (relatedProductsLayout != "hide") 1762 { 1763 // custom (only use related product group here) 1764 var relationGroupId = new WebConfigSettings().GetValue("Perfion/Global", "RelatedProductsRelatedGroupId"); 1765 1766 //string relationGroupId = Dynamicweb.Base.GetGs("/Globalsettings/Picopublish/Global/RelatedProductsRelatedGroupId"); 1767 var relatedGroup = GetLoop("ProductRelatedGroups").FirstOrDefault(l => l.GetString("Ecom:Product:RelatedGroup.GroupID") == relationGroupId && l.GetLoop("Products").Count() > 0); 1768 1769 if (relatedGroup != null) 1770 { 1771 // custom 1772 string relatedGroupId = relatedGroup.GetString("Ecom:Product:RelatedGroup.Name"); 1773 string baseFeedPageUrl = "/Default.aspx?ID=" + GetPageIdByNavigationTag("ProductsPage") + "&PageSize=" + relatedProductsPageSize + "&ProdID=" + GetString("Ecom:Product.ID") + "&feed=true"; 1774 string relatedFeed = baseFeedPageUrl + "&" + relatedGroupId + "=" + GetString("Ecom:Product.ID") + "&GroupName=" + relatedGroupId; 1775 string relatedGroupName = relatedProductsLayout != "maininformation" ? relatedGroup.GetString("Ecom:Product:RelatedGroup.Name") : ""; 1776 1777 Block detailsRelated = new Block() 1778 { 1779 Name = relatedGroupName, 1780 Id = relatedGroupId, 1781 SortId = 70, 1782 Template = RenderRelatedProducts(relatedGroupName, relatedGroupId, relatedFeed, relatedProductsLayout), 1783 Design = new Design 1784 { 1785 Size = "12", 1786 RenderType = RenderType.Column, 1787 HidePadding = true 1788 } 1789 }; 1790 1791 productRelatedPage.Add(relatedProductsLayout, detailsRelated); 1792 } 1793 } 1794 } 1795 1796 @helper RenderRelatedProducts(string name, string groupId, string relatedFeedUrl, string layout) 1797 { 1798 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("RelatedProductsLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 1799 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("RelatedProductsLayout").SelectedValue == "Ribbon" ? "u-padding--lg" : ""; 1800 1801 <div class="product__section @ribbonClasses dw-mod"> 1802 <div class="center-container @ribbonSubClasses dw-mod "> 1803 @if (layout == "Section") 1804 { 1805 <h2 class="u-margin-top">@Translate("RelatedHeading", "Relaterede varer")</h2> 1806 } 1807 1808 <div class="js-handlebars-root" id="[email protected]" data-template="ProductContainer" data-pre-render-template="ProductPreRenderContainer" data-json-feed="@relatedFeedUrl" data-preloader="minimal"></div> 1809 </div> 1810 </div> 1811 } 1812 1813 @helper RenderRelatedProductsMini(string name, string groupId, string relatedFeedUrl) 1814 { 1815 <div class="js-handlebars-root" id="[email protected]" data-template="ProductContainerMini" data-pre-render-template="ProductPreRenderContainer" data-json-feed="@relatedFeedUrl" data-preloader="minimal"></div> 1816 } 1817 1818 @* Script templates for related products *@ 1819 <script id="ProductPreRenderContainer" type="text/x-template"> 1820 <div class="u-h600px u-full-width"> 1821 <div class="grid"> 1822 <div class="grid__col-12"> 1823 <div class="pre-render-element pre-render-element--md"></div> 1824 </div> 1825 </div> 1826 </div> 1827 </script> 1828 1829 <script id="ProductContainer" type="text/x-template"> 1830 {{#.}} 1831 <div class="u-min-h400px u-full-width "> 1832 <div class="grid"> 1833 <div class="grid__col-45px grid__col--bleed-x relatedleft"> 1834 <div class="grid__cell grid__cell--align-middle-left"> 1835 <button class="btn btn--condensed btn--clean {{prevdisabled}} dw-mod" onclick="HandlebarsBolt.UpdateContent('ProductList_{{groupName}}', '{{prevPage}}')" {{prevdisabled}}><i class="fas fa-chevron-left fa-2x"></i></button> 1836 </div> 1837 </div> 1838 <div class="grid__col-auto grid__col--bleed-x"> 1839 <div id="ProductsContainer" data-template="ProductGridItemContainer" class="grid product-list dw-mod" data-save-cookie="true"> 1840 {{#ProductsContainer}} 1841 <div id="Product{{productId}}" class="[email protected] product-list__grid-item dw-mod"> 1842 {{#Product}} 1843 @if (useGoogleTagManager) 1844 { 1845 <text>{{{googleEnchantImpression 'Related products' currency googleImpression}}}</text> 1846 } 1847 <div class="grid__cell product-list__grid-item__image dw-mod {{noImage}}"> 1848 <div class="stickers-container dw-mod"> 1849 {{#Stickers}} 1850 {{>Sticker}} 1851 {{/Stickers}} 1852 </div> 1853 {{!-- custom --}} 1854 <a href="{{link}}" onclick="Scroll.SavePosition(event)"><img class="grid__cell-img grid__cell-img--centered u-padding b-lazy" src="/Files/Images/placeholder.gif" data-src="{{PerfionImageSrc imageGuid 200 200}}" alt="{{name}}" /></a> 1855 </div> 1856 <div class="grid__cell product-list__grid-item__price-info {{shortGridInfo}} dw-mod"> 1857 <a href="{{link}}" onclick="Scroll.SavePosition(event)" title="{{name}}"><h6>{{name}}</h6></a> 1858 {{#if showProductNumber}} 1859 <div class="item-number dw-mod">{{number}}</div> 1860 {{/if}} 1861 1862 {{#ifCond PerfionProductFreightAddon "==" true }} 1863 <div class="freigtextra related" title='@Translate("Freightaddon", "Fragttillæg")'> 1864 <i class="fas fa-truck"></i> 1865 </div> 1866 {{/ifCond}} 1867 1868 @if (!relatedOnlyPreview) 1869 { 1870 if (relatedPointShopOnly) 1871 { 1872 <text> 1873 {{#if havePointPrice}} 1874 <div>{{points}} @Translate("points")</div> 1875 {{else}} 1876 @Translate("Not available") 1877 {{/if}} 1878 </text> 1879 } 1880 else 1881 { 1882 @* custom *@ 1883 <div class="priceinfocontainer"> 1884 <text>{{#if showPrice}}</text> 1885 <text>{{#if showinfoPrice}}</text> 1886 <div class="before-price {{onSale}} dw-mod">{{discount}}</div> 1887 <div class="price price--product-list dw-mod newprice"><span>@Translate("Nu", "Nu")</span>{{price}}</div> 1888 <div class="price price--product-list price withoutvat dw-mod">{{priceWithoutVat}} @Translate("EksMoms", "ex. moms")</div> 1889 <div class="price price--product-list price withoutvat dw-mod beforeprice"><span>@Translate("Beforeprice", "Før")</span> {{informativePrice.priceWithVat}}</div> 1890 <div class="price price--product-list price withoutvat dw-mod">{{informativePrice.price}} @Translate("EksMoms", "ex. moms")</div> 1891 <text>{{else}}</text> 1892 <div class="before-price {{onSale}} dw-mod">{{discount}}</div> 1893 <div class="price price--product-list dw-mod">{{price}}</div> 1894 <div class="price price--product-list price withoutvat dw-mod">{{priceWithoutVat}} @Translate("EksMoms", "ex. moms")</div> 1895 <text>{{/if}}</text> 1896 <text>{{/if}}</text> 1897 1898 <text>{{#ifCond startPrice "&&" showVariantPrice}}</text> 1899 <div class="pp__startprice-container"> 1900 {{#if isStartingPrice}} 1901 <span class="price price--product-list dw-mod pp__startprice">@Translate("StartingFrom", "Fra") {{startPrice.priceWithVat}}</span> 1902 <div class="price price--product-list price withoutvat dw-mod">@Translate("StartingFrom", "Fra") {{startPrice.price}} @Translate("EksMoms", "ex. moms")</div> 1903 {{/if}} 1904 {{#unless isStartingPrice}} 1905 <span class="price price--product-list dw-mod pp__startprice">{{startPrice.priceWithVat}}</span> 1906 <div class="price price--product-list price withoutvat dw-mod">{{startPrice.price}} @Translate("EksMoms", "ex. moms")</div> 1907 {{/unless}} 1908 </div> 1909 <text>{{/ifCond}}</text> 1910 </div> 1911 } 1912 } 1913 </div> 1914 1915 <div class="product-list__grid-item__footer dw-mod"> 1916 <div class="u-ta-center"> 1917 <a href="{{link}}" id="CartButton_{{id}}" class="btn btn--primary u-no-margin dw-mod">@Translate("View")</a> 1918 </div> 1919 </div> 1920 {{/Product}} 1921 </div> 1922 {{/ProductsContainer}} 1923 </div> 1924 </div> 1925 <div class="grid__col-45px grid__col--bleed-x relatedright"> 1926 <div class="grid__cell grid__cell--align-middle-right"> 1927 <button class="btn btn--condensed btn--clean {{nextdisabled}} dw-mod" onclick="HandlebarsBolt.UpdateContent('ProductList_{{groupName}}', '{{nextPage}}')" {{nextdisabled}}><i class="fas fa-chevron-right fa-2x"></i></button> 1928 </div> 1929 </div> 1930 </div> 1931 </div> 1932 {{/.}} 1933 </script> 1934 1935 <script id="ProductContainerMini" type="text/x-template"> 1936 {{#.}} 1937 <div class="u-full-width"> 1938 <div class="grid"> 1939 <div class="grid__col-45px grid__col--bleed-x relatedleft"> 1940 <div class="grid__cell grid__cell--align-middle-left"> 1941 <button class="btn btn--condensed btn--clean {{prevdisabled}} dw-mod" onclick="HandlebarsBolt.UpdateContent('ProductList_{{groupName}}', '{{prevPage}}')" {{prevdisabled}}><i class="fas fa-chevron-left fa-2x"></i></button> 1942 </div> 1943 </div> 1944 <div class="grid__col-auto grid__col--bleed-x"> 1945 <div id="ProductsContainer" class="grid product-list dw-mod"> 1946 {{#ProductsContainer}} 1947 <div id="Product{{productId}}" class="[email protected] product-list__grid-item dw-mod"> 1948 {{#Product}} 1949 @if (useGoogleTagManager) 1950 { 1951 <text>{{{googleEnchantImpression 'Related products' currency googleImpression}}}</text> 1952 } 1953 <div class="grid__cell product-list__grid-item__image dw-mod {{noImage}}"> 1954 <div class="stickers-container dw-mod"> 1955 {{#Stickers}} 1956 {{>Sticker}} 1957 {{/Stickers}} 1958 </div> 1959 <a href="{{link}}" onclick="Scroll.SavePosition(event)"><img class="grid__cell-img grid__cell-img--centered b-lazy" src="/Files/Images/placeholder.gif" data-src="/Admin/Public/GetImage.ashx?width=300&amp;height=300&amp;crop=5&amp;Compression=75&amp;FillCanvas=true&amp;DoNotUpscale=true&amp;image={{image}}" alt="{{name}}" /></a> 1960 </div> 1961 1962 <div class="grid__cell product-list__grid-item__price-info {{shortGridInfo}} dw-mod"> 1963 <a href="{{link}}" onclick="Scroll.SavePosition(event)" title="{{name}}"><h6 class="u-condensed-text">{{name}}</h6></a> 1964 {{#if showProductNumber}} 1965 <div class="item-number dw-mod">{{number}}</div> 1966 {{/if}} 1967 @if (!relatedOnlyPreview) 1968 { 1969 if (relatedPointShopOnly) 1970 { 1971 <text> 1972 {{#if havePointPrice}} 1973 <div>{{points}} @Translate("points")</div> 1974 {{else}} 1975 @Translate("Not available") 1976 {{/if}} 1977 </text> 1978 } 1979 else 1980 { 1981 <div>{{price}}</div> 1982 <div class="before-price {{onSale}} dw-mod">{{discount}}</div> 1983 } 1984 } 1985 </div> 1986 {{/Product}} 1987 </div> 1988 {{/ProductsContainer}} 1989 </div> 1990 </div> 1991 <div class="grid__col-45px grid__col--bleed-x relatedright"> 1992 <div class="grid__cell grid__cell--align-middle-right"> 1993 <button class="btn btn--condensed btn--clean {{nextdisabled}} dw-mod" onclick="HandlebarsBolt.UpdateContent('ProductList_{{groupName}}', '{{nextPage}}')" {{nextdisabled}}><i class="fas fa-chevron-right fa-2x"></i></button> 1994 </div> 1995 </div> 1996 </div> 1997 </div> 1998 {{/.}} 1999 </script> 2000 2001 <script id="Sticker" type="text/x-template"> 2002 <div class="stickers-container__tag {{className}} dw-mod">{{text}}</div> 2003 </script> 2004 2005 @* Favorites templates *@ 2006 2007 <script id="FavoriteTemplate" type="text/x-template"> 2008 <div class="favorites-list u-ta-left"> 2009 <label for="FavoriteTrigger_{{id}}" class="u-no-margin"><i class="{{favoriteIcon}} fa-1_5x"></i></label> 2010 <input type="checkbox" id="FavoriteTrigger_{{id}}" class="dropdown-trigger" /> 2011 <div class="dropdown dropdown--absolute-position"> 2012 <div class="dropdown__content dropdown__content--show-left dropdown__content--padding u-w220px dw-mod"> 2013 <ul class="list list--clean dw-mod"> 2014 {{#FavoriteLists}} 2015 {{>FavoriteListItem}} 2016 {{/FavoriteLists}} 2017 </ul> 2018 </div> 2019 <label class="dropdown-trigger-off" for="FavoriteTrigger_{{id}}"></label> 2020 </div> 2021 </div> 2022 </script> 2023 2024 <script id="FavoriteListItem" type="text/x-template"> 2025 <li> 2026 <a href="{{link}}" class="list__link u-no-underline dw-mod" onclick="{{facebookPixelAction}}"><i class="{{favoriteIcon}}"></i> {{name}}</a> 2027 </li> 2028 </script> 2029 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 2030 2031 @* 2032 NOTICE: Some blocks depend on each other, so the priority here matters. 2033 *@ 2034 2035 @* Trustpilot after stock *@ 2036 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 2037 @using System.Linq 2038 @using Dynamicweb.Rapido.Blocks 2039 2040 @{ 2041 2042 2043 2044 Block Trustpilot = new Block() 2045 { 2046 Id = "Trustpilot", 2047 SortId = 91, 2048 Template = RenderTrustpilot() 2049 }; 2050 2051 mainInfoPage.Add("MainInformation", Trustpilot); 2052 2053 } 2054 2055 @helper RenderTrustpilot() 2056 { 2057 if (GetString("Ecom:Product.LanguageID") == "LANG2") 2058 { 2059 <!-- TrustBox script --> 2060 <script type="text/javascript" src="//widget.trustpilot.com/bootstrap/v5/tp.widget.bootstrap.min.js" async></script> 2061 <!-- End TrustBox script --> 2062 <div class="trustpilotcontainer product" style="margin-left: -9px;"> 2063 <!-- TrustBox widget - Drop-Down --> 2064 <div class="trustpilot-widget" data-locale="da-DK" data-template-id="5418052cfbfb950d88702476" data-businessunit-id="46a167b20000640005006fd2" data-style-height="30px" data-style-width="305px" data-theme="light" data-stars="1,2,3,4,5" data-review-languages="da"> 2065 <a href="https://dk.trustpilot.com/review/www.p-lindberg.dk" target="_blank" rel="noopener">Trustpilot</a> 2066 </div> 2067 2068 <!-- End TrustBox widget --> 2069 2070 </div> 2071 } 2072 2073 } 2074 2075 2076 2077 2078 @* Description override *@ 2079 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 2080 @using Dynamicweb.Core 2081 @using System 2082 @using System.Web 2083 @using System.Collections.Generic 2084 @using Dynamicweb.Rapido.Blocks 2085 2086 @functions { 2087 BlocksPage customProductDescriptionPage = BlocksPage.GetBlockPage("Product"); 2088 } 2089 2090 @{ 2091 string layout = !String.IsNullOrEmpty(Pageview.AreaSettings.GetItem("ProductPage").GetString("FullDescriptionLayout")) ? Pageview.AreaSettings.GetItem("ProductPage").GetList("FullDescriptionLayout").SelectedValue : "Section"; 2092 layout = layout == "Ribbon" ? "Section" : layout; 2093 2094 // tabs layout is handled by live integration 2095 if (layout != "Tabs") 2096 { 2097 if (!string.IsNullOrEmpty(GetString("Ecom:Product.LongDescription")) && layout != "hide") 2098 { 2099 Block detailsDescription = new Block() 2100 { 2101 Name = layout != "MainInformation" ? Translate("Description") : "", 2102 Id = "FullDescription", 2103 SortId = 10, 2104 Template = CustomRenderProductDescription(layout), 2105 Design = new Design 2106 { 2107 Size = "12", 2108 RenderType = RenderType.Column, 2109 HidePadding = true 2110 } 2111 }; 2112 customProductDescriptionPage.ReplaceBlock(detailsDescription); 2113 } 2114 } 2115 } 2116 2117 @helper CustomRenderProductDescription(string layout) 2118 { 2119 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("FullDescriptionLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 2120 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("FullDescriptionLayout").SelectedValue == "Ribbon" ? "u-padding--lg" : ""; 2121 2122 <div class="product__section @ribbonClasses dw-mod"> 2123 <div class="product__description center-container @ribbonSubClasses dw-mod"> 2124 @if (layout == "Section") 2125 { 2126 <h2>@Translate("Description")</h2> 2127 } 2128 2129 @GetString("Ecom:Product.LongDescription") 2130 </div> 2131 </div> 2132 } 2133 2134 @* Chemical section after description *@ 2135 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 2136 @using Dynamicweb.Core 2137 @using System 2138 @using System.Linq 2139 @using System.Web 2140 @using System.Collections.Generic 2141 @using Dynamicweb.Ecommerce.International 2142 @using Dynamicweb.Rapido.Blocks 2143 2144 @using PLindberg.Dynamicweb; 2145 @functions { 2146 BlocksPage productPage = BlocksPage.GetBlockPage("Product"); 2147 } 2148 2149 @{ 2150 var chemicalValues = new string[] { 2151 GetString("Ecom:Product:Field.PerfionChemicalHSentences"), 2152 GetString("Ecom:Product:Field.PerfionChemicalEUHSentences"), 2153 GetString("Ecom:Product:Field.PerfionChemicalPSentences"), 2154 GetString("Ecom:Product:Field.PerfionChemicalGHSSentences"), 2155 GetString("Ecom:Product:Field.PerfionChemicalSignalWords"), 2156 GetString("Ecom:Product:Field.PerfionChemicalPictogramImages") 2157 }; 2158 2159 // if there is some chemical information 2160 if (chemicalValues.Any(v => !string.IsNullOrEmpty(v))) 2161 { 2162 string desctiptionLayout = !String.IsNullOrEmpty(Pageview.AreaSettings.GetItem("ProductPage").GetString("FullDescriptionLayout")) ? Pageview.AreaSettings.GetItem("ProductPage").GetList("FullDescriptionLayout").SelectedValue : "Section"; 2163 Block chemicalSectionBlock = new Block() 2164 { 2165 Name = "ChemicalSection", 2166 Id = "ChemicalSection", 2167 SortId = 10, 2168 Template = RenderChemicalLayout(), 2169 SkipRenderBlocksList = false, 2170 Design = new Design 2171 { 2172 Size = "12", 2173 RenderType = RenderType.Column, 2174 HidePadding = false 2175 } 2176 }; 2177 2178 productPage.Add(desctiptionLayout, chemicalSectionBlock); 2179 } 2180 } 2181 2182 @helper RenderChemicalLayout() 2183 { 2184 <div class="chemical__section dw-mod"> 2185 <div class="grid"> 2186 <div class="grid__col-8"> 2187 <h2>@Translate("ChemicalEnvironmentAndSafety")</h2> 2188 <hr class="splitter" /> 2189 @RenderChemicalEnvironment() 2190 </div> 2191 <div class="grid__col-4"> 2192 @RenderDangerImages() 2193 </div> 2194 <div class="grid__col-12"> 2195 @RenderChemicalUN() 2196 </div> 2197 @* Chemical data sheets *@ 2198 {{#if hasDatasheets}} 2199 {{#showFiles files "@currentLanguageId"}} 2200 <div class="grid__col-12"> 2201 <h2>@Translate("Datasheets", "Produktblade")</h2> 2202 <hr class="splitter" /> 2203 </div> 2204 {{/showFiles}} 2205 {{/if}} 2206 {{#files}} 2207 {{#showFile caption "@currentLanguageId"}} 2208 {{#if isDatasheet}} 2209 <div class="grid__col-12"> 2210 <div class="grid__col-12 chemical-download"> 2211 <a href="{{url}}" target="_blank"><i class="fa fa-download"></i>&nbsp;&nbsp;{{caption}}</a> 2212 </div> 2213 </div> 2214 {{/if}} 2215 {{/showFile}} 2216 {{/files}} 2217 </div> 2218 </div> 2219 } 2220 2221 @helper TextList(IEnumerable<string> texts, string @class = "") 2222 { 2223 <ul class="@(@class)"> 2224 @foreach (string text in texts) 2225 { 2226 <li>@text</li> 2227 } 2228 </ul> 2229 } 2230 2231 @helper RenderChemicalEnvironment() 2232 { 2233 var dangerSentences = GetString("Ecom:Product:Field.PerfionChemicalHSentences").SplitOn().Concat(GetString("Ecom:Product:Field.PerfionChemicalEUHSentences").SplitOn()); 2234 var securitySentences = GetString("Ecom:Product:Field.PerfionChemicalPSentences").SplitOn().Concat(GetString("Ecom:Product:Field.PerfionChemicalGHSSentences").SplitOn()); 2235 2236 <div class="chemical__environment center-container dw-mod"> 2237 @if (!string.IsNullOrEmpty(GetString("Ecom:Product:Field.PerfionChemicalSignalWords"))) 2238 { 2239 @Translate("ContainsSignalWords")<text>:</text> 2240 @TextList(GetString("Ecom:Product:Field.PerfionChemicalSignalWords").SplitOn(), "chemical__list") 2241 } 2242 2243 @if (dangerSentences.Any(v => !string.IsNullOrEmpty(v))) 2244 { 2245 @Translate("ContainsDangerSentences")<text>:</text> 2246 @TextList(dangerSentences, "chemical__list") 2247 } 2248 2249 @if (securitySentences.Any(v => !string.IsNullOrEmpty(v))) 2250 { 2251 @Translate("ContainsSafetySentences")<text>:</text> 2252 @TextList(securitySentences, "chemical__list") 2253 } 2254 </div> 2255 } 2256 2257 @helper RenderDangerImages() 2258 { 2259 var imageGuids = GetString("Ecom:Product:Field.PerfionChemicalPictogramImages").SplitOn().Select(g => 2260 { 2261 Guid guid; 2262 return Guid.TryParse(g, out guid) ? guid : Guid.Empty; 2263 }); 2264 2265 <div class="chemical__images grid__cell dw-mod"> 2266 <div class="grid"> 2267 @foreach (var guid in imageGuids) 2268 { 2269 <div class="grid-col-2"> 2270 <div class="chemical__image-container grid__cell"> 2271 <img class="chemical__image b-lazy" src="/Files/Images/placeholder.gif" @PerfionImageSrc(guid, 75, 75, "data-src=") /> 2272 </div> 2273 </div> 2274 } 2275 </div> 2276 </div> 2277 } 2278 2279 @helper RenderChemicalUN() 2280 { 2281 var sentences = GetString("Ecom:Product:Field.PerfionChemicalUN").SplitOn(); 2282 2283 <div class="chemical__un"> 2284 @foreach (var sentence in sentences) 2285 { 2286 <p class="chemical__un-sentence">@sentence</p> 2287 } 2288 </div> 2289 } 2290 2291 @* Tabs after chemical section *@ 2292 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 2293 @using Dynamicweb.Core 2294 @using System 2295 @using System.Linq 2296 @using System.Web 2297 @using System.Collections.Generic 2298 @using Dynamicweb.Rapido.Blocks 2299 2300 @functions { 2301 Block tabTriggerBlock = new Block() 2302 { 2303 Name = "Tab Triggers", 2304 Id = "TabTriggers", 2305 SortId = 10, 2306 SkipRenderBlocksList = true 2307 }; 2308 Block tabLabelBlock = new Block() 2309 { 2310 Name = "Tab Labels", 2311 Id = "TabLabels", 2312 SortId = 20, 2313 SkipRenderBlocksList = true 2314 }; 2315 Block tabBlock = new Block() 2316 { 2317 Name = "Tab Block", 2318 Id = "TabBlock", 2319 SortId = 30, 2320 SkipRenderBlocksList = true 2321 }; 2322 } 2323 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 2324 @using Dynamicweb.Core 2325 @using System 2326 @using System.Web 2327 @using System.Collections.Generic 2328 @using Dynamicweb.Ecommerce.International 2329 @using Dynamicweb.Rapido.Blocks 2330 2331 @functions { 2332 BlocksPage specProductPage = BlocksPage.GetBlockPage("Product"); 2333 string currentLanguageId = Language.GetCultureInfo().Name.Substring(3); 2334 } 2335 2336 @{ 2337 var descriptionLayout = !String.IsNullOrEmpty(Pageview.AreaSettings.GetItem("ProductPage").GetString("FullDescriptionLayout")) ? Pageview.AreaSettings.GetItem("ProductPage").GetList("FullDescriptionLayout").SelectedValue : "Section"; 2338 bool shouldRenderDescription = descriptionLayout == "Tabs"; 2339 2340 Block chemicalSection = specProductPage.GetBlockById("ChemicalSection"); 2341 Block specTriggersBlock = new Block() 2342 { 2343 Name = "SpecTriggerBlock", 2344 Id = "SpecTriggerBlock", 2345 SortId = 10, 2346 Template = RenderSpecTabTriggers(shouldRenderDescription) 2347 }; 2348 Block specLabelsBlock = new Block() 2349 { 2350 Name = "SpecTriggerBlock", 2351 Id = "SpecTriggerBlock", 2352 SortId = 10, 2353 Template = RenderSpecTabLabels(shouldRenderDescription) 2354 }; 2355 Block specTabsBlock = new Block() 2356 { 2357 Name = "SpecTabsBlock", 2358 Id = "SpecTabsBlock", 2359 SortId = 10, 2360 Template = RenderSpecTabBlocks(shouldRenderDescription) 2361 }; 2362 tabTriggerBlock.BlocksList.Add(specTriggersBlock); 2363 tabLabelBlock.BlocksList.Add(specLabelsBlock); 2364 tabBlock.BlocksList.Add(specTabsBlock); 2365 } 2366 2367 @helper RenderSpecTabTriggers(bool shouldRenderDescription) 2368 { 2369 if (shouldRenderDescription) 2370 { 2371 <input type="radio" class="tabs__trigger" name="productTabs" id="FullDescription" onchange="bLazy.revalidate()" checked> 2372 } 2373 <text> 2374 {{#if technicalSpecificationGroups}} 2375 <input type="radio" class="tabs__trigger" name="productTabs" id="TechnicalSpecifications" onchange="bLazy.revalidate()" @(!shouldRenderDescription ? "checked" : string.Empty)> 2376 {{/if}} 2377 {{#if videos}} 2378 <input type="radio" class="tabs__trigger" name="productTabs" id="Videos" onchange="bLazy.revalidate()"> 2379 {{/if}} 2380 {{#showFiles files "@currentLanguageId"}} 2381 {{#unless onlyDatasheets}} 2382 <input type="radio" class="tabs__trigger" name="productTabs" id="Files" onchange="bLazy.revalidate()"> 2383 {{/unless}} 2384 {{/showFiles}} 2385 </text> 2386 } 2387 2388 @helper RenderSpecTabLabels(bool shouldRenderDescription) 2389 { 2390 if (shouldRenderDescription) 2391 { 2392 <label for="FullDescription" class="tabs__label dw-mod">@Translate("Description", "Description")</label> 2393 } 2394 <text> 2395 {{#if technicalSpecificationGroups}} 2396 <label for="TechnicalSpecifications" class="tabs__label dw-mod">@Translate("TechnicalSpecifications", "TechnicalSpecifications")</label> 2397 {{/if}} 2398 {{#if videos}} 2399 <label for="Videos" class="tabs__label dw-mod">@Translate("Videos", "Videos")</label> 2400 {{/if}} 2401 {{#showFiles files "@currentLanguageId"}} 2402 {{#unless onlyDatasheets}} 2403 <label for="Files" class="tabs__label dw-mod">@Translate("Files", "Files")</label> 2404 {{/unless}} 2405 {{/showFiles}} 2406 </text> 2407 } 2408 2409 @helper RenderSpecTabBlocks(bool shouldRenderDescription) 2410 { 2411 if (shouldRenderDescription) 2412 { 2413 <text>{{>DescriptionContainer}}</text> 2414 } 2415 <text> 2416 {{#if technicalSpecificationGroups}} 2417 {{>TechnicalSpecificationGroupsContainer}} 2418 {{/if}} 2419 {{#if videos}} 2420 {{>VideosContainer}} 2421 {{/if}} 2422 {{#showFiles files "@currentLanguageId"}} 2423 {{#unless onlyDatasheets}} 2424 {{>FilesContainer}} 2425 {{/unless}} 2426 {{/showFiles}} 2427 </text> 2428 } 2429 2430 <script id="DescriptionContainer" type="text/x-template"> 2431 <div class="tabs__block dw-mod" id="Block__FullDescription"> 2432 <section class="product__section paragraph-container paragraph-container--full-width product__section--bordered dw-mod"> 2433 <div class="center-container u-padding--lg dw-mod"> 2434 <div class="product__section dw-mod"> 2435 <div class="product__description center-container dw-mod"> 2436 @GetString("Ecom:Product.LongDescription") 2437 2438 @if (chemicalSection != null) 2439 { 2440 @RenderBlock(new Block() 2441 { 2442 Design = new Design() 2443 { 2444 RenderType = RenderType.Row, 2445 Size = "10" 2446 }, 2447 BlocksList = new List<Block> { 2448 chemicalSection 2449 } 2450 }); 2451 } 2452 </div> 2453 </div> 2454 </div> 2455 </section> 2456 </div> 2457 </script> 2458 2459 <script id="TechnicalSpecificationGroupsContainer" type="text/x-template"> 2460 <div class="tabs__block dw-mod" id="Block__TechnicalSpecifications"> 2461 <section class="product__section paragraph-container paragraph-container--full-width product__section--bordered dw-mod"> 2462 <div class="center-container u-padding--lg dw-mod"> 2463 <div class="product__section dw-mod"> 2464 <div class="product__description center-container dw-mod"> 2465 <table class="table--no-top-border"> 2466 <tbody> 2467 {{#technicalSpecificationGroups}} 2468 <tr> 2469 <td class="u-bold"> 2470 {{#if caption}} 2471 {{caption}} 2472 {{else}} 2473 {{name}} 2474 {{/if}} 2475 </td> 2476 <td></td> 2477 </tr> 2478 {{#technicalSpecifications}} 2479 <tr> 2480 <td> 2481 {{#if caption}} 2482 {{caption}} 2483 {{else}} 2484 {{name}} 2485 {{/if}} 2486 </td> 2487 <td> 2488 <span class="TechnicalSpecifications_value">{{text}}</span>&nbsp;<span class="TechnicalSpecifications_unit">{{unit}}</span> 2489 </td> 2490 </tr> 2491 {{/technicalSpecifications}} 2492 {{/technicalSpecificationGroups}} 2493 </tbody> 2494 </table> 2495 </div> 2496 </div> 2497 </div> 2498 </section> 2499 </div> 2500 </script> 2501 2502 <script id="VideosContainer" type="text/x-template"> 2503 <div class="tabs__block dw-mod" id="Block__Videos"> 2504 <section class="product__section paragraph-container paragraph-container--full-width product__section--bordered dw-mod"> 2505 <div class="center-container u-padding--lg dw-mod"> 2506 <div class="product__section dw-mod"> 2507 <div class="center-container dw-mod"> 2508 <div class="grid grid--external-bleed-x u-margin-bottom--lg"> 2509 {{#videos}} 2510 <div class="grid__col-md-12 grid__col-lg-12"> 2511 <div class="video-wrapper"> 2512 <iframe id="youtube-video" src="{{link}}"></iframe> 2513 </div> 2514 </div> 2515 {{/videos}} 2516 </div> 2517 </div> 2518 </div> 2519 </div> 2520 </section> 2521 </div> 2522 </script> 2523 2524 <script id="FilesContainer" type="text/x-template"> 2525 <div class="tabs__block dw-mod" id="Block__Files"> 2526 <section class="product__section paragraph-container paragraph-container--full-width product__section--bordered dw-mod"> 2527 <div class="center-container u-padding--lg dw-mod"> 2528 <div class="product__section dw-mod"> 2529 <div class="product__description center-container dw-mod"> 2530 <table class="table--no-top-border"> 2531 <tbody> 2532 {{#files}} 2533 {{#showFile caption "@currentLanguageId"}} 2534 {{#unless isDatasheet}} 2535 <tr> 2536 <td colspan="2"> 2537 <a href="{{url}}" target="_blank"><i class="fa fa-download"></i>&nbsp;&nbsp;{{caption}}</a> 2538 </td> 2539 </tr> 2540 {{/unless}} 2541 {{/showFile}} 2542 {{/files}} 2543 </tbody> 2544 </table> 2545 </div> 2546 </div> 2547 </div> 2548 </section> 2549 </div> 2550 </script> 2551 2552 <script id="TabsPreRenderContainer" type="text/x-template"> 2553 <div class="u-h600px u-full-width"> 2554 <div class="grid"> 2555 <div class="grid__col-12"> 2556 <div class="pre-render-element pre-render-element--md"></div> 2557 </div> 2558 </div> 2559 </div> 2560 </script> 2561 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 2562 @using Dynamicweb.Core 2563 @using System 2564 @using System.Linq 2565 @using System.Web 2566 @using System.Collections.Generic 2567 @using Dynamicweb.Rapido.Blocks 2568 2569 @using PLindberg.Dynamicweb.Common; 2570 2571 @using System.Globalization; 2572 2573 @using Dynamicweb.Rendering; 2574 @using Dynamicweb.Rapido.Blocks; 2575 2576 @helper RenderModalDialog(string id, Block header, Block body) 2577 { 2578 <input type="checkbox" id="@id-trigger" class="modal-trigger" /> 2579 <div class="modal-container"> 2580 <label for="@id-trigger" id="notification-email-modaloverlay" class="modal-overlay"></label> 2581 <div class="modal modal--sm" id="@id"> 2582 <div class="modal__header"> 2583 @RenderBlock(header) 2584 </div> 2585 <div class="modal__body"> 2586 @RenderBlock(body) 2587 </div> 2588 </div> 2589 </div> 2590 } 2591 2592 @{ 2593 var sparePartsGroupId = new WebConfigSettings().GetValue("Perfion/Global","SparePartsRelatedGroupId"); 2594 2595 sparePartsGroupId = !string.IsNullOrEmpty(sparePartsGroupId) ? sparePartsGroupId : ""; 2596 var sparePartsRelatedGroup = GetLoop("ProductRelatedGroups").FirstOrDefault(l => l.GetString("Ecom:Product:RelatedGroup.GroupID") == sparePartsGroupId && l.GetLoop("Products").Count() > 0); 2597 if (sparePartsRelatedGroup != null) 2598 { 2599 Block modalHeader = new Block() 2600 { 2601 Id = "SPStockModalHeader", 2602 Name = "Modal Header", 2603 Template = RenderModalHeader() 2604 }; 2605 Block modalBody = new Block() 2606 { 2607 Id = "SPStockModalBody", 2608 Name = "Modal Body", 2609 Template = RenderModalBody() 2610 }; 2611 Block sparePartTriggersBlock = new Block() 2612 { 2613 Name = "SPTriggerBlock", 2614 Id = "SPTriggerBlock", 2615 SortId = 20, 2616 Template = RenderTabTriggers(), 2617 SkipRenderBlocksList = true 2618 }; 2619 Block sparePartLabelsBlock = new Block() 2620 { 2621 Name = "SPTriggerBlock", 2622 Id = "SPTriggerBlock", 2623 SortId = 20, 2624 Template = RenderTabLabels(), 2625 SkipRenderBlocksList = true 2626 }; 2627 Block sparePartTabsBlock = new Block() 2628 { 2629 Name = "SPTabsBlock", 2630 Id = "SPTabsBlock", 2631 SortId = 20, 2632 Template = RenderTabBlocks(sparePartsRelatedGroup, modalHeader, modalBody), 2633 SkipRenderBlocksList = true 2634 }; 2635 2636 tabTriggerBlock.BlocksList.Add(sparePartTriggersBlock); 2637 tabLabelBlock.BlocksList.Add(sparePartLabelsBlock); 2638 tabBlock.BlocksList.Add(sparePartTabsBlock); 2639 } 2640 } 2641 2642 @helper RenderTabTriggers() 2643 { 2644 <input type="radio" class="tabs__trigger" name="productTabs" id="SpareParts" onchange="bLazy.revalidate()"> 2645 } 2646 2647 @helper RenderTabLabels() 2648 { 2649 <label for="SpareParts" class="tabs__label dw-mod">@Translate("SpareParts")</label> 2650 } 2651 2652 @helper RenderTabBlocks(LoopItem relatedGroup, Block modalHeader, Block modalBody) 2653 { 2654 string sparePartsGroupName = relatedGroup.GetString("Ecom:Product:RelatedGroup.Name"); 2655 string sparePartsGroupId = ToPascalCase(sparePartsGroupName); 2656 string baseFeedPageUrl = "/Default.aspx?ID=" + GetPageIdByNavigationTag("SpareParts") + "&ProdID=" + GetString("Ecom:Product.ID") + "&feed=true"; 2657 string sparePartsFeed = baseFeedPageUrl + "&" + sparePartsGroupId + "=" + GetString("Ecom:Product.ID") + "&GroupName=" + sparePartsGroupId; 2658 2659 <div class="tabs__block dw-mod" id="Block__SpareParts"> 2660 <div class="pp__spare-parts dw-mod"> 2661 <div class="grid"> 2662 <div class="grid__col-lg-12"> 2663 <div id="SparePartsContainer" data-template="SparePartsTemplate" data-pre-render-template="SparePartsPreRenderContainer" data-json-feed="@sparePartsFeed" data-preloader="minimal"> 2664 </div> 2665 @RenderModalDialog("stock-notify", modalHeader, modalBody) 2666 </div> 2667 </div> 2668 </div> 2669 </div> 2670 } 2671 2672 @helper RenderModalHeader() 2673 { 2674 <h2>@Translate("NotificationModalTitle", "Lagerstand email")</h2> 2675 } 2676 2677 @helper RenderModalBody() 2678 { 2679 <p>@Translate("NotificationModalText", "Modtag en email når varren er på lager igen.")</p> 2680 <div class="notification-email-formgroup"> 2681 @*<label for="notification-email">Email: </label>*@ 2682 <input type="text" name="notification-email" id="stock-notify-email-input" value="@GetString("UserManagement:User.Email")" placeholder="@Translate("Emailaddress")" /> 2683 </div> 2684 <div class="notification-email-formgroup"> 2685 <button type="button" id="stock-notify-btn" class="btn btn--primary btn--condensed u-no-margin dw-mod notification-email-button" name="" value=""> 2686 <i class="notification-email-button-icon"></i><span class="u-hidden-xs u-hidden-xxs">&nbsp;@Translate("NotificationButton", "Send")</span> 2687 </button> 2688 </div> 2689 } 2690 2691 2692 <script id="SparePartsPreRenderContainer" type="text/x-template"> 2693 <div class="u-h600px u-full-width"> 2694 <div class="grid"> 2695 <div class="grid__col-12"> 2696 <div class="pre-render-element pre-render-element--md"></div> 2697 </div> 2698 </div> 2699 </div> 2700 </script> 2701 2702 <script id="SparePartsTemplate" type="text/x-template"> 2703 {{#.}} 2704 <table class="spare-parts-form table table-bordered"> 2705 <thead> 2706 <tr> 2707 <td>@Translate("Productnumber", "Varenr.")</td> 2708 <td>@Translate("ProductName", "Vare")</td> 2709 <td>@Translate("Stock state", "Lagerstatus")</td> 2710 <td>@Translate("Price pr unit", "Pris pr. stk")</td> 2711 <td>@Translate("Quantity", "Antal")</td> 2712 <td></td> 2713 </tr> 2714 </thead> 2715 <tbody> 2716 {{#ProductsContainer}} 2717 {{#Product}} 2718 <tr> 2719 <td>{{number}}</td> 2720 <td>{{name}}</td> 2721 <td class="u-ta-left"> 2722 {{#ifCond stockState '===' 'stock-icon--in'}} 2723 <div class="stock-icon stock-icon--in"></div> 2724 {{/ifCond}} 2725 {{#ifCond stockState '===' 'stock-icon--few'}} 2726 <div class="stock-icon stock-icon--few"></div> 2727 {{/ifCond}} 2728 {{#ifCond stockState '===' 'stock-icon--not'}} 2729 <div class="stock-icon stock-icon--not"></div> 2730 <a href="#" class="pp__sparepart-notify-click" onclick="document.getElementById('stock-notify-trigger').click(); return false;" 2731 data-productid="{{productId}}" data-productnumber="{{number}}" data-productvariant="{{variantid}}" data-productlanguage="{{languageId}}" 2732 data-page="@GetPageIdByNavigationTag("AddStockNotification")"><i class="far fa-envelope"></i>&nbsp;@Translate("Modtag en email")</a> 2733 2734 <p class="{{hideDelivery}}"> 2735 <span>@Translate("Shipping")</span>&nbsp;<span>{{stockDeliveryText}}</span>&nbsp;<span>{{stockDeliveryUnit}}</span> 2736 </p> 2737 {{/ifCond}} 2738 </td> 2739 <td> 2740 <span class="sparepartprice">{{price}} @Translate("InklMoms", "inkl. moms")</span> 2741 <div class="price price--product-page dw-mod withoutvat">{{priceWithoutVat}} @Translate("EksMoms", "ex. moms")</div> 2742 </td> 2743 <td> 2744 <input type="number" min="1" step="1" class="quantity" value="1" /> 2745 </td> 2746 <td class="spareparts-addtobasket"> 2747 <button class="btn btn--primary btn--condensed u-pull--right addtobasket" type="button" data-productid="{{productId}}" data-variantid="{{variantid}}" data-productlink="{{link}}" data-imageguid="{{imageGuid}}"> 2748 <i class="fal fa-shopping-cart"></i> 2749 </button> 2750 </td> 2751 </tr> 2752 {{/Product}} 2753 {{/ProductsContainer}} 2754 </tbody> 2755 </table> 2756 {{/.}} 2757 </script> 2758 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 2759 @using Dynamicweb.Core 2760 @using System 2761 @using System.Linq 2762 @using System.Web 2763 @using System.Collections.Generic 2764 @using Dynamicweb.Rapido.Blocks 2765 2766 @functions { 2767 BlocksPage tabsProductPage = BlocksPage.GetBlockPage("Product"); 2768 } 2769 2770 @{ 2771 Block tabsLayoutBlock = new Block() 2772 { 2773 Name = "Tabs Layout", 2774 Id = "TabsLayout", 2775 SortId = 10, 2776 SkipRenderBlocksList = false, 2777 Template = RenderWrapper(tabTriggerBlock, tabLabelBlock, tabBlock), 2778 Design = new Design 2779 { 2780 Size = "12", 2781 RenderType = RenderType.Column, 2782 HidePadding = true 2783 } 2784 }; 2785 2786 tabsProductPage.Add("Section", tabsLayoutBlock); 2787 } 2788 2789 @helper RenderWrapper(Block tabTriggerBlock, Block tabLabelBlock, Block tabBlock) 2790 { 2791 @* Technical Spec *@ 2792 string feed = "/Default.aspx?ID=" + GetPageIdByNavigationTag("PerfionLiveFeed") + "&PerfionProductID=" + GetString("Ecom:Product:Field.PerfionProductId") + "&LanguageID=" + GetString("Ecom:Product.LanguageID") + "&PerfionMainImage=" + (!string.IsNullOrEmpty(GetString("Ecom:Product:Field.PerfionMainImage")) ? GetString("Ecom:Product:Field.PerfionMainImage") : "0") + "&GroupID=" + GetString("Ecom:ProductList:Page.GroupID"); 2793 2794 <div class="grid__col-12 product__info u-no-padding dw-mod js-handlebars-root" id="Tabs" data-template="SpecsTemplate" data-pre-render-template="SpecsPreRenderContainer" data-json-feed="@feed" data-preloader="minimal"> 2795 </div> 2796 2797 <script id="SpecsTemplate" type="text/x-template"> 2798 @RenderTabLayoutSection(tabTriggerBlock, tabLabelBlock, tabBlock) 2799 </script> 2800 } 2801 2802 @helper RenderTabLayoutSection(Block tabTriggerBlock, Block tabLabelBlock, Block tabBlock) 2803 { 2804 <div class="pp__tab-triggers"> 2805 @RenderBlockList(tabTriggerBlock.BlocksList) 2806 2807 <div class="tabs__list dw-mod"> 2808 @RenderBlockList(tabLabelBlock.BlocksList) 2809 </div> 2810 2811 <div class="tabs__blocks dw-mod"> 2812 @RenderBlockList(tabBlock.BlocksList) 2813 </div> 2814 </div> 2815 } 2816 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 2817 @using System.Globalization 2818 @using System.Linq 2819 @using Dynamicweb.Rapido.Blocks 2820 2821 @{ 2822 BlocksPage mainInfo = BlocksPage.GetBlockPage("Product"); 2823 2824 Block modalStockHeader = new Block() 2825 { 2826 Id = "StockNotifyHeader", 2827 Template = RenderStockNotifyHeader() 2828 }; 2829 Block modalStockBody = new Block() 2830 { 2831 Id = "StockNotifyBody", 2832 Template = RenderStockNotifyBody() 2833 }; 2834 Block stockBlock = new Block() 2835 { 2836 Id = "StockAndShippingNotifyMail", 2837 SortId = 90, 2838 Template = RenderStock(modalStockHeader, modalStockBody) 2839 }; 2840 Block customStockAndShipping = new Block() 2841 { 2842 Id = "StockAndShipping", 2843 SortId = 90, 2844 Template = RenderVariantStockAndShipping(stockBlock) 2845 }; 2846 2847 // overskriv StockAndShipping fra MainInformation 2848 mainInfo.ReplaceBlock(customStockAndShipping); 2849 //mainInfo.Add("MainInformation", stockBlock); 2850 } 2851 2852 @helper RenderStock(Block modalHeader, Block modalBody) 2853 { 2854 string dropshipping = GetString("Ecom:Product:Field.DropShipping"); // custom 2855 2856 var nextAvailableDate = PLindberg.Website.CustomModules.Helpers.GetNextAvailableStockDate(this); 2857 if (GetInteger("Ecom:Product.Stock") < 1 && nextAvailableDate.Length > 0) 2858 { 2859 <div class="appear-stockinfo"> 2860 <p> 2861 <i class="fas fa-reply"></i> 2862 @Translate("AppearStock", "Forventes på lager: ") 2863 @nextAvailableDate 2864 </p> 2865 </div> 2866 } 2867 2868 if (GetString("Ecom:Product:Field.PerfionItemStatus").ToUpper() == "O" && GetInteger("Ecom:Product.Stock") == 0) 2869 { 2870 @* onclick="notificationEmail('@GetString("Ecom:Product.Number")', @(string.IsNullOrEmpty(GetString("UserManagement:User.Email")) ? "null" : "'" + GetString("UserManagement:User.Email") + "'" )); return false;" *@ 2871 <div><a href="#" class="stock-notification-email-link" onclick="document.getElementById('notification-email-modal-trigger').click(); return false;"><i class="far fa-envelope"></i>@Translate("Modtag en email")</a></div> 2872 2873 @RenderModalDialog("notification-email-modal", modalHeader, modalBody) 2874 } 2875 2876 if (GetInteger("Ecom:Product.Stock") > 0 && dropshipping != "J") 2877 { 2878 <p class="delivery green"><i class="fa fa-truck" aria-hidden="true"></i>@Translate("deliverytext", "Levering 1-3 dage")</p> 2879 } 2880 2881 2882 } 2883 2884 @helper RenderStockNotifyHeader() 2885 { 2886 <h2>@Translate("NotificationModalTitle", "Lagerstand email")</h2> 2887 } 2888 2889 @helper RenderStockNotifyBody() 2890 { 2891 <p>@Translate("NotificationModalText", "Modtag en email når varren er på lager igen.")</p> 2892 <div class="notification-email-formgroup"> 2893 <input type="text" name="notification-email" id="notification-email-input" value="@GetString("UserManagement:User.Email")" placeholder='@Translate("Emailaddress")' /> 2894 </div> 2895 <div class="notification-email-formgroup"> 2896 <button type="button" id="" class="btn btn--primary btn--condensed u-no-margin dw-mod notification-email-button" name="" value="" 2897 onclick="signupStockEmailNotification('notification-email-modal-trigger', '@GetPageIdByNavigationTag("AddStockNotification")', '@GetString("Ecom:Product.Number")', '@GetString("Ecom:Product.ID")', '@GetString("Ecom:Product.VariantID")', '@GetString("Ecom:Product.LanguageID")', document.getElementById('notification-email-input').value);"> 2898 <i class="notification-email-button-icon"></i><span class="u-hidden-xs u-hidden-xxs"> @Translate("NotificationButton")</span> 2899 </button> 2900 </div> 2901 } 2902 2903 @helper RenderVariantStockAndShipping(Block StockAndShippingNotifyMail) 2904 { 2905 bool hideStockState = Pageview.AreaSettings.GetItem("ProductPage").GetString("HideStockState") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideStockState") : false; 2906 bool hideDelivery = Pageview.AreaSettings.GetItem("ProductPage").GetString("HideShipping") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideShipping") : false; 2907 bool onlyPreview = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("OnlyPreviewForAnonymous") && Pageview.User == null; 2908 2909 var variantLoop = GetLoop("VariantCombinations"); 2910 var hasSelectedVariant = !string.IsNullOrEmpty(GetString("Ecom:Product.SelectedVariantComboID")); 2911 var hasVariantCombinations = variantLoop.Count > 0; 2912 var highestStockCount = hasVariantCombinations ? variantLoop[0].GetInteger("Ecom:Product.Stock") : 0; 2913 2914 string stockIcon = "stock-icon--not"; 2915 string stockText = GetString("Ecom:Product:Stock.Text"); 2916 string dropshipping = GetString("Ecom:Product:Field.DropShipping"); // custom 2917 string dropshippingfrase = GetString("Ecom:Product:Field.DropShippingFrase"); // custom 2918 2919 bool PerfionProductFreightAddon = GetBoolean("Ecom:Product:Field.PerfionProductFreightAddon"); //Custom 2920 2921 2922 2923 if (!hasSelectedVariant && hasVariantCombinations) 2924 { 2925 foreach (var variantItem in variantLoop) 2926 { 2927 var stockCount = variantItem.GetInteger("Ecom:Product.Stock"); 2928 2929 if (stockCount >= highestStockCount) 2930 { 2931 highestStockCount = stockCount; 2932 stockText = variantItem.GetString("Ecom:Product:Stock.Text"); 2933 } 2934 } 2935 2936 stockIcon = highestStockCount > 0 ? highestStockCount < 5 ? "stock-icon--few" : "stock-icon--in" : "stock-icon--not"; 2937 } 2938 else if (GetInteger("Ecom:Product.Stock") > 0) 2939 { 2940 stockIcon = GetInteger("Ecom:Product.Stock") < 5 ? "stock-icon--few" : "stock-icon--in"; 2941 stockText = GetString("Ecom:Product:Stock.Text"); 2942 } 2943 2944 if (!onlyPreview) 2945 { 2946 string KlarnaOnsiteLocale = Pageview.AreaSettings.GetItem("Custom").GetString("KlarnaOnsiteLocale") != null ? Pageview.AreaSettings.GetItem("Custom").GetString("KlarnaOnsiteLocale") : ""; 2947 //credit-promotion-badge 2948 string KlarnaOnsiteKey = Pageview.AreaSettings.GetItem("Custom").GetString("KlarnaOnsiteKey") != null ? Pageview.AreaSettings.GetItem("Custom").GetString("KlarnaOnsiteKey") : ""; 2949 2950 double klarnaAmount = 0; 2951 2952 //var variantLoop = GetLoop("VariantCombinations"); 2953 //var hasSelectedVariant = !string.IsNullOrEmpty(GetString("Ecom:Product.VariantID")); 2954 var lowestVariantPrice = variantLoop.GetLowestVariantPrice(); 2955 // if main product 2956 if (variantLoop.Count() > 0 && !hasSelectedVariant) 2957 { 2958 klarnaAmount = Math.Round(lowestVariantPrice.PriceWithVat * 100,0); 2959 } 2960 else 2961 { 2962 klarnaAmount = Math.Round(GetDouble("Ecom:Product.Price.PriceWithVAT.Value") * 100,0); 2963 } 2964 2965 2966 <div> 2967 <div class="product__stock-delivery dw-mod grid__col-lg-6 grid__col-md-6 grid__col-sm-12 grid__col-xs-12 u-pull--right"> 2968 @if (!string.IsNullOrEmpty(KlarnaOnsiteLocale)){ 2969 <klarna-placement data-key="@KlarnaOnsiteKey" 2970 data-locale="@KlarnaOnsiteLocale" 2971 data-purchase-amount="@klarnaAmount"></klarna-placement> 2972 } 2973 </div> 2974 <div class="product__stock-delivery dw-mod grid__col-lg-6 grid__col-md-6 grid__col-sm-12 grid__col-xs-12"> 2975 @if (!hideStockState) 2976 { 2977 if (dropshipping != "J") 2978 { 2979 <div> 2980 <span class="stock-icon @stockIcon" title="@stockText"></span>&nbsp;@stockText 2981 </div> 2982 } 2983 else 2984 { 2985 <span class="stock-icon stock-icon--in u-no-margin dw-mod"></span>@Translate("From supplier", "Fra leverandør") 2986 <p>@dropshippingfrase</p> 2987 } 2988 2989 2990 } 2991 2992 @if (!String.IsNullOrEmpty(GetString("Ecom:Product:Stock.DeliveryText")) && !hideDelivery) 2993 { 2994 <p> 2995 <span>@Translate("Shipping")</span>&nbsp;<span>@GetString("Ecom:Product:Stock.DeliveryText")</span>&nbsp;<span>@GetString("Ecom:Product:Stock.DeliveryUnit")</span> 2996 </p> 2997 } 2998 2999 @RenderBlock(StockAndShippingNotifyMail) 3000 </div> 3001 </div> 3002 } 3003 if (PerfionProductFreightAddon == true ) 3004 { 3005 <div class="freigtextra " title='@Translate("Freightaddon", "Fragttillæg")'> 3006 <i class="fas fa-truck"></i> @Translate("Freightaddon", "Fragttillæg") 3007 </div> 3008 3009 } 3010 3011 } 3012 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 3013 @using Dynamicweb.Core 3014 @using System 3015 @using System.Linq 3016 @using System.Web 3017 @using System.Collections.Generic 3018 @using Dynamicweb.Ecommerce.International 3019 @using Dynamicweb.Rapido.Blocks 3020 3021 @functions { 3022 3023 BlocksPage productFreightPage = BlocksPage.GetBlockPage("Product"); 3024 } 3025 3026 3027 @{ 3028 3029 string freightextraLayout = "Section"; 3030 3031 bool PerfionProductFreightAddon = GetBoolean("Ecom:Product:Field.PerfionProductFreightAddon"); 3032 string freightext = GetString("Ecom:Product:Field.PerfionProductFreightText"); 3033 3034 if (PerfionProductFreightAddon == true && freightext != "") 3035 { 3036 Block freightTriggersBlock = new Block() 3037 { 3038 Name = "FTriggerBlock", 3039 Id = "FTriggerBlock", 3040 SortId = 90, 3041 Template = RenderFTabTriggers(), 3042 SkipRenderBlocksList = true 3043 }; 3044 3045 Block freightLabelsBlock = new Block() 3046 { 3047 Name = "FLabelBlock", 3048 SortId = 90, 3049 Template = RenderFTabLabels(), 3050 SkipRenderBlocksList = true 3051 }; 3052 3053 Block freightTabsBlock = new Block() 3054 { 3055 Name = "FTabsBlock", 3056 Id = "FTabsBlock", 3057 SortId = 90, 3058 Template = RenderFTabBlocks(), 3059 SkipRenderBlocksList = true 3060 }; 3061 3062 tabTriggerBlock.BlocksList.Add(freightTriggersBlock); 3063 tabLabelBlock.BlocksList.Add(freightLabelsBlock); 3064 tabBlock.BlocksList.Add(freightTabsBlock); 3065 } 3066 3067 3068 3069 } 3070 @helper RenderFTabTriggers() 3071 { 3072 <input type="radio" class="tabs__trigger" name="productTabs" id="Freight" onchange="bLazy.revalidate()"> 3073 } 3074 @helper RenderFTabLabels() 3075 { 3076 <label for="Freight" class="tabs__label dw-mod">@Translate("Freightaddon", "Fragttillæg")</label> 3077 } 3078 @helper RenderFTabBlocks() 3079 { 3080 3081 <div class="tabs__block dw-mod" id="Block__Freight"> 3082 <div class="pp__freightextra dw-mod"> 3083 <div class="grid"> 3084 <div class="grid__col-lg-12"> 3085 <div class="product__section paragraph-container paragraph-container--full-width product__section--bordered dw-mod"> 3086 <div class="center-container u-padding--lg dw-mod"> 3087 @GetString("Ecom:Product:Field.PerfionProductFreightText") 3088 3089 </div> 3090 </div> 3091 </div> 3092 </div> 3093 </div> 3094 </div> 3095 3096 3097 3098 } 3099 3100 3101 3102 @* Price starting from variant *@ 3103 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 3104 @using Dynamicweb.Core 3105 @using System 3106 @using System.Linq 3107 @using System.Web 3108 @using System.Collections.Generic 3109 @using Dynamicweb.Rapido.Blocks 3110 3111 @using PLindberg.Dynamicweb; 3112 @using PLindberg.Dynamicweb.ProductPrices; 3113 @functions { 3114 BlocksPage startPricePage = BlocksPage.GetBlockPage("Product"); 3115 } 3116 3117 @{ 3118 var variantLoop = GetLoop("VariantCombinations"); 3119 var hasSelectedVariant = !string.IsNullOrEmpty(GetString("Ecom:Product.VariantID")); 3120 var lowestVariantPrice = variantLoop.GetLowestVariantPrice(); 3121 var isStartingPrice = !variantLoop.VariantsHasSamePrice(); 3122 3123 // has variants 3124 if (variantLoop.Count() > 0 && !hasSelectedVariant) 3125 { 3126 Block startPriceBlock = new Block() 3127 { 3128 Name = "Starting Price", 3129 Id = "StartPrice", 3130 SortId = 50, 3131 Template = RenderStartingPrice(isStartingPrice, lowestVariantPrice), 3132 Design = new Design 3133 { 3134 Size = "12", 3135 RenderType = RenderType.Column, 3136 HidePadding = false 3137 } 3138 }; 3139 3140 startPricePage.Add("MainInformation", startPriceBlock); 3141 } 3142 } 3143 3144 @helper RenderStartingPrice(bool isStartingPrice, Price price) 3145 { 3146 if (price != null) 3147 { 3148 if (isStartingPrice) 3149 { 3150 <div class="pp__startprice-container"> 3151 <span class="price price--product-list dw-mod pp__startprice">@string.Format("{0} {1}", Translate("StartingFrom", "Fra"), price.PriceWithVatFormatted)</span> 3152 <div class="price price--product-list price withoutvat dw-mod">@string.Format("{0} {1} {2}", Translate("StartingFrom", "Fra"), price.PriceWithoutVatFormatted, Translate("EksMoms", "ex. moms"))</div> 3153 </div> 3154 } 3155 else 3156 { 3157 <div class="pp__startprice-container"> 3158 <span class="price price--product-list dw-mod pp__startprice">@price.PriceWithVatFormatted</span> 3159 <div class="price price--product-list price withoutvat dw-mod">@string.Format("{0} {1}", price.PriceWithoutVatFormatted, Translate("EksMoms", "ex. moms"))</div> 3160 </div> 3161 } 3162 } 3163 } 3164 3165 <div class="product__info dw-mod u-margin-bottom--lg js-product"> 3166 <div class="grid grid--align-content-start"> 3167 @* The @RenderBlockList base helper is included in Components/GridBuilder.cshtml *@ 3168 @RenderBlockList(productsPage.BlocksRoot.BlocksList) 3169 @{ 3170 //var p = ProductPrices.GetBestPrice(GetLoop("Product.Prices"), GetString("Ecom:Product.ID"), GetString("Ecom:Product.VariantID")); 3171 } 3172 </div> 3173 </div>

Ähnliche Produkte

Empfohlene Produkte