From 6528c8a53ad3d1da5e656d55fabdb89a2fced0de Mon Sep 17 00:00:00 2001 From: Prophet731 Date: Thu, 19 Mar 2026 14:07:12 -0500 Subject: [PATCH] fix: restore OS template icons using correct VirtFusion path /img/logo/ The VirtFusion panel serves OS icons at /img/logo/{icon} not /storage/os/{icon}. Restore image loading in both rebuild gallery (module.js) and checkout gallery (hooks.php) with onerror fallback to letter badges. Also restore baseUrl population in hooks.php for checkout page. Co-Authored-By: Claude Opus 4.6 (1M context) --- modules/servers/VirtFusionDirect/hooks.php | 32 ++++++++++++++++--- .../VirtFusionDirect/templates/css/module.css | 5 +++ .../VirtFusionDirect/templates/js/module.js | 19 +++++++++-- 3 files changed, 49 insertions(+), 7 deletions(-) diff --git a/modules/servers/VirtFusionDirect/hooks.php b/modules/servers/VirtFusionDirect/hooks.php index f39e2ca..9064704 100644 --- a/modules/servers/VirtFusionDirect/hooks.php +++ b/modules/servers/VirtFusionDirect/hooks.php @@ -85,8 +85,14 @@ add_hook('ClientAreaFooterOutput', 1, function ($vars) { return null; } + $vfServer = \WHMCS\Database\Capsule::table('tblservers') + ->where('type', 'VirtFusionDirect') + ->where('disabled', 0) + ->first(); + $baseUrl = $vfServer ? rtrim('https://' . $vfServer->hostname, '/') : ''; + $galleryData = [ - 'baseUrl' => '', + 'baseUrl' => $baseUrl, 'categories' => \WHMCS\Module\Server\VirtFusionDirect\Module::groupOsTemplates($templates_data['data'] ?? [], true), ]; @@ -182,7 +188,15 @@ add_hook('ClientAreaFooterOutput', 1, function ($vars) { var catIcon = document.createElement('span'); catIcon.className = 'vf-os-category-icon'; catIcon.style.background = catColor; - catIcon.textContent = (cat.name || '?')[0].toUpperCase(); + if (cat.icon && osGalleryData.baseUrl) { + var catImg = document.createElement('img'); + catImg.src = osGalleryData.baseUrl + '/img/logo/' + encodeURIComponent(cat.icon); + catImg.alt = ''; + catImg.onerror = function() { this.parentNode.textContent = (cat.name || '?')[0].toUpperCase(); }; + catIcon.appendChild(catImg); + } else { + catIcon.textContent = (cat.name || '?')[0].toUpperCase(); + } var catTitle = document.createElement('span'); catTitle.textContent = cat.name + ' (' + cat.templates.length + ')'; @@ -222,9 +236,17 @@ add_hook('ClientAreaFooterOutput', 1, function ($vars) { var iconDiv = document.createElement('div'); iconDiv.className = 'vf-os-icon'; iconDiv.style.background = catColor; - var sp = document.createElement('span'); - sp.textContent = (tpl.name || '?')[0].toUpperCase(); - iconDiv.appendChild(sp); + if (tpl.icon && osGalleryData.baseUrl) { + var tplImg = document.createElement('img'); + tplImg.src = osGalleryData.baseUrl + '/img/logo/' + encodeURIComponent(tpl.icon); + tplImg.alt = ''; + tplImg.onerror = function() { this.parentNode.textContent = ''; var s = document.createElement('span'); s.textContent = (tpl.name || '?')[0].toUpperCase(); this.parentNode.appendChild(s); }; + iconDiv.appendChild(tplImg); + } else { + var sp = document.createElement('span'); + sp.textContent = (tpl.name || '?')[0].toUpperCase(); + iconDiv.appendChild(sp); + } card.appendChild(iconDiv); var labelDiv = document.createElement('div'); diff --git a/modules/servers/VirtFusionDirect/templates/css/module.css b/modules/servers/VirtFusionDirect/templates/css/module.css index 1045860..1bd1a59 100644 --- a/modules/servers/VirtFusionDirect/templates/css/module.css +++ b/modules/servers/VirtFusionDirect/templates/css/module.css @@ -278,6 +278,11 @@ font-size: 0.85rem; flex-shrink: 0; } +.vf-os-category-icon img { + width: 18px; + height: 18px; + object-fit: contain; +} .vf-os-category-arrow { margin-left: auto; font-size: 0.7rem; diff --git a/modules/servers/VirtFusionDirect/templates/js/module.js b/modules/servers/VirtFusionDirect/templates/js/module.js index 3ab82d3..ae18c24 100644 --- a/modules/servers/VirtFusionDirect/templates/js/module.js +++ b/modules/servers/VirtFusionDirect/templates/js/module.js @@ -328,13 +328,22 @@ function vfRenderOsGallery(container, data, hiddenInput) { return; } + var baseUrl = data.baseUrl || ""; + $.each(data.categories, function (ci, category) { var section = $('
').attr("data-category", ci); var brandColor = vfGetBrandColor(category.name); // Accordion header var header = $('
'); - var iconSpan = $('').css("background", brandColor).text((category.name || "?")[0].toUpperCase()); + var iconSpan = $('').css("background", brandColor); + if (category.icon && baseUrl) { + var catImg = $('').attr("src", baseUrl + "/img/logo/" + encodeURIComponent(category.icon)); + catImg.on("error", function () { $(this).replaceWith($('').text((category.name || "?")[0].toUpperCase())); }); + iconSpan.append(catImg); + } else { + iconSpan.text((category.name || "?")[0].toUpperCase()); + } var titleSpan = $('').text(category.name + " (" + category.templates.length + ")"); var arrow = $('' + (ci === 0 ? '▼' : '▶') + ''); header.append(iconSpan).append(titleSpan).append(arrow); @@ -364,7 +373,13 @@ function vfRenderOsGallery(container, data, hiddenInput) { if (tpl.eol) card.addClass("vf-os-card-eol"); var iconDiv = $('
').css("background", brandColor); - iconDiv.append($('').text((tpl.name || "?")[0].toUpperCase())); + if (tpl.icon && baseUrl) { + var tplImg = $('').attr("src", baseUrl + "/img/logo/" + encodeURIComponent(tpl.icon)); + tplImg.on("error", function () { $(this).replaceWith($('').text((tpl.name || "?")[0].toUpperCase())); }); + iconDiv.append(tplImg); + } else { + iconDiv.append($('').text((tpl.name || "?")[0].toUpperCase())); + } card.append(iconDiv); card.append($('
').text(tpl.name));