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
|
import json
|
||||||
from typing import Annotated, Union
|
from typing import Annotated, Union
|
||||||
|
|
||||||
|
from celery import chain
|
||||||
from django.core.serializers.json import DjangoJSONEncoder
|
from django.core.serializers.json import DjangoJSONEncoder
|
||||||
from django.db.models import Prefetch
|
from django.db.models import Prefetch
|
||||||
from django.shortcuts import redirect
|
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.schema import BaseSchema
|
||||||
from c3nav.api.utils import NonEmptyStr
|
from c3nav.api.utils import NonEmptyStr
|
||||||
from c3nav.mapdata.api.base import api_etag, api_stats, can_access_geometry
|
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 import Source, Theme, Area, Space
|
||||||
from c3nav.mapdata.models.geometry.space import ObstacleGroup, Obstacle
|
from c3nav.mapdata.models.geometry.space import ObstacleGroup, Obstacle
|
||||||
from c3nav.mapdata.models.locations import DynamicLocation, LocationRedirect, Position, LocationGroup
|
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,
|
LocationDisplay, ProjectionPipelineSchema, ProjectionSchema,
|
||||||
SlimListableLocationSchema, SlimLocationSchema, all_location_definitions,
|
SlimListableLocationSchema, SlimLocationSchema, all_location_definitions,
|
||||||
listable_location_definitions, LegendSchema, LegendItemSchema)
|
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,
|
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)
|
searchable_locations_for_request, visible_locations_for_request)
|
||||||
from c3nav.mapdata.utils.user import can_access_editor
|
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 = 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",
|
@map_api_router.get('/bounds/', summary="get boundaries",
|
||||||
description="get maximum boundaries of everything on the map",
|
description="get maximum boundaries of everything on the map",
|
||||||
response={200: WithBoundsSchema, **auth_responses})
|
response={200: WithBoundsSchema, **auth_responses})
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
import bisect
|
import bisect
|
||||||
import string
|
import string
|
||||||
from abc import ABC, abstractmethod
|
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 django.conf import settings
|
||||||
|
from ninja import Schema
|
||||||
|
|
||||||
|
|
||||||
class AbstractGrid(ABC):
|
class AbstractGrid(ABC):
|
||||||
|
@ -18,6 +20,13 @@ class AbstractGrid(ABC):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class GridSchema(Schema):
|
||||||
|
rows: Sequence[float]
|
||||||
|
cols: Sequence[float]
|
||||||
|
invert_x: bool
|
||||||
|
invert_y: bool
|
||||||
|
|
||||||
|
|
||||||
class Grid(AbstractGrid):
|
class Grid(AbstractGrid):
|
||||||
enabled = True
|
enabled = True
|
||||||
|
|
||||||
|
@ -41,6 +50,14 @@ class Grid(AbstractGrid):
|
||||||
else:
|
else:
|
||||||
raise ValueError('column coordinates are not ordered')
|
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):
|
def get_square_for_point(self, x, y):
|
||||||
x = bisect.bisect(self.cols, x)
|
x = bisect.bisect(self.cols, x)
|
||||||
if x <= 0 or x >= len(self.cols):
|
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 Field as APIField
|
||||||
from pydantic import PositiveInt
|
from pydantic import PositiveInt
|
||||||
|
|
||||||
from c3nav.api.schema import BaseSchema, GeometrySchema
|
from c3nav.api.schema import BaseSchema, GeometrySchema
|
||||||
|
from c3nav.mapdata.grid import GridSchema
|
||||||
from c3nav.mapdata.schemas.model_base import AnyLocationID, BoundsSchema
|
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):
|
class WithBoundsSchema(BaseSchema):
|
||||||
"""
|
"""
|
||||||
Describing a bounding box
|
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:
|
if grid.enabled:
|
||||||
ctx['grid'] = json.dumps({
|
ctx['grid'] = json.dumps(grid.serialize().model_dump(), separators=(',', ':'), cls=DjangoJSONEncoder)
|
||||||
'rows': grid.rows,
|
|
||||||
'cols': grid.cols,
|
|
||||||
'invert_x': grid.invert_x,
|
|
||||||
'invert_y': grid.invert_y,
|
|
||||||
}, separators=(',', ':'), cls=DjangoJSONEncoder)
|
|
||||||
|
|
||||||
csrf.get_token(request)
|
csrf.get_token(request)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue