Skip to content

Commit

Permalink
Improve javascript/views
Browse files Browse the repository at this point in the history
  • Loading branch information
JasonGrace2282 committed Oct 18, 2024
1 parent 42cf904 commit 10115b6
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 52 deletions.
18 changes: 15 additions & 3 deletions tin/apps/assignments/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,8 @@ class Meta:


class FileActionForm(forms.ModelForm):
"""A form to create (or edit) a :class:`.FileAction`."""

class Meta:
model = FileAction
fields = [
Expand All @@ -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)

Expand Down
2 changes: 1 addition & 1 deletion tin/apps/assignments/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
name="create_file_action",
),
path(
"files/actions/delete/<int:action_id>",
"<int:course_id>/files/actions/delete/",
views.delete_file_action_view,
name="delete_file_action",
),
Expand Down
23 changes: 14 additions & 9 deletions tin/apps/assignments/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
12 changes: 12 additions & 0 deletions tin/static/css/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,10 @@ a.link {
text-align: center;
}

.hidden {
visibility: hidden;
}

.tin-btn {
border: 1px solid #cfcfcf;

Expand All @@ -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;
}
Expand Down Expand Up @@ -337,6 +345,10 @@ code > pre {
color: red;
}

.red {
color: red;
}

h3.errors {
margin-bottom: 0.5em;
}
Expand Down
7 changes: 7 additions & 0 deletions tin/static/css/choose.css
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
111 changes: 73 additions & 38 deletions tin/templates/assignments/choose_file_action.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,61 +3,96 @@

{% block head %}
<link rel="stylesheet" href="{% static "css/choose.css" %}">
<script>
function addFileAction(actionId) {
$.post(
"{% url 'assignments:choose_file_action' course.id %}",
{
csrfmiddlewaretoken: "{{ csrf_token }}",
file_action: actionId,
},
function(data) {
const url = `{% url 'assignments:create_file_action' course.id %}?action=${actionId}`;
const action = $("#id_" + actionId);
action.fadeOut(200);
action.hide();
action.find("button").replaceWith(`<a class="tin-btn card-btn" href="${url}">Edit File Action</a>`);
$("#course-actions").append(action);
action.fadeIn(200);
}
);
}
<script type="text/javascript">
function addFileAction(actionId) {
$.post(
"{% url 'assignments:choose_file_action' course.id %}",
{
csrfmiddlewaretoken: "{{ csrf_token }}",
file_action: actionId,
},
function(data) {
const url = `{% url 'assignments:create_file_action' course.id %}?action=${actionId}`;
$("#id_" + actionId).fadeOut(200).promise().done((action) => {
action.find("button").replaceWith(`<a class="tin-btn card-btn" href="${url}">Edit File Action</a>`);
// whether to show the remove button on hover
action.find(".card-topright").removeClass("other-courses");
$("#course-actions").append(action);
action.fadeIn(200);
});
}
);
}

function removeFileAction(actionId) {
$.post(
"{% url 'assignments:delete_file_action' course.id %}",
{
csrfmiddlewaretoken: "{{ csrf_token }}",
file_action: actionId,
},
function(data) {
$("#id_" + actionId).fadeOut(300).promise().done((action) => {
action.find("a.tin-btn").replaceWith(`<button class="tin-btn card-btn" onclick="addFileAction(${actionId})">Add to course</button>`);
action.find(".card-topright").addClass("hidden other-courses");
$("#new-actions").append(action);
action.fadeIn(200);
});
}
);
}

$(function() {
$(".card").on("mouseenter", function() {
$(this).find(".card-topright").not(".other-courses").removeClass("hidden");
}).on("mouseleave", function() {
$(this).find(".card-topright").addClass("hidden");
});
})
</script>
{% endblock %}

{% block main %}
{% if course_actions %}
<div class="multi-part-container">
<h2>Your File Actions</h2>
<a class="tin-btn" href="{% url 'assignments:create_file_action' course.id %}">Create new file action</a>
</div>
<div class="multi-part-container" id="course-actions-title">
<h2>Your File Actions</h2>
<a class="tin-btn" href="{% url 'assignments:create_file_action' course.id %}">Create new file action</a>
</div>


<div class="row" id="course-actions">
{% for action in course_actions %}
<div class="col">
<div class="card">
<div class="card-content">
<h5 class="card-title">{{ action.name }}</h5>
<p class="card-description">{{ action.description }}</p>
<a class="tin-btn card-btn" href="{% url 'assignments:create_file_action' course.id %}?action={{ action.id }}">
Edit File Action
</a>
<div class="row" id="course-actions">
{% for action in course_actions %}
<div class="col" id="id_{{ action.id }}">
<div class="card">
<div class="card-content">
<div class="card-topright hidden">
<span onclick="removeFileAction({{ action.id }})">
<i class="fa-solid fa-trash-can red fake-btn" title="Remove from course"></i>
</span>
</div>
<h5 class="card-title">{{ action.name }}</h5>
<p class="card-description">{{ action.description }}</p>
<a class="tin-btn card-btn" href="{% url 'assignments:create_file_action' course.id %}?action={{ action.id }}">
Edit File Action
</a>
</div>
</div>
{% endfor %}
</div>
{% endif %}
</div>
{% endfor %}
</div>


<h2>Choose a File Action</h2>

<div class="row">
<div class="row" id="new-actions">
{% for action in actions %}
<div class="col" id="id_{{ action.id }}">
<div class="card">
<div class="card-content">
<div class="card-topright hidden other-courses">
<span onclick="removeFileAction({{ action.id }})">
<i class="fa-solid fa-trash-can red fake-btn" title="Remove from course"></i>
</span>
</div>
<h5 class="card-title">{{ action.name }}</h5>
<p class="card-description">{{ action.description }}</p>
<button id="btn-{{ action.id}}" class="tin-btn card-btn" onclick="addFileAction({{ action.id }})">Add to course</button>
Expand Down
4 changes: 3 additions & 1 deletion tin/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
{% include "meta.html" %}

<link rel="stylesheet" href="{% static 'css/base.css' %}">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css"
integrity="sha512-Kc323vGBEqzTmouAECnVceyQqyqdsSiqLQISBL29aUW4U/M7pSPA/gEUZQqv1cwx4OnYxTxve5UMg5GT6L4JJg=="
crossorigin="anonymous" referrerpolicy="no-referrer">
<link rel="stylesheet" type="text/css"
href="https://fonts.googleapis.com/css?family=Open+Sans:100italic,400italic,700italic,100,400,700"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"
Expand Down

0 comments on commit 10115b6

Please sign in to comment.