add editor API stubs
This commit is contained in:
parent
9738ea23ba
commit
bf2dd3b33b
6 changed files with 231 additions and 0 deletions
|
@ -54,6 +54,10 @@ ninja_api = c3navAPI(
|
||||||
"name": "mapdata",
|
"name": "mapdata",
|
||||||
"description": "Access the raw map data",
|
"description": "Access the raw map data",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "editor",
|
||||||
|
"description": "Endpoints for the editor and to interface with the editor",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "mesh",
|
"name": "mesh",
|
||||||
"description": "Manage the location node mesh network",
|
"description": "Manage the location node mesh network",
|
||||||
|
|
|
@ -36,6 +36,16 @@ class LineStringSchema(Schema):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class LineSchema(Schema):
|
||||||
|
"""
|
||||||
|
A GeoJSON LineString with only two points
|
||||||
|
"""
|
||||||
|
type: Literal["LineString"]
|
||||||
|
coordinates: tuple[tuple[float, float], tuple[float, float]] = APIField(
|
||||||
|
example=[[1.5, 1.5], [5, 8.7]]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class PointSchema(Schema):
|
class PointSchema(Schema):
|
||||||
"""
|
"""
|
||||||
A GeoJSON Point
|
A GeoJSON Point
|
||||||
|
|
|
@ -12,6 +12,7 @@ from c3nav.api.api import SessionViewSet
|
||||||
from c3nav.api.newapi import auth_api_router
|
from c3nav.api.newapi import auth_api_router
|
||||||
from c3nav.api.ninja import ninja_api
|
from c3nav.api.ninja import ninja_api
|
||||||
from c3nav.editor.api import ChangeSetViewSet, EditorViewSet
|
from c3nav.editor.api import ChangeSetViewSet, EditorViewSet
|
||||||
|
from c3nav.editor.newapi.endpoints import editor_api_router
|
||||||
from c3nav.mapdata.api import (AccessRestrictionGroupViewSet, AccessRestrictionViewSet, AreaViewSet, BuildingViewSet,
|
from c3nav.mapdata.api import (AccessRestrictionGroupViewSet, AccessRestrictionViewSet, AreaViewSet, BuildingViewSet,
|
||||||
ColumnViewSet, CrossDescriptionViewSet, DoorViewSet, DynamicLocationPositionViewSet,
|
ColumnViewSet, CrossDescriptionViewSet, DoorViewSet, DynamicLocationPositionViewSet,
|
||||||
HoleViewSet, LeaveDescriptionViewSet, LevelViewSet, LineObstacleViewSet,
|
HoleViewSet, LeaveDescriptionViewSet, LevelViewSet, LineObstacleViewSet,
|
||||||
|
@ -34,6 +35,7 @@ ninja_api.add_router("/map/", map_api_router)
|
||||||
ninja_api.add_router("/routing/", routing_api_router)
|
ninja_api.add_router("/routing/", routing_api_router)
|
||||||
ninja_api.add_router("/positioning/", positioning_api_router)
|
ninja_api.add_router("/positioning/", positioning_api_router)
|
||||||
ninja_api.add_router("/mapdata/", mapdata_api_router)
|
ninja_api.add_router("/mapdata/", mapdata_api_router)
|
||||||
|
ninja_api.add_router("/editor/", editor_api_router)
|
||||||
ninja_api.add_router("/mesh/", mesh_api_router)
|
ninja_api.add_router("/mesh/", mesh_api_router)
|
||||||
|
|
||||||
|
|
||||||
|
|
0
src/c3nav/editor/newapi/__init__.py
Normal file
0
src/c3nav/editor/newapi/__init__.py
Normal file
111
src/c3nav/editor/newapi/endpoints.py
Normal file
111
src/c3nav/editor/newapi/endpoints.py
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
from datetime import datetime
|
||||||
|
from typing import Annotated, Optional, Literal, Union
|
||||||
|
|
||||||
|
from django.db import IntegrityError, transaction
|
||||||
|
from ninja import Field as APIField
|
||||||
|
from ninja import Query
|
||||||
|
from ninja import Router as APIRouter
|
||||||
|
from ninja import Schema, UploadedFile
|
||||||
|
from ninja.pagination import paginate
|
||||||
|
from pydantic import PositiveInt, field_validator
|
||||||
|
|
||||||
|
from c3nav.api.exceptions import API404, APIConflict, APIRequestValidationFailed
|
||||||
|
from c3nav.api.newauth import APITokenAuth, auth_permission_responses, auth_responses, validate_responses
|
||||||
|
from c3nav.api.schema import GeometrySchema, LineSchema
|
||||||
|
from c3nav.api.utils import NonEmptyStr
|
||||||
|
from c3nav.editor.newapi.schemas import GeometryStylesSchema, EditorID, EditorSpaceGeometriesElemSchema, \
|
||||||
|
EditorLevelGeometriesElemSchema, UpdateCacheKey
|
||||||
|
from c3nav.mapdata.models import Source
|
||||||
|
from c3nav.mapdata.newapi.base import newapi_etag
|
||||||
|
from c3nav.mapdata.schemas.responses import BoundsSchema
|
||||||
|
from c3nav.mesh.dataformats import BoardType, ChipType, FirmwareImage
|
||||||
|
from c3nav.mesh.messages import MeshMessageType
|
||||||
|
from c3nav.mesh.models import FirmwareBuild, FirmwareVersion, NodeMessage
|
||||||
|
|
||||||
|
editor_api_router = APIRouter(tags=["editor"], auth=APITokenAuth(permissions={"editor_access"}))
|
||||||
|
|
||||||
|
|
||||||
|
@editor_api_router.get('/bounds/', summary="Get editor map boundaries",
|
||||||
|
response={200: BoundsSchema, **auth_permission_responses})
|
||||||
|
@newapi_etag()
|
||||||
|
def bounds(request):
|
||||||
|
return {
|
||||||
|
"bounds": Source.max_bounds(),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@editor_api_router.get('/geometrystyles/', summary="get the default colors for each geometry type",
|
||||||
|
response={200: GeometryStylesSchema, **auth_permission_responses})
|
||||||
|
@newapi_etag(permissions=False)
|
||||||
|
def geometrystyles():
|
||||||
|
return {
|
||||||
|
'building': '#aaaaaa',
|
||||||
|
'space': '#eeeeee',
|
||||||
|
'hole': 'rgba(255, 0, 0, 0.3)',
|
||||||
|
'door': '#ffffff',
|
||||||
|
'area': '#55aaff',
|
||||||
|
'stair': '#a000a0',
|
||||||
|
'ramp': 'rgba(160, 0, 160, 0.2)',
|
||||||
|
'obstacle': '#999999',
|
||||||
|
'lineobstacle': '#999999',
|
||||||
|
'column': 'rgba(0, 0, 50, 0.3)',
|
||||||
|
'poi': '#4488cc',
|
||||||
|
'shadow': '#000000',
|
||||||
|
'graphnode': '#009900',
|
||||||
|
'graphedge': '#00CC00',
|
||||||
|
'altitudemarker': '#0000FF',
|
||||||
|
'wifimeasurement': '#DDDD00',
|
||||||
|
'rangingbeacon': '#CC00CC',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@editor_api_router.get('/geometries/space/{space_id}/', summary="get the geometries to display for a space",
|
||||||
|
response={200: list[EditorSpaceGeometriesElemSchema], **API404.dict(),
|
||||||
|
**auth_permission_responses})
|
||||||
|
@newapi_etag() # todo: correct?
|
||||||
|
def space_geometries(space_id: EditorID, update_cache_key: UpdateCacheKey = None):
|
||||||
|
"""
|
||||||
|
look. this is a complex mess. there will hopefully be more documentation soon. or a better endpoint.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
@editor_api_router.get('/geometries/level/{level_id}/', summary="get the geometries to display for a level",
|
||||||
|
response={200: list[EditorLevelGeometriesElemSchema], **API404.dict(),
|
||||||
|
**auth_permission_responses})
|
||||||
|
@newapi_etag() # todo: correct?
|
||||||
|
def level_geometries(level_id: EditorID, update_cache_key: UpdateCacheKey = None):
|
||||||
|
"""
|
||||||
|
look. this is a complex mess. there will hopefully be more documentation soon. or a better endpoint.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
# todo: need a way to pass the changeset if it's not a session API key
|
||||||
|
|
||||||
|
|
||||||
|
@editor_api_router.get('/{path:path}/', summary="access the editor UI programmatically",
|
||||||
|
response={200: dict, **API404.dict(), **auth_permission_responses})
|
||||||
|
@newapi_etag() # todo: correct?
|
||||||
|
def view_as_api(path: str):
|
||||||
|
"""
|
||||||
|
get editor views rendered as JSON instead of HTML.
|
||||||
|
`path` is the path after /editor/.
|
||||||
|
this is a mess. good luck. if you actually want to use this, poke us so we might add better documentation.
|
||||||
|
"""
|
||||||
|
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
@editor_api_router.post('/{path:path}/', summary="access the editor UI programmatically",
|
||||||
|
response={200: dict, **API404.dict(), **auth_permission_responses})
|
||||||
|
@newapi_etag() # todo: correct?
|
||||||
|
def view_as_api(path: str):
|
||||||
|
"""
|
||||||
|
get editor views rendered as JSON instead of HTML.
|
||||||
|
`path` is the path after /editor/.
|
||||||
|
this is a mess. good luck. if you actually want to use this, poke us so we might add better documentation.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
104
src/c3nav/editor/newapi/schemas.py
Normal file
104
src/c3nav/editor/newapi/schemas.py
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
from typing import Annotated, Union, Literal, Optional
|
||||||
|
|
||||||
|
from ninja import Schema
|
||||||
|
from pydantic import Field as APIField, PositiveInt
|
||||||
|
|
||||||
|
from c3nav.api.schema import LineSchema, GeometrySchema
|
||||||
|
from c3nav.api.utils import NonEmptyStr
|
||||||
|
|
||||||
|
GeometryStylesSchema = Annotated[
|
||||||
|
dict[
|
||||||
|
Annotated[str, APIField(title="feature type")],
|
||||||
|
Annotated[str, APIField(title="color")]
|
||||||
|
],
|
||||||
|
APIField(description="mapping with a color for each feature type")
|
||||||
|
]
|
||||||
|
EditorID = Union[
|
||||||
|
Annotated[PositiveInt, APIField(title="an existing object that might have been modified in this changeset")],
|
||||||
|
Annotated[str, APIField(pattern="^c:[0-9]+$", title="an object that was created in this changeset")],
|
||||||
|
]
|
||||||
|
EditorGeometriesUpdateCacheKeyElem = Annotated[
|
||||||
|
tuple[
|
||||||
|
Literal["update_cache_key"],
|
||||||
|
Annotated[NonEmptyStr, APIField(title="the new cache key")],
|
||||||
|
],
|
||||||
|
APIField(
|
||||||
|
title="new cache key", # todo better explanation
|
||||||
|
description="the first element of the list, it informs you of the cache key to store these geometries under"
|
||||||
|
)
|
||||||
|
]
|
||||||
|
EditorGeometriesCacheReferenceElem = Annotated[
|
||||||
|
tuple[
|
||||||
|
Annotated[NonEmptyStr, APIField(title="geometry type")],
|
||||||
|
Annotated[EditorID, APIField(title="geometry id")], # this could be an editor id, right?
|
||||||
|
],
|
||||||
|
APIField(
|
||||||
|
title="reference to a cached geometry", # todo better explanation
|
||||||
|
description="replaces an element that has not changed from the cache key you supplied. get it from your cache."
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class BaseEditorGeometriesPropertiesSchema(Schema):
|
||||||
|
id: EditorID
|
||||||
|
type: NonEmptyStr
|
||||||
|
bounds: bool = False
|
||||||
|
color: Optional[str] = None
|
||||||
|
opacity: Optional[float] = None # todo: range
|
||||||
|
|
||||||
|
|
||||||
|
class EditorGeometriesGraphEdgePropertiesSchema(Schema):
|
||||||
|
id: EditorID
|
||||||
|
type: Literal["graphedge"]
|
||||||
|
from_node: EditorID
|
||||||
|
to_node: EditorID
|
||||||
|
|
||||||
|
|
||||||
|
class EditorSpaceGeometriesPropertiesSchema(BaseEditorGeometriesPropertiesSchema):
|
||||||
|
space: EditorID
|
||||||
|
|
||||||
|
|
||||||
|
class EditorLevelGeometriesPropertiesSchema(BaseEditorGeometriesPropertiesSchema):
|
||||||
|
level: EditorID
|
||||||
|
|
||||||
|
|
||||||
|
class EditorGeometriesGraphEdgeElemSchema(Schema):
|
||||||
|
type: Literal["Feature"]
|
||||||
|
properties: EditorGeometriesGraphEdgePropertiesSchema
|
||||||
|
geometry: LineSchema
|
||||||
|
|
||||||
|
|
||||||
|
class BaseEditorGeometriesGeometryElemSchema(Schema):
|
||||||
|
type: Literal["Feature"]
|
||||||
|
geometry: GeometrySchema = APIField(description="geometry, potentially modified for displaying")
|
||||||
|
original_geometry: Optional[GeometrySchema] = APIField(
|
||||||
|
default=None,
|
||||||
|
description="original unchanged geometry, not modified, original(??)", # todo: more precise
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class EditorSpaceGeometriesGeometryElemSchema(BaseEditorGeometriesGeometryElemSchema):
|
||||||
|
properties: EditorSpaceGeometriesPropertiesSchema
|
||||||
|
|
||||||
|
|
||||||
|
class EditorLevelGeometriesGeometryElemSchema(BaseEditorGeometriesGeometryElemSchema):
|
||||||
|
properties: EditorLevelGeometriesPropertiesSchema
|
||||||
|
|
||||||
|
|
||||||
|
EditorSpaceGeometriesElemSchema = Union[
|
||||||
|
EditorGeometriesUpdateCacheKeyElem,
|
||||||
|
Annotated[EditorSpaceGeometriesGeometryElemSchema, APIField(title="a geometry object")],
|
||||||
|
Annotated[EditorGeometriesGraphEdgeElemSchema, APIField(title="a graph edge")],
|
||||||
|
EditorGeometriesCacheReferenceElem,
|
||||||
|
]
|
||||||
|
EditorLevelGeometriesElemSchema = Union[
|
||||||
|
EditorGeometriesUpdateCacheKeyElem,
|
||||||
|
Annotated[EditorLevelGeometriesGeometryElemSchema, APIField(title="a geometry object")],
|
||||||
|
Annotated[EditorGeometriesGraphEdgeElemSchema, APIField(title="a graph edge")],
|
||||||
|
EditorGeometriesCacheReferenceElem,
|
||||||
|
]
|
||||||
|
|
||||||
|
UpdateCacheKey = Annotated[
|
||||||
|
Optional[NonEmptyStr],
|
||||||
|
APIField(default=None, pattern="^c:[0-9]+$", title="the cache key under which you have cached objects"),
|
||||||
|
]
|
Loading…
Add table
Add a link
Reference in a new issue