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