.
This commit is contained in:
+6
-21
@@ -50,7 +50,7 @@ from .models import (
|
||||
# IncorrectAnswers,
|
||||
)
|
||||
from generic.models import CidUser, Examination
|
||||
from generic.views import AuthorRequiredMixin, ExamCloneMixin, ExamViews, GenericViewBase
|
||||
from generic.views import AuthorRequiredMixin, ExamCloneMixin, ExamCreateBase, ExamDeleteBase, ExamUpdateBase, ExamViews, GenericViewBase
|
||||
from reversion.views import RevisionMixin
|
||||
|
||||
from .decorators import user_is_author_or_anatomy_checker
|
||||
@@ -963,30 +963,19 @@ class QuestionDelete(AuthorOrCheckerRequiredMixin, DeleteView):
|
||||
success_url = reverse_lazy("anatomy:question_list")
|
||||
|
||||
|
||||
class ExamCreate(RevisionMixin, LoginRequiredMixin, CreateView):
|
||||
class ExamCreate(ExamCreateBase):
|
||||
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
|
||||
):
|
||||
class ExamUpdate(ExamUpdateBase, AuthorOrCheckerRequiredMixin):
|
||||
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 ExamDelete(AuthorOrCheckerRequiredMixin, ExamDeleteBase):
|
||||
model = Exam
|
||||
|
||||
|
||||
|
||||
class ExamViewSet(RevisionMixin, viewsets.ModelViewSet):
|
||||
@@ -1009,10 +998,6 @@ class ExamAuthorUpdate(RevisionMixin, LoginRequiredMixin, AuthorRequiredMixin, U
|
||||
model = Exam
|
||||
form_class = ExamAuthorForm
|
||||
|
||||
class ExamDelete(RevisionMixin, AuthorOrCheckerRequiredMixin, DeleteView):
|
||||
model = Exam
|
||||
template_name = "exam_confirm_delete.html"
|
||||
success_url = reverse_lazy("anatomy:index")
|
||||
|
||||
|
||||
GenericViews = GenericViewBase("anatomy", AnatomyQuestion, CidUserAnswer, Exam)
|
||||
|
||||
+30
-7
@@ -32,7 +32,7 @@ import urllib
|
||||
from django.views import View
|
||||
from django.views.generic.edit import CreateView, UpdateView, DeleteView
|
||||
from django_filters.views import FilterView
|
||||
from django_filters import FilterSet
|
||||
from django_filters import FilterSet, OrderingFilter
|
||||
from django_tables2.views import SingleTableMixin
|
||||
from reversion.views import RevisionMixin
|
||||
from atlas.models import CaseCollection
|
||||
@@ -294,6 +294,8 @@ class ExamViews(View, LoginRequiredMixin):
|
||||
# exam_group = group_map[self.app_name]
|
||||
|
||||
class ExamFilter(FilterSet):
|
||||
sort_order = OrderingFilter(fields=(("name", "name"), ("exam_mode", "exam_mode")))
|
||||
|
||||
class Meta:
|
||||
model = exam
|
||||
fields = {
|
||||
@@ -329,6 +331,8 @@ class ExamViews(View, LoginRequiredMixin):
|
||||
# filter param is either missing or empty, use initial as default
|
||||
if not data.get("archive"):
|
||||
data["archive"] = False
|
||||
if not data.get("sort_order"):
|
||||
data["sort_order"] = "name"
|
||||
|
||||
super().__init__(data, *args, **kwargs)
|
||||
|
||||
@@ -523,15 +527,18 @@ class ExamViews(View, LoginRequiredMixin):
|
||||
|
||||
@method_decorator(login_required)
|
||||
def exam_list(self, request, all=False):
|
||||
if all:
|
||||
exams = self.Exam.objects.all().order_by("name")
|
||||
|
||||
if not self.check_user_access(request.user):
|
||||
#raise PermissionDenied
|
||||
exam_list = self.Exam.objects.filter(author__id=request.user.id).order_by("name")
|
||||
else:
|
||||
exams = self.Exam.objects.filter(exam_mode=True, archive=False).order_by(
|
||||
exam_list = self.Exam.objects.all().order_by("name")
|
||||
|
||||
if not all:
|
||||
exams = exam_list.filter(exam_mode=True, archive=False).order_by(
|
||||
"name"
|
||||
)
|
||||
|
||||
if not self.check_user_access(request.user):
|
||||
raise PermissionDenied
|
||||
|
||||
marking = False
|
||||
|
||||
@@ -1021,7 +1028,7 @@ class ExamViews(View, LoginRequiredMixin):
|
||||
|
||||
view_feedback = False
|
||||
if (
|
||||
#request.user.groups.filter(name=self.checker_group).exists() or
|
||||
# request.user.groups.filter(name=self.checker_group).exists() or
|
||||
request.user.groups.filter(name="feedback_checker").exists()
|
||||
or request.user in question.author.all()
|
||||
):
|
||||
@@ -2095,6 +2102,14 @@ class ExamCreateBase(RevisionMixin, LoginRequiredMixin, CreateView):
|
||||
form.instance.author.add(self.request.user.id)
|
||||
return super().form_valid(form)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
# Call the base implementation first to get a context
|
||||
context = super().get_context_data(**kwargs)
|
||||
print(dir(context["view"]))
|
||||
print(context["view"].template_name_suffix)
|
||||
print(context["view"].model.app_name)
|
||||
return context
|
||||
|
||||
|
||||
class ExamUpdateBase(RevisionMixin, LoginRequiredMixin, UpdateView):
|
||||
template_name = "exam_update_form.html"
|
||||
@@ -2106,3 +2121,11 @@ class ExamUpdateBase(RevisionMixin, LoginRequiredMixin, UpdateView):
|
||||
form.instance.author.add(self.request.user.id)
|
||||
|
||||
return super().form_valid(form)
|
||||
|
||||
|
||||
class ExamDeleteBase(RevisionMixin, DeleteView):
|
||||
template_name = "exam_confirm_delete.html"
|
||||
|
||||
def get_success_url(self) -> str:
|
||||
# return super().get_success_url()(self):
|
||||
return reverse_lazy(f"{self.model.app_name}:index")
|
||||
|
||||
+8
-27
@@ -75,7 +75,7 @@ from django.forms.models import model_to_dict
|
||||
from longs.forms import LongCreationDefaultForm
|
||||
from longs.models import LongCreationDefault
|
||||
|
||||
from generic.views import AuthorRequiredMixin, ExamCloneMixin, ExamViews
|
||||
from generic.views import AuthorRequiredMixin, ExamCloneMixin, ExamCreateBase, ExamDeleteBase, ExamUpdateBase, ExamViews
|
||||
from reversion.views import RevisionMixin
|
||||
import reversion
|
||||
|
||||
@@ -1112,47 +1112,28 @@ def long_series_order_upload_filename(request, pk):
|
||||
|
||||
GenericExamViews = ExamViews(Exam, Long, None, CidUserAnswer, "longs", "long")
|
||||
|
||||
|
||||
class ExamCreate(RevisionMixin, LoginRequiredMixin, CreateView):
|
||||
class ExamCreate(ExamCreateBase):
|
||||
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(ExamUpdateBase, AuthorOrCheckerRequiredMixin):
|
||||
model = Exam
|
||||
form_class = ExamForm
|
||||
|
||||
|
||||
class ExamDelete(AuthorOrCheckerRequiredMixin, ExamDeleteBase):
|
||||
model = Exam
|
||||
|
||||
class ExamClone(ExamCloneMixin, ExamCreate):
|
||||
"""Clone exam view"""
|
||||
|
||||
|
||||
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 ExamAuthorUpdate(RevisionMixin, LoginRequiredMixin, AuthorRequiredMixin, UpdateView):
|
||||
model = Exam
|
||||
form_class = ExamAuthorForm
|
||||
|
||||
|
||||
class ExamDelete(RevisionMixin, AuthorOrCheckerRequiredMixin, DeleteView):
|
||||
model = Exam
|
||||
template_name = "exam_confirm_delete.html"
|
||||
success_url = reverse_lazy("longs:index")
|
||||
|
||||
|
||||
class ExamViewSet(RevisionMixin, viewsets.ModelViewSet):
|
||||
queryset = Exam.objects.all().order_by("name")
|
||||
serializer_class = ExamSerializer
|
||||
|
||||
+12
-25
@@ -45,6 +45,9 @@ import plotly.express as px
|
||||
from generic.views import (
|
||||
AuthorRequiredMixin,
|
||||
ExamCloneMixin,
|
||||
ExamCreateBase,
|
||||
ExamDeleteBase,
|
||||
ExamUpdateBase,
|
||||
ExamViews,
|
||||
GenericViewBase,
|
||||
)
|
||||
@@ -377,17 +380,19 @@ GenericExamViews = ExamViews(Exam, Question, None, CidUserAnswer, "physics", "ph
|
||||
|
||||
GenericViews = GenericViewBase("physics", Question, CidUserAnswer, Exam)
|
||||
|
||||
|
||||
class ExamCreate(RevisionMixin, LoginRequiredMixin, CreateView):
|
||||
class ExamCreate(ExamCreateBase):
|
||||
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(ExamUpdateBase, AuthorOrCheckerRequiredMixin):
|
||||
model = Exam
|
||||
form_class = ExamForm
|
||||
|
||||
|
||||
class ExamDelete(AuthorOrCheckerRequiredMixin, ExamDeleteBase):
|
||||
model = Exam
|
||||
|
||||
|
||||
|
||||
class ExamClone(AuthorOrCheckerRequiredMixin, ExamCloneMixin, ExamCreate):
|
||||
@@ -401,24 +406,6 @@ class ExamAuthorUpdate(
|
||||
form_class = ExamAuthorForm
|
||||
|
||||
|
||||
class ExamDelete(RevisionMixin, AuthorOrCheckerRequiredMixin, DeleteView):
|
||||
model = Exam
|
||||
template_name = "exam_confirm_delete.html"
|
||||
success_url = reverse_lazy("physics:index")
|
||||
|
||||
|
||||
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 QuestionView(
|
||||
|
||||
+5
-1
@@ -1,12 +1,16 @@
|
||||
|
||||
from cProfile import label
|
||||
import django_filters
|
||||
|
||||
from generic.models import UserGrades
|
||||
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
class UserListFilter(django_filters.FilterSet):
|
||||
|
||||
userprofile__grade = django_filters.CharFilter(label="Grade")
|
||||
userprofile__grade = django_filters.ModelChoiceFilter(label="Grade", queryset=UserGrades.objects.all())
|
||||
#test2 = django_filters.CharFilter()
|
||||
|
||||
class Meta:
|
||||
model= User
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
<button id="add-to-exam" data-exam_json_edit_url="{% url 'generic:generic_exam_json_edit' %}"
|
||||
data-exam_list_url="{% url 'rapid-exam-list' %}" data-type="rapid" data-csrf="{{ csrf_token}}"
|
||||
data-qid="{{question.pk}}">Add to exam</button>
|
||||
<button id="cancel-add-to-exam" style="display:none">Cancel</button>
|
||||
<span id="exam-options"></span>
|
||||
</div>
|
||||
<p class="pre-whitespace"><b>Open Access:</b> {{ question.open_access }}</p>
|
||||
@@ -156,8 +157,15 @@
|
||||
})
|
||||
})
|
||||
|
||||
$("#cancel-add-to-exam").click(function (evt) {
|
||||
$("#add-to-exam").toggle();
|
||||
$("#cancel-add-to-exam").toggle();
|
||||
$("#exam-options").empty();
|
||||
})
|
||||
|
||||
$("#add-to-exam").click(function (evt) {
|
||||
$("#add-to-exam").toggle();
|
||||
$("#cancel-add-to-exam").toggle();
|
||||
|
||||
var jqxhr = $.get(evt.target.dataset.exam_list_url, function (data) {
|
||||
console.log(data);
|
||||
@@ -380,11 +388,18 @@
|
||||
<style>
|
||||
.toggle-button {
|
||||
font-size: x-small;
|
||||
opacity: 10%;
|
||||
opacity: 30%;
|
||||
}
|
||||
|
||||
.toggle-button:hover {
|
||||
font-size: x-small;
|
||||
opacity: 100%;
|
||||
}
|
||||
|
||||
#cancel-add-to-exam {
|
||||
border-style: dashed;
|
||||
}
|
||||
#cancel-add-to-exam:hover {
|
||||
background-color: purple;
|
||||
}
|
||||
</style>
|
||||
@@ -33,6 +33,18 @@ def create_superuser(db, django_user_model):
|
||||
"admin", "ross@xkjq.uk", "adminpassword"
|
||||
)
|
||||
|
||||
@pytest.fixture(params=EXAM_VIEWS)
|
||||
def set_up_exams(request, django_user_model, create_superuser):
|
||||
basic_user = django_user_model.objects.create_user(
|
||||
"user1", "user@user.net", "pass2"
|
||||
)
|
||||
|
||||
e1 = request.param.Exam.objects.create(name="test exam", exam_mode=True)
|
||||
e = request.param.Exam.objects.create(name="test exam 2", exam_mode=True)
|
||||
e.author.add(basic_user)
|
||||
return request.param
|
||||
|
||||
|
||||
|
||||
# @pytest.fixture
|
||||
# def create_exam(db):
|
||||
@@ -40,6 +52,18 @@ def create_superuser(db, django_user_model):
|
||||
|
||||
# Very basic tests, make sure we can hit key urls without error
|
||||
|
||||
def test_index2(client, set_up_exams):
|
||||
client.login(username="admin", password="adminpassword")
|
||||
response = client.get(reverse(f"{set_up_exams.app_name}:index"))
|
||||
assert response.status_code == 200
|
||||
|
||||
assert (
|
||||
BeautifulSoup(response.content, "html.parser")
|
||||
.find("h4", {"class": "exam-number-title"})
|
||||
.getText()
|
||||
== "2 exams found."
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("exam_views", EXAM_VIEWS)
|
||||
def test_index(client, create_superuser, exam_views, django_user_model):
|
||||
@@ -63,6 +87,15 @@ def test_index(client, create_superuser, exam_views, django_user_model):
|
||||
== "2 exams found."
|
||||
)
|
||||
|
||||
|
||||
response = client.get(reverse(f"{exam_views.app_name}:exam_list"))
|
||||
assert response.status_code == 200
|
||||
assert (
|
||||
len(BeautifulSoup(response.content, "html.parser")
|
||||
.select("a.exam-name"))
|
||||
== 2
|
||||
)
|
||||
|
||||
if exam_views.app_name in JSON_APPS:
|
||||
response = client.get(reverse(f"{exam_views.app_name}:active_exams"))
|
||||
|
||||
@@ -86,7 +119,6 @@ def test_index(client, create_superuser, exam_views, django_user_model):
|
||||
HTTP_X_REQUESTED_WITH="XMLHttpRequest",
|
||||
)
|
||||
|
||||
print(f"{e1.valid_user_users.all()=}")
|
||||
|
||||
assert json.loads(add_user_response.content)["status"] == "success"
|
||||
|
||||
@@ -103,6 +135,15 @@ def test_index(client, create_superuser, exam_views, django_user_model):
|
||||
== "1 exams found."
|
||||
)
|
||||
|
||||
response = client.get(reverse(f"{exam_views.app_name}:exam_list"))
|
||||
|
||||
assert (
|
||||
len(BeautifulSoup(response.content, "html.parser")
|
||||
.select("a.exam-name"))
|
||||
== 1
|
||||
)
|
||||
|
||||
|
||||
if exam_views.app_name in JSON_APPS:
|
||||
response = client.get(reverse(f"{exam_views.app_name}:active_exams"))
|
||||
|
||||
|
||||
+6
-7
@@ -46,6 +46,7 @@ from generic.views import (
|
||||
AuthorRequiredMixin,
|
||||
ExamCloneMixin,
|
||||
ExamCreateBase,
|
||||
ExamDeleteBase,
|
||||
ExamUpdateBase,
|
||||
ExamViews,
|
||||
GenericViewBase,
|
||||
@@ -787,6 +788,9 @@ class ExamUpdate(ExamUpdateBase, AuthorOrCheckerRequiredMixin):
|
||||
form_class = ExamForm
|
||||
|
||||
|
||||
class ExamDelete(AuthorOrCheckerRequiredMixin, ExamDeleteBase):
|
||||
model = Exam
|
||||
|
||||
class ExamAuthorUpdate(
|
||||
RevisionMixin, LoginRequiredMixin, AuthorRequiredMixin, UpdateView
|
||||
):
|
||||
@@ -794,11 +798,6 @@ class ExamAuthorUpdate(
|
||||
form_class = ExamAuthorForm
|
||||
|
||||
|
||||
class ExamDelete(RevisionMixin, AuthorOrCheckerRequiredMixin, DeleteView):
|
||||
model = Exam
|
||||
template_name = "exam_confirm_delete.html"
|
||||
success_url = reverse_lazy("rapids:index")
|
||||
|
||||
|
||||
class UserAnswerView(LoginRequiredMixin, DetailView):
|
||||
model = CidUserAnswer
|
||||
@@ -840,9 +839,9 @@ class ExamViewSet(RevisionMixin, viewsets.ModelViewSet):
|
||||
"""
|
||||
user = self.request.user
|
||||
if user.groups.filter(name="rapid_checker").exists():
|
||||
return Exam.objects.all()
|
||||
return Exam.objects.filter(archive=False).order_by('name')
|
||||
|
||||
return Exam.objects.filter(author__id=user.id)
|
||||
return Exam.objects.filter(author__id=user.id, archive=False).order_by('name')
|
||||
|
||||
|
||||
class QuestionAnswerViewSet(viewsets.ModelViewSet):
|
||||
|
||||
+6
-44
@@ -40,7 +40,7 @@ import json
|
||||
import statistics
|
||||
import plotly.express as px
|
||||
|
||||
from generic.views import AuthorRequiredMixin, ExamCloneMixin, ExamViews, GenericViewBase
|
||||
from generic.views import AuthorRequiredMixin, ExamCloneMixin, ExamCreateBase, ExamDeleteBase, ExamUpdateBase, ExamViews, GenericViewBase
|
||||
|
||||
from rest_framework import viewsets, permissions
|
||||
from rest_framework.pagination import PageNumberPagination
|
||||
@@ -342,31 +342,17 @@ class QuestionDelete(AuthorOrCheckerRequiredMixin, DeleteView):
|
||||
success_url = reverse_lazy("sbas:question_list")
|
||||
|
||||
|
||||
class ExamCreate(RevisionMixin, LoginRequiredMixin, CreateView):
|
||||
class ExamCreate(ExamCreateBase):
|
||||
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
|
||||
):
|
||||
class ExamUpdate(ExamUpdateBase, AuthorOrCheckerRequiredMixin):
|
||||
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 ExamDelete(AuthorOrCheckerRequiredMixin, ExamDeleteBase):
|
||||
model = Exam
|
||||
|
||||
# class ExamViewSet(RevisionMixin, viewsets.ModelViewSet):
|
||||
# # queryset = Exam.objects.all().order_by('name')
|
||||
@@ -388,30 +374,6 @@ class ExamAuthorUpdate(RevisionMixin, LoginRequiredMixin, AuthorRequiredMixin, U
|
||||
form_class = ExamAuthorForm
|
||||
|
||||
|
||||
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"""
|
||||
|
||||
class ExamDelete(RevisionMixin, AuthorOrCheckerRequiredMixin, DeleteView):
|
||||
model = Exam
|
||||
template_name = "exam_confirm_delete.html"
|
||||
success_url = reverse_lazy("sbas:index")
|
||||
|
||||
|
||||
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)
|
||||
"""Clone exam view"""
|
||||
@@ -1,12 +1,10 @@
|
||||
{% extends "base.html" %}
|
||||
{% comment %} {% extends exam.app_name|add:"/base.html" %} {% endcomment %}
|
||||
{% extends view.model.app_name|add:"/base.html" %}
|
||||
|
||||
{% block js %}
|
||||
{{ form.media }}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{{form.instance}}
|
||||
|
||||
<h2>Add Exam</h2>
|
||||
<form action="" method="post">
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
<h1>Examinations</h1>
|
||||
<div class="{{app_name}}">
|
||||
Active exams:<br/>
|
||||
<ul class="exam-list">
|
||||
<ul class="exam-list exam-list-active">
|
||||
{% for exam in exams %}
|
||||
{% if exam.active %}
|
||||
<li class="exam-item">
|
||||
<a href="{% url app_name|add:':exam_overview' pk=exam.pk %}" class="flex-col-2">{{exam.name}}</a>
|
||||
<a href="{% url app_name|add:':exam_overview' pk=exam.pk %}" class="flex-col-2 exam-name">{{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>
|
||||
@@ -22,11 +22,11 @@
|
||||
</ul>
|
||||
|
||||
Inactive exams:<br/>
|
||||
<ul class="exam-list">
|
||||
<ul class="exam-list exam-list-inactive">
|
||||
{% for exam in exams %}
|
||||
{% if not exam.active %}
|
||||
<li class="exam-item">
|
||||
<a href="{% url app_name|add:':exam_overview' pk=exam.pk %}" class="flex-col-2">{{exam.name}}</a>
|
||||
<a href="{% url app_name|add:':exam_overview' pk=exam.pk %}" class="flex-col-2 exam-name">{{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>
|
||||
|
||||
Reference in New Issue
Block a user