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