100% tilfredshedsgaranti
DK's største udvalg af udespa & sauna
Fri fragt & levering på ordrer over 1000kr
Kundeservice alle ugens dage
100% tilfredshedsgaranti
DK's største udvalg af udespa & sauna
Fri fragt & levering på ordrer over 1000kr
Kundeservice alle ugens dage
100% tilfredshedsgaranti
DK's største udvalg af udespa & sauna
Error executing template "Designs/Rapido/eCom/Product/ProductCustom.cshtml"
System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at CompiledRazorTemplates.Dynamic.RazorEngine_b49522825e434bfca486d0932ef5ff96.<>c__DisplayClass97_0.<RenderProductSection>b__0(TextWriter __razor_helper_writer) in D:\web\denform.dk\Files\Templates\Designs\Rapido\eCom\Product\ProductCustom.cshtml:line 5210
   at RazorEngine.Templating.TemplateWriter.ToString()
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at CompiledRazorTemplates.Dynamic.RazorEngine_b49522825e434bfca486d0932ef5ff96.<>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_b49522825e434bfca486d0932ef5ff96.<>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_b49522825e434bfca486d0932ef5ff96.<>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_b49522825e434bfca486d0932ef5ff96.<>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_b49522825e434bfca486d0932ef5ff96.Execute() in D:\web\denform.dk\Files\Templates\Designs\Rapido\eCom\Product\ProductCustom.cshtml:line 6978
   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 2808 bool GetRecursiveGroupValue(string fieldName) 2809 { 2810 //only enable datepicker for DK 2811 if (Pageview.Area.ID != 21) 2812 { 2813 return false; 2814 } 2815 2816 string productId = GetString("Ecom:Product.ID"); 2817 string variantId = GetString("Ecom:Product.VariantID"); 2818 var product = new Dynamicweb.Ecommerce.Products.ProductService().GetProductById(productId, variantId, Pageview.Area.EcomLanguageId); 2819 2820 if (product == null) 2821 { 2822 return false; 2823 } 2824 else 2825 { 2826 var productGroups = product.Groups; 2827 2828 foreach (var group in productGroups) 2829 { 2830 //check if the product group has the field set to true 2831 if ((bool)group.ProductGroupFieldValues.GetProductGroupFieldValue(fieldName).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(fieldName).Value == true) 2841 { 2842 return true; 2843 } 2844 } 2845 } 2846 } 2847 2848 return false; 2849 } 2850 2851 2852 bool isEcomArea() 2853 { 2854 return Pageview.Area.Item["NotEcomArea"] != null && Pageview.Area.Item["NotEcomArea"].ToString().ToLower() == "true" ? false : true; 2855 } 2856 } 2857 2858 2859 //family members 2860 bool mainInfoIsFamilyMember = false; 2861 bool mainInfoIsFamilyMaster = false; 2862 var mainInfoVariantGroups = GetLoop("VariantGroups"); 2863 var mainInfoVariantGroupCount = mainInfoVariantGroups.Count; 2864 if (mainInfoVariantGroupCount == 1) 2865 { 2866 var firstVariantGroup = Dynamicweb.Ecommerce.Services.VariantGroups.GetVariantGroup(Dynamicweb.Ecommerce.Common.Context.LanguageID, mainInfoVariantGroups[0]?.GetString("Ecom:VariantGroup.ID")); 2867 if (firstVariantGroup != null) 2868 { 2869 mainInfoIsFamilyMember = firstVariantGroup.Family; 2870 string variantId = !string.IsNullOrEmpty(GetString("Ecom:Product.VariantID")) ? GetString("Ecom:Product.VariantID") : GetString("Ecom:Product.VariantID.Extented"); 2871 mainInfoIsFamilyMaster = string.IsNullOrEmpty(variantId); 2872 } 2873 } 2874 2875 bool mainInfoRenderVariantsAsProducts = mainInfoVariantsCount > 1 && Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("RenderVariantsAsProductList"); 2876 2877 if (mainInfoIsFamilyMember) 2878 { 2879 mainInfoRenderVariantsAsProducts = mainInfoVariantsCount > 1 && Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("RenderFamilyVariantsAsProducts") && mainInfoIsFamilyMaster; 2880 } 2881 2882 if (Pageview.AreaSettings.GetItem("ProductPage").GetList("VariantsMatrixLayout") != null && mainInfoVariantsCount > 1) 2883 { 2884 mainInfoRenderVariantsAsProducts = Pageview.AreaSettings.GetItem("ProductPage").GetList("VariantsMatrixLayout").SelectedValue != "hide" && Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("EnableVariantMatrix") ? true : mainInfoRenderVariantsAsProducts; 2885 } 2886 2887 Block mainInfoHeader = new Block() 2888 { 2889 Id = "MainInfoHeader", 2890 SortId = 10, 2891 Template = RenderMainInfoHeader() 2892 }; 2893 mainInfoPage.Add("MainInformation", mainInfoHeader); 2894 2895 Block mainInfoDescription = new Block() 2896 { 2897 Id = "ShortDescription", 2898 SortId = 20, 2899 Template = RenderShortDescription() 2900 }; 2901 mainInfoPage.Add("MainInformation", mainInfoDescription); 2902 2903 if (!mainInfoRenderVariantsAsProducts && !mainInfoIsFamilyMember) 2904 { 2905 Block mainInfoVariants = new Block() 2906 { 2907 Id = "Variants", 2908 SortId = 50, 2909 Template = RenderMainInfoVariants() 2910 }; 2911 mainInfoPage.Add("MainInformation", mainInfoVariants); 2912 } 2913 2914 Block mainInfoBOM = new Block() 2915 { 2916 Id = "BOM", 2917 SortId = 60, 2918 Template = RenderMainInfoBOM() 2919 }; 2920 mainInfoPage.Add("MainInformation", mainInfoBOM); 2921 2922 if (!mainInfoRenderVariantsAsProducts) 2923 { 2924 if (!hideAddToCartButton) 2925 { 2926 Block mainInfoBuy = new Block() 2927 { 2928 Id = "Buy", 2929 SortId = 80, 2930 Template = RenderMainInfoBuy() 2931 }; 2932 mainInfoPage.Add("MainInformation", mainInfoBuy); 2933 } 2934 } 2935 2936 if (Dynamicweb.Core.Converter.ToBoolean(GetGlobalValue("Global:Extranet.UserName")) && User.IsBuyingAllowed() && GetPageIdByNavigationTag("OrderDraft") != 0) 2937 { 2938 Modal selectDraftModal = new Modal 2939 { 2940 Id = "OrderDraftSelect", 2941 Heading = new Heading { Title = Translate("Select draft cart"), Level = 2 }, 2942 BodyTemplate = RenderOrderDraftSelectModalContent(), 2943 Width = ModalWidth.Md 2944 }; 2945 selectDraftModal.AddAction(new Button { Title = Translate("Cancel"), OnClick = "document.getElementById('OrderDraftSelectModalTrigger').checked = false", ButtonLayout = ButtonLayout.Secondary }); 2946 selectDraftModal.AddAction(new Button { Title = Translate("Add"), OnClick = "addToSelectedCart()" }); 2947 2948 Block orderDraftSelect = new Block 2949 { 2950 Id = "OrderDraft", 2951 SortId = 90, 2952 Component = selectDraftModal 2953 }; 2954 mainInfoPage.Add("MainInformation", orderDraftSelect); 2955 2956 Modal notificationDraftModal = new Modal 2957 { 2958 Id = "OrderDraftNotification", 2959 Heading = new Heading { Title = Translate("Added to cart"), Level = 2 }, 2960 BodyText = Translate("The product has been added to the selected cart"), 2961 Width = ModalWidth.Md 2962 }; 2963 notificationDraftModal.AddAction(new Button { Title = Translate("View draft"), OnClick = "goToSelectedCart()", ButtonLayout = ButtonLayout.Secondary }); 2964 notificationDraftModal.AddAction(new Button { Title = Translate("Continue shopping"), OnClick = "document.getElementById('OrderDraftNotificationModalTrigger').checked = false" }); 2965 2966 Block orderDraftComplete = new Block 2967 { 2968 Id = "OrderDraftComplete", 2969 SortId = 100, 2970 Component = notificationDraftModal 2971 }; 2972 mainInfoPage.Add("MainInformation", orderDraftComplete); 2973 2974 2975 Block orderDraftScripts = new Block 2976 { 2977 Id = "OrderDraftScripts", 2978 SortId = 110, 2979 Template = RenderOrderDraftScripts() 2980 }; 2981 mainInfoPage.Add("MainInformation", orderDraftScripts); 2982 } 2983 2984 //Block googleTagManagerScripts = new Block 2985 //{ 2986 // Id = "GoogleTagManagerScripts", 2987 // SortId = 120, 2988 // Template = RenderGoogleTagManagerScripts() 2989 //}; 2990 //mainInfoPage.Add("Snippets", googleTagManagerScripts); 2991 } 2992 2993 @helper RenderMainInfoHeader() 2994 { 2995 bool renderVariantsAsProducts = GetInteger("Ecom:Product.VariantCount") > 1 && Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("RenderVariantsAsProductList"); 2996 if (Pageview.AreaSettings.GetItem("ProductPage").GetList("VariantsMatrixLayout") != null && GetInteger("Ecom:Product.VariantCount") > 1) 2997 { 2998 renderVariantsAsProducts = Pageview.AreaSettings.GetItem("ProductPage").GetList("VariantsMatrixLayout").SelectedValue != "hide" && Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("EnableVariantMatrix") ? true : renderVariantsAsProducts; 2999 } 3000 3001 string pageId = GetGlobalValue("Global:Page.ID").ToString(); 3002 string currentPrice = GetString("Ecom:Product.Discount.Price.PriceFormatted") == GetString("Ecom:Product.Price.PriceFormatted") ? GetString("Ecom:Product.Price.PriceFormatted") : GetString("Ecom:Product.Discount.Price.PriceFormatted"); 3003 bool hideFavorites = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideFavoriteButton"); 3004 bool hideProductNumber = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideProductNumber"); 3005 3006 bool useFontAwesomePro = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetBoolean("UseFontAwesomePro"); 3007 var selectedFavoriteIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("FavoriteIcon") != null ? Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("FavoriteIcon").SelectedValue : "star"; 3008 string favoriteIcon = "fas fa-" + selectedFavoriteIcon; 3009 string favoriteOutlineIcon = "fal fa-" + selectedFavoriteIcon; 3010 bool hideStockState = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideStockState"); 3011 bool hideDelivery = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideShipping"); 3012 3013 3014 <div> 3015 <div class="nc-product__top-header"> 3016 3017 @if (GetRecursiveGroupValue("Cashback")) 3018 { 3019 <a title="@Translate("CashbackHover")" onclick="document.getElementById('CashbackModalModalTrigger').checked = true" href="javascript:void(0)" class="nc-product__cashback"> 3020 <img alt="Cashback logo" src="/Files/Images/cashback.png"/> 3021 </a> 3022 } 3023 3024 <h1 class="nc-product__product-title">@GetString("Ecom:Product.Name") </h1> 3025 @if (GetBoolean("Ecom:Product.HaveDiscount")) 3026 { 3027 <div class="nc-product__price nc-product__price--discounted"> 3028 <h2 class="nc-product__valuta nc-product__price-content"> 3029 @GetString("Ecom:Product.Price.Currency.Code") 3030 </h2> 3031 <h2 class="nc-product__discount-price nc-product__price-content">@String.Format("{0:0.0,00}", GetString("Ecom:Product.Discount.Price.Price"))</h2> 3032 <h2 class="nc-product__full-price nc-product__price-content">@String.Format("{0:0.0,00}", GetString("Ecom:Product.Price.Price")) </h2> 3033 </div> 3034 } 3035 else 3036 { 3037 <div class="nc-product__price"> 3038 <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> 3039 </div> 3040 } 3041 3042 @if (User.IsStockInfoAllowed()) 3043 { 3044 Dynamicweb.Ecommerce.Products.ProductService service = new Dynamicweb.Ecommerce.Products.ProductService(); 3045 string ProductId = GetString("Ecom:Product.ID"); 3046 string VariantId = GetString("Ecom:Product.VariantID"); 3047 string defaultLanguage = Dynamicweb.Ecommerce.Common.Context.LanguageID; 3048 3049 //null checks for product and variant 3050 if (!string.IsNullOrEmpty(ProductId) && !string.IsNullOrEmpty(defaultLanguage) || !string.IsNullOrEmpty(ProductId) && !string.IsNullOrEmpty(VariantId) && !string.IsNullOrEmpty(defaultLanguage)) 3051 { 3052 var currentProduct = service.GetProductById(ProductId, VariantId, defaultLanguage); 3053 3054 if (currentProduct != null && isEcomArea()) 3055 { 3056 bool neverOutOfStock = currentProduct.NeverOutOfStock; 3057 3058 <div class="nc-product__stock-delivery dw-mod"> 3059 3060 @**If never out of stock is enabled on a product and 'hide stock state' is not enabled**@ 3061 @if (neverOutOfStock && !hideStockState) 3062 { 3063 <span class="stock-icon stock-icon--in u-no-margin dw-mod" title="@Translate("På lager")"></span> 3064 <span class="nc-stock__stock-text">@Translate("På lager")</span> 3065 } 3066 @**If hide stock state is not enabled**@ 3067 else if (!hideStockState) 3068 { 3069 // Check if HideStockState is not enabled, or if there is stock available 3070 3071 //if stocklevel > 0 3072 <div class="stock-instock-container" style="display: none"> 3073 <span class="stock-icon stock-icon--in u-no-margin dw-mod" title=""></span> 3074 <span class="nc-stock__stock-text"></span> 3075 </div> 3076 3077 // if not stocklevel > 0 3078 <div class="stock-notinstock-container" style="display: none"> 3079 <span class="stock-icon stock-icon--not u-no-margin dw-mod" title="@Translate("Ikke på lager")"></span> 3080 <span class="nc-stock__stock-text">@Translate("Ikke på lager")</span> 3081 </div> 3082 } 3083 else 3084 { 3085 <span class="u-no-margin dw-mod"></span> 3086 <span class="nc-stock__stock-text"></span> 3087 } 3088 3089 @if (!hideDelivery) 3090 { 3091 <span class="nc-product__delivery-text"> 3092 <img src="/Files/Templates/Designs/Rapido/css/icons/deliverytruck.svg" class="nc-product__delivery-icon"/> 3093 <span class="nc-product__delivery-text__content"></span> 3094 </span> 3095 } 3096 </div> 3097 } 3098 } 3099 } 3100 </div> 3101 <div class="u-pull--right"> 3102 @if (!hideFavorites && Dynamicweb.Core.Converter.ToBoolean(GetGlobalValue("Global:Extranet.UserName")) && !renderVariantsAsProducts) 3103 { 3104 string favoriteId = "Favorite" + GetString("Ecom:Product.ID"); 3105 <div id="@favoriteId" class="favorites favorites--md u-pull--right js-favorite-btn dw-mod"> 3106 <div> 3107 @{ 3108 string favorite = GetBoolean("Ecom:Product.IsProductInFavoriteList") ? favoriteIcon : favoriteOutlineIcon; 3109 string AddToWishlist = "fbq('track', 'AddToWishlist', {" + 3110 "content_name: '" + GetString("Ecom:Product.Name") + "'," + 3111 "content_ids: ['" + GetString("Ecom:Product.Number") + "']," + 3112 "value: " + GetDouble("Ecom:Product.Price.Price") + "," + 3113 "currency: '" + GetString("Ecom:Product.Price.Currency.Code") + "'" + 3114 "});"; 3115 } 3116 <label for="FavoriteTrigger"> 3117 <i class="@favorite fa-1_5x"></i> 3118 </label> 3119 </div> 3120 <input type="checkbox" id="FavoriteTrigger" class="dropdown-trigger"/> 3121 3122 <div class="dropdown"> 3123 <div class="dropdown__content dropdown__content--show-left dropdown__content--padding u-w220px dw-mod"> 3124 <ul class="list list--clean dw-mod"> 3125 @if (GetLoop("CustomerCenter.ListTypes").Count > 0) 3126 { 3127 foreach (LoopItem listType in GetLoop("CustomerCenter.ListTypes")) 3128 { 3129 foreach (LoopItem list in listType.GetLoop("CustomerCenter.ProductLists")) 3130 { 3131 string favLinkType = list.GetString("Ecom:Product.List.IsProductInThisList") == "True" ? list.GetString("Ecom:Product.RemoveFromThisList") : list.GetString("Ecom:Product.AddToThisListAction"); 3132 string isInListIcon = list.GetString("Ecom:Product.List.IsProductInThisList") == "True" ? favoriteIcon : favoriteOutlineIcon; 3133 <li> 3134 <a href="@favLinkType" class="list__link u-no-underline dw-mod" onclick="@(list.GetString("Ecom:Product.List.IsProductInThisList") != "True" && useFacebookPixel ? AddToWishlist : "")"> 3135 <i class="@isInListIcon u-margin-right--lg"></i> @list.GetValue("Ecom:CustomerCenter.List.Name") 3136 </a> 3137 </li> 3138 } 3139 } 3140 } 3141 else 3142 { 3143 string favLinkType = GetString("Ecom:Product.AddToFavorites") + "&CCListType=0&CCCreateNewList=" + Translate("My favorites"); 3144 string isInListIcon = favoriteOutlineIcon; 3145 <li> 3146 <a href="@favLinkType" class="list__link u-no-underline dw-mod" onclick="@(useFacebookPixel ? AddToWishlist : "")"> 3147 <i class="@isInListIcon u-margin-right--lg"></i> @Translate("My favorites") 3148 </a> 3149 </li> 3150 } 3151 </ul> 3152 </div> 3153 <label class="dropdown-trigger-off" for="FavoriteTrigger"></label> 3154 </div> 3155 </div> 3156 } 3157 </div> 3158 </div> 3159 } 3160 3161 @helper RenderStockAndShipping() 3162 { 3163 <div class="nc-product__item-number">@Translate("Product number"): @GetString("Ecom:Product.Number")</div> 3164 } 3165 3166 @helper RenderShortDescription() 3167 { 3168 string pageUrl = GetGlobalValue("Global:Pageview.Url.Raw"); 3169 if (!String.IsNullOrEmpty(GetString("Ecom:Product.ShortDescription"))) 3170 { 3171 Pageview.Meta.AddTag("og:description", GetString("Ecom:Product.ShortDescription")); 3172 <div class="introduction-text"> 3173 3174 3175 @if (!String.IsNullOrEmpty((string)Pageview.Area.Item["TrustpilotImage"])) 3176 { 3177 <img alt="trustpilot" class="introduction-text__trustpilot" src="@Pageview.Area.Item["TrustpilotImage"]"/> 3178 } 3179 3180 3181 @GetString("Ecom:Product.ShortDescription") 3182 @GetString("Ecom:Product:Field.USP") 3183 <div class="nc-product__anchor-links"> 3184 <a href="#ProductDetails" rel="noopener" class="nc-product__link"> 3185 @Translate("ProductDetails", "Detaljer om produktet") 3186 <img src="~/Files/Templates/Designs/Rapido/css/icons/arrow-right-papaya-orange.svg" class="nc-product__anchor-arrow"/> 3187 </a> 3188 <a href="#ProductSpecs" class="nc-product__link"> 3189 @Translate("Specs", "Specifikationer") 3190 <img src="~/Files/Templates/Designs/Rapido/css/icons/arrow-right-papaya-orange.svg" class="nc-product__anchor-arrow"/> 3191 </a> 3192 </div> 3193 </div> 3194 } 3195 } 3196 3197 @helper RenderMainInfoVariants() 3198 { 3199 string pageId = GetGlobalValue("Global:Page.ID").ToString(); 3200 string productId = GetString("Ecom:Product.ID"); 3201 string variantSelection = !String.IsNullOrEmpty(HttpContext.Current.Request.QueryString.Get("variantId")) ? HttpContext.Current.Request.QueryString.Get("variantId").Replace(".", ",") : ""; 3202 string hideHelpText = ""; 3203 string variantsLayout = Pageview.AreaSettings.GetItem("Ecommerce").GetString("VariantsLayout") != null ? Pageview.AreaSettings.GetItem("Ecommerce").GetList("VariantsLayout").SelectedValue : "buttons"; 3204 3205 foreach (LoopItem variantgroup in GetLoop("VariantGroups")) 3206 { 3207 foreach (LoopItem variantoption in variantgroup.GetLoop("VariantAvailableOptions")) 3208 { 3209 if (variantoption.GetBoolean("Ecom:VariantOption.Selected")) 3210 { 3211 hideHelpText = "u-hidden"; 3212 } 3213 } 3214 } 3215 3216 if (GetLoop("VariantGroups").Count > 0) 3217 { 3218 var variantCombinationsObject = new List<Array>(); 3219 foreach (LoopItem variantcomb in GetLoop("VariantCombinations")) 3220 { 3221 string[] combinations = variantcomb.GetString("Ecom:VariantCombination.VariantID").Split('.'); 3222 variantCombinationsObject.Add(combinations); 3223 } 3224 3225 string combinationsJson = Newtonsoft.Json.JsonConvert.SerializeObject(variantCombinationsObject).Replace("\"", "\'"); 3226 3227 var variantGroupsObject = new List<List<String>>(); 3228 foreach (LoopItem variantGroup in GetLoop("VariantGroups")) 3229 { 3230 var variantsObject = new List<String>(); 3231 foreach (LoopItem variantOption in variantGroup.GetLoop("VariantAvailableOptions")) 3232 { 3233 variantsObject.Add(variantOption.GetString("Ecom:VariantOption.ID")); 3234 } 3235 3236 variantGroupsObject.Add(variantsObject); 3237 } 3238 3239 string variantsJson = Newtonsoft.Json.JsonConvert.SerializeObject(variantGroupsObject).Replace("\"", "\'"); 3240 string productGroupId = HttpContext.Current.Request["GroupId"]; 3241 3242 <div> 3243 <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"> 3244 @foreach (LoopItem variantGroup in GetLoop("VariantGroups")) 3245 { 3246 string groupId = variantGroup.GetString("Ecom:VariantGroup.ID"); 3247 3248 <div> 3249 <div class="product__variant-group-name u-bold dw-mod">@variantGroup.GetString("Ecom:VariantGroup.Name")</div> 3250 <div class="u-margin-top"> 3251 @if (variantsLayout == "buttons") 3252 { 3253 foreach (LoopItem variantOption in variantGroup.GetLoop("VariantAvailableOptions")) 3254 { 3255 string selected = variantOption.GetBoolean("Ecom:VariantOption.Selected") ? "checked" : ""; 3256 string color = !String.IsNullOrEmpty(variantOption.GetString("Ecom:VariantOption.Colorcode")) ? variantOption.GetString("Ecom:VariantOption.Colorcode") : null; 3257 color = color == null && !String.IsNullOrEmpty(variantOption.GetString("Ecom:VariantOption.Color")) ? variantOption.GetString("Ecom:VariantOption.Color") : color; 3258 3259 if (!String.IsNullOrEmpty(color)) 3260 { 3261 <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> 3262 } 3263 else 3264 { 3265 <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> 3266 } 3267 } 3268 } 3269 else 3270 { 3271 <select id="VariantSelector_@groupId" class="u-full-width dw-mod" name="VariantSelector_@groupId" onchange="MatchVariants.SelectOnChange(event)"> 3272 <option>@Translate("Choose")</option> 3273 @foreach (LoopItem variantOption in variantGroup.GetLoop("VariantAvailableOptions")) 3274 { 3275 string check = variantOption.GetBoolean("Ecom:VariantOption.Selected") ? "checked" : ""; 3276 string selected = variantOption.GetBoolean("Ecom:VariantOption.Selected") ? "selected" : ""; 3277 string color = !String.IsNullOrEmpty(variantOption.GetString("Ecom:VariantOption.Colorcode")) ? variantOption.GetString("Ecom:VariantOption.Colorcode") : null; 3278 color = color == null && !String.IsNullOrEmpty(variantOption.GetString("Ecom:VariantOption.Color")) ? variantOption.GetString("Ecom:VariantOption.Color") : color; 3279 3280 <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> 3281 } 3282 </select> 3283 } 3284 </div> 3285 </div> 3286 } 3287 </div> 3288 <small class="js-help-text help-text @hideHelpText">@Translate("Please select variant!")</small> 3289 </div> 3290 } 3291 } 3292 3293 @helper RenderMainInfoBOM() 3294 { 3295 if (GetLoop("BOMProducts").Count > 0) 3296 { 3297 <h2 class="section-title">@Translate("Including products")</h2> 3298 foreach (LoopItem BOMProductItem in GetLoop("BOMProducts")) 3299 { 3300 string link = "/" + BOMProductItem.GetString("Ecom:Product.LinkGroup.Clean") + (!String.IsNullOrEmpty(BOMProductItem.GetString("Ecom:Product.VariantID")) ? "&VariantID=" + BOMProductItem.GetString("Ecom:Product.VariantID") : ""); 3301 <div class="grid__col--border grid"> 3302 <div class="grid__cell grid__cell--align-middle-left"> 3303 <a href="@link" class="u-pull--left u-margin-right"> 3304 <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")"/> 3305 </a> 3306 <a href="@link">@BOMProductItem.GetString("Ecom:Product.Name")</a> 3307 </div> 3308 </div> 3309 } 3310 } 3311 } 3312 3313 @helper RenderMainInfoBuy() 3314 { 3315 string pageId = GetGlobalValue("Global:Page.ID").ToString(); 3316 string variantId = HttpContext.Current.Request.QueryString.Get("variantId"); 3317 string productId = GetString("Ecom:Product.ID"); 3318 string feedId = pageId + "&ProductID=" + productId + "&VariantID=" + variantId + "&Feed=True&redirect=false"; 3319 3320 <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> 3321 <input type="hidden" value="@GetString("Ecom:Product.VariantID.Extented")" name="Variant" id="Variant_@GetString("Ecom:Product.ID")"/> 3322 @RenderMainInfoBuyScripts() 3323 } 3324 3325 @helper RenderPriceInfo() 3326 { 3327 bool pointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly"); 3328 bool showPrice = !Pageview.AreaSettings.GetItem("ProductList").GetBoolean("HidePrice"); 3329 bool showCartButton = !Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideAddToCartButton"); 3330 bool showVATPrice = Pageview.AreaSettings.GetItem("ProductList").GetBoolean("ShowBothPricesWithWithoutVAT"); 3331 bool isPricesWithVATEnabled = Converter.ToBoolean(Pageview.Area.EcomPricesWithVat); 3332 3333 <div class="price price--product-page dw-mod">{{ncPrice}}</div> 3334 } 3335 3336 3337 3338 @helper RenderMainInfoBuyScripts() 3339 { 3340 bool showPrice = !Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HidePrice"); 3341 bool showCartButton = !Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideAddToCartButton"); 3342 bool pointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly"); 3343 string variantId = HttpContext.Current.Request.QueryString.Get("variantId") ?? ""; 3344 string feedId = GetGlobalValue("Global:Page.ID").ToString() + "&ProductID=" + GetString("Ecom:Product.ID") + "&VariantID=" + variantId + "&Feed=True&redirect=false"; 3345 string cartIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon") != null ? Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon").SelectedValue : "fas fa-shopping-cart"; 3346 bool showVATPrice = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("ShowBothPricesWithWithoutVAT"); 3347 bool isPricesWithVATEnabled = Converter.ToBoolean(Pageview.Area.EcomPricesWithVat); 3348 3349 var customerId = Dynamicweb.Security.UserManagement.User.GetCurrentExtranetUserId(); 3350 var shopId = Pageview.Area.EcomShopId; 3351 var orderType = Dynamicweb.Ecommerce.Orders.OrderType.Order; 3352 var cartsList = (List<Dynamicweb.Ecommerce.Orders.Order>)Dynamicweb.Ecommerce.Services.Orders.GetCustomerOrdersByType(customerId, shopId, orderType, 0, false, "", DateTime.MinValue, false, true); 3353 bool hidePrice = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HidePrice"); 3354 3355 @* Handlebars templates *@ 3356 <script id="PricesAndActionsTemplate" type="text/x-template"> 3357 {{#.}} 3358 @if (Dynamicweb.Rapido.Services.User.IsPricesAllowed() && !hidePrice && isEcomArea()) 3359 { 3360 <div class="product__price-wrap dw-mod"> 3361 @RenderPriceInfo() 3362 </div> 3363 } 3364 3365 @if (showCartButton && Dynamicweb.Rapido.Services.User.IsBuyingAllowed() && isEcomArea()) 3366 { 3367 string klaviyoAddedToCartEvent = ""; 3368 var addToCartBtn = new AddToCart 3369 { 3370 WrapperCssClass = "product__price-actions-flex-wrap buttons-collection--right dw-mod", 3371 AddButton = new AddToCartButton 3372 { 3373 ProductId = "{{productId}}", 3374 VariantId = "{{variantid}}", 3375 UnitId = "{{unitId}}", 3376 ProductInfo = "{{productInfo}}", 3377 BuyForPoints = pointShopOnly, 3378 OnClick = "trackAddedToCart({{klaviyoAction}});", 3379 ExtraAttributes = new Dictionary<string, string> 3380 { 3381 { "{{disabledBuyButton}}", "" } 3382 }, 3383 CssClass = "nc-product__price-buy-button" 3384 }, 3385 UnitSelector = new UnitSelector 3386 { 3387 OptionsContent = "{{#unitOptions}}{{>UnitOption}}{{/unitOptions}}", 3388 Id = "UnitOptions_{{id}}", 3389 SelectedOption = "{{unitName}}", 3390 CssClass = "{{#if hasOnlyOneUnit}}unit-selector--readonly{{/if}} {{hasUnits}}" 3391 } 3392 }; 3393 3394 if (!pointShopOnly) 3395 { 3396 addToCartBtn.QuantitySelector = new QuantitySelector 3397 { 3398 Id = "Quantity_{{id}}" 3399 }; 3400 } 3401 3402 <div class="nc-product__price-actions-wrap dw-mod"> 3403 @Render(addToCartBtn) 3404 3405 @if (Dynamicweb.Core.Converter.ToBoolean(GetGlobalValue("Global:Extranet.UserName")) && User.IsBuyingAllowed() && cartsList.Count > 0 && GetPageIdByNavigationTag("OrderDraft") != 0) 3406 { 3407 var addToDraftCart = new Button 3408 { 3409 Id = "AddToDraftCart", 3410 Title = Translate("Add to draft"), 3411 ButtonLayout = ButtonLayout.Secondary, 3412 OnClick = "document.getElementById('OrderDraftSelectModalTrigger').checked = true", 3413 CssClass = "u-w220px u-margin-top" 3414 }; 3415 3416 @Render(addToDraftCart) 3417 } 3418 3419 @if (Pageview.User != null && !pointShopOnly && Dynamicweb.Security.Licensing.LicenseManager.LicenseHasFeature("LoyaltyPoints")) 3420 { 3421 <text> 3422 {{#if canBePurchasedWithPoints}} 3423 <form method="post" role="form" class="u-no-margin u-margin-top"> 3424 <input type="hidden" name="ProductID" value="{{id}}" /> 3425 <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> 3426 </form> 3427 {{/if}} 3428 </text> 3429 } 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 </div> 3456 3457 } 3458 else 3459 { 3460 <button type="button" id="CartButton_{{id}}" class="u-hidden"></button> 3461 } 3462 3463 @if (GetRecursiveGroupValue("UseDatepicker")) 3464 { 3465 <a onclick="document.getElementById('DatepickerModalModalTrigger').checked = true;" href="javascript:void(0)" class="datepicker-text">@Translate("Datepicker modal open text")</a> 3466 } 3467 3468 @RenderStockAndShipping() 3469 {{/.}} 3470 </script> 3471 3472 <script id="UnitOption" type="text/x-template"> 3473 <div class="dropdown__item dw-mod" onclick="HandlebarsBolt.UpdateContent('PriceAndActions', '{{link}}&feed=true&UnitID={{value}}')">{{name}}</div> 3474 </script> 3475 3476 <script> 3477 document.addEventListener("DOMContentLoaded", function () { 3478 if (document.getElementById("PriceAndActions")) { 3479 document.getElementById("PriceAndActions").addEventListener("contentLoaded", function (event) { 3480 if (document.querySelector(".js-variants") != null) { 3481 MatchVariants.Update(document.querySelector(".js-variants"), "DoNothing"); 3482 } 3483 }); 3484 } 3485 }); 3486 </script> 3487 } 3488 3489 @{ 3490 Modal Datepicker = new Modal 3491 { 3492 Id = "DatepickerModal", 3493 Heading = new Heading 3494 { 3495 Level = 0, 3496 }, 3497 Width = ModalWidth.Full, 3498 BodyTemplate = RenderDatepicker() 3499 }; 3500 3501 3502 Modal Cashback = new Modal 3503 { 3504 Id = "CashbackModal", 3505 Heading = new Heading 3506 { 3507 Level = 0, 3508 }, 3509 Width = ModalWidth.Full, 3510 BodyTemplate = RenderCashback() 3511 }; 3512 } 3513 3514 3515 @helper RenderDatepicker() 3516 { 3517 <div class="dp-modal"> 3518 <div class="dp-modal__header"> 3519 @Translate("Datepicker modal header") 3520 </div> 3521 <div class="dp-modal__text-container"> 3522 <div class="dp-modal__text-container__text"> 3523 @Translate("Datepicker modal text") 3524 </div> 3525 </div> 3526 <label for="DatepickerModalModalTrigger" class="modal-button"> 3527 Luk 3528 </label> 3529 </div> 3530 } 3531 3532 3533 @helper RenderCashback() 3534 { 3535 <div class="cashback-modal"> 3536 <div class="text__container"> 3537 @Pageview.Area.Item["CashbackText"] 3538 </div> 3539 <label for="CashbackModalModalTrigger" class="modal-button"> 3540 Luk 3541 </label> 3542 </div> 3543 } 3544 3545 @if (GetRecursiveGroupValue("UseDatepicker")) 3546 { 3547 @Render(Datepicker) 3548 } 3549 3550 @if (GetRecursiveGroupValue("Cashback")) 3551 { 3552 @Render(Cashback) 3553 } 3554 3555 3556 @helper RenderOrderDraftSelectModalContent() 3557 { 3558 var customerId = Dynamicweb.Security.UserManagement.User.GetCurrentExtranetUserId(); 3559 var shopId = Pageview.Area.EcomShopId; 3560 var orderType = Dynamicweb.Ecommerce.Orders.OrderType.Order; 3561 var cartsList = (List<Dynamicweb.Ecommerce.Orders.Order>)Dynamicweb.Ecommerce.Services.Orders.GetCustomerOrdersByType(customerId, shopId, orderType, 0, false, "", DateTime.MinValue, false, true); 3562 3563 SelectField cartSelector = new SelectField 3564 { 3565 Id = "CartSelector", 3566 Label = Translate("I want to add this product to") 3567 }; 3568 3569 foreach (Dynamicweb.Ecommerce.Orders.Order cart in cartsList) 3570 { 3571 string name = !string.IsNullOrEmpty(cart.DisplayName) ? cart.DisplayName : cart.Id; 3572 cartSelector.Options.Add(new SelectFieldOption { Label = name, Value = cart.Id }); 3573 } 3574 3575 @Render(cartSelector) 3576 } 3577 3578 @helper RenderOrderDraftScripts() 3579 { 3580 string productId = GetString("Ecom:Product.ID"); 3581 string variantId = !string.IsNullOrEmpty(GetString("Ecom:Product.VariantID")) ? GetString("Ecom:Product.VariantID") : GetString("Ecom:Product.VariantID.Extented"); 3582 string unitId = GetString("Ecom:Product.DefaultUnitID"); 3583 var cartCmdUrl = "/Default.aspx?ID=" + Pageview.Page.ID; 3584 int orderDraftPageId = GetPageIdByNavigationTag("DraftDetails"); 3585 int orderDraftParagraphId = Dynamicweb.Content.Services.Paragraphs.GetParagraphsByPageId(orderDraftPageId).ToList().First().ID; 3586 3587 foreach (LoopItem unitOption in GetLoop("Units")) 3588 { 3589 if (unitOption.GetString("Ecom:VariantOption.Selected") == "SELECTED") 3590 { 3591 unitId = unitOption.GetString("Ecom:VariantOption.ID"); 3592 } 3593 } 3594 3595 <script> 3596 function addToSelectedCart() { 3597 var requestUrl = "@cartCmdUrl" + "&cartcmd=Add&Quantity=1" + "&CartId=" + document.getElementById("CartSelector").value + "&ProductId=@productId" + "&VariantId=@variantId" + "&UnitId=@unitId"; 3598 3599 console.log(requestUrl) 3600 3601 document.getElementById('OrderDraftSelectModalTrigger').checked = false; 3602 3603 var overlayElement = document.createElement('div'); 3604 overlayElement.className = "preloader-overlay"; 3605 overlayElement.setAttribute('id', "CartOverlay"); 3606 var overlayElementIcon = document.createElement('div'); 3607 overlayElementIcon.className = "preloader-overlay__icon dw-mod"; 3608 overlayElementIcon.style.top = window.pageYOffset + "px"; 3609 overlayElement.appendChild(overlayElementIcon); 3610 document.getElementById('content').parentNode.insertBefore(overlayElement, document.getElementById('content')); 3611 3612 Request.Fetch().get( 3613 requestUrl, 3614 function () { 3615 var overlayNode = document.getElementById('CartOverlay'); 3616 overlayNode.parentNode.removeChild(overlayNode); 3617 document.getElementById('OrderDraftNotificationModalTrigger').checked = true; 3618 }, 3619 null, 3620 false 3621 ); 3622 } 3623 3624 function goToSelectedCart() { 3625 window.location = "/Default.aspx?ID=" + "@orderDraftPageId" + "&CartID=" + document.getElementById('CartSelector').value + "&CartCmd=setcart" + "&redirect=false"; 3626 } 3627 </script> 3628 } 3629 3630 3631 @{ 3632 bool useGoogleTagManager = !string.IsNullOrEmpty(Pageview.AreaSettings.GetItem("Settings").GetString("GoogleTagManagerID")); 3633 3634 var pageService = new PageService(); 3635 GroupHelper gh = new GroupHelper(); 3636 GroupService groupService = new GroupService(); 3637 3638 var _group = groupService.GetGroup(GetString("Ecom:Product.PrimaryOrFirstGroupID")); 3639 var groupNames = gh.GetParentsRecursively(_group, new List<string>()); 3640 3641 groupNames = gh.Format(groupNames, _group); 3642 var groups = gh.ListToString(groupNames); 3643 3644 if (useGoogleTagManager) 3645 { 3646 var groupObject = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(GetString("Ecom:Product.PrimaryOrFirstGroupID")); 3647 <script> 3648 price = @GetDouble("Ecom:Product.Price.PriceWithVAT.Value"); 3649 3650 dataLayer.push({ecommerce:null}); 3651 dataLayer.push({ 3652 'event': 'view_item', 3653 "ecommerce":{ 3654 "currency" : "@GetString("Ecom:Product.CurrencyCode")", 3655 "value" : 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": "1", 3667 } 3668 ] 3669 }, 3670 }); 3671 3672 // Measure a view of product details. This example assumes the detail view occurs on pageload, 3673 // and also tracks a standard pageview of the details page. 3674 dataLayer.push({ 3675 'event': 'productDetails', 3676 "ecommerce": { 3677 "detail": { 3678 "currencyCode": "@GetString("Ecom:Product.Price.Currency.Code")", 3679 "actionField": {}, // 'detail' actions have an optional list property. 3680 "products": [{ 3681 "name": "@GetString("Ecom:Product.Name")", // Name or ID is required. 3682 "id": "@GetString("Ecom:Product.ID")", 3683 "price": "@(GetDouble("Ecom:Product.Discount.Price.Price") != GetDouble("Ecom:Product.Price.Price") ? GetDouble("Ecom:Product.Discount.Price.Price") : GetDouble("Ecom:Product.Price.Price"))", 3684 "brand": "@GetString("Ecom:Product:Field.brand.Value")", 3685 "category": "@(groupObject != null ? groupObject.Name : "")", 3686 "variant": "@(!string.IsNullOrEmpty(GetString("Ecom:Product.VariantID")) ? GetString("Ecom:Product.VariantID") : GetString("Ecom:Product.VariantID.Extented"))" 3687 }] 3688 } 3689 } 3690 }); 3691 </script> 3692 } 3693 } 3694 3695 3696 <script type="text/javascript"> 3697 function trackAddedToCart(data){ 3698 data.AddedItemQuantity = parseFloat(document.getElementById('Quantity_@GetString("Ecom:Product.Number")').value) 3699 _learnq.push(["track", "Added to Cart", data]); 3700 } 3701 </script> 3702 <script> 3703 3704 3705 function AddToCartClicked(quantity){ 3706 3707 var price = @GetDouble("Ecom:Product.Price.PriceWithVAT.Value"); 3708 3709 dataLayer.push({ecommerce:null}); 3710 dataLayer.push({ 3711 'event': 'add_to_cart', 3712 "ecommerce":{ 3713 "currency" : "@GetString("Ecom:Product.CurrencyCode")", 3714 "value" : quantity * price, 3715 "items":[ 3716 { 3717 'item_id': "@GetString("Ecom:Product.ID")", 3718 "item_name": "@GetString("Ecom:Product.Name")", 3719 'price': price, 3720 "item_category": ("@groups".split("_")[0] != null ? "@groups".split("_")[0] : ""), 3721 "item_category2": ("@groups".split("_")[1] != null ? "@groups".split("_")[1] : ""), 3722 "item_category3": ("@groups".split("_")[2] != null ? "@groups".split("_")[2] : ""), 3723 "item_category4": ("@groups".split("_")[3] != null ? "@groups".split("_")[3] : ""), 3724 "item_category5": ("@groups".split("_")[4] != null ? "@groups".split("_")[4] : ""), 3725 "quantity": quantity, 3726 } 3727 ], 3728 }, 3729 }); 3730 } 3731 function delay() { 3732 setTimeout(function() { 3733 3734 var AddToCartButton = document.getElementsByClassName("nc-product__price-buy-button")[0]; 3735 3736 AddToCartButton.addEventListener("click", function (item){ 3737 3738 var q = "Quantity_"; 3739 q += "@GetString("Ecom:Product.ID")"; 3740 var quantity = document.getElementById(q).value; 3741 AddToCartClicked(quantity); 3742 }) 3743 3744 }, 200); 3745 } 3746 3747 if (document.readyState == 'complete') { 3748 delay(); 3749 } else { 3750 document.onreadystatechange = function () { 3751 if (document.readyState === "complete") { 3752 delay(); 3753 } 3754 } 3755 } 3756 </script> 3757 3758 <script type="text/javascript"> 3759 function trackAddedToCart(data){ 3760 data.AddedItemQuantity = parseFloat(document.getElementById('Quantity_@GetString("Ecom:Product.Number")').value) 3761 _learnq.push(["track", "Added to Cart", data]); 3762 } 3763 </script> 3764 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 3765 @using Dynamicweb.Core 3766 @using System 3767 @using System.Web 3768 @using System.Collections.Generic 3769 @using Dynamicweb.Ecommerce.Products 3770 @using Dynamicweb.Rapido.Blocks 3771 @using Dynamicweb.Rapido.Blocks.Components.General 3772 @using System.Text.Json; 3773 @using Dynamicweb.Frontend.Devices 3774 3775 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 3776 @using System.Linq; 3777 @using Dynamicweb.Rapido.Blocks.Components.General 3778 @using System.Collections.Generic 3779 3780 @functions{ 3781 Dictionary<string, StickersListPosition> stickerPositions = new Dictionary<string, StickersListPosition> 3782 { 3783 { "top-left", StickersListPosition.TopLeft }, 3784 { "top-right", StickersListPosition.TopRight }, 3785 { "bottom-left", StickersListPosition.BottomLeft }, 3786 { "bottom-right", StickersListPosition.BottomRight } 3787 }; 3788 3789 public void AddSticker(List<StickersCollection> list, Sticker sticker, StickersListPosition stickerPosition) 3790 { 3791 StickersCollection stickersContainerTemp = list.FirstOrDefault(stickersContainer => stickersContainer.Position == stickerPosition); 3792 if (stickersContainerTemp == null) 3793 { 3794 stickersContainerTemp = new StickersCollection() 3795 { 3796 Position = stickerPosition, 3797 Stickers = new List<Sticker>() 3798 }; 3799 list.Add(stickersContainerTemp); 3800 } 3801 stickersContainerTemp.Stickers.Add(sticker); 3802 } 3803 3804 public List<StickersCollection> GetStickersContainersList(List<LoopItem> discountsLoop, double discountPrice, double price, DateTime createdDate, string customStickerValue) 3805 { 3806 bool pointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly"); 3807 bool isSaleStickersEnabled = Pageview.AreaSettings.GetItem("Ecommerce").GetItem("SaleSticker").GetBoolean("Enable"); 3808 bool isNewsStickersEnabled = Pageview.AreaSettings.GetItem("Ecommerce").GetItem("NewSticker").GetBoolean("Enable"); 3809 bool isCustomStickersEnabled = Pageview.AreaSettings.GetItem("Ecommerce").GetItem("CustomSticker").GetBoolean("Enable"); 3810 3811 List<StickersCollection> resultList = new List<StickersCollection>(); 3812 3813 if (!pointShopOnly && isSaleStickersEnabled) 3814 { 3815 string contentType = Pageview.AreaSettings.GetItem("Ecommerce").GetItem("SaleSticker").GetString("ContentType"); 3816 contentType = !string.IsNullOrEmpty(contentType) ? contentType : "Name"; 3817 var currency = Dynamicweb.Ecommerce.Services.Currencies.GetDefaultCurrency(); 3818 Sticker saleSticker = new Sticker(); 3819 saleSticker.CssClass = "stickers-container__tag--sale"; 3820 3821 switch (contentType) 3822 { 3823 case "Name": 3824 foreach (LoopItem discount in discountsLoop) 3825 { 3826 saleSticker.Title = discount.GetString("Ecom:Product.Discount.Name"); 3827 } 3828 break; 3829 case "Amount": 3830 if (discountsLoop.Count > 0) 3831 { 3832 saleSticker.Title = Dynamicweb.Ecommerce.Services.Currencies.Format(currency, discountPrice - price); 3833 } 3834 break; 3835 case "Percents": 3836 double percents = 0; 3837 foreach (LoopItem discount in discountsLoop) 3838 { 3839 percents += discount.GetDouble("Ecom:Product.Discount.PercentWithoutVAT"); 3840 } 3841 if (percents > 0) 3842 { 3843 saleSticker.Title = Math.Round(percents, 0) + "%"; 3844 } 3845 break; 3846 case "Amount and percents": 3847 double amount = 0; 3848 double percent = 0; 3849 foreach (LoopItem discount in discountsLoop) 3850 { 3851 if (discount.GetString("Ecom:Product.Discount.Type") == "PERCENT") 3852 { 3853 percent += discount.GetDouble("Ecom:Product.Discount.PercentWithoutVAT"); 3854 } 3855 else if (discount.GetString("Ecom:Product.Discount.Type") == "AMOUNT") 3856 { 3857 amount += discount.GetDouble("Ecom:Product.Discount.AmountWithVAT"); 3858 } 3859 } 3860 3861 if (percent > 0) 3862 { 3863 saleSticker.Title = percent + "%"; 3864 } 3865 else if (amount > 0) 3866 { 3867 saleSticker.Title = "-" + Dynamicweb.Ecommerce.Services.Currencies.Format(currency, amount); 3868 } 3869 break; 3870 default: 3871 if (discountsLoop.Count > 0) 3872 { 3873 saleSticker.Title = Translate("Sale!"); 3874 } 3875 break; 3876 } 3877 StickersListPosition saleStickerPosition = StickersListPosition.TopLeft; 3878 if (Pageview.AreaSettings.GetItem("Ecommerce").GetItem("SaleSticker").GetList("Position") != null) 3879 { 3880 string value = Pageview.AreaSettings.GetItem("Ecommerce").GetItem("SaleSticker").GetList("Position").SelectedValue; 3881 saleStickerPosition = stickerPositions.ContainsKey(value) ? stickerPositions[value] : stickerPositions["top-left"]; 3882 } 3883 if (!string.IsNullOrEmpty(saleSticker.Title)) 3884 { 3885 AddSticker(resultList, saleSticker, saleStickerPosition); 3886 } 3887 } 3888 3889 if (!pointShopOnly && isNewsStickersEnabled && createdDate.AddDays(Converter.ToDouble(Pageview.AreaSettings.GetItem("Ecommerce").GetItem("NewSticker").GetString("Expiration"))) > DateTime.Now) 3890 { 3891 Sticker newSticker = new Sticker(); 3892 newSticker.CssClass = "stickers-container__tag--new"; 3893 newSticker.Title = Translate("New!"); 3894 3895 StickersListPosition newStickerPosition = StickersListPosition.TopLeft; 3896 if (Pageview.AreaSettings.GetItem("Ecommerce").GetItem("NewSticker").GetList("Position") != null) 3897 { 3898 string value = Pageview.AreaSettings.GetItem("Ecommerce").GetItem("NewSticker").GetList("Position").SelectedValue; 3899 newStickerPosition = stickerPositions.ContainsKey(value) ? stickerPositions[value] : stickerPositions["top-left"]; 3900 } 3901 if (!string.IsNullOrEmpty(newSticker.Title)) 3902 { 3903 AddSticker(resultList, newSticker, newStickerPosition); 3904 } 3905 } 3906 3907 if (!pointShopOnly && isCustomStickersEnabled && !string.IsNullOrEmpty(customStickerValue)) 3908 { 3909 Sticker customSticker = new Sticker(); 3910 customSticker.CssClass = "stickers-container__tag--custom"; 3911 customSticker.Title = customStickerValue; 3912 3913 StickersListPosition customStickerPosition = StickersListPosition.TopLeft; 3914 if (Pageview.AreaSettings.GetItem("Ecommerce").GetItem("CustomSticker").GetList("Position") != null) 3915 { 3916 string value = Pageview.AreaSettings.GetItem("Ecommerce").GetItem("CustomSticker").GetList("Position").SelectedValue; 3917 customStickerPosition = stickerPositions.ContainsKey(value) ? stickerPositions[value] : stickerPositions["top-left"]; 3918 } 3919 if (!string.IsNullOrEmpty(customSticker.Title)) 3920 { 3921 AddSticker(resultList, customSticker, customStickerPosition); 3922 } 3923 } 3924 3925 return resultList; 3926 } 3927 } 3928 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 3929 3930 3931 @* 3932 This is a temporary fallback for the DefaultImage. The image pattern MUST be set up like this: 3933 3934 ImageSmall = /{ProductNumber}.jpg 3935 ImageMedium = /{ProductNumber}{VariantOptionLevel1}.jpg 3936 ImageLarge = /{ProductNumber}{VariantComboName}.jpg 3937 3938 In addition to the ImageDefault setting 3939 *@ 3940 3941 @functions { 3942 public string GetProductImage(LoopItem productObject = null) 3943 { 3944 string theImage = ""; 3945 3946 if (productObject == null) { 3947 theImage = GetString("Ecom:Product.ImageDefault.Default.Clean"); 3948 theImage = String.IsNullOrEmpty(theImage) ? GetString("Ecom:Product.ImageLarge.Clean") : theImage; 3949 theImage = String.IsNullOrEmpty(theImage) ? GetString("Ecom:Product.ImageMedium.Clean") : theImage; 3950 theImage = String.IsNullOrEmpty(theImage) ? GetString("Ecom:Product.ImageSmall.Clean") : theImage; 3951 theImage = String.IsNullOrEmpty(theImage) ? GetString("Ecom:Product.ImageLarge.Default.Clean") : theImage; 3952 } else { 3953 theImage = productObject.GetString("Ecom:Product.ImageDefault.Default.Clean"); 3954 theImage = String.IsNullOrEmpty(theImage) ? productObject.GetString("Ecom:Product.ImageLarge.Clean") : theImage; 3955 theImage = String.IsNullOrEmpty(theImage) ? productObject.GetString("Ecom:Product.ImageMedium.Clean") : theImage; 3956 theImage = String.IsNullOrEmpty(theImage) ? productObject.GetString("Ecom:Product.ImageSmall.Clean") : theImage; 3957 theImage = String.IsNullOrEmpty(theImage) ? productObject.GetString("Ecom:Product.ImageLarge.Default.Clean") : theImage; 3958 } 3959 3960 return theImage; 3961 } 3962 } 3963 3964 @functions { 3965 BlocksPage mainImagePage = BlocksPage.GetBlockPage("Product"); 3966 bool showThumbs; 3967 bool thumbsOnTheSide; 3968 } 3969 3970 @{ 3971 int imageBlockWidth = Pageview.AreaSettings.GetItem("ProductPage").GetList("TopLayout") != null ? Converter.ToInt32(Pageview.AreaSettings.GetItem("ProductPage").GetList("TopLayout").SelectedValue) : 6; 3972 string blocksPosition = Pageview.AreaSettings.GetItem("ProductPage").GetList("ImageSectionPosition") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("ImageSectionPosition").SelectedValue : "thumbs-image-info"; 3973 bool infoOnTheRight = blocksPosition.LastIndexOf("info") == blocksPosition.Length - 4; 3974 showThumbs = blocksPosition.IndexOf("thumbs") != -1; 3975 thumbsOnTheSide = showThumbs && blocksPosition.IndexOf("thumbsBottom") == -1; 3976 bool thumbsOnTheLeft = blocksPosition.IndexOf("image") > blocksPosition.IndexOf("thumbs"); 3977 if (infoOnTheRight) 3978 { 3979 imageBlockWidth = 14 - imageBlockWidth; 3980 if (imageBlockWidth == 0) 3981 { 3982 imageBlockWidth = 14; 3983 } 3984 } 3985 3986 if (Pageview.Device.ToString() == "Mobile" || Pageview.Device.ToString() == "Tablet") 3987 { 3988 thumbsOnTheSide = false; 3989 } 3990 3991 Block mainImageBlock = new Block() 3992 { 3993 Id = "MainImage", 3994 SortId = infoOnTheRight ? 10 : 20, 3995 Design = new Design 3996 { 3997 Size = Converter.ToString(imageBlockWidth), 3998 RenderType = RenderType.Column 3999 }, 4000 BlocksList = new List<Block> 4001 { 4002 new Block 4003 { 4004 Id = "MainImageRow", 4005 SortId = 10, 4006 Design = new Design 4007 { 4008 RenderType = RenderType.Row 4009 }, 4010 BlocksList = new List<Block> 4011 { 4012 new Block 4013 { 4014 Id = "Carousel", 4015 SortId = 10, 4016 Template = RenderThumbnails(), 4017 Design = new Design 4018 { 4019 Size = thumbsOnTheSide ? "2" : "12", 4020 RenderType = RenderType.Column 4021 } 4022 } 4023 } 4024 } 4025 } 4026 }; 4027 mainImagePage.Add("Top", mainImageBlock); 4028 4029 mainImagePage.Add("MainImageRow", 4030 new Block() 4031 { 4032 Id = "ProductImageModal", 4033 SortId = 0, 4034 Component = new Modal 4035 { 4036 Id = "Gallery", 4037 Width = ModalWidth.Lg, 4038 Height = ModalHeight.Full, 4039 BodyTemplate = RenderProductImagesCarousel("modalCarousel", 1, "horizontal", 3, true) 4040 } 4041 }); 4042 4043 if (showThumbs) 4044 { 4045 mainImagePage.Add("MainImageRow", 4046 new Block 4047 { 4048 Id = "Image", 4049 SortId = thumbsOnTheLeft ? 20 : 0, 4050 Template = RenderProductImage(), 4051 Design = new Design 4052 { 4053 Size = thumbsOnTheSide ? "auto" : "12", 4054 RenderType = RenderType.Column 4055 } 4056 }); 4057 } 4058 } 4059 4060 @helper RenderProductStickers() 4061 { 4062 List<StickersCollection> StickersContainers = GetStickersContainersList( 4063 GetLoop("ProductDiscounts"), 4064 GetDouble("Ecom:Product.Discount.Price.Price"), 4065 GetDouble("Ecom:Product.Price.Price"), 4066 GetDate("Ecom:Product.Created"), 4067 GetString("Ecom:Product:Field.CustomSticker.Value") 4068 ); 4069 4070 foreach (StickersCollection stickersContainer in StickersContainers) 4071 { 4072 @Render(new StickersCollection { Stickers = stickersContainer.Stickers, Position = stickersContainer.Position }) 4073 } 4074 } 4075 4076 @helper RenderProductImage() 4077 { 4078 //Add product image to the og meta data 4079 Pageview.Meta.AddTag("og:image", GetProductImage()); 4080 4081 <label for="GalleryModalTrigger" class="nc-product__image-container u-position-relative br-25"> 4082 @{ 4083 Image productImage = new Image 4084 { 4085 Path = GetProductImage(), 4086 Id = "Image_" + GetString("Ecom:Product.ID"), 4087 CssClass = "nc-product__image-container__image br-25", 4088 Title = GetString("Ecom:Product.Name"), 4089 OnClick = "modalCarousel.GoToSlide('modalCarousel', this.getAttribute('data-number'))", 4090 DisableLazyLoad = true, 4091 ImageDefault = new ImageSettings 4092 { 4093 Width = 800, 4094 Height = 800, 4095 Crop = 7, 4096 FillCanvas = true 4097 } 4098 }; 4099 productImage.ExtraAttributes.Add("data-number", "0"); 4100 } 4101 4102 @Render(productImage) 4103 4104 @RenderProductStickers() 4105 4106 @RenderDiscountAmountCountDown() 4107 4108 </label> 4109 } 4110 4111 4112 4113 @helper RenderDiscountAmountCountDown() 4114 { 4115 string productId = GetString("Ecom:Product.ID"); 4116 string variantId = GetString("Ecom:Product.Variant.ID"); 4117 4118 <div style="display: none" class="nc-product__image-container__countdown"> 4119 <div class="nc-product__image-container__countdown__text"> 4120 @Translate("DiscountOnly") 4121 </div> 4122 <div id="ws-discount-stock-level" class="nc-product__image-container__countdown__amount"> 4123 4124 </div> 4125 <div class="nc-product__image-container__countdown__text"> 4126 @Translate("DiscountLeft") 4127 </div> 4128 </div> 4129 4130 <script> 4131 4132 //get initial stock with js 4133 const xhr = new XMLHttpRequest(); 4134 const currentProductId = "@productId"; 4135 const currentProductVariantId = "@variantId"; 4136 var requestUrl = "/dwapi/ecommerce/products/" + currentProductId; 4137 if (currentProductVariantId) { 4138 requestUrl += "/" + currentProductVariantId; 4139 } 4140 4141 var discountAmount = 0; 4142 xhr.open('GET', window.location.origin + requestUrl, true); 4143 4144 var stockLevel = 0; 4145 var stockStatus = ""; 4146 var stockDeliveryText = ""; 4147 var neverOutOfStock = false; 4148 4149 xhr.onload = function () { 4150 if (xhr.status === 200) { 4151 4152 const data = JSON.parse(xhr.responseText); 4153 discountAmount = parseInt(data?.ProductFields?.DiscountAmount?.Value); 4154 4155 if(discountAmount > 0){ 4156 document.getElementById("ws-discount-stock-level").textContent = discountAmount; 4157 document.querySelector(".nc-product__image-container__countdown").style.display = "flex"; 4158 } 4159 4160 stockLevel = parseInt(data?.StockLevel); 4161 stockDeliveryText = data?.StockDeliveryText; 4162 stockStatus = data?.StockStatus; 4163 neverOutOfStock = data?.NeverOutOfstock; 4164 var stockInStock = document.querySelector('.stock-instock-container'); 4165 var stockNotInStock = document.querySelector('.stock-notinstock-container'); 4166 4167 if (stockDeliveryText == null){ 4168 stockDeliveryText = ""; 4169 } 4170 4171 if (stockLevel > 0) 4172 { 4173 4174 if (stockInStock) 4175 { 4176 stockInStock.style.display = "block"; 4177 stockNotInStock.style.display = "none"; 4178 stockInStock.firstChild.title = stockStatus; 4179 stockInStock.children[1].textContent = stockStatus; 4180 } 4181 4182 } 4183 else 4184 { 4185 if (stockInStock){ 4186 stockInStock.style.display = "none"; 4187 stockNotInStock.style.display = "block"; 4188 } 4189 } 4190 4191 4192 if (!neverOutOfStock) 4193 { 4194 document.querySelector('.nc-product__stock-delivery').style.display = "flex"; 4195 4196 if(stockLevel > 0) 4197 { 4198 document.querySelector('.nc-stock__stock-text').textContent = stockStatus; 4199 } 4200 4201 } 4202 4203 document.querySelector('.nc-product__delivery-text__content').textContent = "@Translate("Delivery", "Levering") " + stockDeliveryText; 4204 4205 } else { 4206 console.error('Request failed. Status:', xhr.status); 4207 } 4208 }; 4209 4210 xhr.onerror = function () { 4211 console.error('Network error.'); 4212 }; 4213 4214 xhr.send(); 4215 4216 4217 const scheme = window.location.protocol === "https:" ? "wss:" : "ws:"; 4218 const ws = new WebSocket(`${scheme}//${window.location.host}/WebSocketRequestHandler.ashx`); 4219 4220 ws.onmessage = e => { 4221 const { productId, productVariantId, newStock } = JSON.parse(e.data); 4222 4223 var wsProductId = productId; 4224 var wsVariantId = productVariantId; 4225 4226 if (productVariantId == null) { 4227 wsVariantId = ""; 4228 } 4229 4230 if (currentProductId == wsProductId && currentProductVariantId == wsVariantId) 4231 { 4232 document.getElementById("ws-discount-stock-level").textContent = newStock; 4233 if (newStock <= 0) { 4234 document.getElementById("ws-discount-stock-level").textContent = "0"; 4235 document.getElementById("ws-discount-stock-level").parentElement.style.display = "none"; 4236 } 4237 4238 } 4239 }; 4240 ws.onerror = console.error; 4241 4242 </script> 4243 } 4244 4245 @helper RenderThumbnails() 4246 { 4247 <div class="dw-mod"> 4248 @RenderProductImagesCarousel( 4249 "productCarousel", 4250 !showThumbs ? 1 : 5, 4251 thumbsOnTheSide ? "vertical" : "horizontal", 4252 !showThumbs ? 3 : 2 4253 ) 4254 @if (!showThumbs) 4255 { 4256 @RenderProductStickers() 4257 } 4258 </div> 4259 } 4260 4261 @helper RenderProductImagesCarousel(string id, int slidesInView, string direction, int preloaderSize, bool isModal = false) 4262 { 4263 var selectedImageCategories = Pageview.AreaSettings.GetItem("ProductPage").GetList("ProductImagesInTopSection").SelectedValues; 4264 var imagesFromAssets = GetLoop("ImageCategories").Where(x => selectedImageCategories.Contains(x.GetString("Category.Id"))); 4265 4266 HashSet<string> images = new HashSet<string>(); 4267 4268 images.Add(GetProductImage()); 4269 4270 foreach (LoopItem alternativeImage in GetLoop("Ecom:Product.AlternativeImages")) 4271 { 4272 string alt_image = alternativeImage.GetString("Ecom:Product.AlternativeImages.Image"); 4273 4274 if (!string.IsNullOrEmpty(alt_image)) 4275 { 4276 images.Add(alt_image); 4277 } 4278 } 4279 4280 int assetImagesCount = 0; 4281 foreach (LoopItem category in imagesFromAssets) 4282 { 4283 foreach (LoopItem asset in category.GetLoop("Category.Images")) 4284 { 4285 assetImagesCount++; 4286 } 4287 } 4288 4289 if (assetImagesCount > 0) 4290 { 4291 foreach (LoopItem category in imagesFromAssets) 4292 { 4293 foreach (LoopItem asset in category.GetLoop("Category.Images")) 4294 { 4295 images.Add(asset.GetString("Ecom:Product:Detail.Image.Clean")); 4296 } 4297 } 4298 } 4299 else 4300 { 4301 foreach (LoopItem detail in GetLoop("Details")) 4302 { 4303 string detail_image = detail.GetString("Ecom:Product:Detail.Image.Clean"); 4304 4305 if (!string.IsNullOrEmpty(detail_image)) 4306 { 4307 string ext = Path.GetExtension(detail_image).ToLower(); 4308 if (ext == ".jpg" || ext == ".jpeg" || ext == ".gif" || ext == ".png") 4309 { 4310 images.Add(detail_image); 4311 } 4312 } 4313 } 4314 } 4315 4316 <div class="carousel dw-mod" id="@id"> 4317 <div class="thumb-list carousel__container @(slidesInView != 1 ? "carousel__container--hidden" : "") js-carousel-slides dw-mod"> 4318 @{ var i = 0; } 4319 @foreach (var image in images) 4320 { 4321 @RenderProductImage(image, slidesInView == 1, isModal ? "modal--full__img" : "", i == 0, isModal) 4322 i++; //first is active 4323 } 4324 </div> 4325 4326 <script> 4327 document.addEventListener("DOMContentLoaded", function () { 4328 @id = new CarouselModule('#@id', { 4329 slidesInView: @slidesInView, 4330 direction: "@direction", 4331 preloaderSize: @preloaderSize, 4332 showCounter: @isModal.ToString().ToLower() 4333 }); 4334 }); 4335 </script> 4336 </div> 4337 } 4338 4339 @helper RenderProductImage(string image, bool isBig, string cssClass = "", bool isActive = false, bool isModal = false) 4340 { 4341 string productId = GetString("Ecom:Product.ID"); 4342 string imagePrefix = "/Admin/Public/GetImage.ashx?width=800&amp;height=800&amp;crop=7&FillCanvas=True&DoNotUpscale=true&amp;Compression=75&amp;image="; 4343 4344 Image productImage = new Image 4345 { 4346 Path = image, 4347 Title = GetString("Ecom:Product.Name"), 4348 DisableLazyLoad = true, 4349 ImageDefault = new ImageSettings 4350 { 4351 Width = 800, 4352 Height = 800, 4353 Crop = 5, 4354 FillCanvas = false 4355 }, 4356 CssClass = "u-middle br-sm-15" + cssClass, 4357 OnClick = "modalCarousel.GoToSlide('modalCarousel', this.closest('.carousel__slide').index());" 4358 }; 4359 productImage.ExtraAttributes.Add("data-image", image); 4360 4361 <div class="carousel__slide dw-mod"> 4362 4363 @if (isModal) 4364 { 4365 @Render(new Image { Path = image, CssClass = cssClass, Title = GetString("Ecom:Product.Name"), DisableImageEngine = true }) 4366 ; 4367 } 4368 else if (isBig) 4369 { 4370 <label for="GalleryModalTrigger" class="u-middle"> 4371 @Render(productImage) 4372 </label> 4373 } 4374 else 4375 { 4376 Image productThumb = productImage; 4377 productThumb.ImageDefault = new ImageSettings 4378 { 4379 Width = 200, 4380 Height = 200, 4381 Crop = 7, 4382 FillCanvas = true 4383 }; 4384 productImage.CssClass += " thumb-list__image"; 4385 <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)"> 4386 <label for="GalleryModalTrigger" class="thumb-list__image-label"> 4387 @Render(productThumb) 4388 </label> 4389 </div> 4390 } 4391 </div> 4392 } 4393 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 4394 @using Dynamicweb.Core 4395 @using System 4396 @using System.Web 4397 @using System.Collections.Generic 4398 @using Dynamicweb.Rapido.Blocks 4399 @using Dynamicweb.Rapido.Blocks.Components.General 4400 4401 @functions { 4402 BlocksPage productAssetsPage = BlocksPage.GetBlockPage("Product"); 4403 } 4404 4405 @{ 4406 string productAssetsLayout = !String.IsNullOrEmpty(Pageview.AreaSettings.GetItem("ProductPage").GetString("ProductAssetsLayout")) ? Pageview.AreaSettings.GetItem("ProductPage").GetList("ProductAssetsLayout").SelectedValue : "Section"; 4407 productAssetsLayout = productAssetsLayout == "Ribbon" ? "Section" : productAssetsLayout; 4408 4409 if (productAssetsLayout != "hide") 4410 { 4411 Block productAssetsBlock = new Block() 4412 { 4413 Name = productAssetsLayout != "MainInformation" ? Translate("Product assets") : "", 4414 Id = "ProductAssets", 4415 SortId = 10, 4416 Template = RenderProductAssets(productAssetsLayout, downloadDocuments), @*downloadDocuments variable, declared in Product.cshtml and defined in Fields.cshtml*@ 4417 Design = new Design 4418 { 4419 Size = "12", 4420 RenderType = RenderType.Column, 4421 HidePadding = true 4422 } 4423 }; 4424 productAssetsPage.Add(productAssetsLayout, productAssetsBlock); 4425 } 4426 } 4427 4428 @helper RenderProductAssets(string layout, List<LoopItem> documents) 4429 { 4430 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("ProductAssetsLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 4431 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("ProductAssetsLayout").SelectedValue == "Ribbon" ? "u-padding--lg" : ""; 4432 string exportPageId = GetPageIdByNavigationTag("ProductExportFeed").ToString(); 4433 4434 //images 4435 4436 HashSet<string> images = new HashSet<string>(); 4437 4438 images.Add(GetProductImage()); 4439 4440 foreach (LoopItem alternativeImage in GetLoop("Ecom:Product.AlternativeImages")) 4441 { 4442 string alt_image = alternativeImage.GetString("Ecom:Product.AlternativeImages.Image"); 4443 4444 if (!string.IsNullOrEmpty(alt_image)) 4445 { 4446 images.Add(alt_image); 4447 } 4448 } 4449 4450 foreach (LoopItem detail in GetLoop("Details")) 4451 { 4452 string detail_image = detail.GetString("Ecom:Product:Detail.Image.Clean"); 4453 4454 if (!string.IsNullOrEmpty(detail_image)) 4455 { 4456 images.Add(detail_image); 4457 } 4458 } 4459 4460 <div class="product__section @ribbonClasses dw-mod"> 4461 <div class="product__description center-container @ribbonSubClasses dw-mod"> 4462 @if (layout == "Section") 4463 { 4464 @Render(new Heading { Title = Translate("Product assets"), Level = 2 }) 4465 } 4466 4467 <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"> 4468 <div class="grid"> 4469 @if (images.Count > 0) 4470 { 4471 <div class="grid__col-md-4 js-checkboxes-list"> 4472 @Render(new CheckboxField { Id = "allImages", OnChange = "selectAll(this)", Label = Translate("Images") + "(" + images.Count + ")" }) 4473 4474 <ul class="panel-list"> 4475 @foreach (string image in images) 4476 { 4477 @RenderProductPanelListItem(image) 4478 } 4479 </ul> 4480 </div> 4481 } 4482 4483 @if (documents.Count > 0) 4484 { 4485 <div class="grid__col-md-4 js-checkboxes-list"> 4486 @Render(new CheckboxField { Id = "allDocuments", OnChange = "selectAll(this)", Label = Translate("Documents") + "(" + documents.Count + ")" }) 4487 4488 <ul class="panel-list"> 4489 @foreach (LoopItem document in documents) 4490 { 4491 string fieldValue; 4492 if (!string.IsNullOrEmpty(document.GetString("Document.FullPath"))) 4493 { 4494 fieldValue = document.GetString("Product.CustomField.Value.Clean"); 4495 @RenderDocument(fieldValue) 4496 } 4497 if (document.GetString("Ecom:Product.CategoryField.TypeID") == "9") 4498 { 4499 fieldValue = document.GetString("Ecom:Product.CategoryField.Value"); 4500 @RenderDocument(fieldValue) 4501 } 4502 if (!string.IsNullOrEmpty(document.GetString("Ecom:Product:Detail.Image.Clean"))) 4503 { 4504 fieldValue = document.GetString("Ecom:Product:Detail.Image.Clean"); 4505 @RenderDocument(fieldValue) 4506 } 4507 } 4508 </ul> 4509 </div> 4510 } 4511 <div class="grid__col-md-4"> 4512 @Render(new HiddenField { Id = "ID", Name = "ID", Value = "532" }) 4513 @Render(new HiddenField { Id = "download", Name = "download", Value = "true" }) 4514 @Render(new HiddenField { Id = "siteUrl", Name = "siteUrl", Value = string.Format("{0}://{1}", GetGlobalValue("Global:Request.Scheme"), GetGlobalValue("Global:Request.Host")) }) 4515 4516 <div class="u-bold u-margin-bottom">@Translate("Export")</div> 4517 4518 @{ 4519 SelectField languageSelect = new SelectField 4520 { 4521 Id = "exportLanguage", 4522 Label = Translate("Language"), 4523 Name = "RequestLanguageId", 4524 CssClass = "u-full-width" 4525 }; 4526 foreach (var lang in Dynamicweb.Ecommerce.Services.Languages.GetLanguages().OrderBy(l => l.Name)) 4527 { 4528 var selected = lang.IsDefault ? true : false; 4529 languageSelect.Options.Add(new SelectFieldOption { Label = lang.Name, Value = lang.LanguageId, Checked = selected }); 4530 } 4531 @Render(languageSelect) 4532 4533 SelectField purposeSelect = new SelectField 4534 { 4535 Id = "purpose", 4536 Label = Translate("Image purpose"), 4537 Name = "purpose", 4538 CssClass = "u-full-width" 4539 }; 4540 purposeSelect.Options.Add(new SelectFieldOption { Label = Translate("Office"), Value = "Office" }); 4541 purposeSelect.Options.Add(new SelectFieldOption { Label = Translate("Original"), Value = "Original" }); 4542 purposeSelect.Options.Add(new SelectFieldOption { Label = Translate("Print"), Value = "Print" }); 4543 purposeSelect.Options.Add(new SelectFieldOption { Label = Translate("Web"), Value = "Web" }); 4544 @Render(purposeSelect) 4545 4546 SelectField formatSelect = new SelectField 4547 { 4548 Id = "exportFormat", 4549 Label = Translate("Export format"), 4550 Name = "format", 4551 CssClass = "u-full-width" 4552 }; 4553 formatSelect.Options.Add(new SelectFieldOption { Label = Translate("Csv"), Value = "csv" }); 4554 formatSelect.Options.Add(new SelectFieldOption { Label = Translate("Json"), Value = "json" }); 4555 formatSelect.Options.Add(new SelectFieldOption { Label = Translate("Xml"), Value = "xml" }); 4556 @Render(formatSelect) 4557 } 4558 4559 @Render(new Button { ButtonType = ButtonType.Submit, ButtonLayout = ButtonLayout.Primary, CssClass = "btn--full u-no-margin", Title = Translate("Download") }) 4560 </div> 4561 </div> 4562 </form> 4563 </div> 4564 </div> 4565 <script> 4566 function selectAll(checkbox) { 4567 checkbox.closest(".js-checkboxes-list").querySelectorAll(".js-checkbox").forEach(function (input) { 4568 input.checked = checkbox.checked; 4569 }); 4570 } 4571 </script> 4572 } 4573 4574 @helper RenderProductPanelListItem(string imageName) 4575 { 4576 <li class="panel-list__item"> 4577 <div class="panel-list__item-check"> 4578 <input id="Image_@imageName" name="Image_@imageName" type="checkbox" class="form__control u-no-margin dw-mod js-checkbox" /> 4579 <label for="Image_@imageName"></label> 4580 </div> 4581 <div class="panel-list__item-image"> 4582 <label for="Image_@imageName" class="u-no-margin"> 4583 @Render(new Image { Path = imageName, Title = Path.GetFileName(imageName), ImageDefault = new ImageSettings { Width = 55, Height = 55, Crop = 5, FillCanvas = true } }) 4584 </label> 4585 </div> 4586 <div class="panel-list__item-name"> 4587 <label for="Image_@imageName" class="u-truncate-text u-w170px" title="@Path.GetFileName(imageName)"> 4588 @Path.GetFileName(imageName) 4589 </label> 4590 </div> 4591 </li> 4592 } 4593 4594 @helper RenderDocument(string fieldValue) 4595 { 4596 <li class="panel-list__item"> 4597 <div class="panel-list__item-check"> 4598 <input id="Document_@fieldValue" name="Document_@fieldValue" type="checkbox" class="form__control u-no-margin js-checkbox dw-mod"> 4599 <label for="Document_@fieldValue"></label> 4600 </div> 4601 <div class="panel-list__item-name"> 4602 <label for="Document_@fieldValue" class="u-truncate-text u-no-margin u-max-w220px" title="@Path.GetFileName(fieldValue)"> 4603 @Path.GetFileName(fieldValue) 4604 </label> 4605 </div> 4606 </li> 4607 } 4608 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 4609 @using Dynamicweb.Core 4610 @using System 4611 @using System.Web 4612 @using System.Collections.Generic 4613 @using Dynamicweb.Rapido.Blocks 4614 @using Dynamicweb.Rapido.Blocks.Components.General 4615 4616 @functions { 4617 BlocksPage productGeneratePDFPage = BlocksPage.GetBlockPage("Product"); 4618 } 4619 4620 @{ 4621 string generatePDFLayout = !String.IsNullOrEmpty(Pageview.AreaSettings.GetItem("ProductPage").GetString("GeneratePDFLayout")) ? Pageview.AreaSettings.GetItem("ProductPage").GetList("GeneratePDFLayout").SelectedValue : "Section"; 4622 generatePDFLayout = generatePDFLayout == "Ribbon" ? "Section" : generatePDFLayout; 4623 4624 if (GetPageIdByNavigationTag("ProductPagePDFTemplates") > 0 && generatePDFLayout != "hide") 4625 { 4626 Block generatePDFBlock = new Block() 4627 { 4628 Name = generatePDFLayout != "MainInformation" ? Translate("Generate PDF") : "", 4629 Id = "GeneratePDF", 4630 SortId = 10, 4631 Template = RenderGeneratePDF(generatePDFLayout), 4632 Design = new Design 4633 { 4634 Size = "12", 4635 RenderType = RenderType.Column, 4636 HidePadding = true 4637 } 4638 }; 4639 4640 productGeneratePDFPage.Add(generatePDFLayout, generatePDFBlock); 4641 } 4642 } 4643 4644 @helper RenderGeneratePDF(string layout) 4645 { 4646 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("GeneratePDFLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 4647 ribbonClasses = layout == "Tabs" ? "" : ribbonClasses; 4648 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("GeneratePDFLayout").SelectedValue == "Ribbon" ? "center-container--ribbon" : ""; 4649 string exportPageId = GetPageIdByNavigationTag("ProductExportFeed").ToString(); 4650 int pdfFolderId = GetPageIdByNavigationTag("ProductPagePDFTemplates"); 4651 4652 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" }; 4653 form.Add(new HiddenField { Name = "siteUrl", Value = string.Format("{0}://{1}", GetGlobalValue("Global:Request.Scheme"), GetGlobalValue("Global:Request.Host")) }); 4654 4655 //Select languages 4656 SelectField languagesList = new SelectField 4657 { 4658 Id = "RequestLanguageID", 4659 Name = "RequestLanguageID", 4660 Label = Translate("Language"), 4661 CssClass = "u-full-width" 4662 }; 4663 4664 foreach (var lang in Dynamicweb.Ecommerce.Services.Languages.GetLanguages().OrderBy(l => l.Name)) 4665 { 4666 languagesList.Options.Add(new SelectFieldOption 4667 { 4668 Label = lang.Name, 4669 Value = lang.LanguageId, 4670 Checked = lang.IsDefault ? true : false 4671 }); 4672 } 4673 form.Add(languagesList); 4674 4675 //Select pages 4676 SelectField pagesList = new SelectField 4677 { 4678 Id = "PDFTemplate", 4679 Name = "ID", 4680 Label = Translate("Generate PDF"), 4681 CssClass = "u-full-width" 4682 }; 4683 4684 foreach (Dynamicweb.Content.Page page in ServiceLocator.Current.GetPageService().GetPagesByParentID(pdfFolderId)) 4685 { 4686 pagesList.Options.Add(new SelectFieldOption 4687 { 4688 Label = page.MenuText, 4689 Value = Converter.ToString(page.ID) 4690 }); 4691 } 4692 form.Add(pagesList); 4693 4694 form.Add(new Button { ButtonType = ButtonType.Submit, Title = Translate("Generate PDF"), CssClass = "btn--full u-no-margin" }); 4695 4696 <div class="product__section @ribbonClasses grid dw-mod"> 4697 <div class="dw-mod grid__col-md-4 @ribbonSubClasses"> 4698 @if (layout == "Section") 4699 { 4700 @Render(new Heading { Title = Translate("Generate PDF"), Level = 2 }) 4701 } 4702 @Render(form) 4703 </div> 4704 </div> 4705 } 4706 4707 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 4708 @using Dynamicweb.Core 4709 @using System 4710 @using System.Web 4711 @using System.Collections.Generic 4712 @using Dynamicweb.Rapido.Blocks 4713 @using Dynamicweb.Rapido.Blocks.Components.General 4714 4715 @functions { 4716 BlocksPage productDescriptionPage = BlocksPage.GetBlockPage("Product"); 4717 } 4718 4719 @{ 4720 string fullDesctiptionLayout = !String.IsNullOrEmpty(Pageview.AreaSettings.GetItem("ProductPage").GetString("FullDescriptionLayout")) ? Pageview.AreaSettings.GetItem("ProductPage").GetList("FullDescriptionLayout").SelectedValue : "Section"; 4721 fullDesctiptionLayout = fullDesctiptionLayout == "Ribbon" ? "Section" : fullDesctiptionLayout; 4722 4723 if (!string.IsNullOrEmpty(GetString("Ecom:Product.LongDescription")) && fullDesctiptionLayout != "hide") 4724 { 4725 Block detailsDescription = new Block() 4726 { 4727 Name = fullDesctiptionLayout != "MainInformation" ? Translate("Description") : "", 4728 Id = "FullDescription", 4729 SortId = 30, 4730 Template = RenderProductDescription(fullDesctiptionLayout), 4731 Design = new Design 4732 { 4733 Size = "12", 4734 RenderType = RenderType.Column, 4735 HidePadding = true 4736 } 4737 }; 4738 productDescriptionPage.Add(fullDesctiptionLayout, detailsDescription); 4739 } 4740 } 4741 4742 @helper RenderProductDescription(string layout) 4743 { 4744 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("FullDescriptionLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 4745 ribbonClasses = layout == "Tabs" ? "" : ribbonClasses; 4746 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("FullDescriptionLayout").SelectedValue == "Ribbon" ? "center-container--ribbon" : ""; 4747 4748 <div class="product__section @ribbonClasses dw-mod"> 4749 <div class="product__description center-container @ribbonSubClasses dw-mod"> 4750 @if (layout == "Section") { 4751 @Render(new Heading { Title = Translate("Description"), Level = 2 }) 4752 } 4753 @Render(new Text { Content = GetString("Ecom:Product.LongDescription") }) 4754 </div> 4755 </div> 4756 } 4757 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 4758 @using Dynamicweb.Core 4759 @using System 4760 @using System.Collections 4761 @using System.Web 4762 @using System.Globalization; 4763 @using System.Collections.Generic 4764 @using Dynamicweb.Content 4765 @using Dynamicweb.Content.Items 4766 @using Dynamicweb.Ecommerce.Products.Categories 4767 @using Dynamicweb.Ecommerce.Products.FieldDisplayGroups 4768 @using Dynamicweb.Ecommerce.Synchronization 4769 @using Dynamicweb.Rapido.Blocks 4770 @using VestjyskMarketing.Models 4771 @using Page = System.Web.UI.Page 4772 4773 4774 4775 @functions { 4776 BlocksPage productFieldsPage = BlocksPage.GetBlockPage("Product"); 4777 4778 4779 static string ConvertBytes(long bytes) 4780 { 4781 double size = bytes / 1024; //KB 4782 if (size > 1024) 4783 { 4784 size = (bytes / 1024f) / 1024f; //MB 4785 return string.Format("{0:n1} MB", size); 4786 } 4787 else 4788 { 4789 return string.Format("{0:n0} KB", size); 4790 } 4791 } 4792 4793 static bool isImage(string path) 4794 { 4795 return new List<string> { ".jpg", ".jpeg", ".gif", ".png", ".svg" }.Contains(Path.GetExtension(path).ToLower()); 4796 } 4797 4798 string getIconForFile(string fileName) 4799 { 4800 string ext = Path.GetExtension(fileName); 4801 string icon = ""; 4802 switch (ext.ToLower()) 4803 { 4804 case ".xls": 4805 case ".xlsx": 4806 icon = "fa-file-excel"; 4807 break; 4808 case ".ppt": 4809 case ".pptx": 4810 icon = "fa-file-powerpoint"; 4811 break; 4812 case ".doc": 4813 case ".docx": 4814 icon = "fa-file-word"; 4815 break; 4816 case ".jpg": 4817 case ".jpeg": 4818 case ".png": 4819 case ".gif": 4820 case ".pdf": 4821 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 + "' />"; 4822 default: 4823 icon = "fa-file"; 4824 break; 4825 } 4826 return "<i class='product__document-icon far " + icon + "'></i> "; 4827 } 4828 4829 } 4830 4831 @*downloadDocuments variable, declared in Product.cshtml - this variable also will be used in ProductAssets.cshtml*@ 4832 4833 4834 4835 @{ 4836 var selectedDownloadCategories = Pageview.AreaSettings.GetItem("ProductPage").GetList("DownloadAssets").SelectedValues; 4837 var downloadsFromAssets = GetLoop("ImageCategories").Where(x => selectedDownloadCategories.Contains(x.GetString("Category.Id"))); 4838 4839 if (string.IsNullOrEmpty(selectedDownloadCategories.ToString())) 4840 { 4841 foreach (LoopItem customField in GetLoop("CustomFieldValues")) 4842 { 4843 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") 4844 { 4845 if (!string.IsNullOrEmpty(customField.GetString("Document.FullPath"))) 4846 { 4847 downloadDocuments.Add(customField); 4848 } 4849 } 4850 } 4851 4852 foreach (LoopItem customField in GetLoop("ProductCategories")) 4853 { 4854 foreach (LoopItem field in customField.GetLoop("ProductCategoryFields")) 4855 { 4856 if (!string.IsNullOrEmpty(field.GetString("Ecom:Product.CategoryField.Label")) && !string.IsNullOrEmpty(field.GetString("Ecom:Product.CategoryField.Value"))) 4857 { 4858 if (field.GetString("Ecom:Product.CategoryField.TypeID") == "9") 4859 { 4860 downloadDocuments.Add(field); 4861 } 4862 } 4863 } 4864 } 4865 } 4866 else 4867 { 4868 foreach (LoopItem category in downloadsFromAssets) 4869 { 4870 foreach (LoopItem asset in category.GetLoop("Category.Images")) 4871 { 4872 downloadDocuments.Add(asset); 4873 } 4874 } 4875 } 4876 4877 bool collectAllDownloads = Pageview.AreaSettings.GetItem("ProductPage").GetString("CollectAllDownloads") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("CollectAllDownloads") : true; 4878 string detailFieldsLayout = Pageview.AreaSettings.GetItem("ProductPage").GetList("DetailFieldsLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("DetailFieldsLayout").SelectedValue : "Section"; 4879 detailFieldsLayout = detailFieldsLayout == "Ribbon" || string.IsNullOrEmpty(detailFieldsLayout) ? "Section" : detailFieldsLayout; 4880 string categoryFieldsLayout = Pageview.AreaSettings.GetItem("ProductPage").GetList("CategoryFieldsLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("CategoryFieldsLayout").SelectedValue : "Section"; 4881 categoryFieldsLayout = categoryFieldsLayout == "Ribbon" || string.IsNullOrEmpty(categoryFieldsLayout) ? "Section" : categoryFieldsLayout; 4882 string displayGroupsLayout = Pageview.AreaSettings.GetItem("ProductPage").GetList("DisplayGroupsLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("DisplayGroupsLayout").SelectedValue : "Section"; 4883 displayGroupsLayout = displayGroupsLayout == "Ribbon" || string.IsNullOrEmpty(displayGroupsLayout) ? "Section" : displayGroupsLayout; 4884 string downloadsFieldsLayout = Pageview.AreaSettings.GetItem("ProductPage").GetList("DownloadsLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("DownloadsLayout").SelectedValue : "Section"; 4885 downloadsFieldsLayout = downloadsFieldsLayout == "Ribbon" || string.IsNullOrEmpty(downloadsFieldsLayout) ? "Section" : downloadsFieldsLayout; 4886 4887 string detailFieldsView = Pageview.AreaSettings.GetItem("ProductPage").GetList("DetailFieldsView") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("DetailFieldsView").SelectedValue : "grid"; 4888 string categoryFieldsView = Pageview.AreaSettings.GetItem("ProductPage").GetList("CategoryFieldsView") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("CategoryFieldsView").SelectedValue : "grid"; 4889 string downloadsFieldsView = Pageview.AreaSettings.GetItem("ProductPage").GetList("DownloadsFieldsView") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("DownloadsFieldsView").SelectedValue : "grid"; 4890 4891 if (GetLoop("CustomFieldValues").Count > 0 && detailFieldsLayout != "hide") 4892 { 4893 if (string.IsNullOrEmpty(Pageview.AreaSettings.GetItem("ProductPage").GetString("ProductDetailFields"))) 4894 { 4895 Block detailsCustom = new Block() 4896 { 4897 Name = detailFieldsLayout != "MainInformation" ? Translate("Details") : "", 4898 Id = "CustomFields", 4899 SortId = 30, 4900 Design = new Design 4901 { 4902 Size = "12", 4903 RenderType = RenderType.Column, 4904 HidePadding = true 4905 } 4906 }; 4907 4908 detailsCustom.Template = RenderProductSection(detailFieldsLayout, detailFieldsView, Translate("Information"), RenderCustomFields(GetLoop("CustomFieldValues"), detailFieldsView)); 4909 productFieldsPage.Add(detailFieldsLayout, detailsCustom); 4910 } 4911 else 4912 { 4913 var detailFieldsDisplayGroups = Pageview.AreaSettings.GetItem("ProductPage").GetList("ProductDetailFields").SelectedValues; 4914 var displayGroups = GetLoop("FieldDisplayGroups").Where(x => detailFieldsDisplayGroups.Contains(x.GetString("Ecom:FieldDisplayGroup.ID"))); 4915 4916 4917 foreach (var group in displayGroups) 4918 { 4919 Block detailsCustom = new Block() 4920 { 4921 Name = detailFieldsLayout != "MainInformation" ? group.GetString("Ecom:FieldDisplayGroup.Name") : "", 4922 Id = "DetailFields_" + group.GetString("Ecom:FieldDisplayGroup.ID"), 4923 SortId = 30, 4924 Design = new Design 4925 { 4926 Size = "12", 4927 RenderType = RenderType.Column, 4928 HidePadding = true 4929 } 4930 }; 4931 4932 detailsCustom.Template = RenderProductSection(detailFieldsLayout, detailFieldsView, Translate("Information"), RenderDetailsFields(group.GetLoop("Fields"), detailFieldsView)); 4933 productFieldsPage.Add(detailFieldsLayout, detailsCustom); 4934 } 4935 } 4936 } 4937 4938 if (categoryFieldsLayout != "hide") 4939 { 4940 foreach (LoopItem categoryGroup in GetLoop("ProductCategories")) 4941 { 4942 bool hasFields = categoryGroup.GetLoop("ProductCategoryFields").FirstOrDefault(cf => !string.IsNullOrEmpty(cf.GetString("Ecom:Product.CategoryField.Value"))) != null; 4943 4944 4945 if (collectAllDownloads) 4946 { 4947 int downloadableCount = 0; 4948 foreach (LoopItem field in categoryGroup.GetLoop("ProductCategoryFields")) 4949 { 4950 if (field.GetString("Ecom:Product.CategoryField.TypeID") == "9") 4951 { 4952 downloadableCount++; 4953 } 4954 } 4955 4956 if (downloadableCount == categoryGroup.GetLoop("ProductCategoryFields").Count) 4957 { 4958 hasFields = false; 4959 } 4960 } 4961 4962 //hasFields needs to be true, if not description will not be shown, even if it is not empty 4963 hasFields = true; 4964 4965 if (hasFields) 4966 { 4967 Block detailsCategoryFields = new Block() 4968 { 4969 Name = categoryFieldsLayout != "MainInformation" ? categoryGroup.GetString("Ecom:Product.Category.Name") : "", 4970 Id = ToPascalCase(categoryGroup.GetString("Ecom:Product.Category.Name")), 4971 SortId = 40, 4972 Template = RenderProductSection(categoryFieldsLayout, categoryFieldsView, categoryGroup.GetString("Ecom:Product.Category.Name"), RenderProductCategoryFields(categoryGroup.GetLoop("ProductCategoryFields"), categoryFieldsView)), 4973 Design = new Design 4974 { 4975 Size = "12", 4976 RenderType = RenderType.Column, 4977 HidePadding = true 4978 } 4979 }; 4980 4981 productFieldsPage.Add(categoryFieldsLayout, detailsCategoryFields); 4982 } 4983 } 4984 } 4985 4986 if (displayGroupsLayout != "hide") 4987 { 4988 var detailFieldsDisplayGroups = Pageview.AreaSettings.GetItem("ProductPage").GetList("ProductDetailFields").SelectedValues; 4989 var displayGroups = GetLoop("FieldDisplayGroups").Where(x => !detailFieldsDisplayGroups.Contains(x.GetString("Ecom:FieldDisplayGroup.ID"))); 4990 4991 4992 foreach (LoopItem group in displayGroups) 4993 { 4994 int fieldsCount = 0; 4995 4996 foreach (LoopItem field in group.GetLoop("Fields")) 4997 { 4998 if (!string.IsNullOrEmpty(field.GetString("Ecom:FieldDisplayGroup.Field.Name")) && !string.IsNullOrEmpty(field.GetString("Ecom:FieldDisplayGroup.Field.Value"))) 4999 { 5000 fieldsCount++; 5001 } 5002 } 5003 5004 if (fieldsCount != 0) 5005 { 5006 Block displayGroup = new Block() 5007 { 5008 Name = displayGroupsLayout != "MainInformation" ? group.GetString("Ecom:FieldDisplayGroup.Name") : "", 5009 Id = "DisplayGroup_" + group.GetString("Ecom:FieldDisplayGroup.ID"), 5010 SortId = 40, 5011 Template = RenderProductSection(displayGroupsLayout, categoryFieldsView, group.GetString("Ecom:FieldDisplayGroup.Name"), RenderDetailsFields(group.GetLoop("Fields"), categoryFieldsView)), 5012 Design = new Design 5013 { 5014 Size = "12", 5015 RenderType = RenderType.Column, 5016 HidePadding = true 5017 } 5018 }; 5019 productFieldsPage.Add(displayGroupsLayout, displayGroup); 5020 } 5021 else 5022 { 5023 Block displayGroup = new Block() 5024 { 5025 Name = displayGroupsLayout != "MainInformation" ? group.GetString("Ecom:FieldDisplayGroup.Name") : "", 5026 Id = "DisplayGroup_" + group.GetString("Ecom:FieldDisplayGroup.ID"), 5027 SortId = 40, 5028 Template = RenderProductDescription(displayGroupsLayout, categoryFieldsView, group.GetString("Ecom:FieldDisplayGroup.Name"), RenderDetailsFields(group.GetLoop("Fields"), categoryFieldsView)), 5029 Design = new Design 5030 { 5031 Size = "12", 5032 RenderType = RenderType.Column, 5033 HidePadding = true 5034 } 5035 }; 5036 productFieldsPage.Add(displayGroupsLayout, displayGroup); 5037 } 5038 } 5039 } 5040 5041 if (downloadDocuments.Count > 0 && downloadsFieldsLayout != "hide" && collectAllDownloads == true) 5042 { 5043 Block detailsDownloads = new Block() 5044 { 5045 Name = downloadsFieldsLayout != "MainInformation" ? Translate("Downloads") : "", 5046 Id = "StandardDownloads", 5047 SortId = 50, 5048 Template = RenderProductSection(downloadsFieldsLayout, downloadsFieldsView, Translate("Downloads"), RenderProductDownloadsFields(downloadDocuments, downloadsFieldsView)), 5049 Design = new Design 5050 { 5051 Size = "12", 5052 RenderType = RenderType.Column, 5053 HidePadding = true 5054 } 5055 }; 5056 5057 productFieldsPage.Add(downloadsFieldsLayout, detailsDownloads); 5058 } 5059 } 5060 5061 @helper RenderCustomFields(List<LoopItem> fieldsLoop, string viewType) 5062 { 5063 bool collectAllDownloads = Pageview.AreaSettings.GetItem("ProductPage").GetString("CollectAllDownloads") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("CollectAllDownloads") : true; 5064 5065 foreach (LoopItem customField in fieldsLoop) 5066 { 5067 string fieldValue = customField.GetString("Product.CustomField.Value.Clean"); 5068 fieldValue = fieldValue == "False" ? Translate("No") : fieldValue; 5069 fieldValue = fieldValue == "True" ? Translate("Yes") : fieldValue; 5070 5071 if (customField.GetLoop("Product.CustomField.Options").Count > 0) 5072 { 5073 List<string> accumulatedValues = new List<string>(); 5074 5075 foreach (var option in customField.GetLoop("Product.CustomField.Options")) 5076 { 5077 if (option.GetBoolean("Product.CustomField.Option.IsSelected")) 5078 { 5079 accumulatedValues.Add(option.GetString("Product.CustomField.Option.Name")); 5080 } 5081 } 5082 fieldValue = string.Join(", ", accumulatedValues); 5083 } 5084 5085 if (!string.IsNullOrEmpty(customField.GetString("Product.CustomField.Name")) && !string.IsNullOrEmpty(fieldValue) && customField.GetString("Product.CustomField.Name") != "Custom sticker" && customField.GetString("Product.CustomField.Name") != "RRP") 5086 { 5087 if (string.IsNullOrEmpty(customField.GetString("Document.FullPath"))) 5088 { 5089 @RenderFieldItem(customField.GetString("Product.CustomField.Name"), fieldValue, viewType) 5090 ; 5091 } 5092 else if (collectAllDownloads == false) 5093 { 5094 @RenderFieldItem(customField.GetString("Product.CustomField.Name"), fieldValue, viewType, "download") 5095 ; 5096 } 5097 } 5098 } 5099 } 5100 5101 @helper RenderProductSection(string layout, string viewType, string name, RazorEngine.Templating.TemplateWriter writer) 5102 { 5103 string ribbonClasses = layout == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 5104 ribbonClasses = layout == "Tabs" ? "" : ribbonClasses; 5105 string ribbonSubClasses = layout == "Ribbon" ? "center-container--ribbon" : ""; 5106 5107 5108 <div class="product__section @ribbonClasses dw-mod js-product-detail-info"> 5109 5110 <div class="center-container @ribbonSubClasses dw-mod"> 5111 @if (viewType != "table") 5112 { 5113 <div class="grid grid--bleed u-margin-bottom--lg"> 5114 5115 </div> 5116 } 5117 else 5118 { 5119 string tableWidth = layout != "MainInformation" ? "grid__col-md-6" : "grid__col-md-12"; 5120 5121 5122 Dynamicweb.Ecommerce.Products.ProductService productService = new Dynamicweb.Ecommerce.Products.ProductService(); 5123 5124 var product = productService.GetProductById(GetString("Ecom:Product.ID"), GetString("Ecom:Product.VariantID"), GetString("Ecom:Product.LanguageID")); 5125 var categoryService = new ProductCategoryService(); 5126 5127 5128 List<string> labels = new List<string>(); 5129 List<string> values = new List<string>(); 5130 5131 if (categoryService.GetCategories(product, true) != null && categoryService.GetCategories(product, true).FirstOrDefault() != null) 5132 { 5133 var data = categoryService.GetCategories(product, true).FirstOrDefault().Fields.ToArray(); 5134 5135 5136 if (data != null) 5137 { 5138 foreach (var field in data) 5139 { 5140 var lang = GetString("Ecom:Product.LanguageID"); 5141 5142 if (categoryService.GetProductCategoryFieldValue(product, field).Value != null) 5143 { 5144 var fieldData = categoryService.GetProductCategoryFieldValue(product, field).Value.ToString(); 5145 labels.Add(field.GetLabel(lang)); 5146 values.Add((fieldData)); 5147 } 5148 } 5149 } 5150 } 5151 5152 5153 if (name != "") 5154 { 5155 @* Details about the product card *@ 5156 <div class="grid u-margin-bottom--lg nc-grid"> 5157 <div class="@tableWidth grid__col-sm-12 grid__col-xs-12 table__white extra-specs br-25" id="ProductDetails"> 5158 <table class="table--no-borders"> 5159 <h3>@Translate("ProductDetails", "Detaljer om produktet")</h3> 5160 <div class="more-info"> 5161 @GetString("Ecom:Product.LongDescription") 5162 5163 </div> 5164 <button class="expand-info--box accordion" data-info="@Translate("DataInfo", "Udvid info")" data-info-close="@Translate("DataInfoClose", "Fold info ind")"> 5165 </button> 5166 </table> 5167 5168 </div> 5169 </div> 5170 if (labels.Count > 1) 5171 { 5172 @* Specifications for the product card *@ 5173 <div class="grid u-margin-bottom--lg nc-grid"> 5174 <div class="@tableWidth grid__col-sm-12 grid__col-xs-12 table__white extra-specs br-25" id="ProductSpecs"> 5175 <table class="table--no-borders"> 5176 <h3>@Translate("ProductSpecs", "Specifikationer")</h3> 5177 <tbody> 5178 @for (int i = 0; i < labels.Count; i++) 5179 { 5180 if (!string.IsNullOrEmpty(values[i]) && !string.IsNullOrEmpty(labels[i])) 5181 { 5182 <tr> 5183 <th style="padding: 0">@labels[i]</th> 5184 @if (values[i] == "True") 5185 { 5186 <td style="padding: 0">@Translate("Yes")</td> 5187 } 5188 else if (values[i] == "False") 5189 { 5190 <td style="padding: 0">@Translate("No")</td> 5191 } 5192 else 5193 { 5194 <td style="padding: 0">@values[i]</td> 5195 } 5196 </tr> 5197 } 5198 } 5199 5200 </tbody> 5201 <button class="expand-info--box accordion" data-info="@Translate("DataInfo", "Udvid info")" data-info-close="@Translate("DataInfoClose", "Fold info ind")"> 5202 </button> 5203 </table> 5204 </div> 5205 </div> 5206 } 5207 5208 @* Guarantee for the product card *@ 5209 string pageLink = GetString("Ecom:Product:Field.ProductGuarantee"); 5210 string pageUrl = !string.IsNullOrEmpty(pageLink) ? pageLink.Split('=')[1] : ""; 5211 int pageId; 5212 bool productGuaranteeFound = Int32.TryParse(pageUrl, out pageId); 5213 5214 if (productGuaranteeFound) 5215 { 5216 ItemService itemService = new ItemService(); 5217 var productGuarantee = itemService.GetItemByPageId(pageId, false); 5218 5219 if (productGuarantee != null && productGuarantee["ProductGuarantees"] != null) 5220 { 5221 int productGuaranteeListId = (int)productGuarantee["ProductGuarantees"]; 5222 var productGuaranteeList = ItemList.GetItemListById(productGuaranteeListId).Relations; 5223 5224 foreach (Item productGuaranteeModule in productGuaranteeList) 5225 { 5226 string guaranteeVideo = (string)productGuaranteeModule["Video"]; 5227 string guaranteeImage = (string)productGuaranteeModule["Image"]; 5228 string guaranteeImageAlt = (string)productGuaranteeModule["ImageAlt"]; 5229 string guaranteeText = (string)productGuaranteeModule["Text"]; 5230 5231 bool textIsEmpty = string.IsNullOrEmpty(guaranteeText); 5232 bool onlyText = string.IsNullOrEmpty(guaranteeImage) && string.IsNullOrEmpty(guaranteeVideo); 5233 5234 5235 <div class="grid u-margin-bottom--lg nc-grid"> 5236 <div class="@tableWidth grid__col-sm-12 grid__col-xs-12 padding-none br-25" id="ProductGuarantee"> 5237 5238 @if (!string.IsNullOrEmpty(guaranteeVideo)) 5239 { 5240 <video class="@(textIsEmpty ? "br-25" :"br-top-25")" muted="" playsinline="" disablepictureinpicture="" width="1920" height="auto" autoplay="true" loop> 5241 <source src="@guaranteeVideo" type="video/mp4"> 5242 </video> 5243 } 5244 else 5245 { 5246 <img class="guarantee-image @(textIsEmpty ? "br-25" :"br-25-top")" src="@guaranteeImage" alt="@guaranteeImageAlt"/> 5247 } 5248 5249 @if (!string.IsNullOrEmpty(guaranteeText)) 5250 { 5251 <div class="guarantee-text @(onlyText ? "br-25" :"br-25-bottom")"> 5252 @guaranteeText 5253 </div> 5254 } 5255 </div> 5256 </div> 5257 } 5258 } 5259 } 5260 } 5261 } 5262 </div> 5263 </div> 5264 } 5265 5266 @helper RenderProductDescription(string layout, string viewType, string name, RazorEngine.Templating.TemplateWriter writer, int fieldsCount = 0) 5267 { 5268 string ribbonClasses = layout == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 5269 ribbonClasses = layout == "Tabs" ? "" : ribbonClasses; 5270 string ribbonSubClasses = layout == "Ribbon" ? "center-container--ribbon" : ""; 5271 5272 5273 <div class="product__section @ribbonClasses dw-mod js-product-detail-info"> 5274 <div class="center-container @ribbonSubClasses dw-mod"> 5275 @if (viewType != "table") 5276 { 5277 <div class="grid grid--bleed u-margin-bottom--lg"> 5278 5279 @writer 5280 </div> 5281 } 5282 else 5283 { 5284 string tableWidth = layout != "MainInformation" ? "grid__col-md-6" : "grid__col-md-12"; 5285 5286 @* Details about the product card *@ 5287 <div class="grid u-margin-bottom--lg nc-grid"> 5288 <div class="@tableWidth grid__col-sm-12 grid__col-xs-12 table__white extra-specs" id="ProductDetails"> 5289 <table class="table--no-borders"> 5290 <h3>@Translate("ProductDetails", "Detaljer om produktet")</h3> 5291 <div class="more-info"> 5292 @GetString("Ecom:Product.LongDescription") 5293 </div> 5294 <button class="expand-info--box accordion" data-info="@Translate("DataInfo", "Udvid info")" data-info-close="@Translate("DataInfoClose", "Fold info ind")"> 5295 </button> 5296 </table> 5297 5298 </div> 5299 </div> 5300 } 5301 </div> 5302 </div> 5303 } 5304 5305 @helper RenderProductCategoryFields(List<LoopItem> fieldsLoop, string viewType) 5306 { 5307 bool collectAllDownloads = Pageview.AreaSettings.GetItem("ProductPage").GetString("CollectAllDownloads") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("CollectAllDownloads") : true; 5308 5309 foreach (LoopItem categoryField in fieldsLoop) 5310 { 5311 string fieldValue = categoryField.GetString("Ecom:Product.CategoryField.Value"); 5312 fieldValue = fieldValue == "False" ? Translate("No") : fieldValue; 5313 fieldValue = fieldValue == "True" ? Translate("Yes") : fieldValue; 5314 5315 if (!string.IsNullOrEmpty(categoryField.GetString("Ecom:Product.CategoryField.Label")) && !string.IsNullOrEmpty(fieldValue)) 5316 { 5317 if (categoryField.GetString("Ecom:Product.CategoryField.TypeID") != "9" || collectAllDownloads == false) 5318 { 5319 if (categoryField.GetString("Ecom:Product.CategoryField.TypeID") == "15") 5320 { 5321 @RenderFieldItem(categoryField.GetString("Ecom:Product.CategoryField.Label"), categoryField.GetString("Ecom:Product.CategoryField.OptionLabel"), viewType) 5322 ; 5323 } 5324 else if (categoryField.GetString("Ecom:Product.CategoryField.TypeID") == "8") 5325 { 5326 @RenderFieldItem(categoryField.GetString("Ecom:Product.CategoryField.Label"), fieldValue, viewType, "link") 5327 ; 5328 } 5329 else if (categoryField.GetString("Ecom:Product.CategoryField.TypeID") == "9") 5330 { 5331 @RenderFieldItem(categoryField.GetString("Ecom:Product.CategoryField.Label"), fieldValue, viewType, "download") 5332 ; 5333 } 5334 else 5335 { 5336 @RenderFieldItem(categoryField.GetString("Ecom:Product.CategoryField.Label"), fieldValue, viewType) 5337 ; 5338 } 5339 } 5340 } 5341 } 5342 } 5343 5344 @helper RenderDetailsFields(IEnumerable<LoopItem> fields, string viewType) 5345 { 5346 foreach (LoopItem field in fields) 5347 { 5348 string fieldValue = field.GetString("Ecom:FieldDisplayGroup.Field.Value"); 5349 fieldValue = fieldValue == "False" ? Translate("No") : fieldValue; 5350 fieldValue = fieldValue == "True" ? Translate("Yes") : fieldValue; 5351 5352 if (!string.IsNullOrEmpty(field.GetString("Ecom:FieldDisplayGroup.Field.Name")) && !string.IsNullOrEmpty(fieldValue)) 5353 { 5354 if (field.GetString("Ecom:FieldDisplayGroup.Field.TypeId") == "15") 5355 { 5356 @RenderFieldItem(field.GetString("Ecom:FieldDisplayGroup.Field.Name"), field.GetString("Ecom:FieldDisplayGroup.Field.OptionLabel"), viewType) 5357 ; 5358 } 5359 else if (field.GetString("Ecom:FieldDisplayGroup.Field.TypeId") == "8") 5360 { 5361 @RenderFieldItem(field.GetString("Ecom:Product.CategoryField.Name"), fieldValue, viewType, "link") 5362 ; 5363 } 5364 else if (field.GetString("Ecom:FieldDisplayGroup.Field.TypeId") == "9") 5365 { 5366 @RenderFieldItem(field.GetString("Ecom:FieldDisplayGroup.Field.Name"), fieldValue, viewType, "download") 5367 ; 5368 } 5369 else 5370 { 5371 @RenderFieldItem(field.GetString("Ecom:FieldDisplayGroup.Field.Name"), fieldValue, viewType) 5372 ; 5373 } 5374 } 5375 } 5376 } 5377 5378 @helper RenderProductDownloadsFields(List<LoopItem> fieldsLoop, string viewType) 5379 { 5380 foreach (LoopItem document in fieldsLoop) 5381 { 5382 string fieldValue; 5383 if (!string.IsNullOrEmpty(document.GetString("Document.FullPath"))) 5384 { 5385 fieldValue = document.GetString("Product.CustomField.Value.Clean"); 5386 @RenderFieldItem(fieldValue, document.GetString("Document.FullPath"), viewType, "download") 5387 } 5388 5389 if (document.GetString("Ecom:Product.CategoryField.TypeID") == "9") 5390 { 5391 fieldValue = document.GetString("Ecom:Product.CategoryField.Value"); 5392 @RenderFieldItem(fieldValue, fieldValue, viewType, "download") 5393 } 5394 if (!string.IsNullOrEmpty(document.GetString("Ecom:Product:Detail.Image.Clean"))) 5395 { 5396 fieldValue = document.GetString("Ecom:Product:Detail.Image.Clean"); 5397 @RenderFieldItem("", fieldValue, viewType, "download") 5398 } 5399 } 5400 } 5401 5402 @helper RenderFieldItem(string name, string value, string viewType, string fieldType = "clean") 5403 { 5404 if (viewType != "table") 5405 { 5406 string fieldColumns = viewType == "list" ? "12" : "4"; 5407 <div class="grid__col-md-@fieldColumns grid__col-sm-12 u-margin-bottom"> 5408 <div class="u-bold"> 5409 @name 5410 </div> 5411 <div> 5412 @RenderFieldItemContent(name, value, fieldType) 5413 </div> 5414 </div> 5415 } 5416 else 5417 { 5418 <tr> 5419 <th>@name</th> 5420 <td> 5421 @RenderFieldItemContent(name, value, fieldType) 5422 </td> 5423 </tr> 5424 } 5425 } 5426 5427 @helper RenderFieldItemContent(string name, string value, string fieldType = "clean") 5428 { 5429 if (fieldType == "link") 5430 { 5431 <a target="_blank" rel="noopener" href="@value"> 5432 @if (isImage(value)) 5433 { 5434 @getIconForFile(value) 5435 } 5436 else 5437 { 5438 @value 5439 } 5440 </a> 5441 } 5442 else if (fieldType == "download") 5443 { 5444 FileInfo info = new FileInfo(Dynamicweb.Core.SystemInformation.MapPath(value)); 5445 5446 if (info.Exists) 5447 { 5448 <div class="grid grid--no-wrap"> 5449 <a href="@value" download title="@Translate("Download")" class="product__document dw-mod">@getIconForFile(value)</a> 5450 <div class="product__document-info dw-mod"> 5451 <a href="@value" download title="@Translate("Download")" class="product__document dw-mod">@Path.GetFileName(value)</a> 5452 <small class="u-block u-margin-top">@ConvertBytes(info.Length)</small> 5453 </div> 5454 </div> 5455 } 5456 } 5457 else 5458 { 5459 @value 5460 } 5461 } 5462 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 5463 @using Dynamicweb.Core 5464 @using System.Text.RegularExpressions 5465 @using System 5466 @using System.Web 5467 @using System.Collections.Generic 5468 @using Dynamicweb.Rapido.Blocks 5469 @using Dynamicweb.Rapido.Blocks.Components.General 5470 5471 @functions{ 5472 BlocksPage productVideoPage = BlocksPage.GetBlockPage("Product"); 5473 } 5474 5475 @{ 5476 var selectedVideoCategories = Pageview.AreaSettings.GetItem("ProductPage").GetList("VideoAssets").SelectedValues; 5477 var videosFromAssets = GetLoop("ImageCategories").Where(x => selectedVideoCategories.Contains(x.GetString("Category.Id"))); 5478 5479 string videosLayout = Pageview.AreaSettings.GetItem("ProductPage").GetList("VideosLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("VideosLayout").SelectedValue : "Section"; 5480 videosLayout = videosLayout == "Ribbon" || string.IsNullOrEmpty(videosLayout) ? "Section" : videosLayout; 5481 5482 int videosCount = 0; 5483 5484 if (videosFromAssets != null) 5485 { 5486 foreach (LoopItem category in videosFromAssets) { 5487 foreach (LoopItem asset in category.GetLoop("Category.Images")) { 5488 videosCount++; 5489 } 5490 } 5491 } else { 5492 foreach (LoopItem detailField in GetLoop("Details")) 5493 { 5494 if (detailField.GetString("Ecom:Product:Detail.Text").IndexOf("iframe") != -1 && detailField.GetString("Ecom:Product:Detail.Text").IndexOf("youtube.com/embed") != -1) 5495 { 5496 videosCount++; 5497 } 5498 if (detailField.GetString("Ecom:Product:Detail.Text").IndexOf("iframe") != -1 && detailField.GetString("Ecom:Product:Detail.Text").IndexOf("vimeo.com") != -1) 5499 { 5500 videosCount++; 5501 } 5502 } 5503 } 5504 5505 if (videosCount > 0 && videosLayout != "hide") 5506 { 5507 Block detailsVideos = new Block() 5508 { 5509 Name = videosLayout != "MainInformation" ? Translate("Videos") : "", 5510 Id = "Videos", 5511 SortId = 60, 5512 Template = RenderProductVideos(videosCount, videosLayout), 5513 Design = new Design 5514 { 5515 Size = "12", 5516 RenderType = RenderType.Column, 5517 HidePadding = true 5518 } 5519 }; 5520 productVideoPage.Add(videosLayout, detailsVideos); 5521 } 5522 } 5523 5524 @helper RenderProductVideos(int videosCount, string layout) { 5525 var selectedVideoCategories = Pageview.AreaSettings.GetItem("ProductPage").GetList("VideoAssets").SelectedValues; 5526 var videosFromAssets = GetLoop("ImageCategories").Where(x => selectedVideoCategories.Contains(x.GetString("Category.Id"))); 5527 5528 string videoColumn = "12"; 5529 videoColumn = videosCount == 2 ? "6" : videoColumn; 5530 videoColumn = videosCount > 2 ? "4" : videoColumn; 5531 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("VideosLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 5532 ribbonClasses = layout == "Tabs" ? "" : ribbonClasses; 5533 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("VideosLayout").SelectedValue == "Ribbon" ? "center-container--ribbon" : ""; 5534 5535 <div class="product__section @ribbonClasses dw-mod"> 5536 <div class="center-container @ribbonSubClasses dw-mod"> 5537 @if (layout == "Section") { 5538 @Render(new Heading { Title = Translate("Videos"), Level = 2 }) 5539 } 5540 5541 <div class="grid u-margin-bottom--lg"> 5542 @if (videosFromAssets != null) { 5543 foreach (LoopItem category in videosFromAssets) { 5544 foreach (LoopItem asset in category.GetLoop("Category.Images")) { 5545 //getting video ID from youtube URL 5546 string videoCode = asset.GetString("Ecom:Product:Detail.Image.Clean"); 5547 Regex regex = new Regex(@".be\/(.[^?]*)"); 5548 Match match = regex.Match(videoCode); 5549 string videoId = ""; 5550 if (match.Success) 5551 { 5552 videoId = match.Groups[1].Value; 5553 } 5554 else 5555 { 5556 regex = new Regex(@"v=([^&]+)"); 5557 match = regex.Match(videoCode); 5558 if (match.Success) 5559 { 5560 videoId = match.Groups[1].Value; 5561 } 5562 } 5563 5564 <div class="grid__col-md-@videoColumn grid__col-lg-@videoColumn"> 5565 <div class="video-wrapper"> 5566 <div class="js-youtube-video" data-video="@videoId" id="ytPlayer@(Guid.NewGuid().ToString("N"))" data-auto-play="False" data-enable-controls="1"></div> 5567 </div> 5568 </div> 5569 } 5570 } 5571 } else { 5572 foreach (LoopItem detailField in GetLoop("Details")) 5573 { 5574 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) 5575 { 5576 <div class="grid__col-md-@videoColumn grid__col-lg-@videoColumn"> 5577 <div class="video-wrapper"> 5578 @detailField.GetString("Ecom:Product:Detail.Text") 5579 </div> 5580 </div> 5581 } 5582 } 5583 } 5584 </div> 5585 </div> 5586 </div> 5587 } 5588 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 5589 @using Dynamicweb.Core 5590 @using System 5591 @using System.Web 5592 @using System.Collections.Generic 5593 @using Denform.Website.CustomModules 5594 @using Dynamicweb.Rapido.Blocks 5595 @using Dynamicweb.Rapido.Blocks.Components.Ecommerce 5596 @using Dynamicweb.Rapido.Blocks.Components.General 5597 @using Dynamicweb.Rapido.Services 5598 5599 5600 @functions{ 5601 BlocksPage productRelatedPage = BlocksPage.GetBlockPage("Product"); 5602 } 5603 5604 @{ 5605 string relatedProductsLayout = Pageview.AreaSettings.GetItem("ProductPage").GetList("RelatedProductsLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("RelatedProductsLayout").SelectedValue : "Section"; 5606 relatedProductsLayout = relatedProductsLayout == "Ribbon" || string.IsNullOrEmpty(relatedProductsLayout) ? "Section" : relatedProductsLayout; 5607 bool relatedShowStock = Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetBoolean("ShowStockAndShipping"); 5608 bool showAddToDownloadButton = Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetBoolean("ShowAddToDownloadButton"); 5609 bool relatedShowPrice = !Pageview.AreaSettings.GetItem("ProductList").GetBoolean("HidePrice"); 5610 bool relatedShowFavoriteButton = !Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetBoolean("HideFavoriteButton") && Pageview.User != null; 5611 bool relatedPointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly"); 5612 bool relatedShowCartButton = Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetBoolean("ShowAddToCartButton"); 5613 bool relatedShowViewButton = Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetBoolean("ShowViewButton"); 5614 string relatedCartIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon") != null ? Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon").SelectedValue : "fas fa-shopping-cart"; 5615 string relatedMoreText = !string.IsNullOrEmpty(Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetString("ViewMoreText")) ? Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetString("ViewMoreText") : "View"; 5616 bool relatedShowNumber = Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetBoolean("ShowProductNumber"); 5617 //string relatedImageZoomOnHover = Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetBoolean("HoverImageZoom") ? "image-hover--zoom" : ""; 5618 5619 int pageId = Pageview.Page.ID; 5620 string pageUrl = TemplateHelper.GetPageUrl(pageId); 5621 5622 string relatedGroupId = ""; 5623 5624 int relatedProductsPageSize = 5; 5625 5626 if (Pageview.Device.ToString() == "Mobile") 5627 { 5628 relatedProductsPageSize = 2; 5629 } 5630 5631 if (Pageview.Device.ToString() == "Tablet") 5632 { 5633 relatedProductsPageSize = 4; 5634 } 5635 5636 int relatedProductsColumnWidth = 12 / relatedProductsPageSize; 5637 5638 if (relatedProductsLayout != "hide") 5639 { 5640 var i = 0; 5641 foreach (LoopItem relatedGroup in GetLoop("ProductRelatedGroups")) 5642 { 5643 5644 relatedGroupId = ToPascalCase(relatedGroup.GetString("Ecom:Product:RelatedGroup.Name")); 5645 string baseFeedPageUrl = "/Default.aspx?ID=" + GetPageIdByNavigationTag("ProductsPage") + "&PageSize=" + relatedProductsPageSize + "&ProdID=" + GetString("Ecom:Product.ID") + "&feed=true"; 5646 string relatedFeed = baseFeedPageUrl + "&" + relatedGroupId + "=" + GetString("Ecom:Product.ID")+ GetString("Ecom:Product.VariantID") + "&GroupName=" + relatedGroupId; 5647 string relatedGroupName = relatedProductsLayout != "maininformation" ? relatedGroup.GetString("Ecom:Product:RelatedGroup.Name") : ""; 5648 5649 i++; 5650 5651 Block detailsRelated = new Block() 5652 { 5653 Name = relatedGroupId, 5654 Id = relatedGroupId, 5655 SortId = 70 + i, 5656 Template = RenderRelatedProducts(Translate("Related_Products_heading", "Did you remember?"), relatedGroupId, relatedFeed, relatedProductsLayout), 5657 Design = new Design 5658 { 5659 Size = "12", 5660 RenderType = RenderType.Column, 5661 HidePadding = true 5662 } 5663 }; 5664 5665 productRelatedPage.Add(relatedProductsLayout, detailsRelated); 5666 } 5667 } 5668 } 5669 5670 @helper RenderRelatedProducts(string name, string groupId, string relatedFeedUrl, string layout) 5671 { 5672 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("RelatedProductsLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 5673 ribbonClasses = layout == "Tabs" ? "" : ribbonClasses; 5674 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("RelatedProductsLayout").SelectedValue == "Ribbon" ? "center-container--ribbon" : ""; 5675 5676 <div class="nc-related-products @ribbonClasses "> 5677 <div class="center-container @ribbonSubClasses dw-mod"> 5678 @if (layout == "Section") { 5679 <div style="text-align:center;" class="u-margin-bottom--xl"> 5680 @Render(new Heading { Title = name, Level = 2 }) 5681 </div> 5682 } 5683 <div class="js-handlebars-root" id="ProductList_@groupId" data-template="ProductContainer" data-pre-render-template="ProductPreRenderContainer" data-json-feed="@relatedFeedUrl" data-preloader="overlay"></div> 5684 </div> 5685 </div> 5686 } 5687 @* Script templates for related products *@ 5688 <script id="ProductPreRenderContainer" type="text/x-template"> 5689 <div class="u-h600px u-full-width"> 5690 <div class="grid"> 5691 <div class="grid__col-12"> 5692 <div class="pre-render-element pre-render-element--md"></div> 5693 </div> 5694 </div> 5695 </div> 5696 </script> 5697 5698 5699 <script id="ProductContainer" type="text/x-template"> 5700 {{#.}} 5701 {{log this}} 5702 <div class="nc-product-list__wrap dw-mod"> 5703 <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"> 5704 {{#ProductsContainer}} 5705 <div id="Product{{productId}}" class="product-list-item br-25 dw-mod"> 5706 {{#Product}} 5707 <div class="dw-mod {{noImage}}"> 5708 <a href="{{link}}" class="product-list-item__link dw-mod"> 5709 @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" }) 5710 {{#StickersContainers}} 5711 {{>StickersContainer}} 5712 {{/StickersContainers}} 5713 </a> 5714 </div> 5715 <div class="product-list-item__content-container"> 5716 {{log this}} 5717 <div class="product-list-item__item-content"> 5718 <div class="product-list-item__header"> 5719 <a href="{{link}}" class="product-list-item__title-container" title="{{ name }}"> 5720 <h4 class="product-list-item__title"> 5721 {{ name }} 5722 </h4> 5723 @*{{#if description}} 5724 <h6 class="product-list-item__sub-title"> 5725 {{ description }} 5726 </h6> 5727 {{/if}}*@ 5728 </a> 5729 </div> 5730 <div class="product-list-price"> 5731 <div class="product-list-price__container"> 5732 <div class="product-list-price__valuta"> 5733 {{currency}} 5734 </div> 5735 {{#if discount}} 5736 <div class="product-list-price__price"> 5737 {{discount}} 5738 </div> 5739 {{/if}} 5740 @*{{#if price}} 5741 <div class="product-list-price__vat"> 5742 {{price}} 5743 </div> 5744 {{/if}}*@ 5745 </div> 5746 <div class="product-list-price__link-container"> 5747 @{ 5748 var addToCartBtn = new AddToCart 5749 { 5750 WrapperCssClass = "", 5751 AddButton = new AddToCartButton 5752 { 5753 ProductId = "{{productId}}", 5754 VariantId = "{{variantid}}", 5755 UnitId = "{{unitId}}", ProductInfo = "{{productInfo}}", 5756 OnClick = "{{facebookPixelAction}}", 5757 ButtonLayout = ButtonLayout.None, 5758 ExtraAttributes = new Dictionary<string, string> 5759 { 5760 { "{{disabledBuyButton}}", "" } 5761 }, 5762 CssClass = "product-list-price__link product-list-price__button btn", 5763 Icon = new Icon { 5764 Prefix = "u-hidden", 5765 Label = Translate("Add to basket", "Læg i kurv"), 5766 CssClass = "u-full-width" 5767 } 5768 } 5769 }; 5770 @Render(addToCartBtn) 5771 } 5772 </div> 5773 </div> 5774 </div> 5775 </div> 5776 {{/Product}} 5777 </div> 5778 {{/ProductsContainer}} 5779 </div> 5780 </div> 5781 <div style="display:flex; justify-content:center"> 5782 <div class="grid__col-45px grid__col--bleed-x"> 5783 <div class="grid__cell grid__cell--align-middle-left"> 5784 <button type="button" class="btn--condensed btn btn--clean dw-mod {{prevdisabled}} u-position-relative" OnClick="HandlebarsBolt.UpdateContent('ProductList_@relatedGroupId', '{{prevPage}}')" {{prevdisabled}}> 5785 <i class="fas fa-chevron-left fa-2x u-flex--align-center arrow-prev-page"></i> 5786 </button> 5787 </div> 5788 </div> 5789 <div class="grid__col-45px grid__col--bleed-x"> 5790 <div class="grid__cell grid__cell--align-middle-right"> 5791 <h4>{{currentPage}}/{{totalPages}}</h4> 5792 </div> 5793 </div> 5794 <div class="grid__col-45px grid__col--bleed-x"> 5795 <div class="grid__cell grid__cell--align-middle-right"> 5796 <button type="button" class="btn--condensed btn btn--clean dw-mod {{nextdisabled}} u-position-relative" OnClick="HandlebarsBolt.UpdateContent('ProductList_@relatedGroupId', '{{nextPage}}')" {{nextdisabled}}> 5797 <i class="fas fa-chevron-right fa-2x u-flex--align-center arrow-next-page"></i> 5798 </button> 5799 </div> 5800 </div> 5801 </div> 5802 {{/.}} 5803 </script> 5804 5805 <script id="StickersContainer" type="text/x-template"> 5806 <div class="stickers-container stickers-container--{{{convertStickerPositionToClassName Position}}} dw-mod"> 5807 {{#Stickers}} 5808 {{>Sticker}} 5809 {{/Stickers}} 5810 </div> 5811 </script> 5812 5813 <script id="Sticker" type="text/x-template"> 5814 @Render(new Sticker { Title = "{{Title}}", CssClass = "{{CssClass}}" }) 5815 </script> 5816 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 5817 @using Dynamicweb.Core 5818 @using System 5819 @using System.Web 5820 @using System.Collections.Generic 5821 @using Dynamicweb.Rapido.Blocks 5822 @using Dynamicweb.Rapido.Blocks.Components.General 5823 @using Dynamicweb.Rapido.Blocks.Components.Ecommerce 5824 @using Dynamicweb.Rapido.Services 5825 5826 @functions { 5827 BlocksPage productVariantsListPage = BlocksPage.GetBlockPage("Product"); 5828 Dictionary<string, object> variantListSettings = new Dictionary<string, object> { 5829 { "RenderVariantsAsProducts", false }, 5830 { "RenderVariantGroupsInTable", false }, 5831 { "HideImage", false }, 5832 { "HideProductNumbers", false } 5833 }; 5834 } 5835 5836 @{ 5837 var variantsCount = GetInteger("Ecom:Product.VariantCount"); 5838 string variantsListLayout = Pageview.AreaSettings.GetItem("ProductPage").GetList("VariantsListLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("VariantsListLayout").SelectedValue : "Section"; 5839 variantsListLayout = variantsListLayout == "Ribbon" ? "Section" : variantsListLayout; 5840 5841 //family members 5842 bool isFamilyMember = false; 5843 var variantGroups = GetLoop("VariantGroups"); 5844 var variantGroupCount = variantGroups.Count; 5845 if (variantGroupCount == 1) 5846 { 5847 var firstVariantGroup = Dynamicweb.Ecommerce.Services.VariantGroups.GetVariantGroup(Dynamicweb.Ecommerce.Common.Context.LanguageID, variantGroups[0]?.GetString("Ecom:VariantGroup.ID")); 5848 if (firstVariantGroup != null) 5849 { 5850 isFamilyMember = firstVariantGroup.Family; 5851 } 5852 } 5853 if (isFamilyMember) 5854 { 5855 variantListSettings["RenderVariantsAsProducts"] = variantsCount > 1 && Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("RenderFamilyVariantsAsProducts"); 5856 variantListSettings["RenderVariantGroupsInTable"] = false; 5857 variantListSettings["HideImage"] = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideImageForEachFamilyVariant"); 5858 variantListSettings["HideProductNumbers"] = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideFamilyProductNumbers"); 5859 } 5860 else 5861 { 5862 variantListSettings["RenderVariantsAsProducts"] = variantsCount > 1 && Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("RenderVariantsAsProductList"); 5863 variantListSettings["RenderVariantGroupsInTable"] = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("RenderVariantGroupsInTable"); 5864 variantListSettings["HideImage"] = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideImageForEachVariant"); 5865 variantListSettings["HideProductNumbers"] = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideProductNumbers"); 5866 } 5867 5868 if (Converter.ToBoolean(variantListSettings["RenderVariantsAsProducts"]) && variantsListLayout != "hide" && (isFamilyMember || !isFamilyMember)) 5869 { 5870 productVariantsListPage.Add(variantsListLayout, new Block 5871 { 5872 Name = variantsListLayout != "MainInformation" ? Translate("Variants list") : "", 5873 Id = "VariantsList", 5874 SortId = 20, 5875 Template = RenderVariantsProductList(variantsListLayout), 5876 Design = new Design 5877 { 5878 Size = "12", 5879 RenderType = RenderType.Column, 5880 HidePadding = true 5881 } 5882 }); 5883 5884 productVariantsListPage.Add("Section", new Block 5885 { 5886 Id = "VariantListScripts", 5887 SortId = 100, 5888 Template = RenderVariantListScripts(), 5889 Design = new Design {} 5890 }); 5891 } 5892 } 5893 5894 @helper RenderVariantsProductList(string layout) 5895 { 5896 string variantsListPageSize = HttpContext.Current.Request.QueryString.Get("PageSize") ?? "30"; 5897 string variantsFeedUrl = "/Default.aspx?ID=" + GetPageIdByNavigationTag("ProductsPage") + "&PageSize=" + variantsListPageSize + "&MainProductID=" + GetString("Ecom:Product.ID") + "&OnlyShowVariants=true&feed=true"; 5898 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("VariantsListLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 5899 ribbonClasses = layout == "Tabs" ? "" : ribbonClasses; 5900 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("VariantsListLayout").SelectedValue == "Ribbon" ? "center-container--ribbon" : ""; 5901 5902 <div class="product__section @ribbonClasses dw-mod"> 5903 <div class="center-container @ribbonSubClasses dw-mod"> 5904 @if (layout == "Section") 5905 { 5906 @Render(new Heading { Title = Translate("Variants"), Level = 2 }) 5907 } 5908 <div class="js-handlebars-root" id="VariantsListRoot" data-template="VariantProductsContainer" data-json-feed="@variantsFeedUrl" data-preloader="minimal"></div> 5909 </div> 5910 </div> 5911 } 5912 5913 @helper RenderVariantListScripts() 5914 { 5915 bool showProductNumberForVariants = !Converter.ToBoolean(variantListSettings["HideProductNumbers"]); 5916 bool showImageForEachVariant = !Converter.ToBoolean(variantListSettings["HideImage"]); 5917 bool variantsPointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly"); 5918 string variantsListPageSize = HttpContext.Current.Request.QueryString.Get("PageSize") ?? "30"; 5919 string variantsFeedUrl = "/Default.aspx?ID=" + GetPageIdByNavigationTag("ProductsPage") + "&PageSize=" + variantsListPageSize + "&MainProductID=" + GetString("Ecom:Product.ID") + "&OnlyShowVariants=true&feed=true"; 5920 string variantsCartIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon") != null ? Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon").SelectedValue : "fas fa-shopping-cart"; 5921 5922 <script id="VariantProductsContainer" type="text/x-template"> 5923 {{#.}} 5924 <div> 5925 <table id="VariantsProductsContainer" class="table u-position-relative dw-mod"> 5926 <thead> 5927 <tr> 5928 @if (showImageForEachVariant) 5929 { 5930 <td width="75">&nbsp;</td> 5931 } 5932 <td>@Translate("Product")</td> 5933 {{#AvailableCustomFields}} 5934 {{>TableFieldNameTemplate}} 5935 {{/AvailableCustomFields}} 5936 @if (Converter.ToBoolean(variantListSettings["RenderVariantGroupsInTable"])) { 5937 foreach (LoopItem variantgroup in GetLoop("VariantGroups")) 5938 { 5939 <td>@variantgroup.GetString("Ecom:VariantGroup.Name")</td> 5940 } 5941 } 5942 <td>&nbsp;</td> 5943 </tr> 5944 </thead> 5945 5946 <tbody id="VariantProductListContainer" data-template="VariantProductItemContainer" data-save-cookie="true"> 5947 {{#ProductsContainer}} 5948 {{>VariantProductItemContainer}} 5949 {{/ProductsContainer}} 5950 </tbody> 5951 </table> 5952 </div> 5953 5954 <div class="grid"> 5955 <div class="grid__col-12 grid__col--bleed-y"> 5956 @{ 5957 Button moreButton = new Button { Id = "LoadMoreButton", ButtonLayout = ButtonLayout.Primary, CssClass = "btn--full {{nextdisabled}}", Title = Translate("Load") + " " + Translate("more"), OnClick = "LoadMore.Next(this)" }; 5958 moreButton.ExtraAttributes.Add("data-current", "{{currentPage}}"); 5959 moreButton.ExtraAttributes.Add("data-page-size", "{{pageSize}}"); 5960 moreButton.ExtraAttributes.Add("data-total", "{{totalPages}}"); 5961 moreButton.ExtraAttributes.Add("data-container", "VariantProductListContainer"); 5962 moreButton.ExtraAttributes.Add("data-feed-url", variantsFeedUrl + "{{loadMoreFeedParams}}"); 5963 moreButton.ExtraAttributes.Add("", "{{nextdisabled}}"); 5964 } 5965 @Render(moreButton) 5966 </div> 5967 </div> 5968 {{/.}} 5969 </script> 5970 5971 <script id="VariantProductItemContainer" type="text/x-template"> 5972 {{#.}} 5973 <tr id="VariantProduct{{id}}" class="js-product" data-template="VariantProductItem" data-preloader="overlay" style="z-index: {{zIndex}}"> 5974 {{#Product}} 5975 {{>VariantProductItem}} 5976 {{/Product}} 5977 </tr> 5978 {{/.}} 5979 </script> 5980 5981 <script id="VariantProductItem" type="text/x-template"> 5982 {{#.}} 5983 @if (showImageForEachVariant) 5984 { 5985 <td width="75"> 5986 <div class="lightbox u-hidden-xxs"> 5987 <a href="{{link}}" onclick="Scroll.SavePosition(event)" title="{{name}}{{#if variantName}}, {{variantName}}{{/if}}"> 5988 <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}}" /> 5989 <div class="u-margin-right {{noImage}}"> 5990 <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}}" /> 5991 </div> 5992 </a> 5993 </div> 5994 </td> 5995 } 5996 5997 <td class="u-va-middle"> 5998 <a href="{{link}}" onclick="Scroll.SavePosition(event)" title="{{name}}{{#if variantName}}, {{variantName}}{{/if}}"> 5999 <h6 class="u-no-margin">{{name}}{{#if variantName}}, {{variantName}}{{/if}}</h6> 6000 </a> 6001 @if (showProductNumberForVariants) 6002 { 6003 <div class="item-number item-number--compressed u-margin-bottom dw-mod"> 6004 <div>{{number}}</div> 6005 </div> 6006 } 6007 @if (User.IsStockInfoAllowed()) 6008 { 6009 <text>{{#if stockText}}</text> 6010 <div class="item-number item-number--compressed dw-mod"> 6011 <span> 6012 <span class="stock-icon {{stockState}} u-no-margin dw-mod" title="{{stockText}}"></span> 6013 <span class="u-margin-right--lg"> {{stockText}}</span> 6014 {{deliveryText}} 6015 </span> 6016 </div> 6017 <text>{{/if}}</text> 6018 } 6019 else 6020 { 6021 <div class="grid__cell-footer stickers-container stickers-container--block dw-mod"> 6022 {{#Stickers}} 6023 {{>MiniSticker}} 6024 {{/Stickers}} 6025 </div> 6026 } 6027 </td> 6028 {{#CustomFields}} 6029 {{>TableFieldValueTemplate}} 6030 {{/CustomFields}} 6031 @if (Converter.ToBoolean(variantListSettings["RenderVariantGroupsInTable"])) 6032 { 6033 <text> 6034 {{#VariantSelectionNames}} 6035 {{>TableFieldNameTemplate}} 6036 {{/VariantSelectionNames}} 6037 </text> 6038 } 6039 <td class="u-va-middle"> 6040 @if (Dynamicweb.Rapido.Services.User.IsPricesAllowed() && !Dynamicweb.Rapido.Services.User.IsBuyingAllowed()) 6041 { 6042 <div class="u-hidden-sm"> 6043 <div class="u-full-width u-ta-right u-padding-right"> 6044 <div class="before-price {{onSale}} before-price--micro dw-mod">{{discount}}</div> 6045 <div class="price price--product-list price--micro dw-mod">{{price}}</div> 6046 </div> 6047 </div> 6048 } 6049 6050 <div class="grid grid--align-center grid--justify-end"> 6051 <div class="u-margin-right u-hidden-xs u-hidden-xxs"> 6052 @if (variantsPointShopOnly) 6053 { 6054 <text> 6055 {{#if canBePurchasedWithPoints}} 6056 <div class="price price--product-list price--micro dw-mod">{{points}} @Translate("points")</div> 6057 {{else}} 6058 {{#if havePointPrice}} 6059 <small class="help-text u-no-margin u-margin-top">@Translate("Not enough points to buy this")</small> 6060 {{else}} 6061 <small class="help-text u-no-margin u-margin-top">@Translate("Not available")</small> 6062 {{/if}} 6063 {{/if}} 6064 </text> 6065 } 6066 else if (Dynamicweb.Rapido.Services.User.IsPricesAllowed()) 6067 { 6068 <div class="before-price before-price--micro {{onSale}} dw-mod">{{discount}}</div> 6069 <div class="price price--condensed price--product-list dw-mod">{{price}}</div> 6070 } 6071 </div> 6072 6073 @if (Dynamicweb.Rapido.Services.User.IsBuyingAllowed()) 6074 { 6075 var addToCartBtn = new AddToCart 6076 { 6077 AddButton = new AddToCartButton 6078 { 6079 HideTitle = true, 6080 ProductId = "{{productId}}", 6081 VariantId = "{{variantid}}", 6082 UnitId = "{{unitId}}", 6083 ProductInfo = "{{productInfo}}", 6084 BuyForPoints = variantsPointShopOnly, 6085 OnClick = "{{facebookPixelAction}}" 6086 }, 6087 UnitSelector = new UnitSelector 6088 { 6089 OptionsContent = "{{#unitOptions}}{{>VariantUnitOption}}{{/unitOptions}}", 6090 Id = "UnitOptions_{{id}}", 6091 SelectedOption = "{{unitName}}", 6092 CssClass = "{{hasUnits}}" 6093 } 6094 }; 6095 6096 if (!variantsPointShopOnly) 6097 { 6098 addToCartBtn.QuantitySelector = new QuantitySelector 6099 { 6100 Id = "Quantity_{{id}}" 6101 }; 6102 } 6103 6104 <div class="grid__cell u-flex-grow--0"> 6105 @Render(addToCartBtn) 6106 </div> 6107 } 6108 <div class="favorites u-margin-left dw-mod"> 6109 {{#Favorite}} 6110 {{>FavoriteTemplate}} 6111 {{/Favorite}} 6112 </div> 6113 </div> 6114 </td> 6115 {{/.}} 6116 </script> 6117 6118 <script id="TableFieldNameTemplate" type="text/x-template"> 6119 <td class="u-va-middle">{{name}}</td> 6120 </script> 6121 6122 <script id="TableFieldValueTemplate" type="text/x-template"> 6123 <td class="u-va-middle">{{value}}</td> 6124 </script> 6125 6126 <script id="MiniSticker" type="text/x-template"> 6127 <div class="stickers-container__tag stickers-container__tag--micro {{CssClass}} dw-mod">{{Title}}</div> 6128 </script> 6129 6130 <script id="VariantUnitOption" type="text/x-template"> 6131 <div class="dropdown__item dw-mod" onclick="HandlebarsBolt.UpdateContent(this.closest('.js-product').id, '{{link}}&feed=true&UnitID={{value}}')">{{name}}</div> 6132 </script> 6133 } 6134 6135 6136 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 6137 @using Dynamicweb.Core 6138 @using System 6139 @using System.Web 6140 @using System.Collections.Generic 6141 @using Dynamicweb.Rapido.Blocks 6142 @using Dynamicweb.Rapido.Blocks.Components.General 6143 @using Dynamicweb.Rapido.Blocks.Components.Ecommerce 6144 6145 @functions { 6146 BlocksPage productVariantsMatrixPage = BlocksPage.GetBlockPage("Product"); 6147 } 6148 6149 6150 @{ 6151 var matrixLayoutSetting = Pageview.AreaSettings.GetItem("ProductPage").GetList("VariantsMatrixLayout"); 6152 string variantsMatrixLayout = matrixLayoutSetting != null && !string.IsNullOrEmpty(matrixLayoutSetting.SelectedValue) ? matrixLayoutSetting.SelectedValue : "Section"; 6153 variantsMatrixLayout = variantsMatrixLayout == "Ribbon" ? "Section" : variantsMatrixLayout; 6154 bool renderVariantsAsMatrix = GetInteger("Ecom:Product.VariantCount") > 1 && variantsMatrixLayout.ToLower() != "hide" && Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("EnableVariantMatrix"); 6155 6156 if (renderVariantsAsMatrix) 6157 { 6158 Block variantsMatrix = new Block() 6159 { 6160 Name = Translate("Variants"), 6161 Id = "VariantsMatrix", 6162 SortId = 15, 6163 Template = RenderVariantsMatrixSection(variantsMatrixLayout), 6164 Design = new Design 6165 { 6166 Size = "12", 6167 RenderType = RenderType.Column, 6168 HidePadding = true 6169 } 6170 }; 6171 6172 if (variantsMatrixLayout == "Section") { 6173 productVariantsMatrixPage.Add(variantsMatrix); 6174 } else { 6175 productVariantsMatrixPage.Add(variantsMatrixLayout, variantsMatrix); 6176 } 6177 } 6178 } 6179 6180 @helper RenderVariantsMatrixSection(string layout) 6181 { 6182 string cartIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon") != null ? Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon").SelectedValue : "fas fa-shopping-cart"; 6183 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("VariantsListLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 6184 ribbonClasses = layout == "Tabs" ? "" : ribbonClasses; 6185 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("VariantsListLayout").SelectedValue == "Ribbon" ? "center-container--ribbon" : ""; 6186 6187 List<LoopItem> variantInfos = GetLoop("VariantInfos"); 6188 string productId = GetString("Ecom:Product.ID"); 6189 string pageId = Pageview.Page.ID.ToString(); 6190 6191 6192 <div class="product__section u-no-padding @ribbonClasses dw-mod"> 6193 <div class="center-container @ribbonSubClasses dw-mod"> 6194 @RenderVariantInfoMatrix(variantInfos, productId, pageId, 0, "add") 6195 </div> 6196 </div> 6197 } 6198 6199 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 6200 @using Dynamicweb.Rendering 6201 @using Dynamicweb.Core 6202 @using System 6203 @using System.Web 6204 @using System.Collections.Generic 6205 @using Dynamicweb.Rapido.Blocks 6206 @using Dynamicweb.Rapido.Blocks.Components 6207 @using Dynamicweb.Rapido.Blocks.Components.General 6208 6209 6210 @* Component - Variant Info Matrix. This replaces the old Variant Matrix with a much cleaner approach *@ 6211 6212 @helper RenderVariantInfoMatrix(List<LoopItem> variantInfos, string productId, string pageId, double totalPrice = 0, string actionType = "update") { 6213 string cartIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon") != null ? Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon").SelectedValue : "fas fa-shopping-cart"; 6214 bool hideAddToCartButton = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("hideAddToCartButton"); 6215 6216 string currencyCode = Dynamicweb.Ecommerce.Common.Context.Currency.Code; 6217 string countryCode = Pageview.Area.CultureInfo != null ? Pageview.Area.CultureInfo.Name : "en-US"; 6218 6219 int loopCount = 0; 6220 int dimensionsCount = 0; 6221 bool firstRun = true; 6222 List<string> headerLabels = new List<string>(); 6223 6224 //Collect the missing data needed to render matrixes 6225 foreach (var variantInfoFirst in variantInfos) 6226 { 6227 dimensionsCount = 1; 6228 6229 foreach (var variantInfoSecond in variantInfoFirst.GetLoop("VariantInfos")) 6230 { 6231 dimensionsCount = 2; 6232 6233 if (firstRun) { 6234 headerLabels.Add(variantInfoSecond.GetString("OptionName")); 6235 } 6236 6237 foreach (var variantInfoThird in variantInfoSecond.GetLoop("VariantInfos")) 6238 { 6239 dimensionsCount = 3; 6240 } 6241 } 6242 6243 firstRun = false; 6244 } 6245 6246 @*One dimension*@ 6247 if (dimensionsCount == 1) 6248 { 6249 int totalQuantity = 0; 6250 6251 <table cellspacing="0" class="table matrix js-matrix dw-mod"> 6252 <thead class="matrix__head dw-mod"> 6253 <tr> 6254 @foreach (var variantInfoFirst in variantInfos) 6255 { 6256 <td class="u-bold u-ta-center" width="80" > 6257 <div>@variantInfoFirst.GetString("OptionName")</div> 6258 <small>@variantInfoFirst.GetString("VariantId")</small> 6259 </td> 6260 } 6261 <td width="80px" align="right" class="matrix-label-field-right dw-mod">@Translate("Totals")</td> 6262 <td>&nbsp;</td> 6263 </tr> 6264 </thead> 6265 <tbody> 6266 <tr> 6267 @foreach (var variantInfoFirst in variantInfos) 6268 { 6269 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; 6270 6271 loopCount++; 6272 totalQuantity += variantInfoFirst.GetInteger("Quantity"); 6273 6274 <td class="matrix__input-cell dw-mod"> 6275 @if (variantInfoFirst.GetBoolean("IsProduct")) 6276 { 6277 <input type="hidden" name="ProductLoopCounter@(loopCount)" value="@(loopCount)" /> 6278 <input type="hidden" name="ProductID@(loopCount)" value="@productId" /> 6279 <input type="hidden" name="VariantID@(loopCount)" value="@variantInfoFirst.GetString("VariantId")" /> 6280 <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"> 6281 } else { 6282 <div class="matrix__cell-disabled dw-mod"></div> 6283 } 6284 </td> 6285 } 6286 <td class="u-va-middle"> 6287 <div class="u-bold u-ta-right matrix-label-field-right dw-mod" data-row-total="ONE"> 6288 @totalQuantity 6289 </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 </tbody> 6296 <tfoot> 6297 <tr> 6298 <td colspan="@(variantInfos.Count + 2)">&nbsp;</td> 6299 </tr> 6300 @if (!hideAddToCartButton) 6301 { 6302 <tr> 6303 <td colspan="@(variantInfos.Count + 2)" class="u-ta-right"> 6304 <div class="u-padding--lg"> 6305 @if (actionType == "update") { 6306 @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" }) 6307 } else if (actionType == "justadd") { 6308 @Render(new Button { OnClick = "Matrix.AddToCart(this, '" + pageId + "');", Title = Translate("Add"), ButtonLayout = ButtonLayout.Tertiary, CssClass = "u-no-margin" }) 6309 } else { 6310 @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" }) 6311 } 6312 </div> 6313 </td> 6314 </tr> 6315 } 6316 </tfoot> 6317 </table> 6318 } 6319 6320 @*Two dimensions*@ 6321 if (dimensionsCount == 2) 6322 { 6323 Dictionary<string, int> columnTotals = new Dictionary<string, int>(); 6324 int counter = 0; 6325 int totalProducts = 0; 6326 int totalColumns = 0; 6327 6328 <table class="table matrix js-matrix dw-mod" cellspacing="0"> 6329 <thead class="matrix__head dw-mod"> 6330 <tr> 6331 <td width="160">&nbsp;</td> 6332 @foreach (string label in headerLabels) 6333 { 6334 <td class="u-bold u-ta-center" width="80">@label</td> 6335 } 6336 <td align="right" width="80" class="matrix-label-field-right dw-mod">@Translate("Totals")</td> 6337 <td>&nbsp;</td> 6338 </tr> 6339 </thead> 6340 <tbody> 6341 @foreach (var variantInfoFirst in variantInfos) 6342 { 6343 int totalRowQuantity = 0; 6344 counter += variantInfoFirst.GetInteger("Quantity"); 6345 totalColumns = variantInfoFirst.GetLoop("VariantInfos").Count; 6346 6347 <tr> 6348 <td class="matrix-label-field-left dw-mod"> 6349 <div class="u-pull--left"> 6350 <div>@variantInfoFirst.GetString("OptionName")</div> 6351 <small>@variantInfoFirst.GetString("VariantId")</small> 6352 </div> 6353 6354 @if (!string.IsNullOrEmpty(variantInfoFirst.GetString("Image"))) { 6355 <div class="matrix-option-image u-pull--right dw-mod" onclick="Matrix.ShowOptionImageModal(this)" data-img-src="/files/@variantInfoFirst.GetString("Image")"> 6356 @Render(new Image { 6357 Path = variantInfoFirst.GetString("Image"), 6358 ImageDefault = new ImageSettings { 6359 Width = 28, 6360 Height = 28 6361 }, 6362 ImageMedium = new ImageSettings { 6363 Width = 28, 6364 Height = 28 6365 }, 6366 ImageSmall = new ImageSettings { 6367 Width = 28, 6368 Height = 28 6369 } 6370 }) 6371 </div> 6372 } 6373 </td> 6374 @foreach (var variantInfoSecond in variantInfoFirst.GetLoop("VariantInfos")) 6375 { 6376 loopCount++; 6377 totalRowQuantity += variantInfoSecond.GetInteger("Quantity"); 6378 6379 string optionName = variantInfoSecond.GetString("OptionName"); 6380 int optionQuantity = variantInfoSecond.GetInteger("Quantity"); 6381 if (columnTotals.ContainsKey(optionName)) { 6382 columnTotals[optionName] += optionQuantity; 6383 } else { 6384 columnTotals.Add(optionName, optionQuantity); 6385 } 6386 6387 <td class="matrix__input-cell dw-mod"> 6388 @if (variantInfoSecond.GetBoolean("IsProduct")) { 6389 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; 6390 6391 <input type="hidden" name="ProductLoopCounter@(loopCount)" value="@(loopCount)" /> 6392 <input type="hidden" name="ProductID@(loopCount)" value="@productId" /> 6393 <input type="hidden" name="VariantID@(loopCount)" value="@variantInfoSecond.GetString("VariantId")" /> 6394 <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")"> 6395 } else { 6396 <div class="matrix__cell-disabled dw-mod"></div> 6397 } 6398 </td> 6399 } 6400 <td class="u-va-middle matrix-label-field-right dw-mod"> 6401 <div class="u-bold u-ta-right" data-row-total="@variantInfoFirst.GetString("OptionName")"> 6402 @totalRowQuantity 6403 </div> 6404 </td> 6405 <td>&nbsp;</td> 6406 </tr> 6407 } 6408 </tbody> 6409 <tfoot> 6410 <tr> 6411 <td class="u-bold u-va-middle matrix-label-field-left dw-mod">@Translate("Totals")</td> 6412 @foreach (var item in columnTotals) 6413 { 6414 totalProducts += item.Value; 6415 6416 <td> 6417 <div class="u-bold u-ta-center u-padding--lg" data-column-total="@item.Key"> 6418 @item.Value 6419 </div> 6420 </td> 6421 } 6422 <td class="u-bold u-va-middle u-ta-right matrix-label-field-right dw-mod" align="right"> 6423 <div class="js-total-quantity">@totalProducts</div> 6424 </td> 6425 <td class="u-bold u-va-middle u-ta-right matrix-label-field-right dw-mod"> 6426 <div class="js-total-price" data-currency-code="@currencyCode" data-country-code="@countryCode"></div> 6427 </td> 6428 </tr> 6429 <tr> 6430 <td colspan="@(totalColumns + 4)" class="u-ta-right u-no-padding"> 6431 <div class="u-padding--lg"> 6432 @if (actionType == "update") { 6433 @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" }) 6434 } else { 6435 @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" }) 6436 } 6437 </div> 6438 </td> 6439 </tr> 6440 </tfoot> 6441 </table> 6442 } 6443 6444 6445 Modal optionColorImage = new Modal { 6446 Id = "OptionColorImage", 6447 BodyTemplate = @Render(new Image { Path = "/Files/Images/placeholder.gif", Id = "OptionColorImageElement", DisableImageEngine = true, DisableLazyLoad = true }), 6448 Width = ModalWidth.Full 6449 }; 6450 6451 @Render(optionColorImage) 6452 } 6453 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 6454 @using Dynamicweb.Core 6455 @using System 6456 @using System.Web 6457 @using System.Collections.Generic 6458 @using Dynamicweb.Rapido.Blocks 6459 @functions { 6460 BlocksPage productSnippetsPage = BlocksPage.GetBlockPage("Product"); 6461 } 6462 6463 @{ 6464 Block googleProductSchema = new Block() 6465 { 6466 Id = "GoogleProductSchema", 6467 SortId = 10, 6468 Template = RenderGoogleProductSchema() 6469 }; 6470 6471 productSnippetsPage.Add("Snippets", googleProductSchema); 6472 } 6473 6474 @helper RenderGoogleProductSchema() 6475 { 6476 var siteURL = Dynamicweb.Context.Current.Request.Url.Scheme + "://" + Dynamicweb.Context.Current.Request.Url.Host; 6477 var image = GetProductImage(); 6478 var brand = GetString("Ecom:Product:Field.brand.Value"); 6479 var variantid = !string.IsNullOrEmpty(GetString("Ecom:Product.VariantID")) ? GetString("Ecom:Product.VariantID") : GetString("Ecom:Product.VariantID.Extented"); 6480 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 : "")); 6481 6482 <script type="application/ld+json"> 6483 { 6484 "@@context": "http://schema.org/", 6485 "@@type": "Product", 6486 "name": "@GetString("Ecom:Product.Name")", 6487 @if (!string.IsNullOrEmpty(image)) 6488 { 6489 <text>"image": [ 6490 "@siteURL/Admin/Public/GetImage.ashx?width=400&height=400&crop=0&Compression=75&DoNotUpscale=true&image=@image", 6491 "@siteURL/Admin/Public/GetImage.ashx?width=400&height=300&crop=0&Compression=75&DoNotUpscale=true&image=@image", 6492 "@siteURL/Admin/Public/GetImage.ashx?width=448&height=225&crop=0&Compression=75&DoNotUpscale=true&image=@image" 6493 ],</text> 6494 } 6495 "description": "@GetString("Ecom:Product.ShortDescription")", 6496 "mpn": "925872", 6497 @if (!string.IsNullOrEmpty(brand)) 6498 { 6499 <text>"brand": { 6500 "@@type": "Thing", 6501 "name": "@brand" 6502 },</text> 6503 } 6504 "offers": { 6505 "@@type": "Offer", 6506 "priceCurrency": "@GetString("Ecom:Product.Price.Currency.Code")", 6507 "price": "@GetString("Ecom:Product.Price.Price")", 6508 "availability": "@(GetInteger("Ecom:Product.Stock") > 0 ? "InStock" : "OutOfStock")", 6509 "url": "@url" 6510 } 6511 } 6512 </script> 6513 } 6514 6515 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 6516 6517 @using System.Globalization 6518 @using Dynamicweb.Rapido.Blocks 6519 @using Dynamicweb.Rapido.Blocks.Components.General 6520 6521 @functions { 6522 BlocksPage snippetsTemplatesPage = BlocksPage.GetBlockPage("Product"); 6523 } 6524 6525 @{ 6526 snippetsTemplatesPage.Add(new Block { 6527 Id = "FavoritesTemplates", 6528 SortId = 100, 6529 Template = RenderFavoritesTemplates() 6530 }); 6531 } 6532 6533 @helper RenderFavoritesTemplates() 6534 { 6535 var selectedFavoriteIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("FavoriteIcon") != null ? Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("FavoriteIcon").SelectedValue : "star"; 6536 string favoriteIcon = "fas fa-" + selectedFavoriteIcon; 6537 string favoriteOutlineIcon = "fal fa-" + selectedFavoriteIcon; 6538 bool useFacebookPixel = !string.IsNullOrEmpty(Pageview.AreaSettings.GetItem("Settings").GetString("FacebookPixelID")); 6539 string currentFavoriteListId = HttpContext.Current.Request.QueryString.Get("ListID"); 6540 string host = HttpContext.Current.Request.Url.Scheme + "://" + HttpContext.Current.Request.Url.Host; 6541 6542 // Klaviyo "Viewed Product" tracker event 6543 <script type="text/javascript"> 6544 var _learnq = _learnq || []; 6545 var item = { 6546 "ProductName": "@GetString("Ecom:Product.Name")", 6547 "ProductID": "@GetString("Ecom:Product.ID")", 6548 "SKU": "@GetString("Ecom:Product.Number")", 6549 "Categories": ["@GetString("Ecom:Group.Name")"], 6550 "ImageURL": "@GetString("Ecom:Product.ImageDefault")", 6551 "URL": "@host@Pageview.SearchFriendlyUrl", 6552 "Price": @Convert.ToDecimal(GetDouble("Ecom:Product.Price.Price")).ToString("F", CultureInfo.GetCultureInfo("en-US")) 6553 }; 6554 _learnq.push(["track", "Viewed Product", item]); 6555 </script> 6556 6557 <script id="FavoriteTemplate" type="text/x-template"> 6558 <div class="favorites-list u-ta-left js-favorites-list"> 6559 @Render(new Button { 6560 CssClass = "u-no-margin js-favorite-btn", 6561 Icon = new Icon 6562 { 6563 Name = "{{#if isInAnyFavoriteList}}" + favoriteIcon + "{{else}}" + favoriteOutlineIcon + "{{/if}}", 6564 CssClass = "fa-1_5x", 6565 LabelPosition = IconLabelPosition.After 6566 }, 6567 ButtonLayout = ButtonLayout.LinkClean, 6568 ButtonType = ButtonType.Button, 6569 OnClick = "document.getElementById('FavoriteTrigger_{{id}}').checked = true" 6570 }) 6571 <input type="checkbox" id="FavoriteTrigger_{{id}}" class="dropdown-trigger" /> 6572 <div class="dropdown dropdown--position-32px"> 6573 <div class="dropdown__content dropdown__content--show-left dropdown__content--padding u-w220px dw-mod"> 6574 <ul class="list list--clean dw-mod"> 6575 {{#FavoriteLists}} 6576 {{>FavoriteListItem}} 6577 {{/FavoriteLists}} 6578 </ul> 6579 </div> 6580 <label class="dropdown-trigger-off" for="FavoriteTrigger_{{id}}"></label> 6581 </div> 6582 </div> 6583 </script> 6584 6585 <script id="FavoriteListItem" type="text/x-template"> 6586 <li> 6587 @{ 6588 var button = new Button { 6589 CssClass = "list__link u-no-underline", 6590 OnClick = "toggleFavAction(this, event)", 6591 Icon = new Icon { Name = "{{#if isInFavoriteList}}" + favoriteIcon + "{{else}}" + favoriteOutlineIcon + "{{/if}}", LabelPosition = IconLabelPosition.After }, 6592 AltText = "{{#if isInFavoriteList}}" + Translate("Remove from") + " {{name}}{{else}}" + Translate("Add to") + " {{name}}{{/if}}", 6593 Title = "{{name}}", 6594 ButtonType = ButtonType.Button, 6595 ButtonLayout = ButtonLayout.LinkClean, 6596 ExtraAttributes = new Dictionary<string, string> 6597 { 6598 { "data-list-id", "{{listId}}" }, 6599 { "data-list-name", "{{name}}" }, 6600 { "data-remove-link", "{{removeLink}}" }, 6601 { "data-add-link", "{{addLink}}" }, 6602 { "data-is-in-list", "{{isInFavoriteList}}" }, 6603 6604 } 6605 }; 6606 if (useFacebookPixel) 6607 { 6608 button.ExtraAttributes.Add("data-facebook-object", "{{facebookPixelAddAction}}"); 6609 } 6610 } 6611 <div class="grid__cell"> 6612 @Render(button) 6613 </div> 6614 </li> 6615 </script> 6616 6617 <script> 6618 @if (!string.IsNullOrEmpty(currentFavoriteListId)) 6619 { 6620 <text> 6621 window.currentFavoriteListId = "@currentFavoriteListId"; 6622 </text> 6623 } 6624 function toggleFavAction(button, event) { 6625 if (button.getAttribute('data-add-link').indexOf('CCCreateNewList') > -1) { 6626 Scroll.SavePosition(event); 6627 @if (useFacebookPixel) 6628 { 6629 <text> 6630 fbq('track', 'AddToWishlist', JSON.parse(button.getAttribute('data-facebook-object'))); 6631 </text> 6632 } 6633 location.href = button.getAttribute('data-add-link'); 6634 return; 6635 } 6636 let isAdd = button.getAttribute('data-is-in-list') == "false"; 6637 Request.Fetch().get( 6638 isAdd ? button.getAttribute('data-add-link') : button.getAttribute('data-remove-link'), 6639 function (result) { 6640 button.querySelector('i').className = isAdd ? '@favoriteIcon u-margin-right--lg' : '@favoriteOutlineIcon u-margin-right--lg'; 6641 button.setAttribute('data-is-in-list', isAdd); 6642 button.setAttribute('title', (!isAdd ? '@Translate("Add to") ' : '@Translate("Remove from") ') + button.getAttribute('data-list-name')) 6643 let favList = button.closest('.js-favorites-list'); 6644 let favBtn = favList.querySelector('.js-favorite-btn i'); 6645 let isInAnyFavoriteList = favList.querySelector('[data-is-in-list=true]') != null; 6646 if (isInAnyFavoriteList) { 6647 favBtn.className = '@favoriteIcon' + ' fa-1_5x'; 6648 } else { 6649 favBtn.className = '@favoriteOutlineIcon' + ' fa-1_5x'; 6650 } 6651 @if (useFacebookPixel) 6652 { 6653 <text> 6654 if (isAdd) { 6655 fbq('track', 'AddToWishlist', JSON.parse(button.getAttribute('data-facebook-object'))); 6656 } 6657 </text> 6658 } 6659 if (window.currentFavoriteListId != null) { //if this page is favorite list 6660 let listId = button.getAttribute("data-list-id"); 6661 if (listId == window.currentFavoriteListId && !isAdd) { 6662 location.reload(); 6663 } 6664 } 6665 }, 6666 function () { 6667 console.error("FavoriteLists: Error in ToggleFavAction request"); 6668 }, 6669 false 6670 ); 6671 } 6672 </script> 6673 } 6674 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 6675 @using Dynamicweb.Core 6676 @using System 6677 @using System.Web 6678 @using System.Collections.Generic 6679 @using Dynamicweb.Rapido.Blocks 6680 6681 @{ 6682 BlocksPage customProductBlocks = BlocksPage.GetBlockPage("Product"); 6683 6684 } 6685 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 6686 @using Dynamicweb.Core 6687 @using System 6688 @using System.Web 6689 @using System.Collections.Generic 6690 @using Dynamicweb.Rapido.Blocks 6691 @using Dynamicweb.Rapido.Blocks.Components.General 6692 @using System.Linq; 6693 6694 @functions { 6695 BlocksPage productCompaniesPage = BlocksPage.GetBlockPage("Product"); 6696 } 6697 6698 @{ 6699 string productCompanies = "Section"; 6700 6701 Block productsCompaniesBlock = new Block() 6702 { 6703 Name = productCompanies, 6704 Id = "productCompanies", 6705 SortId = 29, 6706 Template = RenderCompanies(), 6707 Design = new Design 6708 { 6709 Size = "12", 6710 RenderType = RenderType.Column, 6711 HidePadding = true 6712 } 6713 }; 6714 productCompaniesPage.Add(productCompanies, productsCompaniesBlock); 6715 6716 } 6717 6718 <link rel="stylesheet" href="/Files/Templates/Designs/Rapido/node_modules/swiper/swiper-bundle.min.css"> 6719 <script src="/Files/Templates/Designs/Rapido/node_modules/swiper/swiper-bundle.min.js"></script> 6720 <script> 6721 6722 document.addEventListener('DOMContentLoaded', function() { 6723 6724 var weDeliverTo = new Swiper('.weDeliverToSlider', { 6725 loop: true, 6726 slidesPerView: 4, 6727 allowTouchMove: false, 6728 autoplay: { 6729 delay: 0, 6730 disableOnInteraction: false, 6731 }, 6732 spaceBetween: 50, 6733 speed: 3500, 6734 breakpoints: { 6735 // when window width is >= 320px 6736 320: { 6737 slidesPerView: 2, 6738 spaceBetween: 50 6739 }, 6740 // when window width is >= 480px 6741 480: { 6742 slidesPerView: 3, 6743 spaceBetween: 50 6744 }, 6745 6746 1040: { 6747 slidesPerView: 4, 6748 spaceBetween: 50 6749 } 6750 } 6751 6752 }); 6753 }); 6754 6755 </script> 6756 6757 @helper RenderCompanies() 6758 { 6759 6760 if (!string.IsNullOrEmpty(GetString("Ecom:Product:Field.WeDeliverTo.Value.FullPath"))) 6761 { 6762 string tableWidth = "grid__col-md-6"; 6763 6764 <div class="center-container dw-mod"> 6765 <div class="@tableWidth grid__col-sm-12 grid__col-xs-12 companies"> 6766 <div class="companies__header">@Translate("We deliver to")</div> 6767 <div class="weDeliverToSlider"> 6768 6769 @{ 6770 List<string> weDeliverToPaths = GetString("Ecom:Product:Field.WeDeliverTo.Value.FullPath").Split(',').ToList(); 6771 6772 if (weDeliverToPaths.Count <= 4) 6773 { 6774 // Keep a safe copy of the original set 6775 var originalSlides = new List<string>(weDeliverToPaths); 6776 6777 // Keep adding the original slides until we hit at least 8 total 6778 while (weDeliverToPaths.Count < 8) 6779 { 6780 weDeliverToPaths.AddRange(originalSlides); 6781 } 6782 } 6783 } 6784 6785 <div class="swiper-wrapper"> 6786 @{ 6787 6788 foreach(string path in weDeliverToPaths) 6789 { 6790 string fileName = Path.GetFileNameWithoutExtension(path); 6791 <div class="swiper-slide"> 6792 <img src="@path.Replace("https://denform.no","")" alt="@fileName" /> 6793 </div> 6794 } 6795 } 6796 6797 </div> 6798 </div> 6799 </div> 6800 </div> 6801 } 6802 6803 } 6804 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 6805 @using Dynamicweb.Core 6806 @using System 6807 @using System.Web 6808 @using System.Collections.Generic 6809 @using Dynamicweb.Rapido.Blocks 6810 @using Dynamicweb.Rapido.Blocks.Components.General 6811 @using System.Linq; 6812 6813 @functions { 6814 BlocksPage productTrustpilotPage = BlocksPage.GetBlockPage("Product"); 6815 } 6816 6817 @{ 6818 string productTrustpilot = "Section"; 6819 6820 Block productsTrustpilotBlock = new Block() 6821 { 6822 Name = productTrustpilot, 6823 Id = "productTrustpilot", 6824 SortId = 31, 6825 Template = RenderTrustPilot(), 6826 Design = new Design 6827 { 6828 Size = "12", 6829 RenderType = RenderType.Column, 6830 HidePadding = true 6831 } 6832 }; 6833 productTrustpilotPage.Add(productTrustpilot, productsTrustpilotBlock); 6834 } 6835 6836 <link rel="stylesheet" href="/Files/Templates/Designs/Rapido/node_modules/swiper/swiper-bundle.min.css"> 6837 <script src="/Files/Templates/Designs/Rapido/node_modules/swiper/swiper-bundle.min.js"></script> 6838 <script> 6839 document.addEventListener('DOMContentLoaded', function() { 6840 var trustpilotSlider = new Swiper('.trustpilotSlider', { 6841 loop: true, 6842 slidesPerView: 5, 6843 allowTouchMove: false, 6844 autoplay: { 6845 delay: 0, 6846 disableOnInteraction: false, 6847 }, 6848 spaceBetween: 25, 6849 speed: 3500, 6850 breakpoints: { 6851 // when window width is >= 320px 6852 320: { 6853 slidesPerView: 2, 6854 spaceBetween: 25 6855 }, 6856 // when window width is >= 480px 6857 480: { 6858 slidesPerView: 2, 6859 spaceBetween: 25 6860 }, 6861 1040: { 6862 slidesPerView: 3, 6863 spaceBetween: 25 6864 }, 6865 1500: { 6866 slidesPerView: 5, 6867 spaceBetween: 25 6868 } 6869 } 6870 }); 6871 }); 6872 </script> 6873 6874 6875 @helper RenderTrustPilot() 6876 { 6877 6878 if(Pageview.Area.Item["TPImages"] == null) 6879 { 6880 return; 6881 } 6882 6883 int itemListRelationId = (int)Pageview.Area.Item["TPImages"]; 6884 var images = Dynamicweb.Content.Items.ItemList.GetItemListById(itemListRelationId).Relations.ToList(); 6885 bool showTrustpilotSlider = GetBoolean("Ecom:Product:Field.ShowTrustpilotSlider"); 6886 6887 if (images != null && images.Count > 0 && showTrustpilotSlider) 6888 { 6889 string tableWidth = "grid__col-md-12"; 6890 6891 <div class="center-container dw-mod"> 6892 <div class="@tableWidth grid__col-sm-12 grid__col-xs-12 trustpilot"> 6893 <div class="trustpilot__header"> 6894 @Pageview.Area.Item["TPHeader"] 6895 </div> 6896 <div class="trustpilotSlider"> 6897 <div class="swiper-wrapper"> 6898 @{ 6899 foreach(Dynamicweb.Content.Items.Item image in images) 6900 { 6901 string imagePath = (string)image["ImagePath"]; 6902 string fileName = Path.GetFileNameWithoutExtension(imagePath); 6903 6904 <div class="swiper-slide"> 6905 <img src="@imagePath" alt="@fileName" /> 6906 </div> 6907 6908 } 6909 } 6910 </div> 6911 </div> 6912 <div class="trustpilot__text"> 6913 @Pageview.Area.Item["TPText"] 6914 </div> 6915 <div class="trustpilot__logo-container"> 6916 <img class="trustpilot__logo-container__image" style="width: 19px" src="\Files\Images\Trustpilot\tplogo.png"/> 6917 <div class="trustpilot__logo-container__text">Trustpilot</div> 6918 </div> 6919 </div> 6920 </div> 6921 } 6922 } 6923 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 6924 @using Dynamicweb.Core 6925 @using System 6926 @using System.Web 6927 @using System.Collections.Generic 6928 @using Dynamicweb.Rapido.Blocks 6929 @using Dynamicweb.Rapido.Blocks.Components.General 6930 @using System.Linq; 6931 6932 @functions { 6933 BlocksPage productVideoPage2 = BlocksPage.GetBlockPage("Product"); 6934 } 6935 6936 @{ 6937 string productVideo = "Section"; 6938 6939 Block productVideoBlock = new Block() 6940 { 6941 Name = productVideo, 6942 Id = "productVideo", 6943 SortId = 29, 6944 Template = RenderProductVideo(), 6945 Design = new Design 6946 { 6947 Size = "12", 6948 RenderType = RenderType.Column, 6949 HidePadding = true 6950 } 6951 }; 6952 productVideoPage2.Add(productVideo, productVideoBlock); 6953 } 6954 6955 @helper RenderProductVideo() 6956 { 6957 6958 string videoPath = GetString("Ecom:Product:Field.Video.FullPath"); 6959 6960 if (!string.IsNullOrEmpty(videoPath)) 6961 { 6962 videoPath += "#t=0.001"; 6963 string tableWidth = "grid__col-md-6"; 6964 <div class="center-container dw-mod"> 6965 <div class="@tableWidth grid__col-sm-12 grid__col-xs-12 " style="padding: 0;"> 6966 <video class="br-25" controls="" muted="" playsinline="" disablepictureinpicture="" width="1920" height="auto"> 6967 <source src="@videoPath" type="video/mp4"> 6968 </video> 6969 </div> 6970 </div> 6971 } 6972 } 6973 6974 6975 <div class="nc-product marble-white-section js-product"> 6976 <div class="grid"> 6977 @* The @RenderBlockList base helper is included in Components/GridBuilder.cshtml *@ 6978 @RenderBlockList(productsPage.BlocksRoot.BlocksList) 6979 </div> 6980 </div> 6981 6982 @helper RenderProductTop() 6983 { 6984 List<Block> subBlocks = productsPage.GetBlockListById("Top").OrderBy(item => item.SortId).ToList(); 6985 6986 <div class="nc-product__top"> 6987 <div class="nc-product__top-grid grid"> 6988 @RenderBlockList(subBlocks) 6989 </div> 6990 </div> 6991 } 6992 6993 @helper RenderProductMiniTabs() 6994 { 6995 List<Block> subBlocks = productsPage.GetBlockListById("MiniTabs").OrderBy(item => item.SortId).ToList(); 6996 6997 if (subBlocks.Count > 0) 6998 { 6999 <div class="grid__col-12 product__info tabs u-no-padding u-margin-bottom--lg dw-mod"> 7000 @{ 7001 bool firstTab = true; 7002 foreach (Block item in subBlocks) 7003 { 7004 string isChecked = firstTab ? "checked" : ""; 7005 firstTab = false; 7006 7007 <input type="radio" class="tabs__trigger" name="productMiniTabs" id="@item.Id" onchange="bLazy.revalidate()" @isChecked /> 7008 } 7009 } 7010 7011 <div class="tabs__list dw-mod"> 7012 @foreach (Block item in subBlocks) 7013 { 7014 <label for="@item.Id" class="tabs__label dw-mod">@item.Name</label> 7015 } 7016 </div> 7017 7018 <div class="tabs__blocks dw-mod"> 7019 @foreach (Block item in subBlocks) 7020 { 7021 string hidePadding = item.Design.HidePadding ? "u-no-padding" : ""; 7022 7023 if (item.Design.RenderType != RenderType.Hide) 7024 { 7025 <div class="tabs__block u-border dw-mod" id="Block__@item.Id"> 7026 <block class="product__block paragraph-container product__block--bordered dw-mod"> 7027 <div class="center-container dw-mod"> 7028 @RenderBlock(item) 7029 </div> 7030 </block> 7031 </div> 7032 } 7033 } 7034 </div> 7035 </div> 7036 } 7037 } 7038 7039 @helper RenderProductTabs() 7040 { 7041 List<Block> subBlocks = productsPage.GetBlockListById("Tabs").OrderBy(item => item.SortId).ToList(); 7042 7043 if (Pageview.Device.ToString() != "Mobile") { 7044 <div class="grid__col-12 product__info product__info--tabs tabs dw-mod"> 7045 @{ 7046 bool firstTab = true; 7047 foreach (Block item in subBlocks) 7048 { 7049 string isChecked = firstTab ? "checked" : ""; 7050 firstTab = false; 7051 7052 <input type="radio" class="tabs__trigger" name="productTabs" id="@item.Id" onchange="bLazy.revalidate()" @isChecked /> 7053 } 7054 } 7055 7056 <div class="tabs__list dw-mod"> 7057 @foreach (Block item in subBlocks) 7058 { 7059 if (item.Design.RenderType != RenderType.Hide) 7060 { 7061 <label for="@item.Id" class="tabs__label dw-mod">@item.Name</label> 7062 } 7063 } 7064 </div> 7065 7066 <div class="tabs__blocks dw-mod"> 7067 @foreach (Block item in subBlocks) 7068 { 7069 if (item.Design.RenderType != RenderType.Hide) 7070 { 7071 <div class="tabs__block dw-mod" id="Block__@item.Id"> 7072 <section class="product__section paragraph-container paragraph-container--full-width product__section--bordered dw-mod"> 7073 <div class="center-container u-padding--lg dw-mod"> 7074 @RenderBlock(item) 7075 </div> 7076 </section> 7077 </div> 7078 } 7079 } 7080 </div> 7081 </div> 7082 <div class="product-overlay-overlap"> </div> 7083 7084 7085 } else { 7086 foreach (Block item in subBlocks) 7087 { 7088 if (item.Design.RenderType != RenderType.Hide) 7089 { 7090 <div class="center-container dw-mod"> 7091 <div class="padding-position-left padding-size-sm"> 7092 @Render(new Heading { Title = item.Name, Level = 2 }) 7093 </div> 7094 7095 @RenderBlock(item) 7096 </div> 7097 } 7098 } 7099 } 7100 }