wip: move panel to a dedicated module

This commit is contained in:
Yohan Boniface 2024-03-14 20:29:28 +01:00
parent 1e2d990a3a
commit c4e86c4ab9
16 changed files with 311 additions and 224 deletions

View file

@ -544,7 +544,6 @@ i.info {
.permissions-panel, .permissions-panel,
.umap-upload, .umap-upload,
.umap-share, .umap-share,
.umap-edit-container,
.umap-datalayer-container, .umap-datalayer-container,
.umap-layer-properties-container, .umap-layer-properties-container,
.umap-browse-data, .umap-browse-data,
@ -711,9 +710,6 @@ input[type=hidden].blur + [type="button"] {
.leaflet-right { .leaflet-right {
transition: all .7s; transition: all .7s;
} }
.umap-ui .leaflet-right {
right: 400px;
}
#umap-panel, #umap-panel,
#umap-alert-container, #umap-alert-container,
#umap-tooltip-container { #umap-tooltip-container {
@ -941,44 +937,7 @@ input:invalid {
/* *********** */ /* *********** */
/* Mobile */ /* Mobile */
/* *********** */ /* *********** */
@media all and (orientation:landscape) {
.umap-edit-enabled #umap-panel {
top: 46px;
}
#umap-panel {
width: 400px;
right: -400px;
top: 0;
}
.umap-ui #umap-panel {
right: 0;
visibility: visible;
}
#umap-panel.condensed {
margin-top: 10px;
margin-right: 10px;
max-height: 500px;
bottom: initial;
width: 390px;
border-radius: 5px;
border: 1px solid var(--color-lightGray);
}
}
@media all and (orientation:portrait) { @media all and (orientation:portrait) {
#umap-panel {
height: 50%;
max-height: 400px;
width: 100%;
bottom: 0;
right: -100%;
}
.umap-ui #umap-panel {
right: 0;
visibility: visible;
}
.umap-ui .leaflet-right {
right: 0;
}
#umap-alert-container { #umap-alert-container {
width: 100%; width: 100%;
left: 0; left: 0;

View file

@ -0,0 +1,120 @@
.panel {
/* Added for playwright to consider the element as non visible */
/* as being out of the visible viewport is not enough */
visibility: hidden;
position: absolute;
bottom: 20px;
overflow-x: auto;
z-index: 1010;
background-color: #fff;
opacity: 0.98;
cursor: initial;
border-radius: 5px;
border: 1px solid var(--color-lightGray);
}
.panel.dark {
border-left: 1px solid #222;
background-color: var(--color-darkGray);
color: #efefef;
}
.panel.fullwidth {
width: 100%;
right: -100%;
z-index: 10000;
padding-left: 0;
padding-right: 0;
}
.umap-caption-bar-enabled .panel {
bottom: 46px;
}
.panel {
-moz-box-sizing:border-box;
-webkit-box-sizing:border-box;
box-sizing: border-box;
}
.panel .umap-popup-content img {
/* See https://github.com/Leaflet/Leaflet/commit/61d746818b99d362108545c151a27f09d60960ee#commitcomment-6061847 */
max-width: 99% !important;
}
.panel .umap-popup-content {
max-height: inherit;
}
.panel .body {
clear: both;
height: calc(100% - 32px); /* Minus size of toolbox */
padding: 10px;
}
.panel .toolbox {
padding: 5px 10px;
overflow: hidden;
display: flex;
flex-direction: row-reverse;
font-size: 10px;
justify-content: flex-start;
gap: 5px;
line-height: 2.2em;
}
.panel.dark .toolbox {
background-color: var(--color-darkGray);
border-bottom: 1px solid #232729;
}
.panel .toolbox li {
cursor: pointer;
display: inline;
padding: 0 2px;
border: 1px solid #b6b6b3;
border-radius: 2px;
}
.panel.dark .toolbox
.panel.dark .toolbox li {
color: #d3dfeb;
border: 1px solid #202425;
}
.panel .toolbox li:hover {
background-color: #d4d4d2;
}
.panel.dark .toolbox li:hover {
background-color: #353c3e;
}
@media all and (orientation:landscape) {
.panel {
top: 0;
margin-top: 10px;
width: 390px;
}
.panel.condensed {
max-height: 500px;
bottom: initial;
}
.panel.right {
margin-right: 10px;
right: -400px;
}
.panel.left {
left: -400px;
}
.panel.left.on {
left: 60px;
visibility: visible;
}
.panel.right.on {
right: 40px;
visibility: visible;
}
.umap-edit-enabled .panel {
top: 46px;
}
}
@media all and (orientation:portrait) {
.panel {
height: 50%;
max-height: 400px;
width: 100%;
bottom: 0;
right: -100%;
}
.panel.on {
right: 0;
visibility: visible;
}
}

View file

@ -1,13 +1,10 @@
import { DomUtil, DomEvent } from '../../vendors/leaflet/leaflet-src.esm.js' import { DomUtil, DomEvent } from '../../vendors/leaflet/leaflet-src.esm.js'
import Orderable from './orderable.js' import { translate } from './i18n.js'
import {translate} from './i18n.js'
export default class Browser { export default class Browser {
constructor(map) { constructor(map) {
this.map = map this.map = map
this.map.on('moveend', this.onMoveEnd, this) this.map.on('moveend', this.onMoveEnd, this)
this.map.on('edit:enabled', this.onEnableEdit, this)
this.map.on('edit:disabled', this.onDisableEdit, this)
this.options = { this.options = {
filter: '', filter: '',
inBbox: false, inBbox: false,
@ -72,13 +69,9 @@ export default class Browser {
} }
addDataLayer(datalayer, parent) { addDataLayer(datalayer, parent) {
let className = `orderable datalayer ${datalayer.getHidableClass()}` let className = `datalayer ${datalayer.getHidableClass()}`
if (this.map.ui.PANEL_MODE !== 'condensed') className += ' show-list' if (this.map.panel.MODE !== 'condensed') className += ' show-list'
const container = DomUtil.create( const container = DomUtil.create('div', className, parent),
'div',
className,
parent
),
headline = DomUtil.create('h5', '', container) headline = DomUtil.create('h5', '', container)
container.id = this.datalayerId(datalayer) container.id = this.datalayerId(datalayer)
const ul = DomUtil.create('ul', '', container) const ul = DomUtil.create('ul', '', container)
@ -87,7 +80,6 @@ export default class Browser {
this.map.ui.once('panel:closed', () => { this.map.ui.once('panel:closed', () => {
datalayer.off('datachanged', this.onDataLayerChanged, this) datalayer.off('datachanged', this.onDataLayerChanged, this)
}) })
container.dataset.id = L.stamp(datalayer)
} }
updateDatalayer(datalayer) { updateDatalayer(datalayer) {
@ -125,7 +117,7 @@ export default class Browser {
}) })
} }
isOpen () { isOpen() {
return !!document.querySelector('.umap-browser') return !!document.querySelector('.umap-browser')
} }
@ -160,70 +152,19 @@ export default class Browser {
}) })
formContainer.appendChild(builder.build()) formContainer.appendChild(builder.build())
const addButton = L.DomUtil.create('li', 'add-datalayer show-on-edit') this.map.panel.open({
L.DomUtil.create('i', 'umap-icon-16 umap-add', addButton)
const label = L.DomUtil.create('span', '', addButton)
label.textContent = label.title = L._('Add a layer')
const addProperty = function () {
const newName = prompt(L._('Please enter the name of the property'))
if (!newName || !this.validateName(newName)) return
this.datalayer.indexProperty(newName)
this.edit()
}
L.DomEvent.on(addButton, 'click', this.newDataLayer, this)
let className = 'umap-browser'
if (this.map.editEnabled) className += ' dark'
this.map.ui.openPanel({
data: { html: container }, data: { html: container },
className: className, className: 'umap-browser',
actions: [addButton]
}) })
this.map.eachBrowsableDataLayer((datalayer) => { this.map.eachBrowsableDataLayer((datalayer) => {
this.addDataLayer(datalayer, dataContainer) this.addDataLayer(datalayer, dataContainer)
}) })
// After datalayers have been added.
const orderable = new Orderable(dataContainer, L.bind(this.onReorder, this))
} }
newDataLayer () { static backButton(map) {
const datalayer = this.map.createDataLayer({})
datalayer.edit()
}
onReorder(src, dst, initialIndex, finalIndex) {
const layer = this.map.datalayers[src.dataset.id],
other = this.map.datalayers[dst.dataset.id],
minIndex = Math.min(layer.getRank(), other.getRank()),
maxIndex = Math.max(layer.getRank(), other.getRank())
if (finalIndex === 0) layer.bringToTop()
else if (finalIndex > initialIndex) layer.insertBefore(other)
else layer.insertAfter(other)
this.map.eachDataLayerReverse((datalayer) => {
if (datalayer.getRank() >= minIndex && datalayer.getRank() <= maxIndex)
datalayer.isDirty = true
})
this.map.indexDatalayers()
}
onEnableEdit () {
if (!this.isOpen()) return
this.map.ui._panel.classList.add('dark')
}
onDisableEdit () {
if (!this.isOpen()) return
this.map.ui._panel.classList.remove('dark')
}
static backButton (map) {
const button = L.DomUtil.create('li', '') const button = L.DomUtil.create('li', '')
L.DomUtil.create('i', 'umap-icon-16 umap-back', button) L.DomUtil.create('i', 'icon icon-16 icon-back', button)
const label = L.DomUtil.create('span', '', button)
button.title = L._('Back to browser') button.title = L._('Back to browser')
// Fixme: remove me when this is merged and released // Fixme: remove me when this is merged and released
// https://github.com/Leaflet/Leaflet/pull/9052 // https://github.com/Leaflet/Leaflet/pull/9052
@ -231,5 +172,4 @@ export default class Browser {
L.DomEvent.on(button, 'click', map.openBrowser, map) L.DomEvent.on(button, 'click', map.openBrowser, map)
return button return button
} }
} }

View file

@ -1,8 +1,10 @@
import URLs from './urls.js' import URLs from './urls.js'
import Browser from './browser.js' import Browser from './browser.js'
import { Panel, EditPanel } from './panel.js'
import * as Utils from './utils.js' import * as Utils from './utils.js'
import { SCHEMA } from './schema.js' import { SCHEMA } from './schema.js'
import { Request, ServerRequest, RequestError, HTTPError, NOKError } from './request.js' import { Request, ServerRequest, RequestError, HTTPError, NOKError } from './request.js'
import Orderable from './orderable.js'
// Import modules and export them to the global scope. // Import modules and export them to the global scope.
// For the not yet module-compatible JS out there. // For the not yet module-compatible JS out there.
@ -15,6 +17,9 @@ window.U = {
HTTPError, HTTPError,
NOKError, NOKError,
Browser, Browser,
Panel,
EditPanel,
Utils, Utils,
SCHEMA, SCHEMA,
Orderable,
} }

View file

@ -0,0 +1,81 @@
export class Panel {
MODE = 'condensed'
CLASSNAME = 'left'
constructor(parent) {
this.parent = parent
this.container = L.DomUtil.create('div', '', this.parent)
L.DomEvent.disableClickPropagation(this.container)
L.DomEvent.on(this.container, 'contextmenu', L.DomEvent.stopPropagation) // Do not activate our custom context menu.
L.DomEvent.on(this.container, 'wheel', L.DomEvent.stopPropagation)
L.DomEvent.on(this.container, 'MozMousePixelScroll', L.DomEvent.stopPropagation)
}
resetClassName() {
this.container.className = `with-transition panel ${this.CLASSNAME} ${this.MODE}`
}
open(e) {
//this.fire('panel:open')
// We reset all because we can't know which class has been added
// by previous ui processes...
this.resetClassName()
this.container.innerHTML = ''
const actionsContainer = L.DomUtil.create('ul', 'toolbox', this.container)
const body = L.DomUtil.create('div', 'body', this.container)
if (e.data.html.nodeType && e.data.html.nodeType === 1)
body.appendChild(e.data.html)
else body.innerHTML = e.data.html
const closeLink = L.DomUtil.create('li', 'umap-close-link', actionsContainer)
L.DomUtil.add('i', 'icon icon-16 icon-close', closeLink)
closeLink.title = L._('Close')
const resizeLink = L.DomUtil.create('li', 'umap-resize-link', actionsContainer)
L.DomUtil.add('i', 'icon icon-16 icon-resize', resizeLink)
resizeLink.title = L._('Toggle size')
if (e.actions) {
for (let i = 0; i < e.actions.length; i++) {
actionsContainer.appendChild(e.actions[i])
}
}
if (e.className) L.DomUtil.addClass(this.container, e.className)
if (L.DomUtil.hasClass(this.container, 'on')) {
// Already open.
//this.fire('panel:ready')
} else {
L.DomEvent.once(
this.container,
'transitionend',
function (e) {
//this.fire('panel:ready')
},
this
)
L.DomUtil.addClass(this.container, 'on')
}
L.DomEvent.on(closeLink, 'click', this.close, this)
L.DomEvent.on(resizeLink, 'click', this.resize, this)
}
resize() {
if (this.MODE === 'expanded') {
this.MODE = 'condensed'
this.container.classList.remove('expanded')
this.container.classList.add('condensed')
} else {
this.MODE = 'expanded'
this.container.classList.remove('condensed')
this.container.classList.add('expanded')
}
}
close() {
if (L.DomUtil.hasClass(this.container, 'on')) {
L.DomUtil.removeClass(this.container, 'on')
//this.fire('panel:closed')
}
}
}
export class EditPanel extends Panel {
CLASSNAME = 'right dark'
}

View file

@ -29,6 +29,18 @@ U.ImportAction = U.BaseAction.extend({
}, },
}) })
U.EditLayersAction = U.BaseAction.extend({
options: {
helpMenu: true,
className: 'umap-control-browse dark',
tooltip: L._('See layers'),
},
addHooks: function () {
this.map.editDatalayers()
},
})
U.EditCaptionAction = U.BaseAction.extend({ U.EditCaptionAction = U.BaseAction.extend({
options: { options: {
helpMenu: true, helpMenu: true,
@ -280,7 +292,6 @@ U.ContinueLineAction = U.BaseVertexAction.extend({
}) })
// Leaflet.Toolbar doesn't allow twice same toolbar class… // Leaflet.Toolbar doesn't allow twice same toolbar class…
U.ImportToolbar = L.Toolbar.Control.extend({})
U.SettingsToolbar = L.Toolbar.Control.extend({}) U.SettingsToolbar = L.Toolbar.Control.extend({})
U.DrawToolbar = L.Toolbar.Control.extend({ U.DrawToolbar = L.Toolbar.Control.extend({
initialize: function (options) { initialize: function (options) {
@ -316,6 +327,7 @@ U.DrawToolbar = L.Toolbar.Control.extend({
}, },
}) })
U.DropControl = L.Class.extend({ U.DropControl = L.Class.extend({
initialize: function (map) { initialize: function (map) {
this.map = map this.map = map
@ -507,7 +519,7 @@ L.Control.Button = L.Control.extend({
U.DataLayersControl = L.Control.Button.extend({ U.DataLayersControl = L.Control.Button.extend({
options: { options: {
position: 'topright', position: 'topleft',
className: 'umap-control-browse', className: 'umap-control-browse',
title: L._('See layers'), title: L._('See layers'),
}, },
@ -519,8 +531,8 @@ U.DataLayersControl = L.Control.Button.extend({
U.CaptionControl = L.Control.Button.extend({ U.CaptionControl = L.Control.Button.extend({
options: { options: {
position: 'topright', position: 'topleft',
className: 'umap-control-caption hide-on-edit', className: 'umap-control-caption',
title: L._('About'), title: L._('About'),
}, },
@ -614,6 +626,8 @@ const ControlsMixin = {
'search', 'search',
'fullscreen', 'fullscreen',
'embed', 'embed',
'datalayers',
'caption',
'locate', 'locate',
'measure', 'measure',
'editinosm', 'editinosm',
@ -669,7 +683,7 @@ const ControlsMixin = {
}) })
container.appendChild(builder.build()) container.appendChild(builder.build())
this.ui.openPanel({ data: { html: container } }) this.panel.open({ data: { html: container } })
}, },
displayCaption: function () { displayCaption: function () {
@ -749,7 +763,7 @@ const ControlsMixin = {
`, `,
urls urls
) )
this.ui.openPanel({ data: { html: container } }) this.panel.open({ data: { html: container } })
}, },
renderEditToolbar: function () { renderEditToolbar: function () {
@ -899,6 +913,49 @@ const ControlsMixin = {
this this
) )
}, },
editDatalayers: function () {
if (!this.editEnabled) return
const container = L.DomUtil.create('div')
L.DomUtil.createTitle(container, L._('Manage layers'), 'layers')
const ul = L.DomUtil.create('ul', '', container)
this.eachDataLayerReverse((datalayer) => {
const row = L.DomUtil.create('li', 'orderable', ul)
const dragHandle = L.DomUtil.create('i', 'icon icon-16 icon-drag', row)
dragHandle.title = L._('Drag to reorder')
datalayer.renderToolbox(row)
const title = L.DomUtil.add('span', '', row, datalayer.options.name)
L.DomUtil.classIf(row, '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],
other = this.datalayers[dst.dataset.id],
minIndex = Math.min(layer.getRank(), other.getRank()),
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({ data: { html: container } })
},
} }
/* Used in view mode to define the current tilelayer */ /* Used in view mode to define the current tilelayer */
@ -971,7 +1028,7 @@ U.TileLayerChooser = L.Control.extend({
L.DomUtil.createTitle(container, L._('Change tilelayers'), 'tilelayer') L.DomUtil.createTitle(container, L._('Change tilelayers'), 'tilelayer')
this._tilelayers_container = L.DomUtil.create('ul', '', container) this._tilelayers_container = L.DomUtil.create('ul', '', container)
this.buildList(options) this.buildList(options)
this.map.ui.openPanel({ this.map.editPanel.open({
data: { html: container }, data: { html: container },
className: options.className, className: options.className,
}) })
@ -1201,6 +1258,7 @@ U.SearchControl = L.Control.extend({
}, },
onAdd: function (map) { onAdd: function (map) {
this.map = map
const container = L.DomUtil.create('div', 'leaflet-control-search umap-control') const container = L.DomUtil.create('div', 'leaflet-control-search umap-control')
L.DomEvent.disableClickPropagation(container) L.DomEvent.disableClickPropagation(container)
L.DomUtil.createButton( L.DomUtil.createButton(
@ -1209,38 +1267,37 @@ U.SearchControl = L.Control.extend({
L._('Search location'), L._('Search location'),
(e) => { (e) => {
L.DomEvent.stop(e) L.DomEvent.stop(e)
this.openPanel(map) this.open()
}, },
this this
) )
return container return container
}, },
openPanel: function (map) { open: function () {
const options = { const options = {
limit: 10, limit: 10,
noResultLabel: L._('No results'), noResultLabel: L._('No results'),
} }
if (map.options.photonUrl) options.url = map.options.photonUrl if (this.map.options.photonUrl) options.url = this.map.options.photonUrl
const container = L.DomUtil.create('div', 'umap-search') const container = L.DomUtil.create('div', '')
const title = L.DomUtil.create('h3', '', container) L.DomUtil.createTitle(container, L._('Search location'), 'search')
title.textContent = L._('Search location')
const input = L.DomUtil.create('input', 'photon-input', container) const input = L.DomUtil.create('input', 'photon-input', container)
const resultsContainer = L.DomUtil.create('div', 'photon-autocomplete', container) const resultsContainer = L.DomUtil.create('div', 'photon-autocomplete', container)
this.search = new U.Search(map, input, options) this.search = new U.Search(this.map, input, options)
const id = Math.random() const id = Math.random()
this.search.on('ajax:send', () => { this.search.on('ajax:send', () => {
map.fire('dataloading', { id: id }) this.map.fire('dataloading', { id: id })
}) })
this.search.on('ajax:return', () => { this.search.on('ajax:return', () => {
map.fire('dataload', { id: id }) this.map.fire('dataload', { id: id })
}) })
this.search.resultsContainer = resultsContainer this.search.resultsContainer = resultsContainer
map.ui.once('panel:ready', () => { this.map.ui.once('panel:ready', () => {
input.focus() input.focus()
}) })
map.ui.openPanel({ data: { html: container } }) this.map.panel.open({ data: { html: container } })
}, },
}) })

View file

@ -132,11 +132,7 @@ U.FeatureMixin = {
this.appendEditFieldsets(container) this.appendEditFieldsets(container)
const advancedActions = L.DomUtil.createFieldset(container, L._('Advanced actions')) const advancedActions = L.DomUtil.createFieldset(container, L._('Advanced actions'))
this.getAdvancedEditActions(advancedActions) this.getAdvancedEditActions(advancedActions)
this.map.ui.openPanel({ this.map.editPanel.open({ data: { html: container } })
data: { html: container },
className: 'dark',
actions: [U.Browser.backButton(this.map)],
})
this.map.editedFeature = this this.map.editedFeature = this
if (!this.isOnScreen()) this.zoomTo(e) if (!this.isOnScreen()) this.zoomTo(e)
}, },

View file

@ -117,7 +117,7 @@ U.Importer = L.Class.extend({
open: function () { open: function () {
if (!this.container) this.build() if (!this.container) this.build()
this.map.ui.openPanel({ data: { html: this.container }, className: 'dark' }) this.map.editPanel.open({ data: { html: this.container } })
}, },
openFiles: function () { openFiles: function () {

View file

@ -56,6 +56,8 @@ U.Map = L.Map.extend({
if (geojson.geometry) this.options.center = this.latLng(geojson.geometry) if (geojson.geometry) this.options.center = this.latLng(geojson.geometry)
this.urls = new U.URLs(this.options.urls) this.urls = new U.URLs(this.options.urls)
this.panel = new U.Panel(this._container)
if (this.hasEditMode()) this.editPanel = new U.EditPanel(this._container)
this.ui = new U.UI(this._container) this.ui = new U.UI(this._container)
this.ui.on('dataloading', (e) => this.fire('dataloading', e)) this.ui.on('dataloading', (e) => this.fire('dataloading', e))
this.ui.on('dataload', (e) => this.fire('dataload', e)) this.ui.on('dataload', (e) => this.fire('dataload', e))
@ -330,15 +332,16 @@ U.Map = L.Map.extend({
new U.EditControl(this).addTo(this) new U.EditControl(this).addTo(this)
const editActions = [ const editActions = [
U.EditLayersAction,
U.EditCaptionAction, U.EditCaptionAction,
U.EditPropertiesAction, U.EditPropertiesAction,
U.ChangeTileLayerAction, U.ChangeTileLayerAction,
U.UpdateExtentAction, U.UpdateExtentAction,
U.UpdatePermsAction, U.UpdatePermsAction,
U.ImportAction,
] ]
if (this.options.editMode === 'advanced') { if (this.options.editMode === 'advanced') {
new U.SettingsToolbar({ actions: editActions }).addTo(this) new U.SettingsToolbar({ actions: editActions }).addTo(this)
new U.ImportToolbar({ actions: [U.ImportAction] }).addTo(this)
} }
new U.DrawToolbar({ map: this }).addTo(this) new U.DrawToolbar({ map: this }).addTo(this)
@ -438,8 +441,6 @@ U.Map = L.Map.extend({
L.DomUtil.addClass(control._container, 'display-on-more') L.DomUtil.addClass(control._container, 'display-on-more')
else L.DomUtil.removeClass(control._container, 'display-on-more') else L.DomUtil.removeClass(control._container, 'display-on-more')
} }
if (this.getOption('datalayersControl')) this._controls.datalayers.addTo(this)
if (this.getOption('captionControl')) this._controls.caption.addTo(this)
if (this.getOption('permanentCredit')) this._controls.permanentCredit.addTo(this) if (this.getOption('permanentCredit')) this._controls.permanentCredit.addTo(this)
if (this.getOption('moreControl')) this._controls.more.addTo(this) if (this.getOption('moreControl')) this._controls.more.addTo(this)
if (this.getOption('scaleControl')) this._controls.scale.addTo(this) if (this.getOption('scaleControl')) this._controls.scale.addTo(this)
@ -775,6 +776,11 @@ U.Map = L.Map.extend({
return new U.DataLayer(this, datalayer) return new U.DataLayer(this, datalayer)
}, },
newDataLayer: function () {
const datalayer = this.createDataLayer({})
datalayer.edit()
},
getDefaultOption: function (option) { getDefaultOption: function (option) {
return U.SCHEMA[option] && U.SCHEMA[option].default return U.SCHEMA[option] && U.SCHEMA[option].default
}, },
@ -812,10 +818,6 @@ U.Map = L.Map.extend({
}) })
}, },
manageDatalayers: function () {
if (this._controls.datalayers) this._controls.datalayers.openPanel()
},
toGeoJSON: function () { toGeoJSON: function () {
let features = [] let features = []
this.eachDataLayer((datalayer) => { this.eachDataLayer((datalayer) => {
@ -1061,7 +1063,7 @@ U.Map = L.Map.extend({
else window.location = data.url else window.location = data.url
alert.content = data.info || alert.content alert.content = data.info || alert.content
this.once('saved', () => this.ui.alert(alert)) this.once('saved', () => this.ui.alert(alert))
this.ui.closePanel() this.editPanel.close()
this.permissions.save() this.permissions.save()
} }
}, },
@ -1164,7 +1166,6 @@ U.Map = L.Map.extend({
UIFields.push(`options.${this.HIDDABLE_CONTROLS[i]}Control`) UIFields.push(`options.${this.HIDDABLE_CONTROLS[i]}Control`)
} }
UIFields = UIFields.concat([ UIFields = UIFields.concat([
'options.datalayersControl',
'options.moreControl', 'options.moreControl',
'options.scrollWheelZoom', 'options.scrollWheelZoom',
'options.miniMap', 'options.miniMap',
@ -1550,7 +1551,7 @@ U.Map = L.Map.extend({
this._editSlideshow(container) this._editSlideshow(container)
this._advancedActions(container) this._advancedActions(container)
this.ui.openPanel({ data: { html: container }, className: 'dark' }) this.editPanel.open({ data: { html: container }, className: 'dark' })
}, },
enableEdit: function () { enableEdit: function () {
@ -1822,7 +1823,7 @@ U.Map = L.Map.extend({
}, },
search: function () { search: function () {
if (this._controls.search) this._controls.search.openPanel(this) if (this._controls.search) this._controls.search.open()
}, },
getFilterKeys: function () { getFilterKeys: function () {

View file

@ -1379,9 +1379,8 @@ U.DataLayer = L.Evented.extend({
'_blank' '_blank'
) )
} }
this.map.ui.openPanel({ this.map.editPanel.open({
data: { html: container }, data: { html: container },
className: 'dark',
actions: [U.Browser.backButton(this.map)], actions: [U.Browser.backButton(this.map)],
}) })
}, },

View file

@ -126,7 +126,7 @@ U.MapPermissions = L.Class.extend({
this.map.eachDataLayer((datalayer) => { this.map.eachDataLayer((datalayer) => {
datalayer.permissions.edit(container) datalayer.permissions.edit(container)
}) })
this.map.ui.openPanel({ data: { html: container }, className: 'dark' }) this.map.editPanel.open({ data: { html: container }, className: 'dark' })
}, },
attach: async function () { attach: async function () {

View file

@ -55,7 +55,7 @@ U.Popup.Panel = U.Popup.extend({
}, },
onAdd: function (map) { onAdd: function (map) {
map.ui.openPanel({ map.panel.open({
data: { html: this._content }, data: { html: this._content },
actions: [U.Browser.backButton(map)], actions: [U.Browser.backButton(map)],
}) })
@ -71,7 +71,7 @@ U.Popup.Panel = U.Popup.extend({
}, },
onRemove: function (map) { onRemove: function (map) {
map.ui.closePanel() map.panel.close()
// fire events as in base class Popup.js:onRemove // fire events as in base class Popup.js:onRemove
map.fire('popupclose', { popup: this }) map.fire('popupclose', { popup: this })

View file

@ -155,7 +155,7 @@ U.Share = L.Class.extend({
open: function () { open: function () {
if (!this.container) this.build() if (!this.container) this.build()
this.map.ui.openPanel({ data: { html: this.container } }) this.map.panel.open({ data: { html: this.container } })
}, },
format: function (mode) { format: function (mode) {

View file

@ -5,7 +5,6 @@ U.UI = L.Evented.extend({
ALERTS: Array(), ALERTS: Array(),
ALERT_ID: null, ALERT_ID: null,
TOOLTIP_ID: null, TOOLTIP_ID: null,
PANEL_MODE: 'condensed',
initialize: function (parent) { initialize: function (parent) {
this.parent = parent this.parent = parent
@ -14,78 +13,12 @@ U.UI = L.Evented.extend({
L.DomEvent.on(this.container, 'contextmenu', L.DomEvent.stopPropagation) // Do not activate our custom context menu. L.DomEvent.on(this.container, 'contextmenu', L.DomEvent.stopPropagation) // Do not activate our custom context menu.
L.DomEvent.on(this.container, 'wheel', L.DomEvent.stopPropagation) L.DomEvent.on(this.container, 'wheel', L.DomEvent.stopPropagation)
L.DomEvent.on(this.container, 'MozMousePixelScroll', L.DomEvent.stopPropagation) L.DomEvent.on(this.container, 'MozMousePixelScroll', L.DomEvent.stopPropagation)
this._panel = L.DomUtil.create('div', '', this.container)
this._panel.id = 'umap-panel'
this._alert = L.DomUtil.create('div', 'with-transition', this.container) this._alert = L.DomUtil.create('div', 'with-transition', this.container)
this._alert.id = 'umap-alert-container' this._alert.id = 'umap-alert-container'
this._tooltip = L.DomUtil.create('div', '', this.container) this._tooltip = L.DomUtil.create('div', '', this.container)
this._tooltip.id = 'umap-tooltip-container' this._tooltip.id = 'umap-tooltip-container'
}, },
resetPanelClassName: function () {
this._panel.className = `with-transition ${this.PANEL_MODE}`
},
openPanel: function (e) {
this.fire('panel:open')
// We reset all because we can't know which class has been added
// by previous ui processes...
this.resetPanelClassName()
this._panel.innerHTML = ''
const actionsContainer = L.DomUtil.create('ul', 'toolbox', this._panel)
const body = L.DomUtil.create('div', 'body', this._panel)
if (e.data.html.nodeType && e.data.html.nodeType === 1)
body.appendChild(e.data.html)
else body.innerHTML = e.data.html
const closeLink = L.DomUtil.create('li', 'umap-close-link', actionsContainer)
L.DomUtil.add('i', 'umap-icon-16 umap-close-icon', closeLink)
closeLink.title = L._('Close')
const resizeLink = L.DomUtil.create('li', 'umap-resize-link', actionsContainer)
L.DomUtil.add('i', 'umap-icon-16 umap-resize-icon', resizeLink)
resizeLink.title = L._('Toggle size')
if (e.actions) {
for (let i = 0; i < e.actions.length; i++) {
actionsContainer.appendChild(e.actions[i])
}
}
if (e.className) L.DomUtil.addClass(this._panel, e.className)
if (L.DomUtil.hasClass(this.parent, 'umap-ui')) {
// Already open.
this.fire('panel:ready')
} else {
L.DomEvent.once(
this._panel,
'transitionend',
function (e) {
this.fire('panel:ready')
},
this
)
L.DomUtil.addClass(this.parent, 'umap-ui')
}
L.DomEvent.on(closeLink, 'click', this.closePanel, this)
L.DomEvent.on(resizeLink, 'click', this.resizePanel, this)
},
resizePanel: function () {
if (this.PANEL_MODE === 'expanded') {
this.PANEL_MODE = 'condensed'
this._panel.classList.remove('expanded')
this._panel.classList.add('condensed')
} else {
this.PANEL_MODE = 'expanded'
this._panel.classList.remove('condensed')
this._panel.classList.add('expanded')
}
},
closePanel: function () {
if (L.DomUtil.hasClass(this.parent, 'umap-ui')) {
L.DomUtil.removeClass(this.parent, 'umap-ui')
this.fire('panel:closed')
}
},
alert: function (e) { alert: function (e) {
if (L.DomUtil.hasClass(this.parent, 'umap-alert')) this.ALERTS.push(e) if (L.DomUtil.hasClass(this.parent, 'umap-alert')) this.ALERTS.push(e)
else this.popAlert(e) else this.popAlert(e)

View file

@ -862,6 +862,7 @@ ul.photon-autocomplete {
/* ********************************* */ /* ********************************* */
/* Browser panel */ /* Browser panel */
/* ********************************* */ /* ********************************* */
a.umap-control-browse,
.umap-control-browse [type="button"] { .umap-control-browse [type="button"] {
background-position: -36px -72px; background-position: -36px -72px;
} }
@ -869,12 +870,6 @@ a.umap-control-caption,
.umap-control-caption [type="button"] { .umap-control-caption [type="button"] {
background-position: -72px -72px; background-position: -72px -72px;
} }
.umap-edit-enabled .umap-control-caption [type="button"],
.umap-edit-enabled .umap-control-browse [type="button"] {
background-image: url('./img/24-white.svg');
background-color: var(--color-darkGray);
}
.search-result-tools i,
.leaflet-inplace-toolbar a { .leaflet-inplace-toolbar a {
background-repeat: no-repeat; background-repeat: no-repeat;
background-image: url('./img/16.svg'); background-image: url('./img/16.svg');

View file

@ -28,4 +28,5 @@
<link rel="stylesheet" href="{% static 'umap/content.css' %}" /> <link rel="stylesheet" href="{% static 'umap/content.css' %}" />
<link rel="stylesheet" href="{% static 'umap/nav.css' %}" /> <link rel="stylesheet" href="{% static 'umap/nav.css' %}" />
<link rel="stylesheet" href="{% static 'umap/map.css' %}" /> <link rel="stylesheet" href="{% static 'umap/map.css' %}" />
<link rel="stylesheet" href="{% static 'umap/css/panel.css' %}" />
<link rel="stylesheet" href="{% static 'umap/theme.css' %}" /> <link rel="stylesheet" href="{% static 'umap/theme.css' %}" />