diff --git a/blog/migrations/0030_alter_category_locale.py b/blog/migrations/0030_alter_category_locale.py
new file mode 100644
index 00000000..ad5693a1
--- /dev/null
+++ b/blog/migrations/0030_alter_category_locale.py
@@ -0,0 +1,25 @@
+# Generated by Django 5.0.8 on 2024-08-23 13:17
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ("blog", "0029_alter_blogentrypage_body_alter_blogindexpage_body_and_more"),
+ ("wagtailcore", "0094_alter_page_locale"),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name="category",
+ name="locale",
+ field=models.ForeignKey(
+ editable=False,
+ on_delete=django.db.models.deletion.PROTECT,
+ related_name="+",
+ to="wagtailcore.locale",
+ verbose_name="locale",
+ ),
+ ),
+ ]
diff --git a/content_manager/locale/fr/LC_MESSAGES/django.mo b/content_manager/locale/fr/LC_MESSAGES/django.mo
index d6a6c51a..d60706a8 100644
Binary files a/content_manager/locale/fr/LC_MESSAGES/django.mo and b/content_manager/locale/fr/LC_MESSAGES/django.mo differ
diff --git a/content_manager/locale/fr/LC_MESSAGES/django.po b/content_manager/locale/fr/LC_MESSAGES/django.po
index 48ae5101..e1a0cf17 100644
--- a/content_manager/locale/fr/LC_MESSAGES/django.po
+++ b/content_manager/locale/fr/LC_MESSAGES/django.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-07-24 17:14+0200\n"
-"PO-Revision-Date: 2024-07-24 17:14+0200\n"
+"POT-Creation-Date: 2024-08-23 16:16+0200\n"
+"PO-Revision-Date: 2024-08-23 16:17+0200\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: fr\n"
@@ -201,7 +201,7 @@ msgstr "Badge"
#: content_manager/blocks.py:615 content_manager/blocks.py:624
#: content_manager/blocks.py:666 content_manager/blocks.py:780
#: content_manager/blocks.py:810 content_manager/blocks.py:910
-#: content_manager/models.py:276
+#: content_manager/models.py:323
msgid "Title"
msgstr "Titre"
@@ -849,27 +849,27 @@ msgstr "Icône du côté droit"
msgid "Icon on the left side"
msgstr "Icône du côté gauche"
-#: content_manager/models.py:25
+#: content_manager/models.py:26
msgid "Content page"
msgstr "Page de contenu"
-#: content_manager/models.py:42
+#: content_manager/models.py:43
msgid "Tag"
msgstr "Étiquette"
-#: content_manager/models.py:94
+#: content_manager/models.py:95
msgid "Site configuration"
msgstr "Configuration du site"
-#: content_manager/models.py:95
+#: content_manager/models.py:96
msgid "Site configurations"
msgstr "Configurations du site"
-#: content_manager/models.py:98
+#: content_manager/models.py:99
msgid "Institution (header)"
msgstr "Institution (en-tête)"
-#: content_manager/models.py:101
+#: content_manager/models.py:102
msgid ""
"Institution brand as defined on page https://www.info.gouv.fr/marque-de-"
"letat/le-bloc-marque"
@@ -877,69 +877,101 @@ msgstr ""
"Nom de l’institution tel que défini sur la page https://www.info.gouv.fr/"
"marque-de-letat/le-bloc-marque"
-#: content_manager/models.py:105
+#: content_manager/models.py:106
msgid "Institution with line break (header)"
msgstr "Institution avec césure (en-tête)"
-#: content_manager/models.py:109
+#: content_manager/models.py:110
msgid "Institution brand with
tags for line breaks"
msgstr "Nom de l’institution avec des
pour les retours à la ligne"
-#: content_manager/models.py:112
+#: content_manager/models.py:113
msgid "Institution (footer)"
msgstr "Institution (pied)"
-#: content_manager/models.py:119
+#: content_manager/models.py:120
msgid "Institution with line break (footer)"
msgstr "Institution avec césure (pied)"
-#: content_manager/models.py:126 content_manager/models.py:128
+#: content_manager/models.py:127 content_manager/models.py:129
msgid "Site title"
msgstr "Titre du site"
-#: content_manager/models.py:132 content_manager/models.py:134
+#: content_manager/models.py:133 content_manager/models.py:135
msgid "Site tagline"
msgstr "Sous-titre du site"
-#: content_manager/models.py:139
-msgid "Important notice"
-msgstr "Bandeau d’information importante"
+#: content_manager/models.py:140
+msgid "Notice title"
+msgstr "Titre du bandeau"
-#: content_manager/models.py:144
+#: content_manager/models.py:144 content_manager/models.py:151
+msgid "Can include HTML"
+msgstr "Peut inclure du HTML"
+
+#: content_manager/models.py:148
+msgid "Notice description"
+msgstr "Description du bandeau"
+
+#: content_manager/models.py:154
+msgid "Notice type"
+msgstr "Type de bandeau"
+
+#: content_manager/models.py:160
msgid ""
-"The important notice banner should only be used for essential and temporary "
-"information. (Excessive or continuous use risks “drowning” the "
-"message.)"
+"Use is strictly regulated, see documentation."
msgstr ""
-"Le bandeau d’information importante doit être utilisé uniquement pour une "
-"information primordiale et temporaire. (Une utilisation excessive ou "
-"continue risque de “noyer” le message)"
+"L’usage de ce bandeau est strictement encadré, voir la documentation."
+
+#: content_manager/models.py:166
+msgid "Notice link"
+msgstr "Lien du bandeau"
+
+#: content_manager/models.py:169
+msgid "Standardized consultation link at the end of the notice."
+msgstr "Lien de consultation standardisé à la fin du bandeau."
+
+#: content_manager/models.py:173
+msgid "Notice icon class"
+msgstr "Classe d’icône du bandeau"
+
+#: content_manager/models.py:177
+msgid "For weather alerts only"
+msgstr "Pour les bandeaux de vigilance météo uniquement"
+
+#: content_manager/models.py:180
+msgid "Collapsible?"
+msgstr "Refermable ?"
-#: content_manager/models.py:149
+#: content_manager/models.py:182
msgid "Show the BETA tag next to the title"
msgstr "Afficher la mention BETA à côté du titre"
-#: content_manager/models.py:152 content_manager/models.py:312
+#: content_manager/models.py:185 content_manager/models.py:359
msgid "Description"
msgstr "Description"
-#: content_manager/models.py:165 content_manager/models.py:209
+#: content_manager/models.py:198 content_manager/models.py:256
msgid "Operator logo"
msgstr "Logo opérateur"
-#: content_manager/models.py:169
+#: content_manager/models.py:202
msgid "Logo alt text"
msgstr "Alternative textuelle du logo"
-#: content_manager/models.py:172
+#: content_manager/models.py:205
msgid "Must contain the text present in the image."
msgstr "Doit impérativement contenir le texte présent dans l’image."
-#: content_manager/models.py:175
+#: content_manager/models.py:208
msgid "Width (em)"
msgstr "Largeur (em)"
-#: content_manager/models.py:181
+#: content_manager/models.py:214
msgid ""
"To be adjusted according to the width of the logo. Example for a "
"vertical logo: 3.5, Example for a horizontal logo: 8."
@@ -947,87 +979,101 @@ msgstr ""
"À ajuster en fonction de la largeur du logo. Exemple pour un logo vertical: "
"3.5, Exemple pour un logo horizontal: 8."
-#: content_manager/models.py:190
+#: content_manager/models.py:223
msgid "Newsletter description"
msgstr "Description de la lettre d’information"
-#: content_manager/models.py:193
+#: content_manager/models.py:226
msgid "Newsletter registration URL"
msgstr "URL d‘inscription à la lettre d’information"
-#: content_manager/models.py:218
+#: content_manager/models.py:244
+msgid "Important notice"
+msgstr "Bandeau d’information importante"
+
+#: content_manager/models.py:246
+msgid ""
+"The important notice banner should only be used for essential and temporary "
+"information. (Excessive or continuous use risks “drowning” "
+"the message.)"
+msgstr ""
+"Le bandeau d’information importante doit être utilisé uniquement pour une "
+"information primordiale et temporaire. (Une utilisation excessive ou "
+"continue risque de “noyer” le message)"
+
+#: content_manager/models.py:265
msgid "Advanced settings"
msgstr "Paramètres avancés"
-#: content_manager/models.py:228
+#: content_manager/models.py:275
msgid "Header"
msgstr "En-tête"
-#: content_manager/models.py:235
+#: content_manager/models.py:282
msgid "Footer"
msgstr "Pied de page"
-#: content_manager/models.py:245
+#: content_manager/models.py:292
msgid "Newsletter"
msgstr "Lettre d’information"
-#: content_manager/models.py:247 content_manager/models.py:293
+#: content_manager/models.py:294 content_manager/models.py:340
msgid "Social media items"
msgstr "Liens de réseaux sociaux"
-#: content_manager/models.py:251
+#: content_manager/models.py:298
msgid "Generic"
msgstr "Génériques"
-#: content_manager/models.py:252
+#: content_manager/models.py:299
msgid "Brand block"
msgstr "Bloc-marque"
-#: content_manager/models.py:253
+#: content_manager/models.py:300
msgid "Newsletter and social media"
msgstr "Lettre d’information et réseaux sociaux"
-#: content_manager/models.py:279
+#: content_manager/models.py:326
msgid "URL"
msgstr "URL"
-#: content_manager/models.py:283
+#: content_manager/models.py:330
msgid "Icon class"
msgstr "Classe d’icône"
-#: content_manager/models.py:292
+#: content_manager/models.py:339
msgid "Social media item"
msgstr "Lien de réseau social"
-#: content_manager/models.py:299
+#: content_manager/models.py:346
msgid "Category"
msgstr "Catégorie"
-#: content_manager/models.py:302
+#: content_manager/models.py:349
msgid "Mega menu category"
msgstr "Catégorie de méga menu"
-#: content_manager/models.py:303
+#: content_manager/models.py:350
msgid "Mega menu categories"
msgstr "Catégories de méga menu"
-#: content_manager/models.py:308
+#: content_manager/models.py:355
msgid "Name"
msgstr "Nom"
-#: content_manager/models.py:313
+#: content_manager/models.py:360
msgid "Main link"
msgstr "Lien principal"
-#: content_manager/models.py:323
+#: content_manager/models.py:370
msgid "Categories"
msgstr "Catégories"
-#: content_manager/models.py:324
+#: content_manager/models.py:371
msgid "Maximum 4 categories, each with maximum 8 links."
msgstr "Maximum 4 catégories, chacune contenant maximum 8 liens."
-#: content_manager/models.py:335
+#: content_manager/models.py:382
msgid "Mega menu"
msgstr "Méga menu"
@@ -1097,9 +1143,6 @@ msgstr "Liste de pages avec l’étiquette {tag}"
#~ msgid "The link appears as a button under the text block"
#~ msgstr "Le lien apparaît comme un bouton sous le bloc de texte"
-#~ msgid "Can contain HTML."
-#~ msgstr "Peut contenir du HTML."
-
#~ msgid "Callout title"
#~ msgstr "Titre de l’appel à action"
diff --git a/content_manager/migrations/0039_rename_notice_cmsdsfrconfig_notice_title.py b/content_manager/migrations/0039_rename_notice_cmsdsfrconfig_notice_title.py
new file mode 100644
index 00000000..26bae0be
--- /dev/null
+++ b/content_manager/migrations/0039_rename_notice_cmsdsfrconfig_notice_title.py
@@ -0,0 +1,17 @@
+# Generated by Django 5.0.8 on 2024-08-23 13:18
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ("content_manager", "0038_alter_contentpage_body"),
+ ]
+
+ operations = [
+ migrations.RenameField(
+ model_name="cmsdsfrconfig",
+ old_name="notice",
+ new_name="notice_title",
+ ),
+ ]
diff --git a/content_manager/migrations/0040_cmsdsfrconfig_notice_description_and_more.py b/content_manager/migrations/0040_cmsdsfrconfig_notice_description_and_more.py
new file mode 100644
index 00000000..ee208413
--- /dev/null
+++ b/content_manager/migrations/0040_cmsdsfrconfig_notice_description_and_more.py
@@ -0,0 +1,83 @@
+# Generated by Django 5.0.8 on 2024-08-23 13:26
+
+import wagtail.fields
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ("content_manager", "0039_rename_notice_cmsdsfrconfig_notice_title"),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name="cmsdsfrconfig",
+ name="notice_description",
+ field=wagtail.fields.RichTextField(
+ blank=True, default="", help_text="Can include HTML", verbose_name="Notice description"
+ ),
+ ),
+ migrations.AddField(
+ model_name="cmsdsfrconfig",
+ name="notice_icon_class",
+ field=models.CharField(
+ blank=True,
+ default="",
+ help_text="For weather alerts only",
+ max_length=200,
+ verbose_name="Notice icon class",
+ ),
+ ),
+ migrations.AddField(
+ model_name="cmsdsfrconfig",
+ name="notice_is_collapsible",
+ field=models.BooleanField(default=False, verbose_name="Collapsible?"),
+ ),
+ migrations.AddField(
+ model_name="cmsdsfrconfig",
+ name="notice_link",
+ field=models.URLField(
+ blank=True,
+ default="",
+ help_text="Standardized consultation link at the end of the notice.",
+ verbose_name="Notice link",
+ ),
+ ),
+ migrations.AddField(
+ model_name="cmsdsfrconfig",
+ name="notice_type",
+ field=models.CharField(
+ blank=True,
+ choices=[
+ ("Generic notices", [("info", "Information"), ("warning", "Warning"), ("alert", "Alert")]),
+ (
+ "Weather alert notices",
+ [
+ ("weather-orange", "Orange weather alert"),
+ ("weather-red", "Red weather alert"),
+ ("weather-purple", "Purple weather alert"),
+ ],
+ ),
+ (
+ "Alert notices",
+ [
+ ("attack", "Attack alert"),
+ ("witness", "Call for witnesses"),
+ ("cyberattack", "Cyberattack"),
+ ],
+ ),
+ ],
+ default="info",
+ help_text='Use is strictly regulated, see documentation.',
+ max_length=20,
+ verbose_name="Notice type",
+ ),
+ ),
+ migrations.AlterField(
+ model_name="cmsdsfrconfig",
+ name="notice_title",
+ field=wagtail.fields.RichTextField(
+ blank=True, default="", help_text="Can include HTML", verbose_name="Notice title"
+ ),
+ ),
+ ]
diff --git a/content_manager/models.py b/content_manager/models.py
index d0af8b50..71ea3de7 100644
--- a/content_manager/models.py
+++ b/content_manager/models.py
@@ -1,6 +1,7 @@
from django.db import models
from django.forms.widgets import Textarea
from django.utils.translation import gettext_lazy as _
+from dsfr.constants import NOTICE_TYPE_CHOICES
from modelcluster.fields import ParentalKey
from modelcluster.models import ClusterableModel
from modelcluster.tags import ClusterTaggableManager
@@ -135,17 +136,49 @@ class Meta:
blank=True,
)
- notice = RichTextField(
- _("Important notice"),
+ notice_title = RichTextField(
+ _("Notice title"),
default="",
blank=True,
features=LIMITED_RICHTEXTFIELD_FEATURES,
+ help_text=_("Can include HTML"),
+ )
+
+ notice_description = RichTextField(
+ _("Notice description"),
+ default="",
+ blank=True,
+ help_text=_("Can include HTML"),
+ )
+ notice_type = models.CharField(
+ _("Notice type"),
+ choices=NOTICE_TYPE_CHOICES,
+ default="info",
+ blank=True,
+ max_length=20,
help_text=_(
- "The important notice banner should only be used for essential and temporary information. \
- (Excessive or continuous use risks “drowning” the message.)"
+ 'Use is strictly regulated, see \
+ documentation.'
),
)
+ notice_link = models.URLField(
+ _("Notice link"),
+ default="",
+ blank=True,
+ help_text=_("Standardized consultation link at the end of the notice."),
+ )
+
+ notice_icon_class = models.CharField(
+ _("Notice icon class"),
+ max_length=200,
+ default="",
+ blank=True,
+ help_text=_("For weather alerts only"),
+ )
+
+ notice_is_collapsible = models.BooleanField(_("Collapsible?"), default=False) # type: ignore
+
beta_tag = models.BooleanField(_("Show the BETA tag next to the title"), default=False)
footer_description = RichTextField(
@@ -199,7 +232,21 @@ class Meta:
FieldPanel("site_title"),
FieldPanel("site_tagline"),
FieldPanel("footer_description"),
- FieldPanel("notice"),
+ MultiFieldPanel(
+ [
+ FieldPanel("notice_title"),
+ FieldPanel("notice_description"),
+ FieldPanel("notice_type"),
+ FieldPanel("notice_link"),
+ FieldPanel("notice_icon_class", widget=DsfrIconPickerWidget),
+ FieldPanel("notice_is_collapsible"),
+ ],
+ heading=_("Important notice"),
+ help_text=_(
+ "The important notice banner should only be used for essential and temporary information. \
+ (Excessive or continuous use risks “drowning” the message.)"
+ ),
+ ),
MultiFieldPanel(
[
FieldPanel("operator_logo_file"),
diff --git a/content_manager/tests/test_views.py b/content_manager/tests/test_views.py
index 09f74e2d..10889185 100644
--- a/content_manager/tests/test_views.py
+++ b/content_manager/tests/test_views.py
@@ -118,7 +118,7 @@ def test_notice_is_not_set_by_default(self):
)
def test_notice_can_be_set(self):
- self.config.notice = "Ceci est une information importante et temporaire."
+ self.config.notice_title = "Ceci est une information importante et temporaire."
self.config.save()
url = self.content_page.url
diff --git a/locale/fr/LC_MESSAGES/django.mo b/locale/fr/LC_MESSAGES/django.mo
index 988f808b..7e164e54 100644
Binary files a/locale/fr/LC_MESSAGES/django.mo and b/locale/fr/LC_MESSAGES/django.mo differ
diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po
index 07ca917a..f06dfd37 100644
--- a/locale/fr/LC_MESSAGES/django.po
+++ b/locale/fr/LC_MESSAGES/django.po
@@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-08-20 11:23+0200\n"
-"PO-Revision-Date: 2024-08-20 11:25+0200\n"
+"POT-Creation-Date: 2024-08-23 16:16+0200\n"
+"PO-Revision-Date: 2024-08-23 16:17+0200\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: fr\n"
@@ -45,7 +45,7 @@ msgstr "Retourner à l’accueil"
msgid "Display settings"
msgstr "Paramètres d’affichage"
-#: templates/blocks/footer.html:56
+#: templates/blocks/footer.html:56 templates/blocks/notice.html:4
msgid "Opens a new window"
msgstr "Ouvre une nouvelle fenêtre"
@@ -72,3 +72,11 @@ msgstr "Menu"
#: templates/blocks/header.html:106
msgid "Main menu"
msgstr "Menu principal"
+
+#: templates/blocks/notice.html:2
+msgid "Hide message"
+msgstr "Masquer le message"
+
+#: templates/blocks/notice.html:3
+msgid "Consultation link"
+msgstr "Lien de consultation"
diff --git a/static/css/style.css b/static/css/style.css
index b488637c..9c234e6d 100644
--- a/static/css/style.css
+++ b/static/css/style.css
@@ -1 +1 @@
-.cmsfr-hero{background-size:cover;background-position:center;background-repeat:no-repeat}.cmsfr-hero-large{display:flex;justify-content:center;align-items:center;text-align:center}.cmsfr-background-dark h1,.cmsfr-background-dark p,.cmsfr-background-dark ul{color:white}:root[data-fr-theme=light] .cmsfr-background-dark .fr-btn--secondary{background-color:rgba(255,255,255,0.3)}.fr-header__service-title em{font-weight:lighter}.cmsfr-author_card__header{flex:0 0 6rem !important;width:6rem !important}.cmsfr-author-img{border-radius:50%;height:4.5rem !important;margin:1.5rem;width:4.5rem}.cmsfr-footer__bottom-extra{border-left:1px solid var(--border-default-grey);padding-left:1em;margin-left:1em}
+.cmsfr-hero{background-size:cover;background-position:center;background-repeat:no-repeat}.cmsfr-hero-large{display:flex;justify-content:center;align-items:center;text-align:center}.cmsfr-background-dark h1,.cmsfr-background-dark p,.cmsfr-background-dark ul{color:white}:root[data-fr-theme=light] .cmsfr-background-dark .fr-btn--secondary{background-color:rgba(255,255,255,0.3)}.fr-header__service-title em{font-weight:lighter}.cmsfr-author_card__header{flex:0 0 6rem !important;width:6rem !important}.cmsfr-author-img{border-radius:50%;height:4.5rem !important;margin:1.5rem;width:4.5rem}.cmsfr-footer__bottom-extra{border-left:1px solid var(--border-default-grey);padding-left:1em;margin-left:1em}.cmsfr-display__inline{display:inline}
diff --git a/static/css/style.sass b/static/css/style.sass
index e60b5f24..9b937d4d 100644
--- a/static/css/style.sass
+++ b/static/css/style.sass
@@ -36,3 +36,6 @@
border-left: 1px solid var(--border-default-grey)
padding-left: 1em
margin-left: 1em
+
+.cmsfr-display__inline
+ display: inline
diff --git a/templates/base.html b/templates/base.html
index 29d31fb4..1cafd78c 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -1,81 +1,82 @@
{% load i18n static dsfr_tags wagtailuserbar wagtailsettings_tags sass_tags %}
{% get_settings %}
-
-
-