From c5670c9453517acdb336f41fa5d3b5fec424b5e1 Mon Sep 17 00:00:00 2001 From: Yann Sionneau Date: Mon, 5 Dec 2022 18:26:33 +0100 Subject: [PATCH 01/23] Test Django 3.2 LTS --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index be2b211b..dab9293c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -Django>=2.2.28,<3.* +Django~=3.2.0 django-colorfield==0.1.15 django-tinymce==2.8.0 django-mailer==1.2.6 From 0707d69d250c5816633ad5de0ea4bc8d81e44542 Mon Sep 17 00:00:00 2001 From: Yann Sionneau Date: Mon, 5 Dec 2022 19:56:43 +0100 Subject: [PATCH 02/23] Test Django 4.1 --- Jenkinsfile | 2 +- requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index f6abec84..84ec2939 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -8,7 +8,7 @@ node { sh ''' cd $WORKSPACE -rm -rf venv && virtualenv -p python3 venv +rm -rf venv && python3.8 -m venv venv source venv/bin/activate pip3 install -r requirements_dev.txt cat < my.cnf diff --git a/requirements.txt b/requirements.txt index dab9293c..a16afa9a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -Django~=3.2.0 +Django~=4.1.0 django-colorfield==0.1.15 django-tinymce==2.8.0 django-mailer==1.2.6 From c56aa51db7c565a9fdc362fafc38ebac4d81cb55 Mon Sep 17 00:00:00 2001 From: Yann Sionneau Date: Sat, 10 Jun 2023 17:37:47 +0200 Subject: [PATCH 03/23] Update to Django 4.2 LTS --- requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index a16afa9a..108814ff 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ -Django~=4.1.0 +Django~=4.2.0 django-colorfield==0.1.15 -django-tinymce==2.8.0 +django-tinymce==3.5.0 django-mailer==1.2.6 django-maintenance-mode django-phonenumber-field[phonenumbers]==6.3.0 From 40c683811f06b563c0cd89ab9095dffb1dbe6d24 Mon Sep 17 00:00:00 2001 From: Yann Sionneau Date: Sat, 10 Jun 2023 18:04:12 +0200 Subject: [PATCH 04/23] Replace deprecated translation functions with new ones --- pytition/petition/admin.py | 280 +++++++++++++++++------------------ pytition/petition/forms.py | 2 +- pytition/petition/helpers.py | 2 +- pytition/petition/models.py | 36 ++--- pytition/petition/views.py | 4 +- 5 files changed, 162 insertions(+), 162 deletions(-) diff --git a/pytition/petition/admin.py b/pytition/petition/admin.py index b600c34a..d900a1e4 100644 --- a/pytition/petition/admin.py +++ b/pytition/petition/admin.py @@ -1,6 +1,6 @@ from django.contrib import admin from django.forms import ModelForm -from django.utils.translation import ugettext_lazy +from django.utils.translation import gettext_lazy from django.contrib import messages from django.core.exceptions import ValidationError from django import forms @@ -18,7 +18,7 @@ class PytitionUserAdmin(admin.ModelAdmin): def name(self, pu): return pu - name.description = ugettext_lazy("Name") + name.description = gettext_lazy("Name") @admin.register(SlugModel) @@ -36,8 +36,8 @@ def petition_num(self, org): def user_num(self, org): return org.members.count() - petition_num.description = ugettext_lazy('Number of petitions') - user_num.description = ugettext_lazy('Number of members') + petition_num.description = gettext_lazy('Number of petitions') + user_num.description = gettext_lazy('Number of members') def confirm(modeladmin, request, queryset): @@ -46,7 +46,7 @@ def confirm(modeladmin, request, queryset): signature.confirm() signature.save() except ValidationError as e: - messages.error(request, ugettext_lazy("Error: {}").format(e.message)) + messages.error(request, gettext_lazy("Error: {}").format(e.message)) def resend_confirmation_mail(modeladmin, request, queryset): @@ -54,8 +54,8 @@ def resend_confirmation_mail(modeladmin, request, queryset): send_confirmation_email(request, signature) -confirm.short_description = ugettext_lazy("Confirm the signatures") -resend_confirmation_mail.short_description = ugettext_lazy("Send the confirmation email once again") +confirm.short_description = gettext_lazy("Confirm the signatures") +resend_confirmation_mail.short_description = gettext_lazy("Send the confirmation email once again") @admin.register(Signature) @@ -82,14 +82,14 @@ class Meta: #inlines = (SlugInlineAdmin, ) exclude = ('slugs', ) help_texts = { - 'linear_gradient_direction': ugettext_lazy('This is a gradient color. If selected, the background color will be a gradient color. If not, the background color will be a monochrome background color.'), - 'gradient_to': ugettext_lazy('Only used if gradient is selected'), - 'gradient_from': ugettext_lazy('Only used if gradient is selected'), - 'footer_links': ugettext_lazy('Put a bullet point list of links, it will appear horizontally in the page footer'), - 'twitter_description': ugettext_lazy('This is the description of the petition, it will be displayed in Twitter/Facebook cards when the link is posted to social networks. To be tested via https://cards-dev.twitter.com/validator and https://developers.facebook.com/tools/debug/'), - 'twitter_image': ugettext_lazy('Picture displayed in Twitter/Facebook cards when the link is posted to social networks. To be tested via https://cards-dev.twitter.com/validator and https://developers.facebook.com/tools/debug/'), - 'has_newsletter': ugettext_lazy('Allow to chose whether the newsletter subscription checkbox is shown or not'), - 'newsletter_subscribe_http_data': ugettext_lazy("""Only in case subscription to the newsletter via HTTP POST or GET methods. Put here data to be sent, using Python dictionary syntax. e.g.:
+ 'linear_gradient_direction': gettext_lazy('This is a gradient color. If selected, the background color will be a gradient color. If not, the background color will be a monochrome background color.'), + 'gradient_to': gettext_lazy('Only used if gradient is selected'), + 'gradient_from': gettext_lazy('Only used if gradient is selected'), + 'footer_links': gettext_lazy('Put a bullet point list of links, it will appear horizontally in the page footer'), + 'twitter_description': gettext_lazy('This is the description of the petition, it will be displayed in Twitter/Facebook cards when the link is posted to social networks. To be tested via https://cards-dev.twitter.com/validator and https://developers.facebook.com/tools/debug/'), + 'twitter_image': gettext_lazy('Picture displayed in Twitter/Facebook cards when the link is posted to social networks. To be tested via https://cards-dev.twitter.com/validator and https://developers.facebook.com/tools/debug/'), + 'has_newsletter': gettext_lazy('Allow to chose whether the newsletter subscription checkbox is shown or not'), + 'newsletter_subscribe_http_data': gettext_lazy("""Only in case subscription to the newsletter via HTTP POST or GET methods. Put here data to be sent, using Python dictionary syntax. e.g.:
{\'_wpcf7\': 21,
\'_wpcf7_version\': \'4.9\',
\'_wpcf7_locale\': \'fr_FR\',
@@ -97,60 +97,60 @@ class Meta: \'_wpcf7_container_post': \'5398\',
\'your-email\': \'\'
}"""), - 'newsletter_subscribe_http_mailfield': ugettext_lazy('Only when HTTP POST or GET subscription method is used. Name of the field to send via GET or POST, containing the email address to subscribe. Following the example of preceding form field, that would be \'your-email\''), - 'newsletter_subscribe_http_url': ugettext_lazy('Only when HTTP POST or GET subscription method is used. Adresse HTTP à requêter via GET ou POST pour enregistrer quelqu\'un sur la newsletter'), - 'newsletter_subscribe_mail_subject': ugettext_lazy('Only when EMAIL subscription method is used. Inscrire ici la syntaxe de sujet du mail qui permet d\'inscrire quelqu\'un à la newsletter. Indiquez {} à la place où le mail du signataire doit être inséré. Ex: \'ADD NOM_LISTE {} NOM_SIGNATAIRE\''), - 'newsletter_subscribe_mail_from': ugettext_lazy('Only when EMAIL subscription method is used. L\'expéditeur du mail qui permet d\'enregistrer quelqu\'un à la newsletter. Il s\'agit généralement d\'une adresse qui est administratrice de la liste SYMPA ou MAILMAN'), - 'newsletter_subscribe_mail_to': ugettext_lazy('Only when EMAIL subscription method is used. Adresse email d\'administration de la liste, ex : sympa@NOM_LISTE.listes.vox.coop'), - 'newsletter_subscribe_method': ugettext_lazy('This selects the newsletter subscription method. It is either HTTP GET or POST or via sending EMAIL to the newsletter admin address'), - 'published': ugettext_lazy('If checked, the petition is published and accessible on the website by everybody. If not checked, the petition is only accessible by logged in users, others will get a 404 error.'), - 'newsletter_text': ugettext_lazy('E.g.: I want to receive updates or informations from this organization.'), - 'sign_form_footer': ugettext_lazy('E.g.: Your data will stay strictly confidential and will not be sold, given away or exchanged with third parties. Informations about this campaign as well as other news about this organization will be sent to you if you checked the checkbox. You can unsubscribe at any moment.'), - 'org_twitter_handle': ugettext_lazy('The twitter account handle of the organization, starting with the \'@\' symbol. E.g.: @RAP_Asso. This is necessary in order to attribute the \'Twitter Card\' to the correct account. See https://developer.twitter.com/en/docs/tweets/optimize-with-cards/overview/summary'), - 'use_custom_email_settings': ugettext_lazy('Check if you want to use your own E-Mail SMTP account.'), - 'confirmation_email_reply': ugettext_lazy('e.g.: petition@mydomain.tld'), - 'newsletter_subscribe_mail_smtp_host': ugettext_lazy('If you don\'t have a real email account, leave \'localhost\'.'), - 'newsletter_subscribe_mail_smtp_port': ugettext_lazy('25 for cleartext connection, 587 for STARTTLS, 465 for TLS. Prefer TLS if the email server supports it.'), - 'newsletter_subscribe_mail_smtp_user': ugettext_lazy('Leave empty if you don\'t use any account autentication.'), - 'newsletter_subscribe_mail_smtp_password': ugettext_lazy('Leave empty if you don\'t use any account autentication.'), - 'newsletter_subscribe_mail_smtp_tls': ugettext_lazy('SMTP connection encrypted via TLS, prefer this rather than STARTTLS if possible. Don\'t check both. The 2 settings are mutually exclusive.'), - 'newsletter_subscribe_mail_smtp_starttls': ugettext_lazy('Connexion SMTP chiffrée via STARTTLS, préférez TLS à ce réglage. Ne pas cocher les 2. Les 2 réglages sont mutuellement exclusifs.'), + 'newsletter_subscribe_http_mailfield': gettext_lazy('Only when HTTP POST or GET subscription method is used. Name of the field to send via GET or POST, containing the email address to subscribe. Following the example of preceding form field, that would be \'your-email\''), + 'newsletter_subscribe_http_url': gettext_lazy('Only when HTTP POST or GET subscription method is used. Adresse HTTP à requêter via GET ou POST pour enregistrer quelqu\'un sur la newsletter'), + 'newsletter_subscribe_mail_subject': gettext_lazy('Only when EMAIL subscription method is used. Inscrire ici la syntaxe de sujet du mail qui permet d\'inscrire quelqu\'un à la newsletter. Indiquez {} à la place où le mail du signataire doit être inséré. Ex: \'ADD NOM_LISTE {} NOM_SIGNATAIRE\''), + 'newsletter_subscribe_mail_from': gettext_lazy('Only when EMAIL subscription method is used. L\'expéditeur du mail qui permet d\'enregistrer quelqu\'un à la newsletter. Il s\'agit généralement d\'une adresse qui est administratrice de la liste SYMPA ou MAILMAN'), + 'newsletter_subscribe_mail_to': gettext_lazy('Only when EMAIL subscription method is used. Adresse email d\'administration de la liste, ex : sympa@NOM_LISTE.listes.vox.coop'), + 'newsletter_subscribe_method': gettext_lazy('This selects the newsletter subscription method. It is either HTTP GET or POST or via sending EMAIL to the newsletter admin address'), + 'published': gettext_lazy('If checked, the petition is published and accessible on the website by everybody. If not checked, the petition is only accessible by logged in users, others will get a 404 error.'), + 'newsletter_text': gettext_lazy('E.g.: I want to receive updates or informations from this organization.'), + 'sign_form_footer': gettext_lazy('E.g.: Your data will stay strictly confidential and will not be sold, given away or exchanged with third parties. Informations about this campaign as well as other news about this organization will be sent to you if you checked the checkbox. You can unsubscribe at any moment.'), + 'org_twitter_handle': gettext_lazy('The twitter account handle of the organization, starting with the \'@\' symbol. E.g.: @RAP_Asso. This is necessary in order to attribute the \'Twitter Card\' to the correct account. See https://developer.twitter.com/en/docs/tweets/optimize-with-cards/overview/summary'), + 'use_custom_email_settings': gettext_lazy('Check if you want to use your own E-Mail SMTP account.'), + 'confirmation_email_reply': gettext_lazy('e.g.: petition@mydomain.tld'), + 'newsletter_subscribe_mail_smtp_host': gettext_lazy('If you don\'t have a real email account, leave \'localhost\'.'), + 'newsletter_subscribe_mail_smtp_port': gettext_lazy('25 for cleartext connection, 587 for STARTTLS, 465 for TLS. Prefer TLS if the email server supports it.'), + 'newsletter_subscribe_mail_smtp_user': gettext_lazy('Leave empty if you don\'t use any account autentication.'), + 'newsletter_subscribe_mail_smtp_password': gettext_lazy('Leave empty if you don\'t use any account autentication.'), + 'newsletter_subscribe_mail_smtp_tls': gettext_lazy('SMTP connection encrypted via TLS, prefer this rather than STARTTLS if possible. Don\'t check both. The 2 settings are mutually exclusive.'), + 'newsletter_subscribe_mail_smtp_starttls': gettext_lazy('Connexion SMTP chiffrée via STARTTLS, préférez TLS à ce réglage. Ne pas cocher les 2. Les 2 réglages sont mutuellement exclusifs.'), } labels = { - 'title': ugettext_lazy('Petition title'), - 'text': ugettext_lazy('Petition text'), - 'side_text': ugettext_lazy('Side text, on top of form'), - 'target': ugettext_lazy('Signature target number'), - 'paper_signatures': ugettext_lazy('Number of paper (or other external medium) signatures'), - 'paper_signatures_enabled': ugettext_lazy('Enable paper signatures accounting'), - 'linear_gradient_direction': ugettext_lazy('Direction of linear gradient for background color'), - 'gradient_from': ugettext_lazy('Source color for linear gradient'), - 'gradient_to': ugettext_lazy('Destinatoin color for linear gradient'), - 'bgcolor': ugettext_lazy('Color for monochrome background color'), - 'footer_text': ugettext_lazy('Footer text'), - 'footer_links': ugettext_lazy('Footer links'), - 'twitter_description': ugettext_lazy('Description for Twitter/Facebook cards'), - 'twitter_image': ugettext_lazy('Picture for Twitter/Facebook cards'), - 'has_newsletter': ugettext_lazy('Is the petition associated with a newsletter?'), - 'newsletter_subscribe_http_data': ugettext_lazy('Data structure to be sent in order to subscribe someone to the newsletter in case of HTTP method'), - 'newsletter_subscribe_http_mailfield': ugettext_lazy('Name of the field which should contain the email value in the PHP data structure'), - 'newsletter_subscribe_http_url': ugettext_lazy('HTTP URL for newsletter subscription'), - 'newsletter_subscribe_mail_subject': ugettext_lazy('Email subject for newsletter subscription command'), - 'newsletter_subscribe_mail_from': ugettext_lazy('FROM field for newsletter subscription command'), - 'newsletter_subscribe_mail_to': ugettext_lazy('TO field for newsletter subscription command'), - 'newsletter_subscribe_method': ugettext_lazy('Newsletter subscription method'), - 'published': ugettext_lazy('Puslibhed'), - 'newsletter_text': ugettext_lazy('Form label text of newsletter subscription checkbox'), - 'sign_form_footer': ugettext_lazy('Sign form footer text'), - 'org_twitter_handle': ugettext_lazy('Organization Twitter handle'), - 'use_custom_email_settings': ugettext_lazy('Use custom e-mail settings?'), - 'confirmation_email_reply': ugettext_lazy('Confirmation email Reply-to address'), - 'newsletter_subscribe_mail_smtp_host': ugettext_lazy('SMTP server hostname'), - 'newsletter_subscribe_mail_smtp_port': ugettext_lazy('SMTP port'), - 'newsletter_subscribe_mail_smtp_user': ugettext_lazy('SMTP username'), - 'newsletter_subscribe_mail_smtp_password': ugettext_lazy('SMTP password'), - 'newsletter_subscribe_mail_smtp_tls': ugettext_lazy('SMTP via TLS?'), - 'newsletter_subscribe_mail_smtp_starttls': ugettext_lazy('SMTP via STARTTLS?'), + 'title': gettext_lazy('Petition title'), + 'text': gettext_lazy('Petition text'), + 'side_text': gettext_lazy('Side text, on top of form'), + 'target': gettext_lazy('Signature target number'), + 'paper_signatures': gettext_lazy('Number of paper (or other external medium) signatures'), + 'paper_signatures_enabled': gettext_lazy('Enable paper signatures accounting'), + 'linear_gradient_direction': gettext_lazy('Direction of linear gradient for background color'), + 'gradient_from': gettext_lazy('Source color for linear gradient'), + 'gradient_to': gettext_lazy('Destinatoin color for linear gradient'), + 'bgcolor': gettext_lazy('Color for monochrome background color'), + 'footer_text': gettext_lazy('Footer text'), + 'footer_links': gettext_lazy('Footer links'), + 'twitter_description': gettext_lazy('Description for Twitter/Facebook cards'), + 'twitter_image': gettext_lazy('Picture for Twitter/Facebook cards'), + 'has_newsletter': gettext_lazy('Is the petition associated with a newsletter?'), + 'newsletter_subscribe_http_data': gettext_lazy('Data structure to be sent in order to subscribe someone to the newsletter in case of HTTP method'), + 'newsletter_subscribe_http_mailfield': gettext_lazy('Name of the field which should contain the email value in the PHP data structure'), + 'newsletter_subscribe_http_url': gettext_lazy('HTTP URL for newsletter subscription'), + 'newsletter_subscribe_mail_subject': gettext_lazy('Email subject for newsletter subscription command'), + 'newsletter_subscribe_mail_from': gettext_lazy('FROM field for newsletter subscription command'), + 'newsletter_subscribe_mail_to': gettext_lazy('TO field for newsletter subscription command'), + 'newsletter_subscribe_method': gettext_lazy('Newsletter subscription method'), + 'published': gettext_lazy('Puslibhed'), + 'newsletter_text': gettext_lazy('Form label text of newsletter subscription checkbox'), + 'sign_form_footer': gettext_lazy('Sign form footer text'), + 'org_twitter_handle': gettext_lazy('Organization Twitter handle'), + 'use_custom_email_settings': gettext_lazy('Use custom e-mail settings?'), + 'confirmation_email_reply': gettext_lazy('Confirmation email Reply-to address'), + 'newsletter_subscribe_mail_smtp_host': gettext_lazy('SMTP server hostname'), + 'newsletter_subscribe_mail_smtp_port': gettext_lazy('SMTP port'), + 'newsletter_subscribe_mail_smtp_user': gettext_lazy('SMTP username'), + 'newsletter_subscribe_mail_smtp_password': gettext_lazy('SMTP password'), + 'newsletter_subscribe_mail_smtp_tls': gettext_lazy('SMTP via TLS?'), + 'newsletter_subscribe_mail_smtp_starttls': gettext_lazy('SMTP via STARTTLS?'), } @@ -161,23 +161,23 @@ class PetitionAdmin(admin.ModelAdmin): search_fields = ('title', ) list_display = ('title', 'non_confirmed_signature_number', 'confirmed_signature_number') fieldsets = ( - (ugettext_lazy('To whom is this petition?'), + (gettext_lazy('To whom is this petition?'), { 'fields': ('org', 'user') } ), - (ugettext_lazy('Content of the petition'), + (gettext_lazy('Content of the petition'), { 'fields': ('title', 'text', 'side_text', 'footer_text', 'footer_links', 'sign_form_footer', 'target', 'paper_signatures_enabled', 'paper_signatures') } ), - (ugettext_lazy('Background color'), + (gettext_lazy('Background color'), { 'fields': ('linear_gradient_direction', 'gradient_from', 'gradient_to', 'bgcolor') } ), - (ugettext_lazy('Setup of the newsletter associated to the petition'), + (gettext_lazy('Setup of the newsletter associated to the petition'), { 'fields': ('has_newsletter', 'newsletter_text', 'newsletter_subscribe_method', 'newsletter_subscribe_http_data', 'newsletter_subscribe_http_mailfield', @@ -188,16 +188,16 @@ class PetitionAdmin(admin.ModelAdmin): 'newsletter_subscribe_mail_smtp_tls', 'newsletter_subscribe_mail_smtp_starttls') } ), - (ugettext_lazy('Confirmation email setup'), + (gettext_lazy('Confirmation email setup'), { 'fields': ('confirmation_email_reply', ) } ), - (ugettext_lazy('Petition meta-data for social networks'), + (gettext_lazy('Petition meta-data for social networks'), { 'fields': ('twitter_description', 'twitter_image', 'org_twitter_handle') }), - (ugettext_lazy('Publish the petition'), + (gettext_lazy('Publish the petition'), { 'fields': ('published', ) }) @@ -205,11 +205,11 @@ class PetitionAdmin(admin.ModelAdmin): def non_confirmed_signature_number(self, petition): return petition.get_signature_number(confirmed=False) - non_confirmed_signature_number.short_description = ugettext_lazy('Unconfirmed signatures') + non_confirmed_signature_number.short_description = gettext_lazy('Unconfirmed signatures') def confirmed_signature_number(self, petition): return petition.get_signature_number(confirmed=True) - confirmed_signature_number.short_description = ugettext_lazy('Confirmed signatures') + confirmed_signature_number.short_description = gettext_lazy('Confirmed signatures') class PetitionTemplateForm(ModelForm): @@ -222,14 +222,14 @@ class Meta: model = PetitionTemplate fields = ['linear_gradient_direction', 'side_text'] help_texts = { - 'linear_gradient_direction': ugettext_lazy('This is a gradient color. If selected, the background color will be a gradient color. If not, the background color will be a monochrome background color.'), - 'gradient_to': ugettext_lazy('Only used if gradient is selected'), - 'gradient_from': ugettext_lazy('Only used if gradient is selected'), - 'footer_links': ugettext_lazy('Put a bullet point list of links, it will appear horizontally in the page footer'), - 'twitter_description': ugettext_lazy('This is the description of the petition, it will be displayed in Twitter/Facebook cards when the link is posted to social networks. To be tested via https://cards-dev.twitter.com/validator and https://developers.facebook.com/tools/debug/'), - 'twitter_image': ugettext_lazy('Picture displayed in Twitter/Facebook cards when the link is posted to social networks. To be tested via https://cards-dev.twitter.com/validator and https://developers.facebook.com/tools/debug/'), - 'has_newsletter': ugettext_lazy('Allow to chose whether the newsletter subscription checkbox is shown or not'), - 'newsletter_subscribe_http_data': ugettext_lazy("""Only in case subscription to the newsletter via HTTP POST or GET methods. Put here data to be sent, using Python dictionary syntax. e.g.:
+ 'linear_gradient_direction': gettext_lazy('This is a gradient color. If selected, the background color will be a gradient color. If not, the background color will be a monochrome background color.'), + 'gradient_to': gettext_lazy('Only used if gradient is selected'), + 'gradient_from': gettext_lazy('Only used if gradient is selected'), + 'footer_links': gettext_lazy('Put a bullet point list of links, it will appear horizontally in the page footer'), + 'twitter_description': gettext_lazy('This is the description of the petition, it will be displayed in Twitter/Facebook cards when the link is posted to social networks. To be tested via https://cards-dev.twitter.com/validator and https://developers.facebook.com/tools/debug/'), + 'twitter_image': gettext_lazy('Picture displayed in Twitter/Facebook cards when the link is posted to social networks. To be tested via https://cards-dev.twitter.com/validator and https://developers.facebook.com/tools/debug/'), + 'has_newsletter': gettext_lazy('Allow to chose whether the newsletter subscription checkbox is shown or not'), + 'newsletter_subscribe_http_data': gettext_lazy("""Only in case subscription to the newsletter via HTTP POST or GET methods. Put here data to be sent, using Python dictionary syntax. e.g.:
{\'_wpcf7\': 21,
\'_wpcf7_version\': \'4.9\',
\'_wpcf7_locale\': \'fr_FR\',
@@ -237,58 +237,58 @@ class Meta: \'_wpcf7_container_post': \'5398\',
\'your-email\': \'\'
}"""), - 'newsletter_subscribe_http_mailfield': ugettext_lazy('Only when HTTP POST or GET subscription method is used. Name of the field to send via GET or POST, containing the email address to subscribe. Following the example of preceding form field, that would be \'your-email\''), - 'newsletter_subscribe_http_url': ugettext_lazy('Only when HTTP POST or GET subscription method is used. Adresse HTTP à requêter via GET ou POST pour enregistrer quelqu\'un sur la newsletter'), - 'newsletter_subscribe_mail_subject': ugettext_lazy('Only when EMAIL subscription method is used. Inscrire ici la syntaxe de sujet du mail qui permet d\'inscrire quelqu\'un à la newsletter. Indiquez {} à la place où le mail du signataire doit être inséré. Ex: \'ADD NOM_LISTE {} NOM_SIGNATAIRE\''), - 'newsletter_subscribe_mail_from': ugettext_lazy('Only when EMAIL subscription method is used. L\'expéditeur du mail qui permet d\'enregistrer quelqu\'un à la newsletter. Il s\'agit généralement d\'une adresse qui est administratrice de la liste SYMPA ou MAILMAN'), - 'newsletter_subscribe_mail_to': ugettext_lazy('Only when EMAIL subscription method is used. Adresse email d\'administration de la liste, ex : sympa@NOM_LISTE.listes.vox.coop'), - 'newsletter_subscribe_method': ugettext_lazy('This selects the newsletter subscription method. It is either HTTP GET or POST or via sending EMAIL to the newsletter admin address'), - 'published': ugettext_lazy('If checked, the petition is published and accessible on the website by everybody. If not checked, the petition is only accessible by logged in users, others will get a 404 error.'), - 'newsletter_text': ugettext_lazy('E.g.: I want to receive updates or informations from this organization.'), - 'sign_form_footer': ugettext_lazy('E.g.: Your data will stay strictly confidential and will not be sold, given away or exchanged with third parties. Informations about this campaign as well as other news about this organization will be sent to you if you checked the checkbox. You can unsubscribe at any moment.'), - 'org_twitter_handle': ugettext_lazy('The twitter account handle of the organization, starting with the \'@\' symbol. E.g.: @RAP_Asso. This is necessary in order to attribute the \'Twitter Card\' to the correct account. See https://developer.twitter.com/en/docs/tweets/optimize-with-cards/overview/summary'), - 'use_custom_email_settings': ugettext_lazy('Check if you want to use your own E-Mail SMTP account.'), - 'confirmation_email_reply': ugettext_lazy('e.g.: petition@mydomain.tld'), - 'newsletter_subscribe_mail_smtp_host': ugettext_lazy('If you don\'t have a real email account, leave \'localhost\'.'), - 'newsletter_subscribe_mail_smtp_port': ugettext_lazy('25 for cleartext connection, 587 for STARTTLS, 465 for TLS. Prefer TLS if the email server supports it.'), - 'newsletter_subscribe_mail_smtp_user': ugettext_lazy('Leave empty if you don\'t use any account autentication.'), - 'newsletter_subscribe_mail_smtp_password': ugettext_lazy('Leave empty if you don\'t use any account autentication.'), - 'newsletter_subscribe_mail_smtp_tls': ugettext_lazy('SMTP connection encrypted via TLS, prefer this rather than STARTTLS if possible. Don\'t check both. The 2 settings are mutually exclusive.'), - 'newsletter_subscribe_mail_smtp_starttls': ugettext_lazy('Connexion SMTP chiffrée via STARTTLS, préférez TLS à ce réglage. Ne pas cocher les 2. Les 2 réglages sont mutuellement exclusifs.'), + 'newsletter_subscribe_http_mailfield': gettext_lazy('Only when HTTP POST or GET subscription method is used. Name of the field to send via GET or POST, containing the email address to subscribe. Following the example of preceding form field, that would be \'your-email\''), + 'newsletter_subscribe_http_url': gettext_lazy('Only when HTTP POST or GET subscription method is used. Adresse HTTP à requêter via GET ou POST pour enregistrer quelqu\'un sur la newsletter'), + 'newsletter_subscribe_mail_subject': gettext_lazy('Only when EMAIL subscription method is used. Inscrire ici la syntaxe de sujet du mail qui permet d\'inscrire quelqu\'un à la newsletter. Indiquez {} à la place où le mail du signataire doit être inséré. Ex: \'ADD NOM_LISTE {} NOM_SIGNATAIRE\''), + 'newsletter_subscribe_mail_from': gettext_lazy('Only when EMAIL subscription method is used. L\'expéditeur du mail qui permet d\'enregistrer quelqu\'un à la newsletter. Il s\'agit généralement d\'une adresse qui est administratrice de la liste SYMPA ou MAILMAN'), + 'newsletter_subscribe_mail_to': gettext_lazy('Only when EMAIL subscription method is used. Adresse email d\'administration de la liste, ex : sympa@NOM_LISTE.listes.vox.coop'), + 'newsletter_subscribe_method': gettext_lazy('This selects the newsletter subscription method. It is either HTTP GET or POST or via sending EMAIL to the newsletter admin address'), + 'published': gettext_lazy('If checked, the petition is published and accessible on the website by everybody. If not checked, the petition is only accessible by logged in users, others will get a 404 error.'), + 'newsletter_text': gettext_lazy('E.g.: I want to receive updates or informations from this organization.'), + 'sign_form_footer': gettext_lazy('E.g.: Your data will stay strictly confidential and will not be sold, given away or exchanged with third parties. Informations about this campaign as well as other news about this organization will be sent to you if you checked the checkbox. You can unsubscribe at any moment.'), + 'org_twitter_handle': gettext_lazy('The twitter account handle of the organization, starting with the \'@\' symbol. E.g.: @RAP_Asso. This is necessary in order to attribute the \'Twitter Card\' to the correct account. See https://developer.twitter.com/en/docs/tweets/optimize-with-cards/overview/summary'), + 'use_custom_email_settings': gettext_lazy('Check if you want to use your own E-Mail SMTP account.'), + 'confirmation_email_reply': gettext_lazy('e.g.: petition@mydomain.tld'), + 'newsletter_subscribe_mail_smtp_host': gettext_lazy('If you don\'t have a real email account, leave \'localhost\'.'), + 'newsletter_subscribe_mail_smtp_port': gettext_lazy('25 for cleartext connection, 587 for STARTTLS, 465 for TLS. Prefer TLS if the email server supports it.'), + 'newsletter_subscribe_mail_smtp_user': gettext_lazy('Leave empty if you don\'t use any account autentication.'), + 'newsletter_subscribe_mail_smtp_password': gettext_lazy('Leave empty if you don\'t use any account autentication.'), + 'newsletter_subscribe_mail_smtp_tls': gettext_lazy('SMTP connection encrypted via TLS, prefer this rather than STARTTLS if possible. Don\'t check both. The 2 settings are mutually exclusive.'), + 'newsletter_subscribe_mail_smtp_starttls': gettext_lazy('Connexion SMTP chiffrée via STARTTLS, préférez TLS à ce réglage. Ne pas cocher les 2. Les 2 réglages sont mutuellement exclusifs.'), } labels = { - 'name': ugettext_lazy('Petition template name'), - 'text': ugettext_lazy('Petition text'), - 'side_text': ugettext_lazy('Side text, on top of form'), - 'target': ugettext_lazy('Signature target number'), - 'linear_gradient_direction': ugettext_lazy('Direction of linear gradient for background color'), - 'gradient_from': ugettext_lazy('Source color for linear gradient'), - 'gradient_to': ugettext_lazy('Destinatoin color for linear gradient'), - 'bgcolor': ugettext_lazy('Color for monochrome background color'), - 'footer_text': ugettext_lazy('Footer text'), - 'footer_links': ugettext_lazy('Footer links'), - 'twitter_description': ugettext_lazy('Description for Twitter/Facebook cards'), - 'twitter_image': ugettext_lazy('Picture for Twitter/Facebook cards'), - 'has_newsletter': ugettext_lazy('Is the petition associated with a newsletter?'), - 'newsletter_subscribe_http_data': ugettext_lazy('Data structure to be sent in order to subscribe someone to the newsletter in case of HTTP method'), - 'newsletter_subscribe_http_mailfield': ugettext_lazy('Name of the field which should contain the email value in the PHP data structure'), - 'newsletter_subscribe_http_url': ugettext_lazy('HTTP URL for newsletter subscription'), - 'newsletter_subscribe_mail_subject': ugettext_lazy('Email subject for newsletter subscription command'), - 'newsletter_subscribe_mail_from': ugettext_lazy('FROM field for newsletter subscription command'), - 'newsletter_subscribe_mail_to': ugettext_lazy('TO field for newsletter subscription command'), - 'newsletter_subscribe_method': ugettext_lazy('Newsletter subscription method'), - 'published': ugettext_lazy('Puslibhed'), - 'newsletter_text': ugettext_lazy('Form label text of newsletter subscription checkbox'), - 'sign_form_footer': ugettext_lazy('Sign form footer text'), - 'org_twitter_handle': ugettext_lazy('Organization Twitter handle'), - 'use_custom_email_settings': ugettext_lazy('Use custom e-mail settings?'), - 'confirmation_email_reply': ugettext_lazy('Confirmation email Reply-to address'), - 'newsletter_subscribe_mail_smtp_host': ugettext_lazy('SMTP server hostname'), - 'newsletter_subscribe_mail_smtp_port': ugettext_lazy('SMTP port'), - 'newsletter_subscribe_mail_smtp_user': ugettext_lazy('SMTP username'), - 'newsletter_subscribe_mail_smtp_password': ugettext_lazy('SMTP password'), - 'newsletter_subscribe_mail_smtp_tls': ugettext_lazy('SMTP via TLS?'), - 'newsletter_subscribe_mail_smtp_starttls': ugettext_lazy('SMTP via STARTTLS?'), + 'name': gettext_lazy('Petition template name'), + 'text': gettext_lazy('Petition text'), + 'side_text': gettext_lazy('Side text, on top of form'), + 'target': gettext_lazy('Signature target number'), + 'linear_gradient_direction': gettext_lazy('Direction of linear gradient for background color'), + 'gradient_from': gettext_lazy('Source color for linear gradient'), + 'gradient_to': gettext_lazy('Destinatoin color for linear gradient'), + 'bgcolor': gettext_lazy('Color for monochrome background color'), + 'footer_text': gettext_lazy('Footer text'), + 'footer_links': gettext_lazy('Footer links'), + 'twitter_description': gettext_lazy('Description for Twitter/Facebook cards'), + 'twitter_image': gettext_lazy('Picture for Twitter/Facebook cards'), + 'has_newsletter': gettext_lazy('Is the petition associated with a newsletter?'), + 'newsletter_subscribe_http_data': gettext_lazy('Data structure to be sent in order to subscribe someone to the newsletter in case of HTTP method'), + 'newsletter_subscribe_http_mailfield': gettext_lazy('Name of the field which should contain the email value in the PHP data structure'), + 'newsletter_subscribe_http_url': gettext_lazy('HTTP URL for newsletter subscription'), + 'newsletter_subscribe_mail_subject': gettext_lazy('Email subject for newsletter subscription command'), + 'newsletter_subscribe_mail_from': gettext_lazy('FROM field for newsletter subscription command'), + 'newsletter_subscribe_mail_to': gettext_lazy('TO field for newsletter subscription command'), + 'newsletter_subscribe_method': gettext_lazy('Newsletter subscription method'), + 'published': gettext_lazy('Puslibhed'), + 'newsletter_text': gettext_lazy('Form label text of newsletter subscription checkbox'), + 'sign_form_footer': gettext_lazy('Sign form footer text'), + 'org_twitter_handle': gettext_lazy('Organization Twitter handle'), + 'use_custom_email_settings': gettext_lazy('Use custom e-mail settings?'), + 'confirmation_email_reply': gettext_lazy('Confirmation email Reply-to address'), + 'newsletter_subscribe_mail_smtp_host': gettext_lazy('SMTP server hostname'), + 'newsletter_subscribe_mail_smtp_port': gettext_lazy('SMTP port'), + 'newsletter_subscribe_mail_smtp_user': gettext_lazy('SMTP username'), + 'newsletter_subscribe_mail_smtp_password': gettext_lazy('SMTP password'), + 'newsletter_subscribe_mail_smtp_tls': gettext_lazy('SMTP via TLS?'), + 'newsletter_subscribe_mail_smtp_starttls': gettext_lazy('SMTP via STARTTLS?'), } @@ -297,22 +297,22 @@ class PetitionTemplateAdmin(admin.ModelAdmin): #change_form_template = 'petition/petition_change_form.html' form = PetitionTemplateForm fieldsets = ( - (ugettext_lazy('To whom is this petition template?'), + (gettext_lazy('To whom is this petition template?'), { 'fields': ('org', 'user') } ), - (ugettext_lazy('Content of the petition'), + (gettext_lazy('Content of the petition'), { 'fields': ('name', 'text', 'side_text', 'footer_text', 'footer_links', 'sign_form_footer', 'target') } ), - (ugettext_lazy('Background color'), + (gettext_lazy('Background color'), { 'fields': ('linear_gradient_direction', 'gradient_from', 'gradient_to', 'bgcolor') } ), - (ugettext_lazy('Setup of the newsletter associated to the petition'), + (gettext_lazy('Setup of the newsletter associated to the petition'), { 'fields': ('has_newsletter', 'newsletter_text', 'newsletter_subscribe_method', 'newsletter_subscribe_http_data', 'newsletter_subscribe_http_mailfield', @@ -323,12 +323,12 @@ class PetitionTemplateAdmin(admin.ModelAdmin): 'newsletter_subscribe_mail_smtp_tls', 'newsletter_subscribe_mail_smtp_starttls') } ), - (ugettext_lazy('Confirmation email setup'), + (gettext_lazy('Confirmation email setup'), { 'fields': ('confirmation_email_reply', ) } ), - (ugettext_lazy('Petition meta-data for social networks'), + (gettext_lazy('Petition meta-data for social networks'), { 'fields': ('twitter_description', 'twitter_image', 'org_twitter_handle') }), diff --git a/pytition/petition/forms.py b/pytition/petition/forms.py index 56691fdf..6352eb1b 100644 --- a/pytition/petition/forms.py +++ b/pytition/petition/forms.py @@ -1,6 +1,6 @@ from django.forms import ModelForm, ValidationError from django import forms -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from django.contrib.auth.forms import UserCreationForm, UsernameField from django.contrib.auth import get_user_model from django.utils.text import slugify diff --git a/pytition/petition/helpers.py b/pytition/petition/helpers.py index b1003906..291ef245 100644 --- a/pytition/petition/helpers.py +++ b/pytition/petition/helpers.py @@ -7,7 +7,7 @@ from django.template.loader import render_to_string from django.utils.html import strip_tags from django.core.mail import get_connection, EmailMultiAlternatives, EmailMessage -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from django.contrib.auth.models import User # Remove all moderated instances of Petition diff --git a/pytition/petition/models.py b/pytition/petition/models.py index 3a63b4fb..0da3a088 100644 --- a/pytition/petition/models.py +++ b/pytition/petition/models.py @@ -1,8 +1,8 @@ from django.db import models from django.utils.html import mark_safe, strip_tags from django.utils.text import slugify -from django.utils.translation import ugettext as _ -from django.utils.translation import ugettext_lazy +from django.utils.translation import gettext as _ +from django.utils.translation import gettext_lazy from django.core.exceptions import ValidationError from django.db.models.signals import post_save, post_delete, pre_save from django.dispatch import receiver @@ -25,7 +25,7 @@ class PytitionUser(models.Model): user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="pytitionuser") invitations = models.ManyToManyField('Organization', related_name="invited", blank=True) - default_template = models.ForeignKey('PetitionTemplate', blank=True, null=True, related_name='+', verbose_name=ugettext_lazy("Default petition template"), to_field='id', on_delete=models.SET_NULL) + default_template = models.ForeignKey('PetitionTemplate', blank=True, null=True, related_name='+', verbose_name=gettext_lazy("Default petition template"), to_field='id', on_delete=models.SET_NULL) moderated = models.BooleanField(default=False) def drop(self): @@ -85,8 +85,8 @@ def __repr__(self): # --------------------------------- Organization ------------------------------ class Organization(models.Model): - name = models.CharField(max_length=200, verbose_name=ugettext_lazy("Name"), unique=True, null=False, blank=False) - default_template = models.ForeignKey('PetitionTemplate', blank=True, null=True, related_name='+', verbose_name=ugettext_lazy("Default petition template"), to_field='id', on_delete=models.SET_NULL) + name = models.CharField(max_length=200, verbose_name=gettext_lazy("Name"), unique=True, null=False, blank=False) + default_template = models.ForeignKey('PetitionTemplate', blank=True, null=True, related_name='+', verbose_name=gettext_lazy("Default petition template"), to_field='id', on_delete=models.SET_NULL) slugname = models.SlugField(max_length=200, unique=True) members = models.ManyToManyField(PytitionUser, through='Permission') @@ -173,7 +173,7 @@ class Petition(models.Model): ) # Description - title = models.TextField(verbose_name=ugettext_lazy("Title")) + title = models.TextField(verbose_name=gettext_lazy("Title")) text = tinymce_models.HTMLField(blank=True) side_text = tinymce_models.HTMLField(blank=True) target = models.IntegerField(default=500) @@ -438,15 +438,15 @@ def moderate(self, do_moderate=True): # --------------------------------- Signature --------------------------------- class Signature(models.Model): - first_name = models.CharField(max_length=50, verbose_name=ugettext_lazy("First name")) - last_name = models.CharField(max_length=50, verbose_name=ugettext_lazy("Last name")) - phone = PhoneNumberField(max_length=20, blank=True, verbose_name=ugettext_lazy("Phone number")) - email = models.EmailField(verbose_name=ugettext_lazy("Email address")) + first_name = models.CharField(max_length=50, verbose_name=gettext_lazy("First name")) + last_name = models.CharField(max_length=50, verbose_name=gettext_lazy("Last name")) + phone = PhoneNumberField(max_length=20, blank=True, verbose_name=gettext_lazy("Phone number")) + email = models.EmailField(verbose_name=gettext_lazy("Email address")) confirmation_hash = models.CharField(max_length=128) - confirmed = models.BooleanField(default=False, verbose_name=ugettext_lazy("Confirmed")) - petition = models.ForeignKey(Petition, on_delete=models.CASCADE, verbose_name=ugettext_lazy("Petition")) - subscribed_to_mailinglist = models.BooleanField(default=False, verbose_name=ugettext_lazy("Subscribed to mailing list")) - date = models.DateTimeField(blank=True, auto_now_add=True, verbose_name=ugettext_lazy("Date")) + confirmed = models.BooleanField(default=False, verbose_name=gettext_lazy("Confirmed")) + petition = models.ForeignKey(Petition, on_delete=models.CASCADE, verbose_name=gettext_lazy("Petition")) + subscribed_to_mailinglist = models.BooleanField(default=False, verbose_name=gettext_lazy("Subscribed to mailing list")) + date = models.DateTimeField(blank=True, auto_now_add=True, verbose_name=gettext_lazy("Date")) ipaddress = models.TextField(blank=True, null=True) def clean(self): @@ -501,7 +501,7 @@ class PetitionTemplate(models.Model): ) # Description - name = models.CharField(max_length=50, verbose_name=ugettext_lazy("Name")) + name = models.CharField(max_length=50, verbose_name=gettext_lazy("Name")) text = tinymce_models.HTMLField(blank=True) side_text = tinymce_models.HTMLField(blank=True) target = models.IntegerField(blank=True, null=True) @@ -580,8 +580,8 @@ def __repr__(self): # ------------------------------------ Permission ----------------------------- class Permission(models.Model): - organization = models.ForeignKey(Organization, on_delete=models.CASCADE, verbose_name=ugettext_lazy("Organization related to these permissions")) - user = models.ForeignKey(PytitionUser, on_delete=models.CASCADE, verbose_name=ugettext_lazy("User related to these permissions")) + organization = models.ForeignKey(Organization, on_delete=models.CASCADE, verbose_name=gettext_lazy("Organization related to these permissions")) + user = models.ForeignKey(PytitionUser, on_delete=models.CASCADE, verbose_name=gettext_lazy("User related to these permissions")) can_add_members = models.BooleanField(default=False) can_remove_members = models.BooleanField(default=False) can_create_petitions = models.BooleanField(default=True) @@ -655,7 +655,7 @@ def post_delete_user(sender, instance, *args, **kwargs): # ------------------------------------ ModerationReason ----------------------------- class ModerationReason(models.Model): - msg = models.TextField(verbose_name=ugettext_lazy("message")) + msg = models.TextField(verbose_name=gettext_lazy("message")) visible = models.BooleanField(default=True) class Moderation(models.Model): diff --git a/pytition/petition/views.py b/pytition/petition/views.py index a8877466..5ada3257 100644 --- a/pytition/petition/views.py +++ b/pytition/petition/views.py @@ -9,7 +9,7 @@ from django.http import Http404, HttpResponse, HttpResponseForbidden, JsonResponse from django.conf import settings from django.core.exceptions import ValidationError -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from django.contrib import messages from django.contrib.messages import get_messages from django.utils.html import format_html @@ -1805,4 +1805,4 @@ def report_petition(request, petition_id, reason_id=None): Moderation.objects.create(petition=petition, reason=reason) else: Moderation.objects.create(petition=petition) - return HttpResponse(status=200) \ No newline at end of file + return HttpResponse(status=200) From 2b8e9dbb76c3dd3bba10215a0d65445dd40d75eb Mon Sep 17 00:00:00 2001 From: Yann Sionneau Date: Sat, 10 Jun 2023 18:09:16 +0200 Subject: [PATCH 05/23] Update django-colorfield for Django 4.x --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 108814ff..55cb5533 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ Django~=4.2.0 -django-colorfield==0.1.15 +django-colorfield==0.8.0 django-tinymce==3.5.0 django-mailer==1.2.6 django-maintenance-mode From e9bdc0ac72573be63ebdc0cad3701cc28a8f88b1 Mon Sep 17 00:00:00 2001 From: Yann Sionneau Date: Sat, 10 Jun 2023 18:14:30 +0200 Subject: [PATCH 06/23] Update urls for Django 4.x --- pytition/petition/urls.py | 2 +- pytition/pytition/urls.py | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pytition/petition/urls.py b/pytition/petition/urls.py index cc8625a1..2182997a 100644 --- a/pytition/petition/urls.py +++ b/pytition/petition/urls.py @@ -1,4 +1,4 @@ -from django.conf.urls import include +from django.urls import include from django.urls import path from . import views diff --git a/pytition/pytition/urls.py b/pytition/pytition/urls.py index c1206100..83f82f2c 100644 --- a/pytition/pytition/urls.py +++ b/pytition/pytition/urls.py @@ -13,17 +13,17 @@ 1. Import the include() function: from django.conf.urls import url, include 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) """ -from django.conf.urls import url, include +from django.urls import include, re_path from django.contrib import admin from petition.views import index from django.conf import settings from django.conf.urls.static import static urlpatterns = [ - url(r'^$', index, name="index"), - url(r'^petition/', include('petition.urls')), - url(r'^admin/', admin.site.urls), - url(r'^tinymce/', include('tinymce.urls')), - url(r'^i18n/', include('django.conf.urls.i18n')), - url(r'^maintenance-mode/', include('maintenance_mode.urls')), + re_path(r'^$', index, name="index"), + re_path(r'^petition/', include('petition.urls')), + re_path(r'^admin/', admin.site.urls), + re_path(r'^tinymce/', include('tinymce.urls')), + re_path(r'^i18n/', include('django.conf.urls.i18n')), + re_path(r'^maintenance-mode/', include('maintenance_mode.urls')), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) From da4e3c2e8987a98c768dff239351ed93781b99b5 Mon Sep 17 00:00:00 2001 From: Yann Sionneau Date: Sun, 11 Jun 2023 13:55:05 +0200 Subject: [PATCH 07/23] Fix Jenkinsfile for recent jenkins/debian --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 84ec2939..ff6f0fa5 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -9,7 +9,7 @@ node { sh ''' cd $WORKSPACE rm -rf venv && python3.8 -m venv venv -source venv/bin/activate +. venv/bin/activate pip3 install -r requirements_dev.txt cat < my.cnf [client] From fddeefc68924f59f80b97b58b798305885deb57b Mon Sep 17 00:00:00 2001 From: Yann Sionneau Date: Sun, 11 Jun 2023 13:55:20 +0200 Subject: [PATCH 08/23] Fix color picker test --- pytition/petition/tests/tests_EditPetitionView.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pytition/petition/tests/tests_EditPetitionView.py b/pytition/petition/tests/tests_EditPetitionView.py index ef1f4734..30168f06 100644 --- a/pytition/petition/tests/tests_EditPetitionView.py +++ b/pytition/petition/tests/tests_EditPetitionView.py @@ -387,9 +387,9 @@ def test_edit_template_POST_style_form(self): self.assertTemplateUsed(response, "petition/edit_petition.html") p2.refresh_from_db() - style_form_data['bgcolor'] = '#' + style_form_data['bgcolor'] - style_form_data['gradient_from'] = '#' + style_form_data['gradient_from'] - style_form_data['gradient_to'] = '#' + style_form_data['gradient_to'] + style_form_data['bgcolor'] = style_form_data['bgcolor'] + style_form_data['gradient_from'] = style_form_data['gradient_from'] + style_form_data['gradient_to'] = style_form_data['gradient_to'] for key, value in style_form_data.items(): if key == "style_form_submitted": continue From 00976bef3b2b28756bac86e28496ae554ab159b2 Mon Sep 17 00:00:00 2001 From: Yann Sionneau Date: Sun, 11 Jun 2023 13:55:40 +0200 Subject: [PATCH 09/23] Django 4.x requires psycopg 3.1.8 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 127dc22c..b3ff0a95 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,7 +13,7 @@ RUN mkdir /mediaroot WORKDIR /code COPY requirements.txt requirements_dev.txt /code/ RUN pip install -r requirements_dev.txt -RUN pip install psycopg2-binary==2.8.4 +RUN pip install "psycopg[binary]==3.1.8" COPY . /code/ COPY pytition/pytition/settings/config_example.py /config/docker_config.py RUN touch /config/__init__.py From 97794e9da2f189e4ac1711e981a7e778eb4f03c9 Mon Sep 17 00:00:00 2001 From: Yann Sionneau Date: Sun, 11 Jun 2023 14:13:56 +0200 Subject: [PATCH 10/23] Jenkins server has been updated to Debian 12, now Python is 3.11 by default which is supported by Django 4.2 --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index ff6f0fa5..dd56a4bd 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -8,7 +8,7 @@ node { sh ''' cd $WORKSPACE -rm -rf venv && python3.8 -m venv venv +rm -rf venv && python3 -m venv venv . venv/bin/activate pip3 install -r requirements_dev.txt cat < my.cnf From 67114b165317f0b46d9ea8df4ac1fc8a967832a3 Mon Sep 17 00:00:00 2001 From: Yann Sionneau Date: Sun, 11 Jun 2023 15:39:10 +0200 Subject: [PATCH 11/23] Update Dependencies in README.md --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index bb3c7524..e5268414 100644 --- a/README.md +++ b/README.md @@ -54,14 +54,14 @@ Those are external projects that are needed and used by Pytition, but included i ## Dependencies -* Python 3 -* Django 2.2.x -* django-tinymce 2.8.0 -* django-colorfield 0.1.15 +* Python 3.8 up to 3.11 +* Django 4.2.x +* django-tinymce 3.5.0 +* django-colorfield 0.8.0 * requests 2.20.x -* mysqlclient 1.3.13 +* mysqlclient 2.0.1 * beautifulsoup4 4.6.3 -* django-formtools 2.1 +* django-formtools 2.2 * bcrypt ## Translations From 069239f43c9a8675d3b7877b977be134c763ed3a Mon Sep 17 00:00:00 2001 From: Yann Sionneau Date: Fri, 28 Jul 2023 18:48:36 +0200 Subject: [PATCH 12/23] Specify default AutoField type to avoid unwanted future migrations This is needed since Django 3.2 --- pytition/pytition/settings/base.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pytition/pytition/settings/base.py b/pytition/pytition/settings/base.py index aff4ac86..b66d0f76 100644 --- a/pytition/pytition/settings/base.py +++ b/pytition/pytition/settings/base.py @@ -84,6 +84,7 @@ ] WSGI_APPLICATION = 'pytition.wsgi.application' +DEFAULT_AUTO_FIELD = "django.db.models.AutoField" if os.environ.get('USE_POSTGRESQL'): from .pgsql import DATABASES From 23a97537ab70545b66634bce7a8a255f28ddf2e0 Mon Sep 17 00:00:00 2001 From: Yann Sionneau Date: Wed, 9 Aug 2023 10:01:07 +0200 Subject: [PATCH 13/23] Update requirements.txt Update Django-TinyMCE to 3.6.1 which updates TinyMCE from 5.10.1 to 5.10.7 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 55cb5533..2ea4d3fa 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ Django~=4.2.0 django-colorfield==0.8.0 -django-tinymce==3.5.0 +django-tinymce==3.6.1 django-mailer==1.2.6 django-maintenance-mode django-phonenumber-field[phonenumbers]==6.3.0 From c37629925b461c87d9d12c09f18f529222905d07 Mon Sep 17 00:00:00 2001 From: Yann Sionneau Date: Wed, 9 Aug 2023 10:40:40 +0200 Subject: [PATCH 14/23] Remove references to TINYMCE_JS_URL. We now use the JS provided by django-tinymce package. --- dev/INSTALL.md | 3 +-- doc/configuration.rst | 2 -- doc/installation.rst | 2 -- doc/multi-domain-install.rst | 2 -- pytition/pytition/settings/base.py | 3 --- pytition/pytition/settings/config_example.py | 4 ---- 6 files changed, 1 insertion(+), 15 deletions(-) diff --git a/dev/INSTALL.md b/dev/INSTALL.md index 4e542f24..9dceab4e 100644 --- a/dev/INSTALL.md +++ b/dev/INSTALL.md @@ -24,9 +24,8 @@ In a production environment you should modify the following settings: ### Setup your customization -You can customize the TinyMCE variables: +You can customize the TinyMCE editor via this variable: -* TINYMCE_JS_URL * TINYMCE_DEFAULT_CONFIG ### Setup mysql credentials diff --git a/doc/configuration.rst b/doc/configuration.rst index 147e4fc3..5948cc05 100644 --- a/doc/configuration.rst +++ b/doc/configuration.rst @@ -13,8 +13,6 @@ You **must** set the following variables: .. automodule:: pytition.settings.config_example :members: -.. warning:: The ``TINYMCE_JS_URL`` setting must be present in your config file if you modified the ``STATIC_URL`` setting from its default value (``/static/``), either before of after the ``DO NOT EDIT AFTER THIS BANNER``. It is already present in the config_example.py file. - Not mandatory but important settings ==================================== diff --git a/doc/installation.rst b/doc/installation.rst index e2d78d0a..24bf2723 100644 --- a/doc/installation.rst +++ b/doc/installation.rst @@ -125,8 +125,6 @@ Those are: * DATABASES * ALLOWED_HOSTS -.. warning:: If you do not use the ``config_example.py`` sample file as a base for your config, do NOT forget to also set ``TINYMCE_JS_URL``. Most likely you will just need to set it to ``STATIC_URL + TINYMCE_JS_PATH`` - .. note:: Do not forget to put a correct path to your `my.cnf` MySQL credential file in your config `DATABASES` setting. Initialize Pytition project database. Pay attention to be in your virtualenv to enter the following commands: diff --git a/doc/multi-domain-install.rst b/doc/multi-domain-install.rst index 06046d3b..aa4b8a09 100644 --- a/doc/multi-domain-install.rst +++ b/doc/multi-domain-install.rst @@ -125,8 +125,6 @@ Those are: * DATABASES * ALLOWED_HOSTS -.. warning:: If you do not use the ``config_example.py`` sample file as a base for your config, do NOT forget to also set ``TINYMCE_JS_URL``. Most likely you will just need to set it to ``STATIC_URL + TINYMCE_JS_PATH`` - .. warning:: Pay attention to the following config values: .. code-block:: none diff --git a/pytition/pytition/settings/base.py b/pytition/pytition/settings/base.py index b66d0f76..d90c024b 100644 --- a/pytition/pytition/settings/base.py +++ b/pytition/pytition/settings/base.py @@ -155,11 +155,8 @@ STATIC_ROOT = os.environ.get('STATIC_ROOT') LOGIN_URL = '/petition/login/' -TINYMCE_JS_PATH = '/vendor/tinymce/js/tinymce/tinymce.min.js' -TINYMCE_JS_URL = STATIC_URL + TINYMCE_JS_PATH TINYMCE_DEFAULT_CONFIG = { 'plugins': 'print preview fullpage searchreplace autolink directionality visualblocks visualchars fullscreen image link media template codesample table charmap hr pagebreak nonbreaking anchor toc insertdatetime advlist lists textcolor wordcount imagetools contextmenu colorpicker textpattern help', - 'theme': "modern", 'cleanup_on_startup': True, 'custom_undo_redo_levels': 10, 'toolbar1': 'formatselect | bold italic strikethrough forecolor backcolor | link | alignleft aligncenter alignright alignjustify | numlist bullist outdent indent | removeformat | fontselect | fontsizeselect', diff --git a/pytition/pytition/settings/config_example.py b/pytition/pytition/settings/config_example.py index 188792ad..9924e460 100644 --- a/pytition/pytition/settings/config_example.py +++ b/pytition/pytition/settings/config_example.py @@ -152,10 +152,6 @@ import os -# This needs to be redefined because STATIC_URL might be set in this config -# after TINYMCE_JS_URL was defined -TINYMCE_JS_URL = STATIC_URL + TINYMCE_JS_PATH - if DEFAULT_INDEX_THUMBNAIL == "": print("Please set a default index thumbnail or your index page will not be very beautiful") From 4ae61c7f738a0e7cbd62f2211ff0e38dfccbd277 Mon Sep 17 00:00:00 2001 From: Yann Sionneau Date: Sat, 30 Sep 2023 11:41:27 +0200 Subject: [PATCH 15/23] Fix signature confirmation link sent by e-mail The link was wrong in case Pytition was not installed at the root of the webserver, which is what happens on YunoHost. for instance if it's in http://domain.com/pytition/ instead of directly in http://domain.com/ One must use `reverse()` which takes care of adding the `script_prefix` and not just put a hand-crafted relative uri as argument to `build_absolute_uri()` --- pytition/petition/helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytition/petition/helpers.py b/pytition/petition/helpers.py index 291ef245..29592230 100644 --- a/pytition/petition/helpers.py +++ b/pytition/petition/helpers.py @@ -93,7 +93,7 @@ def footer_content_processor(request): # Send Confirmation email def send_confirmation_email(request, signature): petition = signature.petition - url = request.build_absolute_uri("/petition/{}/confirm/{}".format(petition.id, signature.confirmation_hash)) + url = request.build_absolute_uri(reverse("confirm", args=[petition.id, signature.confirmation_hash])) html_message = render_to_string("petition/confirmation_email.html", {'firstname': signature.first_name, 'url': url}) message = strip_tags(html_message) with get_connection() as connection: From db9878681b30927b97c8d80064caca074fa1a285 Mon Sep 17 00:00:00 2001 From: Yann Sionneau Date: Sat, 30 Sep 2023 17:17:56 +0200 Subject: [PATCH 16/23] Fix petition edit page showing the 'style & apparence' pane by default This was because the logic was to show the first pane containing errors. And the fields of the style pane were not declared as optional in the StyleForm. Therefore the fields were marked as "errors" "this field is required". Mark those fields as non-required. --- pytition/petition/forms.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pytition/petition/forms.py b/pytition/petition/forms.py index 6352eb1b..f75b2cf1 100644 --- a/pytition/petition/forms.py +++ b/pytition/petition/forms.py @@ -184,10 +184,10 @@ def clean(self): class StyleForm(forms.Form): ### Graphical UI style info of Petition ### - bgcolor = forms.CharField(widget=ColorWidget) - linear_gradient_direction = forms.ChoiceField(choices=Petition.LINEAR_GRADIENT_CHOICES) - gradient_from = forms.CharField(widget=ColorWidget) - gradient_to = forms.CharField(widget=ColorWidget) + bgcolor = forms.CharField(widget=ColorWidget, required=False) + linear_gradient_direction = forms.ChoiceField(choices=Petition.LINEAR_GRADIENT_CHOICES, required=False) + gradient_from = forms.CharField(widget=ColorWidget, required=False) + gradient_to = forms.CharField(widget=ColorWidget, required=False) class PytitionUserCreationForm(UserCreationForm): From 4de660ddc66128fc861a0b75827cffe8832ea1ee Mon Sep 17 00:00:00 2001 From: Yann Sionneau Date: Sat, 30 Sep 2023 17:20:25 +0200 Subject: [PATCH 17/23] Fix missing style_form_submitted initialization for edit_petition view --- pytition/petition/views.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pytition/petition/views.py b/pytition/petition/views.py index 5ada3257..d96900c7 100644 --- a/pytition/petition/views.py +++ b/pytition/petition/views.py @@ -1226,6 +1226,7 @@ def edit_petition(request, petition_id): 'email_form_submitted': False, 'social_network_form_submitted': False, 'newsletter_form_submitted': False, + 'style_form_submitted': False, } if request.method == "POST": From 366e75e1031b8b19303ca819319ed925b7eddc7f Mon Sep 17 00:00:00 2001 From: Yann Sionneau Date: Sat, 30 Sep 2023 17:20:50 +0200 Subject: [PATCH 18/23] Update django-colorfield dependency to fix warning issue See: https://github.com/fabiocaccamo/django-colorfield/pull/145 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 2ea4d3fa..4a55e692 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ Django~=4.2.0 -django-colorfield==0.8.0 +django-colorfield==0.10.1 django-tinymce==3.6.1 django-mailer==1.2.6 django-maintenance-mode From d21df50665394b0f5db43eb080bbd54adb1db73a Mon Sep 17 00:00:00 2001 From: Yann Sionneau Date: Sun, 8 Oct 2023 22:42:47 +0200 Subject: [PATCH 19/23] Rework Signature model/form handling: hash generation should be part of the model, not the form. --- pytition/petition/forms.py | 11 ----------- pytition/petition/models.py | 3 +++ 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/pytition/petition/forms.py b/pytition/petition/forms.py index f75b2cf1..a5b0d1cc 100644 --- a/pytition/petition/forms.py +++ b/pytition/petition/forms.py @@ -10,7 +10,6 @@ from .widgets import SwitchField from .helpers import send_welcome_mail -import uuid import html from tinymce.widgets import TinyMCE from colorfield.fields import ColorWidget @@ -47,16 +46,6 @@ def __init__(self, petition=None, *args, **kwargs): else: self.fields['subscribed_to_mailinglist'].label = self.instance.petition.newsletter_text - def save(self, commit=True): - object = super().save(commit=False) - hashstring = str(uuid.uuid4()) - object.confirmation_hash = hashstring - object.confirmed = False - if commit: - object.save() - return object - - class PetitionCreationStep1(forms.Form): ### Ask for title ### title = forms.CharField(max_length=200) diff --git a/pytition/petition/models.py b/pytition/petition/models.py index 0da3a088..3ca9f9d8 100644 --- a/pytition/petition/models.py +++ b/pytition/petition/models.py @@ -19,6 +19,7 @@ from .helpers import sanitize_html import html +import uuid # ----------------------------------- PytitionUser ---------------------------- @@ -456,6 +457,8 @@ def clean(self): def save(self, *args, **kwargs): self.clean() + if not self.confirmation_hash: + self.confirmation_hash = str(uuid.uuid4()) if self.confirmed: # invalidating other signatures from same email Signature.objects.filter(petition=self.petition).filter(email=self.email)\ From 8225555580eb3c60e0f0df4b4478010705c8b055 Mon Sep 17 00:00:00 2001 From: Yann Sionneau Date: Fri, 13 Oct 2023 23:24:31 +0200 Subject: [PATCH 20/23] UI: show content tab as selected when landing on petition edit page The tab was shown as selected only when clicked, but since this is the default tab it should be shown as selected by default. --- pytition/petition/templates/petition/edit_petition.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pytition/petition/templates/petition/edit_petition.html b/pytition/petition/templates/petition/edit_petition.html index 9991cc1f..a2311b55 100644 --- a/pytition/petition/templates/petition/edit_petition.html +++ b/pytition/petition/templates/petition/edit_petition.html @@ -51,8 +51,8 @@ {% endif %}
- {% trans "Content" %} + {% trans "Content" %} {% trans "Style & Look" %} Date: Sat, 14 Oct 2023 11:47:20 +0200 Subject: [PATCH 21/23] translation: fixed issues in French translation --- pytition/locale/fr_FR/LC_MESSAGES/django.po | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pytition/locale/fr_FR/LC_MESSAGES/django.po b/pytition/locale/fr_FR/LC_MESSAGES/django.po index 500f1a27..dcb6574c 100644 --- a/pytition/locale/fr_FR/LC_MESSAGES/django.po +++ b/pytition/locale/fr_FR/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: Pytition\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-08-15 21:12+0200\n" -"PO-Revision-Date: 2022-08-15 21:15+0200\n" +"PO-Revision-Date: 2023-10-14 11:18+0200\n" "Last-Translator: Yann Sionneau \n" "Language-Team: French (France) \n" @@ -17,7 +17,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Poedit 2.3\n" +"X-Generator: Poedit 3.0.1\n" #: pytition/petition/admin.py:21 pytition/petition/models.py:87 #: pytition/petition/models.py:502 @@ -638,7 +638,7 @@ msgstr "Utilisateur lié à ces permissions" #: pytition/petition/models.py:655 msgid "message" -msgstr "Message" +msgstr "message" #: pytition/petition/templates/layouts/base.html:12 msgid "Homepage" @@ -2073,7 +2073,7 @@ msgstr "" #: pytition/petition/views.py:1724 msgid "Petition successfully transfered!" -msgstr "Permissions transférée avec succès !" +msgstr "Pétition transférée avec succès !" #: pytition/petition/views.py:1727 msgid "Something went wrong while transferring this petition." From 7e04ac7686553c68915d18a96aa3d6f1d5286d56 Mon Sep 17 00:00:00 2001 From: Yann Sionneau Date: Sat, 14 Oct 2023 11:48:43 +0200 Subject: [PATCH 22/23] Fixed error messages not showing in formulars This is a known unresolved issue in Bootstrap 4 See: https://github.com/twbs/bootstrap/issues/23454 --- pytition/petition/templates/petition/bs4_form.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytition/petition/templates/petition/bs4_form.html b/pytition/petition/templates/petition/bs4_form.html index 6c377cf0..1732ad05 100644 --- a/pytition/petition/templates/petition/bs4_form.html +++ b/pytition/petition/templates/petition/bs4_form.html @@ -23,7 +23,7 @@ {% render_field field|bootstrap class="is-invalid" %}
{% for error in field.errors %} -
+
{{ error }}
{% endfor %} From cab2284ba8cf9756e5ed2e93dc55a6a68ffd8aa6 Mon Sep 17 00:00:00 2001 From: Yann Sionneau Date: Sat, 14 Oct 2023 11:56:06 +0200 Subject: [PATCH 23/23] Fixed invalid error message saying text field was required --- pytition/petition/forms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytition/petition/forms.py b/pytition/petition/forms.py index a5b0d1cc..17dd77a2 100644 --- a/pytition/petition/forms.py +++ b/pytition/petition/forms.py @@ -94,7 +94,7 @@ class PetitionCreationStep3(forms.Form): class ContentFormGeneric(forms.Form): ### Content of a Petition ### - text = forms.CharField(widget=TinyMCE) + text = forms.CharField(widget=TinyMCE, required=False) target = forms.IntegerField(required=False) side_text = forms.CharField(widget=TinyMCE, required=False) footer_text = forms.CharField(widget=TinyMCE, required=False)