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