|
1 |
| -{% include "header.html" %} |
| 1 | +{% extends "base.html" %} |
2 | 2 |
|
3 | 3 | {% set show_prev_link = false %}
|
4 | 4 | {% set show_next_link = false %}
|
|
8 | 8 | {% set urlq = url + '?' %}
|
9 | 9 | {% endif %}
|
10 | 10 |
|
11 |
| - |
| 11 | +{% block content %} |
12 | 12 | <nav aria-label="breadcrumb">
|
13 | 13 | <ol class="breadcrumb bg-light">
|
14 | 14 | {% for crumb in crumbs %}
|
15 | 15 | {% if not loop.last %}
|
16 |
| - <li class="breadcrumb-item"><a href="{{ crumb.url }}/">{{ crumb.part }}</a></li> |
17 |
| - {% else %}<li class="breadcrumb-item active" aria-current="page">{{ crumb.part }}</li> |
| 16 | + <li class="breadcrumb-item"><a href="{{ crumb.url }}/">{{ crumb.part }}</a></li> |
| 17 | + {% else %} |
| 18 | + <li class="breadcrumb-item active" aria-current="page">{{ crumb.part }}</li> |
18 | 19 | {% endif %}
|
19 | 20 | {% endfor %}
|
20 | 21 |
|
21 | 22 | <li class="ml-auto json-link"><a target="_blank" href="{{ urlq }}f=geojson">GeoJSON</a></li>
|
22 | 23 | </ol>
|
23 | 24 | </nav>
|
24 | 25 |
|
25 |
| -<h1>Collection Items: {{ response.title or response.id }}</h1> |
26 |
| - |
27 |
| -<div id="map" class="rounded" style="width:100%; height:400px;">Loading...</div> |
28 |
| - |
29 |
| -<p> |
30 |
| - <b>Number of matching items:</b> {{ response.numberMatched }}<br/> |
31 |
| - <b>Number of returned items:</b> {{ response.numberReturned }}<br/> |
32 |
| -</p> |
33 |
| - |
34 |
| -<div class="form-row" style="margin-bottom:10px;" id="controls"> |
35 |
| - {% for link in response.links %} |
36 |
| - {% if link.rel == 'previous' %} |
37 |
| - <div class="col-auto"><a class="btn btn-secondary" title="previous page" href="{{ link.href }}">prev</a></div> |
38 |
| - {% endif %} |
39 |
| - {% endfor %} |
40 |
| - <div class="col-auto"> |
41 |
| - <select class="form-control" id="limit"> <!-- TODO: dynamically populate the values based on oga_max_limit --> |
42 |
| - <option value="10">page size</option> |
43 |
| - <option>10</option> |
44 |
| - <option>100</option> |
45 |
| - <option>1000</option> |
46 |
| - <option>10000</option> |
47 |
| - </select> |
| 26 | +<h1 class="my-4"> |
| 27 | + <span class="d-block text-uppercase text-muted h6 mb-0">Collection Items:</span> |
| 28 | + {{ response.title or response.id }} |
| 29 | +</h1> |
| 30 | +{% if response.features|length > 0 %} |
| 31 | +<div class="d-flex flex-row align-items-center mb-4"> |
| 32 | + <div class="flex-grow-1"> |
| 33 | + Showing {{ response.numberReturned }} of {{ response.numberMatched }} items |
48 | 34 | </div>
|
49 |
| - {% for link in response.links %} |
50 |
| - {% if link.rel == 'next' %} |
51 |
| - <div class="col-auto"><a class="btn btn-secondary" title="next page" href="{{ link.href }}">next</a></div> |
| 35 | + <div class="form-inline ml-auto" style="gap: 10px"> |
| 36 | + <div class="d-flex"> |
| 37 | + <label for="limit">Page size: </label> |
| 38 | + <select class="form-control form-control-sm ml-1" id="limit" aria-label="Select page size"> <!-- TODO: dynamically populate the values based on oga_max_limit --> |
| 39 | + <option value="10" {% if limit == 10 %}selected{% endif %}>10</option> |
| 40 | + <option value="25" {% if limit == 25 %}selected{% endif %}>25</option> |
| 41 | + <option value="50" {% if limit == 50 %}selected{% endif %}>50</option> |
| 42 | + <option value="100" {% if limit == 100 %}selected{% endif %}>100</option> |
| 43 | + </select> |
| 44 | + </div> |
| 45 | + {% if response.links|length > 0 %} |
| 46 | + <div class="btn-group btn-group-sm" role="group" aria-label="Paginate"> |
| 47 | + {% for link in response.links %} |
| 48 | + {% if link.rel == 'prev' or link.rel == 'previous' %} |
| 49 | + <a class="btn btn-secondary" title="previous page" href="{{ link.href }}">« prev</a> |
| 50 | + {% endif %} |
| 51 | + {% endfor %} |
| 52 | + {% for link in response.links %} |
| 53 | + {% if link.rel == 'next' %} |
| 54 | + <a class="btn btn-secondary" title="next page" href="{{ link.href }}">next »</a> |
| 55 | + {% endif %} |
| 56 | + {% endfor %} |
52 | 57 | {% endif %}
|
53 |
| - {% endfor %} |
| 58 | + </div> |
| 59 | + </div> |
54 | 60 | </div>
|
| 61 | + |
| 62 | +<div id="map" class="rounded mb-2" style="width:100%; height:400px;">Loading...</div> |
| 63 | + |
55 | 64 | <div class="table-responsive">
|
56 |
| -{% if response.features is defined and response.features|length > 0 %} |
57 |
| -<table class="table"> |
58 |
| - <thead class="thead-light"> |
59 |
| - <th>ID</th> |
60 |
| -{% for key, value in response.features.0.properties.items() %} |
61 |
| - <th style="font-size: 13px">{{ key }}</th> |
62 |
| -{% endfor %} |
63 |
| - </thead> |
64 |
| - <tbody> |
65 |
| -{% for feature in response.features %} |
66 |
| - <tr style="font-size: 11px"> |
67 |
| - <td><a target="_blank" href="{{ template.api_root }}/collections/{{ feature.collection }}/items/{{ feature.id }}">{{ feature.id }}</a></td> |
68 |
| - {% for key, value in feature.properties.items() %} |
69 |
| - <td style="overflow: hidden; text-overflow: ellipsis; max-width: 200px; white-space: nowrap;">{{ value }}</td> |
70 |
| - {% endfor %} |
71 |
| - </tr> |
72 |
| -{% endfor %} |
73 |
| - </tbody> |
74 |
| -</table> |
75 |
| -{% endif %} |
| 65 | + {% if response.features and response.features|length > 0 %} |
| 66 | + <table class="table"> |
| 67 | + <thead class="thead-light"> |
| 68 | + <th>ID</th> |
| 69 | + {% for key, value in response.features.0.properties.items() %} |
| 70 | + <th style="font-size: 13px">{{ key }}</th> |
| 71 | + {% endfor %} |
| 72 | + </thead> |
| 73 | + <tbody> |
| 74 | + {% for feature in response.features %} |
| 75 | + <tr style="font-size: 11px"> |
| 76 | + <td><a target="_blank" href="{{ template.api_root }}/collections/{{ feature.collection }}/items/{{ feature.id }}">{{ feature.id }}</a></td> |
| 77 | + {% for key, value in feature.properties.items() %} |
| 78 | + <td style="overflow: hidden; text-overflow: ellipsis; max-width: 200px; white-space: nowrap;">{{ value }}</td> |
| 79 | + {% endfor %} |
| 80 | + </tr> |
| 81 | + {% endfor %} |
| 82 | + </tbody> |
| 83 | + </table> |
| 84 | + {% endif %} |
76 | 85 | </div>
|
| 86 | +{% else %} |
| 87 | +<div class="text-center mx-auto py-5 w-50"> |
| 88 | + <p class="h4 mb-3">No items found</p> |
| 89 | + <p>You need to add STAC Collections and Items; for example by following the <a href="https://github.com/vincentsarago/MAXAR_opendata_to_pgstac">MAXAR open data demo</a> or <a href="https://github.com/developmentseed/eoAPI/tree/main/demo">other demos.</a></p> |
| 90 | +</div> |
| 91 | +{% endif %} |
77 | 92 |
|
78 | 93 | <script>
|
79 |
| - |
80 |
| - |
81 |
| - |
82 |
| -function changePageSize() { |
83 |
| - var url = "{{ template.api_root }}/collections/{{ response.features[0].collection }}/items?"; |
84 |
| - const searchParams = new URLSearchParams(window.location.search); |
85 |
| - searchParams.set('limit', $("#limit").val()); |
86 |
| - url += searchParams.toString(); |
87 |
| - window.location.href = url; |
88 |
| -} |
89 |
| -$(function() { |
90 |
| - // |
91 |
| - // mapping |
92 |
| - // |
93 |
| - var geojson = {{ response|tojson }}; |
94 |
| - |
95 |
| - var features = (geojson.features) ? geojson.features : []; |
96 |
| - var hasGeom = features.some(feat => feat.geometry); |
97 |
| - if (hasGeom) { |
98 |
| - var map = L.map('map').setView([0, 0], 1); |
99 |
| - map.addLayer(new L.TileLayer( |
100 |
| - 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', { |
101 |
| - maxZoom: 18, |
102 |
| - attribution: 'Map data © <a href="https://openstreetmap.org/copyright">OpenStreetMap contributors</a>' |
| 94 | + window.addEventListener("load", function () { |
| 95 | + // Pagination |
| 96 | + document.getElementById("limit").addEventListener("change", (event) => { |
| 97 | + // Set new page size |
| 98 | + const limit = event.target.value; |
| 99 | + let url = "{{ template.api_root }}/collections/{{ response.id }}/items?"; |
| 100 | + const searchParams = new URLSearchParams(window.location.search); |
| 101 | + searchParams.set('limit', limit); |
| 102 | + url += searchParams.toString(); |
| 103 | + window.location.href = url; |
| 104 | + }); |
| 105 | + |
| 106 | + // Mapping |
| 107 | + const geojson = {{ response|tojson }}; |
| 108 | + |
| 109 | + const hasGeom = geojson.features && geojson.features.some(feat => feat.geometry); |
| 110 | + if (hasGeom) { |
| 111 | + const map = L.map('map').setView([0, 0], 1); |
| 112 | + map.addLayer(new L.TileLayer( |
| 113 | + 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', { |
| 114 | + maxZoom: 18, |
| 115 | + attribution: 'Map data © <a href="https://openstreetmap.org/copyright">OpenStreetMap contributors</a>' |
| 116 | + } |
| 117 | + )); |
| 118 | + |
| 119 | + function addPopup(feature, layer) { |
| 120 | + const aElm = document.createElement('a'); |
| 121 | + aElm.setAttribute('href', `{{ template.api_root }}/collections/${feature.collection}/items/${feature.id}`); |
| 122 | + aElm.setAttribute('target', '_blank'); |
| 123 | + aElm.innerText = feature.id; |
| 124 | + layer.bindPopup(aElm); |
103 | 125 | }
|
104 |
| - )); |
105 | 126 |
|
106 |
| - function addPopup(feature, layer) { |
107 |
| - var aElm = document.createElement('a'); |
108 |
| - aElm.setAttribute('href', `{{ template.api_root }}/collections/${feature.collection}/items/${feature.id}`); |
109 |
| - aElm.setAttribute('target', '_blank'); |
110 |
| - aElm.innerText = feature.id; |
111 |
| - layer.bindPopup(aElm); |
112 |
| - } |
113 |
| - |
114 |
| - var features = L.geoJSON(geojson, { |
115 |
| - onEachFeature: addPopup |
116 |
| - }).addTo(map); |
117 |
| - |
118 |
| - map.fitBounds(features.getBounds()); |
119 |
| - } else { |
120 |
| - document.getElementById("map").style.display = "none"; |
121 |
| - } |
| 127 | + const features = L.geoJSON(geojson, { |
| 128 | + onEachFeature: addPopup, |
| 129 | + weight: 2 |
| 130 | + }).addTo(map); |
122 | 131 |
|
123 |
| - // |
124 |
| - // event handling |
125 |
| - // |
126 |
| - $("#limit").on("change", function() { |
127 |
| - changePageSize(); |
| 132 | + map.fitBounds(features.getBounds()); |
| 133 | + } else { |
| 134 | + document.getElementById("map").style.display = "none"; |
| 135 | + } |
128 | 136 | });
|
129 |
| -}); |
130 | 137 | </script>
|
131 |
| - |
132 |
| -{% include "footer.html" %} |
| 138 | +{% endblock %} |
0 commit comments