xref: /webtrees/resources/views/admin/location-edit.phtml (revision 1792ff1cf1956b41f3e3c853cfb279a803a71ed2)
1<?php
2
3use Fisharebest\Webtrees\I18N;
4use Fisharebest\Webtrees\View;
5
6?>
7
8<?= view('components/breadcrumbs', ['links' => $breadcrumbs]) ?>
9
10<h1><?= $title ?></h1>
11
12<div class="form-group row">
13    <div class="col-sm-10 offset-sm-1">
14        <div id="osm-map" class="wt-ajax-load col-sm-12 osm-admin-map" dir="ltr"></div>
15    </div>
16</div>
17
18<form method="post">
19    <?= csrf_field() ?>
20    <input type="hidden" name="place_id" value="<?= e($place_id) ?>">
21    <input type="hidden" name="place_long" value="<?= e($lng) ?>">
22    <input type="hidden" name="place_lati" value="<?= e($lat) ?>">
23
24    <div class="form-group row">
25        <label class="col-form-label col-sm-1" for="new_place_name">
26            <?= I18N::translate('Place') ?>
27        </label>
28        <div class="col-sm-5">
29            <input type="text" id="new_place_name" name="new_place_name" value="<?= e($location->locationName()) ?>"
30            class="form-control" required>
31        </div>
32        <label class="col-form-label col-sm-1" for="icon">
33            <?= I18N::translate('Flag') ?>
34        </label>
35        <div class="col-sm-4">
36            <div class="input-group" dir="ltr">
37                <input type="text" name="icon" id="icon" class="form-control" value="<?= e($location->icon()) ?>">
38            </div>
39        </div>
40    </div>
41
42    <div class="form-group row">
43        <label class="col-form-label col-sm-1" for="new_place_lati">
44            <?= I18N::translate('Latitude') ?>
45        </label>
46        <div class="col-sm-3">
47            <div class="input-group">
48                <input type="text" dir="ltr" id="new_place_lati" class="editable form-control" name="new_place_lati" required
49                placeholder="<?= I18N::translate('degrees') ?>" value="<?= e($lat) ?>"
50                >
51            </div>
52        </div>
53
54        <label class="col-form-label col-sm-1" for="new_place_long">
55            <?= I18N::translate('Longitude') ?>
56        </label>
57        <div class="col-sm-3">
58            <div class="input-group">
59                <input type="text" dir="ltr" id="new_place_long" class="editable form-control" name="new_place_long" required
60                placeholder="<?= I18N::translate('degrees') ?>" value="<?= e($lng) ?>"
61                >
62            </div>
63        </div>
64        <label class="col-form-label col-sm-1" for="new_zoom_factor">
65            <?= I18N::translate('Zoom') ?>
66        </label>
67        <div class="col-sm-2">
68            <input type="text" id="new_zoom_factor" name="new_zoom_factor" value="<?= e($location->zoom()) ?>"
69            class="form-control" required readonly>
70        </div>
71    </div>
72
73    <div class="form-group row">
74        <div class="col-sm-10 offset-sm-1">
75            <button class="btn btn-primary" type="submit">
76                <?= /* I18N: A button label. */
77                I18N::translate('save')
78                ?>
79            </button>
80            <a class="btn btn-secondary" href="<?= e(route('map-data', ['parent_id' => $parent_id])) ?>">
81                <?= I18N::translate('cancel') ?>
82            </a>
83        </div>
84    </div>
85</form>
86
87<?php View::push('styles') ?>
88<style>
89    .osm-wrapper, .osm-user-map {
90        height: 45vh
91    }
92
93    .osm-admin-map {
94        height: 55vh;
95        border: 1px solid darkGrey
96    }
97
98    .osm-sidebar {
99        height: 100%;
100        overflow-y: auto;
101        padding: 0;
102        margin: 0;
103        border: 0;
104        display: none;
105        font-size: small;
106    }
107
108    .osm-sidebar .gchart {
109        margin: 1px;
110        padding: 2px
111    }
112
113    .osm-sidebar .gchart img {
114        height: 15px;
115        width: 25px
116    }
117
118    .osm-sidebar .border-danger:hover {
119        cursor: not-allowed
120    }
121</style>
122<?php View::endpush() ?>
123
124<?php View::push('javascript') ?>
125<script type="application/javascript">
126    "use strict";
127
128    window.WT_OSM_ADMIN = (function () {
129        let baseData = {
130            minZoom:         2,
131            providerName:    "OpenStreetMap.Mapnik",
132            providerOptions: [],
133            I18N:            {
134                zoomInTitle: <?= json_encode(I18N::translate('Zoom in')) ?>,
135                zoomOutTitle: <?= json_encode(I18N::translate('Zoom out')) ?>,
136                reset: <?= json_encode(I18N::translate('Reset to initial map state')) ?>,
137                noData: <?= json_encode(I18N::translate('No mappable items')) ?>,
138                error: <?= json_encode(I18N::translate('An unknown error occurred')) ?>
139            },
140        };
141
142        let map      = null;
143        let marker   = L.marker([0, 0], {
144            draggable: true,
145        });
146        /**
147         *
148         * @private
149         */
150        let _drawMap = function () {
151            map = L.map("osm-map", {
152                    center:      [0, 0],
153                    minZoom:     baseData.minZoom, // maxZoom set by leaflet-providers.js
154                    zoomControl: false, // remove default
155                },
156            );
157            L.tileLayer.provider(baseData.providerName, baseData.providerOptions).addTo(map);
158            L.control.zoom({ // Add zoom with localised text
159                zoomInTitle:  baseData.I18N.zoomInTitle,
160                zoomOutTitle: baseData.I18N.zoomOutTitle,
161            }).addTo(map);
162
163            // postcss_image_inliner breaks the autodetection of image paths.
164            L.Icon.Default.imagePath = <?= json_encode(asset('css/images/')) ?>;
165
166            marker
167                .on("dragend", function (e) {
168                    let coords = marker.getLatLng();
169                    map.panTo(coords);
170                    _update_Controls({
171                        place:  "",
172                        coords: coords,
173                        zoom:   map.getZoom(),
174                    });
175                })
176                .addTo(map);
177            let searchControl = new window.GeoSearch.GeoSearchControl({
178                provider:        new window.GeoSearch.OpenStreetMapProvider(),
179                retainZoomLevel: true,
180                autoClose:       true,
181                showMarker:      false,
182            });
183
184            map
185                .addControl(searchControl)
186                .on("geosearch/showlocation", function (result) {
187                    let lat   = result.location.y;
188                    let lng   = result.location.x;
189                    let place = result.location.label.split(",", 1);
190
191                    marker.setLatLng([lat, lng]);
192                    map.panTo([lat, lng]);
193
194                    _update_Controls({
195                        place:  place.shift(),
196                        coords: {
197                            "lat": lat,
198                            "lng": lng,
199                        },
200                        zoom:   map.getZoom(),
201                    });
202                })
203                .on("zoomend", function (e) {
204                    $("#new_zoom_factor").val(map.getZoom());
205                    map.panTo(marker.getLatLng());
206                });
207        };
208
209        let data = <?= json_encode($data) ?>;
210
211        /**
212         *
213         * @param newData
214         * @private
215         */
216        let _update_Controls = function (newData) {
217            let placeEl = $("#new_place_name");
218            if (!placeEl.val().length && newData.place.length) {
219                placeEl.val(newData.place);
220            }
221            $("#new_place_lati").val(Number(newData.coords.lat).toFixed(5)); // 5 decimal places (about 1 metre accuracy)
222            $("#new_place_long").val(Number(newData.coords.lng).toFixed(5));
223            $("#new_zoom_factor").val(Number(newData.zoom));
224        };
225
226        $(function () {
227            $(".editable").on("change", function (e) {
228                let lat = $("#new_place_lati").val();
229                let lng = $("#new_place_long").val();
230                marker.setLatLng([lat, lng]);
231                map.panTo([lat, lng]);
232            });
233        });
234
235        /**
236         *
237         * @param id
238         */
239        let initialize = function (id) {
240            _drawMap();
241
242            marker.setLatLng(data.coordinates);
243
244            if (data.coordinates[0] === 0 && data.coordinates[1] === 0) {
245                map.fitWorld();
246            } else {
247                map.setView(data.coordinates, data.zoom);
248            }
249        };
250
251        return {
252            /**
253             *
254             * @param id
255             */
256            drawMap: function (id) {
257                initialize(id);
258            },
259        };
260    })();
261
262    WT_OSM_ADMIN.drawMap(<?= json_encode($ref) ?>);
263</script>
264<?php View::endpush() ?>
265