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