From d82b0e743a7e75ee652b5d343bea252ad405d1c9 Mon Sep 17 00:00:00 2001 From: Brian Kelly Date: Tue, 5 Nov 2024 11:16:40 -0600 Subject: [PATCH 1/2] Preview Shapefiles associated with GeoServer layers --- README.rst | 73 ++++++++++++++++++- .../geoserver.css | 6 ++ .../invenio_previewer_geospatial/geoserver.js | 28 +++++++ invenio_previewer_geospatial/config.py | 4 + .../extensions/geoserver.py | 32 ++++++++ .../geoserver.html | 12 +++ invenio_previewer_geospatial/webpack.py | 2 + setup.cfg | 1 + 8 files changed, 155 insertions(+), 3 deletions(-) create mode 100644 invenio_previewer_geospatial/assets/semantic-ui/css/invenio_previewer_geospatial/geoserver.css create mode 100644 invenio_previewer_geospatial/assets/semantic-ui/js/invenio_previewer_geospatial/geoserver.js create mode 100644 invenio_previewer_geospatial/extensions/geoserver.py create mode 100644 invenio_previewer_geospatial/templates/semantic-ui/invenio_previewer_geospatial/geoserver.html diff --git a/README.rst b/README.rst index a45f106..3997e6b 100644 --- a/README.rst +++ b/README.rst @@ -28,6 +28,7 @@ package: :: PREVIEWER_PREVIEWERS_ORDER = [ + "invenio_previewer.extensions.geoserver", "invenio_previewer.extensions.gpx", "invenio_previewer.extensions.csv_papaparsejs", "invenio_previewer.extensions.json_prismjs", @@ -44,6 +45,7 @@ package: ] PREVIEWER_PREFERENCE = [ + "geoserver", "gpx", "csv_papaparsejs", "json_prismjs", @@ -58,13 +60,13 @@ package: "txt", ] -Allow Images from Open Street Map -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Allow Images from Open Street Map & GeoServers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In ``invenio.cfg`` edit ``APP_DEFAULT_SECURE_HEADERS`` to allow images from OpenStreetMap: -:: +.. code:: python APP_DEFAULT_SECURE_HEADERS = { 'content_security_policy': { @@ -77,12 +79,77 @@ from OpenStreetMap: 'img-src': [ "'self'", "https://*.openstreetmap.org", + "https://maps-public.geo.nyu.edu/geoserver/sdr/wms", 'data:', ] }, ... } +Add Custom GeoServer Fields +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In ``invenio.cfg`` add the following namespace, custom fields and UI elements: + +.. code:: python + + # Set these if you want to override the field names below + PREVIEWER_GEOSPATIAL_CUSTOM_FIELDS_GEOSERVER_WMS_URL = "geoserver:wms_url" + PREVIEWER_GEOSPATIAL_CUSTOM_FIELDS_GEOSERVER_WFS_URL = "geoserver:wfs_url" + PREVIEWER_GEOSPATIAL_CUSTOM_FIELDS_GEOSERVER_LAYER_NAME = "geoserver:layer_name" + + RDM_NAMESPACES = { + "geoserver": "https://geoserver.org/" + } + + RDM_CUSTOM_FIELDS = [ + TextCF(name="geoserver:wms_url"), + TextCF(name="geoserver:wfs_url"), + TextCF(name="geoserver:layer_name"), + ] + + RDM_CUSTOM_FIELDS_UI = [ + { + "section": _("GeoServer"), + "fields": [ + dict( + field="geoserver:wms_url", + ui_widget="Input", + props=dict( + label="WMS URL", + placeholder="https://maps-public.geo.nyu.edu/geoserver/sdr/wms", + icon="linkify", + description="GeoServer WMS Service Base URL", + required=False + ) + ), + dict( + field="geoserver:wfs_url", + ui_widget="Input", + props=dict( + label="WMS URL", + placeholder="https://maps-public.geo.nyu.edu/geoserver/sdr/wfs", + icon="linkify", + description="GeoServer WFS Service Base URL", + required=False + ) + ), + dict( + field="geoserver:layer_name", + ui_widget="Input", + props=dict( + label="Layer Name", + placeholder="sdr:nyu_2451_12345", + icon="pencil", + description="Name of the GeoServer Layer this data can be found in", + required=False + ) + ) + ] + } + ] + + Development ----------- diff --git a/invenio_previewer_geospatial/assets/semantic-ui/css/invenio_previewer_geospatial/geoserver.css b/invenio_previewer_geospatial/assets/semantic-ui/css/invenio_previewer_geospatial/geoserver.css new file mode 100644 index 0000000..edb9af7 --- /dev/null +++ b/invenio_previewer_geospatial/assets/semantic-ui/css/invenio_previewer_geospatial/geoserver.css @@ -0,0 +1,6 @@ +@import "leaflet/dist/leaflet.css"; + +#map { + width: 100%; + height: 480px; +} diff --git a/invenio_previewer_geospatial/assets/semantic-ui/js/invenio_previewer_geospatial/geoserver.js b/invenio_previewer_geospatial/assets/semantic-ui/js/invenio_previewer_geospatial/geoserver.js new file mode 100644 index 0000000..beaa80e --- /dev/null +++ b/invenio_previewer_geospatial/assets/semantic-ui/js/invenio_previewer_geospatial/geoserver.js @@ -0,0 +1,28 @@ +import L from "leaflet" +import "leaflet/dist/leaflet.css"; + +document.addEventListener("DOMContentLoaded", () => { + const mapElement = document.getElementById("map"); + const baseUrl = mapElement.getAttribute("data-base-url") + const layerName = mapElement.getAttribute("data-layer-name") + + const map = L.map('map').setView([51.505, -0.09], 13); + + L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', { + maxZoom: 19, + attribution: '© OpenStreetMap' + }).addTo(map); + + const wmsLayer = L.tileLayer.wms(baseUrl, { + layers: layerName, + format: 'image/png', + transparent: true + }); + + wmsLayer.addTo(map); + wmsLayer.setOpacity(0.75); + map.fitBounds([ + [17.881242, -179.14734], + [71.390482, 179.778465] + ]) +}); diff --git a/invenio_previewer_geospatial/config.py b/invenio_previewer_geospatial/config.py index 0c4a9fc..dcc469b 100644 --- a/invenio_previewer_geospatial/config.py +++ b/invenio_previewer_geospatial/config.py @@ -10,3 +10,7 @@ PREVIEWER_GEOSPATIAL_BASE_TEMPLATE = "invenio_previewer_geospatial/base.html" """Default base template for the demo page.""" + +PREVIEWER_GEOSPATIAL_CUSTOM_FIELDS_GEOSERVER_WMS_URL = "geoserver:wms_url" +PREVIEWER_GEOSPATIAL_CUSTOM_FIELDS_GEOSERVER_WFS_URL = "geoserver:wfs_url" +PREVIEWER_GEOSPATIAL_CUSTOM_FIELDS_GEOSERVER_LAYER_NAME = "geoserver:layer_name" diff --git a/invenio_previewer_geospatial/extensions/geoserver.py b/invenio_previewer_geospatial/extensions/geoserver.py new file mode 100644 index 0000000..646f507 --- /dev/null +++ b/invenio_previewer_geospatial/extensions/geoserver.py @@ -0,0 +1,32 @@ +"""GeoServer Previewer.""" + +from flask import render_template, current_app +from invenio_previewer.proxies import current_previewer + +previewable_extensions = ["shp"] + + +def can_preview(file): + """Check if file can be previewed.""" + return file.is_local() and file.has_extensions(".shp") + + +def preview(file): + """Render the Geoserver template.""" + return render_template( + "invenio_previewer_geospatial/geoserver.html", + file=file, + record=file.record, + wms_url_field=( + current_app.config.get( + "PREVIEWER_GEOSPATIAL_CUSTOM_FIELDS_GEOSERVER_WMS_URL" + ) + ), + layer_name_field=( + current_app.config.get( + "PREVIEWER_GEOSPATIAL_CUSTOM_FIELDS_GEOSERVER_LAYER_NAME" + ) + ), + js_bundles=current_previewer.js_bundles + ["geoserver_js.js"], + css_bundles=current_previewer.css_bundles + ["geoserver_css.css"], + ) diff --git a/invenio_previewer_geospatial/templates/semantic-ui/invenio_previewer_geospatial/geoserver.html b/invenio_previewer_geospatial/templates/semantic-ui/invenio_previewer_geospatial/geoserver.html new file mode 100644 index 0000000..155575d --- /dev/null +++ b/invenio_previewer_geospatial/templates/semantic-ui/invenio_previewer_geospatial/geoserver.html @@ -0,0 +1,12 @@ +{%- extends config.PREVIEWER_ABSTRACT_TEMPLATE %} + +{% block panel %} + {% if record.custom_fields[wms_url_field] and record.custom_fields[layer_name_field] %} +
+ {% else %} +

Sorry, this Shapefile has no associated GeoServer layer.

+ {% endif %} +{% endblock %} diff --git a/invenio_previewer_geospatial/webpack.py b/invenio_previewer_geospatial/webpack.py index e2d51ad..ff879d7 100644 --- a/invenio_previewer_geospatial/webpack.py +++ b/invenio_previewer_geospatial/webpack.py @@ -11,6 +11,8 @@ entry={ "gpx_js": "./js/invenio_previewer_geospatial/gpx.js", "gpx_css": "./css/invenio_previewer_geospatial/gpx.css", + "geoserver_js": "./js/invenio_previewer_geospatial/geoserver.js", + "geoserver_css": "./css/invenio_previewer_geospatial/geoserver.css", }, dependencies={"leaflet": "^1.9.4", "leaflet-gpx": "^2.1.2"}, ), diff --git a/setup.cfg b/setup.cfg index 10b3443..824c5ba 100644 --- a/setup.cfg +++ b/setup.cfg @@ -49,6 +49,7 @@ invenio_assets.webpack = invenio_previewer_geospatial = invenio_previewer_geospatial.webpack:theme invenio_previewer.previewers = gpx = invenio_previewer_geospatial.extensions.gpx + geoserver = invenio_previewer_geospatial.extensions.geoserver [build_sphinx] source-dir = docs/ From fbbe518301fc82345d9d0b77688725f1cde0e3a6 Mon Sep 17 00:00:00 2001 From: Brian Kelly Date: Tue, 5 Nov 2024 11:24:55 -0600 Subject: [PATCH 2/2] Fix isort complaint --- invenio_previewer_geospatial/extensions/geoserver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/invenio_previewer_geospatial/extensions/geoserver.py b/invenio_previewer_geospatial/extensions/geoserver.py index 646f507..b1e67b7 100644 --- a/invenio_previewer_geospatial/extensions/geoserver.py +++ b/invenio_previewer_geospatial/extensions/geoserver.py @@ -1,6 +1,6 @@ """GeoServer Previewer.""" -from flask import render_template, current_app +from flask import current_app, render_template from invenio_previewer.proxies import current_previewer previewable_extensions = ["shp"]