This commit introduces a new feature for generating and managing PDF distributions of bibs. It adds a new AJAX action to handle requests for the distribution panel, along with corresponding JavaScript functions to refresh and initialize the panel. CSS styles are updated to enhance the layout of the distribution panel, and new PHP functions are added to support the generation and metadata handling for the PDF prints. The version code is incremented to 4.72.759 to reflect these changes.
3046 lines
118 KiB
JavaScript
3046 lines
118 KiB
JavaScript
/**
|
||
* MSIN-4435 — Bib assignments v4 (#module-bib)
|
||
* Chargé uniquement sur inc_tableau_gestion_epreuves.
|
||
*/
|
||
(function () {
|
||
'use strict';
|
||
const moduleBib = document.getElementById('module-bib');
|
||
|
||
|
||
if (moduleBib) {
|
||
|
||
function bibAjaxLangSuffix() {
|
||
var lang = moduleBib.dataset.lang || 'fr';
|
||
return '&lang=' + encodeURIComponent(lang)
|
||
+ '&csrf_token=' + encodeURIComponent(bibCsrfToken());
|
||
}
|
||
|
||
function bibJs(attr) {
|
||
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);
|
||
var i = 0;
|
||
return tpl.replace(/%d/g, function () {
|
||
return String(args[i++] ?? 0);
|
||
});
|
||
}
|
||
|
||
var bibLoaderDepth = 0;
|
||
|
||
function bibLoaderShow() {
|
||
if (!window.Ms1Loader) {
|
||
return;
|
||
}
|
||
bibLoaderDepth++;
|
||
if (bibLoaderDepth === 1) {
|
||
var msg = bibJs('jsLoaderWait');
|
||
Ms1Loader.show(msg || undefined);
|
||
}
|
||
}
|
||
|
||
function bibLoaderHide() {
|
||
if (!window.Ms1Loader) {
|
||
return;
|
||
}
|
||
bibLoaderDepth = Math.max(0, bibLoaderDepth - 1);
|
||
if (bibLoaderDepth === 0) {
|
||
Ms1Loader.hide();
|
||
}
|
||
}
|
||
|
||
/** fetch ajax_bib_range.php — loader plein ecran par defaut (compteur si appels imbriques). */
|
||
function bibFetch(url, options, settings) {
|
||
settings = settings || {};
|
||
var useLoader = settings.loader !== false;
|
||
if (useLoader) {
|
||
bibLoaderShow();
|
||
}
|
||
return fetch(url, options).finally(function () {
|
||
if (useLoader) {
|
||
bibLoaderHide();
|
||
}
|
||
});
|
||
}
|
||
|
||
var BIB_BATCH_CHUNK_SIZE = 50;
|
||
|
||
function bibBatchProgressShow(processed, total) {
|
||
var intTotal = total > 0 ? total : 1;
|
||
var msg = bibJsFmt('jsBatchProgress', processed, intTotal);
|
||
if (window.Ms1Loader && Ms1Loader.showProgress) {
|
||
Ms1Loader.showProgress(processed, intTotal, msg);
|
||
} else {
|
||
bibLoaderShow();
|
||
}
|
||
}
|
||
|
||
function bibBatchProgressHide() {
|
||
if (window.Ms1Loader && Ms1Loader.hide) {
|
||
Ms1Loader.hide();
|
||
} else {
|
||
bibLoaderHide();
|
||
}
|
||
}
|
||
|
||
/** MSIN-4436 — Force la fermeture du loader (batch global : évite overlay bloqué). */
|
||
function bibBatchProgressForceHide() {
|
||
bibLoaderDepth = 0;
|
||
bibBatchProgressHide();
|
||
}
|
||
|
||
function bibAfterBatchGoSuccess(row, data, isResetMode, options) {
|
||
options = options || {};
|
||
let existing = document.querySelector('.epr-row-view');
|
||
if (existing) {
|
||
existing.remove();
|
||
}
|
||
|
||
if (data.html) {
|
||
row.insertAdjacentHTML('afterend', data.html);
|
||
}
|
||
|
||
bibAfterBatchGoRefreshOnly(row, isResetMode, options);
|
||
}
|
||
|
||
function bibAfterBatchGoRefreshOnly(row, isResetMode, options) {
|
||
options = options || {};
|
||
if (!row) {
|
||
return Promise.resolve();
|
||
}
|
||
|
||
if (isResetMode) {
|
||
row.classList.remove('reset-mode');
|
||
row.dataset.mode = '';
|
||
|
||
let btnReset = row.querySelector('.btn-reset');
|
||
if (btnReset) {
|
||
btnReset.textContent = row.dataset.resetLabel || btnReset.textContent;
|
||
}
|
||
}
|
||
row.classList.remove('batch-mode');
|
||
|
||
let container = row.querySelector('.bib-container');
|
||
if (container) {
|
||
container.classList.remove('batch-mode');
|
||
}
|
||
|
||
let btnBatch = row.querySelector('.btn-assign-batch');
|
||
if (btnBatch) {
|
||
btnBatch.textContent = row.dataset.batchLabel || btnBatch.textContent;
|
||
}
|
||
|
||
row.querySelectorAll('.bib-start, .bib-qty, .bib-end').forEach(input => {
|
||
input.removeAttribute('readonly');
|
||
});
|
||
|
||
row.querySelectorAll('.batch-select-range').forEach(cb => {
|
||
cb.checked = false;
|
||
cb.disabled = false;
|
||
});
|
||
|
||
syncBibUiState(row);
|
||
|
||
var useLoader = options.loader !== false;
|
||
var skipAnomalies = options.skipAnomalies === true;
|
||
var refreshLite = options.refreshLite === true || isResetMode === true;
|
||
|
||
return bibFetch('/ajax_bib_range.php', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||
body:
|
||
'action=refresh_ranges'
|
||
+ '&epr_id=' + encodeURIComponent(row.dataset.eprId)
|
||
+ '&mode=assign'
|
||
+ (refreshLite ? '&lite=1' : '')
|
||
+ bibAjaxLangSuffix()
|
||
}, { loader: useLoader })
|
||
.then(function (res) {
|
||
if (!res.ok) {
|
||
throw new Error(bibJs('jsErrGeneric'));
|
||
}
|
||
return res.json();
|
||
})
|
||
.then(function (refresh) {
|
||
|
||
if (!refresh.success) {
|
||
return;
|
||
}
|
||
|
||
let containerRef = setBibContainerHtml(row, refresh.html, { skipAnomalies: skipAnomalies });
|
||
if (!containerRef) {
|
||
return;
|
||
}
|
||
|
||
return bibFetch('/ajax_bib_range.php', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/x-www-form-urlencoded'
|
||
},
|
||
body:
|
||
'action=batch_analysis'
|
||
+ '&epr_id=' + encodeURIComponent(row.dataset.eprId)
|
||
+ bibAjaxLangSuffix()
|
||
}, { loader: false })
|
||
.then(function (res) { return res.json(); })
|
||
.then(function (stats) {
|
||
|
||
if (!stats.success) {
|
||
return;
|
||
}
|
||
|
||
bibSyncEprBibStats(row, stats.info);
|
||
syncBibUiState(row);
|
||
});
|
||
});
|
||
}
|
||
|
||
function bibGetRowSortKeys(row) {
|
||
if (!row) {
|
||
return { sort1: '', sort2: '' };
|
||
}
|
||
var s1 = row.querySelector('.batch-order');
|
||
var s2 = row.querySelector('.batch-order-2');
|
||
return {
|
||
sort1: s1 ? s1.value : '',
|
||
sort2: s2 ? s2.value : ''
|
||
};
|
||
}
|
||
|
||
function bibGetGlobalBatchSortKeys(panel) {
|
||
if (!panel) {
|
||
return { sort1: '', sort2: '' };
|
||
}
|
||
var s1 = panel.querySelector('.bib-global-batch-order');
|
||
var s2 = panel.querySelector('.bib-global-batch-order-2');
|
||
return {
|
||
sort1: s1 ? s1.value : '',
|
||
sort2: s2 ? s2.value : ''
|
||
};
|
||
}
|
||
|
||
function bibAppendBatchSortParams(body, sortKeys) {
|
||
sortKeys = sortKeys || {};
|
||
return body
|
||
+ '&sort_1=' + encodeURIComponent(sortKeys.sort1 || '')
|
||
+ '&sort_2=' + encodeURIComponent(sortKeys.sort2 || '');
|
||
}
|
||
|
||
function bibFetchBatchApplyChunk(row, selected, sortKeys, opts) {
|
||
opts = opts || {};
|
||
sortKeys = sortKeys || bibGetRowSortKeys(row);
|
||
var body =
|
||
'action=batch_apply_chunk'
|
||
+ '&epr_id=' + encodeURIComponent(row.dataset.eprId)
|
||
+ '&ranges=' + encodeURIComponent(JSON.stringify(selected))
|
||
+ bibAppendBatchSortParams('', sortKeys)
|
||
+ '&chunk_size=' + BIB_BATCH_CHUNK_SIZE
|
||
+ '&total_initial=' + (opts.totalInitial || 0)
|
||
+ '&batch_reset=' + (opts.batchReset ? 1 : 0)
|
||
+ bibAjaxLangSuffix();
|
||
|
||
return fetch('/ajax_bib_range.php', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||
body: body
|
||
})
|
||
.then(function (res) {
|
||
if (!res.ok) {
|
||
throw new Error(bibJs('jsErrGeneric'));
|
||
}
|
||
return res.json();
|
||
})
|
||
.catch(function (err) {
|
||
if (err && err.message) {
|
||
throw err;
|
||
}
|
||
throw new Error(bibJs('jsErrGeneric'));
|
||
});
|
||
}
|
||
|
||
function bibRunBatchApplyChunks(row, selected, sortKeys, options) {
|
||
options = options || {};
|
||
var showResult = options.showResult !== false;
|
||
var manageLoader = options.manageLoader !== false;
|
||
var deferUiRefresh = options.deferUiRefresh === true;
|
||
var onProgress = options.onProgress;
|
||
var totalInitial = options.totalInitial > 0
|
||
? options.totalInitial
|
||
: bibRowPendingBibs(row);
|
||
var batchReset = true;
|
||
var chunkGuard = 0;
|
||
var maxChunks = Math.max(50, Math.ceil((totalInitial || 1) / BIB_BATCH_CHUNK_SIZE) + 5);
|
||
|
||
if (manageLoader) {
|
||
bibBatchProgressShow(0, totalInitial > 0 ? totalInitial : 1);
|
||
}
|
||
|
||
function runChunk() {
|
||
chunkGuard++;
|
||
if (chunkGuard > maxChunks) {
|
||
return Promise.reject(new Error(bibJs('jsErrGeneric')));
|
||
}
|
||
|
||
return bibFetchBatchApplyChunk(row, selected, sortKeys, {
|
||
batchReset: batchReset,
|
||
totalInitial: totalInitial
|
||
}).then(function (data) {
|
||
if (!data || !data.success) {
|
||
throw new Error((data && data.message) || bibJs('jsErrGeneric'));
|
||
}
|
||
|
||
if (data.total_initial) {
|
||
totalInitial = data.total_initial;
|
||
}
|
||
batchReset = false;
|
||
|
||
var processed = data.processed || 0;
|
||
if (onProgress) {
|
||
onProgress(processed, totalInitial);
|
||
} else if (manageLoader) {
|
||
bibBatchProgressShow(processed, totalInitial);
|
||
}
|
||
|
||
if (data.complete) {
|
||
if (showResult) {
|
||
bibAfterBatchGoSuccess(row, data, false);
|
||
} else if (!deferUiRefresh) {
|
||
bibAfterBatchGoRefreshOnly(row, false, { loader: false, skipAnomalies: true });
|
||
}
|
||
return data;
|
||
}
|
||
|
||
return runChunk();
|
||
});
|
||
}
|
||
|
||
return runChunk()
|
||
.catch(function (err) {
|
||
if (manageLoader) {
|
||
alert(err.message || bibJs('jsErrGeneric'));
|
||
}
|
||
throw err;
|
||
})
|
||
.finally(function () {
|
||
if (manageLoader) {
|
||
bibBatchProgressHide();
|
||
}
|
||
});
|
||
}
|
||
|
||
// MSIN-4436 — Batch global (épreuves solo), chargement différé à l'ouverture.
|
||
var bibGlobalBatchLoadPromise = null;
|
||
|
||
function bibGetGlobalBatchPanel() {
|
||
return document.getElementById('bib-global-batch');
|
||
}
|
||
|
||
function bibEnsureGlobalBatchPanelLoaded() {
|
||
var mount = document.getElementById('bib-global-batch-mount');
|
||
var panel = bibGetGlobalBatchPanel();
|
||
|
||
if (!mount || !panel) {
|
||
return Promise.resolve(null);
|
||
}
|
||
|
||
if (panel.getAttribute('data-global-batch-loaded') === '1') {
|
||
return Promise.resolve(panel);
|
||
}
|
||
|
||
if (bibGlobalBatchLoadPromise) {
|
||
return bibGlobalBatchLoadPromise;
|
||
}
|
||
|
||
bibGlobalBatchLoadPromise = bibFetch('/ajax_bib_range.php', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||
body:
|
||
'action=global_batch_panel'
|
||
+ '&eve_id=' + encodeURIComponent(moduleBib.dataset.eveId || '')
|
||
+ bibAjaxLangSuffix()
|
||
})
|
||
.then(function (res) { return res.json(); })
|
||
.then(function (data) {
|
||
if (!data.success || !data.html) {
|
||
throw new Error(data.message || bibJs('jsErrGeneric'));
|
||
}
|
||
|
||
mount.innerHTML = data.html;
|
||
panel = bibGetGlobalBatchPanel();
|
||
if (panel) {
|
||
panel.setAttribute('data-global-batch-loaded', '1');
|
||
panel.removeAttribute('data-global-batch-deferred');
|
||
}
|
||
return panel;
|
||
})
|
||
.finally(function () {
|
||
bibGlobalBatchLoadPromise = null;
|
||
});
|
||
|
||
return bibGlobalBatchLoadPromise;
|
||
}
|
||
|
||
function bibGlobalBatchSetToggleState(toggle, isOpen) {
|
||
if (!toggle) {
|
||
return;
|
||
}
|
||
toggle.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
|
||
var label = isOpen
|
||
? (toggle.getAttribute('data-label-close') || '')
|
||
: (toggle.getAttribute('data-label-open') || '');
|
||
if (label) {
|
||
toggle.textContent = label;
|
||
}
|
||
}
|
||
|
||
function bibGlobalBatchOpenPanel(panel) {
|
||
if (!panel) {
|
||
return;
|
||
}
|
||
var body = panel.querySelector('.bib-global-batch__body');
|
||
var toggle = panel.querySelector('.bib-global-batch-toggle');
|
||
if (body) {
|
||
body.classList.remove('bib-ui-hidden');
|
||
}
|
||
bibGlobalBatchSetToggleState(toggle, true);
|
||
updateGlobalBatchAnalysis();
|
||
}
|
||
|
||
function bibSetGlobalBatchInfo(infoEl, text, state) {
|
||
if (!infoEl) {
|
||
return;
|
||
}
|
||
|
||
infoEl.textContent = text || '';
|
||
infoEl.classList.remove('text-muted', 'text-danger', 'text-warning', 'text-success');
|
||
|
||
if (state === 'error') {
|
||
infoEl.classList.add('text-danger');
|
||
} else if (state === 'warning') {
|
||
infoEl.classList.add('text-warning');
|
||
} else if (state === 'ok') {
|
||
infoEl.classList.add('text-success');
|
||
} else {
|
||
infoEl.classList.add('text-muted');
|
||
}
|
||
}
|
||
|
||
function bibCollectGlobalBatchPlans() {
|
||
var bibGlobalBatchPanel = bibGetGlobalBatchPanel();
|
||
if (!bibGlobalBatchPanel) {
|
||
return [];
|
||
}
|
||
|
||
var plans = [];
|
||
bibGlobalBatchPanel.querySelectorAll('.bib-global-epr').forEach(function (eprBlock) {
|
||
var eprCb = eprBlock.querySelector('.bib-global-epr-select');
|
||
if (!eprCb || !eprCb.checked) {
|
||
return;
|
||
}
|
||
|
||
var eprId = parseInt(eprCb.dataset.eprId || eprBlock.dataset.eprId || '0', 10);
|
||
if (!eprId) {
|
||
return;
|
||
}
|
||
|
||
var ranges = [];
|
||
eprBlock.querySelectorAll('.bib-global-range-select:checked').forEach(function (rangeCb) {
|
||
ranges.push(rangeCb.dataset.rangeId);
|
||
});
|
||
|
||
if (ranges.length > 0) {
|
||
plans.push({ epr_id: eprId, ranges: ranges });
|
||
}
|
||
});
|
||
|
||
return plans;
|
||
}
|
||
|
||
function updateGlobalBatchAnalysis() {
|
||
var bibGlobalBatchPanel = bibGetGlobalBatchPanel();
|
||
if (!bibGlobalBatchPanel) {
|
||
return Promise.resolve();
|
||
}
|
||
|
||
var plans = bibCollectGlobalBatchPlans();
|
||
var infoEl = bibGlobalBatchPanel.querySelector('.bib-global-batch__info');
|
||
var sortKeys = bibGetGlobalBatchSortKeys(bibGlobalBatchPanel);
|
||
|
||
if (!infoEl) {
|
||
return Promise.resolve();
|
||
}
|
||
|
||
if (plans.length === 0) {
|
||
bibSetGlobalBatchInfo(
|
||
infoEl,
|
||
bibJs('jsGlobalNoEpr') || bibJs('jsBatchNone'),
|
||
'error'
|
||
);
|
||
return Promise.resolve(null);
|
||
}
|
||
|
||
var hasRange = plans.some(function (p) { return p.ranges.length > 0; });
|
||
if (!hasRange) {
|
||
bibSetGlobalBatchInfo(
|
||
infoEl,
|
||
bibJs('jsGlobalNoSeq') || bibJs('jsNoSeqSelected'),
|
||
'error'
|
||
);
|
||
return Promise.resolve(null);
|
||
}
|
||
|
||
bibSetGlobalBatchInfo(infoEl, bibJs('jsLoaderWait') || '…', 'normal');
|
||
|
||
return fetch('/ajax_bib_range.php', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||
body:
|
||
'action=batch_global_analysis'
|
||
+ '&eve_id=' + encodeURIComponent(moduleBib.dataset.eveId || '')
|
||
+ bibAppendBatchSortParams('', sortKeys)
|
||
+ '&plans=' + encodeURIComponent(JSON.stringify(plans))
|
||
+ bibAjaxLangSuffix()
|
||
})
|
||
.then(function (res) { return res.json(); })
|
||
.then(function (data) {
|
||
if (!data.success) {
|
||
bibSetGlobalBatchInfo(
|
||
infoEl,
|
||
data.message || bibJs('jsErrGeneric'),
|
||
'error'
|
||
);
|
||
return data;
|
||
}
|
||
|
||
var state = (data.stats && data.stats.nb_manque > 0) ? 'warning' : 'normal';
|
||
bibSetGlobalBatchInfo(infoEl, data.info || '', state);
|
||
return data;
|
||
})
|
||
.catch(function () {
|
||
bibSetGlobalBatchInfo(infoEl, bibJs('jsErrGeneric'), 'error');
|
||
return null;
|
||
});
|
||
}
|
||
|
||
function bibRunGlobalBatchGo() {
|
||
var bibGlobalBatchPanel = bibGetGlobalBatchPanel();
|
||
if (!bibGlobalBatchPanel) {
|
||
return;
|
||
}
|
||
|
||
var plans = bibCollectGlobalBatchPlans();
|
||
var sortKeys = bibGetGlobalBatchSortKeys(bibGlobalBatchPanel);
|
||
|
||
if (plans.length === 0) {
|
||
alert(bibJs('jsGlobalNoEpr') || bibJs('jsBatchNone'));
|
||
return;
|
||
}
|
||
|
||
if (!plans.some(function (p) { return p.ranges.length > 0; })) {
|
||
alert(bibJs('jsGlobalNoSeq') || bibJs('jsNoSeqSelected'));
|
||
return;
|
||
}
|
||
|
||
fetch('/ajax_bib_range.php', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||
body:
|
||
'action=batch_global_analysis'
|
||
+ '&eve_id=' + encodeURIComponent(moduleBib.dataset.eveId || '')
|
||
+ bibAppendBatchSortParams('', sortKeys)
|
||
+ '&plans=' + encodeURIComponent(JSON.stringify(plans))
|
||
+ bibAjaxLangSuffix()
|
||
})
|
||
.then(function (res) {
|
||
if (!res.ok) {
|
||
throw new Error(bibJs('jsErrGeneric'));
|
||
}
|
||
return res.json();
|
||
})
|
||
.then(function (analysis) {
|
||
if (!analysis || !analysis.success) {
|
||
throw new Error((analysis && analysis.message) || bibJs('jsErrGeneric'));
|
||
}
|
||
|
||
var globalTotal = (analysis.stats && analysis.stats.nb_participants)
|
||
? analysis.stats.nb_participants
|
||
: 1;
|
||
var completedOffset = 0;
|
||
var runResults = [];
|
||
|
||
bibBatchProgressShow(0, globalTotal);
|
||
|
||
var chain = Promise.resolve();
|
||
|
||
plans.forEach(function (plan) {
|
||
chain = chain.then(function () {
|
||
var row = moduleBib.querySelector('.epr-row[data-epr-id="' + plan.epr_id + '"]');
|
||
if (!row) {
|
||
throw new Error(bibJs('jsErrGeneric'));
|
||
}
|
||
|
||
var pendingBefore = bibRowPendingBibs(row);
|
||
var offset = completedOffset;
|
||
|
||
return bibRunBatchApplyChunks(row, plan.ranges, sortKeys, {
|
||
showResult: false,
|
||
manageLoader: false,
|
||
deferUiRefresh: true,
|
||
totalInitial: pendingBefore,
|
||
onProgress: function (processed) {
|
||
bibBatchProgressShow(offset + processed, globalTotal);
|
||
}
|
||
}).then(function (data) {
|
||
runResults.push({
|
||
epr_id: plan.epr_id,
|
||
assigned: data.assigned_total || 0,
|
||
total: data.total_initial || pendingBefore
|
||
});
|
||
completedOffset = offset + pendingBefore;
|
||
});
|
||
});
|
||
});
|
||
|
||
return chain.then(function () {
|
||
bibBatchProgressShow(globalTotal, globalTotal);
|
||
|
||
var refreshChain = Promise.resolve();
|
||
runResults.forEach(function (result) {
|
||
refreshChain = refreshChain.then(function () {
|
||
var row = moduleBib.querySelector('.epr-row[data-epr-id="' + result.epr_id + '"]');
|
||
if (!row) {
|
||
return null;
|
||
}
|
||
return bibAfterBatchGoRefreshOnly(row, false, {
|
||
loader: false,
|
||
skipAnomalies: true
|
||
});
|
||
});
|
||
});
|
||
|
||
return refreshChain.then(function () {
|
||
if (typeof refreshBibAnomaliesPanel === 'function') {
|
||
refreshBibAnomaliesPanel();
|
||
}
|
||
|
||
var panelRef = bibGetGlobalBatchPanel();
|
||
var infoEl = panelRef ? panelRef.querySelector('.bib-global-batch__info') : null;
|
||
var totalAssigned = 0;
|
||
var totalExpected = 0;
|
||
|
||
runResults.forEach(function (result) {
|
||
totalAssigned += result.assigned;
|
||
totalExpected += result.total;
|
||
});
|
||
|
||
var remaining = Math.max(0, totalExpected - totalAssigned);
|
||
|
||
return updateGlobalBatchAnalysis().then(function () {
|
||
if (totalAssigned === 0 && totalExpected > 0) {
|
||
var msgNone = bibJs('jsAssignNone') || bibJs('jsErrGeneric');
|
||
bibSetGlobalBatchInfo(infoEl, msgNone, 'error');
|
||
alert(msgNone);
|
||
} else if (remaining > 0) {
|
||
var msgPartial = bibJsFmt('jsAssignPartial', totalAssigned, remaining);
|
||
bibSetGlobalBatchInfo(infoEl, msgPartial, 'warning');
|
||
alert(msgPartial);
|
||
} else if (totalAssigned > 0) {
|
||
bibSetGlobalBatchInfo(
|
||
infoEl,
|
||
bibJsFmt('jsAssignFull', totalAssigned),
|
||
'ok'
|
||
);
|
||
}
|
||
});
|
||
});
|
||
});
|
||
})
|
||
.catch(function (err) {
|
||
alert(err.message || bibJs('jsErrGeneric'));
|
||
})
|
||
.finally(function () {
|
||
bibBatchProgressForceHide();
|
||
});
|
||
}
|
||
|
||
moduleBib.addEventListener('click', function (e) {
|
||
var globalToggle = e.target.closest('.bib-global-batch-toggle');
|
||
if (globalToggle) {
|
||
var panel = globalToggle.closest('#bib-global-batch');
|
||
if (!panel) {
|
||
return;
|
||
}
|
||
|
||
var body = panel.querySelector('.bib-global-batch__body');
|
||
if (!body) {
|
||
return;
|
||
}
|
||
|
||
var willOpen = body.classList.contains('bib-ui-hidden');
|
||
|
||
if (willOpen && panel.getAttribute('data-global-batch-deferred') === '1') {
|
||
bibEnsureGlobalBatchPanelLoaded()
|
||
.then(function (loadedPanel) {
|
||
if (!loadedPanel) {
|
||
return;
|
||
}
|
||
bibGlobalBatchOpenPanel(loadedPanel);
|
||
})
|
||
.catch(function (err) {
|
||
alert(err.message || bibJs('jsErrGeneric'));
|
||
});
|
||
return;
|
||
}
|
||
|
||
var hidden = body.classList.toggle('bib-ui-hidden');
|
||
bibGlobalBatchSetToggleState(globalToggle, !hidden);
|
||
if (!hidden) {
|
||
updateGlobalBatchAnalysis();
|
||
}
|
||
return;
|
||
}
|
||
|
||
if (e.target.closest('.btn-simuler-global-batch')) {
|
||
e.preventDefault();
|
||
var bibGlobalBatchPanel = bibGetGlobalBatchPanel();
|
||
var plans = bibCollectGlobalBatchPlans();
|
||
var sortKeys = bibGlobalBatchPanel
|
||
? bibGetGlobalBatchSortKeys(bibGlobalBatchPanel)
|
||
: { sort1: '', sort2: '' };
|
||
|
||
if (plans.length === 0) {
|
||
alert(bibJs('jsGlobalNoEpr') || bibJs('jsBatchNone'));
|
||
return;
|
||
}
|
||
|
||
bibFetch('/ajax_bib_range.php', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||
body:
|
||
'action=batch_global_simulate'
|
||
+ '&eve_id=' + encodeURIComponent(moduleBib.dataset.eveId || '')
|
||
+ bibAppendBatchSortParams('', sortKeys)
|
||
+ '&plans=' + encodeURIComponent(JSON.stringify(plans))
|
||
+ bibAjaxLangSuffix()
|
||
})
|
||
.then(function (res) { return res.json(); })
|
||
.then(function (data) {
|
||
if (!data.success) {
|
||
alert(data.message || bibJs('jsErrGeneric'));
|
||
return;
|
||
}
|
||
|
||
var existing = document.querySelector('.epr-row-view');
|
||
if (existing) {
|
||
existing.remove();
|
||
}
|
||
|
||
var anchor = bibGetGlobalBatchPanel();
|
||
if (anchor) {
|
||
anchor.insertAdjacentHTML('afterend', data.html);
|
||
}
|
||
});
|
||
|
||
return;
|
||
}
|
||
|
||
if (e.target.closest('.btn-go-global-batch')) {
|
||
e.preventDefault();
|
||
bibRunGlobalBatchGo();
|
||
}
|
||
});
|
||
|
||
moduleBib.addEventListener('change', function (e) {
|
||
if (!e.target.matches('.bib-global-epr-select, .bib-global-range-select, .bib-global-batch-order, .bib-global-batch-order-2')) {
|
||
return;
|
||
}
|
||
|
||
var bibGlobalBatchPanel = bibGetGlobalBatchPanel();
|
||
if (!bibGlobalBatchPanel || !bibGlobalBatchPanel.contains(e.target)) {
|
||
return;
|
||
}
|
||
|
||
var eprBlock = e.target.closest('.bib-global-epr');
|
||
if (eprBlock && e.target.classList.contains('bib-global-epr-select')) {
|
||
var checked = e.target.checked;
|
||
eprBlock.querySelectorAll('.bib-global-range-select').forEach(function (cb) {
|
||
cb.disabled = !checked;
|
||
if (!checked) {
|
||
cb.checked = false;
|
||
}
|
||
});
|
||
}
|
||
updateGlobalBatchAnalysis();
|
||
});
|
||
|
||
function bibRowPendingBibs(row) {
|
||
if (!row) return 0;
|
||
return parseInt(row.dataset.bibAAssigner || '0', 10) || 0;
|
||
}
|
||
|
||
function bibSyncEprBibStats(row, info) {
|
||
if (!row || !info) return;
|
||
|
||
if (info.total !== undefined) {
|
||
let totalEl = row.querySelector('.bib-total');
|
||
if (totalEl) totalEl.textContent = info.total;
|
||
}
|
||
if (info.avec_bib !== undefined) {
|
||
let avecEl = row.querySelector('.bib-avec');
|
||
if (avecEl) avecEl.textContent = info.avec_bib;
|
||
}
|
||
|
||
let pending = (info.a_assigner !== undefined && info.a_assigner !== null)
|
||
? info.a_assigner
|
||
: (info.sans_bib || 0);
|
||
row.dataset.bibAAssigner = String(parseInt(pending, 10) || 0);
|
||
}
|
||
|
||
function bibAlertAutoPendingBibs(row) {
|
||
alert(bibJsFmt('jsAutoPendingBibs', bibRowPendingBibs(row)).replace(/\\n/g, '\n'));
|
||
}
|
||
|
||
/** Bloque l'entrée en mode auto si des inscriptions n'ont pas encore de dossard. */
|
||
function bibBlockAutoActivation(row) {
|
||
if (!row || row.dataset.autoActive === '1') {
|
||
return false;
|
||
}
|
||
if (bibRowPendingBibs(row) > 0) {
|
||
bibAlertAutoPendingBibs(row);
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
// MSIN-4379 — Mise à jour affichage quantités (panneau gestion + pastille en-tête).
|
||
function bibApplyQteData(data) {
|
||
if (!data || typeof data !== 'object') {
|
||
return;
|
||
}
|
||
|
||
Object.keys(data).forEach(function (eprId) {
|
||
if (eprId === 'total') {
|
||
return;
|
||
}
|
||
|
||
let row = data[eprId];
|
||
if (!row) {
|
||
return;
|
||
}
|
||
|
||
let elOrigine = document.getElementById('qte_origine_' + eprId);
|
||
let elAjustement = document.getElementById('qte_ajustement_' + eprId);
|
||
let elCourante = document.getElementById('qte_courante_' + eprId);
|
||
let elInscrits = document.getElementById('qte_inscrits_' + eprId);
|
||
let elCheckin = document.getElementById('qte_checkin_' + eprId);
|
||
let elRestante = document.getElementById('qte_restante_' + eprId);
|
||
|
||
if (elOrigine) {
|
||
elOrigine.textContent = row.qte_origine;
|
||
}
|
||
if (elAjustement) {
|
||
elAjustement.textContent = row.qte_ajustement;
|
||
}
|
||
if (elCourante) {
|
||
elCourante.textContent = row.qte_courante;
|
||
}
|
||
if (elInscrits) {
|
||
elInscrits.textContent = row.qte_inscrits;
|
||
}
|
||
if (elCheckin) {
|
||
elCheckin.textContent = row.qte_checkin;
|
||
}
|
||
if (elRestante) {
|
||
elRestante.value = row.qte_restante;
|
||
}
|
||
|
||
let dispoBadge = document.querySelector(
|
||
'.epr-row[data-epr-id="' + eprId + '"] .epr-header-summary--dispo'
|
||
);
|
||
if (dispoBadge && row.qte_restante !== undefined) {
|
||
let labelParts = dispoBadge.textContent.split(':');
|
||
let label = labelParts.length > 1 ? labelParts[0].trim() : '';
|
||
dispoBadge.textContent = label + ' : ' + row.qte_restante;
|
||
}
|
||
|
||
let btnQte = document.querySelector(
|
||
'.epr-gestion-panel[data-epr-id="' + eprId + '"] .btn_qte'
|
||
);
|
||
if (btnQte) {
|
||
btnQte.setAttribute('data-qte_initiale', row.qte_restante);
|
||
}
|
||
});
|
||
}
|
||
|
||
function bibSaveQte(btn) {
|
||
let eprId = btn.getAttribute('data-epr_id');
|
||
if (!eprId) {
|
||
return;
|
||
}
|
||
|
||
let input = document.getElementById('qte_restante_' + eprId);
|
||
if (!input) {
|
||
return;
|
||
}
|
||
|
||
let intQte = parseInt(input.value, 10);
|
||
if (isNaN(intQte) || intQte < 0) {
|
||
alert(bibJs('err-generic'));
|
||
return;
|
||
}
|
||
|
||
bibLoaderShow();
|
||
fetch('/ajax_promoteur.php', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/x-www-form-urlencoded'
|
||
},
|
||
credentials: 'same-origin',
|
||
body:
|
||
'a=qte'
|
||
+ '&epr_id=' + encodeURIComponent(eprId)
|
||
+ '&qte=' + encodeURIComponent(intQte)
|
||
+ '&lang=' + encodeURIComponent(moduleBib.dataset.lang || 'fr')
|
||
})
|
||
.then(function (res) {
|
||
return res.json();
|
||
})
|
||
.then(function (result) {
|
||
if (result && result.state === 'success' && result.data) {
|
||
bibApplyQteData(result.data);
|
||
return;
|
||
}
|
||
alert(bibJs('err-generic'));
|
||
})
|
||
.catch(function () {
|
||
alert(bibJs('server-error'));
|
||
})
|
||
.finally(function () {
|
||
bibLoaderHide();
|
||
});
|
||
}
|
||
|
||
// MSIN-4379 — Réduire / développer les blocs gestion et assignation (en-tête seul visible).
|
||
moduleBib.addEventListener('click', function (e) {
|
||
let btnToggle = e.target.closest('.epr-block-toggle');
|
||
if (!btnToggle || !moduleBib.contains(btnToggle)) {
|
||
return;
|
||
}
|
||
let block = btnToggle.closest('.epr-block');
|
||
if (!block) {
|
||
return;
|
||
}
|
||
let collapsed = block.classList.toggle('is-collapsed');
|
||
btnToggle.setAttribute('aria-expanded', collapsed ? 'false' : 'true');
|
||
let label = collapsed
|
||
? (btnToggle.getAttribute('data-label-expand') || '')
|
||
: (btnToggle.getAttribute('data-label-collapse') || '');
|
||
if (label) {
|
||
btnToggle.setAttribute('aria-label', label);
|
||
btnToggle.setAttribute('title', label);
|
||
}
|
||
let icon = btnToggle.querySelector('.fa');
|
||
if (icon) {
|
||
icon.classList.toggle('fa-chevron-up', !collapsed);
|
||
icon.classList.toggle('fa-chevron-down', collapsed);
|
||
}
|
||
|
||
// MSIN-4424 — Sommaire quantités : chargement à la première ouverture.
|
||
if (!collapsed && block.id === 'bib-qty-summary-panel'
|
||
&& block.getAttribute('data-bib-qty-summary-deferred') === '1') {
|
||
refreshBibQtySummaryPanel();
|
||
}
|
||
|
||
// MSIN-4433 — Impression PDF : chargement à la première ouverture.
|
||
if (!collapsed && block.id === 'bib-dist-print-panel'
|
||
&& block.getAttribute('data-bib-dist-print-deferred') === '1') {
|
||
refreshBibDistPrintPanel();
|
||
}
|
||
});
|
||
|
||
// ============================================================
|
||
// MSIN-4379 — Tippy.js (module #module-bib uniquement)
|
||
// info_texte → data-tippy-content (tip court)
|
||
// info_aide → data-tippy-content sur .btn-aide-bib (pop-up long)
|
||
// Ré-init après chaque refresh AJAX des séquences.
|
||
// ============================================================
|
||
|
||
function getBibContainer(row) {
|
||
if (!row) return null;
|
||
return row.querySelector('.epr-block-assign .epr-table.bib-container')
|
||
|| row.querySelector('.epr-table.bib-container')
|
||
|| row.querySelector('.epr-block-assign .bib-container')
|
||
|| row.querySelector('.bib-container');
|
||
}
|
||
|
||
function bibTippyEscapeHtml(str) {
|
||
return String(str)
|
||
.replace(/&/g, '&')
|
||
.replace(/</g, '<')
|
||
.replace(/>/g, '>')
|
||
.replace(/"/g, '"');
|
||
}
|
||
|
||
function bibTippyAideContent(reference) {
|
||
let span = reference.querySelector('.bib-aide-text');
|
||
if (!span) {
|
||
return '';
|
||
}
|
||
// Mini-formatage : retours à la ligne → <br> ; double saut → paragraphe.
|
||
let lines = span.textContent.replace(/\r\n/g, '\n').replace(/\r/g, '\n').trim().split('\n');
|
||
let html = '';
|
||
let para = [];
|
||
lines.forEach(function (line) {
|
||
if (line.trim() === '') {
|
||
if (para.length) {
|
||
html += '<p>' + para.join('<br>') + '</p>';
|
||
para = [];
|
||
}
|
||
} else {
|
||
para.push(bibTippyEscapeHtml(line));
|
||
}
|
||
});
|
||
if (para.length) {
|
||
html += '<p>' + para.join('<br>') + '</p>';
|
||
}
|
||
return html;
|
||
}
|
||
|
||
function initModuleBibTippy(root) {
|
||
if (typeof tippy === 'undefined') return;
|
||
let scope = root || moduleBib;
|
||
scope.querySelectorAll('[data-tippy-content], .bib-aide-trigger').forEach(function (el) {
|
||
if (el._tippy) {
|
||
el._tippy.destroy();
|
||
}
|
||
});
|
||
|
||
tippy(scope.querySelectorAll('[data-tippy-content]'), {
|
||
theme: 'ms1-bib',
|
||
animation: 'fade',
|
||
allowHTML: false,
|
||
maxWidth: 280,
|
||
interactive: false
|
||
});
|
||
|
||
tippy(scope.querySelectorAll('.bib-aide-trigger'), {
|
||
theme: 'ms1-bib ms1-bib-aide',
|
||
animation: 'fade',
|
||
allowHTML: true,
|
||
maxWidth: 420,
|
||
interactive: true,
|
||
content: bibTippyAideContent
|
||
});
|
||
}
|
||
|
||
/** Visibilité UI v4 — bib-ui-hidden sur le conteneur (bouton + ? ensemble). */
|
||
function bibQuery(row, selector) {
|
||
return (row || moduleBib).querySelector(selector);
|
||
}
|
||
|
||
function bibSetVisible(target, show, row) {
|
||
let el = target;
|
||
if (typeof target === 'string') {
|
||
el = bibQuery(row, target);
|
||
} else if (el && el.nodeType === 1
|
||
&& !el.classList.contains('epr-action-group')
|
||
&& !el.classList.contains('batch-config-container')
|
||
&& !el.classList.contains('auto-config-container')
|
||
&& !el.classList.contains('epr-add-range-row')) {
|
||
el = el.closest('.epr-action-group') || el;
|
||
}
|
||
if (el) {
|
||
el.classList.toggle('bib-ui-hidden', !show);
|
||
}
|
||
}
|
||
|
||
function bibRowModes(row) {
|
||
return {
|
||
batch: row.classList.contains('batch-mode'),
|
||
auto: row.classList.contains('auto-mode'),
|
||
reset: row.classList.contains('reset-mode'),
|
||
};
|
||
}
|
||
|
||
function bibHasSavedSequences(row) {
|
||
return Array.from(row.querySelectorAll('.bib-range[data-id]')).some(function (line) {
|
||
return parseInt(line.getAttribute('data-id') || '0', 10) > 0;
|
||
});
|
||
}
|
||
|
||
function bibCountSelectedRanges(row) {
|
||
return row.querySelectorAll('.batch-select-range:checked').length;
|
||
}
|
||
|
||
/** MSIN-4436 — Développe un bloc repliable #module-bib. */
|
||
function bibExpandBlock(block) {
|
||
if (!block || !block.classList.contains('is-collapsed')) {
|
||
return;
|
||
}
|
||
|
||
block.classList.remove('is-collapsed');
|
||
let btn = block.querySelector('.epr-block-toggle');
|
||
if (btn) {
|
||
btn.setAttribute('aria-expanded', 'true');
|
||
let label = btn.getAttribute('data-label-collapse') || '';
|
||
if (label) {
|
||
btn.setAttribute('aria-label', label);
|
||
btn.setAttribute('title', label);
|
||
}
|
||
let icon = btn.querySelector('.fa');
|
||
if (icon) {
|
||
icon.classList.add('fa-chevron-up');
|
||
icon.classList.remove('fa-chevron-down');
|
||
}
|
||
}
|
||
}
|
||
|
||
let bibFocusApplied = false;
|
||
|
||
/** MSIN-4436 — Retour depuis fiche inscription : rouvrir le panneau ciblé. */
|
||
function bibApplyFocusFromUrlOnce() {
|
||
if (bibFocusApplied) {
|
||
return;
|
||
}
|
||
|
||
let focus = new URLSearchParams(window.location.search).get('bib_focus');
|
||
if (!focus) {
|
||
return;
|
||
}
|
||
|
||
bibFocusApplied = true;
|
||
|
||
let panelId = null;
|
||
if (focus === 'anomalies') {
|
||
panelId = 'bib-anomalies-panel';
|
||
} else if (focus === 'qty_summary') {
|
||
panelId = 'bib-qty-summary-panel';
|
||
} else if (focus === 'dist_print') {
|
||
panelId = 'bib-dist-print-panel';
|
||
} else if (focus === 'event_config') {
|
||
panelId = 'bib-event-config-panel';
|
||
}
|
||
|
||
if (!panelId) {
|
||
return;
|
||
}
|
||
|
||
let panel = document.getElementById(panelId);
|
||
if (!panel) {
|
||
return;
|
||
}
|
||
|
||
bibExpandBlock(panel);
|
||
|
||
if (focus === 'qty_summary' && panel.getAttribute('data-bib-qty-summary-deferred') === '1') {
|
||
refreshBibQtySummaryPanel();
|
||
}
|
||
|
||
if (focus === 'dist_print' && panel.getAttribute('data-bib-dist-print-deferred') === '1') {
|
||
refreshBibDistPrintPanel();
|
||
}
|
||
|
||
panel.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||
}
|
||
|
||
/** MSIN-4379 — Rafraîchit le dashboard anomalies (chien de garde). */
|
||
function refreshBibAnomaliesPanel() {
|
||
let mount = document.getElementById('bib-anomalies-mount');
|
||
if (!mount || !moduleBib) {
|
||
return Promise.resolve();
|
||
}
|
||
|
||
let eveId = moduleBib.dataset.eveId || '';
|
||
if (!eveId) {
|
||
return Promise.resolve();
|
||
}
|
||
|
||
return bibFetch('/ajax_bib_range.php', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/x-www-form-urlencoded'
|
||
},
|
||
body: 'action=anomalies&eve_id=' + encodeURIComponent(eveId) + bibAjaxLangSuffix()
|
||
}, { loader: false })
|
||
.then(function (res) { return res.json(); })
|
||
.then(function (data) {
|
||
if (!data.success || !data.html) {
|
||
return;
|
||
}
|
||
mount.innerHTML = data.html;
|
||
initModuleBibTippy(mount);
|
||
});
|
||
}
|
||
|
||
/** MSIN-4433 — Rafraîchit le panneau impression PDF. */
|
||
function refreshBibDistPrintPanel() {
|
||
let mount = document.getElementById('bib-dist-print-mount');
|
||
if (!mount || !moduleBib) {
|
||
return Promise.resolve();
|
||
}
|
||
|
||
let panel = document.getElementById('bib-dist-print-panel');
|
||
let blnDeferred = panel && panel.getAttribute('data-bib-dist-print-deferred') === '1';
|
||
let blnLoaded = panel && panel.getAttribute('data-bib-dist-print-loaded') === '1';
|
||
if (!blnDeferred && !blnLoaded) {
|
||
return Promise.resolve();
|
||
}
|
||
|
||
let eveId = moduleBib.dataset.eveId || '';
|
||
if (!eveId) {
|
||
return Promise.resolve();
|
||
}
|
||
|
||
let blnWasExpanded = panel && !panel.classList.contains('is-collapsed');
|
||
|
||
return bibFetch('/ajax_bib_range.php', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/x-www-form-urlencoded'
|
||
},
|
||
body: 'action=dist_print_panel&eve_id=' + encodeURIComponent(eveId) + bibAjaxLangSuffix()
|
||
}, { loader: false })
|
||
.then(function (res) { return res.json(); })
|
||
.then(function (data) {
|
||
if (!data.success || !data.html) {
|
||
return;
|
||
}
|
||
mount.innerHTML = data.html;
|
||
initModuleBibTippy(mount);
|
||
initBibDistPrintPanel(mount);
|
||
if (blnWasExpanded) {
|
||
let newPanel = document.getElementById('bib-dist-print-panel');
|
||
if (newPanel) {
|
||
bibExpandBlock(newPanel);
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
/** MSIN-4433 — Limite questions + rafraîchissement après génération PDF. */
|
||
function initBibDistPrintPanel(root) {
|
||
root = root || document;
|
||
let panel = root.querySelector ? root.querySelector('#bib-dist-print-panel') : null;
|
||
if (!panel) {
|
||
panel = document.getElementById('bib-dist-print-panel');
|
||
}
|
||
if (!panel || panel.getAttribute('data-bib-dist-print-init') === '1') {
|
||
return;
|
||
}
|
||
panel.setAttribute('data-bib-dist-print-init', '1');
|
||
|
||
let intMax = parseInt(panel.getAttribute('data-max-questions') || '5', 10);
|
||
if (!intMax || intMax < 1) {
|
||
intMax = 5;
|
||
}
|
||
|
||
panel.addEventListener('change', function (ev) {
|
||
let cb = ev.target;
|
||
if (!cb || !cb.classList || !cb.classList.contains('bib-dist-print-question-cb')) {
|
||
return;
|
||
}
|
||
if (!cb.checked) {
|
||
return;
|
||
}
|
||
let section = cb.closest('.bib-dist-print-epr');
|
||
if (!section) {
|
||
return;
|
||
}
|
||
let tabChecked = section.querySelectorAll('.bib-dist-print-question-cb:checked');
|
||
if (tabChecked.length > intMax) {
|
||
cb.checked = false;
|
||
}
|
||
});
|
||
|
||
let form = panel.querySelector('.bib-dist-print-form');
|
||
if (form) {
|
||
form.addEventListener('submit', function () {
|
||
window.setTimeout(function () {
|
||
refreshBibDistPrintPanel();
|
||
}, 1500);
|
||
});
|
||
}
|
||
}
|
||
|
||
/** MSIN-4424 — Rafraîchit le sommaire des quantités (si déjà chargé ou ouverture). */
|
||
function refreshBibQtySummaryPanel() {
|
||
let mount = document.getElementById('bib-qty-summary-mount');
|
||
if (!mount || !moduleBib) {
|
||
return;
|
||
}
|
||
|
||
let panel = document.getElementById('bib-qty-summary-panel');
|
||
let blnDeferred = panel && panel.getAttribute('data-bib-qty-summary-deferred') === '1';
|
||
let blnLoaded = panel && panel.getAttribute('data-bib-qty-summary-loaded') === '1';
|
||
if (!blnDeferred && !blnLoaded) {
|
||
return;
|
||
}
|
||
|
||
let eveId = moduleBib.dataset.eveId || '';
|
||
if (!eveId) {
|
||
return;
|
||
}
|
||
|
||
let blnWasExpanded = panel && !panel.classList.contains('is-collapsed');
|
||
|
||
bibFetch('/ajax_bib_range.php', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/x-www-form-urlencoded'
|
||
},
|
||
body: 'action=qty_summary&eve_id=' + encodeURIComponent(eveId) + bibAjaxLangSuffix()
|
||
}, { loader: false })
|
||
.then(function (res) { return res.json(); })
|
||
.then(function (data) {
|
||
if (!data.success || !data.html) {
|
||
return;
|
||
}
|
||
mount.innerHTML = data.html;
|
||
initModuleBibTippy(mount);
|
||
if (blnWasExpanded) {
|
||
let newPanel = document.getElementById('bib-qty-summary-panel');
|
||
if (newPanel) {
|
||
newPanel.classList.remove('is-collapsed');
|
||
let btn = newPanel.querySelector('.epr-block-toggle');
|
||
if (btn) {
|
||
btn.setAttribute('aria-expanded', 'true');
|
||
let icon = btn.querySelector('.fa');
|
||
if (icon) {
|
||
icon.classList.remove('fa-chevron-down');
|
||
icon.classList.add('fa-chevron-up');
|
||
}
|
||
}
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
function bibQtySummaryShouldRefresh() {
|
||
let panel = document.getElementById('bib-qty-summary-panel');
|
||
return panel && panel.getAttribute('data-bib-qty-summary-loaded') === '1';
|
||
}
|
||
|
||
function setBibContainerHtml(row, html, opts) {
|
||
opts = opts || {};
|
||
let container = getBibContainer(row);
|
||
if (!container) return null;
|
||
// renderBibRanges renvoie un bloc .epr-table.bib-container complet.
|
||
if (html.indexOf('bib-container') !== -1) {
|
||
container.outerHTML = html;
|
||
container = getBibContainer(row);
|
||
} else {
|
||
container.innerHTML = html;
|
||
}
|
||
if (container) {
|
||
initModuleBibTippy(row);
|
||
initBibRangeRows(container);
|
||
}
|
||
syncBibUiState(row);
|
||
if (!opts.skipAnomalies) {
|
||
refreshBibAnomaliesPanel();
|
||
}
|
||
if (!opts.skipQtySummary && bibQtySummaryShouldRefresh()) {
|
||
refreshBibQtySummaryPanel();
|
||
}
|
||
return container;
|
||
}
|
||
|
||
// MSIN-4429 — Séquence : Début puis Qté ou Fin (pilote / calculé).
|
||
function bibRangeParseInt(val) {
|
||
var n = parseInt(String(val || '').trim(), 10);
|
||
return isNaN(n) ? 0 : n;
|
||
}
|
||
|
||
function bibRangeGetFields(row) {
|
||
if (!row) return null;
|
||
return {
|
||
start: row.querySelector('.bib-start'),
|
||
qty: row.querySelector('.bib-qty'),
|
||
end: row.querySelector('.bib-end')
|
||
};
|
||
}
|
||
|
||
function bibRangeGetErrorEl(row) {
|
||
var el = row && row.nextElementSibling;
|
||
if (el && el.classList.contains('bib-error')) {
|
||
return el;
|
||
}
|
||
return null;
|
||
}
|
||
|
||
function bibRangeClearRangeError(row) {
|
||
var errEl = bibRangeGetErrorEl(row);
|
||
if (!errEl) return;
|
||
|
||
var msg = errEl.querySelector('.bib-range-validate-msg');
|
||
if (msg) {
|
||
msg.remove();
|
||
}
|
||
|
||
if (!errEl.querySelector('div:not(.bib-range-validate-msg)') && !errEl.textContent.trim()) {
|
||
errEl.style.display = 'none';
|
||
}
|
||
}
|
||
|
||
function bibRangeClearFieldClasses(row) {
|
||
var fields = bibRangeGetFields(row);
|
||
if (!fields) return;
|
||
[fields.start, fields.qty, fields.end].forEach(function (el) {
|
||
if (!el) return;
|
||
el.classList.remove('bib-field--idle', 'bib-field--pick', 'bib-field--calc', 'bib-field--active');
|
||
});
|
||
}
|
||
|
||
function bibRangeClearValidationUi(row) {
|
||
var fields = bibRangeGetFields(row);
|
||
if (!fields) return;
|
||
|
||
[fields.start, fields.qty, fields.end].forEach(function (el) {
|
||
if (el) {
|
||
el.classList.remove('bib-field--invalid');
|
||
}
|
||
});
|
||
|
||
bibRangeClearRangeError(row);
|
||
}
|
||
|
||
/** MSIN-4429 — Validation différée (blur / OK), pas pendant la frappe. */
|
||
function bibRangeValidate(row) {
|
||
var fields = bibRangeGetFields(row);
|
||
if (!fields) return null;
|
||
|
||
var start = bibRangeParseInt(fields.start && fields.start.value);
|
||
if (start <= 0) {
|
||
return null;
|
||
}
|
||
|
||
var pilot = row.dataset.rangePilot || '';
|
||
if (!pilot) {
|
||
return null;
|
||
}
|
||
|
||
if (pilot === 'end') {
|
||
var strEnd = String(fields.end && fields.end.value || '').trim();
|
||
if (strEnd === '') {
|
||
return null;
|
||
}
|
||
var end = bibRangeParseInt(strEnd);
|
||
if (end <= 0) {
|
||
return { key: 'incomplete', field: 'end' };
|
||
}
|
||
if (end < start) {
|
||
return { key: 'invalidEnd', field: 'end', start: start };
|
||
}
|
||
}
|
||
|
||
if (pilot === 'qty') {
|
||
var strQty = String(fields.qty && fields.qty.value || '').trim();
|
||
if (strQty === '') {
|
||
return null;
|
||
}
|
||
var qty = bibRangeParseInt(strQty);
|
||
if (qty <= 0) {
|
||
return { key: 'invalidQty', field: 'qty' };
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
function bibRangeValidationMessage(validation) {
|
||
if (!validation) {
|
||
return '';
|
||
}
|
||
if (validation.key === 'invalidEnd') {
|
||
return bibJsFmt('jsRangeInvalidEnd', validation.start);
|
||
}
|
||
if (validation.key === 'invalidQty') {
|
||
return bibJs('jsRangeInvalidQty');
|
||
}
|
||
if (validation.key === 'incomplete') {
|
||
return bibJs('jsRangeIncomplete') || bibJs('jsFieldsRequired');
|
||
}
|
||
return bibJs('jsRangeInvalid') || bibJs('jsFieldsRequired');
|
||
}
|
||
|
||
function bibRangeShowValidation(row, validation) {
|
||
var fields = bibRangeGetFields(row);
|
||
if (!fields) {
|
||
return;
|
||
}
|
||
|
||
bibRangeClearValidationUi(row);
|
||
|
||
if (!validation) {
|
||
return;
|
||
}
|
||
|
||
var target = validation.field === 'qty' ? fields.qty : fields.end;
|
||
if (target) {
|
||
target.classList.add('bib-field--invalid');
|
||
}
|
||
|
||
var errEl = bibRangeGetErrorEl(row);
|
||
if (!errEl) {
|
||
return;
|
||
}
|
||
|
||
var msgEl = errEl.querySelector('.bib-range-validate-msg');
|
||
if (!msgEl) {
|
||
msgEl = document.createElement('div');
|
||
msgEl.className = 'bib-range-validate-msg';
|
||
errEl.insertBefore(msgEl, errEl.firstChild);
|
||
}
|
||
msgEl.textContent = bibRangeValidationMessage(validation);
|
||
errEl.style.display = 'block';
|
||
}
|
||
|
||
function bibRangeValidateOnBlur(row) {
|
||
applyBibRangeFieldState(row);
|
||
bibRangeShowValidation(row, bibRangeValidate(row));
|
||
}
|
||
|
||
function applyBibRangeFieldState(row) {
|
||
var fields = bibRangeGetFields(row);
|
||
if (!fields || !fields.start || !fields.qty || !fields.end) return;
|
||
|
||
if (row.dataset.locked === '1') {
|
||
bibRangeClearFieldClasses(row);
|
||
return;
|
||
}
|
||
|
||
var start = bibRangeParseInt(fields.start.value);
|
||
var pilot = row.dataset.rangePilot || '';
|
||
|
||
bibRangeClearFieldClasses(row);
|
||
|
||
if (start <= 0) {
|
||
fields.qty.classList.add('bib-field--idle');
|
||
fields.end.classList.add('bib-field--idle');
|
||
fields.qty.readOnly = true;
|
||
fields.end.readOnly = true;
|
||
fields.qty.value = '';
|
||
fields.end.value = '';
|
||
row.dataset.rangePilot = '';
|
||
return;
|
||
}
|
||
|
||
if (!pilot) {
|
||
fields.qty.classList.add('bib-field--pick');
|
||
fields.end.classList.add('bib-field--pick');
|
||
fields.qty.readOnly = true;
|
||
fields.end.readOnly = true;
|
||
return;
|
||
}
|
||
|
||
if (pilot === 'qty') {
|
||
var qty = bibRangeParseInt(fields.qty.value);
|
||
fields.qty.classList.add('bib-field--active');
|
||
fields.end.classList.add('bib-field--calc');
|
||
fields.qty.readOnly = false;
|
||
fields.end.readOnly = true;
|
||
if (qty > 0) {
|
||
fields.end.value = String(start + qty - 1);
|
||
} else {
|
||
fields.end.value = '';
|
||
}
|
||
} else if (pilot === 'end') {
|
||
var end = bibRangeParseInt(fields.end.value);
|
||
fields.end.classList.add('bib-field--active');
|
||
fields.qty.classList.add('bib-field--calc');
|
||
fields.end.readOnly = false;
|
||
fields.qty.readOnly = true;
|
||
if (end >= start) {
|
||
fields.qty.value = String(end - start + 1);
|
||
} else {
|
||
fields.qty.value = '';
|
||
}
|
||
}
|
||
}
|
||
|
||
function onBibRangeFieldPick(row, pilot) {
|
||
if (!row || row.dataset.locked === '1') return;
|
||
|
||
var fields = bibRangeGetFields(row);
|
||
if (!fields || !fields.start) return;
|
||
|
||
if (bibRangeParseInt(fields.start.value) <= 0) {
|
||
fields.start.focus();
|
||
return;
|
||
}
|
||
|
||
row.dataset.rangePilot = pilot;
|
||
applyBibRangeFieldState(row);
|
||
|
||
var target = pilot === 'qty' ? fields.qty : fields.end;
|
||
if (target) {
|
||
target.focus();
|
||
target.select();
|
||
}
|
||
}
|
||
|
||
function onBibRangeStartChange(row) {
|
||
var fields = bibRangeGetFields(row);
|
||
if (!fields || !fields.start) return;
|
||
|
||
var start = bibRangeParseInt(fields.start.value);
|
||
var lastStart = bibRangeParseInt(row.dataset.rangeLastStart || '0');
|
||
|
||
if (start !== lastStart && !row.dataset.rangePilot) {
|
||
fields.qty.value = '';
|
||
fields.end.value = '';
|
||
row.dataset.hasValues = '0';
|
||
}
|
||
|
||
row.dataset.rangeLastStart = String(start);
|
||
|
||
if (start <= 0) {
|
||
row.dataset.rangePilot = '';
|
||
}
|
||
|
||
applyBibRangeFieldState(row);
|
||
}
|
||
|
||
function bindBibRangeRow(row) {
|
||
if (!row || row.dataset.bibRangeBound === '1') return;
|
||
row.dataset.bibRangeBound = '1';
|
||
|
||
var fields = bibRangeGetFields(row);
|
||
if (!fields || !fields.start || !fields.qty || !fields.end) return;
|
||
|
||
row.dataset.rangeLastStart = String(bibRangeParseInt(fields.start.value));
|
||
|
||
fields.start.addEventListener('input', function () {
|
||
bibRangeClearValidationUi(row);
|
||
onBibRangeStartChange(row);
|
||
});
|
||
|
||
fields.qty.addEventListener('input', function () {
|
||
bibRangeClearValidationUi(row);
|
||
row.dataset.rangePilot = 'qty';
|
||
applyBibRangeFieldState(row);
|
||
});
|
||
|
||
fields.end.addEventListener('input', function () {
|
||
bibRangeClearValidationUi(row);
|
||
row.dataset.rangePilot = 'end';
|
||
applyBibRangeFieldState(row);
|
||
});
|
||
|
||
fields.start.addEventListener('blur', function () {
|
||
bibRangeValidateOnBlur(row);
|
||
});
|
||
|
||
fields.qty.addEventListener('blur', function () {
|
||
bibRangeValidateOnBlur(row);
|
||
});
|
||
|
||
fields.end.addEventListener('blur', function () {
|
||
bibRangeValidateOnBlur(row);
|
||
});
|
||
|
||
fields.qty.addEventListener('click', function () {
|
||
onBibRangeFieldPick(row, 'qty');
|
||
});
|
||
|
||
fields.end.addEventListener('click', function () {
|
||
onBibRangeFieldPick(row, 'end');
|
||
});
|
||
|
||
fields.qty.addEventListener('focus', function () {
|
||
onBibRangeFieldPick(row, 'qty');
|
||
});
|
||
|
||
fields.end.addEventListener('focus', function () {
|
||
onBibRangeFieldPick(row, 'end');
|
||
});
|
||
|
||
applyBibRangeFieldState(row);
|
||
|
||
if (row.dataset.id === '0' && !fields.start.value) {
|
||
fields.start.focus();
|
||
}
|
||
}
|
||
|
||
function initBibRangeRows(root) {
|
||
if (!root) return;
|
||
root.querySelectorAll('.bib-range').forEach(bindBibRangeRow);
|
||
}
|
||
|
||
function bibCsrfToken() {
|
||
return moduleBib ? (moduleBib.dataset.csrfToken || '') : '';
|
||
}
|
||
|
||
initModuleBibTippy(moduleBib);
|
||
initBibRangeRows(moduleBib);
|
||
|
||
// ============================================================
|
||
// MSIN-4379 — Étape 2 : assignation automatique (interface JS)
|
||
// Prochain tour : étape 6 (fxAssignAutoBibForParticipant), étape 7 (fxMajCommande).
|
||
// ============================================================
|
||
|
||
/** MSIN-4379 — Compte les séquences cochées et met à jour le texte d'aide. */
|
||
function updateAutoSelectionInfo(row) {
|
||
|
||
if (!row) return;
|
||
|
||
let count = row.querySelectorAll('.batch-select-range:checked').length;
|
||
let info = row.querySelector('.auto-info-text');
|
||
if (!info) return;
|
||
|
||
if (count === 0) {
|
||
info.textContent = bibJs('jsAutoSelectHint');
|
||
} else {
|
||
info.textContent = bibJsFmt('jsAutoSelectCount', count);
|
||
}
|
||
}
|
||
|
||
function syncAutoUiState(row, isActive) {
|
||
if (!row) return;
|
||
|
||
let btnAuto = row.querySelector('.btn-auto');
|
||
row.dataset.autoActive = isActive ? '1' : '0';
|
||
row.classList.toggle('auto-enabled', isActive);
|
||
|
||
if (btnAuto) {
|
||
btnAuto.textContent = isActive ? row.dataset.autoLabelConfig : row.dataset.autoLabel;
|
||
btnAuto.classList.toggle('btn-bib-auto--active', isActive);
|
||
let autoAide = bibQuery(row, '.epr-action-auto-group .epr-btn-aide-segment .bib-aide-trigger');
|
||
if (autoAide) {
|
||
autoAide.classList.add('btn-aide-tone-auto');
|
||
autoAide.classList.remove('btn-aide-tone-success', 'btn-aide-tone-secondary');
|
||
}
|
||
}
|
||
}
|
||
|
||
/** MSIN-4379 — Quitte le mode édition auto sans sauver ; recharge les plages (mode assign). */
|
||
function exitAutoMode(row) {
|
||
|
||
if (!row) return;
|
||
|
||
row.classList.remove('auto-mode');
|
||
|
||
let container = row.querySelector('.bib-container');
|
||
if (container) {
|
||
container.classList.remove('batch-mode');
|
||
}
|
||
|
||
row.querySelectorAll('.bib-start, .bib-qty, .bib-end').forEach(input => {
|
||
input.removeAttribute('readonly');
|
||
});
|
||
|
||
bibFetch('/ajax_bib_range.php', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/x-www-form-urlencoded'
|
||
},
|
||
body:
|
||
'action=refresh_ranges'
|
||
+ '&epr_id=' + encodeURIComponent(row.dataset.eprId)
|
||
+ '&mode=assign'
|
||
+ bibAjaxLangSuffix()
|
||
})
|
||
.then(res => res.json())
|
||
.then(data => {
|
||
|
||
if (!data.success) return;
|
||
|
||
let bibContainer = setBibContainerHtml(row, data.html);
|
||
});
|
||
}
|
||
|
||
/** MSIN-4379 — Ouvre le mode édition : checkboxes, bloc Accepter/Annuler, refresh mode=auto. */
|
||
function enterAutoMode(row) {
|
||
|
||
if (!row) return;
|
||
|
||
if (row.classList.contains('batch-mode') || row.classList.contains('reset-mode')) {
|
||
return;
|
||
}
|
||
|
||
if (bibBlockAutoActivation(row)) {
|
||
return;
|
||
}
|
||
|
||
row.classList.add('auto-mode');
|
||
|
||
let container = row.querySelector('.bib-container');
|
||
if (container) {
|
||
container.classList.add('batch-mode');
|
||
}
|
||
|
||
row.querySelectorAll('.bib-start, .bib-qty, .bib-end').forEach(input => {
|
||
input.setAttribute('readonly', true);
|
||
});
|
||
|
||
syncBibUiState(row);
|
||
|
||
bibFetch('/ajax_bib_range.php', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/x-www-form-urlencoded'
|
||
},
|
||
body:
|
||
'action=refresh_ranges'
|
||
+ '&epr_id=' + encodeURIComponent(row.dataset.eprId)
|
||
+ '&mode=auto'
|
||
+ bibAjaxLangSuffix()
|
||
})
|
||
.then(res => res.json())
|
||
.then(data => {
|
||
|
||
if (!data.success) return;
|
||
|
||
let bibContainer = setBibContainerHtml(row, data.html);
|
||
if (!bibContainer) return;
|
||
|
||
bibContainer.classList.add('batch-mode');
|
||
|
||
row.querySelectorAll('.bib-start, .bib-qty, .bib-end').forEach(input => {
|
||
input.setAttribute('readonly', true);
|
||
});
|
||
|
||
updateAutoSelectionInfo(row);
|
||
syncBibUiState(row);
|
||
});
|
||
}
|
||
|
||
function bibSyncResetAllEprButton(row) {
|
||
if (!row) {
|
||
return;
|
||
}
|
||
|
||
let wrap = row.querySelector('.epr-identity-reset-all');
|
||
if (!wrap) {
|
||
return;
|
||
}
|
||
|
||
let avecBib = parseInt(bibQuery(row, '.bib-avec')?.textContent || '0', 10) || 0;
|
||
if (avecBib <= 0) {
|
||
wrap.classList.add('bib-ui-hidden');
|
||
return;
|
||
}
|
||
|
||
wrap.classList.remove('bib-ui-hidden');
|
||
|
||
let btn = wrap.querySelector('.btn-reset-all-epr');
|
||
if (!btn) {
|
||
return;
|
||
}
|
||
|
||
let hasLock = row.querySelector('.btn-bib-lock--closed') !== null;
|
||
btn.disabled = hasLock;
|
||
}
|
||
|
||
function syncBibUiState(row) {
|
||
if (!row) return;
|
||
|
||
let modes = bibRowModes(row);
|
||
let avecBib = parseInt(bibQuery(row, '.bib-avec')?.textContent || '0', 10) || 0;
|
||
let hasSequences = bibHasSavedSequences(row);
|
||
let hasSelection = bibCountSelectedRanges(row) > 0;
|
||
let inBatchFlow = modes.batch || modes.reset;
|
||
let inAutoFlow = modes.auto;
|
||
let inPickFlow = inBatchFlow || inAutoFlow;
|
||
|
||
row.querySelectorAll('.team-mode-box input[type="radio"]').forEach(function (radio) {
|
||
if (!radio.closest('.team-mode-option.disabled')) {
|
||
radio.disabled = avecBib > 0;
|
||
}
|
||
});
|
||
|
||
let showReset = hasSequences && (avecBib > 0 || modes.reset)
|
||
&& !modes.auto
|
||
&& (!modes.batch || modes.reset);
|
||
bibSetVisible('.epr-action-batch-group',
|
||
hasSequences && ((!modes.reset && !modes.auto) || modes.batch), row);
|
||
bibSetVisible('.epr-action-reset-group', showReset, row);
|
||
bibSetVisible('.epr-action-auto-group',
|
||
hasSequences && !modes.reset && !modes.auto && !modes.batch, row);
|
||
|
||
if (hasSequences) {
|
||
syncAutoUiState(row, row.dataset.autoActive === '1');
|
||
}
|
||
|
||
bibSetVisible('.epr-add-range-row', !inPickFlow, row);
|
||
bibSetVisible('.batch-config-container', inBatchFlow, row);
|
||
bibSetVisible('.auto-config-container', inAutoFlow, row);
|
||
|
||
let showPick = inPickFlow && !hasSelection;
|
||
let showBatchReady = inBatchFlow && hasSelection;
|
||
let showAutoReady = inAutoFlow && hasSelection;
|
||
bibSetVisible('.bib-seq-pick-prompt', showPick, row);
|
||
bibSetVisible('.batch-config-ready', showBatchReady, row);
|
||
bibSetVisible('.auto-config-ready', showAutoReady, row);
|
||
|
||
let bibContainer = getBibContainer(row);
|
||
if (bibContainer) {
|
||
bibContainer.classList.toggle('batch-awaiting-selection', showPick);
|
||
}
|
||
|
||
bibSetVisible('.epr-action-desactiver-group',
|
||
hasSequences && row.dataset.autoActive === '1' && inAutoFlow, row);
|
||
bibSetVisible('.epr-action-cancel-auto-group', inAutoFlow, row);
|
||
bibSetVisible('.epr-action-accept-auto-group', showAutoReady, row);
|
||
bibSetVisible('.epr-auto-info-group', showAutoReady, row);
|
||
bibSetVisible('.batch-reset-warning', showBatchReady && modes.reset, row);
|
||
bibSetVisible('.epr-batch-order-wrap', showBatchReady && !modes.reset, row);
|
||
bibSetVisible('.epr-batch-order-wrap--secondary', showBatchReady && !modes.reset, row);
|
||
bibSetVisible('.epr-action-sim-group', showBatchReady && !modes.reset, row);
|
||
bibSetVisible('.epr-action-go-group', showBatchReady, row);
|
||
bibSyncResetAllEprButton(row);
|
||
}
|
||
|
||
function updateBatchAnalysis(row) {
|
||
|
||
if (!row) return;
|
||
|
||
let totalDispo = 0;
|
||
let totalReset = 0;
|
||
|
||
// =====================
|
||
// TOTAL DISPO
|
||
// Source officielle = PHP
|
||
// JS ne recalcule PAS les disponibilités.
|
||
// Il additionne seulement les valeurs affichées dans .bib-dispo.
|
||
// =====================
|
||
row.querySelectorAll('.batch-select-range:checked').forEach(cb => {
|
||
|
||
let line = cb.closest('.epr-line');
|
||
if (!line) return;
|
||
|
||
let usedDiv = line.querySelector('.bib-used');
|
||
let dispoDiv = line.querySelector('.bib-dispo');
|
||
|
||
let used = parseInt((usedDiv?.textContent || '0'), 10);
|
||
let dispo = parseInt((dispoDiv?.textContent || '0'), 10);
|
||
|
||
if (isNaN(used)) {
|
||
used = 0;
|
||
}
|
||
|
||
if (isNaN(dispo)) {
|
||
dispo = 0;
|
||
}
|
||
|
||
totalReset += used;
|
||
totalDispo += dispo;
|
||
});
|
||
|
||
bibFetch('/ajax_bib_range.php', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/x-www-form-urlencoded'
|
||
},
|
||
body: 'action=batch_analysis&epr_id=' + encodeURIComponent(row.dataset.eprId) + bibAjaxLangSuffix()
|
||
}, { loader: false })
|
||
.then(res => res.json())
|
||
.then(data => {
|
||
|
||
if (!data.success) return;
|
||
|
||
bibSyncEprBibStats(row, data.info);
|
||
syncBibUiState(row);
|
||
let sansBib = bibRowPendingBibs(row);
|
||
let isResetMode = row.dataset.mode === 'reset';
|
||
let message = '';
|
||
|
||
if (isResetMode) {
|
||
|
||
if (totalReset === 0) {
|
||
message = bibJs('jsBatchNone');
|
||
} else {
|
||
message = bibJsFmt('jsBatchResetCount', totalReset);
|
||
}
|
||
|
||
} else {
|
||
|
||
if (totalDispo === 0) {
|
||
message = bibJs('jsBatchNone');
|
||
} else if (totalDispo < sansBib) {
|
||
message = bibJsFmt('jsBatchSummaryShort', totalDispo, sansBib, sansBib - totalDispo);
|
||
} else {
|
||
message = bibJsFmt('jsBatchSummaryOk', totalDispo, sansBib);
|
||
}
|
||
|
||
}
|
||
|
||
let info = row.querySelector('.epr-actions .batch-info-text');
|
||
if (info && bibCountSelectedRanges(row) > 0) {
|
||
info.textContent = message;
|
||
}
|
||
|
||
syncBibUiState(row);
|
||
});
|
||
}
|
||
|
||
// =====================
|
||
// BATCH CHECKBOX CHANGE (PROPRE)
|
||
// =====================
|
||
moduleBib.addEventListener('change', function (e) {
|
||
|
||
// =====================
|
||
// TEAM MODE
|
||
// =====================
|
||
let teamRadio = e.target.closest('.team-mode-box input[type="radio"]');
|
||
|
||
if (teamRadio) {
|
||
|
||
if (teamRadio.disabled) return;
|
||
|
||
let box = teamRadio.closest('.team-mode-box');
|
||
if (!box) return;
|
||
|
||
bibFetch('/ajax_bib_range.php', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/x-www-form-urlencoded'
|
||
},
|
||
body:
|
||
'action=save_team_mode'
|
||
+ '&epr_id=' + encodeURIComponent(box.dataset.eprId)
|
||
+ '&team_mode=' + encodeURIComponent(teamRadio.value)
|
||
+ bibAjaxLangSuffix()
|
||
}, { loader: false });
|
||
|
||
return;
|
||
}
|
||
|
||
let cb = e.target.closest('.batch-select-range');
|
||
if (!cb) return;
|
||
|
||
let row = cb.closest('.epr-row');
|
||
if (!row) return;
|
||
|
||
// MSIN-4379 — Mode auto : même sélection de séquences que le batch, sans GO/simulation.
|
||
if (row.classList.contains('auto-mode')) {
|
||
updateAutoSelectionInfo(row);
|
||
syncBibUiState(row);
|
||
return;
|
||
}
|
||
|
||
if (row.dataset.loading === '1') return;
|
||
let existing = document.querySelector('.epr-row-view');
|
||
if (existing) existing.remove();
|
||
row.dataset.loading = '1';
|
||
|
||
// 1. garder sélection
|
||
let selected = [];
|
||
row.querySelectorAll('.batch-select-range:checked').forEach(el => {
|
||
selected.push(el.dataset.rangeId);
|
||
});
|
||
|
||
// 2. analyse gauche/droite
|
||
updateBatchAnalysis(row);
|
||
|
||
// 3. sortir du cycle du change
|
||
setTimeout(() => {
|
||
|
||
bibFetch('/ajax_bib_range.php', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/x-www-form-urlencoded'
|
||
},
|
||
body:
|
||
'action=refresh_ranges'
|
||
+ '&epr_id=' + encodeURIComponent(row.dataset.eprId)
|
||
+ '&mode=' + encodeURIComponent(row.dataset.mode || 'assign')
|
||
+ bibAjaxLangSuffix()
|
||
}, { loader: false })
|
||
.then(res => res.json())
|
||
.then(data => {
|
||
|
||
if (!data.success) {
|
||
row.dataset.loading = '0';
|
||
return;
|
||
}
|
||
|
||
setBibContainerHtml(row, data.html);
|
||
let container = getBibContainer(row);
|
||
if (!container) {
|
||
row.dataset.loading = '0';
|
||
return;
|
||
}
|
||
|
||
// 4. refresh complet serveur
|
||
// Re-sync après refresh serveur
|
||
|
||
container.classList.add('batch-mode');
|
||
|
||
// 5. remettre readonly
|
||
container.querySelectorAll('.bib-start, .bib-qty, .bib-end').forEach(input => {
|
||
input.setAttribute('readonly', true);
|
||
});
|
||
|
||
// 6. restaurer checkbox
|
||
container.querySelectorAll('.batch-select-range').forEach(el => {
|
||
if (selected.includes(el.dataset.rangeId)) {
|
||
el.checked = true;
|
||
}
|
||
});
|
||
updateBatchAnalysis(row);
|
||
|
||
row.dataset.loading = '0';
|
||
|
||
})
|
||
.catch(() => {
|
||
row.dataset.loading = '0';
|
||
});
|
||
|
||
}, 0);
|
||
});
|
||
|
||
moduleBib.querySelectorAll('.epr-row').forEach(syncBibUiState);
|
||
|
||
moduleBib.addEventListener('click', function (e) {
|
||
|
||
let btnQte = e.target.closest('.btn_qte');
|
||
if (btnQte && moduleBib.contains(btnQte)) {
|
||
e.preventDefault();
|
||
bibSaveQte(btnQte);
|
||
return;
|
||
}
|
||
|
||
let btnGotoAssign = e.target.closest('.bib-anomaly-goto-assign');
|
||
if (btnGotoAssign) {
|
||
e.preventDefault();
|
||
|
||
let eprId = btnGotoAssign.dataset.eprId;
|
||
if (!eprId) {
|
||
return;
|
||
}
|
||
|
||
let row = moduleBib.querySelector('.epr-row[data-epr-id="' + eprId + '"]');
|
||
if (row) {
|
||
row.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||
let btnView = row.querySelector('.btn-view-range[data-range-id="0"]');
|
||
if (btnView) {
|
||
btnView.click();
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
let btnTrad = e.target.closest('.btn-admin-trad, .btn-bib-trad');
|
||
if (btnTrad) {
|
||
e.preventDefault();
|
||
e.stopPropagation();
|
||
let url = btnTrad.getAttribute('data-trad-url');
|
||
if (!url) {
|
||
return;
|
||
}
|
||
let clef = btnTrad.getAttribute('data-info-clef') || 'bib_trad';
|
||
let popup = window.open(
|
||
url,
|
||
'bib_trad_' + clef,
|
||
'width=960,height=640,scrollbars=yes,resizable=yes'
|
||
);
|
||
if (popup) {
|
||
let timer = setInterval(function () {
|
||
if (popup.closed) {
|
||
clearInterval(timer);
|
||
window.location.reload();
|
||
}
|
||
}, 400);
|
||
}
|
||
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;
|
||
}
|
||
|
||
bibFetch('/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')
|
||
+ 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);
|
||
syncBibUiState(row);
|
||
}
|
||
|
||
if (data.html) {
|
||
setBibContainerHtml(row, data.html);
|
||
bibSyncResetAllEprButton(row);
|
||
}
|
||
});
|
||
|
||
return;
|
||
}
|
||
|
||
// =====================
|
||
// MSIN-4436 — Réinitialiser tous les dossards (épreuve entière)
|
||
// =====================
|
||
let btnResetAllEpr = e.target.closest('.btn-reset-all-epr');
|
||
if (btnResetAllEpr) {
|
||
|
||
e.preventDefault();
|
||
|
||
let row = btnResetAllEpr.closest('.epr-row');
|
||
if (!row) {
|
||
return;
|
||
}
|
||
|
||
if (btnResetAllEpr.disabled) {
|
||
alert(bibJsConfirm('jsResetAllLocked'));
|
||
return;
|
||
}
|
||
|
||
if (row.querySelector('.btn-bib-lock--closed')) {
|
||
alert(bibJsConfirm('jsResetAllLocked'));
|
||
bibSyncResetAllEprButton(row);
|
||
return;
|
||
}
|
||
|
||
if (!confirm(bibJsConfirm('jsResetAllConfirm'))) {
|
||
return;
|
||
}
|
||
|
||
bibFetch('/ajax_bib_range.php', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/x-www-form-urlencoded'
|
||
},
|
||
body:
|
||
'action=reset_all_apply'
|
||
+ '&epr_id=' + encodeURIComponent(row.dataset.eprId)
|
||
+ bibAjaxLangSuffix()
|
||
})
|
||
.then(res => res.json())
|
||
.then(data => {
|
||
|
||
if (!data.success) {
|
||
alert(data.message || bibJs('jsErrGeneric'));
|
||
return;
|
||
}
|
||
|
||
bibAfterBatchGoSuccess(row, data, false);
|
||
});
|
||
|
||
return;
|
||
}
|
||
|
||
// =====================
|
||
// DELETE
|
||
// =====================
|
||
let btnDelete = e.target.closest('.btn-delete-range');
|
||
if (btnDelete) {
|
||
|
||
|
||
e.preventDefault();
|
||
|
||
let container = btnDelete.closest('.bib-container');
|
||
let errorDiv = container.querySelector('.bib-error-global');
|
||
|
||
// reset erreur
|
||
if (errorDiv) {
|
||
errorDiv.style.display = 'none';
|
||
errorDiv.innerText = '';
|
||
}
|
||
|
||
let id = btnDelete.dataset.id;
|
||
if (!id) return;
|
||
|
||
bibFetch('/ajax_bib_range.php', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/x-www-form-urlencoded'
|
||
},
|
||
body: 'action=delete&id=' + encodeURIComponent(id) + bibAjaxLangSuffix()
|
||
})
|
||
.then(res => res.text())
|
||
.then(raw => {
|
||
|
||
let data;
|
||
try {
|
||
data = JSON.parse(raw);
|
||
} catch (err) {
|
||
if (errorDiv) {
|
||
errorDiv.innerText = bibJs('jsServerError');
|
||
errorDiv.style.display = 'block';
|
||
}
|
||
return;
|
||
}
|
||
|
||
if (!data.success) {
|
||
if (errorDiv) {
|
||
errorDiv.innerText = data.message || bibJs('jsErrGeneric');
|
||
errorDiv.style.display = 'block';
|
||
}
|
||
return;
|
||
}
|
||
|
||
setBibContainerHtml(btnDelete.closest('.epr-row'), data.html);
|
||
});
|
||
|
||
return;
|
||
}
|
||
|
||
// =====================
|
||
// SAVE
|
||
// =====================
|
||
let btnSave = e.target.closest('.btn-save-range');
|
||
if (btnSave) {
|
||
e.preventDefault();
|
||
|
||
let row = btnSave.closest('.bib-range');
|
||
let errorDiv = row.nextElementSibling;
|
||
let epr_id = btnSave.dataset.eprId;
|
||
|
||
// reset
|
||
if (errorDiv) {
|
||
errorDiv.style.display = 'none';
|
||
errorDiv.innerText = '';
|
||
}
|
||
|
||
applyBibRangeFieldState(row);
|
||
|
||
let start = bibRangeParseInt(row.querySelector('.bib-start').value);
|
||
let end = bibRangeParseInt(row.querySelector('.bib-end').value);
|
||
let id = btnSave.dataset.id;
|
||
let validation = bibRangeValidate(row);
|
||
|
||
// ligne temporaire vide = on la retire
|
||
if (id == 0 && start <= 0) {
|
||
row.remove();
|
||
if (errorDiv && errorDiv.classList.contains('bib-error')) {
|
||
errorDiv.remove();
|
||
}
|
||
return;
|
||
}
|
||
|
||
if (start <= 0 || end <= 0) {
|
||
validation = validation || { key: 'incomplete' };
|
||
}
|
||
|
||
if (!validation && end < start) {
|
||
validation = { key: 'invalidEnd', field: 'end', start: start };
|
||
}
|
||
|
||
if (validation) {
|
||
bibRangeShowValidation(row, validation);
|
||
if (errorDiv) {
|
||
var msgEl = errorDiv.querySelector('.bib-range-validate-msg');
|
||
if (!msgEl) {
|
||
errorDiv.innerText = bibRangeValidationMessage(validation);
|
||
}
|
||
errorDiv.style.display = 'block';
|
||
}
|
||
var invalidField = validation.field === 'qty'
|
||
? row.querySelector('.bib-qty')
|
||
: row.querySelector('.bib-end');
|
||
if (invalidField) {
|
||
invalidField.focus();
|
||
}
|
||
return;
|
||
}
|
||
|
||
bibFetch('/ajax_bib_range.php', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/x-www-form-urlencoded'
|
||
},
|
||
body:
|
||
'action=save'
|
||
+ '&id=' + encodeURIComponent(id)
|
||
+ '&epr_id=' + encodeURIComponent(epr_id)
|
||
+ '&start=' + encodeURIComponent(start)
|
||
+ '&end=' + encodeURIComponent(end)
|
||
+ bibAjaxLangSuffix()
|
||
})
|
||
.then(res => res.text())
|
||
.then(raw => {
|
||
|
||
let data;
|
||
try {
|
||
data = JSON.parse(raw);
|
||
} catch (err) {
|
||
errorDiv.innerText = bibJs('jsServerError');
|
||
errorDiv.style.display = 'block';
|
||
return;
|
||
}
|
||
|
||
if (!data.success) {
|
||
errorDiv.innerText = data.message || bibJs('jsErrGeneric');
|
||
errorDiv.style.display = 'block';
|
||
return;
|
||
}
|
||
|
||
setBibContainerHtml(btnSave.closest('.epr-row'), data.html);
|
||
});
|
||
|
||
return;
|
||
}
|
||
// =====================
|
||
// VIEW
|
||
// =====================
|
||
let btnView = e.target.closest('.btn-view-range');
|
||
if (btnView) {
|
||
e.preventDefault();
|
||
|
||
let epr_id = btnView.dataset.eprId;
|
||
let range_id = btnView.dataset.rangeId;
|
||
|
||
console.log('epr_id:', epr_id);
|
||
console.log('range_id:', range_id);
|
||
if (!epr_id || typeof range_id === 'undefined') return;
|
||
|
||
let container = btnView.closest('.epr-block');
|
||
|
||
// Vérifier si une vue est déjà ouverte
|
||
let existing = document.querySelector('.epr-row-view');
|
||
|
||
// Toggle : si c'est le même œil qui a ouvert la vue, on la ferme et on s'arrête
|
||
if (existing
|
||
&& existing.dataset.eprId === epr_id
|
||
&& existing.dataset.rangeId === range_id
|
||
) {
|
||
existing.remove();
|
||
return;
|
||
}
|
||
|
||
// Un autre œil a été cliqué : fermer la vue précédente avant d'ouvrir la nouvelle
|
||
if (existing) {
|
||
existing.remove();
|
||
}
|
||
|
||
bibFetch('/ajax_bib_range.php', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/x-www-form-urlencoded'
|
||
},
|
||
body:
|
||
'action=view'
|
||
+ '&epr_id=' + encodeURIComponent(epr_id)
|
||
+ '&range_id=' + encodeURIComponent(range_id)
|
||
+ bibAjaxLangSuffix()
|
||
})
|
||
.then(res => res.text())
|
||
.then(raw => {
|
||
|
||
let data;
|
||
try {
|
||
data = JSON.parse(raw);
|
||
} catch (err) {
|
||
console.log(bibJs('jsServerError'));
|
||
return;
|
||
}
|
||
|
||
if (!data.success) {
|
||
console.log(data.message || bibJs('jsErrGeneric'));
|
||
return;
|
||
}
|
||
|
||
let row = btnView.closest('.epr-row');
|
||
|
||
// Injecter la nouvelle vue sous la ligne du bouton cliqué,
|
||
// en mémorisant epr_id et range_id pour le toggle suivant
|
||
row.insertAdjacentHTML('afterend', data.html);
|
||
|
||
// Stocker les identifiants sur la vue injectée pour pouvoir détecter
|
||
// le 2e clic sur le même œil
|
||
let newView = row.nextElementSibling;
|
||
if (newView && newView.classList.contains('epr-row-view')) {
|
||
newView.dataset.eprId = epr_id;
|
||
newView.dataset.rangeId = range_id;
|
||
}
|
||
});
|
||
|
||
return;
|
||
}
|
||
|
||
|
||
// =====================
|
||
// CLOSE VIEW
|
||
// =====================
|
||
let btnClose = e.target.closest('.btn-close-view');
|
||
if (btnClose) {
|
||
e.preventDefault();
|
||
|
||
let view = btnClose.closest('.epr-row-view');
|
||
if (view) {
|
||
view.remove();
|
||
}
|
||
|
||
return;
|
||
}
|
||
// =====================
|
||
// ASSIGN BATCH
|
||
// =====================
|
||
// Active/désactive le mode batch pour UNE épreuve.
|
||
// - Affiche les checkbox
|
||
// - Bloque Début/Fin
|
||
// - Affiche le bloc de configuration
|
||
// - Recalcule l’analyse initiale
|
||
// =====================
|
||
let btnBatch = e.target.closest('.btn-assign-batch');
|
||
if (btnBatch) {
|
||
|
||
e.preventDefault();
|
||
|
||
let row = btnBatch.closest('.epr-row');
|
||
if (!row) return;
|
||
|
||
// MSIN-4379 — Batch et auto sont mutuellement exclusifs.
|
||
if (row.classList.contains('auto-mode')) {
|
||
return;
|
||
}
|
||
|
||
let container = row.querySelector('.bib-container');
|
||
if (!container) return;
|
||
|
||
// OFF
|
||
if (row.classList.contains('batch-mode')) {
|
||
|
||
row.classList.remove('batch-mode');
|
||
row.querySelectorAll('.batch-select-range').forEach(cb => {
|
||
cb.disabled = false;
|
||
});
|
||
container.classList.remove('batch-mode');
|
||
|
||
row.querySelectorAll('.bib-start, .bib-qty, .bib-end').forEach(input => {
|
||
input.removeAttribute('readonly');
|
||
});
|
||
|
||
btnBatch.textContent = row.dataset.batchLabel || btnBatch.textContent;
|
||
|
||
let goBtn = row.querySelector('.btn-go-batch');
|
||
if (goBtn) {
|
||
goBtn.textContent = row.dataset.goLabel || goBtn.textContent;
|
||
}
|
||
row.querySelectorAll('.batch-select-range').forEach(cb => {
|
||
cb.checked = false;
|
||
});
|
||
let info = row.querySelector('.epr-actions .batch-info-text');
|
||
if (info) info.textContent = '';
|
||
syncBibUiState(row);
|
||
return;
|
||
}
|
||
|
||
// ON
|
||
row.classList.add('batch-mode');
|
||
container.classList.add('batch-mode');
|
||
|
||
row.querySelectorAll('.bib-start, .bib-qty, .bib-end').forEach(input => {
|
||
input.setAttribute('readonly', true);
|
||
});
|
||
|
||
btnBatch.textContent = row.dataset.batchLabelCancel || btnBatch.textContent;
|
||
let goBtn = row.querySelector('.btn-go-batch');
|
||
if (goBtn) {
|
||
goBtn.textContent = row.dataset.goLabel || goBtn.textContent;
|
||
}
|
||
if (typeof updateBatchAnalysis === 'function') {
|
||
updateBatchAnalysis(row);
|
||
}
|
||
syncBibUiState(row);
|
||
|
||
return;
|
||
}
|
||
// =====================
|
||
// SIMULER BATCH
|
||
// =====================
|
||
let btnSim = e.target.closest('.btn-simuler-batch');
|
||
if (btnSim) {
|
||
|
||
e.preventDefault();
|
||
|
||
let row = btnSim.closest('.epr-row');
|
||
if (!row) return;
|
||
|
||
let selected = [];
|
||
|
||
row.querySelectorAll('.batch-select-range:checked').forEach(cb => {
|
||
selected.push(cb.dataset.rangeId);
|
||
});
|
||
|
||
if (selected.length === 0) {
|
||
alert(bibJs('jsNoSeqSelected'));
|
||
return;
|
||
}
|
||
let isResetMode = row.dataset.mode === 'reset';
|
||
let sortKeys = bibGetRowSortKeys(row);
|
||
|
||
bibFetch('/ajax_bib_range.php', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/x-www-form-urlencoded'
|
||
},
|
||
body:
|
||
(isResetMode ? 'action=reset_preview' : 'action=batch_go')
|
||
+ '&epr_id=' + encodeURIComponent(row.dataset.eprId)
|
||
+ '&ranges=' + encodeURIComponent(JSON.stringify(selected))
|
||
+ bibAppendBatchSortParams('', sortKeys)
|
||
+ bibAjaxLangSuffix()
|
||
})
|
||
.then(res => res.json())
|
||
.then(data => {
|
||
|
||
if (!data.success) {
|
||
alert(data.message || bibJs('jsErrGeneric'));
|
||
return;
|
||
}
|
||
|
||
let existing = document.querySelector('.epr-row-view');
|
||
if (existing) {
|
||
existing.remove();
|
||
}
|
||
|
||
row.insertAdjacentHTML('afterend', data.html);
|
||
|
||
|
||
});
|
||
|
||
return;
|
||
}
|
||
|
||
// =====================
|
||
// RESET MODE
|
||
// =====================
|
||
let btnReset = e.target.closest('.btn-reset');
|
||
if (btnReset) {
|
||
|
||
e.preventDefault();
|
||
|
||
let row = btnReset.closest('.epr-row');
|
||
if (!row) return;
|
||
|
||
// MSIN-4379 — Reset et auto sont mutuellement exclusifs.
|
||
if (row.classList.contains('auto-mode')) {
|
||
return;
|
||
}
|
||
|
||
let container = row.querySelector('.bib-container');
|
||
if (!container) return;
|
||
|
||
// =====================
|
||
// OFF
|
||
// =====================
|
||
if (row.classList.contains('reset-mode')) {
|
||
|
||
row.classList.remove('reset-mode');
|
||
btnReset.textContent = row.dataset.resetLabel || btnReset.textContent;
|
||
container.classList.remove('batch-mode');
|
||
|
||
row.querySelectorAll('.bib-start, .bib-qty, .bib-end').forEach(input => {
|
||
input.removeAttribute('readonly');
|
||
});
|
||
|
||
row.querySelectorAll('.batch-select-range').forEach(cb => {
|
||
cb.checked = false;
|
||
});
|
||
|
||
let goBtn = row.querySelector('.btn-go-batch');
|
||
if (goBtn) {
|
||
goBtn.textContent = row.dataset.goLabel || goBtn.textContent;
|
||
}
|
||
|
||
let info = row.querySelector('.epr-actions .batch-info-text');
|
||
if (info) {
|
||
info.innerHTML = '';
|
||
}
|
||
row.dataset.mode = '';
|
||
syncBibUiState(row);
|
||
return;
|
||
}
|
||
|
||
// =====================
|
||
// ON
|
||
// =====================
|
||
row.classList.add('reset-mode');
|
||
btnReset.textContent = row.dataset.resetCancelLabel || btnReset.textContent;
|
||
row.dataset.mode = 'reset';
|
||
container.classList.add('batch-mode');
|
||
|
||
row.querySelectorAll('.bib-start, .bib-qty, .bib-end').forEach(input => {
|
||
input.setAttribute('readonly', true);
|
||
});
|
||
|
||
syncBibUiState(row);
|
||
|
||
let goBtn = row.querySelector('.btn-go-batch');
|
||
if (goBtn) {
|
||
goBtn.textContent = row.dataset.resetLabel || goBtn.textContent;
|
||
}
|
||
|
||
bibFetch('/ajax_bib_range.php', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/x-www-form-urlencoded'
|
||
},
|
||
body:
|
||
'action=refresh_ranges'
|
||
+ '&epr_id=' + encodeURIComponent(row.dataset.eprId)
|
||
+ '&mode=reset'
|
||
+ bibAjaxLangSuffix()
|
||
})
|
||
.then(res => res.json())
|
||
.then(data => {
|
||
|
||
if (!data.success) return;
|
||
|
||
let container = setBibContainerHtml(row, data.html);
|
||
if (!container) return;
|
||
|
||
container.classList.add('batch-mode');
|
||
|
||
row.querySelectorAll('.bib-start, .bib-qty, .bib-end').forEach(input => {
|
||
input.setAttribute('readonly', true);
|
||
});
|
||
|
||
syncBibUiState(row);
|
||
});
|
||
|
||
return;
|
||
}
|
||
|
||
|
||
|
||
|
||
// =====================
|
||
// GO BATCH
|
||
// =====================
|
||
let btnGo = e.target.closest('.btn-go-batch');
|
||
if (btnGo) {
|
||
|
||
e.preventDefault();
|
||
|
||
let row = btnGo.closest('.epr-row');
|
||
if (!row) return;
|
||
|
||
let selected = [];
|
||
|
||
row.querySelectorAll('.batch-select-range:checked').forEach(cb => {
|
||
selected.push(cb.dataset.rangeId);
|
||
});
|
||
|
||
if (selected.length === 0) {
|
||
alert(bibJs('jsNoSeqSelected'));
|
||
return;
|
||
}
|
||
let isResetMode = row.dataset.mode === 'reset';
|
||
let sortKeys = bibGetRowSortKeys(row);
|
||
|
||
if (isResetMode) {
|
||
bibFetch('/ajax_bib_range.php', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/x-www-form-urlencoded'
|
||
},
|
||
body:
|
||
'action=reset_apply'
|
||
+ '&epr_id=' + encodeURIComponent(row.dataset.eprId)
|
||
+ '&ranges=' + encodeURIComponent(JSON.stringify(selected))
|
||
+ bibAppendBatchSortParams('', sortKeys)
|
||
+ bibAjaxLangSuffix()
|
||
})
|
||
.then(res => res.json())
|
||
.then(data => {
|
||
|
||
if (!data.success) {
|
||
alert(data.message || bibJs('jsErrGeneric'));
|
||
return;
|
||
}
|
||
|
||
bibAfterBatchGoSuccess(row, data, true);
|
||
});
|
||
|
||
return;
|
||
}
|
||
|
||
bibRunBatchApplyChunks(row, selected, sortKeys);
|
||
|
||
return;
|
||
}
|
||
|
||
// =====================
|
||
// MSIN-4379 — Étape 2 : AUTO DOSSARD (clics Accepter / Annuler / Désactiver / Activer)
|
||
// Prochain tour : étape 6–7 (assignation PHP à l'inscription).
|
||
// =====================
|
||
let btnAccepterAuto = e.target.closest('.btn-accepter-auto');
|
||
if (btnAccepterAuto) {
|
||
|
||
e.preventDefault();
|
||
|
||
let row = btnAccepterAuto.closest('.epr-row');
|
||
if (!row) return;
|
||
|
||
let selected = [];
|
||
|
||
row.querySelectorAll('.batch-select-range:checked').forEach(cb => {
|
||
selected.push(cb.dataset.rangeId);
|
||
});
|
||
|
||
if (selected.length === 0) {
|
||
alert(bibJs('jsNoSeqSelected'));
|
||
return;
|
||
}
|
||
|
||
if (bibRowPendingBibs(row) > 0) {
|
||
bibAlertAutoPendingBibs(row);
|
||
return;
|
||
}
|
||
|
||
// MSIN-4379 — Persiste epr_bib_auto=1 sur les séquences choisies (save_auto_config).
|
||
bibFetch('/ajax_bib_range.php', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/x-www-form-urlencoded'
|
||
},
|
||
body:
|
||
'action=save_auto_config'
|
||
+ '&epr_id=' + encodeURIComponent(row.dataset.eprId)
|
||
+ '&active=1'
|
||
+ '&ranges=' + encodeURIComponent(JSON.stringify(selected))
|
||
+ bibAjaxLangSuffix()
|
||
})
|
||
.then(res => res.json())
|
||
.then(data => {
|
||
|
||
if (!data.success) {
|
||
alert(data.message || bibJs('jsErrGeneric'));
|
||
return;
|
||
}
|
||
|
||
syncAutoUiState(row, true);
|
||
exitAutoMode(row);
|
||
syncBibUiState(row);
|
||
});
|
||
|
||
return;
|
||
}
|
||
|
||
// MSIN-4379 — Annule l'édition sans appeler save_auto_config.
|
||
let btnAnnulerAuto = e.target.closest('.btn-annuler-auto');
|
||
if (btnAnnulerAuto) {
|
||
|
||
e.preventDefault();
|
||
|
||
let row = btnAnnulerAuto.closest('.epr-row');
|
||
if (!row) return;
|
||
|
||
exitAutoMode(row);
|
||
return;
|
||
}
|
||
|
||
// MSIN-4379 — Désactive l'auto en base (active=0, toutes les séquences à 0).
|
||
let btnDesactiverAuto = e.target.closest('.btn-desactiver-auto');
|
||
if (btnDesactiverAuto) {
|
||
|
||
e.preventDefault();
|
||
|
||
let row = btnDesactiverAuto.closest('.epr-row');
|
||
if (!row) return;
|
||
|
||
if (!confirm(bibJs('jsAutoDisableConfirm'))) {
|
||
return;
|
||
}
|
||
|
||
bibFetch('/ajax_bib_range.php', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/x-www-form-urlencoded'
|
||
},
|
||
body:
|
||
'action=save_auto_config'
|
||
+ '&epr_id=' + encodeURIComponent(row.dataset.eprId)
|
||
+ '&active=0'
|
||
+ '&ranges=' + encodeURIComponent('[]')
|
||
+ bibAjaxLangSuffix()
|
||
})
|
||
.then(res => res.json())
|
||
.then(data => {
|
||
|
||
if (!data.success) {
|
||
alert(data.message || bibJs('jsErrGeneric'));
|
||
return;
|
||
}
|
||
|
||
syncAutoUiState(row, false);
|
||
exitAutoMode(row);
|
||
syncBibUiState(row);
|
||
});
|
||
|
||
return;
|
||
}
|
||
|
||
// MSIN-4379 — Entrée dans le mode configuration auto.
|
||
let btnAuto = e.target.closest('.btn-auto');
|
||
if (btnAuto) {
|
||
|
||
e.preventDefault();
|
||
|
||
let row = btnAuto.closest('.epr-row');
|
||
if (!row) return;
|
||
|
||
if (row.classList.contains('batch-mode') || row.classList.contains('reset-mode')) {
|
||
return;
|
||
}
|
||
|
||
enterAutoMode(row);
|
||
return;
|
||
}
|
||
|
||
// =====================
|
||
// CREATE
|
||
// =====================
|
||
|
||
let btn = e.target.closest('.btn-add-range');
|
||
if (!btn) return;
|
||
|
||
e.preventDefault();
|
||
|
||
let container = btn.closest('.bib-container');
|
||
let errorDiv = container.querySelector('.bib-error-global');
|
||
|
||
// reset
|
||
if (errorDiv) {
|
||
errorDiv.style.display = 'none';
|
||
errorDiv.innerText = '';
|
||
}
|
||
|
||
let epr_id = btn.dataset.eprId;
|
||
if (!epr_id) return;
|
||
|
||
bibFetch('/ajax_bib_range.php', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/x-www-form-urlencoded'
|
||
},
|
||
body: 'action=create&epr_id=' + encodeURIComponent(epr_id) + bibAjaxLangSuffix()
|
||
})
|
||
.then(res => res.text())
|
||
.then(raw => {
|
||
|
||
let data;
|
||
try {
|
||
data = JSON.parse(raw);
|
||
} catch (err) {
|
||
if (errorDiv) {
|
||
errorDiv.innerText = bibJs('jsServerError');
|
||
errorDiv.style.display = 'block';
|
||
}
|
||
return;
|
||
}
|
||
|
||
if (!data.success) {
|
||
console.log('CREATE ERROR:', data);
|
||
console.log('container:', container);
|
||
console.log('errorDiv:', errorDiv);
|
||
if (errorDiv) {
|
||
errorDiv.innerText = data.message || bibJs('jsErrGeneric');
|
||
errorDiv.style.display = 'block';
|
||
}
|
||
return;
|
||
}
|
||
|
||
setBibContainerHtml(btn.closest('.epr-row'), data.html);
|
||
});
|
||
});
|
||
|
||
function syncBibEventConfigHeaderNote() {
|
||
let note = document.querySelector('[data-bib-inter-epr-note]');
|
||
let chk = moduleBib.querySelector('.bib-event-allow-inter-epr');
|
||
if (!note || !chk) {
|
||
return;
|
||
}
|
||
note.classList.toggle('bib-ui-hidden', !chk.checked);
|
||
}
|
||
|
||
// MSIN-4424 — Autoriser mêmes numéros entre épreuves (réglage événement).
|
||
let chkAllowInterEpr = moduleBib.querySelector('.bib-event-allow-inter-epr');
|
||
if (chkAllowInterEpr) {
|
||
chkAllowInterEpr.addEventListener('change', function () {
|
||
let eveId = moduleBib.dataset.eveId || '';
|
||
if (!eveId) {
|
||
return;
|
||
}
|
||
|
||
bibFetch('/ajax_bib_range.php', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/x-www-form-urlencoded'
|
||
},
|
||
body:
|
||
'action=save_allow_inter_epr'
|
||
+ '&eve_id=' + encodeURIComponent(eveId)
|
||
+ '&allow=' + (chkAllowInterEpr.checked ? '1' : '0')
|
||
+ bibAjaxLangSuffix()
|
||
})
|
||
.then(function (res) { return res.json(); })
|
||
.then(function (data) {
|
||
if (!data.success) {
|
||
chkAllowInterEpr.checked = !chkAllowInterEpr.checked;
|
||
alert(data.message || bibJs('jsErrGeneric'));
|
||
return;
|
||
}
|
||
|
||
moduleBib.dataset.allowInterEpr = data.allow_inter_epr ? '1' : '0';
|
||
syncBibEventConfigHeaderNote();
|
||
|
||
let mount = document.getElementById('bib-anomalies-mount');
|
||
if (mount && data.anomalies_html) {
|
||
mount.innerHTML = data.anomalies_html;
|
||
initModuleBibTippy(mount);
|
||
}
|
||
|
||
if (bibQtySummaryShouldRefresh()) {
|
||
refreshBibQtySummaryPanel();
|
||
}
|
||
})
|
||
.catch(function () {
|
||
chkAllowInterEpr.checked = !chkAllowInterEpr.checked;
|
||
alert(bibJs('jsErrGeneric'));
|
||
});
|
||
});
|
||
}
|
||
|
||
// MSIN-4436 — Anomalies : coquille légère au chargement, détail en AJAX.
|
||
if (document.querySelector('#bib-anomalies-panel[data-bib-anomalies-deferred="1"]')) {
|
||
refreshBibAnomaliesPanel().then(function () {
|
||
bibApplyFocusFromUrlOnce();
|
||
});
|
||
} else {
|
||
bibApplyFocusFromUrlOnce();
|
||
}
|
||
}
|
||
})();
|