rename Section back to Level

This commit is contained in:
Laura Klünder 2017-06-11 14:43:14 +02:00
parent 27ff35e785
commit 1498b7aeb0
27 changed files with 416 additions and 334 deletions

View file

@ -7,19 +7,19 @@ from rest_framework.response import Response
from rest_framework.viewsets import ViewSet
from shapely.ops import cascaded_union
from c3nav.mapdata.models import Section, Space
from c3nav.mapdata.models import Level, Space
class EditorViewSet(ViewSet):
"""
Editor API
/geometries/ returns a list of geojson features, you have to specify ?section=<id> or ?space=<id>
/geometries/ returns a list of geojson features, you have to specify ?level=<id> or ?space=<id>
/geometrystyles/ returns styling information for all geometry types
"""
def _get_section_geometries(self, section: Section):
buildings = section.buildings.all()
def _get_level_geometries(self, level: Level):
buildings = level.buildings.all()
buildings_geom = cascaded_union([building.geometry for building in buildings])
spaces = {space.id: space for space in section.spaces.all()}
spaces = {space.id: space for space in level.spaces.all()}
holes_geom = []
for space in spaces.values():
if space.outside:
@ -38,66 +38,66 @@ class EditorViewSet(ViewSet):
results = []
results.extend(buildings)
for door in section.doors.all():
for door in level.doors.all():
results.append(door)
results.extend(spaces.values())
return results
def _get_sections_pk(self, section):
sections_under = ()
sections_on_top = ()
lower_section = section.lower().first()
primary_sections = (section,) + ((lower_section,) if lower_section else ())
secondary_sections = Section.objects.filter(on_top_of__in=primary_sections).values_list('pk', 'on_top_of')
if lower_section:
sections_under = tuple(pk for pk, on_top_of in secondary_sections if on_top_of == lower_section.pk)
def _get_levels_pk(self, level):
levels_under = ()
levels_on_top = ()
lower_level = level.lower().first()
primary_levels = (level,) + ((lower_level,) if lower_level else ())
secondary_levels = Level.objects.filter(on_top_of__in=primary_levels).values_list('pk', 'on_top_of')
if lower_level:
levels_under = tuple(pk for pk, on_top_of in secondary_levels if on_top_of == lower_level.pk)
if True:
sections_on_top = tuple(pk for pk, on_top_of in secondary_sections if on_top_of == section.pk)
sections = chain([section.pk], sections_under, sections_on_top)
return sections, sections_on_top, sections_under
levels_on_top = tuple(pk for pk, on_top_of in secondary_levels if on_top_of == level.pk)
levels = chain([level.pk], levels_under, levels_on_top)
return levels, levels_on_top, levels_under
@list_route(methods=['get'])
def geometries(self, request, *args, **kwargs):
section = request.GET.get('section')
level = request.GET.get('level')
space = request.GET.get('space')
if section is not None:
if level is not None:
if space is not None:
raise ValidationError('Only section or space can be specified.')
section = get_object_or_404(Section, pk=section)
raise ValidationError('Only level or space can be specified.')
level = get_object_or_404(Level, pk=level)
sections, sections_on_top, sections_under = self._get_sections_pk(section)
sections = Section.objects.filter(pk__in=sections).prefetch_related('buildings', 'spaces', 'doors',
'spaces__groups', 'spaces__holes',
'spaces__columns')
sections = {s.pk: s for s in sections}
levels, levels_on_top, levels_under = self._get_levels_pk(level)
levels = Level.objects.filter(pk__in=levels).prefetch_related('buildings', 'spaces', 'doors',
'spaces__groups', 'spaces__holes',
'spaces__columns')
levels = {s.pk: s for s in levels}
section = sections[section.pk]
sections_under = [sections[pk] for pk in sections_under]
sections_on_top = [sections[pk] for pk in sections_on_top]
level = levels[level.pk]
levels_under = [levels[pk] for pk in levels_under]
levels_on_top = [levels[pk] for pk in levels_on_top]
results = chain(
*(self._get_section_geometries(s) for s in sections_under),
self._get_section_geometries(section),
*(self._get_section_geometries(s) for s in sections_on_top)
*(self._get_level_geometries(s) for s in levels_under),
self._get_level_geometries(level),
*(self._get_level_geometries(s) for s in levels_on_top)
)
return Response([obj.to_geojson() for obj in results])
elif space is not None:
space = get_object_or_404(Space.objects.select_related('section', 'section__on_top_of'), pk=space)
section = space.section
space = get_object_or_404(Space.objects.select_related('level', 'level__on_top_of'), pk=space)
level = space.level
doors = [door for door in section.doors.all() if door.geometry.intersects(space.geometry)]
doors = [door for door in level.doors.all() if door.geometry.intersects(space.geometry)]
doors_space_geom = cascaded_union([door.geometry for door in doors]+[space.geometry])
sections, sections_on_top, sections_under = self._get_sections_pk(section.primary_section)
other_spaces = Space.objects.filter(section__pk__in=sections).prefetch_related('groups')
levels, levels_on_top, levels_under = self._get_levels_pk(level.primary_level)
other_spaces = Space.objects.filter(level__pk__in=levels).prefetch_related('groups')
other_spaces = [s for s in other_spaces
if s.geometry.intersects(doors_space_geom) and s.pk != space.pk]
space.bounds = True
buildings = section.buildings.all()
buildings = level.buildings.all()
buildings_geom = cascaded_union([building.geometry for building in buildings])
for other_space in other_spaces:
if other_space.outside:
@ -122,7 +122,7 @@ class EditorViewSet(ViewSet):
)
return Response(sum([self._get_geojsons(obj) for obj in results], ()))
else:
raise ValidationError('No section or space specified.')
raise ValidationError('No level or space specified.')
def _get_geojsons(self, obj):
return ((obj.to_shadow_geojson(),) if hasattr(obj, 'to_shadow_geojson') else ()) + (obj.to_geojson(),)

View file

@ -16,9 +16,9 @@ class MapitemFormMixin(ModelForm):
super().__init__(*args, **kwargs)
creating = not self.instance.pk
if 'section' in self.fields:
# hide section widget
self.fields['section'].widget = HiddenInput()
if 'level' in self.fields:
# hide level widget
self.fields['level'].widget = HiddenInput()
if 'space' in self.fields:
# hide space widget

View file

@ -110,7 +110,7 @@ legend {
right: 8px;
top: 8px;
}
[data-sections], [data-subsections] {
[data-levels], [data-sublevels] {
display:none;
}
form button.invisiblesubmit {
@ -211,47 +211,47 @@ form button.invisiblesubmit {
}
/* leaftlet sections control */
.leaflet-control-sections {
/* leaftlet levels control */
.leaflet-control-levels {
overflow:hidden;
}
.leaflet-control-subsections {
.leaflet-control-sublevels {
position:absolute;
}
.leaflet-control-sections a, .leaflet-control-sections a:hover {
.leaflet-control-levels a, .leaflet-control-levels a:hover {
width: auto;
font-size: 14px;
padding: 0 7px;
white-space: nowrap;
}
.leaflet-touch .leaflet-control-sections a, .leaflet-touch .leaflet-control-sections a:hover {
.leaflet-touch .leaflet-control-levels a, .leaflet-touch .leaflet-control-levels a:hover {
width: auto;
height:36px;
line-height:37px;
font-size: 14px;
padding: 0 12px;
}
.leaflet-control-sections a, .leaflet-control-sections a:hover {
.leaflet-control-levels a, .leaflet-control-levels a:hover {
opacity:0;
margin-top:-26px;
}
.leaflet-touch .leaflet-control-sections a, .leaflet-touch .leaflet-control-sections a:hover {
.leaflet-touch .leaflet-control-levels a, .leaflet-touch .leaflet-control-levels a:hover {
margin-top:-36px;
}
.leaflet-control-sections a.current, .leaflet-control-sections-expanded a, .leaflet-control-sections-expanded a:hover,
.leaflet-touch .leaflet-control-sections a.current, .leaflet-touch .leaflet-control-sections-expanded a,
.leaflet-touch .leaflet-control-sections-expanded a:hover {
.leaflet-control-levels a.current, .leaflet-control-levels-expanded a, .leaflet-control-levels-expanded a:hover,
.leaflet-touch .leaflet-control-levels a.current, .leaflet-touch .leaflet-control-levels-expanded a,
.leaflet-touch .leaflet-control-levels-expanded a:hover {
opacity:1;
margin-top:0;
}
.leaflet-control-sections:not(.leaflet-control-sections-expanded) a.current {
.leaflet-control-levels:not(.leaflet-control-levels-expanded) a.current {
border-radius:4px;
border-width:0;
}
.leaflet-control-sections a.current {
.leaflet-control-levels a.current {
font-weight:bold;
}
.leaflet-control-sections .leaflet-disabled.current {
.leaflet-control-levels .leaflet-disabled.current {
color:#000000;
background-color:#ffffff;
}

View file

@ -38,11 +38,11 @@ editor = {
$('body').removeClass('show-map');
});
editor._section_control = new SectionControl().addTo(editor.map);
editor._subsection_control = new SectionControl({addClasses: 'leaflet-control-subsections'}).addTo(editor.map);
editor._level_control = new LevelControl().addTo(editor.map);
editor._sublevel_control = new LevelControl({addClasses: 'leaflet-control-sublevels'}).addTo(editor.map);
editor._section_control_container = $(editor._section_control._container);
editor._subsection_control_container = $(editor._subsection_control._container);
editor._level_control_container = $(editor._level_control._container);
editor._sublevel_control_container = $(editor._sublevel_control._container);
editor.init_geometries();
},
@ -105,30 +105,30 @@ editor = {
},
_sidebar_unload: function() {
// unload the sidebar. called on sidebar_get and form submit.
editor._section_control.disable();
editor._subsection_control.disable();
editor._level_control.disable();
editor._sublevel_control.disable();
$('#sidebar').addClass('loading').find('.content').html('');
editor._cancel_editing();
},
_fill_section_control: function (section_control, section_list) {
var sections = section_list.find('a');
if (sections.length) {
_fill_level_control: function (level_control, level_list) {
var levels = level_list.find('a');
if (levels.length) {
var current;
for (var i = 0; i < sections.length; i++) {
var section = $(sections[i]);
section_control.addSection(section.attr('data-id'), section.text(), section.attr('href'), section.is('.current'));
for (var i = 0; i < levels.length; i++) {
var level = $(levels[i]);
level_control.addLevel(level.attr('data-id'), level.text(), level.attr('href'), level.is('.current'));
}
if (sections.length > 1) {
section_control.enable();
if (levels.length > 1) {
level_control.enable();
} else {
section_control.disable();
level_control.disable();
}
section_control.show()
level_control.show()
} else {
section_control.hide();
level_control.hide();
}
section_control.current_id = parseInt(section_list.attr('data-current-id'));
level_control.current_id = parseInt(level_list.attr('data-current-id'));
},
_sidebar_loaded: function(data) {
// sidebar was loaded. load the content. check if there are any redirects. call _check_start_editing.
@ -157,28 +157,28 @@ editor = {
(editing_id.length ? editing_id.attr('data-editing') : null)
);
$('body').addClass('map-enabled');
editor._section_control.clearSections();
editor._subsection_control.clearSections();
editor._level_control.clearLevels();
editor._sublevel_control.clearLevels();
editor._fill_section_control(editor._section_control, content.find('[data-sections]'));
editor._fill_section_control(editor._subsection_control, content.find('[data-subsections]'));
editor._fill_level_control(editor._level_control, content.find('[data-levels]'));
editor._fill_level_control(editor._sublevel_control, content.find('[data-sublevels]'));
var section_control_offset = $(editor._section_control_container).position();
var offset_parent = $(editor._section_control_container).offsetParent();
$(editor._subsection_control._container).css({
bottom: offset_parent.height()-section_control_offset.top-editor._section_control_container.height()-parseInt(editor._section_control_container.css('margin-bottom')),
right: offset_parent.width()-section_control_offset.left
var level_control_offset = $(editor._level_control_container).position();
var offset_parent = $(editor._level_control_container).offsetParent();
$(editor._sublevel_control._container).css({
bottom: offset_parent.height()-level_control_offset.top-editor._level_control_container.height()-parseInt(editor._level_control_container.css('margin-bottom')),
right: offset_parent.width()-level_control_offset.left
});
} else {
$('body').removeClass('map-enabled').removeClass('show-map');
editor._section_control.hide();
editor._subsection_control.hide();
editor._level_control.hide();
editor._sublevel_control.hide();
}
},
_sidebar_error: function(data) {
$('#sidebar').removeClass('loading').find('.content').html('<h3>Error '+data.status+'</h3>'+data.statusText);
editor._section_control.hide();
editor._subsection_control.hide();
editor._level_control.hide();
editor._sublevel_control.hide();
},
_sidebar_link_click: function(e) {
// listener for link-clicks in the sidebar.
@ -314,14 +314,14 @@ editor = {
_get_geometry_style: function (feature) {
// style callback for GeoJSON loader
var style = editor._get_mapitem_type_style(feature.properties.type);
if (editor._section_control.current_section_id === editor._subsection_control.current_section_id) {
if (editor._subsection_control.section_ids.indexOf(feature.properties.section) >= 0 && editor._section_control.current_section_id !== feature.properties.section) {
if (editor._level_control.current_level_id === editor._sublevel_control.current_level_id) {
if (editor._sublevel_control.level_ids.indexOf(feature.properties.level) >= 0 && editor._level_control.current_level_id !== feature.properties.level) {
style.stroke = true;
style.weight = 1;
style.color = '#ffffff';
}
} else {
if (editor._subsection_control.current_section_id !== feature.properties.section) {
if (editor._sublevel_control.current_level_id !== feature.properties.level) {
style.fillOpacity = 0.5;
}
}
@ -529,18 +529,18 @@ editor = {
};
SectionControl = L.Control.extend({
LevelControl = L.Control.extend({
options: {
position: 'bottomright',
addClasses: ''
},
onAdd: function () {
this._container = L.DomUtil.create('div', 'leaflet-control-sections leaflet-bar '+this.options.addClasses);
this._sectionButtons = [];
this._container = L.DomUtil.create('div', 'leaflet-control-levels leaflet-bar '+this.options.addClasses);
this._levelButtons = [];
//noinspection JSUnusedGlobalSymbols
this.current_section_id = null;
this.section_ids = [];
this.current_level_id = null;
this.level_ids = [];
this._disabled = true;
this._expanded = false;
this.hide();
@ -561,9 +561,9 @@ SectionControl = L.Control.extend({
return this._container;
},
addSection: function (id, title, href, current) {
this.section_ids.push(parseInt(id));
if (current) this.current_section_id = parseInt(id);
addLevel: function (id, title, href, current) {
this.level_ids.push(parseInt(id));
if (current) this.current_level_id = parseInt(id);
var link = L.DomUtil.create('a', (current ? 'current' : ''), this._container);
link.innerHTML = title;
@ -571,32 +571,32 @@ SectionControl = L.Control.extend({
L.DomEvent
.on(link, 'mousedown dblclick', L.DomEvent.stopPropagation)
.on(link, 'click', this._sectionClick, this);
.on(link, 'click', this._levelClick, this);
this._sectionButtons.push(link);
this._levelButtons.push(link);
return link;
},
clearSections: function() {
this.current_section_id = null;
this.section_ids = [];
for (var i = 0; i < this._sectionButtons.length; i++) {
L.DomUtil.remove(this._sectionButtons[i]);
clearLevels: function() {
this.current_level_id = null;
this.level_ids = [];
for (var i = 0; i < this._levelButtons.length; i++) {
L.DomUtil.remove(this._levelButtons[i]);
}
this._sectionButtons = [];
this._levelButtons = [];
},
disable: function () {
for (var i = 0; i < this._sectionButtons.length; i++) {
L.DomUtil.addClass(this._sectionButtons[i], 'leaflet-disabled');
for (var i = 0; i < this._levelButtons.length; i++) {
L.DomUtil.addClass(this._levelButtons[i], 'leaflet-disabled');
}
this.collapse();
this._disabled = true;
},
enable: function () {
for (var i = 0; i < this._sectionButtons.length; i++) {
L.DomUtil.removeClass(this._sectionButtons[i], 'leaflet-disabled');
for (var i = 0; i < this._levelButtons.length; i++) {
L.DomUtil.removeClass(this._levelButtons[i], 'leaflet-disabled');
}
this._disabled = false;
},
@ -609,7 +609,7 @@ SectionControl = L.Control.extend({
this._container.style.display = '';
},
_sectionClick: function (e) {
_levelClick: function (e) {
e.preventDefault();
e.stopPropagation();
if (!this._expanded) {
@ -625,13 +625,13 @@ SectionControl = L.Control.extend({
expand: function () {
if (this._disabled) return;
this._expanded = true;
L.DomUtil.addClass(this._container, 'leaflet-control-sections-expanded');
L.DomUtil.addClass(this._container, 'leaflet-control-levels-expanded');
return this;
},
collapse: function () {
this._expanded = false;
L.DomUtil.removeClass(this._container, 'leaflet-control-sections-expanded');
L.DomUtil.removeClass(this._container, 'leaflet-control-levels-expanded');
return this;
}
});

View file

@ -1,6 +1,6 @@
{% load bootstrap3 %}
{% load i18n %}
{% include 'editor/fragment_sections.html' %}
{% include 'editor/fragment_levels.html' %}
<h3>{% blocktrans %}Delete {{ model_title }}{% endblocktrans %}</h3>
<form action="{{ path }}" method="post">

View file

@ -1,7 +1,7 @@
{% load bootstrap3 %}
{% load i18n %}
{% include 'editor/fragment_sections.html' %}
{% include 'editor/fragment_levels.html' %}
<h3>
{% if new %}
@ -10,8 +10,8 @@
{% blocktrans %}Edit {{ model_title }}{% endblocktrans %}
{% endif %}
{% if on_top_of %}
{% with on_top_of.title as on_top_of_section_title %}
<small>{% blocktrans %}on top of {{ on_top_of_section_title }}{% endblocktrans %}</small>
{% with on_top_of.title as on_top_of_level_title %}
<small>{% blocktrans %}on top of {{ on_top_of_level_title }}{% endblocktrans %}</small>
{% endwith %}
{% endif %}
</h3>

View file

@ -0,0 +1,26 @@
{% if levels %}
<ul data-levels>
{% for l in levels %}
<li>
<a data-id="{{ l.pk }}" href="{% if level_as_pk %}{% url level_url pk=l.id %}{% else %}{% url level_url level=l.id %}{% endif %}"{% if level.primary_level == l %} class="current"{% endif %}>{{ l.title }}</a>
</li>
{% endfor %}
</ul>
<ul data-sublevels>
{% for l in level.primary_level.sublevels %}
<li>
<a data-id="{{ l.pk }}" href="{% if level_as_pk %}{% url level_url pk=l.id %}{% else %}{% url level_url level=l.id %}{% endif %}"{% if level == l %} class="current"{% endif %}>{{ l.sublevel_title }}</a>
</li>
{% endfor %}
</ul>
{% elif level %}
<ul data-levels>
<li><a data-id="{{ level.primary_level.pk }}" href="" class="current">{{ level.primary_level.title }}</a></li>
</ul>
<ul data-sublevels>
<li><a data-id="{{ level.pk }}" href="" class="current">{{ level.sublevel_title }}</a></li>
</ul>
{% endif %}
{% if geometry_url %}
<span data-geometry-url="{{ geometry_url }}"></span>
{% endif %}

View file

@ -1,26 +0,0 @@
{% if sections %}
<ul data-sections>
{% for s in sections %}
<li>
<a data-id="{{ s.pk }}" href="{% if section_as_pk %}{% url section_url pk=s.id %}{% else %}{% url section_url section=s.id %}{% endif %}"{% if section.primary_section == s %} class="current"{% endif %}>{{ s.title }}</a>
</li>
{% endfor %}
</ul>
<ul data-subsections>
{% for s in section.primary_section.subsections %}
<li>
<a data-id="{{ s.pk }}" href="{% if section_as_pk %}{% url section_url pk=s.id %}{% else %}{% url section_url section=s.id %}{% endif %}"{% if section == s %} class="current"{% endif %}>{{ s.subsection_title }}</a>
</li>
{% endfor %}
</ul>
{% elif section %}
<ul data-sections>
<li><a data-id="{{ section.primary_section.pk }}" href="" class="current">{{ section.primary_section.title }}</a></li>
</ul>
<ul data-subsections>
<li><a data-id="{{ section.pk }}" href="" class="current">{{ section.subsection_title }}</a></li>
</ul>
{% endif %}
{% if geometry_url %}
<span data-geometry-url="{{ geometry_url }}"></span>
{% endif %}

View file

@ -1,15 +1,15 @@
{% load bootstrap3 %}
{% load i18n %}
<a class="btn btn-default btn-sm pull-right" accesskey="n" href="{% url 'editor.sections.create' %}">
{% trans 'Section' as model_title %}
<a class="btn btn-default btn-sm pull-right" accesskey="n" href="{% url 'editor.levels.create' %}">
{% trans 'Level' as model_title %}
{% blocktrans %}New {{ model_title }}{% endblocktrans %}
</a>
<h3>{% trans 'Sections' %}</h3>
<h3>{% trans 'Level' %}</h3>
<div class="list-group">
{% for s in sections %}
<a href="{% url 'editor.sections.detail' pk=s.pk %}" class="list-group-item">
{{ s.title }}
{% for l in levels %}
<a href="{% url 'editor.levels.detail' pk=l.pk %}" class="list-group-item">
{{ l.title }}
</a>
{% endfor %}
</div>

View file

@ -0,0 +1,42 @@
{% load bootstrap3 %}
{% load i18n %}
{% include 'editor/fragment_levels.html' %}
<a class="btn btn-default btn-sm pull-right" accesskey="e" href="{% url 'editor.levels.edit' pk=level.pk %}">
{% trans 'Level' as model_title %}
{% blocktrans %}Edit {{ model_title }}{% endblocktrans %}
</a>
<h3>
<h3>
{{ level.title }}
{% if level.on_top_of != None %}
{% with level.on_top_of.title as on_top_of_level_title %}
<small>{% blocktrans %}on top of {{ on_top_of_level_title }}{% endblocktrans %}</small>
{% endwith %}
{% endif %}
</h3>
<p>
{% if level.on_top_of == None %}
<a href="{% url 'editor.index' %}">&laquo; {% trans 'back to overview' %}</a>
{% else %}
<a href="{% url 'editor.levels.detail' pk=level.on_top_of.pk %}">&laquo; {% trans 'back to parent level' %}</a>
{% endif %}
</p>
{% include 'editor/fragment_child_models.html' %}
<div class="clearfix"></div>
{% if level.on_top_of == None %}
<a class="btn btn-default btn-sm pull-right" accesskey="n" href="{% url 'editor.levels_on_top.create' on_top_of=level.pk %}">
{% blocktrans %}New {{ model_title }}{% endblocktrans %}
</a>
<h3>{% trans 'Levels on top' %}</h3>
<div class="list-group">
{% for l in levels_on_top %}
<a href="{% url 'editor.levels.detail' pk=l.pk %}" class="list-group-item">
{{ l.title }}
</a>
{% endfor %}
</div>
{% endif %}

View file

@ -1,16 +1,16 @@
{% load bootstrap3 %}
{% load i18n %}
{% include 'editor/fragment_sections.html' %}
{% include 'editor/fragment_levels.html' %}
<a class="btn btn-default btn-sm pull-right" accesskey="n" href="{{ create_url }}">
{% blocktrans %}New {{ model_title }}{% endblocktrans %}
</a>
<h3>
{% blocktrans %}{{ model_title_plural }}{% endblocktrans %}
{% if section %}
{% with section.title as section_title %}
<small>{% blocktrans %}in section {{ section_title }}{% endblocktrans %}</small>
{% if level %}
{% with level.title as level_title %}
<small>{% blocktrans %}on level {{ level_title }}{% endblocktrans %}</small>
{% endwith %}
{% endif %}
{% if space %}

View file

@ -1,41 +0,0 @@
{% load bootstrap3 %}
{% load i18n %}
{% include 'editor/fragment_sections.html' %}
<a class="btn btn-default btn-sm pull-right" accesskey="e" href="{% url 'editor.sections.edit' pk=section.pk %}">
{% trans 'Section' as model_title %}
{% blocktrans %}Edit {{ model_title }}{% endblocktrans %}
</a>
<h3>
{{ section.title }}
{% if section.on_top_of != None %}
{% with section.on_top_of.title as on_top_of_section_title %}
<small>{% blocktrans %}on top of {{ on_top_of_section_title }}{% endblocktrans %}</small>
{% endwith %}
{% endif %}
</h3>
<p>
{% if section.on_top_of == None %}
<a href="{% url 'editor.index' %}">&laquo; {% trans 'back to overview' %}</a>
{% else %}
<a href="{% url 'editor.sections.detail' pk=section.on_top_of.pk %}">&laquo; {% trans 'back to parent section' %}</a>
{% endif %}
</p>
{% include 'editor/fragment_child_models.html' %}
<div class="clearfix"></div>
{% if section.on_top_of == None %}
<a class="btn btn-default btn-sm pull-right" accesskey="n" href="{% url 'editor.sections_on_top.create' on_top_of=section.pk %}">
{% blocktrans %}New {{ model_title }}{% endblocktrans %}
</a>
<h3>{% trans 'Sections on top' %}</h3>
<div class="list-group">
{% for s in sections_on_top %}
<a href="{% url 'editor.sections.detail' pk=s.pk %}" class="list-group-item">
{{ s.title }}
</a>
{% endfor %}
</div>
{% endif %}

View file

@ -1,14 +1,14 @@
{% load bootstrap3 %}
{% load i18n %}
{% include 'editor/fragment_sections.html' %}
{% include 'editor/fragment_levels.html' %}
<a class="btn btn-default btn-sm pull-right" accesskey="e" href="{% url 'editor.spaces.edit' section=space.section.pk pk=space.pk %}">
<a class="btn btn-default btn-sm pull-right" accesskey="e" href="{% url 'editor.spaces.edit' level=space.level.pk pk=space.pk %}">
{% trans 'Space' as model_title %}
{% blocktrans %}Edit {{ model_title }}{% endblocktrans %}
</a>
<h3>{{ space.title }}</h3>
<p>
<a href="{% url 'editor.spaces.list' section=space.section.pk %}">&laquo; {% trans 'back to overview' %}</a>
<a href="{% url 'editor.spaces.list' level=space.level.pk %}">&laquo; {% trans 'back to overview' %}</a>
</p>
{% include 'editor/fragment_child_models.html' %}

View file

@ -1,7 +1,7 @@
from django.apps import apps
from django.conf.urls import url
from c3nav.editor.views import edit, list_objects, main_index, section_detail, space_detail
from c3nav.editor.views import edit, level_detail, list_objects, main_index, space_detail
def add_editor_urls(model_name, parent_model_name=None, with_list=True, explicit_edit=False):
@ -30,17 +30,17 @@ def add_editor_urls(model_name, parent_model_name=None, with_list=True, explicit
urlpatterns = [
url(r'^$', main_index, name='editor.index'),
url(r'^sections/(?P<pk>[0-9]+)/$', section_detail, name='editor.sections.detail'),
url(r'^sections/(?P<section>[0-9]+)/spaces/(?P<pk>[0-9]+)/$', space_detail, name='editor.spaces.detail'),
url(r'^sections/(?P<on_top_of>[0-9]+)/sections_on_top/create$', edit, name='editor.sections_on_top.create',
kwargs={'model': 'Section'}),
url(r'^levels/(?P<pk>[0-9]+)/$', level_detail, name='editor.levels.detail'),
url(r'^levels/(?P<level>[0-9]+)/spaces/(?P<pk>[0-9]+)/$', space_detail, name='editor.spaces.detail'),
url(r'^levels/(?P<on_top_of>[0-9]+)/levels_on_top/create$', edit, name='editor.levels_on_top.create',
kwargs={'model': 'Level'}),
]
urlpatterns.extend(add_editor_urls('Section', with_list=False, explicit_edit=True))
urlpatterns.extend(add_editor_urls('Level', with_list=False, explicit_edit=True))
urlpatterns.extend(add_editor_urls('LocationGroup'))
urlpatterns.extend(add_editor_urls('Source'))
urlpatterns.extend(add_editor_urls('Building', 'Section'))
urlpatterns.extend(add_editor_urls('Space', 'Section', explicit_edit=True))
urlpatterns.extend(add_editor_urls('Door', 'Section'))
urlpatterns.extend(add_editor_urls('Building', 'Level'))
urlpatterns.extend(add_editor_urls('Space', 'Level', explicit_edit=True))
urlpatterns.extend(add_editor_urls('Door', 'Level'))
urlpatterns.extend(add_editor_urls('Hole', 'Space'))
urlpatterns.extend(add_editor_urls('Area', 'Space'))
urlpatterns.extend(add_editor_urls('Stair', 'Space'))

View file

@ -10,7 +10,7 @@ from django.urls import reverse
from django.utils.translation import ugettext_lazy as _
from django.views.decorators.cache import never_cache
from c3nav.mapdata.models import Section, Space
from c3nav.mapdata.models import Level, Space
from c3nav.mapdata.models.base import EDITOR_FORM_MODELS
@ -39,7 +39,7 @@ def child_model(model_name, kwargs=None, parent=None):
@sidebar_view
def main_index(request):
return render(request, 'editor/index.html', {
'sections': Section.objects.filter(on_top_of__isnull=True),
'levels': Level.objects.filter(on_top_of__isnull=True),
'child_models': [
child_model('LocationGroup'),
child_model('Source'),
@ -48,28 +48,28 @@ def main_index(request):
@sidebar_view
def section_detail(request, pk):
section = get_object_or_404(Section.objects.select_related('on_top_of'), pk=pk)
def level_detail(request, pk):
level = get_object_or_404(Level.objects.select_related('on_top_of'), pk=pk)
return render(request, 'editor/section.html', {
'sections': Section.objects.filter(on_top_of__isnull=True),
'section': section,
'section_url': 'editor.sections.detail',
'section_as_pk': True,
return render(request, 'editor/level.html', {
'levels': Level.objects.filter(on_top_of__isnull=True),
'level': level,
'level_url': 'editor.levels.detail',
'level_as_pk': True,
'child_models': [child_model(model_name, kwargs={'section': pk}, parent=section)
'child_models': [child_model(model_name, kwargs={'level': pk}, parent=level)
for model_name in ('Building', 'Space', 'Door')],
'sections_on_top': section.sections_on_top.all(),
'geometry_url': '/api/editor/geometries/?section='+str(section.primary_section_pk),
'levels_on_top': level.levels_on_top.all(),
'geometry_url': '/api/editor/geometries/?level='+str(level.primary_level_pk),
})
@sidebar_view
def space_detail(request, section, pk):
space = get_object_or_404(Space, section__id=section, pk=pk)
def space_detail(request, level, pk):
space = get_object_or_404(Space, level__id=level, pk=pk)
return render(request, 'editor/space.html', {
'section': space.section,
'level': space.level,
'space': space,
'child_models': [child_model(model_name, kwargs={'space': pk}, parent=space)
@ -79,7 +79,7 @@ def space_detail(request, section, pk):
@sidebar_view
def edit(request, pk=None, model=None, section=None, space=None, on_top_of=None, explicit_edit=False):
def edit(request, pk=None, model=None, level=None, space=None, on_top_of=None, explicit_edit=False):
model = EDITOR_FORM_MODELS[model]
related_name = model._meta.default_related_name
@ -87,19 +87,19 @@ def edit(request, pk=None, model=None, section=None, space=None, on_top_of=None,
if pk is not None:
# Edit existing map item
kwargs = {'pk': pk}
if section is not None:
kwargs.update({'section__id': section})
if level is not None:
kwargs.update({'level__id': level})
elif space is not None:
kwargs.update({'space__id': space})
obj = get_object_or_404(model, **kwargs)
if False: # todo can access
raise PermissionDenied
elif section is not None:
section = get_object_or_404(Section, pk=section)
elif level is not None:
level = get_object_or_404(Level, pk=level)
elif space is not None:
space = get_object_or_404(Space, pk=space)
elif on_top_of is not None:
on_top_of = get_object_or_404(Section.objects.filter(on_top_of__isnull=True), pk=on_top_of)
on_top_of = get_object_or_404(Level.objects.filter(on_top_of__isnull=True), pk=on_top_of)
new = obj is None
# noinspection PyProtectedMember
@ -117,55 +117,55 @@ def edit(request, pk=None, model=None, section=None, space=None, on_top_of=None,
'geomtype': model._meta.get_field('geometry').geomtype,
})
if model == Section:
if model == Level:
ctx.update({
'section': obj,
'back_url': reverse('editor.index') if new else reverse('editor.sections.detail', kwargs={'pk': pk}),
'level': obj,
'back_url': reverse('editor.index') if new else reverse('editor.levels.detail', kwargs={'pk': pk}),
})
if not new:
ctx.update({
'geometry_url': '/api/editor/geometries/?section='+str(obj.primary_section_pk),
'geometry_url': '/api/editor/geometries/?level='+str(obj.primary_level_pk),
'on_top_of': obj.on_top_of,
})
elif on_top_of:
ctx.update({
'geometry_url': '/api/editor/geometries/?section=' + str(on_top_of.pk),
'geometry_url': '/api/editor/geometries/?level=' + str(on_top_of.pk),
'on_top_of': on_top_of,
'back_url': reverse('editor.sections.detail', kwargs={'pk': on_top_of.pk}),
'back_url': reverse('editor.levels.detail', kwargs={'pk': on_top_of.pk}),
})
elif model == Space and not new:
section = obj.section
level = obj.level
ctx.update({
'section': obj.section,
'back_url': reverse('editor.spaces.detail', kwargs={'section': obj.section.pk, 'pk': pk}),
'level': obj.level,
'back_url': reverse('editor.spaces.detail', kwargs={'level': obj.level.pk, 'pk': pk}),
'geometry_url': '/api/editor/geometries/?space='+pk,
})
elif model == Space and new:
ctx.update({
'section': section,
'back_url': reverse('editor.spaces.list', kwargs={'section': section.pk}),
'geometry_url': '/api/editor/geometries/?section='+str(section.primary_section_pk),
'level': level,
'back_url': reverse('editor.spaces.list', kwargs={'level': level.pk}),
'geometry_url': '/api/editor/geometries/?level='+str(level.primary_level_pk),
})
elif hasattr(model, 'section'):
elif hasattr(model, 'level'):
if obj:
section = obj.section
level = obj.level
ctx.update({
'section': section,
'back_url': reverse('editor.'+related_name+'.list', kwargs={'section': section.pk}),
'geometry_url': '/api/editor/geometries/?section='+str(section.primary_section_pk),
'level': level,
'back_url': reverse('editor.'+related_name+'.list', kwargs={'level': level.pk}),
'geometry_url': '/api/editor/geometries/?level='+str(level.primary_level_pk),
})
elif hasattr(model, 'space'):
if obj:
space = obj.space
ctx.update({
'section': space.section,
'level': space.level,
'back_url': reverse('editor.'+related_name+'.list', kwargs={'space': space.pk}),
'geometry_url': '/api/editor/geometries/?space='+str(space.pk),
})
else:
kwargs = {}
if section is not None:
kwargs.update({'section': section})
if level is not None:
kwargs.update({'level': level})
elif space is not None:
kwargs.update({'space': space})
@ -181,12 +181,12 @@ def edit(request, pk=None, model=None, section=None, space=None, on_top_of=None,
# todo: suggest changes
raise NotImplementedError
obj.delete()
if model == Section:
if model == Level:
if obj.on_top_of_id is not None:
return redirect(reverse('editor.sections.detail', kwargs={'pk': obj.on_top_of_id}))
return redirect(reverse('editor.levels.detail', kwargs={'pk': obj.on_top_of_id}))
return redirect(reverse('editor.index'))
elif model == Space:
return redirect(reverse('editor.spaces.list', kwargs={'section': obj.section.pk}))
return redirect(reverse('editor.spaces.list', kwargs={'level': obj.level.pk}))
return redirect(ctx['back_url'])
ctx['obj_title'] = obj.title
return render(request, 'editor/delete.html', ctx)
@ -213,8 +213,8 @@ def edit(request, pk=None, model=None, section=None, space=None, on_top_of=None,
# todo: suggest changes
raise NotImplementedError
if section is not None:
obj.section = section
if level is not None:
obj.level = level
if space is not None:
obj.space = space
@ -237,7 +237,7 @@ def edit(request, pk=None, model=None, section=None, space=None, on_top_of=None,
@sidebar_view
def list_objects(request, model=None, section=None, space=None, explicit_edit=False):
def list_objects(request, model=None, level=None, space=None, explicit_edit=False):
model = EDITOR_FORM_MODELS[model]
if not request.resolver_match.url_name.endswith('.list'):
raise ValueError('url_name does not end with .list')
@ -254,25 +254,25 @@ def list_objects(request, model=None, section=None, space=None, explicit_edit=Fa
queryset = model.objects.all().order_by('id')
reverse_kwargs = {}
if section is not None:
reverse_kwargs['section'] = section
section = get_object_or_404(Section, pk=section)
queryset = queryset.filter(section=section)
if level is not None:
reverse_kwargs['level'] = level
level = get_object_or_404(Level, pk=level)
queryset = queryset.filter(level=level)
ctx.update({
'back_url': reverse('editor.sections.detail', kwargs={'pk': section.pk}),
'back_title': _('back to section'),
'sections': Section.objects.filter(on_top_of__isnull=True),
'section': section,
'section_url': request.resolver_match.url_name,
'geometry_url': '/api/editor/geometries/?section='+str(section.primary_section_pk),
'back_url': reverse('editor.levels.detail', kwargs={'pk': level.pk}),
'back_title': _('back to level'),
'levels': Level.objects.filter(on_top_of__isnull=True),
'level': level,
'level_url': request.resolver_match.url_name,
'geometry_url': '/api/editor/geometries/?level='+str(level.primary_level_pk),
})
elif space is not None:
reverse_kwargs['space'] = space
space = get_object_or_404(Space, pk=space)
queryset = queryset.filter(space=space)
ctx.update({
'section': space.section,
'back_url': reverse('editor.spaces.detail', kwargs={'section': space.section.pk, 'pk': space.pk}),
'level': space.level,
'back_url': reverse('editor.spaces.detail', kwargs={'level': space.level.pk, 'pk': space.pk}),
'back_title': _('back to space'),
'geometry_url': '/api/editor/geometries/?space='+str(space.pk),
})