Error executing template "Designs/SermanTipsmark/_parsed/Basic_News.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_d23a8ca2cfb34378bdc2ac702add9e08.Execute() in C:\Solutions\SermanTipsmark\Staging\Web\Files\Templates\Designs\SermanTipsmark\_parsed\Basic_News.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.Frontend; 219 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel> 220 221 @Title("Page") 222 @Description("Default page template") 223 @if (Pageview.IsCurrentUserAllowed) 224 { 225 string columns = !string.IsNullOrEmpty(Model.Item.GetValue<ListViewModel>("Columns").SelectedValue) ? Model.Item.GetValue<ListViewModel>("Columns").SelectedValue : "d-grid-12"; 226 //string width = !string.IsNullOrEmpty(Model.Item.GetValue<ListViewModel>("Width").SelectedValue) ? Model.Item.GetValue<ListViewModel>("Width").SelectedValue : "container-5"; 227 <main class="d-block"> 228 <nav class="page-nav bg-200"> 229 <div class="container d-flex justify-content-start align-items-center"> 230 <button type="button" 231 class="btn btn-sidebar btn-square border rounded btn-sm mr-3" 232 v-b-toggle.sidebar-navigation 233 aria-label="@Translate("Toggle sidebar", "Toogle Sidebar")"> 234 <span class="arrow-left"></span> 235 </button> 236 @RenderNavigation(new { Template = "basic_Breadcrumb.xslt", Expandmode = "all", StartLevel = 1, EndLevel = 5 }) 237 </div> 238 </nav> 239 @if (Model.Item.GetFile("TopImage") != null) 240 { 241 <figure class="container"> 242 <img src="@Model.Item.GetFile("TopImage").Path" 243 alt="@Model.Item.GetString("Title")" 244 class="img-fluid" 245 loading="lazy" /> 246 </figure> 247 } 248 <div class="container py-4"> 249 <section class="layout"> 250 251 <header class="d-flex justify-content-between align-items-center pb-4"> 252 <h1>@Model.Item.GetString("Title")</h1> 253 </header> 254 <div class="@columns"> 255 @Model.Placeholder("Content", "Content", "unwrap:true;default:true") 256 </div> 257 </section> 258 </div> 259 </main> 260 } 261 262 <footer class="basic_footer py-4"> 263 @{ 264 var imageLinks = Model.Area.Item.GetItems("ImageLinks").Where(s => s.GetFile("Image") != null); 265 } 266 <div class="container d-grid-3-3-3-3"> 267 @if (!string.IsNullOrEmpty(Model.Area.Item.GetString("FooterOneTitle")) && !string.IsNullOrEmpty(Model.Area.Item.GetString("FooterOneText"))) 268 { 269 <div class="basic_footer-box mt-0"> 270 <b-button variant="footer" v-b-toggle.footer-one> 271 @Model.Area.Item.GetString("FooterOneTitle") 272 <span class="plus-minus"></span> 273 </b-button> 274 <b-collapse id="footer-one"> 275 <div class="flow-2 font-size-sm"> 276 @Model.Area.Item.GetString("FooterOneText") 277 </div> 278 </b-collapse> 279 </div> 280 } 281 @if (!string.IsNullOrEmpty(Model.Area.Item.GetString("FooterTwoTitle")) && !string.IsNullOrEmpty(Model.Area.Item.GetString("FooterTwoText"))) 282 { 283 <div class="basic_footer-box mt-0"> 284 <b-button variant="footer" v-b-toggle.footer-two> 285 @Model.Area.Item.GetString("FooterTwoTitle") 286 <span class="plus-minus"></span> 287 </b-button> 288 <b-collapse id="footer-two"> 289 <div class="flow-2 font-size-sm"> 290 @Model.Area.Item.GetString("FooterTwoText") 291 </div> 292 </b-collapse> 293 </div> 294 } 295 @if (!string.IsNullOrEmpty(Model.Area.Item.GetString("FooterThreeTitle")) && !string.IsNullOrEmpty(Model.Area.Item.GetString("FooterThreeText"))) 296 { 297 <div class="basic_footer-box mt-0"> 298 <b-button variant="footer" v-b-toggle.footer-three> 299 @Model.Area.Item.GetString("FooterThreeTitle") 300 <span class="plus-minus"></span> 301 </b-button> 302 <b-collapse id="footer-three"> 303 <div class="flow-2 font-size-sm"> 304 @Model.Area.Item.GetString("FooterThreeText") 305 </div> 306 </b-collapse> 307 </div> 308 } 309 @if (!string.IsNullOrEmpty(Model.Area.Item.GetString("FooterFourTitle")) && !string.IsNullOrEmpty(Model.Area.Item.GetString("FooterFourText"))) 310 { 311 <div class="basic_footer-box mt-0"> 312 <b-button variant="footer" v-b-toggle.footer-four> 313 @Model.Area.Item.GetString("FooterFourTitle") 314 <span class="plus-minus"></span> 315 </b-button> 316 <b-collapse id="footer-four"> 317 <div class="flow-2 font-size-sm"> 318 @Model.Area.Item.GetString("FooterFourText") 319 </div> 320 </b-collapse> 321 </div> 322 } 323 </div> 324 325 @if (!string.IsNullOrEmpty(Model.Area.Item.GetString("FooterCopyright")) || imageLinks != null && imageLinks.Any()) 326 { 327 328 <div class="basic_footer-sub container pt-4 d-flex align-items-center"> 329 @if (!string.IsNullOrEmpty(Model.Area.Item.GetString("FooterCopyright"))) 330 { 331 <p class="font-size-xs"> 332 &copy; @DateTime.Now.Year @Model.Area.Item.GetString("FooterCopyright") 333 </p> 334 } 335 @if (imageLinks != null && imageLinks.Any()) 336 { 337 <div class="basic_footer-imagelinks d-flex align-items-center"> 338 @foreach (var item in imageLinks) 339 { 340 string target = item.GetString("Url").Contains("http") ? "_blank" : "_self"; 341 string rel = item.GetString("Url").Contains("http") ? "noreferrer noopener" : ""; 342 <a href="@item.GetString("Url")" class="d-inline-flex align-items-center p-1" rel="@rel" target="@target" title="@item.GetString("Title")"> 343 <img src="@item.GetFile("Image").Path" class="img-fluid" width="32" alt="@item.GetString("Title")" /> 344 </a> 345 } 346 </div> 347 } 348 </div> 349 } 350 </footer> 351 </div> 352 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 353 354 <script type="text/x-template" id="cart-icon-template"> 355 @{ 356 string cartIconPrefix = "Minicart "; 357 } 358 <a :href="cartlink" class="btn btn-square"> 359 <b-icon-cart3 font-scale="1.65"></b-icon-cart3> 360 <span class="sr-only">@Translate(cartIconPrefix + "Checkout", "Checkout")</span> 361 <span v-if="!cartEmpty" class="cart-quantity d-flex align-items-center justify-content-center">{{quantity}}</span> 362 </a> 363 </script> 364 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel> 365 366 <script type="text/x-template" id="basic-facet-filter-template"> 367 @{ 368 string basicFacetPrefix = "Filter "; 369 } 370 <div v-if="!queryLoading && !error && facetFilters" class="facets" id="sidebar-filter"> 371 372 373 374 <div class="facet-collapse" v-if="HasActiveFilter()"> 375 <p id="selected-filter-label" class="btn btn-collapse"> 376 @Translate(basicFacetPrefix + "Active", "Active") 377 </p> 378 <div class="pb-3 flow-2" aria-labelledby="selected-filter-label"> 379 <template v-for="facetFilter in facetFilters"> 380 <div v-for="option in SelectedOptions(facetFilter)" class="custom-control"> 381 <input type="checkbox" 382 :id="'Selected-' + facetFilter.name + '-' + option.name" 383 :name="facetFilter.name" 384 :value="option.value" 385 :v-model="option.selected" 386 :checked="option.selected" 387 v-on:click="ToggleFilter(facetFilter.queryParameter,option)" 388 class="custom-control-input" /> 389 <label :for="'Selected-' + facetFilter.name + '-' + option.name" class="custom-facet-label"> 390 <b-icon-x-circle-fill></b-icon-x-circle-fill> 391 <span> 392 {{facetFilter.name}}: {{option.label}} 393 </span> 394 </label> 395 </div> 396 </template> 397 </div> 398 </div> 399 <div class="facet-collapse" v-for="(facetFilter, index) in facetFilters"> 400 <b-button variant="collapse" v-b-toggle="'filter-group-' + facetFilter.name.replace(/\s/g, '').toLowerCase()"> 401 <span>{{facetFilter.name}}</span> 402 <span class="arrow-down"></span> 403 </b-button> 404 <b-collapse :id="'filter-group-' + facetFilter.name.replace(/\s/g, '').toLowerCase()" :visible="ShowGroupIfSelected(facetFilter.options, index)"> 405 <div class="py-3 flow-2"> 406 <template v-if="facetFilter.options.length > 5"> 407 <div v-for="option in facetFilter.options.slice(0, 5)" class="custom-control custom-checkbox"> 408 <input type="checkbox" class="custom-control-input" 409 :id="'UnSelected-' + facetFilter.name + '-' + option.name" 410 :name="facetFilter.name" 411 :value="option.value" 412 :v-model="option.selected" 413 :checked="option.selected" 414 v-on:click="ToggleFilter(facetFilter.queryParameter,option)" /> 415 <label :for="'UnSelected-' + facetFilter.name + '-' + option.name" class="custom-control-label"> 416 {{option.label}}<span class="count">({{option.count}})</span> 417 </label> 418 </div> 419 <b-collapse class="basic_filter-expand flow-2" :id="'filter-expand-' + facetFilter.name.replace(/\s/g, '').toLowerCase()" :visible="ShowMoreIfSelected(facetFilter.options, index)"> 420 <div v-for="option in facetFilter.options.slice(5)" class="custom-control custom-checkbox facet-option"> 421 <input type="checkbox" class="custom-control-input" 422 :id="'UnSelected-' + facetFilter.name + '-' + option.name" 423 :name="facetFilter.name" 424 :value="option.value" 425 :v-model="option.selected" 426 :checked="option.selected" 427 v-on:click="ToggleFilter(facetFilter.queryParameter,option)" /> 428 <label :for="'UnSelected-' + facetFilter.name + '-' + option.name" class="custom-control-label"> 429 {{option.label}} <span class="count">({{option.count}})</span> 430 </label> 431 </div> 432 </b-collapse> 433 <a v-b-toggle="'filter-expand-' + facetFilter.name.replace(/\s/g, '').toLowerCase()" class="btn btn-inline" v-if="facetFilter.options.length > 5"> 434 <span class="plus-minus"></span> 435 <span class="show-more">@Translate(basicFacetPrefix + "show more", "show more")</span> 436 <span class="show-less">@Translate(basicFacetPrefix + "show less", "show less")</span> 437 </a> 438 </template> 439 <template v-else> 440 <div v-for="option in facetFilter.options" class="custom-control custom-checkbox"> 441 <input type="checkbox" class="custom-control-input" 442 :id="'UnSelected-' + facetFilter.name + '-' + option.name" 443 :name="facetFilter.name" 444 :value="option.value" 445 :v-model="option.selected" 446 :checked="option.selected" 447 v-on:click="ToggleFilter(facetFilter.queryParameter,option)" /> 448 <label :for="'UnSelected-' + facetFilter.name + '-' + option.name" class="custom-control-label"> 449 {{option.label}} 450 </label> 451 </div> 452 </template> 453 </div> 454 </b-collapse> 455 </div> 456 457 </div> 458 </script> 459 460 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel> 461 <script type="text/x-template" id="add-to-basket-simple-template"> 462 @{ 463 string addToBasketSimplePrifix = "BuyButton "; 464 } 465 <div v-if="!isB2C"> 466 <label :for="'quantity-' + productId" class="sr-only">@Translate(addToBasketSimplePrifix + "Quantity", "Quantity")</label> 467 <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)"> 468 <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")"> 469 <slot> 470 <b-icon-cart3></b-icon-cart3> 471 <span v-if="buttonLabel">{{buttonLabel}}</span> 472 </slot> 473 </button> 474 </div> 475 </script> 476 477 <script type="text/x-template" id="quick-add-template"> 478 @{ 479 string quickAddPrifix = "BuyButton "; 480 } 481 <div v-if="!isB2C" v-bind:class="[{added: IsAdded}, {adding: IsAdding}]"> 482 <label for="quantity">@Translate(quickAddPrifix + "Quantity", "Quantity")</label> 483 <input class="form-control" type="number" id="quantity" name="quantity" v-model="quantity" autocomplete="off"> 484 </div> 485 </script> 486 487 <script type="text/x-template" id="add-to-basket-button-only-template"> 488 @{ 489 string addToBasketPrefix = "BuyButton "; 490 } 491 <div v-if="!isB2C"> 492 <button :class="['btn', buttonClass, {added: IsAdded}, {adding: IsAdding}]" v-on:click="addToBasket()"> 493 <slot> 494 <b-icon-cart3></b-icon-cart3> 495 <span>@Translate(addToBasketPrefix + "Add to basket", "Add to basket")</span> 496 </slot> 497 </button> 498 </div> 499 </script> 500 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel> 501 <script type="text/x-template" id="async-price-template"> 502 @{ 503 string asyncPrefix = "Async "; 504 } 505 <div :class="'async' + (loading && !onlyStock ? ' loading text-center' : '')"> 506 <template v-if="error"> 507 <p class="text-danger font-weight-bold">{{error}}</p> 508 </template> 509 <template v-if="!onlyPrice && !error"> 510 @*<div class="d-flex align-items-center flex-wrap font-size-xs" >*@ 511 <template v-if="!loading && price && !hasStock"> 512 <p class="stock out-of-stock"> 513 <link itemprop="availability" href="http://schema.org/SoldOut" /> 514 @Translate(asyncPrefix + "Out Of Stock", "Out Of Stock") 515 </p> 516 <p class="text-muted font-size-xs"> 517 <template v-if="outOfStockText && outOfStockText !=''"> 518 {{outOfStockText}} 519 </template> 520 <template v-else> 521 <a href="@NORRIQ.Common8.Razor.Navigation.GetUrlByNavigationTag("service-contact")" style="z-index:10;">@Translate(asyncPrefix + "Contact Service", "Contact Service")</a> 522 </template> 523 </p> 524 </template> 525 @*</div>*@ 526 <p class="stock in-stock" v-if="!loading && price && hasStock && !isB2C"> 527 <link itemprop="availability" href="http://schema.org/InStock" /> 528 @Translate(asyncPrefix + "In Stock", "In Stock") ({{ productStockAmount }}) 529 </p> 530 <p class="stock in-stock" v-if="!loading && price && hasStock && isB2C"> 531 <link itemprop="availability" href="http://schema.org/InStock" /> 532 @Translate(asyncPrefix + "In Stock", "In Stock") 533 </p> 534 </template> 535 <template v-if="!onlyStock && !isB2C"> 536 <div v-if="!loading && price" class="price-settings"> 537 <div class="price"> 538 <p :class="'unit-price ' + classType" itemprop="priceCurrency" :content="price.unitPrice?.currencyKey"> 539 <span itemprop="price" :content="unitPrice">{{ netUnitPriceString | currency }}</span> 540 </p> 541 @if (Pageview.User != null) 542 { 543 <template v-if="savingsPercentage != 0"> 544 <p class="list-price">{{ defaultUnitPriceString | currency }}</p> 545 </template> 546 547 } 548 </div> 549 @if (Pageview.User != null) 550 { 551 <template v-if="savingsPercentage != 0"> 552 <div class="ml-4"> 553 <span class="badge size-2 bg-success text-white">{{savingsPercentage}}%</span> 554 </div> 555 </template> 556 } 557 </div> 558 </template> 559 </div> 560 </script> 561 562 563 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel> 564 565 @{ 566 string relatedProductsPrefix = "Related Products "; 567 } 568 569 570 <script type="text/x-template" id="related-products-template"> 571 572 <section class="related plp grid-view"> 573 <header> 574 <h2 class="text-center"> 575 {{header}} 576 </h2> 577 </header> 578 <div class="related-products products"> 579 <article v-for="product in relatedProducts"> 580 <a :href="product.url" class="position-relative"> 581 <figure class="d-flex justify-content-center align-items-center border p-2" style="min-height:1px;"> 582 <img :src="imageUrl(product)" 583 :alt="product.name" 584 itemprop="image" 585 class="img-fluid" /> 586 </figure> 587 <header class="flow-1"> 588 <h1 class="font-size-lg text-dark">{{product.name}}</h1> 589 <p class="font-size-xs text-800">@Translate(relatedProductsPrefix + "Product Number", "Product Number") {{product.number}}</p> 590 <async-price class-type="asyncprice-plp" 591 :default-price-without-vat="product.price?.priceWithoutVat" 592 :default-price-with-vat="product.price?.priceWithVat" 593 :product-id="product.number" 594 :variant-id="product.variantId" 595 unit-of-measure="" 596 only-stock="true" 597 :dw-stock-amount="product.stockAmount" 598 :out-of-stock-text="product.outOfStockText"> 599 </async-price> 600 </header> 601 </a> 602 <footer class="flow-3"> 603 <async-price class-type="asyncprice-plp" 604 :default-price-without-vat="product.price?.priceWithoutVat" 605 :default-price-with-vat="product.price?.priceWithVat" 606 :product-id="product.number" 607 :variant-id="product.variantId" 608 unit-of-measure="" 609 only-price="true" 610 :dw-stock-amount="product.stockAmount" 611 :out-of-stock-text="product.outOfStockText"> 612 </async-price> 613 <div class="buy-settings position-relative"> 614 @if (Pageview.User != null) 615 { 616 <favorite-lists :is-favorite-mode="@NORRIQ.Common8.Razor.Navigation.GetPageIdByNavigationTag("favorites") == @Pageview.ID" 617 :product="product" 618 button-class="border btn-square mr-2"></favorite-lists> 619 } 620 <add-to-basket-simple class="d-flex align-items-center" 621 :product-id="product.id" 622 :variant-id="product.variantId" 623 :unit-of-measure="product.defaultUnitId" 624 :language-id="product.languageId" 625 button-class="btn-primary px-3 ml-2" 626 input-class="text-center" 627 :product-name="product.name" 628 :product-number="product.number" 629 :price="product.price" 630 button-label=""> 631 </add-to-basket-simple> 632 </div> 633 @*<add-to-basket-button-only product-id="product.id" 634 variant-id="product.variantId" 635 unit-of-measure="STK" 636 button-class="btn-primary" 637 input-class="form-control-lg text-center px-1" 638 button-label="@Translate(relatedProductsPrefix + "Add to basket", "Add to basket")"> 639 </add-to-basket-button-only>*@ 640 </footer> 641 </article> 642 </div> 643 </section> 644 </script> 645 646 647 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel> 648 649 <script type="text/x-template" id="pagination-template"> 650 @{ 651 string paginationPrefix = "Pagination "; 652 } 653 <footer class="d-flex justify-content-center align-items-center pt-4"> 654 <nav aria-label="@Translate(paginationPrefix + "Produktliste pagination", "Produktliste pagination")"> 655 <ul class="pagination"> 656 <li :class="['page-item', currentPage == 1 ? 'disabled' : '' ]"> 657 <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"> 658 <b-icon-chevron-left></b-icon-chevron-left> 659 </a> 660 </li> 661 <template v-if="hasGroupId"> 662 <li class="btn btn-sm " v-for="n in totalPages" :key="n" :class="(n == currentPage ? ' is-active' : '')"> 663 <a v-on:click="togglePage(n)" v-bind:aria-current="(n == currentPage ? 'aria-page' : '')" class="page-link"> 664 {{n}} 665 </a> 666 </li> 667 </template> 668 <template v-else> 669 <li class="btn btn-square btn-sm "> 670 <span class="page-label"> 671 {{currentPage}} 672 </span> 673 </li> 674 <li class="btn btn-sm btn-square"> 675 <span class="page-label"> 676 @Translate("of") 677 </span> 678 </li> 679 <li class="btn btn-square btn-sm "> 680 <span class="page-label"> 681 {{totalPages}} 682 </span> 683 </li> 684 </template> 685 <li :class="'page-item' + (currentPage >= totalPages ? ' disabled' : '')"> 686 <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"> 687 <b-icon-chevron-right></b-icon-chevron-right> 688 </a> 689 </li> 690 </ul> 691 </nav> 692 </footer> 693 </script> 694 695 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel> 696 @{ 697 //This template contains everything for the favoritelist items. 698 string favoriteListPrefix = "FavoriteList "; 699 } 700 <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> 701 702 <script type="text/x-template" id="favorite-item-template"> 703 @*<div class="basic_favoriteitem">*@ 704 <div class="custom-control custom-checkbox"> 705 <input type="checkbox" :checked="isActive" v-on:change="toggleItem()" :id="'fav-' +favoriteList.id" class="custom-control-input"/> 706 <label :for="'fav-' + favoriteList.id" class="custom-control-label"> 707 {{favoriteList.name}} 708 </label> 709 710 @*<input type="checkbox" :value="favoriteList.id" :checked="isItemAddedToThisList(favoriteList)" v-on:change="toggleItem($event, favoriteList.id)" class="form-check-input" /> 711 <label :for="'fav-' + favoriteList.id" class="form-check-label"> 712 {{favoriteList.name}} 713 </label>*@ 714 </div> 715 @*</div>*@ 716 </script> 717 718 <script type="text/x-template" id="favorite-list-template"> 719 <div class="fav"> 720 <button :aria-controls="'favorite' + product.id" :class="['btn', buttonClass]" aria-label="@Translate(" Favorite", "Favorite" )" v-on:click="toggleItem()"> 721 <template v-if="isActive"> 722 <b-icon-star-fill class="font-size-lg"></b-icon-star-fill> 723 </template> 724 <template v-else> 725 <b-icon-star></b-icon-star> 726 </template> 727 </button> 728 <div class="fav-overlay" v-autoClose.nonPath="closeToggle" :id="'favorite' + product.id"> 729 <div class="fav-inwrap" v-if="showingMenu"> 730 <template v-if="loading"> 731 <div class="text-center"> 732 <span class="spinner-md-default"></span> 733 </div> 734 </template> 735 <div class="flow-3" v-if="!loading"> 736 <h5 class="m-0">@Translate(favoriteListPrefix + "Favoritliste", "Favoritliste")</h5> 737 <template v-if="favoriteLists.length > '0'"> 738 <p class="font-size-sm text-600"> 739 @Translate(favoriteListPrefix + "Tilføj eller fjern markering.", "Tilføj eller fjern markering.") 740 </p> 741 <div class="flow-2 pb-3 border-bottom"> 742 <favorite-item v-for="favoriteList in favoriteLists" :favorite-list="favoriteList" :product="product" :key="favoriteList.id" /> 743 </div> 744 <div class="custom-control custom-checkbox"> 745 <input type="checkbox" v-model="addNewList" id="addNewListCheckbox" class="custom-control-input" /> 746 <label for="addNewListCheckbox" class="custom-control-label"> 747 @Translate(favoriteListPrefix + "Ny favoritliste", "Ny favoritliste") 748 </label> 749 </div> 750 <div v-if="addNewList" class="d-flex align-items-center"> 751 <label for="addNewListNameInput" class="sr-only">@Translate(favoriteListPrefix + "Navn", "Navn")</label> 752 <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" /> 753 <button v-on:click="saveAsNewList" class="btn btn-dark ml-2 px-3">@Translate(favoriteListPrefix + "Gem", "Gem")</button> 754 </div> 755 </template> 756 <template v-else> 757 <p>@Translate(favoriteListPrefix + "NoFavoritliste", "Du har endnu ingen favoritlister, angiv navn for at oprette en.")</p> 758 <div class="d-flex align-items-center"> 759 <label for="addNewListNameInput" class="sr-only">@Translate(favoriteListPrefix + "Navn", "Navn")</label> 760 <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" /> 761 <button v-on:click="saveAsNewList" class="btn btn-dark ml-2 px-3">@Translate(favoriteListPrefix + "Gem", "Gem")</button> 762 </div> 763 </template> 764 765 </div> 766 </div> 767 </div> 768 </div> 769 </script> 770 771 <script src="@NORRIQ.Common8.Razor.TimestampSource.GetSourceWithTimestamp("/Files/dist/scripts/bundle.min.js")"></script> 772 @{ 773 var user = NORRIQ.Universal.Identity.Dw.UserViewModel.GetCurrentUser<NORRIQ.Universal.Identity.Dw.UserViewModel>(); 774 var userJson = JsonConvert.SerializeObject(user); 775 var currency = Pageview.User?.Currency ?? Pageview.Area.EcomCurrencyId; 776 } 777 <script> 778 AppStart.VueProvider.init({ 779 webApiUrl: '@System.Web.Configuration.WebConfigurationManager.AppSettings["WebApiUrl"]', 780 currencyCode: '@currency', 781 locale: '@Pageview.Area.Culture', 782 currencyLeft: true, 783 currencySpacing: true, 784 currencySymbol: '@currency', 785 currencyDecimalSeparator: ',', 786 currencyGroupSeparator: '.', 787 currencyDecimalDigits: 2, 788 dateFormatShort: '@Pageview.Area.Dateformat', 789 user: @userJson 790 }); 791 </script> 792 <script append="replace"></script> 793 </body> 794 </html> 795