diff --git a/static/style.css b/static/style.css index e50cca49..d8958ff4 100644 --- a/static/style.css +++ b/static/style.css @@ -552,3 +552,9 @@ code{ background:var(--panel2); border:1px solid var(--border); border-radius:4p .columnFilterMenu.hidden{ display:none; } .columnFilterOption{ display:flex; align-items:center; gap:6px; padding:4px 6px; border-radius:4px; font-size:12.5px; white-space:nowrap; } .columnFilterOption:hover{ background:var(--panel2); } + +/* ---------- Panneau "Configurer la valeur" (variable Objet/Tableau) ---------- */ +/* La colonne "Clé" n'a de sens que pour un Objet (paires clé/valeur) — un + Tableau n'est qu'une liste de valeurs, voir openVarValuePanel() dans + game_dashboard.html. */ +#varValuePanel[data-mode="tableau"] .varValueKeyField{ display:none; } diff --git a/templates/game_dashboard.html b/templates/game_dashboard.html index c8b9df5d..43a0f41c 100644 --- a/templates/game_dashboard.html +++ b/templates/game_dashboard.html @@ -146,12 +146,13 @@ {% if variables %} @@ -174,7 +175,10 @@ {% if v.type in ('objet', 'tableau') %} - +
+ + +
{% else %} {% endif %} @@ -196,6 +200,56 @@ {% endif %} + + + + + +

Paramètres du jeu

@@ -651,6 +705,19 @@ function toggleDashCreate(tab) { } } +// Barre "+ Créer une variable" : pour un type Objet/Tableau, la valeur de +// départ se configure via le panneau à champs (voir openVarValuePanel) — +// la saisie libre n'a alors plus de sens, remplacée par un aperçu en +// lecture seule + le bouton "🔧 Configurer". +function onVarTypeSelectChange(sel) { + var valueInput = document.getElementById('newVarValue'); + var configureBtn = document.getElementById('newVarConfigureBtn'); + var structured = sel.value === 'objet' || sel.value === 'tableau'; + valueInput.readOnly = structured; + configureBtn.style.display = structured ? '' : 'none'; + if (structured && !valueInput.value) valueInput.value = sel.value === 'objet' ? '{}' : '[]'; +} + // Onglet initial : ?tab=... (utilisé par les liens "crée-en un" ailleurs // dans l'outil, ex. l'éditeur d'écran, pour arriver directement sur le bon // onglet plutôt que de laisser deviner où cliquer). @@ -942,5 +1009,101 @@ function switchObjectPanelTab(btn, tab) { p.classList.toggle('active', p.dataset.optabPanel === tab); }); } + +// ---------- Panneau "Configurer la valeur" (variable Objet/Tableau) ---------- +// Un seul panneau partagé (voir le commentaire sur son HTML) : à +// l'ouverture, mémorise vers quel (targetId) le JSON reconstruit +// devra être réécrit, construit une ligne par clé/élément déjà présent +// dans le JSON actuel de cet , puis "OK" sérialise les lignes et +// referme. +(function () { + var panel = document.getElementById('varValuePanel'); + var rowsWrap = document.getElementById('varValueRows'); + var rowTemplate = document.getElementById('varValueRowTemplate'); + var title = document.getElementById('varValuePanelTitle'); + var hint = document.getElementById('varValuePanelHint'); + + makeFloatPanelDraggable(panel, document.getElementById('varValuePanelHeader')); + makeFloatPanelResizable(panel, document.getElementById('varValuePanelResizeHandle')); + makeFloatPanelFullscreenable(panel, panel.querySelector('.floatPanelFullscreenBtn')); + + function valueTypeOf(v) { + if (typeof v === 'boolean') return 'booleen'; + if (typeof v === 'number') return 'nombre'; + return 'texte'; // texte, et repli pour un objet/tableau imbriqué (non éditable ici, voir addRowFrom) + } + function valueTextOf(v, type) { + if (type === 'booleen') return v ? 'Oui' : 'Non'; + if (typeof v === 'object' && v !== null) return JSON.stringify(v); // imbriqué : préservé tel quel, en texte opaque + return v == null ? '' : String(v); + } + function coerceRowValue(type, text) { + if (type === 'nombre') { var n = parseFloat(text); return isNaN(n) ? 0 : n; } + if (type === 'booleen') return ['oui', 'vrai', '1', 'true'].indexOf(text.trim().toLowerCase()) !== -1; + return text; + } + + function addRowFrom(key, value) { + var clone = rowTemplate.content.cloneNode(true); + var row = clone.querySelector('.varValueRow'); + var type = valueTypeOf(value); + if (key !== null) row.querySelector('.varValueKey').value = key; + row.querySelector('.varValueType').value = type; + row.querySelector('.varValueValue').value = valueTextOf(value, type); + row.querySelector('.varValueRemoveBtn').addEventListener('click', function () { row.remove(); }); + rowsWrap.appendChild(clone); + } + + window.addVarValueRow = function () { + addRowFrom(panel.dataset.mode === 'tableau' ? null : '', ''); + }; + + window.openVarValuePanel = function (targetInputId, mode) { + var input = document.getElementById(targetInputId); + if (!input) return; + panel.dataset.target = targetInputId; + panel.dataset.mode = mode; + rowsWrap.innerHTML = ''; + var parsed; + try { parsed = JSON.parse(input.value || (mode === 'objet' ? '{}' : '[]')); } catch (e) { parsed = mode === 'objet' ? {} : []; } + if (mode === 'tableau') { + title.textContent = '⋮⋮ Configurer le tableau'; + hint.textContent = 'Une ligne par élément — valeurs simples uniquement (pas de tableau/objet imbriqué).'; + (Array.isArray(parsed) ? parsed : []).forEach(function (v) { addRowFrom(null, v); }); + } else { + title.textContent = '⋮⋮ Configurer l\'objet'; + hint.textContent = 'Une ligne par clé — valeurs simples uniquement (pas de tableau/objet imbriqué).'; + Object.keys(parsed || {}).forEach(function (k) { addRowFrom(k, parsed[k]); }); + } + if (!rowsWrap.children.length) window.addVarValueRow(); + panel.classList.remove('hidden'); + panel._fsToggle.enter(); + }; + + window.closeVarValuePanel = function () { + panel.classList.add('hidden'); + }; + + window.applyVarValuePanel = function () { + var mode = panel.dataset.mode; + var result = mode === 'tableau' ? [] : {}; + rowsWrap.querySelectorAll('.varValueRow').forEach(function (row) { + var type = row.querySelector('.varValueType').value; + var value = coerceRowValue(type, row.querySelector('.varValueValue').value); + if (mode === 'tableau') { + result.push(value); + } else { + var key = row.querySelector('.varValueKey').value.trim(); + if (key) result[key] = value; + } + }); + var input = document.getElementById(panel.dataset.target); + if (input) { + input.value = JSON.stringify(result); + input.dispatchEvent(new Event('input', { bubbles: true })); + } + closeVarValuePanel(); + }; +})(); {% endblock %}