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/notifications/README.md b/admin_notifications/README.md
similarity index 100%
rename from notifications/README.md
rename to admin_notifications/README.md
diff --git a/notifications/__init__.py b/admin_notifications/__init__.py
similarity index 100%
rename from notifications/__init__.py
rename to admin_notifications/__init__.py
diff --git a/admin_notifications/apps.py b/admin_notifications/apps.py
new file mode 100644
index 000000000..48789da9a
--- /dev/null
+++ b/admin_notifications/apps.py
@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class AdminNotificationsConfig(AppConfig):
+ name = 'admin_notifications'
diff --git a/notifications/migrations/0001_initial.py b/admin_notifications/migrations/0001_initial.py
similarity index 83%
rename from notifications/migrations/0001_initial.py
rename to admin_notifications/migrations/0001_initial.py
index 8fbdf6886..7294fda61 100644
--- a/notifications/migrations/0001_initial.py
+++ b/admin_notifications/migrations/0001_initial.py
@@ -1,4 +1,4 @@
-# Generated by Django 3.1.14 on 2022-07-29 13:17
+# Generated by Django 5.2.4 on 2025-09-04 11:37
from django.db import migrations, models
@@ -13,13 +13,13 @@ class Migration(migrations.Migration):
operations = [
migrations.CreateModel(
- name='Notification',
+ name='AdminNotification',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('head', models.CharField(max_length=255)),
('body', models.TextField()),
('url', models.URLField(blank=True, null=True)),
- ('groups', models.ManyToManyField(related_name='notifications', to='auth.Group')),
+ ('groups', models.ManyToManyField(related_name='admin_notifications', to='auth.group')),
],
),
]
diff --git a/notifications/migrations/__init__.py b/admin_notifications/migrations/__init__.py
similarity index 100%
rename from notifications/migrations/__init__.py
rename to admin_notifications/migrations/__init__.py
diff --git a/notifications/models.py b/admin_notifications/models.py
similarity index 80%
rename from notifications/models.py
rename to admin_notifications/models.py
index 464f46cf7..82b661427 100644
--- a/notifications/models.py
+++ b/admin_notifications/models.py
@@ -1,12 +1,12 @@
from django.db import models
-
-class Notification(models.Model):
+class AdminNotification(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')
+ groups = models.ManyToManyField(to='auth.Group', related_name='admin_notifications')
def __str__(self):
return self.head
+
diff --git a/notifications/processors.py b/admin_notifications/processors.py
similarity index 100%
rename from notifications/processors.py
rename to admin_notifications/processors.py
diff --git a/admin_notifications/views.py b/admin_notifications/views.py
new file mode 100644
index 000000000..938f32541
--- /dev/null
+++ b/admin_notifications/views.py
@@ -0,0 +1,61 @@
+import json
+from user_notifications.models import NotificationMeta, NotificationLog
+from wagtail_modeladmin.views import CreateView
+from webpush import send_user_notification
+from notifications.signals import notify
+from notifications.models import Notification
+from iogt_users.models import User
+
+
+class CreateNotificationView(CreateView):
+ def form_valid(self, form):
+ payload = form.cleaned_data.copy()
+ groups = payload.pop('groups')
+ users = User.objects.filter(groups__in=groups).distinct()
+ for user in users:
+ 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
+
+ # 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)
+ NotificationLog.objects.create(
+ user=user,
+ notification_key=payload.get("head", "IoGT Notification"),
+ tags='',
+ state="sent",
+ notification=notif_instance
+ )
+ 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)}",
+ notification=None
+ )
+ return super().form_valid(form)
diff --git a/admin_notifications/wagtail_hooks.py b/admin_notifications/wagtail_hooks.py
new file mode 100644
index 000000000..44329a0ad
--- /dev/null
+++ b/admin_notifications/wagtail_hooks.py
@@ -0,0 +1,16 @@
+from django.conf import settings
+from wagtail_modeladmin.options import ModelAdmin
+from admin_notifications.models import AdminNotification
+from admin_notifications.views import CreateNotificationView
+
+
+class NotificationModelAdmin(ModelAdmin):
+ model = AdminNotification
+ menu_label = 'Admin Notifications'
+ menu_icon = 'mail'
+ list_display = ('head', 'body', 'url',)
+ list_filter = ('groups',)
+ search_fields = ('head', 'body', 'url',)
+ menu_order = 601
+ create_view_class = CreateNotificationView
+
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/templates/comment_reply.html b/comments/templates/comment_reply.html
index 95f448a9c..a8ce979e1 100644
--- a/comments/templates/comment_reply.html
+++ b/comments/templates/comment_reply.html
@@ -6,7 +6,7 @@
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/common/translation_utils/translation_status.csv b/common/translation_utils/translation_status.csv
index a5d3fb642..4c3b67cd4 100644
--- a/common/translation_utils/translation_status.csv
+++ b/common/translation_utils/translation_status.csv
@@ -716,3 +716,7 @@ Custom permissions,,,,needs translation,,,
Submit,,translate,,has partial translation,,,
Farsi,,not needed,,not needed,,,
Burmese,,not needed,,not needed,,,
+Hausa,,not needed,,not needed,,,
+Yoruba,,not needed,,not needed,,,
+Igbo,,not needed,,not needed,,,
+Pidgin,,not needed,,not needed,,,
diff --git a/common/translation_utils/translations.csv b/common/translation_utils/translations.csv
index 3ad9e949a..3e651baed 100644
--- a/common/translation_utils/translations.csv
+++ b/common/translation_utils/translations.csv
@@ -1,7 +1,7 @@
-Row type,is in use,comment,English,Spanish,French,Portuguese,Arabic,Swahili,Chichewa,Kinyarwanda,Ndebele,Shona,Kirundi,Malagasy,Nepali,Urdu,Kichwa/Quichua,Russian,Zulu,Tigrinya,Tajik,Kurdish,Khmer,Uzbek,Karakalpak,Indonesian,Sinhala,Tamil,Bengali,Dari,Pashto,Hindi,Ukraine,Turkish,Farsi,Burmese
-Language,,,English,Spanish,French,Portuguese,Arabic,Swahili,Chichewa,Kinyarwanda,Ndebele,Shona,Kirundi,Malagasy,Nepali,Urdu,Kichwa/Quichua,Russian,Zulu,Tigrinya,Tajik,Kurdish,Khmer,Uzbek,Karakalpak,Indonesian,Sinhala,Tamil,Bengali,Dari,Pashto,Hindi,Ukraine,Turkish,Farsi,Burmese
-ll-LL,,,en,es,fr-CG,pt-MZ,ar-MA,sw-KE,ny-MW,rw-RW,nr-ZW,sn-ZW,rn-BI,mg-MG,ne-NP,ur-PK,qu-EC,ru-RU,zu-ZA,ti-ET,tg-TJ,ku,km-KH,uz-UZ,kaa,id,si,ta,bn-BN,prs,ps,hi,uk,tr,fa,my
-ll,,,en,es,fr,pt,ar,sw,ny,rw,nr,sn,rn,mg,ne,ur,qu,ru,zu,ti,tg,ku,km,uz,kaa,id,si,ta,bn,prs,ps,hi,uk,tr,fa,my
+Row type,is in use,comment,English,Spanish,French,Portuguese,Arabic,Swahili,Chichewa,Kinyarwanda,Ndebele,Shona,Kirundi,Malagasy,Nepali,Urdu,Kichwa/Quichua,Russian,Zulu,Tigrinya,Tajik,Kurdish,Khmer,Uzbek,Karakalpak,Indonesian,Sinhala,Tamil,Bengali,Dari,Pashto,Hindi,Ukraine,Turkish,Farsi,Burmese,Hausa,Yoruba,Igbo,Pidgin
+Language,,,English,Spanish,French,Portuguese,Arabic,Swahili,Chichewa,Kinyarwanda,Ndebele,Shona,Kirundi,Malagasy,Nepali,Urdu,Kichwa/Quichua,Russian,Zulu,Tigrinya,Tajik,Kurdish,Khmer,Uzbek,Karakalpak,Indonesian,Sinhala,Tamil,Bengali,Dari,Pashto,Hindi,Ukraine,Turkish,Farsi,Burmese,Hausa,Yoruba,Igbo,Pidgin
+ll-LL,,,en,es,fr-CG,pt-MZ,ar-MA,sw-KE,ny-MW,rw-RW,nr-ZW,sn-ZW,rn-BI,mg-MG,ne-NP,ur-PK,qu-EC,ru-RU,zu-ZA,ti-ET,tg-TJ,ku,km-KH,uz-UZ,kaa,id,si,ta,bn-BN,prs,ps,hi,uk,tr,fa,my,ha,yo,ig,pcm
+ll,,,en,es,fr,pt,ar,sw,ny,rw,nr,sn,rn,mg,ne,ur,qu,ru,zu,ti,tg,ku,km,uz,kaa,id,si,ta,bn,prs,ps,hi,uk,tr,fa,my,ha,yo,ig,pcm
Region,,,English,Latin America,"West African, DRC","Angola, Mozambique",Morocco,Kenya,"Malawi, Zambia",Rwanda,Zimbabwe,Zimbabwe,Burundi,Madagascar,Nepal,Pakistan,Ecuador,Russia,South Africa,Ethiopia,Tajikistan,Sorani,Cambodia,Uzbekistan,Karakalpakstan,Indonesia,Sri Lanka,Sri Lanka,Bangladesh,Afghanistan,Afghanistan,India,Ukraine,Turkey,Iran,Myanmar
Section,,,Homepage,Homepage,Homepage,Homepage,Homepage,Homepage,Homepage,Homepage,Homepage,Homepage,Homepage,Homepage,Homepage,Homepage,Homepage,Homepage,Homepage,Homepage,Homepage,Homepage,Homepage,Homepage,Homepage,Homepage,Homepage,Homepage,Homepage,Homepage,Homepage,Homepage,Головна,,,
,,,Polls,Encuestas,Sondages,Votações,استطلاعات الرأي,Utafiti,Kafukufuku ofunsa maganizo a anthu,Amatora,Ikhetho,Sarudzo,Amatora,Fitsapan-kevitra,चुनावहरू,پولز,Tapuykuna,Голосования,Ukuvota,መረጻታት,Назарсанҷиҳо,دەنگدانەکان,ការបោះឆ្នោតស្ទង់មតិ,Tanlovlar,Sorawnama,Jajak pendapat,,,,,,,Опитування,,,
diff --git a/docker-compose.test.yml b/docker-compose.test.yml
index 445b2fcf0..4efbcd761 100644
--- a/docker-compose.test.yml
+++ b/docker-compose.test.yml
@@ -19,4 +19,4 @@ services:
environment:
POSTGRES_USER: iogt
POSTGRES_PASSWORD: iogt
- POSTGRES_DB: iogt
+ POSTGRES_DB: iogt
\ No newline at end of file
diff --git a/docker-compose.yml b/docker-compose.yml
index 3bd1b4755..99316da04 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -5,10 +5,43 @@ services:
target: dev
args:
requirements: requirements.dev.txt
- environment:
- DJANGO_SETTINGS_MODULE: iogt.settings.dev
+ env_file:
+ - .env
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
+ celery:
+ build:
+ context: ./
+ target: dev
+ args:
+ requirements: requirements.dev.txt
+ command: celery -A iogt worker -l info
+ depends_on:
+ - django
+ - redis
+ env_file:
+ - .env
+ volumes:
+ - ./:/app/
+
+ redis:
+ image: redis:7
+
+ db:
+ image: postgres:14-alpine
+ environment:
+ POSTGRES_USER: postgres
+ POSTGRES_PASSWORD: postgresiogt
+ POSTGRES_DB: iogt
\ No newline at end of file
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/forms.py b/home/forms.py
index a88ee6b3e..e04bf18f0 100644
--- a/home/forms.py
+++ b/home/forms.py
@@ -15,4 +15,4 @@ def clean(self):
f'This section is not eligible for showing the progress bar. '
f'Disable "Show Progress Bar" on "{progress_bar_enabled_ancestor_title}" section first.')
- return cleaned_data
+ return cleaned_data
\ No newline at end of file
diff --git a/home/management/commands/copy_page_revisions.py b/home/management/commands/copy_page_revisions.py
new file mode 100644
index 000000000..c23a56146
--- /dev/null
+++ b/home/management/commands/copy_page_revisions.py
@@ -0,0 +1,60 @@
+import logging
+from django.core.management.base import BaseCommand
+from django.contrib.contenttypes.models import ContentType
+from django.db import connection
+from wagtail.models import Page, Revision
+
+logger = logging.getLogger(__name__)
+
+class Command(BaseCommand):
+ help = "Copy missing revisions from wagtailcore_pagerevision to wagtail_revision"
+
+ def handle(self, *args, **options):
+ page_ct = ContentType.objects.get_for_model(Page)
+ copied, skipped, errors = 0, 0, 0
+
+ logger.info("Starting migration from wagtailcore_pagerevision → wagtail_revision")
+
+ with connection.cursor() as cursor:
+ cursor.execute("""
+ SELECT id, created_at, content, approved_go_live_at, page_id, user_id
+ FROM wagtailcore_pagerevision
+ """)
+ rows = cursor.fetchall()
+
+ for row in rows:
+ pr_id, created_at, content, approved_go_live_at, page_id, user_id = row
+
+ page = Page.objects.filter(id=page_id).first()
+ if not page:
+ logger.warning(f"Skipping orphaned revision {pr_id}, page_id={page_id} not found")
+ continue
+
+ # Deduplication check
+ if Revision.objects.filter(
+ content_type=page_ct,
+ object_id=str(page.id),
+ created_at=created_at,
+ ).exists():
+ skipped += 1
+ logger.debug(f"Skipped duplicate revision {pr_id} for page {page_id}")
+ continue
+
+ try:
+ Revision.objects.create(
+ base_content_type=page_ct,
+ content=content,
+ approved_go_live_at=approved_go_live_at,
+ created_at=created_at,
+ user_id=user_id,
+ content_type=page_ct,
+ object_id=str(page.id),
+ object_str=str(page),
+ )
+ copied += 1
+ logger.info(f"Copied revision {pr_id} → page {page_id}")
+ except Exception as e:
+ errors += 1
+ logger.error(f"Error copying revision {pr_id}: {e}")
+
+ logger.info(f"Migration completed. Copied={copied}, Skipped={skipped}, Errors={errors}")
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/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/migrations/0062_alter_manifestsettings_language.py b/home/migrations/0062_alter_manifestsettings_language.py
new file mode 100644
index 000000000..d634d7a82
--- /dev/null
+++ b/home/migrations/0062_alter_manifestsettings_language.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.2.25 on 2025-08-18 10:31
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('home', '0061_article_notification_tags'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='manifestsettings',
+ name='language',
+ field=models.CharField(choices=[('ar', 'Arabic'), ('bn', 'Bengali'), ('ny', 'Chichewa'), ('prs', 'Dari'), ('en', 'English'), ('fa', 'Farsi'), ('fr', 'French'), ('hi', 'Hindi'), ('id', 'Indonesian'), ('kaa', 'Karakalpak'), ('km', 'Khmer'), ('rw', 'Kinyarwanda'), ('rn', 'Kirundi'), ('ku', 'Kurdish'), ('mg', 'Malagasy'), ('my', 'Burmese'), ('ne', 'Nepali'), ('nr', 'Ndebele'), ('ps', 'Pashto'), ('pt', 'Portuguese'), ('qu', 'Quechua'), ('ru', 'Russian'), ('sn', 'Shona'), ('si', 'Sinhala'), ('es', 'Spanish'), ('sw', 'Swahili'), ('tg', 'Tajik'), ('ta', 'Tamil'), ('ti', 'Tigrinya'), ('tr', 'Turkish'), ('uk', 'Ukraine'), ('ur', 'Urdu'), ('uz', 'Uzbek'), ('zu', 'Zulu'), ('xy', 'Testing'), ('ha', 'Hausa'), ('yo', 'Yoruba'), ('ig', 'Igbo'), ('pcm', 'Pidgin')], default='en', help_text='Choose language', max_length=3, verbose_name='Language'),
+ ),
+ ]
diff --git a/home/migrations/0063_section_notification_tags_and_more.py b/home/migrations/0063_section_notification_tags_and_more.py
new file mode 100644
index 000000000..3dc4d44ca
--- /dev/null
+++ b/home/migrations/0063_section_notification_tags_and_more.py
@@ -0,0 +1,32 @@
+# Generated by Django 5.2.4 on 2025-09-04 06:06
+
+import django.db.models.deletion
+import modelcluster.fields
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('home', '0062_alter_manifestsettings_language'),
+ ('taggit', '0006_rename_taggeditem_content_type_object_id_taggit_tagg_content_8fc721_idx'),
+ ('user_notifications', '0005_seed_notification_tables'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='section',
+ name='notification_tags',
+ field=modelcluster.fields.ParentalManyToManyField(blank=True, to='user_notifications.notificationtag'),
+ ),
+ migrations.AlterField(
+ model_name='articletaggeditem',
+ name='tag',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(app_label)s_%(class)s_items', to='taggit.tag'),
+ ),
+ migrations.AlterField(
+ model_name='sectiontaggeditem',
+ name='tag',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(app_label)s_%(class)s_items', to='taggit.tag'),
+ ),
+ ]
diff --git a/home/models.py b/home/models.py
index e29442647..21c24f6ab 100644
--- a/home/models.py
+++ b/home/models.py
@@ -14,8 +14,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 (
@@ -25,7 +25,7 @@
ObjectList,
TabbedInterface,
)
-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
@@ -55,7 +55,7 @@
)
import iogt.iogt_globals as globals_
from django.db.models import Avg, Count
-
+from user_notifications.models import NotificationTag, NotificationPreference
User = get_user_model()
logger = logging.getLogger(__name__)
@@ -125,8 +125,12 @@ 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):
return [self.url] + collect_urls_from_streamfield(self.home_featured_content)
@@ -214,7 +218,7 @@ class Section(Page, PageUtilsMixin, CommentableMixin, TitleIconMixin):
blank=True,
use_json_field=True,
)
-
+ notification_tags = ParentalManyToManyField(NotificationTag, blank=True)
tags = ClusterTaggableManager(through='SectionTaggedItem', blank=True)
show_progress_bar = models.BooleanField(default=False)
larger_image_for_top_page_in_list_as_in_v1 = models.BooleanField(default=False)
@@ -222,7 +226,7 @@ class Section(Page, PageUtilsMixin, CommentableMixin, TitleIconMixin):
show_in_menus_default = True
promote_panels = Page.promote_panels + [
- MultiFieldPanel([FieldPanel("tags"), ], heading='Metadata'),
+ MultiFieldPanel([FieldPanel("tags"), FieldPanel("notification_tags"),], heading='Metadata'),
]
content_panels = Page.content_panels + [
@@ -482,7 +486,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 +496,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 = [
@@ -573,7 +577,6 @@ class BannerIndexPage(Page):
parent_page_types = ['home.HomePage']
subpage_types = ['home.BannerPage']
-
class BannerPage(Page, PageUtilsMixin):
parent_page_types = ['home.BannerIndexPage']
subpage_types = []
diff --git a/home/static/css/global/admin.css b/home/static/css/global/admin.css
index 75c2f1bda..b3583a70b 100644
--- a/home/static/css/global/admin.css
+++ b/home/static/css/global/admin.css
@@ -1,24 +1,282 @@
.action-add-block-paragraph_v1_legacy {
- text-decoration: line-through;
- pointer-events: none;
- background-color: gray;
+ text-decoration: line-through;
+ pointer-events: none;
+ background-color: gray;
}
.red-help-text p.help {
- color: red;
- font-weight: bold;
+ color: red;
+ font-weight: bold;
}
.disabled-clean-name textarea {
- pointer-events: none;
- background-color: #e6e6e6;
- color: #4d4d4d;
+ pointer-events: none;
+ background-color: #e6e6e6;
+ color: #4d4d4d;
}
-.object > h2.title-wrapper:before {
- height: 40px;
+.object>h2.title-wrapper:before {
+ height: 40px;
}
-.object > h2.title-wrapper {
- position: unset;
+.object>h2.title-wrapper {
+ position: unset;
}
+
+.w-field--collection_choice_field select,
+.w-w-field .w-field--commentable select {
+ width: 100%;
+ max-width: 100%;
+ box-sizing: border-box;
+}
+
+.listing-filter select,
+.c-dropdown select {
+ min-height: 40px;
+ padding: 6px 10px;
+ border-radius: 6px;
+ font-size: 14px;
+}
+
+#collection_chooser_collection_id-label {
+ margin-right: 20px;
+ white-space: nowrap;
+}
+
+#collection_chooser_collection_id {
+ width: 100%;
+ max-width: 100%;
+}
+
+@media (min-width: 768px) {
+ #collection_chooser_collection_id {
+ max-width: 600px;
+ }
+}
+
+@media (min-width: 1200px) {
+ #collection_chooser_collection_id {
+ max-width: 800px;
+ }
+}
+
+.w-field__input input:not(#id_q),
+.w-field__input select[id="collection_chooser_collection_id"] {
+ background-color: #f8f8f8 !important;
+ border: 1px solid #b1b4b6 !important;
+ border-radius: 4px !important;
+ transition: background-color 0.2s ease, border-color 0.2s ease;
+}
+
+.w-field__input select#collection_chooser_collection_id:hover {
+ background-color: #fff !important;
+}
+
+#wrapper #collection_chooser_collection_id:focus,
+.w-field__input select#collection_chooser_collection_id:focus {
+ background-color: #fff !important;
+ border-color: #ffbf47 !important;
+ box-shadow: 0 0 0 3px rgba(255, 191, 71, 0.5) !important;
+ outline: 0 !important;
+}
+
+
+.w-field__input select#id_adddocument_collection {
+ width: 100% !important;
+ max-width: none !important;
+ box-sizing: border-box;
+}
+
+.w-field__input select[id="id_collection"] {
+ width: 100% !important;
+ min-width: unset;
+ max-width: 880px;
+ background-color: #f8f8f8 !important;
+ border: 1px solid #b1b4b6 !important;
+ border-radius: 4px !important;
+ padding: 14px 15px !important;
+ font-size: 18px !important;
+ line-height: 1.4 !important;
+}
+
+@media (min-width: 768px) and (max-width: 1199px) {
+ .w-field__input select[id="id_collection"] {
+ width: 100% !important;
+ max-width: 750px;
+ }
+}
+
+@media (min-width: 1200px) {
+ .w-field__input select[id="id_collection"] {
+ max-width: 880px;
+ }
+}
+
+.w-field {
+ display: block;
+ /* margin-bottom: 1rem; */
+}
+
+.w-field__label {
+ display: block;
+ margin-bottom: 0.5rem;
+ max-width: 100%;
+}
+
+.w-field__input {
+ display: block;
+ width: 100%;
+}
+
+.w-field__input select[id="id_language_code"] {
+ width: 100%;
+ box-sizing: border-box;
+ background-color: #fafafa;
+ border: 1px solid var(--w-color-border-field, #ccc);
+ border-radius: 4px;
+ padding: 0.5rem;
+}
+
+@media screen and (min-width: 50em) {
+ .w-field--choice_field {
+ box-sizing: border-box;
+ display: flex;
+ align-items: center;
+ gap: 1rem;
+ }
+
+ .w-field__input {
+ max-width: 100.3333%;
+ }
+
+
+ .w-field__input select[id="id_language_code"] {
+ width: 100% !important;
+ background-color: #fafafa;
+ border: 1px solid var(--w-color-border-field, #ccc);
+ border-radius: 4px;
+ padding: 0.5rem;
+ }
+}
+
+header .left:first-child {
+ float: left;
+ padding-bottom: 0;
+}
+
+header .right {
+ float: right;
+ text-align: end;
+}
+
+header h1 {
+ color: #2e1f5e;
+ position: relative;
+}
+
+header svg {
+ max-height: 1em;
+ max-width: 1em;
+}
+
+
+.row-flex {
+ display: flex;
+ align-items: center;
+}
+
+.row-flex .left {
+ flex: auto;
+ align-items: center;
+ display: flex;
+}
+
+.fields-inline {
+ display: flex;
+ gap: 0.75rem;
+ align-items: center;
+}
+
+.fields-inline>li {
+ margin: 0;
+ flex: 0 0 auto;
+}
+
+.changelist-filter ul li a {
+ display: block;
+ padding: 8px 12px;
+ margin: 6px 0;
+ border: 1px solid rgb(0, 125, 126);
+ border-radius: 3px;
+ background-color: #fff;
+ text-decoration: none;
+ color: rgb(0, 125, 126);
+ font-size: .9em;
+ font-weight: 400;
+ line-height: 1.2em;
+ box-sizing: border-box;
+ font-size:12.24px
+}
+
+.changelist-filter ul li a:hover {
+ background-color: #e0f2f1;
+}
+
+
+
+.changelist-filter ul li.selected a {
+ background-color:rgb(0, 125, 126) !important;
+ border-color: rgb(0, 125, 126) !important;
+ color: #fff !important;
+}
+
+.dropdown-container {
+ margin-left: 10px;
+ display: flex;
+ align-items: center;
+ background-color: rgb(0, 125, 126);
+ font-size: .875rem;
+ height: 3em;
+ line-height: calc(3em - 2px);
+ padding: 0 1.4em;
+ -webkit-font-smoothing: auto;
+ border: 1px solid rgb(0, 125, 126);
+ border-radius: .1875rem;
+ display: inline-block;
+ font-weight: 400;
+ outline-offset: 3px;
+ padding: 0 1em;
+ position: relative;
+ text-decoration: none;
+ transition: background-color .1s ease;
+ vertical-align: middle;
+ white-space: nowrap;
+ width: auto;
+}
+
+.dropdown-container:hover {
+ background-color: rgb(0, 91, 94);
+ border-color: #0000;
+}
+
+.dropdown-container button {
+ height: 100%;
+}
+
+.header-title {
+ margin-right: 1.5rem;
+}
+
+.dropdown-container .w-dropdown__toggle {
+ color: white;
+}
+
+.c-wagtailautocomplete__suggestions__item--active, .c-wagtailautocomplete__selection {
+ background-color: rgb(0, 125, 126) !important;
+ color: white !important;
+}
+
+svg.c-wagtailautocomplete__search-icon {
+ height: 30px !important;
+ width: 30px !important;
+}
\ No newline at end of file
diff --git a/home/static/css/global/global.css b/home/static/css/global/global.css
index 4df37737f..42dfb5b1e 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,20 +1306,101 @@ 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;
+ -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: 5px;
+}
+
+.notification-bell-wrapper {
+ position: relative;
+ display: inline-block;
+}
+
+.notification-bell {
+ font-size: 1.5rem;
+ transition: color 0.3s ease;
+ display: flex;
+}
+
+#notif-bell.highlighted {
+ fill: #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;
+ 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;
- appearance: none;
+ -moz-appearance: none;
+ appearance: none;
margin-right: 10px;
background: #FDD256;
border: none;
@@ -1273,14 +1415,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;
@@ -1302,17 +1444,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;
@@ -1332,7 +1474,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;
@@ -1361,9 +1503,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;
@@ -1389,14 +1531,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 {
@@ -1420,11 +1567,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 {
@@ -1437,31 +1589,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;
}
@@ -1489,7 +1656,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;
@@ -1502,6 +1669,7 @@ body.rtl {
border-radius: 0;
border-width: 0 0 1px 0;
}
+
.footer-head #header,
.footer-head .header-holder {
/* padding-left: 0;
@@ -1531,15 +1699,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; */
}
@@ -1570,15 +1741,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;
}
@@ -1587,22 +1761,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;
}
@@ -1616,18 +1798,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;
@@ -1635,6 +1824,7 @@ body.rtl {
box-sizing: border-box;
}
}
+
@media screen and (min-width: 1400px) {
.header-holder {
max-width: 1400px;
@@ -1642,12 +1832,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%;
@@ -1657,6 +1849,7 @@ body.rtl {
#header .btn-holder .nav-bar__item__icon {
/* display: flex; */
}
+
#header .btn-holder .nav-bar__item a {
margin: 0;
}
@@ -1666,6 +1859,7 @@ body.rtl {
width: 29%;
max-width: 400px;
}
+
.link-login {
display: none;
}
@@ -1673,30 +1867,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 {
@@ -1713,7 +1907,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;
@@ -1773,11 +1968,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 {
@@ -1802,7 +1997,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;
@@ -1914,9 +2110,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 {
@@ -1930,8 +2126,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 */
@@ -1943,4 +2141,240 @@ body.rtl {
width: 100%;
height: auto;
}
-/* questionnaires end */
\ No newline at end of file
+
+/* questionnaires end */
+
+
+
+/* Notification Section */
+.notification-overlay {
+ position: fixed;
+ display: none;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: rgba(0,0,0,0.4);
+ z-index: 999;
+}
+
+/* Notification panel */
+.notification-panel {
+ position: fixed;
+ top: 0;
+ right: 0;
+ width: 460px;
+ height: 100%;
+ background: #fff;
+ box-shadow: -4px 0 12px rgba(0,0,0,0.2);
+ padding: 24px;
+ font-family: Arial, sans-serif;
+ display: none;
+ flex-direction: column;
+ z-index: 1000;
+ overflow-y: auto;
+}
+
+/* Header */
+.notification-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ 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: 20px;
+ cursor: pointer;
+ width: 20%;
+}
+
+.notification-list {
+ margin: 0;
+ padding: 0;
+}
+
+.notification-item {
+ display: block;
+ width: 100%;
+ padding: 1rem;
+ text-decoration: none;
+ color: inherit;
+ border-bottom: 1px solid #e6e6e6;
+ 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.read {
+ background-color: #fff;
+ font-weight: normal;
+}
+
+.notification-body {
+ margin: 0;
+ padding: 0;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+
+.notification-text {
+ margin: 0;
+ font-size: 0.8rem;
+}
+
+.notification-title {
+ font-weight: 600;
+ font-size: 0.85rem;
+}
+
+.notification-empty {
+ padding: 24px;
+ text-align: center;
+ color: #999;
+ font-style: italic;
+}
+
+.notification-footer {
+ text-align: center;
+ padding: 12px 0;
+ background: #fafafa;
+ border-top: 1px solid #e0e0e0;
+}
+
+.notification-footer a {
+ color: #3367d6;
+ font-weight: 500;
+ text-decoration: none;
+}
+
+.notification-footer a:hover {
+ text-decoration: underline;
+}
+
+.bold {
+ font-weight: bold;
+}
+
+.unread-dot {
+ display: inline-block;
+ width: 8px;
+ height: 8px;
+ background-color: #007bff; /* Bootstrap primary blue */
+ border-radius: 50%;
+ margin-left: 8px;
+}
+
+@media (max-width: 768px) {
+ #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;
+}
+
+
+.notification-callout-text {
+ background-color: #eaf7ff;
+ color: #0c5460;
+ font-size: 13px;
+ padding: 4px 8px;
+ margin-top: 5px;
+ border-radius: 4px;
+}
+
+.enable-notifications-nudge {
+ position: fixed;
+ bottom: 20px;
+ left: 20px;
+ background-color: #fff8e1;
+ color: black;
+ 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;
+ font-size: large;
+}
+
+.notification-preference-on-registration-survey {
+ background-color: #fff8e1;
+ color: black;
+ 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;
+ font-family: "Segoe UI", sans-serif;
+ animation: slideIn 0.5s ease-out;
+ margin-top: 15px;
+ font-size: large;
+}
+
+.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;
+ }
+}
+
+.notification-name {
+ font-size: 0.75rem;
+ color: #555;
+ margin: 0;
+ margin-bottom: 5px;
+}
\ No newline at end of file
diff --git a/home/templates/blocks/image.html b/home/templates/blocks/image.html
index a0de1a5ad..6180cef8b 100644
--- a/home/templates/blocks/image.html
+++ b/home/templates/blocks/image.html
@@ -1,3 +1,2 @@
{% load home_tags %}
-
-{% render_image value %}
+{% render_image value %}
\ No newline at end of file
diff --git a/home/templates/home/home_page.html b/home/templates/home/home_page.html
index 99c3ffaba..1556fdfaa 100644
--- a/home/templates/home/home_page.html
+++ b/home/templates/home/home_page.html
@@ -9,6 +9,11 @@
{% 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/home/templates/wagtailimages/images/edit.html b/home/templates/wagtailimages/edit.html
similarity index 73%
rename from home/templates/wagtailimages/images/edit.html
rename to home/templates/wagtailimages/edit.html
index 93881a2e9..cc9f69c2c 100644
--- a/home/templates/wagtailimages/images/edit.html
+++ b/home/templates/wagtailimages/edit.html
@@ -1,16 +1,15 @@
{% extends "wagtailadmin/base.html" %}
{% load wagtailimages_tags wagtailadmin_tags i18n l10n %}
+{% load home_tags %}
{% block titletag %}{% blocktrans trimmed with title=image.title %}Editing image {{ title }}{% endblocktrans %}{% endblock %}
{% block extra_css %}
{{ block.super }}
{{ form.media.css }}
-
-
-
{% endblock %}
+
{% block extra_js %}
{{ block.super }}
@@ -24,11 +23,6 @@
});
});
-
-
-
-
-
{% endblock %}
{% block content %}
@@ -44,11 +38,22 @@
{% for field in form %}
{% if field.name == 'file' %}
- {% include "wagtailimages/images/_file_field_as_li.html" with li_classes="label-above" %}
+ {% if form.instance.pk and form.instance.file %}
+
+ {{ form.instance.file.name }}
+
+ {% endif %}
+ {% include "wagtailadmin/shared/field.html" with field=field %}
{% elif field.is_hidden %}
{{ field }}
{% else %}
- {% include "wagtailadmin/shared/field_as_li.html" with li_classes="label-above" %}
+ {% if field.name == "collection" %}
+
+ {% include "wagtailadmin/shared/field.html" with field=field %}
+
+ {% else %}
+ {% include "wagtailadmin/shared/field.html" with field=field %}
+ {% endif %}
{% if field.name == 'title' %}
Remember title also act as alt text, so include a brief description for screen readers.
@@ -59,9 +64,9 @@
@@ -99,27 +104,20 @@
-