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