Refactor code structure for improved readability and maintainability
This commit is contained in:
@@ -17,11 +17,11 @@
|
||||
data-series-id="{{series.pk}}"
|
||||
aria-label="Open series actions for Series {{ forloop.counter }}">
|
||||
<div class="series-card-thumb-wrap">
|
||||
{% with preview_image=series.images.first %}
|
||||
{% if preview_image and preview_image.image %}
|
||||
<img src="{{ preview_image.image.url }}"
|
||||
alt="Series {{ forloop.counter }} thumbnail"
|
||||
class="series-card-thumb">
|
||||
{% with series_thumbnail=series.get_thumbnail %}
|
||||
{% if series_thumbnail.1 %}
|
||||
<div class="series-card-thumb-generated" aria-label="Series {{ forloop.counter }} thumbnail">
|
||||
{{ series_thumbnail.0|safe }}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="series-card-thumb series-card-thumb-placeholder">
|
||||
<i class="bi bi-image"></i>
|
||||
@@ -565,15 +565,21 @@
|
||||
Remove selected series from case
|
||||
</button>
|
||||
<button hx-post="{% url 'atlas:series_bulk_delete' %}"
|
||||
id="series-delete-selected-btn"
|
||||
title="delete selected series"
|
||||
hx-include="[name='series-ids']:checked"
|
||||
hx-target="#series-action-results"
|
||||
hx-swap="innerHTML"
|
||||
hx-indicator="#series-delete-indicator"
|
||||
hx-confirm="Delete the selected series from the database? This cannot be undone."
|
||||
class="btn btn-sm btn-danger text-start"
|
||||
type="button">
|
||||
Delete selected series
|
||||
</button>
|
||||
<span id="series-delete-indicator" class="htmx-indicator small text-danger">
|
||||
<span class="spinner-border spinner-border-sm me-1" role="status" aria-hidden="true"></span>
|
||||
Deleting...
|
||||
</span>
|
||||
<button type="button"
|
||||
class="btn btn-sm btn-secondary text-start"
|
||||
data-bs-toggle="modal"
|
||||
@@ -836,12 +842,11 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<h5>Resources</h5>
|
||||
|
||||
{% if can_edit%}
|
||||
<div class="mb-2">
|
||||
<div id="resource-search-panel-placeholder">
|
||||
<section class="case-detail-section card mb-3">
|
||||
<div class="card-header d-flex justify-content-between align-items-center flex-wrap gap-2">
|
||||
<h5 class="mb-0">Resources</h5>
|
||||
{% if can_edit %}
|
||||
<div id="resource-search-panel-placeholder" class="d-inline-flex">
|
||||
<button class="btn btn-sm btn-outline-primary"
|
||||
hx-get="{% url 'atlas:resource_search_panel' %}?case_id={{ case.pk }}"
|
||||
hx-target="#resource-search-panel-placeholder"
|
||||
@@ -849,29 +854,35 @@
|
||||
Add Resource
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% include 'atlas/partials/case_resources_list.html' with case=case %}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{% comment %} <p><b>Scrapped:</b> {{ case.scrapped }} <a
|
||||
href="{% url 'atlas:case_scrap' pk=case.pk %}">(toggle)</a> {% endcomment %}
|
||||
|
||||
<div class="atlas-answer">
|
||||
<div class="pre-whitespace">
|
||||
Condition:
|
||||
<ul>
|
||||
{% for con in case.condition.all %}
|
||||
<li>{{con.get_link}}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<div>
|
||||
<section class="case-detail-section card mb-3 atlas-answer">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">Clinical Summary</h5>
|
||||
</div>
|
||||
<div class="card-body pre-whitespace">
|
||||
<div class="mb-3">
|
||||
<strong>Condition:</strong>
|
||||
<ul class="mb-2">
|
||||
{% for con in case.condition.all %}
|
||||
<li>{{con.get_link}}</li>
|
||||
{% empty %}
|
||||
<li class="text-muted">None</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<strong>Procedure(s):</strong>
|
||||
{% if case.procedures.all %}
|
||||
<ul>
|
||||
<ul class="mb-2">
|
||||
{% for proc in case.procedures.all %}
|
||||
<li>{{ proc.get_link }}</li>
|
||||
{% endfor %}
|
||||
@@ -880,43 +891,48 @@
|
||||
<span class="text-muted">None</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
|
||||
<div class="mb-3">
|
||||
{% include 'atlas/partials/_series_findings.html' %}
|
||||
|
||||
{% include 'atlas/partials/_case_displaysets.html' %}
|
||||
</div>
|
||||
{% include 'atlas/partials/_case_differentials.html' %}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<b>Collections:</b>
|
||||
|
||||
{% if can_edit %}
|
||||
<button class="btn btn-sm btn-primary"
|
||||
hx-get="{% url 'atlas:case_collection_form' case.pk %}"
|
||||
hx-target="#collection-form">
|
||||
Add to collection</button>
|
||||
{% endif %}
|
||||
<div id="collection-form"></div>
|
||||
<ul id="case-{{ case.pk }}-collections">
|
||||
{% for collection in case.casecollection_set.all %}
|
||||
<li id="collection-{{ collection.pk }}">
|
||||
<a href="{% url 'atlas:collection_detail' pk=collection.pk %}">{{ collection.name }}</a>
|
||||
{% if can_edit %}
|
||||
<button
|
||||
class="btn btn-sm btn-outline-danger remove-button"
|
||||
hx-post="{% url 'atlas:remove_case_from_collection' case.pk collection.pk %}"
|
||||
hx-target="#collection-{{ collection.pk }}"
|
||||
hx-swap="outerHTML"
|
||||
hx-confirm="Are you sure you want to remove this case from the collection?">
|
||||
Remove
|
||||
</button>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</p>
|
||||
<section class="case-detail-section card mb-3">
|
||||
<div class="card-header d-flex justify-content-between align-items-center flex-wrap gap-2">
|
||||
<h5 class="mb-0">Collections</h5>
|
||||
{% if can_edit %}
|
||||
<button class="btn btn-sm btn-primary"
|
||||
hx-get="{% url 'atlas:case_collection_form' case.pk %}"
|
||||
hx-target="#collection-form">
|
||||
Add to collection
|
||||
</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="collection-form" class="mb-2"></div>
|
||||
<ul id="case-{{ case.pk }}-collections" class="list-group list-group-flush">
|
||||
{% for collection in case.casecollection_set.all %}
|
||||
<li id="collection-{{ collection.pk }}" class="list-group-item d-flex justify-content-between align-items-center flex-wrap gap-2">
|
||||
<a href="{% url 'atlas:collection_detail' pk=collection.pk %}">{{ collection.name }}</a>
|
||||
{% if can_edit %}
|
||||
<button
|
||||
class="btn btn-sm btn-outline-danger remove-button"
|
||||
hx-post="{% url 'atlas:remove_case_from_collection' case.pk collection.pk %}"
|
||||
hx-target="#collection-{{ collection.pk }}"
|
||||
hx-swap="outerHTML"
|
||||
hx-confirm="Are you sure you want to remove this case from the collection?">
|
||||
Remove
|
||||
</button>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% empty %}
|
||||
<li class="list-group-item text-muted">No collections linked.</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
{% if casedetail %}
|
||||
@@ -924,30 +940,45 @@
|
||||
|
||||
{% endif %}
|
||||
|
||||
<section class="case-detail-section card mb-3">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">Linked Cases</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="mb-2"><strong>Previous case:</strong> {{ case.previous_case.get_link }}</p>
|
||||
<p class="mb-0"><strong>Next case:</strong>
|
||||
{% if case.next_case %}
|
||||
{{ case.next_case.get_link }}
|
||||
{% else %}
|
||||
<a href="{% url 'atlas:case_clone_next' case.pk %}">Clone and add next case</a>
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="case-detail-section card mb-3">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">Notes</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% include 'question_notes.html' %}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="case-detail-section card mb-3">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">Case Metadata</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="mb-2"><strong>Checked by:</strong> {% for verified in case.verified.all %} <a
|
||||
href="{% url 'atlas:verified_detail' pk=verified.pk %}">{{verified}}</a>{% if not forloop.last %}, {% endif %}{% empty %}<span class="text-muted">None</span>{% endfor %}</p>
|
||||
|
||||
<p class="pre-whitespace"><b>Previous case:</b> {{ case.previous_case.get_link }}</p>
|
||||
<p class="pre-whitespace"><b>Next case:</b>
|
||||
{% if case.next_case %}
|
||||
{{ case.next_case.get_link }}
|
||||
{% else %}
|
||||
<a href="{% url 'atlas:case_clone_next' case.pk %}">Clone and add next case</a>
|
||||
{% endif %}
|
||||
</p>
|
||||
<div>
|
||||
{% include 'question_notes.html' %}
|
||||
<p class="mb-2"><strong>Author(s):</strong> {% for author in case.author.all %} <a
|
||||
href="{% url 'atlas:author_detail' pk=author.pk %}">{{author}}</a>{% if not forloop.last %}, {% endif %}{% empty %}<span class="text-muted">None</span>{% endfor %}</p>
|
||||
|
||||
</div>
|
||||
|
||||
<p><b>Checked by:</b> {% for verified in case.verified.all %} <a
|
||||
href="{% url 'atlas:verified_detail' pk=verified.pk %}">{{verified}}</a>, {% endfor %}</p>
|
||||
|
||||
<p><b>Author(s):</b> {% for author in case.author.all %} <a
|
||||
href="{% url 'atlas:author_detail' pk=author.pk %}">{{author}}</a>, {% endfor %}</p>
|
||||
|
||||
|
||||
<p><b>Case size:</b> {{ case.get_total_series_images_size | filesizeformat }}</p>
|
||||
<p class="mb-0"><strong>Case size:</strong> {{ case.get_total_series_images_size | filesizeformat }}</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{% include 'atlas/partials/_finding_modal.html' %}
|
||||
<!-- Reorder Series Modal -->
|
||||
@@ -1317,6 +1348,7 @@
|
||||
// Show the alert when a result is received
|
||||
const resultsSpan = document.getElementById("series-action-results");
|
||||
const alertDiv = document.getElementById("series-action-alert");
|
||||
const deleteSelectedSeriesBtn = document.getElementById("series-delete-selected-btn");
|
||||
const observer = new MutationObserver(function(mutations) {
|
||||
if (resultsSpan.textContent.trim() !== "") {
|
||||
alertDiv.style.display = "block";
|
||||
@@ -1326,6 +1358,27 @@
|
||||
});
|
||||
observer.observe(resultsSpan, { childList: true, subtree: true });
|
||||
|
||||
if (deleteSelectedSeriesBtn) {
|
||||
deleteSelectedSeriesBtn.addEventListener("htmx:beforeRequest", function() {
|
||||
deleteSelectedSeriesBtn.disabled = true;
|
||||
alertDiv.classList.remove("alert-success", "alert-danger");
|
||||
alertDiv.classList.add("alert-info");
|
||||
resultsSpan.textContent = "Deleting selected series...";
|
||||
alertDiv.style.display = "block";
|
||||
});
|
||||
|
||||
deleteSelectedSeriesBtn.addEventListener("htmx:afterRequest", function(evt) {
|
||||
deleteSelectedSeriesBtn.disabled = false;
|
||||
const status = evt.detail && evt.detail.xhr ? evt.detail.xhr.status : 0;
|
||||
alertDiv.classList.remove("alert-info", "alert-success", "alert-danger");
|
||||
if (status >= 200 && status < 300) {
|
||||
alertDiv.classList.add("alert-success");
|
||||
} else {
|
||||
alertDiv.classList.add("alert-danger");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Listen for toggle events on the <details> element
|
||||
if (detailsElement) {
|
||||
detailsElement.addEventListener("toggle", toggleCheckboxes);
|
||||
@@ -1835,6 +1888,22 @@
|
||||
display: block;
|
||||
background: rgba(255,255,255,0.04);
|
||||
}
|
||||
.series-card-thumb-generated,
|
||||
.series-card-thumb-generated span {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
border-radius: 0.4rem;
|
||||
overflow: hidden;
|
||||
border: 1px solid rgba(255,255,255,0.1);
|
||||
background: rgba(255,255,255,0.04);
|
||||
}
|
||||
.series-card-thumb-generated img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
}
|
||||
.series-card-thumb-placeholder {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -1934,6 +2003,31 @@
|
||||
vertical-align: middle;
|
||||
text-align: left;
|
||||
}
|
||||
#series-delete-indicator {
|
||||
display: none;
|
||||
}
|
||||
#series-delete-indicator.htmx-request {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
.case-detail-section {
|
||||
border: 1px solid rgba(255,255,255,0.08);
|
||||
background: rgba(255,255,255,0.02);
|
||||
}
|
||||
.case-detail-section .card-header {
|
||||
background: rgba(255,255,255,0.03);
|
||||
border-bottom: 1px solid rgba(255,255,255,0.08);
|
||||
}
|
||||
.case-detail-section .card-body {
|
||||
overflow-x: auto;
|
||||
}
|
||||
.case-detail-section .list-group-item {
|
||||
background: transparent;
|
||||
border-color: rgba(255,255,255,0.08);
|
||||
}
|
||||
.case-detail-section table {
|
||||
width: 100%;
|
||||
}
|
||||
@media (max-width: 991.98px) {
|
||||
.series-toolbar {
|
||||
flex-direction: column;
|
||||
@@ -1941,6 +2035,12 @@
|
||||
.series-toolbar-btn {
|
||||
width: 100%;
|
||||
}
|
||||
.case-detail-section .card-header {
|
||||
padding: .65rem .85rem;
|
||||
}
|
||||
.case-detail-section .card-body {
|
||||
padding: .75rem .85rem;
|
||||
}
|
||||
}
|
||||
@media (max-width: 575.98px) {
|
||||
.series-block {
|
||||
|
||||
+187
-187
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user