Projet

Général

Profil

0003-maps-add-tiles-layer-22639.patch

Lauréline Guérin, 18 février 2020 14:32

Télécharger (25 ko)

Voir les différences:

Subject: [PATCH 3/5] maps: add tiles layer (#22639)

 combo/apps/maps/forms.py                      |  56 ++++---
 combo/apps/maps/manager_views.py              |  11 +-
 .../maps/migrations/0009_map_layer_kind.py    |  16 +-
 combo/apps/maps/models.py                     |  36 ++++-
 .../templates/maps/layer_options_form.html    |   4 +-
 .../maps/templates/maps/manager_home.html     |   7 +-
 .../maps/templates/maps/map_cell_form.html    |  15 +-
 combo/apps/maps/urls.py                       |   4 +-
 tests/test_maps_manager.py                    | 153 +++++++++++++++---
 9 files changed, 239 insertions(+), 63 deletions(-)
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 © <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
-