diff --git a/app/javascript/packs/application.js b/app/javascript/packs/application.js index f3e8bc09..974b869d 100644 --- a/app/javascript/packs/application.js +++ b/app/javascript/packs/application.js @@ -18,6 +18,13 @@ require("trix") require("@rails/actiontext") +import { Application } from 'stimulus' +import { definitionsFromContext } from "stimulus/webpack-helpers" + +const application = Application.start() +const context = require.context("./controllers", true, /\.js$/) +application.load(definitionsFromContext(context)) + import tableDragger from 'table-dragger' import {EditorState} from "prosemirror-state" diff --git a/app/javascript/packs/controllers/geo_controller.js b/app/javascript/packs/controllers/geo_controller.js new file mode 100644 index 00000000..e0c4400e --- /dev/null +++ b/app/javascript/packs/controllers/geo_controller.js @@ -0,0 +1,69 @@ +import 'core-js/stable' +import 'regenerator-runtime/runtime' +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' ] + + 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 map () { + if (!this._map) { + this._map = L.map(this.mapTarget).setView(this.coords, 13) + + L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { + maxZoom: 19, + attribution: '© OpenStreetMap contributors' + }).addTo(this._map) + } + + return this._map + } +} diff --git a/app/views/posts/attributes/_geo.haml b/app/views/posts/attributes/_geo.haml index e3b3ab46..b62a23c8 100644 --- a/app/views/posts/attributes/_geo.haml +++ b/app/views/posts/attributes/_geo.haml @@ -1,11 +1,12 @@ -.row +.row{ data: { controller: 'geo' } } .col .form-group = label_tag "post_#{attribute}_lat", post_label_t(attribute, :lat, post: post) = text_field(*field_name_for('post', attribute, :lat), value: metadata.value['lat'], - **field_options(attribute, metadata)) + **field_options(attribute, metadata), + data: { target: 'geo.lat' }) = render 'posts/attribute_feedback', post: post, attribute: [attribute, :lat], metadata: metadata .col @@ -14,6 +15,9 @@ post_label_t(attribute, :lng, post: post) = text_field(*field_name_for('post', attribute, :lng), value: metadata.value['lng'], - **field_options(attribute, metadata)) + **field_options(attribute, metadata), + data: { target: 'geo.lng' }) = render 'posts/attribute_feedback', post: post, attribute: [attribute, :lng], metadata: metadata + .col-12.mb-3 + %div{ data: { target: 'geo.map' }, style: 'height: 250px' } diff --git a/package.json b/package.json index c7271c34..901760d9 100644 --- a/package.json +++ b/package.json @@ -7,9 +7,11 @@ "commonmark": "^0.29.0", "input-map": "git+https://0xacab.org/sutty/input-map.git", "input-tag": "git+https://0xacab.org/sutty/input-tag.git", + "leaflet": "^1.7.1", "prosemirror-example-setup": "^1.1.2", "prosemirror-markdown": "^1.4.5", "prosemirror-schema-basic": "^1.1.2", + "stimulus": "^1.1.1", "table-dragger": "git+https://0xacab.org/sutty/table-dragger.git", "trix": "git+https://0xacab.org/sutty/trix.git", "zepto": "^1.2.0" diff --git a/yarn.lock b/yarn.lock index 860c3cd0..8af9b502 100644 --- a/yarn.lock +++ b/yarn.lock @@ -746,6 +746,30 @@ webpack-cli "^3.3.2" webpack-sources "^1.3.0" +"@stimulus/core@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@stimulus/core/-/core-1.1.1.tgz#42b0cfe5b73ca492f41de64b77a03980bae92c82" + integrity sha512-PVJv7IpuQx0MVPCBblXc6O2zbCmU8dlxXNH4bC9KK6LsvGaE+PCXXrXQfXUwAsse1/CmRu/iQG7Ov58himjiGg== + dependencies: + "@stimulus/mutation-observers" "^1.1.1" + +"@stimulus/multimap@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@stimulus/multimap/-/multimap-1.1.1.tgz#b95e3fd607345ab36e5d5b55486ee1a12d56b331" + integrity sha512-26R1fI3a8uUj0WlMmta4qcfIQGlagegdP4PTz6lz852q/dXlG6r+uPS/bx+H8GtfyS+OOXVr3SkZ0Zg0iRqRfQ== + +"@stimulus/mutation-observers@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@stimulus/mutation-observers/-/mutation-observers-1.1.1.tgz#0f6c6f081308427fed2a26360dda0c173b79cfc0" + integrity sha512-/zCnnw1KJlWO2mrx0yxYaRFZWMGnDMdOgSnI4hxDLxdWVuL2HMROU8FpHWVBLjKY3T9A+lGkcrmPGDHF3pfS9w== + dependencies: + "@stimulus/multimap" "^1.1.1" + +"@stimulus/webpack-helpers@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@stimulus/webpack-helpers/-/webpack-helpers-1.1.1.tgz#eff60cd4e58b921d1a2764dc5215f5141510f2c2" + integrity sha512-XOkqSw53N9072FLHvpLM25PIwy+ndkSSbnTtjKuyzsv8K5yfkFB2rv68jU1pzqYa9FZLcvZWP4yazC0V38dx9A== + "@types/events@*": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" @@ -3895,6 +3919,11 @@ lcid@^2.0.0: dependencies: invert-kv "^2.0.0" +leaflet@^1.7.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/leaflet/-/leaflet-1.7.1.tgz#10d684916edfe1bf41d688a3b97127c0322a2a19" + integrity sha512-/xwPEBidtg69Q3HlqPdU3DnrXQOvQU/CCHA1tcDQVzOwm91YMYaILjNp7L4Eaw5Z4sOYdbBz6koWyibppd8Zqw== + linkify-it@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.2.0.tgz#e3b54697e78bf915c70a38acd78fd09e0058b1cf" @@ -6623,6 +6652,14 @@ stdout-stream@^1.4.0: dependencies: readable-stream "^2.0.1" +stimulus@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/stimulus/-/stimulus-1.1.1.tgz#53c2fded6849e7b85eed3ed8dd76e33abd74bec5" + integrity sha512-R0mBqKp48YnRDZOxZ8hiOH4Ilph3Yj78CIFTBkCwyHs4iGCpe7xlEdQ7cjIxb+7qVCSxFKgxO+mAQbsNgt/5XQ== + dependencies: + "@stimulus/core" "^1.1.1" + "@stimulus/webpack-helpers" "^1.1.1" + stream-browserify@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b"