editor forms for new feature models

This commit is contained in:
Laura Klünder 2016-10-13 15:55:15 +02:00
parent 4b74eb0cf5
commit ecc7c4f829
6 changed files with 86 additions and 58 deletions

View file

@ -1,63 +1,87 @@
import json
from collections import OrderedDict
from django.conf import settings
from django.forms import CharField, Form, ModelForm, ValidationError
from django.forms import CharField, Form, ModelForm
from django.forms.models import ModelChoiceField
from django.forms.widgets import HiddenInput
from django.utils.translation import ugettext_lazy as _
from shapely.geometry.geo import mapping
from c3nav.mapdata.models import Feature, Package
from c3nav.mapdata.models import Package
from c3nav.mapdata.models.features import Inside, Room
from c3nav.mapdata.permissions import get_unlocked_packages
class FeatureForm(ModelForm):
class FeatureFormMixin(ModelForm):
def __init__(self, *args, feature_type, request=None, **kwargs):
self.feature_type = feature_type
self.request = request
super().__init__(*args, **kwargs)
self.fields['level'].widget = HiddenInput()
self.fields['geometry'].widget = HiddenInput()
creating = not self.instance.pk
titles = OrderedDict((lang_code, '') for lang_code, language in settings.LANGUAGES)
if self.instance is not None and self.instance.pk:
# disable name on non-direct editing
if not creating and not settings.DIRECT_EDITING:
self.fields['name'].disabled = True
# restrict package choices and field_name
if not creating:
if not settings.DIRECT_EDITING:
self.fields['package'].widget = HiddenInput()
self.fields['package'].disabled = True
titles.update(self.instance.titles)
self.initial['package'] = self.instance.package.name
elif not settings.DIRECT_EDITING:
unlocked_packages = get_unlocked_packages(request)
if len(unlocked_packages) == 1:
self.fields['package'].widget = HiddenInput()
self.fields['package'].initial = next(iter(unlocked_packages))
self.fields['package'].disabled = True
else:
self.fields['package'] = ModelChoiceField(
queryset=Package.objects.filter(name__in=unlocked_packages)
queryset=Package.objects.filter(name__in=unlocked_packages),
)
self.fields['package'].to_field_name = 'name'
# hide level widget and set field_name
self.fields['level'].widget = HiddenInput()
self.fields['level'].to_field_name = 'name'
if not creating:
self.initial['level'] = self.instance.level.name
# hide geometry widget
self.fields['geometry'].widget = HiddenInput()
if not creating:
self.initial['geometry'] = json.dumps(mapping(self.instance.geometry), separators=(',', ':'))
# parse titles
self.titles = None
if hasattr(self.instance, 'titles'):
titles = OrderedDict((lang_code, '') for lang_code, language in settings.LANGUAGES)
if self.instance is not None and self.instance.pk:
titles.update(self.instance.titles)
language_titles = dict(settings.LANGUAGES)
for language in titles.keys():
new_title = self.data.get('title_' + language)
if new_title is not None:
titles[language] = new_title
self.fields['title_' + language] = CharField(label=language_titles.get(language, language), required=False,
self.fields['title_' + language] = CharField(label=language_titles.get(language, language),
required=False,
initial=titles[language].strip(), max_length=50)
self.titles = titles
def clean(self):
super().clean()
if not any(self.titles.values()):
raise ValidationError(
_('You have to select a title in at least one language.')
)
def get_languages(self):
pass
def create_editor_form(feature_model, add_fields=None):
class EditorForm(FeatureFormMixin, ModelForm):
class Meta:
# generate extra fields in the number specified via extra_fields
model = Feature
fields = ['name', 'package', 'level', 'geometry']
model = feature_model
fields = ['name', 'package', 'level', 'geometry'] + (add_fields if add_fields is not None else [])
feature_model.EditorForm = EditorForm
create_editor_form(Inside)
create_editor_form(Room)
class CommitForm(Form):

View file

@ -321,8 +321,7 @@ editor = {
editor.map.fitBounds(editor._editing.getBounds());
$('.leaflet-drawbar').hide();
var endpoint = editor.feature_types[editor._creating].endpoint;
var path = '/editor/' + endpoint + '/add/';
var path = '/editor/features/' + editor._creating + '/add/';
$('#mapeditcontrols').removeClass('list');
$('body').addClass('controls');
$('#mapeditdetail').load(path, editor.edit_form_loaded);
@ -333,8 +332,7 @@ editor = {
if (editor._creating !== null || editor._editing !== null) return;
editor._highlight_layer.clearLayers();
editor._editing = editor.features[name].layer;
var endpoint = editor.feature_types[editor._editing.feature.properties.feature_type].endpoint;
var path = '/editor/'+endpoint+'/edit/' + name + '/';
var path = '/editor/features/'+ editor._editing.feature.properties.feature_type +'/edit/' + name + '/';
$('#mapeditcontrols').removeClass('list');
$('#mapeditdetail').load(path, editor.edit_form_loaded);
$('body').addClass('controls');

View file

@ -6,7 +6,7 @@ from c3nav.editor.views import edit_feature, finalize, oauth_callback
urlpatterns = [
url(r'^$', TemplateView.as_view(template_name='editor/map.html'), name='editor.index'),
url(r'^features/(?P<feature_type>[^/]+)/add/$', edit_feature, name='editor.feature.add'),
url(r'^features/edit/(?P<name>[^/]+)/$', edit_feature, name='editor.feature.edit'),
url(r'^features/(?P<feature_type>[^/]+)/edit/(?P<name>[^/]+)/$', edit_feature, name='editor.feature.edit'),
url(r'^finalize/$', finalize, name='editor.finalize'),
url(r'^oauth/(?P<hoster>[^/]+)/callback$', oauth_callback, name='editor.oauth.callback')
]

View file

@ -4,36 +4,34 @@ from django.core.exceptions import PermissionDenied, SuspiciousOperation
from django.core.signing import BadSignature
from django.http.response import Http404
from django.shortcuts import get_object_or_404, render
from django.utils import translation
# from c3nav.editor.forms import FeatureForm
from c3nav.editor.hosters import get_hoster_for_package, hosters
from c3nav.mapdata.models.features import FEATURE_TYPES, Feature
from c3nav.mapdata.models.features import FEATURE_TYPES
from c3nav.mapdata.models.package import Package
from c3nav.mapdata.packageio.write import json_encode
from c3nav.mapdata.permissions import can_access_package
def edit_feature(request, feature_type=None, name=None):
def edit_feature(request, feature_type, name=None):
model = FEATURE_TYPES.get(feature_type)
if model is None:
raise Http404()
feature = None
if name is not None:
# Edit existing feature
feature = get_object_or_404(Feature, name=name)
feature = get_object_or_404(model, name=name)
if not can_access_package(request, feature.package):
raise PermissionDenied
feature_type = FEATURE_TYPES.get(feature.feature_type)
else:
# Create new feature
feature = None
feature_type = FEATURE_TYPES.get(feature_type)
if feature_type is None:
raise Http404()
if request.method == 'POST':
if feature is not None and request.POST.get('delete') == '1':
# Delete this feature!
if request.POST.get('delete_confirm') == '1':
if not settings.DIRECT_EDITING:
title_en = feature.titles.get('en', next(iter(feature.titles.values())))
commit_msg = 'Deleted %s: %s' % (feature_type.title_en.lower(), title_en)
with translation.override('en'):
commit_msg = 'Deleted %s: %s' % (model._meta.verbose_name, feature.title)
return render(request, 'editor/feature_success.html', {
'data': signing.dumps({
'type': 'editor.edit',
@ -41,7 +39,7 @@ def edit_feature(request, feature_type=None, name=None):
'package_name': feature.package.name,
'commit_id': feature.package.commit_id,
'commit_msg': commit_msg,
'file_path': feature.tofilename(),
'file_path': feature.get_filename(),
})
})
@ -54,13 +52,14 @@ def edit_feature(request, feature_type=None, name=None):
'path': request.path
})
form = FeatureForm(instance=feature, data=request.POST, feature_type=feature_type, request=request)
form = model.EditorForm(instance=feature, data=request.POST, feature_type=feature_type, request=request)
if form.is_valid():
# Update/create feature
commit_type = 'Created' if feature is None else 'Updated'
action = 'create' if feature is None else 'edit'
feature = form.instance
feature.feature_type = feature_type.name
if form.titles is not None:
feature.titles = {}
for language, title in form.titles.items():
if title:
@ -68,8 +67,8 @@ def edit_feature(request, feature_type=None, name=None):
if not settings.DIRECT_EDITING:
content = json_encode(feature.tofile())
title_en = feature.titles.get('en', next(iter(feature.titles.values())))
commit_msg = '%s %s: %s' % (commit_type, feature_type.title_en.lower(), title_en)
with translation.override('en'):
commit_msg = '%s %s: %s' % (commit_type, model._meta.verbose_name, feature.title)
return render(request, 'editor/feature_success.html', {
'data': signing.dumps({
'type': 'editor.edit',
@ -77,7 +76,7 @@ def edit_feature(request, feature_type=None, name=None):
'package_name': feature.package.name,
'commit_id': feature.package.commit_id,
'commit_msg': commit_msg,
'file_path': feature.tofilename(),
'file_path': feature.get_filename(),
'content': content,
})
})
@ -86,7 +85,7 @@ def edit_feature(request, feature_type=None, name=None):
return render(request, 'editor/feature_success.html', {})
else:
form = FeatureForm(instance=feature, feature_type=feature_type, request=request)
form = model.EditorForm(instance=feature, feature_type=feature_type, request=request)
return render(request, 'editor/feature.html', {
'form': form,

View file

@ -23,9 +23,15 @@ class Feature(MapdataModel):
level = models.ForeignKey('mapdata.Level', on_delete=models.CASCADE, verbose_name=_('level'))
geometry = GeometryField()
EditorForm = None
class Meta:
abstract = True
@property
def title(self):
return self.name
@classmethod
def fromfile(cls, data, file_path):
kwargs = super().fromfile(data, file_path)

View file

@ -160,6 +160,7 @@ class ReaderItem:
# Change name references to the referenced object
for name, model in self.relations.items():
if name in self.data:
print(name, self.data[name])
self.data[name] = self.reader.saved_items[model][self.data[name]].obj
obj, created = self.model.objects.update_or_create(name=self.data['name'], defaults=self.data)