Add skip and next buttons to question review with corresponding JavaScript functionality
This commit is contained in:
@@ -3073,6 +3073,13 @@ class GenericViewBase:
|
|||||||
# Read filters
|
# Read filters
|
||||||
category = request.POST.get("category") or request.GET.get("category")
|
category = request.POST.get("category") or request.GET.get("category")
|
||||||
status = request.POST.get("status") or request.GET.get("status") or "ANY"
|
status = request.POST.get("status") or request.GET.get("status") or "ANY"
|
||||||
|
# How many matching questions to skip (useful for Skip button). Expected integer >= 0.
|
||||||
|
try:
|
||||||
|
skip = int(request.POST.get("skip") or request.GET.get("skip") or 0)
|
||||||
|
if skip < 0:
|
||||||
|
skip = 0
|
||||||
|
except Exception:
|
||||||
|
skip = 0
|
||||||
|
|
||||||
# Build base queryset of questions for this app
|
# Build base queryset of questions for this app
|
||||||
qs = self.question_object.objects.all().order_by("pk")
|
qs = self.question_object.objects.all().order_by("pk")
|
||||||
@@ -3120,6 +3127,10 @@ class GenericViewBase:
|
|||||||
match = True
|
match = True
|
||||||
|
|
||||||
if match:
|
if match:
|
||||||
|
# If caller asked us to skip N matches, decrement and continue until skip==0
|
||||||
|
if skip and skip > 0:
|
||||||
|
skip -= 1
|
||||||
|
continue
|
||||||
|
|
||||||
form = QuestionReviewForm()
|
form = QuestionReviewForm()
|
||||||
return render(request, f"{self.app_name}/question_review_question.html", {"question": question, "form": form, "app_name": self.app_name, "filters": {"category": category, "status": status}})
|
return render(request, f"{self.app_name}/question_review_question.html", {"question": question, "form": form, "app_name": self.app_name, "filters": {"category": category, "status": status}})
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
</a>
|
</a>
|
||||||
<ul class="dropdown-menu" aria-labelledby="sbasQuestionsDropdown">
|
<ul class="dropdown-menu" aria-labelledby="sbasQuestionsDropdown">
|
||||||
<li><a class="dropdown-item" href="{% url 'sbas:question_view' %}"><i class="bi bi-list-ul"></i> All Questions</a></li>
|
<li><a class="dropdown-item" href="{% url 'sbas:question_view' %}"><i class="bi bi-list-ul"></i> All Questions</a></li>
|
||||||
<li><a class="dropdown-item" href="{% url 'sbas:question_review_start' %}"><i class="bi bi-list-ul"></i> Review Questions</a></li>
|
<li><a class="dropdown-item" href="{% url 'sbas:question_review_start' %}"><i class="bi bi-bookmarks-fill"></i> Review Questions</a></li>
|
||||||
<!-- Additional items can be added here -->
|
<!-- Additional items can be added here -->
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -117,6 +117,48 @@
|
|||||||
{% comment %} The included partial contains its own <form> with hx-post. Do not wrap it in another form (nested forms break submission). {% endcomment %}
|
{% comment %} The included partial contains its own <form> with hx-post. Do not wrap it in another form (nested forms break submission). {% endcomment %}
|
||||||
{% include 'generic/partials/question_review_form.html' with app_name='sbas' question=question form=form %}
|
{% include 'generic/partials/question_review_form.html' with app_name='sbas' question=question form=form %}
|
||||||
|
|
||||||
|
<div class="d-flex gap-2 mt-3">
|
||||||
|
{# Skip increments a 'skip' query param used by the view to skip matching questions #}
|
||||||
|
<button id="review-skip-btn" type="button" class="btn btn-outline-secondary">Skip</button>
|
||||||
|
|
||||||
|
{# Next should only be enabled after a successful Save (server will send HX-Trigger 'reviewSaved') #}
|
||||||
|
<button id="review-next-btn" type="button" class="btn btn-primary" disabled>Next</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
(function(){
|
||||||
|
const nextBtn = document.getElementById('review-next-btn');
|
||||||
|
|
||||||
|
// Listen for the server-triggered event 'reviewSaved' (sent via HX-Trigger header).
|
||||||
|
// HTMX will dispatch a DOM event with the same name when it receives the header.
|
||||||
|
document.addEventListener('reviewSaved', function(){
|
||||||
|
nextBtn.disabled = false;
|
||||||
|
skipBtn.disabled = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Navigate to the review-next endpoint without query parameters
|
||||||
|
nextBtn.addEventListener('click', function(){
|
||||||
|
const base = "{% url app_name|add:':question_review_next' %}";
|
||||||
|
window.location.href = base;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Skip: increment 'skip' query param (defaults to 1) and include current filters
|
||||||
|
const skipBtn = document.getElementById('review-skip-btn');
|
||||||
|
skipBtn.addEventListener('click', function(){
|
||||||
|
const base = "{% url app_name|add:':question_review_next' %}";
|
||||||
|
// read existing skip from current URL (if present) and increment
|
||||||
|
const curParams = new URLSearchParams(window.location.search);
|
||||||
|
let curSkip = parseInt(curParams.get('skip') || '0', 10) || 0;
|
||||||
|
const newSkip = curSkip + 1;
|
||||||
|
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
params.set('skip', String(newSkip));
|
||||||
|
|
||||||
|
window.location.href = base + '?' + params.toString();
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
|
||||||
<div id="question-review-block" class="mt-4">
|
<div id="question-review-block" class="mt-4">
|
||||||
{# Placeholder while HTMX fetches review/block #}
|
{# Placeholder while HTMX fetches review/block #}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user