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