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..26e227f93 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 3.2.25 on 2025-08-08 09:24 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..76a415536 --- /dev/null +++ b/admin_notifications/views.py @@ -0,0 +1,61 @@ +import json +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 +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/notifications/wagtail_hooks.py b/admin_notifications/wagtail_hooks.py similarity index 60% rename from notifications/wagtail_hooks.py rename to admin_notifications/wagtail_hooks.py index a5582b6ad..6c4fac2a7 100644 --- a/notifications/wagtail_hooks.py +++ b/admin_notifications/wagtail_hooks.py @@ -1,13 +1,12 @@ from django.conf import settings from wagtail.contrib.modeladmin.options import ModelAdmin, modeladmin_register - -from notifications.models import Notification -from notifications.views import CreateNotificationView +from admin_notifications.models import AdminNotification +from admin_notifications.views import CreateNotificationView class NotificationModelAdmin(ModelAdmin): - model = Notification - menu_label = 'Notifications' + model = AdminNotification + menu_label = 'Admin Notifications' menu_icon = 'mail' list_display = ('head', 'body', 'url',) list_filter = ('groups',) @@ -15,6 +14,3 @@ class NotificationModelAdmin(ModelAdmin): menu_order = 601 create_view_class = CreateNotificationView - -if settings.PUSH_NOTIFICATION: - modeladmin_register(NotificationModelAdmin) 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/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/models.py b/home/models.py index e29442647..d2ce54ac7 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 ( @@ -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) @@ -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/global.css b/home/static/css/global/global.css index 4df37737f..f7bed26fc 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,225 @@ 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-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/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 %}