Dev #2
@@ -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; }
|
||||
|
||||
@@ -146,12 +146,13 @@
|
||||
</div>
|
||||
<form method="post" action="{{ url_for('create_global_var', slug=game.slug) }}" class="dashCreateBar" id="dashCreate-variables" style="display:none;">
|
||||
<input type="text" name="name" placeholder="Nom (ex. porte_ouverte)" required autocomplete="off">
|
||||
<select name="type">
|
||||
<select id="newVarType" name="type" onchange="onVarTypeSelectChange(this)">
|
||||
{% for key, val in variable_types.items() %}
|
||||
<option value="{{ key }}">{{ val.label }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<textarea name="default_value" placeholder="Valeur de départ (JSON pour Objet/Tableau, ex. {} ou [])" rows="1"></textarea>
|
||||
<input type="text" id="newVarValue" name="default_value" placeholder="Valeur de départ">
|
||||
<button type="button" id="newVarConfigureBtn" class="button is-small" style="display:none;" onclick="openVarValuePanel('newVarValue', document.getElementById('newVarType').value)">🔧 Configurer la valeur</button>
|
||||
<button type="submit" class="primary">Créer</button>
|
||||
</form>
|
||||
{% if variables %}
|
||||
@@ -174,7 +175,10 @@
|
||||
</td>
|
||||
<td>
|
||||
{% if v.type in ('objet', 'tableau') %}
|
||||
<textarea form="varEditForm{{ v.id }}" name="value" rows="3" aria-label="Valeur de « {{ v.name }} »">{{ v.value or '' }}</textarea>
|
||||
<div class="fieldRow" style="align-items:center;">
|
||||
<input type="text" form="varEditForm{{ v.id }}" name="value" id="varValue-{{ v.id }}" value="{{ v.value or '' }}" readonly aria-label="Valeur de « {{ v.name }} »">
|
||||
<button type="button" class="button is-small" onclick="openVarValuePanel('varValue-{{ v.id }}', '{{ v.type }}')">🔧 Configurer</button>
|
||||
</div>
|
||||
{% else %}
|
||||
<input type="text" form="varEditForm{{ v.id }}" name="value" value="{{ v.value or '' }}" aria-label="Valeur de « {{ v.name }} »">
|
||||
{% endif %}
|
||||
@@ -196,6 +200,56 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- ---------- Panneau "Configurer la valeur" (variable Objet/Tableau) ---------- -->
|
||||
<!-- Un seul panneau partagé (pas un par variable) : une seule valeur à la
|
||||
fois peut être en cours d'édition. openVarValuePanel(targetInputId,
|
||||
mode) mémorise vers quel <input> écrire le JSON reconstruit (celui de
|
||||
la barre de création, ou celui, en lecture seule, de la ligne d'une
|
||||
variable existante) — pas de JSON à taper à la main : une ligne par
|
||||
clé (Objet) ou par élément (Tableau), avec un type (Texte/Nombre/
|
||||
Oui-Non) qui pilote comment la valeur est encodée en JSON. Ne gère
|
||||
que des valeurs SIMPLES (pas d'objet/tableau imbriqué) — largement
|
||||
suffisant pour une configuration ou une liste, et ça reste lisible
|
||||
pour qui ne connaît pas JSON. -->
|
||||
<div class="floatPanel floatPanel--center hidden" id="varValuePanel">
|
||||
<div class="floatPanelHeader" id="varValuePanelHeader">
|
||||
<span class="floatPanelTitle" id="varValuePanelTitle">⋮⋮ Configurer la valeur</span>
|
||||
<button type="button" class="button is-small floatPanelFullscreenBtn" title="Plein écran">⛶</button>
|
||||
<button type="button" class="button is-small" onclick="closeVarValuePanel()">✕</button>
|
||||
</div>
|
||||
<div class="floatPanelBody">
|
||||
<p class="hint mb-2" id="varValuePanelHint"></p>
|
||||
<button type="button" class="button is-outlined is-fullwidth mb-2" onclick="addVarValueRow()">+ Ajouter</button>
|
||||
<div id="varValueRows"></div>
|
||||
<div class="actionsRow"><button type="button" class="primary" onclick="applyVarValuePanel()">OK — utiliser cette valeur</button></div>
|
||||
</div>
|
||||
<div class="floatPanelResizeHandle" id="varValuePanelResizeHandle"></div>
|
||||
</div>
|
||||
|
||||
<template id="varValueRowTemplate">
|
||||
<div class="fieldRowCard box varValueRow">
|
||||
<div class="fieldRow">
|
||||
<div class="formField varValueKeyField">
|
||||
<label>Clé</label>
|
||||
<input type="text" class="varValueKey" placeholder="ex. nom, degats...">
|
||||
</div>
|
||||
<div class="formField">
|
||||
<label>Type</label>
|
||||
<select class="varValueType">
|
||||
<option value="texte">Texte</option>
|
||||
<option value="nombre">Nombre</option>
|
||||
<option value="booleen">Oui / Non</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="formField" style="flex:2;">
|
||||
<label>Valeur</label>
|
||||
<input type="text" class="varValueValue" placeholder="ex. Alice, 12, Oui...">
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="button is-small is-danger varValueRemoveBtn">🗑️ Retirer</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="dangerZone dashDangerZone">
|
||||
<h3>Paramètres du jeu</h3>
|
||||
<form method="post" action="{{ url_for('game_rename', slug=game.slug) }}">
|
||||
@@ -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 <input> (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 <input>, 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();
|
||||
};
|
||||
})();
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user