Skip to content

Commit 65744eb

Browse files
committed
Non-admin CRUD views for ParticipationTag and ParticipationRole
1 parent 741d027 commit 65744eb

File tree

10 files changed

+741
-54
lines changed

10 files changed

+741
-54
lines changed

course/enrollment.py

Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1114,4 +1114,251 @@ def edit_participation(pctx, participation_id):
11141114

11151115
# }}}
11161116

1117+
1118+
# {{{ edit_participation_tag
1119+
1120+
class EditParticipationTagForm(StyledModelForm):
1121+
def __init__(self, add_new, *args, **kwargs):
1122+
# type: (bool, *Any, **Any) -> None
1123+
super(EditParticipationTagForm, self).__init__(*args, **kwargs)
1124+
1125+
if add_new:
1126+
self.helper.add_input(
1127+
Submit("submit", _("Add")))
1128+
else:
1129+
self.helper.add_input(
1130+
Submit("submit", _("Update")))
1131+
1132+
class Meta:
1133+
model = ParticipationTag
1134+
exclude = ("course",)
1135+
1136+
1137+
@course_view
1138+
def view_participation_tag_list(pctx):
1139+
if not pctx.has_permission(pperm.view_gradebook):
1140+
raise PermissionDenied(_("may not edit participation tags"))
1141+
1142+
participation_tags = list(ParticipationTag.objects.filter(course=pctx.course))
1143+
1144+
return render_course_page(pctx, "course/participation-tag-list.html", {
1145+
"participation_tags": participation_tags,
1146+
1147+
# Wrappers used by JavaScript template (tmpl) so as not to
1148+
# conflict with Django template's tag wrapper
1149+
"JQ_OPEN": "{%",
1150+
"JQ_CLOSE": "%}",
1151+
})
1152+
1153+
1154+
@course_view
1155+
def edit_participation_tag(pctx, ptag_id):
1156+
# type: (CoursePageContext, int) -> http.HttpResponse
1157+
if not pctx.has_permission(pperm.edit_participation):
1158+
raise PermissionDenied()
1159+
1160+
request = pctx.request
1161+
1162+
num_ptag_id = int(ptag_id)
1163+
1164+
if num_ptag_id == -1:
1165+
ptag = ParticipationTag(course=pctx.course)
1166+
add_new = True
1167+
else:
1168+
ptag = get_object_or_404(ParticipationTag, id=num_ptag_id)
1169+
add_new = False
1170+
1171+
if ptag.course.id != pctx.course.id:
1172+
raise SuspiciousOperation(
1173+
"may not edit participation tag in different course")
1174+
1175+
if request.method == "POST":
1176+
form = EditParticipationTagForm(add_new, request.POST, instance=ptag)
1177+
try:
1178+
if form.is_valid():
1179+
form.save()
1180+
messages.add_message(request, messages.SUCCESS, _("Changes saved."))
1181+
return redirect(
1182+
"relate-view_participation_tags", pctx.course.identifier)
1183+
except IntegrityError:
1184+
messages.add_message(
1185+
request, messages.ERROR,
1186+
_("A participation tag with that name already exists."))
1187+
1188+
else:
1189+
form = EditParticipationTagForm(add_new, instance=ptag)
1190+
1191+
return render_course_page(pctx, "course/generic-course-form.html", {
1192+
"form_description": _("Edit Participation Tag"),
1193+
"form": form,
1194+
})
1195+
1196+
1197+
@course_view
1198+
def delete_participation_tag(pctx, ptag_id):
1199+
# type: (CoursePageContext, int) -> http.HttpResponse
1200+
1201+
if not pctx.has_permission(pperm.edit_participation):
1202+
raise PermissionDenied()
1203+
1204+
request = pctx.request
1205+
1206+
if not request.is_ajax() or request.method != "POST":
1207+
raise PermissionDenied(_("only AJAX POST is allowed"))
1208+
1209+
num_ptag_id = int(ptag_id)
1210+
1211+
ptag = get_object_or_404(ParticipationTag, id=num_ptag_id)
1212+
1213+
if ptag.course.id != pctx.course.id:
1214+
raise SuspiciousOperation(
1215+
"may not delete participation tag in different course")
1216+
1217+
if "delete" in request.POST:
1218+
try:
1219+
ptag.delete()
1220+
except Exception as e:
1221+
return http.JsonResponse(
1222+
{"error": _(
1223+
"Error when deleting participation tag '%(tag)s'."
1224+
" %(error_type)s: %(error)s.") % {
1225+
"tag": ptag.name,
1226+
"error_type": type(e).__name__,
1227+
"error": str(e)}},
1228+
status=400)
1229+
else:
1230+
return http.JsonResponse(
1231+
{"message": _("successfully deleted participation tag '%(tag)s'.")
1232+
% {"tag": ptag.name},
1233+
"message_level": messages.DEFAULT_TAGS[messages.SUCCESS]})
1234+
1235+
else:
1236+
raise SuspiciousOperation(_("invalid operation"))
1237+
1238+
# }}}
1239+
1240+
1241+
# {{{ edit_participation_role
1242+
1243+
class EditParticipationRoleForm(StyledModelForm):
1244+
def __init__(self, add_new, *args, **kwargs):
1245+
# type: (bool, *Any, **Any) -> None
1246+
super(EditParticipationRoleForm, self).__init__(*args, **kwargs)
1247+
1248+
if add_new:
1249+
self.helper.add_input(
1250+
Submit("submit", _("Add")))
1251+
else:
1252+
self.helper.add_input(
1253+
Submit("submit", _("Update")))
1254+
1255+
class Meta:
1256+
model = ParticipationRole
1257+
exclude = ("course",)
1258+
1259+
1260+
@course_view
1261+
def view_participation_role_list(pctx):
1262+
if not pctx.has_permission(pperm.view_gradebook):
1263+
raise PermissionDenied(_("may not edit participation tags"))
1264+
1265+
participation_roles = list(ParticipationRole.objects.filter(course=pctx.course))
1266+
1267+
return render_course_page(pctx, "course/participation-role-list.html", {
1268+
"participation_roles": participation_roles,
1269+
1270+
# Wrappers used by JavaScript template (tmpl) so as not to
1271+
# conflict with Django template's tag wrapper
1272+
"JQ_OPEN": "{%",
1273+
"JQ_CLOSE": "%}",
1274+
})
1275+
1276+
1277+
@course_view
1278+
def edit_participation_role(pctx, prole_id):
1279+
# type: (CoursePageContext, int) -> http.HttpResponse
1280+
if not pctx.has_permission(pperm.edit_participation):
1281+
raise PermissionDenied()
1282+
1283+
request = pctx.request
1284+
1285+
num_prole_id = int(prole_id)
1286+
1287+
if num_prole_id == -1:
1288+
prole = ParticipationRole(course=pctx.course)
1289+
add_new = True
1290+
else:
1291+
prole = get_object_or_404(ParticipationRole, id=num_prole_id)
1292+
add_new = False
1293+
1294+
if prole.course.id != pctx.course.id:
1295+
raise SuspiciousOperation(
1296+
"may not edit participation role in different course")
1297+
1298+
if request.method == "POST":
1299+
form = EditParticipationRoleForm(add_new, request.POST, instance=prole)
1300+
try:
1301+
if form.is_valid():
1302+
form.save()
1303+
messages.add_message(request, messages.SUCCESS, _("Changes saved."))
1304+
return redirect(
1305+
"relate-view_participation_roles", pctx.course.identifier)
1306+
except IntegrityError:
1307+
messages.add_message(
1308+
request, messages.ERROR,
1309+
_("A participation role with that name already exists."))
1310+
1311+
else:
1312+
form = EditParticipationRoleForm(add_new, instance=prole)
1313+
1314+
return render_course_page(pctx, "course/generic-course-form.html", {
1315+
"form_description": _("Edit Participation Role"),
1316+
"form": form,
1317+
})
1318+
1319+
1320+
@course_view
1321+
def delete_participation_role(pctx, prole_id):
1322+
# type: (CoursePageContext, int) -> http.HttpResponse
1323+
1324+
if not pctx.has_permission(pperm.edit_participation):
1325+
raise PermissionDenied()
1326+
1327+
request = pctx.request
1328+
1329+
if not request.is_ajax() or request.method != "POST":
1330+
raise PermissionDenied(_("only AJAX POST is allowed"))
1331+
1332+
num_prole_id = int(prole_id)
1333+
1334+
prole = get_object_or_404(ParticipationRole, id=num_prole_id)
1335+
1336+
if prole.course.id != pctx.course.id:
1337+
raise SuspiciousOperation(
1338+
"may not delete participation role in different course")
1339+
1340+
if "delete" in request.POST:
1341+
try:
1342+
prole.delete()
1343+
except Exception as e:
1344+
return http.JsonResponse(
1345+
{"error": _(
1346+
"Error when deleting participation role '%(role)s'."
1347+
" %(error_type)s: %(error)s.") % {
1348+
"role": prole.identifier,
1349+
"error_type": type(e).__name__,
1350+
"error": str(e)}},
1351+
status=400)
1352+
else:
1353+
return http.JsonResponse(
1354+
{"message": _("successfully deleted participation role '%(role)s'.")
1355+
% {"role": prole.identifier},
1356+
"message_level": messages.DEFAULT_TAGS[messages.SUCCESS]})
1357+
1358+
else:
1359+
raise SuspiciousOperation(_("invalid operation"))
1360+
1361+
# }}}
1362+
1363+
11171364
# vim: foldmethod=marker

course/templates/course/course-base.html

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,23 @@
4848
</li>
4949
{% endif %}
5050

51-
{% if pperm.view_gradebook %}
51+
{% if pperm.view_gradebook or pperm.edit_participation %}
5252
<li class="dropdown">
5353
<a href="#" class="dropdown-toggle" data-toggle="dropdown">{% trans "Grading" context "menu item" %}<b class="caret"></b></a>
5454
<ul class="dropdown-menu">
55+
<li role="presentation" class="dropdown-header">{% trans "Participations" %}</li>
56+
<li><a href="{% url "relate-view_participant_list" course.identifier %}">{% trans "List of participants" %}</a></li>
57+
{% if pperm.edit_participation %}
58+
<li><a href="{% url "relate-view_participation_roles" course.identifier %}">{% trans "Participation roles" %}</a></li>
59+
<li><a href="{% url "relate-view_participation_tags" course.identifier %}">{% trans "Participation tags" %}</a></li>
60+
<li role="presentation" class="divider"></li>
61+
{% endif %}
5562
{% if pperm.view_analytics %}
5663
<li><a href="{% url "relate-flow_list" course.identifier %}">{% trans "Analytics Overview" %}</a></li>
5764
{% endif %}
58-
5965
{% if pperm.view_gradebook %}
6066
<li role="presentation" class="divider"></li>
6167
<li role="presentation" class="dropdown-header">{% trans "Grade Book" %}</li>
62-
<li><a href="{% url "relate-view_participant_list" course.identifier %}">{% trans "List of Participants" %}</a></li>
6368
<li><a href="{% url "relate-view_grading_opportunity_list" course.identifier %}">{% trans "List of Grading Opportunities" %}</a></li>
6469
<li><a href="{% url "relate-view_gradebook" course.identifier %}">{% trans "Grade book" %}</a></li>
6570
{% if pperm.batch_export_grade %}

course/templates/course/gradebook-participant-list.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44
{% load static %}
55

66
{% block title %}
7-
{% trans "List of Participants" %} - {{ relate_site_name }}
7+
{% trans "List of participants" %} - {{ relate_site_name }}
88
{% endblock %}
99

1010
{% block header_extra %}
1111
{% include "datatables-header.html" %}
1212
{% endblock %}
1313

1414
{% block content %}
15-
<h1>{% trans "List of Participants" %}</h1>
15+
<h1>{% trans "List of participants" %}</h1>
1616

1717
<a href="{% url "relate-edit_participation" course.identifier -1 %}" class="btn btn-default">{% trans "Add participant" %}</a>
1818

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{% extends "course/course-base.html" %}
2+
{% load i18n %}
3+
4+
{% load static %}
5+
6+
{% block title %}
7+
{% trans "Participation roles" %} - {{ relate_site_name }}
8+
{% endblock %}
9+
10+
{% block header_extra %}
11+
{% include "datatables-header.html" %}
12+
{% endblock %}
13+
14+
{% block content %}
15+
<h1>{% trans "Participation roles" %}</h1>
16+
17+
<a href="{% url "relate-edit_participation_role" course.identifier -1 %}" class="btn btn-default">{% trans "Add participation role" %}</a>
18+
19+
{% include "course/participation-role-table.html" with participation_roles=participation_roles %}
20+
21+
{% endblock %}
22+
23+
{% block page_bottom_javascript_extra %}
24+
<script src="{{ STATIC_URL }}blueimp-tmpl/js/tmpl.min.js"></script>
25+
{% endblock %}

0 commit comments

Comments
 (0)