Skip to content

Commit

Permalink
Vision
Browse files Browse the repository at this point in the history
More realistic alternative to `current`

Add custom elements scaffold

looks right, doesn't open

found a way to use import, but not have icons modal texts displayed before script is loaded

fix usage of custom elements prototype before it was loaded

make it open the modal

dont know

some progess with native dialogs

make it look somewhat like bootstrap

progress?

make animations work

implement confirmation logic

ough, now the slots inherit values from the .card-header bar

Use `:defined` instead of `.loaded` class

more modals and fix blocktrans
  • Loading branch information
niklasmohrin committed Sep 25, 2023
1 parent 93cf241 commit 6edafce
Show file tree
Hide file tree
Showing 10 changed files with 253 additions and 69 deletions.
2 changes: 2 additions & 0 deletions evap/evaluation/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
<body>
<script type="text/javascript" src="{% static 'bootstrap/dist/js/bootstrap.bundle.min.js' %}"></script>

{% include "custom_elements.html" %}

{% block modals %}
{% if user.is_authenticated %}
{% trans 'Feedback' as title %}
Expand Down
27 changes: 27 additions & 0 deletions evap/evaluation/templates/confirmation_modal_template.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{% load static %}

<template id="confirmation-modal-template">
<link rel="stylesheet" href="{% static 'css/evap.css' %}" />

<dialog class="evap-modal-dialog">
<form method="dialog">
<div class="evap-modal-container">
<header>
<h5><slot name="title"></slot></h5>
<button class="btn-close"></button>
</header>
<section class="question-area">
<slot name="question"></slot>
</section>
<section class="button-area">
<button class="btn btn-light" autofocus>{% trans 'Cancel' %}</button>
<button class="btn ms-2" data-event-type="confirm">
<slot name="action-text"></slot>
</button>
</section>
</div>
</form>
</dialog>

<slot name="show-button"></slot>
</template>
9 changes: 9 additions & 0 deletions evap/evaluation/templates/custom_elements.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{% load static %}

{% include "confirmation_modal_template.html" %}

<script type="module">
import { ConfirmationModal } from "{% static 'js/confirmation-modal.js' %}";

customElements.define("confirmation-modal", ConfirmationModal);
</script>
59 changes: 36 additions & 23 deletions evap/grades/templates/grades_course_view.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{% extends 'grades_course_base.html' %}
{% load static %}

{% block content %}
{{ block.super }}
Expand Down Expand Up @@ -30,13 +31,45 @@ <h3 class="mb-3">{{ course.name }} ({{ semester.name }})</h3>
<a href="{% url 'grades:download_grades' grade_document.id %}" class="btn btn-sm btn-light" data-bs-toggle="tooltip" data-bs-placement="top" title="{% trans 'Download' %}"><span class="fas fa-download"></span></a>
{% if user.is_grade_publisher %}
<a href="{% url 'grades:edit_grades' grade_document.id %}" class="btn btn-sm btn-light" data-bs-toggle="tooltip" data-bs-placement="top" title="{% trans 'Edit' %}"><span class="fas fa-pencil"></span></a>
<button type="button" {{ disable_if_archived }} onclick="deleteGradedocumentModalShow({{ grade_document.id }}, '{{ grade_document.description|escapejs }}');" class="btn btn-sm btn-danger" data-bs-toggle="tooltip" data-bs-placement="top" title="{% trans 'Delete' %}">
<span class="fas fa-trash"></span>
</button>
<confirmation-modal confirm-button-class="btn-danger" data-delete-document="{{ grade_document.id }}">
<span slot="title">{% trans 'Delete grade document' %}</span>
<span slot="action-text">{% trans 'Delete grade document' %}</span>
<span slot="question">
{% blocktrans with description=grade_document.description %}
Do you really want to delete the grade document <strong>{{ description }}</strong>?
{% endblocktrans %}
</span>

<button slot="show-button" type="button" {{ disable_if_archived }} class="btn btn-sm btn-danger" data-bs-toggle="tooltip" data-bs-placement="top" title="{% trans 'Delete' %}">
<span class="fas fa-trash"></span>
</button>
</confirmation-modal>
{% endif %}
</td>
</tr>
{% endfor %}

<script type="module">
import { CSRF_HEADERS } from "{% static 'js/csrf-utils.js' %}";

document.querySelectorAll("confirmation-modal[data-delete-document]").forEach(modal => {
modal.addEventListener("confirmed", async () => {
const response = await fetch("{% url 'grades:delete_grades' %}", {
body: new URLSearchParams({grade_document_id: modal.dataset.deleteDocument}),
headers: CSRF_HEADERS,
method: "POST",
});

if (response.ok) {
const row = modal.closest("tr");
// TODO: animate
row.remove();
} else {
window.alert("{% trans 'The server is not responding.' %}");
}
});
});
</script>
</tbody>
</table>
{% else %}
Expand All @@ -49,23 +82,3 @@ <h3 class="mb-3">{{ course.name }} ({{ semester.name }})</h3>
<a href="{% url 'grades:upload_grades' course.id %}?final=true" class="btn btn-dark {{ disable_if_archived }}">{% trans 'Upload new final grades' %}</a>
{% endif %}
{% endblock %}

{% block modals %}
{{ block.super }}
{% trans 'Delete grade document' as title %}
{% trans 'Do you really want to delete the grade document <strong data-label=""></strong>?' as question %}
{% trans 'Delete grade document' as action_text %}
{% include 'confirmation_modal.html' with modal_id='deleteGradedocumentModal' title=title question=question action_text=action_text btn_type='danger' %}
<script type="text/javascript">
function deleteGradedocumentModalAction(dataId) {
fetch("{% url 'grades:delete_grades' %}", {
body: new URLSearchParams({grade_document_id: dataId}),
headers: CSRF_HEADERS,
method: "POST",
}).then(response => {
assert(response.ok);
fadeOutThenRemove(document.getElementById('grade_document-row-'+dataId));
}).catch(error => {window.alert("{% trans 'The server is not responding.' %}");});
};
</script>
{% endblock %}
76 changes: 41 additions & 35 deletions evap/grades/templates/grades_semester_view.html
Original file line number Diff line number Diff line change
Expand Up @@ -64,17 +64,38 @@ <h3 class="col-8 mb-0">
{% if num_final_grades > 0 %}
<span class="fas fa-file"></span> {{ num_final_grades }}
{% elif course.gets_no_grade_documents %}
<a href="#" onclick="confirmLateruploadModalShow({{ course.id }}, '{{ course.name|escapejs }}');">
<span class="fas fa-xmark light-link" data-bs-toggle="tooltip" data-bs-placement="top" title="{% trans 'Grade documents for this course will not be uploaded. Click to change.' %}"></span>
</a>
<confirmation-modal confirm-button-class="btn-primary" data-toggle-grades-course="{{ course.id }}">
<span slot="title">{% trans 'Will final grades be uploaded?' %}</span>
<span slot="action-text">{% trans 'Confirm' %}</span>
<span slot="question">
{% blocktrans with course_name=course.name %}
Please confirm that a grade document for the course <strong>{{ course_name }}</strong> will be uploaded later on.
{% endblocktrans %}
</span>

<a slot="show-button" href="#">
<span class="fas fa-xmark light-link" data-bs-toggle="tooltip" data-bs-placement="top" title="{% trans 'Grade documents for this course will not be uploaded. Click to change.' %}"></span>
</a>
</confirmation-modal>
{% endif %}
</td>
<td class="text-end" style="min-width:72px">
{% if not course.gets_no_grade_documents %}
{% if num_final_grades == 0 %}
<button type="button" {{ disable_if_archived }} onclick="confirmNouploadModalShow({{ course.id }}, '{{ course.name|escapejs }}');" class="btn btn-sm btn-secondary" data-bs-toggle="tooltip" data-bs-placement="top" title="{% trans 'Confirm that final grades have been submitted but will not be uploaded.' %}">
<span class="fas fa-xmark"></span>
</button>
<confirmation-modal confirm-button-class="btn-primary" data-toggle-grades-course="{{ course.id }}">
<span slot="title">{% trans 'Have final grades been submitted?' %}</span>
<span slot="action-text">{% trans 'Confirm' %}</span>
<span slot="question">
{% blocktrans with course_name=course.name %}
Please confirm that the final grades for the course <strong>{{ course_name }}</strong> have been submitted but will not be uploaded.
{% endblocktrans %}
</span>

<button slot="show-button" type="button" {{ disable_if_archived }} class="btn btn-sm btn-secondary" data-bs-toggle="tooltip" data-bs-placement="top" title="{% trans 'Confirm that final grades have been submitted but will not be uploaded.' %}">
<span class="fas fa-xmark"></span>
</button>
</confirmation-modal>

<div class="btn-group" role="group" data-bs-toggle="tooltip" data-bs-placement="top" title="{% trans 'Upload grade document' %}">
<button type="button" id="btnUpload{{ course.id }}" class="btn btn-sm btn-dark dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="fas fa-upload"></span>
Expand All @@ -93,42 +114,27 @@ <h3 class="col-8 mb-0">
{% endfor %}
</tbody>
</table>

<script type="module">
import { CSRF_HEADERS } from "{% static 'js/csrf-utils.js' %}";

document.querySelectorAll("confirmation-modal[data-toggle-grades-course]").forEach(modal => {
modal.addEventListener("confirmed", () => {
fetch("{% url 'grades:toggle_no_grades' %}", {
method: "POST",
headers: CSRF_HEADERS,
body: new URLSearchParams({"course_id": modal.dataset.toggleGradesCourse}),
}).then(() => location.reload());
});
});
</script>
{% else %}
<span class="fst-italic">{% trans 'No courses have been created yet' %}</span>
{% endif %}
</div>
</div>
{% endblock %}

{% block modals %}
{{ block.super }}
{% trans 'Have final grades been submitted?' as title %}
{% trans 'Please confirm that the final grades for the course <strong data-label=""></strong> have been submitted but will not be uploaded.' as question %}
{% trans 'Confirm' as action_text %}
{% include 'confirmation_modal.html' with modal_id='confirmNouploadModal' title=title question=question action_text=action_text btn_type='primary' %}
<script type="text/javascript">
function confirmNouploadModalAction(dataId) {
fetch("{% url 'grades:toggle_no_grades' %}", {
body: new URLSearchParams({course_id: dataId}),
headers: CSRF_HEADERS,
method: "POST",
}).then(response => {
assert(response.ok);
location.reload();
}).catch(error => {window.alert("{% trans 'The server is not responding.' %}");});
};
</script>
{% trans 'Will final grades be uploaded?' as title %}
{% trans 'Please confirm that a grade document for the course <strong data-label=""></strong> will be uploaded later on.' as question %}
{% trans 'Confirm' as action_text %}
{% include 'confirmation_modal.html' with modal_id='confirmLateruploadModal' title=title question=question action_text=action_text btn_type='primary' %}
<script type="text/javascript">
function confirmLateruploadModalAction(dataId) {
confirmNouploadModalAction(dataId);
};
</script>
{% endblock %}

{% block additional_javascript %}
<script type="module">
import {TableGrid} from "{% static 'js/datagrid.js' %}";
Expand Down
29 changes: 19 additions & 10 deletions evap/staff/templates/staff_semester_view.html
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,25 @@ <h3>
<div class="btn-switch ms-2">
<div class="btn-switch-label">{% trans 'Reward points active' %}</div>
<div class="btn-switch btn-group icon-buttons">
<button type="button" onclick="activateRewardPointsModalShow({{ semester.id }}, '{{ semester.name|escapejs }}');" class="btn btn-sm btn-light{% if rewards_active %} active{% endif %}"><span class="fas fa-check" aria-hidden="true"></span></button>
<confirmation-modal confirm-button-class="btn-primary" data-delete-document="{{ grade_document.id }}">
<span slot="title">{% trans 'Activate reward points' %}</span>
<span slot="action-text">{% trans 'Activate reward points' %}</span>
<span slot="question">
{% blocktrans with semester_name=semester.name %}
Do you want to activate the reward points for the semester <strong>{{ semester_name }}</strong>?
The activation will allow participants to receive reward points when voting and will also grant all eligible points for participants who have already voted so far.
The process will take a while.
{% endblocktrans %}
</span>

<button slot="show-button" type="button" class="btn btn-sm btn-light{% if rewards_active %} active{% endif %}"><span class="fas fa-check" aria-hidden="true"></span></button>
</confirmation-modal>

<script defer type="text/javascript">
const modal = document.currentScript.previousElementSibling;
modal.addEventListener("confirmed", () => document.getElementById("form_activation_status").requestSubmit());
</script>

<button type="submit" name="activation_status" value="off" form="form_activation_status" class="btn btn-sm btn-light{% if not rewards_active %} active{% endif %}"><span class="fas fa-xmark" aria-hidden="true"></span></button>
</div>
</div>
Expand Down Expand Up @@ -564,15 +582,6 @@ <h3>
}).catch(error => {window.alert("{% trans 'The server is not responding.' %}");});
};
</script>
{% trans 'Activate reward points' as title %}
{% blocktrans asvar question %}Do you want to activate the reward points for the semester <strong data-label=""></strong>? The activation will allow participants to receive reward points when voting and will also grant all eligible points for participants who have already voted so far. The process will take a while.{% endblocktrans %}
{% trans 'Activate reward points' as action_text %}
{% include 'confirmation_modal.html' with modal_id='activateRewardPointsModal' title=title question=question action_text=action_text btn_type='primary' %}
<script type="text/javascript">
function activateRewardPointsModalAction() {
document.getElementById("form_activation_status").requestSubmit();
}
</script>
{% endblock %}

{% block additional_javascript %}
Expand Down
1 change: 1 addition & 0 deletions evap/static/scss/_components.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@
@import "components/modal";
@import "components/tooltip";

@import "components/confirmation-modal";
@import "components/distribution-bar";
@import "components/quick-review";
77 changes: 77 additions & 0 deletions evap/static/scss/components/_confirmation-modal.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
confirmation-modal:not(:defined) > :not([slot="show-button"]) {
// Without this, the elements that are slotted into the dialog element show up as if they are just normal child
// elements and disappear once the custom element registration is done. To avoid a short flicker of these elements,
// we hide them until the constructor of the custom element has run.
display: none;
}

dialog.evap-modal-dialog {
padding: 0;
border: 1px solid $dark-gray;
border-radius: 0.5rem;
z-index: 1050;
inset-block-start: -70vh;

font-weight: initial;
line-height: initial;

// https://youtu.be/4prVdA7_6u0
&[open] {
animation: modal-enter 300ms forwards;
}

&[closing] {
display: block;
pointer-events: none;
animation: modal-exit 300ms forwards;
}

@keyframes modal-enter {
from {
transform: translateY(-100%);
opacity: 0;
}
to {
transform: translateY(0%);
opacity: 1;
}
}

@keyframes modal-exit {
from {
transform: translateY(0%);
opacity: 1;
}
to {
transform: translateY(-100%);
opacity: 0;
}
}

&::backdrop {
background-color: black;
opacity: 50%;
}

.evap-modal-container {
> * {
padding: 1rem;
}

> :not(:first-child) {
border-top: 1px solid $light-gray;
}

header {
display: flex;
flex-direction: row;
justify-content: space-between;
}

.button-area {
display: flex;
flex-flow: wrap;
justify-content: center;
}
}
}
Loading

0 comments on commit 6edafce

Please sign in to comment.