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