Error executing template "Designs/SermanTipsmark/_parsed/Basic_Page.parsed.cshtml"
System.ArgumentException: An item with the same key has already been added.
   at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
   at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
   at Dynamicweb.Ecommerce.Products.GroupRelation.get_GroupRelationsByChildId(String childId)
   at Dynamicweb.Ecommerce.Products.Group.get_IsTopGroup()
   at Dynamicweb.Ecommerce.Shops.Shop.get_TopLevelGroups(String languageId)
   at Dynamicweb.Ecommerce.Frontend.NavigationProviders.GroupNavigationProvider.MakeGroupTree(Page page, NavigationItem parentNode)
   at Dynamicweb.Ecommerce.Frontend.NavigationProviders.GroupNavigationProvider.Process(NavigationItem node)
   at Dynamicweb.Ecommerce.Frontend.NavigationProviders.GroupNavigationProvider.ProcessTree(RootNavigationItem rootNode, NavigationType navigationType)
   at Dynamicweb.Frontend.XmlNavigation.MakeXml(Int32 parentId, Int32 levelStart, Int32 levelStop, Expand expand, Int32 selectedAreaId)
   at Dynamicweb.Frontend.XmlNavigation.GetNavigationHtml(Int32 parentId, Int32 levelStart, Int32 levelStop, Expand expand, String name, String xsltPath, Int32 selectedAreaId, Boolean sitemapMode, NameValueCollection settings, NameValueCollection attributes, IncludeMode mode)
   at Dynamicweb.Frontend.XmlNavigation.GetNavigationHtml(NameValueCollection settings, NameValueCollection attributes)
   at CompiledRazorTemplates.Dynamic.RazorEngine_37add7fb7c344ad389d6ac20e0b76b73.Execute() in C:\Solutions\SermanTipsmark\Test\Web\Files\Templates\Designs\SermanTipsmark\_parsed\Basic_Page.parsed.cshtml:line 214
   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.b__0(TextWriter writer)
   at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
   at Dynamicweb.Rendering.Template.RenderRazorTemplate()

1 @using System.Globalization 2 @using Dynamicweb.Content 3 @using Dynamicweb.Content.Items 4 @using Dynamicweb.Frontend; 5 @using Newtonsoft.Json 6 @using Newtonsoft.Json.Serialization 7 @using NLWI.Core.Factory 8 @using SermanTipsmark.Web.CustomCode.Items.Settings 9 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel> 10 <!DOCTYPE html> 11 <html lang="@Pageview.Area.Culture"> 12 <head> 13 <meta charset='utf-8' /> 14 <meta name="description" content="@Model.Description" /> 15 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5, user-scalable=yes, shrink-to-fit=no" /> 16 <meta http-equiv="x-ua-compatible" content="ie=edge"> 17 <meta name="theme-color" content="#0067a8" /> 18 @Model.MetaTags 19 @if (Model.Area.Item.GetBoolean("NoIndex")) 20 { 21 <!-- TODO: remove on launch--> 22 <meta name="robots" content="noindex, nofollow" /> 23 } 24 @{ 25 var websiteSettings = Item.GetItemById(Model.Area.ItemType, Model.Area.ItemId).ToCodeFirstItem<Websites>(); 26 27 } 28 <title>@Model.Title</title> 29 <link rel="preload" href="@NORRIQ.Common8.Razor.TimestampSource.GetSourceWithTimestamp("/Files/dist/css/SermanTipsmark-min.css")" as="style" /> 30 <link href="@NORRIQ.Common8.Razor.TimestampSource.GetSourceWithTimestamp("/Files/dist/css/SermanTipsmark-min.css")" rel="stylesheet" /> 31 <style type="text/css"> 32 @@media print { 33 .table .thead-dark th, 34 .border-bottom, 35 .table td, 36 .summary > li { 37 color: black; 38 border-color: gray; 39 } 40 a { 41 color: black; 42 text-decoration: none; 43 } 44 .basic_header, 45 .basic_footer, 46 .checkout .btn, 47 .step-list { 48 display: none; 49 } 50 } 51 </style> 52 <script id="CookieConsent" src="https://policy.app.cookieinformation.com/uc.js" data-culture="@Pageview.Area.CultureInfo.TwoLetterISOLanguageName.ToUpper()" type="text/javascript"></script> 53 54 @if (websiteSettings.TrackGoogleTrackManager) 55 { 56 <!-- Google Tag Manager --> 57 <script> 58 (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': 59 new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], 60 j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 61 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); 62 })(window,document,'script','dataLayer','@websiteSettings.GoogleTrackManager');</script> 63 <!-- End Google Tag Manager --> 64 } 65 @if (websiteSettings.TrackGa) 66 { 67 68 <!-- Google Analytics --> 69 <script async src="https://www.googletagmanager.com/gtag/js?id=@websiteSettings.GoogleGATracking"></script> 70 <script> 71 window.dataLayer = window.dataLayer || []; 72 function gtag(){dataLayer.push(arguments);} 73 gtag('js', new Date()); 74 75 gtag('config', '@websiteSettings.GoogleGATracking'); 76 @if (websiteSettings.TrackAdWords) 77 { 78 <text> 79 gtag('config', '@websiteSettings.GoogleAdWords'); 80 </text> 81 } 82 </script> 83 <!-- End Google Analytics --> 84 85 } 86 87 88 89 @if (websiteSettings.EnableHeaderScript) 90 { 91 @websiteSettings.HeaderScript 92 } 93 </head> 94 <body> 95 <div id="app"> 96 <header class="basic_header bg-primary w-100 position-relative elevation-3"> 97 @{ 98 string basicHeaderPrefix = "Header "; 99 } 100 @if (Pageview.User != null) 101 { 102 <div class="basic_header-top bg-primary text-white py-1"> 103 <div class="container d-flex justify-content-end align-items-center"> 104 <p class="font-size-xs nowrap"> 105 <b-icon-person-fill class="mr-1"></b-icon-person-fill> 106 <span class="mr-1 nowrap ellipsis">@Pageview.User.Name</span> 107 <span class="mr-1">-</span> 108 <a href="/admin/public/extranetlogoff.aspx?ID=@(NORRIQ.Common8.Razor.Navigation.GetPageIdByNavigationTag("home"))" class="text-light" v-clear-cache:click.user.cart>@Translate(basicHeaderPrefix + "Sign out", "Sign out")</a> 109 </p> 110 </div> 111 </div> 112 } 113 <div class="basic_header-main position-relative"> 114 <div class="container d-flex justify-content-between align-items-center"> 115 <a href="@Translate(basicHeaderPrefix + "logo url", "/")" class="basic_header-logo d-flex align-items-center py-3" title="@Translate(basicHeaderPrefix + "Go to frontpage", "Go to frontpage")"> 116 @if (Model.Area.Item.GetFile("Logo") != null) 117 { 118 <img class="img-fluid" src="@Model.Area.Item.GetFile("Logo")" alt="@Translate(basicHeaderPrefix + "Website Logo Alttext", "Website Logo Alttext")" /> 119 } 120 else 121 { 122 <i>@Translate(basicHeaderPrefix + "No logo found", "No logo found, please configure it in the Dynamicweb Administration")</i> 123 } 124 </a> 125 <form class="basic_header-search position-relative d-flex justify-content-end flex-grow-1" action="/Default.aspx"> 126 <input name="Id" type="hidden" value="@NORRIQ.Common8.Razor.Navigation.GetPageIdByNavigationTag("searchresult")"> 127 <label for="productsearch" class="sr-only">@Translate(basicHeaderPrefix + "Search", "Search")</label> 128 <input type="search" class="form-control position-relative border-0" placeholder="@Translate(basicHeaderPrefix + "Search", "Search")" id="productsearch" name="productsearch"> 129 <button type="submit" class="btn btn-square position-absolute position-top-right" aria-label="@Translate(basicHeaderPrefix + "Search", "Search")"> 130 <b-icon-search font-scale="1.25"></b-icon-search> 131 </button> 132 </form> 133 <div class="basic_header-functions d-flex align-items-center"> 134 <button type="button" 135 class="btn btn-square btn-burger" 136 aria-label="@Translate(basicHeaderPrefix + "Open main navigation", "Open main navigation")" 137 v-b-toggle.basic_navigation> 138 <b-icon-list font-scale="2" style="margin-top:4px;"></b-icon-list> 139 </button> 140 <b-dropdown variant="square" right no-caret id="langSelector"> 141 <template v-slot:button-content> 142 <img src="@Pageview.Area.Flag32X32" alt="@Pageview.Area.CultureInfo.EnglishName" /> 143 <span class="sr-only">@Pageview.Area.CultureInfo.EnglishName</span> 144 </template> 145 <template> 146 @{ 147 var groupId = System.Web.HttpContext.Current.Request["GroupId"]; 148 var productId = System.Web.HttpContext.Current.Request["ProductId"]; 149 var variantId = System.Web.HttpContext.Current.Request["VariantId"]; 150 } 151 @foreach (var lang in Model.Languages) 152 { 153 var langCode = lang.Culture.Split('-').Last(); 154 var cultureInfo = CultureInfo.GetCultureInfo(lang.Culture); 155 var language = cultureInfo.NativeName.Split('(')[0]; 156 language = cultureInfo.TextInfo.ToTitleCase(language); 157 var url = $"/Default.aspx?Id={lang.Page.ID}"; 158 var query = System.Web.HttpUtility.ParseQueryString(System.Web.HttpContext.Current.Request.QueryString.ToString()); 159 query.Remove("Id"); 160 query.Remove("GroupId"); 161 query.Remove("ProductId"); 162 query.Remove("VariantId"); 163 if (!string.IsNullOrWhiteSpace(groupId)) 164 { 165 url += $"&GroupId={groupId}"; 166 } 167 if (!string.IsNullOrWhiteSpace(productId)) 168 { 169 url += $"&ProductId={productId}"; 170 } 171 if (!string.IsNullOrWhiteSpace(variantId)) 172 { 173 url += $"&VariantId={variantId}"; 174 } 175 var urlencodedQuery = url; 176 if (query.HasKeys()) 177 { 178 urlencodedQuery += "&" + query.ToString(); 179 180 } 181 <b-dropdown-item href="@urlencodedQuery" link-class="d-flex align-items-center"><img src="@($"/Admin/Images/Flags/flag_{langCode}.png")" alt="@Translate(basicHeaderPrefix + language, language)" /><span class="font-size-sm ml-2">@Translate(basicHeaderPrefix + language, language)</span></b-dropdown-item> 182 } 183 @*<b-dropdown-item href="/admin/public/extranetlogoff.aspx?ID=@(NORRIQ.Common8.Razor.Navigation.GetPageIdByNavigationTag("home"))" v-clear-cache:click.user.cart class="border-top bg-light">@Translate(basicHeaderPrefix + "Sign out", "Sign out")</b-dropdown-item>*@ 184 </template> 185 </b-dropdown> 186 @if (Pageview.User == null) 187 { 188 <a href="@NORRIQ.Common8.Razor.Navigation.GetUrlByNavigationTag("selfservice")" class="btn btn-square" aria-label="@Translate(basicHeaderPrefix + "Login", "Login")"> 189 <b-icon-person font-scale="2"></b-icon-person> 190 </a> 191 } 192 else 193 { 194 <b-dropdown variant="square" right no-caret> 195 <template v-slot:button-content> 196 <b-icon-person font-scale="2"></b-icon-person> 197 <span class="sr-only">User</span> 198 </template> 199 <template> 200 @RenderNavigation(new { Template = "dropdown.xslt", Expandmode = "all", StartLevel = 1, EndLevel = 4, NavigationTag = "selfservice" }) 201 @*<b-dropdown-item href="/admin/public/extranetlogoff.aspx?ID=@(NORRIQ.Common8.Razor.Navigation.GetPageIdByNavigationTag("home"))" v-clear-cache:click.user.cart class="border-top bg-light">@Translate(basicHeaderPrefix + "Sign out", "Sign out")</b-dropdown-item>*@ 202 </template> 203 </b-dropdown> 204 } 205 @if (Pageview.User != null) 206 { 207 <cart-icon cartlink="@NORRIQ.Common8.Razor.Navigation.GetUrlByNavigationTag("checkout")"></cart-icon> 208 } 209 </div> 210 </div> 211 </div> 212 <template> 213 <b-sidebar id="basic_navigation" tag="nav" bg-variant="nav" text-variant="nav" backdrop body-class="container"> 214 @RenderNavigation(new { Template = "basic_Header.xslt", Expandmode = "all", StartLevel = 1, EndLevel = 4 }) 215 </b-sidebar> 216 </template> 217 </header> 218 @using Dynamicweb.Content.Items 219 @using Dynamicweb.Frontend; 220 @using SermanTipsmark.Web.CustomCode.Items.Pages 221 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel> 222 223 @Title("Page") 224 @Description("Default page template") 225 @if (Pageview.IsCurrentUserAllowed) 226 { 227 string pageLayout = !string.IsNullOrEmpty(Model.Item.GetValue<ListViewModel>("Layout").SelectedValue) ? Model.Item.GetValue<ListViewModel>("Layout").SelectedValue : "page-menu"; 228 string cssClass = !string.IsNullOrEmpty(Model.Item.GetString("CssClass")) ? " " + Model.Item.GetString("CssClass") : ""; 229 string columns = !string.IsNullOrEmpty(Model.Item.GetValue<ListViewModel>("Columns").SelectedValue) ? Model.Item.GetValue<ListViewModel>("Columns").SelectedValue : "d-grid-12"; 230 string width = Model.Item.GetBoolean("FullWidth") ? "container-0" : "container"; 231 string background = !string.IsNullOrEmpty(Model.Item.GetValue<ListViewModel>("BgColor").SelectedValue) ? " " + Model.Item.GetValue<ListViewModel>("BgColor").SelectedValue : ""; 232 string color = !string.IsNullOrEmpty(Model.Item.GetValue<ListViewModel>("TextColor").SelectedValue) ? " " + Model.Item.GetValue<ListViewModel>("TextColor").SelectedValue : ""; 233 string padding = !string.IsNullOrEmpty(Model.Item.GetValue<ListViewModel>("Padding").SelectedValue) ? " " + Model.Item.GetValue<ListViewModel>("Padding").SelectedValue : " py-4"; 234 string gap = Model.Item.GetBoolean("NoGaps") ? "gap-0" : ""; 235 <main class="d-block"> 236 @if (!Model.Item.GetBoolean("HideBreadcrumb") || pageLayout == "page-menu") 237 { 238 <nav class="page-nav"> 239 <div class="container d-flex justify-content-start align-items-center"> 240 @if (pageLayout == "page-menu") 241 { 242 <button type="button" 243 class="btn btn-sidebar btn-square border p-0 btn-sm mr-3" 244 v-b-toggle.sidebar 245 aria-label="@Translate("Toggle sidebar", "Toogle Sidebar")"> 246 <span class="arrow-left"></span> 247 </button> 248 } 249 @if (!Model.Item.GetBoolean("HideBreadcrumb")) 250 { 251 @RenderNavigation(new { Template = "basic_Breadcrumb.xslt", Expandmode = "all", StartLevel = 1, EndLevel = 5 }) 252 } 253 </div> 254 </nav> 255 } 256 257 @if (pageLayout == "page-menu") 258 { 259 @*<main class="d-block">*@ 260 <div class="@pageLayout @width @padding"> 261 <aside class="sidebar"> 262 <b-sidebar id="sidebar" backdrop shadow bg-variant="white" text-variant="dark" tag="nav"> 263 @RenderNavigation(new { Template = "basic_ListView.xslt", Expandmode = "all", StartLevel = 1, EndLevel = 3 }) 264 </b-sidebar> 265 </aside> 266 <div class="content"> 267 @RenderBanner() 268 <section class="layout@(cssClass)@(background)@(color)"> 269 @RenderHeader() 270 <div class="@columns @width @gap"> 271 @RenderPlaceholder() 272 </div> 273 </section> 274 </div> 275 </div> 276 @*</main>*@ 277 } 278 else if (pageLayout == "page-content") 279 { 280 <div class="@pageLayout @width @padding"> 281 @RenderBanner() 282 <section class="layout@(cssClass)@(background)@(color)"> 283 @RenderHeader() 284 <div class="@columns @width @gap"> 285 @RenderPlaceholder() 286 </div> 287 </section> 288 </div> 289 } 290 else 291 { 292 293 @RenderPlaceholder() 294 295 } 296 </main> 297 } 298 else 299 { 300 <main class="d-flex justify-content-center align-items-center w-100 h-100"> 301 @RenderPlaceholder() 302 </main> 303 } 304 @helper RenderPlaceholder() 305 { 306 @Model.Placeholder("Content", "Content", "unwrap:true;default:true") 307 } 308 309 @helper RenderHeader() 310 { 311 if (!string.IsNullOrEmpty(Model.Item.GetString("Title"))) 312 { 313 string display = Model.Item.GetBoolean("Display") ? "display " : ""; 314 string align = !string.IsNullOrEmpty(Model.Item.GetValue<ListViewModel>("Align").SelectedValue) ? Model.Item.GetValue<ListViewModel>("Align").SelectedValue + " " : ""; 315 string headingClass = align + display; 316 <header class="pb-4"> 317 <h1 class="@headingClass">@Model.Item.GetString("Title")</h1> 318 </header> 319 } 320 } 321 322 @helper RenderBanner() 323 { 324 var item = Item.GetItemById(Model.ItemType, Model.ItemId).ToCodeFirstItem<Basic_Page>(); 325 if (Model.Item.GetFile("TopImage") != null) 326 { 327 <figure class="page-banner layout"> 328 <img src="@Model.Item.GetFile("TopImage").Path" 329 alt="@Model.Item.GetString("Title")" 330 class="img-fluid @(item.ImageFullWith ? "full-with": "")" 331 loading="lazy" /> 332 </figure> 333 } 334 } 335 336 <footer class="basic_footer py-4"> 337 @{ 338 var imageLinks = Model.Area.Item.GetItems("ImageLinks").Where(s => s.GetFile("Image") != null); 339 } 340 <div class="container d-grid-3-3-3-3"> 341 @if (!string.IsNullOrEmpty(Model.Area.Item.GetString("FooterOneTitle")) && !string.IsNullOrEmpty(Model.Area.Item.GetString("FooterOneText"))) 342 { 343 <div class="basic_footer-box mt-0"> 344 <b-button variant="footer" v-b-toggle.footer-one> 345 @Model.Area.Item.GetString("FooterOneTitle") 346 <span class="plus-minus"></span> 347 </b-button> 348 <b-collapse id="footer-one"> 349 <div class="flow-2 font-size-sm"> 350 @Model.Area.Item.GetString("FooterOneText") 351 </div> 352 </b-collapse> 353 </div> 354 } 355 @if (!string.IsNullOrEmpty(Model.Area.Item.GetString("FooterTwoTitle")) && !string.IsNullOrEmpty(Model.Area.Item.GetString("FooterTwoText"))) 356 { 357 <div class="basic_footer-box mt-0"> 358 <b-button variant="footer" v-b-toggle.footer-two> 359 @Model.Area.Item.GetString("FooterTwoTitle") 360 <span class="plus-minus"></span> 361 </b-button> 362 <b-collapse id="footer-two"> 363 <div class="flow-2 font-size-sm"> 364 @Model.Area.Item.GetString("FooterTwoText") 365 </div> 366 </b-collapse> 367 </div> 368 } 369 @if (!string.IsNullOrEmpty(Model.Area.Item.GetString("FooterThreeTitle")) && !string.IsNullOrEmpty(Model.Area.Item.GetString("FooterThreeText"))) 370 { 371 <div class="basic_footer-box mt-0"> 372 <b-button variant="footer" v-b-toggle.footer-three> 373 @Model.Area.Item.GetString("FooterThreeTitle") 374 <span class="plus-minus"></span> 375 </b-button> 376 <b-collapse id="footer-three"> 377 <div class="flow-2 font-size-sm"> 378 @Model.Area.Item.GetString("FooterThreeText") 379 </div> 380 </b-collapse> 381 </div> 382 } 383 @if (!string.IsNullOrEmpty(Model.Area.Item.GetString("FooterFourTitle")) && !string.IsNullOrEmpty(Model.Area.Item.GetString("FooterFourText"))) 384 { 385 <div class="basic_footer-box mt-0"> 386 <b-button variant="footer" v-b-toggle.footer-four> 387 @Model.Area.Item.GetString("FooterFourTitle") 388 <span class="plus-minus"></span> 389 </b-button> 390 <b-collapse id="footer-four"> 391 <div class="flow-2 font-size-sm"> 392 @Model.Area.Item.GetString("FooterFourText") 393 </div> 394 </b-collapse> 395 </div> 396 } 397 </div> 398 399 @if (!string.IsNullOrEmpty(Model.Area.Item.GetString("FooterCopyright")) || imageLinks != null && imageLinks.Any()) 400 { 401 402 <div class="basic_footer-sub container pt-4 d-flex align-items-center"> 403 @if (!string.IsNullOrEmpty(Model.Area.Item.GetString("FooterCopyright"))) 404 { 405 <p class="font-size-xs"> 406 &copy; @DateTime.Now.Year @Model.Area.Item.GetString("FooterCopyright") 407 </p> 408 } 409 @if (imageLinks != null && imageLinks.Any()) 410 { 411 <div class="basic_footer-imagelinks d-flex align-items-center"> 412 @foreach (var item in imageLinks) 413 { 414 string target = item.GetString("Url").Contains("http") ? "_blank" : "_self"; 415 string rel = item.GetString("Url").Contains("http") ? "noreferrer noopener" : ""; 416 <a href="@item.GetString("Url")" class="d-inline-flex align-items-center p-1" rel="@rel" target="@target" title="@item.GetString("Title")"> 417 <img src="@item.GetFile("Image").Path" class="img-fluid" width="32" alt="@item.GetString("Title")" /> 418 </a> 419 } 420 </div> 421 } 422 </div> 423 } 424 </footer> 425 </div> 426 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 427 428 <script type="text/x-template" id="cart-icon-template"> 429 @{ 430 string cartIconPrefix = "Minicart "; 431 } 432 <a :href="cartlink" class="btn btn-square"> 433 <b-icon-cart3 font-scale="1.65"></b-icon-cart3> 434 <span class="sr-only">@Translate(cartIconPrefix + "Checkout", "Checkout")</span> 435 <span v-if="!cartEmpty" class="cart-quantity d-flex align-items-center justify-content-center">{{quantity}}</span> 436 </a> 437 </script> 438 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel> 439 440 <script type="text/x-template" id="basic-facet-filter-template"> 441 @{ 442 string basicFacetPrefix = "Filter "; 443 } 444 <div v-if="!queryLoading && !error && facetFilters" class="facets" id="sidebar-filter"> 445 446 447 448 <div class="facet-collapse" v-if="HasActiveFilter()"> 449 <p id="selected-filter-label" class="btn btn-collapse"> 450 @Translate(basicFacetPrefix + "Active", "Active") 451 </p> 452 <div class="pb-3 flow-2" aria-labelledby="selected-filter-label"> 453 <template v-for="facetFilter in facetFilters"> 454 <div v-for="option in SelectedOptions(facetFilter)" class="custom-control"> 455 <input type="checkbox" 456 :id="'Selected-' + facetFilter.name + '-' + option.name" 457 :name="facetFilter.name" 458 :value="option.value" 459 :v-model="option.selected" 460 :checked="option.selected" 461 v-on:click="ToggleFilter(facetFilter.queryParameter,option)" 462 class="custom-control-input" /> 463 <label :for="'Selected-' + facetFilter.name + '-' + option.name" class="custom-facet-label"> 464 <b-icon-x-circle-fill></b-icon-x-circle-fill> 465 <span> 466 {{facetFilter.name}}: {{option.label}} 467 </span> 468 </label> 469 </div> 470 </template> 471 </div> 472 </div> 473 <div class="facet-collapse" v-for="(facetFilter, index) in facetFilters"> 474 <b-button variant="collapse" v-b-toggle="'filter-group-' + facetFilter.name.replace(/\s/g, '').toLowerCase()"> 475 <span>{{facetFilter.name}}</span> 476 <span class="arrow-down"></span> 477 </b-button> 478 <b-collapse :id="'filter-group-' + facetFilter.name.replace(/\s/g, '').toLowerCase()" :visible="ShowGroupIfSelected(facetFilter.options, index)"> 479 <div class="py-3 flow-2"> 480 <template v-if="facetFilter.options.length > 5"> 481 <div v-for="option in facetFilter.options.slice(0, 5)" class="custom-control custom-checkbox"> 482 <input type="checkbox" class="custom-control-input" 483 :id="'UnSelected-' + facetFilter.name + '-' + option.name" 484 :name="facetFilter.name" 485 :value="option.value" 486 :v-model="option.selected" 487 :checked="option.selected" 488 v-on:click="ToggleFilter(facetFilter.queryParameter,option)" /> 489 <label :for="'UnSelected-' + facetFilter.name + '-' + option.name" class="custom-control-label"> 490 {{option.label}}<span class="count">({{option.count}})</span> 491 </label> 492 </div> 493 <b-collapse class="basic_filter-expand flow-2" :id="'filter-expand-' + facetFilter.name.replace(/\s/g, '').toLowerCase()" :visible="ShowMoreIfSelected(facetFilter.options, index)"> 494 <div v-for="option in facetFilter.options.slice(5)" class="custom-control custom-checkbox facet-option"> 495 <input type="checkbox" class="custom-control-input" 496 :id="'UnSelected-' + facetFilter.name + '-' + option.name" 497 :name="facetFilter.name" 498 :value="option.value" 499 :v-model="option.selected" 500 :checked="option.selected" 501 v-on:click="ToggleFilter(facetFilter.queryParameter,option)" /> 502 <label :for="'UnSelected-' + facetFilter.name + '-' + option.name" class="custom-control-label"> 503 {{option.label}} <span class="count">({{option.count}})</span> 504 </label> 505 </div> 506 </b-collapse> 507 <a v-b-toggle="'filter-expand-' + facetFilter.name.replace(/\s/g, '').toLowerCase()" class="btn btn-inline" v-if="facetFilter.options.length > 5"> 508 <span class="plus-minus"></span> 509 <span class="show-more">@Translate(basicFacetPrefix + "show more", "show more")</span> 510 <span class="show-less">@Translate(basicFacetPrefix + "show less", "show less")</span> 511 </a> 512 </template> 513 <template v-else> 514 <div v-for="option in facetFilter.options" class="custom-control custom-checkbox"> 515 <input type="checkbox" class="custom-control-input" 516 :id="'UnSelected-' + facetFilter.name + '-' + option.name" 517 :name="facetFilter.name" 518 :value="option.value" 519 :v-model="option.selected" 520 :checked="option.selected" 521 v-on:click="ToggleFilter(facetFilter.queryParameter,option)" /> 522 <label :for="'UnSelected-' + facetFilter.name + '-' + option.name" class="custom-control-label"> 523 {{option.label}} 524 </label> 525 </div> 526 </template> 527 </div> 528 </b-collapse> 529 </div> 530 531 </div> 532 </script> 533 534 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel> 535 <script type="text/x-template" id="add-to-basket-simple-template"> 536 @{ 537 string addToBasketSimplePrifix = "BuyButton "; 538 } 539 <div v-if="!isB2C"> 540 <label :for="'quantity-' + productId" class="sr-only">@Translate(addToBasketSimplePrifix + "Quantity", "Quantity")</label> 541 <input @@focus="$event.target.select()" :class="['form-control form-quantity', inputClass]" type="tel" name="quantity" :id="'quantity-' + productId" v-model="quantity" autocomplete="off" onclick="this.setSelectionRange(0, this.value.length)"> 542 <button :disabled="quantity < 1" :class="['btn', buttonClass, {added: IsAdded}, {adding: IsAdding}]" v-on:click="addToBasketAndResetQuantity()" aria-label="@Translate(addToBasketSimplePrifix + "Add to Basket", "Add to Basket")"> 543 <slot> 544 <b-icon-cart3></b-icon-cart3> 545 <span v-if="buttonLabel">{{buttonLabel}}</span> 546 </slot> 547 </button> 548 </div> 549 </script> 550 551 <script type="text/x-template" id="quick-add-template"> 552 @{ 553 string quickAddPrifix = "BuyButton "; 554 } 555 <div v-if="!isB2C" v-bind:class="[{added: IsAdded}, {adding: IsAdding}]"> 556 <label for="quantity">@Translate(quickAddPrifix + "Quantity", "Quantity")</label> 557 <input class="form-control" type="number" id="quantity" name="quantity" v-model="quantity" autocomplete="off"> 558 </div> 559 </script> 560 561 <script type="text/x-template" id="add-to-basket-button-only-template"> 562 @{ 563 string addToBasketPrefix = "BuyButton "; 564 } 565 <div v-if="!isB2C"> 566 <button :class="['btn', buttonClass, {added: IsAdded}, {adding: IsAdding}]" v-on:click="addToBasket()"> 567 <slot> 568 <b-icon-cart3></b-icon-cart3> 569 <span>@Translate(addToBasketPrefix + "Add to basket", "Add to basket")</span> 570 </slot> 571 </button> 572 </div> 573 </script> 574 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel> 575 <script type="text/x-template" id="async-price-template"> 576 @{ 577 string asyncPrefix = "Async "; 578 } 579 <div :class="'async' + (loading && !onlyStock ? ' loading text-center' : '')"> 580 <template v-if="error"> 581 <p class="text-danger font-weight-bold">{{error}}</p> 582 </template> 583 <template v-if="!onlyPrice && !error"> 584 @*<div class="d-flex align-items-center flex-wrap font-size-xs" >*@ 585 <template v-if="!loading && price && !hasStock"> 586 <p class="stock out-of-stock"> 587 <link itemprop="availability" href="http://schema.org/SoldOut" /> 588 @Translate(asyncPrefix + "Out Of Stock", "Out Of Stock") 589 </p> 590 <p class="text-muted font-size-xs"> 591 <template v-if="outOfStockText && outOfStockText !=''"> 592 {{outOfStockText}} 593 </template> 594 <template v-else> 595 <a href="@NORRIQ.Common8.Razor.Navigation.GetUrlByNavigationTag("service-contact")" style="z-index:10;">@Translate(asyncPrefix + "Contact Service", "Contact Service")</a> 596 </template> 597 </p> 598 </template> 599 @*</div>*@ 600 <p class="stock in-stock" v-if="!loading && price && hasStock && !isB2C"> 601 <link itemprop="availability" href="http://schema.org/InStock" /> 602 @Translate(asyncPrefix + "In Stock", "In Stock") ({{ productStockAmount }}) 603 </p> 604 <p class="stock in-stock" v-if="!loading && price && hasStock && isB2C"> 605 <link itemprop="availability" href="http://schema.org/InStock" /> 606 @Translate(asyncPrefix + "In Stock", "In Stock") 607 </p> 608 </template> 609 <template v-if="!onlyStock && !isB2C"> 610 <div v-if="!loading && price" class="price-settings"> 611 <div class="price"> 612 <p :class="'unit-price ' + classType" itemprop="priceCurrency" :content="price.unitPrice?.currencyKey"> 613 <span itemprop="price" :content="unitPrice">{{ netUnitPriceString | currency }}</span> 614 </p> 615 @if (Pageview.User != null) 616 { 617 <template v-if="savingsPercentage != 0"> 618 <p class="list-price">{{ defaultUnitPriceString | currency }}</p> 619 </template> 620 621 } 622 </div> 623 @if (Pageview.User != null) 624 { 625 <template v-if="savingsPercentage != 0"> 626 <div class="ml-4"> 627 <span class="badge size-2 bg-success text-white">{{savingsPercentage}}%</span> 628 </div> 629 </template> 630 } 631 </div> 632 </template> 633 </div> 634 </script> 635 636 637 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel> 638 639 @{ 640 string relatedProductsPrefix = "Related Products "; 641 } 642 643 644 <script type="text/x-template" id="related-products-template"> 645 646 <section class="related plp grid-view"> 647 <header> 648 <h2 class="text-center"> 649 {{header}} 650 </h2> 651 </header> 652 <div class="related-products products"> 653 <article v-for="product in relatedProducts"> 654 <a :href="product.url" class="position-relative"> 655 <figure class="d-flex justify-content-center align-items-center border p-2" style="min-height:1px;"> 656 <img :src="imageUrl(product)" 657 :alt="product.name" 658 itemprop="image" 659 class="img-fluid" /> 660 </figure> 661 <header class="flow-1"> 662 <h1 class="font-size-lg text-dark">{{product.name}}</h1> 663 <p class="font-size-xs text-800">@Translate(relatedProductsPrefix + "Product Number", "Product Number") {{product.number}}</p> 664 <async-price class-type="asyncprice-plp" 665 :default-price-without-vat="product.price?.priceWithoutVat" 666 :default-price-with-vat="product.price?.priceWithVat" 667 :product-id="product.number" 668 :variant-id="product.variantId" 669 unit-of-measure="" 670 only-stock="true" 671 :dw-stock-amount="product.stockAmount" 672 :out-of-stock-text="product.outOfStockText"> 673 </async-price> 674 </header> 675 </a> 676 <footer class="flow-3"> 677 <async-price class-type="asyncprice-plp" 678 :default-price-without-vat="product.price?.priceWithoutVat" 679 :default-price-with-vat="product.price?.priceWithVat" 680 :product-id="product.number" 681 :variant-id="product.variantId" 682 unit-of-measure="" 683 only-price="true" 684 :dw-stock-amount="product.stockAmount" 685 :out-of-stock-text="product.outOfStockText"> 686 </async-price> 687 <div class="buy-settings position-relative"> 688 @if (Pageview.User != null) 689 { 690 <favorite-lists :is-favorite-mode="@NORRIQ.Common8.Razor.Navigation.GetPageIdByNavigationTag("favorites") == @Pageview.ID" 691 :product="product" 692 button-class="border btn-square mr-2"></favorite-lists> 693 } 694 <add-to-basket-simple class="d-flex align-items-center" 695 :product-id="product.id" 696 :variant-id="product.variantId" 697 :unit-of-measure="product.defaultUnitId" 698 :language-id="product.languageId" 699 button-class="btn-primary px-3 ml-2" 700 input-class="text-center" 701 :product-name="product.name" 702 :product-number="product.number" 703 :price="product.price" 704 button-label=""> 705 </add-to-basket-simple> 706 </div> 707 @*<add-to-basket-button-only product-id="product.id" 708 variant-id="product.variantId" 709 unit-of-measure="STK" 710 button-class="btn-primary" 711 input-class="form-control-lg text-center px-1" 712 button-label="@Translate(relatedProductsPrefix + "Add to basket", "Add to basket")"> 713 </add-to-basket-button-only>*@ 714 </footer> 715 </article> 716 </div> 717 </section> 718 </script> 719 720 721 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel> 722 723 <script type="text/x-template" id="pagination-template"> 724 @{ 725 string paginationPrefix = "Pagination "; 726 } 727 <footer class="d-flex justify-content-center align-items-center pt-4"> 728 <nav aria-label="@Translate(paginationPrefix + "Produktliste pagination", "Produktliste pagination")"> 729 <ul class="pagination"> 730 <li :class="['page-item', currentPage == 1 ? 'disabled' : '' ]"> 731 <a class="btn btn-square btn-sm" v-on:click="togglePrevPage()" aria-label="@Translate(paginationPrefix + "Previous Page", "Previous Page")" v-bind:aria-disabled="currentPage > 1 ? 'true' : null"> 732 <b-icon-chevron-left></b-icon-chevron-left> 733 </a> 734 </li> 735 <template v-if="hasGroupId"> 736 <li class="btn btn-sm " v-for="n in totalPages" :key="n" :class="(n == currentPage ? ' is-active' : '')"> 737 <a v-on:click="togglePage(n)" v-bind:aria-current="(n == currentPage ? 'aria-page' : '')" class="page-link"> 738 {{n}} 739 </a> 740 </li> 741 </template> 742 <template v-else> 743 <li class="btn btn-square btn-sm "> 744 <span class="page-label"> 745 {{currentPage}} 746 </span> 747 </li> 748 <li class="btn btn-sm btn-square"> 749 <span class="page-label"> 750 @Translate("of") 751 </span> 752 </li> 753 <li class="btn btn-square btn-sm "> 754 <span class="page-label"> 755 {{totalPages}} 756 </span> 757 </li> 758 </template> 759 <li :class="'page-item' + (currentPage >= totalPages ? ' disabled' : '')"> 760 <a v-on:click="toggleNextPage()" aria-label="@Translate(paginationPrefix + "Next Page", "Next Page")" class="btn btn-square btn-sm" v-bind:aria-disabled="totalPages > currentPage ? 'true' : null"> 761 <b-icon-chevron-right></b-icon-chevron-right> 762 </a> 763 </li> 764 </ul> 765 </nav> 766 </footer> 767 </script> 768 769 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel> 770 @{ 771 //This template contains everything for the favoritelist items. 772 string favoriteListPrefix = "FavoriteList "; 773 } 774 <span id="favoritelistitem_confirm_delete_on_all" style="display: none; visibility: hidden">@Translate(favoriteListPrefix + "_confirm_delete_all", "Er du sikker på at du vil fjerne produktet {0} fra alle lister ?")</span> 775 776 <script type="text/x-template" id="favorite-item-template"> 777 @*<div class="basic_favoriteitem">*@ 778 <div class="custom-control custom-checkbox"> 779 <input type="checkbox" :checked="isActive" v-on:change="toggleItem()" :id="'fav-' +favoriteList.id" class="custom-control-input"/> 780 <label :for="'fav-' + favoriteList.id" class="custom-control-label"> 781 {{favoriteList.name}} 782 </label> 783 784 @*<input type="checkbox" :value="favoriteList.id" :checked="isItemAddedToThisList(favoriteList)" v-on:change="toggleItem($event, favoriteList.id)" class="form-check-input" /> 785 <label :for="'fav-' + favoriteList.id" class="form-check-label"> 786 {{favoriteList.name}} 787 </label>*@ 788 </div> 789 @*</div>*@ 790 </script> 791 792 <script type="text/x-template" id="favorite-list-template"> 793 <div class="fav"> 794 <button :aria-controls="'favorite' + product.id" :class="['btn', buttonClass]" aria-label="@Translate(" Favorite", "Favorite" )" v-on:click="toggleItem()"> 795 <template v-if="isActive"> 796 <b-icon-star-fill class="font-size-lg"></b-icon-star-fill> 797 </template> 798 <template v-else> 799 <b-icon-star></b-icon-star> 800 </template> 801 </button> 802 <div class="fav-overlay" v-autoClose.nonPath="closeToggle" :id="'favorite' + product.id"> 803 <div class="fav-inwrap" v-if="showingMenu"> 804 <template v-if="loading"> 805 <div class="text-center"> 806 <span class="spinner-md-default"></span> 807 </div> 808 </template> 809 <div class="flow-3" v-if="!loading"> 810 <h5 class="m-0">@Translate(favoriteListPrefix + "Favoritliste", "Favoritliste")</h5> 811 <template v-if="favoriteLists.length > '0'"> 812 <p class="font-size-sm text-600"> 813 @Translate(favoriteListPrefix + "Tilføj eller fjern markering.", "Tilføj eller fjern markering.") 814 </p> 815 <div class="flow-2 pb-3 border-bottom"> 816 <favorite-item v-for="favoriteList in favoriteLists" :favorite-list="favoriteList" :product="product" :key="favoriteList.id" /> 817 </div> 818 <div class="custom-control custom-checkbox"> 819 <input type="checkbox" v-model="addNewList" id="addNewListCheckbox" class="custom-control-input" /> 820 <label for="addNewListCheckbox" class="custom-control-label"> 821 @Translate(favoriteListPrefix + "Ny favoritliste", "Ny favoritliste") 822 </label> 823 </div> 824 <div v-if="addNewList" class="d-flex align-items-center"> 825 <label for="addNewListNameInput" class="sr-only">@Translate(favoriteListPrefix + "Navn", "Navn")</label> 826 <input type="text" id="addNewListNameInput" v-model="addNewListNameInput" class="form-control new-list-name-input" placeholder="@Translate(favoriteListPrefix + "Navn", "Navn")" v-on:keyup.enter="saveAsNewList" /> 827 <button v-on:click="saveAsNewList" class="btn btn-dark ml-2 px-3">@Translate(favoriteListPrefix + "Gem", "Gem")</button> 828 </div> 829 </template> 830 <template v-else> 831 <p>@Translate(favoriteListPrefix + "NoFavoritliste", "Du har endnu ingen favoritlister, angiv navn for at oprette en.")</p> 832 <div class="d-flex align-items-center"> 833 <label for="addNewListNameInput" class="sr-only">@Translate(favoriteListPrefix + "Navn", "Navn")</label> 834 <input type="text" id="addNewListNameInput" v-model="addNewListNameInput" class="form-control new-list-name-input" placeholder="@Translate(favoriteListPrefix + "Navn", "Navn")" v-on:keyup.enter="saveAsNewList" /> 835 <button v-on:click="saveAsNewList" class="btn btn-dark ml-2 px-3">@Translate(favoriteListPrefix + "Gem", "Gem")</button> 836 </div> 837 </template> 838 839 </div> 840 </div> 841 </div> 842 </div> 843 </script> 844 845 <script src="@NORRIQ.Common8.Razor.TimestampSource.GetSourceWithTimestamp("/Files/dist/scripts/bundle.min.js")"></script> 846 @{ 847 var user = NORRIQ.Universal.Identity.Dw.UserViewModel.GetCurrentUser<NORRIQ.Universal.Identity.Dw.UserViewModel>(); 848 var userJson = JsonConvert.SerializeObject(user); 849 var currency = Pageview.User?.Currency ?? Pageview.Area.EcomCurrencyId; 850 } 851 <script> 852 AppStart.VueProvider.init({ 853 webApiUrl: '@System.Web.Configuration.WebConfigurationManager.AppSettings["WebApiUrl"]', 854 currencyCode: '@currency', 855 locale: '@Pageview.Area.Culture', 856 currencyLeft: true, 857 currencySpacing: true, 858 currencySymbol: '@currency', 859 currencyDecimalSeparator: ',', 860 currencyGroupSeparator: '.', 861 currencyDecimalDigits: 2, 862 dateFormatShort: '@Pageview.Area.Dateformat', 863 user: @userJson 864 }); 865 </script> 866 <script append="replace"></script> 867 </body> 868 </html> 869