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 *@