Error executing template "Designs/Rapido/_parsed/ContentPage.parsed.cshtml"
System.NullReferenceException: Object reference not set to an instance of an object.
at CompiledRazorTemplates.Dynamic.RazorEngine_282e9389798f4500a2a7d6b36a09d511.<RenderSchema>b__104_0(TextWriter __razor_helper_writer) in D:\dynamicweb.net\Solutions\Philipson Wine Test\Files\Templates\Designs\Rapido\_parsed\ContentPage.parsed.cshtml:line 4154
at RazorEngine.Templating.TemplateWriter.ToString()
at System.Lazy`1.CreateValue()
at System.Lazy`1.LazyInitValue()
at CompiledRazorTemplates.Dynamic.RazorEngine_282e9389798f4500a2a7d6b36a09d511.<>c__DisplayClass3_0.<RenderBlock>b__0(TextWriter __razor_helper_writer) in D:\dynamicweb.net\Solutions\Philipson Wine Test\Files\Templates\Designs\Rapido\_parsed\ContentPage.parsed.cshtml:line 302
at CompiledRazorTemplates.Dynamic.RazorEngine_282e9389798f4500a2a7d6b36a09d511.<>c__DisplayClass2_0.<RenderBlockList>b__0(TextWriter __razor_helper_writer) in D:\dynamicweb.net\Solutions\Philipson Wine Test\Files\Templates\Designs\Rapido\_parsed\ContentPage.parsed.cshtml:line 189
at CompiledRazorTemplates.Dynamic.RazorEngine_282e9389798f4500a2a7d6b36a09d511.<RenderMasterHead>b__331_0(TextWriter __razor_helper_writer) in D:\dynamicweb.net\Solutions\Philipson Wine Test\Files\Templates\Designs\Rapido\_parsed\ContentPage.parsed.cshtml:line 14552
at RazorEngine.Templating.TemplateWriter.ToString()
at System.Lazy`1.CreateValue()
at System.Lazy`1.LazyInitValue()
at CompiledRazorTemplates.Dynamic.RazorEngine_282e9389798f4500a2a7d6b36a09d511.<>c__DisplayClass3_0.<RenderBlock>b__0(TextWriter __razor_helper_writer) in D:\dynamicweb.net\Solutions\Philipson Wine Test\Files\Templates\Designs\Rapido\_parsed\ContentPage.parsed.cshtml:line 302
at CompiledRazorTemplates.Dynamic.RazorEngine_282e9389798f4500a2a7d6b36a09d511.<>c__DisplayClass2_0.<RenderBlockList>b__0(TextWriter __razor_helper_writer) in D:\dynamicweb.net\Solutions\Philipson Wine Test\Files\Templates\Designs\Rapido\_parsed\ContentPage.parsed.cshtml:line 189
at CompiledRazorTemplates.Dynamic.RazorEngine_282e9389798f4500a2a7d6b36a09d511.<>c__DisplayClass3_0.<RenderBlock>b__0(TextWriter __razor_helper_writer) in D:\dynamicweb.net\Solutions\Philipson Wine Test\Files\Templates\Designs\Rapido\_parsed\ContentPage.parsed.cshtml:line 342
at CompiledRazorTemplates.Dynamic.RazorEngine_282e9389798f4500a2a7d6b36a09d511.<>c__DisplayClass2_0.<RenderBlockList>b__0(TextWriter __razor_helper_writer) in D:\dynamicweb.net\Solutions\Philipson Wine Test\Files\Templates\Designs\Rapido\_parsed\ContentPage.parsed.cshtml:line 189
at CompiledRazorTemplates.Dynamic.RazorEngine_282e9389798f4500a2a7d6b36a09d511.Execute() in D:\dynamicweb.net\Solutions\Philipson Wine Test\Files\Templates\Designs\Rapido\_parsed\ContentPage.parsed.cshtml:line 14541
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.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
2
3 @using System.Web;
4 @using Dynamicweb
5 @using Dynamicweb.Frontend
6 @using Dynamicweb.Frontend.Devices
7 @using Dynamicweb.Extensibility
8 @using Dynamicweb.Content
9 @using Dynamicweb.Security
10 @using Dynamicweb.Core
11 @using System
12 @using System.Web
13 @using System.IO
14 @using System.Text.RegularExpressions;
15 @using Dynamicweb.Rapido.Blocks
16 @using System.Net
17 @using Dynamicweb.Logging
18 @using Dynamicweb.Environment;
19
20
21 @functions {
22 BlocksPage masterPage = BlocksPage.GetBlockPage("Master");
23
24 string getFontFamily(params string[] items)
25 {
26 var itemParent = Pageview.AreaSettings;
27 foreach (var item in items)
28 {
29 itemParent = itemParent.GetItem(item);
30 if (itemParent == null)
31 {
32 return null;
33 }
34 }
35
36 var googleFont = itemParent.GetGoogleFont("FontFamily");
37 if (googleFont == null)
38 {
39 return null;
40 }
41 return googleFont.Family.Replace(" ", "+");
42 }
43
44 }
45
46 @{
47 Block root = new Block
48 {
49 Id = "Root",
50 SortId = 10,
51 BlocksList = new List<Block>
52 {
53 new Block {
54 Id = "Head",
55 SortId = 10,
56 SkipRenderBlocksList = true,
57 Template = RenderMasterHead(),
58 BlocksList = new List<Block>
59 {
60 new Block {
61 Id = "HeadMetadata",
62 SortId = 10,
63 Template = CustomRenderMasterMetadata(),
64 },
65 new Block {
66 Id = "HeadCss",
67 SortId = 20,
68 Template = RenderMasterCss(),
69 },
70 new Block {
71 Id = "HeadManifest",
72 SortId = 30,
73 Template = RenderMasterManifest(),
74 }
75 }
76 },
77 new Block {
78 Id = "Body",
79 SortId = 20,
80 SkipRenderBlocksList = true,
81 Template = RenderMasterBody(),
82 BlocksList = new List<Block>
83 {
84 new Block()
85 {
86 Id = "Master",
87 SortId = 10,
88 BlocksList = new List<Block> {
89 new Block {
90 Id = "MasterTopSnippets",
91 SortId = 10
92 },
93 new Block {
94 Id = "MasterMain",
95 SortId = 20,
96 Template = RenderMain(),
97 SkipRenderBlocksList = true,
98 BlocksList = new List<Block> {
99 new Block {
100 Id = "MasterHeader",
101 SortId = 10,
102 Template = RenderMasterHeader(),
103 SkipRenderBlocksList = true
104 },
105 new Block {
106 Id = "MasterPageContent",
107 SortId = 20,
108 Template = RenderPageContent()
109 },
110 new Block {
111 Id = "MasterPageOverlay",
112 SortId = 30,
113 Template = RenderOverlay()
114 }
115 }
116 },
117 new Block {
118 Id = "MasterFooter",
119 SortId = 30
120 },
121 new Block {
122 Id = "MasterReferences",
123 SortId = 40
124 },
125 new Block {
126 Id = "MasterBottomSnippets",
127 SortId = 50
128 }
129 }
130 }
131 }
132 }
133 }
134 };
135
136 masterPage.Add(root);
137 }
138
139 @{
140 bool isHeaderHidden = Model.PropertyItem.GetBoolean("HideHeader");
141 bool isFooterHidden = Model.PropertyItem.GetBoolean("HideFooter");
142 string fileVersion = Converter.ToString(System.Web.HttpContext.Current.Cache["FileVersion"]);
143 if (string.IsNullOrEmpty(fileVersion))
144 {
145 try
146 {
147 var assembly = System.Reflection.Assembly.Load("Application");
148 if (assembly != null)
149 {
150 fileVersion = System.Diagnostics.FileVersionInfo.GetVersionInfo(assembly.Location).FileVersion;
151 System.Web.HttpContext.Current.Cache["FileVersion"] = fileVersion;
152 }
153 }
154 catch (Exception ex)
155 {
156 LogManager.Current.GetLogger("Smartpage/Assemblies").Error("Error while loading Application assembly: ", ex);
157 }
158 }
159 }
160
161 @* Include the required Grid builder (Contains the methods @RenderBlockList and @RenderBlock) *@
162 @using System.Text.RegularExpressions
163 @using System.Collections.Generic
164 @using System.Reflection
165 @using System.Web
166 @using System.Web.UI.HtmlControls
167 @using Dynamicweb.Rapido.Blocks.Components
168 @using Dynamicweb.Rapido.Blocks.Components.Articles
169 @using Dynamicweb.Rapido.Blocks.Components.Documentation
170 @using Dynamicweb.Rapido.Blocks
171
172
173 @*--- START: Base block renderers ---*@
174
175 @helper RenderBlockList(List<Block> blocks)
176 {
177 bool debug = !String.IsNullOrEmpty(HttpContext.Current.Request.QueryString.Get("debug")) ? Convert.ToBoolean(HttpContext.Current.Request.QueryString.Get("debug")) : false;
178 blocks = blocks.OrderBy(item => item.SortId).ToList();
179
180 foreach (Block item in blocks)
181 {
182 if (debug)
183 {
184 <!-- Block START: @item.Id -->
185 }
186
187 if (item.Design == null)
188 {
189 @RenderBlock(item)
190 }
191 else if (item.Design.RenderType == RenderType.None)
192 {
193 string cssClass = item.Design.CssClass != null ? item.Design.CssClass : "";
194
195 <div class="@cssClass dw-mod">
196 @RenderBlock(item)
197 </div>
198 }
199 else if (item.Design.RenderType != RenderType.Hide)
200 {
201 string cssClass = item.Design.CssClass != null ? item.Design.CssClass : "";
202
203 if (!item.SkipRenderBlocksList)
204 {
205 if (item.Design.RenderType == RenderType.Row)
206 {
207 <div class="grid grid--align-content-start @cssClass dw-mod" id="Block__@item.Id">
208 @RenderBlock(item)
209 </div>
210 }
211
212 if (item.Design.RenderType == RenderType.Column)
213 {
214 string hidePadding = item.Design.HidePadding ? "u-no-padding" : "";
215 string size = item.Design.Size ?? "12";
216 size = Regex.IsMatch(size, @"\d") ? "md-" + item.Design.Size : item.Design.Size;
217
218 // Used to remove sticky--facet class from Navigation if there are no products
219 if (item.Id == "Navigation")
220 {
221
222 <text>
223 {{#if totalProductsCount}}
224 <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">
225 @RenderBlock(item)
226 </div>
227 {{else}}
228 <div class="grid__col-lg-@item.Design.Size grid__col-md-@item.Design.Size grid__col-sm-12 grid__col-xs-12 @hidePadding dw-mod" id="Block__@item.Id" style="top: 75px; position: sticky; align-self: baseline; overflow-y: auto;">
229 @RenderBlock(item)
230 </div>
231 {{/if}}
232
233 </text>
234 }
235 else
236 {
237 <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">
238 @RenderBlock(item)
239 </div>
240 }
241 }
242
243 if (item.Design.RenderType == RenderType.Table)
244 {
245 <table class="table @cssClass dw-mod" id="Block__@item.Id">
246 @RenderBlock(item)
247 </table>
248 }
249
250 if (item.Design.RenderType == RenderType.TableRow)
251 {
252 <tr class="@cssClass dw-mod" id="Block__@item.Id">
253 @RenderBlock(item)
254 </tr>
255 }
256
257 if (item.Design.RenderType == RenderType.TableColumn)
258 {
259 <td class="@cssClass dw-mod" id="Block__@item.Id">
260 @RenderBlock(item)
261 </td>
262 }
263
264 if (item.Design.RenderType == RenderType.CardHeader)
265 {
266 <div class="card-header @cssClass dw-mod">
267 @RenderBlock(item)
268 </div>
269 }
270
271 if (item.Design.RenderType == RenderType.CardBody)
272 {
273 <div class="card @cssClass dw-mod">
274 @RenderBlock(item)
275 </div>
276 }
277
278 if (item.Design.RenderType == RenderType.CardFooter)
279 {
280 <div class="card-footer @cssClass dw-mod">
281 @RenderBlock(item)
282 </div>
283 }
284 }
285 else
286 {
287 @RenderBlock(item)
288 }
289 }
290
291 if (debug)
292 {
293 <!-- Block END: @item.Id -->
294 }
295 }
296 }
297
298 @helper RenderBlock(Block item)
299 {
300 bool debug = !String.IsNullOrEmpty(HttpContext.Current.Request.QueryString.Get("debug")) ? Convert.ToBoolean(HttpContext.Current.Request.QueryString.Get("debug")) : false;
301
302 if (item.Template != null)
303 {
304 @BlocksPage.RenderTemplate(item.Template)
305 }
306
307 if (item.Component != null)
308 {
309 string customSufix = "Custom";
310 string methodName = item.Component.HelperName;
311
312 ComponentBase[] methodParameters = new ComponentBase[1];
313 methodParameters[0] = item.Component;
314 Type methodType = this.GetType();
315
316 MethodInfo customMethod = methodType.GetMethod(methodName + customSufix);
317 MethodInfo generalMethod = methodType.GetMethod(methodName);
318
319 try
320 {
321 if (debug)
322 {
323 <!-- Component: @methodName.Replace("Render", "") -->
324 }
325 @customMethod.Invoke(this, methodParameters).ToString();
326 }
327 catch
328 {
329 try
330 {
331 @generalMethod.Invoke(this, methodParameters).ToString();
332 }
333 catch (Exception ex)
334 {
335 throw new Exception(item.Component.GetType().Name + " method '" + methodName + "' could not be invoked", ex);
336 }
337 }
338 }
339
340 if (item.BlocksList.Count > 0 && !item.SkipRenderBlocksList)
341 {
342 @RenderBlockList(item.BlocksList)
343 }
344 }
345
346 @*--- END: Base block renderers ---*@
347
348
349 @* Include the components *@
350 @using Dynamicweb.Rapido.Blocks.Components
351 @using Dynamicweb.Rapido.Blocks.Components.General
352 @using Dynamicweb.Rapido.Blocks
353 @using System.IO
354
355 @* Required *@
356 @using Dynamicweb.Rapido.Blocks.Components
357 @using Dynamicweb.Rapido.Blocks.Components.General
358 @using Dynamicweb.Rapido.Blocks
359
360
361 @helper Render(ComponentBase component)
362 {
363 if (component != null)
364 {
365 @component.Render(this)
366 }
367 }
368
369 @* Components *@
370 @using System.Reflection
371 @using Dynamicweb.Rapido.Blocks.Components.General
372
373
374 @* Component *@
375
376 @helper RenderIcon(Icon settings)
377 {
378 if (settings != null)
379 {
380 string color = settings.Color != null ? "style=\"color: " + settings.Color + "\"" : "";
381
382 if (settings.Name != null)
383 {
384 if (string.IsNullOrEmpty(settings.Label))
385 {
386 <i class="@settings.Prefix @settings.Name @settings.CssClass" @color></i>
387 }
388 else
389 {
390 if (settings.LabelPosition == IconLabelPosition.Before)
391 {
392 <span>@settings.Label <i class="@settings.Prefix @settings.Name @settings.CssClass" @color></i></span>
393 }
394 else
395 {
396 <span><i class="@settings.Prefix @settings.Name u-margin-right--lg @settings.CssClass u-w20px" @color></i>@settings.Label</span>
397 }
398 }
399 }
400 else if (!string.IsNullOrEmpty(settings.Label))
401 {
402 @settings.Label
403 }
404 }
405 }
406 @using System.Reflection
407 @using Dynamicweb.Rapido.Blocks.Components.General
408 @using Dynamicweb.Rapido.Blocks.Components
409 @using Dynamicweb.Core
410
411 @* Component *@
412
413 @helper RenderButton(Button settings)
414 {
415 if (settings != null && (!string.IsNullOrEmpty(settings.Title) || settings.Icon != null))
416 {
417 Dictionary<string, string> attributes = new Dictionary<string, string>();
418 List<string> classList = settings.CssClass != null ? settings.CssClass.Split(' ').ToList() : new List<string>();
419 if (settings.Disabled)
420 {
421 attributes.Add("disabled", "true");
422 classList.Add("disabled");
423 }
424
425 if (!string.IsNullOrEmpty(settings.ConfirmText) || !string.IsNullOrEmpty(settings.ConfirmTitle))
426 {
427 settings.Id = !string.IsNullOrEmpty(settings.Id) ? settings.Id : Guid.NewGuid().ToString("N");
428 @RenderConfirmDialog(settings);
429 settings.OnClick = "document.getElementById('" + settings.Id + "ModalTrigger').checked = true";
430 }
431
432 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); }
433 if (!string.IsNullOrEmpty(settings.Name)) { attributes.Add("name", settings.Name); }
434 if (!string.IsNullOrEmpty(settings.AltText))
435 {
436 attributes.Add("title", settings.AltText);
437 }
438 else if (!string.IsNullOrEmpty(settings.Title))
439 {
440 attributes.Add("title", settings.Title);
441 }
442
443 var onClickEvents = new List<string>();
444 if (!string.IsNullOrEmpty(settings.OnClick))
445 {
446 onClickEvents.Add(settings.OnClick);
447 }
448 if (!string.IsNullOrEmpty(settings.Href))
449 {
450 if (settings.Href.StartsWith("default.aspx", StringComparison.InvariantCultureIgnoreCase))
451 {
452 settings.Href = "/" + settings.Href;
453 }
454
455 onClickEvents.Add("location.href='" + settings.Href + "'");
456 }
457 if (onClickEvents.Count > 0)
458 {
459 attributes.Add("onClick", string.Join(";", onClickEvents));
460 }
461
462 if (settings.ButtonLayout != ButtonLayout.None)
463 {
464 classList.Add("btn");
465 string btnLayout = Enum.GetName(typeof(ButtonLayout), settings.ButtonLayout).ToLower();
466 if (btnLayout == "linkclean")
467 {
468 btnLayout = "link-clean"; //fix
469 }
470 classList.Add("btn--" + btnLayout);
471 }
472
473 if (settings.Icon == null)
474 {
475 settings.Icon = new Icon();
476 }
477 settings.Icon.Label = settings.Title;
478
479 attributes.Add("type", Enum.GetName(typeof(ButtonType), settings.ButtonType).ToLower());
480
481 //If link is a paragraph, go to that paragraph
482 if (!string.IsNullOrEmpty(settings.Href) && settings.Href.Contains("#"))
483 {
484 string[] hrefSplit = settings.Href.Trim().Split('#');
485 string idToScrollTo = "paragraph_" + hrefSplit[1].Trim();
486
487 int pageId = Dynamicweb.Environment.Helpers.LinkHelper.GetInternalPageId(settings.Href.TrimStart('/'));
488 if (Pageview.ID == pageId)
489 {
490 attributes.Remove("onClick");
491 attributes.Add("onClick", "document.getElementById('" + idToScrollTo + "').scrollIntoView({behavior: 'smooth'})");
492 }
493 else if (pageId != 0)
494 {
495 settings.Href = hrefSplit[0].Trim() + "#paragraph_" + hrefSplit[1].Trim();
496 attributes.Remove("onClick");
497 attributes.Add("onClick", "location.href='" + settings.Href + "'");
498 }
499 }
500
501 <button class="@string.Join(" ", classList) dw-mod" @ComponentMethods.AddAttributes(attributes) @ComponentMethods.AddAttributes(settings.ExtraAttributes)>@Render(settings.Icon)</button>
502 }
503 }
504
505 @helper RenderConfirmDialog(Button settings)
506 {
507 Modal confirmDialog = new Modal
508 {
509 Id = settings.Id,
510 Width = ModalWidth.Sm,
511 Heading = new Heading
512 {
513 Level = 2,
514 Title = settings.ConfirmTitle
515 },
516 BodyText = settings.ConfirmText
517 };
518
519 confirmDialog.AddAction(new Button { Title = Translate("Cancel"), ButtonLayout = ButtonLayout.Secondary, OnClick = "document.getElementById('" + settings.Id + "ModalTrigger').checked = false"});
520 confirmDialog.AddAction(new Button { Title = Translate("OK"), ButtonLayout = ButtonLayout.Primary, OnClick = "document.getElementById('" + settings.Id + "ModalTrigger').checked = false;" + settings.OnClick });
521
522 @Render(confirmDialog)
523 }
524 @using Dynamicweb.Rapido.Blocks.Components.General
525 @using Dynamicweb.Rapido.Blocks.Components
526 @using Dynamicweb.Core
527
528 @helper RenderDashboard(Dashboard settings)
529 {
530 var widgets = settings.GetWidgets();
531
532 if (!string.IsNullOrEmpty(settings.WidgetsBaseBackgroundColor))
533 {
534 //set bg color for them
535
536 System.Drawing.Color color = System.Drawing.ColorTranslator.FromHtml(settings.WidgetsBaseBackgroundColor);
537 int r = Convert.ToInt16(color.R);
538 int g = Convert.ToInt16(color.G);
539 int b = Convert.ToInt16(color.B);
540
541 var count = widgets.Length;
542 var max = Math.Max(r, Math.Max(g, b));
543 double step = 255.0 / (max * count);
544 var i = 0;
545 foreach (var widget in widgets)
546 {
547 i++;
548
549 var shade = "rgb(" + Converter.ToString(r * step * i).Replace(",", ".") + ", " + Converter.ToString(g * step * i).Replace(",", ".") + ", " + Converter.ToString(b * step * i).Replace(",", ".") + ")";
550 widget.BackgroundColor = shade;
551 }
552 }
553
554 <div class="dashboard @settings.CssClass dw-mod" @ComponentMethods.AddAttributes(settings.ExtraAttributes)>
555 @foreach (var widget in widgets)
556 {
557 <div class="dashboard__widget">
558 @Render(widget)
559 </div>
560 }
561 </div>
562 }
563 @using Dynamicweb.Rapido.Blocks.Components.General
564 @using Dynamicweb.Rapido.Blocks.Components
565
566 @helper RenderDashboardWidgetLink(DashboardWidgetLink settings)
567 {
568 if (!string.IsNullOrEmpty(settings.Link))
569 {
570 var backgroundStyles = "";
571 if (!string.IsNullOrEmpty(settings.BackgroundColor))
572 {
573 backgroundStyles = "style=\"background-color:" + settings.BackgroundColor + "\"";
574 }
575
576 <a href="@settings.Link" class="widget widget--link @settings.CssClass dw-mod" @backgroundStyles title="@settings.Title" @ComponentMethods.AddAttributes(settings.ExtraAttributes)>
577 <div class="u-center-middle u-color-light">
578 @if (settings.Icon != null)
579 {
580 settings.Icon.CssClass += "widget__icon";
581 @Render(settings.Icon)
582 }
583 <div class="widget__title">@settings.Title</div>
584 </div>
585 </a>
586 }
587 }
588 @using Dynamicweb.Rapido.Blocks.Components.General
589 @using Dynamicweb.Rapido.Blocks.Components
590
591 @helper RenderDashboardWidgetCounter(DashboardWidgetCounter settings)
592 {
593 var backgroundStyles = "";
594 if (!string.IsNullOrEmpty(settings.BackgroundColor))
595 {
596 backgroundStyles = "style='background-color:" + settings.BackgroundColor + "'";
597 }
598
599 <div class="widget @settings.CssClass dw-mod" @backgroundStyles @ComponentMethods.AddAttributes(settings.ExtraAttributes)>
600 <div class="u-center-middle u-color-light">
601 @if (settings.Icon != null)
602 {
603 settings.Icon.CssClass += "widget__icon";
604 @Render(settings.Icon)
605 }
606 <div class="widget__counter">@settings.Count</div>
607 <div class="widget__title">@settings.Title</div>
608 </div>
609 </div>
610 }
611 @using System.Reflection
612 @using Dynamicweb.Rapido.Blocks.Components.General
613 @using Dynamicweb.Rapido.Blocks.Components
614 @using Dynamicweb.Core
615
616 @* Component *@
617
618 @helper RenderLink(Link settings)
619 {
620 if (settings != null && !string.IsNullOrEmpty(settings.Href) && (!string.IsNullOrEmpty(settings.Title) || settings.Icon != null))
621 {
622 Dictionary<string, string> attributes = new Dictionary<string, string>();
623 List<string> classList = settings.CssClass != null ? settings.CssClass.Split(' ').ToList() : new List<string>();
624 if (settings.Disabled)
625 {
626 attributes.Add("disabled", "true");
627 classList.Add("disabled");
628 }
629
630 if (!string.IsNullOrEmpty(settings.AltText))
631 {
632 attributes.Add("title", settings.AltText);
633 }
634 else if (!string.IsNullOrEmpty(settings.Title))
635 {
636 attributes.Add("title", settings.Title);
637 }
638
639 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); }
640 if (!string.IsNullOrEmpty(settings.Name)) { attributes.Add("name", settings.Name); }
641 if (!string.IsNullOrEmpty(settings.OnClick)) { attributes.Add("onClick", settings.OnClick); }
642 attributes.Add("href", settings.Href);
643
644 if (settings.ButtonLayout != ButtonLayout.None)
645 {
646 classList.Add("btn");
647 string btnLayout = Enum.GetName(typeof(ButtonLayout), settings.ButtonLayout).ToLower();
648 if (btnLayout == "linkclean")
649 {
650 btnLayout = "link-clean"; //fix
651 }
652 classList.Add("btn--" + btnLayout);
653 }
654
655 if (settings.Icon == null)
656 {
657 settings.Icon = new Icon();
658 }
659 settings.Icon.Label = settings.Title;
660
661 if (settings.Target == LinkTargetType.Blank && settings.Rel == LinkRelType.None)
662 {
663 settings.Rel = LinkRelType.Noopener;
664 }
665 if (settings.Target != LinkTargetType.None)
666 {
667 attributes.Add("target", "_" + Enum.GetName(typeof(LinkTargetType), settings.Target).ToLower());
668 }
669 if (settings.Download)
670 {
671 attributes.Add("download", "true");
672 }
673 if (settings.Rel != LinkRelType.None)
674 {
675 attributes.Add("rel", Enum.GetName(typeof(LinkRelType), settings.Rel).ToLower());
676 }
677
678 <a class="@string.Join(" ", classList) dw-mod" @ComponentMethods.AddAttributes(attributes) @ComponentMethods.AddAttributes(settings.ExtraAttributes)>@Render(settings.Icon)</a>
679 }
680 }
681 @using System.Reflection
682 @using Dynamicweb.Rapido.Blocks.Components
683 @using Dynamicweb.Rapido.Blocks.Components.General
684 @using Dynamicweb.Rapido.Blocks
685
686
687 @* Component *@
688
689 @helper RenderRating(Rating settings)
690 {
691 if (settings.Score > 0)
692 {
693 int rating = settings.Score;
694 string iconType = "fa-star";
695
696 switch (settings.Type.ToString()) {
697 case "Stars":
698 iconType = "fa-star";
699 break;
700 case "Hearts":
701 iconType = "fa-heart";
702 break;
703 case "Lemons":
704 iconType = "fa-lemon";
705 break;
706 case "Bombs":
707 iconType = "fa-bomb";
708 break;
709 }
710
711 <div class="u-ta-right">
712 @for (int i = 0; i < settings.OutOf; i++)
713 {
714 <i class="@(rating > i ? "fas" : "far") @iconType"></i>
715 }
716 </div>
717 }
718 }
719 @using System.Reflection
720 @using Dynamicweb.Rapido.Blocks.Components.General
721 @using Dynamicweb.Rapido.Blocks.Components
722
723
724 @* Component *@
725
726 @helper RenderSelectFieldOption(SelectFieldOption settings)
727 {
728 Dictionary<string, string> attributes = new Dictionary<string, string>();
729 if (settings.Checked) { attributes.Add("selected", "true"); }
730 if (settings.Disabled) { attributes.Add("disabled", "true"); }
731 if (settings.Value != null) { attributes.Add("value", settings.Value); }
732 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); }
733
734 <option @ComponentMethods.AddAttributes(attributes) @ComponentMethods.AddAttributes(settings.ExtraAttributes)>@settings.Label</option>
735 }
736 @using System.Reflection
737 @using Dynamicweb.Rapido.Blocks.Components.General
738 @using Dynamicweb.Rapido.Blocks.Components
739
740
741 @* Component *@
742
743 @helper RenderNavigation(Navigation settings) {
744 @RenderNavigation(new
745 {
746 id = settings.Id,
747 cssclass = settings.CssClass,
748 startLevel = settings.StartLevel,
749 endlevel = settings.EndLevel,
750 expandmode = settings.Expandmode,
751 sitemapmode = settings.SitemapMode,
752 template = settings.Template
753 })
754 }
755 @using Dynamicweb.Rapido.Blocks.Components.General
756 @using Dynamicweb.Rapido.Blocks.Components
757
758
759 @* Component *@
760
761 @helper RenderBreadcrumbNavigation(BreadcrumbNavigation settings) {
762 settings.Id = String.IsNullOrEmpty(settings.Id) ? "breadcrumb" : settings.Id;
763 settings.Template = String.IsNullOrEmpty(settings.Template) ? "Breadcrumb.xslt" : settings.Template;
764 settings.StartLevel = settings.StartLevel == 0 ? 1 : settings.StartLevel;
765 settings.EndLevel = settings.EndLevel == 10 ? 1 : settings.EndLevel;
766 settings.Expandmode = String.IsNullOrEmpty(settings.Expandmode) ? "all" : settings.Expandmode;
767 settings.SitemapMode = false;
768
769 @RenderNavigation(settings)
770 }
771 @using Dynamicweb.Rapido.Blocks.Components.General
772 @using Dynamicweb.Rapido.Blocks.Components
773
774
775 @* Component *@
776
777 @helper RenderLeftNavigation(LeftNavigation settings) {
778 settings.Id = String.IsNullOrEmpty(settings.Id) ? "breadcrumb" : settings.Id;
779 settings.Template = String.IsNullOrEmpty(settings.Template) ? "Breadcrumb.xslt" : settings.Template;
780 settings.StartLevel = settings.StartLevel == 0 ? 1 : settings.StartLevel;
781 settings.EndLevel = settings.EndLevel == 10 ? 1 : settings.EndLevel;
782 settings.Expandmode = String.IsNullOrEmpty(settings.Expandmode) ? "all" : settings.Expandmode;
783
784 <div class="grid__cell">
785 @RenderNavigation(settings)
786 </div>
787 }
788 @using System.Reflection
789 @using Dynamicweb.Rapido.Blocks.Components.General
790 @using Dynamicweb.Core
791
792 @* Component *@
793
794 @helper RenderHeading(Heading settings)
795 {
796 if (settings != null && !string.IsNullOrEmpty(settings.Title))
797 {
798 string color = settings.Color != null ? "style=\"color: " + settings.Color + "\"" : "";
799 string tagName = settings.Level != 0 ? "h" + settings.Level.ToString() : "div";
800
801 @("<" + tagName + " class=\"" + settings.CssClass + " dw-mod\" " + color + ">")
802 if (!string.IsNullOrEmpty(settings.Link))
803 {
804 @Render(new Link { Href = settings.Link, Icon = settings.Icon, Title = settings.Title, ButtonLayout = ButtonLayout.None })
805 }
806 else
807 {
808 if (settings.Icon == null)
809 {
810 settings.Icon = new Icon();
811 }
812 settings.Icon.Label = settings.Title;
813 @Render(settings.Icon)
814 }
815 @("</" + tagName + ">");
816 }
817 }
818 @using Dynamicweb.Rapido.Blocks.Components
819 @using Dynamicweb.Rapido.Blocks.Components.General
820 @using Dynamicweb.Rapido.Blocks
821
822
823 @* Component *@
824
825 @helper RenderImage(Image settings)
826 {
827 string cleanImagePath = string.Empty;
828 if (settings.Path is string)
829 {
830 cleanImagePath = settings.Path;
831 }
832 int index = cleanImagePath.IndexOf("&x");
833 if (index >= 0)
834 {
835 cleanImagePath = cleanImagePath.Substring(0, index);
836 }
837
838 if (settings.FilterPrimary != ImageFilter.None || settings.FilterSecondary != ImageFilter.None)
839 {
840 Dictionary<string, string> optionalAttributes = new Dictionary<string, string>();
841 if (!string.IsNullOrEmpty(settings.FilterColor)) { optionalAttributes.Add("style", "background-color: " + settings.FilterColor); }
842
843 if (settings.Caption != null)
844 {
845 @:<div>
846 }
847
848 var primaryFilterClass = settings.FilterPrimary.ToString().ToLower();
849 var secondaryFilterClass = settings.FilterSecondary.ToString().ToLower();
850
851 <div class="image-filter image-filter--@primaryFilterClass u-position-relative dw-mod" @ComponentMethods.AddAttributes(optionalAttributes)>
852 <div class="image-filter image-filter--@secondaryFilterClass dw-mod">
853 @if (settings.Link != null)
854 {
855 <a href="@settings.Link">
856 @RenderTheImage(settings, cleanImagePath)
857 </a>
858 }
859 else
860 {
861 @RenderTheImage(settings, cleanImagePath)
862 }
863 </div>
864 </div>
865
866 if (settings.Caption != null)
867 {
868 <span class="image-caption dw-mod">@settings.Caption</span>
869 @:</div>
870 }
871 }
872 else
873 {
874 if (settings.Caption != null)
875 {
876 @:<div>
877 }
878 if (!string.IsNullOrEmpty(settings.Link))
879 {
880 <a href="@settings.Link">
881 @RenderTheImage(settings, cleanImagePath)
882 </a>
883 }
884 else
885 {
886 @RenderTheImage(settings, cleanImagePath)
887 }
888
889 if (settings.Caption != null)
890 {
891 <span class="image-caption dw-mod">@settings.Caption</span>
892 @:</div>
893 }
894 }
895 }
896
897 @helper RenderTheImage(Image settings, string cleanImagePath)
898 {
899 if (settings != null)
900 {
901 string placeholderImage = "/Files/Images/placeholder.gif";
902 string imageEngine = "/Admin/Public/GetImage.ashx?";
903
904 // CDN
905 var cdnUrl = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetString("CDNUrl");
906 bool cdnActivate = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetBoolean("CDNActivate");
907 if (!string.IsNullOrWhiteSpace(cdnUrl) && cdnActivate)
908 {
909 imageEngine = cdnUrl + imageEngine;
910 }
911
912 string imageStyle = "";
913
914 switch (settings.Style)
915 {
916 case ImageStyle.Ball:
917 imageStyle = "grid__cell-img--ball";
918 break;
919
920 case ImageStyle.Triangle:
921 imageStyle = "grid__cell-img--triangle";
922 break;
923 }
924
925 if (settings.Style == ImageStyle.Ball || settings.Style == ImageStyle.Circle || settings.Style == ImageStyle.Triangle)
926 {
927 settings.ImageDefault.Crop = settings.ImageDefault.Crop == 5 ? settings.ImageDefault.Crop = 0 : settings.ImageDefault.Crop;
928
929 if (settings.ImageDefault != null)
930 {
931 settings.ImageDefault.Height = settings.ImageDefault.Width;
932 }
933 if (settings.ImageMedium != null)
934 {
935 settings.ImageMedium.Height = settings.ImageMedium.Width;
936 }
937 if (settings.ImageSmall != null)
938 {
939 settings.ImageSmall.Height = settings.ImageSmall.Width;
940 }
941 }
942
943 string defaultImage = imageEngine;
944 string imageSmall = "";
945 string imageMedium = "";
946
947 if (settings.DisableImageEngine)
948 {
949 defaultImage = settings.Path;
950 }
951 else
952 {
953 if (settings.ImageDefault != null)
954 {
955 defaultImage += Dynamicweb.Rapido.Services.Images.GetImagePathFromSettings(settings.ImageDefault);
956
957 if (settings.Path.GetType() != typeof(string))
958 {
959 defaultImage += settings.Path != null ? "Image=" + settings.Path.PathUrlEncoded : "";
960 defaultImage += settings.Path != null ? "&" + settings.Path.GetFocalPointParameters() : "";
961 }
962 else
963 {
964 defaultImage += settings.Path != null ? "Image=" + settings.Path : "";
965 }
966 }
967
968 if (settings.ImageSmall != null)
969 {
970 imageSmall = "data-src-small=\"" + imageEngine;
971 imageSmall += Dynamicweb.Rapido.Services.Images.GetImagePathFromSettings(settings.ImageSmall);
972
973 if (settings.Path.GetType() != typeof(string))
974 {
975 imageSmall += settings.Path != null ? "Image=" + settings.Path.PathUrlEncoded : "";
976 imageSmall += settings.Path != null ? "&" + settings.Path.GetFocalPointParameters() : "";
977 }
978 else
979 {
980 imageSmall += settings.Path != null ? "Image=" + settings.Path : "";
981 }
982
983 imageSmall += "\"";
984 }
985
986 if (settings.ImageMedium != null)
987 {
988 imageMedium = "data-src-medium=\"" + imageEngine;
989 imageMedium += Dynamicweb.Rapido.Services.Images.GetImagePathFromSettings(settings.ImageMedium);
990
991 if (settings.Path.GetType() != typeof(string))
992 {
993 imageMedium += settings.Path != null ? "Image=" + settings.Path.PathUrlEncoded : "";
994 imageMedium += settings.Path != null ? "&" + settings.Path.GetFocalPointParameters() : "";
995 }
996 else
997 {
998 imageMedium += settings.Path != null ? "Image=" + settings.Path : "";
999 }
1000
1001 imageMedium += "\"";
1002 }
1003 }
1004
1005 Dictionary<string, string> optionalAttributes = new Dictionary<string, string>();
1006 if (cleanImagePath != null)
1007 {
1008 Dynamicweb.Content.Files.Metadata.Meta metadata = Dynamicweb.Content.Files.Metadata.EditorFactory.GetMetadataForFile(cleanImagePath);
1009 if (metadata != null)
1010 {
1011 string metaDataAlt = metadata.GetValue("alt");
1012 optionalAttributes.Add("alt", metaDataAlt);
1013 }
1014 }
1015 if (!string.IsNullOrEmpty(settings.OnClick)) { optionalAttributes.Add("onclick", settings.OnClick); }
1016 if (!string.IsNullOrEmpty(settings.Title))
1017 {
1018 optionalAttributes.Add("alt", settings.Title);
1019 optionalAttributes.Add("title", settings.Title);
1020 }
1021
1022 if (settings.DisableLazyLoad)
1023 {
1024 <img id="@settings.Id" class="@imageStyle @settings.CssClass dw-mod" src="@defaultImage" @ComponentMethods.AddAttributes(optionalAttributes) @ComponentMethods.AddAttributes(settings.ExtraAttributes) />
1025 }
1026 else
1027 {
1028 <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) />
1029 }
1030 }
1031 }
1032 @using System.Reflection
1033 @using Dynamicweb.Rapido.Blocks.Components.General
1034 @using Dynamicweb.Rapido.Blocks.Components
1035
1036 @* Component *@
1037
1038 @helper RenderFileField(FileField settings)
1039 {
1040 var attributes = new Dictionary<string, string>();
1041 if (string.IsNullOrEmpty(settings.Id))
1042 {
1043 settings.Id = Guid.NewGuid().ToString("N");
1044 }
1045
1046 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); }
1047 if (settings.Disabled) { attributes.Add("disabled", "true"); }
1048 if (settings.Required) { attributes.Add("required", "true"); }
1049 if (settings.Multiple) { attributes.Add("multiple", "true"); }
1050 if (!string.IsNullOrEmpty(settings.Name)) { attributes.Add("name", settings.Name); }
1051 if (string.IsNullOrEmpty(settings.ChooseFileText))
1052 {
1053 settings.ChooseFileText = Translate("Choose file");
1054 }
1055 if (string.IsNullOrEmpty(settings.NoFilesChosenText))
1056 {
1057 settings.NoFilesChosenText = Translate("No files chosen...");
1058 }
1059 if (!string.IsNullOrEmpty(settings.OnClick)) { attributes.Add("onclick", settings.OnClick); }
1060
1061 if (settings.Required && !String.IsNullOrEmpty(settings.Label)) { settings.Label += " <span class=\"required dw-mod\">*</span>"; }
1062
1063 string setValueToFakeInput = "FileUpload.setValueToFakeInput(this)";
1064 attributes.Add("onchange", setValueToFakeInput + (!string.IsNullOrEmpty(settings.OnChange) ? settings.OnChange : ""));
1065
1066 attributes.Add("type", "file");
1067 if (settings.Value != null) { attributes.Add("value", settings.Value); }
1068 settings.CssClass = "u-full-width " + settings.CssClass;
1069
1070 var resultAttributes = attributes.Concat(settings.ExtraAttributes).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.Last().Value);
1071
1072 <div class="form__field-group u-full-width @settings.WrapperCssClass dw-mod">
1073 @if (!string.IsNullOrEmpty(settings.Label))
1074 {
1075 <label for="@settings.Id">@settings.Label</label>
1076 }
1077 @if (!string.IsNullOrEmpty(settings.HelpText))
1078 {
1079 <small class="form__help-text">@settings.HelpText</small>
1080 }
1081
1082 <div class="form__field-combi file-input u-no-margin dw-mod">
1083 <input @ComponentMethods.AddAttributes(resultAttributes) class="file-input__real-input" data-no-files-text="@settings.NoFilesChosenText" data-many-files-text="@Translate("files")" />
1084 <label for="@settings.Id" class="file-input__btn btn--secondary btn dw-mod">@settings.ChooseFileText</label>
1085 <label for="@settings.Id" class="@settings.CssClass file-input__fake-input js-fake-input dw-mod">@settings.NoFilesChosenText</label>
1086 @if (settings.UploadButton != null)
1087 {
1088 settings.UploadButton.CssClass += " btn--condensed u-no-margin";
1089 @Render(settings.UploadButton)
1090 }
1091 </div>
1092 @Render(new NotificationMessage { Message = settings.ErrorMessage })
1093 </div>
1094 }
1095 @using System.Reflection
1096 @using Dynamicweb.Rapido.Blocks.Components.General
1097 @using Dynamicweb.Rapido.Blocks.Components
1098 @using Dynamicweb.Core
1099 @using System.Linq
1100
1101 @* Component *@
1102
1103 @helper RenderDateTimeField(DateTimeField settings)
1104 {
1105 if (string.IsNullOrEmpty(settings.Id))
1106 {
1107 settings.Id = Guid.NewGuid().ToString("N");
1108 }
1109
1110 var textField = new TextField {
1111 Name = settings.Name,
1112 Id = settings.Id,
1113 Label = settings.Label,
1114 HelpText = settings.HelpText,
1115 Value = settings.Value,
1116 Disabled = settings.Disabled,
1117 Required = settings.Required,
1118 ErrorMessage = settings.ErrorMessage,
1119 CssClass = settings.CssClass,
1120 WrapperCssClass = settings.WrapperCssClass,
1121 OnChange = settings.OnChange,
1122 OnClick = settings.OnClick,
1123 ExtraAttributes = settings.ExtraAttributes,
1124 //
1125 Placeholder = settings.Placeholder
1126 };
1127
1128 @Render(textField)
1129
1130 List<string> jsAttributes = new List<string>();
1131
1132 jsAttributes.Add("mode: '" + Enum.GetName(typeof(DateTimeFieldMode), settings.Mode).ToLower() + "'");
1133
1134 if (!string.IsNullOrEmpty(settings.DateFormat))
1135 {
1136 jsAttributes.Add("dateFormat: '" + settings.DateFormat + "'");
1137 }
1138 if (!string.IsNullOrEmpty(settings.MinDate))
1139 {
1140 jsAttributes.Add("minDate: '" + settings.MinDate + "'");
1141 }
1142 if (!string.IsNullOrEmpty(settings.MaxDate))
1143 {
1144 jsAttributes.Add("maxDate: '" + settings.MaxDate + "'");
1145 }
1146 if (settings.IsInline)
1147 {
1148 jsAttributes.Add("inline: " + Converter.ToString(settings.IsInline).ToLower());
1149 }
1150 if (settings.EnableTime)
1151 {
1152 jsAttributes.Add("enableTime: " + Converter.ToString(settings.EnableTime).ToLower());
1153 }
1154 if (settings.EnableWeekNumbers)
1155 {
1156 jsAttributes.Add("weekNumbers: " + Converter.ToString(settings.EnableWeekNumbers).ToLower());
1157 }
1158
1159 jsAttributes.AddRange(settings.GetFlatPickrOptions().Select(x => x.Key + ": " + x.Value));
1160
1161 <script>
1162 document.addEventListener("DOMContentLoaded", function () {
1163 flatpickr("#@textField.Id", {
1164 @string.Join(",", jsAttributes)
1165 });
1166 });
1167 </script>
1168 }
1169 @using System.Reflection
1170 @using Dynamicweb.Rapido.Blocks.Components.General
1171 @using Dynamicweb.Rapido.Blocks.Components
1172
1173 @* Component *@
1174
1175 @helper RenderTextField(TextField settings)
1176 {
1177 var attributes = new Dictionary<string, string>();
1178 if (!string.IsNullOrEmpty(settings.Label) && string.IsNullOrEmpty(settings.Id))
1179 {
1180 settings.Id = Guid.NewGuid().ToString("N");
1181 }
1182
1183 /*base settings*/
1184 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); }
1185 if (!string.IsNullOrEmpty(settings.OnClick)) { attributes.Add("onclick", settings.OnClick); }
1186 if (!string.IsNullOrEmpty(settings.OnChange)) { attributes.Add("onchange", settings.OnChange); }
1187 if (settings.Disabled) { attributes.Add("disabled", "true"); }
1188 if (settings.Required) { attributes.Add("required", "true"); }
1189 if (!string.IsNullOrEmpty(settings.Name)) { attributes.Add("name", settings.Name); }
1190 /*end*/
1191
1192 if (!string.IsNullOrEmpty(settings.OnKeyUp)) { attributes.Add("onkeyup", settings.OnKeyUp); }
1193 if (!string.IsNullOrEmpty(settings.OnInput)) { attributes.Add("oninput", settings.OnInput); }
1194 if (!string.IsNullOrEmpty(settings.OnFocus)) { attributes.Add("onfocus", settings.OnFocus); }
1195 if (settings.ReadOnly) { attributes.Add("readonly", "true"); }
1196 if (settings.MaxLength != 0) { attributes.Add("maxlength", settings.MaxLength.ToString()); }
1197 if (!string.IsNullOrEmpty(settings.Placeholder)) { attributes.Add("placeholder", settings.Placeholder); }
1198 attributes.Add("type", Enum.GetName(typeof(TextFieldType), settings.Type).ToLower());
1199 if (settings.Type == TextFieldType.Password) { attributes.Add("autocomplete", "off"); };
1200 if (settings.Value != null) { attributes.Add("value", settings.Value); }
1201
1202 settings.CssClass = "u-full-width " + settings.CssClass;
1203
1204 if (settings.Required && !String.IsNullOrEmpty(settings.Label)) { settings.Label += " <span class=\"required dw-mod\">*</span>"; }
1205
1206 var resultAttributes = attributes.Concat(settings.ExtraAttributes).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.Last().Value);
1207
1208 string noMargin = "u-no-margin";
1209 if (!settings.ReadOnly) {
1210 noMargin = "";
1211 }
1212
1213 <div class="form__field-group u-full-width @noMargin @settings.WrapperCssClass dw-mod">
1214 @if (!string.IsNullOrEmpty(settings.Label))
1215 {
1216 <label for="@settings.Id">@settings.Label</label>
1217 }
1218 @if (!string.IsNullOrEmpty(settings.HelpText))
1219 {
1220 <small class="form__help-text">@settings.HelpText</small>
1221 }
1222
1223 @if (settings.ActionButton != null)
1224 {
1225 settings.ActionButton.CssClass += " btn--condensed u-no-margin";
1226 <div class="form__field-combi u-no-margin dw-mod">
1227 <input @ComponentMethods.AddAttributes(resultAttributes) class="@settings.CssClass dw-mod" />
1228 @Render(settings.ActionButton)
1229 </div>
1230 }
1231 else
1232 {
1233 <input @ComponentMethods.AddAttributes(resultAttributes) class="@settings.CssClass dw-mod" />
1234 }
1235
1236 @Render(new NotificationMessage { Message = settings.ErrorMessage })
1237 </div>
1238 }
1239 @using System.Reflection
1240 @using Dynamicweb.Rapido.Blocks.Components.General
1241 @using Dynamicweb.Rapido.Blocks.Components
1242
1243 @* Component *@
1244
1245 @helper RenderNumberField(NumberField settings)
1246 {
1247 var attributes = new Dictionary<string, string>();
1248 if (!string.IsNullOrEmpty(settings.Label) && string.IsNullOrEmpty(settings.Id))
1249 {
1250 settings.Id = Guid.NewGuid().ToString("N");
1251 }
1252
1253 /*base settings*/
1254 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); }
1255 if (!string.IsNullOrEmpty(settings.OnClick)) { attributes.Add("onclick", settings.OnClick); }
1256 if (!string.IsNullOrEmpty(settings.OnChange)) { attributes.Add("onchange", settings.OnChange); }
1257 if (settings.Disabled) { attributes.Add("disabled", "true"); }
1258 if (settings.Required) { attributes.Add("required", "true"); }
1259 if (!string.IsNullOrEmpty(settings.Name)) { attributes.Add("name", settings.Name); }
1260 /*end*/
1261
1262 if (!string.IsNullOrEmpty(settings.OnKeyUp)) { attributes.Add("onkeyup", settings.OnKeyUp); }
1263 if (!string.IsNullOrEmpty(settings.OnInput)) { attributes.Add("oninput", settings.OnInput); }
1264 if (!string.IsNullOrEmpty(settings.OnFocus)) { attributes.Add("onfocus", settings.OnFocus); }
1265 if (settings.ReadOnly) { attributes.Add("readonly", "true"); }
1266 if (settings.Max != null) { attributes.Add("max", settings.Max.ToString()); }
1267 if (settings.Min != null) { attributes.Add("min", settings.Min.ToString()); }
1268 if (settings.Step != 0) { attributes.Add("step", settings.Step.ToString()); }
1269 if (settings.Value != null && !string.IsNullOrEmpty(settings.Value.ToString())) { attributes.Add("value", settings.Value.ToString()); }
1270 attributes.Add("type", "number");
1271
1272 var resultAttributes = attributes.Concat(settings.ExtraAttributes).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.Last().Value);
1273
1274 <div class="form__field-group u-full-width @settings.WrapperCssClass dw-mod">
1275 @if (!string.IsNullOrEmpty(settings.Label))
1276 {
1277 <label for="@settings.Id">@settings.Label</label>
1278 }
1279 @if (!string.IsNullOrEmpty(settings.HelpText))
1280 {
1281 <small class="form__help-text">@settings.HelpText</small>
1282 }
1283
1284 @if (settings.ActionButton != null)
1285 {
1286 settings.ActionButton.CssClass += " btn--condensed u-no-margin";
1287 <div class="form__field-combi u-no-margin dw-mod">
1288 <input @ComponentMethods.AddAttributes(resultAttributes) class="@settings.CssClass dw-mod" />
1289 @Render(settings.ActionButton)
1290 </div>
1291 }
1292 else
1293 {
1294 <input @ComponentMethods.AddAttributes(resultAttributes) class="@settings.CssClass dw-mod" />
1295 }
1296
1297 @Render(new NotificationMessage { Message = settings.ErrorMessage })
1298 </div>
1299 }
1300 @using System.Reflection
1301 @using Dynamicweb.Rapido.Blocks.Components.General
1302 @using Dynamicweb.Rapido.Blocks.Components
1303
1304
1305 @* Component *@
1306
1307 @helper RenderTextareaField(TextareaField settings)
1308 {
1309 Dictionary<string, string> attributes = new Dictionary<string, string>();
1310 string id = settings.Id;
1311 if (!string.IsNullOrEmpty(settings.Label) && string.IsNullOrEmpty(id))
1312 {
1313 id = Guid.NewGuid().ToString("N");
1314 }
1315
1316 if (!string.IsNullOrEmpty(id)) { attributes.Add("id", id); }
1317 if (!string.IsNullOrEmpty(settings.OnClick)) { attributes.Add("onclick", settings.OnClick); }
1318 if (!string.IsNullOrEmpty(settings.OnKeyUp)) { attributes.Add("onkeyup", settings.OnKeyUp); }
1319 if (!string.IsNullOrEmpty(settings.OnInput)) { attributes.Add("oninput", settings.OnInput); }
1320 if (!string.IsNullOrEmpty(settings.OnFocus)) { attributes.Add("onfocus", settings.OnFocus); }
1321 if (!string.IsNullOrEmpty(settings.OnChange)) { attributes.Add("onchange", settings.OnChange); }
1322 if (!string.IsNullOrEmpty(settings.Placeholder)) { attributes.Add("placeholder", settings.Placeholder); }
1323 if (settings.Disabled) { attributes.Add("disabled", "true"); }
1324 if (settings.Required) { attributes.Add("required", "true"); }
1325 if (settings.ReadOnly) { attributes.Add("readonly", "true"); }
1326 if (settings.MaxLength != 0) { attributes.Add("maxlength", settings.MaxLength.ToString()); }
1327 if (settings.Rows != 0) { attributes.Add("rows", settings.Rows.ToString()); }
1328 attributes.Add("name", settings.Name);
1329
1330 if (settings.Required && !String.IsNullOrEmpty(settings.Label)) { settings.Label += " <span class=\"required dw-mod\">*</span>"; }
1331
1332 <div class="form__field-group @settings.WrapperCssClass dw-mod">
1333 @if (!string.IsNullOrEmpty(settings.Label))
1334 {
1335 <label for="@id">@settings.Label</label>
1336 }
1337 @if (!string.IsNullOrEmpty(settings.HelpText))
1338 {
1339 <small class="form__help-text">@settings.HelpText</small>
1340 }
1341
1342 <textarea class="u-full-width @settings.CssClass dw-mod" @ComponentMethods.AddAttributes(attributes) @ComponentMethods.AddAttributes(settings.ExtraAttributes)>@settings.Value</textarea>
1343
1344 @Render(new NotificationMessage { Message = settings.ErrorMessage })
1345 </div>
1346 }
1347 @using System.Reflection
1348 @using Dynamicweb.Rapido.Blocks.Components.General
1349 @using Dynamicweb.Rapido.Blocks.Components
1350
1351
1352 @* Component *@
1353
1354 @helper RenderHiddenField(HiddenField settings) {
1355 var attributes = new Dictionary<string, string>();
1356 attributes.Add("type", "hidden");
1357 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); }
1358 if (settings.Value != null) { attributes.Add("value", settings.Value); }
1359 if (!string.IsNullOrEmpty(settings.Name)) { attributes.Add("name", settings.Name); }
1360
1361 <input @ComponentMethods.AddAttributes(attributes) @ComponentMethods.AddAttributes(settings.ExtraAttributes)/>
1362 }
1363 @using System.Reflection
1364 @using Dynamicweb.Rapido.Blocks.Components.General
1365 @using Dynamicweb.Rapido.Blocks.Components
1366
1367 @* Component *@
1368
1369 @helper RenderCheckboxField(CheckboxField settings)
1370 {
1371 var attributes = new Dictionary<string, string>();
1372 if (!string.IsNullOrEmpty(settings.Label) && string.IsNullOrEmpty(settings.Id))
1373 {
1374 settings.Id = Guid.NewGuid().ToString("N");
1375 }
1376
1377 /*base settings*/
1378 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); }
1379 if (!string.IsNullOrEmpty(settings.OnClick)) { attributes.Add("onclick", settings.OnClick); }
1380 if (!string.IsNullOrEmpty(settings.OnChange)) { attributes.Add("onchange", settings.OnChange); }
1381 if (settings.Disabled) { attributes.Add("disabled", "true"); }
1382 if (settings.Required) { attributes.Add("required", "true"); }
1383 if (!string.IsNullOrEmpty(settings.Name)) { attributes.Add("name", settings.Name); }
1384 /*end*/
1385
1386 if (settings.Required && !String.IsNullOrEmpty(settings.Label)) { settings.Label += " <span class=\"required dw-mod\">*</span>"; }
1387
1388 attributes.Add("type", "checkbox");
1389 if (settings.Checked) { attributes.Add("checked", "true"); }
1390 settings.CssClass = "form__control " + settings.CssClass;
1391 if (settings.Value != null) { attributes.Add("value", settings.Value); }
1392
1393 var resultAttributes = attributes.Concat(settings.ExtraAttributes).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.Last().Value);
1394
1395 <div class="form__field-group @settings.WrapperCssClass dw-mod">
1396 <input @ComponentMethods.AddAttributes(resultAttributes) class="@settings.CssClass dw-mod" />
1397 @if (!string.IsNullOrEmpty(settings.Label))
1398 {
1399 <label for="@settings.Id" class="dw-mod">@settings.Label</label>
1400 }
1401 @if (!string.IsNullOrEmpty(settings.HelpText))
1402 {
1403 <small class="form__help-text">@settings.HelpText</small>
1404 }
1405 @Render(new NotificationMessage { Message = settings.ErrorMessage })
1406 </div>
1407 }
1408 @using System.Reflection
1409 @using Dynamicweb.Rapido.Blocks.Components.General
1410 @using Dynamicweb.Rapido.Blocks.Components
1411
1412
1413 @* Component *@
1414
1415 @helper RenderCheckboxListField(CheckboxListField settings)
1416 {
1417 <div class="form__field-group @settings.WrapperCssClass u-margin-bottom dw-mod" @ComponentMethods.AddAttributes(settings.ExtraAttributes)>
1418 @if (!string.IsNullOrEmpty(settings.Label))
1419 {
1420 <label>@settings.Label</label>
1421 }
1422 @if (!string.IsNullOrEmpty(settings.HelpText))
1423 {
1424 <small class="form__help-text">@settings.HelpText</small>
1425 }
1426
1427 @foreach (var item in settings.Options)
1428 {
1429 if (settings.Required)
1430 {
1431 item.Required = true;
1432 }
1433 if (settings.Disabled)
1434 {
1435 item.Disabled = true;
1436 }
1437 if (!string.IsNullOrEmpty(settings.Name))
1438 {
1439 item.Name = settings.Name;
1440 }
1441 if (!string.IsNullOrEmpty(settings.CssClass))
1442 {
1443 item.CssClass += settings.CssClass;
1444 }
1445
1446 /* value is not supported */
1447
1448 if (!string.IsNullOrEmpty(settings.OnClick))
1449 {
1450 item.OnClick += settings.OnClick;
1451 }
1452 if (!string.IsNullOrEmpty(settings.OnChange))
1453 {
1454 item.OnChange += settings.OnChange;
1455 }
1456 @Render(item)
1457 }
1458
1459 @Render(new NotificationMessage { Message = settings.ErrorMessage })
1460 </div>
1461 }
1462 @using Dynamicweb.Rapido.Blocks.Components.General
1463
1464 @* Component *@
1465
1466 @helper RenderSearch(Search settings)
1467 {
1468 var searchValue = HttpContext.Current.Request.QueryString.Get(settings.SearchParameter) ?? "";
1469 var groupValue = HttpContext.Current.Request.QueryString.Get(settings.GroupsParameter) ?? "";
1470
1471 if (string.IsNullOrEmpty(settings.Id))
1472 {
1473 settings.Id = Guid.NewGuid().ToString("N");
1474 }
1475
1476 var resultAttributes = new Dictionary<string, string>();
1477
1478 if (settings.PageSize != 0)
1479 {
1480 resultAttributes.Add("data-page-size", settings.PageSize.ToString());
1481 }
1482 if (!string.IsNullOrEmpty(settings.GroupItemsFeedUrl))
1483 {
1484 resultAttributes.Add("data-groups-feed-url", settings.GroupItemsFeedUrl);
1485 if (!string.IsNullOrEmpty(groupValue))
1486 {
1487 resultAttributes.Add("data-selected-group", groupValue);
1488 }
1489 if (!string.IsNullOrEmpty(settings.GroupsParameter))
1490 {
1491 resultAttributes.Add("data-groups-parameter", settings.GroupsParameter);
1492 }
1493 }
1494 resultAttributes.Add("data-force-init", "true");
1495 if (settings.GoToFirstSearchResultOnEnter)
1496 {
1497 resultAttributes.Add("data-go-to-first-search-result-on-enter", settings.GoToFirstSearchResultOnEnter.ToString().ToLower());
1498 }
1499 if (!string.IsNullOrEmpty(settings.SearchParameter))
1500 {
1501 resultAttributes.Add("data-search-parameter", settings.SearchParameter);
1502 }
1503 resultAttributes.Add("data-search-feed-url", settings.SearchData.SearchFeedUrl);
1504 resultAttributes.Add("data-results-template-id", settings.SearchData.ResultsTemplateId);
1505
1506 if (settings.SecondSearchData != null)
1507 {
1508 resultAttributes.Add("data-second-search-feed-url", settings.SecondSearchData.SearchFeedUrl);
1509 resultAttributes.Add("data-second-results-template-id", settings.SecondSearchData.ResultsTemplateId);
1510 }
1511 if (!string.IsNullOrEmpty(settings.ResultsPageUrl))
1512 {
1513 resultAttributes.Add("data-results-page-url", settings.ResultsPageUrl);
1514 }
1515
1516 resultAttributes = resultAttributes.Concat(settings.ExtraAttributes).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.Last().Value);
1517
1518 string searchFieldCss = (settings.SearchButton == null) ? "search--with-icon" : "";
1519
1520 <div class="search @settings.CssClass @searchFieldCss js-search-data-source dw-mod" id="@settings.Id" @ComponentMethods.AddAttributes(resultAttributes)>
1521 @if (!string.IsNullOrEmpty(settings.GroupItemsFeedUrl))
1522 {
1523 <button type="button" class="search__groups-btn dw-mod js-search-groups-btn">@Translate("All")</button>
1524 <ul class="dropdown dropdown--absolute-position dw-mod search__groups-results js-search-groups-list"></ul>
1525 }
1526
1527 <input type="text" class="search__field dw-mod js-search-field" placeholder="@settings.Placeholder" value="@searchValue">
1528
1529 <div class="dropdown dropdown--absolute-position search__results dw-mod js-search-results @(settings.SecondSearchData != null ? "search__results--combined" : "")">
1530 @if (settings.SecondSearchData != null)
1531 {
1532 <div class="search__column search__column--products dw-mod">
1533 <div class="search__column-header dw-mod">@Translate("Products")</div>
1534 <ul class="search__results-list dw-mod js-search-results-list" id="@(settings.Id)_ResultsList"></ul>
1535 @if (!string.IsNullOrEmpty(settings.SearchData.ResultsPageUrl))
1536 {
1537 @Render(new Link {
1538 Title = Translate("View all"),
1539 CssClass = "js-view-all-button u-margin",
1540 Href = settings.SearchData.ResultsPageUrl
1541 });
1542 }
1543 </div>
1544 <div class="search__column search__column--pages dw-mod">
1545 <div class="search__column-header">@Translate("Pages")</div>
1546 <ul class="search__results-list dw-mod js-search-results-second-list" id="@(settings.Id)_SecondResultsList"></ul>
1547 @if (!string.IsNullOrEmpty(settings.SecondSearchData.ResultsPageUrl))
1548 {
1549 @Render(new Link
1550 {
1551 Title = Translate("View all"),
1552 CssClass = "js-view-all-button u-margin",
1553 Href = settings.SecondSearchData.ResultsPageUrl
1554 });
1555 }
1556 </div>
1557 }
1558 else
1559 {
1560 <div class="search__column search__column--only dw-mod">
1561 <ul class="search__results-list dw-mod js-search-results-list" id="@(settings.Id)_ResultsList"></ul>
1562 @if (!string.IsNullOrEmpty(settings.SearchData.ResultsPageUrl))
1563 {
1564 @Render(new Link {
1565 Title = Translate("View all"),
1566 CssClass = "js-view-all-button u-margin",
1567 Href = settings.SearchData.ResultsPageUrl
1568 });
1569 }
1570 </div>
1571 }
1572 </div>
1573
1574 @if (settings.SearchButton != null)
1575 {
1576 settings.SearchButton.CssClass += " search__btn js-search-btn";
1577 if (settings.RenderDefaultSearchIcon)
1578 {
1579 settings.SearchButton.Icon = new Icon { Name = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("SearchIcon").SelectedValue };
1580 }
1581 @Render(settings.SearchButton);
1582 }
1583 </div>
1584 }
1585 @using System.Reflection
1586 @using Dynamicweb.Rapido.Blocks.Components.General
1587 @using Dynamicweb.Rapido.Blocks.Components
1588
1589
1590 @* Component *@
1591
1592 @helper RenderSelectField(SelectField settings)
1593 {
1594 if (!string.IsNullOrEmpty(settings.Label) && string.IsNullOrEmpty(settings.Id))
1595 {
1596 settings.Id = Guid.NewGuid().ToString("N");
1597 }
1598
1599 <div class="form__field-group u-full-width @settings.WrapperCssClass dw-mod">
1600 @if (!string.IsNullOrEmpty(settings.Label))
1601 {
1602 <label for="@settings.Id">@settings.Label</label>
1603 }
1604 @if (!string.IsNullOrEmpty(settings.HelpText))
1605 {
1606 <small class="form__help-text">@settings.HelpText</small>
1607 }
1608
1609 @if (settings.ActionButton != null)
1610 {
1611 settings.ActionButton.CssClass += " btn--condensed u-no-margin";
1612 <div class="form__field-combi u-no-margin dw-mod">
1613 @RenderSelectBase(settings)
1614 @Render(settings.ActionButton)
1615 </div>
1616 }
1617 else
1618 {
1619 @RenderSelectBase(settings)
1620 }
1621
1622 @Render(new NotificationMessage { Message = settings.ErrorMessage })
1623 </div>
1624 }
1625
1626 @helper RenderSelectBase(SelectField settings)
1627 {
1628 var attributes = new Dictionary<string, string>();
1629
1630 /*base settings*/
1631 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); }
1632 if (!string.IsNullOrEmpty(settings.OnClick)) { attributes.Add("onclick", settings.OnClick); }
1633 if (!string.IsNullOrEmpty(settings.OnChange)) { attributes.Add("onchange", settings.OnChange); }
1634 if (settings.Disabled) { attributes.Add("disabled", "true"); }
1635 if (settings.Required) { attributes.Add("required", "true"); }
1636 if (!string.IsNullOrEmpty(settings.Name)) { attributes.Add("name", settings.Name); }
1637 /*end*/
1638
1639 var resultAttributes = attributes.Concat(settings.ExtraAttributes).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.Last().Value);
1640
1641 <select @ComponentMethods.AddAttributes(resultAttributes) class="u-full-width @settings.CssClass dw-mod">
1642 @if (settings.Default != null)
1643 {
1644 @Render(settings.Default)
1645 }
1646
1647 @foreach (var item in settings.Options)
1648 {
1649 if (settings.Value != null) {
1650 item.Checked = item.Value == settings.Value;
1651 }
1652 @Render(item)
1653 }
1654 </select>
1655 }
1656 @using System.Reflection
1657 @using Dynamicweb.Rapido.Blocks.Components.General
1658 @using Dynamicweb.Rapido.Blocks.Components
1659
1660 @* Component *@
1661
1662 @helper RenderRadioButtonField(RadioButtonField settings)
1663 {
1664 var attributes = new Dictionary<string, string>();
1665 if (!string.IsNullOrEmpty(settings.Label) && string.IsNullOrEmpty(settings.Id))
1666 {
1667 settings.Id = Guid.NewGuid().ToString("N");
1668 }
1669
1670 /*base settings*/
1671 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); }
1672 if (!string.IsNullOrEmpty(settings.OnClick)) { attributes.Add("onclick", settings.OnClick); }
1673 if (!string.IsNullOrEmpty(settings.OnChange)) { attributes.Add("onchange", settings.OnChange); }
1674 if (settings.Disabled) { attributes.Add("disabled", "true"); }
1675 if (settings.Required) { attributes.Add("required", "true"); }
1676 if (!string.IsNullOrEmpty(settings.Name)) { attributes.Add("name", settings.Name); }
1677 /*end*/
1678
1679 attributes.Add("type", "radio");
1680 if (settings.Checked) { attributes.Add("checked", "true"); }
1681 settings.CssClass = "form__control " + settings.CssClass;
1682 if (settings.Value != null) { attributes.Add("value", settings.Value); }
1683
1684 var resultAttributes = attributes.Concat(settings.ExtraAttributes).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.Last().Value);
1685
1686 <div class="form__field-group @settings.WrapperCssClass dw-mod">
1687 <input @ComponentMethods.AddAttributes(resultAttributes) class="@settings.CssClass dw-mod" />
1688 @if (!string.IsNullOrEmpty(settings.Label))
1689 {
1690 <label for="@settings.Id" class="dw-mod">@settings.Label</label>
1691 }
1692 @if (!string.IsNullOrEmpty(settings.HelpText))
1693 {
1694 <small class="form__help-text">@settings.HelpText</small>
1695 }
1696 @Render(new NotificationMessage { Message = settings.ErrorMessage })
1697 </div>
1698 }
1699 @using System.Reflection
1700 @using Dynamicweb.Rapido.Blocks.Components.General
1701 @using Dynamicweb.Rapido.Blocks.Components
1702
1703
1704 @* Component *@
1705
1706 @helper RenderRadioButtonListField(RadioButtonListField settings)
1707 {
1708 if (settings.Required && !String.IsNullOrEmpty(settings.Label)) { settings.Label += " <span class=\"required dw-mod\">*</span>"; }
1709
1710 <div class="form__field-group @settings.WrapperCssClass u-margin-bottom dw-mod" @ComponentMethods.AddAttributes(settings.ExtraAttributes)>
1711 @if (!string.IsNullOrEmpty(settings.Label))
1712 {
1713 <label>@settings.Label</label>
1714 }
1715 @if (!string.IsNullOrEmpty(settings.HelpText))
1716 {
1717 <small class="form__help-text">@settings.HelpText</small>
1718 }
1719
1720 @foreach (var item in settings.Options)
1721 {
1722 if (settings.Required)
1723 {
1724 item.Required = true;
1725 }
1726 if (settings.Disabled)
1727 {
1728 item.Disabled = true;
1729 }
1730 if (!string.IsNullOrEmpty(settings.Name))
1731 {
1732 item.Name = settings.Name;
1733 }
1734 if (settings.Value != null && settings.Value == item.Value)
1735 {
1736 item.Checked = true;
1737 }
1738 if (!string.IsNullOrEmpty(settings.OnClick))
1739 {
1740 item.OnClick += settings.OnClick;
1741 }
1742 if (!string.IsNullOrEmpty(settings.OnChange))
1743 {
1744 item.OnChange += settings.OnChange;
1745 }
1746 if (!string.IsNullOrEmpty(settings.CssClass))
1747 {
1748 item.CssClass += settings.CssClass;
1749 }
1750 @Render(item)
1751 }
1752
1753 @Render(new NotificationMessage { Message = settings.ErrorMessage })
1754 </div>
1755 }
1756 @using System.Reflection
1757 @using Dynamicweb.Rapido.Blocks.Components.General
1758 @using Dynamicweb.Rapido.Blocks.Components
1759
1760
1761 @* Component *@
1762
1763 @helper RenderNotificationMessage(NotificationMessage settings)
1764 {
1765 if (!string.IsNullOrEmpty(settings.Message))
1766 {
1767 var attributes = new Dictionary<string, string>();
1768 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); }
1769
1770 string messageTypeClass = Enum.GetName(typeof(NotificationMessageType), settings.MessageType).ToLower();
1771 <div class="field-@messageTypeClass @settings.CssClass u-full-width dw-mod" @ComponentMethods.AddAttributes(attributes)>@settings.Message</div>
1772 }
1773 }
1774 @using Dynamicweb.Rapido.Blocks.Components.General
1775
1776
1777 @* Component *@
1778
1779 @helper RenderHandlebarsRoot(HandlebarsRoot settings) {
1780 string preRender = !String.IsNullOrEmpty(settings.PreRenderScriptTemplate) ? "data-pre-render-template=\"" + settings.PreRenderScriptTemplate + "\"" : "";
1781
1782 <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>
1783 @if (settings.SubBlocks != null) {
1784 @RenderBlockList(settings.SubBlocks)
1785 }
1786 </div>
1787 }
1788 @using System.Reflection
1789 @using Dynamicweb.Rapido.Blocks.Components.General
1790 @using Dynamicweb.Rapido.Blocks.Components
1791 @using System.Text.RegularExpressions
1792
1793
1794 @* Component *@
1795
1796 @helper RenderSticker(Sticker settings) {
1797 if (!String.IsNullOrEmpty(settings.Title)) {
1798 string size = settings.Size.ToString() != "None" ? "" + "stickers-container__tag--" + settings.Size.ToString().ToLower() : "";
1799 string style = settings.Style.ToString() != "None" ? "" + "stickers-container__tag--" + settings.Style.ToString().ToLower() : "";
1800
1801 Dictionary<String, String> optionalAttributes = new Dictionary<string, string>();
1802 if (!String.IsNullOrEmpty(settings.Color) || !String.IsNullOrEmpty(settings.BackgroundColor)) {
1803 string styleTag = !String.IsNullOrEmpty(settings.Color) ? "color: " + settings.Color + "; " : "";
1804 styleTag += !String.IsNullOrEmpty(settings.BackgroundColor) ? "background-color: " + settings.BackgroundColor + "; " : "";
1805 optionalAttributes.Add("style", styleTag);
1806 }
1807
1808 <div class="stickers-container__tag @size @style @settings.CssClass dw-mod" @ComponentMethods.AddAttributes(optionalAttributes) @ComponentMethods.AddAttributes(settings.ExtraAttributes)>@settings.Title</div>
1809 }
1810 }
1811
1812 @using System.Reflection
1813 @using Dynamicweb.Rapido.Blocks.Components.General
1814 @using Dynamicweb.Rapido.Blocks.Components
1815
1816
1817 @* Component *@
1818
1819 @helper RenderStickersCollection(StickersCollection settings)
1820 {
1821 if (settings.Stickers.Count > 0)
1822 {
1823 string position = "stickers-container--" + Regex.Replace(settings.Position.ToString(), "([a-z])([A-Z])", "$1-$2").ToLower();
1824
1825 <div class="stickers-container @position @settings.CssClass dw-mod" @ComponentMethods.AddAttributes(settings.ExtraAttributes)>
1826 @foreach (Sticker sticker in settings.Stickers)
1827 {
1828 @Render(sticker)
1829 }
1830 </div>
1831 }
1832 }
1833
1834 @using Dynamicweb.Rapido.Blocks.Components.General
1835
1836
1837 @* Component *@
1838
1839 @helper RenderForm(Form settings) {
1840 if (settings != null)
1841 {
1842 Dictionary<string, string> optionalAttributes = new Dictionary<string, string>();
1843 if (!string.IsNullOrEmpty(settings.Action)) { optionalAttributes.Add("action", settings.Action); };
1844 if (!string.IsNullOrEmpty(settings.Name)) { optionalAttributes.Add("name", settings.Name); };
1845 if (!string.IsNullOrEmpty(settings.OnSubmit)) { optionalAttributes.Add("onsubmit", settings.OnSubmit); };
1846 var enctypes = new Dictionary<string, string>
1847 {
1848 { "multipart", "multipart/form-data" },
1849 { "text", "text/plain" },
1850 { "application", "application/x-www-form-urlencoded" }
1851 };
1852 if (settings.Enctype != FormEnctype.none) { optionalAttributes.Add("enctype", enctypes[Enum.GetName(typeof(FormEnctype), settings.Enctype).ToLower()]); };
1853 optionalAttributes.Add("method", settings.Method.ToString());
1854
1855 if (!string.IsNullOrEmpty(settings.FormStartMarkup))
1856 {
1857 @settings.FormStartMarkup
1858 }
1859 else
1860 {
1861 @:<form class="@settings.CssClass u-no-margin dw-mod" @ComponentMethods.AddAttributes(optionalAttributes) @ComponentMethods.AddAttributes(settings.ExtraAttributes)>
1862 }
1863
1864 foreach (var field in settings.GetFields())
1865 {
1866 @Render(field)
1867 }
1868
1869 @:</form>
1870 }
1871 }
1872 @using System.Reflection
1873 @using Dynamicweb.Rapido.Blocks.Components.General
1874 @using Dynamicweb.Rapido.Blocks.Components
1875
1876
1877 @* Component *@
1878
1879 @helper RenderText(Text settings)
1880 {
1881 @settings.Content
1882 }
1883 @using System.Reflection
1884 @using Dynamicweb.Rapido.Blocks.Components.General
1885 @using Dynamicweb.Rapido.Blocks.Components
1886
1887
1888 @* Component *@
1889
1890 @helper RenderContentModule(ContentModule settings) {
1891 if (!string.IsNullOrEmpty(settings.Content))
1892 {
1893 @settings.Content
1894 }
1895 }
1896 @using System.Reflection
1897 @using Dynamicweb.Rapido.Blocks.Components.General
1898 @using Dynamicweb.Rapido.Blocks.Components
1899
1900
1901 @* Component *@
1902
1903 @helper RenderModal(Modal settings) {
1904 if (settings != null)
1905 {
1906 string modalId = !string.IsNullOrEmpty(settings.Id) ? settings.Id : Guid.NewGuid().ToString("N");
1907
1908 string onchange = !string.IsNullOrEmpty(settings.OnClose) ? "onchange=\"if(!this.checked){" + settings.OnClose + "}\"" : "";
1909
1910 <input type="checkbox" id="@(modalId)ModalTrigger" class="modal-trigger" @onchange />
1911
1912 <div class="modal-container">
1913 @if (!settings.DisableDarkOverlay)
1914 {
1915 <label for="@(modalId)ModalTrigger" id="@(modalId)ModalOverlay" class="modal-overlay"></label>
1916 }
1917 <div class="modal modal--@settings.Width.ToString().ToLower() modal-height--@settings.Height.ToString().ToLower()" id="@(modalId)Modal">
1918 @if (settings.Heading != null)
1919 {
1920 if (!string.IsNullOrEmpty(settings.Heading.Title))
1921 {
1922 <div class="modal__header">
1923 @Render(settings.Heading)
1924 </div>
1925 }
1926 }
1927 <div class="modal__body @(settings.Width.ToString().ToLower() == "full" ? "modal__body--full" : "")">
1928 @if (!string.IsNullOrEmpty(settings.BodyText))
1929 {
1930 @settings.BodyText
1931 }
1932 @if (settings.BodyTemplate != null)
1933 {
1934 @settings.BodyTemplate
1935 }
1936 @{
1937 var actions = settings.GetActions();
1938 }
1939 </div>
1940 @if (actions.Length > 0)
1941 {
1942 <div class="modal__footer">
1943 @foreach (var action in actions)
1944 {
1945 if (Pageview.Device.ToString() != "Mobile") {
1946 action.CssClass += " u-no-margin";
1947 } else {
1948 action.CssClass += " u-full-width u-margin-bottom";
1949 }
1950
1951 @Render(action)
1952 }
1953 </div>
1954 }
1955 <label class="modal__close-btn js-modal-close-btn" for="@(modalId)ModalTrigger"></label>
1956 </div>
1957 </div>
1958 }
1959 }
1960 @using Dynamicweb.Rapido.Blocks.Components.General
1961
1962 @* Component *@
1963
1964 @helper RenderMediaListItem(MediaListItem settings)
1965 {
1966 <div class="media-list-item @settings.CssClass dw-mod" @(!string.IsNullOrEmpty(settings.Id) ? "id=\"" + settings.Id + "\"" : "")>
1967 @if (!string.IsNullOrEmpty(settings.Label))
1968 {
1969 if (!string.IsNullOrEmpty(settings.Link))
1970 {
1971 @Render(new Link
1972 {
1973 Href = settings.Link,
1974 CssClass = "media-list-item__sticker dw-mod",
1975 ButtonLayout = ButtonLayout.None,
1976 Title = settings.Label,
1977 OnClick = !string.IsNullOrEmpty(settings.OnClick) ? settings.OnClick : ""
1978 })
1979 }
1980 else if (!string.IsNullOrEmpty(settings.OnClick))
1981 {
1982 <span class="media-list-item__sticker dw-mod" onclick="@(settings.OnClick)">
1983 <span class="u-uppercase">@settings.Label</span>
1984 </span>
1985 }
1986 else
1987 {
1988 <span class="media-list-item__sticker media-list-item__sticker--no-link dw-mod">
1989 <span class="u-uppercase">@settings.Label</span>
1990 </span>
1991 }
1992 }
1993 <div class="media-list-item__wrap">
1994 <div class="media-list-item__info dw-mod">
1995 <div class="media-list-item__header dw-mod">
1996 @if (!string.IsNullOrEmpty(settings.Title))
1997 {
1998 if (!string.IsNullOrEmpty(settings.Link))
1999 {
2000 @Render(new Link
2001 {
2002 Href = settings.Link,
2003 CssClass = "media-list-item__name dw-mod",
2004 ButtonLayout = ButtonLayout.None,
2005 Title = settings.Title,
2006 OnClick = !string.IsNullOrEmpty(settings.OnClick) ? settings.OnClick : ""
2007 })
2008 }
2009 else if (!string.IsNullOrEmpty(settings.OnClick))
2010 {
2011 <span class="media-list-item__name dw-mod" onclick="@(settings.OnClick)">@settings.Title</span>
2012 }
2013 else
2014 {
2015 <span class="media-list-item__name media-list-item__name--no-link dw-mod">@settings.Title</span>
2016 }
2017 }
2018
2019 @if (!string.IsNullOrEmpty(settings.Status))
2020 {
2021 <div class="media-list-item__state dw-mod">@settings.Status</div>
2022 }
2023 </div>
2024 @{
2025 settings.InfoTable.CssClass += " media-list-item__parameters-table";
2026 }
2027
2028 @Render(settings.InfoTable)
2029 </div>
2030 <div class="media-list-item__actions dw-mod">
2031 <div class="media-list-item__actions-list dw-mod">
2032 @{
2033 var actions = settings.GetActions();
2034
2035 foreach (ButtonBase action in actions)
2036 {
2037 action.ButtonLayout = ButtonLayout.None;
2038 action.CssClass += " media-list-item__action link";
2039
2040 @Render(action)
2041 }
2042 }
2043 </div>
2044
2045 @if (settings.SelectButton != null && !string.IsNullOrEmpty(settings.SelectButton.Title))
2046 {
2047 settings.SelectButton.CssClass += " u-no-margin";
2048
2049 <div class="media-list-item__action-button">
2050 @Render(settings.SelectButton)
2051 </div>
2052 }
2053 </div>
2054 </div>
2055 </div>
2056 }
2057 @using Dynamicweb.Rapido.Blocks.Components.General
2058 @using Dynamicweb.Rapido.Blocks.Components
2059
2060 @helper RenderTable(Table settings)
2061 {
2062 Dictionary<string, string> attributes = new Dictionary<string, string>();
2063 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); }
2064
2065 var enumToClasses = new Dictionary<TableDesign, string>
2066 {
2067 { TableDesign.Clean, "table--clean" },
2068 { TableDesign.Bordered, "table--bordered" },
2069 { TableDesign.Striped, "table--striped" },
2070 { TableDesign.Hover, "table--hover" },
2071 { TableDesign.Compact, "table--compact" },
2072 { TableDesign.Condensed, "table--condensed" },
2073 { TableDesign.NoTopBorder, "table--no-top-border" }
2074 };
2075 string tableDesignClass = "";
2076 if (settings.Design != TableDesign.None)
2077 {
2078 tableDesignClass = enumToClasses[settings.Design];
2079 }
2080
2081 if (!string.IsNullOrEmpty(settings.CssClass) || settings.Design != TableDesign.None) { attributes.Add("class", "table " + tableDesignClass + " " + settings.CssClass + " dw-mod"); }
2082
2083 var resultAttributes = attributes.Concat(settings.ExtraAttributes).GroupBy(d => d.Key).ToDictionary(d => d.Key, d => d.Last().Value);
2084
2085 <table @ComponentMethods.AddAttributes(resultAttributes)>
2086 @if (settings.Header != null)
2087 {
2088 <thead>
2089 @Render(settings.Header)
2090 </thead>
2091 }
2092 <tbody>
2093 @foreach (var row in settings.Rows)
2094 {
2095 @Render(row)
2096 }
2097 </tbody>
2098 @if (settings.Footer != null)
2099 {
2100 <tfoot>
2101 @Render(settings.Footer)
2102 </tfoot>
2103 }
2104 </table>
2105 }
2106 @using Dynamicweb.Rapido.Blocks.Components.General
2107 @using Dynamicweb.Rapido.Blocks.Components
2108
2109 @helper RenderTableRow(TableRow settings)
2110 {
2111 Dictionary<string, string> attributes = new Dictionary<string, string>();
2112 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); }
2113
2114 var enumToClasses = new Dictionary<TableRowDesign, string>
2115 {
2116 { TableRowDesign.NoBorder, "table__row--no-border" },
2117 { TableRowDesign.Border, "table__row--border" },
2118 { TableRowDesign.TopBorder, "table__row--top-line" },
2119 { TableRowDesign.BottomBorder, "table__row--bottom-line" },
2120 { TableRowDesign.Solid, "table__row--solid" }
2121 };
2122
2123 string tableRowDesignClass = "";
2124 if (settings.Design != TableRowDesign.None)
2125 {
2126 tableRowDesignClass = enumToClasses[settings.Design];
2127 }
2128
2129 if (!string.IsNullOrEmpty(settings.CssClass) || settings.Design != TableRowDesign.None) { attributes.Add("class", "table__row " + tableRowDesignClass + " " + settings.CssClass + " dw-mod"); }
2130
2131 var resultAttributes = attributes.Concat(settings.ExtraAttributes).GroupBy(d => d.Key).ToDictionary(d => d.Key, d => d.Last().Value);
2132
2133 <tr @ComponentMethods.AddAttributes(resultAttributes)>
2134 @foreach (var cell in settings.Cells)
2135 {
2136 if (settings.IsHeaderRow)
2137 {
2138 cell.IsHeader = true;
2139 }
2140 @Render(cell)
2141 }
2142 </tr>
2143 }
2144 @using Dynamicweb.Rapido.Blocks.Components.General
2145 @using Dynamicweb.Rapido.Blocks.Components
2146 @using Dynamicweb.Core
2147
2148 @helper RenderTableCell(TableCell settings)
2149 {
2150 Dictionary<string, string> attributes = new Dictionary<string, string>();
2151 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); }
2152 if (settings.Colspan != 0) { attributes.Add("colspan", Converter.ToString(settings.Colspan)); }
2153 if (settings.Rowspan != 0) { attributes.Add("rowspan", Converter.ToString(settings.Rowspan)); }
2154 if (!string.IsNullOrEmpty(settings.CssClass)) { attributes.Add("class", settings.CssClass + " dw-mod"); }
2155
2156 var resultAttributes = attributes.Concat(settings.ExtraAttributes).GroupBy(d => d.Key).ToDictionary(d => d.Key, d => d.Last().Value);
2157
2158 string tagName = settings.IsHeader ? "th" : "td";
2159
2160 @("<" + tagName + " " + ComponentMethods.AddAttributes(resultAttributes) + ">")
2161 @settings.Content
2162 @("</" + tagName + ">");
2163 }
2164 @using System.Linq
2165 @using Dynamicweb.Rapido.Blocks.Components.General
2166
2167 @* Component *@
2168
2169 @helper RenderPagination(Dynamicweb.Rapido.Blocks.Components.General.Pagination settings)
2170 {
2171 var pageNumberQueryStringName = Dynamicweb.Rapido.Services.Pagination.GetPageNumberQueryStringName(settings); // Get the proper 'page number' query string parameter
2172 var queryParameters = Dynamicweb.Rapido.Services.Url.GetQueryParameters(pageNumberQueryStringName); // Get the NameValueCollection from the querystring
2173
2174 if (settings.NumberOfPages > 1)
2175 {
2176 string url = HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority) + "/Default.aspx";
2177 string ariaLabel = !string.IsNullOrWhiteSpace(settings.AriaLabel) ? settings.AriaLabel : Translate("Page navigation");
2178 Dictionary<string, int> startAndEndPageNumber = Dynamicweb.Rapido.Services.Pagination.GetStartAndEndPageNumber(settings);
2179
2180 <div class="pager u-margin-top dw-mod @settings.CssClass" aria-label="@ariaLabel">
2181 @if (settings.ShowPagingInfo)
2182 {
2183 <div class="pager__info dw-mod">
2184 @Translate("Page") @settings.CurrentPageNumber @Translate("of") @settings.NumberOfPages
2185 </div>
2186 }
2187 <ul class="pager__list dw-mod">
2188 @if (!string.IsNullOrWhiteSpace(settings.FirstPageUrl) && settings.ShowFirstAndLastControls)
2189 {
2190 @Render(new PaginationItem { Link = settings.FirstPageUrl, Icon = settings.FirstIcon })
2191 }
2192 @if (!string.IsNullOrWhiteSpace(settings.PreviousPageUrl) && settings.ShowNextAndPrevControls)
2193 {
2194 @Render(new PaginationItem { Link = settings.PreviousPageUrl, Icon = settings.PrevIcon })
2195 }
2196 @if (settings.GetPages().Any())
2197 {
2198 foreach (var page in settings.GetPages())
2199 {
2200 @Render(page)
2201 }
2202 }
2203 else
2204 {
2205 for (var page = startAndEndPageNumber["StartPage"]; page <= startAndEndPageNumber["EndPage"]; page++)
2206 {
2207 queryParameters = Dynamicweb.Rapido.Services.Url.UpdateQueryStringParameter(queryParameters, pageNumberQueryStringName, page.ToString());
2208 @Render(new PaginationItem { Label = page.ToString(), Link = Dynamicweb.Rapido.Services.Url.BuildUri(url, queryParameters).PathAndQuery, IsActive = (settings.CurrentPageNumber == page) });
2209 }
2210 }
2211 @if (!string.IsNullOrWhiteSpace(settings.NextPageUrl) && settings.ShowNextAndPrevControls)
2212 {
2213 @Render(new PaginationItem { Link = settings.NextPageUrl, Icon = settings.NextIcon })
2214 }
2215 @if (!string.IsNullOrWhiteSpace(settings.LastPageUrl) && settings.ShowFirstAndLastControls)
2216 {
2217 @Render(new PaginationItem { Link = settings.LastPageUrl, Icon = settings.LastIcon })
2218 }
2219 </ul>
2220 </div>
2221 }
2222 }
2223
2224 @helper RenderPaginationItem(PaginationItem settings)
2225 {
2226 if (settings.Icon == null)
2227 {
2228 settings.Icon = new Icon();
2229 }
2230
2231 settings.Icon.Label = settings.Label;
2232 <li class="pager__btn dw-mod">
2233 @if (settings.IsActive)
2234 {
2235 <span class="pager__num pager__num--current dw-mod">
2236 @Render(settings.Icon)
2237 </span>
2238 }
2239 else
2240 {
2241 <a href="@settings.Link" class="pager__num dw-mod">
2242 @Render(settings.Icon)
2243 </a>
2244 }
2245 </li>
2246 }
2247
2248
2249 @using Dynamicweb.Rapido.Blocks.Components.General
2250 @using Dynamicweb.Rapido.Blocks.Components.Ecommerce
2251
2252
2253 @using Dynamicweb.Frontend
2254 @using System.Reflection
2255 @using Dynamicweb.Content.Items
2256 @using System.Web.UI.HtmlControls
2257 @using Dynamicweb.Rapido.Blocks.Components
2258 @using Dynamicweb.Rapido.Blocks
2259 @using Dynamicweb.Rapido.Blocks.Components.Articles
2260
2261 @* Components for the articles *@
2262 @using System.Reflection
2263 @using Dynamicweb.Rapido.Blocks.Components.Articles
2264
2265
2266 @* Component for the articles *@
2267
2268 @helper RenderArticleBanner(dynamic settings) {
2269 string filterClasses = "image-filter image-filter--darken";
2270 settings.Layout = ArticleHeaderLayout.Banner;
2271
2272 if (settings.Image != null)
2273 {
2274 if (settings.Image.Path != null)
2275 {
2276 <section class="multiple-paragraphs-container u-color-light paragraph-container--full-width">
2277 <div class="background-image @filterClasses dw-mod">
2278 <div class="background-image__wrapper @filterClasses dw-mod">
2279 @{
2280 settings.Image.CssClass += "background-image__cover dw-mod";
2281 }
2282 @Render(settings.Image)
2283 </div>
2284 </div>
2285 <div class="center-container dw-mod">
2286 <div class="grid">
2287 <div class="grid__col-md-8 grid__col-xs-12 paragraph-container paragraph-container--height-lg">
2288 <div class="u-left-middle">
2289 <div>
2290 @if (!String.IsNullOrEmpty(settings.Heading))
2291 {
2292 <h1 class="article__header article__header--giant dw-mod" style="color: @settings.TextColor">@settings.Heading</h1>
2293 }
2294 @if (!String.IsNullOrEmpty(settings.Subheading))
2295 {
2296 <div class="article__leadtext dw-mod" style="color: @settings.TextColor">@settings.Subheading</div>
2297 }
2298 @if (!String.IsNullOrEmpty(settings.Author) || !String.IsNullOrEmpty(settings.Date))
2299 {
2300 <small class="article__post-info u-margin-bottom--lg dw-mod" style="color: @settings.TextColor">@settings.Author @settings.Date</small>
2301 }
2302 @if (!String.IsNullOrEmpty(settings.Link)) {
2303 <div class="grid__cell">
2304 @Render(new Link { Href = settings.Link, Title = settings.LinkText, ButtonLayout = settings.ButtonLayout })
2305 </div>
2306 }
2307 </div>
2308 </div>
2309 </div>
2310 @if (settings.ExternalParagraphId != 0)
2311 {
2312 <div class="grid__col-md-4 grid__col-sm-12 grid__col-xs-12 paragraph-container paragraph-container--height-auto dw-mod">
2313 <div class="u-color-light-gray--bg u-color-dark dw-mod">
2314 @RenderParagraphContent(settings.ExternalParagraphId)
2315 </div>
2316 </div>
2317 }
2318
2319 </div>
2320 </div>
2321 </section>
2322 if (!String.IsNullOrEmpty(settings.Image.Caption)) {
2323 <div class="image-caption dw-mod">@settings.Image.Caption</div>
2324 }
2325 }
2326 else
2327 {
2328 settings.Layout = ArticleHeaderLayout.Clean;
2329 @RenderArticleCleanHeader(settings);
2330 }
2331 }
2332 else
2333 {
2334 settings.Layout = ArticleHeaderLayout.Clean;
2335 @RenderArticleCleanHeader(settings);
2336 }
2337 }
2338 @using System.Reflection
2339 @using Dynamicweb.Rapido.Blocks.Components
2340 @using Dynamicweb.Rapido.Blocks.Components.General
2341 @using Dynamicweb.Rapido.Blocks.Components.Articles
2342 @using Dynamicweb.Rapido.Blocks
2343
2344
2345 @* Component for the articles *@
2346
2347 @helper RenderArticleHeader(ArticleHeader settings) {
2348 dynamic[] methodParameters = new dynamic[1];
2349 methodParameters[0] = settings;
2350 MethodInfo customMethod = this.GetType().GetMethod("RenderArticleHeaderCustom");
2351
2352 if (customMethod != null)
2353 {
2354 @customMethod.Invoke(this, methodParameters).ToString();
2355 } else {
2356 switch (settings.Layout)
2357 {
2358 case ArticleHeaderLayout.Clean:
2359 @RenderArticleCleanHeader(settings);
2360 break;
2361 case ArticleHeaderLayout.Split:
2362 @RenderArticleSplitHeader(settings);
2363 break;
2364 case ArticleHeaderLayout.Banner:
2365 @RenderArticleBannerHeader(settings);
2366 break;
2367 case ArticleHeaderLayout.Overlay:
2368 @RenderArticleOverlayHeader(settings);
2369 break;
2370 default:
2371 @RenderArticleCleanHeader(settings);
2372 break;
2373 }
2374 }
2375 }
2376
2377 @helper RenderArticleCleanHeader(ArticleHeader settings) {
2378 dynamic[] methodParameters = new dynamic[1];
2379 methodParameters[0] = settings;
2380 MethodInfo customMethod = this.GetType().GetMethod("RenderArticleCleanHeaderCustom");
2381
2382 if (customMethod != null)
2383 {
2384 @customMethod.Invoke(this, methodParameters).ToString();
2385 }
2386 else
2387 {
2388 string contentColumns = settings.TextLayout != ArticleHeaderTextLayout.Full ? "8" : "12";
2389
2390 <div class="grid grid--align-content-start grid--justify-start">
2391 <div class="grid__col-md-@contentColumns grid__col-sm-12 u-padding--lg dw-mod">
2392 @if (!String.IsNullOrEmpty(settings.Category) || !String.IsNullOrEmpty(settings.Author) || !String.IsNullOrEmpty(settings.Date) || settings.RatingOutOf != 0)
2393 {
2394 <div class="u-border-bottom u-padding-bottom">
2395 @if (!String.IsNullOrEmpty(settings.Category))
2396 {
2397 <div class="u-pull--left">
2398 <div class="article__category dw-mod" style="color: @settings.CategoryColor">@settings.Category</div>
2399 </div>
2400 }
2401 <div class="u-pull--right">
2402 @if (!String.IsNullOrEmpty(settings.Author) || !String.IsNullOrEmpty(settings.Date))
2403 {
2404 <small class="article__post-info dw-mod">@settings.Author @settings.Date</small>
2405 }
2406 @if (settings.RatingOutOf != 0)
2407 {
2408 @Render(new Rating { Score = settings.RatingScore, OutOf = settings.RatingOutOf })
2409 }
2410 </div>
2411 </div>
2412 }
2413
2414 <div class="grid__cell">
2415 @if (!String.IsNullOrEmpty(settings.Heading))
2416 {
2417 <h1 class="article__header article__header--giant dw-mod">@settings.Heading</h1>
2418 }
2419 @if (settings.Image != null)
2420 {
2421 if (settings.Image.Path != null)
2422 {
2423 <div class="u-padding-bottom--lg">
2424 @Render(settings.Image)
2425 </div>
2426 }
2427 }
2428 @if (!String.IsNullOrEmpty(settings.Subheading))
2429 {
2430 <div class="article__leadtext dw-mod">@settings.Subheading</div>
2431 }
2432 @if (!String.IsNullOrEmpty(settings.Link))
2433 {
2434 <div class="grid__cell">
2435 @Render(new Link { Href = settings.Link, Title = settings.LinkText, ButtonLayout = settings.ButtonLayout })
2436 </div>
2437 }
2438 </div>
2439 </div>
2440 @if (settings.ExternalParagraphId != 0)
2441 {
2442 <div class="grid__col-md-4 grid__col-sm-12 u-padding--lg u-color-light-gray--bg dw-mod">
2443 @RenderParagraphContent(settings.ExternalParagraphId)
2444 </div>
2445 }
2446 </div>
2447 }
2448 }
2449
2450 @helper RenderArticleSplitHeader(ArticleHeader settings) {
2451 dynamic[] methodParameters = new dynamic[1];
2452 methodParameters[0] = settings;
2453 MethodInfo customMethod = this.GetType().GetMethod("RenderArticleSplitHeaderCustom");
2454
2455 if (customMethod != null)
2456 {
2457 @customMethod.Invoke(this, methodParameters).ToString();
2458 }
2459 else
2460 {
2461 string headerColumnWidth = settings.ExternalParagraphId != 0 ? "4" : "6";
2462
2463 if (settings.Image != null)
2464 {
2465 if (settings.Image.Path != null)
2466 {
2467 <section class="multiple-paragraphs-container paragraph-container--full-width">
2468 <div class="grid">
2469 <div class="grid__col-md-@headerColumnWidth grid__col-sm-12 grid__col-xs-12 paragraph-container paragraph-container--height-xl dw-mod">
2470 <div class="u-left-middle u-padding--lg">
2471 <div>
2472 @if (!String.IsNullOrEmpty(settings.Category))
2473 {
2474 <div class="article__category dw-mod" style="color: @settings.CategoryColor">@settings.Category</div>
2475 }
2476 @if (!String.IsNullOrEmpty(settings.Heading))
2477 {
2478 <h1 class="article__header article__header--giant dw-mod">@settings.Heading</h1>
2479 }
2480 @if (!String.IsNullOrEmpty(settings.Subheading))
2481 {
2482 <div class="article__leadtext dw-mod">@settings.Subheading</div>
2483 }
2484 @if (!String.IsNullOrEmpty(settings.Author) || !String.IsNullOrEmpty(settings.Date))
2485 {
2486 <small class="article__post-info u-pull--left dw-mod">@settings.Author @settings.Date</small>
2487 }
2488 @if (settings.RatingOutOf != 0)
2489 {
2490 <div class="u-pull--right">
2491 @Render(new Rating { Score = settings.RatingScore, OutOf = settings.RatingOutOf })
2492 </div>
2493 }
2494 @if (!String.IsNullOrEmpty(settings.Link)) {
2495 <div class="u-full-width u-pull--left u-margin-top">
2496 @Render(new Link { Href = settings.Link, Title = settings.LinkText, ButtonLayout = settings.ButtonLayout })
2497 </div>
2498 }
2499 </div>
2500 </div>
2501 </div>
2502 <div class="grid__col-md-@headerColumnWidth grid__col-sm-12 grid__col-xs-12 paragraph-container paragraph-container--height-auto dw-mod" style="background-image:url(/Admin/Public/GetImage.ashx?width=1800&height=1100&crop=0&Compression=85&DoNotUpscale=true&image=@settings.Image.Path); background-position: center center; background-size: cover;"></div>
2503 @if (settings.ExternalParagraphId != 0)
2504 {
2505 <div class="grid__col-md-4 grid__col-sm-12 grid__col-xs-12 paragraph-container paragraph-container--height-auto u-color-light-gray--bg dw-mod">
2506 @RenderParagraphContent(settings.ExternalParagraphId)
2507 </div>
2508 }
2509 </div>
2510 </section>
2511 }
2512 }
2513 else
2514 {
2515 @RenderArticleCleanHeader(settings);
2516 }
2517 }
2518 }
2519
2520 @helper RenderArticleOverlayHeader(ArticleHeader settings) {
2521 dynamic[] methodParameters = new dynamic[1];
2522 methodParameters[0] = settings;
2523 MethodInfo customMethod = this.GetType().GetMethod("RenderArticleOverlayHeaderCustom");
2524
2525 if (customMethod != null)
2526 {
2527 @customMethod.Invoke(this, methodParameters).ToString();
2528 }
2529 else
2530 {
2531 string contentColumns = settings.TextLayout != ArticleHeaderTextLayout.Full ? "8" : "12";
2532 string contentAlignment = settings.TextLayout == ArticleHeaderTextLayout.Center ? "grid--justify-center" : "";
2533
2534 if (settings.Image != null)
2535 {
2536 if (settings.Image.Path != null)
2537 {
2538 if (settings.ExternalParagraphId == 0)
2539 {
2540 <section class="multiple-paragraphs-container u-color-light paragraph-container--full-width">
2541 <div class="background-image image-filter image-filter--darken dw-mod">
2542 <div class="background-image__wrapper image-filter image-filter--darken dw-mod">
2543 @{
2544 settings.Image.CssClass += "background-image__cover dw-mod";
2545 }
2546 @Render(settings.Image)
2547 </div>
2548 </div>
2549 <div class="center-container dw-mod">
2550 <div class="grid @contentAlignment">
2551 <div class="grid__col-md-@contentColumns grid__col-xs-12 paragraph-container paragraph-container--height-xl u-no-padding dw-mod">
2552 @if (!String.IsNullOrEmpty(settings.Heading))
2553 {
2554 <h1 class="article__header article__header--giant u-padding-top--lg dw-mod" style="color: @settings.TextColor">@settings.Heading</h1>
2555 }
2556 @if (!String.IsNullOrEmpty(settings.Subheading))
2557 {
2558 <div class="article__leadtext dw-mod" style="color: @settings.TextColor">@settings.Subheading</div>
2559 }
2560 <div class="u-margin-top">
2561 @if (!String.IsNullOrEmpty(settings.Author) || !String.IsNullOrEmpty(settings.Date))
2562 {
2563 <small class="article__post-info u-pull--left dw-mod" style="color: @settings.TextColor">@settings.Author @settings.Date</small>
2564 }
2565 @if (settings.RatingOutOf != 0)
2566 {
2567 <div class="u-pull--right">
2568 @Render(new Rating { Score = settings.RatingScore, OutOf = settings.RatingOutOf })
2569 </div>
2570 }
2571 </div>
2572 @if (!String.IsNullOrEmpty(settings.Link))
2573 {
2574 <div class="grid__cell">
2575 @Render(new Link { Href = settings.Link, Title = settings.LinkText, ButtonLayout = settings.ButtonLayout })
2576 </div>
2577 }
2578 </div>
2579 </div>
2580 </div>
2581 </section>
2582 }
2583 else
2584 {
2585 @RenderArticleBanner(settings);
2586 }
2587 }
2588 }
2589 else
2590 {
2591 @RenderArticleCleanHeader(settings);
2592 }
2593 }
2594 }
2595
2596 @helper RenderArticleBannerHeader(dynamic settings) {
2597 dynamic[] methodParameters = new dynamic[1];
2598 methodParameters[0] = settings;
2599 MethodInfo customMethod = this.GetType().GetMethod("RenderArticleBannerHeaderCustom");
2600
2601 if (customMethod != null)
2602 {
2603 @customMethod.Invoke(this, methodParameters).ToString();
2604 }
2605 else
2606 {
2607 @RenderArticleBanner(settings);
2608 }
2609 }
2610 @using System.Reflection
2611 @using System.Text.RegularExpressions;
2612 @using Dynamicweb.Frontend
2613 @using Dynamicweb.Content.Items
2614 @using Dynamicweb.Rapido.Blocks.Components
2615 @using Dynamicweb.Rapido.Blocks.Components.Articles
2616 @using Dynamicweb.Rapido.Blocks
2617
2618 @using Dynamicweb.Content.Items;
2619 @using Dynamicweb.Core
2620
2621 @functions {
2622 public class Author
2623 {
2624 public string Name;
2625 public string Image;
2626 public string Description;
2627 public string Date;
2628 }
2629
2630 public Author GetAuthor(Item item = null)
2631 {
2632 var author = new Author();
2633
2634 var pageView = Dynamicweb.Frontend.PageView.Current();
2635 var currPageItem = Dynamicweb.Content.Services.Pages.GetPage(pageView.ID)?.Item;
2636
2637 if (currPageItem == null) return null;
2638
2639 var authorItem = item ?? Item.GetItemById("AuthorItem", Converter.ToString(currPageItem["SpAuthor"]));
2640
2641 if (authorItem == null || authorItem["Author"] == null) return null;
2642
2643 var authorUrl = Converter.ToString(authorItem["Author"]);
2644 var authorDate = Converter.ToDateTime(authorItem["Date"]);
2645
2646 if (string.IsNullOrWhiteSpace(authorUrl)) return null;
2647
2648 var authorPageId = authorUrl.Contains("=") ? Converter.ToInt32(authorUrl.Substring(authorUrl.LastIndexOf('=') + 1)) : Converter.ToInt32(authorUrl);
2649 var authorPage = Dynamicweb.Content.Services.Pages.GetPage(authorPageId);
2650
2651 if (authorPage == null) return null;
2652
2653 var imgPrefix = "/Admin/Public/GetImage.ashx?width=200&height=200&Compression=99&Quality=99&Format=Webp&Crop=5&image=";
2654
2655 author.Name = authorPage.GetDisplayName();
2656 author.Image = imgPrefix + Converter.ToString(authorPage.Item["Image"]);
2657 author.Description = Converter.ToString(authorPage.Item["Description"]);
2658
2659 if (string.IsNullOrWhiteSpace(Converter.ToString(authorItem["Date"]))) return author;
2660
2661 var month = pageView.Area.CultureInfo.DateTimeFormat.GetMonthName(authorDate.Month);
2662 author.Date = $"{authorDate.Day}. {month} {authorDate.Year}";
2663
2664 return author;
2665 }
2666 }
2667
2668 @* Component for the articles *@
2669
2670 @helper RenderArticleBodyRow(ArticleBodyRow settings)
2671 {
2672 string position = settings.TopLayout == "overlay" ? "article__overlay-offset" : "";
2673 string contentAlignment = settings.TextLayout == "center" ? "grid--justify-center" : "";
2674 var author = GetAuthor();
2675
2676 if (author != null)
2677 {
2678 <div class="author-container">
2679 <div class="author">
2680 <p class="author-desc">@author.Description</p>
2681 <div class="author-wrapper">
2682 <img src="@author.Image" class="author-img" alt="@HttpUtility.HtmlAttributeEncode(author.Name)" />
2683 <div class="author-info">
2684 <span class="author-name">@author.Name</span>
2685 <span class="author-divider @(string.IsNullOrWhiteSpace(author.Date) ? "u-hidden" : "")">|</span>
2686 <span class="author-date">@author.Date</span>
2687 </div>
2688 </div>
2689 </div>
2690 </div>
2691 }
2692
2693 <div class="grid grid--align-content-start @contentAlignment @position dw-mod">
2694 @RenderBlockList(settings.SubBlocks)
2695 </div>
2696 }
2697 @using System.Reflection
2698 @using Dynamicweb.Rapido.Blocks.Components
2699 @using Dynamicweb.Rapido.Blocks.Components.General
2700 @using Dynamicweb.Rapido.Blocks.Components.Articles
2701 @using Dynamicweb.Rapido.Blocks
2702
2703 @* Component for the articles *@
2704
2705 @helper RenderArticleImage(ArticleImage settings)
2706 {
2707 if (settings.Image != null)
2708 {
2709 if (settings.Image.Path != null)
2710 {
2711 <div class="u-margin-bottom--lg">
2712 @Render(settings.Image)
2713 </div>
2714 }
2715 }
2716 }
2717 @using System.Reflection
2718 @using Dynamicweb.Rapido.Blocks.Components
2719 @using Dynamicweb.Rapido.Blocks.Components.Articles
2720
2721
2722 @* Component for the articles *@
2723
2724 @helper RenderArticleSubHeader(ArticleSubHeader settings)
2725 {
2726 if (!String.IsNullOrEmpty(settings.Title))
2727 {
2728 <h2 class="article__header">@settings.Title</h2>
2729 }
2730 }
2731 @using System.Reflection
2732 @using Dynamicweb.Rapido.Blocks.Components
2733 @using Dynamicweb.Rapido.Blocks.Components.Articles
2734 @using Dynamicweb.Rapido.Blocks
2735
2736
2737 @* Component for the articles *@
2738
2739 @helper RenderArticleText(ArticleText settings)
2740 {
2741 if (!String.IsNullOrEmpty(settings.Text))
2742 {
2743 string greatTextClass = settings.EnableLargeText == true ? "article__paragraph--great-text" : "";
2744
2745 <div class="article__paragraph @greatTextClass">
2746 @settings.Text
2747 </div>
2748 }
2749 }
2750 @using System.Reflection
2751 @using Dynamicweb.Rapido.Blocks.Components
2752 @using Dynamicweb.Rapido.Blocks.Components.Articles
2753 @using Dynamicweb.Rapido.Blocks
2754
2755
2756 @* Component for the articles *@
2757
2758 @helper RenderArticleQuote(ArticleQuote settings)
2759 {
2760 string text = Regex.Replace(settings.Text, "<.*?>", String.Empty);
2761
2762 <div class="grid u-padding-bottom--lg">
2763 @if (settings.Image != null)
2764 {
2765 if (settings.Image.Path != null) {
2766 <div class="grid__col-3">
2767 <div class="grid__cell-img">
2768 @{
2769 settings.Image.Title = !String.IsNullOrEmpty(settings.Image.Title) ? settings.Image.Title : settings.Author;
2770 settings.Image.CssClass += " article__image article__image--ball";
2771 settings.Image.ImageDefault.Width = 200;
2772 settings.Image.ImageDefault.Height = 200;
2773 }
2774 @Render(settings.Image)
2775 </div>
2776 </div>
2777 }
2778 }
2779 <div class="grid__col-auto">
2780 @if (!String.IsNullOrEmpty(settings.Text))
2781 {
2782 <div class="article__quote dw-mod">
2783 <i class="fas fa-quote-right u-margin-bottom--lg"></i>
2784 @settings.Text
2785 <i class="fas fa-quote-right"></i>
2786 </div>
2787 }
2788 @if (!String.IsNullOrEmpty(settings.Author))
2789 {
2790 <div class="article__quote-author dw-mod">
2791 - @settings.Author
2792 </div>
2793 }
2794 </div>
2795 </div>
2796 }
2797 @using System.Reflection
2798 @using Dynamicweb.Rapido.Blocks.Components
2799 @using Dynamicweb.Rapido.Blocks.Components.Articles
2800 @using Dynamicweb.Rapido.Blocks
2801
2802 @* Component for the articles *@
2803
2804 @helper RenderArticleInfoTable(ArticleInfoTable settings)
2805 {
2806 <table class="table table--clean">
2807 @foreach (var row in settings.Rows)
2808 {
2809 string iconColor = row.IconColor != null ? row.IconColor : "u-brand-color-two";
2810
2811 <tr>
2812 @if (!String.IsNullOrEmpty(row.Icon))
2813 {
2814 <td class="u-w32px"><i class="@row.Icon fa-2x @row.IconColor"></i></td>
2815 }
2816 <td class="u-no-margin-on-p-elements">
2817 <div class="u-bold">@row.Title</div>
2818 @if (!String.IsNullOrEmpty(row.SubTitle))
2819 {
2820 if (row.Link == null)
2821 {
2822 <div>@row.SubTitle</div>
2823 }
2824 else
2825 {
2826 <a href="@row.Link" class="u-color-inherit">@row.SubTitle</a>
2827 }
2828 }
2829 </td>
2830 </tr>
2831 }
2832 </table>
2833 }
2834 @using System.Reflection
2835 @using Dynamicweb.Rapido.Blocks.Components
2836 @using Dynamicweb.Rapido.Blocks.Components.General
2837 @using Dynamicweb.Rapido.Blocks.Components.Articles
2838 @using Dynamicweb.Rapido.Blocks
2839
2840 @* Component for the articles *@
2841
2842 @helper RenderArticleGalleryModal(ArticleGalleryModal settings)
2843 {
2844 Modal galleryModal = new Modal
2845 {
2846 Id = "ParagraphGallery",
2847 Width = ModalWidth.Full,
2848 BodyTemplate = RenderArticleGalleryModalContent()
2849 };
2850
2851 @Render(galleryModal)
2852 }
2853
2854 @helper RenderArticleGalleryModalContent() {
2855 <div class="modal__image-min-size-wrapper">
2856 @Render(new Image {
2857 Id = "ParagraphGallery",
2858 Path = "#",
2859 CssClass = "modal--full__img",
2860 DisableLazyLoad = true,
2861 DisableImageEngine = true
2862 })
2863 </div>
2864
2865 <div class="modal__images-counter" id="ParagraphGallery_counter"></div>
2866
2867 @Render(new Button {
2868 Id = "ParagraphGallery_prev",
2869 ButtonType = ButtonType.Button,
2870 ButtonLayout = ButtonLayout.None,
2871 CssClass = "modal__prev-btn",
2872 Icon = new Icon { Prefix = "far", Name = "fa-angle-left", LabelPosition = IconLabelPosition.After },
2873 OnClick = "Gallery.prevImage('ParagraphGallery')"
2874 })
2875
2876 @Render(new Button {
2877 Id = "ParagraphGallery_next",
2878 ButtonType = ButtonType.Button,
2879 ButtonLayout = ButtonLayout.None,
2880 CssClass = "modal__next-btn",
2881 Icon = new Icon { Prefix = "far", Name = "fa-angle-right", LabelPosition = IconLabelPosition.After },
2882 OnClick = "Gallery.nextImage('ParagraphGallery')"
2883 })
2884 }
2885 @using System.Reflection
2886 @using Dynamicweb.Rapido.Blocks.Components
2887 @using Dynamicweb.Rapido.Blocks.Components.Articles
2888 @using Dynamicweb.Rapido.Blocks
2889
2890
2891 @* Component for the articles *@
2892
2893 @helper RenderArticleRelated(ArticleRelated settings)
2894 {
2895 string cardClass = Pageview.Device.ToString() != "Tablet" ? "card u-color-light--bg u-full-height" : "";
2896 string cardFooterClass = Pageview.Device.ToString() != "Tablet" ? "card-footer u-color-light--bg" : "";
2897
2898 <section class="multiple-paragraphs-container u-color-light-gray--bg paragraph-container--full-width">
2899 <div class="center-container dw-mod">
2900 <div class="grid u-padding">
2901 <div class="grid__col-md-12 grid__col-xs-12">
2902 <h2 class="article__header u-no-margin u-margin-top">@settings.Title</h2>
2903 </div>
2904 </div>
2905
2906 <div class="js-handlebars-root u-padding" id="@settings.Title.Replace(" ", String.Empty)" data-template="RelatedSimpleTemplate" data-json-feed="/Default.aspx?ID=@settings.FeedPageId&@settings.Query&ExcludeItemID=@settings.CurrentPageId&PageSize=@settings.PageSize"></div>
2907
2908 <script id="RelatedSimpleTemplate" type="text/x-template">
2909 {{#.}}
2910 <div class="grid u-padding-bottom--lg">
2911 {{#Cases}}
2912 <div class="grid__col-lg-3 grid__col-sm-6 image-hover--zoom dw-mod">
2913 <a href="{{link}}" class="u-full-height u-color-light--bg">
2914 {{#if image}}
2915 <div class="u-color-light--bg u-no-padding dw-mod">
2916 <div class="flex-img image-hover__wrapper">
2917 <img class="b-lazy" src="/Files/Images/placeholder.gif" data-src="/Admin/Public/GetImage.ashx?width=680&height=314&crop=1&DoNotUpscale=True&Compression=75&image={{image}}" alt="{{title}}" />
2918 </div>
2919 </div>
2920 {{/if}}
2921
2922 <div class="card u-color-light--bg dw-mod">
2923 <h3 class="article-list__item-header u-truncate-text dw-mod">{{title}}</h3>
2924 <p class="article__short-summary dw-mod">{{summary}}</p>
2925 </div>
2926 </a>
2927 </div>
2928 {{/Cases}}
2929 </div>
2930 {{/.}}
2931 </script>
2932 </div>
2933 </section>
2934 }
2935 @using System.Reflection
2936 @using Dynamicweb.Rapido.Blocks.Components
2937 @using Dynamicweb.Rapido.Blocks.Components.Articles
2938 @using Dynamicweb.Rapido.Blocks
2939
2940
2941 @* Component for the articles *@
2942
2943 @helper RenderArticleMenu(ArticleMenu settings)
2944 {
2945 if (!String.IsNullOrEmpty(settings.Title)) {
2946 <div class="u-margin u-border-bottom">
2947 <h3 class="u-no-margin">@settings.Title</h3>
2948 </div>
2949 }
2950
2951 <ul class="menu-left u-margin-bottom dw-mod">
2952 @foreach (var item in settings.Items)
2953 {
2954 @Render(item)
2955 }
2956 </ul>
2957 }
2958
2959 @helper RenderArticleMenuItem(ArticleMenuItem settings)
2960 {
2961 string link = !String.IsNullOrEmpty(settings.Link) ? settings.Link : "#";
2962
2963 if (!String.IsNullOrEmpty(settings.Title)) {
2964 <li class="menu-left__item dw-mod">
2965 <a href="@link" onclick="@settings.OnClick" class="menu-left__link dw-mod">@settings.Title</a>
2966 </li>
2967 }
2968 }
2969 @using System.Reflection
2970 @using Dynamicweb.Rapido.Blocks.Components
2971 @using Dynamicweb.Rapido.Blocks.Components.Articles
2972 @using Dynamicweb.Rapido.Blocks
2973
2974 @* Component for the articles *@
2975
2976 @helper RenderArticleList(ArticleList settings)
2977 {
2978 if (Pageview != null)
2979 {
2980 bool isParagraph = Pageview.CurrentParagraph != null ? true : false;
2981 string[] sortArticlesListBy = new string[2];
2982
2983 if (isParagraph) {
2984 sortArticlesListBy = Pageview.CurrentParagraph.Item["SortArticlesListBy"] != null && !string.IsNullOrEmpty(Pageview.CurrentParagraph.Item["SortArticlesListBy"].ToString()) ? Pageview.CurrentParagraph.Item["SortArticlesListBy"].ToString().Split('+') : new string[] { "Date", "ASC" };
2985 }
2986 else {
2987 sortArticlesListBy = Pageview.Item["SortArticlesListBy"] != null && !string.IsNullOrEmpty(Pageview.Item["SortArticlesListBy"].ToString()) ? Pageview.Item["SortArticlesListBy"].ToString().Split('+') : new string[] { "Date", "ASC" };
2988 }
2989
2990 string sourcePage = settings.SourcePage != null ? settings.SourcePage : Pageview.ID.ToString();
2991
2992 if (!settings.DisablePagination) {
2993 @RenderItemList(new
2994 {
2995 ItemType = !String.IsNullOrEmpty(settings.ItemType) ? settings.ItemType : "DynamicArticle",
2996 ListSourceType = settings.SourceType,
2997 ListSourcePage = sourcePage,
2998 ItemFieldsList = "*",
2999 Filter = settings.Filter,
3000 ListOrderBy = sortArticlesListBy[0],
3001 ListOrderByDirection = sortArticlesListBy[1],
3002 ListSecondOrderBy = sortArticlesListBy[0] == "Date" ? "InFocusSortId" : "Date",
3003 ListSecondOrderByDirection = "ASC",
3004 IncludeAllChildItems = true,
3005 ListTemplate = settings.Template,
3006 ListPageSize = settings.PageSize.ToString()
3007 });
3008 } else {
3009 @RenderItemList(new
3010 {
3011 ItemType = !String.IsNullOrEmpty(settings.ItemType) ? settings.ItemType : "DynamicArticle",
3012 ListSourceType = settings.SourceType,
3013 ListSourcePage = sourcePage,
3014 ItemFieldsList = "*",
3015 Filter = settings.Filter,
3016 ListOrderBy = sortArticlesListBy[0],
3017 ListOrderByDirection = sortArticlesListBy[1],
3018 ListSecondOrderBy = sortArticlesListBy[0] == "Date" ? "InFocusSortId" : "Date",
3019 ListSecondOrderByDirection = "ASC",
3020 IncludeAllChildItems = true,
3021 ListTemplate = settings.Template,
3022 ListPageSize = settings.PageSize.ToString(),
3023 ListViewMode = "Partial",
3024 ListShowTo = settings.PageSize + 1
3025 });
3026 }
3027 }
3028 }
3029 @using System.Reflection
3030 @using Dynamicweb.Rapido.Blocks.Components.Articles
3031
3032
3033 @* Component for the articles *@
3034
3035 @helper RenderArticleSummary(ArticleSummary settings)
3036 {
3037 if (!String.IsNullOrEmpty(settings.Text))
3038 {
3039 <div class="article__summary dw-mod">@settings.Text</div>
3040 }
3041 }
3042 @using System.Reflection
3043 @using Dynamicweb.Rapido.Blocks.Components
3044 @using Dynamicweb.Rapido.Blocks.Components.Articles
3045 @using Dynamicweb.Rapido.Blocks
3046
3047 @* Component for the articles *@
3048
3049 @helper RenderArticleListCategoryFilter(ArticleListCategoryFilter settings)
3050 {
3051 string pageId = Pageview.ID.ToString();
3052 string selectedFilter = !String.IsNullOrEmpty(HttpContext.Current.Request.QueryString.Get("sourcePage")) ? HttpContext.Current.Request.QueryString.Get("sourcePage") : Translate("All");
3053 var query = HttpUtility.ParseQueryString(HttpContext.Current.Request.QueryString.ToString());
3054
3055 foreach (var option in settings.Categories)
3056 {
3057 selectedFilter = selectedFilter == option.Value ? option.Key : selectedFilter;
3058 }
3059
3060 if (selectedFilter == pageId)
3061 {
3062 selectedFilter = Translate("All");
3063 }
3064
3065 if (Pageview.Device.ToString() != "Mobile" && Pageview.Device.ToString() != "Tablet")
3066 {
3067 <div class="u-pull--right u-margin-left">
3068 <div class="collection u-no-margin">
3069 <h5>@Translate("Category")</h5>
3070 <input type="checkbox" id="CategorySelector" class="dropdown-trigger" />
3071 <div class="dropdown u-w180px dw-mod">
3072 <label class="dropdown__header dropdown__btn dw-mod" for="CategorySelector">@Translate(selectedFilter)</label>
3073 <div class="dropdown__content dw-mod">
3074 @foreach (var option in settings.Categories)
3075 {
3076 <div class="dropdown__item" onclick="QueryArray.setParametersInCurrentURL({ sourceType: 'Page', sourcePage: '@(option.Key.ToLower() == "all" ? pageId : option.Value)' })">@Translate(option.Key)</div>
3077 }
3078 </div>
3079 <label class="dropdown-trigger-off" for="CategorySelector"></label>
3080 </div>
3081 </div>
3082 </div>
3083 }
3084 else
3085 {
3086 <div class="u-full-width u-margin-bottom">
3087 <h5 class="u-no-margin">@Translate("Category")</h5>
3088 <input type="checkbox" id="CategorySelector" class="dropdown-trigger" />
3089 <div class="dropdown u-full-width dw-mod">
3090 <label class="dropdown__header dropdown__btn dw-mod" for="CategorySelector">@Translate(selectedFilter)</label>
3091 <div class="dropdown__content dw-mod">
3092 @foreach (var option in settings.Categories)
3093 {
3094 <div class="dropdown__item" onclick="QueryArray.setParametersInCurrentURL({ sourceType: 'Page', sourcePage: '@(option.Key.ToLower() == "all" ? pageId : option.Value)' })">@Translate(option.Key)</div>
3095 }
3096 </div>
3097 <label class="dropdown-trigger-off" for="CategorySelector"></label>
3098 </div>
3099 </div>
3100 }
3101 }
3102 @using System.Reflection
3103 @using Dynamicweb.Rapido.Blocks.Components
3104 @using Dynamicweb.Rapido.Blocks.Components.Articles
3105 @using Dynamicweb.Rapido.Blocks
3106 @using System.Collections.Generic
3107
3108 @* Component for the articles *@
3109
3110 @helper RenderArticleListFilter(ArticleListFilter settings)
3111 {
3112 string selectedFilter = !String.IsNullOrEmpty(HttpContext.Current.Request.QueryString.Get(settings.SystemName)) ? HttpContext.Current.Request.QueryString.Get(settings.SystemName) : Translate("All");
3113 var query = HttpUtility.ParseQueryString(HttpContext.Current.Request.QueryString.ToString());
3114
3115 if (settings.Options != null)
3116 {
3117 if (settings.Options is IEnumerable<dynamic>)
3118 {
3119 var options = (IEnumerable<dynamic>) settings.Options;
3120 settings.Options = options.OrderBy(item => item.Name);
3121 }
3122
3123 foreach (var option in settings.Options)
3124 {
3125 selectedFilter = selectedFilter == option.Value ? option.Name : selectedFilter;
3126 }
3127
3128 if (Pageview.Device.ToString() != "Mobile" && Pageview.Device.ToString() != "Tablet")
3129 {
3130 <div class="u-pull--right u-margin-left">
3131 <div class="collection u-no-margin">
3132 <h5>@settings.Label</h5>
3133 <input type="checkbox" id="@(settings.SystemName)Selector" class="dropdown-trigger" />
3134 <div class="dropdown u-w180px dw-mod">
3135 <label class="dropdown__header dropdown__btn dw-mod" for="@(settings.SystemName)Selector">@Translate(selectedFilter)</label>
3136 <div class="dropdown__content dw-mod">
3137 <div class="dropdown__item" onclick="QueryArray.setParameterInCurrentURL('@settings.SystemName', '')">@Translate("All")</div>
3138 @foreach (var option in settings.Options)
3139 {
3140 <div class="dropdown__item" onclick="QueryArray.setParameterInCurrentURL('@settings.SystemName', '@option.Value')">@Translate(option.Name)</div>
3141 }
3142 </div>
3143 <label class="dropdown-trigger-off" for="@(settings.SystemName)Selector"></label>
3144 </div>
3145 </div>
3146 </div>
3147 }
3148 else
3149 {
3150 <div class="u-full-width u-margin-bottom">
3151 <h5 class="u-no-margin">@settings.Label</h5>
3152 <input type="checkbox" id="@(settings.SystemName)Selector" class="dropdown-trigger" />
3153 <div class="dropdown u-full-width w-mod">
3154 <label class="dropdown__header dropdown__btn dw-mod" for="@(settings.SystemName)Selector">@Translate(selectedFilter)</label>
3155 <div class="dropdown__content dw-mod">
3156 <div class="dropdown__item" onclick="QueryArray.setParameterInCurrentURL('@settings.SystemName', '')">@Translate("All")</div>
3157 @foreach (var option in settings.Options)
3158 {
3159 <div class="dropdown__item" onclick="QueryArray.setParameterInCurrentURL('@settings.SystemName', '@option.Value')">@Translate(option.Name)</div>
3160 }
3161 </div>
3162 <label class="dropdown-trigger-off" for="@(settings.SystemName)Selector"></label>
3163 </div>
3164 </div>
3165 }
3166 }
3167 }
3168 @using System.Reflection
3169 @using Dynamicweb.Rapido.Blocks.Components
3170 @using Dynamicweb.Rapido.Blocks.Components.Articles
3171 @using Dynamicweb.Rapido.Blocks
3172
3173 @* Component for the articles *@
3174
3175 @helper RenderArticleListSearch(ArticleListSearch settings)
3176 {
3177 string searchParameter = !string.IsNullOrEmpty(settings.SearchParameter) ? settings.SearchParameter : "Title";
3178 string searchWord = HttpContext.Current.Request.QueryString.Get(searchParameter);
3179 string searchString = !string.IsNullOrEmpty(searchWord) ? searchWord.Trim('*') : "";
3180 string className = "u-w340px u-pull--right u-margin-left";
3181
3182 if (Pageview.Device.ToString() == "Mobile" || Pageview.Device.ToString() == "Tablet")
3183 {
3184 className = "u-full-width";
3185 }
3186
3187 <div class="typeahead u-color-inherit u-margin-bottom dw-mod @className">
3188 <input type="text" class="typeahead-search-field u-no-margin dw-mod" placeholder="@Translate("Search in list")" value="@searchString" id="ArticleListSearchInput" onchange="QueryArray.setParameterInCurrentURL('@searchParameter', '*' + document.getElementById('ArticleListSearchInput').value + '*')">
3189 <button type="button" class="btn btn--condensed btn--primary u-no-margin dw-mod"><i class="fas fa-search"></i></button>
3190 </div>
3191 }
3192 @using System.Reflection
3193 @using Dynamicweb.Rapido.Blocks.Components
3194 @using Dynamicweb.Rapido.Blocks.Components.Articles
3195 @using Dynamicweb.Rapido.Blocks
3196
3197 @* Component for the articles *@
3198
3199 @helper RenderArticleListNoResultsInfo(ArticleListNoResultsInfo settings)
3200 {
3201 <div class="u-margin-top--lg u-bold u-ta-center u-bold">@Translate(settings.Message)</div>
3202 }
3203 @using System.Reflection
3204 @using Dynamicweb.Rapido.Blocks.Components
3205 @using Dynamicweb.Rapido.Blocks.Components.General
3206 @using Dynamicweb.Rapido.Blocks.Components.Articles
3207 @using Dynamicweb.Rapido.Blocks
3208 @using System.Text.RegularExpressions
3209
3210 @* Component for the articles *@
3211
3212 @helper RenderArticleListItem(ArticleListItem settings)
3213 {
3214 switch (settings.Type) {
3215 case ArticleListItemType.Card:
3216 @RenderArticleListItemCard(settings);
3217 break;
3218 case ArticleListItemType.List:
3219 @RenderArticleListItemList(settings);
3220 break;
3221 case ArticleListItemType.Simple:
3222 @RenderArticleListItemSimple(settings);
3223 break;
3224 default:
3225 @RenderArticleListItemCard(settings);
3226 break;
3227 }
3228 }
3229
3230 @helper RenderArticleListItemCard(ArticleListItem settings) {
3231 <a href="@settings.Link" class="u-full-height u-color-light--bg">
3232 <div class="u-color-light--bg u-no-padding dw-mod">
3233 @if (settings.Logo != null)
3234 {
3235 string backgroundImage = settings.Image != null ? "background-image:url(/Admin/Public/GetImage.ashx?width=992&height=760&crop=0&Compression=75&DoNotUpscale=True&image=" + settings.Image.Path + "); background-size: cover;" : "";
3236 settings.Logo.ImageDefault.Crop = 5;
3237 settings.Logo.ImageDefault.Width = settings.Logo.ImageDefault.Width == 1920 ? 240 : settings.Logo.ImageDefault.Width;
3238 settings.Logo.ImageDefault.Height = settings.Logo.ImageDefault.Height == 1080 ? 200 : settings.Logo.ImageDefault.Height;
3239 <div class="image-hover__wrapper layered-image layered-image--tinted dw-mod" style="@backgroundImage">
3240 @if (settings.Stickers != null)
3241 {
3242 if (settings.Stickers.Position != StickersListPosition.Custom)
3243 {
3244 @Render(settings.Stickers);
3245 }
3246 }
3247 @RenderImage(settings.Logo)
3248 </div>
3249 } else if (settings.Image != null)
3250 {
3251 <div class="flex-img image-hover__wrapper u-position-relative dw-mod">
3252 @if (settings.Stickers != null)
3253 {
3254 if (settings.Stickers.Position != StickersListPosition.Custom)
3255 {
3256 @Render(settings.Stickers);
3257 }
3258 }
3259 @Render(settings.Image)
3260 </div>
3261 }
3262 </div>
3263
3264 @if (!String.IsNullOrEmpty(settings.Title) || !String.IsNullOrEmpty(settings.Summary))
3265 {
3266 <div class="card u-color-light--bg dw-mod">
3267 @if (settings.Stickers != null)
3268 {
3269 if (settings.Stickers.Position == StickersListPosition.Custom)
3270 {
3271 @Render(settings.Stickers);
3272 }
3273 }
3274 @if (!String.IsNullOrEmpty(settings.Title))
3275 {
3276 <h3 class="article-list__item-header u-truncate-text dw-mod">@settings.Title</h3>
3277 }
3278 @if (!String.IsNullOrEmpty(settings.SubTitle))
3279 {
3280 <div class="article-list__item-micro-info u-truncate-text dw-mod">@settings.SubTitle</div>
3281 }
3282 @if (!String.IsNullOrEmpty(settings.Summary))
3283 {
3284 <p class="article__short-summary dw-mod">@settings.Summary</p>
3285 }
3286 </div>
3287 }
3288 </a>
3289 }
3290
3291 @helper RenderArticleListItemList(ArticleListItem settings) {
3292 <a href="@settings.Link">
3293 <div class="grid u-color-light--bg u-no-padding dw-mod">
3294 <div class="grid__col-md-3">
3295 <div class="u-color-light--bg u-no-padding dw-mod">
3296 @if (settings.Logo != null)
3297 {
3298 string backgroundImage = settings.Image != null ? "background-image:url(/Admin/Public/GetImage.ashx?width=992&height=760&crop=0&Compression=75&DoNotUpscale=True&image=" + settings.Image.Path + "); background-size: cover;" : "";
3299 settings.Logo.ImageDefault.Crop = 5;
3300 settings.Logo.ImageDefault.Width = settings.Logo.ImageDefault.Width == 1920 ? 240 : settings.Logo.ImageDefault.Width;
3301 settings.Logo.ImageDefault.Height = settings.Logo.ImageDefault.Height == 1080 ? 200 : settings.Logo.ImageDefault.Height;
3302 <div class="image-hover__wrapper layered-image layered-image--tinted dw-mod" style="@backgroundImage">
3303 @if (settings.Stickers != null)
3304 {
3305 if (settings.Stickers.Position != StickersListPosition.Custom)
3306 {
3307 @Render(settings.Stickers);
3308 }
3309 }
3310 @RenderImage(settings.Logo)
3311 </div>
3312 } else if (settings.Image != null)
3313 {
3314 <div class="flex-img image-hover__wrapper dw-mod">
3315 @if (settings.Stickers != null)
3316 {
3317 if (settings.Stickers.Position != StickersListPosition.Custom)
3318 {
3319 @Render(settings.Stickers);
3320 }
3321 }
3322 @Render(settings.Image)
3323 </div>
3324 }
3325 </div>
3326 </div>
3327
3328 @if (!String.IsNullOrEmpty(settings.Title) || !String.IsNullOrEmpty(settings.Summary))
3329 {
3330 <div class="grid__col-md-9">
3331 @if (!String.IsNullOrEmpty(settings.Title))
3332 {
3333 <h3 class="article-list__item-header u-truncate-text dw-mod">@settings.Title</h3>
3334 }
3335 @if (settings.Stickers != null)
3336 {
3337 if (settings.Stickers.Position == StickersListPosition.Custom)
3338 {
3339 @Render(settings.Stickers);
3340 }
3341 }
3342 @if (!String.IsNullOrEmpty(settings.SubTitle))
3343 {
3344 <div class="article-list__item-micro-info u-truncate-text dw-mod">@settings.SubTitle</div>
3345 }
3346 @if (!String.IsNullOrEmpty(settings.Summary))
3347 {
3348 <p class="article__short-summary dw-mod">@settings.Summary</p>
3349 }
3350 </div>
3351 }
3352 </div>
3353 </a>
3354 }
3355
3356 @helper RenderArticleListItemSimple(ArticleListItem settings) {
3357 <a href="@settings.Link" class="u-color-inherit">
3358 <div class="grid u-color-light--bg u-no-padding dw-mod">
3359 <div class="grid__col-md-12">
3360 @if (!String.IsNullOrEmpty(settings.Title))
3361 {
3362 <div class="article-list-item__header u-truncate-text u-no-margin dw-mod">@settings.Title</div>
3363 }
3364 @if (!String.IsNullOrEmpty(settings.SubTitle))
3365 {
3366 <div class="article-list__item-micro-info u-truncate-text dw-mod">@settings.SubTitle</div>
3367 }
3368 </div>
3369 </div>
3370 </a>
3371 }
3372 @using System.Reflection
3373 @using Dynamicweb.Rapido.Blocks.Components.Articles
3374
3375
3376 @* Component for the articles *@
3377
3378 @helper RenderArticleAuthorAndDate(ArticleAuthorAndDate settings)
3379 {
3380 <small class="article__subscription">
3381 @if (!(string.IsNullOrWhiteSpace(settings.Author) && string.IsNullOrWhiteSpace(settings.Date)))
3382 {
3383 <text>@Translate("Written")</text>
3384 }
3385 @if (!string.IsNullOrWhiteSpace(settings.Author))
3386 {
3387 <text>@Translate("by") @settings.Author</text>
3388 }
3389 @if (!string.IsNullOrWhiteSpace(settings.Date))
3390 {
3391 <text>@Translate("on") @settings.Date</text>
3392 }
3393 </small>
3394 }
3395 @using System.Reflection
3396 @using Dynamicweb.Rapido.Blocks.Components.Articles
3397 @using Dynamicweb.Rapido.Blocks.Components.General
3398
3399
3400 @* Component for the articles *@
3401
3402 @helper RenderArticleLink(ArticleLink settings)
3403 {
3404 if (!string.IsNullOrEmpty(settings.Title))
3405 {
3406 Button link = new Button {
3407 ConfirmText = settings.ConfirmText,
3408 ConfirmTitle = settings.ConfirmTitle,
3409 ButtonType = settings.ButtonType,
3410 Id = settings.Id,
3411 Title = settings.Title,
3412 AltText = settings.AltText,
3413 OnClick = settings.OnClick,
3414 CssClass = settings.CssClass,
3415 Disabled = settings.Disabled,
3416 Icon = settings.Icon,
3417 Name = settings.Name,
3418 Href = settings.Href,
3419 ButtonLayout = settings.ButtonLayout,
3420 ExtraAttributes = settings.ExtraAttributes
3421 };
3422 <div class="grid__cell">
3423 @Render(link)
3424 </div>
3425 }
3426 }
3427 @using System.Reflection
3428 @using Dynamicweb.Rapido.Blocks
3429 @using Dynamicweb.Rapido.Blocks.Components.Articles
3430 @using Dynamicweb.Rapido.Blocks.Components.General
3431
3432
3433 @* Component for the articles *@
3434
3435 @helper RenderArticleCarousel(ArticleCarousel settings)
3436 {
3437 <div class="grid">
3438 <div class="grid__col-12">
3439 <div class="carousel" id="carousel_@settings.Id">
3440 <div class="carousel__container js-carousel-slides dw-mod">
3441 @RenderBlockList(settings.SubBlocks)
3442 </div>
3443 </div>
3444 </div>
3445 </div>
3446
3447 <script>
3448 document.addEventListener("DOMContentLoaded", function () {
3449 new CarouselModule("#carousel_@settings.Id", {
3450 slideTime: 0,
3451 dots: true
3452 });
3453 });
3454 </script>
3455 }
3456
3457 @helper RenderArticleCarouselSlide(ArticleCarouselSlide settings)
3458 {
3459 string imageEngine = "/Admin/Public/GetImage.ashx?";
3460
3461 string defaultImage = settings.ImageSettings != null ? imageEngine : settings.Image;
3462 if (settings.ImageSettings != null)
3463 {
3464 defaultImage += settings.ImageSettings.Width != 0 ? "Width=" + settings.ImageSettings.Width + "&" : "";
3465 defaultImage += settings.ImageSettings.Height != 0 ? "Height=" + settings.ImageSettings.Height + "&" : "";
3466 defaultImage += "Crop=" + settings.ImageSettings.Crop + "&";
3467 defaultImage += "Compression=" + settings.ImageSettings.Compression + "&";
3468 defaultImage += "DoNotUpscale=" + settings.ImageSettings.DoNotUpscale.ToString() + "&";
3469 defaultImage += "FillCanvas=" + settings.ImageSettings.FillCanvas.ToString() + "&";
3470 defaultImage += "format=webp&";
3471 }
3472 defaultImage += "&Image=" + settings.Image;
3473
3474 <div class="custom-carousel__slide u-min-h300px u-flex dw-mod" style="background-size:cover; background-image:url('@defaultImage')">
3475 <a class="article-carousel-item__wrap" href="@settings.Link" title="@settings.Title">
3476 <h2 class="article-list__item-header u-truncate-text u-color-light dw-mod">@settings.Title</h2>
3477 <div class="article-list__item-info">
3478 @if (settings.Stickers != null)
3479 {
3480 settings.Stickers.Position = StickersListPosition.Custom;
3481 @Render(settings.Stickers);
3482 }
3483
3484 <small class="u-margin-top--lg u-color-light">
3485 @if (!(string.IsNullOrWhiteSpace(settings.Author) && string.IsNullOrWhiteSpace(settings.Date)))
3486 {
3487 <text>@Translate("Written")</text>
3488 }
3489 @if (!string.IsNullOrWhiteSpace(settings.Author))
3490 {
3491 <text>@Translate("by") @settings.Author</text>
3492 }
3493 @if (!string.IsNullOrWhiteSpace(settings.Date))
3494 {
3495 <text>@Translate("on") @settings.Date</text>
3496 }
3497 </small>
3498 </div>
3499
3500 <h3 class="article__short-summary u-color-light">@settings.Summary</h3>
3501 </a>
3502 @if (settings.UseFilters == true)
3503 {
3504 <div class="background-image image-filter image-filter--darken dw-mod"></div>
3505 }
3506 </div>
3507 }
3508 @using System.Text.RegularExpressions
3509 @using Dynamicweb.Rapido.Blocks.Components
3510 @using Dynamicweb.Rapido.Blocks.Components.General
3511 @using Dynamicweb.Rapido.Blocks.Components.Articles
3512 @using Dynamicweb.Rapido.Blocks
3513
3514 @* Component for the articles *@
3515
3516 @helper RenderArticleVideo(ArticleVideo settings)
3517 {
3518 if (settings.Url != null)
3519 {
3520 //getting video ID from youtube URL
3521 string videoCode = settings.Url;
3522 Regex regex = new Regex(@".be\/(.[^?]*)");
3523 Match match = regex.Match(videoCode);
3524 string videoId = "";
3525 if (match.Success)
3526 {
3527 videoId = match.Groups[1].Value;
3528 }
3529 else
3530 {
3531 regex = new Regex(@"v=([^&]+)");
3532 match = regex.Match(videoCode);
3533 if (match.Success)
3534 {
3535 videoId = match.Groups[1].Value;
3536 }
3537 }
3538
3539 int autoPlay = settings.AutoPlay == "true" ? 1 : 0;
3540
3541 <div class="video-wrapper">
3542 <div class="js-youtube-video" data-video="@videoId" id="ytPlayer@(Guid.NewGuid().ToString("N"))" data-auto-play="@autoPlay" data-enable-controls="1"></div>
3543 </div>
3544 }
3545 }
3546
3547
3548
3549 @* Simple helpers *@
3550
3551 @*Requires the Gallery ItemType that comes with Rapido*@
3552 @helper RenderArticleItemGallery(IList<ItemViewModel> gallery) {
3553 if (gallery != null && gallery.Count > 0)
3554 {
3555 int count = 1;
3556
3557 foreach (var item in gallery)
3558 {
3559 if (item.GetFile("ImagePath") != null)
3560 {
3561 string image = item.GetFile("ImagePath").PathUrlEncoded;
3562 string imagePrefix = "/Admin/Public/GetImage.ashx?width=1200&height=820&crop=5&Compression=75&DoNotUpscale=1&image=";
3563 int imagesCount = gallery.Count;
3564
3565 if (count == 1)
3566 {
3567 <label class="gallery" for="ParagraphGalleryModalTrigger" onclick="Gallery.openImage(this.querySelector('.js-gallery'))">
3568 <span class="gallery__main-image">
3569 <img src="/Files/Images/placeholder.gif" data-src="/Admin/Public/GetImage.ashx?width=992&height=760&crop=0&Compression=75&DoNotUpscale=1&image=@image" class="b-lazy flex-img js-gallery" alt="" data-for="ParagraphGallery" data-image="@imagePrefix@image" />
3570 </span>
3571 <span class="gallery__image-counter">
3572 <i class="fas fa-camera fa-2x"></i> <span class="gallery__image-counter__number">@imagesCount</span>
3573 <span class="gallery__image-counter__text">@Translate("See all") <i class="fas fa-angle-right"></i></span>
3574 </span>
3575 </label>
3576 }
3577 else
3578 {
3579 <div class="u-hidden js-gallery" data-for="ParagraphGallery" data-image="@imagePrefix@image"></div>
3580 }
3581
3582 count++;
3583 }
3584 }
3585
3586 @Render(new ArticleGalleryModal())
3587 }
3588 }
3589
3590 @helper RenderMobileFilters(List<Block> subBlocks)
3591 {
3592 if (subBlocks.Count > 0)
3593 {
3594 <div class="grid__col-12">
3595 <input type="checkbox" id="CheckFilters" class="js-remember-state u-hidden" data-expand="CheckFilters" />
3596 <div class="grid u-margin-bottom dw-mod" data-trigger="CheckFilters">
3597 @RenderBlockList(subBlocks)
3598 </div>
3599 <label for="CheckFilters" class="btn btn--secondary btn--full dw-mod js-expand-hide" data-trigger="CheckFilters">@Translate("Select filters")</label>
3600 <label for="CheckFilters" class="btn btn--secondary btn--full dw-mod expandable--collapsed" data-trigger="CheckFilters">@Translate("Close filters")</label>
3601 </div>
3602 }
3603 }
3604
3605
3606 @* Include the Blocks for the page *@
3607 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>
3608
3609 @using System
3610 @using System.Web
3611 @using System.Collections.Generic
3612 @using Dynamicweb.Environment
3613 @using Dynamicweb.Rapido.Blocks.Extensibility
3614 @using Dynamicweb.Rapido.Blocks
3615 @using Dynamicweb.Core
3616 @using Dynamicweb.Frontend
3617 @using Dynamicweb.Configuration
3618 @using Custom.PhilipsonWine.Security.Helpers
3619
3620 @functions {
3621 string GoogleTagManagerID = "";
3622 string GoogleAnalyticsID = "";
3623
3624 public string GetCustomUserFieldValue(string fieldName)
3625 {
3626 var currentUser = Dynamicweb.Security.UserManagement.User.GetCurrentExtranetUser();
3627 if (currentUser != null)
3628 {
3629 return Converter.ToString(currentUser.CustomFieldValues.FirstOrDefault(x => x.CustomField.SystemName == fieldName)?.Value);
3630 }
3631
3632 return "";
3633 }
3634 }
3635
3636 @{
3637 GoogleTagManagerID = Model.Area.Item.GetItem("Settings").GetString("GoogleTagManagerID");
3638 GoogleAnalyticsID = Model.Area.Item.GetItem("Settings").GetString("GoogleAnalyticsTrackingID");
3639 string trustpilotFreeWidget = Model.Area.Item.GetItem("Custom").GetString("FooterTrustpilotFreeWidget");
3640
3641 BlocksPage topSnippetsBlocksPage = BlocksPage.GetBlockPage("Master");
3642
3643
3644 Block cookieInformation = new Block()
3645 {
3646 Id = "CookieInformation",
3647 SortId = 25,
3648 Template = RenderCookieInformation()
3649 };
3650 topSnippetsBlocksPage.Add("Head", cookieInformation);
3651
3652 Block googleConsentModeBlock = new Block()
3653 {
3654 Id = "GoogleConsentMode",
3655 // MUST be rendered before GA
3656 SortId = 9,
3657 Template = RenderGoogleConsentMode()
3658 };
3659 topSnippetsBlocksPage.Add("Head", googleConsentModeBlock);
3660
3661 if (!string.IsNullOrWhiteSpace(GoogleAnalyticsID))
3662 {
3663 Block tagManager = new Block()
3664 {
3665 Id = "GoogleAnalytics",
3666 SortId = 10,
3667 Template = RenderGoogleAnalyticsSnippet()
3668 };
3669 topSnippetsBlocksPage.Add("Head", tagManager);
3670 }
3671
3672 if (!string.IsNullOrWhiteSpace(GoogleTagManagerID))
3673 {
3674 Block GTMDataLayer = new Block()
3675 {
3676 Id = "GTMDataLayer",
3677 SortId = 0,
3678 Template = RenderGTMDataLayer()
3679 };
3680 topSnippetsBlocksPage.Add("Head", GTMDataLayer);
3681 Block tagManager = new Block()
3682 {
3683 Id = "TagManager",
3684 SortId = 20,
3685 Template = RenderGoogleTagManager()
3686 };
3687 topSnippetsBlocksPage.Add("Head", tagManager);
3688
3689 Block tagManagerBodySnippet = new Block()
3690 {
3691 Id = "TagManagerBodySnippet",
3692 SortId = 20,
3693 Template = RenderGoogleTagManagerBodySnippet()
3694 };
3695 topSnippetsBlocksPage.Add(MasterBlockId.MasterTopSnippets, tagManagerBodySnippet);
3696 }
3697
3698 Block facebookPixel = new Block()
3699 {
3700 Id = "FacebookPixel",
3701 SortId = 30,
3702 Template = RenderFacebookPixel()
3703 };
3704
3705 topSnippetsBlocksPage.Add(MasterBlockId.MasterTopSnippets, facebookPixel);
3706
3707 Block facebookPixelProductPage = new Block()
3708 {
3709 Id = "FacebookPixelProductPage",
3710 SortId = 31,
3711 Template = RenderFacebookPixelProductPage()
3712 };
3713
3714 topSnippetsBlocksPage.Add(MasterBlockId.MasterTopSnippets, facebookPixelProductPage);
3715
3716 Block oneSignalBlock = new Block()
3717 {
3718 Id = "OneSignal",
3719 SortId = 50,
3720 Template = RenderOneSignalScript()
3721 };
3722
3723 topSnippetsBlocksPage.Add("Head", oneSignalBlock);
3724
3725 Block openSearchBlock = new Block()
3726 {
3727 Id = "OpenSearch",
3728 SortId = 50,
3729 Template = RenderOpenSearchReference()
3730 };
3731
3732 topSnippetsBlocksPage.Add("Head", openSearchBlock);
3733
3734 if (!string.IsNullOrEmpty(trustpilotFreeWidget))
3735 {
3736 Block trustpilotScriptBlock = new Block()
3737 {
3738 Id = "TrustpilotScript",
3739 SortId = 70,
3740 Template = TrustpilotScript()
3741 };
3742
3743 topSnippetsBlocksPage.Add("Head", trustpilotScriptBlock);
3744 }
3745
3746 string simplifyId = PageView.Current().AreaSettings.GetItem("Custom").GetString("SimplifyId");
3747
3748 if (!string.IsNullOrEmpty(simplifyId))
3749 {
3750 Block simplifyScriptBlock = new Block()
3751 {
3752 Id = "SimplifyScript",
3753 SortId = 5,
3754 Template = RenderSimplifyScript(simplifyId)
3755 };
3756
3757 topSnippetsBlocksPage.Add("Head", simplifyScriptBlock);
3758 }
3759
3760 string vwoUrl = PageView.Current().AreaSettings.GetItem("Custom").GetRawValueString("VWOUrl");
3761 string vwoId = PageView.Current().AreaSettings.GetItem("Custom").GetRawValueString("VWOId");
3762
3763 if (!string.IsNullOrEmpty(vwoId) && !string.IsNullOrEmpty(vwoUrl))
3764 {
3765 Block vwoScriptBlock = new Block()
3766 {
3767 Id = "VWOScript",
3768 SortId = 5,
3769 Template = RenderVWOScript(vwoId, vwoUrl)
3770 };
3771
3772 topSnippetsBlocksPage.Add("Head", vwoScriptBlock);
3773 }
3774
3775 ItemViewModel customSommifySettings = PageView.Current().AreaSettings.GetItem("Custom").GetItem("SommifySettings");
3776 if (customSommifySettings != null)
3777 {
3778 bool sommifyActivated = customSommifySettings.GetBoolean("ActivateSommify");
3779 if (sommifyActivated)
3780 {
3781 Block sommifyScriptBlock = new Block()
3782 {
3783 Id = "SommifyScript",
3784 SortId = 5,
3785 Template = RenderSommifyScript(customSommifySettings)
3786 };
3787
3788 topSnippetsBlocksPage.Add("Head", sommifyScriptBlock);
3789 }
3790 }
3791
3792 string spriiScript = PageView.Current().AreaSettings.GetItem("Custom").GetRawValueString("SpriiScript");
3793 if (!string.IsNullOrEmpty(spriiScript))
3794 {
3795 Block spriiScriptBlock = new Block()
3796 {
3797 Id = "SpriiScript",
3798 SortId = 5,
3799 Template = RenderSpriiScript(spriiScript)
3800 };
3801
3802 topSnippetsBlocksPage.Add("Head", spriiScriptBlock);
3803 }
3804
3805 string klaviyoId = Custom.Klaviyo.Helpers.Helper.GetKlaviyoId(Pageview, "Settings");
3806 if (!string.IsNullOrEmpty(klaviyoId))
3807 {
3808 Block klaviyoScriptBlock = new Block()
3809 {
3810 Id = "KlaviyoScript",
3811 SortId = 10,
3812 Template = RenderKlaviyoScript(klaviyoId)
3813 };
3814
3815 topSnippetsBlocksPage.Add("Head", klaviyoScriptBlock);
3816 }
3817
3818 if (RecaptchaHelper.RecaptchaActivated)
3819 {
3820 Block recaptchaScriptBlock = new Block()
3821 {
3822 Id = "RecaptchaScript",
3823 SortId = 5,
3824 Template = RenderRecaptchaScript()
3825 };
3826
3827 topSnippetsBlocksPage.Add("Head", recaptchaScriptBlock);
3828 }
3829
3830 ItemViewModel customInternationalTelephoneSettings = PageView.Current().AreaSettings.GetItem("Custom").GetItem("InternationalTelephoneSettings");
3831 if (customInternationalTelephoneSettings != null)
3832 {
3833 bool internationalTelephoneActivated = customInternationalTelephoneSettings.GetBoolean("ActivateInternationalTelephone");
3834 if (internationalTelephoneActivated)
3835 {
3836 Block internationalTelephoneScriptBlock = new Block()
3837 {
3838 Id = "InternationalTelephoneScript",
3839 SortId = 5,
3840 Template = RenderInternationalTelephoneScript(customInternationalTelephoneSettings)
3841 };
3842
3843 topSnippetsBlocksPage.Add("Head", internationalTelephoneScriptBlock);
3844 }
3845 }
3846
3847 Block schemaBlock = new Block()
3848 {
3849 Id = "SchemaBlock",
3850 SortId = 100,
3851 Template = RenderSchema()
3852 };
3853
3854 topSnippetsBlocksPage.Add("Head", schemaBlock);
3855 }
3856
3857 @helper RenderCookieInformation()
3858 {
3859 <script id="CookieConsent" src="https://policy.app.cookieinformation.com/uc.js" data-culture="@Pageview.Area.CultureInfo.TwoLetterISOLanguageName.ToUpper()" data-gcm-version="2.0" type="text/javascript"></script>
3860
3861 <script type="text/javascript">
3862 window.addEventListener('CookieInformationConsentGiven', function (event) {
3863 if (!CookieInformation.getConsentGivenFor('cookie_cat_marketing')) {
3864 var allFrames = document.querySelectorAll("iframe");
3865
3866 //Start - Content replacing iframes
3867 for (i = 0; i < allFrames.length; i++) {
3868 var frame = allFrames[i];
3869 if (frame.src.indexOf('youtu') !== -1 || frame.src.indexOf('vimeo') !== -1) {
3870 frame.insertAdjacentHTML("beforebegin", '<div class="consent-placeholder u-brand-color-two" data-category="cookie_cat_marketing" onClick="CookieConsent.renew()">@Translate("Smartpage:Cookieinformation.Renew", "Renew or change your cookie consent to see this content")</div>');
3871 frame.parentNode.removeChild(frame);
3872 }
3873 }
3874 }
3875 // Google Consent mode implementation
3876 if (CookieInformation.getConsentGivenFor('cookie_cat_statistic') && window.gtag != undefined) {
3877 gtag('consent', 'update', { 'analytics_storage': 'granted' });
3878 }
3879 if (CookieInformation.getConsentGivenFor('cookie_cat_marketing') && window.gtag != undefined) {
3880 gtag('consent', 'update', { 'ad_storage': 'granted' });
3881 }
3882
3883 window.dataLayer = window.dataLayer || [];
3884 window.dataLayer.push({ 'event': 'consent_decision_made' });
3885 }, false);
3886
3887 </script>
3888 }
3889
3890 @helper RenderSimplifyScript(string id)
3891 {
3892 <script type="text/javascript">
3893 window.addEventListener('CookieInformationConsentGiven', function (event) {
3894 if (CookieInformation.getConsentGivenFor('cookie_cat_statistic')) {
3895 var script = document.createElement('script');
3896 script.setAttribute('type', 'text/javascript');
3897 script.setAttribute('src', 'https://cdn-sitegainer.com/@id/es6/index.bundle.js');
3898 document.head.appendChild(script);
3899 }
3900 }, false);
3901 </script>
3902 }
3903
3904 @helper RenderVWOScript(string vwoId, string vwoUrl)
3905 {
3906 <link rel="preconnect" href="@vwoUrl" />
3907 <script type='text/javascript' id='vwoCode'>
3908 window._vwo_code || (function () {
3909 var account_id = @vwoId,
3910 version = 2.1,
3911 settings_tolerance = 2000,
3912 hide_element = 'body',
3913 hide_element_style = 'opacity:0 !important;filter:alpha(opacity=0) !important;background:none !important',
3914 f = false, w = window, d = document, v = d.querySelector('#vwoCode'), cK = '_vwo_' + account_id + '_settings', cc = {}; try { var c = JSON.parse(localStorage.getItem('_vwo_' + account_id + '_config')); cc = c && typeof c === 'object' ? c : {} } catch (e) { } var stT = cc.stT === 'session' ? w.sessionStorage : w.localStorage; code = { use_existing_jquery: function () { return typeof use_existing_jquery !== 'undefined' ? use_existing_jquery : undefined }, library_tolerance: function () { return typeof library_tolerance !== 'undefined' ? library_tolerance : undefined }, settings_tolerance: function () { return cc.sT || settings_tolerance }, hide_element_style: function () { return '{' + (cc.hES || hide_element_style) + '}' }, hide_element: function () { if (performance.getEntriesByName('first-contentful-paint')[0]) { return '' } return typeof cc.hE === 'string' ? cc.hE : hide_element }, getVersion: function () { return version }, finish: function (e) { if (!f) { f = true; var t = d.getElementById('_vis_opt_path_hides'); if (t) t.parentNode.removeChild(t); if (e) (new Image).src = '@vwoUrl/ee.gif?a=' + account_id + e } }, finished: function () { return f }, addScript: function (e) { var t = d.createElement('script'); t.type = 'text/javascript'; if (e.src) { t.src = e.src } else { t.text = e.text } d.getElementsByTagName('head')[0].appendChild(t) }, load: function (e, t) { var i = this.getSettings(), n = d.createElement('script'), r = this; t = t || {}; if (i) { n.textContent = i; d.getElementsByTagName('head')[0].appendChild(n); if (!w.VWO || VWO.caE) { stT.removeItem(cK); r.load(e) } } else { var o = new XMLHttpRequest; o.open('GET', e, true); o.withCredentials = !t.dSC; o.responseType = t.responseType || 'text'; o.onload = function () { if (t.onloadCb) { return t.onloadCb(o, e) } if (o.status === 200) { _vwo_code.addScript({ text: o.responseText }) } else { _vwo_code.finish('&e=loading_failure:' + e) } }; o.onerror = function () { if (t.onerrorCb) { return t.onerrorCb(e) } _vwo_code.finish('&e=loading_failure:' + e) }; o.send() } }, getSettings: function () { try { var e = stT.getItem(cK); if (!e) { return } e = JSON.parse(e); if (Date.now() > e.e) { stT.removeItem(cK); return } return e.s } catch (e) { return } }, init: function () { if (d.URL.indexOf('__vwo_disable__') > -1) return; var e = this.settings_tolerance(); w._vwo_settings_timer = setTimeout(function () { _vwo_code.finish(); stT.removeItem(cK) }, e); var t; if (this.hide_element() !== 'body') { t = d.createElement('style'); var i = this.hide_element(), n = i ? i + this.hide_element_style() : '', r = d.getElementsByTagName('head')[0]; t.setAttribute('id', '_vis_opt_path_hides'); v && t.setAttribute('nonce', v.nonce); t.setAttribute('type', 'text/css'); if (t.styleSheet) t.styleSheet.cssText = n; else t.appendChild(d.createTextNode(n)); r.appendChild(t) } else { t = d.getElementsByTagName('head')[0]; var n = d.createElement('div'); n.style.cssText = 'z-index: 2147483647 !important;position: fixed !important;left: 0 !important;top: 0 !important;width: 100% !important;height: 100% !important;background: white !important;'; n.setAttribute('id', '_vis_opt_path_hides'); n.classList.add('_vis_hide_layer'); t.parentNode.insertBefore(n, t.nextSibling) } var o = '@vwoUrl/j.php?a=' + account_id + '&u=' + encodeURIComponent(d.URL) + '&vn=' + version; if (w.location.search.indexOf('_vwo_xhr') !== -1) { this.addScript({ src: o }) } else { this.load(o + '&x=true') } } }; w._vwo_code = code; code.init();
3915 })();
3916 </script>
3917 }
3918
3919 @helper RenderSommifyScript(ItemViewModel customSommifySettings)
3920 {
3921 string sommifyUrl = customSommifySettings.GetRawValueString("SommifyUrl");
3922
3923 if (!string.IsNullOrEmpty(sommifyUrl))
3924 {
3925 <script id="sommifyScript" async src="@sommifyUrl"></script>
3926 }
3927 }
3928
3929 @helper RenderSpriiScript(string spriiScript)
3930 {
3931 <script src="@spriiScript" type="module" crossorigin="anonymous" async></script>
3932 }
3933
3934 @helper RenderRecaptchaScript()
3935 {
3936 string combinedSrc = RecaptchaHelper.RecaptchaScript + "?render=" + RecaptchaHelper.RecaptchaSiteKey;
3937 <script class="js-recaptcha-script" src="@HttpUtility.HtmlAttributeEncode(combinedSrc)"></script>
3938 }
3939
3940 @helper RenderInternationalTelephoneScript(ItemViewModel customInternationalTelephoneSettings)
3941 {
3942 string styleSheetUrl = customInternationalTelephoneSettings.GetRawValueString("StyleSheetUrl");
3943 string minifiedJsUrl = customInternationalTelephoneSettings.GetRawValueString("MinifiedJsUrl");
3944 string utilsJsUrl = customInternationalTelephoneSettings.GetRawValueString("UtilsJsUrl");
3945
3946 if (!string.IsNullOrEmpty(styleSheetUrl) && !string.IsNullOrEmpty(minifiedJsUrl) && !string.IsNullOrEmpty(utilsJsUrl))
3947 {
3948 <link id="internationalTelephoneStylesheet" async rel="stylesheet" href="@styleSheetUrl">
3949 <script id="internationalTelephoneScriptMinified" async src="@minifiedJsUrl"></script>
3950 }
3951 }
3952
3953 @helper RenderGoogleConsentMode()
3954 {
3955 <script>
3956 window.dataLayer = window.dataLayer || [];
3957 function gtag() { dataLayer.push(arguments); }
3958 gtag('consent', 'default', {
3959 'ad_storage': 'denied',
3960 'ad_user_data': 'denied',
3961 'ad_personalization': 'denied',
3962 'analytics_storage': 'denied',
3963 'wait_for_update': 500
3964 });
3965 gtag('set', 'ads_data_redaction', true);
3966 </script>
3967 }
3968
3969 @helper RenderGoogleAnalyticsSnippet()
3970 {
3971 <!-- Global site tag (gtag.js) - Google Analytics -->
3972 <script async src="https://www.googletagmanager.com/gtag/js?id=@GoogleAnalyticsID"></script>
3973 <script>
3974 window.dataLayer = window.dataLayer || [];
3975 function gtag(){dataLayer.push(arguments);}
3976 gtag('js', new Date());
3977
3978 gtag('config', '@GoogleAnalyticsID');
3979 </script>
3980 }
3981
3982 @helper RenderGTMDataLayer()
3983 {
3984 string anonymousId = HttpContext.Current.Request.Cookies["ajs_anonymous_id"]?.Value ?? "undefined";
3985 var currentUser = Dynamicweb.Security.UserManagement.User.GetCurrentExtranetUser();
3986 if (currentUser != null)
3987 {
3988 <script>
3989 window.dataLayer = window.dataLayer || [];
3990 window.dataLayer = [{
3991 'event': 'Active on site',
3992 'attributes': {
3993 'properties': {
3994 'userStatus': 'loggedIn',
3995 'userId': '@currentUser.ID',
3996 'customerType': '@GetCustomUserFieldValue("AccessUser_SpBcCustomerType")',
3997 'customerName': '@currentUser.Name',
3998 'email': '@currentUser.Email',
3999 'mobile': '@currentUser.Phone',
4000 'countryPhoneCode': '@GetCustomUserFieldValue("AccessUser_SpCountryPhoneCode")',
4001 'rawPhoneNumber': '@GetCustomUserFieldValue("AccessUser_SpRawPhoneNumber")',
4002 'combinedPhoneNumber': '@GetCustomUserFieldValue("AccessUser_SpCombinedPhoneNumber")',
4003 'bcId': '@currentUser.CustomerNumber',
4004 'customerCountry': '@currentUser.CountryCode',
4005 'page': '@(HttpContext.Current.Request.Url.Scheme + "://" + HttpContext.Current.Request.Url.Host + HttpContext.Current.Request.RawUrl)',
4006 'deviceCategory': '@Convert.ToString(Pageview.Device)',
4007 'address': {
4008 'country': '@currentUser.CountryCode',
4009 'city': '@currentUser.City',
4010 'postalCode': '@currentUser.Zip',
4011 'street': '@HttpUtility.JavaScriptStringEncode(currentUser.Address)'
4012 }
4013 },
4014 'time': '@DateTime.Now.ToString("G", System.Globalization.CultureInfo.InvariantCulture)',
4015 'uniqueId': '@Guid.NewGuid().ToString("N")',
4016 'shopId': '@Pageview.Area.EcomShopId',
4017 'areaId': '@Converter.ToString(Pageview.AreaID)',
4018 'ajsAnonymousID': '@anonymousId'
4019 }
4020 }]
4021 </script>
4022 }
4023 else
4024 {
4025 <script>
4026 window.dataLayer = window.dataLayer || [];
4027 window.dataLayer = [{
4028 'userStatus': 'notLoggedIn',
4029 'userId': undefined,
4030 'customerType': undefined,
4031 'shopId': '@Pageview.Area.EcomShopId',
4032 'areaId': '@Converter.ToString(Pageview.AreaID)',
4033 'ajsAnonymousID': '@anonymousId'
4034 }]
4035 </script>
4036 }
4037 }
4038
4039 @helper RenderGoogleTagManager()
4040 {
4041 string googleTagManagerSource = "https://gtm.philipsonwine.com";
4042 if (!string.IsNullOrEmpty(Model.Area.Item.GetItem("Settings").GetString("SpGoogleTagManagerSource")))
4043 {
4044 googleTagManagerSource = Model.Area.Item.GetItem("Settings").GetString("SpGoogleTagManagerSource");
4045 }
4046 <script>
4047 (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
4048 new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
4049 j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
4050 '@googleTagManagerSource?id='+i+dl;f.parentNode.insertBefore(j,f);
4051 })(window,document,'script','dataLayer','@GoogleTagManagerID');
4052 </script>
4053 }
4054
4055
4056
4057 @helper RenderGoogleTagManagerBodySnippet()
4058 {
4059 string source = !string.IsNullOrEmpty(Model.Area.Item.GetItem("Settings").GetString("SpGoogleTagManagerBodySnippetSource")) ? Model.Area.Item.GetItem("Settings").GetString("SpGoogleTagManagerBodySnippetSource") : "https://www.googletagmanager.com/ns.html";
4060 <!-- Google Tag Manager (noscript) -->
4061 <noscript>
4062 <iframe src="@source?id=@GoogleTagManagerID"
4063 height="0" width="0" style="display:none;visibility:hidden"></iframe>
4064 </noscript>
4065 <!-- End Google Tag Manager (noscript) -->
4066 }
4067
4068 @helper RenderFacebookPixel()
4069 {
4070 string FacebookPixelID = Model.Area.Item.GetItem("Settings").GetString("FacebookPixelID");
4071
4072 if (!string.IsNullOrWhiteSpace(FacebookPixelID))
4073 {
4074 <!-- Facebook Pixel Code -->
4075 <script>
4076 !function(f,b,e,v,n,t,s)
4077 {if(f.fbq)return;n=f.fbq=function(){n.callMethod?
4078 n.callMethod.apply(n,arguments):n.queue.push(arguments)};
4079 if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
4080 n.queue=[];t=b.createElement(e);t.async=!0;
4081 t.src=v;s=b.getElementsByTagName(e)[0];
4082 s.parentNode.insertBefore(t,s)}(window, document,'script',
4083 'https://connect.facebook.net/en_US/fbevents.js');
4084 fbq('init', '@FacebookPixelID');
4085 fbq('track', 'PageView');
4086 </script>
4087 <noscript><img height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=@FacebookPixelID&ev=PageView&noscript=1" alt="" /></noscript>
4088 }
4089 }
4090
4091
4092 @helper RenderFacebookPixelProductPage()
4093 {
4094 string FacebookPixelID = Model.Area.Item.GetItem("Settings").GetString("FacebookPixelID");
4095 string productId = Dynamicweb.Context.Current.Request["ProductId"];
4096 bool isProductPage = !string.IsNullOrEmpty(productId);
4097
4098 if (!string.IsNullOrWhiteSpace(FacebookPixelID) && isProductPage)
4099 {
4100 var product = Dynamicweb.Ecommerce.Services.Products.GetProductById(productId, string.Empty, true);
4101 if (product != null)
4102 {
4103 <!-- Facebook Pixel Code -->
4104 <script>
4105 fbq('track', 'ViewContent', {
4106 content_ids: '@product.Id',
4107 content_type: 'product',
4108 value: '@product.UnformattedPrice.ToString().Replace(',','.')',
4109 currency: '@Dynamicweb.Ecommerce.Common.Context.Currency.Symbol.Trim()',
4110 content_category: '@Converter.ToString(product.ProductFieldValues.GetProductFieldValue("SpWineDescription")?.Value)'
4111 });
4112 </script>
4113 }
4114 }
4115 }
4116
4117 @helper RenderOneSignalScript()
4118 {
4119 string oneSignalAppId = Model.Area.Item.GetItem("Settings").GetString("SpOneSignalAppId");
4120 if (!string.IsNullOrEmpty(oneSignalAppId))
4121 {
4122 <script src="https://cdn.onesignal.com/sdks/OneSignalSDK.js" async=""></script>
4123 <script>
4124 window.OneSignal = window.OneSignal || [];
4125 OneSignal.push(function() {
4126 OneSignal.init({
4127 appId: "@oneSignalAppId",
4128 });
4129 });
4130 </script>
4131 }
4132 }
4133
4134 @helper RenderOpenSearchReference()
4135 {
4136 <link type="application/opensearchdescription+xml" rel="search" href="https://philipsonwine.com/Files/opensearch.xml" />
4137 }
4138
4139 @helper TrustpilotScript()
4140 {
4141 <script type="text/javascript" src="//widget.trustpilot.com/bootstrap/v5/tp.widget.bootstrap.min.js" async></script>
4142 }
4143
4144 @helper RenderKlaviyoScript(string id)
4145 {
4146 <script async type="text/javascript" src="https://static.klaviyo.com/onsite/js/klaviyo.js?company_id=@(id)"></script>
4147 }
4148
4149 @helper RenderSchema()
4150 {
4151 var schemaSettings = PageView.Current().AreaSettings.GetItem("CustomSchema");
4152 var currentUrl = Dynamicweb.Context.Current.Request.Url.Scheme + "://" + Dynamicweb.Context.Current.Request.Url.Host + Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl("Default.aspx?Id=" + PageView.Current().Page.ID);
4153 var language = PageView.Current().Area.CultureInfo.TwoLetterISOLanguageName;
4154 var returnPolicies = schemaSettings.GetItems("ReturnPolicies");
4155 var certifications = schemaSettings.GetItems("Certifications");
4156 var openingHours = schemaSettings.GetItems("OpeningHours");
4157 var isProductPage = PageView.Current().Page.ID == GetPageIdByNavigationTag("ProductsPage");
4158
4159 <script type="application/ld+json">
4160 {
4161 "@@context": "https://schema.org",
4162 "@@graph": [
4163 @if (!isProductPage)
4164 {
4165 <text>
4166 {
4167 "@@type": "WebPage",
4168 "@@id": "@currentUrl",
4169 "url": "@currentUrl",
4170 "name": "@PageView.Current().Page.GetDisplayName()",
4171 "description": "@PageView.Current().Page.Description",
4172 "inLanguage": "@language",
4173 "keywords": "@PageView.Current().Page.Keywords",
4174 "primaryImageOfPage": "https://philipsonwine.com/Files/Images/philipsonwine/logo/philipson-wine-logo.svg",
4175 @if(!string.IsNullOrEmpty(schemaSettings.GetRawValueString("WebPageSignificantLinks")))
4176 {
4177 var index = 0;
4178 <text>
4179 "significantLink": [
4180 @foreach (var link in schemaSettings.GetRawValueString("WebPageSignificantLinks").Split(','))
4181 {
4182 <text>
4183 "@link"
4184 </text>
4185 index++;
4186 if (index < schemaSettings.GetRawValueString("WebPageSignificantLinks").Split(',').Count())
4187 {
4188 <text>,</text>
4189 }
4190 }
4191
4192 ],
4193 </text>
4194 }
4195 "isPartOf": {
4196 "@@id": "https://philipsonwine.com/#website"
4197 }
4198 },
4199 </text>
4200 }
4201 {
4202 "@@type": "WebSite",
4203 "@@id": "https://philipsonwine.com/#website",
4204 "url": "https://philipsonwine.com/",
4205 "name": "Philipson Wine",
4206 @if (!string.IsNullOrEmpty(schemaSettings.GetRawValueString("WebsiteDescription")))
4207 {
4208 <text>
4209 "description": "@schemaSettings.GetRawValueString("WebsiteDescription")",
4210 </text>
4211 }
4212 "inLanguage": "da",
4213 "author": "Philipson Wine ApS",
4214 "copyrightHolder": "Philipson Wine ApS",
4215 @if (!string.IsNullOrEmpty(schemaSettings.GetRawValueString("WebSiteSearchActionTarget")))
4216 {
4217 <text>
4218 "potentialAction": {
4219 "@@type": "SearchAction",
4220 "target": "@schemaSettings.GetRawValueString("WebSiteSearchActionTarget"){search_term_string}",
4221 "query-input": "required name=search_term_string"
4222 },
4223 </text>
4224 }
4225 "publisher": {
4226 "@@id": "https://philipsonwine.com/#organization"
4227 }
4228 },
4229 {
4230 "@@type": "OnlineStore",
4231 "@@id": "https://philipsonwine.com/#organization",
4232 "name": "Philipson Wine",
4233 "alternateName": "PW",
4234 "legalName": "Philipson Wine ApS",
4235 "url": "https://philipsonwine.com/",
4236 "logo": "https://philipsonwine.com/Files/Images/philipsonwine/logo/philipson-wine-logo.svg",
4237 "description": "@schemaSettings.GetRawValueString("OnlineStoreDescription", "Velkommen til Philipson Wine - din førende vinhandel med mere end 35 års erfaring inden for vinbranchen. Vi er stolte af vores lange historie, vores tætte samarbejde med samtlige anerkendte vinproducenter verden over og af at vi er eneimportør af nogle af de mest kendte producenter")",
4238 "email": "@schemaSettings.GetRawValueString("OnlineStoreEmail", "support@philipsonwine.com")",
4239 "telephone": "@schemaSettings.GetRawValueString("OnlineStoreTelephone", "+4570226888")",
4240 "foundingDate": "1987-01-01",
4241 "founder": "Christian Philipson",
4242 "numberOfEmployees": {
4243 "@@type": "QuantitativeValue",
4244 "value": @schemaSettings.GetInt32("OnlineStoreEmployees")
4245 },
4246 "vatID": "@schemaSettings.GetRawValueString("OnlineStoreVatID", "DK28331843")",
4247 "address": {
4248 "@@type": "PostalAddress",
4249 "streetAddress": "@schemaSettings.GetRawValueString("OnlineStoreAddress", "Kokkedal Industripark 10")",
4250 "addressLocality": "@schemaSettings.GetRawValueString("OnlineStoreCity", "Kokkedal")",
4251 "postalCode": "@schemaSettings.GetRawValueString("OnlineStoreZip", "2980")",
4252 "addressCountry": "@schemaSettings.GetRawValueString("OnlineStoreCountryCode", "DK")"
4253 },
4254 "aggregateRating": {
4255 "@@type": "AggregateRating",
4256 "name": "TrustPilot",
4257 "url": "https://dk.trustpilot.com/review/www.philipsonwine.com",
4258 "ratingValue": "4.2",
4259 "bestRating": "5",
4260 "worstRating": "1",
4261 "reviewCount": "10851"
4262 },
4263 "hasMerchantReturnPolicy": [
4264 @if (returnPolicies.Any())
4265 {
4266 var index = 0;
4267 foreach (var returnPolicy in returnPolicies)
4268 {
4269 <text>
4270 {
4271 "@@type": "MerchantReturnPolicy",
4272 "returnPolicyCategory": "@returnPolicy.GetRawValueString("ReturnPolicyCategory")",
4273 "merchantReturnDays": "@returnPolicy.GetInt32("MerchantReturnDays")",
4274 "returnMethod": "@returnPolicy.GetRawValueString("ReturnMethod")",
4275 "returnFees": "@returnPolicy.GetRawValueString("ReturnFees")",
4276 "refundType": "@returnPolicy.GetRawValueString("RefundType")",
4277 "applicableCountry": "@returnPolicy.GetRawValueString("ApplicableCountry")"
4278 }
4279 </text>
4280 index++;
4281
4282 if (index < returnPolicies.Count)
4283 {
4284 <text>,</text>
4285 }
4286 }
4287 }
4288 ],
4289 "contactPoint": {
4290 "@@type": "ContactPoint",
4291 "telephone": "@schemaSettings.GetRawValueString("OnlineStoreTelephone", "+4570226888")",
4292 "email": "@schemaSettings.GetRawValueString("OnlineStoreEmail", "support@philipsonwine.com")",
4293 "contactType": "customer service",
4294 "areaServed": "DK"
4295 },
4296 @if (!string.IsNullOrEmpty(schemaSettings.GetRawValueString("OnlineStoreSameAs")))
4297 {
4298 var sameAsList = schemaSettings.GetRawValueString("OnlineStoreSameAs").Split(',');
4299 var index = 0;
4300 <text>
4301 "sameAs": [
4302 @foreach (var sameAs in sameAsList)
4303 {
4304 <text>
4305 "@sameAs"
4306 </text>
4307 index++;
4308 if (index < sameAsList.Count())
4309 {
4310 <text>,</text>
4311 }
4312 }
4313 ],
4314 </text>
4315 }
4316 "department": {
4317 "@@type": "LiquorStore",
4318 "name": "@schemaSettings.GetRawValueString("DepartmentName", "Philipson Wine Butik")",
4319 "@@id": "https://philipsonwine.com/#LiquorStore",
4320 "url": "https://philipsonwine.com/",
4321 "telephone": "@schemaSettings.GetRawValueString("DepartmentTelephone", "+4570226888")",
4322 "priceRange": "$$",
4323 "currenciesAccepted": "@schemaSettings.GetRawValueString("DepartmentCurrenciesAccepted", "DKK")",
4324 "paymentAccepted": "@schemaSettings.GetRawValueString("DepartmentPaymentsAccepted", "Cash, Credit Card, MobilePay")",
4325 "brand": {
4326 "@@id": "https://philipsonwine.com/#organization"
4327 },
4328 "knowsLanguage": [
4329 @{
4330 var lanCount = 0;
4331 }
4332
4333 @foreach (var knownLang in schemaSettings.GetRawValueString("DepartmentKnownLanguages", "da,en").Split(',').ToList())
4334 {
4335 <text>
4336 "@knownLang"
4337 </text>
4338 lanCount++;
4339 if (lanCount < schemaSettings.GetRawValueString("DepartmentKnownLanguages", "da,en").Split(',').ToList().Count())
4340 {
4341 <text>,</text>
4342 }
4343 }
4344
4345 ],
4346 "hasCertification": [
4347 @if(certifications.Any())
4348 {
4349 var index = 0;
4350
4351 foreach (var certification in certifications)
4352 {
4353 <text>
4354 {
4355 "@@type": "Certification",
4356 "name": "@certification.GetRawValueString("Name")",
4357 "description": "@certification.GetRawValueString("Description")",
4358 "certificationStatus": "@certification.GetRawValueString("Status")",
4359 "url": "@certification.GetRawValueString("Link")",
4360 "certificationIdentification": "@certification.GetRawValueString("Identification")",
4361 "logo": "@certification.GetRawValueString("Logo")",
4362 "issuedBy": {
4363 "@@type": "Organization",
4364 "name": "@certification.GetRawValueString("IssuerName")",
4365 "url": "@certification.GetRawValueString("IssuerUrl")"
4366 }
4367 }
4368 </text>
4369 index++;
4370 if (index < certifications.Count)
4371 {
4372 <text>,</text>
4373 }
4374 }
4375 }
4376 ],
4377 "address": {
4378 "@@type": "PostalAddress",
4379 "streetAddress": "@schemaSettings.GetRawValueString("DepartmentAddress", "Kokkedal Industripark 10")",
4380 "addressLocality": "@schemaSettings.GetRawValueString("DepartmentCity", "Kokkedal")",
4381 "postalCode": "@schemaSettings.GetRawValueString("DepartmentZip", "2980")",
4382 "addressCountry": "@schemaSettings.GetRawValueString("DepartmentCountryCode", "DK")"
4383 },
4384 @{
4385 var location = schemaSettings.GetRawValueString("DepartmentLocation", "55.90391229999999;12.4796683").Split(';');
4386 }
4387 "geo": {
4388 "@@type": "GeoCoordinates",
4389 "latitude": @location.First(),
4390 "longitude": @location.Last()
4391 },
4392 "openingHoursSpecification": [
4393 @if (openingHours.Any())
4394 {
4395 var index = 0;
4396
4397 foreach (var openingHour in openingHours)
4398 {
4399 var days = openingHour.GetRawValueString("Weekdays").Split(',').ToList();
4400 <text>
4401 {
4402 "@@type": "OpeningHoursSpecification",
4403 "dayOfWeek": @if(days.Count() > 1)
4404 {
4405 <text>
4406 [
4407 @{
4408 var dayCount = 0;
4409 }
4410 @foreach(var day in days)
4411 {
4412 <text>
4413 "@day"
4414 </text>
4415 dayCount++;
4416 if (dayCount < days.Count())
4417 {
4418 <text>,</text>
4419 }
4420 }
4421 ],
4422 </text>
4423 }
4424 else
4425 {
4426 <text>"@days.First()",</text>
4427 }
4428 "opens": "@openingHour.GetRawValueString("Opens")",
4429 "closes": "@openingHour.GetRawValueString("Closes")"
4430 }
4431 </text>
4432 index++;
4433 if (index < openingHours.Count)
4434 {
4435 <text>,</text>
4436 }
4437 }
4438 }
4439 ]
4440 }
4441 }
4442 ]
4443 }
4444 </script>
4445 }
4446 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>
4447
4448 @using System
4449 @using System.Web
4450 @using System.Collections.Generic
4451 @using Dynamicweb.Rapido.Blocks
4452 @using Dynamicweb.Rapido.Blocks.Extensibility
4453 @using Dynamicweb.Security.UserManagement
4454 @using Dynamicweb.Security.UserManagement.ExternalAuthentication
4455 @using Dynamicweb.Rapido.Blocks.Components.General
4456 @using Smartpage.Segment.Providers;
4457
4458 @{
4459 BlocksPage loginBlocksPage = BlocksPage.GetBlockPage("Master");
4460
4461 Block loginModal = new Block()
4462 {
4463 Id = "LoginModal",
4464 SortId = 10,
4465 Component = new Modal
4466 {
4467 Id = "SignIn",
4468 Heading = new Heading
4469 {
4470 Level = 0,
4471 Title = Translate("Sign in")
4472 },
4473 Width = ModalWidth.Xs,
4474 BodyTemplate = RenderLoginForm()
4475 }
4476 };
4477
4478 loginBlocksPage.Add(MasterBlockId.MasterTopSnippets, loginModal);
4479 }
4480
4481 @helper RenderLoginForm()
4482 {
4483 int pageId = Model.TopPage.ID;
4484 int currentPageId = Pageview.ID;
4485 string userSignedInErrorText = "";
4486 int signInProfilePageId = GetPageIdByNavigationTag("SignInPage");
4487 int cartPageId = GetPageIdByNavigationTag("CartPage");
4488 string forgotPasswordPageLink = "/Default.aspx?ID=" + signInProfilePageId + "&LoginAction=Recovery";
4489 int createAccountPageId = GetPageIdByNavigationTag("CreateAccount");
4490 bool showModalOnStart = pageId != GetPageIdByNavigationTag("CustomerCenter") && Model.LogOnFailed;
4491 bool hideCreateAccountLink = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("SignInHideCreateAccount");
4492 bool hideForgotPasswordLink = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("SignInHideForgotPasswordLink");
4493 string cartLogin = currentPageId == cartPageId ? "True" : "False";
4494
4495 if (Model.LogOnFailed)
4496 {
4497 switch (Model.LogOnFailedReason)
4498 {
4499 case LogOnFailedReason.PasswordLengthInvalid:
4500 userSignedInErrorText = Translate("Password length is invalid");
4501 break;
4502 case LogOnFailedReason.IncorrectLogin:
4503 userSignedInErrorText = Translate("Invalid email or password");
4504 break;
4505 case LogOnFailedReason.ExceededFailedLogOnLimit:
4506 userSignedInErrorText = Translate("You have exceeded the limit of allowed login attempts. The user account is temporarily locked");
4507 break;
4508 case LogOnFailedReason.LoginLocked:
4509 userSignedInErrorText = Translate("The user account is temporarily locked");
4510 break;
4511 case LogOnFailedReason.PasswordExpired:
4512 userSignedInErrorText = Translate("The password has expired and needs to be renewed");
4513 break;
4514 default:
4515 userSignedInErrorText = Translate("An unknown error occured");
4516 break;
4517 }
4518 }
4519
4520 Form form = new Form { Method = FormMethod.Post, Name = "LoginModalForm", CssClass = "u-hidden js-login-form" };
4521
4522 if (Model.LogOnFailed && !string.IsNullOrWhiteSpace(userSignedInErrorText))
4523 {
4524 string ajsAnonymousId = HttpContext.Current.Request.Cookies["ajs_anonymous_id"] != null ? HttpContext.Current.Request.Cookies["ajs_anonymous_id"].Value : "undefined";
4525 var failedLoginProperties = new Dictionary<string, object>()
4526 {
4527 { "logOnFailedReason", userSignedInErrorText },
4528 { "device", Pageview.Device.ToString() },
4529 { "ajsAnonymousId", ajsAnonymousId }
4530 };
4531 AnalyticsProvider.Track(null, "Failed Login", failedLoginProperties, Dynamicweb.Frontend.PageView.Current().Area.EcomShopId, null);
4532 }
4533
4534 if (currentPageId == cartPageId)
4535 {
4536 form.Action = "/Default.aspx?ID=" + GetPageIdByNavigationTag("CheckoutPage");
4537 }
4538
4539 form.Add(new HiddenField { Name = "ID", Value = Converter.ToString(pageId) });
4540 form.Add(new HiddenField { Name = "DWExtranetUsernameRemember", Value = "True" });
4541 form.Add(new HiddenField { Name = "DWExtranetPasswordRemember", Value = "True" });
4542 form.Add(new HiddenField { Name = "LoginAction", Value = "Login" });
4543 form.Add(new HiddenField { Name = "CartLogin", Value = cartLogin });
4544 form.Add(new TextField { Id = "LoginUsername", Name = "username", Label = Translate("Email"), CssClass = "u-full-width", Required = true });
4545 form.Add(new TextField { Id = "LoginPassword", Name = "password", Type = TextFieldType.Password, Label = Translate("Password"), CssClass = "u-full-width", Required = true });
4546 form.Add(new NotificationMessage { Message = userSignedInErrorText, MessageType = NotificationMessageType.Error });
4547 form.Add(new CheckboxField { Id = "LoginRememberMe", Value = "True", Name = "Autologin", Label = Translate("Remember me") });
4548 form.Add(new Button { ButtonType = ButtonType.Submit, Title = Translate("Sign in"), CssClass = "btn--full", OnClick = "Buttons.LockButton(event)" });
4549
4550 if (!hideCreateAccountLink)
4551 {
4552 form.Add(new Link { Href = "/default.aspx?ID=" + createAccountPageId, Title = Translate("Create account?"), ButtonLayout = ButtonLayout.None, CssClass = "u-block u-padding-bottom" });
4553 }
4554
4555 if (!hideForgotPasswordLink)
4556 {
4557 form.Add(new Link { Href = forgotPasswordPageLink, Title = Translate("Forgot your password?"), ButtonLayout = ButtonLayout.None, CssClass = "u-block u-padding-bottom" });
4558 }
4559
4560 @Render(form)
4561
4562 if (!string.IsNullOrWhiteSpace(userSignedInErrorText))
4563 {
4564 <script>
4565 window.addEventListener("DOMContentLoaded", () => {
4566 setDatalayerLoginError('@userSignedInErrorText');
4567 })
4568 </script>
4569 }
4570
4571 if (showModalOnStart)
4572 {
4573 <script>
4574 document.getElementById("SignInModalTrigger").checked = true;
4575 document.querySelector('.js-login-form')?.classList.remove('u-hidden');
4576 </script>
4577 }
4578 }
4579
4580 @if (!isHeaderHidden)
4581 {
4582 if (Pageview.Device != Dynamicweb.Frontend.Devices.DeviceType.Desktop)
4583 {
4584 <text>@inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
4585 @using System
4586 @using System.Web
4587 @using System.Collections.Generic
4588 @using Dynamicweb.Rapido.Blocks.Extensibility
4589 @using Dynamicweb.Rapido.Blocks
4590 @using Smartpage.PhilipsonWine.Ecommerce.CartInformation;
4591 @using Smartpage.PhilipsonWine.LiveShopper.Models;
4592 @using Dynamicweb.Frontend
4593
4594 @functions {
4595 BlocksPage mobileHeaderBlocksPage = BlocksPage.GetBlockPage("Master");
4596 }
4597
4598 @{
4599 var mobileTopLayout = !String.IsNullOrEmpty(Model.Area.Item.GetItem("Layout").GetItem("MobileTop").GetString("Design")) ? Model.Area.Item.GetItem("Layout").GetItem("MobileTop").GetList("Design").SelectedValue : "nav-left";
4600 bool mobileHideSearch = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("HideSearch");
4601 bool mobileHideCart = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("HideCart") || !Dynamicweb.Rapido.Services.User.IsBuyingAllowed();
4602
4603 if (Pageview.Device != Dynamicweb.Frontend.Devices.DeviceType.Desktop)
4604 {
4605 Block mobileHeader = new Block()
4606 {
4607 Id = "MobileTop",
4608 SortId = 10,
4609 Template = RenderMobileTop(),
4610 SkipRenderBlocksList = true
4611 };
4612 mobileHeaderBlocksPage.Add(MasterBlockId.MasterHeader, mobileHeader);
4613 }
4614
4615 Block mobileHeaderNavigation = new Block()
4616 {
4617 Id = "MobileHeaderNavigation",
4618 SortId = 10,
4619 Template = RenderMobileHeaderNavigation(),
4620 SkipRenderBlocksList = true
4621 };
4622 mobileHeaderBlocksPage.Add("MobileTop", mobileHeaderNavigation);
4623
4624 Block mobileHeaderLogo = new Block()
4625 {
4626 Id = "MobileHeaderLogo",
4627 SortId = 20,
4628 Template = RenderMobileHeaderLogo(),
4629 SkipRenderBlocksList = true
4630 };
4631 mobileHeaderBlocksPage.Add("MobileTop", mobileHeaderLogo);
4632
4633 Block mobileHeaderActions = new Block()
4634 {
4635 Id = "MobileHeaderActions",
4636 SortId = 30,
4637 Template = RenderMobileTopActions(),
4638 SkipRenderBlocksList = true
4639 };
4640 mobileHeaderBlocksPage.Add("MobileTop", mobileHeaderActions);
4641
4642 Block mobileHeaderNavigationTriggerBlock = new Block()
4643 {
4644 Id = "MobileHeaderNavigationTrigger",
4645 SortId = 10,
4646 Template = RenderMobileHeaderNavigationTrigger()
4647 };
4648 mobileHeaderBlocksPage.Add("MobileTop", mobileHeaderNavigationTriggerBlock);
4649
4650 Block mobileHeaderMiniCart;
4651
4652 if (!mobileHideCart)
4653 {
4654 mobileHeaderMiniCart = new Block
4655 {
4656 Id = "MobileHeaderMiniCart",
4657 SortId = 20,
4658 Template = RenderMobileTopMiniCart()
4659 };
4660
4661 Block miniCartCounterScriptTemplate = new Block
4662 {
4663 Id = "MiniCartCounterScriptTemplate",
4664 Template = RenderMobileMiniCartCounterContent()
4665 };
4666 BlocksPage.GetBlockPage("Master").Add("MasterBottomSnippets", miniCartCounterScriptTemplate);
4667 }
4668 else
4669 {
4670 mobileHeaderMiniCart = new Block
4671 {
4672 Id = "MobileHeaderMiniCart",
4673 SortId = 20
4674 };
4675 }
4676
4677 Block mobileHeaderCustomerCenterBlock = new Block
4678 {
4679 Id = "MobileHeaderCustomerCenter",
4680 SortId = 10,
4681 Template = RenderMobileCustomerCenterAction()
4682 };
4683 mobileHeaderBlocksPage.Add("MobileHeaderActions", mobileHeaderCustomerCenterBlock);
4684
4685 switch (mobileTopLayout)
4686 {
4687 case "nav-left":
4688 mobileHeaderNavigation.SortId = 10;
4689 mobileHeaderLogo.SortId = 20;
4690 mobileHeaderActions.SortId = 30;
4691 mobileHeaderNavigationTriggerBlock.SortId = 30;
4692 mobileHeaderBlocksPage.Add("MobileHeaderActions", mobileHeaderMiniCart);
4693 break;
4694 case "nav-right":
4695 mobileHeaderLogo.SortId = 10;
4696 mobileHeaderActions.SortId = 20;
4697 mobileHeaderNavigation.SortId = 30;
4698 mobileHeaderNavigationTriggerBlock.SortId = 30;
4699 mobileHeaderBlocksPage.Add("MobileHeaderActions", mobileHeaderMiniCart);
4700 break;
4701 case "nav-search-left":
4702 mobileHeaderNavigation.SortId = 10;
4703 mobileHeaderLogo.SortId = 20;
4704 mobileHeaderActions.SortId = 30;
4705 mobileHeaderNavigationTriggerBlock.SortId = 30;
4706 mobileHeaderBlocksPage.Add("MobileHeaderNavigation", mobileHeaderMiniCart);
4707 break;
4708 case "search-left":
4709 mobileHeaderActions.SortId = 10;
4710 mobileHeaderLogo.SortId = 20;
4711 mobileHeaderNavigation.SortId = 30;
4712 mobileHeaderMiniCart.SortId = 0;
4713 mobileHeaderNavigationTriggerBlock.SortId = 30;
4714 mobileHeaderBlocksPage.Add("MobileHeaderNavigation", mobileHeaderMiniCart);
4715 break;
4716 case "custom":
4717 mobileHeaderActions.SortId = 100;
4718 mobileHeaderLogo.SortId = 30;
4719 mobileHeaderNavigation.SortId = 20;
4720 mobileHeaderMiniCart.SortId = 50;
4721 mobileHeaderNavigationTriggerBlock.SortId = 10;
4722 mobileHeaderBlocksPage.Add("MobileHeaderActions", mobileHeaderMiniCart);
4723 break;
4724 }
4725
4726 if (Pageview.Page.NavigationTag == "CartPage")
4727 {
4728 Block mobileCheckoutUsp = new Block
4729 {
4730 Id = "MobileCheckoutUsp",
4731 SortId = 50,
4732 Template = RenderMobileCheckoutUsp()
4733 };
4734 mobileHeaderBlocksPage.Add(MasterBlockId.MasterHeader, mobileCheckoutUsp);
4735 }
4736 }
4737
4738
4739 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
4740
4741 @using System
4742 @using System.Web
4743 @using Dynamicweb.Rapido.Blocks.Extensibility
4744 @using Dynamicweb.Rapido.Blocks
4745
4746 @{
4747 BlocksPage customMobileHeaderBlocksPage = BlocksPage.GetBlockPage("Master");
4748 }
4749
4750 @helper RenderMobileTop()
4751 {
4752 List<Block> subBlocks = this.mobileHeaderBlocksPage.GetBlockListById("MobileTop").OrderBy(item => item.SortId).ToList();
4753 var mobileTopLayout = !String.IsNullOrEmpty(Model.Area.Item.GetItem("Layout").GetItem("MobileTop").GetString("Design")) ? Model.Area.Item.GetItem("Layout").GetItem("MobileTop").GetList("Design").SelectedValue : "nav-left";
4754 DateTime now = DateTime.Now;
4755 var upcomingEvent = Dynamicweb.Context.Current.Application["SpLiveShopperEvent"] as Event;
4756 bool isEventLive = upcomingEvent != null && upcomingEvent.Start > now && upcomingEvent.End < now;
4757 ItemViewModel sommifySettings = PageView.Current().AreaSettings.GetItem("Custom").GetItem("SommifySettings");
4758 bool sommifyIsActive = false;
4759 if (sommifySettings != null)
4760 {
4761 bool activateSommify = sommifySettings.GetBoolean("ActivateSommify");
4762 string sommifyApiKey = sommifySettings.GetRawValueString("SommifyApiKey");
4763 sommifyIsActive = activateSommify && !string.IsNullOrEmpty(sommifyApiKey);
4764 }
4765
4766 <nav class="main-navigation-mobile dw-mod js-navigation-mobile js-main-navigation-mobile @mobileTopLayout" data-use-retractable-menu="@Model.Area.Item.GetItem("Custom").GetBoolean("RetractableMenu")">
4767 <div class="center-container top-container__center-container dw-mod">
4768 <div class="grid grid--align-center">
4769 @RenderBlockList(subBlocks)
4770 </div>
4771 </div>
4772 <div class="navigation-search-container">
4773 <div class="mobile-navigation-search-button header js-open-search" style="@(sommifyIsActive ? "border-radius: 10px 0px 0px 10px;" : "")">
4774 <i class="far fa-search"></i>
4775 <p>@Translate("Smartpage:MobilMenu.SearchButtonText", "Søg efter produkter eller indhold")</p>
4776 </div>
4777 @if (sommifyIsActive)
4778 {
4779 string sommifyIcon = sommifySettings.GetRawValueString("SommifyIcon");
4780 string sommifyBackgroundColor = sommifySettings.GetRawValueString("SommifyBackgroundColor");
4781 string sommifyStyling = !string.IsNullOrEmpty(sommifyBackgroundColor) ? "background-color: " + sommifyBackgroundColor + ";" : "";
4782
4783 <div class="header-menu__link header-menu__link--icon sommify-header-container js-sommify-widget-activator dw-mod" style="@sommifyStyling">
4784 <div class="custom__header__icon__icon">
4785 @if (!string.IsNullOrEmpty(sommifyIcon))
4786 {
4787 <img class="sommify-header-icon" src="@sommifyIcon" />
4788 }
4789 </div>
4790 <div class="custom__header__icon__text sommify-header-text">
4791 @Translate("Smartpage:Header.Sommify.Text", "Wine AI")
4792 </div>
4793 </div>
4794 }
4795 </div>
4796 @if (upcomingEvent != null && isEventLive)
4797 {
4798 <div class="liveshopping-mobile">
4799 <div class="pulsating-circle"></div>
4800 <a href="/Default.aspx?ID=@GetPageIdByNavigationTag("LiveshoppingPage")">
4801 @Translate("Smartpage:Header.LiveshoppingTextMobile", "Vi sender LIVE nu!")
4802 </a>
4803 </div>
4804 }
4805 </nav>
4806 }
4807
4808 @helper RenderMobileHeaderNavigation()
4809 {
4810 List<Block> subBlocks = this.mobileHeaderBlocksPage.GetBlockListById("MobileHeaderNavigation").OrderBy(item => item.SortId).ToList();
4811 if (subBlocks.Any())
4812 {
4813 <div class="grid__col-auto-width">
4814 <ul class="menu dw-mod">
4815 @RenderBlockList(subBlocks)
4816 </ul>
4817 </div>
4818 }
4819 }
4820
4821 @helper RenderMobileHeaderNavigationTrigger()
4822 {
4823 <li class="mobile-navigation-trigger js-mobile-navigation-trigger">
4824 <label for="MobileNavTrigger" class="mobile-nav-trigger-button menu__link menu__link--icon menu__link--mobile dw-mod"></label>
4825 </li>
4826 }
4827
4828 @helper RenderMobileHeaderLogo()
4829 {
4830 List<Block> subBlocks = this.mobileHeaderBlocksPage.GetBlockListById("MobileHeaderLogo").OrderBy(item => item.SortId).ToList();
4831
4832 var mobileTopLayout = !String.IsNullOrEmpty(Model.Area.Item.GetItem("Layout").GetItem("MobileTop").GetString("Design")) ? Model.Area.Item.GetItem("Layout").GetItem("MobileTop").GetList("Design").SelectedValue : "nav-left";
4833 string centeredLogo = mobileTopLayout != "nav-right" ? "u-ta-center" : "";
4834 string firstPageId = Model.Area.FirstActivePage.ID.ToString();
4835 string businessName = Model.Area.Item.GetItem("Settings").GetString("BusinessName");
4836
4837 string mobileLogo = "/Files/Images/logo-dynamicweb.png";
4838 if (Model.Area.Item.GetItem("Layout").GetItem("MobileTop") != null && Model.Area.Item.GetItem("Layout").GetItem("MobileTop").GetFile("Logo") != null)
4839 {
4840 mobileLogo = Model.Area.Item.GetItem("Layout").GetItem("MobileTop").GetFile("Logo").PathUrlEncoded;
4841 }
4842
4843 if (Path.GetExtension(mobileLogo).ToLower() != ".svg")
4844 {
4845 mobileLogo = "/Admin/Public/GetImage.ashx?height=40&width=100&crop=5&Compression=75&image=" + mobileLogo;
4846 }
4847 else
4848 {
4849 mobileLogo = HttpUtility.UrlDecode(mobileLogo);
4850 }
4851
4852 if (mobileTopLayout == "custom")
4853 {
4854 centeredLogo = "u-flex";
4855 }
4856
4857 <div class="grid__col-auto grid__col--bleed">
4858 <div class="grid--justify-center grid__cell @centeredLogo">
4859 <a href="/Default.aspx?ID=@firstPageId" class="logo logo--mobile u-inline-block dw-mod">
4860 <img class="grid__cell-img logo__img logo__img--mobile dw-mod" src="@mobileLogo" alt="@businessName" />
4861 </a>
4862 </div>
4863
4864 @RenderBlockList(subBlocks)
4865 </div>
4866 }
4867
4868 @helper RenderMobileTopActions()
4869 {
4870 List<Block> subBlocks = this.mobileHeaderBlocksPage.GetBlockListById("MobileHeaderActions").OrderBy(item => item.SortId).ToList();
4871
4872 <div class="u-no-padding grid__col-6">
4873 <ul class="grid mobile-top-actions">
4874 @RenderBlockList(subBlocks)
4875 </ul>
4876 </div>
4877 }
4878
4879 @helper RenderMobileCustomerCenterAction()
4880 {
4881 var user = Dynamicweb.Security.UserManagement.User.GetCurrentExtranetUser();
4882
4883 if (user != null)
4884 {
4885 string customerDashboardLink = "/Default.aspx?Id=" + GetPageIdByNavigationTag("CustomerDashboard");
4886 <li class="grid__col-auto mobile-top-actions__action">
4887 <a href="@customerDashboardLink" class="menu__link menu__link--icon menu__link--mobile dw-mod">
4888 @RenderProfileIcon()
4889 <span class="menu__link__text">@Translate("Smartpage:MobileHeader.Profile", "Profil")</span>
4890 </a>
4891 </li>
4892 }
4893 else
4894 {
4895 <li class="grid__col-auto mobile-top-actions__action">
4896 <label for="SignInModalTrigger" class="menu__link menu__link--icon menu__link--mobile dw-mod js-sign-in-modal-trigger">
4897 @RenderProfileIcon()
4898 <span class="menu__link__text">@Translate("Smartpage:MobileHeader.Login", "Login")</span>
4899 </label>
4900 </li>
4901 }
4902
4903 }
4904
4905 @helper RenderProfileIcon()
4906 {
4907 <?xml version="1.0" encoding="UTF-8" ?>
4908
4909 <svg width="16px" height="20px" viewBox="0 0 16 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
4910 <title>60DACE7C-4BF5-4F9F-93C4-F806A7E060C8</title>
4911 <g id="Philipson-Wine" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
4912 <g id="Mobil---ny-header" transform="translate(-228.000000, -11.000000)" fill="#2A4A3A" fill-rule="nonzero">
4913 <g id="Login-mobile" transform="translate(228.000000, 11.000000)">
4914 <path d="M7.87692308,0 C5.4726297,0 3.52629696,1.94633274 3.52629696,4.35062612 C3.52629696,6.7549195 5.4726297,8.70125224 7.87692308,8.70125224 C10.2812165,8.70125224 12.2275492,6.7549195 12.2275492,4.35062612 C12.2275492,1.94633274 10.2812165,0 7.87692308,0 Z" id="Path"></path>
4915 <path d="M9.57137746,10.6003578 L6.18246869,10.6003578 C2.7706619,10.6003578 0,13.3710197 0,16.7828265 L0,19.30161 C0,19.6908766 0.297674419,19.988551 0.686940966,19.988551 L15.0669052,19.988551 C15.4561717,19.988551 15.7538462,19.6908766 15.7538462,19.30161 L15.7538462,16.7828265 C15.7538462,13.3710197 12.9831843,10.6003578 9.57137746,10.6003578 Z" id="Path"></path>
4916 </g>
4917 </g>
4918 </g>
4919 </svg>
4920 }
4921
4922 @helper RenderMobileTopMiniCart()
4923 {
4924 int miniCartFeedPageId = GetPageIdByNavigationTag("MiniCartFeed");
4925 int cartPageId = GetPageIdByNavigationTag("CartPage");
4926 double cartProductsCount = 0;
4927 string totalPrice = 0.ToString("N2");
4928 string showCounterClass = "u-hidden";
4929
4930 if (Model != null && Model.Cart != null && Model.Cart.CartOrderlines != null)
4931 {
4932 CartInformation cartInformation = new CartInformation(Model.Cart);
4933
4934 cartProductsCount = cartInformation.OrderLineCount;
4935 totalPrice = Model.Cart.TotalPrice.Price.Formatted;
4936 showCounterClass = string.Empty;
4937 }
4938
4939 <li class="grid__col-auto mobile-top-actions__action mobile-top-actions__action--mini-cart" id="miniCartWrapper">
4940 <div class="mini-cart dw-mod">
4941 <a href="/Default.aspx?ID=@cartPageId" id="miniCartCounterWrap" class="menu__link menu__link--icon menu__link--mobile dw-mod js-mini-cart-button">
4942 <div class="u-inline u-position-relative">
4943 <?xml version="1.0" encoding="UTF-8" ?>
4944 <svg width="27px" height="23px" viewBox="0 0 27 23" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
4945 <title>684ADC2E-E513-4391-ABAF-ED9723E87695</title>
4946 <g id="Philipson-Wine" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
4947 <g id="Mobil---ny-header" transform="translate(-327.000000, -8.000000)" fill="#2A4A3A">
4948 <path d="M350.342987,22.2387411 L353.077072,12.1651775 C353.114836,11.998797 353.074565,11.8242713 352.967708,11.6912695 C352.856522,11.5719381 352.704894,11.4982887 352.542387,11.4846752 L332.273764,11.4846752 L330.888495,8.44182719 C330.844749,8.16203921 330.586037,7.96803313 330.305223,8.00437367 L327,8.00437367 L327,9.11013998 L329.952811,9.11013998 L331.301626,12.152988 L334.035711,22.2387411 L334.10862,22.4331459 L335.056436,25.8841871 C334.161821,26.361 333.611928,27.3009555 333.634712,28.3145034 L333.634712,28.8734529 L333.695488,28.8734529 C333.939334,30.1096578 335.023741,31.0005706 336.283755,31.000055 C337.775597,31.0066653 338.992321,29.8062883 339.005707,28.3144465 C338.990442,27.744162 338.799454,27.1924465 338.45889,26.7347722 L345.907732,26.7347722 C345.571497,27.1939275 345.384839,27.7454721 345.373048,28.3144465 C345.386434,29.8062883 346.603101,31.0066653 348.095,31.000055 C349.355014,31.0005137 350.439421,30.1096008 350.683267,28.8734529 L350.744043,28.8734529 L350.744043,28.3145034 C350.757486,26.8448191 349.576931,25.6425624 348.107303,25.6291198 C348.099158,25.6290628 348.091013,25.6290059 348.082868,25.6290059 L336.283755,25.6290059 L336.101483,25.6290059 L335.639707,23.9035137 C335.84727,23.9723785 336.065085,24.0052445 336.283755,24.0007446 L348.082811,24.0007446 C349.149161,23.9955043 350.077781,23.2715984 350.342987,22.2387411 Z M348.0103,26.6991721 C348.889252,26.6791222 349.617999,27.3754024 349.637992,28.2543536 C349.638448,28.2744035 349.638505,28.2944535 349.63822,28.3145034 C349.638448,29.1728921 348.953161,29.8744126 348.095,29.8941777 L348.082868,29.8820452 C347.203916,29.9020952 346.475169,29.205815 346.455176,28.3268638 C346.435069,27.4479126 347.131349,26.7191651 348.0103,26.6991721 Z M336.332684,26.6987164 C337.211578,26.712216 337.913155,27.4356092 337.899884,28.3145034 C337.907004,29.180183 337.211008,29.8877982 336.345329,29.8949182 C336.324823,29.8950891 336.304261,29.8948613 336.283755,29.8942347 L336.283755,29.8821022 C335.40469,29.8686027 334.703055,29.1449816 334.716612,28.2659734 C334.730168,27.3869653 335.453675,26.6851599 336.332684,26.6987164 Z" id="Cart-mobile"></path>
4949 </g>
4950 </g>
4951 </svg>
4952 <div class="mini-cart__counter dw-mod @showCounterClass">
4953 <div class="js-handlebars-root js-mini-cart-counter" id="cartCounter" data-template="MiniCartCounterContent" data-json-feed="/Default.aspx?ID=@miniCartFeedPageId&feedType=Counter" data-init-onload="false" data-preloader="false">
4954 <div class="js-mini-cart-counter-content u-ta-center" data-count="@cartProductsCount">
4955 @cartProductsCount
4956 </div>
4957 </div>
4958 </div>
4959 </div>
4960 </a>
4961 <div class="js-handlebars-root js-mini-cart-counter u-ta-center" id="cartCounterPrice" data-template="MiniCartCounterPrice" data-json-feed="/Default.aspx?ID=@miniCartFeedPageId&feedType=Counter" data-init-onload="false" data-preloader="false">
4962 <span class="menu__link__text js-mini-cart-total-price">@totalPrice</span>
4963 </div>
4964 </div>
4965 </li>
4966 }
4967
4968 @helper RenderMobileMiniCartCounterContent()
4969 {
4970 <script id="MiniCartCounterContent" type="text/x-template">
4971 {{#.}}
4972 <div class="js-mini-cart-counter-content dw-mod" data-count="{{numberofproducts}}">
4973 {{numberofproducts}}
4974 </div>
4975 {{/.}}
4976 </script>
4977
4978 <script id="MiniCartCounterPrice" type="text/x-template">
4979 {{#.}}
4980 <span class="menu__link__text js-mini-cart-total-price">{{totalprice}}</span>
4981 {{/.}}
4982 </script>
4983 }
4984
4985 @helper RenderMobileCheckoutUsp()
4986 {
4987 <div class="custom__checkout__headerusp usp-swiper-container">
4988 <div class="swiper-wrapper">
4989 @RenderMobileUsp("help", Translate("Smartpage:Checkout.Brug for hælp?", "Brug for hælp?"), Translate("Smartpage:Checkout.Tel: 70 22 68 88", "Tel: 70 22 68 88"))
4990 @RenderMobileUsp("Secure", Translate("Smartpage:Checkout.Sikker betaling", "Sikker betaling"), Translate("Smartpage:Checkout.Krypteret betaling", "Krypteret betaling"))
4991 @RenderMobileUsp("delivery", Translate("Smartpage:Checkout.Hurtig levering", "Hurtig levering"), Translate("Smartpage:Checkout.1-2 dages levering", "1-2 dages levering"))
4992 @RenderMobileUsp("tilfredshed", Translate("Smartpage:Checkout.100% tilfredshed!", "100% tilfredshed!"), Translate("Smartpage:Checkout.Du kan nemt sende retur", "Du kan nemt sende retur"))
4993 </div>
4994 </div>
4995 }
4996
4997 @helper RenderMobileUsp(string icon, string toptext, string bottomtext)
4998 {
4999 string svg = icon + ".svg";
5000
5001 <div class="swiper-slide">
5002 <div class="u-flex u-padding">
5003 <div class="u-margin-right">
5004 <img src="/Files/Images/SvgIcons/@svg" height="28" width="28" />
5005 </div>
5006 <div class="swiper-slide__text-section">
5007 <div class="u-block">
5008 <strong>@toptext</strong>
5009 </div>
5010 <div class="u-block">
5011 @bottomtext
5012 </div>
5013 </div>
5014 </div>
5015 </div>
5016 }
5017 </text>
5018 <text>@inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
5019 @using System
5020 @using System.Web
5021 @using System.Collections.Generic
5022 @using Dynamicweb.Rapido.Blocks.Extensibility
5023 @using Dynamicweb.Rapido.Blocks
5024 @using System.Text.RegularExpressions
5025 @using Dynamicweb.Ecommerce.International
5026 @using Dynamicweb.Core
5027 @using Custom.PhilipsonWine.Security.Helpers
5028
5029 @functions {
5030 BlocksPage mobileNavigationBlocksPage = BlocksPage.GetBlockPage("Master");
5031 }
5032
5033 @{
5034 bool mobileNavigationItemsHideSignIn = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("HideSignIn");
5035 bool mobileHideCreateAccountLink = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("SignInHideCreateAccount");
5036 bool mobileHideMyProfileLink = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("SignInHideProfile");
5037 bool mobileHideMyOrdersLink = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("SignInHideOrders");
5038 bool mobileHideMySavedCardsLink = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("SignInHideSavedCards");
5039 bool mobileHideMyFavoritesLink = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("SignInHideFavorites");
5040 bool mobileHideCustomerStockLink = false;
5041
5042 List<Currency> currencies = Dynamicweb.Ecommerce.Services.Currencies.GetCurrenciesForLanguage(Dynamicweb.Ecommerce.Common.Context.LanguageID).ToList();
5043
5044 Block mobileNavigation = new Block()
5045 {
5046 Id = "MobileNavigation",
5047 SortId = 10,
5048 Template = MobileNavigation(currencies),
5049 SkipRenderBlocksList = true
5050 };
5051 mobileNavigationBlocksPage.Add(MasterBlockId.MasterTopSnippets, mobileNavigation);
5052
5053 if (Model.CurrentUser.ID > 0 && !mobileHideMyProfileLink)
5054 {
5055 Block mobileNavigationSignIn = new Block
5056 {
5057 Id = "MobileNavigationSignIn",
5058 SortId = 10,
5059 Template = RenderMobileNavigationSignIn()
5060 };
5061 mobileNavigationBlocksPage.Add("MobileNavigation", mobileNavigationSignIn);
5062 }
5063
5064 Block mobileNavigationMenu = new Block
5065 {
5066 Id = "MobileNavigationMenu",
5067 SortId = 20,
5068 Template = RenderMobileNavigationMenu()
5069 };
5070 mobileNavigationBlocksPage.Add("MobileNavigation", mobileNavigationMenu);
5071
5072 Block mobileNavigationActions = new Block
5073 {
5074 Id = "MobileNavigationActions",
5075 SortId = 40,
5076 Template = RenderMobileNavigationActions(),
5077 SkipRenderBlocksList = true
5078 };
5079 mobileNavigationBlocksPage.Add("MobileNavigation", mobileNavigationActions);
5080
5081 NewsletterSignupHelperContext newsletterSignupHelperContext = new NewsletterSignupHelperContext
5082 {
5083 Pageview = Pageview,
5084 GetPageIdByNavigationTag = tag => GetPageIdByNavigationTag(tag),
5085 Translate = (text, def) => Translate(text, def)
5086 };
5087
5088 Block mobileNavigationNewsletterSignup = new Block
5089 {
5090 Id = "MobileNavigationNewsletterSignup",
5091 SortId = 30,
5092 Template = RenderNewsletterSignUp(newsletterSignupHelperContext, "Sidemenu", Pageview.AreaSettings.GetItem("Custom").GetRawValueString("SignupNewsletterId")),
5093 SkipRenderBlocksList = true
5094 };
5095 mobileNavigationBlocksPage.Add("MobileNavigation", mobileNavigationNewsletterSignup);
5096
5097 if (!mobileNavigationItemsHideSignIn)
5098 {
5099 if (Model.CurrentUser.ID <= 0)
5100 {
5101 Block mobileNavigationSignInAction = new Block
5102 {
5103 Id = "MobileNavigationSignInAction",
5104 SortId = 10,
5105 Template = RenderMobileNavigationSignInAction()
5106 };
5107 mobileNavigationBlocksPage.Add("MobileNavigationActions", mobileNavigationSignInAction);
5108
5109 if (!mobileHideCreateAccountLink)
5110 {
5111 Block mobileNavigationCreateAccountAction = new Block
5112 {
5113 Id = "MobileNavigationCreateAccountAction",
5114 SortId = 20,
5115 Template = RenderMobileNavigationCreateAccountAction()
5116 };
5117 mobileNavigationBlocksPage.Add("MobileNavigationActions", mobileNavigationCreateAccountAction);
5118 }
5119 }
5120 else
5121 {
5122 if (!mobileHideMyOrdersLink)
5123 {
5124 Block mobileNavigationOrdersAction = new Block
5125 {
5126 Id = "MobileNavigationOrdersAction",
5127 SortId = 20,
5128 Template = RenderMobileNavigationOrdersAction()
5129 };
5130 mobileNavigationBlocksPage.Add("MobileNavigationActions", mobileNavigationOrdersAction);
5131 }
5132 if (!mobileHideMyFavoritesLink)
5133 {
5134 Block mobileNavigationFavoritesAction = new Block
5135 {
5136 Id = "MobileNavigationFavoritesAction",
5137 SortId = 30,
5138 Template = RenderMobileNavigationFavoritesAction()
5139 };
5140 mobileNavigationBlocksPage.Add("MobileNavigationActions", mobileNavigationFavoritesAction);
5141 }
5142 if (!mobileHideMySavedCardsLink)
5143 {
5144 Block mobileNavigationSavedCardsAction = new Block
5145 {
5146 Id = "MobileNavigationFavoritesAction",
5147 SortId = 30,
5148 Template = RenderMobileNavigationSavedCardsAction()
5149 };
5150 mobileNavigationBlocksPage.Add("MobileNavigationActions", mobileNavigationSavedCardsAction);
5151 }
5152
5153 if (!mobileHideCustomerStockLink)
5154 {
5155 Block mobileNavigationCustomerStockAction = new Block
5156 {
5157 Id = "MobileNavigationCustomerStockAction",
5158 SortId = 31,
5159 Template = RenderMobileNavigationCustomerStockAction()
5160 };
5161 mobileNavigationBlocksPage.Add("MobileNavigationActions", mobileNavigationCustomerStockAction);
5162 }
5163
5164 Block mobileNavigationSignOutAction = new Block
5165 {
5166 Id = "MobileNavigationSignOutAction",
5167 SortId = 50,
5168 Template = RenderMobileNavigationSignOutAction()
5169 };
5170 mobileNavigationBlocksPage.Add("MobileNavigationActions", mobileNavigationSignOutAction);
5171 }
5172 }
5173
5174 var languages = Model.Languages.Where(l => Dynamicweb.Services.Areas.GetArea(l.ID).Published).ToList();
5175
5176 if (languages.Count > 1)
5177 {
5178 Block mobileNavigationLanguagesAction = new Block
5179 {
5180 Id = "MobileNavigationLanguagesAction",
5181 SortId = 60,
5182 Template = RenderMobileNavigationLanguagesAction(languages)
5183 };
5184 mobileNavigationBlocksPage.Add("MobileNavigationActions", mobileNavigationLanguagesAction);
5185 }
5186
5187 if (currencies.Count > 1)
5188 {
5189 mobileNavigationBlocksPage.Add("MobileNavigationActions", new Block
5190 {
5191 Id = "MobileNavigationCurrenciesAction",
5192 SortId = 60,
5193 Template = RenderMobileNavigationCurrenciesAction(currencies)
5194 });
5195 }
5196 }
5197
5198
5199 @helper MobileNavigation(List<Currency> currencies)
5200 {
5201 List<Block> subBlocks = this.mobileNavigationBlocksPage.GetBlockListById("MobileNavigation").OrderBy(item => item.SortId).ToList();
5202 string mobileTopDesign = Model.Area.Item.GetItem("Layout").GetItem("MobileTop").GetList("Design") != null ? Model.Area.Item.GetItem("Layout").GetItem("MobileTop").GetList("Design").SelectedValue : "nav-left";
5203 string position = mobileTopDesign == "nav-left" || mobileTopDesign == "nav-search-left" ? "left" : "right";
5204
5205 <!-- Trigger for mobile navigation -->
5206 <input type="checkbox" id="MobileNavTrigger" class="mobile-nav-trigger mobile-nav-trigger--@position" autocomplete="off" />
5207
5208 <!-- Mobile navigation -->
5209 <nav class="mobile-navigation mobile-navigation--@position dw-mod js-mobile-navigation">
5210 <div class="mobile-navigation__wrapper" id="mobileNavigationWrapper">
5211 <div class="mobile-navigation-header">
5212 <div class="mobile-navigation-header-topbar">
5213 <p>@Translate("Smartpage:MobilMenu.headerText", "Brug for hjælp? +45 70 22 68 88")</p>
5214 @if (currencies.Count > 1)
5215 {
5216 bool languageSelectionFromCookie = Dynamicweb.Environment.CookieManager.GetCookie("ActiveLanguageSelection") != null && Dynamicweb.Core.Converter.ToBoolean(Dynamicweb.Environment.CookieManager.GetCookie("ActiveLanguageSelection").Value);
5217 <div class="mobile-navigation-header-currency">
5218 <select onchange="javascript:location.href=this.value;">
5219 <option disabled selected hidden>@string.Format(Translate("Smartpage:MobilMenu.Currency", "Valuta: {0}"), Dynamicweb.Ecommerce.Common.Context.Currency.Code)</option>
5220 @foreach (Currency currency in currencies)
5221 {
5222 var pageId = Pageview.Page.ID;
5223
5224 if (!languageSelectionFromCookie)
5225 {
5226
5227 var currencyLanguageMapping = Pageview.AreaSettings.GetItem("Custom").GetItems("CurrencyLanguageMapping")?.FirstOrDefault(m => m.GetRawValueString("Currency") == currency.Code);
5228 if (currencyLanguageMapping != null)
5229 {
5230 var language = Model.Languages.FirstOrDefault(l => l.ID == Dynamicweb.Core.Converter.ToInt32(currencyLanguageMapping.GetRawValueString("Language")));
5231
5232 if (language != null)
5233 {
5234 pageId = language.Page.ID;
5235 }
5236 }
5237 }
5238 var qs = HttpUtility.ParseQueryString(Dynamicweb.Context.Current.Request.QueryString.ToString());
5239 qs.Set("ID", Converter.ToString(pageId));
5240 qs.Set("CurrencyCode", currency.Code);
5241 string url = Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl("Default.aspx?" + qs);
5242
5243 <option value="@url">@currency.Code</option>
5244 }
5245 </select>
5246 </div>
5247 }
5248 <div class="mobile-navigation-header-close js-navigation-close">
5249 <div class="mobile-navigation-header-cross">
5250 <span></span>
5251 <span></span>
5252 </div>
5253 </div>
5254 </div>
5255 <div class="mobile-navigation-search-button js-open-search">
5256 <i class="far fa-search"></i>
5257 <p>@Translate("Smartpage:MobilMenu.NavigatioSearchButtonText", "Søg efter produkter eller indhold")</p>
5258 </div>
5259 </div>
5260 @RenderBlockList(subBlocks)
5261 </div>
5262 <div class="mobile-navigation-footer">
5263 <ul>
5264 @foreach (var icon in Pageview.AreaSettings.GetItem("Custom").GetItem("CustomSettings").GetItems("HeaderUSP"))
5265 {
5266 <li>
5267 @if (!string.IsNullOrWhiteSpace(icon.GetString("Link")))
5268 {
5269 <a href="@icon.GetString("Link")"><i class="fa fa-check"></i> @icon.GetString("Label")</a>
5270 }
5271 else
5272 {
5273 <i class="fa fa-check"></i> @icon.GetString("Label")
5274 }
5275 </li>
5276 }
5277 </ul>
5278 </div>
5279 </nav>
5280
5281 <div class="search-overlay-header js-overlay-search">
5282 @RenderOverlaySearchBar()
5283 </div>
5284
5285 <label class="mobile-nav-trigger-off js-mobile-nav-trigger-off" for="MobileNavTrigger"></label>
5286 }
5287
5288 @helper RenderMobileNavigationSignIn()
5289 {
5290 int signInProfilePageId = GetPageIdByNavigationTag("SignInPage");
5291 int myProfilePageId = GetPageIdByNavigationTag("CustomerProfile");
5292 string linkStart = Model.CurrentUser.ID <= 0 ? "/Default.aspx?ID=" + signInProfilePageId + "&RedirectPageId=" : "/Default.aspx?ID=";
5293 string myProfilePageLink = linkStart + myProfilePageId;
5294 string userName = Model.CurrentUser.FirstName;
5295 string bonusFormatted = "";
5296
5297 double bonus = Dynamicweb.Ecommerce.Services.Loyalty.GetPointsBalance(Dynamicweb.Security.UserManagement.User.GetCurrentFrontendUser());
5298
5299 if (Dynamicweb.Core.Converter.ToDouble(bonus) > 0.0)
5300 {
5301 bonusFormatted = Dynamicweb.Ecommerce.Services.Currencies.Format(Dynamicweb.Ecommerce.Common.Context.Currency, bonus);
5302 }
5303
5304 if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(Model.CurrentUser.LastName))
5305 {
5306 userName += " " + Model.CurrentUser.LastName;
5307 }
5308 if (string.IsNullOrEmpty(userName))
5309 {
5310 userName = Model.CurrentUser.Name;
5311 }
5312 if (string.IsNullOrEmpty(userName))
5313 {
5314 userName = Model.CurrentUser.UserName;
5315 }
5316 if (string.IsNullOrEmpty(userName))
5317 {
5318 userName = Model.CurrentUser.Email;
5319 }
5320
5321 <ul class="menu menu-mobile">
5322 <li class="menu-mobile__item logged-in-mobile-item">
5323 <a href="@myProfilePageLink" class="menu-mobile__link dw-mod u-flex--column">
5324 <span class="u-flex u-flex--row">
5325 <i class="@Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("SignInProfileIcon").SelectedValue menu-mobile__link-icon"></i>
5326 @userName
5327 </span>
5328 @if (!string.IsNullOrEmpty(bonusFormatted))
5329 {
5330 <span class="mobile-navigation-description">@Translate("Bonus:") @bonusFormatted</span>
5331 }
5332 </a>
5333 </li>
5334
5335 </ul>
5336 }
5337
5338 @helper RenderMobileNavigationMenu()
5339 {
5340 bool isSlidesDesign = Model.Area.Item.GetItem("Layout").GetItem("MobileNavigation").GetList("Design").SelectedValue == "Slides";
5341 string menuTemplate = isSlidesDesign ? "BaseMenuForMobileSlides.xslt" : "BaseMenuForMobileExpandable.xslt";
5342 string levels = !String.IsNullOrEmpty(Model.Area.Item.GetItem("Layout").GetItem("MobileNavigation").GetString("Levels")) ? Model.Area.Item.GetItem("Layout").GetItem("MobileNavigation").GetString("Levels") : "3";
5343 bool renderPagesInToolBar = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("RenderPagesInToolBar");
5344 int startLevel = 0;
5345
5346 var navigationSettings = new Dynamicweb.Frontend.Navigation.NavigationSettings()
5347 {
5348 RootAreaId = 0,
5349 RootPageId = 0,
5350 RootNavigationTag = "main-menu",
5351 StartLevel = 1,
5352 StopLevel = 99,
5353 ExpandMode = Dynamicweb.Frontend.Navigation.ExpandMode.All
5354 };
5355
5356 var navigationTemplate = "Navigation/SpViewModelNavigationMobile.cshtml";
5357 @Navigation.RenderNavigation(navigationTemplate, navigationSettings)
5358
5359
5360 if (isSlidesDesign)
5361 {
5362 <script>
5363 function goToLevel(level) {
5364 document.getElementById('mobileNavigationWrapper').style.left = -(level * 100) + "%";
5365 }
5366
5367 document.addEventListener('DOMContentLoaded', function () {
5368 goToLevel(document.getElementById('mobileNavigationWrapper').querySelectorAll('input[type=radio]:checked').length);
5369 });
5370 </script>
5371 }
5372
5373 if (renderPagesInToolBar)
5374 {
5375 @RenderNavigation(new
5376 {
5377 id = "topToolsMobileNavigation",
5378 cssclass = "menu menu-mobile dwnavigation",
5379 template = "ToolsMenuForMobile.xslt"
5380 })
5381 }
5382 }
5383
5384 @helper RenderMobileNavigationActions()
5385 {
5386 List<Block> subBlocks = this.mobileNavigationBlocksPage.GetBlockListById("MobileNavigationActions").OrderBy(item => item.SortId).ToList(); ;
5387
5388 <ul class="menu menu-mobile menu-mobile-actions">
5389 @RenderBlockList(subBlocks)
5390 </ul>
5391 }
5392
5393 @helper RenderMobileNavigationSignInAction()
5394 {
5395 <li class="menu-mobile__item mobile-navigation-login">
5396 <label for="SignInModalTrigger" onclick="document.getElementById('MobileNavTrigger').checked = false;" class="menu-mobile__link dw-mod menu-mobile__link--highlighted"><i class="@Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("SignInProfileIcon").SelectedValue menu-mobile__link-icon"></i> @Translate("Sign in")</label>
5397 </li>
5398 }
5399
5400 @helper RenderMobileNavigationCreateAccountAction()
5401 {
5402 int createAccountPageId = GetPageIdByNavigationTag("CreateAccount");
5403
5404 <li class="menu-mobile__item mobile-navigation-create-account">
5405 <h3>@Translate("Smartpage:MobilMenu.CreateAccountHeading", "Opret bruger og få 100 DKK i opstartsbonus")</h3>
5406 <p>@Translate("Smartpage:MobilMenu.CreateAccountText", "(Gælder på dit næste køb)")</p>
5407 <a class="menu-mobile__link menu-mobile__link--highlighted dw-mod" href="/Default.aspx?ID=@createAccountPageId"><i class="@Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("SignInProfileIcon").SelectedValue menu-mobile__link-icon"></i> @Translate("Create account")</a>
5408 </li>
5409 }
5410
5411 @helper RenderMobileNavigationCustomerStockAction()
5412 {
5413 int customerStockPageId = GetPageIdByNavigationTag("CustomerStockPage");
5414
5415 <li class="menu-mobile__item logged-in-mobile-item">
5416 <a class="menu-mobile__link menu-mobile__link--highlighted dw-mod" href="/Default.aspx?ID=@customerStockPageId"><i class="fal fa-clipboard-list menu-mobile__link-icon"></i> @Translate("Smartpage:SignInActions.CustomerStock", "Mit kundelager")</a>
5417 </li>
5418 }
5419
5420 @helper RenderMobileNavigationProfileAction()
5421 {
5422 int signInProfilePageId = GetPageIdByNavigationTag("SignInPage");
5423 string linkStart = Model.CurrentUser.ID <= 0 ? "/Default.aspx?ID=" + signInProfilePageId + "&RedirectPageId=" : "/Default.aspx?ID=";
5424 int myProfilePageId = GetPageIdByNavigationTag("CustomerProfile");
5425 string myProfilePageLink = linkStart + myProfilePageId;
5426
5427 <li class="menu-mobile__item logged-in-mobile-item">
5428 <a href="@myProfilePageLink" class="menu-mobile__link menu-mobile__link--highlighted dw-mod"><i class="@Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("SignInProfileIcon").SelectedValue menu-mobile__link-icon"></i> @Translate("My Profile")</a>
5429 </li>
5430 }
5431
5432 @helper RenderMobileNavigationOrdersAction()
5433 {
5434 int signInProfilePageId = GetPageIdByNavigationTag("SignInPage");
5435 string linkStart = Model.CurrentUser.ID <= 0 ? "/Default.aspx?ID=" + signInProfilePageId + "&RedirectPageId=" : "/Default.aspx?ID=";
5436 int myOrdersPageId = GetPageIdByNavigationTag("CustomerOrders");
5437 string myOrdersPageLink = linkStart + myOrdersPageId;
5438 string ordersIcon = "fas fa-list";
5439
5440 <li class="menu-mobile__item logged-in-mobile-item">
5441 <a href="@myOrdersPageLink" class="menu-mobile__link menu-mobile__link--highlighted dw-mod"><i class="@ordersIcon menu-mobile__link-icon"></i> @Translate("My Orders")</a>
5442 </li>
5443 }
5444
5445 @helper RenderMobileNavigationFavoritesAction()
5446 {
5447 int signInProfilePageId = GetPageIdByNavigationTag("SignInPage");
5448 string linkStart = Model.CurrentUser.ID <= 0 ? "/Default.aspx?ID=" + signInProfilePageId + "&RedirectPageId=" : "/Default.aspx?ID=";
5449 int myFavoritesPageId = GetPageIdByNavigationTag("CustomerFavorites");
5450 string myFavoritesPageLink = linkStart + myFavoritesPageId;
5451 string favoritesIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("FavoriteIcon") != null ? "fas fa-" + Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("FavoriteIcon").SelectedValue : "fa fa-star";
5452
5453
5454 <li class="menu-mobile__item logged-in-mobile-item">
5455 <a href="@myFavoritesPageLink" class="menu-mobile__link menu-mobile__link--highlighted dw-mod"><i class="@favoritesIcon menu-mobile__link-icon"></i> @Translate("My Favorites")</a>
5456 </li>
5457 }
5458
5459 @helper RenderMobileNavigationSavedCardsAction()
5460 {
5461 int signInProfilePageId = GetPageIdByNavigationTag("SignInPage");
5462 string linkStart = Model.CurrentUser.ID <= 0 ? "/Default.aspx?ID=" + signInProfilePageId + "&RedirectPageId=" : "/Default.aspx?ID=";
5463 int mySavedCardsPageId = GetPageIdByNavigationTag("SavedCards");
5464 string mySavedCardsPageLink = linkStart + mySavedCardsPageId;
5465 string savedCardsIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("SavedCards") != null ? "fas fa-" + Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("SavedCards").SelectedValue : "fas fa-credit-card";
5466
5467 <li class="menu-mobile__item logged-in-mobile-item">
5468 <a href="@mySavedCardsPageLink" class="menu-mobile__link menu-mobile__link--highlighted dw-mod"><i class="@savedCardsIcon menu-mobile__link-icon"></i> @Translate("My Saved Cards")</a>
5469 </li>
5470 }
5471
5472 @helper RenderMobileNavigationSignOutAction()
5473 {
5474 int pageId = Model.TopPage.ID;
5475 string signOutIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("SignOutIcon") != null ? "fas fa-" + Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("SignOutIcon").SelectedValue : "far fa-sign-out-alt";
5476
5477 <li class="menu-mobile__item logged-in-mobile-item">
5478 <a class="menu-mobile__link menu-mobile__link--highlighted dw-mod" href="/Admin/Public/ExtranetLogoff.aspx?ID=@pageId" onclick="RememberState.SetCookie('useAnotherAddress', false)"><i class="@signOutIcon menu-mobile__link-icon"></i> @Translate("Sign out")</a>
5479 </li>
5480 }
5481
5482 @helper RenderMobileNavigationLanguagesAction(List<Dynamicweb.Frontend.PageLanguageViewModel> languages)
5483 {
5484 <li class="menu-mobile__item mobile-navigation-language-selector">
5485 <div class="h3">@Translate("Smartpage:MobileLanguageSelector.Language", "Sprog")</div>
5486 <ul class="menu-mobile u-margin-top">
5487 @foreach (var lang in languages)
5488 {
5489 var area = Dynamicweb.Services.Areas.GetArea(lang.ID);
5490 string cultureName = Regex.Replace(Dynamicweb.Services.Areas.GetArea(lang.ID).CultureInfo.NativeName, @" ?\(.*?\)", string.Empty);
5491 cultureName = char.ToUpper(cultureName[0]) + cultureName.Substring(1);
5492 string selectedClass = lang.IsCurrent ? "u-underline" : string.Empty;
5493 string url = Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl($"Default.aspx?Id={lang.Page.ID}&CurrencyCode={area.EcomCurrencyId}&ActiveLanguageSelection=True");
5494
5495 string primaryDomain = area.DomainLock;
5496 if (!string.IsNullOrEmpty(primaryDomain))
5497 {
5498 url = HttpContext.Current.Request.Url.Scheme + "://" + primaryDomain + url;
5499 }
5500
5501 if (url.Contains("/forside"))
5502 {
5503 url = url.Replace("/forside", "");
5504 }
5505 <li class="u-ta-center">
5506 <a class="mobile-navigation-language-selector__link @selectedClass" href="@url">@cultureName</a>
5507 </li>
5508 }
5509 </ul>
5510 </li>
5511 }
5512
5513 @helper RenderMobileNavigationCurrenciesAction(List<Currency> currencies)
5514 {
5515 bool languageSelectionFromCookie = Dynamicweb.Environment.CookieManager.GetCookie("ActiveLanguageSelection") != null && Dynamicweb.Core.Converter.ToBoolean(Dynamicweb.Environment.CookieManager.GetCookie("ActiveLanguageSelection").Value);
5516 <li class="menu-mobile__item mobile-navigation-currency-selector">
5517 <div class="h3">@Translate("Smartpage:MobileCurrencySelector.Currency", "Valuta")</div>
5518 <ul class="menu-mobile u-margin-top">
5519 @foreach (Currency currency in currencies)
5520 {
5521 var pageId = Pageview.Page.ID;
5522
5523 if (!languageSelectionFromCookie)
5524 {
5525
5526 var currencyLanguageMapping = Pageview.AreaSettings.GetItem("Custom").GetItems("CurrencyLanguageMapping")?.FirstOrDefault(m => m.GetRawValueString("Currency") == currency.Code);
5527 if (currencyLanguageMapping != null)
5528 {
5529 var language = Model.Languages.FirstOrDefault(l => l.ID == Dynamicweb.Core.Converter.ToInt32(currencyLanguageMapping.GetRawValueString("Language")));
5530
5531 if (language != null)
5532 {
5533 pageId = language.Page.ID;
5534 }
5535 }
5536 }
5537
5538 var qs = HttpUtility.ParseQueryString(Dynamicweb.Context.Current.Request.QueryString.ToString());
5539 qs.Set("ID", Converter.ToString(pageId));
5540 qs.Set("CurrencyCode", currency.Code);
5541 string url = Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl("Default.aspx?" + qs);
5542
5543 var activeClass = currency.Code == Dynamicweb.Ecommerce.Common.Context.Currency.Code ? "u-underline" : string.Empty;
5544
5545 <li class="u-ta-center">
5546 <a href="@(url)" class="mobile-navigation-currency-selector__link @(activeClass)">@currency.Code</a>
5547 </li>
5548
5549 }
5550 </ul>
5551 </li>
5552 }
5553
5554 @helper RenderOverlaySearchBar()
5555 {
5556 string searchFeedId = string.Empty;
5557 string searchSecondFeedId = string.Empty;
5558 int groupsFeedId;
5559 string productsSearchId = Converter.ToString(GetPageIdByNavigationTag("ProductSearchFeed"));
5560 int productsPageId = GetPageIdByNavigationTag("ProductsPage");
5561 string contentSearchPageLink = GetPageIdByNavigationTag("ContentSearchResults") + "&Areaid=" + Model.Area.ID;
5562 string resultPageLink;
5563 string searchPlaceholder;
5564 string searchType = "product-search";
5565 string searchTemplate;
5566 string searchContentTemplate = "";
5567 string searchValue = HttpContext.Current.Request.QueryString.Get("Search") ?? "";
5568 bool showGroups = true;
5569 string beforeSearchTemplate = Pageview.AreaSettings.GetItem("Custom").GetString("MobileBeforeSearchRecommendationsTemplate");
5570
5571 if (Model.Area.Item.GetItem("Layout").GetList("TopSearch").SelectedValue == "contentSearch")
5572 {
5573 searchFeedId = GetPageIdByNavigationTag("ContentSearchFeed") + "&Areaid=" + Model.Area.ID + "&pagesOnly=true";
5574 resultPageLink = contentSearchPageLink;
5575 searchPlaceholder = Translate("Search page");
5576 groupsFeedId = 0;
5577 searchType = "content-search";
5578 searchTemplate = "SearchPagesTemplate";
5579 showGroups = false;
5580 }
5581 else if (Model.Area.Item.GetItem("Layout").GetList("TopSearch").SelectedValue == "combinedSearch")
5582 {
5583 searchFeedId = productsSearchId + "&feed=true";
5584 searchSecondFeedId = GetPageIdByNavigationTag("ContentSearchFeed") + "&Areaid=" + Model.Area.ID + "&pagesOnly=true";
5585 resultPageLink = Converter.ToString(productsPageId);
5586 searchPlaceholder = Translate("Search products or pages");
5587 groupsFeedId = GetPageIdByNavigationTag("ProductGroupsFeed");
5588 searchType = "combined-search";
5589 searchTemplate = "SearchProductsTemplateWrap";
5590 searchContentTemplate = "SearchPagesTemplateWrap";
5591 showGroups = Model.Area.Item.GetItem("Layout").GetBoolean("ShowGroupsSelector");
5592 }
5593 else
5594 {
5595 resultPageLink = Converter.ToString(productsPageId);
5596 searchFeedId = productsSearchId + "&feed=true";
5597 groupsFeedId = GetPageIdByNavigationTag("ProductGroupsFeed");
5598 searchPlaceholder = Translate("Search products");
5599 searchTemplate = "SearchResultsTypeAheadMobile";
5600 searchType = "product-search";
5601 showGroups = Model.Area.Item.GetItem("Layout").GetBoolean("ShowGroupsSelector");
5602 }
5603
5604 <input type="checkbox" id="MobileSearchTrigger" class="mobile-search-trigger" />
5605
5606 <div class="main-navigation-mobile typeahead-mobile dw-mod overlay-search">
5607 <div class="center-container top-container__center-container u-no-padding dw-mod">
5608 <div class="grid">
5609 <div class="grid__col-11 u-margin-top u-padding-right">
5610 <div class="typeahead-mobile__search-field dw-mod u-no-padding-x js-typeahead" id="MobileProductSearch" data-search-feed-id="@searchFeedId" data-search-second-feed-id="@searchSecondFeedId" data-result-page-id="@resultPageLink" data-search-type="@searchType">
5611 <form class="u-full-width" action="@Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl(productsPageId)" id="SearchSubmitForm">
5612 <input type="text" class="typeahead-autocomplete js-typeahead-autocomplete u-no-margin" disabled />
5613 <input id="TypeaheadSearchFieldMobile" type="text" class="js-typeahead-search-field u-no-margin typeahead-input-field" data-shop-id="@Pageview.Area.EcomShopId" data-area-id="@Dynamicweb.Core.Converter.ToString(Pageview.AreaID)" placeholder="@HttpUtility.HtmlAttributeEncode(searchPlaceholder)" value="@HttpUtility.HtmlAttributeEncode(searchValue)" />
5614 <button type="button" class="u-hidden js-typeahead-enter-btn"></button>
5615 <div class="mobile-clear-search-input js-mobile-clear-search-input">@Translate("Smartpage:MobilMenu.clearSearch", "Ryd")</div>
5616 </form>
5617 <span class="typeahead-search-overlay typeahead-search-container js-handlebars-root js-typeahead-search-content dw-mod" id="MobileProductSearchBarContent" data-template="@searchTemplate" data-json-feed="/Default.aspx?ID=@searchFeedId&feedType=productsOnly" data-init-onload="false"></span>
5618 </div>
5619 </div>
5620 <div class="search-overlay-header-close js-search-overlay-close grid__col-1 u-margin-top u-justify-content--center">
5621 <div class="search-overlay-header-cross">
5622 <span></span>
5623 <span></span>
5624 </div>
5625 <p class="u-no-margin--bottom">@Translate("Smartpage:MobilMenu.CloseText", "Luk")</p>
5626 </div>
5627 </div>
5628 </div>
5629 </div>
5630 }</text>
5631 }
5632 else
5633 {
5634 <text>@inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
5635
5636 @using System
5637 @using System.Web
5638 @using System.Collections.Generic
5639 @using Dynamicweb.Rapido.Blocks.Extensibility
5640 @using Dynamicweb.Rapido.Blocks
5641 @using Smartpage.PhilipsonWine.Ecommerce.CartInformation;
5642
5643 @functions {
5644 BlocksPage headerBlocksPage = BlocksPage.GetBlockPage("Master");
5645 }
5646
5647 @{
5648 Block masterTools = new Block()
5649 {
5650 Id = "MasterDesktopTools",
5651 SortId = 10,
5652 Template = RenderDesktopTools(),
5653 SkipRenderBlocksList = true,
5654 BlocksList = new List<Block>
5655 {
5656 new Block {
5657 Id = "MasterDesktopToolsText",
5658 SortId = 10,
5659 Template = RenderDesktopToolsText(),
5660 Design = new Design
5661 {
5662 Size = "auto",
5663 HidePadding = true,
5664 RenderType = RenderType.Column
5665 }
5666 },
5667 new Block {
5668 Id = "MasterDesktopToolsNavigation",
5669 SortId = 20,
5670 Template = RenderDesktopToolsNavigation(),
5671 Design = new Design
5672 {
5673 Size = "auto-width",
5674 HidePadding = true,
5675 RenderType = RenderType.Column
5676 }
5677 }
5678 }
5679 };
5680 headerBlocksPage.Add("MasterHeader", masterTools);
5681
5682 Block masterDesktopExtra = new Block()
5683 {
5684 Id = "MasterDesktopExtra",
5685 SortId = 10,
5686 Template = RenderDesktopExtra(),
5687 SkipRenderBlocksList = true
5688 };
5689 headerBlocksPage.Add("MasterHeader", masterDesktopExtra);
5690
5691 if (Pageview.Device == Dynamicweb.Frontend.Devices.DeviceType.Desktop)
5692 {
5693 Block masterDesktopNavigation = new Block()
5694 {
5695 Id = "MasterDesktopNavigation",
5696 SortId = 20,
5697 Template = RenderDesktopNavigation(),
5698 SkipRenderBlocksList = true
5699 };
5700 headerBlocksPage.Add("MasterHeader", masterDesktopNavigation);
5701 }
5702
5703
5704 }
5705
5706 @* Include the Blocks for the page *@
5707 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
5708 @using Dynamicweb.Rapido.Blocks
5709
5710 @{
5711 bool isSidemenu = Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("NavigationMegaMenu") != null ? Model.Area.Item.GetItem("Layout").GetItem("Header").GetRawValueString("NavigationMegaMenu") == "sidemenu" : false;
5712 if (isSidemenu && Pageview.Device.ToString() == "Desktop")
5713 {
5714 Block masterDesktopBurgerMenuBlock = new Block
5715 {
5716 Id = "MasterDesktopBurgerMenu",
5717 SortId = 10,
5718 Template = RenderDesktopBurgerMenu()
5719 };
5720
5721 BlocksPage.GetBlockPage("Master").Add("MasterDesktopExtra", masterDesktopBurgerMenuBlock);
5722 }
5723 }
5724
5725 @helper RenderDesktopBurgerMenu()
5726 {
5727 if (GetPageIdByNavigationTag("CheckoutPage") > 0 && (Model.ID == GetPageIdByNavigationTag("CartPage") || Model.ID == GetPageIdByNavigationTag("CheckoutPage")))
5728 {
5729 <a href="/Default.aspx?ID=@GetPageIdByNavigationTag("OffersPage")">
5730 <div class="grid__col-lg-auto-width grid__col-md-auto-width grid__col-sm-12 grid__col-xs-12 u-no-padding grid--align-self-center dw-mod cart-keep-shopping-icon-container">
5731 @RenderCartKeepShopping()
5732 <span class="keep-shopping-text">@Translate("Smartpage:Checkout.KeepShopping")</span>
5733 </div>
5734 </a>
5735 }
5736 else
5737 {
5738 <div class="grid__col-lg-auto-width grid__col-md-auto-width grid__col-sm-12 grid__col-xs-12 u-no-padding grid--align-self-center dw-mod desktop-burger-menu js-desktop-burger-menu">
5739 @RenderDesktopBurgerMenuIcon()
5740 </div>
5741 }
5742 }
5743
5744 @helper RenderDesktopBurgerMenuIcon()
5745 {
5746 <svg class="btn" xmlns="http://www.w3.org/2000/svg" width="95" height="43" viewBox="0 0 95 43">
5747 <g id="Group_121" data-name="Group 121" transform="translate(0 -3)">
5748 <g id="Rectangle_3" data-name="Rectangle 3" transform="translate(0 3)" fill="none" stroke="#fff" stroke-width="1">
5749 <rect width="95" height="43" rx="8" stroke="none" />
5750 <rect x="0.5" y="0.5" width="94" height="42" rx="7.5" fill="none" />
5751 </g>
5752 <rect id="Rectangle_5" data-name="Rectangle 5" width="15" height="2" rx="1" transform="translate(14.5 18.8)" fill="#dedede" />
5753 <rect id="Rectangle_6" data-name="Rectangle 6" width="11" height="2" rx="1" transform="translate(14.5 23.8)" fill="#dedede" />
5754 <rect id="Rectangle_7" data-name="Rectangle 7" width="15" height="2" rx="1" transform="translate(14.5 28.8)" fill="#dedede" />
5755 <text id="Menu" transform="translate(38.5 30.5)" fill="#fff" font-size="16" font-family="Mulish-Bold, Mulish" font-weight="700"><tspan x="0" y="0">@Translate("Smartpage:Desktop.Sidemenu.BurgerButton.Text", "Menu")</tspan></text>
5756 </g>
5757 </svg>
5758 }
5759
5760 @helper RenderCartKeepShopping()
5761 {
5762 <svg xmlns="http://www.w3.org/2000/svg" width="16.59" height="13.6" viewBox="0 0 16.59 13.6">
5763 <g id="Group_6" data-name="Group 6" transform="translate(26.628 88.631) rotate(180)" fill="#c3ad8f">
5764 <path id="Path_3" data-name="Path 3" d="M11.143,82.939H22.759l-3.732,3.732a1.134,1.134,0,1,0,1.6,1.6L26.3,82.607a1.134,1.134,0,0,0,0-1.6L20.63,75.338a1.134,1.134,0,0,0-1.6,1.6l3.732,3.732H11.143a1.134,1.134,0,0,0,0,2.266Z" />
5765 </g>
5766 </svg>
5767 }
5768 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
5769
5770 @using System
5771 @using System.Web
5772 @using Dynamicweb.Rapido.Blocks.Extensibility
5773 @using Dynamicweb.Rapido.Blocks
5774
5775 @{
5776 Block masterDesktopLogo = new Block
5777 {
5778 Id = "MasterDesktopLogo",
5779 SortId = 10,
5780 Template = RenderDesktopLogo(),
5781 Design = new Design
5782 {
5783 Size = "auto-width",
5784 HidePadding = true,
5785 RenderType = RenderType.Column,
5786 CssClass = "grid--align-self-center"
5787 }
5788 };
5789
5790 BlocksPage.GetBlockPage("Master").Add("MasterHeader", masterDesktopLogo);
5791 }
5792
5793
5794 @helper RenderDesktopLogo()
5795 {
5796 string firstPageId = Model.Area.FirstActivePage.ID.ToString();
5797 string topLayout = Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("TopLayout") != null ? Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("TopLayout").SelectedValue : "normal";
5798 string alignClass = topLayout == "two-lines-centered" || topLayout == "two-lines" ? "grid--align-self-center" : "";
5799 alignClass = topLayout == "splitted-center" ? "u-middle" : alignClass;
5800 string logo = Model.Area.Item.GetItem("Layout").GetFile("LogoImage") != null ? Model.Area.Item.GetItem("Layout").GetFile("LogoImage").PathUrlEncoded : "/Files/Images/logo-dynamicweb.png";
5801 if (Path.GetExtension(logo).ToLower() != ".svg")
5802 {
5803 int logoHeight = Model.Area.Item.GetItem("Layout").GetInt32("LogoHeight");
5804 logoHeight = logoHeight > 0 && Pageview.Device.ToString() != "Mobile" ? logoHeight : 40;
5805 logo = "/Admin/Public/GetImage.ashx?height=" + Converter.ToString(logoHeight) + "&crop=5&Compression=75&image=" + logo;
5806 }
5807 else
5808 {
5809 logo = HttpUtility.UrlDecode(logo);
5810 }
5811
5812 string isCartPageClass = Model.ID == GetPageIdByNavigationTag("CartPage") || Model.ID == GetPageIdByNavigationTag("CheckoutPage") ? "is-cart-page" : "";
5813 var url = Dynamicweb.Context.Current.Request.Url.Scheme + "://" + Dynamicweb.Context.Current.Request.Url.Host;
5814 <div class="logo @alignClass dw-mod">
5815 <a href="@url" class="logo__img dw-mod u-block @isCartPageClass">
5816 <img class="grid__cell-img logo__img dw-mod @isCartPageClass" src="@logo" alt="@Translate("Logo")" />
5817 </a>
5818 </div>
5819 }
5820 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
5821
5822 @using System
5823 @using System.Web
5824 @using Dynamicweb.Rapido.Blocks.Extensibility
5825 @using Dynamicweb.Rapido.Blocks
5826
5827 @functions {
5828 string menuType;
5829 }
5830
5831 @{
5832 menuType = Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("NavigationMegaMenu") != null ? Model.Area.Item.GetItem("Layout").GetItem("Header").GetRawValueString("NavigationMegaMenu") : "dropdown";
5833 Block masterDesktopMenu = new Block
5834 {
5835 Id = "MasterDesktopMenu",
5836 SortId = 10,
5837 Template = RenderDesktopMenu(),
5838 Design = new Design
5839 {
5840 Size = "auto",
5841 HidePadding = true,
5842 RenderType = RenderType.Column
5843 }
5844 };
5845
5846 if (menuType == "megamenu")
5847 {
5848 masterDesktopMenu.Design.CssClass = "u-reset-position";
5849 }
5850
5851 if (menuType == "sidemenu")
5852 {
5853 masterDesktopMenu.Design.CssClass = "u-reset-position full-size";
5854 }
5855
5856 BlocksPage.GetBlockPage("Master").Add("MasterHeader", masterDesktopMenu);
5857 }
5858
5859 @helper RenderDesktopMenu()
5860 {
5861 string topLayout = Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("TopLayout") != null ? Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("TopLayout").SelectedValue : "normal";
5862 string menuAlignment = topLayout == "minimal-right" ? "grid--align-self-end" : "";
5863 menuAlignment = topLayout == "minimal-center" ? "grid--align-self-center" : topLayout;
5864 string megamenuPromotionImage = Model.Area.Item.GetItem("Layout").GetItem("Header").GetFile("MegamenuPromotionImage") != null ? Model.Area.Item.GetItem("Layout").GetItem("Header").GetFile("MegamenuPromotionImage").PathUrlEncoded : "";
5865 bool renderPagesInToolBar = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("RenderPagesInToolBar");
5866 bool showOnlyHeaders = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("ShowOnlyHeaders");
5867 int startLevel = renderPagesInToolBar ? 1 : 0;
5868
5869 string promotionLink = Model.Area.Item.GetItem("Layout").GetItem("Header").GetString("MegamenuPromotionLink");
5870
5871 <div class="grid__cell u-flex @(menuType == "sidemenu" ? "sidemenu-container js-sidemenu-container" : "") @(menuType == "megamenu" ? "u-reset-position" : "") @menuAlignment">
5872 @if (Pageview.Page.NavigationTag == "CartPage" && menuType != "sidemenu")
5873 {
5874 <div class="custom__checkout__headerusp grid">
5875 @RenderUsps("help", Translate("Smartpage:Checkout.Brug for hælp?", "Brug for hælp?"), Translate("Smartpage:Checkout.Tel: 70 22 68 88", "Tel: 70 22 68 88"))
5876 @RenderUsps("Secure", Translate("Smartpage:Checkout.Sikker betaling", "Sikker betaling"), Translate("Smartpage:Checkout.Krypteret betaling", "Krypteret betaling"))
5877 @RenderUsps("delivery", Translate("Smartpage:Checkout.Hurtig levering", "Hurtig levering"), Translate("Smartpage:Checkout.1-2 dages levering", "1-2 dages levering"))
5878 @RenderUsps("tilfredshed", Translate("Smartpage:Checkout.100% tilfredshed!", "100% tilfredshed!"), Translate("Smartpage:Checkout.Du kan nemt sende retur", "Du kan nemt sende retur"))
5879 </div>
5880 }
5881 else
5882 {
5883 var navigationSettings = new Dynamicweb.Frontend.Navigation.NavigationSettings()
5884 {
5885 RootAreaId = 0,
5886 RootPageId = 0,
5887 RootNavigationTag = "main-menu",
5888 StartLevel = 1,
5889 StopLevel = 99,
5890 ExpandMode = Dynamicweb.Frontend.Navigation.ExpandMode.All
5891 };
5892
5893 var navigationTemplate = "Navigation/SpViewModelNavigation.cshtml";
5894
5895 @Navigation.RenderNavigation(navigationTemplate, navigationSettings)
5896 }
5897 </div>
5898 }
5899
5900 @helper RenderUsps(string icon, string toptext, string bottomtext)
5901 {
5902 var svg = icon + ".svg";
5903
5904 <div class="grid__col-12 grid__col-md-3">
5905 <div class="grid grid--align-center u-justify-content--center border-right">
5906 <div class="grid__col-2">
5907 <img src="/Files/Images/SvgIcons/@svg" height="35" width="35" />
5908 </div>
5909 <div class="grid__col-8">
5910 <div class="u-block">
5911 <strong>@toptext</strong>
5912 </div>
5913 <div class="u-block">
5914 @bottomtext
5915 </div>
5916 </div>
5917 </div>
5918 </div>
5919 }
5920
5921 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
5922
5923 @using System
5924 @using System.Web
5925 @using Dynamicweb.Rapido.Blocks.Extensibility
5926 @using Dynamicweb.Rapido.Blocks
5927
5928 @{
5929 Block masterDesktopActionsMenu = new Block
5930 {
5931 Id = "MasterDesktopActionsMenu",
5932 SortId = 10,
5933 Template = RenderDesktopActionsMenu(),
5934 Design = new Design
5935 {
5936 CssClass = "u-flex"
5937 },
5938 SkipRenderBlocksList = true
5939
5940 };
5941 BlocksPage.GetBlockPage("Master").Add("MasterHeader", masterDesktopActionsMenu);
5942
5943 if (!string.IsNullOrWhiteSpace(Model.Area.Item.GetItem("Layout").GetItem("Header").GetString("HeaderButtonLink")))
5944 {
5945 Block masterDesktopActionsHeaderButton = new Block
5946 {
5947 Id = "MasterDesktopActionsHeaderButton",
5948 SortId = 60,
5949 Template = RenderHeaderButton()
5950 };
5951 masterDesktopActionsMenu.Add(masterDesktopActionsHeaderButton);
5952 }
5953 }
5954
5955 @helper RenderDesktopActionsMenu()
5956 {
5957 if (Model.ID != GetPageIdByNavigationTag("CartPage") && Model.ID != GetPageIdByNavigationTag("CheckoutPage"))
5958 {
5959 List<Block> subBlocks = this.headerBlocksPage.GetBlockListById("MasterDesktopActionsMenu").OrderBy(item => item.SortId).ToList();
5960
5961 <ul class="menu u-flex dw-mod">
5962 @RenderBlockList(subBlocks)
5963 </ul>
5964 }
5965 else
5966 {
5967 string trustpilotScoreImage = Pageview.AreaSettings.GetItem("Custom").GetRawValueString("TrustpilotScoreImage");
5968 var headerUSPs = Pageview.AreaSettings.GetItem("Custom").GetItems("HeaderUSP");
5969 if (!string.IsNullOrEmpty(trustpilotScoreImage) || headerUSPs.Any())
5970 {
5971 <div class="cart-header-usp-container menu u-flex dw-mod">
5972 @if (!string.IsNullOrEmpty(trustpilotScoreImage))
5973 {
5974 <div class="cart-header-usp">
5975 <span class="cart-header-usp-title">@Translate("Smartpage:Checkout.Anmeldelser", "Anmeldelser")</span>
5976 <img src="@trustpilotScoreImage" />
5977 </div>
5978 }
5979 @if (headerUSPs.Any())
5980 {
5981 foreach (var usp in headerUSPs)
5982 {
5983 <div class="cart-header-usp">
5984 <span class="cart-header-usp-title">@RenderCartHeaderUSPCheckmark() @usp.GetRawValueString("USPTitle")</span>
5985 <span class="cart-header-usp-text">@usp.GetRawValueString("USPDescription")</span>
5986 </div>
5987 }
5988 }
5989 </div>
5990 }
5991 }
5992 }
5993
5994 @helper RenderHeaderButton()
5995 {
5996 string headerButtonText = Model.Area.Item.GetItem("Layout").GetItem("Header").GetString("HeaderButtonText");
5997 string headerButtonLink = Model.Area.Item.GetItem("Layout").GetItem("Header").GetString("HeaderButtonLink");
5998 string headerButtonType = Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("HeaderButtonType") != null ? "btn--" + Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("HeaderButtonType").SelectedName.ToLower() : "";
5999
6000 <li class="menu__item menu__item--horizontal menu--clean dw-mod">
6001 <a class="btn @headerButtonType dw-mod u-no-margin u-margin-top u-margin-left" href="@headerButtonLink">@headerButtonText</a>
6002 </li>
6003 }
6004
6005 @helper RenderCartHeaderUSPCheckmark()
6006 {
6007 <svg xmlns="http://www.w3.org/2000/svg" width="12.036" height="8.826" viewBox="0 0 12.036 8.826">
6008 <g id="Group-2" transform="translate(0 0)">
6009 <g id="Group_13" data-name="Group 13">
6010 <g id="Group">
6011 <g transform="translate(0 0)">
6012 <path id="Checkmark" d="M.176,9.806a.585.585,0,0,1,0-.837l.851-.837a.609.609,0,0,1,.851,0l2.635,2.591,5.644-5.55a.609.609,0,0,1,.851,0l.851.837a.585.585,0,0,1,0,.837l-6.92,6.806a.609.609,0,0,1-.851,0Z" transform="translate(0 -5)" fill="#c3ad8f" fill-rule="evenodd" />
6013 </g>
6014 </g>
6015 </g>
6016 </g>
6017 </svg>
6018 }
6019 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
6020
6021 @using System
6022 @using System.Web
6023 @using Dynamicweb.Core;
6024 @using System.Text.RegularExpressions
6025 @using Dynamicweb.Rapido.Blocks.Extensibility
6026 @using Dynamicweb.Rapido.Blocks
6027
6028 @{
6029 Block masterDesktopActionsMenuLanguageSelector = new Block
6030 {
6031 Id = "MasterDesktopActionsMenuLanguageSelector",
6032 SortId = 40,
6033 Template = RenderLanguageSelector()
6034 };
6035
6036 @*BlocksPage.GetBlockPage("Master").Add("MasterDesktopActionsMenu", masterDesktopActionsMenuLanguageSelector);*@
6037 }
6038
6039 @helper RenderLanguageSelector()
6040 {
6041 string topLayout = Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("TopLayout") != null ? Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("TopLayout").SelectedValue : "normal";
6042 string liClasses = topLayout != "normal" ? "menu__item--top-level u-hidden-xxs" : "menu--clean";
6043 string menuLinkClass = topLayout != "normal" && topLayout != "splitted-center" ? "menu__link menu__link--icon" : "header-menu__link header-menu__link--icon";
6044 string languageViewType = !string.IsNullOrEmpty(Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("LanguageSelector").SelectedValue) ? Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("LanguageSelector").SelectedValue.ToLower() : "";
6045
6046 var languages = Model.Languages.Where(l => Dynamicweb.Services.Areas.GetArea(l.ID).Published).ToList();
6047
6048 if (languages.Count > 1)
6049 {
6050 <li class="menu__item menu__item--horizontal @liClasses menu__item--icon is-dropdown is-dropdown--no-icon dw-mod">
6051 <div class="header-menu__link header-menu__link--icon dw-mod">
6052 <div class="custom__header__icon">
6053 <div class="custom__header__icon__icon" title="@HttpUtility.HtmlAttributeEncode(Translate("Language"))">
6054 <i class="@Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("LanguageIcon").SelectedValue fa-2_5x"></i>
6055 </div>
6056 <div class="custom__header__icon__text">
6057 @Translate("Smartpage:LanguageSelector.Language", "Sprog")
6058 </div>
6059 </div>
6060 </div>
6061 <div class="menu menu--dropdown menu--dropdown-right languages-dropdown dw-mod grid__cell">
6062 @foreach (var lang in languages)
6063 {
6064 var area = Dynamicweb.Content.Services.Areas.GetArea(lang.ID);
6065 var qs = HttpUtility.ParseQueryString(System.Web.HttpContext.Current.Request.QueryString.ToString());
6066 qs.Set("ID", Converter.ToString(lang.Page.ID));
6067 qs.Set("AreaID", Converter.ToString(area.ID));
6068 qs.Set("CurrencyCode", area.EcomCurrencyId);
6069 qs.Set("ActiveLanguageSelection", "True");
6070 string url = Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl("Default.aspx?" + qs);
6071 string widthClass = "menu__item--fixed-width";
6072 string langInfo = "<span class=\"flag-icon flag-icon-" + area.EcomCountryCode.ToLower() + " u-margin-right\"></span>" + lang.Name;
6073 string cultureName = Regex.Replace(area.CultureInfo.NativeName, @" ?\(.*?\)", string.Empty);
6074 cultureName = char.ToUpper(cultureName[0]) + cultureName.Substring(1);
6075 string activeClass = Dynamicweb.Ecommerce.Common.Context.LanguageID == area.EcomLanguageId ? "u-bold" : string.Empty;
6076
6077 if (languageViewType == "flag-culture")
6078 {
6079 langInfo = "<span class=\"flag-icon flag-icon-" + area.EcomCountryCode.ToLower() + " \"></span> " + cultureName;
6080 }
6081
6082 if (languageViewType == "flag")
6083 {
6084 langInfo = "<span class=\"flag-icon flag-icon-" + area.EcomCountryCode.ToLower() + " \"></span>";
6085 widthClass = "";
6086 }
6087
6088 if (languageViewType == "name")
6089 {
6090 langInfo = lang.Name;
6091 }
6092
6093 if (languageViewType == "culture")
6094 {
6095 langInfo = cultureName;
6096 widthClass = "";
6097 }
6098
6099 <div class="menu__item dw-mod @widthClass">
6100 <a href="@url" class="menu-dropdown__link dw-mod @activeClass">@langInfo</a>
6101 </div>
6102 }
6103 </div>
6104 </li>
6105 }
6106 }
6107 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
6108 @using Dynamicweb.Core;
6109 @using Dynamicweb.Rapido.Blocks
6110 @using Smartpage.PhilipsonWine.LoyaltyProgram.Helpers
6111
6112 @{
6113 Block masterDesktopActionsMenuSignIn = new Block
6114 {
6115 Id = "MasterDesktopActionsMenuSignIn",
6116 SortId = 20,
6117 Template = RenderSignIn()
6118 };
6119
6120 BlocksPage.GetBlockPage("Master").Add("MasterDesktopActionsMenu", masterDesktopActionsMenuSignIn);
6121 }
6122
6123 @helper RenderSignIn()
6124 {
6125 bool navigationItemsHideSignIn = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("HideSignIn");
6126 string userInitials = "";
6127 int pageId = Model.Area.FirstPage.ID;
6128 int createAccountPageId = GetPageIdByNavigationTag("CreateAccount");
6129 int myDashboardPageId = GetPageIdByNavigationTag("CustomerDashboard");
6130 int myProfilePageId = GetPageIdByNavigationTag("CustomerProfile");
6131 int myOrdersPageId = GetPageIdByNavigationTag("CustomerOrders");
6132 int myFavoritesPageId = GetPageIdByNavigationTag("CustomerFavorites");
6133 int mySavedCardsPageId = GetPageIdByNavigationTag("SavedCards");
6134 int myOrderDraftsPageId = GetPageIdByNavigationTag("OrderDraft");
6135 int customerStockPageId = GetPageIdByNavigationTag("CustomerStockPage");
6136 int signInProfilePageId = GetPageIdByNavigationTag("SignInPage");
6137 int mySubscriptionsPageId = GetPageIdByNavigationTag("MySubscriptionsPage");
6138 bool hideCreateAccountLink = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("SignInHideCreateAccount");
6139 bool hideMyProfileLink = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("SignInHideProfile");
6140 bool hideMyOrdersLink = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("SignInHideOrders");
6141 bool hideMySavedCardsLink = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("SignInHideSavedCards");
6142 bool hideMyOrderDraftsLink = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("SignInHideOrderDrafts");
6143 bool hideMyFavoritesLink = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("SignInHideFavorites");
6144 bool hideForgotPasswordLink = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("SignInHideForgotPasswordLink");
6145 // Should check on the user if the user has customer stock
6146 bool hideCustomerStock = false;
6147
6148 string linkStart = "/Default.aspx?ID=";
6149 if (Model.CurrentUser.ID <= 0)
6150 {
6151 linkStart += signInProfilePageId + "&RedirectPageId=";
6152 }
6153
6154 string forgotPasswordPageLink = "/Default.aspx?ID=" + signInProfilePageId + "&LoginAction=Recovery";
6155 string myDashboardPageLink = linkStart + myDashboardPageId;
6156 string myProfilePageLink = linkStart + myProfilePageId;
6157 string myOrdersPageLink = linkStart + myOrdersPageId;
6158 string myFavoritesPageLink = linkStart + myFavoritesPageId;
6159 string mySavedCardsPageLink = linkStart + mySavedCardsPageId;
6160 string myOrderDraftsLink = linkStart + myOrderDraftsPageId;
6161 string customerStockLink = linkStart + customerStockPageId;
6162 string mySubscriptionsLink = linkStart + mySubscriptionsPageId;
6163
6164 string profileIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("SignInProfileIcon") != null ? Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("SignInProfileIcon").SelectedValue : "fa fa-user";
6165 string favoritesIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("FavoriteIcon") != null ? "fas fa-" + Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("FavoriteIcon").SelectedValue : "fa fa-star";
6166 string orderDraftsIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("DraftIcon") != null ? Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("DraftIcon").SelectedValue : "fa fa-clipboard";
6167
6168 if (Model.CurrentUser.ID != 0)
6169 {
6170 userInitials = Dynamicweb.Rapido.Services.User.GetInitials(Model.CurrentUser.Name, Model.CurrentUser.FirstName, Model.CurrentUser.LastName, Model.CurrentUser.Email, Model.CurrentUser.UserName);
6171 }
6172
6173 bool businessContactImpersonation = false;
6174
6175 if (Model.CurrentSecondaryUser != null && Model.CurrentSecondaryUser.ID > 0)
6176 {
6177 businessContactImpersonation = Converter.ToBoolean(Model.CurrentSecondaryUser.CustomFields.Values.FirstOrDefault(x => x.SystemName == "AccessUser_SpBcImpersonator")?.Value);
6178 }
6179
6180 if (!navigationItemsHideSignIn)
6181 {
6182 string topLayout = Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("TopLayout") != null ? Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("TopLayout").SelectedValue : "normal";
6183 string liClasses = topLayout != "normal" ? "menu__item--top-level u-hidden-xxs" : "menu__item--clean";
6184 string menuLinkClass = topLayout != "normal" && topLayout != "splitted-center" ? "menu__link menu__link--icon" : "header-menu__link header-menu__link--icon";
6185 bool hasPricePook = false;
6186
6187 <li class="menu__item menu__item--horizontal menu__item menu__item--icon @liClasses is-dropdown is-dropdown--no-icon dw-mod">
6188 <div class="@menuLinkClass dw-mod">
6189 @if (Model.CurrentUser.ID <= 0)
6190 {
6191
6192 <div class="custom__header__icon">
6193 <div class="custom__header__icon__icon">
6194 <svg width="23px" height="40px" viewBox="0 0 23 26" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
6195 <title>Group 4</title>
6196 <g id="Header" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
6197 <g transform="translate(-1392.000000, -66.000000)" fill="#FFFFFF" id="Header---2022---Dec">
6198 <g transform="translate(-1.000000, 0.000000)">
6199 <g id="Profil" transform="translate(1357.000000, 66.194216)">
6200 <g id="Group-4" transform="translate(36.000000, 0.000000)">
6201 <path d="M21.9976173,23.9160939 C22.7572186,23.7577881 23.209611,22.9629324 22.8321614,22.2850013 C22.0000535,20.7904769 20.6891658,19.4771996 19.0122125,18.4763775 C16.8524643,17.187417 14.2062291,16.4887568 11.4839257,16.4887568 C8.76162096,16.4887568 6.11538574,17.1874142 3.95563616,18.476372 C2.27868151,19.4771941 0.967790992,20.7904714 0.135684508,22.2849958 C-0.241767867,22.9629242 0.210623159,23.7577826 0.970225832,23.916087 L0.970225832,23.916087 C7.90485829,25.3613018 15.0629821,25.3613046 21.9976173,23.9160939 L21.9976173,23.9160939 Z" id="Fill-936"></path>
6202 <path d="M18.354274,6.87031532 C18.354274,10.664686 15.2783294,13.7406306 11.4839587,13.7406306 C7.68958795,13.7406306 4.61364336,10.664686 4.61364336,6.87031532 C4.61364336,3.0759446 7.68958795,0 11.4839587,0 C15.2783294,0 18.354274,3.0759446 18.354274,6.87031532 Z" id="Fill-937"></path>
6203 </g>
6204 </g>
6205 </g>
6206 </g>
6207 </g>
6208 </svg>
6209 </div>
6210 <div class="custom__header__icon__text">
6211 @Translate("Smartpage:Header.IconsText.LoginOpret", "Log ind")
6212 <div class="custom__header__icon__text__subtext">@Translate("Smartpage:Header.IconsText.LoginOpret.SubText", "Opret og få bonus")</div>
6213 </div>
6214 </div>
6215 }
6216 else
6217 {
6218
6219 string bonusFormatted = "";
6220
6221 double bonus = Dynamicweb.Ecommerce.Services.Loyalty.GetPointsBalance(Dynamicweb.Security.UserManagement.User.GetCurrentFrontendUser());
6222
6223 if (Dynamicweb.Core.Converter.ToDouble(bonus) > 0.0)
6224 {
6225 bonusFormatted = Dynamicweb.Ecommerce.Services.Currencies.Format(Dynamicweb.Ecommerce.Common.Context.Currency, bonus);
6226 }
6227
6228 <a @(!businessContactImpersonation ? "href=\"" + myDashboardPageLink + "\"" : string.Empty)>
6229 <div class="custom__header__icon">
6230 <div class="custom__header__icon__icon">
6231 <svg width="23px" height="40px" viewBox="0 0 23 26" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
6232 <title></title>
6233 <g id="Header" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
6234 <g transform="translate(-1392.000000, -66.000000)" fill="#FFFFFF" id="Header---2022---Dec">
6235 <g transform="translate(-1.000000, 0.000000)">
6236 <g id="Profil" transform="translate(1357.000000, 66.194216)">
6237 <g id="Group-4" transform="translate(36.000000, 0.000000)">
6238 <path d="M21.9976173,23.9160939 C22.7572186,23.7577881 23.209611,22.9629324 22.8321614,22.2850013 C22.0000535,20.7904769 20.6891658,19.4771996 19.0122125,18.4763775 C16.8524643,17.187417 14.2062291,16.4887568 11.4839257,16.4887568 C8.76162096,16.4887568 6.11538574,17.1874142 3.95563616,18.476372 C2.27868151,19.4771941 0.967790992,20.7904714 0.135684508,22.2849958 C-0.241767867,22.9629242 0.210623159,23.7577826 0.970225832,23.916087 L0.970225832,23.916087 C7.90485829,25.3613018 15.0629821,25.3613046 21.9976173,23.9160939 L21.9976173,23.9160939 Z" id="Fill-936"></path>
6239 <path d="M18.354274,6.87031532 C18.354274,10.664686 15.2783294,13.7406306 11.4839587,13.7406306 C7.68958795,13.7406306 4.61364336,10.664686 4.61364336,6.87031532 C4.61364336,3.0759446 7.68958795,0 11.4839587,0 C15.2783294,0 18.354274,3.0759446 18.354274,6.87031532 Z" id="Fill-937"></path>
6240 </g>
6241 </g>
6242 </g>
6243 </g>
6244 </g>
6245 </svg>
6246 </div>
6247 <div class="custom__header__icon__text">
6248 @{
6249
6250
6251 string name = Translate("Smartpage:Header.IconsText.MinProfil", "Min profil");
6252 int maxLength = 20;
6253 if (businessContactImpersonation)
6254 {
6255 if (Model.CurrentSecondaryUser.Name.Count() > maxLength)
6256 {
6257 name = Model.CurrentSecondaryUser.Name.Substring(0, maxLength - 3) + "...";
6258 }
6259 else
6260 {
6261 name = Model.CurrentSecondaryUser.Name;
6262 }
6263 }
6264 else if (!string.IsNullOrWhiteSpace(Model.CurrentUser.FirstName))
6265 {
6266 name = Model.CurrentUser.FirstName;
6267 }
6268 else if (!string.IsNullOrWhiteSpace(Model.CurrentUser.Name))
6269 {
6270 if (Model.CurrentUser.Name.Count() > maxLength)
6271 {
6272 name = Model.CurrentUser.Name.Substring(0, maxLength - 3) + "...";
6273 }
6274 else
6275 {
6276 name = Model.CurrentUser.Name;
6277 }
6278 }
6279
6280 @name
6281 if (!string.IsNullOrEmpty(bonusFormatted))
6282 {
6283 var user = Dynamicweb.Security.UserManagement.User.GetCurrentFrontendUser();
6284 <div class="custom__header__icon__text__subtext">@string.Format(Translate("Smartpage:SignInActions.Bonus", "Din {0}: {1}"), Helper.GetWelcomeBonus(user) != null ? "velkomstrabat" : "bonus", bonusFormatted)</div>
6285 }
6286 }
6287 </div>
6288 </div>
6289 </a>
6290 }
6291 </div>
6292 <div class="menu menu--dropdown menu--dropdown-right menu--sign-in grid__cell dw-mod">
6293 <ul class="list list--clean dw-mod">
6294 @if (Model.CurrentUser.ID <= 0)
6295 {
6296 <li>
6297 <label for="SignInModalTrigger" class="btn btn--primary btn--full u-no-margin sign-in-modal-trigger-button dw-mod js-sign-in-modal-trigger">@Translate("Sign in")</label>
6298 </li>
6299
6300 if (!hideCreateAccountLink)
6301 {
6302 @RenderListItem("/default.aspx?ID=" + createAccountPageId, Translate("Create account"));
6303 }
6304 if (!hideForgotPasswordLink)
6305 {
6306 @RenderListItem(forgotPasswordPageLink, Translate("Forgot your password?"))
6307 }
6308 if (!hideMyProfileLink || !hideMyOrdersLink || !hideMyFavoritesLink || !hideMySavedCardsLink || !hideCustomerStock)
6309 {
6310 @RenderSeparator()
6311 }
6312 }
6313 @if (!hideMyProfileLink && !businessContactImpersonation)
6314 {
6315 @RenderListItem(myProfilePageLink, Translate("My Profile"), profileIcon)
6316 }
6317
6318 @if (!businessContactImpersonation)
6319 {
6320 @RenderListItem(myDashboardPageLink, Translate("Smartpage:SignInActions.Dashboard", "Mit overblik"), "fas fa-th")
6321 }
6322
6323 @if (!hideMyOrdersLink && !businessContactImpersonation)
6324 {
6325 @RenderListItem(myOrdersPageLink, Translate("My Orders"), "fas fa-list")
6326 }
6327 @if (!hideMyFavoritesLink && !businessContactImpersonation)
6328 {
6329 @RenderListItem(myFavoritesPageLink, Translate("My Favorites"), favoritesIcon)
6330 }
6331 @if (!hideMySavedCardsLink && !businessContactImpersonation)
6332 {
6333 @RenderListItem(mySavedCardsPageLink, Translate("My Saved cards"), "fas fa-credit-card")
6334 }
6335 @if (!hideCustomerStock && !businessContactImpersonation)
6336 {
6337 @RenderListItem(customerStockLink, Translate("Smartpage:SignInActions.CustomerStock", "Mit kundelager"), "fal fa-clipboard-list")
6338 }
6339
6340 @if (Model.CurrentUser.ID > 0)
6341 {
6342 var priceBookList = Dynamicweb.Ecommerce.CustomerCenter.CustomerProductList.GetListByCustomerId(Converter.ToInt32(Model.CurrentUser.ID))?.FirstOrDefault(l => l.Type == "PriceBookList");
6343 if (priceBookList != null)
6344 {
6345 string link = $"/Default.aspx?Id={GetPageIdByNavigationTag("FavoriteProductsPage")}&ListID={priceBookList.ID}&ListName={priceBookList.Name}";
6346 @RenderListItem(link, Translate("Smartpage:SignInActions.PriceBookList", "Prisbog"), "fal fa-dollar-sign")
6347
6348 hasPricePook = true;
6349 }
6350 }
6351
6352 @if (mySubscriptionsPageId != 0 && !businessContactImpersonation)
6353 {
6354 @RenderListItem(mySubscriptionsLink, Translate("Smartpage:SignInActions.MySubscriptions", "Mine abonnementer"), "fal fa-clipboard-list")
6355 }
6356
6357 @if (!hideMyOrderDraftsLink && !businessContactImpersonation)
6358 {
6359 @RenderListItem(myOrderDraftsLink, Translate("My Order drafts"), orderDraftsIcon)
6360 }
6361 @if (Model.CurrentUser.ID > 0)
6362 {
6363 if ((!hideMyProfileLink || !hideMyOrdersLink || !hideMyFavoritesLink || !hideMySavedCardsLink) && (!businessContactImpersonation || hasPricePook))
6364 {
6365 @RenderSeparator()
6366 }
6367
6368 //Check if impersonation is on
6369 if (Model.CurrentSecondaryUser != null && Model.CurrentSecondaryUser.ID > 0)
6370 {
6371 <li>
6372 <div class="list__link dw-mod" onclick="document.getElementById('StopImpersonationModalTrigger').checked = true;">
6373 @Translate("Sign out")
6374 </div>
6375 </li>
6376 }
6377 else
6378 {
6379 @RenderListItem("/Admin/Public/ExtranetLogoff.aspx?ID=" + pageId, Translate("Sign out"))
6380 }
6381 }
6382 </ul>
6383 </div>
6384 </li>
6385 }
6386 }
6387
6388 @helper RenderListItem(string link, string text, string icon = null)
6389 {
6390 <li>
6391 <a href="@link" class="list__link dw-mod" onclick="RememberState.SetCookie('useAnotherAddress', false)">
6392 @if (!string.IsNullOrEmpty(icon))
6393 {<i class="@icon u-margin-right"></i>}@text
6394 </a>
6395 </li>
6396 }
6397
6398 @helper RenderSeparator()
6399 {
6400 <li class="list__seperator dw-mod"></li>
6401 }
6402 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
6403
6404 @using System
6405 @using System.Web
6406 @using Dynamicweb.Rapido.Blocks.Extensibility
6407 @using Dynamicweb.Rapido.Blocks
6408
6409 @{
6410 bool hideMyFavoritesLink = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("HideFavorites");
6411
6412 Block masterDesktopActionsMenuFavorites = new Block
6413 {
6414 Id = "MasterDesktopActionsMenuFavorites",
6415 SortId = 30,
6416 Template = RenderFavorites()
6417 };
6418
6419 if (!hideMyFavoritesLink && Model.CurrentUser.ID > 0)
6420 {
6421 BlocksPage.GetBlockPage("Master").Add("MasterDesktopActionsMenu", masterDesktopActionsMenuFavorites);
6422 }
6423 }
6424
6425 @helper RenderFavorites()
6426 {
6427 int myFavoritesPageId = GetPageIdByNavigationTag("CustomerFavorites");
6428 string myFavoritesPageLink = "/Default.aspx?ID=" + myFavoritesPageId;
6429
6430 string topLayout = Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("TopLayout") != null ? Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("TopLayout").SelectedValue : "normal";
6431 string liClasses = topLayout != "normal" && topLayout != "splitted-center" ? "menu__item--top-level u-hidden-xxs" : "menu--clean";
6432 string menuLinkClass = topLayout != "normal" && topLayout != "splitted-center" ? "menu__link menu__link--icon" : "header-menu__link header-menu__link--icon";
6433
6434 <li class="menu__item menu__item--horizontal @liClasses menu__item--icon dw-mod">
6435 <a href="@myFavoritesPageLink" class="@menuLinkClass dw-mod" title="@Translate("Favorites")">
6436 <i class="fas fa-@Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("FavoriteIcon").SelectedValue fa-1_5x"></i>
6437 </a>
6438 </li>
6439 }
6440 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
6441
6442 @using System
6443 @using System.Web
6444 @using Dynamicweb.Rapido.Blocks.Extensibility
6445 @using Dynamicweb.Rapido.Blocks
6446 @using Dynamicweb.Rapido.Services
6447 @using Smartpage.PhilipsonWine.Ecommerce.CartInformation;
6448 @using Smartpage.PhilipsonWine.Freight.Helpers;
6449
6450 @functions{
6451 public Dynamicweb.Security.UserManagement.User GetCurrentUser() => Dynamicweb.Security.UserManagement.User.GetCurrentFrontendUser();
6452 public bool GetActivateFreightMeter() => Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetBoolean("ActivateFreightMeter");
6453 public double GetFreeShippingLimit() => Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetDouble("FreeShippingLimit");
6454 }
6455
6456 @{
6457 bool hideCart = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("HideCart");
6458 string miniCartLayout = Model.Area.Item.GetItem("Ecommerce").GetItem("MiniCart").GetList("Layout") != null ? Model.Area.Item.GetItem("Ecommerce").GetItem("MiniCart").GetList("Layout").SelectedValue : "dropdown";
6459
6460 if (Dynamicweb.Rapido.Services.User.IsBuyingAllowed() && !hideCart)
6461 {
6462 Block masterDesktopActionsMenuMiniCart = new Block
6463 {
6464 Id = "MasterDesktopActionsMenuMiniCart",
6465 SortId = 60,
6466 Template = RenderMiniCart(miniCartLayout == "dropdown"),
6467 SkipRenderBlocksList = true,
6468 BlocksList = new List<Block>()
6469 };
6470
6471 Block miniCartCounterScriptTemplate = new Block
6472 {
6473 Id = "MiniCartCounterScriptTemplate",
6474 Template = RenderMiniCartCounterContent()
6475 };
6476
6477 Block miniCartFreightMeterScriptTemplate = new Block
6478 {
6479 Id = "MiniCartFreightMeterScriptTemplate",
6480 Template = RenderMiniCartFreightMeterScript()
6481 };
6482
6483 //dropdown layout is default
6484 RazorEngine.Templating.TemplateWriter layoutTemplate;
6485 RazorEngine.Templating.TemplateWriter miniCartTriggerTemplate;
6486 switch (miniCartLayout)
6487 {
6488 case "dropdown":
6489 layoutTemplate = RenderMiniCartDropdownLayout();
6490 miniCartTriggerTemplate = RenderMiniCartTriggerLink();
6491 break;
6492 case "panel":
6493 layoutTemplate = RenderMiniCartPanelLayout();
6494 miniCartTriggerTemplate = RenderMiniCartTriggerLabel();
6495 break;
6496 case "modal":
6497 layoutTemplate = RenderMiniCartModalLayout();
6498 miniCartTriggerTemplate = RenderMiniCartTriggerLabel();
6499 break;
6500 case "none":
6501 default:
6502 layoutTemplate = RenderMiniCartDropdownLayout();
6503 miniCartTriggerTemplate = RenderMiniCartTriggerLink();
6504 break;
6505 }
6506
6507 masterDesktopActionsMenuMiniCart.BlocksList.Add(new Block
6508 {
6509 Id = "MiniCartTrigger",
6510 Template = miniCartTriggerTemplate
6511 });
6512
6513 if (Pageview.Device.ToString() != "Mobile")
6514 {
6515 masterDesktopActionsMenuMiniCart.BlocksList.Add(new Block
6516 {
6517 Id = "MiniCartLayout",
6518 Template = layoutTemplate
6519 });
6520 }
6521
6522 BlocksPage.GetBlockPage("Master").Add("MasterDesktopActionsMenu", masterDesktopActionsMenuMiniCart);
6523 BlocksPage.GetBlockPage("Master").Add("MasterBottomSnippets", miniCartCounterScriptTemplate);
6524 if (GetActivateFreightMeter())
6525 {
6526 BlocksPage.GetBlockPage("Master").Add("MasterBottomSnippets", miniCartFreightMeterScriptTemplate);
6527 }
6528 }
6529
6530 if (hideCart && Dynamicweb.Rapido.Services.User.IsBuyingAllowed())
6531 {
6532 BlocksPage.GetBlockPage("Master").Add("MasterBottomSnippets", new Block
6533 {
6534 Id = "CartInitialization"
6535 });
6536 }
6537 }
6538
6539 @helper RenderMiniCart(bool hasMouseEnterEvent)
6540 {
6541 List<Block> subBlocks = this.masterPage.GetBlockListById("MasterDesktopActionsMenuMiniCart").OrderBy(item => item.SortId).ToList();
6542 string topLayout = Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("TopLayout") != null ? Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("TopLayout").SelectedValue : "normal";
6543 string liClasses = topLayout != "normal" ? "menu__item--top-level" : "menu--clean";
6544 int miniCartFeedPageId = GetPageIdByNavigationTag("MiniCartFeed");
6545 string mouseEvent = "";
6546 string id = "MiniCart";
6547 if (hasMouseEnterEvent)
6548 {
6549 mouseEvent = "onmouseenter=\"Cart.UpdateMiniCart('miniCartTrigger', 'miniCart', 'cartCounter', '/Default.aspx?ID=" + miniCartFeedPageId + "&feedType=MiniCart')\"";
6550 id = "miniCartTrigger";
6551 }
6552 <li class="menu__item menu__item--horizontal menu__item--icon @liClasses dw-mod" id="@id" @mouseEvent>
6553 @RenderBlockList(subBlocks)
6554 </li>
6555 }
6556
6557 @helper RenderMiniCartTriggerLabel()
6558 {
6559 int cartPageId = GetPageIdByNavigationTag("CartPage");
6560 string cartIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon") != null ? Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon").SelectedValue : "fa fa-cart";
6561 string topLayout = Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("TopLayout") != null ? Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("TopLayout").SelectedValue : "normal";
6562 string menuLinkClass = topLayout != "normal" && topLayout != "splitted-center" ? "menu__link menu__link--icon" : "header-menu__link header-menu__link--icon";
6563 int miniCartFeedPageId = GetPageIdByNavigationTag("MiniCartFeed");
6564
6565 <a class="@menuLinkClass dw-mod js-mini-cart-button u-flex u-flex--column mini-cart" href="/Default.aspx?ID=@cartPageId" title="@HttpUtility.HtmlAttributeEncode(Translate("Cart"))">
6566 <div class="custom__header__icon mini-cart">
6567 <div class="custom__header__icon__icon cart" title="@Translate("Cart")">
6568 <object data="/Files/Images/SvgIcons/basket.svg" type="image/svg+xml">
6569 <span>Your browser doesn't support SVG images</span>
6570 </object>
6571 </div>
6572 @RenderMiniCartCounter(miniCartFeedPageId)
6573 </div>
6574 @if (GetActivateFreightMeter())
6575 {
6576 @RenderMiniCartFreightMeter(miniCartFeedPageId)
6577 }
6578 </a>
6579 }
6580
6581 @helper RenderMiniCartTriggerLink()
6582 {
6583 int cartPageId = GetPageIdByNavigationTag("CartPage");
6584 string cartIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon") != null ? Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon").SelectedValue : "fa fa-cart";
6585 string topLayout = Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("TopLayout") != null ? Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("TopLayout").SelectedValue : "normal";
6586 string menuLinkClass = topLayout != "normal" && topLayout != "splitted-center" ? "menu__link menu__link--icon" : "header-menu__link header-menu__link--icon";
6587 int miniCartFeedPageId = GetPageIdByNavigationTag("MiniCartFeed");
6588
6589 <a href="/Default.aspx?ID=@cartPageId" class="@menuLinkClass menu__item--icon dw-mod js-mini-cart-button" title="@HttpUtility.HtmlAttributeEncode(Translate("Cart"))">
6590 <div class="custom__header__icon">
6591 <div class="custom__header__icon__icon" title="@HttpUtility.HtmlAttributeEncode(Translate("Cart"))">
6592 <object data="/Files/Images/SvgIcons/basket.svg" type="image/svg+xml">
6593 <span>Your browser doesn't support SVG images</span>
6594 </object>
6595 </div>
6596 @RenderMiniCartCounter(miniCartFeedPageId)
6597 </div>
6598 </a>
6599 }
6600
6601 @helper RenderMiniCartCounter(int miniCartFeedPageId)
6602 {
6603 double cartProductsCount = 0;
6604 bool cartContainsSubscriptionOrderLine = false;
6605
6606 if (Model != null && Model.Cart != null && Model.Cart.CartOrderlines != null)
6607 {
6608 CartInformation cartInformation = new CartInformation(Model.Cart);
6609
6610 cartProductsCount = cartInformation.OrderLineCount;
6611 cartContainsSubscriptionOrderLine = cartInformation.ContainsSubscriptionOrderLine;
6612 }
6613
6614 string counterPosition = Model.Area.Item.GetItem("Ecommerce").GetItem("MiniCart").GetList("CounterPosition") != null ? Model.Area.Item.GetItem("Ecommerce").GetItem("MiniCart").GetList("CounterPosition").SelectedValue : "right";
6615 bool showPrice = Model.Area.Item.GetItem("Ecommerce").GetItem("MiniCart").GetBoolean("ShowPrice");
6616 string cartProductsTotalPrice = (Model.Cart.TotalPrice != null) ? Model.Cart.TotalPrice.Price.Value.ToString("N2") : "0,00 ";
6617 double freeFee = GetFreeShippingLimit();
6618 double amountToFreeFreight = (Model.Cart.TotalPriceWithoutFees != null) ? freeFee - Model.Cart.TotalPriceWithoutFees.PriceWithVat.Value : freeFee;
6619 string amountToFreeFreightFormatted = amountToFreeFreight.ToString("N2");
6620 string currencyCode = Dynamicweb.Ecommerce.Common.Context.Currency.Symbol;
6621 bool isFreeFreight = amountToFreeFreight <= 0 || cartContainsSubscriptionOrderLine || UserHelper.IsUserWithFreeFreight(GetCurrentUser());
6622
6623 <div class="js-handlebars-root js-mini-cart-counter u-flex u-justify-content--center u-align-end u-flex--column" id="cartCounter" data-template="MiniCartCounterContent" data-json-feed="/Default.aspx?ID=@miniCartFeedPageId&feedType=Counter" data-init-onload="false">
6624 <div class="custom__header__icon__counter">
6625 <div class="mini-cart__counter dw-mod">
6626 <span class="js-mini-cart-counter-content" data-count="@cartProductsCount">
6627 @cartProductsCount
6628 </span>
6629 </div>
6630 </div>
6631 <div>
6632 <div class="u-flex u-flex--row">
6633 <span class="custom__header__icon__text price u-flex">
6634 @cartProductsTotalPrice
6635 </span>
6636 <span class="custom__header__icon__text currency u-flex">@currencyCode</span>
6637 </div>
6638 @if (GetActivateFreightMeter())
6639 {
6640 <div class="custom__header__icon__freight-text">
6641 @if (isFreeFreight)
6642 {
6643 <span class="custom__header__icon__freight-text__freight-bold success u-flex">@Translate("Smartpage:MiniCart.YouHaveFreeFreight", "Du har fri fragt!")</span>
6644 }
6645 else
6646 {
6647 @amountToFreeFreightFormatted @currencyCode @Translate("Smartpage:MiniCart.From", " fra")
6648 <span class="custom__header__icon__freight-text__freight-bold">@Translate("Smartpage:MiniCart.FreeFreight", "fri fragt")</span>
6649 }
6650 </div>
6651 }
6652
6653 </div>
6654 </div>
6655
6656 }
6657
6658 @helper RenderMiniCartFreightMeter(int miniCartFeedPageId)
6659 {
6660 string widthCss = "width: 0%";
6661
6662 if (UserHelper.IsUserWithFreeFreight(GetCurrentUser()))
6663 {
6664 widthCss = $"width: 100%";
6665 }
6666 else if (Dynamicweb.Ecommerce.Common.Context.Cart != null)
6667 {
6668 CartInformation cartInformation = new CartInformation(Model.Cart);
6669 if (cartInformation.ContainsSubscriptionOrderLine)
6670 {
6671 widthCss = $"width: 100%";
6672 }
6673 else
6674 {
6675 double freeFee = GetFreeShippingLimit();
6676 double percentageFreeFreight = 100 - (((freeFee - Model.Cart.TotalPriceWithoutFees.PriceWithVat.Value) / freeFee) * 100);
6677 percentageFreeFreight = Math.Ceiling(percentageFreeFreight);
6678 if (percentageFreeFreight > 100)
6679 {
6680 percentageFreeFreight = 100;
6681 }
6682 widthCss = $"width: {percentageFreeFreight}%";
6683 }
6684 }
6685
6686 <div class="js-handlebars-root " id="miniCartFreightMeter" data-template="MiniCartFreightMeter" data-json-feed="/Default.aspx?ID=@miniCartFeedPageId" data-init-onload="false" data-preloader="none">
6687 <div class="progress-bar-container u-margin-left">
6688 <div class="progress-bar-indicator" style="@widthCss"></div>
6689 </div>
6690 </div>
6691 }
6692
6693 @helper RenderMiniCartFreightMeterScript()
6694 {
6695 <script id="MiniCartFreightMeter" type="text/x-template">
6696 {{#.}}
6697 <div class="progress-bar-container u-margin-left">
6698 <div class="progress-bar-indicator" style="width:{{percentageFreeFreight}}%"></div>
6699 </div>
6700 {{/.}}
6701 </script>
6702 }
6703
6704 @helper RenderMiniCartCounterContent()
6705 {
6706 <script id="MiniCartCounterContent" type="text/x-template">
6707 {{#.}}
6708 <div class="custom__header__icon__counter">
6709 <div class="mini-cart__counter dw-mod">
6710 <span class="js-mini-cart-counter-content" data-count="{{numberofproducts}}">
6711 {{numberofproducts}}
6712 </span>
6713 </div>
6714 </div>
6715 <div>
6716 <div class="u-flex u-flex--row">
6717 <span class="custom__header__icon__text price u-flex">
6718 {{totalpriceCleanFormatted}}
6719 </span>
6720 <span class="custom__header__icon__text currency u-flex">{{currencyCode}}</span>
6721 </div>
6722 @if (GetActivateFreightMeter())
6723 {
6724 <div class="custom__header__icon__freight-text">
6725 {{#if isFreeFreight}}
6726 <span class="custom__header__icon__freight-text__freight-bold success u-flex">@Translate("Smartpage:MiniCart.YouHaveFreeFreight", "Du har fri fragt!")</span>
6727 {{else}}
6728 {{amountToFreeFreightFormatted}} {{currencyCode}} @Translate("Smartpage:MiniCart.From", " fra")
6729 <span class="custom__header__icon__freight-text__freight-bold">@Translate("Smartpage:MiniCart.FreeFreight", "fri fragt")</span>
6730 {{/if}}
6731 </div>
6732 }
6733 </div>
6734 {{/.}}
6735 </script>
6736 }
6737
6738
6739 @helper RenderMiniCartDropdownLayout()
6740 {
6741 int miniCartFeedPageId = GetPageIdByNavigationTag("MiniCartFeed");
6742 string cartPageLink = "/Default.aspx?ID=" + GetPageIdByNavigationTag("CartPage");
6743
6744 <div class="mini-cart mini-cart-dropdown js-mini-cart grid__cell dw-mod" id="miniCart" data-cart-id="@miniCartFeedPageId" data-show-type="dropdown" data-cart-page-link="@cartPageLink">
6745 <div class="mini-cart-dropdown__inner dw-mod">
6746 <h3 class="u-ta-center dw-mod">@Translate("Shopping cart")</h3>
6747 <div class="mini-cart-dropdown__body u-flex dw-mod">
6748 <div class="js-handlebars-root u-flex grid--direction-column u-full-width dw-mod" id="miniCartContent" data-template="MiniCartContent" data-json-feed="/Default.aspx?ID=@miniCartFeedPageId&feedType=MiniCart" data-init-onload="false"></div>
6749 </div>
6750 </div>
6751 </div>
6752 }
6753
6754 @helper RenderMiniCartPanelLayout()
6755 {
6756 int miniCartFeedPageId = GetPageIdByNavigationTag("MiniCartFeed");
6757 string cartPageLink = "/Default.aspx?ID=" + GetPageIdByNavigationTag("CartPage");
6758
6759 <div class="mini-cart grid__cell dw-mod">
6760 <input type="checkbox" id="miniCartTrigger" class="panel-trigger" />
6761 <div class="panel panel--right panel--with-close-btn dw-mod js-mini-cart" id="miniCart" data-cart-id="@miniCartFeedPageId" data-show-type="block" data-cart-page-link="@cartPageLink">
6762 <label for="miniCartTrigger" class="panel__close-btn" title="@Translate("Close panel")"><i class="fas fa-times"></i></label>
6763 <div class="panel__content u-full-width dw-mod">
6764 <h3 class="panel__header dw-mod u-margin-bottom u-ta-center">@Translate("Shopping cart")</h3>
6765 <div class="panel__content-body panel__content-body--cart dw-mod">
6766 <div class="js-handlebars-root u-flex grid--direction-column u-full-height dw-mod" id="miniCartContent" data-template="MiniCartContent" data-json-feed="/Default.aspx?ID=@miniCartFeedPageId&feedType=MiniCart" data-init-onload="false"></div>
6767 </div>
6768 </div>
6769 </div>
6770 </div>
6771 }
6772
6773 @helper RenderMiniCartModalLayout()
6774 {
6775 int miniCartFeedPageId = GetPageIdByNavigationTag("MiniCartFeed");
6776 string cartPageLink = "/Default.aspx?ID=" + GetPageIdByNavigationTag("CartPage");
6777
6778 <div class="mini-cart grid__cell dw-mod">
6779 <input type="checkbox" id="miniCartTrigger" class="modal-trigger" autocomplete="off" />
6780 <div class="modal-container dw-mod js-mini-cart" id="miniCart" data-cart-id="@miniCartFeedPageId" data-show-type="block" data-cart-page-link="@cartPageLink">
6781 <label for="miniCartTrigger" class="modal-overlay"></label>
6782 <div class="modal modal--md modal--top-right dw-mod">
6783 <div class="modal__body u-flex grid--direction-column dw-mod">
6784 <h3 class="dw-mod u-ta-center">@Translate("Shopping cart")</h3>
6785 <div class="js-handlebars-root u-flex grid--direction-column dw-mod" id="miniCartContent" data-template="MiniCartContent" data-json-feed="/Default.aspx?ID=@miniCartFeedPageId&feedType=MiniCart" data-init-onload="false"></div>
6786 </div>
6787 <label class="modal__close-btn modal__close-btn--clean dw-mod" for="miniCartTrigger" title="@Translate("Close modal")"></label>
6788 </div>
6789 </div>
6790 </div>
6791 }
6792
6793
6794 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
6795
6796 @using System
6797 @using System.Web
6798 @using Dynamicweb.Rapido.Blocks.Extensibility
6799 @using Dynamicweb.Rapido.Blocks
6800
6801 @{
6802 bool showOrderDraftLink = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("ShowOrderDraftIcon");
6803
6804 Block masterDesktopActionsMenuOrderDraft = new Block
6805 {
6806 Id = "MasterDesktopActionsMenuOrderDraft",
6807 SortId = 40,
6808 Template = RenderOrderDraft()
6809 };
6810
6811 if (showOrderDraftLink && Model.CurrentUser.ID > 0)
6812 {
6813 BlocksPage.GetBlockPage("Master").Add("MasterDesktopActionsMenu", masterDesktopActionsMenuOrderDraft);
6814 }
6815 }
6816
6817 @helper RenderOrderDraft()
6818 {
6819 int OrderDraftPageId = GetPageIdByNavigationTag("OrderDraft");
6820 string OrderDraftPageLink = "/Default.aspx?ID=" + OrderDraftPageId;
6821 string draftIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("DraftIcon") != null ? Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("DraftIcon").SelectedValue : "fa fa-clipboard";
6822
6823
6824 string topLayout = Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("TopLayout") != null ? Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("TopLayout").SelectedValue : "normal";
6825 string liClasses = topLayout != "normal" ? "menu__item--top-level u-hidden-xxs" : "menu--clean";
6826 string menuLinkClass = topLayout != "normal" && topLayout != "splitted-center" ? "menu__link menu__link--icon" : "header-menu__link header-menu__link--icon";
6827
6828 <li class="menu__item menu__item--horizontal @liClasses menu__item--icon dw-mod">
6829 <a href="@OrderDraftPageLink" class="@menuLinkClass dw-mod" title="@Translate("My order drafts")">
6830 <span class="u-inline u-position-relative">
6831 <i class="@draftIcon fa-1_5x"></i>
6832 </span>
6833 </a>
6834 </li>
6835 }
6836 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
6837
6838 @using System
6839 @using System.Web
6840 @using Dynamicweb.Rapido.Blocks.Extensibility
6841 @using Dynamicweb.Rapido.Blocks
6842
6843 @{
6844 bool showDownloadCartLink = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("ShowDownloadCart");
6845
6846 Block masterDesktopActionsMenuDownloadCart = new Block
6847 {
6848 Id = "MasterDesktopActionsMenuDownloadCart",
6849 SortId = 50,
6850 Template = RenderDownloadCart()
6851 };
6852
6853 if (showDownloadCartLink && Model.CurrentUser.ID > 0)
6854 {
6855 BlocksPage.GetBlockPage("Master").Add("MasterDesktopActionsMenu", masterDesktopActionsMenuDownloadCart);
6856 }
6857 }
6858
6859 @helper RenderDownloadCart()
6860 {
6861 int downloadCartPageId = GetPageIdByNavigationTag("DownloadCart");
6862 string downloadCartPageLink = "/Default.aspx?ID=" + downloadCartPageId;
6863
6864 string topLayout = Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("TopLayout") != null ? Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("TopLayout").SelectedValue : "normal";
6865 string liClasses = topLayout != "normal" ? "menu__item--top-level u-hidden-xxs" : "menu--clean";
6866 string menuLinkClass = topLayout != "normal" && topLayout != "splitted-center" ? "menu__link menu__link--icon" : "header-menu__link header-menu__link--icon";
6867 string counterPosition = Model.Area.Item.GetItem("Ecommerce").GetItem("MiniCart").GetList("CounterPosition") != null ? Model.Area.Item.GetItem("Ecommerce").GetItem("MiniCart").GetList("CounterPosition").SelectedValue : "right";
6868
6869 <li class="menu__item menu__item--horizontal @liClasses menu__item--icon dw-mod">
6870 <a href="@downloadCartPageLink" class="@menuLinkClass dw-mod" title="@Translate("Download cart")">
6871 <span class="u-inline u-position-relative">
6872 <i class="fas fa-cart-arrow-down fa-1_5x"></i>
6873 <span class="mini-cart__counter u-hidden @(counterPosition == "right" ? "mini-cart__counter--inline" : "") dw-mod js-download-cart-counter"></span>
6874 </span>
6875 </a>
6876 </li>
6877 }
6878 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
6879 @using System
6880 @using System.Web
6881 @using Dynamicweb.Rapido.Blocks.Extensibility
6882 @using Dynamicweb.Rapido.Blocks
6883 @using Dynamicweb.Frontend
6884
6885 @functions {
6886 public class SearchConfiguration
6887 {
6888 public string searchFeedId { get; set; }
6889 public string searchSecondFeedId { get; set; }
6890 public int groupsFeedId { get; set; }
6891 public string resultPageLink { get; set; }
6892 public string searchPlaceholder { get; set; }
6893 public string searchType { get; set; }
6894 public string searchTemplate { get; set; }
6895 public string searchContentTemplate { get; set; }
6896 public string searchValue { get; set; }
6897 public bool showGroups { get; set; }
6898
6899 public SearchConfiguration()
6900 {
6901 searchFeedId = "";
6902 searchSecondFeedId = "";
6903 searchType = "product-search";
6904 searchContentTemplate = "";
6905 showGroups = true;
6906 }
6907 }
6908
6909 public class SommifyConfiguration
6910 {
6911 public ItemViewModel sommifySettings { get; set; }
6912 public bool sommifyIsActive { get; set; } = false;
6913 public bool sommifyIsActivated { get; set; }
6914 public string sommifyApi { get; set; }
6915 public string sommifyIcon { get; set; }
6916 public string sommifyStyling { get; set; }
6917 }
6918
6919 public string searchType()
6920 {
6921 return !string.IsNullOrEmpty(Model.Area.Item.GetItem("Layout").GetRawValueString("TopSearch")) ? Model.Area.Item.GetItem("Layout").GetRawValueString("TopSearch") : "productSearch";
6922 }
6923
6924 public bool isProductSearchWithFilters()
6925 {
6926 return searchType() == "productSearchWithFilters";
6927 }
6928
6929 public SommifyConfiguration GetSommifySettings()
6930 {
6931 SommifyConfiguration sommifyConfiguration = null;
6932 ItemViewModel sommifySettings = PageView.Current().AreaSettings.GetItem("Custom").GetItem("SommifySettings");
6933 if (sommifySettings != null)
6934 {
6935 sommifyConfiguration = new SommifyConfiguration();
6936 sommifyConfiguration.sommifySettings = sommifySettings;
6937 sommifyConfiguration.sommifyIsActivated = sommifySettings.GetBoolean("ActivateSommify");
6938 sommifyConfiguration.sommifyApi = sommifySettings.GetRawValueString("SommifyApiKey");
6939 sommifyConfiguration.sommifyIsActive = sommifyConfiguration.sommifyIsActivated && !string.IsNullOrEmpty(sommifyConfiguration.sommifyApi);
6940
6941 if (sommifyConfiguration.sommifyIsActive)
6942 {
6943 sommifyConfiguration.sommifyIcon = sommifySettings.GetRawValueString("SommifyIcon");
6944 string sommifyBackgroundColor = sommifySettings.GetRawValueString("SommifyBackgroundColor");
6945 sommifyConfiguration.sommifyStyling = !string.IsNullOrEmpty(sommifyBackgroundColor) ? "background-color: " + sommifyBackgroundColor + ";" : "";
6946 }
6947 }
6948
6949 return sommifyConfiguration;
6950 }
6951 }
6952 @{
6953 Block masterSearchBar = new Block
6954 {
6955 Id = "MasterSearchBar",
6956 SortId = 40,
6957 Template = RenderSearch("bar"),
6958 Design = new Design
6959 {
6960 Size = "auto",
6961 HidePadding = true,
6962 RenderType = RenderType.Column
6963 }
6964 };
6965
6966 Block masterSearchAction = new Block
6967 {
6968 Id = "MasterDesktopActionsMenuSearch",
6969 SortId = 10,
6970 Template = RenderSearch()
6971 };
6972
6973 BlocksPage.GetBlockPage("Master").Add("MasterHeader", masterSearchBar);
6974 BlocksPage.GetBlockPage("Master").Add("MasterDesktopActionsMenu", masterSearchAction);
6975 }
6976
6977 @helper RenderSearch(string type = "mini-search")
6978 {
6979 if (Model.ID != GetPageIdByNavigationTag("CartPage") && Model.ID != GetPageIdByNavigationTag("CheckoutPage"))
6980 {
6981 string productsSearchId = Converter.ToString(GetPageIdByNavigationTag("ProductSearchFeed"));
6982 int productsPageId = GetPageIdByNavigationTag("ProductsPage");
6983 string contentSearchPageLink = GetPageIdByNavigationTag("ContentSearchResults") + "&Areaid=" + Model.Area.ID;
6984
6985 SearchConfiguration searchConfiguration = null;
6986 switch (searchType())
6987 {
6988 case "contentSearch":
6989 searchConfiguration = new SearchConfiguration()
6990 {
6991 searchFeedId = GetPageIdByNavigationTag("ContentSearchFeed") + "&Areaid=" + Model.Area.ID + "&pagesOnly=true",
6992 resultPageLink = contentSearchPageLink,
6993 searchPlaceholder = Translate("Search page"),
6994 groupsFeedId = 0,
6995 searchType = "content-search",
6996 searchTemplate = "SearchPagesTemplate",
6997 showGroups = false
6998 };
6999 break;
7000 case "productSearchWithFilters":
7001 searchConfiguration = new SearchConfiguration()
7002 {
7003 resultPageLink = Converter.ToString(productsPageId),
7004 searchFeedId = productsSearchId + "&feed=true",
7005 groupsFeedId = GetPageIdByNavigationTag("ProductGroupsFeed"),
7006 searchPlaceholder = Translate("Search products"),
7007 searchTemplate = "SearchResultsTypeAheadWithFilters",
7008 searchType = "product-search",
7009 showGroups = Model.Area.Item.GetItem("Layout").GetBoolean("ShowGroupsSelector")
7010 };
7011 break;
7012 case "combinedSearch":
7013 searchConfiguration = new SearchConfiguration()
7014 {
7015 searchFeedId = productsSearchId + "&feed=true",
7016 searchSecondFeedId = GetPageIdByNavigationTag("ContentSearchFeed") + "&Areaid=" + Model.Area.ID + "&pagesOnly=true",
7017 resultPageLink = Converter.ToString(productsPageId),
7018 searchPlaceholder = Translate("Search products or pages"),
7019 groupsFeedId = GetPageIdByNavigationTag("ProductGroupsFeed"),
7020 searchType = "combined-search",
7021 searchTemplate = "SearchProductsTemplateWrap",
7022 searchContentTemplate = "SearchPagesTemplateWrap",
7023 showGroups = Model.Area.Item.GetItem("Layout").GetBoolean("ShowGroupsSelector")
7024 };
7025 break;
7026 default: //productSearch
7027 searchConfiguration = new SearchConfiguration()
7028 {
7029 resultPageLink = Converter.ToString(productsPageId),
7030 searchFeedId = productsSearchId + "&feed=true",
7031 groupsFeedId = GetPageIdByNavigationTag("ProductGroupsFeed"),
7032 searchPlaceholder = Translate("Search products"),
7033 searchTemplate = "SearchResultsTypeAhead",
7034 searchType = "product-search",
7035 showGroups = Model.Area.Item.GetItem("Layout").GetBoolean("ShowGroupsSelector")
7036 };
7037 break;
7038 }
7039 searchConfiguration.searchValue = HttpContext.Current.Request.QueryString.Get("Search") ?? "";
7040
7041 if (type == "mini-search")
7042 {
7043 @RenderMiniSearch(searchConfiguration)
7044 }
7045 else
7046 {
7047 @RenderSearchBar(searchConfiguration)
7048 @RenderSearchModal(searchConfiguration)
7049 }
7050 }
7051 }
7052
7053 @helper RenderSearchModal(SearchConfiguration options)
7054 {
7055 bool isFavoritesPage = GetPageIdByNavigationTag("FavoriteProductsPage") > 0 ? PageView.Current().ID == GetPageIdByNavigationTag("FavoriteProductsPage") : false;
7056 SommifyConfiguration sommifyConfiguration = GetSommifySettings();
7057 bool userIsImpersonating = Smartpage.PhilipsonWine.Ecommerce.Helpers.Helper.AllowsPartialPurchase();
7058
7059 <input type="checkbox" id="SearchModalTrigger" class="modal-trigger @(isFavoritesPage ? "js-search-modal-trigger-input" : "") @(isProductSearchWithFilters() ? "search-modal-with-filters-trigger-input js-search-modal-with-filters-trigger-input" : "")">
7060 <div class="modal-container @(isProductSearchWithFilters() ? "full-screen-search-modal-container js-full-screen-search-modal-container" : "")">
7061 <label for="SearchModalTrigger" id="SearchModalOverlay" class="@(!isProductSearchWithFilters() ? "modal-overlay" : "")"></label>
7062 <div class="search-modal modal modal--xl modal-height--auto @(isProductSearchWithFilters() ? "search-modal-products-with-filters" : "js-search-modal")" id="SearchModal">
7063 <div class="modal__body js-typeahead"
7064 data-search-feed-id="@options.searchFeedId"
7065 data-search-second-feed-id="@options.searchSecondFeedId"
7066 data-result-page-id="@options.resultPageLink"
7067 data-groups-page-id="@options.groupsFeedId"
7068 data-search-type="@options.searchType">
7069 <div class="grid top-section">
7070 <div class="contact-info grid__col-3 u-padding-left-none">
7071 <div class="icon">
7072 <img src="~/Files/Images/SvgIcons/phone.svg" alt="Alternate Text" />
7073 </div>
7074 <div class="info">
7075 <div class="info__header">
7076 @Translate("Smartpage:Search.Modal.Questions", "Spørgsmål?")
7077 </div>
7078 <div class="info__phone">
7079 @Translate("Smartpage:Search.Modal.PhoneInfo", "Ring tlf: +45 70 22 68 88")
7080 </div>
7081 </div>
7082 </div>
7083 <div class="typeahead u-color-inherit dw-mod custom__header__searchbar @(isProductSearchWithFilters() && !userIsImpersonating ? "js-custom-header-modal-searchbar" : "")" id="ProductSearchBar">
7084 @if (options.showGroups)
7085 {
7086 <button type="button" class="btn btn--condensed u-color-light-gray--bg typeahead-group-btn dw-mod js-typeahead-groups-btn" data-group-id="all">@Translate("All")</button>
7087 <ul class="dropdown dropdown--absolute-position u-min-w220px js-handlebars-root js-typeahead-groups-content dw-mod" id="ProductSearchBarGroupsContent" data-template="SearchGroupsTemplate" data-json-feed="/Default.aspx?ID=@options.groupsFeedId&feedType=productGroups" data-init-onload="false" data-preloader="minimal"></ul>
7088 }
7089 <div class="typeahead-search-field">
7090 <form action="@SearchEngineFriendlyURLs.GetFriendlyUrl(GetPageIdByNavigationTag("ProductsPage"))" id="SearchSubmitForm">
7091 <input id="TypeaheadSearchField" type="text" class="u-no-margin u-full-width u-full-height js-typeahead-search-field js-ignore-click-outside search-input" placeholder="@HttpUtility.HtmlAttributeEncode(options.searchPlaceholder)" value="@HttpUtility.HtmlAttributeEncode(options.searchValue)" name="Search">
7092 </form>
7093 </div>
7094 <button type="button" class="btn btn--condensed btn--primary u-no-margin dw-mod js-typeahead-enter-btn search-bar-icon" title="@HttpUtility.HtmlAttributeEncode(Translate("Search"))" style="@(sommifyConfiguration != null && sommifyConfiguration.sommifyIsActive ? "border-radius: 0px;" : "")">
7095 @{
7096 var customIcon = PageView.Current().AreaSettings.GetItem("Layout").GetFile("CustomSearchIcon");
7097 if (customIcon != null)
7098 {
7099 <img src="@customIcon.Path" />
7100 }
7101 else
7102 {
7103 <i class="@Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("SearchIcon").SelectedValue"></i>
7104 }
7105 }
7106
7107 </button>
7108
7109 @if (sommifyConfiguration != null && sommifyConfiguration.sommifyIsActive)
7110 {
7111 @RenderSommifyOnSearchBar(sommifyConfiguration)
7112 }
7113 </div>
7114 <div class="u-flex u-flex--row modal-close-wrapper">
7115 <span class="info-text__close-button">@Translate("Smartpage:Search.Modal.Close", "Luk vindue")</span><label class="modal__close-btn @(isProductSearchWithFilters() ? "js-search-modal-close-btn" : "")" for="SearchModalTrigger"></label>
7116 </div>
7117 </div>
7118 <div class="grid">
7119 @RenderSearchContent(options.searchTemplate)
7120 </div>
7121 </div>
7122 </div>
7123 </div>
7124 }
7125
7126 @helper RenderSearchContent(string template)
7127 {
7128 <div class="js-typeahead-search-content grid u-flex--row typeahead-search-content" id="ProductSearchBarContent" data-template="@template" data-init-onload="false" data-pre-render-template="ProductSearchPreRenderContainer"></div>
7129 }
7130
7131 @helper RenderSearchBar(SearchConfiguration options)
7132 {
7133 bool isFavoritesPage = GetPageIdByNavigationTag("FavoriteProductsPage") > 0 ? PageView.Current().ID == GetPageIdByNavigationTag("FavoriteProductsPage") : false;
7134
7135 if (isFavoritesPage)
7136 {
7137 <div class="favorites-page-confirm-search-overlay js-favorites-page-confirm-search-overlay"></div>
7138 <div class="favorites-page-confirm-search js-favorites-page-confirm-search">
7139 <div class="favorites-page-confirm-search-body">
7140 <div class="confirm-search-header">@Translate("Smartpage:Search.Modal.FavoritesSearchPrompt", "Ønsker du at søge efter varer i din favoritliste?")</div>
7141 <div class="confirm-search-buttons-container">
7142 <div class="btn btn--secondary dw-mod js-favorites-search-decline">@Translate("Smartpage:Search.Modal.FavoritesSearchPrompt.DeclineButton", "Nej, søg på alle produkter")</div>
7143 <div class="btn btn--primary dw-mod js-favorites-search-accept">@Translate("Smartpage:Search.Modal.FavoritesSearchPrompt.AcceptButton", "Ja, søg i favoritlisten")</div>
7144 </div>
7145 </div>
7146 </div>
7147 }
7148
7149 string searchModalTriggerClasses = "";
7150 searchModalTriggerClasses += "js-search-modal-trigger-focus-onclick";
7151
7152 if (isProductSearchWithFilters())
7153 {
7154 searchModalTriggerClasses += " js-search-modal-with-filters-trigger";
7155 }
7156
7157 SommifyConfiguration sommifyConfiguration = GetSommifySettings();
7158
7159 <div class="typeahead typeahead--centered u-color-inherit custom__header__searchbar @(isProductSearchWithFilters() ? "js-custom-header-searchbar" : "")" id="ProductSearchBar">
7160 <div class="typeahead-search-field">
7161 <label for="SearchModalTrigger" class="search-modal-trigger js-search-modal-trigger @searchModalTriggerClasses"></label>
7162 <input type="text" class="u-no-margin u-full-width u-full-height" placeholder="@HttpUtility.HtmlAttributeEncode(options.searchPlaceholder)" value="@HttpUtility.HtmlAttributeEncode(options.searchValue)" name="Search">
7163 </div>
7164 <button type="button" class="btn btn--condensed btn--primary u-no-margin dw-mod search-bar-icon" title="@HttpUtility.HtmlAttributeEncode(Translate("Search"))" style="@(sommifyConfiguration != null && sommifyConfiguration.sommifyIsActive ? "border-radius: 0px;" : "")">
7165 @{
7166 var customIcon = PageView.Current().AreaSettings.GetItem("Layout").GetFile("CustomSearchIcon");
7167 if (customIcon != null)
7168 {
7169 <img src="@customIcon.Path" />
7170 }
7171 else
7172 {
7173 <i class="@Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("SearchIcon").SelectedValue"></i>
7174 }
7175 }
7176
7177 </button>
7178
7179 @if (sommifyConfiguration != null && sommifyConfiguration.sommifyIsActive)
7180 {
7181 @RenderSommifyOnSearchBar(sommifyConfiguration)
7182 }
7183 </div>
7184 }
7185
7186 @helper RenderSommifyOnSearchBar(SommifyConfiguration sommifyConfiguration)
7187 {
7188 <div class="header-menu__link header-menu__link--icon sommify-header-container js-sommify-widget-activator dw-mod" style="@sommifyConfiguration.sommifyStyling">
7189 <div class="custom__header__icon__icon">
7190 @if (!string.IsNullOrEmpty(sommifyConfiguration.sommifyIcon))
7191 {
7192 <img class="sommify-header-icon" src="@sommifyConfiguration.sommifyIcon" />
7193 }
7194 </div>
7195 <div class="custom__header__icon__text sommify-header-text">
7196 @Translate("Smartpage:Header.Sommify.Text", "Wine AI")
7197 </div>
7198 </div>
7199 }
7200
7201 @helper RenderMiniSearch(SearchConfiguration options)
7202 {
7203 string topLayout = Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("TopLayout") != null ? Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("TopLayout").SelectedValue : "normal";
7204 string menuLinkClass = topLayout != "normal" && topLayout != "splitted-center" ? "menu__link menu__link--icon" : "header-menu__link header-menu__link--icon";
7205
7206 <li class="menu__item menu__item--horizontal menu__item--top-level menu__item--icon u-hidden-xxs is-dropdown is-dropdown--no-icon dw-mod" id="miniSearchIcon">
7207 <div class="@menuLinkClass dw-mod" title="@Translate("Search")">
7208 <i class="@Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("SearchIcon").SelectedValue fa-1_5x"></i>
7209 </div>
7210 <div class="menu menu--dropdown menu--dropdown-right u-no-padding u-w380px grid__cell dw-mod">
7211 <div class="typeahead js-typeahead" id="ProductSearchBar"
7212 data-page-size="7"
7213 data-search-feed-id="@options.searchFeedId"
7214 data-search-second-feed-id="@options.searchSecondFeedId"
7215 data-result-page-id="@options.resultPageLink"
7216 data-search-type="@options.searchType">
7217 <div class="typeahead-search-field">
7218 <input type="text" class="u-no-margin u-full-width js-typeahead-search-field" id="headerSearch" data-shop-id="@Pageview.Area.EcomShopId" data-area-id="@Dynamicweb.Core.Converter.ToString(Pageview.AreaID)" placeholder="@options.searchPlaceholder" value="@options.searchValue">
7219 @if (string.IsNullOrEmpty(options.searchSecondFeedId))
7220 {
7221 <ul class="dropdown dropdown--absolute-position u-min-w220px u-full-width js-handlebars-root js-typeahead-search-content dw-mod" id="ProductSearchBarContent" data-template="@options.searchTemplate" data-json-feed="/Default.aspx?ID=@options.searchFeedId&feedType=productsOnly" data-init-onload="false"></ul>
7222 }
7223 else
7224 {
7225 <div class="dropdown dropdown--absolute-position dropdown--combined grid dropdown--right-aligned">
7226 <div class="js-handlebars-root js-typeahead-search-content grid__col-sm-7 grid__col--bleed-y" id="ProductSearchBarContent" data-template="@options.searchTemplate" data-json-feed="/Default.aspx?ID=@options.searchFeedId&feedType=productsOnly" data-init-onload="false"></div>
7227 <div class="js-handlebars-root js-typeahead-additional-search-content grid__col-sm-5 grid__col--bleed-y" id="ContentSearchBarContent" data-template="@options.searchContentTemplate" data-json-feed="/Default.aspx?ID=@options.searchSecondFeedId" data-init-onload="false"></div>
7228 </div>
7229 }
7230 </div>
7231 </div>
7232 </div>
7233 </li>
7234 }
7235 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
7236
7237 @using System
7238 @using System.Web
7239 @using Dynamicweb.Rapido.Blocks.Extensibility
7240 @using Dynamicweb.Rapido.Blocks
7241
7242 @{
7243 string headerConfigurationTopLayout = Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("TopLayout") != null ? Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("TopLayout").SelectedValue : "normal";
7244 bool headerConfigurationHideSearch = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("HideSearch");
7245
7246 BlocksPage headerConfigurationPage = BlocksPage.GetBlockPage("Master");
7247
7248 Block configDesktopLogo = headerConfigurationPage.GetBlockById("MasterDesktopLogo");
7249 headerConfigurationPage.RemoveBlock(configDesktopLogo);
7250
7251 Block configDesktopMenu = headerConfigurationPage.GetBlockById("MasterDesktopMenu");
7252 headerConfigurationPage.RemoveBlock(configDesktopMenu);
7253
7254 Block configSearchBar = headerConfigurationPage.GetBlockById("MasterSearchBar");
7255 headerConfigurationPage.RemoveBlock(configSearchBar);
7256
7257 Block configSearchAction = headerConfigurationPage.GetBlockById("MasterDesktopActionsMenuSearch");
7258 headerConfigurationPage.RemoveBlock(configSearchAction);
7259
7260 Block configDesktopActionsMenu = headerConfigurationPage.GetBlockById("MasterDesktopActionsMenu");
7261 headerConfigurationPage.RemoveBlock(configDesktopActionsMenu);
7262
7263 Block configDesktopExtra = headerConfigurationPage.GetBlockById("MasterDesktopExtra");
7264
7265 switch (headerConfigurationTopLayout)
7266 {
7267 case "condensed": //2
7268 configDesktopLogo.Design.Size = "auto-width";
7269 headerConfigurationPage.Add("MasterDesktopNavigation", configDesktopLogo);
7270
7271 configDesktopMenu.SortId = 20;
7272 configDesktopMenu.Design.Size = "auto";
7273 headerConfigurationPage.Add("MasterDesktopNavigation", configDesktopMenu);
7274
7275 configDesktopActionsMenu.SortId = 30;
7276 configDesktopActionsMenu.Design.Size = "auto-width";
7277 headerConfigurationPage.Add("MasterDesktopNavigation", configDesktopActionsMenu);
7278
7279 if (!headerConfigurationHideSearch)
7280 {
7281 configSearchBar.SortId = 40;
7282 configSearchBar.Design.Size = "12";
7283 configDesktopExtra.SortId = 50;
7284 headerConfigurationPage.Add("MasterDesktopExtra", configSearchBar);
7285 }
7286 break;
7287 case "splitted": //3
7288 configDesktopLogo.Design.Size = "auto";
7289 headerConfigurationPage.Add("MasterDesktopExtra", configDesktopLogo);
7290
7291 if (!headerConfigurationHideSearch)
7292 {
7293 configSearchBar.SortId = 20;
7294 configSearchBar.Design.Size = "auto";
7295 headerConfigurationPage.Add("MasterDesktopExtra", configSearchBar);
7296 }
7297
7298 headerConfigurationPage.Add("MasterDesktopNavigation", configDesktopMenu);
7299
7300 configDesktopActionsMenu.SortId = 20;
7301 configDesktopActionsMenu.Design.Size = "auto-width";
7302 headerConfigurationPage.Add("MasterDesktopNavigation", configDesktopActionsMenu);
7303 break;
7304 case "splitted-center": //4
7305 configDesktopLogo.Design.Size = "auto";
7306 headerConfigurationPage.Add("MasterDesktopExtra", configDesktopLogo);
7307 headerConfigurationPage.Add("MasterDesktopNavigation", configDesktopMenu);
7308
7309 configDesktopActionsMenu.SortId = 30;
7310 configDesktopActionsMenu.Design.Size = "auto-width";
7311 headerConfigurationPage.Add("MasterDesktopExtra", configDesktopActionsMenu);
7312
7313 if (!headerConfigurationHideSearch)
7314 {
7315 headerConfigurationPage.Add("MasterDesktopActionsMenu", configSearchAction);
7316 }
7317 break;
7318 case "minimal": //5
7319 configDesktopLogo.Design.Size = "auto-width";
7320 headerConfigurationPage.Add("MasterDesktopNavigation", configDesktopLogo);
7321
7322 configDesktopMenu.Design.Size = "auto";
7323 headerConfigurationPage.Add("MasterDesktopNavigation", configDesktopMenu);
7324
7325 configDesktopActionsMenu.SortId = 20;
7326 configDesktopActionsMenu.Design.Size = "auto-width";
7327 headerConfigurationPage.Add("MasterDesktopNavigation", configDesktopActionsMenu);
7328
7329 if (!headerConfigurationHideSearch)
7330 {
7331 headerConfigurationPage.Add("MasterDesktopActionsMenu", configSearchAction);
7332 }
7333 break;
7334 case "minimal-center": //6
7335 configDesktopLogo.Design.Size = "auto-width";
7336 headerConfigurationPage.Add("MasterDesktopNavigation", configDesktopLogo);
7337
7338 configDesktopMenu.Design.Size = "auto";
7339 headerConfigurationPage.Add("MasterDesktopNavigation", configDesktopMenu);
7340
7341 configDesktopActionsMenu.SortId = 20;
7342 configDesktopActionsMenu.Design.Size = "auto-width";
7343 headerConfigurationPage.Add("MasterDesktopNavigation", configDesktopActionsMenu);
7344
7345 if (!headerConfigurationHideSearch)
7346 {
7347 headerConfigurationPage.Add("MasterDesktopActionsMenu", configSearchAction);
7348 }
7349 break;
7350 case "minimal-right": //7
7351 configDesktopLogo.Design.Size = "auto-width";
7352 headerConfigurationPage.Add("MasterDesktopNavigation", configDesktopLogo);
7353
7354 configDesktopMenu.Design.Size = "auto";
7355 headerConfigurationPage.Add("MasterDesktopNavigation", configDesktopMenu);
7356
7357 configDesktopActionsMenu.SortId = 20;
7358 configDesktopActionsMenu.Design.Size = "auto-width";
7359 headerConfigurationPage.Add("MasterDesktopNavigation", configDesktopActionsMenu);
7360
7361 if (!headerConfigurationHideSearch)
7362 {
7363 headerConfigurationPage.Add("MasterDesktopActionsMenu", configSearchAction);
7364 }
7365 break;
7366 case "two-lines": //8
7367 configDesktopLogo.Design.Size = "auto";
7368 headerConfigurationPage.Add("MasterDesktopExtra", configDesktopLogo);
7369
7370 headerConfigurationPage.Add("MasterDesktopNavigation", configDesktopMenu);
7371
7372 configDesktopActionsMenu.SortId = 20;
7373 configDesktopActionsMenu.Design.Size = "auto-width";
7374 headerConfigurationPage.Add("MasterDesktopNavigation", configDesktopActionsMenu);
7375
7376 if (!headerConfigurationHideSearch)
7377 {
7378 headerConfigurationPage.Add("MasterDesktopActionsMenu", configSearchAction);
7379 }
7380 break;
7381 case "two-lines-centered": //9
7382 configDesktopLogo.Design.Size = "auto";
7383 headerConfigurationPage.Add("MasterDesktopExtra", configDesktopLogo);
7384
7385 configDesktopMenu.Design.Size = "auto-width";
7386 headerConfigurationPage.Add("MasterDesktopNavigation", configDesktopMenu);
7387
7388 configDesktopActionsMenu.SortId = 20;
7389 headerConfigurationPage.Add("MasterDesktopNavigation", configDesktopActionsMenu);
7390
7391 if (!headerConfigurationHideSearch)
7392 {
7393 headerConfigurationPage.Add("MasterDesktopActionsMenu", configSearchAction);
7394 }
7395 break;
7396 case "normal": //1
7397 default:
7398 headerConfigurationPage.Add("MasterDesktopExtra", configDesktopLogo);
7399
7400 if (!headerConfigurationHideSearch)
7401 {
7402 configSearchBar.SortId = 20;
7403 headerConfigurationPage.Add("MasterDesktopExtra", configSearchBar);
7404 }
7405
7406 configDesktopActionsMenu.SortId = 30;
7407 headerConfigurationPage.Add("MasterDesktopExtra", configDesktopActionsMenu);
7408
7409 configDesktopActionsMenu.Design.Size = "auto-width";
7410 headerConfigurationPage.Add("MasterDesktopNavigation", configDesktopMenu);
7411 break;
7412 }
7413 }
7414 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
7415 @using Dynamicweb.Rapido.Blocks
7416 @using Dynamicweb.Core;
7417
7418 @{
7419 var user = Dynamicweb.Security.UserManagement.User.GetCurrentExtranetUser();
7420 if (user != null && user.AllowBackend)
7421 {
7422 var editorsGroup = Pageview.AreaSettings.GetItem("Custom").GetRawValue("EditorsGroup");
7423 if (user.GroupsIds.Contains(Converter.ToInt32(editorsGroup)))
7424 {
7425 Block ShowPageIdBlock = new Block
7426 {
7427 Id = "ShowPageId",
7428 SortId = -10,
7429 Template = RenderShowPageIdSection(),
7430 Design = new Design
7431 {
7432 Size = "auto-width",
7433 HidePadding = true,
7434 RenderType = RenderType.Column,
7435 CssClass = "grid--align-self-center"
7436 }
7437 };
7438
7439 BlocksPage.GetBlockPage("Master").Add("MasterHeader", ShowPageIdBlock);
7440 }
7441 }
7442
7443 }
7444
7445 @helper RenderShowPageIdSection()
7446 {
7447 <div class="u-ta-center u-padding" style="background-color:#fecd00">
7448 @Translate("Smartpage:Header.ClickToCopy", "Tryk på side id for at kopiere:") <span onclick="navigator.clipboard.writeText(event.innerText)" class="u-bold u-underline u-pointer">@Pageview.ID</span>
7449 </div>
7450 }
7451 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
7452 @using System.Web
7453 @using Dynamicweb.Rapido.Blocks
7454 @using Dynamicweb;
7455 @using Dynamicweb.Core;
7456 @using System.Text.RegularExpressions
7457 @using Dynamicweb.Ecommerce.International
7458
7459 @{
7460 if (Model.ID != GetPageIdByNavigationTag("CartPage") && Model.ID != GetPageIdByNavigationTag("CheckoutPage"))
7461 {
7462 Block masterToolbar = new Block
7463 {
7464 Id = "MasterToolbar",
7465 SortId = 0,
7466 Template = RenderToolbar(),
7467 Design = new Design
7468 {
7469 Size = "auto-width",
7470 HidePadding = true,
7471 RenderType = RenderType.Column,
7472 CssClass = "grid--align-self-center custom__header__toolbar js-custom__header__toolbar"
7473 }
7474 };
7475
7476 BlocksPage.GetBlockPage("Master").Add("MasterHeader", masterToolbar);
7477 }
7478 }
7479
7480 @helper RenderToolbar()
7481 {
7482 string trustpilotFreeWidget = Model.Area.Item.GetItem("Custom").GetRawValueString("HeaderTrustpilotWidget");
7483 var headerUsp = Pageview.AreaSettings.GetItem("Custom").GetItem("CustomSettings").GetItems("HeaderUSP");
7484 <div class="center-container grid top-container__center-container dw-mod">
7485 <div class="grid grid--align-center custom__header__usp__container">
7486 <div>
7487 <ul class="u-flex custom__header__usp">
7488 @foreach (var usp in headerUsp)
7489 {
7490 var icon = usp.GetFile("Icon");
7491 <li class="u-flex whitespace-nowrap">
7492 @if (!string.IsNullOrWhiteSpace(usp.GetString("Link")))
7493 {
7494 <a class="u-flex" href="@usp.GetString("Link")">
7495 @{
7496 if (icon != null)
7497 {
7498 <img class="u-margin-right" src="@icon.Path" alt="@HttpUtility.HtmlAttributeEncode(usp.GetString("Label"))" />
7499 }
7500 else
7501 {
7502 <i class="fa fa-check u-margin-right u-flex u-flex--align-center"></i>
7503 }
7504 }
7505 @usp.GetString("Label")
7506 </a>
7507 }
7508 else
7509 {
7510 if (icon != null)
7511 {
7512 <img class="u-margin-right" src="@icon.Path" alt="@HttpUtility.HtmlAttributeEncode(usp.GetString("Label"))" />
7513 }
7514 else
7515 {
7516 <i class="fa fa-check u-margin-right u-flex u-flex--align-center"></i>
7517 } @usp.GetString("Label")
7518 }
7519 </li>
7520 }
7521 </ul>
7522 </div>
7523 @if (!string.IsNullOrEmpty(trustpilotFreeWidget))
7524 {
7525 <div>
7526 @trustpilotFreeWidget
7527 </div>
7528 }
7529 <div class="u-align-right custom__header__contacttext">
7530 @Translate("Smartpage:Header.ContactText", "Har du brug for hjælp eller vejledning? +45 70226888")
7531 </div>
7532 <div class="u-align-right currency-selector">
7533 @RenderCurrencySelectorSmall()
7534 </div>
7535 <div class="u-align-right language-selector">
7536 @RenderLanguageSelectorSmall()
7537 </div>
7538 </div>
7539 </div>
7540 }
7541
7542 @helper RenderCurrencySelectorSmall()
7543 {
7544 List<Currency> currencies = Dynamicweb.Ecommerce.Services.Currencies.GetCurrenciesForLanguage(Dynamicweb.Ecommerce.Common.Context.LanguageID).ToList();
7545
7546 if (currencies.Count > 1)
7547 {
7548 bool languageSelectionFromCookie = Dynamicweb.Environment.CookieManager.GetCookie("ActiveLanguageSelection") != null && Converter.ToBoolean(Dynamicweb.Environment.CookieManager.GetCookie("ActiveLanguageSelection").Value);
7549 var topLayout = Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("TopLayout")?.SelectedValue ?? "normal";
7550 var liClasses = topLayout != "normal" ? "menu__item--top-level u-hidden-xxs" : "menu--clean";
7551
7552 <li class="menu__item menu__item--horizontal @liClasses menu__item--icon is-dropdown is-dropdown--no-icon dw-mod">
7553 <div class="current-currency u-flex u-flex--row">
7554 @Dynamicweb.Ecommerce.Common.Context.Currency.Code
7555 </div>
7556 <div class="menu menu--dropdown menu--dropdown-right currencies-dropdown grid__cell dw-mod">
7557 @foreach (Currency currency in currencies)
7558 {
7559 var pageId = Pageview.Page.ID;
7560
7561 if (!languageSelectionFromCookie)
7562 {
7563 var currencyLanguageMapping = Pageview.AreaSettings.GetItem("Custom").GetItems("CurrencyLanguageMapping")?.FirstOrDefault(m => m.GetRawValueString("Currency") == currency.Code);
7564 if (currencyLanguageMapping != null)
7565 {
7566 var language = Model.Languages.FirstOrDefault(l => l.ID == Converter.ToInt32(currencyLanguageMapping.GetRawValueString("Language")));
7567
7568 if (language != null)
7569 {
7570 pageId = language.Page.ID;
7571 }
7572 }
7573 }
7574
7575 var qs = HttpUtility.ParseQueryString(Dynamicweb.Context.Current.Request.QueryString.ToString());
7576 qs.Set("ID", Converter.ToString(pageId));
7577 qs.Set("CurrencyCode", currency.Code);
7578 string url = Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl("Default.aspx?" + qs);
7579
7580 var activeClass = currency.Code == Dynamicweb.Ecommerce.Common.Context.Currency.Code ? "u-bold" : string.Empty;
7581
7582 <div class="menu__item dw-mod">
7583 <a href="@url" class="menu-dropdown__link dw-mod u-flex @(activeClass)">@currency.Code</a>
7584 </div>
7585 }
7586 </div>
7587 </li>
7588 }
7589 }
7590
7591 @helper RenderLanguageSelectorSmall()
7592 {
7593 string topLayout = Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("TopLayout") != null ? Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("TopLayout").SelectedValue : "normal";
7594 string liClasses = topLayout != "normal" ? "menu__item--top-level u-hidden-xxs" : "menu--clean";
7595 string menuLinkClass = topLayout != "normal" && topLayout != "splitted-center" ? "menu__link menu__link--icon" : "header-menu__link header-menu__link--icon";
7596 string languageViewType = !string.IsNullOrEmpty(Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("LanguageSelector").SelectedValue) ? Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("LanguageSelector").SelectedValue.ToLower() : "";
7597
7598 var languages = Model.Languages.Where(l => Dynamicweb.Services.Areas.GetArea(l.ID).Published).ToList();
7599
7600 if (languages.Count > 1)
7601 {
7602 <li class="menu__item menu__item--horizontal @liClasses menu__item--icon is-dropdown is-dropdown--no-icon dw-mod">
7603 <div class="current-language u-flex u-flex--row">
7604 @{
7605 var currentLanguage = Model.Languages.First(l => l.IsCurrent);
7606 var currentArea = Dynamicweb.Services.Areas.GetArea(currentLanguage.ID);
7607 string currentCultureName = Regex.Replace(currentArea.CultureInfo.NativeName, @" ?\(.*?\)", string.Empty);
7608 currentCultureName = char.ToUpper(currentCultureName[0]) + currentCultureName.Substring(1);
7609 string currentLanguageInfo = "<span class=\"flag-icon flag-icon-" + currentArea.EcomCountryCode.ToLower() + " u-margin-right\"></span>" + currentCultureName;
7610 }
7611 @currentLanguageInfo
7612 </div>
7613 <div class="menu menu--dropdown menu--dropdown-right languages-dropdown dw-mod grid__cell">
7614 @foreach (var lang in languages)
7615 {
7616 var area = Dynamicweb.Services.Areas.GetArea(lang.ID);
7617 var qs = HttpUtility.ParseQueryString(System.Web.HttpContext.Current.Request.QueryString.ToString());
7618 qs.Set("ID", Converter.ToString(lang.Page.ID));
7619 qs.Set("CurrencyCode", area.EcomCurrencyId);
7620 qs.Set("ActiveLanguageSelection", "True");
7621 string url = Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl("Default.aspx?" + qs);
7622 string primaryDomain = area.DomainLock;
7623
7624 if (!string.IsNullOrWhiteSpace(primaryDomain))
7625 {
7626 url = HttpContext.Current.Request.Url.Scheme + "://" + primaryDomain + url;
7627 }
7628 else
7629 {
7630 url = HttpContext.Current.Request.Url.Scheme + "://" + area.Domain.Split(new string[] { Environment.NewLine }, StringSplitOptions.None).First() + url;
7631 }
7632
7633
7634 string widthClass = "menu__item--fixed-width";
7635 string langInfo = "<span class=\"flag-icon flag-icon-" + area.EcomCountryCode.ToLower() + " u-margin-right\"></span>" + lang.Name;
7636 string cultureName = Regex.Replace(area.CultureInfo.NativeName, @" ?\(.*?\)", string.Empty);
7637 cultureName = char.ToUpper(cultureName[0]) + cultureName.Substring(1);
7638 string activeClass = Dynamicweb.Ecommerce.Common.Context.LanguageID == area.EcomLanguageId ? "u-bold" : string.Empty;
7639
7640 if (languageViewType == "flag-culture")
7641 {
7642 langInfo = "<span class=\" u-margin-right flag-icon flag-icon-" + area.EcomCountryCode.ToLower() + " \"></span> " + cultureName;
7643 }
7644
7645 if (languageViewType == "flag")
7646 {
7647 langInfo = "<span class=\" u-margin-right flag-icon flag-icon-" + area.EcomCountryCode.ToLower() + " \"></span>";
7648 widthClass = "";
7649 }
7650
7651 if (languageViewType == "name")
7652 {
7653 langInfo = lang.Name;
7654 }
7655
7656 if (languageViewType == "culture")
7657 {
7658 langInfo = cultureName;
7659 widthClass = "";
7660 }
7661
7662 if (url.Contains("/forside"))
7663 {
7664 url = url.Replace("/forside", "");
7665 }
7666
7667 <div class="menu__item dw-mod @widthClass">
7668 <a href="@url" class="menu-dropdown__link dw-mod u-flex @activeClass">@langInfo</a>
7669 </div>
7670 }
7671 </div>
7672 </li>
7673 }
7674 }
7675 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
7676
7677 @using System
7678 @using System.Web
7679 @using Dynamicweb.Rapido.Blocks.Extensibility
7680 @using Dynamicweb.Rapido.Blocks
7681
7682 @{
7683 Block masterDesktopActionsOffers = new Block
7684 {
7685 Id = "MasterDesktopActionsOffers",
7686 SortId = 10,
7687 Template = RenderOffers()
7688 };
7689
7690 @*BlocksPage.GetBlockPage("Master").Add("MasterDesktopActionsMenu", masterDesktopActionsOffers);*@
7691 }
7692
7693 @helper RenderOffers()
7694 {
7695 <li class="menu__item menu__item--horizontal menu__item menu__item--icon menu__item--clean is-dropdown is-dropdown--no-icon dw-mod">
7696 <div class="header-menu__link header-menu__link--icon dw-mod">
7697 <div class="custom__header__icon">
7698 <a href="/Default.aspx?ID=@GetPageIdByNavigationTag("OffersPage")">
7699 <div class="custom__header__icon__icon">
7700 <svg width="48px" height="48px" viewBox="0 0 48 48" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
7701 <g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
7702 <g id="Header" transform="translate(-1289.000000, -56.000000)" fill-rule="nonzero">
7703 <g id="TILBUD">
7704 <g transform="translate(1289.000000, 56.000000)">
7705 <polygon id="Path" fill="#FFCB00" points="43.87725 23.9999062 47.9999063 17.569125 41.2140938 14.0612813 41.569125 6.4306875 33.9385313 6.785625 30.4306875 0 24 4.1225625 17.5692188 0 14.061375 6.78571875 6.430875 6.43078125 6.7858125 14.061375 0 17.569125 4.12265625 23.9999062 0 30.4306875 6.78571875 33.9385312 6.4306875 41.569125 14.0612813 41.2141875 17.569125 48 24 43.8771562 30.4307812 47.9997187 33.938625 41.2140938 41.5692188 41.5690313 41.2141875 33.9384375 48 30.4305937"></polygon>
7706 <path d="M15.68,27.072 C16.544,27.072 17.342,26.904 18.074,26.568 C18.806,26.232 19.442,25.74 19.982,25.092 C20.522,24.444 20.948,23.658 21.26,22.734 C21.572,21.81 21.728,20.76 21.728,19.584 C21.728,18.408 21.572,17.364 21.26,16.452 C20.948,15.54 20.522,14.766 19.982,14.13 C19.442,13.494 18.806,13.008 18.074,12.672 C17.342,12.336 16.544,12.168 15.68,12.168 C14.816,12.168 14.012,12.336 13.268,12.672 C12.524,13.008 11.882,13.494 11.342,14.13 C10.802,14.766 10.382,15.54 10.082,16.452 C9.782,17.364 9.632,18.408 9.632,19.584 C9.632,20.76 9.782,21.81 10.082,22.734 C10.382,23.658 10.802,24.444 11.342,25.092 C11.882,25.74 12.524,26.232 13.268,26.568 C14.012,26.904 14.816,27.072 15.68,27.072 Z M20,36.432 L32.528,12.168 L29.072,12.168 L16.544,36.432 L20,36.432 Z M15.68,23.688 C15.2,23.688 14.78,23.4 14.42,22.824 C14.06,22.248 13.88,21.168 13.88,19.584 C13.88,18.792 13.928,18.138 14.024,17.622 C14.12,17.106 14.252,16.692 14.42,16.38 C14.588,16.068 14.78,15.852 14.996,15.732 C15.212,15.612 15.44,15.552 15.68,15.552 C15.92,15.552 16.148,15.612 16.364,15.732 C16.58,15.852 16.772,16.068 16.94,16.38 C17.108,16.692 17.24,17.106 17.336,17.622 C17.432,18.138 17.48,18.792 17.48,19.584 C17.48,21.168 17.3,22.248 16.94,22.824 C16.58,23.4 16.16,23.688 15.68,23.688 Z M33.32,36.432 C34.184,36.432 34.982,36.264 35.714,35.928 C36.446,35.592 37.082,35.1 37.622,34.452 C38.162,33.804 38.588,33.018 38.9,32.094 C39.212,31.17 39.368,30.12 39.368,28.944 C39.368,27.768 39.212,26.724 38.9,25.812 C38.588,24.9 38.162,24.126 37.622,23.49 C37.082,22.854 36.446,22.368 35.714,22.032 C34.982,21.696 34.184,21.528 33.32,21.528 C32.456,21.528 31.652,21.696 30.908,22.032 C30.164,22.368 29.522,22.854 28.982,23.49 C28.442,24.126 28.022,24.9 27.722,25.812 C27.422,26.724 27.272,27.768 27.272,28.944 C27.272,30.12 27.422,31.17 27.722,32.094 C28.022,33.018 28.442,33.804 28.982,34.452 C29.522,35.1 30.164,35.592 30.908,35.928 C31.652,36.264 32.456,36.432 33.32,36.432 Z M33.32,33.048 C32.84,33.048 32.42,32.76 32.06,32.184 C31.7,31.608 31.52,30.528 31.52,28.944 C31.52,28.152 31.568,27.498 31.664,26.982 C31.76,26.466 31.892,26.052 32.06,25.74 C32.228,25.428 32.42,25.212 32.636,25.092 C32.852,24.972 33.08,24.912 33.32,24.912 C33.56,24.912 33.788,24.972 34.004,25.092 C34.22,25.212 34.412,25.428 34.58,25.74 C34.748,26.052 34.88,26.466 34.976,26.982 C35.072,27.498 35.12,28.152 35.12,28.944 C35.12,30.528 34.94,31.608 34.58,32.184 C34.22,32.76 33.8,33.048 33.32,33.048 Z" id="%" fill="#000000"></path>
7707 </g>
7708 </g>
7709 </g>
7710 </g>
7711 </svg>
7712 </div>
7713 <div class="custom__header__icon__text yellow">
7714 @Translate("Smartpage:Header.IconsText.Tilbud!", "Tilbud!")
7715 </div>
7716 </a>
7717 </div>
7718 </div>
7719 </li>
7720
7721 }
7722 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
7723 @using Dynamicweb.Rapido.Blocks
7724
7725 @{
7726 bool activateOfferNewspaper = Pageview.AreaSettings.GetItem("Custom").GetBoolean("ActivateOfferNewspaper");
7727 bool activatePriceBook = Pageview.AreaSettings.GetItem("Custom").GetBoolean("ActivateHeaderPriceBook");
7728 if (activateOfferNewspaper)
7729 {
7730 Block masterDesktopActionsOfferNewspaperBlock = new Block
7731 {
7732 Id = "MasterDesktopActionsOfferNewspaper",
7733 SortId = 10,
7734 Template = RenderOfferNewspaper()
7735 };
7736
7737 BlocksPage.GetBlockPage("Master").Add("MasterDesktopActionsMenu", masterDesktopActionsOfferNewspaperBlock);
7738 }
7739
7740 if (activatePriceBook && Model.CurrentUser.ID > 0)
7741 {
7742 var priceBookList = Dynamicweb.Ecommerce.CustomerCenter.CustomerProductList.GetListByCustomerId(Converter.ToInt32(Model.CurrentUser.ID))?.FirstOrDefault(l => l.Type == "PriceBookList");
7743 if (priceBookList != null)
7744 {
7745 string link = $"/Default.aspx?Id={GetPageIdByNavigationTag("FavoriteProductsPage")}&ListID={priceBookList.ID}&ListName={priceBookList.Name}";
7746 Block masterDesktopActionsPriceBoookBlock = new Block
7747 {
7748 Id = "MasterDesktopActionsPriceBook",
7749 SortId = 10,
7750 Template = RenderPriceBook(link, Translate("Smartpage:Header.PriceBookText.PriceBook", "Din prisbog"), "fal fa-dollar-sign")
7751 };
7752
7753 BlocksPage.GetBlockPage("Master").Add("MasterDesktopActionsMenu", masterDesktopActionsPriceBoookBlock);
7754 }
7755 }
7756 }
7757
7758 @helper RenderOfferNewspaper()
7759 {
7760 string newsPaperLink = Pageview.AreaSettings.GetItem("Custom").GetString("OfferNewspaperLink");
7761
7762 <li class="menu__item menu__item--horizontal menu__item menu__item--icon menu__item--clean is-dropdown is-dropdown--no-icon dw-mod">
7763 <div class="header-menu__link header-menu__link--icon dw-mod">
7764 <div class="custom__header__icon">
7765 <a href="@newsPaperLink">
7766 <div class="custom__header__icon__icon newspaper-icon">
7767 @RenderOfferNewspaperIcon()
7768 </div>
7769 <div class="custom__header__icon__text">
7770 <div>
7771 <div class="custom__header__icon__text">
7772 @Translate("Smartpage:Header.OfferNewspaperText.OfferNewspaper", "Tilbudsavis")
7773 </div>
7774 </div>
7775 </div>
7776 </a>
7777 </div>
7778 </div>
7779 </li>
7780 }
7781
7782 @helper RenderPriceBook(string link, string text, string icon = null)
7783 {
7784 <li class="menu__item menu__item--horizontal menu__item menu__item--icon menu__item--clean is-dropdown is-dropdown--no-icon dw-mod">
7785 <div class="header-menu__link header-menu__link--icon dw-mod">
7786 <div class="custom__header__icon">
7787 <a href="@link">
7788 @if (!string.IsNullOrEmpty(icon))
7789 {
7790 <div class="custom__header__icon__icon custom__header__icon__price__book @icon"></div>
7791 }
7792 <div class="custom__header__icon__text">
7793 <div>
7794 <div class="custom__header__icon__text">
7795 @text
7796 </div>
7797 </div>
7798 </div>
7799 </a>
7800 </div>
7801 </div>
7802 </li>
7803 }
7804
7805 @helper RenderOfferNewspaperIcon()
7806 {
7807 <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="#ffffff" height="40px" width="54px" version="1.1" viewBox="0 0 465 465" xml:space="preserve">
7808 <g>
7809 <path d="M371.957,60.634h-26.884V9.5c0-2.925-1.348-5.688-3.653-7.488c-2.307-1.801-5.316-2.438-8.15-1.729L90.745,60.912 l0.003,0.012c-4.136,1.028-7.205,4.755-7.205,9.209V455.5c0,5.247,4.253,9.5,9.5,9.5h278.915c5.247,0,9.5-4.253,9.5-9.5V70.134 C381.457,64.887,377.205,60.634,371.957,60.634z M326.074,60.634H170.201l155.873-38.966V60.634z M362.457,446H102.542V79.634 h259.915V446z" />
7810 <path d="M127.632,156.409h209.735c5.247,0,9.5-4.253,9.5-9.5v-43.245c0-5.247-4.253-9.5-9.5-9.5H127.632 c-5.247,0-9.5,4.253-9.5,9.5v43.245C118.132,152.156,122.385,156.409,127.632,156.409z M137.132,113.164h190.735v24.245H137.132 V113.164z" />
7811 <path d="M337.368,175.123H250.22c-5.247,0-9.5,4.253-9.5,9.5v135.358c0,5.247,4.253,9.5,9.5,9.5h87.147c5.247,0,9.5-4.253,9.5-9.5 V184.623C346.868,179.376,342.615,175.123,337.368,175.123z M327.868,310.481H259.72V194.123h68.147V310.481z" />
7812 <path d="M127.632,194.123h87.147c5.247,0,9.5-4.253,9.5-9.5s-4.253-9.5-9.5-9.5h-87.147c-5.247,0-9.5,4.253-9.5,9.5 S122.385,194.123,127.632,194.123z" />
7813 <path d="M127.632,227.794h87.147c5.247,0,9.5-4.253,9.5-9.5s-4.253-9.5-9.5-9.5h-87.147c-5.247,0-9.5,4.253-9.5,9.5 S122.385,227.794,127.632,227.794z" />
7814 <path d="M127.632,261.465h87.147c5.247,0,9.5-4.253,9.5-9.5c0-5.247-4.253-9.5-9.5-9.5h-87.147c-5.247,0-9.5,4.253-9.5,9.5 C118.132,257.212,122.385,261.465,127.632,261.465z" />
7815 <path d="M127.632,295.137h87.147c5.247,0,9.5-4.253,9.5-9.5s-4.253-9.5-9.5-9.5h-87.147c-5.247,0-9.5,4.253-9.5,9.5 S122.385,295.137,127.632,295.137z" />
7816 <path d="M127.632,328.808h87.147c5.247,0,9.5-4.253,9.5-9.5s-4.253-9.5-9.5-9.5h-87.147c-5.247,0-9.5,4.253-9.5,9.5 S122.385,328.808,127.632,328.808z" />
7817 <path d="M127.632,362.479h209.735c5.247,0,9.5-4.253,9.5-9.5s-4.253-9.5-9.5-9.5H127.632c-5.247,0-9.5,4.253-9.5,9.5 S122.385,362.479,127.632,362.479z" />
7818 <path d="M127.632,396.15h209.735c5.247,0,9.5-4.253,9.5-9.5s-4.253-9.5-9.5-9.5H127.632c-5.247,0-9.5,4.253-9.5,9.5 S122.385,396.15,127.632,396.15z" />
7819 <path d="M127.632,429.822h209.735c5.247,0,9.5-4.253,9.5-9.5s-4.253-9.5-9.5-9.5H127.632c-5.247,0-9.5,4.253-9.5,9.5 S122.385,429.822,127.632,429.822z" />
7820 </g>
7821 </svg>
7822 }
7823 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
7824 @using Dynamicweb.Rapido.Blocks
7825 @using Smartpage.PhilipsonWine.LiveShopper.Models;
7826
7827 @{
7828 if (Pageview.AreaSettings.GetItem("Custom").GetBoolean("ActivateLiveshopper"))
7829 {
7830 var upcomingEvent = Dynamicweb.Context.Current.Application["SpLiveShopperEvent"] as Event;
7831 Block masterDesktopActionsLiveshoppingBlock = new Block
7832 {
7833 Id = "MasterDesktopActionsLiveshopping",
7834 SortId = 10,
7835 Template = RenderLiveshoppingIcon(upcomingEvent)
7836 };
7837
7838 BlocksPage.GetBlockPage("Master").Add("MasterDesktopActionsMenu", masterDesktopActionsLiveshoppingBlock);
7839 }
7840 }
7841
7842 @helper RenderLiveshoppingIcon(Event upcomingEvent)
7843 {
7844 DateTime now = DateTime.Now;
7845 bool isEventLive = upcomingEvent != null && now > upcomingEvent.Start && now < upcomingEvent.End;
7846
7847 <li class="menu__item menu__item--horizontal menu__item menu__item--icon menu__item--clean is-dropdown is-dropdown--no-icon dw-mod">
7848 <div class="header-menu__link header-menu__link--icon dw-mod">
7849 <div class="custom__header__icon">
7850 <a href="/Default.aspx?ID=@GetPageIdByNavigationTag("LiveshoppingPage")">
7851 <div class="custom__header__icon__icon liveshopping-icon">
7852 @if (isEventLive)
7853 {
7854 @RenderLiveshoppingGreenIcon()
7855 }
7856 else
7857 {
7858 @RenderLiveshoppingWhiteIcon()
7859 }
7860 </div>
7861 <div class="custom__header__icon__text">
7862 <div>
7863 @if (isEventLive)
7864 {
7865 <div class="pulsating-circle"></div>
7866 }
7867 <div class="custom__header__icon__text">
7868 @Translate("Smartpage:Header.LiveshoppingText.Liveshopping", "Liveshopping")
7869 </div>
7870 </div>
7871 @if (isEventLive)
7872 {
7873 <div class="custom__header__icon__text__subtext">
7874 @Translate("Smartpage:Header.LiveshoppingSubtextText.WeAreLive", "Vi sender nu!")
7875 </div>
7876 }
7877 else if (upcomingEvent != null)
7878 {
7879 TimeSpan timeDifference = now - upcomingEvent.Start;
7880
7881 double daysDifference = Math.Abs((timeDifference).Days);
7882 double hoursDifference = Math.Abs((timeDifference).TotalHours);
7883 double minutesDifference = Math.Abs((timeDifference).TotalMinutes);
7884 double secondsDifference = Math.Abs((timeDifference).TotalSeconds);
7885
7886 string daysText = daysDifference > 1 ? Translate("Smartpage.LiveshoppingCountdown.Days", "dage") : Translate("Smartpage.LiveshoppingCountdown.Day", "dag");
7887 string hoursText = hoursDifference > 1 ? Translate("Smartpage.LiveshoppingCountdown.Hours", "timer") : Translate("Smartpage.LiveshoppingCountdown.Hour", "time");
7888 string minutesText = Translate("Smartpage.LiveshoppingCountdown.Minutes", "min");
7889 string secondsText = Translate("Smartpage.LiveshoppingCountdown.Seconds", "sek");
7890
7891 <div class="u-flex js-countdown custom__header__icon__text__subtext" data-countdown-seconds="@secondsDifference">
7892 <div><span class="js-days u-bold"></span> @daysText</div>
7893 <div><span class="js-hours u-bold"></span> @hoursText</div>
7894 <div><span class="js-minutes u-bold"></span> @minutesText</div>
7895 <div><span class="js-seconds u-bold"></span> @secondsText</div>
7896 </div>
7897 }
7898 </div>
7899 </a>
7900 </div>
7901 </div>
7902 </li>
7903 }
7904
7905 @helper RenderLiveshoppingGreenIcon()
7906 {
7907 <svg width="54px" height="40px" viewBox="0 0 54 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
7908 <title>live-active</title>
7909 <defs>
7910 <path d="M32.0214799,18.4559033 C32.8126585,18.452044 33.5016486,17.9130626 33.6984183,17.1440525 L35.7269729,9.64381814 C35.7549923,9.51994021 35.7251134,9.38999772 35.6458307,9.29097171 C35.5633361,9.20212396 35.4508359,9.14728857 35.3302637,9.13715272 L20.291955,9.13715272 L19.264154,5.38251895 C19.2316971,5.17420385 19.0397451,5.02975734 18.8313957,5.05681456 L16.3790846,5.05681456 L16.3790846,5.88010876 L18.5699235,5.88010876 L19.570677,9.63474252 L21.5992316,17.1440525 L21.6533264,17.2887958 L22.3565586,19.8582558 C21.6927986,20.2132651 21.2848056,20.9131054 21.3017102,21.6677388 L21.3017102,22.0839025 L21.3468033,22.0839025 C21.527725,23.0043143 22.3323005,23.6676401 23.2671683,23.6671945 C24.3740406,23.6721779 25.2767896,22.7784417 25.2867211,21.6676964 C25.275395,21.2430932 25.133692,20.8323155 24.8810102,20.4915557 L30.4076803,20.4915557 C30.1582103,20.8334181 30.0197192,21.2440686 30.0109711,21.6676964 C30.0209025,22.7784417 30.9236093,23.6721779 32.0305239,23.6671945 C32.9653917,23.6675977 33.7699672,23.0042719 33.9508889,22.0839025 L33.9959819,22.0839025 L33.9959819,21.6677388 C34.0059557,20.5734908 33.1300427,19.678355 32.0396524,19.6683464 C32.033609,19.668304 32.0275656,19.6682615 32.0215222,19.6682615 L23.2671683,19.6682615 L23.1319313,19.6682615 L22.7893169,18.3835528 C22.943318,18.4348258 23.1049262,18.459296 23.2671683,18.4559457 L32.0214799,18.4559457 L32.0214799,18.4559033 Z M32.3613634,20.6893079 C32.9780335,20.6752928 33.489321,21.1619997 33.503348,21.7763955 C33.5036677,21.7904106 33.5037077,21.8044257 33.5035079,21.8184408 C33.5036677,22.4184631 33.022872,22.908833 32.4207884,22.9226491 L32.4122763,22.9141683 C31.7956062,22.9281834 31.2843187,22.4414766 31.2702916,21.8270808 C31.2561847,21.2126851 31.7446932,20.7032832 32.3613634,20.6893079 Z M23.4694133,20.6891477 C24.086042,20.698581 24.578266,21.2040784 24.5689546,21.818238 C24.57395,22.4231632 24.0856424,22.9176353 23.4782851,22.9226107 C23.4638984,22.9227301 23.4494718,22.9225709 23.4350851,22.922133 L23.4350851,22.913655 C22.8183365,22.9042217 22.3260725,22.398565 22.3355837,21.7843259 C22.3450949,21.1700867 22.8527046,20.6796746 23.4694133,20.6891477 Z" id="path-1"></path>
7911 <filter x="-76.0%" y="-79.4%" width="252.1%" height="258.7%" filterUnits="objectBoundingBox" id="filter-2">
7912 <feOffset dx="0" dy="0" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
7913 <feGaussianBlur stdDeviation="5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
7914 <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.2 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
7915 </filter>
7916 </defs>
7917 <g id="Header" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
7918 <g transform="translate(-1232.000000, -615.000000)" id="Header---2022---Dec-Copy-2">
7919 <g transform="translate(-1.000000, 496.000000)">
7920 <g id="Live" transform="translate(1192.000000, 0.000000)">
7921 <g id="live-active" transform="translate(41.000000, 125.000000)">
7922 <g id="Shape">
7923 <use fill="black" fill-opacity="1" filter="url(#filter-2)" xlink:href="#path-1"></use>
7924 <use fill="#50A87D" fill-rule="evenodd" xlink:href="#path-1"></use>
7925 </g>
7926 <path d="M10.3647541,23.4047666 C10.5829316,23.6197707 10.8690661,23.7272727 11.1550516,23.7272727 C11.4410371,23.7272727 11.7271716,23.6197707 11.9453492,23.4047666 C12.3818533,22.9744647 12.3818533,22.27717 11.9453492,21.8470149 C9.90470344,19.8360511 8.78073134,17.1623049 8.78073134,14.3182002 C8.78073134,11.4740955 9.90470344,8.80034925 11.9453492,6.78938542 C12.3818533,6.35908351 12.3818533,5.66178882 11.9453492,5.23178063 C11.508994,4.80162559 10.8012582,4.80147873 10.3647541,5.23163377 C7.90176191,7.65865402 6.54545455,10.8857715 6.54545455,14.3182002 C6.54545455,17.7506289 7.90176191,20.9775995 10.3647541,23.4047666 Z" id="Path" fill="#50A87D" fill-rule="nonzero"></path>
7927 <path d="M42.0546508,23.4047666 C42.2728284,23.6197707 42.5589629,23.7272727 42.8449484,23.7272727 C43.1309339,23.7272727 43.4170684,23.6197707 43.6352459,23.4047666 C46.0982381,20.9775995 47.4545455,17.7506289 47.4545455,14.3182002 C47.4545455,10.8857714 46.0980891,7.65865401 43.6352459,5.23163376 C43.1987418,4.80162558 42.491006,4.80147872 42.0546508,5.23178062 C41.6181467,5.66193567 41.6181467,6.35923036 42.0546508,6.78938541 C44.0952966,8.80020238 45.2192687,11.4739486 45.2192687,14.3182002 C45.2192687,17.162158 44.0952966,19.8359043 42.0546508,21.8470149 C41.6181467,22.27717 41.6181467,22.9744647 42.0546508,23.4047666 Z" id="Path" fill="#50A87D" fill-rule="nonzero"></path>
7928 <path d="M6.26235997,27 C6.54414929,27 6.82608544,26.8929969 7.04106176,26.6789908 C7.47116123,26.2506862 7.47116123,25.5566281 7.04106176,25.1284697 C3.92082148,22.0224574 2.20247936,17.8926071 2.20247936,13.5000731 C2.20247936,9.10739287 3.92082148,4.97754257 7.04106176,1.87153028 C7.47116123,1.44322568 7.47116123,0.749167592 7.04106176,0.321009177 C6.61096228,-0.107003059 5.91361082,-0.107003059 5.48365819,0.321009177 C1.94741525,3.84129287 0,8.52179963 0,13.5000731 C0,18.4783466 1.94741525,23.1587071 5.48365819,26.6789908 C5.69863451,26.8928508 5.98042382,27 6.26235997,27 Z" id="Path" fill="#8EFFC8" fill-rule="nonzero"></path>
7929 <path d="M46.1411428,25.1284697 C45.7105281,25.5567743 45.7105281,26.2508324 46.1411428,26.6789908 C46.3563767,26.8929969 46.6386506,27 46.9207775,27 C47.2029043,27 47.4851782,26.8929969 47.7004121,26.6789908 C55.0089536,19.4119921 55.0089536,7.58786173 47.7004121,0.321009177 C47.2697974,-0.107003059 46.5716105,-0.107003059 46.1411428,0.321009177 C45.7105281,0.749313771 45.7105281,1.44337186 46.1411428,1.87153028 C52.5897781,8.28338161 52.5897781,18.7166184 46.1411428,25.1284697 Z" id="Path" fill="#8EFFC8" fill-rule="nonzero"></path>
7930 </g>
7931 </g>
7932 </g>
7933 </g>
7934 </g>
7935 </svg>
7936 }
7937
7938 @helper RenderLiveshoppingWhiteIcon()
7939 {
7940 <svg width="54px" height="40px" viewBox="0 0 54 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
7941 <title>live</title>
7942 <defs>
7943 <path d="M32.0214799,18.4559033 C32.8126585,18.452044 33.5016486,17.9130626 33.6984183,17.1440525 L35.7269729,9.64381814 C35.7549923,9.51994021 35.7251134,9.38999772 35.6458307,9.29097171 C35.5633361,9.20212396 35.4508359,9.14728857 35.3302637,9.13715272 L20.291955,9.13715272 L19.264154,5.38251895 C19.2316971,5.17420385 19.0397451,5.02975734 18.8313957,5.05681456 L16.3790846,5.05681456 L16.3790846,5.88010876 L18.5699235,5.88010876 L19.570677,9.63474252 L21.5992316,17.1440525 L21.6533264,17.2887958 L22.3565586,19.8582558 C21.6927986,20.2132651 21.2848056,20.9131054 21.3017102,21.6677388 L21.3017102,22.0839025 L21.3468033,22.0839025 C21.527725,23.0043143 22.3323005,23.6676401 23.2671683,23.6671945 C24.3740406,23.6721779 25.2767896,22.7784417 25.2867211,21.6676964 C25.275395,21.2430932 25.133692,20.8323155 24.8810102,20.4915557 L30.4076803,20.4915557 C30.1582103,20.8334181 30.0197192,21.2440686 30.0109711,21.6676964 C30.0209025,22.7784417 30.9236093,23.6721779 32.0305239,23.6671945 C32.9653917,23.6675977 33.7699672,23.0042719 33.9508889,22.0839025 L33.9959819,22.0839025 L33.9959819,21.6677388 C34.0059557,20.5734908 33.1300427,19.678355 32.0396524,19.6683464 C32.033609,19.668304 32.0275656,19.6682615 32.0215222,19.6682615 L23.2671683,19.6682615 L23.1319313,19.6682615 L22.7893169,18.3835528 C22.943318,18.4348258 23.1049262,18.459296 23.2671683,18.4559457 L32.0214799,18.4559457 L32.0214799,18.4559033 Z M32.3613634,20.6893079 C32.9780335,20.6752928 33.489321,21.1619997 33.503348,21.7763955 C33.5036677,21.7904106 33.5037077,21.8044257 33.5035079,21.8184408 C33.5036677,22.4184631 33.022872,22.908833 32.4207884,22.9226491 L32.4122763,22.9141683 C31.7956062,22.9281834 31.2843187,22.4414766 31.2702916,21.8270808 C31.2561847,21.2126851 31.7446932,20.7032832 32.3613634,20.6893079 Z M23.4694133,20.6891477 C24.086042,20.698581 24.578266,21.2040784 24.5689546,21.818238 C24.57395,22.4231632 24.0856424,22.9176353 23.4782851,22.9226107 C23.4638984,22.9227301 23.4494718,22.9225709 23.4350851,22.922133 L23.4350851,22.913655 C22.8183365,22.9042217 22.3260725,22.398565 22.3355837,21.7843259 C22.3450949,21.1700867 22.8527046,20.6796746 23.4694133,20.6891477 Z" id="path-1"></path>
7944 <filter x="-76.0%" y="-79.4%" width="252.1%" height="258.7%" filterUnits="objectBoundingBox" id="filter-2">
7945 <feOffset dx="0" dy="0" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
7946 <feGaussianBlur stdDeviation="5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
7947 <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.2 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
7948 </filter>
7949 </defs>
7950 <g id="Header" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
7951 <g transform="translate(-1232.000000, -59.000000)" id="Header---2022---Dec">
7952 <g transform="translate(-1.000000, 0.000000)">
7953 <g id="Live" transform="translate(1192.000000, 65.000000)">
7954 <g id="live" transform="translate(41.000000, 0.000000)">
7955 <g id="Shape">
7956 <use fill="black" fill-opacity="1" filter="url(#filter-2)" xlink:href="#path-1"></use>
7957 <use fill="#FFFFFF" fill-rule="evenodd" xlink:href="#path-1"></use>
7958 </g>
7959 <path d="M10.3647541,23.4047666 C10.5829316,23.6197707 10.8690661,23.7272727 11.1550516,23.7272727 C11.4410371,23.7272727 11.7271716,23.6197707 11.9453492,23.4047666 C12.3818533,22.9744647 12.3818533,22.27717 11.9453492,21.8470149 C9.90470344,19.8360511 8.78073134,17.1623049 8.78073134,14.3182002 C8.78073134,11.4740955 9.90470344,8.80034925 11.9453492,6.78938542 C12.3818533,6.35908351 12.3818533,5.66178882 11.9453492,5.23178063 C11.508994,4.80162559 10.8012582,4.80147873 10.3647541,5.23163377 C7.90176191,7.65865402 6.54545455,10.8857715 6.54545455,14.3182002 C6.54545455,17.7506289 7.90176191,20.9775995 10.3647541,23.4047666 Z" id="Path" fill="#FFFFFF" fill-rule="nonzero"></path>
7960 <path d="M42.0546508,23.4047666 C42.2728284,23.6197707 42.5589629,23.7272727 42.8449484,23.7272727 C43.1309339,23.7272727 43.4170684,23.6197707 43.6352459,23.4047666 C46.0982381,20.9775995 47.4545455,17.7506289 47.4545455,14.3182002 C47.4545455,10.8857714 46.0980891,7.65865401 43.6352459,5.23163376 C43.1987418,4.80162558 42.491006,4.80147872 42.0546508,5.23178062 C41.6181467,5.66193567 41.6181467,6.35923036 42.0546508,6.78938541 C44.0952966,8.80020238 45.2192687,11.4739486 45.2192687,14.3182002 C45.2192687,17.162158 44.0952966,19.8359043 42.0546508,21.8470149 C41.6181467,22.27717 41.6181467,22.9744647 42.0546508,23.4047666 Z" id="Path" fill="#FFFFFF" fill-rule="nonzero"></path>
7961 <path d="M6.26235997,27 C6.54414929,27 6.82608544,26.8929969 7.04106176,26.6789908 C7.47116123,26.2506862 7.47116123,25.5566281 7.04106176,25.1284697 C3.92082148,22.0224574 2.20247936,17.8926071 2.20247936,13.5000731 C2.20247936,9.10739287 3.92082148,4.97754257 7.04106176,1.87153028 C7.47116123,1.44322568 7.47116123,0.749167592 7.04106176,0.321009177 C6.61096228,-0.107003059 5.91361082,-0.107003059 5.48365819,0.321009177 C1.94741525,3.84129287 0,8.52179963 0,13.5000731 C0,18.4783466 1.94741525,23.1587071 5.48365819,26.6789908 C5.69863451,26.8928508 5.98042382,27 6.26235997,27 Z" id="Path" fill="#FFFFFF" fill-rule="nonzero"></path>
7962 <path d="M46.1411428,25.1284697 C45.7105281,25.5567743 45.7105281,26.2508324 46.1411428,26.6789908 C46.3563767,26.8929969 46.6386506,27 46.9207775,27 C47.2029043,27 47.4851782,26.8929969 47.7004121,26.6789908 C55.0089536,19.4119921 55.0089536,7.58786173 47.7004121,0.321009177 C47.2697974,-0.107003059 46.5716105,-0.107003059 46.1411428,0.321009177 C45.7105281,0.749313771 45.7105281,1.44337186 46.1411428,1.87153028 C52.5897781,8.28338161 52.5897781,18.7166184 46.1411428,25.1284697 Z" id="Path" fill="#FFFFFF" fill-rule="nonzero"></path>
7963 </g>
7964 </g>
7965 </g>
7966 </g>
7967 </g>
7968 </svg>
7969 }
7970 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
7971 @using Dynamicweb.Rapido.Blocks
7972
7973 @{
7974 bool activateChainOrdersLink = Pageview.AreaSettings.GetItem("Custom").GetBoolean("ActivateChainOrdersLink");
7975 var chainCustomerProducts = Smartpage.PhilipsonWine.ChainCustomer.ChainProductService.GetChainCustomerProducts();
7976 if (activateChainOrdersLink && chainCustomerProducts.Any())
7977 {
7978 Block masterDesktopActionsChainOrdersBlock = new Block
7979 {
7980 Id = "MasterDesktopActionsChainOrders",
7981 SortId = 10,
7982 Template = RenderChainOrdersAction()
7983 };
7984
7985 BlocksPage.GetBlockPage("Master").Add("MasterDesktopActionsMenu", masterDesktopActionsChainOrdersBlock);
7986 }
7987 }
7988
7989 @helper RenderChainOrdersAction()
7990 {
7991 <li class="menu__item menu__item--horizontal menu__item menu__item--icon menu__item--clean is-dropdown is-dropdown--no-icon dw-mod">
7992 <div class="header-menu__link header-menu__link--icon dw-mod">
7993 <div class="custom__header__icon">
7994 <a href="/Default.aspx?ID=@GetPageIdByNavigationTag("ChainOrdersPage")">
7995 <div class="custom__header__icon__icon chain-order-icon">
7996 <svg xmlns="http://www.w3.org/2000/svg" width="26.786" height="25" viewBox="0 0 26.786 25">
7997 <path id="Path_6" data-name="Path 6" d="M5,30.321A2.679,2.679,0,1,1,7.679,33,2.679,2.679,0,0,1,5,30.321ZM7.679,13.357A2.679,2.679,0,1,0,5,10.679a2.679,2.679,0,0,0,2.679,2.679Zm0,9.821A2.679,2.679,0,1,0,5,20.5,2.679,2.679,0,0,0,7.679,23.179Zm8.929-10.714H30a1.786,1.786,0,0,0,0-3.571H16.607a1.786,1.786,0,1,0,0,3.571Zm0,9.821H30a1.786,1.786,0,1,0,0-3.571H16.607a1.786,1.786,0,1,0,0,3.571Zm0,9.821H30a1.786,1.786,0,0,0,0-3.571H16.607a1.786,1.786,0,1,0,0,3.571Z" transform="translate(-5 -8)" fill="#fff" />
7998 </svg>
7999 </div>
8000 <div class="custom__header__icon__text">
8001 <div>
8002 <div class="custom__header__icon__text">
8003 @Translate("Smartpage:Header.ChainOrdersText.ChainOrders", "Rammeordrer")
8004 </div>
8005 </div>
8006 </div>
8007 </a>
8008 </div>
8009 </div>
8010 </li>
8011 }
8012
8013
8014 @helper RenderDesktopTools()
8015 {
8016 if (Model.ID != GetPageIdByNavigationTag("CartPage") && Model.ID != GetPageIdByNavigationTag("CheckoutPage"))
8017 {
8018 List<Block> subBlocks = headerBlocksPage.GetBlockListById("MasterDesktopTools").OrderBy(item => item.SortId).ToList();
8019
8020 <div class="tools-navigation dw-mod">
8021 <div class="center-container grid top-container__center-container dw-mod">
8022 @RenderBlockList(subBlocks)
8023 </div>
8024 </div>
8025 }
8026 }
8027
8028 @helper RenderDesktopToolsText()
8029 {
8030 string toolsText = Model.Area.Item.GetItem("Layout").GetItem("Header").GetString("ToolsText");
8031 if (!string.IsNullOrEmpty(toolsText))
8032 {
8033 <div class="u-margin-top u-margin-bottom">@toolsText</div>
8034 }
8035 }
8036
8037 @helper RenderDesktopToolsNavigation()
8038 {
8039 bool renderPagesInToolBar = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("RenderPagesInToolBar");
8040
8041 if (renderPagesInToolBar)
8042 {
8043 @RenderNavigation(new
8044 {
8045 id = "topToolsNavigation",
8046 cssclass = "menu menu-tools dw-mod dwnavigation",
8047 template = "TopMenu.xslt"
8048 })
8049 }
8050 }
8051
8052 @helper RenderDesktopNavigation()
8053 {
8054 List<Block> subBlocks = headerBlocksPage.GetBlockListById("MasterDesktopNavigation").OrderBy(item => item.SortId).ToList();
8055 string topLayout = Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("TopLayout") != null ? Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("TopLayout").SelectedValue : "normal";
8056 string alignClass = topLayout == "two-lines-centered" ? "grid--justify-center" : "";
8057 string menuType = Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("NavigationMegaMenu") != null ? Model.Area.Item.GetItem("Layout").GetItem("Header").GetRawValueString("NavigationMegaMenu") : "dropdown";
8058 bool isSidemenu = menuType == "sidemenu";
8059 if (isSidemenu)
8060 {
8061 <div class="sidemenu__modal-overlay js-sidemenu-overlay"></div>
8062 }
8063
8064 <nav class="main-navigation @(isSidemenu ? "sidemenu-navigation js-sidemenu-navigation" : "") js-main-navigation dw-mod">
8065 @if (isSidemenu)
8066 {
8067 <div class="navigation-header">
8068 <div class="navigation-header__previous js-navigation-previous">@RenderPreviousButton()</div>
8069 <div class="navigation-header__mid">
8070 <div class="js-navigation-logo">
8071 @RenderSidemenuLogo()
8072 </div>
8073 <h2 class="js-navigation-active-title"></h2>
8074 </div>
8075 <div class="navigation-header__close js-sidemenu-close">@RenderCloseButton()</div>
8076 </div>
8077 <div class="navigation-container js-navigation-container">
8078 @RenderBlockList(subBlocks)
8079 </div>
8080 <div class="sidemenu-sub-navigation js-sidemenu-sub-navigation">
8081 <div class="navigation-header">
8082 <h2 class="js-sub-navigation-title"></h2>
8083 <div class="navigation-header__close js-sidemenu-close">@RenderCloseButton()</div>
8084 </div>
8085 <div class="navigation-container js-navigation-container">
8086 <div class="js-sub-navigation-items"></div>
8087 </div>
8088 </div>
8089 }
8090 else
8091 {
8092 <div class="center-container top-container__center-container grid @alignClass dw-mod">
8093 @RenderBlockList(subBlocks)
8094 </div>
8095 }
8096 </nav>
8097 }
8098
8099 @helper RenderDesktopExtra()
8100 {
8101 List<Block> subBlocks = headerBlocksPage.GetBlockListById("MasterDesktopExtra").OrderBy(item => item.SortId).ToList();
8102 string menuType = Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("NavigationMegaMenu") != null ? Model.Area.Item.GetItem("Layout").GetItem("Header").GetRawValueString("NavigationMegaMenu") : "dropdown";
8103
8104 if (subBlocks.Count > 0)
8105 {
8106 <div class="header header-top dw-mod custom__header__top js-header-top @(Model.ID == GetPageIdByNavigationTag("CartPage") || Model.ID == GetPageIdByNavigationTag("CheckoutPage") ? "is-cart-page" : "")">
8107 <div class="center-container top-container__center-container grid--justify-space-between grid grid--align-center dw-mod">
8108 @RenderBlockList(subBlocks)
8109 </div>
8110 </div>
8111 }
8112 }
8113
8114 @{
8115 if (Pageview.Page.NavigationTag == "CartPage" && Pageview.Device.ToString() == "Tablet")
8116 {
8117 Block mobileCheckoutUsp = new Block
8118 {
8119 Id = "MobileCheckoutUsp",
8120 SortId = 50,
8121 Template = RenderMobileCheckoutUsp()
8122 };
8123 mobileHeaderBlocksPage.Add(MasterBlockId.MasterHeader, mobileCheckoutUsp);
8124 }
8125 }
8126
8127 @helper RenderPreviousButton()
8128 {
8129 <svg xmlns="http://www.w3.org/2000/svg" width="27.663" height="19.992" viewBox="0 0 27.663 19.992">
8130 <path id="Path_122" data-name="Path 122" d="M11.946,3.067a1.139,1.139,0,0,0-1.61,0L1.346,12.057a.949.949,0,0,0,0,1.344l8.991,8.991a1.139,1.139,0,0,0,1.611-1.611L5.034,13.868H27.592a1.139,1.139,0,1,0,0-2.278H5.034l6.914-6.912a1.139,1.139,0,0,0,0-1.611Z" transform="translate(-1.067 -2.734)" fill="#3b3d3e" fill-rule="evenodd" />
8131 </svg>
8132 }
8133
8134 @helper RenderSidemenuLogo()
8135 {
8136 <svg class="sidemenu-logo" xmlns="http://www.w3.org/2000/svg" width="299.404" height="61.255" viewBox="0 0 299.404 61.255">
8137 <g id="philipson-wine-logo-mobil" transform="translate(0 0)">
8138 <path id="Path_1" data-name="Path 1" d="M76.936,67.213c2.668-.339,3.176-.931,3.176-4.574V42.646c0-2.2-1.059-2.88-2.965-2.372v-.508L85.2,37.181V51.288c2.033-2.033,4.32-4.025,7.2-4.025,3.176,0,5.337,2.118,5.337,5.8v9.573c0,3.558.466,4.277,2.965,4.574v.339H89.515v-.339c2.711-.339,3.092-.974,3.092-4.574V53.955c0-2.584-.974-3.812-3.092-3.812-1.652,0-3.007.974-4.32,2.161V62.639c0,3.6.466,4.32,2.88,4.574v.339H76.936Z" transform="translate(-50.459 -24.385)" fill="#3b3d3e" />
8139 <path id="Path_2" data-name="Path 2" d="M150.708,67.539c2.753-.339,3.3-1.016,3.3-4.574V52.376c0-1.95-1.1-2.33-3.135-1.736v-.51l8.26-2.71V62.965c0,3.515.551,4.277,2.923,4.574v.339H150.708Zm2.8-27.066a2.844,2.844,0,0,1,3.008-2.8,2.8,2.8,0,1,1,0,5.591A2.871,2.871,0,0,1,153.5,40.473Z" transform="translate(-98.843 -24.711)" fill="#3b3d3e" />
8140 <path id="Path_3" data-name="Path 3" d="M190.266,67.213c2.711-.339,3.177-1.016,3.177-4.574V42.731c0-2.923-1.313-2.88-3.219-2.372v-.508l8.3-2.669V62.639c0,3.515.551,4.235,2.965,4.574v.339H190.266Z" transform="translate(-124.76 -24.385)" fill="#3b3d3e" />
8141 <path id="Path_4" data-name="Path 4" d="M230.106,67.539c2.753-.339,3.3-1.016,3.3-4.574V52.376c0-1.95-1.1-2.33-3.135-1.736v-.51l8.26-2.71V62.965c0,3.515.551,4.277,2.923,4.574v.339H230.106Zm2.8-27.066a2.844,2.844,0,0,1,3.008-2.8,2.8,2.8,0,1,1,0,5.591A2.871,2.871,0,0,1,232.9,40.473Z" transform="translate(-150.917 -24.711)" fill="#3b3d3e" />
8142 <path id="Path_5" data-name="Path 5" d="M265.189,96.478c2.8-.338,3.262-1.059,3.262-4.617V71.911c0-2.921-1.1-3.218-2.923-2.753V68.65l8.048-2.541V70.6c2.118-2.667,3.431-4.363,6.524-4.363,5.167,0,8.26,4.279,8.26,9.912,0,6.481-4.872,10.886-10.081,10.886-2.372,0-3.177-.762-4.7-2.076V91.9c.043,3.432.932,4.277,3.516,4.574v.339h-11.9Zm17.536-19.1c0-4.151-1.525-7.963-5-7.963-1.906,0-3.008,1.185-4.151,2.5v8.556c0,3.474,1.906,5.21,4.405,5.21,3.346,0,4.744-3.94,4.744-8.3Z" transform="translate(-173.926 -43.358)" fill="#3b3d3e" />
8143 <path id="Path_6" data-name="Path 6" d="M346.224,86.056a1.281,1.281,0,0,0-.677-.128.839.839,0,0,0-.889.679h-.424V79.66h.381c.551,3.43,3.262,6.31,6.4,6.31a2.973,2.973,0,0,0,3.219-3.007c0-1.821-1.185-2.627-4.7-4.32-4.024-1.864-5.633-3.177-5.633-6.438,0-3.56,3.007-5.973,6.777-5.973a9.222,9.222,0,0,1,4.024.931,1.442,1.442,0,0,0,.678.128.86.86,0,0,0,.762-.551h.423l.339,6.227h-.466c-.677-3.263-3.007-5.592-5.845-5.592-1.78,0-3.219.848-3.219,2.541,0,1.821,1.312,2.5,4.955,4.322,4.194,1.948,6.057,3.346,6.057,6.65,0,4.023-3.685,6.227-7.328,6.227A13.456,13.456,0,0,1,346.224,86.056Z" transform="translate(-225.547 -43.439)" fill="#3b3d3e" />
8144 <path id="Path_7" data-name="Path 7" d="M394.115,76.938a10.314,10.314,0,0,1,10.632-10.463c5.973,0,10.631,4.109,10.631,10.335a10.338,10.338,0,0,1-10.631,10.463C398.774,87.274,394.115,83.123,394.115,76.938Zm15.673,1.4c0-4.574-1.652-10.673-5.761-10.673-2.922,0-4.32,3.43-4.32,7.709,0,4.617,1.652,10.716,5.76,10.716,2.923,0,4.321-3.515,4.321-7.751Z" transform="translate(-258.483 -43.598)" fill="#3b3d3e" />
8145 <path id="Path_8" data-name="Path 8" d="M460.1,86.186c2.753-.339,3.176-1.1,3.176-4.574V71.53c0-2.838-1.059-2.88-3.008-2.33v-.508l8.133-2.584V70.26c2.076-2.033,4.321-4.025,7.2-4.025,3.219,0,5.336,2.118,5.336,5.8v9.573c0,3.558.466,4.277,3.008,4.574v.339H472.763v-.339c2.668-.339,3.049-.974,3.049-4.574V72.927c0-2.584-.974-3.812-3.092-3.812-1.652,0-3.008.974-4.321,2.161V81.612c0,3.515.467,4.277,2.88,4.574v.339H460.1Z" transform="translate(-301.759 -43.358)" fill="#3b3d3e" />
8146 <path id="Path_9" data-name="Path 9" d="M40.509,85.5a9.615,9.615,0,0,1-2.125.487.61.61,0,0,0,.139.01,5.79,5.79,0,0,0,3.456-1.162A7.613,7.613,0,0,1,40.509,85.5Z" transform="translate(-25.174 -55.64)" fill="#3b3d3e" />
8147 <path id="Path_10" data-name="Path 10" d="M23.817,45.21a8.136,8.136,0,0,0-2.94-2.731,10.692,10.692,0,0,0-3.853-1.347,36.6,36.6,0,0,0-4.7-.268H0v.423c.328.04.56.069.9.119s.685.139,1,.2c1.6.407,1.986,1.261,1.986,4.092V65.053c0,3.774-.675,4.152-3.854,4.579v.338H13.924v-.407a5.839,5.839,0,0,1-2.572-.6,3.325,3.325,0,0,1-1.241-1.053,2.923,2.923,0,0,1-.447-1.52c-.02-.616-.05-1.361-.079-2.215,0-.457,0-.874-.02-1.261s-.02-.814-.02-1.271V57.873h2.175c.824,0,1.678-.04,2.552-.1S16,57.6,16.864,57.466a13.006,13.006,0,0,0,2.413-.6A11.224,11.224,0,0,0,21.4,55.8a7.662,7.662,0,0,0,3.1-3.715,7.255,7.255,0,0,0,.477-2.692A7.446,7.446,0,0,0,23.817,45.21Zm-4.539,8.542A7.075,7.075,0,0,1,16.8,56a5.79,5.79,0,0,1-3.456,1.162.61.61,0,0,1-.139-.01,5.475,5.475,0,0,1-.566.06c-.963.07-2,.1-3.1.1V52.162c0-1.281.01-2.592.02-3.933,0-.159,0-.318.01-.477V42.12c.055-.028.113-.069.172-.1a1.338,1.338,0,0,1,.215-.073c3.248-.717,7.6.2,9.495,3.1a7.408,7.408,0,0,1,1.182,4.142,8.017,8.017,0,0,1-1.361,4.559Z" transform="translate(0 -26.8)" fill="#3b3d3e" />
8148 <path id="Path_11" data-name="Path 11" d="M723.748,37.943s-1.373,1.04-2.23.735a4.114,4.114,0,0,0-2.712.511c-1.068.546-1.569.953-2.212,1.22a8.238,8.238,0,0,1-1.575.223s.306-.115.346-.336a1.225,1.225,0,0,1,.256-.466,8.021,8.021,0,0,0-1.981-.076,2.99,2.99,0,0,1-2.262.215.777.777,0,0,0,.411-.381c.105-.266.381-.842.381-.842-.406-.587-1.544-.281-2.276-.642a.76.76,0,0,0,.517-.647,3.83,3.83,0,0,0-1.394-.482c-.727-.075-1.424-.943-1.71-.938a.777.777,0,0,0,.411-.381,5.369,5.369,0,0,1,1.515-1.434,3.136,3.136,0,0,0-.933-.512c-.486-.146-.712-.471-1-.467a1.575,1.575,0,0,0,.522-.361,1.548,1.548,0,0,1,.411-.381,5.648,5.648,0,0,1-1.554-.853,1,1,0,0,0,.477-.426,1.508,1.508,0,0,1-1.008-1.038c-.346-.918-.652-.8-.652-.8a4.931,4.931,0,0,0,1.088-.657,3.019,3.019,0,0,1,.893-.521s-.812-1.174-.988-1.149a4.205,4.205,0,0,0,.852-.3c.2-.135-1.113-.772-1.429-1.229s-.9-1.3-1.078-1.279a2.756,2.756,0,0,0,1.133-.591,1.4,1.4,0,0,1,1.093-.371,1.849,1.849,0,0,0-.561-.672c-.311-.171-.255-.787-.456-.938a1.336,1.336,0,0,0,.7-.1c.371-.16.742-.321.9-.235a1.372,1.372,0,0,0-.251-.5c-.226-.326-.1-.7-.321-.742a1.1,1.1,0,0,0,.547-.185l.261-.18a3.462,3.462,0,0,1-.035-2,.791.791,0,0,0-.125-.878,1.451,1.451,0,0,0,.817.206,10.257,10.257,0,0,1,2.888.412,1.989,1.989,0,0,1-.035-.747,1.011,1.011,0,0,0-.01-.572s.6.451.8.316l-.361-.522c-.045-.065.742-.321.918-.346a1.1,1.1,0,0,1-.125-.878.9.9,0,0,0-.035-.747,2.169,2.169,0,0,0,.506.035c.176-.025.547-.185.7-.1a1.355,1.355,0,0,1-.215-1.008c.146-.486.186-.707.1-.837a2.55,2.55,0,0,0,1.013.07,7.275,7.275,0,0,0,.482-1.394c0-.286.617-1.2.547-1.439,0,0,1.454,1.4,2.025,1.395,0,0,.356-1.018.266-1.148a6.343,6.343,0,0,1,2.056.6s-.336-.346-.3-.567-.316-.456-.316-.456l.722-.21a4.1,4.1,0,0,1,.442-2.427.975.975,0,0,0-.1-.416,2.393,2.393,0,0,0,.953.4,1.767,1.767,0,0,1,.707.186,1.784,1.784,0,0,1,.291-.973,4.279,4.279,0,0,0,.672-1.815s.541.782,1.243.682a3.661,3.661,0,0,0,.462-1.284s.205.436.491.431A7.336,7.336,0,0,0,726.508.384,1.362,1.362,0,0,0,727,.815a13.146,13.146,0,0,1,1.509,2.041c.226.326,1.509.788,1.985,1.615,0,0,.04-.221.411-.381s.346-.336.346-.336a2.456,2.456,0,0,0,.321.742,1.988,1.988,0,0,1,.441,1.334,1.914,1.914,0,0,1,.772,1.394.926.926,0,0,1,.587-.406,1.092,1.092,0,0,0,.717-.5,10.167,10.167,0,0,1,.265,1.359,6.652,6.652,0,0,0,.075,1.78l.366-.446a1.849,1.849,0,0,0,.406,1.84,7.759,7.759,0,0,1,1.013-1.183c.326-.226.762-.431.933-.742a1.382,1.382,0,0,0,.341.632,2.554,2.554,0,0,0,.4.3s.406-.667.757-.717c0,0,.18.261.246.216A3.522,3.522,0,0,1,740.7,8.5c.351-.05.431-.491.431-.491a3.231,3.231,0,0,0,.486,1.4,4.558,4.558,0,0,1,.556,1.64,4.857,4.857,0,0,1,1.219-.747,1.62,1.62,0,0,0,.893-.521,1.411,1.411,0,0,0,.3.853,1.412,1.412,0,0,1,.3.853s.186-.707.557-.867a1.343,1.343,0,0,0,.522-.361s-.015.4.14.481.14.481.14.481a2.3,2.3,0,0,1,1.665-.381.982.982,0,0,0,.7-.1,2.565,2.565,0,0,0-.176,1.279,3,3,0,0,1,.02,1.143,6.838,6.838,0,0,0,1.154-.7.836.836,0,0,0,.035.747,2.191,2.191,0,0,1,.3.567,5.011,5.011,0,0,1,1.62-.446,1.339,1.339,0,0,0,.592-.12,5.5,5.5,0,0,0-.176,1.279c.05.351.075.527-.01.682s.918-.346.918-.346l.07.241a1.542,1.542,0,0,1,.7-.386c.351-.05.837.1,1.183-.24,0,0-.341.622-.161.882s1.63.126,1.87.056.983-.391,1.289-.506a2.092,2.092,0,0,1,.857-.015,12.5,12.5,0,0,1-1.124,2.417,5.113,5.113,0,0,0-.6.8,1.106,1.106,0,0,1,.506.035,2.441,2.441,0,0,0-.943,1.424.512.512,0,0,1,.461-.03c.266.105.426.476.667.406,0,0-.527.075-.652.451a2.645,2.645,0,0,1-.878,1.379s.351-.05.667.406c.135.2.506.035.506.035a4.343,4.343,0,0,1-.6.8,4.929,4.929,0,0,0-.517.647.412.412,0,0,1,.446.366.963.963,0,0,1-.517.647.63.63,0,0,1,.577.276c.226.326.361.522.536.5a3.894,3.894,0,0,0-.471.712,4.628,4.628,0,0,1-.993,1.073.619.619,0,0,1,.226.326c.025.176.05.351.16.371s-.286,0-.547.185a3,3,0,0,0-.477.426,1.133,1.133,0,0,1,.511.321,2.252,2.252,0,0,0,1.329.527,1.213,1.213,0,0,0-.562.582,9.586,9.586,0,0,1-1.535,1.544s1.715,1.224,2.086,1.063a3.572,3.572,0,0,0-.823.762,8.241,8.241,0,0,1-1.234,1.143.694.694,0,0,1,.4.3.875.875,0,0,0,.511.321s-.085.155-.632.341a2.265,2.265,0,0,0-.913.632s.577.276.817.206.772.141.752.251a.507.507,0,0,0-.522.361,1.177,1.177,0,0,1,.642.231c.246.216,1.314.923,1.73.828a.738.738,0,0,1-.391.271c-.306.115-.166.6-.471.712a2.592,2.592,0,0,1,.953.4c.4.3.627.627,1,.467,0,0-.436.205-.5.536s-.281.291-.281.291a1.659,1.659,0,0,1,.8.6c.316.456,1.524.392,2.061.888s.646.517.822.492a3.363,3.363,0,0,1-1.434.993c-1.595.621-1.364,1.233-1.715,1.283a.344.344,0,0,1,.311.171.606.606,0,0,0,.356.236,2.4,2.4,0,0,0-.722.21,5.168,5.168,0,0,1-1.179.526.582.582,0,0,1,.205.436c.005.286.562.672.562.672a4.112,4.112,0,0,0-1.008.215c-.371.16-1.224.461-1.424.311a.412.412,0,0,1,.16.371.945.945,0,0,0,.14.481s-.18-.261-.356-.236a2.169,2.169,0,0,1-.506-.035,3.207,3.207,0,0,0,.346.918c.3.567-.015.4.256.787a6.451,6.451,0,0,0-1.143.02,3.007,3.007,0,0,1-1.715.03s.18.261.03.461a.932.932,0,0,0-.055.617,1.5,1.5,0,0,0-.572.01,1.613,1.613,0,0,1-.857.015,1.724,1.724,0,0,1,.3.853c-.015.4.286,1.249.506,1.289a2.993,2.993,0,0,0-.747.035c-.241.07-.862-.271-1.083-.311s-1.163.13-1.254,0c0,0-.236.356-.166.6a1.1,1.1,0,0,0-.642-.231,1.767,1.767,0,0,1-.707-.186.83.83,0,0,1-.186.707.591.591,0,0,0-.166.6s-.271-.391-.557-.386a1.622,1.622,0,0,1-.908-.336c-.09-.13-.08.441-.08.441a.707.707,0,0,0-.557-.386,6.055,6.055,0,0,1-.076,1.013,1.213,1.213,0,0,0,.175.943,3.54,3.54,0,0,1,.175,1.229,1.419,1.419,0,0,0-.6-.166c-.286,0-1.72-.256-1.72-.256a1.5,1.5,0,0,1-.531-.211s.2.15.03.461-.08.441-.08.441-.381-.411-.667-.406a.943.943,0,0,1-.757-.537s.185.547-.01.682-.211.531-.211.531a4,4,0,0,0-1-.752,4.847,4.847,0,0,1-.978-.577,2.332,2.332,0,0,1-.161.882c-.15.2-.075.727-.075.727a1.6,1.6,0,0,0-1.2-.617,1.174,1.174,0,0,1-1.043-.532l-.015.4s-.687-.3-.712-.471a1.737,1.737,0,0,0-.075.727c.01.572-.512.933-.507,1.218,0,0,.015-.4-.316-.456l-.331-.06h0a2.633,2.633,0,0,1-.221,1.213,4.168,4.168,0,0,0-.311,2.337.981.981,0,0,0-.973-.291c-.7.1-1.419-.657-1.419-.657s-.216.246-.125.376a1.484,1.484,0,0,1-.667-.406,1.935,1.935,0,0,0-.381-.411,2.487,2.487,0,0,1-.737.607.293.293,0,0,0-.105.266s-.16-.371-.381-.411a1.478,1.478,0,0,1-.9-1.018.908.908,0,0,1-.391.271.619.619,0,0,0-.326.226s.06-.331-.14-.481a.837.837,0,0,1-.271-.391,1.579,1.579,0,0,1-.863.983c-.436.205-.411.381-.411.381a1.791,1.791,0,0,0-.431-.762,3.867,3.867,0,0,1-.777-1.68s-.236.356-.567.3a.447.447,0,0,0-.391.271.63.63,0,0,0-.055-.637,2.433,2.433,0,0,1-.391-.983,1.381,1.381,0,0,0-.632.341,2.353,2.353,0,0,1-1.088.657l-.2.135h0a1.132,1.132,0,0,0-.12-.592,4.649,4.649,0,0,1-.3-1.82l-.527.075a.613.613,0,0,0-.241.07s.191-.421.1-.552a1.476,1.476,0,0,1,.091-1.123,1.632,1.632,0,0,1-.812.08.617.617,0,0,0-.526.075,1.411,1.411,0,0,0,.005-.968,1.862,1.862,0,0,1-.04-1.033,4.477,4.477,0,0,0-1.4.2c-.7.386-1.1.085-1.62.446a1.081,1.081,0,0,0-.075-.527,2.97,2.97,0,0,1,.2-1.389,3.8,3.8,0,0,0,.025-1.078,1.111,1.111,0,0,0-.637.055c-.2.135.159-.56.521-.826s.268-.844.736-1.072a1.853,1.853,0,0,1-.687-.087c-.405-.121-.54.149-.54.149a5.8,5.8,0,0,1,1.088-1.331,4.112,4.112,0,0,0,.85-.861,3.685,3.685,0,0,0-.722.21,2.741,2.741,0,0,1,.762-.9c.646-.576.576-.816.576-.816s-.312.2-.523.057a.8.8,0,0,0-.431-.135s1.35-2.1,2.521-2.407c.564-.15,2.378-.1,3.051-1.825.416-1.067.4-1.675,1.188-2.092Z" transform="translate(-462.274 -0.252)" fill="#5a9b84" />
8149 <path id="Path_12" data-name="Path 12" d="M740.031,82.449l-.1-6.922.324-3.711-.044-.227-3.251-1.7a11.665,11.665,0,0,0-2.289-1.984,12.315,12.315,0,0,1-3.242-2.642c-.988-1.149-1.184-1.27-1.4-1.537a7.5,7.5,0,0,1-1.136-1.271c-.37-.628-.711-.424-1.475-1.389s-2.15-2.851-2.15-2.851,2.482,2.8,3.145,3.384,2.436,2.685,2.688,2.816,1.466,1.492,3.036,2.623,2.85,2.238,3.214,2.485,2.9,1.467,2.9,1.467-.711-8.715-.234-12.066-.049-2.6.287-4.184l-.142,6s.016,5.179.179,5.693S740.53,71,740.53,71s3.613-2.628,4.587-3.287,3.672-2.171,4.026-2.5,2.667-1.765,3.132-2.022,4.858-3.1,5.217-3.3-5.742,3.893-5.742,3.893l-4.292,2.809s-2.931,1.964-3.073,2.062l-3.611,2.515c-.1.068-.151.2.105.361s2.995,1.913,3.367,2.057,5.15,2.543,5.15,2.543-3.823-1.693-4.236-1.825a9.566,9.566,0,0,1-1.208-.514c-.226-.117-2.144-1.264-2.144-1.264a11.134,11.134,0,0,0-1.259-.752c-.021.063-.152,1.824-.179,2.389a11.431,11.431,0,0,0-.145,3.041A35.347,35.347,0,0,1,740.031,82.449Z" transform="translate(-475.674 -35.9)" fill="#77ac9a" />
8150 <path id="Path_13" data-name="Path 13" d="M747.7,114.975a18.044,18.044,0,0,1-2.714,3.291,34.237,34.237,0,0,0-2.867,3.094q-1.369,1.616-2.663,3.293c-.431.558-.849,1.127-1.258,1.7a20.682,20.682,0,0,0-1.242,1.715,20.852,20.852,0,0,1,1.04-1.858c.412-.577.831-1.148,1.264-1.709q1.294-1.685,2.671-3.3a34.344,34.344,0,0,1,2.9-3.123,17.852,17.852,0,0,0,2.667-3.239l0,0a.124.124,0,0,1,.2.14Z" transform="translate(-483.341 -75.279)" fill="#77ac9a" />
8151 <path id="Path_14" data-name="Path 14" d="M747.266,124.114l-3.516.681c-.574.109-1.2.21-1.774.26a5.872,5.872,0,0,0-.856.184,3.2,3.2,0,0,0-.85.243,2.777,2.777,0,0,1,.779-.48,6.16,6.16,0,0,1,.892-.192c.616-.055,1.167-.147,1.765-.258l3.511-.681a.124.124,0,0,1,.051.242Z" transform="translate(-485.512 -81.241)" fill="#77ac9a" />
8152 <path id="Path_15" data-name="Path 15" d="M768.036,134.965a40.908,40.908,0,0,1,1.258,3.941,7.883,7.883,0,0,0,.783,1.874l1.047,1.779,1.047,1.779c.321.609.622,1.222.965,1.815s.7,1.179,1.068,1.755c.331.6.7,1.187.986,1.816-.357-.588-.791-1.122-1.194-1.682-.374-.579-.735-1.166-1.075-1.767s-.651-1.218-.971-1.825l-1.045-1.775-1.045-1.775a8.127,8.127,0,0,1-.8-1.918c-.451-1.305-.678-2.684-1.245-3.908l0-.006a.124.124,0,1,1,.224-.1Z" transform="translate(-503.567 -88.471)" fill="#77ac9a" />
8153 <path id="Path_16" data-name="Path 16" d="M752.621,146.4a7.7,7.7,0,0,0,.582-1.46l.578-1.466,1.107-2.957c.2-.5.344-.971.606-1.493a7.074,7.074,0,0,0,.769-1.345,9.992,9.992,0,0,1,1.609-2.736.124.124,0,1,1,.2.147l0,0a9.732,9.732,0,0,0-1.578,2.684,7.329,7.329,0,0,1-.8,1.392c-.206.421-.39.955-.575,1.435l-1.108,2.959-.581,1.472A7.778,7.778,0,0,1,752.621,146.4Z" transform="translate(-493.612 -88.472)" fill="#77ac9a" />
8154 <path id="Path_17" data-name="Path 17" d="M777.165,161.344a2.551,2.551,0,0,0-.627,1.1c-.137.412-.174.87-.313,1.317a3.3,3.3,0,0,0-.231,1.29c.006.221.022.444.045.667L776,166.4c-.078-.218-.139-.439-.2-.661-.023-.227-.04-.456-.046-.687a3.555,3.555,0,0,1,.241-1.364c.132-.417.168-.872.315-1.322a2.725,2.725,0,0,1,.716-1.223.123.123,0,1,1,.165.182h0Z" transform="translate(-508.779 -105.666)" fill="#77ac9a" />
8155 <path id="Path_18" data-name="Path 18" d="M768.406,150.479a8.548,8.548,0,0,0-.87,1.982l-.66,2.109c-.223.7-.425,1.426-.627,2.128-.1.355-.184.711-.254,1.07a8.043,8.043,0,0,0-.256,1.077,6.163,6.163,0,0,1,.013-1.124c.071-.367.16-.729.258-1.088.207-.72.4-1.418.627-2.128l.665-2.125a8.476,8.476,0,0,1,.917-2.063.123.123,0,0,1,.2.136Z" transform="translate(-502.203 -98.55)" fill="#77ac9a" />
8156 <path id="Path_19" data-name="Path 19" d="M795.156,116.774c.069-.076.018-.023.039,0a.539.539,0,0,0,.034.1,1.765,1.765,0,0,0,.123.216,4.715,4.715,0,0,0,.318.417l.7.811q.713.8,1.469,1.565a17.756,17.756,0,0,0,3.28,2.723l.01.007c.827.572,1.711,1.088,2.581,1.614l2.62,1.573c.87.532,1.739,1.063,2.58,1.652a6.221,6.221,0,0,1,1.136,1.037,4.446,4.446,0,0,0,1.21.906,4.515,4.515,0,0,1-1.307-.8c-.2-.157-.387-.352-.578-.5s-.4-.3-.6-.446c-.828-.58-1.7-1.112-2.565-1.642l-2.618-1.572c-.872-.528-1.75-1.039-2.6-1.626l.01.007a17.977,17.977,0,0,1-3.331-2.762q-.76-.768-1.478-1.575l-.706-.818a4.906,4.906,0,0,1-.334-.439,2,2,0,0,1-.142-.251.765.765,0,0,1-.051-.154c.006-.064-.06-.116.076-.257a.124.124,0,0,1,.128.212Z" transform="translate(-521.368 -76.438)" fill="#77ac9a" />
8157 <path id="Path_20" data-name="Path 20" d="M820.818,118.753a9.418,9.418,0,0,1-1.607.231l-1.62.133-3.246.085c-1.082.019-2.165.036-3.247.031-.543,0-1.071.015-1.616.052-.547.021-1.084.021-1.632.01a41.652,41.652,0,0,1-6.424-1l-6.32-1.51a.124.124,0,1,1,.058-.241h0l6.3,1.506a41.5,41.5,0,0,0,6.385,1c.534.011,1.079.011,1.613-.01.534-.037,1.088-.054,1.627-.052,1.082,0,2.161-.012,3.243-.031l3.242-.085,1.622-.009A9.359,9.359,0,0,0,820.818,118.753Z" transform="translate(-521.415 -76.431)" fill="#77ac9a" />
8158 <path id="Path_21" data-name="Path 21" d="M846.918,123.678a2.873,2.873,0,0,0,1.081.913,14.261,14.261,0,0,0,1.371.6c.467.185.934.368,1.408.52a6.6,6.6,0,0,0,.716.192,2.352,2.352,0,0,0,.725.166,2.06,2.06,0,0,1-.774.077,6.708,6.708,0,0,1-.742-.2c-.485-.155-.956-.339-1.425-.525a14.37,14.37,0,0,1-1.4-.609,3.028,3.028,0,0,1-1.187-1.027.123.123,0,0,1,.21-.128h0Z" transform="translate(-555.298 -81.061)" fill="#77ac9a" />
8159 <path id="Path_22" data-name="Path 22" d="M833.111,123.882a8.446,8.446,0,0,0,1.982,1.438c.732.392,1.49.746,2.251,1.086s1.534.659,2.315.948c.391.143.784.281,1.182.395a3.5,3.5,0,0,0,1.2.311,3.245,3.245,0,0,1-1.266-.073c-.407-.117-.8-.256-1.2-.4-.788-.293-1.563-.615-2.33-.954s-1.526-.7-2.269-1.1a8.495,8.495,0,0,1-2.06-1.506.123.123,0,1,1,.18-.168Z" transform="translate(-546.251 -81.211)" fill="#77ac9a" />
8160 <path id="Path_23" data-name="Path 23" d="M814.65,121.22a17.748,17.748,0,0,0,2.708,2.674,16.817,16.817,0,0,0,3.258,1.969,24.505,24.505,0,0,0,3.555,1.413,16.173,16.173,0,0,1,1.784.751,10.161,10.161,0,0,1,1.587,1.1,10.018,10.018,0,0,0-1.7-.882,15.949,15.949,0,0,0-1.756-.739,24.768,24.768,0,0,1-3.58-1.424,17.031,17.031,0,0,1-3.305-2,17.971,17.971,0,0,1-2.75-2.718.124.124,0,1,1,.193-.155h0Z" transform="translate(-534.147 -79.469)" fill="#77ac9a" />
8161 <path id="Path_24" data-name="Path 24" d="M780.794,110.492a9.845,9.845,0,0,0,.614,2.9,21.422,21.422,0,0,0,1.2,2.75,18.733,18.733,0,0,0,1.554,2.563,21.386,21.386,0,0,0,1.962,2.27c1.394,1.444,2.877,2.809,4.385,4.135a8.32,8.32,0,0,0,1.2.89c.419.282.836.568,1.239.875a10.136,10.136,0,0,1,2.094,2.184,10.022,10.022,0,0,0-2.243-1.986q-.6-.449-1.228-.867l-.63-.422c-.215-.155-.4-.322-.592-.486-1.515-1.333-3-2.7-4.4-4.151a21.622,21.622,0,0,1-1.984-2.3,18.961,18.961,0,0,1-1.574-2.6,21.689,21.689,0,0,1-1.214-2.781,10,10,0,0,1-.627-2.989.123.123,0,1,1,.247-.005Z" transform="translate(-511.928 -72.376)" fill="#77ac9a" />
8162 <path id="Path_25" data-name="Path 25" d="M789.294,89c1.863.606,3.684,1.306,5.569,1.787.942.244,1.891.464,2.849.617a21.037,21.037,0,0,0,2.9.212,36.5,36.5,0,0,0,5.832-.107c.967-.1,1.929-.253,2.887-.428.967-.128,1.927-.313,2.9-.427-.957.194-1.9.46-2.855.67-.962.176-1.931.327-2.906.431a36.666,36.666,0,0,1-5.869.109,21.269,21.269,0,0,1-2.933-.214c-.97-.155-1.925-.377-2.873-.622-1.9-.486-3.734-1.19-5.583-1.791a.124.124,0,1,1,.077-.235Z" transform="translate(-517.558 -58.368)" fill="#77ac9a" />
8163 <path id="Path_26" data-name="Path 26" d="M807.147,74.509l4.306.233a36.575,36.575,0,0,0,4.3-.176,31.716,31.716,0,0,0,4.24-.712,14.45,14.45,0,0,1,2.137-.4,5.524,5.524,0,0,0,2.105-.351,5.623,5.623,0,0,1-2.079.6,14.136,14.136,0,0,0-2.1.4,31.943,31.943,0,0,1-4.274.718,36.767,36.767,0,0,1-4.328.177l-4.322-.234a.124.124,0,1,1,.013-.247Z" transform="translate(-529.284 -47.943)" fill="#77ac9a" />
8164 <path id="Path_27" data-name="Path 27" d="M818.6,51.7l3.771-2.147c1.276-.683,2.463-1.517,3.684-2.294s2.4-1.606,3.606-2.407c1.224-.763,2.321-1.728,3.6-2.439a16.651,16.651,0,0,0-1.662,1.393c-.561.458-1.193.826-1.786,1.243-1.208.8-2.4,1.637-3.621,2.417s-2.41,1.612-3.69,2.3l-3.78,2.152a.124.124,0,1,1-.122-.215Z" transform="translate(-536.844 -27.818)" fill="#77ac9a" />
8165 <path id="Path_28" data-name="Path 28" d="M838.226,57.368a5.528,5.528,0,0,0,1.648.443,7.512,7.512,0,0,0,1.725,0,8.617,8.617,0,0,0,1.689-.376c.274-.094.54-.2.832-.293a3.83,3.83,0,0,1,.9-.055,4.9,4.9,0,0,0-.824.291c-.267.085-.546.195-.827.291a8.873,8.873,0,0,1-1.738.387,7.763,7.763,0,0,1-1.784,0,5.726,5.726,0,0,1-1.733-.469.123.123,0,1,1,.1-.224h0Z" transform="translate(-549.635 -37.439)" fill="#77ac9a" />
8166 <path id="Path_29" data-name="Path 29" d="M839.631,46.669a6.875,6.875,0,0,1,.962-2.538,5.145,5.145,0,0,1,.91-1.012,5.28,5.28,0,0,0,.443-.48,1.862,1.862,0,0,0,.177-.257.59.59,0,0,0,.052-.125c.023-.034-.022-.079.033-.023l-.021-.194a4.075,4.075,0,0,1,.5-.446c.183-.131.364-.265.552-.39-.133.183-.275.357-.414.535a4.106,4.106,0,0,1-.467.48l-.021-.194a.26.26,0,0,1,.078.292.83.83,0,0,1-.074.184,2.081,2.081,0,0,1-.2.294,5.544,5.544,0,0,1-.464.5,4.882,4.882,0,0,0-.876.972,6.646,6.646,0,0,0-.923,2.437v.008a.124.124,0,0,1-.243-.044Z" transform="translate(-550.677 -27.023)" fill="#77ac9a" />
8167 <path id="Path_30" data-name="Path 30" d="M830.4,46.345a31.818,31.818,0,0,1,1.5-4.632,18.628,18.628,0,0,1,1.066-2.194,10.881,10.881,0,0,1,.663-1.03,7.674,7.674,0,0,1,.876-.858,10.205,10.205,0,0,0-.676,1,10.625,10.625,0,0,0-.649,1.008,18.386,18.386,0,0,0-1.052,2.166,31.572,31.572,0,0,0-1.484,4.591v0a.124.124,0,0,1-.24-.059Z" transform="translate(-544.619 -24.68)" fill="#77ac9a" />
8168 <path id="Path_31" data-name="Path 31" d="M827.407,63.97a19.83,19.83,0,0,0,2.534.48,11.834,11.834,0,0,0,2.567.065c.863-.073,1.725-.146,2.58-.255.427-.056.854-.119,1.271-.21a2.971,2.971,0,0,0,1.224-.349,2.83,2.83,0,0,1-1.172.59c-.429.093-.861.157-1.292.214-.863.11-1.728.183-2.591.256a12.091,12.091,0,0,1-2.618-.065,20.068,20.068,0,0,1-2.569-.487.124.124,0,0,1,.062-.24Z" transform="translate(-542.558 -41.779)" fill="#77ac9a" />
8169 <path id="Path_32" data-name="Path 32" d="M807.573,46.313a35.731,35.731,0,0,1,1.241-4.381,28.328,28.328,0,0,1,1.859-4.155c.709-1.339,1.449-2.664,2.291-3.931.827-1.338,2.126-2.167,3.027-3.387a12.233,12.233,0,0,1-1.364,1.819l-.788.819a7.593,7.593,0,0,0-.669.887c-.833,1.253-1.571,2.574-2.277,3.908a28.055,28.055,0,0,0-1.845,4.122,35.536,35.536,0,0,0-1.231,4.347v0a.124.124,0,1,1-.242-.052Z" transform="translate(-529.651 -19.977)" fill="#77ac9a" />
8170 <path id="Path_33" data-name="Path 33" d="M788.989,45.215a21.088,21.088,0,0,0,.428-2.962,20.244,20.244,0,0,1,.277-3.011,40.473,40.473,0,0,1,1.318-5.9,48.144,48.144,0,0,1,2.329-5.577c.443-.9.9-1.8,1.428-2.668a11.827,11.827,0,0,0,1.552-2.57,11.92,11.92,0,0,1-1.341,2.7c-.52.85-.975,1.747-1.415,2.646a47.945,47.945,0,0,0-2.315,5.543,40.245,40.245,0,0,0-1.31,5.86,19.991,19.991,0,0,0-.275,2.987,21.331,21.331,0,0,1-.434,3,.124.124,0,1,1-.242-.05Z" transform="translate(-517.462 -14.775)" fill="#77ac9a" />
8171 <path id="Path_34" data-name="Path 34" d="M768.072,19.083l.251-4.693c.1-1.565.136-3.126.158-4.692s.006-3.13-.07-4.691c-.037-.78-.093-1.56-.189-2.332A7.67,7.67,0,0,0,767.8.384a7.774,7.774,0,0,1,.665,2.261c.1.782.153,1.566.19,2.35.077,1.569.087,3.138.071,4.706s-.062,3.138-.159,4.7l-.251,4.693a.124.124,0,1,1-.247-.013Z" transform="translate(-503.569 -0.252)" fill="#77ac9a" />
8172 <path id="Path_35" data-name="Path 35" d="M762.081,16.89l-2.428-2.932a11.105,11.105,0,0,1-1.02-1.627q-.222-.425-.413-.866a5.723,5.723,0,0,1-.211-.941,8.154,8.154,0,0,0,.438.843q.186.432.4.85a10.88,10.88,0,0,0,1,1.59l2.422,2.925a.124.124,0,0,1-.189.159Z" transform="translate(-497.146 -6.902)" fill="#77ac9a" />
8173 <path id="Path_36" data-name="Path 36" d="M756.863,26.857a23.117,23.117,0,0,1-3.781-4.625,21.87,21.87,0,0,1-1.5-2.594l-.29-.685-.339-.659-.569-1.378.792,1.27.342.665.291.685a21.7,21.7,0,0,0,1.477,2.56,22.889,22.889,0,0,0,3.734,4.571l.006.005a.124.124,0,0,1-.167.182Z" transform="translate(-492.147 -11.095)" fill="#77ac9a" />
8174 <path id="Path_37" data-name="Path 37" d="M751.605,40.819a34.287,34.287,0,0,1-2.431-3.3c-.749-1.139-1.454-2.309-2.091-3.516a37.587,37.587,0,0,1-1.711-3.709,13.49,13.49,0,0,0-.984-1.763,4.506,4.506,0,0,0-1.3-1.522,4.618,4.618,0,0,1,1.509,1.384,13.725,13.725,0,0,1,1,1.8,37.414,37.414,0,0,0,1.705,3.7c.632,1.2,1.333,2.362,2.079,3.5a34.118,34.118,0,0,0,2.409,3.268l0,0a.124.124,0,0,1-.189.16Z" transform="translate(-487.358 -17.716)" fill="#77ac9a" />
8175 <path id="Path_38" data-name="Path 38" d="M747.181,47.516a40.23,40.23,0,0,1-4.232-4.383,26.8,26.8,0,0,1-1.775-2.481A24.032,24.032,0,0,1,739.666,38a34.742,34.742,0,0,1-2.03-5.744q-.4-1.469-.719-2.96l-.233-1.505a11.111,11.111,0,0,0-.258-1.494,11.106,11.106,0,0,1,.38,1.471l.353,1.476q.315,1.483.715,2.945a34.5,34.5,0,0,0,2.014,5.7,23.794,23.794,0,0,0,1.494,2.626,26.555,26.555,0,0,0,1.759,2.459,40.016,40.016,0,0,0,4.2,4.353.124.124,0,0,1-.161.188Z" transform="translate(-482.991 -17.246)" fill="#77ac9a" />
8176 <path id="Path_39" data-name="Path 39" d="M714.161,63.262c-.49-.057-.983-.107-1.474-.147a12.509,12.509,0,0,0-1.47-.057,6.532,6.532,0,0,1-1.5-.17,6.727,6.727,0,0,1-.729-.2,2.624,2.624,0,0,1-.629-.434,3.255,3.255,0,0,0,.71.2,6.517,6.517,0,0,0,.7.2,6.329,6.329,0,0,0,1.442.164,12.713,12.713,0,0,1,1.5.058c.5.041.989.091,1.483.148a.124.124,0,0,1-.028.246Z" transform="translate(-464.579 -40.827)" fill="#77ac9a" />
8177 <path id="Path_40" data-name="Path 40" d="M713.224,48.234c.248.169.484.352.721.537.207.214.411.433.6.663a9.537,9.537,0,0,1,1.024,1.476c.3.516.541,1.064.834,1.567a5.569,5.569,0,0,0,1.037,1.37l.015.013a.123.123,0,0,1-.163.185h0a5.683,5.683,0,0,1-1.1-1.445c-.3-.521-.537-1.063-.834-1.568a9.271,9.271,0,0,0-1-1.439c-.187-.224-.387-.439-.592-.65Z" transform="translate(-467.773 -31.635)" fill="#77ac9a" />
8178 <path id="Path_41" data-name="Path 41" d="M713.849,70.752q-1.143.073-2.285.1a20.681,20.681,0,0,1-2.3-.044,14.12,14.12,0,0,1-2.249-.486l-1.1-.316a3.713,3.713,0,0,0-1.082-.319,3.314,3.314,0,0,1,1.149.081l1.1.316a13.887,13.887,0,0,0,2.207.478,20.513,20.513,0,0,0,2.265.042c.758-.019,1.518-.053,2.275-.1a.124.124,0,1,1,.018.247Z" transform="translate(-462.275 -45.694)" fill="#77ac9a" />
8179 <path id="Path_42" data-name="Path 42" d="M719.966,85.662c-.81.115-1.62.207-2.435.273a19.611,19.611,0,0,1-2.456.07c-1.636-.1-3.249-.331-4.862-.573l-.013,0c-.571-.148-1.144-.295-1.72-.421l-.853-.241a3.385,3.385,0,0,0-.867-.156,3.43,3.43,0,0,1,.892.026c.3.036.593.068.884.125.578.136,1.154.276,1.728.428l-.012,0c1.605.242,3.222.47,4.836.571a19.5,19.5,0,0,0,2.423-.07c.808-.066,1.617-.157,2.418-.271a.124.124,0,1,1,.038.244Z" transform="translate(-463.534 -55.481)" fill="#77ac9a" />
8180 <path id="Path_43" data-name="Path 43" d="M728.321,98.625a33.363,33.363,0,0,1-3.9,1.458,15.066,15.066,0,0,1-2.036.471,20.748,20.748,0,0,1-2.083.124,23.842,23.842,0,0,1-4.162-.108,19.116,19.116,0,0,0-2.055-.146q-1.031-.085-2.071-.111,1.034-.1,2.077-.136a19.419,19.419,0,0,1,2.082.148,23.576,23.576,0,0,0,4.121.107c.69-.033,1.387-.021,2.056-.121a14.831,14.831,0,0,0,2-.463,33.18,33.18,0,0,0,3.867-1.446.124.124,0,1,1,.105.224Z" transform="translate(-466.981 -64.526)" fill="#77ac9a" />
8181 <path id="Path_44" data-name="Path 44" d="M729.448,104.4a21.76,21.76,0,0,1-2.524,2.284,10.7,10.7,0,0,1-1.43.94,6.145,6.145,0,0,1-.786.36l-.432.069c-.147,0-.293,0-.433,0l.4-.124.378-.176a5.94,5.94,0,0,0,.752-.345,10.484,10.484,0,0,0,1.4-.918,21.543,21.543,0,0,0,2.492-2.256l0,0a.124.124,0,0,1,.179.17Z" transform="translate(-474.738 -68.339)" fill="#77ac9a" />
8182 <path id="Path_45" data-name="Path 45" d="M740.509,101.543c-.876,1.037-1.795,2.033-2.768,2.978q-.728.711-1.525,1.353c-.265.215-.545.411-.829.6a4.978,4.978,0,0,1-.965.362l.431-.267.4-.3c.276-.187.549-.378.809-.59q.784-.629,1.507-1.337c.965-.937,1.882-1.932,2.75-2.959a.124.124,0,1,1,.192.156Z" transform="translate(-481.676 -66.461)" fill="#77ac9a" />
8183 <path id="Path_46" data-name="Path 46" d="M740.031,82.45l-.1-6.922.324-3.711-.044-.226-3.251-1.7a11.665,11.665,0,0,0-2.289-1.984,12.313,12.313,0,0,1-3.242-2.642c-.988-1.149-1.184-1.27-1.4-1.537a7.5,7.5,0,0,1-1.136-1.271c-.37-.628-.711-.424-1.476-1.389s-2.15-2.851-2.15-2.851,2.482,2.8,3.145,3.384,2.436,2.685,2.688,2.816,1.466,1.492,3.036,2.623,2.85,2.238,3.214,2.485,2.9,1.467,2.9,1.467-.712-8.715-.234-12.066-.049-2.6.287-4.184l-.142,6s.016,5.179.179,5.693S740.53,71,740.53,71s3.613-2.628,4.587-3.287,3.672-2.171,4.026-2.5,2.667-1.765,3.132-2.022,4.858-3.1,5.217-3.3-5.742,3.893-5.742,3.893l-4.292,2.809s-2.931,1.964-3.073,2.062l-3.611,2.515c-.1.068-.151.2.105.361s2.995,1.913,3.367,2.057,5.15,2.543,5.15,2.543-3.823-1.693-4.236-1.826a9.563,9.563,0,0,1-1.208-.514c-.226-.117-2.144-1.264-2.144-1.264a11.115,11.115,0,0,0-1.259-.752c-.021.063-.152,1.824-.179,2.389a11.429,11.429,0,0,0-.145,3.041A35.352,35.352,0,0,1,740.031,82.45Z" transform="translate(-475.673 -35.9)" fill="#77ac9a" />
8184 <path id="Path_47" data-name="Path 47" d="M747.7,114.977a18.041,18.041,0,0,1-2.714,3.292,34.25,34.25,0,0,0-2.867,3.094q-1.369,1.616-2.663,3.293c-.431.559-.849,1.127-1.258,1.7a20.788,20.788,0,0,0-1.242,1.715,20.947,20.947,0,0,1,1.04-1.858c.412-.577.831-1.148,1.264-1.709q1.294-1.685,2.671-3.3a34.323,34.323,0,0,1,2.9-3.123,17.845,17.845,0,0,0,2.667-3.239l0,0a.124.124,0,0,1,.2.14Z" transform="translate(-483.341 -75.281)" fill="#77ac9a" />
8185 <path id="Path_48" data-name="Path 48" d="M747.266,124.115l-3.516.681c-.574.108-1.2.21-1.774.26a5.916,5.916,0,0,0-.856.184,3.207,3.207,0,0,0-.85.243,2.777,2.777,0,0,1,.779-.48,6.161,6.161,0,0,1,.892-.192c.616-.055,1.167-.147,1.765-.258l3.511-.681a.124.124,0,0,1,.051.242Z" transform="translate(-485.512 -81.241)" fill="#77ac9a" />
8186 <path id="Path_49" data-name="Path 49" d="M768.036,134.967a40.907,40.907,0,0,1,1.258,3.941,7.881,7.881,0,0,0,.784,1.874l1.047,1.779,1.047,1.779c.321.609.622,1.222.965,1.815s.7,1.179,1.068,1.755c.331.6.7,1.188.986,1.816-.357-.588-.791-1.122-1.194-1.682-.374-.579-.735-1.167-1.075-1.767s-.651-1.219-.97-1.825l-1.045-1.775-1.045-1.775a8.134,8.134,0,0,1-.8-1.918c-.451-1.305-.678-2.684-1.245-3.908l0-.006a.124.124,0,1,1,.224-.1Z" transform="translate(-503.568 -88.472)" fill="#77ac9a" />
8187 <path id="Path_50" data-name="Path 50" d="M752.621,137.407c.518-.915.734-1.966,1.16-2.926l1.107-2.957c.2-.5.344-.971.606-1.493a7.083,7.083,0,0,0,.769-1.345,9.994,9.994,0,0,1,1.609-2.736l-.026.072.111-4.724a.124.124,0,0,1,.247.006l-.111,4.724a.133.133,0,0,1-.026.073,9.743,9.743,0,0,0-1.578,2.684,7.328,7.328,0,0,1-.8,1.391c-.206.421-.39.955-.575,1.435l-1.108,2.959a14.218,14.218,0,0,1-.612,1.459A7.768,7.768,0,0,1,752.621,137.407Z" transform="translate(-493.612 -79.474)" fill="#77ac9a" />
8188 <path id="Path_51" data-name="Path 51" d="M777.165,161.35a2.552,2.552,0,0,0-.627,1.1c-.137.412-.174.869-.313,1.317a3.3,3.3,0,0,0-.231,1.29c.006.221.022.444.045.667l-.043.686c-.078-.218-.139-.439-.2-.662-.023-.227-.04-.456-.046-.687a3.559,3.559,0,0,1,.241-1.365c.132-.417.168-.872.315-1.321a2.727,2.727,0,0,1,.716-1.223.123.123,0,1,1,.165.183h0Z" transform="translate(-508.779 -105.671)" fill="#77ac9a" />
8189 <path id="Path_52" data-name="Path 52" d="M768.406,150.481a8.536,8.536,0,0,0-.87,1.982l-.66,2.109c-.223.7-.425,1.427-.627,2.128-.1.354-.184.711-.254,1.07a8.086,8.086,0,0,0-.256,1.076,6.176,6.176,0,0,1,.013-1.123c.071-.367.161-.729.258-1.088.207-.72.4-1.418.627-2.128l.665-2.125a8.475,8.475,0,0,1,.917-2.063.123.123,0,1,1,.2.136Z" transform="translate(-502.203 -98.551)" fill="#77ac9a" />
8190 <path id="Path_53" data-name="Path 53" d="M795.156,116.77c.069-.076.018-.023.039,0a.535.535,0,0,0,.034.1,1.761,1.761,0,0,0,.123.216,4.671,4.671,0,0,0,.318.417l.7.811q.713.8,1.469,1.565a17.757,17.757,0,0,0,3.28,2.723l.01.007c.827.572,1.711,1.088,2.581,1.614l2.62,1.573c.87.532,1.739,1.063,2.58,1.652a6.22,6.22,0,0,1,1.136,1.037,4.452,4.452,0,0,0,1.21.906,4.517,4.517,0,0,1-1.307-.8c-.2-.157-.387-.352-.578-.5s-.4-.3-.6-.446c-.828-.58-1.7-1.112-2.565-1.642l-2.618-1.572c-.872-.528-1.75-1.039-2.6-1.626l.01.007a17.965,17.965,0,0,1-3.331-2.763q-.761-.767-1.478-1.575l-.706-.818a4.971,4.971,0,0,1-.334-.439,1.99,1.99,0,0,1-.142-.252.765.765,0,0,1-.051-.154c.006-.064-.06-.116.076-.257a.124.124,0,1,1,.128.212Z" transform="translate(-521.369 -76.434)" fill="#77ac9a" />
8191 <path id="Path_54" data-name="Path 54" d="M820.82,118.755a9.422,9.422,0,0,1-1.607.231l-1.62.133-3.246.085c-1.082.019-2.165.036-3.247.031-.543,0-1.07.015-1.616.052-.547.021-1.084.021-1.632.01a41.616,41.616,0,0,1-6.424-1l-6.32-1.51a.124.124,0,1,1,.057-.241h0l6.3,1.507a41.5,41.5,0,0,0,6.385,1c.534.011,1.079.011,1.613-.01.534-.036,1.088-.054,1.627-.052,1.082,0,2.161-.011,3.243-.031l3.242-.085,1.622-.009A9.393,9.393,0,0,0,820.82,118.755Z" transform="translate(-521.416 -76.432)" fill="#77ac9a" />
8192 <path id="Path_55" data-name="Path 55" d="M846.918,123.68a2.87,2.87,0,0,0,1.081.913,14.174,14.174,0,0,0,1.371.6c.466.185.934.368,1.408.52a6.609,6.609,0,0,0,.716.192,2.351,2.351,0,0,0,.725.166,2.061,2.061,0,0,1-.774.077,6.789,6.789,0,0,1-.742-.2c-.485-.155-.956-.339-1.425-.526a14.3,14.3,0,0,1-1.4-.608,3.027,3.027,0,0,1-1.187-1.027.123.123,0,0,1,.21-.128h0Z" transform="translate(-555.299 -81.062)" fill="#77ac9a" />
8193 <path id="Path_56" data-name="Path 56" d="M833.112,123.884a8.435,8.435,0,0,0,1.982,1.438c.732.392,1.49.747,2.251,1.086s1.534.659,2.315.949c.391.143.784.281,1.182.395a3.5,3.5,0,0,0,1.2.311,3.246,3.246,0,0,1-1.266-.073c-.407-.117-.8-.256-1.2-.4-.788-.293-1.563-.615-2.33-.954s-1.526-.7-2.269-1.1a8.5,8.5,0,0,1-2.06-1.506.123.123,0,0,1,.18-.168h0Z" transform="translate(-546.252 -81.212)" fill="#77ac9a" />
8194 <path id="Path_57" data-name="Path 57" d="M814.651,121.222a17.751,17.751,0,0,0,2.707,2.674,16.816,16.816,0,0,0,3.258,1.969,24.512,24.512,0,0,0,3.555,1.413,16.174,16.174,0,0,1,1.784.751,10.165,10.165,0,0,1,1.587,1.1,10.015,10.015,0,0,0-1.7-.882,15.946,15.946,0,0,0-1.756-.739,24.773,24.773,0,0,1-3.581-1.424,17.046,17.046,0,0,1-3.306-2,17.952,17.952,0,0,1-2.75-2.718.124.124,0,0,1,.193-.154Z" transform="translate(-534.147 -79.47)" fill="#77ac9a" />
8195 <path id="Path_58" data-name="Path 58" d="M780.794,110.493a9.841,9.841,0,0,0,.614,2.9,21.443,21.443,0,0,0,1.2,2.75,18.726,18.726,0,0,0,1.554,2.563,21.383,21.383,0,0,0,1.962,2.27c1.394,1.444,2.877,2.809,4.385,4.135a8.285,8.285,0,0,0,1.2.89c.419.282.836.568,1.239.875a10.143,10.143,0,0,1,2.094,2.184,10.024,10.024,0,0,0-2.243-1.986q-.6-.449-1.228-.867l-.63-.422c-.215-.155-.4-.322-.592-.486-1.515-1.333-3-2.7-4.4-4.151a21.622,21.622,0,0,1-1.984-2.3,18.966,18.966,0,0,1-1.574-2.6,21.7,21.7,0,0,1-1.214-2.782,9.995,9.995,0,0,1-.627-2.989.123.123,0,0,1,.247-.006Z" transform="translate(-511.927 -72.377)" fill="#77ac9a" />
8196 <path id="Path_59" data-name="Path 59" d="M789.3,89.006c1.863.606,3.684,1.306,5.569,1.787.942.244,1.891.464,2.85.617a20.984,20.984,0,0,0,2.9.212,36.426,36.426,0,0,0,5.833-.107c.967-.1,1.929-.253,2.887-.428.967-.128,1.927-.313,2.9-.427-.957.195-1.9.46-2.855.67-.963.176-1.931.328-2.906.431a36.75,36.75,0,0,1-5.869.109,21.322,21.322,0,0,1-2.933-.215c-.97-.155-1.926-.377-2.874-.622-1.9-.486-3.734-1.19-5.583-1.791a.124.124,0,0,1,.077-.235Z" transform="translate(-517.567 -58.372)" fill="#77ac9a" />
8197 <path id="Path_60" data-name="Path 60" d="M807.147,74.51l4.306.233a36.5,36.5,0,0,0,4.3-.176,31.661,31.661,0,0,0,4.24-.712,14.453,14.453,0,0,1,2.137-.4,5.518,5.518,0,0,0,2.105-.351,5.624,5.624,0,0,1-2.079.6,14.138,14.138,0,0,0-2.1.4,31.941,31.941,0,0,1-4.274.718,36.762,36.762,0,0,1-4.328.177l-4.322-.234a.124.124,0,0,1,.013-.247h0Z" transform="translate(-529.284 -47.943)" fill="#77ac9a" />
8198 <path id="Path_61" data-name="Path 61" d="M824.467,42.285a16.6,16.6,0,0,0-1.724,1.286c-.561.457-1.193.825-1.786,1.243-1.208.8-2.4,1.637-3.621,2.417s-2.41,1.612-3.69,2.3l-3.78,2.152.008,0-2.387,1.557-2.453,1.456,2.319-1.661,2.386-1.559.008,0,3.771-2.147c1.276-.683,2.463-1.517,3.684-2.294s2.4-1.606,3.606-2.407c.591-.415,1.217-.779,1.779-1.237a16.671,16.671,0,0,1,1.756-1.309.124.124,0,0,1,.129.211h0Z" transform="translate(-527.987 -27.58)" fill="#77ac9a" />
8199 <path id="Path_62" data-name="Path 62" d="M838.227,57.369a5.528,5.528,0,0,0,1.648.443,7.511,7.511,0,0,0,1.725,0,8.645,8.645,0,0,0,1.689-.376c.274-.094.54-.2.832-.293a3.812,3.812,0,0,1,.9-.055,4.907,4.907,0,0,0-.825.291c-.267.085-.546.2-.827.292a8.9,8.9,0,0,1-1.738.387,7.783,7.783,0,0,1-1.784,0,5.727,5.727,0,0,1-1.733-.469.123.123,0,0,1,.1-.224h0Z" transform="translate(-549.635 -37.439)" fill="#77ac9a" />
8200 <path id="Path_63" data-name="Path 63" d="M839.632,46.669a6.88,6.88,0,0,1,.962-2.538,5.137,5.137,0,0,1,.91-1.012,5.3,5.3,0,0,0,.443-.48,1.854,1.854,0,0,0,.177-.257.586.586,0,0,0,.052-.125c.023-.034-.022-.079.033-.023l-.021-.195a4.07,4.07,0,0,1,.5-.446c.183-.131.364-.265.552-.391-.134.183-.275.358-.414.535a4.079,4.079,0,0,1-.467.48l-.021-.195a.261.261,0,0,1,.078.292.824.824,0,0,1-.074.184,2.1,2.1,0,0,1-.2.294,5.571,5.571,0,0,1-.464.5,4.882,4.882,0,0,0-.876.972,6.641,6.641,0,0,0-.923,2.437v.008a.124.124,0,0,1-.243-.043Z" transform="translate(-550.678 -27.023)" fill="#77ac9a" />
8201 <path id="Path_64" data-name="Path 64" d="M830.4,46.346a31.811,31.811,0,0,1,1.5-4.632,18.668,18.668,0,0,1,1.066-2.195,10.886,10.886,0,0,1,.663-1.03,7.649,7.649,0,0,1,.876-.858,10.161,10.161,0,0,0-.676,1,10.655,10.655,0,0,0-.649,1.008,18.375,18.375,0,0,0-1.052,2.166,31.577,31.577,0,0,0-1.484,4.592v0a.124.124,0,1,1-.24-.059Z" transform="translate(-544.62 -24.681)" fill="#77ac9a" />
8202 <path id="Path_65" data-name="Path 65" d="M827.409,63.971a19.83,19.83,0,0,0,2.534.48,11.833,11.833,0,0,0,2.567.065c.863-.073,1.725-.146,2.58-.255.427-.056.853-.119,1.271-.21a2.965,2.965,0,0,0,1.224-.348,2.83,2.83,0,0,1-1.171.59c-.429.093-.861.157-1.292.214-.863.11-1.728.183-2.591.256a12.091,12.091,0,0,1-2.618-.065,20.07,20.07,0,0,1-2.569-.487.124.124,0,0,1,.062-.24Z" transform="translate(-542.558 -41.78)" fill="#77ac9a" />
8203 <path id="Path_66" data-name="Path 66" d="M807.574,46.314a35.742,35.742,0,0,1,1.241-4.381,28.334,28.334,0,0,1,1.859-4.155c.709-1.339,1.449-2.664,2.291-3.931.827-1.338,2.125-2.167,3.027-3.387a12.228,12.228,0,0,1-1.364,1.818l-.788.82a7.609,7.609,0,0,0-.669.887c-.833,1.253-1.571,2.575-2.277,3.908a28.06,28.06,0,0,0-1.845,4.122,35.518,35.518,0,0,0-1.231,4.347v0a.124.124,0,0,1-.242-.052Z" transform="translate(-529.652 -19.977)" fill="#77ac9a" />
8204 <path id="Path_67" data-name="Path 67" d="M788.989,45.215a21.088,21.088,0,0,0,.428-2.962,20.244,20.244,0,0,1,.277-3.011,40.489,40.489,0,0,1,1.319-5.9,48.143,48.143,0,0,1,2.329-5.577c.443-.9.9-1.8,1.428-2.669a11.816,11.816,0,0,0,1.551-2.571,11.917,11.917,0,0,1-1.341,2.7c-.52.85-.975,1.747-1.415,2.646a47.9,47.9,0,0,0-2.315,5.544,40.237,40.237,0,0,0-1.31,5.86,20.007,20.007,0,0,0-.275,2.987,21.322,21.322,0,0,1-.434,3,.124.124,0,1,1-.242-.05Z" transform="translate(-517.462 -14.775)" fill="#77ac9a" />
8205 <path id="Path_68" data-name="Path 68" d="M767.67.074a10.27,10.27,0,0,1,.639,3.072c.092,1.034.135,2.07.164,3.106.044,2.072.016,4.142-.06,6.212l-.326,6.2-.149,3.094-.271,3.1.024-3.1.149-3.1.325-6.195c.076-2.064.1-4.132.06-6.2-.029-1.032-.072-2.063-.163-3.09a10.175,10.175,0,0,0-.611-2.977l-.008-.017a.123.123,0,1,1,.226-.1Z" transform="translate(-503.327 0)" fill="#77ac9a" />
8206 <path id="Path_69" data-name="Path 69" d="M762.08,16.89l-2.428-2.932a11.126,11.126,0,0,1-1.02-1.627q-.223-.425-.413-.866a5.723,5.723,0,0,1-.211-.941,8.143,8.143,0,0,0,.438.843q.186.432.4.85a10.881,10.881,0,0,0,1,1.59l2.422,2.925a.124.124,0,1,1-.189.159Z" transform="translate(-497.146 -6.902)" fill="#77ac9a" />
8207 <path id="Path_70" data-name="Path 70" d="M756.863,26.857a23.107,23.107,0,0,1-3.781-4.624,21.869,21.869,0,0,1-1.5-2.594l-.29-.685-.339-.659-.569-1.378.792,1.27.342.665.291.685a21.667,21.667,0,0,0,1.477,2.56,22.892,22.892,0,0,0,3.734,4.571l.006.005a.124.124,0,0,1-.167.182Z" transform="translate(-492.147 -11.095)" fill="#77ac9a" />
8208 <path id="Path_71" data-name="Path 71" d="M751.605,40.82a34.285,34.285,0,0,1-2.431-3.3c-.749-1.139-1.455-2.309-2.091-3.516a37.572,37.572,0,0,1-1.711-3.709,13.461,13.461,0,0,0-.984-1.763,4.5,4.5,0,0,0-1.3-1.522,4.616,4.616,0,0,1,1.509,1.384,13.709,13.709,0,0,1,1,1.8,37.45,37.45,0,0,0,1.705,3.7c.632,1.2,1.333,2.362,2.079,3.5a34.1,34.1,0,0,0,2.409,3.268l0,0a.124.124,0,1,1-.188.16Z" transform="translate(-487.358 -17.717)" fill="#77ac9a" />
8209 <path id="Path_72" data-name="Path 72" d="M747.181,47.517a40.23,40.23,0,0,1-4.232-4.383,26.764,26.764,0,0,1-1.775-2.481A24.045,24.045,0,0,1,739.666,38a34.747,34.747,0,0,1-2.03-5.744q-.4-1.469-.719-2.96l-.233-1.505a11.117,11.117,0,0,0-.258-1.494,11.116,11.116,0,0,1,.38,1.471l.353,1.477q.315,1.482.715,2.945a34.493,34.493,0,0,0,2.014,5.7,23.8,23.8,0,0,0,1.494,2.626,26.545,26.545,0,0,0,1.759,2.459,40.019,40.019,0,0,0,4.2,4.353.124.124,0,1,1-.161.188Z" transform="translate(-482.99 -17.247)" fill="#77ac9a" />
8210 <path id="Path_73" data-name="Path 73" d="M714.16,63.262c-.49-.057-.983-.107-1.474-.147a12.5,12.5,0,0,0-1.47-.057,6.529,6.529,0,0,1-1.5-.17,6.729,6.729,0,0,1-.729-.2,2.624,2.624,0,0,1-.629-.434,3.257,3.257,0,0,0,.71.2,6.523,6.523,0,0,0,.7.2,6.33,6.33,0,0,0,1.442.164,12.643,12.643,0,0,1,1.5.058c.5.041.989.091,1.483.148a.124.124,0,1,1-.028.246Z" transform="translate(-464.579 -40.827)" fill="#77ac9a" />
8211 <path id="Path_74" data-name="Path 74" d="M713.223,48.235a6.439,6.439,0,0,1,1.324,1.2,9.522,9.522,0,0,1,1.024,1.476c.3.516.541,1.064.834,1.567a5.568,5.568,0,0,0,1.037,1.37l.013.011.006.007,1.059,1.2a.124.124,0,0,1-.186.164l-1.059-1.2.019.017a5.69,5.69,0,0,1-1.1-1.445c-.3-.521-.537-1.063-.834-1.568a9.285,9.285,0,0,0-1-1.439C713.964,49.164,713.6,48.7,713.223,48.235Z" transform="translate(-467.773 -31.635)" fill="#77ac9a" />
8212 <path id="Path_75" data-name="Path 75" d="M713.849,70.753q-1.143.073-2.285.1a20.684,20.684,0,0,1-2.3-.044,14.117,14.117,0,0,1-2.249-.486l-1.1-.315a3.7,3.7,0,0,0-1.082-.32,3.314,3.314,0,0,1,1.149.081l1.1.316a13.892,13.892,0,0,0,2.207.478,20.442,20.442,0,0,0,2.265.042c.758-.019,1.518-.053,2.275-.1a.124.124,0,0,1,.018.247Z" transform="translate(-462.275 -45.695)" fill="#77ac9a" />
8213 <path id="Path_76" data-name="Path 76" d="M719.966,85.663c-.81.115-1.62.207-2.435.273a19.676,19.676,0,0,1-2.456.07c-1.636-.1-3.249-.331-4.862-.574l-.013,0c-.571-.149-1.144-.3-1.72-.422l-.853-.241a3.385,3.385,0,0,0-.867-.156,3.431,3.431,0,0,1,.892.026c.3.036.593.068.885.125.578.136,1.154.276,1.728.428l-.012,0c1.605.242,3.222.47,4.836.571a19.43,19.43,0,0,0,2.423-.07c.808-.066,1.617-.157,2.418-.271a.124.124,0,0,1,.038.245Z" transform="translate(-463.534 -55.482)" fill="#77ac9a" />
8214 <path id="Path_77" data-name="Path 77" d="M728.319,98.637a33.364,33.364,0,0,1-3.9,1.457,15.017,15.017,0,0,1-2.036.471,20.853,20.853,0,0,1-2.083.124,23.843,23.843,0,0,1-4.162-.109,19.2,19.2,0,0,0-2.055-.146q-1.031-.084-2.071-.112,1.035-.1,2.077-.136a19.418,19.418,0,0,1,2.081.148,23.611,23.611,0,0,0,4.121.106,20.549,20.549,0,0,0,2.056-.121,14.777,14.777,0,0,0,2-.463,33.121,33.121,0,0,0,3.867-1.445.124.124,0,0,1,.105.224Z" transform="translate(-466.979 -64.537)" fill="#77ac9a" />
8215 <path id="Path_78" data-name="Path 78" d="M729.448,104.409a21.793,21.793,0,0,1-2.524,2.284,10.694,10.694,0,0,1-1.43.94,6.19,6.19,0,0,1-.786.36l-.432.069c-.147,0-.292,0-.433,0l.4-.125.378-.176a5.886,5.886,0,0,0,.752-.345,10.449,10.449,0,0,0,1.4-.918,21.539,21.539,0,0,0,2.492-2.255l0,0a.124.124,0,0,1,.179.171Z" transform="translate(-474.738 -68.343)" fill="#77ac9a" />
8216 <path id="Path_79" data-name="Path 79" d="M740.508,101.562c-.876,1.037-1.795,2.033-2.768,2.979q-.728.711-1.525,1.353c-.265.215-.545.411-.829.6a4.962,4.962,0,0,1-.965.363l.431-.267.4-.3c.276-.187.549-.378.809-.59q.784-.629,1.507-1.336c.965-.938,1.882-1.932,2.75-2.959a.124.124,0,0,1,.192.156Z" transform="translate(-481.675 -66.48)" fill="#77ac9a" />
8217 <path id="Path_80" data-name="Path 80" d="M754.387,99.154l1.986-.847.072.25Z" transform="translate(-494.77 -64.475)" fill="#77ac9a" />
8218 <path id="Path_81" data-name="Path 81" d="M754.22,99.073a.088.088,0,0,1-.034-.17l1.985-.847a.091.091,0,0,1,.072,0,.088.088,0,0,1,.047.056l.072.249a.089.089,0,0,1-.06.11l-2.058.6A.1.1,0,0,1,754.22,99.073Zm1.928-.815-.549.234.569-.165Z" transform="translate(-494.603 -64.306)" fill="#77ac9a" />
8219 <path id="Path_82" data-name="Path 82" d="M763.679,118.041a9.777,9.777,0,0,0,.79-1.4c.017-.208.133.2.133.2Z" transform="translate(-500.865 -76.46)" fill="#77ac9a" />
8220 <path id="Path_83" data-name="Path 83" d="M763.51,117.959a.093.093,0,0,1-.051-.016.089.089,0,0,1-.023-.121,8.587,8.587,0,0,0,.776-1.359c.007-.087.04-.134.1-.14.074-.012.127.041.206.322a.089.089,0,0,1-.015.078l-.922,1.2A.087.087,0,0,1,763.51,117.959Zm.822-1.316-.012.028.015-.019Z" transform="translate(-500.696 -76.29)" fill="#77ac9a" />
8221 <path id="Path_84" data-name="Path 84" d="M789.9,77.482s-.019,3.167-.13,3.447a.516.516,0,0,0,.066.5s2.154.987,2.782,1.2-3.123-1.055-3.123-1.055Z" transform="translate(-517.794 -50.817)" fill="#77ac9a" />
8222 <path id="Path_85" data-name="Path 85" d="M792.527,82.565a.172.172,0,0,1-.04-.006h0l-.03-.01-.039-.013-.062-.021-3.062-1.033a.088.088,0,0,1-.06-.092l.406-4.086a.09.09,0,0,1,.092-.079.089.089,0,0,1,.084.089c0,.326-.022,3.191-.137,3.479a.427.427,0,0,0,.042.394c.225.1,2.169.988,2.752,1.184l.069.023-.007.021c.081.041.075.061.064.092A.073.073,0,0,1,792.527,82.565Zm-3.11-1.227.827.279c-.34-.153-.588-.266-.617-.28a.089.089,0,0,1-.031-.024.6.6,0,0,1-.08-.586,8.5,8.5,0,0,0,.086-1.242Z" transform="translate(-517.625 -50.649)" fill="#77ac9a" />
8223 <path id="Path_86" data-name="Path 86" d="M790.813,114.132l-.019,0a41.193,41.193,0,0,1-7.236-2.672.088.088,0,0,1-.041-.118.086.086,0,0,1,.118-.041,41.032,41.032,0,0,0,7.2,2.659.088.088,0,0,1-.019.175Z" transform="translate(-513.87 -72.99)" fill="#77ac9a" />
8224 <path id="Path_87" data-name="Path 87" d="M528.231,44.722c-.974-2.5-2.117-3.007-4.363-3.261v-.339h13v.339c-1.99.211-2.838.677-2.838,1.9a8.983,8.983,0,0,0,.8,3.305l5.846,14.741,4.447-11.734-2.244-5.719c-.721-1.948-2.034-2.33-3.727-2.5v-.339h12.749v.339c-2.076.169-3.135.677-3.135,2.033a10.446,10.446,0,0,0,.932,3.3l5.76,14.741,5.719-14.826a10.587,10.587,0,0,0,.72-3.133c0-1.313-.8-1.907-3.007-2.118v-.339h8.514v.339c-2.288.254-2.754.974-3.643,3.3L553.645,71.154l-7.582-19.146c.043,0-7.328,19.146-7.328,19.146Z" transform="translate(-343.583 -26.97)" fill="#3b3d3e" />
8225 <path id="Path_88" data-name="Path 88" d="M649.672,67.539c2.753-.339,3.3-1.016,3.3-4.574V52.376c0-1.95-1.1-2.33-3.135-1.736v-.51l8.261-2.71V62.965c0,3.515.55,4.277,2.922,4.574v.339H649.672Zm2.8-27.066a2.844,2.844,0,0,1,3.008-2.8,2.8,2.8,0,1,1,0,5.591A2.871,2.871,0,0,1,652.467,40.473Z" transform="translate(-426.092 -24.711)" fill="#3b3d3e" />
8226 <path id="Path_89" data-name="Path 89" d="M686.232,86.186c2.753-.339,3.176-1.1,3.176-4.574V71.53c0-2.838-1.059-2.88-3.008-2.33v-.508l8.133-2.584V70.26c2.076-2.033,4.321-4.025,7.2-4.025,3.219,0,5.336,2.118,5.336,5.8v9.573c0,3.558.466,4.277,3.008,4.574v.339H698.9v-.339c2.668-.339,3.049-.974,3.049-4.574V72.927c0-2.584-.974-3.812-3.092-3.812-1.652,0-3.008.974-4.321,2.161V81.612c0,3.515.466,4.277,2.88,4.574v.339H686.232Z" transform="translate(-450.07 -43.358)" fill="#3b3d3e" />
8227 <path id="Path_90" data-name="Path 90" d="M758.857,77.108c0-5,3.431-10.632,9.319-10.632,5.76,0,8.725,3.94,8.725,7.963H763.6c0,5.338,2.88,9.278,7.032,9.278,2.118,0,4.575-.636,6.523-3.94l.339.169c-1.271,3.643-4.448,7.329-9.192,7.329C762.965,87.274,758.857,82.869,758.857,77.108Zm12.749-4.066c-.339-2.712-1.355-5.253-3.812-5.253-2.33,0-3.854,2.415-4.109,5.253Z" transform="translate(-497.702 -43.598)" fill="#3b3d3e" />
8228 </g>
8229 </svg>
8230
8231 }
8232
8233 @helper RenderCloseButton()
8234 {
8235 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
8236 <path id="Path_91" data-name="Path 91" d="M2.267,2.267a.908.908,0,0,1,1.285,0L12,10.715l8.447-8.449a.909.909,0,0,1,1.285,1.287L13.284,12l8.449,8.448a.909.909,0,0,1-1.287,1.285L12,13.284,3.552,21.734a.909.909,0,1,1-1.285-1.287L10.715,12,2.265,3.552a.908.908,0,0,1,0-1.285Z" transform="translate(-1.999 -1.999)" fill="#3b3d3e" fill-rule="evenodd" />
8237 </svg>
8238 }
8239
8240 @helper SidemenuRenderCartUsps(string icon, string toptext, string bottomtext)
8241 {
8242 var svg = icon + ".svg";
8243
8244 <div class="grid__col-12 grid__col-md-3">
8245 <div class="grid grid--align-center u-justify-content--center border-right">
8246 <div class="grid__col-2">
8247 <img src="/Files/Images/SvgIcons/@svg" height="35" width="35" />
8248 </div>
8249 <div class="grid__col-8">
8250 <div class="u-block">
8251 <strong>@toptext</strong>
8252 </div>
8253 <div class="u-block">
8254 @bottomtext
8255 </div>
8256 </div>
8257 </div>
8258 </div>
8259 }</text>
8260 if (Pageview.Device == Dynamicweb.Frontend.Devices.DeviceType.Tablet)
8261 {
8262 <text>@inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
8263
8264 @using System
8265 @using System.Web
8266 @using System.Collections.Generic
8267 @using Dynamicweb.Rapido.Blocks.Extensibility
8268 @using Dynamicweb.Rapido.Blocks
8269
8270 @functions {
8271 BlocksPage tabletNavigationBlocksPage = BlocksPage.GetBlockPage("Master");
8272 }
8273
8274 @{
8275 bool mobileNavigationItemsHideSignIn = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("HideSignIn");
8276 bool mobileHideCreateAccountLink = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("SignInHideCreateAccount");
8277 bool mobileHideMyProfileLink = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("SignInHideProfile");
8278 bool mobileHideMyOrdersLink = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("SignInHideOrders");
8279 bool mobileHideMySavedCardsLink = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("SignInHideSavedCards");
8280 bool mobileHideMyFavoritesLink = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("SignInHideFavorites");
8281 bool tabletHideCustomerStockLink = false;
8282
8283 Block mobileNavigation = new Block()
8284 {
8285 Id = "TabletNavigation",
8286 SortId = 10,
8287 Template = TabletNavigation(),
8288 SkipRenderBlocksList = true
8289 };
8290 tabletNavigationBlocksPage.Add(MasterBlockId.MasterTopSnippets, mobileNavigation);
8291
8292 if (Model.CurrentUser.ID > 0 && !mobileHideMyProfileLink)
8293 {
8294 Block mobileNavigationSignIn = new Block
8295 {
8296 Id = "MobileNavigationSignIn",
8297 SortId = 10,
8298 Template = RenderTabletNavigationSignIn()
8299 };
8300 tabletNavigationBlocksPage.Add("TabletNavigation", mobileNavigationSignIn);
8301 }
8302
8303 Block mobileNavigationMenu = new Block
8304 {
8305 Id = "TabletNavigationMenu",
8306 SortId = 20,
8307 Template = RenderTabletNavigationMenu()
8308 };
8309 tabletNavigationBlocksPage.Add("TabletNavigation", mobileNavigationMenu);
8310
8311 Block mobileNavigationActions = new Block
8312 {
8313 Id = "TabletNavigationActions",
8314 SortId = 30,
8315 Template = RenderTabletNavigationActions(),
8316 SkipRenderBlocksList = true
8317 };
8318 tabletNavigationBlocksPage.Add("TabletNavigation", mobileNavigationActions);
8319
8320 if (!mobileNavigationItemsHideSignIn)
8321 {
8322 if (Model.CurrentUser.ID <= 0)
8323 {
8324 Block mobileNavigationSignInAction = new Block
8325 {
8326 Id = "TabletNavigationSignInAction",
8327 SortId = 10,
8328 Template = RenderTabletNavigationSignInAction()
8329 };
8330 tabletNavigationBlocksPage.Add("TabletNavigationActions", mobileNavigationSignInAction);
8331
8332 if (!mobileHideCreateAccountLink)
8333 {
8334 Block mobileNavigationCreateAccountAction = new Block
8335 {
8336 Id = "TabletNavigationCreateAccountAction",
8337 SortId = 20,
8338 Template = RenderTabletNavigationCreateAccountAction()
8339 };
8340 tabletNavigationBlocksPage.Add("TabletNavigationActions", mobileNavigationCreateAccountAction);
8341 }
8342 }
8343 else
8344 {
8345 if (!mobileHideMyOrdersLink)
8346 {
8347 Block mobileNavigationOrdersAction = new Block
8348 {
8349 Id = "TabletNavigationOrdersAction",
8350 SortId = 20,
8351 Template = RenderTabletNavigationOrdersAction()
8352 };
8353 tabletNavigationBlocksPage.Add("TabletNavigationActions", mobileNavigationOrdersAction);
8354 }
8355 if (!mobileHideMyFavoritesLink)
8356 {
8357 Block mobileNavigationFavoritesAction = new Block
8358 {
8359 Id = "TabletNavigationFavoritesAction",
8360 SortId = 30,
8361 Template = RenderTabletNavigationFavoritesAction()
8362 };
8363 tabletNavigationBlocksPage.Add("TabletNavigationActions", mobileNavigationFavoritesAction);
8364 }
8365 if (!mobileHideMySavedCardsLink)
8366 {
8367 Block mobileNavigationSavedCardsAction = new Block
8368 {
8369 Id = "TabletNavigationFavoritesAction",
8370 SortId = 30,
8371 Template = RenderTabletNavigationSavedCardsAction()
8372 };
8373 tabletNavigationBlocksPage.Add("TabletNavigationActions", mobileNavigationSavedCardsAction);
8374 }
8375
8376 if (!tabletHideCustomerStockLink)
8377 {
8378 Block tabletNavigationCustomerStockAction = new Block
8379 {
8380 Id = "TabletNavigationCustomerStockAction",
8381 SortId = 31,
8382 Template = RenderTabletNavigationCustomerStockAction()
8383 };
8384 tabletNavigationBlocksPage.Add("TabletNavigationActions", tabletNavigationCustomerStockAction);
8385 }
8386
8387 Block mobileNavigationSignOutAction = new Block
8388 {
8389 Id = "TabletNavigationSignOutAction",
8390 SortId = 40,
8391 Template = RenderTabletNavigationSignOutAction()
8392 };
8393 tabletNavigationBlocksPage.Add("TabletNavigationActions", mobileNavigationSignOutAction);
8394 }
8395 }
8396
8397 if (Model.Languages.Count > 1)
8398 {
8399 Block mobileNavigationLanguagesAction = new Block
8400 {
8401 Id = "TabletNavigationLanguagesAction",
8402 SortId = 50,
8403 Template = RenderTabletNavigationLanguagesAction()
8404 };
8405 tabletNavigationBlocksPage.Add("TabletNavigationActions", mobileNavigationLanguagesAction);
8406 }
8407 }
8408
8409
8410 @helper TabletNavigation()
8411 {
8412 List<Block> subBlocks = this.tabletNavigationBlocksPage.GetBlockListById("TabletNavigation").OrderBy(item => item.SortId).ToList();
8413 string mobileTopDesign = Model.Area.Item.GetItem("Layout").GetItem("MobileTop").GetList("Design") != null ? Model.Area.Item.GetItem("Layout").GetItem("MobileTop").GetList("Design").SelectedValue : "nav-left";
8414 string position = mobileTopDesign == "nav-left" || mobileTopDesign == "nav-search-left" ? "left" : "right";
8415
8416 <!-- Trigger for mobile navigation -->
8417 <input type="checkbox" id="MobileNavTrigger" class="mobile-nav-trigger mobile-nav-trigger--@position" autocomplete="off" />
8418
8419 <!-- Mobile navigation -->
8420 <nav class="mobile-navigation mobile-navigation--@position dw-mod js-mobile-navigation">
8421 <div class="mobile-navigation__wrapper" id="mobileNavigationWrapper">
8422 <div class="mobile-navigation-header">
8423 <div class="mobile-navigation-header-topbar">
8424 <p>@Translate("Smartpage:MobilMenu.headerText", "Brug for hjælp? +45 70 22 68 88")</p>
8425 <div class="mobile-navigation-header-close js-navigation-close">
8426 <div class="mobile-navigation-header-cross">
8427 <span></span>
8428 <span></span>
8429 </div>
8430 <p>@Translate("Smartpage:MobilMenu.CloseText", "Luk")</p>
8431 </div>
8432 </div>
8433 @RenderTabletNavigationSearchBar()
8434 </div>
8435 @RenderBlockList(subBlocks)
8436 </div>
8437 <div class="mobile-navigation-footer">
8438 <ul>
8439 @foreach (var icon in Pageview.AreaSettings.GetItem("Custom").GetItem("CustomSettings").GetItems("HeaderUSP"))
8440 {
8441 <li>
8442 @if (!string.IsNullOrWhiteSpace(icon.GetString("Link")))
8443 {
8444 <a href="@icon.GetString("Link")"><i class="fa fa-check"></i> @icon.GetString("Label")</a>
8445 }
8446 else
8447 {
8448 <i class="fa fa-check"></i> @icon.GetString("Label")
8449 }
8450 </li>
8451 }
8452 </ul>
8453 </div>
8454 </nav>
8455
8456 <label class="mobile-nav-trigger-off js-mobile-nav-trigger-off" for="MobileNavTrigger"></label>
8457 }
8458
8459 @helper RenderTabletNavigationSignIn()
8460 {
8461 int signInProfilePageId = GetPageIdByNavigationTag("SignInPage");
8462 int myProfilePageId = GetPageIdByNavigationTag("CustomerProfile");
8463 string linkStart = Model.CurrentUser.ID <= 0 ? "/Default.aspx?ID=" + signInProfilePageId + "&RedirectPageId=" : "/Default.aspx?ID=";
8464 string myProfilePageLink = linkStart + myProfilePageId;
8465 string userName = Model.CurrentUser.FirstName;
8466 if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(Model.CurrentUser.LastName))
8467 {
8468 userName += " " + Model.CurrentUser.LastName;
8469 }
8470 if (string.IsNullOrEmpty(userName))
8471 {
8472 userName = Model.CurrentUser.Name;
8473 }
8474 if (string.IsNullOrEmpty(userName))
8475 {
8476 userName = Model.CurrentUser.UserName;
8477 }
8478 if (string.IsNullOrEmpty(userName))
8479 {
8480 userName = Model.CurrentUser.Email;
8481 }
8482
8483 <ul class="menu menu-mobile">
8484 <li class="menu-mobile__item">
8485 <a href="@myProfilePageLink" class="menu-mobile__link dw-mod"><i class="@Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("SignInProfileIcon").SelectedValue menu-mobile__link-icon"></i> @userName</a>
8486 </li>
8487 </ul>
8488 }
8489
8490 @helper RenderTabletNavigationMenu()
8491 {
8492 bool isSlidesDesign = Model.Area.Item.GetItem("Layout").GetItem("MobileNavigation").GetList("Design").SelectedValue == "Slides";
8493 string menuTemplate = isSlidesDesign ? "BaseMenuForMobileSlides.xslt" : "BaseMenuForMobileExpandable.xslt";
8494 string levels = !String.IsNullOrEmpty(Model.Area.Item.GetItem("Layout").GetItem("MobileNavigation").GetString("Levels")) ? Model.Area.Item.GetItem("Layout").GetItem("MobileNavigation").GetString("Levels") : "3";
8495 bool renderPagesInToolBar = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("RenderPagesInToolBar");
8496 int startLevel = 0;
8497
8498 var navigationSettings = new Dynamicweb.Frontend.Navigation.NavigationSettings()
8499 {
8500 RootAreaId = 0,
8501 RootPageId = 0,
8502 RootNavigationTag = "main-menu",
8503 StartLevel = 1,
8504 StopLevel = 99,
8505 ExpandMode = Dynamicweb.Frontend.Navigation.ExpandMode.All
8506 };
8507
8508 var navigationTemplate = "Navigation/SpViewModelNavigationMobile.cshtml";
8509 @Navigation.RenderNavigation(navigationTemplate, navigationSettings)
8510
8511
8512 if (isSlidesDesign)
8513 {
8514 <script>
8515 function goToLevel(level) {
8516 document.getElementById('mobileNavigationWrapper').style.left = -(level * 100) + "%";
8517 }
8518
8519 document.addEventListener('DOMContentLoaded', function () {
8520 goToLevel(document.getElementById('mobileNavigationWrapper').querySelectorAll('input[type=radio]:checked').length);
8521 });
8522 </script>
8523 }
8524
8525 if (renderPagesInToolBar)
8526 {
8527 @RenderNavigation(new
8528 {
8529 id = "topToolsMobileNavigation",
8530 cssclass = "menu menu-mobile dwnavigation",
8531 template = "ToolsMenuForMobile.xslt"
8532 })
8533 }
8534 }
8535
8536 @helper RenderTabletNavigationActions()
8537 {
8538 List<Block> subBlocks = this.tabletNavigationBlocksPage.GetBlockListById("TabletNavigationActions").OrderBy(item => item.SortId).ToList(); ;
8539
8540 <ul class="menu menu-mobile">
8541 @RenderBlockList(subBlocks)
8542 </ul>
8543 }
8544
8545 @helper RenderTabletNavigationSignInAction()
8546 {
8547 <li class="menu-mobile__item mobile-navigation-login">
8548 <label for="SignInModalTrigger" onclick="document.getElementById('MobileNavTrigger').checked = false;" class="menu-mobile__link dw-mod menu-mobile__link--highlighted"><i class="@Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("SignInProfileIcon").SelectedValue menu-mobile__link-icon"></i> @Translate("Sign in")</label>
8549 </li>
8550 }
8551
8552 @helper RenderTabletNavigationCreateAccountAction()
8553 {
8554 int createAccountPageId = GetPageIdByNavigationTag("CreateAccount");
8555
8556 <li class="menu-mobile__item mobile-navigation-create-account">
8557 <h3>@Translate("Smartpage:MobilMenu.CreateAccountHeading", "Opret bruger og få 100 DKK i opstartsbonus")</h3>
8558 <p>@Translate("Smartpage:MobilMenu.CreateAccountText", "(Gælder på dit næste køb)")</p>
8559 <a class="menu-mobile__link menu-mobile__link--highlighted dw-mod" href="/Default.aspx?ID=@createAccountPageId"><i class="@Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("SignInProfileIcon").SelectedValue menu-mobile__link-icon"></i> @Translate("Create account")</a>
8560 </li>
8561 }
8562
8563 @helper RenderTabletNavigationProfileAction()
8564 {
8565 int signInProfilePageId = GetPageIdByNavigationTag("SignInPage");
8566 string linkStart = Model.CurrentUser.ID <= 0 ? "/Default.aspx?ID=" + signInProfilePageId + "&RedirectPageId=" : "/Default.aspx?ID=";
8567 int myProfilePageId = GetPageIdByNavigationTag("CustomerProfile");
8568 string myProfilePageLink = linkStart + myProfilePageId;
8569
8570 <li class="menu-mobile__item">
8571 <a href="@myProfilePageLink" class="menu-mobile__link menu-mobile__link--highlighted dw-mod"><i class="@Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("SignInProfileIcon").SelectedValue menu-mobile__link-icon"></i> @Translate("My Profile")</a>
8572 </li>
8573 }
8574
8575 @helper RenderTabletNavigationOrdersAction()
8576 {
8577 int signInProfilePageId = GetPageIdByNavigationTag("SignInPage");
8578 string linkStart = Model.CurrentUser.ID <= 0 ? "/Default.aspx?ID=" + signInProfilePageId + "&RedirectPageId=" : "/Default.aspx?ID=";
8579 int myOrdersPageId = GetPageIdByNavigationTag("CustomerOrders");
8580 string myOrdersPageLink = linkStart + myOrdersPageId;
8581 string ordersIcon = "fas fa-list";
8582
8583 <li class="menu-mobile__item">
8584 <a href="@myOrdersPageLink" class="menu-mobile__link menu-mobile__link--highlighted dw-mod"><i class="@ordersIcon menu-mobile__link-icon"></i> @Translate("My Orders")</a>
8585 </li>
8586 }
8587
8588 @helper RenderTabletNavigationFavoritesAction()
8589 {
8590 int signInProfilePageId = GetPageIdByNavigationTag("SignInPage");
8591 string linkStart = Model.CurrentUser.ID <= 0 ? "/Default.aspx?ID=" + signInProfilePageId + "&RedirectPageId=" : "/Default.aspx?ID=";
8592 int myFavoritesPageId = GetPageIdByNavigationTag("CustomerFavorites");
8593 string myFavoritesPageLink = linkStart + myFavoritesPageId;
8594 string favoritesIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("FavoriteIcon") != null ? "fas fa-" + Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("FavoriteIcon").SelectedValue : "fa fa-star";
8595
8596
8597 <li class="menu-mobile__item">
8598 <a href="@myFavoritesPageLink" class="menu-mobile__link menu-mobile__link--highlighted dw-mod"><i class="@favoritesIcon menu-mobile__link-icon"></i> @Translate("My Favorites")</a>
8599 </li>
8600 }
8601
8602 @helper RenderTabletNavigationSavedCardsAction()
8603 {
8604 int signInProfilePageId = GetPageIdByNavigationTag("SignInPage");
8605 string linkStart = Model.CurrentUser.ID <= 0 ? "/Default.aspx?ID=" + signInProfilePageId + "&RedirectPageId=" : "/Default.aspx?ID=";
8606 int mySavedCardsPageId = GetPageIdByNavigationTag("SavedCards");
8607 string mySavedCardsPageLink = linkStart + mySavedCardsPageId;
8608 string savedCardsIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("SavedCards") != null ? "fas fa-" + Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("SavedCards").SelectedValue : "fas fa-credit-card";
8609
8610 <li class="menu-mobile__item">
8611 <a href="@mySavedCardsPageLink" class="menu-mobile__link menu-mobile__link--highlighted dw-mod"><i class="@savedCardsIcon menu-mobile__link-icon"></i> @Translate("My Saved Cards")</a>
8612 </li>
8613 }
8614
8615 @helper RenderTabletNavigationCustomerStockAction()
8616 {
8617 int customerStockPageId = GetPageIdByNavigationTag("CustomerStockPage");
8618
8619 <li class="menu-mobile__item">
8620 <a class="menu-mobile__link menu-mobile__link--highlighted dw-mod" href="/Default.aspx?ID=@customerStockPageId"><i class="fal fa-clipboard-list menu-mobile__link-icon"></i> @Translate("Smartpage:SignInActions.CustomerStock", "Mit kundelager")</a>
8621 </li>
8622 }
8623
8624 @helper RenderTabletNavigationSignOutAction()
8625 {
8626 int pageId = Model.TopPage.ID;
8627 string signOutIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("SignOutIcon") != null ? "fas fa-" + Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("SignOutIcon").SelectedValue : "far fa-sign-out-alt";
8628
8629 <li class="menu-mobile__item">
8630 <a class="menu-mobile__link menu-mobile__link--highlighted dw-mod" href="/Admin/Public/ExtranetLogoff.aspx?ID=@pageId" onclick="RememberState.SetCookie('useAnotherAddress', false)"><i class="@signOutIcon menu-mobile__link-icon"></i> @Translate("Sign out")</a>
8631 </li>
8632 }
8633
8634 @helper RenderTabletNavigationLanguagesAction()
8635 {
8636 bool isSlidesDesign = Model.Area.Item.GetItem("Layout").GetItem("MobileNavigation").GetList("Design").SelectedValue == "Slides";
8637
8638 string selectedLanguage = "";
8639 foreach (var lang in Model.Languages)
8640 {
8641 if (lang.IsCurrent)
8642 {
8643 selectedLanguage = lang.Name;
8644 }
8645 }
8646
8647 <li class="menu-mobile__item dw-mod menu-mobile__item-language">
8648 @if (isSlidesDesign)
8649 {
8650 <input id="MobileMenuCheck_Language" type="radio" class="expand-trigger" name="mobile-menu-level-1" onclick="goToLevel(1);">
8651 }
8652 else
8653 {
8654 <input id="MobileMenuCheck_Language" type="checkbox" class="expand-trigger">
8655 }
8656 <div class="menu-mobile__link__wrap">
8657 <label for="MobileMenuCheck_Language" class="menu-mobile__link menu-mobile__link--highlighted dw-mod"><i class="@Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("LanguageIcon").SelectedValue menu-mobile__link-icon"></i> @selectedLanguage</label>
8658 <label for="MobileMenuCheck_Language" class="menu-mobile__trigger"></label>
8659 </div>
8660 <ul class="menu-mobile menu-mobile__submenu expand-menu">
8661 @if (isSlidesDesign)
8662 {
8663 <li class="menu-mobile__item dw-mod">
8664 <div class="menu-mobile__link__wrap">
8665 <input id="MobileMenuCheck_Language_back" type="radio" class="expand-trigger" name="mobile-menu-level-1" onclick="goToLevel(0);" />
8666 <label for="MobileMenuCheck_Language_back" class="menu-mobile__trigger menu-mobile__trigger--back"></label>
8667 <label for="MobileMenuCheck_Language_back" class="menu-mobile__link dw-mod ">@Translate("Back")</label>
8668 </div>
8669 </li>
8670 }
8671 @foreach (var lang in Model.Languages)
8672 {
8673 <li class="menu-mobile__item dw-mod">
8674 <a class="menu-mobile__link menu-mobile__link--highlighted dw-mod menu-mobile__link--level-1" href="/Default.aspx?ID=@lang.Page.ID">@lang.Name</a>
8675 </li>
8676 }
8677 </ul>
8678 </li>
8679 }
8680
8681
8682 @helper RenderTabletNavigationSearchBar()
8683 {
8684 string searchFeedId = string.Empty;
8685 string searchSecondFeedId = string.Empty;
8686 int groupsFeedId;
8687 string productsSearchId = Converter.ToString(GetPageIdByNavigationTag("ProductSearchFeed"));
8688 int productsPageId = GetPageIdByNavigationTag("ProductsPage");
8689 string contentSearchPageLink = GetPageIdByNavigationTag("ContentSearchResults") + "&Areaid=" + Model.Area.ID;
8690 string resultPageLink;
8691 string searchPlaceholder;
8692 string searchType = "product-search";
8693 string searchTemplate;
8694 string searchContentTemplate = "";
8695 string searchValue = HttpContext.Current.Request.QueryString.Get("Search") ?? "";
8696 bool showGroups = true;
8697
8698 if (Model.Area.Item.GetItem("Layout").GetList("TopSearch").SelectedValue == "contentSearch")
8699 {
8700 searchFeedId = GetPageIdByNavigationTag("ContentSearchFeed") + "&Areaid=" + Model.Area.ID + "&pagesOnly=true";
8701 resultPageLink = contentSearchPageLink;
8702 searchPlaceholder = Translate("Search page");
8703 groupsFeedId = 0;
8704 searchType = "content-search";
8705 searchTemplate = "SearchPagesTemplate";
8706 showGroups = false;
8707 }
8708 else if (Model.Area.Item.GetItem("Layout").GetList("TopSearch").SelectedValue == "combinedSearch")
8709 {
8710 searchFeedId = productsPageId + "&feed=true";
8711 searchSecondFeedId = GetPageIdByNavigationTag("ContentSearchFeed") + "&Areaid=" + Model.Area.ID + "&pagesOnly=true";
8712 resultPageLink = Converter.ToString(productsPageId);
8713 searchPlaceholder = Translate("Search products or pages");
8714 groupsFeedId = GetPageIdByNavigationTag("ProductGroupsFeed");
8715 searchType = "combined-search";
8716 searchTemplate = "SearchProductsTemplateWrap";
8717 searchContentTemplate = "SearchPagesTemplateWrap";
8718 showGroups = Model.Area.Item.GetItem("Layout").GetBoolean("ShowGroupsSelector");
8719 }
8720 else
8721 {
8722 resultPageLink = Converter.ToString(productsPageId);
8723 searchFeedId = productsSearchId + "&feed=true";
8724 groupsFeedId = GetPageIdByNavigationTag("ProductGroupsFeed");
8725 searchPlaceholder = Translate("Search products");
8726 searchTemplate = "SearchResultsTypeAheadMobile";
8727 searchType = "product-search";
8728 showGroups = Model.Area.Item.GetItem("Layout").GetBoolean("ShowGroupsSelector");
8729 }
8730
8731 <input type="checkbox" id="MobileSearchTrigger" class="mobile-search-trigger" />
8732
8733 <div class="main-navigation-mobile mobile-navigation-header-search typeahead-mobile dw-mod">
8734 <div class="center-container top-container__center-container u-no-padding dw-mod">
8735 <div class="grid">
8736 <div class="typeahead-mobile__search-field tablet dw-mod u-no-padding-x js-typeahead" data-page-size="@(searchType == "combined-search" ? 4 : 8)" id="MobileProductSearch" data-search-feed-id="@searchFeedId" data-search-second-feed-id="@searchSecondFeedId" data-result-page-id="@resultPageLink" data-search-type="@searchType">
8737 <div class="mobile-navigation-header-search">
8738 <i class="far fa-search"></i>
8739 <input id="TypeaheadSearchFieldMobile" type="text" class="js-typeahead-search-field js-tablet-search u-w160px u-no-margin" data-shop-id="@Pageview.Area.EcomShopId" data-area-id="@Dynamicweb.Core.Converter.ToString(Pageview.AreaID)" placeholder="@HttpUtility.HtmlAttributeEncode(searchPlaceholder)" value="@HttpUtility.HtmlAttributeEncode(searchValue)">
8740 <form class="u-full-width" action="@Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl(productsPageId)" id="SearchSubmitForm">
8741 <input type="text" class="typeahead-autocomplete js-typeahead-autocomplete u-no-margin" disabled />
8742 </form>
8743 </div>
8744 <div class="tablet-search js-tablet-search-container u-min-w220px u-full-width">
8745 <span class="typeahead-search-overlay typeahead-search-container js-handlebars-root js-typeahead-search-content dw-mod" id="MobileProductSearchBarContent" data-template="@searchTemplate" data-json-feed="/Default.aspx?ID=@searchFeedId&feedType=productsOnly" data-init-onload="false"></span>
8746 </div>
8747 </div>
8748 </div>
8749 </div>
8750 </div>
8751 }</text>
8752 }
8753 }
8754 }
8755
8756 @using Custom.PhilipsonWine.Security.Helpers
8757 @using Dynamicweb.Frontend
8758
8759 @functions {
8760 public class NewsletterSignupHelperContext
8761 {
8762 public PageView Pageview { get; set; }
8763 public Func<string, int> GetPageIdByNavigationTag { get; set; }
8764 public Func<string, string, string> Translate { get; set; }
8765 }
8766 }
8767
8768 @helper RenderNewsletterSignUp(NewsletterSignupHelperContext context, string origin, string listId, string customThankYouMessage = "")
8769 {
8770 int signupForNewsletterPageId = context.GetPageIdByNavigationTag("SignupForNewsletter");
8771 if (signupForNewsletterPageId > 0 && !string.IsNullOrEmpty(listId))
8772 {
8773 bool isMobile = context.Pageview.Device == Dynamicweb.Frontend.Devices.DeviceType.Mobile;
8774 string translationOrigin = "Custom:" + (isMobile ? "Mobile" : "") + origin + "Signup";
8775 string actionUrl = "/Default.aspx?ID=" + signupForNewsletterPageId;
8776 string placeholderName = context.Translate(translationOrigin + ".Name", "Skriv dit navn");
8777 string placeholderEmail = context.Translate(translationOrigin + ".Email", "Skriv din email");
8778 string url = HttpContext.Current.Request.Url.Scheme + "://" + HttpContext.Current.Request.Url.Host + HttpContext.Current.Request.RawUrl;
8779 string recaptchaSiteKey = RecaptchaHelper.RecaptchaSiteKey;
8780 var user = Dynamicweb.Security.UserManagement.User.GetCurrentFrontendUser();
8781 string userName = user != null ? user.Name : "";
8782 string userEmail = user != null ? user.Email : "";
8783 string wrapperClass = (isMobile ? "mobile-" : "") + origin.ToLower() + "-newsletter-signup-container";
8784 int offersPageId = context.GetPageIdByNavigationTag("OffersPage");
8785
8786 <div class="@wrapperClass js-signup-form-container">
8787 <form class="show-signup-form signup-form js-signup-form" method="post" action="@actionUrl">
8788 <div class="signup-form-container">
8789 <div>
8790 <p class="header-title">@context.Translate(translationOrigin + ".HeaderTitle", "Gå ikke glip af de bedste tilbud!")</p>
8791 <p class="header-text">@context.Translate(translationOrigin + ".HeaderText", "Tilmeld dig vores nyhedsbrev")</p>
8792 </div>
8793 <input required name="name" type="text" value="@HttpUtility.HtmlAttributeEncode(userName)" placeholder="@HttpUtility.HtmlAttributeEncode(placeholderName)" aria-label="@HttpUtility.HtmlAttributeEncode(placeholderName)" autocomplete="given-name" />
8794 <input required name="email" type="email" value="@HttpUtility.HtmlAttributeEncode(userEmail)" placeholder="@HttpUtility.HtmlAttributeEncode(placeholderEmail)" aria-label="@HttpUtility.HtmlAttributeEncode(placeholderEmail)" autocomplete="email" />
8795 <input name="origin" type="hidden" value="@HttpUtility.HtmlAttributeEncode(context.Translate(translationOrigin + ".Tracking.Origin", "Website" + origin + "Signup"))" />
8796 <input name="url" type="hidden" value="@HttpUtility.HtmlAttributeEncode(url)" />
8797 <input name="device" type="hidden" value="@HttpUtility.HtmlAttributeEncode(context.Pageview.Device.ToString())" />
8798 <input name="listId" type="hidden" value="@HttpUtility.HtmlAttributeEncode(listId)" />
8799 <input class="js-newsletter-signup-page-id" name="pageId" type="hidden" value="@HttpUtility.HtmlAttributeEncode(Dynamicweb.Core.Converter.ToString(signupForNewsletterPageId))" />
8800 </div>
8801 @if (RecaptchaHelper.RecaptchaActivated)
8802 {
8803 <input class="js-recaptcha-token-input" name="recaptchaToken" type="hidden" />
8804 <input name="recaptchaSiteKey" type="hidden" value="@HttpUtility.HtmlAttributeEncode(recaptchaSiteKey)" />
8805 <input name="recaptchaAction" type="hidden" value="@HttpUtility.HtmlAttributeEncode(context.Translate(translationOrigin + ".ReCAPTCHA.ActionValue", (isMobile ? "mobile_" : "") + origin.ToLower() + "_signup_newsletter"))" />
8806 <button class="g-recaptcha js-g-recaptcha" data-sitekey="@HttpUtility.HtmlAttributeEncode(recaptchaSiteKey)" data-action="@HttpUtility.HtmlAttributeEncode(context.Translate(translationOrigin + ".ReCAPTCHA.ActionValue", (isMobile ? "mobile_" : "") + origin.ToLower() + "_signup_newsletter"))">@context.Translate(translationOrigin + ".Button", "Tilmeld")</button>
8807 }
8808 else
8809 {
8810 <button>@context.Translate(translationOrigin + ".Button", "Tilmeld")</button>
8811 }
8812 </form>
8813 <div class="hide-signup-form submitted-form-message js-submitted-form-message">
8814 <div>
8815 <p class="header-title">@context.Translate(translationOrigin + ".Submitted.HeaderTitle", "Tak for din tilmelding!")</p>
8816 @if (!string.IsNullOrEmpty(customThankYouMessage))
8817 {
8818 <p class="header-text">@customThankYouMessage</p>
8819 }
8820 else
8821 {
8822 <p class="header-text">@context.Translate(translationOrigin + ".Submitted.HeaderText", "Du er nu tilmeldt vores nyhedsbrev og er en af de første til at modtage vores nye og spændende vintilbud.")</p>
8823 }
8824 </div>
8825 <div class="submitted-form-message-links">
8826 <a href="/">@context.Translate(translationOrigin + ".Submitted.FrontPage", "Gå til forsiden")</a>
8827 @if (offersPageId > 0)
8828 {
8829 <a href="@Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl("Default.aspx?Id=" + offersPageId)">@context.Translate(translationOrigin + ".Submitted.AllOffers", "Se alle tilbud")</a>
8830 }
8831 </div>
8832 <div class="u-hidden u-pointer u-margin-top--lg js-show-signup-form-button">@context.Translate(translationOrigin + ".Submitted.ShowSignupForm", "Se formularen igen")</div>
8833 </div>
8834 </div>
8835 }
8836 }
8837 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
8838
8839 @using System
8840 @using System.Web
8841 @using Dynamicweb.Rapido.Blocks.Extensibility
8842 @using Dynamicweb.Rapido.Blocks
8843 @using Dynamicweb.Rapido.Blocks.Components.General
8844 @using Dynamicweb.Frontend
8845 @using Dynamicweb.Core
8846
8847 @functions {
8848 int impersonationPageId;
8849 string impersonationLayout;
8850 int impersonationFeed;
8851 Block impersonationBar;
8852 bool businessContactImpersonation;
8853
8854 string GetUserNameFromParams(string firstName, string middleName, string lastName, string name, string email, string userName)
8855 {
8856 string username = "";
8857
8858 if (!string.IsNullOrEmpty(firstName) && !string.IsNullOrEmpty(lastName))
8859 {
8860 username = firstName + " " + (!string.IsNullOrEmpty(middleName) ? middleName + " " : "") + lastName;
8861 }
8862 else if (!string.IsNullOrEmpty(name))
8863 {
8864 username = name;
8865 }
8866 else if (!string.IsNullOrEmpty(email))
8867 {
8868 username = email;
8869 }
8870 else
8871 {
8872 username = userName;
8873 }
8874 return username;
8875 }
8876
8877 string GetUserName(UserViewModel user)
8878 {
8879 return GetUserNameFromParams(user.FirstName, user.MiddleName, user.LastName, user.Name, user.Email, user.UserName);
8880 }
8881
8882 string GetUserName(Dynamicweb.Security.UserManagement.User user)
8883 {
8884 return GetUserNameFromParams(user.FirstName, user.MiddleName, user.LastName, user.Name, user.Email, user.UserName);
8885 }
8886 }
8887
8888 @{
8889 impersonationPageId = GetPageIdByNavigationTag("Impersonation");
8890 impersonationLayout = Model.Area.Item.GetItem("Ecommerce").GetList("ImpersonationLayout") != null ? Model.Area.Item.GetItem("Ecommerce").GetList("ImpersonationLayout").SelectedValue : "bar";
8891 impersonationFeed = GetPageIdByNavigationTag("UsersFeed");
8892
8893 businessContactImpersonation = Pageview.User?.CurrentSecondaryUser != null ? Converter.ToBoolean(Pageview.User.CurrentSecondaryUser.CustomFieldValues.FirstOrDefault(x => x.CustomField.SystemName == "AccessUser_SpBcImpersonator")?.Value) : Converter.ToBoolean(Pageview.User?.CustomFieldValues.FirstOrDefault(x => x.CustomField.SystemName == "AccessUser_SpBcImpersonator")?.Value);
8894
8895
8896 if (Model.CurrentUser.ID > 0 && Model.HasSecondaryUsers)
8897 {
8898 impersonationBar = new Block
8899 {
8900 Id = "ImpersonationBar",
8901 SortId = 50,
8902 Template = RenderImpersonation(),
8903 SkipRenderBlocksList = true,
8904 Design = new Design
8905 {
8906 Size = "auto-width",
8907 HidePadding = true,
8908 RenderType = RenderType.Column
8909 }
8910 };
8911
8912 if (impersonationLayout == "top-bar")
8913 {
8914 impersonationBar.SortId = 9;
8915 }
8916
8917 Block impersonationContent = new Block
8918 {
8919 Id = "ImpersonationContent",
8920 SortId = 20
8921 };
8922
8923 if (Model.CurrentSecondaryUser != null && Model.CurrentSecondaryUser.ID > 0)
8924 {
8925 //Render stop impersonation view
8926 impersonationContent.Template = RenderStopImpersonationView();
8927
8928
8929 Modal stopImpersonation = new Modal
8930 {
8931 Id = "StopImpersonation",
8932 Heading = new Heading
8933 {
8934 Level = 2,
8935 Title = Translate("Sign out"),
8936 Icon = new Icon
8937 {
8938 Name = "fa-sign-out",
8939 Prefix = "fas",
8940 LabelPosition = IconLabelPosition.After
8941 }
8942 },
8943 Width = ModalWidth.Sm,
8944 BodyTemplate = RenderStopImpersonationForm()
8945 };
8946
8947 Block stopImpersonationBlock = new Block
8948 {
8949 Id = "StopImpersonationBlock",
8950 SortId = 10,
8951 Component = stopImpersonation
8952 };
8953 impersonationBar.BlocksList.Add(stopImpersonationBlock);
8954 }
8955 else
8956 {
8957 //Render main view
8958 switch (impersonationLayout)
8959 {
8960 case "right-lower-box":
8961 impersonationContent.BlocksList.Add(
8962 new Block
8963 {
8964 Id = "RightLowerBoxHeader",
8965 SortId = 10,
8966 Component = new Heading
8967 {
8968 Level = 5,
8969 Title = Translate("View the list of users you can sign in as"),
8970 CssClass = "impersonation-text"
8971 }
8972 }
8973 );
8974 impersonationContent.BlocksList.Add(
8975 new Block
8976 {
8977 Id = "RightLowerBoxContent",
8978 SortId = 20,
8979 Template = RenderImpersonationControls()
8980 }
8981 );
8982 break;
8983 case "right-lower-bar":
8984 impersonationContent.BlocksList.Add(
8985 new Block
8986 {
8987 Id = "RightLowerBarContent",
8988 SortId = 10,
8989 Template = RenderImpersonationControls()
8990 }
8991 );
8992 break;
8993 case "bar":
8994 default:
8995 impersonationContent.BlocksList.Add(
8996 new Block
8997 {
8998 Id = "ViewListLink",
8999 SortId = 20,
9000 Template = RenderViewListLink()
9001 }
9002 );
9003 impersonationContent.BlocksList.Add(
9004 new Block
9005 {
9006 Id = "BarTypeaheadSearch",
9007 SortId = 30,
9008 Template = RenderTypeaheadSearch()
9009 }
9010 );
9011 break;
9012 }
9013 }
9014 impersonationBar.BlocksList.Add(impersonationContent);
9015
9016 impersonationBar.BlocksList.Add(
9017 new Block
9018 {
9019 Id = "ImpersonationSearchTemplates",
9020 SortId = 30,
9021 Template = RenderSearchResultTemplate()
9022 }
9023 );
9024 if (impersonationLayout != "bar" && impersonationLayout != "top-bar")
9025 {
9026 impersonationBar.BlocksList.Add(
9027 new Block
9028 {
9029 Id = "ImpersonationSearchScripts",
9030 SortId = 40,
9031 Template = RenderSearchScripts()
9032 }
9033 );
9034 }
9035 BlocksPage.GetBlockPage("Master").Add("MasterHeader", impersonationBar);
9036 }
9037 }
9038
9039 @helper RenderImpersonation()
9040 {
9041 List<Block> subBlocks = impersonationBar.BlocksList.OrderBy(item => item.SortId).ToList();
9042 <input type="checkbox" class="impersonation-trigger js-remember-state" id="ImpersonationMinimizeTrigger" />
9043 <div class="impersonation impersonation--@(impersonationLayout)-layout dw-mod" id="Impersonation">
9044 @if (impersonationLayout == "right-lower-box")
9045 {
9046 @RenderRightLowerBoxHeader()
9047 }
9048 <div class="center-container top-container__center-container impersonation__container @(impersonationLayout != "bar" && impersonationLayout != "top-bar" ? "impersonation__container--box" : "") dw-mod">
9049 @*Impersonation*@
9050 @RenderBlockList(subBlocks)
9051 </div>
9052 </div>
9053 }
9054
9055 @helper RenderRightLowerBoxHeader()
9056 {
9057 <div class="impersonation__header dw-mod">
9058 <div class="impersonation__title">@Translate("Impersonation")</div>
9059 <label for="ImpersonationMinimizeTrigger" class="btn btn--impersonation impersonation__minimize-btn dw-mod" onclick="this.blur();">
9060 @Render(new Icon
9061 {
9062 Prefix = "fas",
9063 Name = "fa-window-minimize"
9064 })
9065 </label>
9066 </div>
9067 }
9068
9069 @helper RenderStopImpersonationView()
9070 {
9071 string secondaryUserName = GetUserName(Model.CurrentSecondaryUser);
9072 string userName = GetUserName(Pageview.User);
9073 string impersonationText = "<span class=\"impersonation-light-text dw-mod\">" + Translate("Logged in as") + "</span> <b>" + secondaryUserName + "</b> <span class=\"impersonation-light-text dw-mod\">" + Translate("by") + "</span> <b>" + userName + "</b> ";
9074
9075 if (businessContactImpersonation)
9076 {
9077 impersonationText = "<span class=\"impersonation-light-text dw-mod\">" + Translate("Smartpage:ImpersonationBar.BuyingOnBehalfOf", "Du køber på vegne af") + "</span> <b>" + Model.CurrentUser.Company + "</b>";
9078 }
9079
9080 impersonationText = !businessContactImpersonation ? "<span class=\"impersonation-light-text dw-mod\">" + Translate("Logged in as") + "</span> <b>" + userName + "</b> <span class=\"impersonation-light-text dw-mod\">" + Translate("by") + "</span> <b>" + secondaryUserName + "</b> " : impersonationText;
9081
9082 if (impersonationLayout == "right-lower-box")
9083 {
9084 <div class="u-margin-bottom--lg u-ta-center">
9085 @impersonationText
9086 </div>
9087 <div class="u-margin-bottom--lg u-ta-center">
9088 @RenderSwitchAccountButton()
9089 </div>
9090 @RenderStopImpersonationButton()
9091 }
9092 else
9093 {
9094 <div class="grid grid--align-center impersonation__stop-wrap">
9095 <div class="impersonation-bar-item dw-mod">
9096 @impersonationText
9097 </div>
9098 <div class="impersonation-bar-item dw-mod">
9099 @RenderSwitchAccountButton()
9100 </div>
9101 <div class="impersonation-bar-item dw-mod">
9102 @if (businessContactImpersonation)
9103 {
9104 @RenderStopImpersonation()
9105 }
9106 else
9107 {
9108 @RenderStopImpersonationButton()
9109 }
9110 </div>
9111 </div>
9112 }
9113 }
9114
9115 @helper RenderStopImpersonation()
9116 {
9117 int pageId = Model.TopPage.ID;
9118 <form method="post" class="u-no-margin">
9119 @Render(new Button
9120 {
9121 ButtonType = ButtonType.Submit,
9122 ButtonLayout = ButtonLayout.LinkClean,
9123 Title = businessContactImpersonation ? Translate("Smartpage:Impersonation.DeselectCustomer", "Fravælg kunde") : Translate("Stop impersonation"),
9124 Href = "/Default.aspx?ID=" + pageId,
9125 CssClass = "btn--full",
9126 Icon = new Icon
9127 {
9128 Name = "fa-sign-out",
9129 Prefix = "fal",
9130 LabelPosition = IconLabelPosition.After
9131 },
9132 Name = "DwExtranetRemoveSecondaryUser"
9133 })
9134 </form>
9135 }
9136
9137 @helper RenderSwitchAccountButton()
9138 {
9139 @Render(new Button
9140 {
9141 Href = "/Default.aspx?ID=" + impersonationPageId,
9142 ButtonLayout = ButtonLayout.LinkClean,
9143 Title = businessContactImpersonation ? Translate("Smartpage:Impersonation.ChangeCustomer", "Vælg anden kunde") : Translate("Switch account"),
9144 Icon = new Icon
9145 {
9146 Name = "fa-users",
9147 Prefix = "fal",
9148 LabelPosition = IconLabelPosition.After
9149 },
9150 CssClass = "u-no-margin u-color-inherit"
9151 })
9152 }
9153
9154 @helper RenderStopImpersonationForm()
9155 {
9156 string secondaryUserName = GetUserName(Model.CurrentSecondaryUser);
9157 string userName = GetUserName(Pageview.User);
9158 int pageId = Model.TopPage.ID;
9159
9160 <div class="u-align-center u-margin-bottom-10px u-font-size--sm">@Translate("Smartpage:Impersonation.DeselectCustomerBeforeLogoff", "Du skal først fravælge den valgte kunde før du kan logge ud")</div>
9161
9162 <form method="post" class="u-no-margin">
9163 @if (businessContactImpersonation)
9164 {
9165 @Render(new Button
9166 {
9167 ButtonType = ButtonType.Submit,
9168 ButtonLayout = ButtonLayout.Secondary,
9169 Title = Translate("Smartpage:Impersonation.DeselectCustomer", "Fravælg kunde"),
9170 Href = "/Default.aspx?ID=" + impersonationPageId,
9171 CssClass = "btn--full",
9172 Name = "DwExtranetRemoveSecondaryUser"
9173 })
9174 }
9175 else
9176 {
9177 @Render(new Button
9178 {
9179 ButtonType = ButtonType.Submit,
9180 ButtonLayout = ButtonLayout.Secondary,
9181 Title = Translate("Sign out as") + " " + userName,
9182 Href = "/Default.aspx?ID=" + impersonationPageId,
9183 CssClass = "btn--full",
9184 Name = "DwExtranetRemoveSecondaryUser"
9185 })
9186 }
9187 </form>
9188 }
9189
9190 @helper RenderStopImpersonationButton()
9191 {
9192 @Render(new Button
9193 {
9194 ButtonType = ButtonType.Button,
9195 ButtonLayout = ButtonLayout.LinkClean,
9196 Title = Translate("Sign out"),
9197 Icon = new Icon
9198 {
9199 Name = "fa-sign-out",
9200 Prefix = "fal",
9201 LabelPosition = IconLabelPosition.After
9202 },
9203 OnClick = "document.getElementById('StopImpersonationModalTrigger').checked = true",
9204 CssClass = "u-no-margin"
9205 })
9206 }
9207
9208 @helper RenderImpersonationControls()
9209 {
9210 <div class="impersonation__controls">
9211 @RenderViewListLink()
9212 @RenderSearchBox()
9213 </div>
9214 @RenderResultsList()
9215 }
9216
9217 @helper RenderViewListLink()
9218 {
9219 string title = impersonationLayout == "right-lower-box" ? Translate("View the list") : Translate("View the list of users you can sign in as");
9220
9221 if (businessContactImpersonation)
9222 {
9223 title = Translate("Smartpage:ImpersonationBar.ViewUsersList", "Vis listen med kunder du kan købe på vegne af");
9224 }
9225
9226 string buttonClasses = impersonationLayout == "right-lower-box" ? "impersonation__button btn btn--impersonation" : "impersonation__link impersonation__link";
9227
9228 @Render(new Link
9229 {
9230 ButtonLayout = ButtonLayout.None,
9231 Title = title,
9232 Href = "/Default.aspx?ID=" + impersonationPageId,
9233 CssClass = buttonClasses
9234 })
9235 }
9236
9237 @helper RenderSearchBox()
9238 {
9239 <div class="impersonation__search-wrap">
9240 <input placeholder="@Translate("Search users")" type="text" class="impersonation__search-field dw-mod" onkeyup="searchKeyUpHandler(event)" id="ImpersonationBoxSearchField">
9241 <div id="ImpersonationBoxSearchFind" class="impersonation__search-icon dw-mod" onclick="updateResults(document.getElementById('ImpersonationBoxSearchField').value)">
9242 <i class="fal fa-search"></i>
9243 </div>
9244 <div id="ImpersonationBoxSearchClear" class="impersonation__search-icon u-hidden dw-mod" onclick="clearResults();">
9245 <i class="fal fa-times"></i>
9246 </div>
9247 </div>
9248 }
9249
9250 @helper RenderTypeaheadSearch()
9251 {
9252 <div class="typeahead u-ta-right impersonation__typeahead js-typeahead dw-mod" id="ImpersonationSearchBar"
9253 data-page-size="5"
9254 data-search-feed-id="@impersonationFeed"
9255 data-result-page-id="@impersonationPageId"
9256 data-search-type="user-search"
9257 data-search-parameter-name="q">
9258
9259 <div class="typeahead-search-field">
9260 <input type="text" class="u-no-margin u-full-width js-typeahead-search-field" placeholder="@HttpUtility.HtmlAttributeEncode(businessContactImpersonation ? Translate("Search customers") : Translate("Search users"))">
9261 <ul class="dropdown dropdown--absolute-position u-min-w220px u-full-width js-handlebars-root js-typeahead-search-content dw-mod" id="ImpersonationSearchBarContent" data-template="ImpersonationSearchResult" data-json-feed="/Default.aspx?ID=@impersonationFeed" data-init-onload="false"></ul>
9262 </div>
9263 </div>
9264 }
9265
9266 @helper RenderResultsList()
9267 {
9268 <ul id="ImpersonationBoxSearchResults" class="impersonation__search-results js-handlebars-root dw-mod" data-template="ImpersonationSearchResult" data-json-feed="/Default.aspx?ID=@impersonationFeed" data-init-onload="false" data-preloader="minimal"></ul>
9269 }
9270
9271 @helper RenderSearchResultTemplate()
9272 {
9273 <script id="ImpersonationSearchResult" type="text/x-template">
9274 {{#.}}
9275 {{#Users}}
9276 <li class="impersonation__search-results-item impersonation-user">
9277 <form method="post" class="impersonation-user__form" name="account{{id}}">
9278 <input type="hidden" id="DWExtranetSecondaryUserSelector" name="DWExtranetSecondaryUserSelector" value="{{id}}">
9279 @if (businessContactImpersonation)
9280 {
9281 <div class="impersonation-user__info">
9282 <div class="impersonation-user__name">{{company}}</div>
9283 <div class="impersonation-user__number">{{customerNumber}}</div>
9284 </div>
9285
9286 @Render(new Button
9287 {
9288 ButtonType = ButtonType.Submit,
9289 ButtonLayout = ButtonLayout.Secondary,
9290 Title = Translate("Smartpage:Impersonation.SelectCustomer", "Vælg kunde"),
9291 CssClass = "impersonation-user__sign-in-btn u-pull--right u-no-margin"
9292 });
9293 }
9294 else
9295 {
9296 <div class="impersonation-user__info">
9297 <div class="impersonation-user__name">{{userName}}</div>
9298 <div class="impersonation-user__number">{{customerNumber}}</div>
9299 </div>
9300
9301 @Render(new Button
9302 {
9303 ButtonType = ButtonType.Submit,
9304 ButtonLayout = ButtonLayout.Secondary,
9305 Title = Translate("Sign in as"),
9306 CssClass = "impersonation-user__sign-in-btn u-pull--right u-no-margin"
9307 });
9308 }
9309 </form>
9310 </li>
9311 {{/Users}}
9312 {{#unless Users}}
9313 <li class="impersonation__search-results-item impersonation__search-results-item--not-found">
9314 @Translate("Your search gave 0 results")
9315 </li>
9316 {{/unless}}
9317 {{/.}}
9318 </script>
9319 }
9320
9321 @helper RenderSearchScripts()
9322 {
9323 <script>
9324 let inputDelayTimer;
9325 function searchKeyUpHandler(e) {
9326 clearTimeout(inputDelayTimer);
9327 let value = e.target.value;
9328 if (value != "") {
9329 inputDelayTimer = setTimeout(function () {
9330 updateResults(value);
9331 }, 500);
9332 } else {
9333 clearResults();
9334 }
9335 };
9336
9337 function updateResults(value) {
9338 if (value == "") {
9339 return null;
9340 }
9341 HandlebarsBolt.UpdateContent("ImpersonationBoxSearchResults", "/Default.aspx?ID=@impersonationFeed&q=" + value);
9342 document.getElementById("ImpersonationBoxSearchFind").classList.add("u-hidden");
9343 document.getElementById("ImpersonationBoxSearchClear").classList.remove("u-hidden");
9344 }
9345
9346 function clearResults() {
9347 document.getElementById("ImpersonationBoxSearchField").value = "";
9348 HandlebarsBolt.CleanContainer("ImpersonationBoxSearchResults");
9349 document.getElementById("ImpersonationBoxSearchFind").classList.remove("u-hidden");
9350 document.getElementById("ImpersonationBoxSearchClear").classList.add("u-hidden");
9351 }
9352 </script>
9353 }
9354 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
9355
9356 @using System
9357 @using System.Web
9358 @using System.Collections.Generic
9359 @using Dynamicweb.Rapido.Blocks.Extensibility
9360 @using Dynamicweb.Rapido.Blocks
9361
9362 @{
9363 BlocksPage miniCartBlocksPage = BlocksPage.GetBlockPage("Master");
9364 string orderlinesView = Model.Area.Item.GetItem("Ecommerce").GetItem("MiniCart").GetList("OrderlinesView") != null ? Model.Area.Item.GetItem("Ecommerce").GetItem("MiniCart").GetList("OrderlinesView").SelectedValue : "table";
9365
9366 Block orderLines = new Block
9367 {
9368 Id = "MiniCartOrderLines",
9369 SkipRenderBlocksList = true,
9370 BlocksList = new List<Block>
9371 {
9372 new Block {
9373 Id = "MiniCartOrderLinesList",
9374 SortId = 20,
9375 Template = RenderMiniCartOrderLinesList()
9376 }
9377 }
9378 };
9379
9380 Block orderlinesScriptTemplates = new Block
9381 {
9382 Id = "OrderlinesScriptTemplates"
9383 };
9384
9385 if (orderlinesView == "table")
9386 {
9387 orderLines.Template = RenderMiniCartOrderLinesTable();
9388 orderLines.BlocksList.Add(
9389 new Block
9390 {
9391 Id = "MiniCartOrderlinesTableHeader",
9392 SortId = 10,
9393 Template = RenderMiniCartOrderLinesHeader()
9394 }
9395 );
9396
9397 orderlinesScriptTemplates.Template = RenderMiniCartScriptsTableTemplates();
9398 }
9399 else
9400 {
9401 orderLines.Template = RenderMiniCartOrderLinesBlocks();
9402 orderlinesScriptTemplates.Template = RenderMiniCartScriptsListTemplates();
9403 }
9404
9405 miniCartBlocksPage.Add("MasterBottomSnippets", orderlinesScriptTemplates);
9406
9407 Block miniCartScriptTemplates = new Block()
9408 {
9409 Id = "MasterMiniCartTemplates",
9410 SortId = 1,
9411 Template = RenderMiniCartScriptTemplates(),
9412 SkipRenderBlocksList = true,
9413 BlocksList = new List<Block>
9414 {
9415 orderLines,
9416 new Block {
9417 Id = "MiniCartFooter",
9418 Template = RenderMiniCartFooter(),
9419 SortId = 50,
9420 SkipRenderBlocksList = true,
9421 BlocksList = new List<Block>
9422 {
9423 new Block {
9424 Id = "MiniCartSubTotal",
9425 Template = RenderMiniCartSubTotal(),
9426 SortId = 30
9427 },
9428 new Block {
9429 Id = "MiniCartFees",
9430 Template = RenderMiniCartFees(),
9431 SortId = 40
9432 },
9433 new Block {
9434 Id = "MiniCartPoints",
9435 Template = RenderMiniCartPoints(),
9436 SortId = 50
9437 },
9438 new Block {
9439 Id = "MiniCartTotal",
9440 Template = RenderMiniCartTotal(),
9441 SortId = 60
9442 },
9443 new Block {
9444 Id = "MiniCartDisclaimer",
9445 Template = RenderMiniCartDisclaimer(),
9446 SortId = 70
9447 },
9448 new Block {
9449 Id = "MiniCartActions",
9450 Template = RenderMiniCartActions(),
9451 SortId = 80
9452 }
9453 }
9454 }
9455 }
9456 };
9457
9458 miniCartBlocksPage.Add("MasterBottomSnippets", miniCartScriptTemplates);
9459 }
9460
9461 @helper RenderMiniCartScriptsTableTemplates()
9462 {
9463 <script id="MiniCartOrderline" type="text/x-template">
9464 {{#unless isEmpty}}
9465 <tr>
9466 <td class="u-w60px"><a href="{{link}}" class="{{hideimage}}"><img src="/Admin/Public/GetImage.ashx?width=50&height=50&crop=5&Compression=75&image={{image}}" alt="{{name}}" title="{{name}}"></a></td>
9467 <td class="u-va-middle">
9468 {{#if note}}
9469 <span class="mini-cart-note">{{note}}</span>
9470 {{/if}}
9471 <a href="{{link}}" class="mini-cart-orderline__name" title="{{name}}">{{name}}</a>
9472 {{#if variantname}}
9473 <a href="{{link}}" class="mini-cart-orderline__name mini-cart-orderline__name--sm">{{variantname}}</a>
9474 {{/if}}
9475 {{#if unitname}}
9476 <div class="mini-cart-orderline__name mini-cart-orderline__name--sm">{{unitname}}</div>
9477 {{/if}}
9478 </td>
9479 <td class="u-ta-right u-va-middle">{{quantity}}</td>
9480 <td class="u-ta-right u-va-middle">
9481 {{#if pointsTotal}}
9482 <span class="u-color--loyalty-points">{{pointsTotal}}</span> @Translate("points")
9483 {{else}}
9484 {{totalprice}}
9485 {{/if}}
9486 </td>
9487 </tr>
9488 {{/unless}}
9489 </script>
9490
9491 <script id="MiniCartOrderlineDiscount" type="text/x-template">
9492 {{#unless isEmpty}}
9493 <tr class="table__row--no-border">
9494 <td class="u-w60px">
9495 {{#if image}}
9496 @Render(new Image { Path = "{{image}}", Title = "{{name}} {{variantname}}", ImageDefault = new ImageSettings { Width = 60, Height = 60, Crop = 5 }, CssClass = "u-middle-horizontal" })
9497 {{/if}}
9498 </td>
9499 <td><div class="mini-cart-orderline__name dw-mod">{{name}}</div></td>
9500 <td class="u-ta-right"> </td>
9501 <td class="u-ta-right">{{totalprice}}</td>
9502 </tr>
9503 {{/unless}}
9504 </script>
9505
9506 <script id="MiniPmxCartOrderline" type="text/x-template">
9507 {{#unless isEmpty}}
9508 <tr class="table__row--no-border">
9509 <td class="u-w60px">
9510 @Render(new Image { Path = "/Admin/Public/GetImage.ashx?Width=115&Height=115&Crop=5&DoNotUpscale=True&FillCanvas=False&Image=/Files/Images/philipsonwine/pickandmix/Kasse.png", Title = Translate("Smartpage:Checkout.PMXCart.Name", "Din egen vinkasse"), DisableImageEngine = true, CssClass = "product-image" })
9511 </td>
9512 <td class="u-va-middle">
9513 <span class="mini-cart-orderline__name">@Translate("Smartpage:Checkout.PMXCart.Name", "Din egen vinkasse") {{nr}}</span>
9514 <div class="mini-cart-orderline__name mini-cart-orderline__name--sm">@Translate("Smartpage:Checkout.PMXCart.TopText", "Pick and mix")</div>
9515 </td>
9516 <td class="u-ta-right u-va-middle">{{quantity}}</td>
9517 <td class="u-ta-right u-va-middle">
9518 {{totalPriceClean}}
9519 </td>
9520 </tr>
9521 {{/unless}}
9522 </script>
9523 }
9524
9525 @helper RenderMiniCartScriptsListTemplates()
9526 {
9527 int cartFeedPageId = GetPageIdByNavigationTag("MiniCartFeed");
9528
9529 <script id="MiniCartOrderline" type="text/x-template">
9530 {{#unless isEmpty}}
9531 <div class="mini-cart-orderline grid dw-mod">
9532 <div class="grid__col-4">
9533 <a href="{{link}}" class="{{hideimage}}">
9534 @{
9535 string imageEngine = "/Admin/Public/GetImage.ashx?width=100&height=100&crop=5&Compression=75&image={{image}}";
9536
9537 // CDN
9538 var cdnUrl = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetString("CDNUrl");
9539 bool cdnActivate = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetBoolean("CDNActivate");
9540 if (!string.IsNullOrWhiteSpace(cdnUrl) && cdnActivate)
9541 {
9542 imageEngine = cdnUrl + imageEngine;
9543 }
9544 }
9545 <img class="b-lazy" src="/Files/Images/placeholder.gif" data-src="@imageEngine" alt="{{name}}" title="{{name}}">
9546 </a>
9547 </div>
9548 <div class="grid__col-8">
9549 <a href="{{link}}" class="mini-cart-orderline__name mini-cart-orderline__name--truncate mini-cart-orderline__name--md u-padding-right--lg" title="{{name}}">{{name}}</a>
9550 {{#if variantname}}
9551 <div class="mini-cart-orderline__name mini-cart-orderline__name--sm dw-mod">@Translate("Variant"): {{variantname}}</div>
9552 {{/if}}
9553 {{#if unitname}}
9554 <div class="mini-cart-orderline__name mini-cart-orderline__name--sm dw-mod">@Translate("Unit"): {{unitname}}</div>
9555 {{/if}}
9556 <div class="mini-cart-orderline__name mini-cart-orderline__name--sm dw-mod">@Translate("Qty"): {{quantity}}</div>
9557
9558 <div class="grid__cell-footer">
9559 <div class="grid__cell">
9560 <div class="u-pull--left mini-cart-orderline__price dw-mod">
9561 {{#if pointsTotal}}
9562 <span class="u-color--loyalty-points">{{pointsTotal}}</span> @Translate("points")
9563 {{else}}
9564 {{totalprice}}
9565 {{/if}}
9566 </div>
9567 <button type="button"
9568 title="@Translate("Remove orderline")"
9569 class="btn btn--clean btn--condensed u-pull--right mini-cart-orderline__remove-btn dw-mod"
9570 onclick="{{#if googleImpression}}googleImpressionRemoveFromCart({{googleImpression}});{{/if}}Cart.UpdateCart('miniCartContent', '/Default.aspx?ID=@cartFeedPageId', 'CartCmd=DelOrderLine&key={{id}}&redirect=false', true);">
9571 @Translate("Remove")
9572 </button>
9573 </div>
9574 </div>
9575 </div>
9576 </div>
9577 {{/unless}}
9578 </script>
9579
9580 <script id="MiniCartOrderlineDiscount" type="text/x-template">
9581 {{#unless isEmpty}}
9582 <div class="mini-cart-orderline mini-cart-orderline--discount grid dw-mod">
9583 <div class="grid__col-8">
9584 <div class="mini-cart-orderline__name mini-cart-orderline__name dw-mod">{{name}}</div>
9585 </div>
9586 <div class="grid__col-4 u-align-right">{{totalprice}}</div>
9587 </div>
9588 {{/unless}}
9589 </script>
9590 }
9591
9592 @helper RenderMiniCartScriptTemplates()
9593 {
9594 List<Block> subBlocks = this.masterPage.GetBlockListById("MasterMiniCartTemplates").OrderBy(item => item.SortId).ToList();
9595 bool useGoogleTagManager = !string.IsNullOrEmpty(Pageview.AreaSettings.GetItem("Settings").GetString("GoogleTagManagerID"));
9596 string cartPageLink = string.Concat("/Default.aspx?ID=", GetPageIdByNavigationTag("CartPage"));
9597 bool miniCartUseGoogleTagManager = !string.IsNullOrEmpty(Pageview.AreaSettings.GetItem("Settings").GetString("GoogleTagManagerID"));
9598
9599 <script id="MiniCartContent" type="text/x-template">
9600 {{#.}}
9601 {{#unless isEmpty}}
9602 @if (miniCartUseGoogleTagManager)
9603 {
9604 <text>{{{googleEnchantImpressionEmptyCart OrderLines}}}</text>
9605 }
9606 @RenderBlockList(subBlocks)
9607 {{/unless}}
9608 {{/.}}
9609 </script>
9610 }
9611
9612 @helper RenderMiniCartOrderLinesTable()
9613 {
9614 List<Block> subBlocks = this.masterPage.GetBlockListById("MiniCartOrderLines").OrderBy(item => item.SortId).ToList();
9615
9616 <div class="u-overflow-auto">
9617 <table class="table mini-cart-table dw-mod">
9618 @RenderBlockList(subBlocks)
9619 </table>
9620 </div>
9621 }
9622
9623 @helper RenderMiniCartOrderLinesBlocks()
9624 {
9625 List<Block> subBlocks = this.masterPage.GetBlockListById("MiniCartOrderLines").OrderBy(item => item.SortId).ToList();
9626
9627 <div class="u-overflow-auto">
9628 @RenderBlockList(subBlocks)
9629 </div>
9630 }
9631
9632 @helper RenderMiniCartOrderLinesHeader()
9633 {
9634 <thead>
9635 <tr>
9636 <td> </td>
9637 <td>@Translate("Product")</td>
9638 <td class="u-ta-right">@Translate("Qty")</td>
9639 <td class="u-ta-right" width="150">@Translate("Price")</td>
9640 </tr>
9641 </thead>
9642 }
9643
9644 @helper RenderMiniCartOrderLinesList()
9645 {
9646 <text>
9647 {{#OrderLines}}
9648 {{#ifCond template "===" "CartOrderline"}}
9649 {{>MiniCartOrderline}}
9650 {{/ifCond}}
9651 {{#ifCond template "===" "CartOrderlineMobile"}}
9652 {{>MiniCartOrderline}}
9653 {{/ifCond}}
9654 {{#ifCond template "===" "CartOrderlineDiscount"}}
9655 {{>MiniCartOrderlineDiscount}}
9656 {{/ifCond}}
9657 {{/OrderLines}}
9658 {{#PickAndMixOrderLines}}
9659 {{>MiniPmxCartOrderline}}
9660 {{/PickAndMixOrderLines}}
9661 </text>
9662 }
9663
9664 @helper RenderMiniCartFees()
9665 {
9666 bool pointShop = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly");
9667 if (!pointShop)
9668 {
9669 <text>
9670 {{#unless hidePaymentfee}}
9671 <div class="grid">
9672 <div class="grid__col-6 grid__col--bleed-y">
9673 {{paymentmethod}}
9674 </div>
9675 <div class="grid__col-6 grid__col--bleed-y grid--align-end">{{paymentfee}}</div>
9676 </div>
9677 {{/unless}}
9678 </text>
9679 }
9680 <text>
9681 {{#unless hideShippingfee}}
9682 {{#if shippingmethod}}
9683 <div class="grid">
9684 <div class="grid__col-6 grid__col--bleed-y">
9685 {{shippingmethod}}
9686 </div>
9687 <div class="grid__col-6 grid__col--bleed-y grid--align-end">{{shippingfee}}</div>
9688 </div>
9689 {{/if}}
9690 {{/unless}}
9691 </text>
9692 <text>
9693 {{#if hasTaxSettings}}
9694 <div class="grid">
9695 <div class="grid__col-6 grid__col--bleed-y">@Translate("Sales Tax")</div>
9696 <div class="grid__col-6 grid__col--bleed-y grid--align-end">{{totaltaxes}}</div>
9697 </div>
9698 {{/if}}
9699 </text>
9700 <text>
9701 {{#customerStockOrderlines}}
9702 <div class="grid">
9703 <div class="grid__col-6 grid__col--bleed-y">
9704 {{Description}}
9705 </div>
9706 <div class="grid__col-6 grid__col--bleed-y grid--align-end">{{Fee}}</div>
9707 </div>
9708 {{/customerStockOrderlines}}
9709 </text>
9710 }
9711
9712 @helper RenderMiniCartFooter()
9713 {
9714 List<Block> subBlocks = this.masterPage.GetBlockListById("MiniCartFooter").OrderBy(item => item.SortId).ToList();
9715
9716 <div class="mini-cart__footer u-border-top u-padding-top dw-mod">
9717 @RenderBlockList(subBlocks)
9718 </div>
9719 }
9720
9721 @helper RenderMiniCartActions()
9722 {
9723 int cartPageId = GetPageIdByNavigationTag("CartPage");
9724
9725 <button type="button" title="@Translate("Empty cart")" class="btn btn--secondary u-full-width dw-mod u-no-margin u-margin-bottom" onclick="googleEnchantImpressionEmptyCart(); Cart.EmptyCart(event);">@Translate("Empty cart")</button>
9726 <a href="/Default.aspx?ID=@cartPageId" title="@Translate("Proceed to checkout")" class="btn btn--primary u-full-width u-no-margin dw-mod">@Translate("Proceed to checkout")</a>
9727 }
9728
9729 @helper RenderMiniCartPoints()
9730 {
9731 <text>
9732 {{#if earnings}}
9733 <div class="grid">
9734 <div class="grid__col-6 grid__col--bleed-y">@Translate("Earnings")</div>
9735 <div class="grid__col-6 grid__col--bleed-y grid--align-end">
9736 <div>
9737 <span class="u-color--loyalty-points">{{earnings}}</span> @Translate("points")
9738 </div>
9739 </div>
9740 </div>
9741 {{/if}}
9742 </text>
9743 }
9744
9745 @helper RenderMiniCartSubTotal()
9746 {
9747 bool hasTaxSettings = Dynamicweb.Rapido.Services.Countries.HasTaxSettings(Model.Cart.ID);
9748 bool pointShop = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly");
9749 if (!pointShop)
9750 {
9751 <text>
9752 {{#unless hideSubTotal}}
9753 <div class="grid dw-mod u-bold">
9754 <div class="grid__col-6 grid__col--bleed-y">@Translate("Subtotal")</div>
9755 <div class="grid__col-6 grid__col--bleed-y grid--align-end">
9756 @if (hasTaxSettings)
9757 {
9758 <text>{{subtotalpricewithouttaxes}}</text>
9759 }
9760 else
9761 {
9762 <text>{{subtotalprice}}</text>
9763 }
9764 </div>
9765 </div>
9766 {{/unless}}
9767 </text>
9768 }
9769 }
9770
9771 @helper RenderMiniCartTotal()
9772 {
9773 bool pointShop = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly");
9774
9775 <div class="mini-cart-totals grid u-border-top u-margin-top dw-mod">
9776 <div class="grid__col-6">@Translate("Total")</div>
9777 <div class="grid__col-6 grid--align-end">
9778 <div>
9779 @if (pointShop)
9780 {
9781 <span class="u-color--loyalty-points">{{pointsUsedInCart}}</span> @Translate("points")
9782 }
9783 else
9784 {
9785 <text>{{totalprice}}</text>
9786 }
9787 </div>
9788 </div>
9789 </div>
9790 }
9791
9792 @helper RenderMiniCartDisclaimer()
9793 {
9794 <text>
9795 {{#if showCheckoutDisclaimer}}
9796 <div class="grid u-margin-bottom u-ta-right">
9797 <small class="grid__col-12">{{checkoutDisclaimer}}</small>
9798 </div>
9799 {{/if}}
9800 </text>
9801 }
9802 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
9803 @using Dynamicweb.Rapido.Blocks
9804 @using Dynamicweb.Rapido.Blocks.Components.General
9805 @using Custom.StockHandler.Models.ViewModels
9806 @using Smartpage.Relewise.Services.Models
9807
9808 @using Dynamicweb.Ecommerce.ProductCatalog
9809 @using Dynamicweb.Rendering
9810 @using Dynamicweb.Core
9811 @using System
9812 @using System.Web
9813 @using System.Collections.Generic
9814 @using Dynamicweb.Rapido.Blocks
9815 @using Dynamicweb.Rapido.Blocks.Components
9816 @using Dynamicweb.Rapido.Blocks.Components.General
9817 @using Dynamicweb.Rapido.Services
9818 @using Smartpage.PhilipsonWine.PickNMix.Helper;
9819
9820 @helper GridView(Dynamicweb.Frontend.ItemViewModel gridViewSettings)
9821 {
9822 string facetsBlockViewMode = !String.IsNullOrEmpty(Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("ProductList").GetString("FacetsViewMode")) ? Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("ProductList").GetString("FacetsViewMode").ToLower() : "left";
9823 bool isTopFacets = facetsBlockViewMode == "top";
9824 int columnsCount = Dynamicweb.Context.Current.Request["ID"] == Dynamicweb.Core.Converter.ToString(GetPageIdByNavigationTag("EventsPage")) ? 4 : isTopFacets ? 3 : (gridViewSettings.GetList("Columns") != null ? Converter.ToInt32(gridViewSettings.GetList("Columns").SelectedValue) : 3);
9825 string imageZoomOnHover = gridViewSettings.GetBoolean("HoverImageZoom") ? "image-hover--zoom" : "";
9826 <script id="ProductGridItemContainer" type="text/x-template">
9827 {{#.}}
9828 {{#unless ispickMixProductContainer}}
9829 <div id="Product{{id}}" data-template="GridViewItem" data-preloader="overlay" class="grid__col-lg-@(12 / columnsCount) grid__col-md-6 grid__col-sm-6 grid__col-xs-6 product-list__grid-item @imageZoomOnHover dw-mod product-list-product js-product-list-product {{bannerIsActiveClass}}" style="{{#Banner}}{{bannerStyle}}{{/Banner}}">
9830 {{#Product}}
9831 {{>GridViewItem}}
9832 {{/Product}}
9833 {{#Banner}}
9834 {{>GridViewItemBanner}}
9835 {{/Banner}}
9836 </div>
9837 {{/unless}}
9838
9839 {{/.}}
9840 </script>
9841 }
9842
9843 @helper RenderGridViewItemBanner()
9844 {
9845 <script id="GridViewItemBanner" type="text/x-template">
9846 <div class="grid__col--auto product-scroll-trigger u-no-padding u-full-height u-grey-border u-white-background @(Pageview.Device.ToString() == "Desktop" ? "u-padding-sides-8px" : "") banner-grid {{textPlacement}}" style="background: url('{{bannerImage}}'); background-size: cover;">
9847 <div class="grid__col-12 u-padding-sides-8px banner-text-padding">
9848 {{#if bannerTeaserText}}
9849 <div>
9850 <p style="color: {{bannerTextColor}}" class="banner-teaser-text u-padding-sides-8px">{{{bannerTeaserText}}}</p>
9851 </div>
9852 {{/if}}
9853 {{#if bannerText}}
9854 <div>
9855 <p style="color: {{bannerTextColor}}" class="banner-text u-padding-sides-8px">{{{bannerText}}}</p>
9856 </div>
9857 {{/if}}
9858 {{#if showDivider}}
9859 <hr class="banner-divider-line" />
9860 {{/if}}
9861 {{#if uspItems}}
9862 <div class="banner-usp-container">
9863 {{#each uspItems}}
9864 <div class="banner-usp">
9865 {{#if this.Icon}}
9866 <img class="banner-usp-icon" src="{{this.Icon}}" />
9867 {{/if}}
9868 {{#if this.Label}}
9869 <p class="banner-usp-label">{{this.Label}}</p>
9870 {{/if}}
9871 </div>
9872 {{/each}}
9873 </div>
9874 {{/if}}
9875 {{#if showButton}}
9876 <div class="grid__col-8 btn-banner-wrapper">
9877 <a class="btn btn-banner u-padding-sides-8px" href="{{bannerButtonLink}}">{{bannerButtonText}}</a>
9878 </div>
9879 {{/if}}
9880 </div>
9881 </div>
9882 </script>
9883 }
9884
9885 @helper RenderGridViewItem(BlocksPage page)
9886 {
9887 List<Block> subBlocks = page.GetBlockListById("GridViewItem");
9888 int sliderSpeed = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetInt32("IconSliderSpeed") != 0 ? Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetInt32("IconSliderSpeed") : 3000;
9889
9890 <script id="GridViewItem" type="text/x-template">
9891 {{#.}}
9892 <div class="grid-card{{#if useCustomCocktailProductCardDesign}} cocktail-product-grid-card{{/if}}">
9893 <div class="grid__col--auto js-product-scroll-trigger product-scroll-trigger u-no-padding u-full-height{{#if useCustomCocktailProductCardDesign}} cocktail-pack-product{{else}} u-white-background{{/if}}" data-params="{{googleImpression}}" style="{{RecommendationProductCardBackgroundColor}}">
9894 {{#unless RecommendationDisplayAsGrid}}
9895 {{>RenderBadges}}
9896 {{>RenderLabels}}
9897 {{/unless}}
9898 @RenderBlockList(subBlocks)
9899 </div>
9900
9901 {{#if RecommendationActivatePodium}}
9902 {{#if RecommendationDisplayAsGrid}}
9903 <span class="recommendation-podium-rank {{RecommendationPodiumRankClasses}}" style="{{RecommendationPodiumRankSize}}{{RecommendationPodiumRankGradientColor}}">{{RecommendationPodiumRank}}</span>
9904 {{/if}}
9905 {{/if}}
9906 </div>
9907 {{/.}}
9908 </script>
9909
9910 <script id="RenderBadges" type="text/x-template">
9911 <div class="productlist-badges">
9912 @RenderGridViewItemStickers()
9913 {{#ExpertRatings}}
9914 {{#if isFreeText}}
9915 <div class="rating-badge c100">
9916 <span class="rating-badge--score__freetext">{{text}}</span>
9917 </div>
9918 {{else}}
9919 {{#if isInterval}}
9920 <div class="rating-badge c100">
9921 <span class="rating-badge--score__interval">{{{text}}}</span>
9922 <span class="rating-badge--text">{{name}}</span>
9923 </div>
9924 {{else}}
9925 <div class="rating-badge c100">
9926 <span class="rating-badge--score">{{{text}}}</span>
9927 <span class="rating-badge--text">{{name}}</span>
9928 </div>
9929 {{/if}}
9930 {{/if}}
9931 {{/ExpertRatings}}
9932 {{#if CustomerRatingActive}}
9933 <div class="rating-badge customer-rating">
9934 <span class="rating-badge--score">{{{CustomerRatingInText}}}</span>
9935 <div class="customer-ratings-container">
9936 <div class="js-stars stars" data-average-rating="{{CustomerRatingInText}}">
9937 <i class="fas fa-star js-star star"></i>
9938 <i class="fas fa-star js-star star"></i>
9939 <i class="fas fa-star js-star star"></i>
9940 <i class="fas fa-star js-star star"></i>
9941 <i class="fas fa-star js-star star"></i>
9942 </div>
9943 </div>
9944 <span class="rating-badge--text">({{CustomerRatingCount}} {{CustomerRatingCountText}})</span>
9945 </div>
9946 {{/if}}
9947 </div>
9948 </script>
9949
9950 <script id="RenderLabels" type="text/x-template">
9951 <div class="label-container">
9952 {{#if bomQuantity}}
9953 <div class="top-label">
9954 <span class="top-label__bom-quantity">{{{bomQuantity}}}</span>
9955 </div>
9956 {{/if}}
9957 {{#Labels}}
9958 <div class="top-label">
9959 <div class="top-label__label top-label__label" style="background-color:{{labelBgColor}}; color:{{labelTextColor}}">
9960 {{labelText}}
9961 {{#if tooltipText}}
9962 <i class="fal fa-question-circle info-icon js-tooltip tooltip-icon tooltip-icon--product-list" data-tooltip-placement="{{tooltipPlacement}}" data-tooltip-content="{{tooltipText}}"></i>
9963 {{/if}}
9964 </div>
9965 </div>
9966 {{/Labels}}
9967 </div>
9968 </script>
9969
9970 }
9971
9972 @helper RenderGridViewItemHiddenProperties()
9973 {
9974 <input type="hidden" name="ProductLoopCounter{{id}}" value="{{id}}" />
9975 @*<input type="hidden" name="ProductID{{id}}" value="{{productId}}" />*@
9976 <input type="hidden" name="VariantID{{id}}" value="{{variantid}}" id="Variant_{{id}}" />
9977 <input type="hidden" name="UnitID{{id}}" value="{{unitId}}" id="Unit_{{id}}" />
9978 }
9979
9980 @helper RenderGridViewItemImageContainer(BlocksPage page)
9981 {
9982 List<Block> subBlocks = page.GetBlockListById("GridViewItemImageContainer");
9983
9984 <div class="product-list__grid-item__image dw-mod {{#if RecommendationProductCardBackgroundColor}}u-transparent-background{{/if}} {{noImage}} {{#if RecommendationActivatePodium}}{{#unless RecommendationDisplayAsGrid}}u-position-relative{{/unless}}{{/if}}">
9985 @RenderBlockList(subBlocks)
9986 </div>
9987 }
9988
9989 @helper RenderGridViewItemImage()
9990 {
9991 <text>
9992 {{#if isPickAndMixPage}}
9993 <div class="grid-image-container pmx-grid-image-container">
9994 <div class="grid-image pmx-modal-trigger js-pmx-modal-trigger" style="background-image: -webkit-linear-gradient(rgba(255, 255, 255, 0), rgba(0, 0, 0, 0.03)), url('{{image}}');" data-product-id="{{productId}}"></div>
9995 </div>
9996 {{else}}
9997 <a href="{{link}}"
9998 onclick="Scroll.SavePosition(event); {{#if googleImpression}}googleEnchantImpressionClick({{googleImpression}}, event){{/if}}"
9999 title="{{{name}}}"
10000 class="u-block u-position-relative image-hover__wrapper dw-mod">
10001 <div class="grid-image-container{{#if eventProduct}} event-grid-image-container{{/if}}{{#if useCustomCocktailProductCardDesign}} cocktail-grid-image-container{{/if}}">
10002 <div class="grid-image" style="background-image: {{#unless eventProduct}}{{#unless cocktailProduct}}{{#unless RecommendationProductCardBackgroundColor}}-webkit-linear-gradient(rgba(255, 255, 255, 0), rgba(0, 0, 0, 0.03)),{{/unless}}{{/unless}}{{/unless}} url('{{image}}');" alt="{{name}}"></div>
10003 </div>
10004 </a>
10005 {{#if RecommendationActivatePodium}}
10006 {{#unless RecommendationDisplayAsGrid}}
10007 <span class="recommendation-podium-rank {{RecommendationPodiumRankClasses}}" style="{{RecommendationPodiumRankSize}}{{RecommendationPodiumRankGradientColor}}">{{RecommendationPodiumRank}}</span>
10008 {{/unless}}
10009 {{/if}}
10010 {{/if}}
10011 </text>
10012
10013 }
10014
10015 @helper RenderGridViewItemStickers()
10016 {
10017 <text>
10018 {{#StickersContainers}}
10019 {{>StickersContainer}}
10020 {{/StickersContainers}}
10021 </text>
10022 }
10023
10024 @helper RenderGridViewItemFavorites()
10025 {
10026 <div class="favorites favorites--for-grid-view u-pull--right {{favoriteProductFromImport}} dw-mod" {{favoriteProductFromImport}}>
10027 {{#Favorite}}
10028 {{>FavoriteTemplate}}
10029 {{/Favorite}}
10030 </div>
10031 }
10032
10033 @helper RenderGridViewItemInfoContainer(BlocksPage page)
10034 {
10035 List<Block> subBlocks = page.GetBlockListById("GridViewItemInfoContainer");
10036
10037 <div class="grid__cell product-list__grid-item__price-info dw-mod">
10038 @RenderBlockList(subBlocks)
10039 </div>
10040 }
10041
10042 @helper RenderGridViewItemTitle()
10043 {
10044 <a href="{{link}}" class="u-color-inherit" onclick="{{#if googleImpression}}googleEnchantImpressionClick({{googleImpression}}, event){{/if}}" title="{{name}}{{#if variantName}}, {{variantName}}{{/if}}">
10045 <h6 class="u-condensed-text u-bold">{{{name}}}{{#if variantName}}, {{variantName}}{{/if}}</h6>
10046 </a>
10047 }
10048
10049 @helper RenderGridViewItemNumber()
10050 {
10051 <div class="item-number dw-mod">{{number}}</div>
10052 }
10053
10054 @helper RenderGridViewItemPrice(Dynamicweb.Frontend.ItemViewModel gridViewSettings)
10055 {
10056 int columnsCount = gridViewSettings.GetList("Columns") != null ? Converter.ToInt32(gridViewSettings.GetList("Columns").SelectedValue) : 4;
10057 bool pointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly");
10058 bool showCartButton = Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetBoolean("ShowAddToCartButton");
10059 bool showVATPrice = Pageview.AreaSettings.GetItem("ProductList").GetBoolean("ShowBothPricesWithWithoutVAT");
10060 bool isPricesWithVATEnabled = Converter.ToBoolean(Pageview.Area.EcomPricesWithVat);
10061
10062 if (pointShopOnly)
10063 {
10064 <text>
10065 {{#if havePointPrice}}
10066 <div class="price price--product-list dw-mod">{{points}} @Translate("points")</div>
10067 @if (showCartButton)
10068 {
10069 <text>
10070 {{#unless canBePurchasedWithPoints}}
10071 <small class="help-text u-no-margin">@Translate("Not enough points to buy this")</small>
10072 {{/unless}}
10073 </text>
10074 }
10075 {{else}}
10076 @Translate("Not available")
10077 {{/if}}
10078 </text>
10079
10080 }
10081 else
10082 {
10083 <div class="price price--product-list dw-mod">{{price}}</div>
10084 <div class="before-price {{onSale}} dw-mod">{{discount}}</div>
10085 if (showVATPrice)
10086 {
10087 <div class="vat-price vat-price--product-list u-margin-top dw-mod">
10088 @if (columnsCount <= 4)
10089 {
10090 if (isPricesWithVATEnabled)
10091 {
10092 <span>@Translate("excl. VAT")</span><span> ({{priceWithoutVAT}})</span>
10093 }
10094 else
10095 {
10096 <span>@Translate("incl. VAT")</span><span> ({{priceWithVAT}})</span>
10097 }
10098 }
10099 else
10100 {
10101 if (isPricesWithVATEnabled)
10102 {
10103 <div>@Translate("excl. VAT")</div><div>({{priceWithoutVAT}})</div>
10104 }
10105 else
10106 {
10107 <div>@Translate("incl. VAT")</div><div>({{priceWithVAT}})</div>
10108 }
10109 }
10110 </div>
10111 }
10112 <text>
10113 {{#if priceRRP}}
10114 <div><small>@Translate("RRP") {{priceRRP}}</small></div>
10115 {{/if}}
10116 </text>
10117 }
10118 }
10119
10120 @helper RenderGridViewItemFooter(BlocksPage page, Dynamicweb.Frontend.ItemViewModel gridViewSettings)
10121 {
10122 List<Block> subBlocks = page.GetBlockListById("GridViewItemFooter");
10123 bool showStaticVariants = gridViewSettings.GetBoolean("ShowStaticVariants");
10124 string footerClasses = showStaticVariants ? "u-min-h120px" : "";
10125
10126 <div class="grid-footer">
10127 <div class="product-list__grid-item__footer @footerClasses dw-mod u-padding-1px {{#if RecommendationDisplayAsGrid}}{{#if RecommendationProductCardBackgroundColor}}u-transparent-background{{/if}}{{/if}}">
10128 @RenderBlockList(subBlocks)
10129 </div>
10130 </div>
10131 }
10132
10133 @helper RenderGridViewItemViewButton(Dynamicweb.Frontend.ItemViewModel gridViewSettings)
10134 {
10135 string viewMoreText = gridViewSettings.GetString("ViewMoreText");
10136 viewMoreText = !string.IsNullOrEmpty(viewMoreText) ? viewMoreText : "View";
10137
10138 @Render(new Link
10139 {
10140 Href = "{{link}}",
10141 Id = "CartButton_{{id}}",
10142 Title = Translate(viewMoreText),
10143 OnClick = "{{#if googleImpression}}googleEnchantImpressionClick({{googleImpression}}, event){{/if}}",
10144 ButtonLayout = ButtonLayout.Secondary,
10145 CssClass = "u-no-margin"
10146 });
10147 }
10148
10149 @helper RenderGridViewItemPricesAndAddToCart(Dynamicweb.Frontend.ItemViewModel gridViewSettings, int customerRatingHeartsPadding = 3)
10150 {
10151 int columnsCount = gridViewSettings.GetList("Columns") != null ? Converter.ToInt32(gridViewSettings.GetList("Columns").SelectedValue) : 4;
10152 bool pointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly");
10153 bool showCartButton = Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetBoolean("ShowAddToCartButton");
10154 bool showVATPrice = Pageview.AreaSettings.GetItem("ProductList").GetBoolean("ShowBothPricesWithWithoutVAT");
10155 bool isPricesWithVATEnabled = Converter.ToBoolean(Pageview.Area.EcomPricesWithVat);
10156
10157
10158 <div class="grid">
10159 <div class="grid__col-12 {{#if eventProduct}}event-{{/if}}{{#if useCustomCocktailProductCardDesign}}cocktail-title-container {{/if}}title-container">
10160 {{#unless eventProduct}}
10161 {{#unless cocktailProduct}}
10162 {{#unless RecommendationDisplayAsGrid}}
10163 <span class="area u-ta-center">{{producerName}}</span>
10164 {{/unless}}
10165 {{/unless}}
10166 {{/unless}}
10167 {{#if isPickAndMixPage}}
10168 <h3 class="u-bold title js-title u-ta-center pmx-modal-trigger js-pmx-modal-trigger" data-product-id="{{productId}}">{{name}}</h3>
10169 {{else}}
10170 <a href="{{link}}" class="u-color-inherit" onclick="Scroll.SavePosition(event); {{#if googleImpression}}googleEnchantImpressionClick({{googleImpression}}, event){{/if}}" title="{{name}}">
10171 <h3 class="u-bold title js-title {{#if useCustomCocktailProductCardDesign}}cocktail-product-title u-ta-left{{else}}u-ta-center{{/if}}">{{name}}</h3>
10172 </a>
10173 {{#if useCustomCocktailProductCardDesign}}
10174 <span class="cocktail-product-name-divider"></span>
10175 {{/if}}
10176 {{/if}}
10177
10178 {{#if eventProduct}}
10179 <p class="event-place">
10180 {{eventRestaurantName}}, {{eventAddressShort}}
10181 <span class="event-time">{{eventDate}}, {{eventTime}}</span>
10182 </p>
10183 {{/if}}
10184 </div>
10185 </div>
10186 <text>
10187 {{#unless eventProduct}}
10188 {{#unless RecommendationDisplayAsGrid}}
10189 <div class="grid">
10190 <div class="grid__col-12{{#if useCustomCocktailProductCardDesign}} u-padding-left-none u-padding-right-none{{/if}}">
10191 {{#if useCustomCocktailProductCardDesign}}
10192 <div class="cocktail-product-short-description">
10193 {{description}}
10194 </div>
10195 {{else}}
10196 <div class="tags">
10197 {{#if type}}
10198 {{#ifCond area "||" country}}
10199 <span class="tags__tag">
10200 {{type}},
10201 </span>
10202 {{else}}
10203 <span class="tags__tag">
10204 {{type}}
10205 </span>
10206 {{/ifCond}}
10207 {{/if}}
10208 {{#if area}}
10209 {{#if country}}
10210 <span class="tags__tag">{{area}},</span>
10211 {{else}}
10212 <span class="tags__tag">{{area}}</span>
10213 {{/if}}
10214 {{/if}}
10215 {{#if country}}
10216 <span class="tags__tag">{{country}}</span>
10217 {{/if}}
10218 </div>
10219 {{/if}}
10220 </div>
10221 </div>
10222 {{/unless}}
10223 {{/unless}}
10224 </text>
10225
10226 <text>
10227 {{#if isAddToCartModal}}
10228 <div class="savings">@Translate("Smartpage:ProductList.Product.Save", "SPAR") <strong>{{savings}}</strong> @Translate("Smartpage:ProductList.Product.PerUnit", "PR. FL.")</div>
10229 {{/if}}
10230 </text>
10231 <div class="grid">
10232 <div class="{{pricesSectionCol}}{{#if useCustomCocktailProductCardDesign}} u-padding-left-none u-padding-right-none{{/if}}">
10233 <div class="prices">
10234 {{#unless eventProduct}}
10235 {{#unless isAddToCartModal}}
10236 {{#if bomItemSavings}}
10237 <div class="savings">@Translate("Smartpage:ProductList.Product.Save", "SPAR") <strong>{{bomItemSavingsFormatted}}</strong></div>
10238 {{else if savings}}
10239 <div class="savings">@Translate("Smartpage:ProductList.Product.Save", "SPAR") <strong>{{savings}}</strong> @Translate("Smartpage:ProductList.Product.PerUnit", "PR. FL.")</div>
10240 {{else}}
10241 {{/if}}
10242 {{/unless}}
10243 {{/unless}}
10244 <div class="price price--product-list dw-mod">{{price}}{{#if isSubscription}}@Translate("Smartpage:Checkout.PerMonth", "/md"){{/if}}</div>
10245 <div class="quantity-price">
10246 {{#if isBomParent}}
10247 {{#if bomItemsTotalPriceNotZero}}
10248 <span class="u-block u-color-font-black quantity-price__amount"><strong><s>{{bomQuantityDescription}}</s></strong></span>
10249 {{/if}}
10250 {{pricePerBomItem}}
10251 {{/if}}
10252 {{{quantityDescription}}}
10253 </div>
10254 </div>
10255 </div>
10256 {{#if availableForPurchase}}
10257 {{#unless RecommendationDisplayAsGrid}}
10258 <div class="{{addToCartSectionCol}}{{#if useCustomCocktailProductCardDesign}} u-padding-left-none u-padding-right-none{{/if}} add-to-cart @(Pageview.Device.ToString() == "Desktop" ? "u-padding-left-none u-padding-right-none" : "")">
10259 <div class="grid grid--justify-space-between product-list-validate-product-amount-container js-validate-product-amount-container {{#if isPickAndMixPage }}pmx-add-wrapper{{/if}}">
10260 {{#unless disabledBuyButton}}
10261 {{#unless isPickAndMixPage}}
10262 {{#unless isSubscription}}
10263 <div class="grid__col-6 u-no-padding product-amount-validation-container-max-content">
10264 <span class="product-amount-validation-container product-amount-validation-container__product-list">
10265 <input disabled id="Quantity{{id}}" name="Quantity{{id}}" min="1" max="{{stockLevel}}" value="" data-kolli="{{highestQuantity}}" {{#if productInCartQuantity}} data-product-in-cart-quantity="{{productInCartQuantity}}" {{/if}} type="number" class="quantity dw-mod js-stockcheck js-change-quantity js-product-amount-validation__input" data-max-order-quantity-rule-active="{{MaxOrderQuantityRuleActive}}">
10266 <select id="SelectQuantity{{id}}" name="SelectQuantity{{id}}" min="1" max="{{stockLevel}}" data-max-order-quantity-rule-active="{{MaxOrderQuantityRuleActive}}" class="u-no-padding quantity dw-mod product-amount-validation__select js-product-amount-validation__select">
10267 {{#each productAmountSelection}}
10268 <option {{#if IsDefault}} selected {{/if}} value="{{Value}}">{{Value}}</option>
10269 {{/each}}
10270 <option value="other">@Translate("Products.Amount.Selector.Other", "Andet")</option>
10271 </select>
10272 </span>
10273 </div>
10274 {{else}}
10275 <input id="Quantity{{id}}" name="Quantity{{id}}" min="1" value="1" type="hidden" class="dw-mod js-stockcheck js-change-quantity" data-max-order-quantity-rule-active="{{MaxOrderQuantityRuleActive}}">
10276 {{/unless}}
10277 {{/unless}}
10278 {{/unless}}
10279 {{#if disabledBuyButton}}
10280 <div class="grid__col-12 u-no-padding">
10281 <button class="btn btn--add-to-cart {{disabledBuyButton}}" title="@Translate("Smartpage:Product.Buy.OutOfStock", "Udsolgt")" onclick="Cart.AddToCart(event, { id: '{{productId}}', variantId: '{{variantid}}', unitId: '{{unitId}}', productInfo: {{productInfo}}, quantity: parseInt(document.getElementById('Quantity{{id}}').value), SpPrimeur: '{{isPrimeur}}'}); {{facebookPixelAction}}" type="button">
10282 <span>@Translate("Smartpage:Product.Buy.OutOfStock", "Udsolgt")</span>
10283 </button>
10284 </div>
10285 {{/if}}
10286 {{#unless disabledBuyButton}}
10287 <div class="invalid-amount-tooltip invalid-amount-tooltip-on-product-list grid__col-6 u-no-padding js-product-amount-validation-btn-container">
10288 {{#if isPickAndMixPage}}
10289 @{
10290 string picknmixFeed = $"/Default.aspx?ID={GetPageIdByNavigationTag("picknmixfeedpage")}";
10291 string pageId = Dynamicweb.Context.Current.Request["ID"];
10292
10293 string productFeedUrl = $"/Default.aspx?ID={GetPageIdByNavigationTag("picknmix")}";
10294
10295 productFeedUrl += "&MainProductId={prodIds}&feed=true&redirect=false&pickandmixlist=true";
10296 }
10297 <div class="u-position-relative js-pmx-add-wrapper">
10298 <button class="btn btn--add-to-cart add-to-pmx js-add-to-pmx {{#if quantityPickedPmx}} d-none {{/if}}" title="@HttpUtility.HtmlAttributeEncode(Translate("Smartpage:PickAndMix.Product.Buy", "Køb"))" data-currfeedurl="@productFeedUrl" data-id="{{productId}}" data-productname="{{name}}" data-maxquantity="{{stockLevel}}" data-method="add" data-feedurl="@picknmixFeed" type="button" data-currency-code="{{currency}}">
10299 <span>@Translate("Smartpage:PickAndMix.Product.Buy", "Tilføj")</span>
10300 </button>
10301 <div class="js-pmx-add-remove-wrap pmx-add-remove-wrap {{#unless quantityPickedPmx}} d-none {{/unless}}">
10302 <div class="action js-remove-from-pmx" data-currfeedurl="@productFeedUrl" data-id="{{productId}}" data-method="delete" data-feedurl="@picknmixFeed" data-currency-code="{{currency}}" data-index="0">
10303 -
10304 </div>
10305 <input class="js-update-pmx" data-input-id="js-pmx-input{{productId}}" min="0" type="number" value="{{quantityPickedPmx}}" data-id="{{productId}}" data-maxquantity="{{stockLevel}}" data-method="update" data-productname="{{name}}" data-feedurl="@picknmixFeed" data-currency-code="{{currency}}" data-index="0" data-currfeedurl="@productFeedUrl" />
10306 <div class="action js-add-to-pmx" data-maxquantity="{{stockLevel}}" data-productname="{{name}}" data-currfeedurl="@productFeedUrl" data-id="{{productId}}" data-method="add" data-feedurl="@picknmixFeed" data-currency-code="{{currency}}">
10307 +
10308 </div>
10309 </div>
10310 </div>
10311 {{else}}
10312 <button class="btn btn--add-to-cart js-product-amount-validation-btn {{disabledBuyButton}} {{#if useCustomCocktailProductCardDesign}}cocktail-product-buy-button{{/if}}" title="@Translate("Smartpage:Product.Buy", "Køb")" onclick="Cart.AddToCart(event, { id: '{{productId}}', variantId: '{{variantid}}', unitId: '{{unitId}}', productInfo: {{productInfo}}, quantity: getSelectedQuantity('{{id}}'), SpPrimeur: '{{isPrimeur}}' }); {{facebookPixelAction}}" type="button" data-product-id="{{productId}}" data-one-unit-price="{{oneUnitPrice}}" data-volume-unit-price="{{volumeUnitPrice}}" data-volume-unit-threshold="{{kolli}}" data-currency-code="{{currency}}">
10313 {{#if useCustomCocktailProductCardDesign}}
10314 <span>@Translate("Smartpage:Product.Cocktail.Buy", "Køb pakke")</span>
10315 {{else}}
10316 <span>@Translate("Smartpage:Product.Buy", "Køb")</span>
10317 {{/if}}
10318 </button>
10319 <span class="invalid-amount-tooltip-text">@Translate("Custom.Product.Buy.Tooltip.AmountInvalid", "Det samlede antal er ugyldigt. Klik for at ændre til det nærmest gyldige antal")</span>
10320 {{/if}}
10321 </div>
10322 {{/unless}}
10323 </div>
10324 </div>
10325 {{/unless}}
10326 {{/if}}
10327 {{#if primeurDeliveryDate}}
10328 <div class="grid__col-12 incoming-primeur-date">
10329 <div class="incoming-primeur-date__date">
10330 {{ primeurDeliveryDate }}
10331 </div>
10332 </div>
10333 {{/if}}
10334 {{#if bomSoldOutMessage}}
10335 <div class="grid__col-12 sold-out-message-container">
10336 <div class="sold-out-message">
10337 <span class="message">{{ bomSoldOutMessage }}</span>
10338 </div>
10339 </div>
10340 {{/if}}
10341 </div>
10342 }
10343
10344 @helper RenderGridViewItemActions(Dynamicweb.Frontend.ItemViewModel gridViewSettings, int customerRatingHeartsPadding = 2)
10345 {
10346 if (Dynamicweb.Rapido.Services.User.IsBuyingAllowed())
10347 {
10348 @RenderGridViewItemPricesAndAddToCart(gridViewSettings, customerRatingHeartsPadding)
10349 }
10350 }
10351 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>
10352 @using Dynamicweb
10353 @using Dynamicweb.Core
10354 @using Dynamicweb.Rapido.Blocks.Components.General
10355 @using Dynamicweb.Rapido.Blocks
10356 @using Dynamicweb.Rapido.Blocks.Components
10357 @using Smartpage.Relewise.Services.Models
10358
10359 @functions{
10360 BlocksPage productRecommendationSliderBlock = new BlocksPage();
10361 Dynamicweb.Frontend.ItemViewModel gridViewSettingsRecommendationSlider = null;
10362 }
10363
10364 @helper RenderRecommendationSlider(Smartpage.Relewise.Services.Models.RecommendationItem recommendationItem, int preloaderElementsAmount = 0, Smartpage.PhilipsonWine.Ecommerce.ProductInformation.ExtendedProductViewModel extendedProductViewModel = null, int itemIndex = 0, bool hasMultipleRecommendationItems = false)
10365 {
10366 string marginStyle = "style='margin-top: 2rem; margin-bottom: 2rem;'";
10367 bool isCocktailPack = extendedProductViewModel != null ? extendedProductViewModel.IsCocktailPack : false;
10368 if (isCocktailPack)
10369 {
10370 <div class="paragraph-container--full-width cocktail-product-recommendations">
10371 <div class="@recommendationItem.GridClasses" @(recommendationItem.HideMargin ? string.Empty : marginStyle)>
10372 @RenderRecommendationSliderColumns(recommendationItem, preloaderElementsAmount, isCocktailPack)
10373 </div>
10374 </div>
10375 }
10376 else
10377 {
10378 <div class="@recommendationItem.GridClasses" @(recommendationItem.HideMargin ? string.Empty : marginStyle)>
10379 @RenderRecommendationSliderColumns(recommendationItem, preloaderElementsAmount, false, itemIndex, hasMultipleRecommendationItems)
10380 </div>
10381 }
10382 }
10383
10384 @helper RenderRecommendationSliderColumns(RecommendationItem recommendationItem, int preloaderElementsAmount, bool isCocktailPack = false, int itemIndex = 0, bool hasMultipleRecommendationItems = false)
10385 {
10386 <div class="@recommendationItem.ColClasses js-product-slider-item @(recommendationItem.DisplayAsGrid ? "recommendations-grid-view-container" : "")">
10387 @if (!string.IsNullOrEmpty(recommendationItem.Headline))
10388 {
10389 string centerClass = recommendationItem.CenterHeadline ? "u-ta-center" : "";
10390 string fontColor = !string.IsNullOrEmpty(recommendationItem.HeadlineColor) ? recommendationItem.HeadlineColor : "";
10391
10392 if (isCocktailPack)
10393 {
10394 int cocktailsPage = GetPageIdByNavigationTag("CocktailsPage");
10395 string cocktailsPageLink = cocktailsPage > 0 ? "/Default.aspx?ID=" + cocktailsPage : "";
10396 <div class="cocktail-pack-recommendation-header">
10397 <h2 class="@centerClass" style="color: @fontColor">@recommendationItem.Headline</h2>
10398 <a href="@cocktailsPageLink" class="cocktail-pack-recommendation-button-text btn btn--tertiary dw-mod">@Translate("Smartpage:CocktailRecommendations.Button.SeeAllCocktailPacks", "Se alle drinks pakker") <i class="fa fa-arrow-right custom-product-info__icon"></i></a>
10399 </div>
10400 }
10401 else
10402 {
10403 if (!hasMultipleRecommendationItems)
10404 {
10405 <h2 class="@centerClass" style="color: @fontColor">@recommendationItem.Headline</h2>
10406 }
10407 }
10408 }
10409
10410 @if (!string.IsNullOrEmpty(recommendationItem.APIRoute))
10411 {
10412
10413 gridViewSettingsRecommendationSlider = Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView");
10414
10415 string feedUrl = recommendationItem.GetUrl(GetPageIdByNavigationTag("ProductsPageNoFacets"));
10416
10417 Block gridViewItem = new Block
10418 {
10419 Id = "GridViewItem",
10420 SortId = 10,
10421 Template = RenderGridViewItem(productRecommendationSliderBlock),
10422 SkipRenderBlocksList = true,
10423 BlocksList = new List<Block> {
10424 new Block
10425 {
10426 Id = "GridViewItemHiddenProperties",
10427 SortId = 10,
10428 Template = RenderGridViewItemHiddenProperties()
10429 },
10430 new Block
10431 {
10432 Id = "GridViewItemImageContainer",
10433 SortId = 20,
10434 SkipRenderBlocksList = true,
10435 Template = RenderGridViewItemImageContainer(productRecommendationSliderBlock),
10436 BlocksList = new List<Block>
10437 {
10438 new Block
10439 {
10440 Id = "GridViewItemImage",
10441 SortId = 10,
10442 Template = RenderGridViewItemImage()
10443 }
10444 }
10445 },
10446 new Block
10447 {
10448 Id = "GridViewItemFooter",
10449 SortId = 40,
10450 SkipRenderBlocksList = true,
10451 Template = RenderGridViewItemFooter(productRecommendationSliderBlock, gridViewSettingsRecommendationSlider),
10452 BlocksList = new List<Block> {
10453 new Block
10454 {
10455 Id = "GridViewItemActions",
10456 SortId = 10,
10457 Template = RenderGridViewItemActions(gridViewSettingsRecommendationSlider, 2)
10458 }
10459 }
10460 }
10461 }
10462 };
10463
10464 productRecommendationSliderBlock.Add(gridViewItem);
10465
10466 string swiperPrevButtonClass = recommendationItem.Id + "_SwiperButtonPrev";
10467 string swiperNextButtonClass = recommendationItem.Id + "_SwiperButtonNext";
10468 bool isCartPage = Pageview.ID == GetPageIdByNavigationTag("CartPage");
10469 string preRenderContainerClasses = "js-product-slider-preloader";
10470
10471 if (recommendationItem.DisplayAsGrid)
10472 {
10473 preRenderContainerClasses += " recommendations-grid-view-preloader recommendations-grid-view-preloader--loading";
10474 }
10475 else
10476 {
10477 preRenderContainerClasses += " product-slider-preloader product-slider-preloader--loading";
10478 }
10479
10480 if (recommendationItem.ActivatePodium)
10481 {
10482 preRenderContainerClasses += " podium-activated";
10483 }
10484
10485 Dictionary<string, string> extraAttributes = new Dictionary<string, string>();
10486 string multipleItemsContainerClass = "";
10487
10488 if (hasMultipleRecommendationItems)
10489 {
10490 extraAttributes.Add("data-recommendation-item-index", HttpUtility.HtmlAttributeEncode(Converter.ToString(itemIndex)));
10491 multipleItemsContainerClass = " js-recommendations-container";
10492 }
10493
10494 if (itemIndex > 1)
10495 {
10496 extraAttributes.Add("data-init-onload", "false");
10497 }
10498
10499 bool isActiveByDefault = hasMultipleRecommendationItems && itemIndex == 1;
10500 if (isActiveByDefault)
10501 {
10502 multipleItemsContainerClass += " js-active-recommendation-item";
10503 }
10504
10505 <div class="js-handlebars-root-async grid@(multipleItemsContainerClass)" id="@recommendationItem.Id" data-initialized="@HttpUtility.HtmlAttributeEncode(Converter.ToString(isActiveByDefault).ToLower())" data-template="@("ProductContainer_" + recommendationItem.Id)" data-json-feed="@feedUrl" @ComponentMethods.AddAttributes(extraAttributes)></div>
10506 <div class="@preRenderContainerClasses">
10507 @for (int i = 0; i < (Pageview.Device.ToString() == "Mobile" ? 1 : preloaderElementsAmount); i++)
10508 {
10509 <div class="pre-render-element product-slider-preloader-element"></div>
10510 }
10511 </div>
10512
10513
10514 <script id="@("ProductContainer_" + recommendationItem.Id)" type="text/x-template">
10515 <div class="swiper-container js-product-slider-container product-slider-container @recommendationItem.Id @(!recommendationItem.DisplayAsGrid ? recommendationItem.SwiperContainerClasses : "js-recommendations-deactivate-slider")" data-swiper-config="@recommendationItem.GetLayout()">
10516 {{#each .}}
10517 <div class="swiper-wrapper @(recommendationItem.DisplayAsGrid ? "recommendations-grid-wrapper" : "") @(recommendationItem.ActivatePodium ? "recommendations-podium-container" : "")">
10518 {{#each ProductsContainer}}
10519 <div id="Product{{id}}" data-template="GridViewItem" data-preloader="overlay" class="product-list__grid-item dw-mod js-product-list-product product-list-product swiper-slide @(recommendationItem.DisplayAsGrid ? "product-slider-grid-view-item" : "")">
10520 {{#each Product}}
10521 {{>GridViewItem}}
10522 {{/each}}
10523 </div>
10524 {{/each}}
10525 </div>
10526 <div class="swiper-pagination"></div>
10527 {{/each}}
10528 </div>
10529 @if (!recommendationItem.DisplayAsGrid)
10530 {
10531 string desktopCss = Pageview.Device == Dynamicweb.Frontend.Devices.DeviceType.Desktop ? "custom-swiper-buttons-desktop" : "";
10532 <div id="@swiperPrevButtonClass" class="swiper-button-prev @desktopCss"></div>
10533 <div id="@swiperNextButtonClass" class="swiper-button-next @desktopCss"></div>
10534 }
10535 </script>
10536
10537 @RenderBlockList(productRecommendationSliderBlock.BlocksRoot.BlocksList)
10538
10539 <script id="ProductSliderPreRenderContainer" type="text/x-template">
10540 <div class="grid__col-auto">
10541 <div class="pre-render-element pre-render-element--lg" style="height: 570px;"></div>
10542 </div>
10543 </script>
10544
10545 <script id="StickersContainer" type="text/x-template">
10546 <div class="stickers-container stickers-container--{{{convertStickerPositionToClassName Position}}} dw-mod">
10547 {{#Stickers}}
10548 {{>Sticker}}
10549 {{/Stickers}}
10550 </div>
10551 </script>
10552
10553 <script id="Sticker" type="text/x-template">
10554 @Render(new Sticker { Title = "{{Title}}", CssClass = "{{CssClass}}" })
10555 </script>
10556 }
10557
10558 </div>
10559 }
10560
10561
10562 @{
10563 string addToCartNotificationType = Model.Area.Item.GetItem("Ecommerce").GetItem("MiniCart").GetList("AddToCartNotificationType") != null ? Model.Area.Item.GetItem("Ecommerce").GetItem("MiniCart").GetList("AddToCartNotificationType").SelectedValue : "";
10564 string addToCartNotificationMiniCartLayout = Model.Area.Item.GetItem("Ecommerce").GetItem("MiniCart").GetList("Layout") != null ? Model.Area.Item.GetItem("Ecommerce").GetItem("MiniCart").GetList("Layout").SelectedValue : "dropdown";
10565 bool addToCartHideCartIcon = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("HideCart");
10566
10567 string id = "RecommendationsAddToCartSlider";
10568 var recommendationItem = new RecommendationItem()
10569 {
10570 Id = id,
10571 CenterHeadline = true,
10572 Headline = Translate("Custom:ProductSlider.Recommendations.Headline." + id, "Andre købte også"),
10573 Label = Translate("Custom:ProductSlider.Recommendations.Headline." + id, "Anbefalinger Powerstep"),
10574 Limit = "20",
10575 APIRoute = "PurchasedWithProduct",
10576 NumberOfSlides = 2,
10577 Layout = RecommendationItem.SliderLayout.PowerStep,
10578 GridClasses = "grid u-full-height grid--justify-center",
10579 ColClasses = "grid__col-12 u-no-padding",
10580 HideMargin = true
10581 };
10582
10583 if (Dynamicweb.Rapido.Services.User.IsBuyingAllowed() && !string.IsNullOrEmpty(addToCartNotificationType))
10584 {
10585 if (addToCartNotificationType == "modal")
10586 {
10587 Block addToCartNotificationModal = new Block
10588 {
10589 Id = "AddToCartNotificationModal",
10590 Template = RenderAddToCartNotificationModal()
10591 };
10592
10593 Block addToCartNotificationScript = new Block
10594 {
10595 Id = "AddToCartNotificationScript",
10596 Template = RenderAddToCartNotificationModalScript(recommendationItem)
10597 };
10598
10599 Block freightMeterScript = new Block
10600 {
10601 Id = "FreightMeterScript",
10602 Template = RenderFreightMeterScript()
10603 };
10604
10605 BlocksPage.GetBlockPage("Master").Add("MasterTopSnippets", addToCartNotificationModal);
10606 BlocksPage.GetBlockPage("Master").Add("MasterBottomSnippets", addToCartNotificationScript);
10607 BlocksPage.GetBlockPage("Master").Add("MasterBottomSnippets", freightMeterScript);
10608 }
10609 else if (addToCartNotificationType == "toggle" && addToCartNotificationMiniCartLayout != "none" && !addToCartHideCartIcon)
10610 {
10611 Block addToCartNotificationScript = new Block
10612 {
10613 Id = "AddToCartNotificationScript",
10614 Template = RenderAddToCartNotificationToggleScript()
10615 };
10616 BlocksPage.GetBlockPage("Master").Add("MasterBottomSnippets", addToCartNotificationScript);
10617 }
10618 }
10619
10620 }
10621
10622
10623 @helper RenderAddToCartNotificationModal()
10624 {
10625 <div id="LastAddedProductModal" class="last-added-product-modal" data-template="LastAddedProductTemplate"></div>
10626 }
10627
10628 @helper RenderAddToCartNotificationModalScript(RecommendationItem recommendationItem)
10629 {
10630 int cartPageId = GetPageIdByNavigationTag("CartPage");
10631 <script id="LastAddedProductTemplate" type="text/x-template">
10632 @{
10633
10634 Modal lastAddedProduct = new Modal
10635 {
10636 Id = "LastAddedProduct",
10637 Width = ModalWidth.Lg,
10638 BodyTemplate = Pageview.Device.ToString() == "Mobile" ? RenderMobileModalContent(recommendationItem) : RenderModalContent(recommendationItem),
10639 OnClose = "window.scrollLockDisable();"
10640 };
10641
10642 @Render(lastAddedProduct)
10643 }
10644 </script>
10645
10646 int miniCartPageId = GetPageIdByNavigationTag("MiniCartFeed");
10647 string feedUrl = "/Default.aspx?ID=" + miniCartPageId;
10648 <script>
10649 document.addEventListener('addToCart', function (event) {
10650 if (event.detail.lineNotAddedNotification != null) {
10651 showCartLineNotAddedModal(event.detail.lineNotAddedNotification);
10652 } else {
10653 // Show added to cart modal if not on carts page
10654 if (document.querySelector('.carts-page') == null) {
10655 Cart.ShowLastAddedProductModal(event.detail);
10656 }
10657 }
10658 });
10659
10660 function closeModal(e) {
10661 if (e.classList.contains("js-toggle-last-added-product-modal")) {
10662 localStorage.setItem('LastAddedProductModalHidden', 'true');
10663 var today = new Date();
10664 var oneWeekFromNow = today.setDate(today.getDate() + 7);
10665 localStorage.setItem('LastAddedProductModal.ExpiresIn', JSON.stringify(oneWeekFromNow));
10666 }
10667
10668 document.getElementById('LastAddedProductModalTrigger').checked = false;
10669 window.scrollLockDisable();
10670 }
10671 </script>
10672
10673 string swiperPaginationClass = recommendationItem.Id + "_SwiperPagination";
10674 string swiperPrevButtonClass = recommendationItem.Id + "_SwiperButtonPrev";
10675 string swiperNextButtonClass = recommendationItem.Id + "_SwiperButtonNext";
10676
10677 <script id="@("ProductContainer_" + recommendationItem.Id)" type="text/x-template">
10678 <div class="@recommendationItem.GridClasses">
10679 <div class="@recommendationItem.ColClasses">
10680 <div class="recommendations">
10681 <div id="@("SliderContainer_" + recommendationItem.Id)" class="swiper-container custom-swiper-container product-slider-container js-product-slider-container @recommendationItem.Id" data-swiper-config="@recommendationItem.GetLayout()">
10682 {{#each .}}
10683 <div id="AddToCartRecommendations" class="swiper-wrapper powerstep">
10684 {{#each ProductsContainer}}
10685 <div id="Product{{id}}" data-template="GridViewItem" data-preloader="overlay" class="product-list__grid-item dw-mod swiper-slide product-slider-grid-view-item product-card js-product-grid-item" data-product-id="{{productId}}">
10686 {{#each Product}}
10687 {{>GridViewItem}}
10688 {{/each}}
10689 </div>
10690 {{/each}}
10691 </div>
10692 {{/each}}
10693 <div class="swiper-pagination @swiperPaginationClass"></div>
10694 </div>
10695 <div id="@swiperPrevButtonClass" class="swiper-button-prev"></div>
10696 <div id="@swiperNextButtonClass" class="swiper-button-next"></div>
10697 </div>
10698 </div>
10699 </div>
10700 </script>
10701
10702 }
10703
10704 @helper RenderModalContent(RecommendationItem recommendationItem)
10705 {
10706 int cartPageId = GetPageIdByNavigationTag("CartPage");
10707 int miniCartPageId = GetPageIdByNavigationTag("MiniCartFeed");
10708 bool activateFreightMeter = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetBoolean("ActivateFreightMeter");
10709
10710 <div class="grid added-to-cart-section">
10711 <div class="added-to-cart u-flex u-no-padding u-flex--align-center u-justify-content--center grid grid__col-12 u-flex--row">
10712 <h3 class="grid__col-12 grid--justify-center added-to-cart-text">@RenderCheckmark() @Translate("Smartpage:LastAddedProductModal.AddedToCart", "Tilføjet til kurven")</h3>
10713 @if (activateFreightMeter)
10714 {
10715 <div class="js-handlebars-root freight-meter" id="freightMeterContainer"></div>
10716 }
10717 <div class="product-image-container grid__col-1">
10718 {{#if EcomOrderLineFieldInput_SpPickAndMixGroupId1}}
10719 @Render(new Image { Path = "/Admin/Public/GetImage.ashx?Width=115&Height=115&Crop=5&DoNotUpscale=True&FillCanvas=False&Image=/Files/Images/philipsonwine/pickandmix/Kasse.png", Title = Translate("Smartpage:Checkout.PMXCart.Name", "Din egen vinkasse"), DisableImageEngine = true, CssClass = "product-image" })
10720 {{else}}
10721 @if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request["ProductId"]))
10722 {
10723 @Render(new Image { Path = "{{ productInfo.image }}", Link = "{{ productInfo.link }}", Title = "{{ productInfo.name }}", DisableImageEngine = true, CssClass = "product-image" })
10724 }
10725 else
10726 {
10727 @Render(new Image { Path = "{{ productInfo.addToCartModalImage }}", Link = "{{ productInfo.link }}", Title = "{{ productInfo.name }}", DisableImageEngine = true, CssClass = "product-image" })
10728 }
10729 {{/if}}
10730 </div>
10731 <div class="grid__col-5">
10732 <div class="u-flex u-flex--column">
10733 {{#if EcomOrderLineFieldInput_SpPickAndMixGroupId1}}
10734 <div>@Translate("Smartpage:Checkout.PMXCart.Name", "Din egen vinkasse")</div>
10735 {{else}}
10736 <div class="u-margin-right added-to-cart-quantity">{{quantity}} <span class="u-lowercase">{{unitId}}</span></div>
10737 {{#if productInfo.name}}
10738 <div class="powerstep-product-name">{{productInfo.name}}</div>
10739 {{else}}
10740 <div>{{name}}</div>
10741 {{/if}}
10742 {{#if productInfo.variantName}}
10743 <small class="u-margin-bottom-5px">{{productInfo.variantName}}</small>
10744 {{/if}}
10745 {{#if productInfo.unitName}}
10746 <small class="u-margin-bottom-5px">{{productInfo.unitName}}</small>
10747 {{/if}}
10748 {{/if}}
10749 </div>
10750 </div>
10751 <div class="grid__col-6 u-full-height">
10752 <div class="u-full-width u-flex u-flex--row buttons">
10753 @Render(new Button
10754 {
10755 ButtonType = ButtonType.Button,
10756 ButtonLayout = ButtonLayout.Secondary,
10757 Title = HttpUtility.HtmlAttributeEncode(Translate("Smartpage:LastAddedProductModal.ContinueShopping", "Shop videre")),
10758 CssClass = "u-pull--left u-no-margin btn-continue-shopping u-margin-right--lg white-button",
10759 OnClick = "closeModal(this)"
10760 })
10761 @Render(new Link
10762 {
10763 Href = "/Default.aspx?ID=" + cartPageId,
10764 ButtonLayout = ButtonLayout.Primary,
10765 CssClass = "u-pull--right u-no-margin btn-go-to-checkout",
10766 Title = HttpUtility.HtmlAttributeEncode(Translate("Smartpage:LastAddedProductModal.GoToCart", "Gå til kurven")),
10767 OnClick = "closeModal(this)"
10768 })
10769 </div>
10770 <button onclick="closeModal(this)" class="dont-show-again u-align-content-left u-font-size--xs js-toggle-last-added-product-modal">
10771 @Translate("Smartpage:LastAddedProductModal.DontShowAgain", "Vis ikke igen")
10772 </button>
10773 </div>
10774 </div>
10775 </div>
10776
10777 <div>
10778 {{#if productInfo.hasCustomAddToCartModal}}
10779 <div class="custom-add-to-cart-modal-message">
10780 <div>
10781 <p>{{{productInfo.customModalMessage}}}</p>
10782 </div>
10783 </div>
10784 {{else}}
10785 <div class="others-bought-section">
10786 @RenderModalSubheading(recommendationItem)
10787 </div>
10788 {{/if}}
10789 </div>
10790 }
10791
10792 @helper RenderMobileModalContent(RecommendationItem recommendationItem)
10793 {
10794 int cartPageId = GetPageIdByNavigationTag("CartPage");
10795 int miniCartPageId = GetPageIdByNavigationTag("MiniCartFeed");
10796 bool activateFreightMeter = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetBoolean("ActivateFreightMeter");
10797
10798 <div class="grid grid--align-center grid--justify-center added-to-cart-section">
10799 <div class="added-to-cart u-flex u-no-padding u-flex--align-center u-justify-content--center grid__col-12 grid u-flex--row">
10800 <div class="grid">
10801 <h3 class="added-to-cart-text grid__col-12"> @RenderCheckmark() @Translate("Smartpage:LastAddedProductModal.AddedToCart", "Tilføjet til kurven")</h3>
10802 @if (activateFreightMeter)
10803 {
10804 <div class="js-handlebars-root freight-meter" id="freightMeterContainer"></div>
10805 }
10806 <div class="product-image-container grid__col-2">
10807 {{#if EcomOrderLineFieldInput_SpPickAndMixGroupId1}}
10808 @Render(new Image { Path = "/Admin/Public/GetImage.ashx?Width=115&Height=115&Crop=5&DoNotUpscale=True&FillCanvas=False&Image=/Files/Images/philipsonwine/pickandmix/Kasse.png", Title = Translate("Smartpage:Checkout.PMXCart.Name", "Din egen vinkasse"), DisableImageEngine = true, CssClass = "product-image" })
10809 {{else}}
10810 @if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request["ProductId"]))
10811 {
10812 @Render(new Image { Path = "{{ productInfo.image }}", Link = "{{ productInfo.link }}", Title = "{{ productInfo.name }}", DisableImageEngine = true, CssClass = "product-image" })
10813 }
10814 else
10815 {
10816 @Render(new Image { Path = "{{ productInfo.addToCartModalImage }}", Link = "{{ productInfo.link }}", Title = "{{ productInfo.name }}", DisableImageEngine = true, CssClass = "product-image" })
10817 }
10818 {{/if}}
10819 </div>
10820 <div class="u-flex u-flex--column grid--justify-center grid__col-10">
10821 {{#if EcomOrderLineFieldInput_SpPickAndMixGroupId1}}
10822 <div>@Translate("Smartpage:Checkout.PMXCart.Name", "Din egen vinkasse")</div>
10823 {{else}}
10824 <div class="u-margin-right added-to-cart-quantity">{{quantity}} <span class="u-lowercase">{{unitId}}</span></div>
10825 {{#if productInfo.name}}
10826 <div class="powerstep-product-name">{{productInfo.name}}</div>
10827 {{else}}
10828 <div>{{name}}</div>
10829 {{/if}}
10830 {{#if productInfo.variantName}}
10831 <small class="u-margin-bottom-5px">{{productInfo.variantName}}</small>
10832 {{/if}}
10833 {{#if productInfo.unitName}}
10834 <small class="u-margin-bottom-5px">{{productInfo.unitName}}</small>
10835 {{/if}}
10836 {{/if}}
10837 </div>
10838 </div>
10839 </div>
10840 </div>
10841
10842 <div>
10843 {{#if productInfo.hasCustomAddToCartModal}}
10844 <div class="custom-add-to-cart-modal-message">
10845 <div>
10846 <p>{{{productInfo.customModalMessage}}}</p>
10847 </div>
10848 </div>
10849 {{else}}
10850 <div class="others-bought-section">
10851 @RenderModalSubheading(recommendationItem)
10852 </div>
10853 {{/if}}
10854 </div>
10855
10856 <div class="grid__col-12 grid--justify-center u-no-padding bottom-actions">
10857 <div class="u-flex u-flex--row buttons">
10858 @Render(new Button
10859 {
10860 ButtonType = ButtonType.Button,
10861 ButtonLayout = ButtonLayout.Secondary,
10862 Title = HttpUtility.HtmlAttributeEncode(Translate("Smartpage:LastAddedProductModal.ContinueShopping", "Shop videre")),
10863 CssClass = "u-pull--left u-no-margin btn-continue-shopping u-margin-right--lg white-button",
10864 OnClick = "closeModal(this)"
10865 })
10866 @Render(new Link
10867 {
10868 Href = "/Default.aspx?ID=" + cartPageId,
10869 ButtonLayout = ButtonLayout.Primary,
10870 CssClass = "u-pull--right u-no-margin btn-go-to-checkout",
10871 Title = HttpUtility.HtmlAttributeEncode(Translate("Smartpage:LastAddedProductModal.GoToCart", "Gå til kurven")),
10872 OnClick = "closeModal(this)"
10873 })
10874 </div>
10875
10876 <button onclick="closeModal(this)" class="dont-show-again u-align-content-left u-font-size--xs js-toggle-last-added-product-modal">
10877 @Translate("Smartpage:LastAddedProductModal.DontShowAgain", "Vis ikke igen")
10878 </button>
10879 </div>
10880 }
10881
10882 @helper RenderFreightMeterScript()
10883 {
10884 <script id="FreightMeter" type="text/x-template">
10885 {{#.}}
10886 <div class="freight-message {{powerstepFreightMessageCssClass}}">
10887 {{powerstepFreightMessage}}
10888
10889 {{#unless powerstepFreightMessageCssClass}}
10890 <span class="u-bold">@Translate("Smartpage:LastAddedProductModal.FreeFreight", "fri fragt")</span>
10891 {{/unless}}
10892 </div>
10893 <div class="progress-bar-container">
10894 <div class="progress-bar-indicator" style="width:{{percentageFreeFreight}}%"></div>
10895 </div>
10896 {{/.}}
10897 </script>
10898 }
10899
10900 @{
10901
10902 string cartPageId = GetPageIdByNavigationTag("CartPage").ToString();
10903
10904 if (Dynamicweb.Context.Current.Items["Smartpage:LineAdjusted"] != null)
10905 {
10906 var lineAdjustedNotification = Dynamicweb.Context.Current.Items["Smartpage:LineAdjusted"] as List<LineAdjusted>;
10907
10908 <input type="checkbox" id="CartLineAdjustedModalTrigger" class="modal-trigger" checked>
10909 <div class="modal-container">
10910 <label class="modal-overlay"></label>
10911 <div class="modal modal--lg modal-height--auto" id="CartLineAdjustedModal">
10912 @foreach (LineAdjusted lineAdjusted in lineAdjustedNotification)
10913 {
10914 <div class="modal__header u-fs-18">
10915 <div class="u-ta-center">
10916 <strong><span class="u-underline"><span class="js-product-name">@lineAdjusted.ProductName</span>@Translate("Smartpage:CartLineAdjustedModal.AdjustedNotification", " kan ikke købes i det ønskede antal.")</span></strong>
10917 </div>
10918 </div>
10919 <div class="modal__body">
10920 <div class="grid grid--justify-center">
10921 <div class="grid__col-12 grid__col-lg-4-auto">
10922 <div class="u-ta-center js-text-description u-margin-bottom">
10923 <span>@String.Format(Translate("Smartpage:CartLineAdjustedModal.NewStock", "Der er desværre kun {0} stk. tilbage."), lineAdjusted.NewQuantity)</span><br />
10924 </div>
10925 </div>
10926 </div>
10927 </div>
10928
10929
10930 }
10931 <a href="/Default.aspx?ID=@cartPageId" class="modal__close-btn u-margin-top-5" onclick="document.getElementById('CartLineAdjustedModalTrigger').checked = false;"></a>
10932
10933 <div class="grid">
10934 <div class="grid__col-12-auto u-flex--row u-justify-content--center">
10935 <div class="grid__col-6-auto">
10936 <a href="/Default.aspx?ID=@cartPageId" class="btn btn--secondary u-no-margin--bottom dw-mod js-dismiss-modal" onclick="document.getElementById('CartLineAdjusteddModalTrigger').checked = false;">@Translate("Smartpage:CartLineAdjustedModal.Back", "Tilbage til kurv")</a>
10937 </div>
10938 </div>
10939 </div>
10940 </div>
10941 </div>
10942
10943 }
10944
10945 if (Dynamicweb.Context.Current.Items["Smartpage:RemovedInactiveLine"] != null)
10946 {
10947 var lineRemovedNotification = Dynamicweb.Context.Current.Items["Smartpage:RemovedInactiveLine"] as List<LineRemoved>;
10948
10949 <input type="checkbox" id="CartLineRemovedModalTrigger" class="modal-trigger" checked>
10950 <div class="modal-container">
10951 <label class="modal-overlay"></label>
10952 <div class="modal modal--lg modal-height--auto" id="CartLineRemovedModal">
10953 @foreach (LineRemoved lineRemoved in lineRemovedNotification)
10954 {
10955 string reason = lineRemoved.ReasonDescription == "NotInStock" ? "Varen er desværre blevet udsolgt i mellemtiden." : "Der er sket en fejl.";
10956
10957 <div class="modal__header u-fs-18">
10958 <div class="u-ta-center">
10959 <strong><span class="u-underline"><span class="js-product-name">@lineRemoved.ProductName</span>@Translate("Smartpage:CartLineRemovedModal.IsRemovedNotifacation", " er blevet fjernet fra kurven")</span></strong>
10960 </div>
10961 </div>
10962 <div class="modal__body">
10963 <div class="grid grid--justify-center">
10964 <div class="grid__col-12 grid__col-lg-4-auto">
10965 <div class="u-ta-center js-text-description u-margin-bottom">
10966 <span>@Translate("Smartpage:CartLineRemoval.CouldNotAdd", "Kunne ikke tilføje")</span> @lineRemoved.ProductName <br />
10967 <span>@Translate("Smartpage:CartLineRemoval.Reason." + reason, reason)</span>
10968 </div>
10969 </div>
10970 </div>
10971 </div>
10972
10973
10974 <a href="/Default.aspx?ID=@cartPageId" class="modal__close-btn u-margin-top-5" onclick="document.getElementById('CartLineRemovedModalTrigger').checked = false;"></a>
10975 }
10976 <div class="grid">
10977 <div class="grid__col-12-auto u-flex--row u-justify-content--center">
10978 <div class="grid__col-6-auto">
10979 <a href="/Default.aspx?ID=@cartPageId" class="btn btn--secondary u-no-margin--bottom dw-mod js-dismiss-modal" onclick="document.getElementById('CartLineRemovedModalTrigger').checked = false;">@Translate("Smartpage:CartLineRemovedModal.OK", "OK")</a>
10980 </div>
10981 </div>
10982 </div>
10983 </div>
10984 </div>
10985
10986 }
10987
10988 }
10989
10990 @helper RenderModalSubheading(RecommendationItem recommendationItem)
10991 {
10992 <div class="u-flex grid--align-center">
10993 <div class="seperation-line u-margin-right--lg"></div>
10994 <h3 class="heading-over-slider grid--justify-center whitespace-nowrap">@recommendationItem.Headline</h3>
10995 <div class="seperation-line u-margin-left--lg"></div>
10996 </div>
10997 @RenderRecommendations(recommendationItem)
10998
10999 }
11000
11001 @helper RenderRecommendations(RecommendationItem recommendationItem)
11002 {
11003 string feedUrl = recommendationItem.GetUrl(GetPageIdByNavigationTag("ProductsPageNoFacets"));
11004
11005 <div class="product-slider-item js-product-slider-item js-recommendation-item-container" data-initialized="false">
11006 <div id="@recommendationItem.Id" class="add-to-cart-slider" data-slides-amount="@recommendationItem.NumberOfSlides">
11007 <div class="js-handlebars-root-async js-add-to-cart-product-slider grid" id="@recommendationItem.Id" data-template="@("ProductContainer_" + recommendationItem.Id)" data-json-feed="@feedUrl"></div>
11008 <div class="product-slider-preloader js-product-slider-preloader product-slider-preloader--loading">
11009 <div class="preloader-overlay__icon js-product-slider-preloader-icon"></div>
11010 </div>
11011 </div>
11012 </div>
11013 }
11014
11015
11016 @helper RenderAddToCartNotificationToggleScript()
11017 {
11018 int miniCartFeedPageId = GetPageIdByNavigationTag("MiniCartFeed");
11019
11020 <script>
11021 document.addEventListener('addToCart', function (event) {
11022 if (event.detail.lineNotAddedNotification != null) {
11023 showCartLineNotAddedModal(event.detail.lineNotAddedNotification);
11024 } else {
11025 Cart.ToggleMiniCart('miniCartTrigger', 'miniCart', 'cartCounter', '@miniCartFeedPageId');
11026 }
11027 });
11028 </script>
11029 }
11030
11031 @helper RenderCheckmark()
11032 {
11033 <svg class="added-to-cart-checkmark" width="25px" height="18px" viewBox="0 0 25 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
11034 <title>01130066-C57C-43F6-B6A2-489724630A18</title>
11035 <g id="Powerstep" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
11036 <g transform="translate(-673.000000, -79.000000)" fill="#50A87D" id="Group-2">
11037 <g transform="translate(532.000000, 30.000000)">
11038 <g id="Group" transform="translate(62.279070, 31.000000)">
11039 <g id="Tilføjet-til-kurven" transform="translate(78.720930, 13.000000)">
11040 <path d="M0.359445042,14.8016255 C-0.119815014,14.3303213 -0.119815014,13.5661551 0.359445042,13.0948038 L2.0950309,11.3879821 C2.57429096,10.9166307 3.35140464,10.9166307 3.8306647,11.3879821 L9.20454246,16.6726046 L20.7147898,5.35347814 C21.1940499,4.88217395 21.9711636,4.88217395 22.4504236,5.35347814 L24.1860095,7.06029986 C24.6652696,7.53160404 24.6652696,8.29577025 24.1860095,8.76712158 L10.0723594,22.6465278 C9.59305136,23.1178319 8.81598562,23.1178319 8.33672556,22.6464806 L0.359445042,14.8016255 Z" id="Checkmark"></path>
11041 </g>
11042 </g>
11043 </g>
11044 </g>
11045 </g>
11046 </svg>
11047 }
11048 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>
11049 @using Dynamicweb.Rapido.Blocks.Extensibility
11050 @using Dynamicweb.Rapido.Blocks
11051 @using Dynamicweb.Ecommerce.Common
11052 @using Dynamicweb.Frontend.Navigation
11053
11054
11055 @{
11056 BlocksPage referencesBlocksPage = BlocksPage.GetBlockPage("Master");
11057
11058 Block masterScriptReferences = new Block()
11059 {
11060 Id = "MasterScriptReferences",
11061 SortId = 1,
11062 Template = RenderMasterScriptReferences()
11063 };
11064 referencesBlocksPage.Add(MasterBlockId.MasterReferences, masterScriptReferences);
11065
11066 Block googleBreadcrumbSchema = new Block()
11067 {
11068 Id = "GoogleBreadcrumbSchema",
11069 SortId = 2,
11070 Template = RenderGoogleBreadcrumbSchema()
11071 };
11072 referencesBlocksPage.Add(MasterBlockId.MasterReferences, googleBreadcrumbSchema);
11073
11074 Block googleOrganizationSchema = new Block()
11075 {
11076 Id = "GoogleBreadcrumbSchema",
11077 SortId = 2,
11078 Template = RenderGoogleOrganizationSchema()
11079 };
11080 referencesBlocksPage.Add(MasterBlockId.MasterReferences, googleOrganizationSchema);
11081
11082 }
11083
11084 @helper RenderGoogleOrganizationSchema()
11085 {
11086 string favicon = Model.Area.Item.GetItem("Layout").GetFile("LogoFavicon") != null ? Model.Area.Item.GetItem("Layout").GetFile("LogoFavicon").Path : "/Files/Images/favicon.png";
11087 string path = HttpContext.Current.Request.Url.Scheme + System.Uri.SchemeDelimiter + HttpContext.Current.Request.Url.Authority;
11088
11089 <script type="application/ld+json">
11090 {
11091 "@@context": "https://schema.org",
11092 "@@type": "Organization",
11093 "url": "@(path)",
11094 "logo": "@(path + favicon)"
11095 }
11096 </script>
11097
11098 }
11099
11100 @helper RenderGoogleBreadcrumbSchema()
11101 {
11102 var navigationSettings = new NavigationSettings();
11103 navigationSettings.StartLevel = Pageview.Page.ID == GetPageIdByNavigationTag("ProductsPage") ? 1 : 2;
11104 navigationSettings.StopLevel = 10;
11105 navigationSettings.ExpandMode = ExpandMode.PathOnly;
11106
11107 @Navigation.RenderNavigation("../Navigation/BreadcrumbGoogle.cshtml", navigationSettings)
11108 }
11109
11110 @helper RenderMasterScriptReferences()
11111 {
11112
11113 var fileVersion = System.Web.HttpContext.Current.Cache["FileVersion"];
11114
11115 <script src="/Files/Templates/Designs/Rapido/js/master.min.js?@fileVersion"></script>
11116
11117 if (Model.Area.Item.GetItem("Custom").GetBoolean("UseCustomJavascript"))
11118 {
11119 <script src="/Files/Templates/Designs/Rapido/js/custom.min.js?v=@fileVersion"></script>
11120 }
11121
11122 if (!string.IsNullOrEmpty(Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetString("PurchaseScript")) && !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request["CompletedOrderId"]))
11123 {
11124 <script src="@Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetString("PurchaseScript")"></script>
11125 }
11126 }
11127 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
11128
11129 @using System
11130 @using System.Web
11131 @using System.Collections.Generic
11132 @using Dynamicweb.Core
11133 @using Dynamicweb.Rapido.Blocks.Extensibility
11134 @using Dynamicweb.Rapido.Blocks
11135 @using Dynamicweb.Rapido.Blocks.Components.Ecommerce
11136 @using Dynamicweb.Rapido.Services
11137
11138 @{
11139 BlocksPage searchBlocksPage = BlocksPage.GetBlockPage("Master");
11140 bool navigationItemsHideSearch = Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("HideSearch");
11141 bool isFavoriteList = !string.IsNullOrEmpty(HttpContext.Current.Request.QueryString.Get("ListID"));
11142
11143 if (!navigationItemsHideSearch || isFavoriteList)
11144 {
11145 Block masterSearchScriptTemplates = new Block()
11146 {
11147 Id = "MasterSearchScriptTemplates",
11148 SortId = 1,
11149 Template = RenderSearchScriptTemplates()
11150 };
11151
11152 searchBlocksPage.Add(MasterBlockId.MasterBottomSnippets, masterSearchScriptTemplates);
11153 }
11154 }
11155
11156 @helper RenderSearchScriptTemplates()
11157 {
11158 int productsPageId = GetPageIdByNavigationTag("ProductsPage");
11159 string contentSearchPageLink = GetPageIdByNavigationTag("ContentSearchResults") + "&Areaid=" + Model.Area.ID;
11160 bool useFacebookPixel = !string.IsNullOrWhiteSpace(Pageview.AreaSettings.GetItem("Settings").GetString("FacebookPixelID"));
11161 bool useGoogleTagManager = !string.IsNullOrEmpty(Model.Area.Item.GetItem("Settings").GetString("GoogleTagManagerID"));
11162 bool showPrice = !Pageview.AreaSettings.GetItem("Layout").GetBoolean("HidePriceInSearchResults");
11163 bool showAddToCartButton = !Pageview.AreaSettings.GetItem("Layout").GetBoolean("HideAddToCartButton");
11164 bool showViewButton = !Pageview.AreaSettings.GetItem("Layout").GetBoolean("HideViewButton");
11165 bool showAddToDownloadButton = Pageview.AreaSettings.GetItem("Layout").GetBoolean("ShowAddToDownloadButton");
11166 bool pointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly");
11167 var uspList = Pageview.AreaSettings.GetItem("Custom").GetItems("USPList");
11168
11169 <script id="SearchGroupsTemplate" type="text/x-template">
11170 {{#.}}
11171 <li class="dropdown__item dw-mod" onclick="Search.UpdateGroupSelection(this)" data-group-id="{{id}}">{{name}}</li>
11172 {{/.}}
11173 </script>
11174
11175 <script id="SearchProductsTemplate" type="text/x-template">
11176 {{#AnySpecificElements . 'ProductGridItemContainer'}}
11177 {{#each .}}
11178 {{#Product}}
11179 {{#ifCond template "!==" "SearchMore"}}
11180 <li class="dropdown__item dropdown__item--seperator dw-mod">
11181 @if (useFacebookPixel)
11182 {
11183 <text>{{{facebookPixelSearch name number priceDouble currency searchParameter}}}</text>
11184 }
11185 @if (useGoogleTagManager)
11186 {
11187 <text>{{{googleEnchantImpression googleImpression}}}</text>
11188 }
11189 <div>
11190 <a href="{{link}}"
11191 class="js-typeahead-link u-color-inherit u-pull--left"
11192 onclick="{{#if googleImpression}}googleEnchantImpressionClick({{googleImpression}}, event){{/if}}"
11193 title="{{name}}{{#if variantName}}, {{variantName}}{{/if}}">
11194 <div class="u-margin-right u-pull--left {{noimage}} u-hidden-xs u-hidden-xxs"><img class="b-lazy" src="/Files/Images/placeholder.gif" data-src="/Admin/Public/GetImage.ashx?width=45&height=36&crop=5&FillCanvas=True&Compression=75&image={{image}}" alt="{{name}}{{#if variantName}}, {{variantName}}{{/if}}"></div>
11195 <div class="u-pull--left">
11196 <div class="u-bold u-max-w220px u-truncate-text js-typeahead-name">{{name}}{{#if variantName}}, {{variantName}}{{/if}}</div>
11197 @if (showPrice && Dynamicweb.Rapido.Services.User.IsPricesAllowed())
11198 {
11199 if (pointShopOnly)
11200 {
11201 <text>
11202 {{#if havePointPrice}}
11203 <div>
11204 <span class="u-color--loyalty-points">{{points}}</span> @Translate("points")
11205 </div>
11206 {{else}}
11207 <small class="help-text u-no-margin">@Translate("Not available")</small>
11208 {{/if}}
11209 {{#unless canBePurchasedWithPoints}}
11210 {{#if havePointPrice}}
11211 <small class="help-text u-no-margin">@Translate("Not enough points to buy this")</small>
11212 {{/if}}
11213 {{/unless}}
11214 </text>
11215 }
11216 else
11217 {
11218 <div>{{price}}</div>
11219 }
11220 }
11221 </div>
11222 </a>
11223 <div class="u-margin-left u-pull--right">
11224 @{
11225 var viewBtn = new Link
11226 {
11227 Href = "{{link}}",
11228 OnClick = "{{#if googleImpression}}googleEnchantImpressionClick({{googleImpression}}, event){{/if}}",
11229 ButtonLayout = ButtonLayout.Secondary,
11230 CssClass = "btn--condensed u-no-margin js-ignore-click-outside search btn--add-to-cart",
11231 Title = Translate("View")
11232 };
11233 }
11234 @if (showAddToCartButton && Dynamicweb.Rapido.Services.User.IsBuyingAllowed())
11235 {
11236 <text>{{#if hideAddToCartButton}}</text>
11237 @Render(viewBtn)
11238 <text>{{else}}</text>
11239 @Render(new AddToCartButton
11240 {
11241 HideTitle = true,
11242 ProductId = "{{productId}}",
11243 ProductInfo = "{{productInfo}}",
11244 BuyForPoints = pointShopOnly,
11245 OnClick = "{{facebookPixelAction}}",
11246 CssClass = "u-no-margin js-ignore-click-outside search btn--add-to-cart",
11247 Title = Translate("Buy"),
11248 ExtraAttributes = new Dictionary<string, string>
11249 {
11250 { "{{disabledBuyButton}}", "" }
11251 }
11252 })
11253 <text>{{/if}}</text>
11254 }
11255 else if (showViewButton)
11256 {
11257 @Render(viewBtn)
11258 }
11259 @if (showAddToDownloadButton)
11260 {
11261 <button type="button" class="btn btn--primary u-no-margin btn--condensed dw-mod js-add-to-downloads search" title="@Translate("Add")" data-product-id="{{productId}}">
11262 @Translate("Buy")
11263 </button>
11264 }
11265 </div>
11266 </div>
11267 </li>
11268 {{/ifCond}}
11269 {{#ifCond template "===" "SearchMore"}}
11270 {{>SearchMoreProducts}}
11271 {{/ifCond}}
11272 {{/Product}}
11273 {{/each}}
11274 {{else}}
11275 <li class="dropdown__item dropdown__item--seperator dropdown__item--not-selectable js-no-result dw-mod">
11276 @Translate("Your search gave 0 results")
11277 </li>
11278 {{/AnySpecificElements}}
11279 </script>
11280
11281 <script id="SearchFavoriteProductsTemplate" type="text/x-template">
11282 {{#AnySpecificElements . 'ProductDetailsItemContainer'}}
11283 {{#each .}}
11284 {{#Product}}
11285 {{#ifCond template "!==" "SearchMore"}}
11286 <li class="dropdown__item dropdown__item--seperator dw-mod">
11287 @if (useFacebookPixel)
11288 {
11289 <text>{{{facebookPixelSearch name number priceDouble currency searchParameter}}}</text>
11290 }
11291 @if (useGoogleTagManager)
11292 {
11293 <text>{{{googleEnchantImpression googleImpression}}}</text>
11294 }
11295 <div>
11296 <a href="{{link}}"
11297 class="js-typeahead-link u-color-inherit u-pull--left"
11298 onclick="{{#if googleImpression}}googleEnchantImpressionClick({{googleImpression}}, event){{/if}}"
11299 title="{{name}}{{#if variantName}}, {{variantName}}{{/if}}">
11300 <div class="u-margin-right u-pull--left {{noimage}} u-hidden-xs u-hidden-xxs"><img class="b-lazy" src="/Files/Images/placeholder.gif" data-src="/Admin/Public/GetImage.ashx?width=45&height=36&crop=5&FillCanvas=True&Compression=75&image={{image}}" alt="{{name}}{{#if variantName}}, {{variantName}}{{/if}}"></div>
11301 <div class="u-pull--left">
11302 <div class="u-bold u-max-w220px u-truncate-text js-typeahead-name">{{name}}{{#if variantName}}, {{variantName}}{{/if}}</div>
11303 @if (showPrice && Dynamicweb.Rapido.Services.User.IsPricesAllowed())
11304 {
11305 if (pointShopOnly)
11306 {
11307 <text>
11308 {{#if havePointPrice}}
11309 <div>
11310 <span class="u-color--loyalty-points">{{points}}</span> @Translate("points")
11311 </div>
11312 {{else}}
11313 <small class="help-text u-no-margin">@Translate("Not available")</small>
11314 {{/if}}
11315 {{#unless canBePurchasedWithPoints}}
11316 {{#if havePointPrice}}
11317 <small class="help-text u-no-margin">@Translate("Not enough points to buy this")</small>
11318 {{/if}}
11319 {{/unless}}
11320 </text>
11321 }
11322 else
11323 {
11324 <div>{{price}}</div>
11325 }
11326 }
11327 </div>
11328 </a>
11329 <div class="u-margin-left u-pull--right">
11330 @{
11331 var viewBtnFavorites = new Link
11332 {
11333 Href = "{{link}}",
11334 OnClick = "{{#if googleImpression}}googleEnchantImpressionClick({{googleImpression}}, event){{/if}}",
11335 ButtonLayout = ButtonLayout.Secondary,
11336 CssClass = "btn--condensed u-no-margin js-ignore-click-outside search btn--add-to-cart",
11337 Title = Translate("View")
11338 };
11339 }
11340 @if (showAddToCartButton && Dynamicweb.Rapido.Services.User.IsBuyingAllowed())
11341 {
11342 <text>{{#if hideAddToCartButton}}</text>
11343 @Render(viewBtnFavorites)
11344 <text>{{else}}</text>
11345 @Render(new AddToCartButton
11346 {
11347 HideTitle = true,
11348 ProductId = "{{productId}}",
11349 ProductInfo = "{{productInfo}}",
11350 BuyForPoints = pointShopOnly,
11351 OnClick = "{{facebookPixelAction}}",
11352 CssClass = "u-no-margin js-ignore-click-outside search btn--add-to-cart",
11353 Title = Translate("Buy"),
11354 ExtraAttributes = new Dictionary<string, string>
11355 {
11356 { "{{disabledBuyButton}}", "" }
11357 }
11358 })
11359 <text>{{/if}}</text>
11360 }
11361 else if (showViewButton)
11362 {
11363 @Render(viewBtnFavorites)
11364 }
11365 @if (showAddToDownloadButton)
11366 {
11367 <button type="button" class="btn btn--primary u-no-margin btn--condensed dw-mod js-add-to-downloads search" title="@Translate("Add")" data-product-id="{{productId}}">
11368 @Translate("Buy")
11369 </button>
11370 }
11371 </div>
11372 </div>
11373 </li>
11374 {{/ifCond}}
11375 {{#ifCond template "===" "SearchMore"}}
11376 {{>SearchMoreProducts}}
11377 {{/ifCond}}
11378 {{/Product}}
11379 {{/each}}
11380 {{else}}
11381 <li class="dropdown__item dropdown__item--seperator dropdown__item--not-selectable js-no-result dw-mod">
11382 @Translate("Your search gave 0 results")
11383 </li>
11384 {{/AnySpecificElements}}
11385 </script>
11386
11387 <script id="SearchMoreProducts" type="text/x-template">
11388 <li class="dropdown__item dropdown__item--not-selectable {{stickToBottom}} dw-mod">
11389 <a href="/Default.aspx?ID=@productsPageId&Search={{searchParameter}}&GroupID={{groupId}}" class="btn btn--primary btn--full u-no-margin dw-mod js-typeahead-link search">
11390 @Translate("View all")
11391 </a>
11392 </li>
11393 </script>
11394
11395 <script id="SearchMorePages" type="text/x-template">
11396 <li class="dropdown__item dropdown__item--not-selectable {{stickToBottom}} dw-mod">
11397 <a href="/Default.aspx?ID=@contentSearchPageLink&Search={{searchParameter}}" class="btn btn--primary btn--full u-no-margin dw-mod js-typeahead-link search">
11398 @Translate("View all")
11399 </a>
11400 </li>
11401 </script>
11402
11403 <script id="SearchPagesTemplate" type="text/x-template">
11404 {{#each .}}
11405 {{#ifCond template "!==" "SearchMore"}}
11406 <li class="dropdown__item dropdown__item--seperator dropdown__item--no-padding dw-mod">
11407 <a href="/Default.aspx?ID={{id}}" class="js-typeahead-link dropdown__link u-color-inherit">
11408 <div class="u-margin-right"><i class="fa {{icon}} u-w20px u-ta-center"></i></div>
11409 <div class="u-bold u-truncate-text u-max-w220px js-typeahead-name">{{name}}</div>
11410 </a>
11411 </li>
11412 {{/ifCond}}
11413 {{#ifCond template "===" "SearchMore"}}
11414 {{>SearchMorePages}}
11415 {{/ifCond}}
11416 {{else}}
11417 <li class="dropdown__item dropdown__item--seperator dropdown__item--not-selectable js-no-result dw-mod">
11418 @Translate("Your search gave 0 results")
11419 </li>
11420 {{/each}}
11421 </script>
11422
11423 <script id="SearchPagesTemplateWrap" type="text/x-template">
11424 <div class="dropdown__column-header">@Translate("Pages")</div>
11425 <ul class="dropdown__list u-min-w220px u-full-width u-margin-bottom u-height--auto u-flex-grow--1 dw-mod">
11426 {{>SearchPagesTemplate}}
11427 </ul>
11428 </script>
11429
11430 <script id="SearchProductsTemplateWrap" type="text/x-template">
11431 <div class="dropdown__column-header">@Translate("Products")</div>
11432 <ul class="dropdown__list u-min-w220px u-full-width u-margin-bottom u-height--auto u-flex-grow--1 dw-mod">
11433 {{>SearchProductsTemplate}}
11434 </ul>
11435 </script>
11436 <script id="SearchSpellCheckerSuggestionsTemplateWrap" type="text/x-template">
11437 {{#AnySpecificElements . 'SpellCheckerSuggestion'}}
11438 <div class="dropdown__column-header u-bold">@Translate("Smartpage:Search.SpellCheckerSuggestions.Header", "Mente du?")</div>
11439 <ul class="dropdown__list u-min-w220px u-full-width u-margin-bottom u-height--auto u-flex-grow--1 dw-mod u-padding js-ignore-click-outside spell-checker-suggestions">
11440 {{>SearchSpellCheckerSuggestionsTemplate}}
11441 </ul>
11442 {{/AnySpecificElements}}
11443 </script>
11444
11445 <script id="SearchSpellCheckerSuggestionsTemplate" type="text/x-template">
11446 {{#each .}}
11447 {{#SpellCheckerSuggestion}}
11448 <div class="js-ignore-click-outside js-spell-checker-suggestion spell-checker-suggestion">
11449 {{#if @@last}}
11450 <span>{{suggestion}}</span>
11451 {{else}}
11452 <span>{{suggestion}}</span>,
11453 {{/if}}
11454 </div>
11455 {{/SpellCheckerSuggestion}}
11456 {{/each}}
11457 </script>
11458
11459 var imagePrefix = "/Admin/Public/GetImage.ashx?width=150&height=300&crop=5&Compression=75&FillCanvas=true&DoNotUpscale=true&image=";
11460
11461 // CDN
11462 var cdnUrl = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetString("CDNUrl");
11463 bool cdnActivate = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetBoolean("CDNActivate");
11464 if (!string.IsNullOrWhiteSpace(cdnUrl) && cdnActivate)
11465 {
11466 imagePrefix = cdnUrl + imagePrefix;
11467 }
11468
11469 string columnCss = Pageview.Device.ToString() == "Mobile" ? "grid__col--bleed" : "grid__col--bleed-y";
11470
11471 <script id="SearchResultsTypeAheadWithFilters" type="text/x-template">
11472 {{#.}}
11473 <div class="grid__col-3 u-padding-left-none">
11474 <div class="search-modal-result__title grid__col-12">
11475 <h2 class="search-modal-header u-padding-left-none">
11476 {{searchTermHeader}}
11477 </h2>
11478 </div>
11479 <div id="SearchTermPredictions" class="search-term-predictions">
11480 <ul class="u-padding-none u-margin-top max-height-overflow">
11481 {{#SearchTermPredictions}}
11482 <li class="u-flex whitespace-nowrap">
11483 <a class="u-flex link" href="/Default.aspx?Id=@productsPageId&Search={{Term}}">
11484 <img class="u-margin-right" src="/Files/Images/SvgIcons/Link-arrow.svg" />
11485 <div class="js-search-term-prediction whitespace-nowrap">{{Term}}</div>
11486 </a>
11487 </li>
11488 {{/SearchTermPredictions}}
11489 </ul>
11490 </div>
11491 <div>
11492 <h2 class="grid__col-12 u-no-margin custom-text-style facet-header">@Translate("Custom:Search.Modal.Filters.Header", "Filtre")</h2>
11493 <input type="checkbox" id="CheckFacetGroups" class="js-remember-state u-hidden" data-expand="CheckFacetGroups" />
11494 <div class="grid__col-12 search-facets-container facets-container facets-container--left expandable--collapsed dw-mod" data-trigger="CheckFacetGroups">
11495 {{#FacetGroups}}
11496 <input type="hidden" class="js-remove-facet-parameters_{{queryParameter}}" value="{{queryParameter}}" data-type="{{template}}" />
11497 <input type="checkbox" id="OptionsGroup_{{name}}" class="expand-trigger js-remember-state" {{defaultState}} />
11498 <div class="expand-container facets-container__box dw-mod js-filter custom-border">
11499 <label class="expand-container__btn facets-container__header dw-mod js-facets-container-header" for="OptionsGroup_{{name}}">{{name}}</label>
11500 <div class="expand-container__content dw-mod">
11501 <div class="u-margin {{showFilter}}">
11502 <input type="text" class="u-full-width u-no-margin custom-border" onkeyup="Filter.FilterItems(event)" placeholder="@Translate("Search")" />
11503 </div>
11504 <div class="facets-container__list dw-mod {{template}}">
11505 {{#FacetOptions}}
11506 {{#ifCond template "===" "Checkboxes"}}
11507 {{>SearchFacetsCheckboxes}}
11508 {{/ifCond}}
11509 {{/FacetOptions}}
11510 <div class="u-hidden js-filter-not-found">
11511 @Translate("Your search gave 0 results")
11512 </div>
11513 </div>
11514 </div>
11515 </div>
11516 {{/FacetGroups}}
11517 </div>
11518 <label for="CheckFacetGroups" class="btn btn--primary btn--full u-no-margin dw-mod js-expand-hide facets-container-trigger facets-expander" data-trigger="CheckFacetGroups">
11519 @Translate("Select filters")
11520 <i class="facets-filter-icon"></i>
11521 </label>
11522 <label for="CheckFacetGroups" class="btn btn--primary btn--full u-no-margin dw-mod expandable--collapsed facets-container-trigger facets-expander" data-trigger="CheckFacetGroups">
11523 @Translate("Close filters")
11524 <i class="facets-filter-icon"></i>
11525 </label>
11526 </div>
11527 {{#unless beforeSearch}}
11528 <div class="links-section">
11529 <h2 class="search-modal-header u-padding-left-none">
11530 @Translate("Smartpage:Search.Modal.Links.Header", "Inspiration & hjælp")
11531 </h2>
11532 <ul class="u-padding-none u-margin-top">
11533 @foreach (var usp in uspList)
11534 {
11535 var icon = usp.GetFile("Icon");
11536 <li class="u-flex whitespace-nowrap">
11537 @if (!string.IsNullOrWhiteSpace(usp.GetString("Link")))
11538 {
11539 <a class="u-flex link" href="@usp.GetString("Link")">
11540 @{
11541 if (icon != null)
11542 {
11543 <img class="u-margin-right" src="@icon.Path" alt="@HttpUtility.HtmlAttributeEncode(usp.GetString("Label"))" />
11544 }
11545 else
11546 {
11547 <i class="fa fa-check u-margin-right u-flex u-flex--align-center"></i>
11548 }
11549 }
11550 @usp.GetString("Label")
11551 </a>
11552 }
11553 else
11554 {
11555 if (icon != null)
11556 {
11557 <img class="u-margin-right" src="@icon.Path" alt="@HttpUtility.HtmlAttributeEncode(usp.GetString("Label"))" />
11558 }
11559 else
11560 {
11561 <i class="fa fa-check u-margin-right u-flex u-flex--align-center"></i>
11562 } @usp.GetString("Label")
11563 }
11564 </li>
11565
11566 }
11567 </ul>
11568 </div>
11569 {{/unless}}
11570 </div>
11571 <div class="grid grid__col-9">
11572 <div class="search-modal-result__title grid__col-12">
11573 {{#if header}}
11574 <h2 class="search-modal-header">
11575 {{header}}
11576 </h2>
11577 {{/if}}
11578 {{#if searchHeader}}
11579 <a class="u-underline see-all-link" href="/Default.aspx?ID=@productsPageId&Search={{searchParameter}}">
11580 {{searchHeader}}
11581 </a>
11582 {{/if}}
11583 </div>
11584 <div id="SearchProductsContainer" class="products grid__col-12" data-template="SearchResultsProductsOnly">
11585 {{#if hits}}
11586 {{> SearchResultsProductsOnly this}}
11587 </div>
11588 {{#if searchParameter}}
11589 {{#if totalProductsCount}}
11590 <div class="grid__col-12 @columnCss show-more {{nextdisabled}}">
11591 <div class="show-more-counter-text">
11592 @Translate("Smartpage:Counter.HaveSeen", "Du har set") <strong class="js-curr-amount-products @(!string.IsNullOrEmpty(HttpContext.Current.Request.QueryString.Get("ListID")) ? "js-favorite-product-list-products-counter" : "")">{{currentProducts}}</strong>
11593 @Translate("Smartpage:Counter.OutOf", "af") <strong>{{totalProductsCount}}</strong> @Translate("Smartpage.Counter.Products", "produkter")
11594 </div>
11595 <a href="{{nextPageClean}}" id="LoadMoreButton" class="btn btn--secondary load-more-button js-search-modal-load-more-button dw-mod" data-current="{{currentPage}}" data-page-size="{{pageSize}}" data-total="{{totalPages}}" data-container="SearchProductsContainer" data-feed-url="{{moreFeedFullUrl}}" onclick="LoadMore.Next(event, this, 'undefined', 'searchModal')" {{nextdisabled}}>@Translate("Smartpage:Productlist.LoadMore", "Load more")</a>
11596 </div>
11597 {{/if}}
11598 <div class="grid__col-12 search-more-button">
11599 <a href="/Default.aspx?ID=@productsPageId&Search={{searchParameter}}" class="btn btn--primary btn--full u-no-margin dw-mod js-typeahead-link js-typeahead-with-filters-link search">
11600 @Translate("Smartpage:Search.ShowAllButton.Text", "Se alle {{totalProductsCount}} resultater")
11601 </a>
11602 </div>
11603 {{/if}}
11604 {{else}}
11605 <span>@Translate("Smartpage:Search.NoMatch", "Intet matchede") <b> {{searchParameter}} </b> @Translate("Smartpage:Search.NoMatch.Suggestion", "... prøv en anden søgning!")</span>
11606 {{/if}}
11607 </div>
11608 {{/.}}
11609 </script>
11610
11611 <script id="SearchResultsProductsOnly" type="text/x-template">
11612 {{#.}}
11613 {{#if hits}}
11614 {{#ProductsContainerList}}
11615 {{#Product}}
11616 <div class="grid__col-4">
11617 <a class="search-product grid" href="{{link}}" onclick="{{#if googleImpression}} googleEnchantImpressionClick({{googleImpression}}, event, true) {{/if}}" title="{{{name}}}">
11618 <div class="search-product__image grid__col-3 u-no-padding {{bomProductClass}} {{eventClass}} {{cocktailClass}}">
11619 <div class="grid-image" style="background-image: url('@imagePrefix{{image}}');" alt="{{name}}"></div>
11620 </div>
11621 <div class="search-product__info grid__col-9 u-no-padding">
11622 <div class="labels">
11623 {{#Labels}}
11624 <div class="top-label">
11625 <div class="top-label__label top-label__label" style="background-color:{{labelBgColor}}; color:{{labelTextColor}}">
11626 {{labelText}}
11627 {{#if tooltipText}}
11628 <i class="fal fa-question-circle info-icon js-tooltip tooltip-icon tooltip-icon--product-list" data-tooltip-placement="{{tooltipPlacement}}" data-tooltip-content="{{tooltipText}}"></i>
11629 {{/if}}
11630 </div>
11631 </div>
11632 {{/Labels}}
11633 </div>
11634 <div class="search-product__name js-typeahead-search-product-name">
11635 {{name}}
11636 </div>
11637 {{#unless eventProduct}}
11638 {{#if bomItemSavings}}
11639 <div class="savings">@Translate("Smartpage:ProductList.Product.Save", "SPAR") <strong>{{bomItemSavingsFormatted}}</strong></div>
11640 {{else if savings}}
11641 <div class="savings">@Translate("Smartpage:ProductList.Product.Save", "SPAR") <strong>{{savings}}</strong> @Translate("Smartpage:ProductList.Product.PerUnit", "PR. FL.")</div>
11642 {{else}}
11643 {{/if}}
11644 {{/unless}}
11645 <div class="search-product__price">
11646 <div>{{price}}{{#if isSubscription}}@Translate("Smartpage:Checkout.PerMonth", "/md"){{/if}}</div>
11647 <div class="quantity-price">
11648 {{{quantityDescription}}}
11649 </div>
11650 </div>
11651 </div>
11652 </a>
11653 </div>
11654 {{/Product}}
11655 {{/ProductsContainerList}}
11656 {{/if}}
11657 {{/.}}
11658 </script>
11659
11660 string searchType = !string.IsNullOrEmpty(Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Layout").GetRawValueString("TopSearch")) ? Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Layout").GetRawValueString("TopSearch") : "productSearch";
11661 if (searchType == "productSearchWithFilters")
11662 {
11663 <script id="SearchFacetsCheckboxes" type="text/x-template">
11664 <div class="form__field-group u-no-margin dw-mod">
11665 <input type="checkbox" class="{{selected}} js-checkbox-facet checkbox-facet__checkbox form__control dw-mod" onclick="Facets.UpdateFacets(this);" id="{{queryParameter}}{{value}}" name="{{queryParameter}}" value="[{{value}}]" {{selected}} {{disabled}} data-products-count="{{count}}">
11666 <label class="{{disabled}} checkbox-facet dw-mod" data-filter-value="{{label}}" for="{{queryParameter}}{{value}}">
11667 <span class="checkbox-facet__label dw-mod">{{label}}</span>
11668 <span class="checkbox-facet__count dw-mod">({{count}})</span>
11669 </label>
11670 </div>
11671 </script>
11672 }
11673
11674 <script id="SearchResultsTypeAhead" type="text/x-template">
11675 {{#.}}
11676 <div class="grid__col-3 u-padding-left-none">
11677 <div class="search-modal-result__title grid__col-12">
11678 <h2 class="search-modal-header u-padding-left-none">
11679 {{searchTermHeader}}
11680 </h2>
11681 </div>
11682 <div id="SearchTermPredictions" class="search-term-predictions">
11683 <ul class="u-padding-none u-margin-top">
11684 {{#SearchTermPredictions}}
11685 <li class="u-flex whitespace-nowrap">
11686 <a class="u-flex link" href="/Default.aspx?Id=@productsPageId&Search={{Term}}">
11687 <img class="u-margin-right" src="/Files/Images/SvgIcons/Link-arrow.svg" />
11688 <div class="js-search-term-prediction whitespace-nowrap">{{Term}}</div>
11689 </a>
11690 </li>
11691 {{/SearchTermPredictions}}
11692 </ul>
11693 </div>
11694 {{#unless beforeSearch}}
11695 <div class="links-section">
11696 <h2 class="search-modal-header u-padding-left-none">
11697 @Translate("Smartpage:Search.Modal.Links.Header", "Inspiration & hjælp")
11698 </h2>
11699 <ul class="u-padding-none u-margin-top">
11700 @foreach (var usp in uspList)
11701 {
11702 var icon = usp.GetFile("Icon");
11703 <li class="u-flex whitespace-nowrap">
11704 @if (!string.IsNullOrWhiteSpace(usp.GetString("Link")))
11705 {
11706 <a class="u-flex link" href="@usp.GetString("Link")">
11707 @{
11708 if (icon != null)
11709 {
11710 <img class="u-margin-right" src="@icon.Path" alt="@HttpUtility.HtmlAttributeEncode(usp.GetString("Label"))" />
11711 }
11712 else
11713 {
11714 <i class="fa fa-check u-margin-right u-flex u-flex--align-center"></i>
11715 }
11716 }
11717 @usp.GetString("Label")
11718 </a>
11719 }
11720 else
11721 {
11722 if (icon != null)
11723 {
11724 <img class="u-margin-right" src="@icon.Path" alt="@HttpUtility.HtmlAttributeEncode(usp.GetString("Label"))" />
11725 }
11726 else
11727 {
11728 <i class="fa fa-check u-margin-right u-flex u-flex--align-center"></i>
11729 } @usp.GetString("Label")
11730 }
11731 </li>
11732
11733 }
11734 </ul>
11735 </div>
11736 {{/unless}}
11737 </div>
11738 <div class="grid grid__col-9">
11739 <div class="search-modal-result__title grid__col-12">
11740 {{#if header}}
11741 <h2 class="search-modal-header">
11742 {{header}}
11743 </h2>
11744 {{/if}}
11745 {{#if searchHeader}}
11746 <a class="u-underline see-all-link" href="/Default.aspx?ID=@productsPageId&Search={{searchParameter}}">
11747 {{searchHeader}}
11748 </a>
11749 {{/if}}
11750 </div>
11751 <div class="products grid__col-12">
11752 {{#if hits}}
11753 {{> SearchResultsProductsOnly this}}
11754 </div>
11755 {{#if searchParameter}}
11756 <div class="grid__col-12 search-more-button">
11757 <a href="/Default.aspx?ID=@productsPageId&Search={{searchParameter}}" class="btn btn--primary btn--full u-no-margin dw-mod js-typeahead-link search">
11758 @Translate("Smartpage:Search.ShowAllButton.Text", "Se alle {{totalProductsCount}} resultater")
11759 </a>
11760 </div>
11761 {{/if}}
11762 {{else}}
11763 <span>@Translate("Smartpage:Search.NoMatch", "Intet matchede") <b> {{searchParameter}} </b> @Translate("Smartpage:Search.NoMatch.Suggestion", "... prøv en anden søgning!")</span>
11764 {{/if}}
11765 </div>
11766 {{/.}}
11767 </script>
11768
11769
11770
11771 <script id="SearchResultsTypeAheadMobile" type="text/x-template">
11772 {{#.}}
11773 <div class="typeahead-search-mobile">
11774 {{#if hits}}
11775 {{#if beforeSearch}}
11776 <div class="typeahead-search-recommendations-title">{{header}}</div>
11777 {{else}}
11778 <div class="typeahead-search-alternate-query">
11779 @Translate("Smartpage:Search.ShowingResults", "Viser søgeresultater for") <strong>"{{searchParameter}}"</strong>:
11780 </div>
11781 <div class="typeahead-bubble-container">
11782 <div class="typeahead-bubble-wrapper js-search-category" data-element-id="searchProducts" onclick='window.setSearchCategory(this)'>
11783 <div class="typeahead-talk-bubble js-bubble selected">
11784 <p class="typeahead-bubble-text">Produkter</p>
11785 </div>
11786 <div class="triangle js-triangle selected"></div>
11787 </div>
11788
11789 @*Use this later when implementing more search categories*@
11790 @*<div class="typeahead-bubble-wrapper js-search-category" data-element-id="searchCategories" onclick='window.setSearchCategory(this)'>
11791 <div class="typeahead-talk-bubble js-bubble">
11792 <p class="typeahead-bubble-text">Kategorier</p>
11793 </div>
11794 <div class="triangle js-triangle selected"></div>
11795 </div>
11796
11797 <div class="typeahead-bubble-wrapper js-search-category" data-element-id="SpRegionDescription" onclick='window.setSearchCategory(this)'>
11798 <div class="typeahead-talk-bubble js-bubble">
11799 <p class="typeahead-bubble-text">Områder</p>
11800 </div>
11801 <div class="triangle js-triangle selected"></div>
11802 </div>
11803
11804 <div class="typeahead-bubble-wrapper js-search-category" data-element-id="SpProducerName" onclick='window.setSearchCategory(this)'>
11805 <div class="typeahead-talk-bubble js-bubble">
11806 <p class="typeahead-bubble-text">Producenter</p>
11807 </div>
11808 <div class="triangle js-triangle selected"></div>
11809 </div>
11810
11811 <div class="typeahead-bubble-wrapper js-search-category" data-element-id="SpGrapePrimary" onclick='window.setSearchCategory(this)'>
11812 <div class="typeahead-talk-bubble js-bubble">
11813 <p class="typeahead-bubble-text">Druer</p>
11814 </div>
11815 <div class="triangle js-triangle selected"></div>
11816 </div>*@
11817 </div>
11818 {{/if}}
11819 <div class="typeahead-search-grid">
11820 @* Extra search category example *@
11821 @*<div class="typeahead-search-col js-search-results" id="searchCategories">
11822 <h2>test test</h2>
11823 </div>*@
11824 <div class="typeahead-search-col typeahead-flex-left js-search-results active" id="searchProducts">
11825 <div class="typeahead-search-products">
11826 {{#ProductsContainer}}
11827 {{#GroupedProducts}}
11828 <div class="typeahead-search-title">{{Category}}</div>
11829 {{#Products}}
11830 <a href="{{ link }}" onclick="{{#if googleImpression}}googleEnchantImpressionClick({{googleImpression}}, event, true){{/if}}">
11831 <div class="typeahead-search-product">
11832 <div class="typeahead-search-product-image-container">
11833 <div class="typeahead-search-product-image" style="background-image: url('{{ image }}');"></div>
11834 </div>
11835 <div class="typeahead-search-product-info">
11836 <div class="typeahead-search-product-name js-typeahead-search-product-name">{{ name }}</div>
11837 {{#unless ../../../beforeSearch}}
11838 <div class="typeahead-price-wrapper">
11839 <div class="typeahead-search-product-price">{{price}}</div>
11840 <div class="typeahead-search-product-kolli">
11841 {{{quantityDescription}}}
11842 </div>
11843 </div>
11844 {{/unless}}
11845 </div>
11846 <div class="typeahead-guillemet">
11847 »
11848 </div>
11849 </div>
11850 </a>
11851 {{/Products}}
11852 {{/GroupedProducts}}
11853 {{/ProductsContainer}}
11854 {{#if showAll}}
11855 <div class="typeahead-search-more-results typeahead-search-key-selectable">
11856 <a class="search-more-link" href="/produkter?Search={{searchParameter}}">
11857 @Translate("Smartpage:Search.SeeAllResults", "Se alle søgeresultater")
11858 </a>
11859 </div>
11860 {{/if}}
11861 </div>
11862 </div>
11863 </div>
11864 {{else}}
11865 <div class="typeahead-search-no-results">
11866 @Translate("Smartpage:Search.NoMatch", "Intet matchede") <b>{{searchParameter}}</b> @Translate("Smartpage:Search.NoMatch.Suggestion", "... prøv en anden søgning!")
11867 </div>
11868 {{/if}}
11869 </div>
11870 {{/.}}
11871 </script>
11872
11873 <script id="ProductSearchPreRenderContainer" type="text/x-template">
11874 <div class="search-pre-render-container">
11875 <div class="grid__col-3 u-padding-left-none pre-render-element--search-left-side">
11876 <div class="pre-render-element pre-render-element--search-header u-margin-top"></div>
11877 <div class="pre-render-element pre-render-element--search-terms"></div>
11878 </div>
11879 <div class="grid grid__col-9 pre-render-element--search-right-side">
11880 <div class="pre-render-element pre-render-element--search-header u-margin-top"></div>
11881 <div class="pre-render-element--search-products-container">
11882 @for (int i = 0; i < 9; i++)
11883 {
11884 <div class="pre-render-element pre-render-element--search-product"></div>
11885 }
11886 </div>
11887 </div>
11888 </div>
11889 </script>
11890 }
11891
11892 @using Dynamicweb.Rapido.Blocks.Components
11893 @using Dynamicweb.Rapido.Blocks.Components.General
11894 @using Dynamicweb.Rapido.Blocks
11895 @using System.IO
11896
11897
11898 @using Dynamicweb.Rapido.Blocks.Components.General
11899 @using Dynamicweb.Rapido.Blocks.Components.Ecommerce
11900
11901
11902 @* Component *@
11903
11904 @helper RenderVariantMatrix(VariantMatrix settings) {
11905 if (settings != null)
11906 {
11907 int productLoopCounter = 0;
11908 int groupCount = 0;
11909 List<VariantOption> firstDimension = new List<VariantOption>();
11910 List<VariantOption> secondDimension = new List<VariantOption>();
11911 List<VariantOption> thirdDimension = new List<VariantOption>();
11912
11913 foreach (VariantGroup variantGroup in settings.GetVariantGroups())
11914 {
11915 foreach (VariantOption variantOptions in variantGroup.GetVariantOptions())
11916 {
11917 if (groupCount == 0) {
11918 firstDimension.Add(variantOptions);
11919 }
11920 if (groupCount == 1)
11921 {
11922 secondDimension.Add(variantOptions);
11923 }
11924 if (groupCount == 2)
11925 {
11926 thirdDimension.Add(variantOptions);
11927 }
11928 }
11929 groupCount++;
11930 }
11931
11932 int rowCount = 0;
11933 int columnCount = 0;
11934
11935 <script>
11936 var variantsCollection = [];
11937 </script>
11938
11939 <table class="table table--compact js-variants-matrix dw-mod" id="VariantMatrixTable_@settings.ProductId">
11940 @if (groupCount == 1)
11941 {
11942 <tbody>
11943 @foreach (VariantOption firstVariantOption in firstDimension)
11944 {
11945 var variantId = firstVariantOption.Id;
11946 <tr>
11947 <td class="u-bold">
11948 @firstVariantOption.Name
11949 </td>
11950 <td>
11951 @RenderVariantMatrixQuantityField(variantId, settings, productLoopCounter, rowCount, columnCount)
11952 </td>
11953 </tr>
11954 productLoopCounter++;
11955 }
11956
11957 <tr>
11958 <td> </td>
11959 <td>
11960 <div class="qty-field js-total-qty-column-@columnCount dw-mod">0</div>
11961 </td>
11962 </tr>
11963 </tbody>
11964 }
11965 @if (groupCount == 2)
11966 {
11967 <thead>
11968 <tr>
11969 <td> </td>
11970 @foreach (VariantOption variant in secondDimension)
11971 {
11972 <td>@variant.Name</td>
11973 }
11974 </tr>
11975 </thead>
11976 <tbody>
11977 @foreach (VariantOption firstVariantOption in firstDimension)
11978 {
11979 string variantId = "";
11980 columnCount = 0;
11981
11982 <tr>
11983 <td class="u-min-w120px">@firstVariantOption.Name</td>
11984
11985 @foreach (VariantOption secondVariantOption in secondDimension)
11986 {
11987 variantId = firstVariantOption.Id + "." + secondVariantOption.Id;
11988 <td>
11989 @RenderVariantMatrixQuantityField(variantId, settings, productLoopCounter, rowCount, columnCount)
11990 </td>
11991
11992 columnCount++;
11993
11994 productLoopCounter++;
11995 }
11996
11997 <td>
11998 <div class="qty-field js-total-qty-row-@rowCount dw-mod">0</div>
11999 </td>
12000 </tr>
12001
12002 rowCount++;
12003 }
12004
12005 @{
12006 columnCount = 0;
12007 }
12008
12009 <tr>
12010 <td> </td>
12011 @foreach (VariantOption secondVariantOption in secondDimension)
12012 {
12013 <td>
12014 <div class="qty-field js-total-qty-column-@columnCount dw-mod">0</div>
12015 </td>
12016
12017 columnCount++;
12018 }
12019 <td> </td>
12020 </tr>
12021 </tbody>
12022 }
12023 @if (groupCount == 3)
12024 {
12025 <thead>
12026 <tr>
12027 <td> </td>
12028 @foreach (VariantOption thirdVariantOption in thirdDimension)
12029 {
12030 <td>@thirdVariantOption.Name</td>
12031 }
12032 </tr>
12033 </thead>
12034 <tbody>
12035 @foreach (VariantOption firstVariantOption in firstDimension)
12036 {
12037 int colspan = (thirdDimension.Count + 1);
12038
12039 <tr>
12040 <td colspan="@colspan" class="u-color-light-gray--bg u-bold">@firstVariantOption.Name</td>
12041 </tr>
12042
12043 foreach (VariantOption secondVariantOption in secondDimension)
12044 {
12045 string variantId = "";
12046 columnCount = 0;
12047
12048 <tr>
12049 <td class="u-min-w120px">@secondVariantOption.Name</td>
12050
12051 @foreach (VariantOption thirdVariantOption in thirdDimension)
12052 {
12053 variantId = firstVariantOption.Id + "." + secondVariantOption.Id + "." + thirdVariantOption.Id;
12054
12055 <td>
12056 @RenderVariantMatrixQuantityField(variantId, settings, productLoopCounter, rowCount, columnCount)
12057 </td>
12058
12059 columnCount++;
12060 productLoopCounter++;
12061 }
12062
12063 <td>
12064 <div class="qty-field js-total-qty-row-@rowCount dw-mod">0</div>
12065 </td>
12066 </tr>
12067 rowCount++;
12068 }
12069 }
12070
12071 @{
12072 columnCount = 0;
12073 }
12074
12075 <tr>
12076 <td> </td>
12077 @foreach (VariantOption thirdVariantOption in thirdDimension)
12078 {
12079 <td>
12080 <div class="qty-field js-total-qty-column-@columnCount dw-mod">0</div>
12081 </td>
12082
12083 columnCount++;
12084 }
12085 <td> </td>
12086 </tr>
12087 </tbody>
12088 }
12089 </table>
12090
12091 <script>
12092 document.addEventListener("DOMContentLoaded", function (event) {
12093 MatrixUpdateQuantity("@settings.ProductId");
12094 });
12095
12096 MatrixUpdateQuantity = function (productId) {
12097 var currentMatrix = document.getElementById("VariantMatrixTable_" + productId);
12098 var allQtyFields = currentMatrix.getElementsByClassName("js-qty");
12099
12100 var qtyRowArr = [];
12101 var qtyColumnArr = [];
12102
12103 var totalQty = 0;
12104
12105 for (var i = 0; i < allQtyFields.length; i++) {
12106 qtyRowArr[allQtyFields[i].getAttribute("data-qty-row-group")] = 0;
12107 qtyColumnArr[allQtyFields[i].getAttribute("data-qty-column-group")] = 0;
12108 }
12109
12110 for (var i = 0; i < allQtyFields.length; i++) {
12111 qtyRowArr[allQtyFields[i].getAttribute("data-qty-row-group")] += parseFloat(allQtyFields[i].value);
12112 qtyColumnArr[allQtyFields[i].getAttribute("data-qty-column-group")] += parseFloat(allQtyFields[i].value);
12113 totalQty += parseFloat(allQtyFields[i].value);
12114 }
12115
12116 //Update row counters
12117 for (var i = 0; i < qtyRowArr.length; i++) {
12118 var qtyCounter = currentMatrix.getElementsByClassName("js-total-qty-row-" + i)[0];
12119
12120 if (qtyRowArr[i] != undefined && qtyCounter != null) {
12121 var currentCount = qtyCounter.innerHTML;
12122 qtyCounter.innerHTML = qtyRowArr[i];
12123
12124 if (currentCount != qtyCounter.innerHTML) {
12125 qtyCounter.classList.add("qty-field--active");
12126 }
12127 }
12128
12129 }
12130
12131 //Update column counters
12132 for (var i = 0; i < qtyColumnArr.length; i++) {
12133 var qtyCounter = currentMatrix.getElementsByClassName("js-total-qty-column-" + i)[0];
12134
12135 if (qtyColumnArr[i] != undefined && qtyCounter != null) {
12136 var currentCount = qtyCounter.innerHTML;
12137 qtyCounter.innerHTML = qtyColumnArr[i];
12138
12139 if (currentCount != qtyCounter.innerHTML) {
12140 qtyCounter.classList.add("qty-field--active");
12141 }
12142 }
12143 }
12144
12145 if (document.getElementById("TotalQtyCount_" + productId)) {
12146 document.getElementById("TotalQtyCount_" + productId).innerHTML = totalQty;
12147 }
12148
12149 //Clean up animations
12150 setTimeout(function () {
12151 for (var i = 0; i < qtyRowArr.length; i++) {
12152 var qtyCounter = currentMatrix.getElementsByClassName("js-total-qty-row-" + i)[0];
12153 if (qtyCounter != null) {
12154 qtyCounter.classList.remove("qty-field--active");
12155 }
12156 }
12157 for (var i = 0; i < qtyColumnArr.length; i++) {
12158 var qtyCounter = currentMatrix.getElementsByClassName("js-total-qty-column-" + i)[0];
12159 if (qtyCounter != null) {
12160 qtyCounter.classList.remove("qty-field--active");
12161 }
12162 }
12163 }, 1000);
12164 }
12165 </script>
12166 }
12167 }
12168
12169 @helper RenderVariantMatrixQuantityField(string variantId, VariantMatrix settings, int productLoopCounter, int rowCount, int columnCount)
12170 {
12171 string loopCount = productLoopCounter.ToString();
12172
12173 bool combinationFound = false;
12174 double stock = 0;
12175 double quantityValue = 0;
12176 string note = "";
12177
12178 VariantProduct variantProduct = null;
12179
12180 if (settings.GetVariantProducts().TryGetValue(variantId, out variantProduct))
12181 {
12182 stock = variantProduct.Stock;
12183 quantityValue = variantProduct.Quantity;
12184 combinationFound = true;
12185 }
12186
12187 if (combinationFound)
12188 {
12189 <input type="hidden" name="ProductLoopCounter@(loopCount)" value="@loopCount" />
12190 <input type="hidden" name="ProductID@(loopCount)" value="@settings.ProductId" />
12191 <input type="hidden" name="VariantID@(loopCount)" value="@variantId" />
12192 <input type="hidden" name="CurrentNote@(loopCount)" id="CurrentNote_@(settings.ProductId)_@variantId" value="@note" />
12193 <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">
12194
12195 if (stock != 0)
12196 {
12197 <small>@Translate("Stock") @stock</small>
12198 }
12199
12200 <script>
12201 var variants = '{ "ProductId" :' + '"@settings.ProductId"' + ', "VariantId": ' + '"@variantId"' +'}';
12202 variantsCollection.push(variants);
12203 document.getElementById("Quantity_@(settings.ProductId)_@variantId").closest(".js-variants-matrix").setAttribute("data-variants-collection", "[" + variantsCollection + "]" );
12204 </script>
12205 }
12206 else
12207 {
12208 <div class="use-btn-height" style="background-color: #a8a8a8"></div>
12209 }
12210 }
12211 @using Dynamicweb.Rapido.Blocks.Components.Ecommerce
12212
12213 @* Component *@
12214
12215 @helper RenderAddToCart(AddToCart settings)
12216 {
12217 //set Id for quantity selector to get it's value from button
12218 if (settings.QuantitySelector != null)
12219 {
12220 if (string.IsNullOrEmpty(settings.QuantitySelector.Id))
12221 {
12222 settings.QuantitySelector.Id = Guid.NewGuid().ToString("N");
12223 }
12224
12225 settings.AddButton.QuantitySelectorId = settings.QuantitySelector.Id;
12226
12227 if (settings.Disabled)
12228 {
12229 settings.QuantitySelector.Disabled = true;
12230 }
12231
12232 if (string.IsNullOrEmpty(settings.QuantitySelector.Name))
12233 {
12234 settings.QuantitySelector.Name = settings.QuantitySelector.Id;
12235 }
12236 }
12237
12238 if (settings.Disabled)
12239 {
12240 settings.AddButton.Disabled = true;
12241 }
12242
12243 settings.AddButton.CssClass += " btn--condensed";
12244
12245 //unitsSelector
12246 if (settings.UnitSelector != null)
12247 {
12248 if (settings.Disabled)
12249 {
12250 settings.QuantitySelector.Disabled = true;
12251 }
12252 }
12253
12254 <div class="buttons-collection @settings.WrapperCssClass" @ComponentMethods.AddAttributes(settings.ExtraAttributes)>
12255 @if (settings.UnitSelector != null)
12256 {
12257 @Render(settings.UnitSelector)
12258 }
12259 @if (settings.QuantitySelector != null)
12260 {
12261 @Render(settings.QuantitySelector)
12262 }
12263 @Render(settings.AddButton)
12264 </div>
12265 }
12266 @using Dynamicweb.Rapido.Blocks.Components.Ecommerce
12267
12268 @* Component *@
12269
12270 @helper RenderAddToCartButton(AddToCartButton settings)
12271 {
12272 if (!settings.HideTitle)
12273 {
12274 if (string.IsNullOrEmpty(settings.Title))
12275 {
12276 if (settings.BuyForPoints)
12277 {
12278 settings.Title = Translate("Buy with points");
12279 }
12280 else
12281 {
12282 settings.Title = Translate("Add to cart");
12283 }
12284 }
12285 }
12286 else
12287 {
12288 settings.Title = "";
12289 }
12290
12291 if (settings.Icon == null)
12292 {
12293 settings.Icon = new Icon();
12294 settings.Icon.LabelPosition = Dynamicweb.Rapido.Blocks.Components.General.IconLabelPosition.After;
12295 }
12296
12297 if (string.IsNullOrEmpty(settings.Icon.Name))
12298 {
12299 settings.Icon.Name = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon").SelectedValue;
12300 }
12301
12302 settings.OnClick = "Cart.AddToCart(event, { " +
12303 "id: '" + settings.ProductId + "'," +
12304 (!string.IsNullOrEmpty(settings.VariantId) ? "variantId: '" + settings.VariantId + "'," : "") +
12305 (!string.IsNullOrEmpty(settings.UnitId) ? "unitId: '" + settings.UnitId + "'," : "") +
12306 (settings.BuyForPoints ? "buyForPoints: true," : "") +
12307 (!string.IsNullOrEmpty(settings.ProductInfo) ? "productInfo: " + settings.ProductInfo + "," : "") +
12308 "quantity: " + (string.IsNullOrEmpty(settings.QuantitySelectorId) ? "1" : "parseFloat(document.getElementById('" + settings.QuantitySelectorId + "').value)") +
12309 "});" + settings.OnClick;
12310
12311 @RenderButton(settings)
12312 }
12313 @using Dynamicweb.Rapido.Blocks.Components.Ecommerce
12314
12315 @* Component *@
12316
12317 @helper RenderUnitSelector(UnitSelector settings)
12318 {
12319 if (string.IsNullOrEmpty(settings.Id))
12320 {
12321 settings.Id = Guid.NewGuid().ToString("N");
12322 }
12323 var disabledClass = settings.Disabled ? "disabled" : "";
12324
12325 <input type="checkbox" id="@settings.Id" class="dropdown-trigger" />
12326 <div class="dropdown unit-selector @settings.CssClass @disabledClass dw-mod" @ComponentMethods.AddAttributes(settings.ExtraAttributes)>
12327 <label class="dropdown__header dropdown__btn dropdown__btn--unit-selector dw-mod" for="@settings.Id">@settings.SelectedOption</label>
12328 <div class="dropdown__content dw-mod">
12329 @settings.OptionsContent
12330 </div>
12331 <label class="dropdown-trigger-off" for="@settings.Id"></label>
12332 </div>
12333 }
12334 @using System.Reflection
12335 @using Dynamicweb.Rapido.Blocks.Components.Ecommerce
12336
12337 @* Component *@
12338
12339 @helper RenderQuantitySelector(QuantitySelector settings)
12340 {
12341 var attributes = new Dictionary<string, string>();
12342
12343 /*base settings*/
12344 if (!string.IsNullOrEmpty(settings.Id)) { attributes.Add("id", settings.Id); }
12345 if (!string.IsNullOrEmpty(settings.OnClick)) { attributes.Add("onclick", settings.OnClick); }
12346 if (!string.IsNullOrEmpty(settings.OnChange)) { attributes.Add("onchange", settings.OnChange); }
12347 if (settings.Disabled) { attributes.Add("disabled", "true"); }
12348 if (settings.Required) { attributes.Add("required", "true"); }
12349 if (!string.IsNullOrEmpty(settings.Name)) { attributes.Add("name", settings.Name); }
12350 /*end*/
12351
12352 if (!string.IsNullOrEmpty(settings.OnKeyUp)) { attributes.Add("onkeyup", settings.OnKeyUp); }
12353 if (!string.IsNullOrEmpty(settings.OnInput)) { attributes.Add("oninput", settings.OnInput); }
12354 if (!string.IsNullOrEmpty(settings.OnFocus)) { attributes.Add("onfocus", settings.OnFocus); }
12355 if (settings.ReadOnly) { attributes.Add("readonly", "true"); }
12356 if (settings.Max != null) { attributes.Add("max", settings.Max.ToString()); }
12357 if (settings.Min == null) { settings.Min = 1; }
12358 attributes.Add("min", settings.Min.ToString());
12359 if (settings.Step != null && !string.IsNullOrEmpty(settings.Step.ToString())) { attributes.Add("step", settings.Step.ToString()); }
12360 if (settings.Value == null) { settings.Value = 1; }
12361 attributes.Add("value", settings.Value.ToString());
12362 attributes.Add("type", "number");
12363
12364 var resultAttributes = attributes.Concat(settings.ExtraAttributes).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.Last().Value);
12365
12366 <input @ComponentMethods.AddAttributes(resultAttributes) class="@settings.CssClass dw-mod" />
12367 }
12368 @using Dynamicweb.Rapido.Blocks.Components
12369
12370 @using Dynamicweb.Frontend
12371 @using Dynamicweb.Frontend.Devices
12372 @using Dynamicweb.Rapido.Blocks.Components.Ecommerce
12373 @using Dynamicweb.Rapido.Blocks.Components.General
12374 @using System.Collections.Generic;
12375
12376 @* Component *@
12377
12378 @helper RenderCustomerCenterList(CustomerCenterList settings)
12379 {
12380 bool isTouchDevice = Pageview.Device.ToString() == "Mobile" || Pageview.Device.ToString() == "Tablet" ? true : false;
12381 string hideActions = isTouchDevice ? "u-block" : "";
12382
12383 <table class="table data-list dw-mod">
12384 @if (settings.GetHeaders().Length > 0) {
12385 <thead>
12386 <tr class="u-bold">
12387 @foreach (CustomerCenterListHeaderItem header in settings.GetHeaders())
12388 {
12389 var attributes = new Dictionary<string, string>();
12390 if (!string.IsNullOrEmpty(header.Id)) { attributes.Add("id", header.Id); }
12391 if (!string.IsNullOrEmpty(header.CssClass)) { attributes.Add("class", header.CssClass); }
12392 attributes.Add("align", header.Align.ToString());
12393 attributes = attributes.Concat(header.ExtraAttributes).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.Last().Value);
12394
12395 <td @ComponentMethods.AddAttributes(attributes)>@header.Title</td>
12396 }
12397 </tr>
12398 </thead>
12399 }
12400 @foreach (CustomerCenterListItem listItem in settings.GetItems())
12401 {
12402 int columnCount = 0;
12403 int totalColumns = listItem.GetInfoItems().Length;
12404 string rowHasActions = listItem.GetActions().Length > 0 ? "data-list__item--has-acions" : "";
12405 listItem.Id = !string.IsNullOrEmpty(listItem.Id) ? listItem.Id : Guid.NewGuid().ToString("N");
12406
12407 var attributes = new Dictionary<string, string>();
12408 if (!string.IsNullOrEmpty(listItem.Title)) { attributes.Add("title", listItem.Title); };
12409
12410 attributes = attributes.Concat(listItem.ExtraAttributes).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.Last().Value);
12411 <tbody class="data-list__item @rowHasActions @listItem.CssClass dw-mod" @ComponentMethods.AddAttributes(attributes)>
12412 <tr>
12413 @if (!string.IsNullOrEmpty(listItem.Title) || !string.IsNullOrEmpty(listItem.Description)) {
12414 <td rowspan="2" onclick="@listItem.OnClick" class="data-list__main-item dw-mod">
12415 @if (!string.IsNullOrEmpty(listItem.Title)) {
12416 <div class="u-bold">@listItem.Title</div>
12417 }
12418 @if (!string.IsNullOrEmpty(listItem.Description)) {
12419 <div>@listItem.Description</div>
12420 }
12421 </td>
12422 }
12423
12424 @foreach (CustomerCenterListInfoItem infoItem in listItem.GetInfoItems())
12425 {
12426 var infoAttributes = new Dictionary<string, string>();
12427 if (!string.IsNullOrEmpty(infoItem.Id)) { infoAttributes.Add("id", infoItem.Id); };
12428 if (!string.IsNullOrEmpty(infoItem.OnClick)) { infoAttributes.Add("onclick", infoItem.OnClick); };
12429 infoAttributes.Add("align", infoItem.Align.ToString());
12430
12431 infoAttributes = infoAttributes.Concat(infoItem.ExtraAttributes).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.Last().Value);
12432 string columnClick = columnCount < (totalColumns-1) ? "onclick=\"" + listItem.OnClick + "\"" : "";
12433
12434 <td @ComponentMethods.AddAttributes(infoAttributes) @columnClick class="data-list__info-item dw-mod">
12435 @if (!string.IsNullOrEmpty(infoItem.Title)) {
12436 <div>@infoItem.Title</div>
12437 }
12438 @if (!string.IsNullOrEmpty(infoItem.Subtitle)) {
12439 <div><small>@infoItem.Subtitle</small></div>
12440 }
12441 </td>
12442
12443 columnCount++;
12444 }
12445 </tr>
12446 <tr>
12447 <td colspan="7" align="right" class="u-va-bottom u-no-border">
12448 <div class="data-list__actions @hideActions dw-mod" id="ActionsMenu_@listItem.Id">
12449 @foreach (ButtonBase action in listItem.GetActions())
12450 {
12451 action.ButtonLayout = ButtonLayout.LinkClean;
12452 action.CssClass += " data-list__action-button link";
12453
12454 @Render(action)
12455 }
12456 </div>
12457 </td>
12458 </tr>
12459 </tbody>
12460 }
12461 </table>
12462 }
12463 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
12464 @using System.Web
12465 @using Dynamicweb.Rapido.Blocks.Extensibility
12466 @using Dynamicweb.Rapido.Blocks
12467 @using Dynamicweb.Core
12468 @using System.Linq
12469 @using Dynamicweb.Frontend
12470
12471 @functions{
12472 public class SommifyConfig
12473 {
12474 public string ApiKey { get; set; }
12475 public string Position { get; set; }
12476 public string Localization { get; set; }
12477 public string Currency { get; set; }
12478 public string SalesWeight { get; set; }
12479 public string MiniCartFeedPageId { get; set; }
12480 public bool EnableChatFunction { get; set; }
12481 public bool EnableFullScreen { get; set; }
12482 public Dictionary<string, List<string>> Prompts { get; set; }
12483 public string GoogleImpression { get; set; }
12484 }
12485
12486 public class GoogleImpression
12487 {
12488 public string Email { get; set; }
12489 public string Guid { get; set; }
12490 public string ShopId { get; set; }
12491 public string AreaId { get; set; }
12492 public string Origin { get; set; }
12493 public string Device { get; set; }
12494 }
12495
12496 public class InternationalTelephoneConfig
12497 {
12498 public string UtilsJsUrl { get; set; }
12499 public string InitialCountry { get; set; }
12500 public string SelectedCountryAriaLabel { get; set; }
12501 public string NoCountrySelected { get; set; }
12502 public string CountryListAriaLabel { get; set; }
12503 public string SearchPlaceholder { get; set; }
12504 public string ZeroSearchResults { get; set; }
12505 public string ErrorMessageIsPossible { get; set; }
12506 public string ErrorMessageInvalidCountryCode { get; set; }
12507 public string ErrorMessageTooShort { get; set; }
12508 public string ErrorMessageTooLong { get; set; }
12509 public string ErrorMessageIsPossibleLocalOnly { get; set; }
12510 public string ErrorMessageInvalidLength { get; set; }
12511 public bool StrictMode { get; set; }
12512 }
12513 }
12514
12515 @{
12516 BlocksPage bottomSnippetsBlocksPage = BlocksPage.GetBlockPage("Master");
12517
12518 Block primaryBottomSnippets = new Block()
12519 {
12520 Id = "MasterJavascriptInitializers",
12521 SortId = 100,
12522 Template = RenderPrimaryBottomSnippets()
12523 };
12524 bottomSnippetsBlocksPage.Add(MasterBlockId.MasterReferences, primaryBottomSnippets);
12525
12526 if (Dynamicweb.Rapido.Services.User.IsBuyingAllowed())
12527 {
12528 Block miniCartPageId = new Block
12529 {
12530 Id = "MiniCartPageId",
12531 Template = RenderMiniCartPageId()
12532 };
12533 bottomSnippetsBlocksPage.Add(MasterBlockId.MasterReferences, miniCartPageId);
12534 }
12535
12536 ItemViewModel sommifySettings = PageView.Current().AreaSettings.GetItem("Custom").GetItem("SommifySettings");
12537 if (sommifySettings != null)
12538 {
12539 bool activateSommify = sommifySettings.GetBoolean("ActivateSommify");
12540 string sommifyApiKey = sommifySettings.GetRawValueString("SommifyApiKey");
12541 if (activateSommify && !string.IsNullOrEmpty(sommifyApiKey))
12542 {
12543 Block sommifyData = new Block
12544 {
12545 Id = "SommifyData",
12546 Template = RenderSommifyData(activateSommify, sommifyApiKey, sommifySettings)
12547 };
12548 bottomSnippetsBlocksPage.Add(MasterBlockId.MasterReferences, sommifyData);
12549 }
12550 }
12551
12552 ItemViewModel internationalTelephoneSettings = PageView.Current().AreaSettings.GetItem("Custom").GetItem("InternationalTelephoneSettings");
12553 if (internationalTelephoneSettings != null)
12554 {
12555 bool activateInternationalTelephone = internationalTelephoneSettings.GetBoolean("ActivateInternationalTelephone");
12556 if (activateInternationalTelephone)
12557 {
12558 Block internationalTelephone = new Block
12559 {
12560 Id = "InternationalTelephoneSettings",
12561 Template = RenderInternationalTelephoneSettings(internationalTelephoneSettings)
12562 };
12563 bottomSnippetsBlocksPage.Add(MasterBlockId.MasterReferences, internationalTelephone);
12564 }
12565 }
12566
12567 string searchType = !string.IsNullOrEmpty(PageView.Current().AreaSettings.GetItem("Layout").GetRawValueString("TopSearch")) ? PageView.Current().AreaSettings.GetItem("Layout").GetRawValueString("TopSearch") : "productSearch";
12568 if (searchType == "productSearchWithFilters")
12569 {
12570 Block searchFacetsInitializers = new Block
12571 {
12572 Id = "SearchFacetsInitializers",
12573 Template = RenderSearchFacetsInitializers()
12574 };
12575 bottomSnippetsBlocksPage.Add(MasterBlockId.MasterReferences, searchFacetsInitializers);
12576 }
12577
12578 int activateBooztDiscountPageId = GetPageIdByNavigationTag("ActivateBooztDiscount");
12579 if (activateBooztDiscountPageId > 0)
12580 {
12581 Block booztDiscountPageId = new Block
12582 {
12583 Id = "BooztDiscountPageId",
12584 Template = RenderActivateBooztDiscountPageId(activateBooztDiscountPageId)
12585 };
12586 bottomSnippetsBlocksPage.Add(MasterBlockId.MasterReferences, booztDiscountPageId);
12587 }
12588 }
12589
12590 @helper RenderPrimaryBottomSnippets()
12591 {
12592 bool isWireframeMode = Model.Area.Item.GetItem("Settings").GetBoolean("WireframeMode");
12593 bool useGoogleTagManager = !string.IsNullOrEmpty(Pageview.AreaSettings.GetItem("Settings").GetString("GoogleTagManagerID"));
12594
12595 if (isWireframeMode)
12596 {
12597 <script>
12598 Wireframe.Init(true);
12599 </script>
12600 }
12601
12602 //if digitalwarehouse
12603 if (Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("ShowDownloadCart"))
12604 {
12605 string cartContextId = Converter.ToString(HttpContext.Current.Application["DownloadCartContext"]);
12606
12607 if (string.IsNullOrEmpty(cartContextId))
12608 {
12609 var moduleProps = Dynamicweb.Modules.Properties.GetParagraphModuleSettings(GetPageIdByNavigationTag("DownloadCart"), "eCom_CartV2");
12610 var cartSettings = new Dynamicweb.Ecommerce.Cart.ModuleSettings(moduleProps);
12611 cartContextId = cartSettings.OrderContextID;
12612 HttpContext.Current.Application["DownloadCartContext"] = cartContextId;
12613 }
12614
12615 <script>
12616 let downloadCart = new DownloadCart({
12617 cartPageId: @GetPageIdByNavigationTag("MiniCartFeed"),
12618 contextId: "@cartContextId",
12619 addButtonText: "@Translate("Add")",
12620 removeButtonText: "@Translate("Remove")"
12621 });
12622 </script>
12623 }
12624
12625 <!--$$Javascripts-->
12626 }
12627
12628 @helper RenderMiniCartPageId()
12629 {
12630 int miniCartFeedPageId = GetPageIdByNavigationTag("MiniCartFeed");
12631 <script>
12632 window.cartId = "@miniCartFeedPageId";
12633 </script>
12634 }
12635
12636 @helper RenderSommifyData(bool activateSommify, string sommifyApiKey, ItemViewModel sommifySettings)
12637 {
12638 string sommifyPosition = sommifySettings.GetRawValueString("SommifyPosition");
12639 string sommifyLocalization = sommifySettings.GetRawValueString("SommifyLocalization");
12640 string sommifyCurrency = sommifySettings.GetRawValueString("SommifyCurrency");
12641 string sommifySalesWeight = Converter.ToString(sommifySettings.GetInt32("SommifySalesWeight"));
12642 string miniCartFeedPageId = Converter.ToString(GetPageIdByNavigationTag("MiniCartFeed"));
12643 bool sommifyEnableChatFunction = sommifySettings.GetBoolean("SommifyEnableChatFunction");
12644 bool sommifyEnableFullScreen = sommifySettings.GetBoolean("SommifyEnableFullScreen");
12645 var sommifyPrompts = sommifySettings.GetItems("SommifyPrompts");
12646 Dictionary<string, List<string>> sommifyPromptsDictionary = new Dictionary<string, List<string>>();
12647
12648 if (sommifyPrompts != null && sommifyPrompts.Any())
12649 {
12650 var prompts = new List<string>();
12651 foreach (var sommifyPrompt in sommifyPrompts)
12652 {
12653 prompts.Add(sommifyPrompt.GetRawValueString("Prompt"));
12654 }
12655 sommifyPromptsDictionary.Add(sommifyLocalization, prompts);
12656 }
12657
12658 string serializedPrompts = Newtonsoft.Json.JsonConvert.SerializeObject(sommifyPromptsDictionary);
12659 var sommifyConfig = new SommifyConfig();
12660 sommifyConfig.ApiKey = sommifyApiKey;
12661 sommifyConfig.Position = sommifyPosition;
12662 sommifyConfig.Localization = sommifyLocalization;
12663 sommifyConfig.Currency = sommifyCurrency;
12664 sommifyConfig.SalesWeight = sommifySalesWeight;
12665 sommifyConfig.MiniCartFeedPageId = miniCartFeedPageId;
12666 sommifyConfig.EnableChatFunction = sommifyEnableChatFunction;
12667 sommifyConfig.EnableFullScreen = sommifyEnableFullScreen;
12668 sommifyConfig.Prompts = sommifyPromptsDictionary;
12669
12670 bool useGoogleTagManager = !string.IsNullOrEmpty(Pageview.AreaSettings.GetItem("Settings").GetRawValueString("GoogleTagManagerID"));
12671 if (useGoogleTagManager)
12672 {
12673 var user = Dynamicweb.Security.UserManagement.User.GetCurrentExtranetUser();
12674 var googleImpression = new GoogleImpression()
12675 {
12676 Email = user != null ? user.Email : "",
12677 Guid = Guid.NewGuid().ToString("N"),
12678 ShopId = Pageview.Area.EcomShopId,
12679 AreaId = Converter.ToString(Pageview.AreaID),
12680 Origin = Translate("Sommify.Datalayer.AddToCart.Origin", "Sommify"),
12681 Device = Pageview.Device.ToString()
12682 };
12683 sommifyConfig.GoogleImpression = Newtonsoft.Json.JsonConvert.SerializeObject(googleImpression);
12684 }
12685
12686 <div class="d-none js-sommify-config" data-config="@HttpUtility.HtmlAttributeEncode(Newtonsoft.Json.JsonConvert.SerializeObject(sommifyConfig))"></div>
12687 }
12688
12689 @helper RenderInternationalTelephoneSettings(ItemViewModel internationalTelephoneSettings)
12690 {
12691 string utilsJsUrl = internationalTelephoneSettings.GetRawValueString("UtilsJsUrl");
12692 if (!string.IsNullOrEmpty(utilsJsUrl))
12693 {
12694 string initialCountry = internationalTelephoneSettings.GetRawValueString("InitialCountry");
12695 bool strictMode = internationalTelephoneSettings.GetBoolean("StrictMode");
12696 var internationalTelephoneConfig = new InternationalTelephoneConfig();
12697 internationalTelephoneConfig.UtilsJsUrl = utilsJsUrl;
12698 internationalTelephoneConfig.InitialCountry = initialCountry;
12699 internationalTelephoneConfig.SelectedCountryAriaLabel = Translate("International.Telephone.Input.SelectedCountry", "Valgt land");
12700 internationalTelephoneConfig.NoCountrySelected = Translate("International.Telephone.Input.NoCountrySelected", "Du har ikke valgt et land");
12701 internationalTelephoneConfig.CountryListAriaLabel = Translate("International.Telephone.Input.CountryList", "Liste over lande");
12702 internationalTelephoneConfig.SearchPlaceholder = Translate("International.Telephone.Input.SearchPlaceholder", "Søg");
12703 internationalTelephoneConfig.ZeroSearchResults = Translate("International.Telephone.Input.NoSearchResults", "Ingen resultater");
12704 internationalTelephoneConfig.ErrorMessageIsPossible = Translate("International.Telephone.ErrorMessage.IsPossible", "Nummeret er muligt");
12705 internationalTelephoneConfig.ErrorMessageInvalidCountryCode = Translate("International.Telephone.ErrorMessage.InvalidCountryCode", "Fejlagtig landekode");
12706 internationalTelephoneConfig.ErrorMessageTooShort = Translate("International.Telephone.ErrorMessage.TooShort", "Nummeret er for kort");
12707 internationalTelephoneConfig.ErrorMessageTooLong = Translate("International.Telephone.ErrorMessage.TooLong", "Nummeret er for langt");
12708 internationalTelephoneConfig.ErrorMessageIsPossibleLocalOnly = Translate("International.Telephone.ErrorMessage.IsPossibleLocalOnly", "Nummeret er kun muligt lokalt");
12709 internationalTelephoneConfig.ErrorMessageInvalidLength = Translate("International.Telephone.ErrorMessage.InvalidLength", "Ugyldig længde");
12710 internationalTelephoneConfig.StrictMode = strictMode;
12711
12712 <div class="d-none js-international-telephone-config" data-config="@HttpUtility.HtmlAttributeEncode(Newtonsoft.Json.JsonConvert.SerializeObject(internationalTelephoneConfig))"></div>
12713 }
12714 }
12715
12716 @helper RenderSearchFacetsInitializers()
12717 {
12718 <script>
12719 document.addEventListener("DOMContentLoaded", function (event) {
12720 var productSearchBarContent = document.getElementById("ProductSearchBarContent");
12721 if (productSearchBarContent != null) {
12722 productSearchBarContent.addEventListener('contentLoaded', function (e) {
12723 if (getTarget(e).id === "ProductSearchBarContent") {
12724 Facets.Init("selectedFacets", "ProductSearchBarContent");
12725 }
12726 }, false);
12727 }
12728 });
12729 </script>
12730 }
12731
12732 @helper RenderActivateBooztDiscountPageId(int activateBooztDiscountPageId)
12733 {
12734 <script>
12735 window.booztDiscountPageId = "@activateBooztDiscountPageId";
12736 </script>
12737 }
12738 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
12739 @using System.Web
12740 @using Dynamicweb.Rapido.Blocks.Extensibility
12741 @using Dynamicweb.Rapido.Blocks
12742 @using Dynamicweb
12743 @using Dynamicweb.Core
12744 @using Dynamicweb.Security.UserManagement
12745 @using Smartpage.PhilipsonWine.EcomDiscount.Services
12746
12747 @functions {
12748 public class StockMessage
12749 {
12750 public string Class { get; set; }
12751 public string HeaderMessage { get; set; }
12752 public string BodyMessage { get; set; }
12753 }
12754 string GetHrefLang(string cultureName)
12755 {
12756 var hrefLang = cultureName;
12757 switch (cultureName.ToLower())
12758 {
12759 case "en-150":
12760 hrefLang = "en-GB";
12761 break;
12762 }
12763 return hrefLang;
12764 }
12765
12766 string GetProductFieldValue(string productField)
12767 {
12768 var product = Dynamicweb.Ecommerce.Services.Products.GetProductById(Dynamicweb.Context.Current.Request["ProductId"], string.Empty, Dynamicweb.Ecommerce.Common.Context.LanguageID);
12769 if (product != null)
12770 {
12771 string productFieldValue = Converter.ToString(Dynamicweb.Ecommerce.Services.Products.GetProductFieldValue(product, productField));
12772 if (!string.IsNullOrEmpty(productFieldValue))
12773 {
12774 return productFieldValue;
12775 }
12776 else
12777 {
12778 return null;
12779 }
12780 }
12781 else
12782 {
12783 return null;
12784 }
12785 }
12786 }
12787
12788 @{
12789 BlocksPage masterCustomBlocksPage = BlocksPage.GetBlockPage("Master");
12790 }
12791
12792 @{
12793
12794 bool userIsImpersonating = Smartpage.PhilipsonWine.Ecommerce.Helpers.Helper.AllowsPartialPurchase();
12795 Block stockLevelWarningModal = new Block()
12796 {
12797 Id = "stockLevelWarningModal",
12798 SortId = 20,
12799 SkipRenderBlocksList = true,
12800 Template = RenderStockLevelWarningModal(userIsImpersonating)
12801 };
12802 masterCustomBlocksPage.Add("MasterTopSnippets", stockLevelWarningModal);
12803
12804
12805 bool strictModeForProductAmountSelection = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetBoolean("StrictModeForProductAmountSelection");
12806 if (strictModeForProductAmountSelection)
12807 {
12808 Block invalidProductAmountModal = new Block()
12809 {
12810 Id = "invalidProductAmountModal",
12811 SortId = 20,
12812 SkipRenderBlocksList = true,
12813 Template = RenderInvalidProductAmountModal(userIsImpersonating)
12814 };
12815 masterCustomBlocksPage.Add("MasterTopSnippets", invalidProductAmountModal);
12816 }
12817
12818 string userAgent = Dynamicweb.Context.Current.Request.Headers["User-Agent"];
12819
12820 if (Dynamicweb.Frontend.PageView.Current().Device != Dynamicweb.Frontend.Devices.DeviceType.Bot)
12821 {
12822 Block ageModalBlock = new Block
12823 {
12824 Id = "AgeModal",
12825 Template = RenderAgeRestrictionModal()
12826 };
12827
12828 masterCustomBlocksPage.Add(MasterBlockId.MasterHeader, ageModalBlock);
12829 }
12830
12831 Dynamicweb.Security.UserManagement.User frontendUser = Dynamicweb.Security.UserManagement.User.GetCurrentFrontendUser();
12832 Block engrosRedirectModalBlock = new Block
12833 {
12834 Id = "EngrosRedirectModal",
12835 Template = RenderEngrosRedirectModal(frontendUser)
12836 };
12837
12838 if (!Converter.ToBoolean(Pageview.AreaSettings.GetItem("Custom").GetBoolean("IsEngrosSite")) && frontendUser != null && Converter.ToBoolean(Dynamicweb.Context.Current.Session["twoday:EngrosRedirect"]))
12839 {
12840 masterCustomBlocksPage.Add(MasterBlockId.MasterHeader, engrosRedirectModalBlock);
12841
12842 Dynamicweb.Context.Current.Session.Remove("twoday:EngrosRedirect");
12843 }
12844
12845 Block swedishCurrencySelectorBlock = new Block
12846 {
12847 Id = "SwedishCurrencySelector",
12848 Template = RenderSwedishCurrencySelector()
12849 };
12850
12851 Block businessContactImpersonationModal = new Block
12852 {
12853 Id = "BusinessContactImpersonationModal",
12854 Template = RenderBusinessContactImpersonationModal()
12855 };
12856
12857 string mainSalesCategory = GetProductFieldValue("SpMainSalesCategory");
12858 if (!string.IsNullOrEmpty(mainSalesCategory))
12859 {
12860 string cocktailPackCategory = Dynamicweb.Configuration.SystemConfiguration.Instance.GetValue("/Globalsettings/Smartpage/Ecommerce/CocktailPackCategory");
12861 if (mainSalesCategory == cocktailPackCategory)
12862 {
12863 Block shareUrlModal = new Block()
12864 {
12865 Id = "shareUrlModal",
12866 Template = RenderShareUrlModal()
12867 };
12868 masterCustomBlocksPage.Add("MasterTopSnippets", shareUrlModal);
12869 }
12870 }
12871
12872 bool showModalCurrencySelectorModal = Converter.ToBoolean(Dynamicweb.Context.Current.Session["smartpage:SwedishCurrencySelector"]);
12873
12874 if (showModalCurrencySelectorModal)
12875 {
12876 masterCustomBlocksPage.Add(MasterBlockId.MasterHeader, swedishCurrencySelectorBlock);
12877
12878 // Reset session until next time user logs in
12879 Dynamicweb.Context.Current.Session.Remove("smartpage:SwedishCurrencySelector");
12880 }
12881
12882 bool confirmUserInformationModalActive = Dynamicweb.Configuration.SystemConfiguration.Instance.GetBoolean("/Globalsettings/Smartpage/Customers/ConfirmUserInformationModalActive");
12883 if (confirmUserInformationModalActive && Pageview.User != null && !showModalCurrencySelectorModal)
12884 {
12885 var customerTypeField = Pageview.User.CustomFieldValues.FirstOrDefault(x => x.CustomField.SystemName == "AccessUser_SpBcCustomerType");
12886 if (customerTypeField != null && Converter.ToString(customerTypeField.Value).Equals("Private", StringComparison.InvariantCultureIgnoreCase))
12887 {
12888 var profileUpdatedManuallyDateField = Pageview.User.CustomFieldValues.FirstOrDefault(x => x.CustomField.SystemName == "AccessUser_SpProfileUpdatedManuallyDate");
12889 if (profileUpdatedManuallyDateField != null)
12890 {
12891 DateTime profileUpdatedManuallyDate = Converter.ToDateTime(profileUpdatedManuallyDateField.Value);
12892 var confirmUserInformationInterval = Dynamicweb.Configuration.SystemConfiguration.Instance.GetInt32("/Globalsettings/Smartpage/Customers/ConfirmUserInformationInterval");
12893 if (profileUpdatedManuallyDate.AddMonths(confirmUserInformationInterval) < DateTime.Now)
12894 {
12895 Block userEditModalBlock = new Block
12896 {
12897 Id = "UserEditModal",
12898 Template = RenderUserEditModal()
12899 };
12900 masterCustomBlocksPage.Add(MasterBlockId.MasterHeader, userEditModalBlock);
12901 }
12902 }
12903 }
12904 }
12905
12906 bool showModalBusinessContactImpersonation = Converter.ToBoolean(Dynamicweb.Context.Current.Session["Smartpage:BusinessContactImpersonation"]);
12907
12908 if (showModalBusinessContactImpersonation)
12909 {
12910 masterCustomBlocksPage.Add(MasterBlockId.MasterHeader, businessContactImpersonationModal);
12911
12912 // Reset session until next time user logs in
12913 Dynamicweb.Context.Current.Session.Remove("Smartpage:BusinessContactImpersonation");
12914 }
12915
12916 Block primeurWineAlert = new Block
12917 {
12918 Id = "PrimeurWineAlert",
12919 Template = RenderPrimeurWineAlert()
12920 };
12921
12922 masterCustomBlocksPage.Add(MasterBlockId.MasterHeader, primeurWineAlert);
12923
12924 Block cartLineNotAddedModal = new Block
12925 {
12926 Id = "CartLineNotAdded",
12927 Template = RenderCartLineNotAddedModal()
12928 };
12929
12930 masterCustomBlocksPage.Add(MasterBlockId.MasterHeader, cartLineNotAddedModal);
12931
12932 Block hrefLangBlock = new Block
12933 {
12934 Id = "HrefLangBlock",
12935 SortId = 50,
12936 Template = RenderHrefLang()
12937 };
12938
12939 masterCustomBlocksPage.Add("Head", hrefLangBlock);
12940
12941 string activeCampaignForm = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetString("ActiveCampaignForm");
12942 if (!string.IsNullOrEmpty(activeCampaignForm) && Dynamicweb.Frontend.PageView.Current().ID == GetPageIdByNavigationTag("LiveshoppingPage"))
12943 {
12944 Block liveshoppingActiveCampaignSignUpModalBlock = new Block
12945 {
12946 Id = "LiveshoppingActiveCampaignSignUpModal",
12947 Template = RenderLiveshoppingActiveCampaignSignUpModal(activeCampaignForm)
12948 };
12949
12950 masterCustomBlocksPage.Add(MasterBlockId.MasterHeader, liveshoppingActiveCampaignSignUpModalBlock);
12951 }
12952
12953
12954 if (BooztDiscountService.AnyBooztDiscountActivatedForProductPage())
12955 {
12956 foreach (var booztDiscount in BooztDiscountService.GetDiscounts(Dynamicweb.Security.UserManagement.User.GetCurrentFrontendUser()))
12957 {
12958 Block booztDiscountTermsConditionsModal = new Block
12959 {
12960 Id = "BooztDiscountTermsConditionsModal",
12961 Template = RenderBooztDiscountTermsConditionsModal(booztDiscount)
12962 };
12963 masterCustomBlocksPage.Add(MasterBlockId.MasterHeader, booztDiscountTermsConditionsModal);
12964 }
12965 }
12966 }
12967
12968 @helper RenderPrimeurWineAlert()
12969 {
12970 <input type="checkbox" id="PrimeurWineModalTrigger" class="modal-trigger">
12971 <div class="modal-container">
12972 <label for="PrimeurWineModalTrigger" id="PrimeurWineModalOverlay" class="modal-overlay"></label>
12973 <div class="modal modal--md modal-height--auto" id="rateProductModal">
12974 <div class="modal__header u-ta-center">
12975 @Translate("Smartpage:Checkout.Primeur.Alert.Header", "Du kan desværre ikke bestille både en primeur vin og en almindelig vin")
12976 </div>
12977 <div class="modal__body u-ta-center">
12978 <p>@Translate("Smartpage:Checkout.Primeur.Alert.Text", "Du bedes fjerne enten primeur vinen eller den almindelige")</p>
12979 </div>
12980 <label class="modal__close-btn" for="PrimeurWineModalTrigger"></label>
12981 </div>
12982 </div>
12983 }
12984
12985 @helper RenderStockLevelWarningModal(bool userIsImpersonating)
12986 {
12987 var messages = new List<StockMessage>();
12988 messages.Add(new StockMessage()
12989 {
12990 Class = "js-out-of-stock-message",
12991 HeaderMessage = Translate("Smartpage:StockLevel.Warning.Header", "Vi har desværre ikke flere på lager"),
12992 BodyMessage = Translate("Smartpage:StockLevel.Warning.Body", "Vi har nedskrevet antal til max lagerantal:")
12993 });
12994 messages.Add(new StockMessage()
12995 {
12996 Class = "js-max-order-quantity-message",
12997 HeaderMessage = Translate("Smartpage:MaxOrderQuantity.Warning.Header", "Maksimalt ordre antal overskredet"),
12998 BodyMessage = Translate("Smartpage:MaxOrderQuantity.Warning.Body", "Du har overskrevet det maksimalt tilladte antal:")
12999 });
13000 if (userIsImpersonating)
13001 {
13002 messages.Add(new StockMessage()
13003 {
13004 Class = "js-impersonator-max-order-quantity-message",
13005 HeaderMessage = Translate("Smartpage:Impersonator.MaxOrderQuantity.Warning.Header", "Maksimalt ordre antal overskredet"),
13006 BodyMessage = Translate("Smartpage:Impersonator.MaxOrderQuantity.Warning.Body", "Vær opmærksom på, at du har overskrevet det maksimalt tilladte antal.<br><b>Da du er impersonator har du dog lov til det.</b> Det maksimale tilladte antal er:")
13007 });
13008 }
13009 <input type="checkbox" id="stockLevelWarningModalTrigger" class="modal-trigger">
13010 <div class="modal-container">
13011 <label for="stockLevelWarningModalTrigger" id="stockLevelWarningModalOverlay" class="modal-overlay"></label>
13012 <div class="modal modal-height--auto js-stock-level-warning-modal @(userIsImpersonating ? "js-user-is-impersonator" : "")">
13013 @foreach (var message in messages)
13014 {
13015 <div class="js-message @message.Class">
13016 <div class="modal__header">@message.HeaderMessage</div>
13017 <div class="modal__body">@message.BodyMessage <span class="js-modal__max"></span></div>
13018 </div>
13019 }
13020 <label class="modal__close-btn" for="stockLevelWarningModalTrigger"></label>
13021 </div>
13022 </div>
13023 }
13024
13025 @helper RenderInvalidProductAmountModal(bool userIsImpersonator)
13026 {
13027 var messages = new List<StockMessage>();
13028 messages.Add(new StockMessage()
13029 {
13030 Class = "js-invalid-amount-message",
13031 HeaderMessage = Translate("Smartpage:InvalidAmount.Warning.Header", "Antallet er ugyldigt"),
13032 BodyMessage = Translate("Smartpage:InvalidAmount.Warning.Body", "Du bedes købe varen i hele kasser.<br>Det nærmeste gyldige antal er:")
13033 });
13034 messages.Add(new StockMessage()
13035 {
13036 Class = "js-invalid-amount-already-in-cart-message",
13037 HeaderMessage = Translate("Smartpage:InvalidAmount.AlreadyInCart.Warning.Header", "Du bedes købe varen i hele kasser"),
13038 BodyMessage = Translate("Smartpage:InvalidAmount.AlreadyInCart.Warning.Body", "Du har allerede varen i kurven, og det samlede antal er ugyldigt.<br>Det <b>nærmeste gyldige antal</b> du yderligere kan tilføje er:")
13039 });
13040 messages.Add(new StockMessage()
13041 {
13042 Class = "js-in-cart-invalid-amount-message",
13043 HeaderMessage = Translate("Smartpage:InvalidAmount.ChangeCart.Warning.Header", "Antallet er ugyldigt"),
13044 BodyMessage = Translate("Smartpage:InvalidAmount.ChangeCart.Warning.Body", "Du bedes købe varen i hele kasser.<br>Du kan i stedet ændre antallet til det nærmeste gyldige antal:")
13045 });
13046 if (userIsImpersonator)
13047 {
13048 messages.Add(new StockMessage()
13049 {
13050 Class = "js-impersonator-invalid-amount-message",
13051 HeaderMessage = Translate("Smartpage:InvalidAmount.Impersonator.Warning.Header", "Antallet bryder varens kolli tal"),
13052 BodyMessage = Translate("Smartpage:InvalidAmount.Impersonator.Warning.Body", "Vær opmærksom på, at det samlede antal bryder varens kolli.<br>Det er tilladt da du er impersonator, men du kan evt. opdatere til dette nærmeste gyldige antal:")
13053 });
13054 }
13055 bool isCartPage = Pageview.ID == GetPageIdByNavigationTag("CartPage");
13056
13057 <input type="checkbox" id="invalidProductAmountWarningModalTrigger" class="modal-trigger">
13058 <div class="modal-container">
13059 <label for="invalidProductAmountWarningModalTrigger" id="invalidProductAmountWarningModalOverlay" class="modal-overlay @(isCartPage ? "js-in-cart-invalid-amount-prevent-close" : "")"></label>
13060 <div class="modal modal-height--auto js-invalid-product-amount-warning-modal @(userIsImpersonator ? "js-product-amount-impersonator-mode" : "js-product-amount-strict-mode")">
13061 @foreach (var message in messages)
13062 {
13063 <div class="js-message @message.Class">
13064 <div class="modal__header">@message.HeaderMessage</div>
13065 <div class="modal__body">@message.BodyMessage <b class="js-modal__nearest-valid-amount"></b><span class="js-modal__total-product-amount-container">@Translate("Smartpage.InvalidAmount.Warning.TotalAmount", "<br>Det <b>samlede antal i din kurv</b> vil i alt være:") <b class="js-modal__total-product-amount"></b></span></div>
13066 <div class="d-none js-in-cart-invalid-amount-button-container in-cart-invalid-amount-button-container">
13067 @if (userIsImpersonator)
13068 {
13069 <label class="btn btn--secondary dw-mod js-in-cart-impersonator-invalid-amount-close-modal" for="invalidProductAmountWarningModalTrigger" style="">@Translate("Smartpage:InvalidAmount.Impersonator.ChangeCart.Warning.Decline", "Nej tak, behold mit valg")</label>
13070 }
13071 else
13072 {
13073 <div class="btn btn--secondary dw-mod js-in-cart-invalid-amount-decline-nearest" style="">@Translate("Smartpage:InvalidAmount.ChangeCart.Warning.Decline", "Nej tak, behold tidligere antal")</div>
13074 }
13075 <div class="btn btn--primary dw-mod js-in-cart-invalid-amount-accept-nearest" style="">@Translate("Smartpage:InvalidAmount.ChangeCart.Warning.Accept", "Ja tak, opdatér antal")</div>
13076 </div>
13077 </div>
13078 }
13079 <label class="modal__close-btn @(isCartPage ? "js-in-cart-invalid-amount-prevent-close-btn" : "")" for="invalidProductAmountWarningModalTrigger"></label>
13080 </div>
13081 </div>
13082 }
13083
13084 @helper RenderMobileTopSearchBar()
13085 {
13086 string searchFeedId = "";
13087 string searchSecondFeedId = "";
13088 int groupsFeedId;
13089 string productsSearchId = Converter.ToString(GetPageIdByNavigationTag("ProductSearchFeed"));
13090 int productsPageId = GetPageIdByNavigationTag("ProductsPage");
13091 string contentSearchPageLink = GetPageIdByNavigationTag("ContentSearchResults") + "&Areaid=" + Model.Area.ID;
13092 string resultPageLink;
13093 string searchPlaceholder;
13094 string searchType = "product-search";
13095 string searchTemplate;
13096 string searchContentTemplate = "";
13097 string searchValue = HttpContext.Current.Request.QueryString.Get("Search") ?? "";
13098 bool showGroups = true;
13099
13100 if (Model.Area.Item.GetItem("Layout").GetList("TopSearch").SelectedValue == "contentSearch")
13101 {
13102 searchFeedId = GetPageIdByNavigationTag("ContentSearchFeed") + "&Areaid=" + Model.Area.ID + "&pagesOnly=true";
13103 resultPageLink = contentSearchPageLink;
13104 searchPlaceholder = Translate("Search page");
13105 groupsFeedId = 0;
13106 searchType = "content-search";
13107 searchTemplate = "SearchPagesTemplate";
13108 showGroups = false;
13109 }
13110 else if (Model.Area.Item.GetItem("Layout").GetList("TopSearch").SelectedValue == "combinedSearch")
13111 {
13112 searchFeedId = productsPageId + "&feed=true";
13113 searchSecondFeedId = GetPageIdByNavigationTag("ContentSearchFeed") + "&Areaid=" + Model.Area.ID + "&pagesOnly=true";
13114 resultPageLink = Converter.ToString(productsPageId);
13115 searchPlaceholder = Translate("Search products or pages");
13116 groupsFeedId = GetPageIdByNavigationTag("ProductGroupsFeed");
13117 searchType = "combined-search";
13118 searchTemplate = "SearchProductsTemplateWrap";
13119 searchContentTemplate = "SearchPagesTemplateWrap";
13120 showGroups = Model.Area.Item.GetItem("Layout").GetBoolean("ShowGroupsSelector");
13121 }
13122 else
13123 {
13124 resultPageLink = Converter.ToString(productsPageId);
13125 searchFeedId = productsSearchId + "&feed=true";
13126 groupsFeedId = GetPageIdByNavigationTag("ProductGroupsFeed");
13127 searchPlaceholder = Translate("Search products");
13128 searchTemplate = "SearchResultsTypeAheadMobile";
13129 searchType = "product-search";
13130 showGroups = Model.Area.Item.GetItem("Layout").GetBoolean("ShowGroupsSelector");
13131 }
13132
13133 <input type="checkbox" id="MobileSearchTrigger" class="mobile-search-trigger" />
13134
13135 <div class="main-navigation-mobile typeahead-mobile dw-mod">
13136 <div class="center-container top-container__center-container u-no-padding dw-mod">
13137 <div class="grid">
13138 <div class="grid__col-auto">
13139 <div class="typeahead-mobile__search-field dw-mod u-no-padding-x js-typeahead" data-page-size="@(searchType == "combined-search" ? 4 : 8)" id="MobileProductSearch" data-search-feed-id="@searchFeedId" data-search-second-feed-id="@searchSecondFeedId" data-result-page-id="@resultPageLink" data-search-type="@searchType">
13140 <form action="@Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl(GetPageIdByNavigationTag("ProductsPage"))">
13141 <input id="TypeaheadSearchFieldMobile" type="text" class="js-typeahead-search-field u-w160px u-no-margin" placeholder="@HttpUtility.HtmlAttributeEncode(searchPlaceholder)" value="@HttpUtility.HtmlAttributeEncode(searchValue)" name="Search" data-shop-id="@Pageview.Area.EcomShopId" data-area-id="@Converter.ToString(Pageview.AreaID)">
13142 </form>
13143 @if (string.IsNullOrEmpty(searchSecondFeedId))
13144 {
13145 <ul class="dropdown dropdown--absolute-position u-min-w220px u-full-width js-handlebars-root js-typeahead-search-content dw-mod" id="MobileProductSearchBarContent" data-template="@searchTemplate" data-json-feed="/Default.aspx?ID=@searchFeedId&feedType=productsOnly" data-init-onload="false"></ul>
13146 }
13147 else
13148 {
13149 <div class="dropdown dropdown--absolute-position dropdown--combined grid dropdown--combined-mobile grid">
13150
13151 <div class="js-handlebars-root js-typeahead-search-content grid__col-sm-7 grid__col--bleed-y" id="MobileProductSearchBarContent" data-template="@searchTemplate" data-json-feed="/Default.aspx?ID=@searchFeedId&feedType=productsOnly" data-init-onload="false"></div>
13152 <div class="js-handlebars-root js-typeahead-additional-search-content grid__col-sm-5 grid__col--bleed-y" id="MobileContentSearchBarContent" data-template="@searchContentTemplate" data-json-feed="/Default.aspx?ID=@searchSecondFeedId" data-init-onload="false"></div>
13153 <div class="js-spell-check-suggestions grid__col-sm-12 grid__col--bleed-y" id="SpellCheckerSuggestionsSearchBarContent" data-template="SearchSpellCheckerSuggestionsTemplateWrap" data-init-onload="false"></div>
13154 </div>
13155 }
13156 <button type="button" class="btn btn--condensed btn--primary u-no-margin dw-mod js-typeahead-enter-btn"><i class="@Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("SearchIcon").SelectedValue"></i></button>
13157 </div>
13158 </div>
13159 </div>
13160 </div>
13161 </div>
13162 }
13163
13164 @helper RenderEngrosRedirectModal(Dynamicweb.Security.UserManagement.User frontendUser)
13165 {
13166 string logo = Model.Area.Item.GetItem("Layout").GetFile("LogoImage") != null ? Model.Area.Item.GetItem("Layout").GetFile("LogoImage").PathUrlEncoded : "/Files/Images/logo-dynamicweb.png";
13167 if (Path.GetExtension(logo).ToLower() != ".svg")
13168 {
13169 int logoHeight = Model.Area.Item.GetItem("Layout").GetInt32("LogoHeight");
13170 logoHeight = logoHeight > 0 && Pageview.Device != Dynamicweb.Frontend.Devices.DeviceType.Mobile ? logoHeight : 40;
13171 logo = "/Admin/Public/GetImage.ashx?height=" + Converter.ToString(logoHeight) + "&crop=5&Compression=75&image=" + logo;
13172 }
13173 else
13174 {
13175 logo = HttpUtility.UrlDecode(logo);
13176 }
13177
13178 var redirect = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetRawValueString("EngrosRedirectUrl");
13179 if (frontendUser != null)
13180 {
13181 string userName = frontendUser.UserName;
13182 string userPassword = frontendUser.Password;
13183 if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(userPassword))
13184 {
13185 string loginToken = Dynamicweb.Frontend.LoginHandler.GetLoginToken(userName, userPassword);
13186 if (!string.IsNullOrEmpty(loginToken))
13187 {
13188 redirect += "?username=" + userName + "&PwToken=" + loginToken;
13189 }
13190 }
13191 }
13192
13193 <input type="checkbox" id="EngrosRedirectModalTrigger" class="modal-trigger" checked>
13194 <div class="modal-container">
13195 <label class="modal-overlay model-overlay--disallow"></label>
13196 <div class="modal modal--md modal-height--auto engros-redirect-modal" id="EngrosRedirectModal">
13197 <div class="modal__header">
13198 <img class="grid__cell-img logo__img dw-mod" src="@logo" alt="Logo">
13199 <div class="u-ta-center header-text">
13200 <strong>@Translate("Smartpage:EngrosRedirectModal.Welcome", "Velkommen tilbage")</strong>
13201 </div>
13202 </div>
13203 <div class="modal__body">
13204 <div class="u-ta-center">@Translate("Smartpage:EngrosRedirectModal.Text", "Vi kan se at du har brugeradgang til vores professionel site.")</div>
13205 <div class="u-ta-center focus-text">@Translate("Smartpage:EngrosRedirectModal.FocusText", "Videre til professionel site?")</div>
13206 <div class="engros-redirect-modal__buttons">
13207 <label for="EngrosRedirectModalTrigger" class="btn btn--secondary dw-mod">@Translate("Smartpage:EngrosRedirectModal.No", "Nej, bliv her")</label>
13208 <a href="@redirect" class="btn btn--primary dw-mod" onclick="">@Translate("Smartpage:EngrosRedirectModal.Yes", "Ja, videre tak")</a>
13209 </div>
13210 </div>
13211 </div>
13212 </div>
13213 }
13214
13215 @helper RenderAgeRestrictionModal()
13216 {
13217 string logo = Model.Area.Item.GetItem("Layout").GetFile("LogoImage") != null ? Model.Area.Item.GetItem("Layout").GetFile("LogoImage").PathUrlEncoded : "/Files/Images/logo-dynamicweb.png";
13218 if (Path.GetExtension(logo).ToLower() != ".svg")
13219 {
13220 int logoHeight = Model.Area.Item.GetItem("Layout").GetInt32("LogoHeight");
13221 logoHeight = logoHeight > 0 && Pageview.Device.ToString() != "Mobile" ? logoHeight : 40;
13222 logo = "/Admin/Public/GetImage.ashx?height=" + Converter.ToString(logoHeight) + "&crop=5&Compression=75&image=" + logo;
13223 }
13224 else
13225 {
13226 logo = HttpUtility.UrlDecode(logo);
13227 }
13228
13229 <input type="checkbox" id="AgeRestrictionModalTrigger" class="modal-trigger">
13230 <div class="modal-container">
13231 <label class="modal-overlay model-overlay--disallow"></label>
13232 <div class="modal modal--md modal-height--auto age-restriction-modal" id="AgeRestrictionModal">
13233 <div class="modal__header">
13234 <img class="grid__cell-img logo__img dw-mod" src="@logo" alt="Logo">
13235 <div class="u-ta-center header-text">
13236 <strong>@Translate("Smartpage:AgeRestrictionModal.Welcome", "Velkommen")</strong>
13237 </div>
13238 </div>
13239 <div class="modal__body">
13240 <div class="u-ta-center">@Translate("Smartpage:AgeRestrictionModal.Text", "Husk at du skal være fyldt 18 år for at købe varer indeholdende alkohol hos PhilipsonWine.com")</div>
13241 <div class="u-ta-center focus-text">@Translate("Smartpage:AgeRestrictionModal.AreYouOverEighteen", "Er du over 18 år?")</div>
13242 <div class="age-restriction-modal__buttons">
13243 <a href="/Default.aspx?ID=@GetPageIdByNavigationTag("AgeRestrictionPage")" class="btn btn--secondary dw-mod js-decline-age-consent" onclick="setAgeConsent(event, false)">@Translate("Smartpage:AgeRestrictionModal.No", "Nej")</a>
13244 <button class="btn btn--primary dw-mod" onclick="setAgeConsent(event, true)">@Translate("Smartpage:AgeRestrictionModal.Yes", "Ja")</button>
13245 </div>
13246 </div>
13247 </div>
13248 </div>
13249
13250 <script>
13251 // Check if user has taken action on age restriction modal
13252 document.addEventListener("DOMContentLoaded", function () {
13253 var modalTrigger = document.getElementById('AgeRestrictionModalTrigger');
13254 var expiresIn = localStorage.getItem('OverEighteenInteraction.ExpiresIn');
13255 var today = new Date();
13256 if (localStorage.getItem('OverEighteenInteraction') == 'null' || (expiresIn != 'null' && new Date(expiresIn) < today)) {
13257 if (modalTrigger != null) {
13258 modalTrigger.checked = true;
13259 }
13260 // Disallow scroll until user has taken action on age restriction modal
13261 document.querySelector('body').style.height = '100%';
13262 }
13263 if (localStorage.getItem('OverEighteenInteraction') == 'false' && expiresIn != 'null' && new Date(expiresIn) > today) {
13264 var notAllowedLink = document.querySelector('.js-decline-age-consent').getAttribute('href');
13265 if (notAllowedLink != null) {
13266 window.location.href = notAllowedLink;
13267 }
13268 }
13269 if (expiresIn != 'null' && new Date(expiresIn) < today && modalTrigger != null) {
13270 modalTrigger.checked = true;
13271 }
13272 });
13273
13274 function setAgeConsent(event, selection) {
13275 event.preventDefault();
13276
13277 // Allow scroll again
13278 document.querySelector('body').style.height = 'initial';
13279
13280 // Hide modal
13281 var modalTrigger = document.getElementById('AgeRestrictionModalTrigger');
13282 if (modalTrigger != null) {
13283 modalTrigger.checked = true;
13284 }
13285
13286 // Expires in
13287 var oneWeekFromNow = new Date();
13288 oneWeekFromNow.setDate(oneWeekFromNow.getDate() + 7);
13289 localStorage.setItem('OverEighteenInteraction.ExpiresIn', oneWeekFromNow);
13290
13291 if (selection) {
13292 // Save selection
13293 localStorage.setItem('OverEighteenInteraction', 'true');
13294 modalTrigger.checked = false;
13295 } else {
13296 localStorage.setItem('OverEighteenInteraction', 'false');
13297 window.location.href = event.target.getAttribute('href');
13298 }
13299 }
13300 </script>
13301 }
13302
13303 @helper RenderSwedishCurrencySelector()
13304 {
13305 // Use PageID for navigating user instead of AreaID to avoid infinite triggering of modal
13306 string queryString = Dynamicweb.Environment.Helpers.LinkHelper.StripQueryString(HttpContext.Current.Request.Url.PathAndQuery, "AreaID");
13307 queryString = Dynamicweb.Environment.Helpers.LinkHelper.StripQueryString(queryString, "CurrencyCode");
13308 queryString = Dynamicweb.Environment.Helpers.LinkHelper.ReplaceQueryString(queryString, "Id", Converter.ToString(Pageview.ID));
13309
13310 <input type="checkbox" id="SwedishCurrencySelectorModalTrigger" class="modal-trigger">
13311 <div class="modal-container">
13312 <label class="modal-overlay model-overlay--disallow"></label>
13313 <div class="modal modal--lg modal-height--auto swedish-currency-selector-modal" id="SwedishCurrencySelectorModal">
13314 <div class="modal__header">
13315 <div class="u-ta-center header-text">
13316 <strong>@Translate("Smartpage:SwedishCurrencySelector.Welcome", "Velkommen")</strong>
13317 </div>
13318 </div>
13319 <div class="modal__body">
13320 <div class="grid">
13321 <div class="grid__col-12 grid__col-sm-6 currency-section">
13322 <div class="u-ta-center">@Translate("Smartpage:SwedishCurrencySelector.SwedishCurrencyOptionText", "Ønsker du at få din ordre sendt med fragt, da vil ordren blive beregnet i SEK inkl. Svenske afgifter")</div>
13323 <a href="@Dynamicweb.Environment.Helpers.LinkHelper.AddToQueryString(queryString, "CurrencyCode=SEK")" class="btn btn--primary dw-mod">@Translate("Smartpage:SwedishCurrencySelector.SwedishCurrencyOption", "SEK")</a>
13324 </div>
13325 <div class="grid__col-12 grid__col-sm-6 currency-section">
13326 <div class="u-ta-center">@Translate("Smartpage:SwedishCurrencySelector.DanishCurrencyOptionText", "Ønsker du at afhente din ordre, da vil ordren blive beregnet i DKK")</div>
13327 <a href="@Dynamicweb.Environment.Helpers.LinkHelper.AddToQueryString(queryString, "CurrencyCode=DKK")" class="btn btn--primary dw-mod">@Translate("Smartpage:SwedishCurrencySelector.DanishCurrencyOption", "DKK")</a>
13328 </div>
13329 </div>
13330 </div>
13331 </div>
13332 </div>
13333
13334 <script>
13335 document.addEventListener("DOMContentLoaded", function () {
13336 var modalTrigger = document.getElementById('SwedishCurrencySelectorModalTrigger');
13337 if (modalTrigger != null) {
13338 modalTrigger.checked = true;
13339 }
13340 });
13341 </script>
13342 }
13343
13344 @helper CustomRenderMasterMetadata()
13345 {
13346 var swatches = new Dynamicweb.Content.Items.ColorSwatchService();
13347 var brandColors = swatches.GetColorSwatch(Pageview.AreaID);
13348 string brandColorOne = brandColors.Palette["BrandColor1"];
13349
13350 if (!String.IsNullOrEmpty(Model.Area.Item.GetItem("Settings").GetString("AppName")) && Model.Area.Item.GetItem("Settings").GetFile("AppIcon") != null)
13351 {
13352 Manifest manifest = new Manifest
13353 {
13354 name = Model.Area.Item.GetItem("Settings").GetString("AppName"),
13355 short_name = !String.IsNullOrEmpty(Model.Area.Item.GetItem("Settings").GetString("AppShortName")) ? Model.Area.Item.GetItem("Settings").GetString("AppShortName") : Model.Area.Item.GetItem("Settings").GetString("AppName"),
13356 start_url = "/",
13357 display = "standalone",
13358 background_color = Model.Area.Item.GetItem("Settings").GetString("AppBackgroundColor"),
13359 theme_color = Model.Area.Item.GetItem("Settings").GetString("AppThemeColor")
13360 };
13361
13362 manifest.icons = new List<ManifestIcon> {
13363 new ManifestIcon {
13364 src = "/Admin/Public/GetImage.ashx?width=192&height=192&crop=5&image=" + Model.Area.Item.GetItem("Settings").GetFile("AppIcon").PathUrlEncoded,
13365 sizes = "192x192",
13366 type = "image/png"
13367 },
13368 new ManifestIcon {
13369 src = "/Admin/Public/GetImage.ashx?width=512&height=512&crop=5&image=" + Model.Area.Item.GetItem("Settings").GetFile("AppIcon").PathUrlEncoded,
13370 sizes = "512x512",
13371 type = "image/png"
13372 },
13373 new ManifestIcon {
13374 src = "/Admin/Public/GetImage.ashx?width=1024&height=1024&crop=5&image=" + Model.Area.Item.GetItem("Settings").GetFile("AppIcon").PathUrlEncoded,
13375 sizes = "1024x1024",
13376 type = "image/png"
13377 }
13378 };
13379
13380 string manifestFilePath = HttpContext.Current.Request.MapPath("/Files/Templates/Designs/Rapido/manifest.json");
13381 string manifestJSON = Newtonsoft.Json.JsonConvert.SerializeObject(manifest);
13382 string currentManifest = File.ReadAllText(manifestFilePath);
13383
13384 if (manifestJSON != currentManifest)
13385 {
13386 File.WriteAllText(manifestFilePath, manifestJSON);
13387 }
13388 }
13389
13390 string titleTag = Model.Title;
13391
13392 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request["ProductId"]))
13393 {
13394 titleTag = $"{Translate("Smartpage:ProductTitleTag.Buy", "Køb")} {Model.Title.TrimEnd()} {Translate("Smartpage:ProductTitleTag.Today", "i dag")} | {Translate("Smartpage:ProductTitleTag.Name", "Philipson Wine")}";
13395 }
13396
13397 <meta charset="utf-8" />
13398 <title>@titleTag</title>
13399 <meta name="viewport" content="width=device-width, initial-scale=1.0">
13400 <meta name="theme-color" content="@brandColorOne" />
13401
13402 if (Model.MetaTags != null && !Model.MetaTags.Contains("robots"))
13403 {
13404 Pageview.Meta.AddTag("robots", "index, follow");
13405 }
13406
13407 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request["ProductId"]))
13408 {
13409 if (!string.IsNullOrEmpty(Pageview.AreaSettings.GetItem("Custom").GetString("OpenGraphGlobalImage")) && Model.MetaTags != null && !Model.MetaTags.Contains("og:image") && Model.PropertyItem != null && Model.PropertyItem.GetFile("OpenGraphImage") != null)
13410 {
13411 string logoimage = Converter.ToString(Pageview.AreaSettings.GetItem("Custom").GetFile("OpenGraphGlobalImage").Path);
13412 var metaImage = "<meta property=\"og:image\" content=\"" + string.Format("{0}://{1}{2}", Dynamicweb.Context.Current.Request.Url.Scheme, HttpContext.Current.Request.Url.Host, logoimage) + "\">";
13413 Pageview.Meta.AddTag(metaImage);
13414 }
13415 }
13416 else
13417 {
13418 if (Model.MetaTags != null && !Model.MetaTags.Contains("og:image") && Model.PropertyItem != null && Model.PropertyItem.GetFile("OpenGraphImage") != null)
13419 {
13420 Pageview.Meta.AddTag("og:image", string.Format("{0}://{1}{2}", Dynamicweb.Context.Current.Request.Url.Scheme, HttpContext.Current.Request.Url.Host, Model.PropertyItem.GetFile("OpenGraphImage")));
13421 }
13422 else
13423 {
13424 if (!string.IsNullOrEmpty(Pageview.AreaSettings.GetItem("Custom").GetString("OpenGraphGlobalImage")))
13425 {
13426 string logoimage = Converter.ToString(Pageview.AreaSettings.GetItem("Custom").GetFile("OpenGraphGlobalImage").Path);
13427 var metaImage = "<meta property=\"og:image\" content=\"" + string.Format("{0}://{1}{2}", Dynamicweb.Context.Current.Request.Url.Scheme, HttpContext.Current.Request.Url.Host, logoimage) + "\">";
13428 Pageview.Meta.AddTag(metaImage);
13429 }
13430 }
13431 }
13432
13433 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request["ProductId"]))
13434 {
13435 string description = $"{Translate("Smartpage:ProductDescriptionTag.Buy", "Køb")} {Model.Title.TrimEnd()} {Translate("Smartpage:ProductDescriptionTag.DeliveryText", "og få hurtig levering til din dør med fri fragt ved køb over 399 kroner.")}";
13436 string producerCode = GetProductFieldValue("SpProducerCode");
13437
13438 if (!string.IsNullOrEmpty(producerCode))
13439 {
13440 var producer = Smartpage.PhilipsonWine.Producer.CustomProducerService.Instance.GetProducer(producerCode);
13441 if (producer != null && !string.IsNullOrWhiteSpace(producer.ProducerName))
13442 {
13443 description = $"{Translate("Smartpage:ProductDescriptionTag.Buy", "Køb")} {Model.Title.TrimEnd()} {Translate("Smartpage:ProductDescriptionTag.From", "fra")} {producer.ProducerName} {Translate("Smartpage:ProductDescriptionTag.DeliveryText", "og få hurtig levering til din dør med fri fragt ved køb over 399 kroner.")}";
13444 }
13445 }
13446
13447 Pageview.Meta.AddTag("description", HttpUtility.HtmlAttributeEncode(description));
13448 Pageview.Meta.AddTag("<meta property=\"og:description\" content=\"" + HttpUtility.HtmlAttributeEncode(description) + "\">");
13449 }
13450 else if (!Model.MetaTags.Contains("og:description") && !string.IsNullOrEmpty(Model.Description))
13451 {
13452 var description = Regex.Replace(Model.Description, "<.*?>", string.Empty);
13453 var metadescription = "<meta property=\"og:description\" content=\"" + HttpUtility.HtmlAttributeEncode(description) + "\">";
13454 Pageview.Meta.AddTag(metadescription);
13455 }
13456
13457 Pageview.Meta.AddTag("<meta property=\"og:title\" content=\"" + HttpUtility.HtmlAttributeEncode(titleTag) + "\">");
13458
13459 Pageview.Meta.AddTag("<meta property=\"og:site_name\" content=\"" + Pageview.Area.Name + "\">");
13460 Pageview.Meta.AddTag("<meta property=\"og:url\" content=\"" + HttpContext.Current.Request.Url.ToString() + "\">");
13461
13462 // check to see if the current page is a productpage
13463 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request["ProductId"]))
13464 {
13465 Pageview.Meta.AddTag("<meta property=\"og:type\" content=\"Product\">");
13466 }
13467 else
13468 {
13469 Pageview.Meta.AddTag("<meta property=\"og:type\" content=\"Website\">");
13470 }
13471
13472 if (!string.IsNullOrEmpty(Model.Area.Item.GetItem("Settings").GetString("FacebookAppID")))
13473 {
13474 Pageview.Meta.AddTag("fb:app_id", Model.Area.Item.GetItem("Settings").GetString("FacebookAppID"));
13475 }
13476
13477 @Model.MetaTags
13478 }
13479
13480 @helper RenderCartLineNotAddedModal()
13481 {
13482 <input type="checkbox" id="CartLineNotAddedModalTrigger" class="modal-trigger">
13483 <div class="modal-container">
13484 <label class="modal-overlay"></label>
13485 <div class="modal modal--lg modal-height--auto" id="CartLineNotAddedModal">
13486 <div class="modal__header u-fs-18">
13487 <div class="u-ta-center">
13488 <strong><span class="js-product-name"></span><span class="u-underline">@Translate("Smartpage:CartLineNotAddedModal.CouldNotBeAdded", " kunne ikke tilføjes til kurven")</span></strong>
13489 </div>
13490 </div>
13491 <div class="modal__body">
13492 <div class="grid grid--justify-center">
13493 <div class="grid__col-12 grid__col-sm-6">
13494 <div class="u-ta-center js-text-description u-margin-bottom"></div>
13495 <div class="u-ta-center js-text-add-quantity-instead u-margin-bottom u-bold"></div>
13496 <div class="grid">
13497 <div class="grid__col-sm-auto">
13498 <button class="btn btn--secondary u-no-margin--bottom dw-mod js-dismiss-modal" onclick="document.getElementById('CartLineNotAddedModalTrigger').checked = false;">@Translate("Smartpage:CartLineNotAddedModal.OK", "OK")</button>
13499 </div>
13500 <div class="grid__col-sm-auto u-display-none">
13501 <button class="btn btn--primary dw-mod u-no-margin--bottom js-add-quantity-instead" onclick="document.getElementById('CartLineNotAddedModalTrigger').checked = false;">@Translate("Smartpage:CartLineNotAddedModal.Add", "Tilføj")</button>
13502 </div>
13503 </div>
13504 </div>
13505 </div>
13506 </div>
13507 <label class="modal__close-btn u-margin-top-5" for="CartLineNotAddedModalTrigger"></label>
13508 </div>
13509 </div>
13510 }
13511
13512 @helper RenderHrefLang()
13513 {
13514 var languages = Model.Languages.Where(l => Dynamicweb.Content.Services.Areas.GetArea(l.ID).Published).ToList();
13515 foreach (var language in languages)
13516 {
13517 string domain = !string.IsNullOrEmpty(language.PrimaryDomain) ? language.PrimaryDomain : Dynamicweb.Context.Current.Request.Url.Host;
13518 if (!string.IsNullOrEmpty(domain))
13519 {
13520 var qs = HttpUtility.ParseQueryString(System.Web.HttpContext.Current.Request.QueryString.ToString());
13521 qs.Set("ID", Convert.ToString(language.Page.ID));
13522
13523 var page = Dynamicweb.Content.Services.Pages.GetPage(language.FirstActivePage.ID);
13524
13525 string url = domain + Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl(language.Page.ID);
13526
13527 foreach (string key in qs)
13528 {
13529 if (key == null || key.Equals("ID", StringComparison.InvariantCultureIgnoreCase))
13530 {
13531 continue;
13532 }
13533
13534 var urlFromHandler = Dynamicweb.Frontend.UrlProviders.Handler.GetUrlFromQueryString(key, qs[key], page.Area.EcomLanguageId);
13535 if (Dynamicweb.Frontend.SearchEngineFriendlyURLs.UseExtensionLessUrls)
13536 {
13537 url += urlFromHandler.Replace(".aspx", "");
13538 }
13539 else
13540 {
13541 url = url.Replace(".aspx", urlFromHandler);
13542 }
13543
13544 }
13545
13546 if (url.Contains("/forside"))
13547 {
13548 url = url.Replace("/forside", "");
13549 }
13550
13551 <link rel="alternate" hreflang="@GetHrefLang(language.Culture)" href="@(Dynamicweb.Context.Current.Request.Url.Scheme + "://" + url)" />
13552
13553 if (GetHrefLang(language.Culture) == "en-GB")
13554 {
13555 <link rel="alternate" hreflang="x-default" href="@(Dynamicweb.Context.Current.Request.Url.Scheme + "://" + url)" />
13556 }
13557 }
13558 }
13559 }
13560
13561 @helper RenderLiveshoppingActiveCampaignSignUpModal(string activeCampaignForm)
13562 {
13563 <input type="checkbox" id="LiveshoppingActiveCampaignSignUpModalTrigger" class="modal-trigger">
13564 <div class="modal-container">
13565 <label for="LiveshoppingActiveCampaignSignUpModalTrigger" class="modal-overlay"></label>
13566 <div class="modal modal--md modal-height--auto liveshopping-signup-modal" id="LiveshoppingActiveCampaignSignUpModal">
13567 <div class="modal__header">
13568 <div class="u-ta-center header-text">
13569 <strong>@Translate("Smartpage:LiveshoppingActiveCampaignSignUpModal.Signup", "Tilmelding")</strong>
13570 </div>
13571 </div>
13572 <div class="modal__body">
13573 @activeCampaignForm
13574 </div>
13575 <label class="modal__close-btn" for="LiveshoppingActiveCampaignSignUpModalTrigger"></label>
13576 </div>
13577 </div>
13578 }
13579
13580 @helper RenderBooztDiscountTermsConditionsModal(Smartpage.PhilipsonWine.EcomDiscount.Model.BooztDiscount booztDiscount)
13581 {
13582 int quantity = booztDiscount.Discount.BooztDiscountQuantity;
13583 int amount = booztDiscount.Discount.BooztDiscountAmount;
13584 string quantityPluralCheck = quantity > 1 ? Translate("Custom:BooztDiscount.TermsConditions.Modal.Products.Pluralis", "varer") : Translate("Custom:BooztDiscount.TermsConditions.Modal.Product.Singular", "vare");
13585 int termsAndConditionsPageId = GetPageIdByNavigationTag("TermsAndConditions");
13586
13587 <input type="checkbox" id="OptionalDiscountTermsConditionsModalTrigger_@booztDiscount.Discount.Discount.ID" class="modal-trigger">
13588 <div class="modal-container">
13589 <label for="OptionalDiscountTermsConditionsModalTrigger_@booztDiscount.Discount.Discount.ID" class="modal-overlay"></label>
13590 <div class="modal modal--md modal-height--auto" id="OptionalDiscountTermsConditionsModal">
13591 <div class="modal__header">
13592 <div class="u-ta-center header-text">
13593 <h3 class="custom-optional-discount-terms-conditions-modal-header">@Translate("Custom:BooztDiscount.TermsConditions.Modal.Header", "Aktiver tilbud")</h3>
13594 </div>
13595 </div>
13596 <div class="modal__body">
13597 <ul>
13598 @if (termsAndConditionsPageId > 0)
13599 {
13600 <li>
13601 <a class="u-underline" href="/Default.aspx?ID=@termsAndConditionsPageId">@Translate("Custom:BooztDiscount.TermsConditions.Modal.Body.List.TermsConditionsLink", "Philipson Wine vilkår og betingelser er gældende")</a>
13602 </li>
13603 }
13604
13605 <li>@Translate("Custom:BooztDiscount.TermsConditions.Modal.Body.List.OnlyApplicableFor", "Kun varer, der er markeret med kampagnebanneret, er omfattet af kampagnen")</li>
13606
13607 @if (quantity > 0 && amount <= 0)
13608 {
13609 <li>@string.Format(Translate("Custom:BooztDiscount.TermsConditions.Modal.Body.List.QuantityOnlyRequirement", "Der skal købes mindst {0} {1}, før dette tilbud kan anvendes"), quantity, quantityPluralCheck)</li>
13610 }
13611 else if (quantity <= 0 && amount > 0)
13612 {
13613 <li>@string.Format(Translate("Custom:BooztDiscount.TermsConditions.Modal.Body.List.AmountOnlyRequirement", "Den sammenlagte ordreværdi skal mindst være {0} {1}, før dette tilbud kan anvendes"), amount, Dynamicweb.Ecommerce.Common.Context.Currency.Symbol)</li>
13614 }
13615 else if (quantity > 0 && amount > 0)
13616 {
13617 <li>@string.Format(Translate("Custom:BooztDiscount.TermsConditions.Modal.Body.List.QuantityAndAmountRequirements", "Der skal købes mindst {0} {1} for mindst {2} {3} i den sammenlagte ordreværdi, før dette tilbud kan anvendes"), quantity, quantityPluralCheck, amount, Dynamicweb.Ecommerce.Common.Context.Currency.Symbol)</li>
13618 }
13619 </ul>
13620 </div>
13621 <div class="modal__footer">
13622 <label class="btn btn--primary dw-mod u-margin-auto u-block u-width-max-content" for="OptionalDiscountTermsConditionsModalTrigger_@booztDiscount.Discount.Discount.ID">@Translate("Custom:BooztDiscount.TermsConditions.Modal.Footer.AcceptTerms", "Ok, jeg forstår")</label>
13623 </div>
13624 <label class="modal__close-btn" for="OptionalDiscountTermsConditionsModalTrigger_@booztDiscount.Discount.Discount.ID"></label>
13625 </div>
13626 </div>
13627 }
13628
13629 @helper RenderUserEditModal()
13630 {
13631
13632 <input type="checkbox" id="UserEditModalTrigger" class="modal-trigger">
13633
13634 <div class="modal-container useredit-modal js-useredit-modal" data-usereditpageurl="/Default.aspx?ID=@GetPageIdByNavigationTag("useredit")">
13635 <label class="modal-overlay model-overlay--disallow"></label>
13636 <div class="modal modal--lg modal-height--auto" id="UserEditModal">
13637 <div class="modal__header">
13638 <div class="u-ta-center header-text u-flex u-flex--column">
13639 <strong>@Translate("Smartpage:UsereditModal.Title", "Opdatér brugerinfo")</strong>
13640 <span class="u-font-size--md">@Translate("Smartpage:UsereditModal.Subtitle", "Lorem ipsum")</span>
13641 </div>
13642 </div>
13643 <div class="modal__body js-useredit-modal-body">
13644 </div>
13645 <p class="js-useredit-form-respons-error u-no-margin--bottom u-hidden u-ta-center">@Translate("Smartpage:UsereditModal.Error", "Kunne ikke opdatere")</p>
13646 </div>
13647 </div>
13648 <script>
13649 var modalTrigger = document.getElementById('UserEditModalTrigger');
13650 if (modalTrigger != null) {
13651 modalTrigger.checked = true;
13652 }
13653 </script>
13654 }
13655
13656 @helper RenderBusinessContactImpersonationModal()
13657 {
13658 <input type="checkbox" id="BusinessContactImpersonationModalTrigger" class="modal-trigger">
13659
13660 <div class="modal-container impersonation-modal js-impersonation-modal">
13661 <label class="modal-overlay model-overlay--disallow"></label>
13662 <div class="modal modal--lg modal-height--auto" id="BusinessContactImpersonationModal">
13663 <div class="modal__header">
13664 <div class="u-ta-center header-text u-flex u-flex--column">
13665 @Translate("Smartpage:BusinessContactImpersonationModal.Header", "Ønsker du at handle på vegne af en anden kunde?")
13666 </div>
13667 </div>
13668 <div class="modal__body js-impersonation-modal-body">
13669 @if (Model.CurrentSecondaryUser != null && Model.CurrentSecondaryUser.ID > 0 && Model.CurrentUser != null && Model.CurrentUser.ID > 0)
13670 {
13671 <div class="u-ta-center u-margin-bottom">@Translate("Smartpage:BusinessContactImpersonationModal.CurrentSecondaryUser", "Du handler i øjeblikket på vegne af"): @Model.CurrentUser.Company</div>
13672 }
13673 <div class="grid">
13674 <div class="grid__col-sm-auto">
13675 @if (Model.CurrentSecondaryUser != null && Model.CurrentSecondaryUser.ID > 0)
13676 {
13677 <form method="post" class="u-no-margin u-full-width">
13678 <button class="btn btn--secondary u-no-margin--bottom dw-mod u-full-width" name="DwExtranetRemoveSecondaryUser" onclick="location.href='@Dynamicweb.Context.Current.Request.Url.PathAndQuery'" type="submit">
13679 @Translate("Smartpage:BusinessContactImpersonationModal.No", "Nej - jeg vil selv købe")
13680 </button>
13681 </form>
13682 }
13683 else
13684 {
13685 <button class="btn btn--secondary u-no-margin--bottom dw-mod js-dismiss-modal" onclick="document.getElementById('BusinessContactImpersonationModalTrigger').checked = false;">@Translate("Smartpage:BusinessContactImpersonationModal.No", "Nej - jeg vil selv købe")</button>
13686 }
13687 </div>
13688 <div class="grid__col-sm-auto">
13689 @if (Model.CurrentSecondaryUser != null && Model.CurrentSecondaryUser.ID > 0)
13690 {
13691 <button class="btn btn--secondary dw-mod u-no-margin--bottom" onclick="document.location.href='/Default.aspx?ID=@GetPageIdByNavigationTag("Impersonation")';">@Translate("Smartpage:BusinessContactImpersonationModal.ChangeCustomer", "Vælg anden kunde")</button>
13692 }
13693 else
13694 {
13695 <button class="btn btn--secondary dw-mod u-no-margin--bottom" onclick="document.location.href='/Default.aspx?ID=@GetPageIdByNavigationTag("Impersonation")';">@Translate("Smartpage:BusinessContactImpersonationModal.CustomerList", "Ja - vis kundeliste")</button>
13696 }
13697 </div>
13698 </div>
13699 </div>
13700 <label class="modal__close-btn" for="BusinessContactImpersonationModalTrigger"></label>
13701 </div>
13702 </div>
13703 <script>
13704 var modalTrigger = document.getElementById('BusinessContactImpersonationModalTrigger');
13705 if (modalTrigger != null) {
13706 modalTrigger.checked = true;
13707 }
13708 </script>
13709 }
13710
13711 @helper RenderShareUrlModal()
13712 {
13713 string currentUrl = Dynamicweb.Context.Current.Request.Url.Scheme + "://" + Dynamicweb.Context.Current.Request.Url.Host + Dynamicweb.Context.Current.Request.RawUrl;
13714 var shareOnMediaList = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetItems("ShareOnMediaList");
13715 if (shareOnMediaList != null && shareOnMediaList.Any())
13716 {
13717 int productId = Converter.ToInt32(Dynamicweb.Context.Current.Request["ProductId"]);
13718 string productName = Dynamicweb.Ecommerce.Services.Products.GetProductById(Dynamicweb.Context.Current.Request["ProductId"], string.Empty, Dynamicweb.Ecommerce.Common.Context.LanguageID)?.Name;
13719
13720 <input type="checkbox" id="ShareUrlModalTrigger" class="modal-trigger">
13721 <div id="ShareUrlModal" class="modal-container js-share-url-modal">
13722 <label class="modal-overlay js-share-url-close-modal"></label>
13723 <div class="modal modal--md modal-height--auto">
13724 <div class="modal__header">
13725 <div class="u-ta-center header-text u-flex u-flex--column">
13726 <strong>@Translate("Custom:ShareUrlModal.Title", "Del linket med dine venner!")</strong>
13727 </div>
13728 </div>
13729 <div class="modal__body">
13730 <div class="share-media-options-container">
13731 @foreach (var media in shareOnMediaList)
13732 {
13733 string mediaLogo = media.GetRawValueString("MediaLogo");
13734 string shareUrl = media.GetRawValueString("ShareUrl");
13735 if (!string.IsNullOrEmpty(mediaLogo) && !string.IsNullOrEmpty(shareUrl))
13736 {
13737 // CDN
13738 var cdnUrl = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetRawValueString("CDNUrl");
13739 bool cdnActivate = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItem("Custom").GetBoolean("CDNActivate");
13740 if (!string.IsNullOrWhiteSpace(cdnUrl) && cdnActivate)
13741 {
13742 mediaLogo = cdnUrl + mediaLogo;
13743 }
13744
13745 string constructedUrl = shareUrl + HttpUtility.HtmlAttributeEncode(Converter.ToString(currentUrl));
13746 bool isDesktop = Pageview.Device == Dynamicweb.Frontend.Devices.DeviceType.Desktop;
13747 bool showOnDesktop = media.GetBoolean("ShowOnDesktop");
13748
13749 if (!isDesktop || showOnDesktop)
13750 {
13751 string viewClickData = Smartpage.Tracking.Models.CustomTrackingDataLayer.CustomViewClickData((productId > 0 ? productId : Model.ID), media.GetRawValueString("MediaName"), Translate("Custom:DataLayer.ViewClick.SharePage.CreativeSlot", "Share page on media"), constructedUrl, currentUrl, Converter.ToString(Pageview.Device));
13752
13753 <a class="share-media-option-button js-view-click-share-url-event-trigger" href="@constructedUrl" target="_blank" data-params="@HttpUtility.HtmlAttributeEncode(viewClickData)">
13754 <img class="share-media-option-img" src="@mediaLogo" />
13755 </a>
13756 }
13757 }
13758 }
13759 </div>
13760 </div>
13761 <div class="modal__body">
13762 <div class="u-font-size--md u-bold u-flex u-justify-content--center u-padding--lg">@Translate("Custom:ShareUrlModal.CopyToClipboard.Header", "Eller kopiér linket her:")</div>
13763 <div class="u-flex u-justify-content--center content-row--column-gap-sm">
13764 <input class="share-url-input" type="text" value="@currentUrl" readonly />
13765 <button class="btn btn--primary dw-mod js-share-url-copy-button js-view-click-share-url-event-trigger" data-alert-text="@HttpUtility.HtmlAttributeEncode(Translate("Custom:ShareUrlModal.CopyToClipboard.AlertText", "Du har kopieret linket til denne side. Del linket med dine venner og bekendte!"))" data-current-url="@HttpUtility.HtmlAttributeEncode(currentUrl)" data-params="@HttpUtility.HtmlAttributeEncode(Smartpage.Tracking.Models.CustomTrackingDataLayer.CustomViewClickData(productId, productName, Translate("Custom:DataLayer.ViewClick.ShareUrlModal.CopyToClipboard.CreativeSlot", "Copy to clipboard"), currentUrl, currentUrl, Converter.ToString(Pageview.Device)))">@Translate("Custom:ShareUrlModal.CopyToClipboard.Button", "Kopiér")</button>
13766 </div>
13767 </div>
13768 <label class="modal__close-btn js-share-url-close-modal" for="ShareUrlModalTrigger"></label>
13769 </div>
13770 </div>
13771 }
13772 }
13773
13774 @if (!isFooterHidden)
13775 {
13776 <text>@inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
13777
13778 @using System
13779 @using System.Web
13780 @using System.Collections.Generic
13781 @using Dynamicweb.Rapido.Blocks.Extensibility
13782 @using Dynamicweb.Rapido.Blocks
13783 @using Dynamicweb.Rapido.Blocks.Components.General
13784 @using Custom.PhilipsonWine.Security.Helpers
13785
13786 @functions {
13787 BlocksPage footerBlocksPage = BlocksPage.GetBlockPage("Master");
13788 }
13789
13790 @{
13791 string footerColumnOneContent = Model.Area.Item.GetItem("Layout").GetItem("FooterColumnOne").GetString("Content");
13792 string footerColumnTwoContent = Model.Area.Item.GetItem("Layout").GetItem("FooterColumnTwo").GetString("Content");
13793 string footerColumnThreeContent = Model.Area.Item.GetItem("Layout").GetItem("FooterColumnThree").GetString("Content");
13794 string footerColumnOneHeader = Model.Area.Item.GetItem("Layout").GetItem("FooterColumnOne").GetString("Header");
13795 string footerColumnTwoHeader = Model.Area.Item.GetItem("Layout").GetItem("FooterColumnTwo").GetString("Header");
13796 string footerColumnThreeHeader = Model.Area.Item.GetItem("Layout").GetItem("FooterColumnThree").GetString("Header");
13797 string footerColumnFourContent = Model.Area.Item.GetItem("Layout").GetString("FooterColumnFourTrustpilot");
13798
13799 // Banner columns
13800 string footerBannerColumnOneContent = Model.Area.Item.GetItem("Layout").GetItem("FooterBannerColumnOne")?.GetString("Content");
13801 string footerBannerColumnOneIcon = Model.Area.Item.GetItem("Layout").GetItem("FooterBannerColumnOne")?.GetString("Icon");
13802 string footerBannerColumnTwoContent = Model.Area.Item.GetItem("Layout").GetItem("FooterBannerColumnTwo")?.GetString("Content");
13803 string footerBannerColumnTwoIcon = Model.Area.Item.GetItem("Layout").GetItem("FooterBannerColumnTwo")?.GetString("Icon");
13804 string footerBannerColumnThreeContent = Model.Area.Item.GetItem("Layout").GetItem("FooterBannerColumnThree")?.GetString("Content");
13805 string footerBannerColumnThreeIcon = Model.Area.Item.GetItem("Layout").GetItem("FooterBannerColumnThree")?.GetString("Icon");
13806
13807 // Bottom columns
13808 string footerBottomColumnOneContent = Model.Area.Item.GetItem("Layout").GetItem("FooterBottomColumnOne")?.GetString("Content");
13809 string footerBottomColumnOneHeader = Model.Area.Item.GetItem("Layout").GetItem("FooterBottomColumnOne")?.GetString("Header");
13810 string footerBottomColumnTwoContent = Model.Area.Item.GetItem("Layout").GetItem("FooterBottomColumnTwo")?.GetString("Content");
13811 string footerBottomColumnTwoHeader = Model.Area.Item.GetItem("Layout").GetItem("FooterBottomColumnTwo")?.GetString("Header");
13812 string footerBottomColumnThreeContent = Model.Area.Item.GetItem("Layout").GetItem("FooterBottomColumnThree")?.GetString("Content");
13813 string footerBottomColumnThreeHeader = Model.Area.Item.GetItem("Layout").GetItem("FooterBottomColumnThree")?.GetString("Header");
13814
13815 bool isDesktop = Pageview.Device == Dynamicweb.Frontend.Devices.DeviceType.Desktop;
13816
13817 // FOOTER BANNER CONTAINER
13818 Block masterFooterBannerContent = new Block()
13819 {
13820 Id = "MasterFooterBannerContent",
13821 SortId = 10,
13822 Template = RenderFooterBanner(),
13823 SkipRenderBlocksList = true
13824 };
13825 footerBlocksPage.Add(MasterBlockId.MasterFooter, masterFooterBannerContent);
13826
13827
13828 // FOOTER COLUMNS CONTAINER
13829 Block masterFooterContent = new Block()
13830 {
13831 Id = "MasterFooterContent",
13832 SortId = 20,
13833 Template = RenderFooter(),
13834 SkipRenderBlocksList = true
13835 };
13836 footerBlocksPage.Add(MasterBlockId.MasterFooter, masterFooterContent);
13837
13838
13839 // FOOTER BOTTOM CONTAINER
13840 Block masterFooterBottomContent = new Block()
13841 {
13842 Id = "MasterFooterBottomContent",
13843 SortId = 30,
13844 Template = RenderFooterBottom(),
13845 SkipRenderBlocksList = true
13846 };
13847 footerBlocksPage.Add(MasterBlockId.MasterFooter, masterFooterBottomContent);
13848
13849 if (!string.IsNullOrEmpty(footerBannerColumnOneContent) && !string.IsNullOrEmpty(footerBannerColumnOneIcon))
13850 {
13851 if (isDesktop)
13852 {
13853 Block masterFooterBannerColumnOne = new Block
13854 {
13855 Id = "MasterFooterColumnOne",
13856 SortId = 10,
13857 Template = RenderFooterBannerColumn(footerBannerColumnOneIcon, footerBannerColumnOneContent),
13858 Design = new Design
13859 {
13860 Size = "auto",
13861 RenderType = RenderType.Column,
13862 CssClass = "u-justify-content--center"
13863 }
13864 };
13865 footerBlocksPage.Add("MasterFooterBannerContent", masterFooterBannerColumnOne);
13866 }
13867 else
13868 {
13869 Block masterFooterBannerColumnOne = new Block
13870 {
13871 Id = "MasterFooterColumnOne",
13872 SortId = 10,
13873 Template = RenderFooterBannerColumn(footerBannerColumnOneIcon, footerBannerColumnOneContent),
13874 Design = new Design
13875 {
13876 RenderType = RenderType.Column,
13877 CssClass = "u-justify-content--center grid__col-6 border-right border-bottom"
13878 }
13879 };
13880 footerBlocksPage.Add("MasterFooterBannerContent", masterFooterBannerColumnOne);
13881 }
13882 }
13883
13884 if (!string.IsNullOrEmpty(footerBannerColumnTwoContent) && !string.IsNullOrEmpty(footerBannerColumnTwoIcon))
13885 {
13886 if (isDesktop)
13887 {
13888 Block masterFooterBannerColumnTwo = new Block
13889 {
13890 Id = "MasterFooterColumnOne",
13891 SortId = 20,
13892 Template = RenderFooterBannerColumn(footerBannerColumnTwoIcon, footerBannerColumnTwoContent),
13893 Design = new Design
13894 {
13895 Size = "auto",
13896 RenderType = RenderType.Column,
13897 CssClass = "u-justify-content--center"
13898 }
13899 };
13900 footerBlocksPage.Add("MasterFooterBannerContent", masterFooterBannerColumnTwo);
13901 }
13902 else
13903 {
13904 Block masterFooterBannerColumnTwo = new Block
13905 {
13906 Id = "MasterFooterColumnOne",
13907 SortId = 20,
13908 Template = RenderFooterBannerColumn(footerBannerColumnTwoIcon, footerBannerColumnTwoContent),
13909 Design = new Design
13910 {
13911 RenderType = RenderType.Column,
13912 CssClass = "u-justify-content--center grid__col-6 border-bottom"
13913 }
13914 };
13915 footerBlocksPage.Add("MasterFooterBannerContent", masterFooterBannerColumnTwo);
13916 }
13917 }
13918
13919 if (!string.IsNullOrEmpty(footerBannerColumnThreeContent) && !string.IsNullOrEmpty(footerBannerColumnThreeIcon))
13920 {
13921 if (isDesktop)
13922 {
13923 Block masterFooterBannerColumnThree = new Block
13924 {
13925 Id = "MasterFooterColumnOne",
13926 SortId = 20,
13927 Template = RenderFooterBannerColumn(footerBannerColumnThreeIcon, footerBannerColumnThreeContent),
13928 Design = new Design
13929 {
13930 Size = "auto",
13931 RenderType = RenderType.Column,
13932 CssClass = "u-justify-content--center"
13933 }
13934 };
13935 footerBlocksPage.Add("MasterFooterBannerContent", masterFooterBannerColumnThree);
13936 }
13937 else
13938 {
13939 Block masterFooterBannerColumnThree = new Block
13940 {
13941 Id = "MasterFooterColumnOne",
13942 SortId = 20,
13943 Template = RenderFooterBannerColumn(footerBannerColumnThreeIcon, footerBannerColumnThreeContent),
13944 Design = new Design
13945 {
13946 RenderType = RenderType.Column,
13947 CssClass = "u-justify-content--center grid__col-6 border-right"
13948 }
13949 };
13950 footerBlocksPage.Add("MasterFooterBannerContent", masterFooterBannerColumnThree);
13951 }
13952 }
13953
13954 var footerSocialBanner = Model.Area.Item.GetItem("Layout").GetItem("FooterBannerSocial");
13955 if (footerSocialBanner != null && footerSocialBanner.GetItems("Icons").Any())
13956 {
13957 if (isDesktop)
13958 {
13959 Block masterFooterSocialLinks = new Block
13960 {
13961 Id = "MasterFooterSocialLinks",
13962 SortId = 50,
13963 Template = RenderFooterSocialLinks(footerSocialBanner),
13964 Design = new Design
13965 {
13966 Size = "auto",
13967 RenderType = RenderType.Column,
13968 CssClass = "u-justify-content--center"
13969 }
13970 };
13971 footerBlocksPage.Add("MasterFooterBannerContent", masterFooterSocialLinks);
13972 }
13973 else
13974 {
13975 Block masterFooterSocialLinks = new Block
13976 {
13977 Id = "MasterFooterSocialLinks",
13978 SortId = 50,
13979 Template = RenderFooterSocialLinks(footerSocialBanner),
13980 Design = new Design
13981 {
13982 RenderType = RenderType.Column,
13983 CssClass = "u-justify-content--center grid__col-6"
13984 }
13985 };
13986 footerBlocksPage.Add("MasterFooterBannerContent", masterFooterSocialLinks);
13987 }
13988 }
13989
13990 // Footer top columns
13991
13992 if (!string.IsNullOrEmpty(footerColumnOneContent) || !string.IsNullOrEmpty(footerColumnOneHeader))
13993 {
13994 if (isDesktop)
13995 {
13996 Block masterFooterColumnOne = new Block
13997 {
13998 Id = "MasterFooterColumnOne",
13999 SortId = 10,
14000 Template = RenderFooterColumn(footerColumnOneHeader, footerColumnOneContent),
14001 Design = new Design
14002 {
14003 Size = "auto",
14004 RenderType = RenderType.Column
14005 }
14006 };
14007 footerBlocksPage.Add("MasterFooterContent", masterFooterColumnOne);
14008 }
14009 else
14010 {
14011 Block masterFooterColumnOne = new Block
14012 {
14013 Id = "MasterFooterColumnOne",
14014 SortId = 10,
14015 Template = RenderFooterColumn(footerColumnOneHeader, footerColumnOneContent),
14016 Design = new Design
14017 {
14018 RenderType = RenderType.Column,
14019 CssClass = "grid__col-6 mobile-order-1"
14020 }
14021 };
14022 footerBlocksPage.Add("MasterFooterContent", masterFooterColumnOne);
14023 }
14024 }
14025
14026 if (!string.IsNullOrEmpty(footerColumnTwoContent) || !string.IsNullOrEmpty(footerColumnTwoHeader))
14027 {
14028 if (isDesktop)
14029 {
14030 Block masterFooterColumnTwo = new Block
14031 {
14032 Id = "MasterFooterColumnTwo",
14033 SortId = 20,
14034 Template = RenderFooterColumn(footerColumnTwoHeader, footerColumnTwoContent),
14035 Design = new Design
14036 {
14037 Size = "auto",
14038 RenderType = RenderType.Column
14039 }
14040 };
14041 footerBlocksPage.Add("MasterFooterContent", masterFooterColumnTwo);
14042 }
14043 }
14044
14045 if (!string.IsNullOrEmpty(footerColumnThreeContent) || !string.IsNullOrEmpty(footerColumnThreeHeader))
14046 {
14047 if (isDesktop)
14048 {
14049 Block masterFooterColumnThree = new Block
14050 {
14051 Id = "MasterFooterColumnThree",
14052 SortId = 30,
14053 Template = RenderFooterColumn(footerColumnThreeHeader, footerColumnThreeContent),
14054 Design = new Design
14055 {
14056 Size = "auto",
14057 RenderType = RenderType.Column
14058 }
14059 };
14060 footerBlocksPage.Add("MasterFooterContent", masterFooterColumnThree);
14061 }
14062 else
14063 {
14064 Block masterFooterColumnThree = new Block
14065 {
14066 Id = "MasterFooterColumnThree",
14067 SortId = 30,
14068 Template = RenderFooterColumn(footerColumnThreeHeader, footerColumnThreeContent),
14069 Design = new Design
14070 {
14071 RenderType = RenderType.Column,
14072 CssClass = "grid__col-6 mobile-order-1"
14073 }
14074 };
14075 footerBlocksPage.Add("MasterFooterContent", masterFooterColumnThree);
14076 }
14077 }
14078
14079 if (!string.IsNullOrEmpty(footerColumnFourContent))
14080 {
14081 if (isDesktop)
14082 {
14083 Block masterFooterTrustpilot = new Block
14084 {
14085 Id = "MasterFooterTrustpilot",
14086 SortId = 40,
14087 Template = RenderTrustpilotWidget(footerColumnFourContent),
14088 Design = new Design
14089 {
14090 Size = "auto",
14091 RenderType = RenderType.Column
14092 }
14093 };
14094 footerBlocksPage.Add("MasterFooterContent", masterFooterTrustpilot);
14095 }
14096 else
14097 {
14098 Block masterFooterTrustpilot = new Block
14099 {
14100 Id = "MasterFooterTrustpilot",
14101 SortId = 40,
14102 Template = RenderTrustpilotWidget(footerColumnFourContent),
14103 Design = new Design
14104 {
14105 Size = "12",
14106 RenderType = RenderType.Column,
14107 CssClass = "mobile-order-7"
14108 }
14109 };
14110 footerBlocksPage.Add("MasterFooterContent", masterFooterTrustpilot);
14111 }
14112 }
14113
14114 // Footer USP
14115 var footerUsp = Model.Area.Item.GetItem("Layout").GetItems("FooterUSP");
14116 if (footerUsp != null && footerUsp.Any())
14117 {
14118 Block masterUSP = new Block
14119 {
14120 Id = "MasterUSP",
14121 SortId = 50,
14122 Template = RenderFooterUSP(footerUsp),
14123 Design = new Design
14124 {
14125 Size = "12",
14126 RenderType = RenderType.Column,
14127 CssClass = "footer__usp mobile-order-2"
14128 }
14129 };
14130 footerBlocksPage.Add("MasterFooterContent", masterUSP);
14131
14132 }
14133
14134
14135 // Footer bottom columns
14136 if (!string.IsNullOrEmpty(footerBottomColumnOneContent) || !string.IsNullOrEmpty(footerBottomColumnOneHeader))
14137 {
14138 if (isDesktop)
14139 {
14140 Block masterFooterBottomColumnOne = new Block
14141 {
14142 Id = "MasterFooterBottomColumnOne",
14143 SortId = 60,
14144 Template = RenderFooterBottomColumn(footerBottomColumnOneHeader, footerBottomColumnOneContent),
14145 Design = new Design
14146 {
14147 Size = "3",
14148 RenderType = RenderType.Column,
14149 CssClass = "footer__bottom"
14150 }
14151 };
14152 footerBlocksPage.Add("MasterFooterContent", masterFooterBottomColumnOne);
14153 }
14154 else
14155 {
14156 Block masterFooterBottomColumnOne = new Block
14157 {
14158 Id = "MasterFooterBottomColumnOne",
14159 SortId = 60,
14160 Template = RenderFooterBottomColumn(footerBottomColumnOneHeader, footerBottomColumnOneContent),
14161 Design = new Design
14162 {
14163 RenderType = RenderType.Column,
14164 CssClass = "footer__bottom mobile-order-3 grid__col-6"
14165 }
14166 };
14167 footerBlocksPage.Add("MasterFooterContent", masterFooterBottomColumnOne);
14168 }
14169 }
14170
14171 if (!string.IsNullOrEmpty(footerBottomColumnTwoContent) || !string.IsNullOrEmpty(footerBottomColumnTwoHeader))
14172 {
14173 if (isDesktop)
14174 {
14175 Block masterFooterBottomColumnTwo = new Block
14176 {
14177 Id = "MasterFooterBottomColumnTwo",
14178 SortId = 70,
14179 Template = RenderFooterBottomColumn(footerBottomColumnTwoHeader, footerBottomColumnTwoContent),
14180 Design = new Design
14181 {
14182 Size = "3",
14183 RenderType = RenderType.Column,
14184 CssClass = "footer__bottom"
14185 }
14186 };
14187 footerBlocksPage.Add("MasterFooterContent", masterFooterBottomColumnTwo);
14188 }
14189 else
14190 {
14191 Block masterFooterBottomColumnTwo = new Block
14192 {
14193 Id = "MasterFooterBottomColumnTwo",
14194 SortId = 70,
14195 Template = RenderFooterBottomColumn(footerBottomColumnTwoHeader, footerBottomColumnTwoContent),
14196 Design = new Design
14197 {
14198 RenderType = RenderType.Column,
14199 CssClass = "footer__bottom mobile-order-4 grid__col-6"
14200 }
14201 };
14202 footerBlocksPage.Add("MasterFooterContent", masterFooterBottomColumnTwo);
14203 }
14204 }
14205
14206 if (!string.IsNullOrEmpty(footerBottomColumnThreeContent) || !string.IsNullOrEmpty(footerBottomColumnThreeHeader))
14207 {
14208 if (isDesktop)
14209 {
14210 Block masterFooterBottomColumnThree = new Block
14211 {
14212 Id = "MasterFooterBottomColumnOne",
14213 SortId = 80,
14214 Template = RenderFooterBottomColumn(footerBottomColumnThreeHeader, footerBottomColumnThreeContent),
14215 Design = new Design
14216 {
14217 Size = "3",
14218 RenderType = RenderType.Column,
14219 CssClass = "footer__bottom"
14220 }
14221 };
14222 footerBlocksPage.Add("MasterFooterContent", masterFooterBottomColumnThree);
14223 }
14224 else
14225 {
14226 Block masterFooterBottomColumnThree = new Block
14227 {
14228 Id = "MasterFooterBottomColumnOne",
14229 SortId = 80,
14230 Template = RenderFooterBottomColumn(footerBottomColumnThreeHeader, footerBottomColumnThreeContent),
14231 Design = new Design
14232 {
14233 RenderType = RenderType.Column,
14234 CssClass = "footer__bottom grid__col-6 mobile-order-5"
14235 }
14236 };
14237 footerBlocksPage.Add("MasterFooterContent", masterFooterBottomColumnThree);
14238 }
14239 }
14240
14241 if (Model.Area.Item.GetItem("Layout").GetBoolean("FooterNewsletterSignUp"))
14242 {
14243 NewsletterSignupHelperContext newsletterSignupHelperContext = new NewsletterSignupHelperContext
14244 {
14245 Pageview = Pageview,
14246 GetPageIdByNavigationTag = tag => GetPageIdByNavigationTag(tag),
14247 Translate = (text, def) => Translate(text, def)
14248 };
14249
14250 Block masterFooterNewsletterSignUp = new Block
14251 {
14252 Id = "MasterFooterNewsletterSignUp",
14253 SortId = 90,
14254 Template = RenderNewsletterSignUp(newsletterSignupHelperContext, "Footer", Model.Area.Item.GetItem("Custom").GetRawValueString("SignupNewsletterId")),
14255 Design = new Design
14256 {
14257 Size = "3",
14258 RenderType = RenderType.Column,
14259 CssClass = "footer__bottom mobile-order-6"
14260 }
14261 };
14262 footerBlocksPage.Add("MasterFooterContent", masterFooterNewsletterSignUp);
14263 }
14264
14265 // LAST ROW
14266
14267
14268 if (isDesktop)
14269 {
14270 Block masterFooterCopyright = new Block
14271 {
14272 Id = "MasterFooterCopyright",
14273 SortId = 100,
14274 Template = RenderFooterCopyright(),
14275 Design = new Design
14276 {
14277 Size = "8",
14278 RenderType = RenderType.Column,
14279 CssClass = "u-flex--row grid--align-center"
14280 }
14281 };
14282 footerBlocksPage.Add("MasterFooterBottomContent", masterFooterCopyright);
14283 }
14284 else
14285 {
14286 Block masterFooterCopyright = new Block
14287 {
14288 Id = "MasterFooterCopyright",
14289 SortId = 100,
14290 Template = RenderFooterCopyright(),
14291 Design = new Design
14292 {
14293 Size = "8",
14294 RenderType = RenderType.Column,
14295 CssClass = "u-flex--column grid--align-center"
14296 }
14297 };
14298 footerBlocksPage.Add("MasterFooterBottomContent", masterFooterCopyright);
14299 }
14300
14301
14302 var footerPayments = Model.Area.Item.GetItem("Layout").GetItems("FooterPayments");
14303 if (footerPayments != null && footerPayments.Any())
14304 {
14305 Block masterFooterPayments = new Block
14306 {
14307 Id = "MasterFooterPayments",
14308 SortId = 110,
14309 Template = RenderFooterPayments(footerPayments),
14310 Design = new Design
14311 {
14312 Size = "4",
14313 RenderType = RenderType.Column
14314 }
14315 };
14316 footerBlocksPage.Add("MasterFooterBottomContent", masterFooterPayments);
14317 }
14318 }
14319
14320 @helper RenderFooter()
14321 {
14322 List<Block> subBlocks = this.footerBlocksPage.GetBlockListById("MasterFooterContent").OrderBy(item => item.SortId).ToList();
14323
14324 <footer class="footer dw-mod">
14325 <div class="center-container top-container__center-container dw-mod">
14326 <div class="grid grid--external-bleed-x u-justify-content--center">
14327 @RenderBlockList(subBlocks)
14328 </div>
14329 </div>
14330 </footer>
14331 }
14332
14333 @helper RenderFooterBanner()
14334 {
14335 List<Block> subBlocks = this.footerBlocksPage.GetBlockListById("MasterFooterBannerContent").OrderBy(item => item.SortId).ToList();
14336
14337 <footer class="footer__banner dw-mod">
14338 <div class="center-container top-container__center-container dw-mod">
14339 <div class="grid grid--external-bleed-x u-full-height">
14340 @RenderBlockList(subBlocks)
14341 </div>
14342 </div>
14343 </footer>
14344 }
14345
14346 @helper RenderFooterBottom()
14347 {
14348 List<Block> subBlocks = this.footerBlocksPage.GetBlockListById("MasterFooterBottomContent").OrderBy(item => item.SortId).ToList();
14349
14350 <footer class="footer__end dw-mod">
14351 <div class="center-container top-container__center-container dw-mod">
14352 <div class="grid grid--external-bleed-x u-full-height">
14353 @RenderBlockList(subBlocks)
14354 </div>
14355 </div>
14356 </footer>
14357 }
14358
14359 @helper RenderFooterBannerColumn(string icon, string content)
14360 {
14361 <div class="footer__banner__container">
14362 <div class="footer__banner__icon dw-mod"><img src="@icon" /></div>
14363 <div class="footer__banner__content dw-mod">
14364 @content
14365 </div>
14366 </div>
14367 }
14368
14369
14370 @helper RenderFooterColumn(string header, string content)
14371 {
14372 <h3 class="footer__heading dw-mod">@header</h3>
14373 <div class="footer__content dw-mod">
14374 @content
14375 </div>
14376 }
14377
14378 @helper RenderFooterBottomColumn(string header, string content)
14379 {
14380 <h3 class="footer__bottom__heading dw-mod">@header</h3>
14381 <div class="footer__bottom__content dw-mod">
14382 @content
14383 </div>
14384 }
14385
14386 @helper RenderTrustpilotWidget(string content)
14387 {
14388 var footerBadges = Model.Area.Item.GetItem("Custom").GetItems("FooterBadges");
14389 string trustpilotFreeWidget = Model.Area.Item.GetItem("Custom").GetString("FooterTrustpilotFreeWidget");
14390
14391 @trustpilotFreeWidget
14392
14393 if (footerBadges != null)
14394 {
14395 <div class="footer-badges-flex">
14396 @foreach (var badge in footerBadges)
14397 {
14398 string badgeImage = badge.GetString("FooterBadgeImage");
14399 string badgeLink = badge.GetString("FooterBadgeLink");
14400 if (!string.IsNullOrEmpty(badgeLink))
14401 {
14402 <a href="@badgeLink" class="footer-badge-flex-item">
14403 <img src="@badgeImage" />
14404 </a>
14405 }
14406 else
14407 {
14408 <div class="footer-badge-flex-item">
14409 <img src="@badgeImage" />
14410 </div>
14411 }
14412 }
14413 </div>
14414 }
14415 }
14416
14417 @helper RenderFooterSocialLinks(Dynamicweb.Frontend.ItemViewModel footerSocialBanner)
14418 {
14419 var bannerContent = footerSocialBanner.GetString("Content");
14420 var bannerItems = footerSocialBanner.GetItems("Icons");
14421
14422 <div class="footer__banner__container social">
14423 <div class="footer__banner__content">
14424 <strong>@bannerContent</strong>
14425 </div>
14426 <div class="collection dw-mod">
14427 @foreach (var socialitem in bannerItems)
14428 {
14429 string socialLink = socialitem.GetString("Link");
14430 string socialIcon = socialitem.GetString("Icon");
14431 string socialIconTitle = socialitem.GetString("Title");
14432
14433 <a href="@socialLink" target="_blank" title="@socialIconTitle" class="u-margin-bottom-5px" rel="noopener"><img src="@socialIcon" /></a>
14434 }
14435 </div>
14436 </div>
14437 }
14438
14439 @helper RenderFooterPayments(IList<Dynamicweb.Frontend.ItemViewModel> footerPayments)
14440 {
14441 <div class="footer__end__content dw-mod">
14442 <p class="d-none d-lg-block">@Translate("Altid sikker og krypteret betaling")</p>
14443 <div class="collection dw-mod">
14444 @foreach (var payment in footerPayments)
14445 {
14446 var paymentItem = payment.GetValue("CardTypeOrVerifiedPayment") as Dynamicweb.Frontend.ListViewModel;
14447 string paymentImage = null;
14448 string paymentTitle = paymentItem.SelectedName;
14449 ListOptionViewModel selected = paymentItem.SelectedOptions.FirstOrDefault();
14450 if (selected != null)
14451 {
14452 paymentImage = selected.Icon;
14453 }
14454
14455 <div class="footer__card-type">
14456 <img class="b-lazy" src="/Files/Images/placeholder.gif" data-src="/Admin/Public/GetImage.ashx?width=60&Compression=75&image=@paymentImage" alt="@paymentTitle" title="@paymentTitle" />
14457 </div>
14458 }
14459 </div>
14460 </div>
14461 }
14462
14463 @helper RenderFooterCopyright()
14464 {
14465 string logo = Model.Area.Item.GetItem("Layout").GetFile("LogoImage") != null ? Model.Area.Item.GetItem("Layout").GetFile("LogoImage").PathUrlEncoded : "/Files/Images/logo-dynamicweb.png";
14466 if (Path.GetExtension(logo).ToLower() != ".svg")
14467 {
14468 int logoHeight = Model.Area.Item.GetItem("Layout").GetInt32("LogoHeight");
14469 logoHeight = logoHeight > 0 && Pageview.Device != Dynamicweb.Frontend.Devices.DeviceType.Mobile ? logoHeight : 40;
14470 logo = "/Admin/Public/GetImage.ashx?height=" + Converter.ToString(logoHeight) + "&crop=5&Compression=75&image=" + logo;
14471 }
14472 else
14473 {
14474 logo = HttpUtility.UrlDecode(logo);
14475 }
14476
14477
14478 <div class="footer__end__logo"><img src="@logo" /></div>
14479 <div class="footer__end__content">
14480 @Model.Area.Item.GetItem("Layout").GetString("FooterCopyrightText")
14481 </div>
14482 }
14483
14484 @helper RenderFooterUSP(IList<Dynamicweb.Frontend.ItemViewModel> footerUsp)
14485 {
14486 <div class="grid dw-mod">
14487 @foreach (var usp in footerUsp)
14488 {
14489 <div class="grid__col-lg-auto grid__col-md-auto grid__col-6 mobile-border dw-mod">
14490 <div class="footer__usp__content">
14491 <div class="icon">
14492 <svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
14493 viewBox="0 0 408.576 408.576" style="enable-background:new 0 0 408.576 408.576;fill:#55DE9B" xml:space="preserve">
14494 <g>
14495 <g>
14496 <path d="M204.288,0C91.648,0,0,91.648,0,204.288s91.648,204.288,204.288,204.288s204.288-91.648,204.288-204.288
14497 S316.928,0,204.288,0z M318.464,150.528l-130.56,129.536c-7.68,7.68-19.968,8.192-28.16,0.512L90.624,217.6
14498 c-8.192-7.68-8.704-20.48-1.536-28.672c7.68-8.192,20.48-8.704,28.672-1.024l54.784,50.176L289.28,121.344
14499 c8.192-8.192,20.992-8.192,29.184,0C326.656,129.536,326.656,142.336,318.464,150.528z" />
14500 </g>
14501 </g>
14502 </svg>
14503 </div>
14504 <div class="usp">@usp.GetValue("Label")</div>
14505 </div>
14506 </div>
14507 }
14508
14509 </div>
14510 }</text>
14511 }
14512
14513
14514 @functions {
14515 public class ManifestIcon
14516 {
14517 public string src { get; set; }
14518 public string type { get; set; }
14519 public string sizes { get; set; }
14520 }
14521
14522 public class Manifest
14523 {
14524 public string name { get; set; }
14525 public string short_name { get; set; }
14526 public string start_url { get; set; }
14527 public string display { get; set; }
14528 public string background_color { get; set; }
14529 public string theme_color { get; set; }
14530 public List<ManifestIcon> icons { get; set; }
14531 }
14532 }
14533
14534 <!DOCTYPE html>
14535
14536 <html lang="@Pageview.Area.CultureInfo.TwoLetterISOLanguageName">
14537
14538
14539
14540 @* The @RenderBlockList base helper is included in Components/GridBuilder.cshtml *@
14541 @RenderBlockList(masterPage.BlocksRoot.BlocksList)
14542
14543
14544
14545 @helper RenderMasterHead()
14546 {
14547 List<Block> subBlocks = this.masterPage.GetBlockListById("Head").OrderBy(item => item.SortId).ToList();
14548
14549 <head>
14550 <!-- Rapido version 3.3.1 -->
14551
14552 @RenderBlockList(subBlocks)
14553 </head>
14554
14555 }
14556
14557 @helper RenderMasterMetadata()
14558 {
14559 var swatches = new Dynamicweb.Content.Items.ColorSwatchService();
14560 var brandColors = swatches.GetColorSwatch(1);
14561 string brandColorOne = brandColors.Palette["BrandColor1"];
14562
14563 if (!String.IsNullOrEmpty(Model.Area.Item.GetItem("Settings").GetString("AppName")) && Model.Area.Item.GetItem("Settings").GetFile("AppIcon") != null)
14564 {
14565 Manifest manifest = new Manifest
14566 {
14567 name = Model.Area.Item.GetItem("Settings").GetString("AppName"),
14568 short_name = !String.IsNullOrEmpty(Model.Area.Item.GetItem("Settings").GetString("AppShortName")) ? Model.Area.Item.GetItem("Settings").GetString("AppShortName") : Model.Area.Item.GetItem("Settings").GetString("AppName"),
14569 start_url = "/",
14570 display = "standalone",
14571 background_color = Dynamicweb.Core.Converter.ToString(Model.Area.Item.GetItem("Settings").GetValue("AppBackgroundColor")),
14572 theme_color = Dynamicweb.Core.Converter.ToString(Model.Area.Item.GetItem("Settings").GetValue("AppThemeColor"))
14573 };
14574
14575 manifest.icons = new List<ManifestIcon> {
14576 new ManifestIcon {
14577 src = "/Admin/Public/GetImage.ashx?width=192&height=192&crop=5&image=" + Model.Area.Item.GetItem("Settings").GetFile("AppIcon").PathUrlEncoded,
14578 sizes = "192x192",
14579 type = "image/png"
14580 },
14581 new ManifestIcon {
14582 src = "/Admin/Public/GetImage.ashx?width=512&height=512&crop=5&image=" + Model.Area.Item.GetItem("Settings").GetFile("AppIcon").PathUrlEncoded,
14583 sizes = "512x512",
14584 type = "image/png"
14585 },
14586 new ManifestIcon {
14587 src = "/Admin/Public/GetImage.ashx?width=1024&height=1024&crop=5&image=" + Model.Area.Item.GetItem("Settings").GetFile("AppIcon").PathUrlEncoded,
14588 sizes = "1024x1024",
14589 type = "image/png"
14590 }
14591 };
14592
14593 string manifestFilePath = HttpContext.Current.Request.MapPath("/Files/Templates/Designs/Rapido/manifest.json");
14594 string manifestJSON = Newtonsoft.Json.JsonConvert.SerializeObject(manifest);
14595 string currentManifest = File.ReadAllText(manifestFilePath);
14596
14597 if (manifestJSON != currentManifest)
14598 {
14599 File.WriteAllText(manifestFilePath, manifestJSON);
14600 }
14601 }
14602
14603 <meta charset="utf-8" />
14604 <title>@Model.Title</title>
14605 <meta name="viewport" content="width=device-width, initial-scale=1.0">
14606 <meta name="robots" content="index, follow">
14607 <meta name="theme-color" content="@brandColorOne" />
14608
14609 if (Model.MetaTags != null && !Model.MetaTags.Contains("og:image") && Model.PropertyItem != null && Model.PropertyItem.GetFile("OpenGraphImage") != null)
14610 {
14611 Pageview.Meta.AddTag("og:image", string.Format("{0}://{1}{2}", Dynamicweb.Context.Current.Request.Url.Scheme, HttpContext.Current.Request.Url.Host, Model.PropertyItem.GetFile("OpenGraphImage")));
14612 }
14613
14614 if (!Model.MetaTags.Contains("og:description") && !string.IsNullOrEmpty(Model.Description))
14615 {
14616 Pageview.Meta.AddTag("og:description", Model.Description);
14617 }
14618
14619 Pageview.Meta.AddTag("og:title", Model.Title);
14620 Pageview.Meta.AddTag("og:site_name", Model.Name);
14621 Pageview.Meta.AddTag("og:url", HttpContext.Current.Request.Url.ToString());
14622 Pageview.Meta.AddTag("og:type", "Website");
14623
14624 if (!string.IsNullOrEmpty(Model.Area.Item.GetItem("Settings").GetString("FacebookAppID")))
14625 {
14626 Pageview.Meta.AddTag("fb:app_id", Model.Area.Item.GetItem("Settings").GetString("FacebookAppID"));
14627 }
14628
14629 @Model.MetaTags
14630 }
14631
14632 @helper RenderMasterCss()
14633 {
14634 var fonts = new string[] {
14635 getFontFamily("Layout", "HeaderFont"),
14636 getFontFamily("Layout", "SubheaderFont"),
14637 getFontFamily("Layout", "TertiaryHeaderFont"),
14638 getFontFamily("Layout", "BodyText"),
14639 getFontFamily("Layout", "Header", "ToolsFont"),
14640 getFontFamily("Layout", "Header", "NavigationFont"),
14641 getFontFamily("Layout", "MobileNavigation", "Font"),
14642 getFontFamily("ProductList", "Facets", "HeaderFont"),
14643 getFontFamily("ProductPage", "PriceFontDesign"),
14644 getFontFamily("Ecommerce", "SaleSticker", "Font"),
14645 getFontFamily("Ecommerce", "NewSticker", "Font"),
14646 getFontFamily("Ecommerce", "CustomSticker", "Font")
14647 };
14648
14649 string autoCssLink = "/Files/Templates/Designs/Rapido/css/rapido/rapido_" + Model.Area.ID.ToString() + ".min.css?ticks=" + Model.Area.UpdatedDate.Ticks;
14650 string favicon = Model.Area.Item.GetItem("Layout").GetFile("LogoFavicon") != null ? Model.Area.Item.GetItem("Layout").GetFile("LogoFavicon").Path : "/Files/Images/favicon.png";
14651 bool useFontAwesomePro = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetBoolean("UseFontAwesomePro");
14652 string fontAwesomeCssLink = "/Files/Templates/Designs/Rapido/css/fonts/FontAwesomeFree/css/fontawesome-all.min.css";
14653 if (useFontAwesomePro)
14654 {
14655 fontAwesomeCssLink = "/Files/Templates/Designs/Rapido/css/fonts/FontAwesomePro/css/fontawesome-all.min.css";
14656 }
14657
14658 var fileVersion = System.Web.HttpContext.Current.Cache["FileVersion"];
14659
14660 //Favicon
14661 <link href="@favicon" rel="icon" type="image/png">
14662
14663 //Base (Default, wireframe) styles
14664 <link rel="stylesheet" href="/Files/Templates/Designs/Rapido/css/base/base.min.css" type="text/css">
14665
14666 //Rapido Css from Website Settings
14667 <link rel="stylesheet" id="rapidoCss" href="@autoCssLink" type="text/css">
14668
14669 //Ignite Css (Custom site specific styles)
14670 <link rel="stylesheet" id="igniteCss" type="text/css" href="/Files/Templates/Designs/Rapido/css/ignite/ignite.min.css?v=@fileVersion">
14671
14672 //Font awesome
14673 // Several references since all browser dont support preloading
14674 // Only one request are made per ressource
14675 <link rel="preload" as="style" href="@fontAwesomeCssLink">
14676 <link rel="stylesheet" href="@fontAwesomeCssLink">
14677
14678 //Flag icon
14679 <link rel="stylesheet" href="/Files/Templates/Designs/Rapido/css/fonts/flag-icon.min.css" type="text/css">
14680
14681 //Google fonts
14682 var family = string.Join("%7C", fonts.Where(x => !string.IsNullOrEmpty(x)).Distinct().Select(x => string.Format("{0}:ital,100,200,300,400,500,600,700,800,900", x)));
14683
14684 <link href="https://fonts.googleapis.com/css?family=@family" rel="stylesheet">
14685
14686 <link href="@fontAwesomeCssLink" rel="stylesheet">
14687 <link href="/Files/Templates/Designs/Rapido/css/base/base.min.css" rel="stylesheet">
14688 <link href="@autoCssLink" rel="stylesheet">
14689 <link href="/Files/Templates/Designs/Rapido/css/ignite/ignite.min.css?v=@fileVersion" rel="stylesheet">
14690 <link href="/Files/Templates/Designs/Rapido/css/fonts/flag-icon.min.css" rel="stylesheet">
14691
14692 // Preload heavy things for faster pagespeed
14693 // Several references since all browser dont support preloading
14694 // Only one request are made per ressource
14695 <link rel="preload" as="font" type="font/woff2" crossorigin href="~/Files/Templates/Designs/Rapido/css/fonts/FontAwesomePro/webfonts/fa-brands-400.woff2" />
14696 <link rel="stylesheet" type="font/woff2" crossorigin href="~/Files/Templates/Designs/Rapido/css/fonts/FontAwesomePro/webfonts/fa-brands-400.woff2" />
14697 <link rel="preload" as="font" type="font/woff2" crossorigin href="~/Files/Templates/Designs/Rapido/css/fonts/FontAwesomePro/webfonts/fa-regular-400.woff2" />
14698 <link rel="stylesheet" type="font/woff2" crossorigin href="~/Files/Templates/Designs/Rapido/css/fonts/FontAwesomePro/webfonts/fa-regular-400.woff2" />
14699 <link rel="preload" as="font" type="font/woff2" crossorigin href="~/Files/Templates/Designs/Rapido/css/fonts/FontAwesomePro/webfonts/fa-light-300.woff2" />
14700 <link rel="stylesheet" type="font/woff2" crossorigin href="~/Files/Templates/Designs/Rapido/css/fonts/FontAwesomePro/webfonts/fa-light-300.woff2" />
14701 <link rel="preload" as="font" type="font/woff2" crossorigin href="~/Files/Templates/Designs/Rapido/css/fonts/FontAwesomePro/webfonts/fa-solid-900.woff2" />
14702 <link rel="stylesheet" type="font/woff2" crossorigin href="~/Files/Templates/Designs/Rapido/css/fonts/FontAwesomePro/webfonts/fa-solid-900.woff2" />
14703
14704 }
14705
14706 @helper RenderMasterManifest()
14707 {
14708 if (!String.IsNullOrEmpty(Model.Area.Item.GetItem("Settings").GetString("AppName")))
14709 {
14710 <link rel="manifest" href="/Files/Templates/Designs/Rapido/manifest.json">
14711 @*PushPromise("/Files/Templates/Designs/Rapido/manifest.json");*@
14712 }
14713 }
14714
14715 @helper RenderMasterBody()
14716 {
14717 List<Block> subBlocks = this.masterPage.GetBlockListById("Body").OrderBy(item => item.SortId).ToList();
14718 string designLayout = Model.PropertyItem.GetItem("CustomSettings") != null ? Model.PropertyItem.GetItem("CustomSettings").GetString("DesignLayout") != null ? Model.PropertyItem.GetItem("CustomSettings").GetList("DesignLayout").SelectedValue : "" : "";
14719
14720 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request["ProductId"]))
14721 {
14722 designLayout += " on-product-page";
14723 }
14724
14725 if (!string.IsNullOrEmpty(designLayout))
14726 {
14727 designLayout = "class=\"" + designLayout + "\"";
14728 }
14729 else if (Pageview.Page.NavigationTag == "CartPage")
14730 {
14731 designLayout = "class=\"carts-page js-carts-page\"";
14732 }
14733
14734 <body @designLayout data-mini-cart-id="@GetPageIdByNavigationTag("MiniCartFeed")">
14735 @RenderBlockList(subBlocks)
14736 </body>
14737
14738 }
14739
14740 @helper RenderMasterHeader()
14741 {
14742 List<Block> subBlocks = this.masterPage.GetBlockListById("MasterHeader").OrderBy(item => item.SortId).ToList();
14743 bool isNavigationStickyMenu = Pageview.Device == Dynamicweb.Frontend.Devices.DeviceType.Desktop && Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("StickyTop");
14744 string stickyTop = isNavigationStickyMenu ? "top-container--sticky" : "";
14745
14746 <header class="top-container @stickyTop js-top-container dw-mod" id="Top">
14747 @RenderBlockList(subBlocks)
14748 </header>
14749 }
14750
14751 @helper RenderMain()
14752 {
14753 List<Block> subBlocks = this.masterPage.GetBlockListById("MasterMain").OrderBy(item => item.SortId).ToList();
14754 bool isCocktailsPage = Dynamicweb.Context.Current.Request["ID"] == Converter.ToString(GetPageIdByNavigationTag("CocktailsPage"));
14755
14756 <main class="site dw-mod@(isCocktailsPage ? " custom-cocktails-page" : "")">
14757 @RenderBlockList(subBlocks)
14758 </main>
14759 }
14760
14761 @helper RenderPageContent()
14762 {
14763 bool isNavigationStickyMenu = Pageview.Device == Dynamicweb.Frontend.Devices.DeviceType.Desktop && Model.Area.Item.GetItem("Layout").GetItem("Header").GetBoolean("StickyTop");
14764 string pagePos = isNavigationStickyMenu ? "js-page-pos" : "";
14765
14766 <div id="Page" class="page @pagePos">
14767 <div id="content">
14768 @RenderSnippet("Content")
14769 </div>
14770 </div>
14771 }
14772
14773 @helper RenderOverlay()
14774 {
14775 string menuType = Model.Area.Item.GetItem("Layout").GetItem("Header").GetList("NavigationMegaMenu") != null ? Model.Area.Item.GetItem("Layout").GetItem("Header").GetRawValueString("NavigationMegaMenu") : "dropdown";
14776 if (menuType != "sidemenu")
14777 {
14778 <div id="js-page-overlay">
14779 </div>
14780 }
14781 }
14782
14783 @* Hack to support nested helpers *@
14784 @SnippetStart("Content")
14785 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
14786
14787
14788 @if (!Model.IsCurrentUserAllowed)
14789 {
14790 int signInPage = GetPageIdByNavigationTag("SignInPage");
14791 int dashboardPage = GetPageIdByNavigationTag("CustomerDashboard");
14792 int notValidLoginPage = GetPageIdByNavigationTag("NotValidLogin");
14793 var user = Dynamicweb.Security.UserManagement.User.GetCurrentFrontendUser();
14794 bool isEngrosSite = Pageview.AreaSettings.GetItem("Custom").GetBoolean("IsEngrosSite");
14795
14796 if (!Pageview.IsVisualEditorMode)
14797 {
14798 if (signInPage != 0)
14799 {
14800 if (signInPage != Model.ID && user == null)
14801 {
14802 Dynamicweb.Context.Current.Response.Redirect("/Default.aspx?ID=" + signInPage);
14803 }
14804 else
14805 {
14806 if (isEngrosSite && notValidLoginPage != Model.ID && notValidLoginPage != 0 && user != null)
14807 {
14808 Dynamicweb.Context.Current.Response.Redirect("/Default.aspx?ID=" + notValidLoginPage);
14809 }
14810 else
14811 {
14812 if (dashboardPage != 0)
14813 {
14814 Dynamicweb.Context.Current.Response.Redirect("/Default.aspx?ID=" + dashboardPage);
14815 }
14816 else
14817 {
14818 Dynamicweb.Context.Current.Response.Redirect("/");
14819 }
14820 }
14821 }
14822 }
14823 else
14824 {
14825 <div class="alert alert-dark m-0" role="alert">
14826 <span>@Translate("You do not have access to this page")</span>
14827 </div>
14828 }
14829 }
14830 else
14831 {
14832 <div class="alert alert-dark m-0" role="alert">
14833 <span>@Translate("To work on this page, you must be signed in, in the frontend")</span>
14834 </div>
14835 }
14836 }
14837
14838 @* Render the grid *@
14839 @Model.Grid("Grid", "Grid", "default:true;sort:1", "Pages")
14840
14841 @if (Model.PropertyItem.GetBoolean("IsNewsLetterConfirmationPage"))
14842 {
14843 <script>
14844 window.dataLayer.push({
14845 'event': 'newsLetterSignup',
14846 'signupType': 'footer',
14847 'shopId': '@Pageview.Area.EcomShopId',
14848 'areaId': '@Dynamicweb.Core.Converter.ToString(Pageview.AreaID)'
14849 })
14850 </script>
14851 }
14852 @SnippetEnd("Content")
14853
14854 </html>
14855
14856