Error executing template "Designs/Rapido/eCom/Product/SpProduct.cshtml"
System.IO.IOException: The process cannot access the file 'E:\Dynamicweb\Solutions\Kruuse\Files\Templates\Designs\Rapido\Translations.xml' because it is being used by another process.
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
   at Dynamicweb.Rendering.Translation.Source.WriteDocument(XmlDocument document)
   at Dynamicweb.Rendering.Translation.Source.Save()
   at Dynamicweb.Rendering.Translation.Source.UpdateTranslationSource(Source source, IEnumerable`1 newKeys, String designName, IEnumerable`1 cultures)
   at Dynamicweb.Rendering.Template.TranslateText(String text, String defaultValue, String cultureName)
   at Dynamicweb.Rendering.TemplateBase`1.Translate(String text)
   at CompiledRazorTemplates.Dynamic.RazorEngine_aafcc94cf2f24f9da9c5f4d94f0ebf8b.Execute() in E:\Dynamicweb\Solutions\Kruuse\Files\Templates\Designs\Rapido\eCom\Product\SpProduct.cshtml:line 2120
   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 @functions { 15 BlocksPage productsPage = BlocksPage.GetBlockPage("Product"); 16 17 public static string ToPascalCase(string str) 18 { 19 return CultureInfo.InvariantCulture.TextInfo 20 .ToTitleCase(str.ToLowerInvariant()) 21 .Replace("-", "") 22 .Replace("_", "") 23 .Replace(" ", ""); 24 } 25 } 26 27 @{ 28 Block productTop = new Block() 29 { 30 Id = "Top", 31 SortId = 10, 32 Design = new Design 33 { 34 RenderType = RenderType.Row 35 } 36 }; 37 productsPage.Add(productTop); 38 39 Block productMainInfo = new Block() 40 { 41 Id = "MainInformation", 42 SortId = 10, 43 Design = new Design 44 { 45 Size = "auto", 46 RenderType = RenderType.Column 47 } 48 }; 49 productsPage.Add("Top", productMainInfo); 50 51 if (!String.IsNullOrWhiteSpace(Pageview.AreaSettings.GetItem("ProductPage").GetString("ImageSectionPosition"))) 52 { 53 productMainInfo.SortId = Pageview.AreaSettings.GetItem("ProductPage").GetList("ImageSectionPosition").SelectedValue == "left-left" || Pageview.AreaSettings.GetItem("ProductPage").GetList("ImageSectionPosition").SelectedValue == "left-right" ? 2 : 1; 54 } 55 56 //Optional mini tabs block 57 Block miniTabsBlock = new Block() 58 { 59 Id = "MiniTabs", 60 SortId = 40, 61 Template = RenderProductMiniTabs(), 62 SkipRenderBlocksList = true 63 }; 64 productsPage.Add("MainInformation", miniTabsBlock); 65 //----- 66 67 Block productTabsBlock = new Block() 68 { 69 Id = "Tabs", 70 SortId = 30, 71 Template = RenderProductTabs(), 72 SkipRenderBlocksList = true 73 }; 74 productsPage.Add(productTabsBlock); 75 76 Block productDetailsBlock = new Block() 77 { 78 Id = "Section", 79 SortId = 30 80 }; 81 productsPage.Add(productDetailsBlock); 82 83 Block productSnippetsBlock = new Block() 84 { 85 Id = "Snippets", 86 SortId = 40 87 }; 88 productsPage.Add(productSnippetsBlock); 89 } 90 91 @* Include the required Grid builder (Contains the methods @RenderBlockList and @RenderBlock) *@ 92 @using System.Text.RegularExpressions 93 @using System.Collections.Generic 94 @using Dynamicweb.Rapido.Blocks 95 96 97 @*--- START: Base block renderers ---*@ 98 99 @helper RenderBlockList(List<Block> blocks) 100 { 101 blocks = blocks.OrderBy(item => item.SortId).ToList(); 102 103 foreach (Block item in blocks) 104 { 105 <!-- START: @item.Id --> 106 107 if (item.Design == null) 108 { 109 @RenderBlock(item) 110 } 111 else if (item.Design.RenderType != RenderType.Hide) 112 { 113 if (item.Design.RenderType == RenderType.Row) 114 { 115 <div class="grid grid--align-content-start"> 116 @RenderBlock(item) 117 </div> 118 } 119 120 if (item.Design.RenderType == RenderType.Column) 121 { 122 string hidePadding = item.Design.HidePadding ? "u-no-padding" : ""; 123 string size = item.Design.Size != null ? item.Design.Size : "12"; 124 size = Regex.IsMatch(size, @"\d") ? "md-" + item.Design.Size : item.Design.Size; 125 126 <div class="grid__col-lg-@item.Design.Size grid__col-md-@item.Design.Size grid__col-sm-12 grid__col-xs-12 @hidePadding" id="Block__@item.Id"> 127 @RenderBlock(item) 128 </div> 129 } 130 131 if (item.SkipRenderBlocksList == true) 132 { 133 @RenderBlock(item) 134 } 135 } 136 137 <!-- END: @item.Id --> 138 } 139 } 140 141 @helper RenderBlock(Block item) 142 { 143 if (item.Template != null) 144 { 145 @BlocksPage.RenderTemplate(item.Template) 146 } 147 148 if (item.BlocksList.Count > 0 && item.SkipRenderBlocksList == false) 149 { 150 @RenderBlockList(item.BlocksList) 151 } 152 } 153 154 @*--- END: Base block renderers ---*@ 155 156 157 @* Include the Blocks for the page *@ 158 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 159 @using Dynamicweb.Core 160 @using System 161 @using System.Web 162 @using System.Collections.Generic 163 @using System.Text.RegularExpressions; 164 @using Dynamicweb.Rapido.Blocks 165 @using Newtonsoft.Json; 166 @using System.Xml; 167 @using System.Net; 168 @using Dynamicweb.Environment; 169 @using System.Text 170 @using Newtonsoft.Json.Linq 171 172 173 174 175 @functions { 176 BlocksPage mainImagePage = BlocksPage.GetBlockPage("Product"); 177 } 178 179 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 180 181 182 @* 183 This is a temporary fallback for the DefaultImage. The image pattern MUST be set up like this: 184 185 ImageSmall = /{ProductNumber}.jpg 186 ImageMedium = /{ProductNumber}{VariantOptionLevel1}.jpg 187 ImageLarge = /{ProductNumber}{VariantComboName}.jpg 188 189 In addition to the ImageDefault setting 190 *@ 191 192 @functions { 193 public string GetProductImage(LoopItem productObject = null) 194 { 195 string theImage = ""; 196 197 if (productObject == null) 198 { 199 theImage = GetString("Ecom:Product.ImageDefault.Default.Clean"); 200 theImage = String.IsNullOrEmpty(theImage) ? GetString("Ecom:Product.ImageLarge.Clean") : theImage; 201 theImage = String.IsNullOrEmpty(theImage) ? GetString("Ecom:Product.ImageMedium.Clean") : theImage; 202 theImage = String.IsNullOrEmpty(theImage) ? GetString("Ecom:Product.ImageSmall.Clean") : theImage; 203 theImage = String.IsNullOrEmpty(theImage) ? GetString("Ecom:Product.ImageLarge.Default.Clean") : theImage; 204 } 205 else 206 { 207 theImage = productObject.GetString("Ecom:Product.ImageDefault.Default.Clean"); 208 theImage = String.IsNullOrEmpty(theImage) ? productObject.GetString("Ecom:Product.ImageLarge.Clean") : theImage; 209 theImage = String.IsNullOrEmpty(theImage) ? productObject.GetString("Ecom:Product.ImageMedium.Clean") : theImage; 210 theImage = String.IsNullOrEmpty(theImage) ? productObject.GetString("Ecom:Product.ImageSmall.Clean") : theImage; 211 theImage = String.IsNullOrEmpty(theImage) ? productObject.GetString("Ecom:Product.ImageLarge.Default.Clean") : theImage; 212 } 213 214 return theImage; 215 } 216 } 217 218 @{ 219 string imageBlockPosition = !String.IsNullOrEmpty(Pageview.AreaSettings.GetItem("ProductPage").GetString("ImageSectionPosition")) ? Pageview.AreaSettings.GetItem("ProductPage").GetList("ImageSectionPosition").SelectedValue : "right-right"; 220 string imageBlockWidth = !String.IsNullOrEmpty(Pageview.AreaSettings.GetItem("ProductPage").GetString("TopLayout")) ? Pageview.AreaSettings.GetItem("ProductPage").GetList("TopLayout").SelectedValue : "6"; 221 imageBlockWidth = imageBlockPosition == "left-left" || imageBlockPosition == "left-right" ? Converter.ToString(12 - Converter.ToInt32(imageBlockWidth)) : imageBlockWidth; 222 223 Block mainImageBlock = new Block() 224 { 225 Id = "MainImage", 226 SortId = imageBlockPosition == "left-left" || imageBlockPosition == "left-right" ? 1 : 2, 227 Template = RenderMainImageContainer(), 228 Design = new Design 229 { 230 Size = imageBlockWidth, 231 RenderType = RenderType.Column 232 } 233 }; 234 235 mainImagePage.Add("Top", mainImageBlock); 236 } 237 238 @helper RenderModal() 239 { 240 string imagePrefix = "/Admin/Public/GetImage.ashx?width=800&amp;height=800&amp;crop=5&FillCanvas=True&DoNotUpscale=true&amp;Compression=75&amp;image="; 241 242 <!-- Trigger for the gallery modal --> 243 <input type="checkbox" id="GalleryModalTrigger" class="modal-trigger" /> 244 245 if (!String.IsNullOrEmpty(GetProductImage())) 246 { 247 <!-- Gallery modal --> 248 <div class="modal-container custom-gallery-modal"> 249 <label for="GalleryModalTrigger" id="GalleryModalOverlay" class="modal-overlay"></label> 250 <div class="modal modal--full" id="GalleryModal"> 251 <div class="modal__body modal__body--full"> 252 <div class="gallery-slider"> 253 <div class="gallery-slider__image" id="FullImage"> 254 <img src="@GetProductImage()" class="modal--full__img js-gallery-image" alt="@GetString("Ecom:Product.Name")" /> 255 </div> 256 <div class="gallery-slider__image-counter" id="FullImage_counter"></div> 257 <label class="gallery-slider__close-btn" for="GalleryModalTrigger"></label> 258 <button class="gallery-slider__previous-btn" id="FullImage_prev" onclick="Gallery.prevImage('FullImage')"></button> 259 <button class="gallery-slider__next-btn" id="FullImage_next" onclick="Gallery.nextImage('FullImage')"></button> 260 </div> 261 </div> 262 </div> 263 </div> 264 } 265 } 266 267 @helper RenderMainImageContainer() 268 { 269 string imageBlockPosition = !String.IsNullOrEmpty(Pageview.AreaSettings.GetItem("ProductPage").GetString("ImageSectionPosition")) ? Pageview.AreaSettings.GetItem("ProductPage").GetList("ImageSectionPosition").SelectedValue : "right-right"; 270 @RenderModal() 271 272 <div class="grid grid--bleed"> 273 @if (imageBlockPosition == "left-left" || imageBlockPosition == "right-left") 274 { 275 @RenderThumbnails() 276 @RenderImage() 277 } 278 else 279 { 280 @RenderImage() 281 @RenderThumbnails() 282 } 283 </div> 284 } 285 286 @helper RenderImage() 287 { 288 string imagePrefix = "/Admin/Public/GetImage.ashx?width=800&amp;height=800&amp;crop=5&FillCanvas=True&DoNotUpscale=true&amp;Compression=75&amp;image="; 289 string productId = GetString("Ecom:Product.ID"); 290 bool pointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly") && Pageview.User == null; 291 292 <div class="grid__col-auto"> 293 <div class="stickers-container dw-mod"> 294 @{ 295 if (Pageview.AreaSettings.GetItem("Ecommerce").GetItem("SaleSticker").GetBoolean("Enable") && !pointShopOnly) 296 { 297 string contentType = Pageview.AreaSettings.GetItem("Ecommerce").GetItem("SaleSticker").GetString("ContentType"); 298 string text = ""; 299 var currency = Dynamicweb.Ecommerce.Services.Currencies.GetDefaultCurrency(); 300 301 switch (contentType) 302 { 303 case "Name": 304 foreach (LoopItem discount in GetLoop("ProductDiscounts")) 305 { 306 text = discount.GetString("Ecom:Product.Discount.Name"); 307 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 308 } 309 break; 310 case "Amount": 311 if (GetLoop("ProductDiscounts").Count > 0) 312 { 313 text = Dynamicweb.Ecommerce.Services.Currencies.Format(currency, GetDouble("Ecom:Product.Discount.Price.Price") - GetDouble("Ecom:Product.Price.Price")); 314 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 315 } 316 break; 317 case "Percents": 318 double percents = 0; 319 foreach (LoopItem discount in GetLoop("ProductDiscounts")) 320 { 321 percents += discount.GetDouble("Ecom:Product.Discount.PercentWithoutVAT"); 322 } 323 if (percents > 0) 324 { 325 text = Math.Round(percents, 0) + "%"; 326 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 327 } 328 break; 329 case "Amount and percents": 330 double amount = 0; 331 double percent = 0; 332 foreach (LoopItem discount in GetLoop("ProductDiscounts")) 333 { 334 if (discount.GetString("Ecom:Product.Discount.Type") == "PERCENT") 335 { 336 percent += discount.GetDouble("Ecom:Product.Discount.PercentWithoutVAT"); 337 } 338 else if (discount.GetString("Ecom:Product.Discount.Type") == "AMOUNT") 339 { 340 amount += discount.GetDouble("Ecom:Product.Discount.AmountWithVAT"); 341 } 342 } 343 if (percent > 0) 344 { 345 text = percent + "%"; 346 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 347 } 348 if (amount > 0) 349 { 350 text = Dynamicweb.Ecommerce.Services.Currencies.Format(currency, amount); 351 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 352 } 353 break; 354 default: 355 if (GetLoop("ProductDiscounts").Count > 0) 356 { 357 text = Translate("Sale!"); 358 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 359 } 360 break; 361 } 362 } 363 364 if (!pointShopOnly && Pageview.AreaSettings.GetItem("Ecommerce").GetItem("NewSticker").GetBoolean("Enable") && GetDate("Ecom:Product.Created").AddDays(Converter.ToDouble(Pageview.AreaSettings.GetItem("Ecommerce").GetItem("NewSticker").GetString("Expiration"))) > DateTime.Now) 365 { 366 <div class="stickers-container__tag stickers-container__tag--new dw-mod">@Translate("New!")</div> 367 } 368 369 if (!pointShopOnly && !String.IsNullOrEmpty(GetString("Ecom:Product:Field.CustomSticker.Value"))) 370 { 371 <div class="stickers-container__tag stickers-container__tag--custom dw-mod">@GetString("Ecom:Product:Field.CustomSticker.Value")</div> 372 } 373 374 if (Pageview.AreaSettings.GetItem("Custom").GetItem("CustomSettings").GetItem("SpDiscontinuedSticker").GetBoolean("Enable")) 375 { 376 if (GetBoolean("Ecom:Product:Field.Discontinued") && GetInteger("Ecom:Product.Stock") == 0) 377 { 378 <div class="stickers-container__tag stickers-container__tag--discontinued dw-mod">@Translate("Discontinued!")</div> 379 } 380 } 381 382 if (Pageview.AreaSettings.GetItem("Custom").GetItem("CustomSettings").GetItem("SpToBeDiscontinuedSticker").GetBoolean("Enable")) 383 { 384 if (GetBoolean("Ecom:Product:Field.Discontinued") && GetInteger("Ecom:Product.Stock") > 0) 385 { 386 <div class="stickers-container__tag stickers-container__tag--tobediscontinued dw-mod">@Translate("To be discontinued!")</div> 387 } 388 } 389 390 if (Pageview.AreaSettings.GetItem("Custom").GetItem("CustomSettings").GetItem("SpHillsCampaignSticker").GetBoolean("Enable")) 391 { 392 if (!string.IsNullOrEmpty(GetString("Ecom:Product:Field.HillsCampaignSplash")) 393 && (GetDate("Ecom:Product:Field.HillsCampaignFromDate") == DateTime.MinValue || GetDate("Ecom:Product:Field.HillsCampaignFromDate") <= DateTime.Today) 394 && (GetDate("Ecom:Product:Field.HillsCampaignToDate") == DateTime.MinValue || GetDate("Ecom:Product:Field.HillsCampaignToDate") >= DateTime.Today)) 395 { 396 <div class="stickers-container__tag stickers-container__tag--hillscampaign dw-mod"> 397 @if (!string.IsNullOrEmpty(GetString("Ecom:Product:Field.HillsCampaignLink"))) 398 { 399 <a href="@GetString("Ecom:Product:Field.HillsCampaignLink")" title="@GetString("Ecom:Product:Field.HillsCampaignSplash")"> 400 @GetString("Ecom:Product:Field.HillsCampaignSplash") 401 </a> 402 } 403 else 404 { 405 @GetString("Ecom:Product:Field.HillsCampaignSplash") 406 } 407 </div> 408 } 409 } 410 } 411 </div> 412 <label for="GalleryModalTrigger" class="product__image-container" id="Preview_@GetString("Ecom:Product.ID")"> 413 <img class="thumb-image-view product__image-container__image dw-mod b-lazy" src="/Files/Images/placeholder.gif" data-src="@imagePrefix@GetProductImage()" alt="@GetString("Ecom:Product.Name")" data-for="FullImage" data-number="0" onclick="Gallery.openImageByNum(this)" /> 414 </label> 415 </div> 416 } 417 418 @helper RenderThumbnails() 419 { 420 var cookieBot = new Smartpage.CookieManager.CookieBot(); 421 422 <div class="grid__col-2 u-hidden-xxs dw-mod"> 423 <div class="product__thumbs dw-mod"> 424 <i class="fas fa-circle-notch fa-spin preloader js-remove-after-load"></i> <!--preloader--> 425 <div class="carousel js-carousel-container carousel--hidden dw-mod" id="leftCarousel"> 426 <div class="thumb-list carousel__container dw-mod"> 427 @*Main image thumb*@ 428 429 430 @* Check if products has image and check if it returns default image - if true - print it*@ 431 @if (Converter.ToString(GetProductImage()).Contains(GetString("Ecom:Product.ImageLarge.Default.Clean"))) 432 { 433 @RenderThumbnail(GetProductImage()) 434 } 435 436 437 @{ 438 bool youtubevideoIsSet = false; 439 } 440 @foreach (LoopItem alternativeImage in GetLoop("Ecom:Product.AlternativeImages")) 441 { 442 if (!String.IsNullOrEmpty(alternativeImage.GetString("Ecom:Product.AlternativeImages.Image"))) 443 { 444 @RenderThumbnail(alternativeImage.GetString("Ecom:Product.AlternativeImages.Image")) 445 } 446 if (alternativeImage.GetInteger("Ecom:Product.AlternativeImages.LoopCounter") == 2) 447 { 448 if (cookieBot.Statistics) 449 { 450 youtubevideoIsSet = true; 451 @RenderYoutube() 452 } 453 } 454 } 455 456 @foreach (LoopItem detail in GetLoop("Details")) 457 { 458 if (!String.IsNullOrEmpty(detail.GetString("Ecom:Product:Detail.Image.Clean"))) 459 { 460 string ext = Path.GetExtension(detail.GetString("Ecom:Product:Detail.Image.Clean")).ToLower(); 461 if (ext == ".jpg" || ext == ".jpeg" || ext == ".gif" || ext == ".png") 462 { 463 @RenderThumbnail(detail.GetString("Ecom:Product:Detail.Image.Clean")) 464 } 465 if (detail.GetInteger("Ecom:Product.AlternativeImages.LoopCounter") == 2 && youtubevideoIsSet == false) 466 { 467 if (cookieBot.Statistics) 468 { 469 youtubevideoIsSet = true; 470 @RenderYoutube() 471 } 472 } 473 } 474 } 475 476 @if (cookieBot.Statistics && youtubevideoIsSet == false) 477 { 478 @RenderYoutube() 479 } 480 </div> 481 <div class="js-carousel-data" data-carousel-slide-time="0" data-direction="vertical" data-sliding-type="items" data-slides-in-view="5"> 482 <div class="carousel-prev-btn carousel-prev-btn--vertical dw-mod" onclick="Carousel.GetPreviousSlide('leftCarousel')"></div> 483 <div class="carousel-next-btn carousel-next-btn--vertical dw-mod" onclick="Carousel.GetNextSlide('leftCarousel')"></div> 484 </div> 485 </div> 486 </div> 487 </div> 488 } 489 490 @helper RenderThumbnail(string image) 491 { 492 string productId = GetString("Ecom:Product.ID"); 493 string thumbPrefix = "/Admin/Public/GetImage.ashx?width=200&amp;height=200&amp;crop=5&FillCanvas=True&DoNotUpscale=true&amp;Compression=75&amp;image="; 494 string imagePrefix = "/Admin/Public/GetImage.ashx?width=800&amp;height=800&amp;crop=5&FillCanvas=True&DoNotUpscale=true&amp;Compression=75&amp;image="; 495 496 <div class="carousel__slide carousel__slide--vertical dw-mod"> 497 <div class="thumb-list__item thumb-list__item--active dw-mod js-thumb js-gallery" data-for="Preview_@productId" data-preview="@imagePrefix@image" data-preview-type="img" onmouseover="Gallery.openImage(this)"> 498 <label for="GalleryModalTrigger"> 499 <img src="@thumbPrefix@image" alt="@GetString("Ecom:Product.Name")" class="js-gallery" data-for="FullImage" data-preview="@image" data-preview-type="img" onclick="Gallery.openImage(this)"> 500 </label> 501 </div> 502 </div> 503 } 504 505 @helper RenderYoutube() 506 { 507 string productId = GetString("Ecom:Product.ID"); 508 var videos = GetLoop("Smartpage:Product.VideoLoop"); 509 510 foreach (var video in videos) 511 { 512 513 <div class="carousel__slide carousel__slide--vertical dw-mod"> 514 <div class="thumb-list__item dw-mod js-thumb js-gallery" data-for="Preview_@productId" data-preview="@video.GetString("Preview")" data-preview-type="@video.GetString("PreviewType")" onmouseover="Gallery.openImage(this)"> 515 <label for="GalleryModalTrigger" class="u-position-relative"> 516 <i class="thumb-play-btn fas fa-play-circle u-brand-color-one" onclick="Gallery.openImage(document.getElementById('thumb-video_@video.GetString("VideoID")'))"></i> 517 <img id="thumb-video_@video.GetString("VideoID")" src="@video.GetString("Thumbnail")" alt="@GetString("Ecom:Product.Name")" class="js-gallery" data-for="FullImage" data-preview="@video.GetString("Preview")" data-preview-type="@video.GetString("PreviewType")" onclick="Gallery.openImage(this)"> 518 </label> 519 </div> 520 </div> 521 522 } 523 } 524 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 525 @using Dynamicweb.Core 526 @using System 527 @using System.Web 528 @using System.Collections.Generic 529 @using Dynamicweb.Rapido.Blocks 530 @using Smartpage.CookieManager 531 @using System.Text.RegularExpressions 532 @using Smartpage.Ecommerce.Repo; 533 534 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 535 @using System.Text.RegularExpressions 536 @using Dynamicweb.Core 537 @functions{ 538 /* 539 * Price States: 540 * 1: Exact amount is displayed (green) 541 * 2: Currently unavailable (yellow) 542 * NOTE: IF product manufactor is in Website Settings list, then *2-alternative* is used 543 * 3: Not available (red) 544 * 4: Contact Kruuse for buying this product (grey) 545 */ 546 547 public class Prices 548 { 549 public string price { get; set; } 550 public double priceDouble { get; set; } 551 public string discount { get; set; } 552 } 553 554 Prices renderPriceObject() 555 { 556 Prices priceOjbect = new Prices(); 557 558 if (GetString("Ecom:Product.Discount.Price.PriceFormatted") != GetString("Ecom:Product.Price.PriceFormatted") || GetString("Ecom:Product.Discount.Price.PriceFormatted") != GetString("Ecom:Product.InformativePrice.PriceFormatted")) 559 { 560 priceOjbect.price = GetString("Ecom:Product.Discount.Price.PriceFormatted"); 561 priceOjbect.priceDouble = (GetDouble("Ecom:Product.Discount.Price.PricePIP") / 100); 562 priceOjbect.discount = GetString("Ecom:Product.InformativePrice.PriceFormatted"); 563 } 564 else 565 { 566 priceOjbect.price = GetString("Ecom:Product.Price.PriceFormatted"); 567 priceOjbect.priceDouble = (GetDouble("Ecom:Product.Price.PricePIP") / 100); 568 } 569 570 return priceOjbect; 571 } 572 573 Prices renderPriceObject(LoopItem product) 574 { 575 Prices priceOjbect = new Prices(); 576 577 if (product.GetString("Ecom:Product.Discount.Price.PriceFormatted") != product.GetString("Ecom:Product.Price.PriceFormatted") || product.GetString("Ecom:Product.Discount.Price.PriceFormatted") != product.GetString("Ecom:Product.InformativePrice.PriceFormatted")) 578 { 579 priceOjbect.price = product.GetString("Ecom:Product.Discount.Price.PriceFormatted"); 580 priceOjbect.priceDouble = (product.GetDouble("Ecom:Product.Discount.Price.PricePIP") / 100); 581 priceOjbect.discount = product.GetString("Ecom:Product.InformativePrice.PriceFormatted"); 582 } 583 else 584 { 585 priceOjbect.price = product.GetString("Ecom:Product.Price.PriceFormatted"); 586 priceOjbect.priceDouble = (product.GetDouble("Ecom:Product.Price.PricePIP") / 100); 587 } 588 589 return priceOjbect; 590 } 591 592 string renderPriceState() 593 { 594 return renderPriceState(renderPriceObject().priceDouble); 595 } 596 597 string renderPriceState(double price) 598 { 599 if (GetInteger("Smartpage:Product.Prices.Count") == 0 || price >= Pageview.AreaSettings.GetItem("Custom").GetItem("CustomSettings").GetDouble("SpProductPriceLimit")) 600 { 601 return "4"; 602 } 603 else if (GetInteger("Ecom:Product.Stock") <= 0) 604 { 605 if (GetBoolean("Ecom:Product:Field.Discontinued")) 606 { 607 return "3"; 608 } 609 else 610 { 611 return "2"; 612 } 613 } 614 else 615 { 616 return "1"; 617 } 618 } 619 620 string renderPriceState(Dynamicweb.Ecommerce.Products.Product product) 621 { 622 if (product.Prices == null || product.Prices.Count == 0 || product.Price.Price >= Pageview.AreaSettings.GetItem("Custom").GetItem("CustomSettings").GetDouble("SpProductPriceLimit")) 623 { 624 return "4"; 625 } 626 else if (product.Stock <= 0) 627 { 628 if (Converter.ToBoolean(product.GetProductFieldValue("Discontinued"))) 629 { 630 return "3"; 631 } 632 else 633 { 634 return "2"; 635 } 636 } 637 else 638 { 639 return "1"; 640 } 641 } 642 643 string renderPriceState(Dynamicweb.Ecommerce.Products.Product product, string stockAmount) 644 { 645 if (product.Prices == null || product.Prices.Count == 0 || product.Price.Price >= Pageview.AreaSettings.GetItem("Custom").GetItem("CustomSettings").GetDouble("SpProductPriceLimit")) 646 { 647 return "4"; 648 } 649 else if (Converter.ToInt32(stockAmount) <= 0) 650 { 651 if (Converter.ToBoolean(product.GetProductFieldValue("Discontinued"))) 652 { 653 return "3"; 654 } 655 else 656 { 657 return "2"; 658 } 659 } 660 else 661 { 662 return "1"; 663 } 664 } 665 666 string renderPriceState(LoopItem product) 667 { 668 return renderPriceState(product, renderPriceObject(product).priceDouble); 669 } 670 671 672 string renderPriceState(LoopItem product, double price) 673 { 674 if (product.GetInteger("Smartpage:Product.Prices.Count") == 0 || price >= Pageview.AreaSettings.GetItem("Custom").GetItem("CustomSettings").GetDouble("SpProductPriceLimit")) 675 { 676 return "4"; 677 } 678 else if (product.GetInteger("Ecom:Product.Stock") <= 0) 679 { 680 if (product.GetBoolean("Ecom:Product:Field.Discontinued")) 681 { 682 return "3"; 683 } 684 else 685 { 686 return "2"; 687 } 688 } 689 else 690 { 691 return "1"; 692 } 693 } 694 695 696 string renderPriceState(LoopItem product, string stockAmount) 697 { 698 return renderPriceState(product, renderPriceObject(product).priceDouble, stockAmount); 699 } 700 701 string renderPriceState(LoopItem product, double price, string stockAmount) 702 { 703 if (product.GetInteger("Smartpage:Product.Prices.Count") == 0 || price >= Pageview.AreaSettings.GetItem("Custom").GetItem("CustomSettings").GetDouble("SpProductPriceLimit")) 704 { 705 return "4"; 706 } 707 else if (Converter.ToInt32(stockAmount) <= 0) 708 { 709 if (product.GetBoolean("Ecom:Product:Field.Discontinued")) 710 { 711 return "3"; 712 } 713 else 714 { 715 return "2"; 716 } 717 } 718 else 719 { 720 return "1"; 721 } 722 } 723 724 string renderPrice(string price) 725 { 726 var priceState = renderPriceState(); 727 if (priceState != "4") 728 { 729 return price; 730 } 731 732 return ""; 733 } 734 735 string renderPrice(LoopItem product, string price) 736 { 737 var priceState = renderPriceState(product); 738 if (priceState != "4") 739 { 740 return price; 741 } 742 743 return ""; 744 } 745 746 double renderPrice(double price) 747 { 748 var priceState = renderPriceState(price); 749 if (priceState != "4") 750 { 751 return price; 752 } 753 754 return 0; 755 } 756 757 double renderPrice(LoopItem product, double price) 758 { 759 var priceState = renderPriceState(product, price); 760 if (priceState != "4") 761 { 762 return price; 763 } 764 765 return 0; 766 } 767 768 string renderStockState() 769 { 770 var priceState = renderPriceState(); 771 772 return "stock-icon--state" + priceState; 773 } 774 775 string renderStockState(Dynamicweb.Ecommerce.Products.Product product) 776 { 777 var priceState = renderPriceState(product); 778 779 return "stock-icon--state" + priceState; 780 } 781 782 string renderStockState(Dynamicweb.Ecommerce.Products.Product product, string stockAmount) 783 { 784 var priceState = renderPriceState(product, stockAmount); 785 786 return "stock-icon--state" + priceState; 787 } 788 789 string renderStockState(LoopItem product) 790 { 791 var priceState = renderPriceState(product); 792 793 return "stock-icon--state" + priceState; 794 } 795 796 string renderStockText(string stockLevel) 797 { 798 var priceState = renderPriceState(); 799 var useAlternative = priceState == "2" && Pageview.AreaSettings.GetItem("Custom").GetItem("CustomSettings").GetList("SpAlternativeStockTextManufacturers").SelectedValues.Any(i => i == GetString("Ecom:Manufacturer.ID")); 800 801 return string.Format(Translate("State" + priceState + (useAlternative ? "Alternative" : ""), "{0}"), stockLevel); 802 } 803 804 string renderStockText(LoopItem product) 805 { 806 var priceState = renderPriceState(product); 807 var useAlternative = priceState == "2" && Pageview.AreaSettings.GetItem("Custom").GetItem("CustomSettings").GetList("SpAlternativeStockTextManufacturers").SelectedValues.Any(i => i == product.GetString("Ecom:Manufacturer.ID")); 808 809 return string.Format(Translate("State" + priceState + (useAlternative ? "Alternative" : ""), "{0}"), product.GetString("Ecom:Product.Stock")); 810 } 811 812 string renderStockText(LoopItem product, string stockAmount) 813 { 814 var priceState = renderPriceState(product, stockAmount); 815 var useAlternative = priceState == "2" && Pageview.AreaSettings.GetItem("Custom").GetItem("CustomSettings").GetList("SpAlternativeStockTextManufacturers").SelectedValues.Any(i => i == product.GetString("Ecom:Manufacturer.ID")); 816 817 return string.Format(Translate("State" + priceState + (useAlternative ? "Alternative" : ""), "{0}"), stockAmount); 818 } 819 820 string renderHideBuyOptions(string option) 821 { 822 var priceState = renderPriceState(); 823 if (priceState == "3" || priceState == "4") 824 { 825 return option; 826 } 827 828 return ""; 829 } 830 831 string renderHideBuyOptions(LoopItem product, string option) 832 { 833 var priceState = renderPriceState(product); 834 if (priceState == "3" || priceState == "4") 835 { 836 return option; 837 } 838 839 return ""; 840 } 841 } 842 843 @functions { 844 bool useFacebookPixel; 845 bool useGoogleTagManager; 846 BlocksPage mainInfoPage = BlocksPage.GetBlockPage("Product"); 847 848 CookieBot cookieBot = new CookieBot(); 849 } 850 851 @{ 852 bool mainInfoRenderVariantsAsProducts = Pageview.AreaSettings.GetItem("ProductPage").GetString("RenderVariantsAsProductList") != null && GetInteger("Ecom:Product.VariantCount") > 1 ? Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("RenderVariantsAsProductList") : false; 853 bool mainPointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly"); 854 bool mainInfoOnlyPreview = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("OnlyPreviewForAnonymous") && Pageview.User == null; 855 string mainInfoVariantId = HttpContext.Current.Request.QueryString.Get("variantId") != null ? HttpContext.Current.Request.QueryString.Get("variantId") : ""; 856 string mainInfoFeedId = GetGlobalValue("Global:Page.ID").ToString() + "&ProductID=" + GetString("Ecom:Product.ID") + "&VariantID=" + mainInfoVariantId + "&Feed=True&redirect=false"; 857 string mainInfoCartIcon = "fas fa-shopping-cart"; 858 859 useFacebookPixel = !string.IsNullOrWhiteSpace(Pageview.AreaSettings.GetItem("Settings").GetString("FacebookPixelID")) && cookieBot.Marketing; 860 useGoogleTagManager = !string.IsNullOrEmpty(Pageview.AreaSettings.GetItem("Settings").GetString("GoogleTagManagerID")) && cookieBot.Statistics; 861 862 Block mainInfoHeader = new Block() 863 { 864 Id = "MainInfoHeader", 865 SortId = 10, 866 Template = RenderMainInfoHeader() 867 }; 868 mainInfoPage.Add("MainInformation", mainInfoHeader); 869 870 Block mainInfoDescription = new Block() 871 { 872 Id = "ShortDescription", 873 SortId = 30, 874 Template = RenderShortDescription() 875 }; 876 mainInfoPage.Add("MainInformation", mainInfoDescription); 877 878 if (!mainInfoRenderVariantsAsProducts) 879 { 880 Block mainInfoVariants = new Block() 881 { 882 Id = "Variants", 883 SortId = 50, 884 Template = RenderMainInfoVariants() 885 }; 886 mainInfoPage.Add("MainInformation", mainInfoVariants); 887 } 888 889 Block mainInfoBOM = new Block() 890 { 891 Id = "BOM", 892 SortId = 60, 893 Template = RenderMainInfoBOM() 894 }; 895 mainInfoPage.Add("MainInformation", mainInfoBOM); 896 897 if (!mainInfoRenderVariantsAsProducts) 898 { 899 Block mainInfoBuy = new Block() 900 { 901 Id = "Buy", 902 SortId = 80, 903 Template = RenderMainInfoBuy() 904 }; 905 mainInfoPage.Add("MainInformation", mainInfoBuy); 906 907 //Block stockAndShipping = new Block() 908 //{ 909 // Id = "StockAndShipping", 910 // SortId = 90, 911 // Template = RenderStockAndShipping() 912 //}; 913 //mainInfoPage.Add("MainInformation", stockAndShipping); 914 } 915 } 916 917 @helper RenderMainInfoHeader() 918 { 919 bool renderVariantsAsProducts = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("RenderVariantsAsProductList") != null && GetInteger("Ecom:Product.VariantCount") > 1 ? Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("RenderVariantsAsProductList") : false; 920 string pageId = GetGlobalValue("Global:Page.ID").ToString(); 921 //string currentPrice = renderPrice(GetString("Ecom:Product.Discount.Price.PriceFormatted") == GetString("Ecom:Product.Price.PriceFormatted") ? GetString("Ecom:Product.Price.PriceFormatted") : GetString("Ecom:Product.Discount.Price.PriceFormatted")); 922 bool hideProductNumber = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideProductNumber"); 923 924 bool useFontAwesomePro = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetBoolean("UseFontAwesomePro"); 925 var selectedFavoriteIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("FavoriteIcon") != null ? Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("FavoriteIcon").SelectedValue : "star"; 926 string favoriteIcon = "fas fa-" + selectedFavoriteIcon + " fac-red"; 927 string favoriteOutlineIcon = "far fa-" + selectedFavoriteIcon + " fac-grey"; 928 Dynamicweb.Ecommerce.Products.Product apiProduct = Dynamicweb.Ecommerce.Services.Products.GetProductByNumber(GetString("Ecom:Product.Number"), Dynamicweb.Ecommerce.Common.Context.LanguageID); 929 930 <div> 931 <div class="u-pull--left product__title dw-mod"> 932 <h1 class="u-no-margin">@GetString("Ecom:Product.Name") @GetString("Ecom:Product.SelectedVariantComboName")</h1> 933 934 @if (!hideProductNumber && apiProduct != null && !apiProduct.IsVariantMaster) 935 { 936 <div class="item-number dw-mod">@GetString("Ecom:Product.Number")</div> 937 } 938 </div> 939 </div> 940 } 941 942 @helper RenderStockAndShipping() 943 { 944 bool hideStockState = Pageview.AreaSettings.GetItem("ProductPage").GetString("HideStockState") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideStockState") : false; 945 bool hideDelivery = Pageview.AreaSettings.GetItem("ProductPage").GetString("HideShipping") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideShipping") : false; 946 bool onlyPreview = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("OnlyPreviewForAnonymous") && Pageview.User == null; 947 948 var stockState = renderStockState(); 949 var stockText = renderStockText(GetString("Ecom:Product.Stock")); 950 var deliveryText = string.IsNullOrEmpty(GetString("Ecom:Product:Stock.DeliveryText")) ? "" : ", " + Translate("Delivery") + " " + GetString("Ecom:Product:Stock.DeliveryText") + " " + GetString("Ecom:Product:Stock.DeliveryUnit"); 951 string variantId = GetString("Ecom:Product.VariantID"); 952 int variantCount = GetInteger("Ecom:Product.VariantCount"); 953 954 if (!onlyPreview && (!string.IsNullOrEmpty(stockState)) /*|| !string.IsNullOrEmpty(deliveryText)) && !string.IsNullOrEmpty(variantId) && variantCount > 0*/) 955 { 956 <div class="product__stock-delivery dw-mod"> 957 <span> 958 @if (!hideStockState) 959 { 960 <span class="stock-icon @stockState u-no-margin dw-mod" title="@stockText"></span> @stockText@deliveryText 961 } 962 963 @if (!string.IsNullOrEmpty(deliveryText) && !hideDelivery) 964 { 965 @deliveryText 966 } 967 </span> 968 </div> 969 } 970 } 971 972 @helper RenderShortDescription() 973 { 974 if (!String.IsNullOrEmpty(GetString("Ecom:Product.ShortDescription"))) 975 { 976 var shortDescription = GetString("Ecom:Product.ShortDescription"); 977 978 if (!cookieBot.Statistics) 979 { 980 var iframes = Regex.Match(shortDescription, "<iframe[^>]*?(?:\\/>|>[^<]*?<\\/iframe>)"); 981 if (iframes.Success) 982 { 983 foreach (Group item in iframes.Groups) 984 { 985 shortDescription = shortDescription.Replace(item.Value, ""); 986 } 987 } 988 } 989 990 <div class="introduction-text"> 991 @shortDescription 992 </div> 993 } 994 } 995 996 @helper RenderMainInfoVariants() 997 { 998 string pageId = GetGlobalValue("Global:Page.ID").ToString(); 999 string productId = GetString("Ecom:Product.ID"); 1000 string variantSelection = !String.IsNullOrEmpty(HttpContext.Current.Request.QueryString.Get("variantId")) ? HttpContext.Current.Request.QueryString.Get("variantId").Replace(".", ",") : ""; 1001 string hideHelpText = ""; 1002 1003 foreach (LoopItem variantgroup in GetLoop("VariantGroups")) 1004 { 1005 foreach (LoopItem variantoption in variantgroup.GetLoop("VariantAvailableOptions")) 1006 { 1007 if (variantoption.GetBoolean("Ecom:VariantOption.Selected")) 1008 { 1009 hideHelpText = "u-hidden"; 1010 } 1011 } 1012 } 1013 1014 if (GetLoop("VariantGroups").Count > 0) 1015 { 1016 var variantCombinationsObject = new List<Array>(); 1017 foreach (LoopItem variantcomb in GetLoop("VariantStockCombinations")) 1018 { 1019 string[] combinations = variantcomb.GetString("Ecom:VariantStockCombination.VariantID").Split('.'); 1020 variantCombinationsObject.Add(combinations); 1021 } 1022 1023 string combinationsJson = Newtonsoft.Json.JsonConvert.SerializeObject(variantCombinationsObject).Replace("\"", "\'"); 1024 1025 var variantGroupsObject = new List<List<String>>(); 1026 foreach (LoopItem variantGroup in GetLoop("VariantGroups")) 1027 { 1028 var variantsObject = new List<String>(); 1029 foreach (LoopItem variantOption in variantGroup.GetLoop("VariantAvailableOptions")) 1030 { 1031 variantsObject.Add(variantOption.GetString("Ecom:VariantOption.ID")); 1032 } 1033 variantGroupsObject.Add(variantsObject); 1034 } 1035 string variantsJson = Newtonsoft.Json.JsonConvert.SerializeObject(variantGroupsObject).Replace("\"", "\'"); 1036 1037 <div> 1038 <div 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"> 1039 @foreach (LoopItem variantGroup in GetLoop("VariantGroups")) 1040 { 1041 string groupId = variantGroup.GetString("Ecom:VariantGroup.ID"); 1042 1043 <div> 1044 <div class="u-bold">@variantGroup.GetString("Ecom:VariantGroup.Name")</div> 1045 <div> 1046 @foreach (LoopItem variantOption in variantGroup.GetLoop("VariantAvailableOptions")) 1047 { 1048 Dynamicweb.Ecommerce.Products.Product apiProductVariant = Dynamicweb.Ecommerce.Services.Products.GetProductById(GetString("Ecom:Product.ID"), variantOption.GetString("Ecom:VariantOption.ID"), Dynamicweb.Ecommerce.Common.Context.LanguageID); 1049 string selected = variantOption.GetBoolean("Ecom:VariantOption.Selected") ? "checked" : ""; 1050 if (apiProductVariant.Active) 1051 { 1052 if (!string.IsNullOrEmpty(variantOption.GetString("Ecom:VariantOption.ImgSmall.Clean"))) 1053 { 1054 string variantImage = "/Admin/Public/GetImage.ashx?width=100&amp;height=50&amp;crop=5&amp;Compression=75&amp;image=/Images/" + variantOption.GetString("Ecom: VariantOption.ImgSmall.Clean"); 1055 <img data-variant-id="@variantOption.GetString("Ecom:VariantOption.ID")" data-variant-group="@groupId" src="@variantImage" onclick="MatchVariants.SelectThis(event)" alt="@variantOption.GetString("Ecom:VariantOption.Name")" title="@variantOption.GetString("Ecom:VariantOption.Name")" class="btn btn--tag @selected js-variant-option" data-check="@selected" /> 1056 } 1057 else 1058 { 1059 <button type="button" data-variant-id="@variantOption.GetString("Ecom:VariantOption.ID")" data-variant-group="@groupId" onclick="MatchVariants.SelectThis(event)" class="btn btn--tag @selected js-variant-option" data-check="@selected">@variantOption.GetString("Ecom:VariantOption.Name")</button> 1060 } 1061 } 1062 } 1063 </div> 1064 </div> 1065 } 1066 </div> 1067 <small class="js-help-text help-text @hideHelpText">@Translate("Please select variant!")</small> 1068 </div> 1069 { 1070 bool mainInfoOnlyPreview = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("OnlyPreviewForAnonymous") && Pageview.User == null; 1071 if (!mainInfoOnlyPreview) 1072 { 1073 Dynamicweb.Ecommerce.Products.Product apiProduct = Dynamicweb.Ecommerce.Services.Products.GetProductByNumber(GetString("Ecom:Product.Number"), Dynamicweb.Ecommerce.Common.Context.LanguageID); 1074 if (apiProduct != null && apiProduct.IsVariantMaster) 1075 { 1076 VariantPriceService variantPriceService = new VariantPriceService(); 1077 var fromPrice = variantPriceService.GetLowestPrice(GetString("Ecom:Product.ID"), Dynamicweb.Ecommerce.Common.Context.Currency.Code, Dynamicweb.Security.UserManagement.User.GetCurrentExtranetUser()); 1078 <h5>@Translate("Smartpage:Variant.FromPrice.Text", "Fra:") @fromPrice</h5> 1079 } 1080 } 1081 } 1082 1083 1084 } 1085 } 1086 1087 @helper RenderMainInfoBOM() 1088 { 1089 if (GetLoop("BOMProducts").Count > 0) 1090 { 1091 <h2 class="section-title">@Translate("Including products")</h2> 1092 foreach (LoopItem BOMProductItem in GetLoop("BOMProducts")) 1093 { 1094 string link = "/" + BOMProductItem.GetString("Ecom:Product.LinkGroup.Clean") + (!String.IsNullOrEmpty(BOMProductItem.GetString("Ecom:Product.VariantID")) ? "&VariantID=" + BOMProductItem.GetString("Ecom:Product.VariantID") : ""); 1095 <div class="grid__col--border grid"> 1096 <div class="grid__cell grid__cell--align-middle-left"> 1097 <a href="@link" class="u-pull--left u-margin-right"> 1098 <img src="/Admin/Public/GetImage.ashx?width=50&image=@BOMProductItem.GetString("Ecom:Product.ImageDefault.Default.Clean")&Compression=99" alt="@BOMProductItem.GetString("Ecom:Product.Name")" /> 1099 </a> 1100 <a href="@link">@BOMProductItem.GetString("Ecom:Product.Name")</a> 1101 </div> 1102 </div> 1103 } 1104 } 1105 } 1106 1107 @helper RenderMainInfoBuy() 1108 { 1109 string pageId = GetGlobalValue("Global:Page.ID").ToString(); 1110 string variantId = HttpContext.Current.Request.QueryString.Get("variantId"); 1111 string productId = GetString("Ecom:Product.ID"); 1112 string feedId = pageId + "&ProductID=" + productId + "&VariantID=" + variantId + "&Feed=True&redirect=false"; 1113 1114 <div class="product__price-actions js-handlebars-root dw-mod" id="PriceAndActions" data-template="PricesAndActionsTemplate" data-json-feed="/Default.aspx?ID=@feedId" data-preloader="minimal"></div> 1115 <input type="hidden" value="@GetString("Ecom:Product.VariantID.Extented")" name="Variant" id="Variant_@GetString("Ecom:Product.ID")" /> 1116 } 1117 1118 @* Handlebars templates *@ 1119 1120 1121 <script id="PricesAndActionsTemplate" type="text/x-template"> 1122 1123 1124 {{#.}} 1125 {{#if discontinued}} 1126 {{>DiscontinuedTemplate}} 1127 {{else}} 1128 @if (!mainInfoOnlyPreview) 1129 { 1130 1131 <text>{{#if Prices}}</text> 1132 <div class="u-margin-bottom--lg dw-mod"> 1133 {{>PriceList}} 1134 </div> 1135 <text>{{/if}}</text> 1136 1137 <div class="product__price-actions__price dw-mod u-margin-bottom--lg"> 1138 @if (mainPointShopOnly) 1139 { 1140 <text> 1141 {{#if havePointPrice}} 1142 <div class="price price--product-page dw-mod">{{points}} @Translate("points")</div> 1143 {{else}} 1144 @Translate("Not available") 1145 {{/if}} 1146 </text> 1147 } 1148 else 1149 { 1150 <text> 1151 {{#ifCond variantSelected "!==" "False"}} 1152 <div class="before-price {{onSale}} dw-mod">{{discount}}</div> 1153 <div class="price price--product-page dw-mod">{{price}}</div> 1154 {{#if standardOrderQuantity}} 1155 <div class="{{hideBuyOptions}}">@Translate("Kolli"): {{standardOrderQuantity}}</div> 1156 {{/if}} 1157 {{/ifCond}} 1158 </text> 1159 } 1160 </div> 1161 <div class="buttons-collection buttons-collection--right product__price-actions__actions {{hideBuyOptions}} dw-mod"> 1162 <input type="checkbox" id="UnitOptions_{{id}}" class="dropdown-trigger" /> 1163 <div class="dropdown u-w150px u-w80px--xs dw-mod {{hasUnits}}"> 1164 <label class="dropdown__header dropdown__btn dw-mod" for="UnitOptions_{{id}}">{{unitName}}</label> 1165 <div id="unitOptions" class="dropdown__content dw-mod"> 1166 {{#unitOptions}} 1167 {{>UnitOption}} 1168 {{/unitOptions}} 1169 </div> 1170 <label class="dropdown-trigger-off" for="UnitOptions_{{id}}"></label> 1171 </div> 1172 1173 <input type="hidden" value="{{unitId}}" name="Unit" id="Unit_{{id}}" /> 1174 @if (mainPointShopOnly) 1175 { 1176 <button type="button" id="CartButton_{{id}}" class="btn btn--primary btn--condensed dw-mod js-cart-btn {{disabledBuyButton}} {{#unless canBePurchasedWithPoints}}js-stay-disabled{{/unless}}" name="CartCmd" value="addWithPoints" 1177 onclick="Cart.AddToCartByObject(event, { 1178 id: '{{productId}}', 1179 variantId: '{{variantid}}', 1180 unitId: '{{unitId}}', 1181 quantity: 1, 1182 buyForPoints: true, 1183 productInfo: {{productInfo}}, 1184 multiplum: {{multiplum}}, 1185 multiplumUnitId: '{{ProductDefaultUnitId}}', 1186 standardOrderQuantity: {{standardOrderQuantity}} 1187 }); {{facebookPixelAction}}"> 1188 <i class="@mainInfoCartIcon"></i><span class="u-hidden-xs u-hidden-xxs"> @Translate("Buy with points")</span> 1189 </button> 1190 <text> 1191 {{#unless canBePurchasedWithPoints}} 1192 {{#if havePointPrice}} 1193 <small class="help-text u-no-margin u-margin-top">@Translate("Not enough points to buy this")</small> 1194 {{/if}} 1195 {{/unless}} 1196 </text> 1197 } 1198 else 1199 { 1200 <text>{{#ifCond multiplum ">" "1"}} 1201 <input type="number" class="u-w70px product-quantity" id="Quantity_{{id}}" name="Quantity" value="{{multiplum}}" min="1"> 1202 {{else}} 1203 <input type="number" class="u-w70px product-quantity" id="Quantity_{{id}}" name="Quantity" value="1" min="1"> 1204 {{/ifCond}} 1205 </text> 1206 <button type="button" id="CartButton_{{id}}" class="btn btn--primary btn--condensed dw-mod js-cart-btn" name="submit" 1207 onclick="Cart.AddToCartByObject(event, { 1208 id: '{{productId}}', 1209 variantId: '{{variantid}}', 1210 unitId: '{{unitId}}', 1211 quantity: document.getElementById('Quantity_{{id}}').value, 1212 productInfo: {{productInfo}}, 1213 multiplum: {{multiplum}}, 1214 multiplumUnitId: '{{ProductDefaultUnitId}}', 1215 standardOrderQuantity: {{standardOrderQuantity}} 1216 }); {{facebookPixelAction}}"> 1217 <i class="@mainInfoCartIcon"></i><span class="u-hidden-xs u-hidden-xxs"> @Translate("Add to cart")</span> 1218 </button> 1219 } 1220 1221 @if (Dynamicweb.Core.Converter.ToBoolean(GetGlobalValue("Global:Extranet.UserName")) && !(Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("RenderVariantsAsProductList") && GetInteger("Ecom:Product.VariantCount") > 1)) 1222 { 1223 1224 <text>{{>FavoriteTemplateContainer}}</text> 1225 1226 } 1227 1228 </div> 1229 if (Pageview.User != null && !mainPointShopOnly && Dynamicweb.Security.Licensing.LicenseManager.LicenseHasFeature("LoyaltyPoints")) 1230 { 1231 <text> 1232 {{#if canBePurchasedWithPoints}} 1233 <form method="post" role="form" class="u-no-margin u-margin-top"> 1234 <input type="hidden" name="ProductID" value="{{id}}" /> 1235 <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> 1236 </form> 1237 {{/if}} 1238 </text> 1239 } 1240 } 1241 else 1242 { 1243 <button type="button" id="CartButton_{{id}}" class="u-hidden"></button> 1244 } 1245 {{/if}} 1246 1247 @{ 1248 bool hideStockState = Pageview.AreaSettings.GetItem("ProductPage").GetString("HideStockState") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideStockState") : false; 1249 bool hideDelivery = Pageview.AreaSettings.GetItem("ProductPage").GetString("HideShipping") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideShipping") : false; 1250 var deliveryText = string.IsNullOrEmpty(GetString("Ecom:Product:Stock.DeliveryText")) ? "" : ", " + Translate("Delivery") + " " + GetString("Ecom:Product:Stock.DeliveryText") + " " + GetString("Ecom:Product:Stock.DeliveryUnit"); 1251 } 1252 @if (!mainInfoOnlyPreview) 1253 { 1254 <text> 1255 {{#ifCond hasVariants "!==" "disabled"}} 1256 <div class="product__stock-delivery dw-mod"> 1257 <span> 1258 @if (!hideStockState) 1259 { 1260 <span class="stock-icon {{stockState}} u-no-margin dw-mod" title="{{stockText}}"></span> @:{{stockText}} 1261 } 1262 1263 @if (!string.IsNullOrEmpty(deliveryText) && !hideDelivery) 1264 { 1265 @deliveryText 1266 } 1267 </span> 1268 </div> 1269 {{/ifCond}} 1270 </text> 1271 } 1272 {{/.}} 1273 </script> 1274 1275 1276 <script id="FavoriteTemplateContainer" type="text/x-template"> 1277 {{#Favorite}} 1278 <div id="Favorite_{{id}}" class="u-inline"> 1279 <button type="button" id="FavoriteButton_{{id}}" class="btn btn--default btn--condensed u-no-margin dw-mod favorite-btn" onclick="document.getElementById('FavoriteTrigger_{{id}}').click();"> 1280 {{#if anyItemsInList}} 1281 <span class="u-hidden-xs u-hidden-xxs favorite-btn-text">{{modifyText}}</span> 1282 {{else}} 1283 <span class="u-hidden-xs u-hidden-xxs favorite-btn-text">{{addText}}</span> 1284 {{/if}} 1285 <i class="{{favoriteIcon}}"></i> 1286 </button> 1287 <input type="checkbox" id="FavoriteTrigger_{{id}}" class="dropdown-trigger" /> 1288 <div class="dropdown favorites-dropdown"> 1289 <div class="dropdown__content dropdown__content--show-left dropdown__content--padding u-w220px dw-mod"> 1290 <span class="u-bold">@Translate("Your lists")</span> 1291 <ul class="list list--clean dw-mod" id="FavoriteContainer_{{id}}"> 1292 {{#FavoriteLists}} 1293 <li> 1294 {{#if isInThisList}} 1295 <span class="is-in-list">{{name}}</span> 1296 <a class="remove-from-favorites" onclick="{{facebookPixelAction}} List.RemoveFromList('detail', '{{link}}');"><i class="fa fa-times u-color-font-black"></i></a> 1297 {{else}} 1298 <span>{{name}}</span> 1299 <a class="add-to-favorites" onclick="{{facebookPixelAction}} List.AddToList('detail', '{{link}}', '{{id}}', '{{variantId}}', '@GetPageIdByNavigationTag("ProductsPage")', this);">@Translate("Add")</a> 1300 {{/if}} 1301 </li> 1302 {{/FavoriteLists}} 1303 </ul> 1304 </div> 1305 <label class="dropdown-trigger-off" for="FavoriteTrigger_{{id}}"></label> 1306 </div> 1307 </div> 1308 {{/Favorite}} 1309 </script> 1310 1311 <script id="Units" type="text/x-template"> 1312 <div class="dropdown__item dw-mod" onclick="HandlebarsBolt.UpdateContent('PriceAndActions', '/Default.aspx?ID=@mainInfoFeedId&UnitID={{value}}')">{{name}}</div> 1313 </script> 1314 1315 <script id="UnitOption" type="text/x-template"> 1316 <div class="dropdown__item dw-mod" onclick="HandlebarsBolt.UpdateContent('PriceAndActions', '{{link}}&feed=true&UnitID={{value}}&rid={{id}}')">{{name}}</div> 1317 </script> 1318 1319 1320 <script> 1321 document.addEventListener("DOMContentLoaded", function () { 1322 if (document.getElementById("PriceAndActions")) { 1323 document.getElementById("PriceAndActions").addEventListener("contentLoaded", function (event) { 1324 if (document.querySelector(".js-variants") != null) { 1325 MatchVariants.Update(document.querySelector(".js-variants"), "DoNothing"); 1326 } 1327 }); 1328 } 1329 }); 1330 </script> 1331 1332 @if (useGoogleTagManager) 1333 { 1334 var groupObject = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(GetString("Ecom:Product.PrimaryOrFirstGroupID")); 1335 1336 <script> 1337 // Measure a view of product details. This example assumes the detail view occurs on pageload, 1338 // and also tracks a standard pageview of the details page. 1339 dataLayer.push({ 1340 'ecommerce': { 1341 'detail': { 1342 'actionField': {}, // 'detail' actions have an optional list property. 1343 'products': [{ 1344 'name': '@GetString("Ecom:Product.Name")', // Name or ID is required. 1345 'id': '@GetString("Ecom:Product.ID")', 1346 'price': '@(GetDouble("Ecom:Product.Discount.Price.Price") != GetDouble("Ecom:Product.Price.Price") ? GetDouble("Ecom:Product.Discount.Price.Price") : GetDouble("Ecom:Product.Price.Price"))', 1347 'brand': '@GetString("Ecom:Product:Field.brand.Value")', 1348 'category': '@(groupObject != null ? groupObject.Name : "")', 1349 'variant': '@(!string.IsNullOrEmpty(GetString("Ecom:Product.VariantID")) ? GetString("Ecom:Product.VariantID") : GetString("Ecom:Product.VariantID.Extented"))' 1350 }] 1351 } 1352 } 1353 }); 1354 </script> 1355 } 1356 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 1357 @using Dynamicweb.Core 1358 @using System 1359 @using System.Web 1360 @using System.Collections.Generic 1361 @using Dynamicweb.Rapido.Blocks 1362 @using Smartpage.CookieManager 1363 @using System.Text.RegularExpressions 1364 1365 @functions { 1366 BlocksPage productDescriptionPage = BlocksPage.GetBlockPage("Product"); 1367 } 1368 1369 @{ 1370 string fullDesctiptionLayout = !String.IsNullOrEmpty(Pageview.AreaSettings.GetItem("ProductPage").GetString("FullDescriptionLayout")) ? Pageview.AreaSettings.GetItem("ProductPage").GetList("FullDescriptionLayout").SelectedValue : "Section"; 1371 fullDesctiptionLayout = fullDesctiptionLayout == "Ribbon" ? "Section" : fullDesctiptionLayout; 1372 1373 if (!string.IsNullOrEmpty(GetString("Ecom:Product.LongDescription")) && fullDesctiptionLayout != "hide") 1374 { 1375 Block detailsDescription = new Block() 1376 { 1377 Name = fullDesctiptionLayout != "MainInformation" ? Translate("Description") : "", 1378 Id = "FullDescription", 1379 SortId = 10, 1380 Template = RenderProductDescription(fullDesctiptionLayout), 1381 Design = new Design 1382 { 1383 Size = "12", 1384 RenderType = RenderType.Column, 1385 HidePadding = true 1386 } 1387 }; 1388 productDescriptionPage.Add(fullDesctiptionLayout, detailsDescription); 1389 } 1390 } 1391 1392 @helper RenderProductDescription(string layout) 1393 { 1394 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("FullDescriptionLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 1395 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("FullDescriptionLayout").SelectedValue == "Ribbon" ? "u-padding--lg" : ""; 1396 1397 <div class="product__section @ribbonClasses dw-mod"> 1398 <div class="product__description center-container @ribbonSubClasses dw-mod"> 1399 @if (layout == "Section") { 1400 <h2>@Translate("Description")</h2> 1401 } 1402 1403 @{ 1404 var longDescription = GetString("Ecom:Product.LongDescription"); 1405 1406 if (!new CookieBot().Statistics) 1407 { 1408 var iframes = Regex.Match(longDescription, "<iframe[^>]*?(?:\\/>|>[^<]*?<\\/iframe>)"); 1409 if (iframes.Success) 1410 { 1411 foreach (Group item in iframes.Groups) 1412 { 1413 longDescription = longDescription.Replace(item.Value, ""); 1414 } 1415 } 1416 } 1417 1418 @longDescription 1419 } 1420 </div> 1421 </div> 1422 } 1423 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 1424 @using Dynamicweb.Core 1425 @using System 1426 @using System.Web 1427 @using System.Globalization; 1428 @using System.Collections.Generic 1429 @using Dynamicweb.Rapido.Blocks 1430 @using System.Linq 1431 1432 @functions { 1433 BlocksPage productFieldsPage = BlocksPage.GetBlockPage("Product"); 1434 List<LoopItem> downloadDocuments = new List<LoopItem>(); 1435 1436 static string ConvertBytes(long bytes) 1437 { 1438 double size = bytes / 1024; //KB 1439 if (size > 1024) 1440 { 1441 size = (bytes / 1024f) / 1024f; //MB 1442 return string.Format("{0:n1} MB", size); 1443 } 1444 else 1445 { 1446 return string.Format("{0:n0} KB", size); 1447 } 1448 } 1449 1450 static bool isImage(string path) 1451 { 1452 return new List<string> { ".jpg", ".jpeg", ".gif", ".png", ".svg" }.Contains(Path.GetExtension(path).ToLower()); 1453 } 1454 1455 string getIconForFile(string fileName) 1456 { 1457 string ext = Path.GetExtension(fileName); 1458 string icon = ""; 1459 switch (ext.ToLower()) 1460 { 1461 case ".xls": 1462 case ".xlsx": 1463 icon = "fa-file-excel"; 1464 break; 1465 case ".ppt": 1466 case ".pptx": 1467 icon = "fa-file-powerpoint"; 1468 break; 1469 case ".doc": 1470 case ".docx": 1471 icon = "fa-file-word"; 1472 break; 1473 case ".jpg": 1474 case ".jpeg": 1475 case ".png": 1476 case ".gif": 1477 case ".pdf": 1478 return "<img class='product__document-img' alt='" + fileName + "' src='/Admin/Public/GetImage.ashx?crop=5&height=70&width=120&Compression=75&DoNotUpscale=true&image=" + HttpUtility.UrlEncode(fileName) + "' />"; 1479 default: 1480 icon = "fa-file"; 1481 break; 1482 } 1483 return "<i class='product__document-icon far " + icon + "'></i> "; 1484 } 1485 } 1486 1487 @{ 1488 foreach (LoopItem customField in GetLoop("CustomFieldValues")) 1489 { 1490 if (!string.IsNullOrEmpty(customField.GetString("Product.CustomField.Name")) && !string.IsNullOrEmpty(customField.GetString("Product.CustomField.Value.Clean")) && customField.GetString("Product.CustomField.Name") != "Custom sticker") 1491 { 1492 if (!string.IsNullOrEmpty(customField.GetString("Document.FullPath"))) 1493 { 1494 downloadDocuments.Add(customField); 1495 } 1496 } 1497 } 1498 1499 foreach (LoopItem customField in GetLoop("ProductCategories")) 1500 { 1501 foreach (LoopItem field in customField.GetLoop("ProductCategoryFields")) 1502 { 1503 if (!string.IsNullOrEmpty(field.GetString("Ecom:Product.CategoryField.Label")) && !string.IsNullOrEmpty(field.GetString("Ecom:Product.CategoryField.Value"))) 1504 { 1505 if (field.GetString("Ecom:Product.CategoryField.TypeID") == "9") 1506 { 1507 downloadDocuments.Add(field); 1508 } 1509 } 1510 } 1511 } 1512 1513 foreach (LoopItem detail in GetLoop("Details")) 1514 { 1515 if (!string.IsNullOrEmpty(detail.GetString("Ecom:Product:Detail.Image.Clean"))) 1516 { 1517 downloadDocuments.Add(detail); 1518 } 1519 } 1520 1521 string detailFieldsLayout = Pageview.AreaSettings.GetItem("ProductPage").GetList("DetailFieldsLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("DetailFieldsLayout").SelectedValue : "Section"; 1522 detailFieldsLayout = detailFieldsLayout == "Ribbon" || string.IsNullOrEmpty(detailFieldsLayout) ? "Section" : detailFieldsLayout; 1523 string categoryFieldsLayout = Pageview.AreaSettings.GetItem("ProductPage").GetList("CategoryFieldsLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("CategoryFieldsLayout").SelectedValue : "Section"; 1524 categoryFieldsLayout = categoryFieldsLayout == "Ribbon" || string.IsNullOrEmpty(categoryFieldsLayout) ? "Section" : categoryFieldsLayout; 1525 string downloadsFieldsLayout = Pageview.AreaSettings.GetItem("ProductPage").GetList("DownloadsLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("DownloadsLayout").SelectedValue : "Section"; 1526 downloadsFieldsLayout = downloadsFieldsLayout == "Ribbon" || string.IsNullOrEmpty(downloadsFieldsLayout) ? "Section" : downloadsFieldsLayout; 1527 1528 if (GetLoop("CustomFieldValues").Count > 0 && detailFieldsLayout != "hide") 1529 { 1530 Block detailsCustom = new Block() 1531 { 1532 Name = detailFieldsLayout != "MainInformation" ? Translate("Details") : "", 1533 Id = "CustomFields", 1534 SortId = 30, 1535 Template = RenderCustomData(detailFieldsLayout), 1536 Design = new Design 1537 { 1538 Size = "12", 1539 RenderType = RenderType.Column, 1540 HidePadding = true 1541 } 1542 }; 1543 1544 productFieldsPage.Add(detailFieldsLayout, detailsCustom); 1545 } 1546 1547 if (categoryFieldsLayout != "hide") 1548 { 1549 foreach (LoopItem categoryGroup in GetLoop("ProductCategories")) 1550 { 1551 bool hasFields = categoryGroup.GetLoop("ProductCategoryFields").FirstOrDefault(cf => !string.IsNullOrEmpty(cf.GetString("Ecom:Product.CategoryField.Value"))) != null; 1552 if (hasFields) 1553 { 1554 Block detailsCategoryFields = new Block() 1555 { 1556 Name = categoryFieldsLayout != "MainInformation" ? categoryGroup.GetString("Ecom:Product.Category.Name") : "", 1557 Id = ToPascalCase(categoryGroup.GetString("Ecom:Product.Category.Name")), 1558 SortId = 40, 1559 Template = RenderProductCategory(categoryGroup.GetString("Ecom:Product.Category.Name"), categoryGroup, categoryFieldsLayout), 1560 Design = new Design 1561 { 1562 Size = "12", 1563 RenderType = RenderType.Column, 1564 HidePadding = true 1565 } 1566 }; 1567 1568 productFieldsPage.Add(categoryFieldsLayout, detailsCategoryFields); 1569 } 1570 } 1571 } 1572 1573 if (downloadDocuments.Count > 0 && downloadsFieldsLayout != "hide") 1574 { 1575 Block detailsDownloads = new Block() 1576 { 1577 Name = downloadsFieldsLayout != "MainInformation" ? Translate("Downloads") : "", 1578 Id = "Downloads", 1579 SortId = 50, 1580 Template = RenderProductDownloads(downloadsFieldsLayout), 1581 Design = new Design 1582 { 1583 Size = "12", 1584 RenderType = RenderType.Column, 1585 HidePadding = true 1586 } 1587 }; 1588 1589 productFieldsPage.Add(downloadsFieldsLayout, detailsDownloads); 1590 } 1591 } 1592 1593 @helper RenderCustomData(string layout) 1594 { 1595 string viewType = Pageview.AreaSettings.GetItem("ProductPage").GetString("DetailFieldsView") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("DetailFieldsView").SelectedValue : "grid"; 1596 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("DetailFieldsLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 1597 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("DetailFieldsLayout").SelectedValue == "Ribbon" ? "u-padding--lg" : ""; 1598 1599 <div class="product__section @ribbonClasses dw-mod"> 1600 <div class="center-container @ribbonSubClasses dw-mod"> 1601 @if (layout == "Section") 1602 { 1603 <h2>@Translate("Information")</h2> 1604 } 1605 1606 @if (viewType != "table") 1607 { 1608 <div class="grid grid--external-bleed-x u-margin-bottom--lg"> 1609 @RenderCustomFields(GetLoop("CustomFieldValues"), viewType) 1610 </div> 1611 } 1612 else 1613 { 1614 string tableWidth = layout != "MainInformation" ? "grid__col-md-6" : "grid__col-md-12"; 1615 1616 <div class="grid grid--external-bleed-x u-margin-bottom--lg"> 1617 <div class="@tableWidth grid__col-sm-12 grid__col-xs-12"> 1618 <table class="table--no-top-border"> 1619 @RenderCustomFields(GetLoop("CustomFieldValues"), viewType) 1620 </table> 1621 </div> 1622 </div> 1623 } 1624 </div> 1625 </div> 1626 } 1627 1628 @helper RenderCustomFields(List<LoopItem> fieldsLoop, string viewType) 1629 { 1630 var hiddenProductFieldsList = Pageview.AreaSettings.GetItem("Custom").GetItem("CustomSettings").GetList("SpHiddenProductFields"); 1631 1632 foreach (LoopItem customField in fieldsLoop) 1633 { 1634 var fieldHidden = hiddenProductFieldsList.SelectedValues.Any(x => x == customField.GetString("Product.CustomField.Template")); 1635 if (!fieldHidden) 1636 { 1637 1638 string fieldValue = customField.GetString("Product.CustomField.Value.Clean"); 1639 fieldValue = fieldValue == "False" ? Translate("No") : fieldValue; 1640 fieldValue = fieldValue == "True" ? Translate("Yes") : fieldValue; 1641 1642 if (customField.GetLoop("Product.CustomField.Options").Count > 0) 1643 { 1644 fieldValue = customField.GetString("Product.CustomField.Label"); 1645 } 1646 1647 1648 if ( 1649 !string.IsNullOrEmpty(customField.GetString("Product.CustomField.Name")) && !string.IsNullOrEmpty(fieldValue)) 1650 { 1651 if (string.IsNullOrEmpty(customField.GetString("Document.FullPath"))) 1652 { 1653 @RenderFieldItem(customField.GetString("Product.CustomField.Name"), fieldValue, viewType); 1654 } 1655 } 1656 } 1657 } 1658 } 1659 1660 @helper RenderProductCategory(string name, LoopItem categoryGroup, string layout) 1661 { 1662 string viewType = Pageview.AreaSettings.GetItem("ProductPage").GetString("CategoryFieldsView") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("CategoryFieldsView").SelectedValue : "grid"; 1663 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("CategoryFieldsLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 1664 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("CategoryFieldsLayout").SelectedValue == "Ribbon" ? "u-padding--lg" : ""; 1665 1666 <div class="product__section @ribbonClasses dw-mod"> 1667 <div class="center-container @ribbonSubClasses dw-mod"> 1668 @if (layout == "Section") 1669 { 1670 <h2>@name</h2> 1671 } 1672 1673 @if (viewType != "table") 1674 { 1675 <div class="grid grid--external-bleed-x u-margin-bottom--lg"> 1676 @RenderProductCategoryFields(categoryGroup.GetLoop("ProductCategoryFields"), viewType) 1677 </div> 1678 } 1679 else 1680 { 1681 string tableWidth = layout != "MainInformation" ? "grid__col-md-6" : "grid__col-md-12"; 1682 1683 <div class="grid grid--external-bleed-x u-margin-bottom--lg"> 1684 <div class="@tableWidth grid__col-sm-12 grid__col-xs-12"> 1685 <table class="table--no-top-border"> 1686 @RenderProductCategoryFields(categoryGroup.GetLoop("ProductCategoryFields"), viewType) 1687 </table> 1688 </div> 1689 </div> 1690 } 1691 </div> 1692 </div> 1693 } 1694 1695 @helper RenderProductCategoryFields(List<LoopItem> fieldsLoop, string viewType) 1696 { 1697 foreach (LoopItem categoryField in fieldsLoop) 1698 { 1699 string fieldValue = categoryField.GetString("Ecom:Product.CategoryField.Value"); 1700 fieldValue = fieldValue == "False" ? Translate("No") : fieldValue; 1701 fieldValue = fieldValue == "True" ? Translate("Yes") : fieldValue; 1702 1703 if (!string.IsNullOrEmpty(categoryField.GetString("Ecom:Product.CategoryField.Label")) && !string.IsNullOrEmpty(fieldValue)) 1704 { 1705 if (categoryField.GetString("Ecom:Product.CategoryField.TypeID") != "9") 1706 { 1707 if (categoryField.GetString("Ecom:Product.CategoryField.TypeID") == "15") 1708 { 1709 @RenderFieldItem(categoryField.GetString("Ecom:Product.CategoryField.Label"), categoryField.GetString("Ecom:Product.CategoryField.OptionLabel"), viewType); 1710 } 1711 else if (categoryField.GetString("Ecom:Product.CategoryField.TypeID") == "8") 1712 { 1713 @RenderFieldItem(categoryField.GetString("Ecom:Product.CategoryField.Label"), fieldValue, viewType, "link"); 1714 } 1715 else 1716 { 1717 @RenderFieldItem(categoryField.GetString("Ecom:Product.CategoryField.Label"), fieldValue, viewType); 1718 } 1719 } 1720 } 1721 } 1722 } 1723 1724 @helper RenderProductDownloads(string layout) 1725 { 1726 string viewType = Pageview.AreaSettings.GetItem("ProductPage").GetString("DownloadsView") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("DownloadsView").SelectedValue : "grid"; 1727 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("DownloadsLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 1728 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("DownloadsLayout").SelectedValue == "Ribbon" ? "u-padding--lg" : ""; 1729 1730 <div class="product__section @ribbonClasses dw-mod"> 1731 <div class="center-container @ribbonSubClasses dw-mod"> 1732 @if (layout == "Section") 1733 { 1734 <h2>@Translate("Downloads")</h2> 1735 } 1736 1737 @if (viewType != "table") 1738 { 1739 <div class="grid grid--external-bleed-x u-margin-bottom--lg"> 1740 @RenderProductDownloadsFields(downloadDocuments, viewType) 1741 </div> 1742 } 1743 else 1744 { 1745 string tableWidth = layout != "MainInformation" ? "grid__col-md-6" : "grid__col-md-12"; 1746 1747 <div class="grid grid--external-bleed-x u-margin-bottom--lg"> 1748 <div class="@tableWidth grid__col-sm-12 grid__col-xs-12"> 1749 <table class="table--no-top-border"> 1750 @RenderProductDownloadsFields(downloadDocuments, viewType) 1751 </table> 1752 </div> 1753 </div> 1754 } 1755 </div> 1756 </div> 1757 } 1758 1759 @helper RenderProductDownloadsFields(List<LoopItem> fieldsLoop, string viewType) 1760 { 1761 foreach (LoopItem document in fieldsLoop) 1762 { 1763 string fieldValue; 1764 if (!string.IsNullOrEmpty(document.GetString("Document.FullPath"))) 1765 { 1766 fieldValue = document.GetString("Product.CustomField.Value.Clean"); 1767 @RenderFieldItem(fieldValue, document.GetString("Document.FullPath"), viewType, "download") 1768 } 1769 1770 if (document.GetString("Ecom:Product.CategoryField.TypeID") == "9") 1771 { 1772 fieldValue = document.GetString("Ecom:Product.CategoryField.Value"); 1773 @RenderFieldItem(fieldValue, fieldValue, viewType, "download") 1774 } 1775 1776 if (!string.IsNullOrEmpty(document.GetString("Ecom:Product:Detail.Image.Clean"))) 1777 { 1778 fieldValue = document.GetString("Ecom:Product:Detail.Image.Clean"); 1779 var fileName = System.IO.Path.GetFileName(fieldValue); 1780 @RenderFieldItem(document.GetString("Ecom:Product:Detail.Image.Clean"), document.GetString("Ecom:Product:Detail.Image.Clean"), viewType, "download") 1781 } 1782 } 1783 } 1784 1785 @helper RenderFieldItem(string name, string value, string viewType, string fieldType = "clean") 1786 { 1787 if (viewType != "table") 1788 { 1789 string fieldColumns = viewType == "list" ? "12" : "4"; 1790 <div class="grid__col-md-@fieldColumns u-margin-bottom"> 1791 @if (fieldType == "download") 1792 { 1793 <div> 1794 @RenderFieldItemContent(name, value, fieldType) 1795 </div> 1796 } 1797 else 1798 { 1799 <div class="u-bold"> 1800 @name 1801 </div> 1802 <div> 1803 @RenderFieldItemContent(name, value, fieldType) 1804 </div> 1805 } 1806 </div> 1807 } 1808 else 1809 { 1810 <tr> 1811 @if (fieldType == "download") 1812 { 1813 <td colspan="2"> 1814 @RenderFieldItemContent(name, value, fieldType) 1815 </td> 1816 } 1817 else 1818 { 1819 <td class="u-bold">@name</td> 1820 <td> 1821 @RenderFieldItemContent(name, value, fieldType) 1822 </td> 1823 } 1824 </tr> 1825 } 1826 } 1827 1828 @helper RenderFieldItemContent(string name, string value, string fieldType = "clean") 1829 { 1830 if (fieldType == "link") 1831 { 1832 <a target="_blank" href="@value"> 1833 @if (isImage(value)) 1834 { 1835 @getIconForFile(value) 1836 } 1837 else 1838 { 1839 @value 1840 } 1841 </a> 1842 } 1843 else if (fieldType == "download") 1844 { 1845 FileInfo info = new FileInfo(Dynamicweb.Core.SystemInformation.MapPath(value)); 1846 1847 if (info.Exists) 1848 { 1849 <div class="grid grid--no-wrap"> 1850 <a href="@name" download title="@Translate("Download")" class="product__document u-min-w120px u-ta-center dw-mod">@getIconForFile(value)</a> 1851 <div class="product__document-info dw-mod"> 1852 <a href="@name" download title="@Translate("Download")" class="product__document dw-mod">@Path.GetFileName(value)</a> 1853 <small class="u-block u-margin-top">@ConvertBytes(info.Length)</small> 1854 </div> 1855 </div> 1856 } 1857 } 1858 else 1859 { 1860 @value 1861 } 1862 } 1863 1864 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 1865 @using Dynamicweb.Core 1866 @using System 1867 @using System.Web 1868 @using System.Collections.Generic 1869 @using Dynamicweb.Rapido.Blocks 1870 @using Smartpage.CookieManager 1871 1872 @functions{ 1873 BlocksPage productVideoPage = BlocksPage.GetBlockPage("Product"); 1874 } 1875 1876 @{ 1877 string videosLayout = Pageview.AreaSettings.GetItem("ProductPage").GetString("VideosLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("VideosLayout").SelectedValue : "Section"; 1878 videosLayout = videosLayout == "Ribbon" || string.IsNullOrEmpty(videosLayout) ? "Section" : videosLayout; 1879 1880 int videosCount = 0; 1881 1882 foreach (LoopItem detailField in GetLoop("Details")) 1883 { 1884 if (detailField.GetString("Ecom:Product:Detail.Text").IndexOf("iframe") != -1 && detailField.GetString("Ecom:Product:Detail.Text").IndexOf("youtube.com/embed") != -1) 1885 { 1886 videosCount++; 1887 } 1888 if (detailField.GetString("Ecom:Product:Detail.Text").IndexOf("iframe") != -1 && detailField.GetString("Ecom:Product:Detail.Text").IndexOf("vimeo.com") != -1) 1889 { 1890 videosCount++; 1891 } 1892 } 1893 1894 if (videosCount > 0 && videosLayout != "hide") 1895 { 1896 Block detailsVideos = new Block() 1897 { 1898 Name = videosLayout != "MainInformation" ? Translate("Videos") : "", 1899 Id = "Videos", 1900 SortId = 60, 1901 Template = ProductVideos(videosCount, videosLayout), 1902 Design = new Design 1903 { 1904 Size = "12", 1905 RenderType = RenderType.Column, 1906 HidePadding = true 1907 } 1908 }; 1909 productVideoPage.Add(videosLayout, detailsVideos); 1910 } 1911 } 1912 1913 @helper ProductVideos(int videosCount, string layout) 1914 { 1915 string videoColumn = "12"; 1916 videoColumn = videosCount == 2 ? "6" : videoColumn; 1917 videoColumn = videosCount > 2 ? "4" : videoColumn; 1918 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("VideosLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 1919 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("VideosLayout").SelectedValue == "Ribbon" ? "u-padding--lg" : ""; 1920 bool showVideo = new CookieBot().Statistics; 1921 1922 <div class="product__section @ribbonClasses dw-mod"> 1923 <div class="center-container @ribbonSubClasses dw-mod"> 1924 @if (layout == "Section") 1925 { 1926 <h2>@Translate("Videos")</h2> 1927 } 1928 1929 <div class="grid grid--external-bleed-x u-margin-bottom--lg"> 1930 @foreach (LoopItem detailField in GetLoop("Details")) 1931 { 1932 if (detailField.GetString("Ecom:Product:Detail.Text").IndexOf("iframe") != -1 && detailField.GetString("Ecom:Product:Detail.Text").IndexOf("youtube.com/embed") != -1 || detailField.GetString("Ecom:Product:Detail.Text").IndexOf("iframe") != -1 && detailField.GetString("Ecom:Product:Detail.Text").IndexOf("vimeo.com") != -1 && showVideo) 1933 { 1934 <div class="grid__col-md-@videoColumn grid__col-lg-@videoColumn"> 1935 <div class="video-wrapper"> 1936 @detailField.GetString("Ecom:Product:Detail.Text") 1937 </div> 1938 </div> 1939 } 1940 } 1941 </div> 1942 </div> 1943 </div> 1944 } 1945 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 1946 @using Dynamicweb.Core 1947 @using System 1948 @using System.Web 1949 @using System.Collections.Generic 1950 @using Dynamicweb.Rapido.Blocks 1951 1952 @functions{ 1953 BlocksPage productRelatedPage = BlocksPage.GetBlockPage("Product"); 1954 } 1955 1956 @{ 1957 bool onlyPreview = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("OnlyPreviewForAnonymous") && Pageview.User == null; 1958 bool gridViewShowViewButton = Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetString("ShowViewButton") != null ? Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetBoolean("ShowViewButton") : true; 1959 bool gridViewShowStock = Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetString("ShowStockAndShipping") != null ? Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetBoolean("ShowStockAndShipping") : true; 1960 1961 string relatedProductsLayout = Pageview.AreaSettings.GetItem("ProductPage").GetList("RelatedProductsLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("RelatedProductsLayout").SelectedValue : "Section"; 1962 relatedProductsLayout = relatedProductsLayout == "Ribbon" || string.IsNullOrEmpty(relatedProductsLayout) ? "Section" : relatedProductsLayout; 1963 bool relatedOnlyPreview = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("OnlyPreviewForAnonymous") && Pageview.User == null; 1964 bool relatedPointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly"); 1965 1966 int relatedProductsPageSize = 4; 1967 int relatedProductsColumnWidth = 3; 1968 1969 if (Pageview.Device.ToString() == "Mobile") 1970 { 1971 relatedProductsPageSize = 1; 1972 relatedProductsColumnWidth = 12; 1973 } 1974 1975 if (Pageview.Device.ToString() == "Tablet") 1976 { 1977 relatedProductsPageSize = 3; 1978 relatedProductsColumnWidth = 4; 1979 } 1980 1981 if (relatedProductsLayout != "hide") 1982 { 1983 foreach (LoopItem relatedGroup in GetLoop("ProductRelatedGroups")) 1984 { 1985 // Replacement products - only shown if product stock is 0 and discontinued 1986 var relatedGroupReplacementGroupId = Pageview.AreaSettings.GetItem("Custom").GetItem("CustomSettings").GetList("SpReplacementProducts").SelectedValue; 1987 if (relatedGroupReplacementGroupId == relatedGroup.GetString("Ecom:Product:RelatedGroup.GroupID") && !(GetInteger("Ecom:Product.Stock") == 0 && GetBoolean("Ecom:Product:Field.Discontinued"))) 1988 { 1989 continue; 1990 } 1991 1992 string relatedGroupId = ToPascalCase(relatedGroup.GetString("Ecom:Product:RelatedGroup.Name")); 1993 string SpRelatedGroupId = relatedGroup.GetString("Ecom:Product:RelatedGroup.GroupID"); 1994 string relatedGroupName = relatedProductsLayout != "maininformation" ? relatedGroup.GetString("Ecom:Product:RelatedGroup.Name") : ""; 1995 string baseFeedPageUrl = "/Default.aspx?ID=" + GetPageIdByNavigationTag("RelatedProductsFeed") + "&PageSize=" + relatedProductsPageSize; 1996 string relatedFeed = baseFeedPageUrl + "&" + relatedGroupId + "=" + GetString("Ecom:Product.ID") + "&GroupName=" + relatedGroupId + "&feed=true"; 1997 1998 Block detailsRelated = new Block() 1999 { 2000 Name = relatedGroupName, 2001 Id = relatedGroupId, 2002 SortId = 70, 2003 Template = RenderRelatedProducts(relatedGroupName, relatedGroupId, relatedFeed, relatedProductsLayout, SpRelatedGroupId), 2004 Design = new Design 2005 { 2006 Size = "12", 2007 RenderType = RenderType.Column, 2008 HidePadding = true 2009 } 2010 }; 2011 2012 productRelatedPage.Add(relatedProductsLayout, detailsRelated); 2013 } 2014 } 2015 } 2016 2017 @helper RenderRelatedProducts(string name, string groupName, string relatedFeedUrl, string layout, string GroupID) 2018 { 2019 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("RelatedProductsLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 2020 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("RelatedProductsLayout").SelectedValue == "Ribbon" ? "u-padding--lg" : ""; 2021 var alternativeProductsGroupId = Pageview.AreaSettings.GetItem("Custom").GetItem("CustomSettings").GetList("SpAlternativeProducts").SelectedValue; 2022 var replacementProductsGroupId = Pageview.AreaSettings.GetItem("Custom").GetItem("CustomSettings").GetList("SpReplacementProducts").SelectedValue; 2023 2024 2025 2026 if (alternativeProductsGroupId != GroupID && replacementProductsGroupId != GroupID) 2027 { 2028 <div class="product__section @ribbonClasses dw-mod"> 2029 <div class="center-container @ribbonSubClasses dw-mod"> 2030 @if (layout == "Section") 2031 { 2032 <h2 class="u-bold u-ta-center">@name</h2> 2033 } 2034 2035 <div class="js-handlebars-root" id="ProductList_@groupName" data-template="ProductContainer" data-pre-render-template="ProductPreRenderContainer" data-json-feed="@relatedFeedUrl" data-preloader="minimal"></div> 2036 </div> 2037 </div> 2038 } 2039 2040 } 2041 2042 @helper RenderRelatedProductsMini(string name, string groupId, string relatedFeedUrl) 2043 { 2044 <div class="js-handlebars-root" id="ProductList_@groupId" data-template="ProductContainerMini" data-pre-render-template="ProductPreRenderContainer" data-json-feed="@relatedFeedUrl" data-preloader="minimal"></div> 2045 } 2046 2047 @* Script templates for related products *@ 2048 <script id="ProductPreRenderContainer" type="text/x-template"> 2049 <div class="u-h600px u-full-width"> 2050 <div class="grid"> 2051 <div class="grid__col-12"> 2052 <div class="pre-render-element pre-render-element--md"></div> 2053 </div> 2054 </div> 2055 </div> 2056 </script> 2057 2058 <script id="ProductContainer" type="text/x-template"> 2059 {{#.}} 2060 <div class="u-full-width"> 2061 <div class="grid"> 2062 <div class="grid__col-45px grid__col--bleed-x"> 2063 <div class="grid__cell grid__cell--align-middle-left"> 2064 <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> 2065 </div> 2066 </div> 2067 <div class="grid__col-auto grid__col--bleed-x"> 2068 <div id="ProductsContainer" data-template="ProductGridItemContainer" class="grid product-list dw-mod" data-save-cookie="true"> 2069 {{#ProductsContainer}} 2070 <div id="Product{{productId}}" class="grid__col-@relatedProductsColumnWidth product-list__grid-item dw-mod"> 2071 {{#Product}} 2072 @if (useGoogleTagManager) 2073 { 2074 <text>{{{googleEnchantImpression 'Related products' currency googleImpression}}}</text> 2075 } 2076 <div class="grid__cell product-list__grid-item__image dw-mod {{noImage}}"> 2077 <div class="stickers-container dw-mod"> 2078 {{#Stickers}} 2079 {{>Sticker}} 2080 {{/Stickers}} 2081 </div> 2082 <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;image={{image}}" alt="{{name}}" /></a> 2083 </div> 2084 2085 <div class="grid__cell product-list__grid-item__price-info related-price-info {{shortGridInfo}} dw-mod"> 2086 <a href="{{link}}" onclick="Scroll.SavePosition(event)" title="{{name}}"><h6 class="u-condensed-text">{{name}}</h6></a> 2087 {{#if showProductNumber}} 2088 <div class="item-number dw-mod">{{number}}</div> 2089 {{/if}} 2090 @if (!relatedOnlyPreview) 2091 { 2092 if (relatedPointShopOnly) 2093 { 2094 <text> 2095 {{#if havePointPrice}} 2096 <div>{{points}} @Translate("points")</div> 2097 {{else}} 2098 @Translate("Not available") 2099 {{/if}} 2100 </text> 2101 } 2102 else 2103 { 2104 <text> 2105 <div class="price price--product-list dw-mod">{{price}}</div> 2106 <div class="before-price {{onSale}} dw-mod">{{discount}}</div> 2107 {{#if standardOrderQuantity}} 2108 <div>@Translate("Kolli"): {{standardOrderQuantity}}</div> 2109 {{/if}} 2110 </text> 2111 } 2112 } 2113 </div> 2114 2115 <div class="product-list__grid-item__footer dw-mod"> 2116 2117 @if (gridViewShowViewButton) 2118 { 2119 <div class="u-ta-center"> 2120 <a href="{{link}}" id="CartButton_{{id}}" class="btn btn--primary btn--arrow btn--full u-no-margin dw-mod">@Translate("View")</a> 2121 </div> 2122 } 2123 2124 @if (!onlyPreview && gridViewShowStock) 2125 { 2126 <div> 2127 <span class="stock-icon {{stockState}} u-no-margin dw-mod" title="{{stockText}}"></span> {{stockText}}{{deliveryText}} 2128 </div> 2129 } 2130 2131 </div> 2132 {{/Product}} 2133 </div> 2134 {{/ProductsContainer}} 2135 </div> 2136 </div> 2137 <div class="grid__col-45px grid__col--bleed-x"> 2138 <div class="grid__cell grid__cell--align-middle-right"> 2139 <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> 2140 </div> 2141 </div> 2142 </div> 2143 </div> 2144 {{/.}} 2145 </script> 2146 2147 <script id="ProductContainerMini" type="text/x-template"> 2148 {{#.}} 2149 <div class="u-full-width"> 2150 <div class="grid"> 2151 <div class="grid__col-45px grid__col--bleed-x"> 2152 <div class="grid__cell grid__cell--align-middle-left"> 2153 <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> 2154 </div> 2155 </div> 2156 <div class="grid__col-auto grid__col--bleed-x"> 2157 <div id="ProductsContainer" class="grid product-list dw-mod"> 2158 {{#ProductsContainer}} 2159 <div id="Product{{productId}}" class="grid__col-@relatedProductsColumnWidth product-list__grid-item dw-mod"> 2160 {{#Product}} 2161 @if (useGoogleTagManager) 2162 { 2163 <text>{{{googleEnchantImpression 'Related products' currency googleImpression}}}</text> 2164 } 2165 <div class="grid__cell product-list__grid-item__image dw-mod {{noImage}}"> 2166 <div class="stickers-container dw-mod"> 2167 {{#Stickers}} 2168 {{>Sticker}} 2169 {{/Stickers}} 2170 </div> 2171 <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> 2172 </div> 2173 2174 <div class="grid__cell product-list__grid-item__price-info {{shortGridInfo}} dw-mod"> 2175 <a href="{{link}}" onclick="Scroll.SavePosition(event)" title="{{name}}"><h6 class="u-condensed-text">{{name}}</h6></a> 2176 {{#if showProductNumber}} 2177 <div class="item-number dw-mod">{{number}}</div> 2178 {{/if}} 2179 @if (!relatedOnlyPreview) 2180 { 2181 if (relatedPointShopOnly) 2182 { 2183 <text> 2184 {{#if havePointPrice}} 2185 <div>{{points}} @Translate("points")</div> 2186 {{else}} 2187 @Translate("Not available") 2188 {{/if}} 2189 </text> 2190 } 2191 else 2192 { 2193 <div>{{price}}</div> 2194 <div class="before-price {{onSale}} dw-mod">{{discount}}</div> 2195 } 2196 } 2197 </div> 2198 {{/Product}} 2199 </div> 2200 {{/ProductsContainer}} 2201 </div> 2202 </div> 2203 <div class="grid__col-45px grid__col--bleed-x"> 2204 <div class="grid__cell grid__cell--align-middle-right"> 2205 <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> 2206 </div> 2207 </div> 2208 </div> 2209 </div> 2210 {{/.}} 2211 </script> 2212 2213 <script id="Sticker" type="text/x-template"> 2214 <div class="stickers-container__tag {{className}} dw-mod">{{text}}</div> 2215 </script> 2216 2217 @* Favorites templates *@ 2218 2219 <script id="FavoriteTemplate" type="text/x-template"> 2220 <div class="favorites-list u-ta-left"> 2221 <label for="FavoriteTrigger_{{id}}" class="u-no-margin"><i class="{{favoriteIcon}} fa-1_5x"></i></label> 2222 <input type="checkbox" id="FavoriteTrigger_{{id}}" class="dropdown-trigger" /> 2223 <div class="dropdown dropdown--absolute-position"> 2224 <div class="dropdown__content dropdown__content--show-left dropdown__content--padding u-w220px dw-mod"> 2225 <ul class="list list--clean dw-mod"> 2226 {{#FavoriteLists}} 2227 {{>FavoriteListItem}} 2228 {{/FavoriteLists}} 2229 </ul> 2230 </div> 2231 <label class="dropdown-trigger-off" for="FavoriteTrigger_{{id}}"></label> 2232 </div> 2233 </div> 2234 </script> 2235 2236 <script id="FavoriteListItem" type="text/x-template"> 2237 <li> 2238 <a href="{{link}}" class="list__link u-no-underline dw-mod" onclick="{{facebookPixelAction}}"><i class="{{favoriteIcon}}"></i> {{name}}</a> 2239 </li> 2240 </script> 2241 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 2242 @using Dynamicweb.Core 2243 @using System 2244 @using System.Web 2245 @using System.Collections.Generic 2246 @using Dynamicweb.Rapido.Blocks 2247 2248 @functions { 2249 BlocksPage productVariantsPage = BlocksPage.GetBlockPage("Product"); 2250 } 2251 2252 @{ 2253 bool renderVariantsAsProducts = Pageview.AreaSettings.GetItem("ProductPage").GetString("RenderVariantsAsProductList") != null && GetInteger("Ecom:Product.VariantCount") > 1 ? Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("RenderVariantsAsProductList") : false; 2254 bool variantsOnlyPreview = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("OnlyPreviewForAnonymous") && Pageview.User == null; 2255 string variantsListPageSize = HttpContext.Current.Request.QueryString.Get("PageSize") != null ? HttpContext.Current.Request.QueryString.Get("PageSize") : "30"; 2256 string variantsFeedUrl = "/Default.aspx?ID=" + GetPageIdByNavigationTag("ProductsPage") + "&PageSize=" + variantsListPageSize + "&MainProductID=" + GetString("Ecom:Product.ID") + "&OnlyShowVariants=true&feed=true"; 2257 string variantsCartIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetString("CartIcon") != null ? Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon").SelectedValue : "fas fa-shopping-cart"; 2258 bool variantsPointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly"); 2259 2260 string variantsListLayout = Pageview.AreaSettings.GetItem("ProductPage").GetString("VariantsListLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("VariantsListLayout").SelectedValue : "Section"; 2261 variantsListLayout = variantsListLayout == "Ribbon" ? "Section" : variantsListLayout; 2262 2263 2264 if (renderVariantsAsProducts && variantsListLayout != "hide") 2265 { 2266 Block detailsVariantsList = new Block() 2267 { 2268 Name = variantsListLayout != "MainInformation" ? Translate("Variants list") : "", 2269 Id = "VariantsList", 2270 SortId = 20, 2271 Template = RenderVariantsProductList(variantsListLayout), 2272 Design = new Design 2273 { 2274 Size = "12", 2275 RenderType = RenderType.Column, 2276 HidePadding = true 2277 } 2278 }; 2279 productVariantsPage.Add(variantsListLayout, detailsVariantsList); 2280 } 2281 } 2282 2283 @helper RenderVariantsProductList(string layout) 2284 { 2285 string variantsListPageSize = HttpContext.Current.Request.QueryString.Get("PageSize") != null ? HttpContext.Current.Request.QueryString.Get("PageSize") : "30"; 2286 string variantsFeedUrl = "/Default.aspx?ID=" + GetPageIdByNavigationTag("ProductsPage") + "&PageSize=" + variantsListPageSize + "&MainProductID=" + GetString("Ecom:Product.ID") + "&OnlyShowVariants=true&feed=true"; 2287 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("VariantsListLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 2288 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("VariantsListLayout").SelectedValue == "Ribbon" ? "u-padding--lg" : ""; 2289 2290 <div class="product__section @ribbonClasses dw-mod"> 2291 <div class="center-container @ribbonSubClasses dw-mod"> 2292 @if (layout == "Section") { 2293 <h2>@Translate("Variants")</h2> 2294 } 2295 2296 <div class="js-handlebars-root" id="VariantsListRoot" data-template="VariantProductsContainer" data-json-feed="@variantsFeedUrl" data-preloader="minimal"></div> 2297 </div> 2298 </div> 2299 } 2300 2301 2302 @* Script templates for variant products *@ 2303 2304 <script id="VariantProductsContainer" type="text/x-template"> 2305 {{#.}} 2306 <div class=""> 2307 <table id="VariantsProductsContainer" class="table u-position-relative dw-mod"> 2308 <thead> 2309 <tr> 2310 <td width="75">&nbsp;</td> 2311 <td>@Translate("Product")</td> 2312 {{#AvailableCustomFields}} 2313 {{>TableFieldNameTemplate}} 2314 {{/AvailableCustomFields}} 2315 @if (Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("RenderVariantGroupsInTable")) { 2316 foreach (LoopItem variantgroup in GetLoop("VariantGroups")) 2317 { 2318 <td>@variantgroup.GetString("Ecom:VariantGroup.Name")</td> 2319 } 2320 } 2321 <td width="360">&nbsp;</td> 2322 </tr> 2323 </thead> 2324 2325 <tbody id="VariantProductListContainer" data-template="VariantProductItemContainer" data-save-cookie="true"> 2326 {{#ProductsContainer}} 2327 {{>VariantProductItemContainer}} 2328 {{/ProductsContainer}} 2329 </tbody> 2330 </table> 2331 </div> 2332 2333 <div class="grid"> 2334 <div class="grid__col-12 grid__col--bleed-y"> 2335 <button type="button" id="LoadMoreButton" class="btn btn--primary 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> 2336 </div> 2337 </div> 2338 {{/.}} 2339 </script> 2340 2341 <script id="VariantProductItemContainer" type="text/x-template"> 2342 {{#.}} 2343 <tr id="VariantProduct{{id}}" data-template="VariantProductItem" data-preloader="overlay" style="z-index: {{zIndex}}"> 2344 {{#Product}} 2345 {{>VariantProductItem}} 2346 {{/Product}} 2347 </tr> 2348 {{/.}} 2349 </script> 2350 2351 <script id="VariantProductItem" type="text/x-template"> 2352 {{#.}} 2353 <td width="75"> 2354 <div class="lightbox u-hidden-xxs"> 2355 <a href="{{link}}" onclick="Scroll.SavePosition(event)"> 2356 <img class="lightbox__image {{noImage}}" src="/Admin/Public/GetImage.ashx?width=220&amp;height=220&amp;crop=5&amp;Compression=75&amp;image={{image}}" alt="{{name}}" /> 2357 <div class="u-margin-right {{noImage}}"> 2358 <img src="/Admin/Public/GetImage.ashx?width=75&amp;height=55&amp;crop=5&FillCanvas=true&amp;Compression=75&amp;image={{image}}" alt="{{name}}" /> 2359 </div> 2360 </a> 2361 </div> 2362 </td> 2363 <td class="u-va-middle"> 2364 <a href="{{link}}" onclick="Scroll.SavePosition(event)" title="{{name}}"><h6 class="u-no-margin">{{name}}</h6></a> 2365 <div class="item-number item-number--compressed dw-mod"> 2366 {{#if showProductNumber}}{{number}}{{/if}} 2367 @if (!variantsOnlyPreview) 2368 { 2369 <span> 2370 <span class="stock-icon {{stockState}} u-no-margin dw-mod" title="{{stockText}}"></span> {{stockText}}{{deliveryText}} 2371 </span> 2372 } 2373 else 2374 { 2375 <div class="grid__cell-footer stickers-container stickers-container--block dw-mod"> 2376 {{#Stickers}} 2377 {{>MiniSticker}} 2378 {{/Stickers}} 2379 </div> 2380 } 2381 </div> 2382 </td> 2383 {{#CustomFields}} 2384 {{>TableFieldValueTemplate}} 2385 {{/CustomFields}} 2386 @if (Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("RenderVariantGroupsInTable")) 2387 { 2388 <text> 2389 {{#VariantSelectionNames}} 2390 {{>TableFieldNameTemplate}} 2391 {{/VariantSelectionNames}} 2392 </text> 2393 } 2394 <td width="320" class="u-va-middle"> 2395 @if (variantsOnlyPreview) 2396 { 2397 <div class="u-hidden-sm"> 2398 <div class="u-full-width u-ta-right u-padding-right"> 2399 <div class="before-price {{onSale}} before-price--micro dw-mod">{{discount}}</div> 2400 <div class="price price--product-list price--micro dw-mod">{{price}}</div> 2401 </div> 2402 </div> 2403 } 2404 else 2405 { 2406 <div class="grid grid--align-center grid--justify-end"> 2407 <div class="favorites u-margin-right {{hasVariants}} dw-mod" {{hasVariants}}> 2408 {{#Favorite}} 2409 {{>FavoriteTemplate}} 2410 {{/Favorite}} 2411 </div> 2412 <div class="u-margin-right"> 2413 <input type="checkbox" id="UnitOptions_{{id}}" class="dropdown-trigger" /> 2414 <div class="dropdown u-w120px {{hasUnits}} dw-mod"> 2415 <label class="dropdown__header dropdown__btn dw-mod" for="UnitOptions_{{id}}">{{unitName}}</label> 2416 <div id="unitOptions" class="dropdown__content dw-mod"> 2417 {{#unitOptions}} 2418 {{>UnitOption}} 2419 {{/unitOptions}} 2420 </div> 2421 <label class="dropdown-trigger-off" for="UnitOptions_{{id}}"></label> 2422 </div> 2423 <input type="hidden" value="{{unitId}}" name="Unit{{id}}" id="Unit_{{id}}" /> 2424 <input type="hidden" value="{{variantid}}" name="VariantID{{id}}" id="Variant_{{id}}" /> 2425 </div> 2426 <div class="u-margin-right u-hidden-xs u-hidden-xxs"> 2427 @if (variantsPointShopOnly) 2428 { 2429 <text> 2430 {{#if canBePurchasedWithPoints}} 2431 <div class="price price--product-list price--micro dw-mod">{{points}} @Translate("points")</div> 2432 {{else}} 2433 {{#if havePointPrice}} 2434 <small class="help-text u-no-margin u-margin-top">@Translate("Not enough points to buy this")</small> 2435 {{else}} 2436 <small class="help-text u-no-margin u-margin-top">@Translate("Not available")</small> 2437 {{/if}} 2438 {{/if}} 2439 </text> 2440 } 2441 else 2442 { 2443 <div class="before-price before-price--micro {{onSale}} dw-mod">{{discount}}</div> 2444 <div class="price price--condensed price--product-list dw-mod">{{price}}</div> 2445 } 2446 </div> 2447 @if (variantsPointShopOnly) 2448 { 2449 <div> 2450 <button {{#unless canBePurchasedWithPoints}} disabled{{/unless}} type="button" 2451 id="CartButton_{{id}}" 2452 class="btn btn--primary btn--condensed u-no-margin dw-mod js-cart-btn {{#unless canBePurchasedWithPoints}}disabled js-stay-disabled{{/unless}}" 2453 name="CartCmd" 2454 value="addWithPoints" 2455 onclick="Cart.AddToCart(event, { 2456 id: '{{productId}}', 2457 variantId: '{{variantid}}', 2458 unitId: '{{unitId}}', 2459 quantity: 1, 2460 buyForPoints: true, 2461 productInfo: {{productInfo}} 2462 })"> 2463 <i class="@variantsCartIcon"></i> 2464 </button> 2465 </div> 2466 } 2467 else 2468 { 2469 <div> 2470 <input type="number" class="u-w80px u-no-margin u-margin-right" id="Quantity_{{id}}" name="Quantity{{id}}" value="1" min="1"> 2471 </div> 2472 <div> 2473 <button type="button" id="CartButton_{{id}}" class="btn btn--primary btn--condensed u-no-margin dw-mod" name="submit" 2474 onclick="Cart.AddToCart(event, { 2475 id: '{{productId}}', 2476 variantId: '{{variantid}}', 2477 unitId: '{{unitId}}', 2478 quantity: document.getElementById('Quantity_{{id}}').value, 2479 productInfo: {{productInfo}} 2480 });"> 2481 <i class="@variantsCartIcon"></i> 2482 </button> 2483 </div> 2484 } 2485 </div> 2486 } 2487 </td> 2488 {{/.}} 2489 </script> 2490 2491 <script id="TableFieldNameTemplate" type="text/x-template"> 2492 <td class="u-va-middle">{{name}}</td> 2493 </script> 2494 2495 <script id="TableFieldValueTemplate" type="text/x-template"> 2496 <td class="u-va-middle">{{value}}</td> 2497 </script> 2498 2499 <script id="MiniSticker" type="text/x-template"> 2500 <div class="stickers-container__tag stickers-container__tag--micro {{className}} dw-mod">{{text}}</div> 2501 </script> 2502 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 2503 @using Dynamicweb.Core 2504 @using System 2505 @using System.Web 2506 @using System.Collections.Generic 2507 @using Dynamicweb.Rapido.Blocks 2508 2509 @{ 2510 BlocksPage customProductBlocks = BlocksPage.GetBlockPage("Product"); 2511 2512 customProductBlocks.Add("MainInformation", new Block() 2513 { 2514 Id = "ProductConcepts", 2515 SortId = 35, 2516 Template = RenderProductConceptsCustom() 2517 }); 2518 } 2519 2520 @helper RenderProductConceptsCustom() 2521 { 2522 // note: don't include .introduction-concepts element, if product concepts is not used or empty. 2523 var concepts = GetLoop("Smartpage:Product.ConceptLoop"); 2524 if (concepts.Any()) 2525 { 2526 <div class="introduction-concepts"> 2527 @foreach (var concept in concepts) 2528 { 2529 if(!string.IsNullOrEmpty(concept.GetString("Concept"))){ 2530 2531 <a href="/Default.aspx?ID=@concept.GetString("PageId")" class="btn btn--primary dw-mod"> 2532 <i class="fac fa-book"></i><span>@concept.GetString("Concept")</span><i class="fa fa-angle-right u-inline"></i> 2533 </a> 2534 } 2535 } 2536 </div> 2537 } 2538 } 2539 2540 <script id="PriceList" type="text/x-template"> 2541 {{#if Prices}} 2542 {{#ifCond variantSelected "!==" "False"}} 2543 <div class="priceList__prices dw-mod"> 2544 {{#Prices}} 2545 <div class="priceList__price dw-mod"> 2546 <div> 2547 <span>{{Quantity}}x {{UnitText}}</span> 2548 </div> 2549 <div> 2550 <div class="before-price {{onSale}} dw-mod">{{PriceBeforeDiscount}}</div> 2551 <div class="price price--product-list dw-mod">{{PriceAfterDiscount}}</div> 2552 </div> 2553 </div> 2554 {{/Prices}} 2555 </div> 2556 {{/ifCond}} 2557 {{/if}} 2558 </script> 2559 2560 2561 2562 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 2563 2564 @using Dynamicweb.Rapido.Blocks 2565 2566 @{ 2567 BlocksPage productsPageRaptor = BlocksPage.GetBlockPage("Product"); 2568 2569 string relatedProductsLayoutRaptor = Pageview.AreaSettings.GetItem("ProductPage").GetList("RelatedProductsLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("RelatedProductsLayout").SelectedValue : "Section"; 2570 relatedProductsLayoutRaptor = relatedProductsLayoutRaptor == "Ribbon" || string.IsNullOrEmpty(relatedProductsLayoutRaptor) ? "Section" : relatedProductsLayoutRaptor; 2571 2572 if (relatedProductsLayoutRaptor != "hide") 2573 { 2574 productsPageRaptor.Add(relatedProductsLayout, new Block() 2575 { 2576 Id = "RaptorRelated", 2577 Name = "RaptorRelated", 2578 SortId = 10, 2579 Template = RenderRaptorRelatedItems() 2580 }); 2581 } 2582 } 2583 2584 @helper RenderRaptorRelatedItems() 2585 { 2586 bool onlyPreview = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("OnlyPreviewForAnonymous") && Pageview.User == null; 2587 bool hideRecommendations = !string.IsNullOrWhiteSpace(Dynamicweb.Context.Current.Request.QueryString["ListID"]) || !string.IsNullOrWhiteSpace(Dynamicweb.Context.Current.Request.QueryString["Search"]); 2588 var uri = Dynamicweb.Context.Current.Request.Url; 2589 2590 var url = uri.AbsoluteUri; 2591 if (url.Contains("ID")) 2592 { 2593 url += "&feed=true"; 2594 } 2595 else 2596 { 2597 url += "?feed=true"; 2598 } 2599 2600 <div class="grid grid--external-bleed grid--align-content-start js-handlebars-root" id="productList" data-template="RecommendationContainer" data-pre-render-template="ProductPreRenderContainer" data-json-feed="@url" data-preloader="overlay"></div> 2601 2602 <script id="RecommendationContainer" type="text/x-template"> 2603 @if (!hideRecommendations) 2604 { 2605 <text> 2606 {{RecommendedProducts.length}} 2607 {{#.}} 2608 {{#ifCond RecommendedProducts.length ">" "0"}} 2609 <div class="grid reccomendations"> 2610 <span class="u-bold u-ta-center reccomendation-header">@Translate("Recommendations")</span> 2611 {{#RecommendedProducts}} 2612 {{>RecommendationContainerItem}} 2613 {{/RecommendedProducts}} 2614 </div> 2615 {{/ifCond}} 2616 {{/.}} 2617 </text> 2618 } 2619 </script> 2620 2621 <script id="RecommendationContainerItem" type="text/x-template"> 2622 2623 <div class="reccomendation grid__col-sm-2 grid__col-xs-12 dw-mod"> 2624 <div id="RecommendProductProduct{{id}}" class="reccomendation-container product-list__grid-item dw-mod js-product recommended-product"> 2625 <input type="hidden" name="ProductLoopCounter{{id}}" value="{{id}}"> 2626 <input type="hidden" name="ProductID{{id}}" value="{{productId}}"> 2627 <input type="hidden" value="" name="VariantID{{id}}" id="RecommendVariant_{{id}}"> 2628 2629 <div class="grid__cell-footer stickers-container dw-mod"> 2630 {{#Stickers}} 2631 {{>MiniStickerRelated}} 2632 {{/Stickers}} 2633 </div> 2634 2635 <div class="reccomendation-image grid__cell product-list__grid-item__image dw-mod "> 2636 <a href="{{link}}" onclick="Scroll.SavePosition(event);" title="{{name}}"> 2637 <img class="grid__cell-img--centered u-padding b-lazy b-loaded" 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}}"> 2638 </a> 2639 </div> 2640 2641 <div class="reccomendation-price-info grid__cell product-list__grid-item__price-info dw-mod"> 2642 <a href="{{link}}" onclick="Scroll.SavePosition(event);" title="{{name}}"> 2643 <h6 class="u-condensed-text">{{name}}</h6> 2644 </a> 2645 <div class="item-number dw-mod">{{number}}</div> 2646 @if (!onlyPreview) 2647 { 2648 <div class="{{hideBuyOptions}}"> 2649 <div class="price price--product-list dw-mod">{{price}} {{unitName}}</div> 2650 <div class="before-price u-hidden dw-mod"></div> 2651 {{#if standardOrderQuantity}} 2652 <div>@Translate("Kolli"): {{standardOrderQuantity}}</div> 2653 {{/if}} 2654 <input type="hidden" value="" name="Unit{{id}}" id="RecommendUnit_{{id}}"> 2655 </div> 2656 } 2657 </div> 2658 2659 <div class="reccomendation-footer product-list__grid-item__footer dw-mod"> 2660 <div class="u-ta-center u-inline-block u-margin-top"> 2661 @if (onlyPreview) 2662 { 2663 <a href="{{link}}" class="btn btn--primary btn--arrow btn--full u-no-margin dw-mod">@Translate("View")</a> 2664 } 2665 else 2666 { 2667 <div class="buttons-collection {{hideBuyOptions}}"> 2668 <button type="button" id="RecommendCartButton_{{id}}" class="js-cart-btn btn btn--primary btn--condensed u-pull--right dw-mod " name="submit" onclick="Cart.AddToCart(event, { 2669 id: '{{productId}}', 2670 variantId: '{{variantId}}', 2671 unitId: '{{unitID}}', 2672 loopId: '{{id}}', 2673 quantity: document.getElementById('RecommendQuantity_{{id}}').value, 2674 productInfo: {{productInfo}}, 2675 multiplum: {{multiplum}}, 2676 multiplumUnitId: '{{ProductDefaultUnitId}}', 2677 standardOrderQuantity:{{standardOrderQuantity}}, 2678 quantityElementId: 'RecommendQuantity_{{id}}' 2679 }); "> 2680 <i class="fas fa-shopping-cart"></i><span class="u-hidden-xs u-hidden-xxs"></span> 2681 </button> 2682 2683 <input type="number" class="u-w80px u-pull--right" id="RecommendQuantity_{{id}}" name="Quantity{{id}}" value="1" min="1"> 2684 2685 </div> 2686 } 2687 </div> 2688 2689 @if (!onlyPreview) 2690 { 2691 <div class="u-ta-center u-hidden"> 2692 <a href="{{link}}" id="CartButton_{{id}}" class="btn btn--primary btn--full btn--arrow u-no-margin dw-mod" onclick="Scroll.SavePosition(event); {{googleImpressionClick}}" title="@Translate("View more")">@Translate("View more")</a> 2693 </div> 2694 <div> 2695 <span class="stock-icon {{stockState}} u-no-margin dw-mod" title="{{stockText}}"></span> {{stockText}}{{deliveryText}} 2696 </div> 2697 } 2698 2699 </div> 2700 </div> 2701 </div> 2702 2703 2704 </script> 2705 2706 <script id="MiniStickerRelated" type="text/x-template"> 2707 <div class="stickers-container__tag stickers-container__tag--micro {{className}} dw-mod">{{text}}</div> 2708 </script> 2709 } 2710 2711 @*@helper RenderStockAndShipping(LoopItem loopItem) 2712 { 2713 bool hideStockState = Pageview.AreaSettings.GetItem("ProductPage").GetString("HideStockState") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideStockState") : false; 2714 bool hideDelivery = Pageview.AreaSettings.GetItem("ProductPage").GetString("HideShipping") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideShipping") : false; 2715 bool onlyPreview = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("OnlyPreviewForAnonymous") && Pageview.User == null; 2716 2717 var stockState = renderStockState(loopItem); 2718 var stockText = renderStockText(loopItem); 2719 var deliveryText = string.IsNullOrEmpty(loopItem.GetString("Ecom:Product:Stock.DeliveryText")) ? "" : ", " + Translate("Delivery") + " " + loopItem.GetString("Ecom:Product:Stock.DeliveryText") + " " + loopItem.GetString("Ecom:Product:Stock.DeliveryUnit"); 2720 2721 if (!onlyPreview && (!string.IsNullOrEmpty(stockState) || !string.IsNullOrEmpty(deliveryText))) 2722 { 2723 <div> 2724 @if (!hideStockState) 2725 { 2726 <span class="stock-icon @stockState u-no-margin dw-mod" title="@stockText"></span> @stockText@deliveryText 2727 } 2728 2729 @if (!string.IsNullOrEmpty(deliveryText) && !hideDelivery) 2730 { 2731 @deliveryText 2732 } 2733 </div> 2734 } 2735 }*@ 2736 2737 <div class="product__info dw-mod u-margin-bottom--lg js-product"> 2738 <div class="grid grid--align-content-start"> 2739 @* The @RenderBlockList base helper is included in Components/GridBuilder.cshtml *@ 2740 @RenderBlockList(productsPage.BlocksRoot.BlocksList) 2741 </div> 2742 </div> 2743 2744 @helper RenderProductMiniTabs() 2745 { 2746 List<Block> subBlocks = productsPage.GetBlockListById("MiniTabs").OrderBy(item => item.SortId).ToList(); 2747 2748 if (subBlocks.Count > 0) 2749 { 2750 <div class="grid__col-12 product__info tabs u-no-padding u-margin-bottom--lg dw-mod"> 2751 @{ 2752 bool firstTab = true; 2753 foreach (Block item in subBlocks) 2754 { 2755 string isChecked = firstTab ? "checked" : ""; 2756 firstTab = false; 2757 2758 <input type="radio" class="tabs__trigger" name="productMiniTabs" id="@item.Id" onchange="bLazy.revalidate()" @isChecked /> 2759 } 2760 } 2761 2762 <div class="tabs__list dw-mod"> 2763 @foreach (Block item in subBlocks) 2764 { 2765 <label for="@item.Id" class="tabs__label dw-mod">@item.Name</label> 2766 } 2767 </div> 2768 2769 <div class="tabs__blocks dw-mod"> 2770 @foreach (Block item in subBlocks) 2771 { 2772 string hidePadding = item.Design.HidePadding ? "u-no-padding" : ""; 2773 2774 if (item.Design.RenderType != RenderType.Hide) 2775 { 2776 <div class="tabs__block u-border dw-mod" id="Block__@item.Id"> 2777 <block class="product__block paragraph-container product__block--bordered dw-mod"> 2778 <div class="center-container u-padding--lg dw-mod"> 2779 @RenderBlock(item) 2780 </div> 2781 </block> 2782 </div> 2783 } 2784 } 2785 </div> 2786 </div> 2787 } 2788 } 2789 2790 @helper RenderProductTabs() 2791 { 2792 List<Block> subBlocks = productsPage.GetBlockListById("Tabs").OrderBy(item => item.SortId).ToList(); 2793 2794 <div class="grid__col-12 product__info tabs u-no-padding dw-mod"> 2795 @{ 2796 bool firstTab = true; 2797 foreach (Block item in subBlocks) 2798 { 2799 string isChecked = firstTab ? "checked" : ""; 2800 firstTab = false; 2801 2802 <input type="radio" class="tabs__trigger" name="productTabs" id="@item.Id" onchange="bLazy.revalidate()" @isChecked /> 2803 } 2804 } 2805 2806 <div class="tabs__list dw-mod"> 2807 @foreach (Block item in subBlocks) 2808 { 2809 <label for="@item.Id" class="tabs__label dw-mod">@item.Name</label> 2810 } 2811 </div> 2812 2813 <div class="tabs__blocks dw-mod"> 2814 @foreach (Block item in subBlocks) 2815 { 2816 string hidePadding = item.Design.HidePadding ? "u-no-padding" : ""; 2817 2818 if (item.Design.RenderType != RenderType.Hide) 2819 { 2820 <div class="tabs__block dw-mod" id="Block__@item.Id"> 2821 <section class="product__section paragraph-container paragraph-container--full-width product__section--bordered dw-mod"> 2822 <div class="center-container u-padding--lg dw-mod"> 2823 @RenderBlock(item) 2824 </div> 2825 </section> 2826 </div> 2827 } 2828 } 2829 </div> 2830 </div> 2831 }