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 (0x80004005): The specified network name is no longer available
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.DetailRepository.GetDefaultImage(String productId, String productVariantId, String productLanguageId, String detailType)
at Dynamicweb.Ecommerce.Products.DetailService.GetDefaultDetail(String productId, String productVariantId, String languageId, IList`1 details)
at Dynamicweb.Ecommerce.Products.ProductImageService.GetImagePath(Product product, List`1 details, Boolean ignoreNoPictureSetting, Shop shop)
at Dynamicweb.Ecommerce.Products.ProductImageService.GetImagePath(Product product)
at CompiledRazorTemplates.Dynamic.RazorEngine_7d1fca181aac4722939548360dfc71bb.SetMetaTags() in D:\dynamicweb.net\Solutions\Nextech\superhome.cloud.dynamicweb-cms.com\Files\Templates\Designs\Swift\Swift_Page.cshtml:line 1204
at CompiledRazorTemplates.Dynamic.RazorEngine_7d1fca181aac4722939548360dfc71bb.Execute() in D:\dynamicweb.net\Solutions\Nextech\superhome.cloud.dynamicweb-cms.com\Files\Templates\Designs\Swift\Swift_Page.cshtml:line 267
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:64,State:0,Class:20
1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
2 @using System
3 @using System.Web
4 @using Dynamicweb
5 @using Dynamicweb.Environment
6 @using Dynamicweb.Frontend
7 @using NextechDWAddIn.Common
8
9 @using NextechDWAddIn.Helpers
10 @using NextechDWAddIn.AWSCognito
11
12 @functions {
13 string GetCookieOptInPermission(string category)
14 {
15 bool categoryOrAllGranted = false;
16
17 if (CookieManager.IsCookieManagementActive)
18 {
19 var cookieOptInLevel = CookieManager.GetCookieOptInLevel();
20 var cookieOptInCategories = CookieManager.GetCookieOptInCategories();
21 categoryOrAllGranted = cookieOptInCategories.Contains(category) || cookieOptInLevel == CookieOptInLevel.All;
22 }
23
24 return categoryOrAllGranted ? "granted" : "denied";
25 }
26
27 bool AllowTracking()
28 {
29 bool allowTracking = true;
30 if (CookieManager.IsCookieManagementActive)
31 {
32 var cookieOptInLevel = CookieManager.GetCookieOptInLevel();
33 var cookieOptInCategories = CookieManager.GetCookieOptInCategories();
34
35 bool consentEither = (cookieOptInCategories.Contains("Statistical") || cookieOptInCategories.Contains("Marketing"));
36 bool consentFunctional = cookieOptInLevel == CookieOptInLevel.Functional;
37 bool consentAtLeastOne = cookieOptInLevel == CookieOptInLevel.All || (consentFunctional && consentEither);
38
39 allowTracking = consentAtLeastOne;
40 }
41 return allowTracking;
42 }
43 }
44
45 @{
46 var cartSummaryPageId = Dynamicweb.Content.Services.Pages.GetPageByNavigationTag(Model.Area.ID, "CartSummary")?.ID;
47 bool enableMiniCart = Model.Area.Item?.GetBoolean("EnableOffcanvasMiniCart") ?? false;
48 var offcanvasMiniCartBehaviour = Model.Area.Item?.GetRawValueString("OffcanvasMinicartBehaviour", "3") ?? "3";
49 bool miniCartEnabled = cartSummaryPageId != null && enableMiniCart;
50 var brandingPageId = Model.Area.Item?.GetInt32("BrandingPage") ?? 0;
51 var themePageId = Model.Area.Item?.GetInt32("ThemesPage") ?? 0;
52 var cssPageId = Model.Area.Item?.GetInt32("CssPage") ?? 0;
53 var brandingPage = brandingPageId != 0 ? Dynamicweb.Content.Services.Pages?.GetPage(brandingPageId) ?? null : null;
54 var themesParagraphs = themePageId != 0 ? Dynamicweb.Content.Services.Paragraphs?.GetParagraphsByPageId(themePageId) ?? null : null;
55 var cssParagraphs = cssPageId != 0 ? Dynamicweb.Content.Services.Paragraphs?.GetParagraphsByPageId(cssPageId) ?? null : null;
56 string currentLanguageTwoLetter = ExecutingContext.GetCulture(true).TwoLetterISOLanguageName;
57
58
59
60
61
62 //CS NT Autologin cookie 20251105..
63 if(Pageview.User == null)
64 {
65 var sessioncookie = CookieManager.GetCookie("DW_Extranet");
66 if (sessioncookie is object && sessioncookie != null)
67 {
68 string DWExtranetUsername = sessioncookie["DWExtranetUsername"];
69 string DWExtranetTkn = sessioncookie["DWExtranetTkn"];
70 //Logger.Instance.Log(ErrorLevel.DebugInfo, $"Swift_Master.cshtml DWExtranetUsername: {DWExtranetUsername} DWExtranetTkn: {DWExtranetTkn}");
71 if (!string.IsNullOrWhiteSpace(DWExtranetUsername) && !string.IsNullOrWhiteSpace(DWExtranetTkn))
72 {
73 var logOnHandler = new Dynamicweb.Frontend.LogOnHandler();
74 logOnHandler.LogOnWithToken(DWExtranetUsername, DWExtranetTkn);
75 if (HttpContext.Current.Request != null && HttpContext.Current.Request.RawUrl != null)
76 {
77 //Logger.Instance.Log(ErrorLevel.DebugInfo, $"Swift_Master.cshtml HttpContext.Current.Request.RawUrl: {HttpContext.Current.Request.RawUrl}");
78 HttpContext.Current.Response.Redirect(HttpContext.Current.Request.RawUrl);
79 }
80 }
81 }
82 }
83 //..CS NT Autologin cookie 20251105
84
85
86
87 //CS NT 20251121
88
89 string redirectURL_cognito = "";
90 try
91 {
92 if(Pageview == null || Pageview.User == null)
93 {
94 string authURL = HttpCookieHelper.GetHttpCookie("AWS_AuthURL");
95 if (string.IsNullOrWhiteSpace(authURL))
96 {
97 var openIdConfiguration = AWSCognito.GetOpenIdConfiguration();
98 if (openIdConfiguration != null && openIdConfiguration.authorization_endpoint != null)
99 {
100 authURL = openIdConfiguration.authorization_endpoint;
101 HttpCookieHelper.SetHttpCookie("AWS_AuthURL", authURL);
102 }
103 }
104 //Logger.Instance.Log(ErrorLevel.Error, $"AWSCognito.cs RedirectToAWSLogin() authURL: " + authURL);
105
106
107 string languagePrefix = "/english";
108 string currentLanguage = ExecutingContext.GetCulture(true).TwoLetterISOLanguageName;
109 if (currentLanguage == "el" || currentLanguage == "gr") { languagePrefix = "/greek"; }
110 string AWSCognitoCallback_redirect = languagePrefix + "/AWSCognitoCallback";
111 string baseUrl = $"{Context.Current.Request.Url.Scheme}://{Context.Current.Request.Url.Host}";
112 string redirectUri = baseUrl + AWSCognitoCallback_redirect;
113
114 //Create url then redirect to it
115 string clientID = CommonFunctions.GetCustomWebsiteSetting("AWS_Cognito_Client_ID");
116 string stateGuid = HttpCookieHelper.GetHttpCookie("AWS_StateGuid");
117 if (string.IsNullOrWhiteSpace(stateGuid))
118 {
119 stateGuid = Guid.NewGuid().ToString();
120 }
121 HttpCookieHelper.SetHttpCookie("AWS_StateGuid", stateGuid);
122 redirectURL_cognito = authURL + "?response_type=code&client_id=" + clientID;
123 redirectURL_cognito += "&redirect_uri=" + redirectUri;
124 redirectURL_cognito += "&scope=openid%20profile%20email+phone";
125 redirectURL_cognito += "&state=" + stateGuid;
126 }
127 }
128 catch (Exception ex)
129 {
130 Logger.Instance.Log(ErrorLevel.Error, $"Navigation.cshtml RedirectToAWSLogin Error: {ex.Message} StackTrace: {ex.StackTrace}");
131 }
132
133
134
135 }
136
137 @if (themesParagraphs != null || brandingPage != null)
138 {
139 string swiftVersion = ReadFile("/Files/Templates/Designs/Swift/swift_version.txt");
140 bool renderAsResponsive = Model.Area.Item.GetString("DeviceRendering", "responsive").Equals("responsive", StringComparison.OrdinalIgnoreCase);
141 bool renderMobile = Pageview.Device == Dynamicweb.Frontend.Devices.DeviceType.Mobile || Pageview.Device == Dynamicweb.Frontend.Devices.DeviceType.Tablet;
142 string responsiveClassDesktop = string.Empty;
143 string responsiveClassMobile = string.Empty;
144 if (renderAsResponsive)
145 {
146 responsiveClassDesktop = " d-none d-xl-block";
147 responsiveClassMobile = " d-block d-xl-none";
148 }
149
150 var headerDesktopLink = Model.Area.Item?.GetLink("HeaderDesktop") ?? null;
151 var headerMobileLink = Model.Area.Item?.GetLink("HeaderMobile") ?? null;
152
153 var footerDesktopLink = Model.Area.Item?.GetLink("FooterDesktop") ?? null;
154 var footerMobileLink = Model.Area.Item?.GetLink("FooterMobile") ?? null;
155
156 var disableWideBreakpoints = Model.Area?.Item?.GetRawValueString("DisableWideBreakpoints", "default");
157
158 string customHeaderInclude = !string.IsNullOrEmpty(Model.Area.Item.GetRawValueString("CustomHeaderInclude")) ? Model.Area.Item.GetFile("CustomHeaderInclude").Name : string.Empty;
159
160 var themesParagraphLastChanged = Dynamicweb.Content.Services.Paragraphs.GetParagraphsByPageId(themePageId).OrderByDescending(p => p.Audit.LastModifiedAt).FirstOrDefault();
161 var cssLastModified = brandingPage.Audit.LastModifiedAt > themesParagraphLastChanged.Audit.LastModifiedAt ? brandingPage.Audit.LastModifiedAt : themesParagraphLastChanged.Audit.LastModifiedAt;
162
163 var cssThemeAndBrandingStyleFileInfo = new System.IO.FileInfo(Dynamicweb.Core.SystemInformation.MapPath($"/Files/Templates/Designs/Swift/_parsed/Swift_css/Swift_styles_{Model.Area.ID}.min.css"));
164
165
166 if (cssPageId != 0)
167 {
168 var cssFileInfo = new System.IO.FileInfo(Dynamicweb.Core.SystemInformation.MapPath($"/Files/Templates/Designs/Swift/_parsed/Swift_css/Swift_css_styles_{Model.Area.ID}.css"));
169 var cssParagraphLastChanged = Dynamicweb.Content.Services.Paragraphs.GetParagraphsByPageId(cssPageId).OrderByDescending(p => p.Audit.LastModifiedAt).FirstOrDefault();
170 if (!cssThemeAndBrandingStyleFileInfo.Exists || cssThemeAndBrandingStyleFileInfo.LastWriteTime < cssParagraphLastChanged.Audit.LastModifiedAt)
171 {
172 var cssPageview = Dynamicweb.Frontend.PageView.GetPageviewByPageID(cssPageId);
173 cssPageview.Redirect = false;
174 cssPageview.Output();
175 }
176 }
177
178 if (!cssThemeAndBrandingStyleFileInfo.Exists || cssThemeAndBrandingStyleFileInfo.LastWriteTime < brandingPage.Audit.LastModifiedAt)
179 {
180 //Branding page has been saved or the file is missing. Rewrite the file to disc.
181 if (brandingPageId > 0)
182 {
183 var brandingPageview = Dynamicweb.Frontend.PageView.GetPageviewByPageID(brandingPageId);
184 brandingPageview.Redirect = false;
185 brandingPageview.Output();
186 }
187 }
188
189 if (!cssThemeAndBrandingStyleFileInfo.Exists || cssThemeAndBrandingStyleFileInfo.LastWriteTime < themesParagraphLastChanged.Audit.LastModifiedAt)
190 {
191 //Branding page has been saved or the file is missing. Rewrite the file to disc.
192 if (themePageId > 0)
193 {
194 var themePageview = Dynamicweb.Frontend.PageView.GetPageviewByPageID(themePageId);
195 themePageview.Redirect = false;
196 themePageview.Output();
197 }
198 }
199
200 // Schema.org details for PDP
201 bool isProductDetailsPage = Dynamicweb.Context.Current.Request.QueryString.AllKeys.Contains("ProductID");
202 bool isArticlePage = Model.ItemType == "Swift_Article";
203 string schemaOrgType = string.Empty;
204
205 if (isProductDetailsPage)
206 {
207 schemaOrgType = "itemscope=\"\" itemtype=\"https://schema.org/Product\"";
208 }
209
210 if (isArticlePage)
211 {
212 schemaOrgType = "itemscope=\"\" itemtype=\"https://schema.org/Article\"";
213 }
214
215
216 var cssStyleFileInfo = new System.IO.FileInfo(Dynamicweb.Core.SystemInformation.MapPath("/Files/Templates/Designs/Swift/Assets/css/styles.css"));
217 @* CS NT - custom Nextech stylesheet *@
218 var cssStyleFileInfoNextech = new System.IO.FileInfo(Dynamicweb.Core.SystemInformation.MapPath("/Files/Templates/Designs/Swift/Assets/css/nextech.css"));
219 @* CS NT - slick stylesheet *@
220 var cssStyleFileInfoSlick = new System.IO.FileInfo(Dynamicweb.Core.SystemInformation.MapPath("/Files/Templates/Designs/Swift/Assets/css/slick.css"));
221 @* CS NT - slick theme stylesheet *@
222 var cssStyleFileInfoSlickTheme = new System.IO.FileInfo(Dynamicweb.Core.SystemInformation.MapPath("/Files/Templates/Designs/Swift/Assets/css/slick-theme.css"));
223
224
225
226
227 var jsFileInfo = new System.IO.FileInfo(Dynamicweb.Core.SystemInformation.MapPath("/Files/Templates/Designs/Swift/Assets/js/scripts.js"));
228 @*CS NT - include custom.js*@
229 var jsFileInfoCustom = new System.IO.FileInfo(Dynamicweb.Core.SystemInformation.MapPath("/Files/Templates/Designs/Swift/Assets/js/custom.js"));
230 @*CS NT - include slick.min.js*@
231 var slickFileInfo = new System.IO.FileInfo(Dynamicweb.Core.SystemInformation.MapPath("/Files/Templates/Designs/Swift/Assets/js/slick.min.js"));
232
233
234 string masterTheme = !string.IsNullOrWhiteSpace(Model.Area.Item.GetRawValueString("Theme")) ? " theme " + Model.Area.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : "";
235
236 string favicon = Model.Area.Item.GetRawValueString("Favicon", "/Files/Templates/Designs/Swift/Assets/Images/favicon.png");
237 string appleTouchIcon = Model.Area.Item.GetRawValueString("AppleTouchIcon", "/Files/Templates/Designs/Swift/Assets/Images/apple-touch-icon.png");
238
239 string headerCssClass = "sticky-top";
240 bool movePageBehind = false;
241
242 if (Model.PropertyItem != null)
243 {
244 headerCssClass = Model.PropertyItem.GetRawValueString("MoveThisPageBehindTheHeader", "sticky-top");
245 movePageBehind = headerCssClass == "fixed-top" && !Pageview.IsVisualEditorMode ? true : false;
246 }
247
248 headerCssClass = headerCssClass == "" ? "sticky-top" : headerCssClass;
249 headerCssClass = Pageview.IsVisualEditorMode ? "" : headerCssClass;
250
251 string googleTagManagerID = Model.Area.Item.GetString("GoogleTagManagerID").Trim();
252 string googleAnalyticsMeasurementID = Model.Area.Item.GetString("GoogleAnalyticsMeasurementID").Trim();
253
254 bool allowTracking = AllowTracking();
255
256 Dynamicweb.Context.Current.Response.AddHeader("link", $"</Files/Templates/Designs/Swift/Assets/css/styles.css?{cssStyleFileInfo.LastWriteTime.Ticks}>; rel=preload; as=style;");
257 Dynamicweb.Context.Current.Response.AddHeader("link", $"</Files/Templates/Designs/Swift/Assets/css/nextech.css?{cssStyleFileInfoNextech.LastWriteTime.Ticks}>; rel=preload; as=style;");
258 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;");
259 Dynamicweb.Context.Current.Response.AddHeader("link", $"</Files/Templates/Designs/Swift/Assets/css/slick.css?{cssStyleFileInfoSlick.LastWriteTime.Ticks}>; rel=preload; as=style;");
260 Dynamicweb.Context.Current.Response.AddHeader("link", $"</Files/Templates/Designs/Swift/Assets/css/slick-theme.css?{cssStyleFileInfoSlickTheme.LastWriteTime.Ticks}>; rel=preload; as=style;");
261
262 Dynamicweb.Context.Current.Response.AddHeader("link", $"</Files/Templates/Designs/Swift/Assets/js/scripts.js?{jsFileInfo.LastWriteTime.Ticks}>; rel=preload; as=script;");
263 Dynamicweb.Context.Current.Response.AddHeader("link", $"</Files/Templates/Designs/Swift/Assets/js/custom.js?{jsFileInfoCustom.LastWriteTime.Ticks}; rel=preload; as=script;");
264 Dynamicweb.Context.Current.Response.AddHeader("link", $"</Files/Templates/Designs/Swift/Assets/js/slick.min.js?{slickFileInfo.LastWriteTime.Ticks}; rel=preload; as=script;");
265
266
267 SetMetaTags();
268
269 List<Dynamicweb.Content.Page> languages = new List<Dynamicweb.Content.Page>();
270
271 var masterPage = Pageview.Area.IsMaster ? Pageview.Page : Pageview.Page.MasterPage;
272 languages.Add(masterPage);
273 if (masterPage?.Languages != null)
274 {
275 foreach (var language in masterPage.Languages)
276 {
277 languages.Add(language);
278 }
279 }
280
281 Uri url = Dynamicweb.Context.Current.Request.Url;
282 string hostName = url.Host;
283
284 <!doctype html>
285 <html lang="@Pageview.Area.CultureInfo.TwoLetterISOLanguageName">
286 <head>
287 <!-- @swiftVersion -->
288 @* Required meta tags *@
289 <meta charset="utf-8">
290 <meta name="viewport" content="height=device-height, width=device-width, initial-scale=1.0">
291 <link rel="shortcut icon" href="@favicon">
292 <link rel="icon" type="image/png" href="@favicon">
293 <link rel="apple-touch-icon" href="@appleTouchIcon">
294
295 @*CS NT Jquery CDN*@
296 <script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
297
298 @Model.MetaTags
299 @*BG 20250416-Google Merchant Listing*@
300 @RenderSnippet("MerchantlistingJSON")
301
302
303
304 @*CS NT Cookie script, raptor, AI chatbot*@
305
306 <script async id="octocom-script" src="https://www.octocom.ai/chatbot/bundle.js"></script>
307
308 <!--Cookie Script Begin-->
309 <script type="text/javascript" charset="UTF-8" src="//cdn.cookie-script.com/s/0f7e74854350119f4ba7f565e3066cd6.js"></script>
310 <!--Cookie Script End-->
311
312 <!-- CS NT Staging? cookie script-->
313 <!--<script type="text/javascript" charset="UTF-8" src="//cdn.cookie-script.com/s/dfe7c945aeca99811bd22710360fd93f.js"></script>-->
314
315 <!-- CS NT natively-->
316 <script async onload="nativelyOnLoad()" src="https://cdn.jsdelivr.net/npm/natively@2.15.16/natively-frontend.min.js"></script>
317 <script>
318 function nativelyOnLoad() {
319 window.natively.setDebug(true); // To see errors
320 }
321 </script>
322
323
324 <script type="text/javascript">
325 let raptorPageViewSent = false;
326
327 window.addEventListener('CookieScriptAcceptAll', function() {
328 console.log('CookieScriptAcceptAll NT');
329
330 if ('@googleTagManagerID' != '')
331 {
332 (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
333 new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
334 j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
335 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
336 })(window,document,'script','dataLayer','@googleTagManagerID');
337 }
338
339
340 (function (d, t) { var g = d.createElement(t), s = d.getElementsByTagName(t)[0]; g.src = "//deliver.raptorstatic.com/script/raptor-3.0.min.js", g.async = "true", s.parentNode.insertBefore(g, s) }(document, "script"));
341 window.raptor || (window.raptor = { q: [{ event: "trackevent", params: { p1: "pageview" } }], push: function (event, params, options) { this.q.push({ event: event, params: params, options: options }) }, customerId: "6463" });
342 raptorPageViewSent = true;
343 })
344
345 window.addEventListener('CookieScriptCategory-targeting', function() {
346 console.log('CookieScriptCategory-targeting NT');
347
348 if ('@googleTagManagerID' != '')
349 {
350 (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
351 new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
352 j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
353 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
354 })(window,document,'script','dataLayer','@googleTagManagerID');
355 }
356
357 (function (d, t) { var g = d.createElement(t), s = d.getElementsByTagName(t)[0]; g.src = "//deliver.raptorstatic.com/script/raptor-3.0.min.js", g.async = "true", s.parentNode.insertBefore(g, s) }(document, "script"));
358 window.raptor || (window.raptor = { q: [{ event: "trackevent", params: { p1: "pageview" } }], push: function (event, params, options) { this.q.push({ event: event, params: params, options: options }) }, customerId: "6463" });
359 raptorPageViewSent = true;
360
361 })
362
363 window.addEventListener('CookieScriptAccept', function(e) {
364 console.log('CookieScriptAccept NT');
365 //console.log(e.detail);
366 var i;
367 var targetingEnabled = false;
368 for (i = 0; i < e.detail.categories.length; ++i) {
369 if(e.detail.categories[i] =='targeting')
370 {
371 targetingEnabled = true;
372 }
373 console.log(e.detail.categories[i]);
374 }
375 console.log('targetingEnabled '+targetingEnabled);
376 if(targetingEnabled)
377 {
378 console.log('CookieScriptAccept targeting NT');
379
380 if ('@googleTagManagerID' != '')
381 {
382 (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
383 new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
384 j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
385 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
386 })(window,document,'script','dataLayer','@googleTagManagerID');
387 }
388
389
390 (function (d, t) { var g = d.createElement(t), s = d.getElementsByTagName(t)[0]; g.src = "//deliver.raptorstatic.com/script/raptor-3.0.min.js", g.async = "true", s.parentNode.insertBefore(g, s) }(document, "script"));
391 window.raptor || (window.raptor = { q: [{ event: "trackevent", params: { p1: "pageview" } }], push: function (event, params, options) { this.q.push({ event: event, params: params, options: options }) }, customerId: "6463" });
392 raptorPageViewSent = true;
393 }
394 })
395
396 if(CookieScript.instance.currentState().categories.indexOf('targeting') >= 0)
397 {
398 if ('@googleTagManagerID' != '')
399 {
400 (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
401 new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
402 j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
403 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
404 })(window,document,'script','dataLayer','@googleTagManagerID');
405 }
406 }
407 if(!raptorPageViewSent && CookieScript.instance.currentState().action == 'accept')
408 {
409 console.log('CookieScript.instance.currentState().action = accept -> Calling pageview');
410
411 window.raptor || (window.raptor = { q: [{ event: "trackevent", params: { p1: "pageview" } }], push: function (event, params, options) { this.q.push({ event: event, params: params, options: options }) }, customerId: "6463" });
412 //(function (d, t) { var g = d.createElement(t), s = d.getElementsByTagName(t)[0]; g.src = "//deliver.raptorstatic.com/script/raptor-3.0.min.js", g.async = "true", s.parentNode.insertBefore(g, s) }(document, "script"));
413
414 }
415
416
417 </script>
418
419
420
421 @{
422 var alreadyWrittenTwoletterIsos = new List<string>();
423 @* Languages meta data *@
424 foreach (var language in languages)
425 {
426 hostName = url.Host;
427 if (language?.Area != null)
428 {
429 if (language.Area?.MasterArea != null && !string.IsNullOrEmpty(language.Area.MasterArea.DomainLock))
430 {
431 hostName = language.Area.MasterArea.DomainLock; //dk.domain.com or dk-domain.dk
432 }
433 if (language != null && language.Area != null && language.Published && language.Area.Active && language.Area.Published)
434 {
435 if (!string.IsNullOrEmpty(language.Area.DomainLock))
436 {
437 hostName = language.Area.DomainLock; //dk.domain.com or dk-domain.dk
438 }
439 string querystring = $"Default.aspx?ID={language.ID}";
440 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["GroupID"]))
441 {
442 querystring += $"&GroupID={Dynamicweb.Context.Current.Request.QueryString["GroupID"]}";
443 }
444 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["ProductID"]))
445 {
446 querystring += $"&ProductID={Dynamicweb.Context.Current.Request.QueryString["ProductID"]}";
447 }
448 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["VariantID"]))
449 {
450 querystring += $"&VariantID={Dynamicweb.Context.Current.Request.QueryString["VariantID"]}";
451 }
452
453 string friendlyUrl = Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl(querystring);
454 if (language.Area.RedirectFirstPage && language.ParentPageId == 0 && language.Sort == 1)
455 {
456 friendlyUrl = "/";
457 }
458 string href = $"{url.Scheme}://{hostName}{friendlyUrl}";
459
460
461 <link rel="alternate" hreflang="@language.Area.CultureInfo.Name.ToLower()" href="@href">
462 if (!alreadyWrittenTwoletterIsos.Contains(language.Area.CultureInfo.TwoLetterISOLanguageName))
463 {
464 alreadyWrittenTwoletterIsos.Add(language.Area.CultureInfo.TwoLetterISOLanguageName);
465 <link rel="alternate" hreflang="@language.Area.CultureInfo.TwoLetterISOLanguageName.ToLower()" href="@href">
466 }
467 }
468 }
469 }
470 }
471
472 <title>@Model.Title</title>
473 @* Bootstrap + Swift stylesheet *@
474 <link href="/Files/Templates/Designs/Swift/Assets/css/styles.css?@cssStyleFileInfo.LastWriteTime.Ticks" rel="stylesheet" media="all" type="text/css">
475 @* CS NT - custom Nextech stylesheet *@
476 <link href="/Files/Templates/Designs/Swift/Assets/css/nextech.css?@cssStyleFileInfoNextech.LastWriteTime.Ticks" rel="stylesheet" media="all" type="text/css">
477 @* CS NT - custom Slick stylesheet *@
478 <link href="/Files/Templates/Designs/Swift/Assets/css/slick.css?@cssStyleFileInfoSlick.LastWriteTime.Ticks" rel="stylesheet" media="all" type="text/css">
479 @* CS NT - Slick-theme stylesheet *@
480 <link href="/Files/Templates/Designs/Swift/Assets/css/slick-theme.css?@cssStyleFileInfoSlickTheme.LastWriteTime.Ticks" rel="stylesheet" media="all" type="text/css">
481
482 @* Font Awesome CS NT *@
483 <link href="/Files/Templates/Designs/Swift/Assets/fonts/FontAwesomeFree/css/fontawesome-all.min.css" rel="stylesheet" media="all" type="text/css">
484
485
486 @* Flags css from Rapido CS NT *@
487 <!-- Flag icon -->
488 <link rel="stylesheet" href="/Files/Templates/Designs/Swift/Assets/css/flag-icon.min.css" type="text/css">
489
490 @if (disableWideBreakpoints != "disableBoth")
491 {
492 <style>
493 @@media ( min-width: 1600px ) {
494 .container-xxl,
495 .container-xl,
496 .container-lg,
497 .container-md,
498 .container-sm,
499 .container {
500 max-width: 1520px;
501 }
502 }
503 </style>
504
505
506
507 if (disableWideBreakpoints != "disableUltraWideOnly")
508 {
509 <style>
510 @@media ( min-width: 1920px ) {
511 .container-xxl,
512 .container-xl,
513 .container-lg,
514 .container-md,
515 .container-sm,
516 .container {
517 max-width: 1820px;
518 }
519 }
520 </style>
521 }
522 }
523
524 @* Branding and Themes min stylesheet *@
525 <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">
526 <script src="/Files/Templates/Designs/Swift/Assets/js/scripts.js?@jsFileInfo.LastWriteTime.Ticks"></script>
527
528 @*<script src="https://cdn.jsdelivr.net/gh/igorlino/elevatezoom-plus@1.2.5/src/jquery.ez-plus.min.js"></script>*@
529 <script src="/Files/Templates/Designs/Swift/Assets/js/jquery.ez-plus1.2.5.min.js"></script>
530
531
532 @*CS NT - include custom.js*@
533 <script src="/Files/Templates/Designs/Swift/Assets/js/custom.js?@jsFileInfoCustom.LastWriteTime.Ticks" defer></script>
534 @*CS NT - include slick.min.js*@
535 <script src="/Files/Templates/Designs/Swift/Assets/js/slick.min.js?@slickFileInfo.LastWriteTime.Ticks" defer></script>
536
537 <script src="https://www.google.com/recaptcha/api.js" async defer></script>
538
539 <script type="module">
540 swift.Scroll.hideHeadersOnScroll();
541 swift.Scroll.handleAlternativeTheme();
542
543 //Only load if AOS
544 const aosColumns = document.querySelectorAll('[data-aos]');
545 if (aosColumns.length > 0) {
546 swift.AssetLoader.Load('/Files/Templates/Designs/Swift/Assets/js/aos.js?@jsFileInfo.LastWriteTime.Ticks', 'js');
547 document.addEventListener('load.swift.assetloader', function () {
548 AOS.init({ duration: 400, delay: 100, easing: 'ease-in-out', mirror: false, disable: window.matchMedia('(prefers-reduced-motion: reduce)') });
549 });
550 }
551 </script>
552
553 @* Google gtag method - always include even if it is not used for anything *@
554 <script>
555 window.dataLayer = window.dataLayer || [];
556 function gtag() { dataLayer.push(arguments); }
557 </script>
558 @* Google tag manager *@
559 @if (false && !string.IsNullOrWhiteSpace(googleTagManagerID))
560 {
561 <script>
562 gtag('consent', 'default', {
563 'ad_storage': 'denied',
564 'ad_user_data': 'denied',
565 'ad_personalization': 'denied',
566 'analytics_storage': 'denied'
567 });
568 </script>
569 <script>
570 (function (w, d, s, l, i) {
571 w[l] = w[l] || []; w[l].push({
572 'gtm.start':
573 new Date().getTime(), event: 'gtm.js'
574 }); var f = d.getElementsByTagName(s)[0],
575 j = d.createElement(s), dl = l != 'dataLayer' ? '&l=' + l : ''; j.async = true; j.src =
576 'https://www.googletagmanager.com/gtm.js?id=' + i + dl; f.parentNode.insertBefore(j, f);
577 })(window, document, 'script', 'dataLayer', '@(googleTagManagerID)');
578 </script>
579 if (allowTracking)
580 {
581 string adConsent = GetCookieOptInPermission("Marketing");
582 string analyticsConsent = GetCookieOptInPermission("Statistical");
583 <script>
584 gtag('consent', 'update', {
585 'ad_storage': '@adConsent',
586 'ad_user_data': '@adConsent',
587 'ad_personalization': '@adConsent',
588 'analytics_storage': '@analyticsConsent'
589 });
590 </script>
591 }
592 }
593
594 @if (!string.IsNullOrWhiteSpace(googleAnalyticsMeasurementID) && allowTracking)
595 {
596 var GoogleAnalyticsDebugMode = "";
597
598 if (Model.Area.Item.GetBoolean("EnableGoogleAnalyticsDebugMode"))
599 {
600 GoogleAnalyticsDebugMode = ", {'debug_mode': true}";
601 }
602
603 <script async src="https://www.googletagmanager.com/gtag/js?id=@googleAnalyticsMeasurementID"></script>
604 <script>
605 gtag('js', new Date());
606 gtag('config', '@googleAnalyticsMeasurementID'@GoogleAnalyticsDebugMode);
607 </script>
608 }
609
610 @*BG-NT Findbar start *@
611 @if (currentLanguageTwoLetter == "el")
612 {
613 <script type="text/javascript" src="https://app.findbar.io/js/superhome.com.cy/findbar.js?index=wmswot" async></script>
614 }
615 else
616 {
617 <script type="text/javascript" src="https://app.findbar.io/js/superhome.com.cy/findbar.js" async></script>
618 }
619 @*BG-NT Findbar end *@
620
621
622 @if (!string.IsNullOrWhiteSpace(customHeaderInclude))
623 {
624 @RenderPartial($"Components/Custom/{customHeaderInclude}")
625 }
626 </head>
627 <body class="brand @(masterTheme)" id="page@(Model.ID)">
628
629 @* Google tag manager *@
630 @if (!string.IsNullOrWhiteSpace(googleTagManagerID) && allowTracking)
631 {
632 <noscript>
633 <iframe src="https://www.googletagmanager.com/ns.html?id=@(googleTagManagerID)"
634 height="0" width="0" style="display:none;visibility:hidden"></iframe>
635 </noscript>
636 }
637
638 @if (renderAsResponsive || !renderMobile)
639 {
640 <header class="page-header @headerCssClass top-0@(responsiveClassDesktop)" id="page-header-desktop">
641 @if (headerDesktopLink != null)
642 {
643 @RenderGrid(headerDesktopLink.PageId)
644 }
645 </header>
646 }
647
648 @if ((renderAsResponsive || renderMobile))
649 {
650 <header class="page-header @headerCssClass top-0@(responsiveClassMobile)" id="page-header-mobile">
651 @if (headerMobileLink != null)
652 {
653 @RenderGrid(headerMobileLink.PageId)
654 }
655 </header>
656 }
657
658 <div data-intersect></div>
659
660 <main id="content" @(schemaOrgType)>
661 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
662 @using System
663 @using Dynamicweb.Ecommerce.ProductCatalog
664
665
666 @{
667 string productIdFromUrl = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("ProductID")) ? Dynamicweb.Context.Current.Request.QueryString.Get("ProductID") : string.Empty;
668 bool isProductDetail = !string.IsNullOrEmpty(productIdFromUrl) && Pageview.Page.NavigationTag.ToLower() == "shop";
669
670 bool isArticlePagePage = Model.ItemType == "Swift_Article";
671 bool isArticleListPage = Model.ItemType == "Swift_ArticleListPage";
672 string schemaOrgProp = string.Empty;
673 if(isArticlePagePage)
674 {
675 schemaOrgProp = "itemprop=\"articleBody\"";
676 }
677
678 string theme = "";
679 string gridContent = "";
680
681 if (Model.PropertyItem != null)
682 {
683 theme = !string.IsNullOrWhiteSpace(Model.PropertyItem.GetRawValueString("Theme")) ? "theme " + Model.PropertyItem.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : "";
684 }
685
686 if (Model.Item != null || Pageview.IsVisualEditorMode)
687 {
688 if (!isProductDetail)
689 {
690 gridContent = Model.Grid("Grid", "Grid", "default:true;sort:1", "Page");
691 }
692 else
693 {
694 var productObject = Dynamicweb.Ecommerce.Services.Products.GetProductById(productIdFromUrl, "", Pageview.Area.EcomLanguageId);
695 var detailPage = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(productObject.PrimaryGroupId)?.Meta.PrimaryPage ?? string.Empty;
696 var detailPageId = detailPage != string.Empty ? Convert.ToInt16(detailPage.Substring(detailPage.LastIndexOf('=') + 1)) : GetPageIdByNavigationTag("ProductDetailPage");
697
698 @RenderGrid(detailPageId)
699 }
700 }
701
702 bool doNotRenderPage = false;
703
704 //Check if we are on the poduct detail page, and if there is data to render
705 ProductViewModel product = new ProductViewModel();
706 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails"))
707 {
708 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"];
709 if (string.IsNullOrEmpty(product.Id)) {
710 doNotRenderPage = true;
711 }
712 }
713
714 //Render the page
715 if (!doNotRenderPage) {
716 string itemIdentifier = Model?.Item?.SystemName != null ? "item_" + Model.Item.SystemName.ToLower() : "item_Swift_Page";
717
718 if (Pageview.IsVisualEditorMode) {
719 @Model.Placeholder("dwcontent", "content", "default:true;sort:1")
720 }
721
722 <div class="@theme @itemIdentifier" @schemaOrgProp>
723 @if (isArticleListPage)
724 {
725 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\"";
726
727 <form @hx id="ArticleFacetForm">
728 @gridContent
729 </form>
730 <script type="module" src="/Files/Templates/Designs/Swift/Assets/js/htmx.js"></script>
731 <script type="module">
732 document.addEventListener('htmx:confirm', (event) => {
733 let filters = event.detail.elt.querySelectorAll('select');
734 for (var i = 0; i < filters.length; i++) {
735 let input = filters[i];
736 if (input.name && !input.value) {
737 input.name = '';
738 }
739 }
740 });
741
742 document.addEventListener('htmx:beforeOnLoad', (event) => {
743 swift.Scroll.stopIntersectionObserver();
744 });
745
746 document.addEventListener('htmx:afterOnLoad', () => {
747 swift.Scroll.hideHeadersOnScroll();
748 swift.Scroll.handleAlternativeTheme();
749 });
750 </script>
751 }
752 else
753 {
754 @gridContent
755 }
756 </div>
757
758 } else {
759 <div class="container">
760 <div class="alert alert-info" role="alert">@Translate("Sorry. There is nothing to view here")</div>
761 </div>
762 }
763
764 if (!Model.IsCurrentUserAllowed)
765 {
766 int signInPage = GetPageIdByNavigationTag("SignInPage");
767 int dashboardPage = GetPageIdByNavigationTag("MyAccountDashboardPage");
768
769 if (!Pageview.IsVisualEditorMode)
770 {
771 if (signInPage != 0)
772 {
773 if (signInPage != Model.ID) {
774 Dynamicweb.Context.Current.Response.Redirect("/Default.aspx?ID=" + signInPage);
775 } else {
776 if (dashboardPage != 0) {
777 Dynamicweb.Context.Current.Response.Redirect("/Default.aspx?ID=" + dashboardPage);
778 } else {
779 Dynamicweb.Context.Current.Response.Redirect("/");
780 }
781 }
782 }
783 else
784 {
785 <div class="alert alert-dark m-0" role="alert">
786 <span>@Translate("You do not have access to this page")</span>
787 </div>
788 }
789 }
790 else
791 {
792 <div class="alert alert-dark m-0" role="alert">
793 <span>@Translate("To work on this page, you must be signed in, in the frontend")</span>
794 </div>
795 }
796 }
797 }
798
799 </main>
800
801 @if (renderAsResponsive || !renderMobile)
802 {
803 <footer class="page-footer@(responsiveClassDesktop)" id="page-footer-desktop">
804 @if (footerDesktopLink != null)
805 {
806 @RenderGrid(footerDesktopLink.PageId)
807 }
808 </footer>
809 }
810
811 @if (renderAsResponsive || renderMobile)
812 {
813 <footer class="page-footer@(responsiveClassMobile)" id="page-footer-mobile">
814 @if (footerMobileLink != null)
815 {
816 @RenderGrid(footerMobileLink.PageId)
817 }
818 </footer>
819 }
820
821 @* Render any offcanvas menu here *@
822 @RenderSnippet("offcanvas")
823
824 @{
825 bool isErpConnectionDown = !Dynamicweb.Core.Converter.ToBoolean(Context.Current.Items["IsWebServiceConnectionAvailable"]);
826 }
827
828 @* Language selector modal *@
829 <div class="modal fade" id="PreferencesModal" tabindex="-1" aria-hidden="true">
830 <div class="modal-dialog modal-dialog-centered modal-sm" id="PreferencesModalContent">
831 @* The content here comes from an external request *@
832 </div>
833 </div>
834
835 @* Favorite toast *@
836 <div aria-live="polite" aria-atomic="true">
837 <div class="position-fixed bottom-0 end-0 p-3" style="z-index: 11">
838 <div id="favoriteNotificationToast" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
839 <div class="toast-header">
840 <strong class="me-auto">@Translate("Favorite list updated")</strong>
841 <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
842 </div>
843 <div class="toast-body d-flex gap-3">
844 <div id="favoriteNotificationToast_Image"></div>
845 <div id="favoriteNotificationToast_Text"></div>
846 </div>
847 </div>
848 </div>
849 </div>
850
851 @* Modal for dynamic content *@
852 <div class="modal fade js-product" id="DynamicModal" tabindex="-1" aria-hidden="true">
853 <div class="modal-dialog modal-dialog-centered modal-md">
854 <div class="modal-content theme light" id="DynamicModalContent">
855 @* The content here comes from an external request *@
856 </div>
857 </div>
858 </div>
859
860 @*CS NT 20251104 *@
861 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel>
862 @using System.Web
863 @using NextechDWAddIn.Common
864 @using NextechDWAddIn.Helpers
865
866 @{
867 bool showMarketingPreferencesModal = false;
868 string userId_newsPref = "";
869 if (Pageview != null && Pageview.User != null)
870 {
871 try
872 {
873 userId_newsPref = Pageview.User.ID.ToString();
874 //todo get cookie value if to show modal. Check this on afterLogin and set the cookie value!
875
876 string UserMarketingPreferences_AttemptsRemaining = HttpCookieHelper.GetHttpCookie("UserMarketingPreferences_AttemptsRemaining");
877 if (!string.IsNullOrWhiteSpace(UserMarketingPreferences_AttemptsRemaining))
878 {
879 if (int.TryParse(UserMarketingPreferences_AttemptsRemaining, out int UserMarketingPreferences_AttemptsRemaining_int))
880 {
881 if (UserMarketingPreferences_AttemptsRemaining_int > 0)
882 {
883 showMarketingPreferencesModal = true;
884 UserMarketingPreferences_AttemptsRemaining_int -= 1;
885 HttpCookieHelper.SetHttpCookie("UserMarketingPreferences_AttemptsRemaining", UserMarketingPreferences_AttemptsRemaining_int.ToString());
886
887 }
888 }
889 }
890 }
891 catch (Exception ex)
892 {
893 Logger.Instance.Log(ErrorLevel.DebugInfo, "MarketingPreferencesModal.cshtml EXCEPTION: " + ex.Message + " StackTrace: " + ex.StackTrace);
894 }
895
896 //if(Pageview.User.ID == 3700){showMarketingPreferencesModal = true;}//CS NT
897
898 }
899
900 }
901
902 @if (showMarketingPreferencesModal)
903 {
904
905 <button type="button" class="btn btn-link p-0 border-0" data-bs-toggle="modal" data-bs-target="#MarketingPreferencesModal" id="MarketingPreferencesModal_Target_Btn" aria-expanded="true" aria-controls="MarketingPreferencesModal_Target_Btn" hidden></button>
906 <div class="modal fade js-product" id="MarketingPreferencesModal" tabindex="-1" aria-hidden="true">
907 <div class="modal-dialog modal-dialog-centered modal-md">
908 <div class="modal-content theme light" id="MarketingPreferencesModalContent">
909
910 <div class="promo-section">
911 <div class="speech-box">
912 <h2>@Translate("Stay in the loop!")</h2>
913 <p>@Translate("I agree to receive updates, offers, and promotional communications from") <span class="fw-bold">SUPERHOME CENTER (DIY) LIMITED</span> @Translate("via SMS and email.")</p>
914
915 <div class="marketing-options">
916 <label class="marketing-checkbox-container">
917 <input type="checkbox" name="marketing_email" id="email_MarketingPreferences" />
918 <span class="marketing-checkmark"></span>
919 <span class="label-text">@Translate("Email")</span>
920 </label>
921
922 <label class="marketing-checkbox-container">
923 <input type="checkbox" name="marketing_sms" id="sms_MarketingPreferences" />
924 <span class="marketing-checkmark"></span>
925 <span class="marketing-label-text">@Translate("SMS")</span>
926 </label>
927 </div>
928
929 <button type="button" class="" id="MarketingPreferencesModal_ConfirmBtn">@Translate("Confirm")</button>
930 </div>
931 </div>
932
933
934
935 @*
936 <div class="modal-header">
937 <button type="button" id="MarketingPreferencesModal-btn-close" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
938 </div>
939
940 <div class="modal-body d-grid gap-3">
941 <span class="w-100">@Translate("I would like to receive updates and marketing information via:")</span>
942
943 <div class="marketing-options">
944 <label class="marketing-checkbox-container">
945 <input type="checkbox" name="marketing_email" id="email_MarketingPreferences" />
946 <span class="marketing-checkmark"></span>
947 <span class="label-text">@Translate("Email")</span>
948 </label>
949
950 <label class="marketing-checkbox-container">
951 <input type="checkbox" name="marketing_sms" id="sms_MarketingPreferences" />
952 <span class="marketing-checkmark"></span>
953 <span class="marketing-label-text">@Translate("SMS")</span>
954 </label>
955 </div>
956 </div>
957
958 <div class="modal-footer text-center" id="MarketingPreferences-modal-footer">
959 <button type="button" class="btn btn-primary" id="MarketingPreferencesModal_ConfirmBtn">@Translate("Confirm")</button>
960 </div>
961 *@
962 </div>
963 </div>
964 </div>
965
966
967
968 <script type="text/javascript">
969 $(document).ready(function () {
970 // Wait for the button element to appear (assuming waitForElm is defined elsewhere)
971 waitForElm('#MarketingPreferencesModal_Target_Btn').then((elm) => {
972 $("#MarketingPreferencesModal_Target_Btn").trigger("click");
973 });
974
975 // Confirm button click handler
976 $("#MarketingPreferencesModal_ConfirmBtn").on("click", function () {
977 const userId = '@userId_newsPref'; // server-side injected variable (string)
978
979 // Get checkbox states
980 const emailSelected = $('#email_MarketingPreferences').is(':checked') ? 1 : 0;
981 const smsSelected = $('#sms_MarketingPreferences').is(':checked') ? 1 : 0;
982
983 console.log("Email marketing:", emailSelected);
984 console.log("SMS marketing:", smsSelected);
985
986 // ✅ Use backticks for template literals, not single quotes
987 const apiUrl = `/MarketingPreferencesAPI?userId=${userId}&emailMarketingSelected=${emailSelected}&SMSMarketingSelected=${smsSelected}`;
988
989 console.log("apiUrl:", apiUrl);
990
991 // Make the GET request
992 $.get(apiUrl)
993 .done(function (response) {
994 console.log('Preferences saved:', response);
995 //alert('Your preferences have been saved successfully!');
996 })
997 .fail(function (xhr, status, error) {
998 //console.log('Error:' + error);
999 //alert('There was a problem saving your preferences.');
1000 });
1001
1002
1003 //document.getElementById('MarketingPreferencesModal-btn-close').click();//close modal
1004 });
1005 });
1006 </script>
1007
1008 <script>
1009 document.addEventListener("DOMContentLoaded", function () {
1010 const confirmBtn = document.getElementById("MarketingPreferencesModal_ConfirmBtn");
1011
1012 confirmBtn.addEventListener("click", function () {
1013 // Get the Bootstrap modal instance
1014 const modalElement = document.getElementById("MarketingPreferencesModal");
1015 const modalInstance = bootstrap.Modal.getInstance(modalElement);
1016
1017 // Hide the modal
1018 modalInstance.hide();
1019 });
1020 });
1021 </script>
1022 }
1023
1024 @* Offcanvas for dynamic content *@
1025 <div class="offcanvas offcanvas-end theme light" tabindex="-1" id="DynamicOffcanvas">
1026 @* The content here comes from an external request *@
1027 </div>
1028
1029 @if (Model.Area.Item.GetBoolean("ShowErpDownMessage") && !Dynamicweb.Core.Converter.ToBoolean(Context.Current.Items["IsWebServiceConnectionAvailable"]))
1030 {
1031 string erpDownMessageTheme = !string.IsNullOrWhiteSpace(Model.Area.Item.GetRawValueString("ErpDownMessageTheme")) ? " theme " + Model.Area.Item.GetRawValueString("ErpDownMessageTheme").Replace(" ", "").Trim().ToLower() : "theme light";
1032
1033 <div class="position-fixed bottom-0 end-0 p-3" style="z-index: 1040">
1034 <div class="toast fade show border-0 @erpDownMessageTheme" role="alert" aria-live="assertive" aria-atomic="true">
1035 <div class="toast-header">
1036 <strong class="me-auto">@Translate("Connection down")</strong>
1037 <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
1038 </div>
1039 <div class="toast-body">
1040 @Translate("We are experiencing some connectivity issues. Not all features may be available to you.")
1041 </div>
1042 </div>
1043 </div>
1044 }
1045
1046 @if (miniCartEnabled)
1047 {
1048 @* Open MiniCart when the cart is updated *@
1049 <script type="module">
1050 document.addEventListener('updated.swift.cart', (event) => {
1051 let orderContext = event?.detail?.formData?.get("OrderContext");
1052 updateCartSummary(orderContext);
1053
1054 @if (offcanvasMiniCartBehaviour == "2" || offcanvasMiniCartBehaviour == "3") {
1055 <text>openMiniCartOffcanvas();</text>
1056 }
1057 });
1058 </script>
1059
1060 if (offcanvasMiniCartBehaviour == "1" || offcanvasMiniCartBehaviour == "3")
1061 {
1062 @* Open MiniCart when toggle is clicked *@
1063 <script type="module">
1064 let miniCartToggles = document.querySelectorAll('.mini-cart-quantity');
1065 miniCartToggles?.forEach((toggle) => {
1066 toggle.parentElement.addEventListener('click', (event) => {
1067 event.preventDefault();
1068 let orderContext = toggle.dataset?.orderContext;
1069 updateCartSummary(orderContext);
1070
1071 openMiniCartOffcanvas();
1072 });
1073 });
1074 </script>
1075 }
1076
1077 <script>
1078
1079 const updateCartSummary = (orderContext) => {
1080 const dynamicOffcanvas = document.getElementById('DynamicOffcanvas');
1081 swift.PageUpdater.UpdateFromUrlInline(event, '/Default.aspx?ID=@(cartSummaryPageId)&CartType=minicart&RequestPageID=@(Pageview.Page.ID)&OrderContext=' + orderContext +'', 'Swift_CartSummary.cshtml', dynamicOffcanvas);
1082 };
1083
1084 const openMiniCartOffcanvas = () => {
1085 const dynamicOffcanvas = document.getElementById('DynamicOffcanvas');
1086 const miniCartOffcanvas = bootstrap.Offcanvas.getOrCreateInstance(dynamicOffcanvas);
1087 dynamicOffcanvas.classList.add('overflow-y-auto');
1088
1089 if (!miniCartOffcanvas._isShown) {
1090 miniCartOffcanvas.show();
1091 hideActiveOffcanvases(miniCartOffcanvas);
1092 }
1093 };
1094
1095 const hideActiveOffcanvases = (miniCartOffcanvas) => {
1096 let activeOffcanvases = document.querySelectorAll('.offcanvas.show');
1097 activeOffcanvases?.forEach((offCanvas) => {
1098 offCanvas = bootstrap.Offcanvas.getInstance(offCanvas);
1099 if (offCanvas !== miniCartOffcanvas) {
1100 offCanvas.hide();
1101 }
1102 });
1103 };
1104
1105 </script>
1106 }
1107
1108
1109
1110
1111 <script>
1112 //CS NT 20251121
1113
1114 document.addEventListener("click", function (e) {
1115 const target = e.target.closest(".is-redirect-cognito-login");
1116 if (!target) return;
1117
1118 e.preventDefault();
1119
1120 const isAndroid = window && window.natively && window.natively.isAndroidApp;
1121
1122 window.location.reload(true);
1123
1124 setTimeout(() => {
1125 if (isAndroid) {
1126 window.natively.openExternalURL('@redirectURL_cognito', true);
1127 } else {
1128 window.location.assign('@redirectURL_cognito');
1129 }
1130 }, 100);
1131 });
1132 </script>
1133
1134
1135 </body>
1136
1137 </html>
1138
1139 }
1140 else if (Pageview.IsVisualEditorMode)
1141 {
1142 <head>
1143 <title>@Model.Title</title>
1144 @* Bootstrap + Swift stylesheet *@
1145 <link href="/Files/Templates/Designs/Swift/Assets/css/styles.css" rel="stylesheet" media="all" type="text/css">
1146 </head>
1147 <body class="p-3">
1148 <div class="alert alert-danger" role="alert">
1149 @Translate("Basic Swift setup is needed!")
1150 </div>
1151
1152 @if (brandingPage == null)
1153 {
1154 <div class="alert alert-warning" role="alert">
1155 @Translate("Please add a Branding page and reference it in website settings")
1156 </div>
1157 }
1158
1159 @if (themesParagraphs == null)
1160 {
1161 <div class="alert alert-warning" role="alert">
1162 @Translate("Please add a Themes collection page and reference it in website settings")
1163 </div>
1164 }
1165 </body>
1166 }
1167
1168
1169 @functions {
1170 void SetMetaTags()
1171 {
1172 //Verification Tokens
1173 string siteVerificationGoogle = Model.Area.Item.GetString("Google_Site_Verification") != null ? Model.Area.Item.GetString("Google_Site_Verification") : "";
1174
1175 //Generic Site Values
1176 string openGraphFacebookAppID = Model.Area.Item.GetString("Fb_app_id") != null ? Model.Area.Item.GetString("Fb_app_id") : "";
1177 string openGraphType = Model.Area.Item.GetString("Open_Graph_Type") != null ? Model.Area.Item.GetString("Open_Graph_Type") : "";
1178 string openGraphSiteName = Model.Area.Item.GetString("Open_Graph_Site_Name") != null ? Model.Area.Item.GetString("Open_Graph_Site_Name") : "";
1179
1180 string twitterCardSite = Model.Area.Item.GetString("Twitter_Site") != null ? Model.Area.Item.GetString("Twitter_Site") : "";
1181
1182 //Page specific values
1183 string openGraphSiteTitle = Model.Area.Item.GetString("Open_Graph_Title") != null ? Model.Area.Item.GetString("Open_Graph_Title") : "";
1184 FileViewModel openGraphImage = Model.Area.Item.GetFile("Open_Graph_Image");
1185 string openGraphImageALT = Model.Area.Item.GetString("Open_Graph_Image_ALT") != null ? Model.Area.Item.GetString("Open_Graph_Image_ALT") : "";
1186 string openGraphDescription = Model.Area.Item.GetString("Open_Graph_Description") != null ? Model.Area.Item.GetString("Open_Graph_Description") : "";
1187
1188 string twitterCardURL = Model.Area.Item.GetString("Twitter_URL") != null ? Model.Area.Item.GetString("Twitter_URL") : "";
1189 string twitterCardTitle = Model.Area.Item.GetString("Twitter_Title") != null ? Model.Area.Item.GetString("Twitter_Title") : "";
1190 string twitterCardDescription = Model.Area.Item.GetString("Twitter_Description") != null ? Model.Area.Item.GetString("Twitter_Description") : "";
1191 FileViewModel twitterCardImage = Model.Area.Item.GetFile("Twitter_Image");
1192 string twitterCardImageALT = Model.Area.Item.GetString("Twitter_Image_ALT") != null ? Model.Area.Item.GetString("Twitter_Image_ALT") : "";
1193
1194 //CS NT 20260116
1195 string productImageNT = "";
1196 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("ProductID")))
1197 {
1198 string productId = Dynamicweb.Context.Current.Request.QueryString.Get("ProductID");
1199 if(!string.IsNullOrEmpty(productId))
1200 {
1201 var product = Dynamicweb.Ecommerce.Services.Products.GetProductById(productId, "",true);
1202 if (product != null)
1203 {
1204 productImageNT = Dynamicweb.Ecommerce.Services.ProductImages.GetImagePath(product);
1205 if(!string.IsNullOrEmpty(productImageNT))
1206 {
1207 productImageNT = Dynamicweb.Context.Current.Request.Url.Scheme + "://" + Dynamicweb.Context.Current.Request.Url.Host + productImageNT;
1208 }
1209 }
1210 }
1211 }
1212 //..CS NT
1213
1214 if (string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["ProductID"]))
1215 {
1216 if (!string.IsNullOrEmpty(Model.Description))
1217 {
1218 Pageview.Meta.AddTag($"<meta property=\"og:description\" content=\"{Model.Description}\">");
1219 }
1220 else
1221 {
1222 Pageview.Meta.AddTag($"<meta property=\"og:description\" content=\"{openGraphDescription}\">");
1223 }
1224
1225 if (!string.IsNullOrEmpty(Pageview.Page.TopImage))
1226 {
1227 Pageview.Meta.AddTag($"<meta property=\"og:image\" content=\"{Dynamicweb.Context.Current.Request.Url.Scheme}://{Dynamicweb.Context.Current.Request.Url.Host}/Files{Pageview.Page.TopImage}\">");
1228 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}\">");
1229 }
1230 else if (openGraphImage != null)
1231 {
1232 Pageview.Meta.AddTag($"<meta property=\"og:image\" content=\"{Dynamicweb.Context.Current.Request.Url.Scheme}://{Dynamicweb.Context.Current.Request.Url.Host}{openGraphImage.Path}\">");
1233 Pageview.Meta.AddTag($"<meta property=\"og:image:secure_url\" content=\"{Dynamicweb.Context.Current.Request.Url.Scheme}://{Dynamicweb.Context.Current.Request.Url.Host}{openGraphImage.Path}\">");
1234 }
1235
1236 if (!string.IsNullOrEmpty(openGraphImageALT))
1237 {
1238 Pageview.Meta.AddTag($"<meta property=\"og:image:alt\" content=\"{openGraphImageALT}\">");
1239 }
1240 if (!string.IsNullOrEmpty(twitterCardDescription))
1241 {
1242 Pageview.Meta.AddTag("twitter:description", twitterCardDescription);
1243 }
1244
1245 if (!string.IsNullOrEmpty(Pageview.Page.TopImage))
1246 {
1247 Pageview.Meta.AddTag("twitter:image", $"{Dynamicweb.Context.Current.Request.Url.Scheme}://{Dynamicweb.Context.Current.Request.Url.Host}/Files{Pageview.Page.TopImage}");
1248 }
1249 else if (twitterCardImage != null)
1250 {
1251 Pageview.Meta.AddTag("twitter:image", $"{Dynamicweb.Context.Current.Request.Url.Scheme}://{Dynamicweb.Context.Current.Request.Url.Host}{openGraphImage.Path}");
1252 }
1253
1254 if (!string.IsNullOrEmpty(twitterCardImageALT))
1255 {
1256 Pageview.Meta.AddTag("twitter:image:alt", twitterCardImageALT);
1257 }
1258 }else if (!string.IsNullOrEmpty(productImageNT))
1259 {
1260 //CS NT 20260116
1261 Pageview.Meta.AddTag($"<meta property=\"og:image\" content=\"{productImageNT}\">");
1262 }
1263
1264 if (!string.IsNullOrEmpty(siteVerificationGoogle))
1265 {
1266 Pageview.Meta.AddTag("google-site-verification", siteVerificationGoogle);
1267 }
1268
1269 if (!string.IsNullOrEmpty(openGraphFacebookAppID))
1270 {
1271 Pageview.Meta.AddTag($"<meta property=\"fb:app_id\" content=\"{openGraphFacebookAppID}\">");
1272 }
1273
1274 if (!string.IsNullOrEmpty(openGraphType))
1275 {
1276 Pageview.Meta.AddTag($"<meta property=\"og:type\" content=\"{openGraphType}\">");
1277 }
1278
1279 if (!string.IsNullOrEmpty(openGraphSiteName))
1280 {
1281 Pageview.Meta.AddTag($"<meta property=\"og:url\" content=\"{Dynamicweb.Context.Current.Request.Url.Scheme}://{Dynamicweb.Context.Current.Request.Url.Host}{Pageview.SearchFriendlyUrl}\">");
1282 }
1283
1284 if (!string.IsNullOrEmpty(openGraphSiteName))
1285 {
1286 Pageview.Meta.AddTag($"<meta property=\"og:site_name\" content=\"{openGraphSiteName}\">");
1287 }
1288
1289
1290
1291 /*CS NT 20260116 fix " in name
1292 if (!string.IsNullOrEmpty(Model.Title))
1293 {
1294 Pageview.Meta.AddTag($"<meta property=\"og:title\" content=\"{Model.Title}\">");
1295 }
1296 else
1297 {
1298 Pageview.Meta.AddTag($"<meta property=\"og:title\" content=\"{openGraphSiteTitle}\">");
1299 }
1300 */
1301
1302 //CS NT 20260116 new
1303 if (!string.IsNullOrEmpty(Model.Title))
1304 {
1305 var safeTitle = System.Net.WebUtility.HtmlEncode(Model.Title);
1306 Pageview.Meta.AddTag($"<meta property=\"og:title\" content=\"{safeTitle}\">");
1307 }
1308 else
1309 {
1310 var safeDefaultTitle = System.Net.WebUtility.HtmlEncode(openGraphSiteTitle);
1311 Pageview.Meta.AddTag($"<meta property=\"og:title\" content=\"{safeDefaultTitle}\">");
1312 }
1313
1314
1315 if (!string.IsNullOrEmpty(twitterCardSite))
1316 {
1317 Pageview.Meta.AddTag("twitter:site", twitterCardSite);
1318 }
1319
1320 if (!string.IsNullOrEmpty(twitterCardURL))
1321 {
1322 Pageview.Meta.AddTag("twitter:url", twitterCardURL);
1323 }
1324
1325 if (!string.IsNullOrEmpty(twitterCardTitle))
1326 {
1327 Pageview.Meta.AddTag("twitter:title", twitterCardTitle);
1328 }
1329 }
1330 }
1331