Fusionne les 4 pages de création dans le dashboard, retire le titre/BDD
Suite de la demande précédente : les 4 pages autrefois listées dans la barre de navigation n'existent plus en tant que pages séparées — tout vit désormais dans les onglets du tableau de bord (commit précédent) ou, pour la création d'un objet, dans un panneau déplaçable. - screens_list.html + sa route (screens_list) : supprimés (l'onglet "Écrans du jeu" du dashboard couvre déjà tout : créer, réordonner, éditer, supprimer). screen_new/screen_move/screen_delete redirigent maintenant vers le dashboard (tab=screens) au lieu de cette page. - element_types.html : supprimé, mais la route element_types est conservée (GET redirige vers le dashboard, POST — utilisé par la barre de création repliable de l'onglet "Éléments de jeu" — continue de fonctionner). element_type_edit/element_type_delete redirigent aussi vers le dashboard. - game_variables.html + sa route (game_variables) : supprimés (l'onglet "Variables" du dashboard couvre déjà tout). create_global_var/ global_var_edit/global_var_delete redirigent vers le dashboard (tab=variables) au lieu de cette page. - object_form.html : supprimé. La route object_new (POST) est conservée pour traiter la soumission du panneau — voir plus bas — mais ne rend plus de page pour un GET (redirige vers le dashboard). Nouveau panneau déplaçable "Nouvel objet" sur le dashboard (bouton "+ Nouvel objet" de l'onglet Objets) : réutilise .floatPanel/ .floatPanelHeader/.floatPanelBody (déjà utilisées dans l'éditeur d'écran) avec une nouvelle variante centrée (.floatPanel--center) et son propre glisser-déposer minimal (pas de position persistée, contrairement aux panneaux de l'éditeur d'écran — inutile pour un panneau ouvert ponctuellement). Contenu et script (object_form.js) repris tels quels de l'ancienne page. base.html : la barre de navigation du jeu n'a donc plus que 2 liens — "📊 Tableau de bord" (nouveau) et "▶️ Jouer" (toujours en dernier). game_dashboard.html : titre du jeu et chemin de la base de données retirés (redondants avec le nom déjà visible dans l'onglet du navigateur/la barre de nav). Les liens "crée-en un"/"gérer les variables" dans l'éditeur d'écran (screen_edit.html) pointent maintenant vers le dashboard avec le bon onglet (?tab=...), lu et appliqué au chargement de la page (switchDashTab() côté JS). 2 tests (test_screens_and_elements.py) mis à jour : ils vérifiaient le contenu des pages supprimées (element-types, screens) — adaptés pour vérifier la même chose sur le dashboard, qui porte maintenant cette information. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
65450a5719
commit
d875557254
@@ -2,8 +2,6 @@
|
||||
{% block title %}{{ game.name }} — Forge Engine{% endblock %}
|
||||
{% block content_class %}content-wide{% endblock %}
|
||||
{% block content %}
|
||||
<h1 class="title">{{ game.name }}</h1>
|
||||
<p class="hint mb-3">Base de données : projects/{{ game.slug }}/game.db</p>
|
||||
|
||||
<!-- Une seule fenêtre, un onglet par catégorie (même principe que les
|
||||
onglets "Écran / Logique / Timeline" de l'éditeur d'écran, voir
|
||||
@@ -20,6 +18,11 @@
|
||||
|
||||
<!-- ---------- Écrans ---------- -->
|
||||
<div class="builderTabPanel active" data-tab-panel="screens">
|
||||
{% if request.args.get('blocked_screen') %}
|
||||
<div class="warningBanner">
|
||||
⚠️ Suppression impossible : au moins un autre écran a un bouton qui cible précisément celui-ci. Retire d'abord cette action.
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="dashPanelHeader">
|
||||
<h2>Écrans du jeu</h2>
|
||||
<button type="button" class="button is-small primary" onclick="toggleDashCreate('screens')">+ Créer un écran</button>
|
||||
@@ -63,9 +66,8 @@
|
||||
<div class="builderTabPanel" data-tab-panel="objects">
|
||||
<div class="dashPanelHeader">
|
||||
<h2>Objets</h2>
|
||||
<a class="button is-small primary" href="{{ url_for('object_new', slug=game.slug) }}">+ Nouvel objet</a>
|
||||
<button type="button" class="button is-small primary" onclick="openNewObjectPanel()">+ Nouvel objet</button>
|
||||
</div>
|
||||
<p class="hint mb-2">Un objet a des champs typés (nombre, texte, relation...) — sa création se fait sur sa propre page.</p>
|
||||
{% if definitions %}
|
||||
<div class="fieldsTableWrap">
|
||||
<table class="table is-fullwidth is-hoverable fieldsTable">
|
||||
@@ -203,6 +205,104 @@
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- ---------- Panneau déplaçable : nouvel objet ---------- -->
|
||||
<!-- Réutilise .floatPanel/.floatPanelHeader/.floatPanelBody (éditeur
|
||||
d'écran, voir style.css) pour la même sensation de fenêtre flottante
|
||||
qu'ailleurs dans l'outil, avec sa propre variante centrée
|
||||
(.floatPanel--center) et son propre glisser-déposer minimal (pas de
|
||||
position persistée en localStorage ici, contrairement aux panneaux de
|
||||
l'éditeur d'écran — inutile pour un panneau ouvert ponctuellement).
|
||||
Contenu repris de l'ancienne page "Définir un nouvel objet"
|
||||
(object_form.html, retirée) : même formulaire, même gabarit de ligne
|
||||
de champ, même script (object_form.js). -->
|
||||
<div class="floatPanel floatPanel--center hidden" id="newObjectPanel">
|
||||
<div class="floatPanelHeader" id="newObjectPanelHeader">
|
||||
<span class="floatPanelTitle">⋮⋮ Nouvel objet</span>
|
||||
<button type="button" class="button is-small" onclick="closeNewObjectPanel()">✕</button>
|
||||
</div>
|
||||
<div class="floatPanelBody">
|
||||
<form method="post" action="{{ url_for('object_new', slug=game.slug) }}" id="objectForm" class="formPassthrough">
|
||||
<div class="formField">
|
||||
<label for="object_name">Nom de l'objet (ex. Personnage, Niveau, Question...)</label>
|
||||
<input type="text" id="object_name" name="object_name" required autocomplete="off">
|
||||
</div>
|
||||
<h2 style="margin-top:16px;">Champs</h2>
|
||||
<button type="button" class="button is-outlined is-fullwidth mb-2" id="btnAddField">+ Ajouter un champ</button>
|
||||
<div id="fieldsList"></div>
|
||||
<div class="actionsRow"><button type="submit" class="primary">Créer l'objet</button></div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template id="fieldRowTemplate">
|
||||
<div class="fieldRowCard box">
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
<div class="field">
|
||||
<label class="label">Nom du champ</label>
|
||||
<div class="control"><input class="input" type="text" name="field_name[]" placeholder="ex. nom, description, pv..." required></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column">
|
||||
<div class="field">
|
||||
<label class="label">Type</label>
|
||||
<div class="control">
|
||||
<div class="select is-fullwidth">
|
||||
<select name="field_type[]" class="fieldTypeSelect">
|
||||
{% for key, val in field_types.items() %}
|
||||
<option value="{{ key }}">{{ val.label }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="relationTarget field" style="display:none;">
|
||||
<label class="label">Objet lié</label>
|
||||
<div class="control">
|
||||
<div class="select is-fullwidth">
|
||||
<select name="field_relation[]">
|
||||
{% for d in definitions %}
|
||||
<option value="{{ d.id }}">{{ d.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{% if not definitions %}
|
||||
<p class="help">Aucun autre objet défini.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="boundsTarget columns" style="display:none;">
|
||||
<div class="column">
|
||||
<div class="field">
|
||||
<label class="label">Valeur mini</label>
|
||||
<div class="control"><input class="input" type="number" step="any" name="field_min[]" placeholder="ex. 0"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column">
|
||||
<div class="field">
|
||||
<label class="label">Valeur maxi</label>
|
||||
<div class="control"><input class="input" type="number" step="any" name="field_max[]" placeholder="ex. 100"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label">Obligatoire ?</label>
|
||||
<div class="control">
|
||||
<div class="select is-fullwidth">
|
||||
<select name="field_required[]">
|
||||
<option value="0">Non</option>
|
||||
<option value="1">Oui</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="button is-small is-danger btnRemoveField">🗑️ Retirer ce champ</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script src="{{ url_for('static', filename='object_form.js') }}"></script>
|
||||
<script>
|
||||
function switchDashTab(tab) {
|
||||
document.querySelectorAll('#dashTabs .builderTabBtn').forEach(function (btn) {
|
||||
@@ -220,5 +320,49 @@ function toggleDashCreate(tab) {
|
||||
if (firstInput) firstInput.focus();
|
||||
}
|
||||
}
|
||||
|
||||
// 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).
|
||||
(function () {
|
||||
var requestedTab = {{ (request.args.get('tab') or '')|tojson }};
|
||||
if (requestedTab) switchDashTab(requestedTab);
|
||||
})();
|
||||
|
||||
// ---------- Panneau déplaçable "Nouvel objet" ----------
|
||||
(function () {
|
||||
var panel = document.getElementById('newObjectPanel');
|
||||
var header = document.getElementById('newObjectPanelHeader');
|
||||
var dragging = false, offsetX = 0, offsetY = 0;
|
||||
|
||||
window.openNewObjectPanel = function () {
|
||||
panel.classList.remove('hidden');
|
||||
};
|
||||
window.closeNewObjectPanel = function () {
|
||||
panel.classList.add('hidden');
|
||||
};
|
||||
|
||||
header.addEventListener('mousedown', function (e) {
|
||||
if (e.target.closest('button')) return;
|
||||
dragging = true;
|
||||
var rect = panel.getBoundingClientRect();
|
||||
panel.style.left = rect.left + 'px';
|
||||
panel.style.top = rect.top + 'px';
|
||||
panel.style.right = 'auto';
|
||||
panel.style.transform = 'none';
|
||||
offsetX = e.clientX - rect.left;
|
||||
offsetY = e.clientY - rect.top;
|
||||
document.body.style.userSelect = 'none';
|
||||
});
|
||||
document.addEventListener('mousemove', function (e) {
|
||||
if (!dragging) return;
|
||||
panel.style.left = (e.clientX - offsetX) + 'px';
|
||||
panel.style.top = (e.clientY - offsetY) + 'px';
|
||||
});
|
||||
document.addEventListener('mouseup', function () {
|
||||
dragging = false;
|
||||
document.body.style.userSelect = '';
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user