feat: Enhance duplicate series handling with deselect functionality and UI updates
This commit is contained in:
@@ -67,7 +67,12 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="selection-summary" class="alert alert-secondary py-2 mb-3 d-none"></div>
|
<div id="selection-summary" class="alert alert-secondary py-2 mb-3 d-none"></div>
|
||||||
<div id="duplicate-progress" class="small text-muted mb-2"></div>
|
<div class="d-flex flex-wrap align-items-center gap-2 mb-2">
|
||||||
|
<div id="duplicate-progress" class="small text-muted"></div>
|
||||||
|
<button type="button" id="deselect-duplicates" class="btn btn-sm btn-outline-danger d-none">
|
||||||
|
<i class="bi bi-x-circle me-1"></i>Deselect all duplicates
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="alert alert-warning d-none anon-alert" role="alert">
|
<div class="alert alert-warning d-none anon-alert" role="alert">
|
||||||
<p class="mb-2">Potential anonymisation issues were detected. Flagged series are highlighted below.</p>
|
<p class="mb-2">Potential anonymisation issues were detected. Flagged series are highlighted below.</p>
|
||||||
@@ -431,6 +436,7 @@
|
|||||||
function updateUploadButtonState() {
|
function updateUploadButtonState() {
|
||||||
const uploadButton = document.getElementById("uploadButton");
|
const uploadButton = document.getElementById("uploadButton");
|
||||||
const anonAlert = document.querySelector(".anon-alert");
|
const anonAlert = document.querySelector(".anon-alert");
|
||||||
|
const deselectDuplicatesBtn = document.getElementById("deselect-duplicates");
|
||||||
const hasSelected = window.uploadPreview.records.some(r => r.include);
|
const hasSelected = window.uploadPreview.records.some(r => r.include);
|
||||||
const hasWarnings = hasAnonymisationWarnings();
|
const hasWarnings = hasAnonymisationWarnings();
|
||||||
const hasDuplicates = window.uploadPreview.records.some(r => r.include && r.duplicate);
|
const hasDuplicates = window.uploadPreview.records.some(r => r.include && r.duplicate);
|
||||||
@@ -439,6 +445,9 @@
|
|||||||
window.uploadPreview.records.some((r) => r.include && !r.duplicateChecked);
|
window.uploadPreview.records.some((r) => r.include && !r.duplicateChecked);
|
||||||
|
|
||||||
renderAnonymisationIssueSummary();
|
renderAnonymisationIssueSummary();
|
||||||
|
if (deselectDuplicatesBtn) {
|
||||||
|
deselectDuplicatesBtn.classList.toggle("d-none", !hasDuplicates);
|
||||||
|
}
|
||||||
|
|
||||||
if (!hasSelected) {
|
if (!hasSelected) {
|
||||||
uploadButton.disabled = true;
|
uploadButton.disabled = true;
|
||||||
@@ -483,14 +492,36 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getSeriesStatusClass(series) {
|
function getSeriesStatusClass(series) {
|
||||||
|
const includeCount = series.files.filter(f => f.include).length;
|
||||||
|
if (!includeCount) return "series-card excluded";
|
||||||
|
|
||||||
const hasTagWarnings = series.files.some(f => f.tagWarnings.length > 0);
|
const hasTagWarnings = series.files.some(f => f.tagWarnings.length > 0);
|
||||||
const hasOcrWarnings = series.files.some(f => f.ocrWarning);
|
const hasOcrWarnings = series.files.some(f => f.ocrWarning);
|
||||||
const hasDuplicates = series.files.some(f => f.duplicate);
|
const hasDuplicates = series.files.some(f => f.include && f.duplicate);
|
||||||
if (hasTagWarnings || hasOcrWarnings) return "series-card warning";
|
if (hasTagWarnings || hasOcrWarnings) return "series-card warning";
|
||||||
if (hasDuplicates) return "series-card duplicate";
|
if (hasDuplicates) return "series-card duplicate";
|
||||||
return "series-card";
|
return "series-card";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function deselectDuplicateSeries() {
|
||||||
|
const duplicateSeriesUids = new Set(
|
||||||
|
window.uploadPreview.records
|
||||||
|
.filter((record) => record.include && record.duplicate)
|
||||||
|
.map((record) => record.seriesUid)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!duplicateSeriesUids.size) {
|
||||||
|
toastr.info("No selected duplicate series to deselect.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
duplicateSeriesUids.forEach((seriesUid) => applyIncludeToSeries(seriesUid, false));
|
||||||
|
window.uploadPreview.forceAnonymisationOverride = false;
|
||||||
|
scheduleDuplicateCheck();
|
||||||
|
renderGroupedPreview();
|
||||||
|
toastr.info(`Deselected ${duplicateSeriesUids.size} duplicate series.`);
|
||||||
|
}
|
||||||
|
|
||||||
function renderGroupedPreview() {
|
function renderGroupedPreview() {
|
||||||
const groupedRoot = document.getElementById("preupload-grouped");
|
const groupedRoot = document.getElementById("preupload-grouped");
|
||||||
const grouped = window.uploadPreview.grouped;
|
const grouped = window.uploadPreview.grouped;
|
||||||
@@ -1264,6 +1295,10 @@
|
|||||||
renderGroupedPreview();
|
renderGroupedPreview();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
bindIfExists("deselect-duplicates", "click", () => {
|
||||||
|
deselectDuplicateSeries();
|
||||||
|
});
|
||||||
|
|
||||||
bindIfExists("show-thumbnails", "change", () => {
|
bindIfExists("show-thumbnails", "change", () => {
|
||||||
renderGroupedPreview();
|
renderGroupedPreview();
|
||||||
});
|
});
|
||||||
@@ -1339,6 +1374,13 @@
|
|||||||
background: rgba(220, 53, 69, 0.08);
|
background: rgba(220, 53, 69, 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.series-card.excluded {
|
||||||
|
border-color: rgba(148, 163, 184, 0.35);
|
||||||
|
background: rgba(148, 163, 184, 0.08);
|
||||||
|
opacity: 0.55;
|
||||||
|
filter: grayscale(0.25);
|
||||||
|
}
|
||||||
|
|
||||||
.series-header {
|
.series-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|||||||
Reference in New Issue
Block a user