]> git.openstreetmap.org Git - nominatim-ui.git/blob - src/pages/DetailsPage.svelte
500c5c30248062c1964789ffb9a63988acecfeb8
[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;
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       base_url = window.location.search;
61     }
62   }
63 </script>
64
65 <Header>
66   <SearchSectionDetails api_request_params={api_request_params}/>
67 </Header>
68
69 <div class="container">
70   {#if aPlace}
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 table-responsive">
85           <tbody>
86             <InfoRow title="Name"><InfoRowList items={aPlace.names} /></InfoRow>
87             <InfoRow title="Type">{aPlace.category}:{aPlace.type}</InfoRow>
88             <InfoRow title="Last Updated">{aPlace.indexed_date}</InfoRow>
89             {#if (isAdminBoundary(aPlace)) }
90               <InfoRow title="Admin Level">{aPlace.admin_level}</InfoRow>
91             {/if}
92             <InfoRow title="Search Rank">{aPlace.rank_search}</InfoRow>
93             <InfoRow title="Address Rank">{aPlace.rank_address} ({formatAddressRank(aPlace.rank_address)})</InfoRow>
94             {#if aPlace.calculated_importance}
95               <InfoRow title="Importance">
96                   {aPlace.calculated_importance}
97                   {#if !aPlace.importance} (estimated){/if}
98               </InfoRow>
99             {/if}
100             <InfoRow title="Coverage">{coverageType(aPlace)}</InfoRow>
101             <InfoRow title="Centre Point (lat,lon)">
102                 {aPlace.centroid.coordinates[1]},{aPlace.centroid.coordinates[0]}
103             </InfoRow>
104             <InfoRow title="OSM">{@html osmLink(aPlace)}</InfoRow>
105             <InfoRow title="Place Id">
106                {aPlace.place_id}
107                (<a href="https://nominatim.org/release-docs/develop/api/Output/#place_id-is-not-a-persistent-id">on this server</a>)
108             </InfoRow>
109             {#if aPlace.calculated_wikipedia}
110               <InfoRow title="Wikipedia Calculated">{@html wikipediaLink(aPlace)}</InfoRow>
111             {/if}
112             <InfoRow title="Computed Postcode">{aPlace.calculated_postcode || ''}</InfoRow>
113             <InfoRow title="Address Tags"><InfoRowList items={aPlace.addresstags} /></InfoRow>
114             <InfoRow title="Extra Tags"><InfoRowList items={aPlace.extratags} /></InfoRow>
115           </tbody>
116         </table>
117       </div>
118       <div class="col-md-6">
119         <div id="map-wrapper">
120           <Map current_result={aPlace} />
121         </div>
122       </div>
123     </div>
124     <div class="row">
125       <div class="col-md-12">
126         <h2>Address</h2>
127          <table id="address" class="table table-striped table-small">
128           <thead>
129             <tr>
130               <th>Local name</th>
131               <th>Type</th>
132               <th>OSM</th>
133               <th>Address rank</th>
134               <th>Admin level</th>
135               <th>Distance</th>
136               <th></th>
137             </tr>
138           </thead>
139           <tbody>
140             {#if aPlace.address}
141               {#each aPlace.address as addressLine}
142                 <DetailsOneRow addressLine={addressLine} bMarkUnusedLines=true bDistanceInMeters=false />
143               {/each}
144             {/if}
145
146             {#if aPlace.linked_places}
147               <tr class="all-columns"><td colspan="6"><h2>Linked Places</h2></td></tr>
148               {#each aPlace.linked_places as addressLine}
149                 <DetailsOneRow addressLine={addressLine} bMarkUnusedLines=true bDistanceInMeters=true />
150               {/each}
151             {/if}
152
153             <tr class="all-columns"><td colspan="6"><h2>Keywords</h2></td></tr>
154             {#if aPlace.keywords}
155               <tr class="all-columns"><td colspan="6"><h3>Name Keywords</h3></td></tr>
156               {#each aPlace.keywords.name as keyword}
157                 <tr>
158                   <td>{formatKeywordToken(keyword.token)}</td>
159                   {#if keyword.id}
160                     <td>word id: {keyword.id}</td>
161                   {/if}
162                 </tr>
163               {/each}
164
165               {#if aPlace.keywords.address}
166                 <tr class="all-columns"><td colspan="6"><h3>Address Keywords</h3></td></tr>
167                 {#each aPlace.keywords.address as keyword}
168                   <tr>
169                     <td>{formatKeywordToken(keyword.token)}</td>
170                     {#if keyword.id}
171                       <td>word id: {keyword.id}</td>
172                     {/if}
173                   </tr>
174                 {/each}
175               {/if}
176             {:else}
177               <tr>
178                 <td>
179                    <a class="btn btn-outline-secondary btn-sm"
180                     href="{base_url}&keywords=1">display keywords</a>
181                 </td>
182               </tr>
183             {/if}
184
185             <tr class="all-columns"><td colspan="6"><h2>Parent Of</h2></td></tr>
186             {#if aPlace.hierarchy}
187
188               {#each Object.keys(aPlace.hierarchy) as type}
189                 <tr class="all-columns"><td colspan="6"><h3>{type}</h3></td></tr>
190                 {#each aPlace.hierarchy[type] as line}
191                   <DetailsOneRow addressLine={line} bDistanceInMeters=true />
192                {/each}
193               {/each}
194
195               {#if Object.keys(aPlace.hierarchy) > 500}
196                 <p>There are more child objects which are not shown.</p>
197               {/if}
198             {:else}
199               <tr>
200                 <td>
201                    <a class="btn btn-outline-secondary btn-sm"
202                     href="{base_url}&hierarchy=1">display child places</a>
203                 </td>
204               </tr>
205             {/if}
206           </tbody>
207         </table>
208       </div>
209     </div>
210   {:else if (window.location.search !== '' && api_request_finished)}
211     No such place found.
212   {/if}
213 </div>
214
215
216
217 <style>
218   h1 {
219     margin: 10px 0;
220     padding-left: 8px;
221   }
222
223   h1 small :global(a) {
224     font-size: 0.5em;
225     white-space: nowrap;
226   }
227
228   h2 {
229     font-size: 2em;
230     padding-left: 8px;
231     background-color: white;
232   }
233   h3 {
234     font-size: 1.5em;
235     padding-left: 8px;
236   }
237
238   tr.all-columns {
239     background-color: white !important; 
240     border: none;
241   }
242   tr.all-columns td {
243     border-top: none !important;
244     padding-left: 0 !important;
245   }
246
247   #map-wrapper {
248     width:100%;
249     min-height: auto;
250     height:300px;
251     border: 1px solid #666;
252   }
253 </style>