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