diff --git a/umap/static/umap/base.css b/umap/static/umap/base.css index f233ff83..631e9c51 100644 --- a/umap/static/umap/base.css +++ b/umap/static/umap/base.css @@ -307,9 +307,6 @@ input + .help-text { .formbox.with-switch { padding-top: 2px; } -.formbox select { - width: calc(100% - 14px); -} fieldset.formbox { border: none; border-top: 1px solid var(--color-lightGray); @@ -386,6 +383,10 @@ fieldset legend { font-size: .9rem; padding: 0 5px; } +fieldset.separator { + border: none; + border-top: 1px solid var(--color-lightGray); +} [data-badge] { position: relative; @@ -633,7 +634,6 @@ i.info { .umap-datalayer-container, .umap-layer-properties-container, .umap-browse-data, -.umap-facet-search, .umap-tilelayer-switcher-container { padding: 0 10px; } diff --git a/umap/static/umap/img/16-white.svg b/umap/static/umap/img/16-white.svg index b652efee..ceabb640 100644 --- a/umap/static/umap/img/16-white.svg +++ b/umap/static/umap/img/16-white.svg @@ -189,5 +189,6 @@ + diff --git a/umap/static/umap/img/source/16-white.svg b/umap/static/umap/img/source/16-white.svg index d5138092..0333e0af 100644 --- a/umap/static/umap/img/source/16-white.svg +++ b/umap/static/umap/img/source/16-white.svg @@ -211,5 +211,6 @@ + diff --git a/umap/static/umap/js/modules/permissions.js b/umap/static/umap/js/modules/permissions.js index 2dde4002..f66de593 100644 --- a/umap/static/umap/js/modules/permissions.js +++ b/umap/static/umap/js/modules/permissions.js @@ -46,97 +46,129 @@ export class MapPermissions { return this.map } + _editAnonymous(container) { + const fields = [] + if (this.isOwner()) { + fields.push([ + 'options.edit_status', + { + handler: 'IntSelect', + label: translate('Who can edit'), + selectOptions: this.map.options.edit_statuses, + }, + ]) + const builder = new U.FormBuilder(this, fields) + const form = builder.build() + container.appendChild(form) + + if (this.options.anonymous_edit_url) { + DomUtil.createCopiableInput( + container, + translate('Secret edit link:'), + this.options.anonymous_edit_url + ) + } + + if (this.map.options.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( + container, + translate('Advanced actions') + ) + const advancedButtons = DomUtil.create('div', 'button-bar', advancedActions) + DomUtil.createButton( + 'button', + advancedButtons, + translate('Attach the map to my account'), + this.attach, + this + ) + } + } + } + + _editWithOwner(container) { + const topFields = [] + const collaboratorsFields = [] + const fieldset = Utils.loadTemplate( + `
${translate('Map')}
` + ) + container.appendChild(fieldset) + if (this.isOwner()) { + topFields.push([ + 'options.edit_status', + { + handler: 'IntSelect', + label: translate('Who can edit'), + selectOptions: this.map.options.edit_statuses, + }, + ]) + topFields.push([ + 'options.share_status', + { + handler: 'IntSelect', + label: translate('Who can view'), + selectOptions: this.map.options.share_statuses, + }, + ]) + collaboratorsFields.push([ + 'options.owner', + { handler: 'ManageOwner', label: translate("Map's owner") }, + ]) + if (this.map.options.user?.teams?.length) { + collaboratorsFields.push([ + 'options.team', + { + handler: 'ManageTeam', + label: translate('Attach map to a team'), + teams: this.map.options.user.teams, + }, + ]) + } + } + collaboratorsFields.push([ + 'options.editors', + { handler: 'ManageEditors', label: translate("Map's editors") }, + ]) + + const builder = new U.FormBuilder(this, topFields) + const form = builder.build() + container.appendChild(form) + if (collaboratorsFields.length) { + const fieldset = Utils.loadTemplate( + `
${translate('Manage collaborators')}
` + ) + container.appendChild(fieldset) + const builder = new U.FormBuilder(this, collaboratorsFields) + const form = builder.build() + container.appendChild(form) + } + } + + _editDatalayers(container) { + if (this.map.hasLayers()) { + const fieldset = Utils.loadTemplate( + `
${translate('Datalayers')}
` + ) + container.appendChild(fieldset) + this.map.eachDataLayer((datalayer) => { + datalayer.permissions.edit(fieldset) + }) + } + } + edit() { if (this.map.options.editMode !== 'advanced') return if (!this.map.options.umap_id) { - return Alert.info(translate('Please save the map first')) + Alert.info(translate('Please save the map first')) + return } const container = DomUtil.create('div', 'permissions-panel') - const fields = [] DomUtil.createTitle(container, translate('Update permissions'), 'icon-key') - if (this.isAnonymousMap()) { - if (this.options.anonymous_edit_url) { - const helpText = `${translate('Secret edit link:')}
${ - this.options.anonymous_edit_url - }` - DomUtil.element({ - tagName: 'p', - className: 'help-text', - innerHTML: helpText, - parent: container, - }) - fields.push([ - 'options.edit_status', - { - handler: 'IntSelect', - label: translate('Who can edit'), - selectOptions: this.map.options.edit_statuses, - helpText: helpText, - }, - ]) - } - } else { - if (this.isOwner()) { - fields.push([ - 'options.edit_status', - { - handler: 'IntSelect', - label: translate('Who can edit'), - selectOptions: this.map.options.edit_statuses, - }, - ]) - fields.push([ - 'options.share_status', - { - handler: 'IntSelect', - label: translate('Who can view'), - selectOptions: this.map.options.share_statuses, - }, - ]) - fields.push([ - 'options.owner', - { handler: 'ManageOwner', label: translate("Map's owner") }, - ]) - if (this.map.options.user?.teams?.length) { - fields.push([ - 'options.team', - { - handler: 'ManageTeam', - label: translate('Attach map to a team'), - teams: this.map.options.user.teams, - }, - ]) - } - } - fields.push([ - 'options.editors', - { handler: 'ManageEditors', label: translate("Map's editors") }, - ]) - } - - const builder = new U.FormBuilder(this, fields) - const form = builder.build() - container.appendChild(form) - if (this.isAnonymousMap() && this.map.options.user) { - // 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( - container, - translate('Advanced actions') - ) - const advancedButtons = DomUtil.create('div', 'button-bar', advancedActions) - DomUtil.createButton( - 'button', - advancedButtons, - translate('Attach the map to my account'), - this.attach, - this - ) - } - DomUtil.add('h4', '', container, translate('Datalayers')) - this.map.eachDataLayer((datalayer) => { - datalayer.permissions.edit(container) - }) + if (this.isAnonymousMap()) this._editAnonymous(container) + else this._editWithOwner(container) + this._editDatalayers(container) this.map.editPanel.open({ content: container, className: 'dark' }) } @@ -157,8 +189,9 @@ export class MapPermissions { for (let i = 0; i < this.options.editors.length; i++) formData.append('editors', this.options.editors[i].id) } - if (this.isOwner() || this.isAnonymousMap()) + if (this.isOwner() || this.isAnonymousMap()) { formData.append('edit_status', this.options.edit_status) + } if (this.isOwner()) { formData.append('owner', this.options.owner?.id) formData.append('team', this.options.team?.id || '') diff --git a/umap/static/umap/js/umap.forms.js b/umap/static/umap/js/umap.forms.js index 7061d632..ce54cfb6 100644 --- a/umap/static/umap/js/umap.forms.js +++ b/umap/static/umap/js/umap.forms.js @@ -1029,6 +1029,7 @@ L.FormBuilder.ManageOwner = L.FormBuilder.Element.extend({ const options = { className: 'edit-owner', on_select: L.bind(this.onSelect, this), + placeholder: L._("Type new owner's username"), } this.autocomplete = new U.AjaxAutocomplete(this.parentNode, options) const owner = this.toHTML() @@ -1058,6 +1059,7 @@ L.FormBuilder.ManageEditors = L.FormBuilder.Element.extend({ className: 'edit-editors', on_select: L.bind(this.onSelect, this), on_unselect: L.bind(this.onUnselect, this), + placeholder: L._("Type editor's username"), } this.autocomplete = new U.AjaxAutocompleteMultiple(this.parentNode, options) this._values = this.toHTML() diff --git a/umap/static/umap/js/umap.js b/umap/static/umap/js/umap.js index 66194aab..51531341 100644 --- a/umap/static/umap/js/umap.js +++ b/umap/static/umap/js/umap.js @@ -724,6 +724,10 @@ U.Map = L.Map.extend({ } }, + hasLayers: function () { + return Boolean(this.datalayers_index.length) + }, + fitDataBounds: function () { const bounds = this.getLayersBounds() if (!this.hasData() || !bounds.isValid()) return false diff --git a/umap/static/umap/map.css b/umap/static/umap/map.css index 1873a1c9..c330e00b 100644 --- a/umap/static/umap/map.css +++ b/umap/static/umap/map.css @@ -820,7 +820,6 @@ a.umap-control-caption, .umap-browser .off .feature { display: none; } -.umap-facet-search .formbox, .umap-browser .datalayer { margin-bottom: 2px; border-radius: 2px; @@ -831,7 +830,7 @@ a.umap-control-caption, .umap-browser.dark .datalayer ul { border: 1px solid #232729; } -.umap-browser h5, .umap-facet-search h5 { +.umap-browser h5 { margin-bottom: 0; overflow: hidden; padding-inline-start: 5px; @@ -849,7 +848,7 @@ a.umap-control-caption, .umap-browser h5 span { margin-inline-start: 10px; } -.umap-browser li, .umap-facet-search li { +.umap-browser li { padding: 2px 0; white-space: nowrap; overflow: hidden;