mirror of
https://github.com/ae-utbm/sith.git
synced 2024-12-22 07:41:14 +00:00
Better style for forum messages
This commit is contained in:
parent
3e5d4c5fbb
commit
6179c3e7d4
@ -156,6 +156,38 @@
|
||||
</nav>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro paginate_jinja(page, nb_pages) %}
|
||||
<nav class="pagination">
|
||||
{% if page <= 1 %}
|
||||
<button disabled="disabled"><i class="fa fa-caret-left"></i></button>
|
||||
{% else %}
|
||||
<a href="?href={{ page - 1 }}">
|
||||
<button>
|
||||
<i class="fa fa-caret-left"></i>
|
||||
</button>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% for i in range(1, nb_pages + 1) %}
|
||||
{% if i == page %}
|
||||
<button class="active">{{ i }}</button>
|
||||
{% else %}
|
||||
<a href="?page={{ i }}">
|
||||
<button>{{ i }}</button>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if page >= nb_pages %}
|
||||
<button disabled="disabled"><i class="fa fa-caret-right"></i></button>
|
||||
{% else %}
|
||||
<a href="?href={{ page - 1 }}">
|
||||
<button>
|
||||
<i class="fa fa-caret-right"></i>
|
||||
</button>
|
||||
</a>
|
||||
{% endif %}
|
||||
</nav>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro paginate(page_obj, paginator, js_action) %}
|
||||
{% set js = js_action|default('') %}
|
||||
{% if page_obj.has_previous() or page_obj.has_next() %}
|
||||
|
@ -170,7 +170,7 @@ class Forum(models.Model):
|
||||
def is_owned_by(self, user):
|
||||
if user.is_anonymous:
|
||||
return False
|
||||
if user.is_in_group(pk=settings.SITH_GROUP_FORUM_ADMIN_ID):
|
||||
if user.is_root or user.is_in_group(pk=settings.SITH_GROUP_FORUM_ADMIN_ID):
|
||||
return True
|
||||
try:
|
||||
m = Forum._club_memberships[self.id][user.id]
|
||||
@ -273,10 +273,10 @@ class ForumTopic(models.Model):
|
||||
return self.forum.is_owned_by(user)
|
||||
|
||||
def can_be_edited_by(self, user):
|
||||
return user.can_edit(self.forum)
|
||||
return user.is_root or user.can_edit(self.forum)
|
||||
|
||||
def can_be_viewed_by(self, user):
|
||||
return user.can_view(self.forum)
|
||||
return user.is_root or user.can_view(self.forum)
|
||||
|
||||
def get_first_unread_message(self, user: User) -> ForumMessage | None:
|
||||
if not hasattr(user, "forum_infos"):
|
||||
@ -355,7 +355,7 @@ class ForumMessage(models.Model):
|
||||
return not self._deleted
|
||||
|
||||
def can_be_moderated_by(self, user):
|
||||
return self.topic.forum.is_owned_by(user) or user.id == self.author.id
|
||||
return self.topic.forum.is_owned_by(user) or user.id == self.author_id
|
||||
|
||||
def get_url(self):
|
||||
return (
|
||||
|
@ -6,21 +6,26 @@
|
||||
padding: 10px;
|
||||
font-weight: bold;
|
||||
border-radius: 5px;
|
||||
|
||||
&:hover {
|
||||
background-color: rgb(211, 211, 211);
|
||||
}
|
||||
}
|
||||
|
||||
.topic {
|
||||
border: solid $primary-neutral-color 1px;
|
||||
padding: 1px;
|
||||
margin: 1px;
|
||||
|
||||
p {
|
||||
margin: 1px;
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
a {
|
||||
color: $black-color;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
@ -30,6 +35,7 @@
|
||||
font-size: x-small;
|
||||
border: none;
|
||||
font-weight: bold;
|
||||
|
||||
a {
|
||||
padding: 1px;
|
||||
}
|
||||
@ -41,10 +47,6 @@
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.last_message date {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.last_message span {
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
@ -57,31 +59,36 @@
|
||||
background: $primary-neutral-light-color;
|
||||
padding: 1px;
|
||||
margin: 1px;
|
||||
|
||||
p {
|
||||
margin: 1px;
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
a {
|
||||
color: $black-color;
|
||||
}
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.search_bar {
|
||||
margin: 10px 0;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
height: 20px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.search_check {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.search_bouton {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.category {
|
||||
margin-top: 5px;
|
||||
background: $secondary-color;
|
||||
@ -93,66 +100,67 @@
|
||||
}
|
||||
|
||||
.message {
|
||||
padding: 1px;
|
||||
margin: 1px;
|
||||
padding: 15px;
|
||||
margin: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
background: $secondary-neutral-light-color;
|
||||
border-radius: 5px;
|
||||
border: 1px darken($secondary-neutral-light-color, 10%) solid;
|
||||
|
||||
&:nth-child(odd) {
|
||||
background: $primary-neutral-light-color;
|
||||
}
|
||||
.title {
|
||||
font-size: 100%;
|
||||
|
||||
.message-header {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
border-bottom: 0.0625rem grey dotted;
|
||||
padding-bottom: 10px;
|
||||
|
||||
img {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.message-metadata {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.message-options {
|
||||
flex: 2;
|
||||
display: flex;
|
||||
justify-content: right;
|
||||
gap: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.message-content {
|
||||
padding: 0 20px;
|
||||
|
||||
&.delete > * {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.markdown blockquote h5 {
|
||||
padding-top: 0;
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.forum-signature {
|
||||
margin: 0;
|
||||
font-size: small;
|
||||
font-style: italic;
|
||||
border-top: 0.0625rem grey dotted;
|
||||
}
|
||||
|
||||
&.unread {
|
||||
background: #e9eea1;
|
||||
}
|
||||
}
|
||||
|
||||
.msg_author.deleted {
|
||||
background: #ffcfcf;
|
||||
}
|
||||
|
||||
.msg_content {
|
||||
&.deleted {
|
||||
background: #ffefef;
|
||||
}
|
||||
display: inline-block;
|
||||
width: 80%;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.msg_author {
|
||||
display: inline-block;
|
||||
width: 19%;
|
||||
text-align: center;
|
||||
img {
|
||||
max-width: 70%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
.msg_header {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
.msg_meta {
|
||||
font-size: small;
|
||||
list-style-type: none;
|
||||
li {
|
||||
padding: 1px;
|
||||
margin: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.forum_signature {
|
||||
color: hsl(0, 0%, 75%);
|
||||
border-top: 1px solid hsl(0, 0%, 75%);
|
||||
a {
|
||||
color: hsl(0, 0%, 75%);
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -97,73 +97,81 @@
|
||||
{% endmacro %}
|
||||
|
||||
{% macro display_message(m, user, unread=False) %}
|
||||
{% if user.can_view(m) %}
|
||||
<div id="msg_{{ m.id }}" class="message {% if unread %}unread{% endif %}">
|
||||
<div class="msg_author {% if m.deleted %}deleted{% endif %}">
|
||||
{% set user_is_admin = m.topic.is_owned_by(user) %}
|
||||
<article id="msg_{{ m.id }}" class="message {% if unread %}unread{% endif %}">
|
||||
{% if user_is_admin or not m._deleted %}
|
||||
<div class="message-header">
|
||||
{% if m.author.avatar_pict %}
|
||||
<img src="{{ m.author.avatar_pict.get_download_url() }}" alt="{% trans %}Profile{% endtrans %}" id="picture" />
|
||||
{% elif m.author.profile_pict %}
|
||||
<img src="{{ m.author.profile_pict.get_download_url() }}" alt="{% trans %}Profile{% endtrans %}" id="picture" />
|
||||
{% else %}
|
||||
<img src="{{ static('core/img/unknown.jpg') }}" alt="{% trans %}Profile{% endtrans %}" id="picture" />
|
||||
{% endif %}
|
||||
<br/>
|
||||
<strong><a href="{{ m.author.get_absolute_url() }}">{{ m.author.get_short_name() }}</a></strong>
|
||||
</div>
|
||||
<div class="msg_content {% if m.deleted %}deleted{% endif %}" {% if m.id == first_unread_message_id %}id="first_unread"{% endif %}>
|
||||
<div class="msg_header">
|
||||
<div class="ib w_big title">
|
||||
<a href="{{ m.get_absolute_url() }}">
|
||||
{{ m.date|localtime|date(DATETIME_FORMAT) }}
|
||||
{{ m.date|localtime|time(DATETIME_FORMAT) }}
|
||||
{%- if m.title -%}
|
||||
- {{ m.title }}
|
||||
{%- endif -%}
|
||||
<div class="message-metadata">
|
||||
<a href="{{ m.author.get_absolute_url() }}">
|
||||
<strong>{{ m.author.get_short_name() }}</strong>
|
||||
</a>
|
||||
<a href="{{ m.get_absolute_url() }}">
|
||||
{{ m.date|localtime|date(DATETIME_FORMAT) }}
|
||||
{{ m.date|localtime|time(DATETIME_FORMAT) }}
|
||||
</a>
|
||||
</div>
|
||||
<div class="message-options">
|
||||
<a href="{{ url('forum:new_message', topic_id=m.topic.id) }}?quote_id={{ m.id }}">
|
||||
<i class="fa fa-quote-right"></i>
|
||||
</a>
|
||||
{% if user.can_edit(m) %}
|
||||
<a href="{{ url('forum:edit_message', message_id=m.id) }}">
|
||||
<i class="fa fa-pencil"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="ib w_small">
|
||||
<span><a href="{{ m.get_absolute_url() }}">#{{ m.id }}</a></span>
|
||||
<br/>
|
||||
<span><a href="{{ url('forum:new_message', topic_id=m.topic.id) }}?quote_id={{ m.id }}">
|
||||
{% trans %}Reply as quote{% endtrans %}</a></span>
|
||||
{% if user.can_edit(m) %}
|
||||
<span> <a href="{{ url('forum:edit_message', message_id=m.id) }}">{% trans %}Edit{% endtrans %}</a></span>
|
||||
{% endif %}
|
||||
{% if m.can_be_moderated_by(user) %}
|
||||
{% if m.deleted %}
|
||||
<span> <a href="{{ url('forum:undelete_message', message_id=m.id) }}">{% trans %}Undelete{% endtrans %}</a></span>
|
||||
{% else %}
|
||||
<span> <a href="{{ url('forum:delete_message', message_id=m.id) }}">{% trans %}Delete{% endtrans %}</a></span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div>
|
||||
{{ m.message|markdown }}
|
||||
{% endif %}
|
||||
|
||||
{% if user_is_admin and m._deleted %}
|
||||
<span>
|
||||
<a href="{{ url('forum:undelete_message', message_id=m.id) }}">
|
||||
{% trans %}Undelete{% endtrans %}
|
||||
</a>
|
||||
</span>
|
||||
{% endif %}
|
||||
{% if not m._deleted and (user_is_admin or user.id == m.author_id) %}
|
||||
<span>
|
||||
<a href="{{ url('forum:delete_message', message_id=m.id) }}">
|
||||
<i class="fa fa-trash"></i>
|
||||
</a>
|
||||
</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %} {# close `user.can_view(m) or user_is_admin` #}
|
||||
{% if user.can_view(m) %}
|
||||
<div
|
||||
class="message-content {%- if m.deleted -%}deleted{%- endif -%}"
|
||||
{%- if m.id == first_unread_message_id -%}id="first_unread"{%- endif -%}
|
||||
>
|
||||
{{ m.message|markdown }}
|
||||
{% if m.can_be_moderated_by(user) %}
|
||||
<ul class="msg_meta">
|
||||
{% for meta in m.metas.select_related('user').order_by('id') %}
|
||||
<li style="background: {% if m.author == meta.user %}#bfffbf{% else %}#ffffbf{% endif %}">
|
||||
{{ meta.get_action_display() }} {{ meta.user.get_short_name() }}
|
||||
{{ meta.get_action_display() }} {{ meta.user.get_short_name() }}
|
||||
{% trans %} at {% endtrans %}{{ meta.date|localtime|time(DATETIME_FORMAT) }}
|
||||
{% trans %} the {% endtrans %}{{ meta.date|localtime|date(DATETIME_FORMAT)}}</li>
|
||||
{% trans %} the {% endtrans %}{{ meta.date|localtime|date(DATETIME_FORMAT)}}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
<div class="forum_signature">{{ m.author.forum_signature|markdown }}</div>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div id="msg_{{ m.id }}" class="message">
|
||||
<div class="msg_author deleted">
|
||||
</div>
|
||||
<div class="msg_content deleted">
|
||||
<p class="ib w_big">{% trans %}Deleted or unreadable message.{% endtrans %}</p>
|
||||
<p class="ib w_small">{{ m.date|localtime|date(DATETIME_FORMAT) }} {{ m.date|localtime|time(DATETIME_FORMAT) }}</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{{ m.mark_as_read(user) or "" }}
|
||||
{% if m.author.forum_signature %}
|
||||
<div class="forum-signature">{{ m.author.forum_signature|markdown }}</div>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<div class="message-content delete">
|
||||
<p>{% trans %}Deleted or unreadable message.{% endtrans %}</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</article>
|
||||
{{ m.mark_as_read(user) or "" }}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro display_search_bar(request) %}
|
||||
|
@ -1,6 +1,7 @@
|
||||
{% extends "core/base.jinja" %}
|
||||
{% from 'core/macros.jinja' import user_profile_link %}
|
||||
{% from 'forum/macros.jinja' import display_message, display_breadcrumb, display_search_bar %}
|
||||
{% from 'core/macros.jinja' import paginate_jinja %}
|
||||
|
||||
{% block title %}
|
||||
{{ topic }}
|
||||
@ -9,25 +10,7 @@
|
||||
|
||||
{% block additional_css %}
|
||||
<link rel="stylesheet" href="{{ scss('forum/css/forum.scss') }}">
|
||||
{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
{{ super() }}
|
||||
<style type="text/css" media="all">
|
||||
.topic {
|
||||
border: solid skyblue 1px;
|
||||
padding: 2px;
|
||||
margin: 2px;
|
||||
}
|
||||
.forum {
|
||||
background: lightblue;
|
||||
padding: 2px;
|
||||
margin: 2px;
|
||||
}
|
||||
.category {
|
||||
background: skyblue;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="{{ scss('core/pagination.scss') }}">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
@ -45,30 +28,24 @@
|
||||
</p>
|
||||
|
||||
{{ display_search_bar(request) }}
|
||||
<p style="text-align: right; background: #d8e7f3;">
|
||||
{% for p in msgs.paginator.page_range %}
|
||||
<span class="ib" style="background: {% if p == msgs.number %}white{% endif %}; margin: 0;"><a href="?page={{ p }}">{{ p }}</a></span>
|
||||
{% endfor %}
|
||||
</p>
|
||||
{{ paginate_jinja(msgs.number, msgs.paginator.num_pages) }}
|
||||
|
||||
{% for m in msgs %}
|
||||
{% if m.id == first_unread_message_id %}
|
||||
<span id="first_unread"></span>
|
||||
{% endif %}
|
||||
{% if m.id >= first_unread_message_id %}
|
||||
{{ display_message(m, user, True) }}
|
||||
{% else %}
|
||||
{{ display_message(m, user, False) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<main class="message-list">
|
||||
{% for m in msgs %}
|
||||
{% if m.id == first_unread_message_id %}
|
||||
<span id="first_unread"></span>
|
||||
{% endif %}
|
||||
{% if m.id >= first_unread_message_id %}
|
||||
{{ display_message(m, user, True) }}
|
||||
{% else %}
|
||||
{{ display_message(m, user, False) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</main>
|
||||
|
||||
<p><a class="ib button" href="{{ url('forum:new_message', topic_id=topic.id) }}">{% trans %}Reply{% endtrans %}</a></p>
|
||||
|
||||
<p style="text-align: right; background: #d8e7f3;">
|
||||
{% for p in msgs.paginator.page_range %}
|
||||
<span class="ib" style="background: {% if p == msgs.number %}white{% endif %}; margin: 0;"><a href="?page={{ p }}">{{ p }}</a></span>
|
||||
{% endfor %}
|
||||
</p>
|
||||
{{ paginate_jinja(msgs.number, msgs.paginator.num_pages) }}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
@ -306,14 +306,15 @@ class ForumTopicDetailView(CanViewMixin, DetailView):
|
||||
queryset = ForumTopic.objects.select_related("forum__parent")
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
topic: ForumTopic = self.object
|
||||
kwargs = super().get_context_data(**kwargs)
|
||||
msg = self.object.get_first_unread_message(self.request.user)
|
||||
msg = topic.get_first_unread_message(self.request.user)
|
||||
if msg is None:
|
||||
kwargs["first_unread_message_id"] = math.inf
|
||||
else:
|
||||
kwargs["first_unread_message_id"] = msg.id
|
||||
paginator = Paginator(
|
||||
self.object.messages.select_related("author__avatar_pict")
|
||||
topic.messages.select_related("author__avatar_pict", "topic__forum")
|
||||
.prefetch_related("topic__forum__edit_groups", "readers")
|
||||
.order_by("date"),
|
||||
settings.SITH_FORUM_PAGE_LENGTH,
|
||||
|
Loading…
Reference in New Issue
Block a user