Skip to content

Commit

Permalink
Merge pull request #265 from hotosm/feat/orthophoto-download
Browse files Browse the repository at this point in the history
hot-fix(orthophoto-download): added assets_url & image_count in get project details
  • Loading branch information
nrjadkry authored Oct 4, 2024
2 parents a8b2aba + e43edaa commit 3ba1c73
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 12 deletions.
2 changes: 1 addition & 1 deletion src/backend/app/projects/project_logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ def process_drone_images(project_id: uuid.UUID, task_id: uuid.UUID):
)


async def get_project_info_from_s3(project_id: uuid.UUID, task_id: uuid.UUID):
def get_project_info_from_s3(project_id: uuid.UUID, task_id: uuid.UUID):
"""
Helper function to get the number of images and the URL to download the assets.
"""
Expand Down
2 changes: 1 addition & 1 deletion src/backend/app/projects/project_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -368,4 +368,4 @@ async def get_assets_info(
"""
Endpoint to get the number of images and the URL to download the assets for a given project and task.
"""
return await project_logic.get_project_info_from_s3(project.id, task_id)
return project_logic.get_project_info_from_s3(project.id, task_id)
44 changes: 36 additions & 8 deletions src/backend/app/projects/project_schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import uuid
from typing import Annotated, Optional, List
from datetime import datetime, date
from app.projects import project_logic
import geojson
from loguru import logger as log
from pydantic import BaseModel, computed_field, Field, model_validator
Expand All @@ -26,6 +27,13 @@
from app.s3 import get_presigned_url


class AssetsInfo(BaseModel):
project_id: str
task_id: str
image_count: int
assets_url: Optional[str]


def validate_geojson(
value: FeatureCollection | Feature | Polygon,
) -> geojson.FeatureCollection:
Expand Down Expand Up @@ -121,16 +129,41 @@ def validate_to_json(cls, value):
return value


class AssetsInfoData(BaseModel):
project_id: int


class TaskOut(BaseModel):
"""Base project model."""

id: uuid.UUID
project_id: uuid.UUID
project_task_index: int
outline: Optional[Polygon | Feature | FeatureCollection]
outline: Optional[Polygon | Feature | FeatureCollection] = None
state: Optional[str] = None
user_id: Optional[str] = None
task_area: Optional[float] = None
name: Optional[str] = None
image_count: Optional[int] = None
assets_url: Optional[str] = None

@model_validator(mode="after")
def set_assets_url(cls, values):
"""Set image_url and image count before rendering the model."""
task_id = values.id
project_id = values.project_id

if task_id and project_id:
data = project_logic.get_project_info_from_s3(project_id, task_id)
if data:
return values.copy(
update={
"assets_url": data.assets_url,
"image_count": data.image_count,
}
)

return values


class DbProject(BaseModel):
Expand Down Expand Up @@ -233,6 +266,7 @@ async def one(db: Connection, project_id: uuid.UUID):
SELECT
t.id,
t.project_task_index,
t.project_id,
ST_AsGeoJSON(t.outline)::jsonb -> 'coordinates' AS coordinates,
ST_AsGeoJSON(t.outline)::jsonb -> 'type' AS type,
ST_XMin(ST_Envelope(t.outline)) AS xmin,
Expand All @@ -259,6 +293,7 @@ async def one(db: Connection, project_id: uuid.UUID):
user_id,
name,
task_area,
project_id,
jsonb_build_object(
'type', 'Feature',
'geometry', jsonb_build_object(
Expand Down Expand Up @@ -474,10 +509,3 @@ class PresignedUrlRequest(BaseModel):
task_id: uuid.UUID
image_name: List[str]
expiry: int # Expiry time in hours


class AssetsInfo(BaseModel):
project_id: str
task_id: str
image_count: int
assets_url: Optional[str]
2 changes: 1 addition & 1 deletion src/backend/app/tasks/task_schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ async def all(db: Connection, project_id: uuid.UUID):
existing_tasks = await cur.fetchall()
# Get all task_ids from the tasks table
task_ids = await Task.get_all_tasks(db, project_id)

# Create a set of existing task_ids for quick lookup
existing_task_ids = {task.task_id for task in existing_tasks}

Expand All @@ -137,7 +138,6 @@ async def all(db: Connection, project_id: uuid.UUID):
}
for task_id in remaining_task_ids
]

# Combine both existing tasks and remaining tasks
combined_tasks = existing_tasks + remaining_tasks
return combined_tasks
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import DataTable from '@Components/common/DataTable';
import Icon from '@Components/common/Icon';
import { useTypedSelector } from '@Store/hooks';
import { useMemo } from 'react';
import { toast } from 'react-toastify';

const contributionsDataColumns = [
{
Expand All @@ -15,6 +17,41 @@ const contributionsDataColumns = [
header: 'Task Status',
accessorKey: 'task_state',
},
{ header: 'Image count', accessorKey: 'image_count' },

{
header: 'Orthophoto',
accessorKey: 'assets_url',
cell: ({ row }: any) => {
const handleDownloadResult = () => {
const { original: rowData } = row;
if (!rowData?.assets_url) return;
try {
const link = document.createElement('a');
link.href = rowData?.assets_url;
link.download = 'assets.zip';
document.body.appendChild(link);
link.click();
link.remove();
} catch (error) {
toast.error(`There wan an error while downloading file ${error}`);
}
};

return (
<div
className="naxatw-group naxatw-flex naxatw-cursor-pointer naxatw-items-center naxatw-gap-1 naxatw-text-center naxatw-font-semibold naxatw-text-red"
tabIndex={0}
role="button"
onKeyDown={() => {}}
onClick={() => handleDownloadResult()}
>
<div className="group-hover:naxatw-underline">Download</div>
<Icon className="!naxatw-text-icon-sm" name="download" />
</div>
);
},
},
];

export default function TableSection() {
Expand All @@ -30,6 +67,8 @@ export default function TableSection() {
user: curr?.name || '-',
task_mapped: `Task# ${curr?.project_task_index}`,
task_state: curr?.state,
assets_url: curr?.assets_url,
image_count: curr?.image_count,
},
];
}, []);
Expand Down
2 changes: 1 addition & 1 deletion src/frontend/src/views/IndividualProject/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ const IndividualProject = () => {
{/* <----------- temporary breadcrumb -----------> */}
</div>
<div className="naxatw-flex naxatw-flex-col naxatw-gap-6 md:naxatw-flex-row">
<div className="naxatw-order-2 naxatw-w-full naxatw-max-w-[27rem]">
<div className="naxatw-order-2 naxatw-w-full naxatw-max-w-[30rem]">
<Tab
orientation="row"
className="naxatw-bg-transparent hover:naxatw-border-b-2 hover:naxatw-border-red"
Expand Down

0 comments on commit 3ba1c73

Please sign in to comment.