Error executing template "Designs/Rapido/eCom/Product/Product.cshtml"
System.NullReferenceException: Object reference not set to an instance of an object.
   at Elkotek.Modules.PDfDocuments.DocumentAssets.GetDocumentsByProductId(String ProductId) in D:\a\1\s\Elkotek\Modules\PDfDocuments\DocumentAssets.cs:line 21
   at CompiledRazorTemplates.Dynamic.RazorEngine_368eabdcaf574881aa332d10700ec6fe.Execute()
   at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader)
   at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer)
   at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
   at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template)
   at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template)
   at Dynamicweb.Rendering.Template.RenderRazorTemplate()

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