github.com/PDOK/gokoala@v0.50.6/internal/ogc/features/templates/features.go.html (about)

     1  {{- /*gotype: github.com/PDOK/gokoala/internal/engine.TemplateData*/ -}}
     2  {{define "content"}}
     3  {{ $cfg := .Config }}
     4  {{ $baseUrl := $cfg.BaseURL }}
     5  
     6  <script>
     7      {{- /* generic function to update query string parameters */ -}}
     8      function updateQueryString(name, value) {
     9          const url = new URL(window.location.href);
    10          url.searchParams.delete('cursor'); // when filters change, we can't continue pagination.
    11          if (value) {
    12            if (name === 'datetime') {
    13              url.searchParams.set(name, new Date(value).toISOString()); // input is %Y-%m-%d, but parameter value should be RFC3339
    14            } else {
    15              url.searchParams.set(name, value);
    16            }
    17          } else {
    18            url.searchParams.delete(name);
    19          }
    20          window.location.href = url.toString();
    21      }
    22  
    23  </script>
    24  
    25  <hgroup>
    26      <h1 class="title h2" id="title">{{ .Config.Title }} - {{ if and .Params.Metadata .Params.Metadata.Title }}{{ .Params.Metadata.Title }}{{ else }}{{ .Params.CollectionID }}{{ end }}</h1>
    27  </hgroup>
    28  
    29  <section class="row py-3">
    30      <div class="col-md-6 col-sm-12">
    31          <!-- description -->
    32          <div class="card">
    33              <h2 class="card-header h5">
    34                  {{ if and .Params.Metadata .Params.Metadata.Title }}
    35                      {{ .Params.Metadata.Title }}
    36                  {{ else }}
    37                      {{ .Params.CollectionID }}
    38                  {{ end }}
    39              </h2>
    40              <div class="card-body">
    41                  {{ if and .Params.Metadata .Params.Metadata.Description }}
    42                      {{ markdown .Params.Metadata.Description }}
    43                  {{ end }}
    44              </div>
    45          </div>
    46  
    47          <!-- filters -->
    48          <form class="col-12 mt-4">
    49              <!-- projection -->
    50              <div class="row mb-2">
    51                  <label for="srs-select" class="col-sm-3 col-form-label fw-bold">{{ i18n "Projection" }}</label>
    52                  <div class="col-sm">
    53                      <select id="srs-select" class="form-select" onchange="updateQueryString('crs', this.value)">
    54                          <option value="http://www.opengis.net/def/crs/OGC/1.3/CRS84" selected>
    55                              http://www.opengis.net/def/crs/OGC/1.3/CRS84
    56                          </option>
    57                          {{ range $index, $srs := .Config.OgcAPI.Features.ProjectionsForCollection $.Params.CollectionID }}
    58                          <option value=http://www.opengis.net/def/crs/EPSG/0/{{ trimPrefix "EPSG:" $srs }}>http://www.opengis.net/def/crs/EPSG/0/{{ $srs }}</option>
    59                          {{ end }}
    60                      </select>
    61                  </div>
    62              </div>
    63              {{ if and .Params.Metadata .Params.Metadata.TemporalProperties }}
    64              <!-- datetime -->
    65              <div class="row mb-2">
    66                  <label for="referencedate-input" class="col-sm-3 col-form-label fw-bold">{{ i18n "ReferenceDate" }}</label>
    67                  <div class="col-sm">
    68                      <input id="referencedate-input" type="date" class="form-control"
    69                             value="{{ if .Params.ReferenceDate }}{{ .Params.ReferenceDate | date "2006-01-02" }}{{ end }}"
    70                             onchange="updateQueryString('datetime', this.value)">
    71                  </div>
    72              </div>
    73              {{ end }}
    74              <!-- limit -->
    75              <div class="row mb-2">
    76                  <label for="limit-select" class="col-sm-3 col-form-label fw-bold">{{ i18n "Limit" }}</label>
    77                  <div class="col-sm">
    78                      <select id="limit-select" class="form-select" aria-label="Limit selection"
    79                              onchange="updateQueryString('limit', this.value)">
    80                          <option value="10" {{if eq .Params.Limit 10 }}selected{{end}}>10 {{ i18n "Items" }}</option>
    81                          <option value="100" {{if eq .Params.Limit 100 }}selected{{end}}>100 {{ i18n "Items" }}</option>
    82                          {{/* see Limit.Max in config.go, can't be smaller than 100 */}}
    83                          <option value="{{ $cfg.OgcAPI.Features.Limit.Max }}" {{if eq .Params.Limit
    84                                  $cfg.OgcAPI.Features.Limit.Max }}selected{{end}}>{{ $cfg.OgcAPI.Features.Limit.Max }} {{
    85                              i18n "Items" }} ({{ i18n "Max" }})
    86                          </option>
    87                      </select>
    88                  </div>
    89              </div>
    90              <!-- property filters -->
    91              {{- range $propFilter := $cfg.OgcAPI.Features.PropertyFiltersForCollection $.Params.CollectionID -}}
    92              <div class="row mb-2">
    93                  <label for="{{ $propFilter.Name }}-input" class="col-sm-3 col-form-label fw-bold text-truncate"
    94                         title="{{ $propFilter.Name | title }}">{{ $propFilter.Name | title }}</label>
    95                  <div class="col-sm">
    96                      <input id="{{ $propFilter.Name }}-input" type="text" class="form-control"
    97                             value="{{ index $.Params.PropertyFilters $propFilter.Name }}"
    98                             onchange="updateQueryString('{{ $propFilter.Name }}', this.value)">
    99                  </div>
   100              </div>
   101              {{ end }}
   102          </form>
   103      </div>
   104  
   105      <!-- map viewer -->
   106      <div class="col-md-6 col-sm-12">
   107          <link rel="stylesheet" type="text/css" href="view-component/styles.css">
   108          <script type="text/javascript" src="view-component/main.js"></script>
   109          <script type="text/javascript" src="view-component/polyfills.js"></script>
   110          <script type="text/javascript" src="view-component/runtime.js"></script>
   111          <app-feature-view id="viewer" background-map="{{ $cfg.OgcAPI.Features.Basemap }}" class="card"></app-feature-view>
   112          <script type="module">
   113            const url = new URL(window.location.href)
   114            url.searchParams.set('f','json');
   115            const viewer = document.getElementById('viewer');
   116            viewer.setAttribute('items-url', url);
   117  
   118            if (url.searchParams.get('crs') !== null) {
   119              let crs = url.searchParams.get('crs');
   120              document.getElementById('srs-select').value = crs;
   121              viewer.setAttribute('projection', crs)
   122            }
   123  
   124            viewer.addEventListener('box', selectbox => {
   125              updateQueryString("bbox", selectbox.detail)
   126            })
   127          </script>
   128          <noscript>Enable Javascript to view features on a map</noscript>
   129      </div>
   130  </section>
   131  
   132  <section class="row">
   133      <!-- pagination -->
   134      <div class="col-md-12">
   135          <nav aria-label="Page navigation">
   136              <ul class="pagination">
   137                  <li>
   138                      <a class="page-link  {{if not .Params.Cursor.HasPrev }}disabled{{end}}" href="{{ .Params.PrevLink }}" aria-label="{{ i18n "Prev" }}">
   139                          <span aria-hidden="true">&laquo;</span>
   140                          {{ i18n "Prev" }}
   141                      </a>
   142                  </li>
   143                  <li>
   144                      <a class="page-link {{if not .Params.Cursor.HasNext }}disabled{{end}}" href="{{ .Params.NextLink }}" aria-label="{{ i18n "Next" }}">
   145                          {{ i18n "Next" }}
   146                          <span aria-hidden="true">&raquo;</span>
   147                      </a>
   148                  </li>
   149              </ul>
   150          </nav>
   151      </div>
   152  
   153      <!-- results/features -->
   154      <div class="col-md-12">
   155          {{ range $feat := .Params.Features }}
   156          <table class="table table-striped">
   157              <thead>
   158              <tr>
   159                  <th colspan="2"><a href="{{ $baseUrl }}/collections/{{ $.Params.CollectionID }}/items/{{ $feat.ID }}" aria-label="{{ i18n "To" }} feature {{ $feat.ID }}">{{ $feat.ID }}</a></th>
   160              </tr>
   161              </thead>
   162              <tbody>
   163              {{ range $key, $value := $feat.Properties }}
   164              <tr>
   165                  <td class="w-20">{{ $key }}</td>
   166                  <td>{{ $value }}</td>
   167              </tr>
   168              {{ end }}
   169              </tbody>
   170          </table>
   171          {{ end }}
   172      </div>
   173  </section>
   174  {{end}}