850 lines
29 KiB
JavaScript
850 lines
29 KiB
JavaScript
(function () {
|
||
"use strict";
|
||
let analysisMatriciMap = {};
|
||
let analysisLoadedCache = {};
|
||
let analysisAssignedState = {};
|
||
let analysisSelectedState = {};
|
||
|
||
function loadAnalysisMatrixNames() {
|
||
return $.ajax({
|
||
url: "get_matrici_db.php",
|
||
method: "GET",
|
||
dataType: "json",
|
||
})
|
||
.done(function (data) {
|
||
analysisMatriciMap = {};
|
||
|
||
(data.value || []).forEach(function (matrice) {
|
||
analysisMatriciMap[String(matrice.IdMatrice)] =
|
||
matrice.NomeMatrice || "#" + matrice.IdMatrice;
|
||
});
|
||
|
||
applyAnalysisMatrixNames();
|
||
})
|
||
.fail(function () {
|
||
analysisMatriciMap = {};
|
||
applyAnalysisMatrixNames();
|
||
});
|
||
}
|
||
|
||
function applyAnalysisMatrixNames() {
|
||
const modal = document.getElementById("analysisModal");
|
||
if (!modal) return;
|
||
|
||
modal.querySelectorAll(".analysis-matrix-item").forEach((item) => {
|
||
const matrixId = item.getAttribute("data-matrix-id");
|
||
const nameEl = item.querySelector(".analysis-matrix-name");
|
||
|
||
let matrixName = "No Matrix";
|
||
if (matrixId && matrixId !== "NO_MATRIX") {
|
||
matrixName =
|
||
analysisMatriciMap[String(matrixId)] || "#" + matrixId;
|
||
}
|
||
|
||
item.setAttribute("data-matrix-name", matrixName);
|
||
|
||
if (nameEl) {
|
||
nameEl.textContent = matrixName;
|
||
}
|
||
});
|
||
|
||
modal.querySelectorAll(".analysis-part-matrix-name").forEach((el) => {
|
||
const matrixId = el.getAttribute("data-matrix-id");
|
||
|
||
if (!matrixId || matrixId === "NO_MATRIX") {
|
||
el.textContent = "No Matrix";
|
||
return;
|
||
}
|
||
|
||
el.textContent =
|
||
analysisMatriciMap[String(matrixId)] || "#" + matrixId;
|
||
});
|
||
}
|
||
function readInitialAssignedAnalyses() {
|
||
const jsonEl = document.getElementById("analysisAssignedInitialData");
|
||
if (!jsonEl) {
|
||
analysisAssignedState = {};
|
||
return;
|
||
}
|
||
|
||
try {
|
||
analysisAssignedState =
|
||
JSON.parse(jsonEl.textContent || "{}") || {};
|
||
} catch (e) {
|
||
analysisAssignedState = {};
|
||
}
|
||
}
|
||
|
||
function getSelectedPartIds() {
|
||
const modal = document.getElementById("analysisModal");
|
||
if (!modal) return [];
|
||
|
||
return Array.from(
|
||
modal.querySelectorAll(".analysis-part-checkbox:checked"),
|
||
).map((el) => String(el.value));
|
||
}
|
||
|
||
function getCurrentSelectedAnalysisRecordKeys() {
|
||
return Object.keys(analysisSelectedState).filter(function (key) {
|
||
return analysisSelectedState[key] === true;
|
||
});
|
||
}
|
||
|
||
function renderAssignedAnalysesForPart(partId) {
|
||
const container = document.getElementById(
|
||
"analysisAssignedListPart" + partId,
|
||
);
|
||
if (!container) return;
|
||
|
||
const items = Array.isArray(analysisAssignedState[String(partId)])
|
||
? analysisAssignedState[String(partId)]
|
||
: [];
|
||
|
||
if (!items.length) {
|
||
container.innerHTML = "";
|
||
return;
|
||
}
|
||
|
||
container.innerHTML = items
|
||
.map(function (item) {
|
||
const recordKey = item.analysis_recordkey || "";
|
||
const title = item.analysis_name || "Unnamed analysis";
|
||
const method = item.analysis_method || "";
|
||
|
||
return `
|
||
<div class="analysis-assigned-chip" data-recordkey="${escapeHtml(recordKey)}">
|
||
<div class="analysis-assigned-chip-text">
|
||
<div class="analysis-assigned-chip-title">${escapeHtml(title)}</div>
|
||
${method ? `<div class="analysis-assigned-chip-method">${escapeHtml(method)}</div>` : ""}
|
||
</div>
|
||
<button type="button"
|
||
class="analysis-remove-btn"
|
||
data-part-id="${escapeHtml(partId)}"
|
||
data-recordkey="${escapeHtml(recordKey)}"
|
||
title="Remove analysis">×</button>
|
||
</div>
|
||
`;
|
||
})
|
||
.join("");
|
||
}
|
||
|
||
function renderAssignedAnalysesForSelectedParts() {
|
||
const modal = document.getElementById("analysisModal");
|
||
if (!modal) return;
|
||
|
||
modal.querySelectorAll(".analysis-part-item").forEach(function (item) {
|
||
const partId = item.getAttribute("data-part-id");
|
||
renderAssignedAnalysesForPart(partId);
|
||
});
|
||
}
|
||
|
||
function syncSelectedAnalysisRows() {
|
||
const modal = document.getElementById("analysisModal");
|
||
if (!modal) return;
|
||
|
||
modal
|
||
.querySelectorAll(".analysis-analysis-item")
|
||
.forEach(function (item) {
|
||
const recordKey = item.getAttribute("data-recordkey") || "";
|
||
if (recordKey && analysisSelectedState[recordKey]) {
|
||
item.classList.add("analysis-selected");
|
||
} else {
|
||
item.classList.remove("analysis-selected");
|
||
}
|
||
});
|
||
}
|
||
|
||
function buildAnalysisPayloadFromRow(rowEl) {
|
||
return {
|
||
analysis_recordkey: rowEl.getAttribute("data-recordkey") || "",
|
||
analysis_name: rowEl.getAttribute("data-analysis-name") || "",
|
||
analysis_method: rowEl.getAttribute("data-analysis-method") || "",
|
||
analysis_level: rowEl.getAttribute("data-analysis-level") || "",
|
||
is_web_selectable: rowEl.getAttribute("data-web") === "1" ? 1 : 0,
|
||
is_accredited:
|
||
rowEl.getAttribute("data-accredited") === "1" ? 1 : 0,
|
||
};
|
||
}
|
||
|
||
function addAnalysisToLocalState(partId, payload, iddatadb, idmatrice) {
|
||
const key = String(partId);
|
||
if (!Array.isArray(analysisAssignedState[key])) {
|
||
analysisAssignedState[key] = [];
|
||
}
|
||
|
||
const exists = analysisAssignedState[key].some(function (item) {
|
||
return item.analysis_recordkey === payload.analysis_recordkey;
|
||
});
|
||
|
||
if (!exists) {
|
||
analysisAssignedState[key].push({
|
||
id: null,
|
||
part_id: parseInt(partId, 10),
|
||
iddatadb: iddatadb || null,
|
||
idmatrice: idmatrice || null,
|
||
analysis_recordkey: payload.analysis_recordkey,
|
||
analysis_name: payload.analysis_name,
|
||
analysis_method: payload.analysis_method,
|
||
analysis_level:
|
||
payload.analysis_level !== ""
|
||
? parseInt(payload.analysis_level, 10)
|
||
: null,
|
||
is_web_selectable: payload.is_web_selectable,
|
||
is_accredited: payload.is_accredited,
|
||
});
|
||
}
|
||
}
|
||
|
||
function removeAnalysisFromLocalState(partId, recordKey) {
|
||
const key = String(partId);
|
||
if (!Array.isArray(analysisAssignedState[key])) {
|
||
return;
|
||
}
|
||
|
||
analysisAssignedState[key] = analysisAssignedState[key].filter(
|
||
function (item) {
|
||
return item.analysis_recordkey !== recordKey;
|
||
},
|
||
);
|
||
}
|
||
|
||
function saveAnalysisAssociation(partId, payload, callback) {
|
||
const modal = document.getElementById("analysisModal");
|
||
if (!modal) return;
|
||
|
||
const iddatadb =
|
||
modal.querySelector("#analysisModalIddatadb")?.value || "";
|
||
const partItem = modal.querySelector(
|
||
'.analysis-part-item[data-part-id="' + partId + '"]',
|
||
);
|
||
const idmatrice = partItem
|
||
? partItem.getAttribute("data-matrix-id") || ""
|
||
: "";
|
||
|
||
$.ajax({
|
||
url: "save_part_analysis.php",
|
||
method: "POST",
|
||
dataType: "json",
|
||
data: {
|
||
part_id: partId,
|
||
iddatadb: iddatadb,
|
||
idmatrice: idmatrice !== "NO_MATRIX" ? idmatrice : "",
|
||
analysis_recordkey: payload.analysis_recordkey,
|
||
analysis_name: payload.analysis_name,
|
||
analysis_method: payload.analysis_method,
|
||
analysis_level: payload.analysis_level,
|
||
is_web_selectable: payload.is_web_selectable,
|
||
is_accredited: payload.is_accredited,
|
||
},
|
||
})
|
||
.done(function () {
|
||
addAnalysisToLocalState(
|
||
partId,
|
||
payload,
|
||
iddatadb,
|
||
idmatrice !== "NO_MATRIX" ? idmatrice : null,
|
||
);
|
||
renderAssignedAnalysesForPart(partId);
|
||
if (typeof callback === "function") callback(true);
|
||
})
|
||
.fail(function (xhr) {
|
||
let message = "Error saving analysis association";
|
||
if (xhr && xhr.responseJSON && xhr.responseJSON.message) {
|
||
message = xhr.responseJSON.message;
|
||
}
|
||
alert(message);
|
||
if (typeof callback === "function") callback(false);
|
||
});
|
||
}
|
||
|
||
function deleteAnalysisAssociation(partId, recordKey, callback) {
|
||
$.ajax({
|
||
url: "delete_part_analysis.php",
|
||
method: "POST",
|
||
dataType: "json",
|
||
data: {
|
||
part_id: partId,
|
||
analysis_recordkey: recordKey,
|
||
},
|
||
})
|
||
.done(function () {
|
||
removeAnalysisFromLocalState(partId, recordKey);
|
||
renderAssignedAnalysesForPart(partId);
|
||
if (typeof callback === "function") callback(true);
|
||
})
|
||
.fail(function (xhr) {
|
||
let message = "Error deleting analysis association";
|
||
if (xhr && xhr.responseJSON && xhr.responseJSON.message) {
|
||
message = xhr.responseJSON.message;
|
||
}
|
||
alert(message);
|
||
if (typeof callback === "function") callback(false);
|
||
});
|
||
}
|
||
function setAnalysisLoadingState(isLoading) {
|
||
const modal = document.getElementById("analysisModal");
|
||
if (!modal) return;
|
||
|
||
const loadingEl = modal.querySelector("#analysisLoadingBox");
|
||
if (!loadingEl) return;
|
||
|
||
if (isLoading) {
|
||
loadingEl.classList.remove("d-none");
|
||
} else {
|
||
loadingEl.classList.add("d-none");
|
||
}
|
||
}
|
||
|
||
function showAnalysisError(message) {
|
||
const modal = document.getElementById("analysisModal");
|
||
if (!modal) return;
|
||
|
||
const errorEl = modal.querySelector("#analysisErrorBox");
|
||
const emptyEl = modal.querySelector("#analysisEmptyBox");
|
||
const listEl = modal.querySelector("#analysisList");
|
||
|
||
if (listEl) listEl.innerHTML = "";
|
||
if (emptyEl) emptyEl.classList.add("d-none");
|
||
|
||
if (errorEl) {
|
||
errorEl.textContent = message || "Error loading analyses";
|
||
errorEl.classList.remove("d-none");
|
||
}
|
||
}
|
||
|
||
function showAnalysisEmpty(message) {
|
||
const modal = document.getElementById("analysisModal");
|
||
if (!modal) return;
|
||
|
||
const errorEl = modal.querySelector("#analysisErrorBox");
|
||
const emptyEl = modal.querySelector("#analysisEmptyBox");
|
||
const listEl = modal.querySelector("#analysisList");
|
||
|
||
if (listEl) listEl.innerHTML = "";
|
||
if (errorEl) errorEl.classList.add("d-none");
|
||
|
||
if (emptyEl) {
|
||
emptyEl.textContent =
|
||
message || "No analyses found for this matrix";
|
||
emptyEl.classList.remove("d-none");
|
||
}
|
||
}
|
||
|
||
function escapeHtml(value) {
|
||
return String(value ?? "")
|
||
.replace(/&/g, "&")
|
||
.replace(/</g, "<")
|
||
.replace(/>/g, ">")
|
||
.replace(/"/g, """)
|
||
.replace(/'/g, "'");
|
||
}
|
||
|
||
function renderAnalysesList(analyses) {
|
||
const modal = document.getElementById("analysisModal");
|
||
if (!modal) return;
|
||
|
||
const errorEl = modal.querySelector("#analysisErrorBox");
|
||
const emptyEl = modal.querySelector("#analysisEmptyBox");
|
||
const listEl = modal.querySelector("#analysisList");
|
||
|
||
if (!listEl) return;
|
||
|
||
if (errorEl) errorEl.classList.add("d-none");
|
||
|
||
if (!Array.isArray(analyses) || analyses.length === 0) {
|
||
showAnalysisEmpty("No analyses found for this matrix");
|
||
return;
|
||
}
|
||
|
||
if (emptyEl) emptyEl.classList.add("d-none");
|
||
|
||
listEl.innerHTML = analyses
|
||
.map(function (item) {
|
||
const recordKey = item.RecordKey || "";
|
||
const analysisName =
|
||
item.NomeAnalisiTraduzione ||
|
||
item.NomeAnalisi ||
|
||
"Unnamed analysis";
|
||
const methodName = item.MetodoNome || "";
|
||
const selectable = item.SelezionabileSuWeb === true;
|
||
const accredited = item.Accreditato === true;
|
||
const level = item.Livello ?? "";
|
||
const searchText = (
|
||
analysisName +
|
||
" " +
|
||
methodName
|
||
).toLowerCase();
|
||
|
||
let badges = "";
|
||
if (selectable) {
|
||
badges += '<span class="badge bg-success">Web</span>';
|
||
} else {
|
||
badges += '<span class="badge bg-secondary">Not web</span>';
|
||
}
|
||
|
||
if (accredited) {
|
||
badges +=
|
||
'<span class="badge bg-info text-dark">Accredited</span>';
|
||
}
|
||
|
||
if (level !== "") {
|
||
badges +=
|
||
'<span class="badge bg-light text-dark border">Level ' +
|
||
escapeHtml(level) +
|
||
"</span>";
|
||
}
|
||
|
||
return `
|
||
<div
|
||
class="list-group-item analysis-analysis-item"
|
||
data-recordkey="${escapeHtml(recordKey)}"
|
||
data-analysis-name="${escapeHtml(analysisName)}"
|
||
data-analysis-method="${escapeHtml(methodName)}"
|
||
data-analysis-level="${escapeHtml(level)}"
|
||
data-web="${selectable ? "1" : "0"}"
|
||
data-accredited="${accredited ? "1" : "0"}"
|
||
data-search="${escapeHtml(searchText)}"
|
||
>
|
||
<div class="fw-semibold">${escapeHtml(analysisName)}</div>
|
||
|
||
${methodName ? `<div class="analysis-analysis-meta mt-1">${escapeHtml(methodName)}</div>` : ""}
|
||
|
||
<div class="analysis-analysis-badges mt-2">
|
||
${badges}
|
||
</div>
|
||
</div>
|
||
`;
|
||
})
|
||
.join("");
|
||
|
||
filterAnalysisList();
|
||
syncSelectedAnalysisRows();
|
||
}
|
||
|
||
function filterAnalysisList() {
|
||
const modal = document.getElementById("analysisModal");
|
||
if (!modal) return;
|
||
|
||
const webOnlyEl = modal.querySelector("#analysisWebOnly");
|
||
const searchEl = modal.querySelector("#analysisSearchInput");
|
||
const items = modal.querySelectorAll(".analysis-analysis-item");
|
||
const emptyEl = modal.querySelector("#analysisEmptyBox");
|
||
const errorEl = modal.querySelector("#analysisErrorBox");
|
||
|
||
const webOnly = webOnlyEl ? webOnlyEl.checked : false;
|
||
const searchValue = searchEl ? searchEl.value.trim().toLowerCase() : "";
|
||
|
||
let visibleCount = 0;
|
||
|
||
items.forEach((item) => {
|
||
const isWeb = item.getAttribute("data-web") === "1";
|
||
const searchText = (
|
||
item.getAttribute("data-search") || ""
|
||
).toLowerCase();
|
||
|
||
let visible = true;
|
||
|
||
if (webOnly && !isWeb) {
|
||
visible = false;
|
||
}
|
||
|
||
if (visible && searchValue && !searchText.includes(searchValue)) {
|
||
visible = false;
|
||
}
|
||
|
||
item.style.display = visible ? "" : "none";
|
||
|
||
if (visible) {
|
||
visibleCount++;
|
||
}
|
||
});
|
||
|
||
if (errorEl) {
|
||
errorEl.classList.add("d-none");
|
||
}
|
||
|
||
if (emptyEl) {
|
||
if (items.length === 0) {
|
||
emptyEl.textContent = "No analyses found for this matrix";
|
||
emptyEl.classList.remove("d-none");
|
||
} else if (visibleCount === 0) {
|
||
emptyEl.textContent = "No analyses match the current filters";
|
||
emptyEl.classList.remove("d-none");
|
||
} else {
|
||
emptyEl.classList.add("d-none");
|
||
}
|
||
}
|
||
}
|
||
|
||
function loadAnalysesByMatrix(matrixId) {
|
||
const modal = document.getElementById("analysisModal");
|
||
if (!modal) return;
|
||
|
||
if (!matrixId || matrixId === "NO_MATRIX") {
|
||
showAnalysisEmpty("No matrix selected");
|
||
return;
|
||
}
|
||
|
||
const listEl = modal.querySelector("#analysisList");
|
||
const errorEl = modal.querySelector("#analysisErrorBox");
|
||
const emptyEl = modal.querySelector("#analysisEmptyBox");
|
||
|
||
if (listEl) listEl.innerHTML = "";
|
||
if (errorEl) errorEl.classList.add("d-none");
|
||
if (emptyEl) {
|
||
emptyEl.textContent = "";
|
||
emptyEl.classList.add("d-none");
|
||
}
|
||
|
||
if (analysisLoadedCache[String(matrixId)]) {
|
||
renderAnalysesList(analysisLoadedCache[String(matrixId)]);
|
||
return;
|
||
}
|
||
|
||
setAnalysisLoadingState(true);
|
||
|
||
$.ajax({
|
||
url: "get_analisi_matrice_filter.php",
|
||
method: "GET",
|
||
dataType: "json",
|
||
data: {
|
||
id_matrice: matrixId,
|
||
},
|
||
})
|
||
.done(function (response) {
|
||
const analyses = Array.isArray(response.value)
|
||
? response.value
|
||
: [];
|
||
analysisLoadedCache[String(matrixId)] = analyses;
|
||
renderAnalysesList(analyses);
|
||
})
|
||
.fail(function (xhr) {
|
||
let message = "Error loading analyses";
|
||
if (xhr && xhr.responseJSON && xhr.responseJSON.error) {
|
||
message = xhr.responseJSON.error;
|
||
}
|
||
showAnalysisError(message);
|
||
})
|
||
.always(function () {
|
||
setAnalysisLoadingState(false);
|
||
});
|
||
}
|
||
|
||
function updateSelectedPartsInfo() {
|
||
const modal = document.getElementById("analysisModal");
|
||
if (!modal) return;
|
||
|
||
const checked = modal.querySelectorAll(
|
||
".analysis-part-checkbox:checked",
|
||
);
|
||
const ids = Array.from(checked).map((el) => el.value);
|
||
|
||
const countEl = modal.querySelector("#analysisSelectedPartsCount");
|
||
const idsEl = modal.querySelector("#analysisSelectedPartsIds");
|
||
|
||
if (countEl) {
|
||
countEl.textContent = `${ids.length} selected`;
|
||
}
|
||
|
||
if (idsEl) {
|
||
idsEl.textContent = ids.length ? ids.join(", ") : "-";
|
||
}
|
||
|
||
modal.querySelectorAll(".analysis-part-item").forEach((item) => {
|
||
const checkbox = item.querySelector(".analysis-part-checkbox");
|
||
if (checkbox && checkbox.checked) {
|
||
item.classList.add("part-checked");
|
||
} else {
|
||
item.classList.remove("part-checked");
|
||
}
|
||
});
|
||
}
|
||
|
||
function selectPartsByMatrix(matrixId, matrixLabel) {
|
||
const modal = document.getElementById("analysisModal");
|
||
if (!modal) return;
|
||
|
||
const partItems = modal.querySelectorAll(".analysis-part-item");
|
||
const matrixLabelEl = modal.querySelector("#analysisCurrentMatrix");
|
||
|
||
partItems.forEach((item) => {
|
||
const itemMatrixId = item.getAttribute("data-matrix-id");
|
||
const checkbox = item.querySelector(".analysis-part-checkbox");
|
||
|
||
item.classList.remove("matrix-active");
|
||
|
||
if (itemMatrixId === String(matrixId)) {
|
||
item.classList.add("matrix-active");
|
||
if (checkbox) checkbox.checked = true;
|
||
} else {
|
||
if (checkbox) checkbox.checked = false;
|
||
}
|
||
});
|
||
|
||
if (matrixLabelEl) {
|
||
matrixLabelEl.textContent = matrixLabel || "-";
|
||
}
|
||
analysisSelectedState = {};
|
||
|
||
const selectedPartIds = getSelectedPartIds();
|
||
selectedPartIds.forEach(function (partId) {
|
||
const assigned = Array.isArray(
|
||
analysisAssignedState[String(partId)],
|
||
)
|
||
? analysisAssignedState[String(partId)]
|
||
: [];
|
||
|
||
assigned.forEach(function (item) {
|
||
if (item.analysis_recordkey) {
|
||
analysisSelectedState[item.analysis_recordkey] = true;
|
||
}
|
||
});
|
||
});
|
||
updateSelectedPartsInfo();
|
||
loadAnalysesByMatrix(matrixId);
|
||
}
|
||
|
||
function clearAnalysisSelection() {
|
||
const modal = document.getElementById("analysisModal");
|
||
if (!modal) return;
|
||
|
||
modal.querySelectorAll(".analysis-matrix-item").forEach((item) => {
|
||
item.classList.remove("active");
|
||
});
|
||
|
||
modal.querySelectorAll(".analysis-part-item").forEach((item) => {
|
||
item.classList.remove("matrix-active", "part-checked");
|
||
});
|
||
|
||
modal.querySelectorAll(".analysis-part-checkbox").forEach((cb) => {
|
||
cb.checked = false;
|
||
});
|
||
|
||
const matrixLabelEl = modal.querySelector("#analysisCurrentMatrix");
|
||
if (matrixLabelEl) matrixLabelEl.textContent = "-";
|
||
|
||
const webOnlyEl = modal.querySelector("#analysisWebOnly");
|
||
if (webOnlyEl) webOnlyEl.checked = false;
|
||
|
||
const searchEl = modal.querySelector("#analysisSearchInput");
|
||
if (searchEl) searchEl.value = "";
|
||
|
||
const listEl = modal.querySelector("#analysisList");
|
||
if (listEl) listEl.innerHTML = "";
|
||
|
||
showAnalysisEmpty("Select a matrix to load analyses");
|
||
updateSelectedPartsInfo();
|
||
}
|
||
|
||
function initAnalysisModal() {
|
||
const modal = document.getElementById("analysisModal");
|
||
if (!modal) return;
|
||
|
||
analysisLoadedCache = {};
|
||
analysisSelectedState = {};
|
||
readInitialAssignedAnalyses();
|
||
renderAssignedAnalysesForSelectedParts();
|
||
|
||
modal.querySelectorAll(".analysis-matrix-item").forEach((btn) => {
|
||
btn.addEventListener("click", function () {
|
||
modal
|
||
.querySelectorAll(".analysis-matrix-item")
|
||
.forEach((x) => x.classList.remove("active"));
|
||
this.classList.add("active");
|
||
|
||
const matrixId = this.getAttribute("data-matrix-id");
|
||
const matrixLabel =
|
||
this.getAttribute("data-matrix-name") ||
|
||
this.textContent.trim();
|
||
|
||
selectPartsByMatrix(matrixId, matrixLabel);
|
||
});
|
||
});
|
||
|
||
modal.querySelectorAll(".analysis-part-checkbox").forEach((cb) => {
|
||
cb.addEventListener("change", function () {
|
||
updateSelectedPartsInfo();
|
||
});
|
||
});
|
||
|
||
const clearBtn = modal.querySelector("#analysisClearSelectionBtn");
|
||
if (clearBtn) {
|
||
clearBtn.addEventListener("click", function () {
|
||
clearAnalysisSelection();
|
||
});
|
||
}
|
||
|
||
const webOnlyEl = modal.querySelector("#analysisWebOnly");
|
||
if (webOnlyEl) {
|
||
webOnlyEl.addEventListener("change", function () {
|
||
filterAnalysisList();
|
||
});
|
||
}
|
||
|
||
const searchEl = modal.querySelector("#analysisSearchInput");
|
||
if (searchEl) {
|
||
searchEl.addEventListener("input", function () {
|
||
filterAnalysisList();
|
||
});
|
||
}
|
||
modal.addEventListener("click", function (e) {
|
||
const removeBtn = e.target.closest(".analysis-remove-btn");
|
||
if (removeBtn) {
|
||
e.preventDefault();
|
||
e.stopPropagation();
|
||
|
||
const partId = removeBtn.getAttribute("data-part-id");
|
||
const recordKey = removeBtn.getAttribute("data-recordkey");
|
||
|
||
deleteAnalysisAssociation(partId, recordKey, function () {
|
||
const stillUsed = Object.keys(analysisAssignedState).some(
|
||
function (pid) {
|
||
return (
|
||
Array.isArray(analysisAssignedState[pid]) &&
|
||
analysisAssignedState[pid].some(
|
||
function (item) {
|
||
return (
|
||
item.analysis_recordkey ===
|
||
recordKey
|
||
);
|
||
},
|
||
)
|
||
);
|
||
},
|
||
);
|
||
|
||
if (!stillUsed) {
|
||
delete analysisSelectedState[recordKey];
|
||
}
|
||
|
||
syncSelectedAnalysisRows();
|
||
});
|
||
|
||
return;
|
||
}
|
||
|
||
const row = e.target.closest(".analysis-analysis-item");
|
||
if (!row) return;
|
||
|
||
const selectedPartIds = getSelectedPartIds();
|
||
if (!selectedPartIds.length) {
|
||
alert("Select at least one part first");
|
||
return;
|
||
}
|
||
|
||
const payload = buildAnalysisPayloadFromRow(row);
|
||
if (!payload.analysis_recordkey) {
|
||
alert("Invalid analysis record key");
|
||
return;
|
||
}
|
||
|
||
const recordKey = payload.analysis_recordkey;
|
||
const alreadySelected = !!analysisSelectedState[recordKey];
|
||
|
||
if (alreadySelected) {
|
||
selectedPartIds.forEach(function (partId) {
|
||
deleteAnalysisAssociation(partId, recordKey);
|
||
});
|
||
|
||
delete analysisSelectedState[recordKey];
|
||
syncSelectedAnalysisRows();
|
||
return;
|
||
}
|
||
|
||
let pending = selectedPartIds.length;
|
||
let atLeastOneSaved = false;
|
||
|
||
selectedPartIds.forEach(function (partId) {
|
||
saveAnalysisAssociation(partId, payload, function (ok) {
|
||
if (ok) atLeastOneSaved = true;
|
||
|
||
pending--;
|
||
if (pending <= 0 && atLeastOneSaved) {
|
||
analysisSelectedState[recordKey] = true;
|
||
syncSelectedAnalysisRows();
|
||
}
|
||
});
|
||
});
|
||
});
|
||
|
||
const firstActiveMatrix = modal.querySelector(
|
||
".analysis-matrix-item.active",
|
||
);
|
||
if (firstActiveMatrix) {
|
||
const matrixId = firstActiveMatrix.getAttribute("data-matrix-id");
|
||
const matrixLabel =
|
||
firstActiveMatrix.getAttribute("data-matrix-name") ||
|
||
firstActiveMatrix.textContent.trim();
|
||
|
||
selectPartsByMatrix(matrixId, matrixLabel);
|
||
} else {
|
||
updateSelectedPartsInfo();
|
||
}
|
||
}
|
||
|
||
// OPEN ANALYSIS MODAL FROM PARTS MODAL BUTTON
|
||
$(document).on("click", ".open-analysis-modal-btn", function () {
|
||
const partsModal = document.getElementById("partsModal");
|
||
const iddatadb = $("#partsModal").data("iddatadb");
|
||
|
||
if (!iddatadb) {
|
||
console.error("iddatadb not found on #partsModal");
|
||
alert("iddatadb not found");
|
||
return;
|
||
}
|
||
|
||
$.ajax({
|
||
url: "modal_analysis.php",
|
||
method: "GET",
|
||
data: { iddatadb: iddatadb },
|
||
success: function (response) {
|
||
$("#analysisModalContainer").html(response);
|
||
|
||
const modalElement = document.getElementById("analysisModal");
|
||
if (!modalElement) {
|
||
console.error("Analysis modal not found: #analysisModal");
|
||
return;
|
||
}
|
||
|
||
let modal = bootstrap.Modal.getInstance(modalElement);
|
||
if (!modal) {
|
||
modal = new bootstrap.Modal(modalElement, {
|
||
backdrop: true,
|
||
keyboard: true,
|
||
focus: true,
|
||
});
|
||
}
|
||
|
||
loadAnalysisMatrixNames().always(function () {
|
||
initAnalysisModal();
|
||
modal.show();
|
||
});
|
||
},
|
||
error: function (xhr, status, error) {
|
||
console.error("Error loading analysis modal:", error);
|
||
alert("Error loading analysis modal: " + error);
|
||
},
|
||
});
|
||
});
|
||
|
||
// CLEANUP ON CLOSE
|
||
$(document).on("hidden.bs.modal", "#analysisModal", function () {
|
||
const modalElement = document.getElementById("analysisModal");
|
||
if (modalElement) {
|
||
const modal = bootstrap.Modal.getInstance(modalElement);
|
||
if (modal) modal.dispose();
|
||
}
|
||
|
||
$("#analysisModalContainer").empty();
|
||
|
||
// keep parts modal alive, but remove extra backdrop leftovers
|
||
$(".modal-backdrop").last().remove();
|
||
|
||
if ($("#partsModal").hasClass("show")) {
|
||
$("body").addClass("modal-open");
|
||
} else {
|
||
$("body").removeClass("modal-open").css("padding-right", "");
|
||
}
|
||
});
|
||
})();
|