Enhance exam status management with HTMX loading indicators and streamline AJAX handling by removing legacy jQuery code
This commit is contained in:
@@ -32,7 +32,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body p-2" hx-get="{% url 'generic:exam_collection_exams_partial' object.pk 'anatomy' %}" hx-trigger="revealed" hx-swap="innerHTML">
|
<div class="card-body p-2" hx-get="{% url 'generic:exam_collection_exams_partial' object.pk 'anatomy' %}" hx-trigger="revealed" hx-swap="innerHTML">
|
||||||
<div class="placeholder small text-muted">Loading anatomy exams…</div>
|
<div class="d-flex align-items-center">
|
||||||
|
<div class="placeholder small text-muted">Loading anatomy exams…</div>
|
||||||
|
<div class="exam-loading ms-2 d-none"><span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-footer add-marker small"></div>
|
<div class="card-footer add-marker small"></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -48,7 +51,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body p-2" hx-get="{% url 'generic:exam_collection_exams_partial' object.pk 'longs' %}" hx-trigger="revealed" hx-swap="innerHTML">
|
<div class="card-body p-2" hx-get="{% url 'generic:exam_collection_exams_partial' object.pk 'longs' %}" hx-trigger="revealed" hx-swap="innerHTML">
|
||||||
<div class="placeholder small text-muted">Loading longs exams…</div>
|
<div class="d-flex align-items-center">
|
||||||
|
<div class="placeholder small text-muted">Loading longs exams…</div>
|
||||||
|
<div class="exam-loading ms-2 d-none"><span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-footer add-marker small"></div>
|
<div class="card-footer add-marker small"></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -64,7 +70,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body p-2" hx-get="{% url 'generic:exam_collection_exams_partial' object.pk 'rapids' %}" hx-trigger="revealed" hx-swap="innerHTML">
|
<div class="card-body p-2" hx-get="{% url 'generic:exam_collection_exams_partial' object.pk 'rapids' %}" hx-trigger="revealed" hx-swap="innerHTML">
|
||||||
<div class="placeholder small text-muted">Loading rapids exams…</div>
|
<div class="d-flex align-items-center">
|
||||||
|
<div class="placeholder small text-muted">Loading rapids exams…</div>
|
||||||
|
<div class="exam-loading ms-2 d-none"><span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-footer add-marker small"></div>
|
<div class="card-footer add-marker small"></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -80,7 +89,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body p-2" hx-get="{% url 'generic:exam_collection_exams_partial' object.pk 'shorts' %}" hx-trigger="revealed" hx-swap="innerHTML">
|
<div class="card-body p-2" hx-get="{% url 'generic:exam_collection_exams_partial' object.pk 'shorts' %}" hx-trigger="revealed" hx-swap="innerHTML">
|
||||||
<div class="placeholder small text-muted">Loading shorts exams…</div>
|
<div class="d-flex align-items-center">
|
||||||
|
<div class="placeholder small text-muted">Loading shorts exams…</div>
|
||||||
|
<div class="exam-loading ms-2 d-none"><span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-footer add-marker small"></div>
|
<div class="card-footer add-marker small"></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -93,7 +105,10 @@
|
|||||||
<a class="btn btn-sm btn-outline-secondary" href="{% url 'physics:exam_list_collection' object.pk %}">View exam list</a>
|
<a class="btn btn-sm btn-outline-secondary" href="{% url 'physics:exam_list_collection' object.pk %}">View exam list</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body p-2" hx-get="{% url 'generic:exam_collection_exams_partial' object.pk 'physics' %}" hx-trigger="revealed" hx-swap="innerHTML">
|
<div class="card-body p-2" hx-get="{% url 'generic:exam_collection_exams_partial' object.pk 'physics' %}" hx-trigger="revealed" hx-swap="innerHTML">
|
||||||
<div class="placeholder small text-muted">Loading physics exams…</div>
|
<div class="d-flex align-items-center">
|
||||||
|
<div class="placeholder small text-muted">Loading physics exams…</div>
|
||||||
|
<div class="exam-loading ms-2 d-none"><span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -105,7 +120,10 @@
|
|||||||
<a class="btn btn-sm btn-outline-secondary" href="{% url 'sbas:exam_list_collection' object.pk %}">View exam list</a>
|
<a class="btn btn-sm btn-outline-secondary" href="{% url 'sbas:exam_list_collection' object.pk %}">View exam list</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body p-2" hx-get="{% url 'generic:exam_collection_exams_partial' object.pk 'sbas' %}" hx-trigger="revealed" hx-swap="innerHTML">
|
<div class="card-body p-2" hx-get="{% url 'generic:exam_collection_exams_partial' object.pk 'sbas' %}" hx-trigger="revealed" hx-swap="innerHTML">
|
||||||
<div class="placeholder small text-muted">Loading SBAs exams…</div>
|
<div class="d-flex align-items-center">
|
||||||
|
<div class="placeholder small text-muted">Loading SBAs exams…</div>
|
||||||
|
<div class="exam-loading ms-2 d-none"><span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
{% partialdef publish-results %}
|
{% partialdef publish-results %}
|
||||||
<div id="publish-results-status" class="d-flex align-items-center gap-2">
|
<div id="publish-results-status" class="d-flex align-items-center gap-2">
|
||||||
<div class="me-2 small text-muted">Publish results</div>
|
<div class="me-2 small text-muted">Results</div>
|
||||||
<div>
|
<div>
|
||||||
{% if exam.publish_results %}
|
{% if exam.publish_results %}
|
||||||
<button
|
<button
|
||||||
class="btn btn-sm btn-success"
|
class="btn btn-sm btn-success published-icon"
|
||||||
hx-post="{% url exam.get_app_name|add:':exam_toggle_results_published' exam.pk %}"
|
hx-post="{% url exam.get_app_name|add:':exam_toggle_results_published' exam.pk %}"
|
||||||
hx-swap="outerHTML"
|
hx-swap="outerHTML"
|
||||||
hx-target="#publish-results-status"
|
hx-target="#publish-results-status"
|
||||||
@@ -15,9 +15,10 @@
|
|||||||
hx-disabled-elt="this"
|
hx-disabled-elt="this"
|
||||||
|
|
||||||
>Published</button>
|
>Published</button>
|
||||||
|
<span class="exam-loading ms-2 d-none"><span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span></span>
|
||||||
{% else %}
|
{% else %}
|
||||||
<button
|
<button
|
||||||
class="btn btn-sm btn-secondary"
|
class="btn btn-sm btn-secondary published-icon"
|
||||||
hx-post="{% url exam.get_app_name|add:':exam_toggle_results_published' exam.pk %}"
|
hx-post="{% url exam.get_app_name|add:':exam_toggle_results_published' exam.pk %}"
|
||||||
hx-swap="outerHTML"
|
hx-swap="outerHTML"
|
||||||
hx-target="#publish-results-status"
|
hx-target="#publish-results-status"
|
||||||
@@ -25,6 +26,7 @@
|
|||||||
aria-label="Publish results"
|
aria-label="Publish results"
|
||||||
hx-disabled-elt="this"
|
hx-disabled-elt="this"
|
||||||
>Unpublished</button>
|
>Unpublished</button>
|
||||||
|
<span class="exam-loading ms-2 d-none"><span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span></span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -33,11 +35,11 @@
|
|||||||
|
|
||||||
{% partialdef exam-active %}
|
{% partialdef exam-active %}
|
||||||
<div id="exam-active-status" class="d-flex align-items-center gap-2">
|
<div id="exam-active-status" class="d-flex align-items-center gap-2">
|
||||||
<div class="me-2 small text-muted">Exam active</div>
|
<div class="me-2 small text-muted">Exam status:</div>
|
||||||
<div>
|
<div>
|
||||||
{% if exam.active %}
|
{% if exam.active %}
|
||||||
<button
|
<button
|
||||||
class="btn btn-sm btn-success"
|
class="btn btn-sm btn-success active-icon"
|
||||||
hx-post="{% url exam.get_app_name|add:':exam_toggle_active' exam.pk %}"
|
hx-post="{% url exam.get_app_name|add:':exam_toggle_active' exam.pk %}"
|
||||||
hx-swap="outerHTML"
|
hx-swap="outerHTML"
|
||||||
hx-target="#exam-active-status"
|
hx-target="#exam-active-status"
|
||||||
@@ -45,9 +47,10 @@
|
|||||||
aria-label="Deactivate exam"
|
aria-label="Deactivate exam"
|
||||||
hx-disabled-elt="this"
|
hx-disabled-elt="this"
|
||||||
>Active</button>
|
>Active</button>
|
||||||
|
<span class="exam-loading ms-2 d-none"><span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span></span>
|
||||||
{% else %}
|
{% else %}
|
||||||
<button
|
<button
|
||||||
class="btn btn-sm btn-secondary"
|
class="btn btn-sm btn-secondary active-icon"
|
||||||
hx-post="{% url exam.get_app_name|add:':exam_toggle_active' exam.pk %}"
|
hx-post="{% url exam.get_app_name|add:':exam_toggle_active' exam.pk %}"
|
||||||
hx-swap="outerHTML"
|
hx-swap="outerHTML"
|
||||||
hx-target="#exam-active-status"
|
hx-target="#exam-active-status"
|
||||||
@@ -55,7 +58,36 @@
|
|||||||
aria-label="Activate exam"
|
aria-label="Activate exam"
|
||||||
hx-disabled-elt="this"
|
hx-disabled-elt="this"
|
||||||
>Inactive</button>
|
>Inactive</button>
|
||||||
|
<span class="exam-loading ms-2 d-none"><span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span></span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endpartialdef exam-active %}
|
{% endpartialdef exam-active %}
|
||||||
|
|
||||||
|
{% partialdef exam-archived %}
|
||||||
|
<div id="exam-archived-status" class="d-flex align-items-center gap-2">
|
||||||
|
<div>
|
||||||
|
{% if exam.archive %}
|
||||||
|
<button
|
||||||
|
class="btn btn-sm btn-warning archived-icon"
|
||||||
|
hx-post="{% url exam.get_app_name|add:':exam_toggle_archived' exam.pk %}"
|
||||||
|
hx-swap="outerHTML"
|
||||||
|
hx-target="#exam-archived-status"
|
||||||
|
title="Click to unarchive this exam"
|
||||||
|
aria-label="Unarchive exam"
|
||||||
|
><i class="bi bi-archive"></i></button>
|
||||||
|
<span class="exam-loading ms-2 d-none"><span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span></span>
|
||||||
|
{% else %}
|
||||||
|
<button
|
||||||
|
class="btn btn-sm btn-secondary archived-icon"
|
||||||
|
hx-post="{% url exam.get_app_name|add:':exam_toggle_archived' exam.pk %}"
|
||||||
|
hx-swap="outerHTML"
|
||||||
|
hx-target="#exam-archived-status"
|
||||||
|
title="Click to archive this exam"
|
||||||
|
aria-label="Archive exam"
|
||||||
|
><i class="bi bi-archive"></i></button>
|
||||||
|
<span class="exam-loading ms-2 d-none"><span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span></span>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endpartialdef %}
|
||||||
+18
-2
@@ -1112,9 +1112,25 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
|
|
||||||
exam = get_object_or_404(self.Exam, pk=pk)
|
exam = get_object_or_404(self.Exam, pk=pk)
|
||||||
|
|
||||||
exam.archive = True if request.POST.get("archive") == "true" else False
|
# Support both legacy JSON POSTs and HTMX button toggles.
|
||||||
print(f"{exam.archive=}")
|
# If this is an HTMX request, toggle the archive flag and
|
||||||
|
# return the `exam-archived` partial for in-place replacement.
|
||||||
|
is_htmx = request.headers.get("HX-Request") == "true"
|
||||||
|
if is_htmx:
|
||||||
|
exam.archive = not exam.archive
|
||||||
|
else:
|
||||||
|
# Legacy POST expects 'archive' == 'true'
|
||||||
|
exam.archive = True if request.POST.get("archive") == "true" else False
|
||||||
|
|
||||||
exam.save()
|
exam.save()
|
||||||
|
|
||||||
|
if is_htmx:
|
||||||
|
return render(
|
||||||
|
request,
|
||||||
|
"generic/partials/exams/exam_status.html#exam-archived",
|
||||||
|
{"exam": exam, "collection": exam},
|
||||||
|
)
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
"status": "success",
|
"status": "success",
|
||||||
"archive": exam.archive,
|
"archive": exam.archive,
|
||||||
|
|||||||
+28
-17
@@ -33,17 +33,20 @@
|
|||||||
{% else %}
|
{% else %}
|
||||||
{{ exam.valid_user_users.count }}
|
{{ exam.valid_user_users.count }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
]</span>
|
]</span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<a href="{% url app_name|add:':exam_scores_all' pk=exam.pk %}" class="flex-col-half">Scores</a>
|
<a href="{% url app_name|add:':exam_scores_all' pk=exam.pk %}" class="flex-col-half">Scores</a>
|
||||||
<input type="checkbox" id="active-{{exam.pk}}" class="exam-active-switch" data-posturl="{% url app_name|add:':exam_toggle_active' pk=exam.pk %}" {% if exam.active %}checked{% endif %}>
|
<span class="flex-col">
|
||||||
<label for="active-{{exam.pk}}" class="flex-col icon-container active-icon" title="Click to toggle active state">Exam Active</label>
|
{% include "generic/partials/exams/exam_status.html#exam-active" %}
|
||||||
<input type="checkbox" id="published-{{exam.pk}}" class="exam-publish-results-switch" data-posturl="{% url app_name|add:':exam_toggle_results_published' pk=exam.pk %}" {% if exam.publish_results %}checked{% endif %}>
|
</span>
|
||||||
<label for="published-{{exam.pk}}" class="flex-col icon-container published-icon" title="Click to toggle published state">Results Published</label>
|
<span class="flex-col">
|
||||||
|
{% include "generic/partials/exams/exam_status.html#publish-results" %}
|
||||||
|
</span>
|
||||||
<a href="{% url app_name|add:':exam_update' pk=exam.pk %}" class="flex-shrink exam-list-edit-button"><i class="bi bi-pencil-square"></i></a>
|
<a href="{% url app_name|add:':exam_update' pk=exam.pk %}" class="flex-shrink exam-list-edit-button"><i class="bi bi-pencil-square"></i></a>
|
||||||
<input type="checkbox" id="archived-{{exam.pk}}" class="exam-archived-switch" data-posturl="{% url app_name|add:':exam_toggle_archived' pk=exam.pk %}" {% if exam.archive %}checked{% endif %}>
|
<span class="flex-shrink">
|
||||||
<label for="archived-{{exam.pk}}" class="flex-shrink icon-archive archived-icon" title="Click to toggle archived state"><i class="bi bi-archive"></i></label>
|
{% include "generic/partials/exams/exam_status.html#exam-archived" %}
|
||||||
|
</span>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
@@ -70,6 +73,11 @@
|
|||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
-moz-user-select: none;
|
-moz-user-select: none;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
padding: 0.15rem 0.45rem;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
line-height: 1;
|
||||||
|
vertical-align: middle;
|
||||||
|
min-width: 3.4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.archived-icon {
|
.archived-icon {
|
||||||
@@ -82,23 +90,26 @@
|
|||||||
opacity: 100%;
|
opacity: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.exam-active-switch:checked + .active-icon {
|
/* Styling for active/published/archive buttons to match previous compact look */
|
||||||
border: 1px solid green;
|
.active-icon.btn-success, .active-icon.btn-primary {
|
||||||
color: green;
|
border: 1px solid #198754;
|
||||||
opacity: 100%;
|
color: #198754;
|
||||||
display: inline-block;
|
opacity: 1;
|
||||||
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.exam-publish-results-switch:checked + .published-icon {
|
.published-icon.btn-success {
|
||||||
border: 1px solid purple;
|
border: 1px solid purple;
|
||||||
color: purple;
|
color: purple;
|
||||||
opacity: 100%;
|
opacity: 1;
|
||||||
display: inline-block;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.exam-archived-switch:checked + .archived-icon {
|
.archived-icon.btn-warning {
|
||||||
color: darkblue;
|
color: darkblue;
|
||||||
opacity: 100%;
|
opacity: 1;
|
||||||
|
background: transparent;
|
||||||
|
border: 1px solid #ffc107;
|
||||||
}
|
}
|
||||||
|
|
||||||
.exam-publish-results-switch, .exam-active-switch, .exam-archived-switch {
|
.exam-publish-results-switch, .exam-active-switch, .exam-archived-switch {
|
||||||
|
|||||||
@@ -1,104 +1,38 @@
|
|||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
// send request to change the is_private state on customSwitches toggle
|
// HTMX loading indicator handlers: show .exam-loading near trigger or in closest .card-body
|
||||||
$("#exam-active-switch, .exam-active-switch").on("change", function (evt) {
|
document.body.addEventListener('htmx:beforeRequest', function(evt){
|
||||||
$.ajax({
|
try {
|
||||||
url: evt.currentTarget.dataset.posturl,
|
var trigger = evt.detail && evt.detail.elt ? evt.detail.elt : null;
|
||||||
data: {
|
if (!trigger) return;
|
||||||
csrfmiddlewaretoken: "{{ csrf_token }}",
|
var spinner = null;
|
||||||
active: this.checked // true if checked else false
|
// prefer spinner sibling of the triggering element
|
||||||
},
|
if (trigger.parentElement) spinner = trigger.parentElement.querySelector('.exam-loading');
|
||||||
type: "POST",
|
// fallback to nearest card-body spinner
|
||||||
dataType: "json",
|
if (!spinner) {
|
||||||
})
|
var card = trigger.closest && trigger.closest('.card-body') ? trigger.closest('.card-body') : null;
|
||||||
// $.ajax().done(), $.ajax().fail(), $ajax().always() are upto you. Add/change accordingly
|
if (card) spinner = card.querySelector('.exam-loading');
|
||||||
.done(function (data) {
|
}
|
||||||
console.log(data);
|
if (spinner) spinner.classList.remove('d-none');
|
||||||
|
} catch (e) { console.error('htmx beforeRequest spinner error', e); }
|
||||||
|
});
|
||||||
|
|
||||||
if (data.status == "success") {
|
document.body.addEventListener('htmx:afterRequest', function(evt){
|
||||||
toastr.info(`Exam: ${data.name} [${data.id}]
|
try {
|
||||||
Active state changed to: ${data.active}.`)
|
var trigger = evt.detail && evt.detail.elt ? evt.detail.elt : null;
|
||||||
}
|
if (!trigger) return;
|
||||||
// show some message according to the response.
|
var spinner = null;
|
||||||
// For eg. A message box showing that the status has been changed
|
if (trigger.parentElement) spinner = trigger.parentElement.querySelector('.exam-loading');
|
||||||
})
|
if (!spinner) {
|
||||||
.fail(function (jqXHR) {
|
var card = trigger.closest && trigger.closest('.card-body') ? trigger.closest('.card-body') : null;
|
||||||
console.log(jqXHR)
|
if (card) spinner = card.querySelector('.exam-loading');
|
||||||
var msg = 'Unknown error';
|
}
|
||||||
try {
|
if (spinner) spinner.classList.add('d-none');
|
||||||
if (jqXHR && jqXHR.responseJSON && jqXHR.responseJSON.status) {
|
} catch (e) { console.error('htmx afterRequest spinner error', e); }
|
||||||
msg = jqXHR.responseJSON.status;
|
});
|
||||||
} else if (jqXHR && jqXHR.responseText) {
|
|
||||||
// fallback to raw responseText (may be HTML)
|
|
||||||
msg = jqXHR.responseText;
|
|
||||||
} else if (jqXHR && jqXHR.statusText) {
|
|
||||||
msg = jqXHR.statusText;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.error('Error parsing failure response', e);
|
|
||||||
}
|
|
||||||
toastr.error(`Failed to change state<br/>${msg}`);
|
|
||||||
})
|
|
||||||
.always(function () {
|
|
||||||
console.log('[Done]');
|
|
||||||
})
|
|
||||||
})
|
|
||||||
$("#exam-publish-results-switch, .exam-publish-results-switch").on("change", function (evt) {
|
|
||||||
$.ajax({
|
|
||||||
url: evt.currentTarget.dataset.posturl,
|
|
||||||
data: {
|
|
||||||
csrfmiddlewaretoken: "{{ csrf_token }}",
|
|
||||||
publish_results: this.checked // true if checked else false
|
|
||||||
},
|
|
||||||
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") {
|
// HTMX handles active/publish/archive toggles via server-rendered partials.
|
||||||
toastr.info(`Exam: ${data.name} [${data.id}]
|
// Removed legacy jQuery AJAX handlers for exam-active, publish-results and archived toggles.
|
||||||
Published state changed to: ${data.publish_results}.`)
|
|
||||||
}
|
|
||||||
// show some message according to the response.
|
|
||||||
// For eg. A message box showing that the status has been changed
|
|
||||||
})
|
|
||||||
.fail(function (data) {
|
|
||||||
toastr.error(`Failed to change state`);
|
|
||||||
})
|
|
||||||
.always(function () {
|
|
||||||
console.log('[Done]');
|
|
||||||
})
|
|
||||||
})
|
|
||||||
$(".exam-archived-switch").on("change", function (evt) {
|
|
||||||
$.ajax({
|
|
||||||
url: evt.currentTarget.dataset.posturl,
|
|
||||||
data: {
|
|
||||||
csrfmiddlewaretoken: "{{ csrf_token }}",
|
|
||||||
archive: this.checked // true if checked else false
|
|
||||||
},
|
|
||||||
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(`Exam: ${data.name} [${data.id}]
|
|
||||||
Archived state changed to: ${data.archive}.`)
|
|
||||||
}
|
|
||||||
// show some message according to the response.
|
|
||||||
// For eg. A message box showing that the status has been changed
|
|
||||||
})
|
|
||||||
.fail(function (data) {
|
|
||||||
toastr.error(`Failed to change state`);
|
|
||||||
})
|
|
||||||
.always(function () {
|
|
||||||
console.log('[Done]');
|
|
||||||
})
|
|
||||||
})
|
|
||||||
$("#button-open-access").click(function (evt) {
|
$("#button-open-access").click(function (evt) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: evt.currentTarget.dataset.posturl,
|
url: evt.currentTarget.dataset.posturl,
|
||||||
|
|||||||
Reference in New Issue
Block a user