]> git.openstreetmap.org Git - nominatim-ui.git/blob - src/pages/DetailsPage.svelte
Enable simple CI run (#77)
[nominatim-ui.git] / src / pages / DetailsPage.svelte
1 <script>
2   import { fetch_from_api, update_html_title } from '../lib/api_utils.js';
3   import { page } from '../lib/stores.js';
4
5   import {
6     osmLink, wikipediaLink, coverageType, isAdminBoundary,
7     formatAddressRank, formatKeywordToken
8   } from '../lib/helpers.js';
9   import MapIcon from '../components/MapIcon.svelte';
10   import DetailsIndex from '../components/DetailsIndex.svelte';
11   import DetailsOneRow from '../components/DetailsOneRow.svelte';
12   import DetailsLink from '../components/DetailsLink.svelte';
13   import Map from '../components/Map.svelte';
14
15   let aPlace;
16   let errorResponse;
17   let base_url = window.location.search;
18   let current_result;
19
20   function loaddata(search_params) {
21     var api_request_params = {
22       place_id: search_params.get('place_id'),
23       osmtype: search_params.get('osmtype'),
24       osmid: search_params.get('osmid'),
25       class: search_params.get('class'),
26       keywords: search_params.get('keywords'),
27       addressdetails: 1,
28       hierarchy: (search_params.get('hierarchy') === '1' ? 1 : 0),
29       group_hierarchy: 1,
30       polygon_geojson: 1,
31       format: 'json'
32     };
33
34     if (api_request_params.place_id || (api_request_params.osmtype && api_request_params.osmid)) {
35
36       if (api_request_params.place_id) {
37         update_html_title('Details for ' + api_request_params.place_id);
38       } else {
39         update_html_title('Details for ' + api_request_params.osmtype + api_request_params.osmid);
40       }
41
42       fetch_from_api('details', api_request_params, function (data) {
43         window.scrollTo(0, 0);
44         if (data.error) {
45           errorResponse = data;
46           current_result = undefined;
47         } else {
48           aPlace = data;
49           errorResponse = undefined;
50           current_result = data;
51         }
52       });
53     } else {
54       aPlace = undefined;
55     }
56   }
57
58   $: {
59     let pageinfo = $page;
60     if (pageinfo.tab === 'details') {
61       loaddata(pageinfo.params);
62     }
63   }
64 </script>
65
66 {#if errorResponse}
67   {errorResponse.error.message}
68 {/if}
69 {#if aPlace}
70   <div class="container">
71     <div class="row">
72       <div class="col-sm-10">
73         <h1>
74           {aPlace.localname}
75           <small><DetailsLink feature={aPlace}>link to this page</DetailsLink></small>
76         </h1>
77       </div>
78       <div class="col-sm-2 text-right">
79         <MapIcon aPlace={aPlace} />
80       </div>
81     </div>
82     <div class="row">
83       <div class="col-md-6">
84         <table id="locationdetails" class="table table-striped">
85           <tbody>
86             <tr>
87               <td>Name</td>
88               <td>
89                 {#each Object.keys(aPlace.names) as name}
90                   <div class="line">
91                     <span class="name">{aPlace.names[name]}</span> ({name})
92                   </div>
93                 {/each}
94               </td>
95             </tr>
96             <tr>
97               <td>Type</td>
98               <td>{aPlace.category}:{aPlace.type}</td>
99             </tr>
100             <tr>
101               <td>Last Updated</td>
102               <td>{aPlace.indexed_date}</td>
103             </tr>
104             {#if (isAdminBoundary(aPlace)) }
105             <tr>
106               <td>Admin Level</td>
107               <td>{aPlace.admin_level}</td>
108             </tr>
109             {/if}
110             <tr>
111               <td>Search Rank</td>
112               <td>{aPlace.rank_search}</td>
113             </tr>
114             <tr>
115               <td>Address Rank</td>
116               <td>{aPlace.rank_address} ({formatAddressRank(aPlace.rank_address)})</td>
117             </tr>
118             {#if aPlace.calculated_importance}
119               <tr>
120                 <td>Importance</td>
121                 <td>
122                   {aPlace.calculated_importance}
123                   {#if !aPlace.importance} (estimated){/if}
124                 </td>
125               </tr>
126             {/if}
127             <tr>
128               <td>Coverage</td>
129               <td>{coverageType(aPlace)}</td>
130             </tr>
131             <tr>
132               <td>Centre Point (lat,lon)</td>
133               <td>
134                 {aPlace.centroid.coordinates[1]},{aPlace.centroid.coordinates[0]}
135               </td>
136             </tr>
137             <tr>
138               <td>OSM</td>
139               <td>{@html osmLink(aPlace)}
140             </tr>
141             <tr>
142               <td>
143                 Place Id
144                 (<a href="https://nominatim.org/release-docs/develop/api/Output/#place_id-is-not-a-persistent-id">on this server</a>)
145               </td>
146               <td>{aPlace.place_id}</td>
147             </tr>
148             {#if aPlace.calculated_wikipedia}
149               <tr>
150                 <td>Wikipedia Calculated</td>
151                 <td>{@html wikipediaLink(aPlace)}</td>
152               </tr>
153             {/if}
154             <tr>
155               <td>Computed Postcode</td>
156               <td>{aPlace.calculated_postcode}</td>
157             </tr>
158             <tr>
159               <td>Address Tags</td>
160               <td>
161                 {#each Object.keys(aPlace.addresstags) as name}
162                   <div class="line">
163                     <span class="name">{aPlace.addresstags[name]}</span> ({name})
164                   </div>
165                 {/each}
166               </td>
167             </tr>
168             <tr>
169               <td>Extra Tags</td>
170               <td>
171                 {#each Object.keys(aPlace.extratags) as name}
172                   <div class="line">
173                     <span class="name">{aPlace.extratags[name]}</span> ({name})
174                   </div>
175                 {/each}
176               </td>
177             </tr>
178           </tbody>
179         </table>
180       </div>
181       <div class="col-md-6">
182         <div id="map-wrapper">
183           <Map {current_result} />
184         </div>
185       </div>
186     </div>
187     <div class="row">
188       <div class="col-md-12">
189         <h2>Address</h2>
190          <table id="address" class="table table-striped table-small">
191           <thead>
192             <tr>
193               <th>Local name</th>
194               <th>Type</th>
195               <th>OSM</th>
196               <th>Address rank</th>
197               <th>Admin level</th>
198               <th>Distance</th>
199               <th></th>
200             </tr>
201           </thead>
202           <tbody>
203             {#if aPlace.address}
204               {#each aPlace.address as addressLine}
205                 <DetailsOneRow addressLine={addressLine} bDistanceInMeters=false />
206               {/each}
207             {/if}
208
209             {#if aPlace.linked_places}
210               <tr class="all-columns"><td colspan="6"><h2>Linked Places</h2></td></tr>
211               {#each aPlace.linked_places as addressLine}
212                 <DetailsOneRow addressLine={addressLine} bDistanceInMeters=true />
213               {/each}
214             {/if}
215
216             <tr class="all-columns"><td colspan="6"><h2>Keywords</h2></td></tr>
217             {#if aPlace.keywords}
218               <tr class="all-columns"><td colspan="6"><h3>Name Keywords</h3></td></tr>
219               {#each aPlace.keywords.name as keyword}
220                 <tr>
221                   <td>{formatKeywordToken(keyword.token)}</td>
222                   {#if keyword.id}
223                     <td>word id: {keyword.id}</td>
224                   {/if}
225                 </tr>
226               {/each}
227
228               <tr class="all-columns"><td colspan="6"><h3>Address Keywords</h3></td></tr>
229               {#each aPlace.keywords.address as keyword}
230                 <tr>
231                   <td>{formatKeywordToken(keyword.token)}</td>
232                   {#if keyword.id}
233                     <td>word id: {keyword.id}</td>
234                   {/if}
235               </tr>
236               {/each}
237             {:else}
238               <tr>
239                 <td>
240                    <a class="btn btn-outline-secondary btn-sm"
241                     href="{base_url}&keywords=1">display keywords</a>
242                 </td>
243               </tr>
244             {/if}
245
246             <tr class="all-columns"><td colspan="6"><h2>Parent Of</h2></td></tr>
247             {#if aPlace.hierarchy}
248
249               {#each Object.keys(aPlace.hierarchy) as type}
250                 <tr class="all-columns"><td colspan="6"><h3>{type}</h3></td></tr>
251                 {#each aPlace.hierarchy[type] as line}
252                   <DetailsOneRow addressLine={line} bDistanceInMeters=true />
253                {/each}
254               {/each}
255
256               {#if Object.keys(aPlace.hierarchy) > 500}
257                 <p>There are more child objects which are not shown.</p>
258               {/if}
259             {:else}
260               <tr>
261                 <td>
262                    <a class="btn btn-outline-secondary btn-sm"
263                     href="{base_url}&hierarchy=1">display child places</a>
264                 </td>
265               </tr>
266             {/if}
267           </tbody>
268         </table>
269       </div>
270     </div>
271   </div>
272 {:else if (window.location.search === '')}
273   <DetailsIndex/>
274 {:else}
275   No such place found.
276 {/if}
277
278
279
280 <style>
281   h1 {
282     margin: 10px 0;
283     padding-left: 8px;
284   }
285
286   h1 small :global(a) {
287     font-size: 0.5em;
288     white-space: nowrap;
289   }
290
291   h2 {
292     font-size: 2em;
293     padding-left: 8px;
294     background-color: white;
295   }
296   h3 {
297     font-size: 1.5em;
298     padding-left: 8px;
299   }
300
301   tr.all-columns {
302     background-color: white !important; 
303     border: none;
304   }
305   tr.all-columns td {
306     border-top: none !important;
307     padding-left: 0 !important;
308   }
309
310   .table {
311     width: 100%;
312   }
313   .table td {
314     font-size: 0.9em;
315   }
316   .table>thead>tr>th, .table>tbody>tr>td {
317     padding: 2px 8px;
318   }
319   .name{
320     font-weight: bold;
321   }
322   #map-wrapper {
323     width:100%;
324     min-height: auto;
325     height:300px;
326     border: 1px solid #666;
327   }
328 </style>