github.com/go-spatial/go-wfs@v0.1.4-0.20190401000911-c9fba2bb5188/wfs3/html_templates.go (about) 1 /////////////////////////////////////////////////////////////////////////////// 2 // 3 // The MIT License (MIT) 4 // Copyright (c) 2018 Tom Kralidis 5 // 6 // Permission is hereby granted, free of charge, to any person obtaining a copy 7 // of this software and associated documentation files (the "Software"), to 8 // deal in the Software without restriction, including without limitation the 9 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 // sell copies of the Software, and to permit persons to whom the Software is 11 // furnished to do so, subject to the following conditions: 12 // 13 // The above copyright notice and this permission notice shall be included in 14 // all copies or substantial portions of the Software. 15 // 16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 20 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 21 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 22 // USE OR OTHER DEALINGS IN THE SOFTWARE. 23 // 24 /////////////////////////////////////////////////////////////////////////////// 25 26 package wfs3 27 28 var tmpl_base = `<!doctype html> 29 <html lang="en"> 30 <head> 31 <meta charset="utf-8"> 32 <title>{{ .config.Metadata.Identification.Title }}</title> 33 {{ range .links }} 34 <link rel="{{ .Rel }}" type="application/json" href="{{ .Href }}"/> 35 {{ end }} 36 <link rel="stylesheet" href="https://openlayers.org/en/v4.6.5/css/ol.css" type="text/css"> 37 <script src="https://openlayers.org/en/v4.6.5/build/ol.js"></script> 38 <style> 39 .map { 40 height: 400px; 41 width: 100%; 42 margin-bottom: 10px; 43 } 44 .arrow_box { 45 border-radius: 5px; 46 padding: 10px; 47 } 48 .arrow_box { 49 position: relative; 50 background: #fff; 51 border: 1px solid #003c88; 52 } 53 .arrow_box:after, .arrow_box:before { 54 top: 100%; 55 left: 50%; 56 border: solid transparent; 57 content: " "; 58 height: 0; 59 width: 0; 60 position: absolute; 61 pointer-events: none; 62 } 63 .arrow_box:after { 64 border-color: rgba(255, 255, 255, 0); 65 border-top-color: #fff; 66 border-width: 10px; 67 margin-left: -10px; 68 } 69 .arrow_box:before { 70 border-color: rgba(153, 153, 153, 0); 71 border-top-color: #003c88; 72 border-width: 11px; 73 margin-left: -11px; 74 } 75 </style> 76 <script> 77 var image = new ol.style.Circle({ 78 radius: 5, 79 fill: new ol.style.Fill({ 80 color: 'rgb(255, 0, 0)' 81 }), 82 stroke: new ol.style.Stroke({color: 'red', width: 1}) 83 }); 84 var styles = { 85 'Point': new ol.style.Style({ 86 image: image 87 }), 88 'LineString': new ol.style.Style({ 89 stroke: new ol.style.Stroke({ 90 color: 'green', 91 width: 1 92 }) 93 }), 94 'MultiLineString': new ol.style.Style({ 95 stroke: new ol.style.Stroke({ 96 color: 'green', 97 width: 1 98 }) 99 }), 100 'MultiPoint': new ol.style.Style({ 101 image: image 102 }), 103 'MultiPolygon': new ol.style.Style({ 104 stroke: new ol.style.Stroke({ 105 color: 'yellow', 106 width: 1 107 }), 108 fill: new ol.style.Fill({ 109 color: 'rgba(255, 255, 0, 0.1)' 110 }) 111 }), 112 'Polygon': new ol.style.Style({ 113 stroke: new ol.style.Stroke({ 114 color: 'blue', 115 lineDash: [4], 116 width: 3 117 }), 118 fill: new ol.style.Fill({ 119 color: 'rgba(0, 0, 255, 0.1)' 120 }) 121 }), 122 'GeometryCollection': new ol.style.Style({ 123 stroke: new ol.style.Stroke({ 124 color: 'magenta', 125 width: 2 126 }), 127 fill: new ol.style.Fill({ 128 color: 'magenta' 129 }), 130 image: new ol.style.Circle({ 131 radius: 10, 132 fill: null, 133 stroke: new ol.style.Stroke({ 134 color: 'magenta' 135 }) 136 }) 137 }), 138 'Circle': new ol.style.Style({ 139 stroke: new ol.style.Stroke({ 140 color: 'red', 141 width: 2 142 }), 143 fill: new ol.style.Fill({ 144 color: 'rgba(255,0,0,0.2)' 145 }) 146 }) 147 }; 148 var styleFunction = function(feature) { 149 return styles[feature.getGeometry().getType()]; 150 }; 151 </script> 152 </head> 153 <body> 154 <header> 155 <h1><a href="{{ .config.Server.URLBasePath }}?f=text/html">{{ .config.Metadata.Identification.Title }}</a><a href="{{ .config.Server.URLBasePath }}"><img src="https://image.flaticon.com/icons/svg/136/136443.svg" width="50" height="50"/></a></h1> 156 <span itemprop="description">{{ .config.Metadata.Identification.Description }}</span> 157 </header> 158 <hr/> 159 {{ .body }} 160 <hr/> 161 <footer>Powered by <a title="jivan" href="https://github.com/go-spatial/jivan">jivan</a><img width="50" height="50" src="https://raw.githubusercontent.com/go-spatial/branding/master/go-spatial.png"/></footer> 162 </body> 163 </html>` 164 165 // The /api/ endpoint doesn't support text/html 166 var tmpl_root = ` 167 <h2><a href="conformance?f=text/html">Conformance</a></h2> 168 <h2><a href="collections?f=text/html">Collections</a></h2> 169 <h2>Links</h2> 170 <ul> 171 {{ range .data.Links }} 172 {{ if (eq .Rel "service") }} 173 <li><a href="{{ .Href }}">{{ .Href }}</a></li> 174 {{ else }} 175 <li><a href="{{ .Href }}?f=text/html">{{ .Href }}?f=text/html</a></li> 176 {{ end }} 177 {{ end }} 178 </ul>` 179 180 var tmpl_conformance = ` 181 <h2>Conformance <a href="{{ .config.Server.URLBasePath }}conformance"><img src="https://image.flaticon.com/icons/svg/136/136443.svg" width="50" height="50"/></a></h2> 182 <ul> 183 {{ range .data.ConformsTo }} 184 <li><a href="{{ . }}">{{ . }}</a></li> 185 {{ end }} 186 </ul>` 187 188 var tmpl_collections = ` 189 <h2>Collections <a href="{{ .config.Server.URLBasePath }}collections"><img src="https://image.flaticon.com/icons/svg/136/136443.svg" width="50" height="50"/></a></h2> 190 <ul> 191 {{ range .data.Collections }} 192 <li><a href="./collections/{{ .Name }}?f=text/html">{{ .Name }}</a></li> 193 {{ end }} 194 </ul>` 195 196 var tmpl_collection = ` 197 <h2>{{ .data.Name }} <a href="{{ .config.Server.URLBasePath }}collections/{{ .data.Name }}"><img src="https://image.flaticon.com/icons/svg/136/136443.svg" width="50" height="50"/></a></h2> 198 <span>{{ .data.Description }}</span> 199 <div><a href="./{{ .data.Name }}/items?f=text/html">Browse Features</a></div> 200 <h2>Links</h2> 201 <ul> 202 {{ range .data.Links }} 203 <li><a href="{{ .Href }}">{{ .Href }}</a></li> 204 {{ end }} 205 </ul>` 206 207 var tmpl_collection_features = ` 208 <link rel="stylesheet" href="https://openlayers.org/en/v4.6.5/css/ol.css" type="text/css"> 209 <script src="https://openlayers.org/en/v4.6.5/build/ol.js"></script> 210 <h2>Features <a href="items"><img src="https://image.flaticon.com/icons/svg/136/136443.svg" width="50" height="50"/></a></h2> 211 {{ range .data.Links }} 212 {{ if (eq .Rel "self") }} 213 <h2><a href="{{ .Href }}">Collection</a></h2> 214 {{ end }} 215 {{ if (eq .Rel "alternate") }} 216 <h2><a href="{{ .Href }}"><img src="https://image.flaticon.com/icons/svg/136/136443.svg" width="50" height="50"/></a></h2> 217 {{ end }} 218 {{ end }} 219 <h2>Links</h2> 220 {{ range .data.Links }} 221 {{ if (eq .Rel "prev") }} 222 <span><a href="{{ .Href }}&f=text/html">Prev</a></span> 223 {{ end }} 224 {{ if (eq .Rel "next") }} 225 <span><a href="{{ .Href }}&f=text/html">Next</a></span> 226 {{ end }} 227 {{ end }} 228 <table> 229 <tr> 230 <td> 231 <ul> 232 {{ range .data.Features }} 233 <li><a href="items/{{ .ID }}?f=text/html">{{ .ID }}</a></li> 234 {{ end }} 235 </ul> 236 </td> 237 <td> 238 <div id="map" class="map"></div> 239 <div id="popup-container" class="arrow_box"></div> 240 </td> 241 </tr> 242 </table> 243 <script> 244 var geojsonObject = {{ .data }}; 245 246 var vectorSource = new ol.source.Vector({ 247 features: (new ol.format.GeoJSON()).readFeatures(geojsonObject, { 248 dataProjection: "EPSG:4326", 249 featureProjection: "EPSG:3857" 250 }) 251 }); 252 var vectorLayer = new ol.layer.Vector({ 253 source: vectorSource, 254 style: styleFunction, 255 }); 256 257 var map = new ol.Map({ 258 layers: [ 259 new ol.layer.Tile({ 260 source: new ol.source.OSM() 261 }), 262 vectorLayer 263 ], 264 target: 'map', 265 controls: ol.control.defaults({ 266 attributionOptions: { 267 collapsible: false 268 } 269 }), 270 view: new ol.View({ 271 zoom: -10 272 }) 273 }); 274 map.getView().fit(vectorLayer.getSource().getExtent(), map.getSize()); 275 276 var overlay = new ol.Overlay({ 277 element: document.getElementById('popup-container'), 278 positioning: 'bottom-center', 279 offset: [0, -10] 280 }); 281 map.addOverlay(overlay); 282 283 map.on('click', function(e) { 284 overlay.setPosition(); 285 var features = map.getFeaturesAtPixel(e.pixel); 286 if (features) { 287 var identifier = features[0].getId(); 288 var coords = features[0].getGeometry().getCoordinates(); 289 var hdms = ol.coordinate.toStringHDMS(ol.proj.toLonLat(coords)); 290 var popup = '<a href="items/' + identifier + '?f=text/html">' + identifier + '</a>'; 291 overlay.getElement().innerHTML = popup; 292 overlay.setPosition(coords); 293 } 294 }); 295 </script>` 296 297 var tmpl_collection_feature = ` 298 <link rel="stylesheet" href="https://openlayers.org/en/v4.6.5/css/ol.css" type="text/css"> 299 <script src="https://openlayers.org/en/v4.6.5/build/ol.js"></script> 300 {{ range .data.Links }} 301 {{ if (eq .Rel "collection") }} 302 <h2><a href="{{ .Href }}">Collection</a></h2> 303 {{ end }} 304 {{ end }} 305 <h2>Feature <a href="{{ .data.ID }}"><img src="https://image.flaticon.com/icons/svg/136/136443.svg" width="50" height="50"/></a></h2> 306 <h2>Links</h2> 307 <table> 308 <tr> 309 <td> 310 <h3>Properties</h3> 311 <ul> 312 {{ range $key, $value := .data.Properties }} 313 <li>{{ $key }}: {{ $value }}</li> 314 {{ end }} 315 </ul> 316 </td> 317 <td> 318 <div id="map" class="map"></div> 319 <div id="popup-container" class="arrow_box"></div> 320 </td> 321 </tr> 322 </table> 323 <script> 324 var geojsonObject = {{ .data }}; 325 326 var vectorSource = new ol.source.Vector({ 327 features: (new ol.format.GeoJSON()).readFeatures(geojsonObject, { 328 dataProjection: "EPSG:4326", 329 featureProjection: "EPSG:3857" 330 }) 331 }); 332 var vectorLayer = new ol.layer.Vector({ 333 source: vectorSource, 334 style: styleFunction, 335 }); 336 337 var map = new ol.Map({ 338 layers: [ 339 new ol.layer.Tile({ 340 source: new ol.source.OSM() 341 }), 342 vectorLayer 343 ], 344 target: 'map', 345 controls: ol.control.defaults({ 346 attributionOptions: { 347 collapsible: false 348 } 349 }), 350 view: new ol.View({ 351 zoom: -10 352 }) 353 }); 354 map.getView().fit(vectorLayer.getSource().getExtent(), map.getSize()); 355 map.getView().setZoom(15); 356 357 var overlay = new ol.Overlay({ 358 element: document.getElementById('popup-container'), 359 positioning: 'bottom-center', 360 offset: [0, -10] 361 }); 362 map.addOverlay(overlay); 363 </script>`