add legend / color key API endpoint

This commit is contained in:
Laura Klünder 2024-09-06 15:07:54 +02:00
parent 839d4beb7c
commit d49b6d6645
4 changed files with 65 additions and 4 deletions

View file

@ -2,6 +2,7 @@ import json
from typing import Annotated, Union
from django.core.serializers.json import DjangoJSONEncoder
from django.db.models import Prefetch
from django.shortcuts import redirect
from django.utils import timezone
from ninja import Query
@ -15,14 +16,16 @@ from c3nav.api.exceptions import API404, APIPermissionDenied, APIRequestValidati
from c3nav.api.schema import BaseSchema
from c3nav.api.utils import NonEmptyStr
from c3nav.mapdata.api.base import api_etag, api_stats, can_access_geometry
from c3nav.mapdata.models import Source
from c3nav.mapdata.models.locations import DynamicLocation, LocationRedirect, Position
from c3nav.mapdata.models import Source, Theme, Area, Space
from c3nav.mapdata.models.geometry.space import ObstacleGroup, Obstacle
from c3nav.mapdata.models.locations import DynamicLocation, LocationRedirect, Position, LocationGroup
from c3nav.mapdata.render.theme import ColorManager
from c3nav.mapdata.schemas.filters import BySearchableFilter, RemoveGeometryFilter
from c3nav.mapdata.schemas.model_base import AnyLocationID, AnyPositionID, CustomLocationID
from c3nav.mapdata.schemas.models import (AnyPositionStatusSchema, FullListableLocationSchema, FullLocationSchema,
LocationDisplay, ProjectionPipelineSchema, ProjectionSchema,
SlimListableLocationSchema, SlimLocationSchema, all_location_definitions,
listable_location_definitions)
listable_location_definitions, LegendSchema, LegendItemSchema)
from c3nav.mapdata.schemas.responses import LocationGeometry, WithBoundsSchema
from c3nav.mapdata.utils.locations import (get_location_by_id_for_request, get_location_by_slug_for_request,
searchable_locations_for_request, visible_locations_for_request)
@ -329,3 +332,40 @@ def get_projection(request):
'rotation_matrix': settings.PROJECTION_ROTATION_MATRIX,
})
return obj
"""
Legend
"""
@map_api_router.get('/legend/{theme_id}/', summary="get legend",
description="Get legend / color key fo theme",
response={200: LegendSchema, **API404.dict(), **auth_responses})
@api_etag(permissions=True)
def legend_for_theme(request, theme_id: int):
try:
manager = ColorManager.for_theme(theme_id or None)
except Theme.DoesNotExist:
raise API404()
locationgroups = LocationGroup.qs_for_request(request).filter(in_legend=True).prefetch_related(
Prefetch('areas', Area.qs_for_request(request))
).prefetch_related(
Prefetch('spaces', Space.qs_for_request(request))
)
obstaclegroups = ObstacleGroup.objects.filter(
pk__in=set(Obstacle.qs_for_request(request).filter(group__isnull=False).values_list('group', flat=True)),
)
return LegendSchema(
base=[],
groups=[item for item in (LegendItemSchema(title=group.title,
fill=manager.locationgroup_fill_color(group),
border=manager.locationgroup_border_color(group))
for group in locationgroups if group.areas.all() or group.spaces.all())
if item.fill or item.border],
obstacles=[item for item in (LegendItemSchema(title=group.title,
fill=manager.obstaclegroup_fill_color(group),
border=manager.obstaclegroup_border_color(group))
for group in obstaclegroups)
if item.fill or item.border],
)

View file

@ -8,6 +8,8 @@ def forwards_func(apps, schema_editor):
for group in LocationGroup.objects.all():
group.in_legend = bool(group.color and (group.can_describe or group.can_search))
group.save()
ObstacleGroup = apps.get_model('mapdata', 'ObstacleGroup')
ObstacleGroup.objects.filter(color__isnull=False).update(in_legend=True)
class Migration(migrations.Migration):
@ -27,5 +29,10 @@ class Migration(migrations.Migration):
name='data',
field=models.JSONField(default=dict, verbose_name='Measurement list'),
),
migrations.AddField(
model_name='obstaclegroup',
name='in_legend',
field=models.BooleanField(default=False, verbose_name='show in legend (if color set)'),
),
migrations.RunPython(forwards_func, migrations.RunPython.noop),
]

View file

@ -13,7 +13,7 @@ from shapely.geometry import CAP_STYLE, JOIN_STYLE, mapping
from c3nav.mapdata.fields import GeometryField, I18nField
from c3nav.mapdata.grid import grid
from c3nav.mapdata.models import Space
from c3nav.mapdata.models import Space, Level
from c3nav.mapdata.models.access import AccessRestrictionMixin
from c3nav.mapdata.models.base import SerializableMixin, TitledMixin
from c3nav.mapdata.models.geometry.base import GeometryMixin
@ -182,6 +182,7 @@ class Ramp(SpaceGeometryMixin, models.Model):
class ObstacleGroup(TitledMixin, models.Model):
color = models.CharField(max_length=32, null=True, blank=True)
in_legend = models.BooleanField(default=False, verbose_name=_('show in legend (if color set)'))
class Meta:
verbose_name = _('Obstacle Group')

View file

@ -805,6 +805,7 @@ class ProjectionPipelineSchema(BaseSchema):
example='+proj=utm +zone=33 +ellps=GRS80 +units=m +no_defs'
)
class ProjectionSchema(ProjectionPipelineSchema):
proj4: NonEmptyStr = APIField(
title='proj4 string',
@ -836,3 +837,15 @@ class ProjectionSchema(ProjectionPipelineSchema):
0, 0, 0, 1
]
)
class LegendItemSchema(BaseSchema):
title: NonEmptyStr = APIField()
fill: str | None
border: str | None
class LegendSchema(BaseSchema):
base: list[LegendItemSchema]
groups: list[LegendItemSchema]
obstacles: list[LegendItemSchema]