diff --git a/com/models.py b/com/models.py index 04f6bf56..8c7111e8 100644 --- a/com/models.py +++ b/com/models.py @@ -170,7 +170,6 @@ def news_notification_callback(notif: Notification): if count: notif.viewed = False notif.param = str(count) - notif.date = timezone.now() else: notif.viewed = True diff --git a/core/migrations/0047_alter_notification_date_alter_notification_type.py b/core/migrations/0047_alter_notification_date_alter_notification_type.py new file mode 100644 index 00000000..77831263 --- /dev/null +++ b/core/migrations/0047_alter_notification_date_alter_notification_type.py @@ -0,0 +1,27 @@ +# Generated by Django 5.2.1 on 2025-06-11 16:10 + +from django.db import migrations, models + +import core.models + + +class Migration(migrations.Migration): + dependencies = [("core", "0046_permissionrights")] + + operations = [ + migrations.AlterField( + model_name="notification", + name="date", + field=models.DateTimeField(auto_now=True, verbose_name="date"), + ), + migrations.AlterField( + model_name="notification", + name="type", + field=models.CharField( + choices=core.models.get_notification_types, + default="GENERIC", + max_length=32, + verbose_name="type", + ), + ), + ] diff --git a/core/models.py b/core/models.py index 23b863f6..0c65e043 100644 --- a/core/models.py +++ b/core/models.py @@ -1451,6 +1451,10 @@ class PageRev(models.Model): return self.page.can_be_edited_by(user) +def get_notification_types(): + return settings.SITH_NOTIFICATIONS + + class Notification(models.Model): user = models.ForeignKey( User, related_name="notifications", on_delete=models.CASCADE @@ -1458,9 +1462,9 @@ class Notification(models.Model): url = models.CharField(_("url"), max_length=255) param = models.CharField(_("param"), max_length=128, default="") type = models.CharField( - _("type"), max_length=32, choices=settings.SITH_NOTIFICATIONS, default="GENERIC" + _("type"), max_length=32, choices=get_notification_types, default="GENERIC" ) - date = models.DateTimeField(_("date"), default=timezone.now) + date = models.DateTimeField(_("date"), auto_now=True) viewed = models.BooleanField(_("viewed"), default=False, db_index=True) def __str__(self): diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index f8c89349..01b3f706 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -5103,8 +5103,9 @@ msgid "There are %s pictures to be moderated in the SAS" msgstr "Il y a %s photos à modérer dans le SAS" #: sith/settings.py -msgid "You've been identified on some pictures" -msgstr "Vous avez été identifié sur des photos" +#, python-format +msgid "You've been identified in album %s" +msgstr "Vous avez été identifié dans l'album %s" #: sith/settings.py #, python-format diff --git a/sas/api.py b/sas/api.py index fa37e974..6f68bd94 100644 --- a/sas/api.py +++ b/sas/api.py @@ -2,7 +2,6 @@ from typing import Any, Literal from django.conf import settings from django.core.exceptions import ValidationError -from django.db.models import F from django.urls import reverse from ninja import Body, File, Query from ninja.security import SessionAuth @@ -105,8 +104,7 @@ class PicturesController(ControllerBase): filters.filter(Picture.objects.viewable_by(user)) .distinct() .order_by("-parent__date", "date") - .select_related("owner") - .annotate(album=F("parent__name")) + .select_related("owner", "parent") ) @route.post( @@ -153,7 +151,9 @@ class PicturesController(ControllerBase): @route.put("/{picture_id}/identified", permissions=[IsAuthenticated, CanView]) def identify_users(self, picture_id: NonNegativeInt, users: set[NonNegativeInt]): - picture = self.get_object_or_exception(Picture, pk=picture_id) + picture = self.get_object_or_exception( + Picture.objects.select_related("parent"), pk=picture_id + ) db_users = list(User.objects.filter(id__in=users)) if len(users) != len(db_users): raise NotFound @@ -166,13 +166,15 @@ class PicturesController(ControllerBase): ] PeoplePictureRelation.objects.bulk_create(relations) for u in identified: + html_id = f"album-{picture.parent_id}" + url = reverse( + "sas:user_pictures", kwargs={"user_id": u.id}, fragment=html_id + ) Notification.objects.get_or_create( user=u, viewed=False, type="NEW_PICTURES", - defaults={ - "url": reverse("sas:user_pictures", kwargs={"user_id": u.id}) - }, + defaults={"url": url, "param": picture.parent.name}, ) @route.delete("/{picture_id}", permissions=[IsSasAdmin]) diff --git a/sas/models.py b/sas/models.py index 4f3ff21e..3a0a8428 100644 --- a/sas/models.py +++ b/sas/models.py @@ -25,11 +25,10 @@ from django.core.cache import cache from django.db import models from django.db.models import Exists, OuterRef, Q from django.urls import reverse -from django.utils import timezone from django.utils.translation import gettext_lazy as _ from PIL import Image -from core.models import SithFile, User +from core.models import Notification, SithFile, User from core.utils import exif_auto_rotate, resize_image @@ -256,14 +255,10 @@ class Album(SasFile): self.save() -def sas_notification_callback(notif): +def sas_notification_callback(notif: Notification): count = Picture.objects.filter(is_moderated=False).count() - if count: - notif.viewed = False - else: - notif.viewed = True - notif.param = "%s" % count - notif.date = timezone.now() + notif.viewed = not bool(count) + notif.param = str(count) class PeoplePictureRelation(models.Model): diff --git a/sas/schemas.py b/sas/schemas.py index 76eb908a..6f490dca 100644 --- a/sas/schemas.py +++ b/sas/schemas.py @@ -18,6 +18,12 @@ class AlbumFilterSchema(FilterSchema): parent_id: int | None = Field(None, q="parent_id") +class SimpleAlbumSchema(ModelSchema): + class Meta: + model = Album + fields = ["id", "name"] + + class AlbumSchema(ModelSchema): class Meta: model = Album @@ -70,7 +76,7 @@ class PictureSchema(ModelSchema): full_size_url: str compressed_url: str thumb_url: str - album: str + album: SimpleAlbumSchema = Field(alias="parent") report_url: str edit_url: str diff --git a/sas/static/bundled/sas/user/pictures-index.ts b/sas/static/bundled/sas/user/pictures-index.ts index a18dede5..f5f2fcbc 100644 --- a/sas/static/bundled/sas/user/pictures-index.ts +++ b/sas/static/bundled/sas/user/pictures-index.ts @@ -22,11 +22,11 @@ document.addEventListener("alpine:init", () => { } as PicturesFetchPicturesData); this.albums = this.pictures.reduce( - (acc: Record, picture: PictureSchema) => { - if (!acc[picture.album]) { - acc[picture.album] = []; + (acc: Record, picture: PictureSchema) => { + if (!acc[picture.album.id]) { + acc[picture.album.id] = []; } - acc[picture.album].push(picture); + acc[picture.album.id].push(picture); return acc; }, {}, diff --git a/sas/templates/sas/user_pictures.jinja b/sas/templates/sas/user_pictures.jinja index cb1f98c5..76c74bc7 100644 --- a/sas/templates/sas/user_pictures.jinja +++ b/sas/templates/sas/user_pictures.jinja @@ -20,11 +20,11 @@ {{ download_button(_("Download all my pictures")) }} {% endif %} -