Skip to content

Commit

Permalink
fix: basemap tile download, refactor to use /{project_id}/name
Browse files Browse the repository at this point in the history
  • Loading branch information
spwoodcock committed Apr 19, 2024
1 parent cfe9d3c commit a5ce930
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 105 deletions.
2 changes: 2 additions & 0 deletions src/backend/app/auth/roles.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,9 @@ async def mapper(
"""A mapper for a specific project."""
# If project is public, skip permission check
if project.visibility == ProjectVisibility.PUBLIC:
# FIXME this is a different type than DbUser
return user_data

db_user = await check_access(
user_data,
db,
Expand Down
3 changes: 2 additions & 1 deletion src/backend/app/projects/project_deps.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,11 @@

async def get_project_by_id(
db: Session = Depends(get_db), project_id: Optional[int] = None
) -> DbProject:
) -> Optional[DbProject]:
"""Get a single project by id."""
if not project_id:
# Skip if no project id passed
# FIXME why do we need this?
return None

db_project = db.query(DbProject).filter(DbProject.id == project_id).first()
Expand Down
200 changes: 100 additions & 100 deletions src/backend/app/projects/project_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,106 @@ async def set_odk_entities_mapping_status(
)


@router.get("/{project_id}/tiles-list/")
async def tiles_list(
project_id: int,
db: Session = Depends(database.get_db),
current_user: AuthUser = Depends(mapper),
):
"""Returns the list of tiles for a project.
Parameters:
project_id: int
db (Session): The database session, provided automatically.
current_user (AuthUser): Check if user is logged in.
Returns:
Response: List of generated tiles for a project.
"""
return await project_crud.get_mbtiles_list(db, project_id)


@router.get("/{project_id}/download-tiles/")
async def download_tiles(
tile_id: int,
db: Session = Depends(database.get_db),
current_user: AuthUser = Depends(mapper),
):
"""Download the basemap tile archive for a project."""
log.debug("Getting tile archive path from DB")
tiles_path = (
db.query(db_models.DbTilesPath)
.filter(db_models.DbTilesPath.id == str(tile_id))
.first()
)
log.info(f"User requested download for tiles: {tiles_path.path}")

project_id = tiles_path.project_id
project = await project_crud.get_project(db, project_id)
filename = Path(tiles_path.path).name.replace(
f"{project_id}_", f"{project.project_name_prefix}_"
)
log.debug(f"Sending tile archive to user: {filename}")

return FileResponse(
tiles_path.path,
headers={"Content-Disposition": f'attachment; filename="{filename}"'},
)


@router.get("/{project_id}/tiles")
async def generate_project_tiles(
background_tasks: BackgroundTasks,
project_id: int,
source: str = Query(
..., description="Select a source for tiles", enum=TILES_SOURCE
),
format: str = Query(
"mbtiles", description="Select an output format", enum=TILES_FORMATS
),
tms: str = Query(
None,
description="Provide a custom TMS URL, optional",
),
db: Session = Depends(database.get_db),
current_user: AuthUser = Depends(mapper),
):
"""Returns basemap tiles for a project.
Args:
background_tasks (BackgroundTasks): FastAPI bg tasks, provided automatically.
project_id (int): ID of project to create tiles for.
source (str): Tile source ("esri", "bing", "topo", "google", "oam").
format (str, optional): Default "mbtiles". Other options: "pmtiles", "sqlite3".
tms (str, optional): Default None. Custom TMS provider URL.
db (Session): The database session, provided automatically.
current_user (AuthUser): Check if user has MAPPER permission.
Returns:
str: Success message that tile generation started.
"""
# Create task in db and return uuid
log.debug(
"Creating generate_project_tiles background task "
f"for project ID: {project_id}"
)
background_task_id = await project_crud.insert_background_task_into_database(
db, project_id=project_id
)

background_tasks.add_task(
project_crud.get_project_tiles,
db,
project_id,
background_task_id,
source,
format,
tms,
)

return {"Message": "Tile generation started"}


@router.get("/{project_id}", response_model=project_schemas.ReadProject)
async def read_project(
current_user: AuthUser = Depends(mapper),
Expand Down Expand Up @@ -1071,106 +1171,6 @@ async def convert_fgb_to_geojson(
return Response(content=json.dumps(data_extract_geojson), headers=headers)


@router.get("/tiles/{project_id}")
async def generate_project_tiles(
background_tasks: BackgroundTasks,
project_id: int,
source: str = Query(
..., description="Select a source for tiles", enum=TILES_SOURCE
),
format: str = Query(
"mbtiles", description="Select an output format", enum=TILES_FORMATS
),
tms: str = Query(
None,
description="Provide a custom TMS URL, optional",
),
db: Session = Depends(database.get_db),
current_user: AuthUser = Depends(mapper),
):
"""Returns basemap tiles for a project.
Args:
background_tasks (BackgroundTasks): FastAPI bg tasks, provided automatically.
project_id (int): ID of project to create tiles for.
source (str): Tile source ("esri", "bing", "topo", "google", "oam").
format (str, optional): Default "mbtiles". Other options: "pmtiles", "sqlite3".
tms (str, optional): Default None. Custom TMS provider URL.
db (Session): The database session, provided automatically.
current_user (AuthUser): Check if user has MAPPER permission.
Returns:
str: Success message that tile generation started.
"""
# Create task in db and return uuid
log.debug(
"Creating generate_project_tiles background task "
f"for project ID: {project_id}"
)
background_task_id = await project_crud.insert_background_task_into_database(
db, project_id=project_id
)

background_tasks.add_task(
project_crud.get_project_tiles,
db,
project_id,
background_task_id,
source,
format,
tms,
)

return {"Message": "Tile generation started"}


@router.get("/tiles_list/{project_id}/")
async def tiles_list(
project_id: int,
db: Session = Depends(database.get_db),
current_user: AuthUser = Depends(mapper),
):
"""Returns the list of tiles for a project.
Parameters:
project_id: int
db (Session): The database session, provided automatically.
current_user (AuthUser): Check if user is logged in.
Returns:
Response: List of generated tiles for a project.
"""
return await project_crud.get_mbtiles_list(db, project_id)


@router.get("/download_tiles/")
async def download_tiles(
tile_id: int,
db: Session = Depends(database.get_db),
current_user: AuthUser = Depends(mapper),
):
"""Download the basemap tile archive for a project."""
log.debug("Getting tile archive path from DB")
tiles_path = (
db.query(db_models.DbTilesPath)
.filter(db_models.DbTilesPath.id == str(tile_id))
.first()
)
log.info(f"User requested download for tiles: {tiles_path.path}")

project_id = tiles_path.project_id
project = await project_crud.get_project(db, project_id)
filename = Path(tiles_path.path).name.replace(
f"{project_id}_", f"{project.project_name_prefix}_"
)
log.debug(f"Sending tile archive to user: {filename}")

return FileResponse(
tiles_path.path,
headers={"Content-Disposition": f'attachment; filename="{filename}"'},
)


@router.get("/boundary_in_osm/{project_id}/")
async def download_task_boundary_osm(
project_id: int,
Expand Down
2 changes: 1 addition & 1 deletion src/frontend/src/api/Project.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ export const GenerateProjectTiles = (url, payload) => {
const generateProjectTiles = async (url, payload) => {
try {
const response = await CoreModules.axios.get(url);
dispatch(GetTilesList(`${import.meta.env.VITE_API_URL}/projects/tiles_list/${payload}/`));
dispatch(GetTilesList(`${import.meta.env.VITE_API_URL}/projects/${payload}/tiles-list/`));
dispatch(ProjectActions.SetGenerateProjectTilesLoading(false));
} catch (error) {
dispatch(ProjectActions.SetGenerateProjectTilesLoading(false));
Expand Down
10 changes: 7 additions & 3 deletions src/frontend/src/components/GenerateBasemap.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,16 @@ const GenerateBasemap = ({ projectInfo }) => {
});
const downloadBasemap = (tileId, toOpfs = false) => {
dispatch(
DownloadTile(`${import.meta.env.VITE_API_URL}/projects/download_tiles/?tile_id=${tileId}`, projectInfo, toOpfs),
DownloadTile(
`${import.meta.env.VITE_API_URL}/projects/${id}/download-tiles/?tile_id=${tileId}`,
projectInfo,
toOpfs,
),
);
};

const getTilesList = () => {
dispatch(GetTilesList(`${import.meta.env.VITE_API_URL}/projects/tiles_list/${id}/`));
dispatch(GetTilesList(`${import.meta.env.VITE_API_URL}/projects/${id}/tiles-list/`));
};

useEffect(() => {
Expand Down Expand Up @@ -80,7 +84,7 @@ const GenerateBasemap = ({ projectInfo }) => {
GenerateProjectTiles(
`${
import.meta.env.VITE_API_URL
}/projects/tiles/${id}?source=${selectedTileSource}&format=${selectedOutputFormat}&tms=${tmsUrl}`,
}/projects/${id}/tiles?source=${selectedTileSource}&format=${selectedOutputFormat}&tms=${tmsUrl}`,
id,
),
);
Expand Down

0 comments on commit a5ce930

Please sign in to comment.