xref: /webtrees/resources/views/admin/location-edit.phtml (revision 47ca61d5ff7f81dd1a16ca5dacebfc3f48cad451)
1d70512abSGreg Roach<?php
2d70512abSGreg Roach
3d70512abSGreg Roachuse Fisharebest\Webtrees\I18N;
4d70512abSGreg Roachuse Fisharebest\Webtrees\View;
5d70512abSGreg Roach
6d70512abSGreg Roach?>
7dd6b2bfcSGreg Roach
8dd6b2bfcSGreg Roach<?= view('components/breadcrumbs', ['links' => $breadcrumbs]) ?>
9dd6b2bfcSGreg Roach
10dd6b2bfcSGreg Roach<h1><?= $title ?></h1>
11dd6b2bfcSGreg Roach
12dd6b2bfcSGreg Roach<div class="form-group row">
13dd6b2bfcSGreg Roach    <div class="col-sm-10 offset-sm-1">
140b4092edSGreg Roach        <div id="osm-map" class="wt-ajax-load col-sm-12 osm-admin-map" dir="ltr"></div>
15dd6b2bfcSGreg Roach    </div>
16dd6b2bfcSGreg Roach</div>
17dd6b2bfcSGreg Roach
18dd6b2bfcSGreg Roach<form method="post">
19dd6b2bfcSGreg Roach    <?= csrf_field() ?>
208af6bbf8SGreg Roach    <input type="hidden" name="place_id" value="<?= e($place_id) ?>">
21dd6b2bfcSGreg Roach
22dd6b2bfcSGreg Roach    <div class="form-group row">
23dd6b2bfcSGreg Roach        <label class="col-form-label col-sm-1" for="new_place_name">
24dd6b2bfcSGreg Roach            <?= I18N::translate('Place') ?>
25dd6b2bfcSGreg Roach        </label>
26dd6b2bfcSGreg Roach        <div class="col-sm-5">
278af6bbf8SGreg Roach            <input type="text" id="new_place_name" name="new_place_name" value="<?= e($location->locationName()) ?>"
28dd6b2bfcSGreg Roach            class="form-control" required>
29dd6b2bfcSGreg Roach        </div>
30dd6b2bfcSGreg Roach        <label class="col-form-label col-sm-1" for="icon">
31dd6b2bfcSGreg Roach            <?= I18N::translate('Flag') ?>
32dd6b2bfcSGreg Roach        </label>
33dd6b2bfcSGreg Roach        <div class="col-sm-4">
34dd6b2bfcSGreg Roach            <div class="input-group" dir="ltr">
35b6c326d8SGreg Roach                <input type="text" name="icon" id="icon" class="form-control" value="<?= e($location->icon()) ?>">
36dd6b2bfcSGreg Roach            </div>
37dd6b2bfcSGreg Roach        </div>
38dd6b2bfcSGreg Roach    </div>
39dd6b2bfcSGreg Roach
40dd6b2bfcSGreg Roach    <div class="form-group row">
4156a34df1SGreg Roach        <label class="col-form-label col-sm-1" for="new_place_lati">
42dd6b2bfcSGreg Roach            <?= I18N::translate('Latitude') ?>
43dd6b2bfcSGreg Roach        </label>
44dd6b2bfcSGreg Roach        <div class="col-sm-3">
45dd6b2bfcSGreg Roach            <div class="input-group">
460e7a2d23SGreg Roach                <input type="text" dir="ltr" id="new_place_lati" class="editable form-control" name="new_place_lati" required
478af6bbf8SGreg Roach                placeholder="<?= I18N::translate('degrees') ?>" value="<?= e($lat) ?>"
48dd6b2bfcSGreg Roach                >
49dd6b2bfcSGreg Roach            </div>
50dd6b2bfcSGreg Roach        </div>
51dd6b2bfcSGreg Roach
5256a34df1SGreg Roach        <label class="col-form-label col-sm-1" for="new_place_long">
53dd6b2bfcSGreg Roach            <?= I18N::translate('Longitude') ?>
54dd6b2bfcSGreg Roach        </label>
55dd6b2bfcSGreg Roach        <div class="col-sm-3">
56dd6b2bfcSGreg Roach            <div class="input-group">
570e7a2d23SGreg Roach                <input type="text" dir="ltr" id="new_place_long" class="editable form-control" name="new_place_long" required
588af6bbf8SGreg Roach                placeholder="<?= I18N::translate('degrees') ?>" value="<?= e($lng) ?>"
59dd6b2bfcSGreg Roach                >
60dd6b2bfcSGreg Roach            </div>
61dd6b2bfcSGreg Roach        </div>
62dd6b2bfcSGreg Roach        <label class="col-form-label col-sm-1" for="new_zoom_factor">
63dd6b2bfcSGreg Roach            <?= I18N::translate('Zoom') ?>
64dd6b2bfcSGreg Roach        </label>
65dd6b2bfcSGreg Roach        <div class="col-sm-2">
668af6bbf8SGreg Roach            <input type="text" id="new_zoom_factor" name="new_zoom_factor" value="<?= e($location->zoom()) ?>"
67dd6b2bfcSGreg Roach            class="form-control" required readonly>
68dd6b2bfcSGreg Roach        </div>
69dd6b2bfcSGreg Roach    </div>
70dd6b2bfcSGreg Roach
71dd6b2bfcSGreg Roach    <div class="form-group row">
72dd6b2bfcSGreg Roach        <div class="col-sm-10 offset-sm-1">
73dd6b2bfcSGreg Roach            <button class="btn btn-primary" type="submit">
74dd6b2bfcSGreg Roach                <?= /* I18N: A button label. */
75dd6b2bfcSGreg Roach                I18N::translate('save')
76dd6b2bfcSGreg Roach                ?>
77dd6b2bfcSGreg Roach            </button>
78dd6b2bfcSGreg Roach            <a class="btn btn-secondary" href="<?= e(route('map-data', ['parent_id' => $parent_id])) ?>">
79dd6b2bfcSGreg Roach                <?= I18N::translate('cancel') ?>
80dd6b2bfcSGreg Roach            </a>
81dd6b2bfcSGreg Roach        </div>
82dd6b2bfcSGreg Roach    </div>
83dd6b2bfcSGreg Roach</form>
84dd6b2bfcSGreg Roach
85dd6b2bfcSGreg Roach<?php View::push('styles') ?>
86dd6b2bfcSGreg Roach<style>
87dd6b2bfcSGreg Roach    .osm-admin-map {
88dd6b2bfcSGreg Roach        height: 55vh;
89dd6b2bfcSGreg Roach        border: 1px solid darkGrey
90dd6b2bfcSGreg Roach    }
91dd6b2bfcSGreg Roach</style>
92dd6b2bfcSGreg Roach<?php View::endpush() ?>
93dd6b2bfcSGreg Roach
94dd6b2bfcSGreg Roach<?php View::push('javascript') ?>
9574b9ba3fSGreg Roach<script>
96caa53803SDavid Drury'use strict';
97dd6b2bfcSGreg Roach
98dd6b2bfcSGreg Roachwindow.WT_OSM_ADMIN = (function () {
99caa53803SDavid Drury  const minZoom = 2;
1002cbb0620SDavid Drury
1012cbb0620SDavid Drury  let provider = <?= json_encode($provider) ?>;
102caa53803SDavid Drury  let data = <?= json_encode($data) ?>;
103dd6b2bfcSGreg Roach  let map = null;
104caa53803SDavid Drury  let add_place = <?= json_encode($place_id === 0) ?>;
105caa53803SDavid Drury
106caa53803SDavid Drury  // map components
107dd6b2bfcSGreg Roach
10875e7614aSGreg Roach  // postcss_image_inliner breaks the autodetection of image paths.
10975e7614aSGreg Roach  L.Icon.Default.imagePath = <?= json_encode(asset('css/images/')) ?>;
11075e7614aSGreg Roach
111caa53803SDavid Drury  // draggable marker
112caa53803SDavid Drury  let marker = L.marker(data.coordinates, {
113caa53803SDavid Drury    draggable: true,
114caa53803SDavid Drury  })
115caa53803SDavid Drury    .on('dragend', function (e) {
116dd6b2bfcSGreg Roach      let coords = marker.getLatLng();
117dd6b2bfcSGreg Roach      map.panTo(coords);
118dd6b2bfcSGreg Roach      _update_Controls({
119caa53803SDavid Drury        place:  '',
120dd6b2bfcSGreg Roach        coords: coords,
121dd6b2bfcSGreg Roach        zoom:   map.getZoom(),
122dd6b2bfcSGreg Roach      });
123dd6b2bfcSGreg Roach    });
124dd6b2bfcSGreg Roach
125caa53803SDavid Drury  //reset map to initial state
126caa53803SDavid Drury  let resetControl = L.Control.extend({
127caa53803SDavid Drury    options: {
128caa53803SDavid Drury      position: 'topleft'
129caa53803SDavid Drury    },
130caa53803SDavid Drury    onAdd:   function (map) {
131caa53803SDavid Drury      let container = L.DomUtil.create('div', 'leaflet-bar leaflet-control leaflet-control-custom');
132caa53803SDavid Drury      container.onclick = function () {
133caa53803SDavid Drury        map.setView(data.coordinates, data.zoom);
134caa53803SDavid Drury        marker.setLatLng(data.coordinates);
135caa53803SDavid Drury        $('form').trigger('reset');
136caa53803SDavid Drury        return false;
137caa53803SDavid Drury      };
138*47ca61d5SGreg Roach      let reset = <?= json_encode(I18N::translate('Reset to initial map state')) ?>;
139caa53803SDavid Drury      let anchor = L.DomUtil.create('a', 'leaflet-control-reset', container);
140caa53803SDavid Drury      anchor.setAttribute('aria-label', reset);
141caa53803SDavid Drury      anchor.href = '#';
142caa53803SDavid Drury      anchor.title = reset;
143caa53803SDavid Drury      anchor.role = 'button';
144caa53803SDavid Drury      let image = L.DomUtil.create('i', 'fas fa-redo', anchor);
145caa53803SDavid Drury      image.alt = reset;
146dd6b2bfcSGreg Roach
147caa53803SDavid Drury      return container;
148caa53803SDavid Drury    }
149caa53803SDavid Drury  });
150dd6b2bfcSGreg Roach
151caa53803SDavid Drury  // zoom control with localised text
152caa53803SDavid Drury  let zoomCtl = new L.control.zoom({
153caa53803SDavid Drury    zoomInTitle:  <?= json_encode(I18N::translate('Zoom in')) ?>,
154caa53803SDavid Drury    zoomOutTitle: <?= json_encode(I18N::translate('Zoom out')) ?>,
155caa53803SDavid Drury  });
156caa53803SDavid Drury
157caa53803SDavid Drury  // Geocoder (place lookup)
158caa53803SDavid Drury  let geocoder = new L.Control.geocoder({
159caa53803SDavid Drury    defaultMarkGeocode: false,
160caa53803SDavid Drury    showResultIcons:    true,
161caa53803SDavid Drury    query:              '<?= e($location->locationName()) ?>',
162caa53803SDavid Drury    placeholder: <?= json_encode(I18N::translate('Place')) ?>,
163caa53803SDavid Drury    errorMessage: <?= json_encode(I18N::translate('Nothing found.')) ?>,
164*47ca61d5SGreg Roach    iconLabel: <?= json_encode(I18N::translate('Search')) ?>
165caa53803SDavid Drury  })
166caa53803SDavid Drury    .on('markgeocode', function (result) {
167caa53803SDavid Drury      let coords = result.geocode.center;
168caa53803SDavid Drury      let place = result.geocode.name.split(',', 1);
169caa53803SDavid Drury      marker.setLatLng(coords);
170caa53803SDavid Drury      map.panTo(coords);
171dd6b2bfcSGreg Roach      _update_Controls({
172dd6b2bfcSGreg Roach        place:  place.shift(),
173caa53803SDavid Drury        coords: coords,
174dd6b2bfcSGreg Roach        zoom:   map.getZoom(),
175dd6b2bfcSGreg Roach      });
176dd6b2bfcSGreg Roach    });
177dd6b2bfcSGreg Roach
178dd6b2bfcSGreg Roach  /**
179dd6b2bfcSGreg Roach   *
180dd6b2bfcSGreg Roach   * @param newData
181dd6b2bfcSGreg Roach   * @private
182dd6b2bfcSGreg Roach   */
183dd6b2bfcSGreg Roach  let _update_Controls = function (newData) {
184dd6b2bfcSGreg Roach
185caa53803SDavid Drury    if (add_place) {
186caa53803SDavid Drury      $('#new_place_name').val(newData.place);
187caa53803SDavid Drury    }
188caa53803SDavid Drury    $('#new_place_lati').val(Number(newData.coords.lat).toFixed(5)); // 5 decimal places (about 1 metre accuracy)
189caa53803SDavid Drury    $('#new_place_long').val(Number(newData.coords.lng).toFixed(5));
190caa53803SDavid Drury    $('#new_zoom_factor').val(Number(newData.zoom));
191*47ca61d5SGreg Roach  };
192caa53803SDavid Drury
193caa53803SDavid Drury  /**
194caa53803SDavid Drury   *
195caa53803SDavid Drury   * @private
196caa53803SDavid Drury   */
197dd6b2bfcSGreg Roach  $(function () {
198caa53803SDavid Drury    // geocoder button tooltip
199caa53803SDavid Drury    $('.leaflet-control-geocoder-icon')
200*47ca61d5SGreg Roach      .attr('title', <?= json_encode(I18N::translate('Search')) ?>);
201caa53803SDavid Drury
202caa53803SDavid Drury    $('.editable').on('change', function (e) {
203caa53803SDavid Drury      let lat = $('#new_place_lati').val();
204caa53803SDavid Drury      let lng = $('#new_place_long').val();
205dd6b2bfcSGreg Roach      marker.setLatLng([lat, lng]);
206dd6b2bfcSGreg Roach      map.panTo([lat, lng]);
207dd6b2bfcSGreg Roach    });
208dd6b2bfcSGreg Roach  });
209dd6b2bfcSGreg Roach
210caa53803SDavid Drury  // Create the map with all controls and layers
211caa53803SDavid Drury  map = L.map('osm-map', {
212caa53803SDavid Drury    minZoom:     minZoom, // maxZoom set by leaflet-providers.js
213caa53803SDavid Drury    zoomControl: false,   // remove default
214caa53803SDavid Drury  })
215caa53803SDavid Drury    .addControl(new resetControl())
216caa53803SDavid Drury    .addControl(zoomCtl)
217caa53803SDavid Drury    .addControl(geocoder)
218caa53803SDavid Drury    .addLayer(marker)
219caa53803SDavid Drury    .addLayer(L.tileLayer(provider.url, provider.options))
220caa53803SDavid Drury    .setView(data.coordinates, data.zoom)
221caa53803SDavid Drury    .on('zoomend', function (e) {
222caa53803SDavid Drury      $('#new_zoom_factor').val(map.getZoom());
223caa53803SDavid Drury      map.panTo(marker.getLatLng());
224caa53803SDavid Drury    });
225dd6b2bfcSGreg Roach
226caa53803SDavid Drury  return 'Leaflet map interface for webtrees-2';
227dd6b2bfcSGreg Roach})();
228dd6b2bfcSGreg Roach</script>
229dd6b2bfcSGreg Roach<?php View::endpush() ?>
230