Skip to content

Commit

Permalink
feat: introduce Map.share_status=DRAFT and DELETED
Browse files Browse the repository at this point in the history
  • Loading branch information
yohanboniface committed Dec 10, 2024
1 parent c15ecfc commit 955b1d5
Show file tree
Hide file tree
Showing 12 changed files with 238 additions and 98 deletions.
18 changes: 4 additions & 14 deletions umap/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,12 @@ class Meta:


class AnonymousMapPermissionsForm(forms.ModelForm):
STATUS = (
(Map.OWNER, _("Only editable with secret edit link")),
(Map.ANONYMOUS, _("Everyone can edit")),
)

edit_status = forms.ChoiceField(choices=STATUS)
edit_status = forms.ChoiceField(choices=Map.ANONYMOUS_EDIT_STATUS)
share_status = forms.ChoiceField(choices=Map.ANONYMOUS_SHARE_STATUS)

class Meta:
model = Map
fields = ("edit_status",)
fields = ("edit_status", "share_status")


class DataLayerForm(forms.ModelForm):
Expand All @@ -65,13 +61,7 @@ class Meta:


class AnonymousDataLayerPermissionsForm(forms.ModelForm):
STATUS = (
(DataLayer.INHERIT, _("Inherit")),
(DataLayer.OWNER, _("Only editable with secret edit link")),
(DataLayer.ANONYMOUS, _("Everyone can edit")),
)

edit_status = forms.ChoiceField(choices=STATUS)
edit_status = forms.ChoiceField(choices=DataLayer.ANONYMOUS_EDIT_STATUS)

class Meta:
model = DataLayer
Expand Down
39 changes: 32 additions & 7 deletions umap/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,22 @@ def get_user_stars_url(self):
return reverse("user_stars", kwargs={"identifier": identifier})


def get_user_metadata(self):
return {
"id": self.pk,
"name": str(self),
"url": self.get_url(),
}


User.add_to_class("__str__", display_name)
User.add_to_class("get_url", get_user_url)
User.add_to_class("get_stars_url", get_user_stars_url)
User.add_to_class("get_metadata", get_user_metadata)


def get_default_share_status():
return settings.UMAP_DEFAULT_SHARE_STATUS or Map.PUBLIC
return settings.UMAP_DEFAULT_SHARE_STATUS or Map.DRAFT


def get_default_edit_status():
Expand Down Expand Up @@ -161,20 +170,30 @@ class Map(NamedModel):
ANONYMOUS = 1
COLLABORATORS = 2
OWNER = 3
DRAFT = 0
PUBLIC = 1
OPEN = 2
PRIVATE = 3
BLOCKED = 9
DELETED = 99
ANONYMOUS_EDIT_STATUS = (
(OWNER, _("Only editable with secret edit link")),
(ANONYMOUS, _("Everyone can edit")),
)
EDIT_STATUS = (
(ANONYMOUS, _("Everyone")),
(COLLABORATORS, _("Editors and team only")),
(OWNER, _("Owner only")),
)
SHARE_STATUS = (
ANONYMOUS_SHARE_STATUS = (
(DRAFT, _("Draft (private)")),
(PUBLIC, _("Everyone (public)")),
)
SHARE_STATUS = ANONYMOUS_SHARE_STATUS + (
(OPEN, _("Anyone with link")),
(PRIVATE, _("Editors and team only")),
(BLOCKED, _("Blocked")),
(DELETED, _("Deleted")),
)
slug = models.SlugField(db_index=True)
center = models.PointField(geography=True, verbose_name=_("center"))
Expand Down Expand Up @@ -352,19 +371,20 @@ def can_edit(self, request=None):
return can

def can_view(self, request):
if self.share_status == self.BLOCKED:
if self.share_status in [Map.BLOCKED, Map.DELETED]:
can = False
elif self.owner is None:
can = True
elif self.share_status in [self.PUBLIC, self.OPEN]:
elif self.share_status in [Map.PUBLIC, Map.OPEN]:
can = True
elif self.owner is None:
can = settings.UMAP_ALLOW_ANONYMOUS and self.is_anonymous_owner(request)
elif not request.user.is_authenticated:
can = False
elif request.user == self.owner:
can = True
else:
restricted = self.share_status in [Map.PRIVATE, Map.DRAFT]
can = not (
self.share_status == self.PRIVATE
restricted
and request.user not in self.editors.all()
and self.team not in request.user.teams.all()
)
Expand Down Expand Up @@ -444,6 +464,11 @@ class DataLayer(NamedModel):
(COLLABORATORS, _("Editors and team only")),
(OWNER, _("Owner only")),
)
ANONYMOUS_EDIT_STATUS = (
(INHERIT, _("Inherit")),
(OWNER, _("Only editable with secret edit link")),
(ANONYMOUS, _("Everyone can edit")),
)
uuid = models.UUIDField(unique=True, primary_key=True, editable=False)
old_id = models.IntegerField(null=True, blank=True)
map = models.ForeignKey(Map, on_delete=models.CASCADE)
Expand Down
14 changes: 13 additions & 1 deletion umap/static/umap/js/modules/permissions.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@ export class MapPermissions extends ServerStored {
selectOptions: this._umap.properties.edit_statuses,
},
])
fields.push([
'properties.share_status',
{
handler: 'IntSelect',
label: translate('Who can view'),
selectOptions: this._umap.properties.share_statuses,
},
])
const builder = new U.FormBuilder(this, fields)
const form = builder.build()
container.appendChild(form)
Expand Down Expand Up @@ -184,11 +192,11 @@ export class MapPermissions extends ServerStored {
}
if (this.isOwner() || this.isAnonymousMap()) {
formData.append('edit_status', this.properties.edit_status)
formData.append('share_status', this.properties.share_status)
}
if (this.isOwner()) {
formData.append('owner', this.properties.owner?.id)
formData.append('team', this.properties.team?.id || '')
formData.append('share_status', this.properties.share_status)
}
const [data, response, error] = await this._umap.server.post(
this.getUrl(),
Expand Down Expand Up @@ -228,6 +236,10 @@ export class MapPermissions extends ServerStored {
]
}
}

isDraft() {
return this.properties.share_status === 0
}
}

export class DataLayerPermissions extends ServerStored {
Expand Down
5 changes: 4 additions & 1 deletion umap/static/umap/js/modules/ui/bar.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ const TOP_BAR_TEMPLATE = `
<button class="edit-save button round" type="button" data-ref="save">
<i class="icon icon-16 icon-save"></i>
<i class="icon icon-16 icon-save-disabled"></i>
<span class="">${translate('Save')}</span>
<span data-ref="saveLabel">${translate('Save')}</span>
<span data-ref="saveDraftLabel">${translate('Save draft')}</span>
</button>
</div>
</div>`
Expand Down Expand Up @@ -145,6 +146,8 @@ export class TopBar extends WithTemplate {

redraw() {
this.elements.peers.hidden = !this._umap.getProperty('syncEnabled')
this.elements.saveLabel.hidden = this._umap.permissions.isDraft()
this.elements.saveDraftLabel.hidden = !this._umap.permissions.isDraft()
}
}

Expand Down
1 change: 1 addition & 0 deletions umap/static/umap/js/modules/umap.js
Original file line number Diff line number Diff line change
Expand Up @@ -1321,6 +1321,7 @@ export default class Umap extends ServerStored {
})
})
}
this.topBar.redraw()
},
numberOfConnectedPeers: () => {
Utils.eachElement('.connected-peers span', (el) => {
Expand Down
1 change: 1 addition & 0 deletions umap/tests/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ class MapFactory(factory.django.DjangoModelFactory):

licence = factory.SubFactory(LicenceFactory)
owner = factory.SubFactory(UserFactory)
share_status = Map.PUBLIC

@classmethod
def _adjust_kwargs(cls, **kwargs):
Expand Down
26 changes: 17 additions & 9 deletions umap/tests/integration/test_anonymous_owned_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,6 @@ def test_owner_permissions_form(map, datalayer, live_server, owner_session):
edit_permissions = owner_session.get_by_title("Update permissions and editors")
expect(edit_permissions).to_be_visible()
edit_permissions.click()
select = owner_session.locator(".umap-field-share_status select")
expect(select).to_be_hidden()
owner_field = owner_session.locator(".umap-field-owner")
expect(owner_field).to_be_hidden()
editors_field = owner_session.locator(".umap-field-editors input")
Expand All @@ -92,8 +90,15 @@ def test_owner_permissions_form(map, datalayer, live_server, owner_session):
".datalayer-permissions select[name='edit_status'] option:checked"
)
expect(option).to_have_text("Inherit")
# Those fields should not be present in anonymous maps
expect(owner_session.locator(".umap-field-share_status select")).to_be_hidden()
expect(owner_session.locator(".umap-field-share_status select")).to_be_visible()
options = [
int(option.get_attribute("value"))
for option in owner_session.locator(
".umap-field-share_status select option"
).all()
]
assert options == [Map.DRAFT, Map.PUBLIC]
# This field should not be present in anonymous maps
expect(owner_session.locator(".umap-field-owner")).to_be_hidden()


Expand Down Expand Up @@ -135,15 +140,15 @@ def test_can_change_perms_after_create(tilelayer, live_server, page):
page.get_by_title("Manage layers").click()
page.get_by_title("Add a layer").click()
page.locator("input[name=name]").fill("Layer 1")
save = page.get_by_role("button", name="Save")
expect(save).to_be_visible()
expect(
page.get_by_role("button", name="Visibility: Draft (private)")
).to_be_visible()
expect(page.get_by_role("button", name="Save", exact=True)).to_be_hidden()
with page.expect_response(re.compile(r".*/datalayer/create/.*")):
save.click()
page.get_by_role("button", name="Save draft", exact=True).click()
edit_permissions = page.get_by_title("Update permissions and editors")
expect(edit_permissions).to_be_visible()
edit_permissions.click()
select = page.locator(".umap-field-share_status select")
expect(select).to_be_hidden()
owner_field = page.locator(".umap-field-owner")
expect(owner_field).to_be_hidden()
editors_field = page.locator(".umap-field-editors input")
Expand All @@ -157,6 +162,9 @@ def test_can_change_perms_after_create(tilelayer, live_server, page):
)
expect(option).to_have_text("Inherit")
expect(page.get_by_label("Secret edit link:")).to_be_visible()
page.locator('select[name="share_status"]').select_option("1")
expect(page.get_by_role("button", name="Save draft", exact=True)).to_be_hidden()
expect(page.get_by_role("button", name="Save", exact=True)).to_be_visible()


def test_alert_message_after_create(
Expand Down
36 changes: 21 additions & 15 deletions umap/tests/integration/test_owned_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,12 @@ def test_owner_permissions_form(map, datalayer, live_server, login):
edit_permissions = page.get_by_title("Update permissions and editors")
expect(edit_permissions).to_be_visible()
edit_permissions.click()
select = page.locator(".umap-field-share_status select")
expect(select).to_be_visible()
expect(page.locator(".umap-field-share_status select")).to_be_visible()
options = [
int(option.get_attribute("value"))
for option in page.locator(".umap-field-share_status select option").all()
]
assert options == [Map.DRAFT, Map.PUBLIC, Map.OPEN, Map.PRIVATE]
# expect(select).to_have_value(Map.PUBLIC) # Does not work
owner_field = page.locator(".umap-field-owner")
expect(owner_field).to_be_visible()
Expand Down Expand Up @@ -181,29 +185,31 @@ def test_can_change_perms_after_create(tilelayer, live_server, login, user):
page.get_by_title("Manage layers").click()
page.get_by_title("Add a layer").click()
page.locator("input[name=name]").fill("Layer 1")
save = page.get_by_role("button", name="Save")
expect(save).to_be_visible()
expect(
page.get_by_role("button", name="Visibility: Draft (private)")
).to_be_visible()
expect(page.get_by_role("button", name="Save", exact=True)).to_be_hidden()
with page.expect_response(re.compile(r".*/map/create/")):
save.click()
page.get_by_role("button", name="Save draft", exact=True).click()
edit_permissions = page.get_by_title("Update permissions and editors")
expect(edit_permissions).to_be_visible()
edit_permissions.click()
select = page.locator(".umap-field-share_status select")
expect(select).to_be_visible()
option = page.locator("select[name='share_status'] option:checked")
expect(option).to_have_text("Everyone (public)")
owner_field = page.locator(".umap-field-owner")
expect(owner_field).to_be_visible()
editors_field = page.locator(".umap-field-editors input")
expect(editors_field).to_be_visible()
datalayer_label = page.get_by_text('Who can edit "Layer 1"')
expect(datalayer_label).to_be_visible()
expect(page.locator(".umap-field-share_status select")).to_be_visible()
expect(page.locator("select[name='share_status'] option:checked")).to_have_text(
"Draft (private)"
)
expect(page.locator(".umap-field-owner")).to_be_visible()
expect(page.locator(".umap-field-editors input")).to_be_visible()
expect(page.get_by_text('Who can edit "Layer 1"')).to_be_visible()
options = page.locator(".datalayer-permissions select[name='edit_status'] option")
expect(options).to_have_count(4)
option = page.locator(
".datalayer-permissions select[name='edit_status'] option:checked"
)
expect(option).to_have_text("Inherit")
page.locator('select[name="share_status"]').select_option("1")
expect(page.get_by_role("button", name="Save draft", exact=True)).to_be_hidden()
expect(page.get_by_role("button", name="Save", exact=True)).to_be_visible()


def test_can_change_owner(map, live_server, login, user):
Expand Down
8 changes: 5 additions & 3 deletions umap/tests/test_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from django.urls import reverse

from umap.models import Map
from umap.forms import DEFAULT_CENTER

from .base import MapFactory

Expand Down Expand Up @@ -160,8 +161,9 @@ def test_can_change_default_edit_status(user, settings):


def test_can_change_default_share_status(user, settings):
map = Map.objects.create(owner=user, center=DEFAULT_CENTER)
assert map.share_status == Map.DRAFT
settings.UMAP_DEFAULT_SHARE_STATUS = Map.PUBLIC
map = Map.objects.create(owner=user, center=DEFAULT_CENTER)
map = MapFactory(owner=user)
assert map.share_status == Map.PUBLIC
settings.UMAP_DEFAULT_SHARE_STATUS = Map.PRIVATE
map = MapFactory(owner=user)
assert map.share_status == Map.PRIVATE
Loading

0 comments on commit 955b1d5

Please sign in to comment.