From a6e896ed890c53effff448957bbecc4efec46e61 Mon Sep 17 00:00:00 2001 From: "a.tolmachev" Date: Sat, 2 May 2026 13:29:46 +0000 Subject: [PATCH] ui: harden wizard shell rendering --- apps/ui/js/wizard-shell.js | 47 +++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/apps/ui/js/wizard-shell.js b/apps/ui/js/wizard-shell.js index 8cbb680..cc835da 100644 --- a/apps/ui/js/wizard-shell.js +++ b/apps/ui/js/wizard-shell.js @@ -1,7 +1,5 @@ (function() { var TOTAL_STEPS = 5; - var CHECK_SVG = ''; - var ARROW_SVG = ''; function tKey(key) { return typeof t === 'function' ? t(key) : key; @@ -23,6 +21,35 @@ return step === 3 ? 'step3-' + window.wizardProtocol + '.html' : 'step' + step + '.html'; } + function buildIconSvg(href, width, height) { + var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + svg.setAttribute('width', String(width)); + svg.setAttribute('height', String(height)); + var use = document.createElementNS('http://www.w3.org/2000/svg', 'use'); + use.setAttribute('href', href); + svg.appendChild(use); + return svg; + } + + function appendHtmlFragment(container, html) { + if (!container) return; + var template = document.createElement('template'); + template.innerHTML = html; + container.appendChild(template.content.cloneNode(true)); + } + + function setContinueButtonContent(button, label) { + if (!button) return; + button.textContent = label + ' '; + button.appendChild( + buildIconSvg( + (window.APP_BASE || '') + 'icons/general/arrow-right.svg#icon', + 13, + 13 + ) + ); + } + function loadStep(step, callback) { var panelId = step === 3 ? step3PanelId() : 'step-panel-' + step; if (document.getElementById(panelId)) { @@ -33,7 +60,7 @@ .then(function(response) { return response.text(); }) .then(function(html) { var container = document.getElementById('step-panel-container'); - if (container) container.insertAdjacentHTML('beforeend', html); + appendHtmlFragment(container, html); if (typeof applyLang === 'function') applyLang(); if (callback) callback(); }) @@ -60,7 +87,15 @@ var status = item.querySelector('.step-status-text'); if (stepNumber < step) { item.classList.add('done'); - if (indicator) indicator.innerHTML = CHECK_SVG; + if (indicator) { + indicator.replaceChildren( + buildIconSvg( + (window.APP_BASE || '') + 'icons/general/check.svg#icon', + 10, + 10 + ) + ); + } if (status) status.textContent = tKey('wizard.status.completed'); } else if (stepNumber === step) { item.classList.add('active'); @@ -91,10 +126,10 @@ if (continueButton) { if (step === TOTAL_STEPS) { var finalLabel = window.wizardMode === 'edit' ? tKey('wizard.button.save_changes') : tKey('wizard.button.create'); - continueButton.innerHTML = finalLabel + ' ' + ARROW_SVG; + setContinueButtonContent(continueButton, finalLabel); continueButton.classList.add('is-final-step'); } else { - continueButton.innerHTML = tKey('wizard.button.continue') + ' ' + ARROW_SVG; + setContinueButtonContent(continueButton, tKey('wizard.button.continue')); continueButton.classList.remove('is-final-step'); } }