From 27e581c40a13334dcc1767b7b15b7497e2d2d552 Mon Sep 17 00:00:00 2001 From: stephan Date: Thu, 18 Jun 2026 09:55:49 -0400 Subject: [PATCH] Implement locking mechanism for bib ranges with AJAX support This commit introduces a locking feature for bib ranges, allowing users to lock or unlock sequences via a new AJAX endpoint. The PHP code is updated to check for locked statuses before performing actions, enhancing data integrity. Additionally, new JavaScript functions are added to handle user interactions for locking and unlocking, along with corresponding CSS styles for visual feedback. This improves the user experience by preventing modifications to locked sequences and providing clear confirmation messages. --- ajax_bib_range.php | 111 +++++++++++++- css/style.css | 50 ++++++- inc_footer_scripts.php | 57 ++++++++ php/inc_fx_promoteur.php | 162 +++++++++++++++++++-- sql/MSIN-4379-bib_v4-range-lock-column.sql | 5 + sql/MSIN-4379-bib_v4-range-lock-i18n.sql | 43 ++++++ 6 files changed, 413 insertions(+), 15 deletions(-) create mode 100644 sql/MSIN-4379-bib_v4-range-lock-column.sql create mode 100644 sql/MSIN-4379-bib_v4-range-lock-i18n.sql diff --git a/ajax_bib_range.php b/ajax_bib_range.php index 31125d1..8466045 100644 --- a/ajax_bib_range.php +++ b/ajax_bib_range.php @@ -73,6 +73,20 @@ if ($action == 'delete') { if ($id > 0) { + $rowLock = $objDatabase->fxGetRow(" + SELECT epr_bib_locked + FROM inscriptions_epreuves_bib + WHERE epr_bib_id = $id + "); + + if ($rowLock && (int)($rowLock['epr_bib_locked'] ?? 0) === 1) { + echo json_encode([ + 'success' => false, + 'message' => fxBibMsg('bib_v4_ajax_range_locked') + ]); + exit; + } + $range = fxInfosBibRange(0,$id); $epr_id = $range[1]["epr_id"]; @@ -169,8 +183,20 @@ if ($action == 'save') { // ===================== if (!$is_new) { - $sqlGet = "SELECT epr_id FROM inscriptions_epreuves_bib WHERE epr_bib_id = $id"; - $epr_id = (int)$objDatabase->fxGetVar($sqlGet); + $sqlGet = "SELECT epr_id, epr_bib_locked FROM inscriptions_epreuves_bib WHERE epr_bib_id = $id"; + $rowRange = $objDatabase->fxGetRow($sqlGet); + + if (!$rowRange || (int)($rowRange['epr_id'] ?? 0) <= 0) { + echo json_encode(['success' => false, 'message' => fxBibMsg('bib_v4_ajax_range_not_found')]); + exit; + } + + if ((int)($rowRange['epr_bib_locked'] ?? 0) === 1) { + echo json_encode(['success' => false, 'message' => fxBibMsg('bib_v4_ajax_range_locked')]); + exit; + } + + $epr_id = (int)$rowRange['epr_id']; if ($epr_id <= 0) { echo json_encode(['success' => false, 'message' => fxBibMsg('bib_v4_ajax_range_not_found')]); @@ -373,6 +399,15 @@ if ($action == 'batch_go') { // Liste des ranges sélectionnés (JSON → array PHP) $ranges = json_decode($_POST['ranges'] ?? '[]', true); + $lockCheck = fxBibAssertRangesUnlocked($epr_id, is_array($ranges) ? $ranges : []); + if (!$lockCheck['success']) { + echo json_encode([ + 'success' => false, + 'message' => $lockCheck['message'] ?? fxBibMsg('bib_v4_ajax_range_locked') + ]); + exit; + } + // Ordre choisi (table bib_assignements) $ba_id = intval($_POST['ba_id'] ?? 0); @@ -444,6 +479,15 @@ if ($action == 'batch_apply') { $ranges = json_decode($_POST['ranges'] ?? '[]', true); $ba_id = intval($_POST['ba_id'] ?? 0); + $lockCheck = fxBibAssertRangesUnlocked($epr_id, is_array($ranges) ? $ranges : []); + if (!$lockCheck['success']) { + echo json_encode([ + 'success' => false, + 'message' => $lockCheck['message'] ?? fxBibMsg('bib_v4_ajax_range_locked') + ]); + exit; + } + $participants = fxGetParticipantsForBatchAssign($epr_id, $ba_id); $tabRanges = fxGetRangesForBatchAssign($epr_id, $ranges); @@ -506,6 +550,15 @@ if ($action == 'reset_preview') { $ranges = json_decode($_POST['ranges'] ?? '[]', true); + $lockCheck = fxBibAssertRangesUnlocked($epr_id, is_array($ranges) ? $ranges : []); + if (!$lockCheck['success']) { + echo json_encode([ + 'success' => false, + 'message' => $lockCheck['message'] ?? fxBibMsg('bib_v4_ajax_range_locked') + ]); + exit; + } + $participants = fxGetParticipantsForBatchReset($epr_id, $ranges); $html = renderBibView( @@ -535,6 +588,15 @@ if ($action == 'reset_apply') { $ranges = json_decode($_POST['ranges'] ?? '[]', true); + $lockCheck = fxBibAssertRangesUnlocked($epr_id, is_array($ranges) ? $ranges : []); + if (!$lockCheck['success']) { + echo json_encode([ + 'success' => false, + 'message' => $lockCheck['message'] ?? fxBibMsg('bib_v4_ajax_range_locked') + ]); + exit; + } + $participants = fxGetParticipantsForBatchReset($epr_id, $ranges); $count = 0; @@ -611,6 +673,51 @@ if ($action == 'save_team_mode') { exit; } +// MSIN-4379 — Verrouillage séquence (cadenas ouvert/fermé) +if ($action == 'toggle_lock') { + + if (!fxBibRequirePromoteurSession()) { + echo json_encode([ + 'success' => false, + 'message' => fxBibMsg('bib_v4_ajax_session_invalid') + ]); + exit; + } + + if (!fxBibValidateCsrf($_POST['csrf_token'] ?? '')) { + echo json_encode([ + 'success' => false, + 'message' => fxBibMsg('bib_v4_ajax_unauthorized') + ]); + exit; + } + + $epr_bib_id = intval($_POST['epr_bib_id'] ?? 0); + $epr_id = intval($_POST['epr_id'] ?? 0); + $locked = intval($_POST['locked'] ?? 0) === 1; + + $result = fxBibSetRangeLocked($epr_bib_id, $locked, $epr_id); + + if (!$result['success']) { + echo json_encode([ + 'success' => false, + 'message' => $result['message'] ?? fxBibMsg('bib_v4_ajax_error') + ]); + exit; + } + + $epr_id = (int)$result['epr_id']; + $tabBibStats = fxInfosBibRange($epr_id); + + echo json_encode([ + 'success' => true, + 'locked' => !empty($result['locked']), + 'auto_active' => fxIsBibAutoActive($epr_id), + 'html' => renderBibRanges($tabBibStats, $epr_id, 'assign') + ]); + exit; +} + // MSIN-4379 — Étape 2 // Endpoint AJAX : sauvegarde ou désactivation de la config auto (epr_bib_auto). // Paramètres : epr_id, active (0|1), ranges (JSON des epr_bib_id), csrf_token. diff --git a/css/style.css b/css/style.css index 8c59e08..6a93cb2 100644 --- a/css/style.css +++ b/css/style.css @@ -1813,10 +1813,11 @@ a.ms1-trad-link.btn-aide-trad{ width:100%; } -/* MSIN-4379 — View/OK/Suppr icônes ; stats regroupées ; badge auto à droite. */ +/* MSIN-4379 — Cadenas + view/OK/stats ; badge auto à droite. */ .epr-line{ display:grid; grid-template-columns: + 32px 40px 58px 58px @@ -1832,6 +1833,7 @@ a.ms1-trad-link.btn-aide-trad{ .bib-container.batch-mode .epr-line{ grid-template-columns: + 32px 40px 58px 58px @@ -1841,6 +1843,52 @@ a.ms1-trad-link.btn-aide-trad{ 28px; } +.epr-col-lock{ + display:flex; + align-items:center; + justify-content:center; + min-width:0; +} + +.btn-bib-lock{ + width:100%; + padding-left:0; + padding-right:0; + border-width:1px; + border-style:solid; +} + +.btn-bib-lock--open{ + background-color:#28a745; + border-color:#218838; + color:#fff; +} + +.btn-bib-lock--open:hover, +.btn-bib-lock--open:focus{ + background-color:#218838; + border-color:#1e7e34; + color:#fff; +} + +.btn-bib-lock--closed{ + background-color:#dc3545; + border-color:#c82333; + color:#fff; +} + +.btn-bib-lock--closed:hover, +.btn-bib-lock--closed:focus{ + background-color:#c82333; + border-color:#bd2130; + color:#fff; +} + +.bib-range--locked .bib-start, +.bib-range--locked .bib-end{ + background-color:#f1f3f5; +} + .epr-col-stats{ display:grid; grid-template-columns:56px 48px 48px; diff --git a/inc_footer_scripts.php b/inc_footer_scripts.php index 8b55227..24aa872 100644 --- a/inc_footer_scripts.php +++ b/inc_footer_scripts.php @@ -1975,6 +1975,10 @@ if ($strLangue == 'fr') { return moduleBib.dataset[attr] || ''; } + function bibJsConfirm(attr) { + return bibJs(attr).replace(/\\n/g, '\n'); + } + function bibJsFmt(attr) { var tpl = bibJs(attr); var args = Array.prototype.slice.call(arguments, 1); @@ -2546,6 +2550,59 @@ if ($strLangue == 'fr') { return; } + // ===================== + // LOCK / UNLOCK SEQUENCE + // ===================== + let btnLock = e.target.closest('.btn-bib-lock'); + if (btnLock) { + e.preventDefault(); + + let row = btnLock.closest('.epr-row'); + if (!row) return; + + let isLocked = btnLock.dataset.locked === '1'; + let confirmMsg = isLocked + ? bibJsConfirm('jsUnlockConfirm') + : bibJsConfirm('jsLockConfirm'); + + if (!confirm(confirmMsg)) { + return; + } + + fetch('/ajax_bib_range.php', { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + }, + body: + 'action=toggle_lock' + + '&epr_bib_id=' + encodeURIComponent(btnLock.dataset.rangeId) + + '&epr_id=' + encodeURIComponent(btnLock.dataset.eprId || row.dataset.eprId) + + '&locked=' + encodeURIComponent(isLocked ? '0' : '1') + + '&csrf_token=' + encodeURIComponent(bibCsrfToken()) + + bibAjaxLangSuffix() + }) + .then(res => res.json()) + .then(data => { + + if (!data.success) { + alert(data.message || bibJs('jsErrGeneric')); + return; + } + + if (typeof data.auto_active !== 'undefined') { + row.dataset.autoActive = data.auto_active ? '1' : '0'; + syncAutoUiState(row, data.auto_active); + } + + if (data.html) { + setBibContainerHtml(row, data.html); + } + }); + + return; + } + // ===================== // DELETE // ===================== diff --git a/php/inc_fx_promoteur.php b/php/inc_fx_promoteur.php index 223325f..f0a2cc1 100644 --- a/php/inc_fx_promoteur.php +++ b/php/inc_fx_promoteur.php @@ -2917,6 +2917,8 @@ function fxBibModuleJsDataAttrs() { 'batch-summary-short' => 'bib_v4_ajax_sim_summary', 'batch-reset-count' => 'bib_v4_ajax_reset_preview_count', 'auto-select-hint' => 'bib_v4_auto_select_hint', + 'lock-confirm' => 'bib_v4_js_lock_confirm', + 'unlock-confirm' => 'bib_v4_js_unlock_confirm', ]; $html = ''; foreach ($map as $attr => $clef) { @@ -3073,9 +3075,122 @@ function fxBibIsRangeAvailableForAuto($epr_id, $epr_bib_id) { return false; } + if (fxBibRangeIsLocked($rows[1])) { + return false; + } + return fxBibRangeDispoFromRow($rows[1]) > 0; } +/** Séquence verrouillée (epr_bib_locked = 1) — plus de modification ni assignation. */ +function fxBibRangeIsLocked(array $range) { + return (int)($range['epr_bib_locked'] ?? 0) === 1; +} + +/** Vérifie qu'aucune des séquences listées n'est verrouillée. */ +function fxBibAssertRangesUnlocked($epr_id, $rangeIds) { + global $objDatabase; + + $epr_id = (int)$epr_id; + + if ($epr_id <= 0 || empty($rangeIds) || !is_array($rangeIds)) { + return ['success' => true]; + } + + $ids = array_values(array_filter(array_map('intval', $rangeIds))); + + if (empty($ids)) { + return ['success' => true]; + } + + $strIds = implode(',', $ids); + + $sql = " + SELECT COUNT(*) + FROM inscriptions_epreuves_bib + WHERE epr_id = $epr_id + AND epr_bib_id IN ($strIds) + AND epr_bib_locked = 1 + "; + + if ((int)$objDatabase->fxGetVar($sql) > 0) { + return ['success' => false, 'message' => fxBibMsg('bib_v4_ajax_range_locked')]; + } + + return ['success' => true]; +} + +/** Bascule le verrou d'une séquence (0 = ouvert, 1 = fermé). */ +function fxBibSetRangeLocked($epr_bib_id, $locked, $epr_id = 0) { + global $objDatabase; + + $epr_bib_id = (int)$epr_bib_id; + $epr_id = (int)$epr_id; + $locked = $locked ? 1 : 0; + + if ($epr_bib_id <= 0) { + return ['success' => false, 'message' => fxBibMsg('bib_v4_ajax_id_invalid')]; + } + + $sqlGet = " + SELECT epr_id + FROM inscriptions_epreuves_bib + WHERE epr_bib_id = $epr_bib_id + "; + $rowEprId = (int)$objDatabase->fxGetVar($sqlGet); + + if ($rowEprId <= 0) { + return ['success' => false, 'message' => fxBibMsg('bib_v4_ajax_range_not_found')]; + } + + if ($epr_id > 0 && $rowEprId !== $epr_id) { + return ['success' => false, 'message' => fxBibMsg('bib_v4_ajax_seq_invalid')]; + } + + $objDatabase->fxQuery(" + UPDATE inscriptions_epreuves_bib + SET epr_bib_locked = $locked + WHERE epr_bib_id = $epr_bib_id + "); + + if ($locked === 1) { + $objDatabase->fxQuery(" + UPDATE inscriptions_epreuves_bib + SET epr_bib_auto = 0 + WHERE epr_bib_id = $epr_bib_id + "); + } + + return [ + 'success' => true, + 'epr_id' => $rowEprId, + 'locked' => $locked === 1, + ]; +} + +/** Bouton cadenas (vert ouvert / rouge fermé) devant une séquence enregistrée. */ +function fxBibRenderRangeLockButton(array $range, $epr_id = 0) { + if ((int)($range['epr_bib_id'] ?? 0) <= 0) { + return '
'; + } + + $locked = fxBibRangeIsLocked($range); + $strClass = $locked ? 'btn-bib-lock--closed' : 'btn-bib-lock--open'; + $strIcon = $locked ? 'fa-lock' : 'fa-unlock'; + $strTip = $locked ? 'bib_v4_tip_lock_closed' : 'bib_v4_tip_lock_open'; + + return ''; +} + /** Badge « Assignation automatique » sur une ligne de séquence (epr_bib_auto = 1). */ function fxBibRenderRangeAutoBadge(array $range, $mode = 'assign') { if ($mode !== 'assign') { @@ -3087,6 +3202,9 @@ function fxBibRenderRangeAutoBadge(array $range, $mode = 'assign') { if ((int)($range['epr_bib_auto'] ?? 0) !== 1) { return ''; } + if (fxBibRangeIsLocked($range)) { + return ''; + } if (fxBibRangeDispoFromRow($range) <= 0) { return ''; } @@ -3302,6 +3420,7 @@ function renderBibRangeHeader() { ob_start(); ?>
+
@@ -3617,6 +3736,7 @@ function fxInfosBibRange($epr_id = 0, $epr_bib_id = 0){ b.epr_bib_start, b.epr_bib_finish, b.epr_bib_auto, /* MSIN-4379 — Étape 1 : flag par séquence (pool auto). */ + b.epr_bib_locked, COUNT(p.no_bib) AS nb_utilises, MAX(p.no_bib) AS dernier_bib, @@ -3713,7 +3833,8 @@ function fxInfosBibRange($epr_id = 0, $epr_bib_id = 0){ b.epr_id, b.epr_bib_start, b.epr_bib_finish, - b.epr_bib_auto + b.epr_bib_auto, + b.epr_bib_locked ORDER BY b.epr_bib_start "; @@ -3741,6 +3862,7 @@ function fxIsBibAutoActive($epr_id) { FROM inscriptions_epreuves_bib WHERE epr_id = $epr_id AND epr_bib_auto = 1 + AND epr_bib_locked = 0 "; return (int)$objDatabase->fxGetVar($sql) > 0; @@ -3802,6 +3924,11 @@ function fxSaveBibAutoConfig($epr_id, $ranges, $active = true) { } } + $lockCheck = fxBibAssertRangesUnlocked($epr_id, $ids); + if (!$lockCheck['success']) { + return $lockCheck; + } + $objDatabase->fxQuery(" UPDATE inscriptions_epreuves_bib SET epr_bib_auto = 1 @@ -3830,6 +3957,7 @@ function fxGetAutoBibRangeIds($epr_id) { FROM inscriptions_epreuves_bib WHERE epr_id = $epr_id AND epr_bib_auto = 1 + AND epr_bib_locked = 0 ORDER BY epr_bib_start "; @@ -4095,10 +4223,16 @@ $nb_utilises = (int)($range['nb_utilises'] ?? 0); $mem_dispo = max(0, $nb_total - $nb_utilises); +$blnRangeLocked = fxBibRangeIsLocked($range); + ?> -
+
+ + 0) { ?> 0) { ?> @@ -4148,28 +4286,28 @@ $mem_dispo = max(0, $nb_total - $nb_utilises); $showCheckbox = false; -if ( +if (!$blnRangeLocked && ( $mode === 'assign' && $mem_dispo > 0 && (int)$range['epr_bib_id'] > 0 -) { +)) { $showCheckbox = true; } -if ( +if (!$blnRangeLocked && ( $mode === 'reset' && (int)$range['nb_utilises'] > 0 && (int)$range['epr_bib_id'] > 0 -) { +)) { $showCheckbox = true; } // MSIN-4379 — Étape 2 : mode « auto » — séquences avec dossards disponibles seulement. -if ( +if (!$blnRangeLocked && ( $mode === 'auto' && $mem_dispo > 0 && (int)$range['epr_bib_id'] > 0 -) { +)) { $showCheckbox = true; } diff --git a/sql/MSIN-4379-bib_v4-range-lock-column.sql b/sql/MSIN-4379-bib_v4-range-lock-column.sql new file mode 100644 index 0000000..de789f4 --- /dev/null +++ b/sql/MSIN-4379-bib_v4-range-lock-column.sql @@ -0,0 +1,5 @@ +-- MSIN-4379 — Verrouillage de séquence de dossards (cadenas ouvert/fermé) + +ALTER TABLE inscriptions_epreuves_bib + ADD COLUMN epr_bib_locked TINYINT(1) NOT NULL DEFAULT 0 + AFTER epr_bib_auto; diff --git a/sql/MSIN-4379-bib_v4-range-lock-i18n.sql b/sql/MSIN-4379-bib_v4-range-lock-i18n.sql new file mode 100644 index 0000000..d2fc11d --- /dev/null +++ b/sql/MSIN-4379-bib_v4-range-lock-i18n.sql @@ -0,0 +1,43 @@ +-- MSIN-4379 — i18n verrouillage séquences de dossards + +INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation) +SELECT 'bib_v4_col_lock', 'fr', '', 'Verrouiller ou déverrouiller la séquence.', 'compte.php', '', 0, 1, '', '', '', NOW() +FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_col_lock' AND info_langue = 'fr' AND info_prg = 'compte.php'); +INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation) +SELECT 'bib_v4_col_lock', 'en', '', 'Lock or unlock the sequence.', 'compte.php', '', 0, 1, '', '', '', NOW() +FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_col_lock' AND info_langue = 'en' AND info_prg = 'compte.php'); + +INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation) +SELECT 'bib_v4_tip_lock_open', 'fr', 'Séquence ouverte', 'Cliquez pour verrouiller : la plage, les dossards et les assignations ne pourront plus être modifiés.', 'compte.php', '', 0, 1, '', '', '', NOW() +FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_tip_lock_open' AND info_langue = 'fr' AND info_prg = 'compte.php'); +INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation) +SELECT 'bib_v4_tip_lock_open', 'en', 'Sequence unlocked', 'Click to lock: range, bibs and assignments can no longer be changed.', 'compte.php', '', 0, 1, '', '', '', NOW() +FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_tip_lock_open' AND info_langue = 'en' AND info_prg = 'compte.php'); + +INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation) +SELECT 'bib_v4_tip_lock_closed', 'fr', 'Séquence verrouillée', 'Cliquez pour déverrouiller (confirmation requise).', 'compte.php', '', 0, 1, '', '', '', NOW() +FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_tip_lock_closed' AND info_langue = 'fr' AND info_prg = 'compte.php'); +INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation) +SELECT 'bib_v4_tip_lock_closed', 'en', 'Sequence locked', 'Click to unlock (confirmation required).', 'compte.php', '', 0, 1, '', '', '', NOW() +FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_tip_lock_closed' AND info_langue = 'en' AND info_prg = 'compte.php'); + +INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation) +SELECT 'bib_v4_js_lock_confirm', 'fr', 'Verrouiller cette séquence ?\n\nTant qu''elle est verrouillée, vous ne pourrez plus modifier la plage de numéros, supprimer la séquence, réinitialiser les dossards ni l''utiliser pour l''assignation automatique ou groupée.', '', 'compte.php', '', 0, 1, '', '', '', NOW() +FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_js_lock_confirm' AND info_langue = 'fr' AND info_prg = 'compte.php'); +INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation) +SELECT 'bib_v4_js_lock_confirm', 'en', 'Lock this sequence?\n\nWhile locked, you cannot change the number range, delete the sequence, reset bibs, or use it for automatic or batch assignment.', '', 'compte.php', '', 0, 1, '', '', '', NOW() +FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_js_lock_confirm' AND info_langue = 'en' AND info_prg = 'compte.php'); + +INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation) +SELECT 'bib_v4_js_unlock_confirm', 'fr', 'Déverrouiller cette séquence ?\n\nAttention : des dossards peuvent déjà avoir été imprimés ou communiqués. Déverrouiller pourrait compromettre la cohérence de vos données.\n\nConfirmez-vous le déverrouillage ?', '', 'compte.php', '', 0, 1, '', '', '', NOW() +FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_js_unlock_confirm' AND info_langue = 'fr' AND info_prg = 'compte.php'); +INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation) +SELECT 'bib_v4_js_unlock_confirm', 'en', 'Unlock this sequence?\n\nWarning: bibs may already have been printed or distributed. Unlocking could compromise your data.\n\nDo you confirm unlocking?', '', 'compte.php', '', 0, 1, '', '', '', NOW() +FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_js_unlock_confirm' AND info_langue = 'en' AND info_prg = 'compte.php'); + +INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation) +SELECT 'bib_v4_ajax_range_locked', 'fr', 'Cette séquence est verrouillée et ne peut pas être modifiée', '', 'compte.php', '', 0, 1, '', '', '', NOW() +FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_range_locked' AND info_langue = 'fr' AND info_prg = 'compte.php'); +INSERT INTO info (info_clef, info_langue, info_texte, info_aide, info_prg, info_description, info_trie, info_actif, info_option1, info_option2, info_option3, info_creation) +SELECT 'bib_v4_ajax_range_locked', 'en', 'This sequence is locked and cannot be modified', '', 'compte.php', '', 0, 1, '', '', '', NOW() +FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM info WHERE info_clef = 'bib_v4_ajax_range_locked' AND info_langue = 'en' AND info_prg = 'compte.php');