• Gratis fragt hele ugen!
  • 100% tilfredshedsgaranti
Har du brug for hjælp eller vejledning? +45 70226888
Error executing template "Designs/Rapido/eCom/ProductCatalog/SpProduct.cshtml"
System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
   at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
   at System.Collections.Generic.Dictionary`2.ValueCollection.Enumerator.MoveNext()
   at Dynamicweb.Ecommerce.Orders.Discounts.DiscountService.InitializeLookup()
   at System.Lazy`1.CreateValue()
   at CompiledRazorTemplates.Dynamic.RazorEngine_3f2b9a3c480549be98ff4e8cc85d9d1f.Execute() in C:\Dynamicweb.Net\Solutions\Philipson Wine\Files\Templates\Designs\Rapido\eCom\ProductCatalog\SpProduct.cshtml:line 3771
   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.b__0(TextWriter writer)
   at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine._Closure$__1-2._Lambda$__29()
   at System.Lazy`1.CreateValue()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at Dynamicweb.Ecommerce.Orders.Discounts.DiscountService.GetDiscounts(DiscountApplyType[] discountTypes, String[] productKeys, Int32 userId, ICollection`1 groupIds, String customerNumber)
   at Dynamicweb.Ecommerce.Orders.Discounts.DiscountService.GetDiscounts(DiscountApplyType discountType, Product product, User user)
   at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine._Closure$__1-2._Lambda$__30()
   at Dynamicweb.Ecommerce.Orders.Discounts.DiscountInfoCollection.LoadDiscounts(User user)
   at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.GetDiscountInfo(PriceViewModelSettings settings, Product product)
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at CompiledRazorTemplates.Dynamic.RazorEngine_3f2b9a3c480549be98ff4e8cc85d9d1f.Execute() in C:\Dynamicweb.Net\Solutions\Philipson Wine\Files\Templates\Designs\Rapido\eCom\ProductCatalog\SpProduct.cshtml:line 3771
   at System.Lazy`1.CreateValue()
   at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.b__0(TextWriter writer)
   at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
   at System.Lazy`1.LazyInitValue()
   at Dynamicweb.Rendering.Template.RenderRazorTemplate()
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine._Closure$__1-2._Lambda$__30()
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at CompiledRazorTemplates.Dynamic.RazorEngine_3f2b9a3c480549be98ff4e8cc85d9d1f.Execute() in C:\Dynamicweb.Net\Solutions\Philipson Wine\Files\Templates\Designs\Rapido\eCom\ProductCatalog\SpProduct.cshtml:line 3771
   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.b__0(TextWriter writer)
   at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
   at Dynamicweb.Rendering.Template.RenderRazorTemplate()

1 @inherits ViewModelTemplate<ProductViewModel> 2 @using Dynamicweb.Ecommerce.ProductCatalog 3 @using Dynamicweb.Rendering 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.Ecommerce 13 @using Dynamicweb.Content.Commenting 14 @using Dynamicweb.Rapido.Blocks.Components.General 15 @using Dynamicweb.Rapido.Blocks 16 @using System.Linq 17 @using Smartpage.PhilipsonWine.Ecommerce.ProductInformation 18 19 20 @functions { 21 22 BlocksPage productsPage = BlocksPage.GetBlockPage("Product"); 23 24 public static string ToPascalCase(string str) 25 { 26 return CultureInfo.InvariantCulture.TextInfo 27 .ToTitleCase(str.ToLowerInvariant()) 28 .Replace("-", "") 29 .Replace("_", "") 30 .Replace(" ", ""); 31 } 32 33 bool eventProduct = false; 34 } 35 36 @{ 37 38 string productBlocksPosition = Pageview.AreaSettings.GetItem("ProductPage").GetList("ImageSectionPosition") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("ImageSectionPosition").SelectedValue : "thumbs-image-info"; 39 bool productInfoOnTheRight = productBlocksPosition.LastIndexOf("info") == productBlocksPosition.Length - 4; 40 41 Pageview.Meta.Title = Model.Name; 42 43 ProductInformation productFields = new ProductInformation(Model); 44 eventProduct = productFields.ProductType == Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetString("EventProductType") ? true : false; 45 46 Block productTop = new Block() 47 { 48 Id = "Top", 49 SortId = 10, 50 SkipRenderBlocksList = true, 51 Template = RenderProductTop() 52 }; 53 productsPage.Add(productTop); 54 55 Block productMainInfo = new Block() 56 { 57 Id = "MainInformation", 58 SortId = productInfoOnTheRight ? 20 : 10, 59 Design = new Design 60 { 61 Size = "auto", 62 RenderType = RenderType.Column 63 } 64 }; 65 productsPage.Add("Top", productMainInfo); 66 67 Block productAddToCartSection = new Block() 68 { 69 Id = "AddToCartSection", 70 SortId = 30 71 }; 72 productsPage.Add("Top", productAddToCartSection); 73 74 Block productAttributeIconsSection = new Block() 75 { 76 Id = "AttributeIcons", 77 SortId = 31 78 }; 79 productsPage.Add(productAttributeIconsSection); 80 81 // Product details section 82 List<Block> productDetails = new List<Block>(); 83 84 Block descriptionSectionBlock = new Block() 85 { 86 Id = "DescriptionSection", 87 SortId = 32, 88 Template = RenderDescription("DescriptionSection") 89 }; 90 91 // Only render if we have a long description 92 if (!string.IsNullOrWhiteSpace(Model.LongDescription)) 93 { 94 productDetails.Add(descriptionSectionBlock); 95 } 96 97 var comments = Dynamicweb.Content.Commenting.Comment.GetComments("ecomProduct", Model.Id, Model.LanguageId); 98 var activeComments = comments.Where(i => i.Active == true).OrderByDescending(i => i.Rating).ThenBy(i => i.CreatedDate); 99 100 if (activeComments.Any() && !eventProduct) 101 { 102 Block customerRatingBlock = new Block() 103 { 104 Id = "CustomerRating", 105 SortId = 35, 106 Template = RenderCustomerRatings(comments, activeComments, "CustomerRating") 107 }; 108 109 productDetails.Add(customerRatingBlock); 110 } 111 112 //Expert rating 113 var expertRatings = Smartpage.PhilipsonWine.Ratings.Controller.ProductRatings.GetRatingProduct(Model.Id); 114 115 Block expertSectionBlock = new Block() 116 { 117 Id = "ExpertSection", 118 SortId = 33, 119 Template = RenderExpertRatings(expertRatings, "ExpertSection") 120 }; 121 122 if (expertRatings.Any() && !eventProduct) 123 { 124 productDetails.Add(expertSectionBlock); 125 } 126 127 var producerId = new ProductInformation(Model).ProducerId; 128 129 if (!string.IsNullOrEmpty(producerId)) 130 { 131 var producerService = new Smartpage.PhilipsonWine.Producer.Repositories.ProducerService(); 132 var producer = producerService.GetProductProducer(producerId); 133 134 if (producer != null && !string.IsNullOrWhiteSpace(producer.ProducerName) && !string.IsNullOrWhiteSpace(producer.ProducerLink) && !producer.ProducerHidden) 135 { 136 Block producerSectionBlock = new Block() 137 { 138 Id = "ProducerSection", 139 SortId = 34, 140 Template = RenderProducerInfo(producer, "ProducerSection") 141 }; 142 productDetails.Add(producerSectionBlock); 143 } 144 } 145 146 if (!eventProduct) 147 { 148 Block productFieldsBlock = new Block() 149 { 150 Id = "ProductFields", 151 SortId = 36, 152 Template = RenderProductFields("ProductFields") 153 }; 154 productDetails.Add(productFieldsBlock); 155 } 156 157 if (eventProduct) 158 { 159 Block producerSectionBlock = new Block() 160 { 161 Id = "EventSection", 162 SortId = 37, 163 Template = RenderEventInfoSection(productFields) 164 }; 165 productDetails.Add(producerSectionBlock); 166 } 167 168 if (!eventProduct && Smartpage.PhilipsonWine.BomItems.Repositories.BomItemService.GetBomItems(Model.Id) != null && Smartpage.PhilipsonWine.BomItems.Repositories.BomItemService.GetBomItems(Model.Id).Count > 0) 169 { 170 Block BOMItemsSectionBlock = new Block() 171 { 172 Id = "BOMItemsSection", 173 SortId = 35, 174 Template = RenderBOMItemsSection("BOMItemsSection") 175 }; 176 productDetails.Add(BOMItemsSectionBlock); 177 } 178 179 string id = "ClerkOthersAlsoBoughtSection"; 180 Block clerkOthersAlsoBoughtBlock = new Block() 181 { 182 Id = id, 183 SortId = 60, 184 Template = RenderClerkSection(id, "power-step-others-also-bought", "u-white-background") 185 }; 186 productDetails.Add(clerkOthersAlsoBoughtBlock); 187 188 if (!eventProduct) 189 { 190 Block inPageMenuBlock = new Block() 191 { 192 Id = "InPageMenu", 193 SortId = 1, 194 Template = RenderInPageMenu(productDetails) 195 }; 196 productDetails.Add(inPageMenuBlock); 197 } 198 199 Block productSnippetsBlock = new Block() 200 { 201 Id = "Snippets", 202 SortId = 55 203 }; 204 productsPage.Add(productSnippetsBlock); 205 206 207 } 208 209 @* Include the required Grid builder (Contains the methods @RenderBlockList and @RenderBlock) *@ 210 @using System.Text.RegularExpressions 211 @using System.Collections.Generic 212 @using System.Reflection 213 @using System.Web 214 @using System.Web.UI.HtmlControls 215 @using Dynamicweb.Rapido.Blocks.Components 216 @using Dynamicweb.Rapido.Blocks.Components.Articles 217 @using Dynamicweb.Rapido.Blocks.Components.Documentation 218 @using Dynamicweb.Rapido.Blocks 219 220 221 @*--- START: Base block renderers ---*@ 222 223 @helper RenderBlockList(List<Block> blocks) 224 { 225 bool debug = !String.IsNullOrEmpty(HttpContext.Current.Request.QueryString.Get("debug")) ? Convert.ToBoolean(HttpContext.Current.Request.QueryString.Get("debug")) : false; 226 blocks = blocks.OrderBy(item => item.SortId).ToList(); 227 228 foreach (Block item in blocks) 229 { 230 if (debug) { 231 <!-- Block START: @item.Id --> 232 } 233 234 if (item.Design == null) 235 { 236 @RenderBlock(item) 237 } 238 else if (item.Design.RenderType == RenderType.None) { 239 string cssClass = item.Design.CssClass != null ? item.Design.CssClass : ""; 240 241 <div class="@cssClass dw-mod"> 242 @RenderBlock(item) 243 </div> 244 } 245 else if (item.Design.RenderType != RenderType.Hide) 246 { 247 string cssClass = item.Design.CssClass != null ? item.Design.CssClass : ""; 248 249 if (!item.SkipRenderBlocksList) { 250 if (item.Design.RenderType == RenderType.Row) 251 { 252 <div class="grid grid--align-content-start @cssClass dw-mod" id="Block__@item.Id"> 253 @RenderBlock(item) 254 </div> 255 } 256 257 if (item.Design.RenderType == RenderType.Column) 258 { 259 string hidePadding = item.Design.HidePadding ? "u-no-padding" : ""; 260 string size = item.Design.Size ?? "12"; 261 size = Regex.IsMatch(size, @"\d") ? "md-" + item.Design.Size : item.Design.Size; 262 263 <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"> 264 @RenderBlock(item) 265 </div> 266 } 267 268 if (item.Design.RenderType == RenderType.Table) 269 { 270 <table class="table @cssClass dw-mod" id="Block__@item.Id"> 271 @RenderBlock(item) 272 </table> 273 } 274 275 if (item.Design.RenderType == RenderType.TableRow) 276 { 277 <tr class="@cssClass dw-mod" id="Block__@item.Id"> 278 @RenderBlock(item) 279 </tr> 280 } 281 282 if (item.Design.RenderType == RenderType.TableColumn) 283 { 284 <td class="@cssClass dw-mod" id="Block__@item.Id"> 285 @RenderBlock(item) 286 </td> 287 } 288 289 if (item.Design.RenderType == RenderType.CardHeader) 290 { 291 <div class="card-header @cssClass dw-mod"> 292 @RenderBlock(item) 293 </div> 294 } 295 296 if (item.Design.RenderType == RenderType.CardBody) 297 { 298 <div class="card @cssClass dw-mod"> 299 @RenderBlock(item) 300 </div> 301 } 302 303 if (item.Design.RenderType == RenderType.CardFooter) 304 { 305 <div class="card-footer @cssClass dw-mod"> 306 @RenderBlock(item) 307 </div> 308 } 309 } 310 else 311 { 312 @RenderBlock(item) 313 } 314 } 315 316 if (debug) { 317 <!-- Block END: @item.Id --> 318 } 319 } 320 } 321 322 @helper RenderBlock(Block item) 323 { 324 bool debug = !String.IsNullOrEmpty(HttpContext.Current.Request.QueryString.Get("debug")) ? Convert.ToBoolean(HttpContext.Current.Request.QueryString.Get("debug")) : false; 325 326 if (item.Template != null) 327 { 328 @BlocksPage.RenderTemplate(item.Template) 329 } 330 331 if (item.Component != null) 332 { 333 string customSufix = "Custom"; 334 string methodName = item.Component.HelperName; 335 336 ComponentBase[] methodParameters = new ComponentBase[1]; 337 methodParameters[0] = item.Component; 338 Type methodType = this.GetType(); 339 340 MethodInfo customMethod = methodType.GetMethod(methodName + customSufix); 341 MethodInfo generalMethod = methodType.GetMethod(methodName); 342 343 try { 344 if (debug) { 345 <!-- Component: @methodName.Replace("Render", "") --> 346 } 347 @customMethod.Invoke(this, methodParameters).ToString(); 348 } catch { 349 try { 350 @generalMethod.Invoke(this, methodParameters).ToString(); 351 } catch(Exception ex) { 352 throw new Exception(item.Component.GetType().Name + " method '" + methodName +"' could not be invoked", ex); 353 } 354 } 355 } 356 357 if (item.BlocksList.Count > 0 && !item.SkipRenderBlocksList) 358 { 359 @RenderBlockList(item.BlocksList) 360 } 361 } 362 363 @*--- END: Base block renderers ---*@ 364 365 @using Dynamicweb.Rapido.Blocks.Components 366 @using Dynamicweb.Rapido.Blocks.Components.General 367 @using Dynamicweb.Rapido.Blocks 368 @using System.IO 369 370 @* Required *@ 371 @using Dynamicweb.Rapido.Blocks.Components 372 @using Dynamicweb.Rapido.Blocks.Components.General 373 @using Dynamicweb.Rapido.Blocks 374 375 376 @helper Render(ComponentBase component) 377 { 378 if (component != null) 379 { 380 @component.Render(this) 381 } 382 } 383 384 @* Components *@ 385 @using System.Reflection 386 @using Dynamicweb.Rapido.Blocks.Components.General 387 388 389 @* Component *@ 390 391 @helper RenderIcon(Icon settings) 392 { 393 if (settings != null) 394 { 395 string color = settings.Color != null ? "style=\"color: " + settings.Color + "\"" : ""; 396 397 if (settings.Name != null) 398 { 399 if (string.IsNullOrEmpty(settings.Label)) 400 { 401 <i class="@settings.Prefix @settings.Name @settings.CssClass" @color></i> 402 } 403 else 404 { 405 if (settings.LabelPosition == IconLabelPosition.Before) 406 { 407 <span>@settings.Label <i class="@settings.Prefix @settings.Name @settings.CssClass" @color></i></span> 408 } 409 else 410 { 411 <span><i class="@settings.Prefix @settings.Name u-margin-right--lg @settings.CssClass u-w20px" @color></i>@settings.Label</span> 412 } 413 } 414 } 415 else if (!string.IsNullOrEmpty(settings.Label)) 416 { 417 @settings.Label 418 } 419 } 420 } 421 @using System.Reflection 422 @using Dynamicweb.Rapido.Blocks.Components.General 423 @using Dynamicweb.Rapido.Blocks.Components 424 @using Dynamicweb.Core 425 426 @* Component *@ 427 428 @helper RenderButton(Button settings) 429 { 430 if (settings != null && (!string.IsNullOrEmpty(settings.Title) || settings.Icon != null)) 431 { 432 Dictionary<string, string> attributes = new Dictionary<string, string>(); 433 List<string> classList = settings.CssClass != null ? settings.CssClass.Split(' ').ToList() : new List<string>(); 434 if (settings.Disabled) { 435 attributes.Add("disabled", "true"); 436 classList.Add("disabled"); 437 } 438 439 if (!string.IsNullOrEmpty(settings.ConfirmText) || !string.IsNullOrEmpty(settings.ConfirmTitle)) 440 { 441 settings.Id = !string.IsNullOrEmpty(settings.Id) ? settings.Id : Guid.NewGuid().ToString("N"); 442 @RenderConfirmDialog(settings); 443 settings.OnClick = "document.getElementById('" + settings.Id + "ModalTrigger').checked = true"; 444 } 445 446 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); } 447 if (!string.IsNullOrEmpty(settings.Name)) { attributes.Add("name", settings.Name); } 448 if (!string.IsNullOrEmpty(settings.AltText)) 449 { 450 attributes.Add("title", settings.AltText); 451 } 452 else if (!string.IsNullOrEmpty(settings.Title)) 453 { 454 attributes.Add("title", settings.Title); 455 } 456 457 var onClickEvents = new List<string>(); 458 if (!string.IsNullOrEmpty(settings.OnClick)) 459 { 460 onClickEvents.Add(settings.OnClick); 461 } 462 if (!string.IsNullOrEmpty(settings.Href)) 463 { 464 onClickEvents.Add("location.href='" + settings.Href + "'"); 465 } 466 if (onClickEvents.Count > 0) 467 { 468 attributes.Add("onClick", string.Join(";", onClickEvents)); 469 } 470 471 if (settings.ButtonLayout != ButtonLayout.None) 472 { 473 classList.Add("btn"); 474 string btnLayout = Enum.GetName(typeof(ButtonLayout), settings.ButtonLayout).ToLower(); 475 if (btnLayout == "linkclean") 476 { 477 btnLayout = "link-clean"; //fix 478 } 479 classList.Add("btn--" + btnLayout); 480 } 481 482 if (settings.Icon == null) 483 { 484 settings.Icon = new Icon(); 485 } 486 settings.Icon.Label = settings.Title; 487 488 attributes.Add("type", Enum.GetName(typeof(ButtonType), settings.ButtonType).ToLower()); 489 490 <button class="@string.Join(" ", classList) dw-mod" @ComponentMethods.AddAttributes(attributes) @ComponentMethods.AddAttributes(settings.ExtraAttributes)>@Render(settings.Icon)</button> 491 } 492 } 493 494 @helper RenderConfirmDialog(Button settings) 495 { 496 Modal confirmDialog = new Modal { 497 Id = settings.Id, 498 Width = ModalWidth.Sm, 499 Heading = new Heading 500 { 501 Level = 2, 502 Title = settings.ConfirmTitle 503 }, 504 BodyText = settings.ConfirmText 505 }; 506 507 confirmDialog.AddAction(new Button { Title = Translate("Cancel"), ButtonLayout = ButtonLayout.Secondary, OnClick = "document.getElementById('" + settings.Id + "ModalTrigger').checked = false"}); 508 confirmDialog.AddAction(new Button { Title = Translate("OK"), ButtonLayout = ButtonLayout.Primary, OnClick = "document.getElementById('" + settings.Id + "ModalTrigger').checked = false;" + settings.OnClick }); 509 510 @Render(confirmDialog) 511 } 512 @using Dynamicweb.Rapido.Blocks.Components.General 513 @using Dynamicweb.Rapido.Blocks.Components 514 @using Dynamicweb.Core 515 516 @helper RenderDashboard(Dashboard settings) 517 { 518 var widgets = settings.GetWidgets(); 519 520 if (!string.IsNullOrEmpty(settings.WidgetsBaseBackgroundColor)) 521 { 522 //set bg color for them 523 524 System.Drawing.Color color = System.Drawing.ColorTranslator.FromHtml(settings.WidgetsBaseBackgroundColor); 525 int r = Convert.ToInt16(color.R); 526 int g = Convert.ToInt16(color.G); 527 int b = Convert.ToInt16(color.B); 528 529 var count = widgets.Length; 530 var max = Math.Max(r, Math.Max(g, b)); 531 double step = 255.0 / (max * count); 532 var i = 0; 533 foreach (var widget in widgets) 534 { 535 i++; 536 537 var shade = "rgb(" + Converter.ToString(r * step * i).Replace(",", ".") + ", " + Converter.ToString(g * step * i).Replace(",", ".") + ", " + Converter.ToString(b * step * i).Replace(",", ".") + ")"; 538 widget.BackgroundColor = shade; 539 } 540 } 541 542 <div class="dashboard @settings.CssClass dw-mod" @ComponentMethods.AddAttributes(settings.ExtraAttributes)> 543 @foreach (var widget in widgets) 544 { 545 <div class="dashboard__widget"> 546 @Render(widget) 547 </div> 548 } 549 </div> 550 } 551 @using Dynamicweb.Rapido.Blocks.Components.General 552 @using Dynamicweb.Rapido.Blocks.Components 553 554 @helper RenderDashboardWidgetLink(DashboardWidgetLink settings) 555 { 556 if (!string.IsNullOrEmpty(settings.Link)) 557 { 558 var backgroundStyles = ""; 559 if (!string.IsNullOrEmpty(settings.BackgroundColor)) 560 { 561 backgroundStyles = "style=\"background-color:" + settings.BackgroundColor + "\""; 562 } 563 564 <a href="@settings.Link" class="widget widget--link @settings.CssClass dw-mod" @backgroundStyles title="@settings.Title" @ComponentMethods.AddAttributes(settings.ExtraAttributes)> 565 <div class="u-center-middle u-color-light"> 566 @if (settings.Icon != null) 567 { 568 settings.Icon.CssClass += "widget__icon"; 569 @Render(settings.Icon) 570 } 571 <div class="widget__title">@settings.Title</div> 572 </div> 573 </a> 574 } 575 } 576 @using Dynamicweb.Rapido.Blocks.Components.General 577 @using Dynamicweb.Rapido.Blocks.Components 578 579 @helper RenderDashboardWidgetCounter(DashboardWidgetCounter settings) 580 { 581 var backgroundStyles = ""; 582 if (!string.IsNullOrEmpty(settings.BackgroundColor)) 583 { 584 backgroundStyles = "style='background-color:" + settings.BackgroundColor + "'"; 585 } 586 587 <div class="widget @settings.CssClass dw-mod" @backgroundStyles @ComponentMethods.AddAttributes(settings.ExtraAttributes)> 588 <div class="u-center-middle u-color-light"> 589 @if (settings.Icon != null) 590 { 591 settings.Icon.CssClass += "widget__icon"; 592 @Render(settings.Icon) 593 } 594 <div class="widget__counter">@settings.Count</div> 595 <div class="widget__title">@settings.Title</div> 596 </div> 597 </div> 598 } 599 @using System.Reflection 600 @using Dynamicweb.Rapido.Blocks.Components.General 601 @using Dynamicweb.Rapido.Blocks.Components 602 @using Dynamicweb.Core 603 604 @* Component *@ 605 606 @helper RenderLink(Link settings) 607 { 608 if (settings != null && !string.IsNullOrEmpty(settings.Href) && (!string.IsNullOrEmpty(settings.Title) || settings.Icon != null)) 609 { 610 Dictionary<string, string> attributes = new Dictionary<string, string>(); 611 List<string> classList = settings.CssClass != null ? settings.CssClass.Split(' ').ToList() : new List<string>(); 612 if (settings.Disabled) 613 { 614 attributes.Add("disabled", "true"); 615 classList.Add("disabled"); 616 } 617 618 if (!string.IsNullOrEmpty(settings.AltText)) 619 { 620 attributes.Add("title", settings.AltText); 621 } 622 else if (!string.IsNullOrEmpty(settings.Title)) 623 { 624 attributes.Add("title", settings.Title); 625 } 626 627 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); } 628 if (!string.IsNullOrEmpty(settings.Name)) { attributes.Add("name", settings.Name); } 629 if (!string.IsNullOrEmpty(settings.OnClick)) { attributes.Add("onClick", settings.OnClick); } 630 attributes.Add("href", settings.Href); 631 632 if (settings.ButtonLayout != ButtonLayout.None) 633 { 634 classList.Add("btn"); 635 string btnLayout = Enum.GetName(typeof(ButtonLayout), settings.ButtonLayout).ToLower(); 636 if (btnLayout == "linkclean") 637 { 638 btnLayout = "link-clean"; //fix 639 } 640 classList.Add("btn--" + btnLayout); 641 } 642 643 if (settings.Icon == null) 644 { 645 settings.Icon = new Icon(); 646 } 647 settings.Icon.Label = settings.Title; 648 649 if (settings.Target == LinkTargetType.Blank && settings.Rel == LinkRelType.None) 650 { 651 settings.Rel = LinkRelType.Noopener; 652 } 653 if (settings.Target != LinkTargetType.None) 654 { 655 attributes.Add("target", "_" + Enum.GetName(typeof(LinkTargetType), settings.Target).ToLower()); 656 } 657 if (settings.Download) 658 { 659 attributes.Add("download", "true"); 660 } 661 if (settings.Rel != LinkRelType.None) 662 { 663 attributes.Add("rel", Enum.GetName(typeof(LinkRelType), settings.Rel).ToLower()); 664 } 665 666 <a class="@string.Join(" ", classList) dw-mod" @ComponentMethods.AddAttributes(attributes) @ComponentMethods.AddAttributes(settings.ExtraAttributes)>@Render(settings.Icon)</a> 667 } 668 } 669 @using System.Reflection 670 @using Dynamicweb.Rapido.Blocks.Components 671 @using Dynamicweb.Rapido.Blocks.Components.General 672 @using Dynamicweb.Rapido.Blocks 673 674 675 @* Component *@ 676 677 @helper RenderRating(Rating settings) 678 { 679 if (settings.Score > 0) 680 { 681 int rating = settings.Score; 682 string iconType = "fa-star"; 683 684 switch (settings.Type.ToString()) { 685 case "Stars": 686 iconType = "fa-star"; 687 break; 688 case "Hearts": 689 iconType = "fa-heart"; 690 break; 691 case "Lemons": 692 iconType = "fa-lemon"; 693 break; 694 case "Bombs": 695 iconType = "fa-bomb"; 696 break; 697 } 698 699 <div class="u-ta-right"> 700 @for (int i = 0; i < settings.OutOf; i++) 701 { 702 <i class="@(rating > i ? "fas" : "far") @iconType"></i> 703 } 704 </div> 705 } 706 } 707 @using System.Reflection 708 @using Dynamicweb.Rapido.Blocks.Components.General 709 @using Dynamicweb.Rapido.Blocks.Components 710 711 712 @* Component *@ 713 714 @helper RenderSelectFieldOption(SelectFieldOption settings) 715 { 716 Dictionary<string, string> attributes = new Dictionary<string, string>(); 717 if (settings.Checked) { attributes.Add("selected", "true"); } 718 if (settings.Disabled) { attributes.Add("disabled", "true"); } 719 if (settings.Value != null) { attributes.Add("value", settings.Value); } 720 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); } 721 722 <option @ComponentMethods.AddAttributes(attributes) @ComponentMethods.AddAttributes(settings.ExtraAttributes)>@settings.Label</option> 723 } 724 @using System.Reflection 725 @using Dynamicweb.Rapido.Blocks.Components.General 726 @using Dynamicweb.Rapido.Blocks.Components 727 728 729 @* Component *@ 730 731 @helper RenderNavigation(Navigation settings) { 732 @RenderNavigation(new 733 { 734 id = settings.Id, 735 cssclass = settings.CssClass, 736 startLevel = settings.StartLevel, 737 endlevel = settings.EndLevel, 738 expandmode = settings.Expandmode, 739 sitemapmode = settings.SitemapMode, 740 template = settings.Template 741 }) 742 } 743 @using Dynamicweb.Rapido.Blocks.Components.General 744 @using Dynamicweb.Rapido.Blocks.Components 745 746 747 @* Component *@ 748 749 @helper RenderBreadcrumbNavigation(BreadcrumbNavigation settings) { 750 settings.Id = String.IsNullOrEmpty(settings.Id) ? "breadcrumb" : settings.Id; 751 settings.Template = String.IsNullOrEmpty(settings.Template) ? "Breadcrumb.xslt" : settings.Template; 752 settings.StartLevel = settings.StartLevel == 0 ? 1 : settings.StartLevel; 753 settings.EndLevel = settings.EndLevel == 10 ? 1 : settings.EndLevel; 754 settings.Expandmode = String.IsNullOrEmpty(settings.Expandmode) ? "all" : settings.Expandmode; 755 settings.SitemapMode = false; 756 757 @RenderNavigation(settings) 758 } 759 @using Dynamicweb.Rapido.Blocks.Components.General 760 @using Dynamicweb.Rapido.Blocks.Components 761 762 763 @* Component *@ 764 765 @helper RenderLeftNavigation(LeftNavigation settings) { 766 settings.Id = String.IsNullOrEmpty(settings.Id) ? "breadcrumb" : settings.Id; 767 settings.Template = String.IsNullOrEmpty(settings.Template) ? "Breadcrumb.xslt" : settings.Template; 768 settings.StartLevel = settings.StartLevel == 0 ? 1 : settings.StartLevel; 769 settings.EndLevel = settings.EndLevel == 10 ? 1 : settings.EndLevel; 770 settings.Expandmode = String.IsNullOrEmpty(settings.Expandmode) ? "all" : settings.Expandmode; 771 772 <div class="grid__cell"> 773 @RenderNavigation(settings) 774 </div> 775 } 776 @using System.Reflection 777 @using Dynamicweb.Rapido.Blocks.Components.General 778 @using Dynamicweb.Core 779 780 @* Component *@ 781 782 @helper RenderHeading(Heading settings) 783 { 784 if (settings != null && !string.IsNullOrEmpty(settings.Title)) 785 { 786 string color = settings.Color != null ? "style=\"color: " + settings.Color + "\"" : ""; 787 string tagName = settings.Level != 0 ? "h" + settings.Level.ToString() : "div"; 788 789 @("<" + tagName + " class=\"" + settings.CssClass + " dw-mod\" " + color + ">") 790 if (!string.IsNullOrEmpty(settings.Link)) 791 { 792 @Render(new Link { Href = settings.Link, Icon = settings.Icon, Title = settings.Title, ButtonLayout = ButtonLayout.None }) 793 } 794 else 795 { 796 if (settings.Icon == null) 797 { 798 settings.Icon = new Icon(); 799 } 800 settings.Icon.Label = settings.Title; 801 @Render(settings.Icon) 802 } 803 @("</" + tagName + ">"); 804 } 805 } 806 @using Dynamicweb.Rapido.Blocks.Components 807 @using Dynamicweb.Rapido.Blocks.Components.General 808 @using Dynamicweb.Rapido.Blocks 809 810 811 @* Component *@ 812 813 @helper RenderImage(Image settings) 814 { 815 if (settings.FilterPrimary != ImageFilter.None || settings.FilterSecondary != ImageFilter.None) 816 { 817 Dictionary<string, string> optionalAttributes = new Dictionary<string, string>(); 818 if (!string.IsNullOrEmpty(settings.FilterColor)) { optionalAttributes.Add("style", "background-color: " + settings.FilterColor); } 819 820 if (settings.Caption != null) 821 { 822 @:<div> 823 } 824 825 var primaryFilterClass = settings.FilterPrimary.ToString().ToLower(); 826 var secondaryFilterClass = settings.FilterSecondary.ToString().ToLower(); 827 828 <div class="image-filter image-filter--@primaryFilterClass u-position-relative dw-mod" @ComponentMethods.AddAttributes(optionalAttributes)> 829 <div class="image-filter image-filter--@secondaryFilterClass dw-mod"> 830 @if (settings.Link != null) 831 { 832 <a href="@settings.Link"> 833 @RenderTheImage(settings) 834 </a> 835 } 836 else 837 { 838 @RenderTheImage(settings) 839 } 840 </div> 841 </div> 842 843 if (settings.Caption != null) 844 { 845 <span class="image-caption dw-mod">@settings.Caption</span> 846 @:</div> 847 } 848 } 849 else 850 { 851 if (settings.Caption != null) 852 { 853 @:<div> 854 } 855 if (!string.IsNullOrEmpty(settings.Link)) 856 { 857 <a href="@settings.Link"> 858 @RenderTheImage(settings) 859 </a> 860 } 861 else 862 { 863 @RenderTheImage(settings) 864 } 865 866 if (settings.Caption != null) 867 { 868 <span class="image-caption dw-mod">@settings.Caption</span> 869 @:</div> 870 } 871 } 872 } 873 874 @helper RenderTheImage(Image settings) 875 { 876 if (settings != null) 877 { 878 string placeholderImage = "/Files/Images/placeholder.gif"; 879 string imageEngine = "/Admin/Public/GetImage.ashx?"; 880 881 // CDN 882 var cdnUrl = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetString("CDNUrl"); 883 bool cdnActivate = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetBoolean("CDNActivate"); 884 if (!string.IsNullOrWhiteSpace(cdnUrl) && cdnActivate) 885 { 886 imageEngine = cdnUrl + imageEngine; 887 } 888 889 string imageStyle = ""; 890 891 switch (settings.Style) 892 { 893 case ImageStyle.Ball: 894 imageStyle = "grid__cell-img--ball"; 895 break; 896 897 case ImageStyle.Triangle: 898 imageStyle = "grid__cell-img--triangle"; 899 break; 900 } 901 902 if (settings.Style == ImageStyle.Ball || settings.Style == ImageStyle.Circle || settings.Style == ImageStyle.Triangle) 903 { 904 settings.ImageDefault.Crop = settings.ImageDefault.Crop == 5 ? settings.ImageDefault.Crop = 0 : settings.ImageDefault.Crop; 905 906 if (settings.ImageDefault != null) 907 { 908 settings.ImageDefault.Height = settings.ImageDefault.Width; 909 } 910 if (settings.ImageMedium != null) 911 { 912 settings.ImageMedium.Height = settings.ImageMedium.Width; 913 } 914 if (settings.ImageSmall != null) 915 { 916 settings.ImageSmall.Height = settings.ImageSmall.Width; 917 } 918 } 919 920 string defaultImage = imageEngine; 921 string imageSmall = ""; 922 string imageMedium = ""; 923 924 if (settings.DisableImageEngine) 925 { 926 defaultImage = settings.Path; 927 } 928 else 929 { 930 if (settings.ImageDefault != null) 931 { 932 defaultImage += Dynamicweb.Rapido.Services.Images.GetImagePathFromSettings(settings.ImageDefault); 933 934 if (settings.Path.GetType() != typeof(string)) 935 { 936 defaultImage += settings.Path != null ? "Image=" + settings.Path.PathUrlEncoded : ""; 937 defaultImage += settings.Path != null ? "&" + settings.Path.GetFocalPointParameters() : ""; 938 } 939 else 940 { 941 defaultImage += settings.Path != null ? "Image=" + settings.Path : ""; 942 } 943 } 944 945 if (settings.ImageSmall != null) 946 { 947 imageSmall = "data-src-small=\"" + imageEngine; 948 imageSmall += Dynamicweb.Rapido.Services.Images.GetImagePathFromSettings(settings.ImageSmall); 949 950 if (settings.Path.GetType() != typeof(string)) 951 { 952 imageSmall += settings.Path != null ? "Image=" + settings.Path.PathUrlEncoded : ""; 953 imageSmall += settings.Path != null ? "&" + settings.Path.GetFocalPointParameters() : ""; 954 } 955 else 956 { 957 imageSmall += settings.Path != null ? "Image=" + settings.Path : ""; 958 } 959 960 imageSmall += "\""; 961 } 962 963 if (settings.ImageMedium != null) 964 { 965 imageMedium = "data-src-medium=\"" + imageEngine; 966 imageMedium += Dynamicweb.Rapido.Services.Images.GetImagePathFromSettings(settings.ImageMedium); 967 968 if (settings.Path.GetType() != typeof(string)) 969 { 970 imageMedium += settings.Path != null ? "Image=" + settings.Path.PathUrlEncoded : ""; 971 imageMedium += settings.Path != null ? "&" + settings.Path.GetFocalPointParameters() : ""; 972 } 973 else 974 { 975 imageMedium += settings.Path != null ? "Image=" + settings.Path : ""; 976 } 977 978 imageMedium += "\""; 979 } 980 } 981 982 Dictionary<string, string> optionalAttributes = new Dictionary<string, string>(); 983 if (!string.IsNullOrEmpty(settings.OnClick)) { optionalAttributes.Add("onclick", settings.OnClick); } 984 if (!string.IsNullOrEmpty(settings.Title)) 985 { 986 optionalAttributes.Add("alt", settings.Title); 987 optionalAttributes.Add("title", settings.Title); 988 } 989 990 if (settings.DisableLazyLoad) 991 { 992 <img id="@settings.Id" class="@imageStyle @settings.CssClass dw-mod" src="@defaultImage" @ComponentMethods.AddAttributes(optionalAttributes) @ComponentMethods.AddAttributes(settings.ExtraAttributes) /> 993 } 994 else 995 { 996 <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) /> 997 } 998 } 999 } 1000 @using System.Reflection 1001 @using Dynamicweb.Rapido.Blocks.Components.General 1002 @using Dynamicweb.Rapido.Blocks.Components 1003 1004 @* Component *@ 1005 1006 @helper RenderFileField(FileField settings) 1007 { 1008 var attributes = new Dictionary<string, string>(); 1009 if (string.IsNullOrEmpty(settings.Id)) 1010 { 1011 settings.Id = Guid.NewGuid().ToString("N"); 1012 } 1013 1014 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); } 1015 if (settings.Disabled) { attributes.Add("disabled", "true"); } 1016 if (settings.Required) { attributes.Add("required", "true"); } 1017 if (settings.Multiple) { attributes.Add("multiple", "true"); } 1018 if (!string.IsNullOrEmpty(settings.Name)) { attributes.Add("name", settings.Name); } 1019 if (string.IsNullOrEmpty(settings.ChooseFileText)) 1020 { 1021 settings.ChooseFileText = Translate("Choose file"); 1022 } 1023 if (string.IsNullOrEmpty(settings.NoFilesChosenText)) 1024 { 1025 settings.NoFilesChosenText = Translate("No files chosen..."); 1026 } 1027 if (!string.IsNullOrEmpty(settings.OnClick)) { attributes.Add("onclick", settings.OnClick); } 1028 1029 if (settings.Required && !String.IsNullOrEmpty(settings.Label)) { settings.Label += " <span class=\"required dw-mod\">*</span>"; } 1030 1031 string setValueToFakeInput = "FileUpload.setValueToFakeInput(this)"; 1032 attributes.Add("onchange", setValueToFakeInput + (!string.IsNullOrEmpty(settings.OnChange) ? settings.OnChange : "")); 1033 1034 attributes.Add("type", "file"); 1035 if (settings.Value != null) { attributes.Add("value", settings.Value); } 1036 settings.CssClass = "u-full-width " + settings.CssClass; 1037 1038 var resultAttributes = attributes.Concat(settings.ExtraAttributes).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.Last().Value); 1039 1040 <div class="form__field-group u-full-width @settings.WrapperCssClass dw-mod"> 1041 @if (!string.IsNullOrEmpty(settings.Label)) 1042 { 1043 <label for="@settings.Id">@settings.Label</label> 1044 } 1045 @if (!string.IsNullOrEmpty(settings.HelpText)) 1046 { 1047 <small class="form__help-text">@settings.HelpText</small> 1048 } 1049 1050 <div class="form__field-combi file-input u-no-margin dw-mod"> 1051 <input @ComponentMethods.AddAttributes(resultAttributes) class="file-input__real-input" data-no-files-text="@settings.NoFilesChosenText" data-many-files-text="@Translate("files")" /> 1052 <label for="@settings.Id" class="file-input__btn btn--secondary btn dw-mod">@settings.ChooseFileText</label> 1053 <label for="@settings.Id" class="@settings.CssClass file-input__fake-input js-fake-input dw-mod">@settings.NoFilesChosenText</label> 1054 @if (settings.UploadButton != null) 1055 { 1056 settings.UploadButton.CssClass += " btn--condensed u-no-margin"; 1057 @Render(settings.UploadButton) 1058 } 1059 </div> 1060 @Render(new NotificationMessage { Message = settings.ErrorMessage }) 1061 </div> 1062 } 1063 @using System.Reflection 1064 @using Dynamicweb.Rapido.Blocks.Components.General 1065 @using Dynamicweb.Rapido.Blocks.Components 1066 @using Dynamicweb.Core 1067 @using System.Linq 1068 1069 @* Component *@ 1070 1071 @helper RenderDateTimeField(DateTimeField settings) 1072 { 1073 if (string.IsNullOrEmpty(settings.Id)) 1074 { 1075 settings.Id = Guid.NewGuid().ToString("N"); 1076 } 1077 1078 var textField = new TextField { 1079 Name = settings.Name, 1080 Id = settings.Id, 1081 Label = settings.Label, 1082 HelpText = settings.HelpText, 1083 Value = settings.Value, 1084 Disabled = settings.Disabled, 1085 Required = settings.Required, 1086 ErrorMessage = settings.ErrorMessage, 1087 CssClass = settings.CssClass, 1088 WrapperCssClass = settings.WrapperCssClass, 1089 OnChange = settings.OnChange, 1090 OnClick = settings.OnClick, 1091 ExtraAttributes = settings.ExtraAttributes, 1092 // 1093 Placeholder = settings.Placeholder 1094 }; 1095 1096 @Render(textField) 1097 1098 List<string> jsAttributes = new List<string>(); 1099 1100 jsAttributes.Add("mode: '" + Enum.GetName(typeof(DateTimeFieldMode), settings.Mode).ToLower() + "'"); 1101 1102 if (!string.IsNullOrEmpty(settings.DateFormat)) 1103 { 1104 jsAttributes.Add("dateFormat: '" + settings.DateFormat + "'"); 1105 } 1106 if (!string.IsNullOrEmpty(settings.MinDate)) 1107 { 1108 jsAttributes.Add("minDate: '" + settings.MinDate + "'"); 1109 } 1110 if (!string.IsNullOrEmpty(settings.MaxDate)) 1111 { 1112 jsAttributes.Add("maxDate: '" + settings.MaxDate + "'"); 1113 } 1114 if (settings.IsInline) 1115 { 1116 jsAttributes.Add("inline: " + Converter.ToString(settings.IsInline).ToLower()); 1117 } 1118 if (settings.EnableTime) 1119 { 1120 jsAttributes.Add("enableTime: " + Converter.ToString(settings.EnableTime).ToLower()); 1121 } 1122 if (settings.EnableWeekNumbers) 1123 { 1124 jsAttributes.Add("weekNumbers: " + Converter.ToString(settings.EnableWeekNumbers).ToLower()); 1125 } 1126 1127 jsAttributes.AddRange(settings.GetFlatPickrOptions().Select(x => x.Key + ": " + x.Value)); 1128 1129 <script> 1130 document.addEventListener("DOMContentLoaded", function () { 1131 flatpickr("#@textField.Id", { 1132 @string.Join(",", jsAttributes) 1133 }); 1134 }); 1135 </script> 1136 } 1137 @using System.Reflection 1138 @using Dynamicweb.Rapido.Blocks.Components.General 1139 @using Dynamicweb.Rapido.Blocks.Components 1140 1141 @* Component *@ 1142 1143 @helper RenderTextField(TextField settings) 1144 { 1145 var attributes = new Dictionary<string, string>(); 1146 if (!string.IsNullOrEmpty(settings.Label) && string.IsNullOrEmpty(settings.Id)) 1147 { 1148 settings.Id = Guid.NewGuid().ToString("N"); 1149 } 1150 1151 /*base settings*/ 1152 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); } 1153 if (!string.IsNullOrEmpty(settings.OnClick)) { attributes.Add("onclick", settings.OnClick); } 1154 if (!string.IsNullOrEmpty(settings.OnChange)) { attributes.Add("onchange", settings.OnChange); } 1155 if (settings.Disabled) { attributes.Add("disabled", "true"); } 1156 if (settings.Required) { attributes.Add("required", "true"); } 1157 if (!string.IsNullOrEmpty(settings.Name)) { attributes.Add("name", settings.Name); } 1158 /*end*/ 1159 1160 if (!string.IsNullOrEmpty(settings.OnKeyUp)) { attributes.Add("onkeyup", settings.OnKeyUp); } 1161 if (!string.IsNullOrEmpty(settings.OnInput)) { attributes.Add("oninput", settings.OnInput); } 1162 if (!string.IsNullOrEmpty(settings.OnFocus)) { attributes.Add("onfocus", settings.OnFocus); } 1163 if (settings.ReadOnly) { attributes.Add("readonly", "true"); } 1164 if (settings.MaxLength != 0) { attributes.Add("maxlength", settings.MaxLength.ToString()); } 1165 if (!string.IsNullOrEmpty(settings.Placeholder)) { attributes.Add("placeholder", settings.Placeholder); } 1166 attributes.Add("type", Enum.GetName(typeof(TextFieldType), settings.Type).ToLower()); 1167 if (settings.Type == TextFieldType.Password) { attributes.Add("autocomplete", "off"); }; 1168 if (settings.Value != null) { attributes.Add("value", settings.Value); } 1169 1170 settings.CssClass = "u-full-width " + settings.CssClass; 1171 1172 if (settings.Required && !String.IsNullOrEmpty(settings.Label)) { settings.Label += " <span class=\"required dw-mod\">*</span>"; } 1173 1174 var resultAttributes = attributes.Concat(settings.ExtraAttributes).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.Last().Value); 1175 1176 string noMargin = "u-no-margin"; 1177 if (!settings.ReadOnly) { 1178 noMargin = ""; 1179 } 1180 1181 <div class="form__field-group u-full-width @noMargin @settings.WrapperCssClass dw-mod"> 1182 @if (!string.IsNullOrEmpty(settings.Label)) 1183 { 1184 <label for="@settings.Id">@settings.Label</label> 1185 } 1186 @if (!string.IsNullOrEmpty(settings.HelpText)) 1187 { 1188 <small class="form__help-text">@settings.HelpText</small> 1189 } 1190 1191 @if (settings.ActionButton != null) 1192 { 1193 settings.ActionButton.CssClass += " btn--condensed u-no-margin"; 1194 <div class="form__field-combi u-no-margin dw-mod"> 1195 <input @ComponentMethods.AddAttributes(resultAttributes) class="@settings.CssClass dw-mod" /> 1196 @Render(settings.ActionButton) 1197 </div> 1198 } 1199 else 1200 { 1201 <input @ComponentMethods.AddAttributes(resultAttributes) class="@settings.CssClass dw-mod" /> 1202 } 1203 1204 @Render(new NotificationMessage { Message = settings.ErrorMessage }) 1205 </div> 1206 } 1207 @using System.Reflection 1208 @using Dynamicweb.Rapido.Blocks.Components.General 1209 @using Dynamicweb.Rapido.Blocks.Components 1210 1211 @* Component *@ 1212 1213 @helper RenderNumberField(NumberField settings) 1214 { 1215 var attributes = new Dictionary<string, string>(); 1216 if (!string.IsNullOrEmpty(settings.Label) && string.IsNullOrEmpty(settings.Id)) 1217 { 1218 settings.Id = Guid.NewGuid().ToString("N"); 1219 } 1220 1221 /*base settings*/ 1222 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); } 1223 if (!string.IsNullOrEmpty(settings.OnClick)) { attributes.Add("onclick", settings.OnClick); } 1224 if (!string.IsNullOrEmpty(settings.OnChange)) { attributes.Add("onchange", settings.OnChange); } 1225 if (settings.Disabled) { attributes.Add("disabled", "true"); } 1226 if (settings.Required) { attributes.Add("required", "true"); } 1227 if (!string.IsNullOrEmpty(settings.Name)) { attributes.Add("name", settings.Name); } 1228 /*end*/ 1229 1230 if (!string.IsNullOrEmpty(settings.OnKeyUp)) { attributes.Add("onkeyup", settings.OnKeyUp); } 1231 if (!string.IsNullOrEmpty(settings.OnInput)) { attributes.Add("oninput", settings.OnInput); } 1232 if (!string.IsNullOrEmpty(settings.OnFocus)) { attributes.Add("onfocus", settings.OnFocus); } 1233 if (settings.ReadOnly) { attributes.Add("readonly", "true"); } 1234 if (settings.Max != null) { attributes.Add("max", settings.Max.ToString()); } 1235 if (settings.Min != null) { attributes.Add("min", settings.Min.ToString()); } 1236 if (settings.Step != 0) { attributes.Add("step", settings.Step.ToString()); } 1237 if (settings.Value != null && !string.IsNullOrEmpty(settings.Value.ToString())) { attributes.Add("value", settings.Value.ToString()); } 1238 attributes.Add("type", "number"); 1239 1240 var resultAttributes = attributes.Concat(settings.ExtraAttributes).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.Last().Value); 1241 1242 <div class="form__field-group u-full-width @settings.WrapperCssClass dw-mod"> 1243 @if (!string.IsNullOrEmpty(settings.Label)) 1244 { 1245 <label for="@settings.Id">@settings.Label</label> 1246 } 1247 @if (!string.IsNullOrEmpty(settings.HelpText)) 1248 { 1249 <small class="form__help-text">@settings.HelpText</small> 1250 } 1251 1252 @if (settings.ActionButton != null) 1253 { 1254 settings.ActionButton.CssClass += " btn--condensed u-no-margin"; 1255 <div class="form__field-combi u-no-margin dw-mod"> 1256 <input @ComponentMethods.AddAttributes(resultAttributes) class="@settings.CssClass dw-mod" /> 1257 @Render(settings.ActionButton) 1258 </div> 1259 } 1260 else 1261 { 1262 <input @ComponentMethods.AddAttributes(resultAttributes) class="@settings.CssClass dw-mod" /> 1263 } 1264 1265 @Render(new NotificationMessage { Message = settings.ErrorMessage }) 1266 </div> 1267 } 1268 @using System.Reflection 1269 @using Dynamicweb.Rapido.Blocks.Components.General 1270 @using Dynamicweb.Rapido.Blocks.Components 1271 1272 1273 @* Component *@ 1274 1275 @helper RenderTextareaField(TextareaField settings) 1276 { 1277 Dictionary<string, string> attributes = new Dictionary<string, string>(); 1278 string id = settings.Id; 1279 if (!string.IsNullOrEmpty(settings.Label) && string.IsNullOrEmpty(id)) 1280 { 1281 id = Guid.NewGuid().ToString("N"); 1282 } 1283 1284 if (!string.IsNullOrEmpty(id)) { attributes.Add("id", id); } 1285 if (!string.IsNullOrEmpty(settings.OnClick)) { attributes.Add("onclick", settings.OnClick); } 1286 if (!string.IsNullOrEmpty(settings.OnKeyUp)) { attributes.Add("onkeyup", settings.OnKeyUp); } 1287 if (!string.IsNullOrEmpty(settings.OnInput)) { attributes.Add("oninput", settings.OnInput); } 1288 if (!string.IsNullOrEmpty(settings.OnFocus)) { attributes.Add("onfocus", settings.OnFocus); } 1289 if (!string.IsNullOrEmpty(settings.OnChange)) { attributes.Add("onchange", settings.OnChange); } 1290 if (!string.IsNullOrEmpty(settings.Placeholder)) { attributes.Add("placeholder", settings.Placeholder); } 1291 if (settings.Disabled) { attributes.Add("disabled", "true"); } 1292 if (settings.Required) { attributes.Add("required", "true"); } 1293 if (settings.ReadOnly) { attributes.Add("readonly", "true"); } 1294 if (settings.MaxLength != 0) { attributes.Add("maxlength", settings.MaxLength.ToString()); } 1295 if (settings.Rows != 0) { attributes.Add("rows", settings.Rows.ToString()); } 1296 attributes.Add("name", settings.Name); 1297 1298 if (settings.Required && !String.IsNullOrEmpty(settings.Label)) { settings.Label += " <span class=\"required dw-mod\">*</span>"; } 1299 1300 <div class="form__field-group @settings.WrapperCssClass dw-mod"> 1301 @if (!string.IsNullOrEmpty(settings.Label)) 1302 { 1303 <label for="@id">@settings.Label</label> 1304 } 1305 @if (!string.IsNullOrEmpty(settings.HelpText)) 1306 { 1307 <small class="form__help-text">@settings.HelpText</small> 1308 } 1309 1310 <textarea class="u-full-width @settings.CssClass dw-mod" @ComponentMethods.AddAttributes(attributes) @ComponentMethods.AddAttributes(settings.ExtraAttributes)>@settings.Value</textarea> 1311 1312 @Render(new NotificationMessage { Message = settings.ErrorMessage }) 1313 </div> 1314 } 1315 @using System.Reflection 1316 @using Dynamicweb.Rapido.Blocks.Components.General 1317 @using Dynamicweb.Rapido.Blocks.Components 1318 1319 1320 @* Component *@ 1321 1322 @helper RenderHiddenField(HiddenField settings) { 1323 var attributes = new Dictionary<string, string>(); 1324 attributes.Add("type", "hidden"); 1325 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); } 1326 if (settings.Value != null) { attributes.Add("value", settings.Value); } 1327 if (!string.IsNullOrEmpty(settings.Name)) { attributes.Add("name", settings.Name); } 1328 1329 <input @ComponentMethods.AddAttributes(attributes) @ComponentMethods.AddAttributes(settings.ExtraAttributes)/> 1330 } 1331 @using System.Reflection 1332 @using Dynamicweb.Rapido.Blocks.Components.General 1333 @using Dynamicweb.Rapido.Blocks.Components 1334 1335 @* Component *@ 1336 1337 @helper RenderCheckboxField(CheckboxField settings) 1338 { 1339 var attributes = new Dictionary<string, string>(); 1340 if (!string.IsNullOrEmpty(settings.Label) && string.IsNullOrEmpty(settings.Id)) 1341 { 1342 settings.Id = Guid.NewGuid().ToString("N"); 1343 } 1344 1345 /*base settings*/ 1346 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); } 1347 if (!string.IsNullOrEmpty(settings.OnClick)) { attributes.Add("onclick", settings.OnClick); } 1348 if (!string.IsNullOrEmpty(settings.OnChange)) { attributes.Add("onchange", settings.OnChange); } 1349 if (settings.Disabled) { attributes.Add("disabled", "true"); } 1350 if (settings.Required) { attributes.Add("required", "true"); } 1351 if (!string.IsNullOrEmpty(settings.Name)) { attributes.Add("name", settings.Name); } 1352 /*end*/ 1353 1354 if (settings.Required && !String.IsNullOrEmpty(settings.Label)) { settings.Label += " <span class=\"required dw-mod\">*</span>"; } 1355 1356 attributes.Add("type", "checkbox"); 1357 if (settings.Checked) { attributes.Add("checked", "true"); } 1358 settings.CssClass = "form__control " + settings.CssClass; 1359 if (settings.Value != null) { attributes.Add("value", settings.Value); } 1360 1361 var resultAttributes = attributes.Concat(settings.ExtraAttributes).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.Last().Value); 1362 1363 <div class="form__field-group @settings.WrapperCssClass dw-mod"> 1364 <input @ComponentMethods.AddAttributes(resultAttributes) class="@settings.CssClass dw-mod" /> 1365 @if (!string.IsNullOrEmpty(settings.Label)) 1366 { 1367 <label for="@settings.Id" class="dw-mod">@settings.Label</label> 1368 } 1369 @if (!string.IsNullOrEmpty(settings.HelpText)) 1370 { 1371 <small class="form__help-text">@settings.HelpText</small> 1372 } 1373 @Render(new NotificationMessage { Message = settings.ErrorMessage }) 1374 </div> 1375 } 1376 @using System.Reflection 1377 @using Dynamicweb.Rapido.Blocks.Components.General 1378 @using Dynamicweb.Rapido.Blocks.Components 1379 1380 1381 @* Component *@ 1382 1383 @helper RenderCheckboxListField(CheckboxListField settings) 1384 { 1385 <div class="form__field-group @settings.WrapperCssClass u-margin-bottom dw-mod" @ComponentMethods.AddAttributes(settings.ExtraAttributes)> 1386 @if (!string.IsNullOrEmpty(settings.Label)) 1387 { 1388 <label>@settings.Label</label> 1389 } 1390 @if (!string.IsNullOrEmpty(settings.HelpText)) 1391 { 1392 <small class="form__help-text">@settings.HelpText</small> 1393 } 1394 1395 @foreach (var item in settings.Options) 1396 { 1397 if (settings.Required) 1398 { 1399 item.Required = true; 1400 } 1401 if (settings.Disabled) 1402 { 1403 item.Disabled = true; 1404 } 1405 if (!string.IsNullOrEmpty(settings.Name)) 1406 { 1407 item.Name = settings.Name; 1408 } 1409 if (!string.IsNullOrEmpty(settings.CssClass)) 1410 { 1411 item.CssClass += settings.CssClass; 1412 } 1413 1414 /* value is not supported */ 1415 1416 if (!string.IsNullOrEmpty(settings.OnClick)) 1417 { 1418 item.OnClick += settings.OnClick; 1419 } 1420 if (!string.IsNullOrEmpty(settings.OnChange)) 1421 { 1422 item.OnChange += settings.OnChange; 1423 } 1424 @Render(item) 1425 } 1426 1427 @Render(new NotificationMessage { Message = settings.ErrorMessage }) 1428 </div> 1429 } 1430 @using Dynamicweb.Rapido.Blocks.Components.General 1431 1432 @* Component *@ 1433 1434 @helper RenderSearch(Search settings) 1435 { 1436 var searchValue = HttpContext.Current.Request.QueryString.Get(settings.SearchParameter) ?? ""; 1437 var groupValue = HttpContext.Current.Request.QueryString.Get(settings.GroupsParameter) ?? ""; 1438 1439 if (string.IsNullOrEmpty(settings.Id)) 1440 { 1441 settings.Id = Guid.NewGuid().ToString("N"); 1442 } 1443 1444 var resultAttributes = new Dictionary<string, string>(); 1445 1446 if (settings.PageSize != 0) 1447 { 1448 resultAttributes.Add("data-page-size", settings.PageSize.ToString()); 1449 } 1450 if (!string.IsNullOrEmpty(settings.GroupItemsFeedUrl)) 1451 { 1452 resultAttributes.Add("data-groups-feed-url", settings.GroupItemsFeedUrl); 1453 if (!string.IsNullOrEmpty(groupValue)) 1454 { 1455 resultAttributes.Add("data-selected-group", groupValue); 1456 } 1457 if (!string.IsNullOrEmpty(settings.GroupsParameter)) 1458 { 1459 resultAttributes.Add("data-groups-parameter", settings.GroupsParameter); 1460 } 1461 } 1462 resultAttributes.Add("data-force-init", "true"); 1463 if (settings.GoToFirstSearchResultOnEnter) 1464 { 1465 resultAttributes.Add("data-go-to-first-search-result-on-enter", settings.GoToFirstSearchResultOnEnter.ToString().ToLower()); 1466 } 1467 if (!string.IsNullOrEmpty(settings.SearchParameter)) 1468 { 1469 resultAttributes.Add("data-search-parameter", settings.SearchParameter); 1470 } 1471 resultAttributes.Add("data-search-feed-url", settings.SearchData.SearchFeedUrl); 1472 resultAttributes.Add("data-results-template-id", settings.SearchData.ResultsTemplateId); 1473 1474 if (settings.SecondSearchData != null) 1475 { 1476 resultAttributes.Add("data-second-search-feed-url", settings.SecondSearchData.SearchFeedUrl); 1477 resultAttributes.Add("data-second-results-template-id", settings.SecondSearchData.ResultsTemplateId); 1478 } 1479 if (!string.IsNullOrEmpty(settings.ResultsPageUrl)) 1480 { 1481 resultAttributes.Add("data-results-page-url", settings.ResultsPageUrl); 1482 } 1483 1484 resultAttributes = resultAttributes.Concat(settings.ExtraAttributes).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.Last().Value); 1485 1486 string searchFieldCss = (settings.SearchButton == null) ? "search--with-icon" : ""; 1487 1488 <div class="search @settings.CssClass @searchFieldCss js-search-data-source dw-mod" id="@settings.Id" @ComponentMethods.AddAttributes(resultAttributes)> 1489 @if (!string.IsNullOrEmpty(settings.GroupItemsFeedUrl)) 1490 { 1491 <button type="button" class="search__groups-btn dw-mod js-search-groups-btn">@Translate("All")</button> 1492 <ul class="dropdown dropdown--absolute-position dw-mod search__groups-results js-search-groups-list"></ul> 1493 } 1494 1495 <input type="text" class="search__field dw-mod js-search-field" placeholder="@settings.Placeholder" value="@searchValue"> 1496 1497 <div class="dropdown dropdown--absolute-position search__results dw-mod js-search-results @(settings.SecondSearchData != null ? "search__results--combined" : "")"> 1498 @if (settings.SecondSearchData != null) 1499 { 1500 <div class="search__column search__column--products dw-mod"> 1501 <div class="search__column-header dw-mod">@Translate("Products")</div> 1502 <ul class="search__results-list dw-mod js-search-results-list" id="@(settings.Id)_ResultsList"></ul> 1503 @if (!string.IsNullOrEmpty(settings.SearchData.ResultsPageUrl)) 1504 { 1505 @Render(new Link { 1506 Title = Translate("View all"), 1507 CssClass = "js-view-all-button u-margin", 1508 Href = settings.SearchData.ResultsPageUrl 1509 }); 1510 } 1511 </div> 1512 <div class="search__column search__column--pages dw-mod"> 1513 <div class="search__column-header">@Translate("Pages")</div> 1514 <ul class="search__results-list dw-mod js-search-results-second-list" id="@(settings.Id)_SecondResultsList"></ul> 1515 @if (!string.IsNullOrEmpty(settings.SecondSearchData.ResultsPageUrl)) 1516 { 1517 @Render(new Link 1518 { 1519 Title = Translate("View all"), 1520 CssClass = "js-view-all-button u-margin", 1521 Href = settings.SecondSearchData.ResultsPageUrl 1522 }); 1523 } 1524 </div> 1525 } 1526 else 1527 { 1528 <div class="search__column search__column--only dw-mod"> 1529 <ul class="search__results-list dw-mod js-search-results-list" id="@(settings.Id)_ResultsList"></ul> 1530 @if (!string.IsNullOrEmpty(settings.SearchData.ResultsPageUrl)) 1531 { 1532 @Render(new Link { 1533 Title = Translate("View all"), 1534 CssClass = "js-view-all-button u-margin", 1535 Href = settings.SearchData.ResultsPageUrl 1536 }); 1537 } 1538 </div> 1539 } 1540 </div> 1541 1542 @if (settings.SearchButton != null) 1543 { 1544 settings.SearchButton.CssClass += " search__btn js-search-btn"; 1545 if (settings.RenderDefaultSearchIcon) 1546 { 1547 settings.SearchButton.Icon = new Icon { Name = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("SearchIcon").SelectedValue }; 1548 } 1549 @Render(settings.SearchButton); 1550 } 1551 </div> 1552 } 1553 @using System.Reflection 1554 @using Dynamicweb.Rapido.Blocks.Components.General 1555 @using Dynamicweb.Rapido.Blocks.Components 1556 1557 1558 @* Component *@ 1559 1560 @helper RenderSelectField(SelectField settings) 1561 { 1562 if (!string.IsNullOrEmpty(settings.Label) && string.IsNullOrEmpty(settings.Id)) 1563 { 1564 settings.Id = Guid.NewGuid().ToString("N"); 1565 } 1566 1567 <div class="form__field-group u-full-width @settings.WrapperCssClass dw-mod"> 1568 @if (!string.IsNullOrEmpty(settings.Label)) 1569 { 1570 <label for="@settings.Id">@settings.Label</label> 1571 } 1572 @if (!string.IsNullOrEmpty(settings.HelpText)) 1573 { 1574 <small class="form__help-text">@settings.HelpText</small> 1575 } 1576 1577 @if (settings.ActionButton != null) 1578 { 1579 settings.ActionButton.CssClass += " btn--condensed u-no-margin"; 1580 <div class="form__field-combi u-no-margin dw-mod"> 1581 @RenderSelectBase(settings) 1582 @Render(settings.ActionButton) 1583 </div> 1584 } 1585 else 1586 { 1587 @RenderSelectBase(settings) 1588 } 1589 1590 @Render(new NotificationMessage { Message = settings.ErrorMessage }) 1591 </div> 1592 } 1593 1594 @helper RenderSelectBase(SelectField settings) 1595 { 1596 var attributes = new Dictionary<string, string>(); 1597 1598 /*base settings*/ 1599 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); } 1600 if (!string.IsNullOrEmpty(settings.OnClick)) { attributes.Add("onclick", settings.OnClick); } 1601 if (!string.IsNullOrEmpty(settings.OnChange)) { attributes.Add("onchange", settings.OnChange); } 1602 if (settings.Disabled) { attributes.Add("disabled", "true"); } 1603 if (settings.Required) { attributes.Add("required", "true"); } 1604 if (!string.IsNullOrEmpty(settings.Name)) { attributes.Add("name", settings.Name); } 1605 /*end*/ 1606 1607 var resultAttributes = attributes.Concat(settings.ExtraAttributes).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.Last().Value); 1608 1609 <select @ComponentMethods.AddAttributes(resultAttributes) class="u-full-width @settings.CssClass dw-mod"> 1610 @if (settings.Default != null) 1611 { 1612 @Render(settings.Default) 1613 } 1614 1615 @foreach (var item in settings.Options) 1616 { 1617 if (settings.Value != null) { 1618 item.Checked = item.Value == settings.Value; 1619 } 1620 @Render(item) 1621 } 1622 </select> 1623 } 1624 @using System.Reflection 1625 @using Dynamicweb.Rapido.Blocks.Components.General 1626 @using Dynamicweb.Rapido.Blocks.Components 1627 1628 @* Component *@ 1629 1630 @helper RenderRadioButtonField(RadioButtonField settings) 1631 { 1632 var attributes = new Dictionary<string, string>(); 1633 if (!string.IsNullOrEmpty(settings.Label) && string.IsNullOrEmpty(settings.Id)) 1634 { 1635 settings.Id = Guid.NewGuid().ToString("N"); 1636 } 1637 1638 /*base settings*/ 1639 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); } 1640 if (!string.IsNullOrEmpty(settings.OnClick)) { attributes.Add("onclick", settings.OnClick); } 1641 if (!string.IsNullOrEmpty(settings.OnChange)) { attributes.Add("onchange", settings.OnChange); } 1642 if (settings.Disabled) { attributes.Add("disabled", "true"); } 1643 if (settings.Required) { attributes.Add("required", "true"); } 1644 if (!string.IsNullOrEmpty(settings.Name)) { attributes.Add("name", settings.Name); } 1645 /*end*/ 1646 1647 attributes.Add("type", "radio"); 1648 if (settings.Checked) { attributes.Add("checked", "true"); } 1649 settings.CssClass = "form__control " + settings.CssClass; 1650 if (settings.Value != null) { attributes.Add("value", settings.Value); } 1651 1652 var resultAttributes = attributes.Concat(settings.ExtraAttributes).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.Last().Value); 1653 1654 <div class="form__field-group @settings.WrapperCssClass dw-mod"> 1655 <input @ComponentMethods.AddAttributes(resultAttributes) class="@settings.CssClass dw-mod" /> 1656 @if (!string.IsNullOrEmpty(settings.Label)) 1657 { 1658 <label for="@settings.Id" class="dw-mod">@settings.Label</label> 1659 } 1660 @if (!string.IsNullOrEmpty(settings.HelpText)) 1661 { 1662 <small class="form__help-text">@settings.HelpText</small> 1663 } 1664 @Render(new NotificationMessage { Message = settings.ErrorMessage }) 1665 </div> 1666 } 1667 @using System.Reflection 1668 @using Dynamicweb.Rapido.Blocks.Components.General 1669 @using Dynamicweb.Rapido.Blocks.Components 1670 1671 1672 @* Component *@ 1673 1674 @helper RenderRadioButtonListField(RadioButtonListField settings) 1675 { 1676 if (settings.Required && !String.IsNullOrEmpty(settings.Label)) { settings.Label += " <span class=\"required dw-mod\">*</span>"; } 1677 1678 <div class="form__field-group @settings.WrapperCssClass u-margin-bottom dw-mod" @ComponentMethods.AddAttributes(settings.ExtraAttributes)> 1679 @if (!string.IsNullOrEmpty(settings.Label)) 1680 { 1681 <label>@settings.Label</label> 1682 } 1683 @if (!string.IsNullOrEmpty(settings.HelpText)) 1684 { 1685 <small class="form__help-text">@settings.HelpText</small> 1686 } 1687 1688 @foreach (var item in settings.Options) 1689 { 1690 if (settings.Required) 1691 { 1692 item.Required = true; 1693 } 1694 if (settings.Disabled) 1695 { 1696 item.Disabled = true; 1697 } 1698 if (!string.IsNullOrEmpty(settings.Name)) 1699 { 1700 item.Name = settings.Name; 1701 } 1702 if (settings.Value != null && settings.Value == item.Value) 1703 { 1704 item.Checked = true; 1705 } 1706 if (!string.IsNullOrEmpty(settings.OnClick)) 1707 { 1708 item.OnClick += settings.OnClick; 1709 } 1710 if (!string.IsNullOrEmpty(settings.OnChange)) 1711 { 1712 item.OnChange += settings.OnChange; 1713 } 1714 if (!string.IsNullOrEmpty(settings.CssClass)) 1715 { 1716 item.CssClass += settings.CssClass; 1717 } 1718 @Render(item) 1719 } 1720 1721 @Render(new NotificationMessage { Message = settings.ErrorMessage }) 1722 </div> 1723 } 1724 @using System.Reflection 1725 @using Dynamicweb.Rapido.Blocks.Components.General 1726 @using Dynamicweb.Rapido.Blocks.Components 1727 1728 1729 @* Component *@ 1730 1731 @helper RenderNotificationMessage(NotificationMessage settings) 1732 { 1733 if (!string.IsNullOrEmpty(settings.Message)) 1734 { 1735 var attributes = new Dictionary<string, string>(); 1736 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); } 1737 1738 string messageTypeClass = Enum.GetName(typeof(NotificationMessageType), settings.MessageType).ToLower(); 1739 <div class="field-@messageTypeClass @settings.CssClass u-full-width dw-mod" @ComponentMethods.AddAttributes(attributes)>@settings.Message</div> 1740 } 1741 } 1742 @using Dynamicweb.Rapido.Blocks.Components.General 1743 1744 1745 @* Component *@ 1746 1747 @helper RenderHandlebarsRoot(HandlebarsRoot settings) { 1748 string preRender = !String.IsNullOrEmpty(settings.PreRenderScriptTemplate) ? "data-pre-render-template=\"" + settings.PreRenderScriptTemplate + "\"" : ""; 1749 1750 <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> 1751 @if (settings.SubBlocks != null) { 1752 @RenderBlockList(settings.SubBlocks) 1753 } 1754 </div> 1755 } 1756 @using System.Reflection 1757 @using Dynamicweb.Rapido.Blocks.Components.General 1758 @using Dynamicweb.Rapido.Blocks.Components 1759 @using System.Text.RegularExpressions 1760 1761 1762 @* Component *@ 1763 1764 @helper RenderSticker(Sticker settings) { 1765 if (!String.IsNullOrEmpty(settings.Title)) { 1766 string size = settings.Size.ToString() != "None" ? "" + "stickers-container__tag--" + settings.Size.ToString().ToLower() : ""; 1767 string style = settings.Style.ToString() != "None" ? "" + "stickers-container__tag--" + settings.Style.ToString().ToLower() : ""; 1768 1769 Dictionary<String, String> optionalAttributes = new Dictionary<string, string>(); 1770 if (!String.IsNullOrEmpty(settings.Color) || !String.IsNullOrEmpty(settings.BackgroundColor)) { 1771 string styleTag = !String.IsNullOrEmpty(settings.Color) ? "color: " + settings.Color + "; " : ""; 1772 styleTag += !String.IsNullOrEmpty(settings.BackgroundColor) ? "background-color: " + settings.BackgroundColor + "; " : ""; 1773 optionalAttributes.Add("style", styleTag); 1774 } 1775 1776 <div class="stickers-container__tag @size @style @settings.CssClass dw-mod" @ComponentMethods.AddAttributes(optionalAttributes) @ComponentMethods.AddAttributes(settings.ExtraAttributes)>@settings.Title</div> 1777 } 1778 } 1779 1780 @using System.Reflection 1781 @using Dynamicweb.Rapido.Blocks.Components.General 1782 @using Dynamicweb.Rapido.Blocks.Components 1783 1784 1785 @* Component *@ 1786 1787 @helper RenderStickersCollection(StickersCollection settings) 1788 { 1789 if (settings.Stickers.Count > 0) 1790 { 1791 string position = "stickers-container--" + Regex.Replace(settings.Position.ToString(), "([a-z])([A-Z])", "$1-$2").ToLower(); 1792 1793 <div class="stickers-container @position @settings.CssClass dw-mod" @ComponentMethods.AddAttributes(settings.ExtraAttributes)> 1794 @foreach (Sticker sticker in settings.Stickers) 1795 { 1796 @Render(sticker) 1797 } 1798 </div> 1799 } 1800 } 1801 1802 @using Dynamicweb.Rapido.Blocks.Components.General 1803 1804 1805 @* Component *@ 1806 1807 @helper RenderForm(Form settings) { 1808 if (settings != null) 1809 { 1810 Dictionary<string, string> optionalAttributes = new Dictionary<string, string>(); 1811 if (!string.IsNullOrEmpty(settings.Action)) { optionalAttributes.Add("action", settings.Action); }; 1812 if (!string.IsNullOrEmpty(settings.Name)) { optionalAttributes.Add("name", settings.Name); }; 1813 if (!string.IsNullOrEmpty(settings.OnSubmit)) { optionalAttributes.Add("onsubmit", settings.OnSubmit); }; 1814 var enctypes = new Dictionary<string, string> 1815 { 1816 { "multipart", "multipart/form-data" }, 1817 { "text", "text/plain" }, 1818 { "application", "application/x-www-form-urlencoded" } 1819 }; 1820 if (settings.Enctype != FormEnctype.none) { optionalAttributes.Add("enctype", enctypes[Enum.GetName(typeof(FormEnctype), settings.Enctype).ToLower()]); }; 1821 optionalAttributes.Add("method", settings.Method.ToString()); 1822 1823 if (!string.IsNullOrEmpty(settings.FormStartMarkup)) 1824 { 1825 @settings.FormStartMarkup 1826 } 1827 else 1828 { 1829 @:<form class="@settings.CssClass u-no-margin dw-mod" @ComponentMethods.AddAttributes(optionalAttributes) @ComponentMethods.AddAttributes(settings.ExtraAttributes)> 1830 } 1831 1832 foreach (var field in settings.GetFields()) 1833 { 1834 @Render(field) 1835 } 1836 1837 @:</form> 1838 } 1839 } 1840 @using System.Reflection 1841 @using Dynamicweb.Rapido.Blocks.Components.General 1842 @using Dynamicweb.Rapido.Blocks.Components 1843 1844 1845 @* Component *@ 1846 1847 @helper RenderText(Text settings) 1848 { 1849 @settings.Content 1850 } 1851 @using System.Reflection 1852 @using Dynamicweb.Rapido.Blocks.Components.General 1853 @using Dynamicweb.Rapido.Blocks.Components 1854 1855 1856 @* Component *@ 1857 1858 @helper RenderContentModule(ContentModule settings) { 1859 if (!string.IsNullOrEmpty(settings.Content)) 1860 { 1861 @settings.Content 1862 } 1863 } 1864 @using System.Reflection 1865 @using Dynamicweb.Rapido.Blocks.Components.General 1866 @using Dynamicweb.Rapido.Blocks.Components 1867 1868 1869 @* Component *@ 1870 1871 @helper RenderModal(Modal settings) { 1872 if (settings != null) 1873 { 1874 string modalId = !string.IsNullOrEmpty(settings.Id) ? settings.Id : Guid.NewGuid().ToString("N"); 1875 1876 string onchange = !string.IsNullOrEmpty(settings.OnClose) ? "onchange=\"if(!this.checked){" + settings.OnClose + "}\"" : ""; 1877 1878 <input type="checkbox" id="@(modalId)ModalTrigger" class="modal-trigger" @onchange /> 1879 1880 <div class="modal-container"> 1881 @if (!settings.DisableDarkOverlay) 1882 { 1883 <label for="@(modalId)ModalTrigger" id="@(modalId)ModalOverlay" class="modal-overlay"></label> 1884 } 1885 <div class="modal modal--@settings.Width.ToString().ToLower() modal-height--@settings.Height.ToString().ToLower()" id="@(modalId)Modal"> 1886 @if (settings.Heading != null) 1887 { 1888 if (!string.IsNullOrEmpty(settings.Heading.Title)) 1889 { 1890 <div class="modal__header"> 1891 @Render(settings.Heading) 1892 </div> 1893 } 1894 } 1895 <div class="modal__body @(settings.Width.ToString().ToLower() == "full" ? "modal__body--full" : "")"> 1896 @if (!string.IsNullOrEmpty(settings.BodyText)) 1897 { 1898 @settings.BodyText 1899 } 1900 @if (settings.BodyTemplate != null) 1901 { 1902 @settings.BodyTemplate 1903 } 1904 @{ 1905 var actions = settings.GetActions(); 1906 } 1907 </div> 1908 @if (actions.Length > 0) 1909 { 1910 <div class="modal__footer"> 1911 @foreach (var action in actions) 1912 { 1913 if (Pageview.Device.ToString() != "Mobile") { 1914 action.CssClass += " u-no-margin"; 1915 } else { 1916 action.CssClass += " u-full-width u-margin-bottom"; 1917 } 1918 1919 @Render(action) 1920 } 1921 </div> 1922 } 1923 <label class="modal__close-btn" for="@(modalId)ModalTrigger"></label> 1924 </div> 1925 </div> 1926 } 1927 } 1928 @using Dynamicweb.Rapido.Blocks.Components.General 1929 1930 @* Component *@ 1931 1932 @helper RenderMediaListItem(MediaListItem settings) 1933 { 1934 <div class="media-list-item @settings.CssClass dw-mod" @(!string.IsNullOrEmpty(settings.Id) ? "id=\"" + settings.Id + "\"" : "")> 1935 @if (!string.IsNullOrEmpty(settings.Label)) 1936 { 1937 if (!string.IsNullOrEmpty(settings.Link)) 1938 { 1939 @Render(new Link 1940 { 1941 Href = settings.Link, 1942 CssClass = "media-list-item__sticker dw-mod", 1943 ButtonLayout = ButtonLayout.None, 1944 Title = settings.Label, 1945 OnClick = !string.IsNullOrEmpty(settings.OnClick) ? settings.OnClick : "" 1946 }) 1947 } 1948 else if (!string.IsNullOrEmpty(settings.OnClick)) 1949 { 1950 <span class="media-list-item__sticker dw-mod" onclick="@(settings.OnClick)"> 1951 <span class="u-uppercase">@settings.Label</span> 1952 </span> 1953 } 1954 else 1955 { 1956 <span class="media-list-item__sticker media-list-item__sticker--no-link dw-mod"> 1957 <span class="u-uppercase">@settings.Label</span> 1958 </span> 1959 } 1960 } 1961 <div class="media-list-item__wrap"> 1962 <div class="media-list-item__info dw-mod"> 1963 <div class="media-list-item__header dw-mod"> 1964 @if (!string.IsNullOrEmpty(settings.Title)) 1965 { 1966 if (!string.IsNullOrEmpty(settings.Link)) 1967 { 1968 @Render(new Link 1969 { 1970 Href = settings.Link, 1971 CssClass = "media-list-item__name dw-mod", 1972 ButtonLayout = ButtonLayout.None, 1973 Title = settings.Title, 1974 OnClick = !string.IsNullOrEmpty(settings.OnClick) ? settings.OnClick : "" 1975 }) 1976 } 1977 else if (!string.IsNullOrEmpty(settings.OnClick)) 1978 { 1979 <span class="media-list-item__name dw-mod" onclick="@(settings.OnClick)">@settings.Title</span> 1980 } 1981 else 1982 { 1983 <span class="media-list-item__name media-list-item__name--no-link dw-mod">@settings.Title</span> 1984 } 1985 } 1986 1987 @if (!string.IsNullOrEmpty(settings.Status)) 1988 { 1989 <div class="media-list-item__state dw-mod">@settings.Status</div> 1990 } 1991 </div> 1992 @{ 1993 settings.InfoTable.CssClass += " media-list-item__parameters-table"; 1994 } 1995 1996 @Render(settings.InfoTable) 1997 </div> 1998 <div class="media-list-item__actions dw-mod"> 1999 <div class="media-list-item__actions-list dw-mod"> 2000 @{ 2001 var actions = settings.GetActions(); 2002 2003 foreach (ButtonBase action in actions) 2004 { 2005 action.ButtonLayout = ButtonLayout.None; 2006 action.CssClass += " media-list-item__action link"; 2007 2008 @Render(action) 2009 } 2010 } 2011 </div> 2012 2013 @if (settings.SelectButton != null && !string.IsNullOrEmpty(settings.SelectButton.Title)) 2014 { 2015 settings.SelectButton.CssClass += " u-no-margin"; 2016 2017 <div class="media-list-item__action-button"> 2018 @Render(settings.SelectButton) 2019 </div> 2020 } 2021 </div> 2022 </div> 2023 </div> 2024 } 2025 @using Dynamicweb.Rapido.Blocks.Components.General 2026 @using Dynamicweb.Rapido.Blocks.Components 2027 2028 @helper RenderTable(Table settings) 2029 { 2030 Dictionary<string, string> attributes = new Dictionary<string, string>(); 2031 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); } 2032 2033 var enumToClasses = new Dictionary<TableDesign, string> 2034 { 2035 { TableDesign.Clean, "table--clean" }, 2036 { TableDesign.Bordered, "table--bordered" }, 2037 { TableDesign.Striped, "table--striped" }, 2038 { TableDesign.Hover, "table--hover" }, 2039 { TableDesign.Compact, "table--compact" }, 2040 { TableDesign.Condensed, "table--condensed" }, 2041 { TableDesign.NoTopBorder, "table--no-top-border" } 2042 }; 2043 string tableDesignClass = ""; 2044 if (settings.Design != TableDesign.None) 2045 { 2046 tableDesignClass = enumToClasses[settings.Design]; 2047 } 2048 2049 if (!string.IsNullOrEmpty(settings.CssClass) || settings.Design != TableDesign.None) { attributes.Add("class", "table " + tableDesignClass + " " + settings.CssClass + " dw-mod"); } 2050 2051 var resultAttributes = attributes.Concat(settings.ExtraAttributes).GroupBy(d => d.Key).ToDictionary(d => d.Key, d => d.Last().Value); 2052 2053 <table @ComponentMethods.AddAttributes(resultAttributes)> 2054 @if (settings.Header != null) 2055 { 2056 <thead> 2057 @Render(settings.Header) 2058 </thead> 2059 } 2060 <tbody> 2061 @foreach (var row in settings.Rows) 2062 { 2063 @Render(row) 2064 } 2065 </tbody> 2066 @if (settings.Footer != null) 2067 { 2068 <tfoot> 2069 @Render(settings.Footer) 2070 </tfoot> 2071 } 2072 </table> 2073 } 2074 @using Dynamicweb.Rapido.Blocks.Components.General 2075 @using Dynamicweb.Rapido.Blocks.Components 2076 2077 @helper RenderTableRow(TableRow settings) 2078 { 2079 Dictionary<string, string> attributes = new Dictionary<string, string>(); 2080 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); } 2081 2082 var enumToClasses = new Dictionary<TableRowDesign, string> 2083 { 2084 { TableRowDesign.NoBorder, "table__row--no-border" }, 2085 { TableRowDesign.Border, "table__row--border" }, 2086 { TableRowDesign.TopBorder, "table__row--top-line" }, 2087 { TableRowDesign.BottomBorder, "table__row--bottom-line" }, 2088 { TableRowDesign.Solid, "table__row--solid" } 2089 }; 2090 2091 string tableRowDesignClass = ""; 2092 if (settings.Design != TableRowDesign.None) 2093 { 2094 tableRowDesignClass = enumToClasses[settings.Design]; 2095 } 2096 2097 if (!string.IsNullOrEmpty(settings.CssClass) || settings.Design != TableRowDesign.None) { attributes.Add("class", "table__row " + tableRowDesignClass + " " + settings.CssClass + " dw-mod"); } 2098 2099 var resultAttributes = attributes.Concat(settings.ExtraAttributes).GroupBy(d => d.Key).ToDictionary(d => d.Key, d => d.Last().Value); 2100 2101 <tr @ComponentMethods.AddAttributes(resultAttributes)> 2102 @foreach (var cell in settings.Cells) 2103 { 2104 if (settings.IsHeaderRow) 2105 { 2106 cell.IsHeader = true; 2107 } 2108 @Render(cell) 2109 } 2110 </tr> 2111 } 2112 @using Dynamicweb.Rapido.Blocks.Components.General 2113 @using Dynamicweb.Rapido.Blocks.Components 2114 @using Dynamicweb.Core 2115 2116 @helper RenderTableCell(TableCell settings) 2117 { 2118 Dictionary<string, string> attributes = new Dictionary<string, string>(); 2119 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); } 2120 if (settings.Colspan != 0) { attributes.Add("colspan", Converter.ToString(settings.Colspan)); } 2121 if (settings.Rowspan != 0) { attributes.Add("rowspan", Converter.ToString(settings.Rowspan)); } 2122 if (!string.IsNullOrEmpty(settings.CssClass)) { attributes.Add("class", settings.CssClass + " dw-mod"); } 2123 2124 var resultAttributes = attributes.Concat(settings.ExtraAttributes).GroupBy(d => d.Key).ToDictionary(d => d.Key, d => d.Last().Value); 2125 2126 string tagName = settings.IsHeader ? "th" : "td"; 2127 2128 @("<" + tagName + " " + ComponentMethods.AddAttributes(resultAttributes) + ">") 2129 @settings.Content 2130 @("</" + tagName + ">"); 2131 } 2132 @using System.Linq 2133 @using Dynamicweb.Rapido.Blocks.Components.General 2134 2135 @* Component *@ 2136 2137 @helper RenderPagination(Dynamicweb.Rapido.Blocks.Components.General.Pagination settings) 2138 { 2139 var pageNumberQueryStringName = Dynamicweb.Rapido.Services.Pagination.GetPageNumberQueryStringName(settings); // Get the proper 'page number' query string parameter 2140 var queryParameters = Dynamicweb.Rapido.Services.Url.GetQueryParameters(pageNumberQueryStringName); // Get the NameValueCollection from the querystring 2141 2142 if (settings.NumberOfPages > 1) 2143 { 2144 string url = HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority) + "/Default.aspx"; 2145 string ariaLabel = !string.IsNullOrWhiteSpace(settings.AriaLabel) ? settings.AriaLabel : Translate("Page navigation"); 2146 Dictionary<string, int> startAndEndPageNumber = Dynamicweb.Rapido.Services.Pagination.GetStartAndEndPageNumber(settings); 2147 2148 <div class="pager u-margin-top dw-mod @settings.CssClass" aria-label="@ariaLabel"> 2149 @if (settings.ShowPagingInfo) 2150 { 2151 <div class="pager__info dw-mod"> 2152 @Translate("Page") @settings.CurrentPageNumber @Translate("of") @settings.NumberOfPages 2153 </div> 2154 } 2155 <ul class="pager__list dw-mod"> 2156 @if (!string.IsNullOrWhiteSpace(settings.FirstPageUrl) && settings.ShowFirstAndLastControls) 2157 { 2158 @Render(new PaginationItem { Link = settings.FirstPageUrl, Icon = settings.FirstIcon }) 2159 } 2160 @if (!string.IsNullOrWhiteSpace(settings.PreviousPageUrl) && settings.ShowNextAndPrevControls) 2161 { 2162 @Render(new PaginationItem { Link = settings.PreviousPageUrl, Icon = settings.PrevIcon }) 2163 } 2164 @if (settings.GetPages().Any()) 2165 { 2166 foreach (var page in settings.GetPages()) 2167 { 2168 @Render(page) 2169 } 2170 } 2171 else 2172 { 2173 for (var page = startAndEndPageNumber["StartPage"]; page <= startAndEndPageNumber["EndPage"]; page++) 2174 { 2175 queryParameters = Dynamicweb.Rapido.Services.Url.UpdateQueryStringParameter(queryParameters, pageNumberQueryStringName, page.ToString()); 2176 @Render(new PaginationItem { Label = page.ToString(), Link = Dynamicweb.Rapido.Services.Url.BuildUri(url, queryParameters).PathAndQuery, IsActive = (settings.CurrentPageNumber == page) }); 2177 } 2178 } 2179 @if (!string.IsNullOrWhiteSpace(settings.NextPageUrl) && settings.ShowNextAndPrevControls) 2180 { 2181 @Render(new PaginationItem { Link = settings.NextPageUrl, Icon = settings.NextIcon }) 2182 } 2183 @if (!string.IsNullOrWhiteSpace(settings.LastPageUrl) && settings.ShowFirstAndLastControls) 2184 { 2185 @Render(new PaginationItem { Link = settings.LastPageUrl, Icon = settings.LastIcon }) 2186 } 2187 </ul> 2188 </div> 2189 } 2190 } 2191 2192 @helper RenderPaginationItem(PaginationItem settings) 2193 { 2194 if (settings.Icon == null) 2195 { 2196 settings.Icon = new Icon(); 2197 } 2198 2199 settings.Icon.Label = settings.Label; 2200 <li class="pager__btn dw-mod"> 2201 @if (settings.IsActive) 2202 { 2203 <span class="pager__num pager__num--current dw-mod"> 2204 @Render(settings.Icon) 2205 </span> 2206 } 2207 else 2208 { 2209 <a href="@settings.Link" class="pager__num dw-mod"> 2210 @Render(settings.Icon) 2211 </a> 2212 } 2213 </li> 2214 } 2215 2216 2217 @using Dynamicweb.Rapido.Blocks.Components.General 2218 @using Dynamicweb.Rapido.Blocks.Components.Ecommerce 2219 2220 2221 @using Dynamicweb.Rapido.Blocks.Components 2222 @using Dynamicweb.Rapido.Blocks.Components.General 2223 @using Dynamicweb.Rapido.Blocks 2224 @using System.IO 2225 2226 2227 @using Dynamicweb.Rapido.Blocks.Components.General 2228 @using Dynamicweb.Rapido.Blocks.Components.Ecommerce 2229 2230 2231 @* Component *@ 2232 2233 @helper RenderVariantMatrix(VariantMatrix settings) { 2234 if (settings != null) 2235 { 2236 int productLoopCounter = 0; 2237 int groupCount = 0; 2238 List<VariantOption> firstDimension = new List<VariantOption>(); 2239 List<VariantOption> secondDimension = new List<VariantOption>(); 2240 List<VariantOption> thirdDimension = new List<VariantOption>(); 2241 2242 foreach (VariantGroup variantGroup in settings.GetVariantGroups()) 2243 { 2244 foreach (VariantOption variantOptions in variantGroup.GetVariantOptions()) 2245 { 2246 if (groupCount == 0) { 2247 firstDimension.Add(variantOptions); 2248 } 2249 if (groupCount == 1) 2250 { 2251 secondDimension.Add(variantOptions); 2252 } 2253 if (groupCount == 2) 2254 { 2255 thirdDimension.Add(variantOptions); 2256 } 2257 } 2258 groupCount++; 2259 } 2260 2261 int rowCount = 0; 2262 int columnCount = 0; 2263 2264 <script> 2265 var variantsCollection = []; 2266 </script> 2267 2268 <table class="table table--compact js-variants-matrix dw-mod" id="VariantMatrixTable_@settings.ProductId"> 2269 @if (groupCount == 1) 2270 { 2271 <tbody> 2272 @foreach (VariantOption firstVariantOption in firstDimension) 2273 { 2274 var variantId = firstVariantOption.Id; 2275 <tr> 2276 <td class="u-bold"> 2277 @firstVariantOption.Name 2278 </td> 2279 <td> 2280 @RenderVariantMatrixQuantityField(variantId, settings, productLoopCounter, rowCount, columnCount) 2281 </td> 2282 </tr> 2283 productLoopCounter++; 2284 } 2285 2286 <tr> 2287 <td>&nbsp;</td> 2288 <td> 2289 <div class="qty-field js-total-qty-column-@columnCount dw-mod">0</div> 2290 </td> 2291 </tr> 2292 </tbody> 2293 } 2294 @if (groupCount == 2) 2295 { 2296 <thead> 2297 <tr> 2298 <td>&nbsp;</td> 2299 @foreach (VariantOption variant in secondDimension) 2300 { 2301 <td>@variant.Name</td> 2302 } 2303 </tr> 2304 </thead> 2305 <tbody> 2306 @foreach (VariantOption firstVariantOption in firstDimension) 2307 { 2308 string variantId = ""; 2309 columnCount = 0; 2310 2311 <tr> 2312 <td class="u-min-w120px">@firstVariantOption.Name</td> 2313 2314 @foreach (VariantOption secondVariantOption in secondDimension) 2315 { 2316 variantId = firstVariantOption.Id + "." + secondVariantOption.Id; 2317 <td> 2318 @RenderVariantMatrixQuantityField(variantId, settings, productLoopCounter, rowCount, columnCount) 2319 </td> 2320 2321 columnCount++; 2322 2323 productLoopCounter++; 2324 } 2325 2326 <td> 2327 <div class="qty-field js-total-qty-row-@rowCount dw-mod">0</div> 2328 </td> 2329 </tr> 2330 2331 rowCount++; 2332 } 2333 2334 @{ 2335 columnCount = 0; 2336 } 2337 2338 <tr> 2339 <td>&nbsp;</td> 2340 @foreach (VariantOption secondVariantOption in secondDimension) 2341 { 2342 <td> 2343 <div class="qty-field js-total-qty-column-@columnCount dw-mod">0</div> 2344 </td> 2345 2346 columnCount++; 2347 } 2348 <td>&nbsp;</td> 2349 </tr> 2350 </tbody> 2351 } 2352 @if (groupCount == 3) 2353 { 2354 <thead> 2355 <tr> 2356 <td>&nbsp;</td> 2357 @foreach (VariantOption thirdVariantOption in thirdDimension) 2358 { 2359 <td>@thirdVariantOption.Name</td> 2360 } 2361 </tr> 2362 </thead> 2363 <tbody> 2364 @foreach (VariantOption firstVariantOption in firstDimension) 2365 { 2366 int colspan = (thirdDimension.Count + 1); 2367 2368 <tr> 2369 <td colspan="@colspan" class="u-color-light-gray--bg u-bold">@firstVariantOption.Name</td> 2370 </tr> 2371 2372 foreach (VariantOption secondVariantOption in secondDimension) 2373 { 2374 string variantId = ""; 2375 columnCount = 0; 2376 2377 <tr> 2378 <td class="u-min-w120px">@secondVariantOption.Name</td> 2379 2380 @foreach (VariantOption thirdVariantOption in thirdDimension) 2381 { 2382 variantId = firstVariantOption.Id + "." + secondVariantOption.Id + "." + thirdVariantOption.Id; 2383 2384 <td> 2385 @RenderVariantMatrixQuantityField(variantId, settings, productLoopCounter, rowCount, columnCount) 2386 </td> 2387 2388 columnCount++; 2389 productLoopCounter++; 2390 } 2391 2392 <td> 2393 <div class="qty-field js-total-qty-row-@rowCount dw-mod">0</div> 2394 </td> 2395 </tr> 2396 rowCount++; 2397 } 2398 } 2399 2400 @{ 2401 columnCount = 0; 2402 } 2403 2404 <tr> 2405 <td>&nbsp;</td> 2406 @foreach (VariantOption thirdVariantOption in thirdDimension) 2407 { 2408 <td> 2409 <div class="qty-field js-total-qty-column-@columnCount dw-mod">0</div> 2410 </td> 2411 2412 columnCount++; 2413 } 2414 <td>&nbsp;</td> 2415 </tr> 2416 </tbody> 2417 } 2418 </table> 2419 2420 <script> 2421 document.addEventListener("DOMContentLoaded", function (event) { 2422 MatrixUpdateQuantity("@settings.ProductId"); 2423 }); 2424 2425 MatrixUpdateQuantity = function (productId) { 2426 var currentMatrix = document.getElementById("VariantMatrixTable_" + productId); 2427 var allQtyFields = currentMatrix.getElementsByClassName("js-qty"); 2428 2429 var qtyRowArr = []; 2430 var qtyColumnArr = []; 2431 2432 var totalQty = 0; 2433 2434 for (var i = 0; i < allQtyFields.length; i++) { 2435 qtyRowArr[allQtyFields[i].getAttribute("data-qty-row-group")] = 0; 2436 qtyColumnArr[allQtyFields[i].getAttribute("data-qty-column-group")] = 0; 2437 } 2438 2439 for (var i = 0; i < allQtyFields.length; i++) { 2440 qtyRowArr[allQtyFields[i].getAttribute("data-qty-row-group")] += parseFloat(allQtyFields[i].value); 2441 qtyColumnArr[allQtyFields[i].getAttribute("data-qty-column-group")] += parseFloat(allQtyFields[i].value); 2442 totalQty += parseFloat(allQtyFields[i].value); 2443 } 2444 2445 //Update row counters 2446 for (var i = 0; i < qtyRowArr.length; i++) { 2447 var qtyCounter = currentMatrix.getElementsByClassName("js-total-qty-row-" + i)[0]; 2448 2449 if (qtyRowArr[i] != undefined && qtyCounter != null) { 2450 var currentCount = qtyCounter.innerHTML; 2451 qtyCounter.innerHTML = qtyRowArr[i]; 2452 2453 if (currentCount != qtyCounter.innerHTML) { 2454 qtyCounter.classList.add("qty-field--active"); 2455 } 2456 } 2457 2458 } 2459 2460 //Update column counters 2461 for (var i = 0; i < qtyColumnArr.length; i++) { 2462 var qtyCounter = currentMatrix.getElementsByClassName("js-total-qty-column-" + i)[0]; 2463 2464 if (qtyColumnArr[i] != undefined && qtyCounter != null) { 2465 var currentCount = qtyCounter.innerHTML; 2466 qtyCounter.innerHTML = qtyColumnArr[i]; 2467 2468 if (currentCount != qtyCounter.innerHTML) { 2469 qtyCounter.classList.add("qty-field--active"); 2470 } 2471 } 2472 } 2473 2474 if (document.getElementById("TotalQtyCount_" + productId)) { 2475 document.getElementById("TotalQtyCount_" + productId).innerHTML = totalQty; 2476 } 2477 2478 //Clean up animations 2479 setTimeout(function () { 2480 for (var i = 0; i < qtyRowArr.length; i++) { 2481 var qtyCounter = currentMatrix.getElementsByClassName("js-total-qty-row-" + i)[0]; 2482 if (qtyCounter != null) { 2483 qtyCounter.classList.remove("qty-field--active"); 2484 } 2485 } 2486 for (var i = 0; i < qtyColumnArr.length; i++) { 2487 var qtyCounter = currentMatrix.getElementsByClassName("js-total-qty-column-" + i)[0]; 2488 if (qtyCounter != null) { 2489 qtyCounter.classList.remove("qty-field--active"); 2490 } 2491 } 2492 }, 1000); 2493 } 2494 </script> 2495 } 2496 } 2497 2498 @helper RenderVariantMatrixQuantityField(string variantId, VariantMatrix settings, int productLoopCounter, int rowCount, int columnCount) 2499 { 2500 string loopCount = productLoopCounter.ToString(); 2501 2502 bool combinationFound = false; 2503 double stock = 0; 2504 double quantityValue = 0; 2505 string note = ""; 2506 2507 VariantProduct variantProduct = null; 2508 2509 if (settings.GetVariantProducts().TryGetValue(variantId, out variantProduct)) 2510 { 2511 stock = variantProduct.Stock; 2512 quantityValue = variantProduct.Quantity; 2513 combinationFound = true; 2514 } 2515 2516 if (combinationFound) 2517 { 2518 <input type="hidden" name="ProductLoopCounter@(loopCount)" value="@loopCount" /> 2519 <input type="hidden" name="ProductID@(loopCount)" value="@settings.ProductId" /> 2520 <input type="hidden" name="VariantID@(loopCount)" value="@variantId" /> 2521 <input type="hidden" name="CurrentNote@(loopCount)" id="CurrentNote_@(settings.ProductId)_@variantId" value="@note" /> 2522 <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"> 2523 2524 if (stock != 0) 2525 { 2526 <small>@Translate("Stock") @stock</small> 2527 } 2528 2529 <script> 2530 var variants = '{ "ProductId" :' + '"@settings.ProductId"' + ', "VariantId": ' + '"@variantId"' +'}'; 2531 variantsCollection.push(variants); 2532 document.getElementById("Quantity_@(settings.ProductId)_@variantId").closest(".js-variants-matrix").setAttribute("data-variants-collection", "[" + variantsCollection + "]" ); 2533 </script> 2534 } 2535 else 2536 { 2537 <div class="use-btn-height" style="background-color: #a8a8a8"></div> 2538 } 2539 } 2540 @using Dynamicweb.Rapido.Blocks.Components.Ecommerce 2541 2542 @* Component *@ 2543 2544 @helper RenderAddToCart(AddToCart settings) 2545 { 2546 //set Id for quantity selector to get it's value from button 2547 if (settings.QuantitySelector != null) 2548 { 2549 if (string.IsNullOrEmpty(settings.QuantitySelector.Id)) 2550 { 2551 settings.QuantitySelector.Id = Guid.NewGuid().ToString("N"); 2552 } 2553 2554 settings.AddButton.QuantitySelectorId = settings.QuantitySelector.Id; 2555 2556 if (settings.Disabled) 2557 { 2558 settings.QuantitySelector.Disabled = true; 2559 } 2560 2561 if (string.IsNullOrEmpty(settings.QuantitySelector.Name)) 2562 { 2563 settings.QuantitySelector.Name = settings.QuantitySelector.Id; 2564 } 2565 } 2566 2567 if (settings.Disabled) 2568 { 2569 settings.AddButton.Disabled = true; 2570 } 2571 2572 settings.AddButton.CssClass += " btn--condensed"; 2573 2574 //unitsSelector 2575 if (settings.UnitSelector != null) 2576 { 2577 if (settings.Disabled) 2578 { 2579 settings.QuantitySelector.Disabled = true; 2580 } 2581 } 2582 2583 <div class="buttons-collection @settings.WrapperCssClass" @ComponentMethods.AddAttributes(settings.ExtraAttributes)> 2584 @if (settings.UnitSelector != null) 2585 { 2586 @Render(settings.UnitSelector) 2587 } 2588 @if (settings.QuantitySelector != null) 2589 { 2590 @Render(settings.QuantitySelector) 2591 } 2592 @Render(settings.AddButton) 2593 </div> 2594 } 2595 @using Dynamicweb.Rapido.Blocks.Components.Ecommerce 2596 2597 @* Component *@ 2598 2599 @helper RenderAddToCartButton(AddToCartButton settings) 2600 { 2601 if (!settings.HideTitle) 2602 { 2603 if (string.IsNullOrEmpty(settings.Title)) 2604 { 2605 if (settings.BuyForPoints) 2606 { 2607 settings.Title = Translate("Buy with points"); 2608 } 2609 else 2610 { 2611 settings.Title = Translate("Add to cart"); 2612 } 2613 } 2614 } 2615 else 2616 { 2617 settings.Title = ""; 2618 } 2619 2620 if (settings.Icon == null) 2621 { 2622 settings.Icon = new Icon(); 2623 settings.Icon.LabelPosition = Dynamicweb.Rapido.Blocks.Components.General.IconLabelPosition.After; 2624 } 2625 2626 if (string.IsNullOrEmpty(settings.Icon.Name)) 2627 { 2628 settings.Icon.Name = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon").SelectedValue; 2629 } 2630 2631 settings.OnClick = "Cart.AddToCart(event, { " + 2632 "id: '" + settings.ProductId + "'," + 2633 (!string.IsNullOrEmpty(settings.VariantId) ? "variantId: '" + settings.VariantId + "'," : "") + 2634 (!string.IsNullOrEmpty(settings.UnitId) ? "unitId: '" + settings.UnitId + "'," : "") + 2635 (settings.BuyForPoints ? "buyForPoints: true," : "") + 2636 (!string.IsNullOrEmpty(settings.ProductInfo) ? "productInfo: " + settings.ProductInfo + "," : "") + 2637 "quantity: " + (string.IsNullOrEmpty(settings.QuantitySelectorId) ? "1" : "parseFloat(document.getElementById('" + settings.QuantitySelectorId + "').value)") + 2638 "});" + settings.OnClick; 2639 2640 @RenderButton(settings) 2641 } 2642 @using Dynamicweb.Rapido.Blocks.Components.Ecommerce 2643 2644 @* Component *@ 2645 2646 @helper RenderUnitSelector(UnitSelector settings) 2647 { 2648 if (string.IsNullOrEmpty(settings.Id)) 2649 { 2650 settings.Id = Guid.NewGuid().ToString("N"); 2651 } 2652 var disabledClass = settings.Disabled ? "disabled" : ""; 2653 2654 <input type="checkbox" id="@settings.Id" class="dropdown-trigger" /> 2655 <div class="dropdown unit-selector @settings.CssClass @disabledClass dw-mod" @ComponentMethods.AddAttributes(settings.ExtraAttributes)> 2656 <label class="dropdown__header dropdown__btn dropdown__btn--unit-selector dw-mod" for="@settings.Id">@settings.SelectedOption</label> 2657 <div class="dropdown__content dw-mod"> 2658 @settings.OptionsContent 2659 </div> 2660 <label class="dropdown-trigger-off" for="@settings.Id"></label> 2661 </div> 2662 } 2663 @using System.Reflection 2664 @using Dynamicweb.Rapido.Blocks.Components.Ecommerce 2665 2666 @* Component *@ 2667 2668 @helper RenderQuantitySelector(QuantitySelector settings) 2669 { 2670 var attributes = new Dictionary<string, string>(); 2671 2672 /*base settings*/ 2673 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); } 2674 if (!string.IsNullOrEmpty(settings.OnClick)) { attributes.Add("onclick", settings.OnClick); } 2675 if (!string.IsNullOrEmpty(settings.OnChange)) { attributes.Add("onchange", settings.OnChange); } 2676 if (settings.Disabled) { attributes.Add("disabled", "true"); } 2677 if (settings.Required) { attributes.Add("required", "true"); } 2678 if (!string.IsNullOrEmpty(settings.Name)) { attributes.Add("name", settings.Name); } 2679 /*end*/ 2680 2681 if (!string.IsNullOrEmpty(settings.OnKeyUp)) { attributes.Add("onkeyup", settings.OnKeyUp); } 2682 if (!string.IsNullOrEmpty(settings.OnInput)) { attributes.Add("oninput", settings.OnInput); } 2683 if (!string.IsNullOrEmpty(settings.OnFocus)) { attributes.Add("onfocus", settings.OnFocus); } 2684 if (settings.ReadOnly) { attributes.Add("readonly", "true"); } 2685 if (settings.Max != null) { attributes.Add("max", settings.Max.ToString()); } 2686 if (settings.Min == null) { settings.Min = 1; } 2687 attributes.Add("min", settings.Min.ToString()); 2688 if (settings.Step != null && !string.IsNullOrEmpty(settings.Step.ToString())) { attributes.Add("step", settings.Step.ToString()); } 2689 if (settings.Value == null) { settings.Value = 1; } 2690 attributes.Add("value", settings.Value.ToString()); 2691 attributes.Add("type", "number"); 2692 2693 var resultAttributes = attributes.Concat(settings.ExtraAttributes).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.Last().Value); 2694 2695 <input @ComponentMethods.AddAttributes(resultAttributes) class="@settings.CssClass dw-mod" /> 2696 } 2697 @using Dynamicweb.Rapido.Blocks.Components 2698 2699 @using Dynamicweb.Frontend 2700 @using Dynamicweb.Frontend.Devices 2701 @using Dynamicweb.Rapido.Blocks.Components.Ecommerce 2702 @using Dynamicweb.Rapido.Blocks.Components.General 2703 @using System.Collections.Generic; 2704 2705 @* Component *@ 2706 2707 @helper RenderCustomerCenterList(CustomerCenterList settings) 2708 { 2709 bool isTouchDevice = Pageview.Device.ToString() == "Mobile" || Pageview.Device.ToString() == "Tablet" ? true : false; 2710 string hideActions = isTouchDevice ? "u-block" : ""; 2711 2712 <table class="table data-list dw-mod"> 2713 @if (settings.GetHeaders().Length > 0) { 2714 <thead> 2715 <tr class="u-bold"> 2716 @foreach (CustomerCenterListHeaderItem header in settings.GetHeaders()) 2717 { 2718 var attributes = new Dictionary<string, string>(); 2719 if (!string.IsNullOrEmpty(header.Id)) { attributes.Add("id", header.Id); } 2720 if (!string.IsNullOrEmpty(header.CssClass)) { attributes.Add("class", header.CssClass); } 2721 attributes.Add("align", header.Align.ToString()); 2722 attributes = attributes.Concat(header.ExtraAttributes).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.Last().Value); 2723 2724 <td @ComponentMethods.AddAttributes(attributes)>@header.Title</td> 2725 } 2726 </tr> 2727 </thead> 2728 } 2729 @foreach (CustomerCenterListItem listItem in settings.GetItems()) 2730 { 2731 int columnCount = 0; 2732 int totalColumns = listItem.GetInfoItems().Length; 2733 string rowHasActions = listItem.GetActions().Length > 0 ? "data-list__item--has-acions" : ""; 2734 listItem.Id = !string.IsNullOrEmpty(listItem.Id) ? listItem.Id : Guid.NewGuid().ToString("N"); 2735 2736 var attributes = new Dictionary<string, string>(); 2737 if (!string.IsNullOrEmpty(listItem.Title)) { attributes.Add("title", listItem.Title); }; 2738 2739 attributes = attributes.Concat(listItem.ExtraAttributes).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.Last().Value); 2740 <tbody class="data-list__item @rowHasActions @listItem.CssClass dw-mod" @ComponentMethods.AddAttributes(attributes)> 2741 <tr> 2742 @if (!string.IsNullOrEmpty(listItem.Title) || !string.IsNullOrEmpty(listItem.Description)) { 2743 <td rowspan="2" onclick="@listItem.OnClick" class="data-list__main-item dw-mod"> 2744 @if (!string.IsNullOrEmpty(listItem.Title)) { 2745 <div class="u-bold">@listItem.Title</div> 2746 } 2747 @if (!string.IsNullOrEmpty(listItem.Description)) { 2748 <div>@listItem.Description</div> 2749 } 2750 </td> 2751 } 2752 2753 @foreach (CustomerCenterListInfoItem infoItem in listItem.GetInfoItems()) 2754 { 2755 var infoAttributes = new Dictionary<string, string>(); 2756 if (!string.IsNullOrEmpty(infoItem.Id)) { infoAttributes.Add("id", infoItem.Id); }; 2757 if (!string.IsNullOrEmpty(infoItem.OnClick)) { infoAttributes.Add("onclick", infoItem.OnClick); }; 2758 infoAttributes.Add("align", infoItem.Align.ToString()); 2759 2760 infoAttributes = infoAttributes.Concat(infoItem.ExtraAttributes).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.Last().Value); 2761 string columnClick = columnCount < (totalColumns-1) ? "onclick=\"" + listItem.OnClick + "\"" : ""; 2762 2763 <td @ComponentMethods.AddAttributes(infoAttributes) @columnClick class="data-list__info-item dw-mod"> 2764 @if (!string.IsNullOrEmpty(infoItem.Title)) { 2765 <div>@infoItem.Title</div> 2766 } 2767 @if (!string.IsNullOrEmpty(infoItem.Subtitle)) { 2768 <div><small>@infoItem.Subtitle</small></div> 2769 } 2770 </td> 2771 2772 columnCount++; 2773 } 2774 </tr> 2775 <tr> 2776 <td colspan="7" align="right" class="u-va-bottom u-no-border"> 2777 <div class="data-list__actions @hideActions dw-mod" id="ActionsMenu_@listItem.Id"> 2778 @foreach (ButtonBase action in listItem.GetActions()) 2779 { 2780 action.ButtonLayout = ButtonLayout.LinkClean; 2781 action.CssClass += " data-list__action-button link"; 2782 2783 @Render(action) 2784 } 2785 </div> 2786 </td> 2787 </tr> 2788 </tbody> 2789 } 2790 </table> 2791 } 2792 2793 @* Include the Blocks for the page *@ 2794 @using Dynamicweb.Ecommerce.ProductCatalog 2795 @using Dynamicweb.Rendering 2796 @using Smartpage.PhilipsonWine.Ratings 2797 @using Smartpage.PhilipsonWine.Ratings.Model 2798 @using System 2799 @using System.Web 2800 2801 @functions 2802 { 2803 //Expert rating values 2804 private (string ratingName, string ratingText, string ratingPercentage, string ratingImage) GetExpertRatingValues(ProductRating ExpertRating) 2805 { 2806 string ratingName = ""; 2807 string ratingText = ""; 2808 double ratingValue = 0; 2809 string ratingPercentage = ""; 2810 string ratingImage = ""; 2811 2812 if (ExpertRating != null) 2813 { 2814 ratingName = ExpertRating.RatingMedia; 2815 2816 if (ExpertRating.RatingType != "2") 2817 { 2818 if (ExpertRating.RatingScoreFrom == ExpertRating.RatingScoreTo) 2819 { 2820 ratingText = ExpertRating.RatingScoreTo; 2821 ratingValue = ((Converter.ToDouble(ExpertRating.RatingScoreTo) / Converter.ToDouble(ExpertRating.RatingMaxScore)) * 100); 2822 } 2823 else 2824 { 2825 ratingText = (ExpertRating.RatingScoreFrom + "<span class='small'>-</span>" + ExpertRating.RatingScoreTo); 2826 ratingValue = ((Converter.ToDouble(ExpertRating.RatingScoreFrom) / Converter.ToDouble(ExpertRating.RatingScoreTo)) * 100); 2827 } 2828 } 2829 else 2830 { 2831 ratingText = (ExpertRating.RatingScoreTo + "<span class='small'>/" + ExpertRating.RatingMaxScore + "</span>"); 2832 ratingValue = ((Converter.ToDouble(ExpertRating.RatingScoreTo) / Converter.ToDouble(ExpertRating.RatingMaxScore)) * 100); 2833 } 2834 2835 if (Double.IsNaN(ratingValue) || Double.IsInfinity(ratingValue)) 2836 { 2837 ratingPercentage = "100"; 2838 } 2839 else 2840 { 2841 ratingPercentage = Converter.ToString(ratingValue); 2842 } 2843 2844 ratingImage = ExpertRating.RatingImageMedia; 2845 } 2846 2847 return (ratingName: ratingName, ratingText: ratingText, ratingPercentage: ratingPercentage, ratingImage: ratingImage); 2848 } 2849 2850 2851 //Customer rating values 2852 2853 private (double ratingInPercent, string ratingInText, double ratingInDouble) GetCustomerRatingValues(double rating) 2854 { 2855 var ratingInPercent = ((rating / 5) * 100); 2856 string ratingInText = Converter.ToString(rating); 2857 2858 return (ratingInPercent: ratingInPercent, ratingInText: ratingInText, ratingInDouble: rating); 2859 } 2860 } 2861 2862 2863 @helper RenderRatingBadge(double ratingInPercent, string name, string value, bool customerRating = true, string image = "") 2864 { 2865 if (!string.IsNullOrEmpty(image)) 2866 { 2867 2868 var imagePath = "/Files/Images/ExpertRatings/" + image + ".png"; 2869 2870 var imagePrefix = "/Admin/Public/GetImage.ashx?width=46&amp;height=46&amp;crop=5&amp;Compression=75&amp;FillCanvas=true&amp;DoNotUpscale=true&amp;image=" + imagePath; 2871 2872 // CDN 2873 var cdnUrl = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetString("CDNUrl"); 2874 bool cdnActivate = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetBoolean("CDNActivate"); 2875 if (!string.IsNullOrWhiteSpace(cdnUrl) && cdnActivate) 2876 { 2877 imagePrefix = cdnUrl + imagePrefix; 2878 } 2879 2880 <div class="expert-rating-image"> 2881 <img class="rating-image" src="@imagePrefix" alt="@HttpUtility.HtmlAttributeEncode(name)" /> 2882 <span class="rating-image--score">@(new HtmlString(value))</span> 2883 </div> 2884 } 2885 else 2886 { 2887 <div class="rating-badge c100 @(customerRating ? "": "dark") js-badge" data-percent="@ratingInPercent"> 2888 <span class="rating-badge--text">@name</span> 2889 <span class="rating-badge--score">@(new HtmlString(value))</span> 2890 <div class="slice"> 2891 <div class="bar"></div> 2892 <div class="fill"></div> 2893 </div> 2894 </div> 2895 } 2896 } 2897 2898 @inherits ViewModelTemplate<ProductViewModel> 2899 @using Dynamicweb.Ecommerce.ProductCatalog 2900 @using Dynamicweb.Rendering 2901 @using Dynamicweb.Core 2902 @using System.Collections.Generic 2903 @using Dynamicweb.Rapido.Blocks 2904 @using Dynamicweb.Rapido.Blocks.Components.General 2905 @using System.Linq 2906 @using Smartpage.PhilipsonWine.Ecommerce.ProductInformation 2907 2908 @using System.Linq; 2909 @using Dynamicweb.Rapido.Blocks.Components.General 2910 @using System.Collections.Generic 2911 @using Dynamicweb.Core 2912 @using Dynamicweb.Ecommerce.ProductCatalog 2913 @using Dynamicweb.Frontend 2914 @using Dynamicweb.Rendering 2915 2916 2917 @functions{ 2918 Dictionary<string, StickersListPosition> stickerPositions = new Dictionary<string, StickersListPosition> 2919 { 2920 { "top-left", StickersListPosition.TopLeft }, 2921 { "top-right", StickersListPosition.TopRight }, 2922 { "bottom-left", StickersListPosition.BottomLeft }, 2923 { "bottom-right", StickersListPosition.BottomRight } 2924 }; 2925 2926 public void AddSticker(List<StickersCollection> list, Sticker sticker, StickersListPosition stickerPosition) 2927 { 2928 StickersCollection stickersContainerTemp = list.FirstOrDefault(stickersContainer => stickersContainer.Position == stickerPosition); 2929 if (stickersContainerTemp == null) 2930 { 2931 stickersContainerTemp = new StickersCollection() 2932 { 2933 Position = stickerPosition, 2934 Stickers = new List<Sticker>() 2935 }; 2936 list.Add(stickersContainerTemp); 2937 } 2938 stickersContainerTemp.Stickers.Add(sticker); 2939 } 2940 2941 public List<StickersCollection> GetStickersContainersList(IEnumerable<Dynamicweb.Ecommerce.Orders.Discounts.Discount> discountsLoop, double discountPrice, double price, DateTime createdDate, string customStickerValue, double percentSaved = 0) 2942 { 2943 bool pointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly"); 2944 bool isSaleStickersEnabled = Pageview.AreaSettings.GetItem("Ecommerce").GetItem("SaleSticker").GetBoolean("Enable"); 2945 bool isNewsStickersEnabled = Pageview.AreaSettings.GetItem("Ecommerce").GetItem("NewSticker").GetBoolean("Enable"); 2946 bool isCustomStickersEnabled = Pageview.AreaSettings.GetItem("Ecommerce").GetItem("CustomSticker").GetBoolean("Enable"); 2947 2948 List<StickersCollection> resultList = new List<StickersCollection>(); 2949 2950 if (!pointShopOnly && isSaleStickersEnabled) 2951 { 2952 string contentType = Pageview.AreaSettings.GetItem("Ecommerce").GetItem("SaleSticker").GetString("ContentType"); 2953 contentType = !string.IsNullOrEmpty(contentType) ? contentType : "Name"; 2954 var currency = Dynamicweb.Ecommerce.Services.Currencies.GetDefaultCurrency(); 2955 Sticker saleSticker = new Sticker(); 2956 saleSticker.CssClass = "stickers-container__tag--sale"; 2957 2958 switch (contentType) 2959 { 2960 case "Name": 2961 foreach (var discount in discountsLoop) 2962 { 2963 saleSticker.Title = discount.Name; 2964 } 2965 break; 2966 case "Amount": 2967 if (discountsLoop.Count() > 0) 2968 { 2969 saleSticker.Title = Dynamicweb.Ecommerce.Services.Currencies.Format(currency, discountPrice - price); 2970 } 2971 break; 2972 case "Percents": 2973 if (percentSaved > 0) 2974 { 2975 saleSticker.Title = "-" + percentSaved + "%"; 2976 } 2977 //NF20201015 - disabled because discount percent is calculated in PriceObject 2978 //else 2979 //{ 2980 // double percents = 0; 2981 // foreach (var discount in discountsLoop) 2982 // { 2983 // percents += discount.GetDouble("Ecom:Product.Discount.PercentWithoutVAT"); 2984 // percents += discount.Percentage; 2985 // } 2986 // if (percents > 0) 2987 // { 2988 // saleSticker.Title = "-" + Math.Round(percents, 0) + "%"; 2989 // } 2990 //} 2991 break; 2992 case "Amount and percents": 2993 double amount = 0; 2994 double percent = 0; 2995 foreach (var discount in discountsLoop) 2996 { 2997 if (Converter.ToString(discount.DiscountType) == "Percentage") 2998 { 2999 percent += discount.Percentage; 3000 } 3001 else if (Converter.ToString(discount.DiscountType) == "Amount") 3002 { 3003 amount += discount.Amount; 3004 } 3005 } 3006 3007 if (percent > 0) 3008 { 3009 saleSticker.Title = percent + "%"; 3010 } 3011 else if (amount > 0) 3012 { 3013 saleSticker.Title = "-" + Dynamicweb.Ecommerce.Services.Currencies.Format(currency, amount); 3014 } 3015 break; 3016 default: 3017 if (discountsLoop.Count() > 0) 3018 { 3019 saleSticker.Title = Translate("Sale!"); 3020 } 3021 break; 3022 } 3023 StickersListPosition saleStickerPosition = StickersListPosition.TopLeft; 3024 if (Pageview.AreaSettings.GetItem("Ecommerce").GetItem("SaleSticker").GetList("Position") != null) 3025 { 3026 string value = Pageview.AreaSettings.GetItem("Ecommerce").GetItem("SaleSticker").GetList("Position").SelectedValue; 3027 saleStickerPosition = stickerPositions.ContainsKey(value) ? stickerPositions[value] : stickerPositions["top-left"]; 3028 } 3029 if (!string.IsNullOrEmpty(saleSticker.Title)) 3030 { 3031 AddSticker(resultList, saleSticker, saleStickerPosition); 3032 } 3033 } 3034 3035 if (!pointShopOnly && isNewsStickersEnabled && createdDate.AddDays(Converter.ToDouble(Pageview.AreaSettings.GetItem("Ecommerce").GetItem("NewSticker").GetString("Expiration"))) > DateTime.Now) 3036 { 3037 Sticker newSticker = new Sticker(); 3038 newSticker.CssClass = "stickers-container__tag--new"; 3039 newSticker.Title = Translate("New!"); 3040 3041 StickersListPosition newStickerPosition = StickersListPosition.TopLeft; 3042 if (Pageview.AreaSettings.GetItem("Ecommerce").GetItem("NewSticker").GetList("Position") != null) 3043 { 3044 string value = Pageview.AreaSettings.GetItem("Ecommerce").GetItem("NewSticker").GetList("Position").SelectedValue; 3045 newStickerPosition = stickerPositions.ContainsKey(value) ? stickerPositions[value] : stickerPositions["top-left"]; 3046 } 3047 if (!string.IsNullOrEmpty(newSticker.Title)) 3048 { 3049 AddSticker(resultList, newSticker, newStickerPosition); 3050 } 3051 } 3052 3053 if (!pointShopOnly && isCustomStickersEnabled && !string.IsNullOrEmpty(customStickerValue)) 3054 { 3055 Sticker customSticker = new Sticker(); 3056 customSticker.CssClass = "stickers-container__tag--custom"; 3057 customSticker.Title = customStickerValue; 3058 3059 StickersListPosition customStickerPosition = StickersListPosition.TopLeft; 3060 if (Pageview.AreaSettings.GetItem("Ecommerce").GetItem("CustomSticker").GetList("Position") != null) 3061 { 3062 string value = Pageview.AreaSettings.GetItem("Ecommerce").GetItem("CustomSticker").GetList("Position").SelectedValue; 3063 customStickerPosition = stickerPositions.ContainsKey(value) ? stickerPositions[value] : stickerPositions["top-left"]; 3064 } 3065 if (!string.IsNullOrEmpty(customSticker.Title)) 3066 { 3067 AddSticker(resultList, customSticker, customStickerPosition); 3068 } 3069 } 3070 3071 return resultList; 3072 } 3073 } 3074 3075 @functions { 3076 BlocksPage mainImagePage = BlocksPage.GetBlockPage("Product"); 3077 bool showThumbs; 3078 bool thumbsOnTheSide; 3079 } 3080 3081 @{ 3082 int imageBlockWidth = Pageview.AreaSettings.GetItem("ProductPage").GetList("TopLayout") != null ? Converter.ToInt32(Pageview.AreaSettings.GetItem("ProductPage").GetList("TopLayout").SelectedValue) : 6; 3083 string blocksPosition = Pageview.AreaSettings.GetItem("ProductPage").GetList("ImageSectionPosition") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("ImageSectionPosition").SelectedValue : "thumbs-image-info"; 3084 bool infoOnTheRight = blocksPosition.LastIndexOf("info") == blocksPosition.Length - 4; 3085 showThumbs = blocksPosition.IndexOf("thumbs") != -1; 3086 thumbsOnTheSide = showThumbs && blocksPosition.IndexOf("thumbsBottom") == -1; 3087 bool thumbsOnTheLeft = blocksPosition.IndexOf("image") > blocksPosition.IndexOf("thumbs"); 3088 if (infoOnTheRight) 3089 { 3090 imageBlockWidth = 12 - imageBlockWidth; 3091 if (imageBlockWidth == 0) 3092 { 3093 imageBlockWidth = 12; 3094 } 3095 } 3096 3097 if (Pageview.Device.ToString() == "Mobile" || Pageview.Device.ToString() == "Tablet") 3098 { 3099 thumbsOnTheSide = false; 3100 } 3101 3102 Block mainImageBlock = new Block() 3103 { 3104 Id = "MainImage", 3105 SortId = infoOnTheRight ? 10 : 20, 3106 Design = new Design 3107 { 3108 Size = "4", 3109 RenderType = RenderType.Column, 3110 CssClass = "u-flex--row" 3111 }, 3112 BlocksList = new List<Block> 3113 { 3114 new Block { 3115 Id = "MainImageRow", 3116 SortId = 10, 3117 Design = new Design 3118 { 3119 RenderType = RenderType.Row 3120 }, 3121 //BlocksList = new List<Block> 3122 //{ 3123 // new Block 3124 // { 3125 // Id = "Carousel", 3126 // SortId = 10, 3127 // Template = RenderThumbnails(), 3128 // Design = new Design 3129 // { 3130 // Size = thumbsOnTheSide ? "2" : "12", 3131 // RenderType = RenderType.Column 3132 // } 3133 // } 3134 //} 3135 } 3136 } 3137 }; 3138 mainImagePage.Add("Top", mainImageBlock); 3139 3140 mainImagePage.Add("MainImageRow", 3141 new Block() 3142 { 3143 Id = "ProductImageModal", 3144 SortId = 0, 3145 Component = new Modal 3146 { 3147 Id = "Gallery", 3148 Width = ModalWidth.Lg, 3149 Height = ModalHeight.Full, 3150 BodyTemplate = RenderProductImagesCarousel("modalCarousel", 1, "horizontal", 3, true) 3151 } 3152 }); 3153 3154 if (showThumbs) 3155 { 3156 mainImagePage.Add("MainImageRow", 3157 new Block 3158 { 3159 Id = "Image", 3160 SortId = thumbsOnTheLeft ? 20 : 0, 3161 Template = RenderProductImage(), 3162 Design = new Design 3163 { 3164 Size = "10", 3165 RenderType = RenderType.Column 3166 } 3167 }); 3168 } 3169 } 3170 3171 @helper RenderProductStickers() 3172 { 3173 ProductInformation productInformation = new ProductInformation(Model); 3174 var priceObject = new Smartpage.PhilipsonWine.Ecommerce.Prices.PriceObject(Model.Id, productInformation.MaxPriceBasedOn, Model.Discount.Price, productInformation.OnSale); 3175 string customSticker = !string.IsNullOrWhiteSpace(productInformation.CustomSticker) ? productInformation.CustomSticker : ""; 3176 var discounts = Dynamicweb.Ecommerce.Services.Discounts.GetApplicableDiscountsForProduct(Model.Id, Model.VariantId, Dynamicweb.Ecommerce.Common.Context.LanguageID, Dynamicweb.Ecommerce.Common.Context.Currency, Dynamicweb.Security.UserManagement.User.GetCurrentExtranetUser()); 3177 3178 List<StickersCollection> StickersContainers = GetStickersContainersList( 3179 discounts, 3180 Model.Discount.Price, 3181 Model.Price.Price, 3182 Converter.ToDateTime(Model.Created), 3183 customSticker, 3184 priceObject.PercentSaved 3185 ); 3186 3187 foreach (StickersCollection stickersContainer in StickersContainers) 3188 { 3189 @Render(new StickersCollection { Stickers = stickersContainer.Stickers, Position = stickersContainer.Position }) 3190 } 3191 } 3192 3193 @helper RenderProductImage() 3194 { 3195 var productInformation = new ProductInformation(Model); 3196 string defaultImage = Model.ImagePatternImages.Any(i => i.Name == "Default") ? Model.ImagePatternImages.First(i => i.Name == "Default").Value : "Files/Images/missing_image.jpg"; 3197 //Add product image to the og meta data 3198 Pageview.Meta.AddTag("og:image", defaultImage); 3199 3200 <label for="GalleryModalTrigger" class="product__image-container u-position-relative"> 3201 @{ 3202 // Fetch image from ImagePattern images to take advantage of improved image patterns functionality 3203 Image productImage = new Image 3204 { 3205 Path = defaultImage, 3206 Id = "Image_" + Model.Id, 3207 CssClass = "u-middle product__image-container__image dw-mod", 3208 Title = HttpUtility.HtmlAttributeEncode(Model.Name), 3209 OnClick = "modalCarousel.GoToSlide('modalCarousel', this.getAttribute('data-number'))", 3210 ImageDefault = new ImageSettings 3211 { 3212 Width = 180, 3213 Height = 430, 3214 Crop = 5, 3215 FillCanvas = true 3216 }, 3217 ImageSmall = new ImageSettings 3218 { 3219 Width = 130, 3220 Height = 300, 3221 Crop = 5, 3222 FillCanvas = true 3223 } 3224 }; 3225 productImage.ExtraAttributes.Add("data-number", "0"); 3226 } 3227 @Render(productImage) 3228 @RenderProductStickers() 3229 @if (productInformation.Primeur) 3230 { 3231 <span class="top-label top-label--product-page"> 3232 <span class="top-label__label"> 3233 @Translate("Primeur", "Primeur") 3234 </span> 3235 </span> 3236 } 3237 </label> 3238 } 3239 3240 @helper RenderThumbnails() 3241 { 3242 <div class="@(showThumbs ? "product__thumbs" : "") dw-mod"> 3243 @RenderProductImagesCarousel( 3244 "productCarousel", 3245 !showThumbs ? 1 : 5, 3246 thumbsOnTheSide ? "vertical" : "horizontal", 3247 !showThumbs ? 3 : 2 3248 ) 3249 @if (!showThumbs) 3250 { 3251 @RenderProductStickers() 3252 } 3253 </div> 3254 } 3255 3256 @helper RenderProductImagesCarousel(string id, int slidesInView, string direction, int preloaderSize, bool isModal = false) 3257 { 3258 //var apiProduct = Dynamicweb.Ecommerce.Services.Products.GetProductById(Model.Id, Model.VariantId, true); 3259 3260 HashSet<string> images = new HashSet<string>(); 3261 3262 foreach (var alternativeImage in Model.ImagePatternImages) 3263 { 3264 string alt_image = alternativeImage.Value; 3265 3266 if (!string.IsNullOrEmpty(alt_image)) 3267 { 3268 images.Add(alt_image); 3269 } 3270 } 3271 3272 foreach (var detail in Model.AssetCategories) 3273 { 3274 foreach (var asset in detail.Assets) 3275 { 3276 string detail_image = asset.Value; 3277 3278 if (!string.IsNullOrEmpty(detail_image)) 3279 { 3280 string ext = Path.GetExtension(detail_image).ToLower(); 3281 if (ext == ".jpg" || ext == ".jpeg" || ext == ".gif" || ext == ".png") 3282 { 3283 images.Add(detail_image); 3284 } 3285 } 3286 3287 } 3288 } 3289 3290 // If no images then add default image to carousel 3291 if (!images.Any()) 3292 { 3293 images.Add("Files/Images/missing_image.jpg"); 3294 } 3295 3296 <div class="carousel dw-mod" id="@id"> 3297 <div class="thumb-list carousel__container @(slidesInView != 1 ? "carousel__container--hidden" : "") js-carousel-slides dw-mod"> 3298 @{ var i = 0; } 3299 @foreach (var image in images) 3300 { 3301 @RenderProductImage(image, slidesInView == 1, isModal ? "modal--full__img" : "", i == 0, isModal) 3302 i++; //first is active 3303 } 3304 </div> 3305 3306 <script> 3307 document.addEventListener("DOMContentLoaded", function () { 3308 @id = new CarouselModule('#@id', { 3309 slidesInView: @slidesInView, 3310 direction: "@direction", 3311 preloaderSize: @preloaderSize, 3312 showCounter: @isModal.ToString().ToLower() 3313 }); 3314 }); 3315 </script> 3316 </div> 3317 } 3318 3319 @helper RenderProductImage(string image, bool isBig, string cssClass = "", bool isActive = false, bool isModal = false) 3320 { 3321 string productId = Model.Id; 3322 string imagePrefix = "/Admin/Public/GetImage.ashx?width=800&amp;height=800&amp;crop=5&FillCanvas=True&DoNotUpscale=true&amp;Compression=75&amp;image="; 3323 3324 Image productImage = new Image 3325 { 3326 Path = image, 3327 Title = HttpUtility.HtmlAttributeEncode(Model.Name), 3328 ImageDefault = new ImageSettings 3329 { 3330 Width = 800, 3331 Height = 800, 3332 Crop = 5, 3333 FillCanvas = true 3334 }, 3335 CssClass = "u-middle " + cssClass, 3336 OnClick = "modalCarousel.GoToSlide('modalCarousel', this.closest('.carousel__slide').index());" 3337 }; 3338 productImage.ExtraAttributes.Add("data-image", image); 3339 3340 <div class="carousel__slide dw-mod"> 3341 @if (isModal) 3342 { 3343 @Render(productImage) 3344 @*@Render(new Image { Path = image, CssClass = cssClass, Title = Model.Name, DisableImageEngine = true });*@ 3345 } 3346 else if (isBig) 3347 { 3348 <label for="GalleryModalTrigger" class="u-middle"> 3349 @Render(productImage) 3350 </label> 3351 } 3352 else 3353 { 3354 Image productThumb = productImage; 3355 productThumb.ImageDefault = new ImageSettings 3356 { 3357 Width = 200, 3358 Height = 200, 3359 Crop = 5, 3360 FillCanvas = true 3361 }; 3362 productImage.CssClass += " thumb-list__image"; 3363 <div class="thumb-list__item dw-mod js-thumb js-gallery @(isActive ? "js-thumb--active thumb-list__item--active" : "")" data-for="Image_@productId" data-image="@imagePrefix@image" onmouseover="Gallery.openImage(this)"> 3364 <label for="GalleryModalTrigger" class="thumb-list__image-label"> 3365 @Render(productThumb) 3366 </label> 3367 </div> 3368 } 3369 </div> 3370 } 3371 @inherits ViewModelTemplate<ProductViewModel> 3372 @using Dynamicweb.Ecommerce.ProductCatalog 3373 @using Dynamicweb.Rendering 3374 @using Dynamicweb.Core 3375 @using System 3376 @using System.Web 3377 @using System.Collections.Generic 3378 @using Dynamicweb.Rapido.Services 3379 @using Dynamicweb.Rapido.Blocks 3380 @using Dynamicweb.Rapido.Blocks.Components.Ecommerce 3381 @using Dynamicweb.Rapido.Blocks.Components.General 3382 @using Smartpage.PhilipsonWine.Ecommerce.ProductInformation 3383 @using Smartpage.PhilipsonWine.Ratings; 3384 @using Smartpage.PhilipsonWine.Ratings.Model; 3385 3386 @functions { 3387 bool useFacebookPixel; 3388 bool useGoogleTagManager; 3389 BlocksPage mainInfoPage = BlocksPage.GetBlockPage("Product"); 3390 } 3391 3392 @{ 3393 var user = Dynamicweb.Security.UserManagement.User.get_Current(Dynamicweb.Security.UserManagement.PagePermissionLevels.Frontend); 3394 useFacebookPixel = !string.IsNullOrWhiteSpace(Pageview.AreaSettings.GetItem("Settings").GetString("FacebookPixelID")); 3395 useGoogleTagManager = !string.IsNullOrEmpty(Pageview.AreaSettings.GetItem("Settings").GetString("GoogleTagManagerID")); 3396 bool hidePrice = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HidePrice"); 3397 bool hideAddToCartButton = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("hideAddToCartButton"); 3398 3399 var productRatings = Dynamicweb.Content.Commenting.Comment.GetComments("ecomProduct", Model.Id, Model.LanguageId); 3400 var activeProductRatings = productRatings.Where(i => i.Active == true).OrderByDescending(i => i.Rating).ThenBy(i => i.CreatedDate); 3401 double totalRatingAmount = 0.0; 3402 //var mainInfoApiProduct = Dynamicweb.Ecommerce.Services.Products.GetProductById(Model.Id, Model.VariantId, true); 3403 ProductInformation mainInformationProductInformation = new ProductInformation(Model); 3404 3405 3406 foreach (var comment in activeProductRatings) 3407 { 3408 totalRatingAmount += comment.Rating; 3409 } 3410 3411 totalRatingAmount = (totalRatingAmount / activeProductRatings.Count()); 3412 3413 Block mainInfoHeader = new Block() 3414 { 3415 Id = "MainInfoHeader", 3416 SortId = 10, 3417 Template = RenderMainInfoHeader(productFields) 3418 }; 3419 mainInfoPage.Add("MainInformation", mainInfoHeader); 3420 3421 if (Model.Rating > 0 && !eventProduct) 3422 { 3423 Block mainInfoCustomerRatings = new Block() 3424 { 3425 Id = "MainInfoCustomerRatings", 3426 SortId = 11, 3427 Template = RenderCustomerRatings(Model.Rating) 3428 }; 3429 mainInfoPage.Add("MainInformation", mainInfoCustomerRatings); 3430 } 3431 3432 // Render divider if there are customer ratings or short description on the product 3433 if (Model.Rating > 0 || !string.IsNullOrWhiteSpace(Model.ShortDescription)) 3434 { 3435 Block mainInfoDivider = new Block() 3436 { 3437 Id = "MainInfoDivider", 3438 SortId = 12, 3439 Template = RenderDivider() 3440 }; 3441 mainInfoPage.Add("MainInformation", mainInfoDivider); 3442 } 3443 3444 if (!eventProduct) 3445 { 3446 Block mainInfoRatings = new Block() 3447 { 3448 Id = "MainInfoRatings", 3449 SortId = 13, 3450 Template = RenderRatings() 3451 }; 3452 mainInfoPage.Add("MainInformation", mainInfoRatings); 3453 } 3454 else 3455 { 3456 Block mainInfoEvent = new Block() 3457 { 3458 Id = "MainInfoEvent", 3459 SortId = 13, 3460 Template = RenderEventInfo(productFields) 3461 }; 3462 mainInfoPage.Add("MainInformation", mainInfoEvent); 3463 } 3464 3465 Block mainInfoDescription = new Block() 3466 { 3467 Id = "ShortDescription", 3468 SortId = 20, 3469 Template = RenderShortDescription() 3470 }; 3471 mainInfoPage.Add("MainInformation", mainInfoDescription); 3472 3473 string[] recommendations = !string.IsNullOrWhiteSpace(productFields.RecommendedTo) ? productFields.RecommendedTo.Split(',') : new string[] { }; 3474 3475 if (!eventProduct) 3476 { 3477 Block mainInfoRecommendations = new Block() 3478 { 3479 Id = "MainInfoRecommendations", 3480 SortId = 21, 3481 Template = RenderRecomendations(recommendations) 3482 }; 3483 mainInfoPage.Add("MainInformation", mainInfoRecommendations); 3484 } 3485 3486 if (user != null && User.IsBuyingAllowed() && GetPageIdByNavigationTag("OrderDraft") != 0) 3487 { 3488 Modal selectDraftModal = new Modal 3489 { 3490 Id = "OrderDraftSelect", 3491 Heading = new Heading { Title = Translate("Select draft cart"), Level = 2 }, 3492 BodyTemplate = RenderOrderDraftSelectModalContent(), 3493 Width = ModalWidth.Md 3494 }; 3495 selectDraftModal.AddAction(new Button { Title = Translate("Cancel"), OnClick = "document.getElementById('OrderDraftSelectModalTrigger').checked = false", ButtonLayout = ButtonLayout.Secondary }); 3496 selectDraftModal.AddAction(new Button { Title = Translate("Add"), OnClick = "addToSelectedCart()" }); 3497 3498 Block orderDraftSelect = new Block 3499 { 3500 Id = "OrderDraft", 3501 SortId = 90, 3502 Component = selectDraftModal 3503 }; 3504 mainInfoPage.Add("MainInformation", orderDraftSelect); 3505 3506 Modal notificationDraftModal = new Modal 3507 { 3508 Id = "OrderDraftNotification", 3509 Heading = new Heading { Title = Translate("Added to cart"), Level = 2 }, 3510 BodyText = Translate("The product has been added to the selected cart"), 3511 Width = ModalWidth.Md 3512 }; 3513 notificationDraftModal.AddAction(new Button { Title = Translate("View draft"), OnClick = "goToSelectedCart()", ButtonLayout = ButtonLayout.Secondary }); 3514 notificationDraftModal.AddAction(new Button { Title = Translate("Continue shopping"), OnClick = "document.getElementById('OrderDraftNotificationModalTrigger').checked = false" }); 3515 3516 Block orderDraftComplete = new Block 3517 { 3518 Id = "OrderDraftComplete", 3519 SortId = 100, 3520 Component = notificationDraftModal 3521 }; 3522 mainInfoPage.Add("MainInformation", orderDraftComplete); 3523 3524 3525 Block orderDraftScripts = new Block 3526 { 3527 Id = "OrderDraftScripts", 3528 SortId = 110, 3529 Template = RenderOrderDraftScripts() 3530 }; 3531 mainInfoPage.Add("MainInformation", orderDraftScripts); 3532 } 3533 } 3534 3535 @helper RenderMainInfoHeader(ProductInformation productInfo) 3536 { 3537 string producerId = productInfo.ProducerId; 3538 var producerService = new Smartpage.PhilipsonWine.Producer.Repositories.ProducerService(); 3539 var producer = producerService.GetProductProducer(producerId); 3540 3541 <div> 3542 <div class="u-pull--left product__title dw-mod"> 3543 @if (eventProduct) 3544 { 3545 <span class="area">@productInfo.EventRestaurantName - @productInfo.EventAddressShort - @productInfo.EventPromotionText</span> 3546 } 3547 else if (producer != null && !string.IsNullOrWhiteSpace(producer.ProducerName)) 3548 { 3549 <span class="area">@producer.ProducerName</span> 3550 } 3551 3552 <h1 class="u-no-margin product-name">@Model.Name </h1> 3553 </div> 3554 </div> 3555 } 3556 3557 @helper RenderCustomerRatings(double? rating, int padding = 0, bool showMore = true) 3558 { 3559 double ratingPercentage = (Converter.ToDouble(rating) / 5) * 100; 3560 3561 <div class="customer-ratings-container u-margin-top-big u-margin-bottom"> 3562 <div class="hearts" data-average-rating-percentage="@ratingPercentage" data-heart-padding="@padding"> 3563 <div class="hearts-outer"> 3564 <img src="/Files/Templates/Designs/Rapido/Images/VectorItemTypes/rating-full-grey-heart.svg" class="full-heart" /> 3565 <img src="/Files/Templates/Designs/Rapido/Images/VectorItemTypes/rating-full-grey-heart.svg" class="full-heart" /> 3566 <img src="/Files/Templates/Designs/Rapido/Images/VectorItemTypes/rating-full-grey-heart.svg" class="full-heart" /> 3567 <img src="/Files/Templates/Designs/Rapido/Images/VectorItemTypes/rating-full-grey-heart.svg" class="full-heart" /> 3568 <img src="/Files/Templates/Designs/Rapido/Images/VectorItemTypes/rating-full-grey-heart.svg" class="full-heart" /> 3569 <div class="hearts-inner"> 3570 <img src="/Files/Templates/Designs/Rapido/Images/VectorItemTypes/rating-full-red-heart.svg" class="full-heart" /> 3571 <img src="/Files/Templates/Designs/Rapido/Images/VectorItemTypes/rating-full-red-heart.svg" class="full-heart" /> 3572 <img src="/Files/Templates/Designs/Rapido/Images/VectorItemTypes/rating-full-red-heart.svg" class="full-heart" /> 3573 <img src="/Files/Templates/Designs/Rapido/Images/VectorItemTypes/rating-full-red-heart.svg" class="full-heart" /> 3574 <img src="/Files/Templates/Designs/Rapido/Images/VectorItemTypes/rating-full-red-heart.svg" class="full-heart" /> 3575 </div> 3576 </div> 3577 </div> 3578 @if (showMore) 3579 { 3580 <div class="rating">@rating <span class="rating__info-text">@Translate("Smartpage:ProductDetail.Rating.OutOfFive", "(ud af 5)") <a href="javascript:void(0)" onclick="scrollToNode('.js-customer-ratings-section')" class="rating__info-text--link small-link">@Translate("Smartpage:ProductDetail.Rating.SeeAll", "Se alle")</a></span></div> 3581 } 3582 </div> 3583 } 3584 3585 @helper RenderDivider() 3586 { 3587 <div class="divider"> 3588 <hr class="u-margin-top-big u-margin-bottom-big" /> 3589 </div> 3590 } 3591 3592 @helper RenderRatings() 3593 { 3594 3595 var ratings = Smartpage.PhilipsonWine.Ratings.Controller.ProductRatings.GetRatingProduct(Model.Id); 3596 if (ratings.Any()) 3597 { 3598 <div class="main-expert-ratings u-margin-top u-margin-bottom"> 3599 @foreach (var item in ratings.Where(x => x.RatingType != Converter.ToString((int)Smartpage.PhilipsonWine.Ratings.Controller.ProductRatings.RatingTypes.FullRating)).Take(3)) 3600 { 3601 <div class="main-expert-ratings__li"> 3602 <label class="main-expert-ratings__label">@item.RatingMedia</label> 3603 <span class="main-expert-ratings__span"> @RenderExpertRating(item.RatingScoreTo, item.RatingScoreFrom, item.RatingMaxScore, item.RatingType, item.RatingTextScore)</span> 3604 </div> 3605 } 3606 <span class="main-expert-ratings__link" onclick="scrollToNode('.js-expert-ratings', -56)">@Translate("Smartpage:Product.ViewAllExpertRatings", "Vis alle")</span> 3607 </div> 3608 } 3609 } 3610 3611 @helper RenderEventInfo(ProductInformation productInfo) 3612 { 3613 3614 <div class="event-info"><i class="far fa-calendar-alt event-info__icon"></i>@Converter.ToDateTime(productInfo.EventDate).ToString("dd. MMMM yyyy")</div> 3615 <div class="event-info"><i class="far fa-clock event-info__icon clock"></i> @Translate("Kl") @productInfo.EventFromTime @(!string.IsNullOrEmpty(productInfo.EventEndTime) ? Translate("til") + " " + Translate("Kl") + " " + productInfo.EventEndTime : "") </div> 3616 <div class="event-info"><i class="fas fa-map-marker-alt event-info__icon"></i>@productInfo.EventAddressLong</div> 3617 3618 @RenderDivider() 3619 } 3620 3621 @helper RenderExpertRating(string scoreTo, string scoreFrom, string scoreMax, string scoreType, string textScore) 3622 { 3623 3624 if (scoreType != "2" && scoreType != "3") 3625 { 3626 if (scoreFrom == scoreTo) 3627 { 3628 @(scoreTo + " " + Translate("point")) 3629 } 3630 else 3631 { 3632 @(scoreFrom + "/" + scoreTo) 3633 } 3634 3635 } 3636 else if (scoreType == "3") 3637 { 3638 @textScore 3639 } 3640 else 3641 { 3642 var missingStars = (Converter.ToInt32(scoreMax) - Converter.ToInt32(scoreTo)); 3643 3644 for (int i = 0; i < Converter.ToInt32(scoreTo); i++) 3645 { 3646 <i class="fas fa-star"></i> 3647 } 3648 3649 for (int i = 0; i < missingStars; i++) 3650 { 3651 <i class="fas fa-star u-color-light-gray"></i> 3652 } 3653 } 3654 } 3655 3656 @helper RenderShortDescription() 3657 { 3658 if (!string.IsNullOrEmpty(Model.ShortDescription)) 3659 { 3660 var description = Regex.Replace(Model.ShortDescription, "<.*?>", String.Empty); 3661 var metadescription = "<meta property=\"og:description\" content=\"" + description + "\">"; 3662 Pageview.Meta.AddTag(metadescription); 3663 Pageview.Meta.AddTag("description", description); 3664 3665 <div class="introduction-text u-margin-top u-margin-bottom"> 3666 @Model.ShortDescription 3667 <a class="small-link" href="javascript:void(0)" onclick="scrollToNode('.js-long-description', -56)">@Translate("Smartpage:ProductDetail.ShortDescription.ReadMore", "Læs mere")</a> 3668 </div> 3669 } 3670 } 3671 3672 @helper RenderRecomendations(string[] recommendations) 3673 { 3674 if (recommendations.Any()) 3675 { 3676 <div> 3677 <hr class="u-margin-top-big u-margin-bottom-big" /> 3678 <div class="reccommendations-container"> 3679 <span class="reccomendations-header">@Translate("Smartpage:ProductDetail.ReccomendedTo", "Anbefalet til")</span> 3680 <div class="reccomendations"> 3681 @foreach (var recommendation in recommendations) 3682 { 3683 <div class="reccomendations__reccommendation">@recommendation</div> 3684 } 3685 </div> 3686 </div> 3687 </div> 3688 } 3689 } 3690 3691 @helper RenderOrderDraftSelectModalContent() 3692 { 3693 var customerId = Dynamicweb.Security.UserManagement.User.GetCurrentExtranetUserId(); 3694 var shopId = Pageview.Area.EcomShopId; 3695 var orderType = Dynamicweb.Ecommerce.Orders.OrderType.Order; 3696 var cartsList = (List<Dynamicweb.Ecommerce.Orders.Order>)Dynamicweb.Ecommerce.Services.Orders.GetCustomerOrdersByType(customerId, shopId, orderType, 0, false, "", DateTime.MinValue, false, true); 3697 3698 SelectField cartSelector = new SelectField 3699 { 3700 Id = "CartSelector", 3701 Label = Translate("I want to add this product to") 3702 }; 3703 3704 foreach (Dynamicweb.Ecommerce.Orders.Order cart in cartsList) 3705 { 3706 string name = !string.IsNullOrEmpty(cart.DisplayName) ? cart.DisplayName : cart.Id; 3707 cartSelector.Options.Add(new SelectFieldOption { Label = name, Value = cart.Id }); 3708 } 3709 3710 @Render(cartSelector) 3711 } 3712 3713 @helper RenderOrderDraftScripts() 3714 { 3715 //var apiProduct = Dynamicweb.Ecommerce.Services.Products.GetProductById(Model.Id, Model.VariantId, true); 3716 string productId = Model.Id; 3717 string variantId = !string.IsNullOrEmpty(Model.VariantId) ? Model.VariantId : Model.VariantId; 3718 string unitId = Model.DefaultUnitId; 3719 var cartCmdUrl = "/Default.aspx?ID=" + Pageview.Page.ID; 3720 int orderDraftPageId = GetPageIdByNavigationTag("DraftDetails"); 3721 int orderDraftParagraphId = Dynamicweb.Services.Paragraphs.GetParagraphsByPageId(orderDraftPageId).ToList().First().ID; 3722 3723 <script> 3724 function addToSelectedCart() { 3725 var requestUrl = "@cartCmdUrl" + "&cartcmd=Add&Quantity=1" + "&CartId=" + document.getElementById("CartSelector").value + "&ProductId=@productId" + "&VariantId=@variantId" + "&UnitId=@unitId"; 3726 3727 console.log(requestUrl) 3728 3729 document.getElementById('OrderDraftSelectModalTrigger').checked = false; 3730 3731 var overlayElement = document.createElement('div'); 3732 overlayElement.className = "preloader-overlay"; 3733 overlayElement.setAttribute('id', "CartOverlay"); 3734 var overlayElementIcon = document.createElement('div'); 3735 overlayElementIcon.className = "preloader-overlay__icon dw-mod"; 3736 overlayElementIcon.style.top = window.pageYOffset + "px"; 3737 overlayElement.appendChild(overlayElementIcon); 3738 document.getElementById('content').parentNode.insertBefore(overlayElement, document.getElementById('content')); 3739 3740 Request.Fetch().get( 3741 requestUrl, 3742 function () { 3743 var overlayNode = document.getElementById('CartOverlay'); 3744 overlayNode.parentNode.removeChild(overlayNode); 3745 document.getElementById('OrderDraftNotificationModalTrigger').checked = true; 3746 }, 3747 null, 3748 false 3749 ); 3750 } 3751 3752 function goToSelectedCart() { 3753 window.location = "/Default.aspx?ID=" + "@orderDraftPageId" + "&CartID=" + document.getElementById('CartSelector').value + "&CartCmd=setcart" + "&redirect=false"; 3754 } 3755 </script> 3756 } 3757 3758 @if (useGoogleTagManager) 3759 { 3760 string mainInformationProducerId = mainInformationProductInformation.ProducerId; 3761 var producerService = new Smartpage.PhilipsonWine.Producer.Repositories.ProducerService(); 3762 var producer = producerService.GetProductProducer(mainInformationProducerId); 3763 3764 <script> 3765 // Measure a view of product details. This example assumes the detail view occurs on pageload, 3766 // and also tracks a standard pageview of the details page. 3767 dataLayer.push({ 3768 'event': 'productDetails', 3769 "ecommerce": { 3770 "detail": { 3771 "currencyCode": "@Model.Price.CurrencyCode", 3772 "actionField": {}, // 'detail' actions have an optional list property. 3773 "products": [{ 3774 "name": "@HttpUtility.HtmlEncode(Model.Name)", // Name or ID is required. 3775 "id": "@Model.Id", 3776 "price": "@(Model.Price.Price != Model.PriceBeforeDiscount.Price ? Model.Price.Price : Model.PriceBeforeDiscount.Price)", 3777 "brand": "@(producer != null ? producer.ProducerName : "")", 3778 "category": "@Model.PrimaryOrDefaultGroup.Name", 3779 "variant": "@(!string.IsNullOrEmpty(Model.VariantId) ? Model.VariantId : Model.VariantId)" 3780 }] 3781 } 3782 } 3783 }); 3784 </script> 3785 } 3786 @inherits ViewModelTemplate<ProductViewModel> 3787 @using Dynamicweb.Ecommerce.ProductCatalog 3788 @using Dynamicweb.Rendering 3789 @using Dynamicweb.Core 3790 @using System 3791 @using System.Web 3792 @using System.Collections.Generic 3793 @using Dynamicweb.Rapido.Services 3794 @using Dynamicweb.Rapido.Blocks 3795 @using Dynamicweb.Rapido.Blocks.Components.Ecommerce 3796 @using Smartpage.PhilipsonWine.Ecommerce.ProductInformation 3797 @using Smartpage.PhilipsonWine.FavoriteList.Controller; 3798 @using Smartpage.PhilipsonWine.EcomPrices; 3799 @using Smartpage.PhilipsonWine.EcomPrices.Models; 3800 3801 3802 @using Dynamicweb.Ecommerce.ProductCatalog 3803 @using Dynamicweb.Rendering 3804 3805 @functions 3806 { 3807 private string FormatPrice(double price) 3808 { 3809 return price.ToString("N2"); 3810 } 3811 } 3812 3813 @functions 3814 { 3815 BlocksPage productAddedToCartProductPage = BlocksPage.GetBlockPage("Product"); 3816 bool addToCartUseFacebookPixel; 3817 bool addToCartUseGoogleTagManager; 3818 3819 public class GoogleImpression 3820 { 3821 public string name { get; set; } 3822 public string id { get; set; } 3823 public string price { get; set; } 3824 public string brand { get; set; } 3825 public string category { get; set; } 3826 public string variant { get; set; } 3827 public string currency { get; set; } 3828 public string list { get; set; } 3829 public int position { get; set; } 3830 } 3831 public class FacebookAction 3832 { 3833 public string content_name { get; set; } 3834 public List<string> content_ids { get; set; } 3835 public string content_type { get; set; } 3836 public double value { get; set; } 3837 public string currency { get; set; } 3838 } 3839 } 3840 3841 @{ 3842 3843 addToCartUseFacebookPixel = !string.IsNullOrWhiteSpace(Pageview.AreaSettings.GetItem("Settings").GetString("FacebookPixelID")); 3844 addToCartUseGoogleTagManager = !string.IsNullOrEmpty(Pageview.AreaSettings.GetItem("Settings").GetString("GoogleTagManagerID")); 3845 3846 Block addedToCartSectionBlock = new Block() 3847 { 3848 Id = "MainAddToCartSection", 3849 SortId = 10, 3850 Template = RenderAddToCartSection() 3851 }; 3852 productAddedToCartProductPage.Add("AddToCartSection", addedToCartSectionBlock); 3853 3854 Block simpleAddedToCartSectionBlock = new Block() 3855 { 3856 Id = "MainSimpleAddToCartSection", 3857 SortId = 11, 3858 Template = RenderSimpleAddToCartSection() 3859 }; 3860 productAddedToCartProductPage.Add("AddToCartSection", simpleAddedToCartSectionBlock); 3861 3862 } 3863 3864 @helper RenderAddToCartSection() 3865 { 3866 var currentUser = Dynamicweb.Security.UserManagement.User.GetCurrentExtranetUser(); 3867 3868 //Get customer specific price and quantity 3869 CustomPrice customPrice = null; 3870 CustomPriceService.GetCustomPriceProducts(currentUser)?.TryGetValue(Model.Id, out customPrice); 3871 3872 <div class="add-to-cart-section-container"> 3873 <section class="add-to-cart-section js-add-to-cart-section"> 3874 @if (Dynamicweb.Rapido.Services.User.IsPricesAllowed()) 3875 { 3876 @RenderPriceInfo(false, customPrice?.PriceQuantity) 3877 } 3878 <div class="product__price-actions dw-mod" id="PriceAndActions"> 3879 @RenderBuyInfo(false, customPrice?.PriceQuantity) 3880 </div> 3881 <input type="hidden" value="@Model.VariantId" name="Variant" id="Variant_@Model.Id" /> 3882 </section> 3883 </div> 3884 3885 //Customer rating 3886 var dwPageId = Dynamicweb.Frontend.PageView.Current().Page.ID; 3887 string currentUrl = Convert.ToString(HttpContext.Current.Request.Url.PathAndQuery); 3888 var pageViewUrl = currentUrl + "#commented"; 3889 var productId = Model.Id; 3890 var langId = Model.LanguageId; 3891 var accessUserName = currentUser != null ? Dynamicweb.Frontend.PageView.Current().User.Name : ""; 3892 var accessUserEmail = currentUser != null ? Dynamicweb.Frontend.PageView.Current().User.Email : ""; 3893 var notify = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetString("ActiveNotificationEmail"); 3894 var notifySenderEmail = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetString("NotifySenderEmail"); 3895 var notifyEmail = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetString("NotifyEmail"); 3896 var notifySenderName = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetString("NotifySenderName"); 3897 3898 <input type="checkbox" id="rateProductModalTrigger" class="modal-trigger"> 3899 <div class="modal-container"> 3900 <label for="rateProductModalTrigger" id="rateProductModalOverlay" class="modal-overlay"></label> 3901 <div class="modal modal--lg modal-height--auto" id="rateProductModal"> 3902 <div class="modal__header u-no-padding-x u-no-border--bottom"> 3903 <div class="u-ta-center u-bold dw-mod">@Translate("Anmeld")<br />@Model.Name</div> 3904 </div> 3905 3906 <div class="full-stars-customer-rating u-padding-top--lg u-padding-bottom--lg"> 3907 <div class="rating-group"> 3908 <input disabled checked class="rating__input rating__input--none" name="rating3" id="rating3-none" value="0" type="radio"> 3909 <label aria-label="1 star" class="rating__label" for="rating3-1"><i class="rating__icon rating__icon--star fas fa-heart"></i></label> 3910 <input class="rating__input js-rating" name="rating3" id="rating3-1" value="1" type="radio"> 3911 <label aria-label="2 stars" class="rating__label" for="rating3-2"><i class="rating__icon rating__icon--star fas fa-heart"></i></label> 3912 <input class="rating__input js-rating" name="rating3" id="rating3-2" value="2" type="radio"> 3913 <label aria-label="3 stars" class="rating__label" for="rating3-3"><i class="rating__icon rating__icon--star fas fa-heart"></i></label> 3914 <input class="rating__input js-rating" name="rating3" id="rating3-3" value="3" type="radio"> 3915 <label aria-label="4 stars" class="rating__label" for="rating3-4"><i class="rating__icon rating__icon--star fas fa-heart"></i></label> 3916 <input class="rating__input js-rating" name="rating3" id="rating3-4" value="4" type="radio"> 3917 <label aria-label="5 stars" class="rating__label" for="rating3-5"><i class="rating__icon rating__icon--star fas fa-heart"></i></label> 3918 <input class="rating__input js-rating" name="rating3" id="rating3-5" value="5" type="radio"> 3919 </div> 3920 </div> 3921 <p class="u-ta-center u-color-danger js-rate-error u-hidden">@Translate("Vurder vinen fra 1 til 5")</p> 3922 3923 <div class="modal__body "> 3924 <form method="post" class="u-ta-center js-comment-form" id="commentform"> 3925 <input type="hidden" name="Comment.Command" id="Comment.Command" value="create" /> 3926 <!--Set active to false if you want to approve comments before publishing on the page--> 3927 <input type="hidden" name="Comment.Active" value="false" /> 3928 <!-- product catalog level comments params --> 3929 <input type="hidden" name="Comment.ItemType" value="ecomProduct" /> 3930 <input type="hidden" name="Comment.ItemID" value="@productId" /> 3931 <input type="hidden" name="Comment.LangID" value="@langId" /> 3932 <!-- end product catalog level comments params --> 3933 <input type="hidden" name="Comment.Continue" value="@pageViewUrl" /> 3934 <input type="hidden" name="Comment.ParentID" id="Comment.ParentID" value="0" /> 3935 3936 <!--Notify info--> 3937 <input type="hidden" name="Comment.Notify" value="@notify" /> 3938 <input type="hidden" name="Comment.NotifyTemplate" value="Comments/Notify.cshtml" /> 3939 <input type="hidden" name="Comment.NotifySubject" id="Comment.NotifySubject" value="@Translate("Ny anmeldelse af produkt"): @productId" /> 3940 <input type="hidden" name="Comment.NotifySenderEmail" value="@notifySenderEmail" /> 3941 <input type="hidden" name="Comment.NotifySenderName" value="@notifySenderName" /> 3942 <input type="hidden" name="Comment.NotifyEmail" value="@notifyEmail" /> 3943 3944 <!--User info--> 3945 <input type="hidden" name="Comment.Rating" id="Comment.Rating" value="0" /> 3946 <input type="hidden" name="Comment.Name" id="Comment.Name" value="@accessUserName" /> 3947 <input type="hidden" name="Comment.Email" id="Comment.Email" value="@accessUserEmail" /> 3948 <input type="hidden" name="Comment.Website" id="Comment.Website" value="" /> 3949 <textarea name="Comment.Text" id="Comment.Text" rows="20" cols="50" class="comment-custom-rating" placeholder="@Translate("Skriv din anmeldelse")"></textarea><br /> 3950 3951 <input type="submit" class="btn btn--primary dw-mod" value="@Translate("Anmeld vin")" /> 3952 </form> 3953 </div> 3954 <label class="modal__close-btn" for="rateProductModalTrigger"></label> 3955 </div> 3956 </div> 3957 3958 3959 <input type="checkbox" id="productRatedModalTrigger" class="modal-trigger"> 3960 <div class="modal-container"> 3961 <label for="productRatedModalTrigger" id="productRatedModalOverlay" class="modal-overlay"></label> 3962 <div class="modal modal--md modal-height--auto u-padding--lg" id="productRatedModal"> 3963 <div class="modal__header u-no-padding-x u-no-border--bottom u-no-padding u-padding-top"> 3964 <div class="u-ta-center u-bold dw-mod">@Translate("Tak for din anmeldelse!")</div> 3965 </div> 3966 <div class="modal__body u-no-padding u-padding-bottom u-ta-center"> 3967 <p>@Translate("Din anmeldelse vises i løbet af 24 timer")</p> 3968 <label for="productRatedModalTrigger" class="js-close-rated btn btn--primary u-no-margin u-margin-top--lg dw-mod">@Translate("Luk")</label> 3969 </div> 3970 </div> 3971 </div> 3972 } 3973 3974 @helper RenderSimpleAddToCartSection() 3975 { 3976 string defaultImage = Model.ImagePatternImages.Any(i => i.Name == "Default") ? Model.ImagePatternImages.First(i => i.Name == "Default").Value : "Files/Images/missing_image.jpg"; 3977 string imagePrefix = "/Admin/Public/GetImage.ashx?width=77&amp;height=180&amp;crop=5&FillCanvas=True&DoNotUpscale=true&amp;Compression=75&amp;image=" + defaultImage; 3978 // CDN 3979 var cdnUrl = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetString("CDNUrl"); 3980 bool cdnActivate = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetBoolean("CDNActivate"); 3981 if (!string.IsNullOrWhiteSpace(cdnUrl) && cdnActivate) 3982 { 3983 imagePrefix = cdnUrl + imagePrefix; 3984 } 3985 <div class="simple-add-to-cart-section-container add-to-cart-section-container"> 3986 <section class="add-to-cart-section js-add-to-cart-section"> 3987 3988 <div class="add-to-cart-section__image"> 3989 <img class="u-full-height u-center-middle" src="@imagePrefix" alt="@HttpUtility.HtmlAttributeEncode(Model.Name)"/> 3990 </div> 3991 3992 @if (Dynamicweb.Rapido.Services.User.IsPricesAllowed()) 3993 { 3994 @RenderPriceInfo(true) 3995 } 3996 <div class="product__price-actions dw-mod" id="PriceAndActions"> 3997 @RenderBuyInfo(true) 3998 </div> 3999 <input type="hidden" value="@Model.VariantId" name="Variant" id="Variant_@Model.Id" /> 4000 </section> 4001 </div> 4002 } 4003 4004 @helper RenderBuyInfo(bool useSimpleLayout = false, int? customPriceQuantity = null) 4005 { 4006 var user = Dynamicweb.Security.UserManagement.User.GetCurrentExtranetUser(); 4007 bool showPrice = !Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HidePrice"); 4008 bool showCartButton = !Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideAddToCartButton"); 4009 bool pointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly"); 4010 string variantId = HttpContext.Current.Request.QueryString.Get("variantId") ?? ""; 4011 string feedId = Dynamicweb.Context.Current.Request["ID"] + "&ProductID=" + Model.Id + "&VariantID=" + variantId + "&Feed=True&redirect=false"; 4012 string cartIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon") != null ? Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon").SelectedValue : "fas fa-shopping-cart"; 4013 bool showVATPrice = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("ShowBothPricesWithWithoutVAT"); 4014 bool isPricesWithVATEnabled = Converter.ToBoolean(Pageview.Area.EcomPricesWithVat); 4015 4016 var customerId = Dynamicweb.Security.UserManagement.User.GetCurrentExtranetUserId(); 4017 var shopId = Pageview.Area.EcomShopId; 4018 var orderType = Dynamicweb.Ecommerce.Orders.OrderType.Order; 4019 var cartsList = (List<Dynamicweb.Ecommerce.Orders.Order>)Dynamicweb.Ecommerce.Services.Orders.GetCustomerOrdersByType(customerId, shopId, orderType, 0, false, "", DateTime.MinValue, false, true); 4020 4021 ProductInformation productInformation = new ProductInformation(Model); 4022 string linkGroup = "Default.aspx?Id=" + GetPageIdByNavigationTag("ProductsPage") + "&GroupId=" + (Model.PrimaryOrDefaultGroup != null ? Model.PrimaryOrDefaultGroup.Id : "") + "&ProductId=" + Model.Id; 4023 string link = Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl(linkGroup); 4024 string image = System.Web.HttpContext.Current.Server.UrlEncode(Model.DefaultImage.Value); 4025 double priceDouble = Model.Price.Price != Model.PriceBeforeDiscount.Price ? Model.Price.Price : Model.PriceBeforeDiscount.Price; 4026 priceDouble = Dynamicweb.Rapido.Services.User.IsPricesAllowed() ? priceDouble : 0; 4027 4028 bool isActive = !productInformation.Blocked && (productInformation.SpProductActive || (user != null && user.CurrentSecondaryUser != null)); 4029 bool availableForPurchase = ProductInformation.OnCustomerStock(Model.Id) && productInformation.SpProductActive ? true : isActive; 4030 string encodedProductName = HttpUtility.JavaScriptStringEncode(Model.Name); 4031 4032 var googleImpression = new GoogleImpression(); 4033 if (addToCartUseGoogleTagManager) 4034 { 4035 googleImpression.name = encodedProductName; 4036 googleImpression.brand = !string.IsNullOrWhiteSpace(productInformation.Brand) ? productInformation.Brand : ""; 4037 googleImpression.category = Model.PrimaryOrDefaultGroup.Name; 4038 googleImpression.id = Model.Id; 4039 googleImpression.position = 1; 4040 googleImpression.price = Converter.ToString((Model.Price.Price != Model.PriceBeforeDiscount.Price ? Model.Price.Price : Model.PriceBeforeDiscount.Price)); 4041 googleImpression.variant = Model.VariantId; 4042 googleImpression.list = "Product catalogue"; 4043 googleImpression.currency = Model.Price.CurrencyCode; 4044 } 4045 4046 string productInfo = HttpUtility.HtmlEncode(Newtonsoft.Json.JsonConvert.SerializeObject(new 4047 { 4048 link = link, 4049 image = image, 4050 name = encodedProductName, 4051 variantName = Dynamicweb.Ecommerce.Services.Variants.GetVariantName(Model.VariantId), 4052 unitName = "", 4053 googleImpression = Newtonsoft.Json.JsonConvert.SerializeObject(googleImpression) 4054 })); 4055 4056 var facebookPixelAction = new FacebookAction(); 4057 if (addToCartUseFacebookPixel) 4058 { 4059 facebookPixelAction.content_name = encodedProductName; 4060 facebookPixelAction.content_ids = new List<string>(new string[] { Model.Number }); 4061 facebookPixelAction.content_type = "product"; 4062 facebookPixelAction.value = priceDouble; 4063 facebookPixelAction.currency = Model.Price.CurrencyCode; 4064 } 4065 4066 int quantity = !String.IsNullOrEmpty(HttpContext.Current.Request.QueryString.Get("quantity")) ? Converter.ToInt32(HttpContext.Current.Request.QueryString.Get("quantity")) : 1; 4067 double points = Converter.ToDouble(Model.PointPrice) * quantity; 4068 bool havePointPrice = points != 0; 4069 bool canBePurchasedWithPoints = false; 4070 string onSale = Model.Discount.PriceFormatted == Model.Price.PriceFormatted ? "u-hidden" : ""; 4071 4072 if (user != null) 4073 { 4074 var availablePoints = user.PointBalance; 4075 var cart = Dynamicweb.Ecommerce.Common.Context.Cart; 4076 var pointsUsedInCart = cart != null ? cart.TotalPoints : 0; 4077 canBePurchasedWithPoints = points > 0 && availablePoints - pointsUsedInCart >= points; 4078 } 4079 string disabledBuyButton = (pointShopOnly && !canBePurchasedWithPoints) ? "disabled" : ""; 4080 4081 if (showCartButton && Dynamicweb.Rapido.Services.User.IsBuyingAllowed() && availableForPurchase) 4082 { 4083 var addToCartBtn = new AddToCart 4084 { 4085 WrapperCssClass = "product__price-actions-flex-wrap buttons-collection--right dw-mod", 4086 AddButton = new AddToCartButton 4087 { 4088 ProductId = Model.Id, 4089 VariantId = Model.VariantId, 4090 UnitId = "", 4091 ProductInfo = productInfo, 4092 BuyForPoints = pointShopOnly, 4093 ExtraAttributes = new Dictionary<string, string> 4094 { 4095 { disabledBuyButton, "" } 4096 }, 4097 CssClass = "product__price-buy-button" 4098 } 4099 }; 4100 4101 if (!pointShopOnly) 4102 { 4103 addToCartBtn.QuantitySelector = new QuantitySelector 4104 { 4105 Id = "Quantity_" + Model.Id 4106 }; 4107 } 4108 4109 int kolli = productInformation.MaxPriceBasedOn > 0 ? productInformation.MaxPriceBasedOn : 1; 4110 4111 if (customPriceQuantity != null && customPriceQuantity > 0) 4112 { 4113 kolli = Converter.ToInt32(customPriceQuantity); 4114 } 4115 4116 var priceObject = new Smartpage.PhilipsonWine.Ecommerce.Prices.PriceObject(Model.Id, kolli, Model.Discount.Price, productInformation.OnSale); 4117 4118 // In case of 1 stk. price is as good as volume price 4119 if (priceObject.DiscountPrice == priceObject.NormalPrice) 4120 { 4121 kolli = 1; 4122 } 4123 4124 <div class="product__price-actions-wrap dw-mod u-margin-top-big u-margin-bottom-big"> 4125 <div class="buttons-collection"> 4126 @if (Model.StockLevel > 0) 4127 { 4128 <input id="Quantity_@Model.Id" name="Quantity_@Model.Id" min="1" max="@Model.StockLevel" value="@kolli" type="number" class="quantity dw-mod js-stockcheck js-change-quantity"> 4129 } 4130 @{ 4131 4132 if (Model.StockLevel > 0) 4133 { 4134 <button class="btn btn--add-to-cart" title="@Translate("Smartpage:ProductDetail.Buy", "Køb")" onclick='Cart.AddToCart(event, { "id": "@Model.Id", "unitId": "@Model.DefaultUnitId", "productInfo": @productInfo, "quantity": parseInt(document.getElementById("Quantity_@Model.Id").value), "SpPrimeur": "@Converter.ToString(productInformation.Primeur)" });' type="button" data-product-id="@Model.Id" data-one-unit-price="@priceObject.NormalPrice" data-volume-unit-price="@priceObject.DiscountPrice" data-volume-unit-threshold="@kolli" data-currency-code="@Model.Price.CurrencyCode"><span><i class="fas fa-shopping-cart shopping-cart u-w20px"></i>@Translate("Smartpage:ProductDetail.Buy", "Køb")</span></button> 4135 } 4136 else 4137 { 4138 <button disabled class="btn btn--add-to-cart" title="@Translate("Smartpage:Product.Buy.OutOfStock", "Udsolgt")" onclick='Cart.AddToCart(event, { "id": "@Model.Id", "unitId": "@Model.DefaultUnitId", "productInfo": @productInfo, "quantity": parseInt(document.getElementById("Quantity_@Model.Id").value), "SpPrimeur": "@Converter.ToString(productInformation.Primeur)"});' type="button"><span><i class="fas fa-shopping-cart shopping-cart u-w20px"></i>@Translate("Smartpage:Product.Buy.OutOfStock", "Udsolgt")</span></button> 4139 } 4140 } 4141 </div> 4142 </div> 4143 } 4144 else 4145 { 4146 <button type="button" id="CartButton_@Model.Id" class="u-hidden"></button> 4147 } 4148 4149 if (!useSimpleLayout) 4150 { 4151 @RenderStockAndShipping() 4152 4153 if (user != null && !eventProduct) 4154 { 4155 @RenderAddToFavoriteList() 4156 } 4157 4158 if (!eventProduct) 4159 { 4160 @RenderCustomerRatingLink() 4161 } 4162 4163 4164 @RenderUSPList(productInformation) 4165 } 4166 4167 4168 @*<script id="UnitOption" type="text/x-template"> 4169 <div class="dropdown__item dw-mod" onclick="HandlebarsBolt.UpdateContent('PriceAndActions', '{{link}}&feed=true&UnitID={{value}}')">{{name}}</div> 4170 </script>*@ 4171 4172 <script> 4173 document.addEventListener("DOMContentLoaded", function () { 4174 if (document.getElementById("PriceAndActions")) { 4175 document.getElementById("PriceAndActions").addEventListener("contentLoaded", function (event) { 4176 if (document.querySelector(".js-variants") != null) { 4177 MatchVariants.Update(document.querySelector(".js-variants"), "DoNothing"); 4178 } 4179 }); 4180 } 4181 }); 4182 </script> 4183 } 4184 4185 @helper RenderPriceInfo(bool useSimpleLayout = false, int? customPriceQuantity = null) 4186 { 4187 ProductInformation productInformation = new ProductInformation(Model); 4188 int priceQuantity = customPriceQuantity != null && customPriceQuantity > 0 ? Converter.ToInt32(customPriceQuantity) : productInformation.MaxPriceBasedOn; 4189 bool pointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly"); 4190 bool showPrice = !Pageview.AreaSettings.GetItem("ProductList").GetBoolean("HidePrice"); 4191 bool showCartButton = !Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideAddToCartButton"); 4192 bool showVATPrice = Pageview.AreaSettings.GetItem("ProductList").GetBoolean("ShowBothPricesWithWithoutVAT"); 4193 bool isPricesWithVATEnabled = Converter.ToBoolean(Pageview.Area.EcomPricesWithVat); 4194 var priceObject = new Smartpage.PhilipsonWine.Ecommerce.Prices.PriceObject(Model.Id, priceQuantity, Model.Discount.Price, productInformation.OnSale); 4195 double savings = priceObject.AmountSaved; 4196 double price = Dynamicweb.Rapido.Services.User.IsPricesAllowed() ? priceObject.DiscountPrice : 0; 4197 string priceWithoutVAT = Converter.ToString(Model.Price.PriceWithoutVat); 4198 priceWithoutVAT = Dynamicweb.Rapido.Services.User.IsPricesAllowed() ? priceWithoutVAT : "0"; 4199 string priceWithVAT = Converter.ToString(Model.Price.PriceWithVat); 4200 priceWithVAT = Dynamicweb.Rapido.Services.User.IsPricesAllowed() ? priceWithVAT : "0"; 4201 string priceRRP = Model.PriceInformative != null && !string.IsNullOrEmpty(Model.PriceInformative.PriceFormatted) ? Model.PriceInformative.PriceFormatted : ""; 4202 priceRRP = Dynamicweb.Rapido.Services.User.IsPricesAllowed() ? priceRRP : "0"; 4203 int quantity = !String.IsNullOrEmpty(HttpContext.Current.Request.QueryString.Get("quantity")) ? Converter.ToInt32(HttpContext.Current.Request.QueryString.Get("quantity")) : 1; 4204 double points = Converter.ToDouble(Model.PointPrice) * quantity; 4205 bool havePointPrice = points != 0; 4206 bool canBePurchasedWithPoints = false; 4207 string onSale = Model.Discount.PriceFormatted == Model.Price.PriceFormatted ? "u-hidden" : ""; 4208 string currencySymbol = Dynamicweb.Ecommerce.Common.Context.Currency.Symbol; 4209 4210 // In case of 1 stk. price is as good as volume price 4211 if (priceObject.DiscountPrice == priceObject.NormalPrice) 4212 { 4213 priceQuantity = 1; 4214 } 4215 4216 var user = Dynamicweb.Security.UserManagement.User.GetCurrentExtranetUser(); 4217 if (user != null) 4218 { 4219 var availablePoints = user.PointBalance; 4220 var cart = Dynamicweb.Ecommerce.Common.Context.Cart; 4221 var pointsUsedInCart = cart != null ? cart.TotalPoints : 0; 4222 canBePurchasedWithPoints = points > 0 && availablePoints - pointsUsedInCart >= points; 4223 } 4224 4225 string simpleLayoutClass = useSimpleLayout ? "simple-layout" : ""; 4226 4227 4228 if (showPrice && Dynamicweb.Rapido.Services.User.IsPricesAllowed()) 4229 { 4230 <div class="prices @simpleLayoutClass"> 4231 4232 @if (savings > 0) 4233 { 4234 <span class="savings">@Translate("Smartpage:ProductDetail.Save", "Spar") @FormatPrice(savings) @currencySymbol @Translate("Smartpage:ProductDetail.pr.", "pr.") @productInformation.Unit.ShortDescription</span> 4235 } 4236 4237 <div class="price price--product-page"> 4238 @priceObject.DiscountPriceFormattedWithoutSymbol 4239 <span class="currency-symbol">@currencySymbol</span> 4240 <span class="quantity-price__amount--mobile"><strong>@Translate("Smartpage:ProductDetail.pr.", "pr.") @productInformation.Unit.ShortDescription v/@priceQuantity</strong></span> 4241 </div> 4242 4243 @if (eventProduct) 4244 { 4245 <div class="quantity-price"> 4246 <span class="u-block u-color-font-black quantity-price__amount"><strong>@Translate("Pr. billet")</strong></span> 4247 </div> 4248 } 4249 else 4250 { 4251 <div class="quantity-price"> 4252 <span class="u-block u-color-font-black quantity-price__amount"><strong>@Translate("Smartpage:ProductDetail.Pr.", "Pr.") @productInformation.Unit.ShortDescription v/@priceQuantity @Translate("Smartpage:ProductDetail.Unit.Stk", "stk.")</strong></span> 4253 @priceObject.NormalPriceFormatted @Translate("Smartpage:ProductDetail.pr.", "pr.") @productInformation.Unit.LongDescription 4254 </div> 4255 } 4256 4257 </div> 4258 } 4259 } 4260 4261 @helper RenderStockAndShipping() 4262 { 4263 4264 bool hideStockState = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideStockState"); 4265 bool hideDelivery = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideShipping"); 4266 4267 var apiProduct = Dynamicweb.Ecommerce.Services.Products.GetProductById(Model.Id, Model.VariantId, true); 4268 var stockStatus = Dynamicweb.Ecommerce.Services.Products.GetStockStatus(apiProduct, apiProduct.LanguageId); 4269 string stockText = stockStatus != null ? stockStatus.Text : ""; 4270 string stockState = Model.StockLevel > 0 ? "stock-icon--in" : "stock-icon--not"; 4271 string deliveryText = stockStatus != null && !string.IsNullOrEmpty(stockStatus.ExpectedDeliveryText) ? stockStatus.ExpectedDeliveryText : ""; 4272 ProductInformation productinfo = new ProductInformation(Model); 4273 bool isPrimeur = productinfo.Primeur; 4274 string primeruDeliveryDate = productinfo.PrimeurIncomingDate != DateTime.MinValue ? productinfo.PrimeurIncomingDate.ToString("dd/MM/yyyy") : Translate("Smartpage:ProductDetail.PrimeurDateNotKnown", "Ukendt"); 4275 4276 if (User.IsStockInfoAllowed()) 4277 { 4278 if (!string.IsNullOrWhiteSpace(stockText)) 4279 { 4280 <div class="product__stock-delivery dw-mod"> 4281 @if (!hideStockState) 4282 { 4283 if (!isPrimeur) 4284 { 4285 <span class="stock-icon @stockState u-no-margin dw-mod" title="@stockText"></span> 4286 <span> 4287 @stockText 4288 @if (!hideDelivery && !string.IsNullOrWhiteSpace(deliveryText)) 4289 { 4290 <text>: @deliveryText</text> 4291 } 4292 </span> 4293 } 4294 else 4295 { 4296 <span class="stock-icon stock-icon--comming u-no-margin dw-mod" title="stock-icon--not"></span> 4297 <span> 4298 @Translate("Smarptage:ProductDetail.PrimeurStockState", "Leveringsdato") 4299 @if (!hideDelivery && !string.IsNullOrWhiteSpace(primeruDeliveryDate)) 4300 { 4301 <text>: @primeruDeliveryDate</text> 4302 } 4303 </span> 4304 } 4305 4306 4307 } 4308 </div> 4309 } 4310 } 4311 } 4312 4313 @helper RenderCustomerRatingLink() 4314 { 4315 4316 var modalTrigger = ""; 4317 4318 if (Dynamicweb.Security.UserManagement.User.GetCurrentExtranetUser() != null) 4319 { 4320 modalTrigger = "rateProductModalTrigger"; 4321 } 4322 else 4323 { 4324 modalTrigger = "SignInModalTrigger"; 4325 } 4326 4327 <div class="product__customer-rating-link"> 4328 <img src="/Files/Templates/Designs/Rapido/Images/VectorItemTypes/rating-full-red-heart.svg" class="full-heart" /> 4329 <strong><label for="@modalTrigger" class="medium-link">@Translate("Smartpage:ProductDetail.ReviewThisWine", "Anmeld denne vin")</label></strong> 4330 </div> 4331 } 4332 4333 @helper RenderUSPList(ProductInformation productInfo) 4334 { 4335 4336 string eventUSP = productInfo.EventUSP; 4337 string[] eventUSPs = eventUSP.Split('#'); 4338 4339 <div class="product__usp-list"> 4340 @if (eventProduct) 4341 { 4342 if (eventUSPs != null && eventUSPs.Length > 0) 4343 { 4344 foreach (var usp in eventUSPs) 4345 { 4346 if (!string.IsNullOrEmpty(usp)) 4347 { 4348 <div class="usp"> 4349 <i class="fas fa-check usp-icon"></i> 4350 <span>@usp</span> 4351 </div> 4352 } 4353 } 4354 } 4355 } 4356 else 4357 { 4358 <div class="usp"> 4359 <i class="fas fa-truck usp-icon"></i> 4360 <span>@Translate("Smartpage:ProductDetail.FreeShipping", "FRI FRAGT!")</span> 4361 </div> 4362 <div class="usp"> 4363 <i class="fas fa-lock usp-icon"></i> 4364 <span>@Translate("Smartpage:ProductDetail.SecurePayment", "Sikker betaling")</span> 4365 </div> 4366 } 4367 </div> 4368 } 4369 4370 @helper RenderAddToFavoriteList() 4371 { 4372 var user = Dynamicweb.Security.UserManagement.User.get_Current(Dynamicweb.Security.UserManagement.PagePermissionLevels.Frontend); 4373 string pageId = Dynamicweb.Context.Current.Request["ID"]; 4374 string currentPrice = Model.Price.PriceFormatted != Model.PriceBeforeDiscount.PriceFormatted ? Model.Price.PriceFormatted : Model.PriceBeforeDiscount.PriceFormatted; 4375 bool hideFavorites = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideFavoriteButton"); 4376 bool hideProductNumber = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideProductNumber"); 4377 4378 bool useFontAwesomePro = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetBoolean("UseFontAwesomePro"); 4379 var selectedFavoriteIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("FavoriteIcon") != null ? Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("FavoriteIcon").SelectedValue : "star"; 4380 string favoriteIcon = "fas fa-" + selectedFavoriteIcon; 4381 string favoriteOutlineIcon = "fal fa-" + selectedFavoriteIcon; 4382 4383 if (!hideFavorites && user != null) 4384 { 4385 string favoriteId = "Favorite" + Model.Id; 4386 var customerCenterLists = Dynamicweb.Ecommerce.CustomerCenter.CustomerProductList.GetListByCustomerId(user.ID); 4387 4388 // This page needs to be used since View Model catalogue can't handle adding to favorites 4389 // Use standard product catalogue instead 4390 string modifyFavoriteListPage = Converter.ToString(GetPageIdByNavigationTag("ModifyFavoriteListPage")); 4391 4392 <div id="@favoriteId" class="favorites js-favorite-btn product__add-to-favorites-link"> 4393 <div> 4394 @{ 4395 string favorite = customerCenterLists.Any(l => l.Products.Any(p => p.ProductId == Model.Id)) ? favoriteIcon : favoriteOutlineIcon; 4396 string AddToWishlist = "fbq('track', 'AddToWishlist', {" + 4397 "content_name: '" + Model.Name + "'," + 4398 "content_ids: ['" + Model.Number + "']," + 4399 "value: " + Model.Price.Price + "," + 4400 "currency: '" + Model.Price.CurrencyCode + "'" + 4401 "});"; 4402 } 4403 <strong><label for="FavoriteTrigger" class="medium-link"><i class="@favorite favorite-icon"></i>@Translate("Smartpage:ProductDetail.AddToFavorites", "Føj til favoritter")</label></strong> 4404 </div> 4405 <input type="checkbox" id="FavoriteTrigger" class="dropdown-trigger" /> 4406 4407 <div class="dropdown"> 4408 <div class="dropdown__content dropdown__content--show-left dropdown__content--padding u-w220px dw-mod"> 4409 <ul class="list list--clean dw-mod"> 4410 @if (customerCenterLists.Count() > 0) 4411 { 4412 4413 4414 //Custom 4415 FavoriteLists favoriteLists = new FavoriteLists(); 4416 4417 foreach (var list in customerCenterLists) 4418 { 4419 bool isInFavoriteList = list.Products.Any(p => p.ProductId == Model.Id); 4420 string addLink = "/Default.aspx?ID=" + modifyFavoriteListPage + "&feed=true&CCAddToMyLists=" + Model.Id + "&CCAddToListVariantID=" + Model.VariantId + "&CCAddToListLanguageID=" + Model.LanguageId + "&CCAddToListID=" + list.ListId + "&CCListType=" + list.Type; 4421 string removeLink = "/Default.aspx?ID=" + modifyFavoriteListPage + "&feed=true&CCRemoveFromMyLists=" + Model.Id + "&CCRemoveFromListVariantID=" + Model.VariantId + "&CCRemoveFromListLanguageID=" + Model.LanguageId + "&ListID=" + list.ListId + "&CCListType=" + list.Type; 4422 string favLinkType = isInFavoriteList ? removeLink : addLink; 4423 string isInListIcon = isInFavoriteList ? favoriteIcon : favoriteOutlineIcon; 4424 bool fromImport = false; 4425 4426 //Custom 4427 if (list.Type == "Favorites") 4428 { 4429 fromImport = favoriteLists.IsProductFromImport(Converter.ToString(Model.Id), Converter.ToString(list.ListId)); 4430 } 4431 4432 if (fromImport == false) 4433 { 4434 <li> 4435 <a href="@favLinkType" class="list__link u-no-underline dw-mod" onclick="@(isInFavoriteList && useFacebookPixel ? AddToWishlist : "")"><i class="@isInListIcon u-margin-right--lg"></i> @list.Name</a> 4436 </li> 4437 } 4438 } 4439 } 4440 else 4441 { 4442 string favLinkType = "/Default.aspx?ID=" + modifyFavoriteListPage + "&feed=true&DoNotShowVariantsAsSingleProducts=True&CCAddToMyLists=" + Model.Id + "&CCAddToListVariantID=" + Model.VariantId + "&CCAddToListLanguageID=" + Model.LanguageId + "&CCListType=0&CCCreateNewList=My favorites"; 4443 string isInListIcon = favoriteOutlineIcon; 4444 <li> 4445 <a href="@favLinkType" class="list__link u-no-underline dw-mod" onclick="@(useFacebookPixel ? AddToWishlist : "")"><i class="@isInListIcon u-margin-right--lg"></i> @Translate("My favorites")</a> 4446 </li> 4447 } 4448 </ul> 4449 </div> 4450 <label class="dropdown-trigger-off" for="FavoriteTrigger"></label> 4451 </div> 4452 </div> 4453 } 4454 } 4455 @inherits ViewModelTemplate<ProductViewModel> 4456 @using Dynamicweb.Ecommerce.ProductCatalog 4457 @using Dynamicweb.Rendering 4458 @using Dynamicweb.Core 4459 @using System 4460 @using System.Web 4461 @using System.Collections.Generic 4462 @using Dynamicweb.Rapido.Blocks 4463 @using Dynamicweb.Rapido.Blocks.Components.General 4464 4465 @functions { 4466 BlocksPage productAssetsPage = BlocksPage.GetBlockPage("Product"); 4467 } 4468 4469 @{ 4470 string productAssetsLayout = !String.IsNullOrEmpty(Pageview.AreaSettings.GetItem("ProductPage").GetString("ProductAssetsLayout")) ? Pageview.AreaSettings.GetItem("ProductPage").GetList("ProductAssetsLayout").SelectedValue : "Section"; 4471 productAssetsLayout = productAssetsLayout == "Ribbon" ? "Section" : productAssetsLayout; 4472 4473 if (productAssetsLayout != "hide") 4474 { 4475 @*TODO: Determine if this should be used*@ 4476 //Block productAssetsBlock = new Block() 4477 //{ 4478 // Name = productAssetsLayout != "MainInformation" ? Translate("Product assets") : "", 4479 // Id = "ProductAssets", 4480 // SortId = 10, 4481 // Template = RenderProductAssets(productAssetsLayout, downloadDocuments), 4482 // Design = new Design 4483 // { 4484 // Size = "12", 4485 // RenderType = RenderType.Column, 4486 // HidePadding = true 4487 // } 4488 //}; 4489 //productAssetsPage.Add(productAssetsLayout, productAssetsBlock); 4490 } 4491 } 4492 4493 @*TODO: Determine if this should be used*@ 4494 @*@helper RenderProductAssets(string layout, List<LoopItem> documents) 4495 { 4496 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("ProductAssetsLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 4497 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("ProductAssetsLayout").SelectedValue == "Ribbon" ? "u-padding--lg" : ""; 4498 string exportPageId = GetPageIdByNavigationTag("ProductExportFeed").ToString(); 4499 4500 //images 4501 4502 HashSet<string> images = new HashSet<string>(); 4503 4504 images.Add(GetProductImage()); 4505 4506 foreach (LoopItem alternativeImage in GetLoop("Ecom:Product.AlternativeImages")) 4507 { 4508 string alt_image = alternativeImage.GetString("Ecom:Product.AlternativeImages.Image"); 4509 4510 if (!string.IsNullOrEmpty(alt_image)) 4511 { 4512 images.Add(alt_image); 4513 } 4514 } 4515 4516 foreach (LoopItem detail in GetLoop("Details")) 4517 { 4518 string detail_image = detail.GetString("Ecom:Product:Detail.Image.Clean"); 4519 4520 if (!string.IsNullOrEmpty(detail_image)) 4521 { 4522 images.Add(detail_image); 4523 } 4524 } 4525 4526 <div class="product__section @ribbonClasses dw-mod"> 4527 <div class="product__description center-container @ribbonSubClasses dw-mod"> 4528 @if (layout == "Section") 4529 { 4530 @Render(new Heading { Title = Translate("Product assets"), Level = 2 }) 4531 } 4532 4533 <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"> 4534 <div class="grid"> 4535 @if (images.Count > 0) 4536 { 4537 <div class="grid__col-md-4 js-checkboxes-list"> 4538 @Render(new CheckboxField { Id = "allImages", OnChange = "selectAll(this)", Label = Translate("Images") + "(" + images.Count + ")" }) 4539 4540 <ul class="panel-list"> 4541 @foreach (string image in images) 4542 { 4543 @RenderProductPanelListItem(image) 4544 } 4545 </ul> 4546 </div> 4547 } 4548 4549 @if (documents.Count > 0) 4550 { 4551 <div class="grid__col-md-4 js-checkboxes-list"> 4552 @Render(new CheckboxField { Id = "allDocuments", OnChange = "selectAll(this)", Label = Translate("Documents") + "(" + documents.Count + ")" }) 4553 4554 <ul class="panel-list"> 4555 @foreach (LoopItem document in documents) 4556 { 4557 string fieldValue; 4558 if (!string.IsNullOrEmpty(document.GetString("Document.FullPath"))) 4559 { 4560 fieldValue = document.GetString("Product.CustomField.Value.Clean"); 4561 @RenderDocument(fieldValue) 4562 } 4563 if (document.GetString("Ecom:Product.CategoryField.TypeID") == "9") 4564 { 4565 fieldValue = document.GetString("Ecom:Product.CategoryField.Value"); 4566 @RenderDocument(fieldValue) 4567 } 4568 } 4569 </ul> 4570 </div> 4571 } 4572 <div class="grid__col-md-4"> 4573 @Render(new HiddenField { Id = "ID", Name = "ID", Value = "532" }) 4574 @Render(new HiddenField { Id = "download", Name = "download", Value = "true" }) 4575 @Render(new HiddenField { Id = "siteUrl", Name = "siteUrl", Value = string.Format("{0}://{1}", GetGlobalValue("Global:Request.Scheme"), GetGlobalValue("Global:Request.Host")) }) 4576 4577 <div class="u-bold u-margin-bottom">@Translate("Export")</div> 4578 4579 @{ 4580 SelectField languageSelect = new SelectField 4581 { 4582 Id = "exportLanguage", 4583 Label = Translate("Language"), 4584 Name = "RequestLanguageId", 4585 CssClass = "u-full-width" 4586 }; 4587 foreach (var lang in Services.Languages.GetLanguages().OrderBy(l => l.Name)) 4588 { 4589 var selected = lang.IsDefault ? true : false; 4590 languageSelect.Options.Add(new SelectFieldOption { Label = lang.Name, Value = lang.LanguageId, Checked = selected }); 4591 } 4592 @Render(languageSelect) 4593 4594 SelectField purposeSelect = new SelectField 4595 { 4596 Id = "purpose", 4597 Label = Translate("Image purpose"), 4598 Name = "purpose", 4599 CssClass = "u-full-width" 4600 }; 4601 purposeSelect.Options.Add(new SelectFieldOption { Label = Translate("Office"), Value = "Office" }); 4602 purposeSelect.Options.Add(new SelectFieldOption { Label = Translate("Original"), Value = "Original" }); 4603 purposeSelect.Options.Add(new SelectFieldOption { Label = Translate("Print"), Value = "Print" }); 4604 purposeSelect.Options.Add(new SelectFieldOption { Label = Translate("Web"), Value = "Web" }); 4605 @Render(purposeSelect) 4606 4607 SelectField formatSelect = new SelectField 4608 { 4609 Id = "exportFormat", 4610 Label = Translate("Export format"), 4611 Name = "format", 4612 CssClass = "u-full-width" 4613 }; 4614 formatSelect.Options.Add(new SelectFieldOption { Label = Translate("Csv"), Value = "csv" }); 4615 formatSelect.Options.Add(new SelectFieldOption { Label = Translate("Json"), Value = "json" }); 4616 formatSelect.Options.Add(new SelectFieldOption { Label = Translate("Xml"), Value = "xml" }); 4617 @Render(formatSelect) 4618 } 4619 4620 @Render(new Button { ButtonType = ButtonType.Submit, ButtonLayout = ButtonLayout.Primary, CssClass = "btn--full u-no-margin", Title = Translate("Download") }) 4621 </div> 4622 </div> 4623 </form> 4624 </div> 4625 </div> 4626 <script> 4627 function selectAll(checkbox) { 4628 checkbox.closest(".js-checkboxes-list").querySelectorAll(".js-checkbox").forEach(function (input) { 4629 input.checked = checkbox.checked; 4630 }); 4631 } 4632 </script> 4633 }*@ 4634 4635 @helper RenderProductPanelListItem(string imageName) 4636 { 4637 <li class="panel-list__item"> 4638 <div class="panel-list__item-check"> 4639 <input id="Image_@imageName" name="Image_@imageName" type="checkbox" class="form__control u-no-margin dw-mod js-checkbox" /> 4640 <label for="Image_@imageName"></label> 4641 </div> 4642 <div class="panel-list__item-image"> 4643 <label for="Image_@imageName" class="u-no-margin"> 4644 @Render(new Image { Path = imageName, Title = Path.GetFileName(imageName), ImageDefault = new ImageSettings { Width = 55, Height = 55, Crop = 5, FillCanvas = true } }) 4645 </label> 4646 </div> 4647 <div class="panel-list__item-name"> 4648 <label for="Image_@imageName" class="u-truncate-text u-w170px" title="@Path.GetFileName(imageName)"> 4649 @Path.GetFileName(imageName) 4650 </label> 4651 </div> 4652 </li> 4653 } 4654 4655 @helper RenderDocument(string fieldValue) 4656 { 4657 <li class="panel-list__item"> 4658 <div class="panel-list__item-check"> 4659 <input id="Document_@fieldValue" name="Document_@fieldValue" type="checkbox" class="form__control u-no-margin js-checkbox dw-mod"> 4660 <label for="Document_@fieldValue"></label> 4661 </div> 4662 <div class="panel-list__item-name"> 4663 <label for="Document_@fieldValue" class="u-truncate-text u-no-margin u-max-w220px" title="@Path.GetFileName(fieldValue)"> 4664 @Path.GetFileName(fieldValue) 4665 </label> 4666 </div> 4667 </li> 4668 } 4669 @inherits ViewModelTemplate<ProductViewModel> 4670 @using Dynamicweb.Ecommerce.ProductCatalog 4671 @using Dynamicweb.Rendering 4672 @using Dynamicweb.Core 4673 @using System 4674 @using System.Web 4675 @using System.Collections.Generic 4676 @using Dynamicweb.Rapido.Blocks 4677 @using Dynamicweb.Rapido.Blocks.Components.General 4678 4679 @functions { 4680 BlocksPage productGeneratePDFPage = BlocksPage.GetBlockPage("Product"); 4681 } 4682 4683 @{ 4684 string generatePDFLayout = !String.IsNullOrEmpty(Pageview.AreaSettings.GetItem("ProductPage").GetString("GeneratePDFLayout")) ? Pageview.AreaSettings.GetItem("ProductPage").GetList("GeneratePDFLayout").SelectedValue : "Section"; 4685 generatePDFLayout = generatePDFLayout == "Ribbon" ? "Section" : generatePDFLayout; 4686 4687 if (GetPageIdByNavigationTag("ProductPagePDFTemplates") > 0 && generatePDFLayout != "hide") 4688 { 4689 Block generatePDFBlock = new Block() 4690 { 4691 Name = generatePDFLayout != "MainInformation" ? Translate("Generate PDF") : "", 4692 Id = "GeneratePDF", 4693 SortId = 10, 4694 Template = RenderGeneratePDF(generatePDFLayout), 4695 Design = new Design 4696 { 4697 Size = "12", 4698 RenderType = RenderType.Column, 4699 HidePadding = true 4700 } 4701 }; 4702 4703 productGeneratePDFPage.Add(generatePDFLayout, generatePDFBlock); 4704 } 4705 } 4706 4707 @helper RenderGeneratePDF(string layout) 4708 { 4709 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("GeneratePDFLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 4710 ribbonClasses = layout == "Tabs" ? "u-no-padding" : ribbonClasses; 4711 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("GeneratePDFLayout").SelectedValue == "Ribbon" ? "center-container--ribbon" : ""; 4712 string exportPageId = GetPageIdByNavigationTag("ProductExportFeed").ToString(); 4713 int pdfFolderId = GetPageIdByNavigationTag("ProductPagePDFTemplates"); 4714 4715 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" }; 4716 form.Add(new HiddenField { Name = "siteUrl", Value = string.Format("{0}://{1}", Dynamicweb.Context.Current.Request.Url.Scheme, Dynamicweb.Context.Current.Request.Url.Host) }); 4717 4718 //Select languages 4719 SelectField languagesList = new SelectField 4720 { 4721 Id = "RequestLanguageID", 4722 Name = "RequestLanguageID", 4723 Label = Translate("Language"), 4724 CssClass = "u-full-width" 4725 }; 4726 4727 foreach (var lang in Dynamicweb.Ecommerce.Services.Languages.GetLanguages().OrderBy(l => l.Name)) 4728 { 4729 languagesList.Options.Add(new SelectFieldOption 4730 { 4731 Label = lang.Name, 4732 Value = lang.LanguageId, 4733 Checked = lang.IsDefault ? true : false 4734 }); 4735 } 4736 form.Add(languagesList); 4737 4738 //Select pages 4739 SelectField pagesList = new SelectField 4740 { 4741 Id = "PDFTemplate", 4742 Name = "ID", 4743 Label = Translate("Generate PDF"), 4744 CssClass = "u-full-width" 4745 }; 4746 4747 foreach (Dynamicweb.Content.Page page in ServiceLocator.Current.GetPageService().GetPagesByParentID(pdfFolderId)) 4748 { 4749 pagesList.Options.Add(new SelectFieldOption 4750 { 4751 Label = page.MenuText, 4752 Value = Converter.ToString(page.ID) 4753 }); 4754 } 4755 form.Add(pagesList); 4756 4757 form.Add(new Button { ButtonType = ButtonType.Submit, Title = Translate("Generate PDF"), CssClass = "btn--full u-no-margin" }); 4758 4759 <div class="product__section @ribbonClasses grid dw-mod"> 4760 <div class="dw-mod grid__col-md-4 @ribbonSubClasses"> 4761 @if (layout == "Section") 4762 { 4763 @Render(new Heading { Title = Translate("Generate PDF"), Level = 2 }) 4764 } 4765 @Render(form) 4766 </div> 4767 </div> 4768 } 4769 4770 @inherits ViewModelTemplate<ProductViewModel> 4771 @using Dynamicweb.Ecommerce.ProductCatalog 4772 @using Dynamicweb.Rendering 4773 @using System.Text.RegularExpressions; 4774 @using Smartpage.PhilipsonWine.Ecommerce.ProductInformation 4775 4776 @helper RenderDescription(string id) 4777 { 4778 ProductInformation productInformation = new ProductInformation(Model); 4779 int maxLength = 400; 4780 string maxLengthPaddingClass = Model.LongDescription.Length > maxLength ? "u-padding-bottom-30" : ""; 4781 4782 <div id="@id" class="paragraph-container paragraph-container--full-width long-description js-long-description @maxLengthPaddingClass"> 4783 <div class="grid grid--justify-center"> 4784 <div class="grid__col-md-6 grid__col-lg-6 grid__col-xlg-5 grid__col-xxlg-4"> 4785 <h2 class="long-description__header">@productInformation.LongDescriptionHeading</h2> 4786 @*Regex used to determine to amount of HTML elements to decide whether or not to show Read more text*@ 4787 @{ 4788 string pattern = "<.*?>(.*?)<\\/.*?>"; 4789 MatchCollection matches = Regex.Matches(Model.LongDescription, pattern); 4790 4791 bool hasHtmlMarkup = matches.Count > 0; 4792 4793 <div class="long-description__content js-long-description__content @(Model.LongDescription.Length > maxLength ? "fade-end" : "")"> 4794 @Model.LongDescription 4795 </div> 4796 4797 if (Model.LongDescription.Length > maxLength) 4798 { 4799 <span class="link-small js-show-description alternative-link-small" data-open="true" data-show-description="@Translate("Smartpage:ProductDetail.Description.ReadMore", "+ læs mere")" data-hide-description="@Translate("Smartpage:ProductDetail.Description.ReadLess", "- læs mindre")">@Translate("Smartpage:ProductDetail.Description.ReadMore", "+ læs mere")</span> 4800 } 4801 4802 } 4803 </div> 4804 </div> 4805 </div> 4806 } 4807 @inherits ViewModelTemplate<ProductViewModel> 4808 @using Dynamicweb.Ecommerce.ProductCatalog 4809 @using Dynamicweb.Rendering 4810 @using Dynamicweb.Core 4811 @using System.Linq 4812 4813 @helper RenderCustomerRatings(Dynamicweb.Content.Commenting.CommentCollection comments, System.Linq.IOrderedEnumerable<Dynamicweb.Content.Commenting.Comment> activeComments, string id) 4814 { 4815 4816 double totalRatingAmount = 0.0; 4817 var commentIndex = 0; 4818 4819 foreach (var comment in activeComments) 4820 { 4821 totalRatingAmount += comment.Rating; 4822 } 4823 4824 var ratingInPercent = ((totalRatingAmount / activeComments.Count()) / 5 * 100); 4825 string ratingInText = Converter.ToString(totalRatingAmount / activeComments.Count()); 4826 4827 <div id="@id" class="paragraph-container paragraph-container--full-width customer-ratings-section"> 4828 <div class="grid grid--justify-center js-customer-ratings-section"> 4829 <div class="grid__col-md-6 grid__col-lg-6 grid__col-xlg-5 grid__col-xxlg-4"> 4830 <h3 class="u-ta-center u-no-margin--bottom heading-reviews">@Translate("Brugernes anmeldelser")</h3> 4831 <div class="total-ratings"> 4832 @RenderCustomerRatings((totalRatingAmount / activeComments.Count()), 0, false) 4833 </div> 4834 @RenderRatingBadge(ratingInPercent, Translate("Philipson Wine"), Converter.ToString(Model.Rating)) 4835 <hr class="horizontal-line"> 4836 @foreach (var comment in activeComments) 4837 { 4838 commentIndex++; 4839 if (commentIndex == 3) 4840 { 4841 @:<div class="js-hidden-ratings u-hidden"> 4842 } 4843 if (commentIndex > 1) 4844 { 4845 <hr class="separation-line--width-full u-margin-top--lg u-margin-bottom--lg" /> 4846 } 4847 <div class="customer-rating"> 4848 <div class="u-bold">@comment.Name <span class="date">@comment.CreatedDate.ToString("dd. MMMM yyyy")</span></div> 4849 @RenderCustomerRatings(comment.Rating, 0, false) 4850 <p class="u-no-margin u-italic">@comment.Text</p> 4851 </div> 4852 if (commentIndex == activeComments.Count() && commentIndex >= 3) 4853 { 4854 @:</div> 4855 } 4856 } 4857 @if (commentIndex > 2) 4858 { 4859 <label class="u-margin-top--lg u-bold show-more js-show-more" data-show-description="@Translate("- skjul anmeldelser")">@Translate("+ flere anmeldelser")</label> 4860 } 4861 </div> 4862 </div> 4863 </div> 4864 } 4865 @inherits ViewModelTemplate<ProductViewModel> 4866 @using Dynamicweb.Ecommerce.ProductCatalog 4867 @using Dynamicweb.Rendering 4868 @using Dynamicweb.Rapido.Blocks 4869 4870 @helper RenderProducerInfo(Smartpage.PhilipsonWine.Producer.Model.Producer producer, string id) 4871 { 4872 <div id="@id" class="paragraph-container paragraph-container--full-width producer-section"> 4873 <div class="grid grid--justify-center"> 4874 <div class="grid__col-md-6 grid__col-lg-6 grid__col-xlg-5 grid__col-xxlg-4"> 4875 <h2 class="producer-section__header u-ta-center">@producer.ProducerName</h2> 4876 <p class="producer-section__text u-ta-center">@producer.ProducerDescription</p> 4877 <a href="/Default.aspx?ID=@producer.ProducerLink" class="producer-section__link">@Translate("Læs om producenten") <i class="fas fa-angle-right producer-section__link-arrow"></i></a> 4878 <div class="u-flex u-justify-content--center producer-section__image-section"> 4879 <div class="grid__col-md-6 producer-section__image" style="background-image: url('@producer.ProducerImageFirst')"></div> 4880 <div class="grid__col-md-6 producer-section__image" style="background-image: url('@producer.ProducerImageSecond')"></div> 4881 </div> 4882 </div> 4883 </div> 4884 </div> 4885 } 4886 @inherits ViewModelTemplate<ProductViewModel> 4887 @using Dynamicweb.Ecommerce.ProductCatalog 4888 @using Dynamicweb.Rendering 4889 @using Dynamicweb.Rapido.Blocks 4890 @using Smartpage.PhilipsonWine.Ecommerce.ProductInformation 4891 4892 @functions 4893 { 4894 BlocksPage productAttributeIconsProductPage = BlocksPage.GetBlockPage("Product"); 4895 } 4896 4897 @{ 4898 if (!eventProduct) 4899 { 4900 Block attributeIconsBlock = new Block() 4901 { 4902 Id = "MainProductAttributeIconSection", 4903 SortId = 10, 4904 Template = RenderProductAttributeIcons() 4905 }; 4906 productAttributeIconsProductPage.Add("AttributeIcons", attributeIconsBlock); 4907 } 4908 } 4909 4910 @helper RenderProductAttributeIcons() 4911 { 4912 ProductInformation productInformation = new ProductInformation(Model); 4913 4914 string type = productInformation.Type; 4915 string country = productInformation.Country; 4916 string primaryGrape = productInformation.PrimaryGrape; 4917 string secondaryGrape = productInformation.SecondaryGrape; 4918 string grapeToShow = !string.IsNullOrWhiteSpace(secondaryGrape) ? Translate("Smartpage:ProductDetail.Information.Blend", "Blend") : primaryGrape; 4919 string area = productInformation.Area; 4920 string year = productInformation.Year == "0" ? Translate("Smartpage:ProductDetail.Information.NonVintage", "NV") : productInformation.Year; 4921 4922 <div class="paragraph-container paragraph-container--full-width product-information"> 4923 <div class="grid grid--justify-center"> 4924 <div class="grid__col-md-6 grid__col-lg-6 grid__col-xlg-5 grid__col-xxlg-4 js-product-information-swiper-container"> 4925 <div class="product-attributes"> 4926 @if (!string.IsNullOrWhiteSpace(type)) 4927 { 4928 <div class="product-attributes__attribute js-attribute"> 4929 <div class="icon"> 4930 @RenderTypeIcon() 4931 </div> 4932 @type 4933 </div> 4934 } 4935 @if (!string.IsNullOrWhiteSpace(grapeToShow)) 4936 { 4937 <div class="product-attributes__attribute js-attribute"> 4938 <div class="icon"> 4939 @RenderGrapeIcon() 4940 </div> 4941 @grapeToShow 4942 </div> 4943 } 4944 @if (!string.IsNullOrWhiteSpace(country)) 4945 { 4946 <div class="product-attributes__attribute js-attribute"> 4947 <div class="icon"> 4948 @RenderCountryIcon() 4949 </div> 4950 @country 4951 </div> 4952 } 4953 @if (!string.IsNullOrWhiteSpace(area)) 4954 { 4955 <div class="product-attributes__attribute js-attribute"> 4956 <div class="icon"> 4957 @RenderAreaIcon() 4958 </div> 4959 @area 4960 </div> 4961 } 4962 @if (!string.IsNullOrWhiteSpace(year)) 4963 { 4964 <div class="product-attributes__attribute js-attribute"> 4965 <div class="icon"> 4966 @RenderYearIcon() 4967 </div> 4968 @year 4969 </div> 4970 } 4971 </div> 4972 </div> 4973 </div> 4974 </div> 4975 } 4976 4977 @helper RenderTypeIcon() 4978 { 4979 <svg width="28" height="35" xmlns="http://www.w3.org/2000/svg"> 4980 <g fill="#000" fill-rule="nonzero"> 4981 <path d="M9.9 10.753a10.818 10.818 0 01-.951-4.444V3.5a.59.59 0 00.596-.583V.583A.59.59 0 008.95 0H4.176a.59.59 0 00-.596.583v2.334a.59.59 0 00.596.583v2.81a10.822 10.822 0 01-.95 4.443L1.55 14.496A17.628 17.628 0 000 21.744v12.673A.59.59 0 00.597 35h11.931a.59.59 0 00.597-.583V21.744a17.623 17.623 0 00-1.551-7.248l-1.675-3.743zM4.772 1.167h3.58v1.166h-3.58V1.167zm7.159 32.666H1.193v-12.09a16.495 16.495 0 011.451-6.78l1.675-3.744a11.958 11.958 0 001.05-4.91V3.5h2.387v2.81a11.954 11.954 0 001.05 4.91l1.675 3.743a16.495 16.495 0 011.45 6.78v12.09z" /> 4982 <path d="M7.066 14.884l.547 1.175c.283.609.524 1.234.722 1.871.082.264.34.445.632.445a.707.707 0 00.185-.025c.349-.095.548-.44.446-.767a16.303 16.303 0 00-.782-2.02l-.547-1.174a.652.652 0 00-.53-.384.677.677 0 00-.615.251.588.588 0 00-.06.627h.002zM6.62 12.828c.105.18.34.297.601.297.09 0 .18-.014.262-.042.33-.11.482-.4.337-.65l-.448-.775c-.152-.242-.53-.348-.854-.242-.324.107-.478.39-.346.637l.449.775zM3.188 20.125c-.311 0-.563.268-.563.599V30.9c0 .33.252.599.563.599h6.75c.31 0 .562-.268.562-.599V20.724c0-.33-.252-.599-.563-.599h-6.75zm6.187 10.178H3.75v-8.98h5.625v8.98zM26.09 33.6a7.914 7.914 0 00-4.056-1.493v-8.22c3.377-.304 5.962-3.072 5.966-6.387a.564.564 0 00-.006-.083l-.314-2.15v-.004l-.879-6.013a.593.593 0 00-.59-.5h-9.546a.592.592 0 00-.59.5l-1.194 8.167a.564.564 0 00-.006.083c.004 3.315 2.59 6.083 5.966 6.387v8.22a7.911 7.911 0 00-4.057 1.494l-.477.35a.576.576 0 00-.207.65.596.596 0 00.565.399h9.545c.257 0 .485-.16.566-.399a.576.576 0 00-.208-.65l-.477-.35zM17.183 9.917h8.51l.717 4.9-1.148.125a10.303 10.303 0 01-3.888-.317l-.072-.02c-1.465-.407-3-.52-4.512-.333l-.248.03.641-4.385zm-1.114 7.623l.298-2.042.57-.068c1.35-.17 2.72-.07 4.03.292l.07.02c1.414.397 2.895.518 4.357.357l1.185-.13.229 1.571c0 2.9-2.404 5.25-5.37 5.25-2.965 0-5.369-2.35-5.369-5.25zm2.64 16.293a6.812 6.812 0 015.46 0h-5.46z" /> 4983 </g> 4984 </svg> 4985 } 4986 4987 @helper RenderGrapeIcon() 4988 { 4989 <img src="~/Files/Images/philipsonwine/ikoner/drue.png" alt="Drue" /> 4990 } 4991 4992 @helper RenderCountryIcon() 4993 { 4994 <svg width="36" height="35" xmlns="http://www.w3.org/2000/svg"> 4995 <path d="M18.12 0C10.995-.001 4.556 4.174 1.751 10.612l-.221.072.086.254c-3.693 8.952.696 19.15 9.803 22.78 2.127.848 4.4 1.283 6.696 1.282 9.833.001 17.805-7.832 17.806-17.497C35.923 7.838 27.953 0 18.121 0zm13.965 26.323l-.914-.898v-2.092a.574.574 0 00-.06-.26l-2.314-4.544v-2.196a.58.58 0 00-.264-.485l-1.78-1.167a.602.602 0 00-.475-.08l-2.18.535-3.663-1.544-.503-3.47 1.396-1.372h2.997l1.01 1.49a.594.594 0 00.396.252l3.56.583a.598.598 0 00.285-.022l3.28-1.075a16.037 16.037 0 01-.771 16.345zM29.637 5.748l-.965.632-2.69-.529-1.745-.57a.592.592 0 00-.331-.014l-2.207.542-.967-.316.717-1.41h2.007c.092 0 .183-.02.265-.06l2.054-1.01a16.673 16.673 0 013.862 2.735zM11.615 2.47l1.424.934c.07.045.15.076.232.09l2.876.47-.28.826-1.499.492a.592.592 0 00-.321.252l-1.704 2.792L9.605 9.94l-4.035.566a.587.587 0 00-.51.577v1.75c0 .155.062.303.173.413l1.013.995v1.003l-2.469-1.619-.895-2.64c1.704-3.827 4.827-6.872 8.733-8.516zm-1.69 19.126l-2.682-.528-.997-1.955v-1.37l2.211-2.174.819 1.61c.1.197.306.322.53.322h3.82l1.607 2.634c.107.175.3.283.508.283h1.65l-.415 2.045-2.247 2.209a.579.579 0 00-.175.412v1.459l-2.136 1.575a.58.58 0 00-.237.466v2.107l-.739-.24-1.042-2.562v-5.721a.586.586 0 00-.474-.572zm-1.783 8.967C2.546 26.436.18 19.307 2.223 12.731l.493 1.453a.584.584 0 00.234.301l2.958 1.939-.675.664a.578.578 0 00-.174.412v1.75c0 .09.022.18.063.26l1.187 2.334a.592.592 0 00.415.311l2.492.49V28c0 .074.015.148.043.216l1.186 2.917a.59.59 0 00.364.337l1.78.583a.592.592 0 00.779-.553v-2.625l2.136-1.575a.58.58 0 00.237-.467v-1.508l2.2-2.163a.58.58 0 00.162-.298l.594-2.916a.584.584 0 00-.582-.698h-2.038l-1.607-2.634a.596.596 0 00-.509-.283h-3.787l-1.02-2.01a.593.593 0 00-.436-.315.588.588 0 00-.515.163l-.77.754V14a.578.578 0 00-.174-.412l-1.013-.996v-1.003l3.645-.512a.603.603 0 00.221-.077l2.968-1.75a.588.588 0 00.203-.2L14.95 6.32l1.572-.516a.582.582 0 00.375-.369l.594-1.75a.581.581 0 00-.465-.758l-3.435-.563-.604-.395a16.84 16.84 0 0111.413.417l-1.084.532h-2.234a.595.595 0 00-.534.322l-1.187 2.334a.579.579 0 00.344.813l1.78.584c.107.035.222.04.331.012l2.207-.541 1.616.529a.442.442 0 00.072.018l2.967.584c.154.03.315 0 .445-.087l1.351-.885a16.482 16.482 0 011.785 2.344l-2.92.957-3.16-.518-1.045-1.54a.596.596 0 00-.491-.26h-3.56a.599.599 0 00-.42.171l-1.78 1.75a.577.577 0 00-.169.495l.594 4.084c.03.202.165.374.356.453l4.154 1.75c.12.05.252.061.377.03l2.12-.521 1.295.85v2.022c0 .09.02.18.06.26l2.314 4.544v2.196c0 .154.063.303.174.412l1.241 1.221c-5.506 7.214-15.918 8.675-23.257 3.262z" fill="#000" fill-rule="nonzero" /> 4996 </svg> 4997 } 4998 4999 @helper RenderAreaIcon() 5000 { 5001 <svg width="37" height="37" xmlns="http://www.w3.org/2000/svg"> 5002 <g fill="#000" fill-rule="nonzero"> 5003 <path d="M36.293 28.59c-5.907 0-11.704 2.595-15.905 7.119a.795.795 0 00.002 1.07c.138.148.319.221.5.221a.682.682 0 00.5-.223c3.938-4.24 9.37-6.671 14.903-6.671.39 0 .707-.34.707-.758s-.317-.757-.707-.757zM21.736 28.077a.742.742 0 00-1.03-.2 29.285 29.285 0 00-7.966 7.968.742.742 0 101.232.827 27.8 27.8 0 017.565-7.566c.34-.229.429-.69.2-1.03zM36.262 22.705c-3.298 0-6.562.61-9.702 1.812-.384.147-.585.603-.45 1.019a.743.743 0 00.696.532.687.687 0 00.246-.046 25.668 25.668 0 019.21-1.72c.408 0 .738-.358.738-.799 0-.441-.33-.798-.738-.798z" /> 5004 <path d="M10.354 32.041c4.754-6.199 11.636-10.503 19.23-12.116h.005a32.209 32.209 0 016.688-.705.723.723 0 000-1.446c-2.054 0-4.101.188-6.113.556v-1.56c2.612-2.21 4.045-5.108 4.045-8.194 0-3.19-1.532-6.179-4.315-8.417a.723.723 0 00-.906 0c-2.783 2.238-4.316 5.227-4.316 8.417 0 3.086 1.434 5.983 4.046 8.194v1.856c-1.373.312-2.726.71-4.051 1.19v-4.23a.72.72 0 00-.21-.51l-4.047-4.071a.723.723 0 00-.513-.213h-8.262a.723.723 0 00-.513.213l-4.046 4.07a.72.72 0 00-.21.51v2.76a33.809 33.809 0 00-1.518-.243v-2.576c1.975-1.7 3.059-3.915 3.059-6.276 0-2.466-1.183-4.775-3.33-6.501a.723.723 0 00-.905 0C2.026 4.475.843 6.784.843 9.249c0 2.361 1.084 4.577 3.06 6.276v2.41a34.156 34.156 0 00-3.18-.149.723.723 0 100 1.446c5.778 0 11.43 1.529 16.413 4.429a34.114 34.114 0 00-3.414 2.651C9.685 24.256 5.2 23.17.722 23.17a.723.723 0 000 1.445c4.074 0 8.156.948 11.865 2.747a34.154 34.154 0 00-3.074 3.402 22.605 22.605 0 00-8.79-1.776.723.723 0 000 1.445c2.71 0 5.36.514 7.89 1.525-.5.694-.974 1.407-1.42 2.139L6.092 35.9a.722.722 0 101.233.753l1.102-1.804a32.082 32.082 0 011.856-2.716.684.684 0 00.071-.093zM26.118 8.576c0-2.568 1.175-5.001 3.323-6.908 2.148 1.907 3.323 4.34 3.323 6.908 0 2.264-.913 4.422-2.6 6.208V9.25a.723.723 0 10-1.446 0v5.534c-1.687-1.786-2.6-3.944-2.6-6.208zm-23.83.674c0-1.843.826-3.594 2.337-4.985 1.511 1.39 2.336 3.142 2.336 4.985 0 1.523-.564 2.984-1.613 4.23V8.673a.723.723 0 10-1.446 0v4.809C2.853 12.234 2.29 10.773 2.29 9.25zm19.919 5.612h-6.225l-2.61-2.625h6.225l2.61 2.625zM11.635 12.54l2.31 2.323h-4.62l2.31-2.323zM8.31 16.308h6.648v4.595a34.266 34.266 0 00-1.012-.446V18.03a.723.723 0 00-.722-.723h-3.18a.723.723 0 00-.723.723v.86c-.336-.088-.673-.171-1.011-.249v-2.333zm4.191 3.579a33.933 33.933 0 00-1.734-.587v-.547h1.734v1.134zm3.902 1.723v-5.302h6.818v4.07a33.917 33.917 0 00-4.732 2.409 34.266 34.266 0 00-2.086-1.177z" /> 5005 <path d="M29.432 7.568c.22 0 .438-.09.594-.247a.847.847 0 00.247-.594.846.846 0 00-.247-.594.846.846 0 00-.594-.247.845.845 0 00-.841.841.846.846 0 00.84.841zM22.95 26.315a.848.848 0 00-.245.594c0 .222.09.438.246.595a.847.847 0 00.594.246c.222 0 .439-.09.595-.246a.846.846 0 00.246-.595.846.846 0 00-.84-.84.847.847 0 00-.595.246z" /> 5006 </g> 5007 </svg> 5008 } 5009 5010 @helper RenderYearIcon() 5011 { 5012 <svg width="35" height="35" xmlns="http://www.w3.org/2000/svg"> 5013 <g fill="#000" fill-rule="nonzero"> 5014 <path d="M33.25 2.333h-2.917V1.75A1.75 1.75 0 0028.583 0h-1.166a1.75 1.75 0 00-1.75 1.75v.583H9.333V1.75A1.75 1.75 0 007.583 0H6.417a1.75 1.75 0 00-1.75 1.75v.583H1.75A1.75 1.75 0 000 4.083V33.25C0 34.216.784 35 1.75 35h31.5A1.75 1.75 0 0035 33.25V4.083a1.75 1.75 0 00-1.75-1.75zm-6.417-.583c0-.322.262-.583.584-.583h1.166c.322 0 .584.26.584.583v3.5a.583.583 0 01-.584.583h-1.166a.583.583 0 01-.584-.583v-3.5zm-21 0c0-.322.262-.583.584-.583h1.166c.322 0 .584.26.584.583v3.5a.583.583 0 01-.584.583H6.417a.583.583 0 01-.584-.583v-3.5zM1.167 4.083c0-.322.26-.583.583-.583h2.917v1.75c0 .966.783 1.75 1.75 1.75h1.166a1.75 1.75 0 001.75-1.75V3.5h16.334v1.75c0 .966.783 1.75 1.75 1.75h1.166a1.75 1.75 0 001.75-1.75V3.5h2.917c.322 0 .583.261.583.583v4.084H1.167V4.083zM33.833 33.25a.583.583 0 01-.583.583H1.75a.583.583 0 01-.583-.583V9.333h32.666V33.25z" /> 5015 <path d="M18.667 23.333h-2.334a.583.583 0 01-.583-.583v-2.333c0-.322.261-.584.583-.584h2.334c.322 0 .583.262.583.584v2.333a.583.583 0 01-.583.583zm-1.75-1.166h1.166V21h-1.166v1.167zM24.5 23.333h-2.333a.583.583 0 01-.584-.583v-2.333c0-.322.262-.584.584-.584H24.5c.322 0 .583.262.583.584v2.333a.583.583 0 01-.583.583zm-1.75-1.166h1.167V21H22.75v1.167zM12.833 23.333H10.5a.583.583 0 01-.583-.583v-2.333c0-.322.26-.584.583-.584h2.333c.322 0 .584.262.584.584v2.333a.583.583 0 01-.584.583zm-1.75-1.166h1.167V21h-1.167v1.167zM30.333 23.333H28a.583.583 0 01-.583-.583v-2.333c0-.322.26-.584.583-.584h2.333c.322 0 .584.262.584.584v2.333a.583.583 0 01-.584.583zm-1.75-1.166h1.167V21h-1.167v1.167zM7 23.333H4.667a.583.583 0 01-.584-.583v-2.333c0-.322.262-.584.584-.584H7c.322 0 .583.262.583.584v2.333a.583.583 0 01-.583.583zm-1.75-1.166h1.167V21H5.25v1.167zM18.667 17.5h-2.334a.583.583 0 01-.583-.583v-2.334c0-.322.261-.583.583-.583h2.334c.322 0 .583.261.583.583v2.334a.583.583 0 01-.583.583zm-1.75-1.167h1.166v-1.166h-1.166v1.166zM24.5 17.5h-2.333a.583.583 0 01-.584-.583v-2.334c0-.322.262-.583.584-.583H24.5c.322 0 .583.261.583.583v2.334a.583.583 0 01-.583.583zm-1.75-1.167h1.167v-1.166H22.75v1.166zM12.833 17.5H10.5a.583.583 0 01-.583-.583v-2.334c0-.322.26-.583.583-.583h2.333c.322 0 .584.261.584.583v2.334a.583.583 0 01-.584.583zm-1.75-1.167h1.167v-1.166h-1.167v1.166zM30.333 17.5H28a.583.583 0 01-.583-.583v-2.334c0-.322.26-.583.583-.583h2.333c.322 0 .584.261.584.583v2.334a.583.583 0 01-.584.583zm-1.75-1.167h1.167v-1.166h-1.167v1.166zM7 17.5H4.667a.583.583 0 01-.584-.583v-2.334c0-.322.262-.583.584-.583H7c.322 0 .583.261.583.583v2.334A.583.583 0 017 17.5zm-1.75-1.167h1.167v-1.166H5.25v1.166zM18.667 29.167h-2.334a.583.583 0 01-.583-.584V26.25c0-.322.261-.583.583-.583h2.334c.322 0 .583.26.583.583v2.333a.583.583 0 01-.583.584zM16.917 28h1.166v-1.167h-1.166V28zM24.5 29.167h-2.333a.583.583 0 01-.584-.584V26.25c0-.322.262-.583.584-.583H24.5c.322 0 .583.26.583.583v2.333a.583.583 0 01-.583.584zM22.75 28h1.167v-1.167H22.75V28zM12.833 29.167H10.5a.583.583 0 01-.583-.584V26.25c0-.322.26-.583.583-.583h2.333c.322 0 .584.26.584.583v2.333a.583.583 0 01-.584.584zM11.083 28h1.167v-1.167h-1.167V28zM30.333 29.167H28a.583.583 0 01-.583-.584V26.25c0-.322.26-.583.583-.583h2.333c.322 0 .584.26.584.583v2.333a.583.583 0 01-.584.584zM28.583 28h1.167v-1.167h-1.167V28zM7 29.167H4.667a.583.583 0 01-.584-.584V26.25c0-.322.262-.583.584-.583H7c.322 0 .583.26.583.583v2.333a.583.583 0 01-.583.584zM5.25 28h1.167v-1.167H5.25V28z" /> 5016 </g> 5017 </svg> 5018 } 5019 @inherits ViewModelTemplate<ProductViewModel> 5020 @using Dynamicweb.Ecommerce.ProductCatalog 5021 @using Dynamicweb.Rendering 5022 @using Dynamicweb.Rapido.Blocks 5023 5024 @helper RenderInPageMenu(List<Block> sections) 5025 { 5026 var excludedSections = new List<string> { 5027 "InPageMenu", 5028 "ClerkAlternativesSection", 5029 "ClerkOthersAlsoBoughtSection" 5030 }; 5031 <div class="paragraph-container paragraph-container--full-width in-page-menu"> 5032 <div class="grid grid--justify-center"> 5033 <div class="grid__col-md-6 grid__col-lg-6 grid__col-xlg-5 grid__col-xxlg-4"> 5034 <div class="in-page-menu__wrapper"> 5035 @foreach (var productSection in sections.OrderBy(x => x.SortId)) 5036 { 5037 if (!excludedSections.Contains(productSection.Id)) 5038 { 5039 <div class="in-page-menu__wrapper__item js-in-page-menu__wrapper__item hover hover-3" onclick="scrollToNode('#@productSection.Id', -56)" data-id="@productSection.Id"> 5040 @Translate("Smartpage:Product.InPageMenu.Title." + productSection.Id, productSection.Id) 5041 </div> 5042 } 5043 } 5044 </div> 5045 </div> 5046 </div> 5047 </div> 5048 } 5049 @inherits ViewModelTemplate<ProductViewModel> 5050 @using Dynamicweb.Ecommerce.ProductCatalog 5051 @using Dynamicweb.Rendering 5052 @using Dynamicweb.Rapido.Blocks 5053 @using Smartpage.PhilipsonWine.Ecommerce.ProductInformation 5054 @using Dynamicweb.Core 5055 5056 @functions 5057 { 5058 public string createFilterCheckboxLink(string key, string value) 5059 { 5060 string filterValue = "[" + value + "]"; 5061 string link = "&" + key + "=" + HttpUtility.UrlEncode(filterValue); 5062 return link; 5063 } 5064 } 5065 5066 @helper RenderProductFields(string id) 5067 { 5068 ProductInformation productInformation = new ProductInformation(Model); 5069 string type = productInformation.Type; 5070 int bottleSizeCl = productInformation.BottleSizeCl; 5071 string producerId = productInformation.ProducerId; 5072 string country = productInformation.Country; 5073 string area = productInformation.Area; 5074 string primaryGrape = productInformation.PrimaryGrape; 5075 string recommendedTo = productInformation.RecommendedTo; 5076 string storage = productInformation.Storage; 5077 int alcoholPercentage = Converter.ToInt32(productInformation.AlcoholPercentage); 5078 string acidityLevel = productInformation.AcidityLevel; 5079 string restSweet = productInformation.RestSweet; 5080 bool ecological = productInformation.Ecological; 5081 5082 string perfionId = productInformation.PerfionId; 5083 string perfionDataSheetPageId = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetString("PerfionDataSheetPageId"); 5084 string datasheetUrl = string.Empty; 5085 5086 if (!string.IsNullOrEmpty(perfionId) && !string.IsNullOrEmpty(perfionDataSheetPageId)) 5087 { 5088 datasheetUrl = string.Format("/Default.aspx?ID={0}&ReportId={1}", perfionDataSheetPageId, perfionId); 5089 } 5090 5091 string keyColClasses = "grid__col-5 grid__col-sm-4"; 5092 string valueColClasses = "grid__col-7 grid__col-sm-8"; 5093 5094 <div id="@id" class="paragraph-container paragraph-container--full-width product-fields"> 5095 <div class="grid grid--justify-center"> 5096 <div class="grid__col-md-6 grid__col-lg-6 grid__col-xlg-5 grid__col-xxlg-4 product-fields-section"> 5097 <h3 class="product-fields-section__header">@Translate("Smartpage:ProductDetail.ProductFields.Header", "Informationer")</h3> 5098 <div class="product-fields-section__fields"> 5099 <div class="field grid"> 5100 <div class="@keyColClasses field__key"> 5101 @Translate("Smartpage:ProductDetail.ProductFields.ProductNumber", "Varenummer") 5102 </div> 5103 <div class="@valueColClasses field__value">@Model.Id</div> 5104 </div> 5105 @if (!string.IsNullOrWhiteSpace(type)) 5106 { 5107 string link = "/Default.aspx?ID=" + GetPageIdByNavigationTag("ProductsPage") + createFilterCheckboxLink("Type", type); 5108 <div class="field grid"> 5109 <div class="@keyColClasses field__key"> 5110 @Translate("Smartpage:ProductDetail.ProductFields.Type", "Type") 5111 </div> 5112 <div class="@valueColClasses field__value"> 5113 <a class="link" href="@link">@type</a> 5114 </div> 5115 </div> 5116 } 5117 @if (bottleSizeCl > 0) 5118 { 5119 <div class="field grid"> 5120 <div class="@keyColClasses field__key"> 5121 @Translate("Smartpage:ProductDetail.ProductFields.BottleSize", "Flaskestørrelse") 5122 </div> 5123 <div class="@valueColClasses field__value"> 5124 @productInformation.BottleSize 5125 </div> 5126 </div> 5127 } 5128 @if (productInformation.Kolli > 1) 5129 { 5130 <div class="field grid"> 5131 <div class="@keyColClasses field__key"> 5132 @Translate("Smartpage:ProductDetail.ProductFields.DeliveredIn", "Leveres i") 5133 </div> 5134 <div class="@valueColClasses field__value"> 5135 @Translate("Smartpage:ProductDetail.ProductFields.DeliveredIn.CartonWith", "Leveres i karton med") @productInformation.Kolli @Translate("Smartpage:ProductDetail.ProductFields.DeliveredIn.Unit", "stk.") 5136 </div> 5137 </div> 5138 } 5139 @if (alcoholPercentage > 0) 5140 { 5141 <div class="field grid"> 5142 <div class="@keyColClasses field__key"> 5143 @Translate("Smartpage:ProductDetail.ProductFields.AlcoholPercentage", "Alkoholprocent") 5144 </div> 5145 <div class="@valueColClasses field__value"> 5146 @alcoholPercentage% 5147 </div> 5148 </div> 5149 } 5150 @if (!string.IsNullOrWhiteSpace(acidityLevel)) 5151 { 5152 <div class="field grid"> 5153 <div class="@keyColClasses field__key"> 5154 @Translate("Smartpage:ProductDetail.ProductFields.AcidityLevel", "Syreniveau") 5155 </div> 5156 <div class="@valueColClasses field__value"> 5157 @acidityLevel% 5158 </div> 5159 </div> 5160 } 5161 @if (!string.IsNullOrWhiteSpace(producerId)) 5162 { 5163 var producerService = new Smartpage.PhilipsonWine.Producer.Repositories.ProducerService(); 5164 var producer = producerService.GetProductProducer(producerId); 5165 5166 if (producer != null && !string.IsNullOrWhiteSpace(producer.ProducerName) && !string.IsNullOrWhiteSpace(producer.ProducerLink) && !producer.ProducerHidden) 5167 { 5168 <div class="field grid"> 5169 <div class="@keyColClasses field__key"> 5170 @Translate("Smartpage:ProductDetail.ProductFields.Producer", "Producent") 5171 </div> 5172 <div class="@valueColClasses field__value"> 5173 <a class="link" href="/Default.aspx?ID=@producer.ProducerLink">@producer.ProducerName</a> 5174 </div> 5175 </div> 5176 } 5177 } 5178 @if (!string.IsNullOrWhiteSpace(country)) 5179 { 5180 string link = "/Default.aspx?ID=" + GetPageIdByNavigationTag("ProductsPage") + createFilterCheckboxLink("Country", country); 5181 <div class="field grid"> 5182 <div class="@keyColClasses field__key"> 5183 @Translate("Smartpage:ProductDetail.ProductFields.Country", "Land") 5184 </div> 5185 <div class="@valueColClasses field__value"> 5186 <a class="link" href="@link">@country</a> 5187 </div> 5188 </div> 5189 } 5190 @if (!string.IsNullOrWhiteSpace(area)) 5191 { 5192 string link = "/Default.aspx?ID=" + GetPageIdByNavigationTag("ProductsPage") + createFilterCheckboxLink("Region", area); 5193 <div class="field grid"> 5194 <div class="@keyColClasses field__key"> 5195 @Translate("Smartpage:ProductDetail.ProductFields.Area", "Area") 5196 </div> 5197 <div class="@valueColClasses field__value"> 5198 <a class="link" href="@link">@area</a> 5199 </div> 5200 </div> 5201 } 5202 @if (!string.IsNullOrWhiteSpace(primaryGrape)) 5203 { 5204 string primaryGrapeLink = "/Default.aspx?ID=" + GetPageIdByNavigationTag("ProductsPage") + "&Grape=" + HttpUtility.UrlEncode("[" + primaryGrape + "]"); 5205 string secondaryGrape = productInformation.SecondaryGrape; 5206 string grapeComposition = productInformation.GrapeComposition; 5207 5208 <div class="field grid"> 5209 <div class="@keyColClasses field__key"> 5210 @Translate("Smartpage:ProductDetail.ProductFields.Grapes", "Druesorter") 5211 </div> 5212 <div class="@valueColClasses field__value"> 5213 @if (string.IsNullOrWhiteSpace(secondaryGrape)) 5214 { 5215 <a class="link" href="@primaryGrapeLink">@grapeComposition</a> 5216 } 5217 else 5218 { 5219 string blendLink = "/Default.aspx?ID=" + GetPageIdByNavigationTag("ProductsPage") + "&Grape=" + HttpUtility.UrlEncode("[" + primaryGrape + "],") + HttpUtility.UrlEncode("[" + secondaryGrape + "]"); 5220 <a class="link" href="@blendLink">@grapeComposition</a> 5221 } 5222 </div> 5223 </div> 5224 } 5225 @if (!string.IsNullOrWhiteSpace(recommendedTo)) 5226 { 5227 string recommendedToFormatted = recommendedTo.Replace(",", ", "); 5228 <div class="field grid"> 5229 <div class="@keyColClasses field__key"> 5230 @Translate("Smartpage:ProductDetail.ProductFields.ReccommendedTo", "Anbefalet til") 5231 </div> 5232 <div class="@valueColClasses field__value"> 5233 @recommendedToFormatted 5234 </div> 5235 </div> 5236 } 5237 @if (!string.IsNullOrWhiteSpace(storage)) 5238 { 5239 <div class="field grid"> 5240 <div class="@keyColClasses field__key"> 5241 @Translate("Smartpage:ProductDetail.ProductFields.Storage", "Lagring") 5242 </div> 5243 <div class="@valueColClasses field__value"> 5244 @storage 5245 </div> 5246 </div> 5247 } 5248 @if (!string.IsNullOrWhiteSpace(restSweet)) 5249 { 5250 <div class="field grid"> 5251 <div class="@keyColClasses field__key"> 5252 @Translate("Smartpage:ProductDetail.ProductFields.RestSweet", "Restsukker") 5253 </div> 5254 <div class="@valueColClasses field__value"> 5255 @restSweet 5256 </div> 5257 </div> 5258 } 5259 @if (ecological) 5260 { 5261 <div class="field grid"> 5262 <div class="@keyColClasses field__key"> 5263 @Translate("Smartpage:ProductDetail.ProductFields.Ecological", "Økologisk") 5264 </div> 5265 <div class="@valueColClasses field__value"> 5266 @Translate("Smartpage:ProductDetail.ProductFields.Ecological.Yes", "Ja") 5267 </div> 5268 </div> 5269 } 5270 @if (!string.IsNullOrWhiteSpace(datasheetUrl)) 5271 { 5272 <a href="@datasheetUrl" class="btn btn--download-datasheet">@Translate("Smartpage:ProductDetail.ProductFields.DownloadDatasheet", "Download produktblad") <i class="fal fa-arrow-to-bottom"></i></a> 5273 } 5274 </div> 5275 </div> 5276 </div> 5277 </div> 5278 } 5279 @inherits ViewModelTemplate<ProductViewModel> 5280 @using Dynamicweb.Ecommerce.ProductCatalog 5281 @using Dynamicweb.Rendering 5282 @using System.Collections.Generic 5283 5284 @helper RenderExpertRatings(List<Smartpage.PhilipsonWine.Ratings.Model.ProductRating> rating, string id) 5285 { 5286 var expertRatingsCounter = 0; 5287 5288 <div id="@id" class="paragraph-container paragraph-container--full-width expert-ratings js-expert-ratings"> 5289 <div class="grid grid--justify-center"> 5290 <div class="grid__col-md-6 grid__col-lg-6 grid__col-xlg-5 grid__col-xxlg-4"> 5291 <h3 class="u-no-margin heading-reviews">@Translate("Anmeldelser")</h3> 5292 <hr class="horizontal-line" /> 5293 5294 @foreach (var item in rating) 5295 { 5296 5297 expertRatingsCounter++; 5298 if (expertRatingsCounter == 3) 5299 { 5300 @:<div class="js-hidden-ratings u-hidden"> 5301 } 5302 if (expertRatingsCounter > 1) 5303 { 5304 <hr class="separation-line--width-full u-margin-top--lg u-margin-bottom--lg" /> 5305 } 5306 5307 if (item.RatingType == "4") 5308 { 5309 var count = 0; 5310 5311 <div class="customer-rating"> 5312 5313 @foreach (var cr in item.CombinedRatings) 5314 { 5315 count++; 5316 5317 if (count == 1) 5318 { 5319 <label class="u-bold">@cr.RatingMedia</label> 5320 5321 } 5322 5323 <div class="expert-ratings__rating"> 5324 @RenderExpertRating(cr.RatingScoreTo, cr.RatingScoreFrom, cr.RatingMaxScore, cr.RatingType, cr.RatingTextScore) 5325 </div> 5326 5327 if (count == item.CombinedRatings.Count) 5328 { 5329 <p class="u-no-margin u-italic">@cr.RatingQuote</p> 5330 } 5331 } 5332 </div> 5333 5334 } 5335 else 5336 { 5337 <div class="customer-rating"> 5338 <label class="u-bold">@item.RatingMedia</label> 5339 <div class="expert-ratings__rating"> 5340 @RenderExpertRating(item.RatingScoreTo, item.RatingScoreFrom, item.RatingMaxScore, item.RatingType, item.RatingTextScore) 5341 </div> 5342 <p class="u-no-margin u-italic">@item.RatingQuote</p> 5343 </div> 5344 } 5345 5346 if (expertRatingsCounter == rating.Count && expertRatingsCounter >= 3) 5347 { 5348 @:</div> 5349 } 5350 } 5351 @if (expertRatingsCounter > 2) 5352 { 5353 <label class="u-margin-top--lg u-bold show-more js-show-more" data-show-description="@Translate("- skjul anmeldelser")">@Translate("+ flere anmeldelser")</label> 5354 } 5355 </div> 5356 </div> 5357 </div> 5358 } 5359 5360 @inherits ViewModelTemplate<ProductViewModel> 5361 @using Dynamicweb.Ecommerce.ProductCatalog 5362 @using Dynamicweb.Rendering 5363 @using Dynamicweb.Core 5364 @using System 5365 @using System.Web 5366 @using System.Collections.Generic 5367 @using Dynamicweb.Rapido.Services 5368 @using Dynamicweb.Rapido.Blocks 5369 @using Dynamicweb.Rapido.Blocks.Components.Ecommerce 5370 @using Dynamicweb.Rapido.Blocks.Components.General 5371 @using System.Text.RegularExpressions; 5372 @using Smartpage.PhilipsonWine.Ratings; 5373 @using Smartpage.PhilipsonWine.Ratings.Model; 5374 5375 5376 @functions 5377 { 5378 BlocksPage ratingBadgesSectionProductPage = BlocksPage.GetBlockPage("Product"); 5379 BlocksPage ratingBadgeSvgFooterBlock = BlocksPage.GetBlockPage("Master"); 5380 } 5381 5382 @{ 5383 5384 var customerRating = GetCustomerRatingValues(Converter.ToDouble(Model.Rating)); 5385 5386 //Getting expert rating data 5387 var expertRatingsBadge = Smartpage.PhilipsonWine.Ratings.Controller.ProductRatings.GetRatingProduct(Model.Id); 5388 5389 //Adding rating badges section to document 5390 Block ratingBadgesSectionBlock = new Block() 5391 { 5392 Id = "ratingBadgesSection", 5393 Template = RenderRatingsBadges(expertRatingsBadge, customerRating) 5394 }; 5395 5396 if (expertRatingsBadge.Any() || customerRating.ratingInDouble > 0) 5397 { 5398 ratingBadgesSectionProductPage.Add("MainImage", ratingBadgesSectionBlock); 5399 } 5400 } 5401 5402 @helper RenderRatingsBadges(List<ProductRating> expertRatings, (double ratingInPercent, string ratingInText, double ratingInDouble) customerRating) 5403 { 5404 <div class="grid grid__col-3 grid--align-content-center u-no-padding jus badges dw-mod"> 5405 @if (customerRating.ratingInDouble > 0) 5406 { 5407 <div class="u-margin-top"> 5408 @RenderRatingBadge(customerRating.ratingInPercent, Translate("Smartpage:CustomerRating.Philipson Wine", "Philipson Wine"), customerRating.ratingInText) 5409 </div> 5410 } 5411 5412 @foreach (var expertRating in expertRatings.Where(x => x.RatingType != Converter.ToString((int)Smartpage.PhilipsonWine.Ratings.Controller.ProductRatings.RatingTypes.FullRating) && x.RatingType != Converter.ToString((int)Smartpage.PhilipsonWine.Ratings.Controller.ProductRatings.RatingTypes.FreeText) && !string.Equals(x.RatingMedia, "den korte avis", StringComparison.InvariantCultureIgnoreCase)).Take(3)) 5413 { 5414 var item = GetExpertRatingValues(expertRating); 5415 5416 <div class="u-margin-top"> 5417 @RenderRatingBadge(Converter.ToDouble(item.ratingPercentage), item.ratingName, item.ratingText, false, item.ratingImage) 5418 </div> 5419 } 5420 5421 </div> 5422 } 5423 5424 5425 @inherits ViewModelTemplate<ProductViewModel> 5426 @using Dynamicweb.Ecommerce.ProductCatalog 5427 @using Dynamicweb.Rendering 5428 @using Dynamicweb.Rapido.Blocks 5429 @using Smartpage.PhilipsonWine.Ecommerce.ProductInformation 5430 @using Smartpage.PhilipsonWine.BomItems 5431 5432 5433 @*@using Dynamicweb.Ecommerce.ProductCatalog 5434 @using Dynamicweb.Rendering 5435 @using Dynamicweb.Core 5436 @using System 5437 @using System.Web 5438 @using System.Collections.Generic 5439 @using Dynamicweb.Rapido.Blocks 5440 @using Dynamicweb.Rapido.Blocks.Components 5441 @using Dynamicweb.Rapido.Blocks.Components.General 5442 @using Dynamicweb.Rapido.Services 5443 5444 @helper GridView(Dynamicweb.Frontend.ItemViewModel gridViewSettings) 5445 { 5446 int columnsCount = gridViewSettings.GetList("Columns") != null ? Converter.ToInt32(gridViewSettings.GetList("Columns").SelectedValue) : 3; 5447 string imageZoomOnHover = gridViewSettings.GetBoolean("HoverImageZoom") ? "image-hover--zoom" : ""; 5448 5449 <script id="ProductGridItemContainer" type="text/x-template"> 5450 {{#.}} 5451 <div id="Product{{id}}" data-template="GridViewItem" data-preloader="overlay" class="grid__col-lg-@(12 / columnsCount) grid__col-md-6 grid__col-sm-6 grid__col-xs-6 product-list__grid-item @imageZoomOnHover dw-mod product-list-product"> 5452 {{#Product}} 5453 {{>GridViewItem}} 5454 {{/Product}} 5455 </div> 5456 {{/.}} 5457 </script> 5458 } 5459 5460 @helper RenderGridViewItem(BlocksPage page) 5461 { 5462 List<Block> subBlocks = page.GetBlockListById("GridViewItem"); 5463 5464 <script id="GridViewItem" type="text/x-template"> 5465 {{#.}} 5466 <div class="grid__col--auto js-product-scroll-trigger u-no-padding u-full-height u-grey-border u-white-background u-padding-sides-8px" data-params="{{googleImpression}}"> 5467 {{>RenderRatingsBadges}} 5468 @RenderBlockList(subBlocks) 5469 </div> 5470 {{/.}} 5471 </script> 5472 5473 <script id="RenderRatingsBadges" type="text/x-template"> 5474 <div class="productlist-rating-badges"> 5475 {{#if CustomerRatingActive}} 5476 <div class="rating-badge c100 js-badge" data-percent="{{CustomerRatingInPercent}}"> 5477 <span class="rating-badge--text">@Translate("Smartpage:CustomerRating.Philipson Wine", "Philipson Wine")</span> 5478 <span class="rating-badge--score">{{{CustomerRatingInText}}}</span> 5479 <div class="slice"> 5480 <div class="bar"></div> 5481 <div class="fill"></div> 5482 </div> 5483 </div> 5484 {{/if}} 5485 {{#ExpertRatings}} 5486 {{#if image}} 5487 <div class="expert-rating-image"> 5488 @{ 5489 var imagePrefix = "/Admin/Public/GetImage.ashx?width=46&amp;height=46&amp;crop=5&amp;Compression=75&amp;FillCanvas=true&amp;DoNotUpscale=true&amp;image=/Files/Images/ExpertRatings/{{image}}.png"; 5490 5491 // CDN 5492 var cdnUrl = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetString("CDNUrl"); 5493 bool cdnActivate = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetBoolean("CDNActivate"); 5494 if (!string.IsNullOrWhiteSpace(cdnUrl) && cdnActivate) 5495 { 5496 imagePrefix = cdnUrl + imagePrefix; 5497 } 5498 } 5499 <img class="rating-image" src="@imagePrefix" alt="{{name}}" /> 5500 <span class="rating-image--score">{{{text}}}</span> 5501 </div> 5502 {{else}} 5503 <div class="rating-badge c100 dark js-badge" data-percent="{{percentage}}"> 5504 <span class="rating-badge--text">{{name}}</span> 5505 <span class="rating-badge--score">{{{text}}}</span> 5506 <div class="slice"> 5507 <div class="bar"></div> 5508 <div class="fill"></div> 5509 </div> 5510 </div> 5511 {{/if}} 5512 {{/ExpertRatings}} 5513 </div> 5514 </script> 5515 5516 5517 5518 } 5519 5520 @helper RenderGridViewItemHiddenProperties() 5521 { 5522 <input type="hidden" name="ProductLoopCounter{{id}}" value="{{id}}" /> 5523 <input type="hidden" name="ProductID{{id}}" value="{{productId}}" /> 5524 <input type="hidden" name="VariantID{{id}}" value="{{variantid}}" id="Variant_{{id}}" /> 5525 <input type="hidden" name="UnitID{{id}}" value="{{unitId}}" id="Unit_{{id}}" /> 5526 } 5527 5528 @helper RenderGridViewItemImageContainer(BlocksPage page) 5529 { 5530 List<Block> subBlocks = page.GetBlockListById("GridViewItemImageContainer"); 5531 5532 <text> 5533 {{#if eventProduct}} 5534 {{#if eventPromotionText}} 5535 <div class="top-label"> 5536 <div class="top-label__label"> 5537 {{eventPromotionText}} 5538 </div> 5539 </div> 5540 {{/if}} 5541 {{else if isPrimeur}} 5542 <div class="top-label"> 5543 <div class="top-label__label"> 5544 {{isPrimeurText}} 5545 </div> 5546 </div> 5547 {{else}} 5548 {{#if promotionText}} 5549 <div class="top-label"> 5550 <div class="top-label__label"> 5551 {{promotionText}} 5552 </div> 5553 </div> 5554 {{/if}} 5555 {{/if}} 5556 </text> 5557 5558 <div class="product-list__grid-item__image dw-mod {{noImage}}"> 5559 @RenderBlockList(subBlocks) 5560 </div> 5561 } 5562 5563 @helper RenderGridViewItemImage() 5564 { 5565 var imagePrefix = "/Admin/Public/GetImage.ashx?width=300&amp;height=300&amp;crop=5&amp;Compression=75&amp;FillCanvas=true&amp;DoNotUpscale=true&amp;image="; 5566 5567 // CDN 5568 var cdnUrl = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetString("CDNUrl"); 5569 bool cdnActivate = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetBoolean("CDNActivate"); 5570 if (!string.IsNullOrWhiteSpace(cdnUrl) && cdnActivate) 5571 { 5572 imagePrefix = cdnUrl + imagePrefix; 5573 } 5574 5575 <a href="{{link}}" 5576 onclick="Scroll.SavePosition(event); {{#if googleImpression}}googleEnchantImpressionClick({{googleImpression}}, event){{/if}}" 5577 title="{{{name}}}" 5578 class="u-block u-position-relative image-hover__wrapper dw-mod"> 5579 <img class="grid__cell-img grid__cell-img--centered u-padding b-lazy u-full-height" src="/Files/Images/placeholder.gif" 5580 data-src="@imagePrefix{{image}}" alt="{{name}}" /> 5581 </a> 5582 } 5583 5584 @helper RenderGridViewItemStickers() 5585 { 5586 <text> 5587 {{#StickersContainers}} 5588 {{>StickersContainer}} 5589 {{/StickersContainers}} 5590 </text> 5591 } 5592 5593 @helper RenderGridViewItemFavorites() 5594 { 5595 <div class="favorites favorites--for-grid-view u-pull--right {{favoriteProductFromImport}} dw-mod" {{favoriteProductFromImport}}> 5596 {{#Favorite}} 5597 {{>FavoriteTemplate}} 5598 {{/Favorite}} 5599 </div> 5600 } 5601 5602 @helper RenderGridViewItemInfoContainer(BlocksPage page) 5603 { 5604 List<Block> subBlocks = page.GetBlockListById("GridViewItemInfoContainer"); 5605 5606 <div class="grid__cell product-list__grid-item__price-info dw-mod"> 5607 @RenderBlockList(subBlocks) 5608 </div> 5609 } 5610 5611 @helper RenderGridViewItemTitle() 5612 { 5613 <a href="{{link}}" class="u-color-inherit" onclick="{{#if googleImpression}}googleEnchantImpressionClick({{googleImpression}}, event){{/if}}" title="{{name}}{{#if variantName}}, {{variantName}}{{/if}}"> 5614 <h6 class="u-condensed-text u-bold">{{{name}}}{{#if variantName}}, {{variantName}}{{/if}}</h6> 5615 </a> 5616 } 5617 5618 @helper RenderGridViewItemNumber() 5619 { 5620 <div class="item-number dw-mod">{{number}}</div> 5621 } 5622 5623 @helper RenderGridViewItemPrice(Dynamicweb.Frontend.ItemViewModel gridViewSettings) 5624 { 5625 int columnsCount = gridViewSettings.GetList("Columns") != null ? Converter.ToInt32(gridViewSettings.GetList("Columns").SelectedValue) : 4; 5626 bool pointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly"); 5627 bool showCartButton = Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetBoolean("ShowAddToCartButton"); 5628 bool showVATPrice = Pageview.AreaSettings.GetItem("ProductList").GetBoolean("ShowBothPricesWithWithoutVAT"); 5629 bool isPricesWithVATEnabled = Converter.ToBoolean(Pageview.Area.EcomPricesWithVat); 5630 5631 if (pointShopOnly) 5632 { 5633 <text> 5634 {{#if havePointPrice}} 5635 <div class="price price--product-list dw-mod">{{points}} @Translate("points")</div> 5636 @if (showCartButton) 5637 { 5638 <text> 5639 {{#unless canBePurchasedWithPoints}} 5640 <small class="help-text u-no-margin">@Translate("Not enough points to buy this")</small> 5641 {{/unless}} 5642 </text> 5643 } 5644 {{else}} 5645 @Translate("Not available") 5646 {{/if}} 5647 </text> 5648 5649 } 5650 else 5651 { 5652 <div class="price price--product-list dw-mod">{{price}}</div> 5653 <div class="before-price {{onSale}} dw-mod">{{discount}}</div> 5654 if (showVATPrice) 5655 { 5656 <div class="vat-price vat-price--product-list u-margin-top dw-mod"> 5657 @if (columnsCount <= 4) 5658 { 5659 if (isPricesWithVATEnabled) 5660 { 5661 <span>@Translate("excl. VAT")</span><span> ({{priceWithoutVAT}})</span> 5662 } 5663 else 5664 { 5665 <span>@Translate("incl. VAT")</span><span> ({{priceWithVAT}})</span> 5666 } 5667 } 5668 else 5669 { 5670 if (isPricesWithVATEnabled) 5671 { 5672 <div>@Translate("excl. VAT")</div><div>({{priceWithoutVAT}})</div> 5673 } 5674 else 5675 { 5676 <div>@Translate("incl. VAT")</div><div>({{priceWithVAT}})</div> 5677 } 5678 } 5679 </div> 5680 } 5681 <text> 5682 {{#if priceRRP}} 5683 <div><small>@Translate("RRP") {{priceRRP}}</small></div> 5684 {{/if}} 5685 </text> 5686 } 5687 } 5688 5689 @helper RenderGridViewItemFooter(BlocksPage page, Dynamicweb.Frontend.ItemViewModel gridViewSettings) 5690 { 5691 List<Block> subBlocks = page.GetBlockListById("GridViewItemFooter"); 5692 bool showStaticVariants = gridViewSettings.GetBoolean("ShowStaticVariants"); 5693 string footerClasses = showStaticVariants ? "u-min-h120px" : ""; 5694 5695 <div class="product-list__grid-item__footer @footerClasses dw-mod u-padding-1px"> 5696 @RenderBlockList(subBlocks) 5697 </div> 5698 } 5699 5700 @helper RenderGridViewItemViewButton(Dynamicweb.Frontend.ItemViewModel gridViewSettings) 5701 { 5702 string viewMoreText = gridViewSettings.GetString("ViewMoreText"); 5703 viewMoreText = !string.IsNullOrEmpty(viewMoreText) ? viewMoreText : "View"; 5704 5705 @Render(new Link 5706 { 5707 Href = "{{link}}", 5708 Id = "CartButton_{{id}}", 5709 Title = Translate(viewMoreText), 5710 OnClick = "{{#if googleImpression}}googleEnchantImpressionClick({{googleImpression}}, event){{/if}}", 5711 ButtonLayout = ButtonLayout.Secondary, 5712 CssClass = "u-no-margin" 5713 }); 5714 } 5715 5716 @helper RenderGridViewItemPricesAndAddToCart(Dynamicweb.Frontend.ItemViewModel gridViewSettings, int customerRatingHeartsPadding = 3, bool hideAddToCart = false) 5717 { 5718 5719 int columnsCount = gridViewSettings.GetList("Columns") != null ? Converter.ToInt32(gridViewSettings.GetList("Columns").SelectedValue) : 4; 5720 bool pointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly"); 5721 bool showCartButton = Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetBoolean("ShowAddToCartButton"); 5722 bool showVATPrice = Pageview.AreaSettings.GetItem("ProductList").GetBoolean("ShowBothPricesWithWithoutVAT"); 5723 bool isPricesWithVATEnabled = Converter.ToBoolean(Pageview.Area.EcomPricesWithVat); 5724 string addToCartSectionCol = hideAddToCart ? "d-none" : "grid__col-6"; 5725 string pricesSectionCol = hideAddToCart ? "grid__col-12" : "grid__col-6"; 5726 5727 <div class="grid"> 5728 <div class="grid__col-12 {{#if eventProduct}}event-{{/if}}title-container " style="height: 85px;"> 5729 {{#unless eventProduct}} 5730 <span class="area u-ta-center">{{producerName}}</span> 5731 {{/unless}} 5732 <a href="{{link}}" class="u-color-inherit" onclick="Scroll.SavePosition(event); {{#if googleImpression}}googleEnchantImpressionClick({{googleImpression}}, event){{/if}}" title="{{name}}"> 5733 <h6 class="u-bold title js-title u-ta-center">{{name}}</h6> 5734 </a> 5735 {{#if eventProduct}} 5736 <p class="event-place"> 5737 {{eventRestaurantName}}, {{eventAddressShort}} 5738 <span class="event-time">{{eventDate}}, {{eventTime}}</span> 5739 </p> 5740 {{/if}} 5741 </div> 5742 </div> 5743 <text> 5744 {{#unless eventProduct}} 5745 <div class="grid"> 5746 <div class="grid__col-12"> 5747 <div class="tags"> 5748 {{#if type}} 5749 <span class="tags__tag">{{type}}</span> 5750 {{/if}} 5751 {{#if area}} 5752 <span class="tags__tag">{{area}}</span> 5753 {{/if}} 5754 {{#if country}} 5755 <span class="tags__tag">{{country}}</span> 5756 {{/if}} 5757 </div> 5758 </div> 5759 </div> 5760 {{/unless}} 5761 </text> 5762 <div class="grid"> 5763 <div class="grid__col-12"> 5764 <div class="customer-ratings-container {{showRating}}"> 5765 <div class="hearts" data-average-rating-percentage="{{ratingPercentage}}" data-heart-padding="@customerRatingHeartsPadding"> 5766 <div class="hearts-outer"> 5767 <img src="/Files/Templates/Designs/Rapido/Images/VectorItemTypes/rating-full-grey-heart.svg" class="full-heart" /> 5768 <img src="/Files/Templates/Designs/Rapido/Images/VectorItemTypes/rating-full-grey-heart.svg" class="full-heart" /> 5769 <img src="/Files/Templates/Designs/Rapido/Images/VectorItemTypes/rating-full-grey-heart.svg" class="full-heart" /> 5770 <img src="/Files/Templates/Designs/Rapido/Images/VectorItemTypes/rating-full-grey-heart.svg" class="full-heart" /> 5771 <img src="/Files/Templates/Designs/Rapido/Images/VectorItemTypes/rating-full-grey-heart.svg" class="full-heart" /> 5772 <div class="hearts-inner"> 5773 <img src="/Files/Templates/Designs/Rapido/Images/VectorItemTypes/rating-full-red-heart.svg" class="full-heart" /> 5774 <img src="/Files/Templates/Designs/Rapido/Images/VectorItemTypes/rating-full-red-heart.svg" class="full-heart" /> 5775 <img src="/Files/Templates/Designs/Rapido/Images/VectorItemTypes/rating-full-red-heart.svg" class="full-heart" /> 5776 <img src="/Files/Templates/Designs/Rapido/Images/VectorItemTypes/rating-full-red-heart.svg" class="full-heart" /> 5777 <img src="/Files/Templates/Designs/Rapido/Images/VectorItemTypes/rating-full-red-heart.svg" class="full-heart" /> 5778 </div> 5779 </div> 5780 </div> 5781 <span class="rating">({{rating}})</span> 5782 </div> 5783 </div> 5784 </div> 5785 5786 <div class="grid"> 5787 <div class="grid__col-12"> 5788 <p class="short-description">{{description}}</p> 5789 </div> 5790 </div> 5791 5792 <div class="grid"> 5793 <div class="@pricesSectionCol"> 5794 <div class="prices"> 5795 {{#unless eventProduct}} 5796 {{#if savings}} 5797 <div class="savings">@Translate("Smartpage:ProductList.Product.Save", "Spar") {{savings}} @Translate("Smartpage:ProductList.Product.PerUnit", "PR. STK.")</div> 5798 {{/if}} 5799 {{/unless}} 5800 <div class="price price--product-list dw-mod">{{price}}</div> 5801 <div class="quantity-price">{{#if eventProduct}} @Translate("Smartpage:ProductList.Product.Pr.", "Pr.") @Translate("Smartpage:ProductList.Product.Ticket", "billet") {{else}}@Translate("Smartpage:ProductList.Product.Pr.", "Pr.") {{unitShortDescription}} v/{{kolli}} @Translate("Smartpage:ProductList.Product.Unit.Stk", "stk.") {{#if bottleSizeCl}}({{bottleSizeCl}} @Translate("Smartpage:ProductList.Product.Unit.Cl", "cl.")){{/if}}{{/if}}</div> 5802 </div> 5803 </div> 5804 {{#if availableForPurchase}} 5805 <div class="@addToCartSectionCol add-to-cart"> 5806 <div class="grid"> 5807 {{#unless disabledBuyButton}} 5808 <div class="grid__col-5 u-no-padding"> 5809 <input id="Quantity{{id}}" name="Quantity{{id}}" min="1" max="{{stockLevel}}" value="{{kolli}}" type="number" class="quantity dw-mod js-stockcheck js-change-quantity"> 5810 </div> 5811 {{/unless}} 5812 {{#if disabledBuyButton}} 5813 <div class="grid__col-12 u-no-padding"> 5814 <button class="btn btn--add-to-cart {{disabledBuyButton}}" title="@Translate("Smartpage:Product.Buy.OutOfStock", "Udsolgt")" onclick="Cart.AddToCart(event, { id: '{{productId}}', variantId: '{{variantid}}', unitId: '{{unitId}}', productInfo: {{productInfo}}, quantity: parseInt(document.getElementById('Quantity{{id}}').value), SpPrimeur: '{{isPrimeur}}'}); {{facebookPixelAction}}" type="button"> 5815 <span>@Translate("Smartpage:Product.Buy.OutOfStock", "Udsolgt")</span> 5816 </button> 5817 </div> 5818 {{/if}} 5819 {{#unless disabledBuyButton}} 5820 <div class="grid__col-7 u-no-padding"> 5821 <button class="btn btn--add-to-cart {{disabledBuyButton}}" title="@Translate("Smartpage:Product.Buy", "Køb")" onclick="Cart.AddToCart(event, { id: '{{productId}}', variantId: '{{variantid}}', unitId: '{{unitId}}', productInfo: {{productInfo}}, quantity: parseInt(document.getElementById('Quantity{{id}}').value), SpPrimeur: '{{isPrimeur}}'}); {{facebookPixelAction}}" type="button" data-product-id="{{productId}}" data-one-unit-price="{{oneUnitPrice}}" data-volume-unit-price="{{volumeUnitPrice}}" data-volume-unit-threshold="{{kolli}}" data-currency-code="{{currency}}"> 5822 <span>@Translate("Smartpage:Product.Buy", "Køb")</span> 5823 </button> 5824 </div> 5825 {{/unless}} 5826 </div> 5827 </div> 5828 {{/if}} 5829 </div> 5830 5831 } 5832 5833 @helper RenderGridViewItemActions(Dynamicweb.Frontend.ItemViewModel gridViewSettings, int customerRatingHeartsPadding = 2, bool hideAddToCart = false) 5834 { 5835 if (Dynamicweb.Rapido.Services.User.IsBuyingAllowed()) 5836 { 5837 @RenderGridViewItemPricesAndAddToCart(gridViewSettings, customerRatingHeartsPadding, hideAddToCart) 5838 } 5839 }*@ 5840 5841 @functions{ 5842 BlocksPage productSliderBlock = new BlocksPage(); 5843 //Dynamicweb.Frontend.ItemViewModel gridViewSettings = null; 5844 } 5845 5846 @{ 5847 gridViewSettings = Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView"); 5848 5849 5850 Block bomItemsBlock = new Block 5851 { 5852 Id = "GridViewItem", 5853 SortId = 10, 5854 Template = RenderGridViewItem(productSliderBlock), 5855 SkipRenderBlocksList = true, 5856 BlocksList = new List<Block> { 5857 new Block 5858 { 5859 Id = "GridViewItemHiddenProperties", 5860 SortId = 10, 5861 Template = RenderGridViewItemHiddenProperties() 5862 }, 5863 new Block 5864 { 5865 Id = "GridViewItemImageContainer", 5866 SortId = 20, 5867 SkipRenderBlocksList = true, 5868 Template = RenderGridViewItemImageContainer(productSliderBlock), 5869 BlocksList = new List<Block> { 5870 new Block 5871 { 5872 Id = "GridViewItemImage", 5873 SortId = 10, 5874 Template = RenderGridViewItemImage() 5875 }, 5876 new Block 5877 { 5878 Id = "GridViewItemStickers", 5879 SortId = 20, 5880 Template = RenderGridViewItemStickers() 5881 } 5882 } 5883 }, 5884 new Block 5885 { 5886 Id = "GridViewItemFooter", 5887 SortId = 40, 5888 SkipRenderBlocksList = true, 5889 Template = RenderGridViewItemFooter(productSliderBlock, gridViewSettings), 5890 BlocksList = new List<Block> { 5891 new Block 5892 { 5893 Id = "GridViewItemActions", 5894 SortId = 10, 5895 Template = RenderGridViewItemActions(gridViewSettings, 2, true) 5896 } 5897 } 5898 } 5899 } 5900 }; 5901 5902 productSliderBlock.Add(bomItemsBlock); 5903 5904 } 5905 5906 @helper RenderBOMItemsSection(string id) 5907 { 5908 var bomItems = Smartpage.PhilipsonWine.BomItems.Repositories.BomItemService.GetBomItems(Model.Id); 5909 5910 List<string> productIds = new List<string>(); 5911 5912 foreach (var product in bomItems) 5913 { 5914 productIds.Add(product.No); 5915 } 5916 5917 string feedUrl = "/Default.aspx?ID=" + GetPageIdByNavigationTag("ProductsPage") + "&Feed=true&IsBomProduct=true&MainProductId=" + string.Join(",", productIds); 5918 5919 string sliderId = "ProductSlider_Slider" + Model.Id; 5920 5921 @RenderBlockList(productSliderBlock.BlocksRoot.BlocksList) 5922 5923 5924 <script id="@("ProductContainer_" + Model.Id)" type="text/x-template"> 5925 {{#each .}} 5926 {{#each ProductsContainer}} 5927 <div id="Product{{id}}" data-template="GridViewItem" data-preloader="overlay" class="product-list__grid-item product-list__bom-item dw-mod product-list-product grid__col-12 grid__col-sm-6"> 5928 {{#each Product}} 5929 {{>GridViewItem}} 5930 {{/each}} 5931 </div> 5932 {{/each}} 5933 {{/each}} 5934 </script> 5935 5936 5937 <script id="ProductPreRenderContainer" type="text/x-template"> 5938 <div class="grid__col-auto"> 5939 <div class="pre-render-element pre-render-element--lg" style="height: 570px;"></div> 5940 </div> 5941 </script> 5942 5943 <script id="StickersContainer" type="text/x-template"> 5944 <div class="stickers-container stickers-container--{{{convertStickerPositionToClassName Position}}} dw-mod"> 5945 {{#Stickers}} 5946 {{>Sticker}} 5947 {{/Stickers}} 5948 </div> 5949 </script> 5950 5951 <script id="Sticker" type="text/x-template"> 5952 @Render(new Sticker { Title = "{{Title}}", CssClass = "{{CssClass}}" }) 5953 </script> 5954 5955 if (bomItems.Any()) 5956 { 5957 <div id="@id" class="paragraph-container paragraph-container--full-width u-white-background bom-items"> 5958 <div class="grid grid--justify-center"> 5959 <div class="grid__col-md-6 grid__col-lg-6 grid__col-xlg-5 grid__col-xxlg-4"> 5960 <h2 class="bom-items__header u-ta-center">@Translate("Smartpage:ProductDetail.BOMItems.Header", "Smagekassen indeholder")</h2> 5961 <div class="js-handlebars-root grid" id="@sliderId" data-template="@("ProductContainer_" + Model.Id)" data-json-feed="@feedUrl" data-preloader="minimal"></div> 5962 </div> 5963 </div> 5964 </div> 5965 } 5966 } 5967 @inherits ViewModelTemplate<ProductViewModel> 5968 @using Dynamicweb.Ecommerce.ProductCatalog 5969 @using Dynamicweb.Rendering 5970 @using Dynamicweb.Core 5971 @using System 5972 @using System.Web 5973 @using Smartpage.PhilipsonWine.Ecommerce.ProductInformation 5974 5975 5976 @helper RenderEventInfoSection(ProductInformation productInfo) 5977 { 5978 var url = productInfo.EventVideo; 5979 var videoId = string.Empty; 5980 5981 if (!string.IsNullOrEmpty(url)) 5982 { 5983 var uri = new Uri(url); 5984 var query = HttpUtility.ParseQueryString(uri.Query); 5985 5986 if (query.AllKeys.Contains("v")) 5987 { 5988 videoId = query["v"]; 5989 } 5990 else 5991 { 5992 videoId = uri.Segments.Last(); 5993 } 5994 5995 } 5996 string producers = productInfo.ProducerId; 5997 string[] producerIds = producers.Split(','); 5998 5999 <div class="paragraph-container paragraph-container--full-width event-section"> 6000 <div class="grid grid--justify-center"> 6001 <div class="grid__col-md-6 grid__col-lg-6 grid__col-xlg-5 grid__col-xxlg-4"> 6002 @if (!string.IsNullOrEmpty(videoId)) // VIDEO 6003 { 6004 <div class="video-wrapper"> 6005 <iframe class="event-video" src="//www.youtube.com/embed/@videoId" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> 6006 </div> 6007 <br /> 6008 } 6009 <div class="grid"> 6010 @if (productInfo != null) 6011 { 6012 <div class="grid__col-md-6 no-padding-left"> 6013 <h2 class="event__header dw-mod">@Translate("Smartpage:ProductPage.Event.Menu", "Menu")</h2> 6014 <div class="js-menu-list menu-list closed"> 6015 @productInfo.EventMenu 6016 </div> 6017 <span class="link-small js-show-menu alternative-link-small" data-open="true" data-show-description="+ @Translate("Smartpage:ProductPage.Event.SeeTheFullMenu", "Se hele menuen")" data-hide-description="- @Translate("Smartpage:ProductPage.Event.HideMenu", "Skjul menuen")">+ @Translate("Smartpage:ProductPage.Event.ShowMenu", "Se hele menuen")</span> 6018 </div> 6019 } 6020 <div class="grid__col-md-6 no-padding-right"> 6021 <h2 class="event__header dw-mod">@Translate("Smartpage:ProductPage.Event.Restaurant", "Restaurant")</h2> 6022 <label class="restaurant-name">@productInfo.EventRestaurantName</label> 6023 <p>@productInfo.EventAddressLong</p> 6024 <a href="//www.google.com/maps/place/@productInfo.EventAddressLong" class="link-maps" target="_blank">@Translate("Smartpage:ProductPage.Event.LookAtMap","Se på kort")</a> 6025 </div> 6026 @if (producerIds != null && producerIds.Length > 0) 6027 { 6028 <div class="grid__col-md-12 u-no-padding-x"> 6029 <h2 class="event__header dw-mod">@Translate("Smartpage:ProductPage.Event.TheProducers", "Producenterne")</h2> 6030 @foreach (var producerId in producerIds) 6031 { 6032 if (!string.IsNullOrEmpty(producerId)) 6033 { 6034 var producerService = new Smartpage.PhilipsonWine.Producer.Repositories.ProducerService(); 6035 var producer = producerService.GetProductProducer(producerId); 6036 6037 <div class="u-margin-bottom producer"> 6038 <label class="producer-name">@producer.ProducerName</label> 6039 <p class="producer-text">@producer.ProducerDescription</p> 6040 <span class="link-small" onclick="window.location = 'Default.aspx?ID=@producer.ProducerLink'">Læs mere</span> 6041 </div> 6042 } 6043 } 6044 </div> 6045 } 6046 </div> 6047 </div> 6048 </div> 6049 </div> 6050 6051 <div class="paragraph-container paragraph-container--full-width event-section-note"> 6052 <div class="grid grid--justify-center"> 6053 <div class="grid__col-md-6 grid__col-lg-6 grid__col-xlg-5 grid__col-xxlg-4"> 6054 <h2 class="event-note__header dw-mod">@Translate("Smartpage:ProductPage.Event.Attention", "Bemærk")</h2> 6055 <p class="u-margin-top u-margin-bottom">@productInfo.EventAttention</p> 6056 </div> 6057 </div> 6058 </div> 6059 } 6060 @inherits ViewModelTemplate<ProductViewModel> 6061 @using Dynamicweb.Ecommerce.ProductCatalog 6062 @using Dynamicweb.Rendering 6063 6064 @helper RenderClerkSection(string id, string clerkTemplate, string containerClass = "") 6065 { 6066 <div id="@id" class="paragraph-container paragraph-container--full-width js-product-slider-container @containerClass" data-swiper-config="clerk-slider-product-page"> 6067 <div class="grid grid--justify-center"> 6068 <div class="grid__col-md-6 grid__col-lg-6 grid__col-xlg-5 grid__col-xxlg-4"> 6069 <h3 class="heading-clerk">@Translate("Smartpage:ClerkRecommendations." + id, id)</h3> 6070 <div class=""> 6071 @{ 6072 string swiperContainerClass = "SliderContainer_" + id; 6073 string swiperPaginationClass = id + "_SwiperPagination"; 6074 string swiperPrevButtonClass = id + "_SwiperButtonPrev"; 6075 string swiperNextButtonClass = id + "_SwiperButtonNext"; 6076 } 6077 <div id="@swiperContainerClass" class="swiper-container product-slider-container @swiperContainerClass"> 6078 <span class="clerk swiper-wrapper" 6079 data-template="@("@" + clerkTemplate)" 6080 data-products="[@Model.Id]"> 6081 </span> 6082 </div> 6083 <div id="@swiperPrevButtonClass" class="swiper-button-prev @swiperPrevButtonClass"></div> 6084 <div id="@swiperNextButtonClass" class="swiper-button-next @swiperNextButtonClass"></div> 6085 <div class="clerk-preloader js-clerk-preloader clerk-preloader--loading"> 6086 <div class="preloader-overlay__icon js-clerk-preloader-icon"></div> 6087 </div> 6088 </div> 6089 </div> 6090 </div> 6091 </div> 6092 } 6093 @inherits ViewModelTemplate<ProductViewModel> 6094 @using Dynamicweb.Ecommerce.ProductCatalog 6095 @using Dynamicweb.Rendering 6096 @using Dynamicweb.Core 6097 @using System 6098 @using System.Web 6099 @using System.Collections.Generic 6100 @using Dynamicweb.Rapido.Blocks 6101 @using Dynamicweb.Rapido.Blocks.Components.General 6102 6103 @functions{ 6104 BlocksPage productVideoPage = BlocksPage.GetBlockPage("Product"); 6105 } 6106 6107 @{ 6108 //var apiProduct = Dynamicweb.Ecommerce.Services.Products.GetProductById(Model.Id, Model.VariantId, true); 6109 string videosLayout = Pageview.AreaSettings.GetItem("ProductPage").GetList("VideosLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("VideosLayout").SelectedValue : "Section"; 6110 videosLayout = videosLayout == "Ribbon" || string.IsNullOrEmpty(videosLayout) ? "Section" : videosLayout; 6111 6112 int videosCount = 0; 6113 6114 foreach (var detailField in Model.AssetCategories) 6115 { 6116 foreach (var asset in detailField.Assets) 6117 { 6118 if (asset.Value.IndexOf("iframe") != -1 && asset.Value.IndexOf("youtube.com/embed") != -1) 6119 { 6120 videosCount++; 6121 } 6122 if (asset.Value.IndexOf("iframe") != -1 && asset.Value.IndexOf("vimeo.com") != -1) 6123 { 6124 videosCount++; 6125 } 6126 } 6127 } 6128 6129 if (videosCount > 0 && videosLayout != "hide") 6130 { 6131 Block detailsVideos = new Block() 6132 { 6133 Name = videosLayout != "MainInformation" ? Translate("Videos") : "", 6134 Id = "Videos", 6135 SortId = 60, 6136 Template = RenderProductVideos(videosCount, videosLayout), 6137 Design = new Design 6138 { 6139 Size = "12", 6140 RenderType = RenderType.Column, 6141 HidePadding = true 6142 } 6143 }; 6144 productVideoPage.Add(videosLayout, detailsVideos); 6145 } 6146 } 6147 6148 @helper RenderProductVideos(int videosCount, string layout) { 6149 //var apiProduct = Dynamicweb.Ecommerce.Services.Products.GetProductById(Model.Id, Model.VariantId, true); 6150 string videoColumn = "12"; 6151 videoColumn = videosCount == 2 ? "6" : videoColumn; 6152 videoColumn = videosCount > 2 ? "4" : videoColumn; 6153 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("VideosLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 6154 ribbonClasses = layout == "Tabs" ? "u-no-padding" : ribbonClasses; 6155 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("VideosLayout").SelectedValue == "Ribbon" ? "center-container--ribbon" : ""; 6156 6157 <div class="product__section @ribbonClasses dw-mod"> 6158 <div class="center-container @ribbonSubClasses dw-mod"> 6159 @if (layout == "Section") { 6160 @Render(new Heading { Title = Translate("Videos"), Level = 2 }) 6161 } 6162 6163 <div class="grid grid--external-bleed-x u-margin-bottom--lg"> 6164 @foreach (var detailField in Model.AssetCategories) 6165 { 6166 foreach (var asset in detailField.Assets) 6167 { 6168 if (asset.Value.IndexOf("iframe") != -1 && asset.Value.IndexOf("youtube.com/embed") != -1 || asset.Value.IndexOf("iframe") != -1 && asset.Value.IndexOf("vimeo.com") != -1) 6169 { 6170 <div class="grid__col-md-@videoColumn grid__col-lg-@videoColumn"> 6171 <div class="video-wrapper"> 6172 @asset.Value 6173 </div> 6174 </div> 6175 } 6176 } 6177 } 6178 </div> 6179 </div> 6180 </div> 6181 } 6182 @inherits ViewModelTemplate<ProductViewModel> 6183 @using Dynamicweb.Ecommerce.ProductCatalog 6184 @using Dynamicweb.Rendering 6185 @using System.Collections.Generic 6186 @using Dynamicweb.Rapido.Blocks.Components.General 6187 @using Dynamicweb.Rapido.Blocks 6188 6189 @using Dynamicweb.Ecommerce.ProductCatalog 6190 @using Dynamicweb.Rendering 6191 @using Dynamicweb.Core 6192 @using System 6193 @using System.Web 6194 @using System.Collections.Generic 6195 @using Dynamicweb.Rapido.Blocks 6196 @using Dynamicweb.Rapido.Blocks.Components 6197 @using Dynamicweb.Rapido.Blocks.Components.General 6198 @using Dynamicweb.Rapido.Services 6199 6200 @helper GridView(Dynamicweb.Frontend.ItemViewModel gridViewSettings) 6201 { 6202 int columnsCount = gridViewSettings.GetList("Columns") != null ? Converter.ToInt32(gridViewSettings.GetList("Columns").SelectedValue) : 3; 6203 string imageZoomOnHover = gridViewSettings.GetBoolean("HoverImageZoom") ? "image-hover--zoom" : ""; 6204 6205 <script id="ProductGridItemContainer" type="text/x-template"> 6206 {{#.}} 6207 <div id="Product{{id}}" data-template="GridViewItem" data-preloader="overlay" class="grid__col-lg-@(12 / columnsCount) grid__col-md-6 grid__col-sm-6 grid__col-xs-6 product-list__grid-item @imageZoomOnHover dw-mod product-list-product"> 6208 {{#Product}} 6209 {{>GridViewItem}} 6210 {{/Product}} 6211 </div> 6212 {{/.}} 6213 </script> 6214 } 6215 6216 @helper RenderGridViewItem(BlocksPage page) 6217 { 6218 List<Block> subBlocks = page.GetBlockListById("GridViewItem"); 6219 6220 <script id="GridViewItem" type="text/x-template"> 6221 {{#.}} 6222 <div class="grid__col--auto js-product-scroll-trigger u-no-padding u-full-height u-grey-border u-white-background u-padding-sides-8px" data-params="{{googleImpression}}"> 6223 {{>RenderRatingsBadges}} 6224 @RenderBlockList(subBlocks) 6225 </div> 6226 {{/.}} 6227 </script> 6228 6229 <script id="RenderRatingsBadges" type="text/x-template"> 6230 <div class="productlist-rating-badges"> 6231 {{#if CustomerRatingActive}} 6232 <div class="rating-badge c100 js-badge" data-percent="{{CustomerRatingInPercent}}"> 6233 <span class="rating-badge--text">@Translate("Smartpage:CustomerRating.Philipson Wine", "Philipson Wine")</span> 6234 <span class="rating-badge--score">{{{CustomerRatingInText}}}</span> 6235 <div class="slice"> 6236 <div class="bar"></div> 6237 <div class="fill"></div> 6238 </div> 6239 </div> 6240 {{/if}} 6241 {{#ExpertRatings}} 6242 {{#if image}} 6243 <div class="expert-rating-image"> 6244 @{ 6245 var imagePrefix = "/Admin/Public/GetImage.ashx?width=46&amp;height=46&amp;crop=5&amp;Compression=75&amp;FillCanvas=true&amp;DoNotUpscale=true&amp;image=/Files/Images/ExpertRatings/{{image}}.png"; 6246 6247 // CDN 6248 var cdnUrl = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetString("CDNUrl"); 6249 bool cdnActivate = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetBoolean("CDNActivate"); 6250 if (!string.IsNullOrWhiteSpace(cdnUrl) && cdnActivate) 6251 { 6252 imagePrefix = cdnUrl + imagePrefix; 6253 } 6254 } 6255 <img class="rating-image" src="@imagePrefix" alt="{{name}}" /> 6256 <span class="rating-image--score">{{{text}}}</span> 6257 </div> 6258 {{else}} 6259 <div class="rating-badge c100 dark js-badge" data-percent="{{percentage}}"> 6260 <span class="rating-badge--text">{{name}}</span> 6261 <span class="rating-badge--score">{{{text}}}</span> 6262 <div class="slice"> 6263 <div class="bar"></div> 6264 <div class="fill"></div> 6265 </div> 6266 </div> 6267 {{/if}} 6268 {{/ExpertRatings}} 6269 </div> 6270 </script> 6271 6272 6273 6274 } 6275 6276 @helper RenderGridViewItemHiddenProperties() 6277 { 6278 <input type="hidden" name="ProductLoopCounter{{id}}" value="{{id}}" /> 6279 <input type="hidden" name="ProductID{{id}}" value="{{productId}}" /> 6280 <input type="hidden" name="VariantID{{id}}" value="{{variantid}}" id="Variant_{{id}}" /> 6281 <input type="hidden" name="UnitID{{id}}" value="{{unitId}}" id="Unit_{{id}}" /> 6282 } 6283 6284 @helper RenderGridViewItemImageContainer(BlocksPage page) 6285 { 6286 List<Block> subBlocks = page.GetBlockListById("GridViewItemImageContainer"); 6287 6288 <text> 6289 {{#if eventProduct}} 6290 {{#if eventPromotionText}} 6291 <div class="top-label"> 6292 <div class="top-label__label"> 6293 {{eventPromotionText}} 6294 </div> 6295 </div> 6296 {{/if}} 6297 {{else if isPrimeur}} 6298 <div class="top-label"> 6299 <div class="top-label__label"> 6300 {{isPrimeurText}} 6301 </div> 6302 </div> 6303 {{else}} 6304 {{#if promotionText}} 6305 <div class="top-label"> 6306 <div class="top-label__label"> 6307 {{promotionText}} 6308 </div> 6309 </div> 6310 {{/if}} 6311 {{/if}} 6312 </text> 6313 6314 <div class="product-list__grid-item__image dw-mod {{noImage}}"> 6315 @RenderBlockList(subBlocks) 6316 </div> 6317 } 6318 6319 @helper RenderGridViewItemImage() 6320 { 6321 var imagePrefix = "/Admin/Public/GetImage.ashx?width=300&amp;height=300&amp;crop=5&amp;Compression=75&amp;FillCanvas=true&amp;DoNotUpscale=true&amp;image="; 6322 6323 // CDN 6324 var cdnUrl = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetString("CDNUrl"); 6325 bool cdnActivate = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetBoolean("CDNActivate"); 6326 if (!string.IsNullOrWhiteSpace(cdnUrl) && cdnActivate) 6327 { 6328 imagePrefix = cdnUrl + imagePrefix; 6329 } 6330 6331 <a href="{{link}}" 6332 onclick="Scroll.SavePosition(event); {{#if googleImpression}}googleEnchantImpressionClick({{googleImpression}}, event){{/if}}" 6333 title="{{{name}}}" 6334 class="u-block u-position-relative image-hover__wrapper dw-mod"> 6335 <img class="grid__cell-img grid__cell-img--centered u-padding b-lazy u-full-height" src="/Files/Images/placeholder.gif" 6336 data-src="@imagePrefix{{image}}" alt="{{name}}" /> 6337 </a> 6338 } 6339 6340 @helper RenderGridViewItemStickers() 6341 { 6342 <text> 6343 {{#StickersContainers}} 6344 {{>StickersContainer}} 6345 {{/StickersContainers}} 6346 </text> 6347 } 6348 6349 @helper RenderGridViewItemFavorites() 6350 { 6351 <div class="favorites favorites--for-grid-view u-pull--right {{favoriteProductFromImport}} dw-mod" {{favoriteProductFromImport}}> 6352 {{#Favorite}} 6353 {{>FavoriteTemplate}} 6354 {{/Favorite}} 6355 </div> 6356 } 6357 6358 @helper RenderGridViewItemInfoContainer(BlocksPage page) 6359 { 6360 List<Block> subBlocks = page.GetBlockListById("GridViewItemInfoContainer"); 6361 6362 <div class="grid__cell product-list__grid-item__price-info dw-mod"> 6363 @RenderBlockList(subBlocks) 6364 </div> 6365 } 6366 6367 @helper RenderGridViewItemTitle() 6368 { 6369 <a href="{{link}}" class="u-color-inherit" onclick="{{#if googleImpression}}googleEnchantImpressionClick({{googleImpression}}, event){{/if}}" title="{{name}}{{#if variantName}}, {{variantName}}{{/if}}"> 6370 <h6 class="u-condensed-text u-bold">{{{name}}}{{#if variantName}}, {{variantName}}{{/if}}</h6> 6371 </a> 6372 } 6373 6374 @helper RenderGridViewItemNumber() 6375 { 6376 <div class="item-number dw-mod">{{number}}</div> 6377 } 6378 6379 @helper RenderGridViewItemPrice(Dynamicweb.Frontend.ItemViewModel gridViewSettings) 6380 { 6381 int columnsCount = gridViewSettings.GetList("Columns") != null ? Converter.ToInt32(gridViewSettings.GetList("Columns").SelectedValue) : 4; 6382 bool pointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly"); 6383 bool showCartButton = Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetBoolean("ShowAddToCartButton"); 6384 bool showVATPrice = Pageview.AreaSettings.GetItem("ProductList").GetBoolean("ShowBothPricesWithWithoutVAT"); 6385 bool isPricesWithVATEnabled = Converter.ToBoolean(Pageview.Area.EcomPricesWithVat); 6386 6387 if (pointShopOnly) 6388 { 6389 <text> 6390 {{#if havePointPrice}} 6391 <div class="price price--product-list dw-mod">{{points}} @Translate("points")</div> 6392 @if (showCartButton) 6393 { 6394 <text> 6395 {{#unless canBePurchasedWithPoints}} 6396 <small class="help-text u-no-margin">@Translate("Not enough points to buy this")</small> 6397 {{/unless}} 6398 </text> 6399 } 6400 {{else}} 6401 @Translate("Not available") 6402 {{/if}} 6403 </text> 6404 6405 } 6406 else 6407 { 6408 <div class="price price--product-list dw-mod">{{price}}</div> 6409 <div class="before-price {{onSale}} dw-mod">{{discount}}</div> 6410 if (showVATPrice) 6411 { 6412 <div class="vat-price vat-price--product-list u-margin-top dw-mod"> 6413 @if (columnsCount <= 4) 6414 { 6415 if (isPricesWithVATEnabled) 6416 { 6417 <span>@Translate("excl. VAT")</span><span> ({{priceWithoutVAT}})</span> 6418 } 6419 else 6420 { 6421 <span>@Translate("incl. VAT")</span><span> ({{priceWithVAT}})</span> 6422 } 6423 } 6424 else 6425 { 6426 if (isPricesWithVATEnabled) 6427 { 6428 <div>@Translate("excl. VAT")</div><div>({{priceWithoutVAT}})</div> 6429 } 6430 else 6431 { 6432 <div>@Translate("incl. VAT")</div><div>({{priceWithVAT}})</div> 6433 } 6434 } 6435 </div> 6436 } 6437 <text> 6438 {{#if priceRRP}} 6439 <div><small>@Translate("RRP") {{priceRRP}}</small></div> 6440 {{/if}} 6441 </text> 6442 } 6443 } 6444 6445 @helper RenderGridViewItemFooter(BlocksPage page, Dynamicweb.Frontend.ItemViewModel gridViewSettings) 6446 { 6447 List<Block> subBlocks = page.GetBlockListById("GridViewItemFooter"); 6448 bool showStaticVariants = gridViewSettings.GetBoolean("ShowStaticVariants"); 6449 string footerClasses = showStaticVariants ? "u-min-h120px" : ""; 6450 6451 <div class="product-list__grid-item__footer @footerClasses dw-mod u-padding-1px"> 6452 @RenderBlockList(subBlocks) 6453 </div> 6454 } 6455 6456 @helper RenderGridViewItemViewButton(Dynamicweb.Frontend.ItemViewModel gridViewSettings) 6457 { 6458 string viewMoreText = gridViewSettings.GetString("ViewMoreText"); 6459 viewMoreText = !string.IsNullOrEmpty(viewMoreText) ? viewMoreText : "View"; 6460 6461 @Render(new Link 6462 { 6463 Href = "{{link}}", 6464 Id = "CartButton_{{id}}", 6465 Title = Translate(viewMoreText), 6466 OnClick = "{{#if googleImpression}}googleEnchantImpressionClick({{googleImpression}}, event){{/if}}", 6467 ButtonLayout = ButtonLayout.Secondary, 6468 CssClass = "u-no-margin" 6469 }); 6470 } 6471 6472 @helper RenderGridViewItemPricesAndAddToCart(Dynamicweb.Frontend.ItemViewModel gridViewSettings, int customerRatingHeartsPadding = 3, bool hideAddToCart = false) 6473 { 6474 6475 int columnsCount = gridViewSettings.GetList("Columns") != null ? Converter.ToInt32(gridViewSettings.GetList("Columns").SelectedValue) : 4; 6476 bool pointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly"); 6477 bool showCartButton = Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetBoolean("ShowAddToCartButton"); 6478 bool showVATPrice = Pageview.AreaSettings.GetItem("ProductList").GetBoolean("ShowBothPricesWithWithoutVAT"); 6479 bool isPricesWithVATEnabled = Converter.ToBoolean(Pageview.Area.EcomPricesWithVat); 6480 string addToCartSectionCol = hideAddToCart ? "d-none" : "grid__col-6"; 6481 string pricesSectionCol = hideAddToCart ? "grid__col-12" : "grid__col-6"; 6482 6483 <div class="grid"> 6484 <div class="grid__col-12 {{#if eventProduct}}event-{{/if}}title-container " style="height: 85px;"> 6485 {{#unless eventProduct}} 6486 <span class="area u-ta-center">{{producerName}}</span> 6487 {{/unless}} 6488 <a href="{{link}}" class="u-color-inherit" onclick="Scroll.SavePosition(event); {{#if googleImpression}}googleEnchantImpressionClick({{googleImpression}}, event){{/if}}" title="{{name}}"> 6489 <h6 class="u-bold title js-title u-ta-center">{{name}}</h6> 6490 </a> 6491 {{#if eventProduct}} 6492 <p class="event-place"> 6493 {{eventRestaurantName}}, {{eventAddressShort}} 6494 <span class="event-time">{{eventDate}}, {{eventTime}}</span> 6495 </p> 6496 {{/if}} 6497 </div> 6498 </div> 6499 <text> 6500 {{#unless eventProduct}} 6501 <div class="grid"> 6502 <div class="grid__col-12"> 6503 <div class="tags"> 6504 {{#if type}} 6505 <span class="tags__tag">{{type}}</span> 6506 {{/if}} 6507 {{#if area}} 6508 <span class="tags__tag">{{area}}</span> 6509 {{/if}} 6510 {{#if country}} 6511 <span class="tags__tag">{{country}}</span> 6512 {{/if}} 6513 </div> 6514 </div> 6515 </div> 6516 {{/unless}} 6517 </text> 6518 <div class="grid"> 6519 <div class="grid__col-12"> 6520 <div class="customer-ratings-container {{showRating}}"> 6521 <div class="hearts" data-average-rating-percentage="{{ratingPercentage}}" data-heart-padding="@customerRatingHeartsPadding"> 6522 <div class="hearts-outer"> 6523 <img src="/Files/Templates/Designs/Rapido/Images/VectorItemTypes/rating-full-grey-heart.svg" class="full-heart" /> 6524 <img src="/Files/Templates/Designs/Rapido/Images/VectorItemTypes/rating-full-grey-heart.svg" class="full-heart" /> 6525 <img src="/Files/Templates/Designs/Rapido/Images/VectorItemTypes/rating-full-grey-heart.svg" class="full-heart" /> 6526 <img src="/Files/Templates/Designs/Rapido/Images/VectorItemTypes/rating-full-grey-heart.svg" class="full-heart" /> 6527 <img src="/Files/Templates/Designs/Rapido/Images/VectorItemTypes/rating-full-grey-heart.svg" class="full-heart" /> 6528 <div class="hearts-inner"> 6529 <img src="/Files/Templates/Designs/Rapido/Images/VectorItemTypes/rating-full-red-heart.svg" class="full-heart" /> 6530 <img src="/Files/Templates/Designs/Rapido/Images/VectorItemTypes/rating-full-red-heart.svg" class="full-heart" /> 6531 <img src="/Files/Templates/Designs/Rapido/Images/VectorItemTypes/rating-full-red-heart.svg" class="full-heart" /> 6532 <img src="/Files/Templates/Designs/Rapido/Images/VectorItemTypes/rating-full-red-heart.svg" class="full-heart" /> 6533 <img src="/Files/Templates/Designs/Rapido/Images/VectorItemTypes/rating-full-red-heart.svg" class="full-heart" /> 6534 </div> 6535 </div> 6536 </div> 6537 <span class="rating">({{rating}})</span> 6538 </div> 6539 </div> 6540 </div> 6541 6542 <div class="grid"> 6543 <div class="grid__col-12"> 6544 <p class="short-description">{{description}}</p> 6545 </div> 6546 </div> 6547 6548 <div class="grid"> 6549 <div class="@pricesSectionCol"> 6550 <div class="prices"> 6551 {{#unless eventProduct}} 6552 {{#if savings}} 6553 <div class="savings">@Translate("Smartpage:ProductList.Product.Save", "Spar") {{savings}} @Translate("Smartpage:ProductList.Product.PerUnit", "PR. STK.")</div> 6554 {{/if}} 6555 {{/unless}} 6556 <div class="price price--product-list dw-mod">{{price}}</div> 6557 <div class="quantity-price">{{#if eventProduct}} @Translate("Smartpage:ProductList.Product.Pr.", "Pr.") @Translate("Smartpage:ProductList.Product.Ticket", "billet") {{else}}@Translate("Smartpage:ProductList.Product.Pr.", "Pr.") {{unitShortDescription}} v/{{kolli}} @Translate("Smartpage:ProductList.Product.Unit.Stk", "stk.") {{#if bottleSizeCl}}({{bottleSizeCl}} @Translate("Smartpage:ProductList.Product.Unit.Cl", "cl.")){{/if}}{{/if}}</div> 6558 </div> 6559 </div> 6560 {{#if availableForPurchase}} 6561 <div class="@addToCartSectionCol add-to-cart"> 6562 <div class="grid"> 6563 {{#unless disabledBuyButton}} 6564 <div class="grid__col-5 u-no-padding"> 6565 <input id="Quantity{{id}}" name="Quantity{{id}}" min="1" max="{{stockLevel}}" value="{{kolli}}" type="number" class="quantity dw-mod js-stockcheck js-change-quantity"> 6566 </div> 6567 {{/unless}} 6568 {{#if disabledBuyButton}} 6569 <div class="grid__col-12 u-no-padding"> 6570 <button class="btn btn--add-to-cart {{disabledBuyButton}}" title="@Translate("Smartpage:Product.Buy.OutOfStock", "Udsolgt")" onclick="Cart.AddToCart(event, { id: '{{productId}}', variantId: '{{variantid}}', unitId: '{{unitId}}', productInfo: {{productInfo}}, quantity: parseInt(document.getElementById('Quantity{{id}}').value), SpPrimeur: '{{isPrimeur}}'}); {{facebookPixelAction}}" type="button"> 6571 <span>@Translate("Smartpage:Product.Buy.OutOfStock", "Udsolgt")</span> 6572 </button> 6573 </div> 6574 {{/if}} 6575 {{#unless disabledBuyButton}} 6576 <div class="grid__col-7 u-no-padding"> 6577 <button class="btn btn--add-to-cart {{disabledBuyButton}}" title="@Translate("Smartpage:Product.Buy", "Køb")" onclick="Cart.AddToCart(event, { id: '{{productId}}', variantId: '{{variantid}}', unitId: '{{unitId}}', productInfo: {{productInfo}}, quantity: parseInt(document.getElementById('Quantity{{id}}').value), SpPrimeur: '{{isPrimeur}}'}); {{facebookPixelAction}}" type="button" data-product-id="{{productId}}" data-one-unit-price="{{oneUnitPrice}}" data-volume-unit-price="{{volumeUnitPrice}}" data-volume-unit-threshold="{{kolli}}" data-currency-code="{{currency}}"> 6578 <span>@Translate("Smartpage:Product.Buy", "Køb")</span> 6579 </button> 6580 </div> 6581 {{/unless}} 6582 </div> 6583 </div> 6584 {{/if}} 6585 </div> 6586 6587 } 6588 6589 @helper RenderGridViewItemActions(Dynamicweb.Frontend.ItemViewModel gridViewSettings, int customerRatingHeartsPadding = 2, bool hideAddToCart = false) 6590 { 6591 if (Dynamicweb.Rapido.Services.User.IsBuyingAllowed()) 6592 { 6593 @RenderGridViewItemPricesAndAddToCart(gridViewSettings, customerRatingHeartsPadding, hideAddToCart) 6594 } 6595 } 6596 6597 @functions { 6598 BlocksPage productRelatedPage = BlocksPage.GetBlockPage("Product"); 6599 Dynamicweb.Frontend.ItemViewModel gridViewSettings = null; 6600 } 6601 6602 @{ 6603 string pageId = Dynamicweb.Context.Current.Request["ID"]; 6604 string relatedProductsLayout = Pageview.AreaSettings.GetItem("ProductPage").GetList("RelatedProductsLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("RelatedProductsLayout").SelectedValue : "Section"; 6605 relatedProductsLayout = relatedProductsLayout == "Ribbon" || string.IsNullOrEmpty(relatedProductsLayout) ? "Section" : relatedProductsLayout; 6606 6607 gridViewSettings = Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView"); 6608 6609 int relatedProductsPageSize = 2; 6610 6611 if (Pageview.Device.ToString() == "Mobile") 6612 { 6613 relatedProductsPageSize = 1; 6614 } 6615 6616 if (Pageview.Device.ToString() == "Tablet") 6617 { 6618 relatedProductsPageSize = 2; 6619 } 6620 6621 int relatedProductsColumnWidth = 12 / relatedProductsPageSize; 6622 6623 if (relatedProductsLayout != "hide") 6624 { 6625 var i = 0; 6626 6627 var relatedGroups = Dynamicweb.Ecommerce.Services.ProductRelated.GetRelations(Model.Id).GroupBy(p => p.RelatedGroupId); 6628 foreach (var relatedGroup in relatedGroups) 6629 { 6630 string baseFeedPageUrl = "/Default.aspx?ID=" + pageId + "&feed=true&PageSize=" + relatedProductsPageSize + "&ProdID=" + Model.Id; 6631 string relatedGroupName = Dynamicweb.Ecommerce.Services.ProductRelatedGroups.GetProductRelatedGroup(relatedGroup.Key, Dynamicweb.Ecommerce.Common.Context.LanguageID) != null ? Dynamicweb.Ecommerce.Services.ProductRelatedGroups.GetProductRelatedGroup(relatedGroup.Key, "LANG2").Name : ""; 6632 string relatedFeed = baseFeedPageUrl + "&" + relatedGroupName.Replace(" ", "") + "=" + Model.Id + "&GroupName=" + relatedGroupName; 6633 6634 i++; 6635 6636 Block gridViewItem = new Block 6637 { 6638 Id = "GridViewItem", 6639 SortId = 10, 6640 Template = RenderGridViewItem(productRelatedPage), 6641 SkipRenderBlocksList = true, 6642 BlocksList = new List<Block> { 6643 new Block 6644 { 6645 Id = "GridViewItemHiddenProperties", 6646 SortId = 10, 6647 Template = RenderGridViewItemHiddenProperties() 6648 }, 6649 new Block 6650 { 6651 Id = "GridViewItemImageContainer", 6652 SortId = 20, 6653 SkipRenderBlocksList = true, 6654 Template = RenderGridViewItemImageContainer(productRelatedPage), 6655 BlocksList = new List<Block> { 6656 new Block 6657 { 6658 Id = "GridViewItemImage", 6659 SortId = 10, 6660 Template = RenderGridViewItemImage() 6661 }, 6662 new Block 6663 { 6664 Id = "GridViewItemStickers", 6665 SortId = 20, 6666 Template = RenderGridViewItemStickers() 6667 } 6668 } 6669 }, 6670 new Block 6671 { 6672 Id = "GridViewItemFooter", 6673 SortId = 40, 6674 SkipRenderBlocksList = true, 6675 Template = RenderGridViewItemFooter(productRelatedPage, gridViewSettings), 6676 BlocksList = new List<Block> { 6677 new Block 6678 { 6679 Id = "GridViewItemActions", 6680 SortId = 10, 6681 Template = RenderGridViewItemActions(gridViewSettings, 0) 6682 } 6683 } 6684 } 6685 } 6686 }; 6687 6688 @*if (eventProduct) 6689 { 6690 productRelatedPage.Add(relatedProductsLayout, gridViewItem); 6691 } 6692 6693 Block detailsRelated = new Block() 6694 { 6695 Name = relatedGroupName, 6696 Id = relatedGroupName, 6697 SortId = 70 + i, 6698 Template = RenderRelatedProducts(relatedGroupName, relatedGroupName, relatedFeed, relatedProductsLayout), 6699 Design = new Design 6700 { 6701 Size = "12", 6702 RenderType = RenderType.Column, 6703 HidePadding = true 6704 } 6705 }; 6706 if (eventProduct) 6707 { 6708 productRelatedPage.Add(relatedProductsLayout, detailsRelated); 6709 }*@ 6710 } 6711 } 6712 } 6713 6714 @helper RenderRelatedProducts(string name, string groupId, string relatedFeedUrl, string layout) 6715 { 6716 <div class="paragraph-container paragraph-container--full-width product-slider"> 6717 <div class="grid grid--justify-center"> 6718 <div class="grid__col-md-6 grid__col-lg-6 grid__col-xlg-5 grid__col-xxlg-4"> 6719 <div class="grid__col-12"> 6720 @if (layout == "Section") { 6721 @Render(new Heading { Title = Translate("Smartpage:ProductDetail.RelatedProducts.Header." + name, name), Level = 2, CssClass = "product-slider__header" }) 6722 } 6723 </div> 6724 <div class="js-handlebars-root" id="ProductList_@groupId" data-template="ProductContainer" data-pre-render-template="ProductPreRenderContainer" data-json-feed="@relatedFeedUrl" data-preloader="overlay"></div> 6725 </div> 6726 </div> 6727 </div> 6728 } 6729 6730 @* Script templates for related products *@ 6731 <script id="ProductPreRenderContainer" type="text/x-template"> 6732 <div class="u-h600px u-full-width"> 6733 <div class="grid"> 6734 <div class="grid__col-12"> 6735 <div class="pre-render-element pre-render-element--md"></div> 6736 </div> 6737 </div> 6738 </div> 6739 </script> 6740 6741 <script id="ProductContainer" type="text/x-template"> 6742 {{#.}} 6743 <div class="product-slider__prev-btn"> 6744 @{ 6745 Button prevButton = new Button { Icon = new Icon { Prefix = "fas", Name = "fa-chevron-left fa-2x", LabelPosition = IconLabelPosition.After }, ButtonLayout = ButtonLayout.Clean, CssClass = "btn--condensed {{prevdisabled}} u-position-relative", OnClick = "HandlebarsBolt.UpdateContent('ProductList_{{groupName}}', '{{prevPage}}')" }; 6746 prevButton.ExtraAttributes.Add("", "{{prevdisabled}}"); 6747 } 6748 @Render(prevButton) 6749 </div> 6750 <div class="grid"> 6751 {{#ProductsContainer}} 6752 <div id="Product{{id}}" data-template="GridViewItem" data-preloader="overlay" class="grid__col-lg-6 grid__col-md-12 grid__col-sm-6 grid__col-xs-6 product-list__grid-item dw-mod product-list-product"> 6753 {{#Product}} 6754 {{>GridViewItem}} 6755 {{/Product}} 6756 </div> 6757 {{/ProductsContainer}} 6758 </div> 6759 6760 <div class="product-slider__next-btn"> 6761 @{ 6762 Button nextButton = new Button { Icon = new Icon { Prefix = "fas", Name = "fa-chevron-right fa-2x", LabelPosition = IconLabelPosition.After }, ButtonLayout = ButtonLayout.Clean, CssClass = "btn--condensed {{nextdisabled}} u-position-relative", OnClick = "HandlebarsBolt.UpdateContent('ProductList_{{groupName}}', '{{nextPage}}')" }; 6763 nextButton.ExtraAttributes.Add("", "{{nextdisabled}}"); 6764 } 6765 @Render(nextButton) 6766 </div> 6767 6768 {{/.}} 6769 </script> 6770 6771 <script id="StickersContainer" type="text/x-template"> 6772 <div class="stickers-container stickers-container--{{{convertStickerPositionToClassName Position}}} dw-mod"> 6773 {{#Stickers}} 6774 {{>Sticker}} 6775 {{/Stickers}} 6776 </div> 6777 </script> 6778 6779 <script id="Sticker" type="text/x-template"> 6780 @Render(new Sticker { Title = "{{Title}}", CssClass = "{{CssClass}}" }) 6781 </script> 6782 6783 <script> 6784 @{ 6785 bool relatedUseGoogleTagManager = !string.IsNullOrEmpty(Pageview.AreaSettings.GetItem("Settings").GetString("GoogleTagManagerID")); 6786 6787 if (relatedUseGoogleTagManager) 6788 { 6789 <text> 6790 document.addEventListener("DOMContentLoaded", function (event) { 6791 Scroll.AddIsInViewportListener(".js-product-scroll-trigger", function (elem) { 6792 let googleImpression = JSON.parse(elem.getAttribute("data-params")); 6793 googleImpression.list = "Related products"; 6794 googleEnchantImpression(googleImpression); 6795 elem.classList.remove("js-product-scroll-trigger"); 6796 }); 6797 }); 6798 </text> 6799 } 6800 } 6801 </script> 6802 @inherits ViewModelTemplate<ProductViewModel> 6803 @using Dynamicweb.Ecommerce.ProductCatalog 6804 @using Dynamicweb.Rendering 6805 @using Dynamicweb.Core 6806 @using Dynamicweb.Rapido.Blocks 6807 @using Smartpage.PhilipsonWine.Ecommerce.ProductInformation 6808 6809 @functions { 6810 BlocksPage productSnippetsPage = BlocksPage.GetBlockPage("Product"); 6811 } 6812 6813 @{ 6814 Block googleProductSchema = new Block() 6815 { 6816 Id = "GoogleProductSchema", 6817 SortId = 10, 6818 Template = RenderGoogleProductSchema() 6819 }; 6820 6821 productSnippetsPage.Add("Snippets", googleProductSchema); 6822 } 6823 6824 @helper RenderGoogleProductSchema() 6825 { 6826 ProductInformation productInformation = new ProductInformation(Model); 6827 var siteURL = Dynamicweb.Context.Current.Request.Url.Scheme + "://" + Dynamicweb.Context.Current.Request.Url.Host; 6828 var image = Model.DefaultImage.Value; 6829 var brand = !string.IsNullOrWhiteSpace(productInformation.Brand) ? productInformation.Brand : ""; 6830 var variantid = !string.IsNullOrEmpty(Model.VariantId) ? Model.VariantId : Model.VariantId; 6831 string linkGroup = "Default.aspx?Id=" + GetPageIdByNavigationTag("ProductsPage") + "&GroupId=" + (Model.PrimaryOrDefaultGroup != null ? Model.PrimaryOrDefaultGroup.Id : "") + "&ProductId=" + Model.Id; 6832 var url = Dynamicweb.Context.Current.Request.Url.Scheme + "://" + Dynamicweb.Context.Current.Request.Url.Host + Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl(linkGroup + (!string.IsNullOrWhiteSpace(variantid) ? "&VariantID=" + variantid : "")); 6833 var priceObject = new Smartpage.PhilipsonWine.Ecommerce.Prices.PriceObject(Model.Id, productInformation.MaxPriceBasedOn, Model.Discount.Price); 6834 6835 <script type="application/ld+json"> 6836 { 6837 "@@context": "http://schema.org/", 6838 "@@type": "Product", 6839 "name": "@Model.Name", 6840 @if (!string.IsNullOrEmpty(image)) 6841 { 6842 <text>"image": [ 6843 "@siteURL/Admin/Public/GetImage.ashx?width=400&height=400&crop=0&Compression=75&DoNotUpscale=true&image=@image", 6844 "@siteURL/Admin/Public/GetImage.ashx?width=400&height=300&crop=0&Compression=75&DoNotUpscale=true&image=@image", 6845 "@siteURL/Admin/Public/GetImage.ashx?width=448&height=225&crop=0&Compression=75&DoNotUpscale=true&image=@image" 6846 ],</text> 6847 } 6848 "description": "@Model.ShortDescription", 6849 "mpn": "925872", 6850 @if (!string.IsNullOrEmpty(brand)) 6851 { 6852 <text>"brand": { 6853 "@@type": "Thing", 6854 "name": "@brand" 6855 },</text> 6856 } 6857 "offers": { 6858 "@@type": "Offer", 6859 "priceCurrency": "@Model.Price.CurrencyCode", 6860 "price": "@priceObject.DiscountPriceFormattedWithoutSymbol.Replace(",", ".")", 6861 "availability": "@(Model.StockLevel > 0 ? "InStock" : "OutOfStock")", 6862 "url": "@url" 6863 }, 6864 "sku": "@Model.Id" 6865 } 6866 </script> 6867 } 6868 6869 @inherits ViewModelTemplate<ProductViewModel> 6870 @using Dynamicweb.Ecommerce.ProductCatalog 6871 @using Dynamicweb.Rendering 6872 @using Dynamicweb.Rapido.Blocks 6873 6874 @functions { 6875 BlocksPage snippetsTemplatesPage = BlocksPage.GetBlockPage("Product"); 6876 } 6877 6878 @{ 6879 snippetsTemplatesPage.Add(new Block { 6880 Id = "FavoritesTemplates", 6881 SortId = 100, 6882 Template = RenderFavoritesTemplates() 6883 }); 6884 } 6885 6886 @helper RenderFavoritesTemplates() 6887 { 6888 var selectedFavoriteIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("FavoriteIcon") != null ? Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("FavoriteIcon").SelectedValue : "star"; 6889 string favoriteIcon = "fas fa-" + selectedFavoriteIcon; 6890 string favoriteOutlineIcon = "fal fa-" + selectedFavoriteIcon; 6891 bool useFacebookPixel = !string.IsNullOrEmpty(Pageview.AreaSettings.GetItem("Settings").GetString("FacebookPixelID")); 6892 string currentFavoriteListId = HttpContext.Current.Request.QueryString.Get("ListID"); 6893 6894 <script id="FavoriteTemplate" type="text/x-template"> 6895 <div class="favorites-list u-ta-left js-favorites-list"> 6896 @Render(new Button { 6897 CssClass = "u-no-margin js-favorite-btn", 6898 Icon = new Icon 6899 { 6900 Name = "{{#if isInAnyFavoriteList}}" + favoriteIcon + "{{else}}" + favoriteOutlineIcon + "{{/if}}", 6901 CssClass = "fa-1_5x", 6902 LabelPosition = IconLabelPosition.After 6903 }, 6904 ButtonLayout = ButtonLayout.LinkClean, 6905 ButtonType = ButtonType.Button, 6906 OnClick = "document.getElementById('FavoriteTrigger_{{id}}').checked = true" 6907 }) 6908 <input type="checkbox" id="FavoriteTrigger_{{id}}" class="dropdown-trigger" /> 6909 <div class="dropdown dropdown--position-32px"> 6910 <div class="dropdown__content dropdown__content--show-left dropdown__content--padding u-w220px dw-mod"> 6911 <ul class="list list--clean dw-mod"> 6912 {{#FavoriteLists}} 6913 {{>FavoriteListItem}} 6914 {{/FavoriteLists}} 6915 </ul> 6916 </div> 6917 <label class="dropdown-trigger-off" for="FavoriteTrigger_{{id}}"></label> 6918 </div> 6919 </div> 6920 </script> 6921 6922 <script id="FavoriteListItem" type="text/x-template"> 6923 <li> 6924 @{ 6925 var button = new Button { 6926 CssClass = "list__link u-no-underline", 6927 OnClick = "toggleFavAction(this, event)", 6928 Icon = new Icon { Name = "{{#if isInFavoriteList}}" + favoriteIcon + "{{else}}" + favoriteOutlineIcon + "{{/if}}", LabelPosition = IconLabelPosition.After }, 6929 AltText = "{{#if isInFavoriteList}}" + Translate("Remove from") + " {{name}}{{else}}" + Translate("Add to") + " {{name}}{{/if}}", 6930 Title = "{{name}}", 6931 ButtonType = ButtonType.Button, 6932 ButtonLayout = ButtonLayout.LinkClean, 6933 ExtraAttributes = new Dictionary<string, string> 6934 { 6935 { "data-list-id", "{{listId}}" }, 6936 { "data-list-name", "{{name}}" }, 6937 { "data-remove-link", "{{removeLink}}" }, 6938 { "data-add-link", "{{addLink}}" }, 6939 { "data-is-in-list", "{{isInFavoriteList}}" }, 6940 6941 } 6942 }; 6943 if (useFacebookPixel) 6944 { 6945 button.ExtraAttributes.Add("data-facebook-object", "{{facebookPixelAddAction}}"); 6946 } 6947 } 6948 <div class="grid__cell"> 6949 @Render(button) 6950 </div> 6951 </li> 6952 </script> 6953 6954 <script> 6955 @if (!string.IsNullOrEmpty(currentFavoriteListId)) 6956 { 6957 <text> 6958 window.currentFavoriteListId = "@currentFavoriteListId"; 6959 </text> 6960 } 6961 function toggleFavAction(button, event) { 6962 if (button.getAttribute('data-add-link').indexOf('CCCreateNewList') > -1) { 6963 Scroll.SavePosition(event); 6964 @if (useFacebookPixel) 6965 { 6966 <text> 6967 fbq('track', 'AddToWishlist', JSON.parse(button.getAttribute('data-facebook-object'))); 6968 </text> 6969 } 6970 location.href = button.getAttribute('data-add-link'); 6971 return; 6972 } 6973 let isAdd = button.getAttribute('data-is-in-list') == "false"; 6974 Request.Fetch().get( 6975 isAdd ? button.getAttribute('data-add-link') : button.getAttribute('data-remove-link'), 6976 function (result) { 6977 button.querySelector('i').className = isAdd ? '@favoriteIcon u-margin-right--lg' : '@favoriteOutlineIcon u-margin-right--lg'; 6978 button.setAttribute('data-is-in-list', isAdd); 6979 button.setAttribute('title', (!isAdd ? '@Translate("Add to") ' : '@Translate("Remove from") ') + button.getAttribute('data-list-name')) 6980 let favList = button.closest('.js-favorites-list'); 6981 let favBtn = favList.querySelector('.js-favorite-btn i'); 6982 let isInAnyFavoriteList = favList.querySelector('[data-is-in-list=true]') != null; 6983 if (isInAnyFavoriteList) { 6984 favBtn.className = '@favoriteIcon' + ' fa-1_5x'; 6985 } else { 6986 favBtn.className = '@favoriteOutlineIcon' + ' fa-1_5x'; 6987 } 6988 @if (useFacebookPixel) 6989 { 6990 <text> 6991 if (isAdd) { 6992 fbq('track', 'AddToWishlist', JSON.parse(button.getAttribute('data-facebook-object'))); 6993 } 6994 </text> 6995 } 6996 if (window.currentFavoriteListId != null) { //if this page is favorite list 6997 let listId = button.getAttribute("data-list-id"); 6998 if (listId == window.currentFavoriteListId && !isAdd) { 6999 location.reload(); 7000 } 7001 } 7002 }, 7003 function () { 7004 console.error("FavoriteLists: Error in ToggleFavAction request"); 7005 }, 7006 false 7007 ); 7008 } 7009 </script> 7010 } 7011 @inherits ViewModelTemplate<ProductViewModel> 7012 @using Dynamicweb.Ecommerce.ProductCatalog 7013 @using Dynamicweb.Rendering 7014 @using Dynamicweb.Rapido.Blocks 7015 7016 @{ 7017 BlocksPage customProductBlocks = BlocksPage.GetBlockPage("Product"); 7018 7019 } 7020 7021 7022 <div class="product__info dw-mod js-product"> 7023 7024 @{ 7025 var navigationSettingsBreadcrump = new Dynamicweb.Frontend.Navigation.NavigationSettings() 7026 { 7027 StartLevel = 2, 7028 StopLevel = 10, 7029 ExpandMode = Dynamicweb.Frontend.Navigation.ExpandMode.PathOnly 7030 }; 7031 } 7032 7033 @if (GetNavigation(navigationSettingsBreadcrump).Nodes.Any()) 7034 { 7035 <ul class="breadcrumb dw-mod"> 7036 @RenderNavigationNodes(GetNavigation(navigationSettingsBreadcrump).Nodes) 7037 7038 @helper RenderNavigationNodes(IEnumerable<Dynamicweb.Frontend.Navigation.NavigationTreeNodeViewModel> nodes) 7039 { 7040 foreach (var node in nodes) 7041 { 7042 if (node.InPath) 7043 { 7044 <li class="breadcrumb__item dw-mod"> 7045 <a href="@node.Link">@node.Name</a> 7046 </li> 7047 @RenderNavigationNodes(node.Nodes); 7048 } 7049 } 7050 } 7051 </ul> 7052 } 7053 7054 <div class="grid grid--direction-column"> 7055 @* The @RenderBlockList base helper is included in Components/GridBuilder.cshtml *@ 7056 @RenderBlockList(productsPage.BlocksRoot.BlocksList) 7057 <div class="paragraph-container--full-width"> 7058 @RenderBlockList(productDetails) 7059 </div> 7060 </div> 7061 </div> 7062 7063 @helper RenderProductTop() 7064 { 7065 List<Block> subBlocks = productsPage.GetBlockListById("Top").OrderBy(item => item.SortId).ToList(); 7066 7067 <div class="product__top paragraph-container paragraph-container--full-width u-grey-border-bottom"> 7068 <div class="center-container dw-mod"> 7069 <div class="grid"> 7070 @RenderBlockList(subBlocks) 7071 </div> 7072 </div> 7073 </div> 7074 } 7075 7076 7077 @helper RenderProductMiniTabs() 7078 { 7079 List<Block> subBlocks = productsPage.GetBlockListById("MiniTabs").OrderBy(item => item.SortId).ToList(); 7080 7081 if (subBlocks.Count > 0) 7082 { 7083 <div class="grid__col-12 product__info tabs u-no-padding u-margin-bottom--lg dw-mod"> 7084 @{ 7085 bool firstTab = true; 7086 foreach (Block item in subBlocks) 7087 { 7088 string isChecked = firstTab ? "checked" : ""; 7089 firstTab = false; 7090 7091 <input type="radio" class="tabs__trigger" name="productMiniTabs" id="@item.Id" onchange="bLazy.revalidate()" @isChecked /> 7092 } 7093 } 7094 7095 <div class="tabs__list dw-mod"> 7096 @foreach (Block item in subBlocks) 7097 { 7098 <label for="@item.Id" class="tabs__label dw-mod">@item.Name</label> 7099 } 7100 </div> 7101 7102 <div class="tabs__blocks dw-mod"> 7103 @foreach (Block item in subBlocks) 7104 { 7105 string hidePadding = item.Design.HidePadding ? "u-no-padding" : ""; 7106 7107 if (item.Design.RenderType != RenderType.Hide) 7108 { 7109 <div class="tabs__block u-border dw-mod" id="Block__@item.Id"> 7110 <block class="product__block paragraph-container product__block--bordered dw-mod"> 7111 <div class="center-container dw-mod"> 7112 @RenderBlock(item) 7113 </div> 7114 </block> 7115 </div> 7116 } 7117 } 7118 </div> 7119 </div> 7120 } 7121 } 7122 7123 @helper RenderProductTabs() 7124 { 7125 List<Block> subBlocks = productsPage.GetBlockListById("Tabs").OrderBy(item => item.SortId).ToList(); 7126 7127 <div class="grid__col-12 product__info product__info--tabs tabs dw-mod"> 7128 @{ 7129 bool firstTab = true; 7130 foreach (Block item in subBlocks) 7131 { 7132 string isChecked = firstTab ? "checked" : ""; 7133 firstTab = false; 7134 7135 <input type="radio" class="tabs__trigger" name="productTabs" id="@item.Id" onchange="bLazy.revalidate()" @isChecked /> 7136 } 7137 } 7138 7139 <div class="tabs__list dw-mod"> 7140 @foreach (Block item in subBlocks) 7141 { 7142 <label for="@item.Id" class="tabs__label dw-mod">@item.Name</label> 7143 } 7144 </div> 7145 7146 <div class="tabs__blocks dw-mod"> 7147 @foreach (Block item in subBlocks) 7148 { 7149 string hidePadding = item.Design.HidePadding ? "u-no-padding" : ""; 7150 7151 if (item.Design.RenderType != RenderType.Hide) 7152 { 7153 <div class="tabs__block dw-mod" id="Block__@item.Id"> 7154 <section class="product__section paragraph-container paragraph-container--full-width product__section--bordered dw-mod"> 7155 <div class="center-container u-padding--lg dw-mod"> 7156 @RenderBlock(item) 7157 </div> 7158 </section> 7159 </div> 7160 } 7161 } 7162 </div> 7163 </div> 7164 } 7165 7166