git displaysets working in viva view

This commit is contained in:
Ross
2025-07-21 10:51:34 +01:00
parent 5187885c3b
commit f5258d7e6f
7 changed files with 117 additions and 61 deletions
+5
View File
@@ -1152,6 +1152,11 @@ class CaseDisplaySet(models.Model, AuthorMixin):
structures = models.ManyToManyField(Structure, blank=True)
conditions = models.ManyToManyField(Condition, blank=True)
def viewerstate_string(self):
return json.dumps(self.viewerstate) if self.viewerstate else "{}"
def annotations_string(self):
return json.dumps(self.annotations) if self.annotations else "{}"
class CaseDetail(models.Model):
+46 -50
View File
@@ -11,6 +11,7 @@
<br>
<button type="button"
class="btn btn-outline-primary btn-sm select-series-btn"
style="display: none;"
data-series-id="{{series.pk}}">
Select
</button>
@@ -238,56 +239,51 @@
{% endif %}
<!-- Series Findings -->
<h5>Series Findings</h5>
{% if case.series.all %}
{% for series in case.get_ordered_series %}
{% for finding in series.findings.all %}
<div class="finding-box" id="finding-box-{{ finding.pk }}" data-series="{{ series.pk }}"
_="on mouseenter
toggle .highlight-series
on #series-block-{{ series.pk }}
until mouseleave"
>
<span>
<a href="{{series.get_absolute_url}}?show_finding={{finding.pk}}">
<button class="btn btn-primary btn-sm">View</button>
</a>
<button class="btn btn-secondary btn-sm view-finding-modal" data-finding-id="{{ finding.pk }}" data-series-id="{{ series.pk }}">
View in Modal
</button>
</span>
{% if finding.findings.all %}
<span>
Findings: {% for f in finding.findings.all %}
{{f.get_link}},&nbsp;
{% endfor %}
</span>
{% endif %}
{% if finding.conditions.all %}
<span>
Conditions: {% for c in finding.conditions.all %}
{{c.get_link}},&nbsp;
{% endfor %}
</span>
{% endif %}
{% if finding.structures.all %}
<span>
Structure: {% for s in finding.structures.all %}
{{s.get_link}},&nbsp;
{% endfor %}
</span>
{% endif %}
{% if finding.description %}
<span>
Description: {{finding.description}}
</span>
{% endif %}
</div>
{% endfor %}
{% endfor %}
{% else %}
No series associated with case.
{% endif %}
<h5>Series Findings</h5>
{% if case.ordered_series %}
{% for series in case.ordered_series %}
{% for finding in series.findings.all %}
<div class="finding-box" id="finding-box-{{ finding.pk }}" data-series="{{ series.pk }}">
<span>
<a href="{{series.get_absolute_url}}?show_finding={{finding.pk}}">
<button class="btn btn-primary btn-sm">View</button>
</a>
<button class="btn btn-secondary btn-sm view-finding-modal" data-finding-id="{{ finding.pk }}" data-series-id="{{ series.pk }}">
View in Modal
</button>
</span>
{% if finding.findings %}
<span>
Findings: {% for f in finding.findings.all %}
{{f.get_link}},&nbsp;
{% endfor %}
</span>
{% endif %}
{% if finding.conditions %}
<span>
Conditions: {% for c in finding.conditions.all %}
{{c.get_link}},&nbsp;
{% endfor %}
</span>
{% endif %}
{% if finding.structures %}
<span>
Structure: {% for s in finding.structures.all %}
{{s.get_link}},&nbsp;
{% endfor %}
</span>
{% endif %}
{% if finding.description %}
<span>
Description: {{finding.description}}
</span>
{% endif %}
</div>
{% endfor %}
{% endfor %}
{% else %}
No series associated with case.
{% endif %}
<!-- Case Display Sets -->
<h5 class="mt-3">Case Display Sets</h5>
+2 -1
View File
@@ -58,7 +58,8 @@
var form = evt.target;
console.log("Form:", form);
console.log("Form matches:", form.matches("form[hx-post*='{% url 'atlas:case_displaysets_add' case.pk %}']"));
if (form && form.matches("form[hx-post*='{% url 'atlas:case_displaysets_add' case.pk %}']")) {
console.log("Form matches:", form.matches("form[hx-post*='display_sets/edit']"));
if (form && (form.matches("form[hx-post*='{% url 'atlas:case_displaysets_add' case.pk %}']") ||form.matches("form[hx-post*='display_sets/edit']" ))) {
// Set hidden fields from JS functions
var viewerState = window.exportViewerState_main_viewer ? window.exportViewerState_main_viewer() : "{}";
var annotations = window.exportAnnotations_main_viewer ? window.exportAnnotations_main_viewer() : "{}";
+51 -2
View File
@@ -62,6 +62,34 @@
{% endfor %}
</details>
</div>
{% if case.display_sets.all %}
<details class="displayset-detail"><summary>Display Sets:</summary>
{% for ds in case.display_sets.all %}
<div class="displayset-block">
<span>
<b>{{ ds.name }}</b>
{% if ds.description %}
<span class="text-muted">({{ ds.description }})</span>
{% endif %}
<button class="open-displayset no-padding text-secondary border-secondary"
data-type="displayset"
data-displayset="{{ ds.pk }}"
data-case="{{ case.pk }}"
data-title="{{ ds.name }}"
data-casejson='{{case.get_viva_details_json}}'
data-images='{{case.get_series_images_nested}}'
data-viewerstate={{ds.viewerstate_string}}
data-annotations='{{ds.annotations_string}}'
>
Load Display Set
</button>
</span>
</div>
{% empty %}
<span class="text-muted">No display sets for this case.</span>
{% endfor %}
</details>
{% endif %}
</div>
</li>
@@ -162,10 +190,31 @@
$("#current-case-discussion").html("<span class='title'>Discussion:</span> "+case_details['discussion']);
$("#current-case-report").html("<span class='title'>Report:</span> "+case_details['report']);
bc.postMessage({"type": "open",
"case" : c.dataset.case, "images": c.dataset.images,
bc.postMessage({"type": "open",
"case" : c.dataset.case, "images": c.dataset.images,
"viewerstate": viewerstate
});
});
$('.open-displayset').click(function() {
let c = this;
console.log('clicked local', c)
console.log('open local', c.dataset.case)
case_details = 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> "+case_details['history']);
$("#current-case-discussion").html("<span class='title'>Discussion:</span> "+case_details['discussion']);
$("#current-case-report").html("<span class='title'>Report:</span> "+case_details['report']);
bc.postMessage({"type": "open",
"case" : c.dataset.case, "images": c.dataset.images,
"viewerstate": viewerstate,
"annotations": annotations
});
});
$('.open-series-local').click(function() {
@@ -16,7 +16,7 @@
<a href="{{ prev_case.get_absolute_url }}">{{ case.title }}</a>
</li>
{% partial case-series %}
{% include "atlas/case_display_block.html#case-series" %}
{% endfor %}
</ul>
{% else %}
+9 -3
View File
@@ -40,11 +40,8 @@
console.log(event);
if (event.data.type == "open") {
document.getElementById("awating-load").style.display = "none";
console.log("open, images: ", event.data.images);
document.getElementById("root").dataset.images = event.data.images;
console.log("viewerstate: ", event.data.viewerstate);
console.log(event.data.viewerstate == {});
if (
event.data.viewerstate &&
Object.keys(event.data.viewerstate).length > 0
@@ -53,6 +50,15 @@
} else {
delete document.getElementById("root").dataset.viewerstate;
}
console.log("Annotations:", event.data.annotations);
if (
event.data.annotations &&
Object.keys(event.data.annotations).length > 0
) {
document.getElementById("root").dataset.annotationjson = event.data.annotations;
} else {
delete document.getElementById("root").dataset.annotationjson;
}
window.mountDicomViewers();
bc.postMessage({"type": "open-complete-local"});
+3 -4
View File
@@ -313,15 +313,13 @@ def case_detail(request, pk):
"series",
queryset=Series.objects.select_related("modality", "examination", "plane", "contrast")
.prefetch_related(
Prefetch("images", queryset=SeriesImage.objects.filter(removed=False).order_by("position")),
Prefetch(
"findings",
queryset=SeriesFinding.objects.prefetch_related(
Prefetch("findings", queryset=Finding.objects.all()),
Prefetch("conditions", queryset=Condition.objects.all()),
Prefetch("structures", queryset=Structure.objects.all()),
"findings", "conditions", "structures"
)
),
Prefetch("images", queryset=SeriesImage.objects.filter(removed=False).order_by("position")),
)
),
),
@@ -340,6 +338,7 @@ def case_detail(request, pk):
)
.get(pk=pk)
)
case.ordered_series = [sd.series for sd in case.seriesdetail_set.all()]
can_edit = case.check_user_can_edit(request.user)
return render(