This commit is contained in:
Yohan Boniface 2025-04-25 05:09:43 +00:00 committed by GitHub
commit 53072b6f5b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 188 additions and 175 deletions

View file

@ -551,6 +551,7 @@ class DataLayer(NamedModel):
if self.old_id:
metadata["old_id"] = self.old_id
metadata["id"] = self.pk
metadata["rank"] = self.rank
metadata["permissions"] = {"edit_status": self.edit_status}
metadata["editMode"] = "advanced" if self.can_edit(request) else "disabled"
metadata["_referenceVersion"] = self.reference_version

View file

@ -113,7 +113,7 @@ export default class Browser {
}
onFormChange() {
this._umap.eachBrowsableDataLayer((datalayer) => {
this._umap.datalayers.browsable().map((datalayer) => {
datalayer.resetLayer(true)
this.updateDatalayer(datalayer)
if (this._umap.fullPanel?.isOpen()) datalayer.tableEdit()
@ -136,7 +136,7 @@ export default class Browser {
onMoveEnd() {
if (!this.isOpen()) return
const isListDynamic = this.options.inBbox
this._umap.eachBrowsableDataLayer((datalayer) => {
this._umap.datalayers.browsable().map((datalayer) => {
if (!isListDynamic && !datalayer.hasDynamicData()) return
this.updateDatalayer(datalayer)
})
@ -145,7 +145,7 @@ export default class Browser {
update() {
if (!this.isOpen()) return
this.dataContainer.innerHTML = ''
this._umap.eachBrowsableDataLayer((datalayer) => {
this._umap.datalayers.browsable().map((datalayer) => {
this.addDataLayer(datalayer, this.dataContainer)
})
}
@ -254,10 +254,10 @@ export default class Browser {
// If at least one layer is shown, hide it
// otherwise show all
let allHidden = true
this._umap.eachBrowsableDataLayer((datalayer) => {
this._umap.datalayers.browsable().map((datalayer) => {
if (datalayer.isVisible()) allHidden = false
})
this._umap.eachBrowsableDataLayer((datalayer) => {
this._umap.datalayers.browsable().map((datalayer) => {
datalayer._forcedVisibility = true
if (allHidden) {
datalayer.show()

View file

@ -68,9 +68,11 @@ export default class Caption extends Utils.WithTemplate {
this.elements.description.hidden = true
}
this.elements.datalayersContainer.innerHTML = ''
this._umap.eachDataLayerReverse((datalayer) =>
this.addDataLayer(datalayer, this.elements.datalayersContainer)
)
this._umap.datalayers
.reverse()
.map((datalayer) =>
this.addDataLayer(datalayer, this.elements.datalayersContainer)
)
this.addCredits()
if (this._umap.properties.created_at) {
const created_at = translate('created at {date}', {
@ -85,7 +87,7 @@ export default class Caption extends Utils.WithTemplate {
}
this._umap.panel.open({ content: this.element }).then(() => {
// Create the legend when the panel is actually on the DOM
this._umap.eachDataLayerReverse((datalayer) => datalayer.renderLegend())
this._umap.datalayers.reverse().map((datalayer) => datalayer.renderLegend())
this._umap.propagate()
})
}

View file

@ -64,6 +64,9 @@ export class DataLayer {
this.setOptions(data)
this.pane.dataset.id = this.id
if (this.options.rank === undefined) {
this.options.rank = this._umap.datalayers.count()
}
if (!Utils.isObject(this.options.remoteData)) {
this.options.remoteData = {}
@ -153,6 +156,9 @@ export class DataLayer {
case 'remote-data':
this.fetchRemoteData()
break
case 'datalayer-rank':
this._umap.reorderDataLayers()
break
}
}
}
@ -249,16 +255,9 @@ export class DataLayer {
if (!error) {
this._umap.modifiedAt = response.headers.get('last-modified')
this.setReferenceVersion({ response, sync: false })
// FIXME: for now the _umap_options property is set dynamically from backend
// And thus it's not in the geojson file in the server
// So do not let all options to be reset
// Fix is a proper migration so all datalayers settings are
// in DB, and we remove it from geojson flat files.
if (geojson._umap_options) {
geojson._umap_options.editMode = this.options.editMode
}
delete geojson._umap_options
// In case of maps pre 1.0 still around
if (geojson._storage) geojson._storage.editMode = this.options.editMode
delete geojson._storage
await this.fromUmapGeoJSON(geojson)
this.backupOptions()
this._loading = false
@ -287,7 +286,6 @@ export class DataLayer {
async fromUmapGeoJSON(geojson) {
if (geojson._storage) geojson._umap_options = geojson._storage // Retrocompat
geojson._umap_options.id = this.id
if (geojson._umap_options) this.setOptions(geojson._umap_options)
if (this.isRemoteLayer()) {
await this.fetchRemoteData()
@ -297,6 +295,7 @@ export class DataLayer {
}
clear() {
// TODO do not startBatch for remoteData layer
this.sync.startBatch()
for (const feature of Object.values(this._features)) {
feature.del()
@ -395,12 +394,7 @@ export class DataLayer {
}
connectToMap() {
if (!this._umap.datalayers[this.id]) {
this._umap.datalayers[this.id] = this
}
if (!this._umap.datalayersIndex.includes(this)) {
this._umap.datalayersIndex.push(this)
}
this._umap.datalayers.add(this)
this._umap.onDataLayersChanged()
}
@ -644,11 +638,19 @@ export class DataLayer {
del(sync = true) {
const oldValue = Utils.CopyJSON(this.umapGeoJSON())
this.erase()
// TODO merge datalayer del and features del in same
// batch
this.clear()
if (sync) {
this.isDeleted = true
this.sync.delete(oldValue)
}
this.hide()
this.parentPane.removeChild(this.pane)
this._umap.onDataLayersChanged()
this.layer.onDelete(this._leafletMap)
this.propagateDelete()
this._leaflet_events_bk = this._leaflet_events
}
empty() {
@ -666,17 +668,6 @@ export class DataLayer {
return datalayer
}
erase() {
this.hide()
this._umap.datalayersIndex.splice(this.getRank(), 1)
this.parentPane.removeChild(this.pane)
this._umap.onDataLayersChanged()
this.layer.onDelete(this._leafletMap)
this.propagateDelete()
this._leaflet_events_bk = this._leaflet_events
this.clear()
}
redraw() {
if (!this.isVisible()) return
this.eachFeature((feature) => feature.redraw())
@ -1091,23 +1082,11 @@ export class DataLayer {
}
getPreviousBrowsable() {
let id = this.getRank()
let next
const index = this._umap.datalayersIndex
while (((id = index[++id] ? id : 0), (next = index[id]))) {
if (next === this || next.canBrowse()) break
}
return next
return this._umap.datalayers.prev(this)
}
getNextBrowsable() {
let id = this.getRank()
let prev
const index = this._umap.datalayersIndex
while (((id = index[--id] ? id : index.length - 1), (prev = index[id]))) {
if (prev === this || prev.canBrowse()) break
}
return prev
return this._umap.datalayers.next(this)
}
umapGeoJSON() {
@ -1118,8 +1097,8 @@ export class DataLayer {
}
}
getRank() {
return this._umap.datalayersIndex.indexOf(this)
getDOMOrder() {
return Array.from(this.parentPane.children).indexOf(this.pane)
}
isReadOnly() {
@ -1141,6 +1120,12 @@ export class DataLayer {
}
}
prepareOptions() {
const options = Utils.CopyJSON(this.options)
delete options.permissions
return JSON.stringify(options)
}
async save() {
if (this.isDeleted) return await this.saveDelete()
if (!this.isRemoteLayer() && !this.isLoaded()) return
@ -1148,8 +1133,8 @@ export class DataLayer {
const formData = new FormData()
formData.append('name', this.options.name)
formData.append('display_on_load', !!this.options.displayOnLoad)
formData.append('rank', this.getRank())
formData.append('settings', JSON.stringify(this.options))
formData.append('rank', this.options.rank)
formData.append('settings', this.prepareOptions())
// Filename support is shaky, don't do it for now.
const blob = new Blob([JSON.stringify(geojson)], { type: 'application/json' })
formData.append('geojson', blob)

View file

@ -24,7 +24,7 @@ export default class Facets {
this.selected[name] = selected
}
this._umap.eachBrowsableDataLayer((datalayer) => {
this._umap.datalayers.browsable().map((datalayer) => {
datalayer.eachFeature((feature) => {
for (const name of names) {
let value = feature.properties[name]

View file

@ -560,7 +560,7 @@ Fields.SlideshowDelay = class extends Fields.IntSelect {
Fields.DataLayerSwitcher = class extends Fields.Select {
getOptions() {
const options = []
this.builder._umap.eachDataLayerReverse((datalayer) => {
this.builder._umap.datalayers.reverse().map((datalayer) => {
if (
datalayer.isLoaded() &&
!datalayer.isDataReadOnly() &&

View file

@ -243,7 +243,7 @@ export default class Importer extends Utils.WithTemplate {
this.raw = null
const layerSelect = this.qs('[name="layer-id"]')
layerSelect.innerHTML = ''
this._umap.eachDataLayerReverse((datalayer) => {
this._umap.datalayers.reverse().map((datalayer) => {
if (datalayer.isLoaded() && !datalayer.isRemoteLayer()) {
DomUtil.element({
tagName: 'option',

View file

@ -0,0 +1,46 @@
export class DataLayerManager extends Object {
add(datalayer) {
this[datalayer.id] = datalayer
}
active() {
return Object.values(this)
.filter((datalayer) => !datalayer.isDeleted)
.sort((a, b) => a.options.rank > b.options.rank)
}
reverse() {
return this.active().reverse()
}
count() {
return this.active().length
}
find(func) {
for (const datalayer of this.reverse()) {
if (func.call(datalayer, datalayer)) {
return datalayer
}
}
}
filter(func) {
return this.active().filter(func)
}
visible() {
return this.filter((datalayer) => datalayer.isVisible())
}
browsable() {
return this.reverse().filter((datalayer) => datalayer.allowBrowse())
}
prev(datalayer) {
const browsable = this.browsable()
const current = browsable.indexOf(datalayer)
const prev = browsable[current - 1] || browsable[browsable.length - 1]
if (!prev.canBrowse()) return this.prev(prev)
return prev
}
next(datalayer) {
const browsable = this.browsable()
const current = browsable.indexOf(datalayer)
const next = browsable[current + 1] || browsable[0]
if (!next.canBrowse()) return this.next(next)
return next
}
}

View file

@ -159,7 +159,7 @@ export class MapPermissions {
`<fieldset class="separator"><legend>${translate('Datalayers')}</legend></fieldset>`
)
container.appendChild(fieldset)
this._umap.eachDataLayer((datalayer) => {
this._umap.datalayers.active().map((datalayer) => {
datalayer.permissions.edit(fieldset)
})
}

View file

@ -327,7 +327,7 @@ export const LeafletMap = BaseMap.extend({
} else if (this.options.defaultView === 'latest') {
this._umap.onceDataLoaded(() => {
if (!this._umap.hasData()) return
const datalayer = this._umap.firstVisibleDatalayer()
const datalayer = this._umap.datalayers.visible()[0]
let feature
if (datalayer) {
const feature = datalayer.getFeatureByIndex(-1)

View file

@ -10,7 +10,7 @@ import { translate } from './i18n.js'
* - `type`: The type of the data
* - `impacts`: A list of impacts than happen when this property is updated, among
* 'ui', 'data', 'limit-bounds', 'datalayer-index', 'remote-data',
* 'background' 'sync'.
* 'background', 'sync', 'datalayer-rank'.
*
* - Extra keys are being passed to the FormBuilder automatically.
*/
@ -436,6 +436,10 @@ export const SCHEMA = {
],
default: 'Default',
},
rank: {
type: Number,
impacts: ['datalayer-rank'],
},
remoteData: {
type: Object,
impacts: ['remote-data'],

View file

@ -204,8 +204,8 @@ class IframeExporter {
delete this.queryString.feature
}
if (this.options.keepCurrentDatalayers) {
this._umap.eachDataLayer((datalayer) => {
if (datalayer.isVisible() && datalayer.createdOnServer) {
this._umap.datalayers.visible().map((datalayer) => {
if (datalayer.createdOnServer) {
datalayers.push(datalayer.id)
}
})

View file

@ -66,7 +66,7 @@ export default class Slideshow extends WithTemplate {
}
defaultDatalayer() {
return this._umap.findDataLayer((d) => d.canBrowse())
return this._umap.datalayers.find((d) => d.canBrowse())
}
startSpinner() {

View file

@ -207,22 +207,35 @@ export class SyncEngine {
this._send(operation)
}
async save() {
const needSave = new Map()
_getDirtyObjects() {
const dirty = new Map()
if (!this._umap.id) {
// There is no operation for first map save
needSave.set(this._umap, [])
dirty.set(this._umap, [])
}
const addDirtyObject = (operation) => {
const updater = this._getUpdater(operation.subject)
const obj = updater.getStoredObject(operation.metadata)
if (!dirty.has(obj)) {
dirty.set(obj, [])
}
dirty.get(obj).push(operation)
}
for (const operation of this._operations.sorted()) {
if (operation.dirty) {
const updater = this._getUpdater(operation.subject)
const obj = updater.getStoredObject(operation.metadata)
if (!needSave.has(obj)) {
needSave.set(obj, [])
addDirtyObject(operation)
if (operation.verb === 'batch') {
for (const op of operation.operations) {
addDirtyObject(op)
}
}
needSave.get(obj).push(operation)
}
}
return dirty
}
async save() {
const needSave = this._getDirtyObjects()
for (const [obj, operations] of needSave.entries()) {
const ok = await obj.save()
if (!ok) return false

View file

@ -207,7 +207,7 @@ export class BottomBar extends WithTemplate {
const select = this.elements.layers
const selected = select.options[select.selectedIndex].value
if (!selected) return
this._umap.eachDataLayer((datalayer) => {
this._umap.datalayers.active().map((datalayer) => {
datalayer.toggle(datalayer.id === selected)
})
})
@ -228,7 +228,7 @@ export class BottomBar extends WithTemplate {
buildDataLayerSwitcher() {
this.elements.layers.innerHTML = ''
const datalayers = this._umap.datalayersIndex.filter((d) => d.options.inCaption)
const datalayers = this._umap.datalayers.filter((d) => d.options.inCaption)
if (datalayers.length < 2) {
this.elements.layers.hidden = true
} else {

View file

@ -33,6 +33,7 @@ import { EditPanel, FullPanel, Panel } from './ui/panel.js'
import Tooltip from './ui/tooltip.js'
import URLs from './urls.js'
import * as Utils from './utils.js'
import { DataLayerManager } from './managers.js'
export default class Umap {
constructor(element, geojson) {
@ -166,8 +167,7 @@ export default class Umap {
}
// Global storage for retrieving datalayers and features.
this.datalayers = {} // All datalayers, including deleted.
this.datalayersIndex = [] // Datalayers actually on the map and ordered.
this.datalayers = new DataLayerManager()
this.featuresIndex = {}
this.formatter = new Formatter(this)
@ -217,7 +217,6 @@ export default class Umap {
}
window.onbeforeunload = () => (this.editEnabled && this.isDirty) || null
this.backup()
}
get isDirty() {
@ -616,7 +615,7 @@ export default class Umap {
this.datalayersLoaded = true
this.fire('datalayersloaded')
const toLoad = []
for (const datalayer of this.datalayersIndex) {
for (const datalayer of this.datalayers.active()) {
if (datalayer.showAtLoad()) toLoad.push(() => datalayer.show())
}
while (toLoad.length) {
@ -630,7 +629,7 @@ export default class Umap {
createDataLayer(options = {}, sync = true) {
options.name =
options.name || `${translate('Layer')} ${this.datalayersIndex.length + 1}`
options.name || `${translate('Layer')} ${this.datalayers.count() + 1}`
const datalayer = new DataLayer(this, this._leafletMap, options)
if (sync !== false) {
@ -651,19 +650,21 @@ export default class Umap {
}
reindexDataLayers() {
this.eachDataLayer((datalayer) => datalayer.reindex())
this.datalayers.active().map((datalayer) => datalayer.reindex())
this.onDataLayersChanged()
}
indexDatalayers() {
const panes = this._leafletMap.getPane('overlayPane')
this.datalayersIndex = []
for (const pane of panes.children) {
if (!pane.dataset || !pane.dataset.id) continue
this.datalayersIndex.push(this.datalayers[pane.dataset.id])
reorderDataLayers() {
const parent = this._leafletMap.getPane('overlayPane')
const datalayers = Object.values(this.datalayers)
.filter((datalayer) => !datalayer._isDeleted)
.sort(
(datalayer1, datalayer2) => datalayer1.options.rank > datalayer2.options.rank
)
for (const datalayer of datalayers) {
const child = parent.querySelector(`[data-id="${datalayer.id}"]`)
parent.appendChild(child)
}
this.onDataLayersChanged()
}
onceDatalayersLoaded(callback, context) {
@ -694,7 +695,6 @@ export default class Umap {
async saveAll() {
if (!this.isDirty) return
if (this._defaultExtent) this._setCenterAndZoom()
this.backup()
const status = await this.sync.save()
if (!status) return
// Do a blind render for now, as we are not sure what could
@ -714,24 +714,6 @@ export default class Umap {
return this.properties.name || translate('Untitled map')
}
backup() {
this.backupProperties()
this._datalayersIndex_bk = [].concat(this.datalayersIndex)
}
backupProperties() {
this._backupProperties = Object.assign({}, this.properties)
this._backupProperties.tilelayer = Object.assign({}, this.properties.tilelayer)
this._backupProperties.limitBounds = Object.assign({}, this.properties.limitBounds)
this._backupProperties.permissions = Object.assign({}, this.permissions.properties)
}
resetProperties() {
this.properties = Object.assign({}, this._backupProperties)
this.properties.tilelayer = Object.assign({}, this._backupProperties.tilelayer)
this.permissions.properties = Object.assign({}, this._backupProperties.permissions)
}
setProperties(newProperties) {
for (const key of Object.keys(SCHEMA)) {
if (newProperties[key] !== undefined) {
@ -744,24 +726,24 @@ export default class Umap {
}
hasData() {
for (const datalayer of this.datalayersIndex) {
for (const datalayer of this.datalayers.active()) {
if (datalayer.hasData()) return true
}
}
hasLayers() {
return Boolean(this.datalayersIndex.length)
return Boolean(this.datalayers.count())
}
allProperties() {
return [].concat(...this.datalayersIndex.map((dl) => dl.allProperties()))
return [].concat(...this.datalayers.active().map((dl) => dl.allProperties()))
}
sortedValues(property) {
return []
.concat(...this.datalayersIndex.map((dl) => dl.sortedValues(property)))
.concat(...this.datalayers.active().map((dl) => dl.sortedValues(property)))
.filter((val, idx, arr) => arr.indexOf(val) === idx)
.sort(U.Utils.naturalSort)
.sort(Utils.naturalSort)
}
editCaption() {
@ -1278,7 +1260,7 @@ export default class Umap {
toGeoJSON() {
let features = []
this.eachDataLayer((datalayer) => {
this.datalayers.active().map((datalayer) => {
if (datalayer.isVisible()) {
features = features.concat(datalayer.featuresToGeoJSON())
}
@ -1354,13 +1336,20 @@ export default class Umap {
if (fields.includes('properties.rules')) {
this.rules.load()
}
this.eachVisibleDataLayer((datalayer) => {
this.datalayers.visible().map((datalayer) => {
datalayer.redraw()
})
break
case 'datalayer-index':
this.reindexDataLayers()
break
case 'datalayer-rank':
// When drag'n'dropping datalayers,
// this get called once per datalayers.
// (and same for undo/redo of the action)
// TODO: call only once
this.reorderDataLayers()
break
case 'background':
this._leafletMap.initTileLayers()
break
@ -1449,7 +1438,7 @@ export default class Umap {
) {
return datalayer
}
datalayer = this.findDataLayer((datalayer) => {
datalayer = this.datalayers.find((datalayer) => {
if (!datalayer.isDataReadOnly() && datalayer.isBrowsable()) {
fallback = datalayer
if (datalayer.isVisible()) return true
@ -1464,49 +1453,20 @@ export default class Umap {
return this.createDirtyDataLayer()
}
findDataLayer(method, context) {
for (let i = this.datalayersIndex.length - 1; i >= 0; i--) {
if (method.call(context, this.datalayersIndex[i])) {
return this.datalayersIndex[i]
}
}
}
eachDataLayer(method, context) {
for (let i = 0; i < this.datalayersIndex.length; i++) {
method.call(context, this.datalayersIndex[i])
}
}
eachDataLayerReverse(method, context, filter) {
for (let i = this.datalayersIndex.length - 1; i >= 0; i--) {
if (filter && !filter.call(context, this.datalayersIndex[i])) continue
method.call(context, this.datalayersIndex[i])
}
}
eachBrowsableDataLayer(method, context) {
this.eachDataLayerReverse(method, context, (d) => d.allowBrowse())
}
eachVisibleDataLayer(method, context) {
this.eachDataLayerReverse(method, context, (d) => d.isVisible())
}
eachFeature(callback, context) {
this.eachBrowsableDataLayer((datalayer) => {
if (datalayer.isVisible()) datalayer.eachFeature(callback, context)
eachFeature(callback) {
this.datalayers.browsable().map((datalayer) => {
if (datalayer.isVisible()) datalayer.eachFeature(callback)
})
}
removeDataLayers() {
this.eachDataLayerReverse((datalayer) => {
this.datalayers.active().map((datalayer) => {
datalayer.del()
})
}
emptyDataLayers() {
this.eachDataLayerReverse((datalayer) => {
this.datalayers.active().map((datalayer) => {
datalayer.empty()
})
}
@ -1520,7 +1480,7 @@ export default class Umap {
</div>
`
const [container, { ul }] = Utils.loadTemplateWithRefs(template)
this.eachDataLayerReverse((datalayer) => {
this.datalayers.reverse().map((datalayer) => {
const row = Utils.loadTemplate(
`<li class="orderable"><i class="icon icon-16 icon-drag" title="${translate('Drag to reorder')}"></i></li>`
)
@ -1539,16 +1499,22 @@ export default class Umap {
const onReorder = (src, dst, initialIndex, finalIndex) => {
const movedLayer = this.datalayers[src.dataset.id]
const targetLayer = this.datalayers[dst.dataset.id]
const minIndex = Math.min(movedLayer.getRank(), targetLayer.getRank())
const maxIndex = Math.max(movedLayer.getRank(), targetLayer.getRank())
const minIndex = Math.min(movedLayer.getDOMOrder(), targetLayer.getDOMOrder())
const maxIndex = Math.max(movedLayer.getDOMOrder(), targetLayer.getDOMOrder())
if (finalIndex === 0) movedLayer.bringToTop()
else if (finalIndex > initialIndex) movedLayer.insertBefore(targetLayer)
else movedLayer.insertAfter(targetLayer)
this.eachDataLayerReverse((datalayer) => {
if (datalayer.getRank() >= minIndex && datalayer.getRank() <= maxIndex)
datalayer.isDirty = true
this.sync.startBatch()
this.datalayers.reverse().map((datalayer) => {
const rank = datalayer.getDOMOrder()
if (rank >= minIndex && rank <= maxIndex) {
const oldRank = datalayer.options.rank
datalayer.options.rank = rank
datalayer.sync.update('options.rank', rank, oldRank)
}
})
this.indexDatalayers()
this.sync.commitBatch()
this.onDataLayersChanged()
}
const orderable = new Orderable(ul, onReorder)
@ -1570,18 +1536,6 @@ export default class Umap {
return datalayer
}
firstVisibleDatalayer() {
return this.findDataLayer((datalayer) => {
if (datalayer.isVisible()) return true
})
}
ensurePanesOrder() {
this.eachDataLayer((datalayer) => {
datalayer.bringToTop()
})
}
openBrowser(mode) {
this.onceDatalayersLoaded(() => this.browser.open(mode))
}
@ -1732,7 +1686,7 @@ export default class Umap {
getLayersBounds() {
const bounds = new latLngBounds()
this.eachBrowsableDataLayer((d) => {
this.datalayers.browsable().map((d) => {
if (d.isVisible()) bounds.extend(d.layer.getBounds())
})
return bounds

View file

@ -131,8 +131,8 @@ class DataLayerFactory(factory.django.DjangoModelFactory):
data.setdefault("_umap_options", {})
if "name" in data["_umap_options"] and kwargs["name"] == cls.name:
kwargs["name"] = data["_umap_options"]["name"]
if "settings" not in kwargs:
kwargs["settings"] = data.get("_umap_options", {})
kwargs.setdefault("settings", {})
kwargs["settings"].update(data.get("_umap_options", {}))
else:
data = DATALAYER_DATA.copy()
data["_umap_options"] = {

View file

@ -50,6 +50,8 @@ def test_created_markers_are_merged(context, live_server, tilelayer):
"editMode": "advanced",
"inCaption": True,
"id": str(datalayer.pk),
"rank": 0,
"remoteData": {},
}
# Now navigate to this map from another tab
@ -87,6 +89,8 @@ def test_created_markers_are_merged(context, live_server, tilelayer):
"inCaption": True,
"editMode": "advanced",
"id": str(datalayer.pk),
"rank": 0,
"remoteData": {},
}
# Now create another marker in the first tab
@ -105,7 +109,8 @@ def test_created_markers_are_merged(context, live_server, tilelayer):
"inCaption": True,
"editMode": "advanced",
"id": str(datalayer.pk),
"permissions": {"edit_status": 1},
"rank": 0,
"remoteData": {},
}
# And again
@ -124,7 +129,8 @@ def test_created_markers_are_merged(context, live_server, tilelayer):
"inCaption": True,
"editMode": "advanced",
"id": str(datalayer.pk),
"permissions": {"edit_status": 1},
"rank": 0,
"remoteData": {},
}
expect(marker_pane_p1).to_have_count(4)
@ -145,7 +151,8 @@ def test_created_markers_are_merged(context, live_server, tilelayer):
"inCaption": True,
"editMode": "advanced",
"id": str(datalayer.pk),
"permissions": {"edit_status": 1},
"rank": 0,
"remoteData": {},
}
expect(marker_pane_p2).to_have_count(5)
@ -271,7 +278,8 @@ def test_same_second_edit_doesnt_conflict(context, live_server, tilelayer):
"inCaption": True,
"editMode": "advanced",
"id": str(datalayer.pk),
"permissions": {"edit_status": 1},
"rank": 0,
"remoteData": {},
}