From 42b51ff283d2cfd8b2084d131e81179e1d614023 Mon Sep 17 00:00:00 2001 From: "Ph. SW." Date: Tue, 22 Oct 2024 21:14:35 +0200 Subject: [PATCH 1/4] =?UTF-8?q?Supprime=20le=20param=C3=A8tre=20`build=5Fp?= =?UTF-8?q?df=5Fwhen=5Fpublished`=20et=20d=C3=A9sactive=20plus=20d'exports?= =?UTF-8?q?=20dans=20les=20tests=20(#6670)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/source/back-end/contents.rst | 1 - zds/settings/abstract_base/zds.py | 1 - zds/settings/prod.py | 1 - zds/tutorialv2/publication_utils.py | 8 +------- zds/tutorialv2/tests/__init__.py | 1 - zds/tutorialv2/tests/tests_feeds.py | 7 +------ zds/tutorialv2/tests/tests_front.py | 3 +-- zds/tutorialv2/tests/tests_utils.py | 6 ------ zds/tutorialv2/tests/tests_views/tests_content.py | 2 -- zds/tutorialv2/tests/tests_views/tests_published.py | 4 +--- zds/utils/api/tests.py | 11 ++++++----- 11 files changed, 10 insertions(+), 35 deletions(-) diff --git a/doc/source/back-end/contents.rst b/doc/source/back-end/contents.rst index dd98c3422e..c8a369940b 100644 --- a/doc/source/back-end/contents.rst +++ b/doc/source/back-end/contents.rst @@ -602,7 +602,6 @@ Ces paramètres sont à surcharger dans le dictionnaire ``ZDS_APP['content']``: - ``user_page_number``: Nombre de contenus de chaque type qu'on affiche sur le profil d'un utilisateur, 5 par défaut, - ``default_image``: chemin vers l'image utilisée par défaut dans les icônes de contenu, - ``import_image_prefix``: préfixe mnémonique permettant d'indiquer que l'image se trouve dans l'archive jointe lors de l'import de contenu -- ``build_pdf_when_published``: indique que la publication générera un PDF (quelque soit la politique, si ``False``, les PDF ne seront pas générés, sauf à appeler la commande adéquate), - ``maximum_slug_size``: taille maximale du slug d'un contenu Paramètres propres aux tribunes libres diff --git a/zds/settings/abstract_base/zds.py b/zds/settings/abstract_base/zds.py index 29ad9724d9..94342f1b02 100644 --- a/zds/settings/abstract_base/zds.py +++ b/zds/settings/abstract_base/zds.py @@ -190,7 +190,6 @@ "user_page_number": 5, "default_image": BASE_DIR / "fixtures" / "noir_black.png", "import_image_prefix": "archive", - "build_pdf_when_published": True, "maximum_slug_size": 150, "characters_per_minute": 1500, "editorial_line_link": "https://zestedesavoir.com/articles/3978/la-ligne-editoriale-officielle-de-zeste-de-savoir-2/", diff --git a/zds/settings/prod.py b/zds/settings/prod.py index 8453c5c287..3fdc86a2ed 100644 --- a/zds/settings/prod.py +++ b/zds/settings/prod.py @@ -129,7 +129,6 @@ def _get_version(): ZDS_APP["site"]["association"]["email"] = "communication@zestedesavoir.com" # content -# ZDS_APP['content']['build_pdf_when_published'] = False ZDS_APP["article"]["repo_path"] = "/opt/zds/data/articles-data" ZDS_APP["content"]["repo_private_path"] = "/opt/zds/data/contents-private" ZDS_APP["content"]["repo_public_path"] = "/opt/zds/data/contents-public" diff --git a/zds/tutorialv2/publication_utils.py b/zds/tutorialv2/publication_utils.py index 59fd7a5a47..99dd9f1e06 100644 --- a/zds/tutorialv2/publication_utils.py +++ b/zds/tutorialv2/publication_utils.py @@ -174,22 +174,16 @@ def write_md_file(md_file_path, parsed_with_local_images, versioned): ) -def generate_external_content( - base_name, extra_contents_path, md_file_path, overload_settings=False, excluded=None, **kwargs -): +def generate_external_content(base_name, extra_contents_path, md_file_path, excluded=None, **kwargs): """ generate all static file that allow offline access to content :param base_name: base nae of file (without extension) :param extra_contents_path: internal directory where all files will be pushed :param md_file_path: bundled markdown file path - :param overload_settings: this option force the function to generate all registered formats even when settings \ - ask for PDF not to be published :param excluded: list of excluded format, None if no exclusion """ excluded = excluded or ["watchdog"] - if not settings.ZDS_APP["content"]["build_pdf_when_published"] and not overload_settings: - excluded.append("pdf") for publicator_name, publicator in PublicatorRegistry.get_all_registered(excluded): try: publicator.publish( diff --git a/zds/tutorialv2/tests/__init__.py b/zds/tutorialv2/tests/__init__.py index af18f67a13..132967f8a7 100644 --- a/zds/tutorialv2/tests/__init__.py +++ b/zds/tutorialv2/tests/__init__.py @@ -14,7 +14,6 @@ overridden_zds_app["content"]["repo_private_path"] = settings.BASE_DIR / "contents-private-test" overridden_zds_app["content"]["repo_public_path"] = settings.BASE_DIR / "contents-public-test" overridden_zds_app["content"]["extra_content_generation_policy"] = "SYNC" -overridden_zds_app["content"]["build_pdf_when_published"] = False class override_for_contents(override_settings): diff --git a/zds/tutorialv2/tests/tests_feeds.py b/zds/tutorialv2/tests/tests_feeds.py index d165c5d73b..aad9605710 100644 --- a/zds/tutorialv2/tests/tests_feeds.py +++ b/zds/tutorialv2/tests/tests_feeds.py @@ -30,6 +30,7 @@ overridden_zds_app = deepcopy(settings.ZDS_APP) overridden_zds_app["content"]["repo_private_path"] = settings.BASE_DIR / "contents-private-test" overridden_zds_app["content"]["repo_public_path"] = settings.BASE_DIR / "contents-public-test" +overridden_zds_app["content"]["extra_content_generation_policy"] = "NOTHING" @override_settings(MEDIA_ROOT=settings.BASE_DIR / "media-test") @@ -37,8 +38,6 @@ class LastTutorialsFeedsTest(TutorialTestMixin, TestCase): def setUp(self): self.overridden_zds_app = overridden_zds_app - # don't build PDF to speed up the tests - overridden_zds_app["content"]["build_pdf_when_published"] = False self.licence = LicenceFactory() self.subcategory = SubCategoryFactory() @@ -225,8 +224,6 @@ def test_content_control_chars(self): class LastArticlesFeedsTest(TutorialTestMixin, TestCase): def setUp(self): self.overridden_zds_app = overridden_zds_app - # don't build PDF to speed up the tests - overridden_zds_app["content"]["build_pdf_when_published"] = False self.licence = LicenceFactory() self.subcategory = SubCategoryFactory() @@ -411,8 +408,6 @@ def test_content_control_chars(self): class LastOpinionsFeedsTest(TutorialTestMixin, TestCase): def setUp(self): self.overridden_zds_app = overridden_zds_app - # don't build PDF to speed up the tests - overridden_zds_app["content"]["build_pdf_when_published"] = False self.subcategory = SubCategoryFactory() self.tag = TagFactory() diff --git a/zds/tutorialv2/tests/tests_front.py b/zds/tutorialv2/tests/tests_front.py index d3322afd39..a7e439160a 100644 --- a/zds/tutorialv2/tests/tests_front.py +++ b/zds/tutorialv2/tests/tests_front.py @@ -26,6 +26,7 @@ overridden_zds_app = deepcopy(settings.ZDS_APP) overridden_zds_app["content"]["repo_private_path"] = settings.BASE_DIR / "contents-private-test" overridden_zds_app["content"]["repo_public_path"] = settings.BASE_DIR / "contents-public-test" +overridden_zds_app["content"]["extra_content_generation_policy"] = "NOTHING" @override_settings(MEDIA_ROOT=settings.BASE_DIR / "media-test") @@ -52,8 +53,6 @@ def tearDown(self): def setUp(self): self.overridden_zds_app = overridden_zds_app - # don't build PDF to speed up the tests - overridden_zds_app["content"]["build_pdf_when_published"] = False self.staff = StaffProfileFactory().user diff --git a/zds/tutorialv2/tests/tests_utils.py b/zds/tutorialv2/tests/tests_utils.py index c3bcc62e2d..f1a5cb40dd 100644 --- a/zds/tutorialv2/tests/tests_utils.py +++ b/zds/tutorialv2/tests/tests_utils.py @@ -342,8 +342,6 @@ def test_generate_markdown(self): def test_generate_pdf(self): """ensure the behavior of the `python manage.py generate_pdf` commmand""" - self.overridden_zds_app["content"]["build_pdf_when_published"] = True # this test need PDF build, if any - tuto = PublishedContentFactory(type="TUTORIAL") # generate and publish a tutorial published = PublishedContent.objects.get(content_pk=tuto.pk) @@ -596,9 +594,6 @@ def setUp(self): self.user_author = ProfileFactory().user self.old_registry = {key: value for key, value in PublicatorRegistry.get_all_registered()} - self.old_build_pdf_when_published = self.overridden_zds_app["content"]["build_pdf_when_published"] - - self.overridden_zds_app["content"]["build_pdf_when_published"] = True def get_latex_file_path(self, published: PublishedContent): """ @@ -856,4 +851,3 @@ def check(path): def tearDown(self): super().tearDown() PublicatorRegistry.registry = self.old_registry - self.overridden_zds_app["content"]["build_pdf_when_published"] = self.old_build_pdf_when_published diff --git a/zds/tutorialv2/tests/tests_views/tests_content.py b/zds/tutorialv2/tests/tests_views/tests_content.py index 2c629e1109..35a58674f1 100644 --- a/zds/tutorialv2/tests/tests_views/tests_content.py +++ b/zds/tutorialv2/tests/tests_views/tests_content.py @@ -2732,8 +2732,6 @@ def test_publication_make_extra_contents(self): NOTE: this test will take time !""" PublicatorRegistry.registry["pdf"] = ZMarkdownRebberLatexPublicator(".pdf") PublicatorRegistry.registry["epub"] = ZMarkdownEpubPublicator() - # obviously, PDF builds have to be enabled - self.overridden_zds_app["content"]["build_pdf_when_published"] = True title = "C'est pas le plus important ici !" diff --git a/zds/tutorialv2/tests/tests_views/tests_published.py b/zds/tutorialv2/tests/tests_views/tests_published.py index 5277aa8fdd..9cf9f5689b 100644 --- a/zds/tutorialv2/tests/tests_views/tests_published.py +++ b/zds/tutorialv2/tests/tests_views/tests_published.py @@ -41,7 +41,7 @@ overridden_zds_app = deepcopy(settings.ZDS_APP) overridden_zds_app["content"]["repo_private_path"] = settings.BASE_DIR / "contents-private-test" overridden_zds_app["content"]["repo_public_path"] = settings.BASE_DIR / "contents-public-test" -overridden_zds_app["content"]["extra_content_generation_policy"] = "SYNC" +overridden_zds_app["content"]["extra_content_generation_policy"] = "NOTHING" @override_settings(MEDIA_ROOT=settings.BASE_DIR / "media-test") @@ -51,8 +51,6 @@ class PublishedContentTests(TutorialTestMixin, TestCase): def setUp(self): self.overridden_zds_app = overridden_zds_app overridden_zds_app["content"]["default_licence_pk"] = LicenceFactory().pk - # don't build PDF to speed up the tests - overridden_zds_app["content"]["build_pdf_when_published"] = False self.staff = StaffProfileFactory().user diff --git a/zds/utils/api/tests.py b/zds/utils/api/tests.py index 407d100f87..f9804a533f 100644 --- a/zds/utils/api/tests.py +++ b/zds/utils/api/tests.py @@ -1,6 +1,8 @@ +from copy import deepcopy import shutil import os from django.conf import settings +from django.test.utils import override_settings from django.urls import reverse from rest_framework import status from rest_framework.test import APITestCase @@ -12,13 +14,15 @@ from zds.tutorialv2.tests.factories import PublishableContentFactory from zds.tutorialv2.publication_utils import publish_content +overridden_zds_app = deepcopy(settings.ZDS_APP) +overridden_zds_app["content"]["extra_content_generation_policy"] = "NOTHING" + +@override_settings(ZDS_APP=overridden_zds_app) class TagListAPITest(APITestCase): def setUp(self): self.client = APIClient() caches[extensions_api_settings.DEFAULT_USE_CACHE].clear() - # don't build PDF to speed up the tests - settings.ZDS_APP["content"]["build_pdf_when_published"] = False def test_list_of_tags_empty(self): """ @@ -159,6 +163,3 @@ def tearDown(self): shutil.rmtree(settings.ZDS_APP["content"]["repo_public_path"]) if os.path.isdir(settings.MEDIA_ROOT): shutil.rmtree(settings.MEDIA_ROOT) - - # re-activate PDF build - settings.ZDS_APP["content"]["build_pdf_when_published"] = True From 1a6e95c7836c7598e0c73d31faa1b4d73d9a64d9 Mon Sep 17 00:00:00 2001 From: "Ph. SW." Date: Tue, 22 Oct 2024 21:31:06 +0200 Subject: [PATCH 2/4] Restaure les itemprop perdus avec c29c53fb7 (#6672) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - le bloc article_schema n'est redéfinit nul part, donc autant le supprimer et utiliser directement sa valeur - personne ne définit de bloc article_centent_schema ou article_content_schema (sans la typo), donc suppression également Ce commit restaure juste les attributs schema.org perdus avec c29c53fb70a5bb5e07a234891bd9d66b27d4a1f4, mais il faudrait sans doute refaire une passe complète sur ces attributs. Fix #6604 --- templates/base_content_page.html | 4 ++-- templates/tutorialv2/base_online.html | 6 ------ templates/tutorialv2/includes/headline/licence.part.html | 2 +- templates/tutorialv2/includes/headline/title.part.html | 4 ++-- 4 files changed, 5 insertions(+), 11 deletions(-) diff --git a/templates/base_content_page.html b/templates/base_content_page.html index 64815b5a51..0c68a182b2 100644 --- a/templates/base_content_page.html +++ b/templates/base_content_page.html @@ -9,12 +9,12 @@ {% block content_out %} -
+
{% block headline %}{% endblock %}
{% block content_page %} -
+
{% block content %}{% endblock %}
{% endblock %} diff --git a/templates/tutorialv2/base_online.html b/templates/tutorialv2/base_online.html index 51d4b3dffc..56f59e8f73 100644 --- a/templates/tutorialv2/base_online.html +++ b/templates/tutorialv2/base_online.html @@ -46,9 +46,3 @@ {% endblock %} - - - -{% block article_schema %} - itemscope itemtype="http://schema.org/Article" -{% endblock %} diff --git a/templates/tutorialv2/includes/headline/licence.part.html b/templates/tutorialv2/includes/headline/licence.part.html index 8426f450a5..9e49fe381e 100644 --- a/templates/tutorialv2/includes/headline/licence.part.html +++ b/templates/tutorialv2/includes/headline/licence.part.html @@ -17,5 +17,5 @@ {% crispy form %} {% elif licence %} - {{ licence }} + {{ licence }} {% endif %} diff --git a/templates/tutorialv2/includes/headline/title.part.html b/templates/tutorialv2/includes/headline/title.part.html index 8ec2bfdeac..a8074eb970 100644 --- a/templates/tutorialv2/includes/headline/title.part.html +++ b/templates/tutorialv2/includes/headline/title.part.html @@ -23,7 +23,7 @@
From c0cef18bb20ae8a7bdce165df235b2a6931e7529 Mon Sep 17 00:00:00 2001 From: "Ph. SW." Date: Wed, 23 Oct 2024 08:09:53 +0200 Subject: [PATCH 3/4] =?UTF-8?q?Ensemble=20d'am=C3=A9liorations=20sur=20la?= =?UTF-8?q?=20page=20listant=20les=20alertes=20(#6671)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Améliore la zone d'admin pour les alertes * Supprime les alertes concernant les commentaires de contenus supprimés Un billet peut être dépublié puis supprimé par son auteurice, si ce billet avait des commentaires avec des alertes, ces alertes n'étaient pas supprimées, ce qui levait une exception lorsqu'on allait sur la page des alertes. On supprime maintenant les alertes lorsque l'élément qu'elles concernent est supprimé. Problème rapporté par Sentry. * Homogénéise les scopes des alertes en base de données * Précise mieux sur la page des alertes sur quel type d'élément porte l'alerte * N'affiche pas de lien vers un commentaire signalé inaccessible sur la page des alertes S'il y avait une alerte sur un contenu dépublié, l'alerte était toujours listée sur la page des alertes, mais avec un lien vers le commentaire signalé mal formé, puisqu'il était de la forme pages/alertes/?page=1&#p123. --- templates/pages/alerts.html | 12 +++- zds/tutorialv2/tests/factories.py | 1 + .../tests/tests_views/tests_published.py | 58 +++++++++++++++++++ zds/utils/admin.py | 4 +- .../migrations/0028_alert_cascade_delete.py | 39 +++++++++++++ .../migrations/0029_normalize_alert_scopes.py | 44 ++++++++++++++ zds/utils/models.py | 31 ++++++++-- 7 files changed, 180 insertions(+), 9 deletions(-) create mode 100644 zds/utils/migrations/0028_alert_cascade_delete.py create mode 100644 zds/utils/migrations/0029_normalize_alert_scopes.py diff --git a/templates/pages/alerts.html b/templates/pages/alerts.html index bd515d3cca..0fc74ddeb8 100644 --- a/templates/pages/alerts.html +++ b/templates/pages/alerts.html @@ -47,6 +47,7 @@

{% trans "Liste des alertes en cours" %}

{% elif alert.scope == 'PROFILE' %}
{{ alert.text }} {% else %} + {# This is an alert about a comment on something (any kind of content or forum post) #} {{ alert.text }} {% endif %} @@ -94,9 +95,16 @@

{% trans "Liste des alertes récemment résolues" %}

{% elif alert.scope == 'PROFILE' %} {{ alert.text }} {% else %} + {# This is an alert about a comment on something (any kind of content or forum post) #} + {% url "member-detail" alert.comment.author.username as url_member_detail %} - {{ alert.text }} par - {{ alert.comment.author.username }} + + {% if alert.is_on_comment_on_unpublished_content %} + {{ alert.text }} + {% else %} + {{ alert.text }} + {% endif %} + par {{ alert.comment.author.username }} {% endif %} diff --git a/zds/tutorialv2/tests/factories.py b/zds/tutorialv2/tests/factories.py index 294dfbe58c..7eba05b258 100644 --- a/zds/tutorialv2/tests/factories.py +++ b/zds/tutorialv2/tests/factories.py @@ -195,6 +195,7 @@ class Meta: ip_address = "192.168.3.1" text = "Bonjour, je me présente, je m'appelle l'homme au texte bidonné" + position = 1 @classmethod def _generate(cls, create, attrs): diff --git a/zds/tutorialv2/tests/tests_views/tests_published.py b/zds/tutorialv2/tests/tests_views/tests_published.py index 9cf9f5689b..3ab70abe64 100644 --- a/zds/tutorialv2/tests/tests_views/tests_published.py +++ b/zds/tutorialv2/tests/tests_views/tests_published.py @@ -15,6 +15,7 @@ from zds.mp.models import PrivateTopic, is_privatetopic_unread from zds.notification.models import ContentReactionAnswerSubscription, Notification from zds.tutorialv2.tests.factories import ( + ContentReactionFactory, PublishableContentFactory, ContainerFactory, ExtractFactory, @@ -2088,3 +2089,60 @@ def test_save_no_redirect(self): result = loads(resp.content.decode("utf-8")) self.assertEqual("ok", result.get("result", None)) self.assertEqual(extract.compute_hash(), result.get("last_hash", None)) + + def test_remove_unpublished_opinion_with_alerted_comments(self): + """Test the page showing alerts with an alerted comment on a removed opinion""" + + alert_page_url = reverse("pages-alerts") + + # 1. Publish opinion + opinion = PublishedContentFactory(type="OPINION", author_list=[self.user_author]) + + # 2. Comment the opinion + random_user = ProfileFactory().user + comment = ContentReactionFactory(related_content=opinion, author=random_user) + + # 3. Create an alert for the comment + self.client.force_login(self.user_staff) + result = self.client.post( + reverse("content:alert-reaction", args=[comment.pk]), + {"signal_text": "No. Try not. Do... or do not. There is no try."}, + follow=False, + ) + self.assertEqual(result.status_code, 302) + + # 4. Display the page listing alerts + resp = self.client.get(alert_page_url) + self.assertEqual(200, resp.status_code) + self.assertContains(resp, comment.get_absolute_url()) # We have a link to the alerted comment + self.assertEqual(len(resp.context["alerts"]), 1) + self.assertEqual(len(resp.context["solved"]), 0) + + # 5. Unpublish the opinion + result = self.client.post( + reverse("validation:ignore-opinion", kwargs={"pk": opinion.pk, "slug": opinion.slug}), + { + "operation": "REMOVE_PUB", + }, + follow=False, + ) + self.assertEqual(result.status_code, 200) + + # 6. Display the page listing alerts + resp = self.client.get(alert_page_url) + self.assertEqual(200, resp.status_code) + self.assertNotContains(resp, 'href="?page=1#p') # We don't have wrong links + self.assertEqual(len(resp.context["alerts"]), 0) + self.assertEqual(len(resp.context["solved"]), 1) + + # 7. Remove the opinion + self.client.force_login(self.user_author) + result = self.client.post(reverse("content:delete", args=[opinion.pk, opinion.slug]), follow=False) + self.assertEqual(result.status_code, 302) + + # 8. Display the page listing alerts + self.client.force_login(self.user_staff) + resp = self.client.get(alert_page_url) + self.assertEqual(200, resp.status_code) + self.assertEqual(len(resp.context["alerts"]), 0) + self.assertEqual(len(resp.context["solved"]), 0) diff --git a/zds/utils/admin.py b/zds/utils/admin.py index fd6618577d..55b7cf3266 100644 --- a/zds/utils/admin.py +++ b/zds/utils/admin.py @@ -25,9 +25,9 @@ def parent_category(self, obj): class AlertAdmin(admin.ModelAdmin): - list_display = ("author", "text", "solved") + list_display = ("author", "scope", "text", "pubdate", "solved", "solved_date") list_filter = ("scope", "solved") - raw_id_fields = ("author", "comment", "moderator", "privatetopic") + raw_id_fields = ("author", "comment", "moderator", "privatetopic", "profile", "content") ordering = ("-pubdate",) search_fields = ("author__username", "text") diff --git a/zds/utils/migrations/0028_alert_cascade_delete.py b/zds/utils/migrations/0028_alert_cascade_delete.py new file mode 100644 index 0000000000..396afac87d --- /dev/null +++ b/zds/utils/migrations/0028_alert_cascade_delete.py @@ -0,0 +1,39 @@ +# Generated by Django 4.2.16 on 2024-10-20 16:28 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ("tutorialv2", "0041_remove_must_reindex"), + ("utils", "0027_remove_update_index_date"), + ] + + operations = [ + migrations.AlterField( + model_name="alert", + name="comment", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="alerts_on_this_comment", + to="utils.comment", + verbose_name="Commentaire", + ), + ), + migrations.AlterField( + model_name="alert", + name="content", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="alerts_on_this_content", + to="tutorialv2.publishablecontent", + verbose_name="Contenu", + ), + ), + ] diff --git a/zds/utils/migrations/0029_normalize_alert_scopes.py b/zds/utils/migrations/0029_normalize_alert_scopes.py new file mode 100644 index 0000000000..315d29906a --- /dev/null +++ b/zds/utils/migrations/0029_normalize_alert_scopes.py @@ -0,0 +1,44 @@ +# Generated by Django 4.2.16 on 2024-10-19 22:55 + +""" +In production, the column `scope` of the table containg the alerts contains +leftovers from older alert management: + +SELECT BINARY scope, COUNT(*) AS nb, MIN(pubdate) AS first_pubdate, MAX(pubdate) AS last_pubdate FROM utils_alert WHERE solved=1 GROUP BY BINARY scope; ++--------------+------+---------------------+---------------------+ +| BINARY scope | nb | first_pubdate | last_pubdate | ++--------------+------+---------------------+---------------------+ +| ARTICLE | 113 | 2017-05-15 11:03:23 | 2024-09-04 10:09:20 | +| Article | 5 | 2017-01-24 21:34:56 | 2017-04-20 15:56:43 | +| CONTENT | 115 | 2017-05-04 12:28:11 | 2024-08-08 08:46:31 | +| FORUM | 3756 | 2016-12-13 19:03:00 | 2024-09-15 22:37:04 | +| OPINION | 202 | 2017-05-21 14:28:24 | 2024-09-04 15:20:13 | +| PROFILE | 1088 | 2019-09-18 22:16:55 | 2024-09-16 17:39:55 | +| TUTORIAL | 392 | 2017-05-21 21:48:11 | 2024-09-12 20:07:01 | +| Tutoriel | 7 | 2016-12-21 22:56:29 | 2017-04-26 12:21:32 | ++--------------+------+---------------------+---------------------+ + +This migration normalizes the scope values of all alerts. +""" + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("utils", "0028_alert_cascade_delete"), + ] + + operations = [ + # These WHERE are actually case *in*sensitive, but it will not change + # the result (just modify more records which don't need it), but + # having a WHERE which is case-sensitive *and* compatible with both + # SQLite and MariaDB seems tricky... + migrations.RunSQL( + ("UPDATE utils_alert SET scope = 'ARTICLE' WHERE scope = 'Article';"), + ), + migrations.RunSQL( + ("UPDATE utils_alert SET scope = 'TUTORIAL' WHERE scope = 'Tutoriel';"), + ), + ] diff --git a/zds/utils/models.py b/zds/utils/models.py index 9a6337fbf2..307e0254c3 100644 --- a/zds/utils/models.py +++ b/zds/utils/models.py @@ -617,7 +617,14 @@ def __str__(self): class Alert(models.Model): - """Alerts on all kinds of Comments and PublishedContents.""" + """Alerts on Profiles, PublishedContents and all kinds of Comments. + + The scope field indicates on which type of element the alert is made: + - PROFILE: the profile of a member + - FORUM: a post on a topic in a forum + - CONTENT: the content (article, opinion or tutorial) itself + - elements of TYPE_CHOICES (ARTICLE, OPINION, TUTORIAL): a comment on a content of this type + """ SCOPE_CHOICES = [ ("PROFILE", _("Profil")), @@ -637,7 +644,7 @@ class Alert(models.Model): db_index=True, null=True, blank=True, - on_delete=models.SET_NULL, + on_delete=models.CASCADE, ) # use of string definition of pk to avoid circular import. profile = models.ForeignKey( @@ -656,7 +663,7 @@ class Alert(models.Model): db_index=True, null=True, blank=True, - on_delete=models.SET_NULL, + on_delete=models.CASCADE, ) scope = models.CharField(max_length=10, choices=SCOPE_CHOICES, db_index=True) text = models.TextField("Texte d'alerte") @@ -681,9 +688,23 @@ class Alert(models.Model): def get_type(self): if self.scope in TYPE_CHOICES_DICT: - return _("Commentaire") + assert self.comment is not None + if self.is_on_comment_on_unpublished_content(): + return _(f"Commentaire sur un {self.SCOPE_CHOICES_DICT[self.scope].lower()} dépublié") + else: + return _(f"Commentaire sur un {self.SCOPE_CHOICES_DICT[self.scope].lower()}") + elif self.scope == "FORUM": + assert self.comment is not None + return _("Message de forum") + elif self.scope == "PROFILE": + assert self.profile is not None + return _("Profil") else: - return self.get_scope_display() + assert self.content is not None + return self.SCOPE_CHOICES_DICT[self.content.type] + + def is_on_comment_on_unpublished_content(self): + return self.scope in TYPE_CHOICES_DICT and not self.get_comment_subclass().related_content.in_public() def is_automated(self): """Returns true if this alert was opened automatically.""" From 34e2307fce4ce6de7982f4adee0ab5b95acb2d13 Mon Sep 17 00:00:00 2001 From: Philippe MILINK Date: Sun, 27 Oct 2024 15:47:23 +0100 Subject: [PATCH 4/4] =?UTF-8?q?G=C3=A8le=20la=20version=20de=20pip?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reste à 24.2 tant que https://github.com/pypa/pip/issues/13046 n'est pas corrigé. --- .github/workflows/ci.yml | 6 +++--- scripts/define_variable.sh | 4 ++++ scripts/install_zds.sh | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 91951fd6d0..f4f1509200 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,6 +9,7 @@ on: env: NODE_VERSION: "18" # needs to be also updated in .nvmrc PYTHON_VERSION: "3.11" + PIP_VERSION: "24.2" # stick to it while https://github.com/pypa/pip/issues/13046 is not fixed, needs to be also updated in scripts/define_variable.sh MARIADB_VERSION: "10.4.10" COVERALLS_VERSION: "3.3.1" # check if Coverage needs to be also updated in requirements-ci.txt TYPESENSE_VERSION: "27.0" # needs to be also updated in scripts/define_variable.sh @@ -59,7 +60,7 @@ jobs: python-version: "${{ env.PYTHON_VERSION }}" - name: Upgrade pip - run: pip install --upgrade pip + run: pip install pip==${{ env.PIP_VERSION }} - name: Retrieve pip cache directory id: pip-cache @@ -188,8 +189,7 @@ jobs: python-version: "${{ env.PYTHON_VERSION }}" - name: Upgrade pip - run: | - pip install --upgrade pip + run: pip install pip==${{ env.PIP_VERSION }} - name: Retrieve pip cache directory id: pip-cache diff --git a/scripts/define_variable.sh b/scripts/define_variable.sh index 6286b37c35..861cc1e4ee 100644 --- a/scripts/define_variable.sh +++ b/scripts/define_variable.sh @@ -8,6 +8,10 @@ if [[ $ZDS_VENV_VERSION == "" ]]; then ZDS_VENV_VERSION="20.24.5" fi +if [[ $ZDS_PIP_VERSION == "" ]]; then + ZDS_PIP_VERSION="24.2" # stick to it while https://github.com/pypa/pip/issues/13046 is not fixed, needs to be also updated in .github/workflows/ci.yml +fi + ZDS_NODE_VERSION=$(cat $ZDSSITE_DIR/.nvmrc) if [[ $ZDS_NVM_VERSION == "" ]]; then diff --git a/scripts/install_zds.sh b/scripts/install_zds.sh index a778ff8e18..703fa86343 100755 --- a/scripts/install_zds.sh +++ b/scripts/install_zds.sh @@ -225,7 +225,7 @@ if ! $(_in "--force-skip-activating" $@) && [[ ( $VIRTUAL_ENV == "" || $(realpat # Some dependencies (like rust ones) require a recent pip: print_info "* upgrading pip" - pip install --upgrade pip; exVal=$? + pip install pip==$ZDS_PIP_VERSION; exVal=$? if [[ $exVal != 0 ]]; then print_error "!! Failed to upgrade pip"