.
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
{% for author in authors %}
|
{% for author in authors %}
|
||||||
<p>Author: <a href="{% url 'atlas:author_detail' pk=author.pk %}">{{author.username}}</a>, </p>
|
<p>Author: <a href="{% url 'atlas:author_detail' pk=author.pk %}">{{author.username}}</a>, </p>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
{% block title %}
|
{% block title %}
|
||||||
Atlas
|
Atlas
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block css %}
|
{% block css %}
|
||||||
@@ -15,16 +15,16 @@ Atlas
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block navigation %}
|
{% block navigation %}
|
||||||
Atlas:
|
Atlas:
|
||||||
{% if request.user.is_authenticated %}
|
{% if request.user.is_authenticated %}
|
||||||
<a href="{% url 'atlas:case_view' %}">Cases</a> /
|
<a href="{% url 'atlas:case_view' %}">Cases</a> /
|
||||||
<a href="{% url 'atlas:series_view' %}">Series</a> /
|
<a href="{% url 'atlas:series_view' %}">Series</a> /
|
||||||
<a href="{% url 'atlas:collection_view' %}">Collections</a> /
|
<a href="{% url 'atlas:collection_view' %}">Collections</a> /
|
||||||
<a href="{% url 'atlas:categories_list' %}">Categories</a> /
|
<a href="{% url 'atlas:categories_list' %}">Categories</a> /
|
||||||
<a href="{% url 'atlas:case_create' %}" title="Create a new atlas case">Create Case</a> /
|
<a href="{% url 'atlas:case_create' %}" title="Create a new atlas case">Create Case</a> /
|
||||||
<a href="{% url 'atlas:series_create' %}" title="Create a new image series">Create Series</a>
|
<a href="{% url 'atlas:series_create' %}" title="Create a new image series">Create Series</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% comment %} </br>
|
{% comment %} </br>
|
||||||
Questions by:
|
Questions by:
|
||||||
<span id="authors-link"><a href="{% url 'atlas:author_list' %}">author</a></span> {% endcomment %}
|
<span id="authors-link"><a href="{% url 'atlas:author_list' %}">author</a></span> {% endcomment %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -4,21 +4,21 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="floating-header">
|
<div class="floating-header">
|
||||||
<a href="{% url 'atlas:case_update' pk=case.pk %}" title="Edit the Case">Edit</a>
|
<a href="{% url 'atlas:case_update' pk=case.pk %}" title="Edit the Case">Edit</a>
|
||||||
<a href="{% url 'atlas:case_clone' pk=case.pk %}"
|
<a href="{% url 'atlas:case_clone' pk=case.pk %}"
|
||||||
title="Clone the Case (duplicate everything but the images)">Clone</a>
|
title="Clone the Case (duplicate everything but the images)">Clone</a>
|
||||||
<a href="{% url 'atlas:case_delete' pk=case.pk %}" title="Delete the Case">Delete</a>
|
<a href="{% url 'atlas:case_delete' pk=case.pk %}" title="Delete the Case">Delete</a>
|
||||||
<a href="#"
|
<a href="#"
|
||||||
onclick="return window.create_popup_window('{% url 'feedback_create' question_type='atlas' pk=case.pk %}')"> Add
|
onclick="return window.create_popup_window('{% url 'feedback_create' question_type='atlas' pk=case.pk %}')"> Add
|
||||||
Note</a>
|
Note</a>
|
||||||
{% if request.user.is_superuser %}
|
{% if request.user.is_superuser %}
|
||||||
<a href="{% url 'admin:atlas_case_change' case.id %}" title="Edit the Case using the admin interface">Admin Edit</a>
|
<a href="{% url 'admin:atlas_case_change' case.id %}" title="Edit the Case using the admin interface">Admin Edit</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% include 'atlas/case_display_block.html' %}
|
{% include 'atlas/case_display_block.html' %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block js %}
|
{% block js %}
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -111,8 +111,8 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</p>
|
</p>
|
||||||
<p class="pre-whitespace"><b>Previous case:</b> {{ case.previous_case }}</p>
|
<p class="pre-whitespace"><b>Previous case:</b> {{ case.previous_case }}</p>
|
||||||
<p class="pre-whitespace"><b>Next case:</b> {{ case.next_case }}</p>
|
<p class="pre-whitespace"><b>Next case:</b> {{ case.next_case }}</p>
|
||||||
<div>
|
<div>
|
||||||
{% include 'question_notes.html' %}
|
{% include 'question_notes.html' %}
|
||||||
|
|
||||||
|
|||||||
@@ -4,95 +4,95 @@
|
|||||||
{% block css %}
|
{% block css %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block js %}
|
{% block js %}
|
||||||
<!--<script type="text/javascript" src="/admin/jsi18n/"></script>-->
|
<!--<script type="text/javascript" src="/admin/jsi18n/"></script>-->
|
||||||
{{form.media}}
|
{{form.media}}
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
function showEditPopup(url) {
|
function showEditPopup(url) {
|
||||||
var win = window.open(url, "Edit",
|
var win = window.open(url, "Edit",
|
||||||
'height=500,width=800,resizable=yes,scrollbars=yes');
|
'height=500,width=800,resizable=yes,scrollbars=yes');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
function showAddPopup(triggeringLink) {
|
function showAddPopup(triggeringLink) {
|
||||||
var name = triggeringLink.id.replace(/^add_/, '');
|
var name = triggeringLink.id.replace(/^add_/, '');
|
||||||
href = triggeringLink.href;
|
href = triggeringLink.href;
|
||||||
var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes');
|
var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes');
|
||||||
win.focus();
|
win.focus();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
function closePopup(win, newID, newRepr, id) {
|
function closePopup(win, newID, newRepr, id) {
|
||||||
console.log(id)
|
console.log(id)
|
||||||
$(id + "_to").append('<option value=' + newID + ' title=' + newRepr + ' >' + newRepr + '</option>')
|
$(id + "_to").append('<option value=' + newID + ' title=' + newRepr + ' >' + newRepr + '</option>')
|
||||||
win.close();
|
win.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function add_series_input_form() {
|
function add_series_input_form() {
|
||||||
var form_idx = $('#id_Case_series-TOTAL_FORMS').val();
|
var form_idx = $('#id_Case_series-TOTAL_FORMS').val();
|
||||||
$('#series_formset').append($('#empty_series_form').html().replace(/__prefix__/g, form_idx));
|
$('#series_formset').append($('#empty_series_form').html().replace(/__prefix__/g, form_idx));
|
||||||
$('#id_Case_series-TOTAL_FORMS').val(parseInt(form_idx) + 1);
|
$('#id_Case_series-TOTAL_FORMS').val(parseInt(form_idx) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function add_differential_input_form() {
|
function add_differential_input_form() {
|
||||||
var form_idx = $('#id_differentialcase-TOTAL_FORMS').val();
|
var form_idx = $('#id_differentialcase-TOTAL_FORMS').val();
|
||||||
$('#casedifferential_formset').append($('#empty_casedifferential_form').html().replace(/__prefix__/g, form_idx));
|
$('#casedifferential_formset').append($('#empty_casedifferential_form').html().replace(/__prefix__/g, form_idx));
|
||||||
$('#id_differentialcase-TOTAL_FORMS').val(parseInt(form_idx) + 1);
|
$('#id_differentialcase-TOTAL_FORMS').val(parseInt(form_idx) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
$('#add_more_series').click(() => { add_series_input_form() });
|
$('#add_more_series').click(() => { add_series_input_form() });
|
||||||
$('#add_more_differential').click(() => { add_differential_input_form() });
|
$('#add_more_differential').click(() => { add_differential_input_form() });
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- {{ form.media }} -->
|
<!-- {{ form.media }} -->
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h2>Submit Case</h2>
|
<h2>Submit Case</h2>
|
||||||
Use this form to create a atlas case. Existing associated image sets can be added using this form.
|
Use this form to create a atlas case. Existing associated image sets can be added using this form.
|
||||||
<form action="" method="post" enctype="multipart/form-data" id="atlas-form">
|
<form action="" method="post" enctype="multipart/form-data" id="atlas-form">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
{{ form.as_table }}
|
{{ form.as_table }}
|
||||||
</table>
|
</table>
|
||||||
<h3>Series:</h3>
|
<h3>Series:</h3>
|
||||||
Add image sets here. These can only be added once created (they can also be added to cases on creation).
|
Add image sets here. These can only be added once created (they can also be added to cases on creation).
|
||||||
<input type="button" value="Add More Series" id="add_more_series">
|
<input type="button" value="Add More Series" id="add_more_series">
|
||||||
<div id="series_formset">
|
<div id="series_formset">
|
||||||
{% for form in series_formset %}
|
{% for form in series_formset %}
|
||||||
<ul class="no-error series-formset">
|
<ul class="no-error series-formset">
|
||||||
{{form.non_field_errors}}
|
{{form.non_field_errors}}
|
||||||
{{form.errors}}
|
{{form.errors}}
|
||||||
{{ form.as_ul }}
|
{{ form.as_ul }}
|
||||||
|
</ul>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{{ series_formset.management_form }}
|
||||||
|
<h3>Differential:</h3>
|
||||||
|
Add differential here.
|
||||||
|
<input type="button" value="Add Another Differential" id="add_more_differential">
|
||||||
|
<div id="casedifferential_formset">
|
||||||
|
{% for form in casedifferential_formset %}
|
||||||
|
<ul class="no-error casedifferential_formset">
|
||||||
|
{{form.non_field_errors}}
|
||||||
|
{{form.errors}}
|
||||||
|
{{ form.as_ul }}
|
||||||
|
</ul>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{{ casedifferential_formset.management_form }}
|
||||||
|
<input type="submit" class="submit-button" value="Submit" name="submit">
|
||||||
|
</form>
|
||||||
|
<div id="empty_series_form" style="display:none">
|
||||||
|
<ul class='no_error series-formset'>
|
||||||
|
{{ series_formset.empty_form.as_ul }}
|
||||||
</ul>
|
</ul>
|
||||||
{% endfor %}
|
|
||||||
</div>
|
</div>
|
||||||
{{ series_formset.management_form }}
|
<div id="empty_casedifferential_form" style="display:none">
|
||||||
<h3>Differential:</h3>
|
<ul class='no_error casedifferential_formset'>
|
||||||
Add differential here.
|
{{ casedifferential_formset.empty_form.as_ul }}
|
||||||
<input type="button" value="Add Another Differential" id="add_more_differential">
|
|
||||||
<div id="casedifferential_formset">
|
|
||||||
{% for form in casedifferential_formset %}
|
|
||||||
<ul class="no-error casedifferential_formset">
|
|
||||||
{{form.non_field_errors}}
|
|
||||||
{{form.errors}}
|
|
||||||
{{ form.as_ul }}
|
|
||||||
</ul>
|
</ul>
|
||||||
{% endfor %}
|
|
||||||
</div>
|
</div>
|
||||||
{{ casedifferential_formset.management_form }}
|
|
||||||
<input type="submit" class="submit-button" value="Submit" name="submit">
|
|
||||||
</form>
|
|
||||||
<div id="empty_series_form" style="display:none">
|
|
||||||
<ul class='no_error series-formset'>
|
|
||||||
{{ series_formset.empty_form.as_ul }}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div id="empty_casedifferential_form" style="display:none">
|
|
||||||
<ul class='no_error casedifferential_formset'>
|
|
||||||
{{ casedifferential_formset.empty_form.as_ul }}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -6,14 +6,14 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<div id="view-filter-options">
|
<div id="view-filter-options">
|
||||||
<h3>Filter Long </h3>
|
<h3>Filter Long </h3>
|
||||||
<form action="" method="get">
|
<form action="" method="get">
|
||||||
{{ filter.form }}
|
{{ filter.form }}
|
||||||
<input class="btn btn-primary btn-sm mt-1 mb-1" type="submit" />
|
<input class="btn btn-primary btn-sm mt-1 mb-1" type="submit" />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
{% render_table table %}
|
{% render_table table %}
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|||||||
@@ -4,51 +4,51 @@
|
|||||||
{% block css %}
|
{% block css %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block js %}
|
{% block js %}
|
||||||
<!--<script type="text/javascript" src="/admin/jsi18n/"></script>-->
|
<!--<script type="text/javascript" src="/admin/jsi18n/"></script>-->
|
||||||
{{form.media}}
|
{{form.media}}
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
function add_case_input_form() {
|
function add_case_input_form() {
|
||||||
var form_idx = $('#id_casedetail_set-TOTAL_FORMS').val();
|
var form_idx = $('#id_casedetail_set-TOTAL_FORMS').val();
|
||||||
$('#case_formset').append($('#empty_case_form').html().replace(/__prefix__/g, form_idx));
|
$('#case_formset').append($('#empty_case_form').html().replace(/__prefix__/g, form_idx));
|
||||||
$('#id_casedetail_set-TOTAL_FORMS').val(parseInt(form_idx) + 1);
|
$('#id_casedetail_set-TOTAL_FORMS').val(parseInt(form_idx) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
$('#add_more_case').click(() => { add_case_input_form() });
|
$('#add_more_case').click(() => { add_case_input_form() });
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<!-- {{ form.media }} -->
|
<!-- {{ form.media }} -->
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h2>Create Collection</h2>
|
<h2>Create Collection</h2>
|
||||||
Use this form to create a collection of cases
|
Use this form to create a collection of cases
|
||||||
<form action="" method="post" enctype="multipart/form-data" id="atlas-form">
|
<form action="" method="post" enctype="multipart/form-data" id="atlas-form">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
{{ form.as_table }}
|
{{ form.as_table }}
|
||||||
</table>
|
</table>
|
||||||
<h3>Cases:</h3>
|
<h3>Cases:</h3>
|
||||||
Add cases here. These can only be added once created (they can also be added to cases on creation).
|
Add cases here. These can only be added once created (they can also be added to cases on creation).
|
||||||
<input type="button" value="Add More Cases" id="add_more_case">
|
<input type="button" value="Add More Cases" id="add_more_case">
|
||||||
<div id="case_formset">
|
<div id="case_formset">
|
||||||
{% for form in case_formset %}
|
{% for form in case_formset %}
|
||||||
<ul class="no-error case-formset">
|
<ul class="no-error case-formset">
|
||||||
{{form.non_field_errors}}
|
{{form.non_field_errors}}
|
||||||
{{form.errors}}
|
{{form.errors}}
|
||||||
{{ form.as_ul }}
|
{{ form.as_ul }}
|
||||||
|
</ul>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{{ case_formset.management_form }}
|
||||||
|
<input type="submit" class="submit-button" value="Submit" name="submit">
|
||||||
|
</form>
|
||||||
|
<div id="empty_case_form" style="display:none">
|
||||||
|
<ul class='no_error case-formset'>
|
||||||
|
{{ case_formset.empty_form.as_ul }}
|
||||||
</ul>
|
</ul>
|
||||||
{% endfor %}
|
|
||||||
</div>
|
</div>
|
||||||
{{ case_formset.management_form }}
|
|
||||||
<input type="submit" class="submit-button" value="Submit" name="submit">
|
|
||||||
</form>
|
|
||||||
<div id="empty_case_form" style="display:none">
|
|
||||||
<ul class='no_error case-formset'>
|
|
||||||
{{ case_formset.empty_form.as_ul }}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
{% extends 'atlas/base.html' %}
|
{% extends 'atlas/base.html' %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="{% url 'atlas:condition_view' %}">Conditions</a></li>
|
<li><a href="{% url 'atlas:condition_view' %}">Conditions</a></li>
|
||||||
<li><a href="{% url 'atlas:finding_view' %}">Findings</a></li>
|
<li><a href="{% url 'atlas:finding_view' %}">Findings</a></li>
|
||||||
<li><a href="{% url 'atlas:structure_view' %}">Structures</li></a>
|
<li><a href="{% url 'atlas:structure_view' %}">Structures</li></a>
|
||||||
<li><a href="{% url 'atlas:subspecialty_view' %}">Subspecialties</li></a>
|
<li><a href="{% url 'atlas:subspecialty_view' %}">Subspecialties</li></a>
|
||||||
<li><a href="{% url 'atlas:presentation_view' %}">Presentations</li></a>
|
<li><a href="{% url 'atlas:presentation_view' %}">Presentations</li></a>
|
||||||
<li><a href="{% url 'atlas:pathological_process_view' %}">Pathological Process</li></a>
|
<li><a href="{% url 'atlas:pathological_process_view' %}">Pathological Process</li></a>
|
||||||
</ul>
|
</ul>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
{% extends 'atlas/base.html' %}
|
{% extends 'atlas/base.html' %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{{category}}:
|
{{category}}:
|
||||||
<ul>
|
<ul>
|
||||||
{% for atlas in atlas %}
|
{% for atlas in atlas %}
|
||||||
<li><a href="{% url 'atlas:case_detail' pk=atlas.pk %}">{{atlas}}
|
<li><a href="{% url 'atlas:case_detail' pk=atlas.pk %}">{{atlas}}
|
||||||
[{{atlas.get_authors}}]</a></li>
|
[{{atlas.get_authors}}]</a></li>
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
{% extends 'atlas/base.html' %}
|
{% extends 'atlas/base.html' %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% include 'atlas/collection_headers.html' %}
|
{% include 'atlas/collection_headers.html' %}
|
||||||
|
|
||||||
{% include "generic/exam_cids.html" %}
|
{% include "generic/exam_cids.html" %}
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -1,65 +1,65 @@
|
|||||||
{% extends 'atlas/base.html' %}
|
{% extends 'atlas/base.html' %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h2>Case {{case_number|add:1}}
|
<h2>Case {{case_number|add:1}}
|
||||||
|
|
||||||
{% if collection.show_title %}
|
{% if collection.show_title %}
|
||||||
: {{case.title}}
|
: {{case.title}}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
{% if collection.show_description and case.description%}
|
||||||
|
<div>
|
||||||
|
Description: {{case.description}}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% if collection.show_history and case.history%}
|
||||||
|
<div>
|
||||||
|
Description: {{case.history}}
|
||||||
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
</h2>
|
<div class="pre-whitespace multi-image-block">
|
||||||
|
{% for series in series_list %}
|
||||||
{% if collection.show_description and case.description%}
|
<span class="series-block">
|
||||||
<div>
|
<span>
|
||||||
Description: {{case.description}}
|
Series {{ forloop.counter }}:
|
||||||
</div>
|
<a href="#" onclick='window.loadDicomViewer(window.images[{{forloop.counter0}}])'>
|
||||||
{% endif %}
|
{{series.get_block}}
|
||||||
{% if collection.show_history and case.history%}
|
</a>
|
||||||
<div>
|
</span>
|
||||||
Description: {{case.history}}
|
</span>
|
||||||
</div>
|
{% endfor %}
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<div class="pre-whitespace multi-image-block">
|
|
||||||
{% for series in series_list %}
|
|
||||||
<span class="series-block">
|
|
||||||
<span>
|
|
||||||
Series {{ forloop.counter }}:
|
|
||||||
<a href="#" onclick='window.loadDicomViewer(window.images[{{forloop.counter0}}])'>
|
|
||||||
{{series.get_block}}
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<div id="single-dicom-viewer" class="dicom-viewer" data-images="" data-annotations=''>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
|
||||||
{% if collection.show_discussion and case.discussion%}
|
|
||||||
<details>
|
|
||||||
<summary>
|
|
||||||
Discussion:
|
|
||||||
</summary>
|
|
||||||
<div>
|
<div>
|
||||||
{{case.discussion}}
|
<div id="single-dicom-viewer" class="dicom-viewer" data-images="" data-annotations=''>
|
||||||
</div>
|
</div>
|
||||||
</details>
|
|
||||||
{% endif %}
|
|
||||||
{% if collection.show_report and case.report%}
|
|
||||||
<details>
|
|
||||||
<summary>
|
|
||||||
Report:
|
|
||||||
</summary>
|
|
||||||
<div>
|
|
||||||
{{case.report}}
|
|
||||||
</div>
|
|
||||||
</details>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if take %}
|
</div>
|
||||||
|
{% if collection.show_discussion and case.discussion%}
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
Discussion:
|
||||||
|
</summary>
|
||||||
|
<div>
|
||||||
|
{{case.discussion}}
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
{% endif %}
|
||||||
|
{% if collection.show_report and case.report%}
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
Report:
|
||||||
|
</summary>
|
||||||
|
<div>
|
||||||
|
{{case.report}}
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if take %}
|
||||||
<form method="POST" class="post-form">{% csrf_token %}
|
<form method="POST" class="post-form">{% csrf_token %}
|
||||||
<div class="form-contents">
|
<div class="form-contents">
|
||||||
{% if collection.publish_results %}<fieldset disabled="disabled">{% endif %}
|
{% if collection.publish_results %}<fieldset disabled="disabled">{% endif %}
|
||||||
@@ -67,52 +67,52 @@
|
|||||||
{% if collection.publish_results %}</fieldset>{% endif %}
|
{% if collection.publish_results %}</fieldset>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% if previous > -1 %}
|
{% if previous > -1 %}
|
||||||
<button type="submit" name="previous" class="save btn btn-default">Previous</button>
|
<button type="submit" name="previous" class="save btn btn-default">Previous</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if next %}
|
{% if next %}
|
||||||
<button type="submit" name="next" class="save btn btn-default">Next</button>
|
<button type="submit" name="next" class="save btn btn-default">Next</button>
|
||||||
{% else %}
|
{% else %}
|
||||||
{% if not exam.publish_results %}
|
{% if not exam.publish_results %}
|
||||||
<button type="submit" name="save" class="save btn btn-default">Save</button>
|
<button type="submit" name="save" class="save btn btn-default">Save</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if collection.publish_results %}
|
{% if collection.publish_results %}
|
||||||
Answer score: {{answer.score}}<br />
|
Answer score: {{answer.score}}<br />
|
||||||
Answer feedback: {{answer.feedback|safe}}
|
Answer feedback: {{answer.feedback|safe}}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<br />
|
<br />
|
||||||
<button type="submit" name="finish" class="save btn btn-default">Overview</button>
|
<button type="submit" name="finish" class="save btn btn-default">Overview</button>
|
||||||
<button type="submit" id="goto-button" value="test" name="goto" class="hide">goto</button>
|
<button type="submit" id="goto-button" value="test" name="goto" class="hide">goto</button>
|
||||||
</form>
|
</form>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div>
|
<div>
|
||||||
{% if previous %}
|
{% if previous %}
|
||||||
<a href="{% url 'atlas:collection_case_view' pk=collection.pk case_number=case_number|add:-1 %}">Previous</a>
|
<a href="{% url 'atlas:collection_case_view' pk=collection.pk case_number=case_number|add:-1 %}">Previous</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if next %}
|
{% if next %}
|
||||||
<a href="{% url 'atlas:collection_case_view' pk=collection.pk case_number=case_number|add:1 %}">Next</a>
|
<a href="{% url 'atlas:collection_case_view' pk=collection.pk case_number=case_number|add:1 %}">Next</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<br />
|
<br />
|
||||||
Return to <a href='{{collection.get_absolute_url}}'>collection</a>
|
Return to <a href='{{collection.get_absolute_url}}'>collection</a>
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block js %}
|
{% block js %}
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
window.images = {
|
window.images = {
|
||||||
{% for series in series_list %}
|
{% for series in series_list %}
|
||||||
{{ forloop.counter0 }}: ["{{ series.get_image_url_array_not_json }}"],
|
{{ forloop.counter0 }}: ["{{ series.get_image_url_array_not_json }}"],
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
}
|
}
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
window.loadDicomViewer(window.images[0])
|
window.loadDicomViewer(window.images[0])
|
||||||
}, 500);
|
}, 500);
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{% endblock js %}
|
{% endblock js %}
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
{% extends 'atlas/base.html' %}
|
{% extends 'atlas/base.html' %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% include 'atlas/collection_headers.html' %}
|
{% include 'atlas/collection_headers.html' %}
|
||||||
<ul>
|
<ul>
|
||||||
{% for case in collection.cases.all %}
|
{% for case in collection.cases.all %}
|
||||||
<li><a href="{% url 'atlas:collection_case_view' pk=collection.pk case_number=forloop.counter0 %}">Case {{forloop.counter}}</a>
|
<li><a href="{% url 'atlas:collection_case_view' pk=collection.pk case_number=forloop.counter0 %}">Case {{forloop.counter}}</a>
|
||||||
: {{case.title}}
|
: {{case.title}}
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -1,17 +1,17 @@
|
|||||||
|
|
||||||
{% if request.user.is_authenticated %}
|
{% if request.user.is_authenticated %}
|
||||||
Collection: {{collection.name}}-> <a href="{% url 'atlas:collection_detail' pk=collection.pk %}">Overview</a> /
|
Collection: {{collection.name}}-> <a href="{% url 'atlas:collection_detail' pk=collection.pk %}">Overview</a> /
|
||||||
<a href="{% url 'atlas:collection_mark_overview' collection.pk %}">Mark</a> /
|
<a href="{% url 'atlas:collection_mark_overview' collection.pk %}">Mark</a> /
|
||||||
<a href="{% url 'atlas:collection_scores_cid' collection.pk %}">Scores</a> /
|
<a href="{% url 'atlas:collection_scores_cid' collection.pk %}">Scores</a> /
|
||||||
<a href="{% url 'atlas:collection_candidates' collection.pk %}">Candidates</a>
|
<a href="{% url 'atlas:collection_candidates' collection.pk %}">Candidates</a>
|
||||||
<div class="floating-header">
|
<div class="floating-header">
|
||||||
<a href="{% url 'atlas:collection_update' collection.id %}" title="Edit the Collection">Edit</a>
|
<a href="{% url 'atlas:collection_update' collection.id %}" title="Edit the Collection">Edit</a>
|
||||||
\ <a href="{% url 'atlas:collection_delete' collection.id %}" title="Delete the Collection">Delete</a>
|
\ <a href="{% url 'atlas:collection_delete' collection.id %}" title="Delete the Collection">Delete</a>
|
||||||
{% comment %} \ <a href="{% url 'atlas:collection_clone' collection.id %}" title="Clone the Collection">Clone</a> {% endcomment %}
|
{% comment %} \ <a href="{% url 'atlas:collection_clone' collection.id %}" title="Clone the Collection">Clone</a> {% endcomment %}
|
||||||
{% if request.user.is_superuser %}
|
{% if request.user.is_superuser %}
|
||||||
\ <a href="{% url 'admin:atlas_casecollection_change' collection.id %}" title="Edit the Collection using the admin interface">Admin Edit</a>
|
\ <a href="{% url 'admin:atlas_casecollection_change' collection.id %}" title="Edit the Collection using the admin interface">Admin Edit</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
{% extends 'atlas/base.html' %}
|
{% extends 'atlas/base.html' %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<a href="{% url 'atlas:collection_create' %}">Create collection</a>
|
<a href="{% url 'atlas:collection_create' %}">Create collection</a>
|
||||||
<ul>
|
<ul>
|
||||||
{% for collection in collections %}
|
{% for collection in collections %}
|
||||||
<li><a href='{{collection.get_absolute_url}}'>{{collection.name}}</a></li>
|
<li><a href='{{collection.get_absolute_url}}'>{{collection.name}}</a></li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -1,30 +1,30 @@
|
|||||||
{% extends 'atlas/base.html' %}
|
{% extends 'atlas/base.html' %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% include 'atlas/collection_headers.html' %}
|
{% include 'atlas/collection_headers.html' %}
|
||||||
|
|
||||||
<div class="vstack gap-3">
|
<div class="vstack gap-3">
|
||||||
{% for case_detail, answers in case_map.items %}
|
{% for case_detail, answers in case_map.items %}
|
||||||
<div class="border border-dark">
|
<div class="border border-dark">
|
||||||
<h4>Case: {{case_detail.case.title}}</h4>
|
<h4>Case: {{case_detail.case.title}}</h4>
|
||||||
Answers
|
Answers
|
||||||
<ul>
|
<ul>
|
||||||
{% for answer in answers %}
|
{% for answer in answers %}
|
||||||
<li {% if not answer.score %}class="flagged"{% endif %}>{{answer.answer}}
|
<li {% if not answer.score %}class="flagged"{% endif %}>{{answer.answer}}
|
||||||
{% if not answer.score %}
|
{% if not answer.score %}
|
||||||
<span class="badge rounded-pill bg-danger">Unmarked</span>
|
<span class="badge rounded-pill bg-danger">Unmarked</span>
|
||||||
|
|
||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<span class="badge rounded-pill bg-info">Score: {{answer.score}}</span>
|
<span class="badge rounded-pill bg-info">Score: {{answer.score}}</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
<a href="{% url 'atlas:collection_mark_question' collection.pk forloop.counter0 %}">Mark</a>
|
<a href="{% url 'atlas:collection_mark_question' collection.pk forloop.counter0 %}">Mark</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -3,11 +3,12 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
{% include 'atlas/collection_headers.html' %}
|
{% include 'atlas/collection_headers.html' %}
|
||||||
<h3>Marking case: {{case.title}}</h3>
|
<h3>Marking case: {{case.title}}</h3>
|
||||||
|
<button class="btn btn-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasTop" aria-controls="offcanvasTop">View Case</button>
|
||||||
|
|
||||||
<form method="POST" class="post-form">{% csrf_token %}
|
<form method="POST" class="post-form">{% csrf_token %}
|
||||||
<div class="vstack gap-3">
|
<div class="vstack gap-3">
|
||||||
{% for answer, form in answer_forms %}
|
{% for answer, form in answer_forms %}
|
||||||
<div class="border border-dark">
|
<div class="border border-dark">
|
||||||
CID: {{answer.cid}}<br />
|
CID: {{answer.cid}}<br />
|
||||||
Answer: {{answer.answer}} <br />
|
Answer: {{answer.answer}} <br />
|
||||||
Score: {{answer.score}}<br />
|
Score: {{answer.score}}<br />
|
||||||
@@ -31,4 +32,24 @@
|
|||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="offcanvas offcanvas-top" tabindex="-1" id="offcanvasTop" aria-labelledby="offcanvasTopLabel">
|
||||||
|
<div class="offcanvas-header">
|
||||||
|
<h5 id="offcanvasTopLabel">Offcanvas top</h5>
|
||||||
|
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="offcanvas-body">
|
||||||
|
{% for series in series_list %}
|
||||||
|
<span class="series-block">
|
||||||
|
<span>
|
||||||
|
Series {{ forloop.counter }}:
|
||||||
|
<a href="#" onclick='window.loadDicomViewer(window.images[{{forloop.counter0}}])'>
|
||||||
|
{{series.get_block}}
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if editing_finding < 1 %}
|
{% if editing_finding < 1 %}
|
||||||
<button id="add-finding-button">Add finding</button>
|
<button id="add-finding-button">Add finding</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<button id="reset-viewport-button">Reset viewport</button>
|
<button id="reset-viewport-button">Reset viewport</button>
|
||||||
<div id="finding-form">
|
<div id="finding-form">
|
||||||
@@ -28,17 +28,17 @@
|
|||||||
<summary>Findings</summary>
|
<summary>Findings</summary>
|
||||||
|
|
||||||
{% for finding in series.findings.all %}
|
{% for finding in series.findings.all %}
|
||||||
<div class="finding-box">
|
<div class="finding-box">
|
||||||
<button class="view-finding-button" data-annotationjson={{finding.annotation_json}}
|
<button class="view-finding-button" data-annotationjson={{finding.annotation_json}}
|
||||||
data-viewportjson={{finding.viewport_json}} data-findingid={{finding.id}}>Click to view</button>
|
data-viewportjson={{finding.viewport_json}} data-findingid={{finding.id}}>Click to view</button>
|
||||||
<span class="view-finding-details">
|
<span class="view-finding-details">
|
||||||
Finding(s): {% for f in finding.findings.all %}{{f.get_link}}{% endfor %}<br />
|
Finding(s): {% for f in finding.findings.all %}{{f.get_link}}{% endfor %}<br />
|
||||||
Structure(s): {% for s in finding.structures.all %}{{s.get_link}}{% endfor %}<br />
|
Structure(s): {% for s in finding.structures.all %}{{s.get_link}}{% endfor %}<br />
|
||||||
Description: {{finding.description}}<br />
|
Description: {{finding.description}}<br />
|
||||||
</span>
|
</span>
|
||||||
<a href="{% url 'atlas:series_edit_finding' pk=series.pk finding_pk=finding.pk %}" class="edit-finding-link">Edit</a>
|
<a href="{% url 'atlas:series_edit_finding' pk=series.pk finding_pk=finding.pk %}" class="edit-finding-link">Edit</a>
|
||||||
<a href="{% url 'atlas:delete_finding' pk=finding.pk %}" class="delete-finding-link">Delete</a>
|
<a href="{% url 'atlas:delete_finding' pk=finding.pk %}" class="delete-finding-link">Delete</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</details>
|
</details>
|
||||||
@@ -58,8 +58,8 @@
|
|||||||
title="orders dicom by uploaded filename">Order by uploaded filename</a>
|
title="orders dicom by uploaded filename">Order by uploaded filename</a>
|
||||||
</div>
|
</div>
|
||||||
{% for image in series.images.all %}
|
{% for image in series.images.all %}
|
||||||
{{image.image.url}}, pos: {{image.position}}, {{image.upload_filename}} [{{image.image.size|filesizeformat}}]<br />
|
{{image.image.url}}, pos: {{image.position}}, {{image.upload_filename}} [{{image.image.size|filesizeformat}}]<br />
|
||||||
{% comment %} {{image.get_dicom_info|safe}}<br /> {% endcomment %}
|
{% comment %} {{image.get_dicom_info|safe}}<br /> {% endcomment %}
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
@@ -109,10 +109,10 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
{% if editing_finding > 0 %}
|
{% if editing_finding > 0 %}
|
||||||
$("#hidden-form").show()
|
$("#hidden-form").show()
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
$(".view-finding-button[data-findingid={{editing_finding}}]").trigger("click");
|
$(".view-finding-button[data-findingid={{editing_finding}}]").trigger("click");
|
||||||
}, 1000)
|
}, 1000)
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
});
|
});
|
||||||
@@ -144,15 +144,15 @@
|
|||||||
series: {{ series.pk }},
|
series: {{ series.pk }},
|
||||||
//annotation_json: JSON.stringify(c.toolStateManager.saveToolState()),
|
//annotation_json: JSON.stringify(c.toolStateManager.saveToolState()),
|
||||||
annotation_json: JSON.stringify(cornerstoneTools.globalImageIdSpecificToolStateManager
|
annotation_json: JSON.stringify(cornerstoneTools.globalImageIdSpecificToolStateManager
|
||||||
.saveToolState()),
|
.saveToolState()),
|
||||||
viewport_json: JSON.stringify(c.viewport),
|
viewport_json: JSON.stringify(c.viewport),
|
||||||
findings: JSON.stringify($('#finding-form select[name="findings"]').find(":selected")
|
findings: JSON.stringify($('#finding-form select[name="findings"]').find(":selected")
|
||||||
.map((i, el) => {
|
.map((i, el) => {
|
||||||
return $(el).val()
|
return $(el).val()
|
||||||
}).toArray()),
|
}).toArray()),
|
||||||
structures: JSON.stringify($('#finding-form select[name="structures"]').find(
|
structures: JSON.stringify($('#finding-form select[name="structures"]').find(
|
||||||
":selected")
|
":selected")
|
||||||
.map((i, el) => {
|
.map((i, el) => {
|
||||||
return $(el).val()
|
return $(el).val()
|
||||||
}).toArray()),
|
}).toArray()),
|
||||||
csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val(),
|
csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val(),
|
||||||
@@ -165,7 +165,7 @@
|
|||||||
},
|
},
|
||||||
error: function (xhr, errmsg, err) {
|
error: function (xhr, errmsg, err) {
|
||||||
console.log(xhr.status + ": " + xhr
|
console.log(xhr.status + ": " + xhr
|
||||||
.responseText); // provide a bit more info about the error to the console
|
.responseText); // provide a bit more info about the error to the console
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,53 +1,53 @@
|
|||||||
{% extends 'atlas/base.html' %}
|
{% extends 'atlas/base.html' %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h2>{{collection.name}}
|
<h2>{{collection.name}}
|
||||||
<ul>
|
<ul>
|
||||||
</ul>
|
</ul>
|
||||||
{% if collection.collection_type == "REP" %}
|
{% if collection.collection_type == "REP" %}
|
||||||
<h2>Start: {{exam.name}}</h2>
|
<h2>Start: {{exam.name}}</h2>
|
||||||
|
|
||||||
Enter your CID and passcode in the below boxes.<br />
|
Enter your CID and passcode in the below boxes.<br />
|
||||||
<p><input id="cid-box" type="text" value="Candidate ID"></p>
|
<p><input id="cid-box" type="text" value="Candidate ID"></p>
|
||||||
<p><input id="passcode-box" type="text" value="Passcode"></p>
|
<p><input id="passcode-box" type="text" value="Passcode"></p>
|
||||||
|
|
||||||
<button>Start</button>
|
<button>Start</button>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
window.location.search.substr(1).split("&").forEach((item) =>
|
window.location.search.substr(1).split("&").forEach((item) =>
|
||||||
{
|
{
|
||||||
s = item.split("=");
|
s = item.split("=");
|
||||||
if (s[0] == "cid") {
|
if (s[0] == "cid") {
|
||||||
$("#cid-box").val(s[1]);
|
$("#cid-box").val(s[1]);
|
||||||
|
|
||||||
}
|
}
|
||||||
if (s[0] == "passcode") {
|
if (s[0] == "passcode") {
|
||||||
$("#passcode-box").val(s[1]);
|
$("#passcode-box").val(s[1]);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$("#cid-box, #passcode-box").keypress(function(e) {
|
||||||
|
// Enter pressed?
|
||||||
|
console.log(e)
|
||||||
|
if(e.which == 10 || e.which == 13) {
|
||||||
|
$("button").click();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$("button").click(() => {
|
||||||
|
let cid = $("#cid-box").val();
|
||||||
|
let passcode = $("#passcode-box").val();
|
||||||
|
|
||||||
|
if (Number.isInteger(parseInt(cid))) {
|
||||||
|
window.location.replace("{% url 'atlas:collection_case_view_take' pk=collection.pk case_number=0 cid='0000000' passcode='ZZZZZZ' %}".replace("0000000", cid).replace("ZZZZZZ", passcode));
|
||||||
|
} else {
|
||||||
|
alert("Please enter a valid Candidate ID (CID).")
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
</script>
|
||||||
|
{% endif %}
|
||||||
$("#cid-box, #passcode-box").keypress(function(e) {
|
|
||||||
// Enter pressed?
|
|
||||||
console.log(e)
|
|
||||||
if(e.which == 10 || e.which == 13) {
|
|
||||||
$("button").click();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$("button").click(() => {
|
|
||||||
let cid = $("#cid-box").val();
|
|
||||||
let passcode = $("#passcode-box").val();
|
|
||||||
|
|
||||||
if (Number.isInteger(parseInt(cid))) {
|
|
||||||
window.location.replace("{% url 'atlas:collection_case_view_take' pk=collection.pk case_number=0 cid='0000000' passcode='ZZZZZZ' %}".replace("0000000", cid).replace("ZZZZZZ", passcode));
|
|
||||||
} else {
|
|
||||||
alert("Please enter a valid Candidate ID (CID).")
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -4,23 +4,23 @@
|
|||||||
{% block css %}
|
{% block css %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block js %}
|
{% block js %}
|
||||||
<!--<script type="text/javascript" src="/admin/jsi18n/"></script>-->
|
<!--<script type="text/javascript" src="/admin/jsi18n/"></script>-->
|
||||||
{{form.media}}
|
{{form.media}}
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- {{ form.media }} -->
|
<!-- {{ form.media }} -->
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h2>Add/Edit Condition</h2>
|
<h2>Add/Edit Condition</h2>
|
||||||
Use this form to create or edit a condition.
|
Use this form to create or edit a condition.
|
||||||
<form action="" method="post" enctype="multipart/form-data" id="condition-form">
|
<form action="" method="post" enctype="multipart/form-data" id="condition-form">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
{{ form.as_table }}
|
{{ form.as_table }}
|
||||||
</table>
|
</table>
|
||||||
<input type="submit" class="submit-button" value="Submit" name="submit">
|
<input type="submit" class="submit-button" value="Submit" name="submit">
|
||||||
</form>
|
</form>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -4,23 +4,23 @@
|
|||||||
{% block css %}
|
{% block css %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block js %}
|
{% block js %}
|
||||||
<!--<script type="text/javascript" src="/admin/jsi18n/"></script>-->
|
<!--<script type="text/javascript" src="/admin/jsi18n/"></script>-->
|
||||||
{{form.media}}
|
{{form.media}}
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- {{ form.media }} -->
|
<!-- {{ form.media }} -->
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h2>Add/Edit Finding</h2>
|
<h2>Add/Edit Finding</h2>
|
||||||
Use this form to create or edit a finding.
|
Use this form to create or edit a finding.
|
||||||
<form action="" method="post" enctype="multipart/form-data" id="finding-form">
|
<form action="" method="post" enctype="multipart/form-data" id="finding-form">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
{{ form.as_table }}
|
{{ form.as_table }}
|
||||||
</table>
|
</table>
|
||||||
<input type="submit" class="submit-button" value="Submit" name="submit">
|
<input type="submit" class="submit-button" value="Submit" name="submit">
|
||||||
</form>
|
</form>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
|
|
||||||
<div class="floating-header">
|
<div class="floating-header">
|
||||||
{% comment %} <a href="{% url 'atlas:pathological_process_update' pk=pathological_process.pk %}" title="Edit the Condition">Edit</a>
|
{% comment %} <a href="{% url 'atlas:pathological_process_update' pk=pathological_process.pk %}" title="Edit the Condition">Edit</a>
|
||||||
<a href="{% url 'atlas:pathological_process_delete' pk=pathological_process.pk %}" title="Delete the Condition">Delete</a> {% endcomment %}
|
<a href="{% url 'atlas:pathological_process_delete' pk=pathological_process.pk %}" title="Delete the Condition">Delete</a> {% endcomment %}
|
||||||
{% if request.user.is_superuser %}
|
{% if request.user.is_superuser %}
|
||||||
<a href="{% url 'admin:atlas_pathologicalprocess_change' pathological_process.id %}"
|
<a href="{% url 'admin:atlas_pathologicalprocess_change' pathological_process.id %}"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
|
|
||||||
<div class="floating-header">
|
<div class="floating-header">
|
||||||
{% comment %} <a href="{% url 'atlas:presentation_update' pk=presentation.pk %}" title="Edit the Condition">Edit</a>
|
{% comment %} <a href="{% url 'atlas:presentation_update' pk=presentation.pk %}" title="Edit the Condition">Edit</a>
|
||||||
<a href="{% url 'atlas:presentation_delete' pk=presentation.pk %}" title="Delete the Condition">Delete</a> {% endcomment %}
|
<a href="{% url 'atlas:presentation_delete' pk=presentation.pk %}" title="Delete the Condition">Delete</a> {% endcomment %}
|
||||||
{% if request.user.is_superuser %}
|
{% if request.user.is_superuser %}
|
||||||
<a href="{% url 'admin:atlas_presentation_change' presentation.id %}"
|
<a href="{% url 'admin:atlas_presentation_change' presentation.id %}"
|
||||||
|
|||||||
@@ -3,118 +3,118 @@
|
|||||||
{% load static %}
|
{% load static %}
|
||||||
|
|
||||||
{% block js %}
|
{% block js %}
|
||||||
<!--<script type="text/javascript" src="/admin/jsi18n/"></script>-->
|
<!--<script type="text/javascript" src="/admin/jsi18n/"></script>-->
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
document.addEventListener('drop', function (e) { e.preventDefault(); }, false);
|
document.addEventListener('drop', function (e) { e.preventDefault(); }, false);
|
||||||
|
|
||||||
function add_input_form() {
|
function add_input_form() {
|
||||||
var form_idx = $('#id_images-TOTAL_FORMS').val();
|
var form_idx = $('#id_images-TOTAL_FORMS').val();
|
||||||
$('#image_form_set').append($('#empty_form').html().replace(/__prefix__/g, form_idx));
|
$('#image_form_set').append($('#empty_form').html().replace(/__prefix__/g, form_idx));
|
||||||
$('#id_images-TOTAL_FORMS').val(parseInt(form_idx) + 1);
|
$('#id_images-TOTAL_FORMS').val(parseInt(form_idx) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
$("#add_examination").appendTo($("label[for='id_examination']"));
|
$("#add_examination").appendTo($("label[for='id_examination']"));
|
||||||
|
|
||||||
dropContainer = document.getElementById("drop-container");
|
dropContainer = document.getElementById("drop-container");
|
||||||
|
|
||||||
dropContainer.ondragover = function (evt) {
|
dropContainer.ondragover = function (evt) {
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
evt.stopPropagation();
|
evt.stopPropagation();
|
||||||
};
|
};
|
||||||
|
|
||||||
dropContainer.ondragenter = function (evt) {
|
dropContainer.ondragenter = function (evt) {
|
||||||
console.log("ENTER")
|
console.log("ENTER")
|
||||||
console.log(evt)
|
console.log(evt)
|
||||||
$(evt.target).addClass("drop-target-active")
|
$(evt.target).addClass("drop-target-active")
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
evt.stopPropagation();
|
evt.stopPropagation();
|
||||||
};
|
};
|
||||||
|
|
||||||
dropContainer.ondragleave = function (evt) {
|
dropContainer.ondragleave = function (evt) {
|
||||||
console.log("ENTER")
|
console.log("ENTER")
|
||||||
console.log(evt)
|
console.log(evt)
|
||||||
$(evt.target).removeClass("drop-target-active")
|
$(evt.target).removeClass("drop-target-active")
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
evt.stopPropagation();
|
evt.stopPropagation();
|
||||||
};
|
};
|
||||||
|
|
||||||
dropContainer.ondrop = function (evt) {
|
dropContainer.ondrop = function (evt) {
|
||||||
$(evt.target).removeClass("drop-target-active");
|
$(evt.target).removeClass("drop-target-active");
|
||||||
|
|
||||||
|
|
||||||
if (evt.dataTransfer.files.length < 1) {
|
if (evt.dataTransfer.files.length < 1) {
|
||||||
toastr.warning(`Drop failed :( try again?`);
|
toastr.warning(`Drop failed :( try again?`);
|
||||||
} else {
|
} else {
|
||||||
toastr.info(`Adding ${evt.dataTransfer.files.length} files.`);
|
toastr.info(`Adding ${evt.dataTransfer.files.length} files.`);
|
||||||
}
|
|
||||||
|
|
||||||
// Get all input elements
|
|
||||||
inputs = $("#atlas-form input[type=file][id^=id_images-]");
|
|
||||||
//fileInput = document.getElementById("id_images-0-image");
|
|
||||||
|
|
||||||
// Make sure we have enough input targets
|
|
||||||
input_diff = (evt.dataTransfer.files.length - inputs.length)
|
|
||||||
|
|
||||||
if (input_diff > 0) {
|
|
||||||
for (let j = 0; j < input_diff; j++) {
|
|
||||||
add_input_form()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Need to make sure we include the new ones...
|
// Get all input elements
|
||||||
inputs = $("#atlas-form input[type=file][id^=id_images-]");
|
inputs = $("#atlas-form input[type=file][id^=id_images-]");
|
||||||
}
|
//fileInput = document.getElementById("id_images-0-image");
|
||||||
|
|
||||||
// Loop through each dropped file and try to assign to an
|
// Make sure we have enough input targets
|
||||||
// input element
|
input_diff = (evt.dataTransfer.files.length - inputs.length)
|
||||||
[...evt.dataTransfer.files].forEach((f) => {
|
|
||||||
let dT = new DataTransfer();
|
|
||||||
dT.clearData();
|
|
||||||
dT.items.add(f);
|
|
||||||
for (let i = 0; i < inputs.length; i++) {
|
|
||||||
el = inputs.get(i)
|
|
||||||
|
|
||||||
if (el.files.length == 0) {
|
if (input_diff > 0) {
|
||||||
el.files = dT.files;
|
for (let j = 0; j < input_diff; j++) {
|
||||||
//ocr(el)
|
add_input_form()
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Need to make sure we include the new ones...
|
||||||
|
inputs = $("#atlas-form input[type=file][id^=id_images-]");
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
|
||||||
// // If you want to use some of the dropped files
|
// Loop through each dropped file and try to assign to an
|
||||||
// const dT = new DataTransfer();
|
// input element
|
||||||
// dT.items.add(evt.dataTransfer.files[0]);
|
[...evt.dataTransfer.files].forEach((f) => {
|
||||||
// dT.items.add(evt.dataTransfer.files[3]);
|
let dT = new DataTransfer();
|
||||||
// fileInput.files = dT.files;
|
dT.clearData();
|
||||||
|
dT.items.add(f);
|
||||||
|
for (let i = 0; i < inputs.length; i++) {
|
||||||
|
el = inputs.get(i)
|
||||||
|
|
||||||
loadDicomViewerAndFileImages();
|
if (el.files.length == 0) {
|
||||||
|
el.files = dT.files;
|
||||||
|
//ocr(el)
|
||||||
|
|
||||||
evt.preventDefault();
|
return false
|
||||||
evt.stopPropagation();
|
}
|
||||||
};
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// // If you want to use some of the dropped files
|
||||||
|
// const dT = new DataTransfer();
|
||||||
|
// dT.items.add(evt.dataTransfer.files[0]);
|
||||||
|
// dT.items.add(evt.dataTransfer.files[3]);
|
||||||
|
// fileInput.files = dT.files;
|
||||||
|
|
||||||
|
loadDicomViewerAndFileImages();
|
||||||
|
|
||||||
|
evt.preventDefault();
|
||||||
|
evt.stopPropagation();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
$('#add_more_images').click(() => { add_input_form() });
|
$('#add_more_images').click(() => { add_input_form() });
|
||||||
|
|
||||||
$("input[type=file]").on('change', function () {
|
$("input[type=file]").on('change', function () {
|
||||||
$(this).removeClass("image-ident-warning");
|
$(this).removeClass("image-ident-warning");
|
||||||
$(this).removeClass("image-ident-ok");
|
$(this).removeClass("image-ident-ok");
|
||||||
console.log("input change1");
|
console.log("input change1");
|
||||||
console.log("input change", this);
|
console.log("input change", this);
|
||||||
//ocr(this);
|
//ocr(this);
|
||||||
//LoadDicomViewer();
|
//LoadDicomViewer();
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
sortable('.sortable');
|
sortable('.sortable');
|
||||||
sortable('.sortable')[0].addEventListener('sortupdate', function (e) {
|
sortable('.sortable')[0].addEventListener('sortupdate', function (e) {
|
||||||
/*
|
/*
|
||||||
|
|
||||||
This event is triggered when the user stops sorting and the DOM position has not yet changed.
|
This event is triggered when the user stops sorting and the DOM position has not yet changed.
|
||||||
|
|
||||||
@@ -125,262 +125,262 @@
|
|||||||
e.detail.origin.elementIndex - {Integer} Index of the element in all elements in the Sortable Container
|
e.detail.origin.elementIndex - {Integer} Index of the element in all elements in the Sortable Container
|
||||||
e.detail.origin.container - {HTMLElement} Sortable Container that element was moved out of (or copied from)
|
e.detail.origin.container - {HTMLElement} Sortable Container that element was moved out of (or copied from)
|
||||||
*/
|
*/
|
||||||
//updateImagePositions();
|
//updateImagePositions();
|
||||||
|
|
||||||
$(".temp-thumb").remove()
|
$(".temp-thumb").remove()
|
||||||
loadDicomViewer();
|
loadDicomViewer();
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function ocr(input) {
|
|
||||||
// Tesseract.recognize(f, "eng",{ logger: m => console.log(m) }
|
|
||||||
// ).then(({ data: { text } }) => {
|
|
||||||
// console.log(text);
|
|
||||||
// l = text.toLowerCase();
|
|
||||||
// if (l.includes("accesion") || l.includes("number") || l.search(/(REF|RK9|RH8|RA9)\d+/g)) {
|
|
||||||
// console.log("SHIT", this);
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
|
|
||||||
console.log('{% static "worker.min.js" %}');
|
|
||||||
console.log('{{ STATIC_URL }}/tesseract-core.wasm.js %}');
|
|
||||||
|
|
||||||
const worker = Tesseract.createWorker({
|
|
||||||
workerPath: '{% static "worker.min.js" %}',
|
|
||||||
langPath: '{% static "" %}',
|
|
||||||
//langPath: '{{ STATIC_URL }}',
|
|
||||||
corePath: '{% static "tesseract-core.wasm.js" %}',
|
|
||||||
});
|
|
||||||
|
|
||||||
const url = URL.createObjectURL(input.files[0]);
|
|
||||||
let img = new Image;
|
|
||||||
img.src = url;
|
|
||||||
|
|
||||||
img.onload = function () {
|
|
||||||
|
|
||||||
|
|
||||||
width = img.width;
|
|
||||||
|
|
||||||
// const rectangle = { left: 0, top: 0, width: width, height: 10 }
|
|
||||||
|
|
||||||
|
|
||||||
(async () => {
|
|
||||||
await worker.load();
|
|
||||||
await worker.loadLanguage('eng');
|
|
||||||
await worker.initialize('eng');
|
|
||||||
// const { data: { text } } = await worker.recognize(input.files[0], { rectangle });
|
|
||||||
const { data: { text } } = await worker.recognize(input.files[0]);
|
|
||||||
//console.log(text);
|
|
||||||
l = text.toLowerCase();
|
|
||||||
$(`img[data-input-id='${input.id}'`).removeClass("image-ident-loading");
|
|
||||||
console.log(l);
|
|
||||||
if (l.includes("accesion") || l.includes("number") || l.search(/(ref|rk9|rh8|ra9|rbz)\d+/g) > -1) {
|
|
||||||
$(input).addClass("image-ident-warning");
|
|
||||||
$(`img[data-input-id='${input.id}'`).addClass("image-ident-warning");
|
|
||||||
} else {
|
|
||||||
$(input).addClass("image-ident-ok");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
await worker.terminate();
|
|
||||||
})();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async function loadDicomViewerAndFileImages(callback) {
|
|
||||||
$("#single-dicom-viewer").empty()
|
|
||||||
//images = []
|
|
||||||
//Function that returns a promise to read the file
|
|
||||||
const reader = (file) => {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const fileReader = new FileReader();
|
|
||||||
fileReader.onload = () => resolve(fileReader);
|
|
||||||
fileReader.readAsDataURL(file);
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
const readFile = (file, el) => {
|
|
||||||
reader(file).then(reader => {
|
|
||||||
console.log("hello", file, el, image)
|
|
||||||
if ($("#id_examination").find(":selected")[0].dataset.select2Id == "2") {
|
|
||||||
var byteArray = new Uint8Array(reader.result);
|
|
||||||
console.log("etrxact")
|
|
||||||
extractDicomStudyDescription(byteArray);
|
|
||||||
}
|
|
||||||
var image = new Image();
|
|
||||||
image.height = 100;
|
|
||||||
image.title = file.name;
|
|
||||||
image.src = reader.result;
|
|
||||||
image.className = "temp-thumb";
|
|
||||||
console.log("read", el);
|
|
||||||
$(el).parent().parent().prepend(image);
|
|
||||||
//images.push(reader.result);
|
|
||||||
loadViewer(images);
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
file_set = $("#image_form_set input[type=file]");
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
file_set.each(async (n, el) => {
|
|
||||||
console.log(el);
|
|
||||||
if (el.files.length > 0) {
|
|
||||||
filename = el.files[0].name;
|
|
||||||
await readFile(el.files[0], el);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
console.log("images from files", images);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadViewer(images) {
|
|
||||||
//dicomViewer.loadCornerstone($("#single-dicom-viewer"), null, images, annotations);
|
|
||||||
file_set = $("#image_form_set input[type=file]");
|
|
||||||
|
|
||||||
n = 0;
|
|
||||||
for (let i = 0; i < file_set.length; i++) {
|
|
||||||
el = file_set.get(i)
|
|
||||||
if (el.files.length > 0) {
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
image_set = $("#image_form_set img");
|
|
||||||
if (n == image_set.length) {
|
|
||||||
const event = new CustomEvent('loadDicomViewer', { "detail": image_set });
|
|
||||||
|
|
||||||
window.dispatchEvent(event);
|
|
||||||
sortable('.sortable');
|
|
||||||
//sortable('.sortable')[0].addEventListener('sortstop', function(e) {
|
|
||||||
updateImagePositions();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateImagePositions() {
|
|
||||||
console.log("UP pos");
|
|
||||||
|
|
||||||
file_set = $("#image_form_set ul");
|
|
||||||
|
|
||||||
n = 0;
|
|
||||||
for (let i = 0; i < file_set.length; i++) {
|
|
||||||
ul = file_set.get(i);
|
|
||||||
console.log(ul)
|
|
||||||
|
|
||||||
file_element = $(ul).find("input[type=file]").get(0);
|
|
||||||
|
|
||||||
// If a (new) file is being uploaded we save it's name prior to it being hashed
|
|
||||||
if (file_element.files.length > 0) {
|
|
||||||
file_name = file_element.files[0].name
|
|
||||||
$(ul).find("input[type=text]").val(file_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file_element.files.length > 0 || $(ul).find(":contains('Currently:')")) {
|
|
||||||
n++;
|
|
||||||
$(ul).find("input[type=number]").val(n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function extractDicomStudyDescription(byteArray) {
|
|
||||||
// We need to setup a try/catch block because parseDicom will throw an exception
|
|
||||||
// if you attempt to parse a non dicom part 10 file (or one that is corrupted)
|
|
||||||
try {
|
|
||||||
// parse byteArray into a DataSet object using the parseDicom library
|
|
||||||
var dataSet = dicomParser.parseDicom(byteArray);
|
|
||||||
|
|
||||||
// dataSet contains the parsed elements. Each element is available via a property
|
|
||||||
// in the dataSet.elements object. The property name is based on the elements group
|
|
||||||
// and element in the following format: xggggeeee where gggg is the group number
|
|
||||||
// and eeee is the element number with lowercase hex characters.
|
|
||||||
|
|
||||||
// To access the data for an element, we need to know its type and its tag.
|
|
||||||
// We will get the sopInstanceUid from the file which is a string and
|
|
||||||
// has the tag (0020,000D)
|
|
||||||
var study_description = dataSet.string('x00081030').toLowerCase();
|
|
||||||
console.log("STUDY", study_description);
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: `{% url 'generic:examination-autocomplete' %}/${encodeURI(study_description)}`,
|
|
||||||
//context: document.body,
|
|
||||||
success: function(data){
|
|
||||||
console.log(data)
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// try to match with a study description (if not already selected)
|
|
||||||
if ($(`#id_examination_to option`).length < 1) {
|
|
||||||
option = $(`#id_examination_from option[title*='${study_description}' i]`);
|
|
||||||
|
|
||||||
if (option.length) {
|
|
||||||
option.appendTo($("#id_examination_to"));
|
|
||||||
toastr.success(`Examination set to ${option.attr('title')} from dicom data`);
|
|
||||||
} else {
|
|
||||||
toastr.warning(
|
|
||||||
`Unable to set examination ${study_description} from dicom data (it needs creating)`);
|
|
||||||
|
|
||||||
|
|
||||||
|
function ocr(input) {
|
||||||
|
// Tesseract.recognize(f, "eng",{ logger: m => console.log(m) }
|
||||||
|
// ).then(({ data: { text } }) => {
|
||||||
|
// console.log(text);
|
||||||
|
// l = text.toLowerCase();
|
||||||
|
// if (l.includes("accesion") || l.includes("number") || l.search(/(REF|RK9|RH8|RA9)\d+/g)) {
|
||||||
|
// console.log("SHIT", this);
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
|
||||||
|
console.log('{% static "worker.min.js" %}');
|
||||||
|
console.log('{{ STATIC_URL }}/tesseract-core.wasm.js %}');
|
||||||
|
|
||||||
|
const worker = Tesseract.createWorker({
|
||||||
|
workerPath: '{% static "worker.min.js" %}',
|
||||||
|
langPath: '{% static "" %}',
|
||||||
|
//langPath: '{{ STATIC_URL }}',
|
||||||
|
corePath: '{% static "tesseract-core.wasm.js" %}',
|
||||||
|
});
|
||||||
|
|
||||||
|
const url = URL.createObjectURL(input.files[0]);
|
||||||
|
let img = new Image;
|
||||||
|
img.src = url;
|
||||||
|
|
||||||
|
img.onload = function () {
|
||||||
|
|
||||||
|
|
||||||
|
width = img.width;
|
||||||
|
|
||||||
|
// const rectangle = { left: 0, top: 0, width: width, height: 10 }
|
||||||
|
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
await worker.load();
|
||||||
|
await worker.loadLanguage('eng');
|
||||||
|
await worker.initialize('eng');
|
||||||
|
// const { data: { text } } = await worker.recognize(input.files[0], { rectangle });
|
||||||
|
const { data: { text } } = await worker.recognize(input.files[0]);
|
||||||
|
//console.log(text);
|
||||||
|
l = text.toLowerCase();
|
||||||
|
$(`img[data-input-id='${input.id}'`).removeClass("image-ident-loading");
|
||||||
|
console.log(l);
|
||||||
|
if (l.includes("accesion") || l.includes("number") || l.search(/(ref|rk9|rh8|ra9|rbz)\d+/g) > -1) {
|
||||||
|
$(input).addClass("image-ident-warning");
|
||||||
|
$(`img[data-input-id='${input.id}'`).addClass("image-ident-warning");
|
||||||
|
} else {
|
||||||
|
$(input).addClass("image-ident-ok");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
await worker.terminate();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function loadDicomViewerAndFileImages(callback) {
|
||||||
|
$("#single-dicom-viewer").empty()
|
||||||
|
//images = []
|
||||||
|
//Function that returns a promise to read the file
|
||||||
|
const reader = (file) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const fileReader = new FileReader();
|
||||||
|
fileReader.onload = () => resolve(fileReader);
|
||||||
|
fileReader.readAsDataURL(file);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const readFile = (file, el) => {
|
||||||
|
reader(file).then(reader => {
|
||||||
|
console.log("hello", file, el, image)
|
||||||
|
if ($("#id_examination").find(":selected")[0].dataset.select2Id == "2") {
|
||||||
|
var byteArray = new Uint8Array(reader.result);
|
||||||
|
console.log("etrxact")
|
||||||
|
extractDicomStudyDescription(byteArray);
|
||||||
|
}
|
||||||
|
var image = new Image();
|
||||||
|
image.height = 100;
|
||||||
|
image.title = file.name;
|
||||||
|
image.src = reader.result;
|
||||||
|
image.className = "temp-thumb";
|
||||||
|
console.log("read", el);
|
||||||
|
$(el).parent().parent().prepend(image);
|
||||||
|
//images.push(reader.result);
|
||||||
|
loadViewer(images);
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
file_set = $("#image_form_set input[type=file]");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
file_set.each(async (n, el) => {
|
||||||
|
console.log(el);
|
||||||
|
if (el.files.length > 0) {
|
||||||
|
filename = el.files[0].name;
|
||||||
|
await readFile(el.files[0], el);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
console.log("images from files", images);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadViewer(images) {
|
||||||
|
//dicomViewer.loadCornerstone($("#single-dicom-viewer"), null, images, annotations);
|
||||||
|
file_set = $("#image_form_set input[type=file]");
|
||||||
|
|
||||||
|
n = 0;
|
||||||
|
for (let i = 0; i < file_set.length; i++) {
|
||||||
|
el = file_set.get(i)
|
||||||
|
if (el.files.length > 0) {
|
||||||
|
n++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (err) {
|
image_set = $("#image_form_set img");
|
||||||
console.log(err);
|
if (n == image_set.length) {
|
||||||
}
|
const event = new CustomEvent('loadDicomViewer', { "detail": image_set });
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{{ form.media }}
|
window.dispatchEvent(event);
|
||||||
|
sortable('.sortable');
|
||||||
|
//sortable('.sortable')[0].addEventListener('sortstop', function(e) {
|
||||||
|
updateImagePositions();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateImagePositions() {
|
||||||
|
console.log("UP pos");
|
||||||
|
|
||||||
|
file_set = $("#image_form_set ul");
|
||||||
|
|
||||||
|
n = 0;
|
||||||
|
for (let i = 0; i < file_set.length; i++) {
|
||||||
|
ul = file_set.get(i);
|
||||||
|
console.log(ul)
|
||||||
|
|
||||||
|
file_element = $(ul).find("input[type=file]").get(0);
|
||||||
|
|
||||||
|
// If a (new) file is being uploaded we save it's name prior to it being hashed
|
||||||
|
if (file_element.files.length > 0) {
|
||||||
|
file_name = file_element.files[0].name
|
||||||
|
$(ul).find("input[type=text]").val(file_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_element.files.length > 0 || $(ul).find(":contains('Currently:')")) {
|
||||||
|
n++;
|
||||||
|
$(ul).find("input[type=number]").val(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function extractDicomStudyDescription(byteArray) {
|
||||||
|
// We need to setup a try/catch block because parseDicom will throw an exception
|
||||||
|
// if you attempt to parse a non dicom part 10 file (or one that is corrupted)
|
||||||
|
try {
|
||||||
|
// parse byteArray into a DataSet object using the parseDicom library
|
||||||
|
var dataSet = dicomParser.parseDicom(byteArray);
|
||||||
|
|
||||||
|
// dataSet contains the parsed elements. Each element is available via a property
|
||||||
|
// in the dataSet.elements object. The property name is based on the elements group
|
||||||
|
// and element in the following format: xggggeeee where gggg is the group number
|
||||||
|
// and eeee is the element number with lowercase hex characters.
|
||||||
|
|
||||||
|
// To access the data for an element, we need to know its type and its tag.
|
||||||
|
// We will get the sopInstanceUid from the file which is a string and
|
||||||
|
// has the tag (0020,000D)
|
||||||
|
var study_description = dataSet.string('x00081030').toLowerCase();
|
||||||
|
console.log("STUDY", study_description);
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: `{% url 'generic:examination-autocomplete' %}/${encodeURI(study_description)}`,
|
||||||
|
//context: document.body,
|
||||||
|
success: function(data){
|
||||||
|
console.log(data)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// try to match with a study description (if not already selected)
|
||||||
|
if ($(`#id_examination_to option`).length < 1) {
|
||||||
|
option = $(`#id_examination_from option[title*='${study_description}' i]`);
|
||||||
|
|
||||||
|
if (option.length) {
|
||||||
|
option.appendTo($("#id_examination_to"));
|
||||||
|
toastr.success(`Examination set to ${option.attr('title')} from dicom data`);
|
||||||
|
} else {
|
||||||
|
toastr.warning(
|
||||||
|
`Unable to set examination ${study_description} from dicom data (it needs creating)`);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{{ form.media }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h2>Add Series</h2>
|
<h2>Add Series</h2>
|
||||||
This form will create a image set that can be associated with a atlas question. If the question has already been created
|
This form will create a image set that can be associated with a atlas question. If the question has already been created
|
||||||
it can be linked below.
|
it can be linked below.
|
||||||
<form action="" method="post" enctype="multipart/form-data" id="atlas-form">
|
<form action="" method="post" enctype="multipart/form-data" id="atlas-form">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<a href="/generic/examination/create" id="add_examination" class="add-popup"
|
<a href="/generic/examination/create" id="add_examination" class="add-popup"
|
||||||
onclick="return showAddPopup(this);"><img src="{% static '/img/icon-addlink.svg' %}"></a>
|
onclick="return showAddPopup(this);"><img src="{% static '/img/icon-addlink.svg' %}"></a>
|
||||||
<table>
|
<table>
|
||||||
{{ form.as_table }}
|
{{ form.as_table }}
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<h3>Images:</h3>
|
<h3>Images:</h3>
|
||||||
<input type="button" value="Add More Images" id="add_more_images">
|
<input type="button" value="Add More Images" id="add_more_images">
|
||||||
<div id="drop-container" class="">Drop images here (or use the buttons below). Dropping images here will overwrite
|
<div id="drop-container" class="">Drop images here (or use the buttons below). Dropping images here will overwrite
|
||||||
existing images in the series. When drag and dropping make sure to drag the first image or the order will not be
|
existing images in the series. When drag and dropping make sure to drag the first image or the order will not be
|
||||||
maintained. Note: dicom images are often not exported in order (although their order can be automatically
|
maintained. Note: dicom images are often not exported in order (although their order can be automatically
|
||||||
detected once uploaded)
|
detected once uploaded)
|
||||||
<div id="single-dicom-viewer" class="dicom-viewer" data-images="" data-annotations=''></div>
|
<div id="single-dicom-viewer" class="dicom-viewer" data-images="" data-annotations=''></div>
|
||||||
<div id="drop-filenames"></div>
|
<div id="drop-filenames"></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="image_form_set" class="sortable">
|
<div id="image_form_set" class="sortable">
|
||||||
{% for form in image_formset %}
|
{% for form in image_formset %}
|
||||||
<ul class="no-error image-formset">
|
<ul class="no-error image-formset">
|
||||||
{{form.non_field_errors}}
|
{{form.non_field_errors}}
|
||||||
{{form.errors}}
|
{{form.errors}}
|
||||||
{{ form.as_ul }}
|
{{ form.as_ul }}
|
||||||
|
</ul>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{{ image_formset.management_form }}
|
||||||
|
<input type="submit" class="submit-button" value="Submit" name="submit">
|
||||||
|
</form>
|
||||||
|
<div id="empty_form" style="display:none">
|
||||||
|
<ul class='no_error image-formset'>
|
||||||
|
{{ image_formset.empty_form.as_ul }}
|
||||||
</ul>
|
</ul>
|
||||||
{% endfor %}
|
|
||||||
</div>
|
</div>
|
||||||
{{ image_formset.management_form }}
|
<div id="images">
|
||||||
<input type="submit" class="submit-button" value="Submit" name="submit">
|
|
||||||
</form>
|
|
||||||
<div id="empty_form" style="display:none">
|
|
||||||
<ul class='no_error image-formset'>
|
|
||||||
{{ image_formset.empty_form.as_ul }}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div id="images">
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -2,19 +2,19 @@
|
|||||||
<div>Description: {{series.description}}</div>
|
<div>Description: {{series.description}}</div>
|
||||||
|
|
||||||
{% if series.case %}
|
{% if series.case %}
|
||||||
Associated case:
|
Associated case:
|
||||||
{% for case in series.case.all %}
|
{% for case in series.case.all %}
|
||||||
<a href="{% url 'atlas:case_detail' pk=case.pk %}">{{case}}</a>
|
<a href="{% url 'atlas:case_detail' pk=case.pk %}">{{case}}</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% else %}
|
{% else %}
|
||||||
This series is not associated with any cases.
|
This series is not associated with any cases.
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<div id="single-dicom-viewer" class="dicom-viewer" data-images="{{ series.get_image_url_array }}" data-annotations=''>
|
<div id="single-dicom-viewer" class="dicom-viewer" data-images="{{ series.get_image_url_array }}" data-annotations=''>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if editing_finding < 1 %}
|
{% if editing_finding < 1 %}
|
||||||
<button id="add-finding-button">Add finding</button>
|
<button id="add-finding-button">Add finding</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<button id="reset-viewport-button">Reset viewport</button>
|
<button id="reset-viewport-button">Reset viewport</button>
|
||||||
<div id="finding-form">
|
<div id="finding-form">
|
||||||
@@ -37,17 +37,17 @@ This series is not associated with any cases.
|
|||||||
<summary>Findings</summary>
|
<summary>Findings</summary>
|
||||||
|
|
||||||
{% for finding in series.findings.all %}
|
{% for finding in series.findings.all %}
|
||||||
<div class="finding-box">
|
<div class="finding-box">
|
||||||
<button class="view-finding-button" data-annotationjson={{finding.annotation_json}}
|
<button class="view-finding-button" data-annotationjson={{finding.annotation_json}}
|
||||||
data-viewportjson={{finding.viewport_json}} data-findingid={{finding.id}}>Click to view</button>
|
data-viewportjson={{finding.viewport_json}} data-findingid={{finding.id}}>Click to view</button>
|
||||||
<span class="view-finding-details">
|
<span class="view-finding-details">
|
||||||
Finding(s): {% for f in finding.findings.all %}{{f.get_link}}{% endfor %}<br />
|
Finding(s): {% for f in finding.findings.all %}{{f.get_link}}{% endfor %}<br />
|
||||||
Structure(s): {% for s in finding.structures.all %}{{s.get_link}}{% endfor %}<br />
|
Structure(s): {% for s in finding.structures.all %}{{s.get_link}}{% endfor %}<br />
|
||||||
Description: {{finding.description}}<br />
|
Description: {{finding.description}}<br />
|
||||||
</span>
|
</span>
|
||||||
<a href="{% url 'atlas:series_edit_finding' pk=series.pk finding_pk=finding.pk %}" class="edit-finding-link">Edit</a>
|
<a href="{% url 'atlas:series_edit_finding' pk=series.pk finding_pk=finding.pk %}" class="edit-finding-link">Edit</a>
|
||||||
<a href="{% url 'atlas:delete_finding' pk=finding.pk %}" class="delete-finding-link">Delete</a>
|
<a href="{% url 'atlas:delete_finding' pk=finding.pk %}" class="delete-finding-link">Delete</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</details>
|
</details>
|
||||||
@@ -67,8 +67,8 @@ This series is not associated with any cases.
|
|||||||
title="orders dicom by uploaded filename">Order by uploaded filename</a>
|
title="orders dicom by uploaded filename">Order by uploaded filename</a>
|
||||||
</div>
|
</div>
|
||||||
{% for image in series.images.all %}
|
{% for image in series.images.all %}
|
||||||
{{image.image.url}}, pos: {{image.position}}, {{image.upload_filename}} [{{image.image.size|filesizeformat}}]<br />
|
{{image.image.url}}, pos: {{image.position}}, {{image.upload_filename}} [{{image.image.size|filesizeformat}}]<br />
|
||||||
{% comment %} {{image.get_dicom_info|safe}}<br /> {% endcomment %}
|
{% comment %} {{image.get_dicom_info|safe}}<br /> {% endcomment %}
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
@@ -118,10 +118,10 @@ This series is not associated with any cases.
|
|||||||
});
|
});
|
||||||
|
|
||||||
{% if editing_finding > 0 %}
|
{% if editing_finding > 0 %}
|
||||||
$("#hidden-form").show()
|
$("#hidden-form").show()
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
$(".view-finding-button[data-findingid={{editing_finding}}]").trigger("click");
|
$(".view-finding-button[data-findingid={{editing_finding}}]").trigger("click");
|
||||||
}, 1000)
|
}, 1000)
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
});
|
});
|
||||||
@@ -153,15 +153,15 @@ This series is not associated with any cases.
|
|||||||
series: {{ series.pk }},
|
series: {{ series.pk }},
|
||||||
//annotation_json: JSON.stringify(c.toolStateManager.saveToolState()),
|
//annotation_json: JSON.stringify(c.toolStateManager.saveToolState()),
|
||||||
annotation_json: JSON.stringify(cornerstoneTools.globalImageIdSpecificToolStateManager
|
annotation_json: JSON.stringify(cornerstoneTools.globalImageIdSpecificToolStateManager
|
||||||
.saveToolState()),
|
.saveToolState()),
|
||||||
viewport_json: JSON.stringify(c.viewport),
|
viewport_json: JSON.stringify(c.viewport),
|
||||||
findings: JSON.stringify($('#finding-form select[name="findings"]').find(":selected")
|
findings: JSON.stringify($('#finding-form select[name="findings"]').find(":selected")
|
||||||
.map((i, el) => {
|
.map((i, el) => {
|
||||||
return $(el).val()
|
return $(el).val()
|
||||||
}).toArray()),
|
}).toArray()),
|
||||||
structures: JSON.stringify($('#finding-form select[name="structures"]').find(
|
structures: JSON.stringify($('#finding-form select[name="structures"]').find(
|
||||||
":selected")
|
":selected")
|
||||||
.map((i, el) => {
|
.map((i, el) => {
|
||||||
return $(el).val()
|
return $(el).val()
|
||||||
}).toArray()),
|
}).toArray()),
|
||||||
csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val(),
|
csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val(),
|
||||||
@@ -174,7 +174,7 @@ This series is not associated with any cases.
|
|||||||
},
|
},
|
||||||
error: function (xhr, errmsg, err) {
|
error: function (xhr, errmsg, err) {
|
||||||
console.log(xhr.status + ": " + xhr
|
console.log(xhr.status + ": " + xhr
|
||||||
.responseText); // provide a bit more info about the error to the console
|
.responseText); // provide a bit more info about the error to the console
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,23 +4,23 @@
|
|||||||
{% block css %}
|
{% block css %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block js %}
|
{% block js %}
|
||||||
<!--<script type="text/javascript" src="/admin/jsi18n/"></script>-->
|
<!--<script type="text/javascript" src="/admin/jsi18n/"></script>-->
|
||||||
{{form.media}}
|
{{form.media}}
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- {{ form.media }} -->
|
<!-- {{ form.media }} -->
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h2>Add/Edit Structure</h2>
|
<h2>Add/Edit Structure</h2>
|
||||||
Use this form to create or edit a structure.
|
Use this form to create or edit a structure.
|
||||||
<form action="" method="post" enctype="multipart/form-data" id="structure-form">
|
<form action="" method="post" enctype="multipart/form-data" id="structure-form">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
{{ form.as_table }}
|
{{ form.as_table }}
|
||||||
</table>
|
</table>
|
||||||
<input type="submit" class="submit-button" value="Submit" name="submit">
|
<input type="submit" class="submit-button" value="Submit" name="submit">
|
||||||
</form>
|
</form>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -1170,11 +1170,14 @@ def collection_mark_question(request, pk, case_number):
|
|||||||
form = CidReportAnswerMarkForm(instance=answer, prefix=answer.pk)
|
form = CidReportAnswerMarkForm(instance=answer, prefix=answer.pk)
|
||||||
answer_forms.append((answer, form))
|
answer_forms.append((answer, form))
|
||||||
|
|
||||||
|
series_list = case.series.all().prefetch_related("images", "examination", "plane")
|
||||||
|
|
||||||
return render(
|
return render(
|
||||||
request,
|
request,
|
||||||
"atlas/collection_mark_question.html",
|
"atlas/collection_mark_question.html",
|
||||||
{
|
{
|
||||||
"collection": collection,
|
"collection": collection,
|
||||||
|
"series_list": series_list,
|
||||||
"answers": answers,
|
"answers": answers,
|
||||||
"case_detail": case_detail,
|
"case_detail": case_detail,
|
||||||
"case": case,
|
"case": case,
|
||||||
|
|||||||
Reference in New Issue
Block a user