Error executing template "Designs/Tapas/eCom/Product/product.cshtml" System.FormatException: Input string was not in a correct format. at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal) at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info) at System.Convert.ToInt32(String value) at Firstweb.ERP.Connector.Helper.Xml.GetInt(XmlNode _xmlNode, String _attributName) in C:\Users\ThomasLarsen\source\repos\Bikepartner\Firstweb.ErpConnector\Code\Helper.Xml.cs:line 80 at Firstweb.ERP.Connector.Configuration.Function.Fill(XmlNode _xmlNode) in C:\Users\ThomasLarsen\source\repos\Bikepartner\Firstweb.ErpConnector\Code\Configuration.Functions.cs:line 152 at Firstweb.ERP.Connector.Configuration.Function..ctor(XmlNode _xmlNode, String _erpOrigin, String _erpClass) in C:\Users\ThomasLarsen\source\repos\Bikepartner\Firstweb.ErpConnector\Code\Configuration.Functions.cs:line 110 at Firstweb.ERP.Connector.Configuration.Functions.GetFunctions(XmlNode _xmlNode) in C:\Users\ThomasLarsen\source\repos\Bikepartner\Firstweb.ErpConnector\Code\Configuration.Functions.cs:line 49 at Firstweb.ERP.Connector.Configuration.Functions.ReadSettings() in C:\Users\ThomasLarsen\source\repos\Bikepartner\Firstweb.ErpConnector\Code\Configuration.Functions.cs:line 65 at Firstweb.ERP.Connector.Configuration.Functions..ctor() in C:\Users\ThomasLarsen\source\repos\Bikepartner\Firstweb.ErpConnector\Code\Configuration.Functions.cs:line 33 at Firstweb.Custom.CustomCode.ERP.Data.GetBackorderLines..ctor(String customerNumber) in C:\Users\ThomasLarsen\source\repos\Bikepartner\Website\CustomCode\ERP\Data\GetBackorderLines.cs:line 46 at Firstweb.Custom.CustomCode.ERP.Data.GetBackorderLines.Instance() in C:\Users\ThomasLarsen\source\repos\Bikepartner\Website\CustomCode\ERP\Data\GetBackorderLines.cs:line 196 at Firstweb.Custom.CustomCode.Frontend.Helpers.Backordre.InBackorders(String itemNo, Int32& backorderRemaining) in C:\Users\ThomasLarsen\source\repos\Bikepartner\Website\CustomCode\Frontend\Helpers.Backordre.cs:line 15 at CompiledRazorTemplates.Dynamic.RazorEngine_206644594ef9407bbb165a8fc7af4de8.Execute() in E:\Dynamicweb\bikepartner.D365LIVE\Files\Templates\Designs\Tapas\eCom\Product\product.cshtml:line 860 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 System 4 @using System.Web; 5 @using System.Web.Script.Serialization; 6 @using System.Linq; 7 @using System.Collections.Generic; 8 @using Dynamicweb.Environment; 9 10 11 @inherits RazorTemplateBase<RazorTemplateModel<Template>> 12 @using Dynamicweb.Rendering; 13 @using System.Text.RegularExpressions; 14 @using Dynamicweb.Environment; 15 16 17 @helper renderProduct(bool showShopFunctionsAlternativeIfNotLoggedIn, LoopItem product, bool renderAs4Cols = false) 18 { 19 bool isBlocked = product.GetBoolean("Ecom:Product:Field.NAVIsBlocked"); 20 21 bool IsPurchaceProduct = (product.GetString("Ecom:Product:Field.NAVPurposeID") == "SKAFFE"); 22 23 string productID = product.GetString("Ecom:Product.ID"); 24 string productNumber = product.GetString("Ecom:Product.Number"); 25 string mainProductID = product.GetString("Ecom:Product:Field.FirstwebMainProductID"); 26 string PrimaryProductPageId = Firstweb.Custom.CustomCode.Tapas.Context.AreaPages.GetPageId("productcatalog"); 27 28 string productLink = product.GetString("Ecom:Product.Link.Clean"); 29 30 if (!String.IsNullOrEmpty(PrimaryProductPageId)) 31 { 32 productLink = "/Default.aspx?id=" + PrimaryProductPageId + "&productid=" + productID; 33 } 34 35 string languageId = product.GetString("Ecom:Product.LanguageID"); 36 string variantId = product.GetString("Ecom:Product.VariantID"); 37 38 string productName = product.GetString("Ecom:Product.Name"); 39 string productShortDescription = product.GetString("Ecom:Product.ShortDescription"); 40 41 double nettoPrice = product.GetDouble("Ecom:Product.Price.PriceWithoutVAT"); //GetString("Firstweb:ErpPriceInfo.NettoPriceFormatted"); 42 string bruttoPrice = product.GetString("Firstweb:EcomProduct:BruttoPriceFormattedWithSymbol"); 43 44 double bruttoPriceDouble = product.GetDouble("Firstweb:EcomProduct:BruttoPrice"); 45 double deltaBruttoNetto = Math.Abs(bruttoPriceDouble - nettoPrice); 46 if (product.GetBoolean("Firstweb:EcomProduct:BruttoPriceIsConverted") && deltaBruttoNetto < 0.5) 47 { 48 bruttoPrice = product.GetString("Ecom:Product.Price.PriceWithoutVATFormatted"); 49 } 50 51 string availableAmount = product.GetString("Firstweb:ErpStockInfo.StockQuantity"); 52 string stockColor = product.GetString("Firstweb:ErpStockInfo.StockColor"); 53 bool priceAndStockFound = product.GetBoolean("Firstweb:ErpPriceInfo.PriceAndStockFound"); 54 bool priceFound = product.GetBoolean("Firstweb:ErpPriceInfo.PriceFound"); 55 bool hasQuantityPrices = product.GetBoolean("Firstweb:ErpPriceInfo.HasQuantityPrices"); 56 string RRPrice = product.GetString("Firstweb:ErpPriceInfo:Prices.RRPFormatted"); 57 58 int productPackagingQuantity = product.GetInteger("Ecom:Product:Field.NAVMinQuantity"); 59 int defaultQuantity = productPackagingQuantity > 0 ? productPackagingQuantity : 1; 60 61 bool hasVariants = (product.GetLoop("VariantCombinations").Count() > 0); 62 63 //Images 64 List<Dynamicweb.Ecommerce.Products.Detail> productImages = Firstweb.Custom.CustomCode.Frontend.Helpers.ProductImages.GetProductImages(languageId, productID, variantId); 65 Dynamicweb.Ecommerce.Products.Detail primaryProductImage = productImages.FirstOrDefault(x=>x.IsDefault); //Tag you can use instead: product.GetString("Ecom:Product.ImageDefault.Clean"); 66 //check for valid default image 67 if (primaryProductImage == null) 68 { 69 primaryProductImage = new Dynamicweb.Ecommerce.Products.Detail { Value = "" }; 70 } 71 else if (primaryProductImage.Value == null) 72 { 73 primaryProductImage.Value = ""; 74 } 75 76 //Sorted: first by imagegroup then by sortorder 77 //@foreach (var productImage in productImages) 78 //{ 79 //productImage.Value; //This is the imagepath eks. /Images/products/R12155_10_2.jpg 80 //productImage.IsDefault; //If the image is default or not. 81 //} 82 83 string primaryProductImageUrl = "/admin/public/getimage.ashx?image=" + primaryProductImage.Value + "&altFmImage_path=/Files/Images/ecom/Products/no-image.jpg&width=500&height=300&Compression=90&Crop=5"; 84 if (String.IsNullOrEmpty(primaryProductImage.Value)) 85 { 86 primaryProductImageUrl = "/admin/public/getimage.ashx?image=/Files/Images/ecom/Products/no-image.jpg&width=500&height=300&Compression=90&Crop=5"; 87 } 88 89 //Other packagings 90 var otherPackagingProducts = Firstweb.Custom.CustomCode.Frontend.Helpers.OtherPackagingProducts.GetOtherPackagingProducts(mainProductID, false).Where(i => i.Id != productID); 91 var showOtherPackagingProducts = otherPackagingProducts.Count() > 0; 92 93 94 //Customer product number 95 //string customerProductNumber = Firstweb.Custom.CustomCode.Frontend.Helpers.CustomerProductNumbers.GetCustomerProductNumber(productID); 96 97 //OrderTemplate 98 int productInFavoritLists = product.GetInteger("Firstweb:Ecom:Product:OrderTemplate.InTemplates.Count"); 99 100 string orderLineId = product.GetString("Firstweb:OrderTemplate:Line.ID"); 101 string orderTemplateId = product.GetString("Firstweb:OrderTemplate:Line.OrderTemplateID"); 102 int orderLineQuantity = product.GetInteger("Firstweb:OrderTemplate:Line.Quantity"); 103 104 bool inFavourite = productInFavoritLists > 0 ? true : false; 105 string inFavouriteBoolJS = inFavourite.ToString().ToLower(); 106 107 bool isOrderTemplate = !String.IsNullOrEmpty(orderLineId); 108 109 string productPriceCacheKey = orderLineId != "" ? orderLineId : productNumber; 110 111 112 113 114 string stock = ""; 115 116 string addBorderCss = isOrderTemplate ? "border-1" : ""; 117 118 119 if (!priceAndStockFound) 120 { 121 stock = "asyncLoad"; 122 } 123 else 124 { 125 stock = availableAmount; 126 } 127 128 string WidthClass = renderAs4Cols ? "col-md-4 col-lg-3" : "col-md-4"; 129 bool ShowShopFunctions = Firstweb.Custom.CustomCode.Tapas.Context.Current.ShopFunctionsVisibility.ShowShopFunctions(); 130 string BrandLogo = "/admin/public/getimage.ashx?image=" + product.GetString("Ecom:Product:Field.FirstwebBrandLogo.Value.FullPath") + "&height=25&crop=5"; 131 string BrandName = product.GetString("Ecom:Product:Field.FirstwebBrand.Value.Clean"); 132 string AddingToCartText = Translate("Product.AddingToCart", "Tilføjer produkt"); 133 string PickListText = Translate("Ordertemplate.SelectList", "Vælg en liste"); 134 bool ShowBeforePrice = product.GetBoolean("Firstweb:EcomProduct:DisplayBeforePrice"); 135 string BeforePriceFormatted = product.GetString("Firstweb:EcomProduct:BeforePriceFormattedWithSymbol"); 136 string StockStatus = product.GetString("Firstweb:StockStatusColor"); //hvis rød og confirmed deliverydate - hvis dato 137 string StockLabel = product.GetString("Firstweb:StockStatusTitle"); 138 string ConfirmedDeliveryDate = product.GetString("Ecom:Product:Field.NAVConfirmedDeliveryDate.Value.Clean"); 139 bool NotInStock = product.GetBoolean("Firstweb:NotInStock"); 140 bool ShowQuantityPrices = product.GetBoolean("Firstweb:EcomProduct:ShowQuantityPricelistIcon"); 141 string Collisize = product.GetString("Ecom:Product:Field.NAVColli"); 142 string CatalogueRemark = product.GetString("Ecom:Product:Field.NAVCatalogRemark.Value"); 143 bool HidePrices = Firstweb.Custom.CustomCode.Frontend.Helpers.Product.HidePrices(); 144 string productCurrency = product.GetString("Ecom:Product.Currency.Symbol"); 145 146 IEnumerable<Dynamicweb.Ecommerce.Products.ProductRelated> replacementProducts = Firstweb.Custom.CustomCode.Frontend.Helpers.Product.GetReplacementProducts(productID); 147 148 bool HasSimilarProducts = Firstweb.Custom.CustomCode.Frontend.Helpers.Product.HasSimilarProducts(productID); 149 150 151 bool showSubInfoContainer = (HasSimilarProducts) || (ShowShopFunctions && (ShowQuantityPrices && !HidePrices)); 152 153 string showSubInfoClass = "show-subinfo"; 154 155 int backorderRemaining = 0; 156 bool inBackorders = Firstweb.Custom.CustomCode.Frontend.Helpers.Backordre.InBackorders(productNumber, out backorderRemaining); 157 string addToCartWarningText = inBackorders ? Translate("Cart.RestorderFirstPart", "Du har allerede") + " " + backorderRemaining + " " + Translate("Cart.RestorderSecondPart", "i restorder af denne.") : ""; 158 string addToCartWarningTextConfirmation = inBackorders ? addToCartWarningText + " - " + Translate("Cart.RestorderConfirm", "Vil du forsætte?") : ""; 159 160 161 <!-- ko viewModel: 'ProductViewModel'--> 162 <!-- ko initValue: {observable: ProductId, value:'@productID'}--><!-- /ko--> 163 <div class="col-xs-12 col-sm-6 @WidthClass xs-m-b-3 price product-tile" data-productid="@productNumber" data-productkey="@productPriceCacheKey" data-test="@PrimaryProductPageId"> 164 <div class="product-list-item bg-white position-relative @showSubInfoClass"> 165 166 <a href="@productLink"> 167 @if (!String.IsNullOrEmpty(CatalogueRemark)) 168 { 169 <div class="catalogue-remark">@CatalogueRemark</div> 170 } 171 <div class="brand-image"> 172 @if (!String.IsNullOrEmpty(product.GetString("Ecom:Product:Field.FirstwebBrandLogo.Value.FullPath"))) 173 { 174 <img src="@BrandLogo" alt="@BrandName" /> 175 } 176 </div> 177 <div class="product-image"> 178 <img src="@primaryProductImageUrl" alt="@productName" style="max-height:150px;"/> 179 </div> 180 <div class="product-info"> 181 <p class="product-info-top"><span class="product-number">@productNumber</span><span class="product-colli">@Translate("Product.ColliSize", "Kolli"): @Collisize</span></p> 182 <p class="product-name">@productName</p> 183 184 </div> 185 @if (!isBlocked) 186 { 187 188 189 if (ShowShopFunctions) 190 { 191 <div class="productlist-price-area "> 192 <div class="width-50"> 193 @if (IsPurchaceProduct) 194 { 195 <p class="purchace-product text-left"> 196 <i class="far fa-truck"></i> @Translate("Product.PurchaceProduct", "Skaffevare") 197 </p> 198 } 199 else 200 { 201 <p class="stock-indicator"> 202 <span class="stock-load-async" style="background-color: @StockStatus"></span> 203 <span class="stock-name">@StockLabel</span> 204 <span class="stock-name js-in-stock-again hide">@Translate("Product.StockExpectedAgaing", "På lager: ")<span class="js-stock-date"></span></span> 205 </p> 206 if (NotInStock && !String.IsNullOrEmpty(ConfirmedDeliveryDate)) 207 { 208 <p class="stock-cdd">@Translate("Product.ConfirmedDeliveryDate", "På lager"): @ConfirmedDeliveryDate</p> 209 } 210 211 if (StockStatus == "#009600") 212 { 213 <p class="stock-cdd">@Translate("Product.OnStockDeliveryText", "Levering: 1-2 dage")</p> 214 } 215 } 216 217 </div> 218 <div class="width-50"> 219 220 @if (!HidePrices) 221 { 222 223 <p><span class="price-display-normalprice">@bruttoPrice</span></p> 224 <p><span class="price-display-yourprice">@product.GetString("Ecom:Product.Price.PriceWithoutVATFormatted")</span></p> 225 if (ShowBeforePrice && 1==0) 226 { 227 <p><span class="price-display-medium-label">@Translate("Product.Beforeprice", "Førpris")</span> <span class="price-display-medium">@BeforePriceFormatted</span></p> 228 } 229 } 230 </div> 231 </div> 232 233 234 } 235 } 236 237 </a> 238 @if (!isBlocked) 239 { 240 if (ShowShopFunctions) 241 { 242 <div class="add-to-cart-area"> 243 @if (isOrderTemplate) 244 { 245 <!-- ko initValue: {observable: Quantity, value:@orderLineQuantity}--><!-- /ko--> 246 } 247 else 248 { 249 <!-- ko initValue: {observable: Quantity, value:@defaultQuantity}--><!-- /ko--> 250 } 251 <input class="product-quantity js-product-quantity" type="number" name="quantity" data-bind="value: Quantity, event: { keypress: function() { if (window.event.keyCode == 13) { $parent.addItemToCart(ProductId(), $(window.event.target).val(), '', '', '@AddingToCartText'); animateCart(event); } return true;}}" /> 252 <div title="@addToCartWarningText" class="btn btn-primary js-product-buy-btn" data-addedtocarttext="@Translate("Product.AddedToCart", "Varen er tilføjet")" 253 data-bind="click: function() { if ('@inBackorders' == 'False' || confirm('@addToCartWarningTextConfirmation')) { $parent.addItemToCart(ProductId(), Quantity(), '', '', '@AddingToCartText'); animateCart(event); }}" 254 data-productid="@productID"> 255 @Translate("Product.AddToCart", "TILFØJ TIL KURV") 256 257 @if (inBackorders) 258 { 259 <i class="fas fa-exclamation-triangle"></i> 260 } 261 </div> 262 <div class="not-in-stock-indicator js-not-in-stock-indicator hide"> 263 <p>@Translate("Product.NotInStock", "Ikke på lager")</p> 264 </div> 265 @if (!isOrderTemplate) 266 { 267 <div class="favorite-list-icon" data-toggle="modal" data-target="#modal-@productID" data-bind="with: OrderTemplateViewModel"> 268 <div class="favorite-list-icon-btn" data-bind=" 269 oninit: function() { IsInFavoriteList('@inFavourite'.toLowerCase()) }, 270 css : { showFavorite : ShowOrderTemplateDialog, showNewList : OrderTemplateShowNewList, added: IsInFavoriteList() == 'true', notadded: IsInFavoriteList() == 'false' }, 271 click: ToggleOrderTemplateDialog"> 272 <i class="fas fa-star"></i> 273 </div> 274 </div> 275 <div class="modal fade" id="modal-@productID" tabindex="-1" role="dialog" data-bind="with: OrderTemplateViewModel"> 276 <!-- ko initValue: {observable: OrderTemplateRelationCount, value:'@productInFavoritLists'}--><!-- /ko--> 277 <!-- ko initValue: {observable: ShowInFavourite, value: @inFavouriteBoolJS}--><!-- /ko--> 278 <!-- ko initValue: {observable: ModalSelector, value: '#modal-@productID'}--><!-- /ko--> 279 <div class="modal-dialog" role="document"> 280 <div class="modal-content fav-list"> 281 282 <p class="favlist-header">@Translate("Ordertemplate.AddToExistingList", "Tilføj til eksisterende favoritliste")</p> 283 284 <div class="existing-lists"> 285 286 <select class="favField select-fix" 287 data-bind="options: OrderTemplateList, 288 optionsCaption: '@PickListText', 289 optionsText: function(item) { return item.Value.Name() + ' (' + item.Value.Count() + ')' }, 290 value: OrderTemplateSelectedList"></select> 291 292 <input class="product-quantity" type="number" name="quantity" data-bind="textInput: OrderTemplateQuantity" /> 293 294 <div class="btn btn-primary" 295 data-bind="click: function() { 296 OrderTemplateShowNewList() 297 ? CreateNewOrderTemplateList('@productID') 298 : AddProductToOrderTemplate('@productID' , OrderTemplateQuantity()) 299 }"> 300 @Translate("Ordertemplate.AddToList", "Tilføj") 301 </div> 302 303 </div> 304 305 <p class="or-text">@Translate("Ordertemplate.OrNewList", "eller...")</p> 306 307 <p class="favlist-header">@Translate("Ordertemplate.AddToNewList", "Tilføj til ny favoritliste")</p> 308 309 <form id="EditForm-@productID" 310 name="EditForm"> 311 <label class="xs-m-b-1" for="name">@Translate("Ordertemplate.ListName", "Favoritliste navn")</label> 312 <div class="new-list"> 313 <input type="text" 314 name="name" 315 _id="name" 316 data-bind="textInput: OrderTemplateNewListName" 317 autofocus 318 autocomplete="off" /> 319 320 <input class="product-quantity" type="number" name="quantity" data-bind="textInput: OrderTemplateNewListQuantity" /> 321 322 <button type="submit" 323 class="btn btn-primary" 324 _id="btnSave" 325 data-bind="click: function() { CreateNewOrderTemplateList('@productID', OrderTemplateNewListQuantity()) }"> 326 @Translate("Ordertemplate.SaveToNewList", "Tilføj til ny favoritliste") 327 </button> 328 </div> 329 </form> 330 331 </div> 332 </div> 333 </div> 334 } 335 else 336 { 337 <div class="favorite-list-icon" data-bind="with: OrderTemplateViewModel"> 338 <!-- ko initValue: {observable: OrderTemplateId, value:'@orderTemplateId'}--><!-- /ko--> 339 <!-- ko initValue: {observable: OrderTemplateLineId, value:'@orderLineId'}--><!-- /ko--> 340 <i class="fas fa-times" 341 data-bind=" 342 oninit: function() { IsInFavoriteList('@inFavourite'.toLowerCase()) }, 343 css: { showFavorite: ShowOrderTemplateDialog, showNewList: OrderTemplateShowNewList, active: IsInFavoriteList() == 'true' }, 344 click: DeleteOrderTemplateLine"> 345 </i> 346 </div> 347 } 348 </div> 349 } 350 351 if (showSubInfoContainer) 352 { 353 <div class="subinfo-container"> 354 @if (HasSimilarProducts && 1==2) 355 { 356 <a href="@productLink" class="similarproducts-info">@Translate("Product.HasSimilarProducts", "Lignende produkter")</a> 357 } 358 @if (ShowShopFunctions) 359 { 360 if (ShowQuantityPrices && !HidePrices) 361 { 362 <div class="quantity-prices-container"> 363 @RenderQuantityPrices(productNumber, productCurrency, productID) 364 </div> 365 } 366 367 } 368 369 370 </div> 371 } 372 373 374 } 375 else 376 { 377 @RenderReplacementProducts(replacementProducts, PrimaryProductPageId) 378 } 379 </div> 380 381 </div> 382 <!-- /ko--> 383 } 384 385 386 387 388 389 @helper renderRelatedProduct(LoopItem repatedProduct) 390 { 391 string productID = repatedProduct.GetString("Ecom:Product.ID"); 392 string productNumber = repatedProduct.GetString("Ecom:Product.Number"); 393 string mainProductID = GetString("Ecom:Product:Field.FirstwebMainProductID"); 394 395 string productName = repatedProduct.GetString("Ecom:Product.Name"); 396 string productDescription = GetString("Ecom:Product.LongDescription"); 397 string productShortDescription = GetString("Ecom:Product.ShortDescription"); 398 399 string nettoPrice = repatedProduct.GetString("Firstweb:ErpPriceInfo.NettoPriceFormatted"); 400 int bruttoPrice = repatedProduct.GetInteger("Firstweb:ErpPriceInfo.BruttoAmountFormattedNoSymbol"); 401 402 int productPackagingQuantity = repatedProduct.GetInteger("Ecom:Product:Field.NAVMinQuantity"); 403 int defaultQuantity = productPackagingQuantity > 0 ? productPackagingQuantity : 1; 404 405 string languageId = repatedProduct.GetString("Ecom:Product.LanguageID"); 406 string variantId = repatedProduct.GetString("Ecom:Product.VariantID"); 407 408 int productInFavoritLists = GetInteger("Firstweb:Ecom:Product:OrderTemplate.InTemplates.Count"); 409 410 List<Dynamicweb.Ecommerce.Products.Detail> productImages = Firstweb.Custom.CustomCode.Frontend.Helpers.ProductImages.GetProductImages(languageId, productID, variantId); 411 Dynamicweb.Ecommerce.Products.Detail primaryProductImage = productImages.FirstOrDefault(x=>x.IsDefault); //Tag you can use instead: product.GetString("Ecom:Product.ImageDefault.Clean"); 412 //check for valid default image 413 if (primaryProductImage == null) 414 { 415 primaryProductImage = new Dynamicweb.Ecommerce.Products.Detail { Value = "" }; 416 } 417 else if (primaryProductImage.Value == null) 418 { 419 primaryProductImage.Value = ""; 420 } 421 422 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"; 423 424 //Sorted: first by imagegroup then by sortorder 425 //@foreach (var productImage in productImages) 426 //{ 427 //productImage.Value; //This is the imagepath eks. /Images/products/R12155_10_2.jpg 428 //productImage.IsDefault; //If the image is default or not. 429 //} 430 431 <li> 432 <article class="xs-p-2 lg-p-1 rounded-5 border-1 border-color-default"> 433 <div class="row is-flex xs-is-flex-column sm-is-flex-col md-is-flex-col"> 434 435 <div class="col-md-12 md-is-flex lg-p-r-0"> 436 <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"> 437 <img class="img-responsive xs-auto-margin sm-auto-margin" src="@primaryProductImageUrl" /> 438 </section> 439 440 <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"> 441 <header class="xs-m-b-1"> 442 <h2 data-bind="text: name" 443 class="h2 tertiary-font xs-m-t-0"> 444 @productName 445 </h2> 446 </header> 447 448 <section class="xs-m-b-1 clearfix"> 449 <span class="pull-left font-size-small"> 450 @Translate("Product.NumberShort", "Varenr."): <span>@productNumber</span> 451 </span> 452 </section> 453 454 <section class="word-break"> 455 <p class="font-size-small"> 456 @productShortDescription 457 </p> 458 </section> 459 </section> 460 </div> 461 462 <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 463 lg-p-l-0 is-flex is-flex-col sm-is-flex-row sm-is-flex-wrap sm-flex-justify-space-between 464 md-is-flex-row md-is-flex-wrap md-flex-justify-space-between lg-flex-grow-2 lg-flex-justify-space-between"> 465 466 <div class="is-flex xs-m-t-1 sm-m-t-0 is-flex-col lg-m-b-auto"> 467 468 </div> 469 470 <div class="is-flex is-flex-col md-m-b-1 lg-m-b-0"> 471 <h4 class="h4 tertiary-font font-size-16px xs-m-b-1 sm-m-t-0 md-text-right lg-text-right"> 472 @nettoPrice 473 </h4> 474 475 <section class="xs-m-b-1 clearfix is-flex xs-flex-space-between lg-is-row-reverse"> 476 <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"> 477 @renderQuantityBox(defaultQuantity) 478 </div> 479 480 <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"> 481 <span>@Translate("Product.Packaging", "Forpakning"): </span> 482 <span> @productPackagingQuantity</span> 483 </div> 484 </section> 485 </div> 486 487 <section class="t-align-right clearfix sm-width-100 md-width-100"> 488 <button _data-bind="click: handleAddProductToCart" 489 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"> 490 @Translate("Product.AddToCart", "Tilføj til kurv") 491 </button> 492 </section> 493 </section> 494 495 </div> 496 </article> 497 </li> 498 499 500 501 } 502 503 @helper renderProductBuyBox(bool showShopFunctionsAlternativeIfNotLoggedIn, string productName, string productId, string price, int productPackagingQuantity, int quantity, string stockColor) 504 { 505 506 507 <article class="product-packaging border-bottom-1"> 508 <section class="row md-is-flex lg-is-flex md-is-flex-center lg-is-flex-center"> 509 <section class="packaging-section col-md-4 col-lg-5"> 510 <h4 class="h4 xs-m-t-0 xs-m-b-0 tertiary-font v-align-mid">@productName</h4> 511 </section> 512 513 514 515 @if (Firstweb.Custom.CustomCode.Tapas.Context.Current.ShopFunctionsVisibility.ShowShopFunctions()) 516 { 517 <section class="packaging-section md-p-l-0 xs-col-12 col-md-2 col-lg-2 tertiary-font"> 518 <span>@price</span> 519 520 521 </section> 522 <div class="stock md-is-self-end lg-is-self-end lg-order-0" > 523 @Translate("Product.StockStatus", "Lagerstatus"): <div class="stock-load-async @stockColor"></div> 524 525 </div> 526 <section class="packaging-section md-p-l-0 lg-p-r-8p packaging-section--alt xs-col-12 col-md-4 col-lg-3"> 527 <ul class="list-unstyled lg-m-l-auto lg-p-r-24p xs-m-b-0"> 528 <li> 529 <h5 class="h5 xs-m-b-0 xs-m-t-0 line-height-16px"> 530 <span>@Translate("Product.Packaging", "Forpakning"): </span> 531 <span> @productPackagingQuantity</span> 532 </h5> 533 </li> 534 </ul> 535 536 @renderQuantityBox(quantity) 537 538 </section> 539 540 <section class="packaging-section md-p-l-0 packaging-section--buy xs-col-12 col-md-2 col-lg-2 t-align-right"> 541 <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" 542 _data-bind="click: handleAddProductToCart"> 543 @Translate("Product.AddToCart", "Tilføj til kurv") 544 </button> 545 </section> 546 547 } 548 else if (showShopFunctionsAlternativeIfNotLoggedIn) 549 { 550 var replaceWith = Firstweb.Custom.CustomCode.Tapas.Context.Current.ShopFunctionsVisibility.ReplaceWith(); 551 552 <section> 553 554 @if (replaceWith == "LOGIN") 555 { 556 <text>@renderLogin()</text> 557 } 558 else if (replaceWith == "RESELLER") 559 { 560 <text>@renderResellerLink()</text> 561 } 562 </section> 563 } 564 565 </section> 566 </article> 567 } 568 569 570 @helper renderInstantSearchProduct(LoopItem product) 571 { 572 bool isBlocked = product.GetBoolean("Ecom:Product:Field.NAVIsBlocked"); 573 string productID = product.GetString("Ecom:Product.ID"); 574 string productNumber = product.GetString("Ecom:Product.Number"); 575 string mainProductID = product.GetString("Ecom:Product:Field.FirstwebMainProductID"); 576 577 string productLink = product.GetString("Ecom:Product.Link.Clean"); 578 579 string productName = product.GetString("Ecom:Product.Name"); 580 string productShortDescription = product.GetString("Ecom:Product.ShortDescription"); 581 582 int productPackagingQuantity = product.GetInteger("Firstweb:ErpPriceInfo:ExtraInfos.PackagingSize"); 583 int defaultQuantity = productPackagingQuantity > 0 ? productPackagingQuantity : 1; 584 585 string languageId = product.GetString("Ecom:Product.LanguageID"); 586 string variantId = product.GetString("Ecom:Product.VariantID"); 587 588 bool hasVariants = (product.GetLoop("VariantCombinations").Count() > 0); 589 590 //Images 591 List<Dynamicweb.Ecommerce.Products.Detail> productImages = Firstweb.Custom.CustomCode.Frontend.Helpers.ProductImages.GetProductImages(languageId, productID, variantId); 592 Dynamicweb.Ecommerce.Products.Detail primaryProductImage = productImages.FirstOrDefault(x=>x.IsDefault); //Tag you can use instead: product.GetString("Ecom:Product.ImageDefault.Clean"); 593 594 //check for valid default image 595 if (primaryProductImage == null) 596 { 597 primaryProductImage = new Dynamicweb.Ecommerce.Products.Detail { Value = "" }; 598 } 599 else if (primaryProductImage.Value == null) 600 { 601 primaryProductImage.Value = ""; 602 } 603 604 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"; 605 if (String.IsNullOrEmpty(primaryProductImage.Value)) 606 { 607 primaryProductImageUrl = "/admin/public/getimage.ashx?image=/Files/Images/ecom/Products/no-image.jpg&width=200&height=125&Compression=90&Crop=5"; 608 } 609 //Sorted: first by imagegroup then by sortorder 610 //@foreach (var productImage in productImages) 611 //{ 612 //productImage.Value; //This is the imagepath eks. /Images/products/R12155_10_2.jpg 613 //productImage.IsDefault; //If the image is default or not. 614 //} 615 616 //Other packagings 617 //var otherPackagingProducts = Firstweb.Custom.CustomCode.Frontend.Helpers.OtherPackagingProducts.GetOtherPackagingProducts(mainProductID, false).Where(i => i.Id != productID); 618 //var showOtherPackagingProducts = otherPackagingProducts.Count() > 0; 619 620 int loopCount = product.GetInteger("Products.LoopCounter") - 1; 621 <div class="col-xs-12 col-sm-3 xs-m-b-1"> 622 623 <article class="instant-search-product bg-white productCount @loopCount" data-bind="css: {'item--selected': navSelectedItem() == @loopCount}"> 624 <div class="cursor-pointer info" 625 data-bind="click: function() { window.location.href='@productLink'}"> 626 <div class="hidden-xs product-image"> 627 <img class="img-responsive center-block" src="@primaryProductImageUrl"> 628 </div> 629 630 <div class="name"> 631 <p>@productName</p> 632 633 634 <span>@Translate("Product.NumberShort", "Varenr.") @productNumber</span> 635 </div> 636 </div> 637 638 @if (Firstweb.Custom.CustomCode.Tapas.Context.Current.ShopFunctionsVisibility.ShowShopFunctions()) 639 { 640 <div class="buy-container" data-bind="defineObservable: { quantity: 1 }"> 641 642 <input class="product-quantity" type="number" name="quantity" data-bind="value: quantity" /> 643 644 <button class="btn btn-primary btn-xs add-to-cart" 645 data-bind="click: function(evt) { $parent.onAddToCart('@productID', quantity()) }"> 646 @Translate("Product.AddToCart", "Tilføj til kurv") 647 </button> 648 </div> 649 } 650 </article> 651 652 </div> 653 654 } 655 656 657 658 @helper renderQuantityBox(int quantity) 659 { 660 <input class="product-quantity" type="number" name="quantity" value="@quantity" /> 661 } 662 663 664 @helper renderLogin() 665 { 666 <button class="btn btn-primary" data-toggle="modal" data-target=".loginModal">@Translate("Product.LoginToShop", "Log ind for at købe")</button> 667 } 668 @helper renderResellerLink() 669 { 670 <a href="@Firstweb.Custom.CustomCode.Tapas.Context.Current.ShopFunctionsVisibility.ReplaceLink()" class="btn btn-primary">@Translate("Product.FindReseller", "Find forhandler")</a> 671 } 672 673 @helper RenderQuantityPrices(string productNumber, string productCurrency, string productID) 674 { 675 <div class="quantity-prices" data-bind="getQuantityPrices: { productId: '@productID', pageId: '@Firstweb.Custom.CustomCode.Tapas.Context.AreaPages.GetPageId("productcatalog")', linkText: '@Translate("Product.ShowAllCombinedDiscountsProducts.LinkText", "Se alle samkøbsrabat produkter for")'}"> 676 <span> 677 @Translate("QuantityPrices.Text", "% køb flere spar mere") 678 </span> 679 680 <i class="fal fa-chevron-down"></i> 681 <div class="quantity-prices-results js-results"> 682 <div class="xs-m-t-1 js-quantity-discount-html"></div> 683 <div class="xs-m-t-1 js-multine-discount-html"></div> 684 </div> 685 </div> 686 } 687 688 @helper RenderReplacementProducts(IEnumerable<Dynamicweb.Ecommerce.Products.ProductRelated> replacementProducts, string _primaryProductPageId) 689 { 690 691 if (replacementProducts.Any(rp => rp.Product != null)) 692 { 693 <div class="blocked-product"> 694 <p class="blocked-product-header">@Translate("Product.ProductIsBlocked", "Varen er udgået")</p> 695 <div class="replacement-products" data-bind="replacementProducts"> 696 <span> 697 @Translate("ReplacementProducts.Text", "Se erstatningsvarer") 698 </span> 699 <i class="fas fa-sort-down"></i> 700 <div class="replacement-products-results js-results"> 701 702 @foreach (var replacementProduct in replacementProducts.Where(rp => rp.Product != null)) 703 { 704 string productLink = "/Default.aspx?id=" + _primaryProductPageId + "&productid=" + replacementProduct.Product.Id; 705 <a href="@productLink" class="xs-m-b-0">@replacementProduct.Product.Number</a> 706 } 707 708 </div> 709 </div> 710 </div> 711 } 712 } 713 714 @{ 715 string configForceStock = GetString("Firstweb:ErpStockInfo.Configuration(ForceStock)"); 716 string configForcePrice = GetString("Firstweb:ErpPriceInfo.Configuration(ForcePrice)"); 717 string configForceQuantityPrices = GetString("Firstweb:ErpPriceInfo.Configuration(ForceQuantityPrices)"); 718 string configPreparePricesAndStocksOnRelatedProducts = GetString("Firstweb:ErpPriceInfo.Configuration(PreparePricesAndStocksOnRelatedProducts)"); 719 720 string productID = GetString("Ecom:Product.ID"); 721 string productNumber = GetString("Ecom:Product.Number"); 722 723 string languageId = GetString("Ecom:Product.LanguageID"); 724 string variantId = GetString("Ecom:Product.VariantID"); 725 726 string mainProductID = GetString("Ecom:Product:Field.FirstwebMainProductID"); 727 728 string productName = GetString("Ecom:Product.Name"); 729 string productDescription = GetString("Ecom:Product.LongDescription"); 730 731 //Fallback til engelsk beskrivelse fjernet 732 //if (String.IsNullOrEmpty(productDescription)) 733 //{ 734 // productDescription = GetString("Ecom:Product:Field.Supplier_ProductDescription_EN"); 735 //} 736 737 string productShortDescription = GetString("Ecom:Product.ShortDescription"); 738 739 double nettoPrice = GetDouble("Ecom:Product.Price.PriceWithoutVAT"); //GetString("Firstweb:ErpPriceInfo.NettoPriceFormatted"); 740 string bruttoPrice = GetString("Firstweb:EcomProduct:BruttoPriceFormattedWithSymbol"); 741 742 double bruttoPriceDouble = GetDouble("Firstweb:EcomProduct:BruttoPrice"); 743 double deltaBruttoNetto = Math.Abs(bruttoPriceDouble - nettoPrice); 744 if (GetBoolean("Firstweb:EcomProduct:BruttoPriceIsConverted") && deltaBruttoNetto < 0.5) 745 { 746 bruttoPrice = GetString("Ecom:Product.Price.PriceWithoutVATFormatted"); 747 } 748 749 750 bool hasQuantityPrices = GetBoolean("Firstweb:ErpPriceInfo.HasQuantityPrices"); 751 752 string availableAmount = GetString("Firstweb:ErpStockInfo.StockQuantity"); 753 string stockColor = GetString("Firstweb:ErpStockInfo.StockColor"); 754 string productCurrency = GetString("Ecom:Product.Currency.Symbol"); 755 756 int productPackagingQuantity = GetInteger("Ecom:Product:Field.NAVMinQuantity"); 757 int defaultQuantity = productPackagingQuantity > 0 ? productPackagingQuantity : 1; //udskrives i salgskvanti og antals felt ved læg i kurv 758 759 int productInFavoritLists = GetInteger("Firstweb:Ecom:Product:OrderTemplate.InTemplates.Count"); 760 string inFavouriteBoolJS = productInFavoritLists > 0 ? "true" : "false"; 761 bool hasVariants = (GetLoop("VariantCombinations").Count() > 0); 762 763 string Collisize = GetString("Ecom:Product:Field.NAVColli"); //Antal i kolli 764 765 bool IsPurchaceProduct = (GetString("Ecom:Product:Field.NAVPurposeID") == "SKAFFE"); 766 767 bool HidePrices = Firstweb.Custom.CustomCode.Frontend.Helpers.Product.HidePrices(); 768 769 string currentPageId = Dynamicweb.Context.Current.Request.GetString("ID"); 770 771 //Images 772 List<Dynamicweb.Ecommerce.Products.Detail> productImages = Firstweb.Custom.CustomCode.Frontend.Helpers.ProductImages.GetProductImages(languageId, productID, variantId); 773 Dynamicweb.Ecommerce.Products.Detail primaryProductImage = productImages.FirstOrDefault(x => x.IsDefault); //Tag you can use instead: product.GetString("Ecom:Product.ImageDefault.Clean"); 774 775 //check for valid default image 776 if (primaryProductImage == null) 777 { 778 primaryProductImage = new Dynamicweb.Ecommerce.Products.Detail { Value = "" }; 779 } 780 else if (primaryProductImage.Value == null) 781 { 782 primaryProductImage.Value = ""; 783 } 784 785 786 string primaryProductImageUrl = "/admin/public/getimage.ashx?image=" + primaryProductImage.Value + "&altFmImage_path=/Files/Images/ecom/Products/no-image.jpg&width=1200&Compression=99&Crop=5"; 787 if (String.IsNullOrEmpty(primaryProductImage.Value)) 788 { 789 primaryProductImageUrl = "/admin/public/getimage.ashx?image=/Files/Images/ecom/Products/no-image.jpg&width=1200&Compression=99&Crop=5"; 790 } 791 792 //Other packagings 793 var otherPackagingProducts = Firstweb.Custom.CustomCode.Frontend.Helpers.OtherPackagingProducts.GetOtherPackagingProducts(mainProductID).Where(i => i.Id != productID); 794 var showOtherPackagingProducts = otherPackagingProducts.Count() > 0; 795 796 //Documents 797 var productDocuments = Firstweb.Custom.CustomCode.Frontend.Helpers.ProductDocuments.Instance(productNumber, mainProductID).GetDocuments(); 798 799 //Related products 800 var productRelatedGroups = GetLoop("ProductRelatedGroups").Where(g => g.GetString("Ecom:Product:RelatedGroup.GroupID") != "RELGRP12"); 801 bool showRelatedProducts = productRelatedGroups.Any(); 802 803 //Related articles 804 var relatedArticles = Firstweb.Custom.CustomCode.Frontend.Helpers.Articles.GetRelatedArticles(productID); 805 806 bool showRelatedArticles = relatedArticles.Count > 0; 807 808 809 var breadCrumbGroupList = Firstweb.Custom.CustomCode.Frontend.Helpers.EcomGroups.getBreadCrumbGroupListByProduct(productID, true); 810 811 string BrandLogo = "/admin/public/getimage.ashx?image=" + GetString("Ecom:Product:Field.FirstwebBrandLogo.Value.FullPath") + "&height=40&crop=5"; 812 string BrandName = GetString("Ecom:Product:Field.FirstwebBrand.Label"); 813 814 string ByggebasenNumber = GetString("Ecom:Product:Field.FirstwebBBN.Value.Clean"); 815 string EAN = GetString("Ecom:Product:Field.FirstwebEAN.Value.Clean"); 816 string RRP = GetString("Firstweb:ErpPriceInfo:Prices.RRPFormatted"); 817 818 string priceWithoutVAT = GetString("Ecom:Product.Price.PriceWithoutVATFormatted"); 819 820 string productCatalog_PageId = Firstweb.Custom.CustomCode.Tapas.Context.AreaPages.GetPageId("productcatalog"); 821 822 string CatalogueRemark = GetString("Ecom:Product:Field.NAVCatalogRemark.Value"); 823 824 bool ShowShopFunctions = Firstweb.Custom.CustomCode.Tapas.Context.Current.ShopFunctionsVisibility.ShowShopFunctions(); 825 826 var QuantityPrices = GetLoop("Firstweb:ErpPriceInfo:QuantityPrices"); 827 828 string YtVideoId = GetString("Ecom:Product:Field.FirstwebVideoID.Value"); 829 string YtVideoPreviewImage = $"https://img.youtube.com/vi/{YtVideoId}/0.jpg"; 830 831 bool isBlocked = GetBoolean("Ecom:Product:Field.NAVIsBlocked"); 832 IEnumerable<Dynamicweb.Ecommerce.Products.ProductRelated> replacementProducts = Firstweb.Custom.CustomCode.Frontend.Helpers.Product.GetReplacementProducts(productID); 833 834 string DocumentLink_UserManual = GetString("Ecom:Product:Field.FirstwebUserManual.Value.Clean"); 835 string DocumentLink_DataSheet = GetString("Ecom:Product:Field.FirstwebDataSheet.Value.Clean"); 836 string DocumentLink_LockCertificate = GetString("Ecom:Product:Field.FirstwebLockCertificate.Value.Clean"); 837 string DocumentLink_BikelightTest = GetString("Ecom:Product:Field.FirstwebBikelightTest.Value.Clean"); 838 string DocumentLink_Catalog = GetString("Ecom:Product:Field.FirstwebCatalog.Value.Clean"); 839 840 string DocumentLink_ExtraProductDocument1 = GetString("Ecom:Product:Field.FirstwebExtraProductDocument1_File.Value.Clean"); 841 string DocumentLink_ExtraProductDocument2 = GetString("Ecom:Product:Field.FirstwebExtraProductDocument2_File.Value.Clean"); 842 843 bool ShowDownload = (!String.IsNullOrEmpty(DocumentLink_UserManual) || !String.IsNullOrEmpty(DocumentLink_DataSheet) || !String.IsNullOrEmpty(DocumentLink_LockCertificate) || !String.IsNullOrEmpty(DocumentLink_BikelightTest) || !String.IsNullOrEmpty(DocumentLink_Catalog) || !String.IsNullOrEmpty(DocumentLink_ExtraProductDocument1)|| !String.IsNullOrEmpty(DocumentLink_ExtraProductDocument2)); 844 845 int IndicatorCounter = 0; 846 string FindDealerPage = string.Format("/Default.aspx?id={0}", Firstweb.Custom.CustomCode.Tapas.Context.AreaPages.GetPageId("FindDealer")); 847 DateTime BackInStock = GetDate("Firstweb:ErpStockInfo.DeliveryDate"); 848 bool ShowBeforePrice = GetBoolean("Firstweb:EcomProduct:DisplayBeforePrice"); 849 string BeforePriceFormatted = GetString("Firstweb:EcomProduct:BeforePriceFormattedWithSymbol"); 850 string StockStatus = GetString("Firstweb:StockStatusColor"); //hvis rød og confirmed deliverydate - hvis dato 851 string StockLabel = GetString("Firstweb:StockStatusTitle"); 852 string ConfirmedDeliveryDate = GetString("Ecom:Product:Field.NAVConfirmedDeliveryDate.Value"); 853 bool NotInStock = GetBoolean("Firstweb:NotInStock"); 854 bool ShowQuantityPrices = GetBoolean("Firstweb:EcomProduct:ShowQuantityPricelistIcon"); 855 856 var ProductSpecificationsDisplayGroup = GetLoop("FieldDisplayGroups").FirstOrDefault(fdg => fdg.GetString("Ecom:FieldDisplayGroup.SystemName") == "ProductSpecifications"); 857 858 859 int backorderRemaining = 0; 860 bool inBackorders = Firstweb.Custom.CustomCode.Frontend.Helpers.Backordre.InBackorders(productNumber, out backorderRemaining); 861 string addToCartWarningText = inBackorders ? Translate("Cart.RestorderFirstPart", "Du har allerede") + " " + backorderRemaining + " " + Translate("Cart.RestorderSecondPart", "i restorder af denne.") : ""; 862 string addToCartWarningTextConfirmation = inBackorders ? addToCartWarningText + " - " + Translate("Cart.RestorderConfirm", "Vil du forsætte?") : ""; 863 864 bool HasUSP_DA = !String.IsNullOrEmpty(GetString("Ecom:Product:Field.USP1.Value.Clean")); 865 //Fallback til engelsk USP fjernet 866 //bool HasUSP_EN = !String.IsNullOrEmpty(GetString("Ecom:Product:Field.Supplier_USP1_EN.Value.Clean")); 867 bool HasUSP_EN = false; 868 } 869 870 871 <div class="container product-details"> 872 <div id="blueimp-gallery" class="blueimp-gallery blueimp-gallery-controls" data-filter=".gallery-image"> 873 <div class="slides"></div> 874 <a class="prev">‹</a> 875 <a class="next">›</a> 876 <a class="close">×</a> 877 </div> 878 879 <!--breadcrumbs --> 880 <ol class="breadcrumb xs-m-b-1 xs-m-t-3"> 881 <li class="position-relative"> 882 <a href="" title="@Translate("Firstweb.Content.Breadcrumbs.FrontPage", "Forside")">@Translate("Firstweb.Content.Breadcrumbs.FrontPage", "Forside")</a> 883 </li> 884 885 886 887 @foreach (var link in breadCrumbGroupList) 888 { 889 string activeBreadcrumbCss = breadCrumbGroupList.Last() == link ? "active-breadcrumb" : ""; 890 <li class="position-relative @activeBreadcrumbCss"> 891 @if (link == breadCrumbGroupList.FirstOrDefault()) 892 { 893 <span title="@link.Name">@link.Name</span> 894 } 895 else 896 { 897 <a href="/Default.aspx?ID=@GetString("Ecom:Product:Page.ID")&GroupID=@link.Id" title="@link.Name">@link.Name</a> 898 } 899 </li> 900 } 901 902 </ol> 903 <!--breadcrumbs--> 904 905 <main class="xs-p-b-3 xs-m-t-2" data-bind="viewModel: 'ProductPageViewModel'"> 906 <!-- ko initValue: {observable: Quantity, value:'@defaultQuantity'}--><!-- /ko--> 907 908 <div class="row row-ce"> 909 <section class="col-xs-12 col-md-6"> 910 @if (!String.IsNullOrEmpty(GetString("Ecom:Product:Field.FirstwebBrandLogo.Value.FullPath"))) 911 { 912 <img src="@BrandLogo" alt="@BrandName" /> 913 } 914 915 @if (!String.IsNullOrEmpty(CatalogueRemark)) 916 { 917 <div class="catalogue-remark">@CatalogueRemark</div> 918 } 919 <!-- Product images --> 920 <div id="product-carousel" class="carousel product-carousel slide" data-ride="carousel"> 921 922 <!-- Wrapper for slides --> 923 <div class="carousel-inner" role="listbox"> 924 @if (productImages.Any()) 925 { 926 foreach (var pi in productImages) 927 { 928 string ActiveCss = pi == productImages.First() ? "active" : ""; 929 string ImageUrl = "/admin/public/getimage.ashx?image=" + pi.Value + "&altFmImage_path=/Files/Images/ecom/Products/no-image.jpg&width=1200&height=800&Compression=99&Crop=5"; 930 string LargeImage = "/admin/public/getimage.ashx?image=" + pi.Value + "&altFmImage_path=/Files/Images/ecom/Products/no-image.jpg&width=3800&height=2000&Compression=99Crop=5"; 931 <div class="item @ActiveCss"> 932 <a class="gallery-image" href="@LargeImage" data-gallery> 933 <img class="img-responsive" src="@ImageUrl" alt="@productName" style="max-height:400px;max-width:600px;"> 934 </a> 935 </div> 936 } 937 } 938 else 939 { 940 <div class="item active"> 941 <img class="img-responsive" src="@primaryProductImageUrl" alt="@productName" style="height:400px;"> 942 </div> 943 } 944 </div> 945 946 <div class="product-indicators carousel-indicators"> 947 @foreach (var pi in productImages) 948 { 949 string FirstClass = IndicatorCounter == 0 ? "active" : ""; 950 string ImageUrl = "/admin/public/getimage.ashx?image=" + pi.Value + "&altFmImage_path=/Files/Images/ecom/Products/no-image.jpg&width=125&height=80&Compression=90&Crop=5"; 951 <div class="indicator @FirstClass" data-target="#product-carousel" data-slide-to="@IndicatorCounter"> 952 <img class="img-responsive" src="@ImageUrl" alt="@productName"> 953 </div> 954 IndicatorCounter++; 955 } 956 957 958 @if (!String.IsNullOrEmpty(YtVideoId)) 959 { 960 <div class="product-video"> 961 962 <img style="display:none;" src="@YtVideoPreviewImage" data-toggle="modal" data-target="#ytModal" data-bind="productYoutubeVideo: { videoId: '@YtVideoId', modalId: '#ytModal', playerId: 'productYtVideo' }" /> 963 964 <div class="yt-bg"></div> 965 966 <i class="far fa-play-circle" data-toggle="modal" data-target="#ytModal"></i> 967 968 <div class="modal fade" id="ytModal" tabindex="-1" role="dialog"> 969 <div class="modal-dialog modal-lg" role="document"> 970 <div class="modal-content"> 971 <div class="youtube-video-container"> 972 <div class="video" id="productYtVideo"></div> 973 </div> 974 </div> 975 </div> 976 </div> 977 978 </div> 979 } 980 981 982 </div> 983 984 </div> 985 986 </section> 987 988 <div class="col-xs-12 col-md-6"> 989 <h1 class="font-strong xs-m-t-0 xs-m-b-2">@productName</h1> 990 991 <section> 992 993 <div class="product-keyinfo"> 994 995 <div class="keyinfo"> 996 <p>@Translate("Product.NumberShort", "Varenr.")</p> 997 <p>@productNumber</p> 998 </div> 999 1000 <div class="keyinfo"> 1001 <p>@Translate("Product.EAN", "EAN")</p> 1002 <p>@EAN</p> 1003 </div> 1004 1005 <div class="keyinfo"> 1006 <p>@Translate("Product.SalesQuantity", "Salgskvanti")</p> 1007 <p>@defaultQuantity</p> 1008 </div> 1009 1010 <div class="keyinfo"> 1011 <p>@Translate("Product.Colli", "Antal i kolli")</p> 1012 <p>@Collisize</p> 1013 </div> 1014 @if (@Firstweb.Custom.CustomCode.Frontend.Helpers.Users.IsEmployee()) 1015 { 1016 <div class="keyinfo"> 1017 <a class="btn btn-primary" style="padding: 6px 8px;" data-toggle="modal" data-target="#extraEmployeeProductInfo" data-load-url="/Default.aspx?Id=@Firstweb.Custom.CustomCode.Tapas.Context.AreaPages.GetPageId("extrapageinfo")&ProductId=@productID"><i class="fas fa-info-circle" style="font-size:20px;"></i></a> 1018 </div> 1019 1020 <div class="modal fade" id="extraEmployeeProductInfo" tabindex="-1" role="dialog" data-load-url="/Default.aspx?Id=&ProductId="> 1021 <div class="modal-dialog modal-lg" role="document"> 1022 <div class="modal-content"> 1023 <div class="modal-header"> 1024 <h1 class="modal-title" style=" display: inline-block;">Ekstra produkt info</h1> 1025 <button type="button" class="close" data-dismiss="modal" aria-label="Close" style="font-size:36px"> 1026 <span aria-hidden="true">×</span> 1027 </button> 1028 </div> 1029 <div class="modal-body" style="padding:20px;"></div> 1030 1031 </div> 1032 </div> 1033 </div> 1034 1035 1036 } 1037 </div> 1038 1039 </section> 1040 1041 1042 1043 1044 1045 <div class="row row-ce product-description xs-m-b-2"> 1046 1047 <div class="col-xs-12 col-md-6" style="align-self: flex-end;"> 1048 @if (!isBlocked) 1049 { 1050 if (ShowShopFunctions) 1051 { 1052 <div class="productlist-price-area "> 1053 <div class="width-50"> 1054 @if (IsPurchaceProduct) 1055 { 1056 <p class="purchace-product text-left"> 1057 <i class="far fa-truck"></i> @Translate("Product.PurchaceProduct", "Skaffevare") 1058 </p> 1059 } 1060 else 1061 { 1062 <p class="stock-indicator"> 1063 <span class="stock-load-async" style="background-color: @StockStatus"></span> 1064 <span class="stock-name">@StockLabel</span> 1065 <span class="stock-name js-in-stock-again hide">@Translate("Product.StockExpectedAgaing", "På lager: ")<span class="js-stock-date"></span></span> 1066 </p> 1067 if (NotInStock && !String.IsNullOrEmpty(ConfirmedDeliveryDate)) 1068 { 1069 <p class="stock-cdd">@Translate("Product.ConfirmedDeliveryDate", "På lager"): @ConfirmedDeliveryDate</p> 1070 } 1071 1072 if (StockStatus == "#009600") 1073 { 1074 <p class="stock-cdd">@Translate("Product.OnStockDeliveryText", "Levering: 1-2 dage")</p> 1075 } 1076 } 1077 1078 </div> 1079 <div class="width-50"> 1080 1081 @if (!HidePrices) 1082 { 1083 1084 <p><span class="price-display-normalprice">@bruttoPrice</span></p> 1085 <p><span class="price-display-yourprice">@GetString("Ecom:Product.Price.PriceWithoutVATFormatted")</span></p> 1086 if (ShowBeforePrice && 1 == 0) 1087 { 1088 <p><span class="price-display-medium-label">@Translate("Product.Beforeprice", "Førpris")</span> <span class="price-display-medium">@BeforePriceFormatted</span></p> 1089 } 1090 } 1091 </div> 1092 </div> 1093 1094 } 1095 } 1096 else 1097 { 1098 @RenderReplacementProducts(replacementProducts, productCatalog_PageId) 1099 } 1100 1101 </div> 1102 1103 <div class="col-xs-12 col-md-6 xs-m-t-2"> 1104 1105 1106 @if (ShowShopFunctions && !isBlocked) 1107 { 1108 <div class="add-to-cart xs-m-t-1"> 1109 <input class="product-quantity" type="number" name="quantity" min="1" data-bind="textInput: Quantity, event: { keypress: function() { if (window.event.keyCode == 13) { addItemToCart('@productID', $(window.event.target).val(), '', '', '@Translate("Product.AddingToCart", "Tilføjer produkt")'); animateCart(event); } return true;}}" /> 1110 <div title="@addToCartWarningText" class="btn btn-primary js-product-buy-btn" data-addedtocarttext="@Translate("Product.AddedToCart", "Varen er tilføjet")" 1111 data-bind="click: function() { if ('@inBackorders' == 'False' || confirm('@addToCartWarningTextConfirmation')) { addItemToCart('@productID', Quantity(), '', '', '@Translate("Product.AddingToCart", "Tilføjer produkt")'); animateCart(event); } }" 1112 data-productid="@productID"> 1113 @Translate("Product.AddToCart", "TILFØJ TIL KURV") 1114 1115 @if (inBackorders) 1116 { 1117 <i style=""float:right; class="fas fa-exclamation-triangle"></i> 1118 } 1119 1120 </div> 1121 1122 1123 <div class="favorite-list-icon" data-toggle="modal" data-target="#modal-@productID" data-bind="with: OrderTemplateViewModel"> 1124 <div class="favorite-list-icon-btn" data-bind=" 1125 oninit: function() { IsInFavoriteList('@inFavouriteBoolJS'.toLowerCase()) }, 1126 css : { showFavorite : ShowOrderTemplateDialog, showNewList : OrderTemplateShowNewList, added: IsInFavoriteList() == 'true', notadded: IsInFavoriteList() == 'false' }, 1127 visible: $root.User().IsLoggedIn(), 1128 click: ToggleOrderTemplateDialog"> 1129 <i class="fas fa-star"></i> 1130 </div> 1131 </div> 1132 1133 1134 </div> 1135 1136 if (ShowQuantityPrices && !HidePrices) 1137 { 1138 <div> 1139 @RenderQuantityPrices(productNumber, productCurrency, productID) 1140 </div> 1141 } 1142 1143 <div class="modal fade" id="modal-@productID" tabindex="-1" role="dialog" data-bind="with: OrderTemplateViewModel"> 1144 <!-- ko initValue: {observable: OrderTemplateRelationCount, value:'@productInFavoritLists'}--><!-- /ko--> 1145 <!-- ko initValue: {observable: ShowInFavourite, value: @inFavouriteBoolJS}--><!-- /ko--> 1146 <!-- ko initValue: {observable: ModalSelector, value: '#modal-@productID'}--><!-- /ko--> 1147 <div class="modal-dialog" role="document"> 1148 <div class="modal-content fav-list"> 1149 1150 <p class="favlist-header">@Translate("Ordertemplate.AddToExistingList", "Tilføj til eksisterende favoritliste")</p> 1151 1152 <div class="existing-lists"> 1153 1154 <select class="favField select-fix" 1155 data-bind="options: OrderTemplateList, 1156 optionsCaption: '@Translate("Ordertemplate.SelectList", "Vælg en liste")...', 1157 optionsText: function(item) { return item.Value.Name() + ' (' + item.Value.Count() + ')' }, 1158 value: OrderTemplateSelectedList"></select> 1159 1160 <input class="product-quantity" type="number" name="quantity" data-bind="textInput: OrderTemplateQuantity" /> 1161 1162 <div class="btn btn-primary" 1163 data-bind="click: function() { 1164 OrderTemplateShowNewList() 1165 ? CreateNewOrderTemplateList('@productID') 1166 : AddProductToOrderTemplate('@productID' , OrderTemplateQuantity()) 1167 }"> 1168 @Translate("Ordertemplate.AddToList", "Tilføj") 1169 </div> 1170 1171 </div> 1172 1173 <p class="or-text">@Translate("Ordertemplate.OrNewList", "eller...")</p> 1174 1175 <p class="favlist-header">@Translate("Ordertemplate.AddToNewList", "Tilføj til ny favoritliste")</p> 1176 1177 <form id="EditForm-@productID" 1178 name="EditForm"> 1179 <label class="xs-m-b-1" for="name">@Translate("Ordertemplate.ListName", "Favoritliste navn")</label> 1180 <div class="new-list"> 1181 <input type="text" 1182 name="name" 1183 _id="name" 1184 data-bind="textInput: OrderTemplateNewListName" 1185 autofocus 1186 autocomplete="off" /> 1187 1188 <input class="product-quantity" type="number" name="quantity" data-bind="textInput: OrderTemplateNewListQuantity" /> 1189 1190 <button type="submit" 1191 class="btn btn-primary" 1192 _id="btnSave" 1193 data-bind="click: function() { CreateNewOrderTemplateList('@productID', OrderTemplateNewListQuantity()) }"> 1194 @Translate("Ordertemplate.SaveToNewList", "Tilføj til ny favoritliste") 1195 </button> 1196 </div> 1197 </form> 1198 1199 </div> 1200 </div> 1201 </div> 1202 } 1203 else if (!ShowShopFunctions) 1204 { 1205 <div class="xs-m-t-2 text-right"> 1206 @* 1207 <a href="@FindDealerPage" class="btn btn-primary">@Translate("Product.FindDealerLink", "Find forhandler")</a> 1208 *@ 1209 </div> 1210 } 1211 1212 1213 1214 1215 </div> 1216 1217 </div> 1218 1219 <div class="row row-ce"> 1220 @if (!String.IsNullOrEmpty(productDescription) || HasUSP_DA || HasUSP_EN) 1221 { 1222 <div class="col-xs-12 xs-m-b-2"> 1223 <div class="description-box" data-bind="readMore: { readMoreToggler: '.js-read-more' }"> 1224 <div class="rte-content"> 1225 @productDescription 1226 @if(HasUSP_DA) 1227 { 1228 <ul> 1229 @for (int i = 1; i <= 5; i++) 1230 { 1231 string usp = GetString($"Ecom:Product:Field.USP{i}.Value.Clean"); 1232 if (!String.IsNullOrEmpty(usp)) 1233 { 1234 <li>@usp</li> 1235 } 1236 } 1237 1238 1239 </ul> 1240 } 1241 else if(HasUSP_EN) 1242 { 1243 <ul> 1244 @for (int i = 1; i <= 5; i++) 1245 { 1246 string usp = GetString($"Ecom:Product:Field.Supplier_USP{i}_EN.Value.Clean"); 1247 if (!String.IsNullOrEmpty(usp)) 1248 { 1249 <li>@usp</li> 1250 } 1251 } 1252 1253 </ul> 1254 } 1255 1256 1257 </div> 1258 <div class="read-more js-read-more"><span class="js-read-more-text" data-readmore="Læs mere" data-readless="Læs mindre">Læs mere</span><span class="xs-m-l-1"><i class="fal fa-chevron-down"></i></span></div> 1259 </div> 1260 </div> 1261 } 1262 1263 @*<div class="col-xs-12"> 1264 @RenderSnippet("RelatedProductLink") 1265 </div>*@ 1266 1267 1268 1269 1270 1271 <div class="col-xs-6 spec-left"> 1272 @if (ShowDownload) 1273 { 1274 <div class="specificaitons-header" 1275 data-bind="productSpecifications: { toggleClass: 'open', elementToSlideToggle: '.js-documents' }"> 1276 <span>@Translate("Product.ProductDownloads", "Download")</span> 1277 <span class="xs-m-l-1"><i class="fal fa-chevron-down"></i></span> 1278 </div> 1279 } 1280 </div> 1281 1282 1283 1284 1285 <div class="col-xs-6 @(ShowDownload ? "spec-right" : "")"> 1286 <div class="specificaitons-header" 1287 data-bind="productSpecifications: { toggleClass: 'open', elementToSlideToggle: '.js-specifications' }"> 1288 <span>@Translate("Product.ProductSpecifications", "Produktspecifikationer")</span> 1289 <span class="xs-m-l-1"><i class="fal fa-chevron-down"></i></span> 1290 </div> 1291 1292 </div> 1293 1294 1295 1296 <div class="col-xs-12"> 1297 <div class="value-matrix js-specifications"> 1298 <div class="xs-m-b-1"> 1299 <div class="row"> 1300 <div class="col-xs-12"> 1301 <ul class="list-unstyled xs-m-t-0 xs-m-b-0"> 1302 1303 @if (ProductSpecificationsDisplayGroup != null) 1304 { 1305 foreach (var fv in ProductSpecificationsDisplayGroup.GetLoop("Fields")) 1306 { 1307 string FieldValue = fv.GetString("Ecom:FieldDisplayGroup.Field.Value"); 1308 1309 if (!String.IsNullOrEmpty(FieldValue) && FieldValue != "False") 1310 { 1311 1312 string FieldId = fv.GetString("Ecom:FieldDisplayGroup.Field.Id"); 1313 string FieldName = fv.GetString("Ecom:FieldDisplayGroup.Field.Name"); 1314 string FieldNameTranslated = Translate("ProductFields:" + FieldId, FieldName); 1315 string FieldValueTranslated = FieldValue; 1316 if (FieldValue == "True") 1317 { 1318 FieldValueTranslated = "Ja"; 1319 } 1320 1321 <li class="bg-light-grey is-flex is-space-between padding-bottom-8px padding-top-8px xs-p-l-1 xs-p-r-1"> 1322 <div>@FieldNameTranslated</div> 1323 <div>@FieldValueTranslated</div> 1324 </li> 1325 } 1326 } 1327 } 1328 1329 1330 1331 @foreach (var productCategory in GetLoop("ProductCategories")) 1332 { 1333 foreach (var productCategoryField in productCategory.GetLoop("ProductCategoryFields")) 1334 { 1335 string categoryField = productCategoryField.GetString("Ecom:Product.CategoryField.Value.Clean"); 1336 1337 if (!String.IsNullOrEmpty(categoryField)) 1338 { 1339 string categoryLabel = productCategoryField.GetString("Ecom:Product.CategoryField.Label"); 1340 if (categoryLabel.StartsWith("#")) 1341 { 1342 categoryLabel = categoryLabel.TrimStart(new char[] { '#' }); 1343 categoryField = Translate($"SpecValue:{categoryField}", categoryField); 1344 } 1345 1346 <li class="bg-light-grey is-flex is-space-between padding-bottom-8px padding-top-8px xs-p-l-1 xs-p-r-1" data-test="@productCategoryField.GetString("Ecom:Product.CategoryField.TemplateTag")"> 1347 <div>@categoryLabel</div> 1348 <div>@categoryField</div> 1349 </li> 1350 } 1351 1352 } 1353 } 1354 1355 </ul> 1356 </div> 1357 </div> 1358 </div> 1359 </div> 1360 1361 1362 @if (ShowDownload) 1363 { 1364 <div class="value-matrix js-documents"> 1365 <div class="xs-m-b-1"> 1366 <div class="row"> 1367 <div class="col-xs-12"> 1368 <ul class="list-unstyled xs-m-t-0 xs-m-b-0"> 1369 1370 1371 1372 @if (!String.IsNullOrEmpty(DocumentLink_UserManual)) 1373 { 1374 string documentName = Translate("Product.Documents.UserManual", "Brugervejledning"); 1375 string filename = System.IO.Path.GetFileName(DocumentLink_UserManual); 1376 <li class="bg-light-grey xs-p-l-1 xs-p-r-1"> 1377 <a href="@DocumentLink_UserManual" download=""> 1378 <div class="row"> 1379 <div class="col-xs-3">@documentName</div> 1380 <div class="col-xs-8">@filename</div> 1381 <div class="col-xs-1 download"><i class="fal fa-chevron-down"></i></div> 1382 </div> 1383 </a> 1384 </li> 1385 } 1386 1387 @if (!String.IsNullOrEmpty(DocumentLink_DataSheet)) 1388 { 1389 string documentName = Translate("Product.Documents.DataSheet", "Datablad"); 1390 string filename = System.IO.Path.GetFileName(DocumentLink_DataSheet); 1391 <li class="bg-light-grey xs-p-l-1 xs-p-r-1"> 1392 <a href="@DocumentLink_DataSheet" download=""> 1393 <div class="row"> 1394 <div class="col-xs-3">@documentName</div> 1395 <div class="col-xs-8">@filename</div> 1396 <div class="col-xs-1 download"><i class="fal fa-chevron-down"></i></div> 1397 </div> 1398 </a> 1399 </li> 1400 } 1401 1402 @if (!String.IsNullOrEmpty(DocumentLink_LockCertificate)) 1403 { 1404 string documentName = Translate("Product.Documents.LockCertificate", "Låsebevis"); 1405 string filename = System.IO.Path.GetFileName(DocumentLink_LockCertificate); 1406 <li class="bg-light-grey xs-p-l-1 xs-p-r-1"> 1407 <a href="@DocumentLink_LockCertificate" download=""> 1408 <div class="row"> 1409 <div class="col-xs-3">@documentName</div> 1410 <div class="col-xs-8">@filename</div> 1411 <div class="col-xs-1 download"><i class="fal fa-chevron-down"></i></div> 1412 </div> 1413 </a> 1414 </li> 1415 } 1416 1417 @if (!String.IsNullOrEmpty(DocumentLink_BikelightTest)) 1418 { 1419 string documentName = Translate("Product.Documents.BikelightTest", "Lygtetest"); 1420 string filename = System.IO.Path.GetFileName(DocumentLink_BikelightTest); 1421 <li class="bg-light-grey xs-p-l-1 xs-p-r-1"> 1422 <a href="@DocumentLink_BikelightTest" download=""> 1423 <div class="row"> 1424 <div class="col-xs-3">@documentName</div> 1425 <div class="col-xs-8">@filename</div> 1426 <div class="col-xs-1 download"><i class="fal fa-chevron-down"></i></div> 1427 </div> 1428 </a> 1429 </li> 1430 } 1431 1432 @if (!String.IsNullOrEmpty(DocumentLink_Catalog)) 1433 { 1434 string documentName = Translate("Product.Documents.Catalog", "Katalog"); 1435 string filename = System.IO.Path.GetFileName(DocumentLink_Catalog); 1436 <li class="bg-light-grey xs-p-l-1 xs-p-r-1"> 1437 <a href="@DocumentLink_Catalog" download=""> 1438 <div class="row"> 1439 <div class="col-xs-3">@documentName</div> 1440 <div class="col-xs-8">@filename</div> 1441 <div class="col-xs-1 download"><i class="fal fa-chevron-down"></i></div> 1442 </div> 1443 </a> 1444 </li> 1445 } 1446 1447 @if (!String.IsNullOrEmpty(DocumentLink_ExtraProductDocument1)) 1448 { 1449 string documentName = GetString("Ecom:Product:Field.FirstwebExtraProductDocument1_Description.Value.Clean"); 1450 documentName = String.IsNullOrEmpty(documentName) ? "Dokument" : documentName; 1451 string filename = System.IO.Path.GetFileName(DocumentLink_ExtraProductDocument1); 1452 <li class="bg-light-grey xs-p-l-1 xs-p-r-1"> 1453 <a href="@DocumentLink_ExtraProductDocument1" download=""> 1454 <div class="row"> 1455 <div class="col-xs-3">@documentName</div> 1456 <div class="col-xs-8">@filename</div> 1457 <div class="col-xs-1 download"><i class="fal fa-chevron-down"></i></div> 1458 </div> 1459 </a> 1460 </li> 1461 } 1462 1463 @if (!String.IsNullOrEmpty(DocumentLink_ExtraProductDocument2)) 1464 { 1465 string documentName = GetString("Ecom:Product:Field.FirstwebExtraProductDocument2_Description.Value.Clean"); 1466 documentName = String.IsNullOrEmpty(documentName) ? "Dokument" : documentName; 1467 string filename = System.IO.Path.GetFileName(DocumentLink_ExtraProductDocument2); 1468 <li class="bg-light-grey xs-p-l-1 xs-p-r-1"> 1469 <a href="@DocumentLink_ExtraProductDocument2" download=""> 1470 <div class="row"> 1471 <div class="col-xs-3">@documentName</div> 1472 <div class="col-xs-8">@filename</div> 1473 <div class="col-xs-1 download"><i class="fal fa-chevron-down"></i></div> 1474 </div> 1475 </a> 1476 </li> 1477 } 1478 1479 1480 </ul> 1481 </div> 1482 </div> 1483 </div> 1484 </div> 1485 } 1486 </div> 1487 <div class="col-xs-12 col-md-6 xs-m-t-3 md-m-t-0"> 1488 1489 1490 1491 </div> 1492 </div> 1493 </div> 1494 </div> 1495 </main> 1496 1497 </div> 1498 1499 @if (showRelatedProducts) 1500 { 1501 bool relatedProductsFound = false; 1502 <div class="js-show-related"> 1503 @foreach (var Group in productRelatedGroups) 1504 { 1505 string GroupName = Group.GetString("Ecom:Product:RelatedGroup.Name"); 1506 string GroupID = Group.GetString("Ecom:Product:RelatedGroup.GroupID"); 1507 1508 1509 var RelatedProductsLoop = Group.GetLoop("RelatedProducts"); 1510 1511 if (RelatedProductsLoop.Any()) 1512 { 1513 relatedProductsFound = true; 1514 <div class="millarco-productlist related-products xs-p-t-3" data-bind="viewModel: 'ProductListViewModel'"> 1515 <div class="container" data-bind="asyncPriceLoad: productListLoad"> 1516 <p class="related-group-header">@GroupName</p> 1517 <div class="row row-ce"> 1518 @foreach (var Product in RelatedProductsLoop) 1519 { 1520 @renderProduct(false, Product, true) 1521 } 1522 </div> 1523 </div> 1524 </div> 1525 } 1526 1527 } 1528 </div> 1529 1530 if (relatedProductsFound) 1531 { 1532 @SnippetStart("RelatedProductLink") 1533 1534 <div class="specificaitons-header" data-bind="scrollToElement: { target: 'js-show-related' }"> 1535 <span>@Translate("Product.ProductRelatedProducts", "Relaterede produkter")</span> 1536 <span class="xs-m-l-1"><i class="fal fa-chevron-down"></i></span> 1537 </div> 1538 1539 @SnippetEnd("RelatedProductLink") 1540 } 1541 1542 1543 } 1544