Error executing template "Designs/Swift/_parsed/Swift_CustomerCenter.parsed.cshtml"
System.NullReferenceException: Object reference not set to an instance of an object.
at CompiledRazorTemplates.Dynamic.RazorEngine_dd34643eef3a44e895419e1049dda4ff.Execute() in C:\inetpub\wwwroot\directions2023_dev\Files\Templates\Designs\Swift\_parsed\Swift_CustomerCenter.parsed.cshtml:line 516
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 @using System
3 @using Dynamicweb
4 @using Dynamicweb.Environment
5 @using Dynamicweb.Frontend
6 @using System;
7 @using System.Web;
8
9 @{
10 //CUSTOM CODE
11 //handle Maintenance mode
12 var maintenancePage = Model.Area.Item?.GetLink("MaintenancePage") ?? null;
13 bool maintenanceMode = Model.Area.Item.GetBoolean("MaintenanceMode");
14 DateTime maintenanceStartDate = Model.Area.Item.GetDateTime("MaintenanceStartDate");
15 DateTime maintenanceEndDate = Model.Area.Item.GetDateTime("MaintenanceEndDate");
16 DateTime currentDate = System.DateTime.Now;
17 maintenanceMode = maintenanceMode && maintenanceStartDate <= currentDate && maintenanceEndDate >= currentDate;
18 var adminUser = Dynamicweb.Security.UserManagement.User.GetCurrentBackendUser();
19 int currentPage = Dynamicweb.Frontend.PageView.Current().Page.ID;
20
21 if(maintenanceMode && maintenancePage != null && adminUser == null && maintenancePage.PageId != currentPage)
22 {
23 string redirectLink = "/" + maintenancePage;
24 HttpContext.Current.Response.Redirect(redirectLink);
25 }
26 //CUSTOM CODE
27
28 var brandingPageId = Model.Area.Item?.GetInt32("BrandingPage") ?? 0;
29 var themePageId = Model.Area.Item?.GetInt32("ThemesPage") ?? 0;
30 var cssPageId = Model.Area.Item?.GetInt32("CssPage") ?? 0;
31
32 var brandingPage = brandingPageId != 0 ? Dynamicweb.Content.Services.Pages?.GetPage(brandingPageId) ?? null : null;
33 var themesParagraphs = themePageId != 0 ? Dynamicweb.Content.Services.Paragraphs?.GetParagraphsByPageId(themePageId) ?? null : null;
34 var cssParagraphs = cssPageId != 0 ? Dynamicweb.Content.Services.Paragraphs?.GetParagraphsByPageId(cssPageId) ?? null : null;
35
36 //CUSTOM CODE
37 var backgroundPageId = Model.Area.Item?.GetInt32("BackgroundsPage") ?? 0;
38 var backgroundParagraphs = backgroundPageId != 0 ? Dynamicweb.Content.Services.Paragraphs?.GetParagraphsByPageId(backgroundPageId) ?? null : null;
39
40
41 //CUSTOM CODE
42 }
43
44 @if (themesParagraphs != null || brandingPage != null)
45 {
46 string swiftVersion = ReadFile("/Files/Templates/Designs/Swift/swift_version.txt");
47 bool renderAsResponsive = Model.Area.Item.GetString("DeviceRendering", "responsive").Equals("responsive", StringComparison.OrdinalIgnoreCase);
48 bool renderMobile = Pageview.Device == Dynamicweb.Frontend.Devices.DeviceType.Mobile || Pageview.Device == Dynamicweb.Frontend.Devices.DeviceType.Tablet;
49 string responsiveClassDesktop = string.Empty;
50 string responsiveClassMobile = string.Empty;
51 if (renderAsResponsive)
52 {
53 responsiveClassDesktop = " d-none d-xl-block";
54 responsiveClassMobile = " d-block d-xl-none";
55 }
56
57 var headerDesktopLink = Model.Area.Item?.GetLink("HeaderDesktop") ?? null;
58 var headerMobileLink = Model.Area.Item?.GetLink("HeaderMobile") ?? null;
59
60 var footerDesktopLink = Model.Area.Item?.GetLink("FooterDesktop") ?? null;
61 var footerMobileLink = Model.Area.Item?.GetLink("FooterMobile") ?? null;
62
63 var disableWideBreakpoints = Model.Area?.Item?.GetRawValueString("DisableWideBreakpoints", "default");
64
65 string customHeaderInclude = !string.IsNullOrEmpty(Model.Area.Item.GetRawValueString("CustomHeaderInclude")) ? Model.Area.Item.GetFile("CustomHeaderInclude").Name : string.Empty;
66
67 var themesParagraphLastChanged = themesParagraphs.OrderByDescending(p => p.Audit.LastModifiedAt).FirstOrDefault();
68 var cssLastModified = brandingPage.Audit.LastModifiedAt > themesParagraphLastChanged.Audit.LastModifiedAt ? brandingPage.Audit.LastModifiedAt : themesParagraphLastChanged.Audit.LastModifiedAt;
69
70 var cssThemeAndBrandingStyleFileInfo = new System.IO.FileInfo(Dynamicweb.Core.SystemInformation.MapPath($"/Files/Templates/Designs/Swift/_parsed/Swift_css/Swift_styles_{Model.Area.ID}.min.css"));
71 //CUSTOM CODE
72 //Create a collection with all last modified dates
73 List<DateTime> filesAudit = new List<DateTime>();
74 if(brandingPage != null)
75 {
76 filesAudit.Add(brandingPage.Audit.LastModifiedAt);
77 }
78 if(backgroundParagraphs != null)
79 {
80 var backgroundParagraphLastChanged = backgroundParagraphs.OrderByDescending(p => p.Audit.LastModifiedAt).FirstOrDefault();
81 filesAudit.Add(backgroundParagraphLastChanged.Audit.LastModifiedAt);
82 }
83
84 cssLastModified = filesAudit.Max();
85
86
87 if (backgroundPageId != 0)
88 {
89 var backgroundFileInfo = new System.IO.FileInfo(Dynamicweb.Core.SystemInformation.MapPath($"/Files/Templates/Designs/Swift/_parsed/Swift_css/Swift_backgrounds_styles_{Model.Area.ID}.css"));
90
91 if(backgroundParagraphs.Any())
92 {
93 var backgroundParagraphLastChanged = backgroundParagraphs.OrderByDescending(p => p.Audit.LastModifiedAt).FirstOrDefault();
94 if (!cssThemeAndBrandingStyleFileInfo.Exists || cssThemeAndBrandingStyleFileInfo.LastWriteTime < backgroundParagraphLastChanged.Audit.LastModifiedAt)
95 {
96 var backgroundPageview = Dynamicweb.Frontend.PageView.GetPageviewByPageID(backgroundPageId);
97 backgroundPageview.Redirect = false;
98 backgroundPageview.Output();
99 }
100 }
101 }
102
103 //CUSTOM CODE
104
105 if (cssPageId != 0)
106 {
107 var cssFileInfo = new System.IO.FileInfo(Dynamicweb.Core.SystemInformation.MapPath($"/Files/Templates/Designs/Swift/_parsed/Swift_css/Swift_css_styles_{Model.Area.ID}.css"));
108
109 if(cssParagraphs.Any())
110 {
111 var cssParagraphLastChanged = cssParagraphs.OrderByDescending(p => p.Audit.LastModifiedAt).FirstOrDefault();
112 if (!cssThemeAndBrandingStyleFileInfo.Exists || cssThemeAndBrandingStyleFileInfo.LastWriteTime < cssParagraphLastChanged.Audit.LastModifiedAt)
113 {
114 var cssPageview = Dynamicweb.Frontend.PageView.GetPageviewByPageID(cssPageId);
115 cssPageview.Redirect = false;
116 cssPageview.Output();
117 }
118 }
119 }
120
121
122
123 if (!cssThemeAndBrandingStyleFileInfo.Exists || cssThemeAndBrandingStyleFileInfo.LastWriteTime < brandingPage.Audit.LastModifiedAt)
124 {
125 //Branding page has been saved or the file is missing. Rewrite the file to disc.
126 if (brandingPageId > 0)
127 {
128 var brandingPageview = Dynamicweb.Frontend.PageView.GetPageviewByPageID(brandingPageId);
129 brandingPageview.Redirect = false;
130 brandingPageview.Output();
131 }
132 }
133
134 if (!cssThemeAndBrandingStyleFileInfo.Exists || cssThemeAndBrandingStyleFileInfo.LastWriteTime < themesParagraphLastChanged.Audit.LastModifiedAt)
135 {
136 //Branding page has been saved or the file is missing. Rewrite the file to disc.
137 if (themePageId > 0)
138 {
139 var themePageview = Dynamicweb.Frontend.PageView.GetPageviewByPageID(themePageId);
140 themePageview.Redirect = false;
141 themePageview.Output();
142 }
143 }
144
145 // Schema.org details for PDP
146 bool isProductDetailsPage = Dynamicweb.Context.Current.Request.QueryString.AllKeys.Contains("ProductID");
147 bool isArticlePage = Model.ItemType == "Swift_Article";
148 string schemaOrgType = string.Empty;
149
150 if (isProductDetailsPage)
151 {
152 schemaOrgType = "itemscope=\"\" itemtype=\"https://schema.org/Product\"";
153 }
154
155 if (isArticlePage)
156 {
157 schemaOrgType = "itemscope=\"\" itemtype=\"https://schema.org/Article\"";
158 }
159
160
161 var cssStyleFileInfo = new System.IO.FileInfo(Dynamicweb.Core.SystemInformation.MapPath("/Files/Templates/Designs/Swift/Assets/css/styles.css"));
162 var jsFileInfo = new System.IO.FileInfo(Dynamicweb.Core.SystemInformation.MapPath("/Files/Templates/Designs/Swift/Assets/js/scripts.js"));
163 //CUSTOM CODE//
164 var customJsFileInfo = new System.IO.FileInfo(Dynamicweb.Core.SystemInformation.MapPath("Files/Templates/Designs/Swift/Assets/js/custom-scripts.js"));
165 //CUSTOM CODE//
166 string masterTheme = !string.IsNullOrWhiteSpace(Model.Area.Item.GetRawValueString("Theme")) ? " theme " + Model.Area.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : "";
167
168 string favicon = Model.Area.Item.GetRawValueString("Favicon", "/Files/Templates/Designs/Swift/Assets/Images/favicon.png");
169 string appleTouchIcon = Model.Area.Item.GetRawValueString("AppleTouchIcon", "/Files/Templates/Designs/Swift/Assets/Images/apple-touch-icon.png");
170
171 string headerCssClass = "sticky-top";
172 bool movePageBehind = false;
173
174 if (Model.PropertyItem != null)
175 {
176 headerCssClass = Model.PropertyItem.GetRawValueString("MoveThisPageBehindTheHeader", "sticky-top");
177 movePageBehind = headerCssClass == "fixed-top" && !Pageview.IsVisualEditorMode ? true : false;
178 }
179
180 headerCssClass = headerCssClass == "" ? "sticky-top" : headerCssClass;
181 headerCssClass = Pageview.IsVisualEditorMode ? "" : headerCssClass;
182
183 string googleTagManagerID = Model.Area.Item.GetString("GoogleTagManagerID");
184 string googleAnalyticsMeasurementID = Model.Area.Item.GetString("GoogleAnalyticsMeasurementID");
185
186 bool allowTracking = true;
187 if (CookieManager.IsCookieManagementActive)
188 {
189 var cookieOptInLevel = CookieManager.GetCookieOptInLevel();
190 allowTracking = cookieOptInLevel == CookieOptInLevel.All || (cookieOptInLevel == CookieOptInLevel.Functional && CookieManager.GetCookieOptInCategories().Contains("Statistical"));
191 }
192
193 Dynamicweb.Context.Current.Response.AddHeader("link", $"</Files/Templates/Designs/Swift/Assets/css/styles.css?{cssStyleFileInfo.LastWriteTime.Ticks}>; rel=preload; as=style;");
194 Dynamicweb.Context.Current.Response.AddHeader("link", $"</Files/Templates/Designs/Swift/_parsed/Swift_css/Swift_styles_{Model.Area.ID}.min.css?{cssLastModified.Ticks}>; rel=preload; as=style;");
195 Dynamicweb.Context.Current.Response.AddHeader("link", $"</Files/Templates/Designs/Swift/Assets/js/scripts.js?{jsFileInfo.LastWriteTime.Ticks}>; rel=preload; as=script;");
196 //CUSTOM CODE
197 Dynamicweb.Context.Current.Response.AddHeader("link", $"</Files/Templates/Designs/Swift/Assets/js/custom-scripts.js?{customJsFileInfo.LastWriteTime.Ticks}>; rel=preload; as=script;");
198 //CUSTOM CODE
199 SetMetaTags();
200
201 List<Dynamicweb.Content.Page> languages = new List<Dynamicweb.Content.Page>();
202
203 var masterPage = Pageview.Area.IsMaster ? Pageview.Page : Pageview.Page.MasterPage;
204 languages.Add(masterPage);
205 if (masterPage?.Languages != null)
206 {
207 foreach (var language in masterPage.Languages)
208 {
209 languages.Add(language);
210 }
211 }
212
213 Uri url = Dynamicweb.Context.Current.Request.Url;
214 string hostName = url.Host;
215
216 <!doctype html>
217 <html lang="@Pageview.Area.CultureInfo.TwoLetterISOLanguageName">
218 <head>
219 <!-- @swiftVersion -->
220 @* Required meta tags *@
221 <meta charset="utf-8">
222 <meta name="viewport" content="height=device-height, width=device-width, initial-scale=1.0">
223 <link rel="shortcut icon" href="@favicon">
224 <link rel="apple-touch-icon" href="@appleTouchIcon">
225
226 @Model.MetaTags
227
228 @{
229 var alreadyWrittenTwoletterIsos = new List<string>();
230 @* Languages meta data *@
231 foreach (var language in languages)
232 {
233 hostName = url.Host;
234 if (language?.Area != null)
235 {
236 if (language.Area?.MasterArea != null && !string.IsNullOrEmpty(language.Area.MasterArea.DomainLock))
237 {
238 hostName = language.Area.MasterArea.DomainLock; //dk.domain.com or dk-domain.dk
239 }
240 if (language != null && language.Published && language.Area.Active && language.Area.Published)
241 {
242 if (!string.IsNullOrEmpty(language.Area.DomainLock))
243 {
244 hostName = language.Area.DomainLock; //dk.domain.com or dk-domain.dk
245 }
246 string querystring = $"Default.aspx?ID={language.ID}";
247 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["GroupID"]))
248 {
249 querystring += $"&GroupID={Dynamicweb.Context.Current.Request.QueryString["GroupID"]}";
250 }
251 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["ProductID"]))
252 {
253 querystring += $"&ProductID={Dynamicweb.Context.Current.Request.QueryString["ProductID"]}";
254 }
255 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["VariantID"]))
256 {
257 querystring += $"&VariantID={Dynamicweb.Context.Current.Request.QueryString["VariantID"]}";
258 }
259
260 string friendlyUrl = Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl(querystring);
261 if (language.Area.RedirectFirstPage && language.ParentPageId == 0 && language.Sort == 1)
262 {
263 friendlyUrl = "/";
264 }
265 string href = $"{url.Scheme}://{hostName}{friendlyUrl}";
266
267
268 <link rel="alternate" hreflang="@language.Area.CultureInfo.Name.ToLower()" href="@href">
269 if (!alreadyWrittenTwoletterIsos.Contains(language.Area.CultureInfo.TwoLetterISOLanguageName))
270 {
271 <link rel="alternate" hreflang="@language.Area.CultureInfo.TwoLetterISOLanguageName.ToLower()" href="@href">
272 }
273 }
274 }
275 }
276 }
277
278 <title>@Model.Title</title>
279 @* Bootstrap + Swift stylesheet *@
280 <link href="/Files/Templates/Designs/Swift/Assets/css/styles.css?@cssStyleFileInfo.LastWriteTime.Ticks" rel="stylesheet" media="all" type="text/css">
281
282 @if (disableWideBreakpoints != "disableBoth")
283 {
284 <style>
285 @@media ( min-width: 1600px ) {
286 .container-xxl,
287 .container-xl,
288 .container-lg,
289 .container-md,
290 .container-sm,
291 .container {
292 max-width: 1520px;
293 }
294 }
295 </style>
296
297
298
299 if (disableWideBreakpoints != "disableUltraWideOnly")
300 {
301 <style>
302 @@media ( min-width: 1920px ) {
303 .container-xxl,
304 .container-xl,
305 .container-lg,
306 .container-md,
307 .container-sm,
308 .container {
309 max-width: 1820px;
310 }
311 }
312 </style>
313 }
314 }
315
316 @* Branding and Themes min stylesheet *@
317 <link href="/Files/Templates/Designs/Swift/_parsed/Swift_css/Swift_styles_@(Model.Area.ID).min.css?@cssLastModified.Ticks" rel="stylesheet" media="all" type="text/css" data-last-modified-content="@cssLastModified">
318 <script src="/Files/Templates/Designs/Swift/Assets/js/scripts.js?@jsFileInfo.LastWriteTime.Ticks" defer></script>
319 @*CUSTOM CODE*@
320 <script src="/Files/Templates/Designs/Swift/Assets/js/custom-scripts.js?@customJsFileInfo.LastWriteTime.Ticks" defer></script>
321 @*CUSTOM CODE*@
322 <script type="module">
323 swift.Scroll.hideHeadersOnScroll();
324 swift.Scroll.handleAlternativeTheme();
325
326 window.addEventListener('load', () => {
327 const aosColumns = document.querySelectorAll('[data-aos]');
328 if (aosColumns.length > 0) {
329 swift.AssetLoader.Load('/Files/Templates/Designs/Swift/Assets/js/aos.js?@jsFileInfo.LastWriteTime.Ticks', 'js');
330 document.addEventListener('load.swift.assetloader', function () {
331 AOS.init({ duration: 400, delay: 100, easing: 'ease-in-out', mirror: false, disable: window.matchMedia('(prefers-reduced-motion: reduce)') });
332 });
333 }
334 })
335 </script>
336
337 @* Google tag manager *@
338 @if (!string.IsNullOrWhiteSpace(googleTagManagerID) && allowTracking)
339 {
340 <script>
341 (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
342 new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
343 j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
344 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
345 })(window, document, 'script', 'dataLayer', '@(googleTagManagerID)');
346
347 function gtag() { dataLayer.push(arguments); }
348 </script>
349 }
350
351 @if (!string.IsNullOrWhiteSpace(googleAnalyticsMeasurementID) && allowTracking)
352 {
353 var GoogleAnalyticsDebugMode = "";
354
355 if (Model.Area.Item.GetBoolean("EnableGoogleAnalyticsDebugMode"))
356 {
357 GoogleAnalyticsDebugMode = ", {'debug_mode': true}";
358 }
359
360 <script async src="https://www.googletagmanager.com/gtag/js?id=@googleAnalyticsMeasurementID"></script>
361 <script>
362 window.dataLayer = window.dataLayer || [];
363 function gtag() { dataLayer.push(arguments); }
364 gtag('js', new Date());
365 gtag('config', '@googleAnalyticsMeasurementID'@GoogleAnalyticsDebugMode);
366 </script>
367 }
368
369 @if (!string.IsNullOrWhiteSpace(customHeaderInclude))
370 {
371 @RenderPartial($"Components/Custom/{customHeaderInclude}")
372 }
373 </head>
374 <body class="brand @(masterTheme)" id="page@(Model.ID)">
375
376 @* Google tag manager *@
377 @if (!string.IsNullOrWhiteSpace(googleTagManagerID) && allowTracking)
378 {
379 <noscript>
380 <iframe src="https://www.googletagmanager.com/ns.html?id=@(googleTagManagerID)"
381 height="0" width="0" style="display:none;visibility:hidden"></iframe>
382 </noscript>
383 }
384
385 @if (renderAsResponsive || !renderMobile)
386 {
387 <header class="page-header @headerCssClass top-0@(responsiveClassDesktop)" id="page-header-desktop">
388 @if (headerDesktopLink != null)
389 {
390 @RenderGrid(headerDesktopLink.PageId)
391 }
392 </header>
393 }
394
395 @if ((renderAsResponsive || renderMobile))
396 {
397 <header class="page-header @headerCssClass top-0@(responsiveClassMobile)" id="page-header-mobile">
398 @if (headerMobileLink != null)
399 {
400 @RenderGrid(headerMobileLink.PageId)
401 }
402 </header>
403 }
404
405 <div data-intersect></div>
406
407 <main id="content" @(schemaOrgType)>
408 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
409 @using System
410 @using Dynamicweb.Ecommerce.ProductCatalog
411 @using Dynamicweb.Frontend.Navigation
412
413
414 @{
415 string productIdFromUrl = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("ProductID")) ? Dynamicweb.Context.Current.Request.QueryString.Get("ProductID") : string.Empty;
416 bool isProductDetail = !string.IsNullOrEmpty(productIdFromUrl) && Pageview.Page.NavigationTag.ToLower() == "shop";
417
418 bool isArticlePagePage = Model.ItemType == "Swift_Article";
419 bool isArticleListPage = Model.ItemType == "Swift_ArticleListPage";
420 string schemaOrgProp = string.Empty;
421 if(isArticlePagePage)
422 {
423 schemaOrgProp = "itemprop=\"articleBody\"";
424 }
425
426 string theme = "";
427 string gridContent = "";
428
429 if (Model.PropertyItem != null)
430 {
431 theme = !string.IsNullOrWhiteSpace(Model.PropertyItem.GetRawValueString("Theme")) ? "theme " + Model.PropertyItem.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : "";
432 }
433
434 if (Model.Item != null || Pageview.IsVisualEditorMode)
435 {
436 if (!isProductDetail)
437 {
438 gridContent = Model.Grid("Grid", "Grid", "default:true;sort:1", "Page");
439 }
440 else
441 {
442 var productObject = Dynamicweb.Ecommerce.Services.Products.GetProductById(productIdFromUrl, "", Pageview.Area.EcomLanguageId);
443 var detailPage = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(productObject.PrimaryGroupId)?.Meta.PrimaryPage ?? string.Empty;
444 var detailPageId = detailPage != string.Empty ? Convert.ToInt16(detailPage.Substring(detailPage.LastIndexOf('=') + 1)) : GetPageIdByNavigationTag("ProductDetailPage");
445
446 @RenderGrid(detailPageId)
447 }
448 }
449
450 //Navigation settings
451 string navAlignment = "justify-content-start text-start";
452 string navOrientation = "flex-column";
453 string layout = "lines";
454 string linkFontWeight = "fw-normal";
455 string navTitleFontWeight = "fw-bold";
456 string NavTitleCasing = "text-capitalize";
457 string linkCasing = "";
458 string linkFontSize = "fs-6";
459 string navTitleFontSize = "h6";
460 string navigationRoot = "112";
461 bool showOnlyFirstLevel = true;
462 string contentPadding = " px-3 py-3";
463
464 var navigationSettings = new NavigationSettings();
465 navigationSettings.StartLevel = 1;
466 navigationSettings.StopLevel = 10;
467 navigationSettings.ExpandMode = ExpandMode.All;
468
469 navigationSettings.Parameters.Add("Layout", layout);
470 navigationSettings.Parameters.Add("LinkFontSize", linkFontSize);
471 navigationSettings.Parameters.Add("NavOrientation", navOrientation);
472 navigationSettings.Parameters.Add("LinkFontWeight", linkFontWeight);
473 navigationSettings.Parameters.Add("NavAlignment", navAlignment);
474 navigationSettings.Parameters.Add("LinkCasing", linkCasing);
475 navigationSettings.Parameters.Add("Theme", theme);
476 navigationSettings.Parameters.Add("ShowOnlyFirstNavLevel", showOnlyFirstLevel);
477
478 if (!string.IsNullOrEmpty(navigationRoot))
479 {
480 int rootPageId = Convert.ToInt32(navigationRoot);
481 navigationSettings.RootPageId = rootPageId;
482
483 var page = Dynamicweb.Content.Services.Pages.GetPage(rootPageId);
484 if (page != null && !string.IsNullOrEmpty(page.NavigationTag))
485 {
486 navigationSettings.Parameters.Add("menu-id", page.NavigationTag.ToLower());
487 }
488
489 }
490 else
491 {
492 navigationSettings.Parameters.Add("menu-id", "root");
493 }
494
495
496 bool doNotRenderPage = false;
497
498 //Check if we are on the poduct detail page, and if there is data to render
499 ProductViewModel product = new ProductViewModel();
500 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails"))
501 {
502 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"];
503 if (string.IsNullOrEmpty(product.Id)) {
504 doNotRenderPage = true;
505 }
506 }
507
508 //Render the page
509 if (!doNotRenderPage) {
510 string itemIdentifier = Model?.Item?.SystemName != null ? "item_" + Model.Item.SystemName.ToLower() : "item_Swift_Page";
511 string sectionClass = "py-3 py-lg-3";
512 string containerClass = "container-xl";
513 string mobileColumnSize = "1";
514 string rowClass = "";
515
516 <div class="@theme @itemIdentifier" @schemaOrgProp>
517 <div class="@(sectionClass)@(theme)">
518 <div class="@containerClass">
519 <div class="grid grid-@(mobileColumnSize) grid-lg-4@(rowClass)">
520 <div class="g-col order-first order-lg-0" data-col-size="3" style="--bs-columns:12">
521 <div class="h-100@(theme) item_@Model.Item.SystemName.ToLower()">
522 @if (!string.IsNullOrEmpty(Model.Item.GetString("Title")) && !Model.Item.GetBoolean("HideTitle"))
523 {
524 <h3 class="@contentPadding">@Model.Item.GetString("Title")</h3>
525 }
526
527 @Navigation.RenderNavigation("Navigation/Vertical.cshtml", navigationSettings)
528 </div>
529 </div>
530 <div class="g-col g-col-lg-3" data-col-size="9" style="--bs-columns:12">
531 @gridContent
532 </div>
533 </div>
534 </div>
535 </div>
536
537 </div>
538
539 } else {
540 <div class="container">
541 <div class="alert alert-info" role="alert">@Translate("Sorry. There is nothing to view here")</div>
542 </div>
543 }
544
545 if (!Model.IsCurrentUserAllowed)
546 {
547 int signInPage = GetPageIdByNavigationTag("SignInPage");
548 int dashboardPage = GetPageIdByNavigationTag("MyAccountDashboardPage");
549
550 if (!Pageview.IsVisualEditorMode)
551 {
552 if (signInPage != 0)
553 {
554 if (signInPage != Model.ID) {
555 Dynamicweb.Context.Current.Response.Redirect("/Default.aspx?ID=" + signInPage);
556 } else {
557 if (dashboardPage != 0) {
558 Dynamicweb.Context.Current.Response.Redirect("/Default.aspx?ID=" + dashboardPage);
559 } else {
560 Dynamicweb.Context.Current.Response.Redirect("/");
561 }
562 }
563 }
564 else
565 {
566 <div class="alert alert-dark m-0" role="alert">
567 <span>@Translate("You do not have access to this page") @Pageview.Page.ID</span>
568 </div>
569 }
570 }
571 else
572 {
573 <div class="alert alert-dark m-0" role="alert">
574 <span>@Translate("To work on this page, you must be signed in, in the frontend")</span>
575 </div>
576 }
577 }
578 }
579
580 </main>
581
582 @if (renderAsResponsive || !renderMobile)
583 {
584 <footer class="page-footer@(responsiveClassDesktop)" id="page-footer-desktop">
585 @if (footerDesktopLink != null)
586 {
587 @RenderGrid(footerDesktopLink.PageId)
588 }
589 </footer>
590 }
591
592 @if (renderAsResponsive || renderMobile)
593 {
594 <footer class="page-footer@(responsiveClassMobile)" id="page-footer-mobile">
595 @if (footerMobileLink != null)
596 {
597 @RenderGrid(footerMobileLink.PageId)
598 }
599 </footer>
600 }
601
602 @* Render any offcanvas menu here *@
603 @RenderSnippet("offcanvas")
604
605 @{
606 bool isErpConnectionDown = !Dynamicweb.Core.Converter.ToBoolean(Context.Current.Items["IsWebServiceConnectionAvailable"]);
607 }
608
609 @* Language selector modal *@
610 <div class="modal fade" id="PreferencesModal" tabindex="-1" aria-hidden="true">
611 <div class="modal-dialog modal-dialog-centered modal-sm" id="PreferencesModalContent">
612 @* The content here comes from an external request *@
613 </div>
614 </div>
615
616 @* Favorite toast *@
617 <div aria-live="polite" aria-atomic="true">
618 <div class="position-fixed bottom-0 end-0 p-3" style="z-index: 11">
619 <div id="favoriteNotificationToast" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
620 <div class="toast-header">
621 <strong class="me-auto">@Translate("Favorite list updated")</strong>
622 <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
623 </div>
624 <div class="toast-body d-flex gap-3">
625 <div id="favoriteNotificationToast_Image"></div>
626 <div id="favoriteNotificationToast_Text"></div>
627 </div>
628 </div>
629 </div>
630 </div>
631
632 @* Modal for dynamic content *@
633 <div class="modal fade js-product" id="DynamicModal" tabindex="-1" aria-hidden="true">
634 <div class="modal-dialog modal-dialog-centered modal-md">
635 <div class="modal-content theme light" id="DynamicModalContent">
636 @* The content here comes from an external request *@
637 </div>
638 </div>
639 </div>
640
641 @* Offcanvas for dynamic content *@
642 <div class="offcanvas offcanvas-end theme light" tabindex="-1" id="DynamicOffcanvas" style="width: 30rem">
643 @* The content here comes from an external request *@
644 </div>
645
646 @if (Model.Area.Item.GetBoolean("ShowErpDownMessage") && !Dynamicweb.Core.Converter.ToBoolean(Context.Current.Items["IsWebServiceConnectionAvailable"]))
647 {
648 string erpDownMessageTheme = !string.IsNullOrWhiteSpace(Model.Area.Item.GetRawValueString("ErpDownMessageTheme")) ? " theme " + Model.Area.Item.GetRawValueString("ErpDownMessageTheme").Replace(" ", "").Trim().ToLower() : "theme light";
649
650 <div class="position-fixed bottom-0 end-0 p-3" style="z-index: 1040">
651 <div class="toast fade show border-0 @erpDownMessageTheme" role="alert" aria-live="assertive" aria-atomic="true">
652 <div class="toast-header">
653 <strong class="me-auto">@Translate("Connection down")</strong>
654 <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
655 </div>
656 <div class="toast-body">
657 @Translate("We are experiencing some connectivity issues. Not all features may be available to you.")
658 </div>
659 </div>
660 </div>
661 }
662 @* START CUSTOM CODE *@
663 @RenderFaqModal()
664 @RenderCustomFontStyleTag()
665 @* END CUSTOM CODE *@
666
667 </body>
668 </html>
669 } else if (Pageview.IsVisualEditorMode) {
670 <head>
671 <title>@Model.Title</title>
672 @* Bootstrap + Swift stylesheet *@
673 <link href="/Files/Templates/Designs/Swift/Assets/css/styles.css" rel="stylesheet" media="all" type="text/css">
674 </head>
675 <body class="p-3">
676 <div class="alert alert-danger" role="alert">
677 @Translate("Basic Swift setup is needed!")
678 </div>
679
680 @if (brandingPage == null) {
681 <div class="alert alert-warning" role="alert">
682 @Translate("Please add a Branding page and reference it in website settings")
683 </div>
684 }
685
686 @if (themesParagraphs == null) {
687 <div class="alert alert-warning" role="alert">
688 @Translate("Please add a Themes collection page and reference it in website settings")
689 </div>
690 }
691 </body>
692 }
693
694
695 @functions {
696 void SetMetaTags()
697 {
698 //Verification Tokens
699 string siteVerificationGoogle = Model.Area.Item.GetString("Google_Site_Verification") != null ? Model.Area.Item.GetString("Google_Site_Verification") : "";
700
701 //Generic Site Values
702 string openGraphFacebookAppID = Model.Area.Item.GetString("Fb_app_id") != null ? Model.Area.Item.GetString("Fb_app_id") : "";
703 string openGraphType = Model.Area.Item.GetString("Open_Graph_Type") != null ? Model.Area.Item.GetString("Open_Graph_Type") : "";
704 string openGraphSiteName = Model.Area.Item.GetString("Open_Graph_Site_Name") != null ? Model.Area.Item.GetString("Open_Graph_Site_Name") : "";
705
706 string twitterCardSite = Model.Area.Item.GetString("Twitter_Site") != null ? Model.Area.Item.GetString("Twitter_Site") : "";
707
708 //Page specific values
709 string openGraphSiteTitle = Model.Area.Item.GetString("Open_Graph_Title") != null ? Model.Area.Item.GetString("Open_Graph_Title") : "";
710 FileViewModel openGraphImage = Model.Area.Item.GetFile("Open_Graph_Image");
711 string openGraphImageALT = Model.Area.Item.GetString("Open_Graph_Image_ALT") != null ? Model.Area.Item.GetString("Open_Graph_Image_ALT") : "";
712 string openGraphDescription = Model.Area.Item.GetString("Open_Graph_Description") != null ? Model.Area.Item.GetString("Open_Graph_Description") : "";
713
714 string twitterCardURL = Model.Area.Item.GetString("Twitter_URL") != null ? Model.Area.Item.GetString("Twitter_URL") : "";
715 string twitterCardTitle = Model.Area.Item.GetString("Twitter_Title") != null ? Model.Area.Item.GetString("Twitter_Title") : "";
716 string twitterCardDescription = Model.Area.Item.GetString("Twitter_Description") != null ? Model.Area.Item.GetString("Twitter_Description") : "";
717 FileViewModel twitterCardImage = Model.Area.Item.GetFile("Twitter_Image");
718 string twitterCardImageALT = Model.Area.Item.GetString("Twitter_Image_ALT") != null ? Model.Area.Item.GetString("Twitter_Image_ALT") : "";
719
720 if (string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["ProductID"]))
721 {
722 if (!string.IsNullOrEmpty(Model.Description))
723 {
724 Pageview.Meta.AddTag($"<meta property=\"og:description\" content=\"{Model.Description}\">");
725 }
726 else
727 {
728 Pageview.Meta.AddTag($"<meta property=\"og:description\" content=\"{openGraphDescription}\">");
729 }
730
731 if (!string.IsNullOrEmpty(Pageview.Page.TopImage))
732 {
733 Pageview.Meta.AddTag($"<meta property=\"og:image\" content=\"{Dynamicweb.Context.Current.Request.Url.Scheme}://{Dynamicweb.Context.Current.Request.Url.Host}/Files{Pageview.Page.TopImage}\">");
734 Pageview.Meta.AddTag($"<meta property=\"og:image:secure_url\" content=\"{Dynamicweb.Context.Current.Request.Url.Scheme}://{Dynamicweb.Context.Current.Request.Url.Host}/Files{Pageview.Page.TopImage}\">");
735 }
736 else if (openGraphImage != null)
737 {
738 Pageview.Meta.AddTag($"<meta property=\"og:image\" content=\"{Dynamicweb.Context.Current.Request.Url.Scheme}://{Dynamicweb.Context.Current.Request.Url.Host}{openGraphImage.Path}\">");
739 Pageview.Meta.AddTag($"<meta property=\"og:image:secure_url\" content=\"{Dynamicweb.Context.Current.Request.Url.Scheme}://{Dynamicweb.Context.Current.Request.Url.Host}{openGraphImage.Path}\">");
740 }
741
742 if (!string.IsNullOrEmpty(openGraphImageALT))
743 {
744 Pageview.Meta.AddTag($"<meta property=\"og:image:alt\" content=\"{openGraphImageALT}\">");
745 }
746 if (!string.IsNullOrEmpty(twitterCardDescription))
747 {
748 Pageview.Meta.AddTag("twitter:description", twitterCardDescription);
749 }
750
751 if (!string.IsNullOrEmpty(Pageview.Page.TopImage))
752 {
753 Pageview.Meta.AddTag("twitter:image", $"{Dynamicweb.Context.Current.Request.Url.Scheme}://{Dynamicweb.Context.Current.Request.Url.Host}/Files{Pageview.Page.TopImage}");
754 }
755 else if (twitterCardImage != null)
756 {
757 Pageview.Meta.AddTag("twitter:image", $"{Dynamicweb.Context.Current.Request.Url.Scheme}://{Dynamicweb.Context.Current.Request.Url.Host}{openGraphImage.Path}");
758 }
759
760 if (!string.IsNullOrEmpty(twitterCardImageALT))
761 {
762 Pageview.Meta.AddTag("twitter:image:alt", twitterCardImageALT);
763 }
764 }
765
766 if (!string.IsNullOrEmpty(siteVerificationGoogle))
767 {
768 Pageview.Meta.AddTag("google-site-verification", siteVerificationGoogle);
769 }
770
771 if (!string.IsNullOrEmpty(openGraphFacebookAppID))
772 {
773 Pageview.Meta.AddTag($"<meta property=\"fb:app_id\" content=\"{openGraphFacebookAppID}\">");
774 }
775
776 if (!string.IsNullOrEmpty(openGraphType))
777 {
778 Pageview.Meta.AddTag($"<meta property=\"og:type\" content=\"{openGraphType}\">");
779 }
780
781 if (!string.IsNullOrEmpty(openGraphSiteName))
782 {
783 Pageview.Meta.AddTag($"<meta property=\"og:url\" content=\"{Dynamicweb.Context.Current.Request.Url.Scheme}://{Dynamicweb.Context.Current.Request.Url.Host}{Pageview.SearchFriendlyUrl}\">");
784 }
785
786 if (!string.IsNullOrEmpty(openGraphSiteName))
787 {
788 Pageview.Meta.AddTag($"<meta property=\"og:site_name\" content=\"{openGraphSiteName}\">");
789 }
790
791 if (!string.IsNullOrEmpty(Model.Title))
792 {
793 Pageview.Meta.AddTag($"<meta property=\"og:title\" content=\"{Model.Title}\">");
794 }
795 else
796 {
797 Pageview.Meta.AddTag($"<meta property=\"og:title\" content=\"{openGraphSiteTitle}\">");
798 }
799
800 if (!string.IsNullOrEmpty(twitterCardSite))
801 {
802 Pageview.Meta.AddTag("twitter:site", twitterCardSite);
803 }
804
805 if (!string.IsNullOrEmpty(twitterCardURL))
806 {
807 Pageview.Meta.AddTag("twitter:url", twitterCardURL);
808 }
809
810 if (!string.IsNullOrEmpty(twitterCardTitle))
811 {
812 Pageview.Meta.AddTag("twitter:title", twitterCardTitle);
813 }
814 }
815 }
816
817 @* START CUSTOM CODE *@
818 @helper RenderFaqModal()
819 {
820 var faqPage = Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl(GetPageIdByNavigationTag("FAQ"));
821 <div class="modal modal-xl faq-modal" aria-hidden="true" data-url="@faqPage">
822 <div class="modal-dialog">
823 <div class="modal-content">
824 <div class="modal-header">
825 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
826 </div>
827 <div class="modal-body p-0"></div>
828 </div>
829 </div>
830 </div>
831 }
832 @helper RenderCustomFontStyleTag()
833 {
834 <style>
835 @@font-face {
836 font-family: 'Arsilon';
837 font-style: normal;
838 font-weight: 400;
839 font-display: swap;
840 src: url(/Files/Templates/Designs/Swift/Assets/fonts/Arsilon.woff2) format('woff2');
841 }
842
843
844 span.special {
845 font-family:'Arsilon';
846 font-weight:400;
847 font-style:normal;
848 line-height:1.5;
849 font-size:72px;
850 }
851 </style>
852 }
853 @* END CUSTOM CODE *@