Fix map basestyle with static_ul

This commit is contained in:
phil 2024-12-22 02:41:56 +01:00
parent 244194e832
commit ac53f655e2
4 changed files with 76 additions and 51 deletions

View file

@ -32,6 +32,7 @@ dependencies = [
"websockets>=12.0", "websockets>=12.0",
"pyxdg>=0.28", "pyxdg>=0.28",
"typer-slim>=0.15.1", "typer-slim>=0.15.1",
"httpx>=0.28.1",
] ]
requires-python = ">=3.12" requires-python = ">=3.12"
readme = "README.md" readme = "README.md"
@ -62,5 +63,4 @@ dev-dependencies = [
"types-python-jose>=3.3.4.20240106", "types-python-jose>=3.3.4.20240106",
"types-passlib>=1.7.7.20240311", "types-passlib>=1.7.7.20240311",
"pytest>=8.3.4", "pytest>=8.3.4",
"httpx>=0.28.1",
] ]

View file

@ -1,15 +1,21 @@
from collections import OrderedDict, defaultdict from collections import OrderedDict, defaultdict
import logging import logging
from json import dumps from json import dumps, loads
from fastapi import (APIRouter, Request, HTTPException, from httpx import AsyncClient
Response, status) from fastapi import APIRouter, Request, HTTPException, Response, status
from sqlalchemy.orm import selectinload from sqlalchemy.orm import selectinload
from sqlalchemy.exc import NoResultFound from sqlalchemy.exc import NoResultFound
from sqlmodel import select from sqlmodel import select
from gisaf.models.map_bases import (BaseMap, BaseMapLayer, BaseMapWithStores, from gisaf.models.map_bases import (
BaseStyle, MapInitData, MaplibreStyle) BaseMap,
BaseMapLayer,
BaseMapWithStores,
BaseStyle,
MapInitData,
MaplibreStyle,
)
from gisaf.models.misc import Qml from gisaf.models.misc import Qml
from gisaf.registry import registry from gisaf.registry import registry
from gisaf.database import db_session, fastapi_db_session from gisaf.database import db_session, fastapi_db_session
@ -24,25 +30,31 @@ api = APIRouter(
# responses={404: {"description": "Not found"}}, # responses={404: {"description": "Not found"}},
) )
async def get_base_styles(): async def get_base_styles():
async with db_session() as session: async with db_session() as session:
query = select(BaseStyle.name)\ query = (
.where(BaseStyle.enabled==True)\ select(BaseStyle.name)
.order_by(BaseStyle.id) # type: ignore # noqa: E712 .where(BaseStyle.enabled == True)
.order_by(BaseStyle.id)
) # type: ignore # noqa: E712
data = await session.exec(query) data = await session.exec(query)
base_styles = data.all() base_styles = data.all()
## TODO: tiles_registry ## TODO: tiles_registry
logger.warning('TODO: tiles_registry') logger.warning("TODO: tiles_registry")
# base_styles.extend(tiles_registry.mbtiles.values()) # base_styles.extend(tiles_registry.mbtiles.values())
return [BaseStyle(name=bs) for bs in base_styles] # type: ignore return [BaseStyle(name=bs) for bs in base_styles] # type: ignore
async def get_base_maps() -> list[BaseMapWithStores]: async def get_base_maps() -> list[BaseMapWithStores]:
async with db_session() as session: async with db_session() as session:
query1 = select(BaseMap) #.options(selectinload(BaseMap.layers)) # type: ignore query1 = select(
BaseMap
) # .options(selectinload(BaseMap.layers)) # type: ignore
data1 = await session.exec(query1) data1 = await session.exec(query1)
base_maps = data1.all() base_maps = data1.all()
base_map_dict = {bm.id: bm.name for bm in base_maps} base_map_dict = {bm.id: bm.name for bm in base_maps}
query2 = select(BaseMapLayer).options(selectinload(BaseMapLayer.base_map)) # type: ignore query2 = select(BaseMapLayer).options(selectinload(BaseMapLayer.base_map)) # type: ignore
data2 = await session.exec(query2) data2 = await session.exec(query2)
base_map_layers = data2.all() base_map_layers = data2.all()
bms: dict[str, list] = defaultdict(list) bms: dict[str, list] = defaultdict(list)
@ -54,23 +66,28 @@ async def get_base_maps() -> list[BaseMapWithStores]:
for bm, bmls in OrderedDict(sorted(bms.items())).items() for bm, bmls in OrderedDict(sorted(bms.items())).items()
] ]
@api.get('/init-data')
@api.get("/init-data")
async def get_init_data() -> MapInitData: async def get_init_data() -> MapInitData:
await registry.update_stores_counts() await registry.update_stores_counts()
df = registry.stores.reset_index().\ df = registry.stores.reset_index().drop(
drop(columns=['model', 'raw_model', 'base_gis_type']) columns=["model", "raw_model", "base_gis_type"]
)
return MapInitData( return MapInitData(
baseStyles=await get_base_styles(), baseStyles=await get_base_styles(),
baseMaps=await get_base_maps(), baseMaps=await get_base_maps(),
groups=registry.primary_groups, groups=registry.primary_groups,
stores=df.to_dict(orient='records') # type: ignore stores=df.to_dict(orient="records"), # type: ignore
) )
@api.get('/base_style/{name}')
async def get_base_style(request: Request, name: str, @api.get("/base_style/{name}")
db_session: fastapi_db_session, async def get_base_style(
) -> BaseStyle: request: Request,
data = await db_session.exec(select(BaseStyle).where(BaseStyle.name==name)) name: str,
db_session: fastapi_db_session,
) -> BaseStyle:
data = await db_session.exec(select(BaseStyle).where(BaseStyle.name == name))
try: try:
base_style = data.one() base_style = data.one()
except NoResultFound: except NoResultFound:
@ -79,19 +96,26 @@ async def get_base_style(request: Request, name: str,
# name=name, # name=name,
# style=dumps({}) # style=dumps({})
# ) # )
if base_style.static_url is not None:
## Externally managed style, no need to get anything from tiles registry
async with AsyncClient() as client:
resp = await client.get(base_style.static_url)
base_style.style = loads(resp.content)
if name in tiles_registry.mbtiles: if name in tiles_registry.mbtiles:
## Try to get base_style from tiles_registry ## Try to get base_style from tiles_registry
tiles = tiles_registry.mbtiles['name'] tiles = tiles_registry.mbtiles["name"]
style = dumps(await tiles.get_style(style_record=base_style, style = dumps(await tiles.get_style(style_record=base_style, request=request))
request=request))
else: else:
style = base_style.style # type: ignore style = base_style.style # type: ignore
return BaseStyle(name=name, style=style) # type: ignore return BaseStyle(name=name, style=style) # type: ignore
@api.get('/layer_style/{store}')
async def get_layer_style(request: Request, store: str, @api.get("/layer_style/{store}")
response: Response, async def get_layer_style(
) -> MaplibreStyle | None: request: Request,
store: str,
response: Response,
) -> MaplibreStyle | None:
try: try:
store_record = registry.stores.loc[store] store_record = registry.stores.loc[store]
except KeyError: except KeyError:
@ -101,18 +125,18 @@ async def get_layer_style(request: Request, store: str,
## Get layer_defs from live redis and give symbol ## Get layer_defs from live redis and give symbol
return await redis_store.get_maplibre_style(store) return await redis_store.get_maplibre_style(store)
## Set the etag based on the last modification of the model's style. ## Set the etag based on the last modification of the model's style.
#if store in info.schema.app['registry'].geom_auto: # if store in info.schema.app['registry'].geom_auto:
if store_record.custom: if store_record.custom:
## The style is in Qml ## The style is in Qml
ttag_channel = 'gisaf_map.qml' ttag_channel = "gisaf_map.qml"
else: else:
## The style is in Category ## The style is in Category
ttag_channel = 'gisaf_survey.category' ttag_channel = "gisaf_survey.category"
## Check if the request was etagged: ## Check if the request was etagged:
ttag = await redis_store.get_ttag(ttag_channel) ttag = await redis_store.get_ttag(ttag_channel)
if ttag and request.headers.get('If-None-Match') == ttag: if ttag and request.headers.get("If-None-Match") == ttag:
raise HTTPException(status_code=status.HTTP_304_NOT_MODIFIED) raise HTTPException(status_code=status.HTTP_304_NOT_MODIFIED)
# request.not_modified = True # request.not_modified = True
# return MaplibreStyle() # return MaplibreStyle()
response.headers['ETag'] = ttag response.headers["ETag"] = ttag
return await store_record.model.get_maplibre_style() return await store_record.model.get_maplibre_style()

View file

@ -12,30 +12,31 @@ class Store(StoreNameOnly):
count: int | None = None count: int | None = None
custom: bool custom: bool
description: str description: str
#extra: dict[str, Any] | None # extra: dict[str, Any] | None
gis_type: str gis_type: str
group: str group: str
#icon: str # icon: str
in_menu: bool in_menu: bool
is_db: bool is_db: bool
is_line_work: bool is_line_work: bool
is_live: bool is_live: bool
long_name: str | None long_name: str | None
#mapbox_layout: dict[str, Any] | None # mapbox_layout: dict[str, Any] | None
#mapbox_paint: dict[str, Any] | None # mapbox_paint: dict[str, Any] | None
type: str type: str
# mapbox_type_custom: str | None # mapbox_type_custom: str | None
#mapbox_type_default: str # mapbox_type_default: str
minor_group_1: str | None minor_group_1: str | None
minor_group_2: str | None minor_group_2: str | None
#model: GeoModel # model: GeoModel
#name_letter: str # name_letter: str
#name_number: int # name_number: int
#raw_model: GeoPointSurveyModel # raw_model: GeoPointSurveyModel
#raw_model_store_name: str # raw_model_store_name: str
status: str status: str
style: str | None style: str | None
symbol: str | None symbol: str | None
title: str title: str
viewable_role: str | None viewable_role: str | None = None
z_index: int z_index: int = 500

6
uv.lock generated
View file

@ -538,7 +538,7 @@ wheels = [
[[package]] [[package]]
name = "gisaf-backend" name = "gisaf-backend"
version = "0.6.0a0" version = "0.0.0"
source = { editable = "." } source = { editable = "." }
dependencies = [ dependencies = [
{ name = "aiopath" }, { name = "aiopath" },
@ -548,6 +548,7 @@ dependencies = [
{ name = "fastapi" }, { name = "fastapi" },
{ name = "geoalchemy2" }, { name = "geoalchemy2" },
{ name = "geopandas" }, { name = "geopandas" },
{ name = "httpx" },
{ name = "itsdangerous" }, { name = "itsdangerous" },
{ name = "matplotlib" }, { name = "matplotlib" },
{ name = "orjson" }, { name = "orjson" },
@ -586,7 +587,6 @@ mqtt = [
[package.dev-dependencies] [package.dev-dependencies]
dev = [ dev = [
{ name = "asyncpg-stubs" }, { name = "asyncpg-stubs" },
{ name = "httpx" },
{ name = "ipdb" }, { name = "ipdb" },
{ name = "pandas-stubs" }, { name = "pandas-stubs" },
{ name = "pretty-errors" }, { name = "pretty-errors" },
@ -610,6 +610,7 @@ requires-dist = [
{ name = "geopandas", specifier = ">=1.0.1" }, { name = "geopandas", specifier = ">=1.0.1" },
{ name = "gisaf-backend", extras = ["contextily"], marker = "extra == 'all'" }, { name = "gisaf-backend", extras = ["contextily"], marker = "extra == 'all'" },
{ name = "gisaf-backend", extras = ["mqtt"], marker = "extra == 'all'" }, { name = "gisaf-backend", extras = ["mqtt"], marker = "extra == 'all'" },
{ name = "httpx", specifier = ">=0.28.1" },
{ name = "itsdangerous", specifier = ">=2.1.2" }, { name = "itsdangerous", specifier = ">=2.1.2" },
{ name = "matplotlib", specifier = ">=3.8.3" }, { name = "matplotlib", specifier = ">=3.8.3" },
{ name = "orjson", specifier = ">=3.9.10" }, { name = "orjson", specifier = ">=3.9.10" },
@ -636,7 +637,6 @@ requires-dist = [
[package.metadata.requires-dev] [package.metadata.requires-dev]
dev = [ dev = [
{ name = "asyncpg-stubs", specifier = ">=0.29.1" }, { name = "asyncpg-stubs", specifier = ">=0.29.1" },
{ name = "httpx", specifier = ">=0.28.1" },
{ name = "ipdb", specifier = ">=0.13.13" }, { name = "ipdb", specifier = ">=0.13.13" },
{ name = "pandas-stubs", specifier = ">=2.1.4.231218" }, { name = "pandas-stubs", specifier = ">=2.1.4.231218" },
{ name = "pretty-errors", specifier = ">=1.2.25" }, { name = "pretty-errors", specifier = ">=1.2.25" },