diff --git a/base/templates/blocks/products_by_service_menu.html b/base/templates/blocks/products_by_service_menu.html index 30449e1e..d2e51f46 100644 --- a/base/templates/blocks/products_by_service_menu.html +++ b/base/templates/blocks/products_by_service_menu.html @@ -13,23 +13,11 @@ -
+
{% for sub_page in products %} {% if sub_page.show_in_menus and sub_page.live %} -
+
- diff --git a/nmhs_cms/static/css/navigation.css b/nmhs_cms/static/css/navigation.css index f6e0aee9..2d1a9d68 100644 --- a/nmhs_cms/static/css/navigation.css +++ b/nmhs_cms/static/css/navigation.css @@ -238,27 +238,33 @@ header { .megamenu .service-group-title { font-size: 14px; - font-weight: 500; - padding: 10px 0; + font-weight: 600; + padding: 5px 0; display: flex; align-items: center; } .megamenu .service-group-icon { - height: 28px; - width: 28px; + height: 40px; + width: 40px; + border-radius: 50%; margin-right: 10px; + background-color: rgba(0, 153, 151, 0.1); + display: flex; + align-items: center; + justify-content: center; } .megamenu .service-group-icon svg { - height: 100%; - width: 100%; + height: 24px; + width: 24px; color: var(--primary-color); } .megamenu .service-group-items { - margin-left: 8px; - padding: 4px 0 0; + margin-left: 10px; + margin-bottom: 4px; + padding: 4px 0; } .megamenu .sub-items-list { @@ -266,6 +272,10 @@ header { border-top: 1px solid #f0f0f0; } +.megamenu .product-nav-item { + padding: 5px !important; +} + .alert { font-size: 14px @@ -282,6 +292,11 @@ header { @media screen and (max-width: 768px) { + .megamenu { + padding: 6px; + } + + .navbar-brand img { max-width: 200px; } diff --git a/pages/cap/models.py b/pages/cap/models.py index d6b5c42b..0ddce271 100644 --- a/pages/cap/models.py +++ b/pages/cap/models.py @@ -2,7 +2,6 @@ from capeditor.pubsub.publish import publish_cap_mqtt_message from django.db import models from django.urls import reverse -from django.utils import timezone from django.utils.functional import cached_property from django.utils.translation import gettext_lazy as _ from geomanager.models import SubCategory, Metadata @@ -41,29 +40,33 @@ def get_context(self, request, *args, **kwargs): @cached_property def cap_alerts(self): - alerts = CapAlertPage.objects.all().live().order_by('-sent') + alerts = CapAlertPage.objects.all().live().filter(status="Actual").order_by('-sent') alert_infos = [] for alert in alerts: for alert_info in alert.infos: - # info = alert_info.get("info") - # if info.value.get('expires').date() >= datetime.today().date(): alert_infos.append(alert_info) + alert_infos = sorted(alert_infos, key=lambda x: x.get("sent", {}), reverse=True) + return alert_infos @cached_property - def active_alerts(self): - alerts = CapAlertPage.objects.all().live().order_by('-sent') - active_alert_infos = [] - - for alert in alerts: - for alert_info in alert.infos: - info = alert_info.get("info") - if info.value.get('expires') > timezone.localtime(): - active_alert_infos.append(alert_info) + def alerts_by_expiry(self): + all_alerts = self.cap_alerts + active_alerts = [] + past_alerts = [] + + for alert in all_alerts: + if alert.get("expired"): + past_alerts.append(alert) + else: + active_alerts.append(alert) - return active_alert_infos + return { + "active_alerts": active_alerts, + "past_alerts": past_alerts + } @cached_property def filters(self): @@ -111,6 +114,9 @@ class CapAlertPage(MetadataPageMixin, AbstractCapAlertPage): *AbstractCapAlertPage.content_panels ] + class Meta: + ordering = ["-sent"] + @cached_property def xml_link(self): return reverse("cap_alert_detail", args=(self.identifier,)) diff --git a/pages/cap/static/cap/css/cap_list_page.css b/pages/cap/static/cap/css/cap_list_page.css index 8e48436f..c745e5fd 100644 --- a/pages/cap/static/cap/css/cap_list_page.css +++ b/pages/cap/static/cap/css/cap_list_page.css @@ -38,18 +38,74 @@ .alert-item-title { font-weight: 600; font-size: 15px; - } .alert-severity-label { font-size: 13px; } -.alert-effective { +.alert-time-info { font-size: 13px; + display: flex; + align-items: center; +} +.alert-info-headline { + font-size: 13px; + margin-bottom: 4px; +} + +.alert-time-info .time-icon { + width: 10px; + margin-right: 4px; +} + +.alert-time-info .time-icon svg { + height: 100%; + width: 100%; +} + + +.alert-time-info .time-em { + font-weight: 600; + margin-right: 4px; +} + + +.alert-effective { } .alert-category-filter { padding-bottom: 40px; +} + +.alerts-group { + margin-bottom: 50px; +} + +.alerts-group .group-title { + font-size: 24px; + font-weight: 600; + margin-bottom: 20px; +} + +.empty-alerts-state { + display: flex; + align-items: center; + font-size: 14px; + font-weight: 600; + background-color: #f8f9fb; + padding: 20px; +} + +.empty-alerts-icon { + height: 24px; + width: 24px; + margin-right: 8px; +} + +.empty-alerts-icon svg { + height: 100%; + width: 100%; + fill: green; } \ No newline at end of file diff --git a/pages/cap/templates/cap/alert_list.html b/pages/cap/templates/cap/alert_list.html index 8f103ad2..664671f5 100644 --- a/pages/cap/templates/cap/alert_list.html +++ b/pages/cap/templates/cap/alert_list.html @@ -23,51 +23,42 @@

{{ page.heading }}

{% endif %} -
{% endif %}
- {% for alert_info in page.cap_alerts %} - -
-
{% if page.filters.severity %} diff --git a/pages/cap/templates/cap/include_alert_list_item.html b/pages/cap/templates/cap/include_alert_list_item.html new file mode 100644 index 00000000..95430ce2 --- /dev/null +++ b/pages/cap/templates/cap/include_alert_list_item.html @@ -0,0 +1,48 @@ +{% load static wagtailcore_tags wagtailimages_tags lazyimages_tags wagtailiconchooser_tags i18n %} + + +
+
+
+
+ {% if alert_info.event_icon %} + {% svg_icon name=alert_info.event_icon %} + {% endif %} +
+
+
+
+ {{ alert_info.status }}: {{ alert_info.event|truncatechars:60 }} +
+ {% if alert_info.properties.headline %} +
+ {{ alert_info.properties.headline|truncatechars:60 }} +
+ {% endif %} +
+ + {% svg_icon name="calendar-alt" %} + + + {% translate "Issued on:" %} + + + {% blocktranslate trimmed with issued_on=alert_info.properties.sent|date:"d M Y h:i a" %} + {{ issued_on }} + {% endblocktranslate %} + +
+
+
+
+ + + +
+
+
\ No newline at end of file diff --git a/pages/cap/templatetags/cap_tags.py b/pages/cap/templatetags/cap_tags.py index e121dbf1..bd5b6053 100644 --- a/pages/cap/templatetags/cap_tags.py +++ b/pages/cap/templatetags/cap_tags.py @@ -10,7 +10,7 @@ @register.inclusion_tag(filename="cap/active_alert.html") def get_latest_active_cap_alert(): - alerts = CapAlertPage.objects.all().live().order_by('-sent') + alerts = CapAlertPage.objects.all().live().filter(status="Actual") active_alert_infos = [] for alert in alerts: diff --git a/pages/cap/views.py b/pages/cap/views.py index 629e45e1..751569bf 100644 --- a/pages/cap/views.py +++ b/pages/cap/views.py @@ -65,18 +65,11 @@ def description(self): return None def items(self): - alerts = CapAlertPage.objects.all().live() - - active_alert_infos = [] - - for alert in alerts: - for info in alert.info: - active_alert_infos.append(alert.id) - - return CapAlertPage.objects.filter(id__in=active_alert_infos).live() + alerts = CapAlertPage.objects.all().live().filter(status="Actual") + return alerts def item_title(self, item): - return item.info[0].value.get('headline') + return item.title def item_link(self, item): return reverse("cap_alert_detail", args=[item.identifier]) @@ -91,16 +84,13 @@ def item_enclosures(self, item: Model) -> List[Enclosure]: return super().item_enclosures(item) def item_guid(self, item): - return item.identifier def item_author_name(self, item): - try: site = Site.objects.get(is_default_site=True) if site: cap_setting = CapSetting.for_site(site) - return cap_setting.sender except Exception: @@ -125,13 +115,13 @@ class AlertDetail(generics.RetrieveAPIView): serializer_class.Meta.model = CapAlertPage renderer_classes = (CapXMLRenderer,) - queryset = CapAlertPage.objects.live() + queryset = CapAlertPage.objects.live().filter(status="Actual") lookup_field = "identifier" def cap_geojson(request): - alerts = CapAlertPage.objects.all().live() + alerts = CapAlertPage.objects.all().live().filter(status="Actual") active_alert_infos = [] for alert in alerts: diff --git a/pages/cap/wagtail_hooks.py b/pages/cap/wagtail_hooks.py index ed83b006..286fdc49 100644 --- a/pages/cap/wagtail_hooks.py +++ b/pages/cap/wagtail_hooks.py @@ -96,7 +96,7 @@ def add_geomanager_datasets(request): if cap_geomanager_settings.show_on_mapviewer and cap_geomanager_settings.geomanager_subcategory: # check if we have any live alerts - has_live_alerts = CapAlertPage.objects.live().exists() + has_live_alerts = CapAlertPage.objects.live().filter(status="Actual").exists() # create dataset dataset = create_cap_geomanager_dataset(cap_geomanager_settings, has_live_alerts, request) diff --git a/pages/home/models.py b/pages/home/models.py index ec11407b..7b1f488e 100644 --- a/pages/home/models.py +++ b/pages/home/models.py @@ -262,13 +262,13 @@ def get_forecast_by_daterange(self): @cached_property def cap_alerts(self): - alerts = CapAlertPage.objects.all().live().order_by('-sent') + alerts = CapAlertPage.objects.all().live().filter(status="Actual") active_alert_infos = [] geojson = {"type": "FeatureCollection", "features": []} for alert in alerts: for info in alert.info: - if info.value.get('expires').date() >= datetime.today().date(): + if info.value.get('expires') > timezone.localtime(): start_time = info.value.get("effective") or alert.sent if timezone.now() > start_time: diff --git a/requirements.txt b/requirements.txt index d600fc75..05402ae4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,7 +9,7 @@ attrs==23.1.0 beautifulsoup4==4.9.3 billiard==3.6.4.0 cachetools==5.3.0 -capeditor==0.4.8 +capeditor==0.4.9 Cartopy==0.22.0 celery==5.2.7 certifi==2023.07.22