django-extended-ol 1.0.0__py3-none-any.whl → 1.1.0__py3-none-any.whl
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.
- django_extended_ol/admin.py +5 -1
- django_extended_ol/forms/widgets.py +11 -1
- django_extended_ol/static/olwidget/css/WMTSWidget.css +30 -0
- django_extended_ol/static/olwidget/js/WMTSWidget.js +64 -0
- django_extended_ol/templates/gis/openlayers-wmts.html +8 -0
- {django_extended_ol-1.0.0.dist-info → django_extended_ol-1.1.0.dist-info}/METADATA +18 -4
- django_extended_ol-1.1.0.dist-info/RECORD +13 -0
- {django_extended_ol-1.0.0.dist-info → django_extended_ol-1.1.0.dist-info}/WHEEL +1 -1
- django_extended_ol-1.0.0.dist-info/RECORD +0 -12
- {django_extended_ol-1.0.0.dist-info → django_extended_ol-1.1.0.dist-info/licenses}/LICENSE +0 -0
- {django_extended_ol-1.0.0.dist-info → django_extended_ol-1.1.0.dist-info}/top_level.txt +0 -0
django_extended_ol/admin.py
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
from django.contrib.gis.admin import GISModelAdmin
|
|
2
|
-
from .forms.widgets import WMTSWidget
|
|
2
|
+
from .forms.widgets import WMTSWidget, WMTSWithSearchWidget
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
class WMTSGISModelAdmin(GISModelAdmin):
|
|
6
6
|
gis_widget = WMTSWidget
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class WMTSGISWithSearchModelAdmin(GISModelAdmin):
|
|
10
|
+
gis_widget = WMTSWithSearchWidget
|
|
@@ -21,13 +21,16 @@ class WMTSWidget(OpenLayersWidget):
|
|
|
21
21
|
"default_map_center": settings.OLWIDGET["globals"].get("default_center", center_from_extent),
|
|
22
22
|
"default_resolution": settings.OLWIDGET["globals"].get("default_resolution", 8),
|
|
23
23
|
"extent": extent,
|
|
24
|
-
"resolutions"
|
|
24
|
+
"resolutions": settings.OLWIDGET["globals"]["resolutions"]
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
class Media(OpenLayersWidget.Media):
|
|
28
28
|
js = OpenLayersWidget.Media.js + (
|
|
29
29
|
"olwidget/js/WMTSWidget.js",
|
|
30
30
|
)
|
|
31
|
+
css = {
|
|
32
|
+
"all": OpenLayersWidget.Media.css["all"] + ("olwidget/css/WMTSWidget.css",)
|
|
33
|
+
}
|
|
31
34
|
|
|
32
35
|
def __init__(self, attrs=None):
|
|
33
36
|
super().__init__()
|
|
@@ -36,3 +39,10 @@ class WMTSWidget(OpenLayersWidget):
|
|
|
36
39
|
self.attrs[key] = self.widget_options[key]
|
|
37
40
|
if attrs:
|
|
38
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
|
+
}
|
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
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
|
+
*/
|
|
5
11
|
createMap() {
|
|
6
12
|
this.map_extent = this.options.extent;
|
|
7
13
|
this.projection = new ol.proj.Projection({
|
|
@@ -24,4 +30,62 @@ class WMTSWidget extends MapWidget {
|
|
|
24
30
|
defaultCenter() {
|
|
25
31
|
return this.options.default_center;
|
|
26
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
|
+
}
|
|
27
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
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: django-extended-ol
|
|
3
|
-
Version: 1.
|
|
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
|
|
@@ -22,7 +22,8 @@ Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
|
|
22
22
|
Requires-Python: >=3.10
|
|
23
23
|
Description-Content-Type: text/markdown
|
|
24
24
|
License-File: LICENSE
|
|
25
|
-
Requires-Dist: Django
|
|
25
|
+
Requires-Dist: Django>=5.0
|
|
26
|
+
Dynamic: license-file
|
|
26
27
|
|
|
27
28
|
# django-extended-ol
|
|
28
29
|
|
|
@@ -67,11 +68,14 @@ OLWIDGET = {
|
|
|
67
68
|
"url_template": 'https://sitn.ne.ch/mapproxy95/wmts/1.0.0/{layer}/{style}/{TileMatrixSet}/{TileMatrix}/{TileRow}/{TileCol}.png',
|
|
68
69
|
"request_encoding": 'REST', # optional
|
|
69
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}'
|
|
70
74
|
}
|
|
71
75
|
}
|
|
72
76
|
```
|
|
73
77
|
|
|
74
|
-
3. You can now use WMTSWidget in your gis forms:
|
|
78
|
+
3. You can now use `WMTSWidget` in your gis forms:
|
|
75
79
|
|
|
76
80
|
```python
|
|
77
81
|
from django_extended_ol.forms.widgets import WMTSWidget
|
|
@@ -80,6 +84,8 @@ class MyCustomGISClass:
|
|
|
80
84
|
gis_widget = WMTSWidget
|
|
81
85
|
```
|
|
82
86
|
|
|
87
|
+
If you want a search widget, you can use `WMTSWithSearchWidget`. Please check search service specification below.
|
|
88
|
+
|
|
83
89
|
4. You can also use it in your admin.py:
|
|
84
90
|
|
|
85
91
|
```python
|
|
@@ -90,11 +96,19 @@ class MyCustomGISClass:
|
|
|
90
96
|
admin.site.register(YourGeomModel, WMTSGISModelAdmin)
|
|
91
97
|
```
|
|
92
98
|
|
|
99
|
+
If you want the search widget please use `WMTSGISWithSearchModelAdmin`. Please check search service specification below.
|
|
100
|
+
|
|
93
101
|
5. Start the development server and visit the admin.
|
|
94
102
|
|
|
95
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
|
+
|
|
96
109
|
# Build this package
|
|
97
110
|
|
|
98
111
|
```sh
|
|
99
112
|
py -m build
|
|
113
|
+
py -m twine upload dist/*
|
|
100
114
|
```
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
django_extended_ol/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
django_extended_ol/admin.py,sha256=gmm3dZHcCwop1QNm5RJr2iHkBUPqWdDexe80espo32g,281
|
|
3
|
+
django_extended_ol/apps.py,sha256=hw3h5JXhThL1TSDfWa2wxwBTWvCHuaEHWb8axT_QP88,188
|
|
4
|
+
django_extended_ol/forms/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
+
django_extended_ol/forms/widgets.py,sha256=QvqDtWdBoFsG_IGW9QaEHEVgud49mD-0d4rjxq1cMqE,1987
|
|
6
|
+
django_extended_ol/static/olwidget/css/WMTSWidget.css,sha256=Rw8fvpdpjoA-1Icp3gwpE78XPOViL5YNXNGy20TzQOM,538
|
|
7
|
+
django_extended_ol/static/olwidget/js/WMTSWidget.js,sha256=fS9hCvChKIIvJasDJt75Rh3Am0yJjrlL229w_rRkU3I,3152
|
|
8
|
+
django_extended_ol/templates/gis/openlayers-wmts.html,sha256=zSsGwdN8bESYHq-OTx4__fgbB_Kn50dYgWFTfzd2w00,2231
|
|
9
|
+
django_extended_ol-1.1.0.dist-info/licenses/LICENSE,sha256=0uvSPKfP0VUrQ1XqeXD62tYc54cfQqt21YI9lWW9hq8,1564
|
|
10
|
+
django_extended_ol-1.1.0.dist-info/METADATA,sha256=jp-6LZJbiiZhgNxG7gP_6YQs226LQ0V0rmf2-FXsqz8,3663
|
|
11
|
+
django_extended_ol-1.1.0.dist-info/WHEEL,sha256=SmOxYU7pzNKBqASvQJ7DjX3XGUF92lrGhMb3R6_iiqI,91
|
|
12
|
+
django_extended_ol-1.1.0.dist-info/top_level.txt,sha256=rX8AqitfQu0etd6PoOeNxcRl5fsus-YOs932PGUjDIs,19
|
|
13
|
+
django_extended_ol-1.1.0.dist-info/RECORD,,
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
django_extended_ol/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
django_extended_ol/admin.py,sha256=tE7_DtllUHuNSEpsKLkfUdLpSX7uhjZa-Q5y2UH7h7A,165
|
|
3
|
-
django_extended_ol/apps.py,sha256=hw3h5JXhThL1TSDfWa2wxwBTWvCHuaEHWb8axT_QP88,188
|
|
4
|
-
django_extended_ol/forms/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
-
django_extended_ol/forms/widgets.py,sha256=u6P3G7lCCbtYnw6bMsQ5EAh5bZ2gsTKACL4PBHbT6yo,1681
|
|
6
|
-
django_extended_ol/static/olwidget/js/WMTSWidget.js,sha256=6fGzhd8wx20Oll_64fu7ZPfs9MZwj74vQYZ7hnanfxE,796
|
|
7
|
-
django_extended_ol/templates/gis/openlayers-wmts.html,sha256=4MhZr_ldK_w7t2sswmHjTekX_P_js9SsXHW_0ESBSPw,1926
|
|
8
|
-
django_extended_ol-1.0.0.dist-info/LICENSE,sha256=0uvSPKfP0VUrQ1XqeXD62tYc54cfQqt21YI9lWW9hq8,1564
|
|
9
|
-
django_extended_ol-1.0.0.dist-info/METADATA,sha256=OUyTNy8FtaC14xCuwMwlwtOgeN8mcAvPm2vT8lRLLh0,2954
|
|
10
|
-
django_extended_ol-1.0.0.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
|
11
|
-
django_extended_ol-1.0.0.dist-info/top_level.txt,sha256=rX8AqitfQu0etd6PoOeNxcRl5fsus-YOs932PGUjDIs,19
|
|
12
|
-
django_extended_ol-1.0.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|