django-extended-ol 0.1.0__tar.gz → 1.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of django-extended-ol might be problematic. Click here for more details.

Files changed (22) hide show
  1. {django_extended_ol-0.1.0/django_extended_ol.egg-info → django_extended_ol-1.1.0}/PKG-INFO +37 -7
  2. {django_extended_ol-0.1.0 → django_extended_ol-1.1.0}/README.md +34 -5
  3. django_extended_ol-1.1.0/django_extended_ol/admin.py +10 -0
  4. {django_extended_ol-0.1.0 → django_extended_ol-1.1.0}/django_extended_ol/forms/widgets.py +11 -2
  5. django_extended_ol-1.1.0/django_extended_ol/static/olwidget/css/WMTSWidget.css +30 -0
  6. django_extended_ol-1.1.0/django_extended_ol/static/olwidget/js/WMTSWidget.js +91 -0
  7. {django_extended_ol-0.1.0 → django_extended_ol-1.1.0}/django_extended_ol/templates/gis/openlayers-wmts.html +8 -0
  8. {django_extended_ol-0.1.0 → django_extended_ol-1.1.0/django_extended_ol.egg-info}/PKG-INFO +37 -7
  9. {django_extended_ol-0.1.0 → django_extended_ol-1.1.0}/django_extended_ol.egg-info/SOURCES.txt +1 -0
  10. {django_extended_ol-0.1.0 → django_extended_ol-1.1.0}/pyproject.toml +1 -1
  11. django_extended_ol-0.1.0/django_extended_ol/admin.py +0 -6
  12. django_extended_ol-0.1.0/django_extended_ol/static/olwidget/js/WMTSWidget.js +0 -27
  13. {django_extended_ol-0.1.0 → django_extended_ol-1.1.0}/LICENSE +0 -0
  14. {django_extended_ol-0.1.0 → django_extended_ol-1.1.0}/MANIFEST.in +0 -0
  15. {django_extended_ol-0.1.0 → django_extended_ol-1.1.0}/django_extended_ol/__init__.py +0 -0
  16. {django_extended_ol-0.1.0 → django_extended_ol-1.1.0}/django_extended_ol/apps.py +0 -0
  17. {django_extended_ol-0.1.0 → django_extended_ol-1.1.0}/django_extended_ol/forms/__init__.py +0 -0
  18. {django_extended_ol-0.1.0 → django_extended_ol-1.1.0}/django_extended_ol.egg-info/dependency_links.txt +0 -0
  19. {django_extended_ol-0.1.0 → django_extended_ol-1.1.0}/django_extended_ol.egg-info/requires.txt +0 -0
  20. {django_extended_ol-0.1.0 → django_extended_ol-1.1.0}/django_extended_ol.egg-info/top_level.txt +0 -0
  21. {django_extended_ol-0.1.0 → django_extended_ol-1.1.0}/setup.cfg +0 -0
  22. {django_extended_ol-0.1.0 → django_extended_ol-1.1.0}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: django-extended-ol
3
- Version: 0.1.0
3
+ Version: 1.1.0
4
4
  Summary: An openlayers widget for Django with extended capabilities
5
5
  Author-email: SITN <sitn@ne.ch>
6
6
  Project-URL: Homepage, https://github.com/sitn/django-extended-ol
@@ -23,25 +23,32 @@ Requires-Python: >=3.10
23
23
  Description-Content-Type: text/markdown
24
24
  License-File: LICENSE
25
25
  Requires-Dist: Django>=5.0
26
+ Dynamic: license-file
26
27
 
27
28
  # django-extended-ol
28
29
 
29
30
  django-extended-ol is a Django app that extends the basic OpenLayers Widget.
30
31
 
32
+ Features:
33
+
31
34
  * Custom WMTS base_layer with fixed resolutions
32
35
 
33
36
  ## Quick start
34
37
 
35
- 1. Add "olwidget" to your INSTALLED_APPS setting like this:
38
+ ```sh
39
+ pip install django-extended-ol
40
+ ```
41
+
42
+ 1. Add "django_extended_ol" to your INSTALLED_APPS setting like this:
36
43
 
37
44
  ```python
38
45
  INSTALLED_APPS = [
39
46
  ...,
40
- "olwidget",
47
+ "django_extended_ol",
41
48
  ]
42
49
  ```
43
50
 
44
- 2. Configure olwidget in your settings.py, here's an example:
51
+ 2. Configure django_extended_ol in your settings.py, here's an example:
45
52
 
46
53
  ```python
47
54
  OLWIDGET = {
@@ -61,16 +68,24 @@ OLWIDGET = {
61
68
  "url_template": 'https://sitn.ne.ch/mapproxy95/wmts/1.0.0/{layer}/{style}/{TileMatrixSet}/{TileMatrix}/{TileRow}/{TileCol}.png',
62
69
  "request_encoding": 'REST', # optional
63
70
  "format": 'image/png' # optional
71
+ },
72
+ "search": { # optional, only if you want a search service
73
+ "url_template": 'https://sitn.ne.ch/search?limit=10&partitionlimit=2&interface=desktop&query={search_term}'
64
74
  }
65
75
  }
66
76
  ```
67
77
 
68
- 3. You can now use WMTSWidget in your gis forms:
78
+ 3. You can now use `WMTSWidget` in your gis forms:
69
79
 
70
80
  ```python
71
- gis_widget = WMTSWidget
81
+ from django_extended_ol.forms.widgets import WMTSWidget
82
+ ...
83
+ class MyCustomGISClass:
84
+ gis_widget = WMTSWidget
72
85
  ```
73
86
 
87
+ If you want a search widget, you can use `WMTSWithSearchWidget`. Please check search service specification below.
88
+
74
89
  4. You can also use it in your admin.py:
75
90
 
76
91
  ```python
@@ -81,4 +96,19 @@ gis_widget = WMTSWidget
81
96
  admin.site.register(YourGeomModel, WMTSGISModelAdmin)
82
97
  ```
83
98
 
99
+ If you want the search widget please use `WMTSGISWithSearchModelAdmin`. Please check search service specification below.
100
+
84
101
  5. Start the development server and visit the admin.
102
+
103
+
104
+ ## Search service specification
105
+
106
+ You'll need a templated URL as showcased in the `settings.py` above.
107
+ Such service should reply GeoJSON feature collection and each feature should have a `bbox` and a property named `label`.
108
+
109
+ # Build this package
110
+
111
+ ```sh
112
+ py -m build
113
+ py -m twine upload dist/*
114
+ ```
@@ -2,20 +2,26 @@
2
2
 
3
3
  django-extended-ol is a Django app that extends the basic OpenLayers Widget.
4
4
 
5
+ Features:
6
+
5
7
  * Custom WMTS base_layer with fixed resolutions
6
8
 
7
9
  ## Quick start
8
10
 
9
- 1. Add "olwidget" to your INSTALLED_APPS setting like this:
11
+ ```sh
12
+ pip install django-extended-ol
13
+ ```
14
+
15
+ 1. Add "django_extended_ol" to your INSTALLED_APPS setting like this:
10
16
 
11
17
  ```python
12
18
  INSTALLED_APPS = [
13
19
  ...,
14
- "olwidget",
20
+ "django_extended_ol",
15
21
  ]
16
22
  ```
17
23
 
18
- 2. Configure olwidget in your settings.py, here's an example:
24
+ 2. Configure django_extended_ol in your settings.py, here's an example:
19
25
 
20
26
  ```python
21
27
  OLWIDGET = {
@@ -35,16 +41,24 @@ OLWIDGET = {
35
41
  "url_template": 'https://sitn.ne.ch/mapproxy95/wmts/1.0.0/{layer}/{style}/{TileMatrixSet}/{TileMatrix}/{TileRow}/{TileCol}.png',
36
42
  "request_encoding": 'REST', # optional
37
43
  "format": 'image/png' # optional
44
+ },
45
+ "search": { # optional, only if you want a search service
46
+ "url_template": 'https://sitn.ne.ch/search?limit=10&partitionlimit=2&interface=desktop&query={search_term}'
38
47
  }
39
48
  }
40
49
  ```
41
50
 
42
- 3. You can now use WMTSWidget in your gis forms:
51
+ 3. You can now use `WMTSWidget` in your gis forms:
43
52
 
44
53
  ```python
45
- gis_widget = WMTSWidget
54
+ from django_extended_ol.forms.widgets import WMTSWidget
55
+ ...
56
+ class MyCustomGISClass:
57
+ gis_widget = WMTSWidget
46
58
  ```
47
59
 
60
+ If you want a search widget, you can use `WMTSWithSearchWidget`. Please check search service specification below.
61
+
48
62
  4. You can also use it in your admin.py:
49
63
 
50
64
  ```python
@@ -55,4 +69,19 @@ gis_widget = WMTSWidget
55
69
  admin.site.register(YourGeomModel, WMTSGISModelAdmin)
56
70
  ```
57
71
 
72
+ If you want the search widget please use `WMTSGISWithSearchModelAdmin`. Please check search service specification below.
73
+
58
74
  5. Start the development server and visit the admin.
75
+
76
+
77
+ ## Search service specification
78
+
79
+ You'll need a templated URL as showcased in the `settings.py` above.
80
+ Such service should reply GeoJSON feature collection and each feature should have a `bbox` and a property named `label`.
81
+
82
+ # Build this package
83
+
84
+ ```sh
85
+ py -m build
86
+ py -m twine upload dist/*
87
+ ```
@@ -0,0 +1,10 @@
1
+ from django.contrib.gis.admin import GISModelAdmin
2
+ from .forms.widgets import WMTSWidget, WMTSWithSearchWidget
3
+
4
+
5
+ class WMTSGISModelAdmin(GISModelAdmin):
6
+ gis_widget = WMTSWidget
7
+
8
+
9
+ class WMTSGISWithSearchModelAdmin(GISModelAdmin):
10
+ gis_widget = WMTSWithSearchWidget
@@ -10,7 +10,6 @@ class WMTSWidget(OpenLayersWidget):
10
10
  (extent[0] + extent[2]) / 2,
11
11
  (extent[1] + extent[3]) / 2,
12
12
  ]
13
- print(center_from_extent)
14
13
  widget_options = {
15
14
  "wmts_layer_name": settings.OLWIDGET["wmts"].get("layer_name"),
16
15
  "wmts_style": settings.OLWIDGET["wmts"]["style"],
@@ -22,13 +21,16 @@ class WMTSWidget(OpenLayersWidget):
22
21
  "default_map_center": settings.OLWIDGET["globals"].get("default_center", center_from_extent),
23
22
  "default_resolution": settings.OLWIDGET["globals"].get("default_resolution", 8),
24
23
  "extent": extent,
25
- "resolutions" : settings.OLWIDGET["globals"]["resolutions"]
24
+ "resolutions": settings.OLWIDGET["globals"]["resolutions"]
26
25
  }
27
26
 
28
27
  class Media(OpenLayersWidget.Media):
29
28
  js = OpenLayersWidget.Media.js + (
30
29
  "olwidget/js/WMTSWidget.js",
31
30
  )
31
+ css = {
32
+ "all": OpenLayersWidget.Media.css["all"] + ("olwidget/css/WMTSWidget.css",)
33
+ }
32
34
 
33
35
  def __init__(self, attrs=None):
34
36
  super().__init__()
@@ -37,3 +39,10 @@ class WMTSWidget(OpenLayersWidget):
37
39
  self.attrs[key] = self.widget_options[key]
38
40
  if attrs:
39
41
  self.attrs.update(attrs)
42
+
43
+
44
+ class WMTSWithSearchWidget(WMTSWidget):
45
+ widget_options = {
46
+ **WMTSWidget.widget_options,
47
+ "search_url": settings.OLWIDGET["search"].get("url_template", None)
48
+ }
@@ -0,0 +1,30 @@
1
+ .ext-ol-search {
2
+ position: absolute;
3
+ top: 0.5em;
4
+ left: 2.5em;
5
+ }
6
+
7
+ .ext-ol-autocomplete-results {
8
+ border: 1px solid var(--border-color);
9
+ max-height: 200px;
10
+ overflow-y: auto;
11
+ background-color: var(--body-bg);
12
+ color: var(--body-fg);
13
+ width: 20em;
14
+ position: absolute;
15
+ top: 2.5em;
16
+ left: 2.5em;
17
+ }
18
+
19
+ .ext-ol-autocomplete-results div {
20
+ padding: 8px;
21
+ cursor: pointer;
22
+ }
23
+
24
+ .ext-ol-autocomplete-results div:hover {
25
+ background-color: var(--darkened-bg);
26
+ }
27
+
28
+ .ext-ol-hidden {
29
+ display: none;
30
+ }
@@ -0,0 +1,91 @@
1
+ /* global ol */
2
+ 'use strict';
3
+
4
+ class WMTSWidget extends MapWidget {
5
+
6
+ /**
7
+ * Overrides MapWiget.createMap() that is called by
8
+ * MapWidget itself and stores the map in this.map
9
+ * @returns ol.Map instance
10
+ */
11
+ createMap() {
12
+ this.map_extent = this.options.extent;
13
+ this.projection = new ol.proj.Projection({
14
+ code: `EPSG:${this.options.map_srid}`,
15
+ extent: this.map_extent,
16
+ });
17
+ return new ol.Map({
18
+ target: this.options.map_id,
19
+ layers: [this.options.base_layer],
20
+ view: new ol.View({
21
+ center: this.options.default_center,
22
+ resolution: this.options.default_resolution,
23
+ projection: this.projection,
24
+ resolutions: this.options.resolutions,
25
+ constrainResolution: true
26
+ })
27
+ });
28
+ }
29
+
30
+ defaultCenter() {
31
+ return this.options.default_center;
32
+ }
33
+
34
+ search(searchterm) {
35
+ let debounceTimeout;
36
+ const query = searchterm.trim();
37
+
38
+ clearTimeout(debounceTimeout);
39
+ if (query.length < 3) {
40
+ this.clearResults()
41
+ return;
42
+ }
43
+
44
+ debounceTimeout = setTimeout(() => {
45
+ const url = this.options.search_url.replace('{search_term}', encodeURIComponent(query));
46
+
47
+ fetch(url)
48
+ .then(response => response.json())
49
+ .then(data => {
50
+ this.clearResults();
51
+ if (data && data.features) {
52
+ data.features.forEach(feature => {
53
+ const label = feature.properties.label;
54
+ const coords = feature.geometry.coordinates;
55
+ const div = document.createElement("div");
56
+ div.textContent = label;
57
+ div.addEventListener("click", () => {
58
+ this.clearResults();
59
+ this.inputSearchElement.value = label;
60
+ this.map.getView().fit(feature.bbox, {padding: [50, 50, 50, 50]})
61
+ });
62
+ this.divSearchResults.appendChild(div);
63
+ this.divSearchResults.classList.remove("ext-ol-hidden");
64
+ });
65
+ }
66
+ })
67
+ .catch(error => {
68
+ console.error("Search error!", error);
69
+ console.error(`Something went wrong parsing the response of ${url}`);
70
+ });
71
+ }, 300);
72
+ }
73
+
74
+ clearResults() {
75
+ this.divSearchResults.innerHTML = "";
76
+ this.divSearchResults.classList.add("ext-ol-hidden");
77
+ }
78
+
79
+ createInteractions() {
80
+ super.createInteractions();
81
+ document.addEventListener("DOMContentLoaded", () => {
82
+ document.querySelectorAll('.ext-ol-search-widget').forEach((divElement) => {
83
+ this.inputSearchElement = divElement.querySelector('input');
84
+ this.divSearchResults = divElement.querySelector('div.ext-ol-autocomplete-results');
85
+ this.inputSearchElement.addEventListener("input", () => this.search(this.inputSearchElement.value));
86
+ });
87
+ });
88
+ }
89
+ }
90
+
91
+
@@ -6,6 +6,12 @@
6
6
 
7
7
  <div id="{{ id }}_div_map" class="dj_map_wrapper">
8
8
  <div id="{{ id }}_map" class="dj_map"></div>
9
+ {% if search_url %}
10
+ <div id="{{ id }}_input_search" class="ext-ol-search-widget">
11
+ <input type="text" class="vTextField ext-ol-search" name="search">
12
+ <div class="ext-ol-autocomplete-results ext-ol-hidden"></div>
13
+ </div>
14
+ {% endif %}
9
15
  {% if not disabled %}<span class="clear_features"><a href="">{% translate "Delete all Features" %}</a></span>{% endif %}
10
16
  {% if display_raw %}<p>{% translate "Debugging window (serialized value)" %}</p>{% endif %}
11
17
  <textarea id="{{ id }}" class="vSerializedField required" cols="150" rows="10" name="{{ name }}"
@@ -52,6 +58,8 @@ const WMTSOptions = {
52
58
  options.base_layer = new ol.layer.Tile({
53
59
  source: new ol.source.WMTS(WMTSOptions),
54
60
  });
61
+
62
+ options.search_url = '{{ search_url|safe }}';
55
63
  {% endblock %}
56
64
 
57
65
  var {{ module }} = new WMTSWidget(options);
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: django-extended-ol
3
- Version: 0.1.0
3
+ Version: 1.1.0
4
4
  Summary: An openlayers widget for Django with extended capabilities
5
5
  Author-email: SITN <sitn@ne.ch>
6
6
  Project-URL: Homepage, https://github.com/sitn/django-extended-ol
@@ -23,25 +23,32 @@ Requires-Python: >=3.10
23
23
  Description-Content-Type: text/markdown
24
24
  License-File: LICENSE
25
25
  Requires-Dist: Django>=5.0
26
+ Dynamic: license-file
26
27
 
27
28
  # django-extended-ol
28
29
 
29
30
  django-extended-ol is a Django app that extends the basic OpenLayers Widget.
30
31
 
32
+ Features:
33
+
31
34
  * Custom WMTS base_layer with fixed resolutions
32
35
 
33
36
  ## Quick start
34
37
 
35
- 1. Add "olwidget" to your INSTALLED_APPS setting like this:
38
+ ```sh
39
+ pip install django-extended-ol
40
+ ```
41
+
42
+ 1. Add "django_extended_ol" to your INSTALLED_APPS setting like this:
36
43
 
37
44
  ```python
38
45
  INSTALLED_APPS = [
39
46
  ...,
40
- "olwidget",
47
+ "django_extended_ol",
41
48
  ]
42
49
  ```
43
50
 
44
- 2. Configure olwidget in your settings.py, here's an example:
51
+ 2. Configure django_extended_ol in your settings.py, here's an example:
45
52
 
46
53
  ```python
47
54
  OLWIDGET = {
@@ -61,16 +68,24 @@ OLWIDGET = {
61
68
  "url_template": 'https://sitn.ne.ch/mapproxy95/wmts/1.0.0/{layer}/{style}/{TileMatrixSet}/{TileMatrix}/{TileRow}/{TileCol}.png',
62
69
  "request_encoding": 'REST', # optional
63
70
  "format": 'image/png' # optional
71
+ },
72
+ "search": { # optional, only if you want a search service
73
+ "url_template": 'https://sitn.ne.ch/search?limit=10&partitionlimit=2&interface=desktop&query={search_term}'
64
74
  }
65
75
  }
66
76
  ```
67
77
 
68
- 3. You can now use WMTSWidget in your gis forms:
78
+ 3. You can now use `WMTSWidget` in your gis forms:
69
79
 
70
80
  ```python
71
- gis_widget = WMTSWidget
81
+ from django_extended_ol.forms.widgets import WMTSWidget
82
+ ...
83
+ class MyCustomGISClass:
84
+ gis_widget = WMTSWidget
72
85
  ```
73
86
 
87
+ If you want a search widget, you can use `WMTSWithSearchWidget`. Please check search service specification below.
88
+
74
89
  4. You can also use it in your admin.py:
75
90
 
76
91
  ```python
@@ -81,4 +96,19 @@ gis_widget = WMTSWidget
81
96
  admin.site.register(YourGeomModel, WMTSGISModelAdmin)
82
97
  ```
83
98
 
99
+ If you want the search widget please use `WMTSGISWithSearchModelAdmin`. Please check search service specification below.
100
+
84
101
  5. Start the development server and visit the admin.
102
+
103
+
104
+ ## Search service specification
105
+
106
+ You'll need a templated URL as showcased in the `settings.py` above.
107
+ Such service should reply GeoJSON feature collection and each feature should have a `bbox` and a property named `label`.
108
+
109
+ # Build this package
110
+
111
+ ```sh
112
+ py -m build
113
+ py -m twine upload dist/*
114
+ ```
@@ -13,5 +13,6 @@ django_extended_ol.egg-info/requires.txt
13
13
  django_extended_ol.egg-info/top_level.txt
14
14
  django_extended_ol/forms/__init__.py
15
15
  django_extended_ol/forms/widgets.py
16
+ django_extended_ol/static/olwidget/css/WMTSWidget.css
16
17
  django_extended_ol/static/olwidget/js/WMTSWidget.js
17
18
  django_extended_ol/templates/gis/openlayers-wmts.html
@@ -4,7 +4,7 @@ build-backend = 'setuptools.build_meta'
4
4
 
5
5
  [project]
6
6
  name = "django-extended-ol"
7
- version = "0.1.0"
7
+ version = "1.1.0"
8
8
  authors = [
9
9
  { name="SITN", email="sitn@ne.ch" },
10
10
  ]
@@ -1,6 +0,0 @@
1
- from django.contrib.gis.admin import GISModelAdmin
2
- from .forms.widgets import WMTSWidget
3
-
4
-
5
- class WMTSGISModelAdmin(GISModelAdmin):
6
- gis_widget = WMTSWidget
@@ -1,27 +0,0 @@
1
- /* global ol */
2
- 'use strict';
3
-
4
- class WMTSWidget extends MapWidget {
5
- createMap() {
6
- this.map_extent = this.options.extent;
7
- this.projection = new ol.proj.Projection({
8
- code: `EPSG:${this.options.map_srid}`,
9
- extent: this.map_extent,
10
- });
11
- return new ol.Map({
12
- target: this.options.map_id,
13
- layers: [this.options.base_layer],
14
- view: new ol.View({
15
- center: this.options.default_center,
16
- resolution: this.options.default_resolution,
17
- projection: this.projection,
18
- resolutions: this.options.resolutions,
19
- constrainResolution: true
20
- })
21
- });
22
- }
23
-
24
- defaultCenter() {
25
- return this.options.default_center;
26
- }
27
- }