Merge pull request #1295 from umap-project/load-all-before-download
Make sure we load all data before downloading it
This commit is contained in:
commit
f57ef51bf6
5 changed files with 284 additions and 21 deletions
|
@ -986,7 +986,8 @@ L.U.Map.include({
|
||||||
const status = this.permissions.getShareStatusDisplay()
|
const status = this.permissions.getShareStatusDisplay()
|
||||||
name.textContent = this.getDisplayName()
|
name.textContent = this.getDisplayName()
|
||||||
// status is not set until map is saved once
|
// status is not set until map is saved once
|
||||||
if (status) share_status.textContent = L._('Visibility: {status}', {
|
if (status)
|
||||||
|
share_status.textContent = L._('Visibility: {status}', {
|
||||||
status: status,
|
status: status,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1129,19 +1130,38 @@ L.U.Map.include({
|
||||||
toggleCaveat()
|
toggleCaveat()
|
||||||
const download = L.DomUtil.create('a', 'button', container)
|
const download = L.DomUtil.create('a', 'button', container)
|
||||||
download.textContent = L._('Download data')
|
download.textContent = L._('Download data')
|
||||||
L.DomEvent.on(download, 'click', () => this.download(typeInput.value), this)
|
L.DomEvent.on(
|
||||||
|
download,
|
||||||
|
'click',
|
||||||
|
() => {
|
||||||
|
if (typeInput.value === 'umap') this.fullDownload()
|
||||||
|
else this.download(typeInput.value)
|
||||||
|
}
|
||||||
|
)
|
||||||
this.ui.openPanel({ data: { html: container } })
|
this.ui.openPanel({ data: { html: container } })
|
||||||
},
|
},
|
||||||
|
|
||||||
download: function (mode) {
|
fullDownload: function () {
|
||||||
|
// Make sure all data is loaded before downloading
|
||||||
|
this.once('dataloaded', () => this.download())
|
||||||
|
this.loadDatalayers(true) // Force load
|
||||||
|
},
|
||||||
|
|
||||||
|
format: function (mode) {
|
||||||
const type = this.EXPORT_TYPES[mode || 'umap']
|
const type = this.EXPORT_TYPES[mode || 'umap']
|
||||||
const content = type.formatter(this)
|
const content = type.formatter(this)
|
||||||
let name = this.options.name || 'data'
|
let name = this.options.name || 'data'
|
||||||
name = name.replace(/[^a-z0-9]/gi, '_').toLowerCase()
|
name = name.replace(/[^a-z0-9]/gi, '_').toLowerCase()
|
||||||
|
const filename = name + type.ext
|
||||||
|
return {content, filetype: type.filetype, filename}
|
||||||
|
},
|
||||||
|
|
||||||
|
download: function (mode) {
|
||||||
|
const {content, filetype, filename} = this.format(mode)
|
||||||
|
const blob = new Blob([content], { type: filetype })
|
||||||
window.URL = window.URL || window.webkitURL
|
window.URL = window.URL || window.webkitURL
|
||||||
const blob = new Blob([content], { type: type.filetype })
|
|
||||||
const el = document.createElement('a')
|
const el = document.createElement('a')
|
||||||
el.download = name + type.ext
|
el.download = filename
|
||||||
el.href = window.URL.createObjectURL(blob)
|
el.href = window.URL.createObjectURL(blob)
|
||||||
el.style.display = 'none'
|
el.style.display = 'none'
|
||||||
document.body.appendChild(el)
|
document.body.appendChild(el)
|
||||||
|
|
|
@ -379,33 +379,41 @@ L.U.Map.include({
|
||||||
},
|
},
|
||||||
|
|
||||||
initDatalayers: function () {
|
initDatalayers: function () {
|
||||||
let toload = (dataToload = seen = this.options.datalayers.length)
|
for (let j = 0; j < this.options.datalayers.length; j++) {
|
||||||
const self = this
|
this.createDataLayer(this.options.datalayers[j])
|
||||||
|
}
|
||||||
|
this.loadDatalayers()
|
||||||
|
},
|
||||||
|
|
||||||
|
loadDatalayers: function (force) {
|
||||||
|
force = force || L.Util.queryString('download') // In case we are in download mode, let's go strait to loading all data
|
||||||
|
let toload = (dataToload = total = this.datalayers_index.length)
|
||||||
let datalayer
|
let datalayer
|
||||||
const loaded = () => {
|
const loaded = () => {
|
||||||
self.datalayersLoaded = true
|
this.datalayersLoaded = true
|
||||||
self.fire('datalayersloaded')
|
this.fire('datalayersloaded')
|
||||||
}
|
}
|
||||||
const decrementToLoad = () => {
|
const decrementToLoad = () => {
|
||||||
toload--
|
toload--
|
||||||
if (toload === 0) loaded()
|
if (toload === 0) loaded()
|
||||||
}
|
}
|
||||||
const dataLoaded = () => {
|
const dataLoaded = () => {
|
||||||
self.dataLoaded = true
|
this.dataLoaded = true
|
||||||
self.fire('dataloaded')
|
this.fire('dataloaded')
|
||||||
}
|
}
|
||||||
const decrementDataToLoad = () => {
|
const decrementDataToLoad = () => {
|
||||||
dataToload--
|
dataToload--
|
||||||
if (dataToload === 0) dataLoaded()
|
if (dataToload === 0) dataLoaded()
|
||||||
}
|
}
|
||||||
for (let j = 0; j < this.options.datalayers.length; j++) {
|
this.eachDataLayer(function (datalayer) {
|
||||||
datalayer = this.createDataLayer(this.options.datalayers[j])
|
if (force && !datalayer.hasDataLoaded()) datalayer.show()
|
||||||
if (datalayer.displayedOnLoad()) datalayer.onceLoaded(decrementToLoad)
|
if (datalayer.displayedOnLoad() || force) datalayer.onceLoaded(decrementToLoad)
|
||||||
else decrementToLoad()
|
else decrementToLoad()
|
||||||
if (datalayer.displayedOnLoad()) datalayer.onceDataLoaded(decrementDataToLoad)
|
if (datalayer.displayedOnLoad() || force)
|
||||||
|
datalayer.onceDataLoaded(decrementDataToLoad)
|
||||||
else decrementDataToLoad()
|
else decrementDataToLoad()
|
||||||
}
|
})
|
||||||
if (seen === 0) {
|
if (total === 0) {
|
||||||
// no datalayer
|
// no datalayer
|
||||||
loaded()
|
loaded()
|
||||||
dataLoaded()
|
dataLoaded()
|
||||||
|
@ -1128,9 +1136,11 @@ L.U.Map.include({
|
||||||
},
|
},
|
||||||
|
|
||||||
serialize: function () {
|
serialize: function () {
|
||||||
|
// Do not use local path during unit tests
|
||||||
|
const uri = window.location.protocol === 'file:' ? null : window.location.href
|
||||||
const umapfile = {
|
const umapfile = {
|
||||||
type: 'umap',
|
type: 'umap',
|
||||||
uri: window.location.href,
|
uri: uri,
|
||||||
properties: this.exportOptions(),
|
properties: this.exportOptions(),
|
||||||
geometry: this.geometry(),
|
geometry: this.geometry(),
|
||||||
layers: [],
|
layers: [],
|
||||||
|
|
230
umap/static/umap/test/Map.Export.js
Normal file
230
umap/static/umap/test/Map.Export.js
Normal file
|
@ -0,0 +1,230 @@
|
||||||
|
describe('L.U.Map.Export', function () {
|
||||||
|
before(function () {
|
||||||
|
this.server = sinon.fakeServer.create()
|
||||||
|
this.server.respondWith(
|
||||||
|
/\/datalayer\/62\/\?.*/,
|
||||||
|
JSON.stringify(RESPONSES.datalayer62_GET)
|
||||||
|
)
|
||||||
|
this.options = {
|
||||||
|
umap_id: 99,
|
||||||
|
}
|
||||||
|
this.map = initMap({ umap_id: 99 })
|
||||||
|
this.server.respond()
|
||||||
|
this.datalayer = this.map.getDataLayerByUmapId(62)
|
||||||
|
})
|
||||||
|
after(function () {
|
||||||
|
this.server.restore()
|
||||||
|
clickCancel()
|
||||||
|
resetMap()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('#formatters()', function () {
|
||||||
|
it('should export to geojson', function () {
|
||||||
|
const { content, filetype, filename } = this.map.format('geojson')
|
||||||
|
assert.equal(filetype, 'application/json')
|
||||||
|
assert.equal(filename, 'name_of_the_map.geojson')
|
||||||
|
assert.deepEqual(JSON.parse(content), {
|
||||||
|
type: 'FeatureCollection',
|
||||||
|
features: [
|
||||||
|
{
|
||||||
|
type: 'Feature',
|
||||||
|
properties: {
|
||||||
|
name: 'name poly',
|
||||||
|
},
|
||||||
|
geometry: {
|
||||||
|
type: 'Polygon',
|
||||||
|
coordinates: [
|
||||||
|
[
|
||||||
|
[11.25, 53.585984],
|
||||||
|
[10.151367, 52.975108],
|
||||||
|
[12.689209, 52.167194],
|
||||||
|
[14.084473, 53.199452],
|
||||||
|
[12.634277, 53.618579],
|
||||||
|
[11.25, 53.585984],
|
||||||
|
[11.25, 53.585984],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'Feature',
|
||||||
|
properties: {
|
||||||
|
_umap_options: {
|
||||||
|
color: 'OliveDrab',
|
||||||
|
},
|
||||||
|
name: 'test',
|
||||||
|
},
|
||||||
|
geometry: {
|
||||||
|
type: 'Point',
|
||||||
|
coordinates: [-0.274658, 52.57635],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'Feature',
|
||||||
|
properties: {
|
||||||
|
_umap_options: {
|
||||||
|
fill: false,
|
||||||
|
},
|
||||||
|
name: 'test',
|
||||||
|
},
|
||||||
|
geometry: {
|
||||||
|
type: 'LineString',
|
||||||
|
coordinates: [
|
||||||
|
[-0.571289, 54.476422],
|
||||||
|
[0.439453, 54.610255],
|
||||||
|
[1.724854, 53.448807],
|
||||||
|
[4.163818, 53.988395],
|
||||||
|
[5.306396, 53.533778],
|
||||||
|
[6.591797, 53.709714],
|
||||||
|
[7.042236, 53.350551],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should export to gpx', function () {
|
||||||
|
const { content, filetype, filename } = this.map.format('gpx')
|
||||||
|
assert.equal(filetype, 'application/gpx+xml')
|
||||||
|
assert.equal(filename, 'name_of_the_map.gpx')
|
||||||
|
const expected =
|
||||||
|
'<gpx xmlns="http://www.topografix.com/GPX/1/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd" version="1.1" creator="togpx"><metadata/><wpt lat="52.57635" lon="-0.274658"><name>test</name><desc>name=test</desc></wpt><trk><name>name poly</name><desc>name=name poly</desc><trkseg><trkpt lat="53.585984" lon="11.25"/><trkpt lat="52.975108" lon="10.151367"/><trkpt lat="52.167194" lon="12.689209"/><trkpt lat="53.199452" lon="14.084473"/><trkpt lat="53.618579" lon="12.634277"/><trkpt lat="53.585984" lon="11.25"/><trkpt lat="53.585984" lon="11.25"/></trkseg></trk><trk><name>test</name><desc>name=test</desc><trkseg><trkpt lat="54.476422" lon="-0.571289"/><trkpt lat="54.610255" lon="0.439453"/><trkpt lat="53.448807" lon="1.724854"/><trkpt lat="53.988395" lon="4.163818"/><trkpt lat="53.533778" lon="5.306396"/><trkpt lat="53.709714" lon="6.591797"/><trkpt lat="53.350551" lon="7.042236"/></trkseg></trk></gpx>'
|
||||||
|
assert.equal(content, expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should export to gpx', function () {
|
||||||
|
const { content, filetype, filename } = this.map.format('kml')
|
||||||
|
assert.equal(filetype, 'application/vnd.google-earth.kml+xml')
|
||||||
|
assert.equal(filename, 'name_of_the_map.kml')
|
||||||
|
const expected =
|
||||||
|
'<?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://www.opengis.net/kml/2.2"><Document><Placemark><name>name poly</name><ExtendedData><Data name="name"><value>name poly</value></Data></ExtendedData><Polygon><outerBoundaryIs><LinearRing><coordinates>11.25,53.585984 10.151367,52.975108 12.689209,52.167194 14.084473,53.199452 12.634277,53.618579 11.25,53.585984 11.25,53.585984</coordinates></LinearRing></outerBoundaryIs></Polygon></Placemark><Placemark><name>test</name><ExtendedData><Data name="_umap_options"><value>[object Object]</value></Data><Data name="name"><value>test</value></Data></ExtendedData><Point><coordinates>-0.274658,52.57635</coordinates></Point></Placemark><Placemark><name>test</name><ExtendedData><Data name="_umap_options"><value>[object Object]</value></Data><Data name="name"><value>test</value></Data></ExtendedData><LineString><coordinates>-0.571289,54.476422 0.439453,54.610255 1.724854,53.448807 4.163818,53.988395 5.306396,53.533778 6.591797,53.709714 7.042236,53.350551</coordinates></LineString></Placemark></Document></kml>'
|
||||||
|
assert.equal(content, expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should export to umap', function () {
|
||||||
|
const { content, filetype, filename } = this.map.format('umap')
|
||||||
|
assert.equal(filetype, 'application/json')
|
||||||
|
assert.equal(filename, 'name_of_the_map.umap')
|
||||||
|
const expected = {
|
||||||
|
type: 'umap',
|
||||||
|
uri: null,
|
||||||
|
properties: {
|
||||||
|
easing: false,
|
||||||
|
embedControl: true,
|
||||||
|
fullscreenControl: true,
|
||||||
|
searchControl: true,
|
||||||
|
datalayersControl: true,
|
||||||
|
zoomControl: true,
|
||||||
|
permanentCreditBackground: true,
|
||||||
|
slideshow: {},
|
||||||
|
captionMenus: true,
|
||||||
|
captionBar: false,
|
||||||
|
limitBounds: {},
|
||||||
|
overlay: null,
|
||||||
|
tilelayer: {
|
||||||
|
attribution: 'HOT and friends',
|
||||||
|
name: 'HOT OSM-fr server',
|
||||||
|
url_template: 'http://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png',
|
||||||
|
rank: 99,
|
||||||
|
minZoom: 0,
|
||||||
|
maxZoom: 20,
|
||||||
|
id: 2,
|
||||||
|
},
|
||||||
|
licence: '',
|
||||||
|
description: 'The description of the map',
|
||||||
|
name: 'name of the map',
|
||||||
|
displayPopupFooter: false,
|
||||||
|
miniMap: false,
|
||||||
|
moreControl: true,
|
||||||
|
scaleControl: true,
|
||||||
|
scrollWheelZoom: true,
|
||||||
|
zoom: 6,
|
||||||
|
},
|
||||||
|
geometry: {
|
||||||
|
type: 'Point',
|
||||||
|
coordinates: [5.0592041015625, 52.05924589011585],
|
||||||
|
},
|
||||||
|
layers: [
|
||||||
|
{
|
||||||
|
type: 'FeatureCollection',
|
||||||
|
features: [
|
||||||
|
{
|
||||||
|
type: 'Feature',
|
||||||
|
properties: {
|
||||||
|
name: 'name poly',
|
||||||
|
},
|
||||||
|
geometry: {
|
||||||
|
type: 'Polygon',
|
||||||
|
coordinates: [
|
||||||
|
[
|
||||||
|
[11.25, 53.585984],
|
||||||
|
[10.151367, 52.975108],
|
||||||
|
[12.689209, 52.167194],
|
||||||
|
[14.084473, 53.199452],
|
||||||
|
[12.634277, 53.618579],
|
||||||
|
[11.25, 53.585984],
|
||||||
|
[11.25, 53.585984],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'Feature',
|
||||||
|
properties: {
|
||||||
|
_umap_options: {
|
||||||
|
color: 'OliveDrab',
|
||||||
|
},
|
||||||
|
name: 'test',
|
||||||
|
},
|
||||||
|
geometry: {
|
||||||
|
type: 'Point',
|
||||||
|
coordinates: [-0.274658, 52.57635],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'Feature',
|
||||||
|
properties: {
|
||||||
|
_umap_options: {
|
||||||
|
fill: false,
|
||||||
|
},
|
||||||
|
name: 'test',
|
||||||
|
},
|
||||||
|
geometry: {
|
||||||
|
type: 'LineString',
|
||||||
|
coordinates: [
|
||||||
|
[-0.571289, 54.476422],
|
||||||
|
[0.439453, 54.610255],
|
||||||
|
[1.724854, 53.448807],
|
||||||
|
[4.163818, 53.988395],
|
||||||
|
[5.306396, 53.533778],
|
||||||
|
[6.591797, 53.709714],
|
||||||
|
[7.042236, 53.350551],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
_umap_options: {
|
||||||
|
displayOnLoad: true,
|
||||||
|
browsable: true,
|
||||||
|
iconClass: 'Default',
|
||||||
|
name: 'Elephants',
|
||||||
|
id: 62,
|
||||||
|
pictogram_url: null,
|
||||||
|
opacity: null,
|
||||||
|
weight: null,
|
||||||
|
fillColor: '',
|
||||||
|
color: '',
|
||||||
|
stroke: true,
|
||||||
|
smoothFactor: null,
|
||||||
|
dashArray: '',
|
||||||
|
fillOpacity: null,
|
||||||
|
fill: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
assert.deepEqual(JSON.parse(content), expected)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
|
@ -1,4 +1,4 @@
|
||||||
describe('L.Utorage.Polyline', function () {
|
describe('L.U.Polyline', function () {
|
||||||
var p2ll, map
|
var p2ll, map
|
||||||
|
|
||||||
before(function () {
|
before(function () {
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
<script src="../vendors/measurable/Leaflet.Measurable.js"></script>
|
<script src="../vendors/measurable/Leaflet.Measurable.js"></script>
|
||||||
<script src="../vendors/locatecontrol/L.Control.Locate.js"></script>
|
<script src="../vendors/locatecontrol/L.Control.Locate.js"></script>
|
||||||
<script src="../vendors/dompurify/purify.js"></script>
|
<script src="../vendors/dompurify/purify.js"></script>
|
||||||
|
<script src="../vendors/togpx/togpx.js"></script>
|
||||||
|
<script src="../vendors/tokml/tokml.js"></script>
|
||||||
<script src="../js/umap.core.js"></script>
|
<script src="../js/umap.core.js"></script>
|
||||||
<script src="../js/umap.autocomplete.js"></script>
|
<script src="../js/umap.autocomplete.js"></script>
|
||||||
<script src="../js/umap.popup.js"></script>
|
<script src="../js/umap.popup.js"></script>
|
||||||
|
@ -68,6 +70,7 @@
|
||||||
<script src="./_pre.js"></script>
|
<script src="./_pre.js"></script>
|
||||||
<script src="./Map.js"></script>
|
<script src="./Map.js"></script>
|
||||||
<script src="./Map.Init.js"></script>
|
<script src="./Map.Init.js"></script>
|
||||||
|
<script src="./Map.Export.js"></script>
|
||||||
<script src="./DataLayer.js"></script>
|
<script src="./DataLayer.js"></script>
|
||||||
<script src="./TableEditor.js"></script>
|
<script src="./TableEditor.js"></script>
|
||||||
<script src="./Feature.js"></script>
|
<script src="./Feature.js"></script>
|
||||||
|
|
Loading…
Reference in a new issue