Files
penracourses/rapids/templates/rapids/question_display_block.html
T

423 lines
16 KiB
HTML
Executable File

<div class="rapid {% if question.scrapped %}rapid-scrapped{% endif %}">
{% comment %} <button id="edit-button">Inline Edit</button> {% endcomment %}
<div class="date">
{{ question.created_date|date:"d/m/Y" }}
</div>
<div class="id">
ID: {{ question.id }}
</div>
<p class="pre-whitespace"><b>Rapid:</b> {{ question }}</p>
<p class="pre-whitespace"><b>Normal:</b> {{ question.normal }} <button id="toggle-normal-button"
class="toggle-button">toggle</button></p>
<p class="pre-whitespace"><b>Region:</b> {{ question.get_regions }}</p>
<p class="pre-whitespace"><b>Examination:</b> {{ question.get_examinations }}</p>
<p class="pre-whitespace"><b>Laterality:</b> {{ question.laterality }}
<button class="toggle-laterality-button toggle-button" data-lat="LEFT">Left</button>
<button class="toggle-laterality-button toggle-button" data-lat="RIGHT">Right</button>
<button class="toggle-laterality-button toggle-button" data-lat="BILAT">Bilateral</button>
<button class="toggle-laterality-button toggle-button" data-lat="NONE">None</button>
</p>
<p class="pre-whitespace"><b>Abnormality:</b> {{ question.get_abnormalities }}</p>
<div class="pre-whitespace multi-image-block"><b>Images:</b>
{% for image in question.images.all %}
<span class="image-block">
Image {{ forloop.counter }}{% if image.description %} ({{image.description}}){% endif %}{% if image.feedback_image %} [feedback image]{% endif %}:
<div class="dicom-image-legacy rapid-img {% if image.feedback_image %}feedback-img{% endif %}"
data-url="https://www.penracourses.org.uk{{ image.image.url}}"></div>
</span>
{% endfor %}
</div>
<div>
Exam(s): {% for exam in question.exams.all %}
<a href="{% url 'rapids:exam_overview' pk=exam.pk %}">{{ exam }}</a>,
{% endfor %}
<button class="btn btn-sm" hx-get="{% url 'rapids:question_add_exam' question_id=question.pk %}"
hx-target="#exam-list"
hx-swap="innerHTML">Edit exam(s)</button>
<span id="exam-list"></span>
{% comment %} <button id="add-to-exam" data-exam_json_edit_url="{% url 'generic:generic_exam_json_edit' %}"
data-exam_list_url="{% url 'api-1:rapid_user_exams' %}" data-type="rapids" data-csrf="{{ csrf_token}}"
data-qid="{{question.pk}}">Add to exam</button>
<button id="cancel-add-to-exam" style="display:none">Cancel</button>
<span id="exam-options"></span> {% endcomment %}
</div>
<p class="pre-whitespace"><b>Open Access:</b> {{ question.open_access }}</p>
<p class="pre-whitespace"><b>Feedback:</b> {{ question.feedback }}</p>
<p class="pre-whitespace"><b>History:</b> {{ question.history }}</p>
<p><b>Author(s):</b> {% for author in question.author.all %} <a
href="{% url 'rapids:author_detail' pk=author.pk %}">{{author}}</a>, {% endfor %}</p>
<p><b>Checked by:</b> {% for verified in question.verified.all %} <a
href="{% url 'rapids:verified_detail' pk=verified.pk %}">{{verified}}</a>, {% endfor %}</p>
{% comment %} <p><b>Scrapped:</b> {{ question.scrapped }} <a
href="{% url 'rapids:rapid_scrap' pk=question.pk %}">(toggle)</a></p> {% endcomment %}
<p class="pre-whitespace">
<details>
<summary>
Answers:
</summary>
<table>
<tr><th>Answer</th><th>Score</th></tr>
{% for answer in question.answers.all|dictsortreversed:"status" %}
<tr>
<td>
<span {% if answer.proposed %}class="proposed-answer" data-aid="{{answer.pk}}" data-question-type="rapid"
{% endif %}>
{{ answer }}
</span>
</td>
<td>{{answer.status}}</td>
</tr>
{% endfor %}
</table>
</details>
</p>
</div>
<div>
{% if view_feedback %}
{% include 'question_notes.html' %}
{% if not question.normal %}
<details>
<summary>
Suggested answers
</summary>
<ul class="suggested_answers">
{% for ans in question.get_suggested_answers %}
<li data-string="{{ans}}">{{ans}}</li>
{% endfor %}
</ul>
</details>
{% endif %}
{% endif %}
</div>
<details open>
<summary>
Image viewer
</summary>
<div id="single-dicom-viewer" class="dicom-viewer" data-images="{{ question.get_image_url_array }}"
data-annotations='{{question.get_image_annotations}}'>
</div>
<button id="save-annotations" class="save-rapid-annotations">Save Annotations</button>
</details>
<details>
<summary>
Image annotations:
</summary>
{% for image in question.images.all %}
<span class="image-block">
Image {{ forloop.counter }}: {{image.image_annotations}}<br />
</span>
{% endfor %}
</details>
<a href="{% url 'rapids:question_anonymise_dicom' pk=question.pk %}"
title="Anonymise dicom images">Anonymise dicoms</a><br />
<script>
$(document).ready(function () {
$("#edit-button").click(() => {
$(".toggle-button").toggle();
});
$(".toggle-button").hide();
// send request to change the is_private state on customSwitches toggle
$("#save-annotations").click(function () {
let el = $(".cornerstone-element").get(0);
let c = cornerstone.getEnabledElement(el);
let toolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager;
//let image_id = c.image.imageId;
let toolstate = toolStateManager.saveToolState();
let images = JSON.parse(document.getElementById("single-dicom-viewer").dataset.images);
let json_toolstates = [];
for (const image of images) {
json_toolstates.push(JSON.stringify(toolstate[image]));
}
console.log("json_toolstates", json_toolstates)
$.ajax({
url: "{% url 'rapids:question_save_annotation' pk=question.pk %}",
data: {
csrfmiddlewaretoken: "{{ csrf_token }}",
// Yes we do double encode the json....
annotation: JSON.stringify(json_toolstates),
},
type: "POST",
dataType: "json",
error: function (e) {
toastr.warning(`Error saving annotations`)
console.log(e);
},
})
// $.ajax().done(), $.ajax().fail(), $ajax().always() are upto you. Add/change accordingly
.done(function (data) {
console.log(data);
// show some message according to the response.
// For eg. A message box showing that the status has been changed
if (data.status == "success") {
toastr.info('Annotations saved')
} else {
toastr.warning('Error saving annotations')
}
})
.always(function () {
console.log('[Done]');
})
})
{% comment %} $("#cancel-add-to-exam").click(function (evt) {
$("#add-to-exam").toggle();
$("#cancel-add-to-exam").toggle();
$("#exam-options").empty();
})
$("#add-to-exam").click(function (evt) {
$("#add-to-exam").toggle();
$("#cancel-add-to-exam").toggle();
var jqxhr = $.get(evt.target.dataset.exam_list_url, function (data) {
console.log(data);
$("#exam-options").empty();
data.forEach((obj, n) => {
$("#exam-options").append($(document.createElement('button')).prop({
type: 'button',
innerHTML: obj.name,
class: '',
}).data("exam-id", obj.id).click((evt) => {
addToExam(evt)
}))
})
})
.done(function () {
//alert( "second success" );
})
.fail(function () {
//alert( "error" );
})
.always(function () {
//alert( "finished" );
});
return;
function addToExam(evt) {
let exam_button = document.getElementById("add-to-exam");
let ids = [];
ids.push(exam_button.dataset.qid);
// if no question selected
if (ids.length < 1) {
toastr.info('No question selected.');
return
}
let post_url = exam_button.dataset.exam_json_edit_url;
let type = exam_button.dataset.type;
let csrf = exam_button.dataset.csrf;
$.ajax({
url: post_url,
data: {
csrfmiddlewaretoken: csrf,
add_exam_questions: JSON.stringify(ids),
type: type,
exam_id: $(evt.target).data("exam-id"),
},
type: "POST",
dataType: "json",
})
// $.ajax().done(), $.ajax().fail(), $ajax().always() are upto you. Add/change accordingly
.done(function (data) {
console.log(data);
if (data.status == "success") {
toastr.info('Questions added to exams.')
}
})
.always(function () {
console.log('[Done]');
$("#exam-options").empty();
})
}
});
//var $crf_token = $('[name="csrfmiddlewaretoken"]').attr('value');
/* beautify ignore:start */
n = !{{ question.normal | lower }}
/* beautify ignore:end */
$("#toggle-normal-button").click(function () {
$.ajax({
url: "{% url 'rapid-detail' question.id %}",
type: 'PATCH',
headers: {
"X-CSRFToken": "{{ csrf_token }}"
},
timeout: 3000,
data: {
csrfmiddlewaretoken: "{{ csrf_token }}",
normal: n,
}
})
.done(function (data) {
console.log(data);
toastr.info('Answer updated')
})
.fail(function () {
alert('Error updating this model instance.');
});
});
$(".toggle-laterality-button").each((n, el) => {
$(el).click(function () {
$.ajax({
url: "{% url 'rapid-detail' question.id %}",
type: 'PATCH',
headers: {
"X-CSRFToken": "{{ csrf_token }}"
},
timeout: 3000,
data: {
csrfmiddlewaretoken: "{{ csrf_token }}",
laterality: el.dataset.lat,
}
})
.done(function (data) {
console.log(data);
toastr.info('Answer updated')
})
.fail(function () {
alert('Error updating this model instance.');
});
});
});
{% endcomment %}
$(".suggested_answers li").each((n, el) => {
$(el).append($("<span class='correct'>[Add Correct]</span>").on("click", function () {
$.ajax({
url: "{% url 'answer_submit' %}",
data: {
csrfmiddlewaretoken: "{{ csrf_token }}",
//active: this.checked // true if checked else false
question_type: "rapid",
qid: "{{question.pk}}",
status: 2,
answer: el.dataset.string,
},
type: "POST",
dataType: "json",
})
// $.ajax().done(), $.ajax().fail(), $ajax().always() are upto you. Add/change accordingly
.done(function (data) {
console.log(data);
if (data.success) {
toastr.info('Answer saved')
$(el).find(".correct").remove()
}
// show some message according to the response.
// For eg. A message box showing that the status has been changed
})
.always(function () {
console.log('[Done]');
})
}))
});
// send request to change the is_private state on customSwitches toggle
$(".proposed-answer").each((n, el) => {
// Add button to confirm answer is correct
$(el).append($("<span class='confirm'>[Add Correct]</span>").on("click", function () {
$.ajax({
url: "{% url 'answer_suggestion_confirm' %}",
data: {
csrfmiddlewaretoken: "{{ csrf_token }}",
//active: this.checked // true if checked else false
question_type: "rapid",
aid: el.dataset.aid,
status: 2,
},
type: "POST",
dataType: "json",
})
// $.ajax().done(), $.ajax().fail(), $ajax().always() are upto you. Add/change accordingly
.done(function (data) {
console.log(data);
if (data.success) {
toastr.info('Answer saved')
$(el).find(".confirm").remove()
$(el).removeClass("proposed-answer")
}
// show some message according to the response.
// For eg. A message box showing that the status has been changed
})
.always(function () {
console.log('[Done]');
})
}))
// Add button to confirm answer is incorrect
$(el).append($("<span class='confirm'>[Incorrect]</span>").on("click", function () {
$.ajax({
url: "{% url 'answer_suggestion_confirm' %}",
data: {
csrfmiddlewaretoken: "{{ csrf_token }}",
//active: this.checked // true if checked else false
question_type: "rapid",
aid: el.dataset.aid,
status: 0,
},
type: "POST",
dataType: "json",
})
// $.ajax().done(), $.ajax().fail(), $ajax().always() are upto you. Add/change accordingly
.done(function (data) {
console.log(data);
if (data.success) {
toastr.info('Answer saved')
$(el).find(".confirm").remove()
$(el).removeClass("proposed-answer")
}
// show some message according to the response.
// For eg. A message box showing that the status has been changed
})
.always(function () {
console.log('[Done]');
})
}))
});
});
</script>
<style>
.toggle-button {
font-size: x-small;
opacity: 30%;
}
.toggle-button:hover {
font-size: x-small;
opacity: 100%;
}
#cancel-add-to-exam {
border-style: dashed;
}
#cancel-add-to-exam:hover {
background-color: purple;
}
</style>