mirror of
https://github.com/umap-project/umap.git
synced 2025-04-30 12:12:36 +02:00
Merge pull request #2121 from umap-project/permissions-revamp
Chore: rework permissions panel
This commit is contained in:
commit
52e0259a64
7 changed files with 133 additions and 93 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -189,5 +189,6 @@
|
|||
<path id="path8" transform="translate(0 812.36)" d="m8.1903 37.424c-0.48722-0.17411-0.79231-0.44207-0.99467-0.87363l-0.1908-0.40689-1.3703-0.0034c-1.4983-0.0037-1.5911-0.03214-1.5406-0.47225l0.026557-0.23161 2.8423-0.0451 0.19827-0.3895c0.34789-0.68343 0.86349-1.0091 1.5923-1.0058 0.71771 0.0033 1.3415 0.43242 1.6291 1.1207l0.11636 0.27848h4.6574c4.5203 0 4.66 0.0047 4.7428 0.1594 0.1159 0.21656 0.10767 0.30093-0.04419 0.45278-0.11466 0.11466-0.66063 0.1295-4.7632 0.1295h-4.6337l-0.10498 0.2903c-0.15257 0.42194-0.62749 0.84447-1.1103 0.98785-0.49622 0.14736-0.6615 0.14879-1.0524 0.0091zm0.96896-0.84513c0.698-0.33122 0.698-1.3772 0-1.7084-0.35156-0.16682-0.49258-0.16849-0.82704-0.0098-0.33761 0.16021-0.5445 0.51333-0.5445 0.92936 0 0.36801 0.16007 0.60614 0.53566 0.79693 0.31576 0.16039 0.48419 0.15875 0.83587-0.0081z" fill="#f2f2f2" stroke="#999" stroke-width=".25" style="paint-order:fill markers stroke"/>
|
||||
<path id="path9" transform="translate(0 812.36)" d="m12.773 42.244c-0.4045-0.18728-0.73246-0.52685-0.9029-0.93487l-0.12875-0.30821-7.6214-0.04285-0.026557-0.23161c-0.055311-0.48238-0.16774-0.4688 3.8893-0.46961l3.7189-7.33e-4 0.21287-0.43192c0.65163-1.3222 2.4726-1.2846 3.1257 0.06446l0.17859 0.36892h2.2972c2.2584 0 2.2988 3e-3 2.391 0.17524 0.06808 0.12721 0.06936 0.22886 0.0047 0.37084l-0.08912 0.1956h-4.6108l-0.15493 0.35024c-0.38713 0.87516-1.4373 1.2865-2.2839 0.89448zm1.0632-0.70036c0.37802-0.15795 0.5443-0.42579 0.54116-0.87174-4e-3 -0.57358-0.36338-0.90877-0.9743-0.90877-0.31204 0-0.40386 0.04292-0.64992 0.30383-0.25777 0.27331-0.28248 0.33986-0.2461 0.66262 0.04524 0.40136 0.22819 0.65122 0.5956 0.81339 0.31718 0.14001 0.39991 0.14008 0.73356 6.68e-4z" fill="#f2f2f2" stroke="#999" stroke-width=".25" style="paint-order:fill markers stroke"/>
|
||||
<path id="path1-67-5" d="m154.68 963.54 4.7344 4.7344-5.0508 4.6836-1.3594-1.4668 3.5274-3.2695-3.2656-3.2656z" color="#000000" fill="#f2f2f2" fill-rule="evenodd" stroke="#999" stroke-width=".25"/>
|
||||
<path id="copy" d="m58 914.36v3.5h4v4h3.5v-7.5zm-4 4v7.5h7.5v-7.5z" fill="#f2f2f2" style="paint-order:fill markers stroke"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
|
@ -211,5 +211,6 @@
|
|||
<path style="fill:#f2f2f2;stroke:#999999;stroke-width:0.25;paint-order:fill markers stroke" d="m 8.1902877,37.423896 c -0.4872187,-0.174113 -0.7923051,-0.442073 -0.9946703,-0.873627 l -0.1907982,-0.406887 -1.3702708,-0.0034 c -1.4982701,-0.0037 -1.5910875,-0.03214 -1.5406237,-0.47225 l 0.026557,-0.23161 1.4211632,-0.02255 1.4211632,-0.02255 0.1982698,-0.389502 c 0.347892,-0.683434 0.8634941,-1.009111 1.592299,-1.005764 0.7177082,0.0033 1.3415151,0.432422 1.6290831,1.120669 l 0.116359,0.278485 h 4.65745 c 4.520341,0 4.659962,0.0047 4.742759,0.159402 0.1159,0.216562 0.107667,0.300926 -0.04419,0.452784 -0.114657,0.114657 -0.660626,0.129501 -4.763204,0.129501 h -4.633703 l -0.104975,0.290304 c -0.152574,0.421935 -0.6274874,0.844474 -1.1103021,0.987854 -0.4962156,0.147361 -0.6614998,0.148792 -1.0523644,0.0091 z m 0.9689602,-0.845129 c 0.6980003,-0.331223 0.6980003,-1.377155 0,-1.708378 -0.3515556,-0.166824 -0.4925823,-0.168492 -0.8270409,-0.0098 -0.3376099,0.160207 -0.5444962,0.513326 -0.5444962,0.929363 0,0.368008 0.1600657,0.606145 0.5356626,0.796928 0.3157622,0.16039 0.4841923,0.158752 0.8358745,-0.0081 z" id="path8" transform="translate(0,812.36218)" />
|
||||
<path style="fill:#f2f2f2;stroke:#999999;stroke-width:0.25;paint-order:fill markers stroke" d="m 12.773494,42.243521 c -0.4045,-0.187277 -0.732456,-0.526846 -0.902897,-0.934868 l -0.128748,-0.308213 -3.8106837,-0.02143 -3.8106834,-0.02142 -0.026557,-0.23161 c -0.055311,-0.482381 -0.1677415,-0.468805 3.8892984,-0.469606 l 3.7189457,-7.33e-4 0.21287,-0.431917 c 0.651632,-1.322166 2.472575,-1.284611 3.125651,0.06446 l 0.178591,0.36892 h 2.297219 c 2.258426,0 2.298803,0.003 2.391007,0.175244 0.06808,0.127207 0.06936,0.228859 0.0047,0.370843 l -0.08912,0.1956 h -2.305381 -2.30538 l -0.15493,0.350241 c -0.387132,0.875164 -1.437261,1.286451 -2.283867,0.894485 z m 1.063202,-0.700358 c 0.378023,-0.157949 0.544298,-0.425794 0.541165,-0.871741 -0.004,-0.573585 -0.363385,-0.908772 -0.974299,-0.908772 -0.312041,0 -0.40386,0.04292 -0.649922,0.303826 -0.257768,0.273313 -0.282484,0.339859 -0.246104,0.662621 0.04524,0.401361 0.228194,0.651219 0.595596,0.813394 0.317179,0.140006 0.399909,0.140082 0.733564,6.68e-4 z" id="path9" transform="translate(0,812.36218)" />
|
||||
<path style="color:#000000;fill:#f2f2f2;fill-opacity:1;fill-rule:evenodd;stroke:#999999;stroke-width:0.25;stroke-dasharray:none;stroke-opacity:1" d="m 154.67579,963.53902 4.73437,4.73437 -5.05078,4.6836 -1.35938,-1.4668 3.52735,-3.26953 -3.26563,-3.26563 z" id="path1-67-5" />
|
||||
<path id="copy" style="fill:#f2f2f2;paint-order:fill markers stroke;fill-opacity:1" d="m 58,914.36218 v 3.5 h 4 v 4 h 3.5 v -7.5 z m -4,4 v 7.5 h 7.5 v -7.5 z" />
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 70 KiB |
|
@ -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(
|
||||
`<fieldset class="separator"><legend>${translate('Map')}</legend></fieldset>`
|
||||
)
|
||||
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(
|
||||
`<fieldset class="separator"><legend>${translate('Manage collaborators')}</legend></fieldset>`
|
||||
)
|
||||
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(
|
||||
`<fieldset class="separator"><legend>${translate('Datalayers')}</legend></fieldset>`
|
||||
)
|
||||
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:')}<br>${
|
||||
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 || '')
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue