diff --git a/app/javascript/controllers/non_geo_controller.js b/app/javascript/controllers/non_geo_controller.js new file mode 100644 index 00000000..1c618fcb --- /dev/null +++ b/app/javascript/controllers/non_geo_controller.js @@ -0,0 +1,81 @@ +import { Controller } from 'stimulus' + +require("leaflet/dist/leaflet.css") +import L from 'leaflet' +delete L.Icon.Default.prototype._getIconUrl + +L.Icon.Default.mergeOptions({ + iconRetinaUrl: require('leaflet/dist/images/marker-icon-2x.png'), + iconUrl: require('leaflet/dist/images/marker-icon.png'), + shadowUrl: require('leaflet/dist/images/marker-shadow.png'), +}) + +export default class extends Controller { + static targets = [ 'lat', 'lng', 'map', 'overlay' ] + + async connect () { + this.marker() + + this.latTarget.addEventListener('change', event => this.marker()) + this.lngTarget.addEventListener('change', event => this.marker()) + window.addEventListener('resize', event => this.map.invalidateSize()) + + this.map.on('click', event => { + this.latTarget.value = event.latlng.lat + this.lngTarget.value = event.latlng.lng + + this.latTarget.dispatchEvent(new Event('change')) + }) + } + + marker () { + if (this._marker) this.map.removeLayer(this._marker) + + this._marker = L.marker(this.coords).addTo(this.map) + + return this._marker + } + + get lat () { + const lat = parseFloat(this.latTarget.value) + + return isNaN(lat) ? 0 : lat + } + + get lng () { + const lng = parseFloat(this.lngTarget.value) + + return isNaN(lng) ? 0 : lng + } + + get coords () { + return [this.lat, this.lng] + } + + get bounds () { + return [ + [0, 0], + [ + this.svgOverlay.viewBox.baseVal.height, + this.svgOverlay.viewBox.baseVal.width, + ] + ]; + } + + get map () { + if (!this._map) { + this._map = L.map(this.mapTarget, { + minZoom: 0, + maxZoom: 5 + }).setView(this.coords, 0); + + this._layer = L.tileLayer(`${this.element.dataset.site}public/map/{z}/{y}/{x}.png`, { + minNativeZoom: 0, + maxNativeZoom: 5, + noWrap: true + }).addTo(this._map); + } + + return this._map + } +} diff --git a/app/models/metadata_non_geo.rb b/app/models/metadata_non_geo.rb new file mode 100644 index 00000000..6aec8461 --- /dev/null +++ b/app/models/metadata_non_geo.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +class MetadataNonGeo < MetadataGeo; end diff --git a/app/views/posts/attribute_ro/_non_geo.haml b/app/views/posts/attribute_ro/_non_geo.haml new file mode 100644 index 00000000..75f8d2ef --- /dev/null +++ b/app/views/posts/attribute_ro/_non_geo.haml @@ -0,0 +1,6 @@ +- lat = metadata.value['lat'] +- lng = metadata.value['lng'] +%tr{ id: attribute } + %th= post_label_t(attribute, post: post) + %td + = "#{lat},#{lng}" diff --git a/app/views/posts/attributes/_geo.haml b/app/views/posts/attributes/_geo.haml index d048565e..dee4707e 100644 --- a/app/views/posts/attributes/_geo.haml +++ b/app/views/posts/attributes/_geo.haml @@ -1,4 +1,8 @@ .row{ data: { controller: 'geo' } } + .col-12.mb-3 + %p.mb-0= post_label_t(attribute, post: post) + = render 'posts/attribute_feedback', + post: post, attribute: attribute, metadata: metadata .col .form-group = label_tag "#{base}_#{attribute}_lat", diff --git a/app/views/posts/attributes/_non_geo.haml b/app/views/posts/attributes/_non_geo.haml new file mode 100644 index 00000000..3f6a75a6 --- /dev/null +++ b/app/views/posts/attributes/_non_geo.haml @@ -0,0 +1,29 @@ +.row{ data: { controller: 'non-geo', site: site.url } } + .d-none{ hidden: true, data: { target: 'non-geo.overlay' }} + .col-12.mb-3 + %p.mb-0= post_label_t(attribute, post: post) + %p= post_label_t(attribute, post: post) + = render 'posts/attribute_feedback', + post: post, attribute: attribute, metadata: metadata + .col + .form-group + = label_tag "#{base}_#{attribute}_lat", + post_label_t(attribute, :lat, post: post) + = text_field(*field_name_for(base, attribute, :lat), + value: metadata.value['lat'], + **field_options(attribute, metadata), + data: { target: 'non-geo.lat' }) + = render 'posts/attribute_feedback', + post: post, attribute: [attribute, :lat], metadata: metadata + .col + .form-group + = label_tag "#{base}_#{attribute}_lng", + post_label_t(attribute, :lng, post: post) + = text_field(*field_name_for(base, attribute, :lng), + value: metadata.value['lng'], + **field_options(attribute, metadata), + data: { target: 'non-geo.lng' }) + = render 'posts/attribute_feedback', + post: post, attribute: [attribute, :lng], metadata: metadata + .col-12.mb-3 + %div{ data: { target: 'non-geo.map' }, style: 'height: 250px' }