Projet

Général

Profil

0001-maps-add-layers-8454.patch

Voir les différences:

Subject: [PATCH 1/2] maps: add layers (#8454)

 combo/apps/maps/__init__.py                        |  34 +++++++
 combo/apps/maps/forms.py                           |  33 ++++++
 combo/apps/maps/manager_views.py                   |  47 +++++++++
 combo/apps/maps/migrations/0001_initial.py         |  24 +++++
 combo/apps/maps/migrations/__init__.py             |   0
 combo/apps/maps/models.py                          |  48 +++++++++
 combo/apps/maps/static/js/jquery.colourpicker.js   | 112 +++++++++++++++++++++
 combo/apps/maps/templates/maps/manager_base.html   |  11 ++
 combo/apps/maps/templates/maps/manager_home.html   |   8 ++
 .../templates/maps/maplayer_confirm_delete.html    |  17 ++++
 combo/apps/maps/templates/maps/maplayer_form.html  |  30 ++++++
 combo/apps/maps/templates/maps/maplayer_list.html  |  33 ++++++
 combo/apps/maps/urls.py                            |  39 +++++++
 combo/apps/maps/views.py                           |  17 ++++
 combo/manager/static/css/combo.manager.css         |  32 ++++++
 combo/manager/static/js/combo.manager.js           |   6 ++
 combo/manager/templates/combo/manager_base.html    |   1 +
 combo/settings.py                                  |   1 +
 tests/test_maps_manager.py                         |  97 ++++++++++++++++++
 19 files changed, 590 insertions(+)
 create mode 100644 combo/apps/maps/__init__.py
 create mode 100644 combo/apps/maps/forms.py
 create mode 100644 combo/apps/maps/manager_views.py
 create mode 100644 combo/apps/maps/migrations/0001_initial.py
 create mode 100644 combo/apps/maps/migrations/__init__.py
 create mode 100644 combo/apps/maps/models.py
 create mode 100644 combo/apps/maps/static/js/jquery.colourpicker.js
 create mode 100644 combo/apps/maps/templates/maps/manager_base.html
 create mode 100644 combo/apps/maps/templates/maps/manager_home.html
 create mode 100644 combo/apps/maps/templates/maps/maplayer_confirm_delete.html
 create mode 100644 combo/apps/maps/templates/maps/maplayer_form.html
 create mode 100644 combo/apps/maps/templates/maps/maplayer_list.html
 create mode 100644 combo/apps/maps/urls.py
 create mode 100644 combo/apps/maps/views.py
 create mode 100644 tests/test_maps_manager.py
combo/apps/maps/__init__.py
1
# combo - content management system
2
# Copyright (C) 2015  Entr'ouvert
3
#
4
# This program is free software: you can redistribute it and/or modify it
5
# under the terms of the GNU Affero General Public License as published
6
# by the Free Software Foundation, either version 3 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU Affero General Public License for more details.
13
#
14
# You should have received a copy of the GNU Affero General Public License
15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16

  
17
import django.apps
18
from django.core.urlresolvers import reverse
19
from django.utils.translation import ugettext_lazy as _
20

  
21

  
22
class AppConfig(django.apps.AppConfig):
23
    name = 'combo.apps.maps'
24
    verbose_name = _('Maps')
25

  
26
    def get_before_urls(self):
27
        from . import urls
28
        return urls.urlpatterns
29

  
30
    def get_extra_manager_actions(self):
31
        return [{'href': reverse('maps-manager-homepage'),
32
                'text': _('Maps')}]
33

  
34
default_app_config = 'combo.apps.maps.AppConfig'
combo/apps/maps/forms.py
1
# combo - content management system
2
# Copyright (C) 2015  Entr'ouvert
3
#
4
# This program is free software: you can redistribute it and/or modify it
5
# under the terms of the GNU Affero General Public License as published
6
# by the Free Software Foundation, either version 3 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU Affero General Public License for more details.
13
#
14
# You should have received a copy of the GNU Affero General Public License
15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16

  
17
import itertools
18

  
19
from django import forms
20

  
21
from .models import MapLayer
22

  
23
colours = [('%s%s%s' % x, '%s%s%s' % x) for x in itertools.product(('00', '66', '99', 'FF'), repeat=3)]
24

  
25
class MapLayerForm(forms.ModelForm):
26
    class Meta:
27
        model = MapLayer
28
        fields = '__all__'
29
        widgets = {'marker_colour': forms.Select(attrs={'class': 'colour-picker'},
30
                                          choices=colours),
31
                   'icon_colour': forms.Select(attrs={'class': 'colour-picker'},
32
                                          choices=colours),
33
        }
combo/apps/maps/manager_views.py
1
# combo - content management system
2
# Copyright (C) 2015  Entr'ouvert
3
#
4
# This program is free software: you can redistribute it and/or modify it
5
# under the terms of the GNU Affero General Public License as published
6
# by the Free Software Foundation, either version 3 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU Affero General Public License for more details.
13
#
14
# You should have received a copy of the GNU Affero General Public License
15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16

  
17
from django.core.urlresolvers import reverse_lazy
18
from django.views.generic import (TemplateView, ListView, CreateView,
19
                UpdateView, DeleteView)
20

  
21
from .models import MapLayer
22
from .forms import MapLayerForm
23

  
24

  
25
class ManagerHomeView(TemplateView):
26
    template_name = 'maps/manager_home.html'
27

  
28

  
29
class LayersManagerView(ListView):
30
    model = MapLayer
31

  
32

  
33
class LayerAddView(CreateView):
34
    model = MapLayer
35
    form_class = MapLayerForm
36
    success_url = reverse_lazy('maps-manager-layers-list')
37

  
38

  
39
class LayerEditView(UpdateView):
40
    model = MapLayer
41
    form_class = MapLayerForm
42
    success_url = reverse_lazy('maps-manager-layers-list')
43

  
44

  
45
class LayerDeleteView(DeleteView):
46
    model = MapLayer
47
    success_url = reverse_lazy('maps-manager-layers-list')
combo/apps/maps/migrations/0001_initial.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4
from django.db import migrations, models
5

  
6

  
7
class Migration(migrations.Migration):
8

  
9
    dependencies = [
10
    ]
11

  
12
    operations = [
13
        migrations.CreateModel(
14
            name='MapLayer',
15
            fields=[
16
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
17
                ('label', models.CharField(max_length=128, verbose_name='Label')),
18
                ('geojson_url', models.URLField(verbose_name='Geojson URL')),
19
                ('marker_colour', models.CharField(default=b'0000FF', max_length=6, verbose_name='Marker color')),
20
                ('icon', models.CharField(help_text='FontAwesome style name', max_length=32, null=True, verbose_name='Marker icon', blank=True)),
21
                ('icon_colour', models.CharField(default=b'FFFFFF', max_length=6, verbose_name='Icon colour')),
22
            ],
23
        ),
24
    ]
combo/apps/maps/models.py
1
# combo - content management system
2
# Copyright (C) 2015  Entr'ouvert
3
#
4
# This program is free software: you can redistribute it and/or modify it
5
# under the terms of the GNU Affero General Public License as published
6
# by the Free Software Foundation, either version 3 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU Affero General Public License for more details.
13
#
14
# You should have received a copy of the GNU Affero General Public License
15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16

  
17

  
18
from django.db import models
19
from django.utils.translation import ugettext_lazy as _
20

  
21
from combo.utils import requests
22

  
23

  
24
class MapLayer(models.Model):
25
    label = models.CharField(_('Label'), max_length=128)
26
    geojson_url = models.URLField(_('Geojson URL'))
27
    marker_colour = models.CharField(_('Marker color'), max_length=6, default='0000FF')
28
    icon = models.CharField(_('Marker icon'), max_length=32, blank=True, null=True,
29
                            help_text=_('FontAwesome style name'))
30
    icon_colour = models.CharField(_('Icon colour'), max_length=6, default='FFFFFF')
31

  
32
    def __unicode__(self):
33
        return self.label
34

  
35
    def get_geojson(self):
36
        response = requests.get(self.geojson_url,
37
                            remote_service='auto',
38
                            headers={'accept': 'application/json'})
39
        if not response.ok:
40
            return []
41
        features = response.json()
42
        for feature in features:
43
                feature['display_fields'] = feature['properties'].copy()
44
                feature['properties']['colour'] = '#%s' % self.marker_colour
45
                feature['properties']['icon_colour'] = '#%s' % self.icon_colour
46
                feature['properties']['label'] = self.label
47
                feature['properties']['icon'] = self.icon
48
        return features
combo/apps/maps/static/js/jquery.colourpicker.js
1
/* adapted from http://andreaslagerkvist.com/jquery/colour-picker/ */
2

  
3
jQuery.fn.colourPicker = function (conf) {
4
    // Config for plug
5
    var config = jQuery.extend({
6
        id:            'jquery-colour-picker',    // id of colour-picker container
7
        inputBG:    true,                    // Whether to change the input's background to the selected colour's
8
        speed:        500                    // Speed of dialogue-animation
9
    }, conf);
10

  
11
    // Inverts a hex-colour
12
    var hexInvert = function (hex) {
13
        var r = parseInt(hex.substr(0, 2), 16);
14
        var g = parseInt(hex.substr(2, 2), 16);
15
        var b = parseInt(hex.substr(4, 2), 16);
16

  
17
        return 0.212671 * r + 0.715160 * g + 0.072169 * b < 128 ? 'ffffff' : '000000'
18
    };
19

  
20
    // Add the colour-picker dialogue if not added
21
    var colourPicker = jQuery('#' + config.id);
22

  
23
    if (!colourPicker.length) {
24
        colourPicker = jQuery('<div id="' + config.id + '"></div>').appendTo(document.body).hide();
25

  
26
        // Remove the colour-picker if you click outside it (on body)
27
        jQuery(document.body).click(function(event) {
28
            if (!(jQuery(event.target).is('#' + config.id) || jQuery(event.target).parents('#' + config.id).length)) {
29
                colourPicker.hide(config.speed);
30
            }
31
        });
32
    }
33

  
34
    // For every select passed to the plug-in
35
    return this.each(function () {
36
        // Insert icon and input
37
        var select    = jQuery(this);
38
        var icon    = jQuery('<a href="#">...</a>').insertAfter(select);
39
        var input    = jQuery('<input type="text" name="' + select.attr('name') + '" value="' + select.val() + '" size="7" />').insertAfter(select);
40
        var loc        = '';
41

  
42
        // Build a list of colours based on the colours in the select
43
        jQuery('option', select).each(function () {
44
            var option    = jQuery(this);
45
            var hex        = option.val();
46
            var title    = option.text();
47

  
48
            loc += '<li><a href="#" title="' 
49
                    + title 
50
                    + '" rel="' 
51
                    + hex 
52
                    + '" style="background: #' 
53
                    + hex 
54
                    + '; colour: ' 
55
                    + hexInvert(hex) 
56
                    + ';">' 
57
                    + title 
58
                    + '</a></li>';
59
        });
60

  
61
        // Remove select
62
        select.remove();
63

  
64
        // If user wants to, change the input's BG to reflect the newly selected colour
65
        if (config.inputBG) {
66
            input.change(function () {
67
                input.css({background: '#' + input.val(), color: '#' + hexInvert(input.val())});
68
            });
69

  
70
            input.change();
71
        }
72

  
73
        // When you click the icon
74
        icon.click(function () {
75
            // Show the colour-picker next to the icon and fill it with the colours in the select that used to be there
76
            var iconPos    = icon.offset();
77

  
78
            colourPicker.html('<ul>' + loc + '</ul>').css({
79
                position: 'absolute', 
80
                left: iconPos.left + 'px', 
81
                top: iconPos.top + 'px'
82
            }).show(config.speed);
83

  
84
            // When you click a colour in the colour-picker
85
            jQuery('a', colourPicker).click(function () {
86
                // The hex is stored in the link's rel-attribute
87
                var hex = jQuery(this).attr('rel');
88

  
89
                input.val(hex);
90

  
91
                // If user wants to, change the input's BG to reflect the newly selected colour
92
                if (config.inputBG) {
93
                    input.css({background: '#' + hex, color: '#' + hexInvert(hex)});
94
                }
95

  
96
                // Trigger change-event on input
97
                input.change();
98

  
99
                // Hide the colour-picker and return false
100
                colourPicker.hide(config.speed);
101

  
102
                return false;
103
            });
104

  
105
            return false;
106
        });
107
    });
108
};
109

  
110
$(function() {
111
  jQuery('select.colour-picker').colourPicker();
112
});
combo/apps/maps/templates/maps/manager_base.html
1
{% extends "combo/manager_base.html" %}
2
{% load i18n %}
3

  
4
{% block appbar %}
5
<h2>{% trans 'Maps' %}</h2>
6
{% endblock %}
7

  
8
{% block breadcrumb %}
9
{{ block.super }}
10
<a href="{% url 'maps-manager-homepage' %}">{% trans 'Maps' %}</a>
11
{% endblock %}
combo/apps/maps/templates/maps/manager_home.html
1
{% extends "maps/manager_base.html" %}
2
{% load i18n %}
3

  
4
{% block content %}
5
<ul class="apps">
6
 <li><a class="button" href="{% url 'maps-manager-layers-list' %}">{% trans 'Layers' %}</a></li>
7
</ul>
8
{% endblock %}
combo/apps/maps/templates/maps/maplayer_confirm_delete.html
1
{% extends "combo/manager_base.html" %}
2
{% load i18n %}
3

  
4
{% block appbar %}
5
<h2>{{ view.model.get_verbose_name }}</h2>
6
{% endblock %}
7

  
8
{% block content %}
9
<form method="post">
10
  {% csrf_token %}
11
  {% blocktrans %}Are you sure you want to delete this?{% endblocktrans %}
12
  <div class="buttons">
13
    <button class="delete-button">{% trans 'Delete' %}</button>
14
    <a class="cancel" href="{% url 'maps-manager-layers-list' %}">{% trans 'Cancel' %}</a>
15
  </div>
16
</form>
17
{% endblock %}
combo/apps/maps/templates/maps/maplayer_form.html
1
{% extends "maps/maplayer_list.html" %}
2
{% load i18n %}
3

  
4
{% block appbar %}
5
{% if object.id %}
6
<h2>{% trans "Edit Layer" %}</h2>
7
{% else %}
8
<h2>{% trans "New Layer" %}</h2>
9
{% endif %}
10
{% endblock %}
11

  
12
{% block breadcrumb %}
13
{{ block.super }}
14
<a href="{% url 'maps-manager-homepage' %}">{% trans 'Layers' %}</a>
15
{% endblock %}
16

  
17
{% block content %}
18

  
19
<form method="post" enctype="multipart/form-data">
20
  {% csrf_token %}
21
  {{ form.as_p }}
22
  <div class="buttons">
23
    <button class="submit-button">{% trans "Save" %}</button>
24
    <a class="cancel" href="{% url 'maps-manager-layers-list' %}">{% trans 'Cancel' %}</a>
25
    {% if object.id %}
26
    <a class="delete" rel="popup" href="{% url 'maps-manager-layer-delete' pk=object.id %}">{% trans 'Delete' %}</a>
27
    {% endif %}
28
  </div>
29
</form>
30
{% endblock %}
combo/apps/maps/templates/maps/maplayer_list.html
1
{% extends "maps/manager_base.html" %}
2
{% load i18n %}
3

  
4
{% block breadcrumb %}
5
{{ block.super }}
6
<a href="{% url 'maps-manager-homepage' %}">{% trans 'Layers' %}</a>
7
{% endblock %}
8

  
9
{% block appbar %}
10
<h2>{% trans 'Layers' %}</h2>
11
<a rel="popup" href="{% url 'maps-manager-layer-add' %}">{% trans 'New' %}</a>
12
{% endblock %}
13

  
14
{% block content %}
15

  
16
{% if object_list %}
17
<div class="objects-list">
18
 {% for layer in object_list %}
19
 <div>
20
 <a href="{% url 'maps-manager-layer-edit' pk=layer.id %}">{{ layer.label }}
21
 </a>
22
 </div>
23
 {% endfor %}
24
</div>
25
{% else %}
26
<div class="big-msg-info">
27
  {% blocktrans %}
28
  This site doesn't have any layer yet. Click on the "New" button in the top
29
  right of the page to add a first one.
30
  {% endblocktrans %}
31
</div>
32
{% endif %}
33
{% endblock %}
combo/apps/maps/urls.py
1
# combo - content management system
2
# Copyright (C) 2015  Entr'ouvert
3
#
4
# This program is free software: you can redistribute it and/or modify it
5
# under the terms of the GNU Affero General Public License as published
6
# by the Free Software Foundation, either version 3 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU Affero General Public License for more details.
13
#
14
# You should have received a copy of the GNU Affero General Public License
15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16

  
17
from django.conf.urls import url, include
18

  
19
from combo.urls_utils import decorated_includes, manager_required
20

  
21
from .manager_views import (ManagerHomeView, LayersManagerView, LayerAddView,
22
                LayerEditView, LayerDeleteView)
23

  
24
maps_manager_urls = [
25
    url('^$', ManagerHomeView.as_view(), name='maps-manager-homepage'),
26
    url('^layers/$', LayersManagerView.as_view(), name='maps-manager-layers-list'),
27
    url('^layers/add/$', LayerAddView.as_view(), name='maps-manager-layer-add'),
28
    url('^layers/(?P<pk>\w+)/edit$', LayerEditView.as_view(),
29
        name='maps-manager-layer-edit'),
30
    url('^layers/(?P<pk>\w+)/edit/$', LayerEditView.as_view(),
31
        name='maps-manager-layer-edit'),
32
    url('^layers/(?P<pk>\w+)/delete/$', LayerDeleteView.as_view(),
33
        name='maps-manager-layer-delete'),
34
]
35

  
36
urlpatterns = [
37
    url(r'^manage/maps/', decorated_includes(manager_required,
38
        include(maps_manager_urls))),
39
]
combo/apps/maps/views.py
1
# combo - content management system
2
# Copyright (C) 2015  Entr'ouvert
3
#
4
# This program is free software: you can redistribute it and/or modify it
5
# under the terms of the GNU Affero General Public License as published
6
# by the Free Software Foundation, either version 3 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU Affero General Public License for more details.
13
#
14
# You should have received a copy of the GNU Affero General Public License
15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16

  
17
from django.shortcuts import render
combo/manager/static/css/combo.manager.css
301 301
	font-size: 80%;
302 302
	opacity: 0.5;
303 303
}
304

  
305
/* colour picker styles */
306

  
307
#jquery-colour-picker {
308
        background: #fafafa;
309
        width: 250px;
310
        padding: 10px 5px;
311
        border-radius: 5px;
312
        box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.3);
313
        z-index: 2000;
314
}
315

  
316
#jquery-colour-picker ul {
317
        margin: 0;
318
        padding: 0;
319
        list-style-type: none;
320
}
321

  
322
#jquery-colour-picker li {
323
        float: left;
324
        margin: 0 5px 5px 0;
325
}
326

  
327
#jquery-colour-picker li a {
328
        display: block;
329
        width: 13px;
330
        height: 13px;
331
        text-decoration: none;
332
        text-indent: -10000px;
333
        outline: 0;
334
        border: 1px solid #aaa;
335
}
combo/manager/static/js/combo.manager.js
222 222
    window.location = $(this).parent('div').find('option:selected').data('add-url');
223 223
    return false;
224 224
  });
225

  
226
  $(document).on('gadjo:dialog-loaded', function(e, dialog) {
227
      if (jQuery.fn.colourPicker !== undefined) {
228
          jQuery('select.colour-picker').colourPicker({title: ''});
229
      }
230
  });
225 231
});
combo/manager/templates/combo/manager_base.html
30 30
<script src="{% static "ckeditor/ckeditor/ckeditor.js" %}"></script>
31 31
<script type="text/javascript" src="{% static "ckeditor/ckeditor-init.js" %}"></script>
32 32
<script src="{% static "js/combo.manager.js" %}"></script>
33
<script src="{% static "js/jquery.colourpicker.js" %}"></script>
33 34
{% endblock %}
combo/settings.py
75 75
    'combo.apps.notifications',
76 76
    'combo.apps.search',
77 77
    'combo.apps.usersearch',
78
    'combo.apps.maps',
78 79
    'haystack',
79 80
    'xstatic.pkg.chartnew_js',
80 81
)
tests/test_maps_manager.py
1
# -*- coding: utf-8 -*-
2

  
3
import pytest
4
import mock
5

  
6
from django.contrib.auth.models import User
7

  
8
from combo.apps.maps.models import MapLayer
9

  
10
pytestmark = pytest.mark.django_db
11

  
12
@pytest.fixture
13
def admin_user():
14
    try:
15
        user = User.objects.get(username='admin')
16
    except User.DoesNotExist:
17
        user = User.objects.create_superuser('admin', email=None, password='admin')
18
    return user
19

  
20
def login(app, username='admin', password='admin'):
21
    login_page = app.get('/login/')
22
    login_form = login_page.forms[0]
23
    login_form['username'] = username
24
    login_form['password'] = password
25
    resp = login_form.submit()
26
    assert resp.status_int == 302
27
    return app
28

  
29
def test_access(app, admin_user):
30
    app = login(app)
31
    resp = app.get('/manage/', status=200)
32
    assert '/manage/maps/' in resp.body
33

  
34
def test_add_layer(app, admin_user):
35
    MapLayer.objects.all().delete()
36
    app = login(app)
37
    resp = app.get('/manage/maps/layers/', status=200)
38
    resp = resp.click('New')
39
    assert 'js/jquery.colourpicker.js' in resp.content
40
    resp.forms[0]['label'] = 'Test'
41
    resp.forms[0]['geojson_url'] = 'http://example.net/geojson'
42
    assert resp.form['marker_colour'].value == '0000FF'
43
    resp.forms[0]['marker_colour'] = 'FFFFFF'
44
    resp.forms[0]['icon'] = 'fa-bicycle'
45
    assert resp.form['icon_colour'].value == 'FFFFFF'
46
    resp.form['icon_colour'] = '000000'
47
    resp = resp.forms[0].submit()
48
    assert resp.location == 'http://testserver/manage/maps/layers/'
49
    assert MapLayer.objects.count() == 1
50
    layer = MapLayer.objects.get()
51
    assert layer.label == 'Test'
52

  
53
def test_edit_layer(app, admin_user):
54
    test_add_layer(app, admin_user)
55
    app = login(app)
56
    resp = app.get('/manage/maps/layers/', status=200)
57
    resp = resp.click('Test')
58
    resp.forms[0]['geojson_url'] = 'http://example.net/new_geojson'
59
    resp = resp.forms[0].submit()
60
    assert resp.location == 'http://testserver/manage/maps/layers/'
61
    assert MapLayer.objects.count() == 1
62
    layer = MapLayer.objects.get()
63
    assert layer.geojson_url == 'http://example.net/new_geojson'
64

  
65
def test_delete_layer(app, admin_user):
66
    test_add_layer(app, admin_user)
67
    app = login(app)
68
    resp = app.get('/manage/maps/layers/', status=200)
69
    resp = resp.click('Test')
70
    resp = resp.click('Delete')
71
    assert 'Are you sure you want to delete this?' in resp.body
72
    resp = resp.forms[0].submit()
73
    assert resp.location == 'http://testserver/manage/maps/layers/'
74
    assert MapLayer.objects.count() == 0
75

  
76
@mock.patch('combo.apps.maps.models.requests.get')
77
def test_download_geojson(mock_request, app, admin_user):
78
    test_add_layer(app, admin_user)
79
    layer = MapLayer.objects.get()
80
    mocked_response = mock.Mock()
81
    mocked_response.json.return_value = [{'type': 'Feature',
82
            'geometry': {'type': 'Point',
83
                        'coordinates': [2.3233688436448574, 48.83369263315934]},
84
                        'properties': {'property': 'property value'}}]
85
    mocked_response.ok.return_value = True
86
    mock_request.return_value = mocked_response
87
    geojson = layer.get_geojson()
88
    assert len(geojson) > 0
89
    for item in geojson:
90
        assert item['type'] == 'Feature'
91
        assert item['geometry']['type'] == 'Point'
92
        assert item['geometry']['coordinates'] == [2.3233688436448574, 48.83369263315934]
93
        assert item['display_fields'] == {'property': 'property value'}
94
        assert item['properties']['icon'] == 'fa-bicycle'
95
        assert item['properties']['label'] == 'Test'
96
        assert item['properties']['colour'] == '#FFFFFF'
97
        assert item['properties']['icon_colour'] == '#000000'
0
-