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