mirror of
https://github.com/umap-project/umap.git
synced 2025-05-17 11:11:49 +02:00
Compare commits
No commits in common. "86a8e17aec1c38ddc737ad83482e67c510c0f76e" and "a7325dcb02f875aa203315545f35e42a69b84037" have entirely different histories.
86a8e17aec
...
a7325dcb02
10 changed files with 16 additions and 141 deletions
|
@ -3,14 +3,13 @@ import * as Utils from './utils.js'
|
||||||
|
|
||||||
const TEMPLATE = `
|
const TEMPLATE = `
|
||||||
<div class="umap-caption">
|
<div class="umap-caption">
|
||||||
<div class="header">
|
<hgroup>
|
||||||
<i class="icon icon-16 icon-caption icon-block"></i>
|
<h3>
|
||||||
<hgroup>
|
<i class="icon icon-16 icon-caption icon-block"></i>
|
||||||
<h3><span class="map-name" data-ref="name"></span></h3>
|
<span class="map-name" data-ref="name"></span>
|
||||||
<h4 data-ref="author"></h4>
|
</h3>
|
||||||
<h5 class="dates" data-ref="dates"></h5>
|
<h4 data-ref="author"></h4>
|
||||||
</hgroup>
|
</hgroup>
|
||||||
</div>
|
|
||||||
<div class="umap-map-description text" data-ref="description"></div>
|
<div class="umap-map-description text" data-ref="description"></div>
|
||||||
<div class="datalayer-container" data-ref="datalayersContainer"></div>
|
<div class="datalayer-container" data-ref="datalayersContainer"></div>
|
||||||
<div class="credits-container">
|
<div class="credits-container">
|
||||||
|
@ -66,17 +65,6 @@ export default class Caption extends Utils.WithTemplate {
|
||||||
// Create the legend when the panel is actually on the DOM
|
// Create the legend when the panel is actually on the DOM
|
||||||
this._umap.eachDataLayerReverse((datalayer) => datalayer.renderLegend())
|
this._umap.eachDataLayerReverse((datalayer) => datalayer.renderLegend())
|
||||||
})
|
})
|
||||||
if (this._umap.properties.created_at) {
|
|
||||||
const created_at = translate('Created at {date}', {
|
|
||||||
date: new Date(this._umap.properties.created_at).toLocaleDateString(),
|
|
||||||
})
|
|
||||||
const modified_at = translate('Modified at {date}', {
|
|
||||||
date: new Date(this._umap.properties.modified_at).toLocaleDateString(),
|
|
||||||
})
|
|
||||||
this.elements.dates.innerHTML = `${created_at} - ${modified_at}`
|
|
||||||
} else {
|
|
||||||
this.elements.dates.hidden = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addDataLayer(datalayer, parent) {
|
addDataLayer(datalayer, parent) {
|
||||||
|
|
|
@ -574,12 +574,9 @@ export class DataLayer extends ServerStored {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
del(sync = true) {
|
_delete() {
|
||||||
|
this.isDeleted = true
|
||||||
this.erase()
|
this.erase()
|
||||||
if (sync) {
|
|
||||||
this.isDeleted = true
|
|
||||||
this.sync.delete()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
empty() {
|
empty() {
|
||||||
|
@ -822,7 +819,7 @@ export class DataLayer extends ServerStored {
|
||||||
<i class="icon icon-24 icon-delete"></i>${translate('Delete')}
|
<i class="icon icon-24 icon-delete"></i>${translate('Delete')}
|
||||||
</button>`)
|
</button>`)
|
||||||
deleteButton.addEventListener('click', () => {
|
deleteButton.addEventListener('click', () => {
|
||||||
this.del()
|
this._delete()
|
||||||
this._umap.editPanel.close()
|
this._umap.editPanel.close()
|
||||||
})
|
})
|
||||||
advancedButtons.appendChild(deleteButton)
|
advancedButtons.appendChild(deleteButton)
|
||||||
|
@ -1150,12 +1147,8 @@ export class DataLayer extends ServerStored {
|
||||||
if (this.createdOnServer) {
|
if (this.createdOnServer) {
|
||||||
await this._umap.server.post(this.getDeleteUrl())
|
await this._umap.server.post(this.getDeleteUrl())
|
||||||
}
|
}
|
||||||
this.commitDelete()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
commitDelete() {
|
|
||||||
delete this._umap.datalayers[stamp(this)]
|
delete this._umap.datalayers[stamp(this)]
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
getName() {
|
getName() {
|
||||||
|
@ -1228,7 +1221,7 @@ export class DataLayer extends ServerStored {
|
||||||
this._umap.dialog
|
this._umap.dialog
|
||||||
.confirm(translate('Are you sure you want to delete this layer?'))
|
.confirm(translate('Are you sure you want to delete this layer?'))
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.del()
|
this._delete()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
this
|
this
|
||||||
|
|
|
@ -72,14 +72,6 @@ export class DataLayerUpdater extends BaseUpdater {
|
||||||
}
|
}
|
||||||
datalayer.render([key])
|
datalayer.render([key])
|
||||||
}
|
}
|
||||||
|
|
||||||
delete({ metadata }) {
|
|
||||||
const datalayer = this.getDataLayerFromID(metadata.id)
|
|
||||||
if (datalayer) {
|
|
||||||
datalayer.del(false)
|
|
||||||
datalayer.commitDelete()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class FeatureUpdater extends BaseUpdater {
|
export class FeatureUpdater extends BaseUpdater {
|
||||||
|
|
|
@ -694,14 +694,8 @@ a.umap-control-caption,
|
||||||
.datalayer-name {
|
.datalayer-name {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.umap-caption .dates {
|
.umap-caption .umap-map-author {
|
||||||
color: var(--color-mediumGray);
|
padding-inline-start: 31px;
|
||||||
}
|
|
||||||
.umap-caption .header {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
.umap-caption .header i.icon {
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
}
|
||||||
.umap-browser .main-toolbox {
|
.umap-browser .main-toolbox {
|
||||||
padding-left: 4px; /* Align with toolbox below */
|
padding-left: 4px; /* Align with toolbox below */
|
||||||
|
|
|
@ -127,9 +127,6 @@ class DataLayerFactory(factory.django.DjangoModelFactory):
|
||||||
def _adjust_kwargs(cls, **kwargs):
|
def _adjust_kwargs(cls, **kwargs):
|
||||||
if "data" in kwargs:
|
if "data" in kwargs:
|
||||||
data = copy.deepcopy(kwargs.pop("data"))
|
data = copy.deepcopy(kwargs.pop("data"))
|
||||||
data.setdefault("_umap_options", {})
|
|
||||||
if "name" in data["_umap_options"] and kwargs["name"] == cls.name:
|
|
||||||
kwargs["name"] = data["_umap_options"]["name"]
|
|
||||||
if "settings" not in kwargs:
|
if "settings" not in kwargs:
|
||||||
kwargs["settings"] = data.get("_umap_options", {})
|
kwargs["settings"] = data.get("_umap_options", {})
|
||||||
else:
|
else:
|
||||||
|
@ -138,6 +135,7 @@ class DataLayerFactory(factory.django.DjangoModelFactory):
|
||||||
**DataLayerFactory.settings._defaults,
|
**DataLayerFactory.settings._defaults,
|
||||||
**kwargs["settings"],
|
**kwargs["settings"],
|
||||||
}
|
}
|
||||||
|
data.setdefault("_umap_options", {})
|
||||||
kwargs["settings"]["name"] = kwargs["name"]
|
kwargs["settings"]["name"] = kwargs["name"]
|
||||||
data["_umap_options"]["name"] = kwargs["name"]
|
data["_umap_options"]["name"] = kwargs["name"]
|
||||||
data.setdefault("type", "FeatureCollection")
|
data.setdefault("type", "FeatureCollection")
|
||||||
|
|
|
@ -25,7 +25,6 @@ def test_caption(live_server, page, map):
|
||||||
panel.locator(".caption-item .off").get_by_text(non_loaded.name)
|
panel.locator(".caption-item .off").get_by_text(non_loaded.name)
|
||||||
).to_be_visible()
|
).to_be_visible()
|
||||||
expect(panel.locator(".caption-item").get_by_text(hidden.name)).to_be_hidden()
|
expect(panel.locator(".caption-item").get_by_text(hidden.name)).to_be_hidden()
|
||||||
expect(panel.get_by_text("Created at")).to_be_visible()
|
|
||||||
|
|
||||||
|
|
||||||
def test_caption_should_display_owner_as_author(live_server, page, map):
|
def test_caption_should_display_owner_as_author(live_server, page, map):
|
||||||
|
|
|
@ -420,72 +420,6 @@ def test_should_sync_datalayers(new_page, live_server, websocket_server, tilelay
|
||||||
assert DataLayer.objects.count() == 2
|
assert DataLayer.objects.count() == 2
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.xdist_group(name="websockets")
|
|
||||||
def test_should_sync_datalayers_delete(
|
|
||||||
new_page, live_server, websocket_server, tilelayer
|
|
||||||
):
|
|
||||||
map = MapFactory(name="sync", edit_status=Map.ANONYMOUS)
|
|
||||||
map.settings["properties"]["syncEnabled"] = True
|
|
||||||
map.save()
|
|
||||||
data1 = {
|
|
||||||
"type": "FeatureCollection",
|
|
||||||
"features": [
|
|
||||||
{
|
|
||||||
"type": "Feature",
|
|
||||||
"properties": {
|
|
||||||
"name": "Point 1",
|
|
||||||
},
|
|
||||||
"geometry": {"type": "Point", "coordinates": [0.065918, 48.385442]},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"_umap_options": {
|
|
||||||
"name": "datalayer 1",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
data2 = {
|
|
||||||
"type": "FeatureCollection",
|
|
||||||
"features": [
|
|
||||||
{
|
|
||||||
"type": "Feature",
|
|
||||||
"properties": {
|
|
||||||
"name": "Point 2",
|
|
||||||
},
|
|
||||||
"geometry": {"type": "Point", "coordinates": [3.55957, 49.767074]},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"_umap_options": {
|
|
||||||
"name": "datalayer 2",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
DataLayerFactory(map=map, data=data1)
|
|
||||||
DataLayerFactory(map=map, data=data2)
|
|
||||||
|
|
||||||
# Create two tabs
|
|
||||||
peerA = new_page("Page A")
|
|
||||||
peerA.goto(f"{live_server.url}{map.get_absolute_url()}?edit")
|
|
||||||
peerB = new_page("Page B")
|
|
||||||
peerB.goto(f"{live_server.url}{map.get_absolute_url()}?edit")
|
|
||||||
|
|
||||||
peerA.get_by_role("button", name="Open browser").click()
|
|
||||||
expect(peerA.get_by_text("datalayer 1")).to_be_visible()
|
|
||||||
expect(peerA.get_by_text("datalayer 2")).to_be_visible()
|
|
||||||
peerB.get_by_role("button", name="Open browser").click()
|
|
||||||
expect(peerB.get_by_text("datalayer 1")).to_be_visible()
|
|
||||||
expect(peerB.get_by_text("datalayer 2")).to_be_visible()
|
|
||||||
|
|
||||||
# Delete "datalayer 2" in peerA
|
|
||||||
peerA.locator(".datalayer").get_by_role("button", name="Delete layer").first.click()
|
|
||||||
peerA.get_by_role("button", name="OK").click()
|
|
||||||
expect(peerA.get_by_text("datalayer 2")).to_be_hidden()
|
|
||||||
expect(peerB.get_by_text("datalayer 2")).to_be_hidden()
|
|
||||||
|
|
||||||
# Save delete to the server
|
|
||||||
with peerA.expect_response(re.compile(".*/datalayer/delete/.*")):
|
|
||||||
peerA.get_by_role("button", name="Save").click()
|
|
||||||
expect(peerA.get_by_text("datalayer 2")).to_be_hidden()
|
|
||||||
expect(peerB.get_by_text("datalayer 2")).to_be_hidden()
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.xdist_group(name="websockets")
|
@pytest.mark.xdist_group(name="websockets")
|
||||||
def test_create_and_sync_map(
|
def test_create_and_sync_map(
|
||||||
new_page, live_server, websocket_server, tilelayer, login, user
|
new_page, live_server, websocket_server, tilelayer, login, user
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import tempfile
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
import json
|
import json
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
from datetime import datetime, timedelta
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from unittest import mock
|
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -623,17 +621,3 @@ def test_optimistic_merge_conflicting_change_raises(
|
||||||
modified_datalayer = DataLayer.objects.get(pk=datalayer.pk)
|
modified_datalayer = DataLayer.objects.get(pk=datalayer.pk)
|
||||||
merged_features = json.load(modified_datalayer.geojson)["features"]
|
merged_features = json.load(modified_datalayer.geojson)["features"]
|
||||||
assert merged_features == client1_data["features"]
|
assert merged_features == client1_data["features"]
|
||||||
|
|
||||||
|
|
||||||
def test_saving_datalayer_should_change_map_last_modified(
|
|
||||||
client, datalayer, map, post_data
|
|
||||||
):
|
|
||||||
with mock.patch("django.utils.timezone.now") as mocked:
|
|
||||||
mocked.return_value = datetime.utcnow() - timedelta(days=8)
|
|
||||||
map.save() # Change last_modified to past
|
|
||||||
old_modified_at = map.modified_at.date()
|
|
||||||
url = reverse("datalayer_update", args=(map.pk, datalayer.pk))
|
|
||||||
client.login(username=map.owner.username, password="123123")
|
|
||||||
response = client.post(url, post_data, follow=True)
|
|
||||||
assert response.status_code == 200
|
|
||||||
assert Map.objects.get(pk=map.pk).modified_at.date() != old_modified_at
|
|
||||||
|
|
|
@ -614,13 +614,6 @@ class MapDetailMixin(SessionMixin):
|
||||||
"defaultLabelKeys": settings.UMAP_LABEL_KEYS,
|
"defaultLabelKeys": settings.UMAP_LABEL_KEYS,
|
||||||
}
|
}
|
||||||
created = bool(getattr(self, "object", None))
|
created = bool(getattr(self, "object", None))
|
||||||
if created:
|
|
||||||
properties.update(
|
|
||||||
{
|
|
||||||
"created_at": self.object.created_at,
|
|
||||||
"modified_at": self.object.modified_at,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
if (created and self.object.owner) or (not created and not user.is_anonymous):
|
if (created and self.object.owner) or (not created and not user.is_anonymous):
|
||||||
edit_statuses = Map.EDIT_STATUS
|
edit_statuses = Map.EDIT_STATUS
|
||||||
datalayer_statuses = DataLayer.EDIT_STATUS
|
datalayer_statuses = DataLayer.EDIT_STATUS
|
||||||
|
@ -1300,7 +1293,6 @@ class DataLayerUpdate(FormLessEditMixin, UpdateView):
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
self.object = form.save()
|
self.object = form.save()
|
||||||
self.object.map.save(update_fields=["modified_at"])
|
|
||||||
data = {**self.object.metadata(self.request)}
|
data = {**self.object.metadata(self.request)}
|
||||||
if self.request.session.get("needs_reload"):
|
if self.request.session.get("needs_reload"):
|
||||||
data["geojson"] = json.loads(self.object.geojson.read().decode())
|
data["geojson"] = json.loads(self.object.geojson.read().decode())
|
||||||
|
|
Loading…
Reference in a new issue