Skip to content

Commit

Permalink
Merge upstream changes (#4)
Browse files Browse the repository at this point in the history
* WMTS preview: support webassets

* Add on_same_domain check to WMTS and Shapefile viewer

* Bump version

* Add initial test support

* Clean unnecessary fixture

* Replace deprecated url helper

* Add basic test for geojson_view

* Use plugins.toolkit

* Clean unnecesary requirement

* Clean README

* Add shp test

* Use plugins.toolkit

* Add dev-requirements.txt

* Test support for older versions

* Check response body

* Use ckan toolkit instead

* Use toolkit instead of core methods

* Don't assume format field is there

* Bump version

* use `theme` instead of `main_css` in CKAN >=2.9.6

* Migrate CSS to BS5 badges

* Drop tests for unsupported CKAN versions

* Support multiple tile providers, remove Stamen tiles

Copied the same functionality from ckanext-spatial to leverage
leaflet-providers:

ckan/ckanext-spatial#317

https://docs.ckan.org/projects/ckanext-spatial/en/latest/map-widgets.html

* Bump version

* Add leaflet-providers to webassets and attributionControl to JS modules

* Test 2.11

* Add leaflet-providers.js

---------

Co-authored-by: Sol Lee <[email protected]>
Co-authored-by: Adrià Mercader <[email protected]>
Co-authored-by: pdelboca <[email protected]>
Co-authored-by: Sergey Motornyuk <[email protected]>
  • Loading branch information
5 people authored Jul 12, 2024
1 parent fa7e5fd commit 55ce056
Show file tree
Hide file tree
Showing 30 changed files with 1,528 additions and 81 deletions.
58 changes: 58 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: Tests
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.10'
- name: Install requirements
run: pip install flake8 pycodestyle
- name: Check syntax
run: flake8 . --count --select=E901,E999,F821,F822,F823 --show-source --statistics --exclude ckan

test:
needs: lint
strategy:
matrix:
ckan-version: ["2.11", "2.10", 2.9]
fail-fast: false

name: CKAN ${{ matrix.ckan-version }}
runs-on: ubuntu-latest
container:
image: ckan/ckan-dev:${{ matrix.ckan-version }}
services:
solr:
image: ckan/ckan-solr:${{ matrix.ckan-version }}-solr9
postgres:
image: ckan/ckan-postgres-dev:${{ matrix.ckan-version }}
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
redis:
image: redis:3
env:
CKAN_SQLALCHEMY_URL: postgresql://ckan_default:pass@postgres/ckan_test
CKAN_DATASTORE_WRITE_URL: postgresql://datastore_write:pass@postgres/datastore_test
CKAN_DATASTORE_READ_URL: postgresql://datastore_read:pass@postgres/datastore_test
CKAN_SOLR_URL: http://solr:8983/solr/ckan
CKAN_REDIS_URL: redis://redis:6379/1

steps:
- uses: actions/checkout@v4
- name: Install requirements
run: |
pip install -r dev-requirements.txt
pip install -e .
# Replace default path to CKAN core config file with the one on the container
sed -i -e 's/use = config:.*/use = config:\/srv\/app\/src\/ckan\/test-core.ini/' test.ini
- name: Setup extension
run: |
ckan -c test.ini db init
- name: Run tests
run: pytest --ckan-ini=test.ini --disable-warnings ckanext/geoview/tests
20 changes: 10 additions & 10 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ used to be part of ckanext-spatial_.
**Note:** This is a work in progress, if you can help with `OpenLayers`_ or `Leaflet`_ development,
check the `Issues` section for what needs to be done or add a new issue.

This extensions supports CKAN 2.6 onwards, including Python 3 support on CKAN 2.9 or higher.
This extensions supports CKAN 2.7 onwards, including Python 3 support on CKAN 2.9 or higher.

------------
Installation
Expand Down Expand Up @@ -76,11 +76,11 @@ OpenLayers Viewer

The OpenLayers_ viewer provides access to different geospatial formats and services:

To enable it, add ``geo_view`` to your ``ckan.plugins`` setting. (use ``geo_preview`` if you are using CKAN < 2.3)::
To enable it, add ``geo_view`` to your ``ckan.plugins`` setting.::

ckan.plugins = ... resource_proxy geo_view

On CKAN >= 2.3, if you want the geospatial views to be created by default, add the plugin to the following setting::
If you want the geospatial views to be created by default, add the plugin to the following setting::


ckan.views.default_views = ... geo_view
Expand Down Expand Up @@ -247,11 +247,11 @@ Leaflet GeoJSON Viewer

The Leaflet_ GeoJSON_ viewer will render GeoJSON files on a map and add a popup showing the features properties, for those resources that have a ``geojson`` format.

To enable it, add ``geojson_view`` to your ``ckan.plugins`` setting. (use ``geojson_preview`` if you are using CKAN < 2.3)::
To enable it, add ``geojson_view`` to your ``ckan.plugins`` setting.::

ckan.plugins = ... resource_proxy geojson_view

On CKAN >= 2.3, if you want the views to be created by default on all GeoJSON files, add the plugin to the following setting::
If you want the views to be created by default on all GeoJSON files, add the plugin to the following setting::


ckan.views.default_views = ... geojson_view
Expand All @@ -269,11 +269,11 @@ Leaflet WMTS Viewer

The Leaflet_ WMTS viewer will render WMTS (Web Map Tile Service) layers on a map for those resources that have a ``wmts`` format.

To enable it, add ``wmts_view`` to your ``ckan.plugins`` setting. (use ``wmts_preview`` if you are using CKAN < 2.3)::
To enable it, add ``wmts_view`` to your ``ckan.plugins`` setting.::

ckan.plugins = ... resource_proxy wmts_view

On CKAN >= 2.3, if you want the views to be created by default on all WMTS resources, add the plugin to the following setting::
If you want the views to be created by default on all WMTS resources, add the plugin to the following setting::


ckan.views.default_views = ... wmts_view
Expand All @@ -286,11 +286,11 @@ Leaflet ESRI Shapefile Viewer

The Leaflet_ Shapefile_ viewer will render ESRI Shapfiles (A ZIP archive contains the .shp, .shx, .dbf, and .prj files) on a map and add a popup showing the features properties, for those resources that have a ``shp`` format.

To enable it, add ``shp_view`` to your ``ckan.plugins`` setting. (use ``shp_preview`` if you are using CKAN < 2.3)::
To enable it, add ``shp_view`` to your ``ckan.plugins`` setting.::

ckan.plugins = ... resource_proxy shp_view

On CKAN >= 2.3, if you want the views to be created by default on all Shapefiles, add the plugin to the following setting::
If you want the views to be created by default on all Shapefiles, add the plugin to the following setting::


ckan.views.default_views = ... shp_view
Expand All @@ -310,7 +310,7 @@ Common base layers for Map Widgets

The geospatial view plugins support the same base map configurations than the ckanext-spatial `widgets`_.

Check the following page to learn how to choose a different base map layer (Stamen, MapBox or custom):
Check the following page to learn how to choose a different base map layer:

http://docs.ckan.org/projects/ckanext-spatial/en/latest/map-widgets.html

Expand Down
20 changes: 17 additions & 3 deletions ckanext/geoview/plugin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
import mimetypes
from six.moves.urllib.parse import urlparse

import ckantoolkit as toolkit

from ckan import plugins as p
from ckan.common import json
from ckan.lib.datapreview import on_same_domain
from ckan.plugins import toolkit

import ckanext.geoview.utils as utils

Expand Down Expand Up @@ -258,9 +258,16 @@ def info(self):
def can_view(self, data_dict):
resource = data_dict["resource"]
format_lower = resource.get("format", "").lower()
same_domain = False
try:
same_domain = on_same_domain(data_dict)
except KeyError as e:
log.error(
"Unable to determine if url is on same domain: {}".format(e)
)

if format_lower in self.WMTS:
return self.same_domain or self.proxy_enabled
return same_domain or self.proxy_enabled
return False

def view_template(self, context, data_dict):
Expand Down Expand Up @@ -307,9 +314,16 @@ def can_view(self, data_dict):
name_lower = ""
if resource.get("name"):
name_lower = resource.get("name", "").lower()
same_domain = False
try:
same_domain = on_same_domain(data_dict)
except KeyError as e:
log.error(
"Unable to determine if url is on same domain: {}".format(e)
)

if format_lower in self.SHP or any([shp in name_lower for shp in self.SHP]):
return self.same_domain or self.proxy_enabled
return same_domain or self.proxy_enabled
return False

def view_template(self, context, data_dict):
Expand Down
16 changes: 8 additions & 8 deletions ckanext/geoview/public/css/geo-resource-styles.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.label[data-format=wfs] {
.badge[data-format=wfs] {
background-color: #7aae3d;
}
.format-label[data-format=wfs],
Expand All @@ -11,7 +11,7 @@
height: 35px;
}

.label[data-format=wms] {
.badge[data-format=wms] {
background-color: #adc717;
}
.format-label[data-format=wms],
Expand All @@ -24,7 +24,7 @@
height: 35px;
}

.label[data-format=gml] {
.badge[data-format=gml] {
background-color: #7aae3d;
}
.format-label[data-format=gml],
Expand All @@ -37,7 +37,7 @@
height: 35px;
}

.label[data-format=kml] {
.badge[data-format=kml] {
background-color: #7aae3d;
}
.format-label[data-format=kml],
Expand All @@ -50,7 +50,7 @@
height: 35px;
}

.label[data-format=geojson] {
.badge[data-format=geojson] {
background-color: #9855e0;
}
.format-label[data-format=geojson],
Expand All @@ -63,7 +63,7 @@
height: 35px;
}

.label[data-format=wmts] {
.badge[data-format=wmts] {
background-color: #3333ff;
}
.format-label[data-format=wmts],
Expand All @@ -76,7 +76,7 @@
height: 35px;
}

.label[data-format=shp] {
.badge[data-format=shp] {
background-color: #0080ff;
}
.format-label[data-format=shp],
Expand All @@ -89,6 +89,6 @@
height: 35px;
}

.label[data-format=arcgis_rest] {
.badge[data-format=arcgis_rest] {
background-color: #5c3ee0;
}
10 changes: 10 additions & 0 deletions ckanext/geoview/public/css/geojson_preview.css
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,13 @@ html, body {
height: 300px;
overflow: auto;
}

.leaflet-control-no-provider {
background-color: white;
margin-right: 10px;
padding: 10px;
border: 1px solid #b1b1b1;
}
.leaflet-control-attribution {
font-size: 11px;
}
10 changes: 10 additions & 0 deletions ckanext/geoview/public/css/shp_preview.css
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,13 @@ html, body {
overflow: auto;
max-height: 200px;
}

.leaflet-control-no-provider {
background-color: white;
margin-right: 10px;
padding: 10px;
border: 1px solid #b1b1b1;
}
.leaflet-control-attribution {
font-size: 11px;
}
10 changes: 10 additions & 0 deletions ckanext/geoview/public/css/wmts_preview.css
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,13 @@ html, body {
.ui-opacity .handle:hover {
background: #303030;
}

.leaflet-control-no-provider {
background-color: white;
margin-right: 10px;
padding: 10px;
border: 1px solid #b1b1b1;
}
.leaflet-control-attribution {
font-size: 11px;
}
66 changes: 52 additions & 14 deletions ckanext/geoview/public/js/common_map.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
maxZoom: 18
});

var baseLayer;

map = new L.Map(container, leafletMapOptions);

if (mapConfig.type == 'mapbox') {
Expand All @@ -44,28 +46,64 @@
'See http://www.mapbox.com/developers/api-overview/ for details';
}

baseLayerUrl = '//{s}.tiles.mapbox.com/v4/' + mapConfig['mapbox.map_id'] + '/{z}/{x}/{y}.png?access_token=' + mapConfig['mapbox.access_token'];
leafletBaseLayerOptions.handle = mapConfig['mapbox.map_id'];
leafletBaseLayerOptions.subdomains = mapConfig.subdomains || 'abcd';
leafletBaseLayerOptions.attribution = mapConfig.attribution || 'Data: <a href="http://osm.org/copyright" target="_blank">OpenStreetMap</a>, Design: <a href="http://mapbox.com/about/maps" target="_blank">MapBox</a>';
baseLayer = L.tileLayer.provider('MapBox', {
id: mapConfig['mapbox.map_id'],
accessToken: mapConfig['mapbox.access_token']
});

} else if (mapConfig.type == 'custom') {
// Custom XYZ layer
baseLayerUrl = mapConfig['custom.url'];
if (!baseLayerUrl)
throw '[CKAN Map Widgets] Custom URL must be set when using Custom Map type';

baseLayerUrl = mapConfig['custom_url'] || mapConfig['custom.url'];
if (mapConfig.subdomains) leafletBaseLayerOptions.subdomains = mapConfig.subdomains;
if (mapConfig.tms) leafletBaseLayerOptions.tms = mapConfig.tms;
leafletBaseLayerOptions.attribution = mapConfig.attribution;

baseLayer = new L.TileLayer(baseLayerUrl, leafletBaseLayerOptions);

} else if (mapConfig.type == 'wms') {

baseLayerUrl = mapConfig['wms.url'];
wmsOptions = {}
wmsOptions['layers'] = mapConfig['wms.layers'];
wmsOptions['styles'] = mapConfig['wms.styles'] || '';
wmsOptions['format'] = mapConfig['wms.format'] || 'image/png';
if(mapConfig['wms.srs'] || mapConfig['wms.crs']) {
wmsOptions['crs'] = mapConfig['wms.srs'] || mapConfig['wms.crs'];
}
wmsOptions['version'] = mapConfig['wms.version'] || '1.1.1';

baseLayer = new L.TileLayer.WMS(baseLayerUrl, wmsOptions);


} else if (mapConfig.type) {

baseLayer = L.tileLayer.provider(mapConfig.type, mapConfig)

} else {
// Default to Stamen base map
baseLayerUrl = 'https://stamen-tiles-{s}.a.ssl.fastly.net/terrain/{z}/{x}/{y}.png';
leafletBaseLayerOptions.subdomains = mapConfig.subdomains || 'abcd';
leafletBaseLayerOptions.attribution = mapConfig.attribution || 'Map tiles by <a href="http://stamen.com">Stamen Design</a> (<a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>). Data by <a href="http://openstreetmap.org">OpenStreetMap</a> (<a href="http://creativecommons.org/licenses/by-sa/3.0">CC BY SA</a>)';
let c = L.Control.extend({

onAdd: (map) => {
let element = document.createElement("div");
element.className = "leaflet-control-no-provider";
element.innerHTML = 'No map provider set. Please check the <a href="https://docs.ckan.org/projects/ckanext-spatial/en/latest/map-widgets.html">documentation</a>';
return element;
},
onRemove: (map) => {}
})
map.addControl(new c({position: "bottomleft"}))

}

var baseLayer = new L.TileLayer(baseLayerUrl, leafletBaseLayerOptions);
map.addLayer(baseLayer);
if (baseLayer) {
let attribution = L.control.attribution({"prefix": false});
attribution.addTo(map)

map.addLayer(baseLayer);

if (mapConfig.attribution) {
attribution.addAttribution(mapConfig.attribution);
}
}

return map;

Expand Down
2 changes: 1 addition & 1 deletion ckanext/geoview/public/js/geojson_preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ ckan.module('geojsonpreview', function (jQuery, _) {


self.el.append($("<div></div>").attr("id","map"));
self.map = ckan.commonLeafletMap('map', this.options.map_config);
self.map = ckan.commonLeafletMap('map', this.options.map_config, {attributionControl: false});

// hack to make leaflet use a particular location to look for images
L.Icon.Default.imagePath = this.options.site_url + 'js/vendor/leaflet/dist/images';
Expand Down
Loading

0 comments on commit 55ce056

Please sign in to comment.