Skip to content

Commit 03fee06

Browse files
committed
Removed delete AJAX requests. Added edit_participation_role/tag permissions.
1 parent 16bd4c3 commit 03fee06

12 files changed

+198
-378
lines changed

course/constants.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ class participation_permission: # noqa
134134
query_participation = "query_participation"
135135
edit_participation = "edit_participation"
136136
preapprove_participation = "preapprove_participation"
137+
edit_participation_role = "edit_participation_role"
138+
edit_participation_tag = "edit_participation_tag"
137139

138140
manage_instant_flow_requests = "manage_instant_flow_requests"
139141

@@ -249,6 +251,12 @@ class participation_permission: # noqa
249251
pgettext_lazy("Participation permission", "Edit participation")),
250252
(participation_permission.preapprove_participation,
251253
pgettext_lazy("Participation permission", "Preapprove participation")),
254+
(participation_permission.edit_participation_role,
255+
pgettext_lazy(
256+
"Participation permission", "Edit participation role")),
257+
(participation_permission.edit_participation_tag,
258+
pgettext_lazy(
259+
"Participation permission", "Edit participation tag")),
252260

253261
(participation_permission.manage_instant_flow_requests,
254262
pgettext_lazy("Participation permission",

course/enrollment.py

Lines changed: 44 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
THE SOFTWARE.
2525
"""
2626

27+
import json
2728
from sys import intern
2829

2930
from django.utils.translation import (
@@ -1124,10 +1125,12 @@ def __init__(self, add_new, *args, **kwargs):
11241125

11251126
if add_new:
11261127
self.helper.add_input(
1127-
Submit("submit", _("Add")))
1128+
Submit("submit", _("Add"), css_class="btn-success"))
11281129
else:
11291130
self.helper.add_input(
1130-
Submit("submit", _("Update")))
1131+
Submit("submit", _("Update"), css_class="btn-success"))
1132+
self.helper.add_input(
1133+
Submit("delete", _("Delete"), css_class="btn-danger"))
11311134

11321135
class Meta:
11331136
model = ParticipationTag
@@ -1143,18 +1146,13 @@ def view_participation_tag_list(pctx):
11431146

11441147
return render_course_page(pctx, "course/participation-tag-list.html", {
11451148
"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": "%}",
11511149
})
11521150

11531151

11541152
@course_view
11551153
def edit_participation_tag(pctx, ptag_id):
11561154
# type: (CoursePageContext, int) -> http.HttpResponse
1157-
if not pctx.has_permission(pperm.edit_participation):
1155+
if not pctx.has_permission(pperm.edit_participation_tag):
11581156
raise PermissionDenied()
11591157

11601158
request = pctx.request
@@ -1176,13 +1174,23 @@ def edit_participation_tag(pctx, ptag_id):
11761174
form = EditParticipationTagForm(add_new, request.POST, instance=ptag)
11771175
try:
11781176
if form.is_valid():
1179-
# Ref: https://stackoverflow.com/q/21458387/3437454
1180-
with transaction.atomic():
1181-
form.save()
1182-
if add_new:
1183-
msg = _("New participation tag saved.")
1177+
if "submit" in request.POST or "update" in request.POST:
1178+
# Ref: https://stackoverflow.com/q/21458387/3437454
1179+
with transaction.atomic():
1180+
form.save()
1181+
1182+
if "submit" in request.POST:
1183+
assert add_new
1184+
msg = _("New participation tag saved.")
1185+
else:
1186+
msg = _("Changes saved.")
1187+
elif "delete" in request.POST:
1188+
ptag.delete()
1189+
msg = (_("successfully deleted participation tag '%(tag)s'.")
1190+
% {"tag": ptag.name})
11841191
else:
1185-
msg = _("Changes saved.")
1192+
raise SuspiciousOperation(_("invalid operation"))
1193+
11861194
messages.add_message(request, messages.SUCCESS, msg)
11871195
return redirect(
11881196
"relate-view_participation_tags", pctx.course.identifier)
@@ -1199,48 +1207,6 @@ def edit_participation_tag(pctx, ptag_id):
11991207
"form": form,
12001208
})
12011209

1202-
1203-
@course_view
1204-
def delete_participation_tag(pctx, ptag_id):
1205-
# type: (CoursePageContext, int) -> http.HttpResponse
1206-
1207-
if not pctx.has_permission(pperm.edit_participation):
1208-
raise PermissionDenied()
1209-
1210-
request = pctx.request
1211-
1212-
if not request.is_ajax() or request.method != "POST":
1213-
raise PermissionDenied(_("only AJAX POST is allowed"))
1214-
1215-
num_ptag_id = int(ptag_id)
1216-
1217-
ptag = get_object_or_404(ParticipationTag, id=num_ptag_id)
1218-
1219-
if ptag.course.id != pctx.course.id:
1220-
raise SuspiciousOperation(
1221-
"may not delete participation tag in different course")
1222-
1223-
if "delete" in request.POST:
1224-
try:
1225-
ptag.delete()
1226-
except Exception as e:
1227-
return http.JsonResponse(
1228-
{"error": _(
1229-
"Error when deleting participation tag '%(tag)s'."
1230-
" %(error_type)s: %(error)s.") % {
1231-
"tag": ptag.name,
1232-
"error_type": type(e).__name__,
1233-
"error": str(e)}},
1234-
status=400)
1235-
else:
1236-
return http.JsonResponse(
1237-
{"message": _("successfully deleted participation tag '%(tag)s'.")
1238-
% {"tag": ptag.name},
1239-
"message_level": messages.DEFAULT_TAGS[messages.SUCCESS]})
1240-
1241-
else:
1242-
raise SuspiciousOperation(_("invalid operation"))
1243-
12441210
# }}}
12451211

12461212

@@ -1253,10 +1219,12 @@ def __init__(self, add_new, *args, **kwargs):
12531219

12541220
if add_new:
12551221
self.helper.add_input(
1256-
Submit("submit", _("Add")))
1222+
Submit("submit", _("Add"), css_class="btn-success"))
12571223
else:
12581224
self.helper.add_input(
1259-
Submit("submit", _("Update")))
1225+
Submit("submit", _("Update"), css_class="btn-success"))
1226+
self.helper.add_input(
1227+
Submit("delete", _("Delete"), css_class="btn-danger"))
12601228

12611229
class Meta:
12621230
model = ParticipationRole
@@ -1272,18 +1240,13 @@ def view_participation_role_list(pctx):
12721240

12731241
return render_course_page(pctx, "course/participation-role-list.html", {
12741242
"participation_roles": participation_roles,
1275-
1276-
# Wrappers used by JavaScript template (tmpl) so as not to
1277-
# conflict with Django template's tag wrapper
1278-
"JQ_OPEN": "{%",
1279-
"JQ_CLOSE": "%}",
12801243
})
12811244

12821245

12831246
@course_view
12841247
def edit_participation_role(pctx, prole_id):
12851248
# type: (CoursePageContext, int) -> http.HttpResponse
1286-
if not pctx.has_permission(pperm.edit_participation):
1249+
if not pctx.has_permission(pperm.edit_participation_role):
12871250
raise PermissionDenied()
12881251

12891252
request = pctx.request
@@ -1305,14 +1268,24 @@ def edit_participation_role(pctx, prole_id):
13051268
form = EditParticipationRoleForm(add_new, request.POST, instance=prole)
13061269
try:
13071270
if form.is_valid():
1308-
# Ref: https://stackoverflow.com/q/21458387/3437454
1309-
with transaction.atomic():
1310-
form.save()
1311-
1312-
if add_new:
1313-
msg = _("New participation role saved.")
1271+
if "submit" in request.POST or "update" in request.POST:
1272+
# Ref: https://stackoverflow.com/q/21458387/3437454
1273+
with transaction.atomic():
1274+
form.save()
1275+
1276+
if "submit" in request.POST:
1277+
assert add_new
1278+
msg = _("New participation role saved.")
1279+
else:
1280+
msg = _("Changes saved.")
1281+
elif "delete" in request.POST:
1282+
prole.delete()
1283+
msg = (
1284+
_("successfully deleted participation role '%(role)s'.")
1285+
% {"role": prole.identifier})
13141286
else:
1315-
msg = _("Changes saved.")
1287+
raise SuspiciousOperation(_("invalid operation"))
1288+
13161289
messages.add_message(request, messages.SUCCESS, msg)
13171290
return redirect(
13181291
"relate-view_participation_roles", pctx.course.identifier)
@@ -1329,48 +1302,6 @@ def edit_participation_role(pctx, prole_id):
13291302
"form": form,
13301303
})
13311304

1332-
1333-
@course_view
1334-
def delete_participation_role(pctx, prole_id):
1335-
# type: (CoursePageContext, int) -> http.HttpResponse
1336-
1337-
if not pctx.has_permission(pperm.edit_participation):
1338-
raise PermissionDenied()
1339-
1340-
request = pctx.request
1341-
1342-
if not request.is_ajax() or request.method != "POST":
1343-
raise PermissionDenied(_("only AJAX POST is allowed"))
1344-
1345-
num_prole_id = int(prole_id)
1346-
1347-
prole = get_object_or_404(ParticipationRole, id=num_prole_id)
1348-
1349-
if prole.course.id != pctx.course.id:
1350-
raise SuspiciousOperation(
1351-
"may not delete participation role in different course")
1352-
1353-
if "delete" in request.POST:
1354-
try:
1355-
prole.delete()
1356-
except Exception as e:
1357-
return http.JsonResponse(
1358-
{"error": _(
1359-
"Error when deleting participation role '%(role)s'."
1360-
" %(error_type)s: %(error)s.") % {
1361-
"role": prole.identifier,
1362-
"error_type": type(e).__name__,
1363-
"error": str(e)}},
1364-
status=400)
1365-
else:
1366-
return http.JsonResponse(
1367-
{"message": _("successfully deleted participation role '%(role)s'.")
1368-
% {"role": prole.identifier},
1369-
"message_level": messages.DEFAULT_TAGS[messages.SUCCESS]})
1370-
1371-
else:
1372-
raise SuspiciousOperation(_("invalid operation"))
1373-
13741305
# }}}
13751306

13761307

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Generated by Django 3.0.8 on 2020-10-26 08:48
2+
3+
from __future__ import unicode_literals
4+
5+
from django.db import migrations, models
6+
7+
8+
def add_edit_prole_and_ptag_permission(apps, schema_editor):
9+
from course.constants import participation_permission as pperm
10+
11+
ParticipationRolePermission = apps.get_model("course", "ParticipationRolePermission") # noqa
12+
13+
roles_pks = (
14+
ParticipationRolePermission.objects.filter(
15+
permission=pperm.preapprove_participation)
16+
.values_list("role", flat=True)
17+
)
18+
19+
if roles_pks.count():
20+
for pk in roles_pks:
21+
ParticipationRolePermission.objects.get_or_create(
22+
role_id=pk,
23+
permission=pperm.edit_participation_role
24+
)
25+
ParticipationRolePermission.objects.get_or_create(
26+
role_id=pk,
27+
permission=pperm.edit_participation_tag
28+
)
29+
30+
31+
class Migration(migrations.Migration):
32+
33+
dependencies = [
34+
('course', '0113_merge_20190919_1408'),
35+
]
36+
37+
operations = [
38+
migrations.AlterField(
39+
model_name='participationpermission',
40+
name='permission',
41+
field=models.CharField(choices=[('edit_course', 'Edit course'), ('use_admin_interface', 'Use admin interface'), ('manage_authentication_tokens', 'Manage authentication tokens'), ('impersonate_role', 'Impersonate role'), ('set_fake_time', 'Set fake time'), ('set_pretend_facility', 'Pretend to be in facility'), ('edit_course_permissions', 'Edit course permissions'), ('view_hidden_course_page', 'View hidden course page'), ('view_calendar', 'View calendar'), ('send_instant_message', 'Send instant message'), ('access_files_for', 'Access files for'), ('included_in_grade_statistics', 'Included in grade statistics'), ('skip_during_manual_grading', 'Skip during manual grading'), ('edit_exam', 'Edit exam'), ('issue_exam_ticket', 'Issue exam ticket'), ('batch_issue_exam_ticket', 'Batch issue exam ticket'), ('view_participant_masked_profile', "View participants' masked profile only"), ('view_flow_sessions_from_role', 'View flow sessions from role'), ('view_gradebook', 'View gradebook'), ('edit_grading_opportunity', 'Edit grading opportunity'), ('assign_grade', 'Assign grade'), ('view_grader_stats', 'View grader stats'), ('batch_import_grade', 'Batch-import grades'), ('batch_export_grade', 'Batch-export grades'), ('batch_download_submission', 'Batch-download submissions'), ('impose_flow_session_deadline', 'Impose flow session deadline'), ('batch_impose_flow_session_deadline', 'Batch-impose flow session deadline'), ('end_flow_session', 'End flow session'), ('batch_end_flow_session', 'Batch-end flow sessions'), ('regrade_flow_session', 'Regrade flow session'), ('batch_regrade_flow_session', 'Batch-regrade flow sessions'), ('recalculate_flow_session_grade', 'Recalculate flow session grade'), ('batch_recalculate_flow_session_grade', 'Batch-recalculate flow sesssion grades'), ('reopen_flow_session', 'Reopen flow session'), ('grant_exception', 'Grant exception'), ('view_analytics', 'View analytics'), ('preview_content', 'Preview content'), ('update_content', 'Update content'), ('use_git_endpoint', 'Use direct git endpoint'), ('use_markup_sandbox', 'Use markup sandbox'), ('use_page_sandbox', 'Use page sandbox'), ('test_flow', 'Test flow'), ('edit_events', 'Edit events'), ('query_participation', 'Query participation'), ('edit_participation', 'Edit participation'), ('preapprove_participation', 'Preapprove participation'), ('edit_participation_role', 'Edit participation role'), ('edit_participation_tag', 'Edit participation tag'), ('manage_instant_flow_requests', 'Manage instant flow requests')], db_index=True, max_length=200, verbose_name='Permission'),
42+
),
43+
migrations.AlterField(
44+
model_name='participationrolepermission',
45+
name='permission',
46+
field=models.CharField(choices=[('edit_course', 'Edit course'), ('use_admin_interface', 'Use admin interface'), ('manage_authentication_tokens', 'Manage authentication tokens'), ('impersonate_role', 'Impersonate role'), ('set_fake_time', 'Set fake time'), ('set_pretend_facility', 'Pretend to be in facility'), ('edit_course_permissions', 'Edit course permissions'), ('view_hidden_course_page', 'View hidden course page'), ('view_calendar', 'View calendar'), ('send_instant_message', 'Send instant message'), ('access_files_for', 'Access files for'), ('included_in_grade_statistics', 'Included in grade statistics'), ('skip_during_manual_grading', 'Skip during manual grading'), ('edit_exam', 'Edit exam'), ('issue_exam_ticket', 'Issue exam ticket'), ('batch_issue_exam_ticket', 'Batch issue exam ticket'), ('view_participant_masked_profile', "View participants' masked profile only"), ('view_flow_sessions_from_role', 'View flow sessions from role'), ('view_gradebook', 'View gradebook'), ('edit_grading_opportunity', 'Edit grading opportunity'), ('assign_grade', 'Assign grade'), ('view_grader_stats', 'View grader stats'), ('batch_import_grade', 'Batch-import grades'), ('batch_export_grade', 'Batch-export grades'), ('batch_download_submission', 'Batch-download submissions'), ('impose_flow_session_deadline', 'Impose flow session deadline'), ('batch_impose_flow_session_deadline', 'Batch-impose flow session deadline'), ('end_flow_session', 'End flow session'), ('batch_end_flow_session', 'Batch-end flow sessions'), ('regrade_flow_session', 'Regrade flow session'), ('batch_regrade_flow_session', 'Batch-regrade flow sessions'), ('recalculate_flow_session_grade', 'Recalculate flow session grade'), ('batch_recalculate_flow_session_grade', 'Batch-recalculate flow sesssion grades'), ('reopen_flow_session', 'Reopen flow session'), ('grant_exception', 'Grant exception'), ('view_analytics', 'View analytics'), ('preview_content', 'Preview content'), ('update_content', 'Update content'), ('use_git_endpoint', 'Use direct git endpoint'), ('use_markup_sandbox', 'Use markup sandbox'), ('use_page_sandbox', 'Use page sandbox'), ('test_flow', 'Test flow'), ('edit_events', 'Edit events'), ('query_participation', 'Query participation'), ('edit_participation', 'Edit participation'), ('preapprove_participation', 'Preapprove participation'), ('edit_participation_role', 'Edit participation role'), ('edit_participation_tag', 'Edit participation tag'), ('manage_instant_flow_requests', 'Manage instant flow requests')], db_index=True, max_length=200, verbose_name='Permission'),
47+
),
48+
migrations.RunPython(add_edit_prole_and_ptag_permission),
49+
]

course/models.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -736,6 +736,8 @@ def add_instructor_permissions(role):
736736
rpm(role=role, permission=pp.edit_events).save()
737737
rpm(role=role, permission=pp.manage_instant_flow_requests).save()
738738
rpm(role=role, permission=pp.preapprove_participation).save()
739+
rpm(role=role, permission=pp.edit_participation_tag).save()
740+
rpm(role=role, permission=pp.edit_participation_role).save()
739741

740742
add_teaching_assistant_permissions(role)
741743

course/templates/course/course-base.html

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,16 @@
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+
{% if pperm.edit_participation or pperm.query_participation %}
5556
<li role="presentation" class="dropdown-header">{% trans "Participations" %}</li>
5657
<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>
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+
{% if pperm.query_participation %}
61+
<li><a href="{% url "relate-query_participations" course.identifier %}">{% trans "Query participations" context "menu item" %}</a></li>
6162
{% endif %}
63+
<li role="presentation" class="divider"></li>
64+
{% endif %}
6265
{% if pperm.view_analytics %}
6366
<li><a href="{% url "relate-flow_list" course.identifier %}">{% trans "Analytics Overview" %}</a></li>
6467
{% endif %}
@@ -144,7 +147,7 @@
144147
</li>
145148
{% endif %}
146149

147-
{% if pperm.query_participation or pperm.manage_instant_flow_requests or pperm.preapprove_participation %}
150+
{% if pperm.manage_instant_flow_requests or pperm.preapprove_participation %}
148151
{% if not pperm.view_participant_masked_profile %}
149152
<li class="dropdown">
150153
<a href="#" class="dropdown-toggle" data-toggle="dropdown">{% trans "Instructor" context "menu item" %}<b class="caret"></b></a>
@@ -153,10 +156,6 @@
153156
{% if pperm.preapprove_participation %}
154157
<li><a href="{% url "relate-create_preapprovals" course.identifier %}">{% trans "Preapprove enrollments" context "menu item" %}</a></li>
155158
{% endif %}
156-
{% if pperm.query_participation %}
157-
<li><a href="{% url "relate-query_participations" course.identifier %}">{% trans "Query participations" context "menu item" %}</a></li>
158-
{% endif %}
159-
160159
{% if pperm.manage_instant_flow_requests %}
161160
<li role="presentation" class="divider"></li>
162161
<li role="presentation" class="dropdown-header">{% trans "Instant flow requests" %}</li>

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
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 %}

course/templates/course/participation-role-list.html

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
{% load static %}
55

66
{% block title %}
7-
{% trans "Participation roles" %} - {{ relate_site_name }}
7+
{% trans "Participation Roles" %} - {{ relate_site_name }}
88
{% endblock %}
99

1010
{% block header_extra %}
@@ -19,7 +19,3 @@ <h1>{% trans "Participation roles" %}</h1>
1919
{% include "course/participation-role-table.html" with participation_roles=participation_roles %}
2020

2121
{% 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)