Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
35 changed files
with
1,975 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
8 changes: 8 additions & 0 deletions
8
app/controllers/tasks/collecting_events/search_locality_controller.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
class Tasks::CollectingEvents::SearchLocalityController < ApplicationController | ||
include TaskControllerConfiguration | ||
|
||
# GET | ||
def index | ||
end | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -76,8 +76,8 @@ | |
} | ||
else { | ||
return 'search' | ||
} | ||
} | ||
} | ||
} | ||
} | ||
</script> | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,227 @@ | ||
<template> | ||
<div | ||
:style="{ width: this.width, height: this.height }" | ||
ref="leafletMap" | ||
:id="mapId"/> | ||
</template> | ||
|
||
<script> | ||
import L from 'leaflet' | ||
import LeafletDraw from 'leaflet-draw' | ||
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 { | ||
props: { | ||
width: { | ||
type: String, | ||
default: () => { return '500px' } | ||
}, | ||
height: { | ||
type: String, | ||
default: () => { return '500px' } | ||
}, | ||
zoom: { | ||
type: Number, | ||
default: () => { return 18 } | ||
}, | ||
drawControls: { | ||
type: Boolean, | ||
default: () => { return false } | ||
}, | ||
tilesSelection: { | ||
type: Boolean, | ||
default: true | ||
}, | ||
center: { | ||
type: Array, | ||
default: () => { return [0, 0] } | ||
}, | ||
geojson: { | ||
type: Array, | ||
default: () => { return [] } | ||
} | ||
}, | ||
data () { | ||
return { | ||
mapId: Math.random().toString(36).substring(7), | ||
mapObject: undefined, | ||
drawnItems: undefined, | ||
drawControl: undefined, | ||
tiles: { | ||
osm: L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', { | ||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors', | ||
maxZoom: 18 | ||
}), | ||
google: L.tileLayer('http://www.google.cn/maps/vt?lyrs=s@189&gl=cn&x={x}&y={y}&z={z}', { | ||
attribution: 'Google', | ||
maxZoom: 18 | ||
}) | ||
}, | ||
layers: [] | ||
} | ||
}, | ||
watch: { | ||
geojson (newVal) { | ||
if (newVal.length) { | ||
this.geoJSON(newVal) | ||
} | ||
} | ||
}, | ||
mounted () { | ||
this.mapObject = L.map(this.mapId, { | ||
center: this.center, | ||
zoom: this.zoom | ||
}) | ||
this.drawnItems = new L.FeatureGroup() | ||
this.mapObject.addLayer(this.drawnItems) | ||
this.addDrawControllers() | ||
this.handleEvents() | ||
if (this.geojson.length) { | ||
this.geoJSON(this.geojson) | ||
} | ||
}, | ||
methods: { | ||
antimeridian (elem, anti) { | ||
if (Array.isArray(elem)) { | ||
for (var i = 0; i < elem.length; i++) { | ||
if (Array.isArray(elem[i][0])) { | ||
this.antimeridian(elem[i], anti) | ||
} else { | ||
if (Array.isArray(elem[i])) { | ||
if (elem[i][0] < 0) { | ||
if (anti) { | ||
elem[i][0] = 180 + (180 + elem[i][0]) | ||
} | ||
} else { | ||
if (!anti && (elem[i][0] > 180)) { | ||
elem[i][0] = elem[i][0] - 360 | ||
} | ||
} | ||
} else { | ||
if (elem[0] < 0) { | ||
if (anti) { | ||
elem[0] = 180 + (180 + elem[0]) | ||
} | ||
} else { | ||
if (!anti && (elem[0] > 180)) { | ||
elem[0] = elem[0] - 360 | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
}, | ||
addDrawControllers () { | ||
if (this.tilesSelection) { | ||
L.control.layers({ | ||
'OSM': this.tiles.osm.addTo(this.mapObject), | ||
'Google': this.tiles.google | ||
}, { 'Draw layers': this.drawnItems }, { position: 'topleft', collapsed: false }).addTo(this.mapObject) | ||
} | ||
if (this.drawControls) { | ||
this.mapObject.addControl(new L.Control.Draw({ | ||
edit: { | ||
featureGroup: this.drawnItems, | ||
poly: { | ||
allowIntersection: false | ||
}, | ||
edit: true | ||
}, | ||
draw: { | ||
polygon: { | ||
allowIntersection: false, | ||
showArea: true | ||
} | ||
} | ||
})) | ||
this.mapObject.addControl(this.drawnItems) | ||
} | ||
}, | ||
showCoords(click) { | ||
L.popup().setLatLng(click.latlng) | ||
.setContent(click.latlng.toString()) | ||
.openOn(this.mapObject); | ||
}, | ||
handleEvents () { | ||
let that = this | ||
this.mapObject.on(L.Draw.Event.CREATED, function (e) { | ||
var layer = e.layer; | ||
var popUp = L.popup(); | ||
var geoJsonLayer = layer.toGeoJSON() | ||
if (geoJsonLayer.hasOwnProperty('geometry') && geoJsonLayer.geometry.hasOwnProperty('coordinates')) { | ||
//that.antimeridian(geoJsonLayer.geometry.coordinates, false) | ||
} | ||
if (e.layerType === 'circle') { | ||
geoJsonLayer.properties.radius = layer.getRadius() | ||
} | ||
that.$emit('shapeCreated', layer) | ||
that.$emit('geoJsonLayerCreated', geoJsonLayer) | ||
that.drawnItems.addLayer(layer) | ||
}) | ||
this.mapObject.on('draw:edited', (e) => { | ||
var layers = e.layers | ||
that.$emit('shapesEdited', layers) | ||
that.$emit('geoJsonLayersEdited', that.convertGeoJSONWithPointRadius(layers)) | ||
}) | ||
// this.mapObject.on('mouseover', this.showCoords); | ||
}, | ||
removeLayers () { | ||
this.drawnItems.clearLayers() | ||
}, | ||
convertGeoJSONWithPointRadius (layerArray) { | ||
let arrayLayers = [] | ||
layerArray.eachLayer(layer => { | ||
let layerJson = layer.toGeoJSON() | ||
if (typeof layer.getRadius === 'function') { | ||
layerJson.properties.radius = layer.getRadius() | ||
} | ||
//this.antimeridian(layerJson.geometry.coordinates, false) | ||
arrayLayers.push(layerJson) | ||
}) | ||
return arrayLayers | ||
}, | ||
toGeoJSON () { | ||
return this.convertGeoJSONWithPointRadius(this.drawnItems) | ||
}, | ||
addJsonCircle (layer) { | ||
L.circle(layer.geometry.coordinates.reverse(), layer.properties.radius).addTo(this.drawnItems) | ||
// L.circle(layer.geometry.coordinates, layer.properties.radius).addTo(this.drawnItems) | ||
}, | ||
geoJSON (geojsonFeature) { | ||
if (!Array.isArray(geojsonFeature) || geojsonFeature.length === 0) return | ||
this.removeLayers() | ||
let newGeojson = [] | ||
geojsonFeature.forEach(layer => { // scan feature array and either (i) or (ii) | ||
//this.antimeridian(layer.geometry.coordinates, true) | ||
if (layer.geometry.type === 'Point' && layer.properties.hasOwnProperty('radius')) { | ||
this.addJsonCircle(layer) // (i) add a leaflet circle to the drawnItems data element | ||
} else { | ||
newGeojson.push(layer) // (ii) add this feature to the other array | ||
} | ||
}) | ||
L.geoJSON(newGeojson).getLayers().forEach(layer => { | ||
this.drawnItems.on('mouseover', this.showCoords); | ||
this.drawnItems.addLayer(layer) | ||
}); | ||
this.mapObject.fitBounds(this.drawnItems.getBounds()) | ||
} | ||
} | ||
} | ||
</script> |
17 changes: 17 additions & 0 deletions
17
app/javascript/vue/tasks/collecting_events/search_localities/app.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<template> | ||
<div> | ||
<h1>Search and List Localities</h1> | ||
<collecting-event | ||
@itemid="selectedItem=$event" | ||
/> | ||
</div> | ||
</template> | ||
<script> | ||
import CollectingEvent from './components/collectingEvent.vue' | ||
// TODO: ? (de)/persist lists | ||
export default { | ||
components: { | ||
CollectingEvent, | ||
}, | ||
} | ||
</script> |
49 changes: 49 additions & 0 deletions
49
app/javascript/vue/tasks/collecting_events/search_localities/components/alphabet_buttons.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
<template> | ||
<div> | ||
<table> | ||
<tr | ||
v-for="(row, index) in rows" | ||
:key="index"> | ||
<td | ||
v-for="letter in row" | ||
:key="letter" | ||
:class="{ 'selected-letter': (letter == selected) }" | ||
@click="sendLetter(letter)">{{ letter }} | ||
</td> | ||
</tr> | ||
</table> | ||
</div> | ||
</template> | ||
<script> | ||
export default { | ||
data() { | ||
return { | ||
rows: { | ||
alphabet1: "ABCDEFGHIJKLM".split(""), | ||
alphabet2: "NOPQRSTUVWXYZ".split("") | ||
}, | ||
selected: '' | ||
} | ||
}, | ||
methods: { | ||
sendLetter(letter) { | ||
if(letter == this.selected) return | ||
this.setSelectedLetter(letter) | ||
this.$emit("keypress", letter); | ||
}, | ||
setSelectedLetter(letter) { | ||
this.selected = letter | ||
let urlParams = new URLSearchParams(window.location.search) | ||
urlParams.set('letter', letter) | ||
history.pushState(null, null, `/tasks/collecting_events/search_locality/letter?${urlParams.toString()}`) | ||
} | ||
} | ||
} | ||
</script> | ||
|
||
<style scoped> | ||
.selected-letter { | ||
color: #FFF; | ||
background-color: #E3E8E3; | ||
} | ||
</style> |
Oops, something went wrong.