Enhance AnatomyQuestion string representation; improve formatting and handle missing attributes for better readability
This commit is contained in:
+10
-8
@@ -132,14 +132,16 @@ class AnatomyQuestion(QuestionBase):
|
||||
return "anatomy"
|
||||
|
||||
def __str__(self):
|
||||
# Get first answer
|
||||
return "{}/{}: {} [{}, {}]".format(
|
||||
self.pk,
|
||||
self.question_type,
|
||||
self.get_primary_answer(),
|
||||
self.modality,
|
||||
self.structure,
|
||||
)
|
||||
# Nicely formatted representation
|
||||
pk = self.pk or ""
|
||||
qtype = str(self.question_type) if self.question_type else "N/A"
|
||||
primary = self.get_primary_answer() or "None"
|
||||
modality = str(self.modality) if self.modality else "Unknown"
|
||||
structure = str(self.structure) if self.structure else "Unknown"
|
||||
title = self.get_title() if hasattr(self, "get_title") else (self.description or "")
|
||||
if title and len(title) > 60:
|
||||
title = title[:57] + "..."
|
||||
return f"{title} (Type: {qtype}) — Answer: {primary} — Modality: {modality}; Structure: {structure}"
|
||||
|
||||
def get_link(self):
|
||||
return format_html("<a href='{}'>{}</a>", self.get_absolute_url(), self)
|
||||
|
||||
@@ -19,62 +19,62 @@
|
||||
<div class="card">
|
||||
<div class="card-body p-2">
|
||||
<ul class="list-group list-group-flush" id="question-mark-list">
|
||||
{% for question, unmarked_count, unmarked_count2 in question_unmarked_map %}
|
||||
<li class="list-group-item d-flex justify-content-between align-items-start" data-unmarked="{{ unmarked_count }}">
|
||||
{% for question, unmarked_count, unmarked_count2 in question_unmarked_map %}
|
||||
<li class="list-group-item d-flex justify-content-between align-items-start" data-unmarked="{{ unmarked_count }}">
|
||||
<div class="me-3">
|
||||
<a href="{% url 'anatomy:mark2' exam_pk=exam.pk sk=forloop.counter0 %}" class="fw-semibold">Question {{ forloop.counter }}:</a>
|
||||
<div class="small text-truncate" style="max-width:60vw;">{{ question }}</div>
|
||||
</div>
|
||||
<div class="text-end">
|
||||
<div class="small text-muted">Unmarked</div>
|
||||
{% if unmarked_count > 0 %}
|
||||
<span class="badge bg-danger">{{ unmarked_count }}</span>
|
||||
{% else %}
|
||||
<span class="badge bg-secondary">{{ unmarked_count }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="text-end">
|
||||
<div class="small text-muted">Unmarked</div>
|
||||
{% if unmarked_count > 0 %}
|
||||
<span class="badge bg-danger">{{ unmarked_count }}</span>
|
||||
{% else %}
|
||||
<span class="badge bg-secondary">{{ unmarked_count }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</li>
|
||||
{% empty %}
|
||||
<li class="list-group-item small text-muted">No questions found.</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function(){
|
||||
function $(sel, ctx){ return (ctx||document).querySelector(sel); }
|
||||
function $all(sel, ctx){ return Array.from((ctx||document).querySelectorAll(sel)); }
|
||||
<script>
|
||||
(function(){
|
||||
function $(sel, ctx){ return (ctx||document).querySelector(sel); }
|
||||
function $all(sel, ctx){ return Array.from((ctx||document).querySelectorAll(sel)); }
|
||||
|
||||
var showAllBtn = $('.show-all-button');
|
||||
var showUnmarkedBtn = $('.show-unmarked-button');
|
||||
var list = $('#question-mark-list');
|
||||
if (!list) return;
|
||||
var showAllBtn = $('.show-all-button');
|
||||
var showUnmarkedBtn = $('.show-unmarked-button');
|
||||
var list = $('#question-mark-list');
|
||||
if (!list) return;
|
||||
|
||||
function showAll(){
|
||||
$all('#question-mark-list .list-group-item').forEach(function(li){ li.classList.remove('d-none'); });
|
||||
showAllBtn && showAllBtn.classList.add('active');
|
||||
showUnmarkedBtn && showUnmarkedBtn.classList.remove('active');
|
||||
}
|
||||
function showAll(){
|
||||
$all('#question-mark-list .list-group-item').forEach(function(li){ li.classList.remove('d-none'); });
|
||||
showAllBtn && showAllBtn.classList.add('active');
|
||||
showUnmarkedBtn && showUnmarkedBtn.classList.remove('active');
|
||||
}
|
||||
|
||||
function showUnmarked(){
|
||||
$all('#question-mark-list .list-group-item').forEach(function(li){
|
||||
var u = parseInt(li.getAttribute('data-unmarked') || '0', 10);
|
||||
if (u > 0) li.classList.remove('d-none'); else li.classList.add('d-none');
|
||||
});
|
||||
showUnmarkedBtn && showUnmarkedBtn.classList.add('active');
|
||||
showAllBtn && showAllBtn.classList.remove('active');
|
||||
}
|
||||
function showUnmarked(){
|
||||
$all('#question-mark-list .list-group-item').forEach(function(li){
|
||||
var u = parseInt(li.getAttribute('data-unmarked') || '0', 10);
|
||||
if (u > 0) li.classList.remove('d-none'); else li.classList.add('d-none');
|
||||
});
|
||||
showUnmarkedBtn && showUnmarkedBtn.classList.add('active');
|
||||
showAllBtn && showAllBtn.classList.remove('active');
|
||||
}
|
||||
|
||||
if (showAllBtn) showAllBtn.addEventListener('click', function(e){ e.preventDefault(); showAll(); });
|
||||
if (showUnmarkedBtn) showUnmarkedBtn.addEventListener('click', function(e){ e.preventDefault(); showUnmarked(); });
|
||||
if (showAllBtn) showAllBtn.addEventListener('click', function(e){ e.preventDefault(); showAll(); });
|
||||
if (showUnmarkedBtn) showUnmarkedBtn.addEventListener('click', function(e){ e.preventDefault(); showUnmarked(); });
|
||||
|
||||
// Initialize to show all
|
||||
showAll();
|
||||
})();
|
||||
</script>
|
||||
<style>
|
||||
.show-all-button.active, .show-unmarked-button.active { box-shadow: inset 0 -2px 0 rgba(0,0,0,0.08); }
|
||||
</style>
|
||||
{% endblock %}
|
||||
showAll();
|
||||
})();
|
||||
</script>
|
||||
<style>
|
||||
.show-all-button.active, .show-unmarked-button.active { box-shadow: inset 0 -2px 0 rgba(0,0,0,0.08); }
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user