From 9f79e26671194bfa8a254c525b95c1c829cb08bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laura=20Kl=C3=BCnder?= Date: Fri, 23 Sep 2016 15:23:02 +0200 Subject: [PATCH] basic feature adding in editor --- src/c3nav/editor/forms.py | 16 ++++ src/c3nav/editor/static/editor/css/editor.css | 35 ++++++++- src/c3nav/editor/static/editor/js/editor.js | 77 +++++++++++++++---- .../editor/templates/editor/feature.html | 15 ++++ .../templates/editor/feature_success.html | 0 src/c3nav/editor/templates/editor/map.html | 5 +- src/c3nav/editor/urls.py | 5 +- src/c3nav/editor/views.py | 34 ++++++++ 8 files changed, 169 insertions(+), 18 deletions(-) create mode 100644 src/c3nav/editor/forms.py create mode 100644 src/c3nav/editor/templates/editor/feature.html create mode 100644 src/c3nav/editor/templates/editor/feature_success.html create mode 100644 src/c3nav/editor/views.py diff --git a/src/c3nav/editor/forms.py b/src/c3nav/editor/forms.py new file mode 100644 index 00000000..b54167c3 --- /dev/null +++ b/src/c3nav/editor/forms.py @@ -0,0 +1,16 @@ +from django.forms import ModelForm +from django.forms.widgets import HiddenInput + +from ..mapdata.models import Feature + + +class FeatureForm(ModelForm): + def __init__(self, *args, feature_type, **kwargs): + self.feature_type = feature_type + super().__init__(*args, **kwargs) + self.fields['level'].widget = HiddenInput() + self.fields['geometry'].widget = HiddenInput() + + class Meta: + model = Feature + fields = ['name', 'package', 'level', 'geometry'] diff --git a/src/c3nav/editor/static/editor/css/editor.css b/src/c3nav/editor/static/editor/css/editor.css index 8edc94c6..6d5b97bc 100644 --- a/src/c3nav/editor/static/editor/css/editor.css +++ b/src/c3nav/editor/static/editor/css/editor.css @@ -32,16 +32,49 @@ color:#000000; } + #mapeditcontrols { position:absolute; top:54px; bottom:0; + padding:0; + width:350px; + right:0; + overflow:hidden; + background-image:url('/static/img/loader.gif'); + background-repeat:no-repeat; + background-position:center; +} +#mapeditcontrols > div { + position:absolute; + top:0; + bottom:0; + background-color:white; padding:8px; width:350px; right:0; overflow:auto; } -#mapeditcontrols legend .btn { +#mapeditcontrols > #mapeditdetail { + right:-350px; + transition: right 300ms; + -webkit-transition: right 300ms; + pointer-events: none; +} +#mapeditcontrols.detail #mapeditdetail { + right:0; + pointer-events: auto; +} +#mapeditcontrols > #mapeditlist { + display:none; +} +#mapeditcontrols.list > #mapeditlist { + display:block; +} +#mapeditdetail h3 { + margin-top:5px; +} +#mapeditlist legend .btn { padding-left:5.5px; padding-right:5.5px; } diff --git a/src/c3nav/editor/static/editor/js/editor.js b/src/c3nav/editor/static/editor/js/editor.js index ed5bd19f..afd54680 100644 --- a/src/c3nav/editor/static/editor/js/editor.js +++ b/src/c3nav/editor/static/editor/js/editor.js @@ -9,7 +9,7 @@ editor = { minZoom: 1, crs: L.CRS.Simple, editable: true, - closePopupOnClick: false, + closePopupOnClick: false }); L.control.scale({imperial: false}).addTo(editor.map); @@ -18,12 +18,41 @@ editor = { editor.get_packages(); editor.get_sources(); editor.get_levels(); + + $('#mapeditdetail').on('click', '#btn_abort', function() { + if (editor._adding !== null) { + editor._adding.remove(); + editor._adding = null; + editor._drawing = null; + $('#mapeditcontrols').removeClass('detail').addClass('list'); + $('#mapeditdetail').html(''); + $('.start-drawing').prop('disabled', false); + } + }).on('submit', 'form', function(e) { + e.preventDefault(); + var data = $(this).serialize(); + var action = $(this).attr('action'); + $('#mapeditcontrols').removeClass('detail'); + $('#mapeditdetail').html(''); + $.post(action, data, function(data) { + var content = $(data); + if ($('
').append(content).find('form').length > 0) { + $('#mapeditdetail').html(content); + $('#mapeditcontrols').addClass('detail'); + } else { + editor._adding = null; + editor._drawing = null; + $('.start-drawing').prop('disabled', false); + $('#mapeditcontrols').addClass('list'); + } + }); + }); }, get_feature_types: function() { $.getJSON('/api/v1/featuretypes/', function(feature_types) { var feature_type; - var editcontrols = $('#mapeditcontrols'); + var editcontrols = $('#mapeditlist'); for(var i=0;i').appendTo(container).text('cancel').attr({ href: '#', @@ -126,21 +170,24 @@ editor = { }); editor.map.addControl(new L.DrawControl()); - $('#mapeditcontrols').on('click', '.start-drawing', function() { + $('#mapeditlist').on('click', '.start-drawing', function() { console.log($(this).closest('fieldset')); editor.start_drawing($(this).closest('fieldset').attr('name')); }); editor.map.on('editable:drawing:commit', function (e) { - editor._drawing = null; editor._adding = e.layer; e.layer.disableEdit(); - L.popup({ - closeButton: false, - autoClose: false, - }).setContent('').setLatLng(e.layer.getCenter()).openOn(editor.map); $('.leaflet-drawbar').hide(); + var path = '/editor/features/'+editor._drawing+'/add'; + $('#mapeditcontrols').removeClass('list'); + $('#mapeditdetail').html('').load(path, function() { + $('#mapeditcontrols').addClass('detail'); + $('#id_level').val(editor._level); + $('#id_geometry').val(JSON.stringify(editor._adding.toGeoJSON().geometry)); + }); + }).on('editable:drawing:cancel', function (e) { if (editor._drawing !== null && editor._adding === null) { e.layer.remove(); @@ -166,10 +213,10 @@ editor = { editor.map.editTools.stopDrawing(); editor._drawing = null; $('.leaflet-drawbar').hide(); - }, + } }; -if ($('#mapeditcontrols').length) { +if ($('#mapeditlist').length) { editor.init(); } diff --git a/src/c3nav/editor/templates/editor/feature.html b/src/c3nav/editor/templates/editor/feature.html new file mode 100644 index 00000000..bdf3164f --- /dev/null +++ b/src/c3nav/editor/templates/editor/feature.html @@ -0,0 +1,15 @@ +{% load bootstrap3 %} + +

{% if new %}New{% else %}Edit{% endif %} {{ feature_type.title }}

+
+ {% csrf_token %} + {% bootstrap_form form %} + {% buttons %} + + + {% endbuttons %} +
\ No newline at end of file diff --git a/src/c3nav/editor/templates/editor/feature_success.html b/src/c3nav/editor/templates/editor/feature_success.html new file mode 100644 index 00000000..e69de29b diff --git a/src/c3nav/editor/templates/editor/map.html b/src/c3nav/editor/templates/editor/map.html index f5d7f25f..8667f9ed 100644 --- a/src/c3nav/editor/templates/editor/map.html +++ b/src/c3nav/editor/templates/editor/map.html @@ -2,5 +2,8 @@ {% load static %} {% block content %}
-
+
+
+
+
{% endblock %} diff --git a/src/c3nav/editor/urls.py b/src/c3nav/editor/urls.py index 9e850d49..51ce70a4 100644 --- a/src/c3nav/editor/urls.py +++ b/src/c3nav/editor/urls.py @@ -1,6 +1,9 @@ from django.conf.urls import url from django.views.generic import TemplateView +from c3nav.editor.views import add_feature + urlpatterns = [ - url(r'^$', TemplateView.as_view(template_name='editor/map.html'), name='editor.index') + url(r'^$', TemplateView.as_view(template_name='editor/map.html'), name='editor.index'), + url(r'^features/(?P[^/]+)/add/$', add_feature, name='editor.feature.add') ] diff --git a/src/c3nav/editor/views.py b/src/c3nav/editor/views.py new file mode 100644 index 00000000..fcbcb589 --- /dev/null +++ b/src/c3nav/editor/views.py @@ -0,0 +1,34 @@ +from django.db import transaction +from django.http.response import Http404 +from django.shortcuts import render + +from c3nav.editor.forms import FeatureForm +from c3nav.mapdata.models.feature import FEATURE_TYPES +from c3nav.settings import DIRECT_EDITING + + +def add_feature(request, feature_type): + feature_type = FEATURE_TYPES.get(feature_type) + if feature_type is None: + raise Http404() + + if request.method == 'POST': + form = FeatureForm(request.POST, feature_type=feature_type) + if form.is_valid(): + if not DIRECT_EDITING: + return render(request, 'editor/feature_success.html', {}) + + with transaction.atomic(): + feature = form.instance + feature.feature_type = feature_type.name + feature.save() + return render(request, 'editor/feature_success.html', {}) + else: + form = FeatureForm(feature_type=feature_type) + + return render(request, 'editor/feature.html', { + 'form': form, + 'feature_type': feature_type, + 'path': request.path, + 'new': True + })