From 445127254b031602e855892b4deb529ca4d60c60 Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Mon, 9 Sep 2024 18:45:10 +0200 Subject: [PATCH 1/5] fix: do not show "Layers" title if not layers in permissions panel --- umap/static/umap/js/modules/permissions.js | 10 ++++++---- umap/static/umap/js/umap.js | 4 ++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/umap/static/umap/js/modules/permissions.js b/umap/static/umap/js/modules/permissions.js index 2dde4002..3c97ec81 100644 --- a/umap/static/umap/js/modules/permissions.js +++ b/umap/static/umap/js/modules/permissions.js @@ -133,10 +133,12 @@ export class MapPermissions { this ) } - DomUtil.add('h4', '', container, translate('Datalayers')) - this.map.eachDataLayer((datalayer) => { - datalayer.permissions.edit(container) - }) + if (this.map.hasLayers()) { + DomUtil.add('h4', '', container, translate('Datalayers')) + this.map.eachDataLayer((datalayer) => { + datalayer.permissions.edit(container) + }) + } this.map.editPanel.open({ content: container, className: 'dark' }) } 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 From eda122351660a38a0388b9c7faad5e3e17933343 Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Mon, 9 Sep 2024 18:46:59 +0200 Subject: [PATCH 2/5] fix: do not show "Attache to my account" button if no logged in user --- umap/static/umap/js/modules/permissions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/umap/static/umap/js/modules/permissions.js b/umap/static/umap/js/modules/permissions.js index 3c97ec81..307aee03 100644 --- a/umap/static/umap/js/modules/permissions.js +++ b/umap/static/umap/js/modules/permissions.js @@ -117,7 +117,7 @@ export class MapPermissions { const builder = new U.FormBuilder(this, fields) const form = builder.build() container.appendChild(form) - if (this.isAnonymousMap() && this.map.options.user) { + if (this.isAnonymousMap() && 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( From 6d777d9d46a0692e216b175ad6b8571513c06cce Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Mon, 9 Sep 2024 19:03:59 +0200 Subject: [PATCH 3/5] feat: use a copiable input for secret edit link in permissions panel --- umap/static/umap/img/16-white.svg | 1 + umap/static/umap/img/source/16-white.svg | 1 + umap/static/umap/js/modules/permissions.js | 52 +++++++++++----------- 3 files changed, 28 insertions(+), 26 deletions(-) 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 307aee03..df3acd19 100644 --- a/umap/static/umap/js/modules/permissions.js +++ b/umap/static/umap/js/modules/permissions.js @@ -55,23 +55,13 @@ export class MapPermissions { 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, - }) + if (this.isOwner()) { fields.push([ 'options.edit_status', { handler: 'IntSelect', label: translate('Who can edit'), selectOptions: this.map.options.edit_statuses, - helpText: helpText, }, ]) } @@ -117,21 +107,31 @@ export class MapPermissions { const builder = new U.FormBuilder(this, fields) const form = builder.build() container.appendChild(form) - if (this.isAnonymousMap() && 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 - ) + if (this.isAnonymousMap()) { + 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 + ) + } } if (this.map.hasLayers()) { DomUtil.add('h4', '', container, translate('Datalayers')) From 575b563c67319731af32d3575fe2d6459766e73e Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Mon, 9 Sep 2024 19:14:21 +0200 Subject: [PATCH 4/5] chore: remove unused class `umap-facet-search` from css --- umap/static/umap/base.css | 1 - umap/static/umap/map.css | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/umap/static/umap/base.css b/umap/static/umap/base.css index f233ff83..cb65a352 100644 --- a/umap/static/umap/base.css +++ b/umap/static/umap/base.css @@ -633,7 +633,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/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; From b48f911bf26252dd979e6e2f3e3620f5de22d682 Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Mon, 9 Sep 2024 21:10:52 +0200 Subject: [PATCH 5/5] chore: revamp permissions panel --- umap/static/umap/base.css | 7 +- umap/static/umap/js/modules/permissions.js | 153 +++++++++++++-------- umap/static/umap/js/umap.forms.js | 2 + 3 files changed, 98 insertions(+), 64 deletions(-) diff --git a/umap/static/umap/base.css b/umap/static/umap/base.css index cb65a352..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; diff --git a/umap/static/umap/js/modules/permissions.js b/umap/static/umap/js/modules/permissions.js index df3acd19..f66de593 100644 --- a/umap/static/umap/js/modules/permissions.js +++ b/umap/static/umap/js/modules/permissions.js @@ -46,68 +46,21 @@ export class MapPermissions { return this.map } - edit() { - if (this.map.options.editMode !== 'advanced') return - if (!this.map.options.umap_id) { - return Alert.info(translate('Please save the map first')) - } - const container = DomUtil.create('div', 'permissions-panel') + _editAnonymous(container) { const fields = [] - DomUtil.createTitle(container, translate('Update permissions'), 'icon-key') - if (this.isAnonymousMap()) { - if (this.isOwner()) { - fields.push([ - 'options.edit_status', - { - handler: 'IntSelect', - label: translate('Who can edit'), - selectOptions: this.map.options.edit_statuses, - }, - ]) - } - } 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, - }, - ]) - } - } + if (this.isOwner()) { fields.push([ - 'options.editors', - { handler: 'ManageEditors', label: translate("Map's editors") }, + '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) - const builder = new U.FormBuilder(this, fields) - const form = builder.build() - container.appendChild(form) - if (this.isAnonymousMap()) { if (this.options.anonymous_edit_url) { DomUtil.createCopiableInput( container, @@ -133,12 +86,89 @@ export class MapPermissions { ) } } + } + + _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()) { - DomUtil.add('h4', '', container, translate('Datalayers')) + const fieldset = Utils.loadTemplate( + `
${translate('Datalayers')}
` + ) + container.appendChild(fieldset) this.map.eachDataLayer((datalayer) => { - datalayer.permissions.edit(container) + datalayer.permissions.edit(fieldset) }) } + } + + edit() { + if (this.map.options.editMode !== 'advanced') return + if (!this.map.options.umap_id) { + Alert.info(translate('Please save the map first')) + return + } + const container = DomUtil.create('div', 'permissions-panel') + DomUtil.createTitle(container, translate('Update permissions'), 'icon-key') + if (this.isAnonymousMap()) this._editAnonymous(container) + else this._editWithOwner(container) + this._editDatalayers(container) this.map.editPanel.open({ content: container, className: 'dark' }) } @@ -159,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()