Enhance bib production fields by implementing a new builder for Face, Endos, and Info selections. Update UI components and backend logic for improved data handling, including serialization of field keys and sides. Increment version code to 4.72.873.

This commit is contained in:
2026-07-27 18:00:17 -04:00
parent b5d2938d5e
commit e1610ee19c
5 changed files with 297 additions and 224 deletions

View File

@ -4078,92 +4078,112 @@ a.ms1-trad-link.btn-aide-trad{
padding-top:12px;
}
/* MSIN-4515 — Champs Excel imprimeur (Face bleu / Endos rouge / Info blanc) */
/* MSIN-4515 — Champs Excel imprimeur : titre épreuve, ligne Face, + liste */
#module-bib .bib-production-fields{
margin-top:16px;
}
#module-bib .bib-production-fields-intro{
margin-bottom:10px;
margin-bottom:14px;
}
#module-bib .bib-production-fields-legend{
display:flex;
flex-wrap:wrap;
gap:8px 18px;
margin:0 0 16px;
padding:10px 12px;
background:#f5f9ff;
border:1px solid #c5d9f5;
border-left:4px solid #2f5fd0;
border-radius:6px;
font-size:13px;
}
#module-bib .bib-production-fields-legend li{
display:inline-flex;
align-items:center;
gap:8px;
margin:0;
}
#module-bib .bib-prod-swatch{
width:16px;
height:16px;
border-radius:3px;
border:1px solid rgba(0,0,0,.2);
flex:0 0 auto;
}
#module-bib .bib-prod-swatch--face{ background:#5B9BD5; }
#module-bib .bib-prod-swatch--endos{ background:#C00000; }
#module-bib .bib-prod-swatch--info{ background:#fff; }
#module-bib .bib-prod-swatch--none{
background:repeating-linear-gradient(
-45deg,
#f1f1f1,
#f1f1f1 3px,
#ddd 3px,
#ddd 6px
);
}
#module-bib .bib-prod-fields-group{
border:0;
margin:0 0 12px;
#module-bib .bib-prod-fields-epr{
margin:0 0 20px;
padding:0;
}
#module-bib .bib-prod-fields-epr-title{
margin:0 0 10px;
padding:0;
font-size:16px;
font-weight:700;
color:#1a3a6b;
}
#module-bib .bib-prod-builder-list{
display:flex;
flex-direction:column;
gap:10px;
gap:8px;
margin-bottom:8px;
}
#module-bib .bib-prod-builder-row{
display:flex;
flex-wrap:wrap;
align-items:center;
gap:8px 12px;
padding:10px 12px;
padding:8px 10px;
background:#fff;
border:1px solid #e9ecef;
border-radius:6px;
}
#module-bib .bib-prod-builder-field{
flex:1 1 220px;
min-width:180px;
max-width:360px;
#module-bib .bib-prod-builder-label{
flex:1 1 auto;
min-width:120px;
font-size:14px;
font-weight:600;
color:#212529;
}
#module-bib .bib-prod-builder-side-pill{
flex:0 0 auto;
cursor:default;
}
#module-bib .bib-prod-builder-add{
margin-top:4px;
margin-top:2px;
min-width:36px;
}
#module-bib .bib-prod-builder-remove{
margin-left:auto;
}
#module-bib .bib-prod-field-sides{
display:inline-flex;
#module-bib .bib-prod-add-panel{
margin-top:10px;
padding:12px;
background:#f5f9ff;
border:1px solid #c5d9f5;
border-radius:6px;
}
#module-bib .bib-prod-add-panel__title{
margin:0 0 8px;
font-size:13px;
font-weight:600;
color:#1a3a6b;
}
#module-bib .bib-prod-add-choices{
display:flex;
flex-direction:column;
gap:4px;
margin:0 0 10px;
max-height:220px;
overflow:auto;
}
#module-bib .bib-prod-add-choice{
display:block;
width:100%;
text-align:left;
padding:8px 10px;
border:1px solid #dee2e6;
border-radius:4px;
background:#fff;
font-size:13px;
color:#212529;
cursor:pointer;
}
#module-bib .bib-prod-add-choice:hover,
#module-bib .bib-prod-add-choice:focus{
border-color:#5B9BD5;
outline:none;
}
#module-bib .bib-prod-add-choice.is-selected{
border-color:#2f5fd0;
background:#e8f0fe;
font-weight:600;
}
#module-bib .bib-prod-add-sides{
display:flex;
flex-wrap:wrap;
gap:6px;
gap:8px;
}
#module-bib .bib-prod-field-side{
display:inline-flex;
align-items:center;
gap:4px;
margin:0;
padding:4px 10px;
padding:6px 12px;
border:1px solid #ced4da;
border-radius:4px;
font-size:12px;
@ -4173,21 +4193,22 @@ a.ms1-trad-link.btn-aide-trad{
color:#495057;
user-select:none;
}
#module-bib .bib-prod-field-side-input{
position:absolute;
opacity:0;
pointer-events:none;
}
#module-bib .bib-prod-add-side.bib-prod-field-side--face,
#module-bib .bib-prod-builder-side-pill.bib-prod-field-side--face,
#module-bib .bib-prod-field-side--face.is-selected{
background:#5B9BD5;
border-color:#3d7eae;
color:#fff;
}
#module-bib .bib-prod-add-side.bib-prod-field-side--endos,
#module-bib .bib-prod-builder-side-pill.bib-prod-field-side--endos,
#module-bib .bib-prod-field-side--endos.is-selected{
background:#C00000;
border-color:#8a0000;
color:#fff;
}
#module-bib .bib-prod-add-side.bib-prod-field-side--info,
#module-bib .bib-prod-builder-side-pill.bib-prod-field-side--info,
#module-bib .bib-prod-field-side--info.is-selected{
background:#fff;
border-color:#6c757d;

View File

@ -2037,6 +2037,25 @@
// MSIN-4469 — Le téléchargement part dans un nouvel onglet;
// lécran principal revient aussitôt à Quantités et assignation.
// MSIN-4515 — Serialize data-field-key / data-field-side (pas de select).
function bibProdFieldsPanel() {
return moduleBib.querySelector('.bib-production-fields');
}
function bibProdFieldsLabel(attr, fallback) {
var panel = bibProdFieldsPanel();
var val = panel ? panel.getAttribute(attr) : '';
return val || fallback;
}
function bibProdEscapeHtml(str) {
return String(str == null ? '' : str)
.replace(/&/g, '&')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;');
}
function bibProdFieldsSerializeBody() {
var body = '';
var fieldsForm = moduleBib.querySelector('#bib-production-fields-form');
@ -2045,10 +2064,8 @@
}
fieldsForm.querySelectorAll('.bib-prod-builder-row').forEach(function (row) {
var eprId = row.getAttribute('data-epr-id') || '';
var sel = row.querySelector('.bib-prod-builder-field');
var sideInput = row.querySelector('.bib-prod-field-side-input:checked');
var key = sel ? String(sel.value || '') : '';
var side = sideInput ? String(sideInput.value || '') : '';
var key = String(row.getAttribute('data-field-key') || '');
var side = String(row.getAttribute('data-field-side') || '');
if (!eprId || !key || !side) {
return;
}
@ -2061,37 +2078,60 @@
if (!eprId) {
return;
}
if (!section.querySelector('.bib-prod-builder-row .bib-prod-builder-field')) {
if (!section.querySelector('.bib-prod-builder-row[data-field-key]')) {
body += '&' + encodeURIComponent('prod_fields[' + eprId + '][_empty]') + '=';
}
});
return body;
}
function bibProdBuilderRefreshOptionDisabled(section) {
function bibProdBuilderUsedKeys(section) {
var used = {};
if (!section) {
return used;
}
section.querySelectorAll('.bib-prod-builder-row').forEach(function (row) {
var key = row.getAttribute('data-field-key');
if (key) {
used[key] = true;
}
});
return used;
}
function bibProdBuilderClosePanel(section) {
if (!section) {
return;
}
var used = {};
section.querySelectorAll('.bib-prod-builder-field').forEach(function (sel) {
if (sel.value) {
used[sel.value] = true;
}
});
section.querySelectorAll('.bib-prod-builder-field').forEach(function (sel) {
Array.prototype.forEach.call(sel.options, function (opt) {
if (!opt.value) {
opt.disabled = false;
return;
}
opt.disabled = !!(used[opt.value] && opt.value !== sel.value);
});
});
var panel = section.querySelector('.bib-prod-add-panel');
var addBtn = section.querySelector('.bib-prod-builder-add');
var sides = section.querySelector('.bib-prod-add-sides');
var choices = section.querySelector('.bib-prod-add-choices');
if (panel) {
panel.hidden = true;
panel.removeAttribute('data-pending-key');
panel.removeAttribute('data-pending-label');
}
if (sides) {
sides.hidden = true;
}
if (choices) {
choices.innerHTML = '';
}
if (addBtn) {
addBtn.setAttribute('aria-expanded', 'false');
}
}
function bibProdBuilderAddRow(section) {
var list = section.querySelector('.bib-prod-builder-list');
if (!list) {
function bibProdBuilderOpenPanel(section) {
if (!section) {
return;
}
var panel = section.querySelector('.bib-prod-add-panel');
var choices = section.querySelector('.bib-prod-add-choices');
var sides = section.querySelector('.bib-prod-add-sides');
var addBtn = section.querySelector('.bib-prod-builder-add');
if (!panel || !choices) {
return;
}
var options = [];
@ -2100,62 +2140,56 @@
} catch (err) {
options = [];
}
if (!options.length) {
var used = bibProdBuilderUsedKeys(section);
choices.innerHTML = '';
options.forEach(function (opt) {
if (!opt || !opt.key || used[opt.key]) {
return;
}
var li = document.createElement('li');
var btn = document.createElement('button');
btn.type = 'button';
btn.className = 'bib-prod-add-choice';
btn.setAttribute('data-key', String(opt.key));
btn.setAttribute('data-label', String(opt.label || opt.key));
btn.textContent = String(opt.label || opt.key);
li.appendChild(btn);
choices.appendChild(li);
});
if (sides) {
sides.hidden = true;
}
panel.removeAttribute('data-pending-key');
panel.removeAttribute('data-pending-label');
panel.hidden = false;
if (addBtn) {
addBtn.setAttribute('aria-expanded', 'true');
}
}
function bibProdBuilderAppendRow(section, key, label, side) {
var list = section.querySelector('.bib-prod-builder-list');
if (!list || !key || !side) {
return;
}
var eprId = section.getAttribute('data-epr-id') || '';
var idx = list.querySelectorAll('.bib-prod-builder-row').length;
var rowId = 'prod_row_' + eprId + '_' + Date.now() + '_' + idx;
var pickLabel = (list.querySelector('.bib-prod-builder-field option[value=""]')
|| {}).textContent || '…';
var faceLabel = 'Face';
var endosLabel = 'Endos';
var infoLabel = 'Info';
var firstSide = section.querySelector('.bib-prod-field-side--face span');
var secondSide = section.querySelector('.bib-prod-field-side--endos span');
var thirdSide = section.querySelector('.bib-prod-field-side--info span');
if (firstSide) {
faceLabel = firstSide.textContent || faceLabel;
}
if (secondSide) {
endosLabel = secondSide.textContent || endosLabel;
}
if (thirdSide) {
infoLabel = thirdSide.textContent || infoLabel;
}
var removeTitle = (section.querySelector('.bib-prod-builder-remove')
|| {}).getAttribute('aria-label') || '×';
var optHtml = '<option value="">' + pickLabel + '</option>';
options.forEach(function (opt) {
if (!opt || !opt.key) {
return;
}
optHtml += '<option value="' + String(opt.key).replace(/"/g, '&quot;') + '">'
+ String(opt.label || opt.key).replace(/</g, '&lt;') + '</option>';
});
var sideLabel = bibProdFieldsLabel('data-label-' + side, side);
var removeTitle = bibProdFieldsLabel('data-label-remove', '×');
var li = document.createElement('li');
li.className = 'bib-prod-builder-row';
li.setAttribute('data-epr-id', eprId);
li.setAttribute('data-field-key', key);
li.setAttribute('data-field-side', side);
li.innerHTML = ''
+ '<select class="form-control form-control-sm bib-prod-builder-field">' + optHtml + '</select>'
+ '<div class="bib-prod-field-sides" role="radiogroup">'
+ ' <label class="bib-prod-field-side bib-prod-field-side--face is-selected">'
+ ' <input type="radio" class="bib-prod-field-side-input" name="' + rowId + '_side" value="face" checked>'
+ ' <span>' + faceLabel + '</span></label>'
+ ' <label class="bib-prod-field-side bib-prod-field-side--endos">'
+ ' <input type="radio" class="bib-prod-field-side-input" name="' + rowId + '_side" value="endos">'
+ ' <span>' + endosLabel + '</span></label>'
+ ' <label class="bib-prod-field-side bib-prod-field-side--info">'
+ ' <input type="radio" class="bib-prod-field-side-input" name="' + rowId + '_side" value="info">'
+ ' <span>' + infoLabel + '</span></label>'
+ '</div>'
+ '<span class="bib-prod-builder-label">' + bibProdEscapeHtml(label || key) + '</span>'
+ '<span class="bib-prod-field-side bib-prod-field-side--' + bibProdEscapeHtml(side)
+ ' is-selected bib-prod-builder-side-pill" aria-hidden="true">'
+ bibProdEscapeHtml(sideLabel) + '</span>'
+ '<button type="button" class="btn btn-sm btn-outline-secondary bib-prod-builder-remove"'
+ ' aria-label="' + removeTitle.replace(/"/g, '&quot;') + '">'
+ ' title="' + bibProdEscapeHtml(removeTitle) + '"'
+ ' aria-label="' + bibProdEscapeHtml(removeTitle) + '">'
+ '<i class="fa fa-trash" aria-hidden="true"></i></button>';
list.appendChild(li);
bibProdBuilderRefreshOptionDisabled(section);
}
moduleBib.addEventListener('submit', function (e) {
@ -2184,42 +2218,69 @@
}
});
// MSIN-4515 — Builder : pastilles, +, poubelle, enregistrement.
moduleBib.addEventListener('change', function (e) {
var sideInput = e.target.closest('.bib-prod-field-side-input');
if (sideInput && moduleBib.contains(sideInput)) {
var group = sideInput.closest('.bib-prod-field-sides');
if (group) {
group.querySelectorAll('.bib-prod-field-side').forEach(function (lab) {
var inp = lab.querySelector('.bib-prod-field-side-input');
lab.classList.toggle('is-selected', !!(inp && inp.checked));
});
}
}
var fieldSel = e.target.closest('.bib-prod-builder-field');
if (fieldSel && moduleBib.contains(fieldSel)) {
bibProdBuilderRefreshOptionDisabled(
fieldSel.closest('.bib-prod-fields-epr')
);
}
});
// MSIN-4515 — Builder : + → liste → Face/Endos/Info ; poubelle ; enregistrement.
moduleBib.addEventListener('click', function (e) {
var addBtn = e.target.closest('.bib-prod-builder-add');
if (addBtn && moduleBib.contains(addBtn)) {
e.preventDefault();
bibProdBuilderAddRow(addBtn.closest('.bib-prod-fields-epr'));
var sectionAdd = addBtn.closest('.bib-prod-fields-epr');
var panelAdd = sectionAdd ? sectionAdd.querySelector('.bib-prod-add-panel') : null;
if (panelAdd && !panelAdd.hidden) {
bibProdBuilderClosePanel(sectionAdd);
} else {
bibProdBuilderOpenPanel(sectionAdd);
}
return;
}
var choiceBtn = e.target.closest('.bib-prod-add-choice');
if (choiceBtn && moduleBib.contains(choiceBtn)) {
e.preventDefault();
var sectionChoice = choiceBtn.closest('.bib-prod-fields-epr');
var panelChoice = sectionChoice ? sectionChoice.querySelector('.bib-prod-add-panel') : null;
var sidesChoice = sectionChoice ? sectionChoice.querySelector('.bib-prod-add-sides') : null;
if (!panelChoice) {
return;
}
panelChoice.setAttribute('data-pending-key', choiceBtn.getAttribute('data-key') || '');
panelChoice.setAttribute('data-pending-label', choiceBtn.getAttribute('data-label') || '');
sectionChoice.querySelectorAll('.bib-prod-add-choice').forEach(function (btn) {
btn.classList.toggle('is-selected', btn === choiceBtn);
});
if (sidesChoice) {
sidesChoice.hidden = false;
}
return;
}
var sideBtn = e.target.closest('.bib-prod-add-side');
if (sideBtn && moduleBib.contains(sideBtn)) {
e.preventDefault();
var sectionSide = sideBtn.closest('.bib-prod-fields-epr');
var panelSide = sectionSide ? sectionSide.querySelector('.bib-prod-add-panel') : null;
if (!panelSide) {
return;
}
var pendingKey = panelSide.getAttribute('data-pending-key') || '';
var pendingLabel = panelSide.getAttribute('data-pending-label') || pendingKey;
var side = sideBtn.getAttribute('data-side') || '';
if (!pendingKey || !side) {
return;
}
bibProdBuilderAppendRow(sectionSide, pendingKey, pendingLabel, side);
bibProdBuilderClosePanel(sectionSide);
return;
}
var removeBtn = e.target.closest('.bib-prod-builder-remove');
if (removeBtn && moduleBib.contains(removeBtn)) {
e.preventDefault();
var row = removeBtn.closest('.bib-prod-builder-row');
var section = removeBtn.closest('.bib-prod-fields-epr');
var sectionRemove = removeBtn.closest('.bib-prod-fields-epr');
if (row) {
row.remove();
}
bibProdBuilderRefreshOptionDisabled(section);
bibProdBuilderClosePanel(sectionRemove);
return;
}
@ -2268,10 +2329,6 @@
});
});
moduleBib.querySelectorAll('.bib-prod-fields-epr').forEach(function (section) {
bibProdBuilderRefreshOptionDisabled(section);
});
moduleBib.addEventListener('click', function (e) {
var workspaceTab = e.target.closest('.bib-workspace-tab');
if (workspaceTab && moduleBib.contains(workspaceTab)) {

View File

@ -136,11 +136,10 @@ function fxBibProductionCollectSelectableFields($intEveId, $intEprId, $strLangue
return $tabOut;
}
/** MSIN-4515 — Défaut = comportement Excel actuel (n° face, épreuve info). */
/** MSIN-4515 — Défaut = seulement le n° dossard en Face. */
function fxBibProductionDefaultFields() {
return [
['key' => 'no_bib', 'side' => 'face'],
['key' => 'epr_nom', 'side' => 'info'],
];
}

View File

@ -5023,7 +5023,7 @@ function renderBibPreparationOverview(array $tabEpreuves, $strAnomBadges = '') {
}
/**
* MSIN-4515 — Ligne « information sur le dossard » (+ champ + Face/Endos/Info).
* MSIN-4515 — Ligne affichée : libellé + pastille Face/Endos/Info + poubelle (pas de select).
*
* @param array<int, array{key:string,label:string}> $tabSelectable
*/
@ -5038,57 +5038,29 @@ function renderBibProductionBuilderRow(
$intEprId = (int)$intEprId;
$strKey = (string)$strKey;
$strSide = in_array($strSide, ['face', 'endos', 'info'], true) ? $strSide : 'face';
$intRowIndex = (int)$intRowIndex;
$strRowId = 'prod_row_' . $intEprId . '_' . $intRowIndex;
$tabSides = [
'face' => ['class' => 'face', 'label_key' => 'bib_v5_production_fields_side_face'],
'endos' => ['class' => 'endos', 'label_key' => 'bib_v5_production_fields_side_endos'],
'info' => ['class' => 'info', 'label_key' => 'bib_v5_production_fields_side_info'],
$strLabel = $strKey;
foreach ($tabSelectable as $tabOpt) {
if ((string)($tabOpt['key'] ?? '') === $strKey) {
$strLabel = (string)($tabOpt['label'] ?? $strKey);
break;
}
}
$tabSideKeys = [
'face' => 'bib_v5_production_fields_side_face',
'endos' => 'bib_v5_production_fields_side_endos',
'info' => 'bib_v5_production_fields_side_info',
];
$strSideLabel = fxBibTexte($tabSideKeys[$strSide], 0);
ob_start();
?>
<li class="bib-prod-builder-row" data-epr-id="<?php echo $intEprId; ?>">
<label class="sr-only" for="<?php echo fxBibEsc($strRowId); ?>_field">
<?php echo fxBibEsc(fxBibTexte('bib_v5_production_fields_pick', 0)); ?>
</label>
<select id="<?php echo fxBibEsc($strRowId); ?>_field"
class="form-control form-control-sm bib-prod-builder-field"
<?php echo $blnLocked ? 'disabled' : ''; ?>>
<option value=""><?php echo fxBibEsc(fxBibTexte('bib_v5_production_fields_pick', 0)); ?></option>
<?php foreach ($tabSelectable as $tabOpt) {
$strOptKey = (string)($tabOpt['key'] ?? '');
if ($strOptKey === '') {
continue;
}
?>
<option value="<?php echo fxBibEsc($strOptKey); ?>"
<?php echo ($strOptKey === $strKey) ? 'selected' : ''; ?>>
<?php echo fxBibEsc((string)($tabOpt['label'] ?? $strOptKey)); ?>
</option>
<?php } ?>
</select>
<div class="bib-prod-field-sides" role="radiogroup"
aria-label="<?php echo fxBibEsc(fxBibTexte('bib_v5_production_fields_side_face', 0)); ?>">
<?php foreach ($tabSides as $strSideVal => $tabMeta) {
$strId = $strRowId . '_' . $strSideVal;
$blnChecked = ($strSide === $strSideVal);
?>
<label class="bib-prod-field-side bib-prod-field-side--<?php echo fxBibEsc($tabMeta['class']); ?><?php echo $blnChecked ? ' is-selected' : ''; ?>"
for="<?php echo fxBibEsc($strId); ?>">
<input type="radio"
id="<?php echo fxBibEsc($strId); ?>"
class="bib-prod-field-side-input"
name="<?php echo fxBibEsc($strRowId); ?>_side"
value="<?php echo fxBibEsc($strSideVal); ?>"
<?php echo $blnChecked ? 'checked' : ''; ?>
<?php echo $blnLocked ? 'disabled' : ''; ?>>
<span><?php echo fxBibEsc(fxBibTexte($tabMeta['label_key'], 0)); ?></span>
</label>
<?php } ?>
</div>
<li class="bib-prod-builder-row"
data-epr-id="<?php echo $intEprId; ?>"
data-field-key="<?php echo fxBibEsc($strKey); ?>"
data-field-side="<?php echo fxBibEsc($strSide); ?>">
<span class="bib-prod-builder-label"><?php echo fxBibEsc($strLabel); ?></span>
<span class="bib-prod-field-side bib-prod-field-side--<?php echo fxBibEsc($strSide); ?> is-selected bib-prod-builder-side-pill"
aria-hidden="true"><?php echo fxBibEsc($strSideLabel); ?></span>
<?php if (!$blnLocked) { ?>
<button type="button"
class="btn btn-sm btn-outline-secondary bib-prod-builder-remove"
@ -5102,7 +5074,7 @@ function renderBibProductionBuilderRow(
return ob_get_clean();
}
/** @deprecated alias — conserver signature pour appels résiduels */
/** @deprecated */
function renderBibProductionFieldSideRow($intEprId, $strKey, $strLabel, $strSelectedSide, $blnLocked) {
return renderBibProductionBuilderRow(
$intEprId,
@ -5217,10 +5189,15 @@ function renderBibProductionPreview(array $tabEpreuves, $strLangue = 'fr') {
</div>
</section>
<?php // MSIN-4515 — Ajouter une information sur le dossard (peu de lignes, pas un mur). ?>
<?php // MSIN-4515 — Visuel validé : titre épreuve, n° Face, +, panneau choisir puis Face/Endos/Info. ?>
<section class="bib-production-fields epr-block"
data-eve-id="<?php echo $intEveId; ?>"
data-locked="<?php echo $blnProductionLocked ? '1' : '0'; ?>">
data-locked="<?php echo $blnProductionLocked ? '1' : '0'; ?>"
data-label-face="<?php echo fxBibEsc(fxBibTexte('bib_v5_production_fields_side_face', 0)); ?>"
data-label-endos="<?php echo fxBibEsc(fxBibTexte('bib_v5_production_fields_side_endos', 0)); ?>"
data-label-info="<?php echo fxBibEsc(fxBibTexte('bib_v5_production_fields_side_info', 0)); ?>"
data-label-remove="<?php echo fxBibEsc(fxBibTexte('bib_v5_production_fields_remove', 0)); ?>"
data-label-pick="<?php echo fxBibEsc(fxBibTexte('bib_v5_production_fields_pick', 0)); ?>">
<div class="epr-header">
<span class="epr-header-label">
<?php fxBibTexteTrad('bib_v5_production_fields_title', 1); ?>
@ -5228,11 +5205,6 @@ function renderBibProductionPreview(array $tabEpreuves, $strLangue = 'fr') {
</div>
<div class="epr-content">
<p class="bib-production-fields-intro"><?php fxBibTexteTrad('bib_v5_production_fields_intro', 1); ?></p>
<ul class="bib-production-fields-legend list-unstyled">
<li><span class="bib-prod-swatch bib-prod-swatch--face" aria-hidden="true"></span><?php fxBibTexteTrad('bib_v5_production_fields_legend_face', 1); ?></li>
<li><span class="bib-prod-swatch bib-prod-swatch--endos" aria-hidden="true"></span><?php fxBibTexteTrad('bib_v5_production_fields_legend_endos', 1); ?></li>
<li><span class="bib-prod-swatch bib-prod-swatch--info" aria-hidden="true"></span><?php fxBibTexteTrad('bib_v5_production_fields_legend_info', 1); ?></li>
</ul>
<?php if ($blnProductionLocked) { ?>
<p class="text-muted small"><?php fxBibTexteTrad('bib_v5_production_fields_locked', 1); ?></p>
<?php } ?>
@ -5247,11 +5219,16 @@ function renderBibProductionPreview(array $tabEpreuves, $strLangue = 'fr') {
if ($intEprId <= 0) {
continue;
}
$intRangeCount = fxBibCountSavedRanges(fxInfosBibRange($intEprId, 0, false));
$tabSelectable = fxBibProductionCollectSelectableFields($intEveId, $intEprId, $strLangue);
$tabAllowed = [];
$tabLabelByKey = [];
foreach ($tabSelectable as $tabOpt) {
$tabAllowed[(string)$tabOpt['key']] = true;
$strOptKey = (string)($tabOpt['key'] ?? '');
if ($strOptKey === '') {
continue;
}
$tabAllowed[$strOptKey] = true;
$tabLabelByKey[$strOptKey] = (string)($tabOpt['label'] ?? $strOptKey);
}
$tabRows = [];
@ -5268,8 +5245,8 @@ function renderBibProductionPreview(array $tabEpreuves, $strLangue = 'fr') {
];
}
}
// Première visite : une seule ligne (n° Face) — pas tout le catalogue.
if (empty($tabRows) && !$blnProductionLocked) {
// Arrivée : UNIQUEMENT n° dossard Face.
if (empty($tabRows)) {
$tabRows[] = ['key' => 'no_bib', 'side' => 'face'];
}
@ -5279,12 +5256,11 @@ function renderBibProductionPreview(array $tabEpreuves, $strLangue = 'fr') {
'UTF-8'
);
?>
<section class="bib-dist-print-epr bib-prod-fields-epr bib-production-category"
<section class="bib-prod-fields-epr bib-production-category"
data-epr-id="<?php echo $intEprId; ?>"
data-field-options="<?php echo $strOptionsJson; ?>">
<h3 class="bib-dist-print-epr-title">
<h3 class="bib-prod-fields-epr-title">
<?php echo fxBibEsc(fxBibEpreuveDisplayName($tabEpreuve, $strLangue)); ?>
<span class="text-muted small">(<span class="bib-production-range-count"><?php echo $intRangeCount; ?></span>)</span>
</h3>
<?php if (empty($tabSelectable)) { ?>
@ -5304,12 +5280,32 @@ function renderBibProductionPreview(array $tabEpreuves, $strLangue = 'fr') {
);
} ?>
</ul>
<?php if (!$blnProductionLocked) { ?>
<button type="button"
class="btn btn-outline-primary btn-sm bib-prod-builder-add">
<i class="fa fa-plus mr-1" aria-hidden="true"></i>
<?php fxBibTexteTrad('bib_v5_production_fields_add', 1); ?>
class="btn btn-outline-primary btn-sm bib-prod-builder-add"
aria-expanded="false">
<i class="fa fa-plus" aria-hidden="true"></i>
<span class="sr-only"><?php fxBibTexteTrad('bib_v5_production_fields_add', 1); ?></span>
</button>
<div class="bib-prod-add-panel" hidden>
<p class="bib-prod-add-panel__title">
<?php fxBibTexteTrad('bib_v5_production_fields_pick', 1); ?>
</p>
<ul class="bib-prod-add-choices list-unstyled"></ul>
<div class="bib-prod-add-sides" hidden>
<button type="button" class="bib-prod-field-side bib-prod-field-side--face bib-prod-add-side" data-side="face">
<?php fxBibTexteTrad('bib_v5_production_fields_side_face', 1); ?>
</button>
<button type="button" class="bib-prod-field-side bib-prod-field-side--endos bib-prod-add-side" data-side="endos">
<?php fxBibTexteTrad('bib_v5_production_fields_side_endos', 1); ?>
</button>
<button type="button" class="bib-prod-field-side bib-prod-field-side--info bib-prod-add-side" data-side="info">
<?php fxBibTexteTrad('bib_v5_production_fields_side_info', 1); ?>
</button>
</div>
</div>
<?php } ?>
<?php } ?>
</section>

View File

@ -7,7 +7,7 @@
* Constantes *
*
**************/
define('_VERSION_CODE', '4.72.872'); // MSIN-4515 — UI + ajouter info dossard
define('_VERSION_CODE', '4.72.873'); // MSIN-4515 — builder Face/Endos/Info (liste +)
define('_DATE_CODE', '2026-07-27');
//MSIN-4290
define('QR_SECRET_KEY', 'ms1_qr_2026_cle_secrete_longue_et_fixe');