Sorter etter

Error executing template "Designs/Swift/Paragraph/Swift_ProductListGridView_Custom.cshtml"
System.ArgumentException: An item with the same key has already been added.
   at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
   at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
   at Dynamicweb.Ecommerce.FieldTypeProviders.ConversionUnitFieldTypeProviderBase.GetLanguageUnits(Dictionary`2 settings)
   at Dynamicweb.Ecommerce.FieldTypeProviders.ConversionUnitFieldTypeProviderBase.GetValue(Object value, String languageId, Dictionary`2 settings)
   at Dynamicweb.Ecommerce.Products.ProductFieldTypeProvider.GetProductValue(Product product, FieldType fieldType, Object fieldValue)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldValueService.GetCategoryValue(Product product, String defaultLanguageId, IEnumerable`1 orderedGroups, Field catField, Boolean includeInheritance)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldValueService.GetCategoryValue(Product product, String categoryId, String fieldId, Boolean includeInheritance)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldValueService.GetProductCategoryFieldValue(Product product, String categoryId, Field field)
   at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.CreateView(ProductViewModelSettings settings, Product product, Field field)
   at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.GetFieldDisplayGroupValues(ProductViewModelSettings settings, Product product, String languageID, Lazy`1 productIds)
   at Dynamicweb.Ecommerce.ProductCatalog.ViewEngine.<>c__DisplayClass3_1.<BulkCreateView>b__54()
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at CompiledRazorTemplates.Dynamic.RazorEngine_295d8218648b4f2585c7ef4b0a26036a.<RenderProductList>b__5_0(TextWriter __razor_helper_writer)
   at CompiledRazorTemplates.Dynamic.RazorEngine_295d8218648b4f2585c7ef4b0a26036a.Execute()
   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 Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 2 @using Dynamicweb.Ecommerce.ProductCatalog 3 @using Dynamicweb.Ecommerce.CustomerExperienceCenter.Favorites 4 @using System.Web; 5 @using Dynamicweb.Core; 6 @using Dynamicweb.Environment 7 @using Mennt.Tysse.Custom.Helpers 8 9 @functions { 10 Dictionary<string, object> favoriteParameters { get; set; } 11 12 public static string TruncateWithEllipsis(string s, int length) 13 { 14 //there may be a more appropiate unicode character for this 15 const string Ellipsis = ".."; 16 17 if (Ellipsis.Length > length) 18 throw new ArgumentOutOfRangeException("length", length, "length must be at least as long as ellipsis."); 19 20 if (s.Length > length) 21 return s.Substring(0, length - Ellipsis.Length) + Ellipsis; 22 else 23 return s; 24 } 25 } 26 27 @{ 28 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 29 string themePadding = theme != string.Empty ? "p-0" : string.Empty; 30 31 } 32 33 @if (!string.IsNullOrEmpty(theme)) 34 { 35 <div class="h-100@(theme) @themePadding"> 36 @RenderProductList() 37 </div> 38 } 39 else 40 { 41 <div class="pt-3"> 42 @RenderProductList() 43 </div> 44 } 45 46 @helper RenderProductList () { 47 ProductListViewModel productList = new ProductListViewModel(); 48 49 if (Dynamicweb.Context.Current.Items.Contains("ProductList")) 50 { 51 productList = (ProductListViewModel)Dynamicweb.Context.Current.Items["ProductList"]; 52 } 53 54 string anonymousUsersLimitations = Pageview.AreaSettings.GetRawValueString("AnonymousUsers", ""); 55 bool anonymousUser = Pageview.User == null; 56 bool hidePrice = anonymousUsersLimitations.Contains("price") && anonymousUser; 57 58 string detailsPageLink = Dynamicweb.Context.Current.Items["DetailsPageLink"] != null ? Dynamicweb.Context.Current.Items["DetailsPageLink"].ToString() : ""; 59 string productTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("ProductTheme")) ? " theme " + Model.Item.GetRawValueString("ProductTheme").Replace(" ", "").Trim().ToLower() : ""; 60 string productThemePadding = productTheme != string.Empty ? "px-3 px-0" : string.Empty; 61 62 string url = Dynamicweb.Context.Current.Request.RawUrl; 63 bool hideFavoritesSelector = !string.IsNullOrEmpty(Model.Item.GetString("HideFavoritesSelector")) ? Model.Item.GetBoolean("HideFavoritesSelector") : false; 64 string staticVariantsLayout = Model.Item.GetRawValueString("StaticVariantsLayout", "hide"); 65 66 string groupId = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("GroupID")) ? Dynamicweb.Context.Current.Request.QueryString.Get("GroupID") : ""; 67 68 var badgeParms = new Dictionary<string, object>(); 69 badgeParms.Add("saleBadgeType", Model.Item.GetRawValue("SaleBadgeType")); 70 badgeParms.Add("saleBadgeCssClassName", Model.Item.GetRawValue("SaleBadgeDesign")); 71 badgeParms.Add("newBadgeCssClassName", Model.Item.GetRawValue("NewBadgeDesign")); 72 badgeParms.Add("newPublicationDays", Model.Item.GetInt32("NewPublicationDays")); 73 badgeParms.Add("campaignBadgesValues", Model.Item.GetRawValueString("CampaignBadges")); 74 75 bool saleBadgeEnabled = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("SaleBadgeDesign")) && Model.Item.GetRawValueString("SaleBadgeDesign") != "none" ? true : false; 76 bool newBadgeEnabled = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("NewBadgeDesign")) && Model.Item.GetRawValueString("NewBadgeDesign") != "none" ? true : false; 77 78 string googleAnalyticsTrackingID = Pageview.AreaSettings.GetString("GoogleAnalyticsTrackingID"); 79 string googleAnalyticsMeasurementID = Pageview.AreaSettings.GetString("GoogleAnalyticsMeasurementID"); 80 var cookieOptInLevel = CookieManager.GetCookieOptInLevel(); 81 bool allowTracking = cookieOptInLevel == CookieOptInLevel.All || (cookieOptInLevel == CookieOptInLevel.Functional && CookieManager.GetCookieOptInCategories().Contains("Statistical")); 82 Mennt.Tysse.Custom.Models.Dealer selectedDealer = DealerHelper.SelectedDealer(); 83 84 85 86 87 var favoriteParameters = new Dictionary<string, object>(); 88 if (!anonymousUser && !hideFavoritesSelector) 89 { 90 int defaultFavoriteListId = 0; 91 92 IEnumerable<FavoriteList> favoreiteLists = Pageview.User.GetFavoriteLists(); 93 if (favoreiteLists.Count() == 1) { 94 foreach (FavoriteList list in favoreiteLists) { 95 defaultFavoriteListId = list.ListId; 96 } 97 } 98 99 favoriteParameters.Add("ListId", defaultFavoriteListId); 100 } 101 102 if (productList.TotalProductsCount > 0) { 103 int pageSizeSetting = 30; 104 int pageSize = productList.PageSize; 105 pageSize += pageSizeSetting; 106 107 int loadedProducts = productList.PageSize > productList.TotalProductsCount ? productList.TotalProductsCount : productList.PageSize; 108 109 var i = 0; 110 111 <div class="grid grid-1 grid-md-2 grid-xxl-3"> 112 113 @if (!string.IsNullOrWhiteSpace(googleAnalyticsMeasurementID) && allowTracking) 114 { 115 <script> 116 gtag("event", "view_item_list", { 117 item_list_id: "product_list_gridview", 118 item_list_name: "Product list (Gridview)", 119 items: [ 120 @foreach (ProductViewModel product in productList.Products) 121 { 122 <text>{ 123 item_id: "@product.Number", 124 item_name: "@product.Name", 125 currency: "@product.Price.CurrencyCode", 126 price: @product.Price.Price 127 },</text> 128 } 129 ] 130 }); 131 </script> 132 } 133 134 @foreach (ProductViewModel product in productList.Products) 135 { 136 var defaultGroupId = product.PrimaryOrDefaultGroup.Id; 137 var selectedDetailPage = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(defaultGroupId).Meta.PrimaryPage; 138 var productName = TruncateWithEllipsis($"{product.Name} {product.VariantName}", 36); 139 140 string link = string.IsNullOrEmpty(selectedDetailPage) ? $"{detailsPageLink}&groupid={defaultGroupId}" : selectedDetailPage; 141 link += "&productid=" + product.Id; 142 link += !string.IsNullOrEmpty(product.VariantId) ? "&variantid=" + product.VariantId : ""; 143 144 string imagePath = product?.DefaultImage?.Value ?? ""; 145 //imagePath = Dynamicweb.Context.Current.Server.UrlEncode(imagePath); 146 147 string ratio = Model.Item.GetRawValueString("ImageAspectRatio", ""); 148 ratio = ratio != "0" ? ratio : ""; 149 string ratioCssClass = ratio != "" ? " ratio" : ""; 150 string ratioVariable = ratio != "" ? "--bs-aspect-ratio: " + ratio : ""; 151 152 string imagePathXs = "/Admin/Public/GetImage.ashx?width=" + 480 + "&image=" + imagePath + "&format=webp"; 153 string imagePathS = "/Admin/Public/GetImage.ashx?width=" + 640 + "&image=" + imagePath + "&format=webp"; 154 string imagePathFallBack = "/Admin/Public/GetImage.ashx?width=" + 640 + "&image=" + imagePath + "&format=webp"; 155 156 string imageTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("ImageTheme")) ? " theme " + Model.Item.GetRawValueString("ImageTheme").Replace(" ", "").Trim().ToLower() : ""; 157 string imageThemePadding = imageTheme != string.Empty ? "p-3" : string.Empty; 158 string imageOutlineStyle = imageTheme == string.Empty ? "style=\"border: 1px solid transparent\"" : string.Empty; 159 160 string imageId = "ProductImage_" + product.Id + product.VariantId; 161 string priceId = "ProductPrice_" + product.Id + product.VariantId; 162 163 string iconPath = "/Files/Icons/"; 164 165 string showPricesWithVat = Pageview.Area.EcomPricesWithVat.ToLower(); 166 bool neverShowVat = string.IsNullOrEmpty(showPricesWithVat); 167 168 @* Alternative image *@ 169 var supportedImageFormats = new string[] { ".jpg", ".webp", ".png", ".gif" }; 170 string defaultImage = product.DefaultImage != null ? product.DefaultImage.Value : ""; 171 var selectedAssetCategories = Model.Item.GetRawValueString("AlternativeImageAssets"); 172 IEnumerable<MediaViewModel> alternativeImagesList = product.AssetCategories.Where(x => selectedAssetCategories.Contains(x.SystemName)).SelectMany(x => x.Assets); 173 174 if (alternativeImagesList.FirstOrDefault() != null) { 175 alternativeImagesList = alternativeImagesList.OrderByDescending(x => x.Value.Equals(defaultImage)); 176 177 if (alternativeImagesList.First().Value == defaultImage) { 178 alternativeImagesList = alternativeImagesList.Skip(1); 179 } 180 } 181 182 string alternativeImage = alternativeImagesList.FirstOrDefault() != null ? alternativeImagesList.FirstOrDefault().Value : ""; 183 alternativeImage = !string.IsNullOrEmpty(alternativeImage) ? "/Admin/Public/GetImage.ashx?width=" + 640 + "&image=" + alternativeImage + "&format=webp" : ""; 184 185 @* Badges *@ 186 DateTime createdDate = product.Created.Value; 187 bool showBadges = saleBadgeEnabled && product.Discount.Price != 0 ? true : false; 188 showBadges = (newBadgeEnabled && Model.Item.GetInt32("NewPublicationDays") == 0) || (newBadgeEnabled && (createdDate.AddDays(Model.Item.GetInt32("NewPublicationDays")) > DateTime.Now)) ? true : showBadges; 189 showBadges = !string.IsNullOrEmpty(Model.Item.GetRawValueString("CampaignBadges")) ? true : showBadges; 190 191 @* Main features *@ 192 IEnumerable<string> selectedDisplayGroups = Model.Item.GetRawValueString("MainFeatures").Split(',').ToList(); 193 List<CategoryFieldViewModel> mainFeatures = new List<CategoryFieldViewModel>(); 194 195 foreach (var selection in selectedDisplayGroups) 196 { 197 foreach (CategoryFieldViewModel group in product.FieldDisplayGroups.Values) 198 { 199 if (selection == group.Id) { 200 mainFeatures.Add(group); 201 } 202 } 203 } 204 205 var hideBuyInformation = product.ProductFields.Values.FirstOrDefault(x => x.SystemName == "hideBuyOption"); 206 var hideBuyInformationValue = hideBuyInformation.Value.ToString(); 207 208 var clickShop = product.ProductFields.Values.FirstOrDefault(x => x.SystemName == "ClickShop"); 209 var clickShopValue = clickShop.Value.ToString(); 210 211 var alternativProduct = product.ProductFields.Values.FirstOrDefault(x => x.SystemName == "UseAlternativeProduct"); 212 var alternativProductValue = alternativProduct.Value.ToString(); 213 var alternativProductNumber = product.ProductFields.Values.FirstOrDefault(x => x.SystemName == "AlternativeProduct"); 214 var alternativProductNumberValue = alternativProductNumber.Value.ToString(); 215 var currentUrl = Dynamicweb.Frontend.PageView.Current().SearchFriendlyUrl; 216 217 @* Custom fields 218 var totalWeightModel = product.ProductFields.Values.FirstOrDefault(x => x.SystemName == "TotalWeight"); 219 var payloadModel = product.ProductFields.Values.FirstOrDefault(x => x.SystemName == "Payload"); 220 var insideDimensionModel = product.ProductFields.Values.FirstOrDefault(x => x.SystemName == "InsideDimension"); 221 var outsideModel = product.ProductFields.Values.FirstOrDefault(x => x.SystemName == "OutsideDimension"); 222 var amountAxlesModel = product.ProductFields.Values.FirstOrDefault(x => x.SystemName == "AmountAxles"); 223 var brakeModel = product.ProductFields.Values.FirstOrDefault(x => x.SystemName == "Brake"); 224 var outsideWheelModel = product.ProductFields.Values.FirstOrDefault(x => x.SystemName == "OutsideWheel"); 225 var tippModel = product.ProductFields.Values.FirstOrDefault(x => x.SystemName == "Tipp"); 226 227 var totalWeightValue = totalWeightModel.Value.ToString(); 228 var payloadValue = payloadModel.Value.ToString(); 229 var insideDimensionValue = insideDimensionModel.Value.ToString(); 230 var outsideModelValue = outsideModel.Value.ToString(); 231 var amountAxlesValue = amountAxlesModel.Value.ToString(); 232 var brakeValue = brakeModel.Value.ToString(); 233 var outsideWheelValue = outsideWheelModel.Value.ToString(); 234 var tippValue = tippModel.Value.ToString();*@ 235 236 int dealerStock = DealerHelper.GetDealerStock(product.Id); 237 238 <!--Lagerstatus start--> 239 var test = Dynamicweb.Ecommerce.Products.Product.GetProductById(product.Number); 240 var groupID = test.GetDefaultGroupByShopId("SHOP1"); 241 var parent = groupID.PrimaryParentGroupId; 242 243 var groups = ""; 244 var spareParts = "false"; 245 foreach (var x in test.Groups) 246 { 247 groups = x.Name; 248 } 249 250 if (groups.Contains("Reservedeler")) 251 { 252 spareParts = "true"; 253 } 254 <!--Lagerstatus end--> 255 256 257 258 <article class="position-relative@(productTheme) product-list-item box p-0 d-flex flex-column" style="height: fit-content"> 259 @if (!anonymousUser && !hideFavoritesSelector && product.VariantInfo.VariantInfo == null) { 260 <div class="position-absolute top-0 end-0 my-3" style="z-index: 2"> 261 @RenderPartial("Components/ToggleFavorite.cshtml", product, favoriteParameters) 262 </div> 263 } 264 265 @if (showBadges) { 266 <div class="position-absolute top-0 left-0 p-1 p-lg-2 ps-0 ps-lg-0" style="z-index: 2"> 267 @RenderPartial("Components/EcommerceBadge_custom.cshtml", product, badgeParms) 268 </div> 269 } 270 271 <a href="@link"> 272 <div class="overflow-hidden@(imageTheme)" @imageOutlineStyle> 273 <div class="ratio" style="@(ratioVariable)"> 274 <div class="d-flex justify-content-center align-items-center"> 275 @*if (string.IsNullOrEmpty(alternativeImage)) { 276 <img 277 id="@imageId" 278 279 src="@imagePath" 280 loading="lazy" 281 decoding="async" 282 class="mw-100 mh-100 @imageThemePadding" 283 alt="@product.Name"> 284 } else { 285 <img 286 id="@imageId" 287 src="@imagePathFallBack" 288 loading="lazy" 289 decoding="async" 290 class="mw-100 mh-100 @imageThemePadding" 291 alt="@product.Name" 292 onmouseover="this.src='@alternativeImage'" 293 onmouseout="this.src='@imagePathFallBack'"> 294 }*@ 295 <img class="productlist-image" src="@imagePath" alt="@product.Name"/> 296 </div> 297 </div> 298 299 300 <div class="position-relative"> 301 @if (product.VariantInfo.VariantInfo != null && staticVariantsLayout == "images") { 302 int variantGroupCount = 0; 303 int showMaxVariantGroups = 2; 304 int showMaxVariants = 3; 305 var productVariantTheme = productTheme != "" ? productTheme : "bg-white"; 306 307 <div 308 class="static-variants w-100 d-none d-lg-block position-absolute left-0 bottom-0 @productTheme" 309 id="StaticVariants_@product.Id" 310 style="pointer-events: none;"> 311 312 @foreach (var variantGroup in product.VariantGroups()) 313 { 314 int variantsCount = 0; 315 316 <div class="d-flex gap-2 mb-2"> 317 @foreach (var variant in variantGroup.Options) 318 { 319 if (variantGroupCount < showMaxVariantGroups) 320 { 321 var optionsCount = variantGroup.Options.Count(); 322 323 if (variantsCount < showMaxVariants) 324 { 325 string optionWidth = !string.IsNullOrEmpty(variant.Color) ? "w-25" : ""; 326 327 <article class="static-variants-option @optionWidth @(productVariantTheme)" title="@product.Name @variant.Name" style="pointer-events: initial;"> 328 @if (!string.IsNullOrEmpty(variant.Color)) 329 { 330 string defaultProductImage = Dynamicweb.Context.Current.Server.UrlEncode(product.DefaultImage.Value); 331 string variantImage = Dynamicweb.Context.Current.Server.UrlEncode(variant.Image.Value); 332 string defaultPrice = !hidePrice ? product.Price.PriceFormatted : "0"; 333 string variantPrice = !hidePrice ? product.Price.PriceFormatted : "0"; 334 335 <figure class="figure w-100 d-block m-0" onmouseover="switchVariantProduct('@product.Id', '@defaultPrice', '@variantImage')" onmouseout="switchVariantProduct('@product.Id', '@variantPrice', '@defaultProductImage')"> 336 <div class="d-flex align-items-center justify-content-center"> 337 <img src="/admin/public/GetImage.ashx?image=@variantImage&width=75&height=75&crop=5&FillCanvas=true&format=webp&Quality=70" height="75" width="75" class="p-1 text-small" loading="lazy" decoding="async" alt="@product.Name, @variant.Name"> 338 </div> 339 </figure> 340 } 341 else 342 { 343 <div class="d-flex align-items-center justify-content-center"> 344 @variant.Name 345 </div> 346 } 347 <div class="visually-hidden"> 348 <h4>@Translate("Variant Name")</h4> 349 <p>@product.Name, @variant.Name</p> 350 @if (!hidePrice) { 351 <h4>@Translate("Variant Price")</h4> 352 <p><span class="text-price">@product.Price.PriceFormatted</span></p> 353 } 354 </div> 355 </article> 356 } 357 358 variantsCount++; 359 360 if (variantsCount == showMaxVariants && optionsCount != showMaxVariants) 361 { 362 int left = optionsCount - showMaxVariants; 363 <div class="variant-option ms-1 d-flex justify-content-center align-items-center"> 364 <span>+@left</span> 365 </div> 366 } 367 } 368 } 369 370 </div> 371 372 variantGroupCount++; 373 } 374 </div> 375 } 376 </div> 377 </div> 378 </a> 379 <div class="@productThemePadding"> 380 381 <div> 382 <a href="@link" class="text-decoration-none text-productname-productlist"><h3 class="Product-name-size heading-size-box mb-1" title="@product.Name @product.VariantName">@product.Name</h3></a> 383 @if (!Model.Item.GetBoolean("HideProductNumber")) { 384 385 <p class="fs-7 pb-0 opacity-85 mb-2 productNumber">@product.Number</p> 386 387 } 388 389 <div class="text-shortdecription-productlist mb-3"> @Dynamicweb.Core.Helpers.StringHelper.StripHtml(product.ShortDescription)</div> 390 391 @if (alternativProductValue == "1") 392 { 393 <div>@Translate("UTGÅTT VARE - Erstattet av:") <a href="reservedeler-og-ekstrautstyr?productid=@alternativProductNumberValue">@alternativProductNumberValue</a></div> 394 } 395 @if (mainFeatures.Count > 0) 396 { 397 398 foreach (CategoryFieldViewModel mainFeatureGroup in mainFeatures) 399 { 400 401 @RenderFieldsFromList(mainFeatureGroup.Fields, i) 402 403 } 404 405 } 406 407 @*<ul class="p-0 lh-sm mt-3" style="list-style-type: none"> 408 @if (!string.IsNullOrEmpty(totalWeightValue)) { 409 <li class="d-flex justify-content-between mb-1">@Translate("Totalvekt") <span>@totalWeightValue</span></li> 410 <li class="d-flex justify-content-between mb-1">@Translate("Kassemål (LxBxH)") <span>@insideDimensionValue</span></li> 411 <li class="justify-content-between mb-1 hidden-custom-field-@i" style="display:none">@Translate("Nyttelast") <span>@payloadValue</span></li> 412 <li class="justify-content-between mb-1 hidden-custom-field-@i" style="display:none">@Translate("Utvendig mål (LxBxH)") <span>@outsideModelValue</span></li> 413 <li class="justify-content-between mb-1 hidden-custom-field-@i" style="display:none">@Translate("Antall aksler") <span>@amountAxlesValue</span></li> 414 <li class="justify-content-between mb-1 hidden-custom-field-@i" style="display:none">@Translate("Brems") <span>@Translate(brakeValue)</span></li> 415 <li class="justify-content-between mb-1 hidden-custom-field-@i" style="display:none">@Translate("Utenpåliggende hjul") <span>@Translate(outsideWheelValue)</span></li> 416 <li class="justify-content-between mb-1 hidden-custom-field-@i" style="display:none">@Translate("Tipp") <span>@Translate(tippValue)</span></li> 417 } 418 </ul>*@ 419 420 <div class="d-none"> 421 @if (product.ProductCategories != null) { 422 423 if (product.ProductCategories.Count > 0) { 424 foreach (var group in product.ProductCategories) { 425 CategoryFieldViewModel category = group.Value; 426 bool hideHeader = Model.Item.GetBoolean("HideGroupHeaders"); 427 428 @*if (!hideHeader) { 429 <h4 class="h4 mb-4">@group.Key</h4> 430 }*@ 431 432 if (product.ProductCategories.Count == 2) 433 { 434 if (group.Key == "Varehenger") 435 { 436 @RenderFieldsFromList(category.Fields, i); 437 } 438 } 439 else 440 { 441 @RenderFieldsFromList(category.Fields, i); 442 } 443 444 } 445 } 446 } 447 </div> 448 @if (!currentUrl.Contains("ekstrautstyr")) { 449 <div class="mb-2" onclick="toggleCustomFields(@i)" style="cursor:pointer; font-size:13px; font-weight:500;"> 450 <span id="toggleFields_@i">Flere detaljer</span> 451 <span class="icon-2"> 452 <img id="toggleFieldsIcon_@i" src="/Files/Templates/Designs/Swift/Assets/icons/chevron-down.svg" /> 453 </span> 454 </div> 455 } 456 </div> 457 </div> 458 459 <div class="d-flex flex-column justify-content-end mt-auto px-3 pb-2 pt-0"> 460 @if ( hideBuyInformationValue == "True" ) 461 { 462 <div class="regular-bread-text">@Translate("IKKE SALGSVARE - Klikk på produkt for å få frem stykkliste")</div> 463 } 464 else 465 { 466 if (!hidePrice) { 467 string priceMin = ""; 468 string priceMax = ""; 469 470 <div> 471 <div class="d-flex align-items-baseline"> 472 <span itemprop="priceCurrency" content="@product.Price.CurrencyCode" class="d-none"></span> 473 474 @if (showPricesWithVat == "false" && !neverShowVat) { 475 string beforePrice = product.PriceBeforeDiscount.PriceWithVatFormatted; 476 477 <span itemprop="price" content="@product.Price.PriceWithoutVat" class="d-none"></span> 478 if (product.Price.Price != product.PriceBeforeDiscount.Price) { 479 <span class="text-decoration-line-through opacity-75 me-3 text-price">@beforePrice</span> 480 } 481 } else { 482 string beforePrice = product.PriceBeforeDiscount.PriceWithVatFormatted; 483 484 <span itemprop="price" content="@product.Price.Price" class="d-none"></span> 485 if (product.Price.Price != product.PriceBeforeDiscount.Price) { 486 <span class="text-decoration-line-through opacity-75 me-3 text-price">@beforePrice</span> 487 } 488 } 489 490 @if (showPricesWithVat == "false" && !neverShowVat) { 491 string price = product.Price.PriceWithoutVatFormatted; 492 if (product?.VariantInfo?.VariantInfo != null) { 493 priceMin = product?.VariantInfo?.PriceMin?.PriceWithoutVatFormatted != null ? product.VariantInfo.PriceMin.PriceWithoutVatFormatted : ""; 494 priceMax = product?.VariantInfo?.PriceMax?.PriceWithoutVatFormatted != null ? product.VariantInfo.PriceMax.PriceWithoutVatFormatted : ""; 495 } 496 if (priceMin != priceMax) { 497 price = priceMin + " - " + priceMax; 498 } 499 <span class="text-price fw-bold">@price</span> 500 } else { 501 string price = product.Price.PriceWithVatFormatted; 502 string priceWithoutVat = product.Price.PriceWithoutVatFormatted; 503 if (product?.VariantInfo?.VariantInfo != null) { 504 priceMin = product?.VariantInfo?.PriceMin?.PriceFormatted != null ? product.VariantInfo.PriceMin.PriceFormatted : ""; 505 priceMax = product?.VariantInfo?.PriceMax?.PriceFormatted != null ? product.VariantInfo.PriceMax.PriceFormatted : ""; 506 } 507 if (priceMin != priceMax) { 508 price = priceMin + " - " + priceMax; 509 } 510 if (alternativProductValue != "1") 511 { 512 if (product.Price.Price != product.PriceBeforeDiscount.Price) { 513 <span class="text-price price-size netPrice tysse-red">@price</span> 514 <span class="text-price price-size priceWithoutVat tysse-red" style="display: none;">@priceWithoutVat <span style="font-size: 14px;">@Translate("eks.MVA")</span></span> 515 } else { 516 <span class="text-price price-size netPrice">@price</span> 517 <span class="text-price price-size priceWithoutVat" style="display: none;">@priceWithoutVat <span style="font-size: 14px;">@Translate("eks.MVA")</span></span> 518 } 519 } 520 } 521 </div> 522 @*if (showPricesWithVat == "false" && !neverShowVat) { 523 string price = product.Price.PriceWithVatFormatted; 524 if (product?.VariantInfo?.VariantInfo != null) { 525 priceMin = product?.VariantInfo?.PriceMin?.PriceWithVatFormatted != null ? product.VariantInfo.PriceMin.PriceWithVatFormatted : ""; 526 priceMax = product?.VariantInfo?.PriceMax?.PriceWithVatFormatted != null ? product.VariantInfo.PriceMax.PriceWithVatFormatted : ""; 527 } 528 if (priceMin != priceMax) { 529 price = priceMin + " - " + priceMax; 530 } 531 <div class="fs-7 opacity-85 text-price">@price @Translate("Incl. VAT")</div> 532 }*@ 533 </div> 534 } 535 } 536 @if (product.VariantInfo.VariantInfo != null && staticVariantsLayout == "swatches") { 537 var optionCount = product.VariantInfo.VariantInfo.Count(); 538 var showMaxVariants = 5; 539 540 <div class="d-flex flex-row gap-1 align-items-center"> 541 @foreach (VariantInfoViewModel variant in product.VariantInfo.VariantInfo.Take(showMaxVariants)) 542 { 543 <span class="colorbox colorbox-sm rounded-circle me-1" style="background-color: @variant.OptionColor"></span> 544 } 545 @if (optionCount > showMaxVariants) 546 { 547 int left = optionCount - showMaxVariants; 548 <span class="ms-2">+@left</span> 549 } 550 </div> 551 } 552 <!-- <div class="mt-2"> 553 <a href="@link" class="btn btn-primary w-100">@Translate("Les mer")</a> 554 </div> --> 555 556 </div> 557 <div class="px-3 pb-3 gap-2" style="display: grid; grid-template-columns: 1fr 1fr;"> 558 559 <!-- Lagerstatus start --> 560 <div> 561 562 563 @if(selectedDealer != null){ 564 565 <div data-productid="@product.Id"> 566 @if (spareParts == "true") { 567 <div class=""> 568 <span class="icon-2" style="color: #D79C04;"> @ReadFile(iconPath + "alert-circle.svg")</span> 569 <span class="x-small-text-bold">@Translate("Usikker lagerstatus")</span> 570 </div> 571 } 572 573 else{ 574 575 576 if(dealerStock <= 0){ 577 <div data-productid="@product.Id" class="notInStock"> 578 <span class="icon-2" style="color: grey;"> @ReadFile(iconPath + "alert-circle.svg")</span> 579 <span class="x-small-text-bold">@Translate("Ikke på lager")</span> 580 </div> 581 <div class="x-small-text">@Translate("Kontakt oss for leveringstid")</div> 582 <div class="x-small-text">@Translate("Tlf:") @selectedDealer.Phone</div> 583 } 584 else 585 { 586 <div data-productid="@product.Id" class="inStock" style="min-height: 57px; display: flex;"> 587 <span class="icon-2" style="color: green; align-self: end;"> @ReadFile(iconPath + "check-circle.svg")</span> 588 <span data-productid="@product.Id" class="x-small-text-bold stockText" style="align-self: end; margin-left: 5px;">@Translate("På lager")</span> 589 </div> 590 } 591 592 } 593 594 <hr class="my-1" style="margin: 0" /> 595 <!-- VELG BUTIKK--> 596 @if (spareParts == "true") { 597 <div class="mt-1"> 598 <div class="small-text">@Translate("")</div> 599 </div> 600 } 601 602 <div> 603 <div class="dealerNameSlider x-small-text">@selectedDealer.Name</div> 604 <div data-bs-toggle="modal" data-bs-target="#FindDealer" data-productid="@product.Id" data-group="@spareParts" class="x-small-text text-decoration-underline dealer-modal" style=" cursor: pointer;">Endre butikk</div> 605 </div> 606 607 </div> 608 } 609 else 610 { 611 <!-- Ingen butikk valgt start--> 612 <div data-productid="@product.Id" class="noDealer d-block"> 613 <div class=""> 614 <span class="icon-2" style="color: #A9A9A9;"> @ReadFile(iconPath + "home.svg")</span> 615 <span class="x-small-text-bold">@Translate("Ingen butikk valgt")</span> 616 </div> 617 <hr class="my-1" style="margin: 0" /> 618 <div data-bs-toggle="modal" data-bs-target="#FindDealer" data-productid="@product.Id" data-group="@spareParts" class="x-small-text text-decoration-underline dealer-modal" style=" cursor: pointer;">Velg butikk for lagerstatus</div> 619 </div> 620 <!-- Ingen butikk valgt end--> 621 } 622 </div> 623 <!-- Lagerstatus end --> 624 625 626 <!-- LAGERSTATUS SENDES I POST START --> 627 @if (clickShopValue == "2") 628 { 629 <div> 630 @if (product.StockLevel > 100) 631 { 632 <span class="icon-2" style="color: green;"> @ReadFile(iconPath + "check-circle.svg")</span> 633 <span class="x-small-text-bold">På nettlager </span> 634 <hr class="my-1" style="margin: 0"> 635 <div class="x-small-text">(100+)</div> 636 } 637 else if (product.StockLevel > 50) 638 { 639 <span class="icon-2"style="color: green;"> @ReadFile(iconPath + "check-circle.svg")</span> 640 <span class="x-small-text-bold">På nettlager </span> 641 <hr class="my-1" style="margin: 0"> 642 <div class="x-small-text">(50+)</div> 643 } 644 else if (product.StockLevel > 10) 645 { 646 <span class="icon-2" style="color: green;"> @ReadFile(iconPath + "check-circle.svg")</span> 647 <span class="x-small-text-bold">På nettlager </span> 648 <hr class="my-1" style="margin: 0"> 649 <div class="x-small-text">(10+)</div> 650 } 651 else if (product.StockLevel > 0) 652 { 653 <span class="icon-2"style="color: green;"> @ReadFile(iconPath + "check-circle.svg")</span> 654 <span class="x-small-text-bold">På nettlager</span> 655 <hr class="my-1" style="margin: 0"> 656 <div class="x-small-text">@product.StockLevel</div> 657 } 658 else 659 { 660 <span class="icon-2"> @ReadFile(iconPath + "alert-circle.svg")</span> 661 <span class="x-small-text-bold">@Translate("Ikke på lager")</span> 662 <hr class="my-1" style="margin: 0"> 663 <div class="x-small-text"style="color: white !important;">.</div> 664 } 665 </div> 666 667 668 } 669 else 670 { 671 } 672 673 674 </div> 675 <!-- LAGERSTATUS SENDES I POST SLUTT --> 676 677 </article> 678 i++; 679 } 680 </div> 681 682 <div class="my-3"> 683 <div class="text-center d-flex flex-column gap-3"> 684 <div class="opacity-85">@loadedProducts @Translate("out of") @productList.TotalProductsCount @Translate("products")</div> 685 @if (productList.PageCount != 1) { 686 string sortBySelection = Dynamicweb.Context.Current.Request?.Form["SortBy"] ?? "NameForSort"; 687 sortBySelection = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("SortBy")) ? Dynamicweb.Context.Current.Request.QueryString.Get("SortBy") : sortBySelection; 688 689 var SearchParameter = HttpContext.Current.Request.QueryString.Get("q"); 690 691 <form method="get" action="@url" data-response-target-element="content" class="w-100"> 692 @foreach (FacetGroupViewModel facetGroup in productList.FacetGroups) 693 { 694 foreach (FacetViewModel facetItem in facetGroup.Facets) 695 { 696 foreach (FacetOptionViewModel facetOption in facetItem.Options) 697 { 698 if (facetOption.Selected) 699 { 700 <input type="hidden" name="@facetItem.QueryParameter" value="[@facetOption.Value]" /> 701 } 702 } 703 } 704 } 705 706 @if (productList?.Group?.Id != null) { 707 <input type="hidden" name="GroupId" value="@productList.Group.Id" /> 708 709 } 710 711 <input type="hidden" name="PageSize" value="@pageSize" /> 712 <input type="hidden" name="SortBy" value="@sortBySelection" /> 713 <input type="hidden" name="RequestType" value="UpdateList" /> 714 <input type="hidden" name="q" value="@SearchParameter" /> 715 716 717 <button class="btn btn-primary" type="button" onclick="swift.ProductList.Update(event)">@Translate("Load more products")</button> 718 </form> 719 } 720 </div> 721 </div> 722 723 <script> 724 function switchVariantProduct(id, price, imagesrc) { 725 var productImageElement = document.querySelector("#ProductImage_" + id); 726 var productPriceElement = document.querySelector("#ProductPrice_" + id + " .text-price"); 727 728 if (productPriceElement) { 729 productPriceElement.innerText = price; 730 } 731 732 if (productImageElement) { 733 productImageElement.src = imagesrc; 734 735 var imageSrcset = productImageElement.srcset; 736 imageSrcset = imageSrcset.replace(/image=.*?&/g, 'image=' + imagesrc + "&"); 737 738 productImageElement.srcset = imageSrcset; 739 } 740 } 741 742 function toggleCustomFields (i) { 743 var hiddenFields = document.getElementsByClassName("hidden-custom-field-" + i); 744 var button = document.getElementById("toggleFields_" + i); 745 var icon = document.getElementById("toggleFieldsIcon_" + i); 746 747 for (var i = 0; i < hiddenFields.length; i++) { 748 if (hiddenFields[i].style.display == 'none') { 749 hiddenFields[i].style.display = 'flex'; 750 button.innerHTML = "Mindre detaljer"; 751 icon.src = "/Files/Templates/Designs/Swift/Assets/icons/chevron-up.svg"; 752 } 753 else 754 { 755 hiddenFields[i].style.display = 'none'; 756 button.innerHTML = "Flere detaljer"; 757 icon.src = "/Files/Templates/Designs/Swift/Assets/icons/chevron-down.svg"; 758 } 759 } 760 } 761 762 763 </script> 764 } else { 765 if (!Pageview.IsVisualEditorMode) { 766 <div class="alert alert-dark m-0"> 767 @Translate("We did not find anything matching your search result") 768 </div> 769 } else { 770 <div class="alert alert-dark m-0" role="alert"> 771 <span>@Translate("Product list: The list will be shown here, if any")</span> 772 </div> 773 } 774 } 775 } 776 777 @helper RenderFieldsFromList(Dictionary<string, FieldValueViewModel> fields, int i) { 778 779 var count = 0; 780 781 <div class="mt-0"> 782 <div class="mb-0"> 783 @foreach (var field in fields) { 784 string fieldValue = field.Value?.Value != null ? field.Value.ToString() : ""; 785 786 if (count >= 2) 787 { 788 @RenderHiddenCategoriesFields(field.Value, i) 789 } 790 else 791 { 792 @RenderCategoriesFields(field.Value, i) 793 } 794 795 if (!string.IsNullOrEmpty(fieldValue)) { 796 count++; 797 } 798 } 799 800 </div> 801 </div> 802 } 803 804 @helper RenderCategoriesFields(FieldValueViewModel field, int i) 805 { 806 string fieldValue = field?.Value != null ? field.Value.ToString() : ""; 807 bool noValues = false; 808 809 if (!string.IsNullOrEmpty(fieldValue)) 810 { 811 if (field.Value.GetType() == typeof(System.Collections.Generic.List<FieldOptionValueViewModel>)) 812 { 813 System.Collections.Generic.List<FieldOptionValueViewModel> values = field.Value as System.Collections.Generic.List<FieldOptionValueViewModel>; 814 noValues = values.Count > 0 ? false : true; 815 } 816 } 817 818 if (!string.IsNullOrEmpty(fieldValue) && noValues == false && fieldValue != "0" ) 819 { 820 <div class="d-flex"> 821 <span class="font-size-productlist-product" style="font-size: 13px; font-weight: 400;">@field.Name</span> 822 <span class="ms-auto font-size-productlist-product"style="font-size: 13px; font-weight: 400;"> 823 @RenderCategoriesFieldsValue(field) 824 </span> 825 </div> 826 } 827 } 828 829 @helper RenderHiddenCategoriesFields(FieldValueViewModel field, int i) 830 { 831 string fieldValue = field?.Value != null ? field.Value.ToString() : ""; 832 bool noValues = false; 833 834 if (!string.IsNullOrEmpty(fieldValue)) 835 { 836 if (field.Value.GetType() == typeof(System.Collections.Generic.List<FieldOptionValueViewModel>)) 837 { 838 System.Collections.Generic.List<FieldOptionValueViewModel> values = field.Value as System.Collections.Generic.List<FieldOptionValueViewModel>; 839 noValues = values.Count > 0 ? false : true; 840 } 841 } 842 843 if (!string.IsNullOrEmpty(fieldValue) && noValues == false && fieldValue != "0") 844 { 845 <div class="hidden-custom-field-@i" style="display: none"> 846 <span class="font-size-productlist-product" style="font-size: 13px">@field.Name</span> 847 <span class="ms-auto font-size-productlist-product"style="font-size: 13px"> 848 @RenderCategoriesFieldsValue(field) 849 </span> 850 </div> 851 } 852 } 853 854 @helper RenderCategoriesFieldsValue(FieldValueViewModel field) 855 { 856 string fieldValue = field?.Value != null ? field.Value.ToString() : ""; 857 858 fieldValue = fieldValue == "False" ? Translate("No") : fieldValue; 859 fieldValue = fieldValue == "True" ? Translate("Yes") : fieldValue; 860 861 bool isColor = false; 862 863 if (field.Value.GetType() == typeof(System.Collections.Generic.List<Dynamicweb.Ecommerce.ProductCatalog.FieldOptionValueViewModel>)) 864 { 865 int valueCount = 0; 866 System.Collections.Generic.List<FieldOptionValueViewModel> values = field.Value as System.Collections.Generic.List<FieldOptionValueViewModel>; 867 int totalValues = values.Count; 868 869 foreach (FieldOptionValueViewModel option in values) 870 { 871 if (option.Value.Substring(0, 1) == "#") 872 { 873 isColor = true; 874 } 875 876 if (!isColor) 877 { 878 @option.Name 879 } 880 else 881 { 882 <span class="colorbox-sm" style="background-color: @option.Value" title="@option.Value"></span> 883 } 884 885 if (valueCount != totalValues && valueCount < (totalValues - 1)) 886 { 887 if (isColor) 888 { 889 <text> </text> 890 } 891 else 892 { 893 <text>, </text> 894 } 895 } 896 valueCount++; 897 } 898 } 899 else 900 { 901 if (fieldValue.Substring(0, 1) == "#") 902 { 903 isColor = true; 904 } 905 906 if (!isColor) 907 { 908 @fieldValue 909 } 910 else 911 { 912 <span class="colorbox-sm" style="background-color: @fieldValue" title="@fieldValue"></span> 913 } 914 } 915 } 916 917 @helper RenderField(FieldValueViewModel field) { 918 string fieldValue = field?.Value != null ? field.Value.ToString() : ""; 919 920 if (fieldValue != "") { 921 fieldValue = fieldValue == "False" ? Translate("No") : fieldValue; 922 fieldValue = fieldValue == "True" ? Translate("Yes") : fieldValue; 923 924 if (field.Value.GetType() == typeof(System.Collections.Generic.List<FieldOptionValueViewModel>)) { 925 fieldValue = ""; 926 927 foreach (FieldOptionValueViewModel option in field.Value as System.Collections.Generic.List<FieldOptionValueViewModel>) { 928 fieldValue = option.Value; 929 } 930 } 931 932 bool isColor = false; 933 if (fieldValue.Contains("#") && (Translate(field.Name) == Translate("Color") || Translate(field.Name) == Translate("Colour"))) { 934 isColor = true; 935 } 936 937 if (!string.IsNullOrEmpty(fieldValue)) { 938 if (!isColor) { 939 <li>@fieldValue</li> 940 } else { 941 <li class="position-relative"> 942 <span class="colorbox-sm" style="background-color: @fieldValue"></span> 943 </li> 944 } 945 } 946 } 947 } 948 949
Ved å trykke på "Godta alle" godkjenner du at vi kan samle inn informasjon om deg til forskjellig bruk. F.eks Statistikk og markedsføring