Error executing template "Designs/Swift/Swift_Page.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 (2): 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.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.Open()
at Dynamicweb.Data.DatabaseConnectionProvider.CreateNamedConnection(String connectionName, Boolean open)
at Dynamicweb.Data.Database.CreateDataReader(CommandBuilder commandBuilder, IDbConnection connection, IDbTransaction transaction, Int32 commandTimeout, String connectionName)
at Dynamicweb.Ecommerce.Products.ProductRepository.GetProductById(String productId, String productVariantId, String productLanguageId)
at Dynamicweb.Ecommerce.Products.Internal.ProductServiceCacheStorage.FetchMissingProducts(IEnumerable`1 keys)
at Dynamicweb.Caching.ServiceCache`2.GetCache(IEnumerable`1 keys)
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)
at CompiledRazorTemplates.Dynamic.RazorEngine_50d41fbec0fb40fcbb6f0e6f34fdf4a8.ExecuteAsync()
at RazorEngine.Templating.TemplateBase.Run(ExecuteContext context, TextWriter reader)
at RazorEngine.Templating.RazorEngineCore.RunTemplate(ICompiledTemplate template, TextWriter writer, Object model, DynamicViewBag viewBag)
at RazorEngine.Templating.RazorEngineService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
at RazorEngine.Templating.DynamicWrapperService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass23_0.<Run>b__0(TextWriter writer)
at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, Type modelType, Object model, DynamicViewBag viewBag)
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 }
88
89 if (isArticlePage)
90 {
91 schemaOrgType = "itemscope=\"\" itemtype=\"https://schema.org/Article\"";
92 }
93
94
95 var cssStyleFileInfo = new System.IO.FileInfo(Dynamicweb.Core.SystemInformation.MapPath("/Files/Templates/Designs/Swift/Assets/css/styles.css"));
96 var jsFileInfo = new System.IO.FileInfo(Dynamicweb.Core.SystemInformation.MapPath("/Files/Templates/Designs/Swift/Assets/js/scripts.js"));
97
98 string masterTheme = !string.IsNullOrWhiteSpace(Model.Area.Item.GetRawValueString("Theme")) ? " theme " + Model.Area.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : "";
99
100 string favicon = Model.Area.Item.GetRawValueString("Favicon", "/Files/Templates/Designs/Swift/Assets/Images/favicon.png");
101 string appleTouchIcon = Model.Area.Item.GetRawValueString("AppleTouchIcon", "/Files/Templates/Designs/Swift/Assets/Images/apple-touch-icon.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="@appleTouchIcon">
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"></script>
250 <script type="module">
251 swift.Scroll.hideHeadersOnScroll();
252 swift.Scroll.handleAlternativeTheme();
253
254 //Only load if AOS
255 const aosColumns = document.querySelectorAll('[data-aos]');
256 if (aosColumns.length > 0) {
257 swift.AssetLoader.Load('/Files/Templates/Designs/Swift/Assets/js/aos.js?@jsFileInfo.LastWriteTime.Ticks', 'js');
258 document.addEventListener('load.swift.assetloader', function () {
259 AOS.init({ duration: 400, delay: 100, easing: 'ease-in-out', mirror: false, disable: window.matchMedia('(prefers-reduced-motion: reduce)') });
260 });
261 }
262 </script>
263
264 @* Google tag manager *@
265 @if (!string.IsNullOrWhiteSpace(googleTagManagerID) && allowTracking)
266 {
267 <script>
268 (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
269 new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
270 j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
271 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
272 })(window, document, 'script', 'dataLayer', '@(googleTagManagerID)');
273
274 function gtag() { dataLayer.push(arguments); }
275 </script>
276 }
277
278 @if (!string.IsNullOrWhiteSpace(googleAnalyticsMeasurementID) && allowTracking)
279 {
280 var GoogleAnalyticsDebugMode = "";
281
282 if (Model.Area.Item.GetBoolean("EnableGoogleAnalyticsDebugMode"))
283 {
284 GoogleAnalyticsDebugMode = ", {'debug_mode': true}";
285 }
286
287 <script async src="https://www.googletagmanager.com/gtag/js?id=@googleAnalyticsMeasurementID"></script>
288 <script>
289 window.dataLayer = window.dataLayer || [];
290 function gtag() { dataLayer.push(arguments); }
291 gtag('js', new Date());
292 gtag('config', '@googleAnalyticsMeasurementID'@GoogleAnalyticsDebugMode);
293 </script>
294 }
295
296 @if (!string.IsNullOrWhiteSpace(customHeaderInclude))
297 {
298 @RenderPartial($"Components/Custom/{customHeaderInclude}")
299 }
300 </head>
301 <body class="brand @(masterTheme)" id="page@(Model.ID)">
302
303 @* Google tag manager *@
304 @if (!string.IsNullOrWhiteSpace(googleTagManagerID) && allowTracking)
305 {
306 <noscript>
307 <iframe src="https://www.googletagmanager.com/ns.html?id=@(googleTagManagerID)"
308 height="0" width="0" style="display:none;visibility:hidden"></iframe>
309 </noscript>
310 }
311
312 @if (renderAsResponsive || !renderMobile)
313 {
314 <header class="page-header @headerCssClass top-0@(responsiveClassDesktop)" id="page-header-desktop">
315 @if (headerDesktopLink != null)
316 {
317 @RenderGrid(headerDesktopLink.PageId)
318 }
319 </header>
320 }
321
322 @if ((renderAsResponsive || renderMobile))
323 {
324 <header class="page-header @headerCssClass top-0@(responsiveClassMobile)" id="page-header-mobile">
325 @if (headerMobileLink != null)
326 {
327 @RenderGrid(headerMobileLink.PageId)
328 }
329 </header>
330 }
331
332 <div data-intersect></div>
333
334 <main id="content" @(schemaOrgType)>
335 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
336 @using System
337 @using Dynamicweb.Ecommerce.ProductCatalog
338
339
340 @{
341 string productIdFromUrl = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("ProductID")) ? Dynamicweb.Context.Current.Request.QueryString.Get("ProductID") : string.Empty;
342 bool isProductDetail = !string.IsNullOrEmpty(productIdFromUrl) && Pageview.Page.NavigationTag.ToLower() == "shop";
343
344 bool isArticlePagePage = Model.ItemType == "Swift_Article";
345 bool isArticleListPage = Model.ItemType == "Swift_ArticleListPage";
346 string schemaOrgProp = string.Empty;
347 if(isArticlePagePage)
348 {
349 schemaOrgProp = "itemprop=\"articleBody\"";
350 }
351
352 string theme = "";
353 string gridContent = "";
354
355 if (Model.PropertyItem != null)
356 {
357 theme = !string.IsNullOrWhiteSpace(Model.PropertyItem.GetRawValueString("Theme")) ? "theme " + Model.PropertyItem.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : "";
358 }
359
360 if (Model.Item != null || Pageview.IsVisualEditorMode)
361 {
362 if (!isProductDetail)
363 {
364 gridContent = Model.Grid("Grid", "Grid", "default:true;sort:1", "Page");
365 }
366 else
367 {
368 var productObject = Dynamicweb.Ecommerce.Services.Products.GetProductById(productIdFromUrl, "", Pageview.Area.EcomLanguageId);
369 var detailPage = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(productObject.PrimaryGroupId)?.Meta.PrimaryPage ?? string.Empty;
370 var detailPageId = detailPage != string.Empty ? Convert.ToInt16(detailPage.Substring(detailPage.LastIndexOf('=') + 1)) : GetPageIdByNavigationTag("ProductDetailPage");
371
372 @RenderGrid(detailPageId)
373 }
374 }
375
376 bool doNotRenderPage = false;
377
378 //Check if we are on the poduct detail page, and if there is data to render
379 ProductViewModel product = new ProductViewModel();
380 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails"))
381 {
382 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"];
383 if (string.IsNullOrEmpty(product.Id)) {
384 doNotRenderPage = true;
385 }
386 }
387
388 //Render the page
389 if (!doNotRenderPage) {
390 string itemIdentifier = Model?.Item?.SystemName != null ? "item_" + Model.Item.SystemName.ToLower() : "item_Swift_Page";
391
392 if (Pageview.IsVisualEditorMode) {
393 @Model.Placeholder("dwcontent", "content", "default:true;sort:1")
394 }
395
396 <div class="@theme @itemIdentifier" @schemaOrgProp>
397 @if (isArticleListPage)
398 {
399 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\"";
400
401 <form @hx id="ArticleFacetForm">
402 @gridContent
403 </form>
404 <script type="module" src="/Files/Templates/Designs/Swift/Assets/js/htmx.js"></script>
405 <script type="module">
406 document.addEventListener('htmx:confirm', (event) => {
407 let filters = event.detail.elt.querySelectorAll('select');
408 for (var i = 0; i < filters.length; i++) {
409 let input = filters[i];
410 if (input.name && !input.value) {
411 input.name = '';
412 }
413 }
414 });
415
416 document.addEventListener('htmx:beforeOnLoad', (event) => {
417 swift.Scroll.stopIntersectionObserver();
418 });
419
420 document.addEventListener('htmx:afterOnLoad', () => {
421 swift.Scroll.hideHeadersOnScroll();
422 swift.Scroll.handleAlternativeTheme();
423 });
424 </script>
425 }
426 else
427 {
428 @gridContent
429 }
430 </div>
431
432 } else {
433 <div class="container">
434 <div class="alert alert-info" role="alert">@Translate("Sorry. There is nothing to view here")</div>
435 </div>
436 }
437
438 if (!Model.IsCurrentUserAllowed)
439 {
440 int signInPage = GetPageIdByNavigationTag("SignInPage");
441 int dashboardPage = GetPageIdByNavigationTag("MyAccountDashboardPage");
442
443 if (!Pageview.IsVisualEditorMode)
444 {
445 if (signInPage != 0)
446 {
447 if (signInPage != Model.ID) {
448 Dynamicweb.Context.Current.Response.Redirect("/Default.aspx?ID=" + signInPage);
449 } else {
450 if (dashboardPage != 0) {
451 Dynamicweb.Context.Current.Response.Redirect("/Default.aspx?ID=" + dashboardPage);
452 } else {
453 Dynamicweb.Context.Current.Response.Redirect("/");
454 }
455 }
456 }
457 else
458 {
459 <div class="alert alert-dark m-0" role="alert">
460 <span>@Translate("You do not have access to this page")</span>
461 </div>
462 }
463 }
464 else
465 {
466 <div class="alert alert-dark m-0" role="alert">
467 <span>@Translate("To work on this page, you must be signed in, in the frontend")</span>
468 </div>
469 }
470 }
471 }
472
473 </main>
474
475 @if (renderAsResponsive || !renderMobile)
476 {
477 <footer class="page-footer@(responsiveClassDesktop)" id="page-footer-desktop">
478 @if (footerDesktopLink != null)
479 {
480 @RenderGrid(footerDesktopLink.PageId)
481 }
482 </footer>
483 }
484
485 @if (renderAsResponsive || renderMobile)
486 {
487 <footer class="page-footer@(responsiveClassMobile)" id="page-footer-mobile">
488 @if (footerMobileLink != null)
489 {
490 @RenderGrid(footerMobileLink.PageId)
491 }
492 </footer>
493 }
494
495 <script id="sleeknoteScript" type="text/javascript">
496 (function () {
497 var sleeknoteScriptTag = document.createElement("script");
498 sleeknoteScriptTag.type = "text/javascript";
499 sleeknoteScriptTag.charset = "utf-8";
500 sleeknoteScriptTag.src = ("//sleeknotecustomerscripts.sleeknote.com/31752.js");
501 var s = document.getElementById("sleeknoteScript");
502 s.parentNode.insertBefore(sleeknoteScriptTag, s);
503 })();
504 </script>
505
506
507 @* Render any offcanvas menu here *@
508 @RenderSnippet("offcanvas")
509
510 @{
511 bool isErpConnectionDown = !Dynamicweb.Core.Converter.ToBoolean(Context.Current.Items["IsWebServiceConnectionAvailable"]);
512 }
513
514 @* Language selector modal *@
515 <div class="modal fade" id="PreferencesModal" tabindex="-1" aria-hidden="true">
516 <div class="modal-dialog modal-dialog-centered modal-sm" id="PreferencesModalContent">
517 @* The content here comes from an external request *@
518 </div>
519 </div>
520
521 @* Favorite toast *@
522 <div aria-live="polite" aria-atomic="true">
523 <div class="position-fixed bottom-0 end-0 p-3" style="z-index: 11">
524 <div id="favoriteNotificationToast" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
525 <div class="toast-header">
526 <strong class="me-auto">@Translate("Favorite list updated")</strong>
527 <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
528 </div>
529 <div class="toast-body d-flex gap-3">
530 <div id="favoriteNotificationToast_Image"></div>
531 <div id="favoriteNotificationToast_Text"></div>
532 </div>
533 </div>
534 </div>
535 </div>
536
537 @* Modal for dynamic content *@
538 <div class="modal fade js-product" id="DynamicModal" tabindex="-1" aria-hidden="true">
539 <div class="modal-dialog modal-dialog-centered modal-md">
540 <div class="modal-content theme light" id="DynamicModalContent">
541 @* The content here comes from an external request *@
542 </div>
543 </div>
544 </div>
545
546 @* Offcanvas for dynamic content *@
547 <div class="offcanvas offcanvas-end theme light" tabindex="-1" id="DynamicOffcanvas" style="width: 30rem">
548 @* The content here comes from an external request *@
549 </div>
550
551 @if (Model.Area.Item.GetBoolean("ShowErpDownMessage") && !Dynamicweb.Core.Converter.ToBoolean(Context.Current.Items["IsWebServiceConnectionAvailable"]))
552 {
553 string erpDownMessageTheme = !string.IsNullOrWhiteSpace(Model.Area.Item.GetRawValueString("ErpDownMessageTheme")) ? " theme " + Model.Area.Item.GetRawValueString("ErpDownMessageTheme").Replace(" ", "").Trim().ToLower() : "theme light";
554
555 <div class="position-fixed bottom-0 end-0 p-3" style="z-index: 1040">
556 <div class="toast fade show border-0 @erpDownMessageTheme" role="alert" aria-live="assertive" aria-atomic="true">
557 <div class="toast-header">
558 <strong class="me-auto">@Translate("Connection down")</strong>
559 <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
560 </div>
561 <div class="toast-body">
562 @Translate("We are experiencing some connectivity issues. Not all features may be available to you.")
563 </div>
564 </div>
565 </div>
566 }
567 </body>
568 </html>
569 } else if (Pageview.IsVisualEditorMode) {
570 <head>
571 <title>@Model.Title</title>
572 @* Bootstrap + Swift stylesheet *@
573 <link href="/Files/Templates/Designs/Swift/Assets/css/styles.css" rel="stylesheet" media="all" type="text/css">
574 </head>
575 <body class="p-3">
576 <div class="alert alert-danger" role="alert">
577 @Translate("Basic Swift setup is needed!")
578 </div>
579
580 @if (brandingPage == null) {
581 <div class="alert alert-warning" role="alert">
582 @Translate("Please add a Branding page and reference it in website settings")
583 </div>
584 }
585
586 @if (themesParagraphs == null) {
587 <div class="alert alert-warning" role="alert">
588 @Translate("Please add a Themes collection page and reference it in website settings")
589 </div>
590 }
591 </body>
592 }
593
594
595 @functions {
596 void SetMetaTags()
597 {
598 //Verification Tokens
599 string siteVerificationGoogle = Model.Area.Item.GetString("Google_Site_Verification") != null ? Model.Area.Item.GetString("Google_Site_Verification") : "";
600
601 //Generic Site Values
602 string openGraphFacebookAppID = Model.Area.Item.GetString("Fb_app_id") != null ? Model.Area.Item.GetString("Fb_app_id") : "";
603 string openGraphType = Model.Area.Item.GetString("Open_Graph_Type") != null ? Model.Area.Item.GetString("Open_Graph_Type") : "";
604 string openGraphSiteName = Model.Area.Item.GetString("Open_Graph_Site_Name") != null ? Model.Area.Item.GetString("Open_Graph_Site_Name") : "";
605
606 string twitterCardSite = Model.Area.Item.GetString("Twitter_Site") != null ? Model.Area.Item.GetString("Twitter_Site") : "";
607
608 //Page specific values
609 string openGraphSiteTitle = Model.Area.Item.GetString("Open_Graph_Title") != null ? Model.Area.Item.GetString("Open_Graph_Title") : "";
610 FileViewModel openGraphImage = Model.Area.Item.GetFile("Open_Graph_Image");
611 string openGraphImageALT = Model.Area.Item.GetString("Open_Graph_Image_ALT") != null ? Model.Area.Item.GetString("Open_Graph_Image_ALT") : "";
612 string openGraphDescription = Model.Area.Item.GetString("Open_Graph_Description") != null ? Model.Area.Item.GetString("Open_Graph_Description") : "";
613
614 string twitterCardURL = Model.Area.Item.GetString("Twitter_URL") != null ? Model.Area.Item.GetString("Twitter_URL") : "";
615 string twitterCardTitle = Model.Area.Item.GetString("Twitter_Title") != null ? Model.Area.Item.GetString("Twitter_Title") : "";
616 string twitterCardDescription = Model.Area.Item.GetString("Twitter_Description") != null ? Model.Area.Item.GetString("Twitter_Description") : "";
617 FileViewModel twitterCardImage = Model.Area.Item.GetFile("Twitter_Image");
618 string twitterCardImageALT = Model.Area.Item.GetString("Twitter_Image_ALT") != null ? Model.Area.Item.GetString("Twitter_Image_ALT") : "";
619
620 if (string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["ProductID"]))
621 {
622 if (!string.IsNullOrEmpty(Model.Description))
623 {
624 Pageview.Meta.AddTag($"<meta property=\"og:description\" content=\"{Model.Description}\">");
625 }
626 else
627 {
628 Pageview.Meta.AddTag($"<meta property=\"og:description\" content=\"{openGraphDescription}\">");
629 }
630
631 if (!string.IsNullOrEmpty(Pageview.Page.TopImage))
632 {
633 Pageview.Meta.AddTag($"<meta property=\"og:image\" content=\"{Dynamicweb.Context.Current.Request.Url.Scheme}://{Dynamicweb.Context.Current.Request.Url.Host}/Files{Pageview.Page.TopImage}\">");
634 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}\">");
635 }
636 else if (openGraphImage != null)
637 {
638 Pageview.Meta.AddTag($"<meta property=\"og:image\" content=\"{Dynamicweb.Context.Current.Request.Url.Scheme}://{Dynamicweb.Context.Current.Request.Url.Host}{openGraphImage.Path}\">");
639 Pageview.Meta.AddTag($"<meta property=\"og:image:secure_url\" content=\"{Dynamicweb.Context.Current.Request.Url.Scheme}://{Dynamicweb.Context.Current.Request.Url.Host}{openGraphImage.Path}\">");
640 }
641
642 if (!string.IsNullOrEmpty(openGraphImageALT))
643 {
644 Pageview.Meta.AddTag($"<meta property=\"og:image:alt\" content=\"{openGraphImageALT}\">");
645 }
646 if (!string.IsNullOrEmpty(twitterCardDescription))
647 {
648 Pageview.Meta.AddTag("twitter:description", twitterCardDescription);
649 }
650
651 if (!string.IsNullOrEmpty(Pageview.Page.TopImage))
652 {
653 Pageview.Meta.AddTag("twitter:image", $"{Dynamicweb.Context.Current.Request.Url.Scheme}://{Dynamicweb.Context.Current.Request.Url.Host}/Files{Pageview.Page.TopImage}");
654 }
655 else if (twitterCardImage != null)
656 {
657 Pageview.Meta.AddTag("twitter:image", $"{Dynamicweb.Context.Current.Request.Url.Scheme}://{Dynamicweb.Context.Current.Request.Url.Host}{openGraphImage.Path}");
658 }
659
660 if (!string.IsNullOrEmpty(twitterCardImageALT))
661 {
662 Pageview.Meta.AddTag("twitter:image:alt", twitterCardImageALT);
663 }
664 }
665
666 if (!string.IsNullOrEmpty(siteVerificationGoogle))
667 {
668 Pageview.Meta.AddTag("google-site-verification", siteVerificationGoogle);
669 }
670
671 if (!string.IsNullOrEmpty(openGraphFacebookAppID))
672 {
673 Pageview.Meta.AddTag($"<meta property=\"fb:app_id\" content=\"{openGraphFacebookAppID}\">");
674 }
675
676 if (!string.IsNullOrEmpty(openGraphType))
677 {
678 Pageview.Meta.AddTag($"<meta property=\"og:type\" content=\"{openGraphType}\">");
679 }
680
681 if (!string.IsNullOrEmpty(openGraphSiteName))
682 {
683 Pageview.Meta.AddTag($"<meta property=\"og:url\" content=\"{Dynamicweb.Context.Current.Request.Url.Scheme}://{Dynamicweb.Context.Current.Request.Url.Host}{Pageview.SearchFriendlyUrl}\">");
684 }
685
686 if (!string.IsNullOrEmpty(openGraphSiteName))
687 {
688 Pageview.Meta.AddTag($"<meta property=\"og:site_name\" content=\"{openGraphSiteName}\">");
689 }
690
691 if (!string.IsNullOrEmpty(Model.Title))
692 {
693 Pageview.Meta.AddTag($"<meta property=\"og:title\" content=\"{Model.Title}\">");
694 }
695 else
696 {
697 Pageview.Meta.AddTag($"<meta property=\"og:title\" content=\"{openGraphSiteTitle}\">");
698 }
699
700 if (!string.IsNullOrEmpty(twitterCardSite))
701 {
702 Pageview.Meta.AddTag("twitter:site", twitterCardSite);
703 }
704
705 if (!string.IsNullOrEmpty(twitterCardURL))
706 {
707 Pageview.Meta.AddTag("twitter:url", twitterCardURL);
708 }
709
710 if (!string.IsNullOrEmpty(twitterCardTitle))
711 {
712 Pageview.Meta.AddTag("twitter:title", twitterCardTitle);
713 }
714 }
715 }
716