multiple analysis on same parts

This commit is contained in:
2026-07-23 12:13:28 +02:00
parent a300932421
commit b2a79aec1b
4 changed files with 107 additions and 58 deletions
+55 -38
View File
@@ -106,8 +106,9 @@
}
container.innerHTML = items
.map(function (item) {
.map(function (item, index) {
const recordKey = item.analysis_recordkey || "";
const rowId = item.id != null ? item.id : "";
const title = item.analysis_name || "Unnamed analysis";
const method = item.analysis_method || "";
@@ -121,6 +122,8 @@
class="analysis-remove-btn"
data-part-id="${escapeHtml(partId)}"
data-recordkey="${escapeHtml(recordKey)}"
data-row-id="${escapeHtml(rowId)}"
data-index="${index}"
title="Remove analysis">×</button>
</div>
`;
@@ -166,19 +169,21 @@
};
}
function addAnalysisToLocalState(partId, payload, iddatadb, idmatrice) {
function addAnalysisToLocalState(
partId,
payload,
iddatadb,
idmatrice,
newId,
) {
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,
id: newId || null,
part_id: parseInt(partId, 10),
iddatadb: iddatadb || null,
idmatrice: idmatrice || null,
@@ -195,17 +200,24 @@
}
}
function removeAnalysisFromLocalState(partId, recordKey) {
function removeAnalysisFromLocalState(partId, recordKey, index) {
const key = String(partId);
if (!Array.isArray(analysisAssignedState[key])) {
return;
}
analysisAssignedState[key] = analysisAssignedState[key].filter(
function (item) {
return item.analysis_recordkey !== recordKey;
},
);
const i = parseInt(index, 10);
if (!isNaN(i) && i >= 0 && i < analysisAssignedState[key].length) {
analysisAssignedState[key].splice(i, 1);
return;
}
const found = analysisAssignedState[key].findIndex(function (item) {
return item.analysis_recordkey === recordKey;
});
if (found !== -1) {
analysisAssignedState[key].splice(found, 1);
}
}
function saveAnalysisAssociation(partId, payload, callback) {
@@ -237,12 +249,13 @@
is_accredited: payload.is_accredited,
},
})
.done(function () {
.done(function (resp) {
addAnalysisToLocalState(
partId,
payload,
iddatadb,
idmatrice !== "NO_MATRIX" ? idmatrice : null,
resp && resp.id ? resp.id : null,
);
renderAssignedAnalysesForPart(partId);
if (typeof callback === "function") callback(true);
@@ -257,7 +270,13 @@
});
}
function deleteAnalysisAssociation(partId, recordKey, callback) {
function deleteAnalysisAssociation(
partId,
recordKey,
rowId,
index,
callback,
) {
$.ajax({
url: "delete_part_analysis.php",
method: "POST",
@@ -265,10 +284,11 @@
data: {
part_id: partId,
analysis_recordkey: recordKey,
row_id: rowId || "",
},
})
.done(function () {
removeAnalysisFromLocalState(partId, recordKey);
removeAnalysisFromLocalState(partId, recordKey, index);
renderAssignedAnalysesForPart(partId);
if (typeof callback === "function") callback(true);
})
@@ -707,10 +727,18 @@
const partId = removeBtn.getAttribute("data-part-id");
const recordKey = removeBtn.getAttribute("data-recordkey");
const rowId = removeBtn.getAttribute("data-row-id");
const index = removeBtn.getAttribute("data-index");
deleteAnalysisAssociation(partId, recordKey, function () {
const stillUsed = Object.keys(analysisAssignedState).some(
function (pid) {
deleteAnalysisAssociation(
partId,
recordKey,
rowId,
index,
function () {
const stillUsed = Object.keys(
analysisAssignedState,
).some(function (pid) {
return (
Array.isArray(analysisAssignedState[pid]) &&
analysisAssignedState[pid].some(
@@ -722,15 +750,15 @@
},
)
);
},
);
});
if (!stillUsed) {
delete analysisSelectedState[recordKey];
}
if (!stillUsed) {
delete analysisSelectedState[recordKey];
}
syncSelectedAnalysisRows();
});
syncSelectedAnalysisRows();
},
);
return;
}
@@ -751,17 +779,6 @@
}
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;
+25 -10
View File
@@ -15,8 +15,9 @@ try {
$partId = isset($_POST['part_id']) ? (int)$_POST['part_id'] : 0;
$analysisRecordkey = trim($_POST['analysis_recordkey'] ?? '');
$rowId = isset($_POST['row_id']) && $_POST['row_id'] !== '' ? (int)$_POST['row_id'] : 0;
if ($partId <= 0 || $analysisRecordkey === '') {
if ($partId <= 0 || ($analysisRecordkey === '' && $rowId <= 0)) {
http_response_code(400);
echo json_encode(['success' => false, 'message' => 'Missing required data']);
exit;
@@ -25,15 +26,29 @@ try {
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
$stmt = $pdo->prepare("
DELETE FROM identification_parts_analyses
WHERE part_id = :part_id
AND analysis_recordkey = :analysis_recordkey
");
$stmt->execute([
':part_id' => $partId,
':analysis_recordkey' => $analysisRecordkey,
]);
if ($rowId > 0) {
$stmt = $pdo->prepare("
DELETE FROM identification_parts_analyses
WHERE id = :id
AND part_id = :part_id
LIMIT 1
");
$stmt->execute([
':id' => $rowId,
':part_id' => $partId,
]);
} else {
$stmt = $pdo->prepare("
DELETE FROM identification_parts_analyses
WHERE part_id = :part_id
AND analysis_recordkey = :analysis_recordkey
LIMIT 1
");
$stmt->execute([
':part_id' => $partId,
':analysis_recordkey' => $analysisRecordkey,
]);
}
echo json_encode([
'success' => true,
+2 -10
View File
@@ -54,15 +54,6 @@ try {
:is_web_selectable,
:is_accredited
)
ON DUPLICATE KEY UPDATE
analysis_name = VALUES(analysis_name),
analysis_method = VALUES(analysis_method),
analysis_level = VALUES(analysis_level),
is_web_selectable = VALUES(is_web_selectable),
is_accredited = VALUES(is_accredited),
iddatadb = VALUES(iddatadb),
idmatrice = VALUES(idmatrice),
updated_at = CURRENT_TIMESTAMP
");
$stmt->execute([
@@ -79,7 +70,8 @@ try {
echo json_encode([
'success' => true,
'message' => 'Association saved'
'message' => 'Association saved',
'id' => (int)$pdo->lastInsertId()
]);
} catch (Throwable $e) {
http_response_code(500);