mirror of
https://github.com/ae-utbm/sith.git
synced 2025-02-27 01:47:14 +00:00
Rename news moderate to publish
This commit is contained in:
parent
2e71275f5b
commit
4890fcf0e1
26
com/api.py
26
com/api.py
@ -40,13 +40,13 @@ class CalendarController(ControllerBase):
|
|||||||
return send_raw_file(IcsCalendar.get_internal())
|
return send_raw_file(IcsCalendar.get_internal())
|
||||||
|
|
||||||
@route.get(
|
@route.get(
|
||||||
"/unmoderated.ics",
|
"/unpublished.ics",
|
||||||
permissions=[IsAuthenticated],
|
permissions=[IsAuthenticated],
|
||||||
url_name="calendar_unmoderated",
|
url_name="calendar_unpublished",
|
||||||
)
|
)
|
||||||
def calendar_unmoderated(self):
|
def calendar_unpublished(self):
|
||||||
return HttpResponse(
|
return HttpResponse(
|
||||||
IcsCalendar.get_unmoderated(self.context.request.user),
|
IcsCalendar.get_unpublished(self.context.request.user),
|
||||||
content_type="text/calendar",
|
content_type="text/calendar",
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -54,26 +54,26 @@ class CalendarController(ControllerBase):
|
|||||||
@api_controller("/news")
|
@api_controller("/news")
|
||||||
class NewsController(ControllerBase):
|
class NewsController(ControllerBase):
|
||||||
@route.patch(
|
@route.patch(
|
||||||
"/{int:news_id}/moderate",
|
"/{int:news_id}/publish",
|
||||||
permissions=[HasPerm("com.moderate_news")],
|
permissions=[HasPerm("com.moderate_news")],
|
||||||
url_name="moderate_news",
|
url_name="moderate_news",
|
||||||
)
|
)
|
||||||
def moderate_news(self, news_id: int):
|
def publish_news(self, news_id: int):
|
||||||
news = self.get_object_or_exception(News, id=news_id)
|
news = self.get_object_or_exception(News, id=news_id)
|
||||||
if not news.is_moderated:
|
if not news.is_published:
|
||||||
news.is_moderated = True
|
news.is_published = True
|
||||||
news.moderator = self.context.request.user
|
news.moderator = self.context.request.user
|
||||||
news.save()
|
news.save()
|
||||||
|
|
||||||
@route.patch(
|
@route.patch(
|
||||||
"/{int:news_id}/remove",
|
"/{int:news_id}/unpublish",
|
||||||
permissions=[HasPerm("com.moderate_news")],
|
permissions=[HasPerm("com.moderate_news")],
|
||||||
url_name="remove_news",
|
url_name="unpublish_news",
|
||||||
)
|
)
|
||||||
def remove_news(self, news_id: int):
|
def unpublish_news(self, news_id: int):
|
||||||
news = self.get_object_or_exception(News, id=news_id)
|
news = self.get_object_or_exception(News, id=news_id)
|
||||||
if news.is_moderated:
|
if news.is_published:
|
||||||
news.is_moderated = False
|
news.is_published = False
|
||||||
news.moderator = self.context.request.user
|
news.moderator = self.context.request.user
|
||||||
news.save()
|
news.save()
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ class IcsCalendar:
|
|||||||
_ = f.write(
|
_ = f.write(
|
||||||
cls.ics_from_queryset(
|
cls.ics_from_queryset(
|
||||||
NewsDate.objects.filter(
|
NewsDate.objects.filter(
|
||||||
news__is_moderated=True,
|
news__is_published=True,
|
||||||
end_date__gte=timezone.now() - (relativedelta(months=6)),
|
end_date__gte=timezone.now() - (relativedelta(months=6)),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -71,10 +71,10 @@ class IcsCalendar:
|
|||||||
return cls._INTERNAL_CALENDAR
|
return cls._INTERNAL_CALENDAR
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_unmoderated(cls, user: User) -> bytes:
|
def get_unpublished(cls, user: User) -> bytes:
|
||||||
return cls.ics_from_queryset(
|
return cls.ics_from_queryset(
|
||||||
NewsDate.objects.viewable_by(user).filter(
|
NewsDate.objects.viewable_by(user).filter(
|
||||||
news__is_moderated=False,
|
news__is_published=False,
|
||||||
end_date__gte=timezone.now() - (relativedelta(months=6)),
|
end_date__gte=timezone.now() - (relativedelta(months=6)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
10
com/forms.py
10
com/forms.py
@ -147,8 +147,8 @@ class NewsForm(forms.ModelForm):
|
|||||||
"content": MarkdownInput,
|
"content": MarkdownInput,
|
||||||
}
|
}
|
||||||
|
|
||||||
auto_moderate = forms.BooleanField(
|
auto_publish = forms.BooleanField(
|
||||||
label=_("Automoderation"),
|
label=_("Auto publication"),
|
||||||
widget=CheckboxInput(attrs={"class": "switch"}),
|
widget=CheckboxInput(attrs={"class": "switch"}),
|
||||||
required=False,
|
required=False,
|
||||||
)
|
)
|
||||||
@ -182,12 +182,12 @@ class NewsForm(forms.ModelForm):
|
|||||||
def save(self, commit: bool = True): # noqa FBT001
|
def save(self, commit: bool = True): # noqa FBT001
|
||||||
self.instance.author = self.author
|
self.instance.author = self.author
|
||||||
if (self.author.is_com_admin or self.author.is_root) and (
|
if (self.author.is_com_admin or self.author.is_root) and (
|
||||||
self.cleaned_data.get("auto_moderate") is True
|
self.cleaned_data.get("auto_publish") is True
|
||||||
):
|
):
|
||||||
self.instance.is_moderated = True
|
self.instance.is_published = True
|
||||||
self.instance.moderator = self.author
|
self.instance.moderator = self.author
|
||||||
else:
|
else:
|
||||||
self.instance.is_moderated = False
|
self.instance.is_published = False
|
||||||
created_news = super().save(commit=commit)
|
created_news = super().save(commit=commit)
|
||||||
self.date_form.save(commit=commit, news=created_news)
|
self.date_form.save(commit=commit, news=created_news)
|
||||||
return created_news
|
return created_news
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [("com", "0008_alter_news_options_alter_newsdate_options_and_more")]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name="news", old_name="is_moderated", new_name="is_published"
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="news",
|
||||||
|
name="is_published",
|
||||||
|
field=models.BooleanField(default=False, verbose_name="is published"),
|
||||||
|
),
|
||||||
|
]
|
@ -56,7 +56,7 @@ class Sith(models.Model):
|
|||||||
|
|
||||||
class NewsQuerySet(models.QuerySet):
|
class NewsQuerySet(models.QuerySet):
|
||||||
def moderated(self) -> Self:
|
def moderated(self) -> Self:
|
||||||
return self.filter(is_moderated=True)
|
return self.filter(is_published=True)
|
||||||
|
|
||||||
def viewable_by(self, user: User) -> Self:
|
def viewable_by(self, user: User) -> Self:
|
||||||
"""Filter news that the given user can view.
|
"""Filter news that the given user can view.
|
||||||
@ -68,7 +68,7 @@ class NewsQuerySet(models.QuerySet):
|
|||||||
"""
|
"""
|
||||||
if user.has_perm("com.view_unmoderated_news"):
|
if user.has_perm("com.view_unmoderated_news"):
|
||||||
return self
|
return self
|
||||||
q_filter = Q(is_moderated=True)
|
q_filter = Q(is_published=True)
|
||||||
if user.is_authenticated:
|
if user.is_authenticated:
|
||||||
q_filter |= Q(author_id=user.id)
|
q_filter |= Q(author_id=user.id)
|
||||||
return self.filter(q_filter)
|
return self.filter(q_filter)
|
||||||
@ -104,7 +104,7 @@ class News(models.Model):
|
|||||||
verbose_name=_("author"),
|
verbose_name=_("author"),
|
||||||
on_delete=models.PROTECT,
|
on_delete=models.PROTECT,
|
||||||
)
|
)
|
||||||
is_moderated = models.BooleanField(_("is moderated"), default=False)
|
is_published = models.BooleanField(_("is published"), default=False)
|
||||||
moderator = models.ForeignKey(
|
moderator = models.ForeignKey(
|
||||||
User,
|
User,
|
||||||
related_name="moderated_news",
|
related_name="moderated_news",
|
||||||
@ -127,7 +127,7 @@ class News(models.Model):
|
|||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
super().save(*args, **kwargs)
|
super().save(*args, **kwargs)
|
||||||
if self.is_moderated:
|
if self.is_published:
|
||||||
return
|
return
|
||||||
for user in User.objects.filter(
|
for user in User.objects.filter(
|
||||||
groups__id__in=[settings.SITH_GROUP_COM_ADMIN_ID]
|
groups__id__in=[settings.SITH_GROUP_COM_ADMIN_ID]
|
||||||
@ -154,7 +154,7 @@ class News(models.Model):
|
|||||||
|
|
||||||
def can_be_viewed_by(self, user: User):
|
def can_be_viewed_by(self, user: User):
|
||||||
return (
|
return (
|
||||||
self.is_moderated
|
self.is_published
|
||||||
or user.has_perm("com.view_unmoderated_news")
|
or user.has_perm("com.view_unmoderated_news")
|
||||||
or (user.is_authenticated and self.author_id == user.id)
|
or (user.is_authenticated and self.author_id == user.id)
|
||||||
)
|
)
|
||||||
@ -162,7 +162,7 @@ class News(models.Model):
|
|||||||
|
|
||||||
def news_notification_callback(notif):
|
def news_notification_callback(notif):
|
||||||
count = News.objects.filter(
|
count = News.objects.filter(
|
||||||
dates__start_date__gt=timezone.now(), is_moderated=False
|
dates__start_date__gt=timezone.now(), is_published=False
|
||||||
).count()
|
).count()
|
||||||
if count:
|
if count:
|
||||||
notif.viewed = False
|
notif.viewed = False
|
||||||
@ -182,7 +182,7 @@ class NewsDateQuerySet(models.QuerySet):
|
|||||||
"""
|
"""
|
||||||
if user.has_perm("com.view_unmoderated_news"):
|
if user.has_perm("com.view_unmoderated_news"):
|
||||||
return self
|
return self
|
||||||
q_filter = Q(news__is_moderated=True)
|
q_filter = Q(news__is_published=True)
|
||||||
if user.is_authenticated:
|
if user.is_authenticated:
|
||||||
q_filter |= Q(news__author_id=user.id)
|
q_filter |= Q(news__author_id=user.id)
|
||||||
return self.filter(q_filter)
|
return self.filter(q_filter)
|
||||||
@ -337,7 +337,7 @@ class Screen(models.Model):
|
|||||||
|
|
||||||
def active_posters(self):
|
def active_posters(self):
|
||||||
now = timezone.now()
|
now = timezone.now()
|
||||||
return self.posters.filter(is_moderated=True, date_begin__lte=now).filter(
|
return self.posters.filter(d=True, date_begin__lte=now).filter(
|
||||||
Q(date_end__isnull=True) | Q(date_end__gte=now)
|
Q(date_end__isnull=True) | Q(date_end__gte=now)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -15,14 +15,14 @@ class NewsDateFilterSchema(FilterSchema):
|
|||||||
after: datetime | None = Field(None, q="start_date__gt")
|
after: datetime | None = Field(None, q="start_date__gt")
|
||||||
club_id: int | None = Field(None, q="news__club_id")
|
club_id: int | None = Field(None, q="news__club_id")
|
||||||
news_id: int | None = None
|
news_id: int | None = None
|
||||||
is_moderated: bool | None = Field(None, q="news__is_moderated")
|
is_published: bool | None = Field(None, q="news__is_published")
|
||||||
title: str | None = Field(None, q="news__title__icontains")
|
title: str | None = Field(None, q="news__title__icontains")
|
||||||
|
|
||||||
|
|
||||||
class NewsSchema(ModelSchema):
|
class NewsSchema(ModelSchema):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = News
|
model = News
|
||||||
fields = ["id", "title", "summary", "is_moderated"]
|
fields = ["id", "title", "summary", "is_published"]
|
||||||
|
|
||||||
club: ClubProfileSchema
|
club: ClubProfileSchema
|
||||||
url: str
|
url: str
|
||||||
|
@ -10,10 +10,10 @@ import listPlugin from "@fullcalendar/list";
|
|||||||
import {
|
import {
|
||||||
calendarCalendarExternal,
|
calendarCalendarExternal,
|
||||||
calendarCalendarInternal,
|
calendarCalendarInternal,
|
||||||
calendarCalendarUnmoderated,
|
calendarCalendarUnpublished,
|
||||||
newsDeleteNews,
|
newsDeleteNews,
|
||||||
newsModerateNews,
|
newsPublishNews,
|
||||||
newsRemoveNews,
|
newsUnpublishNews,
|
||||||
} from "#openapi";
|
} from "#openapi";
|
||||||
|
|
||||||
@registerComponent("ics-calendar")
|
@registerComponent("ics-calendar")
|
||||||
@ -89,15 +89,15 @@ export class IcsCalendar extends inheritHtmlElement("div") {
|
|||||||
this.calendar.refetchEvents();
|
this.calendar.refetchEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
async moderateNews(id: number) {
|
async publishNews(id: number) {
|
||||||
await newsModerateNews({
|
await newsPublishNews({
|
||||||
path: {
|
path: {
|
||||||
// biome-ignore lint/style/useNamingConvention: python API
|
// biome-ignore lint/style/useNamingConvention: python API
|
||||||
news_id: id,
|
news_id: id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
this.dispatchEvent(
|
this.dispatchEvent(
|
||||||
new CustomEvent("calendar-moderate", {
|
new CustomEvent("calendar-publish", {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
detail: {
|
detail: {
|
||||||
id: id,
|
id: id,
|
||||||
@ -107,15 +107,15 @@ export class IcsCalendar extends inheritHtmlElement("div") {
|
|||||||
await this.refreshEvents();
|
await this.refreshEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
async removeNews(id: number) {
|
async unpublishNews(id: number) {
|
||||||
await newsRemoveNews({
|
await newsUnpublishNews({
|
||||||
path: {
|
path: {
|
||||||
// biome-ignore lint/style/useNamingConvention: python API
|
// biome-ignore lint/style/useNamingConvention: python API
|
||||||
news_id: id,
|
news_id: id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
this.dispatchEvent(
|
this.dispatchEvent(
|
||||||
new CustomEvent("calendar-remove", {
|
new CustomEvent("calendar-unpublish", {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
detail: {
|
detail: {
|
||||||
id: id,
|
id: id,
|
||||||
@ -157,10 +157,10 @@ export class IcsCalendar extends inheritHtmlElement("div") {
|
|||||||
className: "external",
|
className: "external",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
url: `${await makeUrl(calendarCalendarUnmoderated)}${cacheInvalidate}`,
|
url: `${await makeUrl(calendarCalendarUnpublished)}${cacheInvalidate}`,
|
||||||
format: "ics",
|
format: "ics",
|
||||||
color: "red",
|
color: "red",
|
||||||
className: "unmoderated",
|
className: "unpublished",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -233,20 +233,20 @@ export class IcsCalendar extends inheritHtmlElement("div") {
|
|||||||
const newsId = this.getNewsId(event);
|
const newsId = this.getNewsId(event);
|
||||||
const div = document.createElement("div");
|
const div = document.createElement("div");
|
||||||
if (this.canModerate) {
|
if (this.canModerate) {
|
||||||
if (event.source.internalEventSource.ui.classNames.includes("unmoderated")) {
|
if (event.source.internalEventSource.ui.classNames.includes("unpublished")) {
|
||||||
const button = document.createElement("button");
|
const button = document.createElement("button");
|
||||||
button.innerHTML = `<i class="fa fa-check"></i>${gettext("Moderate")}`;
|
button.innerHTML = `<i class="fa fa-check"></i>${gettext("Publish")}`;
|
||||||
button.setAttribute("class", "btn btn-green");
|
button.setAttribute("class", "btn btn-green");
|
||||||
button.onclick = () => {
|
button.onclick = () => {
|
||||||
this.moderateNews(newsId);
|
this.publishNews(newsId);
|
||||||
};
|
};
|
||||||
div.appendChild(button);
|
div.appendChild(button);
|
||||||
} else {
|
} else {
|
||||||
const button = document.createElement("button");
|
const button = document.createElement("button");
|
||||||
button.innerHTML = `<i class="fa fa-times"></i>${gettext("Remove")}`;
|
button.innerHTML = `<i class="fa fa-times"></i>${gettext("Unpublish")}`;
|
||||||
button.setAttribute("class", "btn btn-orange");
|
button.setAttribute("class", "btn btn-orange");
|
||||||
button.onclick = () => {
|
button.onclick = () => {
|
||||||
this.removeNews(newsId);
|
this.unpublishNews(newsId);
|
||||||
};
|
};
|
||||||
div.appendChild(button);
|
div.appendChild(button);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { exportToHtml } from "#core:utils/globals";
|
import { exportToHtml } from "#core:utils/globals";
|
||||||
import { newsDeleteNews, newsFetchNewsDates, newsModerateNews } from "#openapi";
|
import { newsDeleteNews, newsFetchNewsDates, newsPublishNews } from "#openapi";
|
||||||
|
|
||||||
// This will be used in jinja templates,
|
// This will be used in jinja templates,
|
||||||
// so we cannot use real enums as those are purely an abstraction of Typescript
|
// so we cannot use real enums as those are purely an abstraction of Typescript
|
||||||
@ -7,7 +7,7 @@ const AlertState = {
|
|||||||
// biome-ignore lint/style/useNamingConvention: this feels more like an enum
|
// biome-ignore lint/style/useNamingConvention: this feels more like an enum
|
||||||
PENDING: 1,
|
PENDING: 1,
|
||||||
// biome-ignore lint/style/useNamingConvention: this feels more like an enum
|
// biome-ignore lint/style/useNamingConvention: this feels more like an enum
|
||||||
MODERATED: 2,
|
PUBLISHED: 2,
|
||||||
// biome-ignore lint/style/useNamingConvention: this feels more like an enum
|
// biome-ignore lint/style/useNamingConvention: this feels more like an enum
|
||||||
DELETED: 3,
|
DELETED: 3,
|
||||||
};
|
};
|
||||||
@ -19,11 +19,11 @@ document.addEventListener("alpine:init", () => {
|
|||||||
newsId: newsId as number,
|
newsId: newsId as number,
|
||||||
loading: false,
|
loading: false,
|
||||||
|
|
||||||
async moderateNews() {
|
async publishNews() {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
// biome-ignore lint/style/useNamingConvention: api is snake case
|
// biome-ignore lint/style/useNamingConvention: api is snake case
|
||||||
await newsModerateNews({ path: { news_id: this.newsId } });
|
await newsPublishNews({ path: { news_id: this.newsId } });
|
||||||
this.state = AlertState.MODERATED;
|
this.state = AlertState.PUBLISHED;
|
||||||
this.$dispatch("news-moderated", { newsId: this.newsId, state: this.state });
|
this.$dispatch("news-moderated", { newsId: this.newsId, state: this.state });
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
},
|
},
|
||||||
@ -54,7 +54,7 @@ document.addEventListener("alpine:init", () => {
|
|||||||
* Query the server to know the number of news dates that would be moderated
|
* Query the server to know the number of news dates that would be moderated
|
||||||
* if this one is moderated.
|
* if this one is moderated.
|
||||||
*/
|
*/
|
||||||
async nbToModerate(): Promise<number> {
|
async nbToPublish(): Promise<number> {
|
||||||
// What we want here is the count attribute of the response.
|
// What we want here is the count attribute of the response.
|
||||||
// We don't care about the actual results,
|
// We don't care about the actual results,
|
||||||
// so we ask for the minimum page size possible.
|
// so we ask for the minimum page size possible.
|
||||||
@ -69,8 +69,8 @@ document.addEventListener("alpine:init", () => {
|
|||||||
return interpolate(
|
return interpolate(
|
||||||
gettext(
|
gettext(
|
||||||
"This event will take place every week for %s weeks. " +
|
"This event will take place every week for %s weeks. " +
|
||||||
"If you moderate or delete this event, " +
|
"If you publish or delete this event, " +
|
||||||
"it will also be moderated (or deleted) for the following weeks.",
|
"it will also be published (or deleted) for the following weeks.",
|
||||||
),
|
),
|
||||||
[nbEvents],
|
[nbEvents],
|
||||||
);
|
);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{% macro news_moderation_alert(news, user, alpineState = None) %}
|
{% macro news_moderation_alert(news, user, alpineState = None) %}
|
||||||
{# An alert to display on top of non moderated news,
|
{# An alert to display on top of unpublished news,
|
||||||
with actions to either moderate or delete them.
|
with actions to either publish or delete them.
|
||||||
|
|
||||||
The current state of the alert is accessible through
|
The current state of the alert is accessible through
|
||||||
the given `alpineState` variable.
|
the given `alpineState` variable.
|
||||||
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
This comes in three flavours :
|
This comes in three flavours :
|
||||||
- You can pass the `News` object itself to the macro.
|
- You can pass the `News` object itself to the macro.
|
||||||
In this case, if `request.user` can moderate news,
|
In this case, if `request.user` can publish news,
|
||||||
it will perform an additional db query to know if it is a recurring event.
|
it will perform an additional db query to know if it is a recurring event.
|
||||||
- You can also give only the news id.
|
- You can also give only the news id.
|
||||||
In this case, a server request will be issued to know
|
In this case, a server request will be issued to know
|
||||||
@ -64,16 +64,16 @@
|
|||||||
<template x-if="state === AlertState.PENDING">
|
<template x-if="state === AlertState.PENDING">
|
||||||
<div class="alert alert-yellow">
|
<div class="alert alert-yellow">
|
||||||
<div class="alert-main">
|
<div class="alert-main">
|
||||||
<strong>{% trans %}Waiting moderation{% endtrans %}</strong>
|
<strong>{% trans %}Waiting publication{% endtrans %}</strong>
|
||||||
<p>
|
<p>
|
||||||
{% trans trimmed %}
|
{% trans trimmed %}
|
||||||
This news isn't moderated and is visible
|
This news isn't published and is visible
|
||||||
only by its author and the communication admins.
|
only by its author and the communication admins.
|
||||||
{% endtrans %}
|
{% endtrans %}
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
{% trans trimmed %}
|
{% trans trimmed %}
|
||||||
It will stay hidden for other users until it has been moderated.
|
It will stay hidden for other users until it has been published.
|
||||||
{% endtrans %}
|
{% endtrans %}
|
||||||
</p>
|
</p>
|
||||||
{% if user.has_perm("com.moderate_news") %}
|
{% if user.has_perm("com.moderate_news") %}
|
||||||
@ -84,7 +84,7 @@
|
|||||||
<div
|
<div
|
||||||
{% if news is integer or news is string %}
|
{% if news is integer or news is string %}
|
||||||
x-data="{ nbEvents: 0 }"
|
x-data="{ nbEvents: 0 }"
|
||||||
x-init="nbEvents = await nbToModerate()"
|
x-init="nbEvents = await nbToPublish()"
|
||||||
{% else %}
|
{% else %}
|
||||||
x-data="{ nbEvents: {{ news.dates.count() }} }"
|
x-data="{ nbEvents: {{ news.dates.count() }} }"
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@ -101,8 +101,8 @@
|
|||||||
</div>
|
</div>
|
||||||
{% if user.has_perm("com.moderate_news") %}
|
{% if user.has_perm("com.moderate_news") %}
|
||||||
<span class="alert-aside" :aria-busy="loading">
|
<span class="alert-aside" :aria-busy="loading">
|
||||||
<button class="btn btn-green" @click="moderateNews()" :disabled="loading">
|
<button class="btn btn-green" @click="publishNews()" :disabled="loading">
|
||||||
<i class="fa fa-check"></i> {% trans %}Moderate{% endtrans %}
|
<i class="fa fa-check"></i> {% trans %}Publish{% endtrans %}
|
||||||
</button>
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if user.has_perm("com.delete_news") %}
|
{% if user.has_perm("com.delete_news") %}
|
||||||
@ -113,9 +113,9 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template x-if="state === AlertState.MODERATED">
|
<template x-if="state === AlertState.PUBLISHED">
|
||||||
<div class="alert alert-green">
|
<div class="alert alert-green">
|
||||||
{% trans %}News moderated{% endtrans %}
|
{% trans %}News published{% endtrans %}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template x-if="state === AlertState.DELETED">
|
<template x-if="state === AlertState.DELETED">
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for news in weeklies.filter(is_moderated=True) %}
|
{% for news in weeklies.filter(is_published=True) %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ news.title }}</td>
|
<td>{{ news.title }}</td>
|
||||||
<td>{{ news.summary|markdown }}</td>
|
<td>{{ news.summary|markdown }}</td>
|
||||||
@ -47,7 +47,7 @@
|
|||||||
</td>
|
</td>
|
||||||
<td><a href="{{ url('com:news_detail', news_id=news.id) }}">{% trans %}View{% endtrans %}</a>
|
<td><a href="{{ url('com:news_detail', news_id=news.id) }}">{% trans %}View{% endtrans %}</a>
|
||||||
<a href="{{ url('com:news_edit', news_id=news.id) }}">{% trans %}Edit{% endtrans %}</a>
|
<a href="{{ url('com:news_edit', news_id=news.id) }}">{% trans %}Edit{% endtrans %}</a>
|
||||||
<a href="{{ url('com:news_moderate', news_id=news.id) }}?remove">{% trans %}Remove{% endtrans %}</a>
|
<a href="{{ url('com:news_moderate', news_id=news.id) }}?remove">{% trans %}Unpublish{% endtrans %}</a>
|
||||||
<a href="{{ url('com:news_delete', news_id=news.id) }}">{% trans %}Delete{% endtrans %}</a>
|
<a href="{{ url('com:news_delete', news_id=news.id) }}">{% trans %}Delete{% endtrans %}</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -67,7 +67,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for news in weeklies.filter(is_moderated=False) %}
|
{% for news in weeklies.filter(is_published=False) %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ news.title }}</td>
|
<td>{{ news.title }}</td>
|
||||||
<td>{{ news.summary|markdown }}</td>
|
<td>{{ news.summary|markdown }}</td>
|
||||||
@ -86,7 +86,7 @@
|
|||||||
</td>
|
</td>
|
||||||
<td><a href="{{ url('com:news_detail', news_id=news.id) }}">{% trans %}View{% endtrans %}</a>
|
<td><a href="{{ url('com:news_detail', news_id=news.id) }}">{% trans %}View{% endtrans %}</a>
|
||||||
<a href="{{ url('com:news_edit', news_id=news.id) }}">{% trans %}Edit{% endtrans %}</a>
|
<a href="{{ url('com:news_edit', news_id=news.id) }}">{% trans %}Edit{% endtrans %}</a>
|
||||||
<a href="{{ url('com:news_moderate', news_id=news.id) }}">{% trans %}Moderate{% endtrans %}</a>
|
<a href="{{ url('com:news_moderate', news_id=news.id) }}">{% trans %}Publish{% endtrans %}</a>
|
||||||
<a href="{{ url('com:news_delete', news_id=news.id) }}">{% trans %}Delete{% endtrans %}</a>
|
<a href="{{ url('com:news_delete', news_id=news.id) }}">{% trans %}Delete{% endtrans %}</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -111,7 +111,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for news in events.filter(is_moderated=True) %}
|
{% for news in events.filter(is_published=True) %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ news.title }}</td>
|
<td>{{ news.title }}</td>
|
||||||
<td>{{ news.summary|markdown }}</td>
|
<td>{{ news.summary|markdown }}</td>
|
||||||
@ -124,7 +124,7 @@
|
|||||||
{{ news.dates.all()[0].end_date|localtime|time(DATETIME_FORMAT) }}</td>
|
{{ news.dates.all()[0].end_date|localtime|time(DATETIME_FORMAT) }}</td>
|
||||||
<td><a href="{{ url('com:news_detail', news_id=news.id) }}">{% trans %}View{% endtrans %}</a>
|
<td><a href="{{ url('com:news_detail', news_id=news.id) }}">{% trans %}View{% endtrans %}</a>
|
||||||
<a href="{{ url('com:news_edit', news_id=news.id) }}">{% trans %}Edit{% endtrans %}</a>
|
<a href="{{ url('com:news_edit', news_id=news.id) }}">{% trans %}Edit{% endtrans %}</a>
|
||||||
<a href="{{ url('com:news_moderate', news_id=news.id) }}?remove">{% trans %}Remove{% endtrans %}</a>
|
<a href="{{ url('com:news_moderate', news_id=news.id) }}?remove">{% trans %}Unpublish{% endtrans %}</a>
|
||||||
<a href="{{ url('com:news_delete', news_id=news.id) }}">{% trans %}Delete{% endtrans %}</a>
|
<a href="{{ url('com:news_delete', news_id=news.id) }}">{% trans %}Delete{% endtrans %}</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -145,7 +145,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for news in events.filter(is_moderated=False) %}
|
{% for news in events.filter(is_published=False) %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ news.title }}</td>
|
<td>{{ news.title }}</td>
|
||||||
<td>{{ news.summary|markdown }}</td>
|
<td>{{ news.summary|markdown }}</td>
|
||||||
@ -157,7 +157,7 @@
|
|||||||
{{ news.dates.all()[0].end_date|localtime|time(DATETIME_FORMAT) }}</td>
|
{{ news.dates.all()[0].end_date|localtime|time(DATETIME_FORMAT) }}</td>
|
||||||
<td><a href="{{ url('com:news_detail', news_id=news.id) }}">{% trans %}View{% endtrans %}</a>
|
<td><a href="{{ url('com:news_detail', news_id=news.id) }}">{% trans %}View{% endtrans %}</a>
|
||||||
<a href="{{ url('com:news_edit', news_id=news.id) }}">{% trans %}Edit{% endtrans %}</a>
|
<a href="{{ url('com:news_edit', news_id=news.id) }}">{% trans %}Edit{% endtrans %}</a>
|
||||||
<a href="{{ url('com:news_moderate', news_id=news.id) }}">{% trans %}Moderate{% endtrans %}</a>
|
<a href="{{ url('com:news_moderate', news_id=news.id) }}">{% trans %}Publish{% endtrans %}</a>
|
||||||
<a href="{{ url('com:news_delete', news_id=news.id) }}">{% trans %}Delete{% endtrans %}</a>
|
<a href="{{ url('com:news_delete', news_id=news.id) }}">{% trans %}Delete{% endtrans %}</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
<p><a href="{{ url('com:news_list') }}">{% trans %}Back to news{% endtrans %}</a></p>
|
<p><a href="{{ url('com:news_list') }}">{% trans %}Back to news{% endtrans %}</a></p>
|
||||||
<div x-data="{newsState: AlertState.PENDING}">
|
<div x-data="{newsState: AlertState.PENDING}">
|
||||||
|
|
||||||
{% if not news.is_moderated %}
|
{% if not news.is_published %}
|
||||||
{{ news_moderation_alert(news, user, "newsState") }}
|
{{ news_moderation_alert(news, user, "newsState") }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<article id="news_details" x-show="newsState !== AlertState.DELETED">
|
<article id="news_details" x-show="newsState !== AlertState.DELETED">
|
||||||
@ -51,7 +51,7 @@
|
|||||||
{% if news.moderator %}
|
{% if news.moderator %}
|
||||||
<p>{% trans %}Moderator: {% endtrans %}{{ user_profile_link(news.moderator) }}</p>
|
<p>{% trans %}Moderator: {% endtrans %}{{ user_profile_link(news.moderator) }}</p>
|
||||||
{% elif user.is_com_admin %}
|
{% elif user.is_com_admin %}
|
||||||
<p> <a href="{{ url('com:news_moderate', news_id=news.id) }}">{% trans %}Moderate{% endtrans %}</a></p>
|
<p> <a href="{{ url('com:news_moderate', news_id=news.id) }}">{% trans %}Publish{% endtrans %}</a></p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if user.can_edit(news) %}
|
{% 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>
|
<p> <a href="{{ url('com:news_edit', news_id=news.id) }}">{% trans %}Edit (will be moderated again){% endtrans %}</a></p>
|
||||||
|
@ -80,9 +80,9 @@
|
|||||||
</fieldset>
|
</fieldset>
|
||||||
{% if user.is_root or user.is_com_admin %}
|
{% if user.is_root or user.is_com_admin %}
|
||||||
<fieldset>
|
<fieldset>
|
||||||
{{ form.auto_moderate.errors }}
|
{{ form.auto_publish.errors }}
|
||||||
{{ form.auto_moderate }}
|
{{ form.auto_publish }}
|
||||||
{{ form.auto_moderate.label_tag() }}
|
{{ form.auto_publish.label_tag() }}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<p><input type="submit" value="{% trans %}Save{% endtrans %}" class="btn btn-blue"/></p>
|
<p><input type="submit" value="{% trans %}Save{% endtrans %}" class="btn btn-blue"/></p>
|
||||||
|
@ -57,17 +57,17 @@
|
|||||||
{% for date in dates_group %}
|
{% for date in dates_group %}
|
||||||
<article
|
<article
|
||||||
class="news_event"
|
class="news_event"
|
||||||
{%- if not date.news.is_moderated -%}
|
{%- if not date.news.is_published -%}
|
||||||
x-data="{newsState: AlertState.PENDING}"
|
x-data="{newsState: AlertState.PENDING}"
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
>
|
>
|
||||||
{% if not date.news.is_moderated %}
|
{% if not date.news.is_published %}
|
||||||
{# if a non moderated news is in the object list,
|
{# if a non published news is in the object list,
|
||||||
the logged user is either an admin or the news author #}
|
the logged user is either an admin or the news author #}
|
||||||
{{ news_moderation_alert(date.news, user, "newsState") }}
|
{{ news_moderation_alert(date.news, user, "newsState") }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div
|
<div
|
||||||
{% if not date.news.is_moderated -%}
|
{% if not date.news.is_published -%}
|
||||||
x-show="newsState !== AlertState.DELETED"
|
x-show="newsState !== AlertState.DELETED"
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
>
|
>
|
||||||
@ -120,9 +120,9 @@
|
|||||||
<template x-for="newsDate in newsList" :key="newsDate.id">
|
<template x-for="newsDate in newsList" :key="newsDate.id">
|
||||||
<article
|
<article
|
||||||
class="news_event"
|
class="news_event"
|
||||||
x-data="{ newsState: newsDate.news.is_moderated ? AlertState.MODERATED : AlertState.PENDING }"
|
x-data="{ newsState: newsDate.news.is_published ? AlertState.PULISHED : AlertState.PENDING }"
|
||||||
>
|
>
|
||||||
<template x-if="!newsDate.news.is_moderated">
|
<template x-if="!newsDate.news.is_published">
|
||||||
{{ news_moderation_alert("newsDate.news.id", user, "newsState") }}
|
{{ news_moderation_alert("newsDate.news.id", user, "newsState") }}
|
||||||
</template>
|
</template>
|
||||||
<div x-show="newsState !== AlertState.DELETED">
|
<div x-show="newsState !== AlertState.DELETED">
|
||||||
@ -183,15 +183,15 @@
|
|||||||
x-data
|
x-data
|
||||||
x-ref="calendar"
|
x-ref="calendar"
|
||||||
@news-moderated.window="
|
@news-moderated.window="
|
||||||
|
if ($event.target !== $refs.calendar){
|
||||||
// Avoid triggering a refresh with a dispatch
|
// Avoid triggering a refresh with a dispatch
|
||||||
// from the calendar itself
|
// from the calendar itself
|
||||||
if ($event.target !== $refs.calendar){
|
|
||||||
$refs.calendar.refreshEvents($event);
|
$refs.calendar.refreshEvents($event);
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
@calendar-remove="$dispatch('news-moderated', {newsId: $event.detail.id, state: AlertState.PENDING})"
|
@calendar-remove="$dispatch('news-moderated', {newsId: $event.detail.id, state: AlertState.DELETED})"
|
||||||
@calendar-delete="$dispatch('news-moderated', {newsId: $event.detail.id, state: AlertState.DELETED})"
|
@calendar-unpublish="$dispatch('news-moderated', {newsId: $event.detail.id, state: AlertState.PENDING})"
|
||||||
@calendar-moderate="$dispatch('news-moderated', {newsId: $event.detail.id, state: AlertState.MODERATED})"
|
@calendar-publish="$dispatch('news-moderated', {newsId: $event.detail.id, state: AlertState.PUBLISHED})"
|
||||||
locale="{{ get_language() }}"
|
locale="{{ get_language() }}"
|
||||||
can_moderate="{{ user.has_perm("com.moderate_news") }}"
|
can_moderate="{{ user.has_perm("com.moderate_news") }}"
|
||||||
can_delete="{{ user.has_perm("com.delete_news") }}"
|
can_delete="{{ user.has_perm("com.delete_news") }}"
|
||||||
|
@ -129,14 +129,14 @@ class TestInternalCalendar:
|
|||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
class TestModerateNews:
|
class TestModerateNews:
|
||||||
@pytest.mark.parametrize("news_is_moderated", [True, False])
|
@pytest.mark.parametrize("news_is_published", [True, False])
|
||||||
def test_moderation_ok(self, client: Client, news_is_moderated: bool): # noqa FBT
|
def test_moderation_ok(self, client: Client, news_is_published: bool): # noqa FBT
|
||||||
user = baker.make(
|
user = baker.make(
|
||||||
User, user_permissions=[Permission.objects.get(codename="moderate_news")]
|
User, user_permissions=[Permission.objects.get(codename="moderate_news")]
|
||||||
)
|
)
|
||||||
# The API call should work even if the news is initially moderated.
|
# The API call should work even if the news is initially moderated.
|
||||||
# In the latter case, the result should be a noop, rather than an error.
|
# In the latter case, the result should be a noop, rather than an error.
|
||||||
news = baker.make(News, is_moderated=news_is_moderated)
|
news = baker.make(News, is_published=news_is_published)
|
||||||
initial_moderator = news.moderator
|
initial_moderator = news.moderator
|
||||||
client.force_login(user)
|
client.force_login(user)
|
||||||
response = client.patch(
|
response = client.patch(
|
||||||
@ -147,22 +147,22 @@ class TestModerateNews:
|
|||||||
# If it was already moderated, it should be a no-op, but not an error
|
# If it was already moderated, it should be a no-op, but not an error
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
news.refresh_from_db()
|
news.refresh_from_db()
|
||||||
assert news.is_moderated
|
assert news.is_published
|
||||||
if not news_is_moderated:
|
if not news_is_published:
|
||||||
assert news.moderator == user
|
assert news.moderator == user
|
||||||
else:
|
else:
|
||||||
assert news.moderator == initial_moderator
|
assert news.moderator == initial_moderator
|
||||||
|
|
||||||
def test_moderation_forbidden(self, client: Client):
|
def test_moderation_forbidden(self, client: Client):
|
||||||
user = baker.make(User)
|
user = baker.make(User)
|
||||||
news = baker.make(News, is_moderated=False)
|
news = baker.make(News, is_published=False)
|
||||||
client.force_login(user)
|
client.force_login(user)
|
||||||
response = client.patch(
|
response = client.patch(
|
||||||
reverse("api:moderate_news", kwargs={"news_id": news.id})
|
reverse("api:moderate_news", kwargs={"news_id": news.id})
|
||||||
)
|
)
|
||||||
assert response.status_code == 403
|
assert response.status_code == 403
|
||||||
news.refresh_from_db()
|
news.refresh_from_db()
|
||||||
assert not news.is_moderated
|
assert not news.is_published
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
@ -203,7 +203,7 @@ class TestFetchNewsDates(TestCase):
|
|||||||
value=now() + timedelta(hours=2), increment_by=timedelta(days=1)
|
value=now() + timedelta(hours=2), increment_by=timedelta(days=1)
|
||||||
),
|
),
|
||||||
news=iter(
|
news=iter(
|
||||||
baker.make(News, is_moderated=True, _quantity=5, _bulk_create=True)
|
baker.make(News, is_published=True, _quantity=5, _bulk_create=True)
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
cls.dates.append(
|
cls.dates.append(
|
||||||
@ -211,7 +211,7 @@ class TestFetchNewsDates(TestCase):
|
|||||||
NewsDate,
|
NewsDate,
|
||||||
start_date=now() + timedelta(days=2, hours=1),
|
start_date=now() + timedelta(days=2, hours=1),
|
||||||
end_date=now() + timedelta(days=2, hours=5),
|
end_date=now() + timedelta(days=2, hours=5),
|
||||||
news=baker.make(News, is_moderated=True),
|
news=baker.make(News, is_published=True),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
cls.dates.sort(key=lambda d: d.start_date)
|
cls.dates.sort(key=lambda d: d.start_date)
|
||||||
|
@ -18,7 +18,7 @@ class TestNewsViewableBy(TestCase):
|
|||||||
cls.news = baker.make(
|
cls.news = baker.make(
|
||||||
News,
|
News,
|
||||||
author=itertools.cycle(cls.users),
|
author=itertools.cycle(cls.users),
|
||||||
is_moderated=iter([True, True, True, False, False, False]),
|
is_published=iter([True, True, True, False, False, False]),
|
||||||
_quantity=6,
|
_quantity=6,
|
||||||
_bulk_create=True,
|
_bulk_create=True,
|
||||||
)
|
)
|
||||||
|
@ -168,7 +168,7 @@ class TestNews(TestCase):
|
|||||||
assert not self.new.can_be_viewed_by(self.sli)
|
assert not self.new.can_be_viewed_by(self.sli)
|
||||||
assert not self.new.can_be_viewed_by(self.anonymous)
|
assert not self.new.can_be_viewed_by(self.anonymous)
|
||||||
|
|
||||||
self.new.is_moderated = True
|
self.new.is_published = True
|
||||||
self.new.save()
|
self.new.save()
|
||||||
assert self.new.can_be_viewed_by(self.com_admin)
|
assert self.new.can_be_viewed_by(self.com_admin)
|
||||||
assert self.new.can_be_viewed_by(self.sli)
|
assert self.new.can_be_viewed_by(self.sli)
|
||||||
@ -258,7 +258,7 @@ class TestNewsCreation(TestCase):
|
|||||||
created = News.objects.order_by("id").last()
|
created = News.objects.order_by("id").last()
|
||||||
assertRedirects(response, created.get_absolute_url())
|
assertRedirects(response, created.get_absolute_url())
|
||||||
assert created.title == "Test news"
|
assert created.title == "Test news"
|
||||||
assert not created.is_moderated
|
assert not created.is_published
|
||||||
dates = list(created.dates.values("start_date", "end_date"))
|
dates = list(created.dates.values("start_date", "end_date"))
|
||||||
assert dates == [{"start_date": self.start, "end_date": self.end}]
|
assert dates == [{"start_date": self.start, "end_date": self.end}]
|
||||||
|
|
||||||
@ -281,7 +281,7 @@ class TestNewsCreation(TestCase):
|
|||||||
]
|
]
|
||||||
|
|
||||||
def test_edit_news(self):
|
def test_edit_news(self):
|
||||||
news = baker.make(News, author=self.user, is_moderated=True)
|
news = baker.make(News, author=self.user, is_published=True)
|
||||||
baker.make(
|
baker.make(
|
||||||
NewsDate,
|
NewsDate,
|
||||||
news=news,
|
news=news,
|
||||||
@ -296,7 +296,7 @@ class TestNewsCreation(TestCase):
|
|||||||
created = News.objects.order_by("id").last()
|
created = News.objects.order_by("id").last()
|
||||||
assertRedirects(response, created.get_absolute_url())
|
assertRedirects(response, created.get_absolute_url())
|
||||||
assert created.title == "Test news"
|
assert created.title == "Test news"
|
||||||
assert not created.is_moderated
|
assert not created.is_published
|
||||||
dates = list(created.dates.values("start_date", "end_date"))
|
dates = list(created.dates.values("start_date", "end_date"))
|
||||||
assert dates == [{"start_date": self.start, "end_date": self.end}]
|
assert dates == [{"start_date": self.start, "end_date": self.end}]
|
||||||
|
|
||||||
|
@ -217,9 +217,9 @@ class NewsModerateView(PermissionRequiredMixin, DetailView):
|
|||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
self.object = self.get_object()
|
self.object = self.get_object()
|
||||||
if "remove" in request.GET:
|
if "remove" in request.GET:
|
||||||
self.object.is_moderated = False
|
self.object.is_published = False
|
||||||
else:
|
else:
|
||||||
self.object.is_moderated = True
|
self.object.is_published = True
|
||||||
self.object.moderator = request.user
|
self.object.moderator = request.user
|
||||||
self.object.save()
|
self.object.save()
|
||||||
if "next" in self.request.GET:
|
if "next" in self.request.GET:
|
||||||
@ -309,7 +309,7 @@ class NewsFeed(Feed):
|
|||||||
def items(self):
|
def items(self):
|
||||||
return (
|
return (
|
||||||
NewsDate.objects.filter(
|
NewsDate.objects.filter(
|
||||||
news__is_moderated=True,
|
news__is_published=True,
|
||||||
end_date__gte=timezone.now() - (relativedelta(months=6)),
|
end_date__gte=timezone.now() - (relativedelta(months=6)),
|
||||||
)
|
)
|
||||||
.select_related("news", "news__author")
|
.select_related("news", "news__author")
|
||||||
|
@ -690,7 +690,7 @@ Welcome to the wiki page!
|
|||||||
content="Glou glou glou glou glou glou glou",
|
content="Glou glou glou glou glou glou glou",
|
||||||
club=bar_club,
|
club=bar_club,
|
||||||
author=subscriber,
|
author=subscriber,
|
||||||
is_moderated=True,
|
is_published=True,
|
||||||
moderator=skia,
|
moderator=skia,
|
||||||
)
|
)
|
||||||
news_dates.append(
|
news_dates.append(
|
||||||
@ -704,12 +704,11 @@ Welcome to the wiki page!
|
|||||||
title="Repas barman",
|
title="Repas barman",
|
||||||
summary="Enjoy la fin du semestre!",
|
summary="Enjoy la fin du semestre!",
|
||||||
content=(
|
content=(
|
||||||
"Viens donc t'enjailler avec les autres barmans aux "
|
"Viens donc t'enjailler avec les autres barmans aux frais du BdF! \\o/"
|
||||||
"frais du BdF! \\o/"
|
|
||||||
),
|
),
|
||||||
club=bar_club,
|
club=bar_club,
|
||||||
author=subscriber,
|
author=subscriber,
|
||||||
is_moderated=True,
|
is_published=True,
|
||||||
moderator=skia,
|
moderator=skia,
|
||||||
)
|
)
|
||||||
news_dates.append(
|
news_dates.append(
|
||||||
@ -725,7 +724,7 @@ Welcome to the wiki page!
|
|||||||
content="Fô viendre mangey d'la bonne fondue!",
|
content="Fô viendre mangey d'la bonne fondue!",
|
||||||
club=bar_club,
|
club=bar_club,
|
||||||
author=subscriber,
|
author=subscriber,
|
||||||
is_moderated=True,
|
is_published=True,
|
||||||
moderator=skia,
|
moderator=skia,
|
||||||
)
|
)
|
||||||
news_dates.append(
|
news_dates.append(
|
||||||
@ -741,7 +740,7 @@ Welcome to the wiki page!
|
|||||||
content="Viens faire la fête avec tout plein de gens!",
|
content="Viens faire la fête avec tout plein de gens!",
|
||||||
club=bar_club,
|
club=bar_club,
|
||||||
author=subscriber,
|
author=subscriber,
|
||||||
is_moderated=True,
|
is_published=True,
|
||||||
moderator=skia,
|
moderator=skia,
|
||||||
)
|
)
|
||||||
news_dates.append(
|
news_dates.append(
|
||||||
@ -759,7 +758,7 @@ Welcome to the wiki page!
|
|||||||
"t'amuser le Vendredi soir!",
|
"t'amuser le Vendredi soir!",
|
||||||
club=troll,
|
club=troll,
|
||||||
author=subscriber,
|
author=subscriber,
|
||||||
is_moderated=True,
|
is_published=True,
|
||||||
moderator=skia,
|
moderator=skia,
|
||||||
)
|
)
|
||||||
news_dates.extend(
|
news_dates.extend(
|
||||||
|
16
core/migrations/0044_alter_userban_options.py
Normal file
16
core/migrations/0044_alter_userban_options.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# Generated by Django 4.2.17 on 2025-02-25 14:45
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("core", "0043_bangroup_alter_group_description_alter_user_groups_and_more"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name="userban",
|
||||||
|
options={"verbose_name": "user ban", "verbose_name_plural": "user bans"},
|
||||||
|
),
|
||||||
|
]
|
@ -6,7 +6,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-02-25 11:04+0100\n"
|
"POT-Creation-Date: 2025-02-25 16:38+0100\n"
|
||||||
"PO-Revision-Date: 2016-07-18\n"
|
"PO-Revision-Date: 2016-07-18\n"
|
||||||
"Last-Translator: Maréchal <thomas.girod@utbm.fr\n"
|
"Last-Translator: Maréchal <thomas.girod@utbm.fr\n"
|
||||||
"Language-Team: AE info <ae.info@utbm.fr>\n"
|
"Language-Team: AE info <ae.info@utbm.fr>\n"
|
||||||
@ -812,7 +812,7 @@ msgstr "Nouvelle mailing liste"
|
|||||||
msgid "Subscribe"
|
msgid "Subscribe"
|
||||||
msgstr "S'abonner"
|
msgstr "S'abonner"
|
||||||
|
|
||||||
#: club/forms.py com/templates/com/news_admin_list.jinja
|
#: club/forms.py
|
||||||
msgid "Remove"
|
msgid "Remove"
|
||||||
msgstr "Retirer"
|
msgstr "Retirer"
|
||||||
|
|
||||||
@ -1296,8 +1296,8 @@ msgstr ""
|
|||||||
"Combien de fois l'événement doit-il se répéter (en incluant la première fois)"
|
"Combien de fois l'événement doit-il se répéter (en incluant la première fois)"
|
||||||
|
|
||||||
#: com/forms.py
|
#: com/forms.py
|
||||||
msgid "Automoderation"
|
msgid "Auto publication"
|
||||||
msgstr "Automodération"
|
msgstr "Publication automatique"
|
||||||
|
|
||||||
#: com/models.py
|
#: com/models.py
|
||||||
msgid "alert message"
|
msgid "alert message"
|
||||||
@ -1344,6 +1344,10 @@ msgstr "Le club qui organise l'évènement."
|
|||||||
msgid "author"
|
msgid "author"
|
||||||
msgstr "auteur"
|
msgstr "auteur"
|
||||||
|
|
||||||
|
#: com/models.py
|
||||||
|
msgid "is published"
|
||||||
|
msgstr "est publié"
|
||||||
|
|
||||||
#: com/models.py
|
#: com/models.py
|
||||||
msgid "news"
|
msgid "news"
|
||||||
msgstr "nouvelle"
|
msgstr "nouvelle"
|
||||||
@ -1409,34 +1413,31 @@ msgid "Begin date should be before end date"
|
|||||||
msgstr "La date de début doit être avant celle de fin"
|
msgstr "La date de début doit être avant celle de fin"
|
||||||
|
|
||||||
#: com/templates/com/macros.jinja
|
#: com/templates/com/macros.jinja
|
||||||
msgid "Waiting moderation"
|
msgid "Waiting publication"
|
||||||
msgstr "En attente de modération"
|
msgstr "En attente de publication"
|
||||||
|
|
||||||
#: com/templates/com/macros.jinja
|
#: com/templates/com/macros.jinja
|
||||||
msgid ""
|
msgid ""
|
||||||
"This news isn't moderated and is visible only by its author and the "
|
"This news isn't published and is visible only by its author and the "
|
||||||
"communication admins."
|
"communication admins."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Cette nouvelle n'est pas modérée et n'est visible que par son auteur et les "
|
"Cette nouvelle n'est pas publiée et n'est visible que par son auteur et les "
|
||||||
"admins communication."
|
"admins communication."
|
||||||
|
|
||||||
#: com/templates/com/macros.jinja
|
#: com/templates/com/macros.jinja
|
||||||
msgid "It will stay hidden for other users until it has been moderated."
|
msgid "It will stay hidden for other users until it has been published."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Elle sera cachée pour les autres utilisateurs tant qu'elle ne sera pas "
|
"Elle sera cachée pour les autres utilisateurs tant qu'elle ne sera pas "
|
||||||
"modérée."
|
"publiée."
|
||||||
|
|
||||||
#: com/templates/com/macros.jinja com/templates/com/mailing_admin.jinja
|
#: com/templates/com/macros.jinja com/templates/com/news_admin_list.jinja
|
||||||
#: com/templates/com/news_admin_list.jinja com/templates/com/news_detail.jinja
|
#: com/templates/com/news_detail.jinja
|
||||||
#: core/templates/core/file_detail.jinja
|
msgid "Publish"
|
||||||
#: core/templates/core/file_moderation.jinja sas/templates/sas/moderation.jinja
|
msgstr "Publier"
|
||||||
#: sas/templates/sas/picture.jinja
|
|
||||||
msgid "Moderate"
|
|
||||||
msgstr "Modérer"
|
|
||||||
|
|
||||||
#: com/templates/com/macros.jinja
|
#: com/templates/com/macros.jinja
|
||||||
msgid "News moderated"
|
msgid "News published"
|
||||||
msgstr "Nouvelle modérée"
|
msgstr "Nouvelle publiée"
|
||||||
|
|
||||||
#: com/templates/com/macros.jinja
|
#: com/templates/com/macros.jinja
|
||||||
msgid "News deleted"
|
msgid "News deleted"
|
||||||
@ -1447,6 +1448,12 @@ msgstr "Nouvelle supprimée"
|
|||||||
msgid "Mailing lists administration"
|
msgid "Mailing lists administration"
|
||||||
msgstr "Administration des mailing listes"
|
msgstr "Administration des mailing listes"
|
||||||
|
|
||||||
|
#: com/templates/com/mailing_admin.jinja core/templates/core/file_detail.jinja
|
||||||
|
#: core/templates/core/file_moderation.jinja sas/templates/sas/moderation.jinja
|
||||||
|
#: sas/templates/sas/picture.jinja
|
||||||
|
msgid "Moderate"
|
||||||
|
msgstr "Modérer"
|
||||||
|
|
||||||
#: com/templates/com/mailing_admin.jinja
|
#: com/templates/com/mailing_admin.jinja
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Moderated by %(user)s"
|
msgid "Moderated by %(user)s"
|
||||||
@ -1514,6 +1521,10 @@ msgstr "Modérateur"
|
|||||||
msgid "Dates"
|
msgid "Dates"
|
||||||
msgstr "Dates"
|
msgstr "Dates"
|
||||||
|
|
||||||
|
#: com/templates/com/news_admin_list.jinja
|
||||||
|
msgid "Unpublish"
|
||||||
|
msgstr "Dépublier"
|
||||||
|
|
||||||
#: com/templates/com/news_admin_list.jinja
|
#: com/templates/com/news_admin_list.jinja
|
||||||
msgid "Weeklies to moderate"
|
msgid "Weeklies to moderate"
|
||||||
msgstr "Nouvelles hebdomadaires à modérer"
|
msgstr "Nouvelles hebdomadaires à modérer"
|
||||||
@ -6031,13 +6042,3 @@ msgstr "Vous ne pouvez plus écrire de commentaires, la date est passée."
|
|||||||
#, python-format
|
#, python-format
|
||||||
msgid "Maximum characters: %(max_length)s"
|
msgid "Maximum characters: %(max_length)s"
|
||||||
msgstr "Nombre de caractères max: %(max_length)s"
|
msgstr "Nombre de caractères max: %(max_length)s"
|
||||||
|
|
||||||
#, python-format
|
|
||||||
#~ msgid ""
|
|
||||||
#~ "This event will take place every week for %%s weeks. If you moderate or "
|
|
||||||
#~ "delete this event, it will also be moderated (or deleted) for the "
|
|
||||||
#~ "following weeks."
|
|
||||||
#~ msgstr ""
|
|
||||||
#~ "Cet événement se déroulera chaque semaine pendant %%s semaines. Si vous "
|
|
||||||
#~ "modérez ou supprimez cet événement, il sera également modéré (ou "
|
|
||||||
#~ "supprimé) pour les semaines suivantes."
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-02-25 14:38+0100\n"
|
"POT-Creation-Date: 2025-02-25 16:10+0100\n"
|
||||||
"PO-Revision-Date: 2024-09-17 11:54+0200\n"
|
"PO-Revision-Date: 2024-09-17 11:54+0200\n"
|
||||||
"Last-Translator: Sli <antoine@bartuccio.fr>\n"
|
"Last-Translator: Sli <antoine@bartuccio.fr>\n"
|
||||||
"Language-Team: AE info <ae.info@utbm.fr>\n"
|
"Language-Team: AE info <ae.info@utbm.fr>\n"
|
||||||
@ -22,29 +22,30 @@ msgid "More info"
|
|||||||
msgstr "Plus d'informations"
|
msgstr "Plus d'informations"
|
||||||
|
|
||||||
#: com/static/bundled/com/components/ics-calendar-index.ts
|
#: com/static/bundled/com/components/ics-calendar-index.ts
|
||||||
msgid "Moderate"
|
msgid "Publish"
|
||||||
msgstr "Modérer"
|
msgstr "Publier"
|
||||||
|
|
||||||
#: com/static/bundled/com/components/ics-calendar-index.ts
|
#: com/static/bundled/com/components/ics-calendar-index.ts
|
||||||
#: core/static/bundled/core/components/ajax-select-base.ts
|
msgid "Unpublish"
|
||||||
msgid "Remove"
|
msgstr "Dépublier"
|
||||||
msgstr "Retirer"
|
|
||||||
|
|
||||||
#: com/static/bundled/com/components/ics-calendar-index.ts
|
#: com/static/bundled/com/components/ics-calendar-index.ts
|
||||||
msgid "Delete"
|
msgid "Delete"
|
||||||
msgstr "Supprimer"
|
msgstr "Supprimer"
|
||||||
|
|
||||||
#: com/static/bundled/com/components/moderation-alert-index.ts
|
#: com/static/bundled/com/components/moderation-alert-index.ts
|
||||||
#, javascript-format
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"This event will take place every week for %s weeks. If you moderate or "
|
"This event will take place every week for %s weeks. If you publish or delete "
|
||||||
"delete this event, it will also be moderated (or deleted) for the following "
|
"this event, it will also be published (or deleted) for the following weeks."
|
||||||
"weeks."
|
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Cet événement se déroulera chaque semaine pendant %s semaines. Si vous "
|
"Cet événement se déroulera chaque semaine pendant %s semaines. Si vous "
|
||||||
"modérez ou supprimez cet événement, il sera également modéré (ou supprimé) "
|
"publiez ou supprimez cet événement, il sera également publié (ou supprimé) "
|
||||||
"pour les semaines suivantes."
|
"pour les semaines suivantes."
|
||||||
|
|
||||||
|
#: core/static/bundled/core/components/ajax-select-base.ts
|
||||||
|
msgid "Remove"
|
||||||
|
msgstr "Retirer"
|
||||||
|
|
||||||
#: core/static/bundled/core/components/ajax-select-base.ts
|
#: core/static/bundled/core/components/ajax-select-base.ts
|
||||||
msgid "You need to type %(number)s more characters"
|
msgid "You need to type %(number)s more characters"
|
||||||
msgstr "Vous devez taper %(number)s caractères de plus"
|
msgstr "Vous devez taper %(number)s caractères de plus"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user