From 529ca6700d2088dcb5a82cd951e2bc5f7e176b4f Mon Sep 17 00:00:00 2001 From: Dirk Uys Date: Tue, 9 Apr 2024 16:47:06 +0200 Subject: [PATCH 01/24] bump Django major version and update other deps --- learnwithpeople/settings.py | 3 + requirements.txt | 148 +++++++++++++++++++----------------- 2 files changed, 80 insertions(+), 71 deletions(-) diff --git a/learnwithpeople/settings.py b/learnwithpeople/settings.py index c3c9fdbf..a5c4cf5c 100644 --- a/learnwithpeople/settings.py +++ b/learnwithpeople/settings.py @@ -342,6 +342,9 @@ # Explicitly set DEFAULT_AUTO_FIELD. Option added Django 3.2 DEFAULT_AUTO_FIELD = 'django.db.models.AutoField' +# Update for Django 4.0 - Keep on using pytz until it's deprecated +USE_DEPRECATED_PYTZ = True + #### Backup config #### BACKUP_DIR = os.environ.get('BACKUP_DIR', '/tmp') # Directory where backups will be stored locally diff --git a/requirements.txt b/requirements.txt index 515cb7c4..bc00c0eb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,80 +1,86 @@ -amqp==5.0.6 -asgiref==3.5.1 -async-generator==1.10 -attrs==21.2.0 -billiard==3.6.4.0 -bleach==4.1.0 -boto==2.49.0 -boto3==1.20.14 -botocore==1.23.14 -cachetools==4.2.4 -cairocffi==1.3.0 -CairoSVG==2.5.2 -celery==5.2.2 -certifi==2021.10.8 -cffi==1.15.0 -charset-normalizer==2.0.8 -click==8.0.3 -click-didyoumean==0.3.0 +aiohttp==3.9.3 +aiohttp-retry==2.8.3 +aiosignal==1.3.1 +amqp==5.2.0 +asgiref==3.8.1 +async-timeout==4.0.3 +attrs==23.2.0 +billiard==4.2.0 +bleach==5.0.1 +boto3==1.34.80 +botocore==1.34.80 +cachetools==5.3.3 +cairocffi==1.6.1 +CairoSVG==2.7.1 +celery==5.3.6 +certifi==2024.2.2 +cffi==1.16.0 +charset-normalizer==3.3.2 +click==8.1.7 +click-didyoumean==0.3.1 click-plugins==1.1.1 -click-repl==0.2.0 -crispy-bootstrap5==0.6 -cryptography==36.0.0 -cssselect==1.1.0 -cssselect2==0.4.1 -cssutils==2.3.0 +click-repl==0.3.0 +crispy-bootstrap5==0.7 +cssselect==1.2.0 +cssselect2==0.7.0 +cssutils==2.10.2 defusedxml==0.7.1 -dj-database-url==0.5.0 -Django==3.2.18 -django-bleach==1.0.0 -django-cors-headers==3.10.0 -django-crispy-forms==1.13.0 -django-filter==21.1 -django-phonenumber-field==6.0.0 -django-tinymce==3.4.0 -django-webpack-loader==1.8.1 -djangorestframework==3.12.4 -freezegun==1.1.0 -geonamescache==1.3.0 -gunicorn==20.1.0 -h11==0.12.0 -icalendar==4.0.9 -idna==3.3 -importlib-metadata==4.8.2 -jmespath==0.10.0 -kombu==5.2.2 -lxml==4.6.4 -Markdown==3.3.6 -outcome==1.1.0 -packaging==21.3 -phonenumberslite==8.12.38 -Pillow==8.4.0 +dj-database-url==2.1.0 +Django==4.0.10 +django-bleach==3.1.0 +django-cors-headers==4.3.1 +django-crispy-forms==2.0 +django-filter==23.5 +django-phonenumber-field==7.3.0 +django-tinymce==4.0.0 +django-webpack-loader==3.1.0 +djangorestframework==3.15.1 +exceptiongroup==1.2.0 +freezegun==1.4.0 +frozenlist==1.4.1 +geonamescache==2.0.0 +gunicorn==21.2.0 +h11==0.14.0 +icalendar==5.0.12 +idna==3.6 +importlib_metadata==7.1.0 +jmespath==1.0.1 +kombu==5.3.6 +lxml==5.2.1 +Markdown==3.6 +multidict==6.0.5 +outcome==1.3.0.post0 +packaging==24.0 +phonenumberslite==8.13.34 +pillow==10.3.0 premailer==3.10.0 -prompt-toolkit==3.0.23 -psycopg2-binary==2.9.3 -pycparser==2.21 -pygal==3.0.0 -PyJWT==2.3.0 -pyOpenSSL==21.0.0 -pyparsing==3.0.6 -python-dateutil==2.8.2 -pytz==2021.3 -requests==2.26.0 +prompt-toolkit==3.0.43 +psycopg2-binary==2.9.9 +pycparser==2.22 +pygal==3.0.4 +PyJWT==2.8.0 +PySocks==1.7.1 +python-dateutil==2.9.0.post0 +pytz==2024.1 +requests==2.31.0 s3-backup-rotate==0.3.3 -s3transfer==0.5.0 -selenium==4.1.0 +s3transfer==0.10.1 +selenium==4.19.0 six==1.16.0 -sniffio==1.2.0 +sniffio==1.3.1 sortedcontainers==2.4.0 -sqlparse==0.4.2 +sqlparse==0.4.4 tinycss2==1.1.1 -trio==0.19.0 -trio-websocket==0.9.2 -twilio==7.3.1 +trio==0.25.0 +trio-websocket==0.11.1 +twilio==9.0.4 +typing_extensions==4.11.0 +tzdata==2024.1 unicodecsv==0.14.1 -urllib3==1.26.7 -vine==5.0.0 -wcwidth==0.2.5 +urllib3==1.26.18 +vine==5.1.0 +wcwidth==0.2.13 webencodings==0.5.1 -wsproto==1.0.0 -zipp==3.6.0 +wsproto==1.2.0 +yarl==1.9.4 +zipp==3.18.1 From 2a7e5c9c172af5399f63fad64756b10d4f22a9e2 Mon Sep 17 00:00:00 2001 From: Dirk Uys Date: Tue, 9 Apr 2024 17:10:05 +0200 Subject: [PATCH 02/24] Update names for ugettext and ugettext_lazy --- announce/tasks.py | 2 +- community_calendar/forms.py | 2 +- community_calendar/views.py | 2 +- custom_registration/forms.py | 2 +- custom_registration/views.py | 5 ++++- studygroups/charts.py | 2 +- studygroups/decorators.py | 2 +- studygroups/forms.py | 2 +- studygroups/models/__init__.py | 2 +- studygroups/models/course.py | 4 ++-- studygroups/models/learningcircle.py | 2 +- studygroups/models/team.py | 2 +- studygroups/signals.py | 2 +- studygroups/tasks.py | 2 +- studygroups/views/facilitate.py | 2 +- studygroups/views/learner.py | 2 +- studygroups/views/organizer.py | 2 +- studygroups/views/staff.py | 2 +- surveys/views.py | 2 +- 19 files changed, 23 insertions(+), 20 deletions(-) diff --git a/announce/tasks.py b/announce/tasks.py index 082139b3..99146e74 100644 --- a/announce/tasks.py +++ b/announce/tasks.py @@ -4,7 +4,7 @@ from django.conf import settings from django.urls import reverse from studygroups.utils import render_to_string_ctx -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ import requests from requests.auth import HTTPBasicAuth diff --git a/community_calendar/forms.py b/community_calendar/forms.py index 283d04a6..55bfe28d 100644 --- a/community_calendar/forms.py +++ b/community_calendar/forms.py @@ -1,6 +1,6 @@ # coding=utf-8 from django import forms -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from django.utils import timezone from .models import Event diff --git a/community_calendar/views.py b/community_calendar/views.py index de46d316..59319a37 100644 --- a/community_calendar/views.py +++ b/community_calendar/views.py @@ -8,7 +8,7 @@ from django.utils import formats from django.utils import timezone from django.utils.decorators import method_decorator -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from django import http from .models import Event diff --git a/custom_registration/forms.py b/custom_registration/forms.py index bad03533..22a260f9 100644 --- a/custom_registration/forms.py +++ b/custom_registration/forms.py @@ -2,7 +2,7 @@ from django import forms from django.contrib.auth.models import User from django.contrib.auth.forms import PasswordResetForm -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from django.forms import ValidationError from django.contrib.auth import password_validation from django.contrib.auth.forms import UserCreationForm diff --git a/custom_registration/views.py b/custom_registration/views.py index 558714c2..a7a8bd3d 100644 --- a/custom_registration/views.py +++ b/custom_registration/views.py @@ -3,7 +3,7 @@ from django.urls import reverse, reverse_lazy from django.utils import timezone from django.utils.http import urlsafe_base64_decode -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from django.utils.decorators import method_decorator from django.views.decorators.csrf import csrf_exempt from django.views.decorators.debug import sensitive_post_parameters @@ -310,6 +310,7 @@ def delete(self, request, *args, **kwargs): user.username = random_username user.save() + # ?? delete learning circles if user is deleted? Should this maybe only happen for upcoming and draft lerning circles? for lc in StudyGroup.objects.active().filter(facilitator__user=user): if lc.facilitator_set.count() == 1: lc.deleted_at = timezone.now() @@ -319,6 +320,8 @@ def delete(self, request, *args, **kwargs): lc.save() + # TODO delete team membership + # delete profile data profile = user.profile profile.avatar = '' diff --git a/studygroups/charts.py b/studygroups/charts.py index bd8f804a..a0276898 100644 --- a/studygroups/charts.py +++ b/studygroups/charts.py @@ -13,7 +13,7 @@ from dateutil.relativedelta import relativedelta from pygal.style import Style -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from django.utils import timezone from django.conf import settings from collections import Counter diff --git a/studygroups/decorators.py b/studygroups/decorators.py index 681c6763..a0856049 100644 --- a/studygroups/decorators.py +++ b/studygroups/decorators.py @@ -4,7 +4,7 @@ from django.contrib.auth.decorators import login_required from django.urls import reverse from django import http -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from studygroups.models import StudyGroup from studygroups.models import Facilitator diff --git a/studygroups/forms.py b/studygroups/forms.py index e01e65de..845ecb03 100644 --- a/studygroups/forms.py +++ b/studygroups/forms.py @@ -2,7 +2,7 @@ from django import forms from django.conf import settings from django.conf.global_settings import LANGUAGES -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from django.utils import timezone from django.utils.text import slugify from django.contrib.auth.models import User diff --git a/studygroups/models/__init__.py b/studygroups/models/__init__.py index 89bebfec..29c015a3 100644 --- a/studygroups/models/__init__.py +++ b/studygroups/models/__init__.py @@ -5,7 +5,7 @@ from django.db.models import F from django.utils import timezone from dateutil.relativedelta import relativedelta -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from django.conf import settings from django.contrib.auth.models import User from django.urls import reverse # TODO ideally this shouldn't be in the model diff --git a/studygroups/models/course.py b/studygroups/models/course.py index 3d5c4654..09af51e9 100644 --- a/studygroups/models/course.py +++ b/studygroups/models/course.py @@ -4,7 +4,7 @@ from django.utils import timezone from django.contrib.auth.models import User from django.db.models import F -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from django.core.paginator import Paginator from django.utils.translation import get_language_info @@ -43,7 +43,7 @@ class Course(LifeTimeTrackingModel): caption = models.CharField(max_length=500) on_demand = models.BooleanField(default=False) keywords = models.CharField(max_length=500, blank=True) - topic_guides = models.ManyToManyField(TopicGuide, blank=True, null=True) + topic_guides = models.ManyToManyField(TopicGuide, blank=True) language = models.CharField(max_length=6) # ISO language code created_by = models.ForeignKey(User, blank=True, null=True, on_delete=models.CASCADE) # TODO maybe rename to added_by unlisted = models.BooleanField(default=False) diff --git a/studygroups/models/learningcircle.py b/studygroups/models/learningcircle.py index 03f5030e..ed2e1180 100644 --- a/studygroups/models/learningcircle.py +++ b/studygroups/models/learningcircle.py @@ -1,7 +1,7 @@ # coding=utf-8 from django.db import models from django.utils import timezone -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from django.utils.text import slugify from django.core.serializers.json import DjangoJSONEncoder from django.conf import settings diff --git a/studygroups/models/team.py b/studygroups/models/team.py index 491b644d..052ea4a1 100644 --- a/studygroups/models/team.py +++ b/studygroups/models/team.py @@ -1,5 +1,5 @@ from django.db import models -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from django.contrib.auth.models import User from django.db import IntegrityError from django.conf import settings diff --git a/studygroups/signals.py b/studygroups/signals.py index 1bfa076f..050b9523 100644 --- a/studygroups/signals.py +++ b/studygroups/signals.py @@ -4,7 +4,7 @@ from django.core.mail import EmailMultiAlternatives, send_mail from django.conf import settings from django.utils import timezone -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from studygroups.email_helper import render_html_with_css diff --git a/studygroups/tasks.py b/studygroups/tasks.py index 765442c3..278fd123 100644 --- a/studygroups/tasks.py +++ b/studygroups/tasks.py @@ -5,7 +5,7 @@ from django.conf import settings from django.utils import timezone from django.utils import translation -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from django.contrib.auth.models import User from django.core.mail import EmailMultiAlternatives from django.urls import reverse diff --git a/studygroups/views/facilitate.py b/studygroups/views/facilitate.py index 23de26cc..74923ed6 100644 --- a/studygroups/views/facilitate.py +++ b/studygroups/views/facilitate.py @@ -17,7 +17,7 @@ from django.contrib.auth.decorators import login_required from django.contrib import messages from django.db.models import Q -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from django.utils import timezone from django.utils.decorators import method_decorator from django.core.mail import EmailMultiAlternatives diff --git a/studygroups/views/learner.py b/studygroups/views/learner.py index da55c7b0..c30781b5 100644 --- a/studygroups/views/learner.py +++ b/studygroups/views/learner.py @@ -12,7 +12,7 @@ from django.views.decorators.http import require_http_methods from django.views.decorators.csrf import csrf_exempt from django.utils import timezone -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from django.utils.text import slugify from django.views.generic import ListView, DetailView from django.views.generic.edit import FormView diff --git a/studygroups/views/organizer.py b/studygroups/views/organizer.py index 4c028f84..db8054a8 100644 --- a/studygroups/views/organizer.py +++ b/studygroups/views/organizer.py @@ -11,7 +11,7 @@ from django.utils.decorators import method_decorator from django.views.decorators.csrf import csrf_exempt from django.utils import timezone -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from django.views.generic.base import View from django.views.generic.base import TemplateView from django.views.generic.edit import CreateView, DeleteView, FormView, UpdateView diff --git a/studygroups/views/staff.py b/studygroups/views/staff.py index 866d423b..823ecc2e 100644 --- a/studygroups/views/staff.py +++ b/studygroups/views/staff.py @@ -11,7 +11,7 @@ from django.conf import settings from django.utils import timezone from django.utils.decorators import method_decorator -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from django.views.generic.base import View from django.views.generic import ListView from django.views.generic import TemplateView diff --git a/surveys/views.py b/surveys/views.py index 9d341f05..763ff17a 100644 --- a/surveys/views.py +++ b/surveys/views.py @@ -10,7 +10,7 @@ from django.conf import settings from django.utils import timezone from django.utils.decorators import method_decorator -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from django.views.generic.base import View from django.views.generic import ListView from django.views.generic import TemplateView From ec8e3d8a8b7650844c6c2e0d5f537b04eb09bb5e Mon Sep 17 00:00:00 2001 From: Dirk Uys Date: Tue, 9 Apr 2024 17:40:46 +0200 Subject: [PATCH 03/24] Update CSRF_TRUSTED_ORIGINS with protocol for Django >= 4.0 --- learnwithpeople/settings.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/learnwithpeople/settings.py b/learnwithpeople/settings.py index a5c4cf5c..c9489eb0 100644 --- a/learnwithpeople/settings.py +++ b/learnwithpeople/settings.py @@ -211,13 +211,13 @@ # Exempt trusted domains CSRF_TRUSTED_ORIGINS = [ - '.p2pu.org', + 'https://*.p2pu.org', ] if DEBUG: CSRF_TRUSTED_ORIGINS += [ - 'localhost:8000', - 'localhost:3001', - 'localhost:4000', + 'http://localhost:8000', + 'http://localhost:3001', + 'http://localhost:4000', ] # CORS config From 8e8514807bd0848e71028251bdcb3ecdfa51e7cd Mon Sep 17 00:00:00 2001 From: Dirk Uys Date: Tue, 9 Apr 2024 17:46:58 +0200 Subject: [PATCH 04/24] Remove deprecated url function from urls.py --- announce/urls.py | 6 +- client_logging/urls.py | 4 +- community_calendar/api_urls.py | 6 +- community_calendar/urls.py | 10 +-- contact/urls.py | 4 +- discourse_sso/urls.py | 4 +- places/urls.py | 8 +- studygroups/api_urls.py | 48 +++++------ studygroups/urls.py | 144 ++++++++++++++++----------------- surveys/urls.py | 8 +- 10 files changed, 121 insertions(+), 121 deletions(-) diff --git a/announce/urls.py b/announce/urls.py index e45ef183..7a99f284 100644 --- a/announce/urls.py +++ b/announce/urls.py @@ -1,8 +1,8 @@ -from django.conf.urls import url +from django.urls import re_path from . import views urlpatterns = [ - url(r'^send/$', views.announce_webhook, name='announce_webhook'), - url(r'^mailchimp/(?P[\w-]+)$', views.mailchimp_webhook, name='announce_webhook'), + re_path(r'^send/$', views.announce_webhook, name='announce_webhook'), + re_path(r'^mailchimp/(?P[\w-]+)$', views.mailchimp_webhook, name='announce_webhook'), ] diff --git a/client_logging/urls.py b/client_logging/urls.py index e2462af3..a7b2be6a 100644 --- a/client_logging/urls.py +++ b/client_logging/urls.py @@ -1,7 +1,7 @@ -from django.conf.urls import url +from django.urls import re_path from . import views urlpatterns = [ - url(r'^$', views.LogPostView.as_view(), name='client_logging_logpost'), + re_path(r'^$', views.LogPostView.as_view(), name='client_logging_logpost'), ] diff --git a/community_calendar/api_urls.py b/community_calendar/api_urls.py index 90eb4386..21e028c8 100644 --- a/community_calendar/api_urls.py +++ b/community_calendar/api_urls.py @@ -1,4 +1,4 @@ -from django.conf.urls import url, include +from django.urls import re_path, include from rest_framework import routers from .api import EventViewSet @@ -9,6 +9,6 @@ # Wire up our API using automatic URL routing. # Additionally, we include login URLs for the browsable API. urlpatterns = [ - url(r'^', include(router.urls)), - #url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')) + re_path(r'^', include(router.urls)), + #re_path(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')) ] diff --git a/community_calendar/urls.py b/community_calendar/urls.py index c1c54723..dfb1f8d7 100644 --- a/community_calendar/urls.py +++ b/community_calendar/urls.py @@ -1,10 +1,10 @@ -from django.conf.urls import url +from django.urls import re_path from .views import * urlpatterns = [ - url(r'^event/add/$', EventCreate.as_view(), name='community_calendar_event_create'), - url(r'^event/(?P[\d]+)/edit/$', EventUpdate.as_view(), name='community_calendar_event_edit'), - url(r'^event/(?P[\d]+)/delete/$', EventDelete.as_view(), name='community_calendar_event_delete'), - url(r'^event/(?P[\d]+)/moderate/$', EventModerate.as_view(), name='community_calendar_event_moderate'), + re_path(r'^event/add/$', EventCreate.as_view(), name='community_calendar_event_create'), + re_path(r'^event/(?P[\d]+)/edit/$', EventUpdate.as_view(), name='community_calendar_event_edit'), + re_path(r'^event/(?P[\d]+)/delete/$', EventDelete.as_view(), name='community_calendar_event_delete'), + re_path(r'^event/(?P[\d]+)/moderate/$', EventModerate.as_view(), name='community_calendar_event_moderate'), ] diff --git a/contact/urls.py b/contact/urls.py index 4b8c447e..7deff349 100644 --- a/contact/urls.py +++ b/contact/urls.py @@ -1,7 +1,7 @@ -from django.conf.urls import url +from django.urls import re_path from contact import views urlpatterns = [ - url(r'^contact/$', views.ContactAPIView.as_view(), name='api_contact_form') + re_path(r'^contact/$', views.ContactAPIView.as_view(), name='api_contact_form') ] diff --git a/discourse_sso/urls.py b/discourse_sso/urls.py index 4c87b169..f8349f9b 100644 --- a/discourse_sso/urls.py +++ b/discourse_sso/urls.py @@ -1,7 +1,7 @@ -from django.conf.urls import url +from django.urls import re_path from . import views urlpatterns = [ - url(r'^sso_redirect/$', views.discourse_sso, name='discourse_sso'), + re_path(r'^sso_redirect/$', views.discourse_sso, name='discourse_sso'), ] diff --git a/places/urls.py b/places/urls.py index 0069a999..10411029 100644 --- a/places/urls.py +++ b/places/urls.py @@ -1,4 +1,4 @@ -from django.conf.urls import url +from django.urls import re_path from .views import city_info from .views import city_search @@ -6,7 +6,7 @@ from .views import country_search urlpatterns = [ - url(r'^search/city/$', city_search, name='api_city_search'), - url(r'^search/country/$', country_search, name='api_country_search'), - url(r'^(?P[\d]+)/$', city_info, name='api_city_info'), + re_path(r'^search/city/$', city_search, name='api_city_search'), + re_path(r'^search/country/$', country_search, name='api_country_search'), + re_path(r'^(?P[\d]+)/$', city_info, name='api_city_info'), ] diff --git a/studygroups/api_urls.py b/studygroups/api_urls.py index 247c8a32..d83f13c1 100644 --- a/studygroups/api_urls.py +++ b/studygroups/api_urls.py @@ -1,4 +1,4 @@ -from django.conf.urls import url +from django.urls import re_path from django.conf.urls import include from django.views.generic import TemplateView from django.contrib.auth.decorators import login_required @@ -19,27 +19,27 @@ # TODO split / indicate what is used on www.p2pu.org vs what is used for management UX urlpatterns = [ - url(r'^learningcircles/$', views.LearningCircleListView.as_view(), name='api_learningcircles'), - url(r'^learningcircles/successes/$', views.FinalReportListView.as_view(), name='api_learningcircles_successes'), - url(r'^learningcircles/topics/$', views.LearningCircleTopicListView.as_view(), name='api_learningcircle_topics'), - url(r'^learningcircles/cities/$', views.cities, name='api_learningcircles_cities'), - url(r'^courses/$', views.CourseListView.as_view(), name='api_courses'), - url(r'^courses/topics/$', views.CourseTopicListView.as_view(), name='api_course_topics'), - url(r'^courses/languages/$', views.CourseLanguageListView.as_view(), name='api_course_languages'), - url(r'^signup/$', views.SignupView.as_view(), name='api_learningcircles_signup'), - url(r'^rsvp/$', views.MeetingRsvpView.as_view(), name='api_meeting_rsvp'), - url(r'^learning-circle/$', views.LearningCircleCreateView.as_view(), name='api_learningcircles_create'), - url(r'^learning-circle/(?P[\d]+)/$', views.LearningCircleUpdateView.as_view(), name='api_learningcircles_update'), - url(r'^upload_image/$', views.ImageUploadView.as_view(), name='api_image_upload'), - url(r'^learning-circles-map/$', views.LearningCirclesMapView.as_view(), name='api_learningcircles_map'), - url(r'^instagram-feed/$', views.InstagramFeed.as_view(), name='api_instagram_feed'), - url(r'^teams/$', views.TeamListView.as_view(), name='api_teams'), - url(r'^teams/(?P[\d]+)/$', views.TeamDetailView.as_view(), name='api_teams_detail'), - url(r'^teams/(?P[\d]+)/invitation-url/create/$', views.create_team_invitation_link, name='api_teams_create_invitation_url'), - url(r'^teams/(?P[\d]+)/invitation-url/delete/$', views.delete_team_invitation_link, name='api_teams_delete_invitation_link'), - url(r'^teams/members/$', views.TeamMembershipListView.as_view(), name='api_team_memberships'), - url(r'^teams/invitations/$', views.TeamInvitationListView.as_view(), name='api_team_invitations'), - url(r'^facilitator/invitations/$', views.facilitator_invitation_notifications, name='api_facilitator_invitations'), - url(r'^announcements/$', views.AnnouncementListView.as_view(), name='api_announcements'), - url(r'^drf/', include(router.urls)), + re_path(r'^learningcircles/$', views.LearningCircleListView.as_view(), name='api_learningcircles'), + re_path(r'^learningcircles/successes/$', views.FinalReportListView.as_view(), name='api_learningcircles_successes'), + re_path(r'^learningcircles/topics/$', views.LearningCircleTopicListView.as_view(), name='api_learningcircle_topics'), + re_path(r'^learningcircles/cities/$', views.cities, name='api_learningcircles_cities'), + re_path(r'^courses/$', views.CourseListView.as_view(), name='api_courses'), + re_path(r'^courses/topics/$', views.CourseTopicListView.as_view(), name='api_course_topics'), + re_path(r'^courses/languages/$', views.CourseLanguageListView.as_view(), name='api_course_languages'), + re_path(r'^signup/$', views.SignupView.as_view(), name='api_learningcircles_signup'), + re_path(r'^rsvp/$', views.MeetingRsvpView.as_view(), name='api_meeting_rsvp'), + re_path(r'^learning-circle/$', views.LearningCircleCreateView.as_view(), name='api_learningcircles_create'), + re_path(r'^learning-circle/(?P[\d]+)/$', views.LearningCircleUpdateView.as_view(), name='api_learningcircles_update'), + re_path(r'^upload_image/$', views.ImageUploadView.as_view(), name='api_image_upload'), + re_path(r'^learning-circles-map/$', views.LearningCirclesMapView.as_view(), name='api_learningcircles_map'), + re_path(r'^instagram-feed/$', views.InstagramFeed.as_view(), name='api_instagram_feed'), + re_path(r'^teams/$', views.TeamListView.as_view(), name='api_teams'), + re_path(r'^teams/(?P[\d]+)/$', views.TeamDetailView.as_view(), name='api_teams_detail'), + re_path(r'^teams/(?P[\d]+)/invitation-url/create/$', views.create_team_invitation_link, name='api_teams_create_invitation_url'), + re_path(r'^teams/(?P[\d]+)/invitation-url/delete/$', views.delete_team_invitation_link, name='api_teams_delete_invitation_link'), + re_path(r'^teams/members/$', views.TeamMembershipListView.as_view(), name='api_team_memberships'), + re_path(r'^teams/invitations/$', views.TeamInvitationListView.as_view(), name='api_team_invitations'), + re_path(r'^facilitator/invitations/$', views.facilitator_invitation_notifications, name='api_facilitator_invitations'), + re_path(r'^announcements/$', views.AnnouncementListView.as_view(), name='api_announcements'), + re_path(r'^drf/', include(router.urls)), ] diff --git a/studygroups/urls.py b/studygroups/urls.py index c84accff..2cc18a69 100644 --- a/studygroups/urls.py +++ b/studygroups/urls.py @@ -1,4 +1,4 @@ -from django.conf.urls import url +from django.urls import include, re_path from django.views.generic import TemplateView from django.views.generic.base import RedirectView @@ -50,105 +50,105 @@ from . import views urlpatterns = [ - url(r'^$', FacilitatorDashboard.as_view(), name='studygroups_facilitator'), + re_path(r'^$', FacilitatorDashboard.as_view(), name='studygroups_facilitator'), - url(r'^courses/$', RedirectView.as_view(url='https://www.p2pu.org/en/courses/'), name='studygroups_courses'), + re_path(r'^courses/$', RedirectView.as_view(url='https://www.p2pu.org/en/courses/'), name='studygroups_courses'), - url(r'^studygroups/$', views.studygroups, name='studygroups_search'), + re_path(r'^studygroups/$', views.studygroups, name='studygroups_search'), - url(r'^login_redirect/$', views.login_redirect, name='studygroups_login_redirect'), + re_path(r'^login_redirect/$', views.login_redirect, name='studygroups_login_redirect'), - url(r'^signup/(?P[\w-]+)-(?P[\d]+)/$', views.signup, name='studygroups_signup'), - url(r'^signup/(?P[\d]+)/success/$', SignupSuccess.as_view(), name='studygroups_signup_success'), + re_path(r'^signup/(?P[\w-]+)-(?P[\d]+)/$', views.signup, name='studygroups_signup'), + re_path(r'^signup/(?P[\d]+)/success/$', SignupSuccess.as_view(), name='studygroups_signup_success'), - url(r'^studygroup/create/$', StudyGroupCreate.as_view(), name='studygroups_facilitator_studygroup_create'), - url(r'^studygroup/create/legacy/$', StudyGroupCreateLegacy.as_view(), name='studygroups_studygroup_create_legacy'), - url(r'^studygroup/(?P[\d]+)/$', views.view_study_group, name='studygroups_view_study_group'), - url(r'^studygroup/(?P[\d]+)/learn/$', views.StudyGroupParticipantView.as_view(), name='studygroups_view_learning_circle_participant'), - url(r'^studygroup/(?P[\d]+)/edit/$', StudyGroupUpdate.as_view(), name='studygroups_edit_study_group'), - url(r'^studygroup/(?P[\d]+)/edit/legacy/$', StudyGroupUpdateLegacy.as_view(), name='studygroups_studygroup_edit_legacy'), - url(r'^studygroup/(?P[\d]+)/delete/$', StudyGroupDelete.as_view(), name='studygroups_studygroup_delete'), - url(r'^studygroup/(?P[\d]+)/toggle_signup/$', StudyGroupToggleSignup.as_view(), name='studygroups_studygroup_toggle_signup'), + re_path(r'^studygroup/create/$', StudyGroupCreate.as_view(), name='studygroups_facilitator_studygroup_create'), + re_path(r'^studygroup/create/legacy/$', StudyGroupCreateLegacy.as_view(), name='studygroups_studygroup_create_legacy'), + re_path(r'^studygroup/(?P[\d]+)/$', views.view_study_group, name='studygroups_view_study_group'), + re_path(r'^studygroup/(?P[\d]+)/learn/$', views.StudyGroupParticipantView.as_view(), name='studygroups_view_learning_circle_participant'), + re_path(r'^studygroup/(?P[\d]+)/edit/$', StudyGroupUpdate.as_view(), name='studygroups_edit_study_group'), + re_path(r'^studygroup/(?P[\d]+)/edit/legacy/$', StudyGroupUpdateLegacy.as_view(), name='studygroups_studygroup_edit_legacy'), + re_path(r'^studygroup/(?P[\d]+)/delete/$', StudyGroupDelete.as_view(), name='studygroups_studygroup_delete'), + re_path(r'^studygroup/(?P[\d]+)/toggle_signup/$', StudyGroupToggleSignup.as_view(), name='studygroups_studygroup_toggle_signup'), - url(r'^studygroup/(?P[\d]+)/publish/$', StudyGroupPublish.as_view(), name='studygroups_studygroup_publish'), - url(r'^studygroup/(?P[\d]+)/did_not_happen/$', StudyGroupDidNotHappen.as_view(), name='studygroups_studygroup_did_not_happen'), + re_path(r'^studygroup/(?P[\d]+)/publish/$', StudyGroupPublish.as_view(), name='studygroups_studygroup_publish'), + re_path(r'^studygroup/(?P[\d]+)/did_not_happen/$', StudyGroupDidNotHappen.as_view(), name='studygroups_studygroup_did_not_happen'), - url(r'^studygroup/(?P[\d]+)/message/compose/$', views.message_send, name='studygroups_message_send'), - url(r'^studygroup/(?P[\d]+)/message/edit/(?P[\d]+)/$', views.message_edit, name='studygroups_message_edit'), + re_path(r'^studygroup/(?P[\d]+)/message/compose/$', views.message_send, name='studygroups_message_send'), + re_path(r'^studygroup/(?P[\d]+)/message/edit/(?P[\d]+)/$', views.message_edit, name='studygroups_message_edit'), - url(r'^studygroup/(?P[\d]+)/message/(?P[\d]+)/$', MessageView.as_view(), name='studygroups_message_view'), + re_path(r'^studygroup/(?P[\d]+)/message/(?P[\d]+)/$', MessageView.as_view(), name='studygroups_message_view'), - url(r'^studygroup/(?P[\d]+)/learner/add/$', views.add_learner, name='studygroups_add_learner'), - url(r'^studygroup/(?P[\d]+)/learner/add-multiple/$', ApplicationCreateMultiple.as_view(), name='studygroups_add_learners'), - url(r'^studygroup/(?P[\d]+)/learner/(?P[0-9]+)/edit/$', ApplicationUpdate.as_view(), name='studygroups_application_edit'), - url(r'^studygroup/(?P[\d]+)/learner/(?P[0-9]+)/delete/$', ApplicationDelete.as_view(), name='studygroups_application_delete'), + re_path(r'^studygroup/(?P[\d]+)/learner/add/$', views.add_learner, name='studygroups_add_learner'), + re_path(r'^studygroup/(?P[\d]+)/learner/add-multiple/$', ApplicationCreateMultiple.as_view(), name='studygroups_add_learners'), + re_path(r'^studygroup/(?P[\d]+)/learner/(?P[0-9]+)/edit/$', ApplicationUpdate.as_view(), name='studygroups_application_edit'), + re_path(r'^studygroup/(?P[\d]+)/learner/(?P[0-9]+)/delete/$', ApplicationDelete.as_view(), name='studygroups_application_delete', - url(r'^studygroup/(?P[\w-]+)/survey/$', StudyGroupLearnerSurvey.as_view(), name='studygroups_learner_survey'), - url(r'^studygroup/(?P[\w-]+)/survey/done/$', TemplateView.as_view(template_name='studygroups/learner_survey_done.html'), name='studygroups_learnear_survey_done'), - url(r'^studygroup/(?P[\w-]+)/facilitator_survey/$', StudyGroupFacilitatorSurvey.as_view(), name='studygroups_facilitator_survey'), - url(r'^facilitator_survey/$', TemplateView.as_view(template_name='studygroups/anonymous_facilitator_survey.html'), name='anonymous_facilitator_survey'), - url(r'^facilitator_survey/done/$', TemplateView.as_view(template_name='studygroups/facilitator_survey_done.html'), name='studygroups_facilitator_survey_done'), + re_path(r'^studygroup/(?P[\w-]+)/survey/$', StudyGroupLearnerSurvey.as_view(), name='studygroups_learner_survey'), + re_path(r'^studygroup/(?P[\w-]+)/survey/done/$', TemplateView.as_view(template_name='studygroups/learner_survey_done.html'), name='studygroups_learnear_survey_done'), + re_path(r'^studygroup/(?P[\w-]+)/facilitator_survey/$', StudyGroupFacilitatorSurvey.as_view(), name='studygroups_facilitator_survey'), + re_path(r'^facilitator_survey/$', TemplateView.as_view(template_name='studygroups/anonymous_facilitator_survey.html'), name='anonymous_facilitator_survey'), + re_path(r'^facilitator_survey/done/$', TemplateView.as_view(template_name='studygroups/facilitator_survey_done.html'), name='studygroups_facilitator_survey_done'), - url(r'^studygroup/(?P[\w-]+)/report/$', StudyGroupFinalReport.as_view(), name='studygroups_final_report'), + re_path(r'^studygroup/(?P[\w-]+)/report/$', StudyGroupFinalReport.as_view(), name='studygroups_final_report'), # views regarding study group meetings - url(r'^studygroup/(?P[\d]+)/meeting/(?P[\d]+)/edit/$', MeetingUpdate.as_view(), name='studygroups_meeting_edit'), - url(r'^studygroup/(?P[\d]+)/meeting/create/$', MeetingCreate.as_view(), name='studygroups_meeting_create'), - url(r'^studygroup/(?P[\d]+)/meeting/(?P[0-9]+)/delete/$', MeetingDelete.as_view(), name='studygroups_meeting_delete'), + re_path(r'^studygroup/(?P[\d]+)/meeting/(?P[\d]+)/edit/$', MeetingUpdate.as_view(), name='studygroups_meeting_edit'), + re_path(r'^studygroup/(?P[\d]+)/meeting/create/$', MeetingCreate.as_view(), name='studygroups_meeting_create'), + re_path(r'^studygroup/(?P[\d]+)/meeting/(?P[0-9]+)/delete/$', MeetingDelete.as_view(), name='studygroups_meeting_delete'), - url(r'^studygroup/(?P[\d]+)/meeting/(?P[\d]+)/recap/$', MeetingRecap.as_view(), name='studygroups_meeting_recap'), - url(r'^studygroup/(?P[\d]+)/meeting/(?P[\d]+)/recap/dismiss/$', MeetingRecapDismiss.as_view(), name='studygroups_meeting_recap_dismiss'), + re_path(r'^studygroup/(?P[\d]+)/meeting/(?P[\d]+)/recap/$', MeetingRecap.as_view(), name='studygroups_meeting_recap'), + re_path(r'^studygroup/(?P[\d]+)/meeting/(?P[\d]+)/recap/dismiss/$', MeetingRecapDismiss.as_view(), name='studygroups_meeting_recap_dismiss'), - url(r'^course/create/$', CourseCreate.as_view(), name='studygroups_course_create'), - url(r'^course/(?P[\d]+)/$', CoursePage.as_view(), name='studygroups_course_page'), - url(r'^course/(?P[\d]+)/reviews/$', CourseReviewsPage.as_view(), name='studygroups_course_reviews_page'), - url(r'^course/(?P[\d]+)/edit/$', CourseUpdate.as_view(), name='studygroups_course_edit'), - url(r'^course/(?P[\d]+)/delete/$', CourseDelete.as_view(), name='studygroups_course_delete'), + re_path(r'^course/create/$', CourseCreate.as_view(), name='studygroups_course_create'), + re_path(r'^course/(?P[\d]+)/$', CoursePage.as_view(), name='studygroups_course_page'), + re_path(r'^course/(?P[\d]+)/reviews/$', CourseReviewsPage.as_view(), name='studygroups_course_reviews_page'), + re_path(r'^course/(?P[\d]+)/edit/$', CourseUpdate.as_view(), name='studygroups_course_edit'), + re_path(r'^course/(?P[\d]+)/delete/$', CourseDelete.as_view(), name='studygroups_course_delete'), - url(r'^facilitator/$', RedirectView.as_view(url='/'), name='studygroups_facilitator_deprecated'), - url(r'^facilitator/team-invitation/$', InvitationConfirm.as_view(), name='studygroups_facilitator_invitation_confirm'), - url(r'^facilitator/team-invitation/(?P[\d]+)/$', InvitationConfirm.as_view(), name='studygroups_facilitator_invitation_confirm'), - url(r'^facilitator/team-invitation/(?P[\w-]+)/$', InvitationConfirm.as_view(), name='studygroups_facilitator_invitation_confirm_token'), - url(r'^facilitator/teammembership/(?P[\d]+)/delete/$', LeaveTeam.as_view(), name='studygroups_facilitator_leave_team'), + re_path(r'^facilitator/$', RedirectView.as_view(url='/'), name='studygroups_facilitator_deprecated'), + re_path(r'^facilitator/team-invitation/$', InvitationConfirm.as_view(), name='studygroups_facilitator_invitation_confirm'), + re_path(r'^facilitator/team-invitation/(?P[\d]+)/$', InvitationConfirm.as_view(), name='studygroups_facilitator_invitation_confirm'), + re_path(r'^facilitator/team-invitation/(?P[\w-]+)/$', InvitationConfirm.as_view(), name='studygroups_facilitator_invitation_confirm_token'), + re_path(r'^facilitator/teammembership/(?P[\d]+)/delete/$', LeaveTeam.as_view(), name='studygroups_facilitator_leave_team'), - url(r'^optout/$', OptOutView.as_view(), name='studygroups_optout'), - url(r'^optout/confirm/$', views.optout_confirm, name='studygroups_leave'), + re_path(r'^optout/$', OptOutView.as_view(), name='studygroups_optout'), + re_path(r'^optout/confirm/$', views.optout_confirm, name='studygroups_leave'), - url(r'^rsvp/$', views.rsvp, name='studygroups_rsvp'), - url(r'^rsvp/success/$', TemplateView.as_view(template_name='studygroups/rsvp_success.html'), name='studygroups_rsvp_success'), + re_path(r'^rsvp/$', views.rsvp, name='studygroups_rsvp'), + re_path(r'^rsvp/success/$', TemplateView.as_view(template_name='studygroups/rsvp_success.html'), name='studygroups_rsvp_success'), - url(r'^organize/$', views.organize, name='studygroups_organize'), - url(r'^organize/(?P[\d]+)/$', views.organize_team, name='studygroups_organize_team'), - url(r'^organize/studygroups/$', StudyGroupList.as_view(), name='studygroups_organizer_studygroup_list'), - url(r'^organize/teammembership/(?P[\d]+)/(?P[\d]+)/delete/$', TeamMembershipDelete.as_view(), name='studygroups_teammembership_delete'), - url(r'^organize/team/(?P[\d]+)/member/invite/$', TeamInvitationCreate.as_view(), name='studygroups_team_member_invite'), - url(r'^organize/team/(?P[\d]+)/edit/$', TeamUpdate.as_view(), name='studygroups_team_edit'), - url(r'^organize/team/(?P[\d]+)/course_list/$', TeamCourseList.as_view(), name='studygroups_team_course_list'), + re_path(r'^organize/$', views.organize, name='studygroups_organize'), + re_path(r'^organize/(?P[\d]+)/$', views.organize_team, name='studygroups_organize_team'), + re_path(r'^organize/studygroups/$', StudyGroupList.as_view(), name='studygroups_organizer_studygroup_list'), + re_path(r'^organize/teammembership/(?P[\d]+)/(?P[\d]+)/delete/$', TeamMembershipDelete.as_view(), name='studygroups_teammembership_delete'), + re_path(r'^organize/team/(?P[\d]+)/member/invite/$', TeamInvitationCreate.as_view(), name='studygroups_team_member_invite'), + re_path(r'^organize/team/(?P[\d]+)/edit/$', TeamUpdate.as_view(), name='studygroups_team_edit'), + re_path(r'^organize/team/(?P[\d]+)/course_list/$', TeamCourseList.as_view(), name='studygroups_team_course_list'), - url(r'^get-organizer-guide/$', OrganizerGuideForm.as_view(), name='studygroups_organizer_guide_form'), + re_path(r'^get-organizer-guide/$', OrganizerGuideForm.as_view(), name='studygroups_organizer_guide_form'), # These two URLs are deprecated, but kept for historic purposes - url(r'^report/weekly/$', RedirectView.as_view(pattern_name='studygroups_weekly_update') ), - url(r'^report/weekly/(?P[\d]+)-(?P[\d]+)-(?P[\d]+)/$', RedirectView.as_view(pattern_name='studygroups_weekly_update_date')), + re_path(r'^report/weekly/$', RedirectView.as_view(pattern_name='studygroups_weekly_update') ), + re_path(r'^report/weekly/(?P[\d]+)-(?P[\d]+)-(?P[\d]+)/$', RedirectView.as_view(pattern_name='studygroups_weekly_update_date')), - url(r'^weekly-update/$', views.weekly_update, name='studygroups_weekly_update'), - url(r'^weekly-update/(?P[\d]+)-(?P[\d]+)-(?P[\d]+)/$', views.weekly_update, name='studygroups_weekly_update_date'), - url(r'^weekly-update/(?P[\d]+)/$', views.weekly_update, name='studygroups_weekly_update_team'), - url(r'^weekly-update/(?P[\d]+)/(?P[\d]+)-(?P[\d]+)-(?P[\d]+)/$', views.weekly_update, name='studygroups_weekly_update_team_date'), + re_path(r'^weekly-update/$', views.weekly_update, name='studygroups_weekly_update'), + re_path(r'^weekly-update/(?P[\d]+)-(?P[\d]+)-(?P[\d]+)/$', views.weekly_update, name='studygroups_weekly_update_date'), + re_path(r'^weekly-update/(?P[\d]+)/$', views.weekly_update, name='studygroups_weekly_update_team'), + re_path(r'^weekly-update/(?P[\d]+)/(?P[\d]+)-(?P[\d]+)-(?P[\d]+)/$', views.weekly_update, name='studygroups_weekly_update_team_date'), - url(r'^receive_sms/$', views.receive_sms, name='studygroups_receive_sms'), + re_path(r'^receive_sms/$', views.receive_sms, name='studygroups_receive_sms'), - url(r'^staff/dash/$', StaffDashView.as_view(), name='studygroups_staff_dash'), - url(r'^digest/generate/$', DigestGenerateView.as_view(), name='studygroups_digest_generate'), - url(r'^staff/dash/stats/$', StatsDashView.as_view(), name='studygroups_staff_dash_stats'), + re_path(r'^staff/dash/$', StaffDashView.as_view(), name='studygroups_staff_dash'), + re_path(r'^digest/generate/$', DigestGenerateView.as_view(), name='studygroups_digest_generate'), + re_path(r'^staff/dash/stats/$', StatsDashView.as_view(), name='studygroups_staff_dash_stats'), - url(r'^export/signups/$', ExportSignupsView.as_view(), name='studygroups_export_signups'), - url(r'^export/facilitators/$', ExportFacilitatorsView.as_view(), name='studygroups_export_facilitators'), - url(r'^export/studygroups/$', ExportStudyGroupsView.as_view(), name='studygroups_export_studygroups'), - url(r'^export/courses/$', ExportCoursesView.as_view(), name='studygroups_export_courses'), + re_path(r'^export/signups/$', ExportSignupsView.as_view(), name='studygroups_export_signups'), + re_path(r'^export/facilitators/$', ExportFacilitatorsView.as_view(), name='studygroups_export_facilitators'), + re_path(r'^export/studygroups/$', ExportStudyGroupsView.as_view(), name='studygroups_export_studygroups'), + re_path(r'^export/courses/$', ExportCoursesView.as_view(), name='studygroups_export_courses'), - url(r'^community_digest/(?P[\w-]+)/(?P[\w-]+)/$', CommunityDigestView.as_view(), name='studygroups_community_digest'), + re_path(r'^community_digest/(?P[\w-]+)/(?P[\w-]+)/$', CommunityDigestView.as_view(), name='studygroups_community_digest'), ] diff --git a/surveys/urls.py b/surveys/urls.py index 623dbab7..2f03bf9a 100644 --- a/surveys/urls.py +++ b/surveys/urls.py @@ -1,21 +1,21 @@ -from django.conf.urls import url +from django.urls import re_path from studygroups.decorators import user_is_staff from studygroups.decorators import user_is_group_facilitator from . import views urlpatterns = [ - url( + re_path( r'^learning-circle/export/$', user_is_staff(views.ExportLearnerSurveysView.as_view()), name='survey_learner_responses_csv' ), - url( + re_path( r'^learning-circle/(?P[\d]+)/export/$', user_is_group_facilitator(views.ExportLearnerSurveysView.as_view()), name='survey_learning_circle_learner_responses_csv' ), - url( + re_path( r'^facilitator/export/$', views.ExportFacilitatorSurveysView.as_view(), name='survey_facilitator_responses_csv' From b9650921073965dc16d5764efc58151b71919edf Mon Sep 17 00:00:00 2001 From: Dirk Uys Date: Tue, 9 Apr 2024 17:57:39 +0200 Subject: [PATCH 05/24] Missed some url() calls --- learnwithpeople/urls.py | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/learnwithpeople/urls.py b/learnwithpeople/urls.py index f644eeb1..2758bed4 100644 --- a/learnwithpeople/urls.py +++ b/learnwithpeople/urls.py @@ -1,4 +1,4 @@ -from django.conf.urls import include, url +from django.urls import re_path, include from django.conf.urls.i18n import i18n_patterns from django.conf import settings from django.contrib import admin @@ -6,23 +6,23 @@ from django.urls import reverse, reverse_lazy urlpatterns = i18n_patterns( - url(r'^admin/', admin.site.urls), - url(r'^accounts/', include('custom_registration.urls')), - url(r'^jsi18n/$', JavaScriptCatalog.as_view(packages=['studygroups']), name='javascript-catalog'), - url(r'^discourse/', include('discourse_sso.urls')), - url(r'^surveys/', include('surveys.urls')), - url(r'^community_calendar/', include('community_calendar.urls')), - url(r'^', include('studygroups.urls')) + re_path(r'^admin/', admin.site.urls), + re_path(r'^accounts/', include('custom_registration.urls')), + re_path(r'^jsi18n/$', JavaScriptCatalog.as_view(packages=['studygroups']), name='javascript-catalog'), + re_path(r'^discourse/', include('discourse_sso.urls')), + re_path(r'^surveys/', include('surveys.urls')), + re_path(r'^community_calendar/', include('community_calendar.urls')), + re_path(r'^', include('studygroups.urls')) ) urlpatterns += [ - url(r'^api/', include('studygroups.api_urls')), - url(r'^api/', include('contact.urls')), - url(r'^api/places/', include('places.urls')), - url(r'^api/community_calendar/', include('community_calendar.api_urls')), - url(r'^announce/', include('announce.urls')), - url(r'^log/', include('client_logging.urls')), - url(r'^tinymce/', include('tinymce.urls')), + re_path(r'^api/', include('studygroups.api_urls')), + re_path(r'^api/', include('contact.urls')), + re_path(r'^api/places/', include('places.urls')), + re_path(r'^api/community_calendar/', include('community_calendar.api_urls')), + re_path(r'^announce/', include('announce.urls')), + re_path(r'^log/', include('client_logging.urls')), + re_path(r'^tinymce/', include('tinymce.urls')), ] if settings.DEBUG: @@ -30,12 +30,12 @@ static_url = settings.STATIC_URL.lstrip('/').rstrip('/') from django.views.static import serve urlpatterns += [ - url(r'^%s/(?P.*)$' % media_url, serve, + re_path(r'^%s/(?P.*)$' % media_url, serve, { 'document_root': settings.MEDIA_ROOT, } ), - url(r'^%s/(?P.*)$' % static_url, serve, + re_path(r'^%s/(?P.*)$' % static_url, serve, { 'document_root': settings.STATIC_ROOT, } From 953a15e16e5b6b04e9891bc6b773a1c4f40b59a2 Mon Sep 17 00:00:00 2001 From: Dirk Uys Date: Tue, 9 Apr 2024 19:59:18 +0200 Subject: [PATCH 06/24] More url -> re_path updates --- custom_registration/urls.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/custom_registration/urls.py b/custom_registration/urls.py index 4724163b..9cc2e29b 100644 --- a/custom_registration/urls.py +++ b/custom_registration/urls.py @@ -1,4 +1,4 @@ -from django.conf.urls import include, url +from django.urls import re_path, include from django.contrib.auth.views import LoginView from django.contrib.auth.views import PasswordResetView from django.contrib.auth.views import PasswordResetConfirmView @@ -15,16 +15,16 @@ urlpatterns = [ - url(r'^fe/register/', AjaxSignupView.as_view(), name='fe_register'), - url(r'^fe/login/', AjaxLoginView.as_view(), name='fe_login'), - url(r'^fe/whoami/', WhoAmIView.as_view(), name='fe_whoami'), - url(r'^register/', SignupView.as_view(), name='register'), - url(r'^email_confirm/$', EmailConfirmRequestView.as_view(), name="email_confirm_request"), - url(r'^email_confirm/(?P[0-9A-Za-z_\-]+)/(?P[0-9A-Za-z\-]+)/$', EmailConfirmView.as_view(), name="email_confirm"), - url(r'^login/', LoginView.as_view(redirect_authenticated_user=True), name='login'), - url(r'^password_reset/$', PasswordResetView.as_view(form_class=CustomPasswordResetForm), name="password_reset"), - url(r'^settings/$', AccountSettingsView.as_view(), name="account_settings"), - url(r'^reset/(?P[0-9A-Za-z_\-]+)/(?P[0-9A-Za-z\-]+)/$', PasswordResetConfirmView.as_view(post_reset_login=True, success_url=reverse_lazy('studygroups_login_redirect') ), name='password_reset_confirm'), - url(r'^delete/$', AccountDeleteView.as_view(), name='account_delete'), - url(r'^', include('django.contrib.auth.urls')), + re_path(r'^fe/register/', AjaxSignupView.as_view(), name='fe_register'), + re_path(r'^fe/login/', AjaxLoginView.as_view(), name='fe_login'), + re_path(r'^fe/whoami/', WhoAmIView.as_view(), name='fe_whoami'), + re_path(r'^register/', SignupView.as_view(), name='register'), + re_path(r'^email_confirm/$', EmailConfirmRequestView.as_view(), name="email_confirm_request"), + re_path(r'^email_confirm/(?P[0-9A-Za-z_\-]+)/(?P[0-9A-Za-z\-]+)/$', EmailConfirmView.as_view(), name="email_confirm"), + re_path(r'^login/', LoginView.as_view(redirect_authenticated_user=True), name='login'), + re_path(r'^password_reset/$', PasswordResetView.as_view(form_class=CustomPasswordResetForm), name="password_reset"), + re_path(r'^settings/$', AccountSettingsView.as_view(), name="account_settings"), + re_path(r'^reset/(?P[0-9A-Za-z_\-]+)/(?P[0-9A-Za-z\-]+)/$', PasswordResetConfirmView.as_view(post_reset_login=True, success_url=reverse_lazy('studygroups_login_redirect') ), name='password_reset_confirm'), + re_path(r'^delete/$', AccountDeleteView.as_view(), name='account_delete'), + re_path(r'^', include('django.contrib.auth.urls')), ] From ed1aee206ab246581a3f8d6a3cc4e6f292136ada Mon Sep 17 00:00:00 2001 From: Dirk Uys Date: Tue, 9 Apr 2024 20:12:45 +0200 Subject: [PATCH 07/24] Fix syntax error --- studygroups/urls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/studygroups/urls.py b/studygroups/urls.py index 2cc18a69..c7b79a3d 100644 --- a/studygroups/urls.py +++ b/studygroups/urls.py @@ -81,7 +81,7 @@ re_path(r'^studygroup/(?P[\d]+)/learner/add/$', views.add_learner, name='studygroups_add_learner'), re_path(r'^studygroup/(?P[\d]+)/learner/add-multiple/$', ApplicationCreateMultiple.as_view(), name='studygroups_add_learners'), re_path(r'^studygroup/(?P[\d]+)/learner/(?P[0-9]+)/edit/$', ApplicationUpdate.as_view(), name='studygroups_application_edit'), - re_path(r'^studygroup/(?P[\d]+)/learner/(?P[0-9]+)/delete/$', ApplicationDelete.as_view(), name='studygroups_application_delete', + re_path(r'^studygroup/(?P[\d]+)/learner/(?P[0-9]+)/delete/$', ApplicationDelete.as_view(), name='studygroups_application_delete'), re_path(r'^studygroup/(?P[\w-]+)/survey/$', StudyGroupLearnerSurvey.as_view(), name='studygroups_learner_survey'), re_path(r'^studygroup/(?P[\w-]+)/survey/done/$', TemplateView.as_view(template_name='studygroups/learner_survey_done.html'), name='studygroups_learnear_survey_done'), From e156ee2c6740d8d4f9d6e21e247975295a57ce0d Mon Sep 17 00:00:00 2001 From: Dirk Uys Date: Wed, 10 Apr 2024 11:37:01 +0200 Subject: [PATCH 08/24] remove is_ajax from contact view --- contact/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contact/views.py b/contact/views.py index 5d51486f..c6d9228b 100644 --- a/contact/views.py +++ b/contact/views.py @@ -28,7 +28,7 @@ def post(self, request, *args, **kwargs): # call async task to send email send_contact_form_inquiry.delay(**serializer.data) - if request.GET.get('next') and not request.is_ajax(): + if request.GET.get('next') and not request.headers.get('Content-Type') == 'application/json': # TODO should this be validated? return http.HttpResponseRedirect(request.GET.get('next')) From cd37c09db700211a4e29973dd2d296e2a2c88410 Mon Sep 17 00:00:00 2001 From: Dirk Uys Date: Wed, 10 Apr 2024 11:47:33 +0200 Subject: [PATCH 09/24] Update DeleteView as per Django 4.0 changes --- community_calendar/views.py | 4 ++-- custom_registration/views.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/community_calendar/views.py b/community_calendar/views.py index 59319a37..0eb2e0e4 100644 --- a/community_calendar/views.py +++ b/community_calendar/views.py @@ -57,9 +57,9 @@ class EventDelete(DeleteView): model = Event success_url = reverse_lazy('studygroups_facilitator') - def delete(self, request, *args, **kwargs): + def form_valid(self, form): messages.success(self.request, _('Your event has been deleted.')) - return super().delete(request, *args, **kwargs) + return super().form_valid(request, form) @method_decorator(login_required, name="dispatch") diff --git a/custom_registration/views.py b/custom_registration/views.py index a7a8bd3d..12357ff7 100644 --- a/custom_registration/views.py +++ b/custom_registration/views.py @@ -290,7 +290,7 @@ class AccountDeleteView(DeleteView): def get_object(self): return self.request.user - def delete(self, request, *args, **kwargs): + def form_valid(self, form): user = self.request.user # mark user account as deleted From d872459a26cfe2481f25d50f5aa71ed678250651 Mon Sep 17 00:00:00 2001 From: Dirk Uys Date: Wed, 10 Apr 2024 11:48:26 +0200 Subject: [PATCH 10/24] update command line args for npm i --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 67b89fd7..8fb2acf7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,7 +3,7 @@ WORKDIR /opt/app/ COPY package.json package-lock.json /opt/app/ COPY p2pu-theme/ /opt/app/p2pu-theme/ COPY p2pu-components/ /opt/app/p2pu-components/ -RUN npm install --quiet --production +RUN npm install --omit=dev COPY . /opt/app/ RUN npm run build From 6a660d1e23a68f239daaa60c066c2846ac4e8b10 Mon Sep 17 00:00:00 2001 From: Dirk Uys Date: Wed, 10 Apr 2024 12:02:48 +0200 Subject: [PATCH 11/24] Bump django to 4.1.13 --- requirements.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/requirements.txt b/requirements.txt index bc00c0eb..8e215649 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,8 +7,8 @@ async-timeout==4.0.3 attrs==23.2.0 billiard==4.2.0 bleach==5.0.1 -boto3==1.34.80 -botocore==1.34.80 +boto3==1.34.81 +botocore==1.34.81 cachetools==5.3.3 cairocffi==1.6.1 CairoSVG==2.7.1 @@ -26,7 +26,7 @@ cssselect2==0.7.0 cssutils==2.10.2 defusedxml==0.7.1 dj-database-url==2.1.0 -Django==4.0.10 +Django==4.1.13 django-bleach==3.1.0 django-cors-headers==4.3.1 django-crispy-forms==2.0 From c8a7e3ead06e8a646bc8389de62adaf351a77f50 Mon Sep 17 00:00:00 2001 From: Dirk Uys Date: Wed, 10 Apr 2024 13:00:43 +0200 Subject: [PATCH 12/24] Comment out browser capabilities --- e2e/tests/test_learning_circle_creation.py | 6 +++--- e2e/tests/test_learning_circle_manage.py | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/e2e/tests/test_learning_circle_creation.py b/e2e/tests/test_learning_circle_creation.py index d6f7ddc0..de874dda 100644 --- a/e2e/tests/test_learning_circle_creation.py +++ b/e2e/tests/test_learning_circle_creation.py @@ -33,11 +33,11 @@ def setUpClass(cls): chrome_options.add_argument('--disable-gpu') #chrome_options.add_argument('--auto-open-devtools-for-tabs') #chrome_options.add_argument('--start-maximized') - capabilities = DesiredCapabilities.CHROME - capabilities['loggingPrefs'] = { 'browser':'ALL' } + #capabilities = DesiredCapabilities.CHROME + #capabilities['loggingPrefs'] = { 'browser':'ALL' } cls.driver = webdriver.Remote( command_executor='http://selenium:4444/wd/hub', - desired_capabilities=capabilities, + #desired_capabilities=capabilities, options=chrome_options ) timeout = 10 diff --git a/e2e/tests/test_learning_circle_manage.py b/e2e/tests/test_learning_circle_manage.py index b6061a5e..677aa008 100644 --- a/e2e/tests/test_learning_circle_manage.py +++ b/e2e/tests/test_learning_circle_manage.py @@ -36,11 +36,11 @@ def setUpClass(cls): chrome_options.add_argument('--disable-gpu') #chrome_options.add_argument('--auto-open-devtools-for-tabs') chrome_options.add_argument('--start-maximized') - capabilities = DesiredCapabilities.CHROME - capabilities['loggingPrefs'] = { 'browser':'ALL' } + #capabilities = DesiredCapabilities.CHROME + #capabilities['loggingPrefs'] = { 'browser':'ALL' } cls.driver = webdriver.Remote( command_executor='http://selenium:4444/wd/hub', - desired_capabilities=capabilities, + #desired_capabilities=capabilities, options=chrome_options ) timeout = 10 From a3f6f5c3a3796daa372eaac9c68d144893616265 Mon Sep 17 00:00:00 2001 From: Dirk Uys Date: Wed, 10 Apr 2024 13:25:13 +0200 Subject: [PATCH 13/24] Update calls to find_element_by_css_selector for updated selenium --- e2e/tests/selenium/page_objects.py | 2 +- e2e/tests/test_learning_circle_manage.py | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/e2e/tests/selenium/page_objects.py b/e2e/tests/selenium/page_objects.py index 538dc7f2..3344470b 100644 --- a/e2e/tests/selenium/page_objects.py +++ b/e2e/tests/selenium/page_objects.py @@ -117,7 +117,7 @@ def click_schedule_meetings_button(self): meetings_button.click() def click_login_link(self): - self.driver.find_element_by_css_selector('.registration-modal-content button:first-child').click() + self.driver.find_element(By.CSS_SELECTOR, '.registration-modal-content button:first-child').click() def fill_out_login_modal(self, user_data): self.fill_text_field(RegistrationModalLocators.EMAIL_FIELD, user_data["email"]) diff --git a/e2e/tests/test_learning_circle_manage.py b/e2e/tests/test_learning_circle_manage.py index 677aa008..5f8ff102 100644 --- a/e2e/tests/test_learning_circle_manage.py +++ b/e2e/tests/test_learning_circle_manage.py @@ -125,7 +125,7 @@ def test_meeting_feedback(self): (By.CSS_SELECTOR, "#meeting-1-feedback #id_attendance") )) - attendance = self.driver.find_element_by_css_selector("#meeting-1-feedback #id_attendance") + attendance = self.driver.find_element(By.CSS_SELECTOR, "#meeting-1-feedback #id_attendance") actions = ActionChains(self.driver) actions.pause(1) actions.move_to_element(attendance).perform() @@ -170,7 +170,7 @@ def test_learning_circle_rating(self): (By.CSS_SELECTOR, rating_qs) )) - rating_feedback = self.driver.find_element_by_css_selector(rating_qs) + rating_feedback = self.driver.find_element(By.CSS_SELECTOR, rating_qs) actions = ActionChains(self.driver) actions.pause(1) actions.move_to_element(rating_feedback) @@ -201,7 +201,8 @@ def test_course_rating(self): self.driver.execute_script('window.scrollBy(0, 800);') self.assertEquals(StudyGroup.objects.get(pk=1).course_rating, None) - course_rating = self.driver.find_element_by_css_selector( + course_rating = self.driver.find_element( + By.CSS_SELECTOR, "div.star-rating-input:nth-child(2) > label:nth-child(4) > svg:nth-child(2)" ) actions = ActionChains(self.driver) From 08083203987db59969ff3c58154c9f5d2d4f1f68 Mon Sep 17 00:00:00 2001 From: Dirk Uys Date: Wed, 10 Apr 2024 14:00:58 +0200 Subject: [PATCH 14/24] Fix error --- studygroups/tests/test_facilitator_views.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/studygroups/tests/test_facilitator_views.py b/studygroups/tests/test_facilitator_views.py index e6506467..b4a5942d 100644 --- a/studygroups/tests/test_facilitator_views.py +++ b/studygroups/tests/test_facilitator_views.py @@ -340,8 +340,11 @@ def test_update_study_group_legacy_view(self): del data['weeks'] resp = c.post('/en/studygroup/create/legacy/', data) self.assertEqual(resp.status_code, 200) - expected_error_message = 'Please provide the length of the learning circle in weeks' - self.assertFormError(resp, 'form', 'weeks', expected_error_message) + expected_errors = [ + 'This field is required.', + 'Please provide the length of the learning circle in weeks', + ] + self.assertFormError(resp, 'form', 'weeks', expected_errors) From 7f024b1c1370f1ec22029bff483a21a864e23216 Mon Sep 17 00:00:00 2001 From: Dirk Uys Date: Wed, 10 Apr 2024 14:07:17 +0200 Subject: [PATCH 15/24] Let failed tests lead to failed builds to make issues visible while updating deps --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 63ea0d4e..4591e593 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,9 +38,9 @@ jobs: run: docker run --rm -i --link postgres --link selenium -e DATABASE_URL=postgres://postgres:password@postgres/lc -e SECRET_KEY=abc -e ADMIN_EMAIL=admin@localhost -e RECAPTCHA_SITE_KEY=6Le0DW8bAAAAAJUHXcKkkASxZWMIwDypy1DiBBEX p2pu/learning-circles:${IMAGE_TAG} dockerize -wait tcp://postgres:5432 /opt/django-venv/bin/python /opt/app/manage.py test if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/release' - - name: run tests and continue even if failed + - name: run tests and continue even if failed (put back hard fail until LTS is merged) run: docker run --rm -i --link postgres --link selenium -e DATABASE_URL=postgres://postgres:password@postgres/lc -e SECRET_KEY=abc -e ADMIN_EMAIL=admin@localhost -e RECAPTCHA_SITE_KEY=6Le0DW8bAAAAAJUHXcKkkASxZWMIwDypy1DiBBEX p2pu/learning-circles:${IMAGE_TAG} dockerize -wait tcp://postgres:5432 /opt/django-venv/bin/python /opt/app/manage.py test - continue-on-error: true + continue-on-error: false if: github.ref != 'refs/heads/master' && github.ref != 'refs/heads/release' - name: log into registry From 2f90ffae0593effd27ad98cabf9c333978abd5d6 Mon Sep 17 00:00:00 2001 From: Dirk Uys Date: Wed, 10 Apr 2024 14:26:09 +0200 Subject: [PATCH 16/24] Remove unneeded default_app_config --- custom_registration/__init__.py | 1 - studygroups/__init__.py | 1 - 2 files changed, 2 deletions(-) diff --git a/custom_registration/__init__.py b/custom_registration/__init__.py index 6e8d6d88..e69de29b 100644 --- a/custom_registration/__init__.py +++ b/custom_registration/__init__.py @@ -1 +0,0 @@ -default_app_config = 'custom_registration.apps.CustomRegistrationConfig' diff --git a/studygroups/__init__.py b/studygroups/__init__.py index e94002d6..e69de29b 100644 --- a/studygroups/__init__.py +++ b/studygroups/__init__.py @@ -1 +0,0 @@ -default_app_config = 'studygroups.apps.StudyGroupConfig' From b20bc3920273a4ebd846f14791d1a115a5fbaa8b Mon Sep 17 00:00:00 2001 From: Dirk Uys Date: Wed, 10 Apr 2024 16:39:56 +0200 Subject: [PATCH 17/24] Bump postgres to v16 in CI build. Closes #1157, but database on staging and production still needs to be migrated --- .github/workflows/ci.yml | 2 +- docker-compose.yml | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4591e593..4cad5951 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,7 +29,7 @@ jobs: - name: start postgres container - run: docker run -d --name=postgres -e POSTGRES_PASSWORD=password postgres:11 + run: docker run -d --name=postgres -e POSTGRES_PASSWORD=password postgres:16 - name: start selenium container run: docker run -d --name=selenium --shm-size="2g" -e SCREEN_HEIGHT=2048 selenium/standalone-chrome:4.0.0-20211102 diff --git a/docker-compose.yml b/docker-compose.yml index 3c5fe950..6a4ee529 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,13 +1,13 @@ version: '3' services: postgres: - image: postgres:11 + image: postgres:16 ports: - 5432:5432 environment: - POSTGRES_HOST_AUTH_METHOD=trust volumes: - - ./compose/postgres:/var/lib/postgresql/data + - ./compose/postgres-16:/var/lib/postgresql/data rabbitmq: image: rabbitmq:3 email: @@ -22,8 +22,10 @@ services: - .:/opt/app command: sh -c "npm i && npm run watch" learning-circles: - build: . image: p2pu/learning-circles:local + build: + context: . + network: host ports: - 8000:8000 volumes: From 4dfc8e229ebb22fa4a9c3b1adab7f08872df80b6 Mon Sep 17 00:00:00 2001 From: Dirk Uys Date: Wed, 10 Apr 2024 16:45:57 +0200 Subject: [PATCH 18/24] Bump Django to 4.2.11 --- requirements.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/requirements.txt b/requirements.txt index 8e215649..a6e0bce3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -20,17 +20,17 @@ click==8.1.7 click-didyoumean==0.3.1 click-plugins==1.1.1 click-repl==0.3.0 -crispy-bootstrap5==0.7 +crispy-bootstrap5==2024.2 cssselect==1.2.0 cssselect2==0.7.0 cssutils==2.10.2 defusedxml==0.7.1 dj-database-url==2.1.0 -Django==4.1.13 +Django==4.2.11 django-bleach==3.1.0 django-cors-headers==4.3.1 -django-crispy-forms==2.0 -django-filter==23.5 +django-crispy-forms==2.1 +django-filter==24.2 django-phonenumber-field==7.3.0 django-tinymce==4.0.0 django-webpack-loader==3.1.0 From 8cf0f9e8403bd02fdda835e4d0a1af6335dc5241 Mon Sep 17 00:00:00 2001 From: Dirk Uys Date: Wed, 10 Apr 2024 17:01:23 +0200 Subject: [PATCH 19/24] Update test case to not be dependent on the order of recipients in the to/cc field --- studygroups/tests/test_tasks.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/studygroups/tests/test_tasks.py b/studygroups/tests/test_tasks.py index 964a0c38..da642801 100644 --- a/studygroups/tests/test_tasks.py +++ b/studygroups/tests/test_tasks.py @@ -342,10 +342,10 @@ def test_send_weekly_report(self): send_weekly_update() self.assertEqual(len(mail.outbox), 2) - self.assertEqual(mail.outbox[0].to[0], 'faci1@team.com') - self.assertEqual(mail.outbox[0].to[1], 'organ@team.com') - self.assertEqual(mail.outbox[0].cc[0], 'teams@localhost') - self.assertEqual(mail.outbox[1].to[0], 'admin@test.com') + self.assertIn('faci1@team.com', mail.outbox[0].to) + self.assertIn('organ@team.com', mail.outbox[0].to) + self.assertIn('teams@localhost', mail.outbox[0].cc) + self.assertIn('admin@test.com', mail.outbox[1].to) def test_dont_send_weekly_report(self): From 480939563da81af01defa6e7e98a9ff48017ecb4 Mon Sep 17 00:00:00 2001 From: Dirk Uys Date: Tue, 16 Apr 2024 11:52:35 +0200 Subject: [PATCH 20/24] Log out via POST --- templates/nav.html | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/templates/nav.html b/templates/nav.html index 67843b7c..74c62062 100644 --- a/templates/nav.html +++ b/templates/nav.html @@ -43,7 +43,10 @@ Account settings
  • - Log out +
    + {% csrf_token %} + +
  • From 8390c73478ff49910b821c64c569fe91272bd081 Mon Sep 17 00:00:00 2001 From: Dirk Uys Date: Wed, 17 Apr 2024 16:13:01 +0200 Subject: [PATCH 21/24] Update django db engine name to 'django.db.backends.postgresql' as per deprecation https://docs.djangoproject.com/en/4.2/releases/2.0/\#id1 --- backup/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backup/utils.py b/backup/utils.py index aa6fd3c5..5578e80f 100644 --- a/backup/utils.py +++ b/backup/utils.py @@ -52,7 +52,7 @@ def backup_db(): make a backup of the database ''' - if settings.DATABASES['default']['ENGINE'] != 'django.db.backends.postgresql_psycopg2': + if settings.DATABASES['default']['ENGINE'] != 'django.db.backends.postgresql': raise BackupFailed('Database engine not supported') timestamp = datetime.datetime.utcnow().strftime('%Y-%m-%d') From fbbee1370abec8f8174d2a7c8c8b36dee93c96a0 Mon Sep 17 00:00:00 2001 From: Dirk Uys Date: Wed, 17 Apr 2024 16:22:49 +0200 Subject: [PATCH 22/24] Remove version from docker-compose file --- docker-compose.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 6a4ee529..3c6aa5af 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,3 @@ -version: '3' services: postgres: image: postgres:16 From 252a3bfc91ef4636d67ec533eabfc2662b710087 Mon Sep 17 00:00:00 2001 From: Dirk Uys Date: Wed, 17 Apr 2024 16:27:34 +0200 Subject: [PATCH 23/24] Revert to postgres 15 to match debian bookworm version --- .github/workflows/ci.yml | 2 +- docker-compose.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4cad5951..f1ea0986 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,7 +29,7 @@ jobs: - name: start postgres container - run: docker run -d --name=postgres -e POSTGRES_PASSWORD=password postgres:16 + run: docker run -d --name=postgres -e POSTGRES_PASSWORD=password postgres:15 - name: start selenium container run: docker run -d --name=selenium --shm-size="2g" -e SCREEN_HEIGHT=2048 selenium/standalone-chrome:4.0.0-20211102 diff --git a/docker-compose.yml b/docker-compose.yml index 3c6aa5af..4fa41602 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,12 +1,12 @@ services: postgres: - image: postgres:16 + image: postgres:15 ports: - 5432:5432 environment: - POSTGRES_HOST_AUTH_METHOD=trust volumes: - - ./compose/postgres-16:/var/lib/postgresql/data + - ./compose/postgres-15:/var/lib/postgresql/data rabbitmq: image: rabbitmq:3 email: From 778eb4fc32576a230204cdc4854d0f88f4351458 Mon Sep 17 00:00:00 2001 From: Dirk Uys Date: Mon, 29 Apr 2024 08:58:55 +0200 Subject: [PATCH 24/24] Remove CSS that caused issues with check boxes --- static/sass/_custom.scss | 7 ------- 1 file changed, 7 deletions(-) diff --git a/static/sass/_custom.scss b/static/sass/_custom.scss index b4588a07..eaf20bd9 100644 --- a/static/sass/_custom.scss +++ b/static/sass/_custom.scss @@ -1,10 +1,3 @@ -.form-check { - display: flex; - align-content: center; - align-items: center; - gap: 0.5rem; -} - .report-measurement.shadow { box-shadow: -2px 2px 6px rgba(0,0,0,0.2); }