.
This commit is contained in:
@@ -1,21 +0,0 @@
|
|||||||
{% extends 'anatomy/exams.html' %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
|
|
||||||
{% load thumbnail %}
|
|
||||||
<div class="anatomy">
|
|
||||||
<h1>Exam: {{ exam.name }}</h1>
|
|
||||||
|
|
||||||
<p>{{cid_user_count}} users.</p>
|
|
||||||
|
|
||||||
|
|
||||||
<ol>
|
|
||||||
{% for cid in cid_users %}
|
|
||||||
<li>{{cid.cid}} [{{cid.passcode}}]</li>
|
|
||||||
|
|
||||||
{% endfor %}
|
|
||||||
</ol>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
{% if exam.exam_mode %}
|
{% if exam.exam_mode %}
|
||||||
<a href="{% url 'anatomy:mark_overview' pk=exam.pk %}">Mark</a> /
|
<a href="{% url 'anatomy:mark_overview' pk=exam.pk %}">Mark</a> /
|
||||||
<a href="{% url 'anatomy:exam_scores_cid' pk=exam.pk %}">Scores</a> /
|
<a href="{% url 'anatomy:exam_scores_cid' pk=exam.pk %}">Scores</a> /
|
||||||
<a href="{% url 'anatomy:exam_cids' exam_id=exam.pk %}">CIDs</a> /
|
<a href="{% url 'anatomy:exam_cids' exam_id=exam.pk %}">Candidates</a> /
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a href="{% url 'anatomy:anatomy_create_exam' pk=exam.pk %}">Add New Question</a>
|
<a href="{% url 'anatomy:anatomy_create_exam' pk=exam.pk %}">Add New Question</a>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
+1
-1
@@ -226,7 +226,7 @@ def loadJsonAnswer(answer):
|
|||||||
# in the frontend this is appended with the type
|
# in the frontend this is appended with the type
|
||||||
# e.g. anatomy/1
|
# e.g. anatomy/1
|
||||||
|
|
||||||
# TODO Update to only allow valid CIDs
|
# TODO Update to only allow valid Candidates
|
||||||
eid = int(answer["eid"].split("/")[1])
|
eid = int(answer["eid"].split("/")[1])
|
||||||
# As access is not restricted make sure the data appears valid
|
# As access is not restricted make sure the data appears valid
|
||||||
if (not isinstance(answer["cid"], int)) or (
|
if (not isinstance(answer["cid"], int)) or (
|
||||||
|
|||||||
+6
-1
@@ -10,7 +10,7 @@ from django.forms import (
|
|||||||
from django.forms import inlineformset_factory
|
from django.forms import inlineformset_factory
|
||||||
|
|
||||||
from generic.models import (
|
from generic.models import (
|
||||||
Examination, QuestionNote
|
CidUser, Examination, QuestionNote
|
||||||
)
|
)
|
||||||
|
|
||||||
from django.contrib.admin.widgets import FilteredSelectMultiple
|
from django.contrib.admin.widgets import FilteredSelectMultiple
|
||||||
@@ -66,3 +66,8 @@ class QuestionNoteForm(ModelForm):
|
|||||||
##initial["content_id"] = pk
|
##initial["content_id"] = pk
|
||||||
#self.fields["content_type"].initial = content_type
|
#self.fields["content_type"].initial = content_type
|
||||||
#self.fields["object_id"].initial = pk
|
#self.fields["object_id"].initial = pk
|
||||||
|
|
||||||
|
class CidUserForm(ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = CidUser
|
||||||
|
fields = ["cid", "passcode", "active", "internal_candidate", "name", "email", "supervisor_email"]
|
||||||
@@ -1,8 +1,11 @@
|
|||||||
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.http import HttpRequest
|
from django.http import HttpRequest
|
||||||
from smtplib import SMTPException
|
from smtplib import SMTPException
|
||||||
|
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
from django.views.generic.edit import CreateView
|
||||||
|
from reversion.views import RevisionMixin
|
||||||
|
|
||||||
import tagulous
|
import tagulous
|
||||||
import tagulous.models
|
import tagulous.models
|
||||||
|
|||||||
+4
-1
@@ -23,7 +23,10 @@ class CidUserTable(tables.Table):
|
|||||||
# edit = tables.LinkColumn(
|
# edit = tables.LinkColumn(
|
||||||
# "anatomy:anatomy_question_update", text="Edit", args=[A("pk")], orderable=False
|
# "anatomy:anatomy_question_update", text="Edit", args=[A("pk")], orderable=False
|
||||||
# )
|
# )
|
||||||
cid = tables.LinkColumn("cid_scores", args=[A("cid"), A("passcode")], orderable=True)
|
cid = tables.LinkColumn(
|
||||||
|
"cid_scores", args=[A("cid"), A("passcode")], orderable=True
|
||||||
|
)
|
||||||
|
edit = tables.LinkColumn("generic:update_cid", text="Edit", args=[A("pk")], orderable=True)
|
||||||
# image = ImageColumn("image", orderable=False)
|
# image = ImageColumn("image", orderable=False)
|
||||||
# clone = tables.LinkColumn('anatomy:anatomy_question_clone',
|
# clone = tables.LinkColumn('anatomy:anatomy_question_clone',
|
||||||
# text='Clone',
|
# text='Clone',
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
{% block title %}
|
{% block title %}
|
||||||
CIDs
|
Candidates
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block css %}
|
{% block css %}
|
||||||
@@ -15,7 +15,7 @@ CIDs
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block navigation %}
|
{% block navigation %}
|
||||||
CIDs:
|
Candidates:
|
||||||
{% if request.user.is_authenticated %}
|
{% if request.user.is_authenticated %}
|
||||||
<a href="{% url 'generic:manage_cids' %}">Cids</a> /
|
<a href="{% url 'generic:manage_cids' %}">Cids</a> /
|
||||||
<a href="{% url 'generic:group_view' %}">Groups</a> /
|
<a href="{% url 'generic:group_view' %}">Groups</a> /
|
||||||
|
|||||||
Executable
+26
@@ -0,0 +1,26 @@
|
|||||||
|
{% extends "atlas/base.html" %}
|
||||||
|
<!-- {% load static from static %} -->
|
||||||
|
|
||||||
|
{% block css %}
|
||||||
|
{% endblock %}
|
||||||
|
{% block js %}
|
||||||
|
<!--<script type="text/javascript" src="/admin/jsi18n/"></script>-->
|
||||||
|
{{form.media}}
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- {{ form.media }} -->
|
||||||
|
{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<h2>Edit CID User</h2>
|
||||||
|
Use this form to create or edit a CID user.
|
||||||
|
<form action="" method="post" enctype="multipart/form-data" id="condition-form">
|
||||||
|
{% csrf_token %}
|
||||||
|
|
||||||
|
<table>
|
||||||
|
{{ form.as_table }}
|
||||||
|
</table>
|
||||||
|
<input type="submit" class="submit-button" value="Submit" name="submit">
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
||||||
@@ -26,6 +26,7 @@ urlpatterns = [
|
|||||||
),
|
),
|
||||||
name="examination-autocomplete",
|
name="examination-autocomplete",
|
||||||
),
|
),
|
||||||
|
path("cids/manage/<int:pk>/update", views.CidUserUpdate.as_view(), name="update_cid"),
|
||||||
path("cids/manage/", views.CidUserView.as_view(), name="manage_cids"),
|
path("cids/manage/", views.CidUserView.as_view(), name="manage_cids"),
|
||||||
path("cids/group/", views.group_view, name="group_view"),
|
path("cids/group/", views.group_view, name="group_view"),
|
||||||
path("cids/group/<int:pk>/email", views.group_email, name="group_email"),
|
path("cids/group/<int:pk>/email", views.group_email, name="group_email"),
|
||||||
|
|||||||
+32
-4
@@ -25,14 +25,17 @@ import json
|
|||||||
import urllib
|
import urllib
|
||||||
|
|
||||||
from django.views import View
|
from django.views import View
|
||||||
|
from django.views.generic.edit import CreateView, UpdateView
|
||||||
from django_filters.views import FilterView
|
from django_filters.views import FilterView
|
||||||
from django_tables2.views import SingleTableMixin
|
from django_tables2.views import SingleTableMixin
|
||||||
|
from reversion.views import RevisionMixin
|
||||||
from generic.decorators import user_is_cid_user_manager
|
from generic.decorators import user_is_cid_user_manager
|
||||||
from generic.filters import CidUserFilter
|
from generic.filters import CidUserFilter
|
||||||
|
|
||||||
from generic.tables import CidUserTable
|
from generic.tables import CidUserTable
|
||||||
|
|
||||||
from .forms import (
|
from .forms import (
|
||||||
|
CidUserForm,
|
||||||
ExaminationForm,
|
ExaminationForm,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -414,10 +417,20 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
if not self.check_user_access(request.user):
|
if not self.check_user_access(request.user):
|
||||||
raise PermissionDenied
|
raise PermissionDenied
|
||||||
|
|
||||||
|
marking = False
|
||||||
|
|
||||||
|
if self.app_name in ("rapids", "anatomy", "longs"):
|
||||||
|
marking = True
|
||||||
|
|
||||||
return render(
|
return render(
|
||||||
request,
|
request,
|
||||||
"exam_list.html".format(self.app_name),
|
"exam_list.html".format(self.app_name),
|
||||||
{"exams": exams, "app_name": self.app_name, "view_all": all},
|
{
|
||||||
|
"exams": exams,
|
||||||
|
"app_name": self.app_name,
|
||||||
|
"view_all": all,
|
||||||
|
"marking": marking,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@method_decorator(login_required)
|
@method_decorator(login_required)
|
||||||
@@ -526,8 +539,13 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
|
|
||||||
return render(
|
return render(
|
||||||
request,
|
request,
|
||||||
"{}/exam_cids.html".format(self.app_name),
|
"exam_cids.html",
|
||||||
{"exam": exam, "cid_users": cid_users, "cid_user_count": cid_user_count},
|
{
|
||||||
|
"exam": exam,
|
||||||
|
"cid_users": cid_users,
|
||||||
|
"cid_user_count": cid_user_count,
|
||||||
|
"app_name": self.app_name,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
# @method_decorator(login_required)
|
# @method_decorator(login_required)
|
||||||
@@ -1287,7 +1305,7 @@ def group_email(request, pk, resend=False):
|
|||||||
if resend:
|
if resend:
|
||||||
users = group.ciduser_set.filter()
|
users = group.ciduser_set.filter()
|
||||||
else:
|
else:
|
||||||
users = group.ciduser_set.filter(login_email_sent=False)
|
users = gGroup.ciduser_set.filter(login_email_sent=False)
|
||||||
|
|
||||||
sent = []
|
sent = []
|
||||||
not_sent = []
|
not_sent = []
|
||||||
@@ -1449,3 +1467,13 @@ def manage_cid_users(request):
|
|||||||
|
|
||||||
return JsonResponse({"status": "success"})
|
return JsonResponse({"status": "success"})
|
||||||
return JsonResponse({"status": "fail"})
|
return JsonResponse({"status": "fail"})
|
||||||
|
|
||||||
|
|
||||||
|
class CidUserCreate(RevisionMixin, LoginRequiredMixin, CreateView):
|
||||||
|
model = CidUser
|
||||||
|
form_class = CidUserForm
|
||||||
|
|
||||||
|
|
||||||
|
class CidUserUpdate(RevisionMixin, LoginRequiredMixin, UpdateView):
|
||||||
|
model = CidUser
|
||||||
|
form_class = CidUserForm
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
{% extends 'longs/base.html' %}
|
{% extends 'longs/base.html' %}
|
||||||
|
|
||||||
{% block navigation %}
|
{% block navigation %}
|
||||||
{{block.super}}
|
{{block.super}}
|
||||||
<br/>
|
<br/>
|
||||||
Exams: {{exam.name}}-> <a href="{% url 'longs:exam_overview' pk=exam.pk %}">Overview</a> / <a href="{% url 'longs:mark_overview' pk=exam.pk %}">Mark</a> / <a href="{% url 'longs:exam_scores_cid' pk=exam.pk %}">Scores</a>
|
Exams: {{exam.name}}->
|
||||||
{% endblock %}
|
<a href="{% url 'longs:exam_overview' pk=exam.pk %}">Overview</a> /
|
||||||
|
<a href="{% url 'longs:mark_overview' pk=exam.pk %}">Mark</a> /
|
||||||
|
<a href="{% url 'longs:exam_scores_cid' pk=exam.pk %}">Scores</a>
|
||||||
|
<a href="{% url 'longs:exam_cids' exam_id=exam.pk %}">Candidates</a> /
|
||||||
|
{% endblock %}
|
||||||
|
|||||||
@@ -125,6 +125,7 @@ urlpatterns = [
|
|||||||
path("exam/", views.GenericExamViews.exam_list, name="exam_list"),
|
path("exam/", views.GenericExamViews.exam_list, name="exam_list"),
|
||||||
path("exam/all", views.GenericExamViews.exam_list_all, name="exam_list_all"),
|
path("exam/all", views.GenericExamViews.exam_list_all, name="exam_list_all"),
|
||||||
path("exam/create", views.ExamCreate.as_view(), name="exam_create"),
|
path("exam/create", views.ExamCreate.as_view(), name="exam_create"),
|
||||||
|
path("exam/<int:exam_id>/cids", views.GenericExamViews.exam_cids, name="exam_cids"),
|
||||||
path("exam/<int:exam_id>/clone", views.ExamClone.as_view(), name="exam_clone"),
|
path("exam/<int:exam_id>/clone", views.ExamClone.as_view(), name="exam_clone"),
|
||||||
path("exam/<int:pk>/update", views.ExamUpdate.as_view(), name="exam_update"),
|
path("exam/<int:pk>/update", views.ExamUpdate.as_view(), name="exam_update"),
|
||||||
path("exam/<int:pk>/delete", views.ExamDelete.as_view(), name="exam_delete"),
|
path("exam/<int:pk>/delete", views.ExamDelete.as_view(), name="exam_delete"),
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ urlpatterns = [
|
|||||||
name="exam_toggle_results_published",
|
name="exam_toggle_results_published",
|
||||||
),
|
),
|
||||||
path("exam/<int:exam_id>/clone", views.ExamClone.as_view(), name="exam_clone"),
|
path("exam/<int:exam_id>/clone", views.ExamClone.as_view(), name="exam_clone"),
|
||||||
|
path("exam/<int:exam_id>/cids", views.GenericExamViews.exam_cids, name="exam_cids"),
|
||||||
path("exam/<int:pk>/update", views.ExamUpdate.as_view(), name="exam_update"),
|
path("exam/<int:pk>/update", views.ExamUpdate.as_view(), name="exam_update"),
|
||||||
path("exam/<int:pk>/delete", views.ExamDelete.as_view(), name="exam_delete"),
|
path("exam/<int:pk>/delete", views.ExamDelete.as_view(), name="exam_delete"),
|
||||||
path(
|
path(
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
{% if exam.exam_mode %}
|
{% if exam.exam_mode %}
|
||||||
<a href="{% url 'rapids:mark_overview' pk=exam.pk %}">Mark</a> /
|
<a href="{% url 'rapids:mark_overview' pk=exam.pk %}">Mark</a> /
|
||||||
<a href="{% url 'rapids:exam_scores_cid' pk=exam.pk %}">Scores</a> /
|
<a href="{% url 'rapids:exam_scores_cid' pk=exam.pk %}">Scores</a> /
|
||||||
|
<a href="{% url 'rapids:exam_cids' exam_id=exam.pk %}">Candidates</a> /
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a href="{% url 'rapids:rapid_create_exam' pk=exam.pk %}">Add New Question</a>
|
<a href="{% url 'rapids:rapid_create_exam' pk=exam.pk %}">Add New Question</a>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ urlpatterns = [
|
|||||||
path("exam/all", views.GenericExamViews.exam_list_all, name="exam_list_all"),
|
path("exam/all", views.GenericExamViews.exam_list_all, name="exam_list_all"),
|
||||||
path("exam/create", views.ExamCreate.as_view(), name="exam_create"),
|
path("exam/create", views.ExamCreate.as_view(), name="exam_create"),
|
||||||
path("exam/<int:exam_id>/clone", views.ExamClone.as_view(), name="exam_clone"),
|
path("exam/<int:exam_id>/clone", views.ExamClone.as_view(), name="exam_clone"),
|
||||||
|
path("exam/<int:exam_id>/cids", views.GenericExamViews.exam_cids, name="exam_cids"),
|
||||||
path("exam/<int:pk>/update", views.ExamUpdate.as_view(), name="exam_update"),
|
path("exam/<int:pk>/update", views.ExamUpdate.as_view(), name="exam_update"),
|
||||||
path("exam/<int:pk>/delete", views.ExamDelete.as_view(), name="exam_delete"),
|
path("exam/<int:pk>/delete", views.ExamDelete.as_view(), name="exam_delete"),
|
||||||
path("exam/json/", views.GenericExamViews.active_exams, name="active_exams"),
|
path("exam/json/", views.GenericExamViews.active_exams, name="active_exams"),
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
{% extends 'sbas/base.html' %}
|
{% extends 'sbas/base.html' %}
|
||||||
|
|
||||||
{% block navigation %}
|
{% block navigation %}
|
||||||
{{block.super}}
|
{{block.super}}
|
||||||
<br/>
|
<br/>
|
||||||
Exams: {{exam.name}}-> <a href="{% url 'sbas:exam_overview' pk=exam.pk %}">Overview</a> / <a href="{% url 'sbas:exam_scores_cid' pk=exam.pk %}">Scores</a>
|
Exams: {{exam.name}}->
|
||||||
{% endblock %}
|
<a href="{% url 'sbas:exam_overview' pk=exam.pk %}">Overview</a> /
|
||||||
|
<a href="{% url 'sbas:exam_scores_cid' pk=exam.pk %}">Scores</a>
|
||||||
|
<a href="{% url 'sbas:exam_cids' exam_id=exam.pk %}">Candidates</a> /
|
||||||
|
{% endblock %}
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ urlpatterns = [
|
|||||||
),
|
),
|
||||||
# path("exam/submit", views.GenericExamViews.postExamAnswers, name="exam_answers_submit"),
|
# path("exam/submit", views.GenericExamViews.postExamAnswers, name="exam_answers_submit"),
|
||||||
path("exam/", views.GenericExamViews.exam_list, name="exam_list"),
|
path("exam/", views.GenericExamViews.exam_list, name="exam_list"),
|
||||||
|
path("exam/<int:exam_id>/clone", views.ExamClone.as_view(), name="exam_clone"),
|
||||||
|
path("exam/<int:exam_id>/cids", views.GenericExamViews.exam_cids, name="exam_cids"),
|
||||||
path("exam/available", views.active_exams, name="active_exams"),
|
path("exam/available", views.active_exams, name="active_exams"),
|
||||||
# path("exam/json/<int:pk>", views.exam_json, name="exam_json"),
|
# path("exam/json/<int:pk>", views.exam_json, name="exam_json"),
|
||||||
# path("exam/json/<int:pk>/recreate", views.exam_json_recreate, name="exam_json_recreate"),
|
# path("exam/json/<int:pk>/recreate", views.exam_json_recreate, name="exam_json_recreate"),
|
||||||
|
|||||||
+58
-2
@@ -1,6 +1,7 @@
|
|||||||
|
from reversion.views import RevisionMixin
|
||||||
from generic.mixins import SuperuserRequiredMixin
|
from generic.mixins import SuperuserRequiredMixin
|
||||||
from django.views.generic.detail import DetailView
|
from django.views.generic.detail import DetailView
|
||||||
from sbas.forms import CidUserAnswerForm
|
from sbas.forms import CidUserAnswerForm, ExamForm
|
||||||
from django.shortcuts import render, get_object_or_404, redirect
|
from django.shortcuts import render, get_object_or_404, redirect
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
from django import forms
|
from django import forms
|
||||||
@@ -37,7 +38,7 @@ import json
|
|||||||
import statistics
|
import statistics
|
||||||
import plotly.express as px
|
import plotly.express as px
|
||||||
|
|
||||||
from generic.views import ExamViews, GenericViewBase
|
from generic.views import ExamCloneMixin, ExamViews, GenericViewBase
|
||||||
|
|
||||||
from rest_framework import viewsets, permissions
|
from rest_framework import viewsets, permissions
|
||||||
from rest_framework.pagination import PageNumberPagination
|
from rest_framework.pagination import PageNumberPagination
|
||||||
@@ -319,3 +320,58 @@ class UserAnswerDelete(SuperuserRequiredMixin, DeleteView):
|
|||||||
|
|
||||||
|
|
||||||
GenericViews = GenericViewBase("sbas", Question, CidUserAnswer, Exam)
|
GenericViews = GenericViewBase("sbas", Question, CidUserAnswer, Exam)
|
||||||
|
|
||||||
|
class QuestionDelete(AuthorOrCheckerRequiredMixin, DeleteView):
|
||||||
|
model = Question
|
||||||
|
success_url = reverse_lazy("sbas:question_list")
|
||||||
|
|
||||||
|
|
||||||
|
class ExamCreate(RevisionMixin, LoginRequiredMixin, CreateView):
|
||||||
|
model = Exam
|
||||||
|
form_class = ExamForm
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
|
self.object = form.save(commit=False)
|
||||||
|
self.object.save()
|
||||||
|
|
||||||
|
form.instance.author.add(self.request.user.id)
|
||||||
|
return super().form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
|
class ExamUpdate(
|
||||||
|
RevisionMixin, LoginRequiredMixin, AuthorOrCheckerRequiredMixin, UpdateView
|
||||||
|
):
|
||||||
|
model = Exam
|
||||||
|
form_class = ExamForm
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
|
self.object = form.save(commit=False)
|
||||||
|
self.object.save()
|
||||||
|
|
||||||
|
form.instance.author.add(self.request.user.id)
|
||||||
|
return super().form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
|
#class ExamViewSet(RevisionMixin, viewsets.ModelViewSet):
|
||||||
|
# # queryset = Exam.objects.all().order_by('name')
|
||||||
|
# serializer_class = ExamSerializer
|
||||||
|
# permission_classes = [permissions.IsAuthenticated]
|
||||||
|
#
|
||||||
|
# def get_queryset(self):
|
||||||
|
# """
|
||||||
|
# This view should return a list exams available to a user.
|
||||||
|
# """
|
||||||
|
# user = self.request.user
|
||||||
|
# if user.groups.filter(name="sbas_checker").exists():
|
||||||
|
# return Exam.objects.all()
|
||||||
|
#
|
||||||
|
# return Exam.objects.filter(author__id=user.id)
|
||||||
|
|
||||||
|
|
||||||
|
class ExamDelete(RevisionMixin, AuthorOrCheckerRequiredMixin, DeleteView):
|
||||||
|
model = Exam
|
||||||
|
template_name = "exam_confirm_delete.html"
|
||||||
|
success_url = reverse_lazy("sbas:index")
|
||||||
|
|
||||||
|
class ExamClone(ExamCloneMixin, ExamCreate):
|
||||||
|
"""Clone exam view"""
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
{% extends app_name|add:'/exams.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
{% load thumbnail %}
|
||||||
|
<div class="{{app_name}}">
|
||||||
|
<h1>Exam: {{ exam.name }}</h1>
|
||||||
|
|
||||||
|
<p>{{cid_user_count}} candidates.</p>
|
||||||
|
|
||||||
|
|
||||||
|
<ol>
|
||||||
|
{% for cid in cid_users %}
|
||||||
|
|
||||||
|
<li><a href="{% url 'generic:update_cid' cid.pk %}">{{cid.cid}}</a> [{{cid.passcode}}] {{cid.name}} /
|
||||||
|
{{cid.email}} /
|
||||||
|
{{cid.supervisor_email}} /
|
||||||
|
{% if cid.login_email_sent %}Login email sent{% endif %} /
|
||||||
|
{% if cid.results_email_sent %}Results email sent{% endif %} /
|
||||||
|
</li>
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
@@ -8,7 +8,11 @@
|
|||||||
{% for exam in exams %}
|
{% for exam in exams %}
|
||||||
{% if exam.active %}
|
{% if exam.active %}
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url app_name|add:':exam_overview' pk=exam.pk %}" class="flex-col">{{exam.name}}</a> <a href="{% url app_name|add:':mark_overview' pk=exam.pk %}" class="flex-col">Mark</a><a href="{% url app_name|add:':exam_scores_cid' pk=exam.pk %}" class="flex-col">Scores</a> <span class="flex-col icon-container"><span class="published-icon {% if exam.publish_results %}published{% endif %}">Results Published</span></span>
|
<a href="{% url app_name|add:':exam_overview' pk=exam.pk %}" class="flex-col">{{exam.name}}</a>
|
||||||
|
{% if marking %}<a href="{% url app_name|add:':mark_overview' pk=exam.pk %}" class="flex-col">Mark</a>{% endif %}
|
||||||
|
<a href="{% url app_name|add:':exam_cids' exam_id=exam.pk %}" class="flex-col">Candidates</a>
|
||||||
|
<a href="{% url app_name|add:':exam_scores_cid' pk=exam.pk %}" class="flex-col">Scores</a>
|
||||||
|
<span class="flex-col icon-container"><span class="published-icon {% if exam.publish_results %}published{% endif %}">Results Published</span></span>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@@ -19,7 +23,11 @@
|
|||||||
{% for exam in exams %}
|
{% for exam in exams %}
|
||||||
{% if not exam.active %}
|
{% if not exam.active %}
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url app_name|add:':exam_overview' pk=exam.pk %}" class="flex-col">{{exam.name}}</a> <a href="{% url app_name|add:':mark_overview' pk=exam.pk %}" class="flex-col">Mark</a><a href="{% url app_name|add:':exam_scores_cid' pk=exam.pk %}" class="flex-col">Scores</a> <span class="flex-col icon-container"><span class="published-icon {% if exam.publish_results %}published{% endif %}">Results Published</span></span>
|
<a href="{% url app_name|add:':exam_overview' pk=exam.pk %}" class="flex-col">{{exam.name}}</a>
|
||||||
|
{% if marking %}<a href="{% url app_name|add:':mark_overview' pk=exam.pk %}" class="flex-col">Mark</a>{% endif %}
|
||||||
|
<a href="{% url app_name|add:':exam_cids' exam_id=exam.pk %}" class="flex-col">Candidates</a>
|
||||||
|
<a href="{% url app_name|add:':exam_scores_cid' pk=exam.pk %}" class="flex-col">Scores</a>
|
||||||
|
<span class="flex-col icon-container"><span class="published-icon {% if exam.publish_results %}published{% endif %}">Results Published</span></span>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
Reference in New Issue
Block a user