Error executing template "Designs/Rapido/eCom/Product/Product.cshtml"
System.NullReferenceException: Object reference not set to an instance of an object.
   at CompiledRazorTemplates.Dynamic.RazorEngine_6d81f4cb5dc0495196f02224861c0598.<RenderMainInfoVariantsCustom>b__118_0(TextWriter __razor_helper_writer) in D:\dynamicweb.net\Solutions\Mennt\chrisco-sport.cloud.dynamicweb-cms.com\Files\Templates\Designs\Rapido\eCom\Product\Product.cshtml:line 6265
   at RazorEngine.Templating.TemplateWriter.ToString()
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at CompiledRazorTemplates.Dynamic.RazorEngine_6d81f4cb5dc0495196f02224861c0598.<>c__DisplayClass4_0.<RenderBlock>b__0(TextWriter __razor_helper_writer) in D:\dynamicweb.net\Solutions\Mennt\chrisco-sport.cloud.dynamicweb-cms.com\Files\Templates\Designs\Rapido\eCom\Product\Product.cshtml:line 210
   at CompiledRazorTemplates.Dynamic.RazorEngine_6d81f4cb5dc0495196f02224861c0598.<>c__DisplayClass3_0.<RenderBlockList>b__0(TextWriter __razor_helper_writer) in D:\dynamicweb.net\Solutions\Mennt\chrisco-sport.cloud.dynamicweb-cms.com\Files\Templates\Designs\Rapido\eCom\Product\Product.cshtml:line 120
   at CompiledRazorTemplates.Dynamic.RazorEngine_6d81f4cb5dc0495196f02224861c0598.<>c__DisplayClass4_0.<RenderBlock>b__0(TextWriter __razor_helper_writer) in D:\dynamicweb.net\Solutions\Mennt\chrisco-sport.cloud.dynamicweb-cms.com\Files\Templates\Designs\Rapido\eCom\Product\Product.cshtml:line 243
   at CompiledRazorTemplates.Dynamic.RazorEngine_6d81f4cb5dc0495196f02224861c0598.<>c__DisplayClass3_0.<RenderBlockList>b__0(TextWriter __razor_helper_writer) in D:\dynamicweb.net\Solutions\Mennt\chrisco-sport.cloud.dynamicweb-cms.com\Files\Templates\Designs\Rapido\eCom\Product\Product.cshtml:line 148
   at CompiledRazorTemplates.Dynamic.RazorEngine_6d81f4cb5dc0495196f02224861c0598.<RenderProductTop>b__123_0(TextWriter __razor_helper_writer) in D:\dynamicweb.net\Solutions\Mennt\chrisco-sport.cloud.dynamicweb-cms.com\Files\Templates\Designs\Rapido\eCom\Product\Product.cshtml:line 6688
   at RazorEngine.Templating.TemplateWriter.ToString()
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at CompiledRazorTemplates.Dynamic.RazorEngine_6d81f4cb5dc0495196f02224861c0598.<>c__DisplayClass4_0.<RenderBlock>b__0(TextWriter __razor_helper_writer) in D:\dynamicweb.net\Solutions\Mennt\chrisco-sport.cloud.dynamicweb-cms.com\Files\Templates\Designs\Rapido\eCom\Product\Product.cshtml:line 210
   at CompiledRazorTemplates.Dynamic.RazorEngine_6d81f4cb5dc0495196f02224861c0598.<>c__DisplayClass3_0.<RenderBlockList>b__0(TextWriter __razor_helper_writer) in D:\dynamicweb.net\Solutions\Mennt\chrisco-sport.cloud.dynamicweb-cms.com\Files\Templates\Designs\Rapido\eCom\Product\Product.cshtml:line 120
   at CompiledRazorTemplates.Dynamic.RazorEngine_6d81f4cb5dc0495196f02224861c0598.Execute() in D:\dynamicweb.net\Solutions\Mennt\chrisco-sport.cloud.dynamicweb-cms.com\Files\Templates\Designs\Rapido\eCom\Product\Product.cshtml:line 6675
   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 @using Dynamicweb.Ecommerce 14 15 16 17 @functions { 18 List<LoopItem> downloadDocuments = new List<LoopItem>(); 19 //downloadDocuments variable, will be defined in Fields.cshtml and used in ProductAssets.cshtml 20 21 BlocksPage productsPage = BlocksPage.GetBlockPage("Product"); 22 23 public static string ToPascalCase(string str) 24 { 25 return CultureInfo.InvariantCulture.TextInfo 26 .ToTitleCase(str.ToLowerInvariant()) 27 .Replace("-", "") 28 .Replace("_", "") 29 .Replace(" ", ""); 30 } 31 } 32 33 @{ 34 string productBlocksPosition = Pageview.AreaSettings.GetItem("ProductPage").GetList("ImageSectionPosition") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("ImageSectionPosition").SelectedValue : "thumbs-image-info"; 35 bool productInfoOnTheRight = productBlocksPosition.LastIndexOf("info") == productBlocksPosition.Length - 4; 36 37 Block productTop = new Block() 38 { 39 Id = "Top", 40 SortId = 10, 41 SkipRenderBlocksList = true, 42 Template = RenderProductTop() 43 }; 44 productsPage.Add(productTop); 45 46 Block productMainInfo = new Block() 47 { 48 Id = "MainInformation", 49 SortId = productInfoOnTheRight ? 20 : 10, 50 Design = new Design 51 { 52 Size = "auto", 53 RenderType = RenderType.Column 54 } 55 }; 56 productsPage.Add("Top", productMainInfo); 57 58 //Optional mini tabs block 59 Block miniTabsBlock = new Block() 60 { 61 Id = "MiniTabs", 62 SortId = 40, 63 Template = RenderProductMiniTabs(), 64 SkipRenderBlocksList = true 65 }; 66 productsPage.Add("MainInformation", miniTabsBlock); 67 //----- 68 69 Block productTabsBlock = new Block() 70 { 71 Id = "Tabs", 72 SortId = 20, 73 Template = RenderProductTabs(), 74 SkipRenderBlocksList = true 75 }; 76 productsPage.Add(productTabsBlock); 77 78 Block productDetailsBlock = new Block() 79 { 80 Id = "Section", 81 SortId = 30 82 }; 83 productsPage.Add(productDetailsBlock); 84 85 Block productSnippetsBlock = new Block() 86 { 87 Id = "Snippets", 88 SortId = 40 89 }; 90 productsPage.Add(productSnippetsBlock); 91 } 92 93 @* Include the required Grid builder (Contains the methods @RenderBlockList and @RenderBlock) *@ 94 @using System.Text.RegularExpressions 95 @using System.Collections.Generic 96 @using System.Reflection 97 @using System.Web 98 @using System.Web.UI.HtmlControls 99 @using Dynamicweb.Rapido.Blocks.Components 100 @using Dynamicweb.Rapido.Blocks.Components.Articles 101 @using Dynamicweb.Rapido.Blocks.Components.Documentation 102 @using Dynamicweb.Rapido.Blocks 103 104 105 @*--- START: Base block renderers ---*@ 106 107 @helper RenderBlockList(List<Block> blocks) 108 { 109 bool debug = !String.IsNullOrEmpty(HttpContext.Current.Request.QueryString.Get("debug")) ? Convert.ToBoolean(HttpContext.Current.Request.QueryString.Get("debug")) : false; 110 blocks = blocks.OrderBy(item => item.SortId).ToList(); 111 112 foreach (Block item in blocks) 113 { 114 if (debug) { 115 <!-- Block START: @item.Id --> 116 } 117 118 if (item.Design == null) 119 { 120 @RenderBlock(item) 121 } 122 else if (item.Design.RenderType == RenderType.None) { 123 string cssClass = item.Design.CssClass != null ? item.Design.CssClass : ""; 124 125 <div class="@cssClass dw-mod"> 126 @RenderBlock(item) 127 </div> 128 } 129 else if (item.Design.RenderType != RenderType.Hide) 130 { 131 string cssClass = item.Design.CssClass != null ? item.Design.CssClass : ""; 132 133 if (!item.SkipRenderBlocksList) { 134 if (item.Design.RenderType == RenderType.Row) 135 { 136 <div class="grid grid--align-content-start @cssClass dw-mod" id="Block__@item.Id"> 137 @RenderBlock(item) 138 </div> 139 } 140 141 if (item.Design.RenderType == RenderType.Column) 142 { 143 string hidePadding = item.Design.HidePadding ? "u-no-padding" : ""; 144 string size = item.Design.Size ?? "12"; 145 size = Regex.IsMatch(size, @"\d") ? "md-" + item.Design.Size : item.Design.Size; 146 147 <div class="grid__col-lg-@item.Design.Size grid__col-md-@item.Design.Size grid__col-sm-12 grid__col-xs-12 @hidePadding @cssClass dw-mod" id="Block__@item.Id"> 148 @RenderBlock(item) 149 </div> 150 } 151 152 if (item.Design.RenderType == RenderType.Table) 153 { 154 <table class="table @cssClass dw-mod" id="Block__@item.Id"> 155 @RenderBlock(item) 156 </table> 157 } 158 159 if (item.Design.RenderType == RenderType.TableRow) 160 { 161 <tr class="@cssClass dw-mod" id="Block__@item.Id"> 162 @RenderBlock(item) 163 </tr> 164 } 165 166 if (item.Design.RenderType == RenderType.TableColumn) 167 { 168 <td class="@cssClass dw-mod" id="Block__@item.Id"> 169 @RenderBlock(item) 170 </td> 171 } 172 173 if (item.Design.RenderType == RenderType.CardHeader) 174 { 175 <div class="card-header @cssClass dw-mod"> 176 @RenderBlock(item) 177 </div> 178 } 179 180 if (item.Design.RenderType == RenderType.CardBody) 181 { 182 <div class="card @cssClass dw-mod"> 183 @RenderBlock(item) 184 </div> 185 } 186 187 if (item.Design.RenderType == RenderType.CardFooter) 188 { 189 <div class="card-footer @cssClass dw-mod"> 190 @RenderBlock(item) 191 </div> 192 } 193 } 194 else 195 { 196 @RenderBlock(item) 197 } 198 } 199 200 if (debug) { 201 <!-- Block END: @item.Id --> 202 } 203 } 204 } 205 206 @helper RenderBlock(Block item) 207 { 208 bool debug = !String.IsNullOrEmpty(HttpContext.Current.Request.QueryString.Get("debug")) ? Convert.ToBoolean(HttpContext.Current.Request.QueryString.Get("debug")) : false; 209 210 if (item.Template != null) 211 { 212 @BlocksPage.RenderTemplate(item.Template) 213 } 214 215 if (item.Component != null) 216 { 217 string customSufix = "Custom"; 218 string methodName = item.Component.HelperName; 219 220 ComponentBase[] methodParameters = new ComponentBase[1]; 221 methodParameters[0] = item.Component; 222 Type methodType = this.GetType(); 223 224 MethodInfo customMethod = methodType.GetMethod(methodName + customSufix); 225 MethodInfo generalMethod = methodType.GetMethod(methodName); 226 227 try { 228 if (debug) { 229 <!-- Component: @methodName.Replace("Render", "") --> 230 } 231 @customMethod.Invoke(this, methodParameters).ToString(); 232 } catch { 233 try { 234 @generalMethod.Invoke(this, methodParameters).ToString(); 235 } catch(Exception ex) { 236 throw new Exception(item.Component.GetType().Name + " method '" + methodName +"' could not be invoked", ex); 237 } 238 } 239 } 240 241 if (item.BlocksList.Count > 0 && !item.SkipRenderBlocksList) 242 { 243 @RenderBlockList(item.BlocksList) 244 } 245 } 246 247 @*--- END: Base block renderers ---*@ 248 249 @using Dynamicweb.Rapido.Blocks.Components 250 @using Dynamicweb.Rapido.Blocks.Components.General 251 @using Dynamicweb.Rapido.Blocks 252 @using System.IO 253 254 @* Required *@ 255 @using Dynamicweb.Rapido.Blocks.Components 256 @using Dynamicweb.Rapido.Blocks.Components.General 257 @using Dynamicweb.Rapido.Blocks 258 259 260 @helper Render(ComponentBase component) 261 { 262 if (component != null) 263 { 264 @component.Render(this) 265 } 266 } 267 268 @* Components *@ 269 @using System.Reflection 270 @using Dynamicweb.Rapido.Blocks.Components.General 271 272 273 @* Component *@ 274 275 @helper RenderIcon(Icon settings) 276 { 277 if (settings != null) 278 { 279 string color = settings.Color != null ? "style=\"color: " + settings.Color + "\"" : ""; 280 281 if (settings.Name != null) 282 { 283 if (string.IsNullOrEmpty(settings.Label)) 284 { 285 <i class="@settings.Prefix @settings.Name @settings.CssClass" @color></i> 286 } 287 else 288 { 289 if (settings.LabelPosition == IconLabelPosition.Before) 290 { 291 <div class="u-flex u-flex--align-items-center @settings.CssClass">@settings.Label <i class="@settings.Prefix @settings.Name u-margin-left" @color></i></div> 292 } 293 else 294 { 295 <div class="u-flex u-flex--align-items-center @settings.CssClass"><i class="@settings.Prefix @settings.Name u-margin-right--lg u-w20px" @color></i>@settings.Label</div> 296 } 297 } 298 } 299 else if (!string.IsNullOrEmpty(settings.Label)) 300 { 301 @settings.Label 302 } 303 } 304 } 305 @using System.Reflection 306 @using Dynamicweb.Rapido.Blocks.Components.General 307 @using Dynamicweb.Rapido.Blocks.Components 308 @using Dynamicweb.Core 309 310 @* Component *@ 311 312 @helper RenderButton(Button settings) 313 { 314 if (settings != null && (!string.IsNullOrEmpty(settings.Title) || settings.Icon != null)) 315 { 316 Dictionary<string, string> attributes = new Dictionary<string, string>(); 317 List<string> classList = settings.CssClass != null ? settings.CssClass.Split(' ').ToList() : new List<string>(); 318 if (settings.Disabled) { 319 attributes.Add("disabled", "true"); 320 classList.Add("disabled"); 321 } 322 323 if (!string.IsNullOrEmpty(settings.ConfirmText) || !string.IsNullOrEmpty(settings.ConfirmTitle)) 324 { 325 settings.Id = !string.IsNullOrEmpty(settings.Id) ? settings.Id : Guid.NewGuid().ToString("N"); 326 @RenderConfirmDialog(settings); 327 settings.OnClick = "document.getElementById('" + settings.Id + "ModalTrigger').checked = true"; 328 } 329 330 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); } 331 if (!string.IsNullOrEmpty(settings.Name)) { attributes.Add("name", settings.Name); } 332 if (!string.IsNullOrEmpty(settings.AltText)) 333 { 334 attributes.Add("title", settings.AltText); 335 } 336 else if (!string.IsNullOrEmpty(settings.Title)) 337 { 338 string cleanTitle = Regex.Replace(settings.Title, "<.*?>", String.Empty); 339 cleanTitle = cleanTitle.Replace("&nbsp;", " "); 340 attributes.Add("title", cleanTitle); 341 } 342 343 var onClickEvents = new List<string>(); 344 if (!string.IsNullOrEmpty(settings.OnClick)) 345 { 346 onClickEvents.Add(settings.OnClick); 347 } 348 if (!string.IsNullOrEmpty(settings.Href)) 349 { 350 onClickEvents.Add("location.href='" + settings.Href + "'"); 351 } 352 if (onClickEvents.Count > 0) 353 { 354 attributes.Add("onClick", string.Join(";", onClickEvents)); 355 } 356 357 if (settings.ButtonLayout != ButtonLayout.None) 358 { 359 classList.Add("btn"); 360 string btnLayout = Enum.GetName(typeof(ButtonLayout), settings.ButtonLayout).ToLower(); 361 if (btnLayout == "linkclean") 362 { 363 btnLayout = "link-clean"; //fix 364 } 365 classList.Add("btn--" + btnLayout); 366 } 367 368 if (settings.Icon == null) 369 { 370 settings.Icon = new Icon(); 371 } 372 373 settings.Icon.CssClass += Enum.GetName(typeof(ButtonLayout), settings.ButtonLayout).ToLower() != "linkclean" ? " u-flex--align-center" : ""; 374 settings.Icon.Label = settings.Title; 375 376 attributes.Add("type", Enum.GetName(typeof(ButtonType), settings.ButtonType).ToLower()); 377 378 <button class="@string.Join(" ", classList) dw-mod" @ComponentMethods.AddAttributes(attributes) @ComponentMethods.AddAttributes(settings.ExtraAttributes)>@Render(settings.Icon)</button> 379 } 380 } 381 382 @helper RenderConfirmDialog(Button settings) 383 { 384 Modal confirmDialog = new Modal { 385 Id = settings.Id, 386 Width = ModalWidth.Sm, 387 Heading = new Heading 388 { 389 Level = 2, 390 Title = settings.ConfirmTitle 391 }, 392 BodyText = settings.ConfirmText 393 }; 394 395 confirmDialog.AddAction(new Button { Title = Translate("Cancel"), ButtonLayout = ButtonLayout.Secondary, OnClick = "document.getElementById('" + settings.Id + "ModalTrigger').checked = false"}); 396 confirmDialog.AddAction(new Button { Title = Translate("OK"), ButtonLayout = ButtonLayout.Primary, OnClick = "document.getElementById('" + settings.Id + "ModalTrigger').checked = false;" + settings.OnClick }); 397 398 @Render(confirmDialog) 399 } 400 @using Dynamicweb.Rapido.Blocks.Components.General 401 @using Dynamicweb.Rapido.Blocks.Components 402 @using Dynamicweb.Core 403 404 @helper RenderDashboard(Dashboard settings) 405 { 406 var widgets = settings.GetWidgets(); 407 408 if (!string.IsNullOrEmpty(settings.WidgetsBaseBackgroundColor)) 409 { 410 //set bg color for them 411 412 System.Drawing.Color color = System.Drawing.ColorTranslator.FromHtml(settings.WidgetsBaseBackgroundColor); 413 int r = Convert.ToInt16(color.R); 414 int g = Convert.ToInt16(color.G); 415 int b = Convert.ToInt16(color.B); 416 417 var count = widgets.Length; 418 var max = Math.Max(r, Math.Max(g, b)); 419 double step = 255.0 / (max * count); 420 var i = 0; 421 foreach (var widget in widgets) 422 { 423 i++; 424 425 var shade = "rgb(" + Converter.ToString(r * step * i).Replace(",", ".") + ", " + Converter.ToString(g * step * i).Replace(",", ".") + ", " + Converter.ToString(b * step * i).Replace(",", ".") + ")"; 426 widget.BackgroundColor = shade; 427 } 428 } 429 430 <div class="dashboard @settings.CssClass dw-mod" @ComponentMethods.AddAttributes(settings.ExtraAttributes)> 431 @foreach (var widget in widgets) 432 { 433 <div class="dashboard__widget"> 434 @Render(widget) 435 </div> 436 } 437 </div> 438 } 439 @using Dynamicweb.Rapido.Blocks.Components.General 440 @using Dynamicweb.Rapido.Blocks.Components 441 442 @helper RenderDashboardWidgetLink(DashboardWidgetLink settings) 443 { 444 if (!string.IsNullOrEmpty(settings.Link)) 445 { 446 var backgroundStyles = ""; 447 if (!string.IsNullOrEmpty(settings.BackgroundColor)) 448 { 449 backgroundStyles = "style=\"background-color:" + settings.BackgroundColor + "\""; 450 } 451 452 <a href="@settings.Link" class="widget widget--link @settings.CssClass dw-mod" @backgroundStyles title="@settings.Title" @ComponentMethods.AddAttributes(settings.ExtraAttributes)> 453 <div class="u-center-middle u-color-light"> 454 @if (settings.Icon != null) 455 { 456 settings.Icon.CssClass += "widget__icon"; 457 @Render(settings.Icon) 458 } 459 <div class="widget__title">@settings.Title</div> 460 </div> 461 </a> 462 } 463 } 464 @using Dynamicweb.Rapido.Blocks.Components.General 465 @using Dynamicweb.Rapido.Blocks.Components 466 467 @helper RenderDashboardWidgetCounter(DashboardWidgetCounter settings) 468 { 469 var backgroundStyles = ""; 470 if (!string.IsNullOrEmpty(settings.BackgroundColor)) 471 { 472 backgroundStyles = "style='background-color:" + settings.BackgroundColor + "'"; 473 } 474 475 <div class="widget @settings.CssClass dw-mod" @backgroundStyles @ComponentMethods.AddAttributes(settings.ExtraAttributes)> 476 <div class="u-center-middle u-color-light"> 477 @if (settings.Icon != null) 478 { 479 settings.Icon.CssClass += "widget__icon"; 480 @Render(settings.Icon) 481 } 482 <div class="widget__counter">@settings.Count</div> 483 <div class="widget__title">@settings.Title</div> 484 </div> 485 </div> 486 } 487 @using System.Reflection 488 @using Dynamicweb.Rapido.Blocks.Components.General 489 @using Dynamicweb.Rapido.Blocks.Components 490 @using Dynamicweb.Core 491 492 @* Component *@ 493 494 @helper RenderLink(Link settings) 495 { 496 if (settings != null && !string.IsNullOrEmpty(settings.Href) && (!string.IsNullOrEmpty(settings.Title) || settings.Icon != null)) 497 { 498 Dictionary<string, string> attributes = new Dictionary<string, string>(); 499 List<string> classList = settings.CssClass != null ? settings.CssClass.Split(' ').ToList() : new List<string>(); 500 if (settings.Disabled) 501 { 502 attributes.Add("disabled", "true"); 503 classList.Add("disabled"); 504 } 505 506 if (!string.IsNullOrEmpty(settings.AltText)) 507 { 508 attributes.Add("title", settings.AltText); 509 } 510 else if (!string.IsNullOrEmpty(settings.Title)) 511 { 512 attributes.Add("title", settings.Title); 513 } 514 515 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); } 516 if (!string.IsNullOrEmpty(settings.Name)) { attributes.Add("name", settings.Name); } 517 if (!string.IsNullOrEmpty(settings.OnClick)) { attributes.Add("onClick", settings.OnClick); } 518 attributes.Add("href", settings.Href); 519 520 if (settings.ButtonLayout != ButtonLayout.None) 521 { 522 classList.Add("btn"); 523 string btnLayout = Enum.GetName(typeof(ButtonLayout), settings.ButtonLayout).ToLower(); 524 if (btnLayout == "linkclean") 525 { 526 btnLayout = "link-clean"; //fix 527 } 528 classList.Add("btn--" + btnLayout); 529 } 530 531 if (settings.Icon == null) 532 { 533 settings.Icon = new Icon(); 534 } 535 settings.Icon.Label = settings.Title; 536 537 if (settings.Target == LinkTargetType.Blank && settings.Rel == LinkRelType.None) 538 { 539 settings.Rel = LinkRelType.Noopener; 540 } 541 if (settings.Target != LinkTargetType.None) 542 { 543 attributes.Add("target", "_" + Enum.GetName(typeof(LinkTargetType), settings.Target).ToLower()); 544 } 545 if (settings.Download) 546 { 547 attributes.Add("download", "true"); 548 } 549 if (settings.Rel != LinkRelType.None) 550 { 551 attributes.Add("rel", Enum.GetName(typeof(LinkRelType), settings.Rel).ToLower()); 552 } 553 554 <a class="@string.Join(" ", classList) dw-mod" @ComponentMethods.AddAttributes(attributes) @ComponentMethods.AddAttributes(settings.ExtraAttributes)>@Render(settings.Icon)</a> 555 } 556 } 557 @using System.Reflection 558 @using Dynamicweb.Rapido.Blocks.Components 559 @using Dynamicweb.Rapido.Blocks.Components.General 560 @using Dynamicweb.Rapido.Blocks 561 562 563 @* Component *@ 564 565 @helper RenderRating(Rating settings) 566 { 567 if (settings.Score > 0) 568 { 569 int rating = settings.Score; 570 string iconType = "fa-star"; 571 572 switch (settings.Type.ToString()) { 573 case "Stars": 574 iconType = "fa-star"; 575 break; 576 case "Hearts": 577 iconType = "fa-heart"; 578 break; 579 case "Lemons": 580 iconType = "fa-lemon"; 581 break; 582 case "Bombs": 583 iconType = "fa-bomb"; 584 break; 585 } 586 587 <div class="u-ta-right"> 588 @for (int i = 0; i < settings.OutOf; i++) 589 { 590 <i class="@(rating > i ? "fas" : "far") @iconType"></i> 591 } 592 </div> 593 } 594 } 595 @using System.Reflection 596 @using Dynamicweb.Rapido.Blocks.Components.General 597 @using Dynamicweb.Rapido.Blocks.Components 598 599 600 @* Component *@ 601 602 @helper RenderSelectFieldOption(SelectFieldOption settings) 603 { 604 Dictionary<string, string> attributes = new Dictionary<string, string>(); 605 if (settings.Checked) { attributes.Add("selected", "true"); } 606 if (settings.Disabled) { attributes.Add("disabled", "true"); } 607 if (settings.Value != null) { attributes.Add("value", settings.Value); } 608 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); } 609 610 <option @ComponentMethods.AddAttributes(attributes) @ComponentMethods.AddAttributes(settings.ExtraAttributes)>@settings.Label</option> 611 } 612 @using System.Reflection 613 @using Dynamicweb.Rapido.Blocks.Components.General 614 @using Dynamicweb.Rapido.Blocks.Components 615 616 617 @* Component *@ 618 619 @helper RenderNavigation(Navigation settings) { 620 @RenderNavigation(new 621 { 622 id = settings.Id, 623 cssclass = settings.CssClass, 624 startLevel = settings.StartLevel, 625 endlevel = settings.EndLevel, 626 expandmode = settings.Expandmode, 627 sitemapmode = settings.SitemapMode, 628 template = settings.Template 629 }) 630 } 631 @using Dynamicweb.Rapido.Blocks.Components.General 632 @using Dynamicweb.Rapido.Blocks.Components 633 634 635 @* Component *@ 636 637 @helper RenderBreadcrumbNavigation(BreadcrumbNavigation settings) { 638 settings.Id = String.IsNullOrEmpty(settings.Id) ? "breadcrumb" : settings.Id; 639 settings.Template = String.IsNullOrEmpty(settings.Template) ? "Breadcrumb.xslt" : settings.Template; 640 settings.StartLevel = settings.StartLevel == 0 ? 1 : settings.StartLevel; 641 settings.EndLevel = settings.EndLevel == 10 ? 1 : settings.EndLevel; 642 settings.Expandmode = String.IsNullOrEmpty(settings.Expandmode) ? "all" : settings.Expandmode; 643 settings.SitemapMode = false; 644 645 @RenderNavigation(settings) 646 } 647 @using Dynamicweb.Rapido.Blocks.Components.General 648 @using Dynamicweb.Rapido.Blocks.Components 649 650 651 @* Component *@ 652 653 @helper RenderLeftNavigation(LeftNavigation settings) { 654 settings.Id = String.IsNullOrEmpty(settings.Id) ? "breadcrumb" : settings.Id; 655 settings.Template = String.IsNullOrEmpty(settings.Template) ? "Breadcrumb.xslt" : settings.Template; 656 settings.StartLevel = settings.StartLevel == 0 ? 1 : settings.StartLevel; 657 settings.EndLevel = settings.EndLevel == 10 ? 1 : settings.EndLevel; 658 settings.Expandmode = String.IsNullOrEmpty(settings.Expandmode) ? "all" : settings.Expandmode; 659 660 <div class="grid__cell"> 661 @RenderNavigation(settings) 662 </div> 663 } 664 @using System.Reflection 665 @using Dynamicweb.Rapido.Blocks.Components.General 666 @using Dynamicweb.Core 667 668 @* Component *@ 669 670 @helper RenderHeading(Heading settings) 671 { 672 if (settings != null && !string.IsNullOrEmpty(settings.Title)) 673 { 674 string color = settings.Color != null ? "style=\"color: " + settings.Color + "\"" : ""; 675 string tagName = settings.Level != 0 ? "h" + settings.Level.ToString() : "div"; 676 677 @("<" + tagName + " class=\"" + settings.CssClass + " dw-mod\" " + color + ">") 678 if (!string.IsNullOrEmpty(settings.Link)) 679 { 680 @Render(new Link { Href = settings.Link, Icon = settings.Icon, Title = settings.Title, ButtonLayout = ButtonLayout.None }) 681 } 682 else 683 { 684 if (settings.Icon == null) 685 { 686 settings.Icon = new Icon(); 687 } 688 settings.Icon.Label = settings.Title; 689 @Render(settings.Icon) 690 } 691 @("</" + tagName + ">"); 692 } 693 } 694 @using Dynamicweb.Rapido.Blocks.Components 695 @using Dynamicweb.Rapido.Blocks.Components.General 696 @using Dynamicweb.Rapido.Blocks 697 698 699 @* Component *@ 700 701 @helper RenderImage(Image settings) 702 { 703 if (settings.FilterPrimary != ImageFilter.None || settings.FilterSecondary != ImageFilter.None) 704 { 705 Dictionary<string, string> optionalAttributes = new Dictionary<string, string>(); 706 if (!string.IsNullOrEmpty(settings.FilterColor)) { optionalAttributes.Add("style", "background-color: " + settings.FilterColor); } 707 708 if (settings.Caption != null) 709 { 710 @:<div> 711 } 712 713 var primaryFilterClass = settings.FilterPrimary.ToString().ToLower(); 714 var secondaryFilterClass = settings.FilterSecondary.ToString().ToLower(); 715 716 <div class="image-filter image-filter--@primaryFilterClass u-position-relative dw-mod" @ComponentMethods.AddAttributes(optionalAttributes)> 717 <div class="image-filter image-filter--@secondaryFilterClass dw-mod"> 718 @if (settings.Link != null) 719 { 720 <a href="@settings.Link"> 721 @RenderTheImage(settings) 722 </a> 723 } 724 else 725 { 726 @RenderTheImage(settings) 727 } 728 </div> 729 </div> 730 731 if (settings.Caption != null) 732 { 733 <span class="image-caption dw-mod">@settings.Caption</span> 734 @:</div> 735 } 736 } 737 else 738 { 739 if (settings.Caption != null) 740 { 741 @:<div> 742 } 743 if (!string.IsNullOrEmpty(settings.Link)) 744 { 745 <a href="@settings.Link"> 746 @RenderTheImage(settings) 747 </a> 748 } 749 else 750 { 751 @RenderTheImage(settings) 752 } 753 754 if (settings.Caption != null) 755 { 756 <span class="image-caption dw-mod">@settings.Caption</span> 757 @:</div> 758 } 759 } 760 } 761 762 @helper RenderTheImage(Image settings) 763 { 764 if (settings != null) 765 { 766 string alternativeImage = !string.IsNullOrEmpty(Pageview.AreaSettings.GetItem("Settings").GetString("AlternativeImage")) ? Pageview.AreaSettings.GetItem("Settings").GetFile("AlternativeImage").PathUrlEncoded : "/Images/missing_image.jpg"; 767 string placeholderImage = "/Files/Images/placeholder.gif"; 768 string imageEngine = "/Admin/Public/GetImage.ashx?"; 769 770 string imageStyle = ""; 771 772 switch (settings.Style) 773 { 774 case ImageStyle.Ball: 775 imageStyle = "grid__cell-img--ball"; 776 break; 777 778 case ImageStyle.Triangle: 779 imageStyle = "grid__cell-img--triangle"; 780 break; 781 } 782 783 if (settings.Style == ImageStyle.Ball || settings.Style == ImageStyle.Circle || settings.Style == ImageStyle.Triangle) 784 { 785 settings.ImageDefault.Crop = settings.ImageDefault.Crop == 5 ? settings.ImageDefault.Crop = 0 : settings.ImageDefault.Crop; 786 787 if (settings.ImageDefault != null) 788 { 789 settings.ImageDefault.Height = settings.ImageDefault.Width; 790 } 791 if (settings.ImageMedium != null) 792 { 793 settings.ImageMedium.Height = settings.ImageMedium.Width; 794 } 795 if (settings.ImageSmall != null) 796 { 797 settings.ImageSmall.Height = settings.ImageSmall.Width; 798 } 799 } 800 801 string defaultImage = imageEngine; 802 string imageSmall = ""; 803 string imageMedium = ""; 804 805 if (settings.DisableImageEngine) 806 { 807 defaultImage = settings.Path; 808 } 809 else 810 { 811 if (settings.ImageDefault != null) 812 { 813 defaultImage += Dynamicweb.Rapido.Services.Images.GetImagePathFromSettings(settings.ImageDefault); 814 815 if (settings.Path.GetType() != typeof(string)) 816 { 817 defaultImage += settings.Path != null ? "Image=" + settings.Path.PathUrlEncoded : ""; 818 defaultImage += settings.Path != null ? "&" + settings.Path.GetFocalPointParameters() : ""; 819 } 820 else 821 { 822 defaultImage += settings.Path != null ? "Image=" + settings.Path : ""; 823 } 824 825 defaultImage += "&AlternativeImage=" + alternativeImage; 826 } 827 828 if (settings.ImageSmall != null) 829 { 830 imageSmall = "data-src-small=\"" + imageEngine; 831 imageSmall += Dynamicweb.Rapido.Services.Images.GetImagePathFromSettings(settings.ImageSmall); 832 833 if (settings.Path.GetType() != typeof(string)) 834 { 835 imageSmall += settings.Path != null ? "Image=" + settings.Path.PathUrlEncoded : ""; 836 imageSmall += settings.Path != null ? "&" + settings.Path.GetFocalPointParameters() : ""; 837 } 838 else 839 { 840 imageSmall += settings.Path != null ? "Image=" + settings.Path : ""; 841 } 842 843 imageSmall += "&alternativeImage=" + alternativeImage; 844 845 imageSmall += "\""; 846 } 847 848 if (settings.ImageMedium != null) 849 { 850 imageMedium = "data-src-medium=\"" + imageEngine; 851 imageMedium += Dynamicweb.Rapido.Services.Images.GetImagePathFromSettings(settings.ImageMedium); 852 853 if (settings.Path.GetType() != typeof(string)) 854 { 855 imageMedium += settings.Path != null ? "Image=" + settings.Path.PathUrlEncoded : ""; 856 imageMedium += settings.Path != null ? "&" + settings.Path.GetFocalPointParameters() : ""; 857 } 858 else 859 { 860 imageMedium += settings.Path != null ? "Image=" + settings.Path : ""; 861 } 862 863 imageMedium += "&alternativeImage=" + alternativeImage; 864 865 imageMedium += "\""; 866 } 867 } 868 869 Dictionary<string, string> optionalAttributes = new Dictionary<string, string>(); 870 if (!string.IsNullOrEmpty(settings.OnClick)) { optionalAttributes.Add("onclick", settings.OnClick); } 871 if (!string.IsNullOrEmpty(settings.Title)) 872 { 873 optionalAttributes.Add("alt", settings.Title); 874 optionalAttributes.Add("title", settings.Title); 875 } 876 877 if (settings.DisableLazyLoad) 878 { 879 <img id="@settings.Id" class="@imageStyle @settings.CssClass dw-mod" src="@defaultImage" @ComponentMethods.AddAttributes(optionalAttributes) @ComponentMethods.AddAttributes(settings.ExtraAttributes) /> 880 } 881 else 882 { 883 <img id="@settings.Id" class="b-lazy @imageStyle @settings.CssClass dw-mod" src="@placeholderImage" data-src="@defaultImage" @imageSmall @imageMedium @ComponentMethods.AddAttributes(optionalAttributes) @ComponentMethods.AddAttributes(settings.ExtraAttributes) /> 884 } 885 } 886 } 887 @using System.Reflection 888 @using Dynamicweb.Rapido.Blocks.Components.General 889 @using Dynamicweb.Rapido.Blocks.Components 890 891 @* Component *@ 892 893 @helper RenderFileField(FileField settings) 894 { 895 var attributes = new Dictionary<string, string>(); 896 if (string.IsNullOrEmpty(settings.Id)) 897 { 898 settings.Id = Guid.NewGuid().ToString("N"); 899 } 900 901 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); } 902 if (settings.Disabled) { attributes.Add("disabled", "true"); } 903 if (settings.Required) { attributes.Add("required", "true"); } 904 if (settings.Multiple) { attributes.Add("multiple", "true"); } 905 if (!string.IsNullOrEmpty(settings.Name)) { attributes.Add("name", settings.Name); } 906 if (string.IsNullOrEmpty(settings.ChooseFileText)) 907 { 908 settings.ChooseFileText = Translate("Choose file"); 909 } 910 if (string.IsNullOrEmpty(settings.NoFilesChosenText)) 911 { 912 settings.NoFilesChosenText = Translate("No files chosen..."); 913 } 914 if (!string.IsNullOrEmpty(settings.OnClick)) { attributes.Add("onclick", settings.OnClick); } 915 916 if (settings.Required && !String.IsNullOrEmpty(settings.Label)) { settings.Label += " <span class=\"required dw-mod\">*</span>"; } 917 918 string setValueToFakeInput = "FileUpload.setValueToFakeInput(this)"; 919 attributes.Add("onchange", setValueToFakeInput + (!string.IsNullOrEmpty(settings.OnChange) ? settings.OnChange : "")); 920 921 attributes.Add("type", "file"); 922 if (settings.Value != null) { attributes.Add("value", settings.Value); } 923 settings.CssClass = "u-full-width " + settings.CssClass; 924 925 var resultAttributes = attributes.Concat(settings.ExtraAttributes).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.Last().Value); 926 927 <div class="form__field-group u-full-width @settings.WrapperCssClass dw-mod"> 928 @if (!string.IsNullOrEmpty(settings.Label) || settings.Link != null ) 929 { 930 <div class="u-full-width"> 931 @if (!string.IsNullOrEmpty(settings.Label)) { <label for="@settings.Id" class="u-pull--left">@settings.Label</label> } 932 @if (settings.Link != null) { 933 <div class="u-pull--right"> 934 @{ settings.Link.ButtonLayout = ButtonLayout.LinkClean; } 935 @Render(settings.Link) 936 </div> 937 } 938 </div> 939 940 } 941 942 @if (!string.IsNullOrEmpty(settings.HelpText)) 943 { 944 <small class="form__help-text">@settings.HelpText</small> 945 } 946 947 <div class="form__field-combi file-input u-no-margin dw-mod"> 948 <input @ComponentMethods.AddAttributes(resultAttributes) class="file-input__real-input" data-no-files-text="@settings.NoFilesChosenText" data-many-files-text="@Translate("files")" /> 949 <label for="@settings.Id" class="file-input__btn btn--secondary btn dw-mod">@settings.ChooseFileText</label> 950 <label for="@settings.Id" class="@settings.CssClass file-input__fake-input js-fake-input dw-mod">@settings.NoFilesChosenText</label> 951 @if (settings.UploadButton != null) 952 { 953 settings.UploadButton.CssClass += " btn--condensed u-no-margin"; 954 @Render(settings.UploadButton) 955 } 956 </div> 957 @Render(new NotificationMessage { Message = settings.ErrorMessage }) 958 </div> 959 } 960 @using System.Reflection 961 @using Dynamicweb.Rapido.Blocks.Components.General 962 @using Dynamicweb.Rapido.Blocks.Components 963 @using Dynamicweb.Core 964 @using System.Linq 965 966 @* Component *@ 967 968 @helper RenderDateTimeField(DateTimeField settings) 969 { 970 if (string.IsNullOrEmpty(settings.Id)) 971 { 972 settings.Id = Guid.NewGuid().ToString("N"); 973 } 974 975 var textField = new TextField { 976 Name = settings.Name, 977 Id = settings.Id, 978 Label = settings.Label, 979 HelpText = settings.HelpText, 980 Value = settings.Value, 981 Disabled = settings.Disabled, 982 Required = settings.Required, 983 ErrorMessage = settings.ErrorMessage, 984 CssClass = settings.CssClass, 985 WrapperCssClass = settings.WrapperCssClass, 986 OnChange = settings.OnChange, 987 OnClick = settings.OnClick, 988 Link = settings.Link, 989 ExtraAttributes = settings.ExtraAttributes, 990 // 991 Placeholder = settings.Placeholder 992 }; 993 994 @Render(textField) 995 996 List<string> jsAttributes = new List<string>(); 997 998 jsAttributes.Add("mode: '" + Enum.GetName(typeof(DateTimeFieldMode), settings.Mode).ToLower() + "'"); 999 1000 if (!string.IsNullOrEmpty(settings.DateFormat)) 1001 { 1002 jsAttributes.Add("dateFormat: '" + settings.DateFormat + "'"); 1003 } 1004 if (!string.IsNullOrEmpty(settings.MinDate)) 1005 { 1006 jsAttributes.Add("minDate: '" + settings.MinDate + "'"); 1007 } 1008 if (!string.IsNullOrEmpty(settings.MaxDate)) 1009 { 1010 jsAttributes.Add("maxDate: '" + settings.MaxDate + "'"); 1011 } 1012 if (settings.IsInline) 1013 { 1014 jsAttributes.Add("inline: " + Converter.ToString(settings.IsInline).ToLower()); 1015 } 1016 if (settings.EnableTime) 1017 { 1018 jsAttributes.Add("enableTime: " + Converter.ToString(settings.EnableTime).ToLower()); 1019 } 1020 if (settings.EnableWeekNumbers) 1021 { 1022 jsAttributes.Add("weekNumbers: " + Converter.ToString(settings.EnableWeekNumbers).ToLower()); 1023 } 1024 1025 jsAttributes.AddRange(settings.GetFlatPickrOptions().Select(x => x.Key + ": " + x.Value)); 1026 1027 <script> 1028 document.addEventListener("DOMContentLoaded", function () { 1029 flatpickr("#@textField.Id", { 1030 @string.Join(",", jsAttributes) 1031 }); 1032 }); 1033 </script> 1034 } 1035 @using System.Reflection 1036 @using Dynamicweb.Rapido.Blocks.Components.General 1037 @using Dynamicweb.Rapido.Blocks.Components 1038 1039 @* Component *@ 1040 1041 @helper RenderTextField(TextField settings) 1042 { 1043 var attributes = new Dictionary<string, string>(); 1044 if (!string.IsNullOrEmpty(settings.Label) && string.IsNullOrEmpty(settings.Id)) 1045 { 1046 settings.Id = Guid.NewGuid().ToString("N"); 1047 } 1048 1049 /*base settings*/ 1050 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); } 1051 if (!string.IsNullOrEmpty(settings.OnClick)) { attributes.Add("onclick", settings.OnClick); } 1052 if (!string.IsNullOrEmpty(settings.OnChange)) { attributes.Add("onchange", settings.OnChange); } 1053 if (settings.Disabled) { attributes.Add("disabled", "true"); } 1054 if (settings.Required) { attributes.Add("required", "true"); } 1055 if (!string.IsNullOrEmpty(settings.Name)) { attributes.Add("name", settings.Name); } 1056 /*end*/ 1057 1058 if (!string.IsNullOrEmpty(settings.OnKeyUp)) { attributes.Add("onkeyup", settings.OnKeyUp); } 1059 if (!string.IsNullOrEmpty(settings.OnInput)) { attributes.Add("oninput", settings.OnInput); } 1060 if (!string.IsNullOrEmpty(settings.OnFocus)) { attributes.Add("onfocus", settings.OnFocus); } 1061 if (settings.ReadOnly) { attributes.Add("readonly", "true"); } 1062 if (settings.MaxLength != 0) { attributes.Add("maxlength", settings.MaxLength.ToString()); } 1063 if (!string.IsNullOrEmpty(settings.Placeholder)) { attributes.Add("placeholder", settings.Placeholder); } 1064 attributes.Add("type", Enum.GetName(typeof(TextFieldType), settings.Type).ToLower()); 1065 if (settings.Type == TextFieldType.Password) { attributes.Add("autocomplete", "off"); }; 1066 if (settings.Value != null) { attributes.Add("value", settings.Value); } 1067 1068 settings.CssClass = "u-full-width " + settings.CssClass; 1069 1070 if (settings.Required && !String.IsNullOrEmpty(settings.Label)) { settings.Label += " <span class=\"required dw-mod\">*</span>"; } 1071 1072 var resultAttributes = attributes.Concat(settings.ExtraAttributes).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.Last().Value); 1073 1074 string noMargin = "u-no-margin"; 1075 if (!settings.ReadOnly) { 1076 noMargin = ""; 1077 } 1078 1079 <div class="form__field-group u-full-width @noMargin @settings.WrapperCssClass dw-mod"> 1080 @if (!string.IsNullOrEmpty(settings.Label) || settings.Link != null ) 1081 { 1082 <div class="u-full-width"> 1083 @if (!string.IsNullOrEmpty(settings.Label)) { <label for="@settings.Id" class="u-pull--left">@settings.Label</label> } 1084 @if (settings.Link != null) { 1085 settings.Link.ButtonLayout = ButtonLayout.LinkClean; 1086 1087 <div class="u-pull--right"> 1088 @Render(settings.Link) 1089 </div> 1090 } 1091 </div> 1092 1093 } 1094 1095 @if (!string.IsNullOrEmpty(settings.HelpText)) 1096 { 1097 <small class="form__help-text">@settings.HelpText</small> 1098 } 1099 1100 @if (settings.ActionButton != null) 1101 { 1102 settings.ActionButton.CssClass += " btn--condensed u-no-margin"; 1103 <div class="form__field-combi u-no-margin dw-mod"> 1104 <input @ComponentMethods.AddAttributes(resultAttributes) class="@settings.CssClass dw-mod" /> 1105 @Render(settings.ActionButton) 1106 </div> 1107 } 1108 else 1109 { 1110 <input @ComponentMethods.AddAttributes(resultAttributes) class="@settings.CssClass dw-mod" /> 1111 } 1112 1113 @Render(new NotificationMessage { Message = settings.ErrorMessage }) 1114 </div> 1115 } 1116 @using System.Reflection 1117 @using Dynamicweb.Rapido.Blocks.Components.General 1118 @using Dynamicweb.Rapido.Blocks.Components 1119 1120 @* Component *@ 1121 1122 @helper RenderNumberField(NumberField settings) 1123 { 1124 var attributes = new Dictionary<string, string>(); 1125 if (!string.IsNullOrEmpty(settings.Label) && string.IsNullOrEmpty(settings.Id)) 1126 { 1127 settings.Id = Guid.NewGuid().ToString("N"); 1128 } 1129 1130 /*base settings*/ 1131 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); } 1132 if (!string.IsNullOrEmpty(settings.OnClick)) { attributes.Add("onclick", settings.OnClick); } 1133 if (!string.IsNullOrEmpty(settings.OnChange)) { attributes.Add("onchange", settings.OnChange); } 1134 if (settings.Disabled) { attributes.Add("disabled", "true"); } 1135 if (settings.Required) { attributes.Add("required", "true"); } 1136 if (!string.IsNullOrEmpty(settings.Name)) { attributes.Add("name", settings.Name); } 1137 /*end*/ 1138 1139 if (!string.IsNullOrEmpty(settings.OnKeyUp)) { attributes.Add("onkeyup", settings.OnKeyUp); } 1140 if (!string.IsNullOrEmpty(settings.OnInput)) { attributes.Add("oninput", settings.OnInput); } 1141 if (!string.IsNullOrEmpty(settings.OnFocus)) { attributes.Add("onfocus", settings.OnFocus); } 1142 if (settings.ReadOnly) { attributes.Add("readonly", "true"); } 1143 if (settings.Max != null) { attributes.Add("max", settings.Max.ToString()); } 1144 if (settings.Min != null) { attributes.Add("min", settings.Min.ToString()); } 1145 if (settings.Step != 0) { attributes.Add("step", settings.Step.ToString()); } 1146 if (settings.Value != null && !string.IsNullOrEmpty(settings.Value.ToString())) { attributes.Add("value", settings.Value.ToString()); } 1147 attributes.Add("type", "number"); 1148 1149 var resultAttributes = attributes.Concat(settings.ExtraAttributes).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.Last().Value); 1150 1151 <div class="form__field-group u-full-width @settings.WrapperCssClass dw-mod"> 1152 @if (!string.IsNullOrEmpty(settings.Label) || settings.Link != null ) 1153 { 1154 <div class="u-full-width"> 1155 @if (!string.IsNullOrEmpty(settings.Label)) { <label for="@settings.Id" class="u-pull--left">@settings.Label</label> } 1156 @if (settings.Link != null) { 1157 <div class="u-pull--right"> 1158 @{ settings.Link.ButtonLayout = ButtonLayout.LinkClean; } 1159 @Render(settings.Link) 1160 </div> 1161 } 1162 </div> 1163 1164 } 1165 1166 @if (!string.IsNullOrEmpty(settings.HelpText)) 1167 { 1168 <small class="form__help-text">@settings.HelpText</small> 1169 } 1170 1171 @if (settings.ActionButton != null) 1172 { 1173 settings.ActionButton.CssClass += " btn--condensed u-no-margin"; 1174 <div class="form__field-combi u-no-margin dw-mod"> 1175 <input @ComponentMethods.AddAttributes(resultAttributes) class="@settings.CssClass dw-mod" /> 1176 @Render(settings.ActionButton) 1177 </div> 1178 } 1179 else 1180 { 1181 <div class="form__field-combi u-no-margin dw-mod"> 1182 <input @ComponentMethods.AddAttributes(resultAttributes) class="@settings.CssClass dw-mod" /> 1183 </div> 1184 } 1185 1186 @Render(new NotificationMessage { Message = settings.ErrorMessage }) 1187 </div> 1188 } 1189 @using System.Reflection 1190 @using Dynamicweb.Rapido.Blocks.Components.General 1191 @using Dynamicweb.Rapido.Blocks.Components 1192 1193 1194 @* Component *@ 1195 1196 @helper RenderTextareaField(TextareaField settings) 1197 { 1198 Dictionary<string, string> attributes = new Dictionary<string, string>(); 1199 string id = settings.Id; 1200 if (!string.IsNullOrEmpty(settings.Label) && string.IsNullOrEmpty(id)) 1201 { 1202 id = Guid.NewGuid().ToString("N"); 1203 } 1204 1205 if (!string.IsNullOrEmpty(id)) { attributes.Add("id", id); } 1206 if (!string.IsNullOrEmpty(settings.OnClick)) { attributes.Add("onclick", settings.OnClick); } 1207 if (!string.IsNullOrEmpty(settings.OnKeyUp)) { attributes.Add("onkeyup", settings.OnKeyUp); } 1208 if (!string.IsNullOrEmpty(settings.OnInput)) { attributes.Add("oninput", settings.OnInput); } 1209 if (!string.IsNullOrEmpty(settings.OnFocus)) { attributes.Add("onfocus", settings.OnFocus); } 1210 if (!string.IsNullOrEmpty(settings.OnChange)) { attributes.Add("onchange", settings.OnChange); } 1211 if (!string.IsNullOrEmpty(settings.Placeholder)) { attributes.Add("placeholder", settings.Placeholder); } 1212 if (settings.Disabled) { attributes.Add("disabled", "true"); } 1213 if (settings.Required) { attributes.Add("required", "true"); } 1214 if (settings.ReadOnly) { attributes.Add("readonly", "true"); } 1215 if (settings.MaxLength != 0) { attributes.Add("maxlength", settings.MaxLength.ToString()); } 1216 if (settings.Rows != 0) { attributes.Add("rows", settings.Rows.ToString()); } 1217 attributes.Add("name", settings.Name); 1218 1219 if (settings.Required && !String.IsNullOrEmpty(settings.Label)) { settings.Label += " <span class=\"required dw-mod\">*</span>"; } 1220 1221 <div class="form__field-group @settings.WrapperCssClass dw-mod"> 1222 @if (!string.IsNullOrEmpty(settings.Label) || settings.Link != null ) 1223 { 1224 <div class="u-full-width"> 1225 @if (!string.IsNullOrEmpty(settings.Label)) { <label for="@settings.Id" class="u-pull--left">@settings.Label</label> } 1226 @if (settings.Link != null) { 1227 <div class="u-pull--right"> 1228 @{ settings.Link.ButtonLayout = ButtonLayout.LinkClean; } 1229 @Render(settings.Link) 1230 </div> 1231 } 1232 </div> 1233 } 1234 1235 @if (!string.IsNullOrEmpty(settings.HelpText)) 1236 { 1237 <small class="form__help-text">@settings.HelpText</small> 1238 } 1239 1240 <textarea class="u-full-width @settings.CssClass dw-mod" @ComponentMethods.AddAttributes(attributes) @ComponentMethods.AddAttributes(settings.ExtraAttributes)>@settings.Value</textarea> 1241 1242 @Render(new NotificationMessage { Message = settings.ErrorMessage }) 1243 </div> 1244 } 1245 @using System.Reflection 1246 @using Dynamicweb.Rapido.Blocks.Components.General 1247 @using Dynamicweb.Rapido.Blocks.Components 1248 1249 1250 @* Component *@ 1251 1252 @helper RenderHiddenField(HiddenField settings) { 1253 var attributes = new Dictionary<string, string>(); 1254 attributes.Add("type", "hidden"); 1255 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); } 1256 if (settings.Value != null) { attributes.Add("value", settings.Value); } 1257 if (!string.IsNullOrEmpty(settings.Name)) { attributes.Add("name", settings.Name); } 1258 1259 <input @ComponentMethods.AddAttributes(attributes) @ComponentMethods.AddAttributes(settings.ExtraAttributes)/> 1260 } 1261 @using System.Reflection 1262 @using Dynamicweb.Rapido.Blocks.Components.General 1263 @using Dynamicweb.Rapido.Blocks.Components 1264 1265 @* Component *@ 1266 1267 @helper RenderCheckboxField(CheckboxField settings) 1268 { 1269 var attributes = new Dictionary<string, string>(); 1270 if (!string.IsNullOrEmpty(settings.Label) && string.IsNullOrEmpty(settings.Id)) 1271 { 1272 settings.Id = Guid.NewGuid().ToString("N"); 1273 } 1274 1275 /*base settings*/ 1276 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); } 1277 if (!string.IsNullOrEmpty(settings.OnClick)) { attributes.Add("onclick", settings.OnClick); } 1278 if (!string.IsNullOrEmpty(settings.OnChange)) { attributes.Add("onchange", settings.OnChange); } 1279 if (settings.Disabled) { attributes.Add("disabled", "true"); } 1280 if (settings.Required) { attributes.Add("required", "true"); } 1281 if (!string.IsNullOrEmpty(settings.Name)) { attributes.Add("name", settings.Name); } 1282 /*end*/ 1283 1284 if (settings.Required && !String.IsNullOrEmpty(settings.Label)) { settings.Label += " <span class=\"required dw-mod\">*</span>"; } 1285 1286 attributes.Add("type", "checkbox"); 1287 if (settings.Checked) { attributes.Add("checked", "true"); } 1288 settings.CssClass = "form__control " + settings.CssClass; 1289 if (settings.Value != null) { attributes.Add("value", settings.Value); } 1290 1291 var resultAttributes = attributes.Concat(settings.ExtraAttributes).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.Last().Value); 1292 1293 <div class="form__field-group @settings.WrapperCssClass dw-mod"> 1294 <input @ComponentMethods.AddAttributes(resultAttributes) class="@settings.CssClass dw-mod" /> 1295 @if (!string.IsNullOrEmpty(settings.Label)) 1296 { 1297 <label for="@settings.Id" class="dw-mod">@settings.Label</label> 1298 } 1299 1300 @if (settings.Link != null) { 1301 <span> 1302 @{ settings.Link.ButtonLayout = ButtonLayout.LinkClean; } 1303 @Render(settings.Link) 1304 </span> 1305 } 1306 1307 @if (!string.IsNullOrEmpty(settings.HelpText)) 1308 { 1309 <small class="form__help-text checkbox-help dw-mod">@settings.HelpText</small> 1310 } 1311 @Render(new NotificationMessage { Message = settings.ErrorMessage }) 1312 </div> 1313 } 1314 @using System.Reflection 1315 @using Dynamicweb.Rapido.Blocks.Components.General 1316 @using Dynamicweb.Rapido.Blocks.Components 1317 1318 1319 @* Component *@ 1320 1321 @helper RenderCheckboxListField(CheckboxListField settings) 1322 { 1323 <div class="form__field-group @settings.WrapperCssClass u-margin-bottom dw-mod" @ComponentMethods.AddAttributes(settings.ExtraAttributes)> 1324 @if (!string.IsNullOrEmpty(settings.Label) || settings.Link != null ) 1325 { 1326 <div class="u-full-width"> 1327 @if (!string.IsNullOrEmpty(settings.Label)) { <label for="@settings.Id" class="u-pull--left">@settings.Label</label> } 1328 @if (settings.Link != null) { 1329 <div class="u-pull--right"> 1330 @{ settings.Link.ButtonLayout = ButtonLayout.LinkClean; } 1331 @Render(settings.Link) 1332 </div> 1333 } 1334 </div> 1335 1336 } 1337 1338 <div class="u-pull--left"> 1339 @if (!string.IsNullOrEmpty(settings.HelpText)) 1340 { 1341 <small class="form__help-text">@settings.HelpText</small> 1342 } 1343 1344 @foreach (var item in settings.Options) 1345 { 1346 if (settings.Required) 1347 { 1348 item.Required = true; 1349 } 1350 if (settings.Disabled) 1351 { 1352 item.Disabled = true; 1353 } 1354 if (!string.IsNullOrEmpty(settings.Name)) 1355 { 1356 item.Name = settings.Name; 1357 } 1358 if (!string.IsNullOrEmpty(settings.CssClass)) 1359 { 1360 item.CssClass += settings.CssClass; 1361 } 1362 1363 /* value is not supported */ 1364 1365 if (!string.IsNullOrEmpty(settings.OnClick)) 1366 { 1367 item.OnClick += settings.OnClick; 1368 } 1369 if (!string.IsNullOrEmpty(settings.OnChange)) 1370 { 1371 item.OnChange += settings.OnChange; 1372 } 1373 @Render(item) 1374 } 1375 1376 @Render(new NotificationMessage { Message = settings.ErrorMessage }) 1377 </div> 1378 1379 </div> 1380 } 1381 @using Dynamicweb.Rapido.Blocks.Components.General 1382 1383 @* Component *@ 1384 1385 @helper RenderSearch(Search settings) 1386 { 1387 var searchValue = HttpContext.Current.Request.QueryString.Get(settings.SearchParameter) ?? ""; 1388 var groupValue = HttpContext.Current.Request.QueryString.Get(settings.GroupsParameter) ?? ""; 1389 1390 if (string.IsNullOrEmpty(settings.Id)) 1391 { 1392 settings.Id = Guid.NewGuid().ToString("N"); 1393 } 1394 1395 var resultAttributes = new Dictionary<string, string>(); 1396 1397 if (settings.PageSize != 0) 1398 { 1399 resultAttributes.Add("data-page-size", settings.PageSize.ToString()); 1400 } 1401 if (!string.IsNullOrEmpty(settings.GroupItemsFeedUrl)) 1402 { 1403 resultAttributes.Add("data-groups-feed-url", settings.GroupItemsFeedUrl); 1404 if (!string.IsNullOrEmpty(groupValue)) 1405 { 1406 resultAttributes.Add("data-selected-group", groupValue); 1407 } 1408 if (!string.IsNullOrEmpty(settings.GroupsParameter)) 1409 { 1410 resultAttributes.Add("data-groups-parameter", settings.GroupsParameter); 1411 } 1412 } 1413 resultAttributes.Add("data-force-init", "true"); 1414 if (settings.GoToFirstSearchResultOnEnter) 1415 { 1416 resultAttributes.Add("data-go-to-first-search-result-on-enter", settings.GoToFirstSearchResultOnEnter.ToString().ToLower()); 1417 } 1418 if (!string.IsNullOrEmpty(settings.SearchParameter)) 1419 { 1420 resultAttributes.Add("data-search-parameter", settings.SearchParameter); 1421 } 1422 resultAttributes.Add("data-search-feed-url", settings.SearchData.SearchFeedUrl); 1423 resultAttributes.Add("data-results-template-id", settings.SearchData.ResultsTemplateId); 1424 1425 if (settings.SecondSearchData != null) 1426 { 1427 resultAttributes.Add("data-second-search-feed-url", settings.SecondSearchData.SearchFeedUrl); 1428 resultAttributes.Add("data-second-results-template-id", settings.SecondSearchData.ResultsTemplateId); 1429 } 1430 if (!string.IsNullOrEmpty(settings.ResultsPageUrl)) 1431 { 1432 resultAttributes.Add("data-results-page-url", settings.ResultsPageUrl); 1433 } 1434 1435 resultAttributes = resultAttributes.Concat(settings.ExtraAttributes).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.Last().Value); 1436 1437 string searchFieldCss = (settings.SearchButton == null) ? "search--with-icon" : ""; 1438 1439 <div class="search @settings.CssClass @searchFieldCss js-search-data-source dw-mod" id="@settings.Id" @ComponentMethods.AddAttributes(resultAttributes)> 1440 @if (!string.IsNullOrEmpty(settings.GroupItemsFeedUrl)) 1441 { 1442 <button type="button" class="search__groups-btn dw-mod js-search-groups-btn">@Translate("All")</button> 1443 <ul class="dropdown dropdown--absolute-position dw-mod search__groups-results js-search-groups-list"></ul> 1444 } 1445 1446 <input type="text" class="search__field dw-mod js-search-field" placeholder="@settings.Placeholder" value="@searchValue"> 1447 1448 <div class="dropdown dropdown--absolute-position search__results dw-mod js-search-results @(settings.SecondSearchData != null ? "search__results--combined" : "")"> 1449 @if (settings.SecondSearchData != null) 1450 { 1451 <div class="search__column search__column--products dw-mod"> 1452 <div class="search__column-header dw-mod">@Translate("Products")</div> 1453 <ul class="search__results-list dw-mod js-search-results-list" id="@(settings.Id)_ResultsList"></ul> 1454 @if (!string.IsNullOrEmpty(settings.SearchData.ResultsPageUrl)) 1455 { 1456 @Render(new Link { 1457 Title = Translate("View all"), 1458 CssClass = "js-view-all-button u-margin", 1459 Href = settings.SearchData.ResultsPageUrl 1460 }); 1461 } 1462 </div> 1463 <div class="search__column search__column--pages dw-mod"> 1464 <div class="search__column-header">@Translate("Pages")</div> 1465 <ul class="search__results-list dw-mod js-search-results-second-list" id="@(settings.Id)_SecondResultsList"></ul> 1466 @if (!string.IsNullOrEmpty(settings.SecondSearchData.ResultsPageUrl)) 1467 { 1468 @Render(new Link 1469 { 1470 Title = Translate("View all"), 1471 CssClass = "js-view-all-button u-margin", 1472 Href = settings.SecondSearchData.ResultsPageUrl 1473 }); 1474 } 1475 </div> 1476 } 1477 else 1478 { 1479 <div class="search__column search__column--only dw-mod"> 1480 <ul class="search__results-list dw-mod js-search-results-list" id="@(settings.Id)_ResultsList"></ul> 1481 @if (!string.IsNullOrEmpty(settings.SearchData.ResultsPageUrl)) 1482 { 1483 @Render(new Link { 1484 Title = Translate("View all"), 1485 CssClass = "js-view-all-button u-margin", 1486 Href = settings.SearchData.ResultsPageUrl 1487 }); 1488 } 1489 </div> 1490 } 1491 </div> 1492 1493 @if (settings.SearchButton != null) 1494 { 1495 settings.SearchButton.CssClass += " search__btn js-search-btn"; 1496 if (settings.RenderDefaultSearchIcon) 1497 { 1498 settings.SearchButton.Icon = new Icon { Name = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("SearchIcon").SelectedValue }; 1499 } 1500 @Render(settings.SearchButton); 1501 } 1502 </div> 1503 } 1504 @using System.Reflection 1505 @using Dynamicweb.Rapido.Blocks.Components.General 1506 @using Dynamicweb.Rapido.Blocks.Components 1507 1508 1509 @* Component *@ 1510 1511 @helper RenderSelectField(SelectField settings) 1512 { 1513 if (!string.IsNullOrEmpty(settings.Label) && string.IsNullOrEmpty(settings.Id)) 1514 { 1515 settings.Id = Guid.NewGuid().ToString("N"); 1516 } 1517 1518 <div class="form__field-group u-full-width @settings.WrapperCssClass dw-mod"> 1519 @if (!string.IsNullOrEmpty(settings.Label) || settings.Link != null ) 1520 { 1521 <div class="u-full-width"> 1522 @if (!string.IsNullOrEmpty(settings.Label)) { <label for="@settings.Id" class="u-pull--left">@settings.Label</label> } 1523 @if (settings.Link != null) { 1524 <div class="u-pull--right"> 1525 @{ settings.Link.ButtonLayout = ButtonLayout.LinkClean; } 1526 @Render(settings.Link) 1527 </div> 1528 } 1529 </div> 1530 } 1531 1532 @if (!string.IsNullOrEmpty(settings.HelpText)) 1533 { 1534 <small class="form__help-text">@settings.HelpText</small> 1535 } 1536 1537 @if (settings.ActionButton != null) 1538 { 1539 settings.ActionButton.CssClass += " btn--condensed u-no-margin"; 1540 <div class="form__field-combi u-no-margin dw-mod"> 1541 @RenderSelectBase(settings) 1542 @Render(settings.ActionButton) 1543 </div> 1544 } 1545 else 1546 { 1547 @RenderSelectBase(settings) 1548 } 1549 1550 @Render(new NotificationMessage { Message = settings.ErrorMessage }) 1551 </div> 1552 } 1553 1554 @helper RenderSelectBase(SelectField settings) 1555 { 1556 var attributes = new Dictionary<string, string>(); 1557 1558 /*base settings*/ 1559 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); } 1560 if (!string.IsNullOrEmpty(settings.OnClick)) { attributes.Add("onclick", settings.OnClick); } 1561 if (!string.IsNullOrEmpty(settings.OnChange)) { attributes.Add("onchange", settings.OnChange); } 1562 if (settings.Disabled) { attributes.Add("disabled", "true"); } 1563 if (settings.Required) { attributes.Add("required", "true"); } 1564 if (!string.IsNullOrEmpty(settings.Name)) { attributes.Add("name", settings.Name); } 1565 /*end*/ 1566 1567 var resultAttributes = attributes.Concat(settings.ExtraAttributes).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.Last().Value); 1568 1569 <select @ComponentMethods.AddAttributes(resultAttributes) class="u-full-width @settings.CssClass dw-mod"> 1570 @if (settings.Default != null) 1571 { 1572 @Render(settings.Default) 1573 } 1574 1575 @foreach (var item in settings.Options) 1576 { 1577 if (settings.Value != null) { 1578 item.Checked = item.Value == settings.Value; 1579 } 1580 @Render(item) 1581 } 1582 </select> 1583 } 1584 @using System.Reflection 1585 @using Dynamicweb.Rapido.Blocks.Components.General 1586 @using Dynamicweb.Rapido.Blocks.Components 1587 1588 @* Component *@ 1589 1590 @helper RenderRadioButtonField(RadioButtonField settings) 1591 { 1592 var attributes = new Dictionary<string, string>(); 1593 if (!string.IsNullOrEmpty(settings.Label) && string.IsNullOrEmpty(settings.Id)) 1594 { 1595 settings.Id = Guid.NewGuid().ToString("N"); 1596 } 1597 1598 /*base settings*/ 1599 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); } 1600 if (!string.IsNullOrEmpty(settings.OnClick)) { attributes.Add("onclick", settings.OnClick); } 1601 if (!string.IsNullOrEmpty(settings.OnChange)) { attributes.Add("onchange", settings.OnChange); } 1602 if (settings.Disabled) { attributes.Add("disabled", "true"); } 1603 if (settings.Required) { attributes.Add("required", "true"); } 1604 if (!string.IsNullOrEmpty(settings.Name)) { attributes.Add("name", settings.Name); } 1605 /*end*/ 1606 1607 attributes.Add("type", "radio"); 1608 if (settings.Checked) { attributes.Add("checked", "true"); } 1609 settings.CssClass = "form__control " + settings.CssClass; 1610 if (settings.Value != null) { attributes.Add("value", settings.Value); } 1611 1612 var resultAttributes = attributes.Concat(settings.ExtraAttributes).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.Last().Value); 1613 1614 <div class="form__field-group @settings.WrapperCssClass dw-mod"> 1615 <input @ComponentMethods.AddAttributes(resultAttributes) class="@settings.CssClass dw-mod" /> 1616 @if (!string.IsNullOrEmpty(settings.Label)) 1617 { 1618 <label for="@settings.Id" class="dw-mod">@settings.Label</label> 1619 } 1620 @if (!string.IsNullOrEmpty(settings.HelpText)) 1621 { 1622 <small class="form__help-text">@settings.HelpText</small> 1623 } 1624 @Render(new NotificationMessage { Message = settings.ErrorMessage }) 1625 </div> 1626 } 1627 @using System.Reflection 1628 @using Dynamicweb.Rapido.Blocks.Components.General 1629 @using Dynamicweb.Rapido.Blocks.Components 1630 1631 1632 @* Component *@ 1633 1634 @helper RenderRadioButtonListField(RadioButtonListField settings) 1635 { 1636 if (settings.Required && !String.IsNullOrEmpty(settings.Label)) { settings.Label += " <span class=\"required dw-mod\">*</span>"; } 1637 1638 <div class="form__field-group @settings.WrapperCssClass u-margin-bottom dw-mod" @ComponentMethods.AddAttributes(settings.ExtraAttributes)> 1639 @if (!string.IsNullOrEmpty(settings.Label)) 1640 { 1641 <label>@settings.Label</label> 1642 } 1643 @if (!string.IsNullOrEmpty(settings.HelpText)) 1644 { 1645 <small class="form__help-text">@settings.HelpText</small> 1646 } 1647 1648 @foreach (var item in settings.Options) 1649 { 1650 if (settings.Required) 1651 { 1652 item.Required = true; 1653 } 1654 if (settings.Disabled) 1655 { 1656 item.Disabled = true; 1657 } 1658 if (!string.IsNullOrEmpty(settings.Name)) 1659 { 1660 item.Name = settings.Name; 1661 } 1662 if (settings.Value != null && settings.Value == item.Value) 1663 { 1664 item.Checked = true; 1665 } 1666 if (!string.IsNullOrEmpty(settings.OnClick)) 1667 { 1668 item.OnClick += settings.OnClick; 1669 } 1670 if (!string.IsNullOrEmpty(settings.OnChange)) 1671 { 1672 item.OnChange += settings.OnChange; 1673 } 1674 if (!string.IsNullOrEmpty(settings.CssClass)) 1675 { 1676 item.CssClass += settings.CssClass; 1677 } 1678 @Render(item) 1679 } 1680 1681 @Render(new NotificationMessage { Message = settings.ErrorMessage }) 1682 </div> 1683 } 1684 @using System.Reflection 1685 @using Dynamicweb.Rapido.Blocks.Components.General 1686 @using Dynamicweb.Rapido.Blocks.Components 1687 1688 1689 @* Component *@ 1690 1691 @helper RenderNotificationMessage(NotificationMessage settings) 1692 { 1693 if (!string.IsNullOrEmpty(settings.Message)) 1694 { 1695 var attributes = new Dictionary<string, string>(); 1696 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); } 1697 1698 string messageTypeClass = Enum.GetName(typeof(NotificationMessageType), settings.MessageType).ToLower(); 1699 string messageLayoutClass = Enum.GetName(typeof(NotificationMessageLayout), settings.MessageLayout).ToLower(); 1700 string minHeightClass = settings.Icon != null ? "u-min-h70px" : ""; 1701 1702 <div class="notification-message-@messageTypeClass notification-message-@messageLayoutClass @messageLayoutClass @minHeightClass @settings.CssClass u-full-width dw-mod" @ComponentMethods.AddAttributes(attributes)> 1703 @if (settings.Icon != null) { 1704 settings.Icon.Label = !string.IsNullOrEmpty(settings.Icon.Label) ? settings.Message + settings.Icon.Label : settings.Message; 1705 @Render(settings.Icon) 1706 } else { 1707 @settings.Message 1708 } 1709 </div> 1710 } 1711 } 1712 @using Dynamicweb.Rapido.Blocks.Components.General 1713 1714 1715 @* Component *@ 1716 1717 @helper RenderHandlebarsRoot(HandlebarsRoot settings) { 1718 string preRender = !String.IsNullOrEmpty(settings.PreRenderScriptTemplate) ? "data-pre-render-template=\"" + settings.PreRenderScriptTemplate + "\"" : ""; 1719 1720 <div class="@settings.CssClass dw-mod js-handlebars-root" id="@settings.Id" data-template="@settings.ScriptTemplate" data-json-feed="@settings.FeedUrl" data-init-onload="@settings.InitOnLoad.ToString()" data-preloader="@settings.Preloader" @preRender> 1721 @if (settings.SubBlocks != null) { 1722 @RenderBlockList(settings.SubBlocks) 1723 } 1724 </div> 1725 } 1726 @using System.Reflection 1727 @using Dynamicweb.Rapido.Blocks.Components.General 1728 @using Dynamicweb.Rapido.Blocks.Components 1729 @using System.Text.RegularExpressions 1730 1731 1732 @* Component *@ 1733 1734 @helper RenderSticker(Sticker settings) { 1735 if (!String.IsNullOrEmpty(settings.Title)) { 1736 string size = settings.Size.ToString() != "None" ? "" + "stickers-container__tag--" + settings.Size.ToString().ToLower() : ""; 1737 string style = settings.Style.ToString() != "None" ? "" + "stickers-container__tag--" + settings.Style.ToString().ToLower() : ""; 1738 1739 Dictionary<String, String> optionalAttributes = new Dictionary<string, string>(); 1740 if (!String.IsNullOrEmpty(settings.Color) || !String.IsNullOrEmpty(settings.BackgroundColor)) { 1741 string styleTag = !String.IsNullOrEmpty(settings.Color) ? "color: " + settings.Color + "; " : ""; 1742 styleTag += !String.IsNullOrEmpty(settings.BackgroundColor) ? "background-color: " + settings.BackgroundColor + "; " : ""; 1743 optionalAttributes.Add("style", styleTag); 1744 } 1745 1746 <div class="stickers-container__tag @size @style @settings.CssClass dw-mod" @ComponentMethods.AddAttributes(optionalAttributes) @ComponentMethods.AddAttributes(settings.ExtraAttributes)>@settings.Title</div> 1747 } 1748 } 1749 1750 @using System.Reflection 1751 @using Dynamicweb.Rapido.Blocks.Components.General 1752 @using Dynamicweb.Rapido.Blocks.Components 1753 1754 1755 @* Component *@ 1756 1757 @helper RenderStickersCollection(StickersCollection settings) 1758 { 1759 if (settings.Stickers.Count > 0) 1760 { 1761 string position = "stickers-container--" + Regex.Replace(settings.Position.ToString(), "([a-z])([A-Z])", "$1-$2").ToLower(); 1762 1763 <div class="stickers-container @position @settings.CssClass dw-mod" @ComponentMethods.AddAttributes(settings.ExtraAttributes)> 1764 @foreach (Sticker sticker in settings.Stickers) 1765 { 1766 @Render(sticker) 1767 } 1768 </div> 1769 } 1770 } 1771 1772 @using Dynamicweb.Rapido.Blocks.Components.General 1773 1774 1775 @* Component *@ 1776 1777 @helper RenderForm(Form settings) { 1778 if (settings != null) 1779 { 1780 Dictionary<string, string> optionalAttributes = new Dictionary<string, string>(); 1781 if (!string.IsNullOrEmpty(settings.Action)) { optionalAttributes.Add("action", settings.Action); }; 1782 if (!string.IsNullOrEmpty(settings.Name)) { optionalAttributes.Add("name", settings.Name); }; 1783 if (!string.IsNullOrEmpty(settings.OnSubmit)) { optionalAttributes.Add("onsubmit", settings.OnSubmit); }; 1784 var enctypes = new Dictionary<string, string> 1785 { 1786 { "multipart", "multipart/form-data" }, 1787 { "text", "text/plain" }, 1788 { "application", "application/x-www-form-urlencoded" } 1789 }; 1790 if (settings.Enctype != FormEnctype.none) { optionalAttributes.Add("enctype", enctypes[Enum.GetName(typeof(FormEnctype), settings.Enctype).ToLower()]); }; 1791 optionalAttributes.Add("method", settings.Method.ToString()); 1792 1793 if (!string.IsNullOrEmpty(settings.FormStartMarkup)) 1794 { 1795 @settings.FormStartMarkup 1796 } 1797 else 1798 { 1799 @:<form class="@settings.CssClass u-no-margin dw-mod" @ComponentMethods.AddAttributes(optionalAttributes) @ComponentMethods.AddAttributes(settings.ExtraAttributes)> 1800 } 1801 1802 foreach (var field in settings.GetFields()) 1803 { 1804 @Render(field) 1805 } 1806 1807 @:</form> 1808 } 1809 } 1810 @using System.Reflection 1811 @using Dynamicweb.Rapido.Blocks.Components.General 1812 @using Dynamicweb.Rapido.Blocks.Components 1813 1814 1815 @* Component *@ 1816 1817 @helper RenderText(Text settings) 1818 { 1819 @settings.Content 1820 } 1821 @using System.Reflection 1822 @using Dynamicweb.Rapido.Blocks.Components.General 1823 @using Dynamicweb.Rapido.Blocks.Components 1824 1825 1826 @* Component *@ 1827 1828 @helper RenderContentModule(ContentModule settings) { 1829 if (!string.IsNullOrEmpty(settings.Content)) 1830 { 1831 @settings.Content 1832 } 1833 } 1834 @using System.Reflection 1835 @using Dynamicweb.Rapido.Blocks.Components.General 1836 @using Dynamicweb.Rapido.Blocks.Components 1837 1838 1839 @* Component *@ 1840 1841 @helper RenderModal(Modal settings) { 1842 if (settings != null) 1843 { 1844 string modalId = !string.IsNullOrEmpty(settings.Id) ? settings.Id : Guid.NewGuid().ToString("N"); 1845 1846 string onchange = !string.IsNullOrEmpty(settings.OnClose) ? "onchange=\"if(!this.checked){" + settings.OnClose + "}\"" : ""; 1847 1848 <input type="checkbox" id="@(modalId)ModalTrigger" class="modal-trigger" @onchange /> 1849 1850 <div class="modal-container"> 1851 @if (!settings.DisableDarkOverlay) 1852 { 1853 <label for="@(modalId)ModalTrigger" id="@(modalId)ModalOverlay" class="modal-overlay"></label> 1854 } 1855 <div class="modal modal--@settings.Width.ToString().ToLower() modal-height--@settings.Height.ToString().ToLower()" id="@(modalId)Modal"> 1856 @if (settings.Heading != null) 1857 { 1858 if (!string.IsNullOrEmpty(settings.Heading.Title)) 1859 { 1860 <div class="modal__header"> 1861 @Render(settings.Heading) 1862 </div> 1863 } 1864 } 1865 <div class="modal__body @(settings.Width.ToString().ToLower() == "full" ? "modal__body--full" : "")"> 1866 @if (!string.IsNullOrEmpty(settings.BodyText)) 1867 { 1868 @settings.BodyText 1869 } 1870 @if (settings.BodyTemplate != null) 1871 { 1872 @settings.BodyTemplate 1873 } 1874 @{ 1875 var actions = settings.GetActions(); 1876 } 1877 </div> 1878 @if (actions.Length > 0) 1879 { 1880 <div class="modal__footer"> 1881 @foreach (var action in actions) 1882 { 1883 if (Pageview.Device.ToString() != "Mobile") { 1884 action.CssClass += " u-no-margin"; 1885 } else { 1886 action.CssClass += " u-full-width u-margin-bottom"; 1887 } 1888 1889 @Render(action) 1890 } 1891 </div> 1892 } 1893 <label class="modal__close-btn" for="@(modalId)ModalTrigger"></label> 1894 </div> 1895 </div> 1896 } 1897 } 1898 @using Dynamicweb.Rapido.Blocks.Components.General 1899 1900 @* Component *@ 1901 1902 @helper RenderMediaListItem(MediaListItem settings) 1903 { 1904 <div class="media-list-item @settings.CssClass dw-mod" @(!string.IsNullOrEmpty(settings.Id) ? "id=\"" + settings.Id + "\"" : "")> 1905 @if (!string.IsNullOrEmpty(settings.Label)) 1906 { 1907 if (!string.IsNullOrEmpty(settings.Link)) 1908 { 1909 @Render(new Link 1910 { 1911 Href = settings.Link, 1912 CssClass = "media-list-item__sticker dw-mod", 1913 ButtonLayout = ButtonLayout.None, 1914 Title = settings.Label, 1915 OnClick = !string.IsNullOrEmpty(settings.OnClick) ? settings.OnClick : "" 1916 }) 1917 } 1918 else if (!string.IsNullOrEmpty(settings.OnClick)) 1919 { 1920 <span class="media-list-item__sticker dw-mod" onclick="@(settings.OnClick)"> 1921 <span class="u-uppercase">@settings.Label</span> 1922 </span> 1923 } 1924 else 1925 { 1926 <span class="media-list-item__sticker media-list-item__sticker--no-link dw-mod"> 1927 <span class="u-uppercase">@settings.Label</span> 1928 </span> 1929 } 1930 } 1931 <div class="media-list-item__wrap"> 1932 <div class="media-list-item__info dw-mod"> 1933 <div class="media-list-item__header dw-mod"> 1934 @if (!string.IsNullOrEmpty(settings.Title)) 1935 { 1936 if (!string.IsNullOrEmpty(settings.Link)) 1937 { 1938 @Render(new Link 1939 { 1940 Href = settings.Link, 1941 CssClass = "media-list-item__name dw-mod", 1942 ButtonLayout = ButtonLayout.None, 1943 Title = settings.Title, 1944 OnClick = !string.IsNullOrEmpty(settings.OnClick) ? settings.OnClick : "" 1945 }) 1946 } 1947 else if (!string.IsNullOrEmpty(settings.OnClick)) 1948 { 1949 <span class="media-list-item__name dw-mod" onclick="@(settings.OnClick)">@settings.Title</span> 1950 } 1951 else 1952 { 1953 <span class="media-list-item__name media-list-item__name--no-link dw-mod">@settings.Title</span> 1954 } 1955 } 1956 1957 @if (!string.IsNullOrEmpty(settings.Status)) 1958 { 1959 <div class="media-list-item__state dw-mod">@settings.Status</div> 1960 } 1961 </div> 1962 @{ 1963 settings.InfoTable.CssClass += " media-list-item__parameters-table"; 1964 } 1965 1966 @Render(settings.InfoTable) 1967 </div> 1968 <div class="media-list-item__actions dw-mod"> 1969 <div class="media-list-item__actions-list dw-mod"> 1970 @{ 1971 var actions = settings.GetActions(); 1972 1973 foreach (ButtonBase action in actions) 1974 { 1975 action.ButtonLayout = ButtonLayout.None; 1976 action.CssClass += " media-list-item__action link"; 1977 1978 @Render(action) 1979 } 1980 } 1981 </div> 1982 1983 @if (settings.SelectButton != null && !string.IsNullOrEmpty(settings.SelectButton.Title)) 1984 { 1985 settings.SelectButton.CssClass += " u-no-margin"; 1986 1987 <div class="media-list-item__action-button"> 1988 @Render(settings.SelectButton) 1989 </div> 1990 } 1991 </div> 1992 </div> 1993 </div> 1994 } 1995 @using Dynamicweb.Rapido.Blocks.Components.General 1996 @using Dynamicweb.Rapido.Blocks.Components 1997 1998 @helper RenderTable(Table settings) 1999 { 2000 Dictionary<string, string> attributes = new Dictionary<string, string>(); 2001 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); } 2002 2003 var enumToClasses = new Dictionary<TableDesign, string> 2004 { 2005 { TableDesign.Clean, "table--clean" }, 2006 { TableDesign.Bordered, "table--bordered" }, 2007 { TableDesign.Striped, "table--striped" }, 2008 { TableDesign.Hover, "table--hover" }, 2009 { TableDesign.Compact, "table--compact" }, 2010 { TableDesign.Condensed, "table--condensed" }, 2011 { TableDesign.NoTopBorder, "table--no-top-border" } 2012 }; 2013 string tableDesignClass = ""; 2014 if (settings.Design != TableDesign.None) 2015 { 2016 tableDesignClass = enumToClasses[settings.Design]; 2017 } 2018 2019 if (!string.IsNullOrEmpty(settings.CssClass) || settings.Design != TableDesign.None) { attributes.Add("class", "table " + tableDesignClass + " " + settings.CssClass + " dw-mod"); } 2020 2021 var resultAttributes = attributes.Concat(settings.ExtraAttributes).GroupBy(d => d.Key).ToDictionary(d => d.Key, d => d.Last().Value); 2022 2023 <table @ComponentMethods.AddAttributes(resultAttributes)> 2024 @if (settings.Header != null) 2025 { 2026 <thead> 2027 @Render(settings.Header) 2028 </thead> 2029 } 2030 <tbody> 2031 @foreach (var row in settings.Rows) 2032 { 2033 @Render(row) 2034 } 2035 </tbody> 2036 @if (settings.Footer != null) 2037 { 2038 <tfoot> 2039 @Render(settings.Footer) 2040 </tfoot> 2041 } 2042 </table> 2043 } 2044 @using Dynamicweb.Rapido.Blocks.Components.General 2045 @using Dynamicweb.Rapido.Blocks.Components 2046 2047 @helper RenderTableRow(TableRow settings) 2048 { 2049 Dictionary<string, string> attributes = new Dictionary<string, string>(); 2050 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); } 2051 2052 var enumToClasses = new Dictionary<TableRowDesign, string> 2053 { 2054 { TableRowDesign.NoBorder, "table__row--no-border" }, 2055 { TableRowDesign.Border, "table__row--border" }, 2056 { TableRowDesign.TopBorder, "table__row--top-line" }, 2057 { TableRowDesign.BottomBorder, "table__row--bottom-line" }, 2058 { TableRowDesign.Solid, "table__row--solid" } 2059 }; 2060 2061 string tableRowDesignClass = ""; 2062 if (settings.Design != TableRowDesign.None) 2063 { 2064 tableRowDesignClass = enumToClasses[settings.Design]; 2065 } 2066 2067 if (!string.IsNullOrEmpty(settings.CssClass) || settings.Design != TableRowDesign.None) { attributes.Add("class", "table__row " + tableRowDesignClass + " " + settings.CssClass + " dw-mod"); } 2068 2069 var resultAttributes = attributes.Concat(settings.ExtraAttributes).GroupBy(d => d.Key).ToDictionary(d => d.Key, d => d.Last().Value); 2070 2071 <tr @ComponentMethods.AddAttributes(resultAttributes)> 2072 @foreach (var cell in settings.Cells) 2073 { 2074 if (settings.IsHeaderRow) 2075 { 2076 cell.IsHeader = true; 2077 } 2078 @Render(cell) 2079 } 2080 </tr> 2081 } 2082 @using Dynamicweb.Rapido.Blocks.Components.General 2083 @using Dynamicweb.Rapido.Blocks.Components 2084 @using Dynamicweb.Core 2085 2086 @helper RenderTableCell(TableCell settings) 2087 { 2088 Dictionary<string, string> attributes = new Dictionary<string, string>(); 2089 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); } 2090 if (settings.Colspan != 0) { attributes.Add("colspan", Converter.ToString(settings.Colspan)); } 2091 if (settings.Rowspan != 0) { attributes.Add("rowspan", Converter.ToString(settings.Rowspan)); } 2092 if (!string.IsNullOrEmpty(settings.CssClass)) { attributes.Add("class", settings.CssClass + " dw-mod"); } 2093 2094 var resultAttributes = attributes.Concat(settings.ExtraAttributes).GroupBy(d => d.Key).ToDictionary(d => d.Key, d => d.Last().Value); 2095 2096 string tagName = settings.IsHeader ? "th" : "td"; 2097 2098 @("<" + tagName + " " + ComponentMethods.AddAttributes(resultAttributes) + ">") 2099 @settings.Content 2100 @("</" + tagName + ">"); 2101 } 2102 @using System.Linq 2103 @using Dynamicweb.Rapido.Blocks.Components.General 2104 2105 @* Component *@ 2106 2107 @helper RenderPagination(Dynamicweb.Rapido.Blocks.Components.General.Pagination settings) 2108 { 2109 var pageNumberQueryStringName = Dynamicweb.Rapido.Services.Pagination.GetPageNumberQueryStringName(settings); // Get the proper 'page number' query string parameter 2110 var queryParameters = Dynamicweb.Rapido.Services.Url.GetQueryParameters(pageNumberQueryStringName); // Get the NameValueCollection from the querystring 2111 2112 if (settings.NumberOfPages > 1) 2113 { 2114 string url = HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority) + "/Default.aspx"; 2115 string ariaLabel = !string.IsNullOrWhiteSpace(settings.AriaLabel) ? settings.AriaLabel : Translate("Page navigation"); 2116 Dictionary<string, int> startAndEndPageNumber = Dynamicweb.Rapido.Services.Pagination.GetStartAndEndPageNumber(settings); 2117 2118 <div class="pager u-margin-top dw-mod @settings.CssClass" aria-label="@ariaLabel"> 2119 @if (settings.ShowPagingInfo) 2120 { 2121 <div class="pager__info dw-mod"> 2122 @Translate("Page") @settings.CurrentPageNumber @Translate("of") @settings.NumberOfPages 2123 </div> 2124 } 2125 <ul class="pager__list dw-mod"> 2126 @if (!string.IsNullOrWhiteSpace(settings.FirstPageUrl) && settings.ShowFirstAndLastControls) 2127 { 2128 @Render(new PaginationItem { Link = settings.FirstPageUrl, Icon = settings.FirstIcon }) 2129 } 2130 @if (!string.IsNullOrWhiteSpace(settings.PreviousPageUrl) && settings.ShowNextAndPrevControls) 2131 { 2132 @Render(new PaginationItem { Link = settings.PreviousPageUrl, Icon = settings.PrevIcon }) 2133 } 2134 @if (settings.GetPages().Any()) 2135 { 2136 foreach (var page in settings.GetPages()) 2137 { 2138 @Render(page) 2139 } 2140 } 2141 else 2142 { 2143 for (var page = startAndEndPageNumber["StartPage"]; page <= startAndEndPageNumber["EndPage"]; page++) 2144 { 2145 queryParameters = Dynamicweb.Rapido.Services.Url.UpdateQueryStringParameter(queryParameters, pageNumberQueryStringName, page.ToString()); 2146 @Render(new PaginationItem { Label = page.ToString(), Link = Dynamicweb.Rapido.Services.Url.BuildUri(url, queryParameters).PathAndQuery, IsActive = (settings.CurrentPageNumber == page) }); 2147 } 2148 } 2149 @if (!string.IsNullOrWhiteSpace(settings.NextPageUrl) && settings.ShowNextAndPrevControls) 2150 { 2151 @Render(new PaginationItem { Link = settings.NextPageUrl, Icon = settings.NextIcon }) 2152 } 2153 @if (!string.IsNullOrWhiteSpace(settings.LastPageUrl) && settings.ShowFirstAndLastControls) 2154 { 2155 @Render(new PaginationItem { Link = settings.LastPageUrl, Icon = settings.LastIcon }) 2156 } 2157 </ul> 2158 </div> 2159 } 2160 } 2161 2162 @helper RenderPaginationItem(PaginationItem settings) 2163 { 2164 if (settings.Icon == null) 2165 { 2166 settings.Icon = new Icon(); 2167 } 2168 2169 settings.Icon.Label = settings.Label; 2170 <li class="pager__btn dw-mod"> 2171 @if (settings.IsActive) 2172 { 2173 <span class="pager__num pager__num--current dw-mod"> 2174 @Render(settings.Icon) 2175 </span> 2176 } 2177 else 2178 { 2179 <a href="@settings.Link" class="pager__num dw-mod"> 2180 @Render(settings.Icon) 2181 </a> 2182 } 2183 </li> 2184 } 2185 2186 2187 @using Dynamicweb.Rapido.Blocks.Components.General 2188 @using Dynamicweb.Rapido.Blocks.Components.Ecommerce 2189 2190 2191 @using Dynamicweb.Rapido.Blocks.Components 2192 @using Dynamicweb.Rapido.Blocks.Components.General 2193 @using Dynamicweb.Rapido.Blocks 2194 @using System.IO 2195 2196 2197 @using Dynamicweb.Rapido.Blocks.Components.General 2198 @using Dynamicweb.Rapido.Blocks.Components.Ecommerce 2199 2200 2201 @* Component *@ 2202 2203 @helper RenderVariantMatrix(VariantMatrix settings) { 2204 if (settings != null) 2205 { 2206 int productLoopCounter = 0; 2207 int groupCount = 0; 2208 List<VariantOption> firstDimension = new List<VariantOption>(); 2209 List<VariantOption> secondDimension = new List<VariantOption>(); 2210 List<VariantOption> thirdDimension = new List<VariantOption>(); 2211 2212 foreach (VariantGroup variantGroup in settings.GetVariantGroups()) 2213 { 2214 foreach (VariantOption variantOptions in variantGroup.GetVariantOptions()) 2215 { 2216 if (groupCount == 0) { 2217 firstDimension.Add(variantOptions); 2218 } 2219 if (groupCount == 1) 2220 { 2221 secondDimension.Add(variantOptions); 2222 } 2223 if (groupCount == 2) 2224 { 2225 thirdDimension.Add(variantOptions); 2226 } 2227 } 2228 groupCount++; 2229 } 2230 2231 int rowCount = 0; 2232 int columnCount = 0; 2233 2234 <script> 2235 var variantsCollection = []; 2236 </script> 2237 2238 <table class="table table--compact js-variants-matrix dw-mod" id="VariantMatrixTable_@settings.ProductId"> 2239 @if (groupCount == 1) 2240 { 2241 <tbody> 2242 @foreach (VariantOption firstVariantOption in firstDimension) 2243 { 2244 var variantId = firstVariantOption.Id; 2245 <tr> 2246 <td class="u-bold"> 2247 @firstVariantOption.Name 2248 </td> 2249 <td> 2250 @RenderVariantMatrixQuantityField(variantId, settings, productLoopCounter, rowCount, columnCount) 2251 </td> 2252 </tr> 2253 productLoopCounter++; 2254 } 2255 2256 <tr> 2257 <td>&nbsp;</td> 2258 <td> 2259 <div class="qty-field js-total-qty-column-@columnCount dw-mod">0</div> 2260 </td> 2261 </tr> 2262 </tbody> 2263 } 2264 @if (groupCount == 2) 2265 { 2266 <thead> 2267 <tr> 2268 <td>&nbsp;</td> 2269 @foreach (VariantOption variant in secondDimension) 2270 { 2271 <td>@variant.Name</td> 2272 } 2273 </tr> 2274 </thead> 2275 <tbody> 2276 @foreach (VariantOption firstVariantOption in firstDimension) 2277 { 2278 string variantId = ""; 2279 columnCount = 0; 2280 2281 <tr> 2282 <td class="u-min-w120px">@firstVariantOption.Name</td> 2283 2284 @foreach (VariantOption secondVariantOption in secondDimension) 2285 { 2286 variantId = firstVariantOption.Id + "." + secondVariantOption.Id; 2287 <td> 2288 @RenderVariantMatrixQuantityField(variantId, settings, productLoopCounter, rowCount, columnCount) 2289 </td> 2290 2291 columnCount++; 2292 2293 productLoopCounter++; 2294 } 2295 2296 <td> 2297 <div class="qty-field js-total-qty-row-@rowCount dw-mod">0</div> 2298 </td> 2299 </tr> 2300 2301 rowCount++; 2302 } 2303 2304 @{ 2305 columnCount = 0; 2306 } 2307 2308 <tr> 2309 <td>&nbsp;</td> 2310 @foreach (VariantOption secondVariantOption in secondDimension) 2311 { 2312 <td> 2313 <div class="qty-field js-total-qty-column-@columnCount dw-mod">0</div> 2314 </td> 2315 2316 columnCount++; 2317 } 2318 <td>&nbsp;</td> 2319 </tr> 2320 </tbody> 2321 } 2322 @if (groupCount == 3) 2323 { 2324 <thead> 2325 <tr> 2326 <td>&nbsp;</td> 2327 @foreach (VariantOption thirdVariantOption in thirdDimension) 2328 { 2329 <td>@thirdVariantOption.Name</td> 2330 } 2331 </tr> 2332 </thead> 2333 <tbody> 2334 @foreach (VariantOption firstVariantOption in firstDimension) 2335 { 2336 int colspan = (thirdDimension.Count + 1); 2337 2338 <tr> 2339 <td colspan="@colspan" class="u-color-light-gray--bg u-bold">@firstVariantOption.Name</td> 2340 </tr> 2341 2342 foreach (VariantOption secondVariantOption in secondDimension) 2343 { 2344 string variantId = ""; 2345 columnCount = 0; 2346 2347 <tr> 2348 <td class="u-min-w120px">@secondVariantOption.Name</td> 2349 2350 @foreach (VariantOption thirdVariantOption in thirdDimension) 2351 { 2352 variantId = firstVariantOption.Id + "." + secondVariantOption.Id + "." + thirdVariantOption.Id; 2353 2354 <td> 2355 @RenderVariantMatrixQuantityField(variantId, settings, productLoopCounter, rowCount, columnCount) 2356 </td> 2357 2358 columnCount++; 2359 productLoopCounter++; 2360 } 2361 2362 <td> 2363 <div class="qty-field js-total-qty-row-@rowCount dw-mod">0</div> 2364 </td> 2365 </tr> 2366 rowCount++; 2367 } 2368 } 2369 2370 @{ 2371 columnCount = 0; 2372 } 2373 2374 <tr> 2375 <td>&nbsp;</td> 2376 @foreach (VariantOption thirdVariantOption in thirdDimension) 2377 { 2378 <td> 2379 <div class="qty-field js-total-qty-column-@columnCount dw-mod">0</div> 2380 </td> 2381 2382 columnCount++; 2383 } 2384 <td>&nbsp;</td> 2385 </tr> 2386 </tbody> 2387 } 2388 </table> 2389 2390 <script> 2391 document.addEventListener("DOMContentLoaded", function (event) { 2392 MatrixUpdateQuantity("@settings.ProductId"); 2393 }); 2394 2395 MatrixUpdateQuantity = function (productId) { 2396 var currentMatrix = document.getElementById("VariantMatrixTable_" + productId); 2397 var allQtyFields = currentMatrix.getElementsByClassName("js-qty"); 2398 2399 var qtyRowArr = []; 2400 var qtyColumnArr = []; 2401 2402 var totalQty = 0; 2403 2404 for (var i = 0; i < allQtyFields.length; i++) { 2405 qtyRowArr[allQtyFields[i].getAttribute("data-qty-row-group")] = 0; 2406 qtyColumnArr[allQtyFields[i].getAttribute("data-qty-column-group")] = 0; 2407 } 2408 2409 for (var i = 0; i < allQtyFields.length; i++) { 2410 qtyRowArr[allQtyFields[i].getAttribute("data-qty-row-group")] += parseFloat(allQtyFields[i].value); 2411 qtyColumnArr[allQtyFields[i].getAttribute("data-qty-column-group")] += parseFloat(allQtyFields[i].value); 2412 totalQty += parseFloat(allQtyFields[i].value); 2413 } 2414 2415 //Update row counters 2416 for (var i = 0; i < qtyRowArr.length; i++) { 2417 var qtyCounter = currentMatrix.getElementsByClassName("js-total-qty-row-" + i)[0]; 2418 2419 if (qtyRowArr[i] != undefined && qtyCounter != null) { 2420 var currentCount = qtyCounter.innerHTML; 2421 qtyCounter.innerHTML = qtyRowArr[i]; 2422 2423 if (currentCount != qtyCounter.innerHTML) { 2424 qtyCounter.classList.add("qty-field--active"); 2425 } 2426 } 2427 2428 } 2429 2430 //Update column counters 2431 for (var i = 0; i < qtyColumnArr.length; i++) { 2432 var qtyCounter = currentMatrix.getElementsByClassName("js-total-qty-column-" + i)[0]; 2433 2434 if (qtyColumnArr[i] != undefined && qtyCounter != null) { 2435 var currentCount = qtyCounter.innerHTML; 2436 qtyCounter.innerHTML = qtyColumnArr[i]; 2437 2438 if (currentCount != qtyCounter.innerHTML) { 2439 qtyCounter.classList.add("qty-field--active"); 2440 } 2441 } 2442 } 2443 2444 if (document.getElementById("TotalQtyCount_" + productId)) { 2445 document.getElementById("TotalQtyCount_" + productId).innerHTML = totalQty; 2446 } 2447 2448 //Clean up animations 2449 setTimeout(function () { 2450 for (var i = 0; i < qtyRowArr.length; i++) { 2451 var qtyCounter = currentMatrix.getElementsByClassName("js-total-qty-row-" + i)[0]; 2452 if (qtyCounter != null) { 2453 qtyCounter.classList.remove("qty-field--active"); 2454 } 2455 } 2456 for (var i = 0; i < qtyColumnArr.length; i++) { 2457 var qtyCounter = currentMatrix.getElementsByClassName("js-total-qty-column-" + i)[0]; 2458 if (qtyCounter != null) { 2459 qtyCounter.classList.remove("qty-field--active"); 2460 } 2461 } 2462 }, 1000); 2463 } 2464 </script> 2465 } 2466 } 2467 2468 @helper RenderVariantMatrixQuantityField(string variantId, VariantMatrix settings, int productLoopCounter, int rowCount, int columnCount) 2469 { 2470 string loopCount = productLoopCounter.ToString(); 2471 2472 bool combinationFound = false; 2473 double stock = 0; 2474 double quantityValue = 0; 2475 string note = ""; 2476 2477 VariantProduct variantProduct = null; 2478 2479 if (settings.GetVariantProducts().TryGetValue(variantId, out variantProduct)) 2480 { 2481 stock = variantProduct.Stock; 2482 quantityValue = variantProduct.Quantity; 2483 combinationFound = true; 2484 } 2485 2486 if (combinationFound) 2487 { 2488 <input type="hidden" name="ProductLoopCounter@(loopCount)" value="@loopCount" /> 2489 <input type="hidden" name="ProductID@(loopCount)" value="@settings.ProductId" /> 2490 <input type="hidden" name="VariantID@(loopCount)" value="@variantId" /> 2491 <input type="hidden" name="CurrentNote@(loopCount)" id="CurrentNote_@(settings.ProductId)_@variantId" value="@note" /> 2492 <input type="number" name="Quantity@(loopCount)" id="Quantity_@(settings.ProductId)_@variantId" value="@quantityValue" min="0" class="js-qty u-no-margin u-full-max-width" style="width: 100%; max-width: 100%" onkeyup="MatrixUpdateQuantity('@settings.ProductId')" onmouseup="MatrixUpdateQuantity('@settings.ProductId')" data-qty-row-group="@rowCount" data-qty-column-group="@columnCount"> 2493 2494 if (stock != 0) 2495 { 2496 <small>@Translate("Stock") @stock</small> 2497 } 2498 2499 <script> 2500 var variants = '{ "ProductId" :' + '"@settings.ProductId"' + ', "VariantId": ' + '"@variantId"' +'}'; 2501 variantsCollection.push(variants); 2502 document.getElementById("Quantity_@(settings.ProductId)_@variantId").closest(".js-variants-matrix").setAttribute("data-variants-collection", "[" + variantsCollection + "]" ); 2503 </script> 2504 } 2505 else 2506 { 2507 <div class="use-btn-height" style="background-color: #a8a8a8"></div> 2508 } 2509 } 2510 @using Dynamicweb.Rapido.Blocks.Components.Ecommerce 2511 2512 @* Component *@ 2513 2514 @helper RenderAddToCart(AddToCart settings) 2515 { 2516 //set Id for quantity selector to get it's value from button 2517 if (settings.QuantitySelector != null) 2518 { 2519 if (string.IsNullOrEmpty(settings.QuantitySelector.Id)) 2520 { 2521 settings.QuantitySelector.Id = Guid.NewGuid().ToString("N"); 2522 } 2523 2524 settings.AddButton.QuantitySelectorId = settings.QuantitySelector.Id; 2525 2526 if (settings.Disabled) 2527 { 2528 settings.QuantitySelector.Disabled = true; 2529 } 2530 2531 if (string.IsNullOrEmpty(settings.QuantitySelector.Name)) 2532 { 2533 settings.QuantitySelector.Name = settings.QuantitySelector.Id; 2534 } 2535 } 2536 2537 if (settings.Disabled) 2538 { 2539 settings.AddButton.Disabled = true; 2540 } 2541 2542 settings.AddButton.CssClass += " btn--condensed"; 2543 2544 //unitsSelector 2545 if (settings.UnitSelector != null) 2546 { 2547 if (settings.Disabled) 2548 { 2549 settings.QuantitySelector.Disabled = true; 2550 } 2551 } 2552 2553 <div class="buttons-collection @settings.WrapperCssClass" @ComponentMethods.AddAttributes(settings.ExtraAttributes)> 2554 @if (settings.UnitSelector != null) 2555 { 2556 @Render(settings.UnitSelector) 2557 } 2558 @if (settings.QuantitySelector != null) 2559 { 2560 @Render(settings.QuantitySelector) 2561 } 2562 @Render(settings.AddButton) 2563 </div> 2564 } 2565 @using Dynamicweb.Rapido.Blocks.Components.Ecommerce 2566 2567 @* Component *@ 2568 2569 @helper RenderAddToCartButton(AddToCartButton settings) 2570 { 2571 if (!settings.HideTitle) 2572 { 2573 if (string.IsNullOrEmpty(settings.Title)) 2574 { 2575 if (settings.BuyForPoints) 2576 { 2577 settings.Title = Translate("Buy with points"); 2578 } 2579 else 2580 { 2581 settings.Title = Translate("Add to cart"); 2582 } 2583 } 2584 } 2585 else 2586 { 2587 settings.Title = ""; 2588 } 2589 2590 if (settings.Icon == null) 2591 { 2592 settings.Icon = new Icon(); 2593 settings.Icon.LabelPosition = Dynamicweb.Rapido.Blocks.Components.General.IconLabelPosition.After; 2594 } 2595 2596 if (string.IsNullOrEmpty(settings.Icon.Name)) 2597 { 2598 settings.Icon.Name = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon").SelectedValue; 2599 } 2600 2601 settings.OnClick = "Cart.AddToCart(event, { " + 2602 "id: '" + settings.ProductId + "'," + 2603 (!string.IsNullOrEmpty(settings.VariantId) ? "variantId: '" + settings.VariantId + "'," : "") + 2604 (!string.IsNullOrEmpty(settings.UnitId) ? "unitId: '" + settings.UnitId + "'," : "") + 2605 (settings.BuyForPoints ? "buyForPoints: true," : "") + 2606 (!string.IsNullOrEmpty(settings.ProductInfo) ? "productInfo: " + settings.ProductInfo + "," : "") + 2607 "quantity: " + (string.IsNullOrEmpty(settings.QuantitySelectorId) ? "1" : "parseFloat(document.getElementById('" + settings.QuantitySelectorId + "').value)") + 2608 "});" + settings.OnClick; 2609 2610 @RenderButton(settings) 2611 } 2612 @using Dynamicweb.Rapido.Blocks.Components.Ecommerce 2613 2614 @* Component *@ 2615 2616 @helper RenderUnitSelector(UnitSelector settings) 2617 { 2618 if (string.IsNullOrEmpty(settings.Id)) 2619 { 2620 settings.Id = Guid.NewGuid().ToString("N"); 2621 } 2622 var disabledClass = settings.Disabled ? "disabled" : ""; 2623 2624 <input type="checkbox" id="@settings.Id" class="dropdown-trigger" /> 2625 <div class="dropdown unit-selector @settings.CssClass @disabledClass dw-mod" @ComponentMethods.AddAttributes(settings.ExtraAttributes)> 2626 <label class="dropdown__header dropdown__btn dropdown__btn--unit-selector dw-mod" for="@settings.Id">@settings.SelectedOption</label> 2627 <div class="dropdown__content dw-mod"> 2628 @settings.OptionsContent 2629 </div> 2630 <label class="dropdown-trigger-off" for="@settings.Id"></label> 2631 </div> 2632 } 2633 @using System.Reflection 2634 @using Dynamicweb.Rapido.Blocks.Components.Ecommerce 2635 2636 @* Component *@ 2637 2638 @helper RenderQuantitySelector(QuantitySelector settings) 2639 { 2640 var attributes = new Dictionary<string, string>(); 2641 2642 /*base settings*/ 2643 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); } 2644 if (!string.IsNullOrEmpty(settings.OnClick)) { attributes.Add("onclick", settings.OnClick); } 2645 if (!string.IsNullOrEmpty(settings.OnChange)) { attributes.Add("onchange", settings.OnChange); } 2646 if (settings.Disabled) { attributes.Add("disabled", "true"); } 2647 if (settings.Required) { attributes.Add("required", "true"); } 2648 if (!string.IsNullOrEmpty(settings.Name)) { attributes.Add("name", settings.Name); } 2649 /*end*/ 2650 2651 if (!string.IsNullOrEmpty(settings.OnKeyUp)) { attributes.Add("onkeyup", settings.OnKeyUp); } 2652 if (!string.IsNullOrEmpty(settings.OnInput)) { attributes.Add("oninput", settings.OnInput); } 2653 if (!string.IsNullOrEmpty(settings.OnFocus)) { attributes.Add("onfocus", settings.OnFocus); } 2654 if (settings.ReadOnly) { attributes.Add("readonly", "true"); } 2655 if (settings.Max != null) { attributes.Add("max", settings.Max.ToString()); } 2656 if (settings.Min == null) { settings.Min = 1; } 2657 attributes.Add("min", settings.Min.ToString()); 2658 if (settings.Step != null && !string.IsNullOrEmpty(settings.Step.ToString())) { attributes.Add("step", settings.Step.ToString()); } 2659 if (settings.Value == null) { settings.Value = 1; } 2660 attributes.Add("value", settings.Value.ToString()); 2661 attributes.Add("type", "number"); 2662 2663 var resultAttributes = attributes.Concat(settings.ExtraAttributes).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.Last().Value); 2664 2665 <input @ComponentMethods.AddAttributes(resultAttributes) class="@settings.CssClass dw-mod" /> 2666 } 2667 @using Dynamicweb.Rapido.Blocks.Components 2668 2669 @using Dynamicweb.Frontend 2670 @using Dynamicweb.Frontend.Devices 2671 @using Dynamicweb.Rapido.Blocks.Components.Ecommerce 2672 @using Dynamicweb.Rapido.Blocks.Components.General 2673 @using System.Collections.Generic; 2674 2675 @* Component *@ 2676 2677 @helper RenderCustomerCenterList(CustomerCenterList settings) 2678 { 2679 bool isTouchDevice = Pageview.Device.ToString() == "Mobile" || Pageview.Device.ToString() == "Tablet" ? true : false; 2680 string hideActions = isTouchDevice ? "u-block" : ""; 2681 2682 <table class="table data-list dw-mod"> 2683 @if (settings.GetHeaders().Length > 0) { 2684 <thead> 2685 <tr class="u-bold"> 2686 @foreach (CustomerCenterListHeaderItem header in settings.GetHeaders()) 2687 { 2688 var attributes = new Dictionary<string, string>(); 2689 if (!string.IsNullOrEmpty(header.Id)) { attributes.Add("id", header.Id); } 2690 if (!string.IsNullOrEmpty(header.CssClass)) { attributes.Add("class", header.CssClass); } 2691 attributes.Add("align", header.Align.ToString()); 2692 attributes = attributes.Concat(header.ExtraAttributes).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.Last().Value); 2693 2694 <td @ComponentMethods.AddAttributes(attributes)>@header.Title</td> 2695 } 2696 </tr> 2697 </thead> 2698 } 2699 @foreach (CustomerCenterListItem listItem in settings.GetItems()) 2700 { 2701 int columnCount = 0; 2702 int totalColumns = listItem.GetInfoItems().Length; 2703 string rowHasActions = listItem.GetActions().Length > 0 ? "data-list__item--has-actions" : ""; 2704 listItem.Id = !string.IsNullOrEmpty(listItem.Id) ? listItem.Id : Guid.NewGuid().ToString("N"); 2705 2706 var attributes = new Dictionary<string, string>(); 2707 if (!string.IsNullOrEmpty(listItem.Title)) { attributes.Add("title", listItem.Title); }; 2708 2709 attributes = attributes.Concat(listItem.ExtraAttributes).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.Last().Value); 2710 <tbody class="data-list__item @rowHasActions @listItem.CssClass dw-mod" @ComponentMethods.AddAttributes(attributes)> 2711 <tr> 2712 @if (!string.IsNullOrEmpty(listItem.Title) || !string.IsNullOrEmpty(listItem.Description)) { 2713 string onClick = !string.IsNullOrEmpty(listItem.OnClick) ? "onclick=\"" + listItem.OnClick + "\"" : ""; 2714 2715 <td rowspan="2" @onClick class="data-list__main-item dw-mod"> 2716 @if (!string.IsNullOrEmpty(listItem.Title)) { 2717 <div class="u-bold">@listItem.Title</div> 2718 } 2719 @if (!string.IsNullOrEmpty(listItem.Description)) { 2720 <div>@listItem.Description</div> 2721 } 2722 </td> 2723 } 2724 2725 @foreach (CustomerCenterListInfoItem infoItem in listItem.GetInfoItems()) 2726 { 2727 var infoAttributes = new Dictionary<string, string>(); 2728 if (!string.IsNullOrEmpty(infoItem.Id)) { infoAttributes.Add("id", infoItem.Id); }; 2729 if (!string.IsNullOrEmpty(infoItem.OnClick)) { infoAttributes.Add("onclick", infoItem.OnClick); }; 2730 infoAttributes.Add("align", infoItem.Align.ToString()); 2731 2732 infoAttributes = infoAttributes.Concat(infoItem.ExtraAttributes).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.Last().Value); 2733 string columnClick = columnCount < (totalColumns-1) && !string.IsNullOrEmpty(listItem.OnClick) ? "onclick=\"" + listItem.OnClick + "\"" : ""; 2734 2735 <td @ComponentMethods.AddAttributes(infoAttributes) @columnClick class="data-list__info-item dw-mod"> 2736 @if (!string.IsNullOrEmpty(infoItem.Title)) { 2737 <div>@infoItem.Title</div> 2738 } 2739 @if (!string.IsNullOrEmpty(infoItem.Subtitle)) { 2740 <div><small>@infoItem.Subtitle</small></div> 2741 } 2742 </td> 2743 2744 columnCount++; 2745 } 2746 </tr> 2747 <tr> 2748 <td colspan="7" align="right" class="u-va-bottom u-no-border"> 2749 <div class="data-list__actions @hideActions dw-mod" id="ActionsMenu_@listItem.Id"> 2750 @foreach (ButtonBase action in listItem.GetActions()) 2751 { 2752 action.ButtonLayout = ButtonLayout.LinkClean; 2753 action.Icon.CssClass += " u-full-height"; 2754 action.CssClass += " data-list__action-button link"; 2755 2756 @Render(action) 2757 } 2758 </div> 2759 </td> 2760 </tr> 2761 </tbody> 2762 } 2763 </table> 2764 } 2765 2766 @* Include the Blocks for the page *@ 2767 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 2768 @using Dynamicweb.Core 2769 @using System 2770 @using System.Web 2771 @using System.Collections.Generic 2772 @using Dynamicweb.Rapido.Blocks 2773 @using Dynamicweb.Rapido.Blocks.Components.General 2774 2775 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 2776 @using System.Linq; 2777 @using Dynamicweb.Rapido.Blocks.Components.General 2778 @using System.Collections.Generic 2779 2780 @functions{ 2781 Dictionary<string, StickersListPosition> stickerPositions = new Dictionary<string, StickersListPosition> 2782 { 2783 { "top-left", StickersListPosition.TopLeft }, 2784 { "top-right", StickersListPosition.TopRight }, 2785 { "bottom-left", StickersListPosition.BottomLeft }, 2786 { "bottom-right", StickersListPosition.BottomRight } 2787 }; 2788 2789 public void AddSticker(List<StickersCollection> list, Sticker sticker, StickersListPosition stickerPosition) 2790 { 2791 StickersCollection stickersContainerTemp = list.FirstOrDefault(stickersContainer => stickersContainer.Position == stickerPosition); 2792 if (stickersContainerTemp == null) 2793 { 2794 stickersContainerTemp = new StickersCollection() 2795 { 2796 Position = stickerPosition, 2797 Stickers = new List<Sticker>() 2798 }; 2799 list.Add(stickersContainerTemp); 2800 } 2801 stickersContainerTemp.Stickers.Add(sticker); 2802 } 2803 2804 public List<StickersCollection> GetStickersContainersList(List<LoopItem> discountsLoop, double discountPrice, double price, DateTime createdDate, string customStickerValue) 2805 { 2806 bool pointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly"); 2807 bool isSaleStickersEnabled = Pageview.AreaSettings.GetItem("Ecommerce").GetItem("SaleSticker").GetBoolean("Enable"); 2808 bool isNewsStickersEnabled = Pageview.AreaSettings.GetItem("Ecommerce").GetItem("NewSticker").GetBoolean("Enable"); 2809 bool isCustomStickersEnabled = Pageview.AreaSettings.GetItem("Ecommerce").GetItem("CustomSticker").GetBoolean("Enable"); 2810 2811 List<StickersCollection> resultList = new List<StickersCollection>(); 2812 2813 if (!pointShopOnly && isSaleStickersEnabled) 2814 { 2815 string contentType = Pageview.AreaSettings.GetItem("Ecommerce").GetItem("SaleSticker").GetString("ContentType"); 2816 contentType = !string.IsNullOrEmpty(contentType) ? contentType : "Name"; 2817 var currency = Dynamicweb.Ecommerce.Services.Currencies.GetDefaultCurrency(); 2818 Sticker saleSticker = new Sticker(); 2819 saleSticker.CssClass = "stickers-container__tag--sale"; 2820 2821 switch (contentType) 2822 { 2823 case "Name": 2824 foreach (LoopItem discount in discountsLoop) 2825 { 2826 saleSticker.Title = discount.GetString("Ecom:Product.Discount.Name"); 2827 } 2828 break; 2829 case "Amount": 2830 if (discountsLoop.Count > 0) 2831 { 2832 saleSticker.Title = Dynamicweb.Ecommerce.Services.Currencies.Format(currency, discountPrice - price); 2833 } 2834 break; 2835 case "Percents": 2836 double percents = 0; 2837 foreach (LoopItem discount in discountsLoop) 2838 { 2839 percents += discount.GetDouble("Ecom:Product.Discount.PercentWithoutVAT"); 2840 } 2841 if (percents > 0) 2842 { 2843 saleSticker.Title = Math.Round(percents, 0) + "%"; 2844 } 2845 break; 2846 case "Amount and percents": 2847 double amount = 0; 2848 double percent = 0; 2849 foreach (LoopItem discount in discountsLoop) 2850 { 2851 if (discount.GetString("Ecom:Product.Discount.Type") == "PERCENT") 2852 { 2853 percent += discount.GetDouble("Ecom:Product.Discount.PercentWithoutVAT"); 2854 } 2855 else if (discount.GetString("Ecom:Product.Discount.Type") == "AMOUNT") 2856 { 2857 amount += discount.GetDouble("Ecom:Product.Discount.AmountWithVAT"); 2858 } 2859 } 2860 2861 if (percent > 0) 2862 { 2863 saleSticker.Title = percent + "%"; 2864 } 2865 else if (amount > 0) 2866 { 2867 saleSticker.Title = "-" + Dynamicweb.Ecommerce.Services.Currencies.Format(currency, amount); 2868 } 2869 break; 2870 default: 2871 if (discountsLoop.Count > 0) 2872 { 2873 saleSticker.Title = Translate("Sale!"); 2874 } 2875 break; 2876 } 2877 StickersListPosition saleStickerPosition = StickersListPosition.TopLeft; 2878 if (Pageview.AreaSettings.GetItem("Ecommerce").GetItem("SaleSticker").GetList("Position") != null) 2879 { 2880 string value = Pageview.AreaSettings.GetItem("Ecommerce").GetItem("SaleSticker").GetList("Position").SelectedValue; 2881 saleStickerPosition = stickerPositions.ContainsKey(value) ? stickerPositions[value] : stickerPositions["top-left"]; 2882 } 2883 if (!string.IsNullOrEmpty(saleSticker.Title)) 2884 { 2885 AddSticker(resultList, saleSticker, saleStickerPosition); 2886 } 2887 } 2888 2889 if (!pointShopOnly && isNewsStickersEnabled && createdDate.AddDays(Converter.ToDouble(Pageview.AreaSettings.GetItem("Ecommerce").GetItem("NewSticker").GetString("Expiration"))) > DateTime.Now) 2890 { 2891 Sticker newSticker = new Sticker(); 2892 newSticker.CssClass = "stickers-container__tag--new"; 2893 newSticker.Title = Translate("New!"); 2894 2895 StickersListPosition newStickerPosition = StickersListPosition.TopLeft; 2896 if (Pageview.AreaSettings.GetItem("Ecommerce").GetItem("NewSticker").GetList("Position") != null) 2897 { 2898 string value = Pageview.AreaSettings.GetItem("Ecommerce").GetItem("NewSticker").GetList("Position").SelectedValue; 2899 newStickerPosition = stickerPositions.ContainsKey(value) ? stickerPositions[value] : stickerPositions["top-left"]; 2900 } 2901 if (!string.IsNullOrEmpty(newSticker.Title)) 2902 { 2903 AddSticker(resultList, newSticker, newStickerPosition); 2904 } 2905 } 2906 2907 if (!pointShopOnly && isCustomStickersEnabled && !string.IsNullOrEmpty(customStickerValue)) 2908 { 2909 Sticker customSticker = new Sticker(); 2910 customSticker.CssClass = "stickers-container__tag--custom"; 2911 customSticker.Title = customStickerValue; 2912 2913 StickersListPosition customStickerPosition = StickersListPosition.TopLeft; 2914 if (Pageview.AreaSettings.GetItem("Ecommerce").GetItem("CustomSticker").GetList("Position") != null) 2915 { 2916 string value = Pageview.AreaSettings.GetItem("Ecommerce").GetItem("CustomSticker").GetList("Position").SelectedValue; 2917 customStickerPosition = stickerPositions.ContainsKey(value) ? stickerPositions[value] : stickerPositions["top-left"]; 2918 } 2919 if (!string.IsNullOrEmpty(customSticker.Title)) 2920 { 2921 AddSticker(resultList, customSticker, customStickerPosition); 2922 } 2923 } 2924 2925 return resultList; 2926 } 2927 } 2928 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 2929 2930 2931 @* 2932 This is a temporary fallback for the DefaultImage. The image pattern MUST be set up like this: 2933 2934 ImageSmall = /{ProductNumber}.jpg 2935 ImageMedium = /{ProductNumber}{VariantOptionLevel1}.jpg 2936 ImageLarge = /{ProductNumber}{VariantComboName}.jpg 2937 2938 In addition to the ImageDefault setting 2939 *@ 2940 2941 @functions { 2942 public string GetProductImage(LoopItem productObject = null) 2943 { 2944 string theImage = ""; 2945 2946 if (productObject == null) { 2947 theImage = GetString("Ecom:Product.ImageDefault.Default.Clean"); 2948 theImage = String.IsNullOrEmpty(theImage) ? GetString("Ecom:Product.ImageLarge.Clean") : theImage; 2949 theImage = String.IsNullOrEmpty(theImage) ? GetString("Ecom:Product.ImageMedium.Clean") : theImage; 2950 theImage = String.IsNullOrEmpty(theImage) ? GetString("Ecom:Product.ImageSmall.Clean") : theImage; 2951 theImage = String.IsNullOrEmpty(theImage) ? GetString("Ecom:Product.ImageLarge.Default.Clean") : theImage; 2952 } else { 2953 theImage = productObject.GetString("Ecom:Product.ImageDefault.Default.Clean"); 2954 2955 theImage = String.IsNullOrEmpty(theImage) ? productObject.GetString("Ecom:Product.ImageLarge.Clean") : theImage; 2956 theImage = String.IsNullOrEmpty(theImage) ? productObject.GetString("Ecom:Product.ImageMedium.Clean") : theImage; 2957 theImage = String.IsNullOrEmpty(theImage) ? productObject.GetString("Ecom:Product.ImageSmall.Clean") : theImage; 2958 theImage = String.IsNullOrEmpty(theImage) ? productObject.GetString("Ecom:Product.ImageLarge.Default.Clean") : theImage; 2959 } 2960 2961 2962 return theImage; 2963 } 2964 } 2965 2966 @functions { 2967 BlocksPage mainImagePage = BlocksPage.GetBlockPage("Product"); 2968 bool showThumbs; 2969 bool thumbsOnTheSide; 2970 } 2971 2972 @{ 2973 int imageBlockWidth = Pageview.AreaSettings.GetItem("ProductPage").GetList("TopLayout") != null ? Converter.ToInt32(Pageview.AreaSettings.GetItem("ProductPage").GetList("TopLayout").SelectedValue) : 6; 2974 string blocksPosition = Pageview.AreaSettings.GetItem("ProductPage").GetList("ImageSectionPosition") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("ImageSectionPosition").SelectedValue : "thumbs-image-info"; 2975 bool infoOnTheRight = blocksPosition.LastIndexOf("info") == blocksPosition.Length - 4; 2976 showThumbs = blocksPosition.IndexOf("thumbs") != -1; 2977 thumbsOnTheSide = showThumbs && blocksPosition.IndexOf("thumbsBottom") == -1; 2978 bool thumbsOnTheLeft = blocksPosition.IndexOf("image") > blocksPosition.IndexOf("thumbs"); 2979 if (infoOnTheRight) 2980 { 2981 imageBlockWidth = 12 - imageBlockWidth; 2982 if (imageBlockWidth == 0) 2983 { 2984 imageBlockWidth = 12; 2985 } 2986 } 2987 2988 if (Pageview.Device.ToString() == "Mobile" || Pageview.Device.ToString() == "Tablet") { 2989 thumbsOnTheSide = false; 2990 } 2991 2992 Block mainImageBlock = new Block() 2993 { 2994 Id = "MainImage", 2995 SortId = infoOnTheRight ? 10 : 20, 2996 Design = new Design 2997 { 2998 Size = Converter.ToString(imageBlockWidth), 2999 RenderType = RenderType.Column 3000 }, 3001 BlocksList = new List<Block> 3002 { 3003 new Block { 3004 Id = "MainImageRow", 3005 SortId = 10, 3006 Design = new Design 3007 { 3008 RenderType = RenderType.Row 3009 }, 3010 BlocksList = new List<Block> 3011 { 3012 new Block 3013 { 3014 Id = "Carousel", 3015 SortId = 10, 3016 Template = RenderThumbnails(), 3017 Design = new Design 3018 { 3019 Size = thumbsOnTheSide ? "2" : "12", 3020 RenderType = RenderType.Column 3021 } 3022 } 3023 } 3024 } 3025 } 3026 }; 3027 mainImagePage.Add("Top", mainImageBlock); 3028 3029 mainImagePage.Add("MainImageRow", 3030 new Block() 3031 { 3032 Id = "ProductImageModal", 3033 SortId = 0, 3034 Component = new Modal { 3035 Id = "Gallery", 3036 Width = ModalWidth.Lg, 3037 Height = ModalHeight.Full, 3038 BodyTemplate = RenderProductImagesCarousel("modalCarousel", 1, "horizontal", 3, true) 3039 } 3040 }); 3041 3042 if (showThumbs) 3043 { 3044 mainImagePage.Add("MainImageRow", 3045 new Block 3046 { 3047 Id = "Image", 3048 SortId = thumbsOnTheLeft ? 20 : 0, 3049 Template = RenderProductImage(), 3050 Design = new Design 3051 { 3052 Size = thumbsOnTheSide ? "auto" : "12", 3053 RenderType = RenderType.Column 3054 } 3055 }); 3056 } 3057 } 3058 3059 @helper RenderProductStickers() 3060 { 3061 List<StickersCollection> StickersContainers = GetStickersContainersList( 3062 GetLoop("ProductDiscounts"), 3063 GetDouble("Ecom:Product.Discount.Price.Price"), 3064 GetDouble("Ecom:Product.Price.Price"), 3065 GetDate("Ecom:Product.Created"), 3066 GetString("Ecom:Product:Field.CustomSticker.Value") 3067 ); 3068 3069 foreach (StickersCollection stickersContainer in StickersContainers) 3070 { 3071 @Render(new StickersCollection { Stickers = stickersContainer.Stickers, Position = stickersContainer.Position }) 3072 } 3073 } 3074 3075 @helper RenderProductImage() 3076 { 3077 //Add product image to the og meta data 3078 Pageview.Meta.AddTag("og:image", GetProductImage()); 3079 3080 <label for="GalleryModalTrigger" class="product__image-container u-position-relative"> 3081 @{ 3082 Image productImage = new Image 3083 { 3084 Path = GetProductImage(), 3085 Id = "Image_" + GetString("Ecom:Product.ID"), 3086 CssClass = "u-middle product__image-container__image dw-mod", 3087 Title = GetString("Ecom:Product.Name"), 3088 OnClick = "modalCarousel.GoToSlide('modalCarousel', this.getAttribute('data-number'))", 3089 ImageDefault = new ImageSettings 3090 { 3091 Width = 800, 3092 Height = 800, 3093 Crop = 5, 3094 FillCanvas = true 3095 } 3096 }; 3097 productImage.ExtraAttributes.Add("data-number", "0"); 3098 } 3099 @Render(productImage) 3100 @RenderProductStickers() 3101 </label> 3102 } 3103 3104 @helper RenderThumbnails() 3105 { 3106 <div class="@(showThumbs ? "product__thumbs" : "") dw-mod"> 3107 @RenderProductImagesCarousel( 3108 "productCarousel", 3109 !showThumbs ? 1 : 5, 3110 thumbsOnTheSide ? "vertical" : "horizontal", 3111 !showThumbs ? 3 : 2 3112 ) 3113 @if (!showThumbs) 3114 { 3115 @RenderProductStickers() 3116 } 3117 </div> 3118 } 3119 3120 @helper RenderProductImagesCarousel(string id, int slidesInView, string direction, int preloaderSize, bool isModal = false) 3121 { 3122 var selectedImageCategories = Pageview.AreaSettings.GetItem("ProductPage").GetList("ProductImagesInTopSection").SelectedValues; 3123 var imagesFromAssets = GetLoop("ImageCategories").Where(x => selectedImageCategories.Contains(x.GetString("Category.Id"))); 3124 3125 HashSet<string> images = new HashSet<string>(); 3126 3127 images.Add(GetProductImage()); 3128 3129 foreach (LoopItem alternativeImage in GetLoop("Ecom:Product.AlternativeImages")) 3130 { 3131 string alt_image = alternativeImage.GetString("Ecom:Product.AlternativeImages.Image"); 3132 3133 if (!string.IsNullOrEmpty(alt_image)) 3134 { 3135 images.Add(alt_image); 3136 } 3137 } 3138 3139 int assetImagesCount = 0; 3140 foreach (LoopItem category in imagesFromAssets) { 3141 foreach (LoopItem asset in category.GetLoop("Category.Images")) { 3142 assetImagesCount++; 3143 } 3144 } 3145 3146 if (assetImagesCount > 0) { 3147 foreach (LoopItem category in imagesFromAssets) { 3148 foreach (LoopItem asset in category.GetLoop("Category.Images")) { 3149 images.Add(asset.GetString("Ecom:Product:Detail.Image.Clean")); 3150 } 3151 } 3152 } else { 3153 foreach (LoopItem detail in GetLoop("Details")) 3154 { 3155 string detail_image = detail.GetString("Ecom:Product:Detail.Image.Clean"); 3156 3157 if (!string.IsNullOrEmpty(detail_image)) 3158 { 3159 string ext = Path.GetExtension(detail_image).ToLower(); 3160 if (ext == ".jpg" || ext == ".jpeg" || ext == ".gif" || ext == ".png") 3161 { 3162 images.Add(detail_image); 3163 } 3164 } 3165 } 3166 } 3167 3168 <div class="carousel dw-mod" id="@id"> 3169 <div class="thumb-list carousel__container @(slidesInView != 1 ? "carousel__container--hidden" : "") js-carousel-slides dw-mod"> 3170 @{ var i = 0; } 3171 @foreach (var image in images) 3172 { 3173 @RenderProductImage(image, slidesInView == 1, isModal ? "modal--full__img" : "", i == 0, isModal) 3174 i++; //first is active 3175 } 3176 </div> 3177 3178 <script> 3179 document.addEventListener("DOMContentLoaded", function () { 3180 @id = new CarouselModule('#@id', { 3181 slidesInView: @slidesInView, 3182 direction: "@direction", 3183 preloaderSize: @preloaderSize, 3184 showCounter: @isModal.ToString().ToLower() 3185 }); 3186 }); 3187 </script> 3188 </div> 3189 } 3190 3191 @helper RenderProductImage(string image, bool isBig, string cssClass = "", bool isActive = false, bool isModal = false) 3192 { 3193 string productId = GetString("Ecom:Product.ID"); 3194 string imagePrefix = "/Admin/Public/GetImage.ashx?width=800&amp;height=800&amp;crop=5&FillCanvas=True&DoNotUpscale=true&amp;Compression=75&amp;image="; 3195 3196 Image productImage = new Image { 3197 Path = image, 3198 Title = GetString("Ecom:Product.Name"), 3199 ImageDefault = new ImageSettings { 3200 Width = 800, 3201 Height = 800, 3202 Crop = 5, 3203 FillCanvas = true 3204 }, 3205 CssClass = "u-middle " + cssClass, 3206 OnClick = "modalCarousel.GoToSlide('modalCarousel', this.closest('.carousel__slide').index());" 3207 }; 3208 productImage.ExtraAttributes.Add("data-image", image); 3209 3210 <div class="carousel__slide dw-mod"> 3211 @if (isModal) 3212 { 3213 @Render(new Image { Path = image, CssClass = cssClass, Title = GetString("Ecom:Product.Name"), DisableImageEngine = true }); 3214 } 3215 else if (isBig) 3216 { 3217 <label for="GalleryModalTrigger" class="u-middle"> 3218 @Render(productImage) 3219 </label> 3220 } 3221 else 3222 { 3223 Image productThumb = productImage; 3224 productThumb.ImageDefault = new ImageSettings 3225 { 3226 Width = 200, 3227 Height = 200, 3228 Crop = 5, 3229 FillCanvas = true 3230 }; 3231 productImage.CssClass += " thumb-list__image"; 3232 <div class="thumb-list__item dw-mod js-thumb js-gallery @(isActive ? "js-thumb--active thumb-list__item--active" : "")" data-for="Image_@productId" data-image="@imagePrefix@image" onmouseover="Gallery.openImage(this)"> 3233 <label for="GalleryModalTrigger" class="thumb-list__image-label"> 3234 @Render(productThumb) 3235 </label> 3236 </div> 3237 } 3238 </div> 3239 } 3240 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 3241 @using Dynamicweb.Core 3242 @using System 3243 @using System.Web 3244 @using System.Collections.Generic 3245 @using Dynamicweb.Rapido.Services 3246 @using Dynamicweb.Rapido.Blocks 3247 @using Dynamicweb.Rapido.Blocks.Components.Ecommerce 3248 @using Dynamicweb.Rapido.Blocks.Components.General 3249 3250 @functions { 3251 bool useFacebookPixel; 3252 BlocksPage mainInfoPage = BlocksPage.GetBlockPage("Product"); 3253 } 3254 3255 @{ 3256 var mainInfoVariantsCount = GetInteger("Ecom:Product.VariantCount"); 3257 useFacebookPixel = !string.IsNullOrWhiteSpace(Pageview.AreaSettings.GetItem("Settings").GetString("FacebookPixelID")); 3258 bool hideAddToCartButton = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("hideAddToCartButton"); 3259 3260 //family members 3261 bool mainInfoIsFamilyMember = false; 3262 bool mainInfoIsFamilyMaster = false; 3263 var mainInfoVariantGroups = GetLoop("VariantGroups"); 3264 var mainInfoVariantGroupCount = mainInfoVariantGroups.Count; 3265 if (mainInfoVariantGroupCount == 1) 3266 { 3267 var firstVariantGroup = Dynamicweb.Ecommerce.Services.VariantGroups.GetVariantGroup(Dynamicweb.Ecommerce.Common.Context.LanguageID, mainInfoVariantGroups[0]?.GetString("Ecom:VariantGroup.ID")); 3268 if (firstVariantGroup != null) 3269 { 3270 mainInfoIsFamilyMember = firstVariantGroup.Family; 3271 string variantId = !string.IsNullOrEmpty(GetString("Ecom:Product.VariantID")) ? GetString("Ecom:Product.VariantID") : GetString("Ecom:Product.VariantID.Extented"); 3272 mainInfoIsFamilyMaster = string.IsNullOrEmpty(variantId); 3273 } 3274 } 3275 3276 bool mainInfoRenderVariantsAsProducts = mainInfoVariantsCount > 1 && Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("RenderVariantsAsProductList"); 3277 3278 if (mainInfoIsFamilyMember) 3279 { 3280 mainInfoRenderVariantsAsProducts = mainInfoVariantsCount > 1 && Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("RenderFamilyVariantsAsProducts") && mainInfoIsFamilyMaster; 3281 } 3282 3283 if (Pageview.AreaSettings.GetItem("ProductPage").GetList("VariantsMatrixLayout") != null && mainInfoVariantsCount > 1) 3284 { 3285 mainInfoRenderVariantsAsProducts = Pageview.AreaSettings.GetItem("ProductPage").GetList("VariantsMatrixLayout").SelectedValue != "hide" && Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("EnableVariantMatrix") ? true : mainInfoRenderVariantsAsProducts; 3286 } 3287 3288 Block mainInfoHeader = new Block() 3289 { 3290 Id = "MainInfoHeader", 3291 SortId = 10, 3292 Template = RenderMainInfoHeader() 3293 }; 3294 mainInfoPage.Add("MainInformation", mainInfoHeader); 3295 3296 Block mainInfoDescription = new Block() 3297 { 3298 Id = "ShortDescription", 3299 SortId = 20, 3300 Template = RenderShortDescription() 3301 }; 3302 mainInfoPage.Add("MainInformation", mainInfoDescription); 3303 3304 if (!mainInfoRenderVariantsAsProducts && !mainInfoIsFamilyMember) 3305 { 3306 Block mainInfoVariants = new Block() 3307 { 3308 Id = "Variants", 3309 SortId = 50, 3310 Template = RenderMainInfoVariants() 3311 }; 3312 mainInfoPage.Add("MainInformation", mainInfoVariants); 3313 } 3314 3315 Block mainInfoBOM = new Block() 3316 { 3317 Id = "BOM", 3318 SortId = 60, 3319 Template = RenderMainInfoBOM() 3320 }; 3321 mainInfoPage.Add("MainInformation", mainInfoBOM); 3322 3323 if (!mainInfoRenderVariantsAsProducts) 3324 { 3325 if (!hideAddToCartButton) 3326 { 3327 Block mainInfoBuy = new Block() 3328 { 3329 Id = "Buy", 3330 SortId = 80, 3331 Template = RenderMainInfoBuy() 3332 }; 3333 mainInfoPage.Add("MainInformation", mainInfoBuy); 3334 } 3335 } 3336 3337 if (Dynamicweb.Core.Converter.ToBoolean(GetGlobalValue("Global:Extranet.UserName")) && User.IsBuyingAllowed() && GetPageIdByNavigationTag("OrderDraft") != 0) { 3338 Modal selectDraftModal = new Modal 3339 { 3340 Id = "OrderDraftSelect", 3341 Heading = new Heading { Title = Translate("Select draft cart"), Level = 2 }, 3342 BodyTemplate = RenderOrderDraftSelectModalContent(), 3343 Width = ModalWidth.Md 3344 }; 3345 selectDraftModal.AddAction(new Button { Title = Translate("Cancel"), OnClick = "document.getElementById('OrderDraftSelectModalTrigger').checked = false", ButtonLayout = ButtonLayout.Secondary }); 3346 selectDraftModal.AddAction(new Button { Title = Translate("Add"), OnClick = "addToSelectedCart()" }); 3347 3348 Block orderDraftSelect = new Block 3349 { 3350 Id = "OrderDraft", 3351 SortId = 90, 3352 Component = selectDraftModal 3353 }; 3354 mainInfoPage.Add("MainInformation", orderDraftSelect); 3355 3356 Modal notificationDraftModal = new Modal 3357 { 3358 Id = "OrderDraftNotification", 3359 Heading = new Heading { Title = Translate("Added to cart"), Level = 2 }, 3360 BodyText = Translate("The product has been added to the selected cart"), 3361 Width = ModalWidth.Md 3362 }; 3363 notificationDraftModal.AddAction(new Button { Title = Translate("View draft"), OnClick = "goToSelectedCart()", ButtonLayout = ButtonLayout.Secondary }); 3364 notificationDraftModal.AddAction(new Button { Title = Translate("Continue shopping"), OnClick = "document.getElementById('OrderDraftNotificationModalTrigger').checked = false" }); 3365 3366 Block orderDraftComplete = new Block 3367 { 3368 Id = "OrderDraftComplete", 3369 SortId = 100, 3370 Component = notificationDraftModal 3371 }; 3372 mainInfoPage.Add("MainInformation", orderDraftComplete); 3373 3374 3375 Block orderDraftScripts = new Block 3376 { 3377 Id = "OrderDraftScripts", 3378 SortId = 110, 3379 Template = RenderOrderDraftScripts() 3380 }; 3381 mainInfoPage.Add("MainInformation", orderDraftScripts); 3382 3383 Block googleTagManagerScripts = new Block 3384 { 3385 Id = "GoogleTagManagerScripts", 3386 SortId = 120, 3387 Template = RenderGoogleTagManagerScripts() 3388 }; 3389 mainInfoPage.Add("MainInformation", googleTagManagerScripts); 3390 } 3391 } 3392 3393 @helper RenderMainInfoHeader() 3394 { 3395 bool renderVariantsAsProducts = GetInteger("Ecom:Product.VariantCount") > 1 && Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("RenderVariantsAsProductList"); 3396 if (Pageview.AreaSettings.GetItem("ProductPage").GetList("VariantsMatrixLayout") != null && GetInteger("Ecom:Product.VariantCount") > 1) 3397 { 3398 renderVariantsAsProducts = Pageview.AreaSettings.GetItem("ProductPage").GetList("VariantsMatrixLayout").SelectedValue != "hide" && Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("EnableVariantMatrix") ? true : renderVariantsAsProducts; 3399 } 3400 3401 string pageId = GetGlobalValue("Global:Page.ID").ToString(); 3402 string currentPrice = GetString("Ecom:Product.Discount.Price.PriceFormatted") == GetString("Ecom:Product.Price.PriceFormatted") ? GetString("Ecom:Product.Price.PriceFormatted") : GetString("Ecom:Product.Discount.Price.PriceFormatted"); 3403 bool hideFavorites = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideFavoriteButton"); 3404 bool hideProductNumber = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideProductNumber"); 3405 3406 bool useFontAwesomePro = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetBoolean("UseFontAwesomePro"); 3407 var selectedFavoriteIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("FavoriteIcon") != null ? Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("FavoriteIcon").SelectedValue : "star"; 3408 string favoriteIcon = "fas fa-" + selectedFavoriteIcon; 3409 string favoriteOutlineIcon = "fal fa-" + selectedFavoriteIcon; 3410 3411 <div> 3412 <div class="u-pull--left product__title dw-mod"> 3413 <h1 class="u-no-margin">@GetString("Ecom:Product.Name") </h1> 3414 <h2>@GetString("Ecom:Product.SelectedVariantComboName")</h2> 3415 3416 @if (!hideProductNumber) 3417 { 3418 <div class="item-number dw-mod">@GetString("Ecom:Product.Number")</div> 3419 } 3420 </div> 3421 <div class="u-pull--right"> 3422 @if (!hideFavorites && Dynamicweb.Core.Converter.ToBoolean(GetGlobalValue("Global:Extranet.UserName")) && !renderVariantsAsProducts) 3423 { 3424 string favoriteId = "Favorite" + GetString("Ecom:Product.ID"); 3425 <div id="@favoriteId" class="favorites favorites--md u-pull--right js-favorite-btn dw-mod"> 3426 <div> 3427 @{ 3428 string favorite = GetBoolean("Ecom:Product.IsProductInFavoriteList") ? favoriteIcon : favoriteOutlineIcon; 3429 string AddToWishlist = "fbq('track', 'AddToWishlist', {" + 3430 "content_name: '" + GetString("Ecom:Product.Name") + "'," + 3431 "content_ids: ['" + GetString("Ecom:Product.Number") + "']," + 3432 "value: " + GetDouble("Ecom:Product.Price.Price") + "," + 3433 "currency: '" + GetString("Ecom:Product.Price.Currency.Code") + "'" + 3434 "});"; 3435 } 3436 <label for="FavoriteTrigger"><i class="@favorite fa-1_5x"></i></label> 3437 </div> 3438 <input type="checkbox" id="FavoriteTrigger" class="dropdown-trigger" /> 3439 3440 <div class="dropdown"> 3441 <div class="dropdown__content dropdown__content--show-left dropdown__content--padding u-w220px dw-mod"> 3442 <ul class="list list--clean dw-mod"> 3443 @if (GetLoop("CustomerCenter.ListTypes").Count > 0) 3444 { 3445 foreach (LoopItem listType in GetLoop("CustomerCenter.ListTypes")) 3446 { 3447 foreach (LoopItem list in listType.GetLoop("CustomerCenter.ProductLists")) 3448 { 3449 string favLinkType = list.GetString("Ecom:Product.List.IsProductInThisList") == "True" ? list.GetString("Ecom:Product.RemoveFromThisList") : list.GetString("Ecom:Product.AddToThisListAction"); 3450 string isInListIcon = list.GetString("Ecom:Product.List.IsProductInThisList") == "True" ? favoriteIcon : favoriteOutlineIcon; 3451 <li> 3452 <a href="@favLinkType" class="list__link u-no-underline dw-mod" onclick="@(list.GetString("Ecom:Product.List.IsProductInThisList") != "True" && useFacebookPixel ? AddToWishlist : "")"><i class="@isInListIcon u-margin-right--lg"></i> @list.GetValue("Ecom:CustomerCenter.List.Name")</a> 3453 </li> 3454 } 3455 } 3456 } 3457 else 3458 { 3459 string favLinkType = GetString("Ecom:Product.AddToFavorites") + "&CCListType=0&CCCreateNewList=" + Translate("My favorites"); 3460 string isInListIcon = favoriteOutlineIcon; 3461 <li> 3462 <a href="@favLinkType" class="list__link u-no-underline dw-mod" onclick="@(useFacebookPixel ? AddToWishlist : "")"><i class="@isInListIcon u-margin-right--lg"></i> @Translate("My favorites")</a> 3463 </li> 3464 } 3465 </ul> 3466 </div> 3467 <label class="dropdown-trigger-off" for="FavoriteTrigger"></label> 3468 </div> 3469 </div> 3470 } 3471 </div> 3472 </div> 3473 } 3474 3475 @helper RenderStockAndShipping() 3476 { 3477 bool hideStockState = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideStockState"); 3478 bool hideDelivery = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideShipping"); 3479 3480 if (User.IsStockInfoAllowed()) 3481 { 3482 <text>{{#if stockText}}</text> 3483 <div class="product__stock-delivery dw-mod"> 3484 @if (!hideStockState) 3485 { 3486 <span class="stock-icon {{stockState}} u-no-margin dw-mod" title="{{stockText}}"></span> 3487 <span class="u-margin-right--lg"> {{stockText}}</span> 3488 } 3489 @if (!hideDelivery) 3490 { 3491 <text>{{deliveryText}}</text> 3492 } 3493 </div> 3494 <text>{{/if}}</text> 3495 } 3496 } 3497 3498 @helper RenderShortDescription() 3499 { 3500 if (!String.IsNullOrEmpty(GetString("Ecom:Product.ShortDescription"))) 3501 { 3502 Pageview.Meta.AddTag("og:description", GetString("Ecom:Product.ShortDescription")); 3503 3504 <div class="introduction-text"> 3505 @GetString("Ecom:Product.ShortDescription") 3506 </div> 3507 } 3508 } 3509 3510 @helper RenderMainInfoVariants() 3511 { 3512 string pageId = GetGlobalValue("Global:Page.ID").ToString(); 3513 string productId = GetString("Ecom:Product.ID"); 3514 string variantSelection = !String.IsNullOrEmpty(HttpContext.Current.Request.QueryString.Get("variantId")) ? HttpContext.Current.Request.QueryString.Get("variantId").Replace(".", ",") : ""; 3515 string hideHelpText = ""; 3516 string variantsLayout = Pageview.AreaSettings.GetItem("Ecommerce").GetString("VariantsLayout") != null ? Pageview.AreaSettings.GetItem("Ecommerce").GetList("VariantsLayout").SelectedValue : "buttons"; 3517 3518 foreach (LoopItem variantgroup in GetLoop("VariantGroups")) 3519 { 3520 foreach (LoopItem variantoption in variantgroup.GetLoop("VariantAvailableOptions")) 3521 { 3522 if (variantoption.GetBoolean("Ecom:VariantOption.Selected")) 3523 { 3524 hideHelpText = "u-hidden"; 3525 } 3526 } 3527 } 3528 3529 if (GetLoop("VariantGroups").Count > 0) 3530 { 3531 var variantCombinationsObject = new List<Array>(); 3532 foreach (LoopItem variantcomb in GetLoop("VariantCombinations")) 3533 { 3534 string[] combinations = variantcomb.GetString("Ecom:VariantCombination.VariantID").Split('.'); 3535 variantCombinationsObject.Add(combinations); 3536 } 3537 3538 string combinationsJson = Newtonsoft.Json.JsonConvert.SerializeObject(variantCombinationsObject).Replace("\"", "\'"); 3539 3540 var variantGroupsObject = new List<List<String>>(); 3541 foreach (LoopItem variantGroup in GetLoop("VariantGroups")) 3542 { 3543 var variantsObject = new List<String>(); 3544 foreach (LoopItem variantOption in variantGroup.GetLoop("VariantAvailableOptions")) 3545 { 3546 variantsObject.Add(variantOption.GetString("Ecom:VariantOption.ID")); 3547 } 3548 variantGroupsObject.Add(variantsObject); 3549 } 3550 3551 string variantsJson = Newtonsoft.Json.JsonConvert.SerializeObject(variantGroupsObject).Replace("\"", "\'"); 3552 string productGroupId = HttpContext.Current.Request["GroupId"]; 3553 3554 <div> 3555 <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" data-group-id="@productGroupId"> 3556 @foreach (LoopItem variantGroup in GetLoop("VariantGroups")) 3557 { 3558 string groupId = variantGroup.GetString("Ecom:VariantGroup.ID"); 3559 3560 <div> 3561 <div class="product__variant-group-name u-bold dw-mod">@variantGroup.GetString("Ecom:VariantGroup.Name")</div> 3562 <div class="u-margin-top"> 3563 @if (variantsLayout == "buttons") 3564 { 3565 foreach (LoopItem variantOption in variantGroup.GetLoop("VariantAvailableOptions")) 3566 { 3567 string selected = variantOption.GetBoolean("Ecom:VariantOption.Selected") ? "checked" : ""; 3568 string color = !String.IsNullOrEmpty(variantOption.GetString("Ecom:VariantOption.Colorcode")) ? variantOption.GetString("Ecom:VariantOption.Colorcode") : null; 3569 color = color == null && !String.IsNullOrEmpty(variantOption.GetString("Ecom:VariantOption.Color")) ? variantOption.GetString("Ecom:VariantOption.Color") : color; 3570 3571 if (!String.IsNullOrEmpty(color)) 3572 { 3573 <button type="button" data-variant-id="@variantOption.GetString("Ecom:VariantOption.ID")" data-variant-group="@groupId" onclick="MatchVariants.SelectThis(event)" class="btn btn--colorbox u-margin-right @selected js-variant-option" data-check="@selected" style="background-color: @color"></button> 3574 } 3575 else 3576 { 3577 <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> 3578 } 3579 } 3580 } 3581 else 3582 { 3583 <select id="VariantSelector_@groupId" class="u-full-width dw-mod" name="VariantSelector_@groupId" onchange="MatchVariants.SelectOnChange(event)" > 3584 <option>@Translate("Choose")</option> 3585 @foreach (LoopItem variantOption in variantGroup.GetLoop("VariantAvailableOptions")) 3586 { 3587 string check = variantOption.GetBoolean("Ecom:VariantOption.Selected") ? "checked" : ""; 3588 string selected = variantOption.GetBoolean("Ecom:VariantOption.Selected") ? "selected" : ""; 3589 string color = !String.IsNullOrEmpty(variantOption.GetString("Ecom:VariantOption.Colorcode")) ? variantOption.GetString("Ecom:VariantOption.Colorcode") : null; 3590 color = color == null && !String.IsNullOrEmpty(variantOption.GetString("Ecom:VariantOption.Color")) ? variantOption.GetString("Ecom:VariantOption.Color") : color; 3591 3592 <option class="js-variant-option @selected" id="@(groupId)_@variantOption.GetString("Ecom:VariantOption.ID")" value="@(groupId)_@variantOption.GetString("Ecom:VariantOption.ID")" data-variant-id="@variantOption.GetString("Ecom:VariantOption.ID")" data-variant-group="@groupId" @selected data-check="@check">@variantOption.GetString("Ecom:VariantOption.Name")</option> 3593 } 3594 </select> 3595 } 3596 </div> 3597 </div> 3598 } 3599 </div> 3600 <small class="js-help-text help-text @hideHelpText">@Translate("Please select variant!")</small> 3601 </div> 3602 } 3603 } 3604 3605 @helper RenderMainInfoBOM() 3606 { 3607 if (GetLoop("BOMProducts").Count > 0) 3608 { 3609 <h2 class="section-title">@Translate("Including products")</h2> 3610 foreach (LoopItem BOMProductItem in GetLoop("BOMProducts")) 3611 { 3612 string link = "/" + BOMProductItem.GetString("Ecom:Product.LinkGroup.Clean") + (!String.IsNullOrEmpty(BOMProductItem.GetString("Ecom:Product.VariantID")) ? "&VariantID=" + BOMProductItem.GetString("Ecom:Product.VariantID") : ""); 3613 <div class="grid__col--border grid"> 3614 <div class="grid__cell grid__cell--align-middle-left"> 3615 <a href="@link" class="u-pull--left u-margin-right"> 3616 <img class="b-lazy" src="/Files/Images/placeholder.gif" data-src="/Admin/Public/GetImage.ashx?width=50&image=@GetProductImage(BOMProductItem)&Compression=99" alt="@BOMProductItem.GetString("Ecom:Product.Name")" /> 3617 </a> 3618 <a href="@link">@BOMProductItem.GetString("Ecom:Product.Name")</a> 3619 </div> 3620 </div> 3621 } 3622 } 3623 } 3624 3625 @helper RenderMainInfoBuy() 3626 { 3627 string pageId = GetGlobalValue("Global:Page.ID").ToString(); 3628 string variantId = HttpContext.Current.Request.QueryString.Get("variantId"); 3629 string productId = GetString("Ecom:Product.ID"); 3630 string feedId = pageId + "&ProductID=" + productId + "&VariantID=" + variantId + "&Feed=True&redirect=false"; 3631 3632 3633 <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> 3634 <input type="hidden" value="@GetString("Ecom:Product.VariantID.Extented")" name="Variant" id="Variant_@GetString("Ecom:Product.ID")" /> 3635 @RenderMainInfoBuyScripts() 3636 } 3637 3638 @helper RenderPriceInfo() 3639 { 3640 bool pointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly"); 3641 bool showPrice = !Pageview.AreaSettings.GetItem("ProductList").GetBoolean("HidePrice"); 3642 bool showCartButton = !Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideAddToCartButton"); 3643 bool showVATPrice = Pageview.AreaSettings.GetItem("ProductList").GetBoolean("ShowBothPricesWithWithoutVAT"); 3644 bool isPricesWithVATEnabled = Converter.ToBoolean(Pageview.Area.EcomPricesWithVat); 3645 3646 if (showPrice && Dynamicweb.Rapido.Services.User.IsPricesAllowed()) 3647 { 3648 if (pointShopOnly) 3649 { 3650 <text> 3651 {{#if havePointPrice}} 3652 <div class="price price--product-page dw-mod">{{points}} @Translate("points")</div> 3653 @if (showCartButton) 3654 { 3655 <text> 3656 {{#unless canBePurchasedWithPoints}} 3657 <small class="help-text u-no-margin">@Translate("Not enough points to buy this")</small> 3658 {{/unless}} 3659 </text> 3660 } 3661 {{else}} 3662 @Translate("Not available") 3663 {{/if}} 3664 </text> 3665 3666 } 3667 else 3668 { 3669 <div class="price price--product-page dw-mod">{{price}}</div> 3670 <div class="before-price {{onSale}} dw-mod">{{discount}}</div> 3671 if (showVATPrice) 3672 { 3673 <div class="vat-price vat-price--product-page u-margin-top dw-mod"> 3674 @if (isPricesWithVATEnabled) 3675 { 3676 <span>@Translate("excl. VAT")</span><span> ({{priceWithoutVAT}})</span> 3677 } 3678 else 3679 { 3680 <span>@Translate("incl. VAT")</span><span> ({{priceWithVAT}})</span> 3681 } 3682 </div> 3683 } 3684 <text> 3685 {{#if priceRRP}} 3686 <div><small>@Translate("RRP") {{priceRRP}}</small></div> 3687 {{/if}} 3688 </text> 3689 } 3690 } 3691 } 3692 3693 @helper RenderMainInfoBuyScripts() 3694 { 3695 bool showPrice = !Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HidePrice"); 3696 bool showCartButton = !Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideAddToCartButton"); 3697 bool pointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly"); 3698 string variantId = HttpContext.Current.Request.QueryString.Get("variantId") ?? ""; 3699 string feedId = GetGlobalValue("Global:Page.ID").ToString() + "&ProductID=" + GetString("Ecom:Product.ID") + "&VariantID=" + variantId + "&Feed=True&redirect=false"; 3700 string cartIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon") != null ? Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon").SelectedValue : "fas fa-shopping-cart"; 3701 bool showVATPrice = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("ShowBothPricesWithWithoutVAT"); 3702 bool isPricesWithVATEnabled = Converter.ToBoolean(Pageview.Area.EcomPricesWithVat); 3703 3704 var customerId = Dynamicweb.Security.UserManagement.User.GetCurrentExtranetUserId(); 3705 var shopId = Pageview.Area.EcomShopId; 3706 var orderType = Dynamicweb.Ecommerce.Orders.OrderType.Order; 3707 var cartsList = (List<Dynamicweb.Ecommerce.Orders.Order>)Dynamicweb.Ecommerce.Services.Orders.GetCustomerOrdersByType(customerId, shopId, orderType, 0, false, "", DateTime.MinValue, false, true); 3708 bool hidePrice = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HidePrice"); 3709 3710 @* Handlebars templates *@ 3711 <script id="PricesAndActionsTemplate" type="text/x-template"> 3712 {{#.}} 3713 @if (Dynamicweb.Rapido.Services.User.IsPricesAllowed() && !hidePrice) 3714 { 3715 <div class="product__price-wrap dw-mod"> 3716 @RenderPriceInfo() 3717 </div> 3718 } 3719 3720 @if (showCartButton && Dynamicweb.Rapido.Services.User.IsBuyingAllowed()) 3721 { 3722 var addToCartBtn = new AddToCart 3723 { 3724 WrapperCssClass = "product__price-actions-flex-wrap buttons-collection--right dw-mod", 3725 AddButton = new AddToCartButton 3726 { 3727 ProductId = "{{productId}}", 3728 VariantId = "{{variantid}}", 3729 UnitId = "{{unitId}}", 3730 ProductInfo = "{{productInfo}}", 3731 BuyForPoints = pointShopOnly, 3732 OnClick = "{{facebookPixelAction}}", 3733 ExtraAttributes = new Dictionary<string, string> 3734 { 3735 { "{{disabledBuyButton}}", "" } 3736 }, 3737 CssClass = "product__price-buy-button" 3738 }, 3739 UnitSelector = new UnitSelector 3740 { 3741 OptionsContent = "{{#unitOptions}}{{>UnitOption}}{{/unitOptions}}", 3742 Id = "UnitOptions_{{id}}", 3743 SelectedOption = "{{unitName}}", 3744 CssClass = "{{#if hasOnlyOneUnit}}unit-selector--readonly{{/if}} {{hasUnits}}" 3745 } 3746 }; 3747 3748 if (!pointShopOnly) 3749 { 3750 addToCartBtn.QuantitySelector = new QuantitySelector 3751 { 3752 Id = "Quantity_{{id}}" 3753 }; 3754 } 3755 3756 <div class="product__price-actions-wrap dw-mod"> 3757 @Render(addToCartBtn) 3758 3759 @if (Dynamicweb.Core.Converter.ToBoolean(GetGlobalValue("Global:Extranet.UserName")) && User.IsBuyingAllowed() && cartsList.Count > 0 && GetPageIdByNavigationTag("OrderDraft") != 0) { 3760 var addToDraftCart = new Button 3761 { 3762 Id = "AddToDraftCart", 3763 Title = Translate("Add to draft"), 3764 ButtonLayout = ButtonLayout.Secondary, 3765 OnClick = "document.getElementById('OrderDraftSelectModalTrigger').checked = true", 3766 CssClass = "u-w220px u-margin-top" 3767 }; 3768 3769 @Render(addToDraftCart) 3770 } 3771 3772 @if (Pageview.User != null && !pointShopOnly && Dynamicweb.Security.Licensing.LicenseManager.LicenseHasFeature("LoyaltyPoints")) 3773 { 3774 <text> 3775 {{#if canBePurchasedWithPoints}} 3776 <form method="post" role="form" class="u-no-margin u-margin-top"> 3777 <input type="hidden" name="ProductID" value="{{id}}" /> 3778 <button type="submit" class="btn btn--loyalty-points product__price-points-buy-button 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> 3779 </form> 3780 {{/if}} 3781 </text> 3782 } 3783 </div> 3784 } 3785 else 3786 { 3787 <button type="button" id="CartButton_{{id}}" class="u-hidden"></button> 3788 } 3789 @RenderStockAndShipping() 3790 {{/.}} 3791 </script> 3792 3793 <script id="UnitOption" type="text/x-template"> 3794 <div class="dropdown__item dw-mod" onclick="HandlebarsBolt.UpdateContent('PriceAndActions', '{{link}}&feed=true&UnitID={{value}}')">{{name}}</div> 3795 </script> 3796 3797 <script> 3798 document.addEventListener("DOMContentLoaded", function () { 3799 if (document.getElementById("PriceAndActions")) { 3800 document.getElementById("PriceAndActions").addEventListener("contentLoaded", function (event) { 3801 if (document.querySelector(".js-variants") != null) { 3802 MatchVariants.Update(document.querySelector(".js-variants"), "DoNothing"); 3803 } 3804 }); 3805 } 3806 }); 3807 </script> 3808 } 3809 3810 @helper RenderOrderDraftSelectModalContent() { 3811 var customerId = Dynamicweb.Security.UserManagement.User.GetCurrentExtranetUserId(); 3812 var shopId = Pageview.Area.EcomShopId; 3813 var orderType = Dynamicweb.Ecommerce.Orders.OrderType.Order; 3814 var cartsList = (List<Dynamicweb.Ecommerce.Orders.Order>)Dynamicweb.Ecommerce.Services.Orders.GetCustomerOrdersByType(customerId, shopId, orderType, 0, false, "", DateTime.MinValue, false, true); 3815 3816 SelectField cartSelector = new SelectField 3817 { 3818 Id = "CartSelector", 3819 Label = Translate("I want to add this product to") 3820 }; 3821 3822 foreach (Dynamicweb.Ecommerce.Orders.Order cart in cartsList) { 3823 string name = !string.IsNullOrEmpty(cart.DisplayName) ? cart.DisplayName : cart.Id; 3824 cartSelector.Options.Add(new SelectFieldOption { Label = name, Value = cart.Id }); 3825 } 3826 3827 @Render(cartSelector) 3828 } 3829 3830 @helper RenderOrderDraftScripts() { 3831 string productId = GetString("Ecom:Product.ID"); 3832 string variantId = !string.IsNullOrEmpty(GetString("Ecom:Product.VariantID")) ? GetString("Ecom:Product.VariantID") : GetString("Ecom:Product.VariantID.Extented"); 3833 string unitId = GetString("Ecom:Product.DefaultUnitID"); 3834 var cartCmdUrl = "/Default.aspx?ID=" + Pageview.Page.ID; 3835 int orderDraftPageId = GetPageIdByNavigationTag("DraftDetails"); 3836 int orderDraftParagraphId = Dynamicweb.Services.Paragraphs.GetParagraphsByPageId(orderDraftPageId).ToList().First().ID; 3837 3838 foreach (LoopItem unitOption in GetLoop("Units")) 3839 { 3840 if (unitOption.GetString("Ecom:VariantOption.Selected") == "SELECTED") 3841 { 3842 unitId = unitOption.GetString("Ecom:VariantOption.ID"); 3843 } 3844 } 3845 3846 <script> 3847 function addToSelectedCart() { 3848 var requestUrl = "@cartCmdUrl" + "&cartcmd=Add&Quantity=1" + "&CartId=" + document.getElementById("CartSelector").value + "&ProductId=@productId" + "&VariantId=@variantId" + "&UnitId=@unitId"; 3849 3850 console.log(requestUrl) 3851 3852 document.getElementById('OrderDraftSelectModalTrigger').checked = false; 3853 3854 var overlayElement = document.createElement('div'); 3855 overlayElement.className = "preloader-overlay"; 3856 overlayElement.setAttribute('id', "CartOverlay"); 3857 var overlayElementIcon = document.createElement('div'); 3858 overlayElementIcon.className = "preloader-overlay__icon dw-mod"; 3859 overlayElementIcon.style.top = window.pageYOffset + "px"; 3860 overlayElement.appendChild(overlayElementIcon); 3861 document.getElementById('content').parentNode.insertBefore(overlayElement, document.getElementById('content')); 3862 3863 Request.Fetch().get( 3864 requestUrl, 3865 function () { 3866 var overlayNode = document.getElementById('CartOverlay'); 3867 overlayNode.parentNode.removeChild(overlayNode); 3868 document.getElementById('OrderDraftNotificationModalTrigger').checked = true; 3869 }, 3870 null, 3871 false 3872 ); 3873 } 3874 3875 function goToSelectedCart() { 3876 window.location = "/Default.aspx?ID=" + "@orderDraftPageId" + "&CartID=" + document.getElementById('CartSelector').value + "&CartCmd=setcart" + "&redirect=false"; 3877 } 3878 </script> 3879 } 3880 3881 @helper RenderGoogleTagManagerScripts() { 3882 bool useGoogleTagManager = !string.IsNullOrEmpty(Pageview.AreaSettings.GetItem("Settings").GetString("GoogleTagManagerID")); 3883 3884 if (useGoogleTagManager) 3885 { 3886 var groupObject = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(GetString("Ecom:Product.PrimaryOrFirstGroupID")); 3887 3888 <script> 3889 // Measure a view of product details. This example assumes the detail view occurs on pageload, 3890 // and also tracks a standard pageview of the details page. 3891 dataLayer.push({ 3892 'event': 'productDetails', 3893 "ecommerce": { 3894 "detail": { 3895 "currencyCode": "@GetString("Ecom:Product.Price.Currency.Code")", 3896 "actionField": {}, // 'detail' actions have an optional list property. 3897 "products": [{ 3898 "name": "@GetString("Ecom:Product.Name")", // Name or ID is required. 3899 "id": "@GetString("Ecom:Product.ID")", 3900 "price": "@(GetDouble("Ecom:Product.Discount.Price.Price") != GetDouble("Ecom:Product.Price.Price") ? GetDouble("Ecom:Product.Discount.Price.Price") : GetDouble("Ecom:Product.Price.Price"))", 3901 "brand": "@GetString("Ecom:Product:Field.brand.Value")", 3902 "category": "@(groupObject != null ? groupObject.Name : "")", 3903 "variant": "@(!string.IsNullOrEmpty(GetString("Ecom:Product.VariantID")) ? GetString("Ecom:Product.VariantID") : GetString("Ecom:Product.VariantID.Extented"))" 3904 }] 3905 } 3906 } 3907 }); 3908 </script> 3909 } 3910 } 3911 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 3912 @using Dynamicweb.Core 3913 @using System 3914 @using System.Web 3915 @using System.Collections.Generic 3916 @using Dynamicweb.Rapido.Blocks 3917 @using Dynamicweb.Rapido.Blocks.Components.General 3918 3919 @functions { 3920 BlocksPage productAssetsPage = BlocksPage.GetBlockPage("Product"); 3921 } 3922 3923 @{ 3924 string productAssetsLayout = !String.IsNullOrEmpty(Pageview.AreaSettings.GetItem("ProductPage").GetString("ProductAssetsLayout")) ? Pageview.AreaSettings.GetItem("ProductPage").GetList("ProductAssetsLayout").SelectedValue : "Section"; 3925 productAssetsLayout = productAssetsLayout == "Ribbon" ? "Section" : productAssetsLayout; 3926 3927 if (productAssetsLayout != "hide") 3928 { 3929 Block productAssetsBlock = new Block() 3930 { 3931 Name = productAssetsLayout != "MainInformation" ? Translate("Product assets") : "", 3932 Id = "ProductAssets", 3933 SortId = 10, 3934 Template = RenderProductAssets(productAssetsLayout, downloadDocuments), @*downloadDocuments variable, declared in Product.cshtml and defined in Fields.cshtml*@ 3935 Design = new Design 3936 { 3937 Size = "12", 3938 RenderType = RenderType.Column, 3939 HidePadding = true 3940 } 3941 }; 3942 productAssetsPage.Add(productAssetsLayout, productAssetsBlock); 3943 } 3944 } 3945 3946 @helper RenderProductAssets(string layout, List<LoopItem> documents) 3947 { 3948 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("ProductAssetsLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 3949 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("ProductAssetsLayout").SelectedValue == "Ribbon" ? "u-padding--lg" : ""; 3950 string exportPageId = GetPageIdByNavigationTag("ProductExportFeed").ToString(); 3951 3952 //images 3953 3954 HashSet<string> images = new HashSet<string>(); 3955 3956 images.Add(GetProductImage()); 3957 3958 foreach (LoopItem alternativeImage in GetLoop("Ecom:Product.AlternativeImages")) 3959 { 3960 string alt_image = alternativeImage.GetString("Ecom:Product.AlternativeImages.Image"); 3961 3962 if (!string.IsNullOrEmpty(alt_image)) 3963 { 3964 images.Add(alt_image); 3965 } 3966 } 3967 3968 foreach (LoopItem detail in GetLoop("Details")) 3969 { 3970 string detail_image = detail.GetString("Ecom:Product:Detail.Image.Clean"); 3971 3972 if (!string.IsNullOrEmpty(detail_image)) 3973 { 3974 images.Add(detail_image); 3975 } 3976 } 3977 3978 <div class="product__section @ribbonClasses dw-mod"> 3979 <div class="product__description center-container @ribbonSubClasses dw-mod"> 3980 @if (layout == "Section") 3981 { 3982 @Render(new Heading { Title = Translate("Product assets"), Level = 2 }) 3983 } 3984 3985 <form action="/Default.aspx?ID=@exportPageId&ProductID=@System.Web.HttpContext.Current.Request.QueryString.Get("ProductID")&VariantID=@System.Web.HttpContext.Current.Request.QueryString.Get("VariantID")" method="post" class="u-flex grid--direction-column u-no-margin"> 3986 <div class="grid"> 3987 @if (images.Count > 0) 3988 { 3989 <div class="grid__col-md-4 js-checkboxes-list"> 3990 @Render(new CheckboxField { Id = "allImages", OnChange = "selectAll(this)", Label = Translate("Images") + "(" + images.Count + ")" }) 3991 3992 <ul class="panel-list"> 3993 @foreach (string image in images) 3994 { 3995 @RenderProductPanelListItem(image) 3996 } 3997 </ul> 3998 </div> 3999 } 4000 4001 @if (documents.Count > 0) 4002 { 4003 <div class="grid__col-md-4 js-checkboxes-list"> 4004 @Render(new CheckboxField { Id = "allDocuments", OnChange = "selectAll(this)", Label = Translate("Documents") + "(" + documents.Count + ")" }) 4005 4006 <ul class="panel-list"> 4007 @foreach (LoopItem document in documents) 4008 { 4009 string fieldValue; 4010 if (!string.IsNullOrEmpty(document.GetString("Document.FullPath"))) 4011 { 4012 fieldValue = document.GetString("Product.CustomField.Value.Clean"); 4013 @RenderDocument(fieldValue) 4014 } 4015 if (document.GetString("Ecom:Product.CategoryField.TypeID") == "9") 4016 { 4017 fieldValue = document.GetString("Ecom:Product.CategoryField.Value"); 4018 @RenderDocument(fieldValue) 4019 } 4020 if (!string.IsNullOrEmpty(document.GetString("Ecom:Product:Detail.Image.Clean"))) 4021 { 4022 fieldValue = document.GetString("Ecom:Product:Detail.Image.Clean"); 4023 @RenderDocument(fieldValue) 4024 } 4025 } 4026 </ul> 4027 </div> 4028 } 4029 <div class="grid__col-md-4"> 4030 @Render(new HiddenField { Id = "ID", Name = "ID", Value = "532" }) 4031 @Render(new HiddenField { Id = "download", Name = "download", Value = "true" }) 4032 @Render(new HiddenField { Id = "siteUrl", Name = "siteUrl", Value = string.Format("{0}://{1}", GetGlobalValue("Global:Request.Scheme"), GetGlobalValue("Global:Request.Host")) }) 4033 4034 <div class="u-bold u-margin-bottom">@Translate("Export")</div> 4035 4036 @{ 4037 SelectField languageSelect = new SelectField 4038 { 4039 Id = "exportLanguage", 4040 Label = Translate("Language"), 4041 Name = "RequestLanguageId", 4042 CssClass = "u-full-width" 4043 }; 4044 foreach (var lang in Services.Languages.GetLanguages().OrderBy(l => l.Name)) 4045 { 4046 var selected = lang.IsDefault ? true : false; 4047 languageSelect.Options.Add(new SelectFieldOption { Label = lang.Name, Value = lang.LanguageId, Checked = selected }); 4048 } 4049 @Render(languageSelect) 4050 4051 SelectField purposeSelect = new SelectField 4052 { 4053 Id = "purpose", 4054 Label = Translate("Image purpose"), 4055 Name = "purpose", 4056 CssClass = "u-full-width" 4057 }; 4058 purposeSelect.Options.Add(new SelectFieldOption { Label = Translate("Office"), Value = "Office" }); 4059 purposeSelect.Options.Add(new SelectFieldOption { Label = Translate("Original"), Value = "Original" }); 4060 purposeSelect.Options.Add(new SelectFieldOption { Label = Translate("Print"), Value = "Print" }); 4061 purposeSelect.Options.Add(new SelectFieldOption { Label = Translate("Web"), Value = "Web" }); 4062 @Render(purposeSelect) 4063 4064 SelectField formatSelect = new SelectField 4065 { 4066 Id = "exportFormat", 4067 Label = Translate("Export format"), 4068 Name = "format", 4069 CssClass = "u-full-width" 4070 }; 4071 formatSelect.Options.Add(new SelectFieldOption { Label = Translate("Csv"), Value = "csv" }); 4072 formatSelect.Options.Add(new SelectFieldOption { Label = Translate("Json"), Value = "json" }); 4073 formatSelect.Options.Add(new SelectFieldOption { Label = Translate("Xml"), Value = "xml" }); 4074 @Render(formatSelect) 4075 } 4076 4077 @Render(new Button { ButtonType = ButtonType.Submit, ButtonLayout = ButtonLayout.Primary, CssClass = "btn--full u-no-margin", Title = Translate("Download") }) 4078 </div> 4079 </div> 4080 </form> 4081 </div> 4082 </div> 4083 <script> 4084 function selectAll(checkbox) { 4085 checkbox.closest(".js-checkboxes-list").querySelectorAll(".js-checkbox").forEach(function (input) { 4086 input.checked = checkbox.checked; 4087 }); 4088 } 4089 </script> 4090 } 4091 4092 @helper RenderProductPanelListItem(string imageName) 4093 { 4094 <li class="panel-list__item"> 4095 <div class="panel-list__item-check"> 4096 <input id="Image_@imageName" name="Image_@imageName" type="checkbox" class="form__control u-no-margin dw-mod js-checkbox" /> 4097 <label for="Image_@imageName"></label> 4098 </div> 4099 <div class="panel-list__item-image"> 4100 <label for="Image_@imageName" class="u-no-margin"> 4101 @Render(new Image { Path = imageName, Title = Path.GetFileName(imageName), ImageDefault = new ImageSettings { Width = 55, Height = 55, Crop = 5, FillCanvas = true } }) 4102 </label> 4103 </div> 4104 <div class="panel-list__item-name"> 4105 <label for="Image_@imageName" class="u-truncate-text u-w170px" title="@Path.GetFileName(imageName)"> 4106 @Path.GetFileName(imageName) 4107 </label> 4108 </div> 4109 </li> 4110 } 4111 4112 @helper RenderDocument(string fieldValue) 4113 { 4114 <li class="panel-list__item"> 4115 <div class="panel-list__item-check"> 4116 <input id="Document_@fieldValue" name="Document_@fieldValue" type="checkbox" class="form__control u-no-margin js-checkbox dw-mod"> 4117 <label for="Document_@fieldValue"></label> 4118 </div> 4119 <div class="panel-list__item-name"> 4120 <label for="Document_@fieldValue" class="u-truncate-text u-no-margin u-max-w220px" title="@Path.GetFileName(fieldValue)"> 4121 @Path.GetFileName(fieldValue) 4122 </label> 4123 </div> 4124 </li> 4125 } 4126 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 4127 @using Dynamicweb.Core 4128 @using System 4129 @using System.Web 4130 @using System.Collections.Generic 4131 @using Dynamicweb.Rapido.Blocks 4132 @using Dynamicweb.Rapido.Blocks.Components.General 4133 4134 @functions { 4135 BlocksPage productGeneratePDFPage = BlocksPage.GetBlockPage("Product"); 4136 } 4137 4138 @{ 4139 string generatePDFLayout = !String.IsNullOrEmpty(Pageview.AreaSettings.GetItem("ProductPage").GetString("GeneratePDFLayout")) ? Pageview.AreaSettings.GetItem("ProductPage").GetList("GeneratePDFLayout").SelectedValue : "Section"; 4140 generatePDFLayout = generatePDFLayout == "Ribbon" ? "Section" : generatePDFLayout; 4141 4142 if (GetPageIdByNavigationTag("ProductPagePDFTemplates") > 0 && generatePDFLayout != "hide") 4143 { 4144 Block generatePDFBlock = new Block() 4145 { 4146 Name = generatePDFLayout != "MainInformation" ? Translate("Generate PDF") : "", 4147 Id = "GeneratePDF", 4148 SortId = 10, 4149 Template = RenderGeneratePDF(generatePDFLayout), 4150 Design = new Design 4151 { 4152 Size = "12", 4153 RenderType = RenderType.Column, 4154 HidePadding = true 4155 } 4156 }; 4157 4158 productGeneratePDFPage.Add(generatePDFLayout, generatePDFBlock); 4159 } 4160 } 4161 4162 @helper RenderGeneratePDF(string layout) 4163 { 4164 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("GeneratePDFLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 4165 ribbonClasses = layout == "Tabs" ? "" : ribbonClasses; 4166 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("GeneratePDFLayout").SelectedValue == "Ribbon" ? "center-container--ribbon" : ""; 4167 string exportPageId = GetPageIdByNavigationTag("ProductExportFeed").ToString(); 4168 int pdfFolderId = GetPageIdByNavigationTag("ProductPagePDFTemplates"); 4169 4170 Form form = new Form { Action = "/Default.aspx?MainProductID=" + System.Web.HttpContext.Current.Request.QueryString.Get("ProductID") + "&VariantID=" + System.Web.HttpContext.Current.Request.QueryString.Get("VariantID") + "&Pdf=true", Method = FormMethod.Post, CssClass = "u-no-margin" }; 4171 form.Add(new HiddenField { Name = "siteUrl", Value = string.Format("{0}://{1}", GetGlobalValue("Global:Request.Scheme"), GetGlobalValue("Global:Request.Host")) }); 4172 4173 //Select languages 4174 SelectField languagesList = new SelectField 4175 { 4176 Id = "RequestLanguageID", 4177 Name = "RequestLanguageID", 4178 Label = Translate("Language"), 4179 CssClass = "u-full-width" 4180 }; 4181 4182 foreach (var lang in Services.Languages.GetLanguages().OrderBy(l => l.Name)) 4183 { 4184 languagesList.Options.Add(new SelectFieldOption 4185 { 4186 Label = lang.Name, 4187 Value = lang.LanguageId, 4188 Checked = lang.IsDefault ? true : false 4189 }); 4190 } 4191 form.Add(languagesList); 4192 4193 //Select pages 4194 SelectField pagesList = new SelectField 4195 { 4196 Id = "PDFTemplate", 4197 Name = "ID", 4198 Label = Translate("Generate PDF"), 4199 CssClass = "u-full-width" 4200 }; 4201 4202 foreach (Dynamicweb.Content.Page page in ServiceLocator.Current.GetPageService().GetPagesByParentID(pdfFolderId)) 4203 { 4204 pagesList.Options.Add(new SelectFieldOption 4205 { 4206 Label = page.MenuText, 4207 Value = Converter.ToString(page.ID) 4208 }); 4209 } 4210 form.Add(pagesList); 4211 4212 form.Add(new Button { ButtonType = ButtonType.Submit, Title = Translate("Generate PDF"), CssClass = "btn--full u-no-margin" }); 4213 4214 <div class="product__section @ribbonClasses grid dw-mod"> 4215 <div class="dw-mod grid__col-md-4 @ribbonSubClasses"> 4216 @if (layout == "Section") 4217 { 4218 @Render(new Heading { Title = Translate("Generate PDF"), Level = 2 }) 4219 } 4220 @Render(form) 4221 </div> 4222 </div> 4223 } 4224 4225 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 4226 @using Dynamicweb.Core 4227 @using System 4228 @using System.Web 4229 @using System.Collections.Generic 4230 @using Dynamicweb.Rapido.Blocks 4231 @using Dynamicweb.Rapido.Blocks.Components.General 4232 4233 @functions { 4234 BlocksPage productDescriptionPage = BlocksPage.GetBlockPage("Product"); 4235 } 4236 4237 @{ 4238 string fullDesctiptionLayout = !String.IsNullOrEmpty(Pageview.AreaSettings.GetItem("ProductPage").GetString("FullDescriptionLayout")) ? Pageview.AreaSettings.GetItem("ProductPage").GetList("FullDescriptionLayout").SelectedValue : "Section"; 4239 fullDesctiptionLayout = fullDesctiptionLayout == "Ribbon" ? "Section" : fullDesctiptionLayout; 4240 4241 if (!string.IsNullOrEmpty(GetString("Ecom:Product.LongDescription")) && fullDesctiptionLayout != "hide") 4242 { 4243 Block detailsDescription = new Block() 4244 { 4245 Name = fullDesctiptionLayout != "MainInformation" ? Translate("Description") : "", 4246 Id = "FullDescription", 4247 SortId = 30, 4248 Template = RenderProductDescription(fullDesctiptionLayout), 4249 Design = new Design 4250 { 4251 Size = "12", 4252 RenderType = RenderType.Column, 4253 HidePadding = true 4254 } 4255 }; 4256 productDescriptionPage.Add(fullDesctiptionLayout, detailsDescription); 4257 } 4258 } 4259 4260 @helper RenderProductDescription(string layout) 4261 { 4262 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("FullDescriptionLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 4263 ribbonClasses = layout == "Tabs" ? "" : ribbonClasses; 4264 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("FullDescriptionLayout").SelectedValue == "Ribbon" ? "center-container--ribbon" : ""; 4265 4266 <div class="product__section @ribbonClasses dw-mod"> 4267 <div class="product__description center-container @ribbonSubClasses dw-mod"> 4268 @if (layout == "Section") { 4269 @Render(new Heading { Title = Translate("Description"), Level = 2 }) 4270 } 4271 @Render(new Text { Content = GetString("Ecom:Product.LongDescription") }) 4272 </div> 4273 </div> 4274 } 4275 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 4276 @using Dynamicweb.Core 4277 @using System 4278 @using System.Web 4279 @using System.Globalization; 4280 @using System.Collections.Generic 4281 @using Dynamicweb.Rapido.Blocks 4282 4283 @functions { 4284 BlocksPage productFieldsPage = BlocksPage.GetBlockPage("Product"); 4285 4286 static string ConvertBytes(long bytes) 4287 { 4288 double size = bytes / 1024; //KB 4289 if (size > 1024) 4290 { 4291 size = (bytes / 1024f) / 1024f; //MB 4292 return string.Format("{0:n1} MB", size); 4293 } 4294 else 4295 { 4296 return string.Format("{0:n0} KB", size); 4297 } 4298 } 4299 4300 static bool isImage(string path) 4301 { 4302 return new List<string> { ".jpg", ".jpeg", ".gif", ".png", ".svg" }.Contains(Path.GetExtension(path).ToLower()); 4303 } 4304 4305 string getIconForFile(string fileName) 4306 { 4307 string ext = Path.GetExtension(fileName); 4308 string icon = ""; 4309 switch (ext.ToLower()) 4310 { 4311 case ".xls": 4312 case ".xlsx": 4313 icon = "fa-file-excel"; 4314 break; 4315 case ".ppt": 4316 case ".pptx": 4317 icon = "fa-file-powerpoint"; 4318 break; 4319 case ".doc": 4320 case ".docx": 4321 icon = "fa-file-word"; 4322 break; 4323 case ".jpg": 4324 case ".jpeg": 4325 case ".png": 4326 case ".gif": 4327 case ".pdf": 4328 return "<img class='product__document-img' alt='" + fileName + "' src='/Admin/Public/GetImage.ashx?crop=5&height=70&width=120&Compression=75&DoNotUpscale=true&image=" + fileName + "' />"; 4329 default: 4330 icon = "fa-file"; 4331 break; 4332 } 4333 return "<i class='product__document-icon far " + icon + "'></i> "; 4334 } 4335 } 4336 4337 @*downloadDocuments variable, declared in Product.cshtml - this variable also will be used in ProductAssets.cshtml*@ 4338 4339 4340 4341 @{ 4342 var selectedDownloadCategories = Pageview.AreaSettings.GetItem("ProductPage").GetList("DownloadAssets").SelectedValues; 4343 var downloadsFromAssets = GetLoop("ImageCategories").Where(x => selectedDownloadCategories.Contains(x.GetString("Category.Id"))); 4344 4345 if (string.IsNullOrEmpty(selectedDownloadCategories.ToString())) { 4346 foreach (LoopItem customField in GetLoop("CustomFieldValues")) 4347 { 4348 if (!string.IsNullOrEmpty(customField.GetString("Product.CustomField.Name")) && !string.IsNullOrEmpty(customField.GetString("Product.CustomField.Value.Clean")) && customField.GetString("Product.CustomField.Name") != "Custom sticker" && customField.GetString("Product.CustomField.Name") != "RRP") 4349 { 4350 if (!string.IsNullOrEmpty(customField.GetString("Document.FullPath"))) 4351 { 4352 downloadDocuments.Add(customField); 4353 } 4354 } 4355 } 4356 4357 foreach (LoopItem customField in GetLoop("ProductCategories")) 4358 { 4359 foreach (LoopItem field in customField.GetLoop("ProductCategoryFields")) 4360 { 4361 if (!string.IsNullOrEmpty(field.GetString("Ecom:Product.CategoryField.Label")) && !string.IsNullOrEmpty(field.GetString("Ecom:Product.CategoryField.Value"))) 4362 { 4363 if (field.GetString("Ecom:Product.CategoryField.TypeID") == "9") 4364 { 4365 downloadDocuments.Add(field); 4366 } 4367 } 4368 } 4369 } 4370 } else { 4371 foreach (LoopItem category in downloadsFromAssets) { 4372 foreach (LoopItem asset in category.GetLoop("Category.Images")) { 4373 downloadDocuments.Add(asset); 4374 } 4375 } 4376 } 4377 4378 bool collectAllDownloads = Pageview.AreaSettings.GetItem("ProductPage").GetString("CollectAllDownloads") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("CollectAllDownloads") : true; 4379 string detailFieldsLayout = Pageview.AreaSettings.GetItem("ProductPage").GetList("DetailFieldsLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("DetailFieldsLayout").SelectedValue : "Section"; 4380 detailFieldsLayout = detailFieldsLayout == "Ribbon" || string.IsNullOrEmpty(detailFieldsLayout) ? "Section" : detailFieldsLayout; 4381 string categoryFieldsLayout = Pageview.AreaSettings.GetItem("ProductPage").GetList("CategoryFieldsLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("CategoryFieldsLayout").SelectedValue : "Section"; 4382 categoryFieldsLayout = categoryFieldsLayout == "Ribbon" || string.IsNullOrEmpty(categoryFieldsLayout) ? "Section" : categoryFieldsLayout; 4383 string displayGroupsLayout = Pageview.AreaSettings.GetItem("ProductPage").GetList("DisplayGroupsLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("DisplayGroupsLayout").SelectedValue : "Section"; 4384 displayGroupsLayout = displayGroupsLayout == "Ribbon" || string.IsNullOrEmpty(displayGroupsLayout) ? "Section" : displayGroupsLayout; 4385 string downloadsFieldsLayout = Pageview.AreaSettings.GetItem("ProductPage").GetList("DownloadsLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("DownloadsLayout").SelectedValue : "Section"; 4386 downloadsFieldsLayout = downloadsFieldsLayout == "Ribbon" || string.IsNullOrEmpty(downloadsFieldsLayout) ? "Section" : downloadsFieldsLayout; 4387 4388 string detailFieldsView = Pageview.AreaSettings.GetItem("ProductPage").GetList("DetailFieldsView") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("DetailFieldsView").SelectedValue : "grid"; 4389 string categoryFieldsView = Pageview.AreaSettings.GetItem("ProductPage").GetList("CategoryFieldsView") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("CategoryFieldsView").SelectedValue : "grid"; 4390 string downloadsFieldsView = Pageview.AreaSettings.GetItem("ProductPage").GetList("DownloadsFieldsView") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("DownloadsFieldsView").SelectedValue : "grid"; 4391 4392 if (GetLoop("CustomFieldValues").Count > 0 && detailFieldsLayout != "hide") 4393 { 4394 if (string.IsNullOrEmpty(Pageview.AreaSettings.GetItem("ProductPage").GetString("ProductDetailFields"))) { 4395 Block detailsCustom = new Block() 4396 { 4397 Name = detailFieldsLayout != "MainInformation" ? Translate("Details") : "", 4398 Id = "CustomFields", 4399 SortId = 30, 4400 Design = new Design 4401 { 4402 Size = "12", 4403 RenderType = RenderType.Column, 4404 HidePadding = true 4405 } 4406 }; 4407 4408 detailsCustom.Template = RenderProductSection(detailFieldsLayout, detailFieldsView, Translate("Information"), RenderCustomFields(GetLoop("CustomFieldValues"), detailFieldsView)); 4409 productFieldsPage.Add(detailFieldsLayout, detailsCustom); 4410 } else { 4411 var detailFieldsDisplayGroups = Pageview.AreaSettings.GetItem("ProductPage").GetList("ProductDetailFields").SelectedValues; 4412 var displayGroups = GetLoop("FieldDisplayGroups").Where(x => detailFieldsDisplayGroups.Contains(x.GetString("Ecom:FieldDisplayGroup.ID"))); 4413 4414 foreach (var group in displayGroups) { 4415 Block detailsCustom = new Block() 4416 { 4417 Name = detailFieldsLayout != "MainInformation" ? group.GetString("Ecom:FieldDisplayGroup.Name") : "", 4418 Id = "DetailFields_" + group.GetString("Ecom:FieldDisplayGroup.ID"), 4419 SortId = 30, 4420 Design = new Design 4421 { 4422 Size = "12", 4423 RenderType = RenderType.Column, 4424 HidePadding = true 4425 } 4426 }; 4427 4428 detailsCustom.Template = RenderProductSection(detailFieldsLayout, detailFieldsView, Translate("Information"), RenderDetailsFields(group.GetLoop("Fields"), detailFieldsView)); 4429 productFieldsPage.Add(detailFieldsLayout, detailsCustom); 4430 } 4431 } 4432 } 4433 4434 if (categoryFieldsLayout != "hide") 4435 { 4436 foreach (LoopItem categoryGroup in GetLoop("ProductCategories")) 4437 { 4438 bool hasFields = categoryGroup.GetLoop("ProductCategoryFields").FirstOrDefault(cf => !string.IsNullOrEmpty(cf.GetString("Ecom:Product.CategoryField.Value"))) != null; 4439 4440 if (collectAllDownloads) 4441 { 4442 int downloadableCount = 0; 4443 foreach (LoopItem field in categoryGroup.GetLoop("ProductCategoryFields")) 4444 { 4445 if (field.GetString("Ecom:Product.CategoryField.TypeID") == "9") 4446 { 4447 downloadableCount++; 4448 } 4449 } 4450 4451 if (downloadableCount == categoryGroup.GetLoop("ProductCategoryFields").Count) 4452 { 4453 hasFields = false; 4454 } 4455 } 4456 4457 if (hasFields) 4458 { 4459 Block detailsCategoryFields = new Block() 4460 { 4461 Name = categoryFieldsLayout != "MainInformation" ? categoryGroup.GetString("Ecom:Product.Category.Name") : "", 4462 Id = ToPascalCase(categoryGroup.GetString("Ecom:Product.Category.Name")), 4463 SortId = 40, 4464 Template = RenderProductSection(categoryFieldsLayout, categoryFieldsView, categoryGroup.GetString("Ecom:Product.Category.Name"), RenderProductCategoryFields(categoryGroup.GetLoop("ProductCategoryFields"), categoryFieldsView)), 4465 Design = new Design 4466 { 4467 Size = "12", 4468 RenderType = RenderType.Column, 4469 HidePadding = true 4470 } 4471 }; 4472 4473 productFieldsPage.Add(categoryFieldsLayout, detailsCategoryFields); 4474 } 4475 } 4476 } 4477 4478 if (displayGroupsLayout != "hide") 4479 { 4480 var detailFieldsDisplayGroups = Pageview.AreaSettings.GetItem("ProductPage").GetList("ProductDetailFields").SelectedValues; 4481 var displayGroups = GetLoop("FieldDisplayGroups").Where(x => !detailFieldsDisplayGroups.Contains(x.GetString("Ecom:FieldDisplayGroup.ID"))); 4482 4483 foreach (LoopItem group in displayGroups) 4484 { 4485 Block displayGroup = new Block() 4486 { 4487 Name = displayGroupsLayout != "MainInformation" ? group.GetString("Ecom:FieldDisplayGroup.Name") : "", 4488 Id = "DisplayGroup_" + group.GetString("Ecom:FieldDisplayGroup.ID"), 4489 SortId = 40, 4490 Template = RenderProductSection(displayGroupsLayout, categoryFieldsView, group.GetString("Ecom:FieldDisplayGroup.Name"), RenderDetailsFields(group.GetLoop("Fields"), categoryFieldsView)), 4491 Design = new Design 4492 { 4493 Size = "12", 4494 RenderType = RenderType.Column, 4495 HidePadding = true 4496 } 4497 }; 4498 4499 productFieldsPage.Add(displayGroupsLayout, displayGroup); 4500 } 4501 } 4502 4503 if (downloadDocuments.Count > 0 && downloadsFieldsLayout != "hide" && collectAllDownloads == true) 4504 { 4505 Block detailsDownloads = new Block() 4506 { 4507 Name = downloadsFieldsLayout != "MainInformation" ? Translate("Downloads") : "", 4508 Id = "StandardDownloads", 4509 SortId = 50, 4510 Template = RenderProductSection(downloadsFieldsLayout, downloadsFieldsView, Translate("Downloads"), RenderProductDownloadsFields(downloadDocuments, downloadsFieldsView)), 4511 Design = new Design 4512 { 4513 Size = "12", 4514 RenderType = RenderType.Column, 4515 HidePadding = true 4516 } 4517 }; 4518 4519 productFieldsPage.Add(downloadsFieldsLayout, detailsDownloads); 4520 } 4521 } 4522 4523 @helper RenderCustomFields(List<LoopItem> fieldsLoop, string viewType) 4524 { 4525 bool collectAllDownloads = Pageview.AreaSettings.GetItem("ProductPage").GetString("CollectAllDownloads") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("CollectAllDownloads") : true; 4526 4527 foreach (LoopItem customField in fieldsLoop) 4528 { 4529 string fieldValue = customField.GetString("Product.CustomField.Value.Clean"); 4530 fieldValue = fieldValue == "False" ? Translate("No") : fieldValue; 4531 fieldValue = fieldValue == "True" ? Translate("Yes") : fieldValue; 4532 4533 if (customField.GetLoop("Product.CustomField.Options").Count > 0) 4534 { 4535 List<string> accumulatedValues = new List<string> (); 4536 4537 foreach (var option in customField.GetLoop("Product.CustomField.Options")) 4538 { 4539 if (option.GetBoolean("Product.CustomField.Option.IsSelected")) 4540 { 4541 accumulatedValues.Add(option.GetString("Product.CustomField.Option.Name")); 4542 } 4543 } 4544 fieldValue = string.Join(", ", accumulatedValues); 4545 } 4546 4547 if (!string.IsNullOrEmpty(customField.GetString("Product.CustomField.Name")) && !string.IsNullOrEmpty(fieldValue) && customField.GetString("Product.CustomField.Name") != "Custom sticker" && customField.GetString("Product.CustomField.Name") != "RRP") 4548 { 4549 if (string.IsNullOrEmpty(customField.GetString("Document.FullPath"))) 4550 { 4551 @RenderFieldItem(customField.GetString("Product.CustomField.Name"), fieldValue, viewType); 4552 } 4553 else if (collectAllDownloads == false) 4554 { 4555 @RenderFieldItem(customField.GetString("Product.CustomField.Name"), fieldValue, viewType, "download"); 4556 } 4557 } 4558 } 4559 } 4560 4561 @helper RenderProductSection(string layout, string viewType, string name, RazorEngine.Templating.TemplateWriter writer) 4562 { 4563 string ribbonClasses = layout == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : "u-no-padding"; 4564 ribbonClasses = layout == "Tabs" ? "" : ribbonClasses; 4565 string ribbonSubClasses = layout == "Ribbon" ? "center-container--ribbon" : ""; 4566 4567 4568 <div class="product__section @ribbonClasses dw-mod"> 4569 <div class="center-container @ribbonSubClasses dw-mod"> 4570 @if (layout == "Section") 4571 { 4572 @Render(new Heading { Title = name, Level = 2 }) 4573 } 4574 4575 @if (viewType != "table") 4576 { 4577 <div class="grid grid--bleed u-margin-bottom--lg"> 4578 @writer 4579 </div> 4580 } 4581 else 4582 { 4583 string tableWidth = layout != "MainInformation" ? "grid__col-md-6" : "grid__col-md-12"; 4584 4585 <div class="grid grid--external-bleed-x u-margin-bottom--lg"> 4586 <div class="@tableWidth grid__col-sm-12 grid__col-xs-12"> 4587 <table class="table--no-top-border"> 4588 @writer 4589 </table> 4590 </div> 4591 </div> 4592 } 4593 </div> 4594 </div> 4595 } 4596 4597 @helper RenderProductCategoryFields(List<LoopItem> fieldsLoop, string viewType) 4598 { 4599 bool collectAllDownloads = Pageview.AreaSettings.GetItem("ProductPage").GetString("CollectAllDownloads") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("CollectAllDownloads") : true; 4600 4601 foreach (LoopItem categoryField in fieldsLoop) 4602 { 4603 string fieldValue = categoryField.GetString("Ecom:Product.CategoryField.Value"); 4604 fieldValue = fieldValue == "False" ? Translate("No") : fieldValue; 4605 fieldValue = fieldValue == "True" ? Translate("Yes") : fieldValue; 4606 4607 if (!string.IsNullOrEmpty(categoryField.GetString("Ecom:Product.CategoryField.Label")) && !string.IsNullOrEmpty(fieldValue)) 4608 { 4609 if (categoryField.GetString("Ecom:Product.CategoryField.TypeID") != "9" || collectAllDownloads == false) 4610 { 4611 if (categoryField.GetString("Ecom:Product.CategoryField.TypeID") == "15") 4612 { 4613 @RenderFieldItem(categoryField.GetString("Ecom:Product.CategoryField.Label"), categoryField.GetString("Ecom:Product.CategoryField.OptionLabel"), viewType); 4614 } 4615 else if (categoryField.GetString("Ecom:Product.CategoryField.TypeID") == "8") 4616 { 4617 @RenderFieldItem(categoryField.GetString("Ecom:Product.CategoryField.Label"), fieldValue, viewType, "link"); 4618 } 4619 else if (categoryField.GetString("Ecom:Product.CategoryField.TypeID") == "9") 4620 { 4621 @RenderFieldItem(categoryField.GetString("Ecom:Product.CategoryField.Label"), fieldValue, viewType, "download"); 4622 } 4623 else 4624 { 4625 @RenderFieldItem(categoryField.GetString("Ecom:Product.CategoryField.Label"), fieldValue, viewType); 4626 } 4627 } 4628 } 4629 } 4630 } 4631 4632 @helper RenderDetailsFields(IEnumerable<LoopItem> fields, string viewType) 4633 { 4634 foreach (LoopItem field in fields) 4635 { 4636 string fieldValue = field.GetString("Ecom:FieldDisplayGroup.Field.Value"); 4637 fieldValue = fieldValue == "False" ? Translate("No") : fieldValue; 4638 fieldValue = fieldValue == "True" ? Translate("Yes") : fieldValue; 4639 4640 if (!string.IsNullOrEmpty(field.GetString("Ecom:FieldDisplayGroup.Field.Name")) && !string.IsNullOrEmpty(fieldValue)) 4641 { 4642 if (field.GetString("Ecom:FieldDisplayGroup.Field.TypeId") == "15") 4643 { 4644 @RenderFieldItem(field.GetString("Ecom:FieldDisplayGroup.Field.Name"), field.GetString("Ecom:FieldDisplayGroup.Field.OptionLabel"), viewType); 4645 } 4646 else if (field.GetString("Ecom:FieldDisplayGroup.Field.TypeId") == "8") 4647 { 4648 @RenderFieldItem(field.GetString("Ecom:Product.CategoryField.Label"), fieldValue, viewType, "link"); 4649 } 4650 else if (field.GetString("Ecom:FieldDisplayGroup.Field.TypeId") == "9") 4651 { 4652 @RenderFieldItem(field.GetString("Ecom:FieldDisplayGroup.Field.Name"), fieldValue, viewType, "download"); 4653 } 4654 else 4655 { 4656 @RenderFieldItem(field.GetString("Ecom:FieldDisplayGroup.Field.Name"), fieldValue, viewType); 4657 } 4658 } 4659 } 4660 } 4661 4662 @helper RenderProductDownloadsFields(List<LoopItem> fieldsLoop, string viewType) 4663 { 4664 foreach (LoopItem document in fieldsLoop) 4665 { 4666 string fieldValue; 4667 if (!string.IsNullOrEmpty(document.GetString("Document.FullPath"))) 4668 { 4669 fieldValue = document.GetString("Product.CustomField.Value.Clean"); 4670 @RenderFieldItem(fieldValue, document.GetString("Document.FullPath"), viewType, "download") 4671 } 4672 4673 if (document.GetString("Ecom:Product.CategoryField.TypeID") == "9") 4674 { 4675 fieldValue = document.GetString("Ecom:Product.CategoryField.Value"); 4676 @RenderFieldItem(fieldValue, fieldValue, viewType, "download") 4677 } 4678 if (!string.IsNullOrEmpty(document.GetString("Ecom:Product:Detail.Image.Clean"))) 4679 { 4680 fieldValue = document.GetString("Ecom:Product:Detail.Image.Clean"); 4681 @RenderFieldItem("", fieldValue, viewType, "download") 4682 } 4683 } 4684 } 4685 4686 @helper RenderFieldItem(string name, string value, string viewType, string fieldType = "clean") 4687 { 4688 if (viewType != "table") 4689 { 4690 string fieldColumns = viewType == "list" ? "12" : "4"; 4691 <div class="grid__col-md-@fieldColumns grid__col-sm-12 u-margin-bottom"> 4692 <div class="u-bold"> 4693 @name 4694 </div> 4695 <div> 4696 @RenderFieldItemContent(name, value, fieldType) 4697 </div> 4698 </div> 4699 } 4700 else 4701 { 4702 <tr> 4703 <th>@name</th> 4704 <td> 4705 @RenderFieldItemContent(name, value, fieldType) 4706 </td> 4707 </tr> 4708 } 4709 } 4710 4711 @helper RenderFieldItemContent(string name, string value, string fieldType = "clean") 4712 { 4713 if (fieldType == "link") 4714 { 4715 <a target="_blank" rel="noopener" href="@value"> 4716 @if (isImage(value)) 4717 { 4718 @getIconForFile(value) 4719 } 4720 else 4721 { 4722 @value 4723 } 4724 </a> 4725 } 4726 else if (fieldType == "download") 4727 { 4728 FileInfo info = new FileInfo(Dynamicweb.Core.SystemInformation.MapPath(value)); 4729 4730 if (info.Exists) 4731 { 4732 <div class="grid grid--no-wrap"> 4733 <a href="@value" download title="@Translate("Download")" class="product__document dw-mod">@getIconForFile(value)</a> 4734 <div class="product__document-info dw-mod"> 4735 <a href="@value" download title="@Translate("Download")" class="product__document dw-mod">@Path.GetFileName(value)</a> 4736 <small class="u-block u-margin-top">@ConvertBytes(info.Length)</small> 4737 </div> 4738 </div> 4739 } 4740 } 4741 else 4742 { 4743 @value 4744 } 4745 } 4746 4747 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 4748 @using Dynamicweb.Core 4749 @using System.Text.RegularExpressions 4750 @using System 4751 @using System.Web 4752 @using System.Collections.Generic 4753 @using Dynamicweb.Rapido.Blocks 4754 @using Dynamicweb.Rapido.Blocks.Components.General 4755 4756 @functions{ 4757 BlocksPage productVideoPage = BlocksPage.GetBlockPage("Product"); 4758 } 4759 4760 @{ 4761 var selectedVideoCategories = Pageview.AreaSettings.GetItem("ProductPage").GetList("VideoAssets").SelectedValues; 4762 var videosFromAssets = GetLoop("ImageCategories").Where(x => selectedVideoCategories.Contains(x.GetString("Category.Id"))); 4763 4764 string videosLayout = Pageview.AreaSettings.GetItem("ProductPage").GetList("VideosLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("VideosLayout").SelectedValue : "Section"; 4765 videosLayout = videosLayout == "Ribbon" || string.IsNullOrEmpty(videosLayout) ? "Section" : videosLayout; 4766 4767 int videosCount = 0; 4768 4769 if (videosFromAssets != null) 4770 { 4771 foreach (LoopItem category in videosFromAssets) { 4772 foreach (LoopItem asset in category.GetLoop("Category.Images")) { 4773 videosCount++; 4774 } 4775 } 4776 } else { 4777 foreach (LoopItem detailField in GetLoop("Details")) 4778 { 4779 if (detailField.GetString("Ecom:Product:Detail.Text").IndexOf("iframe") != -1 && detailField.GetString("Ecom:Product:Detail.Text").IndexOf("youtube.com/embed") != -1) 4780 { 4781 videosCount++; 4782 } 4783 if (detailField.GetString("Ecom:Product:Detail.Text").IndexOf("iframe") != -1 && detailField.GetString("Ecom:Product:Detail.Text").IndexOf("vimeo.com") != -1) 4784 { 4785 videosCount++; 4786 } 4787 } 4788 } 4789 4790 if (videosCount > 0 && videosLayout != "hide") 4791 { 4792 Block detailsVideos = new Block() 4793 { 4794 Name = videosLayout != "MainInformation" ? Translate("Videos") : "", 4795 Id = "Videos", 4796 SortId = 60, 4797 Template = RenderProductVideos(videosCount, videosLayout), 4798 Design = new Design 4799 { 4800 Size = "12", 4801 RenderType = RenderType.Column, 4802 HidePadding = true 4803 } 4804 }; 4805 productVideoPage.Add(videosLayout, detailsVideos); 4806 } 4807 } 4808 4809 @helper RenderProductVideos(int videosCount, string layout) { 4810 var selectedVideoCategories = Pageview.AreaSettings.GetItem("ProductPage").GetList("VideoAssets").SelectedValues; 4811 var videosFromAssets = GetLoop("ImageCategories").Where(x => selectedVideoCategories.Contains(x.GetString("Category.Id"))); 4812 4813 string videoColumn = "12"; 4814 videoColumn = videosCount == 2 ? "6" : videoColumn; 4815 videoColumn = videosCount > 2 ? "4" : videoColumn; 4816 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("VideosLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 4817 ribbonClasses = layout == "Tabs" ? "" : ribbonClasses; 4818 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("VideosLayout").SelectedValue == "Ribbon" ? "center-container--ribbon" : ""; 4819 4820 <div class="product__section @ribbonClasses dw-mod"> 4821 <div class="center-container @ribbonSubClasses dw-mod"> 4822 @if (layout == "Section") { 4823 @Render(new Heading { Title = Translate("Videos"), Level = 2 }) 4824 } 4825 4826 <div class="grid u-margin-bottom--lg"> 4827 @if (videosFromAssets != null) { 4828 foreach (LoopItem category in videosFromAssets) { 4829 foreach (LoopItem asset in category.GetLoop("Category.Images")) { 4830 //getting video ID from youtube URL 4831 string videoCode = asset.GetString("Ecom:Product:Detail.Image.Clean"); 4832 Regex regex = new Regex(@".be\/(.[^?]*)"); 4833 Match match = regex.Match(videoCode); 4834 string videoId = ""; 4835 if (match.Success) 4836 { 4837 videoId = match.Groups[1].Value; 4838 } 4839 else 4840 { 4841 regex = new Regex(@"v=([^&]+)"); 4842 match = regex.Match(videoCode); 4843 if (match.Success) 4844 { 4845 videoId = match.Groups[1].Value; 4846 } 4847 } 4848 4849 <div class="grid__col-md-@videoColumn grid__col-lg-@videoColumn"> 4850 <div class="video-wrapper"> 4851 <div class="js-youtube-video" data-video="@videoId" id="ytPlayer@(Guid.NewGuid().ToString("N"))" data-auto-play="False" data-enable-controls="1"></div> 4852 </div> 4853 </div> 4854 } 4855 } 4856 } else { 4857 foreach (LoopItem detailField in GetLoop("Details")) 4858 { 4859 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) 4860 { 4861 <div class="grid__col-md-@videoColumn grid__col-lg-@videoColumn"> 4862 <div class="video-wrapper"> 4863 @detailField.GetString("Ecom:Product:Detail.Text") 4864 </div> 4865 </div> 4866 } 4867 } 4868 } 4869 </div> 4870 </div> 4871 </div> 4872 } 4873 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 4874 @using Dynamicweb.Core 4875 @using System 4876 @using System.Web 4877 @using System.Collections.Generic 4878 @using Dynamicweb.Rapido.Blocks.Components.General 4879 @using Dynamicweb.Rapido.Blocks 4880 @using Dynamicweb.Rapido.Services 4881 4882 4883 @functions{ 4884 BlocksPage productRelatedPage = BlocksPage.GetBlockPage("Product"); 4885 } 4886 4887 @{ 4888 string relatedProductsLayout = Pageview.AreaSettings.GetItem("ProductPage").GetList("RelatedProductsLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("RelatedProductsLayout").SelectedValue : "Section"; 4889 relatedProductsLayout = relatedProductsLayout == "Ribbon" || string.IsNullOrEmpty(relatedProductsLayout) ? "Section" : relatedProductsLayout; 4890 bool relatedShowStock = Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetBoolean("ShowStockAndShipping"); 4891 bool showAddToDownloadButton = Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetBoolean("ShowAddToDownloadButton"); 4892 bool relatedShowPrice = !Pageview.AreaSettings.GetItem("ProductList").GetBoolean("HidePrice"); 4893 bool relatedShowFavoriteButton = !Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetBoolean("HideFavoriteButton") && Pageview.User != null; 4894 bool relatedPointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly"); 4895 bool relatedShowCartButton = Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetBoolean("ShowAddToCartButton"); 4896 bool relatedShowViewButton = Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetBoolean("ShowViewButton"); 4897 string relatedCartIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon") != null ? Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon").SelectedValue : "fas fa-shopping-cart"; 4898 string relatedMoreText = !string.IsNullOrEmpty(Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetString("ViewMoreText")) ? Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetString("ViewMoreText") : "View"; 4899 bool relatedShowNumber = Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetBoolean("ShowProductNumber"); 4900 string relatedImageZoomOnHover = Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetBoolean("HoverImageZoom") ? "image-hover--zoom" : ""; 4901 4902 int relatedProductsPageSize = 4; 4903 4904 if (Pageview.Device.ToString() == "Mobile") 4905 { 4906 relatedProductsPageSize = 1; 4907 } 4908 4909 if (Pageview.Device.ToString() == "Tablet") 4910 { 4911 relatedProductsPageSize = 3; 4912 } 4913 4914 int relatedProductsColumnWidth = 12 / relatedProductsPageSize; 4915 4916 if (relatedProductsLayout != "hide") 4917 { 4918 var i = 0; 4919 foreach (LoopItem relatedGroup in GetLoop("ProductRelatedGroups")) 4920 { 4921 string relatedGroupId = ToPascalCase(relatedGroup.GetString("Ecom:Product:RelatedGroup.Name")); 4922 string baseFeedPageUrl = "/Default.aspx?ID=" + GetPageIdByNavigationTag("ProductsPage") + "&PageSize=" + relatedProductsPageSize + "&ProdID=" + GetString("Ecom:Product.ID") + "&feed=true"; 4923 string relatedFeed = baseFeedPageUrl + "&" + relatedGroupId + "=" + GetString("Ecom:Product.ID")+ GetString("Ecom:Product.VariantID") + "&GroupName=" + relatedGroupId; 4924 string relatedGroupName = relatedProductsLayout != "maininformation" ? relatedGroup.GetString("Ecom:Product:RelatedGroup.Name") : ""; 4925 4926 i++; 4927 4928 Block detailsRelated = new Block() 4929 { 4930 Name = relatedGroupName, 4931 Id = relatedGroupId, 4932 SortId = 70 + i, 4933 Template = RenderRelatedProducts(relatedGroupName, relatedGroupId, relatedFeed, relatedProductsLayout), 4934 Design = new Design 4935 { 4936 Size = "12", 4937 RenderType = RenderType.Column, 4938 HidePadding = true 4939 } 4940 }; 4941 4942 productRelatedPage.Add(relatedProductsLayout, detailsRelated); 4943 } 4944 } 4945 } 4946 4947 @helper RenderRelatedProducts(string name, string groupId, string relatedFeedUrl, string layout) 4948 { 4949 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("RelatedProductsLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 4950 ribbonClasses = layout == "Tabs" ? "" : ribbonClasses; 4951 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("RelatedProductsLayout").SelectedValue == "Ribbon" ? "center-container--ribbon" : ""; 4952 4953 <div class="product__section @ribbonClasses dw-mod"> 4954 <div class="center-container @ribbonSubClasses dw-mod"> 4955 @if (layout == "Section") { 4956 @Render(new Heading { Title = name, Level = 2 }) 4957 } 4958 <div class="js-handlebars-root" id="ProductList_@groupId" data-template="ProductContainer" data-pre-render-template="ProductPreRenderContainer" data-json-feed="@relatedFeedUrl" data-preloader="overlay"></div> 4959 </div> 4960 </div> 4961 } 4962 4963 @* Script templates for related products *@ 4964 <script id="ProductPreRenderContainer" type="text/x-template"> 4965 <div class="u-h600px u-full-width"> 4966 <div class="grid"> 4967 <div class="grid__col-12"> 4968 <div class="pre-render-element pre-render-element--md"></div> 4969 </div> 4970 </div> 4971 </div> 4972 </script> 4973 4974 @helper RenderGridViewPriceInfo() 4975 { 4976 bool pointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly"); 4977 bool showPrice = !Pageview.AreaSettings.GetItem("ProductList").GetBoolean("HidePrice"); 4978 bool showCartButton = Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetBoolean("ShowAddToCartButton"); 4979 bool showVATPrice = Pageview.AreaSettings.GetItem("ProductList").GetBoolean("ShowBothPricesWithWithoutVAT"); 4980 bool isPricesWithVATEnabled = Dynamicweb.Ecommerce.Common.Context.DisplayPricesWithVat; 4981 4982 if (showPrice && Dynamicweb.Rapido.Services.User.IsPricesAllowed()) 4983 { 4984 if (pointShopOnly) 4985 { 4986 <text> 4987 {{#if havePointPrice}} 4988 <div class="price price--product-list dw-mod">{{points}} @Translate("points")</div> 4989 @if (showCartButton) 4990 { 4991 <text> 4992 {{#unless canBePurchasedWithPoints}} 4993 <small class="help-text u-no-margin">@Translate("Not enough points to buy this")</small> 4994 {{/unless}} 4995 </text> 4996 } 4997 {{else}} 4998 @Translate("Not available") 4999 {{/if}} 5000 </text> 5001 } 5002 else 5003 { 5004 <div class="price price--product-list dw-mod">{{price}}</div> 5005 <div class="before-price {{onSale}} dw-mod">{{discount}}</div> 5006 if (showVATPrice) 5007 { 5008 <div class="vat-price vat-price--product-list u-margin-top dw-mod"> 5009 @if (isPricesWithVATEnabled) 5010 { 5011 @* Mennt *@ 5012 <span>@Translate("veil. Pris")</span><span> ({{unitListPrice}})</span> 5013 @* END Mennt *@ 5014 } 5015 </div> 5016 } 5017 <text> 5018 {{#if priceRRP}} 5019 <div><small>@Translate("RRP") {{priceRRP}}</small></div> 5020 {{/if}} 5021 </text> 5022 } 5023 } 5024 } 5025 5026 @helper RenderProductGridItemAddToCart() { 5027 var gridViewSettings = Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView"); 5028 var ecommerceSettings = Pageview.AreaSettings.GetItem("Ecommerce"); 5029 5030 bool pointShopOnly = ecommerceSettings.GetBoolean("PointShopOnly"); 5031 bool showCartButton = gridViewSettings.GetBoolean("ShowAddToCartButton"); 5032 bool showViewButton = gridViewSettings.GetBoolean("ShowViewButton"); 5033 string viewMoreText = gridViewSettings.GetString("ViewMoreText"); 5034 viewMoreText = !string.IsNullOrEmpty(viewMoreText) ? viewMoreText : "View"; 5035 string wrapperClass = "buttons-collection--center"; 5036 int columnsCount = gridViewSettings.GetList("Columns") != null ? Converter.ToInt32(gridViewSettings.GetList("Columns").SelectedValue) : 4; 5037 bool hideButtonText = columnsCount >= 4 || Pageview.Device.ToString() == "Mobile" || Pageview.Device.ToString() == "Tablet"; 5038 5039 if (pointShopOnly && columnsCount <= 4) 5040 { 5041 hideButtonText = false; 5042 } 5043 5044 var viewBtn = new Link 5045 { 5046 Href = "{{link}}", 5047 Id = "CartButton_{{id}}", 5048 Title = Translate(viewMoreText), 5049 OnClick = "{{#if googleImpression}}googleEnchantImpressionClick({{googleImpression}}, event){{/if}}", 5050 ButtonLayout = ButtonLayout.Secondary, 5051 CssClass = "u-no-margin" 5052 }; 5053 5054 if (Dynamicweb.Rapido.Services.User.IsBuyingAllowed()) 5055 { 5056 var addToCartBtn = new AddToCart 5057 { 5058 WrapperCssClass = wrapperClass, 5059 AddButton = new AddToCartButton 5060 { 5061 ProductId = "{{productId}}", 5062 VariantId = "{{variantid}}", 5063 UnitId = "{{unitId}}", 5064 ProductInfo = "{{productInfo}}", 5065 BuyForPoints = pointShopOnly, 5066 HideTitle = hideButtonText, 5067 OnClick = "{{facebookPixelAction}}", 5068 ExtraAttributes = new Dictionary<string, string> 5069 { 5070 { "{{disabledBuyButton}}", "" } 5071 } 5072 } 5073 }; 5074 5075 if (!pointShopOnly) 5076 { 5077 addToCartBtn.QuantitySelector = new QuantitySelector 5078 { 5079 Id = "Quantity{{id}}" 5080 }; 5081 } 5082 5083 if (showCartButton && Dynamicweb.Rapido.Services.User.IsBuyingAllowed()) 5084 { 5085 if (!showViewButton) 5086 { 5087 @Render(addToCartBtn) 5088 } 5089 else 5090 { 5091 <text>{{#if hideAddToCartButton}}</text> 5092 <div>@Render(viewBtn)</div> 5093 <text>{{else}}</text> 5094 @Render(addToCartBtn) 5095 <text>{{/if}}</text> 5096 } 5097 } 5098 else if (showViewButton) 5099 { 5100 <div>@Render(viewBtn)</div> 5101 } 5102 } 5103 else if (showViewButton) 5104 { 5105 <div>@Render(viewBtn)</div> 5106 } 5107 } 5108 5109 <script id="ProductContainer" type="text/x-template"> 5110 {{#.}} 5111 <div class="u-min-h400px u-full-width"> 5112 <div class="grid"> 5113 <div class="grid__col-45px grid__col--bleed-x"> 5114 <div class="grid__cell grid__cell--align-middle-left"> 5115 @{ 5116 Button prevButton = new Button { Icon = new Icon { Prefix = "fas", Name = "fa-chevron-left fa-2x", LabelPosition = IconLabelPosition.After }, ButtonLayout = ButtonLayout.Clean, CssClass = "btn--condensed {{prevdisabled}} u-position-relative", OnClick = "HandlebarsBolt.UpdateContent('ProductList_{{groupName}}', '{{prevPage}}')" }; 5117 prevButton.ExtraAttributes.Add("", "{{prevdisabled}}"); 5118 } 5119 @Render(prevButton) 5120 </div> 5121 </div> 5122 <div class="grid__col-auto grid__col--bleed-x"> 5123 <div id="ProductsContainer" data-template="ProductGridItemContainer" class="grid product-list dw-mod" data-save-cookie="true"> 5124 {{#ProductsContainer}} 5125 <div id="Product{{productId}}" class="grid__col-@relatedProductsColumnWidth product-list__grid-item @relatedImageZoomOnHover dw-mod"> 5126 {{#Product}} 5127 <div class="grid__col--auto js-product-scroll-trigger u-no-padding u-full-height" data-params="{{googleImpression}}"> 5128 <div class="grid__cell product-list__grid-item__image dw-mod {{noImage}}"> 5129 <a href="{{link}}" 5130 onclick="{{#if googleImpression}}googleEnchantImpressionClick({{googleImpression}}, event){{/if}}" 5131 class="u-block u-position-relative image-hover__wrapper dw-mod"> 5132 @Render(new Image { Path = "{{image}}", ImageDefault = new ImageSettings { Width = 300, Height = 300, Crop = 5, FillCanvas = true, DoNotUpscale = true }, Title = "{{name}}", CssClass = "grid__cell-img grid__cell-img--centered u-min-h180px" }) 5133 {{#StickersContainers}} 5134 {{>StickersContainer}} 5135 {{/StickersContainers}} 5136 </a> 5137 @if (relatedShowFavoriteButton) 5138 { 5139 <div class="favorites favorites--for-grid-view u-pull--right {{hasVariants}} dw-mod" {{hasVariants}}> 5140 {{#Favorite}} 5141 {{>FavoriteTemplate}} 5142 {{/Favorite}} 5143 </div> 5144 } 5145 </div> 5146 5147 <div class="grid__cell product-list__grid-item__price-info dw-mod"> 5148 <a href="{{link}}" onclick="{{#if googleImpression}}googleEnchantImpressionClick({{googleImpression}}, event){{/if}}" title="{{name}}" class="u-color-inherit"> 5149 @Render(new Heading { Title = "{{name}}", Level = 6, CssClass = "u-condensed-text u-bold" }) 5150 </a> 5151 5152 @if (relatedShowNumber) 5153 { 5154 @* Mennt *@ 5155 <div class="item-number dw-mod">{{productId}}</div> 5156 @* END Mennt *@ 5157 } 5158 5159 @RenderGridViewPriceInfo() 5160 </div> 5161 5162 <div class="product-list__grid-item__footer dw-mod"> 5163 @RenderProductGridItemAddToCart() 5164 5165 @if (User.IsStockInfoAllowed() && relatedShowStock) 5166 { 5167 <div class="u-margin-top"> 5168 <div><span class="stock-icon {{stockState}} u-no-margin dw-mod" title="{{stockText}}"></span> {{stockText}}</div> 5169 <div> 5170 {{#if deliveryText}} 5171 {{deliveryText}} 5172 {{else}} 5173 - 5174 {{/if}} 5175 </div> 5176 </div> 5177 } 5178 5179 @if (showAddToDownloadButton && Pageview.User != null) 5180 { 5181 Button addButton = new Button { Title = "<span class='js-button-text'>" + Translate("Add") + "</span>", ButtonLayout = ButtonLayout.Primary, CssClass = "u-no-margin u-margin-top btn--condensed dw-mod js-add-to-downloads", Icon = new Icon { Prefix = "fas", Name = "fa-plus", CssClass = "js-button-icon", LabelPosition = IconLabelPosition.After } }; 5182 addButton.ExtraAttributes.Add("data-product-id", "{{productId}}"); 5183 @Render(addButton) 5184 } 5185 </div> 5186 </div> 5187 {{/Product}} 5188 </div> 5189 {{/ProductsContainer}} 5190 </div> 5191 </div> 5192 <div class="grid__col-45px grid__col--bleed-x"> 5193 <div class="grid__cell grid__cell--align-middle-right"> 5194 @{ 5195 Button nextButton = new Button { Icon = new Icon { Prefix = "fas", Name = "fa-chevron-right fa-2x", LabelPosition = IconLabelPosition.After }, ButtonLayout = ButtonLayout.Clean, CssClass = "btn--condensed {{nextdisabled}} u-position-relative", OnClick = "HandlebarsBolt.UpdateContent('ProductList_{{groupName}}', '{{nextPage}}')" }; 5196 nextButton.ExtraAttributes.Add("", "{{nextdisabled}}"); 5197 } 5198 @Render(nextButton) 5199 </div> 5200 </div> 5201 </div> 5202 </div> 5203 {{/.}} 5204 </script> 5205 5206 <script id="StickersContainer" type="text/x-template"> 5207 <div class="stickers-container stickers-container--{{{convertStickerPositionToClassName Position}}} dw-mod"> 5208 {{#Stickers}} 5209 {{>Sticker}} 5210 {{/Stickers}} 5211 </div> 5212 </script> 5213 5214 <script id="Sticker" type="text/x-template"> 5215 @Render(new Sticker { Title = "{{Title}}", CssClass = "{{CssClass}}" }) 5216 </script> 5217 5218 <script> 5219 @{ 5220 bool relatedUseGoogleTagManager = !string.IsNullOrEmpty(Pageview.AreaSettings.GetItem("Settings").GetString("GoogleTagManagerID")); 5221 5222 if (relatedUseGoogleTagManager) 5223 { 5224 <text> 5225 document.addEventListener("DOMContentLoaded", function (event) { 5226 Scroll.AddIsInViewportListener(".js-product-scroll-trigger", function (elem) { 5227 let googleImpression = JSON.parse(elem.getAttribute("data-params")); 5228 googleImpression.list = "Related products"; 5229 googleEnchantImpression(googleImpression); 5230 elem.classList.remove("js-product-scroll-trigger"); 5231 }); 5232 }); 5233 </text> 5234 } 5235 } 5236 </script> 5237 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 5238 @using Dynamicweb.Core 5239 @using System 5240 @using System.Web 5241 @using System.Collections.Generic 5242 @using Dynamicweb.Rapido.Blocks 5243 @using Dynamicweb.Rapido.Blocks.Components.General 5244 @using Dynamicweb.Rapido.Blocks.Components.Ecommerce 5245 @using Dynamicweb.Rapido.Services 5246 5247 @functions { 5248 BlocksPage productVariantsListPage = BlocksPage.GetBlockPage("Product"); 5249 Dictionary<string, object> variantListSettings = new Dictionary<string, object> { 5250 { "RenderVariantsAsProducts", false }, 5251 { "RenderVariantGroupsInTable", false }, 5252 { "HideImage", false }, 5253 { "HideProductNumbers", false } 5254 }; 5255 } 5256 5257 @{ 5258 var variantsCount = GetInteger("Ecom:Product.VariantCount"); 5259 string variantsListLayout = Pageview.AreaSettings.GetItem("ProductPage").GetList("VariantsListLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("VariantsListLayout").SelectedValue : "Section"; 5260 variantsListLayout = variantsListLayout == "Ribbon" ? "Section" : variantsListLayout; 5261 5262 //family members 5263 bool isFamilyMember = false; 5264 var variantGroups = GetLoop("VariantGroups"); 5265 var variantGroupCount = variantGroups.Count; 5266 if (variantGroupCount == 1) 5267 { 5268 var firstVariantGroup = Dynamicweb.Ecommerce.Services.VariantGroups.GetVariantGroup(Dynamicweb.Ecommerce.Common.Context.LanguageID, variantGroups[0]?.GetString("Ecom:VariantGroup.ID")); 5269 if (firstVariantGroup != null) 5270 { 5271 isFamilyMember = firstVariantGroup.Family; 5272 } 5273 } 5274 if (isFamilyMember) 5275 { 5276 variantListSettings["RenderVariantsAsProducts"] = variantsCount > 1 && Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("RenderFamilyVariantsAsProducts"); 5277 variantListSettings["RenderVariantGroupsInTable"] = false; 5278 variantListSettings["HideImage"] = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideImageForEachFamilyVariant"); 5279 variantListSettings["HideProductNumbers"] = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideFamilyProductNumbers"); 5280 } 5281 else 5282 { 5283 variantListSettings["RenderVariantsAsProducts"] = variantsCount > 1 && Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("RenderVariantsAsProductList"); 5284 variantListSettings["RenderVariantGroupsInTable"] = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("RenderVariantGroupsInTable"); 5285 variantListSettings["HideImage"] = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideImageForEachVariant"); 5286 variantListSettings["HideProductNumbers"] = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideProductNumbers"); 5287 } 5288 5289 if (Converter.ToBoolean(variantListSettings["RenderVariantsAsProducts"]) && variantsListLayout != "hide" && (isFamilyMember || !isFamilyMember)) 5290 { 5291 productVariantsListPage.Add(variantsListLayout, new Block 5292 { 5293 Name = variantsListLayout != "MainInformation" ? Translate("Variants list") : "", 5294 Id = "VariantsList", 5295 SortId = 20, 5296 Template = RenderVariantsProductList(variantsListLayout), 5297 Design = new Design 5298 { 5299 Size = "12", 5300 RenderType = RenderType.Column, 5301 HidePadding = true 5302 } 5303 }); 5304 5305 productVariantsListPage.Add("Section", new Block 5306 { 5307 Id = "VariantListScripts", 5308 SortId = 100, 5309 Template = RenderVariantListScripts(), 5310 Design = new Design {} 5311 }); 5312 } 5313 } 5314 5315 @helper RenderVariantsProductList(string layout) 5316 { 5317 string variantsListPageSize = HttpContext.Current.Request.QueryString.Get("PageSize") ?? "30"; 5318 string variantsFeedUrl = "/Default.aspx?ID=" + GetPageIdByNavigationTag("ProductsPage") + "&PageSize=" + variantsListPageSize + "&MainProductID=" + GetString("Ecom:Product.ID") + "&OnlyShowVariants=true&feed=true"; 5319 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("VariantsListLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 5320 ribbonClasses = layout == "Tabs" ? "" : ribbonClasses; 5321 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("VariantsListLayout").SelectedValue == "Ribbon" ? "center-container--ribbon" : ""; 5322 5323 <div class="product__section @ribbonClasses dw-mod"> 5324 <div class="center-container @ribbonSubClasses dw-mod"> 5325 @if (layout == "Section") 5326 { 5327 @Render(new Heading { Title = Translate("Variants"), Level = 2 }) 5328 } 5329 <div class="js-handlebars-root" id="VariantsListRoot" data-template="VariantProductsContainer" data-json-feed="@variantsFeedUrl" data-preloader="minimal"></div> 5330 </div> 5331 </div> 5332 } 5333 5334 @helper RenderVariantListScripts() 5335 { 5336 bool showProductNumberForVariants = !Converter.ToBoolean(variantListSettings["HideProductNumbers"]); 5337 bool showImageForEachVariant = !Converter.ToBoolean(variantListSettings["HideImage"]); 5338 bool variantsPointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly"); 5339 string variantsListPageSize = HttpContext.Current.Request.QueryString.Get("PageSize") ?? "30"; 5340 string variantsFeedUrl = "/Default.aspx?ID=" + GetPageIdByNavigationTag("ProductsPage") + "&PageSize=" + variantsListPageSize + "&MainProductID=" + GetString("Ecom:Product.ID") + "&OnlyShowVariants=true&feed=true"; 5341 string variantsCartIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon") != null ? Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon").SelectedValue : "fas fa-shopping-cart"; 5342 5343 <script id="VariantProductsContainer" type="text/x-template"> 5344 {{#.}} 5345 <div> 5346 <table id="VariantsProductsContainer" class="table u-position-relative dw-mod"> 5347 <thead> 5348 <tr> 5349 @if (showImageForEachVariant) 5350 { 5351 <td width="75">&nbsp;</td> 5352 } 5353 <td>@Translate("Product")</td> 5354 {{#AvailableCustomFields}} 5355 {{>TableFieldNameTemplate}} 5356 {{/AvailableCustomFields}} 5357 @if (Converter.ToBoolean(variantListSettings["RenderVariantGroupsInTable"])) { 5358 foreach (LoopItem variantgroup in GetLoop("VariantGroups")) 5359 { 5360 <td>@variantgroup.GetString("Ecom:VariantGroup.Name")</td> 5361 } 5362 } 5363 <td>&nbsp;</td> 5364 </tr> 5365 </thead> 5366 5367 <tbody id="VariantProductListContainer" data-template="VariantProductItemContainer" data-save-cookie="true"> 5368 {{#ProductsContainer}} 5369 {{>VariantProductItemContainer}} 5370 {{/ProductsContainer}} 5371 </tbody> 5372 </table> 5373 </div> 5374 5375 <div class="grid"> 5376 <div class="grid__col-12 grid__col--bleed-y"> 5377 @{ 5378 Button moreButton = new Button { Id = "LoadMoreButton", ButtonLayout = ButtonLayout.Primary, CssClass = "btn--full {{nextdisabled}}", Title = Translate("Load") + " " + Translate("more"), OnClick = "LoadMore.Next(this)" }; 5379 moreButton.ExtraAttributes.Add("data-current", "{{currentPage}}"); 5380 moreButton.ExtraAttributes.Add("data-page-size", "{{pageSize}}"); 5381 moreButton.ExtraAttributes.Add("data-total", "{{totalPages}}"); 5382 moreButton.ExtraAttributes.Add("data-container", "VariantProductListContainer"); 5383 moreButton.ExtraAttributes.Add("data-feed-url", variantsFeedUrl + "{{loadMoreFeedParams}}"); 5384 moreButton.ExtraAttributes.Add("", "{{nextdisabled}}"); 5385 } 5386 @Render(moreButton) 5387 </div> 5388 </div> 5389 {{/.}} 5390 </script> 5391 5392 <script id="VariantProductItemContainer" type="text/x-template"> 5393 {{#.}} 5394 <tr id="VariantProduct{{id}}" class="js-product" data-template="VariantProductItem" data-preloader="overlay" style="z-index: {{zIndex}}"> 5395 {{#Product}} 5396 {{>VariantProductItem}} 5397 {{/Product}} 5398 </tr> 5399 {{/.}} 5400 </script> 5401 5402 <script id="VariantProductItem" type="text/x-template"> 5403 {{#.}} 5404 @if (showImageForEachVariant) 5405 { 5406 <td width="75"> 5407 <div class="lightbox u-hidden-xxs"> 5408 <a href="{{link}}" onclick="Scroll.SavePosition(event)" title="{{name}}{{#if variantName}}, {{variantName}}{{/if}}"> 5409 <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}}{{#if variantName}}, {{variantName}}{{/if}}" /> 5410 <div class="u-margin-right {{noImage}}"> 5411 <img src="/Admin/Public/GetImage.ashx?width=75&amp;height=55&amp;crop=5&FillCanvas=true&amp;Compression=75&amp;image={{image}}" alt="{{name}}{{#if variantName}}, {{variantName}}{{/if}}" /> 5412 </div> 5413 </a> 5414 </div> 5415 </td> 5416 } 5417 5418 <td class="u-va-middle"> 5419 <a href="{{link}}" onclick="Scroll.SavePosition(event)" title="{{name}}{{#if variantName}}, {{variantName}}{{/if}}"> 5420 <h6 class="u-no-margin">{{name}}{{#if variantName}}, {{variantName}}{{/if}}</h6> 5421 </a> 5422 @if (showProductNumberForVariants) 5423 { 5424 <div class="item-number item-number--compressed u-margin-bottom dw-mod"> 5425 <div>{{number}}</div> 5426 </div> 5427 } 5428 @if (User.IsStockInfoAllowed()) 5429 { 5430 <text>{{#if stockText}}</text> 5431 <div class="item-number item-number--compressed dw-mod"> 5432 <span> 5433 <span class="stock-icon {{stockState}} u-no-margin dw-mod" title="{{stockText}}"></span> 5434 <span class="u-margin-right--lg"> {{stockText}}</span> 5435 {{deliveryText}} 5436 </span> 5437 </div> 5438 <text>{{/if}}</text> 5439 } 5440 else 5441 { 5442 <div class="grid__cell-footer stickers-container stickers-container--block dw-mod"> 5443 {{#Stickers}} 5444 {{>MiniSticker}} 5445 {{/Stickers}} 5446 </div> 5447 } 5448 </td> 5449 {{#CustomFields}} 5450 {{>TableFieldValueTemplate}} 5451 {{/CustomFields}} 5452 @if (Converter.ToBoolean(variantListSettings["RenderVariantGroupsInTable"])) 5453 { 5454 <text> 5455 {{#VariantSelectionNames}} 5456 {{>TableFieldNameTemplate}} 5457 {{/VariantSelectionNames}} 5458 </text> 5459 } 5460 <td class="u-va-middle"> 5461 @if (Dynamicweb.Rapido.Services.User.IsPricesAllowed() && !Dynamicweb.Rapido.Services.User.IsBuyingAllowed()) 5462 { 5463 <div class="u-hidden-sm"> 5464 <div class="u-full-width u-ta-right u-padding-right"> 5465 <div class="before-price {{onSale}} before-price--micro dw-mod">{{discount}}</div> 5466 <div class="price price--product-list price--micro dw-mod">{{price}}</div> 5467 </div> 5468 </div> 5469 } 5470 5471 <div class="grid grid--align-center grid--justify-end"> 5472 <div class="u-margin-right u-hidden-xs u-hidden-xxs"> 5473 @if (variantsPointShopOnly) 5474 { 5475 <text> 5476 {{#if canBePurchasedWithPoints}} 5477 <div class="price price--product-list price--micro dw-mod">{{points}} @Translate("points")</div> 5478 {{else}} 5479 {{#if havePointPrice}} 5480 <small class="help-text u-no-margin u-margin-top">@Translate("Not enough points to buy this")</small> 5481 {{else}} 5482 <small class="help-text u-no-margin u-margin-top">@Translate("Not available")</small> 5483 {{/if}} 5484 {{/if}} 5485 </text> 5486 } 5487 else if (Dynamicweb.Rapido.Services.User.IsPricesAllowed()) 5488 { 5489 <div class="before-price before-price--micro {{onSale}} dw-mod">{{discount}}</div> 5490 <div class="price price--condensed price--product-list dw-mod">{{price}}</div> 5491 } 5492 </div> 5493 5494 @if (Dynamicweb.Rapido.Services.User.IsBuyingAllowed()) 5495 { 5496 var addToCartBtn = new AddToCart 5497 { 5498 AddButton = new AddToCartButton 5499 { 5500 HideTitle = true, 5501 ProductId = "{{productId}}", 5502 VariantId = "{{variantid}}", 5503 UnitId = "{{unitId}}", 5504 ProductInfo = "{{productInfo}}", 5505 BuyForPoints = variantsPointShopOnly, 5506 OnClick = "{{facebookPixelAction}}" 5507 }, 5508 UnitSelector = new UnitSelector 5509 { 5510 OptionsContent = "{{#unitOptions}}{{>VariantUnitOption}}{{/unitOptions}}", 5511 Id = "UnitOptions_{{id}}", 5512 SelectedOption = "{{unitName}}", 5513 CssClass = "{{hasUnits}}" 5514 } 5515 }; 5516 5517 if (!variantsPointShopOnly) 5518 { 5519 addToCartBtn.QuantitySelector = new QuantitySelector 5520 { 5521 Id = "Quantity_{{id}}" 5522 }; 5523 } 5524 5525 <div class="grid__cell u-flex-grow--0"> 5526 @Render(addToCartBtn) 5527 </div> 5528 } 5529 <div class="favorites u-margin-left dw-mod"> 5530 {{#Favorite}} 5531 {{>FavoriteTemplate}} 5532 {{/Favorite}} 5533 </div> 5534 </div> 5535 </td> 5536 {{/.}} 5537 </script> 5538 5539 <script id="TableFieldNameTemplate" type="text/x-template"> 5540 <td class="u-va-middle">{{name}}</td> 5541 </script> 5542 5543 <script id="TableFieldValueTemplate" type="text/x-template"> 5544 <td class="u-va-middle">{{value}}</td> 5545 </script> 5546 5547 <script id="MiniSticker" type="text/x-template"> 5548 <div class="stickers-container__tag stickers-container__tag--micro {{CssClass}} dw-mod">{{Title}}</div> 5549 </script> 5550 5551 <script id="VariantUnitOption" type="text/x-template"> 5552 <div class="dropdown__item dw-mod" onclick="HandlebarsBolt.UpdateContent(this.closest('.js-product').id, '{{link}}&feed=true&UnitID={{value}}')">{{name}}</div> 5553 </script> 5554 } 5555 5556 5557 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 5558 @using Dynamicweb.Core 5559 @using System 5560 @using System.Web 5561 @using System.Collections.Generic 5562 @using Dynamicweb.Rapido.Blocks 5563 @using Dynamicweb.Rapido.Blocks.Components.General 5564 @using Dynamicweb.Rapido.Blocks.Components.Ecommerce 5565 5566 @functions { 5567 BlocksPage productVariantsMatrixPage = BlocksPage.GetBlockPage("Product"); 5568 } 5569 5570 5571 @{ 5572 var matrixLayoutSetting = Pageview.AreaSettings.GetItem("ProductPage").GetList("VariantsMatrixLayout"); 5573 string variantsMatrixLayout = matrixLayoutSetting != null && !string.IsNullOrEmpty(matrixLayoutSetting.SelectedValue) ? matrixLayoutSetting.SelectedValue : "Section"; 5574 variantsMatrixLayout = variantsMatrixLayout == "Ribbon" ? "Section" : variantsMatrixLayout; 5575 bool renderVariantsAsMatrix = GetInteger("Ecom:Product.VariantCount") > 1 && variantsMatrixLayout.ToLower() != "hide" && Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("EnableVariantMatrix"); 5576 5577 if (renderVariantsAsMatrix) 5578 { 5579 Block variantsMatrix = new Block() 5580 { 5581 Name = Translate("Variants"), 5582 Id = "VariantsMatrix", 5583 SortId = 15, 5584 Template = RenderVariantsMatrixSection(variantsMatrixLayout), 5585 Design = new Design 5586 { 5587 Size = "12", 5588 RenderType = RenderType.Column, 5589 HidePadding = true 5590 } 5591 }; 5592 5593 if (variantsMatrixLayout == "Section") { 5594 productVariantsMatrixPage.Add(variantsMatrix); 5595 } else { 5596 productVariantsMatrixPage.Add(variantsMatrixLayout, variantsMatrix); 5597 } 5598 } 5599 } 5600 5601 @helper RenderVariantsMatrixSection(string layout) 5602 { 5603 string cartIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon") != null ? Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon").SelectedValue : "fas fa-shopping-cart"; 5604 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("VariantsListLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 5605 ribbonClasses = layout == "Tabs" ? "" : ribbonClasses; 5606 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("VariantsListLayout").SelectedValue == "Ribbon" ? "center-container--ribbon" : ""; 5607 5608 List<LoopItem> variantInfos = GetLoop("VariantInfos"); 5609 string productId = GetString("Ecom:Product.ID"); 5610 string pageId = Pageview.Page.ID.ToString(); 5611 5612 5613 <div class="product__section u-no-padding @ribbonClasses dw-mod"> 5614 <div class="center-container @ribbonSubClasses dw-mod"> 5615 @RenderVariantInfoMatrix(variantInfos, productId, pageId, 0, "add") 5616 </div> 5617 </div> 5618 } 5619 5620 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 5621 @using Dynamicweb.Rendering 5622 @using Dynamicweb.Core 5623 @using System 5624 @using System.Web 5625 @using System.Collections.Generic 5626 @using Dynamicweb.Rapido.Blocks 5627 @using Dynamicweb.Rapido.Blocks.Components 5628 @using Dynamicweb.Rapido.Blocks.Components.General 5629 5630 5631 @* Component - Variant Info Matrix. This replaces the old Variant Matrix with a much cleaner approach *@ 5632 5633 @helper RenderVariantInfoMatrix(List<LoopItem> variantInfos, string productId, string pageId, double totalPrice = 0, string actionType = "update") { 5634 string cartIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon") != null ? Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon").SelectedValue : "fas fa-shopping-cart"; 5635 bool hideAddToCartButton = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("hideAddToCartButton"); 5636 5637 string currencyCode = Dynamicweb.Ecommerce.Common.Context.Currency.Code; 5638 string countryCode = Pageview.Area.CultureInfo != null ? Pageview.Area.CultureInfo.Name : "en-US"; 5639 5640 int loopCount = 0; 5641 int dimensionsCount = 0; 5642 bool firstRun = true; 5643 List<string> headerLabels = new List<string>(); 5644 5645 //Collect the missing data needed to render matrixes 5646 foreach (var variantInfoFirst in variantInfos) 5647 { 5648 dimensionsCount = 1; 5649 5650 foreach (var variantInfoSecond in variantInfoFirst.GetLoop("VariantInfos")) 5651 { 5652 dimensionsCount = 2; 5653 5654 if (firstRun) { 5655 headerLabels.Add(variantInfoSecond.GetString("OptionName")); 5656 } 5657 5658 foreach (var variantInfoThird in variantInfoSecond.GetLoop("VariantInfos")) 5659 { 5660 dimensionsCount = 3; 5661 } 5662 } 5663 5664 firstRun = false; 5665 } 5666 5667 @*One dimension*@ 5668 if (dimensionsCount == 1) 5669 { 5670 int totalQuantity = 0; 5671 5672 <table cellspacing="0" class="table matrix js-matrix dw-mod"> 5673 <thead class="matrix__head dw-mod"> 5674 <tr> 5675 @foreach (var variantInfoFirst in variantInfos) 5676 { 5677 <td class="u-bold u-ta-center" width="80" > 5678 <div>@variantInfoFirst.GetString("OptionName")</div> 5679 <small>@variantInfoFirst.GetString("VariantId")</small> 5680 </td> 5681 } 5682 <td width="80px" align="right" class="matrix-label-field-right dw-mod">@Translate("Totals")</td> 5683 <td>&nbsp;</td> 5684 </tr> 5685 </thead> 5686 <tbody> 5687 <tr> 5688 @foreach (var variantInfoFirst in variantInfos) 5689 { 5690 double price = Dynamicweb.Ecommerce.Services.Products.GetProductById(productId, variantInfoFirst.GetString("VariantId"), Dynamicweb.Ecommerce.Common.Context.LanguageID).GetPrice(Dynamicweb.Ecommerce.Common.Context.Currency.Code, Dynamicweb.Ecommerce.Common.Context.Country.Code2).Price; 5691 5692 loopCount++; 5693 totalQuantity += variantInfoFirst.GetInteger("Quantity"); 5694 5695 <td class="matrix__input-cell dw-mod"> 5696 @if (variantInfoFirst.GetBoolean("IsProduct")) 5697 { 5698 <input type="hidden" name="ProductLoopCounter@(loopCount)" value="@(loopCount)" /> 5699 <input type="hidden" name="ProductID@(loopCount)" value="@productId" /> 5700 <input type="hidden" name="VariantID@(loopCount)" value="@variantInfoFirst.GetString("VariantId")" /> 5701 <input type="number" name="Quantity@(loopCount)" value="@variantInfoFirst.GetString("Quantity")" data-price="@price" min="0" step="1" oninput="validity.valid||(value='');" class="matrix-input-field dw-mod" onchange="Matrix.UpdateQuantities(this)" data-row-id="ONE"> 5702 } else { 5703 <div class="matrix__cell-disabled dw-mod"></div> 5704 } 5705 </td> 5706 } 5707 <td class="u-va-middle"> 5708 <div class="u-bold u-ta-right matrix-label-field-right dw-mod" data-row-total="ONE"> 5709 @totalQuantity 5710 </div> 5711 </td> 5712 <td class="u-bold u-va-middle u-ta-right matrix-label-field-right dw-mod"> 5713 <div class="js-total-price" data-currency-code="@currencyCode" data-country-code="@countryCode"></div> 5714 </td> 5715 </tr> 5716 </tbody> 5717 <tfoot> 5718 <tr> 5719 <td colspan="@(variantInfos.Count + 2)">&nbsp;</td> 5720 </tr> 5721 @if (!hideAddToCartButton) 5722 { 5723 <tr> 5724 <td colspan="@(variantInfos.Count + 2)" class="u-ta-right"> 5725 <div class="u-padding--lg"> 5726 @if (actionType == "update") { 5727 @Render(new Button { OnClick = "Matrix.UpdateCart(this, '" + pageId + "');", Title = Translate("Update"), ButtonLayout = ButtonLayout.Tertiary, Icon = new Icon { Prefix = "fal", Name = "fa-redo", LabelPosition = IconLabelPosition.After }, CssClass = "u-no-margin" }) 5728 } else if (actionType == "justadd") { 5729 @Render(new Button { OnClick = "Matrix.AddToCart(this, '" + pageId + "');", Title = Translate("Add"), ButtonLayout = ButtonLayout.Tertiary, CssClass = "u-no-margin" }) 5730 } else { 5731 @Render(new Button { OnClick = "Matrix.AddToCart(this, '" + pageId + "');", Title = Translate("Add to cart"), ButtonLayout = ButtonLayout.Tertiary, Icon = new Icon { Name = cartIcon, LabelPosition = IconLabelPosition.After }, CssClass = "u-no-margin" }) 5732 } 5733 </div> 5734 </td> 5735 </tr> 5736 } 5737 </tfoot> 5738 </table> 5739 } 5740 5741 @*Two dimensions*@ 5742 if (dimensionsCount == 2) 5743 { 5744 Dictionary<string, int> columnTotals = new Dictionary<string, int>(); 5745 int counter = 0; 5746 int totalProducts = 0; 5747 int totalColumns = 0; 5748 5749 <table class="table matrix js-matrix dw-mod" cellspacing="0"> 5750 <thead class="matrix__head dw-mod"> 5751 <tr> 5752 <td width="160">&nbsp;</td> 5753 @foreach (string label in headerLabels) 5754 { 5755 <td class="u-bold u-ta-center" width="80">@label</td> 5756 } 5757 <td align="right" width="80" class="matrix-label-field-right dw-mod">@Translate("Totals")</td> 5758 <td>&nbsp;</td> 5759 </tr> 5760 </thead> 5761 <tbody> 5762 @foreach (var variantInfoFirst in variantInfos) 5763 { 5764 int totalRowQuantity = 0; 5765 counter += variantInfoFirst.GetInteger("Quantity"); 5766 totalColumns = variantInfoFirst.GetLoop("VariantInfos").Count; 5767 5768 <tr> 5769 <td class="matrix-label-field-left dw-mod"> 5770 <div class="u-pull--left"> 5771 <div>@variantInfoFirst.GetString("OptionName")</div> 5772 <small>@variantInfoFirst.GetString("VariantId")</small> 5773 </div> 5774 5775 @if (!string.IsNullOrEmpty(variantInfoFirst.GetString("Image"))) { 5776 <div class="matrix-option-image u-pull--right dw-mod" onclick="Matrix.ShowOptionImageModal(this)" data-img-src="/files/@variantInfoFirst.GetString("Image")"> 5777 @Render(new Image { 5778 Path = variantInfoFirst.GetString("Image"), 5779 ImageDefault = new ImageSettings { 5780 Width = 28, 5781 Height = 28 5782 }, 5783 ImageMedium = new ImageSettings { 5784 Width = 28, 5785 Height = 28 5786 }, 5787 ImageSmall = new ImageSettings { 5788 Width = 28, 5789 Height = 28 5790 } 5791 }) 5792 </div> 5793 } 5794 </td> 5795 @foreach (var variantInfoSecond in variantInfoFirst.GetLoop("VariantInfos")) 5796 { 5797 loopCount++; 5798 totalRowQuantity += variantInfoSecond.GetInteger("Quantity"); 5799 5800 string optionName = variantInfoSecond.GetString("OptionName"); 5801 int optionQuantity = variantInfoSecond.GetInteger("Quantity"); 5802 if (columnTotals.ContainsKey(optionName)) { 5803 columnTotals[optionName] += optionQuantity; 5804 } else { 5805 columnTotals.Add(optionName, optionQuantity); 5806 } 5807 5808 <td class="matrix__input-cell dw-mod"> 5809 @if (variantInfoSecond.GetBoolean("IsProduct")) { 5810 double price = Dynamicweb.Ecommerce.Services.Products.GetProductById(productId, variantInfoSecond.GetString("VariantId"), Dynamicweb.Ecommerce.Common.Context.LanguageID).GetPrice(Dynamicweb.Ecommerce.Common.Context.Currency.Code, Dynamicweb.Ecommerce.Common.Context.Country.Code2).Price; 5811 5812 <input type="hidden" name="ProductLoopCounter@(loopCount)" value="@(loopCount)" /> 5813 <input type="hidden" name="ProductID@(loopCount)" value="@productId" /> 5814 <input type="hidden" name="VariantID@(loopCount)" value="@variantInfoSecond.GetString("VariantId")" /> 5815 <input type="number" name="Quantity@(loopCount)" value="@variantInfoSecond.GetString("Quantity")" data-price="@price" min="0" step="1" oninput="validity.valid||(value='');" class="matrix-input-field dw-mod" onchange="Matrix.UpdateQuantities(this)" data-row-id="@variantInfoFirst.GetString("OptionName")" data-column-id="@variantInfoSecond.GetString("OptionName")"> 5816 } else { 5817 <div class="matrix__cell-disabled dw-mod"></div> 5818 } 5819 </td> 5820 } 5821 <td class="u-va-middle matrix-label-field-right dw-mod"> 5822 <div class="u-bold u-ta-right" data-row-total="@variantInfoFirst.GetString("OptionName")"> 5823 @totalRowQuantity 5824 </div> 5825 </td> 5826 <td>&nbsp;</td> 5827 </tr> 5828 } 5829 </tbody> 5830 <tfoot> 5831 <tr> 5832 <td class="u-bold u-va-middle matrix-label-field-left dw-mod">@Translate("Totals")</td> 5833 @foreach (var item in columnTotals) 5834 { 5835 totalProducts += item.Value; 5836 5837 <td> 5838 <div class="u-bold u-ta-center u-padding--lg" data-column-total="@item.Key"> 5839 @item.Value 5840 </div> 5841 </td> 5842 } 5843 <td class="u-bold u-va-middle u-ta-right matrix-label-field-right dw-mod" align="right"> 5844 <div class="js-total-quantity">@totalProducts</div> 5845 </td> 5846 <td class="u-bold u-va-middle u-ta-right matrix-label-field-right dw-mod"> 5847 <div class="js-total-price" data-currency-code="@currencyCode" data-country-code="@countryCode"></div> 5848 </td> 5849 </tr> 5850 <tr> 5851 <td colspan="@(totalColumns + 4)" class="u-ta-right u-no-padding"> 5852 <div class="u-padding--lg"> 5853 @if (actionType == "update") { 5854 @Render(new Button { OnClick = "Matrix.UpdateCart(this, '" + pageId + "');", Title = Translate("Update"), ButtonLayout = ButtonLayout.Tertiary, Icon = new Icon { Prefix = "fal", Name = "fa-redo", LabelPosition = IconLabelPosition.After }, CssClass = "u-no-margin" }) 5855 } else { 5856 @Render(new Button { OnClick = "Matrix.AddToCart(this, '" + pageId + "');", Title = Translate("Add to cart"), ButtonLayout = ButtonLayout.Tertiary, Icon = new Icon { Name = cartIcon, LabelPosition = IconLabelPosition.After }, CssClass = "u-no-margin" }) 5857 } 5858 </div> 5859 </td> 5860 </tr> 5861 </tfoot> 5862 </table> 5863 } 5864 5865 5866 Modal optionColorImage = new Modal { 5867 Id = "OptionColorImage", 5868 BodyTemplate = @Render(new Image { Path = "/Files/Images/placeholder.gif", Id = "OptionColorImageElement", DisableImageEngine = true, DisableLazyLoad = true }), 5869 Width = ModalWidth.Full 5870 }; 5871 5872 @Render(optionColorImage) 5873 } 5874 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 5875 @using Dynamicweb.Core 5876 @using System 5877 @using System.Web 5878 @using System.Collections.Generic 5879 @using Dynamicweb.Rapido.Blocks 5880 @functions { 5881 BlocksPage productSnippetsPage = BlocksPage.GetBlockPage("Product"); 5882 } 5883 5884 @{ 5885 Block googleProductSchema = new Block() 5886 { 5887 Id = "GoogleProductSchema", 5888 SortId = 10, 5889 Template = RenderGoogleProductSchema() 5890 }; 5891 5892 productSnippetsPage.Add("Snippets", googleProductSchema); 5893 } 5894 5895 @helper RenderGoogleProductSchema() 5896 { 5897 var siteURL = Dynamicweb.Context.Current.Request.Url.Scheme + "://" + Dynamicweb.Context.Current.Request.Url.Host; 5898 var image = GetProductImage(); 5899 var brand = GetString("Ecom:Product:Field.brand.Value"); 5900 var variantid = !string.IsNullOrEmpty(GetString("Ecom:Product.VariantID")) ? GetString("Ecom:Product.VariantID") : GetString("Ecom:Product.VariantID.Extented"); 5901 var url = Dynamicweb.Context.Current.Request.Url.Scheme + "://" + GetGlobalValue("Global:Request.Host") + Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl(GetString("Ecom:Product.LinkGroup.Clean") + (!string.IsNullOrWhiteSpace(variantid) ? "&VariantID=" + variantid : "")); 5902 5903 <script type="application/ld+json"> 5904 { 5905 "@@context": "http://schema.org/", 5906 "@@type": "Product", 5907 "name": "@GetString("Ecom:Product.Name")", 5908 @if (!string.IsNullOrEmpty(image)) 5909 { 5910 <text>"image": [ 5911 "@siteURL/Admin/Public/GetImage.ashx?width=400&height=400&crop=0&Compression=75&DoNotUpscale=true&image=@image", 5912 "@siteURL/Admin/Public/GetImage.ashx?width=400&height=300&crop=0&Compression=75&DoNotUpscale=true&image=@image", 5913 "@siteURL/Admin/Public/GetImage.ashx?width=448&height=225&crop=0&Compression=75&DoNotUpscale=true&image=@image" 5914 ],</text> 5915 } 5916 "description": "@GetString("Ecom:Product.ShortDescription")", 5917 "mpn": "925872", 5918 @if (!string.IsNullOrEmpty(brand)) 5919 { 5920 <text>"brand": { 5921 "@@type": "Thing", 5922 "name": "@brand" 5923 },</text> 5924 } 5925 "offers": { 5926 "@@type": "Offer", 5927 "priceCurrency": "@GetString("Ecom:Product.Price.Currency.Code")", 5928 "price": "@GetString("Ecom:Product.Price.Price")", 5929 "availability": "@(GetInteger("Ecom:Product.Stock") > 0 ? "InStock" : "OutOfStock")", 5930 "url": "@url" 5931 } 5932 } 5933 </script> 5934 } 5935 5936 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 5937 5938 @using Dynamicweb.Rapido.Blocks 5939 5940 @functions { 5941 BlocksPage snippetsTemplatesPage = BlocksPage.GetBlockPage("Product"); 5942 } 5943 5944 @{ 5945 snippetsTemplatesPage.Add(new Block { 5946 Id = "FavoritesTemplates", 5947 SortId = 100, 5948 Template = RenderFavoritesTemplates() 5949 }); 5950 } 5951 5952 @helper RenderFavoritesTemplates() 5953 { 5954 var selectedFavoriteIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("FavoriteIcon") != null ? Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("FavoriteIcon").SelectedValue : "star"; 5955 string favoriteIcon = "fas fa-" + selectedFavoriteIcon; 5956 string favoriteOutlineIcon = "fal fa-" + selectedFavoriteIcon; 5957 bool useFacebookPixel = !string.IsNullOrEmpty(Pageview.AreaSettings.GetItem("Settings").GetString("FacebookPixelID")); 5958 string currentFavoriteListId = HttpContext.Current.Request.QueryString.Get("ListID"); 5959 5960 <script id="FavoriteTemplate" type="text/x-template"> 5961 <div class="favorites-list u-ta-left js-favorites-list"> 5962 @Render(new Button { 5963 CssClass = "u-no-margin js-favorite-btn", 5964 Icon = new Icon 5965 { 5966 Name = "{{#if isInAnyFavoriteList}}" + favoriteIcon + "{{else}}" + favoriteOutlineIcon + "{{/if}}", 5967 CssClass = "fa-1_5x", 5968 LabelPosition = IconLabelPosition.After 5969 }, 5970 ButtonLayout = ButtonLayout.LinkClean, 5971 ButtonType = ButtonType.Button, 5972 OnClick = "document.getElementById('FavoriteTrigger_{{id}}').checked = true" 5973 }) 5974 <input type="checkbox" id="FavoriteTrigger_{{id}}" class="dropdown-trigger" /> 5975 <div class="dropdown dropdown--position-32px"> 5976 <div class="dropdown__content dropdown__content--show-left dropdown__content--padding u-w220px dw-mod"> 5977 <ul class="list list--clean dw-mod"> 5978 {{#FavoriteLists}} 5979 {{>FavoriteListItem}} 5980 {{/FavoriteLists}} 5981 </ul> 5982 </div> 5983 <label class="dropdown-trigger-off" for="FavoriteTrigger_{{id}}"></label> 5984 </div> 5985 </div> 5986 </script> 5987 5988 <script id="FavoriteListItem" type="text/x-template"> 5989 <li> 5990 @{ 5991 var button = new Button { 5992 CssClass = "list__link u-no-underline", 5993 OnClick = "toggleFavAction(this, event)", 5994 Icon = new Icon { Name = "{{#if isInFavoriteList}}" + favoriteIcon + "{{else}}" + favoriteOutlineIcon + "{{/if}}", LabelPosition = IconLabelPosition.After }, 5995 AltText = "{{#if isInFavoriteList}}" + Translate("Remove from") + " {{name}}{{else}}" + Translate("Add to") + " {{name}}{{/if}}", 5996 Title = "{{name}}", 5997 ButtonType = ButtonType.Button, 5998 ButtonLayout = ButtonLayout.LinkClean, 5999 ExtraAttributes = new Dictionary<string, string> 6000 { 6001 { "data-list-id", "{{listId}}" }, 6002 { "data-list-name", "{{name}}" }, 6003 { "data-remove-link", "{{removeLink}}" }, 6004 { "data-add-link", "{{addLink}}" }, 6005 { "data-is-in-list", "{{isInFavoriteList}}" }, 6006 6007 } 6008 }; 6009 if (useFacebookPixel) 6010 { 6011 button.ExtraAttributes.Add("data-facebook-object", "{{facebookPixelAddAction}}"); 6012 } 6013 } 6014 <div class="grid__cell"> 6015 @Render(button) 6016 </div> 6017 </li> 6018 </script> 6019 6020 <script> 6021 @if (!string.IsNullOrEmpty(currentFavoriteListId)) 6022 { 6023 <text> 6024 window.currentFavoriteListId = "@currentFavoriteListId"; 6025 </text> 6026 } 6027 function toggleFavAction(button, event) { 6028 if (button.getAttribute('data-add-link').indexOf('CCCreateNewList') > -1) { 6029 Scroll.SavePosition(event); 6030 @if (useFacebookPixel) 6031 { 6032 <text> 6033 fbq('track', 'AddToWishlist', JSON.parse(button.getAttribute('data-facebook-object'))); 6034 </text> 6035 } 6036 location.href = button.getAttribute('data-add-link'); 6037 return; 6038 } 6039 let isAdd = button.getAttribute('data-is-in-list') == "false"; 6040 Request.Fetch().get( 6041 isAdd ? button.getAttribute('data-add-link') : button.getAttribute('data-remove-link'), 6042 function (result) { 6043 button.querySelector('i').className = isAdd ? '@favoriteIcon u-margin-right--lg' : '@favoriteOutlineIcon u-margin-right--lg'; 6044 button.setAttribute('data-is-in-list', isAdd); 6045 button.setAttribute('title', (!isAdd ? '@Translate("Add to") ' : '@Translate("Remove from") ') + button.getAttribute('data-list-name')) 6046 let favList = button.closest('.js-favorites-list'); 6047 let favBtn = favList.querySelector('.js-favorite-btn i'); 6048 let isInAnyFavoriteList = favList.querySelector('[data-is-in-list=true]') != null; 6049 if (isInAnyFavoriteList) { 6050 favBtn.className = '@favoriteIcon' + ' fa-1_5x'; 6051 } else { 6052 favBtn.className = '@favoriteOutlineIcon' + ' fa-1_5x'; 6053 } 6054 @if (useFacebookPixel) 6055 { 6056 <text> 6057 if (isAdd) { 6058 fbq('track', 'AddToWishlist', JSON.parse(button.getAttribute('data-facebook-object'))); 6059 } 6060 </text> 6061 } 6062 if (window.currentFavoriteListId != null) { //if this page is favorite list 6063 let listId = button.getAttribute("data-list-id"); 6064 if (listId == window.currentFavoriteListId && !isAdd) { 6065 location.reload(); 6066 } 6067 } 6068 }, 6069 function () { 6070 console.error("FavoriteLists: Error in ToggleFavAction request"); 6071 }, 6072 false 6073 ); 6074 } 6075 </script> 6076 } 6077 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 6078 @using Dynamicweb.Core 6079 @using System 6080 @using System.Web 6081 @using System.Collections.Generic 6082 @using Dynamicweb.Rapido.Blocks 6083 6084 @{ 6085 BlocksPage customProductBlocks = BlocksPage.GetBlockPage("Product"); 6086 6087 Block mainInfoVariantsCustom = new Block 6088 { 6089 Id = "Variants", 6090 SortId = 50, 6091 Template = RenderMainInfoVariantsCustom() 6092 }; 6093 customProductBlocks.ReplaceBlock(mainInfoVariantsCustom); 6094 6095 Block mainInfoBuyCustom = new Block 6096 { 6097 Id = "Buy", 6098 SortId = 80, 6099 Template = RenderMainInfoBuyCustom() 6100 }; 6101 customProductBlocks.ReplaceBlock(mainInfoBuyCustom); 6102 6103 Block MainInfoHeaderCustom = new Block 6104 { 6105 Id = "MainInfoHeader", 6106 SortId = 10, 6107 Template = RenderMainInfoHeaderCustom() 6108 }; 6109 customProductBlocks.ReplaceBlock(MainInfoHeaderCustom); 6110 6111 var sizeGuide = GetString("Ecom:Product:Field.SizeGuide"); 6112 6113 if (!String.IsNullOrEmpty(sizeGuide)) 6114 { 6115 Block sizeGuideTab = new Block() 6116 { 6117 Name = Translate("Størrelses guide"), 6118 Id = "SizeGuideTab", 6119 SortId = 35, 6120 Template = RenderSizeGuideTab(), 6121 Design = new Design 6122 { 6123 Size = "12", 6124 RenderType = RenderType.Column, 6125 HidePadding = true 6126 } 6127 }; 6128 customProductBlocks.Add("Tabs", sizeGuideTab); 6129 } 6130 } 6131 6132 @helper RenderSizeGuideTab() 6133 { 6134 var sizeGuide = GetString("Ecom:Product:Field.SizeGuide"); 6135 6136 <span>@sizeGuide</span> 6137 } 6138 6139 @helper RenderMainInfoHeaderCustom() 6140 { 6141 bool renderVariantsAsProducts = GetInteger("Ecom:Product.VariantCount") > 1 && Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("RenderVariantsAsProductList"); 6142 if (Pageview.AreaSettings.GetItem("ProductPage").GetList("VariantsMatrixLayout") != null && GetInteger("Ecom:Product.VariantCount") > 1) 6143 { 6144 renderVariantsAsProducts = Pageview.AreaSettings.GetItem("ProductPage").GetList("VariantsMatrixLayout").SelectedValue != "hide" && Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("EnableVariantMatrix") ? true : renderVariantsAsProducts; 6145 } 6146 6147 string pageId = GetGlobalValue("Global:Page.ID").ToString(); 6148 string currentPrice = GetString("Ecom:Product.Discount.Price.PriceFormatted") == GetString("Ecom:Product.Price.PriceFormatted") ? GetString("Ecom:Product.Price.PriceFormatted") : GetString("Ecom:Product.Discount.Price.PriceFormatted"); 6149 bool hideFavorites = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideFavoriteButton"); 6150 bool hideProductNumber = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideProductNumber"); 6151 6152 bool useFontAwesomePro = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetBoolean("UseFontAwesomePro"); 6153 var selectedFavoriteIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("FavoriteIcon") != null ? Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("FavoriteIcon").SelectedValue : "star"; 6154 string favoriteIcon = "fas fa-" + selectedFavoriteIcon; 6155 string favoriteOutlineIcon = "fal fa-" + selectedFavoriteIcon; 6156 6157 <div> 6158 <div class="u-pull--left product__title dw-mod"> 6159 <h1 class="u-no-margin">@GetString("Ecom:Product.Name") </h1> 6160 <h2>@GetString("Ecom:Product.SelectedVariantComboName")</h2> 6161 6162 @if (!hideProductNumber) 6163 { 6164 <div class="item-number dw-mod">@Translate("Varenummer: ") @GetString("Ecom:Product.ID")</div> 6165 } 6166 </div> 6167 <div class="u-pull--right"> 6168 @if (!hideFavorites && Dynamicweb.Core.Converter.ToBoolean(GetGlobalValue("Global:Extranet.UserName")) && !renderVariantsAsProducts) 6169 { 6170 string favoriteId = "Favorite" + GetString("Ecom:Product.ID"); 6171 <div id="@favoriteId" class="favorites favorites--md u-pull--right js-favorite-btn dw-mod"> 6172 <div> 6173 @{ 6174 string favorite = GetBoolean("Ecom:Product.IsProductInFavoriteList") ? favoriteIcon : favoriteOutlineIcon; 6175 string AddToWishlist = "fbq('track', 'AddToWishlist', {" + 6176 "content_name: '" + GetString("Ecom:Product.Name") + "'," + 6177 "content_ids: ['" + GetString("Ecom:Product.Number") + "']," + 6178 "value: " + GetDouble("Ecom:Product.Price.Price") + "," + 6179 "currency: '" + GetString("Ecom:Product.Price.Currency.Code") + "'" + 6180 "});"; 6181 } 6182 <label for="FavoriteTrigger"><i class="@favorite fa-1_5x"></i></label> 6183 </div> 6184 <input type="checkbox" id="FavoriteTrigger" class="dropdown-trigger" /> 6185 6186 <div class="dropdown"> 6187 <div class="dropdown__content dropdown__content--show-left dropdown__content--padding u-w220px dw-mod"> 6188 <ul class="list list--clean dw-mod"> 6189 @if (GetLoop("CustomerCenter.ListTypes").Count > 0) 6190 { 6191 foreach (LoopItem listType in GetLoop("CustomerCenter.ListTypes")) 6192 { 6193 foreach (LoopItem list in listType.GetLoop("CustomerCenter.ProductLists")) 6194 { 6195 string favLinkType = list.GetString("Ecom:Product.List.IsProductInThisList") == "True" ? list.GetString("Ecom:Product.RemoveFromThisList") : list.GetString("Ecom:Product.AddToThisListAction"); 6196 string isInListIcon = list.GetString("Ecom:Product.List.IsProductInThisList") == "True" ? favoriteIcon : favoriteOutlineIcon; 6197 <li> 6198 <a href="@favLinkType" class="list__link u-no-underline dw-mod" onclick="@(list.GetString("Ecom:Product.List.IsProductInThisList") != "True" && useFacebookPixel ? AddToWishlist : "")"><i class="@isInListIcon u-margin-right--lg"></i> @list.GetValue("Ecom:CustomerCenter.List.Name")</a> 6199 </li> 6200 } 6201 } 6202 } 6203 else 6204 { 6205 string favLinkType = GetString("Ecom:Product.AddToFavorites") + "&CCListType=0&CCCreateNewList=" + Translate("My favorites"); 6206 string isInListIcon = favoriteOutlineIcon; 6207 <li> 6208 <a href="@favLinkType" class="list__link u-no-underline dw-mod" onclick="@(useFacebookPixel ? AddToWishlist : "")"><i class="@isInListIcon u-margin-right--lg"></i> @Translate("My favorites")</a> 6209 </li> 6210 } 6211 </ul> 6212 </div> 6213 <label class="dropdown-trigger-off" for="FavoriteTrigger"></label> 6214 </div> 6215 </div> 6216 } 6217 </div> 6218 </div> 6219 } 6220 6221 @helper RenderMainInfoVariantsCustom() 6222 { 6223 string pageId = GetGlobalValue("Global:Page.ID").ToString(); 6224 string productId = GetString("Ecom:Product.ID"); 6225 string variantSelection = !String.IsNullOrEmpty(HttpContext.Current.Request.QueryString.Get("variantId")) ? HttpContext.Current.Request.QueryString.Get("variantId").Replace(".", ",") : ""; 6226 string hideHelpText = ""; 6227 string variantsLayout = Pageview.AreaSettings.GetItem("Ecommerce").GetString("VariantsLayout") != null ? Pageview.AreaSettings.GetItem("Ecommerce").GetList("VariantsLayout").SelectedValue : "buttons"; 6228 6229 foreach (LoopItem variantgroup in GetLoop("VariantGroups")) 6230 { 6231 foreach (LoopItem variantoption in variantgroup.GetLoop("VariantAvailableOptions")) 6232 { 6233 if (variantoption.GetBoolean("Ecom:VariantOption.Selected")) 6234 { 6235 hideHelpText = "u-hidden"; 6236 } 6237 } 6238 } 6239 6240 if (GetLoop("VariantGroups").Count > 0) 6241 { 6242 var variantCombinationsObject = new List<Array>(); 6243 foreach (LoopItem variantcomb in GetLoop("VariantCombinations")) 6244 { 6245 string[] combinations = variantcomb.GetString("Ecom:VariantCombination.VariantID").Split('.'); 6246 variantCombinationsObject.Add(combinations); 6247 } 6248 6249 string combinationsJson = Newtonsoft.Json.JsonConvert.SerializeObject(variantCombinationsObject).Replace("\"", "\'"); 6250 6251 var variantGroupsObject = new List<List<String>>(); 6252 foreach (LoopItem variantGroup in GetLoop("VariantGroups")) 6253 { 6254 var variantsObject = new List<String>(); 6255 foreach (LoopItem variantOption in variantGroup.GetLoop("VariantAvailableOptions")) 6256 { 6257 variantsObject.Add(variantOption.GetString("Ecom:VariantOption.ID")); 6258 } 6259 variantGroupsObject.Add(variantsObject); 6260 } 6261 6262 string variantsJson = Newtonsoft.Json.JsonConvert.SerializeObject(variantGroupsObject).Replace("\"", "\'"); 6263 string productGroupId = HttpContext.Current.Request["GroupId"]; 6264 6265 var selectedVariantArray = HttpContext.Current.Request.QueryString.Get("variantId").Split('.'); 6266 var selectedVariantColorId = selectedVariantArray != null && selectedVariantArray.Length > 0 ? selectedVariantArray[0] : string.Empty; 6267 6268 var sizeGroup = GetLoop("VariantGroups").Where(x => x.GetString("Ecom:VariantGroup.ID") == "STR").FirstOrDefault(); 6269 var sizeGroupVariantCount = sizeGroup != null ? sizeGroup.GetLoop("VariantAvailableOptions").Count : 0; 6270 6271 <div> 6272 <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" data-group-id="@productGroupId"> 6273 <input type="hidden" id="selectedVariantColorId" value="@selectedVariantColorId" /> 6274 <input type="hidden" id="colorVariantsActivated" value="false" /> 6275 @foreach (LoopItem variantGroup in GetLoop("VariantGroups")) 6276 { 6277 string groupId = variantGroup.GetString("Ecom:VariantGroup.ID"); 6278 6279 <div> 6280 6281 <div class="product__variant-group-name u-bold dw-mod">@variantGroup.GetString("Ecom:VariantGroup.Name").Replace("FRG", "Farge").Replace("STR", "Størrelse")</div> 6282 <div class="u-margin-top"> 6283 @if (variantsLayout == "buttons") 6284 { 6285 foreach (LoopItem variantOption in variantGroup.GetLoop("VariantAvailableOptions")) 6286 { 6287 string selected = variantOption.GetBoolean("Ecom:VariantOption.Selected") ? "checked" : ""; 6288 string disabled = variantOption.GetBoolean("Ecom:VariantOption.Disabled") ? "disabled" : ""; 6289 string color = !String.IsNullOrEmpty(variantOption.GetString("Ecom:VariantOption.Colorcode")) ? variantOption.GetString("Ecom:VariantOption.Colorcode") : null; 6290 color = color == null && !String.IsNullOrEmpty(variantOption.GetString("Ecom:VariantOption.Color")) ? variantOption.GetString("Ecom:VariantOption.Color") : color; 6291 var count = variantGroup.GetLoop("VariantAvailableOptions").Count(); 6292 var test = groupId == "STR" && count > 1 ? "true" : "false"; 6293 6294 if (@sizeGroupVariantCount > 1) 6295 { 6296 if (!String.IsNullOrEmpty(color)) 6297 { 6298 <button type="button" data-variant-id="" data-variant-group="@groupId" onclick="MatchVariants.SelectThis(event)" class="btn btn--colorbox u-margin-right @selected js-variant-option" data-check="@selected" style="background-color: @color"></button> 6299 } 6300 else 6301 { 6302 6303 if (groupId == "FRG") { 6304 <button type="button" test="@count" data-variant-id="@variantOption.GetString("Ecom:VariantOption.ID")" data-variant-group="@groupId" onclick="changeColorImage(event, '@GetString("Ecom:Product.ID")', '@variantOption.GetString("Ecom:VariantOption.ID")');" class="btn btn--tag @selected js-variant-option js-variant-option-frg" data-check="@selected">@variantOption.GetString("Ecom:VariantOption.ID").Replace("FRG", "").Replace("STR","")</button> 6305 } else { 6306 <button type="button" test="@count" data-variant-id="@variantOption.GetString("Ecom:VariantOption.ID")" data-variant-group="@groupId" onclick="MatchVariants.SelectThis(event);" class="btn btn--tag @selected js-variant-option js-variant-option-str" data-check="@selected">@variantOption.GetString("Ecom:VariantOption.ID").Replace("FRG", "").Replace("STR","")</button> 6307 } 6308 6309 6310 } 6311 } 6312 else 6313 { 6314 if (!String.IsNullOrEmpty(color)) 6315 { 6316 <button type="button" test="@test" data-variant-id="@variantOption.GetString("Ecom:VariantOption.ID")" data-variant-group="@groupId" onclick="MatchVariants.SelectThis(event)" class="btn btn--colorbox u-margin-right @selected js-variant-option" data-check="@selected" disabled="@disabled" style="background-color: @color"></button> 6317 } 6318 else 6319 { 6320 <button type="button" test="@test" 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" disabled="@disabled">@variantOption.GetString("Ecom:VariantOption.ID").Replace("FRG", "").Replace("STR","")</button> 6321 } 6322 } 6323 } 6324 } 6325 else 6326 { 6327 <select id="VariantSelector_@groupId" class="u-full-width dw-mod" name="VariantSelector_@groupId" onchange="MatchVariants.SelectOnChange(event)" > 6328 <option>@Translate("Choose")</option> 6329 @foreach (LoopItem variantOption in variantGroup.GetLoop("VariantAvailableOptions")) 6330 { 6331 string check = variantOption.GetBoolean("Ecom:VariantOption.Selected") ? "checked" : ""; 6332 string selected = variantOption.GetBoolean("Ecom:VariantOption.Selected") ? "selected" : ""; 6333 string color = !String.IsNullOrEmpty(variantOption.GetString("Ecom:VariantOption.Colorcode")) ? variantOption.GetString("Ecom:VariantOption.Colorcode") : null; 6334 color = color == null && !String.IsNullOrEmpty(variantOption.GetString("Ecom:VariantOption.Color")) ? variantOption.GetString("Ecom:VariantOption.Color") : color; 6335 var result = string.Empty; 6336 var colorCode = variantOption.GetString("Ecom:VariantOption.ID"); 6337 string toRemove = "FRG"; 6338 int i = colorCode.IndexOf(toRemove); 6339 if (i >= 0) 6340 { 6341 result = colorCode.Remove(i, toRemove.Length); 6342 } 6343 6344 <option class="js-variant-option @selected" id="@(groupId)_@variantOption.GetString("Ecom:VariantOption.ID")" value="@(groupId)_@variantOption.GetString("Ecom:VariantOption.ID")" data-variant-id="@variantOption.GetString("Ecom:VariantOption.ID")" data-variant-group="@groupId" @selected data-check="@check">@variantOption.GetString("Ecom:VariantOption.ID").Replace("FRG", "").Replace("STR","")</option> 6345 } 6346 </select> 6347 } 6348 </div> 6349 </div> 6350 } 6351 </div> 6352 <small class="js-help-text help-text @hideHelpText">@Translate("Please select variant!")</small> 6353 </div> 6354 <script> 6355 function changeColorImage(e, productId, selectedVariantOptionId) { 6356 let image = document.getElementById(`Image_${productId}`); 6357 let selectedVariantColorId = document.getElementById('selectedVariantColorId'); 6358 let buyButton = document.getElementById('buyButton'); 6359 6360 image.src = image.src.replace(selectedVariantColorId.value, selectedVariantOptionId); 6361 selectedVariantColorId.value = selectedVariantOptionId; 6362 6363 if (buyButton) { 6364 buyButton.classList.add('disabled'); 6365 } 6366 6367 resetSizeChoices(e); 6368 } 6369 6370 function resetSizeChoices(e) { 6371 var clickedOption = e.currentTarget != null ? e.currentTarget : e; 6372 var clickedOptionId = clickedOption.getAttribute("data-variant-id"); 6373 var currentVariantsBlock = clickedOption.closest(".js-variants"); 6374 var selectionCompleteCommand = currentVariantsBlock.getAttribute("data-selection-complete"); 6375 var selectionsList = currentVariantsBlock.getAttribute("data-variant-selections") ? currentVariantsBlock.getAttribute("data-variant-selections").split(",") : []; 6376 var allOptions = currentVariantsBlock.querySelectorAll(".js-variant-option"); 6377 var allOptionsTotal = allOptions.length; 6378 6379 selectionsList = []; 6380 selectionsList.push(clickedOptionId); 6381 6382 currentVariantsBlock.setAttribute("data-variant-selections", selectionsList); 6383 MatchVariants.Update(clickedOption.closest(".js-variants"), selectionCompleteCommand); 6384 activateColorVariants(); 6385 } 6386 6387 function activateColorVariants() { 6388 let colorVariantsActivated = document.getElementById('colorVariantsActivated'); 6389 6390 document.querySelectorAll('.js-variant-option-frg').forEach(function(button) { 6391 button.disabled = false; 6392 button.classList.remove('disabled'); 6393 }); 6394 6395 colorVariantsActivated.value = 'true'; 6396 } 6397 6398 function activateColorVariantsCheck() { 6399 let colorVariantsActivated = document.getElementById('colorVariantsActivated'); 6400 let disabledButtons = 0; 6401 6402 document.querySelectorAll('.js-variant-option-frg').forEach(function(button) { 6403 if (button.disabled == true) 6404 disabledButtons++; 6405 }); 6406 6407 if (colorVariantsActivated.value == 'false' && disabledButtons > 0) { 6408 activateColorVariants(); 6409 return true; 6410 } else { 6411 return false; 6412 } 6413 } 6414 6415 document.addEventListener("contentLoaded", function (event) { 6416 activateColorVariantsCheck(); 6417 }); 6418 </script> 6419 } 6420 } 6421 6422 @helper RenderMainInfoBuyCustom() 6423 { 6424 string pageId = GetGlobalValue("Global:Page.ID").ToString(); 6425 string variantId = HttpContext.Current.Request.QueryString.Get("variantId"); 6426 string productId = GetString("Ecom:Product.ID"); 6427 string feedId = pageId + "&ProductID=" + productId + "&VariantID=" + variantId + "&Feed=True&redirect=false"; 6428 <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> 6429 <input type="hidden" value="@GetString("Ecom:Product.VariantID.Extented")" name="Variant" id="Variant_@GetString("Ecom:Product.ID")" /> 6430 @RenderMainInfoBuyScriptsCustom() 6431 } 6432 6433 @helper RenderMainInfoBuyScriptsCustom() 6434 { 6435 bool showPrice = !Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HidePrice"); 6436 bool showCartButton = !Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideAddToCartButton"); 6437 bool pointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly"); 6438 string variantId = HttpContext.Current.Request.QueryString.Get("variantId") ?? ""; 6439 string feedId = GetGlobalValue("Global:Page.ID").ToString() + "&ProductID=" + GetString("Ecom:Product.ID") + "&VariantID=" + variantId + "&Feed=True&redirect=false"; 6440 string cartIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon") != null ? Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon").SelectedValue : "fas fa-shopping-cart"; 6441 bool showVATPrice = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("ShowBothPricesWithWithoutVAT"); 6442 bool isPricesWithVATEnabled = Converter.ToBoolean(Pageview.Area.EcomPricesWithVat); 6443 6444 var customerId = Dynamicweb.Security.UserManagement.User.GetCurrentExtranetUserId(); 6445 var shopId = Pageview.Area.EcomShopId; 6446 var orderType = Dynamicweb.Ecommerce.Orders.OrderType.Order; 6447 var cartsList = (List<Dynamicweb.Ecommerce.Orders.Order>)Dynamicweb.Ecommerce.Services.Orders.GetCustomerOrdersByType(customerId, shopId, orderType, 0, false, "", DateTime.MinValue, false, true); 6448 6449 6450 @* Handlebars templates *@ 6451 <script id="PricesAndActionsTemplate" type="text/x-template"> 6452 {{#.}} 6453 @if (Dynamicweb.Rapido.Services.User.IsPricesAllowed()) 6454 { 6455 <div class="product__price-wrap dw-mod"> 6456 @RenderPriceInfoCustom() 6457 </div> 6458 } 6459 6460 @if (showCartButton && Dynamicweb.Rapido.Services.User.IsBuyingAllowed()) 6461 { 6462 var addToCartBtn = new AddToCart 6463 { 6464 WrapperCssClass = "product__price-actions-flex-wrap buttons-collection--right dw-mod", 6465 AddButton = new AddToCartButton 6466 { 6467 Id = "buyButton", 6468 ProductId = "{{productId}}", 6469 VariantId = "{{variantid}}", 6470 UnitId = "{{unitId}}", 6471 ProductInfo = "{{productInfo}}", 6472 BuyForPoints = pointShopOnly, 6473 OnClick = "{{facebookPixelAction}}", 6474 ExtraAttributes = new Dictionary<string, string> 6475 { 6476 { "{{disabledBuyButton}}", "" } 6477 }, 6478 CssClass = "product__price-buy-button" 6479 }, 6480 UnitSelector = new UnitSelector 6481 { 6482 OptionsContent = "{{#unitOptions}}{{>UnitOption}}{{/unitOptions}}", 6483 Id = "UnitOptions_{{id}}", 6484 SelectedOption = "{{unitName}}", 6485 CssClass = "{{#if hasOnlyOneUnit}}unit-selector--readonly{{/if}} {{hasUnits}}" 6486 } 6487 }; 6488 6489 if (!pointShopOnly) 6490 { 6491 addToCartBtn.QuantitySelector = new QuantitySelector 6492 { 6493 Id = "Quantity_{{id}}" 6494 }; 6495 } 6496 6497 <div class="product__price-actions-wrap dw-mod"> 6498 @Render(addToCartBtn) 6499 6500 @if (Dynamicweb.Core.Converter.ToBoolean(GetGlobalValue("Global:Extranet.UserName")) && User.IsBuyingAllowed() && cartsList.Count > 0 && GetPageIdByNavigationTag("OrderDraft") != 0) 6501 { 6502 var addToDraftCart = new Button 6503 { 6504 Id = "AddToDraftCart", 6505 Title = Translate("Add to draft"), 6506 ButtonLayout = ButtonLayout.Secondary, 6507 OnClick = "document.getElementById('OrderDraftSelectModalTrigger').checked = true", 6508 CssClass = "u-w220px u-margin-top" 6509 }; 6510 6511 @Render(addToDraftCart) 6512 } 6513 6514 @if (Pageview.User != null && !pointShopOnly && Dynamicweb.Security.Licensing.LicenseManager.LicenseHasFeature("LoyaltyPoints")) 6515 { 6516 <text> 6517 {{#if canBePurchasedWithPoints}} 6518 <form method="post" role="form" class="u-no-margin u-margin-top"> 6519 <input type="hidden" name="ProductID" value="{{id}}" /> 6520 <button type="submit" class="btn btn--loyalty-points product__price-points-buy-button 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> 6521 </form> 6522 {{/if}} 6523 </text> 6524 } 6525 </div> 6526 } 6527 else 6528 { 6529 <button type="button" id="CartButton_{{id}}" class="u-hidden"></button> 6530 } 6531 @RenderStockAndShippingCustom() 6532 {{/.}} 6533 </script> 6534 6535 <script id="UnitOption" type="text/x-template"> 6536 <div class="dropdown__item dw-mod" onclick="HandlebarsBolt.UpdateContent('PriceAndActions', '{{link}}&feed=true&UnitID={{value}}')">{{name}}</div> 6537 </script> 6538 6539 <script> 6540 document.addEventListener("DOMContentLoaded", function () { 6541 if (document.getElementById("PriceAndActions")) { 6542 document.getElementById("PriceAndActions").addEventListener("contentLoaded", function (event) { 6543 if (document.querySelector(".js-variants") != null) { 6544 MatchVariants.Update(document.querySelector(".js-variants"), "DoNothing"); 6545 } 6546 }); 6547 } 6548 }); 6549 </script> 6550 6551 <script> 6552 document.addEventListener('contentLoaded', function (event) { 6553 console.log('contentLoaded', event); 6554 6555 }); 6556 6557 //test.classList.contains(testClass); 6558 </script> 6559 } 6560 6561 @helper RenderPriceInfoCustom() 6562 { 6563 bool pointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly"); 6564 bool showPrice = !Pageview.AreaSettings.GetItem("ProductList").GetBoolean("HidePrice"); 6565 bool showCartButton = !Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideAddToCartButton"); 6566 bool showVATPrice = Pageview.AreaSettings.GetItem("ProductList").GetBoolean("ShowBothPricesWithWithoutVAT"); 6567 bool isPricesWithVATEnabled = Converter.ToBoolean(Pageview.Area.EcomPricesWithVat); 6568 6569 var customSettings = Pageview.AreaSettings.GetItem("Custom").GetItem("CustomSettings"); 6570 var isB2C = customSettings.GetBoolean("B2C"); 6571 6572 if (showPrice && Dynamicweb.Rapido.Services.User.IsPricesAllowed()) 6573 { 6574 if (pointShopOnly) 6575 { 6576 <text> 6577 {{#if havePointPrice}} 6578 <div class="price price--product-page dw-mod">{{points}} @Translate("points")</div> 6579 @if (showCartButton) 6580 { 6581 <text> 6582 {{#unless canBePurchasedWithPoints}} 6583 <small class="help-text u-no-margin">@Translate("Not enough points to buy this")</small> 6584 {{/unless}} 6585 </text> 6586 } 6587 {{else}} 6588 @Translate("Not available") 6589 {{/if}} 6590 </text> 6591 6592 } 6593 else 6594 { 6595 if (isB2C == false) { 6596 <div class="price price--product-page dw-mod">{{priceWithoutVAT}}</div> 6597 <div class="before-price {{onSale}} dw-mod">{{discount}}</div> 6598 } else { 6599 <text> 6600 {{#ifCond salesPriceWithoutFormat "==" priceWithoutFormat}} 6601 <div class="price price--product-page dw-mod">{{priceWithoutVAT}}</div> 6602 <div class="before-price {{onSale}} dw-mod">{{discount}}</div> 6603 {{else}} 6604 <div class="before-price dw-mod">{{unitListPrice}}</div> 6605 <div class="price price--product-page dw-mod" style="color:red;">{{priceWithoutVAT}} <span style="color: red; margin-left: 8px;">{{percentage}}%</span></div> 6606 {{/ifCond}} 6607 </text> 6608 } 6609 6610 if (showVATPrice && isB2C == false) 6611 { 6612 <div class="vat-price vat-price--product-page u-margin-top dw-mod"> 6613 <span>@Translate("veil. Pris")</span><span> ({{unitListPrice}})</span> 6614 </div> 6615 } 6616 <text> 6617 {{#if priceRRP}} 6618 <div><small>@Translate("RRP") {{priceRRP}}</small></div> 6619 {{/if}} 6620 </text> 6621 } 6622 } 6623 } 6624 6625 @helper RenderStockAndShippingCustom() 6626 { 6627 bool hideStockState = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideStockState"); 6628 bool hideDelivery = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideShipping"); 6629 var userLoggedIn = Pageview.User != null; 6630 6631 if (userLoggedIn) 6632 { 6633 <div class="product__stock-delivery dw-mod"> 6634 {{#ifCond stockNumber "==" "0"}} 6635 @if (!hideStockState) 6636 { 6637 <span class="stock-icon stock-icon--not u-no-margin dw-mod" title="{{stockText}}"></span> 6638 } 6639 @if (!hideDelivery) 6640 { 6641 <text>@Translate("Ikke på lager")</text> 6642 } 6643 {{else ifCond stockNumber ">" "100"}} 6644 @if (!hideStockState) 6645 { 6646 <span class="stock-icon stock-icon--in u-no-margin dw-mod" title="{{stockText}}"></span> 6647 <span class="u-margin-right--lg"> @Translate("Lagerbeholdning:") </span> 6648 } 6649 @if (!hideDelivery) 6650 { 6651 6652 <text>@Translate("Mer enn 100 på lager")</text> 6653 6654 } 6655 {{else}} 6656 @if (!hideStockState) 6657 { 6658 <span class="stock-icon stock-icon--in u-no-margin dw-mod" title="{{stockText}}"></span> 6659 <span class="u-margin-right--lg"> @Translate("Lagerbeholdning:") </span> 6660 } 6661 @if (!hideDelivery) 6662 { 6663 6664 <text>{{stockNumber}} @Translate("stk")</text> 6665 6666 } 6667 {{/ifCond}} 6668 </div> 6669 } 6670 } 6671 6672 <div class="product__info dw-mod u-margin-bottom--lg js-product"> 6673 <div class="grid grid--align-content-start"> 6674 @* The @RenderBlockList base helper is included in Components/GridBuilder.cshtml *@ 6675 @RenderBlockList(productsPage.BlocksRoot.BlocksList) 6676 </div> 6677 </div> 6678 6679 @helper RenderProductTop() 6680 6681 { 6682 6683 List<Block> subBlocks = productsPage.GetBlockListById("Top").OrderBy(item => item.SortId).ToList(); 6684 6685 <div class="product__top paragraph-container paragraph-container--full-width dw-mod"> 6686 <div class="center-container dw-mod"> 6687 <div class="grid"> 6688 @RenderBlockList(subBlocks) 6689 </div> 6690 </div> 6691 </div> 6692 } 6693 6694 @helper RenderProductMiniTabs() 6695 { 6696 List<Block> subBlocks = productsPage.GetBlockListById("MiniTabs").OrderBy(item => item.SortId).ToList(); 6697 6698 if (subBlocks.Count > 0) 6699 { 6700 <div class="grid__col-12 product__info tabs u-no-padding u-margin-bottom--lg dw-mod"> 6701 @{ 6702 bool firstTab = true; 6703 foreach (Block item in subBlocks) 6704 { 6705 string isChecked = firstTab ? "checked" : ""; 6706 firstTab = false; 6707 6708 <input type="radio" class="tabs__trigger" name="productMiniTabs" id="@item.Id" onchange="bLazy.revalidate()" @isChecked /> 6709 } 6710 } 6711 6712 <div class="tabs__list dw-mod"> 6713 @foreach (Block item in subBlocks) 6714 { 6715 <label for="@item.Id" class="tabs__label dw-mod">@item.Name</label> 6716 } 6717 </div> 6718 6719 <div class="tabs__blocks dw-mod"> 6720 @foreach (Block item in subBlocks) 6721 { 6722 string hidePadding = item.Design.HidePadding ? "u-no-padding" : ""; 6723 6724 if (item.Design.RenderType != RenderType.Hide) 6725 { 6726 <div class="tabs__block u-border dw-mod" id="Block__@item.Id"> 6727 <block class="product__block paragraph-container product__block--bordered dw-mod"> 6728 <div class="center-container dw-mod"> 6729 @RenderBlock(item) 6730 </div> 6731 </block> 6732 </div> 6733 } 6734 } 6735 </div> 6736 </div> 6737 } 6738 } 6739 6740 @helper RenderProductTabs() 6741 { 6742 List<Block> subBlocks = productsPage.GetBlockListById("Tabs").OrderBy(item => item.SortId).ToList(); 6743 6744 if (Pageview.Device.ToString() != "Mobile") { 6745 <div class="grid__col-12 product__info product__info--tabs tabs dw-mod"> 6746 @{ 6747 bool firstTab = true; 6748 foreach (Block item in subBlocks) 6749 { 6750 string isChecked = firstTab ? "checked" : ""; 6751 firstTab = false; 6752 6753 <input type="radio" class="tabs__trigger" name="productTabs" id="@item.Id" onchange="bLazy.revalidate()" @isChecked /> 6754 } 6755 } 6756 6757 <div class="tabs__list dw-mod"> 6758 @foreach (Block item in subBlocks) 6759 { 6760 if (item.Design.RenderType != RenderType.Hide) 6761 { 6762 <label for="@item.Id" class="tabs__label dw-mod">@item.Name</label> 6763 } 6764 } 6765 </div> 6766 6767 <div class="tabs__blocks dw-mod"> 6768 @foreach (Block item in subBlocks) 6769 { 6770 if (item.Design.RenderType != RenderType.Hide) 6771 { 6772 <div class="tabs__block dw-mod" id="Block__@item.Id"> 6773 <section class="product__section paragraph-container paragraph-container--full-width product__section--bordered dw-mod"> 6774 <div class="center-container u-padding--lg dw-mod"> 6775 @RenderBlock(item) 6776 </div> 6777 </section> 6778 </div> 6779 } 6780 } 6781 </div> 6782 </div> 6783 } else { 6784 foreach (Block item in subBlocks) 6785 { 6786 if (item.Design.RenderType != RenderType.Hide) 6787 { 6788 <div class="center-container dw-mod"> 6789 <div class="padding-position-left padding-size-sm"> 6790 @Render(new Heading { Title = item.Name, Level = 2 }) 6791 </div> 6792 6793 @RenderBlock(item) 6794 </div> 6795 } 6796 } 6797 } 6798 }