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.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.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_b9c3902d969a4ea2a5aacd25090212c0.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 @* Render any offcanvas menu here *@
496 @RenderSnippet("offcanvas")
497
498 @{
499 bool isErpConnectionDown = !Dynamicweb.Core.Converter.ToBoolean(Context.Current.Items["IsWebServiceConnectionAvailable"]);
500 }
501
502 @* Language selector modal *@
503 <div class="modal fade" id="PreferencesModal" tabindex="-1" aria-hidden="true">
504 <div class="modal-dialog modal-dialog-centered modal-sm" id="PreferencesModalContent">
505 @* The content here comes from an external request *@
506 </div>
507 </div>
508
509 @* Favorite toast *@
510 <div aria-live="polite" aria-atomic="true">
511 <div class="position-fixed bottom-0 end-0 p-3" style="z-index: 11">
512 <div id="favoriteNotificationToast" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
513 <div class="toast-header">
514 <strong class="me-auto">@Translate("Favorite list updated")</strong>
515 <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
516 </div>
517 <div class="toast-body d-flex gap-3">
518 <div id="favoriteNotificationToast_Image"></div>
519 <div id="favoriteNotificationToast_Text"></div>
520 </div>
521 </div>
522 </div>
523 </div>
524
525 @* Modal for dynamic content *@
526 <div class="modal fade js-product" id="DynamicModal" tabindex="-1" aria-hidden="true">
527 <div class="modal-dialog modal-dialog-centered modal-md">
528 <div class="modal-content theme light" id="DynamicModalContent">
529 @* The content here comes from an external request *@
530 </div>
531 </div>
532 </div>
533
534 @* Offcanvas for dynamic content *@
535 <div class="offcanvas offcanvas-end theme light" tabindex="-1" id="DynamicOffcanvas" style="width: 30rem">
536 @* The content here comes from an external request *@
537 </div>
538
539 @if (Model.Area.Item.GetBoolean("ShowErpDownMessage") && !Dynamicweb.Core.Converter.ToBoolean(Context.Current.Items["IsWebServiceConnectionAvailable"]))
540 {
541 string erpDownMessageTheme = !string.IsNullOrWhiteSpace(Model.Area.Item.GetRawValueString("ErpDownMessageTheme")) ? " theme " + Model.Area.Item.GetRawValueString("ErpDownMessageTheme").Replace(" ", "").Trim().ToLower() : "theme light";
542
543 <div class="position-fixed bottom-0 end-0 p-3" style="z-index: 1040">
544 <div class="toast fade show border-0 @erpDownMessageTheme" role="alert" aria-live="assertive" aria-atomic="true">
545 <div class="toast-header">
546 <strong class="me-auto">@Translate("Connection down")</strong>
547 <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
548 </div>
549 <div class="toast-body">
550 @Translate("We are experiencing some connectivity issues. Not all features may be available to you.")
551 </div>
552 </div>
553 </div>
554 }
555 </body>
556 </html>
557 } else if (Pageview.IsVisualEditorMode) {
558 <head>
559 <title>@Model.Title</title>
560 @* Bootstrap + Swift stylesheet *@
561 <link href="/Files/Templates/Designs/Swift/Assets/css/styles.css" rel="stylesheet" media="all" type="text/css">
562 </head>
563 <body class="p-3">
564 <div class="alert alert-danger" role="alert">
565 @Translate("Basic Swift setup is needed!")
566 </div>
567
568 @if (brandingPage == null) {
569 <div class="alert alert-warning" role="alert">
570 @Translate("Please add a Branding page and reference it in website settings")
571 </div>
572 }
573
574 @if (themesParagraphs == null) {
575 <div class="alert alert-warning" role="alert">
576 @Translate("Please add a Themes collection page and reference it in website settings")
577 </div>
578 }
579 </body>
580 }
581
582
583 @functions {
584 void SetMetaTags()
585 {
586 //Verification Tokens
587 string siteVerificationGoogle = Model.Area.Item.GetString("Google_Site_Verification") != null ? Model.Area.Item.GetString("Google_Site_Verification") : "";
588
589 //Generic Site Values
590 string openGraphFacebookAppID = Model.Area.Item.GetString("Fb_app_id") != null ? Model.Area.Item.GetString("Fb_app_id") : "";
591 string openGraphType = Model.Area.Item.GetString("Open_Graph_Type") != null ? Model.Area.Item.GetString("Open_Graph_Type") : "";
592 string openGraphSiteName = Model.Area.Item.GetString("Open_Graph_Site_Name") != null ? Model.Area.Item.GetString("Open_Graph_Site_Name") : "";
593
594 string twitterCardSite = Model.Area.Item.GetString("Twitter_Site") != null ? Model.Area.Item.GetString("Twitter_Site") : "";
595
596 //Page specific values
597 string openGraphSiteTitle = Model.Area.Item.GetString("Open_Graph_Title") != null ? Model.Area.Item.GetString("Open_Graph_Title") : "";
598 FileViewModel openGraphImage = Model.Area.Item.GetFile("Open_Graph_Image");
599 string openGraphImageALT = Model.Area.Item.GetString("Open_Graph_Image_ALT") != null ? Model.Area.Item.GetString("Open_Graph_Image_ALT") : "";
600 string openGraphDescription = Model.Area.Item.GetString("Open_Graph_Description") != null ? Model.Area.Item.GetString("Open_Graph_Description") : "";
601
602 string twitterCardURL = Model.Area.Item.GetString("Twitter_URL") != null ? Model.Area.Item.GetString("Twitter_URL") : "";
603 string twitterCardTitle = Model.Area.Item.GetString("Twitter_Title") != null ? Model.Area.Item.GetString("Twitter_Title") : "";
604 string twitterCardDescription = Model.Area.Item.GetString("Twitter_Description") != null ? Model.Area.Item.GetString("Twitter_Description") : "";
605 FileViewModel twitterCardImage = Model.Area.Item.GetFile("Twitter_Image");
606 string twitterCardImageALT = Model.Area.Item.GetString("Twitter_Image_ALT") != null ? Model.Area.Item.GetString("Twitter_Image_ALT") : "";
607
608 if (string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["ProductID"]))
609 {
610 if (!string.IsNullOrEmpty(Model.Description))
611 {
612 Pageview.Meta.AddTag($"<meta property=\"og:description\" content=\"{Model.Description}\">");
613 }
614 else
615 {
616 Pageview.Meta.AddTag($"<meta property=\"og:description\" content=\"{openGraphDescription}\">");
617 }
618
619 if (!string.IsNullOrEmpty(Pageview.Page.TopImage))
620 {
621 Pageview.Meta.AddTag($"<meta property=\"og:image\" content=\"{Dynamicweb.Context.Current.Request.Url.Scheme}://{Dynamicweb.Context.Current.Request.Url.Host}/Files{Pageview.Page.TopImage}\">");
622 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}\">");
623 }
624 else if (openGraphImage != null)
625 {
626 Pageview.Meta.AddTag($"<meta property=\"og:image\" content=\"{Dynamicweb.Context.Current.Request.Url.Scheme}://{Dynamicweb.Context.Current.Request.Url.Host}{openGraphImage.Path}\">");
627 Pageview.Meta.AddTag($"<meta property=\"og:image:secure_url\" content=\"{Dynamicweb.Context.Current.Request.Url.Scheme}://{Dynamicweb.Context.Current.Request.Url.Host}{openGraphImage.Path}\">");
628 }
629
630 if (!string.IsNullOrEmpty(openGraphImageALT))
631 {
632 Pageview.Meta.AddTag($"<meta property=\"og:image:alt\" content=\"{openGraphImageALT}\">");
633 }
634 if (!string.IsNullOrEmpty(twitterCardDescription))
635 {
636 Pageview.Meta.AddTag("twitter:description", twitterCardDescription);
637 }
638
639 if (!string.IsNullOrEmpty(Pageview.Page.TopImage))
640 {
641 Pageview.Meta.AddTag("twitter:image", $"{Dynamicweb.Context.Current.Request.Url.Scheme}://{Dynamicweb.Context.Current.Request.Url.Host}/Files{Pageview.Page.TopImage}");
642 }
643 else if (twitterCardImage != null)
644 {
645 Pageview.Meta.AddTag("twitter:image", $"{Dynamicweb.Context.Current.Request.Url.Scheme}://{Dynamicweb.Context.Current.Request.Url.Host}{openGraphImage.Path}");
646 }
647
648 if (!string.IsNullOrEmpty(twitterCardImageALT))
649 {
650 Pageview.Meta.AddTag("twitter:image:alt", twitterCardImageALT);
651 }
652 }
653
654 if (!string.IsNullOrEmpty(siteVerificationGoogle))
655 {
656 Pageview.Meta.AddTag("google-site-verification", siteVerificationGoogle);
657 }
658
659 if (!string.IsNullOrEmpty(openGraphFacebookAppID))
660 {
661 Pageview.Meta.AddTag($"<meta property=\"fb:app_id\" content=\"{openGraphFacebookAppID}\">");
662 }
663
664 if (!string.IsNullOrEmpty(openGraphType))
665 {
666 Pageview.Meta.AddTag($"<meta property=\"og:type\" content=\"{openGraphType}\">");
667 }
668
669 if (!string.IsNullOrEmpty(openGraphSiteName))
670 {
671 Pageview.Meta.AddTag($"<meta property=\"og:url\" content=\"{Dynamicweb.Context.Current.Request.Url.Scheme}://{Dynamicweb.Context.Current.Request.Url.Host}{Pageview.SearchFriendlyUrl}\">");
672 }
673
674 if (!string.IsNullOrEmpty(openGraphSiteName))
675 {
676 Pageview.Meta.AddTag($"<meta property=\"og:site_name\" content=\"{openGraphSiteName}\">");
677 }
678
679 if (!string.IsNullOrEmpty(Model.Title))
680 {
681 Pageview.Meta.AddTag($"<meta property=\"og:title\" content=\"{Model.Title}\">");
682 }
683 else
684 {
685 Pageview.Meta.AddTag($"<meta property=\"og:title\" content=\"{openGraphSiteTitle}\">");
686 }
687
688 if (!string.IsNullOrEmpty(twitterCardSite))
689 {
690 Pageview.Meta.AddTag("twitter:site", twitterCardSite);
691 }
692
693 if (!string.IsNullOrEmpty(twitterCardURL))
694 {
695 Pageview.Meta.AddTag("twitter:url", twitterCardURL);
696 }
697
698 if (!string.IsNullOrEmpty(twitterCardTitle))
699 {
700 Pageview.Meta.AddTag("twitter:title", twitterCardTitle);
701 }
702 }
703 }
704