This commit is contained in:
Ross
2022-07-04 16:34:21 +01:00
parent 87a47a1082
commit eb602616b8
13 changed files with 143 additions and 22 deletions
@@ -0,0 +1,17 @@
# Generated by Django 3.2.13 on 2022-06-30 20:45
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('anatomy', '0065_exam_exam_results_emailed'),
]
operations = [
migrations.RemoveField(
model_name='exam',
name='stats_graph',
),
]
+1 -1
View File
@@ -1538,7 +1538,7 @@ def collection_scores_cid(request, pk):
collection.stats_min = min(user_scores_list) collection.stats_min = min(user_scores_list)
collection.stats_max = max(user_scores_list) collection.stats_max = max(user_scores_list)
collection.stats_graph = fig_html #collection.stats_graph = fig_html
collection.user_scores = user_scores collection.user_scores = user_scores
+1 -1
View File
@@ -138,7 +138,7 @@ class ExamBase(models.Model):
stats_max_possible = models.FloatField(default=0) stats_max_possible = models.FloatField(default=0)
stats_graph = models.TextField(default=0) #stats_graph = models.TextField(default=0)
user_scores = models.JSONField(default=dict) user_scores = models.JSONField(default=dict)
@@ -0,0 +1,14 @@
<ul>
{% for user, status in status.items %}
<li class='{% if status.0 %}text-success{% else %}text-warning{% endif %}'>
{{user.username}} {% if status.0 %}success{% else %}failed [{{status.1}}]{% endif %} ({{status.2}})
<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-confirm="Are you sure you wish to delete your account?"
hx-trigger="click, click from:#test"
>Resend</button>
</li>
{% endfor %}
</ul>
<button id="test">Test</button>
@@ -92,8 +92,11 @@
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" title="Email results to users and their supervisors">Email user results</button>
<button id="email-unsent-results-button" title="Email results to users and their supervisors">Email unsent user results</button> <button id="email-unsent-results-button" title="Email results to users and their supervisors">Email unsent user results</button>
<button id="email-results-check-button" title="Check the status of emailed results">Check email status</button> <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-target="#user-details">Check email status</button>
<p>Note: currently only works with registered users</p> <p>Note: currently only works with registered users</p>
<div id="user-details"></div>
</details> </details>
</div> </div>
@@ -135,9 +138,9 @@
evt.preventDefault(); evt.preventDefault();
}) })
$("#email-results-check-button").click((evt) => { //$("#email-results-check-button").click((evt) => {
window.location = "{% url exam.app_name|add:':exam_report_email_status' exam_id=exam.pk %}"; // window.location = "{% url exam.app_name|add:':exam_report_email_status' exam_id=exam.pk %}";
}) //})
}) })
+26 -15
View File
@@ -588,8 +588,17 @@ 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.username] = user_exam.results_emailed_status status[user] = json.loads(user_exam.results_emailed_status)
return render(
request,
"generic/exam_report_email_status.html",
{
"exam": exam,
"status": status,
"app_name": self.app_name,
},
)
return JsonResponse(status) return JsonResponse(status)
@method_decorator(login_required) @method_decorator(login_required)
@@ -597,7 +606,7 @@ class ExamViews(View, LoginRequiredMixin):
return self.exam_report_email(request, exam_id, unsent_only=True) return self.exam_report_email(request, exam_id, unsent_only=True)
@method_decorator(login_required) @method_decorator(login_required)
def exam_report_email(self, request, exam_id, unsent_only=False): def exam_report_email(self, request, exam_id, unsent_only=False, users=None):
exam = get_object_or_404(self.Exam.objects.prefetch_related("author"), pk=exam_id) exam = get_object_or_404(self.Exam.objects.prefetch_related("author"), pk=exam_id)
if request.user not in exam.author.all(): if request.user not in exam.author.all():
@@ -616,7 +625,8 @@ class ExamViews(View, LoginRequiredMixin):
# We only need to send emails to those who have scores # We only need to send emails to those who have scores
# (who should be in exam.user_scores) # (who should be in exam.user_scores)
users = [i[2:] for i in exam.user_scores if i.startswith("u/")] if users is None:
users = [i[2:] for i in exam.user_scores if i.startswith("u/")]
time = timezone.now() time = timezone.now()
@@ -631,11 +641,11 @@ class ExamViews(View, LoginRequiredMixin):
if additional_email: if additional_email:
email_results[user.username] = exam.email_user_results(user, additional_emails=[additional_email]) email_results[user.pk] = exam.email_user_results(user, additional_emails=[additional_email])
else: else:
email_results[user.username] = exam.email_user_results(user) email_results[user.pk] = exam.email_user_results(user)
email_results[user.username].append(f" {time}") email_results[user.pk].append(f"{time}")
user_exam.results_emailed_status = json.dumps(email_results[user.username]) user_exam.results_emailed_status = json.dumps(email_results[user.pk])
user_exam.save() user_exam.save()
@@ -646,20 +656,21 @@ class ExamViews(View, LoginRequiredMixin):
@method_decorator(login_required) @method_decorator(login_required)
def exam_user_report_email(self, request, exam_id, user_id): def exam_user_report_email(self, request, exam_id, user_id):
return self.exam_report_email(request, exam_id, users=[user_id])
# print(Exam.objects.all()) # print(Exam.objects.all())
# exams = Exam.objects.all() # exams = Exam.objects.all()
# print("test", Exam.objects.all().get(id=pk)) # print("test", Exam.objects.all().get(id=pk))
exam = get_object_or_404(self.Exam.objects.prefetch_related("author"), pk=exam_id) #exam = get_object_or_404(self.Exam.objects.prefetch_related("author"), pk=exam_id)
u = get_object_or_404(User, pk=user_id) #u = get_object_or_404(User, pk=user_id)
if request.user not in exam.author.all(): #if request.user not in exam.author.all():
if not self.check_user_access(request.user, exam_id): # if not self.check_user_access(request.user, exam_id):
raise PermissionDenied # raise PermissionDenied
res = exam.email_user_results(u) #res = exam.email_user_results(u)
return HttpResponse(res) #return HttpResponse(res)
@method_decorator(login_required) @method_decorator(login_required)
def exam_user_report(self, request, exam_id, user_id): def exam_user_report(self, request, exam_id, user_id):
@@ -1654,7 +1665,7 @@ class ExamViews(View, LoginRequiredMixin):
exam.stats_min = min(user_scores_list) exam.stats_min = min(user_scores_list)
exam.stats_max = max(user_scores_list) exam.stats_max = max(user_scores_list)
exam.stats_graph = fig_html #exam.stats_graph = fig_html
user_data = {} user_data = {}
for u in cids: for u in cids:
@@ -0,0 +1,17 @@
# Generated by Django 3.2.13 on 2022-06-30 20:45
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('longs', '0063_exam_exam_results_emailed'),
]
operations = [
migrations.RemoveField(
model_name='exam',
name='stats_graph',
),
]
@@ -0,0 +1,17 @@
# Generated by Django 3.2.13 on 2022-06-30 20:45
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('physics', '0025_exam_exam_results_emailed'),
]
operations = [
migrations.RemoveField(
model_name='exam',
name='stats_graph',
),
]
+3
View File
@@ -71,6 +71,7 @@ INSTALLED_APPS = [
"rest_framework", "rest_framework",
"tinymce", "tinymce",
"django_unused_media", "django_unused_media",
"django_htmx",
] ]
MIDDLEWARE = [ MIDDLEWARE = [
@@ -84,6 +85,8 @@ MIDDLEWARE = [
"django.contrib.messages.middleware.MessageMiddleware", "django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware", "django.middleware.clickjacking.XFrameOptionsMiddleware",
"reversion.middleware.RevisionMiddleware", "reversion.middleware.RevisionMiddleware",
"django_htmx.middleware.HtmxMiddleware",
] ]
ROOT_URLCONF = "rad.urls" ROOT_URLCONF = "rad.urls"
@@ -0,0 +1,17 @@
# Generated by Django 3.2.13 on 2022-06-30 20:45
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('rapids', '0060_exam_exam_results_emailed'),
]
operations = [
migrations.RemoveField(
model_name='exam',
name='stats_graph',
),
]
+2 -1
View File
@@ -28,4 +28,5 @@ django_unused_media
pytest-django pytest-django
gunicorn gunicorn
rich rich
bs4 bs4
django-htmx
@@ -0,0 +1,17 @@
# Generated by Django 3.2.13 on 2022-06-30 20:45
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('sbas', '0015_exam_exam_results_emailed'),
]
operations = [
migrations.RemoveField(
model_name='exam',
name='stats_graph',
),
]
+4
View File
@@ -1,5 +1,6 @@
<!DOCTYPE HTML> <!DOCTYPE HTML>
{% load static %} {% load static %}
{% load django_htmx %}
<html> <html>
<head> <head>
@@ -24,6 +25,9 @@
<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>
<script src="https://unpkg.com/htmx.org@1.7.0/dist/htmx.min.js" defer></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>
<script src="{% static 'admin/js/core.js' %}"></script> <script src="{% static 'admin/js/core.js' %}"></script>
<script src="{% static 'admin/js/SelectBox.js' %}"></script> <script src="{% static 'admin/js/SelectBox.js' %}"></script>