Files
williamandClaude Sonnet 5 ccf836f2c5
Build and deploy / test-python (push) Successful in 11m18s
Build and deploy / test-js (push) Successful in 1m16s
Build and deploy / lint-python (push) Successful in 4m24s
Build and deploy / lint-js (push) Successful in 2m51s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped
Build and deploy / sonarqube (push) Successful in 5m30s
Lot 4 modernisation JS (SonarLint) + restauration CI sonarqube non-bloquante
Corrige les findings SonarQube (via SonarLint IDE, fichier par fichier)
sur ~24 fichiers static/js/ : parseFloat/parseInt -> Number.*,
.replace(/x/g,y) -> .replaceAll, .indexOf() -> .includes()/.startsWith(),
getAttribute/setAttribute -> .dataset, tableaux -> Set, x && x.y -> x?.y
(verifie site par site), extraction de template litteraux imbriques,
ternaires imbriquees, refactors de complexite cognitive (S3776) via
tables de dispatch, Object.hasOwn, .at(), et deduplication de fonctions
identiques (S4144). Deux exceptions S2486 documentees/corrigees
(filter-repeater-rows.js) et un cas S2703 de partage inter-scripts
complete (_collisionWizard, trigger-editor.js <-> collision-rules-editor.js).
Details complets dans CODE_QUALITY.md section 5.

Restaure aussi le job CI "sonarqube" (non-bloquant) dans
.gitea/workflows/deploy.yml maintenant que l'instance prod est
operationnelle.

Suites vertes : 276/276 JS (node --test), 591/591 Python (pytest).

SKIP=djlint sur ce commit : hook djlint bloquant sur le backlog H021
(styles inline, 49 occurrences/6 templates) deja documente comme dette
assumee non traitee dans CODE_QUALITY.md section 6, aucun rapport avec
ce commit (aucun template touche ici) - valide explicitement avec
l'utilisateur avant de contourner ce hook.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-18 16:38:29 +02:00

62 lines
2.7 KiB
JavaScript

// object_form.js — ajoute/retire des lignes de champ dans le formulaire de
// définition d'objet, bascule l'affichage du sélecteur "objet lié"
// uniquement quand le type choisi est "relation", et l'affichage des
// bornes mini/maxi (2.2 — bornage automatique) uniquement pour un champ
// numérique.
//
// Tout est enfermé dans une IIFE : cette page est chargée via pjax (voir
// pjax.js), qui rejoue ce script telle-quelle à chaque visite sans
// rechargement complet — une déclaration `const`/`let` au premier niveau
// ferait planter la deuxième exécution ("already declared") et bloquerait
// silencieusement "Ajouter un champ"/"Créer l'objet" dès la deuxième visite
// de cette page dans une même session.
(function () {
var fieldsList = document.getElementById('fieldsList');
var template = document.getElementById('fieldRowTemplate');
var btnAddField = document.getElementById('btnAddField');
var NUMERIC_FIELD_TYPES = new Set(['nombre_entier', 'nombre_decimal']);
function toggle(target, placeholder, visible) {
target.style.display = visible ? '' : 'none';
placeholder.style.display = visible ? 'none' : '';
}
function wireRow(row) {
// Ligne de TABLEAU dense (une ligne = un champ, comme "Champs
// existants" dans object_edit.html) : "Objet lié" et "Mini"/"Maxi"
// gardent toujours leur colonne (jamais masquée, sinon les colonnes
// des différentes lignes ne s'alignent plus) — seul leur CONTENU
// bascule entre le vrai champ de saisie et un espace réservé "—"
// quand il ne s'applique pas au type choisi.
var typeSelect = row.querySelector('.fieldTypeSelect');
var relationTarget = row.querySelector('.relationTarget');
var relationPlaceholder = row.querySelector('.relationPlaceholder');
var boundsTargets = row.querySelectorAll('.boundsTarget');
var boundsPlaceholders = row.querySelectorAll('.boundsPlaceholder');
function syncFieldTypeVisibility() {
var isRelation = typeSelect.value === 'relation';
var isNumeric = NUMERIC_FIELD_TYPES.has(typeSelect.value);
toggle(relationTarget, relationPlaceholder, isRelation);
boundsTargets.forEach(function (el, i) { toggle(el, boundsPlaceholders[i], isNumeric); });
}
typeSelect.addEventListener('change', syncFieldTypeVisibility);
syncFieldTypeVisibility();
row.querySelector('.btnRemoveField').addEventListener('click', function () {
row.remove();
});
}
function addFieldRow() {
var clone = template.content.cloneNode(true);
fieldsList.appendChild(clone);
wireRow(fieldsList.lastElementChild);
}
btnAddField.addEventListener('click', addFieldRow);
// Toujours démarrer avec un premier champ prêt à remplir.
addFieldRow();
})();