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_0dfaae73d0aa4c9eabeb0427ac5c5067.<>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 1141
at CompiledRazorTemplates.Dynamic.RazorEngine_0dfaae73d0aa4c9eabeb0427ac5c5067.Execute() in D:\dynamicweb.net\Solutions\millarco.live\Files\Templates\Designs\Tapas\eCom\Productlist\productlist_Default.cshtml:line 679
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-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 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 bg-white" 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 }
630
631 @if (!isAjaxRequest)
632 {
633 <div class="container">
634 <div class="row">
635 @renderBreadcrumbs()
636 </div>
637 </div>
638
639 <div class="millarco-productlist">
640
641 <section>
642
643 @if (IsGroupList)
644 {
645 @RenderGroupHeader()
646 }
647 else if (!String.IsNullOrWhiteSpace(searchQuery))
648 {
649 <div class="container xs-p-t-3">
650 @RenderSearchHeader(searchQuery)
651 </div>
652 }
653 else if (!IsOutletShop)
654 {
655 <div class="container xs-p-t-3">
656 @RenderParagraphHeader()
657 </div>
658 }
659 else
660 {
661 @RenderOutletShopHeader()
662 }
663
664 </section>
665
666 @if (!isGroupView)
667 {
668 <div class="container product-container">
669
670 <main data-bind="viewModel: 'ProductListViewModel'">
671 <div class="row">
672 <div class="col-lg-3 product-groups-wrapper">
673 <p class="h3">@Translate("ProductSubNavTitle", "Produkter")</p>
674 @if (productsFound)
675 {
676 if (IsGroupList)
677 {
678 <div class="product-groups">
679 @RenderGroupLevelFilter(Firstweb.Custom.CustomCode.Frontend.Helpers.EcomGroups.GetFilterTopLevelGroup(), currentGroupId, currentGroupId, pageId)
680 </div>
681 }
682 }
683 </div>
684 <div class="col-lg-9">
685 <div class="row">
686 @if (productsFound)
687 {
688 <div class="col-xs-12 filter-section">
689 <form method="get"
690 action="/Default.aspx"
691 data-bind="formSubmitOnChange: {
692 text: '@Translate("Productlist.UpdatingFilters", "Opdaterer filter")',
693 delay: '1000' }">
694 <input type="hidden" name="id" value="@GetString("Ecom:ProductList:Page.ID")" />
695
696 @if (!String.IsNullOrEmpty(currentGroupId))
697 {
698 <input type="hidden" name="groupid" value="@currentGroupId" />
699 }
700 @if (!String.IsNullOrEmpty(searchQuery))
701 {
702 <input type="hidden" name="search" value="@searchQuery" />
703 }
704
705 @RenderSorting(sortOrder)
706
707 @RenderFacets()
708 </form>
709 </div>
710 }
711 <div class="col-xs-12 productList"
712 data-bind="asyncPriceLoad: productListLoad,
713 loadOnBool: { observableBool: CartLoading, text: 'Tilføjer produkt' },
714 css: 'loaded'">
715
716 <div class="row row-ce">
717 @RenderProductList(GetLoop("Products"), productsFound)
718 </div>
719
720 @if (ProductGroupVideoList > 0)
721 {
722 @RenderParagraphContent(ProductGroupVideoList)
723 }
724
725 @if (totalPages > 1 && currentPage == 1)
726 {
727 <div class="loadMoreProducts"
728 data-bind="loadMoreProducts: {
729 beforeLoad: function() { $root.stuffLoadingQueue({load: true}) },
730 afterLoad: function() { $root.stuffLoadingQueue({load: false}) },
731 text: '@Translate("Productlist.LoadingProducts", "Henter produkter")',
732 currentPage: @currentPage,
733 totalPages: @totalPages
734 }">
735 </div>
736 }
737
738 @if (!String.IsNullOrEmpty(GetString("Ecom:Group:Field.GroupDescriptionBottom")))
739 {
740 <div class="group-description">@GetString("Ecom:Group:Field.GroupDescriptionBottom")</div>
741 }
742 </div>
743 </div>
744 </div>
745 </div>
746 </main>
747 </div>
748 }
749 else
750 {
751 int subGroupCount = 0;
752 List<LoopItem> subGroups = GetLoop("Subgroups");
753 bool anySelectedGroups = subGroups.Any(g => g.GetBoolean("Ecom:Group:Field.selectedgroup.Value"));
754 bool anyUnselectedGroups = subGroups.Any(g => !g.GetBoolean("Ecom:Group:Field.selectedgroup.Value"));
755 string hideIfAnySelectedGroupsClass = !anySelectedGroups && anyUnselectedGroups ? "" : "hidden";
756
757 <div class="container">
758 <main class="group-view">
759 <div class="row">
760 <div class="col-lg-12">
761 @if (anySelectedGroups)
762 {
763 <div class="selected-groups">
764 <p class="h2 margin-top-40px">@Translate("GroupViewTitle", "Udvalgte kategorier")</p>
765 <div class="row">
766 @foreach (LoopItem group in subGroups.Where(g => g.GetBoolean("Ecom:Group:Field.selectedgroup.Value")))
767 {
768 string imagePath = group.GetString("Ecom:Group.SmallImage");
769 string imagePathCustom = group.GetString("Ecom:Group:Field.selectedgroupimage.Value.Clean");
770 string image;
771 string cssBackground;
772 string groupName = group.GetString("Ecom:Group.Name");
773 string groupImgSize = group.GetString("Ecom:Group:Field.groupImageSize");
774 string groupHeaderColor = group.GetString("Ecom:Group:Field.groupHeaderColor");
775 string groupHeaderFontSize = group.GetString("Ecom:Group:Field.groupHeaderFontSize") + "px";
776 bool headerBg = group.GetBoolean("Ecom:Group:Field.GroupHeaderBgColor");
777 string groupHeaderBg = "";
778 if (headerBg)
779 {
780 groupHeaderBg = "show-bg";
781 }
782 if ( groupImgSize != "100%" )
783 {
784 groupImgSize = "200px";
785 }
786
787 if (!string.IsNullOrEmpty(imagePathCustom))
788 {
789 image = "/admin/public/GetImage.ashx?image=" + imagePathCustom + "&width=400";
790 cssBackground = "background:#fff url('" + image + "') no-repeat center center / cover;";
791 }
792 else
793 {
794 image = "/admin/public/GetImage.ashx?image=" + imagePath + "&width=400";
795 cssBackground = "background:#fff url('" + image + "') no-repeat center center / " + groupImgSize + ";";
796 }
797
798 <div class="col-12 col-sm-6 col-lg-4">
799 <a href="@group.GetString("Ecom:Group.Link.Clean")">
800 <div style="@cssBackground" class="img-responsive margin-bottom-24px group-image">
801 <div class="group-name @groupHeaderColor @groupHeaderBg" style="font-size: @groupHeaderFontSize">@groupName</div>
802 </div>
803 </a>
804 </div>
805 }
806 </div>
807 </div>
808 }
809
810 @if (anySelectedGroups && anyUnselectedGroups)
811 {
812 <div class="row margin-top-18px margin-bottom-18px">
813 <div class="col-12">
814 <div class="groups-view-all centerText">
815 <div onclick="$('.all-groups').removeClass('hidden'), $(this).addClass('hidden');" class="btn btn-primary">@Translate("GroupViewMoreButton", "Se alle grupper")</div>
816 </div>
817 </div>
818 </div>
819 }
820
821 <div class="all-groups @hideIfAnySelectedGroupsClass">
822 <p class="h2 margin-top-40px">@Translate("AllGroupViewTitle", "Alle kategorier")</p>
823 <div class="row">
824 @foreach (LoopItem group in subGroups.Where(g => !g.GetBoolean("Ecom:Group:Field.selectedgroup.Value") && g.GetBoolean("Ecom:Group:Field.FirstwebShowInGroupFilter.Value")))
825 {
826 string imagePath = group.GetString("Ecom:Group.SmallImage");
827 string imagePathCustom = group.GetString("Ecom:Group:Field.selectedgroupimage.Value.Clean");
828 string image;
829 string cssBackground;
830 string groupName = group.GetString("Ecom:Group.Name");
831 string groupImgSize = group.GetString("Ecom:Group:Field.groupImageSize");
832 string groupHeaderColor = group.GetString("Ecom:Group:Field.groupHeaderColor");
833 string groupHeaderFontSize = group.GetString("Ecom:Group:Field.groupHeaderFontSize") + "px";
834 bool headerBg = group.GetBoolean("Ecom:Group:Field.GroupHeaderBgColor");
835 string groupHeaderBg = "";
836 if (headerBg)
837 {
838 groupHeaderBg = "show-bg";
839 }
840 if ( groupImgSize != "100%" )
841 {
842 groupImgSize = "200px";
843 }
844
845 if (!string.IsNullOrEmpty(imagePathCustom))
846 {
847 image = "/admin/public/GetImage.ashx?image=" + imagePathCustom + "&width=400";
848 cssBackground = "background:#fff url('" + image + "') no-repeat center center / cover;";
849 }
850 else
851 {
852 image = "/admin/public/GetImage.ashx?image=" + imagePath + "&width=400";
853 cssBackground = "background:#fff url('" + image + "') no-repeat center center / " + groupImgSize + ";";
854 }
855
856 <div class="col-12 col-sm-6 col-lg-4">
857 <a href="@group.GetString("Ecom:Group.Link.Clean")">
858 <div style="@cssBackground" class="img-responsive margin-bottom-24px group-image">
859 <div class="group-name @groupHeaderColor @groupHeaderBg" style="font-size: @groupHeaderFontSize">@groupName</div>
860 </div>
861 </a>
862 </div>
863 }
864 </div>
865 </div>
866 <div class="margin-top-40px margin-bottom-40px">
867 @if (!String.IsNullOrEmpty(GetString("Ecom:Group:Field.GroupDescriptionBottom")))
868 {
869 <div class="group-description">@GetString("Ecom:Group:Field.GroupDescriptionBottom")</div>
870 }
871 </div>
872 </div>
873 </div>
874 </main>
875 </div>
876 }
877
878 </div>
879 }
880 else
881 {
882 <div class="productsContainer">
883 @RenderProductList(GetLoop("Products"), productsFound)
884 </div>
885 }
886
887 @helper RenderProductList(IEnumerable<LoopItem> Loop, bool productsFound)
888 {
889 if (!productsFound)
890 {
891 <div class="is-flex col-xs-12 xs-m-t-3 xs-m-b-4 sm-m-b-7 font-primary">
892 <h1>@Translate("ProductList.NoProductsFound", ":( There are no products in this category")</h1>
893 </div>
894 }
895 else
896 {
897 var productLoop = Loop.ToList();
898 int currentPage = GetInteger("Ecom:ProductList.CurrentPage");
899 int totalPages = GetInteger("Ecom:ProductList.TotalPages");
900 var count = 0;
901
902 for (int i = 0; i < productLoop.Count(); i++)
903 {
904 var item = productLoop[i];
905 int loopMod = item.GetInteger("Products.LoopMod4");
906 bool renderStartRow = i % 3 == 0 ? true : false;
907 bool renderEndRow = i % 3 == 0 ? true : false;
908
909 if (i == 0 && totalPages > 1)
910 {
911 @:<div class="row row-ce" id="@currentPage">
912 }
913
914 @renderProduct(true, item, true); //This is from renderProduct.cshtml
915
916
917 if (productLoop.Count() - 1 == i && totalPages > 1)
918 {
919 @:</div>
920 }
921 }
922 }
923 }
924
925 @helper RenderOutletShopHeader()
926 {
927 <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')">
928 <div class="container">
929 <div class="row">
930 <div class="col-xs-12 col-md-8 col-lg-6">
931 <div class="text-area">
932 <div class="rte-content">
933 @Dynamicweb.Frontend.PageView.Current().CurrentParagraph.Text
934 </div>
935 <div class="red-divider"></div>
936 </div>
937 </div>
938 </div>
939 </div>
940 </div>
941 }
942
943
944 @helper RenderGroupHeader()
945 {
946 int ProductGroupVideoTop = GetInteger("Ecom:Group:Field.FirstwebProductGroupVideoTop");
947 string Description = GetString("Ecom:Group.Description");
948 string GroupName = GetString("Ecom:Group.Name");
949 string BgImage = GetString("Ecom:Group.LargeImage");
950 bool IsOutletShop = Firstweb.Custom.CustomCode.Frontend.Helpers.Millarco.IsOutletShop();
951 if (IsOutletShop && !String.IsNullOrEmpty(GetString("Ecom:Group:Field.FirstwebOutletGroupImage.Value.Clean")))
952 {
953 BgImage = GetString("Ecom:Group:Field.FirstwebOutletGroupImage.Value.Clean");
954 }
955
956 if (ProductGroupVideoTop > 0)
957 {
958 @RenderParagraphContent(ProductGroupVideoTop)
959 }
960 else
961 {
962 <div class="content-element solid-bg bg-image-and-text-element bg-secondary" style="background-image:url('@BgImage')">
963 <div class="container">
964 <div class="row">
965 <div class="col-xs-12 col-md-8 col-lg-6">
966 <div class="text-area">
967 @if (!String.IsNullOrEmpty(Description))
968 {
969 <div class="rte-content">
970 @Description
971 </div>
972 }
973 else
974 {
975 <h1 class="xs-m-t-0">@GroupName</h1>
976 }
977 <div class="red-divider"></div>
978 </div>
979 </div>
980 </div>
981 </div>
982 </div>
983 }
984 }
985
986 @helper RenderSearchHeader(string searchQuery)
987 {
988 <h1 class="h1 xs-m-t-0 tertiary-font">
989 @Translate("ProductList.SearchResultHeader", "Søgeresultat")
990 </h1>
991
992 <h4 class="h4 lg-m-b-0">
993 @Translate("ProductList.SearchResultText", "Resultater for din søgning"): @searchQuery
994 </h4>
995 }
996
997 @helper RenderParagraphHeader()
998 {
999 <h1 class="h1 lg-m-t-0 tertiary-font">@Dynamicweb.Frontend.PageView.Current().CurrentParagraph.Header</h1>
1000
1001 if (!String.IsNullOrEmpty(Dynamicweb.Frontend.PageView.Current().CurrentParagraph.Text))
1002 {
1003 <p>@Dynamicweb.Frontend.PageView.Current().CurrentParagraph.Text</p>
1004 }
1005 }
1006
1007
1008 @helper RenderGroups(List<Dynamicweb.Ecommerce.Products.Group> breadCrumbGroupList, string currentGroupId)
1009 {
1010 if (breadCrumbGroupList.Count() > 0)
1011 {
1012 var ParentGroup = breadCrumbGroupList.LastOrDefault();
1013 var baseLink = "/Default.aspx?ID=" + Dynamicweb.Frontend.PageView.Current().ID + "&GroupID=";
1014 if (ParentGroup != null)
1015 {
1016 <section class="product__sub-nav">
1017 <p class="xs-m-b-0">
1018 @ParentGroup.Name
1019 </p>
1020
1021 <ul>
1022 @foreach (var subgroup in ParentGroup.Subgroups)
1023 {
1024 <li>
1025 @if (subgroup.Id == currentGroupId)
1026 {
1027 <span>@subgroup.Name</span>
1028 }
1029 else
1030 {
1031 bool DisplayGroup = subgroup.Products.Count() > 0 || subgroup.Subgroups.Where(x => x.Products.Count() > 0).Count() > 0;
1032 if (DisplayGroup)
1033 {
1034 <a href="@baseLink@subgroup.Id">@subgroup.Name</a>
1035 }
1036 }
1037 </li>
1038 }
1039 </ul>
1040 </section>
1041 }
1042 }
1043 }
1044
1045 @helper RenderFacets()
1046 {
1047 foreach (LoopItem facetGroup in GetLoop("FacetGroups"))
1048 {
1049 foreach (LoopItem facet in facetGroup.GetLoop("Facets").Where(x => x.GetLoop("FacetOptions").Any()))
1050 {
1051 string facetName = facet.GetString("Facet.Name");
1052 string translatedFacetName = Translate("ProductList.FacetName" + facet.GetString("Facet.Name"), facet.GetString("Facet.Name"));
1053 bool hasOptions = facet.GetLoop("FacetOptions").Any();
1054 string hasOptionsCss = hasOptions ? "xs-p-t-1 xs-p-b-1" : "";
1055 string FacetIsOpen = facet.GetLoop("FacetOptions").Where(x => x.GetBoolean("FacetOption.Selected")).Any() ? "true" : "false";
1056
1057 <section class="bg-white filter" data-bind="defineObservable: { sortDropdown: @FacetIsOpen }">
1058 @if (hasOptions)
1059 {
1060 <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()) }">
1061 <h3 class="h3 xs-m-t-0 xs-m-b-0 tertiary-font font-size-base filterHeader"
1062 data-bind="toggleClassParent: 'active'">
1063 @translatedFacetName
1064 </h3>
1065 <span>
1066 <i class="fa fa-chevron-down"></i>
1067 </span>
1068 </button>
1069 }
1070
1071 <div class="filter__options line-height-base" data-bind="css: { hidden: !sortDropdown() }">
1072 @foreach (LoopItem option in facet.GetLoop("FacetOptions"))
1073 {
1074 var value = option.GetValue("FacetOption.Value");
1075 string label = option.GetString("FacetOption.Label").Replace("\"", """);
1076 if (label.ToUpper() == "TRUE" || label.ToUpper() == "FALSE")
1077 {
1078 label = Translate("ProductList.FacetOption:" + label, "Ja");
1079 }
1080
1081
1082 int count = option.GetInteger("FacetOption.Count");
1083 bool selected = option.GetBoolean("FacetOption.Selected");
1084 label += " (" + count + ")";
1085 <div class="form-group">
1086 <custom-checkbox params="{ label: '@label',
1087 value: '@value',
1088 checked: @(selected.ToString().ToLower()),
1089 name: '@facet.GetString("Facet.QueryParameter")' }" />
1090 </div>
1091 }
1092 </div>
1093 </section>
1094 }
1095 }
1096 }
1097
1098
1099 @helper RenderSorting(string sortOrder)
1100 {
1101 <section class="bg-white filter filter__container"
1102 data-bind="defineObservable: {
1103 sortOrder: '@sortOrder' || 'ASC',
1104 sortDropdown: false }">
1105 <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()) }">
1106 <p class="h3 xs-m-t-0 xs-m-b-0 tertiary-font font-size-base"
1107 data-bind="toggleClassParent: 'active'">
1108 @Translate("filtersort", "Sortering")
1109 </p>
1110
1111 <span>
1112 <i class="fa fa-chevron-down"></i>
1113 </span>
1114 </button>
1115
1116 <input type="hidden" name="SortBy" value="ProductNameSort" />
1117
1118 <section class="filter__options" data-bind="css: { hidden: !sortDropdown() }">
1119 <div class="form-group">
1120 <custom-radio params="{
1121 label: '@Translate("sortnameaz", "Navn: A - Å")',
1122 value: 'ASC',
1123 checked: sortOrder,
1124 name: 'SortOrder' }" />
1125 </div>
1126
1127 <div class="form-group xs-m-b-0">
1128 <custom-radio params="{
1129 label: '@Translate("sortnameza", "Navn: Å - A")',
1130 value: 'DESC',
1131 checked: sortOrder,
1132 name: 'SortOrder' }" />
1133 </div>
1134 </section>
1135 </section>
1136 }
1137
1138 @helper RenderGroupLevelFilter(IEnumerable<Dynamicweb.Ecommerce.Products.Group> groups, string currentGroupId, string activeGroup, int pageId)
1139 {
1140 var ProductGroups = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(currentGroupId);
1141 bool isTopLevelGroup = ProductGroups.IsTopGroup;
1142 var parentGroup = ProductGroups.PrimaryParentGroupId;
1143
1144 if (isTopLevelGroup)
1145 {
1146 foreach (var group in groups.Where(x => Firstweb.Custom.CustomCode.Frontend.Helpers.EcomGroups.IsFilterGroup(x)))
1147 {
1148 var currentGroup = group.Id.Equals(currentGroupId);
1149 var isCurrentGroup = currentGroup ? "is-active" : "";
1150
1151 <div class="@isCurrentGroup">
1152 <a href="/Default.aspx?Id=@pageId&groupid=@group.Id">@group.Name</a>
1153 </div>
1154
1155 if (currentGroup && group.HasChildGroups)
1156 {
1157 <div class="sub-group">
1158 @foreach (var isSubGroup in group.Subgroups)
1159 {
1160 var setActive = isSubGroup.Id == activeGroup ? "is-active" : "";
1161
1162 <div class="@setActive">
1163 <a href="/Default.aspx?Id=@pageId&groupid=@isSubGroup.Id">@isSubGroup.Name</a>
1164 </div>
1165 }
1166 @*@RenderGroupLevelFilter(group.Subgroups, currentGroupId, (level + 1))*@
1167 </div>
1168 }
1169 }
1170 }
1171 else
1172 {
1173 @RenderGroupLevelFilter(groups, parentGroup, currentGroupId, pageId)
1174 }
1175 }