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