mirror of
https://github.com/umap-project/umap.git
synced 2025-04-28 19:42:36 +02:00
chore: split umap.js in two modules
This commit is contained in:
parent
256d4487e7
commit
c952fed96a
33 changed files with 2605 additions and 2358 deletions
|
@ -1,6 +1,8 @@
|
|||
import Umap from '../modules/umap.js'
|
||||
|
||||
class UmapFragment extends HTMLElement {
|
||||
connectedCallback() {
|
||||
new U.Map(this.firstElementChild.id, JSON.parse(this.dataset.settings))
|
||||
new Umap(this.firstElementChild.id, JSON.parse(this.dataset.settings))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,9 +6,9 @@ import { EXPORT_FORMATS } from './formatter.js'
|
|||
import ContextMenu from './ui/contextmenu.js'
|
||||
|
||||
export default class Browser {
|
||||
constructor(map) {
|
||||
this.map = map
|
||||
this.map.on('moveend', this.onMoveEnd, this)
|
||||
constructor(umap) {
|
||||
this.umap = umap
|
||||
this.umap._leafletMap.on('moveend', this.onMoveEnd, this)
|
||||
this.options = {
|
||||
filter: '',
|
||||
inBbox: false,
|
||||
|
@ -82,7 +82,7 @@ export default class Browser {
|
|||
|
||||
updateDatalayer(datalayer) {
|
||||
// Compute once, but use it for each feature later.
|
||||
this.bounds = this.map.getBounds()
|
||||
this.bounds = this.umap._leafletMap.getBounds()
|
||||
const parent = DomUtil.get(this.datalayerId(datalayer))
|
||||
// Panel is not open
|
||||
if (!parent) return
|
||||
|
@ -115,10 +115,10 @@ export default class Browser {
|
|||
}
|
||||
|
||||
onFormChange() {
|
||||
this.map.eachBrowsableDataLayer((datalayer) => {
|
||||
this.umap.eachBrowsableDataLayer((datalayer) => {
|
||||
datalayer.resetLayer(true)
|
||||
this.updateDatalayer(datalayer)
|
||||
if (this.map.fullPanel?.isOpen()) datalayer.tableEdit()
|
||||
if (this.umap.fullPanel?.isOpen()) datalayer.tableEdit()
|
||||
})
|
||||
this.toggleBadge()
|
||||
}
|
||||
|
@ -132,13 +132,13 @@ export default class Browser {
|
|||
}
|
||||
|
||||
hasFilters() {
|
||||
return !!this.options.filter || this.map.facets.isActive()
|
||||
return !!this.options.filter || this.umap.facets.isActive()
|
||||
}
|
||||
|
||||
onMoveEnd() {
|
||||
if (!this.isOpen()) return
|
||||
const isListDynamic = this.options.inBbox
|
||||
this.map.eachBrowsableDataLayer((datalayer) => {
|
||||
this.umap.eachBrowsableDataLayer((datalayer) => {
|
||||
if (!isListDynamic && !datalayer.hasDynamicData()) return
|
||||
this.updateDatalayer(datalayer)
|
||||
})
|
||||
|
@ -147,7 +147,7 @@ export default class Browser {
|
|||
update() {
|
||||
if (!this.isOpen()) return
|
||||
this.dataContainer.innerHTML = ''
|
||||
this.map.eachBrowsableDataLayer((datalayer) => {
|
||||
this.umap.eachBrowsableDataLayer((datalayer) => {
|
||||
this.addDataLayer(datalayer, this.dataContainer)
|
||||
})
|
||||
}
|
||||
|
@ -186,9 +186,9 @@ export default class Browser {
|
|||
DomEvent.on(builder.form, 'reset', () => {
|
||||
window.setTimeout(builder.syncAll.bind(builder))
|
||||
})
|
||||
if (this.map.options.facetKey) {
|
||||
fields = this.map.facets.build()
|
||||
filtersBuilder = new L.FormBuilder(this.map.facets, fields, {
|
||||
if (this.umap.properties.facetKey) {
|
||||
fields = this.umap.facets.build()
|
||||
filtersBuilder = new L.FormBuilder(this.umap.facets, fields, {
|
||||
callback: () => this.onFormChange(),
|
||||
})
|
||||
DomEvent.on(filtersBuilder.form, 'reset', () => {
|
||||
|
@ -206,7 +206,7 @@ export default class Browser {
|
|||
textContent: translate('Reset all'),
|
||||
})
|
||||
|
||||
this.map.panel.open({
|
||||
this.umap.panel.open({
|
||||
content: container,
|
||||
className: 'umap-browser',
|
||||
})
|
||||
|
@ -230,7 +230,7 @@ export default class Browser {
|
|||
`)
|
||||
container.appendChild(toolbox)
|
||||
toggle.addEventListener('click', () => this.toggleLayers())
|
||||
fitBounds.addEventListener('click', () => this.map.fitDataBounds())
|
||||
fitBounds.addEventListener('click', () => this.umap.fitDataBounds())
|
||||
download.addEventListener('click', () => this.downloadVisible(download))
|
||||
}
|
||||
|
||||
|
@ -240,7 +240,7 @@ export default class Browser {
|
|||
for (const format of Object.keys(EXPORT_FORMATS)) {
|
||||
items.push({
|
||||
label: format,
|
||||
action: () => this.map.share.download(format),
|
||||
action: () => this.umap.share.download(format),
|
||||
})
|
||||
}
|
||||
menu.openBelow(element, items)
|
||||
|
@ -250,10 +250,10 @@ export default class Browser {
|
|||
// If at least one layer is shown, hide it
|
||||
// otherwise show all
|
||||
let allHidden = true
|
||||
this.map.eachBrowsableDataLayer((datalayer) => {
|
||||
this.umap.eachBrowsableDataLayer((datalayer) => {
|
||||
if (datalayer.isVisible()) allHidden = false
|
||||
})
|
||||
this.map.eachBrowsableDataLayer((datalayer) => {
|
||||
this.umap.eachBrowsableDataLayer((datalayer) => {
|
||||
if (allHidden) {
|
||||
datalayer.show()
|
||||
} else {
|
||||
|
@ -271,7 +271,7 @@ export default class Browser {
|
|||
// Fixme: remove me when this is merged and released
|
||||
// https://github.com/Leaflet/Leaflet/pull/9052
|
||||
DomEvent.disableClickPropagation(button)
|
||||
DomEvent.on(button, 'click', map.openBrowser, map)
|
||||
DomEvent.on(button, 'click', map.umap.openBrowser, map.umap)
|
||||
return button
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@ import { translate } from './i18n.js'
|
|||
import * as Utils from './utils.js'
|
||||
|
||||
export default class Caption {
|
||||
constructor(map) {
|
||||
this.map = map
|
||||
constructor(umap) {
|
||||
this.umap = umap
|
||||
}
|
||||
|
||||
isOpen() {
|
||||
|
@ -21,38 +21,36 @@ export default class Caption {
|
|||
const hgroup = DomUtil.element({ tagName: 'hgroup', parent: container })
|
||||
DomUtil.createTitle(
|
||||
hgroup,
|
||||
this.map.getDisplayName(),
|
||||
this.umap.getDisplayName(),
|
||||
'icon-caption icon-block',
|
||||
'map-name'
|
||||
)
|
||||
this.map.addAuthorLink('h4', hgroup)
|
||||
if (this.map.options.description) {
|
||||
const title = Utils.loadTemplate('<h4></h4>')
|
||||
hgroup.appendChild(title)
|
||||
this.umap.addAuthorLink(title)
|
||||
if (this.umap.properties.description) {
|
||||
const description = DomUtil.element({
|
||||
tagName: 'div',
|
||||
className: 'umap-map-description text',
|
||||
safeHTML: Utils.toHTML(this.map.options.description),
|
||||
safeHTML: Utils.toHTML(this.umap.properties.description),
|
||||
parent: container,
|
||||
})
|
||||
}
|
||||
const datalayerContainer = DomUtil.create('div', 'datalayer-container', container)
|
||||
this.map.eachDataLayerReverse((datalayer) =>
|
||||
this.umap.eachDataLayerReverse((datalayer) =>
|
||||
this.addDataLayer(datalayer, datalayerContainer)
|
||||
)
|
||||
const creditsContainer = DomUtil.create('div', 'credits-container', container)
|
||||
this.addCredits(creditsContainer)
|
||||
this.map.panel.open({ content: container }).then(() => {
|
||||
this.umap.panel.open({ content: container }).then(() => {
|
||||
// Create the legend when the panel is actually on the DOM
|
||||
this.map.eachDataLayerReverse((datalayer) => datalayer.renderLegend())
|
||||
this.umap.eachDataLayerReverse((datalayer) => datalayer.renderLegend())
|
||||
})
|
||||
}
|
||||
|
||||
addDataLayer(datalayer, container) {
|
||||
if (!datalayer.options.inCaption) return
|
||||
const p = DomUtil.create(
|
||||
'p',
|
||||
`caption-item ${datalayer.cssId}`,
|
||||
container
|
||||
)
|
||||
const p = DomUtil.create('p', `caption-item ${datalayer.cssId}`, container)
|
||||
const legend = DomUtil.create('span', 'datalayer-legend', p)
|
||||
const headline = DomUtil.create('strong', '', p)
|
||||
if (datalayer.options.description) {
|
||||
|
@ -69,16 +67,16 @@ export default class Caption {
|
|||
addCredits(container) {
|
||||
const credits = DomUtil.createFieldset(container, translate('Credits'))
|
||||
let title = DomUtil.add('h5', '', credits, translate('User content credits'))
|
||||
if (this.map.options.shortCredit || this.map.options.longCredit) {
|
||||
if (this.umap.properties.shortCredit || this.umap.properties.longCredit) {
|
||||
DomUtil.element({
|
||||
tagName: 'p',
|
||||
parent: credits,
|
||||
safeHTML: Utils.toHTML(
|
||||
this.map.options.longCredit || this.map.options.shortCredit
|
||||
this.umap.properties.longCredit || this.umap.properties.shortCredit
|
||||
),
|
||||
})
|
||||
}
|
||||
if (this.map.options.licence) {
|
||||
if (this.umap.properties.licence) {
|
||||
const licence = DomUtil.add(
|
||||
'p',
|
||||
'',
|
||||
|
@ -88,8 +86,8 @@ export default class Caption {
|
|||
DomUtil.createLink(
|
||||
'',
|
||||
licence,
|
||||
this.map.options.licence.name,
|
||||
this.map.options.licence.url
|
||||
this.umap.properties.licence.name,
|
||||
this.umap.properties.licence.url
|
||||
)
|
||||
} else {
|
||||
DomUtil.add('p', '', credits, translate('No licence has been set'))
|
||||
|
@ -100,19 +98,19 @@ export default class Caption {
|
|||
DomUtil.element({
|
||||
tagName: 'strong',
|
||||
parent: tilelayerCredit,
|
||||
textContent: `${this.map.selected_tilelayer.options.name} `,
|
||||
textContent: `${this.umap._leafletMap.selectedTilelayer.options.name} `,
|
||||
})
|
||||
DomUtil.element({
|
||||
tagName: 'span',
|
||||
parent: tilelayerCredit,
|
||||
safeHTML: this.map.selected_tilelayer.getAttribution(),
|
||||
safeHTML: this.umap._leafletMap.selectedTilelayer.getAttribution(),
|
||||
})
|
||||
const urls = {
|
||||
leaflet: 'http://leafletjs.com',
|
||||
django: 'https://www.djangoproject.com',
|
||||
umap: 'https://umap-project.org/',
|
||||
changelog: 'https://docs.umap-project.org/en/master/changelog/',
|
||||
version: this.map.options.umap_version,
|
||||
version: this.umap.properties.umap_version,
|
||||
}
|
||||
const creditHTML = translate(
|
||||
`
|
||||
|
|
|
@ -19,7 +19,7 @@ import loadPopup from '../rendering/popup.js'
|
|||
|
||||
class Feature {
|
||||
constructor(datalayer, geojson = {}, id = null) {
|
||||
this.sync = datalayer.map.sync_engine.proxy(this)
|
||||
this.sync = datalayer.umap.sync_engine.proxy(this)
|
||||
this._marked_for_deletion = false
|
||||
this._isDirty = false
|
||||
this._ui = null
|
||||
|
@ -69,8 +69,8 @@ class Feature {
|
|||
return this._ui
|
||||
}
|
||||
|
||||
get map() {
|
||||
return this.datalayer?.map
|
||||
get umap() {
|
||||
return this.datalayer?.umap
|
||||
}
|
||||
|
||||
get center() {
|
||||
|
@ -168,7 +168,7 @@ class Feature {
|
|||
}
|
||||
|
||||
getSlug() {
|
||||
return this.properties[this.map.getOption('slugKey') || 'name'] || ''
|
||||
return this.properties[this.umap.getOption('slugKey') || 'name'] || ''
|
||||
}
|
||||
|
||||
getPermalink() {
|
||||
|
@ -196,10 +196,10 @@ class Feature {
|
|||
return
|
||||
}
|
||||
// TODO deal with an event instead?
|
||||
if (this.map.slideshow) {
|
||||
this.map.slideshow.current = this
|
||||
if (this.umap.slideshow) {
|
||||
this.umap.slideshow.current = this
|
||||
}
|
||||
this.map.currentFeature = this
|
||||
this.umap.currentFeature = this
|
||||
this.attachPopup()
|
||||
this.ui.openPopup(latlng || this.center)
|
||||
}
|
||||
|
@ -209,7 +209,7 @@ class Feature {
|
|||
return field.startsWith('properties.')
|
||||
})
|
||||
if (impactData) {
|
||||
if (this.map.currentFeature === this) {
|
||||
if (this.umap.currentFeature === this) {
|
||||
this.view()
|
||||
}
|
||||
}
|
||||
|
@ -217,7 +217,7 @@ class Feature {
|
|||
}
|
||||
|
||||
edit(event) {
|
||||
if (!this.map.editEnabled || this.isReadOnly()) return
|
||||
if (!this.umap.editEnabled || this.isReadOnly()) return
|
||||
const container = DomUtil.create('div', 'umap-feature-container')
|
||||
DomUtil.createTitle(
|
||||
container,
|
||||
|
@ -256,12 +256,12 @@ class Feature {
|
|||
translate('Advanced actions')
|
||||
)
|
||||
this.getAdvancedEditActions(advancedActions)
|
||||
const onLoad = this.map.editPanel.open({ content: container })
|
||||
const onLoad = this.umap.editPanel.open({ content: container })
|
||||
onLoad.then(() => {
|
||||
builder.helpers['properties.name'].input.focus()
|
||||
})
|
||||
this.map.editedFeature = this
|
||||
if (!this.ui.isOnScreen(this.map.getBounds())) this.zoomTo(event)
|
||||
this.umap.editedFeature = this
|
||||
if (!this.ui.isOnScreen(this.umap._leafletMap.getBounds())) this.zoomTo(event)
|
||||
}
|
||||
|
||||
getAdvancedEditActions(container) {
|
||||
|
@ -270,7 +270,7 @@ class Feature {
|
|||
<i class="icon icon-24 icon-delete"></i>${translate('Delete')}
|
||||
</button>`)
|
||||
button.addEventListener('click', () => {
|
||||
this.confirmDelete().then(() => this.map.editPanel.close())
|
||||
this.confirmDelete().then(() => this.umap.editPanel.close())
|
||||
})
|
||||
container.appendChild(button)
|
||||
}
|
||||
|
@ -333,7 +333,7 @@ class Feature {
|
|||
if (this.datalayer.isRemoteLayer() && this.datalayer.options.remoteData.dynamic) {
|
||||
return false
|
||||
}
|
||||
return this.map.getOption('displayPopupFooter')
|
||||
return this.umap.getOption('displayPopupFooter')
|
||||
}
|
||||
|
||||
getPopupClass() {
|
||||
|
@ -347,7 +347,7 @@ class Feature {
|
|||
}
|
||||
|
||||
async confirmDelete() {
|
||||
const confirmed = await this.map.dialog.confirm(
|
||||
const confirmed = await this.umap.dialog.confirm(
|
||||
translate('Are you sure you want to delete the feature?')
|
||||
)
|
||||
if (confirmed) {
|
||||
|
@ -359,7 +359,7 @@ class Feature {
|
|||
|
||||
del(sync) {
|
||||
this.isDirty = true
|
||||
this.map.closePopup()
|
||||
this.umap._leafletMap.closePopup()
|
||||
if (this.datalayer) {
|
||||
this.datalayer.removeFeature(this, sync)
|
||||
}
|
||||
|
@ -422,7 +422,7 @@ class Feature {
|
|||
} else if (this.datalayer) {
|
||||
value = this.datalayer.getOption(option, this)
|
||||
} else {
|
||||
value = this.map.getOption(option)
|
||||
value = this.umap.getOption(option)
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
@ -432,19 +432,19 @@ class Feature {
|
|||
// There is a variable inside.
|
||||
if (U.Utils.hasVar(value)) {
|
||||
value = U.Utils.greedyTemplate(value, this.properties, true)
|
||||
if (U.Utils.hasVar(value)) value = this.map.getDefaultOption(option)
|
||||
if (U.Utils.hasVar(value)) value = this.umap.getDefaultOption(option)
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
zoomTo({ easing, latlng, callback } = {}) {
|
||||
if (easing === undefined) easing = this.map.getOption('easing')
|
||||
if (callback) this.map.once('moveend', callback.bind(this))
|
||||
if (easing === undefined) easing = this.umap.getOption('easing')
|
||||
if (callback) this.umap._leafletMap.once('moveend', callback.bind(this))
|
||||
if (easing) {
|
||||
this.map.flyTo(this.center, this.getBestZoom())
|
||||
this.umap._leafletMap.flyTo(this.center, this.getBestZoom())
|
||||
} else {
|
||||
latlng = latlng || this.center
|
||||
this.map.setView(latlng, this.getBestZoom() || this.map.getZoom())
|
||||
this.umap._leafletMap.setView(latlng, this.getBestZoom() || this.umap._leafletMap.getZoom())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -500,7 +500,7 @@ class Feature {
|
|||
|
||||
isFiltered() {
|
||||
const filterKeys = this.datalayer.getFilterKeys()
|
||||
const filter = this.map.browser.options.filter
|
||||
const filter = this.umap.browser.options.filter
|
||||
if (filter && !this.matchFilter(filter, filterKeys)) return true
|
||||
if (!this.matchFacets()) return true
|
||||
return false
|
||||
|
@ -525,10 +525,10 @@ class Feature {
|
|||
}
|
||||
|
||||
matchFacets() {
|
||||
const selected = this.map.facets.selected
|
||||
const selected = this.umap.facets.selected
|
||||
for (const [name, { type, min, max, choices }] of Object.entries(selected)) {
|
||||
let value = this.properties[name]
|
||||
const parser = this.map.facets.getParser(type)
|
||||
const parser = this.umap.facets.getParser(type)
|
||||
value = parser(value)
|
||||
switch (type) {
|
||||
case 'date':
|
||||
|
@ -562,10 +562,10 @@ class Feature {
|
|||
|
||||
extendedProperties() {
|
||||
// Include context properties
|
||||
const properties = this.map.getGeoContext()
|
||||
const properties = this.umap.getGeoContext()
|
||||
const locale = L.getLocale()
|
||||
if (locale) properties.locale = locale
|
||||
if (L.lang) properties.lang = L.lang
|
||||
if (U.lang) properties.lang = U.lang
|
||||
properties.rank = this.getRank() + 1
|
||||
properties.layer = this.datalayer.getName()
|
||||
if (this.ui._map && this.hasGeom()) {
|
||||
|
@ -612,10 +612,10 @@ class Feature {
|
|||
label: translate('Copy as GeoJSON'),
|
||||
action: () => {
|
||||
L.Util.copyToClipboard(JSON.stringify(this.toGeoJSON()))
|
||||
this.map.tooltip.open({ content: L._('✅ Copied!') })
|
||||
this.umap.tooltip.open({ content: L._('✅ Copied!') })
|
||||
},
|
||||
})
|
||||
if (this.map.editEnabled && !this.isReadOnly()) {
|
||||
if (this.umap.editEnabled && !this.isReadOnly()) {
|
||||
items = items.concat(this.getContextMenuEditItems(event))
|
||||
}
|
||||
return items
|
||||
|
@ -623,7 +623,7 @@ class Feature {
|
|||
|
||||
getContextMenuEditItems() {
|
||||
let items = ['-']
|
||||
if (this.map.editedFeature !== this) {
|
||||
if (this.umap.editedFeature !== this) {
|
||||
items.push({
|
||||
label: `${translate('Edit this feature')} (⇧+Click)`,
|
||||
action: () => this.edit(),
|
||||
|
@ -631,7 +631,7 @@ class Feature {
|
|||
}
|
||||
items = items.concat(
|
||||
{
|
||||
label: this.map.help.displayLabel('EDIT_FEATURE_LAYER'),
|
||||
label: this.umap.help.displayLabel('EDIT_FEATURE_LAYER'),
|
||||
action: () => this.datalayer.edit(),
|
||||
},
|
||||
{
|
||||
|
@ -750,17 +750,17 @@ class Path extends Feature {
|
|||
}
|
||||
|
||||
edit(event) {
|
||||
if (this.map.editEnabled) {
|
||||
if (this.umap.editEnabled) {
|
||||
super.edit(event)
|
||||
if (!this.ui.editEnabled()) this.ui.makeGeometryEditable()
|
||||
}
|
||||
}
|
||||
|
||||
_toggleEditing(event) {
|
||||
if (this.map.editEnabled) {
|
||||
if (this.umap.editEnabled) {
|
||||
if (this.ui.editEnabled()) {
|
||||
this.endEdit()
|
||||
this.map.editPanel.close()
|
||||
this.umap.editPanel.close()
|
||||
} else {
|
||||
this.edit(event)
|
||||
}
|
||||
|
@ -786,7 +786,9 @@ class Path extends Feature {
|
|||
}
|
||||
|
||||
getBestZoom() {
|
||||
return this.getOption('zoomTo') || this.map.getBoundsZoom(this.bounds, true)
|
||||
return (
|
||||
this.getOption('zoomTo') || this.umap._leafletMap.getBoundsZoom(this.bounds, true)
|
||||
)
|
||||
}
|
||||
|
||||
endEdit() {
|
||||
|
@ -825,11 +827,14 @@ class Path extends Feature {
|
|||
|
||||
zoomTo({ easing, callback }) {
|
||||
// Use bounds instead of centroid for paths.
|
||||
easing = easing || this.map.getOption('easing')
|
||||
easing = easing || this.umap.getOption('easing')
|
||||
if (easing) {
|
||||
this.map.flyToBounds(this.bounds, this.getBestZoom())
|
||||
this.umap._leafletMap.flyToBounds(this.bounds, this.getBestZoom())
|
||||
} else {
|
||||
this.map.fitBounds(this.bounds, this.getBestZoom() || this.map.getZoom())
|
||||
this.umap._leafletMap.fitBounds(
|
||||
this.bounds,
|
||||
this.getBestZoom() || this.umap._leafletMap.getZoom()
|
||||
)
|
||||
}
|
||||
if (callback) callback.call(this)
|
||||
}
|
||||
|
@ -840,7 +845,7 @@ class Path extends Feature {
|
|||
label: translate('Display measure'),
|
||||
action: () => Alert.info(this.ui.getMeasure()),
|
||||
})
|
||||
if (this.map.editEnabled && !this.isReadOnly() && this.isMulti()) {
|
||||
if (this.umap.editEnabled && !this.isReadOnly() && this.isMulti()) {
|
||||
items.push(...this.getContextMenuMultiItems(event))
|
||||
}
|
||||
return items
|
||||
|
@ -871,11 +876,11 @@ class Path extends Feature {
|
|||
|
||||
getContextMenuEditItems(event) {
|
||||
const items = super.getContextMenuEditItems(event)
|
||||
if (this.map?.editedFeature !== this && this.isSameClass(this.map.editedFeature)) {
|
||||
if (this.map?.editedFeature !== this && this.isSameClass(this.umap.editedFeature)) {
|
||||
items.push({
|
||||
label: translate('Transfer shape to edited feature'),
|
||||
action: () => {
|
||||
this.transferShape(event.latlng, this.map.editedFeature)
|
||||
this.transferShape(event.latlng, this.umap.editedFeature)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
@ -977,8 +982,8 @@ export class LineString extends Path {
|
|||
}
|
||||
const a = toMerge[0]
|
||||
const b = toMerge[1]
|
||||
const p1 = this.map.latLngToContainerPoint(a[a.length - 1])
|
||||
const p2 = this.map.latLngToContainerPoint(b[0])
|
||||
const p1 = this.umap._leafletMap.latLngToContainerPoint(a[a.length - 1])
|
||||
const p2 = this.umap._leafletMap.latLngToContainerPoint(b[0])
|
||||
const tolerance = 5 // px on screen
|
||||
if (Math.abs(p1.x - p2.x) <= tolerance && Math.abs(p1.y - p2.y) <= tolerance) {
|
||||
a.pop()
|
||||
|
@ -1022,7 +1027,7 @@ export class LineString extends Path {
|
|||
})
|
||||
} else if (index === 0 || index === event.vertex.getLastIndex()) {
|
||||
items.push({
|
||||
label: this.map.help.displayLabel('CONTINUE_LINE'),
|
||||
label: this.umap.help.displayLabel('CONTINUE_LINE'),
|
||||
action: () => event.vertex.continue(),
|
||||
})
|
||||
}
|
||||
|
|
|
@ -37,10 +37,10 @@ const LAYER_MAP = LAYER_TYPES.reduce((acc, klass) => {
|
|||
}, {})
|
||||
|
||||
export class DataLayer extends ServerStored {
|
||||
constructor(map, data) {
|
||||
constructor(umap, data) {
|
||||
super()
|
||||
this.map = map
|
||||
this.sync = map.sync_engine.proxy(this)
|
||||
this.umap = umap
|
||||
this.sync = umap.sync_engine.proxy(this)
|
||||
this._index = Array()
|
||||
this._features = {}
|
||||
this._geojson = null
|
||||
|
@ -48,8 +48,11 @@ export class DataLayer extends ServerStored {
|
|||
this._loaded = false // Are layer metadata loaded
|
||||
this._dataloaded = false // Are layer data loaded
|
||||
|
||||
this.parentPane = this.map.getPane('overlayPane')
|
||||
this.pane = this.map.createPane(`datalayer${stamp(this)}`, this.parentPane)
|
||||
this.parentPane = this.umap._leafletMap.getPane('overlayPane')
|
||||
this.pane = this.umap._leafletMap.createPane(
|
||||
`datalayer${stamp(this)}`,
|
||||
this.parentPane
|
||||
)
|
||||
this.pane.dataset.id = stamp(this)
|
||||
// FIXME: should be on layer
|
||||
this.renderer = L.svg({ pane: this.pane })
|
||||
|
@ -128,7 +131,7 @@ export class DataLayer extends ServerStored {
|
|||
for (const impact of impacts) {
|
||||
switch (impact) {
|
||||
case 'ui':
|
||||
this.map.onDataLayersChanged()
|
||||
this.umap.onDataLayersChanged()
|
||||
break
|
||||
case 'data':
|
||||
if (fields.includes('options.type')) {
|
||||
|
@ -153,8 +156,8 @@ export class DataLayer extends ServerStored {
|
|||
}
|
||||
|
||||
autoLoaded() {
|
||||
if (!this.map.datalayersFromQueryString) return this.options.displayOnLoad
|
||||
const datalayerIds = this.map.datalayersFromQueryString
|
||||
if (!this.umap.datalayersFromQueryString) return this.options.displayOnLoad
|
||||
const datalayerIds = this.umap.datalayersFromQueryString
|
||||
let loadMe = datalayerIds.includes(this.umap_id.toString())
|
||||
if (this.options.old_id) {
|
||||
loadMe = loadMe || datalayerIds.includes(this.options.old_id.toString())
|
||||
|
@ -192,7 +195,7 @@ export class DataLayer extends ServerStored {
|
|||
const visible = this.isVisible()
|
||||
if (this.layer) this.layer.clearLayers()
|
||||
// delete this.layer?
|
||||
if (visible) this.map.removeLayer(this.layer)
|
||||
if (visible) this.umap._leafletMap.removeLayer(this.layer)
|
||||
const Class = LAYER_MAP[this.options.type] || DefaultLayer
|
||||
this.layer = new Class(this)
|
||||
// Rendering layer changed, so let's force reset the feature rendering too.
|
||||
|
@ -213,7 +216,7 @@ export class DataLayer extends ServerStored {
|
|||
if (!this.umap_id) return
|
||||
if (this._loading) return
|
||||
this._loading = true
|
||||
const [geojson, response, error] = await this.map.server.get(this._dataUrl())
|
||||
const [geojson, response, error] = await this.umap.server.get(this._dataUrl())
|
||||
if (!error) {
|
||||
this._reference_version = response.headers.get('X-Datalayer-Version')
|
||||
// FIXME: for now this property is set dynamically from backend
|
||||
|
@ -234,7 +237,7 @@ export class DataLayer extends ServerStored {
|
|||
|
||||
dataChanged() {
|
||||
if (!this.hasDataLoaded()) return
|
||||
this.map.onDataLayersChanged()
|
||||
this.umap.onDataLayersChanged()
|
||||
this.layer.dataChanged()
|
||||
}
|
||||
|
||||
|
@ -275,14 +278,14 @@ export class DataLayer extends ServerStored {
|
|||
|
||||
reindex() {
|
||||
const features = Object.values(this._features)
|
||||
Utils.sortFeatures(features, this.map.getOption('sortKey'), L.lang)
|
||||
Utils.sortFeatures(features, this.umap.getOption('sortKey'), U.lang)
|
||||
this._index = features.map((feature) => stamp(feature))
|
||||
}
|
||||
|
||||
showAtZoom() {
|
||||
const from = Number.parseInt(this.options.fromZoom, 10)
|
||||
const to = Number.parseInt(this.options.toZoom, 10)
|
||||
const zoom = this.map.getZoom()
|
||||
const zoom = this.umap._leafletMap.getZoom()
|
||||
return !((!Number.isNaN(from) && zoom < from) || (!Number.isNaN(to) && zoom > to))
|
||||
}
|
||||
|
||||
|
@ -294,14 +297,14 @@ export class DataLayer extends ServerStored {
|
|||
if (!this.isRemoteLayer()) return
|
||||
if (!this.hasDynamicData() && this.hasDataLoaded() && !force) return
|
||||
if (!this.isVisible()) return
|
||||
let url = this.map.localizeUrl(this.options.remoteData.url)
|
||||
let url = this.umap.localizeUrl(this.options.remoteData.url)
|
||||
if (this.options.remoteData.proxy) {
|
||||
url = this.map.proxyUrl(url, this.options.remoteData.ttl)
|
||||
url = this.umap.proxyUrl(url, this.options.remoteData.ttl)
|
||||
}
|
||||
const response = await this.map.request.get(url)
|
||||
const response = await this.umap.request.get(url)
|
||||
if (response?.ok) {
|
||||
this.clear()
|
||||
this.map.formatter
|
||||
this.umap.formatter
|
||||
.parse(await response.text(), this.options.remoteData.format)
|
||||
.then((geojson) => this.fromGeoJSON(geojson))
|
||||
}
|
||||
|
@ -341,25 +344,23 @@ export class DataLayer extends ServerStored {
|
|||
|
||||
connectToMap() {
|
||||
const id = stamp(this)
|
||||
if (!this.map.datalayers[id]) {
|
||||
this.map.datalayers[id] = this
|
||||
if (!this.umap.datalayers[id]) {
|
||||
this.umap.datalayers[id] = this
|
||||
}
|
||||
if (!this.map.datalayers_index.includes(this)) {
|
||||
this.map.datalayers_index.push(this)
|
||||
if (!this.umap.datalayersIndex.includes(this)) {
|
||||
this.umap.datalayersIndex.push(this)
|
||||
}
|
||||
this.map.onDataLayersChanged()
|
||||
this.umap.onDataLayersChanged()
|
||||
}
|
||||
|
||||
_dataUrl() {
|
||||
const template = this.map.options.urls.datalayer_view
|
||||
|
||||
let url = Utils.template(template, {
|
||||
let url = this.umap.urls.get('datalayer_view', {
|
||||
pk: this.umap_id,
|
||||
map_id: this.map.options.umap_id,
|
||||
map_id: this.umap.properties.umap_id,
|
||||
})
|
||||
|
||||
// No browser cache for owners/editors.
|
||||
if (this.map.hasEditMode()) url = `${url}?${Date.now()}`
|
||||
if (this.umap.hasEditMode()) url = `${url}?${Date.now()}`
|
||||
return url
|
||||
}
|
||||
|
||||
|
@ -386,7 +387,7 @@ export class DataLayer extends ServerStored {
|
|||
this._index.push(id)
|
||||
this._features[id] = feature
|
||||
this.indexProperties(feature)
|
||||
this.map.features_index[feature.getSlug()] = feature
|
||||
this.umap.featuresIndex[feature.getSlug()] = feature
|
||||
this.showFeature(feature)
|
||||
this.dataChanged()
|
||||
}
|
||||
|
@ -395,7 +396,7 @@ export class DataLayer extends ServerStored {
|
|||
const id = stamp(feature)
|
||||
if (sync !== false) feature.sync.delete()
|
||||
this.hideFeature(feature)
|
||||
delete this.map.features_index[feature.getSlug()]
|
||||
delete this.umap.featuresIndex[feature.getSlug()]
|
||||
feature.disconnectFromDataLayer(this)
|
||||
this._index.splice(this._index.indexOf(id), 1)
|
||||
delete this._features[id]
|
||||
|
@ -446,7 +447,8 @@ export class DataLayer extends ServerStored {
|
|||
const collection = Array.isArray(geojson)
|
||||
? geojson
|
||||
: geojson.features || geojson.geometries
|
||||
Utils.sortFeatures(collection, this.map.getOption('sortKey'), L.lang)
|
||||
if (!collection) return
|
||||
Utils.sortFeatures(collection, this.umap.getOption('sortKey'), U.lang)
|
||||
for (const feature of collection) {
|
||||
this.makeFeature(feature, sync)
|
||||
}
|
||||
|
@ -486,7 +488,7 @@ export class DataLayer extends ServerStored {
|
|||
}
|
||||
|
||||
async importRaw(raw, format) {
|
||||
this.map.formatter
|
||||
this.umap.formatter
|
||||
.parse(raw, format)
|
||||
.then((geojson) => this.addData(geojson))
|
||||
.then(() => this.zoomTo())
|
||||
|
@ -507,35 +509,35 @@ export class DataLayer extends ServerStored {
|
|||
}
|
||||
|
||||
async importFromUrl(uri, type) {
|
||||
uri = this.map.localizeUrl(uri)
|
||||
const response = await this.map.request.get(uri)
|
||||
uri = this.umap.localizeUrl(uri)
|
||||
const response = await this.umap.request.get(uri)
|
||||
if (response?.ok) {
|
||||
this.importRaw(await response.text(), type)
|
||||
}
|
||||
}
|
||||
|
||||
getColor() {
|
||||
return this.options.color || this.map.getOption('color')
|
||||
return this.options.color || this.umap.getOption('color')
|
||||
}
|
||||
|
||||
getDeleteUrl() {
|
||||
return Utils.template(this.map.options.urls.datalayer_delete, {
|
||||
return this.umap.urls.get('datalayer_delete', {
|
||||
pk: this.umap_id,
|
||||
map_id: this.map.options.umap_id,
|
||||
map_id: this.umap.properties.umap_id,
|
||||
})
|
||||
}
|
||||
|
||||
getVersionsUrl() {
|
||||
return Utils.template(this.map.options.urls.datalayer_versions, {
|
||||
return this.umap.urls.get('datalayer_versions', {
|
||||
pk: this.umap_id,
|
||||
map_id: this.map.options.umap_id,
|
||||
map_id: this.umap.properties.umap_id,
|
||||
})
|
||||
}
|
||||
|
||||
getVersionUrl(name) {
|
||||
return Utils.template(this.map.options.urls.datalayer_version, {
|
||||
return this.umap.urls.get('datalayer_version', {
|
||||
pk: this.umap_id,
|
||||
map_id: this.map.options.umap_id,
|
||||
map_id: this.umap.properties.umap_id,
|
||||
name: name,
|
||||
})
|
||||
}
|
||||
|
@ -556,17 +558,17 @@ export class DataLayer extends ServerStored {
|
|||
options.name = translate('Clone of {name}', { name: this.options.name })
|
||||
delete options.id
|
||||
const geojson = Utils.CopyJSON(this._geojson)
|
||||
const datalayer = this.map.createDataLayer(options)
|
||||
const datalayer = this.umap.createDataLayer(options)
|
||||
datalayer.fromGeoJSON(geojson)
|
||||
return datalayer
|
||||
}
|
||||
|
||||
erase() {
|
||||
this.hide()
|
||||
this.map.datalayers_index.splice(this.getRank(), 1)
|
||||
this.umap.datalayersIndex.splice(this.getRank(), 1)
|
||||
this.parentPane.removeChild(this.pane)
|
||||
this.map.onDataLayersChanged()
|
||||
this.layer.onDelete(this.map)
|
||||
this.umap.onDataLayersChanged()
|
||||
this.layer.onDelete(this.umap._leafletMap)
|
||||
this.propagateDelete()
|
||||
this._leaflet_events_bk = this._leaflet_events
|
||||
this.clear()
|
||||
|
@ -597,7 +599,7 @@ export class DataLayer extends ServerStored {
|
|||
}
|
||||
|
||||
edit() {
|
||||
if (!this.map.editEnabled || !this.isLoaded()) {
|
||||
if (!this.umap.editEnabled || !this.isLoaded()) {
|
||||
return
|
||||
}
|
||||
const container = DomUtil.create('div', 'umap-layer-properties-container')
|
||||
|
@ -631,7 +633,7 @@ export class DataLayer extends ServerStored {
|
|||
DomUtil.createTitle(container, translate('Layer properties'), 'icon-layers')
|
||||
let builder = new U.FormBuilder(this, metadataFields, {
|
||||
callback(e) {
|
||||
this.map.onDataLayersChanged()
|
||||
this.umap.onDataLayersChanged()
|
||||
if (e.helper.field === 'options.type') {
|
||||
this.edit()
|
||||
}
|
||||
|
@ -742,7 +744,7 @@ export class DataLayer extends ServerStored {
|
|||
},
|
||||
],
|
||||
]
|
||||
if (this.map.options.urls.ajax_proxy) {
|
||||
if (this.umap.properties.urls.ajax_proxy) {
|
||||
remoteDataFields.push([
|
||||
'options.remoteData.proxy',
|
||||
{
|
||||
|
@ -768,7 +770,8 @@ export class DataLayer extends ServerStored {
|
|||
this
|
||||
)
|
||||
|
||||
if (this.map.options.urls.datalayer_versions) this.buildVersionsFieldset(container)
|
||||
if (this.umap.properties.urls.datalayer_versions)
|
||||
this.buildVersionsFieldset(container)
|
||||
|
||||
const advancedActions = DomUtil.createFieldset(
|
||||
container,
|
||||
|
@ -781,7 +784,7 @@ export class DataLayer extends ServerStored {
|
|||
</button>`)
|
||||
deleteButton.addEventListener('click', () => {
|
||||
this._delete()
|
||||
this.map.editPanel.close()
|
||||
this.umap.editPanel.close()
|
||||
})
|
||||
advancedButtons.appendChild(deleteButton)
|
||||
|
||||
|
@ -820,9 +823,9 @@ export class DataLayer extends ServerStored {
|
|||
// Fixme: remove me when this is merged and released
|
||||
// https://github.com/Leaflet/Leaflet/pull/9052
|
||||
DomEvent.disableClickPropagation(backButton)
|
||||
DomEvent.on(backButton, 'click', this.map.editDatalayers, this.map)
|
||||
DomEvent.on(backButton, 'click', this.umap.editDatalayers, this.umap)
|
||||
|
||||
this.map.editPanel.open({
|
||||
this.umap.editPanel.open({
|
||||
content: container,
|
||||
actions: [backButton],
|
||||
})
|
||||
|
@ -843,13 +846,13 @@ export class DataLayer extends ServerStored {
|
|||
if (this.layer?.defaults?.[option]) {
|
||||
return this.layer.defaults[option]
|
||||
}
|
||||
return this.map.getOption(option, feature)
|
||||
return this.umap.getOption(option, feature)
|
||||
}
|
||||
|
||||
async buildVersionsFieldset(container) {
|
||||
const appendVersion = (data) => {
|
||||
const date = new Date(Number.parseInt(data.at, 10))
|
||||
const content = `${date.toLocaleString(L.lang)} (${Number.parseInt(data.size) / 1000}Kb)`
|
||||
const content = `${date.toLocaleString(U.lang)} (${Number.parseInt(data.size) / 1000}Kb)`
|
||||
const el = DomUtil.create('div', 'umap-datalayer-version', versionsContainer)
|
||||
const button = DomUtil.createButton(
|
||||
'',
|
||||
|
@ -864,7 +867,7 @@ export class DataLayer extends ServerStored {
|
|||
|
||||
const versionsContainer = DomUtil.createFieldset(container, translate('Versions'), {
|
||||
async callback() {
|
||||
const [{ versions }, response, error] = await this.map.server.get(
|
||||
const [{ versions }, response, error] = await this.umap.server.get(
|
||||
this.getVersionsUrl()
|
||||
)
|
||||
if (!error) versions.forEach(appendVersion)
|
||||
|
@ -874,11 +877,11 @@ export class DataLayer extends ServerStored {
|
|||
}
|
||||
|
||||
async restore(version) {
|
||||
if (!this.map.editEnabled) return
|
||||
this.map.dialog
|
||||
if (!this.umap.editEnabled) return
|
||||
this.umap.dialog
|
||||
.confirm(translate('Are you sure you want to restore this version?'))
|
||||
.then(async () => {
|
||||
const [geojson, response, error] = await this.map.server.get(
|
||||
const [geojson, response, error] = await this.umap.server.get(
|
||||
this.getVersionUrl(version)
|
||||
)
|
||||
if (!error) {
|
||||
|
@ -899,13 +902,13 @@ export class DataLayer extends ServerStored {
|
|||
}
|
||||
|
||||
async show() {
|
||||
this.map.addLayer(this.layer)
|
||||
this.umap._leafletMap.addLayer(this.layer)
|
||||
if (!this.isLoaded()) await this.fetchData()
|
||||
this.propagateShow()
|
||||
}
|
||||
|
||||
hide() {
|
||||
this.map.removeLayer(this.layer)
|
||||
this.umap._leafletMap.removeLayer(this.layer)
|
||||
this.propagateHide()
|
||||
}
|
||||
|
||||
|
@ -922,7 +925,7 @@ export class DataLayer extends ServerStored {
|
|||
const bounds = this.layer.getBounds()
|
||||
if (bounds.isValid()) {
|
||||
const options = { maxZoom: this.getOption('zoomTo') }
|
||||
this.map.fitBounds(bounds, options)
|
||||
this.umap._leafletMap.fitBounds(bounds, options)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -953,7 +956,7 @@ export class DataLayer extends ServerStored {
|
|||
}
|
||||
|
||||
isVisible() {
|
||||
return Boolean(this.layer && this.map.hasLayer(this.layer))
|
||||
return Boolean(this.layer && this.umap._leafletMap.hasLayer(this.layer))
|
||||
}
|
||||
|
||||
getFeatureByIndex(index) {
|
||||
|
@ -990,7 +993,7 @@ export class DataLayer extends ServerStored {
|
|||
getPreviousBrowsable() {
|
||||
let id = this.getRank()
|
||||
let next
|
||||
const index = this.map.datalayers_index
|
||||
const index = this.umap.datalayersIndex
|
||||
while (((id = index[++id] ? id : 0), (next = index[id]))) {
|
||||
if (next === this || next.canBrowse()) break
|
||||
}
|
||||
|
@ -1000,7 +1003,7 @@ export class DataLayer extends ServerStored {
|
|||
getNextBrowsable() {
|
||||
let id = this.getRank()
|
||||
let prev
|
||||
const index = this.map.datalayers_index
|
||||
const index = this.umap.datalayersIndex
|
||||
while (((id = index[--id] ? id : index.length - 1), (prev = index[id]))) {
|
||||
if (prev === this || prev.canBrowse()) break
|
||||
}
|
||||
|
@ -1016,7 +1019,7 @@ export class DataLayer extends ServerStored {
|
|||
}
|
||||
|
||||
getRank() {
|
||||
return this.map.datalayers_index.indexOf(this)
|
||||
return this.umap.datalayersIndex.indexOf(this)
|
||||
}
|
||||
|
||||
isReadOnly() {
|
||||
|
@ -1043,8 +1046,8 @@ export class DataLayer extends ServerStored {
|
|||
// Filename support is shaky, don't do it for now.
|
||||
const blob = new Blob([JSON.stringify(geojson)], { type: 'application/json' })
|
||||
formData.append('geojson', blob)
|
||||
const saveUrl = this.map.urls.get('datalayer_save', {
|
||||
map_id: this.map.options.umap_id,
|
||||
const saveUrl = this.umap.urls.get('datalayer_save', {
|
||||
map_id: this.umap.properties.umap_id,
|
||||
pk: this.umap_id,
|
||||
})
|
||||
const headers = this._reference_version
|
||||
|
@ -1056,7 +1059,7 @@ export class DataLayer extends ServerStored {
|
|||
}
|
||||
|
||||
async _trySave(url, headers, formData) {
|
||||
const [data, response, error] = await this.map.server.post(url, headers, formData)
|
||||
const [data, response, error] = await this.umap.server.post(url, headers, formData)
|
||||
if (error) {
|
||||
if (response && response.status === 412) {
|
||||
AlertConflict.error(
|
||||
|
@ -1072,7 +1075,7 @@ export class DataLayer extends ServerStored {
|
|||
|
||||
// Call the main save, in case something else needs to be saved
|
||||
// as the conflict stopped the saving flow
|
||||
await this.map.saveAll()
|
||||
await this.umap.saveAll()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
@ -1101,9 +1104,9 @@ export class DataLayer extends ServerStored {
|
|||
|
||||
async saveDelete() {
|
||||
if (this.umap_id) {
|
||||
await this.map.server.post(this.getDeleteUrl())
|
||||
await this.umap.server.post(this.getDeleteUrl())
|
||||
}
|
||||
delete this.map.datalayers[stamp(this)]
|
||||
delete this.umap.datalayers[stamp(this)]
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -1125,9 +1128,9 @@ export class DataLayer extends ServerStored {
|
|||
// This keys will be used to filter feature from the browser text input.
|
||||
// By default, it will we use the "name" property, which is also the one used as label in the features list.
|
||||
// When map owner has configured another label or sort key, we try to be smart and search in the same keys.
|
||||
if (this.map.options.filterKey) return this.map.options.filterKey
|
||||
if (this.umap.properties.filterKey) return this.umap.properties.filterKey
|
||||
if (this.getOption('labelKey')) return this.getOption('labelKey')
|
||||
if (this.map.options.sortKey) return this.map.options.sortKey
|
||||
if (this.umap.properties.sortKey) return this.umap.properties.sortKey
|
||||
return 'displayName'
|
||||
}
|
||||
|
||||
|
@ -1178,7 +1181,7 @@ export class DataLayer extends ServerStored {
|
|||
'click',
|
||||
function () {
|
||||
if (!this.isVisible()) return
|
||||
this.map.dialog
|
||||
this.umap.dialog
|
||||
.confirm(translate('Are you sure you want to delete this layer?'))
|
||||
.then(() => {
|
||||
this._delete()
|
||||
|
|
|
@ -3,8 +3,8 @@ import { translate } from './i18n.js'
|
|||
import * as Utils from './utils.js'
|
||||
|
||||
export default class Facets {
|
||||
constructor(map) {
|
||||
this.map = map
|
||||
constructor(umap) {
|
||||
this.umap = umap
|
||||
this.selected = {}
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ export default class Facets {
|
|||
this.selected[name] = selected
|
||||
}
|
||||
|
||||
this.map.eachBrowsableDataLayer((datalayer) => {
|
||||
this.umap.eachBrowsableDataLayer((datalayer) => {
|
||||
datalayer.eachFeature((feature) => {
|
||||
for (const name of names) {
|
||||
let value = feature.properties[name]
|
||||
|
@ -108,8 +108,8 @@ export default class Facets {
|
|||
const defaultType = 'checkbox'
|
||||
const allowedTypes = [defaultType, 'radio', 'number', 'date', 'datetime']
|
||||
const defined = new Map()
|
||||
if (!this.map.options.facetKey) return defined
|
||||
return (this.map.options.facetKey || '').split(',').reduce((acc, curr) => {
|
||||
if (!this.umap.properties.facetKey) return defined
|
||||
return (this.umap.properties.facetKey || '').split(',').reduce((acc, curr) => {
|
||||
let [name, label, type] = curr.split('|')
|
||||
type = allowedTypes.includes(type) ? type : defaultType
|
||||
acc.set(name, { label: label || name, type: type })
|
||||
|
@ -146,15 +146,15 @@ export default class Facets {
|
|||
const defined = this.getDefined()
|
||||
if (!defined.has(property)) {
|
||||
defined.set(property, { label, type })
|
||||
this.map.options.facetKey = this.dumps(defined)
|
||||
this.map.isDirty = true
|
||||
this.umap.properties.facetKey = this.dumps(defined)
|
||||
this.umap.isDirty = true
|
||||
}
|
||||
}
|
||||
|
||||
remove(property) {
|
||||
const defined = this.getDefined()
|
||||
defined.delete(property)
|
||||
this.map.options.facetKey = this.dumps(defined)
|
||||
this.map.isDirty = true
|
||||
this.umap.properties.facetKey = this.dumps(defined)
|
||||
this.umap.isDirty = true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,24 +3,24 @@ import { translate } from './i18n.js'
|
|||
|
||||
export const EXPORT_FORMATS = {
|
||||
geojson: {
|
||||
formatter: async (map) => JSON.stringify(map.toGeoJSON(), null, 2),
|
||||
formatter: async (umap) => JSON.stringify(umap.toGeoJSON(), null, 2),
|
||||
ext: '.geojson',
|
||||
filetype: 'application/json',
|
||||
},
|
||||
gpx: {
|
||||
formatter: async (map) => await map.formatter.toGPX(map.toGeoJSON()),
|
||||
formatter: async (umap) => await umap.formatter.toGPX(umap.toGeoJSON()),
|
||||
ext: '.gpx',
|
||||
filetype: 'application/gpx+xml',
|
||||
},
|
||||
kml: {
|
||||
formatter: async (map) => await map.formatter.toKML(map.toGeoJSON()),
|
||||
formatter: async (umap) => await umap.formatter.toKML(umap.toGeoJSON()),
|
||||
ext: '.kml',
|
||||
filetype: 'application/vnd.google-earth.kml+xml',
|
||||
},
|
||||
csv: {
|
||||
formatter: async (map) => {
|
||||
formatter: async (umap) => {
|
||||
const table = []
|
||||
map.eachFeature((feature) => {
|
||||
umap.eachFeature((feature) => {
|
||||
const row = feature.toGeoJSON().properties
|
||||
const center = feature.center
|
||||
delete row._umap_options
|
||||
|
|
|
@ -48,8 +48,8 @@ const TEMPLATE = `
|
|||
`
|
||||
|
||||
export default class Importer {
|
||||
constructor(map) {
|
||||
this.map = map
|
||||
constructor(umap) {
|
||||
this.umap = umap
|
||||
this.TYPES = ['geojson', 'csv', 'gpx', 'kml', 'osm', 'georss', 'umap']
|
||||
this.IMPORTERS = []
|
||||
this.loadImporters()
|
||||
|
@ -57,9 +57,9 @@ export default class Importer {
|
|||
}
|
||||
|
||||
loadImporters() {
|
||||
for (const [name, config] of Object.entries(this.map.options.importers || {})) {
|
||||
for (const [name, config] of Object.entries(this.umap.properties.importers || {})) {
|
||||
const register = (mod) => {
|
||||
this.IMPORTERS.push(new mod.Importer(this.map, config))
|
||||
this.IMPORTERS.push(new mod.Importer(this.umap, config))
|
||||
}
|
||||
// We need to have explicit static paths for Django's collectstatic with hashes.
|
||||
switch (name) {
|
||||
|
@ -139,8 +139,8 @@ export default class Importer {
|
|||
|
||||
get layer() {
|
||||
return (
|
||||
this.map.datalayers[this.layerId] ||
|
||||
this.map.createDataLayer({ name: this.layerName })
|
||||
this.umap.datalayers[this.layerId] ||
|
||||
this.umap.createDataLayer({ name: this.layerName })
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -167,7 +167,7 @@ export default class Importer {
|
|||
textContent: type,
|
||||
})
|
||||
}
|
||||
this.map.help.parse(this.container)
|
||||
this.umap.help.parse(this.container)
|
||||
DomEvent.on(this.qs('[name=submit]'), 'click', this.submit, this)
|
||||
DomEvent.on(this.qs('[type=file]'), 'change', this.onFileChange, this)
|
||||
for (const element of this.container.querySelectorAll('[onchange]')) {
|
||||
|
@ -206,7 +206,7 @@ export default class Importer {
|
|||
this.layerName = null
|
||||
const layerSelect = this.qs('[name="layer-id"]')
|
||||
layerSelect.innerHTML = ''
|
||||
this.map.eachDataLayerReverse((datalayer) => {
|
||||
this.umap.eachDataLayerReverse((datalayer) => {
|
||||
if (datalayer.isLoaded() && !datalayer.isRemoteLayer()) {
|
||||
DomUtil.element({
|
||||
tagName: 'option',
|
||||
|
@ -227,7 +227,7 @@ export default class Importer {
|
|||
|
||||
open() {
|
||||
if (!this.container) this.build()
|
||||
const onLoad = this.map.editPanel.open({ content: this.container })
|
||||
const onLoad = this.umap.editPanel.open({ content: this.container })
|
||||
onLoad.then(() => this.onLoad())
|
||||
}
|
||||
|
||||
|
@ -251,16 +251,16 @@ export default class Importer {
|
|||
}
|
||||
|
||||
full() {
|
||||
this.map.once('postsync', this.map._setDefaultCenter)
|
||||
this.umap._leafletMap.once('postsync', this.umap._leafletMap._setDefaultCenter)
|
||||
try {
|
||||
if (this.files.length) {
|
||||
for (const file of this.files) {
|
||||
this.map.processFileToImport(file, null, 'umap')
|
||||
this.umap.processFileToImport(file, null, 'umap')
|
||||
}
|
||||
} else if (this.raw) {
|
||||
this.map.importRaw(this.raw)
|
||||
this.umap.importRaw(this.raw)
|
||||
} else if (this.url) {
|
||||
this.map.importFromUrl(this.url, this.format)
|
||||
this.umap.importFromUrl(this.url, this.format)
|
||||
}
|
||||
} catch (e) {
|
||||
Alert.error(translate('Invalid umap data'))
|
||||
|
@ -282,7 +282,7 @@ export default class Importer {
|
|||
url: this.url,
|
||||
format: this.format,
|
||||
}
|
||||
if (this.map.options.urls.ajax_proxy) {
|
||||
if (this.umap.properties.urls.ajax_proxy) {
|
||||
layer.options.remoteData.proxy = true
|
||||
layer.options.remoteData.ttl = SCHEMA.ttl.default
|
||||
}
|
||||
|
@ -300,7 +300,7 @@ export default class Importer {
|
|||
if (this.clear) layer.empty()
|
||||
if (this.files.length) {
|
||||
for (const file of this.files) {
|
||||
this.map.processFileToImport(file, layer, this.format)
|
||||
this.umap.processFileToImport(file, layer, this.format)
|
||||
}
|
||||
} else if (this.raw) {
|
||||
layer.importRaw(this.raw, this.format)
|
||||
|
|
|
@ -7,10 +7,10 @@ import * as Utils from './utils.js'
|
|||
// Dedicated object so we can deal with a separate dirty status, and thus
|
||||
// call the endpoint only when needed, saving one call at each save.
|
||||
export class MapPermissions extends ServerStored {
|
||||
constructor(map) {
|
||||
constructor(umap) {
|
||||
super()
|
||||
this.setOptions(map.options.permissions)
|
||||
this.map = map
|
||||
this.setOptions(umap.properties.permissions)
|
||||
this.umap = umap
|
||||
this._isDirty = false
|
||||
}
|
||||
|
||||
|
@ -28,11 +28,11 @@ export class MapPermissions extends ServerStored {
|
|||
}
|
||||
|
||||
isOwner() {
|
||||
return Boolean(this.map.options.user?.is_owner)
|
||||
return Boolean(this.umap.properties.user?.is_owner)
|
||||
}
|
||||
|
||||
isAnonymousMap() {
|
||||
return !this.map.options.permissions.owner
|
||||
return !this.umap.properties.permissions.owner
|
||||
}
|
||||
|
||||
_editAnonymous(container) {
|
||||
|
@ -43,7 +43,7 @@ export class MapPermissions extends ServerStored {
|
|||
{
|
||||
handler: 'IntSelect',
|
||||
label: translate('Who can edit'),
|
||||
selectOptions: this.map.options.edit_statuses,
|
||||
selectOptions: this.umap.properties.edit_statuses,
|
||||
},
|
||||
])
|
||||
const builder = new U.FormBuilder(this, fields)
|
||||
|
@ -58,7 +58,7 @@ export class MapPermissions extends ServerStored {
|
|||
)
|
||||
}
|
||||
|
||||
if (this.map.options.user?.id) {
|
||||
if (this.umap.properties.user?.id) {
|
||||
// We have a user, and this user has come through here, so they can edit the map, so let's allow to own the map.
|
||||
// Note: real check is made on the back office anyway.
|
||||
const advancedActions = DomUtil.createFieldset(
|
||||
|
@ -90,7 +90,7 @@ export class MapPermissions extends ServerStored {
|
|||
{
|
||||
handler: 'IntSelect',
|
||||
label: translate('Who can edit'),
|
||||
selectOptions: this.map.options.edit_statuses,
|
||||
selectOptions: this.umap.properties.edit_statuses,
|
||||
},
|
||||
])
|
||||
topFields.push([
|
||||
|
@ -98,20 +98,20 @@ export class MapPermissions extends ServerStored {
|
|||
{
|
||||
handler: 'IntSelect',
|
||||
label: translate('Who can view'),
|
||||
selectOptions: this.map.options.share_statuses,
|
||||
selectOptions: this.umap.properties.share_statuses,
|
||||
},
|
||||
])
|
||||
collaboratorsFields.push([
|
||||
'options.owner',
|
||||
{ handler: 'ManageOwner', label: translate("Map's owner") },
|
||||
])
|
||||
if (this.map.options.user?.teams?.length) {
|
||||
if (this.umap.properties.user?.teams?.length) {
|
||||
collaboratorsFields.push([
|
||||
'options.team',
|
||||
{
|
||||
handler: 'ManageTeam',
|
||||
label: translate('Attach map to a team'),
|
||||
teams: this.map.options.user.teams,
|
||||
teams: this.umap.properties.user.teams,
|
||||
},
|
||||
])
|
||||
}
|
||||
|
@ -136,20 +136,20 @@ export class MapPermissions extends ServerStored {
|
|||
}
|
||||
|
||||
_editDatalayers(container) {
|
||||
if (this.map.hasLayers()) {
|
||||
if (this.umap.hasLayers()) {
|
||||
const fieldset = Utils.loadTemplate(
|
||||
`<fieldset class="separator"><legend>${translate('Datalayers')}</legend></fieldset>`
|
||||
)
|
||||
container.appendChild(fieldset)
|
||||
this.map.eachDataLayer((datalayer) => {
|
||||
this.umap.eachDataLayer((datalayer) => {
|
||||
datalayer.permissions.edit(fieldset)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
edit() {
|
||||
if (this.map.options.editMode !== 'advanced') return
|
||||
if (!this.map.options.umap_id) {
|
||||
if (this.umap.properties.editMode !== 'advanced') return
|
||||
if (!this.umap.properties.umap_id) {
|
||||
Alert.info(translate('Please save the map first'))
|
||||
return
|
||||
}
|
||||
|
@ -158,15 +158,15 @@ export class MapPermissions extends ServerStored {
|
|||
if (this.isAnonymousMap()) this._editAnonymous(container)
|
||||
else this._editWithOwner(container)
|
||||
this._editDatalayers(container)
|
||||
this.map.editPanel.open({ content: container, className: 'dark' })
|
||||
this.umap.editPanel.open({ content: container, className: 'dark' })
|
||||
}
|
||||
|
||||
async attach() {
|
||||
const [data, response, error] = await this.map.server.post(this.getAttachUrl())
|
||||
const [data, response, error] = await this.umap.server.post(this.getAttachUrl())
|
||||
if (!error) {
|
||||
this.options.owner = this.map.options.user
|
||||
this.options.owner = this.umap.properties.user
|
||||
Alert.success(translate('Map has been attached to your account'))
|
||||
this.map.editPanel.close()
|
||||
this.umap.editPanel.close()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -186,40 +186,41 @@ export class MapPermissions extends ServerStored {
|
|||
formData.append('team', this.options.team?.id || '')
|
||||
formData.append('share_status', this.options.share_status)
|
||||
}
|
||||
const [data, response, error] = await this.map.server.post(
|
||||
const [data, response, error] = await this.umap.server.post(
|
||||
this.getUrl(),
|
||||
{},
|
||||
formData
|
||||
)
|
||||
if (!error) {
|
||||
this.commit()
|
||||
this.map.fire('postsync')
|
||||
this.umap._leafletMap.fire('postsync')
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
getUrl() {
|
||||
return Utils.template(this.map.options.urls.map_update_permissions, {
|
||||
map_id: this.map.options.umap_id,
|
||||
return this.umap.urls.get('map_update_permissions', {
|
||||
map_id: this.umap.properties.umap_id,
|
||||
})
|
||||
}
|
||||
|
||||
getAttachUrl() {
|
||||
return Utils.template(this.map.options.urls.map_attach_owner, {
|
||||
map_id: this.map.options.umap_id,
|
||||
return this.umap.urls.get('map_attach_owner', {
|
||||
map_id: this.umap.properties.umap_id,
|
||||
})
|
||||
}
|
||||
|
||||
commit() {
|
||||
this.map.options.permissions = Object.assign(
|
||||
this.map.options.permissions,
|
||||
this.umap.properties.permissions = Object.assign(
|
||||
{},
|
||||
this.umap.properties.permissions,
|
||||
this.options
|
||||
)
|
||||
}
|
||||
|
||||
getShareStatusDisplay() {
|
||||
if (this.map.options.share_statuses) {
|
||||
return Object.fromEntries(this.map.options.share_statuses)[
|
||||
if (this.umap.properties.share_statuses) {
|
||||
return Object.fromEntries(this.umap.properties.share_statuses)[
|
||||
this.options.share_status
|
||||
]
|
||||
}
|
||||
|
@ -239,8 +240,8 @@ export class DataLayerPermissions extends ServerStored {
|
|||
this.datalayer = datalayer
|
||||
}
|
||||
|
||||
get map() {
|
||||
return this.datalayer.map
|
||||
get umap() {
|
||||
return this.datalayer.umap
|
||||
}
|
||||
|
||||
edit(container) {
|
||||
|
@ -252,7 +253,7 @@ export class DataLayerPermissions extends ServerStored {
|
|||
label: translate('Who can edit "{layer}"', {
|
||||
layer: this.datalayer.getName(),
|
||||
}),
|
||||
selectOptions: this.map.options.datalayer_edit_statuses,
|
||||
selectOptions: this.umap.properties.datalayer_edit_statuses,
|
||||
},
|
||||
],
|
||||
]
|
||||
|
@ -264,8 +265,8 @@ export class DataLayerPermissions extends ServerStored {
|
|||
}
|
||||
|
||||
getUrl() {
|
||||
return this.map.urls.get('datalayer_permissions', {
|
||||
map_id: this.map.options.umap_id,
|
||||
return this.umap.urls.get('datalayer_permissions', {
|
||||
map_id: this.umap.properties.umap_id,
|
||||
pk: this.datalayer.umap_id,
|
||||
})
|
||||
}
|
||||
|
@ -274,7 +275,7 @@ export class DataLayerPermissions extends ServerStored {
|
|||
if (!this.isDirty) return
|
||||
const formData = new FormData()
|
||||
formData.append('edit_status', this.options.edit_status)
|
||||
const [data, response, error] = await this.map.server.post(
|
||||
const [data, response, error] = await this.umap.server.post(
|
||||
this.getUrl(),
|
||||
{},
|
||||
formData
|
||||
|
|
|
@ -73,7 +73,7 @@ export const Default = FeatureGroup.extend({
|
|||
initialize: function (datalayer) {
|
||||
this.datalayer = datalayer
|
||||
FeatureGroup.prototype.initialize.call(this)
|
||||
LayerMixin.onInit.call(this, this.datalayer.map)
|
||||
LayerMixin.onInit.call(this, this.datalayer.umap._leafletMap)
|
||||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
|
|
|
@ -20,7 +20,7 @@ const ClassifiedMixin = {
|
|||
}
|
||||
this.ensureOptions(this.datalayer.options[key])
|
||||
FeatureGroup.prototype.initialize.call(this, [], this.datalayer.options[key])
|
||||
LayerMixin.onInit.call(this, this.datalayer.map)
|
||||
LayerMixin.onInit.call(this, this.datalayer.umap._leafletMap)
|
||||
},
|
||||
|
||||
ensureOptions: () => {},
|
||||
|
|
|
@ -40,7 +40,7 @@ export const Cluster = L.MarkerClusterGroup.extend({
|
|||
options.maxClusterRadius = this.datalayer.options.cluster.radius
|
||||
}
|
||||
L.MarkerClusterGroup.prototype.initialize.call(this, options)
|
||||
LayerMixin.onInit.call(this, this.datalayer.map)
|
||||
LayerMixin.onInit.call(this, this.datalayer.umap._leafletMap)
|
||||
this._markerCluster = MarkerCluster
|
||||
this._layers = []
|
||||
},
|
||||
|
|
|
@ -21,7 +21,7 @@ export const Heat = L.HeatLayer.extend({
|
|||
initialize: function (datalayer) {
|
||||
this.datalayer = datalayer
|
||||
L.HeatLayer.prototype.initialize.call(this, [], this.datalayer.options.heat)
|
||||
LayerMixin.onInit.call(this, this.datalayer.map)
|
||||
LayerMixin.onInit.call(this, this.datalayer.umap._leafletMap)
|
||||
if (!Utils.isObject(this.datalayer.options.heat)) {
|
||||
this.datalayer.options.heat = {}
|
||||
}
|
||||
|
|
583
umap/static/umap/js/modules/rendering/map.js
Normal file
583
umap/static/umap/js/modules/rendering/map.js
Normal file
|
@ -0,0 +1,583 @@
|
|||
// Goes here all code related to Leaflet, DOM and user interactions.
|
||||
import {
|
||||
Map as BaseMap,
|
||||
DomUtil,
|
||||
DomEvent,
|
||||
latLngBounds,
|
||||
latLng,
|
||||
Control,
|
||||
setOptions,
|
||||
} from '../../../vendors/leaflet/leaflet-src.esm.js'
|
||||
import { translate } from '../i18n.js'
|
||||
import { uMapAlert as Alert } from '../../components/alerts/alert.js'
|
||||
import * as Utils from '../utils.js'
|
||||
import * as Icon from './icon.js'
|
||||
|
||||
// Those options are not saved on the server, so they can live here
|
||||
// instead of in umap.properties
|
||||
BaseMap.mergeOptions({
|
||||
demoTileInfos: { s: 'a', z: 9, x: 265, y: 181, '-y': 181, r: '' },
|
||||
attributionControl: false,
|
||||
})
|
||||
|
||||
const ControlsMixin = {
|
||||
HIDDABLE_CONTROLS: [
|
||||
'zoom',
|
||||
'search',
|
||||
'fullscreen',
|
||||
'embed',
|
||||
'datalayers',
|
||||
'caption',
|
||||
'locate',
|
||||
'measure',
|
||||
'editinosm',
|
||||
'star',
|
||||
'tilelayers',
|
||||
],
|
||||
|
||||
initControls: function () {
|
||||
this.helpMenuActions = {}
|
||||
this._controls = {}
|
||||
|
||||
if (this.umap.hasEditMode() && !this.options.noControl) {
|
||||
new U.EditControl(this).addTo(this)
|
||||
|
||||
new U.DrawToolbar({ map: this }).addTo(this)
|
||||
const editActions = [
|
||||
U.EditCaptionAction,
|
||||
U.EditPropertiesAction,
|
||||
U.EditLayersAction,
|
||||
U.ChangeTileLayerAction,
|
||||
U.UpdateExtentAction,
|
||||
U.UpdatePermsAction,
|
||||
U.ImportAction,
|
||||
]
|
||||
if (this.options.editMode === 'advanced') {
|
||||
new U.SettingsToolbar({ actions: editActions }).addTo(this)
|
||||
}
|
||||
}
|
||||
this._controls.zoom = new Control.Zoom({
|
||||
zoomInTitle: translate('Zoom in'),
|
||||
zoomOutTitle: translate('Zoom out'),
|
||||
})
|
||||
this._controls.datalayers = new U.DataLayersControl(this.umap)
|
||||
this._controls.caption = new U.CaptionControl(this.umap)
|
||||
this._controls.locate = new U.Locate(this, {
|
||||
strings: {
|
||||
title: translate('Center map on your location'),
|
||||
},
|
||||
showPopup: false,
|
||||
// We style this control in our own CSS for consistency with other controls,
|
||||
// but the control breaks if we don't specify a class here, so a fake class
|
||||
// will do.
|
||||
icon: 'umap-fake-class',
|
||||
iconLoading: 'umap-fake-class',
|
||||
flyTo: this.options.easing,
|
||||
onLocationError: (err) => U.Alert.error(err.message),
|
||||
})
|
||||
this._controls.fullscreen = new Control.Fullscreen({
|
||||
title: {
|
||||
false: translate('View Fullscreen'),
|
||||
true: translate('Exit Fullscreen'),
|
||||
},
|
||||
})
|
||||
this._controls.search = new U.SearchControl()
|
||||
this._controls.embed = new Control.Embed(this.umap)
|
||||
this._controls.tilelayersChooser = new U.TileLayerChooser(this)
|
||||
if (this.options.user?.id) this._controls.star = new U.StarControl(this.umap)
|
||||
this._controls.editinosm = new Control.EditInOSM({
|
||||
position: 'topleft',
|
||||
widgetOptions: {
|
||||
helpText: translate(
|
||||
'Open this map extent in a map editor to provide more accurate data to OpenStreetMap'
|
||||
),
|
||||
},
|
||||
})
|
||||
this._controls.measure = new L.MeasureControl().initHandler(this)
|
||||
this._controls.more = new U.MoreControls()
|
||||
this._controls.scale = L.control.scale()
|
||||
this._controls.permanentCredit = new U.PermanentCreditsControl(this)
|
||||
if (this.options.scrollWheelZoom) this.scrollWheelZoom.enable()
|
||||
else this.scrollWheelZoom.disable()
|
||||
this.umap.drop = new U.DropControl(this)
|
||||
this._controls.tilelayers = new U.TileLayerControl(this)
|
||||
},
|
||||
|
||||
renderControls: function () {
|
||||
const hasSlideshow = Boolean(this.options.slideshow?.active)
|
||||
const barEnabled = this.options.captionBar || hasSlideshow
|
||||
document.body.classList.toggle('umap-caption-bar-enabled', barEnabled)
|
||||
document.body.classList.toggle('umap-slideshow-enabled', hasSlideshow)
|
||||
for (const control of Object.values(this._controls)) {
|
||||
this.removeControl(control)
|
||||
}
|
||||
if (this.options.noControl) return
|
||||
|
||||
this._controls.attribution = new U.AttributionControl().addTo(this)
|
||||
if (this.options.miniMap) {
|
||||
this.whenReady(function () {
|
||||
if (this.selectedTilelayer) {
|
||||
this._controls.miniMap = new Control.MiniMap(this.selectedTilelayer, {
|
||||
aimingRectOptions: {
|
||||
color: this.umap.getOption('color'),
|
||||
fillColor: this.umap.getOption('fillColor'),
|
||||
stroke: this.umap.getOption('stroke'),
|
||||
fill: this.umap.getOption('fill'),
|
||||
weight: this.umap.getOption('weight'),
|
||||
opacity: this.umap.getOption('opacity'),
|
||||
fillOpacity: this.umap.getOption('fillOpacity'),
|
||||
},
|
||||
}).addTo(this)
|
||||
this._controls.miniMap._miniMap.invalidateSize()
|
||||
}
|
||||
})
|
||||
}
|
||||
for (const name of this.HIDDABLE_CONTROLS) {
|
||||
const status = this.umap.getOption(`${name}Control`)
|
||||
if (status === false) continue
|
||||
const control = this._controls[name]
|
||||
if (!control) continue
|
||||
control.addTo(this)
|
||||
if (status === undefined || status === null) {
|
||||
DomUtil.addClass(control._container, 'display-on-more')
|
||||
} else {
|
||||
DomUtil.removeClass(control._container, 'display-on-more')
|
||||
}
|
||||
}
|
||||
if (this.umap.getOption('permanentCredit'))
|
||||
this._controls.permanentCredit.addTo(this)
|
||||
if (this.umap.getOption('moreControl')) this._controls.more.addTo(this)
|
||||
if (this.umap.getOption('scaleControl')) this._controls.scale.addTo(this)
|
||||
this._controls.tilelayers.setLayers()
|
||||
},
|
||||
|
||||
renderEditToolbar: function () {
|
||||
const className = 'umap-main-edit-toolbox'
|
||||
const container =
|
||||
document.querySelector(`.${className}`) ||
|
||||
DomUtil.create('div', `${className} with-transition dark`, this._controlContainer)
|
||||
container.innerHTML = ''
|
||||
const leftContainer = DomUtil.create('div', 'umap-left-edit-toolbox', container)
|
||||
const rightContainer = DomUtil.create('div', 'umap-right-edit-toolbox', container)
|
||||
const logo = DomUtil.create('div', 'logo', leftContainer)
|
||||
DomUtil.createLink('', logo, 'uMap', '/', null, translate('Go to the homepage'))
|
||||
const nameButton = DomUtil.createButton('map-name', leftContainer, '')
|
||||
DomEvent.on(nameButton, 'mouseover', () => {
|
||||
this.umap.tooltip.open({
|
||||
content: translate('Edit the title of the map'),
|
||||
anchor: nameButton,
|
||||
position: 'bottom',
|
||||
delay: 500,
|
||||
duration: 5000,
|
||||
})
|
||||
})
|
||||
const shareStatusButton = DomUtil.createButton(
|
||||
'share-status',
|
||||
leftContainer,
|
||||
'',
|
||||
this.umap.permissions.edit,
|
||||
this.umap.permissions
|
||||
)
|
||||
DomEvent.on(shareStatusButton, 'mouseover', () => {
|
||||
this.umap.tooltip.open({
|
||||
content: translate('Update who can see and edit the map'),
|
||||
anchor: shareStatusButton,
|
||||
position: 'bottom',
|
||||
delay: 500,
|
||||
duration: 5000,
|
||||
})
|
||||
})
|
||||
if (this.options.editMode === 'advanced') {
|
||||
DomEvent.on(nameButton, 'click', this.umap.editCaption, this.umap)
|
||||
DomEvent.on(
|
||||
shareStatusButton,
|
||||
'click',
|
||||
this.umap.permissions.edit,
|
||||
this.umap.permissions
|
||||
)
|
||||
}
|
||||
if (this.options.user?.id) {
|
||||
const button = U.Utils.loadTemplate(`
|
||||
<button class="umap-user flat" type="button">
|
||||
<i class="icon icon-16 icon-profile"></i>
|
||||
<span>${this.options.user.name}</span>
|
||||
</button>
|
||||
`)
|
||||
rightContainer.appendChild(button)
|
||||
const menu = new U.ContextMenu({ className: 'dark', fixed: true })
|
||||
const actions = [
|
||||
{
|
||||
label: translate('New map'),
|
||||
action: this.umap.urls.get('map_new'),
|
||||
},
|
||||
{
|
||||
label: translate('My maps'),
|
||||
action: this.umap.urls.get('user_dashboard'),
|
||||
},
|
||||
{
|
||||
label: translate('My teams'),
|
||||
action: this.umap.urls.get('user_teams'),
|
||||
},
|
||||
]
|
||||
if (this.umap.urls.has('user_profile')) {
|
||||
actions.push({
|
||||
label: translate('My profile'),
|
||||
action: this.umap.urls.get('user_profile'),
|
||||
})
|
||||
}
|
||||
button.addEventListener('click', () => {
|
||||
menu.openBelow(button, actions)
|
||||
})
|
||||
}
|
||||
|
||||
const connectedPeers = this.umap.sync.getNumberOfConnectedPeers()
|
||||
if (connectedPeers !== 0) {
|
||||
const connectedPeersCount = DomUtil.createButton(
|
||||
'leaflet-control-connected-peers',
|
||||
rightContainer,
|
||||
''
|
||||
)
|
||||
DomEvent.on(connectedPeersCount, 'mouseover', () => {
|
||||
this.umap.tooltip.open({
|
||||
content: translate(
|
||||
'{connectedPeers} peer(s) currently connected to this map',
|
||||
{
|
||||
connectedPeers: connectedPeers,
|
||||
}
|
||||
),
|
||||
anchor: connectedPeersCount,
|
||||
position: 'bottom',
|
||||
delay: 500,
|
||||
duration: 5000,
|
||||
})
|
||||
})
|
||||
|
||||
const updateConnectedPeersCount = () => {
|
||||
connectedPeersCount.innerHTML = this.sync.getNumberOfConnectedPeers()
|
||||
}
|
||||
updateConnectedPeersCount()
|
||||
}
|
||||
|
||||
this.umap.help.getStartedLink(rightContainer)
|
||||
const controlEditCancel = DomUtil.createButton(
|
||||
'leaflet-control-edit-cancel',
|
||||
rightContainer,
|
||||
DomUtil.add('span', '', null, translate('Cancel edits')),
|
||||
() => this.umap.askForReset()
|
||||
)
|
||||
DomEvent.on(controlEditCancel, 'mouseover', () => {
|
||||
this.umap.tooltip.open({
|
||||
content: this.umap.help.displayLabel('CANCEL'),
|
||||
anchor: controlEditCancel,
|
||||
position: 'bottom',
|
||||
delay: 500,
|
||||
duration: 5000,
|
||||
})
|
||||
})
|
||||
const controlEditDisable = DomUtil.createButton(
|
||||
'leaflet-control-edit-disable',
|
||||
rightContainer,
|
||||
DomUtil.add('span', '', null, translate('View')),
|
||||
this.umap.disableEdit,
|
||||
this.umap
|
||||
)
|
||||
DomEvent.on(controlEditDisable, 'mouseover', () => {
|
||||
this.umap.tooltip.open({
|
||||
content: this.umap.help.displayLabel('PREVIEW'),
|
||||
anchor: controlEditDisable,
|
||||
position: 'bottom',
|
||||
delay: 500,
|
||||
duration: 5000,
|
||||
})
|
||||
})
|
||||
const controlEditSave = DomUtil.createButton(
|
||||
'leaflet-control-edit-save button',
|
||||
rightContainer,
|
||||
DomUtil.add('span', '', null, translate('Save')),
|
||||
() => this.umap.saveAll()
|
||||
)
|
||||
DomEvent.on(controlEditSave, 'mouseover', () => {
|
||||
this.umap.tooltip.open({
|
||||
content: this.umap.help.displayLabel('SAVE'),
|
||||
anchor: controlEditSave,
|
||||
position: 'bottom',
|
||||
delay: 500,
|
||||
duration: 5000,
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
initCaptionBar: function () {
|
||||
const container = DomUtil.create('div', 'umap-caption-bar', this._controlContainer)
|
||||
const name = DomUtil.create('h3', 'map-name', container)
|
||||
DomEvent.disableClickPropagation(container)
|
||||
this.umap.addAuthorLink(container)
|
||||
if (this.umap.getOption('captionMenus')) {
|
||||
DomUtil.createButton(
|
||||
'umap-about-link flat',
|
||||
container,
|
||||
translate('Open caption'),
|
||||
this.umap.openCaption,
|
||||
this
|
||||
)
|
||||
DomUtil.createButton(
|
||||
'umap-open-browser-link flat',
|
||||
container,
|
||||
translate('Browse data'),
|
||||
() => this.openBrowser('data')
|
||||
)
|
||||
if (this.options.facetKey) {
|
||||
DomUtil.createButton(
|
||||
'umap-open-filter-link flat',
|
||||
container,
|
||||
translate('Filter data'),
|
||||
() => this.openBrowser('filters')
|
||||
)
|
||||
}
|
||||
}
|
||||
this.umap.onceDatalayersLoaded(function () {
|
||||
this.slideshow.renderToolbox(container)
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
const ManageTilelayerMixin = {
|
||||
initTileLayers: function () {
|
||||
this.tilelayers = []
|
||||
for (const props of this.options.tilelayers) {
|
||||
const layer = this.createTileLayer(props)
|
||||
this.tilelayers.push(layer)
|
||||
if (
|
||||
this.options.tilelayer &&
|
||||
this.options.tilelayer.url_template === props.url_template
|
||||
) {
|
||||
// Keep control over the displayed attribution for non custom tilelayers
|
||||
this.options.tilelayer.attribution = props.attribution
|
||||
}
|
||||
}
|
||||
if (this.options.tilelayer?.url_template && this.options.tilelayer.attribution) {
|
||||
this.customTilelayer = this.createTileLayer(this.options.tilelayer)
|
||||
this.selectTileLayer(this.customTilelayer)
|
||||
} else {
|
||||
this.selectTileLayer(this.tilelayers[0])
|
||||
}
|
||||
if (this._controls) this._controls.tilelayers.setLayers()
|
||||
},
|
||||
|
||||
createTileLayer: (tilelayer) => new L.TileLayer(tilelayer.url_template, tilelayer),
|
||||
|
||||
selectTileLayer: function (tilelayer) {
|
||||
if (tilelayer === this.selectedTilelayer) {
|
||||
return
|
||||
}
|
||||
try {
|
||||
this.addLayer(tilelayer)
|
||||
this.fire('baselayerchange', { layer: tilelayer })
|
||||
if (this.selectedTilelayer) {
|
||||
this.removeLayer(this.selectedTilelayer)
|
||||
}
|
||||
this.selectedTilelayer = tilelayer
|
||||
if (
|
||||
!Number.isNaN(this.selectedTilelayer.options.minZoom) &&
|
||||
this.getZoom() < this.selectedTilelayer.options.minZoom
|
||||
) {
|
||||
this.setZoom(this.selectedTilelayer.options.minZoom)
|
||||
}
|
||||
if (
|
||||
!Number.isNaN(this.selectedTilelayer.options.maxZoom) &&
|
||||
this.getZoom() > this.selectedTilelayer.options.maxZoom
|
||||
) {
|
||||
this.setZoom(this.selectedTilelayer.options.maxZoom)
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
this.removeLayer(tilelayer)
|
||||
Alert.error(`${translate('Error in the tilelayer URL')}: ${tilelayer._url}`)
|
||||
// Users can put tilelayer URLs by hand, and if they add wrong {variable},
|
||||
// Leaflet throw an error, and then the map is no more editable
|
||||
}
|
||||
this.setOverlay()
|
||||
},
|
||||
|
||||
eachTileLayer: function (callback, context) {
|
||||
const urls = []
|
||||
const callOne = (layer) => {
|
||||
// Prevent adding a duplicate background,
|
||||
// while adding selected/custom on top of the list
|
||||
const url = layer.options.url_template
|
||||
if (urls.indexOf(url) !== -1) return
|
||||
callback.call(context, layer)
|
||||
urls.push(url)
|
||||
}
|
||||
if (this.selectedTilelayer) callOne(this.selectedTilelayer)
|
||||
if (this.customTilelayer) callOne(this.customTilelayer)
|
||||
this.tilelayers.forEach(callOne)
|
||||
},
|
||||
|
||||
setOverlay: function () {
|
||||
if (!this.options.overlay || !this.options.overlay.url_template) return
|
||||
const overlay = this.createTileLayer(this.options.overlay)
|
||||
try {
|
||||
this.addLayer(overlay)
|
||||
if (this.overlay) this.removeLayer(this.overlay)
|
||||
this.overlay = overlay
|
||||
} catch (e) {
|
||||
this.removeLayer(overlay)
|
||||
console.error(e)
|
||||
Alert.error(`${translate('Error in the overlay URL')}: ${overlay._url}`)
|
||||
}
|
||||
},
|
||||
|
||||
updateTileLayers: function () {
|
||||
const callback = (tilelayer) => {
|
||||
this.options.tilelayer = tilelayer.toJSON()
|
||||
this.umap.isDirty = true
|
||||
}
|
||||
if (this._controls.tilelayersChooser) {
|
||||
this._controls.tilelayersChooser.openSwitcher({ callback, edit: true })
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
const EditMixin = {
|
||||
startMarker: function () {
|
||||
return this.editTools.startMarker()
|
||||
},
|
||||
|
||||
startPolyline: function () {
|
||||
return this.editTools.startPolyline()
|
||||
},
|
||||
|
||||
startPolygon: function () {
|
||||
return this.editTools.startPolygon()
|
||||
},
|
||||
|
||||
initEditTools: function () {
|
||||
this.editTools = new U.Editable(this.umap)
|
||||
this.renderEditToolbar()
|
||||
},
|
||||
}
|
||||
|
||||
export const LeafletMap = BaseMap.extend({
|
||||
includes: [ControlsMixin, ManageTilelayerMixin, EditMixin],
|
||||
initialize: function (umap, element) {
|
||||
this.umap = umap
|
||||
const options = this.umap.properties
|
||||
|
||||
BaseMap.prototype.initialize.call(this, element, options)
|
||||
|
||||
// After calling parent initialize, as we are doing initCenter our-selves
|
||||
|
||||
this.loader = new Control.Loading()
|
||||
this.loader.onAdd(this)
|
||||
|
||||
if (!this.options.noControl) {
|
||||
DomEvent.on(document.body, 'dataloading', (e) => this.fire('dataloading', e))
|
||||
DomEvent.on(document.body, 'dataload', (e) => this.fire('dataload', e))
|
||||
this.on('click', this.closeInplaceToolbar)
|
||||
}
|
||||
|
||||
this.on('baselayerchange', (e) => {
|
||||
if (this._controls.miniMap) this._controls.miniMap.onMainMapBaseLayerChange(e)
|
||||
})
|
||||
},
|
||||
|
||||
attachToDom: function () {
|
||||
this.initControls()
|
||||
// Needs locate control and hash to exist
|
||||
this.initCenter()
|
||||
this.initTileLayers()
|
||||
// Needs tilelayer to exist for minimap
|
||||
this.renderControls()
|
||||
this.handleLimitBounds()
|
||||
},
|
||||
|
||||
setOptions: function (options) {
|
||||
setOptions(this, options)
|
||||
},
|
||||
|
||||
closeInplaceToolbar: function () {
|
||||
const toolbar = this._toolbars[L.Toolbar.Popup._toolbar_class_id]
|
||||
if (toolbar) toolbar.remove()
|
||||
},
|
||||
|
||||
latLng: (a, b, c) => {
|
||||
// manage geojson case and call original method
|
||||
if (!(a instanceof L.LatLng) && a.coordinates) {
|
||||
// Guess it's a geojson
|
||||
a = [a.coordinates[1], a.coordinates[0]]
|
||||
}
|
||||
return latLng(a, b, c)
|
||||
},
|
||||
|
||||
_setDefaultCenter: function () {
|
||||
this.options.center = this.latLng(this.options.center)
|
||||
this.setView(this.options.center, this.options.zoom)
|
||||
},
|
||||
|
||||
initCenter: function () {
|
||||
this._setDefaultCenter()
|
||||
if (this.options.hash) this.addHash()
|
||||
if (this.options.hash && this._hash.parseHash(location.hash)) {
|
||||
// FIXME An invalid hash will cause the load to fail
|
||||
this._hash.update()
|
||||
} else if (this.options.defaultView === 'locate' && !this.options.noControl) {
|
||||
this._controls.locate.start()
|
||||
} else if (this.options.defaultView === 'data') {
|
||||
this.umap.onceDataLoaded(this.umap.fitDataBounds)
|
||||
} else if (this.options.defaultView === 'latest') {
|
||||
this.umap.onceDataLoaded(() => {
|
||||
if (!this.umap.hasData()) return
|
||||
const datalayer = this.umap.firstVisibleDatalayer()
|
||||
let feature
|
||||
if (datalayer) {
|
||||
const feature = datalayer.getFeatureByIndex(-1)
|
||||
if (feature) {
|
||||
feature.zoomTo({ callback: this.options.noControl ? null : feature.view })
|
||||
return
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
handleLimitBounds: function () {
|
||||
const south = Number.parseFloat(this.options.limitBounds.south)
|
||||
const west = Number.parseFloat(this.options.limitBounds.west)
|
||||
const north = Number.parseFloat(this.options.limitBounds.north)
|
||||
const east = Number.parseFloat(this.options.limitBounds.east)
|
||||
if (
|
||||
!Number.isNaN(south) &&
|
||||
!Number.isNaN(west) &&
|
||||
!Number.isNaN(north) &&
|
||||
!Number.isNaN(east)
|
||||
) {
|
||||
const bounds = latLngBounds([
|
||||
[south, west],
|
||||
[north, east],
|
||||
])
|
||||
this.options.minZoom = this.getBoundsZoom(bounds, false)
|
||||
try {
|
||||
this.setMaxBounds(bounds)
|
||||
} catch (e) {
|
||||
// Unusable bounds, like -2 -2 -2 -2?
|
||||
console.error('Error limiting bounds', e)
|
||||
}
|
||||
} else {
|
||||
this.options.minZoom = 0
|
||||
this.setMaxBounds()
|
||||
}
|
||||
},
|
||||
|
||||
setMaxBounds: function (bounds) {
|
||||
// Hack. Remove me when fix is released:
|
||||
// https://github.com/Leaflet/Leaflet/pull/4494
|
||||
bounds = latLngBounds(bounds)
|
||||
|
||||
if (!bounds.isValid()) {
|
||||
this.options.maxBounds = null
|
||||
return this.off('moveend', this._panInsideMaxBounds)
|
||||
}
|
||||
return BaseMap.prototype.setMaxBounds.call(this, bounds)
|
||||
},
|
||||
})
|
|
@ -62,8 +62,8 @@ const Panel = Popup.extend({
|
|||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
map.panel.setDefaultMode('expanded')
|
||||
map.panel.open({
|
||||
map.umap.panel.setDefaultMode('expanded')
|
||||
map.umap.panel.open({
|
||||
content: this._content,
|
||||
actions: [Browser.backButton(map)],
|
||||
})
|
||||
|
@ -79,7 +79,7 @@ const Panel = Popup.extend({
|
|||
},
|
||||
|
||||
onRemove: function (map) {
|
||||
map.panel.close()
|
||||
map.umap.panel.close()
|
||||
|
||||
// fire events as in base class Popup.js:onRemove
|
||||
map.fire('popupclose', { popup: this })
|
||||
|
|
|
@ -52,7 +52,7 @@ const FeatureMixin = {
|
|||
onClick: function (event) {
|
||||
if (this._map.measureTools?.enabled()) return
|
||||
this._popupHandlersAdded = true // Prevent leaflet from managing event
|
||||
if (!this._map.editEnabled) {
|
||||
if (!this._map.umap.editEnabled) {
|
||||
this.feature.view(event)
|
||||
} else if (!this.feature.isReadOnly()) {
|
||||
if (event.originalEvent.shiftKey) {
|
||||
|
@ -96,8 +96,8 @@ const FeatureMixin = {
|
|||
DomEvent.stop(event)
|
||||
const items = this.feature
|
||||
.getContextMenuItems(event)
|
||||
.concat(this._map.getContextMenuItems(event))
|
||||
this._map.contextmenu.open(event.originalEvent, items)
|
||||
.concat(this._map.umap.getContextMenuItems(event))
|
||||
this._map.umap.contextmenu.open(event.originalEvent, items)
|
||||
},
|
||||
|
||||
onCommit: function () {
|
||||
|
@ -134,7 +134,7 @@ const PointMixin = {
|
|||
|
||||
_enableDragging: function () {
|
||||
// TODO: start dragging after 1 second on mouse down
|
||||
if (this._map.editEnabled) {
|
||||
if (this._map.umap.editEnabled) {
|
||||
if (!this.editEnabled()) this.enableEdit()
|
||||
// Enabling dragging on the marker override the Draggable._OnDown
|
||||
// event, which, as it stopPropagation, refrain the call of
|
||||
|
@ -146,7 +146,7 @@ const PointMixin = {
|
|||
},
|
||||
|
||||
_disableDragging: function () {
|
||||
if (this._map.editEnabled) {
|
||||
if (this._map.umap.editEnabled) {
|
||||
if (this.editor?.drawing) return // when creating a new marker, the mouse can trigger the mouseover/mouseout event
|
||||
// do not listen to them
|
||||
this.disableEdit()
|
||||
|
@ -253,21 +253,21 @@ export const LeafletMarker = Marker.extend({
|
|||
const PathMixin = {
|
||||
_onMouseOver: function () {
|
||||
if (this._map.measureTools?.enabled()) {
|
||||
this._map.tooltip.open({ content: this.getMeasure(), anchor: this })
|
||||
} else if (this._map.editEnabled && !this._map.editedFeature) {
|
||||
this._map.tooltip.open({ content: translate('Click to edit'), anchor: this })
|
||||
this._map.umap.tooltip.open({ content: this.getMeasure(), anchor: this })
|
||||
} else if (this._map.umap.editEnabled && !this._map.umap.editedFeature) {
|
||||
this._map.umap.tooltip.open({ content: translate('Click to edit'), anchor: this })
|
||||
}
|
||||
},
|
||||
|
||||
makeGeometryEditable: function () {
|
||||
if (this._map.editedFeature !== this.feature) {
|
||||
if (this._map.umap.editedFeature !== this.feature) {
|
||||
this.disableEdit()
|
||||
return
|
||||
}
|
||||
this._map.once('moveend', this.makeGeometryEditable, this)
|
||||
const pointsCount = this._parts.reduce((acc, part) => acc + part.length, 0)
|
||||
if (pointsCount > 100 && this._map.getZoom() < this._map.getMaxZoom()) {
|
||||
this._map.tooltip.open({ content: L._('Please zoom in to edit the geometry') })
|
||||
this._map.umap.tooltip.open({ content: L._('Please zoom in to edit the geometry') })
|
||||
this.disableEdit()
|
||||
} else {
|
||||
this.enableEdit()
|
||||
|
|
|
@ -21,10 +21,10 @@ class Rule {
|
|||
|
||||
set isDirty(status) {
|
||||
this._isDirty = status
|
||||
if (status) this.map.isDirty = status
|
||||
if (status) this.umap.isDirty = status
|
||||
}
|
||||
|
||||
constructor(map, condition = '', options = {}) {
|
||||
constructor(umap, condition = '', options = {}) {
|
||||
// TODO make this public properties when browser coverage is ok
|
||||
// cf https://caniuse.com/?search=public%20class%20field
|
||||
this._condition = null
|
||||
|
@ -37,14 +37,14 @@ class Rule {
|
|||
['!=', this.not_equal],
|
||||
['=', this.equal],
|
||||
]
|
||||
this.map = map
|
||||
this.umap = umap
|
||||
this.active = true
|
||||
this.options = options
|
||||
this.condition = condition
|
||||
}
|
||||
|
||||
render(fields) {
|
||||
this.map.render(fields)
|
||||
this.umap.render(fields)
|
||||
}
|
||||
|
||||
equal(other) {
|
||||
|
@ -102,7 +102,7 @@ class Rule {
|
|||
}
|
||||
|
||||
getMap() {
|
||||
return this.map
|
||||
return this.umap
|
||||
}
|
||||
|
||||
getOption(option) {
|
||||
|
@ -136,7 +136,7 @@ class Rule {
|
|||
const defaultShapeProperties = DomUtil.add('div', '', container)
|
||||
defaultShapeProperties.appendChild(builder.build())
|
||||
const autocomplete = new AutocompleteDatalist(builder.helpers.condition.input)
|
||||
const properties = this.map.allProperties()
|
||||
const properties = this.umap.allProperties()
|
||||
autocomplete.suggestions = properties
|
||||
autocomplete.input.addEventListener('input', (event) => {
|
||||
const value = event.target.value
|
||||
|
@ -144,12 +144,12 @@ class Rule {
|
|||
autocomplete.suggestions = [`${value}=`, `${value}!=`, `${value}>`, `${value}<`]
|
||||
} else if (value.endsWith('=')) {
|
||||
const key = value.split('!')[0].split('=')[0]
|
||||
autocomplete.suggestions = this.map
|
||||
autocomplete.suggestions = this.umap
|
||||
.sortedValues(key)
|
||||
.map((str) => `${value}${str || ''}`)
|
||||
}
|
||||
})
|
||||
this.map.editPanel.open({ content: container })
|
||||
this.umap.editPanel.open({ content: container })
|
||||
}
|
||||
|
||||
renderToolbox(row) {
|
||||
|
@ -176,7 +176,7 @@ class Rule {
|
|||
function () {
|
||||
if (!confirm(translate('Are you sure you want to delete this rule?'))) return
|
||||
this._delete()
|
||||
this.map.editPanel.close()
|
||||
this.umap.editPanel.close()
|
||||
},
|
||||
this
|
||||
)
|
||||
|
@ -186,27 +186,27 @@ class Rule {
|
|||
DomEvent.on(toggle, 'click', () => {
|
||||
this.active = !this.active
|
||||
row.classList.toggle('off', !this.active)
|
||||
this.map.render(['rules'])
|
||||
this.umap.render(['rules'])
|
||||
})
|
||||
}
|
||||
|
||||
_delete() {
|
||||
this.map.rules.rules = this.map.rules.rules.filter((rule) => rule !== this)
|
||||
this.umap.rules.rules = this.umap.rules.rules.filter((rule) => rule !== this)
|
||||
}
|
||||
}
|
||||
|
||||
export default class Rules {
|
||||
constructor(map) {
|
||||
this.map = map
|
||||
constructor(umap) {
|
||||
this.umap = umap
|
||||
this.rules = []
|
||||
this.loadRules()
|
||||
}
|
||||
|
||||
loadRules() {
|
||||
if (!this.map.options.rules?.length) return
|
||||
for (const { condition, options } of this.map.options.rules) {
|
||||
if (!this.umap.properties.rules?.length) return
|
||||
for (const { condition, options } of this.umap.properties.rules) {
|
||||
if (!condition) continue
|
||||
this.rules.push(new Rule(this.map, condition, options))
|
||||
this.rules.push(new Rule(this.umap, condition, options))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -225,7 +225,7 @@ export default class Rules {
|
|||
else newIdx = referenceIdx + 1
|
||||
this.rules.splice(newIdx, 0, moved)
|
||||
moved.isDirty = true
|
||||
this.map.render(['rules'])
|
||||
this.umap.render(['rules'])
|
||||
}
|
||||
|
||||
edit(container) {
|
||||
|
@ -243,14 +243,14 @@ export default class Rules {
|
|||
}
|
||||
|
||||
addRule() {
|
||||
const rule = new Rule(this.map)
|
||||
const rule = new Rule(this.umap)
|
||||
rule.isDirty = true
|
||||
this.rules.push(rule)
|
||||
rule.edit(map)
|
||||
}
|
||||
|
||||
commit() {
|
||||
this.map.options.rules = this.rules.map((rule) => {
|
||||
this.umap.properties.rules = this.rules.map((rule) => {
|
||||
return {
|
||||
condition: rule.condition,
|
||||
options: rule.options,
|
||||
|
|
|
@ -25,7 +25,6 @@ export function has(obj) {
|
|||
}
|
||||
|
||||
function _onUpdate() {
|
||||
console.log(_queue)
|
||||
isDirty = Boolean(_queue.size)
|
||||
document.body.classList.toggle('umap-is-dirty', isDirty)
|
||||
}
|
||||
|
|
|
@ -4,8 +4,8 @@ import { translate } from './i18n.js'
|
|||
import * as Utils from './utils.js'
|
||||
|
||||
export default class Share {
|
||||
constructor(map) {
|
||||
this.map = map
|
||||
constructor(umap) {
|
||||
this.umap = umap
|
||||
}
|
||||
|
||||
build() {
|
||||
|
@ -22,11 +22,11 @@ export default class Share {
|
|||
window.location.protocol + Utils.getBaseUrl()
|
||||
)
|
||||
|
||||
if (this.map.options.shortUrl) {
|
||||
if (this.umap.properties.shortUrl) {
|
||||
DomUtil.createCopiableInput(
|
||||
this.container,
|
||||
translate('Short link'),
|
||||
this.map.options.shortUrl
|
||||
this.umap.properties.shortUrl
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -60,8 +60,8 @@ export default class Share {
|
|||
this.container,
|
||||
translate('All data and settings of the map')
|
||||
)
|
||||
const downloadUrl = Utils.template(this.map.options.urls.map_download, {
|
||||
map_id: this.map.options.umap_id,
|
||||
const downloadUrl = this.umap.urls.get('map_download', {
|
||||
map_id: this.umap.properties.umap_id,
|
||||
})
|
||||
const link = Utils.loadTemplate(`
|
||||
<div>
|
||||
|
@ -115,10 +115,11 @@ export default class Share {
|
|||
'queryString.captionBar',
|
||||
'queryString.captionMenus',
|
||||
]
|
||||
for (let i = 0; i < this.map.HIDDABLE_CONTROLS.length; i++) {
|
||||
UIFields.push(`queryString.${this.map.HIDDABLE_CONTROLS[i]}Control`)
|
||||
// TODO: move HIDDABLE_CONTROLS to SCHEMA ?
|
||||
for (const name of this.umap._leafletMap.HIDDABLE_CONTROLS) {
|
||||
UIFields.push(`queryString.${name}Control`)
|
||||
}
|
||||
const iframeExporter = new IframeExporter(this.map)
|
||||
const iframeExporter = new IframeExporter(this.umap)
|
||||
const buildIframeCode = () => {
|
||||
iframe.textContent = iframeExporter.build()
|
||||
exportUrl.value = window.location.protocol + iframeExporter.buildUrl()
|
||||
|
@ -136,13 +137,13 @@ export default class Share {
|
|||
|
||||
open() {
|
||||
if (!this.container) this.build()
|
||||
this.map.panel.open({ content: this.container })
|
||||
this.umap.panel.open({ content: this.container })
|
||||
}
|
||||
|
||||
async format(mode) {
|
||||
const type = EXPORT_FORMATS[mode]
|
||||
const content = await type.formatter(this.map)
|
||||
const filename = Utils.slugify(this.map.options.name) + type.ext
|
||||
const content = await type.formatter(this.umap)
|
||||
const filename = Utils.slugify(this.umap.properties.name) + type.ext
|
||||
return { content, filetype: type.filetype, filename }
|
||||
}
|
||||
|
||||
|
@ -161,8 +162,8 @@ export default class Share {
|
|||
}
|
||||
|
||||
class IframeExporter {
|
||||
constructor(map) {
|
||||
this.map = map
|
||||
constructor(umap) {
|
||||
this.umap = umap
|
||||
this.baseUrl = Utils.getBaseUrl()
|
||||
this.options = {
|
||||
includeFullScreenLink: true,
|
||||
|
@ -192,22 +193,18 @@ class IframeExporter {
|
|||
height: '300px',
|
||||
}
|
||||
// Use map default, not generic default
|
||||
this.queryString.onLoadPanel = this.map.getOption('onLoadPanel')
|
||||
}
|
||||
|
||||
getMap() {
|
||||
return this.map
|
||||
this.queryString.onLoadPanel = this.umap.getOption('onLoadPanel')
|
||||
}
|
||||
|
||||
buildUrl(options) {
|
||||
const datalayers = []
|
||||
if (this.options.viewCurrentFeature && this.map.currentFeature) {
|
||||
this.queryString.feature = this.map.currentFeature.getSlug()
|
||||
if (this.options.viewCurrentFeature && this.umap.currentFeature) {
|
||||
this.queryString.feature = this.umap.currentFeature.getSlug()
|
||||
} else {
|
||||
delete this.queryString.feature
|
||||
}
|
||||
if (this.options.keepCurrentDatalayers) {
|
||||
this.map.eachDataLayer((datalayer) => {
|
||||
this.umap.eachDataLayer((datalayer) => {
|
||||
if (datalayer.isVisible() && datalayer.umap_id) {
|
||||
datalayers.push(datalayer.umap_id)
|
||||
}
|
||||
|
|
|
@ -13,20 +13,20 @@ const TOOLBOX_TEMPLATE = `
|
|||
`
|
||||
|
||||
export default class Slideshow extends WithTemplate {
|
||||
constructor(map, options) {
|
||||
constructor(umap, options) {
|
||||
super()
|
||||
this.map = map
|
||||
this.umap = umap
|
||||
this._id = null
|
||||
this.CLASSNAME = 'umap-slideshow-active'
|
||||
this.setOptions(options)
|
||||
this._current = null
|
||||
|
||||
if (this.options.autoplay) {
|
||||
this.map.onceDataLoaded(function () {
|
||||
this.umap.onceDataLoaded(function () {
|
||||
this.play()
|
||||
}, this)
|
||||
}
|
||||
this.map.on(
|
||||
this.umap._leafletMap.on(
|
||||
'edit:enabled',
|
||||
function () {
|
||||
this.stop()
|
||||
|
@ -65,7 +65,7 @@ export default class Slideshow extends WithTemplate {
|
|||
}
|
||||
|
||||
defaultDatalayer() {
|
||||
return this.map.findDataLayer((d) => d.canBrowse())
|
||||
return this.umap.findDataLayer((d) => d.canBrowse())
|
||||
}
|
||||
|
||||
startSpinner() {
|
||||
|
@ -83,7 +83,7 @@ export default class Slideshow extends WithTemplate {
|
|||
|
||||
play() {
|
||||
if (this._id) return
|
||||
if (this.map.editEnabled || !this.map.options.slideshow.active) return
|
||||
if (this.umap.editEnabled || !this.umap.options.slideshow.active) return
|
||||
L.DomUtil.addClass(document.body, this.CLASSNAME)
|
||||
this._id = window.setInterval(L.bind(this.loop, this), this.options.delay)
|
||||
this.startSpinner()
|
||||
|
|
|
@ -17,7 +17,7 @@ export default class TableEditor extends WithTemplate {
|
|||
constructor(datalayer) {
|
||||
super()
|
||||
this.datalayer = datalayer
|
||||
this.map = this.datalayer.map
|
||||
this.umap = this.datalayer.umap
|
||||
this.contextmenu = new ContextMenu({ className: 'dark' })
|
||||
this.table = this.loadTemplate(TEMPLATE)
|
||||
if (!this.datalayer.isRemoteLayer()) {
|
||||
|
@ -36,20 +36,20 @@ export default class TableEditor extends WithTemplate {
|
|||
openHeaderMenu(property) {
|
||||
const actions = []
|
||||
let filterItem
|
||||
if (this.map.facets.has(property)) {
|
||||
if (this.umap.facets.has(property)) {
|
||||
filterItem = {
|
||||
label: translate('Remove filter for this column'),
|
||||
action: () => {
|
||||
this.map.facets.remove(property)
|
||||
this.map.browser.open('filters')
|
||||
this.umap.facets.remove(property)
|
||||
this.umap.browser.open('filters')
|
||||
},
|
||||
}
|
||||
} else {
|
||||
filterItem = {
|
||||
label: translate('Add filter for this column'),
|
||||
action: () => {
|
||||
this.map.facets.add(property)
|
||||
this.map.browser.open('filters')
|
||||
this.umap.facets.add(property)
|
||||
this.umap.browser.open('filters')
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -86,8 +86,8 @@ export default class TableEditor extends WithTemplate {
|
|||
}
|
||||
|
||||
renderBody() {
|
||||
const bounds = this.map.getBounds()
|
||||
const inBbox = this.map.browser.options.inBbox
|
||||
const bounds = this.umap._leafletMap.getBounds()
|
||||
const inBbox = this.umap.browser.options.inBbox
|
||||
let html = ''
|
||||
this.datalayer.eachFeature((feature) => {
|
||||
if (feature.isFiltered()) return
|
||||
|
@ -121,7 +121,7 @@ export default class TableEditor extends WithTemplate {
|
|||
}
|
||||
|
||||
renameProperty(property) {
|
||||
this.map.dialog
|
||||
this.umap.dialog
|
||||
.prompt(translate('Please enter the new name of this property'))
|
||||
.then(({ prompt }) => {
|
||||
if (!prompt || !this.validateName(prompt)) return
|
||||
|
@ -135,7 +135,7 @@ export default class TableEditor extends WithTemplate {
|
|||
}
|
||||
|
||||
deleteProperty(property) {
|
||||
this.map.dialog
|
||||
this.umap.dialog
|
||||
.confirm(
|
||||
translate('Are you sure you want to delete this property on all the features?')
|
||||
)
|
||||
|
@ -150,7 +150,7 @@ export default class TableEditor extends WithTemplate {
|
|||
}
|
||||
|
||||
addProperty() {
|
||||
this.map.dialog
|
||||
this.umap.dialog
|
||||
.prompt(translate('Please enter the name of the property'))
|
||||
.then(({ prompt }) => {
|
||||
if (!prompt || !this.validateName(prompt)) return
|
||||
|
@ -187,10 +187,10 @@ export default class TableEditor extends WithTemplate {
|
|||
<button class="flat" type="button" data-ref="filters">
|
||||
<i class="icon icon-16 icon-filters"></i>${translate('Filter data')}
|
||||
</button>`)
|
||||
filterButton.addEventListener('click', () => this.map.browser.open('filters'))
|
||||
filterButton.addEventListener('click', () => this.umap.browser.open('filters'))
|
||||
actions.push(filterButton)
|
||||
|
||||
this.map.fullPanel.open({
|
||||
this.umap.fullPanel.open({
|
||||
content: this.table,
|
||||
className: 'umap-table-editor',
|
||||
actions: actions,
|
||||
|
@ -304,7 +304,7 @@ export default class TableEditor extends WithTemplate {
|
|||
deleteRows() {
|
||||
const selectedRows = this.getSelectedRows()
|
||||
if (!selectedRows.length) return
|
||||
this.map.dialog
|
||||
this.umap.dialog
|
||||
.confirm(
|
||||
translate('Found {count} rows. Are you sure you want to delete all?', {
|
||||
count: selectedRows.length,
|
||||
|
@ -320,9 +320,9 @@ export default class TableEditor extends WithTemplate {
|
|||
this.datalayer.show()
|
||||
this.datalayer.dataChanged()
|
||||
this.renderBody()
|
||||
if (this.map.browser.isOpen()) {
|
||||
this.map.browser.resetFilters()
|
||||
this.map.browser.open('filters')
|
||||
if (this.umap.browser.isOpen()) {
|
||||
this.umap.browser.resetFilters()
|
||||
this.umap.browser.open('filters')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@ import { DomEvent, DomUtil } from '../../../vendors/leaflet/leaflet-src.esm.js'
|
|||
import { translate } from '../i18n.js'
|
||||
|
||||
export class Panel {
|
||||
constructor(map) {
|
||||
this.parent = map._controlContainer
|
||||
this.map = map
|
||||
constructor(umap) {
|
||||
this.parent = umap._leafletMap._controlContainer
|
||||
this.umap = umap
|
||||
this.container = DomUtil.create('div', '', this.parent)
|
||||
// This will be set once according to the panel configurated at load
|
||||
// or by using panels as popups
|
||||
|
@ -80,26 +80,26 @@ export class Panel {
|
|||
onClose() {
|
||||
if (DomUtil.hasClass(this.container, 'on')) {
|
||||
DomUtil.removeClass(this.container, 'on')
|
||||
this.map.invalidateSize({ pan: false })
|
||||
this.umap._leafletMap.invalidateSize({ pan: false })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class EditPanel extends Panel {
|
||||
constructor(map) {
|
||||
super(map)
|
||||
constructor(umap) {
|
||||
super(umap)
|
||||
this.className = 'right dark'
|
||||
}
|
||||
|
||||
onClose() {
|
||||
super.onClose()
|
||||
this.map.editedFeature = null
|
||||
this.umap.editedFeature = null
|
||||
}
|
||||
}
|
||||
|
||||
export class FullPanel extends Panel {
|
||||
constructor(map) {
|
||||
super(map)
|
||||
constructor(umap) {
|
||||
super(umap)
|
||||
this.className = 'full dark'
|
||||
this.mode = 'expanded'
|
||||
}
|
||||
|
|
1603
umap/static/umap/js/modules/umap.js
Normal file
1603
umap/static/umap/js/modules/umap.js
Normal file
File diff suppressed because it is too large
Load diff
|
@ -41,7 +41,7 @@ export function getImpactsFromSchema(fields, schema) {
|
|||
// remove the option prefix for fields
|
||||
// And only keep the first part in case of a subfield
|
||||
// (e.g "options.limitBounds.foobar" will just return "limitBounds")
|
||||
return field.replace('options.', '').split('.')[0]
|
||||
return field.replace('options.', '').replace('properties.', '').split('.')[0]
|
||||
})
|
||||
.reduce((acc, field) => {
|
||||
// retrieve the "impacts" field from the schema
|
||||
|
|
|
@ -2,7 +2,7 @@ U.BaseAction = L.ToolbarAction.extend({
|
|||
initialize: function (map) {
|
||||
this.map = map
|
||||
if (this.options.label) {
|
||||
this.options.tooltip = this.map.help.displayLabel(
|
||||
this.options.tooltip = this.map.umap.help.displayLabel(
|
||||
this.options.label,
|
||||
(withKbdTag = false)
|
||||
)
|
||||
|
@ -25,7 +25,7 @@ U.ImportAction = U.BaseAction.extend({
|
|||
},
|
||||
|
||||
addHooks: function () {
|
||||
this.map.importer.open()
|
||||
this.map.umap.importer.open()
|
||||
},
|
||||
})
|
||||
|
||||
|
@ -37,7 +37,7 @@ U.EditLayersAction = U.BaseAction.extend({
|
|||
},
|
||||
|
||||
addHooks: function () {
|
||||
this.map.editDatalayers()
|
||||
this.map.umap.editDatalayers()
|
||||
},
|
||||
})
|
||||
|
||||
|
@ -49,7 +49,7 @@ U.EditCaptionAction = U.BaseAction.extend({
|
|||
},
|
||||
|
||||
addHooks: function () {
|
||||
this.map.editCaption()
|
||||
this.map.umap.editCaption()
|
||||
},
|
||||
})
|
||||
|
||||
|
@ -61,7 +61,7 @@ U.EditPropertiesAction = U.BaseAction.extend({
|
|||
},
|
||||
|
||||
addHooks: function () {
|
||||
this.map.edit()
|
||||
this.map.umap.edit()
|
||||
},
|
||||
})
|
||||
|
||||
|
@ -84,7 +84,7 @@ U.UpdateExtentAction = U.BaseAction.extend({
|
|||
},
|
||||
|
||||
addHooks: function () {
|
||||
this.map.setCenterAndZoom()
|
||||
this.map.umap.setCenterAndZoom()
|
||||
},
|
||||
})
|
||||
|
||||
|
@ -95,7 +95,7 @@ U.UpdatePermsAction = U.BaseAction.extend({
|
|||
},
|
||||
|
||||
addHooks: function () {
|
||||
this.map.permissions.edit()
|
||||
this.map.umap.permissions.edit()
|
||||
},
|
||||
})
|
||||
|
||||
|
@ -142,7 +142,8 @@ U.AddPolylineShapeAction = U.BaseAction.extend({
|
|||
},
|
||||
|
||||
addHooks: function () {
|
||||
this.map.editedFeature.ui.editor.newShape()
|
||||
// FIXME: smells bad
|
||||
this.map.umap.editedFeature.ui.editor.newShape()
|
||||
},
|
||||
})
|
||||
|
||||
|
@ -305,18 +306,24 @@ U.DrawToolbar = L.Toolbar.Control.extend({
|
|||
|
||||
appendToContainer: function (container) {
|
||||
this.options.actions = []
|
||||
if (this.map.options.enableMarkerDraw) {
|
||||
if (this.map.umap.properties.enableMarkerDraw) {
|
||||
this.options.actions.push(U.DrawMarkerAction)
|
||||
}
|
||||
if (this.map.options.enablePolylineDraw) {
|
||||
if (this.map.umap.properties.enablePolylineDraw) {
|
||||
this.options.actions.push(U.DrawPolylineAction)
|
||||
if (this.map.editedFeature && this.map.editedFeature instanceof U.LineString) {
|
||||
if (
|
||||
this.map.umap.editedFeature &&
|
||||
this.map.umap.editedFeature instanceof U.LineString
|
||||
) {
|
||||
this.options.actions.push(U.AddPolylineShapeAction)
|
||||
}
|
||||
}
|
||||
if (this.map.options.enablePolygonDraw) {
|
||||
if (this.map.umap.properties.enablePolygonDraw) {
|
||||
this.options.actions.push(U.DrawPolygonAction)
|
||||
if (this.map.editedFeature && this.map.editedFeature instanceof U.Polygon) {
|
||||
if (
|
||||
this.map.umap.editedFeature &&
|
||||
this.map.umap.editedFeature instanceof U.Polygon
|
||||
) {
|
||||
this.options.actions.push(U.AddPolygonShapeAction)
|
||||
}
|
||||
}
|
||||
|
@ -360,14 +367,14 @@ U.DropControl = L.Class.extend({
|
|||
L.DomEvent.stop(e)
|
||||
},
|
||||
|
||||
drop: function (e) {
|
||||
drop: function (event) {
|
||||
this.map.scrollWheelZoom.enable()
|
||||
this.dropzone.classList.remove('umap-dragover')
|
||||
L.DomEvent.stop(e)
|
||||
for (let i = 0, file; (file = e.dataTransfer.files[i]); i++) {
|
||||
this.map.processFileToImport(file)
|
||||
for (const file of event.dataTransfer.files) {
|
||||
this.map.umap.processFileToImport(file)
|
||||
}
|
||||
this.map.onceDataLoaded(this.map.fitDataBounds)
|
||||
this.map.umap.onceDataLoaded(this.map.umap.fitDataBounds)
|
||||
},
|
||||
|
||||
dragleave: function () {
|
||||
|
@ -387,15 +394,15 @@ U.EditControl = L.Control.extend({
|
|||
'',
|
||||
container,
|
||||
L._('Edit'),
|
||||
map.enableEdit,
|
||||
map
|
||||
map.umap.enableEdit,
|
||||
map.umap
|
||||
)
|
||||
L.DomEvent.on(
|
||||
enableEditing,
|
||||
'mouseover',
|
||||
() => {
|
||||
map.tooltip.open({
|
||||
content: map.help.displayLabel('TOGGLE_EDIT'),
|
||||
map.umap.tooltip.open({
|
||||
content: map.umap.help.displayLabel('TOGGLE_EDIT'),
|
||||
anchor: enableEditing,
|
||||
position: 'bottom',
|
||||
delay: 750,
|
||||
|
@ -476,8 +483,8 @@ U.PermanentCreditsControl = L.Control.extend({
|
|||
})
|
||||
|
||||
L.Control.Button = L.Control.extend({
|
||||
initialize: function (map, options) {
|
||||
this.map = map
|
||||
initialize: function (umap, options) {
|
||||
this.umap = umap
|
||||
L.Control.prototype.initialize.call(this, options)
|
||||
},
|
||||
|
||||
|
@ -510,11 +517,11 @@ U.DataLayersControl = L.Control.Button.extend({
|
|||
},
|
||||
|
||||
afterAdd: function (container) {
|
||||
U.Utils.toggleBadge(container, this.map.browser.hasFilters())
|
||||
U.Utils.toggleBadge(container, this.umap.browser?.hasFilters())
|
||||
},
|
||||
|
||||
onClick: function () {
|
||||
this.map.openBrowser()
|
||||
this.umap.openBrowser()
|
||||
},
|
||||
})
|
||||
|
||||
|
@ -526,7 +533,7 @@ U.CaptionControl = L.Control.Button.extend({
|
|||
},
|
||||
|
||||
onClick: function () {
|
||||
this.map.openCaption()
|
||||
this.umap.openCaption()
|
||||
},
|
||||
})
|
||||
|
||||
|
@ -537,12 +544,13 @@ U.StarControl = L.Control.Button.extend({
|
|||
},
|
||||
|
||||
getClassName: function () {
|
||||
const status = this.map.options.starred ? ' starred' : ''
|
||||
const status = this.umap.properties.starred ? ' starred' : ''
|
||||
return `leaflet-control-star umap-control${status}`
|
||||
},
|
||||
|
||||
onClick: function () {
|
||||
this.map.star()
|
||||
console.log(this.umap)
|
||||
this.umap.star()
|
||||
},
|
||||
})
|
||||
|
||||
|
@ -554,248 +562,10 @@ L.Control.Embed = L.Control.Button.extend({
|
|||
},
|
||||
|
||||
onClick: function () {
|
||||
this.map.share.open()
|
||||
this.umap.share.open()
|
||||
},
|
||||
})
|
||||
|
||||
const ControlsMixin = {
|
||||
HIDDABLE_CONTROLS: [
|
||||
'zoom',
|
||||
'search',
|
||||
'fullscreen',
|
||||
'embed',
|
||||
'datalayers',
|
||||
'caption',
|
||||
'locate',
|
||||
'measure',
|
||||
'editinosm',
|
||||
'star',
|
||||
'tilelayers',
|
||||
],
|
||||
|
||||
renderEditToolbar: function () {
|
||||
const className = 'umap-main-edit-toolbox'
|
||||
const container =
|
||||
document.querySelector(`.${className}`) ||
|
||||
L.DomUtil.create(
|
||||
'div',
|
||||
`${className} with-transition dark`,
|
||||
this._controlContainer
|
||||
)
|
||||
container.innerHTML = ''
|
||||
const leftContainer = L.DomUtil.create('div', 'umap-left-edit-toolbox', container)
|
||||
const rightContainer = L.DomUtil.create('div', 'umap-right-edit-toolbox', container)
|
||||
const logo = L.DomUtil.create('div', 'logo', leftContainer)
|
||||
L.DomUtil.createLink('', logo, 'uMap', '/', null, L._('Go to the homepage'))
|
||||
const nameButton = L.DomUtil.createButton('map-name', leftContainer, '')
|
||||
L.DomEvent.on(
|
||||
nameButton,
|
||||
'mouseover',
|
||||
function () {
|
||||
this.tooltip.open({
|
||||
content: L._('Edit the title of the map'),
|
||||
anchor: nameButton,
|
||||
position: 'bottom',
|
||||
delay: 500,
|
||||
duration: 5000,
|
||||
})
|
||||
},
|
||||
this
|
||||
)
|
||||
const shareStatusButton = L.DomUtil.createButton(
|
||||
'share-status',
|
||||
leftContainer,
|
||||
'',
|
||||
this.permissions.edit,
|
||||
this.permissions
|
||||
)
|
||||
L.DomEvent.on(
|
||||
shareStatusButton,
|
||||
'mouseover',
|
||||
function () {
|
||||
this.tooltip.open({
|
||||
content: L._('Update who can see and edit the map'),
|
||||
anchor: shareStatusButton,
|
||||
position: 'bottom',
|
||||
delay: 500,
|
||||
duration: 5000,
|
||||
})
|
||||
},
|
||||
this
|
||||
)
|
||||
if (this.options.editMode === 'advanced') {
|
||||
L.DomEvent.on(nameButton, 'click', this.editCaption, this)
|
||||
L.DomEvent.on(shareStatusButton, 'click', this.permissions.edit, this.permissions)
|
||||
}
|
||||
if (this.options.user?.id) {
|
||||
const button = U.Utils.loadTemplate(`
|
||||
<button class="umap-user flat" type="button">
|
||||
<i class="icon icon-16 icon-profile"></i>
|
||||
<span>${this.options.user.name}</span>
|
||||
</button>
|
||||
`)
|
||||
rightContainer.appendChild(button)
|
||||
const menu = new U.ContextMenu({ className: 'dark', fixed: true })
|
||||
const actions = [
|
||||
{
|
||||
label: L._('New map'),
|
||||
action: this.urls.get('map_new'),
|
||||
},
|
||||
{
|
||||
label: L._('My maps'),
|
||||
action: this.urls.get('user_dashboard'),
|
||||
},
|
||||
{
|
||||
label: L._('My teams'),
|
||||
action: this.urls.get('user_teams'),
|
||||
},
|
||||
]
|
||||
if (this.urls.has('user_profile')) {
|
||||
actions.push({
|
||||
label: L._('My profile'),
|
||||
action: this.urls.get('user_profile'),
|
||||
})
|
||||
}
|
||||
button.addEventListener('click', () => {
|
||||
menu.openBelow(button, actions)
|
||||
})
|
||||
}
|
||||
|
||||
const connectedPeers = this.sync.getNumberOfConnectedPeers()
|
||||
if (connectedPeers !== 0) {
|
||||
const connectedPeersCount = L.DomUtil.createButton(
|
||||
'leaflet-control-connected-peers',
|
||||
rightContainer,
|
||||
''
|
||||
)
|
||||
L.DomEvent.on(connectedPeersCount, 'mouseover', () => {
|
||||
this.tooltip.open({
|
||||
content: L._('{connectedPeers} peer(s) currently connected to this map', {
|
||||
connectedPeers: connectedPeers,
|
||||
}),
|
||||
anchor: connectedPeersCount,
|
||||
position: 'bottom',
|
||||
delay: 500,
|
||||
duration: 5000,
|
||||
})
|
||||
})
|
||||
|
||||
const updateConnectedPeersCount = () => {
|
||||
connectedPeersCount.innerHTML =
|
||||
'<span>' + this.sync.getNumberOfConnectedPeers() + '</span>'
|
||||
}
|
||||
updateConnectedPeersCount()
|
||||
}
|
||||
|
||||
this.help.getStartedLink(rightContainer)
|
||||
const controlEditCancel = L.DomUtil.createButton(
|
||||
'leaflet-control-edit-cancel',
|
||||
rightContainer,
|
||||
L.DomUtil.add('span', '', null, L._('Cancel edits')),
|
||||
this.askForReset,
|
||||
this
|
||||
)
|
||||
L.DomEvent.on(
|
||||
controlEditCancel,
|
||||
'mouseover',
|
||||
function () {
|
||||
this.tooltip.open({
|
||||
content: this.help.displayLabel('CANCEL'),
|
||||
anchor: controlEditCancel,
|
||||
position: 'bottom',
|
||||
delay: 500,
|
||||
duration: 5000,
|
||||
})
|
||||
},
|
||||
this
|
||||
)
|
||||
const controlEditDisable = L.DomUtil.createButton(
|
||||
'leaflet-control-edit-disable',
|
||||
rightContainer,
|
||||
L.DomUtil.add('span', '', null, L._('View')),
|
||||
this.disableEdit,
|
||||
this
|
||||
)
|
||||
L.DomEvent.on(
|
||||
controlEditDisable,
|
||||
'mouseover',
|
||||
function () {
|
||||
this.tooltip.open({
|
||||
content: this.help.displayLabel('PREVIEW'),
|
||||
anchor: controlEditDisable,
|
||||
position: 'bottom',
|
||||
delay: 500,
|
||||
duration: 5000,
|
||||
})
|
||||
},
|
||||
this
|
||||
)
|
||||
const controlEditSave = L.DomUtil.createButton(
|
||||
'leaflet-control-edit-save button',
|
||||
rightContainer,
|
||||
L.DomUtil.add('span', '', null, L._('Save')),
|
||||
this.saveAll,
|
||||
this
|
||||
)
|
||||
L.DomEvent.on(
|
||||
controlEditSave,
|
||||
'mouseover',
|
||||
function () {
|
||||
this.tooltip.open({
|
||||
content: this.help.displayLabel('SAVE'),
|
||||
anchor: controlEditSave,
|
||||
position: 'bottom',
|
||||
delay: 500,
|
||||
duration: 5000,
|
||||
})
|
||||
},
|
||||
this
|
||||
)
|
||||
},
|
||||
|
||||
editDatalayers: function () {
|
||||
if (!this.editEnabled) return
|
||||
const container = L.DomUtil.create('div')
|
||||
L.DomUtil.createTitle(container, L._('Manage layers'), 'icon-layers')
|
||||
const ul = L.DomUtil.create('ul', '', container)
|
||||
this.eachDataLayerReverse((datalayer) => {
|
||||
const row = L.DomUtil.create('li', 'orderable', ul)
|
||||
L.DomUtil.createIcon(row, 'icon-drag', L._('Drag to reorder'))
|
||||
datalayer.renderToolbox(row)
|
||||
const title = L.DomUtil.add('span', '', row, datalayer.options.name)
|
||||
row.classList.toggle('off', !datalayer.isVisible())
|
||||
title.textContent = datalayer.options.name
|
||||
row.dataset.id = L.stamp(datalayer)
|
||||
})
|
||||
const onReorder = (src, dst, initialIndex, finalIndex) => {
|
||||
const layer = this.datalayers[src.dataset.id]
|
||||
const other = this.datalayers[dst.dataset.id]
|
||||
const minIndex = Math.min(layer.getRank(), other.getRank())
|
||||
const maxIndex = Math.max(layer.getRank(), other.getRank())
|
||||
if (finalIndex === 0) layer.bringToTop()
|
||||
else if (finalIndex > initialIndex) layer.insertBefore(other)
|
||||
else layer.insertAfter(other)
|
||||
this.eachDataLayerReverse((datalayer) => {
|
||||
if (datalayer.getRank() >= minIndex && datalayer.getRank() <= maxIndex)
|
||||
datalayer.isDirty = true
|
||||
})
|
||||
this.indexDatalayers()
|
||||
}
|
||||
const orderable = new U.Orderable(ul, onReorder)
|
||||
|
||||
const bar = L.DomUtil.create('div', 'button-bar', container)
|
||||
L.DomUtil.createButton(
|
||||
'show-on-edit block add-datalayer button',
|
||||
bar,
|
||||
L._('Add a layer'),
|
||||
this.newDataLayer,
|
||||
this
|
||||
)
|
||||
|
||||
this.editPanel.open({ content: container })
|
||||
},
|
||||
}
|
||||
|
||||
/* Used in view mode to define the current tilelayer */
|
||||
U.TileLayerControl = L.Control.IconLayers.extend({
|
||||
initialize: function (map, options) {
|
||||
|
@ -819,7 +589,7 @@ U.TileLayerControl = L.Control.IconLayers.extend({
|
|||
// Fixme when https://github.com/Leaflet/Leaflet/pull/9201 is released
|
||||
const icon = U.Utils.template(
|
||||
layer.options.url_template,
|
||||
this.map.demoTileInfos
|
||||
this.map.options.demoTileInfos
|
||||
)
|
||||
layers.push({
|
||||
title: layer.options.name,
|
||||
|
@ -885,7 +655,7 @@ U.TileLayerChooser = L.Control.extend({
|
|||
L.DomUtil.createTitle(container, L._('Change tilelayers'), 'icon-tilelayer')
|
||||
this._tilelayers_container = L.DomUtil.create('ul', '', container)
|
||||
this.buildList(options)
|
||||
const panel = options.edit ? this.map.editPanel : this.map.panel
|
||||
const panel = options.edit ? this.map.umap.editPanel : this.map.umap.panel
|
||||
panel.open({ content: container })
|
||||
},
|
||||
|
||||
|
@ -905,7 +675,7 @@ U.TileLayerChooser = L.Control.extend({
|
|||
const el = L.DomUtil.create('li', selectedClass, this._tilelayers_container)
|
||||
const img = L.DomUtil.create('img', '', el)
|
||||
const name = L.DomUtil.create('div', '', el)
|
||||
img.src = U.Utils.template(tilelayer.options.url_template, this.map.demoTileInfos)
|
||||
img.src = U.Utils.template(tilelayer.options.url_template, this.map.options.demoTileInfos)
|
||||
img.loading = 'lazy'
|
||||
name.textContent = tilelayer.options.name
|
||||
L.DomEvent.on(
|
||||
|
@ -935,8 +705,8 @@ U.AttributionControl = L.Control.Attribution.extend({
|
|||
this._container.innerHTML = ''
|
||||
const container = L.DomUtil.create('div', 'attribution-container', this._container)
|
||||
container.innerHTML = credits
|
||||
const shortCredit = this._map.getOption('shortCredit')
|
||||
const captionMenus = this._map.getOption('captionMenus')
|
||||
const shortCredit = this._map.umap.getOption('shortCredit')
|
||||
const captionMenus = this._map.umap.getOption('captionMenus')
|
||||
if (shortCredit) {
|
||||
L.DomUtil.element({
|
||||
tagName: 'span',
|
||||
|
@ -947,7 +717,7 @@ U.AttributionControl = L.Control.Attribution.extend({
|
|||
if (captionMenus) {
|
||||
const link = L.DomUtil.add('a', '', container, ` — ${L._('Open caption')}`)
|
||||
L.DomEvent.on(link, 'click', L.DomEvent.stop)
|
||||
.on(link, 'click', this._map.openCaption, this._map)
|
||||
.on(link, 'click', () => this._map.umap.openCaption())
|
||||
.on(link, 'dblclick', L.DomEvent.stop)
|
||||
}
|
||||
if (window.top === window.self && captionMenus) {
|
||||
|
@ -1139,7 +909,7 @@ U.SearchControl = L.Control.extend({
|
|||
this.map.fire('dataload', { id: id })
|
||||
})
|
||||
this.search.resultsContainer = resultsContainer
|
||||
this.map.panel.open({ content: container }).then(input.focus())
|
||||
this.map.umap.panel.open({ content: container }).then(input.focus())
|
||||
},
|
||||
})
|
||||
|
||||
|
@ -1179,8 +949,9 @@ L.Control.Loading.include({
|
|||
})
|
||||
|
||||
U.Editable = L.Editable.extend({
|
||||
initialize: function (map, options) {
|
||||
L.Editable.prototype.initialize.call(this, map, options)
|
||||
initialize: function (umap, options) {
|
||||
this.umap = umap
|
||||
L.Editable.prototype.initialize.call(this, umap._leafletMap, options)
|
||||
this.on('editable:drawing:click editable:drawing:move', this.drawingTooltip)
|
||||
// Layer for items added by users
|
||||
this.on('editable:drawing:cancel', (event) => {
|
||||
|
@ -1188,7 +959,7 @@ U.Editable = L.Editable.extend({
|
|||
})
|
||||
this.on('editable:drawing:commit', function (event) {
|
||||
event.layer.feature.isDirty = true
|
||||
if (this.map.editedFeature !== event.layer) event.layer.feature.edit(event)
|
||||
if (this.umap.editedFeature !== event.layer) event.layer.feature.edit(event)
|
||||
})
|
||||
this.on('editable:editing', (event) => {
|
||||
const feature = event.layer.feature
|
||||
|
@ -1210,7 +981,7 @@ U.Editable = L.Editable.extend({
|
|||
},
|
||||
|
||||
createPolyline: function (latlngs) {
|
||||
const datalayer = this.map.defaultEditDataLayer()
|
||||
const datalayer = this.umap.defaultEditDataLayer()
|
||||
const point = new U.LineString(datalayer, {
|
||||
geometry: { type: 'LineString', coordinates: [] },
|
||||
})
|
||||
|
@ -1218,7 +989,7 @@ U.Editable = L.Editable.extend({
|
|||
},
|
||||
|
||||
createPolygon: function (latlngs) {
|
||||
const datalayer = this.map.defaultEditDataLayer()
|
||||
const datalayer = this.umap.defaultEditDataLayer()
|
||||
const point = new U.Polygon(datalayer, {
|
||||
geometry: { type: 'Polygon', coordinates: [] },
|
||||
})
|
||||
|
@ -1226,7 +997,7 @@ U.Editable = L.Editable.extend({
|
|||
},
|
||||
|
||||
createMarker: function (latlng) {
|
||||
const datalayer = this.map.defaultEditDataLayer()
|
||||
const datalayer = this.umap.defaultEditDataLayer()
|
||||
const point = new U.Point(datalayer, {
|
||||
geometry: { type: 'Point', coordinates: [latlng.lng, latlng.lat] },
|
||||
})
|
||||
|
@ -1235,15 +1006,15 @@ U.Editable = L.Editable.extend({
|
|||
|
||||
_getDefaultProperties: function () {
|
||||
const result = {}
|
||||
if (this.map.options.featuresHaveOwner?.user) {
|
||||
result.geojson = { properties: { owner: this.map.options.user.id } }
|
||||
if (this.umap.properties.featuresHaveOwner?.user) {
|
||||
result.geojson = { properties: { owner: this.umap.properties.user.id } }
|
||||
}
|
||||
return result
|
||||
},
|
||||
|
||||
connectCreatedToMap: function (layer) {
|
||||
// Overrided from Leaflet.Editable
|
||||
const datalayer = this.map.defaultEditDataLayer()
|
||||
const datalayer = this.umap.defaultEditDataLayer()
|
||||
datalayer.addFeature(layer.feature)
|
||||
layer.isDirty = true
|
||||
return layer
|
||||
|
@ -1251,7 +1022,7 @@ U.Editable = L.Editable.extend({
|
|||
|
||||
drawingTooltip: function (e) {
|
||||
if (e.layer instanceof L.Marker && e.type === 'editable:drawing:start') {
|
||||
this.map.tooltip.open({ content: L._('Click to add a marker') })
|
||||
this.umap.tooltip.open({ content: L._('Click to add a marker') })
|
||||
}
|
||||
if (!(e.layer instanceof L.Polyline)) {
|
||||
// only continue with Polylines and Polygons
|
||||
|
@ -1298,12 +1069,12 @@ U.Editable = L.Editable.extend({
|
|||
}
|
||||
}
|
||||
if (content) {
|
||||
this.map.tooltip.open({ content: content })
|
||||
this.umap.tooltip.open({ content: content })
|
||||
}
|
||||
},
|
||||
|
||||
closeTooltip: function () {
|
||||
this.map.ui.closeTooltip()
|
||||
this.umap.closeTooltip()
|
||||
},
|
||||
|
||||
onVertexRawClick: (e) => {
|
||||
|
@ -1314,7 +1085,7 @@ U.Editable = L.Editable.extend({
|
|||
|
||||
onEscape: function () {
|
||||
this.once('editable:drawing:end', (event) => {
|
||||
this.map.tooltip.close()
|
||||
this.umap.tooltip.close()
|
||||
// Leaflet.Editable will delete the drawn shape if invalid
|
||||
// (eg. line has only one drawn point)
|
||||
// So let's check if the layer has no more shape
|
||||
|
|
|
@ -25,48 +25,6 @@ L.Util.copyToClipboard = (textToCopy) => {
|
|||
}
|
||||
}
|
||||
|
||||
L.Util.queryString = (name, fallback) => {
|
||||
const decode = (s) => decodeURIComponent(s.replace(/\+/g, ' '))
|
||||
const qs = window.location.search.slice(1).split('&')
|
||||
const qa = {}
|
||||
for (const i in qs) {
|
||||
const key = qs[i].split('=')
|
||||
if (!key) continue
|
||||
qa[decode(key[0])] = key[1] ? decode(key[1]) : 1
|
||||
}
|
||||
return qa[name] || fallback
|
||||
}
|
||||
|
||||
L.Util.booleanFromQueryString = (name) => {
|
||||
const value = L.Util.queryString(name)
|
||||
return value === '1' || value === 'true'
|
||||
}
|
||||
|
||||
L.Util.setFromQueryString = (options, name) => {
|
||||
const value = L.Util.queryString(name)
|
||||
if (typeof value !== 'undefined') options[name] = value
|
||||
}
|
||||
|
||||
L.Util.setBooleanFromQueryString = (options, name) => {
|
||||
const value = L.Util.queryString(name)
|
||||
if (typeof value !== 'undefined') options[name] = value === '1' || value === 'true'
|
||||
}
|
||||
|
||||
L.Util.setNumberFromQueryString = (options, name) => {
|
||||
const value = +L.Util.queryString(name)
|
||||
if (!Number.isNaN(value)) options[name] = value
|
||||
}
|
||||
|
||||
L.Util.setNullableBooleanFromQueryString = (options, name) => {
|
||||
let value = L.Util.queryString(name)
|
||||
if (typeof value !== 'undefined') {
|
||||
if (value === 'null') value = null
|
||||
else if (value === '0' || value === 'false') value = false
|
||||
else value = true
|
||||
options[name] = value
|
||||
}
|
||||
}
|
||||
|
||||
L.DomUtil.add = (tagName, className, container, content) => {
|
||||
const el = L.DomUtil.create(tagName, className, container)
|
||||
if (content) {
|
||||
|
|
|
@ -221,14 +221,14 @@ L.FormBuilder.Element.include({
|
|||
this.label = L.DomUtil.create('label', '', this.getLabelParent())
|
||||
this.label.textContent = this.label.title = this.options.label
|
||||
if (this.options.helpEntries) {
|
||||
this.builder.map.help.button(this.label, this.options.helpEntries)
|
||||
this.builder.umap.help.button(this.label, this.options.helpEntries)
|
||||
} else if (this.options.helpTooltip) {
|
||||
const info = L.DomUtil.create('i', 'info', this.label)
|
||||
L.DomEvent.on(
|
||||
info,
|
||||
'mouseover',
|
||||
function () {
|
||||
this.builder.map.tooltip.open({
|
||||
this.builder.umap.tooltip.open({
|
||||
anchor: info,
|
||||
content: this.options.helpTooltip,
|
||||
position: 'top',
|
||||
|
@ -359,7 +359,7 @@ L.FormBuilder.SlideshowDelay = L.FormBuilder.IntSelect.extend({
|
|||
L.FormBuilder.DataLayerSwitcher = L.FormBuilder.Select.extend({
|
||||
getOptions: function () {
|
||||
const options = []
|
||||
this.builder.map.eachDataLayerReverse((datalayer) => {
|
||||
this.builder.umap.eachDataLayerReverse((datalayer) => {
|
||||
if (
|
||||
datalayer.isLoaded() &&
|
||||
!datalayer.isDataReadOnly() &&
|
||||
|
@ -376,11 +376,11 @@ L.FormBuilder.DataLayerSwitcher = L.FormBuilder.Select.extend({
|
|||
},
|
||||
|
||||
toJS: function () {
|
||||
return this.builder.map.datalayers[this.value()]
|
||||
return this.builder.umap.datalayers[this.value()]
|
||||
},
|
||||
|
||||
set: function () {
|
||||
this.builder.map.lastUsedDataLayer = this.toJS()
|
||||
this.builder.umap.lastUsedDataLayer = this.toJS()
|
||||
this.obj.changeDataLayer(this.toJS())
|
||||
},
|
||||
})
|
||||
|
@ -400,7 +400,7 @@ L.FormBuilder.DataFormat = L.FormBuilder.Select.extend({
|
|||
L.FormBuilder.LicenceChooser = L.FormBuilder.Select.extend({
|
||||
getOptions: function () {
|
||||
const licences = []
|
||||
const licencesList = this.builder.obj.options.licences
|
||||
const licencesList = this.builder.obj.properties.licences
|
||||
let licence
|
||||
for (const i in licencesList) {
|
||||
licence = licencesList[i]
|
||||
|
@ -414,7 +414,7 @@ L.FormBuilder.LicenceChooser = L.FormBuilder.Select.extend({
|
|||
},
|
||||
|
||||
toJS: function () {
|
||||
return this.builder.obj.options.licences[this.value()]
|
||||
return this.builder.obj.properties.licences[this.value()]
|
||||
},
|
||||
})
|
||||
|
||||
|
@ -469,8 +469,8 @@ L.FormBuilder.IconUrl = L.FormBuilder.BlurInput.extend({
|
|||
onDefine: async function () {
|
||||
this.buttons.innerHTML = ''
|
||||
this.footer.innerHTML = ''
|
||||
const [{ pictogram_list }, response, error] = await this.builder.map.server.get(
|
||||
this.builder.map.options.urls.pictogram_list_json
|
||||
const [{ pictogram_list }, response, error] = await this.builder.umap.server.get(
|
||||
this.builder.umap.properties.urls.pictogram_list_json
|
||||
)
|
||||
if (!error) this.pictogram_list = pictogram_list
|
||||
this.buildTabs()
|
||||
|
@ -616,7 +616,7 @@ L.FormBuilder.IconUrl = L.FormBuilder.BlurInput.extend({
|
|||
categories[category].push(props)
|
||||
}
|
||||
const sorted = Object.entries(categories).toSorted(([a], [b]) =>
|
||||
U.Utils.naturalSort(a, b, L.lang)
|
||||
U.Utils.naturalSort(a, b, U.lang)
|
||||
)
|
||||
for (const [name, items] of sorted) {
|
||||
this.addCategory(items, name)
|
||||
|
@ -1167,8 +1167,8 @@ U.FormBuilder = L.FormBuilder.extend({
|
|||
}
|
||||
},
|
||||
|
||||
initialize: function (obj, fields, options) {
|
||||
this.map = obj.map || obj.getMap()
|
||||
initialize: function (obj, fields, options = {}) {
|
||||
this.umap = obj.umap || options.umap
|
||||
this.computeDefaultOptions()
|
||||
L.FormBuilder.prototype.initialize.call(this, obj, fields, options)
|
||||
this.on('finish', this.finish)
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -63,7 +63,11 @@ L.FormBuilder = L.Evented.extend({
|
|||
const path = field.split('.')
|
||||
let value = this.obj
|
||||
for (const sub of path) {
|
||||
value = value[sub]
|
||||
try {
|
||||
value = value[sub]
|
||||
} catch {
|
||||
console.log(field)
|
||||
}
|
||||
}
|
||||
return value
|
||||
},
|
||||
|
|
|
@ -41,5 +41,4 @@
|
|||
<script src="{% static 'umap/js/umap.core.js' %}" defer></script>
|
||||
<script src="{% static 'umap/js/umap.forms.js' %}" defer></script>
|
||||
<script src="{% static 'umap/js/umap.controls.js' %}" defer></script>
|
||||
<script src="{% static 'umap/js/umap.js' %}" defer></script>
|
||||
<script src="{% static 'umap/js/components/fragment.js' %}" defer></script>
|
||||
<script type="module" src="{% static 'umap/js/components/fragment.js' %}" defer></script>
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
{% load umap_tags %}
|
||||
{% load umap_tags static %}
|
||||
|
||||
{% include "umap/messages.html" %}
|
||||
<div id="map">
|
||||
</div>
|
||||
<!-- djlint:off -->
|
||||
<script defer type="text/javascript">
|
||||
window.addEventListener('DOMContentLoaded', (event) => {
|
||||
U.MAP = new U.Map("map", {{ map_settings|notag|safe }})
|
||||
})
|
||||
<script defer type="module">
|
||||
import Umap from '{% static "umap/js/modules/umap.js" %}'
|
||||
U.MAP = new Umap("map", {{ map_settings|notag|safe }})
|
||||
</script>
|
||||
<!-- djlint:on -->
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{% extends "umap/content.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load i18n static %}
|
||||
|
||||
{% block head_title %}
|
||||
{{ SITE_NAME }} - {% trans "My Dashboard" %}
|
||||
|
@ -45,23 +45,22 @@
|
|||
{% endblock maincontent %}
|
||||
{% block bottom_js %}
|
||||
{{ block.super }}
|
||||
<script type="text/javascript">
|
||||
!(function () {
|
||||
const CACHE = {}
|
||||
for (const mapOpener of document.querySelectorAll("button.map-opener")) {
|
||||
mapOpener.addEventListener('click', (event) => {
|
||||
const button = event.target.closest('button')
|
||||
button.nextElementSibling.showModal()
|
||||
const mapId = button.dataset.mapId
|
||||
if (!document.querySelector(`#${mapId}_target`).children.length) {
|
||||
const previewSettings = JSON.parse(document.getElementById(mapId).textContent)
|
||||
const map = new U.Map(`${mapId}_target`, previewSettings)
|
||||
CACHE[mapId] = map
|
||||
} else {
|
||||
CACHE[mapId].invalidateSize()
|
||||
}
|
||||
})
|
||||
}
|
||||
})()
|
||||
<script type="module">
|
||||
import Umap from '{% static "umap/js/modules/umap.js" %}'
|
||||
const CACHE = {}
|
||||
for (const mapOpener of document.querySelectorAll("button.map-opener")) {
|
||||
mapOpener.addEventListener('click', (event) => {
|
||||
const button = event.target.closest('button')
|
||||
button.nextElementSibling.showModal()
|
||||
const mapId = button.dataset.mapId
|
||||
if (!document.querySelector(`#${mapId}_target`).children.length) {
|
||||
const previewSettings = JSON.parse(document.getElementById(mapId).textContent)
|
||||
const map = new Umap(`${mapId}_target`, previewSettings)
|
||||
CACHE[mapId] = map
|
||||
} else {
|
||||
CACHE[mapId].invalidateSize()
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
{% endblock bottom_js %}
|
||||
|
|
|
@ -93,10 +93,10 @@ def test_umap_import_from_textarea(live_server, tilelayer, page, settings):
|
|||
page.locator('img[src="https://tile.openstreetmap.fr/hot/6/32/21.png"]')
|
||||
).to_be_visible()
|
||||
# Should not have imported umap_id, while in the file options
|
||||
assert not page.evaluate("U.MAP.options.umap_id")
|
||||
assert not page.evaluate("U.MAP.properties.umap_id")
|
||||
with page.expect_response(re.compile(r".*/datalayer/create/.*")):
|
||||
page.get_by_role("button", name="Save").click()
|
||||
assert page.evaluate("U.MAP.options.umap_id")
|
||||
assert page.evaluate("U.MAP.properties.umap_id")
|
||||
|
||||
|
||||
def test_import_geojson_from_textarea(tilelayer, live_server, page):
|
||||
|
|
Loading…
Reference in a new issue