diff --git a/src/c3nav/editor/forms.py b/src/c3nav/editor/forms.py index d2ef6dd3..4bc0743e 100644 --- a/src/c3nav/editor/forms.py +++ b/src/c3nav/editor/forms.py @@ -109,7 +109,7 @@ class MapitemFormMixin(ModelForm): def create_editor_form(mapitemtype): possible_fields = ['name', 'package', 'altitude', 'level', 'intermediate', 'levels', 'geometry', 'direction', 'elevator', 'button', 'crop_to_level', 'width', 'groups', 'override_altitude', - 'location_type', 'can_search', 'can_describe', 'routing_inclusion'] + 'location_type', 'can_search', 'can_describe', 'routing_inclusion', 'compiled_room'] existing_fields = [field.name for field in mapitemtype._meta.get_fields() if field.name in possible_fields] class EditorForm(MapitemFormMixin, ModelForm): diff --git a/src/c3nav/mapdata/api.py b/src/c3nav/mapdata/api.py index 6e5caa83..05e3acaa 100644 --- a/src/c3nav/mapdata/api.py +++ b/src/c3nav/mapdata/api.py @@ -169,9 +169,12 @@ class LocationViewSet(ViewSet): def list(self, request, **kwargs): locations = [] + locations += list(filter_queryset_by_access(request, LocationGroup.objects.filter(can_search=True, + compiled_room=True))) locations += sorted(filter_arealocations_by_access(request, AreaLocation.objects.filter(can_search=True)), key=AreaLocation.get_sort_key, reverse=True) - locations += list(filter_queryset_by_access(request, LocationGroup.objects.filter(can_search=True))) + locations += list(filter_queryset_by_access(request, LocationGroup.objects.filter(can_search=True, + compiled_room=False))) return Response([location.to_location_json() for location in locations]) def retrieve(self, request, name=None, **kwargs): diff --git a/src/c3nav/mapdata/migrations/0031_locationgroup_compiled_room.py b/src/c3nav/mapdata/migrations/0031_locationgroup_compiled_room.py new file mode 100644 index 00000000..dff71fbe --- /dev/null +++ b/src/c3nav/mapdata/migrations/0031_locationgroup_compiled_room.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.4 on 2016-12-23 21:29 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mapdata', '0030_remove_locationgroup_routing_inclusion'), + ] + + operations = [ + migrations.AddField( + model_name='locationgroup', + name='compiled_room', + field=models.BooleanField(default=False, verbose_name='describes a compiled room'), + ), + ] diff --git a/src/c3nav/mapdata/models/locations.py b/src/c3nav/mapdata/models/locations.py index 6508aa81..529dec0b 100644 --- a/src/c3nav/mapdata/models/locations.py +++ b/src/c3nav/mapdata/models/locations.py @@ -78,6 +78,7 @@ class LocationModelMixin(Location): class LocationGroup(LocationModelMixin, MapItem): titles = JSONField() can_search = models.BooleanField(default=True, verbose_name=_('can be searched')) + compiled_room = models.BooleanField(default=False, verbose_name=_('describes a compiled room')) class Meta: verbose_name = _('Location Group') @@ -88,13 +89,63 @@ class LocationGroup(LocationModelMixin, MapItem): def location_id(self): return 'g:'+self.name + def get_in_levels(self): + last_update = get_last_mapdata_update() + if last_update is None: + return self._get_in_levels() + + cache_key = 'c3nav__mapdata__locationgroup__in_levels__'+last_update.isoformat()+'__'+self.name, + in_levels = cache.get(cache_key) + if not in_levels: + in_levels = self._get_in_levels() + cache.set(cache_key, in_levels, 900) + + return in_levels + + def _get_in_levels(self): + level_ids = set() + in_levels = [] + for arealocation in self.arealocations.all(): + for area in arealocation.get_in_areas(): + if area.location_type == 'level' and area.id not in level_ids: + level_ids.add(area.id) + in_levels.append(area) + + in_levels = sorted(in_levels, key=lambda area: area.level.altitude) + return in_levels + @property def subtitle(self): + if self.compiled_room: + return ', '.join(area.title for area in self.get_in_levels()) return ungettext_lazy('%d location', '%d locations') % self.arealocations.count() def __str__(self): return self.title + @classmethod + def fromfile(cls, data, file_path): + kwargs = super().fromfile(data, file_path) + + if 'compiled_room' not in data: + raise ValueError('Missing compiled_room') + compiled_room = data['compiled_room'] + if not isinstance(compiled_room, bool): + raise ValueError('compiled_room has to be boolean!') + kwargs['compiled_room'] = compiled_room + + return kwargs + + def get_geojson_properties(self): + result = super().get_geojson_properties() + return result + + def tofile(self): + result = super().tofile() + result['compiled_room'] = self.compiled_room + result.move_to_end('geometry') + return result + class AreaLocation(LocationModelMixin, GeometryMapItemWithLevel): LOCATION_TYPES = ( @@ -137,7 +188,7 @@ class AreaLocation(LocationModelMixin, GeometryMapItemWithLevel): if last_update is None: return self._get_in_areas() - cache_key = 'c3nav__mapdata__location__in__areas__'+last_update.isoformat()+'__'+self.name, + cache_key = 'c3nav__mapdata__location__in_areas__'+last_update.isoformat()+'__'+self.name, in_areas = cache.get(cache_key) if not in_areas: in_areas = self._get_in_areas() @@ -160,7 +211,7 @@ class AreaLocation(LocationModelMixin, GeometryMapItemWithLevel): @property def subtitle(self): - return self.get_subtitle() + return self.get_subtitle(with_type=False) @property def subtitle_without_type(self): diff --git a/src/c3nav/mapdata/search.py b/src/c3nav/mapdata/search.py index 145ab616..0831aa90 100644 --- a/src/c3nav/mapdata/search.py +++ b/src/c3nav/mapdata/search.py @@ -38,13 +38,18 @@ def search_location(request, search): words = search.split(' ')[:10] + queryset = LocationGroup.objects.filter(can_seach=True, compiled_room=True) + if isinstance(location, LocationGroup): + queryset.exclude(name='g:' + location.name) + results += list(filter_words(filter_queryset_by_access(request, queryset), words)[:10]) + queryset = AreaLocation.objects.filter(can_seach=True) if isinstance(location, AreaLocation): queryset.exclude(name=location.name) results += sorted(filter_words(filter_arealocations_by_access(request, queryset), words), key=AreaLocation.get_sort_key, reverse=True) - queryset = LocationGroup.objects.filter(can_seach=True) + queryset = LocationGroup.objects.filter(can_seach=True, compiled_room=False) if isinstance(location, LocationGroup): queryset.exclude(name='g:'+location.name) results += list(filter_words(filter_queryset_by_access(request, queryset), words)[:10])