diff --git a/pages/cap/views.py b/pages/cap/views.py index d3485484..7c5ed01d 100644 --- a/pages/cap/views.py +++ b/pages/cap/views.py @@ -1,13 +1,11 @@ import json from typing import List -from lxml import etree from capeditor.constants import SEVERITY_MAPPING from capeditor.models import CapSetting from capeditor.renderers import CapXMLRenderer from capeditor.serializers import AlertSerializer as BaseAlertSerializer from django.contrib.syndication.views import Feed -from base.cache import wagcache from django.core.validators import validate_email from django.db.models.base import Model from django.http import JsonResponse, HttpResponse @@ -17,10 +15,12 @@ from django.utils import timezone from django.utils.feedgenerator import Enclosure, rfc2822_date from django.utils.feedgenerator import Rss201rev2Feed +from lxml import etree from rest_framework.generics import get_object_or_404 from wagtail.api.v2.utils import get_full_url from wagtail.models import Site +from base.cache import wagcache from .models import CapAlertPage from .sign import sign_xml @@ -138,18 +138,28 @@ def get_cap_xml(request, identifier): xml = wagcache.get(f"cap_xml_{identifier}") if not xml: - data = AlertSerializer(alert).data + data = AlertSerializer(alert, context={ + "request": request, + }).data + xml = CapXMLRenderer().render(data) xml_bytes = bytes(xml, encoding='utf-8') + signed = False try: signed_xml = sign_xml(xml_bytes) if signed_xml: xml = signed_xml + signed = True except Exception as e: + print(e) pass - root = etree.fromstring(xml) + if signed: + root = etree.fromstring(xml) + else: + root = etree.fromstring(xml_bytes) + tree = etree.ElementTree(root) style_url = get_full_url(request, reverse("cap_stylesheet")) pi = etree.ProcessingInstruction('xml-stylesheet', f'type="text/xsl" href="{style_url}"') diff --git a/pages/cap/wagtail_hooks.py b/pages/cap/wagtail_hooks.py index f4ccf237..288a98ee 100644 --- a/pages/cap/wagtail_hooks.py +++ b/pages/cap/wagtail_hooks.py @@ -15,6 +15,7 @@ from wagtail.admin.forms.pages import CopyForm from wagtail.admin.menu import MenuItem, Menu from wagtail.blocks import StreamValue +from wagtail_modeladmin.helpers import PagePermissionHelper from wagtail.models import Page from wagtail_modeladmin.helpers import AdminURLHelper from wagtail_modeladmin.menus import GroupMenuItem @@ -32,6 +33,32 @@ from .utils import create_cap_geomanager_dataset +class CAPPagePermissionHelper(PagePermissionHelper): + def user_can_edit_obj(self, user, obj): + can_edit = super().user_can_edit_obj(user, obj) + + if obj.live and obj.status == "Actual": + return False + + return can_edit + + def user_can_delete_obj(self, user, obj): + can_delete = super().user_can_delete_obj(user, obj) + + if obj.live and obj.status == "Actual": + return False + + return can_delete + + def user_can_unpublish_obj(self, user, obj): + can_unpublish = super().user_can_unpublish_obj(user, obj) + + if obj.live and obj.status == "Actual": + return False + + return can_unpublish + + class CAPAdmin(ModelAdmin): model = CapAlertPage menu_label = _('Alerts') @@ -39,6 +66,7 @@ class CAPAdmin(ModelAdmin): menu_order = 200 add_to_settings_menu = False exclude_from_explorer = False + permission_helper_class = CAPPagePermissionHelper class CAPMenuGroupAdminMenuItem(GroupMenuItem): diff --git a/pages/home/static/js/weather_watch.js b/pages/home/static/js/weather_watch.js index 2c94f563..2cf92324 100644 --- a/pages/home/static/js/weather_watch.js +++ b/pages/home/static/js/weather_watch.js @@ -63,14 +63,29 @@ $((async function () { } = await fetch(homeMapSettingsUrl).then(response => response.json()) + // create map const map = new maplibregl.Map({ container: "home-map", // container ID style: defaultStyle, - center: [0, 0], // starting position [lng, lat] - zoom: 4, // starting zoom + center: [0, 0], + zoom: 4, scrollZoom: false, }); + + // Add zoom control to the map. + map.addControl(new maplibregl.NavigationControl({showCompass: false})); + + // add fullscreen control + map.addControl(new maplibregl.FullscreenControl()); + + // add attribution + map.addControl(new maplibregl.AttributionControl({ + customAttribution: '© OpenStreetMap © CARTO', + compact: false, + })); + + // fetch all weather icons and load to map if (weatherIconsUrl) { fetch(weatherIconsUrl).then(response => response.json()).then(icons => { icons.forEach(icon => { @@ -81,6 +96,7 @@ $((async function () { }); } + // fetch forecast settings if (forecastSettingsUrl) { fetch(forecastSettingsUrl).then(response => response.json()).then(settings => { forecastSettings = settings @@ -90,172 +106,7 @@ $((async function () { // wait for map to load await new Promise((resolve) => map.on("load", resolve)); - if (bounds) { - const mapBounds = [[bounds[0], bounds[1]], [bounds[2], bounds[3]]] - map.fitBounds(mapBounds, {padding: 20}); - } else { - if (countryInfo && countryInfo.bbox) { - const bbox = countryInfo.bbox - map.fitBounds(bbox, {padding: 20}); - } - } - - - fetch(homeMapAlertsUrl) - .then(response => { - if (!response.ok) { - throw new Error('Error fetching alerts'); - } - return response.text(); - }) - .then(alertsHTML => { - const $alerts = $(alertsHTML) - - if ($alerts.length) { - $alerts.appendTo("#alerts-container") - $("#alerts-legend").show() - - - // add cap alerts layer - map.addSource("alert-areas", { - type: "geojson", - data: capGeojsonUrl, - }); - - map.addLayer({ - id: "alert-areas-layer", - type: "fill", - source: "alert-areas", - paint: { - "fill-color": [ - "case", - ["==", ["get", "severity"], "Extreme"], - "#d72f2a", - ["==", ["get", "severity"], "Severe"], - "#f89904", - ["==", ["get", "severity"], "Moderate"], - "#e4e616", - ["==", ["get", "severity"], "Minor"], - "#53ffff", - ["==", ["get", "severity"], "Unknown"], - "#3366ff", - "black", - ], - "fill-opacity": 0.7, - "fill-outline-color": "#000", - }, - }); - - // CAP alerts layer on click - map.on("click", "alert-areas-layer", (e) => { - // Copy coordinates array. - - const description = e.features[0].properties.areaDesc; - const severity = e.features[0].properties.severity; - const event = e.features[0].properties.event; - - new maplibregl.Popup() - .setLngLat(e.lngLat) - .setHTML(`
${severity} severity
${key}: ${paramValues[key]}
` - return all - }, "") - - let detailLink - if (cityDetailUrl) { - const detailUrl = cityDetailUrl + citySlug - detailLink = ` - Details - - - - ` - } - - - return `${severity} severity
${key}: ${paramValues[key]}
` + return all + }, "") + + let detailLink + if (cityDetailUrl) { + const detailUrl = cityDetailUrl + citySlug + detailLink = ` + Details + + + + ` + } + + + return `