.
This commit is contained in:
+98
-8
@@ -7,9 +7,11 @@ from django.forms import (
|
|||||||
ModelChoiceField,
|
ModelChoiceField,
|
||||||
ChoiceField,
|
ChoiceField,
|
||||||
CharField,
|
CharField,
|
||||||
|
ValidationError,
|
||||||
modelformset_factory,
|
modelformset_factory,
|
||||||
)
|
)
|
||||||
from django.forms import inlineformset_factory
|
from django.forms import inlineformset_factory
|
||||||
|
from django.shortcuts import get_object_or_404
|
||||||
|
|
||||||
from atlas.models import (
|
from atlas.models import (
|
||||||
Case,
|
Case,
|
||||||
@@ -52,6 +54,7 @@ class ConditionForm(ModelForm):
|
|||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class CaseCollectionForm(ModelForm):
|
class CaseCollectionForm(ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = CaseCollection
|
model = CaseCollection
|
||||||
@@ -73,6 +76,7 @@ class CaseCollectionForm(ModelForm):
|
|||||||
|
|
||||||
super(CaseCollectionForm, self).__init__(*args, **kwargs)
|
super(CaseCollectionForm, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class FindingForm(ModelForm):
|
class FindingForm(ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Finding
|
model = Finding
|
||||||
@@ -204,7 +208,7 @@ class SeriesForm(ModelForm):
|
|||||||
instance.save()
|
instance.save()
|
||||||
self.save_m2m()
|
self.save_m2m()
|
||||||
|
|
||||||
#instance.anonymise_images()
|
# instance.anonymise_images()
|
||||||
|
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
@@ -337,8 +341,6 @@ CaseDifferentialFormSet = inlineformset_factory(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class CaseSeriesForm(ModelForm):
|
class CaseSeriesForm(ModelForm):
|
||||||
def __init__(self, *args, user, **kwargs):
|
def __init__(self, *args, user, **kwargs):
|
||||||
super(CaseSeriesForm, self).__init__(*args, **kwargs)
|
super(CaseSeriesForm, self).__init__(*args, **kwargs)
|
||||||
@@ -354,10 +356,11 @@ class CaseSeriesForm(ModelForm):
|
|||||||
# widget=Select(verbose_name="Series", is_stacked=False),
|
# widget=Select(verbose_name="Series", is_stacked=False),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class CaseCollectionCaseForm(ModelForm):
|
class CaseCollectionCaseForm(ModelForm):
|
||||||
def __init__(self, *args, user, **kwargs):
|
def __init__(self, *args, user, **kwargs):
|
||||||
super(CaseCollectionCaseForm, self).__init__(*args, **kwargs)
|
super(CaseCollectionCaseForm, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
if not user.groups.filter(name="atlas_editor").exists():
|
if not user.groups.filter(name="atlas_editor").exists():
|
||||||
queryset = Case.objects.filter(author__id=user.id)
|
queryset = Case.objects.filter(author__id=user.id)
|
||||||
else:
|
else:
|
||||||
@@ -369,6 +372,7 @@ class CaseCollectionCaseForm(ModelForm):
|
|||||||
# widget=Select(verbose_name="Series", is_stacked=False),
|
# widget=Select(verbose_name="Series", is_stacked=False),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
SeriesFormSet = inlineformset_factory(
|
SeriesFormSet = inlineformset_factory(
|
||||||
Case,
|
Case,
|
||||||
Series.case.through,
|
Series.case.through,
|
||||||
@@ -399,6 +403,7 @@ SeriesImageFormSet = inlineformset_factory(
|
|||||||
max_num=2000,
|
max_num=2000,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class CidReportAnswerForm(ModelForm):
|
class CidReportAnswerForm(ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = CidReportAnswer
|
model = CidReportAnswer
|
||||||
@@ -413,13 +418,14 @@ class CidReportAnswerForm(ModelForm):
|
|||||||
"answer": Textarea(attrs={"cols": 100, "rows": 5}),
|
"answer": Textarea(attrs={"cols": 100, "rows": 5}),
|
||||||
}
|
}
|
||||||
|
|
||||||
#help_texts = {
|
# help_texts = {
|
||||||
# "answer": "Write your answer in here."
|
# "answer": "Write your answer in here."
|
||||||
#}
|
# }
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(CidReportAnswerForm, self).__init__(*args, **kwargs)
|
super(CidReportAnswerForm, self).__init__(*args, **kwargs)
|
||||||
self.fields['answer'].required = False
|
self.fields["answer"].required = False
|
||||||
|
|
||||||
|
|
||||||
class CidReportAnswerMarkForm(ModelForm):
|
class CidReportAnswerMarkForm(ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
@@ -437,4 +443,88 @@ class CidReportAnswerMarkForm(ModelForm):
|
|||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(CidReportAnswerMarkForm, self).__init__(*args, **kwargs)
|
super(CidReportAnswerMarkForm, self).__init__(*args, **kwargs)
|
||||||
self.fields['score'].required = False
|
self.fields["score"].required = False
|
||||||
|
|
||||||
|
|
||||||
|
#class AddCollectionToCaseForm(Form):
|
||||||
|
#
|
||||||
|
# def __init__(self, *args, user, **kwargs):
|
||||||
|
# super(AddCollectionToCaseForm, self).__init__(*args, **kwargs)
|
||||||
|
# print("INIT", args, kwargs)
|
||||||
|
#
|
||||||
|
# if not user.groups.filter(name="atlas_editor").exists():
|
||||||
|
# queryset = CaseCollection.objects.filter(author__id=user.id)
|
||||||
|
# else:
|
||||||
|
# queryset = CaseCollection.objects.all()
|
||||||
|
#
|
||||||
|
# self.valid_collections = queryset
|
||||||
|
# self.case = get_object_or_404(Case, pk=pk)
|
||||||
|
#
|
||||||
|
# self.fields["casecollection"] = ModelMultipleChoiceField(
|
||||||
|
# required=False,
|
||||||
|
# queryset=queryset,
|
||||||
|
# # widget=Select(verbose_name="Series", is_stacked=False),
|
||||||
|
# )
|
||||||
|
#
|
||||||
|
# def save(self, *args, **kwargs):
|
||||||
|
# print("SAVE", args, kwargs)
|
||||||
|
# instance = super(AddCollectionToCaseForm, self).save(*args, **kwargs)
|
||||||
|
#
|
||||||
|
# # Here we save the modified project selection back into the database
|
||||||
|
# instance.casecollection_set.set(self.cleaned_data['casecollection'])
|
||||||
|
#
|
||||||
|
# print(f"{instance=}")
|
||||||
|
#
|
||||||
|
# return instance
|
||||||
|
#
|
||||||
|
# def clean_casecollection(self):
|
||||||
|
# collection_set = self.cleaned_data["casecollection"]
|
||||||
|
#
|
||||||
|
# print(f"{collection_set=}")
|
||||||
|
#
|
||||||
|
# for col in collection_set:
|
||||||
|
# if col not in self.valid_collections:
|
||||||
|
# raise ValidationError("Invalid collection")
|
||||||
|
#
|
||||||
|
# return collection_set
|
||||||
|
|
||||||
|
class AddCollectionToCaseForm(Form):
|
||||||
|
|
||||||
|
def __init__(self, *args, user, **kwargs):
|
||||||
|
super(AddCollectionToCaseForm, self).__init__(*args, **kwargs)
|
||||||
|
print("INIT", args, kwargs)
|
||||||
|
|
||||||
|
if not user.groups.filter(name="atlas_editor").exists():
|
||||||
|
queryset = CaseCollection.objects.filter(author__id=user.id)
|
||||||
|
else:
|
||||||
|
queryset = CaseCollection.objects.all()
|
||||||
|
|
||||||
|
self.valid_collections = queryset
|
||||||
|
|
||||||
|
self.fields["casecollection"] = ModelMultipleChoiceField(
|
||||||
|
required=False,
|
||||||
|
queryset=queryset,
|
||||||
|
# widget=Select(verbose_name="Series", is_stacked=False),
|
||||||
|
)
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
print("SAVE", args, kwargs)
|
||||||
|
instance = super(AddCollectionToCaseForm, self).save(*args, **kwargs)
|
||||||
|
|
||||||
|
# Here we save the modified project selection back into the database
|
||||||
|
instance.casecollection_set.set(self.cleaned_data['casecollection'])
|
||||||
|
|
||||||
|
print(f"{instance=}")
|
||||||
|
|
||||||
|
return instance
|
||||||
|
|
||||||
|
def clean_casecollection(self):
|
||||||
|
collection_set = self.cleaned_data["casecollection"]
|
||||||
|
|
||||||
|
print(f"{collection_set=}")
|
||||||
|
|
||||||
|
for col in collection_set:
|
||||||
|
if col not in self.valid_collections:
|
||||||
|
raise ValidationError("Invalid collection")
|
||||||
|
|
||||||
|
return collection_set
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 3.2.13 on 2022-07-05 20:45
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('atlas', '0045_rename_valid_users_casecollection_valid_cid_users'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='casedetail',
|
||||||
|
name='sort_order',
|
||||||
|
field=models.IntegerField(default=1000),
|
||||||
|
),
|
||||||
|
]
|
||||||
+1
-1
@@ -739,7 +739,7 @@ class CaseDetail(models.Model):
|
|||||||
case = models.ForeignKey(Case, on_delete=models.CASCADE)
|
case = models.ForeignKey(Case, on_delete=models.CASCADE)
|
||||||
collection = models.ForeignKey(CaseCollection, on_delete=models.CASCADE)
|
collection = models.ForeignKey(CaseCollection, on_delete=models.CASCADE)
|
||||||
|
|
||||||
sort_order = models.IntegerField()
|
sort_order = models.IntegerField(default=1000)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ("sort_order",)
|
ordering = ("sort_order",)
|
||||||
|
|||||||
@@ -111,6 +111,11 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
<b>Collections:</b>
|
<b>Collections:</b>
|
||||||
|
<button
|
||||||
|
hx-get="{% url 'atlas:case_collection_form' case.pk %}"
|
||||||
|
hx-target="#collection-form">
|
||||||
|
Add collection</button>
|
||||||
|
<div id="collection-form"></div>
|
||||||
<ul>
|
<ul>
|
||||||
{% for p in case.casecollection_set.all %}
|
{% for p in case.casecollection_set.all %}
|
||||||
<li>{{p.name}}</li>
|
<li>{{p.name}}</li>
|
||||||
|
|||||||
@@ -119,6 +119,8 @@ urlpatterns = [
|
|||||||
# path("unchecked/", views.unchecked_list, name="unchecked_list"),
|
# path("unchecked/", views.unchecked_list, name="unchecked_list"),
|
||||||
# path("verified/<int:pk>/", views.verified_detail, name="verified_detail"),
|
# path("verified/<int:pk>/", views.verified_detail, name="verified_detail"),
|
||||||
path("case/<int:pk>/", views.case_detail, name="case_detail"),
|
path("case/<int:pk>/", views.case_detail, name="case_detail"),
|
||||||
|
#path("case/<int:pk>/collection-form", views.AddCollectionToCaseView.as_view(), name="case_collection_form"),
|
||||||
|
path("case/<int:case_id>/collection-form", views.add_collection_to_case_form, name="case_collection_form"),
|
||||||
path("case/<int:pk>/clone", views.AtlasClone.as_view(), name="case_clone"),
|
path("case/<int:pk>/clone", views.AtlasClone.as_view(), name="case_clone"),
|
||||||
# path("verified/", views.verified, name="verified"),
|
# path("verified/", views.verified, name="verified"),
|
||||||
# path("all_questions/", views.all_questions, name="all_questions"),
|
# path("all_questions/", views.all_questions, name="all_questions"),
|
||||||
|
|||||||
+35
-1
@@ -18,7 +18,7 @@ from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMix
|
|||||||
from django.views.generic.detail import DetailView
|
from django.views.generic.detail import DetailView
|
||||||
from generic.mixins import SuperuserRequiredMixin
|
from generic.mixins import SuperuserRequiredMixin
|
||||||
|
|
||||||
from django.views.generic.edit import CreateView, UpdateView, DeleteView
|
from django.views.generic.edit import CreateView, UpdateView, DeleteView, FormView
|
||||||
from django.views.generic import ListView
|
from django.views.generic import ListView
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
|
|
||||||
@@ -30,6 +30,7 @@ from django.http import HttpResponseRedirect, HttpResponse
|
|||||||
from generic.models import CidUser
|
from generic.models import CidUser
|
||||||
|
|
||||||
from .forms import (
|
from .forms import (
|
||||||
|
AddCollectionToCaseForm,
|
||||||
CaseCollectionCaseFormSet,
|
CaseCollectionCaseFormSet,
|
||||||
CaseCollectionForm,
|
CaseCollectionForm,
|
||||||
CaseForm,
|
CaseForm,
|
||||||
@@ -714,6 +715,39 @@ class AtlasUpdate(
|
|||||||
else:
|
else:
|
||||||
return super().form_invalid(form)
|
return super().form_invalid(form)
|
||||||
|
|
||||||
|
def add_collection_to_case_form(request, case_id):
|
||||||
|
if request.method == 'POST':
|
||||||
|
form = AddCollectionToCaseForm(request.POST, user=request.user)
|
||||||
|
if form.is_valid():
|
||||||
|
case = get_object_or_404(Case, pk=case_id)
|
||||||
|
|
||||||
|
case.casecollection_set.add(*form.cleaned_data["casecollection"])
|
||||||
|
#do_something_with_form_data(form.cleaned_data)
|
||||||
|
return HttpResponse("Done")
|
||||||
|
return render(request, 'web/htmx_contact_form_confirm.html')
|
||||||
|
else:
|
||||||
|
form = AddCollectionToCaseForm(user=request.user)
|
||||||
|
return render(request, 'generic_form.html', {
|
||||||
|
'form': form,
|
||||||
|
'target_url': reverse("atlas:case_collection_form", args=(case_id,))
|
||||||
|
})
|
||||||
|
|
||||||
|
#class AddCollectionToCaseView(FormView):
|
||||||
|
# form_class = AddCollectionToCaseForm
|
||||||
|
# template_name = "generic_form.html"
|
||||||
|
#
|
||||||
|
# def form_valid(self, form):
|
||||||
|
# form.save()
|
||||||
|
# return super(AddCollectionToCaseView, self).form_valid(form)
|
||||||
|
#
|
||||||
|
# def get_form_kwargs(self):
|
||||||
|
# kwargs = super(AddCollectionToCaseView, self).get_form_kwargs()
|
||||||
|
# kwargs.update({"user": self.request.user})
|
||||||
|
# return kwargs
|
||||||
|
#
|
||||||
|
# def get_success_url(self) -> str:
|
||||||
|
# pk = self.kwargs["pk"]
|
||||||
|
# return reverse("atlas:case_detail", kwargs={"pk": pk})
|
||||||
|
|
||||||
class AtlasClone(AtlasCreateBase, CreateView):
|
class AtlasClone(AtlasCreateBase, CreateView):
|
||||||
"""Clones a existing atlas"""
|
"""Clones a existing atlas"""
|
||||||
|
|||||||
+4
-3
@@ -316,9 +316,10 @@ class ExamBase(models.Model):
|
|||||||
exam_text.append(f"Stats\n{'-'*len('Stats')}\n{stats}")
|
exam_text.append(f"Stats\n{'-'*len('Stats')}\n{stats}")
|
||||||
|
|
||||||
|
|
||||||
exam_text.append(
|
if self.app_name == "rapids":
|
||||||
f"Answers breakdown: {callstate}"
|
exam_text.append(
|
||||||
)
|
f"Answers breakdown: {callstate}"
|
||||||
|
)
|
||||||
|
|
||||||
msg = "\n\n".join(exam_text)
|
msg = "\n\n".join(exam_text)
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,12 @@
|
|||||||
<button hx-get="{% url exam.app_name|add:':exam_user_report_email' exam_id=exam.pk user_id=user.pk %}"
|
<button hx-get="{% url exam.app_name|add:':exam_user_report_email' exam_id=exam.pk user_id=user.pk %}"
|
||||||
hx-prompt="Enter any additional emails"
|
hx-prompt="Enter any additional emails"
|
||||||
hx-confirm="Are you sure you wish to delete your account?"
|
hx-confirm="Are you sure you wish to delete your account?"
|
||||||
hx-trigger="click, click from:#test"
|
hx-trigger="click, click from:#resend-all"
|
||||||
>Resend</button>
|
>Resend</button>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
|
{% empty %}
|
||||||
|
No emails sent.
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
<button id="test">Test</button>
|
<button id="resend-all">Resend all</button>
|
||||||
@@ -90,8 +90,19 @@
|
|||||||
<details>
|
<details>
|
||||||
<summary>Email results</summary>
|
<summary>Email results</summary>
|
||||||
User results emailed: {{exam.exam_results_emailed|default:"Never"}}<br/>
|
User results emailed: {{exam.exam_results_emailed|default:"Never"}}<br/>
|
||||||
<button id="email-results-button" title="Email results to users and their supervisors">Email user results</button>
|
<button id="email-results-button"
|
||||||
<button id="email-unsent-results-button" title="Email results to users and their supervisors">Email unsent user results</button>
|
title="Email results to users and their supervisors"
|
||||||
|
hx-get="{% url exam.app_name|add:':exam_report_email' exam_id=exam.pk %}"
|
||||||
|
hx-target="#user-details"
|
||||||
|
hx-confirm="This will email results, please make sure scores have been refreshed before continuing"
|
||||||
|
hx-prompt="Please enter an additional email to send to (user and supervisor will automatically be used if available) if required"
|
||||||
|
>Email user results</button>
|
||||||
|
<button id="email-unsent-results-button" title="Email results to users and their supervisors"
|
||||||
|
hx-get="{% url exam.app_name|add:':exam_report_email_unsent' exam_id=exam.pk %}"
|
||||||
|
hx-target="#user-details"
|
||||||
|
hx-confirm="This will email results, please make sure scores have been refreshed before continuing"
|
||||||
|
hx-prompt="Please enter an additional email to send to (user and supervisor will automatically be used if available) if required"
|
||||||
|
>Email unsent user results</button>
|
||||||
<button id="email-results-check-button" title="Check the status of emailed results"
|
<button id="email-results-check-button" title="Check the status of emailed results"
|
||||||
hx-get="{% url exam.app_name|add:':exam_report_email_status' exam_id=exam.pk %}"
|
hx-get="{% url exam.app_name|add:':exam_report_email_status' exam_id=exam.pk %}"
|
||||||
hx-target="#user-details">Check email status</button>
|
hx-target="#user-details">Check email status</button>
|
||||||
@@ -100,50 +111,5 @@
|
|||||||
</details>
|
</details>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
$(document).ready(() => {
|
|
||||||
$("#email-results-button").click((evt) => {
|
|
||||||
if (confirm("This will email results, please make sure scores have been refreshed before continuing")) {
|
|
||||||
|
|
||||||
let additional_email = prompt("Please enter an additional email to send to (user and supervisor will automatically be used if available) if required");
|
|
||||||
|
|
||||||
let url = "{% url exam.app_name|add:':exam_report_email' exam_id=exam.pk %}";
|
|
||||||
|
|
||||||
if ( additional_email != null ) {
|
|
||||||
url = url + "?additional_email="+encodeURI(additional_email)
|
|
||||||
}
|
|
||||||
|
|
||||||
window.location = url;
|
|
||||||
|
|
||||||
}
|
|
||||||
evt.preventDefault();
|
|
||||||
|
|
||||||
})
|
|
||||||
$("#email-unsent-results-button").click((evt) => {
|
|
||||||
if (confirm("This will email results, please make sure scores have been refreshed before continuing")) {
|
|
||||||
|
|
||||||
let additional_email = prompt("Please enter an additional email to send to (user and supervisor will automatically be used if available) if required");
|
|
||||||
|
|
||||||
let url = "{% url exam.app_name|add:':exam_report_email_unsent' exam_id=exam.pk %}";
|
|
||||||
|
|
||||||
if ( additional_email != null ) {
|
|
||||||
url = url + "?additional_email="+encodeURI(additional_email)
|
|
||||||
}
|
|
||||||
|
|
||||||
window.location = url;
|
|
||||||
|
|
||||||
}
|
|
||||||
evt.preventDefault();
|
|
||||||
|
|
||||||
})
|
|
||||||
//$("#email-results-check-button").click((evt) => {
|
|
||||||
// window.location = "{% url exam.app_name|add:':exam_report_email_status' exam_id=exam.pk %}";
|
|
||||||
//})
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|||||||
+22
-7
@@ -593,7 +593,8 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
for u in users:
|
for u in users:
|
||||||
user = User.objects.get(pk=u)
|
user = User.objects.get(pk=u)
|
||||||
user_exam = exam.get_or_create_cid_user_exam(user_user=user)
|
user_exam = exam.get_or_create_cid_user_exam(user_user=user)
|
||||||
status[user] = json.loads(user_exam.results_emailed_status)
|
if user_exam.results_emailed_status:
|
||||||
|
status[user] = json.loads(user_exam.results_emailed_status)
|
||||||
|
|
||||||
return render(
|
return render(
|
||||||
request,
|
request,
|
||||||
@@ -620,7 +621,11 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
if not self.check_user_access(request.user, exam_id):
|
if not self.check_user_access(request.user, exam_id):
|
||||||
raise PermissionDenied
|
raise PermissionDenied
|
||||||
|
|
||||||
additional_email = request.GET.get("additional_email", "")
|
additional_email = False
|
||||||
|
if request.htmx.prompt is not None:
|
||||||
|
additional_email = request.htmx.prompt
|
||||||
|
|
||||||
|
print(f"{additional_email=}")
|
||||||
|
|
||||||
# check addition email is valid
|
# check addition email is valid
|
||||||
if additional_email:
|
if additional_email:
|
||||||
@@ -646,19 +651,29 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
if additional_email:
|
if additional_email:
|
||||||
email_results[user.pk] = exam.email_user_results(
|
email_results[user] = exam.email_user_results(
|
||||||
user, additional_emails=[additional_email]
|
user, additional_emails=[additional_email]
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
email_results[user.pk] = exam.email_user_results(user)
|
email_results[user] = exam.email_user_results(user)
|
||||||
email_results[user.pk].append(f"{time}")
|
email_results[user].append(f"{time}")
|
||||||
user_exam.results_emailed_status = json.dumps(email_results[user.pk])
|
user_exam.results_emailed_status = json.dumps(email_results[user])
|
||||||
|
|
||||||
user_exam.save()
|
user_exam.save()
|
||||||
|
|
||||||
exam.exam_results_emailed = time
|
exam.exam_results_emailed = time
|
||||||
exam.save()
|
exam.save()
|
||||||
|
|
||||||
|
return render(
|
||||||
|
request,
|
||||||
|
"generic/exam_report_email_status.html",
|
||||||
|
{
|
||||||
|
"exam": exam,
|
||||||
|
"status": email_results,
|
||||||
|
"app_name": self.app_name,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
return JsonResponse(email_results)
|
return JsonResponse(email_results)
|
||||||
|
|
||||||
@method_decorator(login_required)
|
@method_decorator(login_required)
|
||||||
@@ -1343,7 +1358,7 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
if not existing_answers:
|
if not existing_answers:
|
||||||
if uid:
|
if uid:
|
||||||
ans = self.CidUserAnswer(
|
ans = self.CidUserAnswer(
|
||||||
answer=posted_answer, uid=User.objects.get(id=uid)
|
answer=posted_answer, user=User.objects.get(id=uid)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
ans = self.CidUserAnswer(answer=posted_answer, cid=cid)
|
ans = self.CidUserAnswer(answer=posted_answer, cid=cid)
|
||||||
|
|||||||
+2
-1
@@ -25,7 +25,8 @@
|
|||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/core.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/core.js"></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/md5.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/md5.js"></script>
|
||||||
|
|
||||||
<script src="https://unpkg.com/alpinejs" defer></script>
|
{% comment %} <script src="https://unpkg.com/alpinejs" defer></script> {% endcomment %}
|
||||||
|
<script src="https://unpkg.com/hyperscript.org@0.9.5"></script>
|
||||||
<script src="https://unpkg.com/htmx.org@1.7.0/dist/htmx.min.js" defer></script>
|
<script src="https://unpkg.com/htmx.org@1.7.0/dist/htmx.min.js" defer></script>
|
||||||
{% django_htmx_script %}
|
{% django_htmx_script %}
|
||||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<form class="form" hx-post="{{ target_url }}">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ form }}
|
||||||
|
<input type="submit" value="Submit">
|
||||||
|
<button _="on click remove <.form/>">Cancel</button>
|
||||||
|
</form>
|
||||||
Reference in New Issue
Block a user