0003-maps-add-tiles-layer-22639.patch
combo/apps/maps/forms.py | ||
---|---|---|
27 | 27 |
option_template_name = 'maps/icon_radio_option.html' |
28 | 28 | |
29 | 29 | |
30 |
class MapNewLayerForm(forms.ModelForm):
|
|
30 |
class MapLayerForm(forms.ModelForm): |
|
31 | 31 |
geojson_url = TemplatableURLField(label=_('Geojson URL')) |
32 | 32 | |
33 | 33 |
class Meta: |
34 | 34 |
model = MapLayer |
35 |
exclude = ('slug', 'cache_duration', 'include_user_identifier') |
|
36 |
widgets = {'marker_colour': forms.TextInput(attrs={'type': 'color'}), |
|
37 |
'icon_colour': forms.TextInput(attrs={'type': 'color'}), |
|
38 |
} |
|
35 |
exclude = ('kind',) |
|
36 |
widgets = { |
|
37 |
'marker_colour': forms.TextInput(attrs={'type': 'color'}), |
|
38 |
'icon_colour': forms.TextInput(attrs={'type': 'color'}), |
|
39 |
} |
|
39 | 40 | |
40 | 41 |
def __init__(self, *args, **kwargs): |
41 |
super(MapNewLayerForm, self).__init__(*args, **kwargs) |
|
42 |
super(MapLayerForm, self).__init__(*args, **kwargs) |
|
43 |
if self.instance.pk is None: |
|
44 |
# new instance, delete some fields |
|
45 |
del self.fields['slug'] |
|
46 |
del self.fields['cache_duration'] |
|
47 |
del self.fields['include_user_identifier'] |
|
48 |
else: |
|
49 |
# new widget for icon field |
|
50 |
self.fields['icon'].widget = IconRadioSelect() |
|
42 | 51 |
self.fields['icon'].choices = list( |
43 | 52 |
sorted(self.fields['icon'].choices, key=lambda x: slugify(force_text(x[1])))) |
53 |
if self.instance.kind == 'geojson': |
|
54 |
todelete_fields = ['tiles_template_url', 'tiles_attribution', 'tiles_default'] |
|
55 |
else: |
|
56 |
todelete_fields = [ |
|
57 |
'geojson_url', 'marker_colour', 'icon', 'icon_colour', 'cache_duration', |
|
58 |
'include_user_identifier', 'properties'] |
|
59 |
for field in todelete_fields: |
|
60 |
if field in self.fields: |
|
61 |
del self.fields[field] |
|
44 | 62 | |
63 |
def clean(self): |
|
64 |
cleaned_data = super(MapLayerForm, self).clean() |
|
45 | 65 | |
46 |
class MapLayerForm(forms.ModelForm): |
|
47 |
geojson_url = TemplatableURLField(label=_('Geojson URL')) |
|
66 |
if self.instance.kind == 'tiles': |
|
67 |
if MapLayer.objects.filter(kind='tiles', tiles_default=True).exclude(pk=self.instance.pk): |
|
68 |
raise forms.ValidationError(_('Only one default tiles layer can be defined.')) |
|
48 | 69 | |
49 |
class Meta: |
|
50 |
model = MapLayer |
|
51 |
fields = '__all__' |
|
52 |
widgets = {'marker_colour': forms.TextInput(attrs={'type': 'color'}), |
|
53 |
'icon_colour': forms.TextInput(attrs={'type': 'color'}), |
|
54 |
'icon': IconRadioSelect(), |
|
55 |
} |
|
56 | ||
57 |
def __init__(self, *args, **kwargs): |
|
58 |
super(MapLayerForm, self).__init__(*args, **kwargs) |
|
59 |
self.fields['icon'].choices = list( |
|
60 |
sorted(self.fields['icon'].choices, key=lambda x: slugify(force_text(x[1])))) |
|
70 |
return cleaned_data |
|
61 | 71 | |
62 | 72 | |
63 | 73 |
class MapLayerOptionsForm(forms.ModelForm): |
... | ... | |
66 | 76 |
fields = ['map_layer'] |
67 | 77 | |
68 | 78 |
def __init__(self, *args, **kwargs): |
79 |
self.kind = kwargs.pop('kind') |
|
69 | 80 |
super(MapLayerOptionsForm, self).__init__(*args, **kwargs) |
70 |
self.fields['map_layer'].queryset = self.instance.map_cell.get_free_layers() |
|
81 |
if self.kind == 'geojson': |
|
82 |
self.fields['map_layer'].queryset = self.instance.map_cell.get_free_geojson_layers() |
|
83 |
else: |
|
84 |
self.fields['map_layer'].queryset = self.instance.map_cell.get_free_tiles_layers() |
combo/apps/maps/manager_views.py | ||
---|---|---|
24 | 24 |
from .models import Map |
25 | 25 |
from .models import MapLayer |
26 | 26 |
from .models import MapLayerOptions |
27 |
from .forms import MapNewLayerForm, MapLayerForm, MapLayerOptionsForm
|
|
27 |
from .forms import MapLayerForm, MapLayerOptionsForm |
|
28 | 28 | |
29 | 29 | |
30 | 30 |
class MapLayerMixin(object): |
... | ... | |
34 | 34 | |
35 | 35 |
class ManagerHomeView(MapLayerMixin, ListView): |
36 | 36 |
template_name = 'maps/manager_home.html' |
37 |
ordering = ['kind', 'label'] |
|
37 | 38 | |
38 | 39 |
def get_context_data(self, **kwargs): |
39 | 40 |
context = super(ManagerHomeView, self).get_context_data(**kwargs) |
... | ... | |
42 | 43 | |
43 | 44 | |
44 | 45 |
class LayerAddView(MapLayerMixin, CreateView): |
45 |
form_class = MapNewLayerForm
|
|
46 |
form_class = MapLayerForm |
|
46 | 47 |
template_name = 'maps/map_layer_form.html' |
47 | 48 | |
49 |
def get_form_kwargs(self): |
|
50 |
kwargs = super(LayerAddView, self).get_form_kwargs() |
|
51 |
kwargs['instance'] = self.model(kind=self.kwargs['kind']) |
|
52 |
return kwargs |
|
53 | ||
48 | 54 | |
49 | 55 |
class LayerEditView(MapLayerMixin, UpdateView): |
50 | 56 |
form_class = MapLayerForm |
... | ... | |
69 | 75 |
def get_form_kwargs(self): |
70 | 76 |
kwargs = super(MapCellAddLayer, self).get_form_kwargs() |
71 | 77 |
kwargs['instance'] = MapLayerOptions(map_cell=self.cell) |
78 |
kwargs['kind'] = self.kwargs['kind'] |
|
72 | 79 |
return kwargs |
73 | 80 | |
74 | 81 |
def form_valid(self, form): |
combo/apps/maps/migrations/0009_map_layer_kind.py | ||
---|---|---|
20 | 20 |
migrations.AddField( |
21 | 21 |
model_name='maplayer', |
22 | 22 |
name='tiles_attribution', |
23 |
field=models.CharField(blank=True, max_length=1024, null=True, verbose_name='Attribution'), |
|
23 |
field=models.CharField( |
|
24 |
blank=True, |
|
25 |
help_text=( |
|
26 |
'For example: Map data &copy; <a href="https://openstreetmap.org">OpenStreetMap</a> contributors, ' |
|
27 |
'<a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>'), |
|
28 |
max_length=1024, |
|
29 |
null=True, |
|
30 |
verbose_name='Attribution'), |
|
24 | 31 |
), |
25 | 32 |
migrations.AddField( |
26 | 33 |
model_name='maplayer', |
... | ... | |
30 | 37 |
migrations.AddField( |
31 | 38 |
model_name='maplayer', |
32 | 39 |
name='tiles_template_url', |
33 |
field=models.CharField(blank=True, max_length=1024, null=True, verbose_name='Tiles URL'), |
|
40 |
field=models.CharField( |
|
41 |
blank=True, |
|
42 |
help_text='For example: https://tiles.entrouvert.org/hdm/{z}/{x}/{y}.png', |
|
43 |
max_length=1024, |
|
44 |
null=True, |
|
45 |
verbose_name='Tiles URL'), |
|
34 | 46 |
), |
35 | 47 |
] |
combo/apps/maps/models.py | ||
---|---|---|
20 | 20 |
from django.db import models |
21 | 21 |
from django.utils import six |
22 | 22 |
from django.utils.encoding import python_2_unicode_compatible |
23 |
from django.utils.html import escape |
|
23 | 24 |
from django.utils.text import slugify |
24 | 25 |
from django.utils.translation import ugettext_lazy as _ |
25 | 26 |
from django.core.urlresolvers import reverse_lazy |
... | ... | |
33 | 34 |
from combo.utils import requests, get_templated_url |
34 | 35 | |
35 | 36 | |
37 |
KIND = [ |
|
38 |
('tiles', _('Tiles')), |
|
39 |
('geojson', _('GeoJSON')), |
|
40 |
] |
|
41 | ||
36 | 42 |
ICONS = [ |
37 | 43 |
('ambulance', _('Ambulance')), |
38 | 44 |
('asterisk', _('Asterisk')), |
... | ... | |
96 | 102 | |
97 | 103 |
label = models.CharField(_('Label'), max_length=128) |
98 | 104 |
slug = models.SlugField(_('Identifier')) |
105 | ||
106 |
kind = models.CharField(max_length=10, choices=KIND, default='geojson') |
|
107 | ||
108 |
tiles_template_url = models.CharField( |
|
109 |
_('Tiles URL'), |
|
110 |
max_length=1024, |
|
111 |
help_text=_('For example: %s') % settings.COMBO_MAP_TILE_URLTEMPLATE, |
|
112 |
blank=True, null=True) |
|
113 |
tiles_attribution = models.CharField( |
|
114 |
_('Attribution'), |
|
115 |
max_length=1024, |
|
116 |
help_text=_('For example: %s') % escape(settings.COMBO_MAP_ATTRIBUTION), |
|
117 |
blank=True, null=True) |
|
118 |
tiles_default = models.BooleanField(_('Default tiles layer'), default=False) |
|
119 | ||
99 | 120 |
geojson_url = models.CharField(_('Geojson URL'), max_length=1024) |
100 | 121 |
marker_colour = models.CharField(_('Marker colour'), max_length=7, default='#0000FF') |
101 | 122 |
icon = models.CharField(_('Marker icon'), max_length=32, blank=True, null=True, |
... | ... | |
298 | 319 | |
299 | 320 |
def get_geojson(self, request): |
300 | 321 |
geojson = {'type': 'FeatureCollection', 'features': []} |
301 |
layers = self.layers.all()
|
|
322 |
layers = self.layers.filter(kind='geojson')
|
|
302 | 323 |
for layer in layers: |
303 | 324 |
geojson['features'] += layer.get_geojson(request, |
304 | 325 |
multiple_layers=bool(len(layers) > 1)) |
... | ... | |
326 | 347 |
ctx['marker_behaviour_onclick'] = self.marker_behaviour_onclick |
327 | 348 |
return ctx |
328 | 349 | |
329 |
def get_free_layers(self): |
|
330 |
used_layers = MapLayerOptions.objects.filter(map_cell=self).values('map_layer') |
|
331 |
return MapLayer.objects.exclude(pk__in=used_layers) |
|
350 |
def get_maplayer_options(self): |
|
351 |
return self.maplayeroptions_set.order_by('map_layer__kind', 'map_layer__label') |
|
352 | ||
353 |
def get_free_geojson_layers(self): |
|
354 |
used_layers = self.maplayeroptions_set.values('map_layer') |
|
355 |
return MapLayer.objects.filter(kind='geojson').exclude(pk__in=used_layers) |
|
356 | ||
357 |
def get_free_tiles_layers(self): |
|
358 |
used_layers = self.maplayeroptions_set.values('map_layer') |
|
359 |
return MapLayer.objects.filter(kind='tiles').exclude(pk__in=used_layers) |
|
332 | 360 | |
333 | 361 |
def export_subobjects(self): |
334 | 362 |
return {'layers': [x.get_as_serialized_object() for x in MapLayerOptions.objects.filter(map_cell=self)]} |
combo/apps/maps/templates/maps/layer_options_form.html | ||
---|---|---|
3 | 3 | |
4 | 4 |
{% block appbar %} |
5 | 5 |
{% if form.instance.pk %} |
6 |
<h2>{% trans "Edit layer" %}</h2>
|
|
6 |
<h2>{% if form.kind == 'geojson' %}{% trans "Edit GeoJSON layer" %}{% else %}{% trans "Edit tiles layer" %}{% endif %}</h2>
|
|
7 | 7 |
{% else %} |
8 |
<h2>{% trans "New layer" %}</h2>
|
|
8 |
<h2>{% if form.kind == 'geojson' %}{% trans "New GeoJSON layer" %}{% else %}{% trans "New tiles layer" %}{% endif %}</h2>
|
|
9 | 9 |
{% endif %} |
10 | 10 |
{% endblock %} |
11 | 11 |
combo/apps/maps/templates/maps/manager_home.html | ||
---|---|---|
4 | 4 |
{% block appbar %} |
5 | 5 |
<h2>{% trans 'Maps' %}</h2> |
6 | 6 |
<span class="actions"> |
7 |
<a rel="popup" href="{% url 'maps-manager-layer-add' %}">{% trans 'New' %}</a> |
|
7 |
<a rel="popup" href="{% url 'maps-manager-layer-add' kind='geojson' %}">{% trans 'New GeoJSON layer' %}</a> |
|
8 |
<a rel="popup" href="{% url 'maps-manager-layer-add' kind='tiles' %}">{% trans 'New tiles layer' %}</a> |
|
8 | 9 |
</span> |
9 | 10 |
{% endblock %} |
10 | 11 | |
... | ... | |
13 | 14 |
<ul class="objects-list single-links layers"> |
14 | 15 |
{% for layer in object_list %} |
15 | 16 |
<li> |
16 |
<a class="layer-icon-{{ layer.icon }}" href="{% url 'maps-manager-layer-edit' slug=layer.slug %}">{{ layer.label }}</a>
|
|
17 |
<a rel="popup" class="delete" href="{% url 'maps-manager-layer-delete' slug=layer.slug %}">{% trans "remove" %}</a> |
|
17 |
<a class="layer-icon-{{ layer.icon }}" href="{% url 'maps-manager-layer-edit' slug=layer.slug %}">{{ layer.label }} {% if layer.kind == 'tiles' %}({{ layer.get_kind_display }}{% if layer.tiles_default %}{% trans "default layer" %}{% endif %}){% endif %}</a>
|
|
18 |
<a rel="popup" class="delete" href="{% url 'maps-manager-layer-delete' slug=layer.slug %}">{% trans "remove" %}</a>
|
|
18 | 19 |
</li> |
19 | 20 |
{% endfor %} |
20 | 21 |
</ul> |
combo/apps/maps/templates/maps/map_cell_form.html | ||
---|---|---|
3 | 3 | |
4 | 4 |
{% block cell-form %} |
5 | 5 |
{{ form.as_p }} |
6 |
{% with cell.maplayeroptions_set.all as options %}
|
|
6 |
{% with cell.get_maplayer_options as options %}
|
|
7 | 7 |
{% if options %} |
8 | 8 |
<p><label>{% trans "Layers:" %}</label></p> |
9 | 9 |
<div> |
10 | 10 |
<ul class="objects-list list-of-layers"> |
11 | 11 |
{% for option in options %} |
12 | 12 |
<li> |
13 |
<span>{{ option.map_layer }}</span>
|
|
13 |
<span>{{ option.map_layer.label }} {% if option.map_layer.kind == 'tiles' %}({{ option.map_layer.get_kind_display }}){% endif %}</span>
|
|
14 | 14 |
<a rel="popup" title="{% trans "Delete" %}" class="link-action-icon delete" href="{% url 'maps-manager-cell-delete-layer' page_pk=page.pk cell_reference=cell.get_reference layeroptions_pk=option.pk %}">{% trans "Delete" %}</a> |
15 | 15 |
</li> |
16 | 16 |
{% endfor %} |
... | ... | |
18 | 18 |
</div> |
19 | 19 |
{% endif %} |
20 | 20 |
{% endwith %} |
21 |
{% if cell.get_free_layers.exists %} |
|
21 |
{% with cell.get_free_geojson_layers.exists as free_geojson and cell.get_free_tiles_layers.exists as free_tiles %} |
|
22 |
{% if free_geojson or free_tiles %} |
|
22 | 23 |
<div class="buttons"> |
23 |
<a rel="popup" href="{% url 'maps-manager-cell-add-layer' page_pk=page.pk cell_reference=cell.get_reference %}">{% trans "Add a layer" %}</a> |
|
24 |
{% if free_geojson %} |
|
25 |
<a rel="popup" href="{% url 'maps-manager-cell-add-layer' page_pk=page.pk cell_reference=cell.get_reference kind='geojson' %}">{% trans "Add a GeoJSON layer" %}</a> |
|
26 |
{% endif %} |
|
27 |
{% if free_tiles %} |
|
28 |
{% if free_geojson %}|{% endif%} <a rel="popup" href="{% url 'maps-manager-cell-add-layer' page_pk=page.pk cell_reference=cell.get_reference kind='tiles' %}">{% trans "Add a tiles layer" %}</a> |
|
29 |
{% endif %} |
|
24 | 30 |
</div> |
25 | 31 |
{% endif %} |
32 |
{% endwith %} |
|
26 | 33 |
{% endblock %} |
combo/apps/maps/urls.py | ||
---|---|---|
24 | 24 | |
25 | 25 |
maps_manager_urls = [ |
26 | 26 |
url('^$', manager_views.ManagerHomeView.as_view(), name='maps-manager-homepage'), |
27 |
url('^layers/add/$', manager_views.LayerAddView.as_view(), name='maps-manager-layer-add'), |
|
27 |
url('^layers/add/(?P<kind>geojson|tiles)/$', manager_views.LayerAddView.as_view(), name='maps-manager-layer-add'),
|
|
28 | 28 |
url(r'^layers/(?P<slug>[\w-]+)/edit/$', manager_views.LayerEditView.as_view(), |
29 | 29 |
name='maps-manager-layer-edit'), |
30 | 30 |
url(r'^layers/(?P<slug>[\w-]+)/delete/$', manager_views.LayerDeleteView.as_view(), |
31 | 31 |
name='maps-manager-layer-delete'), |
32 |
url(r'^pages/(?P<page_pk>\d+)/cell/(?P<cell_reference>[\w_-]+)/add-layer/$', |
|
32 |
url(r'^pages/(?P<page_pk>\d+)/cell/(?P<cell_reference>[\w_-]+)/add-layer/(?P<kind>geojson|tiles)/$',
|
|
33 | 33 |
manager_views.map_cell_add_layer, |
34 | 34 |
name='maps-manager-cell-add-layer'), |
35 | 35 |
url(r'^pages/(?P<page_pk>\d+)/cell/(?P<cell_reference>[\w_-]+)/layer/(?P<layeroptions_pk>\d+)/delete/$', |
tests/test_maps_manager.py | ||
---|---|---|
11 | 11 |
pytestmark = pytest.mark.django_db |
12 | 12 | |
13 | 13 | |
14 |
@pytest.fixture |
|
15 |
def layer(): |
|
16 |
return MapLayer.objects.create( |
|
17 |
label='Test', |
|
18 |
kind='geojson', |
|
19 |
geojson_url='http://example.org/geojson', |
|
20 |
icon='bicycle', |
|
21 |
marker_colour='#FFFFFF', |
|
22 |
icon_colour='#FFFFFF', |
|
23 |
) |
|
24 | ||
25 | ||
26 |
@pytest.fixture |
|
27 |
def tiles_layer(): |
|
28 |
return MapLayer.objects.create( |
|
29 |
label='Test2', |
|
30 |
kind='tiles', |
|
31 |
tiles_template_url='http://somedomain.com/blabla/{z}/{x}/{y}{r}.png', |
|
32 |
tiles_attribution='Foo bar', |
|
33 |
tiles_default=True, |
|
34 |
) |
|
35 | ||
36 | ||
14 | 37 |
def login(app, username='admin', password='admin'): |
15 | 38 |
login_page = app.get('/login/') |
16 | 39 |
login_form = login_page.forms[0] |
... | ... | |
20 | 43 |
assert resp.status_int == 302 |
21 | 44 |
return app |
22 | 45 | |
46 | ||
23 | 47 |
def test_access(app, admin_user): |
24 | 48 |
app = login(app) |
25 | 49 |
resp = app.get('/manage/', status=200) |
26 | 50 |
assert '/manage/maps/' in resp.text |
27 | 51 | |
28 |
def test_add_layer(app, admin_user): |
|
29 |
MapLayer.objects.all().delete() |
|
52 | ||
53 |
def test_add_geojson_layer(app, admin_user): |
|
30 | 54 |
app = login(app) |
31 | 55 |
resp = app.get('/manage/maps/', status=200) |
32 |
resp = resp.click('New') |
|
56 |
resp = resp.click('New GeoJSON layer') |
|
57 |
assert 'slug' not in resp.context['form'] |
|
58 |
assert 'cache_duration' not in resp.context['form'] |
|
59 |
assert 'include_user_identifier' not in resp.context['form'] |
|
60 |
assert 'tiles_template_url' not in resp.context['form'] |
|
61 |
assert 'tiles_attribution' not in resp.context['form'] |
|
62 |
assert 'tiles_default' not in resp.context['form'] |
|
33 | 63 |
resp.forms[0]['label'] = 'Test' |
34 | 64 |
resp.forms[0]['geojson_url'] = 'http://example.net/geojson' |
35 | 65 |
assert resp.form['marker_colour'].value == '#0000FF' |
... | ... | |
43 | 73 |
layer = MapLayer.objects.get() |
44 | 74 |
assert layer.label == 'Test' |
45 | 75 |
assert layer.slug == 'test' |
76 |
assert layer.kind == 'geojson' |
|
77 | ||
78 | ||
79 |
def test_add_tiles_layer(app, admin_user): |
|
80 |
app = login(app) |
|
81 |
resp = app.get('/manage/maps/', status=200) |
|
82 |
resp = resp.click('New tiles layer') |
|
83 |
assert 'slug' not in resp.context['form'] |
|
84 |
assert 'cache_duration' not in resp.context['form'] |
|
85 |
assert 'include_user_identifier' not in resp.context['form'] |
|
86 |
assert 'geojson_url' not in resp.context['form'] |
|
87 |
assert 'marker_colour' not in resp.context['form'] |
|
88 |
assert 'icon' not in resp.context['form'] |
|
89 |
assert 'icon_colour' not in resp.context['form'] |
|
90 |
assert 'properties' not in resp.context['form'] |
|
91 |
resp.forms[0]['label'] = 'Test' |
|
92 |
resp.forms[0]['tiles_template_url'] = 'http://somedomain.com/blabla/{z}/{x}/{y}{r}.png' |
|
93 |
resp.forms[0]['tiles_attribution'] = 'Foo bar' |
|
94 |
resp.forms[0]['tiles_default'] = True |
|
95 |
resp = resp.forms[0].submit() |
|
96 |
assert resp.location.endswith('/manage/maps/') |
|
97 |
assert MapLayer.objects.count() == 1 |
|
98 |
layer = MapLayer.objects.get() |
|
99 |
assert layer.label == 'Test' |
|
100 |
assert layer.slug == 'test' |
|
101 |
assert layer.kind == 'tiles' |
|
102 |
assert layer.tiles_default is True |
|
46 | 103 | |
47 |
def test_edit_layer(app, admin_user): |
|
48 |
test_add_layer(app, admin_user) |
|
104 |
# only one default layer |
|
105 |
resp = app.get('/manage/maps/', status=200) |
|
106 |
resp = resp.click('New tiles layer') |
|
107 |
resp.forms[0]['label'] = 'Test2' |
|
108 |
resp.forms[0]['tiles_template_url'] = 'http://somedomain.com/blabla/{z}/{x}/{y}{r}.png' |
|
109 |
resp.forms[0]['tiles_attribution'] = 'Foo bar' |
|
110 |
resp.forms[0]['tiles_default'] = True |
|
111 |
resp = resp.forms[0].submit() |
|
112 |
assert '<li>Only one default tiles layer can be defined.</li>' in resp.text |
|
113 | ||
114 | ||
115 |
def test_edit_geojson_layer(app, admin_user, layer): |
|
49 | 116 |
app = login(app) |
50 | 117 |
resp = app.get('/manage/maps/', status=200) |
51 | 118 |
resp = resp.click('Test') |
119 |
assert 'tiles_template_url' not in resp.context['form'] |
|
120 |
assert 'tiles_attribution' not in resp.context['form'] |
|
121 |
assert 'tiles_default' not in resp.context['form'] |
|
52 | 122 |
assert '<li><span class="icon-ambulance"><label' in resp.text |
53 | 123 |
resp.forms[0]['geojson_url'] = 'http://example.net/new_geojson' |
54 | 124 |
resp = resp.forms[0].submit() |
55 | 125 |
assert resp.location.endswith('/manage/maps/') |
56 |
assert MapLayer.objects.count() == 1 |
|
57 |
layer = MapLayer.objects.get() |
|
126 |
layer.refresh_from_db() |
|
58 | 127 |
assert layer.geojson_url == 'http://example.net/new_geojson' |
59 | 128 | |
60 |
def test_delete_layer(app, admin_user): |
|
61 |
test_add_layer(app, admin_user) |
|
129 | ||
130 |
def test_edit_tiles_layer(app, admin_user, tiles_layer): |
|
131 |
app = login(app) |
|
132 |
resp = app.get('/manage/maps/', status=200) |
|
133 |
resp = resp.click('Test') |
|
134 |
assert 'cache_duration' not in resp.context['form'] |
|
135 |
assert 'include_user_identifier' not in resp.context['form'] |
|
136 |
assert 'geojson_url' not in resp.context['form'] |
|
137 |
assert 'marker_colour' not in resp.context['form'] |
|
138 |
assert 'icon' not in resp.context['form'] |
|
139 |
assert 'icon_colour' not in resp.context['form'] |
|
140 |
assert 'properties' not in resp.context['form'] |
|
141 |
resp.forms[0]['tiles_default'] = False |
|
142 |
resp = resp.forms[0].submit() |
|
143 |
assert resp.location.endswith('/manage/maps/') |
|
144 |
tiles_layer.refresh_from_db() |
|
145 |
assert tiles_layer.tiles_default is False |
|
146 | ||
147 | ||
148 |
def test_delete_layer(app, admin_user, layer): |
|
62 | 149 |
app = login(app) |
63 | 150 |
resp = app.get('/manage/maps/', status=200) |
64 | 151 |
resp = resp.click('remove') |
... | ... | |
68 | 155 |
assert MapLayer.objects.count() == 0 |
69 | 156 | |
70 | 157 | |
71 |
def test_list_layers(app, admin_user): |
|
158 |
def test_list_layers(app, admin_user, layer):
|
|
72 | 159 |
page = Page.objects.create(title='One', slug='one', template_name='standard') |
73 | 160 |
map1 = Map.objects.create(page=page, placeholder='map 1', order=0) |
74 | 161 |
map2 = Map.objects.create(page=page, placeholder='map 2', order=1) |
75 | 162 | |
76 |
test_add_layer(app, admin_user) |
|
77 | 163 |
app = login(app) |
78 | 164 |
resp = app.get('/manage/maps/', status=200) |
79 | 165 |
assert '/manage/pages/{}/#cell-{}'.format(page.pk, map1.get_reference()) in resp.text |
... | ... | |
81 | 167 | |
82 | 168 | |
83 | 169 |
@mock.patch('combo.apps.maps.models.requests.get') |
84 |
def test_download_geojson(mock_request, app, admin_user): |
|
85 |
test_add_layer(app, admin_user) |
|
86 |
layer = MapLayer.objects.get() |
|
170 |
def test_download_geojson(mock_request, app, admin_user, layer): |
|
87 | 171 |
mocked_response = mock.Mock() |
88 | 172 |
mock_request.GET = {} |
89 | 173 |
mocked_response.json.return_value = [{'type': 'Feature', |
... | ... | |
125 | 209 |
assert item['properties']['layer']['icon_colour'] == '#FFFFFF' |
126 | 210 | |
127 | 211 | |
128 |
def test_add_delete_layer(app, admin_user): |
|
129 |
layer = MapLayer.objects.create( |
|
130 |
label='bicycles', |
|
131 |
geojson_url='http://example.org/geojson', |
|
132 |
) |
|
212 |
def test_add_delete_layer(app, admin_user, layer, tiles_layer): |
|
133 | 213 |
page = Page.objects.create(title='One', slug='one', template_name='standard') |
134 | 214 |
cell = Map.objects.create(page=page, placeholder='content', order=0, public=True, title='Map') |
135 | 215 |
app = login(app) |
136 | 216 |
resp = app.get('/manage/pages/%s/' % page.pk) |
137 | 217 | |
138 |
assert list(cell.get_free_layers()) == [layer] |
|
139 |
resp = resp.click(href='.*/add-layer/$') |
|
218 |
assert list(cell.get_free_geojson_layers()) == [layer] |
|
219 |
assert list(cell.get_free_tiles_layers()) == [tiles_layer] |
|
220 |
resp = resp.click(href='.*/add-layer/geojson/$') |
|
221 |
assert list(resp.context['form'].fields['map_layer'].queryset) == [layer] |
|
140 | 222 |
resp.forms[0]['map_layer'] = layer.pk |
141 | 223 |
resp = resp.forms[0].submit() |
142 | 224 |
assert resp.status_int == 302 |
... | ... | |
147 | 229 |
assert options.map_layer == layer |
148 | 230 | |
149 | 231 |
resp = resp.follow() |
150 |
assert list(cell.get_free_layers()) == [] |
|
151 |
assert '/add-layer/$' not in resp.text |
|
232 |
assert list(cell.get_free_geojson_layers()) == [] |
|
233 |
assert list(cell.get_free_tiles_layers()) == [tiles_layer] |
|
234 |
assert '/add-layer/geojson/' not in resp.text |
|
235 |
resp = resp.click(href='.*/layer/%s/delete/$' % options.pk) |
|
236 |
resp = resp.forms[0].submit() |
|
237 |
assert resp.status_int == 302 |
|
238 |
assert resp.location.endswith('/manage/pages/%s/#cell-%s' % (page.pk, cell.get_reference())) |
|
239 |
assert MapLayerOptions.objects.count() == 0 |
|
240 | ||
241 |
resp = resp.follow() |
|
242 |
assert list(cell.get_free_geojson_layers()) == [layer] |
|
243 |
assert list(cell.get_free_tiles_layers()) == [tiles_layer] |
|
244 |
resp = resp.click(href='.*/add-layer/tiles/$') |
|
245 |
assert list(resp.context['form'].fields['map_layer'].queryset) == [tiles_layer] |
|
246 |
resp.forms[0]['map_layer'] = tiles_layer.pk |
|
247 |
resp = resp.forms[0].submit() |
|
248 |
assert resp.status_int == 302 |
|
249 |
assert resp.location.endswith('/manage/pages/%s/#cell-%s' % (page.pk, cell.get_reference())) |
|
250 |
assert MapLayerOptions.objects.count() == 1 |
|
251 |
options = MapLayerOptions.objects.get() |
|
252 |
assert options.map_cell == cell |
|
253 |
assert options.map_layer == tiles_layer |
|
254 | ||
255 |
resp = resp.follow() |
|
256 |
assert list(cell.get_free_geojson_layers()) == [layer] |
|
257 |
assert list(cell.get_free_tiles_layers()) == [] |
|
258 |
assert '/add-layer/tiles/' not in resp.text |
|
152 | 259 |
resp = resp.click(href='.*/layer/%s/delete/$' % options.pk) |
153 | 260 |
resp = resp.forms[0].submit() |
154 | 261 |
assert resp.status_int == 302 |
155 |
- |