fix via view page

This commit is contained in:
Ross
2026-06-01 12:05:39 +01:00
parent 74f1ad4b2c
commit 92d4ece061
3 changed files with 223 additions and 156 deletions
+148 -81
View File
@@ -34,9 +34,9 @@
<article class="card border-secondary-subtle shadow-sm case-item"
data-title="{{ case.title }}"
data-case="{{ case.pk }}"
data-casejson="{{ case.viva_details_json|escapejs }}"
data-images="{{ case.series_images_nested_json|escapejs }}"
data-viewerstate="{{ casedetail.default_viewerstate_string|escapejs }}">
data-casejson="{{ case.viva_details_json|urlencode }}"
data-images="{{ case.series_images_nested_json|urlencode }}"
data-viewerstate="{{ casedetail.default_viewerstate_string|urlencode }}">
<header class="card-header d-flex flex-wrap justify-content-between align-items-center gap-2">
<div>
<span class="badge bg-primary me-2">Case {{ forloop.counter }}</span>
@@ -119,10 +119,10 @@
data-displayset="{{ ds.pk }}"
data-case="{{ case.pk }}"
data-title="{{ ds.name }}"
data-casejson="{{ case.viva_details_json|escapejs }}"
data-images="{{ case.series_images_nested_json|escapejs }}"
data-viewerstate="{{ ds.viewerstate_string|escapejs }}"
data-annotations="{{ ds.annotations_string|escapejs }}">
data-casejson="{{ case.viva_details_json|urlencode }}"
data-images="{{ case.series_images_nested_json|urlencode }}"
data-viewerstate="{{ ds.viewerstate_string|urlencode }}"
data-annotations="{{ ds.annotations_string|urlencode }}">
Load Display Set
</button>
<button class="edit-link-displayset btn btn-outline-warning btn-sm" style="display:none;">
@@ -151,6 +151,7 @@
<div class="card border-secondary-subtle shadow-sm">
<div class="card-header"><h2 class="h5 mb-0">Current Case</h2></div>
<div class="card-body" id="case-details">
<div id="user-message" class="alert py-2" style="display:none;"></div>
<div id="loading-case" class="alert alert-warning py-2" style="display:none;">Waiting for case to load in linked window.</div>
<div id="current-case-title" class="mb-2">None</div>
<div id="current-case-series" class="mb-2"></div>
@@ -171,8 +172,42 @@
<script type="text/javascript">
var win2 = false;
let editMode = false;
let viewerConnected = false;
$(document).ready(function() {
const showUserMessage = function(message, level = 'warning') {
const $msg = $('#user-message');
$msg
.removeClass('alert-warning alert-danger alert-success alert-info')
.addClass('alert-' + level)
.text(message)
.show();
};
const clearUserMessage = function() {
$('#user-message').hide().text('');
};
const parseEncodedJson = function(raw, label) {
if (!raw) {
return {};
}
try {
return JSON.parse(decodeURIComponent(raw));
} catch (err) {
throw new Error('Unable to parse ' + label + ' payload.');
}
};
const ensureViewerWindowReady = function() {
if (!win2 || win2.closed) {
showUserMessage('Viewer is not open. Click "Open Viewer Local" before loading a case or series.', 'warning');
return false;
}
clearUserMessage();
return true;
};
// Edit mode toggle
$('#toggle-edit-mode').click(function() {
editMode = !editMode;
@@ -196,8 +231,10 @@
console.log("message received");
console.log(event);
if (event.data.type == "open-complete-local") {
viewerConnected = true;
$("#loading-case").hide();
$("#open-viewer-local").removeClass("flash-button");
clearUserMessage();
//bc.postMessage({"type": "open-complete-local"});
}
};
@@ -209,104 +246,127 @@
$('#viewer').attr('src', url)
});
$('.open-case-local').click(function() {
let c = this.closest(".case-item");
console.log('clicked local', c)
console.log('open local', c.dataset.case)
casedetails = JSON.parse(c.dataset.casejson);
let viewerstate = JSON.parse(c.dataset.viewerstate) || {};
$('#loading-case').show()
$("#open-viewer-local").addClass("flash-button");
$('#current-case-title').html("<span class='title'>Case:</span> "+c.dataset.title);
$("#current-case-history").html("<span class='title'>History:</span> "+casedetails['history']);
$("#current-case-discussion").html("<span class='title'>Discussion:</span> "+casedetails['discussion']);
$("#current-case-report").html("<span class='title'>Report:</span> "+casedetails['report']);
bc.postMessage({"type": "open",
"case" : c.dataset.case, "images": c.dataset.images,
"viewerstate": viewerstate
});
// Inject the per-case question snippet into the current case panel
try {
if (!ensureViewerWindowReady()) {
return;
}
let c = this.closest(".case-item");
console.log('clicked local', c)
console.log('open local', c.dataset.case)
casedetails = parseEncodedJson(c.dataset.casejson, 'case details');
let viewerstate = parseEncodedJson(c.dataset.viewerstate, 'viewer state') || {};
let images = decodeURIComponent(c.dataset.images || '[]');
$('#loading-case').show()
$("#open-viewer-local").addClass("flash-button");
$('#current-case-title').html("<span class='title'>Case:</span> "+c.dataset.title);
$("#current-case-history").html("<span class='title'>History:</span> "+(casedetails['history'] || ''));
$("#current-case-discussion").html("<span class='title'>Discussion:</span> "+(casedetails['discussion'] || ''));
$("#current-case-report").html("<span class='title'>Report:</span> "+(casedetails['report'] || ''));
bc.postMessage({"type": "open",
"case" : c.dataset.case, "images": images,
"viewerstate": viewerstate
});
// Inject the per-case question snippet into the current case panel
var snippet = $(c).find('.question-block-snippet').html();
$('#current-case-questions').html(snippet || '');
} catch (e) {
console.warn('Unable to inject question snippet', e);
console.error('Case load failed', e);
showUserMessage('Case load failed: ' + (e.message || 'Unexpected error while parsing case data.'), 'danger');
}
});
$('.open-displayset').click(function() {
let c = this;
console.log('clicked local', c)
console.log('open local', c.dataset.case)
casedetails = JSON.parse(c.dataset.casejson);
let viewerstate = JSON.parse(c.dataset.viewerstate) || {};
let annotations = JSON.parse(c.dataset.annotations) || {};
$('#loading-case').show()
$("#open-viewer-local").addClass("flash-button");
$('#current-case-title').html("<span class='title'>Case:</span> "+c.dataset.title);
$("#current-case-history").html("<span class='title'>History:</span> "+casedetails['history']);
$("#current-case-discussion").html("<span class='title'>Discussion:</span> "+casedetails['discussion']);
$("#current-case-report").html("<span class='title'>Report:</span> "+casedetails['report']);
bc.postMessage({"type": "open",
"case" : c.dataset.case, "images": c.dataset.images,
"viewerstate": viewerstate,
"annotations": annotations
});
// Inject the per-case question snippet
try {
if (!ensureViewerWindowReady()) {
return;
}
let c = this;
console.log('clicked local', c)
console.log('open local', c.dataset.case)
casedetails = parseEncodedJson(c.dataset.casejson, 'display set case details');
let viewerstate = parseEncodedJson(c.dataset.viewerstate, 'display set viewer state') || {};
let annotations = parseEncodedJson(c.dataset.annotations, 'display set annotations') || {};
let images = decodeURIComponent(c.dataset.images || '[]');
$('#loading-case').show()
$("#open-viewer-local").addClass("flash-button");
$('#current-case-title').html("<span class='title'>Case:</span> "+c.dataset.title);
$("#current-case-history").html("<span class='title'>History:</span> "+(casedetails['history'] || ''));
$("#current-case-discussion").html("<span class='title'>Discussion:</span> "+(casedetails['discussion'] || ''));
$("#current-case-report").html("<span class='title'>Report:</span> "+(casedetails['report'] || ''));
bc.postMessage({"type": "open",
"case" : c.dataset.case, "images": images,
"viewerstate": viewerstate,
"annotations": annotations
});
// Inject the per-case question snippet
var caseItem = $(this).closest('.case-item');
var snippet = caseItem.find('.question-block-snippet').html();
$('#current-case-questions').html(snippet || '');
} catch (e) {
console.warn('Unable to inject question snippet for displayset', e);
console.error('Display set load failed', e);
showUserMessage('Display set load failed: ' + (e.message || 'Unexpected error while parsing display set data.'), 'danger');
}
});
$('.open-series-local').click(function() {
let c = $(this).closest(".case-item")[0];
let seriesNumber = $(this).data('series');
let seriesPk = $(this).data('target');
let caseDetails = JSON.parse(c.dataset.casejson);
let images = JSON.parse(c.dataset.images)[seriesNumber - 1] || [];
$('#loading-case').show();
$("#open-viewer-local").addClass("flash-button");
$('#current-case-title').html("<span class='title'>Case:</span> " + c.dataset.title);
$('#current-case-series').html("<span class='title'>Series:</span> " + seriesNumber);
$("#current-case-history").html("<span class='title'>History:</span> " + caseDetails['history']);
$("#current-case-discussion").html("<span class='title'>Discussion:</span> " + caseDetails['discussion']);
$("#current-case-report").html("<span class='title'>Report:</span> " + caseDetails['report']);
// Send only the images for this series
bc.postMessage({
"type": "open",
"case": c.dataset.case,
"series": seriesPk,
"images": JSON.stringify(images),
});
// Inject the per-case question snippet
try {
if (!ensureViewerWindowReady()) {
return;
}
let c = $(this).closest(".case-item")[0];
let seriesNumber = $(this).data('series');
let seriesPk = $(this).data('target');
let caseDetails = parseEncodedJson(c.dataset.casejson, 'series case details');
let allSeriesImages = parseEncodedJson(c.dataset.images, 'series images');
let images = allSeriesImages[seriesNumber - 1] || [];
$('#loading-case').show();
$("#open-viewer-local").addClass("flash-button");
$('#current-case-title').html("<span class='title'>Case:</span> " + c.dataset.title);
$('#current-case-series').html("<span class='title'>Series:</span> " + seriesNumber);
$("#current-case-history").html("<span class='title'>History:</span> " + (caseDetails['history'] || ''));
$("#current-case-discussion").html("<span class='title'>Discussion:</span> " + (caseDetails['discussion'] || ''));
$("#current-case-report").html("<span class='title'>Report:</span> " + (caseDetails['report'] || ''));
// Send only the images for this series
bc.postMessage({
"type": "open",
"case": c.dataset.case,
"series": seriesPk,
"images": JSON.stringify(images),
});
// Inject the per-case question snippet
var snippet = $(c).find('.question-block-snippet').html();
$('#current-case-questions').html(snippet || '');
} catch (e) {
console.warn('Unable to inject question snippet for series', e);
console.error('Series load failed', e);
showUserMessage('Series load failed: ' + (e.message || 'Unexpected error while parsing series data.'), 'danger');
}
});
// Load resource into linked viewer
$('.open-resource').click(function() {
var src = $(this).data('src');
var title = $(this).data('title') || 'Resource';
$('#loading-case').show();
$("#open-viewer-local").addClass("flash-button");
$('#current-case-title').html("<span class='title'>Resource:</span> "+title);
$('#current-case-history').html('');
$('#current-case-discussion').html('');
$('#current-case-report').html('');
try {
if (!ensureViewerWindowReady()) {
return;
}
var src = $(this).data('src');
var title = $(this).data('title') || 'Resource';
$('#loading-case').show();
$("#open-viewer-local").addClass("flash-button");
$('#current-case-title').html("<span class='title'>Resource:</span> "+title);
$('#current-case-history').html('');
$('#current-case-discussion').html('');
$('#current-case-report').html('');
bc.postMessage({"type": "open", "url": src});
bc.postMessage({"type": "open", "url": src});
} catch (e) {
console.error('Resource load failed', e);
showUserMessage('Resource load failed: ' + (e.message || 'Unexpected error.'), 'danger');
}
});
$('.send-message').click(function() {
var url = $(this).data('target');
@@ -314,7 +374,13 @@
})
$('#open-viewer-local').click(function() {
$("#open-viewer-local").removeClass("flash-button");
openSecondaryWindow("{% url 'atlas:collection_viewer_local_progressive' %}");
viewerConnected = false;
const opened = openSecondaryWindow("{% url 'atlas:collection_viewer_local_progressive' %}");
if (!opened) {
showUserMessage('Unable to open viewer window. Please allow pop-ups for this site and try again.', 'danger');
return;
}
showUserMessage('Viewer window opened. Load a case to begin. If nothing appears, check pop-up blockers and re-open the viewer.', 'info');
//bc.postMessage(url);
})
$('#view-series').click(function() {
@@ -326,11 +392,12 @@
});
function openSecondaryWindow(url) {
//return win2 = window.open(url,'secondary','width=300,height=100');
return win2 = window.open(
win2 = window.open(
url,
'secondary',
'toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=1200,height=800'
);
return win2;
}
</script>
+10 -10
View File
@@ -61,16 +61,16 @@
<p>To do so you will have to first export the files from the PACs system.</p>
<p>Once uploaded the series will be available to be imported into cases
<h2>Cases</h2>
<h3>Ordering dicoms within a series</h3>
<p>Depending on how dicoms are exported images within a stack may appear in the wrong order. This is apparent when viewing the stacks/series as jumping of images.</p>
<p>In most cases this can be fixed by re-ordering based on series metadata (usually slice location).</p>
<p>It is possible to reorder all the stacks in a case at once, or to reorder individual stacks.</p>
<h4>Reorder all stacks in a case</h4>
<p>Go to the case page, click "Manage Series" then "Order dicoms by slice location". This will reorder all the stacks in the case based on slice location.</p>
<h4>Reorder individual stacks</h4>
<p>More ordering options (if the above does not work) are available on the series page.</p>
<p>These can be accessed by opening the "Series info" section and selecting the appropriate button.</p>
<h2>Cases</h2>
<h3>Ordering dicoms within a series</h3>
<p>Depending on how dicoms are exported images within a stack may appear in the wrong order. This is apparent when viewing the stacks/series as jumping of images.</p>
<p>In most cases this can be fixed by re-ordering based on series metadata (usually slice location).</p>
<p>It is possible to reorder all the stacks in a case at once, or to reorder individual stacks.</p>
<h4>Reorder all stacks in a case</h4>
<p>Go to the case page, click "Manage Series" then "Order dicoms by slice location". This will reorder all the stacks in the case based on slice location.</p>
<h4>Reorder individual stacks</h4>
<p>More ordering options (if the above does not work) are available on the series page.</p>
<p>These can be accessed by opening the "Series info" section and selecting the appropriate button.</p>
File diff suppressed because one or more lines are too long