mirror of
https://github.com/ae-utbm/sith.git
synced 2025-01-21 22:41:14 +00:00
News moderation buttons directly on the home page
This commit is contained in:
parent
185fb70dda
commit
2ca3286f0f
39
com/static/bundled/com/components/moderation-alert-index.ts
Normal file
39
com/static/bundled/com/components/moderation-alert-index.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import { exportToHtml } from "#core:utils/globals";
|
||||
import Alpine from "alpinejs";
|
||||
import { newsDeleteNews, newsModerateNews } from "#openapi";
|
||||
|
||||
// This will be used in jinja templates,
|
||||
// so we cannot use real enums as those are purely an abstraction of Typescript
|
||||
const AlertState = {
|
||||
// biome-ignore lint/style/useNamingConvention: this feels more like an enum
|
||||
PENDING: 1,
|
||||
// biome-ignore lint/style/useNamingConvention: this feels more like an enum
|
||||
MODERATED: 2,
|
||||
// biome-ignore lint/style/useNamingConvention: this feels more like an enum
|
||||
DELETED: 3,
|
||||
};
|
||||
exportToHtml("AlertState", AlertState);
|
||||
|
||||
document.addEventListener("alpine:init", () => {
|
||||
Alpine.data("moderationAlert", (newsId: number) => ({
|
||||
state: AlertState.PENDING,
|
||||
newsId: newsId as number,
|
||||
loading: false,
|
||||
|
||||
async moderateNews() {
|
||||
this.loading = true;
|
||||
// biome-ignore lint/style/useNamingConvention: api is snake case
|
||||
await newsModerateNews({ path: { news_id: this.newsId } });
|
||||
this.state = AlertState.MODERATED;
|
||||
this.loading = false;
|
||||
},
|
||||
|
||||
async deleteNews() {
|
||||
this.loading = true;
|
||||
// biome-ignore lint/style/useNamingConvention: api is snake case
|
||||
await newsDeleteNews({ path: { news_id: this.newsId } });
|
||||
this.state = AlertState.DELETED;
|
||||
this.loading = false;
|
||||
},
|
||||
}));
|
||||
});
|
@ -171,7 +171,9 @@
|
||||
}
|
||||
|
||||
.news_event {
|
||||
display: block;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: .5em;
|
||||
padding: 1em;
|
||||
|
||||
header {
|
||||
|
73
com/templates/com/macros.jinja
Normal file
73
com/templates/com/macros.jinja
Normal file
@ -0,0 +1,73 @@
|
||||
{% macro news_moderation_alert(news, user, alpineState = None) %}
|
||||
{# An alert to display on top of non moderated news,
|
||||
with actions to either moderate or delete them.
|
||||
|
||||
The current state of the alert is accessible through
|
||||
the given `alpineState` variable.
|
||||
This state is a `AlertState`, as defined in `moderation-alert-index.ts`
|
||||
|
||||
Example :
|
||||
```jinja
|
||||
<div x-data="{state: AlertState.PENDING}">
|
||||
{{ news_moderation_alert(news, user, "state") }}
|
||||
</div>
|
||||
```
|
||||
|
||||
Args:
|
||||
news: The `News` object to which this alert is related
|
||||
user: The request.user
|
||||
alpineState: An alpine variable name
|
||||
|
||||
Warning:
|
||||
If you use this macro, you must also include `moderation-alert-index.ts`
|
||||
in your template.
|
||||
#}
|
||||
<div
|
||||
x-data="moderationAlert({{ news.id }})"
|
||||
{% if alpineState %}
|
||||
x-modelable="{{ alpineState }}"
|
||||
x-model="state"
|
||||
{% endif %}
|
||||
>
|
||||
<template x-if="state === AlertState.PENDING">
|
||||
<div class="alert alert-yellow">
|
||||
<div class="alert-main">
|
||||
<strong>{% trans %}Waiting moderation{% endtrans %}</strong>
|
||||
<p>
|
||||
{% trans trimmed %}
|
||||
This news isn't moderated and is visible
|
||||
only by its author and the communication admins.
|
||||
{% endtrans %}
|
||||
</p>
|
||||
<p>
|
||||
{% trans trimmed %}
|
||||
It will stay hidden for other users until it has been moderated.
|
||||
{% endtrans %}
|
||||
</p>
|
||||
</div>
|
||||
{% if user.has_perm("com.moderate_news") %}
|
||||
<span class="alert-aside" :aria-busy="loading">
|
||||
<button class="btn btn-green" @click="moderateNews()" :disabled="loading">
|
||||
<i class="fa fa-check"></i> {% trans %}Moderate{% endtrans %}
|
||||
</button>
|
||||
{% endif %}
|
||||
{% if user.has_perm("com.delete_news") %}
|
||||
<button class="btn btn-red" @click="deleteNews()" :disabled="loading">
|
||||
<i class="fa fa-trash-can"></i> {% trans %}Delete{% endtrans %}
|
||||
</button>
|
||||
</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</template>
|
||||
<template x-if="state === AlertState.MODERATED">
|
||||
<div class="alert alert-green">
|
||||
{% trans %}News moderated{% endtrans %}
|
||||
</div>
|
||||
</template>
|
||||
<template x-if="state === AlertState.DELETED">
|
||||
<div class="alert alert-red">
|
||||
{% trans %}News deleted{% endtrans %}
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
{% endmacro %}
|
@ -1,5 +1,6 @@
|
||||
{% extends "core/base.jinja" %}
|
||||
{% from 'core/macros.jinja' import user_profile_link, facebook_share, tweet, link_news_logo, gen_news_metatags %}
|
||||
{% from "com/macros.jinja" import news_moderation_alert %}
|
||||
|
||||
{% block title %}
|
||||
{% trans %}News{% endtrans %} -
|
||||
@ -16,39 +17,49 @@
|
||||
<link rel="stylesheet" href="{{ static('com/css/news-detail.scss') }}">
|
||||
{% endblock %}
|
||||
|
||||
{% block additional_js %}
|
||||
<script type="module" src={{ static("bundled/com/components/moderation-alert-index.ts") }}></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<p><a href="{{ url('com:news_list') }}">{% trans %}Back to news{% endtrans %}</a></p>
|
||||
<section id="news_details">
|
||||
<div class="club_logo">
|
||||
<img src="{{ link_news_logo(news)}}" alt="{{ news.club }}" />
|
||||
<a href="{{ news.club.get_absolute_url() }}">{{ news.club }}</a>
|
||||
</div>
|
||||
<h4>{{ news.title }}</h4>
|
||||
<p class="date">
|
||||
<span>{{ date.start_date|localtime|date(DATETIME_FORMAT) }}
|
||||
{{ date.start_date|localtime|time(DATETIME_FORMAT) }}</span> -
|
||||
<span>{{ date.end_date|localtime|date(DATETIME_FORMAT) }}
|
||||
{{ date.end_date|localtime|time(DATETIME_FORMAT) }}</span>
|
||||
</p>
|
||||
<div class="news_content">
|
||||
<div><em>{{ news.summary|markdown }}</em></div>
|
||||
<br/>
|
||||
<div>{{ news.content|markdown }}</div>
|
||||
{{ facebook_share(news) }}
|
||||
{{ tweet(news) }}
|
||||
<div class="news_meta">
|
||||
<p>{% trans %}Author: {% endtrans %}{{ user_profile_link(news.author) }}</p>
|
||||
{% if news.moderator %}
|
||||
<p>{% trans %}Moderator: {% endtrans %}{{ user_profile_link(news.moderator) }}</p>
|
||||
{% elif user.is_com_admin %}
|
||||
<p> <a href="{{ url('com:news_moderate', news_id=news.id) }}">{% trans %}Moderate{% endtrans %}</a></p>
|
||||
{% endif %}
|
||||
{% if user.can_edit(news) %}
|
||||
<p> <a href="{{ url('com:news_edit', news_id=news.id) }}">{% trans %}Edit (will be moderated again){% endtrans %}</a></p>
|
||||
{% endif %}
|
||||
<div x-data="{newsState: AlertState.PENDING}">
|
||||
|
||||
{% if not news.is_moderated %}
|
||||
{{ news_moderation_alert(news, user, "newsState") }}
|
||||
{% endif %}
|
||||
<article id="news_details" x-show="newsState !== AlertState.DELETED">
|
||||
<div class="club_logo">
|
||||
<img src="{{ link_news_logo(news)}}" alt="{{ news.club }}" />
|
||||
<a href="{{ news.club.get_absolute_url() }}">{{ news.club }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<h4>{{ news.title }}</h4>
|
||||
<p class="date">
|
||||
<span>{{ date.start_date|localtime|date(DATETIME_FORMAT) }}
|
||||
{{ date.start_date|localtime|time(DATETIME_FORMAT) }}</span> -
|
||||
<span>{{ date.end_date|localtime|date(DATETIME_FORMAT) }}
|
||||
{{ date.end_date|localtime|time(DATETIME_FORMAT) }}</span>
|
||||
</p>
|
||||
<div class="news_content">
|
||||
<div><em>{{ news.summary|markdown }}</em></div>
|
||||
<br/>
|
||||
<div>{{ news.content|markdown }}</div>
|
||||
{{ facebook_share(news) }}
|
||||
{{ tweet(news) }}
|
||||
<div class="news_meta">
|
||||
<p>{% trans %}Author: {% endtrans %}{{ user_profile_link(news.author) }}</p>
|
||||
{% if news.moderator %}
|
||||
<p>{% trans %}Moderator: {% endtrans %}{{ user_profile_link(news.moderator) }}</p>
|
||||
{% elif user.is_com_admin %}
|
||||
<p> <a href="{{ url('com:news_moderate', news_id=news.id) }}">{% trans %}Moderate{% endtrans %}</a></p>
|
||||
{% endif %}
|
||||
{% if user.can_edit(news) %}
|
||||
<p> <a href="{{ url('com:news_edit', news_id=news.id) }}">{% trans %}Edit (will be moderated again){% endtrans %}</a></p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
{% extends "core/base.jinja" %}
|
||||
{% from "com/macros.jinja" import news_moderation_alert %}
|
||||
|
||||
{% block title %}
|
||||
{% trans %}News{% endtrans %}
|
||||
@ -14,6 +15,7 @@
|
||||
|
||||
{% block additional_js %}
|
||||
<script type="module" src={{ static("bundled/com/components/ics-calendar-index.ts") }}></script>
|
||||
<script type="module" src={{ static("bundled/com/components/moderation-alert-index.ts") }}></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
@ -46,32 +48,39 @@
|
||||
</div>
|
||||
<div class="news_events_group_items">
|
||||
{% for date in dates_group %}
|
||||
<article class="news_event">
|
||||
<header class="row gap">
|
||||
{% if date.news.club.logo %}
|
||||
<img src="{{ date.news.club.logo.url }}" alt="{{ date.news.club }}"/>
|
||||
{% else %}
|
||||
<img src="{{ static("com/img/news.png") }}" alt="{{ date.news.club }}"/>
|
||||
{% endif %}
|
||||
<div class="header_content">
|
||||
<h4>
|
||||
<a href="{{ url('com:news_detail', news_id=date.news_id) }}">
|
||||
{{ date.news.title }}
|
||||
</a>
|
||||
</h4>
|
||||
<a href="{{ date.news.club.get_absolute_url() }}">{{ date.news.club }}</a>
|
||||
<div class="news_date">
|
||||
<time datetime="{{ date.start_date.isoformat(timespec="seconds") }}">
|
||||
{{ date.start_date|localtime|time(DATETIME_FORMAT) }}
|
||||
</time> -
|
||||
<time datetime="{{ date.end_date.isoformat(timespec="seconds") }}">
|
||||
{{ date.end_date|localtime|time(DATETIME_FORMAT) }}
|
||||
</time>
|
||||
<article class="news_event" x-data="{newsState: AlertState.PENDING}">
|
||||
{% if not date.news.is_moderated %}
|
||||
{# if a non moderated news is in the object list,
|
||||
the logged user is either an admin or the news author #}
|
||||
{{ news_moderation_alert(date.news, user, "newsState") }}
|
||||
{% endif %}
|
||||
<div x-show="newsState !== AlertState.DELETED">
|
||||
<header class="row gap">
|
||||
{% if date.news.club.logo %}
|
||||
<img src="{{ date.news.club.logo.url }}" alt="{{ date.news.club }}"/>
|
||||
{% else %}
|
||||
<img src="{{ static("com/img/news.png") }}" alt="{{ date.news.club }}"/>
|
||||
{% endif %}
|
||||
<div class="header_content">
|
||||
<h4>
|
||||
<a href="{{ url('com:news_detail', news_id=date.news_id) }}">
|
||||
{{ date.news.title }}
|
||||
</a>
|
||||
</h4>
|
||||
<a href="{{ date.news.club.get_absolute_url() }}">{{ date.news.club }}</a>
|
||||
<div class="news_date">
|
||||
<time datetime="{{ date.start_date.isoformat(timespec="seconds") }}">
|
||||
{{ date.start_date|localtime|time(DATETIME_FORMAT) }}
|
||||
</time> -
|
||||
<time datetime="{{ date.end_date.isoformat(timespec="seconds") }}">
|
||||
{{ date.end_date|localtime|time(DATETIME_FORMAT) }}
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<div class="news_content markdown">
|
||||
{{ date.news.summary|markdown }}
|
||||
</div>
|
||||
</header>
|
||||
<div class="news_content markdown">
|
||||
{{ date.news.summary|markdown }}
|
||||
</div>
|
||||
</article>
|
||||
{% endfor %}
|
||||
|
@ -244,6 +244,20 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
&.btn-green {
|
||||
$bg-color: rgba(0, 210, 83, 0.4);
|
||||
background-color: $bg-color;
|
||||
color: $black-color;
|
||||
|
||||
&:not(:disabled):hover {
|
||||
background-color: darken($bg-color, 15%);
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
background-color: lighten($bg-color, 15%);
|
||||
}
|
||||
}
|
||||
|
||||
&.btn-red {
|
||||
background-color: #fc8181;
|
||||
color: black;
|
||||
|
@ -6,7 +6,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-01-19 18:12+0100\n"
|
||||
"POT-Creation-Date: 2025-01-20 17:35+0100\n"
|
||||
"PO-Revision-Date: 2016-07-18\n"
|
||||
"Last-Translator: Maréchal <thomas.girod@utbm.fr\n"
|
||||
"Language-Team: AE info <ae.info@utbm.fr>\n"
|
||||
@ -310,7 +310,7 @@ msgstr "Compte en banque : "
|
||||
#: accounting/templates/accounting/club_account_details.jinja
|
||||
#: accounting/templates/accounting/label_list.jinja
|
||||
#: club/templates/club/club_sellings.jinja club/templates/club/mailing.jinja
|
||||
#: com/templates/com/mailing_admin.jinja
|
||||
#: com/templates/com/macros.jinja com/templates/com/mailing_admin.jinja
|
||||
#: com/templates/com/news_admin_list.jinja com/templates/com/poster_edit.jinja
|
||||
#: com/templates/com/screen_edit.jinja com/templates/com/weekmail.jinja
|
||||
#: core/templates/core/file_detail.jinja
|
||||
@ -935,10 +935,6 @@ msgstr "rôle"
|
||||
msgid "description"
|
||||
msgstr "description"
|
||||
|
||||
#: club/models.py
|
||||
msgid "past member"
|
||||
msgstr "ancien membre"
|
||||
|
||||
#: club/models.py
|
||||
msgid "Email address"
|
||||
msgstr "Adresse email"
|
||||
@ -1408,12 +1404,25 @@ msgstr "temps d'affichage"
|
||||
msgid "Begin date should be before end date"
|
||||
msgstr "La date de début doit être avant celle de fin"
|
||||
|
||||
#: com/templates/com/mailing_admin.jinja com/views.py
|
||||
#: core/templates/core/user_tools.jinja
|
||||
msgid "Mailing lists administration"
|
||||
msgstr "Administration des mailing listes"
|
||||
#: com/templates/com/macros.jinja
|
||||
msgid "Waiting moderation"
|
||||
msgstr "En attente de modération"
|
||||
|
||||
#: com/templates/com/mailing_admin.jinja
|
||||
#: com/templates/com/macros.jinja
|
||||
msgid ""
|
||||
"This news isn't moderated and is visible only by its author and the "
|
||||
"communication admins."
|
||||
msgstr ""
|
||||
"Cette nouvelle n'est pas modérée et n'est visible que par son auteur et les "
|
||||
"admins communication."
|
||||
|
||||
#: com/templates/com/macros.jinja
|
||||
msgid "It will stay hidden for other users until it has been moderated."
|
||||
msgstr ""
|
||||
"Elle sera cachée pour les autres utilisateurs tant qu'elle ne sera pas "
|
||||
"modérée."
|
||||
|
||||
#: com/templates/com/macros.jinja com/templates/com/mailing_admin.jinja
|
||||
#: com/templates/com/news_admin_list.jinja com/templates/com/news_detail.jinja
|
||||
#: core/templates/core/file_detail.jinja
|
||||
#: core/templates/core/file_moderation.jinja sas/templates/sas/moderation.jinja
|
||||
@ -1421,6 +1430,19 @@ msgstr "Administration des mailing listes"
|
||||
msgid "Moderate"
|
||||
msgstr "Modérer"
|
||||
|
||||
#: com/templates/com/macros.jinja
|
||||
msgid "News moderated"
|
||||
msgstr "Nouvelle modérée"
|
||||
|
||||
#: com/templates/com/macros.jinja
|
||||
msgid "News deleted"
|
||||
msgstr "Nouvelle supprimée"
|
||||
|
||||
#: com/templates/com/mailing_admin.jinja com/views.py
|
||||
#: core/templates/core/user_tools.jinja
|
||||
msgid "Mailing lists administration"
|
||||
msgstr "Administration des mailing listes"
|
||||
|
||||
#: com/templates/com/mailing_admin.jinja
|
||||
#, python-format
|
||||
msgid "Moderated by %(user)s"
|
||||
@ -1578,14 +1600,6 @@ msgstr "Discord AE"
|
||||
msgid "Dev Team"
|
||||
msgstr "Pôle Informatique"
|
||||
|
||||
#: com/templates/com/news_list.jinja
|
||||
msgid "Facebook"
|
||||
msgstr "Facebook"
|
||||
|
||||
#: com/templates/com/news_list.jinja
|
||||
msgid "Instagram"
|
||||
msgstr "Instagram"
|
||||
|
||||
#: com/templates/com/news_list.jinja
|
||||
msgid "Birthdays"
|
||||
msgstr "Anniversaires"
|
||||
@ -1599,6 +1613,10 @@ msgstr "%(age)s ans"
|
||||
msgid "You need to subscribe to access this content"
|
||||
msgstr "Vous devez cotiser pour accéder à ce contenu"
|
||||
|
||||
#: com/templates/com/news_list.jinja
|
||||
msgid "You cannot access this content"
|
||||
msgstr "Vous n'avez pas accès à ce contenu"
|
||||
|
||||
#: com/templates/com/poster_edit.jinja com/templates/com/poster_list.jinja
|
||||
msgid "Poster"
|
||||
msgstr "Affiche"
|
||||
@ -3299,8 +3317,8 @@ msgstr "Nom d'utilisateur, email, ou numéro de compte AE"
|
||||
|
||||
#: core/views/forms.py
|
||||
msgid ""
|
||||
"Profile: you need to be visible on the picture, in order to be recognized "
|
||||
"(e.g. by the barmen)"
|
||||
"Profile: you need to be visible on the picture, in order to be recognized (e."
|
||||
"g. by the barmen)"
|
||||
msgstr ""
|
||||
"Photo de profil: vous devez être visible sur la photo afin d'être reconnu "
|
||||
"(par exemple par les barmen)"
|
||||
@ -3906,8 +3924,8 @@ msgstr ""
|
||||
#: counter/templates/counter/mails/account_dump.jinja
|
||||
msgid "If you think this was a mistake, please mail us at ae@utbm.fr."
|
||||
msgstr ""
|
||||
"Si vous pensez qu'il s'agit d'une erreur, veuillez envoyer un mail à "
|
||||
"ae@utbm.fr."
|
||||
"Si vous pensez qu'il s'agit d'une erreur, veuillez envoyer un mail à ae@utbm."
|
||||
"fr."
|
||||
|
||||
#: counter/templates/counter/mails/account_dump.jinja
|
||||
msgid ""
|
||||
|
Loading…
Reference in New Issue
Block a user