diff --git a/requirements.txt b/requirements.txt
index f75f92f8..7713efcb 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,5 @@
Django==2.0.5
+django-agnocomplete==0.12.2
django-compressor==2.1.1
Pillow==5.1.0
psycopg2==2.7.4
diff --git a/umap/autocomplete.py b/umap/autocomplete.py
new file mode 100644
index 00000000..6a485182
--- /dev/null
+++ b/umap/autocomplete.py
@@ -0,0 +1,19 @@
+from django.conf import settings
+from django.contrib.auth import get_user_model
+from django.urls import reverse
+
+
+from agnocomplete.register import register
+from agnocomplete.core import AgnocompleteModel
+
+
+@register
+class AutocompleteUser(AgnocompleteModel):
+ model = get_user_model()
+ fields = ['^username']
+
+ def item(self, current_item):
+ data = super().item(current_item)
+ data['url'] = reverse(settings.USER_MAPS_URL,
+ args=(current_item.get_username(), ))
+ return data
diff --git a/umap/forms.py b/umap/forms.py
index 136cbba0..4a240ff4 100644
--- a/umap/forms.py
+++ b/umap/forms.py
@@ -1,5 +1,3 @@
-# -*- coding: utf-8 -*-
-
from django import forms
from django.contrib.gis.geos import Point
from django.contrib.auth import get_user_model
@@ -28,7 +26,6 @@ class FlatErrorList(ErrorList):
class UpdateMapPermissionsForm(forms.ModelForm):
- owner = forms.ModelChoiceField(User.objects, required=True)
class Meta:
model = Map
diff --git a/umap/models.py b/umap/models.py
index 66caa7e3..0f7e8f16 100644
--- a/umap/models.py
+++ b/umap/models.py
@@ -1,5 +1,3 @@
-# -*- coding: utf-8 -*-
-
import os
import time
@@ -175,6 +173,8 @@ class Map(NamedModel):
and self.is_anonymous_owner(request)):
can = True
if user and user.is_authenticated:
+ # TODO: only when using the anonymous-edit URL with an
+ # authenticated user
# if user is authenticated, attach as owner
self.owner = user
self.save()
diff --git a/umap/settings/base.py b/umap/settings/base.py
index 619d616d..23a93bc3 100644
--- a/umap/settings/base.py
+++ b/umap/settings/base.py
@@ -78,6 +78,7 @@ INSTALLED_APPS = (
'umap',
'compressor',
'social_django',
+ 'agnocomplete',
)
# =============================================================================
@@ -159,8 +160,6 @@ MIDDLEWARE = (
# =============================================================================
ENABLE_ACCOUNT_LOGIN = False
-AUTHENTICATION_BACKENDS += (
-)
# =============================================================================
# Miscellaneous project settings
diff --git a/umap/static/umap/js/umap.autocomplete.js b/umap/static/umap/js/umap.autocomplete.js
index 5cb887a9..0e180ef7 100644
--- a/umap/static/umap/js/umap.autocomplete.js
+++ b/umap/static/umap/js/umap.autocomplete.js
@@ -12,8 +12,10 @@ L.U.AutoComplete = L.Class.extend({
RESULTS: [],
initialize: function (el, options) {
- this.el = L.DomUtil.get(el);
- L.setOptions(options);
+ this.el = el;
+ var ui = new L.U.UI(document.querySelector('header'));
+ this.xhr = new L.U.Xhr(ui);
+ L.setOptions(this, options);
var CURRENT = null;
try {
Object.defineProperty(this, 'CURRENT', {
@@ -37,9 +39,9 @@ L.U.AutoComplete = L.Class.extend({
this.input = L.DomUtil.element('input', {
type: 'text',
placeholder: this.options.placeholder,
- autocomplete: 'off'
- });
- L.DomUtil.before(this.el, this.input);
+ autocomplete: 'off',
+ className: this.options.className
+ }, this.el);
L.DomEvent.on(this.input, 'keydown', this.onKeyDown, this);
L.DomEvent.on(this.input, 'keyup', this.onKeyUp, this);
L.DomEvent.on(this.input, 'blur', this.onBlur, this);
@@ -63,10 +65,7 @@ L.U.AutoComplete = L.Class.extend({
onKeyDown: function (e) {
switch (e.keyCode) {
case L.U.Keys.TAB:
- if(this.CURRENT !== null)
- {
- this.setChoice();
- }
+ if(this.CURRENT !== null) this.setChoice();
L.DomEvent.stop(e);
break;
case L.U.Keys.ENTER:
@@ -149,8 +148,8 @@ L.U.AutoComplete = L.Class.extend({
setChoice: function (choice) {
choice = choice || this.RESULTS[this.CURRENT];
if (choice) {
- this.input.value = choice.display;
- this.select(choice);
+ this.input.value = choice.item.label;
+ this.options.on_select(choice);
this.displaySelected(choice);
this.hide();
if (this.options.callback) {
@@ -165,26 +164,18 @@ L.U.AutoComplete = L.Class.extend({
this.clear();
return;
}
- if(!val) {
- this.clear();
- return;
- }
- if( val + '' === this.CACHE + '') {
- return;
- }
- else {
- this.CACHE = val;
- }
- var results = this._do_search(val);
- return this.handleResults(results);
+ if( val + '' === this.CACHE + '') return;
+ else this.CACHE = val;
+ this._do_search(val, (data) => {
+ this.handleResults(data.data);
+ });
},
createResult: function (item) {
var el = L.DomUtil.element('li', {}, this.container);
- el.innerHTML = item.display;
+ el.innerHTML = item.label;
var result = {
- value: item.value,
- display: item.display,
+ item: item,
el: el
};
L.DomEvent.on(el, 'mouseover', function () {
@@ -223,12 +214,12 @@ L.U.AutoComplete = L.Class.extend({
highlight: function () {
var self = this;
- this.forEach(this.RESULTS, function (item, index) {
+ this.forEach(this.RESULTS, function (result, index) {
if (index === self.CURRENT) {
- L.DomUtil.addClass(item.el, 'on');
+ L.DomUtil.addClass(result.el, 'on');
}
else {
- L.DomUtil.removeClass(item.el, 'on');
+ L.DomUtil.removeClass(result.el, 'on');
}
});
},
@@ -260,114 +251,69 @@ L.U.AutoComplete = L.Class.extend({
});
-L.U.AutoComplete.BaseSelect = L.U.AutoComplete.extend({
+L.U.AutoComplete.Ajax = L.U.AutoComplete.extend({
initialize: function (el, options) {
L.U.AutoComplete.prototype.initialize.call(this, el, options);
if (!this.el) return this;
- this.el.style.display = 'none';
this.createInput();
this.createContainer();
- this.initSelectedContainer();
+ this.selected_container = this.initSelectedContainer();
},
optionToResult: function (option) {
return {
value: option.value,
- display: option.innerHTML
+ label: option.innerHTML
};
},
- _do_search: function (val) {
- var results = [],
- self = this,
- count = 0;
- val = val.toLowerCase();
- this.forEach(this.el, function (item) {
- var candidate = item.innerHTML.toLowerCase();
- if (candidate === val || (candidate.indexOf(val) !== -1 && !item.selected && count < self.options.maxResults)) {
- results.push(self.optionToResult(item));
- count++;
- }
- });
- return results;
- },
-
- select: function (option) {
- this.forEach(this.el, function (item) {
- if (item.value == option.value) {
- item.selected = true;
- }
- });
- },
-
- unselect: function (option) {
- this.forEach(this.el, function (item) {
- if (item.value == option.value) {
- item.selected = false;
- }
- });
+ _do_search: function (val, callback) {
+ val = val.toLowerCase();
+ this.xhr.get('/agnocomplete/AutocompleteUser/?q=' + encodeURIComponent(val), {callback: callback});
}
});
-L.U.AutoComplete.MultiSelect = L.U.AutoComplete.BaseSelect.extend({
+L.U.AutoComplete.Ajax.SelectMultiple = L.U.AutoComplete.Ajax.extend({
initSelectedContainer: function () {
- this.selected_container = L.DomUtil.after(this.input, L.DomUtil.element('ul', {className: 'umap-multiresult'}));
- var self = this;
- this.forEach(this.el, function (option) {
- if (option.selected) {
- self.displaySelected(self.optionToResult(option));
- }
- });
+ return L.DomUtil.after(this.input, L.DomUtil.element('ul', {className: 'umap-multiresult'}));
},
displaySelected: function (result) {
var result_el = L.DomUtil.element('li', {}, this.selected_container);
- result_el.innerHTML = result.display;
+ result_el.innerHTML = result.item.label;
var close = L.DomUtil.element('span', {className: 'close'}, result_el);
close.innerHTML = '×';
L.DomEvent.on(close, 'click', function () {
this.selected_container.removeChild(result_el);
- this.unselect(result);
+ this.options.on_unselect(result);
}, this);
this.hide();
}
});
-L.U.AutoComplete.multiSelect = function (el, options) {
- return new L.U.AutoComplete.MultiSelect(el, options);
-};
-
-L.U.AutoComplete.Select = L.U.AutoComplete.BaseSelect.extend({
+L.U.AutoComplete.Ajax.Select = L.U.AutoComplete.Ajax.extend({
initSelectedContainer: function () {
- this.selected_container = L.DomUtil.after(this.input, L.DomUtil.element('div', {className: 'umap-singleresult'}));
- var self = this;
- if (this.el.selectedIndex !== -1 && this.el[this.el.selectedIndex].value !== '') {
- self.displaySelected(self.optionToResult(this.el[this.el.selectedIndex]));
- }
+ return L.DomUtil.after(this.input, L.DomUtil.element('div', {className: 'umap-singleresult'}));
},
displaySelected: function (result) {
var result_el = L.DomUtil.element('div', {}, this.selected_container);
- result_el.innerHTML = result.display;
+ result_el.innerHTML = result.item.label;
var close = L.DomUtil.element('span', {className: 'close'}, result_el);
close.innerHTML = '×';
this.input.style.display = 'none';
L.DomEvent.on(close, 'click', function () {
this.selected_container.innerHTML = '';
- this.unselect(result);
+ this.options.on_unselect(result);
this.input.style.display = 'block';
}, this);
this.hide();
}
});
-
-L.U.AutoComplete.select = function (el, options) {
- return new L.U.AutoComplete.Select(el, options);
-};
diff --git a/umap/static/umap/js/umap.controls.js b/umap/static/umap/js/umap.controls.js
index f56d5e6c..f00e2ec9 100644
--- a/umap/static/umap/js/umap.controls.js
+++ b/umap/static/umap/js/umap.controls.js
@@ -88,7 +88,7 @@ L.U.UpdatePermsAction = L.U.BaseAction.extend({
},
addHooks: function () {
- this.map.updatePermissions();
+ this.map.permissions.panel();
}
});
diff --git a/umap/static/umap/js/umap.forms.js b/umap/static/umap/js/umap.forms.js
index 428c980a..6ff6d801 100644
--- a/umap/static/umap/js/umap.forms.js
+++ b/umap/static/umap/js/umap.forms.js
@@ -322,6 +322,7 @@ L.FormBuilder.LicenceChooser = L.FormBuilder.Select.extend({
});
+
L.FormBuilder.NullableBoolean = L.FormBuilder.Select.extend({
selectOptions: [
[undefined, L._('inherit')],
@@ -601,6 +602,61 @@ L.FormBuilder.Range = L.FormBuilder.Input.extend({
});
+
+L.FormBuilder.ManageOwner = L.FormBuilder.Element.extend({
+
+ build: function () {
+ var options = {className: 'edit-owner'};
+ options.on_select = (choice) => {
+ this._value = {
+ 'id': choice.item.value,
+ 'name': choice.item.label,
+ 'url': choice.item.url
+ };
+ this.set();
+ }
+ this.autocomplete = new L.U.AutoComplete.Ajax.Select(this.parentNode, options);
+ var owner = this.toHTML();
+ if (owner) this.autocomplete.displaySelected({'item': {'value': owner.id, 'label': owner.name}});
+ },
+
+ value: function () {
+ return this._value;
+ }
+
+});
+
+
+L.FormBuilder.ManageEditors = L.FormBuilder.Element.extend({
+
+ build: function () {
+ var options = {className: 'edit-editors'};
+ options.on_select = (choice) => {
+ this._values.push({
+ 'id': choice.item.value,
+ 'name': choice.item.label,
+ 'url': choice.item.url
+ });
+ this.set();
+ }
+ options.on_unselect = (choice) => {
+ var index = this._values.findIndex((item) => item.id === choice.item.value);
+ if (index !== -1) {
+ this._values.splice(index, 1);
+ this.set();
+ }
+ }
+ this.autocomplete = new L.U.AutoComplete.Ajax.SelectMultiple(this.parentNode, options);
+ this._values = this.toHTML();
+ if (this._values) for (var i = 0; i < this._values.length; i++) this.autocomplete.displaySelected({'item': {'value': this._values[i].id, 'label': this._values[i].name}});
+ },
+
+ value: function () {
+ return this._values;
+ }
+
+});
+
L.U.FormBuilder = L.FormBuilder.extend({
options: {
diff --git a/umap/static/umap/js/umap.js b/umap/static/umap/js/umap.js
index 4e9ce433..ff61488c 100644
--- a/umap/static/umap/js/umap.js
+++ b/umap/static/umap/js/umap.js
@@ -198,6 +198,7 @@ L.U.Map.include({
this.help = new L.U.Help(this);
this.slideshow = new L.U.Slideshow(this, this.options.slideshow);
+ this.permissions = new L.U.MapPermissions(this, this.options.permissions);
this.initCaptionBar();
if (this.options.allowEdit) {
this.editTools = new L.U.Editable(this);
@@ -235,9 +236,9 @@ L.U.Map.include({
L.U.EditPropertiesAction,
L.U.ChangeTileLayerAction,
L.U.ManageDatalayersAction,
- L.U.UpdateExtentAction
+ L.U.UpdateExtentAction,
+ L.U.UpdatePermsAction
];
- if (this.options.urls.map_update_permissions) editActions.push(L.U.UpdatePermsAction);
new L.U.SettingsToolbar({actions: editActions}).addTo(this);
}
this._controls.zoom = new L.Control.Zoom({zoomInTitle: L._('Zoom in'), zoomOutTitle: L._('Zoom out')});
@@ -345,11 +346,13 @@ L.U.Map.include({
this._backupOptions = L.extend({}, this.options);
this._backupOptions.tilelayer = L.extend({}, this.options.tilelayer);
this._backupOptions.limitBounds = L.extend({}, this.options.limitBounds);
+ this._backupOptions.permissions = L.extend({}, this.permissions.options);
},
resetOptions: function () {
this.options = L.extend({}, this._backupOptions);
this.options.tilelayer = L.extend({}, this._backupOptions.tilelayer);
+ this.permissions.options = L.extend({}, this._backupOptions.permissions);
},
initShortcuts: function () {
@@ -676,15 +679,6 @@ L.U.Map.include({
return geojson;
},
- updatePermissions: function () {
- if (!this.options.umap_id) return this.ui.alert({content: L._('Please save the map before'), level: 'info'});
- var url = L.Util.template(this.options.urls.map_update_permissions, {'map_id': this.options.umap_id});
- this.get(url, {
- listen_form: {'id': 'map_edit'},
- className: 'dark'
- });
- },
-
importPanel: function () {
var container = L.DomUtil.create('div', 'umap-upload'),
title = L.DomUtil.create('h4', '', container),
@@ -862,13 +856,7 @@ L.U.Map.include({
var container = L.DomUtil.create('div', 'umap-caption'),
title = L.DomUtil.create('h3', '', container);
title.innerHTML = this.options.name;
- if (this.options.author && this.options.author.name && this.options.author.link) {
- var authorContainer = L.DomUtil.add('h5', 'umap-map-author', container, L._('by') + ' '),
- author = L.DomUtil.create('a');
- author.href = this.options.author.link;
- author.innerHTML = this.options.author.name;
- authorContainer.appendChild(author);
- }
+ this.permissions.addOwnerLink('h5', container);
if (this.options.description) {
var description = L.DomUtil.create('div', 'umap-map-description', container);
description.innerHTML = L.Util.toHTML(this.options.description);
@@ -1079,6 +1067,7 @@ L.U.Map.include({
formData.append('settings', JSON.stringify(geojson));
this.post(this.getSaveUrl(), {
data: formData,
+ context: this,
callback: function (data) {
var duration = 3000;
if (!this.options.umap_id) {
@@ -1094,9 +1083,8 @@ L.U.Map.include({
this.ui.alert({content: msg, level: 'info', duration: duration});
});
this.ui.closePanel();
- this.continueSaving();
- },
- context: this
+ this.permissions.save();
+ }
});
},
@@ -1376,13 +1364,7 @@ L.U.Map.include({
var container = L.DomUtil.create('div', 'umap-caption-bar', this._controlContainer),
name = L.DomUtil.create('h3', '', container);
L.DomEvent.disableClickPropagation(container);
- if (this.options.author && this.options.author.name && this.options.author.link) {
- var authorContainer = L.DomUtil.add('span', 'umap-map-author', container, ' ' + L._('by') + ' '),
- author = L.DomUtil.create('a');
- author.href = this.options.author.link;
- author.innerHTML = this.options.author.name;
- authorContainer.appendChild(author);
- }
+ this.permissions.addOwnerLink('span', container);
var about = L.DomUtil.add('a', 'umap-about-link', container, ' — ' + L._('About'));
about.href = '#';
L.DomEvent.on(about, 'click', this.displayCaption, this);
diff --git a/umap/static/umap/js/umap.permissions.js b/umap/static/umap/js/umap.permissions.js
new file mode 100644
index 00000000..4cb5cc6c
--- /dev/null
+++ b/umap/static/umap/js/umap.permissions.js
@@ -0,0 +1,119 @@
+// 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.
+L.U.MapPermissions = L.Class.extend({
+
+ options: {
+ owner: null,
+ editors: [],
+ share_status: null,
+ edit_status: null
+ },
+
+ initialize: function (map) {
+ this.options = map.options.permissions || {};
+ this.map = map;
+ var isDirty = false,
+ self = this;
+ try {
+ Object.defineProperty(this, 'isDirty', {
+ get: function () {
+ return isDirty;
+ },
+ set: function (status) {
+ isDirty = status;
+ if (status) self.map.isDirty = status;
+ }
+ });
+ }
+ catch (e) {
+ // Certainly IE8, which has a limited version of defineProperty
+ }
+
+ },
+
+ isOwner: function () {
+ return this.map.options.user && this.options.owner && this.map.options.user.id == this.options.owner.id;
+ },
+
+ isAnonymousMap: function () {
+ return !this.options.owner;
+ },
+
+ getMap: function () {
+ return this.map;
+ },
+
+ panel: function () {
+ if (!this.map.options.umap_id) return this.map.ui.alert({content: L._('Please save the map before'), level: 'info'});
+ var container = L.DomUtil.create('div', 'permissions-panel'),
+ fields = [],
+ title = L.DomUtil.create('h4', '', container);
+ if (this.isAnonymousMap()) {
+ if (this.map.options.anonymous_edit_url) {
+ var helpText = L._('Secret edit link is:
{link}', {link: this.map.options.anonymous_edit_url});
+ fields.push(['options.edit_status', {handler: 'IntSelect', label: L._('Who can edit'), selectOptions: this.map.options.anonymous_edit_statuses, helpText: helpText}]);
+ }
+ } else {
+ if (this.isOwner()) {
+ fields.push(['options.edit_status', {handler: 'IntSelect', label: L._('Who can edit'), selectOptions: this.map.options.edit_statuses}]);
+ fields.push(['options.share_status', {handler: 'IntSelect', label: L._('Who can view'), selectOptions: this.map.options.share_statuses}]);
+ fields.push(['options.owner', {handler: 'ManageOwner', label: L._("Map's owner")}]);
+ }
+ fields.push(['options.editors', {handler: 'ManageEditors', label: L._("Map's editors")}]);
+ }
+ title.innerHTML = L._('Update permissions');
+ var builder = new L.U.FormBuilder(this, fields);
+ var form = builder.build();
+ container.appendChild(form);
+ this.map.ui.openPanel({data: {html: container}, className: 'dark'});
+ },
+
+ anonymousMapPanel: function () {
+ var container = L.DomUtil.create('div'),
+ fields = [],
+ title = L.DomUtil.create('h4', '', container);
+ fields.push(['options.edit_status', {handler: 'IntSelect', label: L._('Who can edit'), selectOptions: this.map.options.edit_statuses}]);
+ title.innerHTML = L._('Update permissions');
+ var builder = new L.U.FormBuilder(this, fields);
+ var form = builder.build();
+ container.appendChild(form);
+ this.map.ui.openPanel({data: {html: container}, className: 'dark'});
+ },
+
+ save: function () {
+ if (!this.isDirty) return this.map.continueSaving();
+ var formData = new FormData();
+ if (!this.isAnonymousMap() && this.options.editors) {
+ const editors = this.options.editors.map((u) => u.id);
+ for (var i = 0; i < this.options.editors.length; i++) formData.append('editors', this.options.editors[i].id);
+ }
+ if (this.isOwner() || this.isAnonymousMap()) formData.append('edit_status', this.options.edit_status);
+ if (this.isOwner()) {
+ formData.append('owner', this.options.owner && this.options.owner.id);
+ formData.append('share_status', this.options.share_status);
+ }
+ this.map.post(this.getUrl(), {
+ data: formData,
+ context: this,
+ callback: function (data) {
+ this.isDirty = false;
+ this.map.continueSaving();
+ }
+ });
+ },
+
+ getUrl: function () {
+ return L.Util.template(this.map.options.urls.map_update_permissions, {'map_id': this.map.options.umap_id});
+ },
+
+ addOwnerLink: function (element, container) {
+ if (this.options.owner && this.options.owner.name && this.options.owner.url) {
+ var ownerContainer = L.DomUtil.add(element, 'umap-map-owner', container, ' ' + L._('by') + ' '),
+ owner = L.DomUtil.create('a');
+ owner.href = this.options.owner.url;
+ owner.innerHTML = this.options.owner.name;
+ ownerContainer.appendChild(owner);
+ }
+ }
+
+});
diff --git a/umap/static/umap/test/Map.js b/umap/static/umap/test/Map.js
index dd790df2..11d0eff6 100644
--- a/umap/static/umap/test/Map.js
+++ b/umap/static/umap/test/Map.js
@@ -1,4 +1,4 @@
-describe('L.Utorage.Map', function(){
+describe('L.Umap.Map', function(){
before(function () {
this.server = sinon.fakeServer.create();
diff --git a/umap/static/umap/test/Permissions.js b/umap/static/umap/test/Permissions.js
new file mode 100644
index 00000000..f214dcd9
--- /dev/null
+++ b/umap/static/umap/test/Permissions.js
@@ -0,0 +1,77 @@
+describe('L.Permissions', function () {
+ var path = '/map/99/datalayer/edit/62/';
+
+ before(function () {
+ this.server = sinon.fakeServer.create();
+ this.server.respondWith('GET', '/datalayer/62/', JSON.stringify(RESPONSES.datalayer62_GET));
+ this.map = initMap({umap_id: 99});
+ this.datalayer = this.map.getDataLayerByUmapId(62);
+ this.server.respond();
+ enableEdit();
+ });
+ after(function () {
+ clickCancel();
+ this.server.restore();
+ resetMap();
+ });
+
+ describe('#open()', function () {
+ var button;
+
+ it('should exist update permissions link', function () {
+ button = qs('a.update-map-permissions');
+ expect(button).to.be.ok;
+ });
+
+ it('should open table button click', function () {
+ happen.click(button);
+ expect(qs('.permissions-panel')).to.be.ok;
+ });
+
+ });
+ describe('#anonymous with cookie', function () {
+ var button;
+
+ it('should only allow edit_status', function () {
+ this.map.options.anonymous_edit_url = 'http://anonymous.url'
+ button = qs('a.update-map-permissions');
+ happen.click(button);
+ expect(qs('select[name="edit_status"]')).to.be.ok;
+ expect(qs('select[name="share_status"]')).not.to.be.ok;
+ expect(qs('input.edit-owner')).not.to.be.ok;
+ });
+
+ });
+
+ describe('#editor', function () {
+ var button;
+
+ it('should only allow editors', function () {
+ this.map.permissions.options.owner = {id: 1, url: '/url', name: 'jojo'};
+ button = qs('a.update-map-permissions');
+ happen.click(button);
+ expect(qs('select[name="edit_status"]')).not.to.be.ok;
+ expect(qs('select[name="share_status"]')).not.to.be.ok;
+ expect(qs('input.edit-owner')).not.to.be.ok;
+ expect(qs('input.edit-editors')).to.be.ok;
+ });
+
+ });
+
+ describe('#owner', function () {
+ var button;
+
+ it('should allow everything', function () {
+ this.map.permissions.options.owner = {id: 1, url: '/url', name: 'jojo'};
+ this.map.options.user = {id: 1, url: '/url', name: 'jojo'};
+ button = qs('a.update-map-permissions');
+ happen.click(button);
+ expect(qs('select[name="edit_status"]')).to.be.ok;
+ expect(qs('select[name="share_status"]')).to.be.ok;
+ expect(qs('input.edit-owner')).to.be.ok;
+ expect(qs('input.edit-editors')).to.be.ok;
+ });
+
+ });
+
+});
diff --git a/umap/static/umap/test/index.html b/umap/static/umap/test/index.html
index 4e455a84..639f31aa 100644
--- a/umap/static/umap/test/index.html
+++ b/umap/static/umap/test/index.html
@@ -22,6 +22,7 @@
+
@@ -31,6 +32,7 @@
+
@@ -41,8 +43,12 @@
-
-
+
+
+
+
+
+
@@ -68,6 +74,7 @@
+