Contact

PLA 52 - Mesje voor folie - premium

PLA 52
Geavanceerd gereedschap, ontworpen voor precisie en veiligheid. Dankzij het vervangbare lemmet komt dit mesje nooit in contact met de carrosserie, waardoor het risico op schade wordt geëlimineerd. Voor nog meer gemak kunt u onze PLA 55 overwegen, met vervangmesjes in verpakkingen van 10 stuks.

Voordelen

    • Foliemesje met vervangbaar lemmet
    • Het lemmet kan nooit in contact komen met de carrosserie, geen risico op schade
    • PLA 55: vervangmesjes 10 stuks.

Productdetails

Nummer
PLA 52
Verkoopeenheid
1
Eenheden per omdoos
10
Error compiling template "Designs/Swift/Paragraph/Finixa_ProductDetailsMediaTable.cshtml"
Line 418: The name 'fileSize' does not exist in the current context
Line 170: The variable 'videoNumber' is assigned but its value is never used

1 // <auto-generated/> 2 #pragma warning disable 1591 3 namespace CompiledRazorTemplates.Dynamic 4 { 5 #line hidden 6 using System.Threading.Tasks; 7 using System; 8 using System.Collections.Generic; 9 using System.Linq; 10 using Dynamicweb.Ecommerce.ProductCatalog; 11 using System.Text.RegularExpressions; 12 using System.IO; 13 internal class RazorEngine_e0d00bfb00b94658ad59c1884191558a : Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 14 { 15 #pragma warning disable 1998 16 public async override global::System.Threading.Tasks.Task ExecuteAsync() 17 { 18 19 ProductViewModel product = null; 20 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 21 { 22 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 23 } 24 else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode) 25 { 26 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 27 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 28 if (productList?.Products is object) 29 { 30 product = productList.Products[0]; 31 } 32 } 33 string siteLanguage = Pageview.Area.CultureInfo.Name; 34 35 36 int pageId = Dynamicweb.Context.Current.Request["CurrentPageID"] != null ? Convert.ToInt32(Dynamicweb.Context.Current.Request["CurrentPageID"]) : Pageview.ID; 37 var currentPage = Dynamicweb.Content.Services.Pages.GetPage(pageId); 38 List<Dynamicweb.Content.Page> websiteLanguages = new List<Dynamicweb.Content.Page>(); 39 if (currentPage.Area.IsMaster) 40 { 41 websiteLanguages.Add(currentPage); // Add master language 42 if (currentPage.Languages != null) 43 { 44 foreach (var lang in currentPage.Languages) 45 { 46 if (lang.Area.Active == true) // Filter active languages 47 { 48 websiteLanguages.Add(lang); 49 } 50 } 51 } 52 } 53 else 54 { 55 websiteLanguages.Add(currentPage.MasterPage); // Add master page 56 if (currentPage.MasterPage != null && currentPage.MasterPage.Languages != null) 57 { 58 foreach (var lang in currentPage.MasterPage.Languages) 59 { 60 if (lang.Area.Active == true) 61 { 62 websiteLanguages.Add(lang); 63 } 64 } 65 } 66 } 67 68 69 var ecomLanguages = Dynamicweb.Ecommerce.Services.Languages.GetLanguages(); 70 List<Dynamicweb.Ecommerce.International.Language> activeLanguages = new List<Dynamicweb.Ecommerce.International.Language>(); 71 72 73 foreach (var websiteLanguage in websiteLanguages) 74 { 75 var matchingEcomLanguage = ecomLanguages.FirstOrDefault(ecomLang => 76 string.Equals(ecomLang.Culture, websiteLanguage.Area.CultureInfo.Name, StringComparison.OrdinalIgnoreCase) || 77 string.Equals(ecomLang.Code, websiteLanguage.Area.CultureInfo.TwoLetterISOLanguageName, StringComparison.OrdinalIgnoreCase)); 78 79 if (matchingEcomLanguage != null && !activeLanguages.Contains(matchingEcomLanguage)) 80 { 81 activeLanguages.Add(matchingEcomLanguage); 82 } 83 } 84 85 if (activeLanguages.Count == 0) 86 { 87 activeLanguages = ecomLanguages.ToList(); 88 } 89 if (product is object) 90 { 91 92 supportedImageFormats = new string[] { ".jpg", ".jpeg", ".webp", ".png", ".gif", ".bmp", ".tiff" }; 93 supportedVideoFormats = new string[] { "youtu.be", "youtube", "vimeo", ".mp4", ".webm" }; 94 supportedDocumentFormats = new string[] { ".pdf", ".docx", ".xlsx", ".ppt", ".pptx", ".igs", ".ipt", ".sat", ".stp", ".dwg", ".dxf", ".dwf" }; 95 allSupportedFormats = supportedImageFormats.Concat(supportedVideoFormats).Concat(supportedDocumentFormats).ToArray(); 96 97 98 var selectedAssetCategories = Model.Item.GetList("ImageAssets")?.GetRawValue().OfType<string>(); 99 bool includeImagePatternImages = Model.Item.GetBoolean("ImagePatternImages"); 100 101 102 Dynamicweb.Ecommerce.Products.ProductService ps = new Dynamicweb.Ecommerce.Products.ProductService(); 103 Dynamicweb.Ecommerce.Products.DetailsGroupService dgs = new Dynamicweb.Ecommerce.Products.DetailsGroupService(); 104 105 List<ewiMediaViewModel> productAssets = new List<ewiMediaViewModel>(); 106 List<Dynamicweb.Ecommerce.Products.Product> products = new List<Dynamicweb.Ecommerce.Products.Product>(); 107 foreach (var language in ecomLanguages) 108 { 109 var productitem = ps.GetProductById(product.Id, product.VariantId, language.LanguageId); 110 if (productitem is object) 111 { 112 Dynamicweb.Ecommerce.Products.DetailService detailService = new Dynamicweb.Ecommerce.Products.DetailService(); 113 114 foreach (var detail in detailService.GetDetails(productitem)) 115 { 116 if (detail.LanguageId == language.LanguageId) 117 { 118 Dynamicweb.Ecommerce.Products.DetailsGroup detailsGroup = dgs.GetById(detail.GroupId); 119 120 if (selectedAssetCategories.Contains(detailsGroup.SystemName)) 121 { 122 // Check if this language is already in activeLanguages before adding 123 if (!activeLanguages.Any(al => al.LanguageId == language.LanguageId)) 124 { 125 activeLanguages.Add(language); 126 } 127 128 ewiMediaViewModel productAsset = new ewiMediaViewModel(); 129 productAsset.Value = detail.Value; 130 productAsset.AssetSystemName = detailsGroup.SystemName; 131 productAsset.LanguageId = detail.LanguageId; 132 productAsset.LanguageName = language.NativeName; 133 productAsset.DisplayName = detail.Name; 134 productAssets.Add(productAsset); 135 } 136 } 137 } 138 } 139 } 140 141 142 143 string defaultImage = product.DefaultImage != null ? product.DefaultImage.Value : ""; 144 IEnumerable<MediaViewModel> assetsImages = selectedAssetCategories != null ? 145 product.AssetCategories.Where(x => selectedAssetCategories.Contains(x.SystemName)).SelectMany(x => x.Assets) : 146 product.AssetCategories.SelectMany(x => x.Assets); 147 assetsImages = assetsImages.OrderByDescending(x => x.Value.Equals(defaultImage)); 148 IEnumerable<MediaViewModel> assetsList = new MediaViewModel[] { }; 149 assetsList = productAssets.Cast<MediaViewModel>(); 150 assetsList = includeImagePatternImages ? assetsList.Union(product.ImagePatternImages) : assetsList; 151 assetsList = includeImagePatternImages && assetsList.Count() == 0 ? assetsList.Append(product.DefaultImage) : assetsList; 152 bool defaultImageFallback = Model.Item.GetBoolean("DefaultImageFallback"); 153 bool showOnlyPrimaryImage = Model.Item.GetBoolean("ShowOnlyPrimaryImage"); 154 int totalAssets = 0; 155 if (showOnlyPrimaryImage == false) { 156 foreach (MediaViewModel asset in assetsList) { 157 var assetValue = asset.Value; 158 foreach (string format in allSupportedFormats) { 159 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) { 160 totalAssets++; 161 } 162 } 163 } 164 } 165 if ((totalAssets == 0 && product.DefaultImage != null && selectedAssetCategories?.Count() == 0) || (showOnlyPrimaryImage == true && product.DefaultImage != null)) 166 { 167 assetsList = new List<MediaViewModel>(){ product.DefaultImage }; 168 totalAssets = 1; 169 } 170 int videoNumber = 0; 171 172 string spacing = Model.Item.GetRawValueString("Spacing", "p-0"); 173 spacing = spacing == "none" ? "p-0" : spacing; 174 spacing = spacing == "small" ? "p-3" : spacing; 175 spacing = spacing == "large" ? "p-5" : spacing; 176 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 177 bool hideThumbnails = Model.Item.GetBoolean("HideThumbnails"); 178 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 179 int modalVideoNumber = 0; 180 181 if (totalAssets != 0 && assetsList.Any()) 182 { 183 WriteLiteral(" <div"); 184 BeginWriteAttribute("class", " class=\"", 11709, "\"", 11771, 4); 185 WriteAttributeValue("", 11717, spacing, 11717, 8, false); 186 WriteAttributeValue("", 11725, theme, 11725, 8, false); 187 WriteAttributeValue(" ", 11733, "item_", 11734, 6, true); 188 WriteAttributeValue("", 11739, Model.Item.SystemName.ToLower(), 11739, 32, false); 189 EndWriteAttribute(); 190 WriteLiteral(">\r\n"); 191 if (!string.IsNullOrEmpty(Model.Item.GetString("Title")) && !Model.Item.GetBoolean("HideTitle")) 192 { 193 string titleFontSize = Model.Item.GetRawValueString("TitleFontSize", "h3"); 194 WriteLiteral(" <h3"); 195 BeginWriteAttribute("class", " class=\"", 12013, "\"", 12040, 2); 196 WriteAttributeValue("", 12021, titleFontSize, 12021, 14, false); 197 WriteAttributeValue(" ", 12035, "mb-3", 12036, 5, true); 198 EndWriteAttribute(); 199 WriteLiteral(">\r\n "); 200 Write(Model.Item.GetString("Title")); 201 WriteLiteral("\r\n </h3>\r\n"); 202 } 203 if (activeLanguages.Count > 1) 204 { 205 206 // Filter activeLanguages als deze taal assets bevat 207 var languagesWithAssets = new List<Dynamicweb.Ecommerce.International.Language>(); 208 209 foreach (var lang in activeLanguages) 210 { 211 bool hasAssets = false; 212 foreach (MediaViewModel asset in assetsList) 213 { 214 try { 215 if (asset.GetType().GetProperty("LanguageId") != null) 216 { 217 var assetLangId = asset.GetType().GetProperty("LanguageId").GetValue(asset)?.ToString() ?? ""; 218 if (assetLangId == lang.LanguageId) 219 { 220 hasAssets = true; 221 break; 222 } 223 } 224 } catch { } 225 } 226 227 if (hasAssets) 228 { 229 languagesWithAssets.Add(lang); 230 } 231 } 232 233 Dynamicweb.Ecommerce.International.Language currentLanguage = null; 234 string currentLanguageValue = "ALL"; 235 236 // Toon enkel de taal dropdown als er meer dan 1 taal is met assets 237 if (languagesWithAssets.Count > 1) 238 { 239 240 currentLanguage = languagesWithAssets.FirstOrDefault(lang => 241 string.Equals(lang.Culture, siteLanguage, StringComparison.OrdinalIgnoreCase)) ?? 242 languagesWithAssets.FirstOrDefault(lang => 243 string.Equals(lang.NativeName, "English", StringComparison.OrdinalIgnoreCase)) ?? 244 languagesWithAssets.FirstOrDefault(); 245 246 // Map English naar LANG1 247 currentLanguageValue = currentLanguage != null && 248 string.Equals(currentLanguage.NativeName, "English", StringComparison.OrdinalIgnoreCase) 249 ? "LANG1" : currentLanguage?.LanguageId ?? "ALL"; 250 } 251 if (languagesWithAssets.Count > 1) 252 { 253 WriteLiteral(" <div class=\"mb-3\">\r\n <div class=\"mb-1\">"); 254 Write(Translate("Language")); 255 WriteLiteral(@"</div> 256 <div class=""dropdown js-dropdown""> 257 <button class=""form-select text-start w-100 js-dropdown-btn"" type=""button"" data-bs-toggle=""dropdown"" data-bs-auto-close=""outside"" aria-expanded=""false""> 258 "); 259 Write(currentLanguage?.NativeName ?? "All"); 260 WriteLiteral(@" 261 </button> 262 <div class=""dropdown-menu w-100 p-3""> 263 <div class=""form-check""> 264 <input class=""form-check-input"" type=""checkbox"" name=""LanguageId"" value=""ALL"" id=""LanguageCheckAll"" onchange=""filterResults('ALL', event);""> 265 <label class=""form-check-label"" for=""LanguageCheckAll""> 266 "); 267 Write(Translate("All")); 268 WriteLiteral("\r\n </label>\r\n </div>\r\n"); 269 foreach (var language in languagesWithAssets.GroupBy(l => l.NativeName).Select(g => g.First())) 270 { 271 string languageValue = string.Equals(language.NativeName, "English", StringComparison.OrdinalIgnoreCase) 272 ? "LANG1" : language.LanguageId; 273 bool isCurrentLanguage = language == currentLanguage; 274 WriteLiteral(" <div class=\"form-check\">\r\n <input class=\"form-check-input\" type=\"checkbox\" name=\"LanguageId\" data-short-name=\""); 275 Write(language.NativeName); 276 WriteLiteral("\""); 277 BeginWriteAttribute("value", " value=\"", 16500, "\"", 16522, 1); 278 WriteAttributeValue("", 16508, languageValue, 16508, 14, false); 279 EndWriteAttribute(); 280 BeginWriteAttribute("id", " id=\"", 16523, "\"", 16548, 2); 281 WriteAttributeValue("", 16528, "Check_", 16528, 6, true); 282 WriteAttributeValue("", 16534, languageValue, 16534, 14, false); 283 EndWriteAttribute(); 284 WriteLiteral(" "); 285 Write(isCurrentLanguage ? "checked" : ""); 286 WriteLiteral(" onchange=\"filterResults(\'"); 287 Write(languageValue); 288 WriteLiteral("\', event);\">\r\n <label class=\"form-check-label\""); 289 BeginWriteAttribute("for", " for=\"", 16712, "\"", 16738, 2); 290 WriteAttributeValue("", 16718, "Check_", 16718, 6, true); 291 WriteAttributeValue("", 16724, languageValue, 16724, 14, false); 292 EndWriteAttribute(); 293 WriteLiteral(">\r\n "); 294 Write(language.NativeName); 295 WriteLiteral("\r\n </label>\r\n </div>\r\n"); 296 } 297 WriteLiteral(" </div>\r\n </div>\r\n </div>\r\n"); 298 } 299 } 300 WriteLiteral(" <div class=\"table-responsive\">\r\n <table class=\"table table-hover align-middle mb-0\" style=\"table-layout: fixed;\" id=\"assets-table\">\r\n <thead>\r\n <tr>\r\n"); 301 if (!hideThumbnails) 302 { 303 WriteLiteral(" <th style=\"width:60px\">&nbsp;</th>\r\n"); 304 } 305 WriteLiteral(" <th>"); 306 Write(Translate("Name")); 307 WriteLiteral("</th>\r\n <th>"); 308 Write(Translate("Asset type")); 309 WriteLiteral("</th>\r\n <th>"); 310 Write(Translate("Language")); 311 WriteLiteral("</th>\r\n <th class=\"text-end\" style=\"width:100px\">"); 312 Write(Translate("File type")); 313 WriteLiteral("</th>\r\n <th class=\"text-end d-none d-lg-table-cell\">"); 314 Write(Translate("Download")); 315 WriteLiteral("</th>\r\n </tr>\r\n </thead>\r\n <tbody class=\"border-top-0\">\r\n"); 316 foreach (ewiMediaViewModel asset in productAssets) 317 { 318 var assetValue = asset.Value; 319 string assetName = !string.IsNullOrEmpty(asset.DisplayName) ? asset.DisplayName : asset.Value.Substring(asset.Value.LastIndexOf('/') + 1); 320 321 // Skip videos 322 bool isVideo = false; 323 foreach (string format in supportedVideoFormats) 324 { 325 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) 326 { 327 isVideo = true; 328 } 329 } 330 331 // Only process non-video files 332 if (!isVideo) 333 { 334 // Check if file exists 335 string filePath = Dynamicweb.Context.Current.Server.MapPath(assetValue); 336 if (File.Exists(filePath)) 337 { 338 // Check if it's a supported format 339 if (allSupportedFormats.Any(format => assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0)) 340 { 341 // Get file extension 342 string fileExtension = Path.GetExtension(assetValue).ToLower(); 343 344 // Map English to LANG1 for filtering 345 string languageId = string.Equals(asset.LanguageName, "English", StringComparison.OrdinalIgnoreCase) ? "LANG1" : asset.LanguageId; 346 347 WriteLiteral(" <tr data-language-ids=\""); 348 Write(languageId); 349 WriteLiteral("\" data-language-name=\""); 350 Write(asset.LanguageName); 351 WriteLiteral("\">\r\n"); 352 if (!hideThumbnails) 353 { 354 WriteLiteral(" <td class=\"px-0\">\r\n"); 355 356 string productName = product.Name; 357 string imagePath = asset.Value; 358 string imageLinkPath = imagePath; 359 imagePath = $"/Admin/Public/GetImage.ashx?image={imagePath}&width=60&format=webp"; 360 RatioSettings ratioSettings = GetRatioSettings(); 361 WriteLiteral(" <a"); 362 BeginWriteAttribute("href", " href=\"", 20951, "\"", 20972, 1); 363 WriteAttributeValue("", 20958, imageLinkPath, 20958, 14, false); 364 EndWriteAttribute(); 365 BeginWriteAttribute("class", " class=\"", 20973, "\"", 21035, 3); 366 WriteAttributeValue("", 20981, "d-block", 20981, 7, true); 367 WriteAttributeValue(" ", 20988, ratioSettings.CssClass, 20989, 25, false); 368 WriteAttributeValue("", 21014, ratioSettings.Fill, 21014, 21, false); 369 EndWriteAttribute(); 370 BeginWriteAttribute("style", " style=\"", 21036, "\"", 21072, 1); 371 WriteAttributeValue("", 21044, ratioSettings.CssVariable, 21044, 28, false); 372 EndWriteAttribute(); 373 WriteLiteral(" download"); 374 BeginWriteAttribute("alt", " alt=\"", 21082, "\"", 21100, 1); 375 WriteAttributeValue("", 21088, productName, 21088, 12, false); 376 EndWriteAttribute(); 377 WriteLiteral(">\r\n <div class=\"d-flex align-items-center justify-content-center overflow-hidden h-100\">\r\n <img loading=\"lazy\""); 378 BeginWriteAttribute("src", " src=\"", 21325, "\"", 21341, 1); 379 WriteAttributeValue("", 21331, imagePath, 21331, 10, false); 380 EndWriteAttribute(); 381 WriteLiteral(" class=\"mw-100 mh-100\""); 382 BeginWriteAttribute("alt", " alt=\"", 21364, "\"", 21382, 1); 383 WriteAttributeValue("", 21370, productName, 21370, 12, false); 384 EndWriteAttribute(); 385 WriteLiteral(" />\r\n </div>\r\n </a>\r\n </td>\r\n"); 386 } 387 WriteLiteral(" <td>\r\n <a"); 388 BeginWriteAttribute("href", " href=\"", 21712, "\"", 21730, 1); 389 WriteAttributeValue("", 21719, assetValue, 21719, 11, false); 390 EndWriteAttribute(); 391 WriteLiteral(" class=\"text-decoration-none text-break\""); 392 BeginWriteAttribute("download", " download=\"", 21771, "\"", 21792, 1); 393 WriteAttributeValue("", 21782, assetName, 21782, 10, false); 394 EndWriteAttribute(); 395 BeginWriteAttribute("title", " title=\"", 21793, "\"", 21811, 1); 396 WriteAttributeValue("", 21801, assetName, 21801, 10, false); 397 EndWriteAttribute(); 398 WriteLiteral(">\r\n "); 399 Write(assetName); 400 WriteLiteral("\r\n </a>\r\n </td>\r\n <td>"); 401 Write(asset.AssetSystemName); 402 WriteLiteral("</td>\r\n <td>"); 403 Write(asset.LanguageName); 404 WriteLiteral("</td>\r\n <td class=\"text-end\">"); 405 Write(fileExtension); 406 WriteLiteral("</td>\r\n <td class=\"text-end d-none d-lg-table-cell\">\r\n <a"); 407 BeginWriteAttribute("href", " href=\"", 22361, "\"", 22379, 1); 408 WriteAttributeValue("", 22368, assetValue, 22368, 11, false); 409 EndWriteAttribute(); 410 WriteLiteral(" class=\"text-decoration-none\""); 411 BeginWriteAttribute("download", " download=\"", 22409, "\"", 22430, 1); 412 WriteAttributeValue("", 22420, assetName, 22420, 10, false); 413 EndWriteAttribute(); 414 BeginWriteAttribute("title", " title=\"", 22431, "\"", 22449, 1); 415 WriteAttributeValue("", 22439, assetName, 22439, 10, false); 416 EndWriteAttribute(); 417 WriteLiteral(">\r\n "); 418 Write(fileSize); 419 WriteLiteral(" KB <div class=\"icon-2\" style=\"z-index: 1\">"); 420 Write(ReadFile(iconPath + "download.svg")); 421 WriteLiteral("</div>\r\n </a>\r\n </td>\r\n </tr>\r\n"); 422 } 423 } 424 } 425 } 426 WriteLiteral(@" </tbody> 427 </table> 428 </div> 429 <script> 430 function filterResults(selectedLang, event) { 431 console.log('Filtering by language:', selectedLang); 432 433 // Prevent event bubbling 434 if (event) { 435 event.stopPropagation(); 436 } 437 438 const table = document.getElementById('assets-table'); 439 const rows = table.querySelectorAll('tbody tr'); 440 const button = document.querySelector('.js-dropdown-btn'); 441 442 const checkedBoxes = document.querySelectorAll('input[name=""LanguageId""]:checked'); 443 const checkedLanguages = Array.from(checkedBoxes).map(cb => cb.value); 444 445 // Handle ""All"" checkbox behavior - if ""All"" is checked, uncheck others 446 if (selecte"); 447 WriteLiteral(@"dLang === 'ALL') { 448 const allCheckbox = document.querySelector('input[value=""ALL""]'); 449 if (allCheckbox && allCheckbox.checked) { 450 // Uncheck all other checkboxes 451 document.querySelectorAll('input[name=""LanguageId""]:not([value=""ALL""])').forEach(cb => { 452 cb.checked = false; 453 }); 454 } 455 } else { 456 // If any specific language is checked, uncheck ""All"" 457 const allCheckbox = document.querySelector('input[value=""ALL""]'); 458 if (allCheckbox) { 459 allCheckbox.checked = false; 460 } 461 } 462 463 // Re-get checked languages after potential changes 464 const finalCheckedBoxes = document.querySelectorAll('input[name=""LanguageId""]:checked')"); 465 WriteLiteral(@"; 466 const finalCheckedLanguages = Array.from(finalCheckedBoxes).map(cb => cb.value); 467 468 // Update button text based on selected languages 469 if (finalCheckedLanguages.length === 0) { 470 button.textContent = '"); 471 Write(Translate("All")); 472 WriteLiteral("\';\r\n } else if (finalCheckedLanguages.includes(\'ALL\')) {\r\n button.textContent = \'"); 473 Write(Translate("All")); 474 WriteLiteral(@"'; 475 } else if (finalCheckedLanguages.length === 1) { 476 const selectedCheckbox = document.querySelector(`input[value=""${finalCheckedLanguages[0]}""]`); 477 button.textContent = selectedCheckbox ? selectedCheckbox.getAttribute('data-short-name') : 'All'; 478 } else { 479 button.textContent = `${finalCheckedLanguages.length} languages selected`; 480 } 481 482 // Filter table rows 483 rows.forEach(row => { 484 const rowLanguageIds = row.getAttribute('data-language-ids'); 485 const rowLanguageName = row.getAttribute('data-language-name'); 486 487 if (finalCheckedLanguages.length === 0 || finalCheckedLanguages.includes('ALL')) { 488 row.style.display = ''; 489 } else { 490 const shouldShow = ro"); 491 WriteLiteral(@"wLanguageIds && finalCheckedLanguages.some(lang => 492 rowLanguageIds === lang || 493 rowLanguageIds === 'ALL' 494 ); 495 496 row.style.display = shouldShow ? '' : 'none'; 497 } 498 }); 499 500 } 501 document.addEventListener('DOMContentLoaded', function() { 502 // Set initial state - apply filter for pre-checked language 503 const currentLangCheckbox = document.querySelector('input[name=""LanguageId""]:checked'); 504 if (currentLangCheckbox) { 505 filterResults(currentLangCheckbox.value); 506 } else { 507 // Default to show all if nothing is checked 508 const table = document.getElementById('assets-table'); 509 const rows = table.querySelectorAll('tbody tr'); "); 510 WriteLiteral("\n rows.forEach(row => {\r\n row.style.display = \'\';\r\n });\r\n }\r\n });\r\n </script>\r\n"); 511 foreach (MediaViewModel asset in assetsList) 512 { 513 var assetName = asset.Value.ToLower(); 514 foreach (string videoFormat in supportedVideoFormats) 515 { //Videos 516 if (assetName.IndexOf(videoFormat, StringComparison.OrdinalIgnoreCase) >= 0) 517 { 518 WriteLiteral(" <div class=\"modal fade js-video-modal\""); 519 BeginWriteAttribute("id", " id=\"", 28054, "\"", 28094, 4); 520 WriteAttributeValue("", 28059, "modal_", 28059, 6, true); 521 WriteAttributeValue("", 28065, Model.ID, 28065, 11, false); 522 WriteAttributeValue("", 28076, "_", 28076, 1, true); 523 WriteAttributeValue("", 28077, modalVideoNumber, 28077, 17, false); 524 EndWriteAttribute(); 525 WriteLiteral(" tabindex=\"-1\""); 526 BeginWriteAttribute("aria-labelledby", " aria-labelledby=\"", 28109, "\"", 28186, 4); 527 WriteAttributeValue("", 28127, "productDetailsTableModalTitle_", 28127, 30, true); 528 WriteAttributeValue("", 28157, Model.ID, 28157, 11, false); 529 WriteAttributeValue("", 28168, "_", 28168, 1, true); 530 WriteAttributeValue("", 28169, modalVideoNumber, 28169, 17, false); 531 EndWriteAttribute(); 532 WriteLiteral(@" aria-hidden=""true""> 533 <div class=""modal-dialog modal-dialog-centered modal-xl""> 534 <div class=""modal-content""> 535 <div class=""modal-header visually-hidden""> 536 <h5 class=""modal-title"""); 537 BeginWriteAttribute("id", " id=\"", 28500, "\"", 28564, 4); 538 WriteAttributeValue("", 28505, "productDetailsTableModalTitle_", 28505, 30, true); 539 WriteAttributeValue("", 28535, Model.ID, 28535, 11, false); 540 WriteAttributeValue("", 28546, "_", 28546, 1, true); 541 WriteAttributeValue("", 28547, modalVideoNumber, 28547, 17, false); 542 EndWriteAttribute(); 543 WriteLiteral(">"); 544 Write(product.Title); 545 WriteLiteral(@"</h5> 546 <button type=""button"" class=""btn-close"" data-bs-dismiss=""modal"" aria-label=""Close""></button> 547 </div> 548 <div class=""modal-body p-2 p-lg-3 h-100""> 549 "); 550 551 var videoParams = GetVideoParams(asset, "modal"); 552 Write(RenderPartial("Components/VideoPlayer.cshtml", new Dynamicweb.Frontend.FileViewModel { Path = asset.Value }, videoParams)); 553 WriteLiteral(" </div>\r\n </div>\r\n </div>\r\n </div>\r\n"); 554 modalVideoNumber++; 555 } 556 } 557 } 558 WriteLiteral(" </div>\r\n"); 559 } 560 else if (Pageview.IsVisualEditorMode) 561 { 562 WriteLiteral(" <div"); 563 BeginWriteAttribute("class", " class=\"", 29534, "\"", 29554, 2); 564 WriteAttributeValue("", 29542, "h-100", 29542, 5, true); 565 WriteAttributeValue(" ", 29547, theme, 29548, 6, false); 566 EndWriteAttribute(); 567 WriteLiteral(">\r\n <div class=\"alert alert-dark m-0\">\r\n "); 568 Write(Translate("No assets are available")); 569 WriteLiteral("\r\n </div>\r\n </div>\r\n"); 570 } 571 } 572 } 573 #pragma warning restore 1998 574 575 public ProductViewModel product { get; set; } = new ProductViewModel(); 576 public string[] supportedImageFormats { get; set; } 577 public string[] supportedVideoFormats { get; set; } 578 public string[] supportedDocumentFormats { get; set; } 579 public string[] allSupportedFormats { get; set; } 580 public class RatioSettings 581 { 582 public string Ratio { get; set; } 583 public string CssClass { get; set; } 584 public string CssVariable { get; set; } 585 public string Fill { get; set; } 586 } 587 public RatioSettings GetRatioSettings() 588 { 589 var ratioSettings = new RatioSettings(); 590 string ratio = Model.Item.GetRawValueString("ImageAspectRatio", ""); 591 ratio = ratio != "0" ? ratio : ""; 592 string cssClass = ratio != "" && ratio != "fill" ? " ratio" : ""; 593 string cssVariable = ratio != "" && ratio != "fill" ? "--bs-aspect-ratio: " + ratio : ""; 594 ratioSettings.Ratio = ratio; 595 ratioSettings.CssClass = cssClass; 596 ratioSettings.CssVariable = cssVariable; 597 ratioSettings.Fill = ratio == "fill" ? " h-100" : ""; 598 return ratioSettings; 599 } 600 // PDB: eWings MediaViewModel extender 601 public class ewiMediaViewModel : MediaViewModel 602 { 603 public string LanguageId { get; set; } 604 public string LanguageName { get; set; } 605 public string AssetSystemName { get; set; } 606 } 607 public Dictionary<string, object> GetVideoParams(MediaViewModel asset, string size) 608 { 609 string assetName = !string.IsNullOrEmpty(asset.DisplayName) ? asset.DisplayName : asset.Name; 610 string type = GetVideoType(asset.Value); 611 bool openInModal = Model.Item.GetString("OpenVideoInModal") == "true" ? true : false; 612 bool autoPlay = Model.Item.GetBoolean("VideoAutoPlay"); 613 var videoParams = new Dictionary<string, object>(); 614 videoParams.Add("AssetName", asset.Name); 615 videoParams.Add("AssetVideoType", type); 616 videoParams.Add("AssetDisplayName", asset.DisplayName); 617 videoParams.Add("OpenVideoInModal", openInModal); 618 videoParams.Add("VideoAutoPlay", autoPlay); 619 videoParams.Add("Size", size); 620 videoParams.Add("Id", Model.ID); 621 return videoParams; 622 } 623 public string GetVideoType(string assetValue) 624 { 625 string type = assetValue.IndexOf("youtu.be", StringComparison.OrdinalIgnoreCase) >= 0 || assetValue.IndexOf("youtube", StringComparison.OrdinalIgnoreCase) >= 0 ? "youtube" : string.Empty; 626 type = assetValue.IndexOf("vimeo", StringComparison.OrdinalIgnoreCase) >= 0 ? "vimeo" : type; 627 type = string.IsNullOrEmpty(type) ? "selfhosted" : type; 628 return type; 629 } 630 public string GetYoutubeScreenDump(string assetValue) 631 { 632 var regex = new Regex(@"(?:youtube\.com\/.*[\?&]v=|youtu\.be\/|youtube\.com\/embed\/)([\w-]+)(?:\?.*)?"); 633 Match match = regex.Match(assetValue); 634 string videoId = match.Success ? match.Groups[1].Value : string.Empty; 635 string youtubeThumbnail = $"https://img.youtube.com/vi/{videoId}/mqdefault.jpg"; 636 return youtubeThumbnail; 637 } 638 } 639 } 640 #pragma warning restore 1591 641

1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 2 @using Dynamicweb.Ecommerce.ProductCatalog 3 @using System.Text.RegularExpressions; 4 @using System.IO 5 @functions { 6 public ProductViewModel product { get; set; } = new ProductViewModel(); 7 public string[] supportedImageFormats { get; set; } 8 public string[] supportedVideoFormats { get; set; } 9 public string[] supportedDocumentFormats { get; set; } 10 public string[] allSupportedFormats { get; set; } 11 public class RatioSettings 12 { 13 public string Ratio { get; set; } 14 public string CssClass { get; set; } 15 public string CssVariable { get; set; } 16 public string Fill { get; set; } 17 } 18 public RatioSettings GetRatioSettings() 19 { 20 var ratioSettings = new RatioSettings(); 21 string ratio = Model.Item.GetRawValueString("ImageAspectRatio", ""); 22 ratio = ratio != "0" ? ratio : ""; 23 string cssClass = ratio != "" && ratio != "fill" ? " ratio" : ""; 24 string cssVariable = ratio != "" && ratio != "fill" ? "--bs-aspect-ratio: " + ratio : ""; 25 ratioSettings.Ratio = ratio; 26 ratioSettings.CssClass = cssClass; 27 ratioSettings.CssVariable = cssVariable; 28 ratioSettings.Fill = ratio == "fill" ? " h-100" : ""; 29 return ratioSettings; 30 } 31 // PDB: eWings MediaViewModel extender 32 public class ewiMediaViewModel : MediaViewModel 33 { 34 public string LanguageId { get; set; } 35 public string LanguageName { get; set; } 36 public string AssetSystemName { get; set; } 37 } 38 public Dictionary<string, object> GetVideoParams(MediaViewModel asset, string size) 39 { 40 string assetName = !string.IsNullOrEmpty(asset.DisplayName) ? asset.DisplayName : asset.Name; 41 string type = GetVideoType(asset.Value); 42 bool openInModal = Model.Item.GetString("OpenVideoInModal") == "true" ? true : false; 43 bool autoPlay = Model.Item.GetBoolean("VideoAutoPlay"); 44 var videoParams = new Dictionary<string, object>(); 45 videoParams.Add("AssetName", asset.Name); 46 videoParams.Add("AssetVideoType", type); 47 videoParams.Add("AssetDisplayName", asset.DisplayName); 48 videoParams.Add("OpenVideoInModal", openInModal); 49 videoParams.Add("VideoAutoPlay", autoPlay); 50 videoParams.Add("Size", size); 51 videoParams.Add("Id", Model.ID); 52 return videoParams; 53 } 54 public string GetVideoType(string assetValue) 55 { 56 string type = assetValue.IndexOf("youtu.be", StringComparison.OrdinalIgnoreCase) >= 0 || assetValue.IndexOf("youtube", StringComparison.OrdinalIgnoreCase) >= 0 ? "youtube" : string.Empty; 57 type = assetValue.IndexOf("vimeo", StringComparison.OrdinalIgnoreCase) >= 0 ? "vimeo" : type; 58 type = string.IsNullOrEmpty(type) ? "selfhosted" : type; 59 return type; 60 } 61 public string GetYoutubeScreenDump(string assetValue) 62 { 63 var regex = new Regex(@"(?:youtube\.com\/.*[\?&]v=|youtu\.be\/|youtube\.com\/embed\/)([\w-]+)(?:\?.*)?"); 64 Match match = regex.Match(assetValue); 65 string videoId = match.Success ? match.Groups[1].Value : string.Empty; 66 string youtubeThumbnail = $"https://img.youtube.com/vi/{videoId}/mqdefault.jpg"; 67 return youtubeThumbnail; 68 } 69 } 70 @{ 71 @* Get the product data *@ 72 ProductViewModel product = null; 73 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 74 { 75 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 76 } 77 else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode) 78 { 79 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 80 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 81 if (productList?.Products is object) 82 { 83 product = productList.Products[0]; 84 } 85 } 86 string siteLanguage = Pageview.Area.CultureInfo.Name; 87 88 @* Get active website languages first *@ 89 int pageId = Dynamicweb.Context.Current.Request["CurrentPageID"] != null ? Convert.ToInt32(Dynamicweb.Context.Current.Request["CurrentPageID"]) : Pageview.ID; 90 var currentPage = Dynamicweb.Content.Services.Pages.GetPage(pageId); 91 List<Dynamicweb.Content.Page> websiteLanguages = new List<Dynamicweb.Content.Page>(); 92 if (currentPage.Area.IsMaster) 93 { 94 websiteLanguages.Add(currentPage); // Add master language 95 if (currentPage.Languages != null) 96 { 97 foreach (var lang in currentPage.Languages) 98 { 99 if (lang.Area.Active == true) // Filter active languages 100 { 101 websiteLanguages.Add(lang); 102 } 103 } 104 } 105 } 106 else 107 { 108 websiteLanguages.Add(currentPage.MasterPage); // Add master page 109 if (currentPage.MasterPage != null && currentPage.MasterPage.Languages != null) 110 { 111 foreach (var lang in currentPage.MasterPage.Languages) 112 { 113 if (lang.Area.Active == true) 114 { 115 websiteLanguages.Add(lang); 116 } 117 } 118 } 119 } 120 121 @* Get ecommerce languages and filter by active website languages *@ 122 var ecomLanguages = Dynamicweb.Ecommerce.Services.Languages.GetLanguages(); 123 List<Dynamicweb.Ecommerce.International.Language> activeLanguages = new List<Dynamicweb.Ecommerce.International.Language>(); 124 125 @* Filter ecommerce languages to only include those corresponding to active website languages *@ 126 foreach (var websiteLanguage in websiteLanguages) 127 { 128 var matchingEcomLanguage = ecomLanguages.FirstOrDefault(ecomLang => 129 string.Equals(ecomLang.Culture, websiteLanguage.Area.CultureInfo.Name, StringComparison.OrdinalIgnoreCase) || 130 string.Equals(ecomLang.Code, websiteLanguage.Area.CultureInfo.TwoLetterISOLanguageName, StringComparison.OrdinalIgnoreCase)); 131 132 if (matchingEcomLanguage != null && !activeLanguages.Contains(matchingEcomLanguage)) 133 { 134 activeLanguages.Add(matchingEcomLanguage); 135 } 136 } 137 @* Fallback: if no matches found, use all ecommerce languages *@ 138 if (activeLanguages.Count == 0) 139 { 140 activeLanguages = ecomLanguages.ToList(); 141 } 142 } 143 @if (product is object) 144 { 145 @* Supported formats *@ 146 supportedImageFormats = new string[] { ".jpg", ".jpeg", ".webp", ".png", ".gif", ".bmp", ".tiff" }; 147 supportedVideoFormats = new string[] { "youtu.be", "youtube", "vimeo", ".mp4", ".webm" }; 148 supportedDocumentFormats = new string[] { ".pdf", ".docx", ".xlsx", ".ppt", ".pptx", ".igs", ".ipt", ".sat", ".stp", ".dwg", ".dxf", ".dwf" }; 149 allSupportedFormats = supportedImageFormats.Concat(supportedVideoFormats).Concat(supportedDocumentFormats).ToArray(); 150 151 @* Collect the assets *@ 152 var selectedAssetCategories = Model.Item.GetList("ImageAssets")?.GetRawValue().OfType<string>(); 153 bool includeImagePatternImages = Model.Item.GetBoolean("ImagePatternImages"); 154 155 @* PDB: Collect the valid assets and languages *@ 156 Dynamicweb.Ecommerce.Products.ProductService ps = new Dynamicweb.Ecommerce.Products.ProductService(); 157 Dynamicweb.Ecommerce.Products.DetailsGroupService dgs = new Dynamicweb.Ecommerce.Products.DetailsGroupService(); 158 159 List<ewiMediaViewModel> productAssets = new List<ewiMediaViewModel>(); 160 List<Dynamicweb.Ecommerce.Products.Product> products = new List<Dynamicweb.Ecommerce.Products.Product>(); 161 foreach (var language in ecomLanguages) 162 { 163 var productitem = ps.GetProductById(product.Id, product.VariantId, language.LanguageId); 164 if (productitem is object) 165 { 166 Dynamicweb.Ecommerce.Products.DetailService detailService = new Dynamicweb.Ecommerce.Products.DetailService(); 167 168 foreach (var detail in detailService.GetDetails(productitem)) 169 { 170 if (detail.LanguageId == language.LanguageId) 171 { 172 Dynamicweb.Ecommerce.Products.DetailsGroup detailsGroup = dgs.GetById(detail.GroupId); 173 174 if (selectedAssetCategories.Contains(detailsGroup.SystemName)) 175 { 176 // Check if this language is already in activeLanguages before adding 177 if (!activeLanguages.Any(al => al.LanguageId == language.LanguageId)) 178 { 179 activeLanguages.Add(language); 180 } 181 182 ewiMediaViewModel productAsset = new ewiMediaViewModel(); 183 productAsset.Value = detail.Value; 184 productAsset.AssetSystemName = detailsGroup.SystemName; 185 productAsset.LanguageId = detail.LanguageId; 186 productAsset.LanguageName = language.NativeName; 187 productAsset.DisplayName = detail.Name; 188 productAssets.Add(productAsset); 189 } 190 } 191 } 192 } 193 } 194 195 196 @* Standard asset collection (existing logic) *@ 197 string defaultImage = product.DefaultImage != null ? product.DefaultImage.Value : ""; 198 IEnumerable<MediaViewModel> assetsImages = selectedAssetCategories != null ? 199 product.AssetCategories.Where(x => selectedAssetCategories.Contains(x.SystemName)).SelectMany(x => x.Assets) : 200 product.AssetCategories.SelectMany(x => x.Assets); 201 assetsImages = assetsImages.OrderByDescending(x => x.Value.Equals(defaultImage)); 202 IEnumerable<MediaViewModel> assetsList = new MediaViewModel[] { }; 203 assetsList = productAssets.Cast<MediaViewModel>(); 204 assetsList = includeImagePatternImages ? assetsList.Union(product.ImagePatternImages) : assetsList; 205 assetsList = includeImagePatternImages && assetsList.Count() == 0 ? assetsList.Append(product.DefaultImage) : assetsList; 206 bool defaultImageFallback = Model.Item.GetBoolean("DefaultImageFallback"); 207 bool showOnlyPrimaryImage = Model.Item.GetBoolean("ShowOnlyPrimaryImage"); 208 int totalAssets = 0; 209 if (showOnlyPrimaryImage == false) { 210 foreach (MediaViewModel asset in assetsList) { 211 var assetValue = asset.Value; 212 foreach (string format in allSupportedFormats) { 213 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) { 214 totalAssets++; 215 } 216 } 217 } 218 } 219 if ((totalAssets == 0 && product.DefaultImage != null && selectedAssetCategories?.Count() == 0) || (showOnlyPrimaryImage == true && product.DefaultImage != null)) 220 { 221 assetsList = new List<MediaViewModel>(){ product.DefaultImage }; 222 totalAssets = 1; 223 } 224 int videoNumber = 0; 225 @* Layout settings *@ 226 string spacing = Model.Item.GetRawValueString("Spacing", "p-0"); 227 spacing = spacing == "none" ? "p-0" : spacing; 228 spacing = spacing == "small" ? "p-3" : spacing; 229 spacing = spacing == "large" ? "p-5" : spacing; 230 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 231 bool hideThumbnails = Model.Item.GetBoolean("HideThumbnails"); 232 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 233 int modalVideoNumber = 0; 234 @* Get assets from selected categories or get all assets *@ 235 if (totalAssets != 0 && assetsList.Any()) 236 { 237 <div class="@spacing@(theme) item_@Model.Item.SystemName.ToLower()"> 238 @if (!string.IsNullOrEmpty(Model.Item.GetString("Title")) && !Model.Item.GetBoolean("HideTitle")) 239 { 240 string titleFontSize = Model.Item.GetRawValueString("TitleFontSize", "h3"); 241 <h3 class="@titleFontSize mb-3"> 242 @Model.Item.GetString("Title") 243 </h3> 244 } 245 @if (activeLanguages.Count > 1) 246 { 247 @{ 248 // Filter activeLanguages als deze taal assets bevat 249 var languagesWithAssets = new List<Dynamicweb.Ecommerce.International.Language>(); 250 251 foreach (var lang in activeLanguages) 252 { 253 bool hasAssets = false; 254 foreach (MediaViewModel asset in assetsList) 255 { 256 try { 257 if (asset.GetType().GetProperty("LanguageId") != null) 258 { 259 var assetLangId = asset.GetType().GetProperty("LanguageId").GetValue(asset)?.ToString() ?? ""; 260 if (assetLangId == lang.LanguageId) 261 { 262 hasAssets = true; 263 break; 264 } 265 } 266 } catch { } 267 } 268 269 if (hasAssets) 270 { 271 languagesWithAssets.Add(lang); 272 } 273 } 274 275 Dynamicweb.Ecommerce.International.Language currentLanguage = null; 276 string currentLanguageValue = "ALL"; 277 278 // Toon enkel de taal dropdown als er meer dan 1 taal is met assets 279 if (languagesWithAssets.Count > 1) 280 { 281 282 currentLanguage = languagesWithAssets.FirstOrDefault(lang => 283 string.Equals(lang.Culture, siteLanguage, StringComparison.OrdinalIgnoreCase)) ?? 284 languagesWithAssets.FirstOrDefault(lang => 285 string.Equals(lang.NativeName, "English", StringComparison.OrdinalIgnoreCase)) ?? 286 languagesWithAssets.FirstOrDefault(); 287 288 // Map English naar LANG1 289 currentLanguageValue = currentLanguage != null && 290 string.Equals(currentLanguage.NativeName, "English", StringComparison.OrdinalIgnoreCase) 291 ? "LANG1" : currentLanguage?.LanguageId ?? "ALL"; 292 } 293 } 294 295 @if (languagesWithAssets.Count > 1) 296 { 297 <div class="mb-3"> 298 <div class="mb-1">@Translate("Language")</div> 299 <div class="dropdown js-dropdown"> 300 <button class="form-select text-start w-100 js-dropdown-btn" type="button" data-bs-toggle="dropdown" data-bs-auto-close="outside" aria-expanded="false"> 301 @(currentLanguage?.NativeName ?? "All") 302 </button> 303 <div class="dropdown-menu w-100 p-3"> 304 <div class="form-check"> 305 <input class="form-check-input" type="checkbox" name="LanguageId" value="ALL" id="LanguageCheckAll" onchange="filterResults('ALL', event);"> 306 <label class="form-check-label" for="LanguageCheckAll"> 307 @Translate("All") 308 </label> 309 </div> 310 @foreach (var language in languagesWithAssets.GroupBy(l => l.NativeName).Select(g => g.First())) 311 { 312 string languageValue = string.Equals(language.NativeName, "English", StringComparison.OrdinalIgnoreCase) 313 ? "LANG1" : language.LanguageId; 314 bool isCurrentLanguage = language == currentLanguage; 315 <div class="form-check"> 316 <input class="form-check-input" type="checkbox" name="LanguageId" data-short-name="@language.NativeName" value="@languageValue" id="Check_@languageValue" @(isCurrentLanguage ? "checked" : "") onchange="filterResults('@languageValue', event);"> 317 <label class="form-check-label" for="Check_@languageValue"> 318 @language.NativeName 319 </label> 320 </div> 321 } 322 </div> 323 </div> 324 </div> 325 } 326 } 327 <div class="table-responsive"> 328 <table class="table table-hover align-middle mb-0" style="table-layout: fixed;" id="assets-table"> 329 <thead> 330 <tr> 331 @if (!hideThumbnails) 332 { 333 <th style="width:60px">&nbsp;</th> 334 } 335 <th>@Translate("Name")</th> 336 <th>@Translate("Asset type")</th> 337 <th>@Translate("Language")</th> 338 <th class="text-end" style="width:100px">@Translate("File type")</th> 339 <th class="text-end d-none d-lg-table-cell">@Translate("Download")</th> 340 </tr> 341 </thead> 342 <tbody class="border-top-0"> 343 @foreach (ewiMediaViewModel asset in productAssets) 344 { 345 var assetValue = asset.Value; 346 string assetName = !string.IsNullOrEmpty(asset.DisplayName) ? asset.DisplayName : asset.Value.Substring(asset.Value.LastIndexOf('/') + 1); 347 348 // Skip videos 349 bool isVideo = false; 350 foreach (string format in supportedVideoFormats) 351 { 352 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) 353 { 354 isVideo = true; 355 } 356 } 357 358 // Only process non-video files 359 if (!isVideo) 360 { 361 // Check if file exists 362 string filePath = Dynamicweb.Context.Current.Server.MapPath(assetValue); 363 if (File.Exists(filePath)) 364 { 365 // Check if it's a supported format 366 if (allSupportedFormats.Any(format => assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0)) 367 { 368 // Get file extension 369 string fileExtension = Path.GetExtension(assetValue).ToLower(); 370 371 // Map English to LANG1 for filtering 372 string languageId = string.Equals(asset.LanguageName, "English", StringComparison.OrdinalIgnoreCase) ? "LANG1" : asset.LanguageId; 373 374 <tr data-language-ids="@languageId" data-language-name="@asset.LanguageName"> 375 @if (!hideThumbnails) 376 { 377 <td class="px-0"> 378 @{ 379 string productName = product.Name; 380 string imagePath = asset.Value; 381 string imageLinkPath = imagePath; 382 imagePath = $"/Admin/Public/GetImage.ashx?image={imagePath}&width=60&format=webp"; 383 RatioSettings ratioSettings = GetRatioSettings(); 384 } 385 <a href="@imageLinkPath" class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)" download alt="@productName"> 386 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100"> 387 <img loading="lazy" src="@imagePath" class="mw-100 mh-100" alt="@productName" /> 388 </div> 389 </a> 390 </td> 391 } 392 <td> 393 <a href="@assetValue" class="text-decoration-none text-break" download="@assetName" title="@assetName"> 394 @assetName 395 </a> 396 </td> 397 <td>@asset.AssetSystemName</td> 398 <td>@asset.LanguageName</td> 399 <td class="text-end">@fileExtension</td> 400 <td class="text-end d-none d-lg-table-cell"> 401 <a href="@assetValue" class="text-decoration-none" download="@assetName" title="@assetName"> 402 @fileSize KB <div class="icon-2" style="z-index: 1">@ReadFile(iconPath + "download.svg")</div> 403 </a> 404 </td> 405 </tr> 406 } 407 } 408 } 409 } 410 </tbody> 411 </table> 412 </div> 413 <script> 414 function filterResults(selectedLang, event) { 415 console.log('Filtering by language:', selectedLang); 416 417 // Prevent event bubbling 418 if (event) { 419 event.stopPropagation(); 420 } 421 422 const table = document.getElementById('assets-table'); 423 const rows = table.querySelectorAll('tbody tr'); 424 const button = document.querySelector('.js-dropdown-btn'); 425 426 const checkedBoxes = document.querySelectorAll('input[name="LanguageId"]:checked'); 427 const checkedLanguages = Array.from(checkedBoxes).map(cb => cb.value); 428 429 // Handle "All" checkbox behavior - if "All" is checked, uncheck others 430 if (selectedLang === 'ALL') { 431 const allCheckbox = document.querySelector('input[value="ALL"]'); 432 if (allCheckbox && allCheckbox.checked) { 433 // Uncheck all other checkboxes 434 document.querySelectorAll('input[name="LanguageId"]:not([value="ALL"])').forEach(cb => { 435 cb.checked = false; 436 }); 437 } 438 } else { 439 // If any specific language is checked, uncheck "All" 440 const allCheckbox = document.querySelector('input[value="ALL"]'); 441 if (allCheckbox) { 442 allCheckbox.checked = false; 443 } 444 } 445 446 // Re-get checked languages after potential changes 447 const finalCheckedBoxes = document.querySelectorAll('input[name="LanguageId"]:checked'); 448 const finalCheckedLanguages = Array.from(finalCheckedBoxes).map(cb => cb.value); 449 450 // Update button text based on selected languages 451 if (finalCheckedLanguages.length === 0) { 452 button.textContent = '@Translate("All")'; 453 } else if (finalCheckedLanguages.includes('ALL')) { 454 button.textContent = '@Translate("All")'; 455 } else if (finalCheckedLanguages.length === 1) { 456 const selectedCheckbox = document.querySelector(`input[value="${finalCheckedLanguages[0]}"]`); 457 button.textContent = selectedCheckbox ? selectedCheckbox.getAttribute('data-short-name') : 'All'; 458 } else { 459 button.textContent = `${finalCheckedLanguages.length} languages selected`; 460 } 461 462 // Filter table rows 463 rows.forEach(row => { 464 const rowLanguageIds = row.getAttribute('data-language-ids'); 465 const rowLanguageName = row.getAttribute('data-language-name'); 466 467 if (finalCheckedLanguages.length === 0 || finalCheckedLanguages.includes('ALL')) { 468 row.style.display = ''; 469 } else { 470 const shouldShow = rowLanguageIds && finalCheckedLanguages.some(lang => 471 rowLanguageIds === lang || 472 rowLanguageIds === 'ALL' 473 ); 474 475 row.style.display = shouldShow ? '' : 'none'; 476 } 477 }); 478 479 } 480 document.addEventListener('DOMContentLoaded', function() { 481 // Set initial state - apply filter for pre-checked language 482 const currentLangCheckbox = document.querySelector('input[name="LanguageId"]:checked'); 483 if (currentLangCheckbox) { 484 filterResults(currentLangCheckbox.value); 485 } else { 486 // Default to show all if nothing is checked 487 const table = document.getElementById('assets-table'); 488 const rows = table.querySelectorAll('tbody tr'); 489 rows.forEach(row => { 490 row.style.display = ''; 491 }); 492 } 493 }); 494 </script> 495 @foreach (MediaViewModel asset in assetsList) 496 { 497 var assetName = asset.Value.ToLower(); 498 foreach (string videoFormat in supportedVideoFormats) 499 { //Videos 500 if (assetName.IndexOf(videoFormat, StringComparison.OrdinalIgnoreCase) >= 0) 501 { 502 <div class="modal fade js-video-modal" id="modal_@(Model.ID)_@modalVideoNumber" tabindex="-1" aria-labelledby="productDetailsTableModalTitle_@(Model.ID)_@modalVideoNumber" aria-hidden="true"> 503 <div class="modal-dialog modal-dialog-centered modal-xl"> 504 <div class="modal-content"> 505 <div class="modal-header visually-hidden"> 506 <h5 class="modal-title" id="productDetailsTableModalTitle_@(Model.ID)_@modalVideoNumber">@product.Title</h5> 507 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> 508 </div> 509 <div class="modal-body p-2 p-lg-3 h-100"> 510 @{ 511 var videoParams = GetVideoParams(asset, "modal"); 512 @RenderPartial("Components/VideoPlayer.cshtml", new Dynamicweb.Frontend.FileViewModel { Path = asset.Value }, videoParams) 513 } 514 </div> 515 </div> 516 </div> 517 </div> 518 modalVideoNumber++; 519 } 520 } 521 } 522 </div> 523 } 524 else if (Pageview.IsVisualEditorMode) 525 { 526 <div class="h-100 @theme"> 527 <div class="alert alert-dark m-0"> 528 @Translate("No assets are available") 529 </div> 530 </div> 531 } 532 } 533
By clicking 'Accept All' you consent that we may collect information about you for various purposes, including: Statistics and Marketing