map settings api endpoint (fixes #201)
This commit is contained in:
parent
35a8738424
commit
d254f199e3
4 changed files with 66 additions and 9 deletions
|
@ -1,6 +1,7 @@
|
|||
import json
|
||||
from typing import Annotated, Union
|
||||
|
||||
from celery import chain
|
||||
from django.core.serializers.json import DjangoJSONEncoder
|
||||
from django.db.models import Prefetch
|
||||
from django.shortcuts import redirect
|
||||
|
@ -16,6 +17,7 @@ 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.grid import grid
|
||||
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
|
||||
|
@ -26,7 +28,7 @@ from c3nav.mapdata.schemas.models import (AnyPositionStatusSchema, FullListableL
|
|||
LocationDisplay, ProjectionPipelineSchema, ProjectionSchema,
|
||||
SlimListableLocationSchema, SlimLocationSchema, all_location_definitions,
|
||||
listable_location_definitions, LegendSchema, LegendItemSchema)
|
||||
from c3nav.mapdata.schemas.responses import LocationGeometry, WithBoundsSchema
|
||||
from c3nav.mapdata.schemas.responses import LocationGeometry, WithBoundsSchema, MapSettingsSchema
|
||||
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)
|
||||
from c3nav.mapdata.utils.user import can_access_editor
|
||||
|
@ -34,6 +36,25 @@ from c3nav.mapdata.utils.user import can_access_editor
|
|||
map_api_router = APIRouter(tags=["map"])
|
||||
|
||||
|
||||
@map_api_router.get('/settings/', summary="get map settings",
|
||||
description="get useful/required settings for displaying the map",
|
||||
response={200: MapSettingsSchema, **auth_responses})
|
||||
@api_etag(permissions=False)
|
||||
def map_settings(request):
|
||||
initial_bounds = settings.INITIAL_BOUNDS
|
||||
if not initial_bounds:
|
||||
initial_bounds = tuple(chain(*Source.max_bounds()))
|
||||
else:
|
||||
initial_bounds = (tuple(settings.INITIAL_BOUNDS)[:2], tuple(settings.INITIAL_BOUNDS)[2:])
|
||||
|
||||
return MapSettingsSchema(
|
||||
initial_bounds=initial_bounds,
|
||||
initial_level=settings.INITIAL_LEVEL or None,
|
||||
grid=grid.serialize().model_dump() if grid else None,
|
||||
tile_server=settings.TILE_CACHE_SERVER,
|
||||
)
|
||||
|
||||
|
||||
@map_api_router.get('/bounds/', summary="get boundaries",
|
||||
description="get maximum boundaries of everything on the map",
|
||||
response={200: WithBoundsSchema, **auth_responses})
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import bisect
|
||||
import string
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Optional
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Optional, ClassVar, Sequence
|
||||
|
||||
from django.conf import settings
|
||||
from ninja import Schema
|
||||
|
||||
|
||||
class AbstractGrid(ABC):
|
||||
|
@ -18,6 +20,13 @@ class AbstractGrid(ABC):
|
|||
pass
|
||||
|
||||
|
||||
class GridSchema(Schema):
|
||||
rows: Sequence[float]
|
||||
cols: Sequence[float]
|
||||
invert_x: bool
|
||||
invert_y: bool
|
||||
|
||||
|
||||
class Grid(AbstractGrid):
|
||||
enabled = True
|
||||
|
||||
|
@ -41,6 +50,14 @@ class Grid(AbstractGrid):
|
|||
else:
|
||||
raise ValueError('column coordinates are not ordered')
|
||||
|
||||
def serialize(self) -> GridSchema:
|
||||
return GridSchema(
|
||||
rows=self.rows,
|
||||
cols=self.cols,
|
||||
invert_x=self.invert_y,
|
||||
invert_y=self.invert_y,
|
||||
)
|
||||
|
||||
def get_square_for_point(self, x, y):
|
||||
x = bisect.bisect(self.cols, x)
|
||||
if x <= 0 or x >= len(self.cols):
|
||||
|
|
|
@ -1,12 +1,36 @@
|
|||
from typing import Annotated, Union
|
||||
from typing import Annotated, Union, Optional
|
||||
|
||||
from pydantic import Field as APIField
|
||||
from pydantic import PositiveInt
|
||||
|
||||
from c3nav.api.schema import BaseSchema, GeometrySchema
|
||||
from c3nav.mapdata.grid import GridSchema
|
||||
from c3nav.mapdata.schemas.model_base import AnyLocationID, BoundsSchema
|
||||
|
||||
|
||||
class MapSettingsSchema(BaseSchema):
|
||||
"""
|
||||
various c3nav instance settings
|
||||
"""
|
||||
initial_bounds: Optional[BoundsSchema] = APIField(
|
||||
title="initial boundaries",
|
||||
description="(left, bottom) to (top, right)",
|
||||
)
|
||||
initial_level: Optional[PositiveInt] = APIField(
|
||||
title="initial level id",
|
||||
description="the level id that is intially shown when opening the map",
|
||||
)
|
||||
|
||||
grid: Optional[GridSchema] = APIField(
|
||||
title="grid config",
|
||||
description="grid configuration, if available",
|
||||
)
|
||||
tile_server: Optional[str] = APIField(
|
||||
title="tile server base URL",
|
||||
description="tile server base URL to use, if configured",
|
||||
)
|
||||
|
||||
|
||||
class WithBoundsSchema(BaseSchema):
|
||||
"""
|
||||
Describing a bounding box
|
||||
|
|
|
@ -217,12 +217,7 @@ def map_index(request, mode=None, slug=None, slug2=None, details=None, options=N
|
|||
}
|
||||
|
||||
if grid.enabled:
|
||||
ctx['grid'] = json.dumps({
|
||||
'rows': grid.rows,
|
||||
'cols': grid.cols,
|
||||
'invert_x': grid.invert_x,
|
||||
'invert_y': grid.invert_y,
|
||||
}, separators=(',', ':'), cls=DjangoJSONEncoder)
|
||||
ctx['grid'] = json.dumps(grid.serialize().model_dump(), separators=(',', ':'), cls=DjangoJSONEncoder)
|
||||
|
||||
csrf.get_token(request)
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue