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