multiple analysis on same parts
This commit is contained in:
@@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Phinx\Migration\AbstractMigration;
|
||||||
|
|
||||||
|
final class DropUniqPartAnalysisIndex extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
$this->table('identification_parts_analyses')
|
||||||
|
->removeIndexByName('uniq_part_analysis')
|
||||||
|
->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
$this->table('identification_parts_analyses')
|
||||||
|
->addIndex(['part_id', 'analysis_recordkey'], [
|
||||||
|
'unique' => true,
|
||||||
|
'name' => 'uniq_part_analysis',
|
||||||
|
])
|
||||||
|
->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -106,8 +106,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
container.innerHTML = items
|
container.innerHTML = items
|
||||||
.map(function (item) {
|
.map(function (item, index) {
|
||||||
const recordKey = item.analysis_recordkey || "";
|
const recordKey = item.analysis_recordkey || "";
|
||||||
|
const rowId = item.id != null ? item.id : "";
|
||||||
const title = item.analysis_name || "Unnamed analysis";
|
const title = item.analysis_name || "Unnamed analysis";
|
||||||
const method = item.analysis_method || "";
|
const method = item.analysis_method || "";
|
||||||
|
|
||||||
@@ -121,6 +122,8 @@
|
|||||||
class="analysis-remove-btn"
|
class="analysis-remove-btn"
|
||||||
data-part-id="${escapeHtml(partId)}"
|
data-part-id="${escapeHtml(partId)}"
|
||||||
data-recordkey="${escapeHtml(recordKey)}"
|
data-recordkey="${escapeHtml(recordKey)}"
|
||||||
|
data-row-id="${escapeHtml(rowId)}"
|
||||||
|
data-index="${index}"
|
||||||
title="Remove analysis">×</button>
|
title="Remove analysis">×</button>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
@@ -166,19 +169,21 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function addAnalysisToLocalState(partId, payload, iddatadb, idmatrice) {
|
function addAnalysisToLocalState(
|
||||||
|
partId,
|
||||||
|
payload,
|
||||||
|
iddatadb,
|
||||||
|
idmatrice,
|
||||||
|
newId,
|
||||||
|
) {
|
||||||
const key = String(partId);
|
const key = String(partId);
|
||||||
if (!Array.isArray(analysisAssignedState[key])) {
|
if (!Array.isArray(analysisAssignedState[key])) {
|
||||||
analysisAssignedState[key] = [];
|
analysisAssignedState[key] = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const exists = analysisAssignedState[key].some(function (item) {
|
{
|
||||||
return item.analysis_recordkey === payload.analysis_recordkey;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!exists) {
|
|
||||||
analysisAssignedState[key].push({
|
analysisAssignedState[key].push({
|
||||||
id: null,
|
id: newId || null,
|
||||||
part_id: parseInt(partId, 10),
|
part_id: parseInt(partId, 10),
|
||||||
iddatadb: iddatadb || null,
|
iddatadb: iddatadb || null,
|
||||||
idmatrice: idmatrice || null,
|
idmatrice: idmatrice || null,
|
||||||
@@ -195,17 +200,24 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeAnalysisFromLocalState(partId, recordKey) {
|
function removeAnalysisFromLocalState(partId, recordKey, index) {
|
||||||
const key = String(partId);
|
const key = String(partId);
|
||||||
if (!Array.isArray(analysisAssignedState[key])) {
|
if (!Array.isArray(analysisAssignedState[key])) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
analysisAssignedState[key] = analysisAssignedState[key].filter(
|
const i = parseInt(index, 10);
|
||||||
function (item) {
|
if (!isNaN(i) && i >= 0 && i < analysisAssignedState[key].length) {
|
||||||
return item.analysis_recordkey !== recordKey;
|
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) {
|
function saveAnalysisAssociation(partId, payload, callback) {
|
||||||
@@ -237,12 +249,13 @@
|
|||||||
is_accredited: payload.is_accredited,
|
is_accredited: payload.is_accredited,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.done(function () {
|
.done(function (resp) {
|
||||||
addAnalysisToLocalState(
|
addAnalysisToLocalState(
|
||||||
partId,
|
partId,
|
||||||
payload,
|
payload,
|
||||||
iddatadb,
|
iddatadb,
|
||||||
idmatrice !== "NO_MATRIX" ? idmatrice : null,
|
idmatrice !== "NO_MATRIX" ? idmatrice : null,
|
||||||
|
resp && resp.id ? resp.id : null,
|
||||||
);
|
);
|
||||||
renderAssignedAnalysesForPart(partId);
|
renderAssignedAnalysesForPart(partId);
|
||||||
if (typeof callback === "function") callback(true);
|
if (typeof callback === "function") callback(true);
|
||||||
@@ -257,7 +270,13 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteAnalysisAssociation(partId, recordKey, callback) {
|
function deleteAnalysisAssociation(
|
||||||
|
partId,
|
||||||
|
recordKey,
|
||||||
|
rowId,
|
||||||
|
index,
|
||||||
|
callback,
|
||||||
|
) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: "delete_part_analysis.php",
|
url: "delete_part_analysis.php",
|
||||||
method: "POST",
|
method: "POST",
|
||||||
@@ -265,10 +284,11 @@
|
|||||||
data: {
|
data: {
|
||||||
part_id: partId,
|
part_id: partId,
|
||||||
analysis_recordkey: recordKey,
|
analysis_recordkey: recordKey,
|
||||||
|
row_id: rowId || "",
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.done(function () {
|
.done(function () {
|
||||||
removeAnalysisFromLocalState(partId, recordKey);
|
removeAnalysisFromLocalState(partId, recordKey, index);
|
||||||
renderAssignedAnalysesForPart(partId);
|
renderAssignedAnalysesForPart(partId);
|
||||||
if (typeof callback === "function") callback(true);
|
if (typeof callback === "function") callback(true);
|
||||||
})
|
})
|
||||||
@@ -707,10 +727,18 @@
|
|||||||
|
|
||||||
const partId = removeBtn.getAttribute("data-part-id");
|
const partId = removeBtn.getAttribute("data-part-id");
|
||||||
const recordKey = removeBtn.getAttribute("data-recordkey");
|
const recordKey = removeBtn.getAttribute("data-recordkey");
|
||||||
|
const rowId = removeBtn.getAttribute("data-row-id");
|
||||||
|
const index = removeBtn.getAttribute("data-index");
|
||||||
|
|
||||||
deleteAnalysisAssociation(partId, recordKey, function () {
|
deleteAnalysisAssociation(
|
||||||
const stillUsed = Object.keys(analysisAssignedState).some(
|
partId,
|
||||||
function (pid) {
|
recordKey,
|
||||||
|
rowId,
|
||||||
|
index,
|
||||||
|
function () {
|
||||||
|
const stillUsed = Object.keys(
|
||||||
|
analysisAssignedState,
|
||||||
|
).some(function (pid) {
|
||||||
return (
|
return (
|
||||||
Array.isArray(analysisAssignedState[pid]) &&
|
Array.isArray(analysisAssignedState[pid]) &&
|
||||||
analysisAssignedState[pid].some(
|
analysisAssignedState[pid].some(
|
||||||
@@ -722,15 +750,15 @@
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
|
||||||
if (!stillUsed) {
|
if (!stillUsed) {
|
||||||
delete analysisSelectedState[recordKey];
|
delete analysisSelectedState[recordKey];
|
||||||
}
|
}
|
||||||
|
|
||||||
syncSelectedAnalysisRows();
|
syncSelectedAnalysisRows();
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -751,17 +779,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const recordKey = payload.analysis_recordkey;
|
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 pending = selectedPartIds.length;
|
||||||
let atLeastOneSaved = false;
|
let atLeastOneSaved = false;
|
||||||
|
|||||||
@@ -15,8 +15,9 @@ try {
|
|||||||
|
|
||||||
$partId = isset($_POST['part_id']) ? (int)$_POST['part_id'] : 0;
|
$partId = isset($_POST['part_id']) ? (int)$_POST['part_id'] : 0;
|
||||||
$analysisRecordkey = trim($_POST['analysis_recordkey'] ?? '');
|
$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);
|
http_response_code(400);
|
||||||
echo json_encode(['success' => false, 'message' => 'Missing required data']);
|
echo json_encode(['success' => false, 'message' => 'Missing required data']);
|
||||||
exit;
|
exit;
|
||||||
@@ -25,15 +26,29 @@ try {
|
|||||||
$db = DBHandlerSelect::getInstance();
|
$db = DBHandlerSelect::getInstance();
|
||||||
$pdo = $db->getConnection();
|
$pdo = $db->getConnection();
|
||||||
|
|
||||||
$stmt = $pdo->prepare("
|
if ($rowId > 0) {
|
||||||
DELETE FROM identification_parts_analyses
|
$stmt = $pdo->prepare("
|
||||||
WHERE part_id = :part_id
|
DELETE FROM identification_parts_analyses
|
||||||
AND analysis_recordkey = :analysis_recordkey
|
WHERE id = :id
|
||||||
");
|
AND part_id = :part_id
|
||||||
$stmt->execute([
|
LIMIT 1
|
||||||
':part_id' => $partId,
|
");
|
||||||
':analysis_recordkey' => $analysisRecordkey,
|
$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([
|
echo json_encode([
|
||||||
'success' => true,
|
'success' => true,
|
||||||
|
|||||||
@@ -54,15 +54,6 @@ try {
|
|||||||
:is_web_selectable,
|
:is_web_selectable,
|
||||||
:is_accredited
|
: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([
|
$stmt->execute([
|
||||||
@@ -79,7 +70,8 @@ try {
|
|||||||
|
|
||||||
echo json_encode([
|
echo json_encode([
|
||||||
'success' => true,
|
'success' => true,
|
||||||
'message' => 'Association saved'
|
'message' => 'Association saved',
|
||||||
|
'id' => (int)$pdo->lastInsertId()
|
||||||
]);
|
]);
|
||||||
} catch (Throwable $e) {
|
} catch (Throwable $e) {
|
||||||
http_response_code(500);
|
http_response_code(500);
|
||||||
|
|||||||
Reference in New Issue
Block a user