WIP: move edit_status from Map to DataLayer
This commit is contained in:
parent
73d19e849f
commit
89ab029cab
11 changed files with 228 additions and 51 deletions
|
@ -8,8 +8,12 @@ from django.forms.utils import ErrorList
|
||||||
|
|
||||||
from .models import Map, DataLayer
|
from .models import Map, DataLayer
|
||||||
|
|
||||||
DEFAULT_LATITUDE = settings.LEAFLET_LATITUDE if hasattr(settings, "LEAFLET_LATITUDE") else 51
|
DEFAULT_LATITUDE = (
|
||||||
DEFAULT_LONGITUDE = settings.LEAFLET_LONGITUDE if hasattr(settings, "LEAFLET_LONGITUDE") else 2
|
settings.LEAFLET_LATITUDE if hasattr(settings, "LEAFLET_LATITUDE") else 51
|
||||||
|
)
|
||||||
|
DEFAULT_LONGITUDE = (
|
||||||
|
settings.LEAFLET_LONGITUDE if hasattr(settings, "LEAFLET_LONGITUDE") else 2
|
||||||
|
)
|
||||||
DEFAULT_CENTER = Point(DEFAULT_LONGITUDE, DEFAULT_LATITUDE)
|
DEFAULT_CENTER = Point(DEFAULT_LONGITUDE, DEFAULT_LATITUDE)
|
||||||
|
|
||||||
User = get_user_model()
|
User = get_user_model()
|
||||||
|
@ -21,8 +25,8 @@ class FlatErrorList(ErrorList):
|
||||||
|
|
||||||
def flat(self):
|
def flat(self):
|
||||||
if not self:
|
if not self:
|
||||||
return u''
|
return ""
|
||||||
return u' — '.join([e for e in self])
|
return " — ".join([e for e in self])
|
||||||
|
|
||||||
|
|
||||||
class SendLinkForm(forms.Form):
|
class SendLinkForm(forms.Form):
|
||||||
|
@ -30,69 +34,83 @@ class SendLinkForm(forms.Form):
|
||||||
|
|
||||||
|
|
||||||
class UpdateMapPermissionsForm(forms.ModelForm):
|
class UpdateMapPermissionsForm(forms.ModelForm):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Map
|
model = Map
|
||||||
fields = ('edit_status', 'editors', 'share_status', 'owner')
|
fields = ("edit_status", "editors", "share_status", "owner")
|
||||||
|
|
||||||
|
|
||||||
class AnonymousMapPermissionsForm(forms.ModelForm):
|
class AnonymousMapPermissionsForm(forms.ModelForm):
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(AnonymousMapPermissionsForm, self).__init__(*args, **kwargs)
|
super(AnonymousMapPermissionsForm, self).__init__(*args, **kwargs)
|
||||||
help_text = _('Secret edit link is %s') % self.instance.get_anonymous_edit_url()
|
help_text = _("Secret edit link is %s") % self.instance.get_anonymous_edit_url()
|
||||||
self.fields['edit_status'].help_text = _(help_text)
|
self.fields["edit_status"].help_text = _(help_text)
|
||||||
|
|
||||||
STATUS = (
|
STATUS = (
|
||||||
(Map.ANONYMOUS, _('Everyone can edit')),
|
(Map.ANONYMOUS, _("Everyone can edit")),
|
||||||
(Map.OWNER, _('Only editable with secret edit link'))
|
(Map.OWNER, _("Only editable with secret edit link")),
|
||||||
)
|
)
|
||||||
|
|
||||||
edit_status = forms.ChoiceField(choices=STATUS)
|
edit_status = forms.ChoiceField(choices=STATUS)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Map
|
model = Map
|
||||||
fields = ('edit_status', )
|
fields = ("edit_status",)
|
||||||
|
|
||||||
|
|
||||||
class DataLayerForm(forms.ModelForm):
|
class DataLayerForm(forms.ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = DataLayer
|
||||||
|
fields = ("geojson", "name", "display_on_load", "rank", "settings")
|
||||||
|
|
||||||
|
|
||||||
|
class DataLayerPermissionsForm(forms.ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = DataLayer
|
||||||
|
fields = ("edit_status",)
|
||||||
|
|
||||||
|
|
||||||
|
class AnonymousDataLayerPermissionsForm(forms.ModelForm):
|
||||||
|
STATUS = (
|
||||||
|
(Map.ANONYMOUS, _("Everyone can edit")),
|
||||||
|
(Map.OWNER, _("Only editable with secret edit link")),
|
||||||
|
)
|
||||||
|
|
||||||
|
edit_status = forms.ChoiceField(choices=STATUS)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = DataLayer
|
model = DataLayer
|
||||||
fields = ('geojson', 'name', 'display_on_load', 'rank', 'settings')
|
fields = ("edit_status",)
|
||||||
|
|
||||||
|
|
||||||
class MapSettingsForm(forms.ModelForm):
|
class MapSettingsForm(forms.ModelForm):
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(MapSettingsForm, self).__init__(*args, **kwargs)
|
super(MapSettingsForm, self).__init__(*args, **kwargs)
|
||||||
self.fields['slug'].required = False
|
self.fields["slug"].required = False
|
||||||
self.fields['center'].widget.map_srid = 4326
|
self.fields["center"].widget.map_srid = 4326
|
||||||
|
|
||||||
def clean_slug(self):
|
def clean_slug(self):
|
||||||
slug = self.cleaned_data.get('slug', None)
|
slug = self.cleaned_data.get("slug", None)
|
||||||
name = self.cleaned_data.get('name', None)
|
name = self.cleaned_data.get("name", None)
|
||||||
if not slug and name:
|
if not slug and name:
|
||||||
# If name is empty, don't do nothing, validation will raise
|
# If name is empty, don't do nothing, validation will raise
|
||||||
# later on the process because name is required
|
# later on the process because name is required
|
||||||
self.cleaned_data['slug'] = slugify(name) or "map"
|
self.cleaned_data["slug"] = slugify(name) or "map"
|
||||||
return self.cleaned_data['slug'][:50]
|
return self.cleaned_data["slug"][:50]
|
||||||
else:
|
else:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
def clean_center(self):
|
def clean_center(self):
|
||||||
if not self.cleaned_data['center']:
|
if not self.cleaned_data["center"]:
|
||||||
point = DEFAULT_CENTER
|
point = DEFAULT_CENTER
|
||||||
self.cleaned_data['center'] = point
|
self.cleaned_data["center"] = point
|
||||||
return self.cleaned_data['center']
|
return self.cleaned_data["center"]
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
fields = ('settings', 'name', 'center', 'slug')
|
fields = ("settings", "name", "center", "slug")
|
||||||
model = Map
|
model = Map
|
||||||
|
|
||||||
|
|
||||||
class UserProfileForm(forms.ModelForm):
|
class UserProfileForm(forms.ModelForm):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
fields = ('username', 'first_name', 'last_name')
|
fields = ("username", "first_name", "last_name")
|
||||||
|
|
22
umap/migrations/0013_datalayer_edit_status.py
Normal file
22
umap/migrations/0013_datalayer_edit_status.py
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
# Generated by Django 4.2.2 on 2023-09-07 06:27
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import umap.models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("umap", "0012_datalayer_settings"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="datalayer",
|
||||||
|
name="edit_status",
|
||||||
|
field=models.SmallIntegerField(
|
||||||
|
choices=[(1, "Everyone"), (2, "Editors only"), (3, "Owner only")],
|
||||||
|
default=umap.models.get_default_edit_status,
|
||||||
|
verbose_name="edit status",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -216,6 +216,9 @@ class Map(NamedModel):
|
||||||
"""
|
"""
|
||||||
Define if a user can edit or not the instance, according to his account
|
Define if a user can edit or not the instance, according to his account
|
||||||
or the request.
|
or the request.
|
||||||
|
|
||||||
|
In ownership mode: only owner and editors
|
||||||
|
In anononymous mode: only "anonymous owners" (having edit cookie set)
|
||||||
"""
|
"""
|
||||||
can = False
|
can = False
|
||||||
if request and not self.owner:
|
if request and not self.owner:
|
||||||
|
@ -223,13 +226,9 @@ class Map(NamedModel):
|
||||||
settings, "UMAP_ALLOW_ANONYMOUS", False
|
settings, "UMAP_ALLOW_ANONYMOUS", False
|
||||||
) and self.is_anonymous_owner(request):
|
) and self.is_anonymous_owner(request):
|
||||||
can = True
|
can = True
|
||||||
if self.edit_status == self.ANONYMOUS:
|
if user == self.owner:
|
||||||
can = True
|
can = True
|
||||||
elif not user.is_authenticated:
|
elif user in self.editors.all():
|
||||||
pass
|
|
||||||
elif user == self.owner:
|
|
||||||
can = True
|
|
||||||
elif self.edit_status == self.EDITORS and user in self.editors.all():
|
|
||||||
can = True
|
can = True
|
||||||
return can
|
return can
|
||||||
|
|
||||||
|
@ -303,6 +302,15 @@ class DataLayer(NamedModel):
|
||||||
Layer to store Features in.
|
Layer to store Features in.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
ANONYMOUS = 1
|
||||||
|
EDITORS = 2
|
||||||
|
OWNER = 3
|
||||||
|
EDIT_STATUS = (
|
||||||
|
(ANONYMOUS, _("Everyone")),
|
||||||
|
(EDITORS, _("Editors only")),
|
||||||
|
(OWNER, _("Owner only")),
|
||||||
|
)
|
||||||
|
|
||||||
map = models.ForeignKey(Map, on_delete=models.CASCADE)
|
map = models.ForeignKey(Map, on_delete=models.CASCADE)
|
||||||
description = models.TextField(blank=True, null=True, verbose_name=_("description"))
|
description = models.TextField(blank=True, null=True, verbose_name=_("description"))
|
||||||
geojson = models.FileField(upload_to=upload_to, blank=True, null=True)
|
geojson = models.FileField(upload_to=upload_to, blank=True, null=True)
|
||||||
|
@ -315,6 +323,11 @@ class DataLayer(NamedModel):
|
||||||
settings = models.JSONField(
|
settings = models.JSONField(
|
||||||
blank=True, null=True, verbose_name=_("settings"), default=dict
|
blank=True, null=True, verbose_name=_("settings"), default=dict
|
||||||
)
|
)
|
||||||
|
edit_status = models.SmallIntegerField(
|
||||||
|
choices=EDIT_STATUS,
|
||||||
|
default=get_default_edit_status,
|
||||||
|
verbose_name=_("edit status"),
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ("rank",)
|
ordering = ("rank",)
|
||||||
|
@ -346,8 +359,7 @@ class DataLayer(NamedModel):
|
||||||
path.append(str(self.map.pk))
|
path.append(str(self.map.pk))
|
||||||
return os.path.join(*path)
|
return os.path.join(*path)
|
||||||
|
|
||||||
@property
|
def metadata(self, user=None, request=None):
|
||||||
def metadata(self):
|
|
||||||
# Retrocompat: minimal settings for maps not saved after settings property
|
# Retrocompat: minimal settings for maps not saved after settings property
|
||||||
# has been introduced
|
# has been introduced
|
||||||
obj = self.settings or {
|
obj = self.settings or {
|
||||||
|
@ -355,6 +367,8 @@ class DataLayer(NamedModel):
|
||||||
"displayOnLoad": self.display_on_load,
|
"displayOnLoad": self.display_on_load,
|
||||||
}
|
}
|
||||||
obj["id"] = self.pk
|
obj["id"] = self.pk
|
||||||
|
obj["permissions"] = {"edit_status": self.edit_status}
|
||||||
|
obj["allowEdit"] = self.can_edit(user, request)
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
def clone(self, map_inst=None):
|
def clone(self, map_inst=None):
|
||||||
|
@ -413,6 +427,19 @@ class DataLayer(NamedModel):
|
||||||
if name.startswith(f'{self.pk}_') and name.endswith(".gz"):
|
if name.startswith(f'{self.pk}_') and name.endswith(".gz"):
|
||||||
self.geojson.storage.delete(os.path.join(root, name))
|
self.geojson.storage.delete(os.path.join(root, name))
|
||||||
|
|
||||||
|
def can_edit(self, user=None, request=None):
|
||||||
|
"""
|
||||||
|
Define if a user can edit or not the instance, according to his account
|
||||||
|
or the request.
|
||||||
|
"""
|
||||||
|
can = self.map.can_edit(user, request)
|
||||||
|
if can:
|
||||||
|
# Owner or editor, no need for further checks.
|
||||||
|
return can
|
||||||
|
if self.edit_status == self.ANONYMOUS:
|
||||||
|
can = True
|
||||||
|
return can
|
||||||
|
|
||||||
|
|
||||||
class Star(models.Model):
|
class Star(models.Model):
|
||||||
at = models.DateTimeField(auto_now=True)
|
at = models.DateTimeField(auto_now=True)
|
||||||
|
|
70
umap/static/umap/js/umap.datalayer.permissions.js
Normal file
70
umap/static/umap/js/umap.datalayer.permissions.js
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
L.U.DataLayerPermissions = L.Class.extend({
|
||||||
|
options: {
|
||||||
|
edit_status: null,
|
||||||
|
},
|
||||||
|
|
||||||
|
initialize: function (datalayer) {
|
||||||
|
this.options = L.Util.setOptions(this, datalayer.options.permissions)
|
||||||
|
this.datalayer = datalayer
|
||||||
|
let isDirty = false
|
||||||
|
const self = this
|
||||||
|
try {
|
||||||
|
Object.defineProperty(this, 'isDirty', {
|
||||||
|
get: function () {
|
||||||
|
return isDirty
|
||||||
|
},
|
||||||
|
set: function (status) {
|
||||||
|
isDirty = status
|
||||||
|
if (status) self.datalayer.isDirty = status
|
||||||
|
},
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
// Certainly IE8, which has a limited version of defineProperty
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getMap: function () {
|
||||||
|
return this.datalayer.map
|
||||||
|
},
|
||||||
|
|
||||||
|
edit: function (container) {
|
||||||
|
const fields = [
|
||||||
|
[
|
||||||
|
'options.edit_status',
|
||||||
|
{
|
||||||
|
handler: 'IntSelect',
|
||||||
|
label: `${L._('Who can edit')} "${this.datalayer.getName()}"`,
|
||||||
|
selectOptions: this.datalayer.map.options.edit_statuses,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
builder = new L.U.FormBuilder(this, fields),
|
||||||
|
form = builder.build()
|
||||||
|
container.appendChild(form)
|
||||||
|
},
|
||||||
|
|
||||||
|
getUrl: function () {
|
||||||
|
return L.Util.template(this.datalayer.map.options.urls.datalayer_permissions, {
|
||||||
|
map_id: this.datalayer.map.options.umap_id,
|
||||||
|
pk: this.datalayer.umap_id,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
save: function () {
|
||||||
|
if (!this.isDirty) return this.datalayer.map.continueSaving()
|
||||||
|
const formData = new FormData()
|
||||||
|
formData.append('edit_status', this.options.edit_status)
|
||||||
|
this.datalayer.map.post(this.getUrl(), {
|
||||||
|
data: formData,
|
||||||
|
context: this,
|
||||||
|
callback: function (data) {
|
||||||
|
this.commit()
|
||||||
|
this.isDirty = false
|
||||||
|
this.datalayer.map.continueSaving()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
commit: function () {
|
||||||
|
L.Util.extend(this.datalayer.options.permissions, this.options)
|
||||||
|
},
|
||||||
|
})
|
|
@ -40,7 +40,7 @@ L.U.FeatureMixin = {
|
||||||
preInit: function () {},
|
preInit: function () {},
|
||||||
|
|
||||||
isReadOnly: function () {
|
isReadOnly: function () {
|
||||||
return this.datalayer && this.datalayer.isRemoteLayer()
|
return this.datalayer && (this.datalayer.isRemoteLayer() || this.datalayer.isReadOnly())
|
||||||
},
|
},
|
||||||
|
|
||||||
getSlug: function () {
|
getSlug: function () {
|
||||||
|
|
|
@ -261,6 +261,7 @@ L.U.DataLayer = L.Evented.extend({
|
||||||
}
|
}
|
||||||
this.backupOptions()
|
this.backupOptions()
|
||||||
this.connectToMap()
|
this.connectToMap()
|
||||||
|
this.permissions = new L.U.DataLayerPermissions(this)
|
||||||
if (this.showAtLoad()) this.show()
|
if (this.showAtLoad()) this.show()
|
||||||
if (!this.umap_id) this.isDirty = true
|
if (!this.umap_id) this.isDirty = true
|
||||||
|
|
||||||
|
@ -350,6 +351,13 @@ L.U.DataLayer = L.Evented.extend({
|
||||||
this.map.get(this._dataUrl(), {
|
this.map.get(this._dataUrl(), {
|
||||||
callback: function (geojson, response) {
|
callback: function (geojson, response) {
|
||||||
this._last_modified = response.getResponseHeader('Last-Modified')
|
this._last_modified = response.getResponseHeader('Last-Modified')
|
||||||
|
console.log(this.getName(), this.options)
|
||||||
|
// FIXME: for now this property is set dynamically from backend
|
||||||
|
// And thus it's not in the geojson file in the server
|
||||||
|
// So do not let all options to be reset
|
||||||
|
// Fix is a proper migration so all datalayers settings are
|
||||||
|
// in DB, and we remove it from geojson flat files.
|
||||||
|
geojson['_umap_options']['allowEdit'] = this.options.allowEdit
|
||||||
this.fromUmapGeoJSON(geojson)
|
this.fromUmapGeoJSON(geojson)
|
||||||
this.backupOptions()
|
this.backupOptions()
|
||||||
this.fire('loaded')
|
this.fire('loaded')
|
||||||
|
@ -1182,18 +1190,14 @@ L.U.DataLayer = L.Evented.extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
metadata: function () {
|
|
||||||
return {
|
|
||||||
id: this.umap_id,
|
|
||||||
name: this.options.name,
|
|
||||||
displayOnLoad: this.options.displayOnLoad,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
getRank: function () {
|
getRank: function () {
|
||||||
return this.map.datalayers_index.indexOf(this)
|
return this.map.datalayers_index.indexOf(this)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
isReadOnly: function () {
|
||||||
|
return !this.options.allowEdit
|
||||||
|
},
|
||||||
|
|
||||||
save: function () {
|
save: function () {
|
||||||
if (this.isDeleted) return this.saveDelete()
|
if (this.isDeleted) return this.saveDelete()
|
||||||
if (!this.isLoaded()) {
|
if (!this.isLoaded()) {
|
||||||
|
@ -1220,7 +1224,7 @@ L.U.DataLayer = L.Evented.extend({
|
||||||
this._loaded = true
|
this._loaded = true
|
||||||
this.redraw() // Needed for reordering features
|
this.redraw() // Needed for reordering features
|
||||||
this.isDirty = false
|
this.isDirty = false
|
||||||
this.map.continueSaving()
|
this.permissions.save()
|
||||||
},
|
},
|
||||||
context: this,
|
context: this,
|
||||||
headers: this._last_modified
|
headers: this._last_modified
|
||||||
|
|
|
@ -122,6 +122,10 @@ L.U.MapPermissions = L.Class.extend({
|
||||||
this
|
this
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
L.DomUtil.add('h3', '', container, L._('Datalayers'))
|
||||||
|
this.map.eachDataLayer((datalayer) => {
|
||||||
|
datalayer.permissions.edit(container)
|
||||||
|
})
|
||||||
this.map.ui.openPanel({ data: { html: container }, className: 'dark' })
|
this.map.ui.openPanel({ data: { html: container }, className: 'dark' })
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -34,11 +34,12 @@
|
||||||
<script src="{{ STATIC_URL }}umap/js/umap.forms.js"></script>
|
<script src="{{ STATIC_URL }}umap/js/umap.forms.js"></script>
|
||||||
<script src="{{ STATIC_URL }}umap/js/umap.icon.js"></script>
|
<script src="{{ STATIC_URL }}umap/js/umap.icon.js"></script>
|
||||||
<script src="{{ STATIC_URL }}umap/js/umap.features.js"></script>
|
<script src="{{ STATIC_URL }}umap/js/umap.features.js"></script>
|
||||||
|
<script src="{{ STATIC_URL }}umap/js/umap.permissions.js"></script>
|
||||||
|
<script src="{{ STATIC_URL }}umap/js/umap.datalayer.permissions.js"></script>
|
||||||
<script src="{{ STATIC_URL }}umap/js/umap.layer.js"></script>
|
<script src="{{ STATIC_URL }}umap/js/umap.layer.js"></script>
|
||||||
<script src="{{ STATIC_URL }}umap/js/umap.controls.js"></script>
|
<script src="{{ STATIC_URL }}umap/js/umap.controls.js"></script>
|
||||||
<script src="{{ STATIC_URL }}umap/js/umap.slideshow.js"></script>
|
<script src="{{ STATIC_URL }}umap/js/umap.slideshow.js"></script>
|
||||||
<script src="{{ STATIC_URL }}umap/js/umap.tableeditor.js"></script>
|
<script src="{{ STATIC_URL }}umap/js/umap.tableeditor.js"></script>
|
||||||
<script src="{{ STATIC_URL }}umap/js/umap.permissions.js"></script>
|
|
||||||
<script src="{{ STATIC_URL }}umap/js/umap.js"></script>
|
<script src="{{ STATIC_URL }}umap/js/umap.js"></script>
|
||||||
<script src="{{ STATIC_URL }}umap/js/umap.ui.js"></script>
|
<script src="{{ STATIC_URL }}umap/js/umap.ui.js"></script>
|
||||||
{% endcompress %}
|
{% endcompress %}
|
||||||
|
|
|
@ -28,7 +28,7 @@ def umap_js(locale=None):
|
||||||
@register.inclusion_tag('umap/map_fragment.html')
|
@register.inclusion_tag('umap/map_fragment.html')
|
||||||
def map_fragment(map_instance, **kwargs):
|
def map_fragment(map_instance, **kwargs):
|
||||||
layers = DataLayer.objects.filter(map=map_instance)
|
layers = DataLayer.objects.filter(map=map_instance)
|
||||||
datalayer_data = [c.metadata for c in layers]
|
datalayer_data = [c.metadata() for c in layers]
|
||||||
map_settings = map_instance.settings
|
map_settings = map_instance.settings
|
||||||
if "properties" not in map_settings:
|
if "properties" not in map_settings:
|
||||||
map_settings['properties'] = {}
|
map_settings['properties'] = {}
|
||||||
|
|
|
@ -154,6 +154,11 @@ map_urls = [
|
||||||
views.DataLayerDelete.as_view(),
|
views.DataLayerDelete.as_view(),
|
||||||
name="datalayer_delete",
|
name="datalayer_delete",
|
||||||
),
|
),
|
||||||
|
re_path(
|
||||||
|
r"^map/(?P<map_id>[\d]+)/datalayer/permissions/(?P<pk>\d+)/$",
|
||||||
|
views.UpdateDataLayerPermissions.as_view(),
|
||||||
|
name="datalayer_permissions",
|
||||||
|
),
|
||||||
]
|
]
|
||||||
if settings.FROM_EMAIL:
|
if settings.FROM_EMAIL:
|
||||||
map_urls.append(
|
map_urls.append(
|
||||||
|
|
|
@ -47,6 +47,8 @@ from .forms import (
|
||||||
DEFAULT_CENTER,
|
DEFAULT_CENTER,
|
||||||
AnonymousMapPermissionsForm,
|
AnonymousMapPermissionsForm,
|
||||||
DataLayerForm,
|
DataLayerForm,
|
||||||
|
DataLayerPermissionsForm,
|
||||||
|
AnonymousDataLayerPermissionsForm,
|
||||||
FlatErrorList,
|
FlatErrorList,
|
||||||
MapSettingsForm,
|
MapSettingsForm,
|
||||||
SendLinkForm,
|
SendLinkForm,
|
||||||
|
@ -551,11 +553,16 @@ class MapView(MapDetailMixin, PermissionsMixin, DetailView):
|
||||||
return self.object.get_absolute_url()
|
return self.object.get_absolute_url()
|
||||||
|
|
||||||
def get_datalayers(self):
|
def get_datalayers(self):
|
||||||
datalayers = DataLayer.objects.filter(map=self.object)
|
return [
|
||||||
return [l.metadata for l in datalayers]
|
l.metadata(self.request.user, self.request)
|
||||||
|
for l in self.object.datalayer_set.all()
|
||||||
|
]
|
||||||
|
|
||||||
def is_edit_allowed(self):
|
def is_edit_allowed(self):
|
||||||
return self.object.can_edit(self.request.user, self.request)
|
return self.object.can_edit(self.request.user, self.request) or any(
|
||||||
|
d.can_edit(self.request.user, self.request)
|
||||||
|
for d in self.object.datalayer_set.all()
|
||||||
|
)
|
||||||
|
|
||||||
def get_umap_id(self):
|
def get_umap_id(self):
|
||||||
return self.object.pk
|
return self.object.pk
|
||||||
|
@ -883,7 +890,9 @@ class DataLayerCreate(FormLessEditMixin, GZipMixin, CreateView):
|
||||||
form.instance.map = self.kwargs["map_inst"]
|
form.instance.map = self.kwargs["map_inst"]
|
||||||
self.object = form.save()
|
self.object = form.save()
|
||||||
# Simple response with only metadatas (including new id)
|
# Simple response with only metadatas (including new id)
|
||||||
response = simple_json_response(**self.object.metadata)
|
response = simple_json_response(
|
||||||
|
**self.object.metadata(self.request.user, self.request)
|
||||||
|
)
|
||||||
response["Last-Modified"] = self.last_modified
|
response["Last-Modified"] = self.last_modified
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
@ -896,7 +905,9 @@ class DataLayerUpdate(FormLessEditMixin, GZipMixin, UpdateView):
|
||||||
self.object = form.save()
|
self.object = form.save()
|
||||||
# Simple response with only metadatas (client should not reload all data
|
# Simple response with only metadatas (client should not reload all data
|
||||||
# on save)
|
# on save)
|
||||||
response = simple_json_response(**self.object.metadata)
|
response = simple_json_response(
|
||||||
|
**self.object.metadata(self.request.user, self.request)
|
||||||
|
)
|
||||||
response["Last-Modified"] = self.last_modified
|
response["Last-Modified"] = self.last_modified
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
@ -936,6 +947,21 @@ class DataLayerVersions(BaseDetailView):
|
||||||
return simple_json_response(versions=self.object.versions)
|
return simple_json_response(versions=self.object.versions)
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateDataLayerPermissions(FormLessEditMixin, UpdateView):
|
||||||
|
model = DataLayer
|
||||||
|
pk_url_kwarg = "pk"
|
||||||
|
|
||||||
|
def get_form_class(self):
|
||||||
|
if self.object.map.owner:
|
||||||
|
return DataLayerPermissionsForm
|
||||||
|
else:
|
||||||
|
return AnonymousDataLayerPermissionsForm
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
|
self.object = form.save()
|
||||||
|
return simple_json_response(info=_("Permissions updated with success!"))
|
||||||
|
|
||||||
|
|
||||||
# ############## #
|
# ############## #
|
||||||
# Picto #
|
# Picto #
|
||||||
# ############## #
|
# ############## #
|
||||||
|
|
Loading…
Reference in a new issue