Files
Forge-Engine/templates/object_edit.html
T
williamandClaude Sonnet 5 8f45169209 Retire le fil d'Ariane, centre/réordonne la barre de nav, refait le dashboard
Trois demandes distinctes de l'utilisateur, regroupées car elles touchent
toutes à la navigation d'un jeu :

1. Fil d'Ariane retiré (devenu redondant avec la barre de navigation du
   jeu ajoutée au commit précédent) : bloc breadcrumb_wrap retiré de
   base.html, et son override ({% block breadcrumb %}) retiré des 9
   templates qui le définissaient encore. .breadcrumbBar (CSS) retiré,
   y compris des règles flex:0 0 auto de body.objectEditBody/builderBody.

2. Liens de .gameNavBar centrés (justify-content:center).

3. "Jouer" déplacé en dernier lien (c'est une action à part — ouvre
   l'aperçu jouable dans un nouvel onglet — pas un éditeur de plus comme
   les 4 autres).

4. game_dashboard.html devient un vrai tableau de bord : une grille de
   cartes (Écrans/Objets/Éléments de jeu/Variables), chacune listant les
   entrées existantes avec un accès direct (clic = éditeur concerné) et
   un lien "Gérer" vers la page dédiée pour créer/réorganiser. Remplace
   l'ancien panneau "Créer" (redondant avec la barre de navigation
   persistante) et la simple table "Objets définis". routes/games/
   game_dashboard.py alimente maintenant aussi screen_list, element_types
   (+ usage) et variables, en réutilisant list_screens/
   list_element_types/element_type_usage_count/list_global_variables déjà
   utilisés ailleurs.

Vérifié en rendant toutes les pages concernées via le client de test
Flask : barre de nav présente partout où un `game` est dans le contexte
(absente sur l'accueil), fil d'Ariane absent partout, ordre des liens
avec "Jouer" en dernier.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-27 10:04:09 +02:00

190 lines
8.4 KiB
HTML

{% extends "base.html" %}
{% block title %}Modifier {{ definition.name }} — {{ game.name }}{% endblock %}
{% block content_class %}content-wide content-objectEdit{% endblock %}
{% block body_class %}objectEditBody{% endblock %}
{% block content %}
<h1 class="title">Modifier l'objet « {{ definition.name }} »</h1>
<p class="help mb-4">Table SQL : {{ definition.table_name }}</p>
<form method="post" class="field has-addons">
<div class="control is-expanded">
<label class="label" for="object_name">Nom de l'objet</label>
<input class="input" type="text" id="object_name" name="object_name" value="{{ definition.name }}" required>
</div>
<div class="control" style="align-self:flex-end;">
<button type="submit" class="button">Renommer</button>
</div>
</form>
<div class="twoCol">
<!-- Colonne de gauche : ajouter un champ + supprimer l'objet -->
<div class="colLeft">
<h2 class="subtitle">Ajouter un champ</h2>
<form method="post" action="{{ url_for('object_field_add', slug=game.slug, definition_id=definition.id) }}" class="box" id="addFieldForm">
<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 class="field">
<label class="label">Type</label>
<div class="control">
<div class="select is-fullwidth">
<select name="field_type" id="newFieldType">
{% for key, val in field_types.items() %}
<option value="{{ key }}">{{ val.label }}</option>
{% endfor %}
</select>
</div>
</div>
</div>
<div id="newFieldRelationWrap" class="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 existing_definitions %}
<option value="{{ d.id }}">{{ d.name }}</option>
{% endfor %}
</select>
</div>
</div>
{% if not existing_definitions %}
<p class="help">Aucun autre objet défini.</p>
{% endif %}
</div>
<div id="newFieldBoundsWrap" class="columns" style="display:none;">
<div class="column">
<div class="field">
<label class="label">Valeur mini (optionnel)</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 (optionnel)</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>
<div class="field"><button type="submit" class="button is-primary">+ Ajouter ce champ</button></div>
</form>
<div class="box has-background-danger-dark mt-4">
<h3 class="title is-6 has-text-danger-light">Supprimer cet objet</h3>
<form method="post" action="{{ url_for('object_delete', slug=game.slug, definition_id=definition.id) }}"
onsubmit="return confirm('Supprimer définitivement l\'objet « {{ definition.name }} », sa table et toutes ses données ? Cette action est irréversible.');">
<button type="submit" class="button is-danger">🗑️ Supprimer l'objet « {{ definition.name }} »</button>
</form>
</div>
</div>
<!-- Colonne de droite : champs existants, chacun modifiable -->
<div class="colRight">
<h2 class="subtitle">Champs existants</h2>
{% if definition.fields %}
{% for f in definition.fields %}
<form method="post" action="{{ url_for('object_field_edit', slug=game.slug, definition_id=definition.id, field_id=f.id) }}" id="fieldEditForm{{ f.id }}"></form>
<form method="post" action="{{ url_for('object_field_delete', slug=game.slug, definition_id=definition.id, field_id=f.id) }}" id="fieldDeleteForm{{ f.id }}"
onsubmit="return confirm('Retirer le champ « {{ f.name }} » ? Les données déjà enregistrées dans ce champ seront perdues.');"></form>
{% endfor %}
<div class="fieldsTableWrap">
<table class="table is-fullwidth is-hoverable fieldsTable">
<thead>
<tr>
<th>Nom du champ</th>
<th>Type</th>
<th>Objet lié</th>
<th>Mini</th>
<th>Maxi</th>
<th>Obligatoire ?</th>
<th></th>
</tr>
</thead>
<tbody>
{% for f in definition.fields %}
<tr>
<td><input class="input is-small" type="text" form="fieldEditForm{{ f.id }}" name="field_name" value="{{ f.name }}" aria-label="Nom du champ « {{ f.name }} »" required></td>
<td>{{ field_types.get(f.type, {}).get('label', f.type) }}</td>
<td>
{% if f.type == 'relation' %}
<div class="select is-small">
<select form="fieldEditForm{{ f.id }}" name="field_relation" aria-label="Objet lié pour « {{ f.name }} »">
{% for d in existing_definitions %}
<option value="{{ d.id }}" {{ 'selected' if d.id == f.relation_definition_id else '' }}>{{ d.name }}</option>
{% endfor %}
</select>
</div>
{% else %}
<span class="has-text-grey">—</span>
{% endif %}
</td>
<td>
{% if f.type in ('nombre_entier', 'nombre_decimal') %}
<input class="input is-small" type="number" step="any" form="fieldEditForm{{ f.id }}" name="field_min" value="{{ f.min_value if f.min_value is not none else '' }}" placeholder="ex. 0" aria-label="Valeur mini pour « {{ f.name }} »">
{% else %}
<span class="has-text-grey">—</span>
{% endif %}
</td>
<td>
{% if f.type in ('nombre_entier', 'nombre_decimal') %}
<input class="input is-small" type="number" step="any" form="fieldEditForm{{ f.id }}" name="field_max" value="{{ f.max_value if f.max_value is not none else '' }}" placeholder="ex. 100" aria-label="Valeur maxi pour « {{ f.name }} »">
{% else %}
<span class="has-text-grey">—</span>
{% endif %}
</td>
<td>
<div class="select is-small">
<select form="fieldEditForm{{ f.id }}" name="field_required" aria-label="« {{ f.name }} » obligatoire ?">
<option value="0" {{ 'selected' if not f.required else '' }}>Non</option>
<option value="1" {{ 'selected' if f.required else '' }}>Oui</option>
</select>
</div>
</td>
<td class="fieldsTableActions">
<button type="submit" form="fieldEditForm{{ f.id }}" class="button is-small">Enregistrer</button>
<button type="submit" form="fieldDeleteForm{{ f.id }}" class="button is-small is-danger">🗑️</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<p class="help">Mini/Maxi (bornage automatique) : laisser vide = pas de limite. S'applique à "Donner cette valeur", "Augmenter de..." et "Diminuer de..." dans le graphe de logique.</p>
{% else %}
<p class="help">Aucun champ pour l'instant.</p>
{% endif %}
</div>
</div>
<script>
(function(){
var sel = document.getElementById('newFieldType');
var relWrap = document.getElementById('newFieldRelationWrap');
var boundsWrap = document.getElementById('newFieldBoundsWrap');
var NUMERIC_TYPES = ['nombre_entier', 'nombre_decimal'];
function sync(){
relWrap.style.display = sel.value === 'relation' ? 'block' : 'none';
boundsWrap.style.display = NUMERIC_TYPES.indexOf(sel.value) !== -1 ? 'flex' : 'none';
}
sel.addEventListener('change', sync);
sync();
})();
</script>
{% endblock %}