Nyheder

Sortering

Error executing template "/Designs/Swift/Paragraph/Swift_ProductListGridView_Custom.cshtml"
System.InvalidCastException: Unable to cast object of type 'System.DBNull' to type 'System.String'.
   at NLWI.Platforms.Dynamicweb9.Specs.Repositories.ProductSpecificationRepository.GetSpecificationObjectIdentifiers(HashSet`1 autoIds)
   at NLWI.Platforms.Dynamicweb9.Specs.Repositories.ProductSpecificationRepository.GetProductAutoIdMap(HashSet`1 autoIds)
   at NLWI.Platforms.Dynamicweb9.Specs.Services.CachedProductSpecificationService.<GetAutoIdMap>b__14_1(HashSet`1 k)
   at NLWI.Core.Platform.Caching.DictionaryCaching.GetOrInsert[TKey,TVal](HashSet`1 keys, Func`2 buildCacheKey, Func`2 lookupMethod, CacheOptions cacheOptions)
   at NLWI.Platforms.Dynamicweb9.Specs.Services.CachedProductSpecificationService.GetAutoIdMap(HashSet`1 productAutoIds)
   at NLWI.Platforms.Dynamicweb9.Specs.Services.CachedProductSpecificationService.GetProductSpecifications(HashSet`1 productAutoIds)
   at NLWI.Platforms.Dynamicweb9.Specs.Services.CachedProductSpecificationService.GetProductSpecifications(Int64 productAutoId)
   at CompiledRazorTemplates.Dynamic.RazorEngine_dfcffeb1681942f4b6ce2dcd36fefbb6.<RenderProductList>b__10_0(TextWriter __razor_helper_writer) in C:\inetpub\solutions\Goecker-2022-Staging\Files\Templates\Designs\Swift\Paragraph\Swift_ProductListGridView_Custom.cshtml:line 298
   at CompiledRazorTemplates.Dynamic.RazorEngine_dfcffeb1681942f4b6ce2dcd36fefbb6.Execute() in C:\inetpub\solutions\Goecker-2022-Staging\Files\Templates\Designs\Swift\Paragraph\Swift_ProductListGridView_Custom.cshtml:line 190
   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.Linq 5 @using Dynamicweb.Core 6 @using Dynamicweb.Environment 7 @using NLWI.Core.Factory 8 @using NLWI.Platforms.Dynamicweb9.Specs.ViewModels 9 @using NLWI.Platforms.Dynamicweb9.Specs.Services 10 @using NORRIQ.CustomCode.Razor 11 @using NORRIQ.CustomCode.StockLocations 12 @using System.Text; 13 @using System.Web; 14 @using Dynamicweb; 15 @using Dynamicweb.Core.Encoders 16 @using System.Globalization 17 18 @* CUSTOMIZED STANDARD SWIFT (v1.15.0) TEMPLATE *@ 19 20 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 21 22 @helper RenderAddedModal(bool isRental = false) 23 { 24 string productsFeedUrl = $"/Default.aspx?ID={GetPageIdByNavigationTag("productsfeed")}&feed=true&redirect=false"; 25 string checkoutUrl = isRental ? $"/Default.aspx?ID={GetPageIdByNavigationTag("rentalcheckout")}" : $"/Default.aspx?ID={GetPageIdByNavigationTag("checkout")}"; 26 string cartUrl = "/Default.aspx?ID=" + (GetPageIdByNavigationTag("CartService")); 27 if (!cartUrl.Contains("LayoutTemplate")) 28 { 29 cartUrl += cartUrl.Contains("?") ? "&LayoutTemplate=Swift_MiniCart.cshtml" : "?LayoutTemplate=Swift_MiniCart.cshtml"; 30 } 31 32 <div class="modal fade product-added-modal js-product-added-modal" data-productsfeedurl="@productsFeedUrl" tabindex="-1" role="dialog"> 33 <input type="hidden" class="js-translation choose" value="@HttpUtility.HtmlEncode(Translate("Smartpage.Product.AddedModal.Choose", "Vælg"))" /> 34 <input type="hidden" class="js-translation period-price" value="@HttpUtility.HtmlAttributeEncode(Translate("Smartpage:Rental.PeriodPrice", "Pris for periode:"))" /> 35 <input type="hidden" class="js-translation daily-price" value="@HttpUtility.HtmlAttributeEncode(Translate("Smartpage:Rental.DailyPrice", "Dagspris:"))" /> 36 37 <div class="modal-dialog" role="document"> 38 <div class="modal-content"> 39 <div class="modal-header"> 40 <div class="d-flex flex-column"> 41 <h3 class="modal-title">@Translate("Smartpage.Product.AddedModal.Header", "Tilføjet til kurv")</h3> 42 @if (isRental) 43 { 44 <p> 45 @Translate("Smartpage.Rental.PeriodDays", "Skydedage") 46 <span class="js-rental-periodfrom"></span> - <span class="js-rental-periodto"></span> 47 </p> 48 } 49 </div> 50 <div class="cross-icon cursor-pointer" onclick="hideModal(this)"></div> 51 </div> 52 <div class="spinner-border js-loader powerstep-loader text-dark d-none"> 53 <span class="visually-hidden">Loading..</span> 54 </div> 55 <div class="modal-body container pt-2 pb-0 px-3 m-0 text-center text-lg-start"> 56 <div class="js-product-modal-orderline row gap-2 gap-lg-0 d-flex flex-column flex-lg-row justify-content-between pb-2 border-bottom"> 57 <div class="col-lg-6 col-12 d-flex align-items-center flex-column flex-lg-row gap-3 gap-lg-0"> 58 <img class="js-product-modal-orderline-image mr-2" /> 59 <a class="js-product-modal-orderline-name text-decoration-none fw-bold px-md-3 px-lg-0"> 60 </a> 61 </div> 62 <div class="col-lg-6 col-12 d-flex flex-column align-items-center align-items-lg-end justify-content-center"> 63 @if (!isRental) 64 { 65 <div class="d-flex mr-2"> 66 <span class="js-product-modal-orderline-price"></span> 67 </div> 68 } 69 else 70 { 71 <div class="d-flex mr-2"> 72 <span class="me-2">@Translate("Smartpage:Rental.DailyPrice", "Dagspris:")</span> <span class="js-product-modal-orderline-dailyprice"></span> 73 </div> 74 <div class="d-flex"> 75 <span class="me-2">@Translate("Smartpage:Rental.PeriodPrice", "Pris for periode:")</span> <span class="js-product-modal-orderline-periodprice"></span> 76 </div> 77 } 78 </div> 79 </div> 80 <div class="row border-bottom"> 81 <h5 class="fw-bold py-3 fs-sm-7 fs-md-6">@Translate("Smartpage.Product.AddedModal.Recommendation", "Til ovenstående produkt anbefaler vi:")</h5> 82 </div> 83 <div class="js-product-modal-relatedproducts d-flex flex-column"></div> 84 </div> 85 86 <div class="modal-footer border-top-0 justify-content-end"> 87 @if (!isRental) 88 { 89 <form method="post" action="@cartUrl" class="js-relatedproducts-form"> 90 <input type="hidden" name="cartcmd" value="addmulti" /> 91 <input type="hidden" name="redirect" value="false" /> 92 93 <div class="js-products-inputs"></div> 94 95 <button class="btn btn-primary js-add-to-cart-button disabled" onclick="swift.Cart.Update(event)">@Translate("Tilføj til kurv")</button> 96 </form> 97 } 98 else 99 { 100 <form class="js-relatedproducts-form"> 101 <div class="js-products-inputs"></div> 102 <button class="btn btn-primary js-add-to-rental disabled" onclick="addRelatedRentalProducts(event, this)">@Translate("Tilføj til kurv")</button> 103 </form> 104 } 105 </div> 106 <div class="modal-footer justify-content-between"> 107 <button type="button" class="btn btn-primary" onclick="hideModal(this)">@Translate("Smartpage.Product.AddedModal.BackToShop", "Tilbage til shop")</button> 108 <a href="@checkoutUrl" class="btn btn-primary">@Translate("Smartpage.Product.AddedModal.Checkout", "Til checkout")</a> 109 </div> 110 </div> 111 </div> 112 </div> 113 } 114 @using NLWI.Platforms.Dynamicweb9.Specs.ViewModels 115 116 @functions { 117 string GetProductImage(ProductSpecifications specs) 118 { 119 string imageUrl = "/Files/Images/Perfion/default.png"; 120 121 if (specs.HasKey("Primærbillede")) 122 { 123 imageUrl = specs.GetByKey("Primærbillede").Value; 124 } 125 126 return imageUrl; 127 } 128 129 Dictionary<string, string> GetAllProductImages(ProductSpecifications specs) 130 { 131 Dictionary<string, string> images = new Dictionary<string, string>(); 132 133 foreach (var img in specs.GetByGroup("Billeder")) 134 { 135 if (!images.ContainsKey(img.Value) && img.Key != "Brandlogo") 136 { 137 images.Add(img.Value, img.Caption); 138 } 139 } 140 141 return images; 142 } 143 } 144 145 @functions 146 { 147 bool isLazyLoadingForProductInfoEnabled = Dynamicweb.Ecommerce.DynamicwebLiveIntegration.TemplatesHelper.IsLazyLoadingForProductInfoEnabled; 148 string liveInfoClass = ""; 149 string productInfoFeed = ""; 150 151 string showPricesWithVat = ""; 152 bool neverShowVat = false; 153 154 bool isDetailPage = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("ProductID")); 155 156 ProductListViewModel productList = new ProductListViewModel(); 157 } 158 159 @{ 160 if (Dynamicweb.Context.Current.Items.Contains("ProductList")) 161 { 162 productList = (ProductListViewModel)Dynamicweb.Context.Current.Items["ProductList"]; 163 } 164 165 showPricesWithVat = HttpContext.Current.Session["Smartpage:ShowPricesWithVat"] != null ? Convert.ToString(HttpContext.Current.Session["Smartpage:ShowPricesWithVat"]) : Pageview.Area.EcomPricesWithVat.ToLower(); 166 neverShowVat = string.IsNullOrEmpty(showPricesWithVat); 167 168 if (isLazyLoadingForProductInfoEnabled) 169 { 170 if (Dynamicweb.Context.Current.Items.Contains("ProductInfoFeed")) 171 { 172 productInfoFeed = Dynamicweb.Context.Current.Items["ProductInfoFeed"]?.ToString(); 173 if (!string.IsNullOrEmpty(productInfoFeed)) 174 { 175 productInfoFeed = $"data-product-info-feed=\"{productInfoFeed}\""; 176 } 177 } 178 liveInfoClass = "js-live-info"; 179 } 180 181 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 182 string themePadding = theme != string.Empty ? "p-3" : string.Empty; 183 } 184 185 @if (!isDetailPage) 186 { 187 if (!string.IsNullOrEmpty(theme)) 188 { 189 <div class="h-100@(theme) @themePadding item_@Model.Item.SystemName.ToLower()" @productInfoFeed> 190 @RenderProductList() 191 </div> 192 } 193 else 194 { 195 <div class="pt-3 item_@Model.Item.SystemName.ToLower()" @productInfoFeed> 196 @RenderProductList() 197 </div> 198 } 199 } 200 201 @helper RenderProductList() 202 { 203 var productSpecificationService = ObjectFactory.GetInstance<IProductSpecificationService>(); 204 var stockService = ObjectFactory.GetInstance<StockService>(); 205 var featurePostFix = Pageview.AreaSettings.GetItem("CustomSettings").GetRawValueString("FeaturePostFix_Custom", ""); 206 207 string anonymousUsersLimitations = Pageview.AreaSettings.GetRawValueString("AnonymousUsers", ""); 208 bool anonymousUser = Pageview.User == null; 209 bool hidePrice = anonymousUsersLimitations.Contains("price") && anonymousUser || Pageview.AreaSettings.GetBoolean("ErpDownHidePrices") && !Dynamicweb.Ecommerce.DynamicwebLiveIntegration.TemplatesHelper.IsWebServiceConnectionAvailable(); 210 211 string productTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("ProductTheme")) ? " theme " + Model.Item.GetRawValueString("ProductTheme").Replace(" ", "").Trim().ToLower() : ""; 212 string productThemePadding = productTheme != string.Empty ? "p-3" : string.Empty; 213 214 string url = Dynamicweb.Context.Current.Request.RawUrl; 215 bool hideFavoritesSelector = !string.IsNullOrEmpty(Model.Item.GetString("HideFavoritesSelector")) ? Model.Item.GetBoolean("HideFavoritesSelector") : false; 216 bool showFavoritesSelectorMasterProduct = !string.IsNullOrEmpty(Model.Item.GetString("ShowFavoritesSelectorMasterProduct")) ? Model.Item.GetBoolean("ShowFavoritesSelectorMasterProduct") : false; 217 string staticVariantsLayout = Model.Item.GetRawValueString("StaticVariantsLayout", "hide"); 218 219 string groupId = productList?.Group?.Id != null ? productList.Group.Id : ""; 220 221 string cartUrl = "/Default.aspx?ID=" + (GetPageIdByNavigationTag("CartService")); 222 if (!cartUrl.Contains("LayoutTemplate")) 223 { 224 cartUrl += cartUrl.Contains("?") ? "&LayoutTemplate=Swift_MiniCart.cshtml" : "?LayoutTemplate=Swift_MiniCart.cshtml"; 225 } 226 227 var badgeParms = new Dictionary<string, object>(); 228 badgeParms.Add("saleBadgeType", Model.Item.GetRawValue("SaleBadgeType")); 229 badgeParms.Add("saleBadgeCssClassName", Model.Item.GetRawValue("SaleBadgeDesign")); 230 badgeParms.Add("newBadgeCssClassName", Model.Item.GetRawValue("NewBadgeDesign")); 231 badgeParms.Add("newPublicationDays", Model.Item.GetInt32("NewPublicationDays")); 232 badgeParms.Add("campaignBadgesValues", Model.Item.GetRawValueString("CampaignBadges")); 233 234 bool saleBadgeEnabled = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("SaleBadgeDesign")) && Model.Item.GetRawValueString("SaleBadgeDesign") != "none" ? true : false; 235 bool newBadgeEnabled = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("NewBadgeDesign")) && Model.Item.GetRawValueString("NewBadgeDesign") != "none" ? true : false; 236 237 string googleAnalyticsTrackingID = Pageview.AreaSettings.GetString("GoogleAnalyticsTrackingID"); 238 string googleAnalyticsMeasurementID = Pageview.AreaSettings.GetString("GoogleAnalyticsMeasurementID"); 239 var cookieOptInLevel = CookieManager.GetCookieOptInLevel(); 240 bool allowTracking = cookieOptInLevel == CookieOptInLevel.All || (cookieOptInLevel == CookieOptInLevel.Functional && CookieManager.GetCookieOptInCategories().Contains("Statistical")); 241 242 var favoriteParameters = new Dictionary<string, object>(); 243 if (!anonymousUser && !hideFavoritesSelector) 244 { 245 int defaultFavoriteListId = 0; 246 247 IEnumerable<FavoriteList> favoreiteLists = Pageview.User.GetFavoriteLists(); 248 if (favoreiteLists.Count() == 1) 249 { 250 foreach (FavoriteList list in favoreiteLists) 251 { 252 defaultFavoriteListId = list.ListId; 253 } 254 } 255 256 favoriteParameters.Add("ListId", defaultFavoriteListId); 257 } 258 259 if (productList.TotalProductsCount > 0) 260 { 261 int pageSizeSetting = 30; 262 int pageSize = productList.PageSize; 263 pageSize += pageSizeSetting; 264 265 int loadedProducts = productList.PageSize > productList.TotalProductsCount ? productList.TotalProductsCount : productList.PageSize; 266 267 <div class="grid grid-2 grid-lg-3"> 268 @* 269 20250512: Removed by AE 270 @RenderAddedModal(false) 271 *@ 272 273 <script> 274 window.addEventListener('CookieInformationConsentGiven', function (event) { 275 if (CookieInformation.getConsentGivenFor('cookie_cat_statistic')) { 276 gtag("event", "view_item_list", { 277 item_list_id: "product_list_gridview", 278 item_list_name: "Product list (Gridview)", 279 items: [ 280 @foreach (ProductViewModel product in productList.Products) 281 { 282 <text>{ 283 item_id: "@product.Number", 284 item_name: "@product.Name", 285 currency: "@product.Price.CurrencyCode", 286 price: @product.Price.Price 287 },</text> 288 } 289 ] 290 }); 291 } 292 }, false); 293 </script> 294 295 296 @foreach (ProductViewModel product in productList.Products) 297 { 298 var specs = product.GetSpecifications(); 299 var availableStockLocations = product.StockUnits.Where(a => a.StockLevel > 0).Select(a => a.StockLocationName).ToList(); 300 var inStock = availableStockLocations.Any(); 301 302 string variantIdForLink = !string.IsNullOrEmpty(product.VariantId) ? $"&VariantID={product.VariantId}" : ""; 303 variantIdForLink = string.IsNullOrEmpty(variantIdForLink) && !string.IsNullOrEmpty(product.DefaultVariantId) ? $"&VariantID={product.DefaultVariantId}" : variantIdForLink; 304 305 string link = "Default.aspx?ID=" + GetPageIdByNavigationTag("Shop"); 306 link += $"&GroupID={product.PrimaryOrDefaultGroup.Id}"; 307 link += $"&ProductID={product.Id}"; 308 link += variantIdForLink; 309 link = Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl(link); 310 311 string imagePath = product?.DefaultImage?.Value ?? ""; 312 imagePath = Dynamicweb.Context.Current.Server.UrlEncode(imagePath); 313 314 string ratio = Model.Item.GetRawValueString("ImageAspectRatio", ""); 315 ratio = ratio != "0" ? ratio : ""; 316 string ratioCssClass = ratio != "" ? " ratio" : ""; 317 string ratioVariable = ratio != "" ? "--bs-aspect-ratio: " + ratio : ""; 318 319 string imagePathXs = "/Admin/Public/GetImage.ashx?width=" + 480 + "&image=" + imagePath + "&format=webp"; 320 string imagePathS = "/Admin/Public/GetImage.ashx?width=" + 640 + "&image=" + imagePath + "&format=webp"; 321 string imagePathFallBack = "/Admin/Public/GetImage.ashx?width=" + 640 + "&image=" + imagePath + "&format=webp"; 322 323 string imageTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("ImageTheme")) ? " theme " + Model.Item.GetRawValueString("ImageTheme").Replace(" ", "").Trim().ToLower() : ""; 324 string imageThemePadding = imageTheme != string.Empty ? "p-3" : string.Empty; 325 string imageOutlineStyle = imageTheme == string.Empty ? "style=\"border: 1px solid transparent\"" : string.Empty; 326 327 string imageId = "ProductImage_" + product.Id + product.VariantId; 328 string priceId = "ProductPrice_" + product.Id + product.VariantId; 329 330 @* Alternative image *@ 331 var supportedImageFormats = new string[] { ".jpg", ".webp", ".png", ".gif" }; 332 string defaultImage = product.DefaultImage != null ? product.DefaultImage.Value : ""; 333 var selectedAssetCategories = Model.Item.GetRawValueString("AlternativeImageAssets"); 334 IEnumerable<MediaViewModel> alternativeImagesList = product.AssetCategories.Where(x => selectedAssetCategories.Contains(x.SystemName)).SelectMany(x => x.Assets); 335 336 if (alternativeImagesList.FirstOrDefault() != null) 337 { 338 alternativeImagesList = alternativeImagesList.OrderByDescending(x => x.Value.Equals(defaultImage)); 339 340 if (alternativeImagesList.First().Value == defaultImage) 341 { 342 alternativeImagesList = alternativeImagesList.Skip(1); 343 } 344 } 345 346 string alternativeImage = alternativeImagesList.FirstOrDefault() != null ? alternativeImagesList.FirstOrDefault().Value : ""; 347 alternativeImage = !string.IsNullOrEmpty(alternativeImage) ? "/Admin/Public/GetImage.ashx?width=" + 640 + "&image=" + alternativeImage + "&format=webp" : ""; 348 349 @* Badges *@ 350 DateTime createdDate = product.Created.Value; 351 bool showBadges = saleBadgeEnabled && product.Discount.Price != 0 ? true : false; 352 showBadges = (newBadgeEnabled && Model.Item.GetInt32("NewPublicationDays") == 0) || (newBadgeEnabled && (createdDate.AddDays(Model.Item.GetInt32("NewPublicationDays")) > DateTime.Now)) ? true : showBadges; 353 showBadges = !string.IsNullOrEmpty(Model.Item.GetRawValueString("CampaignBadges")) ? true : showBadges; 354 355 @* Main features *@ 356 IEnumerable<string> selectedDisplayGroups = Model.Item.GetRawValueString("MainFeatures").Split(',').ToList(); 357 List<CategoryFieldViewModel> mainFeatures = new List<CategoryFieldViewModel>(); 358 359 foreach (var selection in selectedDisplayGroups) 360 { 361 foreach (CategoryFieldViewModel group in product.FieldDisplayGroups.Values) 362 { 363 if (selection == group.Id) 364 { 365 mainFeatures.Add(group); 366 } 367 } 368 } 369 370 //CUSTOM 371 var disablePrice = product.ProductFields.ContainsKey("Custom_DisablePrice") ? Convert.ToBoolean(product.ProductFields["Custom_DisablePrice"].Value) : false; 372 var disablePurchase = product.ProductFields.ContainsKey("Custom_DisablePurchase") ? Convert.ToBoolean(product.ProductFields["Custom_DisablePurchase"].Value) : false; 373 var disableStock = product.ProductFields.ContainsKey("Custom_DisableStock") ? Convert.ToBoolean(product.ProductFields["Custom_DisableStock"].Value) : false; 374 var enableContact = product.ProductFields.ContainsKey("Custom_EnableContact") ? Convert.ToBoolean(product.ProductFields["Custom_EnableContact"].Value) : false; 375 var enableBookDemo = product.ProductFields.ContainsKey("Custom_EnableBookDemo") ? Convert.ToBoolean(product.ProductFields["Custom_EnableBookDemo"].Value) : false; 376 377 var productDiscountInfo = Custom.Discounts.Services.DiscountInfoService.GetDiscountExtenderInfoByProductId(product.Id)?.Where(x => !string.IsNullOrEmpty(x.CampaignLabel)); 378 //--CUSTOM 379 380 <article class="position-relative@(productTheme) product-list-item js-product @liveInfoClass" data-product-id="@product.Id" itemscope itemtype="https://schema.org/Product"> 381 382 @if (specs.HasKey("Ikon" + featurePostFix) 383 || (productDiscountInfo != null && productDiscountInfo.Any())) 384 { 385 <div class="product-label"> 386 @foreach (var label in specs.GetAllByKey("Ikon" + featurePostFix)) 387 { 388 var referenceSpecfication = label.GetReferenceSpecification(); 389 var txtcolor = "#ffffff"; 390 if (!string.IsNullOrEmpty(referenceSpecfication.GetByKey("LinkFarvekode").Value)) 391 { 392 txtcolor = referenceSpecfication.GetByKey("LinkFarvekode").Value; 393 } 394 if (referenceSpecfication.HasKey("LinkURL")) 395 { 396 <a href="@(referenceSpecfication.GetByKey("LinkURL").Value)" class="product-label-item" style="background-color:@(referenceSpecfication.GetByKey("Farvekode").Value);color:@txtcolor;"> 397 @referenceSpecfication.GetByKey("Label").Value 398 </a> 399 } 400 else 401 { 402 <span class="product-label-item" style="background-color:@(referenceSpecfication.GetByKey("Farvekode").Value);color:@txtcolor;"> 403 @referenceSpecfication.GetByKey("Label").Value 404 </span> 405 } 406 } 407 408 @*CUSTOM*@ 409 @if (productDiscountInfo != null) 410 { 411 foreach (var discount in productDiscountInfo) 412 { 413 <span class="product-label-item" style="background-color: @discount.CampaignLabelColor; color: @(!string.IsNullOrEmpty(discount.CampaignLabelTextColor) ? discount.CampaignLabelTextColor : "#ffffff");"> 414 @discount.CampaignLabel 415 </span> 416 } 417 } 418 @*CUSTOM*@ 419 420 </div> 421 } 422 423 @if (!anonymousUser) 424 { 425 if (!hideFavoritesSelector && product.VariantInfo.VariantInfo == null) 426 { 427 <div class="position-absolute top-0 end-0 my-3" style="z-index: 2"> 428 @RenderPartial("Components/ToggleFavorite.cshtml", product, favoriteParameters) 429 </div> 430 } 431 else if (showFavoritesSelectorMasterProduct) 432 { 433 <div class="position-absolute top-0 end-0 my-3" style="z-index: 2"> 434 @RenderPartial("Components/ToggleFavorite.cshtml", product, favoriteParameters) 435 </div> 436 } 437 } 438 439 @if (showBadges) 440 { 441 <div class="position-absolute top-0 left-0 p-1 p-lg-2 ps-0 ps-lg-0" style="z-index: 2"> 442 @RenderPartial("Components/EcommerceBadge.cshtml", product, badgeParms) 443 </div> 444 } 445 446 <div class="d-flex flex-column d-block h-100 text-center"> 447 @{ 448 string clickProductLink = string.Empty; 449 if (allowTracking) 450 { 451 clickProductLink = "onclick=\"return clickProductLink('" + @product.Id + "', '" + @product.Name + "', '" + @product.VariantName + "', '" + @product.Price.CurrencyCode + "', '" + @product.Price.Price + "')\""; 452 } 453 } 454 <a href="@link" class="text-decoration-none d-flex flex-column" @clickProductLink> 455 @if (allowTracking) 456 { 457 <script> 458 function clickProductLink(productId, productName, productVariant, productCurrency, productPrice) { 459 if (typeof gtag !== "undefined") { 460 gtag("event", "select_item", { 461 item_list_id: "product_list_gridview", 462 item_list_name: "Product list (Gridview)", 463 items: [ 464 { 465 item_id: productId, 466 item_name: productName, 467 currency: productCurrency, 468 item_list_id: "product_list_gridview", 469 item_list_name: "Product list (Gridview)", 470 item_variant: productVariant, 471 price: productPrice 472 } 473 ] 474 }); 475 } 476 } 477 </script> 478 } 479 480 <div class="@productThemePadding order-2"> 481 <div class="flex-grow-1"> 482 <h3 class="h6 mb-0 text-break" itemprop="name"> 483 @product.Name @if (!string.IsNullOrEmpty(product.VariantName)) 484 {<text>(@product.VariantName)</text>} 485 </h3> 486 @if (!Model.Item.GetBoolean("HideProductNumber")) 487 { 488 <p class="fs-7 opacity-85 mb-2">@product.Number</p> 489 } 490 @if (mainFeatures.Count > 0) 491 { 492 <ul class="p-0 lh-sm opacity-75" style="list-style-position: inside"> 493 @foreach (CategoryFieldViewModel mainFeatureGroup in mainFeatures) 494 { 495 foreach (var field in mainFeatureGroup.Fields) 496 { 497 @RenderField(field.Value) 498 } 499 } 500 </ul> 501 } 502 </div> 503 </div> 504 505 <div class="overflow-hidden order-1 @(imageTheme)" @imageOutlineStyle> 506 <div class="ratio" style="@(ratioVariable)"> 507 <div class="d-flex justify-content-center align-items-center"> 508 @if (string.IsNullOrEmpty(alternativeImage)) 509 { 510 <img id="@imageId" itemprop="image" 511 srcset=" 512 @imagePathXs 480w, 513 @imagePathS 640w" 514 sizes="(min-width: 992px) 33vw, 50vw" 515 src="@imagePathFallBack" 516 loading="lazy" 517 decoding="async" 518 class="mw-100 mh-100 @imageThemePadding" 519 alt="@product.Name"> 520 } 521 else 522 { 523 <img id="@imageId" itemprop="image" 524 src="@imagePathFallBack" 525 loading="lazy" 526 decoding="async" 527 class="mw-100 mh-100 @imageThemePadding" 528 alt="@product.Name" 529 onmouseover="this.src='@alternativeImage'" 530 onmouseout="this.src='@imagePathFallBack'"> 531 } 532 </div> 533 </div> 534 535 @if (product.VariantInfo.VariantInfo != null && staticVariantsLayout == "images") 536 { 537 int variantGroupCount = 0; 538 int showMaxVariantGroups = 2; 539 int showMaxVariants = 3; 540 var productVariantTheme = productTheme != "" ? productTheme : "bg-white"; 541 542 <div class="position-relative"> 543 <div id="StaticVariants_@product.Id" class="static-variants w-100 d-none d-lg-block position-absolute left-0 bottom-0 @productTheme" style="pointer-events: none;"> 544 545 @foreach (var variantGroup in product.VariantGroups()) 546 { 547 int variantsCount = 0; 548 549 <div class="d-flex gap-2 mb-2"> 550 @foreach (var variant in variantGroup.Options) 551 { 552 if (variantGroupCount < showMaxVariantGroups) 553 { 554 var optionsCount = variantGroup.Options.Count(); 555 556 if (variantsCount < showMaxVariants) 557 { 558 string optionWidth = !string.IsNullOrEmpty(variant.Color) ? "w-25" : ""; 559 560 <article class="static-variants-option @optionWidth @(productVariantTheme)" title="@product.Name @variant.Name" style="pointer-events: initial;"> 561 @if (!string.IsNullOrEmpty(variant.Color)) 562 { 563 string defaultProductImage = Dynamicweb.Context.Current.Server.UrlEncode(product.DefaultImage.Value); 564 string variantImage = Dynamicweb.Context.Current.Server.UrlEncode(variant.Image.Value); 565 string defaultPrice = !hidePrice ? product.Price.PriceFormatted : "0"; 566 string variantPrice = !hidePrice ? product.Price.PriceFormatted : "0"; 567 568 if (isLazyLoadingForProductInfoEnabled) 569 { 570 <figure class="w-100 d-block m-0" data-price-formatted="" onmouseover="swift.StaticVariants.SwitchProduct(event, '@product.Id', this.getAttribute('data-price-formatted'), '@variantImage')" onmouseout="swift.StaticVariants.SwitchProduct(event, '@product.Id', this.getAttribute('data-price-formatted'), '@defaultProductImage')"> 571 <div class="d-flex align-items-center justify-content-center"> 572 <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"> 573 </div> 574 </figure> 575 } 576 else 577 { 578 <figure class="w-100 d-block m-0" onmouseover="swift.StaticVariants.SwitchProduct(event, '@product.Id', '@defaultPrice', '@variantImage')" onmouseout="swift.StaticVariants.SwitchProduct(event, '@product.Id', '@variantPrice', '@defaultProductImage')"> 579 <div class="d-flex align-items-center justify-content-center"> 580 <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"> 581 </div> 582 </figure> 583 } 584 } 585 else 586 { 587 <div class="d-flex align-items-center justify-content-center"> 588 @variant.Name 589 </div> 590 } 591 <div class="visually-hidden"> 592 <h4>@product.Name, @variant.Name</h4> 593 @if (!hidePrice) 594 { 595 if (isLazyLoadingForProductInfoEnabled) 596 { 597 <span class="text-price js-text-price"></span> 598 } 599 else 600 { 601 <span class="text-price">@product.Price.PriceFormatted</span> 602 } 603 } 604 </div> 605 </article> 606 } 607 608 variantsCount++; 609 610 if (variantsCount == showMaxVariants && optionsCount != showMaxVariants) 611 { 612 int left = optionsCount - showMaxVariants; 613 <div class="variant-option ms-1 d-flex justify-content-center align-items-center"> 614 <span>+@left</span> 615 </div> 616 } 617 } 618 } 619 </div> 620 621 variantGroupCount++; 622 } 623 </div> 624 </div> 625 } 626 </div> 627 </a> 628 <div class="@productThemePadding mt-auto pt-0"> 629 630 @if (!disableStock) //CUSTOM 631 { 632 <div> 633 @if (inStock && availableStockLocations.Any()) 634 { 635 <span class="icon-stock icon-green position-relative" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-title="@HttpUtility.HtmlAttributeEncode(string.Join("<br />", availableStockLocations))" data-bs-html="true">@Translate("label_in_Stock", "På lager")</span> 636 } 637 else 638 { 639 <span class="icon-stock icon-red position-relative">@Translate("label_not_in_stock", "Ikke på lager")</span> 640 } 641 </div> 642 643 <script> 644 window.addEventListener('DOMContentLoaded', function () { 645 var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]')) 646 var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) { 647 return new bootstrap.Tooltip(tooltipTriggerEl) 648 }) 649 }, false); 650 </script> 651 } 652 653 @if (!hidePrice && !disablePrice) //CUSTOM 654 { 655 string priceMin = ""; 656 string priceMax = ""; 657 658 <div class="mt-2"> 659 <div itemprop="offers" itemscope itemtype="https://schema.org/Offer"> 660 <span itemprop="priceCurrency" content="@product.Price.CurrencyCode" class="d-none"></span> 661 662 @if (showPricesWithVat == "false" && !neverShowVat) 663 { 664 if (isLazyLoadingForProductInfoEnabled) 665 { 666 <span itemprop="price" content="" class="d-none"></span> 667 <span class="text-decoration-line-through js-text-decoration-line-through opacity-75 me-3 text-price js-text-price d-none" data-show-if="LiveProductInfo.product.Price.Price != LiveProductInfo.product.PriceBeforeDiscount.Price"></span> 668 } 669 else 670 { 671 string beforePrice = product.PriceBeforeDiscount.PriceWithoutVatFormatted; 672 string informativePrice = product.PriceInformative.PriceWithoutVatFormatted; 673 674 <span itemprop="price" content="@product.Price.PriceWithoutVat.ToString("0.00", CultureInfo.InvariantCulture)" class="d-none"></span> 675 if (product.Price.Price != product.PriceBeforeDiscount.Price) 676 { 677 <span class="text-decoration-line-through opacity-75 me-3 text-price">@beforePrice</span> 678 } 679 else if (product.PriceInformative.Price > 0) 680 { 681 <span class="text-decoration-line-through opacity-75 me-3 text-price">@informativePrice</span> 682 } 683 } 684 } 685 else 686 { 687 if (isLazyLoadingForProductInfoEnabled) 688 { 689 <span itemprop="price" content="" class="d-none"></span> 690 <span class="text-decoration-line-through js-text-decoration-line-through opacity-75 me-3 text-price js-text-price d-none" data-show-if="LiveProductInfo.product.Price.Price != LiveProductInfo.product.PriceBeforeDiscount.Price"></span> 691 } 692 else 693 { 694 string beforePrice = product.PriceBeforeDiscount.PriceFormatted; 695 string informativePrice = product.PriceInformative.PriceWithVatFormatted; 696 697 <span itemprop="price" content="@product.Price.Price.ToString("0.00", CultureInfo.InvariantCulture)" class="d-none"></span> 698 if (product.Price.Price != product.PriceBeforeDiscount.Price) 699 { 700 <span class="text-decoration-line-through opacity-75 me-3 text-price">@beforePrice</span> 701 } 702 else if (product.PriceInformative.Price > 0) 703 { 704 <span class="text-decoration-line-through opacity-75 me-3 text-price">@informativePrice</span> 705 } 706 } 707 } 708 709 @if (showPricesWithVat == "false" && !neverShowVat) 710 { 711 if (isLazyLoadingForProductInfoEnabled) 712 { 713 <span class="text-price js-text-price"><div class="spinner-border" role="status"></div></span> 714 } 715 else 716 { 717 string price = product.Price.PriceWithoutVatFormatted; 718 if (product?.VariantInfo?.VariantInfo != null) 719 { 720 priceMin = product?.VariantInfo?.PriceMin?.PriceWithoutVatFormatted != null ? product.VariantInfo.PriceMin.PriceWithoutVatFormatted : ""; 721 priceMax = product?.VariantInfo?.PriceMax?.PriceWithoutVatFormatted != null ? product.VariantInfo.PriceMax.PriceWithoutVatFormatted : ""; 722 } 723 if (priceMin != priceMax) 724 { 725 price = priceMin + " - " + priceMax; 726 } 727 <span class="text-price">@price</span> 728 } 729 } 730 else 731 { 732 if (isLazyLoadingForProductInfoEnabled) 733 { 734 <span class="text-price js-text-price"><div class="spinner-border" role="status"></div></span> 735 } 736 else 737 { 738 string price = product.Price.PriceFormatted; 739 if (product?.VariantInfo?.VariantInfo != null) 740 { 741 priceMin = product?.VariantInfo?.PriceMin?.PriceFormatted != null ? product.VariantInfo.PriceMin.PriceFormatted : ""; 742 priceMax = product?.VariantInfo?.PriceMax?.PriceFormatted != null ? product.VariantInfo.PriceMax.PriceFormatted : ""; 743 } 744 if (priceMin != priceMax) 745 { 746 price = priceMin + " - " + priceMax; 747 } 748 <span class="text-price">@price</span> 749 } 750 } 751 </div> 752 @if (showPricesWithVat == "false" && !neverShowVat) 753 { 754 if (isLazyLoadingForProductInfoEnabled) 755 { 756 <div class="fs-7 opacity-85 text-price js-text-price-with-vat d-none" data-suffix="@Translate("Incl. VAT")"></div> 757 } 758 else 759 { 760 string price = product.Price.PriceWithVatFormatted; 761 if (product?.VariantInfo?.VariantInfo != null) 762 { 763 priceMin = product?.VariantInfo?.PriceMin?.PriceWithVatFormatted != null ? product.VariantInfo.PriceMin.PriceWithVatFormatted : ""; 764 priceMax = product?.VariantInfo?.PriceMax?.PriceWithVatFormatted != null ? product.VariantInfo.PriceMax.PriceWithVatFormatted : ""; 765 } 766 if (priceMin != priceMax) 767 { 768 price = priceMin + " - " + priceMax; 769 } 770 <div class="fs-7 opacity-85 text-price">@price @Translate("Incl. VAT")</div> 771 } 772 } 773 </div> 774 } 775 776 <div class="icon-compare mt-2 d-none d-sm-flex justify-content-center align-items-center fs-7" 777 data-number="@HttpUtility.HtmlAttributeEncode(product.Number)" 778 data-image="@HttpUtility.HtmlAttributeEncode(imagePath)" 779 data-name="@HttpUtility.HtmlAttributeEncode(product.Name)" 780 data-link="@HttpUtility.HtmlAttributeEncode(link)" 781 onclick="toggleCompareProduct(event, this)"> 782 <span class="square-icon js-square-icon d-flex" data-product-number="@HttpUtility.HtmlAttributeEncode(product.Number)"></span> 783 <span>@Translate("Sammenlign")</span> 784 </div> 785 786 @if (product.VariantInfo.VariantInfo != null && staticVariantsLayout == "swatches") 787 { 788 var optionCount = product.VariantInfo.VariantInfo.Count(); 789 var showMaxVariants = 5; 790 791 <div class="d-flex flex-row gap-1 align-items-center"> 792 @foreach (VariantInfoViewModel variant in product.VariantInfo.VariantInfo.Take(showMaxVariants)) 793 { 794 <span class="colorbox colorbox-sm rounded-circle border me-1" style="background-color: @variant.OptionColor"></span> 795 } 796 @if (optionCount > showMaxVariants) 797 { 798 int left = optionCount - showMaxVariants; 799 <span class="ms-2">+@left</span> 800 } 801 </div> 802 } 803 804 <div class="mt-3"> 805 <form method="post" action="@cartUrl"> 806 <input type="hidden" name="redirect" value="false" /> 807 <input type="hidden" name="ProductId" value="@product.Id" /> 808 <input type="hidden" name="ProductName" value="@HtmlEncoder.HtmlEncode(product.Name)" /> 809 <input type="hidden" name="ProductVariantName" value="@HtmlEncoder.HtmlEncode(product.VariantName)" /> 810 <input type="hidden" name="ProductCurrency" value="@Dynamicweb.Ecommerce.Common.Context.Currency.Code" /> 811 <input type="hidden" name="ProductPrice" value="@(showPricesWithVat == "false" && !neverShowVat ? product.Price.PriceWithoutVat.ToString("0.00", CultureInfo.InvariantCulture) : product.Price.Price.ToString("0.00", CultureInfo.InvariantCulture))" /> 812 <input type="hidden" name="ProductReferer" value="component_ProductListGridView_Custom"> 813 <input type="hidden" name="cartcmd" value="add" /> 814 <input type="hidden" name="quantity" value="1" /> 815 <input type="hidden" class="js-product-id" value="@product.Id" /> 816 817 @if (!string.IsNullOrEmpty(product.VariantId)) 818 { 819 <input type="hidden" name="VariantId" value="@product.VariantId" /> 820 } 821 822 @*//CUSTOM*@ 823 <div class="d-flex flex-column gap-2"> 824 @if (enableContact) 825 { 826 var enableContactlink = Pageview.AreaSettings.GetItem("CustomSettings").GetLink("Custom_EnableContactLink"); 827 if (enableContactlink != null) 828 { 829 <a href="@(enableContactlink.Url)" class="btn btn-tertiary flex-fill" title="@HttpUtility.HtmlAttributeEncode(Translate("Contact us about price and delivery >>"))"> 830 @Translate("Contact us about price and delivery >>") 831 </a> 832 } 833 } 834 835 @if (enableBookDemo) 836 { 837 var enableBookDemolink = Pageview.AreaSettings.GetItem("CustomSettings").GetLink("Custom_EnableBookDemoLink"); 838 if (enableBookDemolink != null) 839 { 840 <a href="@(enableBookDemolink.Url)" class="btn btn-tertiary flex-fill" title="@HttpUtility.HtmlAttributeEncode(Translate("Contact us about book demo >>"))"> 841 @Translate("Contact us about book demo >>") 842 </a> 843 } 844 } 845 846 @if (!disablePurchase) 847 { 848 if (!specs.GetByKey("Preorder").Value.IsYes()) 849 { 850 <button type="button" onclick="swift.Cart.Update(event)" class="btn btn-primary flex-fill js-add-to-cart-button" title="@HttpUtility.HtmlAttributeEncode(Translate("Add to cart"))" id="AddToCartButton@(product.Id)"> 851 @Translate("Add to cart") 852 </button> 853 } 854 else 855 { 856 <button type="button" class="btn btn-secondary flex-fill" onclick="Form(this).addData('@HttpUtility.HtmlEncode(product.Name)','@product.Id')" data-bs-toggle="modal" data-bs-target="#preorderModal"> 857 @Translate("Preorder") 858 </button> 859 } 860 } 861 </div> 862 @*//CUSTOM*@ 863 </form> 864 </div> 865 866 </div> 867 868 </div> 869 </article> 870 } 871 </div> 872 873 <div class="my-3" id="LoadMoreButton"> 874 <div class="text-center d-flex flex-column gap-3"> 875 <div class="opacity-85">@loadedProducts @Translate("out of") @productList.TotalProductsCount @Translate("products")</div> 876 @if (productList.PageCount != 1) 877 { 878 string sortBySelection = Dynamicweb.Context.Current.Request?.Form["SortBy"] ?? ""; 879 sortBySelection = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("SortBy")) ? Dynamicweb.Context.Current.Request.QueryString.Get("SortBy") : sortBySelection; 880 881 string searchQuery = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("q")) ? Dynamicweb.Context.Current.Request.QueryString.Get("q") : ""; 882 string searchLayout = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("SearchLayout")) ? Dynamicweb.Context.Current.Request.QueryString.Get("SearchLayout") : ""; 883 884 <form method="get" action="@url" data-response-target-element="content" class="w-100"> 885 @foreach (FacetGroupViewModel facetGroup in productList.FacetGroups) 886 { 887 foreach (FacetViewModel facetItem in facetGroup.Facets) 888 { 889 foreach (FacetOptionViewModel facetOption in facetItem.Options) 890 { 891 if (facetOption.Selected) 892 { 893 <input type="hidden" name="@facetItem.QueryParameter" value="[@facetOption.Value]"> 894 } 895 } 896 } 897 } 898 899 <input type="hidden" name="PageSize" value="@pageSize"> 900 <input type="hidden" name="SortBy" value="@sortBySelection"> 901 <input type="hidden" name="RequestType" value="UpdateList"> 902 903 @if (!string.IsNullOrEmpty(searchQuery)) 904 { 905 <input type="hidden" name="q" value="@HttpUtility.HtmlAttributeEncode(searchQuery)"> 906 <input type="hidden" name="SearchLayout" value="@searchLayout"> 907 } 908 909 @{ 910 string nextPageLink = "/Default.aspx?ID=" + Pageview.Page.ID + "&PageSize=" + pageSize + "&SortBy=" + sortBySelection; 911 912 foreach (FacetGroupViewModel facetGroup in productList.FacetGroups) 913 { 914 foreach (FacetViewModel facetItem in facetGroup.Facets) 915 { 916 foreach (FacetOptionViewModel facetOption in facetItem.Options) 917 { 918 if (facetOption.Selected) 919 { 920 nextPageLink += "&" + facetItem.QueryParameter + "=[" + facetOption.Value + "]"; 921 } 922 } 923 } 924 } 925 926 nextPageLink += !string.IsNullOrEmpty(searchQuery) ? "&q=" + searchQuery : ""; 927 } 928 929 <a href="@nextPageLink" class="btn btn-primary" onclick="swift.ProductList.Update(event)" id="LoadMoreButton_@Model.ID">@Translate("Load more products")</a> 930 </form> 931 } 932 </div> 933 </div> 934 } 935 else 936 { 937 if (!Pageview.IsVisualEditorMode) 938 { 939 <div class="alert alert-dark m-0"> 940 @Translate("We did not find anything matching your search result") 941 </div> 942 } 943 else 944 { 945 <div class="alert alert-dark m-0" role="alert"> 946 <span>@Translate("Product list: The list will be shown here, if any")</span> 947 </div> 948 } 949 } 950 } 951 952 @helper RenderField(FieldValueViewModel field) 953 { 954 string fieldValue = field?.Value != null ? field.Value.ToString() : ""; 955 956 if (fieldValue != "") 957 { 958 fieldValue = fieldValue == "False" ? Translate("No") : fieldValue; 959 fieldValue = fieldValue == "True" ? Translate("Yes") : fieldValue; 960 961 if (field.Value.GetType() == typeof(System.Collections.Generic.List<FieldOptionValueViewModel>)) 962 { 963 fieldValue = ""; 964 965 foreach (FieldOptionValueViewModel option in field.Value as System.Collections.Generic.List<FieldOptionValueViewModel>) 966 { 967 fieldValue = option.Name; 968 } 969 } 970 971 bool isColor = false; 972 if (fieldValue.Contains("#") && (Translate(field.Name) == Translate("Color") || Translate(field.Name) == Translate("Colour"))) 973 { 974 isColor = true; 975 } 976 977 if (!string.IsNullOrEmpty(fieldValue)) 978 { 979 if (!isColor) 980 { 981 <li>@(field.Name): @fieldValue</li> 982 } 983 else 984 { 985 <li class="position-relative"> 986 <span class="colorbox-sm" style="background-color: @fieldValue"></span> 987 </li> 988 } 989 } 990 } 991 }