Skip to content

Commit ccaf7be

Browse files
committed
Add semantic lookups for features
1 parent 4ef9cb4 commit ccaf7be

File tree

3 files changed

+79
-12
lines changed

3 files changed

+79
-12
lines changed

pygeoapi/api/itemtypes.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -958,6 +958,8 @@ def get_collection_item(api: API, request: APIRequest,
958958

959959
config_dataset = api.config['resources'][dataset]
960960
linked_data = config_dataset.get('linked-data')
961+
if linked_data:
962+
content['linked_data'] = linked_data
961963

962964
if request.format == F_HTML: # render
963965
tpl_config = api.get_dataset_templates(dataset)
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
.object-property.resource-loading::before,
2+
.literal-value.resource-loading::before {
3+
content: "";
4+
display: inline-block;
5+
margin-right: 0.35em;
6+
width: 1em;
7+
height: 1em;
8+
border: 2px solid rgba(0, 0, 0, 0.2);
9+
border-top-color: black;
10+
border-radius: 50%;
11+
vertical-align: middle;
12+
animation: spin 0.8s linear infinite;
13+
}
14+
15+
.object-property.resource-resolved::after,
16+
.literal-value.resource-resolved::after {
17+
content: "✔";
18+
color: green;
19+
margin-left: 0.35em;
20+
font-weight: bold;
21+
vertical-align: middle;
22+
font-family: "Arial", "Helvetica", sans-serif;
23+
}
24+
25+
.object-property.resource-error::after,
26+
.literal-value.resource-error::after {
27+
content: "✖";
28+
color: red;
29+
margin-left: 0.35em;
30+
font-weight: bold;
31+
vertical-align: middle;
32+
font-family: "Arial", "Helvetica", sans-serif;
33+
}
34+
35+
@keyframes spin {
36+
to { transform: rotate(360deg); }
37+
}

pygeoapi/templates/collections/items/item.html

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,33 @@
11
{% extends "_base.html" %}
22
{% set ptitle = data['properties'][data['title_field']] or data['id'] | string %}
3+
{% set linked_data = data.get('linked_data') %}
34
{% block desc %}{{ data.get('properties',{}).get('description', {}) | string | truncate(250) }}{% endblock %}
45
{% block tags %}{{ data['properties'].get('themes', [{}])[0].get('concepts', []) | join(',') }}{% endblock %}
56
{# Optionally renders an img element, otherwise standard value or link rendering #}
6-
{% macro render_item_value(v, width) -%}
7+
{% macro render_item_value(v, width, additional_classes='') -%}
78
{% set val = v | string | trim %}
89
{% if val|length and val.lower().endswith(('.jpg', '.jpeg', '.png', '.gif', '.bmp')) %}
910
{# Ends with image extension: render img element with link to image #}
11+
<span class="literal-value">
1012
<a href="{{ val }}"><img src="{{ val }}" alt="{{ val.split('/') | last }}" width="{{ width }}"/></a>
13+
</span>
1114
{% elif v is string or v is number %}
12-
{{ val | urlize() }}
15+
<span class="literal-value">{{ val | urlize() }}</span>
1316
{% elif v is mapping %}
14-
{% for i,j in v.items() %}
15-
<i>{{ i }}:</i> {{ render_item_value(j, 60) }}<br/>
16-
{% endfor %}
17+
<table class="table table-striped table-border object-table {{ additional_classes }}">
18+
{% for i,j in v.items() %}
19+
<tr>
20+
<td class="object-property" data-property="{{ i }}">{{ i }}</td>
21+
<td class="object-value">{{ render_item_value(j, 60) }}</td>
22+
</tr>
23+
{% endfor %}
24+
</table>
1725
{% elif v is iterable %}
1826
{% for i in v %}
19-
{{ render_item_value(i, 60) }}
27+
{{ render_item_value(i, 60, 'array-entry') }}
2028
{% endfor %}
2129
{% else %}
22-
{{ val | urlize() }}
30+
<span class="literal-value">{{ val | urlize() }}</span>
2331
{% endif %}
2432
{%- endmacro %}
2533
{% block title %}{{ ptitle }}{% endblock %}
@@ -35,6 +43,7 @@
3543
{% endblock %}
3644
{% block extrahead %}
3745
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css"/>
46+
<link rel="stylesheet" href="{{ config['server']['url'] }}/static/css/linked-data.css">
3847
<script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
3948
{% endblock %}
4049

@@ -71,7 +80,7 @@ <h1>{{ ptitle }}</h1>
7180
</div>
7281
</div>
7382
<div class="col-md-6 col-sm-12">
74-
<table class="table table-striped table-bordered">
83+
<table class="table table-striped table-bordered object-table" id="item-properties-table">
7584
<thead>
7685
<tr>
7786
<th>{% trans %}Property{% endtrans %}</th>
@@ -86,14 +95,14 @@ <h1>{{ ptitle }}</h1>
8695
</tr>
8796
{% endif %}
8897
<tr>
89-
<td>id</td>
90-
<td>{{ data.id }}</td>
98+
<td class="object-property" data-property="id">id</td>
99+
<td class="object-value">{{ data.id }}</td>
91100
</tr>
92101
{% for k, v in data['properties'].items() %}
93102
{% if k != data['id_field'] %}
94103
<tr>
95-
<td>{{ k | striptags }}</td>
96-
<td>{{ render_item_value(v, 80) }}</td>
104+
<td class="object-property" data-property="{{ k | striptags }}">{{ k | striptags }}</td>
105+
<td class="object-value">{{ render_item_value(v, 80) }}</td>
97106
</tr>
98107
{% endif %}
99108
{% endfor %}
@@ -135,4 +144,23 @@ <h1>{{ ptitle }}</h1>
135144
map.addLayer(items);
136145
map.fitBounds(items.getBounds(), {maxZoom: 15});
137146
</script>
147+
{% if linked_data and linked_data.get('context') | length %}
148+
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/rdflib.min.js"></script>
149+
<script src="https://github.com/avillar/jsonld-ui-utils/releases/latest/download/jsonld-ui-utils.min.js"></script>
150+
<script>
151+
const rootElem = document.getElementById('item-properties-table');
152+
if (rootElem) {
153+
const linkedDataConfig = {{ linked_data | tojson }}
154+
const options = {};
155+
if (linkedDataConfig.fallback_sparql_endpoint) {
156+
options.fallbackSparqlEndpoint = linkedDataConfig.fallback_sparql_endpoint;
157+
}
158+
const context = { '@context': linkedDataConfig['context'] };
159+
jsonldUIUtils.loadContext(context)
160+
.then(loadedContext => {
161+
jsonldUIUtils.augment(rootElem, loadedContext, options);
162+
});
163+
}
164+
</script>
165+
{% endif %}
138166
{% endblock %}

0 commit comments

Comments
 (0)