601905200060

Gates V-belt Hi-power Dubl-V AA60

Error executing template "Designs/Swift/Paragraph/Swift_ProductSpecification.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.Products.GroupRelation.GetGroupRelationsByChildId(String childId)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.GetOrderedInheritableParentIds(Group group, String defaultLanguageId)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.RecursivelySearchForFieldValues(Group group, String defaultLanguageId, List`1 categoryFields)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.RecursivelySearchForFieldValues(Group group, String defaultLanguageId, List`1 categoryFields)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.RecursivelySearchForFieldValues(Group group, String defaultLanguageId, List`1 categoryFields)
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.GetGroupFieldValuesByLanguage(Group group, List`1 categoryFields, String languageId, Boolean isInheritedValue, Boolean searchRecursively)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.SearchForGroupFieldValue(Group group, List`1 categoryFields, Boolean allowFallback)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.GetGroupCategoryFieldValues(IEnumerable`1 groups, List`1 fields, Boolean allowFallback)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.GetDefaultCategoryValuesFromGroups(IEnumerable`1 groupInfos, List`1 catFields)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.GetDefaultCategoryValueFromGroups(IEnumerable`1 groupInfos, Field catField)
   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__60()
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at CompiledRazorTemplates.Dynamic.RazorEngine_83c3e920ca6c46f49d5bc5546126d159.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 System.Globalization; 4 @functions 5 { 6 public static class NumberHelper 7 { 8 /// <summary> 9 /// Converts a scientific notation string with a comma (e.g. "5,8E-05") to a decimal. 10 /// Returns 0 if the string is invalid or empty. 11 /// </summary> 12 public static decimal ToDecimal(string input) 13 { 14 if (string.IsNullOrWhiteSpace(input)) 15 { 16 return 0m; 17 } 18 19 // Tell the parser to look for a comma 20 var format = new NumberFormatInfo { NumberDecimalSeparator = "," }; 21 22 // TryParse safely attempts to convert without throwing exceptions on bad data 23 if (decimal.TryParse(input, NumberStyles.Float, format, out decimal result)) 24 { 25 return result; 26 } 27 28 return 0m; // Return a default value if parsing fails 29 } 30 } 31 } 32 @{ 33 ProductViewModel product = null; 34 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 35 { 36 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 37 } 38 else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode) 39 { 40 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 41 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 42 43 if (productList?.Products is object) 44 { 45 product = productList.Products[0]; 46 } 47 } 48 } 49 50 @if (product is object && Model?.Item != null) { 51 var displayGroupsRaw = Model.Item.GetRawValueString("DisplayGroups") ?? ""; 52 IEnumerable<string> selectedDisplayGroupIds = 53 displayGroupsRaw.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); 54 List<CategoryFieldViewModel> displayGroups = new List<CategoryFieldViewModel>(); 55 56 foreach (var selection in selectedDisplayGroupIds) 57 { 58 foreach (CategoryFieldViewModel group in product.FieldDisplayGroups?.Values ?? Enumerable.Empty<CategoryFieldViewModel>()) 59 { 60 if (selection == group.Id) 61 { 62 int fieldsWithNoValueOrZero = 0; 63 64 foreach (var field in group.Fields) 65 { 66 var value = field.Value?.Value?.ToString(); 67 68 if (string.IsNullOrWhiteSpace(value)) 69 { 70 fieldsWithNoValueOrZero++; 71 } 72 } 73 74 if (fieldsWithNoValueOrZero != group.Fields.Count) 75 { 76 displayGroups.Add(group); 77 } 78 } 79 } 80 } 81 82 bool showProductFields = Model.Item.GetBoolean("ProductFields"); 83 84 bool hideTitle = Model.Item.GetBoolean("HideTitle"); 85 86 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 87 88 string titleFontSize = Model.Item.GetRawValueString("TitleFontSize", "display-4"); 89 90 string contentPadding = Model.Item.GetRawValueString("ContentPadding", ""); 91 contentPadding = contentPadding == "none" ? string.Empty : contentPadding; 92 contentPadding = contentPadding == "small" ? " p-2 p-md-3" : contentPadding; 93 contentPadding = contentPadding == "large" ? " p-4 p-md-5" : contentPadding; 94 95 string layout = Model.Item.GetRawValueString("Layout", "list"); 96 string size = Model.Item.GetRawValueString("Size", "full"); 97 string gaps = size == "full" ? " gap-4" : " gap-2"; 98 99 100 if (Pageview.IsVisualEditorMode && displayGroups.Count() == 0) 101 { 102 product.ProductFields.Clear(); 103 product.ProductFields.Add(Translate("Width"), new FieldValueViewModel { Name = Translate("Width"), Value = "99cm" }); 104 product.ProductFields.Add(Translate("Height"), new FieldValueViewModel { Name = Translate("Height"), Value = "195cm" }); 105 showProductFields = true; 106 } 107 108 if (layout == "commas") 109 { 110 gaps = size == "full" ? " gap-4" : " gap-2"; 111 112 } 113 114 <div class="h-100@(gaps)@(theme)@(contentPadding) item_@Model.Item.SystemName.ToLower()"> 115 <div class="grid"> 116 @if ((product.ProductFields != null && Model.Item.GetBoolean("ProductFields")) || (product.ProductCategories != null && Model.Item.GetBoolean("CategoryFields")) || (displayGroups.Count != 0)) { 117 if (!hideTitle) 118 { 119 <h2 class="g-col-12 @titleFontSize">@Model.Item.GetString("Title")</h2> 120 } 121 } 122 123 @if (displayGroups.Count != 0) 124 { 125 if (layout != "accordion") 126 { 127 foreach (var group in displayGroups) 128 { 129 bool hideHeader = Model.Item.GetBoolean("HideGroupHeaders"); 130 131 if (!hideHeader) { 132 <h4 class="g-col-12 h4 mb-0">@group.Name</h4> 133 } 134 135 { @RenderFieldsFromList(group.Fields, layout) } 136 137 } 138 } 139 else 140 { 141 <div class="g-col-12"> 142 <div class="accordion accordion-flush w-100" id="Specifications_@Model.ID"> 143 @foreach (var group in displayGroups) 144 { 145 <div class="accordion-item"> 146 <h2 class="accordion-header" id="SpecificationHeading_@group.Id"> 147 <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#SpecificationItem_@group.Id" aria-expanded="false" aria-controls="SpecificationItem_@group.Id"> 148 @group.Name 149 </button> 150 </h2> 151 <div id="SpecificationItem_@group.Id" class="accordion-collapse collapse" aria-labelledby="SpecificationHeading_@group.Id" data-bs-parent="#Specifications_@Model.ID"> 152 <div class="accordion-body"> 153 @{ @RenderFieldsFromList(group.Fields, "list") } 154 </div> 155 </div> 156 </div> 157 } 158 </div> 159 </div> 160 } 161 } 162 163 @if (product.ProductFields != null && showProductFields) 164 { 165 if (product.ProductFields.Count > 0) 166 { 167 if (layout != "accordion") 168 { 169 {@RenderFieldsFromList(product.ProductFields, layout) } 170 } 171 else 172 { 173 <div class="g-col-12"> 174 <div class="accordion accordion-flush w-100" id="Specifications_@Model.ID"> 175 <div class="accordion-item"> 176 <h2 class="accordion-header" id="SpecificationHeading_@Model.ID"> 177 <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#SpecificationItem_@Model.ID" aria-expanded="false" aria-controls="SpecificationItem_@Model.ID"> 178 @Translate("Specifications") 179 </button> 180 </h2> 181 <div id="SpecificationItem_@Model.ID" class="accordion-collapse" aria-labelledby="SpecificationHeading_@Model.ID" data-bs-parent="#Specifications_@Model.ID"> 182 <div class="accordion-body"> 183 @{ @RenderFieldsFromList(product.ProductFields, "List") } 184 </div> 185 </div> 186 </div> 187 </div> 188 </div> 189 } 190 } 191 } 192 193 @if (product.ProductCategories != null && Model.Item.GetBoolean("CategoryFields")) 194 { 195 if (product.ProductCategories.Count > 0) 196 { 197 if (layout != "accordion") 198 { 199 foreach (var group in product.ProductCategories) 200 { 201 CategoryFieldViewModel category = group.Value; 202 bool hideHeader = Model.Item.GetBoolean("HideGroupHeaders"); 203 204 if (!hideHeader) { 205 <h4 class="g-col-12 h4 mb-0">@group.Value.Name</h4> 206 } 207 208 { @RenderFieldsFromList(category.Fields, layout) } 209 } 210 } 211 else 212 { 213 <div class="g-col-12"> 214 <div class="accordion accordion-flush w-100" id="Specifications_@Model.ID"> 215 @foreach (var group in product.ProductCategories) 216 { 217 CategoryFieldViewModel category = group.Value; 218 219 <div class="accordion-item"> 220 <h2 class="accordion-header" id="SpecificationHeading_@group.Value.Id"> 221 <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#SpecificationItem_@group.Value.Id" aria-expanded="false" aria-controls="SpecificationItem_@group.Value.Id"> 222 @group.Value.Name 223 </button> 224 </h2> 225 <div id="SpecificationItem_@group.Value.Id" class="accordion-collapse" aria-labelledby="SpecificationHeading_@group.Value.Id" data-bs-parent="#Specifications_@Model.ID"> 226 <div class="accordion-body"> 227 @{ @RenderFieldsFromList(category.Fields, "list") } 228 </div> 229 </div> 230 </div> 231 } 232 </div> 233 </div> 234 } 235 } 236 } 237 </div> 238 </div> 239 } 240 else if (Pageview.IsVisualEditorMode) 241 { 242 <div class="alert alert-warning m-0">@Translate("No products available")</div> 243 } 244 245 @helper RenderFieldsFromList(Dictionary<string, FieldValueViewModel> fields, string layout) 246 { 247 string size = Model.Item.GetRawValueString("Size", "full"); 248 string gaps = size != "full" ? " gap-1" : string.Empty; 249 bool hideFieldLabels = Model.Item.GetBoolean("HideFieldLabels"); 250 bool hideFieldsWithZeroValue = Model.Item.GetBoolean("HideFieldsWithZeroValue"); 251 252 if (layout == "columns") { 253 <div class="g-col-12"> 254 <div class="grid@(gaps)"> 255 @foreach (var field in fields) 256 { 257 {@RenderField(field.Value, layout)} 258 } 259 </div> 260 </div> 261 } 262 if (layout == "list") { 263 <div class="g-col-12"> 264 <dl class="grid@(gaps)"> 265 @foreach (var field in fields) 266 { 267 {@RenderField(field.Value, layout)} 268 } 269 </dl> 270 </div> 271 } 272 if (layout == "table") 273 { 274 string tableSize = size == "full" ? "" : " table-sm"; 275 <div class="g-col-12"> 276 <table class="table table-striped@(tableSize)"> 277 @foreach (var field in fields) 278 { 279 {@RenderField(field.Value, layout)} 280 } 281 </table> 282 </div> 283 } 284 if (layout == "bullets") 285 { 286 string listSize = size == "full" ? "" : "m-0 p-0 lh-1 fs-7 opacity-75"; 287 string listStyle = size == "full" ? "" : "style=\"list-style-position: inside\""; 288 <div class="g-col-12"> 289 <ul class="@listSize" @listStyle> 290 @foreach (var field in fields) 291 { 292 {@RenderField(field.Value, layout)} 293 } 294 </ul> 295 </div> 296 } 297 if (layout == "commas") 298 { 299 List<string> featuresList = new List<string>(); 300 301 foreach (var field in fields) 302 { 303 string firstListItemValue = string.Empty; //Hack to support field type providers with a single value 304 305 if (field.Value?.Value != null) 306 { 307 if (field.Value.Value.GetType() == typeof(System.Collections.Generic.List<FieldOptionValueViewModel>)) 308 { 309 System.Collections.Generic.List<FieldOptionValueViewModel> values = field.Value.Value as System.Collections.Generic.List<FieldOptionValueViewModel>; 310 311 //Hack to support field type providers with a single value 312 if (values.FirstOrDefault() != null) 313 { 314 firstListItemValue = values.FirstOrDefault().Value; 315 } 316 } 317 } 318 319 if (!hideFieldsWithZeroValue || (firstListItemValue != "0" && firstListItemValue != "0.0" && field.Value.Value.ToString() != "0" && field.Value.Value.ToString() != "0.0")) 320 { 321 if (field.Value.Value is object && !string.IsNullOrEmpty(field.Value.Value.ToString())) 322 { 323 if (field.Value.Value.GetType() == typeof(System.Collections.Generic.List<FieldOptionValueViewModel>)) 324 { 325 List<string> options = new List<string>(); 326 foreach (FieldOptionValueViewModel option in field.Value.Value as System.Collections.Generic.List<FieldOptionValueViewModel>) 327 { 328 if (!string.IsNullOrWhiteSpace(option.Value)) 329 { 330 if (option.Value.ToString().Contains("#") && (Translate(field.Value.Name) == Translate("Color") || Translate(field.Value.Name) == Translate("Colour"))) 331 { 332 string colorSpan = "<span class=\"colorbox-sm\" style=\"background-color: " + option.Value + "\"></span>"; 333 options.Add(colorSpan); 334 } 335 else if (!string.IsNullOrEmpty(option.Value)) 336 { 337 options.Add(option.Name); 338 } 339 } 340 } 341 string optionsString = (string.Join(", ", options.Select(x => x.ToString()).ToArray())); 342 if ((Translate(field.Value.Name) == Translate("Color") || Translate(field.Value.Name) == Translate("Colour"))) 343 { 344 optionsString = (string.Join(" ", options.Select(x => x.ToString()).ToArray())); 345 } 346 347 if (!string.IsNullOrEmpty(optionsString)) 348 { 349 if (!hideFieldLabels) 350 { 351 featuresList.Add(field.Value.Name + ": " + optionsString); 352 } 353 else 354 { 355 featuresList.Add(optionsString); 356 } 357 } 358 } 359 else 360 { 361 if (!string.IsNullOrWhiteSpace(field.Value.Value.ToString())) 362 { 363 if (field.Value.Value.ToString().Contains("#") && (Translate(field.Value.Name) == Translate("Color") || Translate(field.Value.Name) == Translate("Colour"))) 364 { 365 string colorSpan = "<span class=\"colorbox-sm\" style=\"background-color: " + field.Value.Value + "\"></span>"; 366 367 if (!hideFieldLabels) 368 { 369 featuresList.Add(field.Value.Name + ": " + colorSpan); 370 } 371 else 372 { 373 featuresList.Add(colorSpan); 374 } 375 } 376 else 377 { 378 if (!hideFieldLabels) 379 { 380 featuresList.Add(field.Value.Name + ": " + field.Value.Value.ToString()); 381 } 382 else 383 { 384 featuresList.Add(field.Value.Value.ToString()); 385 } 386 } 387 } 388 } 389 } 390 } 391 } 392 393 string featuresString = (string.Join(", ", featuresList.Select(x => x.ToString()).ToArray())); 394 395 <div class="g-col-12 opacity-75 fs-7">@featuresString</div> 396 } 397 } 398 399 @helper RenderField(FieldValueViewModel field, string layout) 400 { 401 string size = Model.Item.GetRawValueString("Size", "full"); 402 string fieldValue = field?.Value != null ? field.Value.ToString() : ""; 403 bool hideFieldLabels = Model.Item.GetBoolean("HideFieldLabels"); 404 bool noValues = false; 405 string firstListItemValue = string.Empty; //Hack to support field type providers with a single value 406 bool hideFieldsWithZeroValue = Model.Item.GetBoolean("HideFieldsWithZeroValue"); 407 408 if (!string.IsNullOrEmpty(fieldValue)) 409 { 410 if (field.Value.GetType() == typeof(System.Collections.Generic.List<FieldOptionValueViewModel>)) 411 { 412 System.Collections.Generic.List<FieldOptionValueViewModel> values = field.Value as System.Collections.Generic.List<FieldOptionValueViewModel>; 413 noValues = values.Count > 0 ? false : true; 414 415 //Hack to support field type providers with a single value 416 if (values.FirstOrDefault() != null) 417 { 418 firstListItemValue = values.FirstOrDefault().Value; 419 } 420 } 421 } 422 423 if (!string.IsNullOrEmpty(fieldValue) && noValues == false) 424 { 425 if (!hideFieldsWithZeroValue || (firstListItemValue != "0" && firstListItemValue != "0.0" && field.Value.ToString() != "0" && field.Value.ToString() != "0.0")) 426 { 427 if (layout == "columns") 428 { 429 430 <div class="grid g-col-6 g-col-lg-4 gap-1"> 431 @if (!hideFieldLabels) 432 { 433 <dt class="g-col-12 g-col-lg-4">@field.Name</dt> 434 } 435 <dd class="g-col-12 g-col-lg-8 mb-0 text-break"> 436 437 @{ @RenderFieldValue(field)} 438 </dd> 439 </div> 440 } 441 if (layout == "list") 442 { 443 if (!hideFieldLabels) 444 { 445 <dt class="g-col-4">@field.Name</dt> 446 } 447 <dd class="g-col-8 mb-0 text-break"> 448 @{ @RenderFieldValue(field)} 449 </dd> 450 } 451 if (layout == "table") 452 { 453 <tr> 454 @if (!hideFieldLabels) 455 { 456 <th class="w-25 w-lg-50" scope="row">@field.Name</th> 457 } 458 <td class="text-break"> 459 @{ @RenderFieldValue(field) } 460 </td> 461 </tr> 462 } 463 if (layout == "bullets") 464 { 465 <li> 466 @if (!hideFieldLabels) 467 { 468 <strong>@field.Name</strong> 469 } 470 <span> 471 @{ @RenderFieldValue(field) } 472 </span> 473 </li> 474 } 475 } 476 } 477 } 478 479 @helper RenderFieldValue(FieldValueViewModel field) 480 { 481 string fieldValue = field?.Value != null ? field.Value.ToString() : ""; 482 if (field.SystemName == "ProductWeight") 483 { 484 485 decimal calculatedValue = NumberHelper.ToDecimal(fieldValue); 486 decimal baseValue = NumberHelper.ToDecimal("0,00001"); 487 488 489 fieldValue = calculatedValue.ToString("0.######", System.Globalization.CultureInfo.InvariantCulture).Replace(".", ","); 490 491 } 492 bool isLink = field?.Type == "Link"; 493 bool isColor = false; 494 bool isBrandName = field?.SystemName == "Brand_name"; 495 496 fieldValue = fieldValue == "False" ? Translate("No") : fieldValue; 497 fieldValue = fieldValue == "True" ? Translate("Yes") : fieldValue; 498 499 500 if (field.Value.GetType() == typeof(System.Collections.Generic.List<Dynamicweb.Ecommerce.ProductCatalog.FieldOptionValueViewModel>)) 501 { 502 int valueCount = 0; 503 System.Collections.Generic.List<FieldOptionValueViewModel> values = field.Value as System.Collections.Generic.List<FieldOptionValueViewModel>; 504 int totalValues = values.Count; 505 506 foreach (FieldOptionValueViewModel option in values) 507 { 508 if (!string.IsNullOrEmpty(option.Value)) 509 { 510 if (option.Value.Substring(0, 1) == "#") 511 { 512 isColor = true; 513 } 514 } 515 516 if (!isColor) 517 { 518 @option.Name 519 } 520 else 521 { 522 <span class="colorbox-sm" style="background-color: @option.Value" title="@option.Name"></span> 523 } 524 525 if (valueCount != totalValues && valueCount < (totalValues - 1)) 526 { 527 if (isColor) 528 { 529 <text> </text> 530 } 531 else 532 { 533 <text>, </text> 534 } 535 } 536 valueCount++; 537 } 538 } 539 else 540 { 541 if (fieldValue.Substring(0, 1) == "#") 542 { 543 isColor = true; 544 } 545 546 if (!isColor) 547 { 548 if (isLink) 549 { 550 string linktTitle = !fieldValue.Contains("aspx") ? fieldValue : Translate("Go to link"); 551 string target = Pageview.AreaSettings.GetBoolean("OpenLinksInNewTab") && fieldValue.Contains("http") ? "target=\"_blank\"" : string.Empty; 552 string rel = Pageview.AreaSettings.GetBoolean("OpenLinksInNewTab") && fieldValue.Contains("http") ? "rel=\"noopener\"" : string.Empty; 553 554 <a href="@field.Value" title="@field.Name" @target @rel>@linktTitle</a> 555 } 556 else if (isBrandName) 557 { 558 <span itemprop="brand" itemtype="https://schema.org/Brand" itemscope> 559 <span itemprop="name">@fieldValue</span> 560 </span> 561 } 562 else 563 { 564 @fieldValue 565 } 566 567 } 568 else 569 { 570 <span class="colorbox-sm" style="background-color: @fieldValue" title="@fieldValue"></span> 571 } 572 } 573 } 574
Not in stock

Register as a customer under "Log in" to see your prices, or send us an enquiry!

Error executing template "Designs/Swift/Paragraph/Swift_ProductSpecification.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.Products.GroupRelation.GetGroupRelationsByChildId(String childId)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.GetOrderedInheritableParentIds(Group group, String defaultLanguageId)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.RecursivelySearchForFieldValues(Group group, String defaultLanguageId, List`1 categoryFields)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.RecursivelySearchForFieldValues(Group group, String defaultLanguageId, List`1 categoryFields)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.RecursivelySearchForFieldValues(Group group, String defaultLanguageId, List`1 categoryFields)
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.GetGroupFieldValuesByLanguage(Group group, List`1 categoryFields, String languageId, Boolean isInheritedValue, Boolean searchRecursively)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.SearchForGroupFieldValue(Group group, List`1 categoryFields, Boolean allowFallback)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.GetGroupCategoryFieldValues(IEnumerable`1 groups, List`1 fields, Boolean allowFallback)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.GetDefaultCategoryValuesFromGroups(IEnumerable`1 groupInfos, List`1 catFields)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.GetDefaultCategoryValueFromGroups(IEnumerable`1 groupInfos, Field catField)
   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__60()
   at System.Lazy`1.CreateValue()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Lazy`1.get_Value()
   at CompiledRazorTemplates.Dynamic.RazorEngine_83c3e920ca6c46f49d5bc5546126d159.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 System.Globalization; 4 @functions 5 { 6 public static class NumberHelper 7 { 8 /// <summary> 9 /// Converts a scientific notation string with a comma (e.g. "5,8E-05") to a decimal. 10 /// Returns 0 if the string is invalid or empty. 11 /// </summary> 12 public static decimal ToDecimal(string input) 13 { 14 if (string.IsNullOrWhiteSpace(input)) 15 { 16 return 0m; 17 } 18 19 // Tell the parser to look for a comma 20 var format = new NumberFormatInfo { NumberDecimalSeparator = "," }; 21 22 // TryParse safely attempts to convert without throwing exceptions on bad data 23 if (decimal.TryParse(input, NumberStyles.Float, format, out decimal result)) 24 { 25 return result; 26 } 27 28 return 0m; // Return a default value if parsing fails 29 } 30 } 31 } 32 @{ 33 ProductViewModel product = null; 34 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 35 { 36 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 37 } 38 else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode) 39 { 40 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 41 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 42 43 if (productList?.Products is object) 44 { 45 product = productList.Products[0]; 46 } 47 } 48 } 49 50 @if (product is object && Model?.Item != null) { 51 var displayGroupsRaw = Model.Item.GetRawValueString("DisplayGroups") ?? ""; 52 IEnumerable<string> selectedDisplayGroupIds = 53 displayGroupsRaw.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); 54 List<CategoryFieldViewModel> displayGroups = new List<CategoryFieldViewModel>(); 55 56 foreach (var selection in selectedDisplayGroupIds) 57 { 58 foreach (CategoryFieldViewModel group in product.FieldDisplayGroups?.Values ?? Enumerable.Empty<CategoryFieldViewModel>()) 59 { 60 if (selection == group.Id) 61 { 62 int fieldsWithNoValueOrZero = 0; 63 64 foreach (var field in group.Fields) 65 { 66 var value = field.Value?.Value?.ToString(); 67 68 if (string.IsNullOrWhiteSpace(value)) 69 { 70 fieldsWithNoValueOrZero++; 71 } 72 } 73 74 if (fieldsWithNoValueOrZero != group.Fields.Count) 75 { 76 displayGroups.Add(group); 77 } 78 } 79 } 80 } 81 82 bool showProductFields = Model.Item.GetBoolean("ProductFields"); 83 84 bool hideTitle = Model.Item.GetBoolean("HideTitle"); 85 86 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 87 88 string titleFontSize = Model.Item.GetRawValueString("TitleFontSize", "display-4"); 89 90 string contentPadding = Model.Item.GetRawValueString("ContentPadding", ""); 91 contentPadding = contentPadding == "none" ? string.Empty : contentPadding; 92 contentPadding = contentPadding == "small" ? " p-2 p-md-3" : contentPadding; 93 contentPadding = contentPadding == "large" ? " p-4 p-md-5" : contentPadding; 94 95 string layout = Model.Item.GetRawValueString("Layout", "list"); 96 string size = Model.Item.GetRawValueString("Size", "full"); 97 string gaps = size == "full" ? " gap-4" : " gap-2"; 98 99 100 if (Pageview.IsVisualEditorMode && displayGroups.Count() == 0) 101 { 102 product.ProductFields.Clear(); 103 product.ProductFields.Add(Translate("Width"), new FieldValueViewModel { Name = Translate("Width"), Value = "99cm" }); 104 product.ProductFields.Add(Translate("Height"), new FieldValueViewModel { Name = Translate("Height"), Value = "195cm" }); 105 showProductFields = true; 106 } 107 108 if (layout == "commas") 109 { 110 gaps = size == "full" ? " gap-4" : " gap-2"; 111 112 } 113 114 <div class="h-100@(gaps)@(theme)@(contentPadding) item_@Model.Item.SystemName.ToLower()"> 115 <div class="grid"> 116 @if ((product.ProductFields != null && Model.Item.GetBoolean("ProductFields")) || (product.ProductCategories != null && Model.Item.GetBoolean("CategoryFields")) || (displayGroups.Count != 0)) { 117 if (!hideTitle) 118 { 119 <h2 class="g-col-12 @titleFontSize">@Model.Item.GetString("Title")</h2> 120 } 121 } 122 123 @if (displayGroups.Count != 0) 124 { 125 if (layout != "accordion") 126 { 127 foreach (var group in displayGroups) 128 { 129 bool hideHeader = Model.Item.GetBoolean("HideGroupHeaders"); 130 131 if (!hideHeader) { 132 <h4 class="g-col-12 h4 mb-0">@group.Name</h4> 133 } 134 135 { @RenderFieldsFromList(group.Fields, layout) } 136 137 } 138 } 139 else 140 { 141 <div class="g-col-12"> 142 <div class="accordion accordion-flush w-100" id="Specifications_@Model.ID"> 143 @foreach (var group in displayGroups) 144 { 145 <div class="accordion-item"> 146 <h2 class="accordion-header" id="SpecificationHeading_@group.Id"> 147 <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#SpecificationItem_@group.Id" aria-expanded="false" aria-controls="SpecificationItem_@group.Id"> 148 @group.Name 149 </button> 150 </h2> 151 <div id="SpecificationItem_@group.Id" class="accordion-collapse collapse" aria-labelledby="SpecificationHeading_@group.Id" data-bs-parent="#Specifications_@Model.ID"> 152 <div class="accordion-body"> 153 @{ @RenderFieldsFromList(group.Fields, "list") } 154 </div> 155 </div> 156 </div> 157 } 158 </div> 159 </div> 160 } 161 } 162 163 @if (product.ProductFields != null && showProductFields) 164 { 165 if (product.ProductFields.Count > 0) 166 { 167 if (layout != "accordion") 168 { 169 {@RenderFieldsFromList(product.ProductFields, layout) } 170 } 171 else 172 { 173 <div class="g-col-12"> 174 <div class="accordion accordion-flush w-100" id="Specifications_@Model.ID"> 175 <div class="accordion-item"> 176 <h2 class="accordion-header" id="SpecificationHeading_@Model.ID"> 177 <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#SpecificationItem_@Model.ID" aria-expanded="false" aria-controls="SpecificationItem_@Model.ID"> 178 @Translate("Specifications") 179 </button> 180 </h2> 181 <div id="SpecificationItem_@Model.ID" class="accordion-collapse" aria-labelledby="SpecificationHeading_@Model.ID" data-bs-parent="#Specifications_@Model.ID"> 182 <div class="accordion-body"> 183 @{ @RenderFieldsFromList(product.ProductFields, "List") } 184 </div> 185 </div> 186 </div> 187 </div> 188 </div> 189 } 190 } 191 } 192 193 @if (product.ProductCategories != null && Model.Item.GetBoolean("CategoryFields")) 194 { 195 if (product.ProductCategories.Count > 0) 196 { 197 if (layout != "accordion") 198 { 199 foreach (var group in product.ProductCategories) 200 { 201 CategoryFieldViewModel category = group.Value; 202 bool hideHeader = Model.Item.GetBoolean("HideGroupHeaders"); 203 204 if (!hideHeader) { 205 <h4 class="g-col-12 h4 mb-0">@group.Value.Name</h4> 206 } 207 208 { @RenderFieldsFromList(category.Fields, layout) } 209 } 210 } 211 else 212 { 213 <div class="g-col-12"> 214 <div class="accordion accordion-flush w-100" id="Specifications_@Model.ID"> 215 @foreach (var group in product.ProductCategories) 216 { 217 CategoryFieldViewModel category = group.Value; 218 219 <div class="accordion-item"> 220 <h2 class="accordion-header" id="SpecificationHeading_@group.Value.Id"> 221 <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#SpecificationItem_@group.Value.Id" aria-expanded="false" aria-controls="SpecificationItem_@group.Value.Id"> 222 @group.Value.Name 223 </button> 224 </h2> 225 <div id="SpecificationItem_@group.Value.Id" class="accordion-collapse" aria-labelledby="SpecificationHeading_@group.Value.Id" data-bs-parent="#Specifications_@Model.ID"> 226 <div class="accordion-body"> 227 @{ @RenderFieldsFromList(category.Fields, "list") } 228 </div> 229 </div> 230 </div> 231 } 232 </div> 233 </div> 234 } 235 } 236 } 237 </div> 238 </div> 239 } 240 else if (Pageview.IsVisualEditorMode) 241 { 242 <div class="alert alert-warning m-0">@Translate("No products available")</div> 243 } 244 245 @helper RenderFieldsFromList(Dictionary<string, FieldValueViewModel> fields, string layout) 246 { 247 string size = Model.Item.GetRawValueString("Size", "full"); 248 string gaps = size != "full" ? " gap-1" : string.Empty; 249 bool hideFieldLabels = Model.Item.GetBoolean("HideFieldLabels"); 250 bool hideFieldsWithZeroValue = Model.Item.GetBoolean("HideFieldsWithZeroValue"); 251 252 if (layout == "columns") { 253 <div class="g-col-12"> 254 <div class="grid@(gaps)"> 255 @foreach (var field in fields) 256 { 257 {@RenderField(field.Value, layout)} 258 } 259 </div> 260 </div> 261 } 262 if (layout == "list") { 263 <div class="g-col-12"> 264 <dl class="grid@(gaps)"> 265 @foreach (var field in fields) 266 { 267 {@RenderField(field.Value, layout)} 268 } 269 </dl> 270 </div> 271 } 272 if (layout == "table") 273 { 274 string tableSize = size == "full" ? "" : " table-sm"; 275 <div class="g-col-12"> 276 <table class="table table-striped@(tableSize)"> 277 @foreach (var field in fields) 278 { 279 {@RenderField(field.Value, layout)} 280 } 281 </table> 282 </div> 283 } 284 if (layout == "bullets") 285 { 286 string listSize = size == "full" ? "" : "m-0 p-0 lh-1 fs-7 opacity-75"; 287 string listStyle = size == "full" ? "" : "style=\"list-style-position: inside\""; 288 <div class="g-col-12"> 289 <ul class="@listSize" @listStyle> 290 @foreach (var field in fields) 291 { 292 {@RenderField(field.Value, layout)} 293 } 294 </ul> 295 </div> 296 } 297 if (layout == "commas") 298 { 299 List<string> featuresList = new List<string>(); 300 301 foreach (var field in fields) 302 { 303 string firstListItemValue = string.Empty; //Hack to support field type providers with a single value 304 305 if (field.Value?.Value != null) 306 { 307 if (field.Value.Value.GetType() == typeof(System.Collections.Generic.List<FieldOptionValueViewModel>)) 308 { 309 System.Collections.Generic.List<FieldOptionValueViewModel> values = field.Value.Value as System.Collections.Generic.List<FieldOptionValueViewModel>; 310 311 //Hack to support field type providers with a single value 312 if (values.FirstOrDefault() != null) 313 { 314 firstListItemValue = values.FirstOrDefault().Value; 315 } 316 } 317 } 318 319 if (!hideFieldsWithZeroValue || (firstListItemValue != "0" && firstListItemValue != "0.0" && field.Value.Value.ToString() != "0" && field.Value.Value.ToString() != "0.0")) 320 { 321 if (field.Value.Value is object && !string.IsNullOrEmpty(field.Value.Value.ToString())) 322 { 323 if (field.Value.Value.GetType() == typeof(System.Collections.Generic.List<FieldOptionValueViewModel>)) 324 { 325 List<string> options = new List<string>(); 326 foreach (FieldOptionValueViewModel option in field.Value.Value as System.Collections.Generic.List<FieldOptionValueViewModel>) 327 { 328 if (!string.IsNullOrWhiteSpace(option.Value)) 329 { 330 if (option.Value.ToString().Contains("#") && (Translate(field.Value.Name) == Translate("Color") || Translate(field.Value.Name) == Translate("Colour"))) 331 { 332 string colorSpan = "<span class=\"colorbox-sm\" style=\"background-color: " + option.Value + "\"></span>"; 333 options.Add(colorSpan); 334 } 335 else if (!string.IsNullOrEmpty(option.Value)) 336 { 337 options.Add(option.Name); 338 } 339 } 340 } 341 string optionsString = (string.Join(", ", options.Select(x => x.ToString()).ToArray())); 342 if ((Translate(field.Value.Name) == Translate("Color") || Translate(field.Value.Name) == Translate("Colour"))) 343 { 344 optionsString = (string.Join(" ", options.Select(x => x.ToString()).ToArray())); 345 } 346 347 if (!string.IsNullOrEmpty(optionsString)) 348 { 349 if (!hideFieldLabels) 350 { 351 featuresList.Add(field.Value.Name + ": " + optionsString); 352 } 353 else 354 { 355 featuresList.Add(optionsString); 356 } 357 } 358 } 359 else 360 { 361 if (!string.IsNullOrWhiteSpace(field.Value.Value.ToString())) 362 { 363 if (field.Value.Value.ToString().Contains("#") && (Translate(field.Value.Name) == Translate("Color") || Translate(field.Value.Name) == Translate("Colour"))) 364 { 365 string colorSpan = "<span class=\"colorbox-sm\" style=\"background-color: " + field.Value.Value + "\"></span>"; 366 367 if (!hideFieldLabels) 368 { 369 featuresList.Add(field.Value.Name + ": " + colorSpan); 370 } 371 else 372 { 373 featuresList.Add(colorSpan); 374 } 375 } 376 else 377 { 378 if (!hideFieldLabels) 379 { 380 featuresList.Add(field.Value.Name + ": " + field.Value.Value.ToString()); 381 } 382 else 383 { 384 featuresList.Add(field.Value.Value.ToString()); 385 } 386 } 387 } 388 } 389 } 390 } 391 } 392 393 string featuresString = (string.Join(", ", featuresList.Select(x => x.ToString()).ToArray())); 394 395 <div class="g-col-12 opacity-75 fs-7">@featuresString</div> 396 } 397 } 398 399 @helper RenderField(FieldValueViewModel field, string layout) 400 { 401 string size = Model.Item.GetRawValueString("Size", "full"); 402 string fieldValue = field?.Value != null ? field.Value.ToString() : ""; 403 bool hideFieldLabels = Model.Item.GetBoolean("HideFieldLabels"); 404 bool noValues = false; 405 string firstListItemValue = string.Empty; //Hack to support field type providers with a single value 406 bool hideFieldsWithZeroValue = Model.Item.GetBoolean("HideFieldsWithZeroValue"); 407 408 if (!string.IsNullOrEmpty(fieldValue)) 409 { 410 if (field.Value.GetType() == typeof(System.Collections.Generic.List<FieldOptionValueViewModel>)) 411 { 412 System.Collections.Generic.List<FieldOptionValueViewModel> values = field.Value as System.Collections.Generic.List<FieldOptionValueViewModel>; 413 noValues = values.Count > 0 ? false : true; 414 415 //Hack to support field type providers with a single value 416 if (values.FirstOrDefault() != null) 417 { 418 firstListItemValue = values.FirstOrDefault().Value; 419 } 420 } 421 } 422 423 if (!string.IsNullOrEmpty(fieldValue) && noValues == false) 424 { 425 if (!hideFieldsWithZeroValue || (firstListItemValue != "0" && firstListItemValue != "0.0" && field.Value.ToString() != "0" && field.Value.ToString() != "0.0")) 426 { 427 if (layout == "columns") 428 { 429 430 <div class="grid g-col-6 g-col-lg-4 gap-1"> 431 @if (!hideFieldLabels) 432 { 433 <dt class="g-col-12 g-col-lg-4">@field.Name</dt> 434 } 435 <dd class="g-col-12 g-col-lg-8 mb-0 text-break"> 436 437 @{ @RenderFieldValue(field)} 438 </dd> 439 </div> 440 } 441 if (layout == "list") 442 { 443 if (!hideFieldLabels) 444 { 445 <dt class="g-col-4">@field.Name</dt> 446 } 447 <dd class="g-col-8 mb-0 text-break"> 448 @{ @RenderFieldValue(field)} 449 </dd> 450 } 451 if (layout == "table") 452 { 453 <tr> 454 @if (!hideFieldLabels) 455 { 456 <th class="w-25 w-lg-50" scope="row">@field.Name</th> 457 } 458 <td class="text-break"> 459 @{ @RenderFieldValue(field) } 460 </td> 461 </tr> 462 } 463 if (layout == "bullets") 464 { 465 <li> 466 @if (!hideFieldLabels) 467 { 468 <strong>@field.Name</strong> 469 } 470 <span> 471 @{ @RenderFieldValue(field) } 472 </span> 473 </li> 474 } 475 } 476 } 477 } 478 479 @helper RenderFieldValue(FieldValueViewModel field) 480 { 481 string fieldValue = field?.Value != null ? field.Value.ToString() : ""; 482 if (field.SystemName == "ProductWeight") 483 { 484 485 decimal calculatedValue = NumberHelper.ToDecimal(fieldValue); 486 decimal baseValue = NumberHelper.ToDecimal("0,00001"); 487 488 489 fieldValue = calculatedValue.ToString("0.######", System.Globalization.CultureInfo.InvariantCulture).Replace(".", ","); 490 491 } 492 bool isLink = field?.Type == "Link"; 493 bool isColor = false; 494 bool isBrandName = field?.SystemName == "Brand_name"; 495 496 fieldValue = fieldValue == "False" ? Translate("No") : fieldValue; 497 fieldValue = fieldValue == "True" ? Translate("Yes") : fieldValue; 498 499 500 if (field.Value.GetType() == typeof(System.Collections.Generic.List<Dynamicweb.Ecommerce.ProductCatalog.FieldOptionValueViewModel>)) 501 { 502 int valueCount = 0; 503 System.Collections.Generic.List<FieldOptionValueViewModel> values = field.Value as System.Collections.Generic.List<FieldOptionValueViewModel>; 504 int totalValues = values.Count; 505 506 foreach (FieldOptionValueViewModel option in values) 507 { 508 if (!string.IsNullOrEmpty(option.Value)) 509 { 510 if (option.Value.Substring(0, 1) == "#") 511 { 512 isColor = true; 513 } 514 } 515 516 if (!isColor) 517 { 518 @option.Name 519 } 520 else 521 { 522 <span class="colorbox-sm" style="background-color: @option.Value" title="@option.Name"></span> 523 } 524 525 if (valueCount != totalValues && valueCount < (totalValues - 1)) 526 { 527 if (isColor) 528 { 529 <text> </text> 530 } 531 else 532 { 533 <text>, </text> 534 } 535 } 536 valueCount++; 537 } 538 } 539 else 540 { 541 if (fieldValue.Substring(0, 1) == "#") 542 { 543 isColor = true; 544 } 545 546 if (!isColor) 547 { 548 if (isLink) 549 { 550 string linktTitle = !fieldValue.Contains("aspx") ? fieldValue : Translate("Go to link"); 551 string target = Pageview.AreaSettings.GetBoolean("OpenLinksInNewTab") && fieldValue.Contains("http") ? "target=\"_blank\"" : string.Empty; 552 string rel = Pageview.AreaSettings.GetBoolean("OpenLinksInNewTab") && fieldValue.Contains("http") ? "rel=\"noopener\"" : string.Empty; 553 554 <a href="@field.Value" title="@field.Name" @target @rel>@linktTitle</a> 555 } 556 else if (isBrandName) 557 { 558 <span itemprop="brand" itemtype="https://schema.org/Brand" itemscope> 559 <span itemprop="name">@fieldValue</span> 560 </span> 561 } 562 else 563 { 564 @fieldValue 565 } 566 567 } 568 else 569 { 570 <span class="colorbox-sm" style="background-color: @fieldValue" title="@fieldValue"></span> 571 } 572 } 573 } 574
Error executing template "Designs/Swift/Paragraph/Swift_ProductSpecification.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.Products.GroupRelation.GetGroupRelationsByChildId(String childId)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.GetOrderedInheritableParentIds(Group group, String defaultLanguageId)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.RecursivelySearchForFieldValues(Group group, String defaultLanguageId, List`1 categoryFields)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.RecursivelySearchForFieldValues(Group group, String defaultLanguageId, List`1 categoryFields)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.RecursivelySearchForFieldValues(Group group, String defaultLanguageId, List`1 categoryFields)
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.GetGroupFieldValuesByLanguage(Group group, List`1 categoryFields, String languageId, Boolean isInheritedValue, Boolean searchRecursively)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.SearchForGroupFieldValue(Group group, List`1 categoryFields, Boolean allowFallback)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.GetGroupCategoryFieldValues(IEnumerable`1 groups, List`1 fields, Boolean allowFallback)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.GetDefaultCategoryValuesFromGroups(IEnumerable`1 groupInfos, List`1 catFields)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.GetDefaultCategoryValueFromGroups(IEnumerable`1 groupInfos, Field catField)
   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__60()
   at System.Lazy`1.CreateValue()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Lazy`1.get_Value()
   at CompiledRazorTemplates.Dynamic.RazorEngine_83c3e920ca6c46f49d5bc5546126d159.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 System.Globalization; 4 @functions 5 { 6 public static class NumberHelper 7 { 8 /// <summary> 9 /// Converts a scientific notation string with a comma (e.g. "5,8E-05") to a decimal. 10 /// Returns 0 if the string is invalid or empty. 11 /// </summary> 12 public static decimal ToDecimal(string input) 13 { 14 if (string.IsNullOrWhiteSpace(input)) 15 { 16 return 0m; 17 } 18 19 // Tell the parser to look for a comma 20 var format = new NumberFormatInfo { NumberDecimalSeparator = "," }; 21 22 // TryParse safely attempts to convert without throwing exceptions on bad data 23 if (decimal.TryParse(input, NumberStyles.Float, format, out decimal result)) 24 { 25 return result; 26 } 27 28 return 0m; // Return a default value if parsing fails 29 } 30 } 31 } 32 @{ 33 ProductViewModel product = null; 34 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 35 { 36 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 37 } 38 else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode) 39 { 40 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 41 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 42 43 if (productList?.Products is object) 44 { 45 product = productList.Products[0]; 46 } 47 } 48 } 49 50 @if (product is object && Model?.Item != null) { 51 var displayGroupsRaw = Model.Item.GetRawValueString("DisplayGroups") ?? ""; 52 IEnumerable<string> selectedDisplayGroupIds = 53 displayGroupsRaw.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); 54 List<CategoryFieldViewModel> displayGroups = new List<CategoryFieldViewModel>(); 55 56 foreach (var selection in selectedDisplayGroupIds) 57 { 58 foreach (CategoryFieldViewModel group in product.FieldDisplayGroups?.Values ?? Enumerable.Empty<CategoryFieldViewModel>()) 59 { 60 if (selection == group.Id) 61 { 62 int fieldsWithNoValueOrZero = 0; 63 64 foreach (var field in group.Fields) 65 { 66 var value = field.Value?.Value?.ToString(); 67 68 if (string.IsNullOrWhiteSpace(value)) 69 { 70 fieldsWithNoValueOrZero++; 71 } 72 } 73 74 if (fieldsWithNoValueOrZero != group.Fields.Count) 75 { 76 displayGroups.Add(group); 77 } 78 } 79 } 80 } 81 82 bool showProductFields = Model.Item.GetBoolean("ProductFields"); 83 84 bool hideTitle = Model.Item.GetBoolean("HideTitle"); 85 86 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 87 88 string titleFontSize = Model.Item.GetRawValueString("TitleFontSize", "display-4"); 89 90 string contentPadding = Model.Item.GetRawValueString("ContentPadding", ""); 91 contentPadding = contentPadding == "none" ? string.Empty : contentPadding; 92 contentPadding = contentPadding == "small" ? " p-2 p-md-3" : contentPadding; 93 contentPadding = contentPadding == "large" ? " p-4 p-md-5" : contentPadding; 94 95 string layout = Model.Item.GetRawValueString("Layout", "list"); 96 string size = Model.Item.GetRawValueString("Size", "full"); 97 string gaps = size == "full" ? " gap-4" : " gap-2"; 98 99 100 if (Pageview.IsVisualEditorMode && displayGroups.Count() == 0) 101 { 102 product.ProductFields.Clear(); 103 product.ProductFields.Add(Translate("Width"), new FieldValueViewModel { Name = Translate("Width"), Value = "99cm" }); 104 product.ProductFields.Add(Translate("Height"), new FieldValueViewModel { Name = Translate("Height"), Value = "195cm" }); 105 showProductFields = true; 106 } 107 108 if (layout == "commas") 109 { 110 gaps = size == "full" ? " gap-4" : " gap-2"; 111 112 } 113 114 <div class="h-100@(gaps)@(theme)@(contentPadding) item_@Model.Item.SystemName.ToLower()"> 115 <div class="grid"> 116 @if ((product.ProductFields != null && Model.Item.GetBoolean("ProductFields")) || (product.ProductCategories != null && Model.Item.GetBoolean("CategoryFields")) || (displayGroups.Count != 0)) { 117 if (!hideTitle) 118 { 119 <h2 class="g-col-12 @titleFontSize">@Model.Item.GetString("Title")</h2> 120 } 121 } 122 123 @if (displayGroups.Count != 0) 124 { 125 if (layout != "accordion") 126 { 127 foreach (var group in displayGroups) 128 { 129 bool hideHeader = Model.Item.GetBoolean("HideGroupHeaders"); 130 131 if (!hideHeader) { 132 <h4 class="g-col-12 h4 mb-0">@group.Name</h4> 133 } 134 135 { @RenderFieldsFromList(group.Fields, layout) } 136 137 } 138 } 139 else 140 { 141 <div class="g-col-12"> 142 <div class="accordion accordion-flush w-100" id="Specifications_@Model.ID"> 143 @foreach (var group in displayGroups) 144 { 145 <div class="accordion-item"> 146 <h2 class="accordion-header" id="SpecificationHeading_@group.Id"> 147 <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#SpecificationItem_@group.Id" aria-expanded="false" aria-controls="SpecificationItem_@group.Id"> 148 @group.Name 149 </button> 150 </h2> 151 <div id="SpecificationItem_@group.Id" class="accordion-collapse collapse" aria-labelledby="SpecificationHeading_@group.Id" data-bs-parent="#Specifications_@Model.ID"> 152 <div class="accordion-body"> 153 @{ @RenderFieldsFromList(group.Fields, "list") } 154 </div> 155 </div> 156 </div> 157 } 158 </div> 159 </div> 160 } 161 } 162 163 @if (product.ProductFields != null && showProductFields) 164 { 165 if (product.ProductFields.Count > 0) 166 { 167 if (layout != "accordion") 168 { 169 {@RenderFieldsFromList(product.ProductFields, layout) } 170 } 171 else 172 { 173 <div class="g-col-12"> 174 <div class="accordion accordion-flush w-100" id="Specifications_@Model.ID"> 175 <div class="accordion-item"> 176 <h2 class="accordion-header" id="SpecificationHeading_@Model.ID"> 177 <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#SpecificationItem_@Model.ID" aria-expanded="false" aria-controls="SpecificationItem_@Model.ID"> 178 @Translate("Specifications") 179 </button> 180 </h2> 181 <div id="SpecificationItem_@Model.ID" class="accordion-collapse" aria-labelledby="SpecificationHeading_@Model.ID" data-bs-parent="#Specifications_@Model.ID"> 182 <div class="accordion-body"> 183 @{ @RenderFieldsFromList(product.ProductFields, "List") } 184 </div> 185 </div> 186 </div> 187 </div> 188 </div> 189 } 190 } 191 } 192 193 @if (product.ProductCategories != null && Model.Item.GetBoolean("CategoryFields")) 194 { 195 if (product.ProductCategories.Count > 0) 196 { 197 if (layout != "accordion") 198 { 199 foreach (var group in product.ProductCategories) 200 { 201 CategoryFieldViewModel category = group.Value; 202 bool hideHeader = Model.Item.GetBoolean("HideGroupHeaders"); 203 204 if (!hideHeader) { 205 <h4 class="g-col-12 h4 mb-0">@group.Value.Name</h4> 206 } 207 208 { @RenderFieldsFromList(category.Fields, layout) } 209 } 210 } 211 else 212 { 213 <div class="g-col-12"> 214 <div class="accordion accordion-flush w-100" id="Specifications_@Model.ID"> 215 @foreach (var group in product.ProductCategories) 216 { 217 CategoryFieldViewModel category = group.Value; 218 219 <div class="accordion-item"> 220 <h2 class="accordion-header" id="SpecificationHeading_@group.Value.Id"> 221 <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#SpecificationItem_@group.Value.Id" aria-expanded="false" aria-controls="SpecificationItem_@group.Value.Id"> 222 @group.Value.Name 223 </button> 224 </h2> 225 <div id="SpecificationItem_@group.Value.Id" class="accordion-collapse" aria-labelledby="SpecificationHeading_@group.Value.Id" data-bs-parent="#Specifications_@Model.ID"> 226 <div class="accordion-body"> 227 @{ @RenderFieldsFromList(category.Fields, "list") } 228 </div> 229 </div> 230 </div> 231 } 232 </div> 233 </div> 234 } 235 } 236 } 237 </div> 238 </div> 239 } 240 else if (Pageview.IsVisualEditorMode) 241 { 242 <div class="alert alert-warning m-0">@Translate("No products available")</div> 243 } 244 245 @helper RenderFieldsFromList(Dictionary<string, FieldValueViewModel> fields, string layout) 246 { 247 string size = Model.Item.GetRawValueString("Size", "full"); 248 string gaps = size != "full" ? " gap-1" : string.Empty; 249 bool hideFieldLabels = Model.Item.GetBoolean("HideFieldLabels"); 250 bool hideFieldsWithZeroValue = Model.Item.GetBoolean("HideFieldsWithZeroValue"); 251 252 if (layout == "columns") { 253 <div class="g-col-12"> 254 <div class="grid@(gaps)"> 255 @foreach (var field in fields) 256 { 257 {@RenderField(field.Value, layout)} 258 } 259 </div> 260 </div> 261 } 262 if (layout == "list") { 263 <div class="g-col-12"> 264 <dl class="grid@(gaps)"> 265 @foreach (var field in fields) 266 { 267 {@RenderField(field.Value, layout)} 268 } 269 </dl> 270 </div> 271 } 272 if (layout == "table") 273 { 274 string tableSize = size == "full" ? "" : " table-sm"; 275 <div class="g-col-12"> 276 <table class="table table-striped@(tableSize)"> 277 @foreach (var field in fields) 278 { 279 {@RenderField(field.Value, layout)} 280 } 281 </table> 282 </div> 283 } 284 if (layout == "bullets") 285 { 286 string listSize = size == "full" ? "" : "m-0 p-0 lh-1 fs-7 opacity-75"; 287 string listStyle = size == "full" ? "" : "style=\"list-style-position: inside\""; 288 <div class="g-col-12"> 289 <ul class="@listSize" @listStyle> 290 @foreach (var field in fields) 291 { 292 {@RenderField(field.Value, layout)} 293 } 294 </ul> 295 </div> 296 } 297 if (layout == "commas") 298 { 299 List<string> featuresList = new List<string>(); 300 301 foreach (var field in fields) 302 { 303 string firstListItemValue = string.Empty; //Hack to support field type providers with a single value 304 305 if (field.Value?.Value != null) 306 { 307 if (field.Value.Value.GetType() == typeof(System.Collections.Generic.List<FieldOptionValueViewModel>)) 308 { 309 System.Collections.Generic.List<FieldOptionValueViewModel> values = field.Value.Value as System.Collections.Generic.List<FieldOptionValueViewModel>; 310 311 //Hack to support field type providers with a single value 312 if (values.FirstOrDefault() != null) 313 { 314 firstListItemValue = values.FirstOrDefault().Value; 315 } 316 } 317 } 318 319 if (!hideFieldsWithZeroValue || (firstListItemValue != "0" && firstListItemValue != "0.0" && field.Value.Value.ToString() != "0" && field.Value.Value.ToString() != "0.0")) 320 { 321 if (field.Value.Value is object && !string.IsNullOrEmpty(field.Value.Value.ToString())) 322 { 323 if (field.Value.Value.GetType() == typeof(System.Collections.Generic.List<FieldOptionValueViewModel>)) 324 { 325 List<string> options = new List<string>(); 326 foreach (FieldOptionValueViewModel option in field.Value.Value as System.Collections.Generic.List<FieldOptionValueViewModel>) 327 { 328 if (!string.IsNullOrWhiteSpace(option.Value)) 329 { 330 if (option.Value.ToString().Contains("#") && (Translate(field.Value.Name) == Translate("Color") || Translate(field.Value.Name) == Translate("Colour"))) 331 { 332 string colorSpan = "<span class=\"colorbox-sm\" style=\"background-color: " + option.Value + "\"></span>"; 333 options.Add(colorSpan); 334 } 335 else if (!string.IsNullOrEmpty(option.Value)) 336 { 337 options.Add(option.Name); 338 } 339 } 340 } 341 string optionsString = (string.Join(", ", options.Select(x => x.ToString()).ToArray())); 342 if ((Translate(field.Value.Name) == Translate("Color") || Translate(field.Value.Name) == Translate("Colour"))) 343 { 344 optionsString = (string.Join(" ", options.Select(x => x.ToString()).ToArray())); 345 } 346 347 if (!string.IsNullOrEmpty(optionsString)) 348 { 349 if (!hideFieldLabels) 350 { 351 featuresList.Add(field.Value.Name + ": " + optionsString); 352 } 353 else 354 { 355 featuresList.Add(optionsString); 356 } 357 } 358 } 359 else 360 { 361 if (!string.IsNullOrWhiteSpace(field.Value.Value.ToString())) 362 { 363 if (field.Value.Value.ToString().Contains("#") && (Translate(field.Value.Name) == Translate("Color") || Translate(field.Value.Name) == Translate("Colour"))) 364 { 365 string colorSpan = "<span class=\"colorbox-sm\" style=\"background-color: " + field.Value.Value + "\"></span>"; 366 367 if (!hideFieldLabels) 368 { 369 featuresList.Add(field.Value.Name + ": " + colorSpan); 370 } 371 else 372 { 373 featuresList.Add(colorSpan); 374 } 375 } 376 else 377 { 378 if (!hideFieldLabels) 379 { 380 featuresList.Add(field.Value.Name + ": " + field.Value.Value.ToString()); 381 } 382 else 383 { 384 featuresList.Add(field.Value.Value.ToString()); 385 } 386 } 387 } 388 } 389 } 390 } 391 } 392 393 string featuresString = (string.Join(", ", featuresList.Select(x => x.ToString()).ToArray())); 394 395 <div class="g-col-12 opacity-75 fs-7">@featuresString</div> 396 } 397 } 398 399 @helper RenderField(FieldValueViewModel field, string layout) 400 { 401 string size = Model.Item.GetRawValueString("Size", "full"); 402 string fieldValue = field?.Value != null ? field.Value.ToString() : ""; 403 bool hideFieldLabels = Model.Item.GetBoolean("HideFieldLabels"); 404 bool noValues = false; 405 string firstListItemValue = string.Empty; //Hack to support field type providers with a single value 406 bool hideFieldsWithZeroValue = Model.Item.GetBoolean("HideFieldsWithZeroValue"); 407 408 if (!string.IsNullOrEmpty(fieldValue)) 409 { 410 if (field.Value.GetType() == typeof(System.Collections.Generic.List<FieldOptionValueViewModel>)) 411 { 412 System.Collections.Generic.List<FieldOptionValueViewModel> values = field.Value as System.Collections.Generic.List<FieldOptionValueViewModel>; 413 noValues = values.Count > 0 ? false : true; 414 415 //Hack to support field type providers with a single value 416 if (values.FirstOrDefault() != null) 417 { 418 firstListItemValue = values.FirstOrDefault().Value; 419 } 420 } 421 } 422 423 if (!string.IsNullOrEmpty(fieldValue) && noValues == false) 424 { 425 if (!hideFieldsWithZeroValue || (firstListItemValue != "0" && firstListItemValue != "0.0" && field.Value.ToString() != "0" && field.Value.ToString() != "0.0")) 426 { 427 if (layout == "columns") 428 { 429 430 <div class="grid g-col-6 g-col-lg-4 gap-1"> 431 @if (!hideFieldLabels) 432 { 433 <dt class="g-col-12 g-col-lg-4">@field.Name</dt> 434 } 435 <dd class="g-col-12 g-col-lg-8 mb-0 text-break"> 436 437 @{ @RenderFieldValue(field)} 438 </dd> 439 </div> 440 } 441 if (layout == "list") 442 { 443 if (!hideFieldLabels) 444 { 445 <dt class="g-col-4">@field.Name</dt> 446 } 447 <dd class="g-col-8 mb-0 text-break"> 448 @{ @RenderFieldValue(field)} 449 </dd> 450 } 451 if (layout == "table") 452 { 453 <tr> 454 @if (!hideFieldLabels) 455 { 456 <th class="w-25 w-lg-50" scope="row">@field.Name</th> 457 } 458 <td class="text-break"> 459 @{ @RenderFieldValue(field) } 460 </td> 461 </tr> 462 } 463 if (layout == "bullets") 464 { 465 <li> 466 @if (!hideFieldLabels) 467 { 468 <strong>@field.Name</strong> 469 } 470 <span> 471 @{ @RenderFieldValue(field) } 472 </span> 473 </li> 474 } 475 } 476 } 477 } 478 479 @helper RenderFieldValue(FieldValueViewModel field) 480 { 481 string fieldValue = field?.Value != null ? field.Value.ToString() : ""; 482 if (field.SystemName == "ProductWeight") 483 { 484 485 decimal calculatedValue = NumberHelper.ToDecimal(fieldValue); 486 decimal baseValue = NumberHelper.ToDecimal("0,00001"); 487 488 489 fieldValue = calculatedValue.ToString("0.######", System.Globalization.CultureInfo.InvariantCulture).Replace(".", ","); 490 491 } 492 bool isLink = field?.Type == "Link"; 493 bool isColor = false; 494 bool isBrandName = field?.SystemName == "Brand_name"; 495 496 fieldValue = fieldValue == "False" ? Translate("No") : fieldValue; 497 fieldValue = fieldValue == "True" ? Translate("Yes") : fieldValue; 498 499 500 if (field.Value.GetType() == typeof(System.Collections.Generic.List<Dynamicweb.Ecommerce.ProductCatalog.FieldOptionValueViewModel>)) 501 { 502 int valueCount = 0; 503 System.Collections.Generic.List<FieldOptionValueViewModel> values = field.Value as System.Collections.Generic.List<FieldOptionValueViewModel>; 504 int totalValues = values.Count; 505 506 foreach (FieldOptionValueViewModel option in values) 507 { 508 if (!string.IsNullOrEmpty(option.Value)) 509 { 510 if (option.Value.Substring(0, 1) == "#") 511 { 512 isColor = true; 513 } 514 } 515 516 if (!isColor) 517 { 518 @option.Name 519 } 520 else 521 { 522 <span class="colorbox-sm" style="background-color: @option.Value" title="@option.Name"></span> 523 } 524 525 if (valueCount != totalValues && valueCount < (totalValues - 1)) 526 { 527 if (isColor) 528 { 529 <text> </text> 530 } 531 else 532 { 533 <text>, </text> 534 } 535 } 536 valueCount++; 537 } 538 } 539 else 540 { 541 if (fieldValue.Substring(0, 1) == "#") 542 { 543 isColor = true; 544 } 545 546 if (!isColor) 547 { 548 if (isLink) 549 { 550 string linktTitle = !fieldValue.Contains("aspx") ? fieldValue : Translate("Go to link"); 551 string target = Pageview.AreaSettings.GetBoolean("OpenLinksInNewTab") && fieldValue.Contains("http") ? "target=\"_blank\"" : string.Empty; 552 string rel = Pageview.AreaSettings.GetBoolean("OpenLinksInNewTab") && fieldValue.Contains("http") ? "rel=\"noopener\"" : string.Empty; 553 554 <a href="@field.Value" title="@field.Name" @target @rel>@linktTitle</a> 555 } 556 else if (isBrandName) 557 { 558 <span itemprop="brand" itemtype="https://schema.org/Brand" itemscope> 559 <span itemprop="name">@fieldValue</span> 560 </span> 561 } 562 else 563 { 564 @fieldValue 565 } 566 567 } 568 else 569 { 570 <span class="colorbox-sm" style="background-color: @fieldValue" title="@fieldValue"></span> 571 } 572 } 573 } 574

Datasheets & Documents

New column

  Name Download File type
Gates V-belt Hi-power Dubl-V AA60
hi-power-kileremme.png 1024 KB
.png

Request additional documents and drawings

 

Product drawings, documents and brochures of any kind may contain errors for which Brd. Klee is not liable for. 

 
Error executing template "Designs/Swift/Paragraph/Swift_ProductSpecification.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.Products.GroupRelation.GetGroupRelationsByChildId(String childId)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.GetOrderedInheritableParentIds(Group group, String defaultLanguageId)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.RecursivelySearchForFieldValues(Group group, String defaultLanguageId, List`1 categoryFields)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.RecursivelySearchForFieldValues(Group group, String defaultLanguageId, List`1 categoryFields)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.RecursivelySearchForFieldValues(Group group, String defaultLanguageId, List`1 categoryFields)
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.GetGroupFieldValuesByLanguage(Group group, List`1 categoryFields, String languageId, Boolean isInheritedValue, Boolean searchRecursively)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.SearchForGroupFieldValue(Group group, List`1 categoryFields, Boolean allowFallback)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.GetGroupCategoryFieldValues(IEnumerable`1 groups, List`1 fields, Boolean allowFallback)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.GetDefaultCategoryValuesFromGroups(IEnumerable`1 groupInfos, List`1 catFields)
   at Dynamicweb.Ecommerce.Products.Categories.ProductCategoryFieldGroupValueService.GetDefaultCategoryValueFromGroups(IEnumerable`1 groupInfos, Field catField)
   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__60()
   at System.Lazy`1.CreateValue()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Lazy`1.get_Value()
   at CompiledRazorTemplates.Dynamic.RazorEngine_83c3e920ca6c46f49d5bc5546126d159.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 System.Globalization; 4 @functions 5 { 6 public static class NumberHelper 7 { 8 /// <summary> 9 /// Converts a scientific notation string with a comma (e.g. "5,8E-05") to a decimal. 10 /// Returns 0 if the string is invalid or empty. 11 /// </summary> 12 public static decimal ToDecimal(string input) 13 { 14 if (string.IsNullOrWhiteSpace(input)) 15 { 16 return 0m; 17 } 18 19 // Tell the parser to look for a comma 20 var format = new NumberFormatInfo { NumberDecimalSeparator = "," }; 21 22 // TryParse safely attempts to convert without throwing exceptions on bad data 23 if (decimal.TryParse(input, NumberStyles.Float, format, out decimal result)) 24 { 25 return result; 26 } 27 28 return 0m; // Return a default value if parsing fails 29 } 30 } 31 } 32 @{ 33 ProductViewModel product = null; 34 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 35 { 36 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 37 } 38 else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode) 39 { 40 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 41 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 42 43 if (productList?.Products is object) 44 { 45 product = productList.Products[0]; 46 } 47 } 48 } 49 50 @if (product is object && Model?.Item != null) { 51 var displayGroupsRaw = Model.Item.GetRawValueString("DisplayGroups") ?? ""; 52 IEnumerable<string> selectedDisplayGroupIds = 53 displayGroupsRaw.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); 54 List<CategoryFieldViewModel> displayGroups = new List<CategoryFieldViewModel>(); 55 56 foreach (var selection in selectedDisplayGroupIds) 57 { 58 foreach (CategoryFieldViewModel group in product.FieldDisplayGroups?.Values ?? Enumerable.Empty<CategoryFieldViewModel>()) 59 { 60 if (selection == group.Id) 61 { 62 int fieldsWithNoValueOrZero = 0; 63 64 foreach (var field in group.Fields) 65 { 66 var value = field.Value?.Value?.ToString(); 67 68 if (string.IsNullOrWhiteSpace(value)) 69 { 70 fieldsWithNoValueOrZero++; 71 } 72 } 73 74 if (fieldsWithNoValueOrZero != group.Fields.Count) 75 { 76 displayGroups.Add(group); 77 } 78 } 79 } 80 } 81 82 bool showProductFields = Model.Item.GetBoolean("ProductFields"); 83 84 bool hideTitle = Model.Item.GetBoolean("HideTitle"); 85 86 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 87 88 string titleFontSize = Model.Item.GetRawValueString("TitleFontSize", "display-4"); 89 90 string contentPadding = Model.Item.GetRawValueString("ContentPadding", ""); 91 contentPadding = contentPadding == "none" ? string.Empty : contentPadding; 92 contentPadding = contentPadding == "small" ? " p-2 p-md-3" : contentPadding; 93 contentPadding = contentPadding == "large" ? " p-4 p-md-5" : contentPadding; 94 95 string layout = Model.Item.GetRawValueString("Layout", "list"); 96 string size = Model.Item.GetRawValueString("Size", "full"); 97 string gaps = size == "full" ? " gap-4" : " gap-2"; 98 99 100 if (Pageview.IsVisualEditorMode && displayGroups.Count() == 0) 101 { 102 product.ProductFields.Clear(); 103 product.ProductFields.Add(Translate("Width"), new FieldValueViewModel { Name = Translate("Width"), Value = "99cm" }); 104 product.ProductFields.Add(Translate("Height"), new FieldValueViewModel { Name = Translate("Height"), Value = "195cm" }); 105 showProductFields = true; 106 } 107 108 if (layout == "commas") 109 { 110 gaps = size == "full" ? " gap-4" : " gap-2"; 111 112 } 113 114 <div class="h-100@(gaps)@(theme)@(contentPadding) item_@Model.Item.SystemName.ToLower()"> 115 <div class="grid"> 116 @if ((product.ProductFields != null && Model.Item.GetBoolean("ProductFields")) || (product.ProductCategories != null && Model.Item.GetBoolean("CategoryFields")) || (displayGroups.Count != 0)) { 117 if (!hideTitle) 118 { 119 <h2 class="g-col-12 @titleFontSize">@Model.Item.GetString("Title")</h2> 120 } 121 } 122 123 @if (displayGroups.Count != 0) 124 { 125 if (layout != "accordion") 126 { 127 foreach (var group in displayGroups) 128 { 129 bool hideHeader = Model.Item.GetBoolean("HideGroupHeaders"); 130 131 if (!hideHeader) { 132 <h4 class="g-col-12 h4 mb-0">@group.Name</h4> 133 } 134 135 { @RenderFieldsFromList(group.Fields, layout) } 136 137 } 138 } 139 else 140 { 141 <div class="g-col-12"> 142 <div class="accordion accordion-flush w-100" id="Specifications_@Model.ID"> 143 @foreach (var group in displayGroups) 144 { 145 <div class="accordion-item"> 146 <h2 class="accordion-header" id="SpecificationHeading_@group.Id"> 147 <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#SpecificationItem_@group.Id" aria-expanded="false" aria-controls="SpecificationItem_@group.Id"> 148 @group.Name 149 </button> 150 </h2> 151 <div id="SpecificationItem_@group.Id" class="accordion-collapse collapse" aria-labelledby="SpecificationHeading_@group.Id" data-bs-parent="#Specifications_@Model.ID"> 152 <div class="accordion-body"> 153 @{ @RenderFieldsFromList(group.Fields, "list") } 154 </div> 155 </div> 156 </div> 157 } 158 </div> 159 </div> 160 } 161 } 162 163 @if (product.ProductFields != null && showProductFields) 164 { 165 if (product.ProductFields.Count > 0) 166 { 167 if (layout != "accordion") 168 { 169 {@RenderFieldsFromList(product.ProductFields, layout) } 170 } 171 else 172 { 173 <div class="g-col-12"> 174 <div class="accordion accordion-flush w-100" id="Specifications_@Model.ID"> 175 <div class="accordion-item"> 176 <h2 class="accordion-header" id="SpecificationHeading_@Model.ID"> 177 <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#SpecificationItem_@Model.ID" aria-expanded="false" aria-controls="SpecificationItem_@Model.ID"> 178 @Translate("Specifications") 179 </button> 180 </h2> 181 <div id="SpecificationItem_@Model.ID" class="accordion-collapse" aria-labelledby="SpecificationHeading_@Model.ID" data-bs-parent="#Specifications_@Model.ID"> 182 <div class="accordion-body"> 183 @{ @RenderFieldsFromList(product.ProductFields, "List") } 184 </div> 185 </div> 186 </div> 187 </div> 188 </div> 189 } 190 } 191 } 192 193 @if (product.ProductCategories != null && Model.Item.GetBoolean("CategoryFields")) 194 { 195 if (product.ProductCategories.Count > 0) 196 { 197 if (layout != "accordion") 198 { 199 foreach (var group in product.ProductCategories) 200 { 201 CategoryFieldViewModel category = group.Value; 202 bool hideHeader = Model.Item.GetBoolean("HideGroupHeaders"); 203 204 if (!hideHeader) { 205 <h4 class="g-col-12 h4 mb-0">@group.Value.Name</h4> 206 } 207 208 { @RenderFieldsFromList(category.Fields, layout) } 209 } 210 } 211 else 212 { 213 <div class="g-col-12"> 214 <div class="accordion accordion-flush w-100" id="Specifications_@Model.ID"> 215 @foreach (var group in product.ProductCategories) 216 { 217 CategoryFieldViewModel category = group.Value; 218 219 <div class="accordion-item"> 220 <h2 class="accordion-header" id="SpecificationHeading_@group.Value.Id"> 221 <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#SpecificationItem_@group.Value.Id" aria-expanded="false" aria-controls="SpecificationItem_@group.Value.Id"> 222 @group.Value.Name 223 </button> 224 </h2> 225 <div id="SpecificationItem_@group.Value.Id" class="accordion-collapse" aria-labelledby="SpecificationHeading_@group.Value.Id" data-bs-parent="#Specifications_@Model.ID"> 226 <div class="accordion-body"> 227 @{ @RenderFieldsFromList(category.Fields, "list") } 228 </div> 229 </div> 230 </div> 231 } 232 </div> 233 </div> 234 } 235 } 236 } 237 </div> 238 </div> 239 } 240 else if (Pageview.IsVisualEditorMode) 241 { 242 <div class="alert alert-warning m-0">@Translate("No products available")</div> 243 } 244 245 @helper RenderFieldsFromList(Dictionary<string, FieldValueViewModel> fields, string layout) 246 { 247 string size = Model.Item.GetRawValueString("Size", "full"); 248 string gaps = size != "full" ? " gap-1" : string.Empty; 249 bool hideFieldLabels = Model.Item.GetBoolean("HideFieldLabels"); 250 bool hideFieldsWithZeroValue = Model.Item.GetBoolean("HideFieldsWithZeroValue"); 251 252 if (layout == "columns") { 253 <div class="g-col-12"> 254 <div class="grid@(gaps)"> 255 @foreach (var field in fields) 256 { 257 {@RenderField(field.Value, layout)} 258 } 259 </div> 260 </div> 261 } 262 if (layout == "list") { 263 <div class="g-col-12"> 264 <dl class="grid@(gaps)"> 265 @foreach (var field in fields) 266 { 267 {@RenderField(field.Value, layout)} 268 } 269 </dl> 270 </div> 271 } 272 if (layout == "table") 273 { 274 string tableSize = size == "full" ? "" : " table-sm"; 275 <div class="g-col-12"> 276 <table class="table table-striped@(tableSize)"> 277 @foreach (var field in fields) 278 { 279 {@RenderField(field.Value, layout)} 280 } 281 </table> 282 </div> 283 } 284 if (layout == "bullets") 285 { 286 string listSize = size == "full" ? "" : "m-0 p-0 lh-1 fs-7 opacity-75"; 287 string listStyle = size == "full" ? "" : "style=\"list-style-position: inside\""; 288 <div class="g-col-12"> 289 <ul class="@listSize" @listStyle> 290 @foreach (var field in fields) 291 { 292 {@RenderField(field.Value, layout)} 293 } 294 </ul> 295 </div> 296 } 297 if (layout == "commas") 298 { 299 List<string> featuresList = new List<string>(); 300 301 foreach (var field in fields) 302 { 303 string firstListItemValue = string.Empty; //Hack to support field type providers with a single value 304 305 if (field.Value?.Value != null) 306 { 307 if (field.Value.Value.GetType() == typeof(System.Collections.Generic.List<FieldOptionValueViewModel>)) 308 { 309 System.Collections.Generic.List<FieldOptionValueViewModel> values = field.Value.Value as System.Collections.Generic.List<FieldOptionValueViewModel>; 310 311 //Hack to support field type providers with a single value 312 if (values.FirstOrDefault() != null) 313 { 314 firstListItemValue = values.FirstOrDefault().Value; 315 } 316 } 317 } 318 319 if (!hideFieldsWithZeroValue || (firstListItemValue != "0" && firstListItemValue != "0.0" && field.Value.Value.ToString() != "0" && field.Value.Value.ToString() != "0.0")) 320 { 321 if (field.Value.Value is object && !string.IsNullOrEmpty(field.Value.Value.ToString())) 322 { 323 if (field.Value.Value.GetType() == typeof(System.Collections.Generic.List<FieldOptionValueViewModel>)) 324 { 325 List<string> options = new List<string>(); 326 foreach (FieldOptionValueViewModel option in field.Value.Value as System.Collections.Generic.List<FieldOptionValueViewModel>) 327 { 328 if (!string.IsNullOrWhiteSpace(option.Value)) 329 { 330 if (option.Value.ToString().Contains("#") && (Translate(field.Value.Name) == Translate("Color") || Translate(field.Value.Name) == Translate("Colour"))) 331 { 332 string colorSpan = "<span class=\"colorbox-sm\" style=\"background-color: " + option.Value + "\"></span>"; 333 options.Add(colorSpan); 334 } 335 else if (!string.IsNullOrEmpty(option.Value)) 336 { 337 options.Add(option.Name); 338 } 339 } 340 } 341 string optionsString = (string.Join(", ", options.Select(x => x.ToString()).ToArray())); 342 if ((Translate(field.Value.Name) == Translate("Color") || Translate(field.Value.Name) == Translate("Colour"))) 343 { 344 optionsString = (string.Join(" ", options.Select(x => x.ToString()).ToArray())); 345 } 346 347 if (!string.IsNullOrEmpty(optionsString)) 348 { 349 if (!hideFieldLabels) 350 { 351 featuresList.Add(field.Value.Name + ": " + optionsString); 352 } 353 else 354 { 355 featuresList.Add(optionsString); 356 } 357 } 358 } 359 else 360 { 361 if (!string.IsNullOrWhiteSpace(field.Value.Value.ToString())) 362 { 363 if (field.Value.Value.ToString().Contains("#") && (Translate(field.Value.Name) == Translate("Color") || Translate(field.Value.Name) == Translate("Colour"))) 364 { 365 string colorSpan = "<span class=\"colorbox-sm\" style=\"background-color: " + field.Value.Value + "\"></span>"; 366 367 if (!hideFieldLabels) 368 { 369 featuresList.Add(field.Value.Name + ": " + colorSpan); 370 } 371 else 372 { 373 featuresList.Add(colorSpan); 374 } 375 } 376 else 377 { 378 if (!hideFieldLabels) 379 { 380 featuresList.Add(field.Value.Name + ": " + field.Value.Value.ToString()); 381 } 382 else 383 { 384 featuresList.Add(field.Value.Value.ToString()); 385 } 386 } 387 } 388 } 389 } 390 } 391 } 392 393 string featuresString = (string.Join(", ", featuresList.Select(x => x.ToString()).ToArray())); 394 395 <div class="g-col-12 opacity-75 fs-7">@featuresString</div> 396 } 397 } 398 399 @helper RenderField(FieldValueViewModel field, string layout) 400 { 401 string size = Model.Item.GetRawValueString("Size", "full"); 402 string fieldValue = field?.Value != null ? field.Value.ToString() : ""; 403 bool hideFieldLabels = Model.Item.GetBoolean("HideFieldLabels"); 404 bool noValues = false; 405 string firstListItemValue = string.Empty; //Hack to support field type providers with a single value 406 bool hideFieldsWithZeroValue = Model.Item.GetBoolean("HideFieldsWithZeroValue"); 407 408 if (!string.IsNullOrEmpty(fieldValue)) 409 { 410 if (field.Value.GetType() == typeof(System.Collections.Generic.List<FieldOptionValueViewModel>)) 411 { 412 System.Collections.Generic.List<FieldOptionValueViewModel> values = field.Value as System.Collections.Generic.List<FieldOptionValueViewModel>; 413 noValues = values.Count > 0 ? false : true; 414 415 //Hack to support field type providers with a single value 416 if (values.FirstOrDefault() != null) 417 { 418 firstListItemValue = values.FirstOrDefault().Value; 419 } 420 } 421 } 422 423 if (!string.IsNullOrEmpty(fieldValue) && noValues == false) 424 { 425 if (!hideFieldsWithZeroValue || (firstListItemValue != "0" && firstListItemValue != "0.0" && field.Value.ToString() != "0" && field.Value.ToString() != "0.0")) 426 { 427 if (layout == "columns") 428 { 429 430 <div class="grid g-col-6 g-col-lg-4 gap-1"> 431 @if (!hideFieldLabels) 432 { 433 <dt class="g-col-12 g-col-lg-4">@field.Name</dt> 434 } 435 <dd class="g-col-12 g-col-lg-8 mb-0 text-break"> 436 437 @{ @RenderFieldValue(field)} 438 </dd> 439 </div> 440 } 441 if (layout == "list") 442 { 443 if (!hideFieldLabels) 444 { 445 <dt class="g-col-4">@field.Name</dt> 446 } 447 <dd class="g-col-8 mb-0 text-break"> 448 @{ @RenderFieldValue(field)} 449 </dd> 450 } 451 if (layout == "table") 452 { 453 <tr> 454 @if (!hideFieldLabels) 455 { 456 <th class="w-25 w-lg-50" scope="row">@field.Name</th> 457 } 458 <td class="text-break"> 459 @{ @RenderFieldValue(field) } 460 </td> 461 </tr> 462 } 463 if (layout == "bullets") 464 { 465 <li> 466 @if (!hideFieldLabels) 467 { 468 <strong>@field.Name</strong> 469 } 470 <span> 471 @{ @RenderFieldValue(field) } 472 </span> 473 </li> 474 } 475 } 476 } 477 } 478 479 @helper RenderFieldValue(FieldValueViewModel field) 480 { 481 string fieldValue = field?.Value != null ? field.Value.ToString() : ""; 482 if (field.SystemName == "ProductWeight") 483 { 484 485 decimal calculatedValue = NumberHelper.ToDecimal(fieldValue); 486 decimal baseValue = NumberHelper.ToDecimal("0,00001"); 487 488 489 fieldValue = calculatedValue.ToString("0.######", System.Globalization.CultureInfo.InvariantCulture).Replace(".", ","); 490 491 } 492 bool isLink = field?.Type == "Link"; 493 bool isColor = false; 494 bool isBrandName = field?.SystemName == "Brand_name"; 495 496 fieldValue = fieldValue == "False" ? Translate("No") : fieldValue; 497 fieldValue = fieldValue == "True" ? Translate("Yes") : fieldValue; 498 499 500 if (field.Value.GetType() == typeof(System.Collections.Generic.List<Dynamicweb.Ecommerce.ProductCatalog.FieldOptionValueViewModel>)) 501 { 502 int valueCount = 0; 503 System.Collections.Generic.List<FieldOptionValueViewModel> values = field.Value as System.Collections.Generic.List<FieldOptionValueViewModel>; 504 int totalValues = values.Count; 505 506 foreach (FieldOptionValueViewModel option in values) 507 { 508 if (!string.IsNullOrEmpty(option.Value)) 509 { 510 if (option.Value.Substring(0, 1) == "#") 511 { 512 isColor = true; 513 } 514 } 515 516 if (!isColor) 517 { 518 @option.Name 519 } 520 else 521 { 522 <span class="colorbox-sm" style="background-color: @option.Value" title="@option.Name"></span> 523 } 524 525 if (valueCount != totalValues && valueCount < (totalValues - 1)) 526 { 527 if (isColor) 528 { 529 <text> </text> 530 } 531 else 532 { 533 <text>, </text> 534 } 535 } 536 valueCount++; 537 } 538 } 539 else 540 { 541 if (fieldValue.Substring(0, 1) == "#") 542 { 543 isColor = true; 544 } 545 546 if (!isColor) 547 { 548 if (isLink) 549 { 550 string linktTitle = !fieldValue.Contains("aspx") ? fieldValue : Translate("Go to link"); 551 string target = Pageview.AreaSettings.GetBoolean("OpenLinksInNewTab") && fieldValue.Contains("http") ? "target=\"_blank\"" : string.Empty; 552 string rel = Pageview.AreaSettings.GetBoolean("OpenLinksInNewTab") && fieldValue.Contains("http") ? "rel=\"noopener\"" : string.Empty; 553 554 <a href="@field.Value" title="@field.Name" @target @rel>@linktTitle</a> 555 } 556 else if (isBrandName) 557 { 558 <span itemprop="brand" itemtype="https://schema.org/Brand" itemscope> 559 <span itemprop="name">@fieldValue</span> 560 </span> 561 } 562 else 563 { 564 @fieldValue 565 } 566 567 } 568 else 569 { 570 <span class="colorbox-sm" style="background-color: @fieldValue" title="@fieldValue"></span> 571 } 572 } 573 } 574

At Brd. Klee A/S we are ISO 9001:2015 certified

Since 1994, Brd. Klee has been ISO certified after 9001:2015 standard by Norske Veritas.

Reasons to choose us

  • Over 500.000 products
  • Data sheets, manuals og 3D drawings
  • Our employees are specialists
  • More than 75 years in the industry

We can help you 24/7

You can order and have goods delivered 24 hours a day - all year.

Outside normal opening hours, service costs a fee.

Call us on telephone (+45) 43 86 83 33

By clicking 'Accept All' you consent that we may collect information about you for various purposes, including: Statistics and Marketing