diff --git a/tin/apps/assignments/forms.py b/tin/apps/assignments/forms.py index 8ed2d08f..314cc5e1 100644 --- a/tin/apps/assignments/forms.py +++ b/tin/apps/assignments/forms.py @@ -244,6 +244,8 @@ class Meta: class FileActionForm(forms.ModelForm): + """A form to create (or edit) a :class:`.FileAction`.""" + class Meta: model = FileAction fields = [ @@ -254,12 +256,22 @@ class Meta: "match_value", "case_sensitive_match", ] - help_texts = { - "command": "You can use $FILE to reference the file that matches the below criteria." - } class ChooseFileActionForm(forms.Form): + """A form to choose a file action. + + .. warning:: + + This will allow a user to modify any file action, + including file actions that are added to a course the user + is not a teacher in. + + This form is primarily intended for use with Javascript, + where the file action id cannot be determined at template rendering + time. + """ + def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) diff --git a/tin/apps/assignments/urls.py b/tin/apps/assignments/urls.py index b82a7f73..9b8d3383 100644 --- a/tin/apps/assignments/urls.py +++ b/tin/apps/assignments/urls.py @@ -35,7 +35,7 @@ name="create_file_action", ), path( - "files/actions/delete/", + "/files/actions/delete/", views.delete_file_action_view, name="delete_file_action", ), diff --git a/tin/apps/assignments/views.py b/tin/apps/assignments/views.py index 64171402..659ff356 100644 --- a/tin/apps/assignments/views.py +++ b/tin/apps/assignments/views.py @@ -16,6 +16,7 @@ from django.urls import reverse from django.utils.text import slugify from django.utils.timezone import now +from django.views.decorators.http import require_POST from ... import sandboxing from ..auth.decorators import login_required, teacher_or_superuser_required @@ -552,20 +553,24 @@ def create_file_action(request, course_id: int): @teacher_or_superuser_required -def delete_file_action_view(request, action_id: int): - """Delete a :class:`.FileAction` +@require_POST +def delete_file_action_view(request, course_id: int): + """Removes a :class:`.FileAction` from a :class:`.Course`. + + This does NOT permanently delete the :class:`.FileAction`. Args: request: The request + course_id: The primary key of the :class:`.Course` action_id: The primary key of the :class:`.FileAction` """ - if request.user.is_superuser: - obj = FileAction - else: - obj = FileAction.objects.filter(course__teacher=request.user) - action = get_object_or_404(obj, id=action_id) - action.delete() - return redirect("courses:index") + course = get_object_or_404(Course.objects.filter_editable(request.user), id=course_id) + form = ChooseFileActionForm(request.POST) + if form.is_valid(): + action = form.cleaned_data["file_action"] + action.courses.remove(course) + return http.JsonResponse({"success": True}) + return http.JsonResponse({"success": False, "errors": form.errors.as_json()}, status=400) @teacher_or_superuser_required diff --git a/tin/static/css/base.css b/tin/static/css/base.css index 1a2a25f8..2da323f8 100644 --- a/tin/static/css/base.css +++ b/tin/static/css/base.css @@ -249,6 +249,10 @@ a.link { text-align: center; } +.hidden { + visibility: hidden; +} + .tin-btn { border: 1px solid #cfcfcf; @@ -257,6 +261,10 @@ a.link { background: linear-gradient(to bottom, #dfdfdf 0%, #cfcfcf 100%); } +.fake-btn { + cursor: pointer; +} + .form-input > :is(select.selectized, input):not(input[type='checkbox']) { min-width: 250px; } @@ -337,6 +345,10 @@ code > pre { color: red; } +.red { + color: red; +} + h3.errors { margin-bottom: 0.5em; } diff --git a/tin/static/css/choose.css b/tin/static/css/choose.css index a48a8ef1..8c5f122b 100644 --- a/tin/static/css/choose.css +++ b/tin/static/css/choose.css @@ -67,6 +67,13 @@ word-wrap: break-word; } +.card-topright { + position: absolute; + top: 0; + right: 0; + padding: 10px; +} + .card-title { font-size: 1.25rem; margin-top: 0; diff --git a/tin/templates/assignments/choose_file_action.html b/tin/templates/assignments/choose_file_action.html index 78da2029..7f74b937 100644 --- a/tin/templates/assignments/choose_file_action.html +++ b/tin/templates/assignments/choose_file_action.html @@ -3,61 +3,96 @@ {% block head %} - {% endblock %} {% block main %} - {% if course_actions %} -
-

Your File Actions

- Create new file action -
+
+

Your File Actions

+ Create new file action +
-
- {% for action in course_actions %} -
-
-
-
{{ action.name }}
-

{{ action.description }}

- - Edit File Action - +
+ {% for action in course_actions %} +
+
+
+ +
{{ action.name }}
+

{{ action.description }}

+ + Edit File Action +
- {% endfor %} -
- {% endif %} +
+ {% endfor %} +

Choose a File Action

-
+
{% for action in actions %}
+
{{ action.name }}

{{ action.description }}

diff --git a/tin/templates/base.html b/tin/templates/base.html index 7629a206..0131a3e9 100644 --- a/tin/templates/base.html +++ b/tin/templates/base.html @@ -8,7 +8,9 @@ {% include "meta.html" %} - +