mirror of
https://github.com/ae-utbm/sith.git
synced 2026-09-07 13:04:33 +00:00
Use partials everywhere
This commit is contained in:
@@ -7,7 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Must be loaded before Apline
|
// Must be loaded before Apline
|
||||||
import htmx, { HtmxResponse } from "htmx.org";
|
import htmx from "htmx.org";
|
||||||
import "htmx.org/dist/ext/hx-alpine-compat.js";
|
import "htmx.org/dist/ext/hx-alpine-compat.js";
|
||||||
import "htmx.org/dist/ext/hx-prompt.js";
|
import "htmx.org/dist/ext/hx-prompt.js";
|
||||||
import "htmx.org/dist/ext/hx-download.js";
|
import "htmx.org/dist/ext/hx-download.js";
|
||||||
@@ -48,13 +48,20 @@ polyfillCountryFlagEmojis();
|
|||||||
/**
|
/**
|
||||||
* HTMX
|
* HTMX
|
||||||
*/
|
*/
|
||||||
document.body.addEventListener("htmx:before:request", (event) => {
|
htmx.registerExtension("aria-busy", {
|
||||||
event.target.ariaBusy = true;
|
// biome-ignore lint/style/useNamingConvention: api's name
|
||||||
|
// biome-ignore lint/suspicious/noExplicitAny: no type hint
|
||||||
|
htmx_before_request: (_: HTMLElement, detail: any) => {
|
||||||
|
detail.ctx.target.ariaBusy = "true";
|
||||||
|
},
|
||||||
|
// biome-ignore lint/style/useNamingConvention: api's name
|
||||||
|
// biome-ignore lint/suspicious/noExplicitAny: no type hint
|
||||||
|
htmx_before_swap: (elt: HTMLElement, detail: any) => {
|
||||||
|
detail.ctx.target.ariaBusy = "null";
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
document.body.addEventListener("htmx:before:swap", (event) => {
|
htmx.config.transitions = true;
|
||||||
event.target.ariaBusy = null;
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.assign(window, { htmx });
|
Object.assign(window, { htmx });
|
||||||
|
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ $pedagogy-white-text: #f0f0f0;
|
|||||||
input[type="checkbox"] {
|
input[type="checkbox"] {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
color: white;
|
color: white;
|
||||||
@@ -399,6 +400,7 @@ $pedagogy-white-text: #f0f0f0;
|
|||||||
|
|
||||||
a {
|
a {
|
||||||
color: $pedagogy-white-text;
|
color: $pedagogy-white-text;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
a:hover {
|
a:hover {
|
||||||
@@ -442,7 +444,8 @@ details.accordion>.accordion-content {
|
|||||||
border-right: none;
|
border-right: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.right {
|
.buttons {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,10 @@
|
|||||||
<form
|
<form
|
||||||
|
class="report-form"
|
||||||
hx-post="{{ request.get_full_path() }}"
|
hx-post="{{ request.get_full_path() }}"
|
||||||
hx-ext="error-callbacks"
|
|
||||||
hx-target="this"
|
hx-target="this"
|
||||||
hx-swap="outerHTML"
|
hx-swap="outerHTML"
|
||||||
hx-disabled-elt="input[type='submit']"
|
hx-disable="button input[type='submit']"
|
||||||
hx-trigger="submit"
|
hx-trigger="submit"
|
||||||
hx-callback-404="target.remove()"
|
|
||||||
>
|
>
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ form.non_field_errors() }}
|
{{ form.non_field_errors() }}
|
||||||
@@ -16,15 +15,17 @@
|
|||||||
{{ form.reporter }}
|
{{ form.reporter }}
|
||||||
{{ form.comment }}
|
{{ form.comment }}
|
||||||
|
|
||||||
|
<div class="buttons">
|
||||||
<button
|
<button
|
||||||
hx-get="{{ url('pedagogy:comment_detail', comment_id=comment_id) }}"
|
class="btn btn-red left"
|
||||||
|
hx-get="{{ ue_detail_url }}"
|
||||||
hx-target="closest form"
|
hx-target="closest form"
|
||||||
hx-swap="outerHTML"
|
hx-swap="outerHTML"
|
||||||
>
|
>
|
||||||
{% trans %}Cancel{% endtrans %}
|
{% trans %}Cancel{% endtrans %}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<p class="right" id="nique">
|
<input class="btn btn-green" type="submit" value="{% trans %}Report{% endtrans %}" />
|
||||||
<input type="submit" value="{% trans %}Report{% endtrans %}" />
|
|
||||||
</p>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
{% from "pedagogy/macros.jinja" import display_star %}
|
|
||||||
{% from "core/macros.jinja" import user_profile_link %}
|
|
||||||
|
|
||||||
<div id="comment-{{ comment.id }}" class="comment-container">
|
|
||||||
|
|
||||||
<div class="grade-block">
|
|
||||||
<div class="grade-type">
|
|
||||||
<p>{% trans %}Global grade{% endtrans %}</p>
|
|
||||||
<p>{% trans %}Utility{% endtrans %}</p>
|
|
||||||
<p>{% trans %}Interest{% endtrans %}</p>
|
|
||||||
<p>{% trans %}Teaching{% endtrans %}</p>
|
|
||||||
<p>{% trans %}Work load{% endtrans %}</p>
|
|
||||||
</div>
|
|
||||||
<div class="grade-stars">
|
|
||||||
<p>{{ display_star(comment.grade_global) }}</p>
|
|
||||||
<p>{{ display_star(comment.grade_utility) }}</p>
|
|
||||||
<p>{{ display_star(comment.grade_interest) }}</p>
|
|
||||||
<p>{{ display_star(comment.grade_teaching) }}</p>
|
|
||||||
<p>{{ display_star(comment.grade_work_load) }}</p>
|
|
||||||
</div>
|
|
||||||
<div class="grade-extension"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="comment">
|
|
||||||
<div class="anchor">
|
|
||||||
<a href="{{ url('pedagogy:ue_detail', ue_id=ue.id) }}#comment-{{ comment.id }}"><i class="fa fa-paragraph"></i></a>
|
|
||||||
</div>
|
|
||||||
{{ comment.comment|markdown }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="info">
|
|
||||||
{% if comment.is_reported %}
|
|
||||||
<p class="status-reported">
|
|
||||||
{% trans %}This comment has been reported{% endtrans %}
|
|
||||||
</p>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if comment.author_id == user.id or user.has_perm("pedagogy.change_comment") %}
|
|
||||||
<button
|
|
||||||
class="btn btn-orange action"
|
|
||||||
hx-get="{{ url('pedagogy:comment_update', comment_id=comment.id) }}"
|
|
||||||
hx-swap="outerHTML"
|
|
||||||
hx-target="#comment-{{ comment.id }}"
|
|
||||||
>
|
|
||||||
<i class="fa fa-pencil"></i> {% trans %}Edit{% endtrans %}
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
{% if comment.author_id == user.id or user.has_perm("pedagogy.delete_comment") %}
|
|
||||||
<form class="action"
|
|
||||||
hx-ext="error-callbacks"
|
|
||||||
hx-post="{{ url('pedagogy:comment_delete', comment_id=comment.id) }}"
|
|
||||||
hx-confirm='{% trans obj=object %}Are you sure you want to delete "{{ obj }}"?{% endtrans %}'
|
|
||||||
hx-swap="outerHTML"
|
|
||||||
hx-target="#comment-{{ comment.id }}"
|
|
||||||
hx-callback-404="document.getElementsByTagName('body')[0].dispatchEvent(new CustomEvent('CommentUpdate'));target.remove()"
|
|
||||||
>
|
|
||||||
{% csrf_token %}
|
|
||||||
<button class="btn btn-red action">
|
|
||||||
<i class="fa fa-trash-can"></i> {% trans %}Delete{% endtrans %}
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="comment-end-bar">
|
|
||||||
<div class="report">
|
|
||||||
<p>
|
|
||||||
<a
|
|
||||||
hx-get="{{ url('pedagogy:comment_report', comment_id=comment.id) }}"
|
|
||||||
hx-swap="outerHTML"
|
|
||||||
hx-target="#comment-{{ comment.id }}"
|
|
||||||
>
|
|
||||||
{% trans %}Report this comment{% endtrans %}
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="date"><p>{{ comment.publish_date.strftime('%d/%m/%Y') }}</p></div>
|
|
||||||
|
|
||||||
<div class="author"><p>{{ user_profile_link(comment.author) }}</p></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
@@ -56,9 +56,9 @@
|
|||||||
{{ form.comment }}
|
{{ form.comment }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p class="right">
|
<div class="buttons">
|
||||||
<input type="submit" value="{% trans %}Comment{% endtrans %}" />
|
<input type="submit" value="{% trans %}Comment{% endtrans %}" />
|
||||||
</p>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{% if form.is_creation %}
|
{% if form.is_creation %}
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
{% from "pedagogy/macros.jinja" import display_star %}
|
||||||
|
{% from "core/macros.jinja" import user_profile_link %}
|
||||||
|
|
||||||
{% if comments %}
|
{% if comments %}
|
||||||
<h2>{% trans %}Comments{% endtrans %}</h2>
|
<h2>{% trans %}Comments{% endtrans %}</h2>
|
||||||
<br>
|
<br>
|
||||||
@@ -5,6 +8,84 @@
|
|||||||
|
|
||||||
<section>
|
<section>
|
||||||
{% for comment in comments %}
|
{% for comment in comments %}
|
||||||
{% include "pedagogy/fragments/ue_comment.jinja" %}
|
|
||||||
|
<div id="comment-{{ comment.id }}" class="comment-container">
|
||||||
|
|
||||||
|
<div class="grade-block">
|
||||||
|
<div class="grade-type">
|
||||||
|
<p>{% trans %}Global grade{% endtrans %}</p>
|
||||||
|
<p>{% trans %}Utility{% endtrans %}</p>
|
||||||
|
<p>{% trans %}Interest{% endtrans %}</p>
|
||||||
|
<p>{% trans %}Teaching{% endtrans %}</p>
|
||||||
|
<p>{% trans %}Work load{% endtrans %}</p>
|
||||||
|
</div>
|
||||||
|
<div class="grade-stars">
|
||||||
|
<p>{{ display_star(comment.grade_global) }}</p>
|
||||||
|
<p>{{ display_star(comment.grade_utility) }}</p>
|
||||||
|
<p>{{ display_star(comment.grade_interest) }}</p>
|
||||||
|
<p>{{ display_star(comment.grade_teaching) }}</p>
|
||||||
|
<p>{{ display_star(comment.grade_work_load) }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="grade-extension"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="comment">
|
||||||
|
<div class="anchor">
|
||||||
|
<a href="{{ url('pedagogy:ue_detail', ue_id=ue.id) }}#comment-{{ comment.id }}"><i class="fa fa-paragraph"></i></a>
|
||||||
|
</div>
|
||||||
|
{{ comment.comment|markdown }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="info">
|
||||||
|
{% if comment.is_reported %}
|
||||||
|
<p class="status-reported">
|
||||||
|
{% trans %}This comment has been reported{% endtrans %}
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if comment.author_id == user.id or user.has_perm("pedagogy.change_comment") %}
|
||||||
|
<button
|
||||||
|
class="btn btn-orange action"
|
||||||
|
hx-get="{{ url('pedagogy:comment_update', comment_id=comment.id) }}"
|
||||||
|
hx-swap="outerHTML"
|
||||||
|
hx-target="#comment-{{ comment.id }}"
|
||||||
|
>
|
||||||
|
<i class="fa fa-pencil"></i> {% trans %}Edit{% endtrans %}
|
||||||
|
</button>
|
||||||
|
{% endif %}
|
||||||
|
{% if comment.author_id == user.id or user.has_perm("pedagogy.delete_comment") %}
|
||||||
|
<form class="action"
|
||||||
|
hx-post="{{ url('pedagogy:comment_delete', comment_id=comment.id) }}"
|
||||||
|
hx-confirm='{% trans obj=object %}Are you sure you want to delete "{{ obj }}"?{% endtrans %}'
|
||||||
|
hx-swap="outerHTML"
|
||||||
|
hx-target="#comment-{{ comment.id }}"
|
||||||
|
>
|
||||||
|
{% csrf_token %}
|
||||||
|
<button class="btn btn-red action">
|
||||||
|
<i class="fa fa-trash-can"></i> {% trans %}Delete{% endtrans %}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="comment-end-bar">
|
||||||
|
<div class="report">
|
||||||
|
<p>
|
||||||
|
<a
|
||||||
|
hx-get="{{ url('pedagogy:comment_report', comment_id=comment.id) }}"
|
||||||
|
hx-swap="outerHTML"
|
||||||
|
hx-target="#comment-{{ comment.id }}"
|
||||||
|
>
|
||||||
|
{% trans %}Report this comment{% endtrans %}
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="date"><p>{{ comment.publish_date.strftime('%d/%m/%Y') }}</p></div>
|
||||||
|
|
||||||
|
<div class="author"><p>{{ user_profile_link(comment.author) }}</p></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@@ -82,9 +82,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="comments">
|
<div id="comments">
|
||||||
{% for comment in comments %}
|
{% include "pedagogy/fragments/ue_details/comments.jinja" %}
|
||||||
{% include "pedagogy/fragments/ue_comment.jinja" %}
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ from django.urls import path
|
|||||||
from pedagogy.views import (
|
from pedagogy.views import (
|
||||||
UECommentCreateView,
|
UECommentCreateView,
|
||||||
UECommentDeleteView,
|
UECommentDeleteView,
|
||||||
UECommentDetailView,
|
|
||||||
UECommentReportCreateView,
|
UECommentReportCreateView,
|
||||||
UECommentUpdateView,
|
UECommentUpdateView,
|
||||||
UECreateView,
|
UECreateView,
|
||||||
@@ -46,11 +45,6 @@ urlpatterns = [
|
|||||||
UECommentCreateView.as_view(),
|
UECommentCreateView.as_view(),
|
||||||
name="comment_create",
|
name="comment_create",
|
||||||
),
|
),
|
||||||
path(
|
|
||||||
"comment/<int:comment_id>/",
|
|
||||||
UECommentDetailView.as_view(),
|
|
||||||
name="comment_detail",
|
|
||||||
),
|
|
||||||
path(
|
path(
|
||||||
"comment/<int:comment_id>/edit/",
|
"comment/<int:comment_id>/edit/",
|
||||||
UECommentUpdateView.as_view(),
|
UECommentUpdateView.as_view(),
|
||||||
|
|||||||
+11
-28
@@ -26,6 +26,7 @@ from django.contrib.auth.mixins import PermissionRequiredMixin
|
|||||||
from django.db.models import Exists, OuterRef
|
from django.db.models import Exists, OuterRef
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
from django.urls import reverse, reverse_lazy
|
from django.urls import reverse, reverse_lazy
|
||||||
|
from django.utils.functional import cached_property
|
||||||
from django.views.generic import (
|
from django.views.generic import (
|
||||||
CreateView,
|
CreateView,
|
||||||
DeleteView,
|
DeleteView,
|
||||||
@@ -54,12 +55,9 @@ class UECommentCreateView(PermissionRequiredMixin, FragmentMixin, CreateView):
|
|||||||
permission_required = "pedagogy.add_uecomment"
|
permission_required = "pedagogy.add_uecomment"
|
||||||
object = None # Avoid initialisation bug with FragmentMixin
|
object = None # Avoid initialisation bug with FragmentMixin
|
||||||
|
|
||||||
@property
|
@cached_property
|
||||||
def ue(self):
|
def ue(self):
|
||||||
if hasattr(self, "_ue"):
|
return get_object_or_404(UE, id=self.kwargs.get("ue_id"))
|
||||||
return self._ue
|
|
||||||
self._ue = get_object_or_404(UE, id=self.kwargs.get("ue_id"))
|
|
||||||
return self._ue
|
|
||||||
|
|
||||||
def has_permission(self):
|
def has_permission(self):
|
||||||
if self.ue.has_user_already_commented(self.request.user):
|
if self.ue.has_user_already_commented(self.request.user):
|
||||||
@@ -112,24 +110,6 @@ class UEDetailView(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class UECommentDetailView(PermissionRequiredMixin, DetailView):
|
|
||||||
model = UEComment
|
|
||||||
pk_url_kwarg = "comment_id"
|
|
||||||
template_name = "pedagogy/fragments/ue_comment.jinja"
|
|
||||||
permission_required = "pedagogy.view_ue"
|
|
||||||
context_object_name = "comment"
|
|
||||||
|
|
||||||
def get_queryset(self):
|
|
||||||
return (
|
|
||||||
super().get_queryset().viewable_by(self.request.user).annotate_is_reported()
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
|
||||||
return super().get_context_data(**kwargs) | {
|
|
||||||
"ue": getattr(self.object, "ue", None)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class UECommentUpdateView(PermissionOrAuthorRequiredMixin, AllowFragment, UpdateView):
|
class UECommentUpdateView(PermissionOrAuthorRequiredMixin, AllowFragment, UpdateView):
|
||||||
"""Allow edit of a given comment."""
|
"""Allow edit of a given comment."""
|
||||||
|
|
||||||
@@ -155,7 +135,7 @@ class UECommentUpdateView(PermissionOrAuthorRequiredMixin, AllowFragment, Update
|
|||||||
}
|
}
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
return reverse("pedagogy:comment_detail", kwargs={"comment_id": self.object.id})
|
return reverse("pedagogy:ue_detail", kwargs={"ue_id": self.object.ue.id})
|
||||||
|
|
||||||
|
|
||||||
class UECommentDeleteView(PermissionOrAuthorRequiredMixin, AllowFragment, DeleteView):
|
class UECommentDeleteView(PermissionOrAuthorRequiredMixin, AllowFragment, DeleteView):
|
||||||
@@ -173,7 +153,7 @@ class UECommentDeleteView(PermissionOrAuthorRequiredMixin, AllowFragment, Delete
|
|||||||
return response
|
return response
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
return reverse("pedagogy:comment_detail", kwargs={"comment_id": self.object.id})
|
return reverse("pedagogy:ue_detail", kwargs={"ue_id": self.object.ue.id})
|
||||||
|
|
||||||
|
|
||||||
class UEGuideView(PermissionRequiredMixin, TemplateView):
|
class UEGuideView(PermissionRequiredMixin, TemplateView):
|
||||||
@@ -195,6 +175,10 @@ class UECommentReportCreateView(PermissionRequiredMixin, AllowFragment, CreateVi
|
|||||||
self.ue_comment = get_object_or_404(UEComment, pk=kwargs["comment_id"])
|
self.ue_comment = get_object_or_404(UEComment, pk=kwargs["comment_id"])
|
||||||
return super().dispatch(request, *args, **kwargs)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def ue_detail_url(self):
|
||||||
|
return reverse("pedagogy:ue_detail", kwargs={"ue_id": self.ue_comment.ue.id})
|
||||||
|
|
||||||
def get_form_kwargs(self):
|
def get_form_kwargs(self):
|
||||||
kwargs = super().get_form_kwargs()
|
kwargs = super().get_form_kwargs()
|
||||||
kwargs["reporter_id"] = self.request.user.id
|
kwargs["reporter_id"] = self.request.user.id
|
||||||
@@ -204,6 +188,7 @@ class UECommentReportCreateView(PermissionRequiredMixin, AllowFragment, CreateVi
|
|||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
return super().get_context_data() | {
|
return super().get_context_data() | {
|
||||||
"comment_id": self.ue_comment.id,
|
"comment_id": self.ue_comment.id,
|
||||||
|
"ue_detail_url": self.ue_detail_url,
|
||||||
}
|
}
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
@@ -224,9 +209,7 @@ class UECommentReportCreateView(PermissionRequiredMixin, AllowFragment, CreateVi
|
|||||||
return resp
|
return resp
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
return reverse(
|
return self.ue_detail_url
|
||||||
"pedagogy:comment_detail", kwargs={"comment_id": self.ue_comment.id}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class UEModerationFormView(PermissionRequiredMixin, FormView):
|
class UEModerationFormView(PermissionRequiredMixin, FormView):
|
||||||
|
|||||||
Reference in New Issue
Block a user