add Location.details_display()

This commit is contained in:
Laura Klünder 2017-11-02 13:35:58 +01:00
parent ba3e1e485e
commit 949b88389e
8 changed files with 114 additions and 78 deletions

View file

@ -1,17 +1,15 @@
import mimetypes
from collections import namedtuple
from functools import wraps
from operator import attrgetter
from django.core.cache import cache
from django.db.models import FieldDoesNotExist, Model, Prefetch
from django.db.models import Prefetch
from django.http import HttpResponse
from django.shortcuts import redirect
from django.urls import reverse
from django.utils.cache import get_conditional_response
from django.utils.http import quote_etag
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import get_language, get_language_info
from django.utils.translation import get_language
from rest_framework.decorators import detail_route, list_route
from rest_framework.exceptions import NotFound, ValidationError
from rest_framework.mixins import RetrieveModelMixin
@ -19,7 +17,7 @@ from rest_framework.response import Response
from rest_framework.viewsets import GenericViewSet, ReadOnlyModelViewSet, ViewSet
from c3nav.mapdata.models import AccessRestriction, Building, Door, Hole, LocationGroup, MapUpdate, Source, Space
from c3nav.mapdata.models.access import AccessPermission, AccessRestrictionMixin
from c3nav.mapdata.models.access import AccessPermission
from c3nav.mapdata.models.geometry.level import LevelGeometryMixin
from c3nav.mapdata.models.geometry.space import POI, Area, Column, LineObstacle, Obstacle, SpaceGeometryMixin, Stair
from c3nav.mapdata.models.level import Level
@ -301,78 +299,7 @@ class LocationViewSet(RetrieveModelMixin, GenericViewSet):
if isinstance(location, LocationRedirect):
return redirect('../' + location.target.slug + '/display/')
result = location.serialize(geometry=True)
display = [
(str(_('Type')), str(location.__class__._meta.verbose_name)),
(str(_('ID')), str(location.pk)),
]
for lang, title in sorted(location.titles.items(), key=lambda item: item[0] != get_language()):
language = _('Title ({lang})').format(lang=get_language_info(lang)['name_translated'])
display.append((language, title))
display.append((str(_('Slug')), str(location.get_slug())))
if isinstance(location, Level):
display.append((str(_('short label')), location.short_label))
if isinstance(location, LevelGeometryMixin):
display.append((str(_('Level')), {'slug': location.level.get_slug(), 'title': location.level.title}))
if isinstance(location, SpaceGeometryMixin):
display.append((str(_('Space')), {'slug': location.space.get_slug(), 'title': location.space.title}))
if isinstance(location, LocationGroup):
display.append((str(_('Category')), location.category.title))
if isinstance(location, AccessRestrictionMixin):
display.append((str(_('Access Restriction')),
location.access_restriction_id and location.access_restriction.title))
groupcategories = {}
if isinstance(location, SpecificLocation):
for group in location.groups.all():
groupcategories.setdefault(group.category, []).append(group)
for category, groups in sorted(groupcategories.items(), key=lambda item: item[0].priority, reverse=True):
display.append((category.title, tuple(
{'slug': group.get_slug(), 'title': group.title}
for group in sorted(groups, key=attrgetter('priority'), reverse=True)
)))
model: Model = location.__class__
for name in ('can_search', 'can_describe', 'color', 'outside', 'base_altitude', 'height', 'default_height',
'priority'):
try:
field = model._meta.get_field(name)
except FieldDoesNotExist:
continue
value = getattr(location, name)
if isinstance(value, bool):
value = _('Ja') if value else _('Nein')
display.append((str(field.verbose_name), value and str(value)))
editor_url = None
if isinstance(location, Level):
editor_url = reverse('editor.levels.detail', kwargs={'pk': location.pk})
elif isinstance(location, Space):
editor_url = reverse('editor.spaces.detail', kwargs={'level': location.level_id, 'pk': location.pk})
elif isinstance(location, Area):
editor_url = reverse('editor.areas.edit', kwargs={'space': location.space_id, 'pk': location.pk})
elif isinstance(location, POI):
editor_url = reverse('editor.pois.edit', kwargs={'space': location.space_id, 'pk': location.pk})
elif isinstance(location, LocationGroup):
editor_url = reverse('editor.locationgroups.edit', kwargs={'pk': location.pk})
result = {
'editor_url': editor_url,
'display': display,
'geometry': result['geometry'],
}
return Response(result)
return Response(location.details_display())
@list_route(methods=['get'])
@api_etag(permissions=False)

View file

@ -89,6 +89,13 @@ class AccessRestrictionMixin(SerializableMixin, models.Model):
result['access_restriction'] = self.access_restriction_id
return result
def details_display(self):
result = super().details_display()
result['display'].extend([
(str(_('Access Restriction')), self.access_restriction_id and self.access_restriction.title),
])
return result
@classmethod
def qs_for_request(cls, request, allow_none=False):
return cls.objects.filter(cls.q_for_request(request, allow_none=allow_none))

View file

@ -3,7 +3,7 @@ from collections import OrderedDict
from django.core.cache import cache
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import get_language
from django.utils.translation import get_language, get_language_info
from c3nav.mapdata.fields import JSONField
from c3nav.mapdata.models import MapUpdate
@ -32,6 +32,14 @@ class SerializableMixin(models.Model):
result['id'] = self.pk
return result
def details_display(self):
return {
'display': [
(str(_('Type')), str(self.__class__._meta.verbose_name)),
(str(_('ID')), str(self.pk)),
]
}
@property
def title(self):
return self._meta.verbose_name + ' ' + str(self.id)
@ -57,6 +65,13 @@ class TitledMixin(SerializableMixin, models.Model):
result['title'] = self.title
return result
def details_display(self):
result = super().details_display()
for lang, title in sorted(self.titles.items(), key=lambda item: item[0] != get_language()):
language = _('Title ({lang})').format(lang=get_language_info(lang)['name_translated'])
result['display'].append((language, title))
return result
@property
def title(self):
lang = get_language()

View file

@ -88,6 +88,11 @@ class GeometryMixin(SerializableMixin):
(int(math.ceil(self.maxx)), int(math.ceil(self.maxy))))
return result
def details_display(self):
result = super().details_display()
result['geometry'] = format_geojson(mapping(self.geometry), round=False)
return result
def get_shadow_geojson(self):
pass

View file

@ -4,6 +4,7 @@ from operator import attrgetter, itemgetter
import numpy as np
from django.db import models
from django.db.models import F
from django.urls import reverse
from django.utils.text import format_lazy
from django.utils.translation import ugettext_lazy as _
from scipy.sparse.csgraph._shortest_path import dijkstra
@ -43,6 +44,11 @@ class LevelGeometryMixin(GeometryMixin):
result['level'] = self.level_id
return result
def details_display(self):
result = super().details_display()
result['display'].insert(3, (str(_('Level')), {'slug': self.level.get_slug(), 'title': self.level.title}))
return result
@property
def subtitle(self):
base_subtitle = super().subtitle
@ -96,6 +102,15 @@ class Space(LevelGeometryMixin, SpecificLocation, models.Model):
result['height'] = None if self.height is None else float(str(self.height))
return result
def details_display(self):
result = super().details_display()
result['display'].extend([
(str(_('height')), self.height),
(str(_('outside only')), str(_('yes') if self.outside else _('no'))),
])
result['editor_url'] = reverse('editor.spaces.detail', kwargs={'level': self.level_id, 'pk': self.pk})
return result
class Door(LevelGeometryMixin, AccessRestrictionMixin, models.Model):
"""

View file

@ -1,4 +1,5 @@
from django.db import models
from django.urls import reverse
from django.utils.functional import cached_property
from django.utils.text import format_lazy
from django.utils.translation import ugettext_lazy as _
@ -52,6 +53,11 @@ class SpaceGeometryMixin(GeometryMixin):
self.geometry if force else self.get_changed_geometry()
))
def details_display(self):
result = super().details_display()
result['display'].insert(3, (str(_('Space')), {'slug': self.space.get_slug(), 'title': self.space.title}))
return result
def register_delete(self):
space = self.space
changed_geometries.register(space.level_id, space.geometry.intersection(self.geometry))
@ -88,6 +94,11 @@ class Area(SpaceGeometryMixin, SpecificLocation, models.Model):
result = super()._serialize(**kwargs)
return result
def details_display(self):
result = super().details_display()
result['editor_url'] = reverse('editor.areas.edit', kwargs={'space': self.space_id, 'pk': self.pk})
return result
class Stair(SpaceGeometryMixin, models.Model):
"""
@ -168,6 +179,11 @@ class POI(SpaceGeometryMixin, SpecificLocation, models.Model):
verbose_name_plural = _('Points of Interest')
default_related_name = 'pois'
def details_display(self):
result = super().details_display()
result['editor_url'] = reverse('editor.pois.edit', kwargs={'space': self.space_id, 'pk': self.pk})
return result
class Hole(SpaceGeometryMixin, models.Model):
"""

View file

@ -6,6 +6,7 @@ from operator import attrgetter, itemgetter
from django.conf import settings
from django.db import models
from django.db.models import Prefetch
from django.urls import reverse
from django.utils.functional import cached_property
from django.utils.translation import ugettext_lazy as _
from shapely.geometry import JOIN_STYLE, box
@ -88,6 +89,16 @@ class Level(SpecificLocation, models.Model):
result['default_height'] = float(str(self.default_height))
return result
def details_display(self):
result = super().details_display()
result['display'].insert(3, (str(_('short label')), self.short_label))
result['display'].extend([
(str(_('outside only')), self.base_altitude),
(str(_('default height')), self.default_height),
])
result['editor_url'] = reverse('editor.levels.detail', kwargs={'pk': self.pk})
return result
def _render_space_ground(self, svg, space):
areas_by_color = {}
for area in space.areas.all():

View file

@ -1,8 +1,10 @@
from collections import OrderedDict
from contextlib import suppress
from operator import attrgetter
from django.db import models
from django.db.models import Prefetch
from django.urls import reverse
from django.utils.functional import cached_property
from django.utils.text import format_lazy
from django.utils.translation import ugettext_lazy as _
@ -57,6 +59,11 @@ class LocationSlug(SerializableMixin, models.Model):
result['slug'] = self.get_slug()
return result
def details_display(self):
result = super().details_display()
result['display'].insert(2, (str(_('Slug')), str(self.get_slug())))
return result
@cached_property
def order(self):
return (-1, 0)
@ -94,6 +101,14 @@ class Location(LocationSlug, AccessRestrictionMixin, TitledMixin, models.Model):
result['can_describe'] = self.can_search
return result
def details_display(self):
result = super().details_display()
result['display'].extend([
(str(_('can be searched')), str(_('yes') if self.can_search else _('no'))),
(str(_('can describe')), str(_('yes') if self.can_describe else _('no')))
])
return result
def get_slug(self):
if self.slug is None:
code = self.LOCATION_TYPE_CODES.get(self.__class__.__name__)
@ -139,6 +154,21 @@ class SpecificLocation(Location, models.Model):
result['groups'] = groups
return result
def details_display(self):
result = super().details_display()
groupcategories = {}
for group in self.groups.all():
groupcategories.setdefault(group.category, []).append(group)
for category, groups in sorted(groupcategories.items(), key=lambda item: item[0].priority):
result['display'].insert(3, (category.title, tuple(
{'slug': group.get_slug(), 'title': group.title}
for group in sorted(groups, key=attrgetter('priority'), reverse=True)
)))
return result
@property
def subtitle(self):
groups = tuple(self.groups.all())
@ -230,6 +260,16 @@ class LocationGroup(Location, models.Model):
result['locations'] = tuple(obj.pk for obj in getattr(self, 'locations', ()))
return result
def details_display(self):
result = super().details_display()
result['display'].insert(3, (str(_('Category')), self.category.title))
result['display'].extend([
(str(_('color')), self.color),
(str(_('priority')), self.priority),
])
result['editor_url'] = reverse('editor.locationgroups.edit', kwargs={'pk': self.pk})
return result
@property
def title_for_forms(self):
attributes = []