From 876e4cdfa7c3084a7b8b7a65316653b77d44c160 Mon Sep 17 00:00:00 2001 From: bkfox Date: Tue, 12 Sep 2023 21:00:44 +0200 Subject: [PATCH] feat: add error message page; improve admin ui; add missing test files --- aircox/admin_site.py | 13 +- aircox/controllers/diffusion_monitor.py | 60 ++ aircox/locale/fr/LC_MESSAGES/django.mo | Bin 14348 -> 14556 bytes aircox/locale/fr/LC_MESSAGES/django.po | 670 ++++++++++-------- aircox/management/commands/diffusions.py | 4 +- aircox/models/page.py | 10 + aircox/templates/admin/base.html | 78 +- aircox/templates/admin/index.html | 158 ++--- aircox/templates/aircox/base.html | 4 + aircox/templates/aircox/errors/base.html | 30 + .../templates/aircox/errors/no_station.html | 22 + .../aircox/widgets/basepage_item.html | 2 + .../aircox/widgets/comment_item.html | 41 ++ aircox/tests/admin/__init__.py | 0 .../controllers/test_diffusion_monitor.py | 56 ++ aircox/tests/models/test_signals.py | 110 +++ aircox/tests/test_middleware.py | 48 ++ aircox/tests/test_utils.py | 45 ++ aircox/tests/views/__init__.py | 0 aircox/tests/views/conftest.py | 40 ++ aircox/tests/views/test_base.py | 76 ++ aircox/tests/views/test_mixins.py | 166 +++++ aircox/urls.py | 5 + aircox/views/__init__.py | 3 +- aircox/views/base.py | 6 + aircox/views/errors.py | 8 + .../locale/fr/LC_MESSAGES/django.mo | Bin 1607 -> 1495 bytes .../locale/fr/LC_MESSAGES/django.po | 25 +- 28 files changed, 1242 insertions(+), 438 deletions(-) create mode 100644 aircox/controllers/diffusion_monitor.py create mode 100644 aircox/templates/aircox/errors/base.html create mode 100644 aircox/templates/aircox/errors/no_station.html create mode 100644 aircox/templates/aircox/widgets/comment_item.html create mode 100644 aircox/tests/admin/__init__.py create mode 100644 aircox/tests/controllers/test_diffusion_monitor.py create mode 100644 aircox/tests/models/test_signals.py create mode 100644 aircox/tests/test_middleware.py create mode 100644 aircox/tests/test_utils.py create mode 100644 aircox/tests/views/__init__.py create mode 100644 aircox/tests/views/conftest.py create mode 100644 aircox/tests/views/test_base.py create mode 100644 aircox/tests/views/test_mixins.py create mode 100644 aircox/views/errors.py diff --git a/aircox/admin_site.py b/aircox/admin_site.py index 5f767b1..bfb334f 100644 --- a/aircox/admin_site.py +++ b/aircox/admin_site.py @@ -3,7 +3,7 @@ from django.urls import include, path, reverse from django.utils.translation import gettext_lazy as _ from rest_framework.routers import DefaultRouter -from .models import Comment, Diffusion, Program +from . import models from .views.admin import StatisticsView __all__ = ["AdminSite"] @@ -26,17 +26,20 @@ class AdminSite(admin.AdminSite): context.update( { # all programs - "programs": Program.objects.active() + "programs": models.Program.objects.active() .values("pk", "title") .order_by("title"), # today's diffusions - "diffusions": Diffusion.objects.date() + "diffusions": models.Diffusion.objects.date() .order_by("start") .select_related("episode"), # TODO: only for dashboard # last comments - "comments": Comment.objects.order_by("-date").select_related( - "page" + "comments": models.Comment.objects.order_by( + "-date" + ).select_related("page")[0:10], + "latests": models.Page.objects.select_subclasses().order_by( + "-pub_date" )[0:10], } ) diff --git a/aircox/controllers/diffusion_monitor.py b/aircox/controllers/diffusion_monitor.py new file mode 100644 index 0000000..9f5ced1 --- /dev/null +++ b/aircox/controllers/diffusion_monitor.py @@ -0,0 +1,60 @@ +from datetime import datetime, time +import logging + +from django.db import transaction +from django.utils import timezone as tz + +from aircox.models import Diffusion, Schedule + +logger = logging.getLogger("aircox.commands") + + +__all__ = ("DiffusionMonitor",) + + +class DiffusionMonitor: + """Handle generation and update of Diffusion instances.""" + + date = None + + def __init__(self, date): + self.date = date or date.today() + + def update(self): + episodes, diffusions = [], [] + for schedule in Schedule.objects.filter( + program__active=True, initial__isnull=True + ): + eps, diffs = schedule.diffusions_of_month(self.date) + if eps: + episodes += eps + if diffs: + diffusions += diffs + + logger.info( + "[update] %s: %d episodes, %d diffusions and reruns", + str(schedule), + len(eps), + len(diffs), + ) + + with transaction.atomic(): + logger.info( + "[update] save %d episodes and %d diffusions", + len(episodes), + len(diffusions), + ) + for episode in episodes: + episode.save() + for diffusion in diffusions: + # force episode id's update + diffusion.episode = diffusion.episode + diffusion.save() + + def clean(self): + qs = Diffusion.objects.filter( + type=Diffusion.TYPE_UNCONFIRMED, + start__lt=tz.make_aware(datetime.combine(self.date, time.min)), + ) + logger.info("[clean] %d diffusions will be removed", qs.count()) + qs.delete() diff --git a/aircox/locale/fr/LC_MESSAGES/django.mo b/aircox/locale/fr/LC_MESSAGES/django.mo index 8694fddc337185607d399c97eddcdc0d63f90cb6..53652d05d654959492d66d915feff2ac90e08b5e 100644 GIT binary patch delta 5843 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 1);\n" -#: aircox/admin/episode.py:27 aircox/models/episode.py:183 -#: aircox/models/log.py:82 +#: aircox/admin/diffusion.py:26 aircox/models/diffusion.py:130 +#: aircox/models/log.py:80 msgid "start" msgstr "début" -#: aircox/admin/episode.py:31 aircox/models/episode.py:184 -#: aircox/models/program.py:469 +#: aircox/admin/diffusion.py:31 aircox/models/diffusion.py:131 +#: aircox/models/program.py:186 msgid "end" msgstr "fin" -#: aircox/admin/filters.py:23 +#: aircox/admin/filters.py:27 aircox/tests/admin/test_filters.py:56 msgid "Exact" msgstr "Exact" -#: aircox/admin/filters.py:24 +#: aircox/admin/filters.py:28 aircox/tests/admin/test_filters.py:57 msgid "Since" msgstr "Depuis" -#: aircox/admin/filters.py:25 +#: aircox/admin/filters.py:29 aircox/tests/admin/test_filters.py:58 msgid "Until" msgstr "Jusque" -#: aircox/admin/filters.py:27 +#: aircox/admin/filters.py:33 aircox/tests/admin/test_filters.py:55 msgid "None" msgstr "Aucun" -#: aircox/admin/filters.py:38 +#: aircox/admin/filters.py:49 msgid "Any" msgstr "Tout" -#: aircox/admin/page.py:41 +#: aircox/admin/page.py:43 msgid "Publication Settings" msgstr "Paramètre de la publication" -#: aircox/admin/program.py:40 aircox/models/program.py:282 +#: aircox/admin/program.py:24 aircox/models/schedule.py:67 msgid "Schedule" msgstr "Horaire" -#: aircox/admin/program.py:53 +#: aircox/admin/program.py:38 msgid "Program Settings" msgstr "Paramètres de l'émission" -#: aircox/admin/program.py:64 aircox/models/program.py:118 +#: aircox/admin/schedule.py:33 aircox/models/program.py:115 msgid "Program" msgstr "Émission" -#: aircox/admin/program.py:68 +#: aircox/admin/schedule.py:38 msgid "Day" msgstr "Jour" -#: aircox/admin/sound.py:37 aircox/admin/sound.py:71 +#: aircox/admin/sound.py:45 aircox/admin/sound.py:106 msgid "Audio" msgstr "Audio" -#: aircox/admin/sound.py:65 +#: aircox/admin/sound.py:97 msgid "Program / Episode" msgstr "Émission / Épisode" -#: aircox/admin/sound.py:100 -#: aircox/templates/admin/aircox/playlist_inline.html:20 +#: aircox/admin/sound.py:143 +#: aircox/templates/admin/aircox/playlist_inline.html:17 #: aircox/templates/aircox/episode_detail.html:36 msgid "Playlist" msgstr "Playlist" -#: aircox/admin/sound.py:102 +#: aircox/admin/sound.py:146 msgid "Info" msgstr "Info" -#: aircox/admin/sound.py:116 aircox/models/sound.py:240 +#: aircox/admin/sound.py:160 aircox/models/sound.py:285 msgid "timestamp" msgstr "temps" -#: aircox/admin_site.py:17 aircox/views/admin.py:36 +#: aircox/admin_site.py:15 aircox/tests/test_admin_site.py:40 +#: aircox/views/admin.py:35 msgid "Statistics" msgstr "Statistiques" -#: aircox/filters.py:8 aircox/templates/admin/base.html:84 -#: aircox/templates/admin/base.html:98 aircox/templates/admin/base.html:112 -#: aircox/templates/aircox/base.html:78 +#: aircox/controllers/sound_file.py:233 +msgid "unknown" +msgstr "inconnu" + +#: aircox/filters.py:8 aircox/templates/admin/base.html:90 +#: aircox/templates/admin/base.html:107 aircox/templates/admin/base.html:124 +#: aircox/templates/aircox/base.html:79 #: aircox/templates/aircox/page_list.html:15 msgid "Search" msgstr "Chercher" -#: aircox/filters.py:22 +#: aircox/filters.py:23 msgid "Podcast" msgstr "Podcast" -#: aircox/management/commands/sounds_monitor.py:205 -msgid "unknown" -msgstr "inconnu" - -#: aircox/models/article.py:16 +#: aircox/models/article.py:15 msgid "Article" msgstr "Article" -#: aircox/models/article.py:17 aircox/templates/admin/base.html:95 +#: aircox/models/article.py:16 aircox/templates/admin/base.html:86 #: aircox/templates/aircox/program_detail.html:19 msgid "Articles" msgstr "Articles" -#: aircox/models/episode.py:52 aircox/templates/admin/aircox/statistics.html:23 -msgid "Episode" -msgstr "Épisode" - -#: aircox/models/episode.py:53 aircox/templates/admin/base.html:109 -msgid "Episodes" -msgstr "Épisodes" - -#: aircox/models/episode.py:168 aircox/models/log.py:83 +#: aircox/models/diffusion.py:108 aircox/models/log.py:82 msgid "on air" msgstr "à l'antenne" -#: aircox/models/episode.py:169 +#: aircox/models/diffusion.py:109 msgid "not confirmed" msgstr "non confirmé" -#: aircox/models/episode.py:170 aircox/models/log.py:83 +#: aircox/models/diffusion.py:110 aircox/models/log.py:81 msgid "cancelled" msgstr "annulé" -#: aircox/models/episode.py:174 aircox/models/sound.py:99 -#: aircox/models/sound.py:230 +#: aircox/models/diffusion.py:116 aircox/models/sound.py:114 +#: aircox/models/sound.py:270 msgid "episode" msgstr "épisode" -#: aircox/models/episode.py:177 +#: aircox/models/diffusion.py:121 msgid "schedule" msgstr "horaire" -#: aircox/models/episode.py:181 aircox/models/log.py:91 -#: aircox/models/sound.py:102 aircox/models/station.py:142 +#: aircox/models/diffusion.py:126 aircox/models/log.py:92 +#: aircox/models/sound.py:117 aircox/models/station.py:162 msgid "type" msgstr "type" -#: aircox/models/episode.py:196 aircox/models/log.py:117 +#: aircox/models/diffusion.py:143 aircox/models/log.py:131 msgid "Diffusion" msgstr "Date de diffusion" -#: aircox/models/episode.py:197 aircox/templates/aircox/episode_detail.html:55 +#: aircox/models/diffusion.py:144 +#: aircox/templates/aircox/episode_detail.html:55 #: aircox/templates/aircox/program_detail.html:45 msgid "Diffusions" msgstr "Dates de diffusion" -#: aircox/models/episode.py:199 +#: aircox/models/diffusion.py:146 msgid "edit the diffusions' planification" msgstr "éditer les dates de diffusion" -#: aircox/models/episode.py:208 aircox/templates/aircox/episode_detail.html:71 +#: aircox/models/diffusion.py:155 +#: aircox/templates/aircox/episode_detail.html:71 msgid "rerun" msgstr "rediffusion" -#: aircox/models/log.py:82 +#: aircox/models/episode.py:48 aircox/templates/admin/aircox/statistics.html:23 +msgid "Episode" +msgstr "Épisode" + +#: aircox/models/episode.py:49 aircox/templates/admin/base.html:120 +msgid "Episodes" +msgstr "Épisodes" + +#: aircox/models/log.py:79 msgid "stop" msgstr "stop" -#: aircox/models/log.py:84 aircox/models/sound.py:86 +#: aircox/models/log.py:83 aircox/models/sound.py:94 msgid "other" msgstr "autre" -#: aircox/models/log.py:89 aircox/models/page.py:248 -#: aircox/models/program.py:54 aircox/models/station.py:139 +#: aircox/models/log.py:89 aircox/models/page.py:301 +#: aircox/models/program.py:51 aircox/models/station.py:157 msgid "station" msgstr "station" -#: aircox/models/log.py:89 +#: aircox/models/log.py:90 msgid "related station" msgstr "station relative" -#: aircox/models/log.py:92 aircox/models/program.py:250 +#: aircox/models/log.py:93 aircox/models/schedule.py:43 msgid "date" msgstr "date" -#: aircox/models/log.py:97 +#: aircox/models/log.py:100 msgid "source" msgstr "source" -#: aircox/models/log.py:98 +#: aircox/models/log.py:101 msgid "identifier of the source related to this log" msgstr "identifiant de la source relative à ce log" -#: aircox/models/log.py:102 +#: aircox/models/log.py:107 msgid "comment" msgstr "commentaire" -#: aircox/models/log.py:107 aircox/models/sound.py:143 +#: aircox/models/log.py:115 aircox/models/sound.py:174 msgid "Sound" msgstr "Son" -#: aircox/models/log.py:112 aircox/models/sound.py:259 +#: aircox/models/log.py:123 aircox/models/sound.py:308 #: aircox/templates/admin/aircox/statistics.html:24 msgid "Track" msgstr "Morceau" -#: aircox/models/log.py:143 +#: aircox/models/log.py:155 msgid "Log" msgstr "Log" -#: aircox/models/log.py:144 +#: aircox/models/log.py:156 msgid "Logs" msgstr "Logs" -#: aircox/models/page.py:30 aircox/models/page.py:251 -#: aircox/models/sound.py:244 +#: aircox/models/page.py:34 aircox/models/page.py:305 +#: aircox/models/sound.py:290 msgid "title" msgstr "titre" -#: aircox/models/page.py:31 aircox/models/page.py:76 -#: aircox/models/station.py:38 +#: aircox/models/page.py:35 aircox/models/page.py:93 +#: aircox/models/station.py:34 msgid "slug" msgstr "slug" -#: aircox/models/page.py:34 +#: aircox/models/page.py:38 msgid "Category" msgstr "Catégorie" -#: aircox/models/page.py:35 aircox/templates/aircox/page_list.html:32 +#: aircox/models/page.py:39 aircox/templates/aircox/page_list.html:32 msgid "Categories" msgstr "Catégories" -#: aircox/models/page.py:68 +#: aircox/models/page.py:78 msgid "draft" msgstr "brouillon" -#: aircox/models/page.py:69 +#: aircox/models/page.py:79 msgid "published" msgstr "publié" -#: aircox/models/page.py:70 +#: aircox/models/page.py:80 msgid "trash" msgstr "corbeille" -#: aircox/models/page.py:79 +#: aircox/models/page.py:96 msgid "status" msgstr "statut" -#: aircox/models/page.py:83 +#: aircox/models/page.py:102 msgid "cover" msgstr "couverture" -#: aircox/models/page.py:86 aircox/models/page.py:238 +#: aircox/models/page.py:107 aircox/models/page.py:279 msgid "content" msgstr "contenu" -#: aircox/models/page.py:162 +#: aircox/models/page.py:191 msgid "category" msgstr "catégorie" -#: aircox/models/page.py:165 +#: aircox/models/page.py:197 msgid "publication date" msgstr "date de publication" -#: aircox/models/page.py:167 +#: aircox/models/page.py:200 msgid "featured" msgstr "en avant" -#: aircox/models/page.py:170 +#: aircox/models/page.py:204 msgid "allow comments" msgstr "autoriser les commentaires" -#: aircox/models/page.py:176 +#: aircox/models/page.py:211 msgid "Publication" msgstr "Publication" -#: aircox/models/page.py:177 +#: aircox/models/page.py:212 msgid "Publications" msgstr "Publications" -#: aircox/models/page.py:202 +#: aircox/models/page.py:238 msgid "Home page" msgstr "Page d'accueil" -#: aircox/models/page.py:203 +#: aircox/models/page.py:239 msgid "Diffusions page" msgstr "Grille horaire" -#: aircox/models/page.py:204 +#: aircox/models/page.py:240 msgid "Logs page" msgstr "Page des logs" -#: aircox/models/page.py:205 +#: aircox/models/page.py:241 msgid "Programs list" msgstr "Liste des émissions" -#: aircox/models/page.py:206 +#: aircox/models/page.py:242 msgid "Episodes list" msgstr "Liste des épisodes" -#: aircox/models/page.py:207 +#: aircox/models/page.py:243 msgid "Articles list" msgstr "Liste des articles" -#: aircox/models/page.py:219 +#: aircox/models/page.py:255 msgid "attach to" msgstr "attacher à" -#: aircox/models/page.py:220 +#: aircox/models/page.py:259 msgid "display this page content to related element" msgstr "Afficher le contenu de cette page pour l'élément sélectionné" -#: aircox/models/page.py:231 +#: aircox/models/page.py:272 msgid "related page" msgstr "page liée" -#: aircox/models/page.py:235 +#: aircox/models/page.py:276 msgid "nickname" msgstr "pseudo" -#: aircox/models/page.py:236 +#: aircox/models/page.py:277 msgid "email" msgstr "email" -#: aircox/models/page.py:241 +#: aircox/models/page.py:293 msgid "Comment" msgstr "Commentaire" -#: aircox/models/page.py:242 aircox/templates/aircox/page_detail.html:36 +#: aircox/models/page.py:294 aircox/templates/aircox/page_detail.html:37 msgid "Comments" msgstr "Commentaires" -#: aircox/models/page.py:249 +#: aircox/models/page.py:303 msgid "menu" msgstr "menu" -#: aircox/models/page.py:250 aircox/models/sound.py:104 -#: aircox/models/sound.py:237 +#: aircox/models/page.py:304 aircox/models/sound.py:119 +#: aircox/models/sound.py:280 msgid "order" msgstr "ordre" -#: aircox/models/page.py:252 +#: aircox/models/page.py:306 msgid "url" msgstr "url" -#: aircox/models/page.py:254 +#: aircox/models/page.py:311 msgid "page" msgstr "page" -#: aircox/models/page.py:256 +#: aircox/models/page.py:317 msgid "Menu item" msgstr "Élément du menu" -#: aircox/models/page.py:257 +#: aircox/models/page.py:318 msgid "Menu items" msgstr "Éléments de menu" -#: aircox/models/program.py:56 aircox/models/station.py:52 -#: aircox/models/station.py:144 +#: aircox/models/program.py:54 aircox/models/station.py:48 +#: aircox/models/station.py:164 msgid "active" msgstr "actif" -#: aircox/models/program.py:58 +#: aircox/models/program.py:56 msgid "if not checked this program is no longer active" msgstr "si selectionné, cette émission n'est plus active" -#: aircox/models/program.py:61 +#: aircox/models/program.py:59 msgid "syncronise" msgstr "synchroniser" -#: aircox/models/program.py:63 +#: aircox/models/program.py:61 msgid "update later diffusions according to schedule changes" msgstr "met à jour les dates de diffusion à venir lorsque l'horaire change" -#: aircox/models/program.py:119 aircox/templates/admin/base.html:81 +#: aircox/models/program.py:116 aircox/templates/admin/base.html:103 msgid "Programs" msgstr "Émissions" -#: aircox/models/program.py:174 aircox/models/program.py:457 +#: aircox/models/program.py:171 aircox/models/rerun.py:49 msgid "related program" msgstr "émission apparentée" -#: aircox/models/program.py:178 -msgid "rerun of" -msgstr "rediffusion de" - -#: aircox/models/program.py:222 -msgid "rerun must happen after original" -msgstr "la rediffusion doit être après l'original" - -#: aircox/models/program.py:250 -msgid "date of the first diffusion" -msgstr "date de la première diffusion" - -#: aircox/models/program.py:253 -msgid "time" -msgstr "heure" - -#: aircox/models/program.py:253 -msgid "start time" -msgstr "heure de début" - -#: aircox/models/program.py:256 -msgid "timezone" -msgstr "zone horaire" - -#: aircox/models/program.py:259 -msgid "timezone used for the date" -msgstr "zone horaire utilisée pour la date" - -#: aircox/models/program.py:262 aircox/models/sound.py:117 -msgid "duration" -msgstr "durée" - -#: aircox/models/program.py:263 -msgid "regular duration" -msgstr "durée normale" - -#: aircox/models/program.py:266 -msgid "frequency" -msgstr "fréquence" - -#: aircox/models/program.py:268 -msgid "ponctual" -msgstr "ponctuel" - -#: aircox/models/program.py:269 -#, python-brace-format -msgid "1st {day} of the month" -msgstr "1er {day} du mois" - -#: aircox/models/program.py:270 -#, python-brace-format -msgid "2nd {day} of the month" -msgstr "2e {day} du mois" - -#: aircox/models/program.py:271 -#, python-brace-format -msgid "3rd {day} of the month" -msgstr "3e {day} du mois" - -#: aircox/models/program.py:272 -#, python-brace-format -msgid "4th {day} of the month" -msgstr "4e {day} du mois" - -#: aircox/models/program.py:273 -#, python-brace-format -msgid "last {day} of the month" -msgstr "dernier {day} du mois" - -#: aircox/models/program.py:274 -#, python-brace-format -msgid "1st and 3rd {day} of the month" -msgstr "1er et 3e {day} du mois" - -#: aircox/models/program.py:275 -#, python-brace-format -msgid "2nd and 4th {day} of the month" -msgstr "2ème et 4e {day} du mois" - -#: aircox/models/program.py:276 -msgid "{day}" -msgstr "{day}" - -#: aircox/models/program.py:277 -#, python-brace-format -msgid "one {day} on two" -msgstr "un {day} sur deux" - -#: aircox/models/program.py:283 -msgid "Schedules" -msgstr "Horaires" - -#: aircox/models/program.py:460 +#: aircox/models/program.py:174 msgid "delay" msgstr "délai" -#: aircox/models/program.py:461 +#: aircox/models/program.py:177 msgid "minimal delay between two sound plays" msgstr "délai minimum entre deux sons joués" -#: aircox/models/program.py:464 +#: aircox/models/program.py:180 msgid "begin" msgstr "début" -#: aircox/models/program.py:465 aircox/models/program.py:471 +#: aircox/models/program.py:183 aircox/models/program.py:189 msgid "used to define a time range this stream is played" msgstr "" "utilisé pour définir un intervalle de temps pendant lequel ce stream est joué" -#: aircox/models/sound.py:86 +#: aircox/models/rerun.py:55 +msgid "rerun of" +msgstr "rediffusion de" + +#: aircox/models/rerun.py:87 +msgid "rerun must happen after original" +msgstr "la rediffusion doit être après l'original" + +#: aircox/models/schedule.py:31 +msgid "ponctual" +msgstr "ponctuel" + +#: aircox/models/schedule.py:32 +#, python-brace-format +msgid "1st {day} of the month" +msgstr "1er {day} du mois" + +#: aircox/models/schedule.py:33 +#, python-brace-format +msgid "2nd {day} of the month" +msgstr "2e {day} du mois" + +#: aircox/models/schedule.py:34 +#, python-brace-format +msgid "3rd {day} of the month" +msgstr "3e {day} du mois" + +#: aircox/models/schedule.py:35 +#, python-brace-format +msgid "4th {day} of the month" +msgstr "4e {day} du mois" + +#: aircox/models/schedule.py:36 +#, python-brace-format +msgid "last {day} of the month" +msgstr "dernier {day} du mois" + +#: aircox/models/schedule.py:37 +#, python-brace-format +msgid "1st and 3rd {day} of the month" +msgstr "1er et 3e {day} du mois" + +#: aircox/models/schedule.py:38 +#, python-brace-format +msgid "2nd and 4th {day} of the month" +msgstr "2ème et 4e {day} du mois" + +#: aircox/models/schedule.py:39 +#, python-brace-format +msgid "{day}" +msgstr "{day}" + +#: aircox/models/schedule.py:40 +#, python-brace-format +msgid "one {day} on two" +msgstr "un {day} sur deux" + +#: aircox/models/schedule.py:44 +msgid "date of the first diffusion" +msgstr "date de la première diffusion" + +#: aircox/models/schedule.py:47 +msgid "time" +msgstr "heure" + +#: aircox/models/schedule.py:48 +msgid "start time" +msgstr "heure de début" + +#: aircox/models/schedule.py:51 +msgid "timezone" +msgstr "zone horaire" + +#: aircox/models/schedule.py:55 +msgid "timezone used for the date" +msgstr "zone horaire utilisée pour la date" + +#: aircox/models/schedule.py:58 aircox/models/sound.py:140 +msgid "duration" +msgstr "durée" + +#: aircox/models/schedule.py:59 +msgid "regular duration" +msgstr "durée normale" + +#: aircox/models/schedule.py:62 +msgid "frequency" +msgstr "fréquence" + +#: aircox/models/schedule.py:68 +msgid "Schedules" +msgstr "Horaires" + +#: aircox/models/sound.py:95 msgid "archive" msgstr "archive" -#: aircox/models/sound.py:87 +#: aircox/models/sound.py:96 msgid "excerpt" msgstr "extrait" -#: aircox/models/sound.py:87 +#: aircox/models/sound.py:97 msgid "removed" msgstr "supprimé" -#: aircox/models/sound.py:90 aircox/models/station.py:37 +#: aircox/models/sound.py:100 aircox/models/station.py:33 msgid "name" msgstr "nom" -#: aircox/models/sound.py:93 +#: aircox/models/sound.py:105 msgid "program" msgstr "émission" -#: aircox/models/sound.py:94 +#: aircox/models/sound.py:106 msgid "program related to it" msgstr "émission apparentée à celui-ci" -#: aircox/models/sound.py:104 aircox/models/sound.py:237 +#: aircox/models/sound.py:121 aircox/models/sound.py:282 msgid "position in the playlist" msgstr "position dans la playlist" -#: aircox/models/sound.py:113 aircox/models/station.py:135 +#: aircox/models/sound.py:133 aircox/models/station.py:153 msgid "file" msgstr "fichier" -#: aircox/models/sound.py:119 +#: aircox/models/sound.py:143 msgid "duration of the sound" msgstr "durée du son" -#: aircox/models/sound.py:122 +#: aircox/models/sound.py:146 msgid "modification time" msgstr "dernière modification" -#: aircox/models/sound.py:124 +#: aircox/models/sound.py:149 msgid "last modification date and time" msgstr "date et heure de la dernière modification" -#: aircox/models/sound.py:127 +#: aircox/models/sound.py:152 msgid "good quality" msgstr "bonne qualité" -#: aircox/models/sound.py:127 +#: aircox/models/sound.py:153 msgid "sound meets quality requirements" msgstr "le son rencontre les exigences de qualité" -#: aircox/models/sound.py:131 +#: aircox/models/sound.py:158 msgid "public" msgstr "publique" -#: aircox/models/sound.py:131 +#: aircox/models/sound.py:159 msgid "whether it is publicly available as podcast" msgstr "coché pour rendre le podcast public" -#: aircox/models/sound.py:135 +#: aircox/models/sound.py:163 msgid "downloadable" msgstr "téléchargeable" -#: aircox/models/sound.py:136 +#: aircox/models/sound.py:165 msgid "" "whether it can be publicly downloaded by visitors (sound must be public)" msgstr "" "coché pour permettre le téléchargement public (le podcast doit être " "disponible publiquement)" -#: aircox/models/sound.py:144 +#: aircox/models/sound.py:175 msgid "Sounds" msgstr "Sons" -#: aircox/models/sound.py:234 +#: aircox/models/sound.py:277 msgid "sound" msgstr "son" -#: aircox/models/sound.py:242 +#: aircox/models/sound.py:288 msgid "position (in seconds)" msgstr "position (en secondes)" -#: aircox/models/sound.py:245 +#: aircox/models/sound.py:291 msgid "artist" msgstr "artiste" -#: aircox/models/sound.py:246 +#: aircox/models/sound.py:292 msgid "album" msgstr "album" -#: aircox/models/sound.py:247 +#: aircox/models/sound.py:293 msgid "tags" msgstr "tags" -#: aircox/models/sound.py:248 +#: aircox/models/sound.py:294 msgid "year" msgstr "année" -#: aircox/models/sound.py:251 +#: aircox/models/sound.py:297 msgid "information" msgstr "information" -#: aircox/models/sound.py:254 +#: aircox/models/sound.py:302 msgid "" "additional informations about this track, such as the version, if is it a " "remix, features, etc." @@ -607,77 +611,77 @@ msgstr "" "informations additionnelles à propos de ce morceau, telles que la version, " "s'il s'agit d'un remix, les fonctionnalités, etc" -#: aircox/models/sound.py:260 +#: aircox/models/sound.py:309 msgid "Tracks" msgstr "Morceaux" -#: aircox/models/station.py:41 +#: aircox/models/station.py:37 msgid "path" msgstr "chemin" -#: aircox/models/station.py:42 +#: aircox/models/station.py:38 msgid "path to the working directory" msgstr "chemin vers le repertoire courant" -#: aircox/models/station.py:47 +#: aircox/models/station.py:43 msgid "default station" msgstr "station par défaut" -#: aircox/models/station.py:49 +#: aircox/models/station.py:45 msgid "use this station as the main one." msgstr "utiliser cette station comme principale." -#: aircox/models/station.py:54 +#: aircox/models/station.py:50 msgid "whether this station is still active or not." msgstr "si cette station est active ou non." -#: aircox/models/station.py:58 +#: aircox/models/station.py:56 msgid "Logo" msgstr "Logo" -#: aircox/models/station.py:61 +#: aircox/models/station.py:59 msgid "website's urls" msgstr "URL du site web" -#: aircox/models/station.py:62 -msgid "specify one url per line" -msgstr "spécifiez une url par ligne" +#: aircox/models/station.py:63 +msgid "specify one domain per line, without 'http://' prefix" +msgstr "" -#: aircox/models/station.py:65 +#: aircox/models/station.py:66 msgid "audio streams" msgstr "stream audio" -#: aircox/models/station.py:66 +#: aircox/models/station.py:71 msgid "Audio streams urls used by station's player. One url a line." msgstr "" "Les URL des flux audio utilisés par le lecteur de la station. Une url par " "ligne." -#: aircox/models/station.py:71 +#: aircox/models/station.py:76 msgid "Default pages' cover" msgstr "Couverture par défault des pages." -#: aircox/models/station.py:121 +#: aircox/models/station.py:135 msgid "input" msgstr "entrée" -#: aircox/models/station.py:122 +#: aircox/models/station.py:136 msgid "output" msgstr "sortie" -#: aircox/models/station.py:141 +#: aircox/models/station.py:160 msgid "direction" msgstr "direction" -#: aircox/models/station.py:145 +#: aircox/models/station.py:164 msgid "this port is active" msgstr "ce port est actif" -#: aircox/models/station.py:148 +#: aircox/models/station.py:167 msgid "port settings" msgstr "paramètres du port" -#: aircox/models/station.py:149 +#: aircox/models/station.py:169 msgid "" "list of comma separated params available; this is put in the output config " "file as raw code; plugin related" @@ -685,15 +689,15 @@ msgstr "" "liste des paramètres disponibles séparés par des virgules; placé dans le " "fichier de configuration en tant que code brut; relatif au plugin utilisé" -#: aircox/models/user_settings.py:11 +#: aircox/models/user_settings.py:14 msgid "User" msgstr "Utilisateur" -#: aircox/models/user_settings.py:14 +#: aircox/models/user_settings.py:17 msgid "Playlist Editor Columns" msgstr "Colonnes de l'éditeur de playlist" -#: aircox/models/user_settings.py:16 +#: aircox/models/user_settings.py:19 msgid "Playlist Editor Separator" msgstr "Séparateur de l'éditeur de playlist" @@ -704,9 +708,9 @@ msgstr "Par %(filter_title)s " #: aircox/templates/admin/aircox/page_change_form.html:9 #: aircox/templates/admin/aircox/page_change_list.html:7 -#: aircox/templates/admin/base.html:166 +#: aircox/templates/admin/base.html:182 #: aircox/templates/admin/change_list.html:30 -#: aircox/templates/aircox/base.html:54 +#: aircox/templates/aircox/base.html:55 msgid "Home" msgstr "Accueil" @@ -735,8 +739,8 @@ msgstr "Sauvegarder et continuer" msgid "Publish" msgstr "Publier" -#: aircox/templates/admin/aircox/playlist_inline.html:33 -#: aircox/templates/admin/aircox/playlist_inline.html:34 +#: aircox/templates/admin/aircox/playlist_inline.html:30 +#: aircox/templates/admin/aircox/playlist_inline.html:31 msgid "Track Position" msgstr "Position dans la playlist" @@ -745,7 +749,7 @@ msgid "Time" msgstr "Heure" #: aircox/templates/admin/aircox/statistics.html:25 -#: aircox/templatetags/aircox_admin.py:52 +#: aircox/templatetags/aircox_admin.py:51 msgid "Tags" msgstr "Étiquettes" @@ -753,28 +757,28 @@ msgstr "Étiquettes" msgid "Total" msgstr "Total" -#: aircox/templates/admin/base.html:68 aircox/templates/admin/index.html:11 +#: aircox/templates/admin/base.html:70 aircox/templates/admin/index.html:12 #: aircox/templates/aircox/home.html:47 msgid "Today" msgstr "Aujourd'hui" -#: aircox/templates/admin/base.html:124 +#: aircox/templates/admin/base.html:138 msgid "Tools" msgstr "Outils" -#: aircox/templates/admin/base.html:140 +#: aircox/templates/admin/base.html:156 msgid "View site" msgstr "Voir le site" -#: aircox/templates/admin/base.html:145 +#: aircox/templates/admin/base.html:161 msgid "Documentation" msgstr "Documentation" -#: aircox/templates/admin/base.html:149 +#: aircox/templates/admin/base.html:165 msgid "Change password" msgstr "Changer le mot de passe" -#: aircox/templates/admin/base.html:152 +#: aircox/templates/admin/base.html:168 msgid "Log out" msgstr "Se déconnecter" @@ -790,30 +794,38 @@ msgstr "Veuillez corriger les erreurs ci-dessous." msgid "Filter" msgstr "Filtre" -#: aircox/templates/admin/index.html:27 +#: aircox/templates/admin/index.html:30 msgid "Live diffusion" msgstr "Diffusion en live" -#: aircox/templates/admin/index.html:30 +#: aircox/templates/admin/index.html:33 msgid "Differed diffusion" msgstr "Diffusion différée" -#: aircox/templates/admin/index.html:51 +#: aircox/templates/admin/index.html:54 +msgid "No diffusion is scheduled for today." +msgstr "Aucune diffusion planifiée aujourd'hui" + +#: aircox/templates/admin/index.html:62 msgid "Latest comments" msgstr "Derniers commentaires" -#: aircox/templates/admin/index.html:65 aircox/templates/admin/index.html:66 -msgid "Edit comment" -msgstr "Editer le commentaire" - -#: aircox/templates/admin/index.html:70 aircox/templates/admin/index.html:71 -msgid "Delete comment" -msgstr "Supprimer le commentaire" - -#: aircox/templates/admin/index.html:87 +#: aircox/templates/admin/index.html:67 msgid "All comments" msgstr "Tous les commentaires" +#: aircox/templates/admin/index.html:70 +msgid "No comment posted yet" +msgstr "Aucun commentaire posté pour le moment." + +#: aircox/templates/admin/index.html:78 +msgid "Latest publications" +msgstr "Dernières publications" + +#: aircox/templates/admin/index.html:87 +msgid "Administration" +msgstr "Administration" + #. Translators: in page detail sidebar #: aircox/templates/aircox/article_detail.html:12 msgid "Latest news" @@ -827,7 +839,7 @@ msgstr "Afficher toutes les nouvelles" msgid "More news" msgstr "Plus de nouvelles" -#: aircox/templates/aircox/base.html:147 +#: aircox/templates/aircox/base.html:149 msgid "Recently" msgstr "Récemment" @@ -872,6 +884,36 @@ msgstr "Podcasts" msgid "Rerun of %(date)s" msgstr "Rediffusion du %(date)s" +#: aircox/templates/aircox/errors/base.html:13 +msgid "An error occurred..." +msgstr "" + +#: aircox/templates/aircox/errors/base.html:24 +msgid "An error occurred" +msgstr "" + +#: aircox/templates/aircox/errors/no_station.html:4 +msgid "No station is configured" +msgstr "" + +#: aircox/templates/aircox/errors/no_station.html:7 +msgid "It seems there is no station configured for this website:" +msgstr "" + +#: aircox/templates/aircox/errors/no_station.html:11 +msgid "" +"If you are the website administrator, please connect to administration " +"interface." +msgstr "" + +#: aircox/templates/aircox/errors/no_station.html:13 +msgid "Go to admin" +msgstr "" + +#: aircox/templates/aircox/errors/no_station.html:18 +msgid "If you are a visitor, please contact your favorite radio" +msgstr "" + #: aircox/templates/aircox/home.html:28 msgid "Currently" msgstr "En ce moment" @@ -897,20 +939,20 @@ msgstr "Dernières publications" msgid "That happened on %(station)s" msgstr "C'est passé sur %(station)s" -#: aircox/templates/aircox/page_detail.html:25 +#: aircox/templates/aircox/page_detail.html:26 msgid "Edit" msgstr "Éditer" -#: aircox/templates/aircox/page_detail.html:55 +#: aircox/templates/aircox/page_detail.html:56 msgid "Post a comment" msgstr "Poster un commentaire" -#: aircox/templates/aircox/page_detail.html:80 +#: aircox/templates/aircox/page_detail.html:81 #: aircox/templates/aircox/page_list.html:57 msgid "Reset" msgstr "Réinitialiser" -#: aircox/templates/aircox/page_detail.html:81 +#: aircox/templates/aircox/page_detail.html:82 msgid "Post comment" msgstr "Commenter" @@ -939,6 +981,16 @@ msgstr "Rediffusion" msgid "Recently on %(program)s" msgstr "Récemment dans %(program)s" +#: aircox/templates/aircox/widgets/comment_item.html:7 +#: aircox/templates/aircox/widgets/comment_item.html:8 +msgid "Edit comment" +msgstr "Editer le commentaire" + +#: aircox/templates/aircox/widgets/comment_item.html:12 +#: aircox/templates/aircox/widgets/comment_item.html:13 +msgid "Delete comment" +msgstr "Supprimer le commentaire" + #: aircox/templates/aircox/widgets/dates_menu.html:15 msgid "pick a date" msgstr "choisir une date" @@ -972,31 +1024,31 @@ msgstr "lecteur" msgid "Audio player used to listen to the radio and podcasts" msgstr "Lecteur audio utilisé pour écouter la radio et les podcasts" -#: aircox/templates/aircox/widgets/player.html:22 +#: aircox/templates/aircox/widgets/player.html:23 msgid "Play or pause audio" msgstr "Lire ou suspendre l'audio" -#: aircox/templates/aircox/widgets/player.html:28 +#: aircox/templates/aircox/widgets/player.html:29 msgid "Track currently on air" msgstr "Morceau en ce moment sur les ondes" -#: aircox/templates/aircox/widgets/player.html:37 +#: aircox/templates/aircox/widgets/player.html:38 msgid "Diffusion currently on air" msgstr "Épisode en ce moment sur les ondes" -#: aircox/templates/aircox/widgets/player.html:42 +#: aircox/templates/aircox/widgets/player.html:43 msgid "Currently playing" msgstr "En ce moment" -#: aircox/templatetags/aircox_admin.py:51 +#: aircox/templatetags/aircox_admin.py:48 msgid "Artist" msgstr "Artiste" -#: aircox/templatetags/aircox_admin.py:51 +#: aircox/templatetags/aircox_admin.py:49 msgid "Album" msgstr "Album" -#: aircox/templatetags/aircox_admin.py:51 +#: aircox/templatetags/aircox_admin.py:50 msgid "Title" msgstr "Titre" @@ -1025,78 +1077,80 @@ msgid "Remove" msgstr "Supprimer" #: aircox/templatetags/aircox_admin.py:58 -#| msgid "timestamp" msgid "Timestamp" msgstr "Temps" -#: aircox/urls.py:44 +#: aircox/urls.py:46 msgid "articles/" msgstr "articles/" -#: aircox/urls.py:47 +#: aircox/urls.py:51 msgid "articles//" msgstr "articles//" -#: aircox/urls.py:51 +#: aircox/urls.py:55 msgid "episodes/" msgstr "episodes/" -#: aircox/urls.py:53 +#: aircox/urls.py:57 msgid "episodes//" msgstr "episodes//" -#: aircox/urls.py:55 +#: aircox/urls.py:61 msgid "week/" msgstr "semaine/" -#: aircox/urls.py:57 +#: aircox/urls.py:63 msgid "week//" msgstr "semaine//" -#: aircox/urls.py:60 +#: aircox/urls.py:67 msgid "logs/" msgstr "logs/" -#: aircox/urls.py:61 +#: aircox/urls.py:68 msgid "logs//" msgstr "logs//" -#: aircox/urls.py:64 +#: aircox/urls.py:71 msgid "publications/" msgstr "publications/" -#: aircox/urls.py:67 +#: aircox/urls.py:76 msgid "pages/" msgstr "pages/" -#: aircox/urls.py:73 +#: aircox/urls.py:84 msgid "pages//" msgstr "pages//" -#: aircox/urls.py:80 +#: aircox/urls.py:91 msgid "programs/" msgstr "emissions/" -#: aircox/urls.py:82 +#: aircox/urls.py:93 msgid "programs//" msgstr "emissions//" -#: aircox/urls.py:84 +#: aircox/urls.py:98 msgid "programs//episodes/" msgstr "emissions//episodes/" -#: aircox/urls.py:86 +#: aircox/urls.py:103 msgid "programs//articles/" msgstr "emissions//articles/" -#: aircox/urls.py:88 +#: aircox/urls.py:108 msgid "programs//publications/" msgstr "emissions//publications/" -#: aircox/views/page.py:131 +#: aircox/views/page.py:147 msgid "comments are not allowed" msgstr "les commentaires ne sont pas autorisés" +#~ msgid "specify one url per line" +#~ msgstr "spécifiez une url par ligne" + #~ msgid "track" #~ msgstr "morceau" diff --git a/aircox/management/commands/diffusions.py b/aircox/management/commands/diffusions.py index 9f4e571..3c29234 100755 --- a/aircox/management/commands/diffusions.py +++ b/aircox/management/commands/diffusions.py @@ -11,7 +11,7 @@ from argparse import RawTextHelpFormatter from django.core.management.base import BaseCommand from django.utils import timezone as tz -from aircox.controllers.diffusions import Diffusions +from aircox.controllers.diffusion_monitor import DiffusionMonitor logger = logging.getLogger("aircox.commands") @@ -70,7 +70,7 @@ class Command(BaseCommand): date += tz.timedelta(days=28) date = date.replace(day=1) - actions = Diffusions(date) + actions = DiffusionMonitor(date) if options.get("update"): actions.update() if options.get("clean"): diff --git a/aircox/models/page.py b/aircox/models/page.py index c159ebe..6df60cb 100644 --- a/aircox/models/page.py +++ b/aircox/models/page.py @@ -278,6 +278,16 @@ class Comment(models.Model): date = models.DateTimeField(auto_now_add=True) content = models.TextField(_("content"), max_length=1024) + item_template_name = "aircox/widgets/comment_item.html" + + @cached_property + def parent(self): + """Return Page as its subclass.""" + return Page.objects.select_subclasses().filter(id=self.page_id).first() + + def get_absolute_url(self): + return self.parent.get_absolute_url() + class Meta: verbose_name = _("Comment") verbose_name_plural = _("Comments") diff --git a/aircox/templates/admin/base.html b/aircox/templates/admin/base.html index 4346f5e..4e20dfe 100644 --- a/aircox/templates/admin/base.html +++ b/aircox/templates/admin/base.html @@ -65,7 +65,10 @@