Error executing template "Designs/Rapido/eCom/Product/ProductCustom.cshtml"
System.NullReferenceException: Object reference not set to an instance of an object.
   at CompiledRazorTemplates.Dynamic.RazorEngine_f641ddaacbac4d538d1dc5fff554fe7f.<>c__DisplayClass95_0.<RenderProductSection>b__0(TextWriter __razor_helper_writer) in D:\web\denform.dk\Files\Templates\Designs\Rapido\eCom\Product\ProductCustom.cshtml:line 5088
   at RazorEngine.Templating.TemplateWriter.ToString()
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at CompiledRazorTemplates.Dynamic.RazorEngine_f641ddaacbac4d538d1dc5fff554fe7f.<>c__DisplayClass4_0.<RenderBlock>b__0(TextWriter __razor_helper_writer) in D:\web\denform.dk\Files\Templates\Designs\Rapido\eCom\Product\ProductCustom.cshtml:line 209
   at CompiledRazorTemplates.Dynamic.RazorEngine_f641ddaacbac4d538d1dc5fff554fe7f.<>c__DisplayClass3_0.<RenderBlockList>b__0(TextWriter __razor_helper_writer) in D:\web\denform.dk\Files\Templates\Designs\Rapido\eCom\Product\ProductCustom.cshtml:line 147
   at CompiledRazorTemplates.Dynamic.RazorEngine_f641ddaacbac4d538d1dc5fff554fe7f.<>c__DisplayClass4_0.<RenderBlock>b__0(TextWriter __razor_helper_writer) in D:\web\denform.dk\Files\Templates\Designs\Rapido\eCom\Product\ProductCustom.cshtml:line 247
   at CompiledRazorTemplates.Dynamic.RazorEngine_f641ddaacbac4d538d1dc5fff554fe7f.<>c__DisplayClass3_0.<RenderBlockList>b__0(TextWriter __razor_helper_writer) in D:\web\denform.dk\Files\Templates\Designs\Rapido\eCom\Product\ProductCustom.cshtml:line 119
   at CompiledRazorTemplates.Dynamic.RazorEngine_f641ddaacbac4d538d1dc5fff554fe7f.Execute() in D:\web\denform.dk\Files\Templates\Designs\Rapido\eCom\Product\ProductCustom.cshtml:line 6844
   at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader)
   at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer)
   at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
   at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template)
   at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template)
   at Dynamicweb.Rendering.Template.RenderRazorTemplate()

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