From b54a8458d5029b3494165b7430e21b3ae34ecc0c Mon Sep 17 00:00:00 2001 From: hellekin Date: Fri, 22 Jan 2021 05:32:15 +0100 Subject: Upgrade Rails and add StimulusJS support --- app/javascript/controllers/map_controller.js | 59 +++++++++--- app/javascript/controllers/taxonomy_controller.js | 112 ++++++++++++++++++++-- app/javascript/packs/application.js | 6 ++ 3 files changed, 160 insertions(+), 17 deletions(-) (limited to 'app/javascript') diff --git a/app/javascript/controllers/map_controller.js b/app/javascript/controllers/map_controller.js index 30c1361..1704da8 100644 --- a/app/javascript/controllers/map_controller.js +++ b/app/javascript/controllers/map_controller.js @@ -7,32 +7,65 @@ // import { Controller } from "stimulus" -import "leaflet/dist/leaflet.css" -import 'leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility.webpack.css'; // Re-uses images from ~leaflet package -import L from "leaflet" +import 'leaflet/dist/leaflet.css' +// Re-uses images from ~leaflet package +import 'leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility.webpack.css' + +import * as L from 'leaflet' +import 'leaflet-defaulticon-compatibility' +import "leaflet-providers" +import "leaflet.markercluster/dist/leaflet.markercluster.js" + +import 'leaflet-makimarkers' export default class extends Controller { static targets = [ "container" ] initialize() { - + console.log("Map controller initialized.") + this.mapBoxAPIToken = 'pk.eyJ1IjoibmVtYWVsIiwiYSI6ImNrZzBrYjBudTB3bnMyenFmNWtrN3h3bmMifQ.Rkeyhm-9iIQOV7NAMA5LaA' } connect() { - this.map = L.map(this.containerTarget, { - zoomDelta: 0.5, - zoomSnap: 0.5, - }).setView(this._coordinates(), this._zoom()); + L.MakiMarkers.accessToken = this.mapBoxAPIToken - L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', { + var mapbox = L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', { attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery Mapbox', maxZoom: 18, id: 'mapbox/streets-v11', tileSize: 512, zoomOffset: -1, - accessToken: 'pk.eyJ1IjoibmVtYWVsIiwiYSI6ImNrZzBrYjBudTB3bnMyenFmNWtrN3h3bmMifQ.Rkeyhm-9iIQOV7NAMA5LaA' - }).addTo(this.map); + accessToken: this.mapBoxAPIToken + }) + + var stamen_tr = L.tileLayer.provider('Stamen.Toner') + var stamen_wc = L.tileLayer.provider('Stamen.Watercolor') + var tiles_osm = L.tileLayer.provider('OpenStreetMap.Mapnik') + var tiles_sat = L.tileLayer.provider('Esri.WorldImagery') + + const tilemaps = { + 'osm': tiles_osm, + 'mapbox': mapbox, + 'watercolor': stamen_wc, + 'greyscale': stamen_tr, + 'satellite': tiles_sat + } + + const overlays = {} + + this.map = L.map(this.containerTarget, { + zoomDelta: 0.5, + zoomSnap: 0.5, + layers: [ tiles_osm ], + }).setView(this._coordinates(), this._zoom()); + + L.control.layers(tilemaps, overlays).addTo(this.map) + + L.DomEvent.on(window, 'hashchange', this.doSomethingCool); + + // Allow calling the mapController from elsewhere. + this.element[this.identifier] = this } disconnect() { @@ -40,6 +73,10 @@ export default class extends Controller { console.log('Map controller disconnected.') } + doSomethingCool() { + console.log(window.location.hash) + } + _coordinates() { return [this.data.get('latitude'), this.data.get('longitude')]; } diff --git a/app/javascript/controllers/taxonomy_controller.js b/app/javascript/controllers/taxonomy_controller.js index 16d57fa..02b1483 100644 --- a/app/javascript/controllers/taxonomy_controller.js +++ b/app/javascript/controllers/taxonomy_controller.js @@ -9,15 +9,18 @@ import { Controller } from "stimulus" export default class extends Controller { - static targets = [ "category", "deploy", "filter", "section", "toggle" ] + static targets = [ "category", "deploy", "filter", "layers", "section", "toggle" ] initialize() { console.log("Taxonomy controller initialized.") + + this.overlays = {} + this.sectionsOnMap = [] } connect() { console.log("Taxonomy controller connected.") - + this.taxonomy_uuid = this.data.get('uuid') if (this.hasFilterTarget) { let url = `/taxonomies/${this.data.get('uuid')}/filter.js` console.log(`loading url = ${url}`) @@ -29,10 +32,19 @@ export default class extends Controller { } else { console.log("Taxonomy filter is missing") } + + // Access the map + if (this.map = document.querySelector('#map').parentElement.map.map) { + console.log("Taxonomy Controller connected to this.map") + } else { + console.log("Taxonomy Controller could not load map!") + } } + deploy() { console.log(`deploying taxonomy ${this.data.get('uuid')}`); + fetch(`/taxonomies/${this.data.get('uuid')}.js`) .then(response => response.text()) .then(html => this.deployTarget.innerHTML = html); @@ -45,12 +57,100 @@ export default class extends Controller { } category(event) { - let catId = event.target.dataset.taxonomyCategoryId - event.target.classList.toggle('active') + let catId = (event.target.dataset.taxonomyCategoryId || event.target.parentNode.parentNode.dataset.CategoryId) + let secId = event.target.dataset.taxonomySectionId + console.log(`Category: ${catId}/${secId}`) + var active = event.target.classList.toggle('active') + if (active) { + console.log('activated') + } else { + console.log('deactivated') + } + } + + loadCategory(catId) { + document.querySelector(`#category-${catId}`).lastChild.childNodes.forEach(function(li) { + this._mapLayerToggleSection(li.dataset.taxonomySectionId) + }) } section(event) { - let catId = event.target.dataset.taxonomySectionId - event.target.classList.toggle('active') + let secId = event.target.dataset.taxonomySectionId + console.log(`Section: ${secId} to be loaded`) + this._loadMarkers(secId) + this._mapLayerToggleSection(secId) + } + + _sectionIconName(secId) { + const names = { + 215: 'campsite', + 216: 'hospital', + 217: 'landmark', + 218: 'shelter', + 219: 'lodging', + 220: 'playground', + 221: 'residential-community', + 222: 'home', + 223: 'residential-community', + 224: 'residential-community', + 225: 'home' + + } + return names[secId] || 'circle' + } + + _loadMarkers(secId) { + if (this.overlays[secId] == undefined) { + console.log(`loading markers for section ${secId} [${this._sectionIconName(secId)}]...`) + let overlay = L.layerGroup(); + let markers = L.markerClusterGroup(); + let iconName = this._sectionIconName(secId); + + fetch(`/sections/${secId}.json`, { + headers: { 'X-CSRF-Token': this._csrfToken() } + }) + .then(response => response.json()) + .then(data => { + L.geoJSON(data, { + pointToLayer: function (feature, latlng) { + return L.marker(latlng, { + attribution: feature.source, + icon: L.MakiMarkers.icon({ + icon: iconName, + className: feature.className.baseVal, + color: feature.style.fill, + size: 'm' + }) + }); + }, + onEachFeature: (feature, layer) => { + layer.on('click', () => this.onClick(layer)) + layer.addTo(markers) + } + }) + }) + console.log(`cluster counts ${markers.length} markers`) + this.overlays[secId] = markers + } + } + + onClick(layer) { + console.log(layer) + } + + _mapLayerToggleSection(secId) { + if (this.sectionsOnMap.includes(secId)) { + console.log(`removing section ${secId} from map`) + this.map.removeLayer(this.overlays[secId]) + this.sectionsOnMap.pop(secId) + } else { + console.log(`adding section ${secId} to the map`) + this.sectionsOnMap.push(secId) + this.overlays[secId].addTo(this.map) + } + } + + _csrfToken() { + return document.querySelector('[name=csrf-token]').content } } diff --git a/app/javascript/packs/application.js b/app/javascript/packs/application.js index 5e3eec0..a4b51a8 100644 --- a/app/javascript/packs/application.js +++ b/app/javascript/packs/application.js @@ -15,4 +15,10 @@ require("@rails/activestorage").start() // const images = require.context('../images', true) // const imagePath = (name) => images(name, true) +//= require leaflet +//= require leaflet-defaulticon-compatibility +//= require leaflet.markercluster + import "controllers" + +import 'stylesheets/application' -- cgit v1.2.3