fix(observatory): refine catalog and replay UX

This commit is contained in:
DCCONSTRUCTIONS
2026-08-30 20:36:12 +03:00
parent 023151c186
commit be83283ee0
18 changed files with 2137 additions and 201 deletions
+2
View File
@@ -144,6 +144,7 @@ from k1link.web.map_api import (
build_map_router,
)
from k1link.web.map_view_api import build_map_view_router
from k1link.web.observatory_api import build_observatory_router
from k1link.web.plugin_catalog import DevicePluginCatalog, PluginCatalogError
from k1link.web.plugin_runtime import (
STATE_READ_ACTION_ID,
@@ -691,6 +692,7 @@ app.include_router(
point_color_renderers=plugin_environment.point_color_renderers,
)
)
app.include_router(build_observatory_router(session_store))
app.include_router(
build_environment_router(root_provider=lambda: session_store.data_dir / "ui-environment")
)
+98
View File
@@ -0,0 +1,98 @@
from __future__ import annotations
from typing import Literal
from fastapi import APIRouter, HTTPException, Response
from pydantic import BaseModel, ConfigDict, Field
from k1link.sessions import SessionIntegrityError, SessionNotFoundError, SessionStore
OBSERVATORY_PROJECTION_SCHEMA: Literal[
"missioncore.observatory-lab-projection/v1"
] = "missioncore.observatory-lab-projection/v1"
OBSERVATORY_RENAME_SCHEMA: Literal[
"missioncore.observatory-lab-projection-rename/v1"
] = "missioncore.observatory-lab-projection-rename/v1"
class _StrictApiModel(BaseModel):
model_config = ConfigDict(extra="forbid")
class ObservatoryProjectionRenameRequest(_StrictApiModel):
schema_version: Literal[
"missioncore.observatory-lab-projection-rename/v1"
]
display_name: str = Field(min_length=1, max_length=160)
class ObservatoryProjectionDocument(_StrictApiModel):
schema_version: Literal["missioncore.observatory-lab-projection/v1"]
session_id: str
display_name: str
def build_observatory_router(store: SessionStore) -> APIRouter:
"""Build bounded catalog-only mutations for typed Observatory projections."""
router = APIRouter(tags=["observatory"])
@router.patch(
"/api/v1/observatory/lab-projections/{session_id}",
response_model=ObservatoryProjectionDocument,
)
def rename_observatory_lab_projection(
session_id: str,
request: ObservatoryProjectionRenameRequest,
) -> ObservatoryProjectionDocument:
try:
display_name = store.rename_capability_lab_projection(
session_id,
request.display_name,
)
except SessionNotFoundError as exc:
raise HTTPException(
status_code=404,
detail="Проекция Обсерватории не найдена.",
) from exc
except SessionIntegrityError as exc:
raise HTTPException(
status_code=409,
detail="Запись не является управляемой проекцией Обсерватории.",
) from exc
except ValueError as exc:
raise HTTPException(
status_code=422,
detail="Некорректные параметры проекции Обсерватории.",
) from exc
return ObservatoryProjectionDocument(
schema_version=OBSERVATORY_PROJECTION_SCHEMA,
session_id=session_id,
display_name=display_name,
)
@router.delete(
"/api/v1/observatory/lab-projections/{session_id}",
status_code=204,
)
def delete_observatory_lab_projection(session_id: str) -> Response:
try:
store.delete_capability_lab_projection(session_id)
except SessionNotFoundError as exc:
raise HTTPException(
status_code=404,
detail="Проекция Обсерватории не найдена.",
) from exc
except SessionIntegrityError as exc:
raise HTTPException(
status_code=409,
detail="Запись не является управляемой проекцией Обсерватории.",
) from exc
except ValueError as exc:
raise HTTPException(
status_code=422,
detail="Некорректный идентификатор проекции Обсерватории.",
) from exc
return Response(status_code=204)
return router