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