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