Error executing template "Designs/Tapas/eCom/Productlist/productlist_Default.cshtml"
System.NullReferenceException: Object reference not set to an instance of an object.
   at CompiledRazorTemplates.Dynamic.RazorEngine_3fcd0d9c23bd475da98ec1b05ce71e63.<>c__DisplayClass16_0.<RenderGroupLevelFilter>b__0(TextWriter __razor_helper_writer) in D:\dynamicweb.net\Solutions\millarco.staging\Files\Templates\Designs\Tapas\eCom\Productlist\productlist_Default.cshtml:line 1110
   at CompiledRazorTemplates.Dynamic.RazorEngine_3fcd0d9c23bd475da98ec1b05ce71e63.<>c__DisplayClass16_0.<RenderGroupLevelFilter>b__0(TextWriter __razor_helper_writer) in D:\dynamicweb.net\Solutions\millarco.staging\Files\Templates\Designs\Tapas\eCom\Productlist\productlist_Default.cshtml:line 1142
   at CompiledRazorTemplates.Dynamic.RazorEngine_3fcd0d9c23bd475da98ec1b05ce71e63.Execute() in D:\dynamicweb.net\Solutions\millarco.staging\Files\Templates\Designs\Tapas\eCom\Productlist\productlist_Default.cshtml:line 674
   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 RazorTemplateBase<RazorTemplateModel<Template>> 2 @using Dynamicweb.Rendering; 3 @using Dynamicweb.Environment; 4 5 @inherits RazorTemplateBase<RazorTemplateModel<Template>> 6 @using Dynamicweb.Rendering; 7 @using System.Text.RegularExpressions; 8 9 10 11 @helper renderProduct(bool showShopFunctionsAlternativeIfNotLoggedIn, LoopItem product, bool renderAs4Cols = false) 12 { 13 14 string productID = product.GetString("Ecom:Product.ID"); 15 string productNumber = product.GetString("Ecom:Product.Number"); 16 string mainProductID = product.GetString("Ecom:Product:Field.FirstwebMainProductID"); 17 string PrimaryProductPageId = Firstweb.Custom.CustomCode.Tapas.Context.AreaPages.GetPageId("productcatalog"); 18 19 string productLink = product.GetString("Ecom:Product.Link.Clean"); 20 21 if (!String.IsNullOrEmpty(PrimaryProductPageId)) 22 { 23 productLink = "/Default.aspx?id=" + PrimaryProductPageId + "&productid=" + productID; 24 } 25 26 string languageId = product.GetString("Ecom:Product.LanguageID"); 27 string variantId = product.GetString("Ecom:Product.VariantID"); 28 29 string productName = product.GetString("Ecom:Product.Name"); 30 string productShortDescription = product.GetString("Ecom:Product.ShortDescription"); 31 32 string nettoPrice = product.GetString("Firstweb:ErpPriceInfo.NettoPriceFormatted"); 33 int bruttoPrice = product.GetInteger("Firstweb:ErpPriceInfo.BruttoAmountFormattedNoSymbol"); 34 35 string availableAmount = product.GetString("Firstweb:ErpStockInfo.StockQuantity"); 36 string stockColor = product.GetString("Firstweb:ErpStockInfo.StockColor"); 37 bool priceAndStockFound = product.GetBoolean("Firstweb:ErpPriceInfo.PriceAndStockFound"); 38 bool priceFound = product.GetBoolean("Firstweb:ErpPriceInfo.PriceFound"); 39 bool hasQuantityPrices = product.GetBoolean("Firstweb:ErpPriceInfo.HasQuantityPrices"); 40 string RRPrice = product.GetString("Firstweb:ErpPriceInfo:Prices.RRPFormatted"); 41 string OutletPrice = product.GetString("Firstweb:ErpPriceInfo.NettoPriceFormatted"); 42 43 int productPackagingQuantity = product.GetInteger("Firstweb:ErpPriceInfo:ExtraInfos.PackagingSize"); 44 int defaultQuantity = productPackagingQuantity > 0 ? productPackagingQuantity : 1; 45 46 47 bool hasVariants = (product.GetLoop("VariantCombinations").Count() > 0); 48 49 //Images 50 List<Dynamicweb.Ecommerce.Products.Detail> productImages = Firstweb.Custom.CustomCode.Frontend.Helpers.ProductImages.GetProductImages(languageId, productID, variantId); 51 Dynamicweb.Ecommerce.Products.Detail primaryProductImage = productImages.FirstOrDefault(x=>x.IsDefault); //Tag you can use instead: product.GetString("Ecom:Product.ImageDefault.Clean"); 52 //check for valid default image 53 if (primaryProductImage == null) 54 { 55 primaryProductImage = new Dynamicweb.Ecommerce.Products.Detail { Value = "" }; 56 } 57 else if (primaryProductImage.Value == null) 58 { 59 primaryProductImage.Value = ""; 60 } 61 62 //Sorted: first by imagegroup then by sortorder 63 //@foreach (var productImage in productImages) 64 //{ 65 //productImage.Value; //This is the imagepath eks. /Images/products/R12155_10_2.jpg 66 //productImage.IsDefault; //If the image is default or not. 67 //} 68 69 string primaryProductImageUrl = "/admin/public/getimage.ashx?image=" + primaryProductImage.Value + "&altFmImage_path=/Files/Images/ecom/Products/no-image.jpg&width=250&height=150&Compression=90&Crop=5"; 70 if (String.IsNullOrEmpty(primaryProductImage.Value)) 71 { 72 primaryProductImageUrl = "/admin/public/getimage.ashx?image=/Files/Images/ecom/Products/no-image.jpg&width=250&height=150&Compression=90&Crop=5"; 73 } 74 75 //Other packagings 76 var otherPackagingProducts = Firstweb.Custom.CustomCode.Frontend.Helpers.OtherPackagingProducts.GetOtherPackagingProducts(mainProductID, false).Where(i => i.Id != productID); 77 var showOtherPackagingProducts = otherPackagingProducts.Count() > 0; 78 79 80 //Customer product number 81 //string customerProductNumber = Firstweb.Custom.CustomCode.Frontend.Helpers.CustomerProductNumbers.GetCustomerProductNumber(productID); 82 83 //OrderTemplate 84 int productInFavoritLists = product.GetInteger("Firstweb:Ecom:Product:OrderTemplate.InTemplates.Count"); 85 86 string orderLineId = product.GetString("Firstweb:OrderTemplate:Line.ID"); 87 string orderTemplateId = product.GetString("Firstweb:OrderTemplate:Line.OrderTemplateID"); 88 int orderLineQuantity = product.GetInteger("Firstweb:OrderTemplate:Line.Quantity"); 89 90 bool inFavourite = productInFavoritLists > 0 ? true : false; 91 string inFavouriteBoolJS = inFavourite.ToString().ToLower(); 92 93 bool isOrderTemplate = !String.IsNullOrEmpty(orderLineId); 94 95 string productPriceCacheKey = orderLineId != "" ? orderLineId : productNumber; 96 97 98 99 100 string stock = ""; 101 102 string addBorderCss = isOrderTemplate ? "border-1" : ""; 103 104 105 if (!priceAndStockFound) 106 { 107 stock = "asyncLoad"; 108 } 109 else 110 { 111 stock = availableAmount; 112 } 113 114 string WidthClass = renderAs4Cols ? "col-md-4 col-lg-3" : "col-md-4"; 115 bool ShowShopFunctions = Firstweb.Custom.CustomCode.Tapas.Context.Current.ShopFunctionsVisibility.ShowShopFunctions(); 116 string BrandLogo = "/admin/public/getimage.ashx?image=" + product.GetString("Ecom:Product:Field.FirstwebBrandLogo.Value.FullPath") + "&height=25&crop=5"; 117 string BrandName = product.GetString("Ecom:Product:Field.FirstwebBrand.Value.Clean"); 118 string AddingToCartText = Translate("Product.AddingToCart", "Tilføjer produkt"); 119 string PickListText = Translate("Ordertemplate.SelectList", "Vælg en liste"); 120 bool IsOutletShop = Firstweb.Custom.CustomCode.Frontend.Helpers.Millarco.IsOutletShop(); 121 122 123 <!-- ko viewModel: 'ProductViewModel'--> 124 <!-- ko initValue: {observable: ProductId, value:'@productID'}--><!-- /ko--> 125 <div class="col-xs-12 col-sm-6 @WidthClass price xs-m-b-2 asyncLoad" data-productid="@productNumber" data-productkey="@productPriceCacheKey" data-test="@PrimaryProductPageId"> 126 <div class="product-list-item bg-white"> 127 <a href="@productLink"> 128 <div class="brand-image"> 129 @if (!String.IsNullOrEmpty(product.GetString("Ecom:Product:Field.FirstwebBrandLogo.Value.FullPath"))) 130 { 131 <img src="@BrandLogo" alt="@BrandName" /> 132 } 133 </div> 134 <div class="product-image"> 135 <img src="@primaryProductImageUrl" alt="@productName" /> 136 </div> 137 <div class="product-info"> 138 <p class="product-number">@Translate("Product.NumberShort", "Varenr.") @productNumber</p> 139 <p class="product-name">@productName</p> 140 </div> 141 @if (ShowShopFunctions && !IsOutletShop) 142 { 143 <p class="product-price"> 144 <span class="wave"> 145 <span class="dot"></span> 146 <span class="dot"></span> 147 <span class="dot"></span> 148 </span> 149 <span class="price-load-async"></span> 150 </p> 151 <p class="unit-price">@Translate("Product.PricePer", "Pris pr.") <span class="js-unit-size"></span> @Translate("Product.Unit", "stk.")</p> 152 } 153 else if (IsOutletShop) 154 { 155 <p class="product-price"> 156 @nettoPrice 157 </p> 158 } 159 else if (ShowShopFunctions) 160 { 161 <p class="product-price"> 162 @RRPrice 163 </p> 164 } 165 </a> 166 @if (ShowShopFunctions) 167 { 168 <div class="add-to-cart-area"> 169 @if (isOrderTemplate) 170 { 171 <!-- ko initValue: {observable: Quantity, value:@orderLineQuantity}--><!-- /ko--> 172 } 173 else 174 { 175 <!-- ko initValue: {observable: Quantity, value:@defaultQuantity}--><!-- /ko--> 176 } 177 <input class="product-quantity js-product-quantity hide" type="number" name="quantity" data-bind="value: Quantity" /> 178 <div class="btn btn-primary green js-product-buy-btn hide" 179 data-bind="click: function() { $parent.addItemToCart(ProductId(), Quantity(), '', '', '@AddingToCartText') }" 180 data-productid="@productID"> 181 @Translate("Product.AddToCart", "TILFØJ TIL KURV") 182 </div> 183 <div class="not-in-stock-indicator js-not-in-stock-indicator width-100 is-centered hide"> 184 <p>@Translate("Product.NotInStock", "Ikke p&aring; lager")</p> 185 </div> 186 @if (!isOrderTemplate) 187 { 188 <div class="favorite-list-icon" data-toggle="modal" data-target="#modal-@productID" data-bind="with: OrderTemplateViewModel"> 189 <i class="fas fa-heart" data-bind=" 190 oninit: function() { IsInFavoriteList('@inFavourite'.toLowerCase()) }, 191 css : { showFavorite : ShowOrderTemplateDialog, showNewList : OrderTemplateShowNewList, active: IsInFavoriteList() == 'true' }, 192 visible: $root.User().IsLoggedIn(), 193 click: ToggleOrderTemplateDialog"> 194 </i> 195 </div> 196 <div class="modal fade" id="modal-@productID" tabindex="-1" role="dialog" data-bind="with: OrderTemplateViewModel"> 197 <!-- ko initValue: {observable: OrderTemplateRelationCount, value:'@productInFavoritLists'}--><!-- /ko--> 198 <!-- ko initValue: {observable: ShowInFavourite, value: @inFavouriteBoolJS}--><!-- /ko--> 199 <!-- ko initValue: {observable: ModalSelector, value: '#modal-@productID'}--><!-- /ko--> 200 <div class="modal-dialog" role="document"> 201 <div class="modal-content fav-list"> 202 203 <p class="favlist-header">@Translate("Ordertemplate.AddToExistingList", "Tilføj til eksisterende favoritliste")</p> 204 205 <div class="existing-lists"> 206 207 <select class="favField select-fix" 208 data-bind="options: OrderTemplateList, 209 optionsCaption: '@PickListText', 210 optionsText: function(item) { return item.Value.Name() + ' (' + item.Value.Count() + ')' }, 211 value: OrderTemplateSelectedList"></select> 212 213 <input class="product-quantity" type="number" name="quantity" data-bind="textInput: OrderTemplateQuantity" /> 214 215 <div class="btn btn-primary" 216 data-bind="click: function() { 217 OrderTemplateShowNewList() 218 ? CreateNewOrderTemplateList('@productID') 219 : AddProductToOrderTemplate('@productID' , OrderTemplateQuantity()) 220 }"> 221 @Translate("Ordertemplate.AddToList", "Tilføj") 222 </div> 223 224 </div> 225 226 <p class="or-text">@Translate("Ordertemplate.OrNewList", "eller...")</p> 227 228 <p class="favlist-header">@Translate("Ordertemplate.AddToNewList", "Tilføj til ny favoritliste")</p> 229 230 <form id="EditForm-@productID" 231 name="EditForm"> 232 <label class="xs-m-b-1" for="name">@Translate("Ordertemplate.ListName", "Favoritliste navn")</label> 233 <div class="new-list"> 234 <input type="text" 235 name="name" 236 _id="name" 237 data-bind="textInput: OrderTemplateNewListName" 238 autofocus 239 autocomplete="off" /> 240 241 <input class="product-quantity" type="number" name="quantity" data-bind="textInput: OrderTemplateNewListQuantity" /> 242 243 <button type="submit" 244 class="btn btn-primary" 245 _id="btnSave" 246 data-bind="click: function() { CreateNewOrderTemplateList('@productID', OrderTemplateNewListQuantity()) }"> 247 @Translate("Ordertemplate.SaveToNewList", "Tilføj til ny favoritliste") 248 </button> 249 </div> 250 </form> 251 252 </div> 253 </div> 254 </div> 255 } 256 else 257 { 258 <div class="favorite-list-icon" data-bind="with: OrderTemplateViewModel"> 259 <!-- ko initValue: {observable: OrderTemplateId, value:'@orderTemplateId'}--><!-- /ko--> 260 <!-- ko initValue: {observable: OrderTemplateLineId, value:'@orderLineId'}--><!-- /ko--> 261 <i class="fas fa-times" 262 data-bind=" 263 oninit: function() { IsInFavoriteList('@inFavourite'.toLowerCase()) }, 264 css: { showFavorite: ShowOrderTemplateDialog, showNewList: OrderTemplateShowNewList, active: IsInFavoriteList() == 'true' }, 265 click: DeleteOrderTemplateLine"> 266 </i> 267 </div> 268 } 269 </div> 270 } 271 @if (ShowShopFunctions && !IsOutletShop) 272 { 273 <p class="stock-indicator js-stock-indicator"> 274 <span class="stock-load-async"></span> 275 <span class="stock-name js-stock-name">@Translate("Product.StockStatus", "Lagerstatus")</span> 276 <span class="stock-name js-in-stock-again hide">@Translate("Product.StockExpectedAgaing", "P&aring; lager: ")<span class="js-stock-date"></span></span> 277 </p> 278 } 279 @if (IsOutletShop) 280 { 281 <div class="bg-secondary regular-rrp"> 282 <p class="xs-m-b-0"> 283 @Translate("Product.NormalRRP", "Normal butikspris: ") @RRPrice 284 </p> 285 </div> 286 } 287 </div> 288 289 </div> 290 <!-- /ko--> 291 } 292 293 294 295 296 297 @helper renderRelatedProduct(LoopItem repatedProduct) 298 { 299 string productID = repatedProduct.GetString("Ecom:Product.ID"); 300 string productNumber = repatedProduct.GetString("Ecom:Product.Number"); 301 string mainProductID = GetString("Ecom:Product:Field.FirstwebMainProductID"); 302 303 string productName = repatedProduct.GetString("Ecom:Product.Name"); 304 string productDescription = GetString("Ecom:Product.LongDescription"); 305 string productShortDescription = GetString("Ecom:Product.ShortDescription"); 306 307 string nettoPrice = repatedProduct.GetString("Firstweb:ErpPriceInfo.NettoPriceFormatted"); 308 int bruttoPrice = repatedProduct.GetInteger("Firstweb:ErpPriceInfo.BruttoAmountFormattedNoSymbol"); 309 310 int productPackagingQuantity = repatedProduct.GetInteger("Ecom:Product:Field.FirstwebNoPerColli"); 311 int defaultQuantity = productPackagingQuantity > 0 ? productPackagingQuantity : 1; 312 313 string languageId = repatedProduct.GetString("Ecom:Product.LanguageID"); 314 string variantId = repatedProduct.GetString("Ecom:Product.VariantID"); 315 316 int productInFavoritLists = GetInteger("Firstweb:Ecom:Product:OrderTemplate.InTemplates.Count"); 317 318 List<Dynamicweb.Ecommerce.Products.Detail> productImages = Firstweb.Custom.CustomCode.Frontend.Helpers.ProductImages.GetProductImages(languageId, productID, variantId); 319 Dynamicweb.Ecommerce.Products.Detail primaryProductImage = productImages.FirstOrDefault(x=>x.IsDefault); //Tag you can use instead: product.GetString("Ecom:Product.ImageDefault.Clean"); 320 //check for valid default image 321 if (primaryProductImage == null) 322 { 323 primaryProductImage = new Dynamicweb.Ecommerce.Products.Detail { Value = "" }; 324 } 325 else if (primaryProductImage.Value == null) 326 { 327 primaryProductImage.Value = ""; 328 } 329 330 string primaryProductImageUrl = "/admin/public/getimage.ashx?image=" + primaryProductImage.Value + "&altFmImage_path=/Files/Images/ecom/Products/no-image.jpg&width=300&height=300&Compression=90&Crop=5"; 331 332 //Sorted: first by imagegroup then by sortorder 333 //@foreach (var productImage in productImages) 334 //{ 335 //productImage.Value; //This is the imagepath eks. /Images/products/R12155_10_2.jpg 336 //productImage.IsDefault; //If the image is default or not. 337 //} 338 339 <li> 340 <article class="xs-p-2 lg-p-1 rounded-5 border-1 border-color-default"> 341 <div class="row is-flex xs-is-flex-column sm-is-flex-col md-is-flex-col"> 342 343 <div class="col-md-12 md-is-flex lg-p-r-0"> 344 <section class="col-md-3 col-lg-3 xs-p-0 md-p-l-0 md-p-r-1 lg-p-r-1 lg-p-l-0"> 345 <img class="img-responsive xs-auto-margin sm-auto-margin" src="@primaryProductImageUrl" /> 346 </section> 347 348 <section class="col-md-9 col-lg-7 xs-m-t-2 sm-m-t-2 md-m-t-0 xs-p-0 md-p-r-0 md-p-l-1 lg-p-r-0 lg-p-l-0"> 349 <header class="xs-m-b-1"> 350 <h2 data-bind="text: name" 351 class="h2 tertiary-font xs-m-t-0"> 352 @productName 353 </h2> 354 </header> 355 356 <section class="xs-m-b-1 clearfix"> 357 <span class="pull-left font-size-small"> 358 @Translate("Product.NumberShort", "Varenr."): <span>@productNumber</span> 359 </span> 360 </section> 361 362 <section class="word-break"> 363 <p class="font-size-small"> 364 @productShortDescription 365 </p> 366 </section> 367 </section> 368 </div> 369 370 <section class="col-md-9 col-md-offset-3 col-lg-5 col-lg-offset-0 sm-m-t-1 lg-m-t-0 md-p-l-2 371 lg-p-l-0 is-flex is-flex-col sm-is-flex-row sm-is-flex-wrap sm-flex-justify-space-between 372 md-is-flex-row md-is-flex-wrap md-flex-justify-space-between lg-flex-grow-2 lg-flex-justify-space-between"> 373 374 <div class="is-flex xs-m-t-1 sm-m-t-0 is-flex-col lg-m-b-auto"> 375 376 </div> 377 378 <div class="is-flex is-flex-col md-m-b-1 lg-m-b-0"> 379 <h4 class="h4 tertiary-font font-size-16px xs-m-b-1 sm-m-t-0 md-text-right lg-text-right"> 380 @nettoPrice 381 </h4> 382 383 <section class="xs-m-b-1 clearfix is-flex xs-flex-space-between lg-is-row-reverse"> 384 <div class="pull-right margin-left-1 xs-order-1 sm-order-1 md-order-1 xs-is-self-end sm-is-self-end md-is-self-end lg-m-t-0"> 385 @renderQuantityBox(defaultQuantity) 386 </div> 387 388 <div class="is-flex is-flex-col is-centered xs-margin-right-auto sm-m-r-1 md-m-r-1 font-size-small line-height-base md-text-right lg-text-right"> 389 <span>@Translate("Product.Packaging", "Forpakning"): </span> 390 <span> @productPackagingQuantity</span> 391 </div> 392 </section> 393 </div> 394 395 <section class="t-align-right clearfix sm-width-100 md-width-100"> 396 <button _data-bind="click: handleAddProductToCart" 397 class="btn btn-primary btn-xs tertiary-font lg-p-l-1 lg-p-r-1 xs-width-100 sm-width-100 md-width-100"> 398 @Translate("Product.AddToCart", "Tilføj til kurv") 399 </button> 400 </section> 401 </section> 402 403 </div> 404 </article> 405 </li> 406 407 408 409 } 410 411 @helper renderProductBuyBox(bool showShopFunctionsAlternativeIfNotLoggedIn, string productName, string productId, string price, int productPackagingQuantity, int quantity, string stockColor) 412 { 413 414 415 <article class="product-packaging border-bottom-1"> 416 <section class="row md-is-flex lg-is-flex md-is-flex-center lg-is-flex-center"> 417 <section class="packaging-section col-md-4 col-lg-5"> 418 <h4 class="h4 xs-m-t-0 xs-m-b-0 tertiary-font v-align-mid">@productName</h4> 419 </section> 420 421 422 423 @if (Firstweb.Custom.CustomCode.Tapas.Context.Current.ShopFunctionsVisibility.ShowShopFunctions()) 424 { 425 <section class="packaging-section md-p-l-0 xs-col-12 col-md-2 col-lg-2 tertiary-font"> 426 <span>@price</span> 427 428 429 </section> 430 <div class="stock md-is-self-end lg-is-self-end lg-order-0" > 431 @Translate("Product.StockStatus", "Lagerstatus"): <div class="stock-load-async @stockColor"></div> 432 433 </div> 434 <section class="packaging-section md-p-l-0 lg-p-r-8p packaging-section--alt xs-col-12 col-md-4 col-lg-3"> 435 <ul class="list-unstyled lg-m-l-auto lg-p-r-24p xs-m-b-0"> 436 <li> 437 <h5 class="h5 xs-m-b-0 xs-m-t-0 line-height-16px"> 438 <span>@Translate("Product.Packaging", "Forpakning"): </span> 439 <span> @productPackagingQuantity</span> 440 </h5> 441 </li> 442 </ul> 443 444 @renderQuantityBox(quantity) 445 446 </section> 447 448 <section class="packaging-section md-p-l-0 packaging-section--buy xs-col-12 col-md-2 col-lg-2 t-align-right"> 449 <button class="btn btn-primary btn-xs tertiary-font lg-p-l-1 lg-p-r-1 xs-width-100 sm-width-100 margin-bottom-4px" 450 _data-bind="click: handleAddProductToCart"> 451 @Translate("Product.AddToCart", "Tilføj til kurv") 452 </button> 453 </section> 454 455 } 456 else if (showShopFunctionsAlternativeIfNotLoggedIn) 457 { 458 var replaceWith = Firstweb.Custom.CustomCode.Tapas.Context.Current.ShopFunctionsVisibility.ReplaceWith(); 459 460 <section> 461 462 @if (replaceWith == "LOGIN") 463 { 464 <text>@renderLogin()</text> 465 } 466 else if (replaceWith == "RESELLER") 467 { 468 <text>@renderResellerLink()</text> 469 } 470 </section> 471 } 472 473 </section> 474 </article> 475 } 476 477 478 @helper renderInstantSearchProduct(LoopItem product) 479 { 480 string productID = product.GetString("Ecom:Product.ID"); 481 string productNumber = product.GetString("Ecom:Product.Number"); 482 string mainProductID = product.GetString("Ecom:Product:Field.FirstwebMainProductID"); 483 484 string productLink = product.GetString("Ecom:Product.Link.Clean"); 485 486 string productName = product.GetString("Ecom:Product.Name"); 487 string productShortDescription = product.GetString("Ecom:Product.ShortDescription"); 488 489 int productPackagingQuantity = product.GetInteger("Firstweb:ErpPriceInfo:ExtraInfos.PackagingSize"); 490 int defaultQuantity = productPackagingQuantity > 0 ? productPackagingQuantity : 1; 491 492 string languageId = product.GetString("Ecom:Product.LanguageID"); 493 string variantId = product.GetString("Ecom:Product.VariantID"); 494 495 bool hasVariants = (product.GetLoop("VariantCombinations").Count() > 0); 496 497 //Images 498 List<Dynamicweb.Ecommerce.Products.Detail> productImages = Firstweb.Custom.CustomCode.Frontend.Helpers.ProductImages.GetProductImages(languageId, productID, variantId); 499 Dynamicweb.Ecommerce.Products.Detail primaryProductImage = productImages.FirstOrDefault(x=>x.IsDefault); //Tag you can use instead: product.GetString("Ecom:Product.ImageDefault.Clean"); 500 501 //check for valid default image 502 if (primaryProductImage == null) 503 { 504 primaryProductImage = new Dynamicweb.Ecommerce.Products.Detail { Value = "" }; 505 } 506 else if (primaryProductImage.Value == null) 507 { 508 primaryProductImage.Value = ""; 509 } 510 511 string primaryProductImageUrl = "/admin/public/getimage.ashx?image=" + primaryProductImage.Value + "&altFmImage_path=/Files/Images/ecom/Products/no-image.jpg&width=200&height=125&Compression=90&Crop=5"; 512 if (String.IsNullOrEmpty(primaryProductImage.Value)) 513 { 514 primaryProductImageUrl = "/admin/public/getimage.ashx?image=/Files/Images/ecom/Products/no-image.jpg&width=200&height=125&Compression=90&Crop=5"; 515 } 516 //Sorted: first by imagegroup then by sortorder 517 //@foreach (var productImage in productImages) 518 //{ 519 //productImage.Value; //This is the imagepath eks. /Images/products/R12155_10_2.jpg 520 //productImage.IsDefault; //If the image is default or not. 521 //} 522 523 //Other packagings 524 //var otherPackagingProducts = Firstweb.Custom.CustomCode.Frontend.Helpers.OtherPackagingProducts.GetOtherPackagingProducts(mainProductID, false).Where(i => i.Id != productID); 525 //var showOtherPackagingProducts = otherPackagingProducts.Count() > 0; 526 527 int loopCount = product.GetInteger("Products.LoopCounter") - 1; 528 <div class="col-xs-12 col-sm-3 xs-m-b-1"> 529 530 <article class="instant-search-product bg-white productCount @loopCount" data-bind="css: {'item--selected': navSelectedItem() == @loopCount}"> 531 <div class="cursor-pointer info" 532 data-bind="click: function() { window.location.href='@productLink'}"> 533 <div class="hidden-xs product-image"> 534 <img class="img-responsive center-block" src="@primaryProductImageUrl"> 535 </div> 536 537 <div class="name"> 538 <p>@productName</p> 539 540 541 <span>@Translate("Product.NumberShort", "Varenr.") @productNumber</span> 542 </div> 543 </div> 544 545 @if (Firstweb.Custom.CustomCode.Tapas.Context.Current.ShopFunctionsVisibility.ShowShopFunctions()) 546 { 547 <div class="buy-container" data-bind="defineObservable: { quantity: 1 }"> 548 549 <input class="product-quantity" type="number" name="quantity" data-bind="value: quantity" /> 550 551 <button class="btn btn-primary btn-xs add-to-cart" 552 data-bind="click: function(evt) { $parent.onAddToCart('@productID', quantity()) }"> 553 @Translate("Product.AddToCart", "Tilføj til kurv") 554 </button> 555 </div> 556 } 557 </article> 558 559 </div> 560 561 } 562 563 564 565 @helper renderQuantityBox(int quantity) 566 { 567 <input class="product-quantity" type="number" name="quantity" value="@quantity" /> 568 } 569 570 571 @helper renderLogin() 572 { 573 <button class="btn btn-primary" data-toggle="modal" data-target=".loginModal">@Translate("Product.LoginToShop", "Log ind for at købe")</button> 574 } 575 @helper renderResellerLink() 576 { 577 <a href="@Firstweb.Custom.CustomCode.Tapas.Context.Current.ShopFunctionsVisibility.ReplaceLink()" class="btn btn-primary">@Translate("Product.FindReseller", "Find forhandler")</a> 578 } 579 580 @inherits RazorTemplateBase<RazorTemplateModel<Template>> 581 @using Dynamicweb.Rendering 582 @using Dynamicweb.Environment 583 584 @helper renderBreadcrumbs(string productId = "") 585 { 586 string currentGroupId = Dynamicweb.Context.Current.Request.GetString("GroupID"); 587 string productPageID = Firstweb.Custom.CustomCode.Tapas.Context.AreaPages.GetPageId("productcatalog"); 588 string productPageHref = "/Default.aspx?Id=" + productPageID; 589 var breadCrumbGroupList = Firstweb.Custom.CustomCode.Frontend.Helpers.EcomGroups.getBreadCrumbGroupList(currentGroupId, true); 590 591 if (!String.IsNullOrEmpty(productId)) { 592 breadCrumbGroupList = Firstweb.Custom.CustomCode.Frontend.Helpers.EcomGroups.getBreadCrumbGroupListByProduct(productId, true); 593 } 594 595 <div class="col-xs-12"> 596 <ul class="breadcrumb"> 597 <li><a href="@productPageHref" title="@Translate("Firstweb.Content.Breadcrumbs.ProductPage", "Produkter")">@Translate("Firstweb.Content.Breadcrumbs.ProductPage", "Produkter")</a></li> 598 @foreach (var g in breadCrumbGroupList) { 599 string breadCrumbLink = String.Format("/Default.aspx?Id={0}&amp;GroupId={1}", productPageID, g.Id); 600 <li> <a href='@breadCrumbLink' title="@g.Name">@g.Name </a></li> 601 } 602 </ul> 603 </div> 604 } 605 606 @{ 607 string sortOrder = GetString("Ecom:ProductList.SortOrder"); 608 bool isAjaxRequest = Dynamicweb.Context.Current.Request.GetBoolean("ajaxTapas"); 609 string searchQuery = Dynamicweb.Context.Current.Request.GetString("Search"); 610 string currentGroupId = Dynamicweb.Context.Current.Request.GetString("GroupID"); 611 int pageId = Dynamicweb.Frontend.PageView.Current().ID; 612 var breadCrumbGroupList = Firstweb.Custom.CustomCode.Frontend.Helpers.EcomGroups.getBreadCrumbGroupList(currentGroupId, false); 613 bool IsGroupList = !String.IsNullOrEmpty(currentGroupId); 614 615 int totalPages = GetInteger("Ecom:ProductList.TotalPages"); 616 int currentPage = GetInteger("Ecom:ProductList.CurrentPage"); 617 int productCount = GetInteger("Ecom:ProductList.PageProdCnt"); 618 bool productsFound = (productCount > 0); 619 bool IsOutletShop = Firstweb.Custom.CustomCode.Frontend.Helpers.Millarco.IsOutletShop(); 620 621 int ProductGroupVideoList = GetInteger("Ecom:Group:Field.FirstwebProductGroupVideoList"); 622 623 bool isGroupView = GetBoolean("Ecom:Group:Field.groupview"); 624 } 625 626 @if (!isAjaxRequest) 627 { 628 <div class="container"> 629 <div class="row"> 630 @renderBreadcrumbs() 631 </div> 632 </div> 633 634 <div class="millarco-productlist"> 635 636 <section> 637 638 @if (IsGroupList) 639 { 640 @RenderGroupHeader() 641 } 642 else if (!String.IsNullOrWhiteSpace(searchQuery)) 643 { 644 <div class="container xs-p-t-3"> 645 @RenderSearchHeader(searchQuery) 646 </div> 647 } 648 else if (!IsOutletShop) 649 { 650 <div class="container xs-p-t-3"> 651 @RenderParagraphHeader() 652 </div> 653 } 654 else 655 { 656 @RenderOutletShopHeader() 657 } 658 659 </section> 660 661 @if (!isGroupView) 662 { 663 <div class="container product-container"> 664 665 <main data-bind="viewModel: 'ProductListViewModel'"> 666 <div class="row"> 667 <div class="col-lg-3 product-groups-wrapper"> 668 <p class="h3">@Translate("ProductSubNavTitle", "Produkter")</p> 669 @if (productsFound) 670 { 671 if (IsGroupList) 672 { 673 <div class="product-groups"> 674 @RenderGroupLevelFilter(Firstweb.Custom.CustomCode.Frontend.Helpers.EcomGroups.GetFilterTopLevelGroup(), currentGroupId, currentGroupId, pageId) 675 </div> 676 } 677 } 678 </div> 679 <div class="col-lg-9"> 680 <div class="row"> 681 @if (productsFound) 682 { 683 <div class="col-xs-12 filter-section"> 684 <form method="get" 685 action="/Default.aspx" 686 data-bind="formSubmitOnChange: { 687 text: '@Translate("Productlist.UpdatingFilters", "Opdaterer filter")', 688 delay: '1000' }"> 689 <input type="hidden" name="id" value="@GetString("Ecom:ProductList:Page.ID")" /> 690 691 @if (!String.IsNullOrEmpty(currentGroupId)) 692 { 693 <input type="hidden" name="groupid" value="@currentGroupId" /> 694 } 695 @if (!String.IsNullOrEmpty(searchQuery)) 696 { 697 <input type="hidden" name="search" value="@searchQuery" /> 698 } 699 700 @RenderSorting(sortOrder) 701 702 @RenderFacets() 703 </form> 704 </div> 705 } 706 <div class="col-xs-12 productList" 707 data-bind="asyncPriceLoad: productListLoad, 708 loadOnBool: { observableBool: CartLoading, text: 'Tilføjer produkt' }, 709 css: 'loaded'"> 710 711 <div class="row row-ce"> 712 @RenderProductList(GetLoop("Products"), productsFound) 713 </div> 714 715 @if (ProductGroupVideoList > 0) 716 { 717 @RenderParagraphContent(ProductGroupVideoList) 718 } 719 720 @if (totalPages > 1 && currentPage == 1) 721 { 722 <div class="loadMoreProducts" 723 data-bind="loadMoreProducts: { 724 beforeLoad: function() { $root.stuffLoadingQueue({load: true}) }, 725 afterLoad: function() { $root.stuffLoadingQueue({load: false}) }, 726 text: '@Translate("Productlist.LoadingProducts", "Henter produkter")', 727 currentPage: @currentPage, 728 totalPages: @totalPages 729 }"> 730 </div> 731 } 732 733 @if (!String.IsNullOrEmpty(GetString("Ecom:Group:Field.GroupDescriptionBottom"))) 734 { 735 <div class="group-description">@GetString("Ecom:Group:Field.GroupDescriptionBottom")</div> 736 } 737 </div> 738 </div> 739 </div> 740 </div> 741 </main> 742 </div> 743 } 744 else 745 { 746 int subGroupCount = 0; 747 List<LoopItem> subGroups = GetLoop("Subgroups"); 748 bool anySelectedGroups = subGroups.Any(g => g.GetBoolean("Ecom:Group:Field.selectedgroup.Value")); 749 bool anyUnselectedGroups = subGroups.Any(g => !g.GetBoolean("Ecom:Group:Field.selectedgroup.Value")); 750 string hideIfAnySelectedGroupsClass = !anySelectedGroups && anyUnselectedGroups ? "" : "hidden"; 751 752 <div class="container"> 753 <main class="group-view"> 754 <div class="row"> 755 <div class="col-lg-12"> 756 @if (anySelectedGroups) 757 { 758 <div class="selected-groups"> 759 <p class="h2 margin-top-40px">@Translate("GroupViewTitle", "Udvalgte kategorier")</p> 760 <div class="row"> 761 @foreach (LoopItem group in subGroups.Where(g => g.GetBoolean("Ecom:Group:Field.selectedgroup.Value"))) 762 { 763 string imagePath = group.GetString("Ecom:Group.SmallImage"); 764 string imagePathCustom = group.GetString("Ecom:Group:Field.selectedgroupimage.Value.Clean"); 765 string image; 766 string cssBackground; 767 768 if (!string.IsNullOrEmpty(imagePathCustom)) 769 { 770 image = "/admin/public/GetImage.ashx?image=" + imagePathCustom + "&width=400"; 771 cssBackground = "background:#fff url('" + image + "') no-repeat center center / cover;"; 772 } 773 else 774 { 775 image = "/admin/public/GetImage.ashx?image=" + imagePath + "&width=400"; 776 cssBackground = "background:#fff url('" + image + "') no-repeat center center / 200px;"; 777 } 778 string groupName = group.GetString("Ecom:Group.Name"); 779 780 <div class="col-12 col-sm-6 col-lg-4"> 781 <a href="@group.GetString("Ecom:Group.Link.Clean")"> 782 <div style="@cssBackground" class="img-responsive margin-bottom-24px group-image"> 783 <div class="group-name">@groupName</div> 784 </div> 785 </a> 786 </div> 787 } 788 </div> 789 </div> 790 } 791 792 @if (anySelectedGroups && anyUnselectedGroups) 793 { 794 <div class="row margin-top-18px margin-bottom-18px"> 795 <div class="col-12"> 796 <div class="groups-view-all centerText"> 797 <div onclick="$('.all-groups').removeClass('hidden'), $(this).addClass('hidden');" class="btn btn-primary">@Translate("GroupViewMoreButton", "Se alle grupper")</div> 798 </div> 799 </div> 800 </div> 801 } 802 803 <div class="all-groups @hideIfAnySelectedGroupsClass"> 804 <p class="h2 margin-top-40px">@Translate("AllGroupViewTitle", "Alle kategorier")</p> 805 <div class="row"> 806 @foreach (LoopItem group in subGroups.Where(g => !g.GetBoolean("Ecom:Group:Field.selectedgroup.Value"))) 807 { 808 string imagePath = group.GetString("Ecom:Group.SmallImage"); 809 string imagePathCustom = group.GetString("Ecom:Group:Field.selectedgroupimage.Value.Clean"); 810 string image; 811 string cssBackground; 812 813 if (!string.IsNullOrEmpty(imagePathCustom)) 814 { 815 image = "/admin/public/GetImage.ashx?image=" + imagePathCustom + "&width=400"; 816 cssBackground = "background:#fff url('" + image + "') no-repeat center center / cover;"; 817 } 818 else 819 { 820 image = "/admin/public/GetImage.ashx?image=" + imagePath + "&width=400"; 821 cssBackground = "background:#fff url('" + image + "') no-repeat center center / 200px;"; 822 } 823 string groupName = group.GetString("Ecom:Group.Name"); 824 825 <div class="col-12 col-sm-6 col-lg-4"> 826 <a href="@group.GetString("Ecom:Group.Link.Clean")"> 827 <div style="@cssBackground" class="img-responsive margin-bottom-24px group-image"> 828 <div class="group-name">@groupName</div> 829 </div> 830 </a> 831 </div> 832 } 833 </div> 834 </div> 835 <div class="margin-top-40px margin-bottom-40px"> 836 @if (!String.IsNullOrEmpty(GetString("Ecom:Group:Field.GroupDescriptionBottom"))) 837 { 838 <div class="group-description">@GetString("Ecom:Group:Field.GroupDescriptionBottom")</div> 839 } 840 </div> 841 </div> 842 </div> 843 </main> 844 </div> 845 } 846 847 </div> 848 } 849 else 850 { 851 <div class="productsContainer"> 852 @RenderProductList(GetLoop("Products"), productsFound) 853 </div> 854 } 855 856 @helper RenderProductList(IEnumerable<LoopItem> Loop, bool productsFound) 857 { 858 if (!productsFound) 859 { 860 <div class="is-flex col-xs-12 xs-m-t-3 xs-m-b-4 sm-m-b-7 font-primary"> 861 <h1>@Translate("ProductList.NoProductsFound", ":( There are no products in this category")</h1> 862 </div> 863 } 864 else 865 { 866 var productLoop = Loop.ToList(); 867 int currentPage = GetInteger("Ecom:ProductList.CurrentPage"); 868 int totalPages = GetInteger("Ecom:ProductList.TotalPages"); 869 var count = 0; 870 871 for (int i = 0; i < productLoop.Count(); i++) 872 { 873 var item = productLoop[i]; 874 int loopMod = item.GetInteger("Products.LoopMod4"); 875 bool renderStartRow = i % 3 == 0 ? true : false; 876 bool renderEndRow = i % 3 == 0 ? true : false; 877 878 if (i == 0 && totalPages > 1) 879 { 880 @:<div class="row row-ce" id="@currentPage"> 881 } 882 883 @renderProduct(true, item, true); //This is from renderProduct.cshtml 884 885 886 if (productLoop.Count() - 1 == i && totalPages > 1) 887 { 888 @:</div> 889 } 890 } 891 } 892 } 893 894 @helper RenderOutletShopHeader() 895 { 896 <div class="content-element solid-bg bg-image-and-text-element bg-secondary" style="background-image:url('/Files/Images/@Dynamicweb.Frontend.PageView.Current().CurrentParagraph.Image')"> 897 <div class="container"> 898 <div class="row"> 899 <div class="col-xs-12 col-md-8 col-lg-6"> 900 <div class="text-area"> 901 <div class="rte-content"> 902 @Dynamicweb.Frontend.PageView.Current().CurrentParagraph.Text 903 </div> 904 <div class="red-divider"></div> 905 </div> 906 </div> 907 </div> 908 </div> 909 </div> 910 } 911 912 913 @helper RenderGroupHeader() 914 { 915 int ProductGroupVideoTop = GetInteger("Ecom:Group:Field.FirstwebProductGroupVideoTop"); 916 string Description = GetString("Ecom:Group.Description"); 917 string GroupName = GetString("Ecom:Group.Name"); 918 string BgImage = GetString("Ecom:Group.LargeImage"); 919 bool IsOutletShop = Firstweb.Custom.CustomCode.Frontend.Helpers.Millarco.IsOutletShop(); 920 if (IsOutletShop && !String.IsNullOrEmpty(GetString("Ecom:Group:Field.FirstwebOutletGroupImage.Value.Clean"))) 921 { 922 BgImage = GetString("Ecom:Group:Field.FirstwebOutletGroupImage.Value.Clean"); 923 } 924 925 if (ProductGroupVideoTop > 0) 926 { 927 @RenderParagraphContent(ProductGroupVideoTop) 928 } 929 else 930 { 931 <div class="content-element solid-bg bg-image-and-text-element bg-secondary" style="background-image:url('@BgImage')"> 932 <div class="container"> 933 <div class="row"> 934 <div class="col-xs-12 col-md-8 col-lg-6"> 935 <div class="text-area"> 936 @if (!String.IsNullOrEmpty(Description)) 937 { 938 <div class="rte-content"> 939 @Description 940 </div> 941 } 942 else 943 { 944 <h1 class="xs-m-t-0">@GroupName</h1> 945 } 946 <div class="red-divider"></div> 947 </div> 948 </div> 949 </div> 950 </div> 951 </div> 952 } 953 } 954 955 @helper RenderSearchHeader(string searchQuery) 956 { 957 <h1 class="h1 xs-m-t-0 tertiary-font"> 958 @Translate("ProductList.SearchResultHeader", "S&oslash;geresultat") 959 </h1> 960 961 <h4 class="h4 lg-m-b-0"> 962 @Translate("ProductList.SearchResultText", "Resultater for din s&oslash;gning"): @searchQuery 963 </h4> 964 } 965 966 @helper RenderParagraphHeader() 967 { 968 <h1 class="h1 lg-m-t-0 tertiary-font">@Dynamicweb.Frontend.PageView.Current().CurrentParagraph.Header</h1> 969 970 if (!String.IsNullOrEmpty(Dynamicweb.Frontend.PageView.Current().CurrentParagraph.Text)) 971 { 972 <p>@Dynamicweb.Frontend.PageView.Current().CurrentParagraph.Text</p> 973 } 974 } 975 976 977 @helper RenderGroups(List<Dynamicweb.Ecommerce.Products.Group> breadCrumbGroupList, string currentGroupId) 978 { 979 if (breadCrumbGroupList.Count() > 0) 980 { 981 var ParentGroup = breadCrumbGroupList.LastOrDefault(); 982 var baseLink = "/Default.aspx?ID=" + Dynamicweb.Frontend.PageView.Current().ID + "&GroupID="; 983 if (ParentGroup != null) 984 { 985 <section class="product__sub-nav"> 986 <p class="xs-m-b-0"> 987 @ParentGroup.Name 988 </p> 989 990 <ul> 991 @foreach (var subgroup in ParentGroup.Subgroups) 992 { 993 <li> 994 @if (subgroup.Id == currentGroupId) 995 { 996 <span>@subgroup.Name</span> 997 } 998 else 999 { 1000 bool DisplayGroup = subgroup.Products.Count() > 0 || subgroup.Subgroups.Where(x => x.Products.Count() > 0).Count() > 0; 1001 if (DisplayGroup) 1002 { 1003 <a href="@baseLink@subgroup.Id">@subgroup.Name</a> 1004 } 1005 } 1006 </li> 1007 } 1008 </ul> 1009 </section> 1010 } 1011 } 1012 } 1013 1014 @helper RenderFacets() 1015 { 1016 foreach (LoopItem facetGroup in GetLoop("FacetGroups")) 1017 { 1018 foreach (LoopItem facet in facetGroup.GetLoop("Facets").Where(x => x.GetLoop("FacetOptions").Any())) 1019 { 1020 string facetName = facet.GetString("Facet.Name"); 1021 string translatedFacetName = Translate("ProductList.FacetName" + facet.GetString("Facet.Name"), facet.GetString("Facet.Name")); 1022 bool hasOptions = facet.GetLoop("FacetOptions").Any(); 1023 string hasOptionsCss = hasOptions ? "xs-p-t-1 xs-p-b-1" : ""; 1024 string FacetIsOpen = facet.GetLoop("FacetOptions").Where(x => x.GetBoolean("FacetOption.Selected")).Any() ? "true" : "false"; 1025 1026 <section class="bg-white filter" data-bind="defineObservable: { sortDropdown: @FacetIsOpen }"> 1027 @if (hasOptions) 1028 { 1029 <button class="filter__toggle xs-p-l-0 xs-p-r-0 clear-button is-flex is-space-between is-flex-align-center width-100" data-bind="click: function() { sortDropdown(!sortDropdown()) }"> 1030 <h3 class="h3 xs-m-t-0 xs-m-b-0 tertiary-font font-size-base filterHeader" 1031 data-bind="toggleClassParent: 'active'"> 1032 @translatedFacetName 1033 </h3> 1034 <span> 1035 <i class="fa fa-chevron-down"></i> 1036 </span> 1037 </button> 1038 } 1039 1040 <div class="filter__options line-height-base" data-bind="css: { hidden: !sortDropdown() }"> 1041 @foreach (LoopItem option in facet.GetLoop("FacetOptions")) 1042 { 1043 var value = option.GetValue("FacetOption.Value"); 1044 string label = option.GetString("FacetOption.Label").Replace("\"", "&#x22;"); 1045 if (label.ToUpper() == "TRUE" || label.ToUpper() == "FALSE") 1046 { 1047 label = Translate("ProductList.FacetOption:" + label, "Ja"); 1048 } 1049 1050 1051 int count = option.GetInteger("FacetOption.Count"); 1052 bool selected = option.GetBoolean("FacetOption.Selected"); 1053 label += " (" + count + ")"; 1054 <div class="form-group"> 1055 <custom-checkbox params="{ label: '@label', 1056 value: '@value', 1057 checked: @(selected.ToString().ToLower()), 1058 name: '@facet.GetString("Facet.QueryParameter")' }" /> 1059 </div> 1060 } 1061 </div> 1062 </section> 1063 } 1064 } 1065 } 1066 1067 1068 @helper RenderSorting(string sortOrder) 1069 { 1070 <section class="bg-white filter filter__container" 1071 data-bind="defineObservable: { 1072 sortOrder: '@sortOrder' || 'ASC', 1073 sortDropdown: false }"> 1074 <button class="filter__toggle clear-button is-flex is-space-between is-flex-align-center clear-button xs-p-l-0 xs-p-r-0 width-100" data-bind="click: function() { sortDropdown(!sortDropdown()) }"> 1075 <p class="h3 xs-m-t-0 xs-m-b-0 tertiary-font font-size-base" 1076 data-bind="toggleClassParent: 'active'"> 1077 @Translate("filtersort", "Sortering") 1078 </p> 1079 1080 <span> 1081 <i class="fa fa-chevron-down"></i> 1082 </span> 1083 </button> 1084 1085 <input type="hidden" name="SortBy" value="ProductNameSort" /> 1086 1087 <section class="filter__options" data-bind="css: { hidden: !sortDropdown() }"> 1088 <div class="form-group"> 1089 <custom-radio params="{ 1090 label: '@Translate("sortnameaz", "Navn: A - &Aring;")', 1091 value: 'ASC', 1092 checked: sortOrder, 1093 name: 'SortOrder' }" /> 1094 </div> 1095 1096 <div class="form-group xs-m-b-0"> 1097 <custom-radio params="{ 1098 label: '@Translate("sortnameza", "Navn: &Aring; - A")', 1099 value: 'DESC', 1100 checked: sortOrder, 1101 name: 'SortOrder' }" /> 1102 </div> 1103 </section> 1104 </section> 1105 } 1106 1107 @helper RenderGroupLevelFilter(IEnumerable<Dynamicweb.Ecommerce.Products.Group> groups, string currentGroupId, string activeGroup, int pageId) 1108 { 1109 var ProductGroups = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(currentGroupId); 1110 bool isTopLevelGroup = ProductGroups.IsTopGroup; 1111 var parentGroup = ProductGroups.PrimaryParentGroupId; 1112 1113 if (isTopLevelGroup) 1114 { 1115 foreach (var group in groups.Where(x => Firstweb.Custom.CustomCode.Frontend.Helpers.EcomGroups.IsFilterGroup(x))) 1116 { 1117 var currentGroup = group.Id.Equals(currentGroupId); 1118 var isCurrentGroup = currentGroup ? "is-active" : ""; 1119 1120 <div class="@isCurrentGroup"> 1121 <a href="/Default.aspx?Id=@pageId&groupid=@group.Id">@group.Name</a> 1122 </div> 1123 1124 if (currentGroup && group.HasChildGroups) 1125 { 1126 <div class="sub-group"> 1127 @foreach (var isSubGroup in group.Subgroups) 1128 { 1129 var setActive = isSubGroup.Id == activeGroup ? "is-active" : ""; 1130 1131 <div class="@setActive"> 1132 <a href="/Default.aspx?Id=@pageId&groupid=@isSubGroup.Id">@isSubGroup.Name</a> 1133 </div> 1134 } 1135 @*@RenderGroupLevelFilter(group.Subgroups, currentGroupId, (level + 1))*@ 1136 </div> 1137 } 1138 } 1139 } 1140 else 1141 { 1142 @RenderGroupLevelFilter(groups, parentGroup, currentGroupId, pageId) 1143 } 1144 }

Denne hjemmeside bruger cookies til trafikmåling og optimering af indhold