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