From 62fe4babc43ce3fc06f65e24796daa87f61a14e8 Mon Sep 17 00:00:00 2001 From: Sylvain Boissel Date: Fri, 23 Aug 2024 10:17:24 +0200 Subject: [PATCH] Permet de configurer toutes les options du bandeau d'information importante dans l'admin (#166) * Add full notice configuration options in the admin * Fix translations --- config/settings.py | 2 + dsfr/admin.py | 26 ++- dsfr/constants.py | 28 +++ dsfr/locale/fr/LC_MESSAGES/django.mo | Bin 6956 -> 8716 bytes dsfr/locale/fr/LC_MESSAGES/django.po | 190 ++++++++++++++---- ...fig_notice_type_alter_dsfrconfig_notice.py | 44 ++++ ..._class_alter_dsfrconfig_notice_and_more.py | 71 +++++++ ...1_rename_notice_dsfrconfig_notice_title.py | 18 ++ ..._dsfrconfig_notice_description_and_more.py | 86 ++++++++ dsfr/models.py | 46 ++++- dsfr/templates/dsfr/base.html | 4 +- dsfr/templatetags/dsfr_tags.py | 2 +- pyproject.toml | 2 +- 13 files changed, 461 insertions(+), 58 deletions(-) create mode 100644 dsfr/migrations/0009_dsfrconfig_notice_type_alter_dsfrconfig_notice.py create mode 100644 dsfr/migrations/0010_dsfrconfig_notice_icon_class_alter_dsfrconfig_notice_and_more.py create mode 100644 dsfr/migrations/0011_rename_notice_dsfrconfig_notice_title.py create mode 100644 dsfr/migrations/0012_dsfrconfig_notice_description_and_more.py diff --git a/config/settings.py b/config/settings.py index ccc1f175d..e4a7666da 100644 --- a/config/settings.py +++ b/config/settings.py @@ -131,6 +131,8 @@ TIME_ZONE = "UTC" +USE_L10N = True + USE_I18N = True USE_TZ = True diff --git a/dsfr/admin.py b/dsfr/admin.py index 07e827915..36942f667 100644 --- a/dsfr/admin.py +++ b/dsfr/admin.py @@ -15,18 +15,34 @@ class DsfrConfigAdmin(admin.ModelAdmin): fieldsets = ( ("", {"fields": ("language",)}), ( - "Site", + _("Website"), { "fields": ( ("site_title", "beta_tag"), "site_tagline", - "notice", "mourning", ) }, ), ( - "En-tête", + _("Notice"), + { + "fields": ( + "notice_title", + "notice_description", + "notice_type", + "notice_link", + "notice_icon_class", + "notice_is_collapsible", + ), + "description": _( + "The important notice banner should only be used for essential and temporary information. \ + (Excessive or continuous use risks “drowning” the message.)" + ), + }, + ), + ( + _("Header"), { "fields": ( "header_brand", @@ -35,7 +51,7 @@ class DsfrConfigAdmin(admin.ModelAdmin): }, ), ( - "Pied de page", + _("Footer"), { "fields": ( "footer_brand", @@ -46,7 +62,7 @@ class DsfrConfigAdmin(admin.ModelAdmin): }, ), ( - "Logo opérateur", + _("Operator logo"), { "fields": ( "operator_logo_file", diff --git a/dsfr/constants.py b/dsfr/constants.py index 378db3f06..d550ccf89 100644 --- a/dsfr/constants.py +++ b/dsfr/constants.py @@ -57,6 +57,34 @@ (_("Illustration colors"), COLOR_CHOICES_ILLUSTRATION), ] +# Types allowed for the site Notice +NOTICE_TYPE_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")), + ], + ), +] + # Ratio classes used for medias and cards IMAGE_RATIOS = [ ("fr-ratio-32x9", "32x9"), diff --git a/dsfr/locale/fr/LC_MESSAGES/django.mo b/dsfr/locale/fr/LC_MESSAGES/django.mo index 3e72743e8d473af4b9bdefc9b8fded889fd156bd..1d02895c716a634008884197d772dcdce18488e3 100644 GIT binary patch literal 8716 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 delta 2532 zcmY+`ZEO@p9LMn~7OZWr<>6@Q6Wt;R1zWE?mKG`^P=Qh&M5rLb^;qPf+?IRLs!c8= zHW9-MWr8G1Oi>A#3-LT74Iz z23m<6W(_9?H=^EcJLWRJd6h~bH+G>0d>c8;K~BT)7;3;XSd8CcE?&VPUiBTsY({fk z;X4ai9OI(;jiJWrK@QW$DWCDpYgAYYvj^4iebfL)Q5_t|3HTWn;jhS;<`!zj^60e! zt5MH4qkf-@^|%CwVj4BhPE`N>m{!Am{tridPof4oiyY=#PHOivs-tVDjs|h6#UQGE z3*L{5P!rjTdj3V253ih zxE$4C2WldnSd(K+w|~8p%+`za<0L$b${BT54#U$_s;GpJ?KJIJi>pu*dI?)_2kMQ_ zpa%L1)zJkUf!9&VTEt1ekHRtx`PU0jFV=w?r`!KM-AhFSy^cz@w@?G^M^?`qM!msD zs5iZgN}g-TnC4H^^99UCpYbr%%8kKMI0I>7)}o$EpxX5y?b7BID*D5+7nMApq9$+& zHGwOr2X3O0DZqZI!*bNh)uYhKcw;8m=_O{B2e?Lb|>fewC%n&|ha7x)FWVz*HJ z<*}@KuCRjj*G$T}!B=A*AQllS5ki@-qP$p1)DZ)SnS{zjVi_@pm`glCs5IOmdwz)X z3}W$r?oFmXHhZo0r)XanW^2aGN6k`2vsTe3sbtcAhY1$UbP_606E4A`nDvB~T&0Ov zP3S9_LaZf563Yo~w@Q`9pG{0B<`D~srNk0q4Ka#f{g)52`>JH) zYt81267x~wG2#(IML9t#XzS~<|LJJwVg;e3QF)wbCG?%@TXzVR5_>4$EAH~1bHZI+ zPQ>#zN8N;NE0}MO7qr?yVZ`?(}#hZi}jFY_PQ5dZj(~_tL&`P9ha|y4-{lKXoAChEqLG z!iz-F%!`L(r}l@V38oiK*xMuK+SwJOYs0aG6LFJC*NLY( 1);\n" "X-Generator: Poedit 3.4.2\n" -#: dsfr/admin.py:59 +#: dsfr/admin.py:18 +msgid "Website" +msgstr "Site" + +#: dsfr/admin.py:28 +msgid "Notice" +msgstr "Bandeau d’information importante" + +#: dsfr/admin.py:39 +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)" + +#: dsfr/admin.py:45 +msgid "Header" +msgstr "En-tête" + +#: dsfr/admin.py:54 +msgid "Footer" +msgstr "Pied de page" + +#: dsfr/admin.py:65 dsfr/models.py:129 +msgid "Operator logo" +msgstr "Logo opérateur" + +#: dsfr/admin.py:75 msgid "Newsletter" msgstr "Lettre d’information" @@ -50,7 +80,7 @@ msgstr "Info" msgid "Success" msgstr "Succès" -#: dsfr/constants.py:23 +#: dsfr/constants.py:23 dsfr/constants.py:66 msgid "Warning" msgstr "Avertissement" @@ -74,6 +104,50 @@ msgstr "Couleurs illustratives" msgid "System colors" msgstr "Couleurs système" +#: dsfr/constants.py:63 +msgid "Generic notices" +msgstr "Bandeaux génériques" + +#: dsfr/constants.py:65 +msgid "Information" +msgstr "Information" + +#: dsfr/constants.py:67 +msgid "Alert" +msgstr "Alerte" + +#: dsfr/constants.py:71 +msgid "Weather alert notices" +msgstr "Bandeaux de vigilance météo" + +#: dsfr/constants.py:73 +msgid "Orange weather alert" +msgstr "Vigilance météo orange" + +#: dsfr/constants.py:74 +msgid "Red weather alert" +msgstr "Vigilance météo rouge" + +#: dsfr/constants.py:75 +msgid "Purple weather alert" +msgstr "Vigilance météo violette" + +#: dsfr/constants.py:79 +msgid "Alert notices" +msgstr "Bandeaux d’alerte" + +#: dsfr/constants.py:81 +msgid "Attack alert" +msgstr "Alerte attentat" + +#: dsfr/constants.py:82 +msgid "Call for witnesses" +msgstr "Appel à témoins" + +#: dsfr/constants.py:83 +msgid "Cyberattack" +msgstr "Cyberattaque" + #: dsfr/models.py:20 msgid "Language" msgstr "Langue" @@ -102,109 +176,137 @@ msgstr "Titre du site" msgid "Site tagline" msgstr "Sous-titre du site" -#: dsfr/models.py:42 -msgid "Important notice" -msgstr "Bandeau d’information importante" +#: dsfr/models.py:44 +msgid "Notice title" +msgstr "Titre du bandeau" + +#: dsfr/models.py:48 dsfr/models.py:55 +msgid "Can include HTML" +msgstr "Peut inclure du HTML" + +#: dsfr/models.py:52 +msgid "Notice description" +msgstr "Description du bandeau" -#: dsfr/models.py:46 +#: dsfr/models.py:59 +msgid "Notice type" +msgstr "Type de bandeau" + +#: dsfr/models.py:65 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." -#: dsfr/models.py:53 +#: dsfr/models.py:71 +msgid "Notice link" +msgstr "Lien du bandeau" + +#: dsfr/models.py:74 +msgid "Standardized consultation link at the end of the notice." +msgstr "Lien de consultation standardisé à la fin du bandeau." + +#: dsfr/models.py:78 +msgid "Notice icon class" +msgstr "Classe d’icône du bandeau" + +#: dsfr/models.py:82 +msgid "For weather alerts only" +msgstr "Pour les bandeaux de vigilance météo uniquement" + +#: dsfr/models.py:85 +msgid "Collapsible?" +msgstr "Repliable ?" + +#: dsfr/models.py:89 msgid "Institution (header)" msgstr "Institution (en-tête)" -#: dsfr/models.py:59 +#: dsfr/models.py:95 msgid "Institution with line break (header)" msgstr "Institution avec césure (en-tête)" -#: dsfr/models.py:64 +#: dsfr/models.py:100 msgid "Show the BETA tag next to the title" msgstr "Afficher la mention BETA à côté du titre" -#: dsfr/models.py:68 +#: dsfr/models.py:104 msgid "Institution (footer)" -msgstr "Institution (pied" +msgstr "Institution (pied)" -#: dsfr/models.py:74 +#: dsfr/models.py:110 msgid "Institution with line break (footer)" msgstr "Institution avec césure (pied)" -#: dsfr/models.py:79 +#: dsfr/models.py:115 msgid "Description" msgstr "Description" -#: dsfr/models.py:82 +#: dsfr/models.py:118 msgid "Newsletter description" msgstr "Description de la lettre d’information" -#: dsfr/models.py:86 +#: dsfr/models.py:122 msgid "Newsletter registration URL" msgstr "URL d‘inscription à la lettre d’information" -#: dsfr/models.py:93 -msgid "Operator logo" -msgstr "Logo opérateur" - -#: dsfr/models.py:100 +#: dsfr/models.py:136 msgid "Logo alt text" msgstr "Alternative textuelle du logo" -#: dsfr/models.py:103 +#: dsfr/models.py:139 msgid "Must contain the text present in the image." msgstr "Doit impérativement contenir le texte présent dans l’image." -#: dsfr/models.py:106 +#: dsfr/models.py:142 msgid "Width (em)" msgstr "Largeur (em)" -#: dsfr/models.py:112 +#: dsfr/models.py:148 msgid "" "To be adjusted according to the width of the logo. Example for a " "vertical logo: 3.5, Example for a horizontal logo: 8." msgstr "" -"À ajuster en fonction de la largeur du logo. Exemple pour un logo vertical: " -"3.5, Exemple pour un logo horizontal: 8." +"À ajuster en fonction de la largeur du logo. Exemple pour un logo " +"vertical: 3.5, Exemple pour un logo horizontal: 8." -#: dsfr/models.py:118 +#: dsfr/models.py:154 msgid "Mourning" msgstr "Mise en berne" -#: dsfr/models.py:121 +#: dsfr/models.py:157 msgid "Accessibility compliance status" msgstr "Statut de conformité de l’accessibilité" -#: dsfr/models.py:128 +#: dsfr/models.py:164 msgid "Configuration" msgstr "Configuration" -#: dsfr/models.py:131 +#: dsfr/models.py:167 msgid "Site config:" msgstr "Configuration du site :" -#: dsfr/models.py:139 +#: dsfr/models.py:175 msgid "Title" msgstr "Titre" -#: dsfr/models.py:142 +#: dsfr/models.py:178 msgid "URL" msgstr "URL" -#: dsfr/models.py:147 +#: dsfr/models.py:183 msgid "Icon class" msgstr "Classe d’icône" -#: dsfr/models.py:154 +#: dsfr/models.py:190 msgid "Social media" msgstr "Réseau social" -#: dsfr/models.py:155 +#: dsfr/models.py:191 msgid "Social medias" msgstr "Réseaux sociaux" @@ -263,7 +365,7 @@ msgstr "Abonnez-vous à notre lettre d’information" #: dsfr/templates/dsfr/follow.html:18 msgctxt "Button title" msgid "Subscribe to our newsletter" -msgstr "S'abonner à notre lettre d’information" +msgstr "S’abonner à notre lettre d’information" #: dsfr/templates/dsfr/follow.html:24 msgid "Subscribe" @@ -271,7 +373,7 @@ msgstr "S’abonner" #: dsfr/templates/dsfr/follow.html:34 msgid "Follow us
on social media" -msgstr "Suivez-nous
sur les réseaux sociaux" +msgstr "Suivez-nous
sur les réseaux sociaux" #: dsfr/templates/dsfr/footer.html:9 msgid "Back to home page" diff --git a/dsfr/migrations/0009_dsfrconfig_notice_type_alter_dsfrconfig_notice.py b/dsfr/migrations/0009_dsfrconfig_notice_type_alter_dsfrconfig_notice.py new file mode 100644 index 000000000..4da002c53 --- /dev/null +++ b/dsfr/migrations/0009_dsfrconfig_notice_type_alter_dsfrconfig_notice.py @@ -0,0 +1,44 @@ +# Generated by Django 4.2.15 on 2024-08-23 06:59 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("dsfr", "0008_alter_dsfrsocialmedia_options_dsfrconfig_language_and_more"), + ] + + operations = [ + migrations.AddField( + model_name="dsfrconfig", + name="notice_type", + field=models.CharField( + blank=True, + choices=[ + ("info", "Information"), + ("warning", "Warning"), + ("alert", "Alert"), + ("weather-orange", "Orange weather alert"), + ("weather-red", "Red weather alert"), + ("weather-purple", "Purple weather alert"), + ("attack", "Attack alert"), + ("witness", "Call for witnesses"), + ("cyberattack", "Cyberattack"), + ], + help_text='Use is strictly regulated, see documentation.', + max_length=20, + verbose_name="Notice type", + ), + ), + migrations.AlterField( + model_name="dsfrconfig", + name="notice", + field=models.TextField( + blank=True, + default="", + help_text="The important notice banner should only be used for essential and temporary information. (Excessive or continuous use risks “drowning” the message.)", + verbose_name="Important notice content", + ), + ), + ] diff --git a/dsfr/migrations/0010_dsfrconfig_notice_icon_class_alter_dsfrconfig_notice_and_more.py b/dsfr/migrations/0010_dsfrconfig_notice_icon_class_alter_dsfrconfig_notice_and_more.py new file mode 100644 index 000000000..730818ce8 --- /dev/null +++ b/dsfr/migrations/0010_dsfrconfig_notice_icon_class_alter_dsfrconfig_notice_and_more.py @@ -0,0 +1,71 @@ +# Generated by Django 4.2.15 on 2024-08-23 07:17 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("dsfr", "0009_dsfrconfig_notice_type_alter_dsfrconfig_notice"), + ] + + operations = [ + migrations.AddField( + model_name="dsfrconfig", + 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.AlterField( + model_name="dsfrconfig", + name="notice", + field=models.TextField( + blank=True, + default="", + help_text="The important notice banner should only be used for essential and temporary information. (Excessive or continuous use risks “drowning” the message.)", + verbose_name="Notice content", + ), + ), + migrations.AlterField( + model_name="dsfrconfig", + 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", + ), + ), + ] diff --git a/dsfr/migrations/0011_rename_notice_dsfrconfig_notice_title.py b/dsfr/migrations/0011_rename_notice_dsfrconfig_notice_title.py new file mode 100644 index 000000000..a1326ff90 --- /dev/null +++ b/dsfr/migrations/0011_rename_notice_dsfrconfig_notice_title.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.15 on 2024-08-23 07:24 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("dsfr", "0010_dsfrconfig_notice_icon_class_alter_dsfrconfig_notice_and_more"), + ] + + operations = [ + migrations.RenameField( + model_name="dsfrconfig", + old_name="notice", + new_name="notice_title", + ), + ] diff --git a/dsfr/migrations/0012_dsfrconfig_notice_description_and_more.py b/dsfr/migrations/0012_dsfrconfig_notice_description_and_more.py new file mode 100644 index 000000000..f84623d82 --- /dev/null +++ b/dsfr/migrations/0012_dsfrconfig_notice_description_and_more.py @@ -0,0 +1,86 @@ +# Generated by Django 4.2.15 on 2024-08-23 07:48 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("dsfr", "0011_rename_notice_dsfrconfig_notice_title"), + ] + + operations = [ + migrations.AddField( + model_name="dsfrconfig", + name="notice_description", + field=models.TextField( + blank=True, + default="", + help_text="Can include HTML", + verbose_name="Notice description", + ), + ), + migrations.AddField( + model_name="dsfrconfig", + name="notice_is_collapsible", + field=models.BooleanField(default=False, verbose_name="Collapsible?"), + ), + migrations.AddField( + model_name="dsfrconfig", + 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.AlterField( + model_name="dsfrconfig", + name="notice_title", + field=models.CharField( + blank=True, + default="", + help_text="Can include HTML", + max_length=250, + verbose_name="Notice title", + ), + ), + migrations.AlterField( + model_name="dsfrconfig", + 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", + ), + ), + ] diff --git a/dsfr/models.py b/dsfr/models.py index 87fad2388..4399a6f4c 100644 --- a/dsfr/models.py +++ b/dsfr/models.py @@ -5,7 +5,7 @@ from django.db import models from django.utils.translation import gettext_lazy as _ -from dsfr.constants import DJANGO_DSFR_LANGUAGES +from dsfr.constants import DJANGO_DSFR_LANGUAGES, NOTICE_TYPE_CHOICES def validate_image_extension(value): @@ -38,16 +38,52 @@ class DsfrConfig(models.Model): site_tagline = models.CharField( _("Site tagline"), max_length=200, default=_("Site tagline"), blank=True ) - notice = models.TextField( - _("Important notice"), + + # Notice + notice_title = models.CharField( + _("Notice title"), + max_length=250, + default="", + blank=True, + help_text=_("Can include HTML"), + ) + + notice_description = models.TextField( + _("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 + # Header header_brand = models.CharField( _("Institution (header)"), diff --git a/dsfr/templates/dsfr/base.html b/dsfr/templates/dsfr/base.html index 84e59704e..452924ad0 100644 --- a/dsfr/templates/dsfr/base.html +++ b/dsfr/templates/dsfr/base.html @@ -38,8 +38,8 @@ {% dsfr_theme_modale %} - {% if SITE_CONFIG.notice %} - {% dsfr_notice title=SITE_CONFIG.notice %} + {% if SITE_CONFIG.notice_title or SITE_CONFIG.notice_description %} + {% dsfr_notice title=SITE_CONFIG.notice_title description=SITE_CONFIG.notice_description link=SITE_CONFIG.notice_link type=SITE_CONFIG.notice_type icon=SITE_CONFIG.notice_icon_class is_collapsible=SITE_CONFIG.notice_is_collapsible %} {% endif %}
diff --git a/dsfr/templatetags/dsfr_tags.py b/dsfr/templatetags/dsfr_tags.py index 81d3c1f77..187ae73d1 100644 --- a/dsfr/templatetags/dsfr_tags.py +++ b/dsfr/templatetags/dsfr_tags.py @@ -834,7 +834,7 @@ def dsfr_notice(*args, **kwargs) -> dict: } ``` - Possible values for type: + Possible values for type (list available in constant NOTICE_TYPE_CHOICES): - info - warning diff --git a/pyproject.toml b/pyproject.toml index c0d39a850..0056f78ff 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ authors = ["Sylvain Boissel "] description = "Integrate the French government Design System into a Django app" license = "MIT" name = "django-dsfr" -version = "1.3.0" +version = "1.3.1" classifiers = [ "Development Status :: 5 - Production/Stable", "Environment :: Web Environment",