Error executing template "Designs/Swift/Swift_Page.cshtml"
System.Data.SqlClient.SqlException (0x80131904): A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server)
 ---> System.ComponentModel.Win32Exception (2): The system cannot find the file specified.
   at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
   at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
   at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
   at System.Data.SqlClient.SqlConnection.Open()
   at Dynamicweb.Data.DatabaseConnectionProvider.CreateConnection(Boolean open)
   at Dynamicweb.Data.Database.CreateConnection()
   at Dynamicweb.Data.Database.CreateDataReader(CommandBuilder commandBuilder, IDbConnection connection, IDbTransaction transaction, Int32 commandTimeout)
   at Dynamicweb.Ecommerce.Products.ProductRepository.GetProductById(String productId, String productVariantId, String productLanguageId)
   at Dynamicweb.Ecommerce.Products.ProductService.FetchMissingProducts(IEnumerable`1 keys)
   at Dynamicweb.Caching.ServiceCache`2.GetCache(IEnumerable`1 keys)
   at Dynamicweb.Ecommerce.Products.ProductService.GetProductById(String productId, String productVariantId, String productLanguageId, User user, Boolean showUntranslated)
   at Dynamicweb.Ecommerce.Products.ProductService.GetProductById(String productId, String productVariantId, String productLanguageId)
   at CompiledRazorTemplates.Dynamic.RazorEngine_2d350f2dff464f21b3056f7f7c858fab.ExecuteAsync()
   at RazorEngine.Templating.TemplateBase.Run(ExecuteContext context, TextWriter reader)
   at RazorEngine.Templating.RazorEngineCore.RunTemplate(ICompiledTemplate template, TextWriter writer, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.DynamicWrapperService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass23_0.<Run>b__0(TextWriter writer)
   at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
   at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, Type modelType, Object model, DynamicViewBag viewBag)
   at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template)
   at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template)
   at Dynamicweb.Rendering.Template.RenderRazorTemplate()
ClientConnectionId:00000000-0000-0000-0000-000000000000
Error Number:2,State:0,Class:20

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