From 8d81f5123d82378d868cf2bf7741f7d80c35bca5 Mon Sep 17 00:00:00 2001 From: Ankit Chopra Date: Tue, 1 Jul 2025 16:26:27 +0530 Subject: [PATCH 001/147] Added the changes for the sending notification at time of registeration of user. --- iogt/settings/base.py | 3 ++- iogt/templates/header.html | 10 +++++++++- iogt/urls.py | 1 + iogt_users/forms.py | 14 ++++++++++++++ {notifications => project_notifications}/README.md | 0 .../__init__.py | 0 {notifications => project_notifications}/apps.py | 2 +- .../migrations/0001_initial.py | 0 .../migrations/__init__.py | 0 {notifications => project_notifications}/models.py | 0 .../processors.py | 0 {notifications => project_notifications}/views.py | 0 .../wagtail_hooks.py | 4 ++-- requirements.dev.in | 1 + requirements.in | 1 + 15 files changed, 31 insertions(+), 5 deletions(-) rename {notifications => project_notifications}/README.md (100%) rename {notifications => project_notifications}/__init__.py (100%) rename {notifications => project_notifications}/apps.py (67%) rename {notifications => project_notifications}/migrations/0001_initial.py (100%) rename {notifications => project_notifications}/migrations/__init__.py (100%) rename {notifications => project_notifications}/models.py (100%) rename {notifications => project_notifications}/processors.py (100%) rename {notifications => project_notifications}/views.py (100%) rename {notifications => project_notifications}/wagtail_hooks.py (81%) diff --git a/iogt/settings/base.py b/iogt/settings/base.py index 500c7ec7d..c2794349a 100644 --- a/iogt/settings/base.py +++ b/iogt/settings/base.py @@ -49,6 +49,7 @@ 'matomo', 'messaging', 'modelcluster', + 'project_notifications', 'notifications', 'questionnaires', 'rest_framework', @@ -129,7 +130,7 @@ 'home.processors.commit_hash', 'home.processors.show_footers', 'messaging.processors.add_vapid_public_key', - 'notifications.processors.push_notification', + 'project_notifications.processors.push_notification', 'home.processors.jquery', ], }, diff --git a/iogt/templates/header.html b/iogt/templates/header.html index 6b4b5de47..5ea5e52b7 100644 --- a/iogt/templates/header.html +++ b/iogt/templates/header.html @@ -4,7 +4,7 @@ {% get_language_info for LANGUAGE_CODE as lang %} {% get_available_languages as LANGUAGES %} {% get_language_info_list for LANGUAGES as languages %} - +{% load notifications_tags %} + +{% if user.is_authenticated %} + +{% endif %} \ No newline at end of file diff --git a/iogt/urls.py b/iogt/urls.py index a16a93c19..bdf7f6986 100644 --- a/iogt/urls.py +++ b/iogt/urls.py @@ -82,6 +82,7 @@ path('api/docs/', schema_view.with_ui('swagger'), name='swagger'), path('webpush/subscribe/', save_info, name='save_webpush_info'), path('inbox/notifications/', include('notifications.urls', namespace='notifications')), + path('notifications/', include('user_notifications.urls')), ] if settings.DEBUG: diff --git a/project_notifications/apps.py b/project_notifications/apps.py deleted file mode 100644 index c52bcfd9f..000000000 --- a/project_notifications/apps.py +++ /dev/null @@ -1,5 +0,0 @@ -from django.apps import AppConfig - - -class NotificationsConfig(AppConfig): - name = 'project_notifications' diff --git a/user_notifications/__init__.py b/user_notifications/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/user_notifications/admin.py b/user_notifications/admin.py new file mode 100644 index 000000000..8c38f3f3d --- /dev/null +++ b/user_notifications/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/user_notifications/apps.py b/user_notifications/apps.py new file mode 100644 index 000000000..5937c97ac --- /dev/null +++ b/user_notifications/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class UserNotificationsConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'user_notifications' diff --git a/user_notifications/migrations/0001_initial.py b/user_notifications/migrations/0001_initial.py new file mode 100644 index 000000000..92adc3aa0 --- /dev/null +++ b/user_notifications/migrations/0001_initial.py @@ -0,0 +1,30 @@ +# Generated by Django 3.2.25 on 2025-07-04 09:31 + +from django.db import migrations, models +import django.utils.timezone +import wagtail.fields + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='UserNotificationTemplate', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=255)), + ('message', wagtail.fields.RichTextField()), + ('active', models.BooleanField(default=True)), + ('updated_at', models.DateTimeField(default=django.utils.timezone.now)), + ], + options={ + 'verbose_name': 'User Notification Template', + 'verbose_name_plural': 'User Notification Templates', + }, + ), + ] diff --git a/user_notifications/migrations/__init__.py b/user_notifications/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/project_notifications/models.py b/user_notifications/models.py similarity index 59% rename from project_notifications/models.py rename to user_notifications/models.py index 16b676a7d..4525185d1 100644 --- a/project_notifications/models.py +++ b/user_notifications/models.py @@ -4,18 +4,8 @@ from django.utils.timezone import now from wagtail.fields import RichTextField -class Notification(models.Model): - head = models.CharField(max_length=255) - body = models.TextField() - url = models.URLField(null=True, blank=True) - - groups = models.ManyToManyField(to='auth.Group', related_name='notifications') - - def __str__(self): - return self.head - @register_snippet -class SignupNotificationTemplate(models.Model): +class UserNotificationTemplate(models.Model): title = models.CharField(max_length=255) message = RichTextField(features=["bold", "italic", "link", "ul", "ol"]) active = models.BooleanField(default=True) @@ -31,6 +21,6 @@ def __str__(self): return f"{self.title} ({'active' if self.active else 'inactive'})" class Meta: - verbose_name = "Signup Notification Template" - verbose_name_plural = "Signup Notification Templates" + verbose_name = "User Notification Template" + verbose_name_plural = "User Notification Templates" diff --git a/user_notifications/templates/user_notifications/notification_dropdown.html b/user_notifications/templates/user_notifications/notification_dropdown.html new file mode 100644 index 000000000..2a1f93ac2 --- /dev/null +++ b/user_notifications/templates/user_notifications/notification_dropdown.html @@ -0,0 +1,9 @@ +{% for n in notifications %} + + {{ n.verb }} - {{ n.timestamp|timesince }} ago + +{% empty %} + No notifications +{% endfor %} + +See all diff --git a/user_notifications/templates/user_notifications/notification_list.html b/user_notifications/templates/user_notifications/notification_list.html new file mode 100644 index 000000000..8737e074a --- /dev/null +++ b/user_notifications/templates/user_notifications/notification_list.html @@ -0,0 +1,21 @@ +{% extends "base.html" %} + +{% block content %} +

All Notifications

+Mark all as read + + +{% endblock %} diff --git a/user_notifications/tests.py b/user_notifications/tests.py new file mode 100644 index 000000000..7ce503c2d --- /dev/null +++ b/user_notifications/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/user_notifications/urls.py b/user_notifications/urls.py new file mode 100644 index 000000000..003bf9bc5 --- /dev/null +++ b/user_notifications/urls.py @@ -0,0 +1,13 @@ +# user_notifications/urls.py +from django.urls import path +from . import views + +app_name = 'user_notifications' + +urlpatterns = [ + path('dropdown/', views.latest_notifications, name='dropdown'), + path('all/', views.all_notifications, name='all'), + path('mark-all-read/', views.mark_all_read, name='mark_all_read'), + path('toggle-read//', views.toggle_read, name='toggle_read'), + path('unread-count/', views.unread_count, name='unread_count'), +] diff --git a/user_notifications/views.py b/user_notifications/views.py new file mode 100644 index 000000000..9f2b102f8 --- /dev/null +++ b/user_notifications/views.py @@ -0,0 +1,32 @@ +# user_notifications/views.py +from notifications.models import Notification +from django.contrib.auth.decorators import login_required +from django.shortcuts import render, redirect +from django.http import JsonResponse + +@login_required +def latest_notifications(request): + notifications = Notification.objects.filter(recipient=request.user).order_by('-timestamp')[:5] + return render(request, 'notification_dropdown.html', {'notifications': notifications}) + +@login_required +def all_notifications(request): + notifications = Notification.objects.filter(recipient=request.user).order_by('-timestamp') + return render(request, 'user_notifications/notification_list.html', {'notifications': notifications}) + +@login_required +def mark_all_read(request): + Notification.objects.filter(recipient=request.user, unread=True).update(unread=False) + return redirect('user_notifications:all') + +@login_required +def toggle_read(request, pk): + notif = Notification.objects.get(id=pk, recipient=request.user) + notif.unread = not notif.unread + notif.save() + return redirect('user_notifications:all') + +@login_required +def unread_count(request): + count = Notification.objects.filter(recipient=request.user, unread=True).count() + return JsonResponse({'unread_count': count}) \ No newline at end of file From 338f10f742d9779bb976888a08c33321d2bb01cc Mon Sep 17 00:00:00 2001 From: Ankit Chopra Date: Fri, 4 Jul 2025 17:56:16 +0530 Subject: [PATCH 004/147] added changes for enable/diable notifications --- admin_notifications/views.py | 2 + admin_notifications/wagtail_hooks.py | 13 ++++ docker-compose.test.yml | 12 ++-- docker-compose.yml | 14 ++++ home/models.py | 98 ++++++++++++++++++++++++++-- iogt/settings/dev.py | 11 ++++ iogt/templates/base.html | 1 + iogt/templates/footer.html | 36 ++++++++++ iogt/urls.py | 2 + iogt_users/forms.py | 8 ++- user_notifications/models.py | 8 +++ 11 files changed, 193 insertions(+), 12 deletions(-) diff --git a/admin_notifications/views.py b/admin_notifications/views.py index afccb959d..aa9e3d66b 100644 --- a/admin_notifications/views.py +++ b/admin_notifications/views.py @@ -10,3 +10,5 @@ def form_valid(self, form): for user in group.user_set.all(): send_user_notification(user=user, payload=payload, ttl=1000) return super().form_valid(form) + + diff --git a/admin_notifications/wagtail_hooks.py b/admin_notifications/wagtail_hooks.py index 205fedf30..c6e08b249 100644 --- a/admin_notifications/wagtail_hooks.py +++ b/admin_notifications/wagtail_hooks.py @@ -1,8 +1,11 @@ from django.conf import settings from wagtail.contrib.modeladmin.options import ModelAdmin, modeladmin_register + + from admin_notifications.models import AdminNotification from admin_notifications.views import CreateNotificationView +from user_notifications.models import NotificationPreference class NotificationModelAdmin(ModelAdmin): @@ -16,5 +19,15 @@ class NotificationModelAdmin(ModelAdmin): create_view_class = CreateNotificationView +class NotificationPreferenceAdmin(ModelAdmin): + model = NotificationPreference + menu_label = "Notification Preferences" + menu_icon = "bell" # Wagtail icon name + list_display = ("user", "receive_notifications") + search_fields = ("user__username", "user__email") + +# Register with Wagtail admin if settings.PUSH_NOTIFICATION: modeladmin_register(NotificationModelAdmin) + +modeladmin_register(NotificationPreferenceAdmin) diff --git a/docker-compose.test.yml b/docker-compose.test.yml index 445b2fcf0..ed37a57af 100644 --- a/docker-compose.test.yml +++ b/docker-compose.test.yml @@ -6,17 +6,19 @@ services: args: requirements: requirements.dev.txt environment: - DB_HOST: db + DB_HOST: localhost DB_NAME: iogt - DB_PASSWORD: iogt + DB_PASSWORD: root DB_PORT: '5432' - DB_USER: iogt + DB_USER: postgres DJANGO_SETTINGS_MODULE: iogt.settings.test + ports: + - "5432:5432" depends_on: - db db: image: postgres:14-alpine environment: - POSTGRES_USER: iogt - POSTGRES_PASSWORD: iogt + POSTGRES_USER: postgres + POSTGRES_PASSWORD: root POSTGRES_DB: iogt diff --git a/docker-compose.yml b/docker-compose.yml index 3bd1b4755..f429fe040 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,9 +6,23 @@ services: args: requirements: requirements.dev.txt environment: + DB_HOST: db + DB_NAME: iogt + DB_PASSWORD: postgresiogt + DB_PORT: '5432' + DB_USER: postgres DJANGO_SETTINGS_MODULE: iogt.settings.dev image: iogt:latest + ports: - "8000:8000" + depends_on: + - db volumes: - ./:/app/ + db: + image: postgres:14-alpine + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgresiogt + POSTGRES_DB: iogt diff --git a/home/models.py b/home/models.py index 3305f6024..3091d9fe6 100644 --- a/home/models.py +++ b/home/models.py @@ -3,6 +3,7 @@ from django.conf import settings from django.contrib.admin.utils import flatten + from django.contrib.auth import get_user_model from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.models import ContentType @@ -86,17 +87,95 @@ class HomePage(Page, PageUtilsMixin, TitleIconMixin): FieldPanel('home_featured_content') ] + # def get_context(self, request): + # context = super().get_context(request) + # banners = [] + # for home_page_banner in self.home_page_banners.select_related('banner_page', 'banner_page__banner_link_page').all(): + # banner_page = home_page_banner.banner_page + # if banner_page.live and ((banner_page.banner_link_page and banner_page.banner_link_page.live) or + # banner_page.banner_link_page == None): + # banners.append(banner_page.specific) + # context['banners'] = banners + # return context + + # def get_context(self, request): + # context = super().get_context(request) + # + # # banner_index = BannerIndexPage.objects.live().first() + # site = Site.find_for_request(request) + # root = site.root_page if site else None + # + # banner_index = None + # if root: + # banner_index = BannerIndexPage.objects.descendant_of(root).live().first() + # + # banners = [] + # # if banner_index: + # # banners = [] + # if banner_index: + # for banner in banner_index.get_children().live().order_by('path'): + # if ( + # not hasattr(banner, 'banner_link_page') + # or banner.banner_link_page is None + # or (banner.banner_link_page and banner.banner_link_page.live) + # ): + # banners.append(banner.specific) + # + # context['banners'] = banners + # return context + def get_context(self, request): context = super().get_context(request) + + # Get current language code from request + language_code = request.LANGUAGE_CODE + + try: + current_locale = Locale.objects.get(language_code=language_code) + except Locale.DoesNotExist: + current_locale = Locale.get_default() + # Get the true root of the Wagtail tree (depth=1) + true_root = Page.get_first_root_node() + print('true_root', true_root) + # Find the localized "home" page (like EnglishMainPage, ArabicMainPage) + localized_home = None + for page in true_root.get_children().live(): + if ( + page.locale == current_locale + and page.slug != "home" # or page.title != "Home" + ): + localized_home = page + break + print('localized_home', localized_home) + # Optional fallback to default locale + if not localized_home: + fallback_locale = Locale.get_default() + print('fallback_locale', fallback_locale) + for page in true_root.get_children().live(): + if hasattr(page, 'locale') and page.locale == fallback_locale and page.slug != "home": + localized_home = page + break + print('default_localized_home', localized_home) + + # Find the localized BannerIndexPage (Banner Folder) + banner_index = None + if localized_home: + banner_index = BannerIndexPage.objects.descendant_of(localized_home).live().first() + + # Collect live banners under the localized banner index banners = [] - for home_page_banner in self.home_page_banners.select_related('banner_page', 'banner_page__banner_link_page').all(): - banner_page = home_page_banner.banner_page - if banner_page.live and ((banner_page.banner_link_page and banner_page.banner_link_page.live) or - banner_page.banner_link_page == None): - banners.append(banner_page.specific) + if banner_index: + for banner in banner_index.get_children().live().order_by('path'): + banner_specific = banner.specific + if ( + not hasattr(banner_specific, 'banner_link_page') or + banner_specific.banner_link_page is None or + (banner_specific.banner_link_page and banner_specific.banner_link_page.live) + ): + banners.append(banner_specific) + context['banners'] = banners return context - @property def offline_urls(self): return [self.url] + collect_urls_from_streamfield(self.home_featured_content) @@ -543,6 +622,13 @@ class BannerIndexPage(Page): parent_page_types = ['home.HomePage'] subpage_types = ['home.BannerPage'] + # def get_context(self, request): + # print('testing........................') + # context = super().get_context(request) + # context['banners'] = self.get_children().live().order_by('path') # important! + # print('context', context) + # return context + # class BannerPage(Page, PageUtilsMixin): parent_page_types = ['home.BannerIndexPage'] diff --git a/iogt/settings/dev.py b/iogt/settings/dev.py index eb76e60df..4073bd772 100644 --- a/iogt/settings/dev.py +++ b/iogt/settings/dev.py @@ -1,4 +1,5 @@ from .base import * +from os import getenv WAGTAILADMIN_BASE_URL = 'http://localhost:8000' DEBUG = True @@ -18,6 +19,16 @@ } INSTALLED_APPS += ("django_extensions",) +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.postgresql', + 'NAME': getenv('DB_NAME', 'postgres'), + 'USER': getenv('DB_USER', 'postgres'), + 'PASSWORD': getenv('DB_PASSWORD', 'iogt'), + 'HOST': getenv('DB_HOST', 'database'), + 'PORT': getenv('DB_PORT', '5432'), + } +} try: from .local import * diff --git a/iogt/templates/base.html b/iogt/templates/base.html index 691132d92..92b47fc94 100644 --- a/iogt/templates/base.html +++ b/iogt/templates/base.html @@ -105,6 +105,7 @@ {% endif %} + -{% block extra_js %}{% endblock %} + + document.getElementById("notif-overlay").addEventListener("click", closeNotifPanel); + document.getElementById("notif-close-btn").addEventListener("click", closeNotifPanel); + document.querySelector(".notification-bell").addEventListener("click", openNotifPanel); + + + {% block extra_js %}{% endblock %} - + + \ No newline at end of file diff --git a/iogt_users/forms.py b/iogt_users/forms.py index cf4c6f36b..a3a6604a1 100644 --- a/iogt_users/forms.py +++ b/iogt_users/forms.py @@ -52,8 +52,11 @@ def save(self, request): # Send notification to all staff/admin users # for admin in User.objects.filter(is_staff=True): - template = UserNotificationTemplate.objects.filter(active=True).latest("updated_at") - print('template-data', template) + template = UserNotificationTemplate.objects.filter(active=True) + if not template: + template = UserNotificationTemplate(title="Thank you for registering.", message="Thank you for registering.") + else: + template = template.latest("updated_at") for admin in User.objects.filter(is_staff=True): notify.send( sender=user, diff --git a/user_notifications/urls.py b/user_notifications/urls.py index 003bf9bc5..bb0f1074f 100644 --- a/user_notifications/urls.py +++ b/user_notifications/urls.py @@ -5,7 +5,7 @@ app_name = 'user_notifications' urlpatterns = [ - path('dropdown/', views.latest_notifications, name='dropdown'), + path('latest_notifications/', views.latest_notifications, name='latest_notifications'), path('all/', views.all_notifications, name='all'), path('mark-all-read/', views.mark_all_read, name='mark_all_read'), path('toggle-read//', views.toggle_read, name='toggle_read'), From ebeacb102124667d7707a5d6cfc63879a0b107eb Mon Sep 17 00:00:00 2001 From: Sachin Mehta Date: Wed, 9 Jul 2025 05:29:55 +0000 Subject: [PATCH 008/147] Notifications frontend WIP --- home/static/css/global/global.css | 614 +++++++++++++++++++----------- iogt/templates/base.html | 85 +---- iogt/templates/header.html | 45 ++- user_notifications/views.py | 2 +- 4 files changed, 431 insertions(+), 315 deletions(-) diff --git a/home/static/css/global/global.css b/home/static/css/global/global.css index c957bddd2..1d8ec104d 100644 --- a/home/static/css/global/global.css +++ b/home/static/css/global/global.css @@ -1,4 +1,3 @@ - /* home start */ .home-page__featured-content { padding: 0 22px; @@ -23,6 +22,7 @@ .banner-holder { margin-bottom: 20px; } + .banner-holder img { margin-bottom: 6px; width: 100vw; @@ -30,6 +30,7 @@ border-radius: 12px; } } + /* home end */ @@ -52,11 +53,11 @@ display: -ms-flexbox; display: flex; -webkit-box-pack: justify; - -ms-flex-pack: justify; - justify-content: space-between; + -ms-flex-pack: justify; + justify-content: space-between; -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; + -ms-flex-align: center; + align-items: center; } .featured-content a { @@ -71,7 +72,8 @@ text-align: left; } -.featured-content svg, .section-featured-content svg { +.featured-content svg, +.section-featured-content svg { stroke: currentColor; } @@ -82,7 +84,9 @@ margin-bottom: 19px; padding: 13px 12px; } - .featured-content a, .section-featured-content-title { + + .featured-content a, + .section-featured-content-title { font-size: 16px; line-height: 22px; } @@ -122,14 +126,14 @@ display: flex; -webkit-box-orient: horizontal; -webkit-box-direction: normal; - -ms-flex-direction: row; - flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; + -ms-flex-align: center; + align-items: center; -webkit-box-pack: justify; - -ms-flex-pack: justify; - justify-content: space-between; + -ms-flex-pack: justify; + justify-content: space-between; padding: 8px 0px; border-bottom: 1px solid #EFEFEF; font-style: normal; @@ -178,11 +182,11 @@ } } -.rtl .quiz__imageholder { +.rtl .quiz__imageholder { transform: rotate(180deg); } -.rtl .featured-content__imageholder { +.rtl .featured-content__imageholder { transform: rotate(180deg); } @@ -231,7 +235,8 @@ margin-bottom: 10px; } -.article__content--video a, .article__content--audio a { +.article__content--video a, +.article__content--audio a { color: #303030; } @@ -243,14 +248,14 @@ display: flex; -webkit-box-orient: horizontal; -webkit-box-direction: normal; - -ms-flex-direction: row; - flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; + -ms-flex-pack: center; + justify-content: center; -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; + -ms-flex-align: center; + align-items: center; padding: 8px 16px; border: 1px solid #303030; border-radius: 8px; @@ -298,8 +303,8 @@ display: -ms-flexbox; display: flex; -webkit-box-pack: justify; - -ms-flex-pack: justify; - justify-content: space-between; + -ms-flex-pack: justify; + justify-content: space-between; padding-top: 12px; } @@ -309,14 +314,14 @@ display: flex; -webkit-box-orient: horizontal; -webkit-box-direction: normal; - -ms-flex-direction: row; - flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; + -ms-flex-pack: center; + justify-content: center; -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; + -ms-flex-align: center; + align-items: center; padding: 8px 12px; text-decoration: none; width: 105px; @@ -346,18 +351,21 @@ .article__navigation { padding-top: 24px; } + .article__navigation a { padding: 12px 16px; width: 132px; height: 46px; border-radius: 24px; } + .article__navigation--previous { height: 22px; font-size: 16px; line-height: 22px; border: 1.5px solid #d8d8d8; } + .article__navigation--next { height: 22px; font-size: 16px; @@ -377,11 +385,11 @@ display: flex; -webkit-box-orient: horizontal; -webkit-box-direction: normal; - -ms-flex-direction: row; - flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; + -ms-flex-align: center; + align-items: center; padding: 12px; background: #F7F7F9; font-size: 10px; @@ -408,11 +416,11 @@ display: -ms-flexbox; display: flex; -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; + -ms-flex-pack: center; + justify-content: center; -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; + -ms-flex-align: center; + align-items: center; margin-left: 10px; } @@ -455,25 +463,25 @@ display: flex; -webkit-box-orient: horizontal; -webkit-box-direction: normal; - -ms-flex-direction: row; - flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; + -ms-flex-pack: center; + justify-content: center; -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; + -ms-flex-align: center; + align-items: center; padding: 0; background-color: #303030; border-radius: 24px; -webkit-box-flex: 0; - -ms-flex-positive: 0; - flex-grow: 0; + -ms-flex-positive: 0; + flex-grow: 0; margin: 16px 10px; width: 100%; } -.comments__submit + .comments__submit { +.comments__submit+.comments__submit { margin-left: 10px; } @@ -493,15 +501,18 @@ .comments { padding-top: 40px; } + .comments h2 { padding: 20px; font-size: 16px; line-height: 22px; } + .comments h3 { font-size: 24px; line-height: 28px; } + .comments__count { width: 30px; height: 30px; @@ -509,18 +520,22 @@ line-height: 16px; margin-left: 10px; } + .comments__form { padding: 0px 20px; } + .comments__login { padding: 20px; font-size: 16px; line-height: 24px; } + .comments__submit { padding: 0; margin: 16px 0px; } + .comments__submit input, .comments__submit a { font-size: 16px; @@ -550,8 +565,8 @@ display: -ms-flexbox; display: flex; -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; + -ms-flex-align: center; + align-items: center; margin: 0; } @@ -566,11 +581,11 @@ display: -ms-flexbox; display: flex; -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; + -ms-flex-pack: center; + justify-content: center; -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; + -ms-flex-align: center; + align-items: center; } .individual-comment span p:nth-of-type(2n) { @@ -586,11 +601,11 @@ display: -ms-flexbox; display: flex; -webkit-box-pack: justify; - -ms-flex-pack: justify; - justify-content: space-between; + -ms-flex-pack: justify; + justify-content: space-between; -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; + -ms-flex-align: center; + align-items: center; } .individual-comment__date { @@ -601,7 +616,8 @@ opacity: 0.4; } -.individual-comment .content, .individual-comment__moderator { +.individual-comment .content, +.individual-comment__moderator { font-weight: 500; font-size: 10px; line-height: 16px; @@ -634,34 +650,42 @@ .individual-comment { padding: 20px; } + .individual-comment span p { font-size: 16px; line-height: 24px; margin: 0; } + .individual-comment span p:first-of-type { width: 32px; margin-right: 8px; height: 32px; border-radius: 50%; } + .individual-comment span p:nth-of-type(2n) { font-size: 16px; line-height: 24px; letter-spacing: 0.01em; } + .individual-comment__date { font-size: 12px; line-height: 12px; } - .individual-comment .content, .individual-comment__moderator { + + .individual-comment .content, + .individual-comment__moderator { font-size: 16px; line-height: 24px; } + .individual-comment .report-comment { font-size: 14px; line-height: 20px; } + .individual-comment .report-comment__disclaimer { font-size: 14px; line-height: 20px; @@ -676,7 +700,7 @@ width: 100%; border: 1px solid #EFEFEF; -webkit-box-sizing: border-box; - box-sizing: border-box; + box-sizing: border-box; border-radius: 8px; padding: 7px 12px; font-style: normal; @@ -697,14 +721,17 @@ line-height: 24px; } } + /*# sourceMappingURL=article.css.map */ -.article-card .img-holder, .section-card .img-holder { +.article-card .img-holder, +.section-card .img-holder { overflow: hidden; position: relative; } -.article-card .img-holder.complete:after, .section-card .img-holder.complete:after { +.article-card .img-holder.complete:after, +.section-card .img-holder.complete:after { position: absolute; left: 0; right: 0; @@ -715,7 +742,8 @@ background: linear-gradient(0deg, rgba(26, 144, 144, 0.7), rgba(26, 144, 144, 0.7)); } -.article-card .img-holder.complete:before, .section-card .img-holder.complete:before { +.article-card .img-holder.complete:before, +.section-card .img-holder.complete:before { background-image: url("/static/icons/tick-square.svg"); content: ""; height: 28px; @@ -728,6 +756,7 @@ transform: translate(-50%, -50%); z-index: 2; } + /* article end */ @@ -752,7 +781,8 @@ body.rtl { padding: 0; } -.article-card p.article-title, .section-card p.section-title { +.article-card p.article-title, +.section-card p.section-title { width: 40%; font-weight: bold; margin-right: 5px; @@ -761,12 +791,14 @@ body.rtl { letter-spacing: 0.01em; } -.article-card .article-header, .section-card .section-header { +.article-card .article-header, +.section-card .section-header { padding-left: 10px; padding-right: 10px; } -.article-card .article-header p, .section-card .section-header p { +.article-card .article-header p, +.section-card .section-header p { width: 100%; } @@ -775,11 +807,11 @@ body.rtl { display: -ms-flexbox; display: flex; -webkit-box-pack: justify; - -ms-flex-pack: justify; - justify-content: space-between; + -ms-flex-pack: justify; + justify-content: space-between; -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; + -ms-flex-align: center; + align-items: center; padding: 6px 0px; border-bottom: 1px solid #EFEFEF; text-decoration: none; @@ -804,13 +836,15 @@ body.rtl { height: auto; } -.article-card .img-holder, .section-card .img-holder { +.article-card .img-holder, +.section-card .img-holder { border-radius: 8px; flex: 0 0 50%; height: auto; } -.article-card .img-holder img, .section-card .img-holder img { +.article-card .img-holder img, +.section-card .img-holder img { border-radius: 8px; width: 100%; height: auto; @@ -830,22 +864,27 @@ body.rtl { .article-card { /* margin: 0px 20px; */ } + .article-card h2 { height: 28px; font-weight: 800; font-size: 24px; line-height: 28px; } - .article-card p.article-title, .section-card p.section-title { + + .article-card p.article-title, + .section-card p.section-title { width: 50%; font-size: 16px; margin-right: 5px; line-height: 24px; } - .article-card .article-header p, .section-card .section-header p { + .article-card .article-header p, + .section-card .section-header p { width: 100%; } + .article-card a { padding: 16px 0px; font-size: 16px; @@ -853,9 +892,11 @@ body.rtl { letter-spacing: 0.01em; color: #303030; } + .article-card__img--xs { display: none; } + .article-card__img--sm { display: block; } @@ -869,14 +910,14 @@ body.rtl { display: flex; -webkit-box-orient: vertical; -webkit-box-direction: normal; - -ms-flex-direction: column; - flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; + -ms-flex-pack: center; + justify-content: center; -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; + -ms-flex-align: center; + align-items: center; } .questionnaire-components a { @@ -885,11 +926,11 @@ body.rtl { display: -ms-flexbox; display: flex; -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; + -ms-flex-align: center; + align-items: center; -webkit-box-pack: justify; - -ms-flex-pack: justify; - justify-content: space-between; + -ms-flex-pack: justify; + justify-content: space-between; color: inherit; } @@ -933,18 +974,22 @@ body.rtl { .questionnaire-components { margin: 0px 20px; } + .questionnaire-components p:first-of-type { font-size: 12px; line-height: 16px; } + .questionnaire-components p { padding-right: 20px; margin: 0; } + .questionnaire-components p:nth-of-type(2n) { font-size: 16px; line-height: 22px; } + .questionnaire-components__component { margin: 16px; padding: 8px 12px; @@ -968,37 +1013,40 @@ body.rtl { display: flex; -webkit-box-orient: vertical; -webkit-box-direction: normal; - -ms-flex-direction: column; - flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; padding: 12px; padding-top: 8px; left: 0px; top: 0px; background-color: #E0F2FD; } + .cache-banner p { font-style: normal; font-weight: normal; font-size: 16px; line-height: 24px; } + .cache-banner p:nth-of-type(2n) { font-weight: 700; } + .cache-banner__download { display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-orient: horizontal; -webkit-box-direction: normal; - -ms-flex-direction: row; - flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; + -ms-flex-pack: center; + justify-content: center; -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; + -ms-flex-align: center; + align-items: center; padding: 5px 12px; border: none; height: 26px; @@ -1010,14 +1058,16 @@ body.rtl { line-height: 16px; color: #FFFFFF; } + .cache-banner__close-holder { display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-pack: end; - -ms-flex-pack: end; - justify-content: flex-end; + -ms-flex-pack: end; + justify-content: flex-end; } + .cache-banner__close-holder__button { padding: 0px 4px; background: #0094F4; @@ -1030,17 +1080,21 @@ body.rtl { border: none; } } + /*# sourceMappingURL=global.css.map */ .other-links, -.content .footer__copyright {display: none;} +.content .footer__copyright { + display: none; +} @media screen and (max-width: 767px) and (min-width: 414px) { .footer { - padding-left: 32px; - padding-right: 32px; + padding-left: 32px; + padding-right: 32px; } + .section-container { max-width: 600px; margin: 0 auto; @@ -1093,7 +1147,8 @@ body.rtl { .footer .footer__copyright { display: none; } - .nav-bar{ + + .nav-bar { position: static; width: 100%; } @@ -1104,7 +1159,7 @@ body.rtl { width: 100%; } - .nav-bar__item a{ + .nav-bar__item a { display: flex; margin-bottom: 8px; padding: 9px 12px; @@ -1152,7 +1207,9 @@ body.rtl { margin-top: 0; } - .content .footer__copyright {display: block;} + .content .footer__copyright { + display: block; + } .footer__copyright { margin: 0; @@ -1161,7 +1218,10 @@ body.rtl { } @media screen and (min-width: 1400px) { - .footer .bottom-level {display: none;} + .footer .bottom-level { + display: none; + } + .footer-main, .other-links { display: block; @@ -1169,6 +1229,7 @@ body.rtl { width: 29%; padding: 0 20px; } + .content { max-width: 600px; width: 40%; @@ -1245,38 +1306,43 @@ body.rtl { } .language__select { - display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */ - display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */ - display: -ms-flexbox; /* TWEENER - IE 10 */ - display: -webkit-flex; /* NEW - Chrome */ - display: flex; /* NEW, Spec - Opera 12.1, Firefox 20+ */ + display: -webkit-box; + /* OLD - iOS 6-, Safari 3.1-6 */ + display: -moz-box; + /* OLD - Firefox 19- (buggy but mostly works) */ + display: -ms-flexbox; + /* TWEENER - IE 10 */ + display: -webkit-flex; + /* NEW - Chrome */ + display: flex; + /* NEW, Spec - Opera 12.1, Firefox 20+ */ -webkit-box-pack: end; - -ms-flex-pack: end; - justify-content: flex-end; -} - - .dropdown-menu { - position: absolute; - right: 10px; - top: 40px; - background: white; - border: 1px solid #ccc; - z-index: 1000; - box-shadow: 0px 2px 6px rgba(0, 0, 0, 0.15); - padding: 10px; - border-radius: 6px; - } - - .notification-holder { - display: flex; - align-items: center; - margin-left: 12px; - } + -ms-flex-pack: end; + justify-content: flex-end; +} + +.dropdown-menu { + position: absolute; + right: 10px; + top: 40px; + background: white; + border: 1px solid #ccc; + z-index: 1000; + box-shadow: 0px 2px 6px rgba(0, 0, 0, 0.15); + padding: 10px; + border-radius: 6px; +} + +.notification-holder { + display: flex; + align-items: center; + margin-left: 12px; +} .language__select select { -webkit-appearance: none; - -moz-appearance: none; - appearance: none; + -moz-appearance: none; + appearance: none; margin-right: 10px; background: #FDD256; border: none; @@ -1291,14 +1357,14 @@ body.rtl { display: flex; -webkit-box-orient: horizontal; -webkit-box-direction: normal; - -ms-flex-direction: row; - flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; + -ms-flex-pack: center; + justify-content: center; -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; + -ms-flex-align: center; + align-items: center; padding: 5px 12px; background-image: url("/static/icons/down.svg"); background-repeat: no-repeat; @@ -1320,17 +1386,17 @@ body.rtl { display: flex; -webkit-box-orient: horizontal; -webkit-box-direction: normal; - -ms-flex-direction: row; - flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; + -ms-flex-pack: center; + justify-content: center; -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; + -ms-flex-align: center; + align-items: center; } -.language_drop > a { +.language_drop>a { background: #FDD256; display: flex; flex-direction: column; @@ -1350,7 +1416,7 @@ body.rtl { z-index: 999; } -.language_drop > a > span { +.language_drop>a>span { position: absolute; border-left: 4px solid transparent; border-right: 4px solid transparent; @@ -1379,9 +1445,9 @@ body.rtl { z-index: 99; } -.language_drop:hover > a > span, -.language_drop:active > a > span, -.language_drop:focus > a > span { +.language_drop:hover>a>span, +.language_drop:active>a>span, +.language_drop:focus>a>span { border-top: 4px solid transparent; border-bottom: 4px solid #303030; margin: -2px 0 0; @@ -1407,14 +1473,19 @@ body.rtl { position: relative; } -.language_drop .drop li{ +.language_drop .drop li { width: 100%; margin: 0 0 8px; - display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */ - display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */ - display: -ms-flexbox; /* TWEENER - IE 10 */ - display: -webkit-flex; /* NEW - Chrome */ - display: flex; /* NEW, Spec - Opera 12.1, Firefox 20+ */ + display: -webkit-box; + /* OLD - iOS 6-, Safari 3.1-6 */ + display: -moz-box; + /* OLD - Firefox 19- (buggy but mostly works) */ + display: -ms-flexbox; + /* TWEENER - IE 10 */ + display: -webkit-flex; + /* NEW - Chrome */ + display: flex; + /* NEW, Spec - Opera 12.1, Firefox 20+ */ } .language_drop .drop .selected a { @@ -1438,11 +1509,16 @@ body.rtl { box-sizing: border-box; border-radius: 0 0 8px 8px; align-items: center; - display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */ - display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */ - display: -ms-flexbox; /* TWEENER - IE 10 */ - display: -webkit-flex; /* NEW - Chrome */ - display: flex; /* NEW, Spec - Opera 12.1, Firefox 20+ */ + display: -webkit-box; + /* OLD - iOS 6-, Safari 3.1-6 */ + display: -moz-box; + /* OLD - Firefox 19- (buggy but mostly works) */ + display: -ms-flexbox; + /* TWEENER - IE 10 */ + display: -webkit-flex; + /* NEW - Chrome */ + display: flex; + /* NEW, Spec - Opera 12.1, Firefox 20+ */ } #header:after { @@ -1455,31 +1531,46 @@ body.rtl { align-items: center; padding: 12px 32px; flex: 1; - display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */ - display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */ - display: -ms-flexbox; /* TWEENER - IE 10 */ - display: -webkit-flex; /* NEW - Chrome */ - display: flex; /* NEW, Spec - Opera 12.1, Firefox 20+ */ + display: -webkit-box; + /* OLD - iOS 6-, Safari 3.1-6 */ + display: -moz-box; + /* OLD - Firefox 19- (buggy but mostly works) */ + display: -ms-flexbox; + /* TWEENER - IE 10 */ + display: -webkit-flex; + /* NEW - Chrome */ + display: flex; + /* NEW, Spec - Opera 12.1, Firefox 20+ */ max-width: 664px; margin: 0 auto; } .header-content { - display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */ - display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */ - display: -ms-flexbox; /* TWEENER - IE 10 */ - display: -webkit-flex; /* NEW - Chrome */ - display: flex; /* NEW, Spec - Opera 12.1, Firefox 20+ */ + display: -webkit-box; + /* OLD - iOS 6-, Safari 3.1-6 */ + display: -moz-box; + /* OLD - Firefox 19- (buggy but mostly works) */ + display: -ms-flexbox; + /* TWEENER - IE 10 */ + display: -webkit-flex; + /* NEW - Chrome */ + display: flex; + /* NEW, Spec - Opera 12.1, Firefox 20+ */ flex: 1; justify-content: space-between; } .logo-holder { - display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */ - display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */ - display: -ms-flexbox; /* TWEENER - IE 10 */ - display: -webkit-flex; /* NEW - Chrome */ - display: flex; /* NEW, Spec - Opera 12.1, Firefox 20+ */ + display: -webkit-box; + /* OLD - iOS 6-, Safari 3.1-6 */ + display: -moz-box; + /* OLD - Firefox 19- (buggy but mostly works) */ + display: -ms-flexbox; + /* TWEENER - IE 10 */ + display: -webkit-flex; + /* NEW - Chrome */ + display: flex; + /* NEW, Spec - Opera 12.1, Firefox 20+ */ flex: 1; } @@ -1507,7 +1598,7 @@ body.rtl { margin-right: 12px; } -.form-holder .js-search-btn img{ +.form-holder .js-search-btn img { margin: 0 0 0 12px; border-left: 1px solid #EFEFEF; padding: 5px 0; @@ -1520,6 +1611,7 @@ body.rtl { border-radius: 0; border-width: 0 0 1px 0; } + .footer-head #header, .footer-head .header-holder { /* padding-left: 0; @@ -1549,15 +1641,18 @@ body.rtl { .header-holder { padding: 12px 20px; } + .logo-holder a { max-width: 68px; } + .language__select select { max-width: 74px; font-size: 10px; background-position: 60px; } - .language_drop > a { + + .language_drop>a { min-width: 80px; /* max-width: 80px; */ } @@ -1588,15 +1683,18 @@ body.rtl { padding-top: 20px; } } + @media screen and (max-width: 767px) { .content { padding: 16px 0; } } -.rtl .language_drop > a { + +.rtl .language_drop>a { padding: 5px 12px 5px 20px; } -.rtl .language_drop > a > span { + +.rtl .language_drop>a>span { right: auto; left: 11px; } @@ -1605,22 +1703,30 @@ body.rtl { .footer-head { display: none; } + #header { border-radius: 0; } + .header-holder { padding: 12px 0; max-width: 1000px; } + .logo-holder { flex: initial; } + #header .search__form { display: block; width: 100%; max-width: 600px; } - .form-holder .js-search-btn {display: none;} + + .form-holder .js-search-btn { + display: none; + } + .language__select { margin-left: 12px; } @@ -1634,18 +1740,25 @@ body.rtl { justify-content: flex-start; padding: 0 16px; } + .form-holder { - display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */ - display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */ - display: -ms-flexbox; /* TWEENER - IE 10 */ - display: -webkit-flex; /* NEW - Chrome */ - display: flex; /* NEW, Spec - Opera 12.1, Firefox 20+ */ + display: -webkit-box; + /* OLD - iOS 6-, Safari 3.1-6 */ + display: -moz-box; + /* OLD - Firefox 19- (buggy but mostly works) */ + display: -ms-flexbox; + /* TWEENER - IE 10 */ + display: -webkit-flex; + /* NEW - Chrome */ + display: flex; + /* NEW, Spec - Opera 12.1, Firefox 20+ */ max-width: 600px; width: 60%; flex: 1; padding: 0 16px; flex-basis: 24.5%; } + .main-wrapper { width: 100%; display: flex; @@ -1653,6 +1766,7 @@ body.rtl { box-sizing: border-box; } } + @media screen and (min-width: 1400px) { .header-holder { max-width: 1400px; @@ -1660,12 +1774,14 @@ body.rtl { padding-right: 0; justify-content: space-between; } + #header .btn-holder { display: block; width: 29%; max-width: 400px; padding: 0 20px; } + .form-holder { width: 42%; flex-basis: 42%; @@ -1675,6 +1791,7 @@ body.rtl { #header .btn-holder .nav-bar__item__icon { /* display: flex; */ } + #header .btn-holder .nav-bar__item a { margin: 0; } @@ -1684,6 +1801,7 @@ body.rtl { width: 29%; max-width: 400px; } + .link-login { display: none; } @@ -1691,30 +1809,30 @@ body.rtl { .content .article__content__link-btn { - margin-top: 20px; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-direction: row; - flex-direction: row; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - padding: 8px 16px; - border: 1px solid #303030; - border-radius: 8px; - width: 100%; - font-style: normal; - font-weight: 600; - font-size: 10px; - line-height: 16px; - color: #303030; - text-decoration: none; + margin-top: 20px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + padding: 8px 16px; + border: 1px solid #303030; + border-radius: 8px; + width: 100%; + font-style: normal; + font-weight: 600; + font-size: 10px; + line-height: 16px; + color: #303030; + text-decoration: none; } #app .content-holder .content h1.large { @@ -1731,7 +1849,8 @@ body.rtl { margin: 16px 0; } -#app .content-holder .content h2, .block-heading { +#app .content-holder .content h2, +.block-heading { font-weight: bold; font-size: 16px; line-height: 18px; @@ -1791,11 +1910,11 @@ body.rtl { } } -@media only screen and (min-width: 360px){ +@media only screen and (min-width: 360px) { .content .article__content__link-btn { - font-size: 16px; - line-height: 22px; - padding: 12px 16px; + font-size: 16px; + line-height: 22px; + padding: 12px 16px; } .block-heading { @@ -1820,7 +1939,8 @@ body.rtl { margin: 22px 0; } - #app .content-holder .content h2, .block-heading { + #app .content-holder .content h2, + .block-heading { font-weight: bold; font-size: 22px; line-height: 24px; @@ -1932,9 +2052,9 @@ body.rtl { } #content-wrap .first-content { - flex-direction: column-reverse; - align-items: flex-start; - width: 100%; + flex-direction: column-reverse; + align-items: flex-start; + width: 100%; } #content-wrap .first-content .overlay-holder { @@ -1948,8 +2068,10 @@ body.rtl { width: 100% !important; } -#content-wrap .first-content .img-holder, #content-wrap .first-content .article-header, #content-wrap .first-content .section-header { - width: 100%; +#content-wrap .first-content .img-holder, +#content-wrap .first-content .article-header, +#content-wrap .first-content .section-header { + width: 100%; } /* questionnaires start */ @@ -1961,4 +2083,60 @@ body.rtl { width: 100%; height: auto; } -/* questionnaires end */ \ No newline at end of file + +/* questionnaires end */ + +#notif-overlay { + right: 0; + width: 33%; + height: 100%; + background: white; + box-shadow: -2px 0 10px rgba(0, 0, 0, 0.1); + z-index: 9999; + overflow-y: auto; + transition: transform 0.3s ease; +} + +#notif-panel { + display: none; + position: fixed; + top: 0; + right: -100%; + width: 33.333%; + height: 100%; + background: #fff; + box-shadow: -2px 0 5px rgba(0, 0, 0, 0.2); + z-index: 1001; + transition: right 0.3s ease; + display: flex; + flex-direction: column; +} + +.notif-panel.open { + right: 0; +} + +.notif-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 1rem; + border-bottom: 1px solid #ccc; + background: #f7f7f7; +} + +#notif-content { + padding: 1rem; + overflow-y: auto; + flex-grow: 1; +} + +body.no-scroll { + overflow: hidden; +} + +@media (max-width: 768px) { + #notif-overlay { + width: 100%; + } +} \ No newline at end of file diff --git a/iogt/templates/base.html b/iogt/templates/base.html index 48cfe03c3..82282a124 100644 --- a/iogt/templates/base.html +++ b/iogt/templates/base.html @@ -80,16 +80,17 @@ {% include "footer.html" with page=page_ %} {% endwith %} + -
+
- - - -
- - -
-
-

Notifications

- -
-
- -

Loading...

+ + +
+ + +
+
+

Notifications

+ +
+
+
+
-
+ diff --git a/iogt/templates/header.html b/iogt/templates/header.html index 9a04714ae..7da69168a 100644 --- a/iogt/templates/header.html +++ b/iogt/templates/header.html @@ -18,7 +18,7 @@
{% if request.user.is_authenticated %}
-
+
🔔 {{ request.user.notifications.unread.count }}
@@ -73,32 +73,31 @@ setInterval(refreshUnreadCount, 15000); document.addEventListener("DOMContentLoaded", refreshUnreadCount); - function openNotifPanel() { - document.getElementById('notif-overlay').classList.add('show'); - const panel = document.getElementById('notif-panel'); - panel.classList.add('show'); - panel.style.display = 'block'; - document.body.classList.add('no-scroll'); + function openNotificationsPanel() { + document.querySelector('.notification-panel').style.display = 'block'; + document.getElementById('notification-overlay').style.display = 'block'; + fetch('{% url "user_notifications:latest_notifications" %}').then( + res => res.text() + ).then(html => { + document.getElementById('notification-list').innerHTML = html; + markNotificationsAsRead(); + }); + } - // Fetch notifications - fetch('{% url "user_notifications:latest_notifications" %}') - .then(res => res.text()) - .then(html => { - document.getElementById('notif-content').innerHTML = html; - }); + function closeNotificationsPanel() { + document.querySelector('.notification-panel').style.display = 'none'; + document.getElementById('notification-overlay').style.display = 'none'; } - function closeNotifPanel() { - document.getElementById('notif-overlay').classList.remove('show'); - const panel = document.getElementById('notif-panel'); - panel.classList.remove('show'); - document.body.classList.remove('no-scroll'); + function markNotificationsAsRead() { + const ids = Array.from(document.querySelectorAll('.notification-item.unread')).map(el => el.dataset.id); + if (ids.length === 0) return; + const query = new URLSearchParams(); + ids.forEach(id => query.append('ids[]', id)); + const url = `{% url 'user_notifications:mark_selected_read' %}?${query.toString()}`; - setTimeout(() => { - panel.style.display = 'none'; - }, 300); // wait for animation to complete + fetch(url).then(response => response.json()).then(data => {}); } - document.querySelector(".notification-bell").addEventListener("click", openNotifPanel); {% endif %} \ No newline at end of file diff --git a/user_notifications/templates/user_notifications/notification_dropdown.html b/user_notifications/templates/user_notifications/notification_dropdown.html index 2a1f93ac2..04a52c805 100644 --- a/user_notifications/templates/user_notifications/notification_dropdown.html +++ b/user_notifications/templates/user_notifications/notification_dropdown.html @@ -1,9 +1,13 @@ {% for n in notifications %} - - {{ n.verb }} - {{ n.timestamp|timesince }} ago - + +
+

+ {{ n.verb }} + {% if n.unread %}{% endif %} +

+ {{ n.timestamp|timesince }} ago +
+
{% empty %} - No notifications +
No notifications yet!
{% endfor %} - -See all diff --git a/user_notifications/templates/user_notifications/notification_list.html b/user_notifications/templates/user_notifications/notification_list.html index 8737e074a..bab9b885e 100644 --- a/user_notifications/templates/user_notifications/notification_list.html +++ b/user_notifications/templates/user_notifications/notification_list.html @@ -1,21 +1,28 @@ {% extends "base.html" %} - {% block content %} -

All Notifications

-Mark all as read - +
+ {% endblock %} +{% block extra_js %} + +{% endblock %} \ No newline at end of file diff --git a/user_notifications/urls.py b/user_notifications/urls.py index bb0f1074f..cd40e5754 100644 --- a/user_notifications/urls.py +++ b/user_notifications/urls.py @@ -8,6 +8,7 @@ path('latest_notifications/', views.latest_notifications, name='latest_notifications'), path('all/', views.all_notifications, name='all'), path('mark-all-read/', views.mark_all_read, name='mark_all_read'), + path('mark-selected-read/', views.mark_selected_read, name='mark_selected_read'), path('toggle-read//', views.toggle_read, name='toggle_read'), path('unread-count/', views.unread_count, name='unread_count'), ] diff --git a/user_notifications/views.py b/user_notifications/views.py index a34c662d9..5f01e4564 100644 --- a/user_notifications/views.py +++ b/user_notifications/views.py @@ -25,6 +25,15 @@ def mark_all_read(request): Notification.objects.filter(recipient=request.user, unread=True).update(unread=False) return redirect('user_notifications:all') + +@login_required +def mark_selected_read(request): + ids = request.GET.getlist('ids[]') + if not ids: + return JsonResponse({'status': 'error', 'message': 'No IDs provided'}, status=400) + Notification.objects.filter(recipient=request.user, id__in=ids, unread=True).update(unread=False) + return JsonResponse({'status': 'success', 'message': f'{len(ids)} notifications marked as read'}) + @login_required def toggle_read(request, pk): notif = Notification.objects.get(id=pk, recipient=request.user) From de03ba7ee13337dabd0743ce5247681529721db8 Mon Sep 17 00:00:00 2001 From: Ankit Chopra Date: Fri, 11 Jul 2025 18:44:31 +0530 Subject: [PATCH 010/147] changes to send notifiation to opt in users --- .dockerignore | 2 + admin_notifications/views.py | 5 +- admin_notifications/wagtail_hooks.py | 12 +- home/models.py | 10 +- home/signals.py | 11 + iogt/__init__.py | 3 + iogt/celery.py | 10 + iogt/settings/base.py | 8 +- iogt/static/js/iogt.js | 9 +- iogt/static/js/sw-init.js | 2 + iogt/templates/footer.html | 36 - iogt/templates/sw.js | 23 + iogt_users/forms.py | 22 +- iogt_users/templates/profile.html | 68 +- iogt_users/views.py | 15 +- questionnaires/apps.py | 3 + questionnaires/signals.py | 12 + requirements.dev.in | 2 + requirements.dev.txt | 1042 +++++++++++++++++++++++--- requirements.txt | 790 ++++++++++++++++--- user_notifications/models.py | 51 +- user_notifications/tasks.py | 75 ++ user_notifications/views.py | 41 +- user_notifications/wagtail_hooks.py | 53 ++ 24 files changed, 1995 insertions(+), 310 deletions(-) create mode 100644 iogt/celery.py create mode 100644 questionnaires/signals.py create mode 100644 user_notifications/tasks.py create mode 100644 user_notifications/wagtail_hooks.py diff --git a/.dockerignore b/.dockerignore index 19338251b..217545936 100644 --- a/.dockerignore +++ b/.dockerignore @@ -5,6 +5,8 @@ # Python and others *.pyc +*.pyo +*.db *.swp .DS_Store .python-version diff --git a/admin_notifications/views.py b/admin_notifications/views.py index aa9e3d66b..373a39ec4 100644 --- a/admin_notifications/views.py +++ b/admin_notifications/views.py @@ -1,3 +1,4 @@ +import json from wagtail.contrib.modeladmin.views import CreateView from webpush import send_user_notification @@ -5,10 +6,12 @@ class CreateNotificationView(CreateView): def form_valid(self, form): payload = form.cleaned_data.copy() + print('payload', payload) groups = payload.pop('groups') for group in groups: for user in group.user_set.all(): - send_user_notification(user=user, payload=payload, ttl=1000) + print('user_record', user) + send_user_notification(user=user, payload=json.dumps(payload), ttl=1000) return super().form_valid(form) diff --git a/admin_notifications/wagtail_hooks.py b/admin_notifications/wagtail_hooks.py index c6e08b249..ae63aae64 100644 --- a/admin_notifications/wagtail_hooks.py +++ b/admin_notifications/wagtail_hooks.py @@ -1,11 +1,7 @@ from django.conf import settings from wagtail.contrib.modeladmin.options import ModelAdmin, modeladmin_register - - - from admin_notifications.models import AdminNotification from admin_notifications.views import CreateNotificationView -from user_notifications.models import NotificationPreference class NotificationModelAdmin(ModelAdmin): @@ -18,16 +14,10 @@ class NotificationModelAdmin(ModelAdmin): menu_order = 601 create_view_class = CreateNotificationView +print('status_of_notification', settings.PUSH_NOTIFICATION) -class NotificationPreferenceAdmin(ModelAdmin): - model = NotificationPreference - menu_label = "Notification Preferences" - menu_icon = "bell" # Wagtail icon name - list_display = ("user", "receive_notifications") - search_fields = ("user__username", "user__email") # Register with Wagtail admin if settings.PUSH_NOTIFICATION: modeladmin_register(NotificationModelAdmin) -modeladmin_register(NotificationPreferenceAdmin) diff --git a/home/models.py b/home/models.py index 3091d9fe6..83e51a6c7 100644 --- a/home/models.py +++ b/home/models.py @@ -56,7 +56,7 @@ ) import iogt.iogt_globals as globals_ from django.db.models import Avg, Count - +from user_notifications.tasks import send_signup_notifications User = get_user_model() logger = logging.getLogger(__name__) @@ -591,6 +591,14 @@ def compute_average_rating(self): def compute_number_of_reviews(self): return self.number_of_reviews if self.number_of_reviews else 0 + def publish(self, *args, **kwargs): + was_published = super().publish(*args, **kwargs) + print('in-publish-fn', was_published) + # Trigger Celery notification task + send_signup_notifications.delay(self.id, "article") + + return was_published + class ArticleFeedback(models.Model): article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='feedbacks') diff --git a/home/signals.py b/home/signals.py index 74c8928db..830e47667 100644 --- a/home/signals.py +++ b/home/signals.py @@ -1,6 +1,10 @@ from django.db.models.signals import post_save, post_delete from django.dispatch import receiver from .models import ArticleFeedback +from wagtail.signals import page_published +from .models import Article +from user_notifications.tasks import send_signup_notifications + @receiver(post_save, sender=ArticleFeedback) @receiver(post_delete, sender=ArticleFeedback) @@ -10,3 +14,10 @@ def update_article_feedback_metrics(sender, instance, **kwargs): """ if instance.article: instance.article.update_feedback_metrics() + + +@receiver(page_published) +def trigger_article_notification(sender, instance, **kwargs): + if isinstance(instance, Article): + print("Article published:", instance.title) + send_signup_notifications.delay(instance.id, 'article') diff --git a/iogt/__init__.py b/iogt/__init__.py index e69de29bb..fb989c4e6 100644 --- a/iogt/__init__.py +++ b/iogt/__init__.py @@ -0,0 +1,3 @@ +from .celery import app as celery_app + +__all__ = ('celery_app',) diff --git a/iogt/celery.py b/iogt/celery.py new file mode 100644 index 000000000..f70b7b014 --- /dev/null +++ b/iogt/celery.py @@ -0,0 +1,10 @@ +import os +from celery import Celery + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'your_project.settings') + +app = Celery('your_project') + +app.config_from_object('django.conf:settings', namespace='CELERY') + +app.autodiscover_tasks() diff --git a/iogt/settings/base.py b/iogt/settings/base.py index 74de39e9b..59d5eda17 100644 --- a/iogt/settings/base.py +++ b/iogt/settings/base.py @@ -522,9 +522,9 @@ HAS_MD5_HASH_REGEX = re.compile(r"\.[a-f0-9]{12}\..*$") WEBPUSH_SETTINGS = { - 'VAPID_PUBLIC_KEY': os.getenv('VAPID_PUBLIC_KEY'), - 'VAPID_PRIVATE_KEY': os.getenv('VAPID_PRIVATE_KEY'), - 'VAPID_ADMIN_EMAIL': os.getenv('VAPID_ADMIN_EMAIL'), + 'VAPID_PUBLIC_KEY': 'BBRqGieSqpMGPqVBoV_t3iJ0Afg0qs82cSa2lF-dfcWG50KbpvoKvHmmNS39aMhyMz145lXc5ESczxSA2dCn9_w', + 'VAPID_PRIVATE_KEY': 'uu9bxQU1VtR5be7mgg2gYzGtQkWb3Ncey_jFGg-_mAU', + 'VAPID_ADMIN_EMAIL': 'ankit.chopra@nagarro.com', } COMMENTS_COMMUNITY_MODERATION = os.getenv('COMMENTS_COMMUNITY_MODERATION') == 'enable' @@ -539,7 +539,7 @@ SUPERSET_USERNAME = os.getenv('SUPERSET_USERNAME') SUPERSET_PASSWORD = os.getenv('SUPERSET_PASSWORD') -PUSH_NOTIFICATION = os.getenv('PUSH_NOTIFICATION', 'disable') == 'enable' +PUSH_NOTIFICATION = os.getenv('PUSH_NOTIFICATION', 'enable') == 'enable' JQUERY = os.getenv('JQUERY', 'enable') == 'enable' DATA_UPLOAD_MAX_NUMBER_FIELDS = int(os.getenv('DATA_UPLOAD_MAX_NUMBER_FIELDS', '1000')) diff --git a/iogt/static/js/iogt.js b/iogt/static/js/iogt.js index 07837ef3a..600677c12 100644 --- a/iogt/static/js/iogt.js +++ b/iogt/static/js/iogt.js @@ -152,12 +152,15 @@ const setItem = (key, value) => { }; const registerPushNotification = registration => { + console.log('registration', registration) if (!registration.showNotification) { + console.log('registration-show', registration.showNotification) return; } - if (Notification.permission === 'denied') { - return; - } +// if (Notification.permission === 'denied') { +// console.log('registration-denied', Notification.permission) +// return; +// } if (!'PushManager' in window) { return; } diff --git a/iogt/static/js/sw-init.js b/iogt/static/js/sw-init.js index 9e2c62375..6816d21ee 100644 --- a/iogt/static/js/sw-init.js +++ b/iogt/static/js/sw-init.js @@ -11,8 +11,10 @@ const registerSW = async () => { } const isPushNotificationRegistered = getItem('isPushNotificationRegistered', false); + console.log('isPushNotificationRegistered', isPushNotificationRegistered) if (!isPushNotificationRegistered) { if (isAuthenticated && pushNotification) { + console.log('sending push not') registerPushNotification(registration); } } diff --git a/iogt/templates/footer.html b/iogt/templates/footer.html index 84fd19a68..14461d1cc 100644 --- a/iogt/templates/footer.html +++ b/iogt/templates/footer.html @@ -20,42 +20,6 @@ {% endif %} - - - {% if request.user.is_authenticated and notification_preference.receive_notifications == None %} -
-

Would you like to enable desktop notifications?

- - -
- {% endif %} - \ No newline at end of file diff --git a/iogt/templates/sw.js b/iogt/templates/sw.js index f88cb4699..440499ce2 100644 --- a/iogt/templates/sw.js +++ b/iogt/templates/sw.js @@ -7,6 +7,29 @@ self.addEventListener('install', event => { event.waitUntil(self.skipWaiting()); }); +self.addEventListener('push', function(event) { + console.log('📩 Push received', event); + + const title = "IoGT Notification"; + const options = { + body: "You have a new message.", + icon: "https://cdn-icons-png.flaticon.com/512/3119/3119338.png", +// badge: '/static/img/badge.png', // ✅ Optional + +// data: data.url || '/', // ✅ Click redirection + requireInteraction: true // ✅ Keeps it until dismissed + + }; + + event.waitUntil( + self.registration.showNotification('New Notification', options) + ); + +}); + + + + // ✅ Activate Service Worker self.addEventListener('activate', event => { console.log("🚀 Service Workr Activated!"); diff --git a/iogt_users/forms.py b/iogt_users/forms.py index a3a6604a1..7c4db1d05 100644 --- a/iogt_users/forms.py +++ b/iogt_users/forms.py @@ -7,6 +7,7 @@ from wagtail.users.forms import UserEditForm as WagtailUserEditForm, \ UserCreationForm as WagtailUserCreationForm from user_notifications.models import UserNotificationTemplate +from user_notifications.tasks import send_signup_notifications from .fields import IogtPasswordField from .models import User @@ -49,22 +50,11 @@ def __init__(self, *args, **kwargs): def save(self, request): user = super().save(request) - - # Send notification to all staff/admin users - # for admin in User.objects.filter(is_staff=True): - template = UserNotificationTemplate.objects.filter(active=True) - if not template: - template = UserNotificationTemplate(title="Thank you for registering.", message="Thank you for registering.") - else: - template = template.latest("updated_at") - for admin in User.objects.filter(is_staff=True): - notify.send( - sender=user, - recipient=admin, - verb=template.title, - description=template.message - ) - + # 🔁 Run this logic in background + print('user', user) + print("Sending task to Celery...") + send_signup_notifications.delay(user.id, 'signup') + return user def clean_username(self): username = self.cleaned_data.get('username') diff --git a/iogt_users/templates/profile.html b/iogt_users/templates/profile.html index 21419b40f..eb54d6405 100644 --- a/iogt_users/templates/profile.html +++ b/iogt_users/templates/profile.html @@ -16,8 +16,46 @@

Hey, {{ username }} {% endblocktranslate %} {{ user.username | first | upper }} + {% if request.user.is_authenticated %} +
+

Wouldss you like to enable desktop notifications?

+ + + + + + + +
+ + +
+
+ {% endif %}

- {% endif %} + {% endif %} + {# Show notification banner only if preference is not yet set #}
{% url 'account_change_password' as change_password_url %} {% primary_button title='Change Digital Pin' href=change_password_url icon_path='icons/lock.svg' extra_classnames='change-digital-pin' %} @@ -25,4 +63,30 @@

{% url 'account_logout' as logout_url %} {% primary_button title='Log out' href=logout_url icon_path='icons/arrow_icon_left.svg' extra_classnames='logout-btn' %}

-{% endblock %} + + + +{% endblock %} \ No newline at end of file diff --git a/iogt_users/views.py b/iogt_users/views.py index c9b5df5a3..6b81cb104 100644 --- a/iogt_users/views.py +++ b/iogt_users/views.py @@ -10,18 +10,29 @@ from django.views import View from django.contrib.auth import get_user_model from django.http import JsonResponse +from wagtail.models import Locale from iogt import settings from email_service.mailjet_email_sender import send_email_via_mailjet - +from user_notifications.models import NotificationPreference, NotificationTag @method_decorator(login_required, name='dispatch') class UserDetailView(TemplateView): template_name = 'profile.html' def get_context_data(self, **kwargs): - return {'user': self.request.user} + context = super().get_context_data(**kwargs) + if self.request.user.is_authenticated: + context['notification_preference'] = NotificationPreference.objects.filter(user=self.request.user).first() + else: + context['notification_preference'] = None + context['notification_tags'] = NotificationTag.objects.all() + context['available_languages'] = Locale.objects.all() + context['user'] = self.request.user + print('tags', context['notification_tags']) + print('available_languages', context['available_languages']) + return context @method_decorator(login_required, name='dispatch') diff --git a/questionnaires/apps.py b/questionnaires/apps.py index 198137740..d69623622 100644 --- a/questionnaires/apps.py +++ b/questionnaires/apps.py @@ -3,3 +3,6 @@ class QuestionnairesConfig(AppConfig): name = 'questionnaires' + + def ready(self): + import questionnaires.signals # diff --git a/questionnaires/signals.py b/questionnaires/signals.py new file mode 100644 index 000000000..e710d8503 --- /dev/null +++ b/questionnaires/signals.py @@ -0,0 +1,12 @@ +from django.dispatch import receiver +from wagtail.signals import page_published +from .models import Survey +from user_notifications.tasks import send_signup_notifications + + +@receiver(page_published) +def trigger_survey_notification(sender, instance, **kwargs): + print('in -trigger-function---------------------------------------') + if isinstance(instance, Survey): + print("📢 Article published:", instance.title) + send_signup_notifications.delay(instance.id, 'survey') \ No newline at end of file diff --git a/requirements.dev.in b/requirements.dev.in index 37bf687d8..29e871ed5 100644 --- a/requirements.dev.in +++ b/requirements.dev.in @@ -9,3 +9,5 @@ pytest-django selenium==4.9.1 wagtail-factories django-notifications-hq==1.8.3 +celery==5.3.6 +backports.zoneinfo; python_version < "3.9" diff --git a/requirements.dev.txt b/requirements.dev.txt index c4c1cd8ce..ce07d3e09 100644 --- a/requirements.dev.txt +++ b/requirements.dev.txt @@ -2,79 +2,381 @@ # This file is autogenerated by pip-compile with Python 3.8 # by the following command: # -# pip-compile requirements.dev.in +# pip-compile --generate-hashes requirements.dev.in # -anyascii==0.3.2 +amqp==5.3.1 \ + --hash=sha256:43b3319e1b4e7d1251833a93d672b4af1e40f3d632d479b98661a95f117880a2 \ + --hash=sha256:cddc00c725449522023bad949f70fff7b48f0b1ade74d170a6f10ab044739432 + # via kombu +anyascii==0.3.2 \ + --hash=sha256:3b3beef6fc43d9036d3b0529050b0c48bfad8bc960e9e562d7223cfb94fe45d4 \ + --hash=sha256:9d5d32ef844fe225b8bc7cba7f950534fae4da27a9bf3a6bea2cb0ea46ce4730 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # wagtail -asgiref==3.8.1 +asgiref==3.8.1 \ + --hash=sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47 \ + --hash=sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # django -attrs==23.2.0 +attrs==23.2.0 \ + --hash=sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30 \ + --hash=sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1 # via # outcome # trio -beautifulsoup4==4.9.3 +backports-zoneinfo[tzdata]==0.2.1 ; python_version < "3.9" \ + --hash=sha256:17746bd546106fa389c51dbea67c8b7c8f0d14b5526a579ca6ccf5ed72c526cf \ + --hash=sha256:1b13e654a55cd45672cb54ed12148cd33628f672548f373963b0bff67b217328 \ + --hash=sha256:1c5742112073a563c81f786e77514969acb58649bcdf6cdf0b4ed31a348d4546 \ + --hash=sha256:4a0f800587060bf8880f954dbef70de6c11bbe59c673c3d818921f042f9954a6 \ + --hash=sha256:5c144945a7752ca544b4b78c8c41544cdfaf9786f25fe5ffb10e838e19a27570 \ + --hash=sha256:7b0a64cda4145548fed9efc10322770f929b944ce5cee6c0dfe0c87bf4c0c8c9 \ + --hash=sha256:8439c030a11780786a2002261569bdf362264f605dfa4d65090b64b05c9f79a7 \ + --hash=sha256:8961c0f32cd0336fb8e8ead11a1f8cd99ec07145ec2931122faaac1c8f7fd987 \ + --hash=sha256:89a48c0d158a3cc3f654da4c2de1ceba85263fafb861b98b59040a5086259722 \ + --hash=sha256:a76b38c52400b762e48131494ba26be363491ac4f9a04c1b7e92483d169f6582 \ + --hash=sha256:da6013fd84a690242c310d77ddb8441a559e9cb3d3d59ebac9aca1a57b2e18bc \ + --hash=sha256:e55b384612d93be96506932a786bbcde5a2db7a9e6a4bb4bffe8b733f5b9036b \ + --hash=sha256:e81b76cace8eda1fca50e345242ba977f9be6ae3945af8d46326d776b4cf78d1 \ + --hash=sha256:e8236383a20872c0cdf5a62b554b27538db7fa1bbec52429d8d106effbaeca08 \ + --hash=sha256:f04e857b59d9d1ccc39ce2da1021d196e47234873820cbeaad210724b1ee28ac \ + --hash=sha256:fadbfe37f74051d024037f223b8e001611eac868b5c5b06144ef4d8b799862f2 + # via + # -r requirements.dev.in + # celery + # kombu +beautifulsoup4==4.9.3 \ + --hash=sha256:4c98143716ef1cb40bf7f39a8e3eec8f8b009509e74904ba3a7b315431577e35 \ + --hash=sha256:84729e322ad1d5b4d25f805bfa05b902dd96450f43842c4e99067d5e1369eb25 \ + --hash=sha256:fff47e031e34ec82bf17e00da8f592fe7de69aeea38be00523c04623c04fb666 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # wagtail -bleach==4.1.0 +billiard==4.2.1 \ + --hash=sha256:12b641b0c539073fc8d3f5b8b7be998956665c4233c7c1fcd66a7e677c4fb36f \ + --hash=sha256:40b59a4ac8806ba2c2369ea98d876bc6108b051c227baffd928c644d15d8f3cb + # via celery +bleach==4.1.0 \ + --hash=sha256:0900d8b37eba61a802ee40ac0061f8c2b5dee29c1927dd1d233e075ebf5a71da \ + --hash=sha256:4d2651ab93271d1129ac9cbc679f524565cc8a1b791909c4a51eac4446a15994 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # wagtail-markdown -cairocffi==1.7.1 +cairocffi==1.7.1 \ + --hash=sha256:2e48ee864884ec4a3a34bfa8c9ab9999f688286eb714a15a43ec9d068c36557b \ + --hash=sha256:9803a0e11f6c962f3b0ae2ec8ba6ae45e957a146a004697a1ac1bbf16b073b3f # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # cairosvg -cairosvg==2.7.1 +cairosvg==2.7.1 \ + --hash=sha256:432531d72347291b9a9ebfb6777026b607563fd8719c46ee742db0aef7271ba0 \ + --hash=sha256:8a5222d4e6c3f86f1f7046b63246877a63b49923a1cd202184c3a634ef546b3b # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt -certifi==2024.7.4 +celery==5.3.6 \ + --hash=sha256:870cc71d737c0200c397290d730344cc991d13a057534353d124c9380267aab9 \ + --hash=sha256:9da4ea0118d232ce97dff5ed4974587fb1c0ff5c10042eb15278487cdd27d1af + # via -r requirements.dev.in +certifi==2024.7.4 \ + --hash=sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b \ + --hash=sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # elasticsearch # requests # selenium -cffi==1.16.0 +cffi==1.16.0 \ + --hash=sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc \ + --hash=sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a \ + --hash=sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417 \ + --hash=sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab \ + --hash=sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520 \ + --hash=sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36 \ + --hash=sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743 \ + --hash=sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8 \ + --hash=sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed \ + --hash=sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684 \ + --hash=sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56 \ + --hash=sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324 \ + --hash=sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d \ + --hash=sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235 \ + --hash=sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e \ + --hash=sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088 \ + --hash=sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000 \ + --hash=sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7 \ + --hash=sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e \ + --hash=sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673 \ + --hash=sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c \ + --hash=sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe \ + --hash=sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2 \ + --hash=sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098 \ + --hash=sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8 \ + --hash=sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a \ + --hash=sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0 \ + --hash=sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b \ + --hash=sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896 \ + --hash=sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e \ + --hash=sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9 \ + --hash=sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2 \ + --hash=sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b \ + --hash=sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6 \ + --hash=sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404 \ + --hash=sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f \ + --hash=sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0 \ + --hash=sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4 \ + --hash=sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc \ + --hash=sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936 \ + --hash=sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba \ + --hash=sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872 \ + --hash=sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb \ + --hash=sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614 \ + --hash=sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1 \ + --hash=sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d \ + --hash=sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969 \ + --hash=sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b \ + --hash=sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4 \ + --hash=sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627 \ + --hash=sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956 \ + --hash=sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # cairocffi # cryptography # trio -charset-normalizer==3.3.2 +charset-normalizer==3.3.2 \ + --hash=sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027 \ + --hash=sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087 \ + --hash=sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786 \ + --hash=sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8 \ + --hash=sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09 \ + --hash=sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185 \ + --hash=sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574 \ + --hash=sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e \ + --hash=sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519 \ + --hash=sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898 \ + --hash=sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269 \ + --hash=sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3 \ + --hash=sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f \ + --hash=sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6 \ + --hash=sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8 \ + --hash=sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a \ + --hash=sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73 \ + --hash=sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc \ + --hash=sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714 \ + --hash=sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2 \ + --hash=sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc \ + --hash=sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce \ + --hash=sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d \ + --hash=sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e \ + --hash=sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6 \ + --hash=sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269 \ + --hash=sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 \ + --hash=sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d \ + --hash=sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a \ + --hash=sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4 \ + --hash=sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 \ + --hash=sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d \ + --hash=sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0 \ + --hash=sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed \ + --hash=sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068 \ + --hash=sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac \ + --hash=sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25 \ + --hash=sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 \ + --hash=sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab \ + --hash=sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26 \ + --hash=sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2 \ + --hash=sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db \ + --hash=sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f \ + --hash=sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5 \ + --hash=sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99 \ + --hash=sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c \ + --hash=sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d \ + --hash=sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811 \ + --hash=sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa \ + --hash=sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a \ + --hash=sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03 \ + --hash=sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b \ + --hash=sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04 \ + --hash=sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c \ + --hash=sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001 \ + --hash=sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458 \ + --hash=sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389 \ + --hash=sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99 \ + --hash=sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985 \ + --hash=sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537 \ + --hash=sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238 \ + --hash=sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f \ + --hash=sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d \ + --hash=sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796 \ + --hash=sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a \ + --hash=sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143 \ + --hash=sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8 \ + --hash=sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c \ + --hash=sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5 \ + --hash=sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5 \ + --hash=sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711 \ + --hash=sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4 \ + --hash=sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6 \ + --hash=sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c \ + --hash=sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7 \ + --hash=sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4 \ + --hash=sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b \ + --hash=sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae \ + --hash=sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12 \ + --hash=sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c \ + --hash=sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae \ + --hash=sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8 \ + --hash=sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887 \ + --hash=sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b \ + --hash=sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4 \ + --hash=sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f \ + --hash=sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5 \ + --hash=sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33 \ + --hash=sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519 \ + --hash=sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # requests -click==8.1.7 +click==8.1.7 \ + --hash=sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28 \ + --hash=sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # celery + # click-didyoumean + # click-plugins + # click-repl # rq -colorama==0.4.6 +click-didyoumean==0.3.1 \ + --hash=sha256:4f82fdff0dbe64ef8ab2279bd6aa3f6a99c3b28c05aa09cbfc07c9d7fbb5a463 \ + --hash=sha256:5c4bb6007cfea5f2fd6583a2fb6701a22a41eb98957e63d0fac41c10e7c3117c + # via celery +click-plugins==1.1.1.2 \ + --hash=sha256:008d65743833ffc1f5417bf0e78e8d2c23aab04d9745ba817bd3e71b0feb6aa6 \ + --hash=sha256:d7af3984a99d243c131aa1a828331e7630f4a88a9741fd05c927b204bcf92261 + # via celery +click-repl==0.3.0 \ + --hash=sha256:17849c23dba3d667247dc4defe1757fff98694e90fe37474f3feebb69ced26a9 \ + --hash=sha256:fb7e06deb8da8de86180a33a9da97ac316751c094c6899382da7feeeeb51b812 + # via celery +colorama==0.4.6 \ + --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ + --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # click # pytest # tqdm -coverage==7.6.0 +coverage==7.6.0 \ + --hash=sha256:0086cd4fc71b7d485ac93ca4239c8f75732c2ae3ba83f6be1c9be59d9e2c6382 \ + --hash=sha256:01c322ef2bbe15057bc4bf132b525b7e3f7206f071799eb8aa6ad1940bcf5fb1 \ + --hash=sha256:03cafe82c1b32b770a29fd6de923625ccac3185a54a5e66606da26d105f37dac \ + --hash=sha256:044a0985a4f25b335882b0966625270a8d9db3d3409ddc49a4eb00b0ef5e8cee \ + --hash=sha256:07ed352205574aad067482e53dd606926afebcb5590653121063fbf4e2175166 \ + --hash=sha256:0d1b923fc4a40c5832be4f35a5dab0e5ff89cddf83bb4174499e02ea089daf57 \ + --hash=sha256:0e7b27d04131c46e6894f23a4ae186a6a2207209a05df5b6ad4caee6d54a222c \ + --hash=sha256:1fad32ee9b27350687035cb5fdf9145bc9cf0a094a9577d43e909948ebcfa27b \ + --hash=sha256:289cc803fa1dc901f84701ac10c9ee873619320f2f9aff38794db4a4a0268d51 \ + --hash=sha256:3c59105f8d58ce500f348c5b56163a4113a440dad6daa2294b5052a10db866da \ + --hash=sha256:46c3d091059ad0b9c59d1034de74a7f36dcfa7f6d3bde782c49deb42438f2450 \ + --hash=sha256:482855914928c8175735a2a59c8dc5806cf7d8f032e4820d52e845d1f731dca2 \ + --hash=sha256:49c76cdfa13015c4560702574bad67f0e15ca5a2872c6a125f6327ead2b731dd \ + --hash=sha256:4b03741e70fb811d1a9a1d75355cf391f274ed85847f4b78e35459899f57af4d \ + --hash=sha256:4bea27c4269234e06f621f3fac3925f56ff34bc14521484b8f66a580aacc2e7d \ + --hash=sha256:4d5fae0a22dc86259dee66f2cc6c1d3e490c4a1214d7daa2a93d07491c5c04b6 \ + --hash=sha256:543ef9179bc55edfd895154a51792b01c017c87af0ebaae092720152e19e42ca \ + --hash=sha256:54dece71673b3187c86226c3ca793c5f891f9fc3d8aa183f2e3653da18566169 \ + --hash=sha256:6379688fb4cfa921ae349c76eb1a9ab26b65f32b03d46bb0eed841fd4cb6afb1 \ + --hash=sha256:65fa405b837060db569a61ec368b74688f429b32fa47a8929a7a2f9b47183713 \ + --hash=sha256:6616d1c9bf1e3faea78711ee42a8b972367d82ceae233ec0ac61cc7fec09fa6b \ + --hash=sha256:6fe885135c8a479d3e37a7aae61cbd3a0fb2deccb4dda3c25f92a49189f766d6 \ + --hash=sha256:7221f9ac9dad9492cecab6f676b3eaf9185141539d5c9689d13fd6b0d7de840c \ + --hash=sha256:76d5f82213aa78098b9b964ea89de4617e70e0d43e97900c2778a50856dac605 \ + --hash=sha256:7792f0ab20df8071d669d929c75c97fecfa6bcab82c10ee4adb91c7a54055463 \ + --hash=sha256:831b476d79408ab6ccfadaaf199906c833f02fdb32c9ab907b1d4aa0713cfa3b \ + --hash=sha256:9146579352d7b5f6412735d0f203bbd8d00113a680b66565e205bc605ef81bc6 \ + --hash=sha256:9cc44bf0315268e253bf563f3560e6c004efe38f76db03a1558274a6e04bf5d5 \ + --hash=sha256:a73d18625f6a8a1cbb11eadc1d03929f9510f4131879288e3f7922097a429f63 \ + --hash=sha256:a8659fd33ee9e6ca03950cfdcdf271d645cf681609153f218826dd9805ab585c \ + --hash=sha256:a94925102c89247530ae1dab7dc02c690942566f22e189cbd53579b0693c0783 \ + --hash=sha256:ad4567d6c334c46046d1c4c20024de2a1c3abc626817ae21ae3da600f5779b44 \ + --hash=sha256:b2e16f4cd2bc4d88ba30ca2d3bbf2f21f00f382cf4e1ce3b1ddc96c634bc48ca \ + --hash=sha256:bbdf9a72403110a3bdae77948b8011f644571311c2fb35ee15f0f10a8fc082e8 \ + --hash=sha256:beb08e8508e53a568811016e59f3234d29c2583f6b6e28572f0954a6b4f7e03d \ + --hash=sha256:c4cbe651f3904e28f3a55d6f371203049034b4ddbce65a54527a3f189ca3b390 \ + --hash=sha256:c7b525ab52ce18c57ae232ba6f7010297a87ced82a2383b1afd238849c1ff933 \ + --hash=sha256:ca5d79cfdae420a1d52bf177de4bc2289c321d6c961ae321503b2ca59c17ae67 \ + --hash=sha256:cdab02a0a941af190df8782aafc591ef3ad08824f97850b015c8c6a8b3877b0b \ + --hash=sha256:d17c6a415d68cfe1091d3296ba5749d3d8696e42c37fca5d4860c5bf7b729f03 \ + --hash=sha256:d39bd10f0ae453554798b125d2f39884290c480f56e8a02ba7a6ed552005243b \ + --hash=sha256:d4b3cd1ca7cd73d229487fa5caca9e4bc1f0bca96526b922d61053ea751fe791 \ + --hash=sha256:d50a252b23b9b4dfeefc1f663c568a221092cbaded20a05a11665d0dbec9b8fb \ + --hash=sha256:da8549d17489cd52f85a9829d0e1d91059359b3c54a26f28bec2c5d369524807 \ + --hash=sha256:dcd070b5b585b50e6617e8972f3fbbee786afca71b1936ac06257f7e178f00f6 \ + --hash=sha256:ddaaa91bfc4477d2871442bbf30a125e8fe6b05da8a0015507bfbf4718228ab2 \ + --hash=sha256:df423f351b162a702c053d5dddc0fc0ef9a9e27ea3f449781ace5f906b664428 \ + --hash=sha256:dff044f661f59dace805eedb4a7404c573b6ff0cdba4a524141bc63d7be5c7fd \ + --hash=sha256:e7e128f85c0b419907d1f38e616c4f1e9f1d1b37a7949f44df9a73d5da5cd53c \ + --hash=sha256:ed8d1d1821ba5fc88d4a4f45387b65de52382fa3ef1f0115a4f7a20cdfab0e94 \ + --hash=sha256:f2501d60d7497fd55e391f423f965bbe9e650e9ffc3c627d5f0ac516026000b8 \ + --hash=sha256:f7db0b6ae1f96ae41afe626095149ecd1b212b424626175a6633c2999eaad45b # via -r requirements.dev.in -cryptography==42.0.8 +cryptography==42.0.8 \ + --hash=sha256:013629ae70b40af70c9a7a5db40abe5d9054e6f4380e50ce769947b73bf3caad \ + --hash=sha256:2346b911eb349ab547076f47f2e035fc8ff2c02380a7cbbf8d87114fa0f1c583 \ + --hash=sha256:2f66d9cd9147ee495a8374a45ca445819f8929a3efcd2e3df6428e46c3cbb10b \ + --hash=sha256:2f88d197e66c65be5e42cd72e5c18afbfae3f741742070e3019ac8f4ac57262c \ + --hash=sha256:31f721658a29331f895a5a54e7e82075554ccfb8b163a18719d342f5ffe5ecb1 \ + --hash=sha256:343728aac38decfdeecf55ecab3264b015be68fc2816ca800db649607aeee648 \ + --hash=sha256:5226d5d21ab681f432a9c1cf8b658c0cb02533eece706b155e5fbd8a0cdd3949 \ + --hash=sha256:57080dee41209e556a9a4ce60d229244f7a66ef52750f813bfbe18959770cfba \ + --hash=sha256:5a94eccb2a81a309806027e1670a358b99b8fe8bfe9f8d329f27d72c094dde8c \ + --hash=sha256:6b7c4f03ce01afd3b76cf69a5455caa9cfa3de8c8f493e0d3ab7d20611c8dae9 \ + --hash=sha256:7016f837e15b0a1c119d27ecd89b3515f01f90a8615ed5e9427e30d9cdbfed3d \ + --hash=sha256:81884c4d096c272f00aeb1f11cf62ccd39763581645b0812e99a91505fa48e0c \ + --hash=sha256:81d8a521705787afe7a18d5bfb47ea9d9cc068206270aad0b96a725022e18d2e \ + --hash=sha256:8d09d05439ce7baa8e9e95b07ec5b6c886f548deb7e0f69ef25f64b3bce842f2 \ + --hash=sha256:961e61cefdcb06e0c6d7e3a1b22ebe8b996eb2bf50614e89384be54c48c6b63d \ + --hash=sha256:9c0c1716c8447ee7dbf08d6db2e5c41c688544c61074b54fc4564196f55c25a7 \ + --hash=sha256:a0608251135d0e03111152e41f0cc2392d1e74e35703960d4190b2e0f4ca9c70 \ + --hash=sha256:a0c5b2b0585b6af82d7e385f55a8bc568abff8923af147ee3c07bd8b42cda8b2 \ + --hash=sha256:ad803773e9df0b92e0a817d22fd8a3675493f690b96130a5e24f1b8fabbea9c7 \ + --hash=sha256:b297f90c5723d04bcc8265fc2a0f86d4ea2e0f7ab4b6994459548d3a6b992a14 \ + --hash=sha256:ba4f0a211697362e89ad822e667d8d340b4d8d55fae72cdd619389fb5912eefe \ + --hash=sha256:c4783183f7cb757b73b2ae9aed6599b96338eb957233c58ca8f49a49cc32fd5e \ + --hash=sha256:c9bb2ae11bfbab395bdd072985abde58ea9860ed84e59dbc0463a5d0159f5b71 \ + --hash=sha256:cafb92b2bc622cd1aa6a1dce4b93307792633f4c5fe1f46c6b97cf67073ec961 \ + --hash=sha256:d45b940883a03e19e944456a558b67a41160e367a719833c53de6911cabba2b7 \ + --hash=sha256:dc0fdf6787f37b1c6b08e6dfc892d9d068b5bdb671198c72072828b80bd5fe4c \ + --hash=sha256:dea567d1b0e8bc5764b9443858b673b734100c2871dc93163f58c46a97a83d28 \ + --hash=sha256:dec9b018df185f08483f294cae6ccac29e7a6e0678996587363dc352dc65c842 \ + --hash=sha256:e3ec3672626e1b9e55afd0df6d774ff0e953452886e06e0f1eb7eb0c832e8902 \ + --hash=sha256:e599b53fd95357d92304510fb7bda8523ed1f79ca98dce2f43c115950aa78801 \ + --hash=sha256:fa76fbb7596cc5839320000cdd5d0955313696d9511debab7ee7278fc8b5c84a \ + --hash=sha256:fff12c88a672ab9c9c1cf7b0c80e3ad9e2ebd9d828d955c126be4fd3e5578c9e # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # http-ece # py-vapid # pyjwt # pywebpush -cssselect2==0.7.0 +cssselect2==0.7.0 \ + --hash=sha256:1ccd984dab89fc68955043aca4e1b03e0cf29cad9880f6e28e3ba7a74b14aa5a \ + --hash=sha256:fd23a65bfd444595913f02fc71f6b286c29261e354c41d722ca7a261a49b5969 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # cairosvg -defusedxml==0.7.1 +defusedxml==0.7.1 \ + --hash=sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69 \ + --hash=sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # cairosvg # python3-openid -django==3.2.25 +django==3.2.25 \ + --hash=sha256:7ca38a78654aee72378594d63e51636c04b8e28574f5505dff630895b5472777 \ + --hash=sha256:a52ea7fcf280b16f7b739cec38fa6d3f8953a5456986944c3ca97e79882b4e38 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # django-allauth @@ -101,73 +403,118 @@ django==3.2.25 # wagtail # wagtail-localize # wagtailmedia -django-allauth==0.54.0 +django-allauth==0.54.0 \ + --hash=sha256:120e265f802b65738899c6cb627b827fde46a4d03067034c633f516c2adf3e3e # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt -django-appconf==1.0.6 +django-appconf==1.0.6 \ + --hash=sha256:c3ae442fba1ff7ec830412c5184b17169a7a1e71cf0864a4c3f93cf4c98a1993 \ + --hash=sha256:cfe87ea827c4ee04b9a70fab90b86d704cb02f2981f89da8423cb0fabf88efbf # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # django-compressor -django-cogwheels==0.3 +django-cogwheels==0.3 \ + --hash=sha256:197bd05e7114403d7301214b3f8a371c4fb6039cf21c811f099438b167b5ed21 \ + --hash=sha256:848a4d9f2c96c582a4a4f2e7c276dfd95ab3905748cae13bb7c4b365a6717e94 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # wagtailmenus -django-comments-xtd==2.9.13 +django-comments-xtd==2.9.13 \ + --hash=sha256:0d91e3cc76eae6f30e83b12fb09708e5407664d9daa7b9c1101d7377897f7b42 \ + --hash=sha256:b289b6754d6618fb29e4279c6a1c6a270bc9495e161c42193d8b6216a4884802 # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt -django-compressor==2.4.1 +django-compressor==2.4.1 \ + --hash=sha256:3358077605c146fdcca5f9eaffb50aa5dbe15f238f8854679115ebf31c0415e0 \ + --hash=sha256:f8313f59d5e65712fc28787d084fe834997c9dfa92d064a1a3ec3d3366594d04 # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt -django-contrib-comments==2.2.0 +django-contrib-comments==2.2.0 \ + --hash=sha256:2ca79060bbc8fc5b636981ef6e50f35ab83649af75fc1be47bf770636be3271c \ + --hash=sha256:48de00f15677e016a216aeff205d6e00e4391c9a5702136c64119c472b7356da # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # django-comments-xtd -django-debug-toolbar==4.3.0 +django-debug-toolbar==4.3.0 \ + --hash=sha256:0b0dddee5ea29b9cb678593bc0d7a6d76b21d7799cb68e091a2148341a80f3c4 \ + --hash=sha256:e09b7dcb8417b743234dfc57c95a7c1d1d87a88844abd13b4c5387f807b31bf6 # via -r requirements.dev.in -django-extensions==3.1.5 +django-extensions==3.1.5 \ + --hash=sha256:28e1e1bf49f0e00307ba574d645b0af3564c981a6dfc87209d48cb98f77d0b1a \ + --hash=sha256:9238b9e016bb0009d621e05cf56ea8ce5cce9b32e91ad2026996a7377ca28069 # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt -django-filter==2.4.0 +django-filter==2.4.0 \ + --hash=sha256:84e9d5bb93f237e451db814ed422a3a625751cbc9968b484ecc74964a8696b06 \ + --hash=sha256:e00d32cebdb3d54273c48f4f878f898dced8d5dfaad009438fe61ebdf535ace1 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # wagtail -django-health-check==3.16.5 +django-health-check==3.16.5 \ + --hash=sha256:1edfd49293ccebbce29f9da609c407f307aee240ab799ab4201031341ae78c0f \ + --hash=sha256:8d66781a0ea82b1a8b44878187b38a27370e94f18287312e39be0593e72d8983 # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt -django-model-utils==5.0.0 +django-model-utils==5.0.0 \ + --hash=sha256:041cdd6230d2fbf6cd943e1969318bce762272077f4ecd333ab2263924b4e5eb \ + --hash=sha256:fec78e6c323d565a221f7c4edc703f4567d7bb1caeafe1acd16a80c5ff82056b # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # django-notifications-hq -django-modelcluster==6.3 +django-modelcluster==6.3 \ + --hash=sha256:0caed8a0e889f3abb92f144670878a466ef954ffa6c4c7b9c80e6426b720a49d \ + --hash=sha256:a8783d6565a0663f41cd6003ea361c3a5711e8a2a326160f1ec1eceb3e973d4f # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # wagtail -django-notifications-hq==1.8.3 +django-notifications-hq==1.8.3 \ + --hash=sha256:0f4b216bb382b7c7c4eef273eb211e59c1c6a0ea38cba6077415ac031d330725 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # -r requirements.dev.in -django-permissionedforms==0.1 +django-permissionedforms==0.1 \ + --hash=sha256:4340bb20c4477fffb13b4cc5cccf9f1b1010b64f79956c291c72d2ad2ed243f8 \ + --hash=sha256:d341a961a27cc77fde8cc42141c6ab55cc1f0cb886963cc2d6967b9674fa47d6 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # wagtail -django-redis==5.2.0 +django-redis==5.2.0 \ + --hash=sha256:1d037dc02b11ad7aa11f655d26dac3fb1af32630f61ef4428860a2e29ff92026 \ + --hash=sha256:8a99e5582c79f894168f5865c52bd921213253b7fd64d16733ae4591564465de # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt -django-rq==2.4.1 +django-rq==2.4.1 \ + --hash=sha256:23981f83c537178cbbf730f192c13e99cede2204e9d917b1c1c80c42215dd227 \ + --hash=sha256:f09059ab37403a47c7933bca396fabb7f3058732d132462eade5333bc4bcac5f # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # django-translation-manager -django-sass-processor==1.0.1 +django-sass-processor==1.0.1 \ + --hash=sha256:1f043180c47754018e803a77da003377f5ea6558de57cd6946eb27a32e9c16a2 \ + --hash=sha256:dcaad47c591a2d52689c1bd209259e922e902d886293f0d5c9e0d1a4eb85eda2 # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt -django-taggit==2.1.0 +django-taggit==2.1.0 \ + --hash=sha256:61547a23fc99967c9304107414a09e662b459f4163dbbae32e60b8ba40c34d05 \ + --hash=sha256:a9f41e4ad58efe4b28d86f274728ee87eb98eeae90c9eb4b4efad39e5068184e # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # wagtail -django-test-plus==2.2.4 +django-test-plus==2.2.4 \ + --hash=sha256:06488209a07dca60dc2bbeaeae5ce340d17344163e0b121709cdac7405c6d9ef \ + --hash=sha256:96e4e16fabd3e0339a4b46e02a0a88c92c19800de38d00446571ea036614d332 # via -r requirements.dev.in -django-translation-manager==1.3.0 +django-translation-manager==1.3.0 \ + --hash=sha256:1e3143f48f9ba4d5452d72f55195142c434ea63786546251ae694508df4eb7b1 \ + --hash=sha256:9215b0149e78eaa13992a48367bf4ef28ef450e35863ea3ce7194b3558617bcf # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt -django-treebeard==4.7.1 +django-treebeard==4.7.1 \ + --hash=sha256:846e462904b437155f76e04907ba4e48480716855f88b898df4122bdcfbd6e98 \ + --hash=sha256:995c7120153ab999898fe3043bbdcd8a0fc77cc106eb94de7350e9d02c885135 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # wagtail -django-webpush==0.3.4 +django-webpush==0.3.4 \ + --hash=sha256:28cbe7da20f1df5b61d859f61e2d11d4076de1c367aa048d654894fb8f324065 \ + --hash=sha256:a123102dede1a959f667e075ed746ac5b7d4a8622320162eba41a507a835e1e4 \ + --hash=sha256:a2613784e822e2dde27086fb20b6d1a2b76e4d5dc8271607aecd45c98a3b7954 # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt -djangorestframework==3.13.1 +djangorestframework==3.13.1 \ + --hash=sha256:0c33407ce23acc68eca2a6e46424b008c9c02eceb8cf18581921d0092bc1f2ee \ + --hash=sha256:24c4bf58ed7e85d1fe4ba250ab2da926d263cd57d64b03e8dcef0ac683f8b1aa # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # django-comments-xtd @@ -175,136 +522,396 @@ djangorestframework==3.13.1 # djangorestframework-simplejwt # drf-yasg # wagtail -djangorestframework-simplejwt==5.3.1 +djangorestframework-simplejwt==5.3.1 \ + --hash=sha256:381bc966aa46913905629d472cd72ad45faa265509764e20ffd440164c88d220 \ + --hash=sha256:6c4bd37537440bc439564ebf7d6085e74c5411485197073f508ebdfa34bc9fae # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt -docutils==0.20.1 +docutils==0.20.1 \ + --hash=sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6 \ + --hash=sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # django-comments-xtd -draftjs-exporter==2.1.7 +draftjs-exporter==2.1.7 \ + --hash=sha256:5839cbc29d7bce2fb99837a404ca40c3a07313f2a20e2700de7ad6aa9a9a18fb \ + --hash=sha256:d415a9964690a2cddb66a31ef32dd46c277e9b80434b94e39e3043188ed83e33 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # wagtail -drf-yasg==1.21.7 +drf-yasg==1.21.7 \ + --hash=sha256:4c3b93068b3dfca6969ab111155e4dd6f7b2d680b98778de8fd460b7837bdb0d \ + --hash=sha256:f85642072c35e684356475781b7ecf5d218fff2c6185c040664dd49f0a4be181 # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt -elasticsearch==7.17.9 +elasticsearch==7.17.9 \ + --hash=sha256:0e2454645dc00517dee4c6de3863411a9c5f1955d013c5fefa29123dadc92f98 \ + --hash=sha256:66c4ece2adfe7cc120e2b6a6798a1fd5c777aecf82eec39bb95cef7cfc7ea2b3 # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt -et-xmlfile==1.1.0 +et-xmlfile==1.1.0 \ + --hash=sha256:8eb9e2bc2f8c97e37a2dc85a09ecdcdec9d8a396530a6d5a33b30b9a92da0c5c \ + --hash=sha256:a2ba85d1d6a74ef63837eed693bcb89c3f752169b0e3e7ae5b16ca5e1b3deada # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # openpyxl -exceptiongroup==1.3.0 +exceptiongroup==1.3.0 \ + --hash=sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10 \ + --hash=sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88 # via # pytest # trio # trio-websocket -factory-boy==3.3.0 +factory-boy==3.3.0 \ + --hash=sha256:a2cdbdb63228177aa4f1c52f4b6d83fab2b8623bf602c7dedd7eb83c0f69c04c \ + --hash=sha256:bc76d97d1a65bbd9842a6d722882098eb549ec8ee1081f9fb2e8ff29f0c300f1 # via # -r requirements.dev.in # wagtail-factories -faker==26.0.0 +faker==26.0.0 \ + --hash=sha256:0f60978314973de02c00474c2ae899785a42b2cf4f41b7987e93c132a2b8a4a9 \ + --hash=sha256:886ee28219be96949cd21ecc96c4c742ee1680e77f687b095202c8def1a08f06 # via # -r requirements.dev.in # factory-boy -h11==0.14.0 +h11==0.14.0 \ + --hash=sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d \ + --hash=sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761 # via wsproto -html5lib==1.1 +html5lib==1.1 \ + --hash=sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d \ + --hash=sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # wagtail -http-ece==1.2.0 +http-ece==1.2.0 \ + --hash=sha256:b5920f8efb8e1b5fb025713e3b36fda54336262010634b26dc1f98f85d1eb3de # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # pywebpush -idna==3.7 +idna==3.7 \ + --hash=sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc \ + --hash=sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # requests # trio -importlib-metadata==8.5.0 +importlib-metadata==8.5.0 \ + --hash=sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b \ + --hash=sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # markdown -inflection==0.5.1 +inflection==0.5.1 \ + --hash=sha256:1a29730d366e996aaacffb2f1f1cb9593dc38e2ddd30c91250c6dde09ea9b417 \ + --hash=sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # drf-yasg -iniconfig==2.0.0 +iniconfig==2.0.0 \ + --hash=sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3 \ + --hash=sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374 # via pytest -jsonfield==3.1.0 +jsonfield==3.1.0 \ + --hash=sha256:7e4e84597de21eeaeeaaa7cc5da08c61c48a9b64d0c446b2d71255d01812887a \ + --hash=sha256:df857811587f252b97bafba42e02805e70a398a7a47870bc6358a0308dd689ed # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # django-notifications-hq -l18n==2021.3 +kombu==5.5.4 \ + --hash=sha256:886600168275ebeada93b888e831352fe578168342f0d1d5833d88ba0d847363 \ + --hash=sha256:a12ed0557c238897d8e518f1d1fdf84bd1516c5e305af2dacd85c2015115feb8 + # via celery +l18n==2021.3 \ + --hash=sha256:1956e890d673d17135cc20913253c154f6bc1c00266c22b7d503cc1a5a42d848 \ + --hash=sha256:78495d1df95b6f7dcc694d1ba8994df709c463a1cbac1bf016e1b9a5ce7280b9 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # wagtail -libsass==0.21.0 +libsass==0.21.0 \ + --hash=sha256:06c8776417fe930714bdc930a3d7e795ae3d72be6ac883ff72a1b8f7c49e5ffb \ + --hash=sha256:12f39712de38689a8b785b7db41d3ba2ea1d46f9379d81ea4595802d91fa6529 \ + --hash=sha256:1e25dd9047a9392d3c59a0b869e0404f2b325a03871ee45285ee33b3664f5613 \ + --hash=sha256:659ae41af8708681fa3ec73f47b9735a6725e71c3b66ff570bfce78952f2314e \ + --hash=sha256:6b984510ed94993708c0d697b4fef2d118929bbfffc3b90037be0f5ccadf55e7 \ + --hash=sha256:a005f298f64624f313a3ac618ab03f844c71d84ae4f4a4aec4b68d2a4ffe75eb \ + --hash=sha256:abc29357ee540849faf1383e1746d40d69ed5cb6d4c346df276b258f5aa8977a \ + --hash=sha256:c9ec490609752c1d81ff6290da33485aa7cb6d7365ac665b74464c1b7d97f7da \ + --hash=sha256:d5ba529d9ce668be9380563279f3ffe988f27bc5b299c5a28453df2e0b0fbaf2 \ + --hash=sha256:e2b1a7d093f2e76dc694c17c0c285e846d0b0deb0e8b21dc852ba1a3a4e2f1d6 # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt -lxml==4.9.4 +lxml==4.9.4 \ + --hash=sha256:00e91573183ad273e242db5585b52670eddf92bacad095ce25c1e682da14ed91 \ + --hash=sha256:01bf1df1db327e748dcb152d17389cf6d0a8c5d533ef9bab781e9d5037619229 \ + --hash=sha256:056a17eaaf3da87a05523472ae84246f87ac2f29a53306466c22e60282e54ff8 \ + --hash=sha256:0a08c89b23117049ba171bf51d2f9c5f3abf507d65d016d6e0fa2f37e18c0fc5 \ + --hash=sha256:1343df4e2e6e51182aad12162b23b0a4b3fd77f17527a78c53f0f23573663545 \ + --hash=sha256:1449f9451cd53e0fd0a7ec2ff5ede4686add13ac7a7bfa6988ff6d75cff3ebe2 \ + --hash=sha256:16b9ec51cc2feab009e800f2c6327338d6ee4e752c76e95a35c4465e80390ccd \ + --hash=sha256:1f10f250430a4caf84115b1e0f23f3615566ca2369d1962f82bef40dd99cd81a \ + --hash=sha256:231142459d32779b209aa4b4d460b175cadd604fed856f25c1571a9d78114771 \ + --hash=sha256:232fd30903d3123be4c435fb5159938c6225ee8607b635a4d3fca847003134ba \ + --hash=sha256:23d891e5bdc12e2e506e7d225d6aa929e0a0368c9916c1fddefab88166e98b20 \ + --hash=sha256:266f655d1baff9c47b52f529b5f6bec33f66042f65f7c56adde3fcf2ed62ae8b \ + --hash=sha256:273473d34462ae6e97c0f4e517bd1bf9588aa67a1d47d93f760a1282640e24ac \ + --hash=sha256:2bd9ac6e44f2db368ef8986f3989a4cad3de4cd55dbdda536e253000c801bcc7 \ + --hash=sha256:33714fcf5af4ff7e70a49731a7cc8fd9ce910b9ac194f66eaa18c3cc0a4c02be \ + --hash=sha256:359a8b09d712df27849e0bcb62c6a3404e780b274b0b7e4c39a88826d1926c28 \ + --hash=sha256:365005e8b0718ea6d64b374423e870648ab47c3a905356ab6e5a5ff03962b9a9 \ + --hash=sha256:389d2b2e543b27962990ab529ac6720c3dded588cc6d0f6557eec153305a3622 \ + --hash=sha256:3b505f2bbff50d261176e67be24e8909e54b5d9d08b12d4946344066d66b3e43 \ + --hash=sha256:3d74d4a3c4b8f7a1f676cedf8e84bcc57705a6d7925e6daef7a1e54ae543a197 \ + --hash=sha256:3f3f00a9061605725df1816f5713d10cd94636347ed651abdbc75828df302b20 \ + --hash=sha256:43498ea734ccdfb92e1886dfedaebeb81178a241d39a79d5351ba2b671bff2b2 \ + --hash=sha256:4855161013dfb2b762e02b3f4d4a21cc7c6aec13c69e3bffbf5022b3e708dd97 \ + --hash=sha256:4d973729ce04784906a19108054e1fd476bc85279a403ea1a72fdb051c76fa48 \ + --hash=sha256:4ece9cca4cd1c8ba889bfa67eae7f21d0d1a2e715b4d5045395113361e8c533d \ + --hash=sha256:506becdf2ecaebaf7f7995f776394fcc8bd8a78022772de66677c84fb02dd33d \ + --hash=sha256:520486f27f1d4ce9654154b4494cf9307b495527f3a2908ad4cb48e4f7ed7ef7 \ + --hash=sha256:5557461f83bb7cc718bc9ee1f7156d50e31747e5b38d79cf40f79ab1447afd2d \ + --hash=sha256:562778586949be7e0d7435fcb24aca4810913771f845d99145a6cee64d5b67ca \ + --hash=sha256:59bb5979f9941c61e907ee571732219fa4774d5a18f3fa5ff2df963f5dfaa6bc \ + --hash=sha256:606d445feeb0856c2b424405236a01c71af7c97e5fe42fbc778634faef2b47e4 \ + --hash=sha256:6197c3f3c0b960ad033b9b7d611db11285bb461fc6b802c1dd50d04ad715c225 \ + --hash=sha256:647459b23594f370c1c01768edaa0ba0959afc39caeeb793b43158bb9bb6a663 \ + --hash=sha256:647bfe88b1997d7ae8d45dabc7c868d8cb0c8412a6e730a7651050b8c7289cf2 \ + --hash=sha256:6bee9c2e501d835f91460b2c904bc359f8433e96799f5c2ff20feebd9bb1e590 \ + --hash=sha256:6dbdacf5752fbd78ccdb434698230c4f0f95df7dd956d5f205b5ed6911a1367c \ + --hash=sha256:701847a7aaefef121c5c0d855b2affa5f9bd45196ef00266724a80e439220e46 \ + --hash=sha256:786d6b57026e7e04d184313c1359ac3d68002c33e4b1042ca58c362f1d09ff58 \ + --hash=sha256:7b378847a09d6bd46047f5f3599cdc64fcb4cc5a5a2dd0a2af610361fbe77b16 \ + --hash=sha256:7d1d6c9e74c70ddf524e3c09d9dc0522aba9370708c2cb58680ea40174800013 \ + --hash=sha256:857d6565f9aa3464764c2cb6a2e3c2e75e1970e877c188f4aeae45954a314e0c \ + --hash=sha256:8671622256a0859f5089cbe0ce4693c2af407bc053dcc99aadff7f5310b4aa02 \ + --hash=sha256:88f7c383071981c74ec1998ba9b437659e4fd02a3c4a4d3efc16774eb108d0ec \ + --hash=sha256:8aecb5a7f6f7f8fe9cac0bcadd39efaca8bbf8d1bf242e9f175cbe4c925116c3 \ + --hash=sha256:91bbf398ac8bb7d65a5a52127407c05f75a18d7015a270fdd94bbcb04e65d573 \ + --hash=sha256:936e8880cc00f839aa4173f94466a8406a96ddce814651075f95837316369899 \ + --hash=sha256:953dd5481bd6252bd480d6ec431f61d7d87fdcbbb71b0d2bdcfc6ae00bb6fb10 \ + --hash=sha256:95ae6c5a196e2f239150aa4a479967351df7f44800c93e5a975ec726fef005e2 \ + --hash=sha256:9a2b5915c333e4364367140443b59f09feae42184459b913f0f41b9fed55794a \ + --hash=sha256:9ae6c3363261021144121427b1552b29e7b59de9d6a75bf51e03bc072efb3c37 \ + --hash=sha256:9b556596c49fa1232b0fff4b0e69b9d4083a502e60e404b44341e2f8fb7187f5 \ + --hash=sha256:9c131447768ed7bc05a02553d939e7f0e807e533441901dd504e217b76307745 \ + --hash=sha256:9d9d5726474cbbef279fd709008f91a49c4f758bec9c062dfbba88eab00e3ff9 \ + --hash=sha256:a1bdcbebd4e13446a14de4dd1825f1e778e099f17f79718b4aeaf2403624b0f7 \ + --hash=sha256:a602ed9bd2c7d85bd58592c28e101bd9ff9c718fbde06545a70945ffd5d11868 \ + --hash=sha256:a8edae5253efa75c2fc79a90068fe540b197d1c7ab5803b800fccfe240eed33c \ + --hash=sha256:a905affe76f1802edcac554e3ccf68188bea16546071d7583fb1b693f9cf756b \ + --hash=sha256:a9e7c6d89c77bb2770c9491d988f26a4b161d05c8ca58f63fb1f1b6b9a74be45 \ + --hash=sha256:aa9b5abd07f71b081a33115d9758ef6077924082055005808f68feccb27616bd \ + --hash=sha256:aaa5c173a26960fe67daa69aa93d6d6a1cd714a6eb13802d4e4bd1d24a530644 \ + --hash=sha256:ac7674d1638df129d9cb4503d20ffc3922bd463c865ef3cb412f2c926108e9a4 \ + --hash=sha256:b1541e50b78e15fa06a2670157a1962ef06591d4c998b998047fff5e3236880e \ + --hash=sha256:b1980dbcaad634fe78e710c8587383e6e3f61dbe146bcbfd13a9c8ab2d7b1192 \ + --hash=sha256:bafa65e3acae612a7799ada439bd202403414ebe23f52e5b17f6ffc2eb98c2be \ + --hash=sha256:bb5bd6212eb0edfd1e8f254585290ea1dadc3687dd8fd5e2fd9a87c31915cdab \ + --hash=sha256:bbdd69e20fe2943b51e2841fc1e6a3c1de460d630f65bde12452d8c97209464d \ + --hash=sha256:bc354b1393dce46026ab13075f77b30e40b61b1a53e852e99d3cc5dd1af4bc85 \ + --hash=sha256:bcee502c649fa6351b44bb014b98c09cb00982a475a1912a9881ca28ab4f9cd9 \ + --hash=sha256:bdd9abccd0927673cffe601d2c6cdad1c9321bf3437a2f507d6b037ef91ea307 \ + --hash=sha256:c42ae7e010d7d6bc51875d768110c10e8a59494855c3d4c348b068f5fb81fdcd \ + --hash=sha256:c71b5b860c5215fdbaa56f715bc218e45a98477f816b46cfde4a84d25b13274e \ + --hash=sha256:c7721a3ef41591341388bb2265395ce522aba52f969d33dacd822da8f018aff8 \ + --hash=sha256:ca8e44b5ba3edb682ea4e6185b49661fc22b230cf811b9c13963c9f982d1d964 \ + --hash=sha256:cb53669442895763e61df5c995f0e8361b61662f26c1b04ee82899c2789c8f69 \ + --hash=sha256:cc02c06e9e320869d7d1bd323df6dd4281e78ac2e7f8526835d3d48c69060683 \ + --hash=sha256:d3caa09e613ece43ac292fbed513a4bce170681a447d25ffcbc1b647d45a39c5 \ + --hash=sha256:d82411dbf4d3127b6cde7da0f9373e37ad3a43e89ef374965465928f01c2b979 \ + --hash=sha256:dbcb2dc07308453db428a95a4d03259bd8caea97d7f0776842299f2d00c72fc8 \ + --hash=sha256:dd4fda67f5faaef4f9ee5383435048ee3e11ad996901225ad7615bc92245bc8e \ + --hash=sha256:ddd92e18b783aeb86ad2132d84a4b795fc5ec612e3545c1b687e7747e66e2b53 \ + --hash=sha256:de362ac8bc962408ad8fae28f3967ce1a262b5d63ab8cefb42662566737f1dc7 \ + --hash=sha256:e214025e23db238805a600f1f37bf9f9a15413c7bf5f9d6ae194f84980c78722 \ + --hash=sha256:e8f9f93a23634cfafbad6e46ad7d09e0f4a25a2400e4a64b1b7b7c0fbaa06d9d \ + --hash=sha256:e96a1788f24d03e8d61679f9881a883ecdf9c445a38f9ae3f3f193ab6c591c66 \ + --hash=sha256:ec53a09aee61d45e7dbe7e91252ff0491b6b5fee3d85b2d45b173d8ab453efc1 \ + --hash=sha256:f10250bb190fb0742e3e1958dd5c100524c2cc5096c67c8da51233f7448dc137 \ + --hash=sha256:f1faee2a831fe249e1bae9cbc68d3cd8a30f7e37851deee4d7962b17c410dd56 \ + --hash=sha256:f610d980e3fccf4394ab3806de6065682982f3d27c12d4ce3ee46a8183d64a6a \ + --hash=sha256:f6c35b2f87c004270fa2e703b872fcc984d714d430b305145c39d53074e1ffe0 \ + --hash=sha256:f836f39678cb47c9541f04d8ed4545719dc31ad850bf1832d6b4171e30d65d23 \ + --hash=sha256:f99768232f036b4776ce419d3244a04fe83784bce871b16d2c2e984c7fcea847 \ + --hash=sha256:fd814847901df6e8de13ce69b84c31fc9b3fb591224d6762d0b256d510cbf382 \ + --hash=sha256:fdb325b7fba1e2c40b9b1db407f85642e32404131c08480dd652110fc908561b # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt -markdown==3.6 +markdown==3.6 \ + --hash=sha256:48f276f4d8cfb8ce6527c8f79e2ee29708508bf4d40aa410fbc3b4ee832c850f \ + --hash=sha256:ed4f41f6daecbeeb96e576ce414c41d2d876daa9a16cb35fa8ed8c2ddfad0224 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # wagtail-markdown -oauthlib==3.2.2 +oauthlib==3.2.2 \ + --hash=sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca \ + --hash=sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # requests-oauthlib -openpyxl==3.1.5 +openpyxl==3.1.5 \ + --hash=sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2 \ + --hash=sha256:cf0e3cf56142039133628b5acffe8ef0c12bc902d2aadd3e0fe5878dc08d1050 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # tablib -outcome==1.3.0.post0 +outcome==1.3.0.post0 \ + --hash=sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8 \ + --hash=sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b # via trio -packaging==24.1 +packaging==24.1 \ + --hash=sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002 \ + --hash=sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # bleach # drf-yasg + # kombu # pytest -pillow==9.5.0 +pillow==9.5.0 \ + --hash=sha256:07999f5834bdc404c442146942a2ecadd1cb6292f5229f4ed3b31e0a108746b1 \ + --hash=sha256:0852ddb76d85f127c135b6dd1f0bb88dbb9ee990d2cd9aa9e28526c93e794fba \ + --hash=sha256:1781a624c229cb35a2ac31cc4a77e28cafc8900733a864870c49bfeedacd106a \ + --hash=sha256:1e7723bd90ef94eda669a3c2c19d549874dd5badaeefabefd26053304abe5799 \ + --hash=sha256:229e2c79c00e85989a34b5981a2b67aa079fd08c903f0aaead522a1d68d79e51 \ + --hash=sha256:22baf0c3cf0c7f26e82d6e1adf118027afb325e703922c8dfc1d5d0156bb2eeb \ + --hash=sha256:252a03f1bdddce077eff2354c3861bf437c892fb1832f75ce813ee94347aa9b5 \ + --hash=sha256:2dfaaf10b6172697b9bceb9a3bd7b951819d1ca339a5ef294d1f1ac6d7f63270 \ + --hash=sha256:322724c0032af6692456cd6ed554bb85f8149214d97398bb80613b04e33769f6 \ + --hash=sha256:35f6e77122a0c0762268216315bf239cf52b88865bba522999dc38f1c52b9b47 \ + --hash=sha256:375f6e5ee9620a271acb6820b3d1e94ffa8e741c0601db4c0c4d3cb0a9c224bf \ + --hash=sha256:3ded42b9ad70e5f1754fb7c2e2d6465a9c842e41d178f262e08b8c85ed8a1d8e \ + --hash=sha256:432b975c009cf649420615388561c0ce7cc31ce9b2e374db659ee4f7d57a1f8b \ + --hash=sha256:482877592e927fd263028c105b36272398e3e1be3269efda09f6ba21fd83ec66 \ + --hash=sha256:489f8389261e5ed43ac8ff7b453162af39c3e8abd730af8363587ba64bb2e865 \ + --hash=sha256:54f7102ad31a3de5666827526e248c3530b3a33539dbda27c6843d19d72644ec \ + --hash=sha256:560737e70cb9c6255d6dcba3de6578a9e2ec4b573659943a5e7e4af13f298f5c \ + --hash=sha256:5671583eab84af046a397d6d0ba25343c00cd50bce03787948e0fff01d4fd9b1 \ + --hash=sha256:5ba1b81ee69573fe7124881762bb4cd2e4b6ed9dd28c9c60a632902fe8db8b38 \ + --hash=sha256:5d4ebf8e1db4441a55c509c4baa7a0587a0210f7cd25fcfe74dbbce7a4bd1906 \ + --hash=sha256:60037a8db8750e474af7ffc9faa9b5859e6c6d0a50e55c45576bf28be7419705 \ + --hash=sha256:608488bdcbdb4ba7837461442b90ea6f3079397ddc968c31265c1e056964f1ef \ + --hash=sha256:6608ff3bf781eee0cd14d0901a2b9cc3d3834516532e3bd673a0a204dc8615fc \ + --hash=sha256:662da1f3f89a302cc22faa9f14a262c2e3951f9dbc9617609a47521c69dd9f8f \ + --hash=sha256:7002d0797a3e4193c7cdee3198d7c14f92c0836d6b4a3f3046a64bd1ce8df2bf \ + --hash=sha256:763782b2e03e45e2c77d7779875f4432e25121ef002a41829d8868700d119392 \ + --hash=sha256:77165c4a5e7d5a284f10a6efaa39a0ae8ba839da344f20b111d62cc932fa4e5d \ + --hash=sha256:7c9af5a3b406a50e313467e3565fc99929717f780164fe6fbb7704edba0cebbe \ + --hash=sha256:7ec6f6ce99dab90b52da21cf0dc519e21095e332ff3b399a357c187b1a5eee32 \ + --hash=sha256:833b86a98e0ede388fa29363159c9b1a294b0905b5128baf01db683672f230f5 \ + --hash=sha256:84a6f19ce086c1bf894644b43cd129702f781ba5751ca8572f08aa40ef0ab7b7 \ + --hash=sha256:8507eda3cd0608a1f94f58c64817e83ec12fa93a9436938b191b80d9e4c0fc44 \ + --hash=sha256:85ec677246533e27770b0de5cf0f9d6e4ec0c212a1f89dfc941b64b21226009d \ + --hash=sha256:8aca1152d93dcc27dc55395604dcfc55bed5f25ef4c98716a928bacba90d33a3 \ + --hash=sha256:8d935f924bbab8f0a9a28404422da8af4904e36d5c33fc6f677e4c4485515625 \ + --hash=sha256:8f36397bf3f7d7c6a3abdea815ecf6fd14e7fcd4418ab24bae01008d8d8ca15e \ + --hash=sha256:91ec6fe47b5eb5a9968c79ad9ed78c342b1f97a091677ba0e012701add857829 \ + --hash=sha256:965e4a05ef364e7b973dd17fc765f42233415974d773e82144c9bbaaaea5d089 \ + --hash=sha256:96e88745a55b88a7c64fa49bceff363a1a27d9a64e04019c2281049444a571e3 \ + --hash=sha256:99eb6cafb6ba90e436684e08dad8be1637efb71c4f2180ee6b8f940739406e78 \ + --hash=sha256:9adf58f5d64e474bed00d69bcd86ec4bcaa4123bfa70a65ce72e424bfb88ed96 \ + --hash=sha256:9b1af95c3a967bf1da94f253e56b6286b50af23392a886720f563c547e48e964 \ + --hash=sha256:a0aa9417994d91301056f3d0038af1199eb7adc86e646a36b9e050b06f526597 \ + --hash=sha256:a0f9bb6c80e6efcde93ffc51256d5cfb2155ff8f78292f074f60f9e70b942d99 \ + --hash=sha256:a127ae76092974abfbfa38ca2d12cbeddcdeac0fb71f9627cc1135bedaf9d51a \ + --hash=sha256:aaf305d6d40bd9632198c766fb64f0c1a83ca5b667f16c1e79e1661ab5060140 \ + --hash=sha256:aca1c196f407ec7cf04dcbb15d19a43c507a81f7ffc45b690899d6a76ac9fda7 \ + --hash=sha256:ace6ca218308447b9077c14ea4ef381ba0b67ee78d64046b3f19cf4e1139ad16 \ + --hash=sha256:b416f03d37d27290cb93597335a2f85ed446731200705b22bb927405320de903 \ + --hash=sha256:bf548479d336726d7a0eceb6e767e179fbde37833ae42794602631a070d630f1 \ + --hash=sha256:c1170d6b195555644f0616fd6ed929dfcf6333b8675fcca044ae5ab110ded296 \ + --hash=sha256:c380b27d041209b849ed246b111b7c166ba36d7933ec6e41175fd15ab9eb1572 \ + --hash=sha256:c446d2245ba29820d405315083d55299a796695d747efceb5717a8b450324115 \ + --hash=sha256:c830a02caeb789633863b466b9de10c015bded434deb3ec87c768e53752ad22a \ + --hash=sha256:cb841572862f629b99725ebaec3287fc6d275be9b14443ea746c1dd325053cbd \ + --hash=sha256:cfa4561277f677ecf651e2b22dc43e8f5368b74a25a8f7d1d4a3a243e573f2d4 \ + --hash=sha256:cfcc2c53c06f2ccb8976fb5c71d448bdd0a07d26d8e07e321c103416444c7ad1 \ + --hash=sha256:d3c6b54e304c60c4181da1c9dadf83e4a54fd266a99c70ba646a9baa626819eb \ + --hash=sha256:d3d403753c9d5adc04d4694d35cf0391f0f3d57c8e0030aac09d7678fa8030aa \ + --hash=sha256:d9c206c29b46cfd343ea7cdfe1232443072bbb270d6a46f59c259460db76779a \ + --hash=sha256:e49eb4e95ff6fd7c0c402508894b1ef0e01b99a44320ba7d8ecbabefddcc5569 \ + --hash=sha256:f8286396b351785801a976b1e85ea88e937712ee2c3ac653710a4a57a8da5d9c \ + --hash=sha256:f8fc330c3370a81bbf3f88557097d1ea26cd8b019d6433aa59f71195f5ddebbf \ + --hash=sha256:fbd359831c1657d69bb81f0db962905ee05e5e9451913b18b831febfe0519082 \ + --hash=sha256:fe7e1c262d3392afcf5071df9afa574544f28eac825284596ac6db56e6d11062 \ + --hash=sha256:fed1e1cf6a42577953abbe8e6cf2fe2f566daebde7c34724ec8803c4c0cda579 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # cairosvg # wagtail -pluggy==1.5.0 +pluggy==1.5.0 \ + --hash=sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1 \ + --hash=sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669 # via pytest -polib==1.2.0 +polib==1.2.0 \ + --hash=sha256:1c77ee1b81feb31df9bca258cbc58db1bbb32d10214b173882452c73af06d62d \ + --hash=sha256:f3ef94aefed6e183e342a8a269ae1fc4742ba193186ad76f175938621dbfc26b # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # django-translation-manager # wagtail-localize -psycopg2==2.9.9 +prompt-toolkit==3.0.51 \ + --hash=sha256:52742911fde84e2d423e2f9a4cf1de7d7ac4e51958f648d9540e0fb8db077b07 \ + --hash=sha256:931a162e3b27fc90c86f1b48bb1fb2c528c2761475e57c9c06de13311c7b54ed + # via click-repl +psycopg2==2.9.9 \ + --hash=sha256:121081ea2e76729acfb0673ff33755e8703d45e926e416cb59bae3a86c6a4981 \ + --hash=sha256:38a8dcc6856f569068b47de286b472b7c473ac7977243593a288ebce0dc89516 \ + --hash=sha256:426f9f29bde126913a20a96ff8ce7d73fd8a216cfb323b1f04da402d452853c3 \ + --hash=sha256:5e0d98cade4f0e0304d7d6f25bbfbc5bd186e07b38eac65379309c4ca3193efa \ + --hash=sha256:7e2dacf8b009a1c1e843b5213a87f7c544b2b042476ed7755be813eaf4e8347a \ + --hash=sha256:a7653d00b732afb6fc597e29c50ad28087dcb4fbfb28e86092277a559ae4e693 \ + --hash=sha256:ade01303ccf7ae12c356a5e10911c9e1c51136003a9a1d92f7aa9d010fb98372 \ + --hash=sha256:bac58c024c9922c23550af2a581998624d6e02350f4ae9c5f0bc642c633a2d5e \ + --hash=sha256:c92811b2d4c9b6ea0285942b2e7cac98a59e166d59c588fe5cfe1eda58e72d59 \ + --hash=sha256:d1454bde93fb1e224166811694d600e746430c006fbb031ea06ecc2ea41bf156 \ + --hash=sha256:d735786acc7dd25815e89cc4ad529a43af779db2e25aa7c626de864127e5a024 \ + --hash=sha256:de80739447af31525feddeb8effd640782cf5998e1a4e9192ebdf829717e3913 \ + --hash=sha256:ff432630e510709564c01dafdbe996cb552e0b9f3f065eb89bdce5bd31fabf4c # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt -py-vapid==1.9.1 +py-vapid==1.9.1 \ + --hash=sha256:fe2b5461bf45c7baff1039df6981f03b87faa87cde0482addfa35b3fe636ac1b # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # pywebpush -pycparser==2.22 +pycparser==2.22 \ + --hash=sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6 \ + --hash=sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # cffi -pyjwt[crypto]==2.8.0 +pyjwt[crypto]==2.8.0 \ + --hash=sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de \ + --hash=sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # django-allauth # djangorestframework-simplejwt -pysocks==1.7.1 +pysocks==1.7.1 \ + --hash=sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299 \ + --hash=sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5 \ + --hash=sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0 # via urllib3 -pytest==8.2.2 +pytest==8.2.2 \ + --hash=sha256:c434598117762e2bd304e526244f67bf66bbd7b5d6cf22138be51ff661980343 \ + --hash=sha256:de4bb8104e201939ccdc688b27a89a7be2079b22e2bd2b07f806b6ba71117977 # via # -r requirements.dev.in # pytest-django -pytest-django==4.8.0 +pytest-django==4.8.0 \ + --hash=sha256:5d054fe011c56f3b10f978f41a8efb2e5adfc7e680ef36fb571ada1f24779d90 \ + --hash=sha256:ca1ddd1e0e4c227cf9e3e40a6afc6d106b3e70868fd2ac5798a22501271cd0c7 # via -r requirements.dev.in -python-dateutil==2.9.0.post0 - # via faker -python3-openid==3.2.0 +python-dateutil==2.9.0.post0 \ + --hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \ + --hash=sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427 + # via + # celery + # faker +python3-openid==3.2.0 \ + --hash=sha256:33fbf6928f401e0b790151ed2b5290b02545e8775f982485205a066f874aaeaf \ + --hash=sha256:6626f771e0417486701e0b4daff762e7212e820ca5b29fcc0d05f6f8736dfa6b # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # django-allauth -pytz==2024.1 +pytz==2024.1 \ + --hash=sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812 \ + --hash=sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # django @@ -314,25 +921,82 @@ pytz==2024.1 # djangorestframework # drf-yasg # l18n -pywebpush==1.9.4 +pywebpush==1.9.4 \ + --hash=sha256:e3ded57c9715159f64a5624a656791ee9228b9e076ea0208baa73b53be8c130f # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # django-webpush -pyyaml==6.0.1 +pyyaml==6.0.1 \ + --hash=sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5 \ + --hash=sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc \ + --hash=sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df \ + --hash=sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741 \ + --hash=sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206 \ + --hash=sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27 \ + --hash=sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595 \ + --hash=sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62 \ + --hash=sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98 \ + --hash=sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696 \ + --hash=sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290 \ + --hash=sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9 \ + --hash=sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d \ + --hash=sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6 \ + --hash=sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867 \ + --hash=sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47 \ + --hash=sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486 \ + --hash=sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6 \ + --hash=sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3 \ + --hash=sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 \ + --hash=sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938 \ + --hash=sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0 \ + --hash=sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c \ + --hash=sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735 \ + --hash=sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d \ + --hash=sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28 \ + --hash=sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4 \ + --hash=sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba \ + --hash=sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8 \ + --hash=sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef \ + --hash=sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5 \ + --hash=sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd \ + --hash=sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3 \ + --hash=sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0 \ + --hash=sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515 \ + --hash=sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c \ + --hash=sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c \ + --hash=sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924 \ + --hash=sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 \ + --hash=sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43 \ + --hash=sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859 \ + --hash=sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 \ + --hash=sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54 \ + --hash=sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a \ + --hash=sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b \ + --hash=sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab \ + --hash=sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa \ + --hash=sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c \ + --hash=sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585 \ + --hash=sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d \ + --hash=sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # drf-yasg -rcssmin==1.0.6 +rcssmin==1.0.6 \ + --hash=sha256:ca87b695d3d7864157773a61263e5abb96006e9ff0e021eff90cbe0e1ba18270 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # django-compressor -redis==3.5.3 +redis==3.5.3 \ + --hash=sha256:0e7e0cfca8660dea8b7d5cd8c4f6c5e29e11f31158c0b0ae91a397f00e5a05a2 \ + --hash=sha256:432b788c4530cfe16d8d943a09d40ca6c16149727e4afe8c2c9d5580c59d9f24 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # django-redis # django-rq # rq -requests==2.32.3 +requests==2.32.3 \ + --hash=sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760 \ + --hash=sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # django-allauth @@ -341,21 +1005,42 @@ requests==2.32.3 # requests-oauthlib # wagtail # wagtail-generic-chooser -requests-oauthlib==2.0.0 +requests-oauthlib==2.0.0 \ + --hash=sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36 \ + --hash=sha256:b3dffaebd884d8cd778494369603a9e7b58d29111bf6b41bdc2dcd87203af4e9 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # django-allauth -rjsmin==1.1.0 +rjsmin==1.1.0 \ + --hash=sha256:0ab825839125eaca57cc59581d72e596e58a7a56fbc0839996b7528f0343a0a8 \ + --hash=sha256:211c2fe8298951663bbc02acdffbf714f6793df54bfc50e1c6c9e71b3f2559a3 \ + --hash=sha256:466fe70cc5647c7c51b3260c7e2e323a98b2b173564247f9c89e977720a0645f \ + --hash=sha256:585e75a84d9199b68056fd4a083d9a61e2a92dfd10ff6d4ce5bdb04bc3bdbfaf \ + --hash=sha256:6044ca86e917cd5bb2f95e6679a4192cef812122f28ee08c677513de019629b3 \ + --hash=sha256:714329db774a90947e0e2086cdddb80d5e8c4ac1c70c9f92436378dedb8ae345 \ + --hash=sha256:799890bd07a048892d8d3deb9042dbc20b7f5d0eb7da91e9483c561033b23ce2 \ + --hash=sha256:975b69754d6a76be47c0bead12367a1ca9220d08e5393f80bab0230d4625d1f4 \ + --hash=sha256:b15dc75c71f65d9493a8c7fa233fdcec823e3f1b88ad84a843ffef49b338ac32 \ + --hash=sha256:dd0f4819df4243ffe4c964995794c79ca43943b5b756de84be92b445a652fb86 \ + --hash=sha256:e3908b21ebb584ce74a6ac233bdb5f29485752c9d3be5e50c5484ed74169232c \ + --hash=sha256:e487a7783ac4339e79ec610b98228eb9ac72178973e3dee16eba0e3feef25924 \ + --hash=sha256:ecd29f1b3e66a4c0753105baec262b331bcbceefc22fbe6f7e8bcd2067bcb4d7 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # django-compressor -rq==1.16.2 +rq==1.16.2 \ + --hash=sha256:52e619f6cb469b00e04da74305045d244b75fecb2ecaa4f26422add57d3c5f09 \ + --hash=sha256:5c5b9ad5fbaf792b8fada25cc7627f4d206a9a4455aced371d4f501cc3f13b34 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # django-rq -selenium==4.9.1 +selenium==4.9.1 \ + --hash=sha256:3444f4376321530c36ce8355b6b357d8cf4a7d588ce5cf772183465930bbed0e \ + --hash=sha256:82aedaa85d55bc861f4c89ff9609e82f6c958e2e1e3da3ffcc36703f21d3ee16 # via -r requirements.dev.in -six==1.16.0 +six==1.16.0 \ + --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ + --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # bleach @@ -365,63 +1050,138 @@ six==1.16.0 # l18n # libsass # python-dateutil -sniffio==1.3.1 +sniffio==1.3.1 \ + --hash=sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2 \ + --hash=sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc # via trio -sortedcontainers==2.4.0 +sortedcontainers==2.4.0 \ + --hash=sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88 \ + --hash=sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0 # via trio -soupsieve==2.5 +soupsieve==2.5 \ + --hash=sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690 \ + --hash=sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # beautifulsoup4 -sqlparse==0.5.0 +sqlparse==0.5.0 \ + --hash=sha256:714d0a4932c059d16189f58ef5411ec2287a4360f17cdd0edd2d09d4c5087c93 \ + --hash=sha256:c204494cd97479d0e39f28c93d46c0b2d5959c7b9ab904762ea6c7af211c8663 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # django # django-debug-toolbar -swapper==1.4.0 +swapper==1.4.0 \ + --hash=sha256:57b8378aad234242542fe32dc6e8cff0ed24b63493d20b3c88ee01f894b9345e \ + --hash=sha256:9e083af114ee0593241a7b877e3e0e7d3a580454f5d59016c667a5563306f8fe # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # django-notifications-hq -tablib[xls,xlsx]==3.6.1 +tablib[xls,xlsx]==3.6.1 \ + --hash=sha256:040685fde11e9237675f43e985edb94b63250a5e9236f89d561ce6fb1465b839 \ + --hash=sha256:c771d38ed1d74350a69873db43e0afb7f1cca0ed2915a7243094463eb6789207 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # wagtail -telepath==0.3.1 +telepath==0.3.1 \ + --hash=sha256:925c0609e0a8a6488ec4a55b19d485882cf72223b2b19fe2359a50fddd813c9c \ + --hash=sha256:c280aa8e77ad71ce80e96500a4e4d4a32f35b7e0b52e896bb5fde9a5bcf0699a # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # wagtail -tinycss2==1.3.0 +tinycss2==1.3.0 \ + --hash=sha256:152f9acabd296a8375fbca5b84c961ff95971fcfc32e79550c8df8e29118c54d \ + --hash=sha256:54a8dbdffb334d536851be0226030e9505965bb2f30f21a4a82c55fb2a80fae7 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # cairosvg # cssselect2 -tomli==2.2.1 +tomli==2.2.1 \ + --hash=sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6 \ + --hash=sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd \ + --hash=sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c \ + --hash=sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b \ + --hash=sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8 \ + --hash=sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6 \ + --hash=sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77 \ + --hash=sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff \ + --hash=sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea \ + --hash=sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192 \ + --hash=sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249 \ + --hash=sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee \ + --hash=sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4 \ + --hash=sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98 \ + --hash=sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8 \ + --hash=sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4 \ + --hash=sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281 \ + --hash=sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744 \ + --hash=sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69 \ + --hash=sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13 \ + --hash=sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140 \ + --hash=sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e \ + --hash=sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e \ + --hash=sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc \ + --hash=sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff \ + --hash=sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec \ + --hash=sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2 \ + --hash=sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222 \ + --hash=sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106 \ + --hash=sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272 \ + --hash=sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a \ + --hash=sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7 # via pytest -tqdm==4.66.4 +tqdm==4.66.4 \ + --hash=sha256:b75ca56b413b030bc3f00af51fd2c1a1a5eac6a0c1cca83cbb37a5c52abce644 \ + --hash=sha256:e4d936c9de8727928f3be6079590e97d9abfe8d39a590be678eb5919ffc186bb # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt -trio==0.26.0 +trio==0.26.0 \ + --hash=sha256:67c5ec3265dd4abc7b1d1ab9ca4fe4c25b896f9c93dac73713778adab487f9c4 \ + --hash=sha256:bb9c1b259591af941fccfbabbdc65bc7ed764bd2db76428454c894cd5e3d2032 # via # selenium # trio-websocket -trio-websocket==0.11.1 +trio-websocket==0.11.1 \ + --hash=sha256:18c11793647703c158b1f6e62de638acada927344d534e3c7628eedcb746839f \ + --hash=sha256:520d046b0d030cf970b8b2b2e00c4c2245b3807853ecd44214acd33d74581638 # via selenium -typing-extensions==4.12.2 +typing-extensions==4.12.2 \ + --hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \ + --hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # asgiref # exceptiongroup # wagtail-localize -uritemplate==4.1.1 +tzdata==2025.2 \ + --hash=sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8 \ + --hash=sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9 + # via + # backports-zoneinfo + # celery +uritemplate==4.1.1 \ + --hash=sha256:4346edfc5c3b79f694bccd6d6099a322bbeb628dbf2cd86eea55a456ce5124f0 \ + --hash=sha256:830c08b8d99bdd312ea4ead05994a38e8936266f84b9a7878232db50b044e02e # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # drf-yasg -urllib3[socks]==1.26.19 +urllib3[socks]==1.26.19 \ + --hash=sha256:37a0344459b199fce0e80b0d3569837ec6b6937435c5244e7fd73fa6006830f3 \ + --hash=sha256:3e3d753a8618b86d7de333b4223005f68720bcd6a7d2bcb9fbd2229ec7c1e429 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # elasticsearch # requests # selenium -wagtail==3.0.3 +vine==5.1.0 \ + --hash=sha256:40fdf3c48b2cfe1c38a49e9ae2da6fda88e4794c810050a728bd7413811fb1dc \ + --hash=sha256:8b62e981d35c41049211cf62a0a1242d8c1ee9bd15bb196ce38aefd6799e61e0 + # via + # amqp + # celery + # kombu +wagtail==3.0.3 \ + --hash=sha256:111ed9a0a6ff26d5d881d52deb4bf52b627d79a53c43829611752dbb68a9192f \ + --hash=sha256:23b3e541401355ea183372582050ea52b049c956dd5b506197f957bb68423ab3 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # wagtail-cache @@ -429,54 +1189,90 @@ wagtail==3.0.3 # wagtail-localize # wagtail-markdown # wagtailmedia -wagtail-cache==2.1.1 +wagtail-cache==2.1.1 \ + --hash=sha256:1fe3ca20a3cdf23f31fc9df662a52f743084cd7f60bd870950094d63a87f695a \ + --hash=sha256:2ac16921d022a58240a009a19220554e41963c5172e7dfe4ef741ddd887e991f # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt -wagtail-factories==4.0.0 +wagtail-factories==4.0.0 \ + --hash=sha256:3e39ec1cc13b61c6e467f1bf223ce2d134e823fa9fe4dc7e32d0222cc8d350ec \ + --hash=sha256:f59f9af283da79b3ddab7b2ca95d6a14b5bbbb929a697563e4f7143948693f53 # via -r requirements.dev.in -wagtail-generic-chooser==0.5.1 +wagtail-generic-chooser==0.5.1 \ + --hash=sha256:135f8cc413d83b82bb8956f625f4b9572aa7139ab3835e2ba2d7e19f2171b354 \ + --hash=sha256:280ae7293641d1b121450e17a6d424305e31c832f1af5bd991bc3e49703bf79e # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # wagtailsvg -wagtail-localize==1.4 +wagtail-localize==1.4 \ + --hash=sha256:40f974809509de54dcc18ee6aa98908bffd9dfaba53150e214f4046b2286920e \ + --hash=sha256:fd1195de3c23e3a061576f1b947fe7498676ff5678fe008d4cd388125a20a54a # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt -wagtail-markdown==0.10.0 +wagtail-markdown==0.10.0 \ + --hash=sha256:b16be4b6e3518cc6dd15ab335cbc6d6a9122b5d7e3a61fa11c83597e2660044e \ + --hash=sha256:e4a97eee0211eebaab9c850669e647bc1c8ceb70df38b4db5a2c3d8b02ebaf69 # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt -wagtail-transfer @ https://github.com/IDEMSInternational/wagtail-transfer/archive/52b57b364ebc9acddd412ee708f829b45763c9ab.zip +wagtail-transfer @ https://github.com/IDEMSInternational/wagtail-transfer/archive/52b57b364ebc9acddd412ee708f829b45763c9ab.zip \ + --hash=sha256:049c23e1406564d3b7e8c385e72051f34e707add4f8109d874da670711709548 # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt -wagtailmedia==0.12.0 +wagtailmedia==0.12.0 \ + --hash=sha256:0807515c5d89782666b613de2e4aedab19e9dd358097fad2cb79633c0b5416d3 \ + --hash=sha256:1d39622c3d7d0191e58ffedf45d05fbef851e3905955513012a72ae4d46a12b0 # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt -wagtailmenus==3.1.3 +wagtailmenus==3.1.3 \ + --hash=sha256:0f5669f160d788b1ab8c2b412cb95411e9c07f83e4b52dddc92991752c6fa397 # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt -wagtailsvg==0.0.37 +wagtailsvg==0.0.37 \ + --hash=sha256:4b30433809614fbac09f9088b4aed42a1bfe56f9fb581b858606187cb177ca6b \ + --hash=sha256:dc4d698748bde32034b1eac2275cf159597ca8e399d3830e96391f761aa0cacf # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt -webencodings==0.5.1 +wcwidth==0.2.13 \ + --hash=sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859 \ + --hash=sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5 + # via prompt-toolkit +webencodings==0.5.1 \ + --hash=sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78 \ + --hash=sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # bleach # cssselect2 # html5lib # tinycss2 -whitenoise==5.2.0 +whitenoise==5.2.0 \ + --hash=sha256:05ce0be39ad85740a78750c86a93485c40f08ad8c62a6006de0233765996e5c7 \ + --hash=sha256:05d00198c777028d72d8b0bbd234db605ef6d60e9410125124002518a48e515d # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt -willow==1.4.1 +willow==1.4.1 \ + --hash=sha256:0df8ff528531e00b48d40bf72ed81beac1dc82f2d42e5bbed4aff0218bef8c0d \ + --hash=sha256:fc4042696d090e75aef922fa1ed26d483c764f005b36cf523cf7c34e69d5dd7a # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # wagtail -wsproto==1.2.0 +wsproto==1.2.0 \ + --hash=sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065 \ + --hash=sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736 # via trio-websocket -xlrd==2.0.1 +xlrd==2.0.1 \ + --hash=sha256:6a33ee89877bd9abc1158129f6e94be74e2679636b8a205b43b85206c3f0bbdd \ + --hash=sha256:f72f148f54442c6b056bf931dbc34f986fd0c3b0b6b5a58d013c9aef274d0c88 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # tablib -xlsxwriter==3.2.0 +xlsxwriter==3.2.0 \ + --hash=sha256:9977d0c661a72866a61f9f7a809e25ebbb0fb7036baa3b9fe74afcfca6b3cb8c \ + --hash=sha256:ecfd5405b3e0e228219bcaf24c2ca0915e012ca9464a14048021d21a995d490e # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # wagtail -xlwt==1.3.0 +xlwt==1.3.0 \ + --hash=sha256:a082260524678ba48a297d922cc385f58278b8aa68741596a87de01a9c628b2e \ + --hash=sha256:c59912717a9b28f1a3c2a98fd60741014b06b043936dcecbc113eaaada156c88 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # tablib -zipp==3.20.2 +zipp==3.20.2 \ + --hash=sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350 \ + --hash=sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29 # via # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # importlib-metadata diff --git a/requirements.txt b/requirements.txt index f90572f0d..062bb5019 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,51 +2,250 @@ # This file is autogenerated by pip-compile with Python 3.8 # by the following command: # -# pip-compile requirements.in +# pip-compile --generate-hashes requirements.in # -anyascii==0.3.2 +anyascii==0.3.2 \ + --hash=sha256:3b3beef6fc43d9036d3b0529050b0c48bfad8bc960e9e562d7223cfb94fe45d4 \ + --hash=sha256:9d5d32ef844fe225b8bc7cba7f950534fae4da27a9bf3a6bea2cb0ea46ce4730 # via wagtail -asgiref==3.8.1 +asgiref==3.8.1 \ + --hash=sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47 \ + --hash=sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590 # via django -beautifulsoup4==4.9.3 +beautifulsoup4==4.9.3 \ + --hash=sha256:4c98143716ef1cb40bf7f39a8e3eec8f8b009509e74904ba3a7b315431577e35 \ + --hash=sha256:84729e322ad1d5b4d25f805bfa05b902dd96450f43842c4e99067d5e1369eb25 \ + --hash=sha256:fff47e031e34ec82bf17e00da8f592fe7de69aeea38be00523c04623c04fb666 # via # -r requirements.in # wagtail -bleach==4.1.0 +bleach==4.1.0 \ + --hash=sha256:0900d8b37eba61a802ee40ac0061f8c2b5dee29c1927dd1d233e075ebf5a71da \ + --hash=sha256:4d2651ab93271d1129ac9cbc679f524565cc8a1b791909c4a51eac4446a15994 # via wagtail-markdown -cairocffi==1.7.1 +cairocffi==1.7.1 \ + --hash=sha256:2e48ee864884ec4a3a34bfa8c9ab9999f688286eb714a15a43ec9d068c36557b \ + --hash=sha256:9803a0e11f6c962f3b0ae2ec8ba6ae45e957a146a004697a1ac1bbf16b073b3f # via cairosvg -cairosvg==2.7.1 +cairosvg==2.7.1 \ + --hash=sha256:432531d72347291b9a9ebfb6777026b607563fd8719c46ee742db0aef7271ba0 \ + --hash=sha256:8a5222d4e6c3f86f1f7046b63246877a63b49923a1cd202184c3a634ef546b3b # via -r requirements.in -certifi==2024.7.4 +certifi==2024.7.4 \ + --hash=sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b \ + --hash=sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90 # via # elasticsearch # requests -cffi==1.16.0 +cffi==1.16.0 \ + --hash=sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc \ + --hash=sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a \ + --hash=sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417 \ + --hash=sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab \ + --hash=sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520 \ + --hash=sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36 \ + --hash=sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743 \ + --hash=sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8 \ + --hash=sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed \ + --hash=sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684 \ + --hash=sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56 \ + --hash=sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324 \ + --hash=sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d \ + --hash=sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235 \ + --hash=sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e \ + --hash=sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088 \ + --hash=sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000 \ + --hash=sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7 \ + --hash=sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e \ + --hash=sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673 \ + --hash=sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c \ + --hash=sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe \ + --hash=sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2 \ + --hash=sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098 \ + --hash=sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8 \ + --hash=sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a \ + --hash=sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0 \ + --hash=sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b \ + --hash=sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896 \ + --hash=sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e \ + --hash=sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9 \ + --hash=sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2 \ + --hash=sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b \ + --hash=sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6 \ + --hash=sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404 \ + --hash=sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f \ + --hash=sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0 \ + --hash=sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4 \ + --hash=sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc \ + --hash=sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936 \ + --hash=sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba \ + --hash=sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872 \ + --hash=sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb \ + --hash=sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614 \ + --hash=sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1 \ + --hash=sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d \ + --hash=sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969 \ + --hash=sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b \ + --hash=sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4 \ + --hash=sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627 \ + --hash=sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956 \ + --hash=sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357 # via # cairocffi # cryptography -charset-normalizer==3.3.2 +charset-normalizer==3.3.2 \ + --hash=sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027 \ + --hash=sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087 \ + --hash=sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786 \ + --hash=sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8 \ + --hash=sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09 \ + --hash=sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185 \ + --hash=sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574 \ + --hash=sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e \ + --hash=sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519 \ + --hash=sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898 \ + --hash=sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269 \ + --hash=sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3 \ + --hash=sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f \ + --hash=sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6 \ + --hash=sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8 \ + --hash=sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a \ + --hash=sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73 \ + --hash=sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc \ + --hash=sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714 \ + --hash=sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2 \ + --hash=sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc \ + --hash=sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce \ + --hash=sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d \ + --hash=sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e \ + --hash=sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6 \ + --hash=sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269 \ + --hash=sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 \ + --hash=sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d \ + --hash=sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a \ + --hash=sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4 \ + --hash=sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 \ + --hash=sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d \ + --hash=sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0 \ + --hash=sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed \ + --hash=sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068 \ + --hash=sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac \ + --hash=sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25 \ + --hash=sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 \ + --hash=sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab \ + --hash=sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26 \ + --hash=sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2 \ + --hash=sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db \ + --hash=sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f \ + --hash=sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5 \ + --hash=sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99 \ + --hash=sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c \ + --hash=sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d \ + --hash=sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811 \ + --hash=sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa \ + --hash=sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a \ + --hash=sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03 \ + --hash=sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b \ + --hash=sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04 \ + --hash=sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c \ + --hash=sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001 \ + --hash=sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458 \ + --hash=sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389 \ + --hash=sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99 \ + --hash=sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985 \ + --hash=sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537 \ + --hash=sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238 \ + --hash=sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f \ + --hash=sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d \ + --hash=sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796 \ + --hash=sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a \ + --hash=sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143 \ + --hash=sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8 \ + --hash=sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c \ + --hash=sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5 \ + --hash=sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5 \ + --hash=sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711 \ + --hash=sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4 \ + --hash=sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6 \ + --hash=sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c \ + --hash=sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7 \ + --hash=sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4 \ + --hash=sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b \ + --hash=sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae \ + --hash=sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12 \ + --hash=sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c \ + --hash=sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae \ + --hash=sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8 \ + --hash=sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887 \ + --hash=sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b \ + --hash=sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4 \ + --hash=sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f \ + --hash=sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5 \ + --hash=sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33 \ + --hash=sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519 \ + --hash=sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561 # via requests -click==8.1.7 +click==8.1.7 \ + --hash=sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28 \ + --hash=sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de # via rq -colorama==0.4.6 +colorama==0.4.6 \ + --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ + --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 # via # click # tqdm -cryptography==42.0.8 +cryptography==42.0.8 \ + --hash=sha256:013629ae70b40af70c9a7a5db40abe5d9054e6f4380e50ce769947b73bf3caad \ + --hash=sha256:2346b911eb349ab547076f47f2e035fc8ff2c02380a7cbbf8d87114fa0f1c583 \ + --hash=sha256:2f66d9cd9147ee495a8374a45ca445819f8929a3efcd2e3df6428e46c3cbb10b \ + --hash=sha256:2f88d197e66c65be5e42cd72e5c18afbfae3f741742070e3019ac8f4ac57262c \ + --hash=sha256:31f721658a29331f895a5a54e7e82075554ccfb8b163a18719d342f5ffe5ecb1 \ + --hash=sha256:343728aac38decfdeecf55ecab3264b015be68fc2816ca800db649607aeee648 \ + --hash=sha256:5226d5d21ab681f432a9c1cf8b658c0cb02533eece706b155e5fbd8a0cdd3949 \ + --hash=sha256:57080dee41209e556a9a4ce60d229244f7a66ef52750f813bfbe18959770cfba \ + --hash=sha256:5a94eccb2a81a309806027e1670a358b99b8fe8bfe9f8d329f27d72c094dde8c \ + --hash=sha256:6b7c4f03ce01afd3b76cf69a5455caa9cfa3de8c8f493e0d3ab7d20611c8dae9 \ + --hash=sha256:7016f837e15b0a1c119d27ecd89b3515f01f90a8615ed5e9427e30d9cdbfed3d \ + --hash=sha256:81884c4d096c272f00aeb1f11cf62ccd39763581645b0812e99a91505fa48e0c \ + --hash=sha256:81d8a521705787afe7a18d5bfb47ea9d9cc068206270aad0b96a725022e18d2e \ + --hash=sha256:8d09d05439ce7baa8e9e95b07ec5b6c886f548deb7e0f69ef25f64b3bce842f2 \ + --hash=sha256:961e61cefdcb06e0c6d7e3a1b22ebe8b996eb2bf50614e89384be54c48c6b63d \ + --hash=sha256:9c0c1716c8447ee7dbf08d6db2e5c41c688544c61074b54fc4564196f55c25a7 \ + --hash=sha256:a0608251135d0e03111152e41f0cc2392d1e74e35703960d4190b2e0f4ca9c70 \ + --hash=sha256:a0c5b2b0585b6af82d7e385f55a8bc568abff8923af147ee3c07bd8b42cda8b2 \ + --hash=sha256:ad803773e9df0b92e0a817d22fd8a3675493f690b96130a5e24f1b8fabbea9c7 \ + --hash=sha256:b297f90c5723d04bcc8265fc2a0f86d4ea2e0f7ab4b6994459548d3a6b992a14 \ + --hash=sha256:ba4f0a211697362e89ad822e667d8d340b4d8d55fae72cdd619389fb5912eefe \ + --hash=sha256:c4783183f7cb757b73b2ae9aed6599b96338eb957233c58ca8f49a49cc32fd5e \ + --hash=sha256:c9bb2ae11bfbab395bdd072985abde58ea9860ed84e59dbc0463a5d0159f5b71 \ + --hash=sha256:cafb92b2bc622cd1aa6a1dce4b93307792633f4c5fe1f46c6b97cf67073ec961 \ + --hash=sha256:d45b940883a03e19e944456a558b67a41160e367a719833c53de6911cabba2b7 \ + --hash=sha256:dc0fdf6787f37b1c6b08e6dfc892d9d068b5bdb671198c72072828b80bd5fe4c \ + --hash=sha256:dea567d1b0e8bc5764b9443858b673b734100c2871dc93163f58c46a97a83d28 \ + --hash=sha256:dec9b018df185f08483f294cae6ccac29e7a6e0678996587363dc352dc65c842 \ + --hash=sha256:e3ec3672626e1b9e55afd0df6d774ff0e953452886e06e0f1eb7eb0c832e8902 \ + --hash=sha256:e599b53fd95357d92304510fb7bda8523ed1f79ca98dce2f43c115950aa78801 \ + --hash=sha256:fa76fbb7596cc5839320000cdd5d0955313696d9511debab7ee7278fc8b5c84a \ + --hash=sha256:fff12c88a672ab9c9c1cf7b0c80e3ad9e2ebd9d828d955c126be4fd3e5578c9e # via # http-ece # py-vapid # pyjwt # pywebpush -cssselect2==0.7.0 +cssselect2==0.7.0 \ + --hash=sha256:1ccd984dab89fc68955043aca4e1b03e0cf29cad9880f6e28e3ba7a74b14aa5a \ + --hash=sha256:fd23a65bfd444595913f02fc71f6b286c29261e354c41d722ca7a261a49b5969 # via cairosvg -defusedxml==0.7.1 +defusedxml==0.7.1 \ + --hash=sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69 \ + --hash=sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61 # via # cairosvg # python3-openid -django==3.2.25 +django==3.2.25 \ + --hash=sha256:7ca38a78654aee72378594d63e51636c04b8e28574f5505dff630895b5472777 \ + --hash=sha256:a52ea7fcf280b16f7b739cec38fa6d3f8953a5456986944c3ca97e79882b4e38 # via # -r requirements.in # django-allauth @@ -72,49 +271,90 @@ django==3.2.25 # wagtail # wagtail-localize # wagtailmedia -django-allauth==0.54.0 +django-allauth==0.54.0 \ + --hash=sha256:120e265f802b65738899c6cb627b827fde46a4d03067034c633f516c2adf3e3e # via -r requirements.in -django-appconf==1.0.6 +django-appconf==1.0.6 \ + --hash=sha256:c3ae442fba1ff7ec830412c5184b17169a7a1e71cf0864a4c3f93cf4c98a1993 \ + --hash=sha256:cfe87ea827c4ee04b9a70fab90b86d704cb02f2981f89da8423cb0fabf88efbf # via django-compressor -django-cogwheels==0.3 +django-cogwheels==0.3 \ + --hash=sha256:197bd05e7114403d7301214b3f8a371c4fb6039cf21c811f099438b167b5ed21 \ + --hash=sha256:848a4d9f2c96c582a4a4f2e7c276dfd95ab3905748cae13bb7c4b365a6717e94 # via wagtailmenus -django-comments-xtd==2.9.13 +django-comments-xtd==2.9.13 \ + --hash=sha256:0d91e3cc76eae6f30e83b12fb09708e5407664d9daa7b9c1101d7377897f7b42 \ + --hash=sha256:b289b6754d6618fb29e4279c6a1c6a270bc9495e161c42193d8b6216a4884802 # via -r requirements.in -django-compressor==2.4.1 +django-compressor==2.4.1 \ + --hash=sha256:3358077605c146fdcca5f9eaffb50aa5dbe15f238f8854679115ebf31c0415e0 \ + --hash=sha256:f8313f59d5e65712fc28787d084fe834997c9dfa92d064a1a3ec3d3366594d04 # via -r requirements.in -django-contrib-comments==2.2.0 +django-contrib-comments==2.2.0 \ + --hash=sha256:2ca79060bbc8fc5b636981ef6e50f35ab83649af75fc1be47bf770636be3271c \ + --hash=sha256:48de00f15677e016a216aeff205d6e00e4391c9a5702136c64119c472b7356da # via django-comments-xtd -django-extensions==3.1.5 +django-extensions==3.1.5 \ + --hash=sha256:28e1e1bf49f0e00307ba574d645b0af3564c981a6dfc87209d48cb98f77d0b1a \ + --hash=sha256:9238b9e016bb0009d621e05cf56ea8ce5cce9b32e91ad2026996a7377ca28069 # via -r requirements.in -django-filter==2.4.0 +django-filter==2.4.0 \ + --hash=sha256:84e9d5cbb93f237e451db814ed422a3a625751cbc9968b484ecc74964a8696b06 \ + --hash=sha256:e00d32cebdb3d54273c48f4f878f898dced8d5dfaad009438fe61ebdf535ace1 # via # -r requirements.in # wagtail -django-health-check==3.16.5 +django-health-check==3.16.5 \ + --hash=sha256:1edfd49293ccebbce29f9da609c407f307aee240ab799ab4201031341ae78c0f \ + --hash=sha256:8d66781a0ea82b1a8b44878187b38a27370e94f18287312e39be0593e72d8983 # via -r requirements.in -django-model-utils==5.0.0 +django-model-utils==5.0.0 \ + --hash=sha256:041cdd6230d2fbf6cd943e1969318bce762272077f4ecd333ab2263924b4e5eb \ + --hash=sha256:fec78e6c323d565a221f7c4edc703f4567d7bb1caeafe1acd16a80c5ff82056b # via django-notifications-hq -django-modelcluster==6.3 +django-modelcluster==6.3 \ + --hash=sha256:0caed8a0e889f3abb92f144670878a466ef954ffa6c4c7b9c80e6426b720a49d \ + --hash=sha256:a8783d6565a0663f41cd6003ea361c3a5711e8a2a326160f1ec1eceb3e973d4f # via wagtail -django-notifications-hq==1.8.3 +django-notifications-hq==1.8.3 \ + --hash=sha256:0f4b216bb382b7c7c4eef273eb211e59c1c6a0ea38cba6077415ac031d330725 # via -r requirements.in -django-permissionedforms==0.1 +django-permissionedforms==0.1 \ + --hash=sha256:4340bb20c4477fffb13b4cc5cccf9f1b1010b64f79956c291c72d2ad2ed243f8 \ + --hash=sha256:d341a961a27cc77fde8cc42141c6ab55cc1f0cb886963cc2d6967b9674fa47d6 # via wagtail -django-redis==5.2.0 +django-redis==5.2.0 \ + --hash=sha256:1d037dc02b11ad7aa11f655d26dac3fb1af32630f61ef4428860a2e29ff92026 \ + --hash=sha256:8a99e5582c79f894168f5865c52bd921213253b7fd64d16733ae4591564465de # via -r requirements.in -django-rq==2.4.1 +django-rq==2.4.1 \ + --hash=sha256:23981f83c537178cbbf730f192c13e99cede2204e9d917b1c1c80c42215dd227 \ + --hash=sha256:f09059ab37403a47c7933bca396fabb7f3058732d132462eade5333bc4bcac5f # via django-translation-manager -django-sass-processor==1.0.1 +django-sass-processor==1.0.1 \ + --hash=sha256:1f043180c47754018e803a77da003377f5ea6558de57cd6946eb27a32e9c16a2 \ + --hash=sha256:dcaad47c591a2d52689c1bd209259e922e902d886293f0d5c9e0d1a4eb85eda2 # via -r requirements.in -django-taggit==2.1.0 +django-taggit==2.1.0 \ + --hash=sha256:61547a23fc99967c9304107414a09e662b459f4163dbbae32e60b8ba40c34d05 \ + --hash=sha256:a9f41e4ad58efe4b28d86f274728ee87eb98eeae90c9eb4b4efad39e5068184e # via wagtail -django-translation-manager==1.3.0 +django-translation-manager==1.3.0 \ + --hash=sha256:1e3143f48f9ba4d5452d72f55195142c434ea63786546251ae694508df4eb7b1 \ + --hash=sha256:9215b0149e78eaa13992a48367bf4ef28ef450e35863ea3ce7194b3558617bcf # via -r requirements.in -django-treebeard==4.7.1 +django-treebeard==4.7.1 \ + --hash=sha256:846e462904b437155f76e04907ba4e48480716855f88b898df4122bdcfbd6e98 \ + --hash=sha256:995c7120153ab999898fe3043bbdcd8a0fc77cc106eb94de7350e9d02c885135 # via wagtail -django-webpush==0.3.4 +django-webpush==0.3.4 \ + --hash=sha256:28cbe7da20f1df5b61d859f61e2d11d4076de1c367aa048d654894fb8f324065 \ + --hash=sha256:a123102dede1a959f667e075ed746ac5b7d4a8622320162eba41a507a835e1e4 \ + --hash=sha256:a2613784e822e2dde27086fb20b6d1a2b76e4d5dc8271607aecd45c98a3b7954 # via -r requirements.in -djangorestframework==3.13.1 +djangorestframework==3.13.1 \ + --hash=sha256:0c33407ce23acc68eca2a6e46424b008c9c02eceb8cf18581921d0092bc1f2ee \ + --hash=sha256:24c4bf58ed7e85d1fe4ba250ab2da926d263cd57d64b03e8dcef0ac683f8b1aa # via # -r requirements.in # django-comments-xtd @@ -122,68 +362,294 @@ djangorestframework==3.13.1 # djangorestframework-simplejwt # drf-yasg # wagtail -djangorestframework-simplejwt==5.3.1 +djangorestframework-simplejwt==5.3.1 \ + --hash=sha256:381bc966aa46913905629d472cd72ad45faa265509764e20ffd440164c88d220 \ + --hash=sha256:6c4bd37537440bc439564ebf7d6085e74c5411485197073f508ebdfa34bc9fae # via -r requirements.in -docutils==0.20.1 +docutils==0.20.1 \ + --hash=sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6 \ + --hash=sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b # via django-comments-xtd -draftjs-exporter==2.1.7 +draftjs-exporter==2.1.7 \ + --hash=sha256:5839cbc29d7bce2fb99837a404ca40c3a07313f2a20e2700de7ad6aa9a9a18fb \ + --hash=sha256:d415a9964690a2cddb66a31ef32dd46c277e9b80434b94e39e3043188ed83e33 # via wagtail -drf-yasg==1.21.7 +drf-yasg==1.21.7 \ + --hash=sha256:4c3b93068b3dfca6969ab111155e4dd6f7b2d680b98778de8fd460b7837bdb0d \ + --hash=sha256:f85642072c35e684356475781b7ecf5d218fff2c6185c040664dd49f0a4be181 # via -r requirements.in -elasticsearch==7.17.9 +elasticsearch==7.17.9 \ + --hash=sha256:0e2454645dc00517dee4c6de3863411a9c5f1955d013c5fefa29123dadc92f98 \ + --hash=sha256:66c4ece2adfe7cc120e2b6a6798a1fd5c777aecf82eec39bb95cef7cfc7ea2b3 # via -r requirements.in -et-xmlfile==1.1.0 +et-xmlfile==1.1.0 \ + --hash=sha256:8eb9e2bc2f8c97e37a2dc85a09ecdcdec9d8a396530a6d5a33b30b9a92da0c5c \ + --hash=sha256:a2ba85d1d6a74ef63837eed693bcb89c3f752169b0e3e7ae5b16ca5e1b3deada # via openpyxl -html5lib==1.1 +html5lib==1.1 \ + --hash=sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d \ + --hash=sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f # via wagtail -http-ece==1.2.0 +http-ece==1.2.0 \ + --hash=sha256:b5920f8efb8e1b5fb025713e3b36fda54336262010634b26dc1f98f85d1eb3de # via pywebpush -idna==3.7 +idna==3.7 \ + --hash=sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc \ + --hash=sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0 # via requests -importlib-metadata==8.5.0 +importlib-metadata==8.5.0 \ + --hash=sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b \ + --hash=sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7 # via markdown -inflection==0.5.1 +inflection==0.5.1 \ + --hash=sha256:1a29730d366e996aaacffb2f1f1cb9593dc38e2ddd30c91250c6dde09ea9b417 \ + --hash=sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2 # via drf-yasg -jsonfield==3.1.0 +jsonfield==3.1.0 \ + --hash=sha256:7e4e84597de21eeaeeaaa7cc5da08c61c48a9b64d0c446b2d71255d01812887a \ + --hash=sha256:df857811587f252b97bafba42e02805e70a398a7a47870bc6358a0308dd689ed # via django-notifications-hq -l18n==2021.3 +l18n==2021.3 \ + --hash=sha256:1956e890d673d17135cc20913253c154f6bc1c00266c22b7d503cc1a5a42d848 \ + --hash=sha256:78495d1df95b6f7dcc694d1ba8994df709c463a1cbac1bf016e1b9a5ce7280b9 # via wagtail -libsass==0.21.0 +libsass==0.21.0 \ + --hash=sha256:06c8776417fe930714bdc930a3d7e795ae3d72be6ac883ff72a1b8f7c49e5ffb \ + --hash=sha256:12f39712de38689a8b785b7db41d3ba2ea1d46f9379d81ea4595802d91fa6529 \ + --hash=sha256:1e25dd9047a9392d3c59a0b869e0404f2b325a03871ee45285ee33b3664f5613 \ + --hash=sha256:659ae41af8708681fa3ec73f47b9735a6725e71c3b66ff570bfce78952f2314e \ + --hash=sha256:6b984510ed94993708c0d697b4fef2d118929bbfffc3b90037be0f5ccadf55e7 \ + --hash=sha256:a005f298f64624f313a3ac618ab03f844c71d84ae4f4a4aec4b68d2a4ffe75eb \ + --hash=sha256:abc29357ee540849faf1383e1746d40d69ed5cb6d4c346df276b258f5aa8977a \ + --hash=sha256:c9ec490609752c1d81ff6290da33485aa7cb6d7365ac665b74464c1b7d97f7da \ + --hash=sha256:d5ba529d9ce668be9380563279f3ffe988f27bc5b299c5a28453df2e0b0fbaf2 \ + --hash=sha256:e2b1a7d093f2e76dc694c17c0c285e846d0b0deb0e8b21dc852ba1a3a4e2f1d6 # via -r requirements.in -lxml==4.9.4 +lxml==4.9.4 \ + --hash=sha256:00e91573183ad273e242db5585b52670eddf92bacad095ce25c1e682da14ed91 \ + --hash=sha256:01bf1df1db327e748dcb152d17389cf6d0a8c5d533ef9bab781e9d5037619229 \ + --hash=sha256:056a17eaaf3da87a05523472ae84246f87ac2f29a53306466c22e60282e54ff8 \ + --hash=sha256:0a08c89b23117049ba171bf51d2f9c5f3abf507d65d016d6e0fa2f37e18c0fc5 \ + --hash=sha256:1343df4e2e6e51182aad12162b23b0a4b3fd77f17527a78c53f0f23573663545 \ + --hash=sha256:1449f9451cd53e0fd0a7ec2ff5ede4686add13ac7a7bfa6988ff6d75cff3ebe2 \ + --hash=sha256:16b9ec51cc2feab009e800f2c6327338d6ee4e752c76e95a35c4465e80390ccd \ + --hash=sha256:1f10f250430a4caf84115b1e0f23f3615566ca2369d1962f82bef40dd99cd81a \ + --hash=sha256:231142459d32779b209aa4b4d460b175cadd604fed856f25c1571a9d78114771 \ + --hash=sha256:232fd30903d3123be4c435fb5159938c6225ee8607b635a4d3fca847003134ba \ + --hash=sha256:23d891e5bdc12e2e506e7d225d6aa929e0a0368c9916c1fddefab88166e98b20 \ + --hash=sha256:266f655d1baff9c47b52f529b5f6bec33f66042f65f7c56adde3fcf2ed62ae8b \ + --hash=sha256:273473d34462ae6e97c0f4e517bd1bf9588aa67a1d47d93f760a1282640e24ac \ + --hash=sha256:2bd9ac6e44f2db368ef8986f3989a4cad3de4cd55dbdda536e253000c801bcc7 \ + --hash=sha256:33714fcf5af4ff7e70a49731a7cc8fd9ce910b9ac194f66eaa18c3cc0a4c02be \ + --hash=sha256:359a8b09d712df27849e0bcb62c6a3404e780b274b0b7e4c39a88826d1926c28 \ + --hash=sha256:365005e8b0718ea6d64b374423e870648ab47c3a905356ab6e5a5ff03962b9a9 \ + --hash=sha256:389d2b2e543b27962990ab529ac6720c3dded588cc6d0f6557eec153305a3622 \ + --hash=sha256:3b505f2bbff50d261176e67be24e8909e54b5d9d08b12d4946344066d66b3e43 \ + --hash=sha256:3d74d4a3c4b8f7a1f676cedf8e84bcc57705a6d7925e6daef7a1e54ae543a197 \ + --hash=sha256:3f3f00a9061605725df1816f5713d10cd94636347ed651abdbc75828df302b20 \ + --hash=sha256:43498ea734ccdfb92e1886dfedaebeb81178a241d39a79d5351ba2b671bff2b2 \ + --hash=sha256:4855161013dfb2b762e02b3f4d4a21cc7c6aec13c69e3bffbf5022b3e708dd97 \ + --hash=sha256:4d973729ce04784906a19108054e1fd476bc85279a403ea1a72fdb051c76fa48 \ + --hash=sha256:4ece9cca4cd1c8ba889bfa67eae7f21d0d1a2e715b4d5045395113361e8c533d \ + --hash=sha256:506becdf2ecaebaf7f7995f776394fcc8bd8a78022772de66677c84fb02dd33d \ + --hash=sha256:520486f27f1d4ce9654154b4494cf9307b495527f3a2908ad4cb48e4f7ed7ef7 \ + --hash=sha256:5557461f83bb7cc718bc9ee1f7156d50e31747e5b38d79cf40f79ab1447afd2d \ + --hash=sha256:562778586949be7e0d7435fcb24aca4810913771f845d99145a6cee64d5b67ca \ + --hash=sha256:59bb5979f9941c61e907ee571732219fa4774d5a18f3fa5ff2df963f5dfaa6bc \ + --hash=sha256:606d445feeb0856c2b424405236a01c71af7c97e5fe42fbc778634faef2b47e4 \ + --hash=sha256:6197c3f3c0b960ad033b9b7d611db11285bb461fc6b802c1dd50d04ad715c225 \ + --hash=sha256:647459b23594f370c1c01768edaa0ba0959afc39caeeb793b43158bb9bb6a663 \ + --hash=sha256:647bfe88b1997d7ae8d45dabc7c868d8cb0c8412a6e730a7651050b8c7289cf2 \ + --hash=sha256:6bee9c2e501d835f91460b2c904bc359f8433e96799f5c2ff20feebd9bb1e590 \ + --hash=sha256:6dbdacf5752fbd78ccdb434698230c4f0f95df7dd956d5f205b5ed6911a1367c \ + --hash=sha256:701847a7aaefef121c5c0d855b2affa5f9bd45196ef00266724a80e439220e46 \ + --hash=sha256:786d6b57026e7e04d184313c1359ac3d68002c33e4b1042ca58c362f1d09ff58 \ + --hash=sha256:7b378847a09d6bd46047f5f3599cdc64fcb4cc5a5a2dd0a2af610361fbe77b16 \ + --hash=sha256:7d1d6c9e74c70ddf524e3c09d9dc0522aba9370708c2cb58680ea40174800013 \ + --hash=sha256:857d6565f9aa3464764c2cb6a2e3c2e75e1970e877c188f4aeae45954a314e0c \ + --hash=sha256:8671622256a0859f5089cbe0ce4693c2af407bc053dcc99aadff7f5310b4aa02 \ + --hash=sha256:88f7c383071981c74ec1998ba9b437659e4fd02a3c4a4d3efc16774eb108d0ec \ + --hash=sha256:8aecb5a7f6f7f8fe9cac0bcadd39efaca8bbf8d1bf242e9f175cbe4c925116c3 \ + --hash=sha256:91bbf398ac8bb7d65a5a52127407c05f75a18d7015a270fdd94bbcb04e65d573 \ + --hash=sha256:936e8880cc00f839aa4173f94466a8406a96ddce814651075f95837316369899 \ + --hash=sha256:953dd5481bd6252bd480d6ec431f61d7d87fdcbbb71b0d2bdcfc6ae00bb6fb10 \ + --hash=sha256:95ae6c5a196e2f239150aa4a479967351df7f44800c93e5a975ec726fef005e2 \ + --hash=sha256:9a2b5915c333e4364367140443b59f09feae42184459b913f0f41b9fed55794a \ + --hash=sha256:9ae6c3363261021144121427b1552b29e7b59de9d6a75bf51e03bc072efb3c37 \ + --hash=sha256:9b556596c49fa1232b0fff4b0e69b9d4083a502e60e404b44341e2f8fb7187f5 \ + --hash=sha256:9c131447768ed7bc05a02553d939e7f0e807e533441901dd504e217b76307745 \ + --hash=sha256:9d9d5726474cbbef279fd709008f91a49c4f758bec9c062dfbba88eab00e3ff9 \ + --hash=sha256:a1bdcbebd4e13446a14de4dd1825f1e778e099f17f79718b4aeaf2403624b0f7 \ + --hash=sha256:a602ed9bd2c7d85bd58592c28e101bd9ff9c718fbde06545a70945ffd5d11868 \ + --hash=sha256:a8edae5253efa75c2fc79a90068fe540b197d1c7ab5803b800fccfe240eed33c \ + --hash=sha256:a905affe76f1802edcac554e3ccf68188bea16546071d7583fb1b693f9cf756b \ + --hash=sha256:a9e7c6d89c77bb2770c9491d988f26a4b161d05c8ca58f63fb1f1b6b9a74be45 \ + --hash=sha256:aa9b5abd07f71b081a33115d9758ef6077924082055005808f68feccb27616bd \ + --hash=sha256:aaa5c173a26960fe67daa69aa93d6d6a1cd714a6eb13802d4e4bd1d24a530644 \ + --hash=sha256:ac7674d1638df129d9cb4503d20ffc3922bd463c865ef3cb412f2c926108e9a4 \ + --hash=sha256:b1541e50b78e15fa06a2670157a1962ef06591d4c998b998047fff5e3236880e \ + --hash=sha256:b1980dbcaad634fe78e710c8587383e6e3f61dbe146bcbfd13a9c8ab2d7b1192 \ + --hash=sha256:bafa65e3acae612a7799ada439bd202403414ebe23f52e5b17f6ffc2eb98c2be \ + --hash=sha256:bb5bd6212eb0edfd1e8f254585290ea1dadc3687dd8fd5e2fd9a87c31915cdab \ + --hash=sha256:bbdd69e20fe2943b51e2841fc1e6a3c1de460d630f65bde12452d8c97209464d \ + --hash=sha256:bc354b1393dce46026ab13075f77b30e40b61b1a53e852e99d3cc5dd1af4bc85 \ + --hash=sha256:bcee502c649fa6351b44bb014b98c09cb00982a475a1912a9881ca28ab4f9cd9 \ + --hash=sha256:bdd9abccd0927673cffe601d2c6cdad1c9321bf3437a2f507d6b037ef91ea307 \ + --hash=sha256:c42ae7e010d7d6bc51875d768110c10e8a59494855c3d4c348b068f5fb81fdcd \ + --hash=sha256:c71b5b860c5215fdbaa56f715bc218e45a98477f816b46cfde4a84d25b13274e \ + --hash=sha256:c7721a3ef41591341388bb2265395ce522aba52f969d33dacd822da8f018aff8 \ + --hash=sha256:ca8e44b5ba3edb682ea4e6185b49661fc22b230cf811b9c13963c9f982d1d964 \ + --hash=sha256:cb53669442895763e61df5c995f0e8361b61662f26c1b04ee82899c2789c8f69 \ + --hash=sha256:cc02c06e9e320869d7d1bd323df6dd4281e78ac2e7f8526835d3d48c69060683 \ + --hash=sha256:d3caa09e613ece43ac292fbed513a4bce170681a447d25ffcbc1b647d45a39c5 \ + --hash=sha256:d82411dbf4d3127b6cde7da0f9373e37ad3a43e89ef374965465928f01c2b979 \ + --hash=sha256:dbcb2dc07308453db428a95a4d03259bd8caea97d7f0776842299f2d00c72fc8 \ + --hash=sha256:dd4fda67f5faaef4f9ee5383435048ee3e11ad996901225ad7615bc92245bc8e \ + --hash=sha256:ddd92e18b783aeb86ad2132d84a4b795fc5ec612e3545c1b687e7747e66e2b53 \ + --hash=sha256:de362ac8bc962408ad8fae28f3967ce1a262b5d63ab8cefb42662566737f1dc7 \ + --hash=sha256:e214025e23db238805a600f1f37bf9f9a15413c7bf5f9d6ae194f84980c78722 \ + --hash=sha256:e8f9f93a23634cfafbad6e46ad7d09e0f4a25a2400e4a64b1b7b7c0fbaa06d9d \ + --hash=sha256:e96a1788f24d03e8d61679f9881a883ecdf9c445a38f9ae3f3f193ab6c591c66 \ + --hash=sha256:ec53a09aee61d45e7dbe7e91252ff0491b6b5fee3d85b2d45b173d8ab453efc1 \ + --hash=sha256:f10250bb190fb0742e3e1958dd5c100524c2cc5096c67c8da51233f7448dc137 \ + --hash=sha256:f1faee2a831fe249e1bae9cbc68d3cd8a30f7e37851deee4d7962b17c410dd56 \ + --hash=sha256:f610d980e3fccf4394ab3806de6065682982f3d27c12d4ce3ee46a8183d64a6a \ + --hash=sha256:f6c35b2f87c004270fa2e703b872fcc984d714d430b305145c39d53074e1ffe0 \ + --hash=sha256:f836f39678cb47c9541f04d8ed4545719dc31ad850bf1832d6b4171e30d65d23 \ + --hash=sha256:f99768232f036b4776ce419d3244a04fe83784bce871b16d2c2e984c7fcea847 \ + --hash=sha256:fd814847901df6e8de13ce69b84c31fc9b3fb591224d6762d0b256d510cbf382 \ + --hash=sha256:fdb325b7fba1e2c40b9b1db407f85642e32404131c08480dd652110fc908561b # via -r requirements.in -markdown==3.6 +markdown==3.6 \ + --hash=sha256:48f276f4d8cfb8ce6527c8f79e2ee29708508bf4d40aa410fbc3b4ee832c850f \ + --hash=sha256:ed4f41f6daecbeeb96e576ce414c41d2d876daa9a16cb35fa8ed8c2ddfad0224 # via wagtail-markdown -oauthlib==3.2.2 +oauthlib==3.2.2 \ + --hash=sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca \ + --hash=sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918 # via requests-oauthlib -openpyxl==3.1.5 +openpyxl==3.1.5 \ + --hash=sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2 \ + --hash=sha256:cf0e3cf56142039133628b5acffe8ef0c12bc902d2aadd3e0fe5878dc08d1050 # via tablib -packaging==24.1 +packaging==24.1 \ + --hash=sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002 \ + --hash=sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124 # via # bleach # drf-yasg -pillow==9.5.0 +pillow==9.5.0 \ + --hash=sha256:07999f5834bdc404c442146942a2ecadd1cb6292f5229f4ed3b31e0a108746b1 \ + --hash=sha256:0852ddb76d85f127c135b6dd1f0bb88dbb9ee990d2cd9aa9e28526c93e794fba \ + --hash=sha256:1781a624c229cb35a2ac31cc4a77e28cafc8900733a864870c49bfeedacd106a \ + --hash=sha256:1e7723bd90ef94eda669a3c2c19d549874dd5badaeefabefd26053304abe5799 \ + --hash=sha256:229e2c79c00e85989a34b5981a2b67aa079fd08c903f0aaead522a1d68d79e51 \ + --hash=sha256:22baf0c3cf0c7f26e82d6e1adf118027afb325e703922c8dfc1d5d0156bb2eeb \ + --hash=sha256:252a03f1bdddce077eff2354c3861bf437c892fb1832f75ce813ee94347aa9b5 \ + --hash=sha256:2dfaaf10b6172697b9bceb9a3bd7b951819d1ca339a5ef294d1f1ac6d7f63270 \ + --hash=sha256:322724c0032af6692456cd6ed554bb85f8149214d97398bb80613b04e33769f6 \ + --hash=sha256:35f6e77122a0c0762268216315bf239cf52b88865bba522999dc38f1c52b9b47 \ + --hash=sha256:375f6e5ee9620a271acb6820b3d1e94ffa8e741c0601db4c0c4d3cb0a9c224bf \ + --hash=sha256:3ded42b9ad70e5f1754fb7c2e2d6465a9c842e41d178f262e08b8c85ed8a1d8e \ + --hash=sha256:432b975c009cf649420615388561c0ce7cc31ce9b2e374db659ee4f7d57a1f8b \ + --hash=sha256:482877592e927fd263028c105b36272398e3e1be3269efda09f6ba21fd83ec66 \ + --hash=sha256:489f8389261e5ed43ac8ff7b453162af39c3e8abd730af8363587ba64bb2e865 \ + --hash=sha256:54f7102ad31a3de5666827526e248c3530b3a33539dbda27c6843d19d72644ec \ + --hash=sha256:560737e70cb9c6255d6dcba3de6578a9e2ec4b573659943a5e7e4af13f298f5c \ + --hash=sha256:5671583eab84af046a397d6d0ba25343c00cd50bce03787948e0fff01d4fd9b1 \ + --hash=sha256:5ba1b81ee69573fe7124881762bb4cd2e4b6ed9dd28c9c60a632902fe8db8b38 \ + --hash=sha256:5d4ebf8e1db4441a55c509c4baa7a0587a0210f7cd25fcfe74dbbce7a4bd1906 \ + --hash=sha256:60037a8db8750e474af7ffc9faa9b5859e6c6d0a50e55c45576bf28be7419705 \ + --hash=sha256:608488bdcbdb4ba7837461442b90ea6f3079397ddc968c31265c1e056964f1ef \ + --hash=sha256:6608ff3bf781eee0cd14d0901a2b9cc3d3834516532e3bd673a0a204dc8615fc \ + --hash=sha256:662da1f3f89a302cc22faa9f14a262c2e3951f9dbc9617609a47521c69dd9f8f \ + --hash=sha256:7002d0797a3e4193c7cdee3198d7c14f92c0836d6b4a3f3046a64bd1ce8df2bf \ + --hash=sha256:763782b2e03e45e2c77d7779875f4432e25121ef002a41829d8868700d119392 \ + --hash=sha256:77165c4a5e7d5a284f10a6efaa39a0ae8ba839da344f20b111d62cc932fa4e5d \ + --hash=sha256:7c9af5a3b406a50e313467e3565fc99929717f780164fe6fbb7704edba0cebbe \ + --hash=sha256:7ec6f6ce99dab90b52da21cf0dc519e21095e332ff3b399a357c187b1a5eee32 \ + --hash=sha256:833b86a98e0ede388fa29363159c9b1a294b0905b5128baf01db683672f230f5 \ + --hash=sha256:84a6f19ce086c1bf894644b43cd129702f781ba5751ca8572f08aa40ef0ab7b7 \ + --hash=sha256:8507eda3cd0608a1f94f58c64817e83ec12fa93a9436938b191b80d9e4c0fc44 \ + --hash=sha256:85ec677246533e27770b0de5cf0f9d6e4ec0c212a1f89dfc941b64b21226009d \ + --hash=sha256:8aca1152d93dcc27dc55395604dcfc55bed5f25ef4c98716a928bacba90d33a3 \ + --hash=sha256:8d935f924bbab8f0a9a28404422da8af4904e36d5c33fc6f677e4c4485515625 \ + --hash=sha256:8f36397bf3f7d7c6a3abdea815ecf6fd14e7fcd4418ab24bae01008d8d8ca15e \ + --hash=sha256:91ec6fe47b5eb5a9968c79ad9ed78c342b1f97a091677ba0e012701add857829 \ + --hash=sha256:965e4a05ef364e7b973dd17fc765f42233415974d773e82144c9bbaaaea5d089 \ + --hash=sha256:96e88745a55b88a7c64fa49bceff363a1a27d9a64e04019c2281049444a571e3 \ + --hash=sha256:99eb6cafb6ba90e436684e08dad8be1637efb71c4f2180ee6b8f940739406e78 \ + --hash=sha256:9adf58f5d64e474bed00d69bcd86ec4bcaa4123bfa70a65ce72e424bfb88ed96 \ + --hash=sha256:9b1af95c3a967bf1da94f253e56b6286b50af23392a886720f563c547e48e964 \ + --hash=sha256:a0aa9417994d91301056f3d0038af1199eb7adc86e646a36b9e050b06f526597 \ + --hash=sha256:a0f9bb6c80e6efcde93ffc51256d5cfb2155ff8f78292f074f60f9e70b942d99 \ + --hash=sha256:a127ae76092974abfbfa38ca2d12cbeddcdeac0fb71f9627cc1135bedaf9d51a \ + --hash=sha256:aaf305d6d40bd9632198c766fb64f0c1a83ca5b667f16c1e79e1661ab5060140 \ + --hash=sha256:aca1c196f407ec7cf04dcbb15d19a43c507a81f7ffc45b690899d6a76ac9fda7 \ + --hash=sha256:ace6ca218308447b9077c14ea4ef381ba0b67ee78d64046b3f19cf4e1139ad16 \ + --hash=sha256:b416f03d37d27290cb93597335a2f85ed446731200705b22bb927405320de903 \ + --hash=sha256:bf548479d336726d7a0eceb6e767e179fbde37833ae42794602631a070d630f1 \ + --hash=sha256:c1170d6b195555644f0616fd6ed929dfcf6333b8675fcca044ae5ab110ded296 \ + --hash=sha256:c380b27d041209b849ed246b111b7c166ba36d7933ec6e41175fd15ab9eb1572 \ + --hash=sha256:c446d2245ba29820d405315083d55299a796695d747efceb5717a8b450324115 \ + --hash=sha256:c830a02caeb789633863b466b9de10c015bded434deb3ec87c768e53752ad22a \ + --hash=sha256:cb841572862f629b99725ebaec3287fc6d275be9b14443ea746c1dd325053cbd \ + --hash=sha256:cfa4561277f677ecf651e2b22dc43e8f5368b74a25a8f7d1d4a3a243e573f2d4 \ + --hash=sha256:cfcc2c53c06f2ccb8976fb5c71d448bdd0a07d26d8e07e321c103416444c7ad1 \ + --hash=sha256:d3c6b54e304c60c4181da1c9dadf83e4a54fd266a99c70ba646a9baa626819eb \ + --hash=sha256:d3d403753c9d5adc04d4694d35cf0391f0f3d57c8e0030aac09d7678fa8030aa \ + --hash=sha256:d9c206c29b46cfd343ea7cdfe1232443072bbb270d6a46f59c259460db76779a \ + --hash=sha256:e49eb4e95ff6fd7c0c402508894b1ef0e01b99a44320ba7d8ecbabefddcc5569 \ + --hash=sha256:f8286396b351785801a976b1e85ea88e937712ee2c3ac653710a4a57a8da5d9c \ + --hash=sha256:f8fc330c3370a81bbf3f88557097d1ea26cd8b019d6433aa59f71195f5ddebbf \ + --hash=sha256:fbd359831c1657d69bb81f0db962905ee05e5e9451913b18b831febfe0519082 \ + --hash=sha256:fe7e1c262d3392afcf5071df9afa574544f28eac825284596ac6db56e6d11062 \ + --hash=sha256:fed1e1cf6a42577953abbe8e6cf2fe2f566daebde7c34724ec8803c4c0cda579 # via # cairosvg # wagtail -polib==1.2.0 +polib==1.2.0 \ + --hash=sha256:1c77ee1b81feb31df9bca258cbc58db1bbb32d10214b173882452c73af06d62d \ + --hash=sha256:f3ef94aefed6e183e342a8a269ae1fc4742ba193186ad76f175938621dbfc26b # via # django-translation-manager # wagtail-localize -psycopg2==2.9.9 +psycopg2==2.9.9 \ + --hash=sha256:121081ea2e76729acfb0673ff33755e8703d45e926e416cb59bae3a86c6a4981 \ + --hash=sha256:38a8dcc6856f569068b47de286b472b7c473ac7977243593a288ebce0dc89516 \ + --hash=sha256:426f9f29bde126913a20a96ff8ce7d73fd8a216cfb323b1f04da402d452853c3 \ + --hash=sha256:5e0d98cade4f0e0304d7d6f25bbfbc5bd186e07b38eac65379309c4ca3193efa \ + --hash=sha256:7e2dacf8b009a1c1e843b5213a87f7c544b2b042476ed7755be813eaf4e8347a \ + --hash=sha256:a7653d00b732afb6fc597e29c50ad28087dcb4fbfb28e86092277a559ae4e693 \ + --hash=sha256:ade01303ccf7ae12c356a5e10911c9e1c51136003a9a1d92f7aa9d010fb98372 \ + --hash=sha256:bac58c024c9922c23550af2a581998624d6e02350f4ae9c5f0bc642c633a2d5e \ + --hash=sha256:c92811b2d4c9b6ea0285942b2e7cac98a59e166d59c588fe5cfe1eda58e72d59 \ + --hash=sha256:d1454bde93fb1e224166811694d600e746430c006fbb031ea06ecc2ea41bf156 \ + --hash=sha256:d735786acc7dd25815e89cc4ad529a43af779db2e25aa7c626de864127e5a024 \ + --hash=sha256:de80739447af31525feddeb8effd640782cf5998e1a4e9192ebdf829717e3913 \ + --hash=sha256:ff432630e510709564c01dafdbe996cb552e0b9f3f065eb89bdce5bd31fabf4c # via -r requirements.in -py-vapid==1.9.1 +py-vapid==1.9.1 \ + --hash=sha256:fe2b5461bf45c7baff1039df6981f03b87faa87cde0482addfa35b3fe636ac1b # via pywebpush -pycparser==2.22 +pycparser==2.22 \ + --hash=sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6 \ + --hash=sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc # via cffi -pyjwt[crypto]==2.8.0 +pyjwt[crypto]==2.8.0 \ + --hash=sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de \ + --hash=sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320 # via # -r requirements.in # django-allauth # djangorestframework-simplejwt -python3-openid==3.2.0 +python3-openid==3.2.0 \ + --hash=sha256:33fbf6928f401e0b790151ed2b5290b02545e8775f982485205a066f874aaeaf \ + --hash=sha256:6626f771e0417486701e0b4daff762e7212e820ca5b29fcc0d05f6f8736dfa6b # via django-allauth -pytz==2024.1 +pytz==2024.1 \ + --hash=sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812 \ + --hash=sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319 # via # django # django-comments-xtd @@ -192,19 +658,76 @@ pytz==2024.1 # djangorestframework # drf-yasg # l18n -pywebpush==1.9.4 +pywebpush==1.9.4 \ + --hash=sha256:e3ded57c9715159f64a5624a656791ee9228b9e076ea0208baa73b53be8c130f # via django-webpush -pyyaml==6.0.1 +pyyaml==6.0.1 \ + --hash=sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5 \ + --hash=sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc \ + --hash=sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df \ + --hash=sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741 \ + --hash=sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206 \ + --hash=sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27 \ + --hash=sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595 \ + --hash=sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62 \ + --hash=sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98 \ + --hash=sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696 \ + --hash=sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290 \ + --hash=sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9 \ + --hash=sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d \ + --hash=sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6 \ + --hash=sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867 \ + --hash=sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47 \ + --hash=sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486 \ + --hash=sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6 \ + --hash=sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3 \ + --hash=sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 \ + --hash=sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938 \ + --hash=sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0 \ + --hash=sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c \ + --hash=sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735 \ + --hash=sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d \ + --hash=sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28 \ + --hash=sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4 \ + --hash=sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba \ + --hash=sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8 \ + --hash=sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef \ + --hash=sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5 \ + --hash=sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd \ + --hash=sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3 \ + --hash=sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0 \ + --hash=sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515 \ + --hash=sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c \ + --hash=sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c \ + --hash=sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924 \ + --hash=sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 \ + --hash=sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43 \ + --hash=sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859 \ + --hash=sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 \ + --hash=sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54 \ + --hash=sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a \ + --hash=sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b \ + --hash=sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab \ + --hash=sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa \ + --hash=sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c \ + --hash=sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585 \ + --hash=sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d \ + --hash=sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f # via drf-yasg -rcssmin==1.0.6 +rcssmin==1.0.6 \ + --hash=sha256:ca87b695d3d7864157773a61263e5abb96006e9ff0e021eff90cbe0e1ba18270 # via django-compressor -redis==3.5.3 +redis==3.5.3 \ + --hash=sha256:0e7e0cfca8660dea8b7d5cd8c4f6c5e29e11f31158c0b0ae91a397f00e5a05a2 \ + --hash=sha256:432b788c4530cfe16d8d943a09d40ca6c16149727e4afe8c2c9d5580c59d9f24 # via # -r requirements.in # django-redis # django-rq # rq -requests==2.32.3 +requests==2.32.3 \ + --hash=sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760 \ + --hash=sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6 # via # django-allauth # django-translation-manager @@ -212,13 +735,32 @@ requests==2.32.3 # requests-oauthlib # wagtail # wagtail-generic-chooser -requests-oauthlib==2.0.0 +requests-oauthlib==2.0.0 \ + --hash=sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36 \ + --hash=sha256:b3dffaebd884d8cd778494369603a9e7b58d29111bf6b41bdc2dcd87203af4e9 # via django-allauth -rjsmin==1.1.0 +rjsmin==1.1.0 \ + --hash=sha256:0ab825839125eaca57cc59581d72e596e58a7a56fbc0839996b7528f0343a0a8 \ + --hash=sha256:211c2fe8298951663bbc02acdffbf714f6793df54bfc50e1c6c9e71b3f2559a3 \ + --hash=sha256:466fe70cc5647c7c51b3260c7e2e323a98b2b173564247f9c89e977720a0645f \ + --hash=sha256:585e75a84d9199b68056fd4a083d9a61e2a92dfd10ff6d4ce5bdb04bc3bdbfaf \ + --hash=sha256:6044ca86e917cd5bb2f95e6679a4192cef812122f28ee08c677513de019629b3 \ + --hash=sha256:714329db774a90947e0e2086cdddb80d5e8c4ac1c70c9f92436378dedb8ae345 \ + --hash=sha256:799890bd07a048892d8d3deb9042dbc20b7f5d0eb7da91e9483c561033b23ce2 \ + --hash=sha256:975b69754d6a76be47c0bead12367a1ca9220d08e5393f80bab0230d4625d1f4 \ + --hash=sha256:b15dc75c71f65d9493a8c7fa233fdcec823e3f1b88ad84a843ffef49b338ac32 \ + --hash=sha256:dd0f4819df4243ffe4c964995794c79ca43943b5b756de84be92b445a652fb86 \ + --hash=sha256:e3908b21ebb584ce74a6ac233bdb5f29485752c9d3be5e50c5484ed74169232c \ + --hash=sha256:e487a7783ac4339e79ec610b98228eb9ac72178973e3dee16eba0e3feef25924 \ + --hash=sha256:ecd29f1b3e66a4c0753105baec262b331bcbceefc22fbe6f7e8bcd2067bcb4d7 # via django-compressor -rq==1.16.2 +rq==1.16.2 \ + --hash=sha256:52e619f6cb469b00e04da74305045d244b75fecb2ecaa4f26422add57d3c5f09 \ + --hash=sha256:5c5b9ad5fbaf792b8fada25cc7627f4d206a9a4455aced371d4f501cc3f13b34 # via django-rq -six==1.16.0 +six==1.16.0 \ + --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ + --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 # via # bleach # django-comments-xtd @@ -226,70 +768,120 @@ six==1.16.0 # html5lib # l18n # libsass -soupsieve==2.5 +soupsieve==2.5 \ + --hash=sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690 \ + --hash=sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7 # via beautifulsoup4 -sqlparse==0.5.0 +sqlparse==0.5.0 \ + --hash=sha256:714d0a4932c059d16189f58ef5411ec2287a4360f17cdd0edd2d09d4c5087c93 \ + --hash=sha256:c204494cd97479d0e39f28c93d46c0b2d5959c7b9ab904762ea6c7af211c8663 # via django -swapper==1.4.0 +swapper==1.4.0 \ + --hash=sha256:57b8378aad234242542fe32dc6e8cff0ed24b63493d20b3c88ee01f894b9345e \ + --hash=sha256:9e083af114ee0593241a7b877e3e0e7d3a580454f5d59016c667a5563306f8fe # via django-notifications-hq -tablib[xls,xlsx]==3.6.1 +tablib[xls,xlsx]==3.6.1 \ + --hash=sha256:040685fde11e9237675f43e985edb94b63250a5e9236f89d561ce6fb1465b839 \ + --hash=sha256:c771d38ed1d74350a69873db43e0afb7f1cca0ed2915a7243094463eb6789207 # via wagtail -telepath==0.3.1 +telepath==0.3.1 \ + --hash=sha256:925c0609e0a8a6488ec4a55b19d485882cf72223b2b19fe2359a50fddd813c9c \ + --hash=sha256:c280aa8e77ad71ce80e96500a4e4d4a32f35b7e0b52e896bb5fde9a5bcf0699a # via wagtail -tinycss2==1.3.0 +tinycss2==1.3.0 \ + --hash=sha256:152f9acabd296a8375fbca5b84c961ff95971fcfc32e79550c8df8e29118c54d \ + --hash=sha256:54a8dbdffb334d536851be0226030e9505965bb2f30f21a4a82c55fb2a80fae7 # via # cairosvg # cssselect2 -tqdm==4.66.4 +tqdm==4.66.4 \ + --hash=sha256:b75ca56b413b030bc3f00af51fd2c1a1a5eac6a0c1cca83cbb37a5c52abce644 \ + --hash=sha256:e4d936c9de8727928f3be6079590e97d9abfe8d39a590be678eb5919ffc186bb # via -r requirements.in -typing-extensions==4.12.2 +typing-extensions==4.12.2 \ + --hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \ + --hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8 # via # asgiref # wagtail-localize -uritemplate==4.1.1 +uritemplate==4.1.1 \ + --hash=sha256:4346edfc5c3b79f694bccd6d6099a322bbeb628dbf2cd86eea55a456ce5124f0 \ + --hash=sha256:830c08b8d99bdd312ea4ead05994a38e8936266f84b9a7878232db50b044e02e # via drf-yasg -urllib3==1.26.19 +urllib3==1.26.19 \ + --hash=sha256:37a0344459b199fce0e80b0d3569837ec6b6937435c5244e7fd73fa6006830f3 \ + --hash=sha256:3e3d753a8618b86d7de333b4223005f68720bcd6a7d2bcb9fbd2229ec7c1e429 # via # elasticsearch # requests -wagtail==3.0.3 +wagtail==3.0.3 \ + --hash=sha256:111ed9a0a6ff26d5d881d52deb4bf52b627d79a53c43829611752dbb68a9192f \ + --hash=sha256:23b3e541401355ea183372582050ea52b049c956dd5b506197f957bb68423ab3 # via # -r requirements.in # wagtail-cache # wagtail-localize # wagtail-markdown # wagtailmedia -wagtail-cache==2.1.1 +wagtail-cache==2.1.1 \ + --hash=sha256:1fe3ca20a3cdf23f31fc9df662a52f743084cd7f60bd870950094d63a87f695a \ + --hash=sha256:2ac16921d022a58240a009a19220554e41963c5172e7dfe4ef741ddd887e991f # via -r requirements.in -wagtail-generic-chooser==0.5.1 +wagtail-generic-chooser==0.5.1 \ + --hash=sha256:135f8cc413d83b82bb8956f625f4b9572aa7139ab3835e2ba2d7e19f2171b354 \ + --hash=sha256:280ae7293641d1b121450e17a6d424305e31c832f1af5bd991bc3e49703bf79e # via wagtailsvg -wagtail-localize==1.4 +wagtail-localize==1.4 \ + --hash=sha256:40f974809509de54dcc18ee6aa98908bffd9dfaba53150e214f4046b2286920e \ + --hash=sha256:fd1195de3c23e3a061576f1b947fe7498676ff5678fe008d4cd388125a20a54a # via -r requirements.in -wagtail-markdown==0.10.0 +wagtail-markdown==0.10.0 \ + --hash=sha256:b16be4b6e3518cc6dd15ab335cbc6d6a9122b5d7e3a61fa11c83597e2660044e \ + --hash=sha256:e4a97eee0211eebaab9c850669e647bc1c8ceb70df38b4db5a2c3d8b02ebaf69 # via -r requirements.in -wagtail-transfer @ https://github.com/IDEMSInternational/wagtail-transfer/archive/52b57b364ebc9acddd412ee708f829b45763c9ab.zip +wagtail-transfer @ https://github.com/IDEMSInternational/wagtail-transfer/archive/52b57b364ebc9acddd412ee708f829b45763c9ab.zip \ + --hash=sha256:049c23e1406564d3b7e8c385e72051f34e707add4f8109d874da670711709548 # via -r requirements.in -wagtailmedia==0.12.0 +wagtailmedia==0.12.0 \ + --hash=sha256:0807515c5d89782666b613de2e4aedab19e9dd358097fad2cb79633c0b5416d3 \ + --hash=sha256:1d39622c3d7d0191e58ffedf45d05fbef851e3905955513012a72ae4d46a12b0 # via -r requirements.in -wagtailmenus==3.1.3 +wagtailmenus==3.1.3 \ + --hash=sha256:0f5669f160d788b1ab8c2b412cb95411e9c07f83e4b52dddc92991752c6fa397 # via -r requirements.in -wagtailsvg==0.0.37 +wagtailsvg==0.0.37 \ + --hash=sha256:4b30433809614fbac09f9088b4aed42a1bfe56f9fb581b858606187cb177ca6b \ + --hash=sha256:dc4d698748bde32034b1eac2275cf159597ca8e399d3830e96391f761aa0cacf # via -r requirements.in -webencodings==0.5.1 +webencodings==0.5.1 \ + --hash=sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78 \ + --hash=sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923 # via # bleach # cssselect2 # html5lib # tinycss2 -whitenoise==5.2.0 +whitenoise==5.2.0 \ + --hash=sha256:05ce0be39ad85740a78750c86a93485c40f08ad8c62a6006de0233765996e5c7 \ + --hash=sha256:05d00198c777028d72d8b0bbd234db605ef6d60e9410125124002518a48e515d # via -r requirements.in -willow==1.4.1 +willow==1.4.1 \ + --hash=sha256:0df8ff528531e00b48d40bf72ed81beac1dc82f2d42e5bbed4aff0218bef8c0d \ + --hash=sha256:fc4042696d090e75aef922fa1ed26d483c764f005b36cf523cf7c34e69d5dd7a # via wagtail -xlrd==2.0.1 +xlrd==2.0.1 \ + --hash=sha256:6a33ee89877bd9abc1158129f6e94be74e2679636b8a205b43b85206c3f0bbdd \ + --hash=sha256:f72f148f54442c6b056bf931dbc34f986fd0c3b0b6b5a58d013c9aef274d0c88 # via tablib -xlsxwriter==3.2.0 +xlsxwriter==3.2.0 \ + --hash=sha256:9977d0c661a72866a61f9f7a809e25ebbb0fb7036baa3b9fe74afcfca6b3cb8c \ + --hash=sha256:ecfd5405b3e0e228219bcaf24c2ca0915e012ca9464a14048021d21a995d490e # via wagtail -xlwt==1.3.0 +xlwt==1.3.0 \ + --hash=sha256:a082260524678ba48a297d922cc385f58278b8aa68741596a87de01a9c628b2e \ + --hash=sha256:c59912717a9b28f1a3c2a98fd60741014b06b043936dcecbc113eaaada156c88 # via tablib -zipp==3.20.2 +zipp==3.20.2 \ + --hash=sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350 \ + --hash=sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29 # via importlib-metadata diff --git a/user_notifications/models.py b/user_notifications/models.py index cc0fa49d6..d07127577 100644 --- a/user_notifications/models.py +++ b/user_notifications/models.py @@ -4,9 +4,22 @@ from django.utils.timezone import now from wagtail.fields import RichTextField from iogt.settings.base import AUTH_USER_MODEL - +from django.contrib.auth import get_user_model @register_snippet class UserNotificationTemplate(models.Model): + NOTIFICATION_TYPES = [ + ("signup", "User Signup"), + ("article", "Article Published"), + ("survey", "Survey Published"), + # add more types as needed + ] + + type = models.CharField( + max_length=20, + choices=NOTIFICATION_TYPES, + unique=True, # optional: only one active per type + help_text="Select the type of notification this template is used for." + ) title = models.CharField(max_length=255) message = RichTextField(features=["bold", "italic", "link", "ul", "ol"]) active = models.BooleanField(default=True) @@ -16,6 +29,7 @@ class UserNotificationTemplate(models.Model): FieldPanel('title'), FieldPanel('message'), FieldPanel('active'), + FieldPanel('type'), ] def __str__(self): @@ -26,9 +40,42 @@ class Meta: verbose_name_plural = "User Notification Templates" +class NotificationTag(models.Model): + name = models.CharField(max_length=100, unique=True) + slug = models.SlugField(unique=True) + + def __str__(self): + return self.name + + class NotificationPreference(models.Model): + LANGUAGE_CHOICES = [ + ('en', 'English'), + ('es', 'Spanish'), + ('fr', 'French'), + ('ar', 'Arabic'), + ] user = models.OneToOneField(AUTH_USER_MODEL, on_delete=models.CASCADE) receive_notifications = models.BooleanField(null=True, blank=True) # NULL = not chosen yet + preferred_language = models.CharField(max_length=5, choices=LANGUAGE_CHOICES, default='en') + content_tags = models.ManyToManyField(NotificationTag, blank=True) + + def __str__(self): + return f"{self.user.username}'s Notification Preferences" + + +User = get_user_model() +class NotificationLog(models.Model): + STATE_CHOICES = [ + ('sent', 'Sent'), + ('failed', 'Failed'), + ] + + user = models.ForeignKey(User, on_delete=models.CASCADE) + notification_key = models.CharField(max_length=255) # e.g. template slug or key + state = models.CharField(max_length=20, choices=STATE_CHOICES, default='sent') + received_at = models.DateTimeField(auto_now_add=True) + error_message = models.TextField(blank=True, null=True) def __str__(self): - return f"{self.user.username} preferences" + return f"{self.notification_key} → {self.user.username} [{self.state}]" diff --git a/user_notifications/tasks.py b/user_notifications/tasks.py new file mode 100644 index 000000000..864afb9cd --- /dev/null +++ b/user_notifications/tasks.py @@ -0,0 +1,75 @@ +from celery import shared_task +from django.contrib.auth import get_user_model +from notifications.signals import notify +from user_notifications.models import UserNotificationTemplate, NotificationPreference +from .models import NotificationLog +User = get_user_model() + + +@shared_task +def send_signup_notifications(id, notification_type): + from home.models import Article + from questionnaires.models import Survey + try: + try: + if notification_type == 'signup': + sender = User.objects.get(id=id) + print('sender', sender) + elif notification_type == 'article': + print('notification_type-article-id', id) + sender = Article.objects.get(id=id) + print('sender', sender) + elif notification_type == 'survey': + print('notification_type-survey-id', id) + sender = Survey.objects.get(id=id) + print('sender', sender) + except User.DoesNotExist: + print(f"User with ID {id} not found") + return + template = UserNotificationTemplate.objects.filter(active=True, type=notification_type).latest("updated_at") + print('template', template) + print('preferences', NotificationPreference.objects.filter(receive_notifications=True)) + for notification_preference in NotificationPreference.objects.filter(receive_notifications=True): + try: + print('notification_preference record:-', notification_preference) + print('tags-name from notification_preference record:-', list(notification_preference.content_tags.values_list("name", flat=True))) + print('notification_type value', notification_type.capitalize()) + if (notification_type.capitalize()) not in list(notification_preference.content_tags.values_list("name", flat=True)): + print('if block', notification_preference.user) + NotificationLog.objects.create( + user=notification_preference.user, + notification_key=template.title, + state="type" + ) + else: + print('sending notification to user:-', notification_preference.user) + notify.send( + sender=sender, + url='www.google.com', + recipient=notification_preference.user, + verb=template.title, + description=template.message + ) + # send_user_notification(user=user, payload=json.dumps(template), ttl=1000) + # raise Exception + NotificationLog.objects.create( + user=notification_preference.user, + notification_key=template.title, + state="sent" + ) + + except Exception as e: + NotificationLog.objects.create( + user=notification_preference.user, + notification_key=template.title, + state="failed", + error_message=str(e) + ) + except Exception as e: + # Optional: log failure for user if user or template not found + NotificationLog.objects.create( + user_id=sender, + notification_key=template.title, + state="failed", + error_message=f"Task failure: {str(e)}" + ) \ No newline at end of file diff --git a/user_notifications/views.py b/user_notifications/views.py index 5f01e4564..268ec374f 100644 --- a/user_notifications/views.py +++ b/user_notifications/views.py @@ -8,7 +8,7 @@ from django.http import JsonResponse from django.views.decorators.http import require_POST -from .models import NotificationPreference +from .models import NotificationPreference, NotificationTag @login_required def latest_notifications(request): @@ -51,16 +51,37 @@ def unread_count(request): @login_required def save_notification_preference(request): print('request', request) - data = json.loads(request.body) - choice = data.get("choice") # "yes" or "no" + if request.method == "POST" and request.user.is_authenticated: + data = json.loads(request.body) + print('data', data) + choice = data.get("choice") # "yes" or "no" + language = data.get('language', 'en') + tag_ids = data.get('tags', []) - if choice not in ["yes", "no"]: - return JsonResponse({"error": "Invalid choice"}, status=400) + if choice not in [True, False]: + return JsonResponse({"error": "Invalid choice"}, status=400) - receive = (choice == "yes") - pref, _ = NotificationPreference.objects.get_or_create(user=request.user) - pref.receive_notifications = receive - pref.save() + # receive = (choice == "yes") + # pref, _ = NotificationPreference.objects.get_or_create(user=request.user) + # pref.receive_notifications = receive + # pref.save() + # choice = 'yes' if choice else 'No' + print('choice', choice) + if isinstance(choice, str): + choice = choice.lower() in ['yes', 'true', '1'] + print('choice-changes', choice) + preference, created = NotificationPreference.objects.update_or_create( + user=request.user, + defaults={ + 'receive_notifications': choice, + 'preferred_language': language, + } + ) - return JsonResponse({"status": "saved"}) + if tag_ids: + tags = NotificationTag.objects.filter(id__in=tag_ids) + preference.content_tags.set(tags) + + return JsonResponse({'status': 'ok'}) + return JsonResponse({'error': 'unauthorized'}, status=403) diff --git a/user_notifications/wagtail_hooks.py b/user_notifications/wagtail_hooks.py new file mode 100644 index 000000000..73319e7ff --- /dev/null +++ b/user_notifications/wagtail_hooks.py @@ -0,0 +1,53 @@ +from wagtail.contrib.modeladmin.options import ( + ModelAdmin, ModelAdminGroup, modeladmin_register +) +from .models import NotificationLog, NotificationPreference, NotificationTag + + +class NotificationTagAdmin(ModelAdmin): + model = NotificationTag + menu_label = "Notification Tags" + menu_icon = "tag" + list_display = ("name", "slug") + + +class NotificationPreferenceAdmin(ModelAdmin): + model = NotificationPreference + menu_label = "Notification Preferences" + menu_icon = "bell" + def get_content_tags(self, obj): + return ", ".join([tag.name for tag in obj.content_tags.all()]) + + get_content_tags.short_description = "Tags" + list_display = ("user", "receive_notifications", "preferred_language", "get_content_tags") + search_fields = ("user__username", "user__email") + + + + +class NotificationsGroup(ModelAdminGroup): + menu_label = "User Notifications" + menu_icon = "mail" + menu_order = 200 + items = (NotificationTagAdmin, NotificationPreferenceAdmin) + + +# class NotificationPreferenceAdmin(ModelAdmin): +# model = NotificationPreference +# menu_label = "Notification Preferences" +# menu_icon = "bell" # Wagtail icon name +# list_display = ("user", "receive_notifications") +# search_fields = ("user__username", "user__email") + + +class NotificationLogAdmin(ModelAdmin): + model = NotificationLog + menu_label = "Notification Logs" + menu_icon = "list-ul" # Wagtail icon name + menu_order = 200 + list_display = ("notification_key", "user", "state", "received_at") + search_fields = ("notification_key", "user__username", "user__email") + +modeladmin_register(NotificationsGroup) +# modeladmin_register(NotificationPreferenceAdmin) +modeladmin_register(NotificationLogAdmin) \ No newline at end of file From bdaf6d7bb3340f8cf11efa7f6f89032d3b3ca160 Mon Sep 17 00:00:00 2001 From: Ankit Chopra Date: Fri, 11 Jul 2025 18:49:38 +0530 Subject: [PATCH 011/147] changes of celery image and configuration --- docker-compose.yml | 32 +++++++++++++++++++++++++++++++- iogt/settings/dev.py | 5 +++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index f429fe040..1f00163a6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -20,9 +20,39 @@ services: - db volumes: - ./:/app/ +# db: +# image: postgres:14-alpine +# environment: +# POSTGRES_USER: postgres +# POSTGRES_PASSWORD: postgresiogt +# POSTGRES_DB: iogt + celery: + build: + context: ./ + target: dev + args: + requirements: requirements.dev.txt + command: celery -A iogt worker -l info + depends_on: + - django + - redis + environment: + CELERY_BROKER_URL: redis://redis:6379/0 + DB_HOST: db + DB_NAME: iogt + DB_PASSWORD: postgresiogt + DB_PORT: '5432' + DB_USER: postgres + DJANGO_SETTINGS_MODULE: iogt.settings.dev + volumes: + - ./:/app/ + + redis: + image: redis:7 + db: image: postgres:14-alpine environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgresiogt - POSTGRES_DB: iogt + POSTGRES_DB: iogt \ No newline at end of file diff --git a/iogt/settings/dev.py b/iogt/settings/dev.py index 4073bd772..0c792d8e4 100644 --- a/iogt/settings/dev.py +++ b/iogt/settings/dev.py @@ -29,6 +29,11 @@ 'PORT': getenv('DB_PORT', '5432'), } } +CELERY_BROKER_URL = 'redis://redis:6379/0' +CELERY_RESULT_BACKEND = 'redis://redis:6379/0' +CELERY_ACCEPT_CONTENT = ['json'] +CELERY_TASK_SERIALIZER = 'json' + try: from .local import * From 23edd2813f761792b86e15dbae63771f27ead65a Mon Sep 17 00:00:00 2001 From: Sachin Mehta Date: Tue, 15 Jul 2025 08:59:05 +0000 Subject: [PATCH 012/147] URL clickable and sendign data to push notifications --- admin_notifications/views.py | 36 ++++++++-- admin_notifications/wagtail_hooks.py | 3 - home/models.py | 13 ---- home/signals.py | 1 - iogt/static/js/iogt-no-jquery.js | 10 ++- iogt/static/js/iogt.js | 13 ++-- iogt/templates/header.html | 20 +++++- iogt/templates/sw.js | 69 ++++++++++++++++--- iogt_users/forms.py | 3 - iogt_users/views.py | 2 - questionnaires/signals.py | 2 - user_notifications/models.py | 6 ++ user_notifications/tasks.py | 13 ---- .../notification_dropdown.html | 29 ++++++-- .../user_notifications/notification_list.html | 33 ++++++--- user_notifications/urls.py | 2 + user_notifications/views.py | 44 +++++++++--- 17 files changed, 209 insertions(+), 90 deletions(-) diff --git a/admin_notifications/views.py b/admin_notifications/views.py index 373a39ec4..64faf561b 100644 --- a/admin_notifications/views.py +++ b/admin_notifications/views.py @@ -1,17 +1,41 @@ import json +from user_notifications.models import NotificationMeta from wagtail.contrib.modeladmin.views import CreateView from webpush import send_user_notification - - +from notifications.signals import notify +from notifications.models import Notification class CreateNotificationView(CreateView): def form_valid(self, form): payload = form.cleaned_data.copy() - print('payload', payload) groups = payload.pop('groups') for group in groups: for user in group.user_set.all(): - print('user_record', user) - send_user_notification(user=user, payload=json.dumps(payload), ttl=1000) - return super().form_valid(form) + # 1. Create Notification + notify.send( + sender=self.request.user, + recipient=user, + verb=payload.get('head', 'New Notification'), + description=payload.get('body', ''), + data=payload + ) + # 2. Get latest Notification for user (created just now) + notif_instance = Notification.objects.filter(recipient=user).order_by('-timestamp').first() + if not notif_instance: + continue # Shouldn't happen, but guard just in case + # 3. Avoid duplicate meta creation + NotificationMeta.objects.get_or_create(notification=notif_instance) + + # 4. Send Web Push + send_user_notification( + user=user, + payload={ + "title": payload.get("head", "IoGT Notification"), + "body": payload.get("body", ""), + "url": payload.get("url", "/"), + "notification_id": notif_instance.id + }, + ttl=1000) + + return super().form_valid(form) diff --git a/admin_notifications/wagtail_hooks.py b/admin_notifications/wagtail_hooks.py index ae63aae64..4308c8a92 100644 --- a/admin_notifications/wagtail_hooks.py +++ b/admin_notifications/wagtail_hooks.py @@ -14,9 +14,6 @@ class NotificationModelAdmin(ModelAdmin): menu_order = 601 create_view_class = CreateNotificationView -print('status_of_notification', settings.PUSH_NOTIFICATION) - - # Register with Wagtail admin if settings.PUSH_NOTIFICATION: modeladmin_register(NotificationModelAdmin) diff --git a/home/models.py b/home/models.py index 83e51a6c7..71ece5af1 100644 --- a/home/models.py +++ b/home/models.py @@ -136,7 +136,6 @@ def get_context(self, request): current_locale = Locale.get_default() # Get the true root of the Wagtail tree (depth=1) true_root = Page.get_first_root_node() - print('true_root', true_root) # Find the localized "home" page (like EnglishMainPage, ArabicMainPage) localized_home = None for page in true_root.get_children().live(): @@ -146,16 +145,13 @@ def get_context(self, request): ): localized_home = page break - print('localized_home', localized_home) # Optional fallback to default locale if not localized_home: fallback_locale = Locale.get_default() - print('fallback_locale', fallback_locale) for page in true_root.get_children().live(): if hasattr(page, 'locale') and page.locale == fallback_locale and page.slug != "home": localized_home = page break - print('default_localized_home', localized_home) # Find the localized BannerIndexPage (Banner Folder) banner_index = None @@ -593,7 +589,6 @@ def compute_number_of_reviews(self): def publish(self, *args, **kwargs): was_published = super().publish(*args, **kwargs) - print('in-publish-fn', was_published) # Trigger Celery notification task send_signup_notifications.delay(self.id, "article") @@ -630,14 +625,6 @@ class BannerIndexPage(Page): parent_page_types = ['home.HomePage'] subpage_types = ['home.BannerPage'] - # def get_context(self, request): - # print('testing........................') - # context = super().get_context(request) - # context['banners'] = self.get_children().live().order_by('path') # important! - # print('context', context) - # return context - # - class BannerPage(Page, PageUtilsMixin): parent_page_types = ['home.BannerIndexPage'] subpage_types = [] diff --git a/home/signals.py b/home/signals.py index 830e47667..8c80e9fd9 100644 --- a/home/signals.py +++ b/home/signals.py @@ -19,5 +19,4 @@ def update_article_feedback_metrics(sender, instance, **kwargs): @receiver(page_published) def trigger_article_notification(sender, instance, **kwargs): if isinstance(instance, Article): - print("Article published:", instance.title) send_signup_notifications.delay(instance.id, 'article') diff --git a/iogt/static/js/iogt-no-jquery.js b/iogt/static/js/iogt-no-jquery.js index dbfe42815..c17052422 100644 --- a/iogt/static/js/iogt-no-jquery.js +++ b/iogt/static/js/iogt-no-jquery.js @@ -162,16 +162,20 @@ const registerPushNotification = registration => { const urlB64ToUint8Array = base64String => { const padding = '='.repeat((4 - base64String.length % 4) % 4); const base64 = (base64String + padding) - .replace(/\-/g, '+') + .replace(/-/g, '+') .replace(/_/g, '/'); const rawData = window.atob(base64); const outputArray = new Uint8Array(rawData.length); - const outputData = outputArray.map((output, index) => rawData.charCodeAt(index)); - return outputData; + for (let i = 0; i < rawData.length; ++i) { + outputArray[i] = rawData.charCodeAt(i); + } + + return outputArray; }; + const subscribe = registration => { registration.pushManager.getSubscription() .then(subscription => { diff --git a/iogt/static/js/iogt.js b/iogt/static/js/iogt.js index 600677c12..297004da2 100644 --- a/iogt/static/js/iogt.js +++ b/iogt/static/js/iogt.js @@ -170,15 +170,19 @@ const registerPushNotification = registration => { const urlB64ToUint8Array = base64String => { const padding = '='.repeat((4 - base64String.length % 4) % 4); const base64 = (base64String + padding) - .replace(/\-/g, '+') + .replace(/-/g, '+') .replace(/_/g, '/'); const rawData = window.atob(base64); const outputArray = new Uint8Array(rawData.length); - const outputData = outputArray.map((output, index) => rawData.charCodeAt(index)); - return outputData; -} + for (let i = 0; i < rawData.length; ++i) { + outputArray[i] = rawData.charCodeAt(i); + } + + return outputArray; +}; + const subscribe = registration => { registration.pushManager.getSubscription() @@ -225,6 +229,7 @@ const sendSubscriptionToServer = (subscription, statusType) => { credentials: "include" }).then(resp => { setItem('isPushNotificationRegistered', statusType === 'subscribe'); + console.log(statusType) }); }; diff --git a/iogt/templates/header.html b/iogt/templates/header.html index 7da69168a..da328fa70 100644 --- a/iogt/templates/header.html +++ b/iogt/templates/header.html @@ -96,8 +96,26 @@ ids.forEach(id => query.append('ids[]', id)); const url = `{% url 'user_notifications:mark_selected_read' %}?${query.toString()}`; - fetch(url).then(response => response.json()).then(data => {}); + fetch(url).then(response => response.json()).then(data => { }); } + document.addEventListener("DOMContentLoaded", () => { + const notifLinks = document.querySelectorAll('.notification-item'); + notifLinks.forEach(el => { + el.addEventListener('click', function (e) { + const notifId = this.getAttribute("data-id"); + const notifUrl = this.getAttribute("href"); + + if (notifUrl && notifUrl !== "#") { + // Call click-marking endpoint only for notifications with a valid URL + fetch(`/notifications/mark-clicked/${notifId}/`, { + method: "POST" + }).then(res => res.json()).then(console.log); + } + }); + }); + }); + + {% endif %} \ No newline at end of file diff --git a/iogt/templates/sw.js b/iogt/templates/sw.js index 440499ce2..2702f4380 100644 --- a/iogt/templates/sw.js +++ b/iogt/templates/sw.js @@ -10,32 +10,79 @@ self.addEventListener('install', event => { self.addEventListener('push', function(event) { console.log('📩 Push received', event); - const title = "IoGT Notification"; - const options = { - body: "You have a new message.", - icon: "https://cdn-icons-png.flaticon.com/512/3119/3119338.png", -// badge: '/static/img/badge.png', // ✅ Optional - -// data: data.url || '/', // ✅ Click redirection - requireInteraction: true // ✅ Keeps it until dismissed + let data = {}; + + try { + if (event.data && event.data.json) { + // Try to parse JSON + data = event.data.json(); + } else if (event.data && event.data.text) { + // Fallback to text and wrap in object + const text = event.data.text(); + data = { body: text }; + } + } catch (e) { + console.warn("❌ Failed to parse push data", e); + data = { body: "You have a new message." }; + } + const title = data.title || "New Notification"; + const options = { + body: data.body || "You have a new message.", + icon: data.icon || "https://cdn-icons-png.flaticon.com/512/3119/3119338.png", + data: { + url: data.url || '/', + notification_id: data.notification_id || null, + }, + requireInteraction: true }; event.waitUntil( - self.registration.showNotification('New Notification', options) + self.registration.showNotification(title, options) ); - }); - // ✅ Activate Service Worker self.addEventListener('activate', event => { console.log("🚀 Service Workr Activated!"); event.waitUntil(self.clients.claim()); }); +self.addEventListener('notificationclick', function(event) { + console.log('🔔 Notification clicked:', event); + + // Optional: close the notification + event.notification.close(); + + const notificationData = event.notification.data || {}; + const targetUrl = notificationData.url || '/'; + + // Track click via fetch to server + if (notificationData.notification_id) { + fetch(`/notifications/mark-clicked/${notificationData.notification_id}/`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + credentials: 'include' + }).catch(err => console.warn('❌ Failed to log notification click:', err)); + } + + // Focus tab or open new one + event.waitUntil( + clients.matchAll({ type: 'window', includeUncontrolled: true }).then(clientList => { + for (let client of clientList) { + if (client.url === targetUrl && 'focus' in client) { + return client.focus(); + } + } + return clients.openWindow(targetUrl); + }) + ); +}); + // ✅ Handle Fetch Requests self.addEventListener('fetch', event => { const { request } = event; diff --git a/iogt_users/forms.py b/iogt_users/forms.py index 7c4db1d05..0a9ed352c 100644 --- a/iogt_users/forms.py +++ b/iogt_users/forms.py @@ -50,9 +50,6 @@ def __init__(self, *args, **kwargs): def save(self, request): user = super().save(request) - # 🔁 Run this logic in background - print('user', user) - print("Sending task to Celery...") send_signup_notifications.delay(user.id, 'signup') return user diff --git a/iogt_users/views.py b/iogt_users/views.py index 6b81cb104..ad7563283 100644 --- a/iogt_users/views.py +++ b/iogt_users/views.py @@ -30,8 +30,6 @@ def get_context_data(self, **kwargs): context['notification_tags'] = NotificationTag.objects.all() context['available_languages'] = Locale.objects.all() context['user'] = self.request.user - print('tags', context['notification_tags']) - print('available_languages', context['available_languages']) return context diff --git a/questionnaires/signals.py b/questionnaires/signals.py index e710d8503..bce6920a5 100644 --- a/questionnaires/signals.py +++ b/questionnaires/signals.py @@ -6,7 +6,5 @@ @receiver(page_published) def trigger_survey_notification(sender, instance, **kwargs): - print('in -trigger-function---------------------------------------') if isinstance(instance, Survey): - print("📢 Article published:", instance.title) send_signup_notifications.delay(instance.id, 'survey') \ No newline at end of file diff --git a/user_notifications/models.py b/user_notifications/models.py index d07127577..1da353dc5 100644 --- a/user_notifications/models.py +++ b/user_notifications/models.py @@ -5,6 +5,7 @@ from wagtail.fields import RichTextField from iogt.settings.base import AUTH_USER_MODEL from django.contrib.auth import get_user_model +from notifications.models import Notification @register_snippet class UserNotificationTemplate(models.Model): NOTIFICATION_TYPES = [ @@ -79,3 +80,8 @@ class NotificationLog(models.Model): def __str__(self): return f"{self.notification_key} → {self.user.username} [{self.state}]" + +class NotificationMeta(models.Model): + notification = models.OneToOneField(Notification, on_delete=models.CASCADE, related_name='meta') + is_clicked = models.BooleanField(default=False) + diff --git a/user_notifications/tasks.py b/user_notifications/tasks.py index 864afb9cd..346b6e61c 100644 --- a/user_notifications/tasks.py +++ b/user_notifications/tasks.py @@ -14,35 +14,22 @@ def send_signup_notifications(id, notification_type): try: if notification_type == 'signup': sender = User.objects.get(id=id) - print('sender', sender) elif notification_type == 'article': - print('notification_type-article-id', id) sender = Article.objects.get(id=id) - print('sender', sender) elif notification_type == 'survey': - print('notification_type-survey-id', id) sender = Survey.objects.get(id=id) - print('sender', sender) except User.DoesNotExist: - print(f"User with ID {id} not found") return template = UserNotificationTemplate.objects.filter(active=True, type=notification_type).latest("updated_at") - print('template', template) - print('preferences', NotificationPreference.objects.filter(receive_notifications=True)) for notification_preference in NotificationPreference.objects.filter(receive_notifications=True): try: - print('notification_preference record:-', notification_preference) - print('tags-name from notification_preference record:-', list(notification_preference.content_tags.values_list("name", flat=True))) - print('notification_type value', notification_type.capitalize()) if (notification_type.capitalize()) not in list(notification_preference.content_tags.values_list("name", flat=True)): - print('if block', notification_preference.user) NotificationLog.objects.create( user=notification_preference.user, notification_key=template.title, state="type" ) else: - print('sending notification to user:-', notification_preference.user) notify.send( sender=sender, url='www.google.com', diff --git a/user_notifications/templates/user_notifications/notification_dropdown.html b/user_notifications/templates/user_notifications/notification_dropdown.html index 04a52c805..1340cdddd 100644 --- a/user_notifications/templates/user_notifications/notification_dropdown.html +++ b/user_notifications/templates/user_notifications/notification_dropdown.html @@ -1,13 +1,30 @@ {% for n in notifications %} - +{% if n.data.url %} +
-

- {{ n.verb }} - {% if n.unread %}{% endif %} -

- {{ n.timestamp|timesince }} ago +

+ {{ n.verb }} + {% if not n.is_clicked %}{% endif %} +

+ {{ n.timestamp|timesince }} ago
+{% else %} +
+
+

+ {{ n.verb }} +

+ {{ n.timestamp|timesince }} ago +
+
+{% endif %} {% empty %}
No notifications yet!
{% endfor %} +{% block extra_js %} + +{% endblock %} \ No newline at end of file diff --git a/user_notifications/templates/user_notifications/notification_list.html b/user_notifications/templates/user_notifications/notification_list.html index bab9b885e..d9f2064f0 100644 --- a/user_notifications/templates/user_notifications/notification_list.html +++ b/user_notifications/templates/user_notifications/notification_list.html @@ -2,21 +2,32 @@ {% block content %}
-

All Notifications

+

All Notifications

{% for n in notifications %} - -
-

- {{ n.verb }} - {% if n.unread %}{% endif %} -

- {{ n.timestamp|timesince }} ago -
-
+ {% if n.data.url %} + +
+

+ {{ n.verb }} + {% if not n.is_clicked %}{% endif %} +

+ {{ n.timestamp|timesince }} ago +
+
+ {% else %} +
+
+

+ {{ n.verb }} +

+ {{ n.timestamp|timesince }} ago +
+
+ {% endif %} {% empty %} -
No notifications yet.
+
No notifications yet.
{% endfor %}
diff --git a/user_notifications/urls.py b/user_notifications/urls.py index cd40e5754..43c8a29f6 100644 --- a/user_notifications/urls.py +++ b/user_notifications/urls.py @@ -11,4 +11,6 @@ path('mark-selected-read/', views.mark_selected_read, name='mark_selected_read'), path('toggle-read//', views.toggle_read, name='toggle_read'), path('unread-count/', views.unread_count, name='unread_count'), + path('notifications/mark-clicked//', views.mark_notification_clicked, name='mark_notification_clicked') + ] diff --git a/user_notifications/views.py b/user_notifications/views.py index 268ec374f..909cb5834 100644 --- a/user_notifications/views.py +++ b/user_notifications/views.py @@ -2,22 +2,42 @@ from notifications.models import Notification from django.contrib.auth.decorators import login_required from django.shortcuts import render, redirect +from django.views.decorators.csrf import csrf_exempt from django.http import JsonResponse import json from django.contrib.auth.decorators import login_required from django.http import JsonResponse from django.views.decorators.http import require_POST -from .models import NotificationPreference, NotificationTag +from .models import NotificationMeta, NotificationPreference, NotificationTag @login_required def latest_notifications(request): notifications = Notification.objects.filter(recipient=request.user).order_by('-timestamp')[:5] - return render(request, 'user_notifications/notification_dropdown.html', {'notifications': notifications}) + + meta_map = { + meta.notification_id: meta.is_clicked + for meta in NotificationMeta.objects.filter(notification__in=notifications) + } + + for notif in notifications: + notif.is_clicked = meta_map.get(notif.id, False) + + return render(request, 'user_notifications/notification_dropdown.html', { + 'notifications': notifications + }) @login_required def all_notifications(request): notifications = Notification.objects.filter(recipient=request.user).order_by('-timestamp') + + # Annotate each notification with is_clicked + for n in notifications: + try: + n.is_clicked = n.meta.is_clicked + except NotificationMeta.DoesNotExist: + n.is_clicked = False # default + return render(request, 'user_notifications/notification_list.html', {'notifications': notifications}) @login_required @@ -50,10 +70,8 @@ def unread_count(request): @require_POST @login_required def save_notification_preference(request): - print('request', request) if request.method == "POST" and request.user.is_authenticated: data = json.loads(request.body) - print('data', data) choice = data.get("choice") # "yes" or "no" language = data.get('language', 'en') tag_ids = data.get('tags', []) @@ -61,15 +79,8 @@ def save_notification_preference(request): if choice not in [True, False]: return JsonResponse({"error": "Invalid choice"}, status=400) - # receive = (choice == "yes") - # pref, _ = NotificationPreference.objects.get_or_create(user=request.user) - # pref.receive_notifications = receive - # pref.save() - # choice = 'yes' if choice else 'No' - print('choice', choice) if isinstance(choice, str): choice = choice.lower() in ['yes', 'true', '1'] - print('choice-changes', choice) preference, created = NotificationPreference.objects.update_or_create( user=request.user, defaults={ @@ -85,3 +96,14 @@ def save_notification_preference(request): return JsonResponse({'status': 'ok'}) return JsonResponse({'error': 'unauthorized'}, status=403) +@require_POST +@login_required +def mark_notification_clicked(request, notification_id): + try: + notif = Notification.objects.get(id=notification_id) + meta, _ = NotificationMeta.objects.get_or_create(notification=notif) + meta.is_clicked = True + meta.save() + return JsonResponse({"status": "success"}) + except Notification.DoesNotExist: + return JsonResponse({"error": "Notification not found"}, status=404) From 2837c7e752f2241055fe539744eea2397620a36d Mon Sep 17 00:00:00 2001 From: Sachin Mehta Date: Wed, 16 Jul 2025 07:18:47 +0000 Subject: [PATCH 013/147] Notifications url changes --- admin_notifications/views.py | 2 +- home/static/css/global/global.css | 6 +-- iogt/settings/base.py | 3 ++ iogt/templates/header.html | 37 ++++++++----- iogt/templates/sw.js | 54 +++++++++++++------ .../notification_dropdown.html | 9 ++-- .../user_notifications/notification_list.html | 45 ++++++++-------- user_notifications/urls.py | 2 +- 8 files changed, 98 insertions(+), 60 deletions(-) diff --git a/admin_notifications/views.py b/admin_notifications/views.py index 64faf561b..f445fa9a4 100644 --- a/admin_notifications/views.py +++ b/admin_notifications/views.py @@ -16,7 +16,7 @@ def form_valid(self, form): recipient=user, verb=payload.get('head', 'New Notification'), description=payload.get('body', ''), - data=payload + url=payload.get("url", "/") ) # 2. Get latest Notification for user (created just now) diff --git a/home/static/css/global/global.css b/home/static/css/global/global.css index f414bd7e4..f0a8e8692 100644 --- a/home/static/css/global/global.css +++ b/home/static/css/global/global.css @@ -2157,9 +2157,9 @@ body.rtl { background-color: #f1f5fa; } -.notification-item.unread { - background-color: #e9f3ff; /* Light blue for unread */ - font-weight: 600; +.notification-item.unread, .notification-item.not_clicked { + background-color: #e9f3ff !important; /* Light blue for unread */ + font-weight: 600 !important; } .notification-item.read { diff --git a/iogt/settings/base.py b/iogt/settings/base.py index 59d5eda17..7487b916f 100644 --- a/iogt/settings/base.py +++ b/iogt/settings/base.py @@ -228,6 +228,9 @@ SITE_ID = 1 +#Notifications +DJANGO_NOTIFICATIONS_CONFIG = { 'USE_JSONFIELD': True} + # Comments COMMENTS_APP = 'django_comments_xtd' COMMENTS_XTD_MAX_THREAD_LEVEL = 1 diff --git a/iogt/templates/header.html b/iogt/templates/header.html index da328fa70..04ac25d81 100644 --- a/iogt/templates/header.html +++ b/iogt/templates/header.html @@ -99,22 +99,31 @@ fetch(url).then(response => response.json()).then(data => { }); } - document.addEventListener("DOMContentLoaded", () => { - const notifLinks = document.querySelectorAll('.notification-item'); - notifLinks.forEach(el => { - el.addEventListener('click', function (e) { - const notifId = this.getAttribute("data-id"); - const notifUrl = this.getAttribute("href"); + function handleNotificationClick(event, element) { + if (element.classList.contains('clicked')) { + return; // no fetch, no preventDefault + } + const notifId = element.getAttribute("data-id"); + const notifUrl = element.getAttribute("href"); + const clickUrlTemplate = "{% url 'user_notifications:mark_notification_clicked' 0 %}"; + const clickUrl = clickUrlTemplate.replace("0", notifId); - if (notifUrl && notifUrl !== "#") { - // Call click-marking endpoint only for notifications with a valid URL - fetch(`/notifications/mark-clicked/${notifId}/`, { - method: "POST" - }).then(res => res.json()).then(console.log); - } + if (notifUrl && notifUrl !== "#") { + event.preventDefault(); + + fetch(clickUrl, { + method: "POST", + headers: { + 'X-CSRFToken': '{{ csrf_token }}', + }, + }).then(() => { + window.location.href = notifUrl; + }).catch(err => { + console.warn("Error marking notification clicked:", err); + window.location.href = notifUrl; }); - }); - }); + } + } diff --git a/iogt/templates/sw.js b/iogt/templates/sw.js index 2702f4380..d958b1a48 100644 --- a/iogt/templates/sw.js +++ b/iogt/templates/sw.js @@ -120,24 +120,44 @@ self.addEventListener('fetch', event => { // ✅ Handle GET Requests (Serve from Cache when Offline) event.respondWith( - caches.match(request).then(cachedResponse => { - if (cachedResponse) { - console.log("✅ Serving from cache:", request.url); - return cachedResponse; - } - - return fetch(request) - .then(networkResponse => { - return caches.open('iogt').then(cache => { - cache.put(request, networkResponse.clone()); - return networkResponse; - }); - }) - .catch(() => { - return new Response('Offline - No cached content available', { status: 503 }); - }); - }) + fetch(request.clone(), { cache: 'no-store' }) // 1️⃣ Try the network first + .then(networkResponse => { + // 2️⃣ Optionally save a copy for offline use + // Only cache successful, basic (same‑origin) responses + if (networkResponse.ok && networkResponse.type === 'basic') { + caches.open('iogt') + .then(cache => cache.put(request, networkResponse.clone())) + .catch(err => console.warn('❌ Cache put failed', err)); + } + return networkResponse; // 3️⃣ Always return the live response + }) + .catch(() => { // 4️⃣ Network failed → offline fallback + return caches.match(request) // • Serve from cache if we have it + .then(cached => cached || // • …otherwise show a 503 + new Response('Offline', { status: 503 })); + }) ); + + // ✅ Handle GET Requests (Serve from Cache when Offline) + // event.respondWith( + // caches.match(request).then(cachedResponse => { + // if (cachedResponse) { + // console.log("✅ Serving from cache:", request.url); + // return cachedResponse; + // } + + // return fetch(request) + // .then(networkResponse => { + // return caches.open('iogt').then(cache => { + // cache.put(request, networkResponse.clone()); + // return networkResponse; + // }); + // }) + // .catch(() => { + // return new Response('Offline - No cached content available', { status: 503 }); + // }); + // }) + // ); }); // ✅ Background Sync for Form Submissions diff --git a/user_notifications/templates/user_notifications/notification_dropdown.html b/user_notifications/templates/user_notifications/notification_dropdown.html index 1340cdddd..3e128cbe6 100644 --- a/user_notifications/templates/user_notifications/notification_dropdown.html +++ b/user_notifications/templates/user_notifications/notification_dropdown.html @@ -1,7 +1,9 @@ {% for n in notifications %} {% if n.data.url %} - +

{{ n.verb }} @@ -11,7 +13,8 @@

{% else %} -
+

{{ n.verb }} diff --git a/user_notifications/templates/user_notifications/notification_list.html b/user_notifications/templates/user_notifications/notification_list.html index d9f2064f0..4b38dd52c 100644 --- a/user_notifications/templates/user_notifications/notification_list.html +++ b/user_notifications/templates/user_notifications/notification_list.html @@ -6,28 +6,31 @@

All Notifications

{% for n in notifications %} - {% if n.data.url %} - -
-

- {{ n.verb }} - {% if not n.is_clicked %}{% endif %} -

- {{ n.timestamp|timesince }} ago -
-
- {% else %} -
-
-

- {{ n.verb }} -

- {{ n.timestamp|timesince }} ago -
-
- {% endif %} + {% if n.data.url %} + +
+

+ {{ n.verb }} + {% if not n.is_clicked %}{% endif %} +

+ {{ n.timestamp|timesince }} ago +
+
+ {% else %} +
+
+

+ {{ n.verb }} +

+ {{ n.timestamp|timesince }} ago +
+
+ {% endif %} {% empty %} -
No notifications yet.
+
No notifications yet.
{% endfor %}
diff --git a/user_notifications/urls.py b/user_notifications/urls.py index 43c8a29f6..a37d06334 100644 --- a/user_notifications/urls.py +++ b/user_notifications/urls.py @@ -11,6 +11,6 @@ path('mark-selected-read/', views.mark_selected_read, name='mark_selected_read'), path('toggle-read//', views.toggle_read, name='toggle_read'), path('unread-count/', views.unread_count, name='unread_count'), - path('notifications/mark-clicked//', views.mark_notification_clicked, name='mark_notification_clicked') + path('mark-clicked//', views.mark_notification_clicked, name='mark_notification_clicked') ] From 8f73f9724e812d6b0f6d787f5e3f50ddf1787874 Mon Sep 17 00:00:00 2001 From: Sachin Mehta Date: Wed, 16 Jul 2025 07:52:33 +0000 Subject: [PATCH 014/147] Show description as well in Notifications --- home/static/css/global/global.css | 9 ++++++++- .../notification_dropdown.html | 14 +++++++++---- .../user_notifications/notification_list.html | 20 ++++++++++++------- 3 files changed, 31 insertions(+), 12 deletions(-) diff --git a/home/static/css/global/global.css b/home/static/css/global/global.css index f0a8e8692..9c13d8852 100644 --- a/home/static/css/global/global.css +++ b/home/static/css/global/global.css @@ -2174,10 +2174,17 @@ body.rtl { .notification-text { margin: 0; - font-size: 14px; + font-size: 0.8rem; line-height: 1.4; } +.notification-title { + font-weight: 600; + font-size: 0.85rem; + color: #000; + margin-bottom: 4px; +} + .notification-empty { padding: 24px; text-align: center; diff --git a/user_notifications/templates/user_notifications/notification_dropdown.html b/user_notifications/templates/user_notifications/notification_dropdown.html index 3e128cbe6..8ac42da89 100644 --- a/user_notifications/templates/user_notifications/notification_dropdown.html +++ b/user_notifications/templates/user_notifications/notification_dropdown.html @@ -5,21 +5,27 @@ data-id="{{ n.id }}" onclick="handleNotificationClick(event, this)">
-

+

{{ n.verb }} {% if not n.is_clicked %}{% endif %}

- {{ n.timestamp|timesince }} ago +

+ {{ n.description }} +

+ {{ n.timestamp|timesince }} ago
{% else %}
-

+

{{ n.verb }}

- {{ n.timestamp|timesince }} ago +

+ {{ n.description }} +

+ {{ n.timestamp|timesince }} ago
{% endif %} diff --git a/user_notifications/templates/user_notifications/notification_list.html b/user_notifications/templates/user_notifications/notification_list.html index 4b38dd52c..8d74c75fe 100644 --- a/user_notifications/templates/user_notifications/notification_list.html +++ b/user_notifications/templates/user_notifications/notification_list.html @@ -9,23 +9,29 @@

All Notifications

{% if n.data.url %} + data-id="{{ n.id }}" onclick="handleNotificationClick(event, this)">
-

+

{{ n.verb }} {% if not n.is_clicked %}{% endif %}

- {{ n.timestamp|timesince }} ago +

+ {{ n.description }} +

+ {{ n.timestamp|timesince }} ago
{% else %} -
+
-

+

{{ n.verb }}

- {{ n.timestamp|timesince }} ago +

+ {{ n.description }} +

+ {{ n.timestamp|timesince }} ago
{% endif %} From e954dc558bdddc95ec75cd14d14984234219d2d5 Mon Sep 17 00:00:00 2001 From: Ankit Chopra Date: Wed, 16 Jul 2025 14:03:56 +0530 Subject: [PATCH 015/147] Added changes to create page of the notification preference and also merged code --- admin_notifications/views.py | 3 +- admin_notifications/wagtail_hooks.py | 4 +- home/migrations/0060_auto_20250703_0253.py | 88 +++++++++++++ home/models.py | 15 ++- home/signals.py | 5 +- home/static/css/global/global.css | 24 ++++ iogt/urls.py | 4 +- iogt_users/forms.py | 7 +- iogt_users/templates/profile.html | 64 +--------- iogt_users/templates/user_notification.html | 120 ++++++++++++++++++ iogt_users/urls.py | 6 +- iogt_users/views.py | 29 ++++- questionnaires/signals.py | 5 +- user_notifications/models.py | 1 + user_notifications/tasks.py | 107 +++++++++++----- .../notification_dropdown.html | 4 +- .../user_notifications/notification_list.html | 4 +- user_notifications/views.py | 2 + user_notifications/wagtail_hooks.py | 43 ++++--- 19 files changed, 402 insertions(+), 133 deletions(-) create mode 100644 home/migrations/0060_auto_20250703_0253.py create mode 100644 iogt_users/templates/user_notification.html diff --git a/admin_notifications/views.py b/admin_notifications/views.py index f445fa9a4..df7a687e0 100644 --- a/admin_notifications/views.py +++ b/admin_notifications/views.py @@ -4,6 +4,8 @@ from webpush import send_user_notification from notifications.signals import notify from notifications.models import Notification + + class CreateNotificationView(CreateView): def form_valid(self, form): payload = form.cleaned_data.copy() @@ -37,5 +39,4 @@ def form_valid(self, form): "notification_id": notif_instance.id }, ttl=1000) - return super().form_valid(form) diff --git a/admin_notifications/wagtail_hooks.py b/admin_notifications/wagtail_hooks.py index 4308c8a92..4b4ed2ea8 100644 --- a/admin_notifications/wagtail_hooks.py +++ b/admin_notifications/wagtail_hooks.py @@ -15,6 +15,6 @@ class NotificationModelAdmin(ModelAdmin): create_view_class = CreateNotificationView # Register with Wagtail admin -if settings.PUSH_NOTIFICATION: - modeladmin_register(NotificationModelAdmin) +# if settings.PUSH_NOTIFICATION: +# modeladmin_register(NotificationModelAdmin) diff --git a/home/migrations/0060_auto_20250703_0253.py b/home/migrations/0060_auto_20250703_0253.py new file mode 100644 index 000000000..c5e3f151a --- /dev/null +++ b/home/migrations/0060_auto_20250703_0253.py @@ -0,0 +1,88 @@ +# Generated by Django 3.2.25 on 2025-07-03 02:53 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('home', '0059_burmese_locale'), + ] + + operations = [ + migrations.AlterField( + model_name='articlefeedback', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + migrations.AlterField( + model_name='articlerecommendation', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + migrations.AlterField( + model_name='articletaggeditem', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + migrations.AlterField( + model_name='featuredcontent', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + migrations.AlterField( + model_name='feedbacksettings', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + migrations.AlterField( + model_name='homepagebanner', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + migrations.AlterField( + model_name='iogtflatmenuitem', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + migrations.AlterField( + model_name='localedetail', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + migrations.AlterField( + model_name='manifestsettings', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + migrations.AlterField( + model_name='sectiontaggeditem', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + migrations.AlterField( + model_name='sitesettings', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + migrations.AlterField( + model_name='svgtopngmap', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + migrations.AlterField( + model_name='themesettings', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + migrations.AlterField( + model_name='v1pageurltov2pagemap', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + migrations.AlterField( + model_name='v1tov2objectmap', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + ] diff --git a/home/models.py b/home/models.py index 71ece5af1..c4414ce85 100644 --- a/home/models.py +++ b/home/models.py @@ -56,7 +56,7 @@ ) import iogt.iogt_globals as globals_ from django.db.models import Avg, Count -from user_notifications.tasks import send_signup_notifications +# from user_notifications.tasks import send_signup_notifications User = get_user_model() logger = logging.getLogger(__name__) @@ -587,12 +587,15 @@ def compute_average_rating(self): def compute_number_of_reviews(self): return self.number_of_reviews if self.number_of_reviews else 0 - def publish(self, *args, **kwargs): - was_published = super().publish(*args, **kwargs) - # Trigger Celery notification task - send_signup_notifications.delay(self.id, "article") - return was_published + # def publish(self, *args, **kwargs): + # was_published = super().publish(*args, **kwargs) + # print('in-publish-fn', was_published) + # # Trigger Celery notification task + # send_signup_notifications.delay(self.id, "article") + # + # return was_published + class ArticleFeedback(models.Model): diff --git a/home/signals.py b/home/signals.py index 8c80e9fd9..fe428079c 100644 --- a/home/signals.py +++ b/home/signals.py @@ -3,7 +3,7 @@ from .models import ArticleFeedback from wagtail.signals import page_published from .models import Article -from user_notifications.tasks import send_signup_notifications +from user_notifications.tasks import send_app_notifications @receiver(post_save, sender=ArticleFeedback) @@ -19,4 +19,5 @@ def update_article_feedback_metrics(sender, instance, **kwargs): @receiver(page_published) def trigger_article_notification(sender, instance, **kwargs): if isinstance(instance, Article): - send_signup_notifications.delay(instance.id, 'article') + send_app_notifications.delay(instance.id, 'article') + diff --git a/home/static/css/global/global.css b/home/static/css/global/global.css index 9c13d8852..2d5e291c7 100644 --- a/home/static/css/global/global.css +++ b/home/static/css/global/global.css @@ -2227,4 +2227,28 @@ body.rtl { #notification-overlay { width: 100%; } +} + +.highlight-yes { +background-color: #4caf50 !important; +color: white !important; +} +.highlight-no { +background-color: #f44336 !important; +color: white !important; +} +#yes_button, #no_button { + background-color: #e0e0e0; + color: black; + border: none; + cursor: pointer; + width: 92px; + height: 40 px; + height: 40px; + margin-left: 10px; +} +div.notification-confirmation{ + margin-bottom: 10px; + display: flex; + align-items: center; } \ No newline at end of file diff --git a/iogt/urls.py b/iogt/urls.py index 9ed56115d..046467d3a 100644 --- a/iogt/urls.py +++ b/iogt/urls.py @@ -18,7 +18,7 @@ from wagtail_transfer import urls as wagtailtransfer_urls from admin_login import urls as admin_login_urls from admin_login.views import AzureADSignupView -from user_notifications.views import save_notification_preference +# from user_notifications.views import save_notification_preference from iogt.views import ( @@ -34,7 +34,7 @@ api_url_patterns = [ path('api/v1/questionnaires/', include('questionnaires.api.v1.urls')), path('api/interactive/', include('interactive.api.urls')), - path("notifications/save-preference/", save_notification_preference, name="save_notification_preference"), + # path("notifications/save-preference/", save_notification_preference, name="save_notification_preference"), ] diff --git a/iogt_users/forms.py b/iogt_users/forms.py index 0a9ed352c..f49feab44 100644 --- a/iogt_users/forms.py +++ b/iogt_users/forms.py @@ -7,7 +7,7 @@ from wagtail.users.forms import UserEditForm as WagtailUserEditForm, \ UserCreationForm as WagtailUserCreationForm from user_notifications.models import UserNotificationTemplate -from user_notifications.tasks import send_signup_notifications +from user_notifications.tasks import send_app_notifications from .fields import IogtPasswordField from .models import User @@ -50,7 +50,10 @@ def __init__(self, *args, **kwargs): def save(self, request): user = super().save(request) - send_signup_notifications.delay(user.id, 'signup') + # 🔁 Run this logic in background + print('user', user) + print("Sending task to Celery...") + send_app_notifications.delay(user.id, 'signup') return user def clean_username(self): diff --git a/iogt_users/templates/profile.html b/iogt_users/templates/profile.html index eb54d6405..baf57f344 100644 --- a/iogt_users/templates/profile.html +++ b/iogt_users/templates/profile.html @@ -10,53 +10,20 @@ {% endblock %} {% block allauth_content %} + {% if user.username %}

{% blocktranslate trimmed with username=user.username %} Hey, {{ username }} {% endblocktranslate %} {{ user.username | first | upper }} - {% if request.user.is_authenticated %} -
-

Wouldss you like to enable desktop notifications?

- - - - - - -
- - -
-
- {% endif %}

{% endif %} {# Show notification banner only if preference is not yet set #}
+ {% url 'notification_settings' as notify_url %} + {% primary_button title='Notification Preference' href=notify_url icon_path='icons/arrow_icon_left.svg' extra_classnames='logout-btn' %} {% url 'account_change_password' as change_password_url %} {% primary_button title='Change Digital Pin' href=change_password_url icon_path='icons/lock.svg' extra_classnames='change-digital-pin' %} @@ -64,29 +31,4 @@

{% primary_button title='Log out' href=logout_url icon_path='icons/arrow_icon_left.svg' extra_classnames='logout-btn' %}

- - {% endblock %} \ No newline at end of file diff --git a/iogt_users/templates/user_notification.html b/iogt_users/templates/user_notification.html new file mode 100644 index 000000000..6f55639e2 --- /dev/null +++ b/iogt_users/templates/user_notification.html @@ -0,0 +1,120 @@ +{% extends 'account/base.html' %} +{% load i18n static image_tags generic_components %} + +{% block title %}{% translate "Profile" %}{% endblock %} + + +{% block content %} +{% if request.user.is_authenticated %} +

{% translate "Notification Preference" %}

+
{% translate "Would you like to enable notifications?" %} + + +
+ + + + + + +{% endif %} + + + +{% if request.user.is_authenticated %} + + + + + + + + + + + + + + + + +{% endif %} + + + +{% endblock %} \ No newline at end of file diff --git a/iogt_users/urls.py b/iogt_users/urls.py index 2b0fe187a..4874d5d03 100644 --- a/iogt_users/urls.py +++ b/iogt_users/urls.py @@ -1,8 +1,12 @@ from django.urls import path -from iogt_users.views import UserDetailEditView, UserDetailView, InviteAdminUserView +from iogt_users.views import UserDetailEditView, UserDetailView, InviteAdminUserView, UserNotificationView +from user_notifications.views import save_notification_preference urlpatterns = [ path('invite-admin-user/', InviteAdminUserView.as_view(), name='invite_admin_user'), path('profile/', UserDetailView.as_view(), name='user_profile'), path('profile/edit', UserDetailEditView.as_view(), name='user_profile_edit'), + path('profile/edit', UserDetailEditView.as_view(), name='user_profile_edit'), + path('notifications/settings/', UserNotificationView.as_view(), name='notification_settings'), + path("notifications/save-preference/", save_notification_preference, name="save_notification_preference"), ] \ No newline at end of file diff --git a/iogt_users/views.py b/iogt_users/views.py index ad7563283..b33fce9f1 100644 --- a/iogt_users/views.py +++ b/iogt_users/views.py @@ -17,22 +17,43 @@ from email_service.mailjet_email_sender import send_email_via_mailjet from user_notifications.models import NotificationPreference, NotificationTag -@method_decorator(login_required, name='dispatch') -class UserDetailView(TemplateView): - template_name = 'profile.html' + +class UserNotificationView(TemplateView): + template_name = 'user_notification.html' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) + print('authenticated_user', self.request.user.is_authenticated) if self.request.user.is_authenticated: - context['notification_preference'] = NotificationPreference.objects.filter(user=self.request.user).first() + notification_pref = NotificationPreference.objects.filter(user=self.request.user).first() + context['notification_preference'] = notification_pref + context['selected_tag_ids'] = list( + notification_pref.content_tags.values_list('id', flat=True) + ) if notification_pref else [] + context['selected_language_code'] = ( + notification_pref.preferred_language + if notification_pref and notification_pref.preferred_language else 'en') else: context['notification_preference'] = None context['notification_tags'] = NotificationTag.objects.all() context['available_languages'] = Locale.objects.all() context['user'] = self.request.user + print('tags', context['notification_tags']) + print('languages', context['selected_language_code']) + print('available_languages', context['available_languages']) return context +@method_decorator(login_required, name='dispatch') +class UserDetailView(TemplateView): + template_name = 'profile.html' + + def get_context_data(self, **kwargs): + return {'user': self.request.user} + + + + @method_decorator(login_required, name='dispatch') class UserDetailEditView(UpdateView): model = User diff --git a/questionnaires/signals.py b/questionnaires/signals.py index bce6920a5..c84dcbd1c 100644 --- a/questionnaires/signals.py +++ b/questionnaires/signals.py @@ -1,10 +1,11 @@ from django.dispatch import receiver from wagtail.signals import page_published from .models import Survey -from user_notifications.tasks import send_signup_notifications +from user_notifications.tasks import send_app_notifications @receiver(page_published) def trigger_survey_notification(sender, instance, **kwargs): if isinstance(instance, Survey): - send_signup_notifications.delay(instance.id, 'survey') \ No newline at end of file + print("📢 Article published:", instance.title) + send_app_notifications.delay(instance.id, 'survey') diff --git a/user_notifications/models.py b/user_notifications/models.py index 1da353dc5..f9397a8f0 100644 --- a/user_notifications/models.py +++ b/user_notifications/models.py @@ -77,6 +77,7 @@ class NotificationLog(models.Model): state = models.CharField(max_length=20, choices=STATE_CHOICES, default='sent') received_at = models.DateTimeField(auto_now_add=True) error_message = models.TextField(blank=True, null=True) + tags = models.CharField(max_length=255) def __str__(self): return f"{self.notification_key} → {self.user.username} [{self.state}]" diff --git a/user_notifications/tasks.py b/user_notifications/tasks.py index 346b6e61c..24ca6f6dc 100644 --- a/user_notifications/tasks.py +++ b/user_notifications/tasks.py @@ -3,60 +3,105 @@ from notifications.signals import notify from user_notifications.models import UserNotificationTemplate, NotificationPreference from .models import NotificationLog +from notifications.models import Notification +from user_notifications.models import NotificationMeta +from webpush import send_user_notification +from django.utils.html import strip_tags User = get_user_model() @shared_task -def send_signup_notifications(id, notification_type): +def send_app_notifications(id, notification_type): from home.models import Article from questionnaires.models import Survey try: try: - if notification_type == 'signup': - sender = User.objects.get(id=id) + template = UserNotificationTemplate.objects.filter(active=True, type=notification_type).latest("updated_at") + if notification_type == 'signup' or notification_type == 'web_push': + sender = User.objects.get(id=id) + notify.send( + sender=sender, + url='www.google.com', + recipient=sender, + verb=template.title, + description=template.message + ) + NotificationLog.objects.create( + user=sender, + notification_key=template.title, + tags=notification_type, + state="success" + ) elif notification_type == 'article': sender = Article.objects.get(id=id) elif notification_type == 'survey': sender = Survey.objects.get(id=id) except User.DoesNotExist: return - template = UserNotificationTemplate.objects.filter(active=True, type=notification_type).latest("updated_at") - for notification_preference in NotificationPreference.objects.filter(receive_notifications=True): - try: - if (notification_type.capitalize()) not in list(notification_preference.content_tags.values_list("name", flat=True)): - NotificationLog.objects.create( - user=notification_preference.user, - notification_key=template.title, - state="type" - ) - else: - notify.send( - sender=sender, - url='www.google.com', - recipient=notification_preference.user, - verb=template.title, - description=template.message - ) - # send_user_notification(user=user, payload=json.dumps(template), ttl=1000) - # raise Exception + + if notification_type != 'signup': + for notification_preference in NotificationPreference.objects.filter(receive_notifications=True): + try: + if (notification_type.capitalize()) not in list(notification_preference.content_tags.values_list("name", flat=True)): + NotificationLog.objects.create( + user=notification_preference.user, + notification_key=template.title, + tags=notification_type, + state="type" + ) + else: + notify.send( + sender=sender, + url='www.google.com', + recipient=notification_preference.user, + verb=template.title, + description=template.message + ) + # send_user_notification(user=user, payload=json.dumps(template), ttl=1000) + # raise Exception + NotificationLog.objects.create( + user=notification_preference.user, + notification_key=template.title, + tags=notification_type, + state="sent" + ) + notif_instance = Notification.objects.filter(recipient=notification_preference.user).order_by('-timestamp').first() + if not notif_instance: + continue # Shouldn't happen, but guard just in case + + # 3. Avoid duplicate meta creation + try: + NotificationMeta.objects.get_or_create(notification=notif_instance) + except Exception as e: + print(e) + # 4. Send Web Push + try: + send_user_notification( + user=notification_preference.user, + payload={ + "title": template.title, + "body": strip_tags(template.message), + "url": 'www.google.com', + "notification_id": notif_instance.id + }, + ttl=1000) + except Exception as e: + print(e) + + except Exception as e: NotificationLog.objects.create( user=notification_preference.user, notification_key=template.title, - state="sent" + tags=notification_type, + state="failed", + error_message=str(e) ) - - except Exception as e: - NotificationLog.objects.create( - user=notification_preference.user, - notification_key=template.title, - state="failed", - error_message=str(e) - ) except Exception as e: # Optional: log failure for user if user or template not found NotificationLog.objects.create( user_id=sender, notification_key=template.title, + tags=notification_type, state="failed", error_message=f"Task failure: {str(e)}" ) \ No newline at end of file diff --git a/user_notifications/templates/user_notifications/notification_dropdown.html b/user_notifications/templates/user_notifications/notification_dropdown.html index 8ac42da89..b6a43f55f 100644 --- a/user_notifications/templates/user_notifications/notification_dropdown.html +++ b/user_notifications/templates/user_notifications/notification_dropdown.html @@ -10,7 +10,7 @@ {% if not n.is_clicked %}{% endif %}

- {{ n.description }} + {{ n.description | safe }}

{{ n.timestamp|timesince }} ago
@@ -23,7 +23,7 @@ {{ n.verb }}

- {{ n.description }} + {{ n.description | safe}}

{{ n.timestamp|timesince }} ago
diff --git a/user_notifications/templates/user_notifications/notification_list.html b/user_notifications/templates/user_notifications/notification_list.html index 8d74c75fe..ab3192429 100644 --- a/user_notifications/templates/user_notifications/notification_list.html +++ b/user_notifications/templates/user_notifications/notification_list.html @@ -16,7 +16,7 @@

All Notifications

{% if not n.is_clicked %}{% endif %}

- {{ n.description }} + {{ n.description | safe }}

{{ n.timestamp|timesince }} ago
@@ -29,7 +29,7 @@

All Notifications

{{ n.verb }}

- {{ n.description }} + {{ n.description | safe }}

{{ n.timestamp|timesince }} ago diff --git a/user_notifications/views.py b/user_notifications/views.py index 909cb5834..b9bd7e615 100644 --- a/user_notifications/views.py +++ b/user_notifications/views.py @@ -92,6 +92,8 @@ def save_notification_preference(request): if tag_ids: tags = NotificationTag.objects.filter(id__in=tag_ids) preference.content_tags.set(tags) + else: + preference.content_tags.set(tag_ids) return JsonResponse({'status': 'ok'}) return JsonResponse({'error': 'unauthorized'}, status=403) diff --git a/user_notifications/wagtail_hooks.py b/user_notifications/wagtail_hooks.py index 73319e7ff..79ef63edd 100644 --- a/user_notifications/wagtail_hooks.py +++ b/user_notifications/wagtail_hooks.py @@ -2,7 +2,7 @@ ModelAdmin, ModelAdminGroup, modeladmin_register ) from .models import NotificationLog, NotificationPreference, NotificationTag - +from admin_notifications.wagtail_hooks import NotificationModelAdmin class NotificationTagAdmin(ModelAdmin): model = NotificationTag @@ -15,22 +15,41 @@ class NotificationPreferenceAdmin(ModelAdmin): model = NotificationPreference menu_label = "Notification Preferences" menu_icon = "bell" + def get_content_tags(self, obj): return ", ".join([tag.name for tag in obj.content_tags.all()]) get_content_tags.short_description = "Tags" list_display = ("user", "receive_notifications", "preferred_language", "get_content_tags") - search_fields = ("user__username", "user__email") + search_fields = ("user__username", "user__email", "preferred_language") + list_filter = ('preferred_language', 'content_tags') -class NotificationsGroup(ModelAdminGroup): - menu_label = "User Notifications" - menu_icon = "mail" +# class NotificationsGroup(ModelAdminGroup): +# menu_label = "User Notifications" +# menu_icon = "mail" +# menu_order = 200 +# items = (NotificationTagAdmin, NotificationPreferenceAdmin) + +class NotificationLogAdmin(ModelAdmin): + model = NotificationLog + menu_label = "Notification Logs" + menu_icon = "list-ul" # Wagtail icon name menu_order = 200 - items = (NotificationTagAdmin, NotificationPreferenceAdmin) + list_display = ("notification_key", "user", "state", "tags", "received_at") + search_fields = ("notification_key", "user__username", "user__email", "tags") +class NotificationsParentGroup(ModelAdminGroup): + menu_label= "Parent Notifications" + menu_icon = "bell" + items = ( + NotificationTagAdmin, + NotificationPreferenceAdmin, + NotificationModelAdmin, + NotificationLogAdmin + ) # class NotificationPreferenceAdmin(ModelAdmin): # model = NotificationPreference @@ -40,14 +59,8 @@ class NotificationsGroup(ModelAdminGroup): # search_fields = ("user__username", "user__email") -class NotificationLogAdmin(ModelAdmin): - model = NotificationLog - menu_label = "Notification Logs" - menu_icon = "list-ul" # Wagtail icon name - menu_order = 200 - list_display = ("notification_key", "user", "state", "received_at") - search_fields = ("notification_key", "user__username", "user__email") -modeladmin_register(NotificationsGroup) + +modeladmin_register(NotificationsParentGroup) # modeladmin_register(NotificationPreferenceAdmin) -modeladmin_register(NotificationLogAdmin) \ No newline at end of file +# modeladmin_register(NotificationLogAdmin) \ No newline at end of file From 2a854097574f0799f89dba4196fc82a6204a8ad1 Mon Sep 17 00:00:00 2001 From: Sachin Mehta Date: Wed, 16 Jul 2025 12:35:38 +0000 Subject: [PATCH 016/147] Reverted commented code --- admin_notifications/wagtail_hooks.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/admin_notifications/wagtail_hooks.py b/admin_notifications/wagtail_hooks.py index 4b4ed2ea8..5d2b17d43 100644 --- a/admin_notifications/wagtail_hooks.py +++ b/admin_notifications/wagtail_hooks.py @@ -15,6 +15,5 @@ class NotificationModelAdmin(ModelAdmin): create_view_class = CreateNotificationView # Register with Wagtail admin -# if settings.PUSH_NOTIFICATION: -# modeladmin_register(NotificationModelAdmin) - +if settings.PUSH_NOTIFICATION: + modeladmin_register(NotificationModelAdmin) From f4969b8a3a48750ab2b069df0d5210ca7c45a429 Mon Sep 17 00:00:00 2001 From: AjaySingh Date: Wed, 16 Jul 2025 17:16:38 +0000 Subject: [PATCH 017/147] wagtail upgrade 1 --- Dockerfile | 3 +- docker-compose.yml | 13 + home/models.py | 3 +- iogt/settings/base.py | 23 +- iogt/settings/dev.py | 12 + requirements.dev.txt | 682 ++++++++++++++++-------------------------- requirements.in | 64 ++-- requirements.txt | 271 ++++++++++++----- 8 files changed, 524 insertions(+), 547 deletions(-) diff --git a/Dockerfile b/Dockerfile index b1bbbb147..e863ef3a7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,7 +11,8 @@ RUN apt-get update --yes --quiet \ libpq5 \ && pip install --upgrade pip \ && pip install pip-tools \ - && rm -rf /var/lib/apt/lists/* + && rm -rf /var/lib/apt/lists/* \ + && apt-get install -y git WORKDIR /opt RUN python -m venv venv ENV PATH="/opt/venv/bin:$PATH" diff --git a/docker-compose.yml b/docker-compose.yml index 3bd1b4755..9ad58848e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,8 +7,21 @@ services: requirements: requirements.dev.txt environment: DJANGO_SETTINGS_MODULE: iogt.settings.dev + DB_HOST: db + DB_NAME: iogt + DB_PASSWORD: iogt + DB_PORT: '5432' + DB_USER: iogt + depends_on: + - db image: iogt:latest ports: - "8000:8000" volumes: - ./:/app/ + db: + image: postgres:14-alpine + environment: + POSTGRES_USER: iogt + POSTGRES_PASSWORD: iogt + POSTGRES_DB: iogt diff --git a/home/models.py b/home/models.py index e29442647..495dd00ca 100644 --- a/home/models.py +++ b/home/models.py @@ -25,7 +25,8 @@ ObjectList, TabbedInterface, ) -from wagtail.contrib.settings.models import BaseSetting +# from wagtail.contrib.settings.models import BaseSetting +from wagtail.contrib.settings.models import BaseSiteSetting as BaseSetting from wagtail.contrib.settings.registry import register_setting from wagtail import blocks from wagtail.fields import StreamField diff --git a/iogt/settings/base.py b/iogt/settings/base.py index 500c7ec7d..5c167fb29 100644 --- a/iogt/settings/base.py +++ b/iogt/settings/base.py @@ -15,11 +15,19 @@ PROFANITIES_LIST ) +# Monkey patch for deprecated ugettext_lazy used in third-party packages +import django.utils.translation +from django.utils.translation import gettext_lazy + +# Patch only if missing (for Django 4+ compatibility with old packages) +if not hasattr(django.utils.translation, 'ugettext_lazy'): + django.utils.translation.ugettext_lazy = gettext_lazy + PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) BASE_DIR = os.path.dirname(PROJECT_DIR) INSTALLED_APPS = [ - 'allauth', + 'allauth', 'allauth.account', 'allauth.socialaccount', 'comments', @@ -60,7 +68,7 @@ 'wagtail', 'wagtail.admin', 'wagtail.contrib.forms', - 'wagtail.contrib.modeladmin', + 'wagtail.contrib.redirects', 'wagtail.contrib.settings', 'wagtail.documents', @@ -70,10 +78,8 @@ 'wagtail.sites', 'wagtail.snippets', 'wagtail.users', - 'wagtail_localize', 'wagtail_localize.locales', 'wagtail_transfer', - 'wagtailcache', 'wagtailmarkdown', 'wagtailmedia', 'wagtailmenus', @@ -82,10 +88,12 @@ 'admin_login', 'email_service', ] +#'wagtail-modeladmin', +#'wagtail_localize', # The order of middleware is very important. Take care when modifying this list. MIDDLEWARE = [ - 'wagtailcache.cache.UpdateCacheMiddleware', + #'wagtailcache.cache.UpdateCacheMiddleware', 'django.middleware.security.SecurityMiddleware', 'whitenoise.middleware.WhiteNoiseMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', @@ -101,7 +109,10 @@ 'external_links.middleware.RewriteExternalLinksMiddleware', 'iogt.middleware.GlobalDataMiddleware', # 'admin_login.middleware.CustomAdminLoginRequiredMiddleware', - 'wagtailcache.cache.FetchFromCacheMiddleware', + #'wagtailcache.cache.FetchFromCacheMiddleware', + 'wagtail.contrib.statcache.middleware.StatCacheMiddleware', + 'django.middleware.cache.UpdateCacheMiddleware', # Must be first + 'django.middleware.cache.FetchFromCacheMiddleware', ] # Prevent Wagtail's built in menu from showing in Admin > Settings diff --git a/iogt/settings/dev.py b/iogt/settings/dev.py index eb76e60df..4354b0def 100644 --- a/iogt/settings/dev.py +++ b/iogt/settings/dev.py @@ -1,4 +1,5 @@ from .base import * +from os import getenv WAGTAILADMIN_BASE_URL = 'http://localhost:8000' DEBUG = True @@ -7,6 +8,17 @@ ALLOWED_HOSTS = ['*'] EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.postgresql', + 'NAME': getenv('DB_NAME', 'postgres'), + 'USER': getenv('DB_USER', 'postgres'), + 'PASSWORD': getenv('DB_PASSWORD', 'iogt'), + 'HOST': getenv('DB_HOST', 'database'), + 'PORT': getenv('DB_PORT', '5432'), + } +} + if DEBUG and DEBUG_TOOLBAR_ENABLE: INSTALLED_APPS += ("debug_toolbar",) MIDDLEWARE += ("debug_toolbar.middleware.DebugToolbarMiddleware",) diff --git a/requirements.dev.txt b/requirements.dev.txt index e6f43e065..7d65b0db2 100644 --- a/requirements.dev.txt +++ b/requirements.dev.txt @@ -2,57 +2,41 @@ # This file is autogenerated by pip-compile with Python 3.11 # by the following command: # -# pip-compile --generate-hashes requirements.dev.in +# pip-compile --generate-hashes requirements.in # anyascii==0.3.2 \ --hash=sha256:3b3beef6fc43d9036d3b0529050b0c48bfad8bc960e9e562d7223cfb94fe45d4 \ --hash=sha256:9d5d32ef844fe225b8bc7cba7f950534fae4da27a9bf3a6bea2cb0ea46ce4730 - # via - # -r requirements.txt - # wagtail + # via wagtail asgiref==3.8.1 \ --hash=sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47 \ --hash=sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590 - # via - # -r requirements.txt - # django -attrs==23.2.0 \ - --hash=sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30 \ - --hash=sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1 - # via - # outcome - # trio + # via django beautifulsoup4==4.9.3 \ --hash=sha256:4c98143716ef1cb40bf7f39a8e3eec8f8b009509e74904ba3a7b315431577e35 \ --hash=sha256:84729e322ad1d5b4d25f805bfa05b902dd96450f43842c4e99067d5e1369eb25 \ --hash=sha256:fff47e031e34ec82bf17e00da8f592fe7de69aeea38be00523c04623c04fb666 # via - # -r requirements.txt + # -r requirements.in # wagtail bleach==4.1.0 \ --hash=sha256:0900d8b37eba61a802ee40ac0061f8c2b5dee29c1927dd1d233e075ebf5a71da \ --hash=sha256:4d2651ab93271d1129ac9cbc679f524565cc8a1b791909c4a51eac4446a15994 - # via - # -r requirements.txt - # wagtail-markdown + # via wagtail-markdown cairocffi==1.7.1 \ --hash=sha256:2e48ee864884ec4a3a34bfa8c9ab9999f688286eb714a15a43ec9d068c36557b \ --hash=sha256:9803a0e11f6c962f3b0ae2ec8ba6ae45e957a146a004697a1ac1bbf16b073b3f - # via - # -r requirements.txt - # cairosvg + # via cairosvg cairosvg==2.7.1 \ --hash=sha256:432531d72347291b9a9ebfb6777026b607563fd8719c46ee742db0aef7271ba0 \ --hash=sha256:8a5222d4e6c3f86f1f7046b63246877a63b49923a1cd202184c3a634ef546b3b - # via -r requirements.txt + # via -r requirements.in certifi==2024.7.4 \ --hash=sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b \ --hash=sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90 # via - # -r requirements.txt # elasticsearch # requests - # selenium cffi==1.16.0 \ --hash=sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc \ --hash=sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a \ @@ -107,7 +91,6 @@ cffi==1.16.0 \ --hash=sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956 \ --hash=sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357 # via - # -r requirements.txt # cairocffi # cryptography charset-normalizer==3.3.2 \ @@ -201,69 +184,11 @@ charset-normalizer==3.3.2 \ --hash=sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33 \ --hash=sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519 \ --hash=sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561 - # via - # -r requirements.txt - # requests + # via requests click==8.1.7 \ --hash=sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28 \ --hash=sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de - # via - # -r requirements.txt - # rq -coverage==7.6.0 \ - --hash=sha256:0086cd4fc71b7d485ac93ca4239c8f75732c2ae3ba83f6be1c9be59d9e2c6382 \ - --hash=sha256:01c322ef2bbe15057bc4bf132b525b7e3f7206f071799eb8aa6ad1940bcf5fb1 \ - --hash=sha256:03cafe82c1b32b770a29fd6de923625ccac3185a54a5e66606da26d105f37dac \ - --hash=sha256:044a0985a4f25b335882b0966625270a8d9db3d3409ddc49a4eb00b0ef5e8cee \ - --hash=sha256:07ed352205574aad067482e53dd606926afebcb5590653121063fbf4e2175166 \ - --hash=sha256:0d1b923fc4a40c5832be4f35a5dab0e5ff89cddf83bb4174499e02ea089daf57 \ - --hash=sha256:0e7b27d04131c46e6894f23a4ae186a6a2207209a05df5b6ad4caee6d54a222c \ - --hash=sha256:1fad32ee9b27350687035cb5fdf9145bc9cf0a094a9577d43e909948ebcfa27b \ - --hash=sha256:289cc803fa1dc901f84701ac10c9ee873619320f2f9aff38794db4a4a0268d51 \ - --hash=sha256:3c59105f8d58ce500f348c5b56163a4113a440dad6daa2294b5052a10db866da \ - --hash=sha256:46c3d091059ad0b9c59d1034de74a7f36dcfa7f6d3bde782c49deb42438f2450 \ - --hash=sha256:482855914928c8175735a2a59c8dc5806cf7d8f032e4820d52e845d1f731dca2 \ - --hash=sha256:49c76cdfa13015c4560702574bad67f0e15ca5a2872c6a125f6327ead2b731dd \ - --hash=sha256:4b03741e70fb811d1a9a1d75355cf391f274ed85847f4b78e35459899f57af4d \ - --hash=sha256:4bea27c4269234e06f621f3fac3925f56ff34bc14521484b8f66a580aacc2e7d \ - --hash=sha256:4d5fae0a22dc86259dee66f2cc6c1d3e490c4a1214d7daa2a93d07491c5c04b6 \ - --hash=sha256:543ef9179bc55edfd895154a51792b01c017c87af0ebaae092720152e19e42ca \ - --hash=sha256:54dece71673b3187c86226c3ca793c5f891f9fc3d8aa183f2e3653da18566169 \ - --hash=sha256:6379688fb4cfa921ae349c76eb1a9ab26b65f32b03d46bb0eed841fd4cb6afb1 \ - --hash=sha256:65fa405b837060db569a61ec368b74688f429b32fa47a8929a7a2f9b47183713 \ - --hash=sha256:6616d1c9bf1e3faea78711ee42a8b972367d82ceae233ec0ac61cc7fec09fa6b \ - --hash=sha256:6fe885135c8a479d3e37a7aae61cbd3a0fb2deccb4dda3c25f92a49189f766d6 \ - --hash=sha256:7221f9ac9dad9492cecab6f676b3eaf9185141539d5c9689d13fd6b0d7de840c \ - --hash=sha256:76d5f82213aa78098b9b964ea89de4617e70e0d43e97900c2778a50856dac605 \ - --hash=sha256:7792f0ab20df8071d669d929c75c97fecfa6bcab82c10ee4adb91c7a54055463 \ - --hash=sha256:831b476d79408ab6ccfadaaf199906c833f02fdb32c9ab907b1d4aa0713cfa3b \ - --hash=sha256:9146579352d7b5f6412735d0f203bbd8d00113a680b66565e205bc605ef81bc6 \ - --hash=sha256:9cc44bf0315268e253bf563f3560e6c004efe38f76db03a1558274a6e04bf5d5 \ - --hash=sha256:a73d18625f6a8a1cbb11eadc1d03929f9510f4131879288e3f7922097a429f63 \ - --hash=sha256:a8659fd33ee9e6ca03950cfdcdf271d645cf681609153f218826dd9805ab585c \ - --hash=sha256:a94925102c89247530ae1dab7dc02c690942566f22e189cbd53579b0693c0783 \ - --hash=sha256:ad4567d6c334c46046d1c4c20024de2a1c3abc626817ae21ae3da600f5779b44 \ - --hash=sha256:b2e16f4cd2bc4d88ba30ca2d3bbf2f21f00f382cf4e1ce3b1ddc96c634bc48ca \ - --hash=sha256:bbdf9a72403110a3bdae77948b8011f644571311c2fb35ee15f0f10a8fc082e8 \ - --hash=sha256:beb08e8508e53a568811016e59f3234d29c2583f6b6e28572f0954a6b4f7e03d \ - --hash=sha256:c4cbe651f3904e28f3a55d6f371203049034b4ddbce65a54527a3f189ca3b390 \ - --hash=sha256:c7b525ab52ce18c57ae232ba6f7010297a87ced82a2383b1afd238849c1ff933 \ - --hash=sha256:ca5d79cfdae420a1d52bf177de4bc2289c321d6c961ae321503b2ca59c17ae67 \ - --hash=sha256:cdab02a0a941af190df8782aafc591ef3ad08824f97850b015c8c6a8b3877b0b \ - --hash=sha256:d17c6a415d68cfe1091d3296ba5749d3d8696e42c37fca5d4860c5bf7b729f03 \ - --hash=sha256:d39bd10f0ae453554798b125d2f39884290c480f56e8a02ba7a6ed552005243b \ - --hash=sha256:d4b3cd1ca7cd73d229487fa5caca9e4bc1f0bca96526b922d61053ea751fe791 \ - --hash=sha256:d50a252b23b9b4dfeefc1f663c568a221092cbaded20a05a11665d0dbec9b8fb \ - --hash=sha256:da8549d17489cd52f85a9829d0e1d91059359b3c54a26f28bec2c5d369524807 \ - --hash=sha256:dcd070b5b585b50e6617e8972f3fbbee786afca71b1936ac06257f7e178f00f6 \ - --hash=sha256:ddaaa91bfc4477d2871442bbf30a125e8fe6b05da8a0015507bfbf4718228ab2 \ - --hash=sha256:df423f351b162a702c053d5dddc0fc0ef9a9e27ea3f449781ace5f906b664428 \ - --hash=sha256:dff044f661f59dace805eedb4a7404c573b6ff0cdba4a524141bc63d7be5c7fd \ - --hash=sha256:e7e128f85c0b419907d1f38e616c4f1e9f1d1b37a7949f44df9a73d5da5cd53c \ - --hash=sha256:ed8d1d1821ba5fc88d4a4f45387b65de52382fa3ef1f0115a4f7a20cdfab0e94 \ - --hash=sha256:f2501d60d7497fd55e391f423f965bbe9e650e9ffc3c627d5f0ac516026000b8 \ - --hash=sha256:f7db0b6ae1f96ae41afe626095149ecd1b212b424626175a6633c2999eaad45b - # via -r requirements.dev.in + # via rq cryptography==42.0.8 \ --hash=sha256:013629ae70b40af70c9a7a5db40abe5d9054e6f4380e50ce769947b73bf3caad \ --hash=sha256:2346b911eb349ab547076f47f2e035fc8ff2c02380a7cbbf8d87114fa0f1c583 \ @@ -298,7 +223,6 @@ cryptography==42.0.8 \ --hash=sha256:fa76fbb7596cc5839320000cdd5d0955313696d9511debab7ee7278fc8b5c84a \ --hash=sha256:fff12c88a672ab9c9c1cf7b0c80e3ad9e2ebd9d828d955c126be4fd3e5578c9e # via - # -r requirements.txt # http-ece # py-vapid # pyjwt @@ -306,26 +230,23 @@ cryptography==42.0.8 \ cssselect2==0.7.0 \ --hash=sha256:1ccd984dab89fc68955043aca4e1b03e0cf29cad9880f6e28e3ba7a74b14aa5a \ --hash=sha256:fd23a65bfd444595913f02fc71f6b286c29261e354c41d722ca7a261a49b5969 - # via - # -r requirements.txt - # cairosvg + # via cairosvg defusedxml==0.7.1 \ --hash=sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69 \ --hash=sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61 # via - # -r requirements.txt # cairosvg # python3-openid -django==3.2.25 \ - --hash=sha256:7ca38a78654aee72378594d63e51636c04b8e28574f5505dff630895b5472777 \ - --hash=sha256:a52ea7fcf280b16f7b739cec38fa6d3f8953a5456986944c3ca97e79882b4e38 + # willow +django==5.2.4 \ + --hash=sha256:60c35bd96201b10c6e7a78121bd0da51084733efa303cc19ead021ab179cef5e \ + --hash=sha256:a1228c384f8fa13eebc015196db7b3e08722c5058d4758d20cb287503a540d8f # via - # -r requirements.txt + # -r requirements.in # django-allauth # django-appconf # django-comments-xtd # django-contrib-comments - # django-debug-toolbar # django-extensions # django-filter # django-health-check @@ -333,118 +254,107 @@ django==3.2.25 \ # django-permissionedforms # django-redis # django-rq + # django-stubs-ext # django-taggit + # django-tasks # django-translation-manager # django-treebeard # djangorestframework # djangorestframework-simplejwt # drf-yasg + # laces # wagtail # wagtail-localize # wagtailmedia -django-allauth==0.54.0 \ - --hash=sha256:120e265f802b65738899c6cb627b827fde46a4d03067034c633f516c2adf3e3e - # via -r requirements.txt +django-allauth==0.59.0 \ + --hash=sha256:ec19efb80b34d2f18bd831eab9b10b6301f58d1cce9f39af35f497b7e5b0a141 + # via -r requirements.in django-appconf==1.0.6 \ --hash=sha256:c3ae442fba1ff7ec830412c5184b17169a7a1e71cf0864a4c3f93cf4c98a1993 \ --hash=sha256:cfe87ea827c4ee04b9a70fab90b86d704cb02f2981f89da8423cb0fabf88efbf - # via - # -r requirements.txt - # django-compressor + # via django-compressor django-cogwheels==0.3 \ --hash=sha256:197bd05e7114403d7301214b3f8a371c4fb6039cf21c811f099438b167b5ed21 \ --hash=sha256:848a4d9f2c96c582a4a4f2e7c276dfd95ab3905748cae13bb7c4b365a6717e94 - # via - # -r requirements.txt - # wagtailmenus -django-comments-xtd==2.9.13 \ - --hash=sha256:0d91e3cc76eae6f30e83b12fb09708e5407664d9daa7b9c1101d7377897f7b42 \ - --hash=sha256:b289b6754d6618fb29e4279c6a1c6a270bc9495e161c42193d8b6216a4884802 - # via -r requirements.txt + # via wagtailmenus +django-comments-xtd==2.10.7 \ + --hash=sha256:0e3b833a881bc916a6bd77902a6ff944586073f3bdf020c153aba18a1efb65db \ + --hash=sha256:58f69ada5aa26fbb4d674937493026fc813248432d555902dfd776dab22627f5 + # via -r requirements.in django-compressor==2.4.1 \ --hash=sha256:3358077605c146fdcca5f9eaffb50aa5dbe15f238f8854679115ebf31c0415e0 \ --hash=sha256:f8313f59d5e65712fc28787d084fe834997c9dfa92d064a1a3ec3d3366594d04 - # via -r requirements.txt + # via -r requirements.in django-contrib-comments==2.2.0 \ --hash=sha256:2ca79060bbc8fc5b636981ef6e50f35ab83649af75fc1be47bf770636be3271c \ --hash=sha256:48de00f15677e016a216aeff205d6e00e4391c9a5702136c64119c472b7356da # via - # -r requirements.txt + # -r requirements.in # django-comments-xtd -django-debug-toolbar==4.3.0 \ - --hash=sha256:0b0dddee5ea29b9cb678593bc0d7a6d76b21d7799cb68e091a2148341a80f3c4 \ - --hash=sha256:e09b7dcb8417b743234dfc57c95a7c1d1d87a88844abd13b4c5387f807b31bf6 - # via -r requirements.dev.in django-extensions==3.1.5 \ --hash=sha256:28e1e1bf49f0e00307ba574d645b0af3564c981a6dfc87209d48cb98f77d0b1a \ --hash=sha256:9238b9e016bb0009d621e05cf56ea8ce5cce9b32e91ad2026996a7377ca28069 - # via -r requirements.txt -django-filter==2.4.0 \ - --hash=sha256:84e9d5bb93f237e451db814ed422a3a625751cbc9968b484ecc74964a8696b06 \ - --hash=sha256:e00d32cebdb3d54273c48f4f878f898dced8d5dfaad009438fe61ebdf535ace1 + # via -r requirements.in +django-filter==25.1 \ + --hash=sha256:1ec9eef48fa8da1c0ac9b411744b16c3f4c31176c867886e4c48da369c407153 \ + --hash=sha256:4fa48677cf5857b9b1347fed23e355ea792464e0fe07244d1fdfb8a806215b80 # via - # -r requirements.txt + # -r requirements.in # wagtail django-health-check==3.16.5 \ --hash=sha256:1edfd49293ccebbce29f9da609c407f307aee240ab799ab4201031341ae78c0f \ --hash=sha256:8d66781a0ea82b1a8b44878187b38a27370e94f18287312e39be0593e72d8983 - # via -r requirements.txt + # via -r requirements.in django-modelcluster==6.3 \ --hash=sha256:0caed8a0e889f3abb92f144670878a466ef954ffa6c4c7b9c80e6426b720a49d \ --hash=sha256:a8783d6565a0663f41cd6003ea361c3a5711e8a2a326160f1ec1eceb3e973d4f - # via - # -r requirements.txt - # wagtail + # via wagtail django-permissionedforms==0.1 \ --hash=sha256:4340bb20c4477fffb13b4cc5cccf9f1b1010b64f79956c291c72d2ad2ed243f8 \ --hash=sha256:d341a961a27cc77fde8cc42141c6ab55cc1f0cb886963cc2d6967b9674fa47d6 - # via - # -r requirements.txt - # wagtail + # via wagtail django-redis==5.2.0 \ --hash=sha256:1d037dc02b11ad7aa11f655d26dac3fb1af32630f61ef4428860a2e29ff92026 \ --hash=sha256:8a99e5582c79f894168f5865c52bd921213253b7fd64d16733ae4591564465de - # via -r requirements.txt + # via -r requirements.in django-rq==2.4.1 \ --hash=sha256:23981f83c537178cbbf730f192c13e99cede2204e9d917b1c1c80c42215dd227 \ --hash=sha256:f09059ab37403a47c7933bca396fabb7f3058732d132462eade5333bc4bcac5f - # via - # -r requirements.txt - # django-translation-manager + # via django-translation-manager django-sass-processor==1.0.1 \ --hash=sha256:1f043180c47754018e803a77da003377f5ea6558de57cd6946eb27a32e9c16a2 \ --hash=sha256:dcaad47c591a2d52689c1bd209259e922e902d886293f0d5c9e0d1a4eb85eda2 - # via -r requirements.txt -django-taggit==2.1.0 \ - --hash=sha256:61547a23fc99967c9304107414a09e662b459f4163dbbae32e60b8ba40c34d05 \ - --hash=sha256:a9f41e4ad58efe4b28d86f274728ee87eb98eeae90c9eb4b4efad39e5068184e - # via - # -r requirements.txt - # wagtail -django-test-plus==2.2.4 \ - --hash=sha256:06488209a07dca60dc2bbeaeae5ce340d17344163e0b121709cdac7405c6d9ef \ - --hash=sha256:96e4e16fabd3e0339a4b46e02a0a88c92c19800de38d00446571ea036614d332 - # via -r requirements.dev.in + # via -r requirements.in +django-stubs-ext==5.2.1 \ + --hash=sha256:98fb0646f1a1ef07708eec5f6f7d27523f12c0c8714abae8db981571ff957588 \ + --hash=sha256:fc0582cb3289306c43ce4a0a15af86922ce1dbec3c19eab80980ee70c04e0392 + # via django-tasks +django-taggit==6.1.0 \ + --hash=sha256:ab776264bbc76cb3d7e49e1bf9054962457831bd21c3a42db9138b41956e4cf0 \ + --hash=sha256:c4d1199e6df34125dd36db5eb0efe545b254dec3980ce5dd80e6bab3e78757c3 + # via wagtail +django-tasks==0.7.0 \ + --hash=sha256:499f80d1a051566443cfa88a300d8b03435af7fc5708cad4d8da6d285614f739 \ + --hash=sha256:8a8d64f2dc6e29ac2f45092d90e2dd82dc1dca100dfe3a4f2ce1209db99f3527 + # via wagtail django-translation-manager==1.3.0 \ --hash=sha256:1e3143f48f9ba4d5452d72f55195142c434ea63786546251ae694508df4eb7b1 \ --hash=sha256:9215b0149e78eaa13992a48367bf4ef28ef450e35863ea3ce7194b3558617bcf - # via -r requirements.txt + # via -r requirements.in django-treebeard==4.7.1 \ --hash=sha256:846e462904b437155f76e04907ba4e48480716855f88b898df4122bdcfbd6e98 \ --hash=sha256:995c7120153ab999898fe3043bbdcd8a0fc77cc106eb94de7350e9d02c885135 - # via - # -r requirements.txt - # wagtail + # via wagtail django-webpush==0.3.4 \ --hash=sha256:28cbe7da20f1df5b61d859f61e2d11d4076de1c367aa048d654894fb8f324065 \ --hash=sha256:a123102dede1a959f667e075ed746ac5b7d4a8622320162eba41a507a835e1e4 \ --hash=sha256:a2613784e822e2dde27086fb20b6d1a2b76e4d5dc8271607aecd45c98a3b7954 - # via -r requirements.txt -djangorestframework==3.13.1 \ - --hash=sha256:0c33407ce23acc68eca2a6e46424b008c9c02eceb8cf18581921d0092bc1f2ee \ - --hash=sha256:24c4bf58ed7e85d1fe4ba250ab2da926d263cd57d64b03e8dcef0ac683f8b1aa + # via -r requirements.in +djangorestframework==3.15.2 \ + --hash=sha256:2b8871b062ba1aefc2de01f773875441a961fefbf79f5eed1e32b2f096944b20 \ + --hash=sha256:36fe88cd2d6c6bec23dca9804bab2ba5517a8bb9d8f47ebc68981b56840107ad # via - # -r requirements.txt + # -r requirements.in # django-comments-xtd # django-translation-manager # djangorestframework-simplejwt @@ -453,83 +363,46 @@ djangorestframework==3.13.1 \ djangorestframework-simplejwt==5.3.1 \ --hash=sha256:381bc966aa46913905629d472cd72ad45faa265509764e20ffd440164c88d220 \ --hash=sha256:6c4bd37537440bc439564ebf7d6085e74c5411485197073f508ebdfa34bc9fae - # via -r requirements.txt + # via -r requirements.in docutils==0.21.2 \ --hash=sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f \ --hash=sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2 - # via - # -r requirements.txt - # django-comments-xtd + # via django-comments-xtd draftjs-exporter==2.1.7 \ --hash=sha256:5839cbc29d7bce2fb99837a404ca40c3a07313f2a20e2700de7ad6aa9a9a18fb \ --hash=sha256:d415a9964690a2cddb66a31ef32dd46c277e9b80434b94e39e3043188ed83e33 - # via - # -r requirements.txt - # wagtail + # via wagtail drf-yasg==1.21.7 \ --hash=sha256:4c3b93068b3dfca6969ab111155e4dd6f7b2d680b98778de8fd460b7837bdb0d \ --hash=sha256:f85642072c35e684356475781b7ecf5d218fff2c6185c040664dd49f0a4be181 - # via -r requirements.txt + # via -r requirements.in elasticsearch==7.17.9 \ --hash=sha256:0e2454645dc00517dee4c6de3863411a9c5f1955d013c5fefa29123dadc92f98 \ --hash=sha256:66c4ece2adfe7cc120e2b6a6798a1fd5c777aecf82eec39bb95cef7cfc7ea2b3 - # via -r requirements.txt + # via -r requirements.in et-xmlfile==1.1.0 \ --hash=sha256:8eb9e2bc2f8c97e37a2dc85a09ecdcdec9d8a396530a6d5a33b30b9a92da0c5c \ --hash=sha256:a2ba85d1d6a74ef63837eed693bcb89c3f752169b0e3e7ae5b16ca5e1b3deada - # via - # -r requirements.txt - # openpyxl -factory-boy==3.3.0 \ - --hash=sha256:a2cdbdb63228177aa4f1c52f4b6d83fab2b8623bf602c7dedd7eb83c0f69c04c \ - --hash=sha256:bc76d97d1a65bbd9842a6d722882098eb549ec8ee1081f9fb2e8ff29f0c300f1 - # via - # -r requirements.dev.in - # wagtail-factories -faker==26.0.0 \ - --hash=sha256:0f60978314973de02c00474c2ae899785a42b2cf4f41b7987e93c132a2b8a4a9 \ - --hash=sha256:886ee28219be96949cd21ecc96c4c742ee1680e77f687b095202c8def1a08f06 - # via - # -r requirements.dev.in - # factory-boy -h11==0.14.0 \ - --hash=sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d \ - --hash=sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761 - # via wsproto -html5lib==1.1 \ - --hash=sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d \ - --hash=sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f - # via - # -r requirements.txt - # wagtail + # via openpyxl +filetype==1.2.0 \ + --hash=sha256:66b56cd6474bf41d8c54660347d37afcc3f7d1970648de365c102ef77548aadb \ + --hash=sha256:7ce71b6880181241cf7ac8697a2f1eb6a8bd9b429f7ad6d27b8db9ba5f1c2d25 + # via willow http-ece==1.2.0 \ --hash=sha256:b5920f8efb8e1b5fb025713e3b36fda54336262010634b26dc1f98f85d1eb3de - # via - # -r requirements.txt - # pywebpush + # via pywebpush idna==3.7 \ --hash=sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc \ --hash=sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0 - # via - # -r requirements.txt - # requests - # trio + # via requests inflection==0.5.1 \ --hash=sha256:1a29730d366e996aaacffb2f1f1cb9593dc38e2ddd30c91250c6dde09ea9b417 \ --hash=sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2 - # via - # -r requirements.txt - # drf-yasg -iniconfig==2.0.0 \ - --hash=sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3 \ - --hash=sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374 - # via pytest -l18n==2021.3 \ - --hash=sha256:1956e890d673d17135cc20913253c154f6bc1c00266c22b7d503cc1a5a42d848 \ - --hash=sha256:78495d1df95b6f7dcc694d1ba8994df709c463a1cbac1bf016e1b9a5ce7280b9 - # via - # -r requirements.txt - # wagtail + # via drf-yasg +laces==0.1.2 \ + --hash=sha256:3218e09c1889ae5cf3fc7a82f5bb63ec0c7879889b6a9760bfc42323c694b84d \ + --hash=sha256:980cdaf9a31e883a2b8198132e2388931a4eb8814f5bfa5d8bba13ff9f657b7c + # via wagtail libsass==0.21.0 \ --hash=sha256:06c8776417fe930714bdc930a3d7e795ae3d72be6ac883ff72a1b8f7c49e5ffb \ --hash=sha256:12f39712de38689a8b785b7db41d3ba2ea1d46f9379d81ea4595802d91fa6529 \ @@ -541,7 +414,7 @@ libsass==0.21.0 \ --hash=sha256:c9ec490609752c1d81ff6290da33485aa7cb6d7365ac665b74464c1b7d97f7da \ --hash=sha256:d5ba529d9ce668be9380563279f3ffe988f27bc5b299c5a28453df2e0b0fbaf2 \ --hash=sha256:e2b1a7d093f2e76dc694c17c0c285e846d0b0deb0e8b21dc852ba1a3a4e2f1d6 - # via -r requirements.txt + # via -r requirements.in lxml==4.9.4 \ --hash=sha256:00e91573183ad273e242db5585b52670eddf92bacad095ce25c1e682da14ed91 \ --hash=sha256:01bf1df1db327e748dcb152d17389cf6d0a8c5d533ef9bab781e9d5037619229 \ @@ -636,37 +509,25 @@ lxml==4.9.4 \ --hash=sha256:f99768232f036b4776ce419d3244a04fe83784bce871b16d2c2e984c7fcea847 \ --hash=sha256:fd814847901df6e8de13ce69b84c31fc9b3fb591224d6762d0b256d510cbf382 \ --hash=sha256:fdb325b7fba1e2c40b9b1db407f85642e32404131c08480dd652110fc908561b - # via -r requirements.txt + # via -r requirements.in markdown==3.6 \ --hash=sha256:48f276f4d8cfb8ce6527c8f79e2ee29708508bf4d40aa410fbc3b4ee832c850f \ --hash=sha256:ed4f41f6daecbeeb96e576ce414c41d2d876daa9a16cb35fa8ed8c2ddfad0224 - # via - # -r requirements.txt - # wagtail-markdown + # via wagtail-markdown oauthlib==3.2.2 \ --hash=sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca \ --hash=sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918 - # via - # -r requirements.txt - # requests-oauthlib + # via requests-oauthlib openpyxl==3.1.5 \ --hash=sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2 \ --hash=sha256:cf0e3cf56142039133628b5acffe8ef0c12bc902d2aadd3e0fe5878dc08d1050 - # via - # -r requirements.txt - # tablib -outcome==1.3.0.post0 \ - --hash=sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8 \ - --hash=sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b - # via trio + # via wagtail packaging==24.1 \ --hash=sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002 \ --hash=sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124 # via - # -r requirements.txt # bleach # drf-yasg - # pytest pillow==9.5.0 \ --hash=sha256:07999f5834bdc404c442146942a2ecadd1cb6292f5229f4ed3b31e0a108746b1 \ --hash=sha256:0852ddb76d85f127c135b6dd1f0bb88dbb9ee990d2cd9aa9e28526c93e794fba \ @@ -735,94 +596,166 @@ pillow==9.5.0 \ --hash=sha256:fe7e1c262d3392afcf5071df9afa574544f28eac825284596ac6db56e6d11062 \ --hash=sha256:fed1e1cf6a42577953abbe8e6cf2fe2f566daebde7c34724ec8803c4c0cda579 # via - # -r requirements.txt # cairosvg + # pillow-heif # wagtail -pluggy==1.5.0 \ - --hash=sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1 \ - --hash=sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669 - # via pytest +pillow-heif==0.16.0 \ + --hash=sha256:0075adeb324adb07ddbfbe8a5c79ed12e5d04e60e9a642ff9427e71b5b0adccd \ + --hash=sha256:078bc74fd767625e465b2c107228f9c398b9a128bdf81b3f18812d7c07be660f \ + --hash=sha256:1421d96aebdc9f5773213c8221ce547efb56e37a62da6698312edd4f281efb42 \ + --hash=sha256:17963a73186961fe7792aef01c46e980635f3fcc1836393de39ec9c6776ca51e \ + --hash=sha256:1f4293ecbb81d255d8d887dce4708a58e87c86e53c6f1b1affc4c3105e1bcb8c \ + --hash=sha256:241cf6c510215c6df0ee948dfed06a20c099475250c5c6cac5e7a1ef9e0ec4c3 \ + --hash=sha256:2673048f3cf1498327add70f16e1129be2a09cf4a31cbc02363f5760eb5ba955 \ + --hash=sha256:28c980bf8d5239ee87986c9217a5954b07993d71d391949a9feafad0a9c5e9a7 \ + --hash=sha256:2b7450303f08ec81d1a63a75052863bb687fc3be1fdd8a34d2c0fef627aacae5 \ + --hash=sha256:331579ce4f5fa079595c529b06810886ff76f8ade3eb411a1c9c90853a708022 \ + --hash=sha256:33e0b1549bcdfec363b3ba6fb55b3de882e1409b5b00f5a68a1a027f051e8ef2 \ + --hash=sha256:3501f22985cbb427c76febf07a7e309cb828e485c0cf250a625733fc06fc1815 \ + --hash=sha256:38fa2854ec7dbe6c875d64cc5b3cf5cc55f1c8a0248dc1c7c34e9d2505521b82 \ + --hash=sha256:3a2681d4b62418813289987a9420059d724cd93542d0b05e0928fe4578517714 \ + --hash=sha256:3f062c1be6f04804ffdf0bc452142eff38d7544c8655c04291d16e3b996e4dc4 \ + --hash=sha256:40014105688478d6ca146fc04bff6c13f445d01bdea79417b34ee50c1e559190 \ + --hash=sha256:4b6caa5b13b4dfc180507527254014530f6bedbeabc1de2238918bf5b2700c7e \ + --hash=sha256:4d95004bb77aa640f80617716aa21bc092ec06307f6f2ad423deeeda07b4d29c \ + --hash=sha256:502cebc90c11a6bffa2ea899088999c25fc99c8f322e047a266e541e3046b27c \ + --hash=sha256:5c7f7a94fc2d08ddcf55a6834c4c55b7dea9605656c565ce11c82e3f6e0454a8 \ + --hash=sha256:7794c1a8304eeb841d72cb73aa64cc60c9e5dccb2c7612f8caf528505f78581f \ + --hash=sha256:792e5d88b7d016fe48ae2fd77a852ec8dcf9a7fad1f7f191d35bc173896fe378 \ + --hash=sha256:7e424d6a34b9466d054706393e76b5abdd84fabdc0c72b19ca10435a76140de7 \ + --hash=sha256:7ef47297d526147923f4ecc7ff681a5d5f4e6e3300017681f59968652a0d8afb \ + --hash=sha256:7fabd6534a38078a66ce8b7a5ae8ad37afd9863c930abd3031fb553f1ab4f01a \ + --hash=sha256:88ff22d2b162e7edd9cb9dd98de81455be04c40a99d1d3d3ebe1602b1a21c453 \ + --hash=sha256:89ec30420ddc843c43916febbe31697552ed123396a1696715eea75169866c07 \ + --hash=sha256:8e168d45b2ce63c1fe2334fd02927699b0097de72605f7571948010fd79e58f0 \ + --hash=sha256:8f15dc73ced02a0ccfac93159d12deeaecfbe4335883a1a3309df0f01c26e6e6 \ + --hash=sha256:9273af7224e0fb16c18637184a8ea9a8790105658daab04ad541982b8623e5c1 \ + --hash=sha256:9923dfcc97ae9484d3514f2f6ec368e2ac97cd66f7b95359cc1b0ec0c1cd6157 \ + --hash=sha256:9bf10a1686c2d51f4db8ebb78825f96f28d18d1878599e1c64e88cfbdb70a3d2 \ + --hash=sha256:9fd829c257a763e3a2e8418a773c2808c90799ee3e6b405b5399cb4fdfbe336e \ + --hash=sha256:a146be0c8e7bef204eeaa14799b2fca8a4a52ad972850975e23ef10cee4e7de7 \ + --hash=sha256:a27abb523a07b17c118c09f1a00f92cde2295f8e997600024d4b57df3c5ba818 \ + --hash=sha256:a8856cf5f0d53f83d814ae5c8d34433e5e5ad9f3e328480257cd6e9fbdb4a458 \ + --hash=sha256:b50160331754b603524e6ed33c386f478fd66fb345fa6433a507a01c8de642c6 \ + --hash=sha256:bbd9cc527bbd53c3e7588e16aad170e11cfd180b7e9bd84f18fb020ddec11408 \ + --hash=sha256:be41b7fadd4a9355d24936f6fad83bb8130fe55ba228ec298ad316392bb6f38b \ + --hash=sha256:beb6576cbe5a9404a8f2ad9ec68f6b0c406e5e9f5d5573722dc3244898dc9866 \ + --hash=sha256:c2ad68e3e4be40adfc5290bf6daa1569dd7d18501e17779d217ce5cd8c1e338d \ + --hash=sha256:c7db96ac172e2654676986e8c35fa32bffdd5b429a8c86b9d628c0333c570d82 \ + --hash=sha256:d4595ec975db845d84ab90cbf0678f15b0068b8b83c01d1db7ea524e31bab4b4 \ + --hash=sha256:d9e465d92cf01093e3e4c33776af97368add23ac1c8d0007f34b8d3e3390d6ad \ + --hash=sha256:e0492e4fd6d3334b9eed3651058216ef62f04afa099cfc6b05815c1bf0da2c38 \ + --hash=sha256:e5edd98192f74e4c7cffdd62953b2987e2b1e0d6a55d5c940306bed71f40206a \ + --hash=sha256:f613dfd05fd62a8b7b57649bfa5db1501be41e18b5e15dd4a2fc12d3e3ddfdaa \ + --hash=sha256:f63a1d8f95811569df5df9b6b11674038929c2f696221f2a393aee5ac1e535b4 \ + --hash=sha256:fb3efbe8efd26203589794988b11ea9bf3dea2d3bcf218e658f779d526dfcf80 \ + --hash=sha256:fba5c46f84031f1186bdea2a0c95f82958f8c29321200e73d7ac5e79ee460c83 \ + --hash=sha256:fea4410ce02e295079db5b2617579ba016671d334ac1888a1d4b34aedb56b866 + # via willow polib==1.2.0 \ --hash=sha256:1c77ee1b81feb31df9bca258cbc58db1bbb32d10214b173882452c73af06d62d \ --hash=sha256:f3ef94aefed6e183e342a8a269ae1fc4742ba193186ad76f175938621dbfc26b # via - # -r requirements.txt # django-translation-manager # wagtail-localize -psycopg2==2.9.9 \ - --hash=sha256:121081ea2e76729acfb0673ff33755e8703d45e926e416cb59bae3a86c6a4981 \ - --hash=sha256:38a8dcc6856f569068b47de286b472b7c473ac7977243593a288ebce0dc89516 \ - --hash=sha256:426f9f29bde126913a20a96ff8ce7d73fd8a216cfb323b1f04da402d452853c3 \ - --hash=sha256:5e0d98cade4f0e0304d7d6f25bbfbc5bd186e07b38eac65379309c4ca3193efa \ - --hash=sha256:7e2dacf8b009a1c1e843b5213a87f7c544b2b042476ed7755be813eaf4e8347a \ - --hash=sha256:a7653d00b732afb6fc597e29c50ad28087dcb4fbfb28e86092277a559ae4e693 \ - --hash=sha256:ade01303ccf7ae12c356a5e10911c9e1c51136003a9a1d92f7aa9d010fb98372 \ - --hash=sha256:bac58c024c9922c23550af2a581998624d6e02350f4ae9c5f0bc642c633a2d5e \ - --hash=sha256:c92811b2d4c9b6ea0285942b2e7cac98a59e166d59c588fe5cfe1eda58e72d59 \ - --hash=sha256:d1454bde93fb1e224166811694d600e746430c006fbb031ea06ecc2ea41bf156 \ - --hash=sha256:d735786acc7dd25815e89cc4ad529a43af779db2e25aa7c626de864127e5a024 \ - --hash=sha256:de80739447af31525feddeb8effd640782cf5998e1a4e9192ebdf829717e3913 \ - --hash=sha256:ff432630e510709564c01dafdbe996cb552e0b9f3f065eb89bdce5bd31fabf4c - # via -r requirements.txt +psycopg2-binary==2.9.10 \ + --hash=sha256:04392983d0bb89a8717772a193cfaac58871321e3ec69514e1c4e0d4957b5aff \ + --hash=sha256:056470c3dc57904bbf63d6f534988bafc4e970ffd50f6271fc4ee7daad9498a5 \ + --hash=sha256:0ea8e3d0ae83564f2fc554955d327fa081d065c8ca5cc6d2abb643e2c9c1200f \ + --hash=sha256:155e69561d54d02b3c3209545fb08938e27889ff5a10c19de8d23eb5a41be8a5 \ + --hash=sha256:18c5ee682b9c6dd3696dad6e54cc7ff3a1a9020df6a5c0f861ef8bfd338c3ca0 \ + --hash=sha256:19721ac03892001ee8fdd11507e6a2e01f4e37014def96379411ca99d78aeb2c \ + --hash=sha256:1a6784f0ce3fec4edc64e985865c17778514325074adf5ad8f80636cd029ef7c \ + --hash=sha256:2286791ececda3a723d1910441c793be44625d86d1a4e79942751197f4d30341 \ + --hash=sha256:230eeae2d71594103cd5b93fd29d1ace6420d0b86f4778739cb1a5a32f607d1f \ + --hash=sha256:245159e7ab20a71d989da00f280ca57da7641fa2cdcf71749c193cea540a74f7 \ + --hash=sha256:26540d4a9a4e2b096f1ff9cce51253d0504dca5a85872c7f7be23be5a53eb18d \ + --hash=sha256:270934a475a0e4b6925b5f804e3809dd5f90f8613621d062848dd82f9cd62007 \ + --hash=sha256:27422aa5f11fbcd9b18da48373eb67081243662f9b46e6fd07c3eb46e4535142 \ + --hash=sha256:2ad26b467a405c798aaa1458ba09d7e2b6e5f96b1ce0ac15d82fd9f95dc38a92 \ + --hash=sha256:2b3d2491d4d78b6b14f76881905c7a8a8abcf974aad4a8a0b065273a0ed7a2cb \ + --hash=sha256:2ce3e21dc3437b1d960521eca599d57408a695a0d3c26797ea0f72e834c7ffe5 \ + --hash=sha256:30e34c4e97964805f715206c7b789d54a78b70f3ff19fbe590104b71c45600e5 \ + --hash=sha256:3216ccf953b3f267691c90c6fe742e45d890d8272326b4a8b20850a03d05b7b8 \ + --hash=sha256:32581b3020c72d7a421009ee1c6bf4a131ef5f0a968fab2e2de0c9d2bb4577f1 \ + --hash=sha256:35958ec9e46432d9076286dda67942ed6d968b9c3a6a2fd62b48939d1d78bf68 \ + --hash=sha256:3abb691ff9e57d4a93355f60d4f4c1dd2d68326c968e7db17ea96df3c023ef73 \ + --hash=sha256:3c18f74eb4386bf35e92ab2354a12c17e5eb4d9798e4c0ad3a00783eae7cd9f1 \ + --hash=sha256:3c4745a90b78e51d9ba06e2088a2fe0c693ae19cc8cb051ccda44e8df8a6eb53 \ + --hash=sha256:3c4ded1a24b20021ebe677b7b08ad10bf09aac197d6943bfe6fec70ac4e4690d \ + --hash=sha256:3e9c76f0ac6f92ecfc79516a8034a544926430f7b080ec5a0537bca389ee0906 \ + --hash=sha256:48b338f08d93e7be4ab2b5f1dbe69dc5e9ef07170fe1f86514422076d9c010d0 \ + --hash=sha256:4b3df0e6990aa98acda57d983942eff13d824135fe2250e6522edaa782a06de2 \ + --hash=sha256:512d29bb12608891e349af6a0cccedce51677725a921c07dba6342beaf576f9a \ + --hash=sha256:5a507320c58903967ef7384355a4da7ff3f28132d679aeb23572753cbf2ec10b \ + --hash=sha256:5c370b1e4975df846b0277b4deba86419ca77dbc25047f535b0bb03d1a544d44 \ + --hash=sha256:6b269105e59ac96aba877c1707c600ae55711d9dcd3fc4b5012e4af68e30c648 \ + --hash=sha256:6d4fa1079cab9018f4d0bd2db307beaa612b0d13ba73b5c6304b9fe2fb441ff7 \ + --hash=sha256:6dc08420625b5a20b53551c50deae6e231e6371194fa0651dbe0fb206452ae1f \ + --hash=sha256:73aa0e31fa4bb82578f3a6c74a73c273367727de397a7a0f07bd83cbea696baa \ + --hash=sha256:7559bce4b505762d737172556a4e6ea8a9998ecac1e39b5233465093e8cee697 \ + --hash=sha256:79625966e176dc97ddabc142351e0409e28acf4660b88d1cf6adb876d20c490d \ + --hash=sha256:7a813c8bdbaaaab1f078014b9b0b13f5de757e2b5d9be6403639b298a04d218b \ + --hash=sha256:7b2c956c028ea5de47ff3a8d6b3cc3330ab45cf0b7c3da35a2d6ff8420896526 \ + --hash=sha256:7f4152f8f76d2023aac16285576a9ecd2b11a9895373a1f10fd9db54b3ff06b4 \ + --hash=sha256:7f5d859928e635fa3ce3477704acee0f667b3a3d3e4bb109f2b18d4005f38287 \ + --hash=sha256:851485a42dbb0bdc1edcdabdb8557c09c9655dfa2ca0460ff210522e073e319e \ + --hash=sha256:8608c078134f0b3cbd9f89b34bd60a943b23fd33cc5f065e8d5f840061bd0673 \ + --hash=sha256:880845dfe1f85d9d5f7c412efea7a08946a46894537e4e5d091732eb1d34d9a0 \ + --hash=sha256:8aabf1c1a04584c168984ac678a668094d831f152859d06e055288fa515e4d30 \ + --hash=sha256:8aecc5e80c63f7459a1a2ab2c64df952051df196294d9f739933a9f6687e86b3 \ + --hash=sha256:8cd9b4f2cfab88ed4a9106192de509464b75a906462fb846b936eabe45c2063e \ + --hash=sha256:8de718c0e1c4b982a54b41779667242bc630b2197948405b7bd8ce16bcecac92 \ + --hash=sha256:9440fa522a79356aaa482aa4ba500b65f28e5d0e63b801abf6aa152a29bd842a \ + --hash=sha256:b5f86c56eeb91dc3135b3fd8a95dc7ae14c538a2f3ad77a19645cf55bab1799c \ + --hash=sha256:b73d6d7f0ccdad7bc43e6d34273f70d587ef62f824d7261c4ae9b8b1b6af90e8 \ + --hash=sha256:bb89f0a835bcfc1d42ccd5f41f04870c1b936d8507c6df12b7737febc40f0909 \ + --hash=sha256:c3cc28a6fd5a4a26224007712e79b81dbaee2ffb90ff406256158ec4d7b52b47 \ + --hash=sha256:ce5ab4bf46a211a8e924d307c1b1fcda82368586a19d0a24f8ae166f5c784864 \ + --hash=sha256:d00924255d7fc916ef66e4bf22f354a940c67179ad3fd7067d7a0a9c84d2fbfc \ + --hash=sha256:d7cd730dfa7c36dbe8724426bf5612798734bff2d3c3857f36f2733f5bfc7c00 \ + --hash=sha256:e217ce4d37667df0bc1c397fdcd8de5e81018ef305aed9415c3b093faaeb10fb \ + --hash=sha256:e3923c1d9870c49a2d44f795df0c889a22380d36ef92440ff618ec315757e539 \ + --hash=sha256:e5720a5d25e3b99cd0dc5c8a440570469ff82659bb09431c1439b92caf184d3b \ + --hash=sha256:e8b58f0a96e7a1e341fc894f62c1177a7c83febebb5ff9123b579418fdc8a481 \ + --hash=sha256:e984839e75e0b60cfe75e351db53d6db750b00de45644c5d1f7ee5d1f34a1ce5 \ + --hash=sha256:eb09aa7f9cecb45027683bb55aebaaf45a0df8bf6de68801a6afdc7947bb09d4 \ + --hash=sha256:ec8a77f521a17506a24a5f626cb2aee7850f9b69a0afe704586f63a464f3cd64 \ + --hash=sha256:ecced182e935529727401b24d76634a357c71c9275b356efafd8a2a91ec07392 \ + --hash=sha256:ee0e8c683a7ff25d23b55b11161c2663d4b099770f6085ff0a20d4505778d6b4 \ + --hash=sha256:f0c2d907a1e102526dd2986df638343388b94c33860ff3bbe1384130828714b1 \ + --hash=sha256:f758ed67cab30b9a8d2833609513ce4d3bd027641673d4ebc9c067e4d208eec1 \ + --hash=sha256:f8157bed2f51db683f31306aa497311b560f2265998122abe1dce6428bd86567 \ + --hash=sha256:ffe8ed017e4ed70f68b7b371d84b7d4a790368db9203dfc2d222febd3a9c8863 + # via -r requirements.in py-vapid==1.9.1 \ --hash=sha256:fe2b5461bf45c7baff1039df6981f03b87faa87cde0482addfa35b3fe636ac1b - # via - # -r requirements.txt - # pywebpush + # via pywebpush pycparser==2.22 \ --hash=sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6 \ --hash=sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc - # via - # -r requirements.txt - # cffi + # via cffi pyjwt[crypto]==2.8.0 \ --hash=sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de \ --hash=sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320 # via - # -r requirements.txt + # -r requirements.in # django-allauth # djangorestframework-simplejwt -pysocks==1.7.1 \ - --hash=sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299 \ - --hash=sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5 \ - --hash=sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0 - # via urllib3 -pytest==8.2.2 \ - --hash=sha256:c434598117762e2bd304e526244f67bf66bbd7b5d6cf22138be51ff661980343 \ - --hash=sha256:de4bb8104e201939ccdc688b27a89a7be2079b22e2bd2b07f806b6ba71117977 - # via - # -r requirements.dev.in - # pytest-django -pytest-django==4.8.0 \ - --hash=sha256:5d054fe011c56f3b10f978f41a8efb2e5adfc7e680ef36fb571ada1f24779d90 \ - --hash=sha256:ca1ddd1e0e4c227cf9e3e40a6afc6d106b3e70868fd2ac5798a22501271cd0c7 - # via -r requirements.dev.in -python-dateutil==2.9.0.post0 \ - --hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \ - --hash=sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427 - # via faker python3-openid==3.2.0 \ --hash=sha256:33fbf6928f401e0b790151ed2b5290b02545e8775f982485205a066f874aaeaf \ --hash=sha256:6626f771e0417486701e0b4daff762e7212e820ca5b29fcc0d05f6f8736dfa6b - # via - # -r requirements.txt - # django-allauth + # via django-allauth pytz==2024.1 \ --hash=sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812 \ --hash=sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319 # via - # -r requirements.txt - # django # django-comments-xtd # django-modelcluster - # djangorestframework # drf-yasg - # l18n pywebpush==1.9.4 \ --hash=sha256:e3ded57c9715159f64a5624a656791ee9228b9e076ea0208baa73b53be8c130f - # via - # -r requirements.txt - # django-webpush + # via django-webpush pyyaml==6.0.1 \ --hash=sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5 \ --hash=sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc \ @@ -875,19 +808,15 @@ pyyaml==6.0.1 \ --hash=sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585 \ --hash=sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d \ --hash=sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f - # via - # -r requirements.txt - # drf-yasg + # via drf-yasg rcssmin==1.0.6 \ --hash=sha256:ca87b695d3d7864157773a61263e5abb96006e9ff0e021eff90cbe0e1ba18270 - # via - # -r requirements.txt - # django-compressor + # via django-compressor redis==3.5.3 \ --hash=sha256:0e7e0cfca8660dea8b7d5cd8c4f6c5e29e11f31158c0b0ae91a397f00e5a05a2 \ --hash=sha256:432b788c4530cfe16d8d943a09d40ca6c16149727e4afe8c2c9d5580c59d9f24 # via - # -r requirements.txt + # -r requirements.in # django-redis # django-rq # rq @@ -895,7 +824,6 @@ requests==2.32.3 \ --hash=sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760 \ --hash=sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6 # via - # -r requirements.txt # django-allauth # django-translation-manager # pywebpush @@ -905,9 +833,7 @@ requests==2.32.3 \ requests-oauthlib==2.0.0 \ --hash=sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36 \ --hash=sha256:b3dffaebd884d8cd778494369603a9e7b58d29111bf6b41bdc2dcd87203af4e9 - # via - # -r requirements.txt - # django-allauth + # via django-allauth rjsmin==1.1.0 \ --hash=sha256:0ab825839125eaca57cc59581d72e596e58a7a56fbc0839996b7528f0343a0a8 \ --hash=sha256:211c2fe8298951663bbc02acdffbf714f6793df54bfc50e1c6c9e71b3f2559a3 \ @@ -922,214 +848,116 @@ rjsmin==1.1.0 \ --hash=sha256:e3908b21ebb584ce74a6ac233bdb5f29485752c9d3be5e50c5484ed74169232c \ --hash=sha256:e487a7783ac4339e79ec610b98228eb9ac72178973e3dee16eba0e3feef25924 \ --hash=sha256:ecd29f1b3e66a4c0753105baec262b331bcbceefc22fbe6f7e8bcd2067bcb4d7 - # via - # -r requirements.txt - # django-compressor + # via django-compressor rq==1.16.2 \ --hash=sha256:52e619f6cb469b00e04da74305045d244b75fecb2ecaa4f26422add57d3c5f09 \ --hash=sha256:5c5b9ad5fbaf792b8fada25cc7627f4d206a9a4455aced371d4f501cc3f13b34 - # via - # -r requirements.txt - # django-rq -selenium==4.9.1 \ - --hash=sha256:3444f4376321530c36ce8355b6b357d8cf4a7d588ce5cf772183465930bbed0e \ - --hash=sha256:82aedaa85d55bc861f4c89ff9609e82f6c958e2e1e3da3ffcc36703f21d3ee16 - # via -r requirements.dev.in + # via django-rq six==1.16.0 \ --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 # via - # -r requirements.txt # bleach # django-comments-xtd # django-compressor - # html5lib - # l18n # libsass - # python-dateutil -sniffio==1.3.1 \ - --hash=sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2 \ - --hash=sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc - # via trio -sortedcontainers==2.4.0 \ - --hash=sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88 \ - --hash=sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0 - # via trio soupsieve==2.5 \ --hash=sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690 \ --hash=sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7 - # via - # -r requirements.txt - # beautifulsoup4 + # via beautifulsoup4 sqlparse==0.5.0 \ --hash=sha256:714d0a4932c059d16189f58ef5411ec2287a4360f17cdd0edd2d09d4c5087c93 \ --hash=sha256:c204494cd97479d0e39f28c93d46c0b2d5959c7b9ab904762ea6c7af211c8663 - # via - # -r requirements.txt - # django - # django-debug-toolbar -tablib[xls,xlsx]==3.6.1 \ - --hash=sha256:040685fde11e9237675f43e985edb94b63250a5e9236f89d561ce6fb1465b839 \ - --hash=sha256:c771d38ed1d74350a69873db43e0afb7f1cca0ed2915a7243094463eb6789207 - # via - # -r requirements.txt - # wagtail + # via django telepath==0.3.1 \ --hash=sha256:925c0609e0a8a6488ec4a55b19d485882cf72223b2b19fe2359a50fddd813c9c \ --hash=sha256:c280aa8e77ad71ce80e96500a4e4d4a32f35b7e0b52e896bb5fde9a5bcf0699a - # via - # -r requirements.txt - # wagtail + # via wagtail tinycss2==1.3.0 \ --hash=sha256:152f9acabd296a8375fbca5b84c961ff95971fcfc32e79550c8df8e29118c54d \ --hash=sha256:54a8dbdffb334d536851be0226030e9505965bb2f30f21a4a82c55fb2a80fae7 # via - # -r requirements.txt # cairosvg # cssselect2 tqdm==4.66.4 \ --hash=sha256:b75ca56b413b030bc3f00af51fd2c1a1a5eac6a0c1cca83cbb37a5c52abce644 \ --hash=sha256:e4d936c9de8727928f3be6079590e97d9abfe8d39a590be678eb5919ffc186bb - # via -r requirements.txt -trio==0.26.0 \ - --hash=sha256:67c5ec3265dd4abc7b1d1ab9ca4fe4c25b896f9c93dac73713778adab487f9c4 \ - --hash=sha256:bb9c1b259591af941fccfbabbdc65bc7ed764bd2db76428454c894cd5e3d2032 - # via - # selenium - # trio-websocket -trio-websocket==0.11.1 \ - --hash=sha256:18c11793647703c158b1f6e62de638acada927344d534e3c7628eedcb746839f \ - --hash=sha256:520d046b0d030cf970b8b2b2e00c4c2245b3807853ecd44214acd33d74581638 - # via selenium + # via -r requirements.in typing-extensions==4.12.2 \ --hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \ --hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8 # via - # -r requirements.txt + # django-stubs-ext + # django-tasks # wagtail-localize uritemplate==4.1.1 \ --hash=sha256:4346edfc5c3b79f694bccd6d6099a322bbeb628dbf2cd86eea55a456ce5124f0 \ --hash=sha256:830c08b8d99bdd312ea4ead05994a38e8936266f84b9a7878232db50b044e02e - # via - # -r requirements.txt - # drf-yasg -urllib3[socks]==1.26.19 \ + # via drf-yasg +urllib3==1.26.19 \ --hash=sha256:37a0344459b199fce0e80b0d3569837ec6b6937435c5244e7fd73fa6006830f3 \ --hash=sha256:3e3d753a8618b86d7de333b4223005f68720bcd6a7d2bcb9fbd2229ec7c1e429 # via - # -r requirements.txt # elasticsearch # requests - # selenium -wagtail==3.0.3 \ - --hash=sha256:111ed9a0a6ff26d5d881d52deb4bf52b627d79a53c43829611752dbb68a9192f \ - --hash=sha256:23b3e541401355ea183372582050ea52b049c956dd5b506197f957bb68423ab3 +wagtail==7.0.1 \ + --hash=sha256:92439c50a919826a4ce8c85bdaf3ed0e436d29598bb2954b4fca5f312b969666 \ + --hash=sha256:cfc5c37738f98cae380a15252f5676604f6c61554bef1a3791e34de1e703beec # via - # -r requirements.txt + # -r requirements.in # wagtail-cache - # wagtail-factories # wagtail-localize # wagtail-markdown + # wagtail-modeladmin # wagtailmedia -wagtail-cache==2.1.1 \ - --hash=sha256:1fe3ca20a3cdf23f31fc9df662a52f743084cd7f60bd870950094d63a87f695a \ - --hash=sha256:2ac16921d022a58240a009a19220554e41963c5172e7dfe4ef741ddd887e991f - # via -r requirements.txt -wagtail-factories==4.0.0 \ - --hash=sha256:3e39ec1cc13b61c6e467f1bf223ce2d134e823fa9fe4dc7e32d0222cc8d350ec \ - --hash=sha256:f59f9af283da79b3ddab7b2ca95d6a14b5bbbb929a697563e4f7143948693f53 - # via -r requirements.dev.in +wagtail-cache==3.0.0 \ + --hash=sha256:2bbb8d1bc5c4c9d7755113c0c8b91b3ec8a0c90bd560ef62aab99698961114fa \ + --hash=sha256:a12b9f7dbd41b560b7fa77be08a6c7ab292536e37296dc910275b99c198ddd1e + # via -r requirements.in wagtail-generic-chooser==0.5.1 \ --hash=sha256:135f8cc413d83b82bb8956f625f4b9572aa7139ab3835e2ba2d7e19f2171b354 \ --hash=sha256:280ae7293641d1b121450e17a6d424305e31c832f1af5bd991bc3e49703bf79e - # via - # -r requirements.txt - # wagtailsvg -wagtail-localize==1.4 \ - --hash=sha256:40f974809509de54dcc18ee6aa98908bffd9dfaba53150e214f4046b2286920e \ - --hash=sha256:fd1195de3c23e3a061576f1b947fe7498676ff5678fe008d4cd388125a20a54a - # via -r requirements.txt -wagtail-markdown==0.10.0 \ - --hash=sha256:b16be4b6e3518cc6dd15ab335cbc6d6a9122b5d7e3a61fa11c83597e2660044e \ - --hash=sha256:e4a97eee0211eebaab9c850669e647bc1c8ceb70df38b4db5a2c3d8b02ebaf69 - # via -r requirements.txt + # via wagtailsvg +wagtail-localize==1.12.2 \ + --hash=sha256:42d4a3b6eafac30c87740f8d914da3f9587ec57f934872bde93a42edce449e8e \ + --hash=sha256:a2006793571ae35d3118f091f25c5072eb501a30911b17d98fad028162b63902 + # via -r requirements.in +wagtail-markdown==0.12.1 \ + --hash=sha256:54f1ba375348e86e03f4eca7d2ac3d33245ead9f854028d7ee9c479448f1e678 \ + --hash=sha256:bb5f02b6bdfef74b50a74e7aa3f255c7bc9787cec8d03dae50fc9404a0097dba + # via -r requirements.in +wagtail-modeladmin==2.2.0 \ + --hash=sha256:41e12f9a79f8c1595fce73bd6b51007422f258089564f9df8e09a82246a8e133 \ + --hash=sha256:60ea08b128761b5b6a1cbfe3c8ab828fba13e41ff3d7563a0b8c62c8fe36c4ce + # via -r requirements.in wagtail-transfer @ https://github.com/IDEMSInternational/wagtail-transfer/archive/52b57b364ebc9acddd412ee708f829b45763c9ab.zip \ --hash=sha256:049c23e1406564d3b7e8c385e72051f34e707add4f8109d874da670711709548 - # via -r requirements.txt + # via -r requirements.in wagtailmedia==0.12.0 \ --hash=sha256:0807515c5d89782666b613de2e4aedab19e9dd358097fad2cb79633c0b5416d3 \ --hash=sha256:1d39622c3d7d0191e58ffedf45d05fbef851e3905955513012a72ae4d46a12b0 - # via -r requirements.txt + # via -r requirements.in wagtailmenus==3.1.3 \ --hash=sha256:0f5669f160d788b1ab8c2b412cb95411e9c07f83e4b52dddc92991752c6fa397 - # via -r requirements.txt + # via -r requirements.in wagtailsvg==0.0.37 \ --hash=sha256:4b30433809614fbac09f9088b4aed42a1bfe56f9fb581b858606187cb177ca6b \ --hash=sha256:dc4d698748bde32034b1eac2275cf159597ca8e399d3830e96391f761aa0cacf - # via -r requirements.txt + # via -r requirements.in webencodings==0.5.1 \ --hash=sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78 \ --hash=sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923 # via - # -r requirements.txt # bleach # cssselect2 - # html5lib # tinycss2 whitenoise==5.2.0 \ --hash=sha256:05ce0be39ad85740a78750c86a93485c40f08ad8c62a6006de0233765996e5c7 \ --hash=sha256:05d00198c777028d72d8b0bbd234db605ef6d60e9410125124002518a48e515d - # via -r requirements.txt -willow==1.4.1 \ - --hash=sha256:0df8ff528531e00b48d40bf72ed81beac1dc82f2d42e5bbed4aff0218bef8c0d \ - --hash=sha256:fc4042696d090e75aef922fa1ed26d483c764f005b36cf523cf7c34e69d5dd7a + # via -r requirements.in +willow[heif]==1.10.0 \ + --hash=sha256:26861dbacc9584f5d4566de7d31c092437225abc4b1978fa9ac44a433200f938 \ + --hash=sha256:e10673ff954e79ca0412c648e40dd9ce0b93c8bef798e8468ce3411ff972fb15 # via - # -r requirements.txt # wagtail -wsproto==1.2.0 \ - --hash=sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065 \ - --hash=sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736 - # via trio-websocket -xlrd==2.0.1 \ - --hash=sha256:6a33ee89877bd9abc1158129f6e94be74e2679636b8a205b43b85206c3f0bbdd \ - --hash=sha256:f72f148f54442c6b056bf931dbc34f986fd0c3b0b6b5a58d013c9aef274d0c88 - # via - # -r requirements.txt - # tablib -xlsxwriter==3.2.0 \ - --hash=sha256:9977d0c661a72866a61f9f7a809e25ebbb0fb7036baa3b9fe74afcfca6b3cb8c \ - --hash=sha256:ecfd5405b3e0e228219bcaf24c2ca0915e012ca9464a14048021d21a995d490e - # via - # -r requirements.txt - # wagtail -xlwt==1.3.0 \ - --hash=sha256:a082260524678ba48a297d922cc385f58278b8aa68741596a87de01a9c628b2e \ - --hash=sha256:c59912717a9b28f1a3c2a98fd60741014b06b043936dcecbc113eaaada156c88 - # via - # -r requirements.txt - # tablib -msal==1.31.0 \ - --hash=sha256:96bc37cff82ebe4b160d5fc0f1196f6ca8b50e274ecd0ec5bf69c438514086e7 - # via - # -r requirements.txt - # msal -django-anymail==10.3 \ - --hash=sha256:35d8ec20b06000af3c1638492e32f416fd1a584f0a572cded03f1bc570169ed0 - # via - # -r requirements.txt - # django-anymail -pandas==2.2.3 \ - --hash=sha256:c124333816c3a9b03fbeef3a9f230ba9a737e9e5bb4060aa2107a86cc0a497fc - # via - # -r requirements.txt - # pandas -numpy==1.23.2 \ - --hash=sha256:ac987b35df8c2a2eab495ee206658117e9ce867acf3ccb376a19e83070e69418 - # via - # -r requirements.txt - # numpy -tzdata==2025.1 \ - --hash=sha256:7e127113816800496f027041c570f50bcd464a020098a3b6b199517772303639 - # via - # -r requirements.txt - # numpy + # willow diff --git a/requirements.in b/requirements.in index 92c7a8628..a75c41c88 100644 --- a/requirements.in +++ b/requirements.in @@ -1,33 +1,35 @@ -beautifulsoup4~=4.9.3 -cairosvg~=2.7.0 -django-allauth~=0.54.0 -django-comments-xtd~=2.9.13 -django-compressor==2.4.* -django-extensions==3.1.* -django-filter==2.4.0 -django-health-check==3.16.5 -django-redis~=5.2.0 -django-sass-processor==1.0.* -django-translation-manager~=1.3.0 -django-webpush==0.3.4 -django~=3.2.24 -djangorestframework-simplejwt~=5.3.1 -djangorestframework~=3.13.1 -drf-yasg~=1.21.3 -elasticsearch~=7.16 -libsass==0.21.* -lxml~=4.9 -psycopg2~=2.9.9 -pyjwt~=2.8.0 -redis~=3.0 -tqdm~=4.66 -wagtail-cache~=2.1.1 -wagtail-localize~=1.4.0 -wagtail-markdown~=0.10.0 -wagtail~=3.0.3 -wagtailmedia~=0.12.0 -wagtailmenus==3.1.3 -wagtailsvg==0.0.37 +beautifulsoup4 +cairosvg +django-allauth~=0.59.0 +django-compressor +django-contrib-comments +django-comments-xtd==2.10.7 +django-extensions +django-filter~=25.1 +django-health-check +django-redis +django-sass-processor +django-translation-manager +django-webpush +django~=5.2.4 +djangorestframework-simplejwt +djangorestframework>=3.12,<3.16 +drf-yasg +elasticsearch +libsass +lxml +psycopg2-binary +pyjwt +redis +tqdm +wagtail-markdown==0.12.1 +wagtail-modeladmin +wagtail-localize +wagtail~=7.0 +wagtail-cache==3.0.0 +wagtailmedia +wagtailmenus +git+https://github.com/jmrichardson/wagtail-svg.git@main#egg=wagtailsvg # branch: iogt, tag: v0.8.5-iogt.1 wagtail-transfer @ https://github.com/IDEMSInternational/wagtail-transfer/archive/52b57b364ebc9acddd412ee708f829b45763c9ab.zip -whitenoise==5.2.* +whitenoise diff --git a/requirements.txt b/requirements.txt index d48e89719..7d65b0db2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -237,9 +237,10 @@ defusedxml==0.7.1 \ # via # cairosvg # python3-openid -django==3.2.25 \ - --hash=sha256:7ca38a78654aee72378594d63e51636c04b8e28574f5505dff630895b5472777 \ - --hash=sha256:a52ea7fcf280b16f7b739cec38fa6d3f8953a5456986944c3ca97e79882b4e38 + # willow +django==5.2.4 \ + --hash=sha256:60c35bd96201b10c6e7a78121bd0da51084733efa303cc19ead021ab179cef5e \ + --hash=sha256:a1228c384f8fa13eebc015196db7b3e08722c5058d4758d20cb287503a540d8f # via # -r requirements.in # django-allauth @@ -253,17 +254,20 @@ django==3.2.25 \ # django-permissionedforms # django-redis # django-rq + # django-stubs-ext # django-taggit + # django-tasks # django-translation-manager # django-treebeard # djangorestframework # djangorestframework-simplejwt # drf-yasg + # laces # wagtail # wagtail-localize # wagtailmedia -django-allauth==0.54.0 \ - --hash=sha256:120e265f802b65738899c6cb627b827fde46a4d03067034c633f516c2adf3e3e +django-allauth==0.59.0 \ + --hash=sha256:ec19efb80b34d2f18bd831eab9b10b6301f58d1cce9f39af35f497b7e5b0a141 # via -r requirements.in django-appconf==1.0.6 \ --hash=sha256:c3ae442fba1ff7ec830412c5184b17169a7a1e71cf0864a4c3f93cf4c98a1993 \ @@ -273,9 +277,9 @@ django-cogwheels==0.3 \ --hash=sha256:197bd05e7114403d7301214b3f8a371c4fb6039cf21c811f099438b167b5ed21 \ --hash=sha256:848a4d9f2c96c582a4a4f2e7c276dfd95ab3905748cae13bb7c4b365a6717e94 # via wagtailmenus -django-comments-xtd==2.9.13 \ - --hash=sha256:0d91e3cc76eae6f30e83b12fb09708e5407664d9daa7b9c1101d7377897f7b42 \ - --hash=sha256:b289b6754d6618fb29e4279c6a1c6a270bc9495e161c42193d8b6216a4884802 +django-comments-xtd==2.10.7 \ + --hash=sha256:0e3b833a881bc916a6bd77902a6ff944586073f3bdf020c153aba18a1efb65db \ + --hash=sha256:58f69ada5aa26fbb4d674937493026fc813248432d555902dfd776dab22627f5 # via -r requirements.in django-compressor==2.4.1 \ --hash=sha256:3358077605c146fdcca5f9eaffb50aa5dbe15f238f8854679115ebf31c0415e0 \ @@ -284,14 +288,16 @@ django-compressor==2.4.1 \ django-contrib-comments==2.2.0 \ --hash=sha256:2ca79060bbc8fc5b636981ef6e50f35ab83649af75fc1be47bf770636be3271c \ --hash=sha256:48de00f15677e016a216aeff205d6e00e4391c9a5702136c64119c472b7356da - # via django-comments-xtd + # via + # -r requirements.in + # django-comments-xtd django-extensions==3.1.5 \ --hash=sha256:28e1e1bf49f0e00307ba574d645b0af3564c981a6dfc87209d48cb98f77d0b1a \ --hash=sha256:9238b9e016bb0009d621e05cf56ea8ce5cce9b32e91ad2026996a7377ca28069 # via -r requirements.in -django-filter==2.4.0 \ - --hash=sha256:84e9d5bb93f237e451db814ed422a3a625751cbc9968b484ecc74964a8696b06 \ - --hash=sha256:e00d32cebdb3d54273c48f4f878f898dced8d5dfaad009438fe61ebdf535ace1 +django-filter==25.1 \ + --hash=sha256:1ec9eef48fa8da1c0ac9b411744b16c3f4c31176c867886e4c48da369c407153 \ + --hash=sha256:4fa48677cf5857b9b1347fed23e355ea792464e0fe07244d1fdfb8a806215b80 # via # -r requirements.in # wagtail @@ -319,9 +325,17 @@ django-sass-processor==1.0.1 \ --hash=sha256:1f043180c47754018e803a77da003377f5ea6558de57cd6946eb27a32e9c16a2 \ --hash=sha256:dcaad47c591a2d52689c1bd209259e922e902d886293f0d5c9e0d1a4eb85eda2 # via -r requirements.in -django-taggit==2.1.0 \ - --hash=sha256:61547a23fc99967c9304107414a09e662b459f4163dbbae32e60b8ba40c34d05 \ - --hash=sha256:a9f41e4ad58efe4b28d86f274728ee87eb98eeae90c9eb4b4efad39e5068184e +django-stubs-ext==5.2.1 \ + --hash=sha256:98fb0646f1a1ef07708eec5f6f7d27523f12c0c8714abae8db981571ff957588 \ + --hash=sha256:fc0582cb3289306c43ce4a0a15af86922ce1dbec3c19eab80980ee70c04e0392 + # via django-tasks +django-taggit==6.1.0 \ + --hash=sha256:ab776264bbc76cb3d7e49e1bf9054962457831bd21c3a42db9138b41956e4cf0 \ + --hash=sha256:c4d1199e6df34125dd36db5eb0efe545b254dec3980ce5dd80e6bab3e78757c3 + # via wagtail +django-tasks==0.7.0 \ + --hash=sha256:499f80d1a051566443cfa88a300d8b03435af7fc5708cad4d8da6d285614f739 \ + --hash=sha256:8a8d64f2dc6e29ac2f45092d90e2dd82dc1dca100dfe3a4f2ce1209db99f3527 # via wagtail django-translation-manager==1.3.0 \ --hash=sha256:1e3143f48f9ba4d5452d72f55195142c434ea63786546251ae694508df4eb7b1 \ @@ -336,9 +350,9 @@ django-webpush==0.3.4 \ --hash=sha256:a123102dede1a959f667e075ed746ac5b7d4a8622320162eba41a507a835e1e4 \ --hash=sha256:a2613784e822e2dde27086fb20b6d1a2b76e4d5dc8271607aecd45c98a3b7954 # via -r requirements.in -djangorestframework==3.13.1 \ - --hash=sha256:0c33407ce23acc68eca2a6e46424b008c9c02eceb8cf18581921d0092bc1f2ee \ - --hash=sha256:24c4bf58ed7e85d1fe4ba250ab2da926d263cd57d64b03e8dcef0ac683f8b1aa +djangorestframework==3.15.2 \ + --hash=sha256:2b8871b062ba1aefc2de01f773875441a961fefbf79f5eed1e32b2f096944b20 \ + --hash=sha256:36fe88cd2d6c6bec23dca9804bab2ba5517a8bb9d8f47ebc68981b56840107ad # via # -r requirements.in # django-comments-xtd @@ -370,10 +384,10 @@ et-xmlfile==1.1.0 \ --hash=sha256:8eb9e2bc2f8c97e37a2dc85a09ecdcdec9d8a396530a6d5a33b30b9a92da0c5c \ --hash=sha256:a2ba85d1d6a74ef63837eed693bcb89c3f752169b0e3e7ae5b16ca5e1b3deada # via openpyxl -html5lib==1.1 \ - --hash=sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d \ - --hash=sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f - # via wagtail +filetype==1.2.0 \ + --hash=sha256:66b56cd6474bf41d8c54660347d37afcc3f7d1970648de365c102ef77548aadb \ + --hash=sha256:7ce71b6880181241cf7ac8697a2f1eb6a8bd9b429f7ad6d27b8db9ba5f1c2d25 + # via willow http-ece==1.2.0 \ --hash=sha256:b5920f8efb8e1b5fb025713e3b36fda54336262010634b26dc1f98f85d1eb3de # via pywebpush @@ -385,9 +399,9 @@ inflection==0.5.1 \ --hash=sha256:1a29730d366e996aaacffb2f1f1cb9593dc38e2ddd30c91250c6dde09ea9b417 \ --hash=sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2 # via drf-yasg -l18n==2021.3 \ - --hash=sha256:1956e890d673d17135cc20913253c154f6bc1c00266c22b7d503cc1a5a42d848 \ - --hash=sha256:78495d1df95b6f7dcc694d1ba8994df709c463a1cbac1bf016e1b9a5ce7280b9 +laces==0.1.2 \ + --hash=sha256:3218e09c1889ae5cf3fc7a82f5bb63ec0c7879889b6a9760bfc42323c694b84d \ + --hash=sha256:980cdaf9a31e883a2b8198132e2388931a4eb8814f5bfa5d8bba13ff9f657b7c # via wagtail libsass==0.21.0 \ --hash=sha256:06c8776417fe930714bdc930a3d7e795ae3d72be6ac883ff72a1b8f7c49e5ffb \ @@ -507,7 +521,7 @@ oauthlib==3.2.2 \ openpyxl==3.1.5 \ --hash=sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2 \ --hash=sha256:cf0e3cf56142039133628b5acffe8ef0c12bc902d2aadd3e0fe5878dc08d1050 - # via tablib + # via wagtail packaging==24.1 \ --hash=sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002 \ --hash=sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124 @@ -583,27 +597,136 @@ pillow==9.5.0 \ --hash=sha256:fed1e1cf6a42577953abbe8e6cf2fe2f566daebde7c34724ec8803c4c0cda579 # via # cairosvg + # pillow-heif # wagtail +pillow-heif==0.16.0 \ + --hash=sha256:0075adeb324adb07ddbfbe8a5c79ed12e5d04e60e9a642ff9427e71b5b0adccd \ + --hash=sha256:078bc74fd767625e465b2c107228f9c398b9a128bdf81b3f18812d7c07be660f \ + --hash=sha256:1421d96aebdc9f5773213c8221ce547efb56e37a62da6698312edd4f281efb42 \ + --hash=sha256:17963a73186961fe7792aef01c46e980635f3fcc1836393de39ec9c6776ca51e \ + --hash=sha256:1f4293ecbb81d255d8d887dce4708a58e87c86e53c6f1b1affc4c3105e1bcb8c \ + --hash=sha256:241cf6c510215c6df0ee948dfed06a20c099475250c5c6cac5e7a1ef9e0ec4c3 \ + --hash=sha256:2673048f3cf1498327add70f16e1129be2a09cf4a31cbc02363f5760eb5ba955 \ + --hash=sha256:28c980bf8d5239ee87986c9217a5954b07993d71d391949a9feafad0a9c5e9a7 \ + --hash=sha256:2b7450303f08ec81d1a63a75052863bb687fc3be1fdd8a34d2c0fef627aacae5 \ + --hash=sha256:331579ce4f5fa079595c529b06810886ff76f8ade3eb411a1c9c90853a708022 \ + --hash=sha256:33e0b1549bcdfec363b3ba6fb55b3de882e1409b5b00f5a68a1a027f051e8ef2 \ + --hash=sha256:3501f22985cbb427c76febf07a7e309cb828e485c0cf250a625733fc06fc1815 \ + --hash=sha256:38fa2854ec7dbe6c875d64cc5b3cf5cc55f1c8a0248dc1c7c34e9d2505521b82 \ + --hash=sha256:3a2681d4b62418813289987a9420059d724cd93542d0b05e0928fe4578517714 \ + --hash=sha256:3f062c1be6f04804ffdf0bc452142eff38d7544c8655c04291d16e3b996e4dc4 \ + --hash=sha256:40014105688478d6ca146fc04bff6c13f445d01bdea79417b34ee50c1e559190 \ + --hash=sha256:4b6caa5b13b4dfc180507527254014530f6bedbeabc1de2238918bf5b2700c7e \ + --hash=sha256:4d95004bb77aa640f80617716aa21bc092ec06307f6f2ad423deeeda07b4d29c \ + --hash=sha256:502cebc90c11a6bffa2ea899088999c25fc99c8f322e047a266e541e3046b27c \ + --hash=sha256:5c7f7a94fc2d08ddcf55a6834c4c55b7dea9605656c565ce11c82e3f6e0454a8 \ + --hash=sha256:7794c1a8304eeb841d72cb73aa64cc60c9e5dccb2c7612f8caf528505f78581f \ + --hash=sha256:792e5d88b7d016fe48ae2fd77a852ec8dcf9a7fad1f7f191d35bc173896fe378 \ + --hash=sha256:7e424d6a34b9466d054706393e76b5abdd84fabdc0c72b19ca10435a76140de7 \ + --hash=sha256:7ef47297d526147923f4ecc7ff681a5d5f4e6e3300017681f59968652a0d8afb \ + --hash=sha256:7fabd6534a38078a66ce8b7a5ae8ad37afd9863c930abd3031fb553f1ab4f01a \ + --hash=sha256:88ff22d2b162e7edd9cb9dd98de81455be04c40a99d1d3d3ebe1602b1a21c453 \ + --hash=sha256:89ec30420ddc843c43916febbe31697552ed123396a1696715eea75169866c07 \ + --hash=sha256:8e168d45b2ce63c1fe2334fd02927699b0097de72605f7571948010fd79e58f0 \ + --hash=sha256:8f15dc73ced02a0ccfac93159d12deeaecfbe4335883a1a3309df0f01c26e6e6 \ + --hash=sha256:9273af7224e0fb16c18637184a8ea9a8790105658daab04ad541982b8623e5c1 \ + --hash=sha256:9923dfcc97ae9484d3514f2f6ec368e2ac97cd66f7b95359cc1b0ec0c1cd6157 \ + --hash=sha256:9bf10a1686c2d51f4db8ebb78825f96f28d18d1878599e1c64e88cfbdb70a3d2 \ + --hash=sha256:9fd829c257a763e3a2e8418a773c2808c90799ee3e6b405b5399cb4fdfbe336e \ + --hash=sha256:a146be0c8e7bef204eeaa14799b2fca8a4a52ad972850975e23ef10cee4e7de7 \ + --hash=sha256:a27abb523a07b17c118c09f1a00f92cde2295f8e997600024d4b57df3c5ba818 \ + --hash=sha256:a8856cf5f0d53f83d814ae5c8d34433e5e5ad9f3e328480257cd6e9fbdb4a458 \ + --hash=sha256:b50160331754b603524e6ed33c386f478fd66fb345fa6433a507a01c8de642c6 \ + --hash=sha256:bbd9cc527bbd53c3e7588e16aad170e11cfd180b7e9bd84f18fb020ddec11408 \ + --hash=sha256:be41b7fadd4a9355d24936f6fad83bb8130fe55ba228ec298ad316392bb6f38b \ + --hash=sha256:beb6576cbe5a9404a8f2ad9ec68f6b0c406e5e9f5d5573722dc3244898dc9866 \ + --hash=sha256:c2ad68e3e4be40adfc5290bf6daa1569dd7d18501e17779d217ce5cd8c1e338d \ + --hash=sha256:c7db96ac172e2654676986e8c35fa32bffdd5b429a8c86b9d628c0333c570d82 \ + --hash=sha256:d4595ec975db845d84ab90cbf0678f15b0068b8b83c01d1db7ea524e31bab4b4 \ + --hash=sha256:d9e465d92cf01093e3e4c33776af97368add23ac1c8d0007f34b8d3e3390d6ad \ + --hash=sha256:e0492e4fd6d3334b9eed3651058216ef62f04afa099cfc6b05815c1bf0da2c38 \ + --hash=sha256:e5edd98192f74e4c7cffdd62953b2987e2b1e0d6a55d5c940306bed71f40206a \ + --hash=sha256:f613dfd05fd62a8b7b57649bfa5db1501be41e18b5e15dd4a2fc12d3e3ddfdaa \ + --hash=sha256:f63a1d8f95811569df5df9b6b11674038929c2f696221f2a393aee5ac1e535b4 \ + --hash=sha256:fb3efbe8efd26203589794988b11ea9bf3dea2d3bcf218e658f779d526dfcf80 \ + --hash=sha256:fba5c46f84031f1186bdea2a0c95f82958f8c29321200e73d7ac5e79ee460c83 \ + --hash=sha256:fea4410ce02e295079db5b2617579ba016671d334ac1888a1d4b34aedb56b866 + # via willow polib==1.2.0 \ --hash=sha256:1c77ee1b81feb31df9bca258cbc58db1bbb32d10214b173882452c73af06d62d \ --hash=sha256:f3ef94aefed6e183e342a8a269ae1fc4742ba193186ad76f175938621dbfc26b # via # django-translation-manager # wagtail-localize -psycopg2==2.9.9 \ - --hash=sha256:121081ea2e76729acfb0673ff33755e8703d45e926e416cb59bae3a86c6a4981 \ - --hash=sha256:38a8dcc6856f569068b47de286b472b7c473ac7977243593a288ebce0dc89516 \ - --hash=sha256:426f9f29bde126913a20a96ff8ce7d73fd8a216cfb323b1f04da402d452853c3 \ - --hash=sha256:5e0d98cade4f0e0304d7d6f25bbfbc5bd186e07b38eac65379309c4ca3193efa \ - --hash=sha256:7e2dacf8b009a1c1e843b5213a87f7c544b2b042476ed7755be813eaf4e8347a \ - --hash=sha256:a7653d00b732afb6fc597e29c50ad28087dcb4fbfb28e86092277a559ae4e693 \ - --hash=sha256:ade01303ccf7ae12c356a5e10911c9e1c51136003a9a1d92f7aa9d010fb98372 \ - --hash=sha256:bac58c024c9922c23550af2a581998624d6e02350f4ae9c5f0bc642c633a2d5e \ - --hash=sha256:c92811b2d4c9b6ea0285942b2e7cac98a59e166d59c588fe5cfe1eda58e72d59 \ - --hash=sha256:d1454bde93fb1e224166811694d600e746430c006fbb031ea06ecc2ea41bf156 \ - --hash=sha256:d735786acc7dd25815e89cc4ad529a43af779db2e25aa7c626de864127e5a024 \ - --hash=sha256:de80739447af31525feddeb8effd640782cf5998e1a4e9192ebdf829717e3913 \ - --hash=sha256:ff432630e510709564c01dafdbe996cb552e0b9f3f065eb89bdce5bd31fabf4c +psycopg2-binary==2.9.10 \ + --hash=sha256:04392983d0bb89a8717772a193cfaac58871321e3ec69514e1c4e0d4957b5aff \ + --hash=sha256:056470c3dc57904bbf63d6f534988bafc4e970ffd50f6271fc4ee7daad9498a5 \ + --hash=sha256:0ea8e3d0ae83564f2fc554955d327fa081d065c8ca5cc6d2abb643e2c9c1200f \ + --hash=sha256:155e69561d54d02b3c3209545fb08938e27889ff5a10c19de8d23eb5a41be8a5 \ + --hash=sha256:18c5ee682b9c6dd3696dad6e54cc7ff3a1a9020df6a5c0f861ef8bfd338c3ca0 \ + --hash=sha256:19721ac03892001ee8fdd11507e6a2e01f4e37014def96379411ca99d78aeb2c \ + --hash=sha256:1a6784f0ce3fec4edc64e985865c17778514325074adf5ad8f80636cd029ef7c \ + --hash=sha256:2286791ececda3a723d1910441c793be44625d86d1a4e79942751197f4d30341 \ + --hash=sha256:230eeae2d71594103cd5b93fd29d1ace6420d0b86f4778739cb1a5a32f607d1f \ + --hash=sha256:245159e7ab20a71d989da00f280ca57da7641fa2cdcf71749c193cea540a74f7 \ + --hash=sha256:26540d4a9a4e2b096f1ff9cce51253d0504dca5a85872c7f7be23be5a53eb18d \ + --hash=sha256:270934a475a0e4b6925b5f804e3809dd5f90f8613621d062848dd82f9cd62007 \ + --hash=sha256:27422aa5f11fbcd9b18da48373eb67081243662f9b46e6fd07c3eb46e4535142 \ + --hash=sha256:2ad26b467a405c798aaa1458ba09d7e2b6e5f96b1ce0ac15d82fd9f95dc38a92 \ + --hash=sha256:2b3d2491d4d78b6b14f76881905c7a8a8abcf974aad4a8a0b065273a0ed7a2cb \ + --hash=sha256:2ce3e21dc3437b1d960521eca599d57408a695a0d3c26797ea0f72e834c7ffe5 \ + --hash=sha256:30e34c4e97964805f715206c7b789d54a78b70f3ff19fbe590104b71c45600e5 \ + --hash=sha256:3216ccf953b3f267691c90c6fe742e45d890d8272326b4a8b20850a03d05b7b8 \ + --hash=sha256:32581b3020c72d7a421009ee1c6bf4a131ef5f0a968fab2e2de0c9d2bb4577f1 \ + --hash=sha256:35958ec9e46432d9076286dda67942ed6d968b9c3a6a2fd62b48939d1d78bf68 \ + --hash=sha256:3abb691ff9e57d4a93355f60d4f4c1dd2d68326c968e7db17ea96df3c023ef73 \ + --hash=sha256:3c18f74eb4386bf35e92ab2354a12c17e5eb4d9798e4c0ad3a00783eae7cd9f1 \ + --hash=sha256:3c4745a90b78e51d9ba06e2088a2fe0c693ae19cc8cb051ccda44e8df8a6eb53 \ + --hash=sha256:3c4ded1a24b20021ebe677b7b08ad10bf09aac197d6943bfe6fec70ac4e4690d \ + --hash=sha256:3e9c76f0ac6f92ecfc79516a8034a544926430f7b080ec5a0537bca389ee0906 \ + --hash=sha256:48b338f08d93e7be4ab2b5f1dbe69dc5e9ef07170fe1f86514422076d9c010d0 \ + --hash=sha256:4b3df0e6990aa98acda57d983942eff13d824135fe2250e6522edaa782a06de2 \ + --hash=sha256:512d29bb12608891e349af6a0cccedce51677725a921c07dba6342beaf576f9a \ + --hash=sha256:5a507320c58903967ef7384355a4da7ff3f28132d679aeb23572753cbf2ec10b \ + --hash=sha256:5c370b1e4975df846b0277b4deba86419ca77dbc25047f535b0bb03d1a544d44 \ + --hash=sha256:6b269105e59ac96aba877c1707c600ae55711d9dcd3fc4b5012e4af68e30c648 \ + --hash=sha256:6d4fa1079cab9018f4d0bd2db307beaa612b0d13ba73b5c6304b9fe2fb441ff7 \ + --hash=sha256:6dc08420625b5a20b53551c50deae6e231e6371194fa0651dbe0fb206452ae1f \ + --hash=sha256:73aa0e31fa4bb82578f3a6c74a73c273367727de397a7a0f07bd83cbea696baa \ + --hash=sha256:7559bce4b505762d737172556a4e6ea8a9998ecac1e39b5233465093e8cee697 \ + --hash=sha256:79625966e176dc97ddabc142351e0409e28acf4660b88d1cf6adb876d20c490d \ + --hash=sha256:7a813c8bdbaaaab1f078014b9b0b13f5de757e2b5d9be6403639b298a04d218b \ + --hash=sha256:7b2c956c028ea5de47ff3a8d6b3cc3330ab45cf0b7c3da35a2d6ff8420896526 \ + --hash=sha256:7f4152f8f76d2023aac16285576a9ecd2b11a9895373a1f10fd9db54b3ff06b4 \ + --hash=sha256:7f5d859928e635fa3ce3477704acee0f667b3a3d3e4bb109f2b18d4005f38287 \ + --hash=sha256:851485a42dbb0bdc1edcdabdb8557c09c9655dfa2ca0460ff210522e073e319e \ + --hash=sha256:8608c078134f0b3cbd9f89b34bd60a943b23fd33cc5f065e8d5f840061bd0673 \ + --hash=sha256:880845dfe1f85d9d5f7c412efea7a08946a46894537e4e5d091732eb1d34d9a0 \ + --hash=sha256:8aabf1c1a04584c168984ac678a668094d831f152859d06e055288fa515e4d30 \ + --hash=sha256:8aecc5e80c63f7459a1a2ab2c64df952051df196294d9f739933a9f6687e86b3 \ + --hash=sha256:8cd9b4f2cfab88ed4a9106192de509464b75a906462fb846b936eabe45c2063e \ + --hash=sha256:8de718c0e1c4b982a54b41779667242bc630b2197948405b7bd8ce16bcecac92 \ + --hash=sha256:9440fa522a79356aaa482aa4ba500b65f28e5d0e63b801abf6aa152a29bd842a \ + --hash=sha256:b5f86c56eeb91dc3135b3fd8a95dc7ae14c538a2f3ad77a19645cf55bab1799c \ + --hash=sha256:b73d6d7f0ccdad7bc43e6d34273f70d587ef62f824d7261c4ae9b8b1b6af90e8 \ + --hash=sha256:bb89f0a835bcfc1d42ccd5f41f04870c1b936d8507c6df12b7737febc40f0909 \ + --hash=sha256:c3cc28a6fd5a4a26224007712e79b81dbaee2ffb90ff406256158ec4d7b52b47 \ + --hash=sha256:ce5ab4bf46a211a8e924d307c1b1fcda82368586a19d0a24f8ae166f5c784864 \ + --hash=sha256:d00924255d7fc916ef66e4bf22f354a940c67179ad3fd7067d7a0a9c84d2fbfc \ + --hash=sha256:d7cd730dfa7c36dbe8724426bf5612798734bff2d3c3857f36f2733f5bfc7c00 \ + --hash=sha256:e217ce4d37667df0bc1c397fdcd8de5e81018ef305aed9415c3b093faaeb10fb \ + --hash=sha256:e3923c1d9870c49a2d44f795df0c889a22380d36ef92440ff618ec315757e539 \ + --hash=sha256:e5720a5d25e3b99cd0dc5c8a440570469ff82659bb09431c1439b92caf184d3b \ + --hash=sha256:e8b58f0a96e7a1e341fc894f62c1177a7c83febebb5ff9123b579418fdc8a481 \ + --hash=sha256:e984839e75e0b60cfe75e351db53d6db750b00de45644c5d1f7ee5d1f34a1ce5 \ + --hash=sha256:eb09aa7f9cecb45027683bb55aebaaf45a0df8bf6de68801a6afdc7947bb09d4 \ + --hash=sha256:ec8a77f521a17506a24a5f626cb2aee7850f9b69a0afe704586f63a464f3cd64 \ + --hash=sha256:ecced182e935529727401b24d76634a357c71c9275b356efafd8a2a91ec07392 \ + --hash=sha256:ee0e8c683a7ff25d23b55b11161c2663d4b099770f6085ff0a20d4505778d6b4 \ + --hash=sha256:f0c2d907a1e102526dd2986df638343388b94c33860ff3bbe1384130828714b1 \ + --hash=sha256:f758ed67cab30b9a8d2833609513ce4d3bd027641673d4ebc9c067e4d208eec1 \ + --hash=sha256:f8157bed2f51db683f31306aa497311b560f2265998122abe1dce6428bd86567 \ + --hash=sha256:ffe8ed017e4ed70f68b7b371d84b7d4a790368db9203dfc2d222febd3a9c8863 # via -r requirements.in py-vapid==1.9.1 \ --hash=sha256:fe2b5461bf45c7baff1039df6981f03b87faa87cde0482addfa35b3fe636ac1b @@ -627,12 +750,9 @@ pytz==2024.1 \ --hash=sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812 \ --hash=sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319 # via - # django # django-comments-xtd # django-modelcluster - # djangorestframework # drf-yasg - # l18n pywebpush==1.9.4 \ --hash=sha256:e3ded57c9715159f64a5624a656791ee9228b9e076ea0208baa73b53be8c130f # via django-webpush @@ -740,8 +860,6 @@ six==1.16.0 \ # bleach # django-comments-xtd # django-compressor - # html5lib - # l18n # libsass soupsieve==2.5 \ --hash=sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690 \ @@ -751,10 +869,6 @@ sqlparse==0.5.0 \ --hash=sha256:714d0a4932c059d16189f58ef5411ec2287a4360f17cdd0edd2d09d4c5087c93 \ --hash=sha256:c204494cd97479d0e39f28c93d46c0b2d5959c7b9ab904762ea6c7af211c8663 # via django -tablib[xls,xlsx]==3.6.1 \ - --hash=sha256:040685fde11e9237675f43e985edb94b63250a5e9236f89d561ce6fb1465b839 \ - --hash=sha256:c771d38ed1d74350a69873db43e0afb7f1cca0ed2915a7243094463eb6789207 - # via wagtail telepath==0.3.1 \ --hash=sha256:925c0609e0a8a6488ec4a55b19d485882cf72223b2b19fe2359a50fddd813c9c \ --hash=sha256:c280aa8e77ad71ce80e96500a4e4d4a32f35b7e0b52e896bb5fde9a5bcf0699a @@ -772,7 +886,10 @@ tqdm==4.66.4 \ typing-extensions==4.12.2 \ --hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \ --hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8 - # via wagtail-localize + # via + # django-stubs-ext + # django-tasks + # wagtail-localize uritemplate==4.1.1 \ --hash=sha256:4346edfc5c3b79f694bccd6d6099a322bbeb628dbf2cd86eea55a456ce5124f0 \ --hash=sha256:830c08b8d99bdd312ea4ead05994a38e8936266f84b9a7878232db50b044e02e @@ -783,30 +900,35 @@ urllib3==1.26.19 \ # via # elasticsearch # requests -wagtail==3.0.3 \ - --hash=sha256:111ed9a0a6ff26d5d881d52deb4bf52b627d79a53c43829611752dbb68a9192f \ - --hash=sha256:23b3e541401355ea183372582050ea52b049c956dd5b506197f957bb68423ab3 +wagtail==7.0.1 \ + --hash=sha256:92439c50a919826a4ce8c85bdaf3ed0e436d29598bb2954b4fca5f312b969666 \ + --hash=sha256:cfc5c37738f98cae380a15252f5676604f6c61554bef1a3791e34de1e703beec # via # -r requirements.in # wagtail-cache # wagtail-localize # wagtail-markdown + # wagtail-modeladmin # wagtailmedia -wagtail-cache==2.1.1 \ - --hash=sha256:1fe3ca20a3cdf23f31fc9df662a52f743084cd7f60bd870950094d63a87f695a \ - --hash=sha256:2ac16921d022a58240a009a19220554e41963c5172e7dfe4ef741ddd887e991f +wagtail-cache==3.0.0 \ + --hash=sha256:2bbb8d1bc5c4c9d7755113c0c8b91b3ec8a0c90bd560ef62aab99698961114fa \ + --hash=sha256:a12b9f7dbd41b560b7fa77be08a6c7ab292536e37296dc910275b99c198ddd1e # via -r requirements.in wagtail-generic-chooser==0.5.1 \ --hash=sha256:135f8cc413d83b82bb8956f625f4b9572aa7139ab3835e2ba2d7e19f2171b354 \ --hash=sha256:280ae7293641d1b121450e17a6d424305e31c832f1af5bd991bc3e49703bf79e # via wagtailsvg -wagtail-localize==1.4 \ - --hash=sha256:40f974809509de54dcc18ee6aa98908bffd9dfaba53150e214f4046b2286920e \ - --hash=sha256:fd1195de3c23e3a061576f1b947fe7498676ff5678fe008d4cd388125a20a54a +wagtail-localize==1.12.2 \ + --hash=sha256:42d4a3b6eafac30c87740f8d914da3f9587ec57f934872bde93a42edce449e8e \ + --hash=sha256:a2006793571ae35d3118f091f25c5072eb501a30911b17d98fad028162b63902 + # via -r requirements.in +wagtail-markdown==0.12.1 \ + --hash=sha256:54f1ba375348e86e03f4eca7d2ac3d33245ead9f854028d7ee9c479448f1e678 \ + --hash=sha256:bb5f02b6bdfef74b50a74e7aa3f255c7bc9787cec8d03dae50fc9404a0097dba # via -r requirements.in -wagtail-markdown==0.10.0 \ - --hash=sha256:b16be4b6e3518cc6dd15ab335cbc6d6a9122b5d7e3a61fa11c83597e2660044e \ - --hash=sha256:e4a97eee0211eebaab9c850669e647bc1c8ceb70df38b4db5a2c3d8b02ebaf69 +wagtail-modeladmin==2.2.0 \ + --hash=sha256:41e12f9a79f8c1595fce73bd6b51007422f258089564f9df8e09a82246a8e133 \ + --hash=sha256:60ea08b128761b5b6a1cbfe3c8ab828fba13e41ff3d7563a0b8c62c8fe36c4ce # via -r requirements.in wagtail-transfer @ https://github.com/IDEMSInternational/wagtail-transfer/archive/52b57b364ebc9acddd412ee708f829b45763c9ab.zip \ --hash=sha256:049c23e1406564d3b7e8c385e72051f34e707add4f8109d874da670711709548 @@ -828,27 +950,14 @@ webencodings==0.5.1 \ # via # bleach # cssselect2 - # html5lib # tinycss2 whitenoise==5.2.0 \ --hash=sha256:05ce0be39ad85740a78750c86a93485c40f08ad8c62a6006de0233765996e5c7 \ --hash=sha256:05d00198c777028d72d8b0bbd234db605ef6d60e9410125124002518a48e515d # via -r requirements.in -willow==1.4.1 \ - --hash=sha256:0df8ff528531e00b48d40bf72ed81beac1dc82f2d42e5bbed4aff0218bef8c0d \ - --hash=sha256:fc4042696d090e75aef922fa1ed26d483c764f005b36cf523cf7c34e69d5dd7a - # via wagtail -xlrd==2.0.1 \ - --hash=sha256:6a33ee89877bd9abc1158129f6e94be74e2679636b8a205b43b85206c3f0bbdd \ - --hash=sha256:f72f148f54442c6b056bf931dbc34f986fd0c3b0b6b5a58d013c9aef274d0c88 - # via tablib -xlsxwriter==3.2.0 \ - --hash=sha256:9977d0c661a72866a61f9f7a809e25ebbb0fb7036baa3b9fe74afcfca6b3cb8c \ - --hash=sha256:ecfd5405b3e0e228219bcaf24c2ca0915e012ca9464a14048021d21a995d490e - # via wagtail -xlwt==1.3.0 \ - --hash=sha256:a082260524678ba48a297d922cc385f58278b8aa68741596a87de01a9c628b2e \ - --hash=sha256:c59912717a9b28f1a3c2a98fd60741014b06b043936dcecbc113eaaada156c88 - # via tablib -msal==1.31.0 \ - --hash=sha256:96bc37cff82ebe4b160d5fc0f1196f6ca8b50e274ecd0ec5bf69c438514086e7 +willow[heif]==1.10.0 \ + --hash=sha256:26861dbacc9584f5d4566de7d31c092437225abc4b1978fa9ac44a433200f938 \ + --hash=sha256:e10673ff954e79ca0412c648e40dd9ce0b93c8bef798e8468ce3411ff972fb15 + # via + # wagtail + # willow From 6f9ab6e85a3eb8081f0490034a1d2aec16e3feaf Mon Sep 17 00:00:00 2001 From: Sachin Mehta Date: Thu, 17 Jul 2025 13:18:52 +0000 Subject: [PATCH 018/147] Upgraded required packages, made fix in code --- comments/button_helpers.py | 2 +- comments/views.py | 2 +- comments/wagtail_hooks.py | 4 ++-- home/admin.py | 2 +- home/wagtail_hooks.py | 34 +++++++++++++++++++++++++++++----- interactive/wagtail_hooks.py | 2 +- iogt/settings/base.py | 6 ++++-- iogt_users/wagtail_hooks.py | 4 ++-- messaging/wagtail_hooks.py | 2 +- notifications/views.py | 2 +- notifications/wagtail_hooks.py | 2 +- questionnaires/admin.py | 4 ++-- questionnaires/views.py | 6 ++++-- requirements.in | 17 +++++++++-------- search/views.py | 15 ++++++++++----- 15 files changed, 69 insertions(+), 35 deletions(-) diff --git a/comments/button_helpers.py b/comments/button_helpers.py index d37c35609..cfad23142 100644 --- a/comments/button_helpers.py +++ b/comments/button_helpers.py @@ -1,5 +1,5 @@ from django.urls import reverse -from wagtail.contrib.modeladmin.helpers import ButtonHelper +from wagtail_modeladmin.helpers import ButtonHelper class XtdCommentAdminButtonHelper(ButtonHelper): diff --git a/comments/views.py b/comments/views.py index 270669079..2463e9cfa 100644 --- a/comments/views.py +++ b/comments/views.py @@ -8,7 +8,7 @@ from django.db.models import Q from django.shortcuts import get_object_or_404, redirect from django.utils.decorators import method_decorator -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from django.views import View from django.views.decorators.csrf import csrf_protect from django.views.decorators.http import require_POST diff --git a/comments/wagtail_hooks.py b/comments/wagtail_hooks.py index 3b9a6333c..fccece6f4 100644 --- a/comments/wagtail_hooks.py +++ b/comments/wagtail_hooks.py @@ -4,8 +4,8 @@ from django.utils import timezone from django.utils.html import format_html from django_comments_xtd.models import XtdComment -from wagtail.contrib.modeladmin.options import ModelAdminGroup, ModelAdmin, modeladmin_register -from wagtail.contrib.modeladmin.helpers.permission import PermissionHelper +from wagtail_modeladmin.options import ModelAdminGroup, ModelAdmin, modeladmin_register +from wagtail_modeladmin.helpers.permission import PermissionHelper from .button_helpers import XtdCommentAdminButtonHelper from .filters import FlaggedFilter, ModerationFilter, PublishedFilter diff --git a/home/admin.py b/home/admin.py index 0580f8748..722912c9a 100644 --- a/home/admin.py +++ b/home/admin.py @@ -1,5 +1,5 @@ from django.contrib import admin -from wagtail.contrib.modeladmin.options import ModelAdmin, modeladmin_register +from wagtail_modeladmin.options import ModelAdmin, modeladmin_register from django.db.models import Avg, Count from django.utils.html import format_html from django.urls import reverse diff --git a/home/wagtail_hooks.py b/home/wagtail_hooks.py index c508f2610..a9fb53bdc 100644 --- a/home/wagtail_hooks.py +++ b/home/wagtail_hooks.py @@ -11,8 +11,7 @@ from wagtail import __version__ from wagtail.admin import widgets as wagtailadmin_widgets from wagtail.admin.menu import MenuItem, SubmenuMenuItem -from wagtail.contrib.modeladmin.menus import SubMenu -from wagtail.contrib.modeladmin.options import ModelAdmin, modeladmin_register +from wagtail_modeladmin.options import ModelAdmin, modeladmin_register from wagtail import hooks from wagtail.models import Page, PageViewRestriction from wagtailcache.cache import clear_cache @@ -21,8 +20,9 @@ Section, SectionIndexPage, BannerPage, HomePageBanner, HomePage) from home.translatable_strings import translatable_strings from translation_manager.models import TranslationEntry -from wagtail.core.signals import page_published +from wagtail.signals import page_published from django.dispatch import receiver +from wagtail.admin.menu import Menu @hooks.register('after_publish_page') @@ -138,6 +138,31 @@ def page_listing_buttons(page, page_perms, is_parent=False, next_url=None): ) +# @hooks.register("register_admin_menu_item") +# def about(): +# items = [ +# MenuItem( +# label=f"IoGT {settings.SITE_VERSION}", +# url=f"http://github.com/unicef/iogt/releases/tag/{settings.SITE_VERSION}", +# ), +# MenuItem( +# label=f"Wagtail {__version__}", +# url=f"http://github.com/wagtail/wagtail/releases/tag/v{__version__}" +# ) +# ] + +# # NOTE: +# # Removed `from wagtail_modeladmin.menus import SubMenu` as `SubMenu` is no longer available in the latest wagtail-modeladmin. +# # Used a direct list of MenuItems in SubmenuMenuItem instead. +# # This preserves the "About" submenu with IoGT and Wagtail version links. +# # If future updates break this, consider defining a lightweight `SubMenu` wrapper or refactor to top-level items. +# return SubmenuMenuItem( +# label="About", +# menu=items, +# icon_name="info-circle", +# order=999999, +# ) + @hooks.register("register_admin_menu_item") def about(): items = [ @@ -150,10 +175,9 @@ def about(): url=f"http://github.com/wagtail/wagtail/releases/tag/v{__version__}" ) ] - return SubmenuMenuItem( label="About", - menu=SubMenu(items), + menu=Menu(register_hook_name=None, items=items), icon_name="info-circle", order=999999, ) diff --git a/interactive/wagtail_hooks.py b/interactive/wagtail_hooks.py index dd0d8329b..c453b1950 100644 --- a/interactive/wagtail_hooks.py +++ b/interactive/wagtail_hooks.py @@ -1,4 +1,4 @@ -from wagtail.contrib.modeladmin.options import ( +from wagtail_modeladmin.options import ( ModelAdmin, ModelAdminGroup, modeladmin_register, diff --git a/iogt/settings/base.py b/iogt/settings/base.py index 5c167fb29..9cacd98bc 100644 --- a/iogt/settings/base.py +++ b/iogt/settings/base.py @@ -78,6 +78,7 @@ 'wagtail.sites', 'wagtail.snippets', 'wagtail.users', + 'wagtail_localize', 'wagtail_localize.locales', 'wagtail_transfer', 'wagtailmarkdown', @@ -110,9 +111,10 @@ 'iogt.middleware.GlobalDataMiddleware', # 'admin_login.middleware.CustomAdminLoginRequiredMiddleware', #'wagtailcache.cache.FetchFromCacheMiddleware', - 'wagtail.contrib.statcache.middleware.StatCacheMiddleware', + # 'wagtail.contrib.statcache.middleware.StatCacheMiddleware', 'django.middleware.cache.UpdateCacheMiddleware', # Must be first - 'django.middleware.cache.FetchFromCacheMiddleware', + 'django.middleware.cache.FetchFromCacheMiddleware', + "allauth.account.middleware.AccountMiddleware", # 👈 Add this here ] # Prevent Wagtail's built in menu from showing in Admin > Settings diff --git a/iogt_users/wagtail_hooks.py b/iogt_users/wagtail_hooks.py index 463c29e37..a0eba25d3 100644 --- a/iogt_users/wagtail_hooks.py +++ b/iogt_users/wagtail_hooks.py @@ -5,8 +5,8 @@ from django.db.models import Prefetch from django.urls import reverse from django.utils import timezone -from wagtail.contrib.modeladmin.helpers import ButtonHelper -from wagtail.contrib.modeladmin.options import ModelAdmin, modeladmin_register +from wagtail_modeladmin.helpers import ButtonHelper +from wagtail_modeladmin.options import ModelAdmin, modeladmin_register from home.models import SiteSettings from iogt_users.filters import GroupsFilter diff --git a/messaging/wagtail_hooks.py b/messaging/wagtail_hooks.py index d50e6536c..9a2e951ad 100644 --- a/messaging/wagtail_hooks.py +++ b/messaging/wagtail_hooks.py @@ -1,4 +1,4 @@ -from wagtail.contrib.modeladmin.options import ( +from wagtail_modeladmin.options import ( ModelAdminGroup, ModelAdmin, modeladmin_register) from .models import ChatbotChannel diff --git a/notifications/views.py b/notifications/views.py index afccb959d..158875eac 100644 --- a/notifications/views.py +++ b/notifications/views.py @@ -1,4 +1,4 @@ -from wagtail.contrib.modeladmin.views import CreateView +from wagtail_modeladmin.views import CreateView from webpush import send_user_notification diff --git a/notifications/wagtail_hooks.py b/notifications/wagtail_hooks.py index a5582b6ad..7dc227aae 100644 --- a/notifications/wagtail_hooks.py +++ b/notifications/wagtail_hooks.py @@ -1,5 +1,5 @@ from django.conf import settings -from wagtail.contrib.modeladmin.options import ModelAdmin, modeladmin_register +from wagtail_modeladmin.options import ModelAdmin, modeladmin_register from notifications.models import Notification from notifications.views import CreateNotificationView diff --git a/questionnaires/admin.py b/questionnaires/admin.py index cf018eae6..9452b37eb 100644 --- a/questionnaires/admin.py +++ b/questionnaires/admin.py @@ -1,5 +1,5 @@ -from wagtail.contrib.modeladmin.helpers import ButtonHelper -from wagtail.contrib.modeladmin.options import ModelAdmin, modeladmin_register +from wagtail_modeladmin.helpers import ButtonHelper +from wagtail_modeladmin.options import ModelAdmin, modeladmin_register from .models import Survey, Poll, Quiz diff --git a/questionnaires/views.py b/questionnaires/views.py index aa478f3de..d71063f0e 100644 --- a/questionnaires/views.py +++ b/questionnaires/views.py @@ -15,7 +15,6 @@ from wagtail.contrib.forms.views import ( SubmissionsListView, FormPagesListView as WagtailFormPagesListView, - SafePaginateListView, ) from wagtail.models import Page from xlsxwriter.workbook import Workbook @@ -23,6 +22,9 @@ from questionnaires.forms import GenerateDashboardForm from questionnaires.models import UserSubmission, SurveyFormField, PollFormField, QuizFormField from questionnaires.superset.utils import DashboardGenerator +# SafePaginateListView was an internal class removed in Wagtail 5+ +# Replacing it with ListView for compatibility +from django.views.generic import ListView User = get_user_model() @@ -48,7 +50,7 @@ def get_queryset(self): return super().get_queryset().select_related('page', 'user') -class FormDataPerUserView(SpreadsheetExportMixin, SafePaginateListView): +class FormDataPerUserView(SpreadsheetExportMixin, ListView): """ This view is taking inspiration from `wagtail.contrib.forms.views.FormPagesListView` and `wagtail.contrib.forms.views.SubmissionsListView` diff --git a/requirements.in b/requirements.in index a75c41c88..a9cb516ce 100644 --- a/requirements.in +++ b/requirements.in @@ -6,14 +6,15 @@ django-contrib-comments django-comments-xtd==2.10.7 django-extensions django-filter~=25.1 -django-health-check +django-health-check==3.20.0 django-redis -django-sass-processor +django-sass-processor==1.4.2 django-translation-manager django-webpush django~=5.2.4 djangorestframework-simplejwt djangorestframework>=3.12,<3.16 +django-debug-toolbar==5.2.0 drf-yasg elasticsearch libsass @@ -24,12 +25,12 @@ redis tqdm wagtail-markdown==0.12.1 wagtail-modeladmin -wagtail-localize +wagtail-localize==1.12.2 wagtail~=7.0 wagtail-cache==3.0.0 -wagtailmedia -wagtailmenus -git+https://github.com/jmrichardson/wagtail-svg.git@main#egg=wagtailsvg -# branch: iogt, tag: v0.8.5-iogt.1 -wagtail-transfer @ https://github.com/IDEMSInternational/wagtail-transfer/archive/52b57b364ebc9acddd412ee708f829b45763c9ab.zip +wagtailmedia==0.16 +wagtailmenus==4.0.4 +wagtailsvg @ https://github.com/sachin-mehta/wagtailsvg/archive/905663a5dd6fd9a0ccbe5d5f30080867dc9a8665.zip +wagtail-transfer whitenoise +xlsxwriter==3.2.5 diff --git a/search/views.py b/search/views.py index 2c361fa8f..27d917011 100644 --- a/search/views.py +++ b/search/views.py @@ -4,7 +4,7 @@ from home.models import Article, Section from iogt.settings.base import SEARCH_RESULTS_PER_PAGE -from wagtail.search.models import Query +# from wagtail.search.models import Query from questionnaires.models import Poll, Quiz, Survey @@ -28,10 +28,15 @@ def search(request): search_results = search_group.objects.exclude(id__in=sandbox_page_ids).live().\ filter(locale=Locale.objects.get(language_code=request.LANGUAGE_CODE)).specific().search(search_query) search_results_count = search_results.count() - query = Query.get(search_query) - - # Record hit - query.add_hit() + # Removed in Wagtail 6+: Query.add_hit() was used to log search query usage statistics in the admin. + # As of Wagtail 6 and later, this feature has been deprecated and the model `wagtail.search.models.Query` is no longer available. + # If analytics are still desired, consider implementing a custom `SearchAnalytics` model to log queries, + # or integrate with a third-party analytics platform like Google Analytics or Matomo. + # Example: log query, timestamp, and whether results were found for later analysis. + # query = Query.get(search_query) + + # # Record hit + # query.add_hit() else: search_results = search_group.objects.none() From 2d6b42a0068776ed4bbafe0e1060527474dcbc49 Mon Sep 17 00:00:00 2001 From: Ankit Chopra Date: Fri, 18 Jul 2025 11:18:22 +0530 Subject: [PATCH 019/147] Added redirect url for artilce and survey --- docker-compose.yml | 1 + home/signals.py | 36 +++++++++++++++++++-- iogt_users/templates/user_notification.html | 5 ++- iogt_users/views.py | 3 -- questionnaires/signals.py | 34 +++++++++++++++++-- user_notifications/tasks.py | 6 ++-- user_notifications/wagtail_hooks.py | 3 +- 7 files changed, 72 insertions(+), 16 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 1f00163a6..7949a4922 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -12,6 +12,7 @@ services: DB_PORT: '5432' DB_USER: postgres DJANGO_SETTINGS_MODULE: iogt.settings.dev + DJANGO_RUN_PORT: 8000 image: iogt:latest ports: diff --git a/home/signals.py b/home/signals.py index fe428079c..0afa224ec 100644 --- a/home/signals.py +++ b/home/signals.py @@ -1,7 +1,10 @@ +from urllib.parse import urlparse from django.db.models.signals import post_save, post_delete from django.dispatch import receiver from .models import ArticleFeedback from wagtail.signals import page_published +from wagtail.models import Site +import os from .models import Article from user_notifications.tasks import send_app_notifications @@ -16,8 +19,37 @@ def update_article_feedback_metrics(sender, instance, **kwargs): instance.article.update_feedback_metrics() +def get_site_for_locale(instance): + """ + Return the Wagtail Site object matching the given locale. + """ + for site in Site.objects.all(): + if site.root_page.locale.language_code == instance.locale.language_code: + if not site: + print("No matching site for locale:", instance.locale) + return + + parsed = urlparse(site.root_url) + hostname = parsed.hostname + scheme = parsed.scheme or "http" + port = os.getenv("DJANGO_RUN_PORT") + if hostname in ("localhost", "127.0.0.1"): + host_with_port = f"{scheme}://{hostname}:{port}" + else: + host_with_port = f"{scheme}://{hostname}" + relative = instance.relative_url(site) + if not relative: + print("Could not get relative URL for instance.") + return + full_url = host_with_port + relative + return full_url + return None + + @receiver(page_published) def trigger_article_notification(sender, instance, **kwargs): - if isinstance(instance, Article): - send_app_notifications.delay(instance.id, 'article') + if not isinstance(instance, Article): + return + full_url = get_site_for_locale(instance) + send_app_notifications.delay(instance.id, 'article', full_url) diff --git a/iogt_users/templates/user_notification.html b/iogt_users/templates/user_notification.html index 6f55639e2..aa6dd2057 100644 --- a/iogt_users/templates/user_notification.html +++ b/iogt_users/templates/user_notification.html @@ -91,10 +91,9 @@

{% translate "Notification Preference" %}

}), }).then((res) => { if (res.ok) { - console.log('response', res) - + showToast(`✅ Preference saved successfully.`, "success"); } - }); + }).catch(err =>showToast(`❌ error: Could not save preference!`, "error")) } window.onload = function () { diff --git a/iogt_users/views.py b/iogt_users/views.py index b33fce9f1..298dcb0f7 100644 --- a/iogt_users/views.py +++ b/iogt_users/views.py @@ -38,9 +38,6 @@ def get_context_data(self, **kwargs): context['notification_tags'] = NotificationTag.objects.all() context['available_languages'] = Locale.objects.all() context['user'] = self.request.user - print('tags', context['notification_tags']) - print('languages', context['selected_language_code']) - print('available_languages', context['available_languages']) return context diff --git a/questionnaires/signals.py b/questionnaires/signals.py index c84dcbd1c..810a58757 100644 --- a/questionnaires/signals.py +++ b/questionnaires/signals.py @@ -1,11 +1,39 @@ from django.dispatch import receiver from wagtail.signals import page_published +from wagtail.models import Site +from urllib.parse import urlparse from .models import Survey from user_notifications.tasks import send_app_notifications +import os + + +def get_site_for_locale(locale): + """ + Return the Wagtail Site object matching the given locale. + """ + for site in Site.objects.all(): + if site.root_page.locale.language_code == locale.language_code: + return site + return None @receiver(page_published) def trigger_survey_notification(sender, instance, **kwargs): - if isinstance(instance, Survey): - print("📢 Article published:", instance.title) - send_app_notifications.delay(instance.id, 'survey') + if not isinstance(instance, Survey): + return + site = get_site_for_locale(instance.locale) + if not site: + print("No matching site for locale:", instance.locale) + return + + parsed = urlparse(site.root_url) + hostname = parsed.hostname + scheme = parsed.scheme or "http" + port = os.getenv("DJANGO_RUN_PORT") + host_with_port = f"{scheme}://{hostname}:{port}" + relative = instance.relative_url(site) + if not relative: + print("Could not get relative URL for instance.") + return + full_url = host_with_port + relative + send_app_notifications.delay(instance.id, 'survey', full_url) \ No newline at end of file diff --git a/user_notifications/tasks.py b/user_notifications/tasks.py index 24ca6f6dc..db2f31e18 100644 --- a/user_notifications/tasks.py +++ b/user_notifications/tasks.py @@ -11,7 +11,7 @@ @shared_task -def send_app_notifications(id, notification_type): +def send_app_notifications(id, notification_type, url=None): from home.models import Article from questionnaires.models import Survey try: @@ -52,13 +52,11 @@ def send_app_notifications(id, notification_type): else: notify.send( sender=sender, - url='www.google.com', + url=url, recipient=notification_preference.user, verb=template.title, description=template.message ) - # send_user_notification(user=user, payload=json.dumps(template), ttl=1000) - # raise Exception NotificationLog.objects.create( user=notification_preference.user, notification_key=template.title, diff --git a/user_notifications/wagtail_hooks.py b/user_notifications/wagtail_hooks.py index 79ef63edd..2320d3409 100644 --- a/user_notifications/wagtail_hooks.py +++ b/user_notifications/wagtail_hooks.py @@ -41,8 +41,9 @@ class NotificationLogAdmin(ModelAdmin): list_display = ("notification_key", "user", "state", "tags", "received_at") search_fields = ("notification_key", "user__username", "user__email", "tags") + class NotificationsParentGroup(ModelAdminGroup): - menu_label= "Parent Notifications" + menu_label = "Notifications" menu_icon = "bell" items = ( NotificationTagAdmin, From ba839ce5917806a04f4705165020e678ff5793b4 Mon Sep 17 00:00:00 2001 From: Sachin Mehta Date: Mon, 21 Jul 2025 04:48:58 +0000 Subject: [PATCH 020/147] Generated hashes --- requirements.dev.txt | 55 +++++++++++++++++++++++++++----------------- requirements.txt | 55 +++++++++++++++++++++++++++----------------- 2 files changed, 68 insertions(+), 42 deletions(-) diff --git a/requirements.dev.txt b/requirements.dev.txt index 7d65b0db2..62bb8c716 100644 --- a/requirements.dev.txt +++ b/requirements.dev.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.11 +# This file is autogenerated by pip-compile with Python 3.12 # by the following command: # # pip-compile --generate-hashes requirements.in @@ -247,6 +247,7 @@ django==5.2.4 \ # django-appconf # django-comments-xtd # django-contrib-comments + # django-debug-toolbar # django-extensions # django-filter # django-health-check @@ -291,6 +292,10 @@ django-contrib-comments==2.2.0 \ # via # -r requirements.in # django-comments-xtd +django-debug-toolbar==5.2.0 \ + --hash=sha256:15627f4c2836a9099d795e271e38e8cf5204ccd79d5dbcd748f8a6c284dcd195 \ + --hash=sha256:9e7f0145e1a1b7d78fcc3b53798686170a5b472d9cf085d88121ff823e900821 + # via -r requirements.in django-extensions==3.1.5 \ --hash=sha256:28e1e1bf49f0e00307ba574d645b0af3564c981a6dfc87209d48cb98f77d0b1a \ --hash=sha256:9238b9e016bb0009d621e05cf56ea8ce5cce9b32e91ad2026996a7377ca28069 @@ -301,9 +306,9 @@ django-filter==25.1 \ # via # -r requirements.in # wagtail -django-health-check==3.16.5 \ - --hash=sha256:1edfd49293ccebbce29f9da609c407f307aee240ab799ab4201031341ae78c0f \ - --hash=sha256:8d66781a0ea82b1a8b44878187b38a27370e94f18287312e39be0593e72d8983 +django-health-check==3.20.0 \ + --hash=sha256:bcb2b8f36f463cead0564a028345c5b17e2a2d18e9cc88ecd611b13a26521926 \ + --hash=sha256:cd69ac5facf73fe7241d9492d939b57bd20e24f46c4edea91e6a900bf22c2d8e # via -r requirements.in django-modelcluster==6.3 \ --hash=sha256:0caed8a0e889f3abb92f144670878a466ef954ffa6c4c7b9c80e6426b720a49d \ @@ -321,9 +326,9 @@ django-rq==2.4.1 \ --hash=sha256:23981f83c537178cbbf730f192c13e99cede2204e9d917b1c1c80c42215dd227 \ --hash=sha256:f09059ab37403a47c7933bca396fabb7f3058732d132462eade5333bc4bcac5f # via django-translation-manager -django-sass-processor==1.0.1 \ - --hash=sha256:1f043180c47754018e803a77da003377f5ea6558de57cd6946eb27a32e9c16a2 \ - --hash=sha256:dcaad47c591a2d52689c1bd209259e922e902d886293f0d5c9e0d1a4eb85eda2 +django-sass-processor==1.4.2 \ + --hash=sha256:59c1028b5a5bd0158a0ea92ac5d538e5d89eb547e910a45e334d9c7b3b814b18 \ + --hash=sha256:604b00b19f7bbccfb838f766a284257bad3bb4ec3012f0770a1415913783bacc # via -r requirements.in django-stubs-ext==5.2.1 \ --hash=sha256:98fb0646f1a1ef07708eec5f6f7d27523f12c0c8714abae8db981571ff957588 \ @@ -868,7 +873,9 @@ soupsieve==2.5 \ sqlparse==0.5.0 \ --hash=sha256:714d0a4932c059d16189f58ef5411ec2287a4360f17cdd0edd2d09d4c5087c93 \ --hash=sha256:c204494cd97479d0e39f28c93d46c0b2d5959c7b9ab904762ea6c7af211c8663 - # via django + # via + # django + # django-debug-toolbar telepath==0.3.1 \ --hash=sha256:925c0609e0a8a6488ec4a55b19d485882cf72223b2b19fe2359a50fddd813c9c \ --hash=sha256:c280aa8e77ad71ce80e96500a4e4d4a32f35b7e0b52e896bb5fde9a5bcf0699a @@ -909,14 +916,16 @@ wagtail==7.0.1 \ # wagtail-localize # wagtail-markdown # wagtail-modeladmin + # wagtail-transfer # wagtailmedia + # wagtailmenus wagtail-cache==3.0.0 \ --hash=sha256:2bbb8d1bc5c4c9d7755113c0c8b91b3ec8a0c90bd560ef62aab99698961114fa \ --hash=sha256:a12b9f7dbd41b560b7fa77be08a6c7ab292536e37296dc910275b99c198ddd1e # via -r requirements.in -wagtail-generic-chooser==0.5.1 \ - --hash=sha256:135f8cc413d83b82bb8956f625f4b9572aa7139ab3835e2ba2d7e19f2171b354 \ - --hash=sha256:280ae7293641d1b121450e17a6d424305e31c832f1af5bd991bc3e49703bf79e +wagtail-generic-chooser==0.7 \ + --hash=sha256:42ec66e4c4154f52e0ee6219d098a424e32349518176ebc213eade789585e746 \ + --hash=sha256:a79ade8189e23813b0c65dbf0f9617cd462fc36cab1ed3a26c01c835fa4e113d # via wagtailsvg wagtail-localize==1.12.2 \ --hash=sha256:42d4a3b6eafac30c87740f8d914da3f9587ec57f934872bde93a42edce449e8e \ @@ -930,19 +939,19 @@ wagtail-modeladmin==2.2.0 \ --hash=sha256:41e12f9a79f8c1595fce73bd6b51007422f258089564f9df8e09a82246a8e133 \ --hash=sha256:60ea08b128761b5b6a1cbfe3c8ab828fba13e41ff3d7563a0b8c62c8fe36c4ce # via -r requirements.in -wagtail-transfer @ https://github.com/IDEMSInternational/wagtail-transfer/archive/52b57b364ebc9acddd412ee708f829b45763c9ab.zip \ - --hash=sha256:049c23e1406564d3b7e8c385e72051f34e707add4f8109d874da670711709548 +wagtail-transfer==0.9.4 \ + --hash=sha256:8f6cc4b919764795b0418424a3881b09984e2615922107516a0e5625635278e1 # via -r requirements.in -wagtailmedia==0.12.0 \ - --hash=sha256:0807515c5d89782666b613de2e4aedab19e9dd358097fad2cb79633c0b5416d3 \ - --hash=sha256:1d39622c3d7d0191e58ffedf45d05fbef851e3905955513012a72ae4d46a12b0 +wagtailmedia==0.16.0 \ + --hash=sha256:1f757984240822a7ddfe3eda8e58243f31a3c29935ce8014499e7e664923d4c9 \ + --hash=sha256:40e3adc077ed6251b9c43a7177649e8cdefa4f94828dff6f1ca3e48ba61dcdca # via -r requirements.in -wagtailmenus==3.1.3 \ - --hash=sha256:0f5669f160d788b1ab8c2b412cb95411e9c07f83e4b52dddc92991752c6fa397 +wagtailmenus==4.0.4 \ + --hash=sha256:afcaf9a08897dad831561a70293280c1eac67a5052507e79e8c0366f209730b4 \ + --hash=sha256:f5646431ce89e7df1b69e782e12a46796a2be4d7036d2f2af63178f156dd605d # via -r requirements.in -wagtailsvg==0.0.37 \ - --hash=sha256:4b30433809614fbac09f9088b4aed42a1bfe56f9fb581b858606187cb177ca6b \ - --hash=sha256:dc4d698748bde32034b1eac2275cf159597ca8e399d3830e96391f761aa0cacf +wagtailsvg @ https://github.com/sachin-mehta/wagtailsvg/archive/905663a5dd6fd9a0ccbe5d5f30080867dc9a8665.zip \ + --hash=sha256:a5def9616825985b67f475cb0f00e3b31124b93c4ecff3037503cb309481dad8 # via -r requirements.in webencodings==0.5.1 \ --hash=sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78 \ @@ -961,3 +970,7 @@ willow[heif]==1.10.0 \ # via # wagtail # willow +xlsxwriter==3.2.5 \ + --hash=sha256:4f4824234e1eaf9d95df9a8fe974585ff91d0f5e3d3f12ace5b71e443c1c6abd \ + --hash=sha256:7e88469d607cdc920151c0ab3ce9cf1a83992d4b7bc730c5ffdd1a12115a7dbe + # via -r requirements.in \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 7d65b0db2..62bb8c716 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.11 +# This file is autogenerated by pip-compile with Python 3.12 # by the following command: # # pip-compile --generate-hashes requirements.in @@ -247,6 +247,7 @@ django==5.2.4 \ # django-appconf # django-comments-xtd # django-contrib-comments + # django-debug-toolbar # django-extensions # django-filter # django-health-check @@ -291,6 +292,10 @@ django-contrib-comments==2.2.0 \ # via # -r requirements.in # django-comments-xtd +django-debug-toolbar==5.2.0 \ + --hash=sha256:15627f4c2836a9099d795e271e38e8cf5204ccd79d5dbcd748f8a6c284dcd195 \ + --hash=sha256:9e7f0145e1a1b7d78fcc3b53798686170a5b472d9cf085d88121ff823e900821 + # via -r requirements.in django-extensions==3.1.5 \ --hash=sha256:28e1e1bf49f0e00307ba574d645b0af3564c981a6dfc87209d48cb98f77d0b1a \ --hash=sha256:9238b9e016bb0009d621e05cf56ea8ce5cce9b32e91ad2026996a7377ca28069 @@ -301,9 +306,9 @@ django-filter==25.1 \ # via # -r requirements.in # wagtail -django-health-check==3.16.5 \ - --hash=sha256:1edfd49293ccebbce29f9da609c407f307aee240ab799ab4201031341ae78c0f \ - --hash=sha256:8d66781a0ea82b1a8b44878187b38a27370e94f18287312e39be0593e72d8983 +django-health-check==3.20.0 \ + --hash=sha256:bcb2b8f36f463cead0564a028345c5b17e2a2d18e9cc88ecd611b13a26521926 \ + --hash=sha256:cd69ac5facf73fe7241d9492d939b57bd20e24f46c4edea91e6a900bf22c2d8e # via -r requirements.in django-modelcluster==6.3 \ --hash=sha256:0caed8a0e889f3abb92f144670878a466ef954ffa6c4c7b9c80e6426b720a49d \ @@ -321,9 +326,9 @@ django-rq==2.4.1 \ --hash=sha256:23981f83c537178cbbf730f192c13e99cede2204e9d917b1c1c80c42215dd227 \ --hash=sha256:f09059ab37403a47c7933bca396fabb7f3058732d132462eade5333bc4bcac5f # via django-translation-manager -django-sass-processor==1.0.1 \ - --hash=sha256:1f043180c47754018e803a77da003377f5ea6558de57cd6946eb27a32e9c16a2 \ - --hash=sha256:dcaad47c591a2d52689c1bd209259e922e902d886293f0d5c9e0d1a4eb85eda2 +django-sass-processor==1.4.2 \ + --hash=sha256:59c1028b5a5bd0158a0ea92ac5d538e5d89eb547e910a45e334d9c7b3b814b18 \ + --hash=sha256:604b00b19f7bbccfb838f766a284257bad3bb4ec3012f0770a1415913783bacc # via -r requirements.in django-stubs-ext==5.2.1 \ --hash=sha256:98fb0646f1a1ef07708eec5f6f7d27523f12c0c8714abae8db981571ff957588 \ @@ -868,7 +873,9 @@ soupsieve==2.5 \ sqlparse==0.5.0 \ --hash=sha256:714d0a4932c059d16189f58ef5411ec2287a4360f17cdd0edd2d09d4c5087c93 \ --hash=sha256:c204494cd97479d0e39f28c93d46c0b2d5959c7b9ab904762ea6c7af211c8663 - # via django + # via + # django + # django-debug-toolbar telepath==0.3.1 \ --hash=sha256:925c0609e0a8a6488ec4a55b19d485882cf72223b2b19fe2359a50fddd813c9c \ --hash=sha256:c280aa8e77ad71ce80e96500a4e4d4a32f35b7e0b52e896bb5fde9a5bcf0699a @@ -909,14 +916,16 @@ wagtail==7.0.1 \ # wagtail-localize # wagtail-markdown # wagtail-modeladmin + # wagtail-transfer # wagtailmedia + # wagtailmenus wagtail-cache==3.0.0 \ --hash=sha256:2bbb8d1bc5c4c9d7755113c0c8b91b3ec8a0c90bd560ef62aab99698961114fa \ --hash=sha256:a12b9f7dbd41b560b7fa77be08a6c7ab292536e37296dc910275b99c198ddd1e # via -r requirements.in -wagtail-generic-chooser==0.5.1 \ - --hash=sha256:135f8cc413d83b82bb8956f625f4b9572aa7139ab3835e2ba2d7e19f2171b354 \ - --hash=sha256:280ae7293641d1b121450e17a6d424305e31c832f1af5bd991bc3e49703bf79e +wagtail-generic-chooser==0.7 \ + --hash=sha256:42ec66e4c4154f52e0ee6219d098a424e32349518176ebc213eade789585e746 \ + --hash=sha256:a79ade8189e23813b0c65dbf0f9617cd462fc36cab1ed3a26c01c835fa4e113d # via wagtailsvg wagtail-localize==1.12.2 \ --hash=sha256:42d4a3b6eafac30c87740f8d914da3f9587ec57f934872bde93a42edce449e8e \ @@ -930,19 +939,19 @@ wagtail-modeladmin==2.2.0 \ --hash=sha256:41e12f9a79f8c1595fce73bd6b51007422f258089564f9df8e09a82246a8e133 \ --hash=sha256:60ea08b128761b5b6a1cbfe3c8ab828fba13e41ff3d7563a0b8c62c8fe36c4ce # via -r requirements.in -wagtail-transfer @ https://github.com/IDEMSInternational/wagtail-transfer/archive/52b57b364ebc9acddd412ee708f829b45763c9ab.zip \ - --hash=sha256:049c23e1406564d3b7e8c385e72051f34e707add4f8109d874da670711709548 +wagtail-transfer==0.9.4 \ + --hash=sha256:8f6cc4b919764795b0418424a3881b09984e2615922107516a0e5625635278e1 # via -r requirements.in -wagtailmedia==0.12.0 \ - --hash=sha256:0807515c5d89782666b613de2e4aedab19e9dd358097fad2cb79633c0b5416d3 \ - --hash=sha256:1d39622c3d7d0191e58ffedf45d05fbef851e3905955513012a72ae4d46a12b0 +wagtailmedia==0.16.0 \ + --hash=sha256:1f757984240822a7ddfe3eda8e58243f31a3c29935ce8014499e7e664923d4c9 \ + --hash=sha256:40e3adc077ed6251b9c43a7177649e8cdefa4f94828dff6f1ca3e48ba61dcdca # via -r requirements.in -wagtailmenus==3.1.3 \ - --hash=sha256:0f5669f160d788b1ab8c2b412cb95411e9c07f83e4b52dddc92991752c6fa397 +wagtailmenus==4.0.4 \ + --hash=sha256:afcaf9a08897dad831561a70293280c1eac67a5052507e79e8c0366f209730b4 \ + --hash=sha256:f5646431ce89e7df1b69e782e12a46796a2be4d7036d2f2af63178f156dd605d # via -r requirements.in -wagtailsvg==0.0.37 \ - --hash=sha256:4b30433809614fbac09f9088b4aed42a1bfe56f9fb581b858606187cb177ca6b \ - --hash=sha256:dc4d698748bde32034b1eac2275cf159597ca8e399d3830e96391f761aa0cacf +wagtailsvg @ https://github.com/sachin-mehta/wagtailsvg/archive/905663a5dd6fd9a0ccbe5d5f30080867dc9a8665.zip \ + --hash=sha256:a5def9616825985b67f475cb0f00e3b31124b93c4ecff3037503cb309481dad8 # via -r requirements.in webencodings==0.5.1 \ --hash=sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78 \ @@ -961,3 +970,7 @@ willow[heif]==1.10.0 \ # via # wagtail # willow +xlsxwriter==3.2.5 \ + --hash=sha256:4f4824234e1eaf9d95df9a8fe974585ff91d0f5e3d3f12ace5b71e443c1c6abd \ + --hash=sha256:7e88469d607cdc920151c0ab3ce9cf1a83992d4b7bc730c5ffdd1a12115a7dbe + # via -r requirements.in \ No newline at end of file From 0e28a2a6b0693328a39a14e531b258c47f7eb70f Mon Sep 17 00:00:00 2001 From: Sachin Mehta Date: Tue, 22 Jul 2025 09:18:47 +0000 Subject: [PATCH 021/147] Fixed issue on new Article page --- home/wagtail_hooks.py | 3 +-- messaging/blocks.py | 9 ++++----- messaging/models.py | 3 ++- requirements.dev.txt | 6 +++--- requirements.in | 2 +- requirements.txt | 6 +++--- 6 files changed, 14 insertions(+), 15 deletions(-) diff --git a/home/wagtail_hooks.py b/home/wagtail_hooks.py index a9fb53bdc..47ef438ca 100644 --- a/home/wagtail_hooks.py +++ b/home/wagtail_hooks.py @@ -127,8 +127,7 @@ def global_admin_js(): @hooks.register('register_page_listing_buttons') -def page_listing_buttons(page, page_perms, is_parent=False, next_url=None): - # Using more menu's "Sort menu order" button from wagtail +def page_listing_buttons(page, is_parent=False, next_url=None, user=None, **kwargs): if is_parent: yield wagtailadmin_widgets.PageListingButton( _('Sort child pages'), diff --git a/messaging/blocks.py b/messaging/blocks.py index 550370b6a..b2d4b2034 100644 --- a/messaging/blocks.py +++ b/messaging/blocks.py @@ -1,12 +1,11 @@ from django import forms from wagtail import blocks +from wagtail.snippets.blocks import SnippetChooserBlock -from .models import ChatbotChannel - -class ChatBotChannelChooserBlock(blocks.ChooserBlock): - target_model = ChatbotChannel - widget = forms.Select +class ChatBotChannelChooserBlock(SnippetChooserBlock): + def __init__(self, **kwargs): + super().__init__(target_model='messaging.ChatbotChannel', **kwargs) class ChatBotButtonBlock(blocks.StructBlock): diff --git a/messaging/models.py b/messaging/models.py index 52c557cde..8ef8b92d2 100644 --- a/messaging/models.py +++ b/messaging/models.py @@ -14,12 +14,13 @@ from rest_framework import status from django.core.exceptions import ValidationError from wagtail.images.models import Image +from wagtail.snippets.models import register_snippet from .querysets import ThreadQuerySet logger = logging.getLogger(__name__) - +@register_snippet class ChatbotChannel(models.Model): display_name = models.CharField( max_length=80, help_text=_('Name for the bot that the user will see when interacting with it')) diff --git a/requirements.dev.txt b/requirements.dev.txt index 62bb8c716..9fc55382f 100644 --- a/requirements.dev.txt +++ b/requirements.dev.txt @@ -2,7 +2,7 @@ # This file is autogenerated by pip-compile with Python 3.12 # by the following command: # -# pip-compile --generate-hashes requirements.in +# pip-compile --generate-hashes # anyascii==0.3.2 \ --hash=sha256:3b3beef6fc43d9036d3b0529050b0c48bfad8bc960e9e562d7223cfb94fe45d4 \ @@ -950,8 +950,8 @@ wagtailmenus==4.0.4 \ --hash=sha256:afcaf9a08897dad831561a70293280c1eac67a5052507e79e8c0366f209730b4 \ --hash=sha256:f5646431ce89e7df1b69e782e12a46796a2be4d7036d2f2af63178f156dd605d # via -r requirements.in -wagtailsvg @ https://github.com/sachin-mehta/wagtailsvg/archive/905663a5dd6fd9a0ccbe5d5f30080867dc9a8665.zip \ - --hash=sha256:a5def9616825985b67f475cb0f00e3b31124b93c4ecff3037503cb309481dad8 +wagtailsvg @ https://github.com/sachin-mehta/wagtailsvg/archive/3d2ecc67d993faeffd3251e88ad2e38b3265c0e4.zip \ + --hash=sha256:21b736639aeebeab3633df1b7e5f2e0d4633f685840a8c5b65994ca004c024e6 # via -r requirements.in webencodings==0.5.1 \ --hash=sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78 \ diff --git a/requirements.in b/requirements.in index a9cb516ce..32b20e7a3 100644 --- a/requirements.in +++ b/requirements.in @@ -30,7 +30,7 @@ wagtail~=7.0 wagtail-cache==3.0.0 wagtailmedia==0.16 wagtailmenus==4.0.4 -wagtailsvg @ https://github.com/sachin-mehta/wagtailsvg/archive/905663a5dd6fd9a0ccbe5d5f30080867dc9a8665.zip +wagtailsvg @ https://github.com/sachin-mehta/wagtailsvg/archive/3d2ecc67d993faeffd3251e88ad2e38b3265c0e4.zip wagtail-transfer whitenoise xlsxwriter==3.2.5 diff --git a/requirements.txt b/requirements.txt index 62bb8c716..9fc55382f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ # This file is autogenerated by pip-compile with Python 3.12 # by the following command: # -# pip-compile --generate-hashes requirements.in +# pip-compile --generate-hashes # anyascii==0.3.2 \ --hash=sha256:3b3beef6fc43d9036d3b0529050b0c48bfad8bc960e9e562d7223cfb94fe45d4 \ @@ -950,8 +950,8 @@ wagtailmenus==4.0.4 \ --hash=sha256:afcaf9a08897dad831561a70293280c1eac67a5052507e79e8c0366f209730b4 \ --hash=sha256:f5646431ce89e7df1b69e782e12a46796a2be4d7036d2f2af63178f156dd605d # via -r requirements.in -wagtailsvg @ https://github.com/sachin-mehta/wagtailsvg/archive/905663a5dd6fd9a0ccbe5d5f30080867dc9a8665.zip \ - --hash=sha256:a5def9616825985b67f475cb0f00e3b31124b93c4ecff3037503cb309481dad8 +wagtailsvg @ https://github.com/sachin-mehta/wagtailsvg/archive/3d2ecc67d993faeffd3251e88ad2e38b3265c0e4.zip \ + --hash=sha256:21b736639aeebeab3633df1b7e5f2e0d4633f685840a8c5b65994ca004c024e6 # via -r requirements.in webencodings==0.5.1 \ --hash=sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78 \ From ce55828514397c87db172361a472df8dd374499f Mon Sep 17 00:00:00 2001 From: Sachin Mehta Date: Tue, 22 Jul 2025 09:48:08 +0000 Subject: [PATCH 022/147] included modeladmin in installed apps --- iogt/settings/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iogt/settings/base.py b/iogt/settings/base.py index 9cacd98bc..6e5d54c06 100644 --- a/iogt/settings/base.py +++ b/iogt/settings/base.py @@ -68,7 +68,7 @@ 'wagtail', 'wagtail.admin', 'wagtail.contrib.forms', - + 'wagtail_modeladmin', 'wagtail.contrib.redirects', 'wagtail.contrib.settings', 'wagtail.documents', From ae3d267c93283ccd7e1e410b3c3e7ffed4746ae1 Mon Sep 17 00:00:00 2001 From: Ankit Chopra Date: Thu, 24 Jul 2025 15:58:04 +0530 Subject: [PATCH 023/147] Added notify and publish button on article and survey --- admin_notifications/wagtail_hooks.py | 3 - home/models.py | 8 +- home/signals.py | 42 --------- home/wagtail_hooks.py | 15 +++ iogt/static/css/user-profile.css | 4 + iogt/static/js/iogt.js | 2 +- iogt/templates/header.html | 53 ++++++----- iogt/templates/sw.js | 48 +++++----- iogt/utils.py | 80 ++++++++++++++++ iogt_users/forms.py | 2 +- iogt_users/views.py | 2 - questionnaires/apps.py | 2 - .../0033_survey_notification_tags.py | 20 ++++ questionnaires/models.py | 8 +- questionnaires/signals.py | 39 -------- questionnaires/wagtail_hooks.py | 19 +++- user_notifications/models.py | 6 +- user_notifications/tasks.py | 92 +++++++++---------- .../notification_dropdown.html | 3 +- .../user_notifications/notification_list.html | 2 +- user_notifications/views.py | 3 +- user_notifications/wagtail_hooks.py | 24 ++--- 22 files changed, 262 insertions(+), 215 deletions(-) create mode 100644 questionnaires/migrations/0033_survey_notification_tags.py delete mode 100644 questionnaires/signals.py diff --git a/admin_notifications/wagtail_hooks.py b/admin_notifications/wagtail_hooks.py index 5d2b17d43..6c4fac2a7 100644 --- a/admin_notifications/wagtail_hooks.py +++ b/admin_notifications/wagtail_hooks.py @@ -14,6 +14,3 @@ class NotificationModelAdmin(ModelAdmin): menu_order = 601 create_view_class = CreateNotificationView -# Register with Wagtail admin -if settings.PUSH_NOTIFICATION: - modeladmin_register(NotificationModelAdmin) diff --git a/home/models.py b/home/models.py index 360d99edb..44bf625fa 100644 --- a/home/models.py +++ b/home/models.py @@ -15,8 +15,8 @@ from django.utils.encoding import force_str from django.utils.translation import gettext_lazy as _ from modelcluster.contrib.taggit import ClusterTaggableManager +from modelcluster.fields import ParentalKey, ParentalManyToManyField from iogt.settings.base import WAGTAIL_CONTENT_LANGUAGES -from modelcluster.fields import ParentalKey from rest_framework import status from taggit.models import TaggedItemBase from wagtail.admin.panels import ( @@ -56,7 +56,7 @@ ) import iogt.iogt_globals as globals_ from django.db.models import Avg, Count -# from user_notifications.tasks import send_signup_notifications +from user_notifications.models import NotificationTag User = get_user_model() logger = logging.getLogger(__name__) @@ -482,7 +482,7 @@ class Article(AbstractArticle): # New fields for precomputed values average_rating = models.FloatField(default=0.0, null=True) number_of_reviews = models.PositiveIntegerField(default=0, null=True) - + notification_tags = ParentalManyToManyField(NotificationTag, blank=True) content_panels = AbstractArticle.content_panels + [ MultiFieldPanel([ InlinePanel('recommended_articles', @@ -492,7 +492,7 @@ class Article(AbstractArticle): ] promote_panels = AbstractArticle.promote_panels + [ - MultiFieldPanel([FieldPanel("tags"), ], heading='Metadata'), + MultiFieldPanel([FieldPanel("tags"), FieldPanel("notification_tags"),], heading='Metadata'), ] edit_handler_list = [ diff --git a/home/signals.py b/home/signals.py index 0afa224ec..886d11c14 100644 --- a/home/signals.py +++ b/home/signals.py @@ -1,12 +1,6 @@ -from urllib.parse import urlparse from django.db.models.signals import post_save, post_delete from django.dispatch import receiver from .models import ArticleFeedback -from wagtail.signals import page_published -from wagtail.models import Site -import os -from .models import Article -from user_notifications.tasks import send_app_notifications @receiver(post_save, sender=ArticleFeedback) @@ -17,39 +11,3 @@ def update_article_feedback_metrics(sender, instance, **kwargs): """ if instance.article: instance.article.update_feedback_metrics() - - -def get_site_for_locale(instance): - """ - Return the Wagtail Site object matching the given locale. - """ - for site in Site.objects.all(): - if site.root_page.locale.language_code == instance.locale.language_code: - if not site: - print("No matching site for locale:", instance.locale) - return - - parsed = urlparse(site.root_url) - hostname = parsed.hostname - scheme = parsed.scheme or "http" - port = os.getenv("DJANGO_RUN_PORT") - if hostname in ("localhost", "127.0.0.1"): - host_with_port = f"{scheme}://{hostname}:{port}" - else: - host_with_port = f"{scheme}://{hostname}" - relative = instance.relative_url(site) - if not relative: - print("Could not get relative URL for instance.") - return - full_url = host_with_port + relative - return full_url - return None - - -@receiver(page_published) -def trigger_article_notification(sender, instance, **kwargs): - if not isinstance(instance, Article): - return - full_url = get_site_for_locale(instance) - send_app_notifications.delay(instance.id, 'article', full_url) - diff --git a/home/wagtail_hooks.py b/home/wagtail_hooks.py index c508f2610..b811c4c41 100644 --- a/home/wagtail_hooks.py +++ b/home/wagtail_hooks.py @@ -23,6 +23,9 @@ from translation_manager.models import TranslationEntry from wagtail.core.signals import page_published from django.dispatch import receiver +from iogt.utils import NotifyAndPublishMenuItem, notify_and_publish_view +from .models import Article +from django.urls import path @hooks.register('after_publish_page') @@ -238,3 +241,15 @@ def create_home_page_banner(sender, instance, **kwargs): parent = parent.get_parent().specific if parent: HomePageBanner.objects.get_or_create(source=parent, banner_page=instance) + + +@hooks.register('register_admin_urls') +def register_custom_form_pages_list_view(): + return [ + path("notify-and-publish//", notify_and_publish_view, name="notify_and_publish"), + ] + + +@hooks.register('register_page_action_menu_item') +def register_notify_and_publish_menu_item(): + return NotifyAndPublishMenuItem(order=100, allowed_models=Article) # \ No newline at end of file diff --git a/iogt/static/css/user-profile.css b/iogt/static/css/user-profile.css index 98ea54269..f245a4d62 100644 --- a/iogt/static/css/user-profile.css +++ b/iogt/static/css/user-profile.css @@ -9,6 +9,10 @@ clear: both } +p.notification-enable { + font-size: 16px; + color: #EE4B2B; +} .profile__icon { background-color: #0070e2; border-radius: 50%; diff --git a/iogt/static/js/iogt.js b/iogt/static/js/iogt.js index 3e70d0550..1b59df4da 100644 --- a/iogt/static/js/iogt.js +++ b/iogt/static/js/iogt.js @@ -258,7 +258,7 @@ const setItem = (key, value) => { const registerPushNotification = (registration) => { if ( !registration.showNotification || - Notification.permission === "denied" || +// Notification.permission === "denied" || !("PushManager" in window) ) { return; diff --git a/iogt/templates/header.html b/iogt/templates/header.html index 04ac25d81..42848a0e9 100644 --- a/iogt/templates/header.html +++ b/iogt/templates/header.html @@ -98,32 +98,35 @@ fetch(url).then(response => response.json()).then(data => { }); } - - function handleNotificationClick(event, element) { - if (element.classList.contains('clicked')) { - return; // no fetch, no preventDefault - } - const notifId = element.getAttribute("data-id"); - const notifUrl = element.getAttribute("href"); - const clickUrlTemplate = "{% url 'user_notifications:mark_notification_clicked' 0 %}"; - const clickUrl = clickUrlTemplate.replace("0", notifId); - - if (notifUrl && notifUrl !== "#") { - event.preventDefault(); - - fetch(clickUrl, { - method: "POST", - headers: { - 'X-CSRFToken': '{{ csrf_token }}', - }, - }).then(() => { - window.location.href = notifUrl; - }).catch(err => { - console.warn("Error marking notification clicked:", err); - window.location.href = notifUrl; - }); - } +function handleNotificationClick(event, element) { + event.preventDefault(); + const notifId = element.getAttribute("data-id"); + const notifUrl = element.getAttribute("data-url"); + if (!notifUrl || notifUrl === "#") { + console.warn("❌ Invalid or missing notification URL:", notifUrl); + return; } + const clickUrlTemplate = "{% url 'user_notifications:mark_notification_clicked' 0 %}"; + const clickUrl = clickUrlTemplate.replace("0", notifId); + element.classList.add('clicked'); + fetch(clickUrl, { + method: "POST", + headers: { + "X-CSRFToken": getCookie("csrftoken"), + }, + }).then(() => { + window.location.href = notifUrl; // or window.open(notifUrl, "_blank"); + }).catch((err) => { + console.error("Error marking as clicked:", err); + window.location.href = notifUrl; + }); +} + +function getCookie(name) { + const value = `; ${document.cookie}`; + const parts = value.split(`; ${name}=`); + if (parts.length === 2) return parts.pop().split(';').shift(); +} diff --git a/iogt/templates/sw.js b/iogt/templates/sw.js index 1df068830..6d12e4693 100644 --- a/iogt/templates/sw.js +++ b/iogt/templates/sw.js @@ -85,6 +85,7 @@ self.addEventListener("notificationclick", function (event) { if (notificationData.notification_id) { fetch(`/notifications/mark-clicked/${notificationData.notification_id}/`, { method: "POST", + "X-CSRFToken": "{{ csrf_token }}", headers: { "Content-Type": "application/json", }, @@ -172,32 +173,29 @@ self.addEventListener("fetch", (event) => { ); return; } - + if (request.method === 'GET') { // ✅ Handle GET Requests (Serve from Cache when Offline) - event.respondWith( - fetch(request.clone(), { cache: "no-store" }) // 1️⃣ Try the network first - .then((networkResponse) => { - // 2️⃣ Optionally save a copy for offline use - // Only cache successful, basic (same‑origin) responses - if (networkResponse.ok && networkResponse.type === "basic") { - caches - .open("iogt") - .then((cache) => cache.put(request, networkResponse.clone())) - .catch((err) => console.warn("❌ Cache put failed", err)); - } - return networkResponse; // 3️⃣ Always return the live response - }) - .catch(() => { - // 4️⃣ Network failed → offline fallback - return caches - .match(request) // • Serve from cache if we have it - .then( - (cached) => - cached || // • …otherwise show a 503 - new Response("Offline", { status: 503 }) - ); - }) - ); + event.respondWith( + fetch(request.clone(), { cache: 'no-store' }) // 1️⃣ Try the network first + .then(networkResponse => { + // 2️⃣ Optionally save a copy for offline use + const responseClone = networkResponse.clone(); // ✅ Clone early + const cacheRequest = new Request(request.url, { method: 'GET' }); + // Only cache successful, basic (same‑origin) responses + if (networkResponse.ok && networkResponse.type === 'basic' && request.method === 'GET') { + caches.open('iogt') + .then(cache => cache.put(cacheRequest, responseClone)) + .catch(err => console.warn('❌ Cache put failed', err)); + } + return networkResponse; // 3️⃣ Always return the live response + }) + .catch(() => { // 4️⃣ Network failed → offline fallback + return caches.match(request) // • Serve from cache if we have it + .then(cached => cached || // • …otherwise show a 503 + new Response('Offline', { status: 503 })); + }) + ); + } // ✅ Handle GET Requests (Serve from Cache when Offline) // event.respondWith( diff --git a/iogt/utils.py b/iogt/utils.py index 7c4fd9132..1954dc596 100644 --- a/iogt/utils.py +++ b/iogt/utils.py @@ -1,5 +1,85 @@ +from django.contrib.admin.views.decorators import staff_member_required from django.conf import settings +from django.shortcuts import get_object_or_404, redirect +from wagtail.admin.action_menu import ActionMenuItem +from django.urls import path, reverse +from django.utils.html import format_html_join, format_html +from questionnaires.models import Survey +from home.models import Article +from wagtail.models import Site, Page +from wagtail.admin import messages +from user_notifications.tasks import send_app_notifications +from wagtail.contrib.modeladmin.helpers import AdminURLHelper def has_md5_hash(name): return bool(settings.HAS_MD5_HASH_REGEX.search(name)) + + +class NotifyAndPublishMenuItem(ActionMenuItem): + label = "Notify & Publish" + name = "notify_and_publish" + + def __init__(self, order=100, allowed_models=None): + super().__init__(order=order) + if allowed_models is None: + self.allowed_models = tuple() + else: + # Handle single class passed directly + self.allowed_models = (allowed_models,) + + def is_shown(self, context): # ✅ Correct for Wagtail 3.2 + page = context.get("page") + return isinstance(getattr(page, "specific", page), self.allowed_models) + + def render_html(self, context): + page = context["page"] + url = reverse("notify_and_publish", args=[page.id]) + return format_html( + '' + ' {}' + '', + url, + self.label, + ) + + +# shared view +@staff_member_required +def notify_and_publish_view(request, page_id): + page = Page.objects.get(id=page_id).specific + revision = page.save_revision(user=request.user) + revision.publish() + if isinstance(page, Survey): + full_url = get_site_for_locale(page) + send_app_notifications.delay(page.id, full_url, 'survey') + messages.success(request, f"Survey '{page.title}' published and notified.") + + elif isinstance(page, Article): + full_url = get_site_for_locale(page) + send_app_notifications.delay(page.id, full_url, 'article') + messages.success(request, f"Article '{page.title}' published and notified.") + + else: + messages.error(request, "Not a valid Survey or Article page.") + + modeladmin_url = AdminURLHelper(type(page)) + return redirect(modeladmin_url.index_url) + + +def get_site_for_locale(instance): + """ + Return the Wagtail Site object matching the given locale. + """ + for site in Site.objects.all(): + if site.root_page.locale.language_code == instance.locale.language_code: + if not site: + print("No matching site for locale:", instance.locale) + return + relative = instance.relative_url(site) + if not relative: + print("Could not get relative URL for instance.") + return + full_url = settings.WAGTAILADMIN_BASE_URL + relative + return full_url + return None \ No newline at end of file diff --git a/iogt_users/forms.py b/iogt_users/forms.py index f49feab44..23e6ce2fa 100644 --- a/iogt_users/forms.py +++ b/iogt_users/forms.py @@ -53,7 +53,7 @@ def save(self, request): # 🔁 Run this logic in background print('user', user) print("Sending task to Celery...") - send_app_notifications.delay(user.id, 'signup') + send_app_notifications.delay(user.id, notification_type='signup') return user def clean_username(self): diff --git a/iogt_users/views.py b/iogt_users/views.py index 298dcb0f7..d05f4740e 100644 --- a/iogt_users/views.py +++ b/iogt_users/views.py @@ -49,8 +49,6 @@ def get_context_data(self, **kwargs): return {'user': self.request.user} - - @method_decorator(login_required, name='dispatch') class UserDetailEditView(UpdateView): model = User diff --git a/questionnaires/apps.py b/questionnaires/apps.py index d69623622..74f07ca2a 100644 --- a/questionnaires/apps.py +++ b/questionnaires/apps.py @@ -4,5 +4,3 @@ class QuestionnairesConfig(AppConfig): name = 'questionnaires' - def ready(self): - import questionnaires.signals # diff --git a/questionnaires/migrations/0033_survey_notification_tags.py b/questionnaires/migrations/0033_survey_notification_tags.py new file mode 100644 index 000000000..3a1840f42 --- /dev/null +++ b/questionnaires/migrations/0033_survey_notification_tags.py @@ -0,0 +1,20 @@ +# Generated by Django 3.2.25 on 2025-07-21 03:58 + +from django.db import migrations +import modelcluster.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('user_notifications', '0007_notificationmeta'), + ('questionnaires', '0032_auto_20250526_0135'), + ] + + operations = [ + migrations.AddField( + model_name='survey', + name='notification_tags', + field=modelcluster.fields.ParentalManyToManyField(blank=True, to='user_notifications.NotificationTag'), + ), + ] diff --git a/questionnaires/models.py b/questionnaires/models.py index 682df84ea..d29013497 100644 --- a/questionnaires/models.py +++ b/questionnaires/models.py @@ -12,6 +12,7 @@ from wagtailmarkdown.blocks import MarkdownBlock from wagtailsvg.edit_handlers import SvgChooserPanel from wagtailsvg.models import Svg +from user_notifications.models import NotificationTag from home.blocks import ( MediaBlock, @@ -25,7 +26,7 @@ collect_urls_from_streamfield, get_all_renditions_urls, ) -from modelcluster.fields import ParentalKey +from modelcluster.fields import ParentalKey, ParentalManyToManyField from wagtail.admin.panels import (FieldPanel, InlinePanel, MultiFieldPanel) from wagtail.contrib.forms.models import (AbstractForm, AbstractFormField, AbstractFormSubmission) @@ -384,6 +385,7 @@ def next_page(self, choice): class Survey(QuestionnairePage, AbstractForm): base_form_class = SurveyForm form_builder = CustomFormBuilder + notification_tags = ParentalManyToManyField(NotificationTag, blank=True) parent_page_types = [ "home.HomePage", "home.Section", "home.Article", "questionnaires.SurveyIndexPage", 'home.FooterIndexPage', @@ -443,7 +445,9 @@ class Survey(QuestionnairePage, AbstractForm): TranslatableField('survey_form_fields'), TranslatableField('thank_you_text') ] - + promote_panels = Page.promote_panels + [ + MultiFieldPanel([FieldPanel("notification_tags"), ], heading='Metadata'), + ] @cached_property def has_page_breaks(self): return any( diff --git a/questionnaires/signals.py b/questionnaires/signals.py deleted file mode 100644 index 810a58757..000000000 --- a/questionnaires/signals.py +++ /dev/null @@ -1,39 +0,0 @@ -from django.dispatch import receiver -from wagtail.signals import page_published -from wagtail.models import Site -from urllib.parse import urlparse -from .models import Survey -from user_notifications.tasks import send_app_notifications -import os - - -def get_site_for_locale(locale): - """ - Return the Wagtail Site object matching the given locale. - """ - for site in Site.objects.all(): - if site.root_page.locale.language_code == locale.language_code: - return site - return None - - -@receiver(page_published) -def trigger_survey_notification(sender, instance, **kwargs): - if not isinstance(instance, Survey): - return - site = get_site_for_locale(instance.locale) - if not site: - print("No matching site for locale:", instance.locale) - return - - parsed = urlparse(site.root_url) - hostname = parsed.hostname - scheme = parsed.scheme or "http" - port = os.getenv("DJANGO_RUN_PORT") - host_with_port = f"{scheme}://{hostname}:{port}" - relative = instance.relative_url(site) - if not relative: - print("Could not get relative URL for instance.") - return - full_url = host_with_port + relative - send_app_notifications.delay(instance.id, 'survey', full_url) \ No newline at end of file diff --git a/questionnaires/wagtail_hooks.py b/questionnaires/wagtail_hooks.py index 383e5d17c..c5fe1fb25 100644 --- a/questionnaires/wagtail_hooks.py +++ b/questionnaires/wagtail_hooks.py @@ -1,12 +1,14 @@ -from django.urls import path -from django.utils.html import format_html_join + +from django.urls import path, reverse +from django.utils.html import format_html_join, format_html from django.templatetags.static import static from wagtail import hooks -from wagtail.models import Locale - +from wagtail.models import Locale, Page from questionnaires.views import FormPagesListView, FormDataPerUserView, generate_dashboard +from questionnaires.models import Survey +from iogt.utils import NotifyAndPublishMenuItem, notify_and_publish_view @hooks.register('insert_editor_js', order=0) def editor_js(): @@ -21,10 +23,19 @@ def editor_js(): return js_includes + + + @hooks.register('register_admin_urls') def register_custom_form_pages_list_view(): return [ path('forms/', FormPagesListView.as_view(), name='index'), path('form-data/', FormDataPerUserView.as_view(), name='form_data_per_user'), path('generate-dashboard//', generate_dashboard, name='generate_dashboard'), + path("notify-and-publish//", notify_and_publish_view, name="notify_and_publish"), ] + + +@hooks.register('register_page_action_menu_item') +def register_notify_and_publish_menu_item(): + return NotifyAndPublishMenuItem(order=100, allowed_models=Survey) # diff --git a/user_notifications/models.py b/user_notifications/models.py index f9397a8f0..6cc8b208f 100644 --- a/user_notifications/models.py +++ b/user_notifications/models.py @@ -6,7 +6,8 @@ from iogt.settings.base import AUTH_USER_MODEL from django.contrib.auth import get_user_model from notifications.models import Notification -@register_snippet + + class UserNotificationTemplate(models.Model): NOTIFICATION_TYPES = [ ("signup", "User Signup"), @@ -66,6 +67,8 @@ def __str__(self): User = get_user_model() + + class NotificationLog(models.Model): STATE_CHOICES = [ ('sent', 'Sent'), @@ -82,6 +85,7 @@ class NotificationLog(models.Model): def __str__(self): return f"{self.notification_key} → {self.user.username} [{self.state}]" + class NotificationMeta(models.Model): notification = models.OneToOneField(Notification, on_delete=models.CASCADE, related_name='meta') is_clicked = models.BooleanField(default=False) diff --git a/user_notifications/tasks.py b/user_notifications/tasks.py index db2f31e18..0c6b4a910 100644 --- a/user_notifications/tasks.py +++ b/user_notifications/tasks.py @@ -11,7 +11,7 @@ @shared_task -def send_app_notifications(id, notification_type, url=None): +def send_app_notifications(id, url=None, notification_type=None): from home.models import Article from questionnaires.models import Survey try: @@ -21,7 +21,6 @@ def send_app_notifications(id, notification_type, url=None): sender = User.objects.get(id=id) notify.send( sender=sender, - url='www.google.com', recipient=sender, verb=template.title, description=template.message @@ -30,61 +29,54 @@ def send_app_notifications(id, notification_type, url=None): user=sender, notification_key=template.title, tags=notification_type, - state="success" + state="sent" ) - elif notification_type == 'article': - sender = Article.objects.get(id=id) - elif notification_type == 'survey': - sender = Survey.objects.get(id=id) except User.DoesNotExist: return + if notification_type=='article': + sender = Article.objects.get(id=id) + elif notification_type == 'survey': + sender = Survey.objects.get(id=id) if notification_type != 'signup': - for notification_preference in NotificationPreference.objects.filter(receive_notifications=True): + article_or_survey_tags_id = list(sender.notification_tags.values_list('id', flat=True)) + for notification_preference in NotificationPreference.objects.filter(receive_notifications=True, content_tags__in=article_or_survey_tags_id).select_related('user').distinct(): try: - if (notification_type.capitalize()) not in list(notification_preference.content_tags.values_list("name", flat=True)): - NotificationLog.objects.create( - user=notification_preference.user, - notification_key=template.title, - tags=notification_type, - state="type" - ) - else: - notify.send( - sender=sender, - url=url, - recipient=notification_preference.user, - verb=template.title, - description=template.message - ) - NotificationLog.objects.create( - user=notification_preference.user, - notification_key=template.title, - tags=notification_type, - state="sent" - ) - notif_instance = Notification.objects.filter(recipient=notification_preference.user).order_by('-timestamp').first() - if not notif_instance: - continue # Shouldn't happen, but guard just in case + notify.send( + sender=sender, + url=url, + recipient=notification_preference.user, + verb=template.title, + description=template.message + ) + NotificationLog.objects.create( + user=notification_preference.user, + notification_key=template.title, + tags=notification_type, + state="sent" + ) + notif_instance = Notification.objects.filter(recipient=notification_preference.user).order_by('-timestamp').first() + if not notif_instance: + continue # Shouldn't happen, but guard just in case - # 3. Avoid duplicate meta creation - try: - NotificationMeta.objects.get_or_create(notification=notif_instance) - except Exception as e: - print(e) - # 4. Send Web Push - try: - send_user_notification( - user=notification_preference.user, - payload={ - "title": template.title, - "body": strip_tags(template.message), - "url": 'www.google.com', - "notification_id": notif_instance.id - }, - ttl=1000) - except Exception as e: - print(e) + # 3. Avoid duplicate meta creation + try: + NotificationMeta.objects.get_or_create(notification=notif_instance) + except Exception as e: + print(e) + # 4. Send Web Push + try: + send_user_notification( + user=notification_preference.user, + payload={ + "title": template.title, + "body": strip_tags(template.message), + "url": url, + "notification_id": notif_instance.id + }, + ttl=1000) + except Exception as e: + print(e) except Exception as e: NotificationLog.objects.create( diff --git a/user_notifications/templates/user_notifications/notification_dropdown.html b/user_notifications/templates/user_notifications/notification_dropdown.html index b6a43f55f..9c7eb45ff 100644 --- a/user_notifications/templates/user_notifications/notification_dropdown.html +++ b/user_notifications/templates/user_notifications/notification_dropdown.html @@ -1,6 +1,7 @@ {% for n in notifications %} {% if n.data.url %} - diff --git a/user_notifications/templates/user_notifications/notification_list.html b/user_notifications/templates/user_notifications/notification_list.html index ab3192429..20ad32ceb 100644 --- a/user_notifications/templates/user_notifications/notification_list.html +++ b/user_notifications/templates/user_notifications/notification_list.html @@ -7,7 +7,7 @@

All Notifications

{% for n in notifications %} {% if n.data.url %} -
diff --git a/user_notifications/views.py b/user_notifications/views.py index b9bd7e615..265da7933 100644 --- a/user_notifications/views.py +++ b/user_notifications/views.py @@ -14,7 +14,8 @@ @login_required def latest_notifications(request): notifications = Notification.objects.filter(recipient=request.user).order_by('-timestamp')[:5] - + for n in notifications: + print('Notification ID:', n.id) meta_map = { meta.notification_id: meta.is_clicked for meta in NotificationMeta.objects.filter(notification__in=notifications) diff --git a/user_notifications/wagtail_hooks.py b/user_notifications/wagtail_hooks.py index 2320d3409..cce204a8f 100644 --- a/user_notifications/wagtail_hooks.py +++ b/user_notifications/wagtail_hooks.py @@ -1,7 +1,7 @@ from wagtail.contrib.modeladmin.options import ( ModelAdmin, ModelAdminGroup, modeladmin_register ) -from .models import NotificationLog, NotificationPreference, NotificationTag +from .models import NotificationLog, NotificationPreference, NotificationTag, UserNotificationTemplate from admin_notifications.wagtail_hooks import NotificationModelAdmin class NotificationTagAdmin(ModelAdmin): @@ -14,7 +14,7 @@ class NotificationTagAdmin(ModelAdmin): class NotificationPreferenceAdmin(ModelAdmin): model = NotificationPreference menu_label = "Notification Preferences" - menu_icon = "bell" + menu_icon = "user" def get_content_tags(self, obj): return ", ".join([tag.name for tag in obj.content_tags.all()]) @@ -25,14 +25,6 @@ def get_content_tags(self, obj): list_filter = ('preferred_language', 'content_tags') - - -# class NotificationsGroup(ModelAdminGroup): -# menu_label = "User Notifications" -# menu_icon = "mail" -# menu_order = 200 -# items = (NotificationTagAdmin, NotificationPreferenceAdmin) - class NotificationLogAdmin(ModelAdmin): model = NotificationLog menu_label = "Notification Logs" @@ -42,6 +34,13 @@ class NotificationLogAdmin(ModelAdmin): search_fields = ("notification_key", "user__username", "user__email", "tags") +class UserNotificationTemplateAdmin(ModelAdmin): + model = UserNotificationTemplate + menu_label = "User Notification Template" + menu_icon = "tag" + list_display = ("title", "message", "active", "updated_at") + + class NotificationsParentGroup(ModelAdminGroup): menu_label = "Notifications" menu_icon = "bell" @@ -49,9 +48,12 @@ class NotificationsParentGroup(ModelAdminGroup): NotificationTagAdmin, NotificationPreferenceAdmin, NotificationModelAdmin, - NotificationLogAdmin + NotificationLogAdmin, + UserNotificationTemplateAdmin ) + + # class NotificationPreferenceAdmin(ModelAdmin): # model = NotificationPreference # menu_label = "Notification Preferences" From 77d39b00bafa173e39492f6591c161d8c690437a Mon Sep 17 00:00:00 2001 From: Ankit Chopra Date: Mon, 28 Jul 2025 11:18:37 +0530 Subject: [PATCH 024/147] added checkbox --- iogt/static/css/accounts.css | 36 +++++ iogt/static/css/iogt.css | 5 +- iogt_users/templates/user_notification.html | 137 ++++++++++++++------ requirements.dev.in | 1 - user_notifications/views.py | 2 +- 5 files changed, 138 insertions(+), 43 deletions(-) diff --git a/iogt/static/css/accounts.css b/iogt/static/css/accounts.css index 21f90ba07..2cfc7691b 100644 --- a/iogt/static/css/accounts.css +++ b/iogt/static/css/accounts.css @@ -95,3 +95,39 @@ form input[type="checkbox"] { font-weight: 500; line-height: 14px; } + .multiselect-dropdown { + position: relative; + width: 540px; + user-select: none; + } + + .dropdown-btn { + padding: 10px; + border: 1px solid #ccc; + background: #fff; + cursor: pointer; + border-radius: 5px; + } + + .dropdown-content { + display: none; + position: absolute; + background-color: white; + border: 1px solid #ccc; + border-top: none; + max-height: 200px; + overflow-y: auto; + z-index: 1000; + width: 100%; + border-radius: 0 0 5px 5px; + } + + .dropdown-content label { + display: block; + padding: 8px 10px; + cursor: pointer; + } + + .dropdown-content label:hover { + background-color: #f0f0f0; + } diff --git a/iogt/static/css/iogt.css b/iogt/static/css/iogt.css index f1a00457d..b43454acc 100644 --- a/iogt/static/css/iogt.css +++ b/iogt/static/css/iogt.css @@ -2205,8 +2205,9 @@ } .load-more a, button{ + margin:10px; font-size: 14px; - line-height: 20px; + line-height: 10px; font-weight: 600; border-radius: 24px; padding: 12px 16px; @@ -2214,7 +2215,7 @@ color: #303030; display: block; text-align: center; - width: 100%; + width: 20%; cursor: pointer; transition: all 0.2s linear; text-decoration: none; diff --git a/iogt_users/templates/user_notification.html b/iogt_users/templates/user_notification.html index aa6dd2057..3c68e4643 100644 --- a/iogt_users/templates/user_notification.html +++ b/iogt_users/templates/user_notification.html @@ -8,9 +8,16 @@ {% if request.user.is_authenticated %}

{% translate "Notification Preference" %}

{% translate "Would you like to enable notifications?" %} - - + + + +
- - +
+ + +
{% endif %} @@ -56,27 +70,63 @@

{% translate "Notification Preference" %}

{% endblock %} \ No newline at end of file diff --git a/requirements.dev.in b/requirements.dev.in index 29e871ed5..29ca2f43f 100644 --- a/requirements.dev.in +++ b/requirements.dev.in @@ -10,4 +10,3 @@ selenium==4.9.1 wagtail-factories django-notifications-hq==1.8.3 celery==5.3.6 -backports.zoneinfo; python_version < "3.9" diff --git a/user_notifications/views.py b/user_notifications/views.py index 265da7933..3d3fe8f2e 100644 --- a/user_notifications/views.py +++ b/user_notifications/views.py @@ -73,7 +73,7 @@ def unread_count(request): def save_notification_preference(request): if request.method == "POST" and request.user.is_authenticated: data = json.loads(request.body) - choice = data.get("choice") # "yes" or "no" + choice = data.get("preference") # "yes" or "no" language = data.get('language', 'en') tag_ids = data.get('tags', []) From d817983f0b3f755c1b419fe53b18f9e6b885712f Mon Sep 17 00:00:00 2001 From: Shubham Goel <130149461+shubhamgoel02@users.noreply.github.com> Date: Mon, 28 Jul 2025 15:56:09 +0530 Subject: [PATCH 025/147] 3.0.8-rc.3 --- iogt/settings/production.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iogt/settings/production.py b/iogt/settings/production.py index bb2ab3719..f7b08c5d8 100644 --- a/iogt/settings/production.py +++ b/iogt/settings/production.py @@ -33,7 +33,7 @@ }, } -SITE_VERSION = '3.0.7' +SITE_VERSION = '3.0.8-rc.3' try: from .local import * From b21741bc970c16f8285638b3d50fb6b7e613b676 Mon Sep 17 00:00:00 2001 From: Sachin Mehta Date: Mon, 28 Jul 2025 11:00:52 +0000 Subject: [PATCH 026/147] Notifications post demo changes --- home/static/css/global/global.css | 26 ++ iogt/static/css/accounts.css | 3 +- iogt/static/css/user-profile.css | 3 +- iogt/static/js/iogt-no-jquery.js | 11 +- iogt/static/js/iogt.js | 13 +- iogt/static/js/sw-init.js | 2 - iogt/templates/sw.js | 2 - iogt_users/templates/user_notification.html | 264 +++++++++++--------- iogt_users/views.py | 1 - 9 files changed, 197 insertions(+), 128 deletions(-) diff --git a/home/static/css/global/global.css b/home/static/css/global/global.css index 2d5e291c7..c25803f0d 100644 --- a/home/static/css/global/global.css +++ b/home/static/css/global/global.css @@ -1339,6 +1339,32 @@ body.rtl { margin-left: 12px; } +.notification_language select { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + width: 100%; +} + +.notification_language { + position: relative; + width: 100%; + max-width: 100%; +} + +.notification_language::after { + content: ""; + position: absolute; + top: 50%; + right: 12px; + transform: translateY(-50%); + pointer-events: none; + + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-top: 6px solid #555; +} + .language__select select { -webkit-appearance: none; -moz-appearance: none; diff --git a/iogt/static/css/accounts.css b/iogt/static/css/accounts.css index 2cfc7691b..12003b03d 100644 --- a/iogt/static/css/accounts.css +++ b/iogt/static/css/accounts.css @@ -73,6 +73,7 @@ form input[type="checkbox"] { .profile-form__btn { margin-bottom: 8px; + margin-left: 0px; } .profile-form__btn:last-child { @@ -130,4 +131,4 @@ form input[type="checkbox"] { .dropdown-content label:hover { background-color: #f0f0f0; - } + } \ No newline at end of file diff --git a/iogt/static/css/user-profile.css b/iogt/static/css/user-profile.css index f245a4d62..552916828 100644 --- a/iogt/static/css/user-profile.css +++ b/iogt/static/css/user-profile.css @@ -51,7 +51,8 @@ p.notification-enable { } .profile-form__btn { - margin-bottom: 8px + margin-bottom: 8px; + margin-left: 0px; } .profile-form__btn:last-child { diff --git a/iogt/static/js/iogt-no-jquery.js b/iogt/static/js/iogt-no-jquery.js index 60448db88..f2492e0b2 100644 --- a/iogt/static/js/iogt-no-jquery.js +++ b/iogt/static/js/iogt-no-jquery.js @@ -266,9 +266,16 @@ const setItem = (key, value) => { const registerPushNotification = (registration) => { if (!registration.showNotification) return; - if (Notification.permission === "denied") return; if (!"PushManager" in window) return; - subscribe(registration); + if (Notification.permission === "default") { + Notification.requestPermission(function (permission) { + if (permission === "granted") { + subscribe(registration); + } + }); + } else if (Notification.permission === "granted") { + subscribe(registration); + } }; const urlB64ToUint8Array = (base64String) => { diff --git a/iogt/static/js/iogt.js b/iogt/static/js/iogt.js index 1b59df4da..a35e3260f 100644 --- a/iogt/static/js/iogt.js +++ b/iogt/static/js/iogt.js @@ -258,12 +258,21 @@ const setItem = (key, value) => { const registerPushNotification = (registration) => { if ( !registration.showNotification || -// Notification.permission === "denied" || !("PushManager" in window) ) { return; } - subscribe(registration); + + // Ask permission first if needed + if (Notification.permission === "default") { + Notification.requestPermission().then(permission => { + if (permission === "granted") { + subscribe(registration); // Now safe to subscribe + } + }); + } else if (Notification.permission === "granted") { + subscribe(registration); // Already granted + } }; const urlB64ToUint8Array = (base64String) => { diff --git a/iogt/static/js/sw-init.js b/iogt/static/js/sw-init.js index d4e5b322c..40c23d174 100644 --- a/iogt/static/js/sw-init.js +++ b/iogt/static/js/sw-init.js @@ -29,10 +29,8 @@ const registerSW = async () => { const registration = await navigator.serviceWorker.register(serviceWorkerURL, {scope: '/'}); const isPushNotificationRegistered = getItem('isPushNotificationRegistered', false); - console.log('isPushNotificationRegistered', isPushNotificationRegistered) if (!isPushNotificationRegistered) { if (isAuthenticated && pushNotification) { - console.log('sending push not') registerPushNotification(registration); } } diff --git a/iogt/templates/sw.js b/iogt/templates/sw.js index 6d12e4693..54e266149 100644 --- a/iogt/templates/sw.js +++ b/iogt/templates/sw.js @@ -114,8 +114,6 @@ self.addEventListener("notificationclick", function (event) { self.addEventListener("fetch", (event) => { const { request } = event; - console.log("🔎 Fetch event triggered:", request.url, request.method); - // ✅ Handle POST Requests (Save to IndexedDB if offline) if (request.method === "POST") { event.respondWith( diff --git a/iogt_users/templates/user_notification.html b/iogt_users/templates/user_notification.html index 3c68e4643..b300a2b1b 100644 --- a/iogt_users/templates/user_notification.html +++ b/iogt_users/templates/user_notification.html @@ -5,153 +5,181 @@ {% block content %} -{% if request.user.is_authenticated %} -

{% translate "Notification Preference" %}

-
{% translate "Would you like to enable notifications?" %} - -  
- -  
- - - - - -
- - - - -
- +{% if request.user.is_authenticated %} +

{% translate "Notification Preference" %}

+
+ {% translate "Do you want to receive notifications?" %} +
+
+
+
+
+ +
+ +
+ + +
+
+
+ +
+ {% endif %} + {% endblock %} \ No newline at end of file diff --git a/iogt_users/views.py b/iogt_users/views.py index d05f4740e..e90cd5f66 100644 --- a/iogt_users/views.py +++ b/iogt_users/views.py @@ -23,7 +23,6 @@ class UserNotificationView(TemplateView): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) - print('authenticated_user', self.request.user.is_authenticated) if self.request.user.is_authenticated: notification_pref = NotificationPreference.objects.filter(user=self.request.user).first() context['notification_preference'] = notification_pref From 77239a28526bd0699dc5abcb701f5cb1cf32ccd1 Mon Sep 17 00:00:00 2001 From: Ankit-lab809 Date: Wed, 30 Jul 2025 08:31:02 +0530 Subject: [PATCH 027/147] Shown call out at notification symbol and also sent artcile/survey name --- admin_notifications/views.py | 66 +++++++++++++-------- home/models.py | 7 ++- home/static/css/global/global.css | 12 +++- home/templates/home/home_page.html | 6 ++ iogt/templates/base.html | 2 +- iogt_users/templates/user_notification.html | 1 + user_notifications/tasks.py | 4 +- user_notifications/wagtail_hooks.py | 22 ++++++- 8 files changed, 88 insertions(+), 32 deletions(-) diff --git a/admin_notifications/views.py b/admin_notifications/views.py index df7a687e0..4da040814 100644 --- a/admin_notifications/views.py +++ b/admin_notifications/views.py @@ -1,5 +1,5 @@ import json -from user_notifications.models import NotificationMeta +from user_notifications.models import NotificationMeta, NotificationLog from wagtail.contrib.modeladmin.views import CreateView from webpush import send_user_notification from notifications.signals import notify @@ -12,31 +12,47 @@ def form_valid(self, form): groups = payload.pop('groups') for group in groups: for user in group.user_set.all(): - # 1. Create Notification - notify.send( - sender=self.request.user, - recipient=user, - verb=payload.get('head', 'New Notification'), - description=payload.get('body', ''), - url=payload.get("url", "/") - ) + try: + # 1. Create Notification + notify.send( + sender=self.request.user, + recipient=user, + verb=payload.get('head', 'New Notification'), + description=payload.get('body', ''), + url=payload.get("url", "/") + ) - # 2. Get latest Notification for user (created just now) - notif_instance = Notification.objects.filter(recipient=user).order_by('-timestamp').first() - if not notif_instance: - continue # Shouldn't happen, but guard just in case + # 2. Get latest Notification for user (created just now) + notif_instance = Notification.objects.filter(recipient=user).order_by('-timestamp').first() + if not notif_instance: + continue # Shouldn't happen, but guard just in case - # 3. Avoid duplicate meta creation - NotificationMeta.objects.get_or_create(notification=notif_instance) + # 3. Avoid duplicate meta creation + NotificationMeta.objects.get_or_create(notification=notif_instance) - # 4. Send Web Push - send_user_notification( - user=user, - payload={ - "title": payload.get("head", "IoGT Notification"), - "body": payload.get("body", ""), - "url": payload.get("url", "/"), - "notification_id": notif_instance.id - }, - ttl=1000) + # 4. Send Web Push + send_user_notification( + user=user, + payload={ + "title": payload.get("head", "IoGT Notification"), + "body": payload.get("body", ""), + "url": payload.get("url", "/"), + "notification_id": notif_instance.id + }, + ttl=1000) + NotificationLog.objects.create( + user=user, + notification_key=payload.get("head", "IoGT Notification"), + tags='', + state="sent" + ) + except Exception as e: + # Optional: log failure for user if user or template not found + NotificationLog.objects.create( + user=user, + notification_key=payload.get("head", "IoGT Notification"), + tags='', + state="failed", + error_message=f"Task failure: {str(e)}" + ) return super().form_valid(form) diff --git a/home/models.py b/home/models.py index 44bf625fa..0e2abff16 100644 --- a/home/models.py +++ b/home/models.py @@ -56,7 +56,7 @@ ) import iogt.iogt_globals as globals_ from django.db.models import Avg, Count -from user_notifications.models import NotificationTag +from user_notifications.models import NotificationTag, NotificationPreference User = get_user_model() logger = logging.getLogger(__name__) @@ -126,6 +126,11 @@ def get_context(self, request): ): banners.append(banner_specific) context['banners'] = banners + show_notification_nudge = False + if request.user and request.user.is_authenticated: + pref = NotificationPreference.objects.filter(user=request.user).first() + context["notification_preference"] = pref + context['user'] = request.user return context @property def offline_urls(self): diff --git a/home/static/css/global/global.css b/home/static/css/global/global.css index c25803f0d..c739f79f2 100644 --- a/home/static/css/global/global.css +++ b/home/static/css/global/global.css @@ -2154,7 +2154,7 @@ body.rtl { } /* Close Button */ -.close-btn { +.notification-close-btn { background: transparent; border: none; font-size: 36px; @@ -2277,4 +2277,14 @@ div.notification-confirmation{ margin-bottom: 10px; display: flex; align-items: center; +} + + +.notification-callout-text { + background-color: #eaf7ff; + color: #0c5460; + font-size: 13px; + padding: 4px 8px; + margin-top: 5px; + border-radius: 4px; } \ No newline at end of file diff --git a/home/templates/home/home_page.html b/home/templates/home/home_page.html index 99c3ffaba..377b2e063 100644 --- a/home/templates/home/home_page.html +++ b/home/templates/home/home_page.html @@ -9,6 +9,12 @@ {% block content %}
+ {% if user.is_authenticated and not notification_preference.receive_notifications %} + + {% endif %} {% include 'home/tags/banners_list.html' with banners=banners %}
{% if page.home_featured_content %} diff --git a/iogt/templates/base.html b/iogt/templates/base.html index c97941291..5a19c9836 100644 --- a/iogt/templates/base.html +++ b/iogt/templates/base.html @@ -108,7 +108,7 @@

Notifications

- +
diff --git a/iogt_users/templates/user_notification.html b/iogt_users/templates/user_notification.html index b300a2b1b..8cdc13433 100644 --- a/iogt_users/templates/user_notification.html +++ b/iogt_users/templates/user_notification.html @@ -111,6 +111,7 @@

{% translate "Notification Preference" %}

const masterCheckbox = document.getElementById("select-all"); const checkboxes = document.querySelectorAll('.tag-checkbox'); checkboxes.forEach(cb => cb.checked = masterCheckbox.checked); + updateSelectedTopicLabel(); } function setNotificationPref() { diff --git a/user_notifications/tasks.py b/user_notifications/tasks.py index 0c6b4a910..494ca8897 100644 --- a/user_notifications/tasks.py +++ b/user_notifications/tasks.py @@ -46,7 +46,7 @@ def send_app_notifications(id, url=None, notification_type=None): sender=sender, url=url, recipient=notification_preference.user, - verb=template.title, + verb=f"{sender.title} {template.title}", description=template.message ) NotificationLog.objects.create( @@ -69,7 +69,7 @@ def send_app_notifications(id, url=None, notification_type=None): send_user_notification( user=notification_preference.user, payload={ - "title": template.title, + "title": f"{sender.title} {template.title}", "body": strip_tags(template.message), "url": url, "notification_id": notif_instance.id diff --git a/user_notifications/wagtail_hooks.py b/user_notifications/wagtail_hooks.py index cce204a8f..783dc60e0 100644 --- a/user_notifications/wagtail_hooks.py +++ b/user_notifications/wagtail_hooks.py @@ -30,8 +30,26 @@ class NotificationLogAdmin(ModelAdmin): menu_label = "Notification Logs" menu_icon = "list-ul" # Wagtail icon name menu_order = 200 - list_display = ("notification_key", "user", "state", "tags", "received_at") - search_fields = ("notification_key", "user__username", "user__email", "tags") + list_display = ("notification_key", "user", "state", "get_notification_url", "get_is_clicked", "tags", "received_at") + search_fields = ("notification_key", "user__username", "user__email", "tags", "get_notification_url") + + def get_is_clicked(self, obj): + try: + return obj.notification.meta.is_clicked + except AttributeError: + return False # or 'N/A' if you prefer + + get_is_clicked.boolean = True # shows a checkmark in admin + get_is_clicked.short_description = 'Is Clicked' + + def get_notification_url(self, obj): + try: + url = obj.notification.data["url"] + return url + except AttributeError: + return "" + get_notification_url.short_description = "Target URL" + class UserNotificationTemplateAdmin(ModelAdmin): From 0a9b1125312fc2e3e5a18d3963a07040fee5b4af Mon Sep 17 00:00:00 2001 From: Sachin Mehta Date: Wed, 30 Jul 2025 08:27:11 +0000 Subject: [PATCH 028/147] notifications demo feedback completed --- admin_notifications/views.py | 6 +- home/static/css/global/global.css | 94 +++++++++-- home/templates/home/home_page.html | 5 +- home/templatetags/clean_html.py | 9 ++ iogt/templates/header.html | 21 ++- iogt_users/templates/user_notification.html | 7 +- user_notifications/models.py | 2 +- user_notifications/tasks.py | 146 +++++++++--------- .../notification_dropdown.html | 35 +++-- .../user_notifications/notification_list.html | 48 +++--- user_notifications/wagtail_hooks.py | 23 ++- 11 files changed, 257 insertions(+), 139 deletions(-) create mode 100644 home/templatetags/clean_html.py diff --git a/admin_notifications/views.py b/admin_notifications/views.py index 4da040814..ba266905d 100644 --- a/admin_notifications/views.py +++ b/admin_notifications/views.py @@ -44,7 +44,8 @@ def form_valid(self, form): user=user, notification_key=payload.get("head", "IoGT Notification"), tags='', - state="sent" + state="sent", + notification=notif_instance ) except Exception as e: # Optional: log failure for user if user or template not found @@ -53,6 +54,7 @@ def form_valid(self, form): notification_key=payload.get("head", "IoGT Notification"), tags='', state="failed", - error_message=f"Task failure: {str(e)}" + error_message=f"Task failure: {str(e)}", + notification=None ) return super().form_valid(form) diff --git a/home/static/css/global/global.css b/home/static/css/global/global.css index c739f79f2..f61ab1ed1 100644 --- a/home/static/css/global/global.css +++ b/home/static/css/global/global.css @@ -1339,6 +1339,38 @@ body.rtl { margin-left: 12px; } +.notification-bell-wrapper { + position: relative; + display: inline-block; +} + +.notification-bell { + font-size: 1.5rem; + transition: color 0.3s ease; + color: #FDD256; +} + +.notification-bell.highlighted { + color: #007bff !important; /* blue glow */ +} + +.notif-badge { + position: absolute; + top: -8px; + right: -8px; + background-color: red; + color: white; + border-radius: 50%; + padding: 2px 6px; + font-size: 0.7rem; + font-weight: bold; + display: inline-block; + line-height: 1; + min-width: 16px; + text-align: center; + box-shadow: 0 0 4px rgba(0, 0, 0, 0.3); +} + .notification_language select { -webkit-appearance: none; -moz-appearance: none; @@ -2147,19 +2179,19 @@ body.rtl { display: flex; justify-content: space-between; align-items: center; - padding: 0px 20px; border-bottom: 1px solid #e0e0e0; font-size: 16px; font-weight: 600; + margin-bottom: 10px; } /* Close Button */ .notification-close-btn { background: transparent; border: none; - font-size: 36px; - margin-top: 36px; + font-size: 20px; cursor: pointer; + width: 20%; } .notification-list { @@ -2170,24 +2202,22 @@ body.rtl { .notification-item { display: block; width: 100%; - padding: 12px 16px; + padding: 1rem; text-decoration: none; color: inherit; border-bottom: 1px solid #e6e6e6; - background-color: white; + border-radius: 8px; transition: background 0.2s ease; box-sizing: border-box; + background-color: #f0f8ff; + margin-bottom: 5px; + box-shadow: 0 1px 4px rgba(0,0,0,0.05); } .notification-item:hover { background-color: #f1f5fa; } -.notification-item.unread, .notification-item.not_clicked { - background-color: #e9f3ff !important; /* Light blue for unread */ - font-weight: 600 !important; -} - .notification-item.read { background-color: #fff; font-weight: normal; @@ -2196,19 +2226,19 @@ body.rtl { .notification-body { margin: 0; padding: 0; + display: flex; + align-items: center; + justify-content: space-between; } .notification-text { margin: 0; font-size: 0.8rem; - line-height: 1.4; } .notification-title { font-weight: 600; font-size: 0.85rem; - color: #000; - margin-bottom: 4px; } .notification-empty { @@ -2246,7 +2276,6 @@ body.rtl { background-color: #007bff; /* Bootstrap primary blue */ border-radius: 50%; margin-left: 8px; - vertical-align: middle; } @media (max-width: 768px) { @@ -2287,4 +2316,41 @@ div.notification-confirmation{ padding: 4px 8px; margin-top: 5px; border-radius: 4px; +} + +.enable-notifications-nudge { + position: fixed; + bottom: 20px; + left: 20px; + background-color: #fff8e1; + color: #333; + border-left: 5px solid goldenrod; + box-shadow: 0 4px 8px rgba(0,0,0,0.15); + padding: 15px 10px; + border-radius: 8px; + display: flex; + align-items: center; + gap: 10px; + z-index: 9999; + font-family: "Segoe UI", sans-serif; + animation: slideIn 0.5s ease-out; + margin-right: 15px; +} + +.notification-toast a { + color: #007bff; + text-decoration: underline; + font-weight: 500; + cursor: pointer; +} + +@keyframes slideIn { + from { + transform: translateX(100%); + opacity: 0; + } + to { + transform: translateX(0%); + opacity: 1; + } } \ No newline at end of file diff --git a/home/templates/home/home_page.html b/home/templates/home/home_page.html index 377b2e063..268f0e3c8 100644 --- a/home/templates/home/home_page.html +++ b/home/templates/home/home_page.html @@ -10,9 +10,8 @@ {% block content %}
{% if user.is_authenticated and not notification_preference.receive_notifications %} -
- 🔔 This app wants your permission to enable notifications. - Enable Notifications +
+ 🔔 IOGT wants your permission to enable notifications
{% endif %} {% include 'home/tags/banners_list.html' with banners=banners %} diff --git a/home/templatetags/clean_html.py b/home/templatetags/clean_html.py new file mode 100644 index 000000000..040347ea8 --- /dev/null +++ b/home/templatetags/clean_html.py @@ -0,0 +1,9 @@ +from django import template +from bs4 import BeautifulSoup + +register = template.Library() + +@register.filter +def strip_html(value): + soup = BeautifulSoup(value, "html.parser") + return soup.get_text(separator=" ", strip=True) diff --git a/iogt/templates/header.html b/iogt/templates/header.html index 42848a0e9..83b3377fa 100644 --- a/iogt/templates/header.html +++ b/iogt/templates/header.html @@ -18,8 +18,11 @@
{% if request.user.is_authenticated %}
-
- 🔔 {{ request.user.notifications.unread.count }} +
+
+ + +
{% endif %} @@ -58,12 +61,14 @@ .then(res => res.json()) .then(data => { const countEl = document.getElementById("notif-count"); + const bell = document.getElementById("notif-bell"); if (data.unread_count > 0) { - countEl.textContent = data.unread_count; - countEl.style.display = "inline"; + countEl.innerText = data.unread_count > 99 ? "99+" : data.unread_count; + countEl.style.display = "inline-block"; + bell.classList.add("highlighted"); } else { - countEl.textContent = ''; countEl.style.display = "none"; + bell.classList.remove("highlighted"); } }) .catch(err => console.warn("⚠️ Failed to fetch unread count", err)); @@ -96,7 +101,9 @@ ids.forEach(id => query.append('ids[]', id)); const url = `{% url 'user_notifications:mark_selected_read' %}?${query.toString()}`; - fetch(url).then(response => response.json()).then(data => { }); + fetch(url).then(response => response.json()).then(data => { + refreshUnreadCount(); + }); } function handleNotificationClick(event, element) { event.preventDefault(); @@ -112,7 +119,7 @@ fetch(clickUrl, { method: "POST", headers: { - "X-CSRFToken": getCookie("csrftoken"), + "X-CSRFToken": "{{ csrf_token }}", }, }).then(() => { window.location.href = notifUrl; // or window.open(notifUrl, "_blank"); diff --git a/iogt_users/templates/user_notification.html b/iogt_users/templates/user_notification.html index 8cdc13433..ec345ffbf 100644 --- a/iogt_users/templates/user_notification.html +++ b/iogt_users/templates/user_notification.html @@ -133,7 +133,7 @@

{% translate "Notification Preference" %}

if ("Notification" in window && Notification.permission !== "granted") { Notification.requestPermission().then(permission => { if (permission !== "granted") { - showToast("🔕 Web Push Notifications not enabled. You can still use the app without them.", "info"); + showToast("🔕 Web Push Notifications are off. You can enable them from your browser settings. You'll still receive in-app notifications.", "warning"); } }); } @@ -157,9 +157,10 @@

{% translate "Notification Preference" %}

}), }).then((res) => { if (res.ok) { - if ("Notification" in window && Notification.permission !== "granted") { + //Add delay to show it as another toast will be showing up for permission + if (preference && "Notification" in window && Notification.permission !== "granted") { setTimeout(() => { - showToast("✅ Preferences saved successfully.", "success"); + showToast("✅ Preference saved successfully.", "success"); }, 3500); } else { diff --git a/user_notifications/models.py b/user_notifications/models.py index 6cc8b208f..89bb38327 100644 --- a/user_notifications/models.py +++ b/user_notifications/models.py @@ -74,7 +74,7 @@ class NotificationLog(models.Model): ('sent', 'Sent'), ('failed', 'Failed'), ] - + notification = models.OneToOneField(Notification, null=True, blank=True, on_delete=models.SET_NULL, related_name='logs') user = models.ForeignKey(User, on_delete=models.CASCADE) notification_key = models.CharField(max_length=255) # e.g. template slug or key state = models.CharField(max_length=20, choices=STATE_CHOICES, default='sent') diff --git a/user_notifications/tasks.py b/user_notifications/tasks.py index 494ca8897..3016053d8 100644 --- a/user_notifications/tasks.py +++ b/user_notifications/tasks.py @@ -15,83 +15,79 @@ def send_app_notifications(id, url=None, notification_type=None): from home.models import Article from questionnaires.models import Survey try: - try: - template = UserNotificationTemplate.objects.filter(active=True, type=notification_type).latest("updated_at") - if notification_type == 'signup' or notification_type == 'web_push': - sender = User.objects.get(id=id) - notify.send( + template = UserNotificationTemplate.objects.filter(active=True, type=notification_type).latest("updated_at") + if notification_type in ['signup', 'web_push']: + sender = User.objects.get(id=id) + notify.send( + sender=sender, + recipient=sender, + verb=template.title, + description=template.message + ) + notif_instance = Notification.objects.filter( + recipient=notification_preference.user + ).order_by('-timestamp').first() + NotificationLog.objects.create( + user=sender, + notification_key=template.title, + tags=notification_type, + state="sent", + notification=notif_instance + ) + return + except Exception as e: + return + if notification_type=='article': + sender = Article.objects.get(id=id) + elif notification_type == 'survey': + sender = Survey.objects.get(id=id) + + if notification_type != 'signup': + article_or_survey_tags_id = list(sender.notification_tags.values_list('id', flat=True)) + for notification_preference in NotificationPreference.objects.filter( + receive_notifications=True, + content_tags__in=article_or_survey_tags_id + ).select_related('user').distinct(): + try: + notify.send( sender=sender, - recipient=sender, - verb=template.title, + url=url, + recipient=notification_preference.user, + verb=f"{template.title}", description=template.message ) - NotificationLog.objects.create( - user=sender, - notification_key=template.title, - tags=notification_type, - state="sent" - ) - except User.DoesNotExist: - return - if notification_type=='article': - sender = Article.objects.get(id=id) - elif notification_type == 'survey': - sender = Survey.objects.get(id=id) - if notification_type != 'signup': - article_or_survey_tags_id = list(sender.notification_tags.values_list('id', flat=True)) - for notification_preference in NotificationPreference.objects.filter(receive_notifications=True, content_tags__in=article_or_survey_tags_id).select_related('user').distinct(): - try: - notify.send( - sender=sender, - url=url, - recipient=notification_preference.user, - verb=f"{sender.title} {template.title}", - description=template.message - ) - NotificationLog.objects.create( - user=notification_preference.user, - notification_key=template.title, - tags=notification_type, - state="sent" - ) - notif_instance = Notification.objects.filter(recipient=notification_preference.user).order_by('-timestamp').first() - if not notif_instance: - continue # Shouldn't happen, but guard just in case - - # 3. Avoid duplicate meta creation - try: - NotificationMeta.objects.get_or_create(notification=notif_instance) - except Exception as e: - print(e) - # 4. Send Web Push - try: - send_user_notification( - user=notification_preference.user, - payload={ - "title": f"{sender.title} {template.title}", - "body": strip_tags(template.message), - "url": url, - "notification_id": notif_instance.id - }, - ttl=1000) - except Exception as e: - print(e) + notif_instance = Notification.objects.filter( + recipient=notification_preference.user + ).order_by('-timestamp').first() + + NotificationLog.objects.create( + user=notification_preference.user, + notification_key=template.title, + tags=notification_type, + state="sent", + notification=notif_instance + ) - except Exception as e: - NotificationLog.objects.create( - user=notification_preference.user, - notification_key=template.title, - tags=notification_type, - state="failed", - error_message=str(e) - ) - except Exception as e: - # Optional: log failure for user if user or template not found - NotificationLog.objects.create( - user_id=sender, - notification_key=template.title, - tags=notification_type, - state="failed", - error_message=f"Task failure: {str(e)}" - ) \ No newline at end of file + # 3. Avoid duplicate meta creation + NotificationMeta.objects.get_or_create(notification=notif_instance) + + # 4. Send Web Push + send_user_notification( + user=notification_preference.user, + payload={ + "title": f"{template.title}", + "body": strip_tags(template.message), + "url": url, + "notification_id": notif_instance.id + }, + ttl=1000 + ) + except Exception as e: + NotificationLog.objects.create( + user=notification_preference.user, + notification_key=template.title, + tags=notification_type, + state="failed", + error_message=str(e) + ) \ No newline at end of file diff --git a/user_notifications/templates/user_notifications/notification_dropdown.html b/user_notifications/templates/user_notifications/notification_dropdown.html index 9c7eb45ff..05a19b7cc 100644 --- a/user_notifications/templates/user_notifications/notification_dropdown.html +++ b/user_notifications/templates/user_notifications/notification_dropdown.html @@ -1,3 +1,4 @@ +{% load clean_html %} {% for n in notifications %} {% if n.data.url %}
-

+

{{ n.verb }} {% if not n.is_clicked %}{% endif %}

-

- {{ n.description | safe }} -

- {{ n.timestamp|timesince }} ago + {{ n.timestamp|timesince }} ago
+

{{ n.description|strip_html }}

+ {% if n.actor.notification_tags.all %} +

+ Topic(s): + {% for tag in n.actor.notification_tags.all %} + {{ tag.name }}{% if not forloop.last %}, {% endif %} + {% endfor %} +

+ {% endif %}
{% else %}
-

+

{{ n.verb }}

-

- {{ n.description | safe}} -

- {{ n.timestamp|timesince }} ago + {{ n.timestamp|timesince }} ago
+

+ {{ n.description|strip_html }} +

+ {% if n.actor.notification_tags.all %} +

+ Topic(s): + {% for tag in n.actor.notification_tags.all %} + {{ tag.name }}{% if not forloop.last %}, {% endif %} + {% endfor %} +

+ {% endif %}
{% endif %} {% empty %} diff --git a/user_notifications/templates/user_notifications/notification_list.html b/user_notifications/templates/user_notifications/notification_list.html index 20ad32ceb..97d59b171 100644 --- a/user_notifications/templates/user_notifications/notification_list.html +++ b/user_notifications/templates/user_notifications/notification_list.html @@ -1,6 +1,6 @@ {% extends "base.html" %} {% block content %} - +{% load clean_html %}

All Notifications

@@ -11,29 +11,41 @@

All Notifications

class="notification-item {% if n.unread %} unread {% else %} read {% endif %} {% if n.is_clicked %} clicked {% else %} not_clicked {% endif %}" data-id="{{ n.id }}" onclick="handleNotificationClick(event, this)">
-

- {{ n.verb }} - {% if not n.is_clicked %}{% endif %} -

-

- {{ n.description | safe }} -

- {{ n.timestamp|timesince }} ago +

+ {{ n.verb }} + {% if not n.is_clicked %}{% endif %} +

+ {{ n.timestamp|timesince }} ago
- +

{{ n.description|strip_html }}

+ {% if n.actor.notification_tags.all %} +

+ Topic(s): + {% for tag in n.actor.notification_tags.all %} + {{ tag.name }}{% if not forloop.last %}, {% endif %} + {% endfor %} +

+ {% endif %} + {% else %}
-

- {{ n.verb }} -

-

- {{ n.description | safe }} -

- {{ n.timestamp|timesince }} ago +

+ {{ n.verb }} +

+ {{ n.timestamp|timesince }} ago
-
+

{{ n.description|strip_html }}

+ {% if n.actor.notification_tags.all %} +

+ Topic(s): + {% for tag in n.actor.notification_tags.all %} + {{ tag.name }}{% if not forloop.last %}, {% endif %} + {% endfor %} +

+ {% endif %} +
{% endif %} {% empty %}
No notifications yet.
diff --git a/user_notifications/wagtail_hooks.py b/user_notifications/wagtail_hooks.py index 783dc60e0..f2fed87a8 100644 --- a/user_notifications/wagtail_hooks.py +++ b/user_notifications/wagtail_hooks.py @@ -1,3 +1,4 @@ +from django.utils.html import format_html from wagtail.contrib.modeladmin.options import ( ModelAdmin, ModelAdminGroup, modeladmin_register ) @@ -31,7 +32,18 @@ class NotificationLogAdmin(ModelAdmin): menu_icon = "list-ul" # Wagtail icon name menu_order = 200 list_display = ("notification_key", "user", "state", "get_notification_url", "get_is_clicked", "tags", "received_at") - search_fields = ("notification_key", "user__username", "user__email", "tags", "get_notification_url") + search_fields = ("notification_key", "user__username", "user__email", "tags") + list_filter = ("state", "tags", "user") + ordering = ["-received_at"] + + def has_add_permission(self, request): + return False + + def has_edit_permission(self, request, obj=None): + return False + + def has_delete_permission(self, request, obj=None): + return False def get_is_clicked(self, obj): try: @@ -43,11 +55,10 @@ def get_is_clicked(self, obj): get_is_clicked.short_description = 'Is Clicked' def get_notification_url(self, obj): - try: - url = obj.notification.data["url"] - return url - except AttributeError: - return "" + url = obj.notification.data.get("url") if hasattr(obj.notification, "data") else "" + if url: + return format_html('{}', url, url) + return "-" get_notification_url.short_description = "Target URL" From 7091962567d372bca7dd01e7efba5be191e387f1 Mon Sep 17 00:00:00 2001 From: Sachin Mehta Date: Wed, 30 Jul 2025 09:01:19 +0000 Subject: [PATCH 029/147] Changed icon on profile page --- iogt/static/icons/bell-solid.svg | 1 + iogt/static/js/iogt-no-jquery.js | 1 + iogt/static/js/iogt.js | 3 +++ iogt_users/templates/profile.html | 2 +- iogt_users/templates/user_notification.html | 2 +- 5 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 iogt/static/icons/bell-solid.svg diff --git a/iogt/static/icons/bell-solid.svg b/iogt/static/icons/bell-solid.svg new file mode 100644 index 000000000..96f35738e --- /dev/null +++ b/iogt/static/icons/bell-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/iogt/static/js/iogt-no-jquery.js b/iogt/static/js/iogt-no-jquery.js index f2492e0b2..89a24d4c5 100644 --- a/iogt/static/js/iogt-no-jquery.js +++ b/iogt/static/js/iogt-no-jquery.js @@ -78,6 +78,7 @@ const init = () => { ".change-digital-pin", ".comments__form", ".logout-btn", + ".notification-pref-btn", ".progress-holder", ".report-comment", ".search-form-holder", diff --git a/iogt/static/js/iogt.js b/iogt/static/js/iogt.js index a35e3260f..d1bd02990 100644 --- a/iogt/static/js/iogt.js +++ b/iogt/static/js/iogt.js @@ -58,6 +58,7 @@ $(document).ready(() => { const changeDigitalPinBtn = $(".change-digital-pin"); const loginCreateAccountBtns = $(".login-create-account-btn"); const logoutBtn = $(".logout-btn"); + const notificationPreferenceButton = $(".notification-pref-btn"); const externalLinks = $('a[href*="/external-link/?next="]'); questionnaireSubmitBtns.each((index, btn) => { @@ -91,6 +92,7 @@ $(document).ready(() => { changeDigitalPinBtn.hide(); loginCreateAccountBtns.hide(); logoutBtn.hide(); + notificationPreferenceButton.hide(); externalLinks.each((index, link) => { const $link = $(link); if (!$link.data("offline-bound")) { @@ -128,6 +130,7 @@ $(document).ready(() => { changeDigitalPinBtn.show(); loginCreateAccountBtns.show(); logoutBtn.show(); + notificationPreferenceButton.show(); externalLinks.show(); externalLinks.each((index, link) => { $(link).off("click.offline"); diff --git a/iogt_users/templates/profile.html b/iogt_users/templates/profile.html index baf57f344..17fa35c7c 100644 --- a/iogt_users/templates/profile.html +++ b/iogt_users/templates/profile.html @@ -23,7 +23,7 @@

{# Show notification banner only if preference is not yet set #}
{% url 'notification_settings' as notify_url %} - {% primary_button title='Notification Preference' href=notify_url icon_path='icons/arrow_icon_left.svg' extra_classnames='logout-btn' %} + {% primary_button title='Notification Preference' href=notify_url icon_path='icons/bell-solid.svg' extra_classnames='notification-pref-btn' %} {% url 'account_change_password' as change_password_url %} {% primary_button title='Change Digital Pin' href=change_password_url icon_path='icons/lock.svg' extra_classnames='change-digital-pin' %} diff --git a/iogt_users/templates/user_notification.html b/iogt_users/templates/user_notification.html index ec345ffbf..b6e2f573f 100644 --- a/iogt_users/templates/user_notification.html +++ b/iogt_users/templates/user_notification.html @@ -1,7 +1,7 @@ {% extends 'account/base.html' %} {% load i18n static image_tags generic_components %} -{% block title %}{% translate "Profile" %}{% endblock %} +{% block title %}{% translate "Notification Preference" %}{% endblock %} {% block content %} From b38e9a1ae2b77ee8e1755af8082d618b03de1adb Mon Sep 17 00:00:00 2001 From: Ankit-lab809 Date: Thu, 31 Jul 2025 18:27:38 +0530 Subject: [PATCH 030/147] Include name in notification and corrected designs --- .../0061_article_notification_tags.py | 20 ++++++ home/static/css/global/global.css | 11 +++- home/templates/home/home_page.html | 2 +- iogt/utils.py | 11 +++- iogt_users/templates/user_notification.html | 8 +-- .../0033_survey_notification_tags.py | 4 +- .../migrations/0003_auto_20250728_1222.py | 61 +++++++++++++++++++ .../0004_notificationlog_notification.py | 21 +++++++ .../0005_seed_notification_tables.py | 50 +++++++++++++++ .../notification_dropdown.html | 8 +++ .../user_notifications/notification_list.html | 27 +++++--- 11 files changed, 201 insertions(+), 22 deletions(-) create mode 100644 home/migrations/0061_article_notification_tags.py create mode 100644 user_notifications/migrations/0003_auto_20250728_1222.py create mode 100644 user_notifications/migrations/0004_notificationlog_notification.py create mode 100644 user_notifications/migrations/0005_seed_notification_tables.py diff --git a/home/migrations/0061_article_notification_tags.py b/home/migrations/0061_article_notification_tags.py new file mode 100644 index 000000000..bbbceb1e2 --- /dev/null +++ b/home/migrations/0061_article_notification_tags.py @@ -0,0 +1,20 @@ +# Generated by Django 3.2.25 on 2025-07-28 12:22 + +from django.db import migrations +import modelcluster.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('user_notifications', '0003_auto_20250728_1222'), + ('home', '0060_auto_20250703_0253'), + ] + + operations = [ + migrations.AddField( + model_name='article', + name='notification_tags', + field=modelcluster.fields.ParentalManyToManyField(blank=True, to='user_notifications.NotificationTag'), + ), + ] diff --git a/home/static/css/global/global.css b/home/static/css/global/global.css index f61ab1ed1..2d784df01 100644 --- a/home/static/css/global/global.css +++ b/home/static/css/global/global.css @@ -2172,6 +2172,7 @@ body.rtl { display: none; flex-direction: column; z-index: 1000; + overflow-y: auto; } /* Header */ @@ -2323,7 +2324,7 @@ div.notification-confirmation{ bottom: 20px; left: 20px; background-color: #fff8e1; - color: #333; + color: black; border-left: 5px solid goldenrod; box-shadow: 0 4px 8px rgba(0,0,0,0.15); padding: 15px 10px; @@ -2335,6 +2336,7 @@ div.notification-confirmation{ font-family: "Segoe UI", sans-serif; animation: slideIn 0.5s ease-out; margin-right: 15px; + font-size: large; } .notification-toast a { @@ -2353,4 +2355,11 @@ div.notification-confirmation{ transform: translateX(0%); opacity: 1; } +} + +.notification-name { + font-size: 0.75rem; + color: #555; + margin: 0; + margin-bottom: 5px; } \ No newline at end of file diff --git a/home/templates/home/home_page.html b/home/templates/home/home_page.html index 268f0e3c8..1556fdfaa 100644 --- a/home/templates/home/home_page.html +++ b/home/templates/home/home_page.html @@ -11,7 +11,7 @@
{% if user.is_authenticated and not notification_preference.receive_notifications %}
- 🔔 IOGT wants your permission to enable notifications + 🔔 Don’t miss out! Turn on notifications to stay updated with the latest from IOGT."
{% endif %} {% include 'home/tags/banners_list.html' with banners=banners %} diff --git a/iogt/utils.py b/iogt/utils.py index 1954dc596..dc2eed7f4 100644 --- a/iogt/utils.py +++ b/iogt/utils.py @@ -48,8 +48,15 @@ def render_html(self, context): @staff_member_required def notify_and_publish_view(request, page_id): page = Page.objects.get(id=page_id).specific - revision = page.save_revision(user=request.user) - revision.publish() + latest_revision = page.get_latest_revision_as_page() + + if latest_revision: + # This gives you the latest draft version as a page instance + revision = latest_revision.save_revision(user=request.user) + revision.publish() + else: + revision = page.save_revision(user=request.user) + revision.publish() if isinstance(page, Survey): full_url = get_site_for_locale(page) send_app_notifications.delay(page.id, full_url, 'survey') diff --git a/iogt_users/templates/user_notification.html b/iogt_users/templates/user_notification.html index b6e2f573f..d39dc9fdc 100644 --- a/iogt_users/templates/user_notification.html +++ b/iogt_users/templates/user_notification.html @@ -133,16 +133,11 @@

{% translate "Notification Preference" %}

if ("Notification" in window && Notification.permission !== "granted") { Notification.requestPermission().then(permission => { if (permission !== "granted") { - showToast("🔕 Web Push Notifications are off. You can enable them from your browser settings. You'll still receive in-app notifications.", "warning"); + showToast("🔕 Web push notifications are disabled. You’ll still receive important updates within the app."); } }); } } - else - { - document.getElementById('language-select').value = selectedLanguage; - unselectTopics(); - } fetch("{% url 'save_notification_preference' %}", { method: "POST", @@ -172,7 +167,6 @@

{% translate "Notification Preference" %}

document.addEventListener('DOMContentLoaded', function () { document.getElementById('save').addEventListener('click', setNotificationPref); - document.getElementById('no').addEventListener('click', unselectTopics); document.getElementById('select-notification-tags').addEventListener('click', toggleDropdown); document.getElementById('select-all').addEventListener('click', toggleSelectAll); updateSelectedTopicLabel(); diff --git a/questionnaires/migrations/0033_survey_notification_tags.py b/questionnaires/migrations/0033_survey_notification_tags.py index 3a1840f42..28312e9f9 100644 --- a/questionnaires/migrations/0033_survey_notification_tags.py +++ b/questionnaires/migrations/0033_survey_notification_tags.py @@ -1,4 +1,4 @@ -# Generated by Django 3.2.25 on 2025-07-21 03:58 +# Generated by Django 3.2.25 on 2025-07-28 12:22 from django.db import migrations import modelcluster.fields @@ -7,7 +7,7 @@ class Migration(migrations.Migration): dependencies = [ - ('user_notifications', '0007_notificationmeta'), + ('user_notifications', '0003_auto_20250728_1222'), ('questionnaires', '0032_auto_20250526_0135'), ] diff --git a/user_notifications/migrations/0003_auto_20250728_1222.py b/user_notifications/migrations/0003_auto_20250728_1222.py new file mode 100644 index 000000000..94fceea40 --- /dev/null +++ b/user_notifications/migrations/0003_auto_20250728_1222.py @@ -0,0 +1,61 @@ +# Generated by Django 3.2.25 on 2025-07-28 12:22 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.NOTIFICATIONS_NOTIFICATION_MODEL), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('user_notifications', '0002_notificationpreference'), + ] + + operations = [ + migrations.CreateModel( + name='NotificationTag', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100, unique=True)), + ('slug', models.SlugField(unique=True)), + ], + ), + migrations.AddField( + model_name='notificationpreference', + name='preferred_language', + field=models.CharField(choices=[('en', 'English'), ('es', 'Spanish'), ('fr', 'French'), ('ar', 'Arabic')], default='en', max_length=5), + ), + migrations.AddField( + model_name='usernotificationtemplate', + name='type', + field=models.CharField(choices=[('signup', 'User Signup'), ('article', 'Article Published'), ('survey', 'Survey Published')], default='User Signup', help_text='Select the type of notification this template is used for.', max_length=20, unique=True), + preserve_default=False, + ), + migrations.CreateModel( + name='NotificationMeta', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('is_clicked', models.BooleanField(default=False)), + ('notification', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='meta', to=settings.NOTIFICATIONS_NOTIFICATION_MODEL)), + ], + ), + migrations.CreateModel( + name='NotificationLog', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('notification_key', models.CharField(max_length=255)), + ('state', models.CharField(choices=[('sent', 'Sent'), ('failed', 'Failed')], default='sent', max_length=20)), + ('received_at', models.DateTimeField(auto_now_add=True)), + ('error_message', models.TextField(blank=True, null=True)), + ('tags', models.CharField(max_length=255)), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.AddField( + model_name='notificationpreference', + name='content_tags', + field=models.ManyToManyField(blank=True, to='user_notifications.NotificationTag'), + ), + ] diff --git a/user_notifications/migrations/0004_notificationlog_notification.py b/user_notifications/migrations/0004_notificationlog_notification.py new file mode 100644 index 000000000..a82eb7da0 --- /dev/null +++ b/user_notifications/migrations/0004_notificationlog_notification.py @@ -0,0 +1,21 @@ +# Generated by Django 3.2.25 on 2025-07-31 06:02 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.NOTIFICATIONS_NOTIFICATION_MODEL), + ('user_notifications', '0003_auto_20250728_1222'), + ] + + operations = [ + migrations.AddField( + model_name='notificationlog', + name='notification', + field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='logs', to=settings.NOTIFICATIONS_NOTIFICATION_MODEL), + ), + ] diff --git a/user_notifications/migrations/0005_seed_notification_tables.py b/user_notifications/migrations/0005_seed_notification_tables.py new file mode 100644 index 000000000..1454cacf1 --- /dev/null +++ b/user_notifications/migrations/0005_seed_notification_tables.py @@ -0,0 +1,50 @@ +# Generated by Django 3.2.25 on 2025-07-31 06:02 + +from django.conf import settings +from django.db import migrations, models +from django.contrib.auth.models import Group +from iogt_users.models import User +import django.db.models.deletion +from user_notifications.models import UserNotificationTemplate + + +def reverse_seed_notification_tables(apps, schema_editor): + Group.objects.filter(name="Notify All Users").delete() + UserNotificationTemplate.objects.all().delete() + + +def seed_notification_tables(apps, schema_editor): + group, created = Group.objects.get_or_create(name="Notify All Users") + all_users = User.objects.all() + group.user_set.set(all_users) # replaces current users with all users + + article_template, _ = UserNotificationTemplate.objects.get_or_create( + type='article', + title='A New Article Has Been Published!', + message='Tap here to read the latest article now.' + ) + + survey_template, _ = UserNotificationTemplate.objects.get_or_create( + type='survey', + title='We Value Your Feedback!', + message='Take a quick survey to share your thoughts.' + ) + + signup_template, _ = UserNotificationTemplate.objects.get_or_create( + type='signup', + title='Welcome Aboard!', + message='Your account has been successfully created.' + ) + + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.NOTIFICATIONS_NOTIFICATION_MODEL), + ('user_notifications', '0004_notificationlog_notification'), + ] + + operations = [ + migrations.RunPython(seed_notification_tables, reverse_seed_notification_tables), + ] diff --git a/user_notifications/templates/user_notifications/notification_dropdown.html b/user_notifications/templates/user_notifications/notification_dropdown.html index 05a19b7cc..0eeea0ed8 100644 --- a/user_notifications/templates/user_notifications/notification_dropdown.html +++ b/user_notifications/templates/user_notifications/notification_dropdown.html @@ -15,6 +15,10 @@

{{ n.description|strip_html }}

{% if n.actor.notification_tags.all %} +

+ Name: + {{n.actor.title}} +

Topic(s): {% for tag in n.actor.notification_tags.all %} @@ -36,6 +40,10 @@ {{ n.description|strip_html }}

{% if n.actor.notification_tags.all %} +

+ Name: + {{n.actor.title}} +

Topic(s): {% for tag in n.actor.notification_tags.all %} diff --git a/user_notifications/templates/user_notifications/notification_list.html b/user_notifications/templates/user_notifications/notification_list.html index 97d59b171..357279d6d 100644 --- a/user_notifications/templates/user_notifications/notification_list.html +++ b/user_notifications/templates/user_notifications/notification_list.html @@ -18,15 +18,20 @@

All Notifications

{{ n.timestamp|timesince }} ago

{{ n.description|strip_html }}

+ {% if n.actor.notification_tags.all %} +

+ Name: + {{n.actor.title}} +

- Topic(s): - {% for tag in n.actor.notification_tags.all %} - {{ tag.name }}{% if not forloop.last %}, {% endif %} - {% endfor %} + Topic(s): + {% for tag in n.actor.notification_tags.all %} + {{ tag.name }}{% if not forloop.last %}, {% endif %} + {% endfor %}

{% endif %} - + {% else %}
@@ -38,11 +43,15 @@

All Notifications

{{ n.description|strip_html }}

{% if n.actor.notification_tags.all %} +

+ Name: + {{n.actor.title}} +

- Topic(s): - {% for tag in n.actor.notification_tags.all %} - {{ tag.name }}{% if not forloop.last %}, {% endif %} - {% endfor %} + Topic(s): + {% for tag in n.actor.notification_tags.all %} + {{ tag.name }}{% if not forloop.last %}, {% endif %} + {% endfor %}

{% endif %}

From 37b136f1a3f93e53dcad2cc1e8c16271a1f13749 Mon Sep 17 00:00:00 2001 From: Sachin Mehta Date: Fri, 1 Aug 2025 07:01:08 +0000 Subject: [PATCH 031/147] Commiting updated requirements file --- requirements.dev.txt | 273 ++++++++++++++++--------------------------- 1 file changed, 102 insertions(+), 171 deletions(-) diff --git a/requirements.dev.txt b/requirements.dev.txt index ce07d3e09..3b595d1ab 100644 --- a/requirements.dev.txt +++ b/requirements.dev.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.11 # by the following command: # # pip-compile --generate-hashes requirements.dev.in @@ -12,13 +12,13 @@ anyascii==0.3.2 \ --hash=sha256:3b3beef6fc43d9036d3b0529050b0c48bfad8bc960e9e562d7223cfb94fe45d4 \ --hash=sha256:9d5d32ef844fe225b8bc7cba7f950534fae4da27a9bf3a6bea2cb0ea46ce4730 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # wagtail asgiref==3.8.1 \ --hash=sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47 \ --hash=sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # django attrs==23.2.0 \ --hash=sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30 \ @@ -26,33 +26,12 @@ attrs==23.2.0 \ # via # outcome # trio -backports-zoneinfo[tzdata]==0.2.1 ; python_version < "3.9" \ - --hash=sha256:17746bd546106fa389c51dbea67c8b7c8f0d14b5526a579ca6ccf5ed72c526cf \ - --hash=sha256:1b13e654a55cd45672cb54ed12148cd33628f672548f373963b0bff67b217328 \ - --hash=sha256:1c5742112073a563c81f786e77514969acb58649bcdf6cdf0b4ed31a348d4546 \ - --hash=sha256:4a0f800587060bf8880f954dbef70de6c11bbe59c673c3d818921f042f9954a6 \ - --hash=sha256:5c144945a7752ca544b4b78c8c41544cdfaf9786f25fe5ffb10e838e19a27570 \ - --hash=sha256:7b0a64cda4145548fed9efc10322770f929b944ce5cee6c0dfe0c87bf4c0c8c9 \ - --hash=sha256:8439c030a11780786a2002261569bdf362264f605dfa4d65090b64b05c9f79a7 \ - --hash=sha256:8961c0f32cd0336fb8e8ead11a1f8cd99ec07145ec2931122faaac1c8f7fd987 \ - --hash=sha256:89a48c0d158a3cc3f654da4c2de1ceba85263fafb861b98b59040a5086259722 \ - --hash=sha256:a76b38c52400b762e48131494ba26be363491ac4f9a04c1b7e92483d169f6582 \ - --hash=sha256:da6013fd84a690242c310d77ddb8441a559e9cb3d3d59ebac9aca1a57b2e18bc \ - --hash=sha256:e55b384612d93be96506932a786bbcde5a2db7a9e6a4bb4bffe8b733f5b9036b \ - --hash=sha256:e81b76cace8eda1fca50e345242ba977f9be6ae3945af8d46326d776b4cf78d1 \ - --hash=sha256:e8236383a20872c0cdf5a62b554b27538db7fa1bbec52429d8d106effbaeca08 \ - --hash=sha256:f04e857b59d9d1ccc39ce2da1021d196e47234873820cbeaad210724b1ee28ac \ - --hash=sha256:fadbfe37f74051d024037f223b8e001611eac868b5c5b06144ef4d8b799862f2 - # via - # -r requirements.dev.in - # celery - # kombu beautifulsoup4==4.9.3 \ --hash=sha256:4c98143716ef1cb40bf7f39a8e3eec8f8b009509e74904ba3a7b315431577e35 \ --hash=sha256:84729e322ad1d5b4d25f805bfa05b902dd96450f43842c4e99067d5e1369eb25 \ --hash=sha256:fff47e031e34ec82bf17e00da8f592fe7de69aeea38be00523c04623c04fb666 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # wagtail billiard==4.2.1 \ --hash=sha256:12b641b0c539073fc8d3f5b8b7be998956665c4233c7c1fcd66a7e677c4fb36f \ @@ -62,18 +41,18 @@ bleach==4.1.0 \ --hash=sha256:0900d8b37eba61a802ee40ac0061f8c2b5dee29c1927dd1d233e075ebf5a71da \ --hash=sha256:4d2651ab93271d1129ac9cbc679f524565cc8a1b791909c4a51eac4446a15994 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # wagtail-markdown cairocffi==1.7.1 \ --hash=sha256:2e48ee864884ec4a3a34bfa8c9ab9999f688286eb714a15a43ec9d068c36557b \ --hash=sha256:9803a0e11f6c962f3b0ae2ec8ba6ae45e957a146a004697a1ac1bbf16b073b3f # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # cairosvg cairosvg==2.7.1 \ --hash=sha256:432531d72347291b9a9ebfb6777026b607563fd8719c46ee742db0aef7271ba0 \ --hash=sha256:8a5222d4e6c3f86f1f7046b63246877a63b49923a1cd202184c3a634ef546b3b - # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # via -r requirements.txt celery==5.3.6 \ --hash=sha256:870cc71d737c0200c397290d730344cc991d13a057534353d124c9380267aab9 \ --hash=sha256:9da4ea0118d232ce97dff5ed4974587fb1c0ff5c10042eb15278487cdd27d1af @@ -82,7 +61,7 @@ certifi==2024.7.4 \ --hash=sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b \ --hash=sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # elasticsearch # requests # selenium @@ -140,10 +119,9 @@ cffi==1.16.0 \ --hash=sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956 \ --hash=sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # cairocffi # cryptography - # trio charset-normalizer==3.3.2 \ --hash=sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027 \ --hash=sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087 \ @@ -236,13 +214,13 @@ charset-normalizer==3.3.2 \ --hash=sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519 \ --hash=sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # requests click==8.1.7 \ --hash=sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28 \ --hash=sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # celery # click-didyoumean # click-plugins @@ -263,11 +241,7 @@ click-repl==0.3.0 \ colorama==0.4.6 \ --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 - # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt - # click - # pytest - # tqdm + # via -r requirements.txt coverage==7.6.0 \ --hash=sha256:0086cd4fc71b7d485ac93ca4239c8f75732c2ae3ba83f6be1c9be59d9e2c6382 \ --hash=sha256:01c322ef2bbe15057bc4bf132b525b7e3f7206f071799eb8aa6ad1940bcf5fb1 \ @@ -356,7 +330,7 @@ cryptography==42.0.8 \ --hash=sha256:fa76fbb7596cc5839320000cdd5d0955313696d9511debab7ee7278fc8b5c84a \ --hash=sha256:fff12c88a672ab9c9c1cf7b0c80e3ad9e2ebd9d828d955c126be4fd3e5578c9e # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # http-ece # py-vapid # pyjwt @@ -365,20 +339,20 @@ cssselect2==0.7.0 \ --hash=sha256:1ccd984dab89fc68955043aca4e1b03e0cf29cad9880f6e28e3ba7a74b14aa5a \ --hash=sha256:fd23a65bfd444595913f02fc71f6b286c29261e354c41d722ca7a261a49b5969 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # cairosvg defusedxml==0.7.1 \ --hash=sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69 \ --hash=sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # cairosvg # python3-openid django==3.2.25 \ --hash=sha256:7ca38a78654aee72378594d63e51636c04b8e28574f5505dff630895b5472777 \ --hash=sha256:a52ea7fcf280b16f7b739cec38fa6d3f8953a5456986944c3ca97e79882b4e38 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # django-allauth # django-appconf # django-comments-xtd @@ -405,32 +379,32 @@ django==3.2.25 \ # wagtailmedia django-allauth==0.54.0 \ --hash=sha256:120e265f802b65738899c6cb627b827fde46a4d03067034c633f516c2adf3e3e - # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # via -r requirements.txt django-appconf==1.0.6 \ --hash=sha256:c3ae442fba1ff7ec830412c5184b17169a7a1e71cf0864a4c3f93cf4c98a1993 \ --hash=sha256:cfe87ea827c4ee04b9a70fab90b86d704cb02f2981f89da8423cb0fabf88efbf # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # django-compressor django-cogwheels==0.3 \ --hash=sha256:197bd05e7114403d7301214b3f8a371c4fb6039cf21c811f099438b167b5ed21 \ --hash=sha256:848a4d9f2c96c582a4a4f2e7c276dfd95ab3905748cae13bb7c4b365a6717e94 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # wagtailmenus django-comments-xtd==2.9.13 \ --hash=sha256:0d91e3cc76eae6f30e83b12fb09708e5407664d9daa7b9c1101d7377897f7b42 \ --hash=sha256:b289b6754d6618fb29e4279c6a1c6a270bc9495e161c42193d8b6216a4884802 - # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # via -r requirements.txt django-compressor==2.4.1 \ --hash=sha256:3358077605c146fdcca5f9eaffb50aa5dbe15f238f8854679115ebf31c0415e0 \ --hash=sha256:f8313f59d5e65712fc28787d084fe834997c9dfa92d064a1a3ec3d3366594d04 - # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # via -r requirements.txt django-contrib-comments==2.2.0 \ --hash=sha256:2ca79060bbc8fc5b636981ef6e50f35ab83649af75fc1be47bf770636be3271c \ --hash=sha256:48de00f15677e016a216aeff205d6e00e4391c9a5702136c64119c472b7356da # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # django-comments-xtd django-debug-toolbar==4.3.0 \ --hash=sha256:0b0dddee5ea29b9cb678593bc0d7a6d76b21d7799cb68e091a2148341a80f3c4 \ @@ -439,59 +413,59 @@ django-debug-toolbar==4.3.0 \ django-extensions==3.1.5 \ --hash=sha256:28e1e1bf49f0e00307ba574d645b0af3564c981a6dfc87209d48cb98f77d0b1a \ --hash=sha256:9238b9e016bb0009d621e05cf56ea8ce5cce9b32e91ad2026996a7377ca28069 - # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # via -r requirements.txt django-filter==2.4.0 \ --hash=sha256:84e9d5bb93f237e451db814ed422a3a625751cbc9968b484ecc74964a8696b06 \ --hash=sha256:e00d32cebdb3d54273c48f4f878f898dced8d5dfaad009438fe61ebdf535ace1 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # wagtail django-health-check==3.16.5 \ --hash=sha256:1edfd49293ccebbce29f9da609c407f307aee240ab799ab4201031341ae78c0f \ --hash=sha256:8d66781a0ea82b1a8b44878187b38a27370e94f18287312e39be0593e72d8983 - # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # via -r requirements.txt django-model-utils==5.0.0 \ --hash=sha256:041cdd6230d2fbf6cd943e1969318bce762272077f4ecd333ab2263924b4e5eb \ --hash=sha256:fec78e6c323d565a221f7c4edc703f4567d7bb1caeafe1acd16a80c5ff82056b # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # django-notifications-hq django-modelcluster==6.3 \ --hash=sha256:0caed8a0e889f3abb92f144670878a466ef954ffa6c4c7b9c80e6426b720a49d \ --hash=sha256:a8783d6565a0663f41cd6003ea361c3a5711e8a2a326160f1ec1eceb3e973d4f # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # wagtail django-notifications-hq==1.8.3 \ --hash=sha256:0f4b216bb382b7c7c4eef273eb211e59c1c6a0ea38cba6077415ac031d330725 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt # -r requirements.dev.in + # -r requirements.txt django-permissionedforms==0.1 \ --hash=sha256:4340bb20c4477fffb13b4cc5cccf9f1b1010b64f79956c291c72d2ad2ed243f8 \ --hash=sha256:d341a961a27cc77fde8cc42141c6ab55cc1f0cb886963cc2d6967b9674fa47d6 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # wagtail django-redis==5.2.0 \ --hash=sha256:1d037dc02b11ad7aa11f655d26dac3fb1af32630f61ef4428860a2e29ff92026 \ --hash=sha256:8a99e5582c79f894168f5865c52bd921213253b7fd64d16733ae4591564465de - # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # via -r requirements.txt django-rq==2.4.1 \ --hash=sha256:23981f83c537178cbbf730f192c13e99cede2204e9d917b1c1c80c42215dd227 \ --hash=sha256:f09059ab37403a47c7933bca396fabb7f3058732d132462eade5333bc4bcac5f # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # django-translation-manager django-sass-processor==1.0.1 \ --hash=sha256:1f043180c47754018e803a77da003377f5ea6558de57cd6946eb27a32e9c16a2 \ --hash=sha256:dcaad47c591a2d52689c1bd209259e922e902d886293f0d5c9e0d1a4eb85eda2 - # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # via -r requirements.txt django-taggit==2.1.0 \ --hash=sha256:61547a23fc99967c9304107414a09e662b459f4163dbbae32e60b8ba40c34d05 \ --hash=sha256:a9f41e4ad58efe4b28d86f274728ee87eb98eeae90c9eb4b4efad39e5068184e # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # wagtail django-test-plus==2.2.4 \ --hash=sha256:06488209a07dca60dc2bbeaeae5ce340d17344163e0b121709cdac7405c6d9ef \ @@ -500,23 +474,23 @@ django-test-plus==2.2.4 \ django-translation-manager==1.3.0 \ --hash=sha256:1e3143f48f9ba4d5452d72f55195142c434ea63786546251ae694508df4eb7b1 \ --hash=sha256:9215b0149e78eaa13992a48367bf4ef28ef450e35863ea3ce7194b3558617bcf - # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # via -r requirements.txt django-treebeard==4.7.1 \ --hash=sha256:846e462904b437155f76e04907ba4e48480716855f88b898df4122bdcfbd6e98 \ --hash=sha256:995c7120153ab999898fe3043bbdcd8a0fc77cc106eb94de7350e9d02c885135 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # wagtail django-webpush==0.3.4 \ --hash=sha256:28cbe7da20f1df5b61d859f61e2d11d4076de1c367aa048d654894fb8f324065 \ --hash=sha256:a123102dede1a959f667e075ed746ac5b7d4a8622320162eba41a507a835e1e4 \ --hash=sha256:a2613784e822e2dde27086fb20b6d1a2b76e4d5dc8271607aecd45c98a3b7954 - # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # via -r requirements.txt djangorestframework==3.13.1 \ --hash=sha256:0c33407ce23acc68eca2a6e46424b008c9c02eceb8cf18581921d0092bc1f2ee \ --hash=sha256:24c4bf58ed7e85d1fe4ba250ab2da926d263cd57d64b03e8dcef0ac683f8b1aa # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # django-comments-xtd # django-translation-manager # djangorestframework-simplejwt @@ -525,40 +499,33 @@ djangorestframework==3.13.1 \ djangorestframework-simplejwt==5.3.1 \ --hash=sha256:381bc966aa46913905629d472cd72ad45faa265509764e20ffd440164c88d220 \ --hash=sha256:6c4bd37537440bc439564ebf7d6085e74c5411485197073f508ebdfa34bc9fae - # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # via -r requirements.txt docutils==0.20.1 \ --hash=sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6 \ --hash=sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # django-comments-xtd draftjs-exporter==2.1.7 \ --hash=sha256:5839cbc29d7bce2fb99837a404ca40c3a07313f2a20e2700de7ad6aa9a9a18fb \ --hash=sha256:d415a9964690a2cddb66a31ef32dd46c277e9b80434b94e39e3043188ed83e33 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # wagtail drf-yasg==1.21.7 \ --hash=sha256:4c3b93068b3dfca6969ab111155e4dd6f7b2d680b98778de8fd460b7837bdb0d \ --hash=sha256:f85642072c35e684356475781b7ecf5d218fff2c6185c040664dd49f0a4be181 - # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # via -r requirements.txt elasticsearch==7.17.9 \ --hash=sha256:0e2454645dc00517dee4c6de3863411a9c5f1955d013c5fefa29123dadc92f98 \ --hash=sha256:66c4ece2adfe7cc120e2b6a6798a1fd5c777aecf82eec39bb95cef7cfc7ea2b3 - # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # via -r requirements.txt et-xmlfile==1.1.0 \ --hash=sha256:8eb9e2bc2f8c97e37a2dc85a09ecdcdec9d8a396530a6d5a33b30b9a92da0c5c \ --hash=sha256:a2ba85d1d6a74ef63837eed693bcb89c3f752169b0e3e7ae5b16ca5e1b3deada # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # openpyxl -exceptiongroup==1.3.0 \ - --hash=sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10 \ - --hash=sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88 - # via - # pytest - # trio - # trio-websocket factory-boy==3.3.0 \ --hash=sha256:a2cdbdb63228177aa4f1c52f4b6d83fab2b8623bf602c7dedd7eb83c0f69c04c \ --hash=sha256:bc76d97d1a65bbd9842a6d722882098eb549ec8ee1081f9fb2e8ff29f0c300f1 @@ -579,31 +546,29 @@ html5lib==1.1 \ --hash=sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d \ --hash=sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # wagtail http-ece==1.2.0 \ --hash=sha256:b5920f8efb8e1b5fb025713e3b36fda54336262010634b26dc1f98f85d1eb3de # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # pywebpush idna==3.7 \ --hash=sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc \ --hash=sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # requests # trio importlib-metadata==8.5.0 \ --hash=sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b \ --hash=sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7 - # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt - # markdown + # via -r requirements.txt inflection==0.5.1 \ --hash=sha256:1a29730d366e996aaacffb2f1f1cb9593dc38e2ddd30c91250c6dde09ea9b417 \ --hash=sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # drf-yasg iniconfig==2.0.0 \ --hash=sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3 \ @@ -613,7 +578,7 @@ jsonfield==3.1.0 \ --hash=sha256:7e4e84597de21eeaeeaaa7cc5da08c61c48a9b64d0c446b2d71255d01812887a \ --hash=sha256:df857811587f252b97bafba42e02805e70a398a7a47870bc6358a0308dd689ed # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # django-notifications-hq kombu==5.5.4 \ --hash=sha256:886600168275ebeada93b888e831352fe578168342f0d1d5833d88ba0d847363 \ @@ -623,7 +588,7 @@ l18n==2021.3 \ --hash=sha256:1956e890d673d17135cc20913253c154f6bc1c00266c22b7d503cc1a5a42d848 \ --hash=sha256:78495d1df95b6f7dcc694d1ba8994df709c463a1cbac1bf016e1b9a5ce7280b9 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # wagtail libsass==0.21.0 \ --hash=sha256:06c8776417fe930714bdc930a3d7e795ae3d72be6ac883ff72a1b8f7c49e5ffb \ @@ -636,7 +601,7 @@ libsass==0.21.0 \ --hash=sha256:c9ec490609752c1d81ff6290da33485aa7cb6d7365ac665b74464c1b7d97f7da \ --hash=sha256:d5ba529d9ce668be9380563279f3ffe988f27bc5b299c5a28453df2e0b0fbaf2 \ --hash=sha256:e2b1a7d093f2e76dc694c17c0c285e846d0b0deb0e8b21dc852ba1a3a4e2f1d6 - # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # via -r requirements.txt lxml==4.9.4 \ --hash=sha256:00e91573183ad273e242db5585b52670eddf92bacad095ce25c1e682da14ed91 \ --hash=sha256:01bf1df1db327e748dcb152d17389cf6d0a8c5d533ef9bab781e9d5037619229 \ @@ -731,24 +696,24 @@ lxml==4.9.4 \ --hash=sha256:f99768232f036b4776ce419d3244a04fe83784bce871b16d2c2e984c7fcea847 \ --hash=sha256:fd814847901df6e8de13ce69b84c31fc9b3fb591224d6762d0b256d510cbf382 \ --hash=sha256:fdb325b7fba1e2c40b9b1db407f85642e32404131c08480dd652110fc908561b - # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # via -r requirements.txt markdown==3.6 \ --hash=sha256:48f276f4d8cfb8ce6527c8f79e2ee29708508bf4d40aa410fbc3b4ee832c850f \ --hash=sha256:ed4f41f6daecbeeb96e576ce414c41d2d876daa9a16cb35fa8ed8c2ddfad0224 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # wagtail-markdown oauthlib==3.2.2 \ --hash=sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca \ --hash=sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # requests-oauthlib openpyxl==3.1.5 \ --hash=sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2 \ --hash=sha256:cf0e3cf56142039133628b5acffe8ef0c12bc902d2aadd3e0fe5878dc08d1050 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # tablib outcome==1.3.0.post0 \ --hash=sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8 \ @@ -758,7 +723,7 @@ packaging==24.1 \ --hash=sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002 \ --hash=sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # bleach # drf-yasg # kombu @@ -831,7 +796,7 @@ pillow==9.5.0 \ --hash=sha256:fe7e1c262d3392afcf5071df9afa574544f28eac825284596ac6db56e6d11062 \ --hash=sha256:fed1e1cf6a42577953abbe8e6cf2fe2f566daebde7c34724ec8803c4c0cda579 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # cairosvg # wagtail pluggy==1.5.0 \ @@ -842,7 +807,7 @@ polib==1.2.0 \ --hash=sha256:1c77ee1b81feb31df9bca258cbc58db1bbb32d10214b173882452c73af06d62d \ --hash=sha256:f3ef94aefed6e183e342a8a269ae1fc4742ba193186ad76f175938621dbfc26b # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # django-translation-manager # wagtail-localize prompt-toolkit==3.0.51 \ @@ -863,25 +828,26 @@ psycopg2==2.9.9 \ --hash=sha256:d735786acc7dd25815e89cc4ad529a43af779db2e25aa7c626de864127e5a024 \ --hash=sha256:de80739447af31525feddeb8effd640782cf5998e1a4e9192ebdf829717e3913 \ --hash=sha256:ff432630e510709564c01dafdbe996cb552e0b9f3f065eb89bdce5bd31fabf4c - # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # via -r requirements.txt py-vapid==1.9.1 \ --hash=sha256:fe2b5461bf45c7baff1039df6981f03b87faa87cde0482addfa35b3fe636ac1b # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # pywebpush pycparser==2.22 \ --hash=sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6 \ --hash=sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # cffi pyjwt[crypto]==2.8.0 \ --hash=sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de \ --hash=sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # django-allauth # djangorestframework-simplejwt + # pyjwt pysocks==1.7.1 \ --hash=sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299 \ --hash=sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5 \ @@ -907,13 +873,13 @@ python3-openid==3.2.0 \ --hash=sha256:33fbf6928f401e0b790151ed2b5290b02545e8775f982485205a066f874aaeaf \ --hash=sha256:6626f771e0417486701e0b4daff762e7212e820ca5b29fcc0d05f6f8736dfa6b # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # django-allauth pytz==2024.1 \ --hash=sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812 \ --hash=sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # django # django-comments-xtd # django-modelcluster @@ -924,7 +890,7 @@ pytz==2024.1 \ pywebpush==1.9.4 \ --hash=sha256:e3ded57c9715159f64a5624a656791ee9228b9e076ea0208baa73b53be8c130f # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # django-webpush pyyaml==6.0.1 \ --hash=sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5 \ @@ -979,18 +945,18 @@ pyyaml==6.0.1 \ --hash=sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d \ --hash=sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # drf-yasg rcssmin==1.0.6 \ --hash=sha256:ca87b695d3d7864157773a61263e5abb96006e9ff0e021eff90cbe0e1ba18270 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # django-compressor redis==3.5.3 \ --hash=sha256:0e7e0cfca8660dea8b7d5cd8c4f6c5e29e11f31158c0b0ae91a397f00e5a05a2 \ --hash=sha256:432b788c4530cfe16d8d943a09d40ca6c16149727e4afe8c2c9d5580c59d9f24 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # django-redis # django-rq # rq @@ -998,7 +964,7 @@ requests==2.32.3 \ --hash=sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760 \ --hash=sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # django-allauth # django-translation-manager # pywebpush @@ -1009,7 +975,7 @@ requests-oauthlib==2.0.0 \ --hash=sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36 \ --hash=sha256:b3dffaebd884d8cd778494369603a9e7b58d29111bf6b41bdc2dcd87203af4e9 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # django-allauth rjsmin==1.1.0 \ --hash=sha256:0ab825839125eaca57cc59581d72e596e58a7a56fbc0839996b7528f0343a0a8 \ @@ -1026,13 +992,13 @@ rjsmin==1.1.0 \ --hash=sha256:e487a7783ac4339e79ec610b98228eb9ac72178973e3dee16eba0e3feef25924 \ --hash=sha256:ecd29f1b3e66a4c0753105baec262b331bcbceefc22fbe6f7e8bcd2067bcb4d7 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # django-compressor rq==1.16.2 \ --hash=sha256:52e619f6cb469b00e04da74305045d244b75fecb2ecaa4f26422add57d3c5f09 \ --hash=sha256:5c5b9ad5fbaf792b8fada25cc7627f4d206a9a4455aced371d4f501cc3f13b34 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # django-rq selenium==4.9.1 \ --hash=sha256:3444f4376321530c36ce8355b6b357d8cf4a7d588ce5cf772183465930bbed0e \ @@ -1042,7 +1008,7 @@ six==1.16.0 \ --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # bleach # django-comments-xtd # django-compressor @@ -1062,78 +1028,45 @@ soupsieve==2.5 \ --hash=sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690 \ --hash=sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # beautifulsoup4 sqlparse==0.5.0 \ --hash=sha256:714d0a4932c059d16189f58ef5411ec2287a4360f17cdd0edd2d09d4c5087c93 \ --hash=sha256:c204494cd97479d0e39f28c93d46c0b2d5959c7b9ab904762ea6c7af211c8663 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # django # django-debug-toolbar swapper==1.4.0 \ --hash=sha256:57b8378aad234242542fe32dc6e8cff0ed24b63493d20b3c88ee01f894b9345e \ --hash=sha256:9e083af114ee0593241a7b877e3e0e7d3a580454f5d59016c667a5563306f8fe # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # django-notifications-hq tablib[xls,xlsx]==3.6.1 \ --hash=sha256:040685fde11e9237675f43e985edb94b63250a5e9236f89d561ce6fb1465b839 \ --hash=sha256:c771d38ed1d74350a69873db43e0afb7f1cca0ed2915a7243094463eb6789207 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt + # tablib # wagtail telepath==0.3.1 \ --hash=sha256:925c0609e0a8a6488ec4a55b19d485882cf72223b2b19fe2359a50fddd813c9c \ --hash=sha256:c280aa8e77ad71ce80e96500a4e4d4a32f35b7e0b52e896bb5fde9a5bcf0699a # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # wagtail tinycss2==1.3.0 \ --hash=sha256:152f9acabd296a8375fbca5b84c961ff95971fcfc32e79550c8df8e29118c54d \ --hash=sha256:54a8dbdffb334d536851be0226030e9505965bb2f30f21a4a82c55fb2a80fae7 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # cairosvg # cssselect2 -tomli==2.2.1 \ - --hash=sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6 \ - --hash=sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd \ - --hash=sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c \ - --hash=sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b \ - --hash=sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8 \ - --hash=sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6 \ - --hash=sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77 \ - --hash=sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff \ - --hash=sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea \ - --hash=sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192 \ - --hash=sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249 \ - --hash=sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee \ - --hash=sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4 \ - --hash=sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98 \ - --hash=sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8 \ - --hash=sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4 \ - --hash=sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281 \ - --hash=sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744 \ - --hash=sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69 \ - --hash=sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13 \ - --hash=sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140 \ - --hash=sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e \ - --hash=sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e \ - --hash=sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc \ - --hash=sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff \ - --hash=sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec \ - --hash=sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2 \ - --hash=sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222 \ - --hash=sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106 \ - --hash=sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272 \ - --hash=sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a \ - --hash=sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7 - # via pytest tqdm==4.66.4 \ --hash=sha256:b75ca56b413b030bc3f00af51fd2c1a1a5eac6a0c1cca83cbb37a5c52abce644 \ --hash=sha256:e4d936c9de8727928f3be6079590e97d9abfe8d39a590be678eb5919ffc186bb - # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # via -r requirements.txt trio==0.26.0 \ --hash=sha256:67c5ec3265dd4abc7b1d1ab9ca4fe4c25b896f9c93dac73713778adab487f9c4 \ --hash=sha256:bb9c1b259591af941fccfbabbdc65bc7ed764bd2db76428454c894cd5e3d2032 @@ -1148,27 +1081,25 @@ typing-extensions==4.12.2 \ --hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \ --hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt - # asgiref - # exceptiongroup + # -r requirements.txt # wagtail-localize tzdata==2025.2 \ --hash=sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8 \ --hash=sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9 # via - # backports-zoneinfo # celery + # kombu uritemplate==4.1.1 \ --hash=sha256:4346edfc5c3b79f694bccd6d6099a322bbeb628dbf2cd86eea55a456ce5124f0 \ --hash=sha256:830c08b8d99bdd312ea4ead05994a38e8936266f84b9a7878232db50b044e02e # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # drf-yasg urllib3[socks]==1.26.19 \ --hash=sha256:37a0344459b199fce0e80b0d3569837ec6b6937435c5244e7fd73fa6006830f3 \ --hash=sha256:3e3d753a8618b86d7de333b4223005f68720bcd6a7d2bcb9fbd2229ec7c1e429 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # elasticsearch # requests # selenium @@ -1183,7 +1114,7 @@ wagtail==3.0.3 \ --hash=sha256:111ed9a0a6ff26d5d881d52deb4bf52b627d79a53c43829611752dbb68a9192f \ --hash=sha256:23b3e541401355ea183372582050ea52b049c956dd5b506197f957bb68423ab3 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # wagtail-cache # wagtail-factories # wagtail-localize @@ -1192,7 +1123,7 @@ wagtail==3.0.3 \ wagtail-cache==2.1.1 \ --hash=sha256:1fe3ca20a3cdf23f31fc9df662a52f743084cd7f60bd870950094d63a87f695a \ --hash=sha256:2ac16921d022a58240a009a19220554e41963c5172e7dfe4ef741ddd887e991f - # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # via -r requirements.txt wagtail-factories==4.0.0 \ --hash=sha256:3e39ec1cc13b61c6e467f1bf223ce2d134e823fa9fe4dc7e32d0222cc8d350ec \ --hash=sha256:f59f9af283da79b3ddab7b2ca95d6a14b5bbbb929a697563e4f7143948693f53 @@ -1201,30 +1132,30 @@ wagtail-generic-chooser==0.5.1 \ --hash=sha256:135f8cc413d83b82bb8956f625f4b9572aa7139ab3835e2ba2d7e19f2171b354 \ --hash=sha256:280ae7293641d1b121450e17a6d424305e31c832f1af5bd991bc3e49703bf79e # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # wagtailsvg wagtail-localize==1.4 \ --hash=sha256:40f974809509de54dcc18ee6aa98908bffd9dfaba53150e214f4046b2286920e \ --hash=sha256:fd1195de3c23e3a061576f1b947fe7498676ff5678fe008d4cd388125a20a54a - # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # via -r requirements.txt wagtail-markdown==0.10.0 \ --hash=sha256:b16be4b6e3518cc6dd15ab335cbc6d6a9122b5d7e3a61fa11c83597e2660044e \ --hash=sha256:e4a97eee0211eebaab9c850669e647bc1c8ceb70df38b4db5a2c3d8b02ebaf69 - # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # via -r requirements.txt wagtail-transfer @ https://github.com/IDEMSInternational/wagtail-transfer/archive/52b57b364ebc9acddd412ee708f829b45763c9ab.zip \ --hash=sha256:049c23e1406564d3b7e8c385e72051f34e707add4f8109d874da670711709548 - # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # via -r requirements.txt wagtailmedia==0.12.0 \ --hash=sha256:0807515c5d89782666b613de2e4aedab19e9dd358097fad2cb79633c0b5416d3 \ --hash=sha256:1d39622c3d7d0191e58ffedf45d05fbef851e3905955513012a72ae4d46a12b0 - # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # via -r requirements.txt wagtailmenus==3.1.3 \ --hash=sha256:0f5669f160d788b1ab8c2b412cb95411e9c07f83e4b52dddc92991752c6fa397 - # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # via -r requirements.txt wagtailsvg==0.0.37 \ --hash=sha256:4b30433809614fbac09f9088b4aed42a1bfe56f9fb581b858606187cb177ca6b \ --hash=sha256:dc4d698748bde32034b1eac2275cf159597ca8e399d3830e96391f761aa0cacf - # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # via -r requirements.txt wcwidth==0.2.13 \ --hash=sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859 \ --hash=sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5 @@ -1233,7 +1164,7 @@ webencodings==0.5.1 \ --hash=sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78 \ --hash=sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # bleach # cssselect2 # html5lib @@ -1241,12 +1172,12 @@ webencodings==0.5.1 \ whitenoise==5.2.0 \ --hash=sha256:05ce0be39ad85740a78750c86a93485c40f08ad8c62a6006de0233765996e5c7 \ --hash=sha256:05d00198c777028d72d8b0bbd234db605ef6d60e9410125124002518a48e515d - # via -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # via -r requirements.txt willow==1.4.1 \ --hash=sha256:0df8ff528531e00b48d40bf72ed81beac1dc82f2d42e5bbed4aff0218bef8c0d \ --hash=sha256:fc4042696d090e75aef922fa1ed26d483c764f005b36cf523cf7c34e69d5dd7a # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # wagtail wsproto==1.2.0 \ --hash=sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065 \ @@ -1256,23 +1187,23 @@ xlrd==2.0.1 \ --hash=sha256:6a33ee89877bd9abc1158129f6e94be74e2679636b8a205b43b85206c3f0bbdd \ --hash=sha256:f72f148f54442c6b056bf931dbc34f986fd0c3b0b6b5a58d013c9aef274d0c88 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # tablib xlsxwriter==3.2.0 \ --hash=sha256:9977d0c661a72866a61f9f7a809e25ebbb0fb7036baa3b9fe74afcfca6b3cb8c \ --hash=sha256:ecfd5405b3e0e228219bcaf24c2ca0915e012ca9464a14048021d21a995d490e # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # wagtail xlwt==1.3.0 \ --hash=sha256:a082260524678ba48a297d922cc385f58278b8aa68741596a87de01a9c628b2e \ --hash=sha256:c59912717a9b28f1a3c2a98fd60741014b06b043936dcecbc113eaaada156c88 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # tablib zipp==3.20.2 \ --hash=sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350 \ --hash=sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29 # via - # -r C:\Users\ankitchopra\Documents\iogt\requirements.txt + # -r requirements.txt # importlib-metadata From 710cd3bbd3d358a56c101f7b07b857ef06438e87 Mon Sep 17 00:00:00 2001 From: Sachin Mehta Date: Mon, 4 Aug 2025 06:22:24 +0000 Subject: [PATCH 032/147] Replaced field_as_li to field.html and removed cache for notifications --- home/templates/wagtailimages/images/edit.html | 2 +- iogt/templates/header.html | 7 ++-- iogt/templates/sw.js | 41 ++++++++++--------- .../wagtailadmin/chooser/external_link.html | 2 +- iogt/templates/wagtailusers/users/create.html | 16 ++++---- iogt/templates/wagtailusers/users/edit.html | 18 ++++---- .../templates/questionnaires/form_data.html | 2 +- user_notifications/views.py | 11 +++-- 8 files changed, 53 insertions(+), 46 deletions(-) diff --git a/home/templates/wagtailimages/images/edit.html b/home/templates/wagtailimages/images/edit.html index 93881a2e9..3da488dba 100644 --- a/home/templates/wagtailimages/images/edit.html +++ b/home/templates/wagtailimages/images/edit.html @@ -48,7 +48,7 @@ {% elif field.is_hidden %} {{ field }} {% else %} - {% include "wagtailadmin/shared/field_as_li.html" with li_classes="label-above" %} + {% include "wagtailadmin/shared/field.html" with li_classes="label-above" %} {% if field.name == 'title' %}

Remember title also act as alt text, so include a brief description for screen readers. diff --git a/iogt/templates/header.html b/iogt/templates/header.html index 83b3377fa..9088fbb64 100644 --- a/iogt/templates/header.html +++ b/iogt/templates/header.html @@ -74,9 +74,10 @@ .catch(err => console.warn("⚠️ Failed to fetch unread count", err)); } - // Poll every 15 seconds - setInterval(refreshUnreadCount, 15000); - document.addEventListener("DOMContentLoaded", refreshUnreadCount); + document.addEventListener("DOMContentLoaded", function () { + refreshUnreadCount(); // run it once when page loads + setInterval(refreshUnreadCount, 15000); // then every 15 seconds + }); function openNotificationsPanel() { document.querySelector('.notification-panel').style.display = 'block'; diff --git a/iogt/templates/sw.js b/iogt/templates/sw.js index ecc421e5d..ed64ada0a 100644 --- a/iogt/templates/sw.js +++ b/iogt/templates/sw.js @@ -164,27 +164,28 @@ self.addEventListener("fetch", (event) => { return; } if (request.method === 'GET') { - // ✅ Handle GET Requests (Serve from Cache when Offline) - event.respondWith( - fetch(request.clone(), { cache: 'no-store' }) // 1️⃣ Try the network first - .then(networkResponse => { - // 2️⃣ Optionally save a copy for offline use - const responseClone = networkResponse.clone(); // ✅ Clone early - const cacheRequest = new Request(request.url, { method: 'GET' }); - // Only cache successful, basic (same‑origin) responses - if (networkResponse.ok && networkResponse.type === 'basic' && request.method === 'GET') { - caches.open('iogt') - .then(cache => cache.put(cacheRequest, responseClone)) - .catch(err => console.warn('❌ Cache put failed', err)); - } - return networkResponse; // 3️⃣ Always return the live response - }) - .catch(() => { // 4️⃣ Network failed → offline fallback - return caches.match(request) // • Serve from cache if we have it - .then(cached => cached || // • …otherwise show a 503 - new Response('Offline', { status: 503 })); - }) + // ✅ Handle GET Requests (Serve from Cache when Offline) + event.respondWith( + fetch(request, { cache: 'no-store' }) // 1️⃣ Try the network first + .then(networkResponse => { + // 2️⃣ Optionally save a copy for offline use + const responseClone = networkResponse.clone(); // ✅ Clone early + const cacheRequest = new Request(request.url, { method: 'GET' }); + // Only cache successful, basic (same‑origin) responses + if (networkResponse.ok && networkResponse.type === 'basic' && request.method === 'GET') { + caches.open('iogt') + .then(cache => cache.put(cacheRequest, responseClone)) + .catch(err => console.warn('❌ Cache put failed', err)); + } + return networkResponse; // 3️⃣ Always return the live response + }) + .catch(() => { // 4️⃣ Network failed → offline fallback + return caches.match(request) // • Serve from cache if we have it + .then(cached => cached || // • …otherwise show a 503 + new Response('Offline', { status: 503 }) ); + }) + ); } }); diff --git a/iogt/templates/wagtailadmin/chooser/external_link.html b/iogt/templates/wagtailadmin/chooser/external_link.html index e7c960acc..284b87d04 100644 --- a/iogt/templates/wagtailadmin/chooser/external_link.html +++ b/iogt/templates/wagtailadmin/chooser/external_link.html @@ -13,7 +13,7 @@ {% csrf_token %}

    {% for field in form %} - {% include "wagtailadmin/shared/field_as_li.html" %} + {% include "wagtailadmin/shared/field.html" %} {% endfor %}
diff --git a/iogt/templates/wagtailusers/users/create.html b/iogt/templates/wagtailusers/users/create.html index e7976a7b6..88c39d133 100644 --- a/iogt/templates/wagtailusers/users/create.html +++ b/iogt/templates/wagtailusers/users/create.html @@ -2,19 +2,19 @@ {% block fields %} {% if form.separate_username_field %} - {% include "wagtailadmin/shared/field_as_li.html" with field=form.username_field %} + {% include "wagtailadmin/shared/field.html" with field=form.username_field %} {% endif %} - {% include "wagtailadmin/shared/field_as_li.html" with field=form.email %} + {% include "wagtailadmin/shared/field.html" with field=form.email %} {% block extra_fields %} - {% include "wagtailadmin/shared/field_as_li.html" with field=form.display_name %} - {% include "wagtailadmin/shared/field_as_li.html" with field=form.first_name %} - {% include "wagtailadmin/shared/field_as_li.html" with field=form.last_name %} - {% include "wagtailadmin/shared/field_as_li.html" with field=form.terms_accepted %} + {% include "wagtailadmin/shared/field.html" with field=form.display_name %} + {% include "wagtailadmin/shared/field.html" with field=form.first_name %} + {% include "wagtailadmin/shared/field.html" with field=form.last_name %} + {% include "wagtailadmin/shared/field.html" with field=form.terms_accepted %} {% endblock extra_fields %} {% if form.password1 %} - {% include "wagtailadmin/shared/field_as_li.html" with field=form.password1 %} + {% include "wagtailadmin/shared/field.html" with field=form.password1 %} {% endif %} {% if form.password2 %} - {% include "wagtailadmin/shared/field_as_li.html" with field=form.password2 %} + {% include "wagtailadmin/shared/field.html" with field=form.password2 %} {% endif %} {% endblock fields %} diff --git a/iogt/templates/wagtailusers/users/edit.html b/iogt/templates/wagtailusers/users/edit.html index 3c099849a..5c46be9bc 100644 --- a/iogt/templates/wagtailusers/users/edit.html +++ b/iogt/templates/wagtailusers/users/edit.html @@ -2,23 +2,23 @@ {% block fields %} {% if form.separate_username_field %} - {% include "wagtailadmin/shared/field_as_li.html" with field=form.username_field %} + {% include "wagtailadmin/shared/field.html" with field=form.username_field %} {% endif %} - {% include "wagtailadmin/shared/field_as_li.html" with field=form.email %} + {% include "wagtailadmin/shared/field.html" with field=form.email %} {% block extra_fields %} - {% include "wagtailadmin/shared/field_as_li.html" with field=form.display_name %} - {% include "wagtailadmin/shared/field_as_li.html" with field=form.first_name %} - {% include "wagtailadmin/shared/field_as_li.html" with field=form.last_name %} - {% include "wagtailadmin/shared/field_as_li.html" with field=form.terms_accepted %} + {% include "wagtailadmin/shared/field.html" with field=form.display_name %} + {% include "wagtailadmin/shared/field.html" with field=form.first_name %} + {% include "wagtailadmin/shared/field.html" with field=form.last_name %} + {% include "wagtailadmin/shared/field.html" with field=form.terms_accepted %} {% endblock extra_fields %} {% if form.password1 %} - {% include "wagtailadmin/shared/field_as_li.html" with field=form.password1 %} + {% include "wagtailadmin/shared/field.html" with field=form.password1 %} {% endif %} {% if form.password2 %} - {% include "wagtailadmin/shared/field_as_li.html" with field=form.password2 %} + {% include "wagtailadmin/shared/field.html" with field=form.password2 %} {% endif %} {% if form.is_active %} - {% include "wagtailadmin/shared/field_as_li.html" with field=form.is_active %} + {% include "wagtailadmin/shared/field.html" with field=form.is_active %} {% endif %} {% endblock fields %} \ No newline at end of file diff --git a/questionnaires/templates/questionnaires/form_data.html b/questionnaires/templates/questionnaires/form_data.html index 0191b9a96..59c2e2328 100644 --- a/questionnaires/templates/questionnaires/form_data.html +++ b/questionnaires/templates/questionnaires/form_data.html @@ -52,7 +52,7 @@

diff --git a/home/templates/wagtailimages/generic/edit.html b/home/templates/wagtailimages/generic/edit.html deleted file mode 100644 index 890facf87..000000000 --- a/home/templates/wagtailimages/generic/edit.html +++ /dev/null @@ -1,39 +0,0 @@ -{# templates/wagtailadmin/generic/edit.html #} -{% extends "wagtailadmin/base.html" %} -{% load wagtailadmin_tags i18n %} - -{% block titletag %}{{ view.get_page_title }}{% endblock %} - -{% block content %} -
-
- {% csrf_token %} - -
    - {# Title field #} - - - {# File field (for image/document uploads) #} - {% if form.file %} - {% include "wagtailadmin/shared/field.html" with field=form.file %} - {% endif %} - - {# Collection dropdown #} - {% if form.collection %} - {% include "wagtailadmin/shared/field.html" with field=form.collection %} - {% endif %} - - {# Duration field (if your model defines it) #} - {% if form.duration %} - {% include "wagtailadmin/shared/field.html" with field=form.duration %} - {% endif %} -
- -
- -
-
-
-{% endblock %} diff --git a/home/templatetags/home_tags.py b/home/templatetags/home_tags.py index 62a4fc4ba..46f4e3565 100644 --- a/home/templatetags/home_tags.py +++ b/home/templatetags/home_tags.py @@ -170,14 +170,4 @@ def social_meta_tags(context): if page: context['site_name'] = page.get_site().site_name - return context - - -@register.simple_tag -def usage_count_enabled(): - """ - Returns True or False depending on your business logic. - This will be callable as {% usage_count_enabled %} in templates. - """ - # Example logic — replace with your actual condition - return True \ No newline at end of file + return context \ No newline at end of file diff --git a/home/templatetags/language_tags.py b/home/templatetags/language_tags.py deleted file mode 100644 index 856d66837..000000000 --- a/home/templatetags/language_tags.py +++ /dev/null @@ -1,6 +0,0 @@ -from django import template -from django.conf import settings -from django.utils.translation import get_language_info - -register = template.Library() - diff --git a/home/wagtail_hooks.py b/home/wagtail_hooks.py index 35c940554..49e6b91d2 100644 --- a/home/wagtail_hooks.py +++ b/home/wagtail_hooks.py @@ -140,31 +140,6 @@ def page_listing_buttons(page, is_parent=False, next_url=None, user=None, **kwar ) -# @hooks.register("register_admin_menu_item") -# def about(): -# items = [ -# MenuItem( -# label=f"IoGT {settings.SITE_VERSION}", -# url=f"http://github.com/unicef/iogt/releases/tag/{settings.SITE_VERSION}", -# ), -# MenuItem( -# label=f"Wagtail {__version__}", -# url=f"http://github.com/wagtail/wagtail/releases/tag/v{__version__}" -# ) -# ] - -# # NOTE: -# # Removed `from wagtail_modeladmin.menus import SubMenu` as `SubMenu` is no longer available in the latest wagtail-modeladmin. -# # Used a direct list of MenuItems in SubmenuMenuItem instead. -# # This preserves the "About" submenu with IoGT and Wagtail version links. -# # If future updates break this, consider defining a lightweight `SubMenu` wrapper or refactor to top-level items. -# return SubmenuMenuItem( -# label="About", -# menu=items, -# icon_name="info-circle", -# order=999999, -# ) - @hooks.register("register_admin_menu_item") def about(): items = [ diff --git a/iogt/settings/base.py b/iogt/settings/base.py index c2b1af83e..8618f9016 100644 --- a/iogt/settings/base.py +++ b/iogt/settings/base.py @@ -83,6 +83,7 @@ 'wagtail_localize', 'wagtail_localize.locales', 'wagtail_transfer', + 'wagtailcache', 'wagtailmarkdown', 'wagtailmedia', 'wagtailmenus', @@ -90,10 +91,7 @@ 'webpush', 'admin_login', 'email_service', - 'wagtailcache' ] -#'wagtail-modeladmin', -#'wagtail_localize', # The order of middleware is very important. Take care when modifying this list. MIDDLEWARE = [ @@ -115,9 +113,9 @@ # 'admin_login.middleware.CustomAdminLoginRequiredMiddleware', 'wagtailcache.cache.FetchFromCacheMiddleware', # 'wagtail.contrib.statcache.middleware.StatCacheMiddleware', - 'django.middleware.cache.UpdateCacheMiddleware', # Must be first + 'django.middleware.cache.UpdateCacheMiddleware', 'django.middleware.cache.FetchFromCacheMiddleware', - "allauth.account.middleware.AccountMiddleware", # 👈 Add this here + "allauth.account.middleware.AccountMiddleware", ] # Prevent Wagtail's built in menu from showing in Admin > Settings diff --git a/iogt/static/css/iogt.css b/iogt/static/css/iogt.css index 005f6c32e..b43454acc 100644 --- a/iogt/static/css/iogt.css +++ b/iogt/static/css/iogt.css @@ -2761,6 +2761,4 @@ width: 30%; font-size: 14px; } - } - - \ No newline at end of file + } \ No newline at end of file diff --git a/iogt_users/forms.py b/iogt_users/forms.py index 3dde2643c..bba14078c 100644 --- a/iogt_users/forms.py +++ b/iogt_users/forms.py @@ -109,7 +109,6 @@ def clean_displayname(self): class Meta(WagtailUserCreationForm.Meta): model = User fields = WagtailUserCreationForm.Meta.fields | {'first_name', 'last_name', 'username', 'display_name', 'terms_accepted', 'groups'} - # fields = ('first_name', 'last_name', 'username', 'display_name', 'terms_accepted', 'groups') class WagtailAdminUserEditForm(WagtailUserEditForm): diff --git a/iogt_users/templates/iogt_users/wagtailusers/users/index.html b/iogt_users/templates/iogt_users/wagtailusers/users/index.html index d98e5a405..753cc99f1 100644 --- a/iogt_users/templates/iogt_users/wagtailusers/users/index.html +++ b/iogt_users/templates/iogt_users/wagtailusers/users/index.html @@ -24,48 +24,6 @@ {% trans "Select all users in listing" as select_all_text %} {% include 'wagtailadmin/bulk_actions/footer.html' with select_all_obj_text=select_all_text app_label=app_label model_name=model_name objects=users %}
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -