Skip to content

Commit

Permalink
fix: merge conflict
Browse files Browse the repository at this point in the history
  • Loading branch information
Sujit committed Sep 24, 2024
2 parents 2e6b2dc + 4423a0c commit 1b7520a
Show file tree
Hide file tree
Showing 12 changed files with 223 additions and 14 deletions.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ repos:
# Lint / autoformat: Python code
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: "v0.6.5"
rev: "v0.6.7"
hooks:
# Run the linter
- id: ruff
Expand Down
3 changes: 3 additions & 0 deletions src/backend/app/db/db_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ class DbTask(Base):
)
project_task_index = cast(int, Column(Integer))
outline = cast(WKBElement, Column(Geometry("POLYGON", srid=4326)))
take_off_point = cast(
WKBElement, Column(Geometry("POINT", srid=4326), nullable=True)
)


class DbProject(Base):
Expand Down
1 change: 0 additions & 1 deletion src/backend/app/drones/drone_schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ class DbDrone(BaseDrone):
@staticmethod
async def one(db: Connection, drone_id: int):
"""Get a single drone by it's ID"""
print("drone_id = ", drone_id)
async with db.cursor(row_factory=class_row(DbDrone)) as cur:
await cur.execute(
"""
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
"""added take_off_point in task
Revision ID: aec0d408df01
Revises: 2b92f8a9bbec
Create Date: 2024-09-24 03:57:03.760365
"""

import geoalchemy2
import sqlalchemy as sa
from alembic import op
from typing import Sequence, Union


# revision identifiers, used by Alembic.
revision: str = "aec0d408df01"
down_revision: Union[str, None] = "2b92f8a9bbec"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column("projects", "forward_overlap_percent")
op.drop_column("projects", "side_overlap_percent")
op.add_column(
"tasks",
sa.Column(
"take_off_point",
geoalchemy2.types.Geometry(
geometry_type="POINT",
srid=4326,
from_text="ST_GeomFromEWKT",
name="geometry",
),
nullable=True,
),
)
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column("tasks", "take_off_point")
op.add_column(
"projects",
sa.Column(
"side_overlap_percent",
sa.DOUBLE_PRECISION(precision=53),
autoincrement=False,
nullable=True,
),
)
op.add_column(
"projects",
sa.Column(
"forward_overlap_percent",
sa.DOUBLE_PRECISION(precision=53),
autoincrement=False,
nullable=True,
),
)
# ### end Alembic commands ###
47 changes: 46 additions & 1 deletion src/backend/app/tasks/task_logic.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,55 @@
from psycopg import Connection
import uuid
import json
from psycopg import Connection
from app.models.enums import HTTPStatus, State
from fastapi import HTTPException
from psycopg.rows import dict_row


async def update_take_off_point_in_db(
db: Connection, task_id: uuid.UUID, take_off_point: str
):
"""Update take_off_point in the task table"""

async with db.cursor() as cur:
await cur.execute(
"""
UPDATE tasks
SET take_off_point = ST_SetSRID(ST_GeomFromGeoJSON(%(take_off_point)s), 4326)
WHERE id = %(task_id)s;
""",
{
"task_id": str(task_id),
"take_off_point": json.dumps(take_off_point),
},
)


async def get_take_off_point_from_db(db: Connection, task_id: uuid.UUID):
"""Get take_off_point from task table"""

async with db.cursor(row_factory=dict_row) as cur:
await cur.execute(
"""
SELECT ST_AsGeoJSON(take_off_point) as take_off_point
FROM tasks
WHERE id = %(task_id)s;
""",
{"task_id": str(task_id)},
)

data = await cur.fetchone()
if data is None:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND, detail="Task not found"
)
return (
json.loads(data["take_off_point"])
if data.get("take_off_point") is not None
else None
)


async def get_task_geojson(db: Connection, task_id: uuid.UUID):
async with db.cursor() as cur:
await cur.execute(
Expand Down
27 changes: 22 additions & 5 deletions src/backend/app/waypoints/waypoint_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@
waypoints,
)
from app.models.enums import HTTPStatus
from app.tasks.task_logic import get_task_geojson
from app.tasks.task_logic import (
get_task_geojson,
get_take_off_point_from_db,
update_take_off_point_in_db,
)
from app.waypoints.waypoint_logic import check_point_within_buffer
from app.db import database
from app.utils import merge_multipolygon
Expand Down Expand Up @@ -61,16 +65,29 @@ async def get_task_waypoint(
# create a takeoff point in this format ["lon","lat"]
if take_off_point:
take_off_point = [take_off_point.longitude, take_off_point.latitude]

# Validate that the take-off point is within a 200m buffer of the task boundary
if not check_point_within_buffer(take_off_point, task_geojson, 200):
raise HTTPException(
status_code=400,
detail="Take off point should be within 200m of the boundary",
)

# Update take_off_point in tasks table
geojson_point = {"type": "Point", "coordinates": take_off_point}
await update_take_off_point_in_db(db, task_id, geojson_point)

else:
# take the centroid of the task as the takeoff point
task_polygon = shape(task_geojson["features"][0]["geometry"])
task_centroid = task_polygon.centroid
take_off_point = [task_centroid.x, task_centroid.y]
# Retrieve the take-off point from the database if not explicitly provided
take_off_point_from_db = await get_take_off_point_from_db(db, task_id)

if take_off_point_from_db:
take_off_point = take_off_point_from_db["coordinates"]
else:
# Use the centroid of the task polygon as the default take-off point
task_polygon = shape(task_geojson["features"][0]["geometry"])
task_centroid = task_polygon.centroid
take_off_point = [task_centroid.x, task_centroid.y]

forward_overlap = project.front_overlap if project.front_overlap else 70
side_overlap = project.side_overlap if project.side_overlap else 70
Expand Down
20 changes: 19 additions & 1 deletion src/frontend/src/api/tasks.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
/* eslint-disable import/prefer-default-export */
import { getIndividualTask, getTaskWaypoint } from '@Services/tasks';
import {
getIndividualTask,
getTaskAssetsInfo,
getTaskWaypoint,
} from '@Services/tasks';
import { useQuery, UseQueryOptions } from '@tanstack/react-query';

export const useGetTaskWaypointQuery = (
Expand Down Expand Up @@ -28,3 +32,17 @@ export const useGetIndividualTaskQuery = (
...queryOptions,
});
};

export const useGetTaskAssetsInfo = (
projectId: string,
taskId: string,
queryOptions?: Partial<UseQueryOptions>,
) => {
return useQuery({
queryKey: ['task-assets-info'],
enabled: !!taskId,
queryFn: () => getTaskAssetsInfo(projectId, taskId),
select: (res: any) => res.data,
...queryOptions,
});
};
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { useParams } from 'react-router-dom';
import { useGetIndividualTaskQuery, useGetTaskWaypointQuery } from '@Api/tasks';
import {
useGetIndividualTaskQuery,
useGetTaskAssetsInfo,
useGetTaskWaypointQuery,
} from '@Api/tasks';
import { useState } from 'react';
// import { useTypedSelector } from '@Store/hooks';
import { format } from 'date-fns';
import DescriptionBoxComponent from './DescriptionComponent';
import QuestionBox from '../QuestionBox';
import UploadsInformation from '../UploadsInformation';

const DescriptionBox = () => {
// const secondPageStates = useTypedSelector(state => state.droneOperatorTask);
Expand All @@ -21,6 +26,8 @@ const DescriptionBox = () => {
},
},
);
const { data: taskAssetsInformation }: Record<string, any> =
useGetTaskAssetsInfo(projectId as string, taskId as string);

const { data: taskDescription }: Record<string, any> =
useGetIndividualTaskQuery(taskId as string, {
Expand Down Expand Up @@ -103,7 +110,28 @@ const DescriptionBox = () => {
))}
</div>
{/* {!secondPage && <QuestionBox />} */}
<QuestionBox setFlyable={setFlyable} flyable={flyable} />
<QuestionBox
setFlyable={setFlyable}
flyable={flyable}
haveNoImages={taskAssetsInformation?.image_count === 0}
/>

{taskAssetsInformation?.image_count > 0 && (
<div className="naxatw-flex naxatw-flex-col naxatw-gap-5">
<UploadsInformation
data={[
{
name: 'Image count',
value: taskAssetsInformation?.image_count,
},
{
name: 'Orthophoto available',
value: taskAssetsInformation?.assets_url ? 'Yes' : 'No',
},
]}
/>
</div>
)}
</>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,14 @@ import UploadsBox from '../UploadsBox';
interface IQuestionBoxProps {
flyable: string;
setFlyable: React.Dispatch<React.SetStateAction<any>>;
haveNoImages: boolean;
}

const QuestionBox = ({ flyable, setFlyable }: IQuestionBoxProps) => {
const QuestionBox = ({
flyable,
setFlyable,
haveNoImages,
}: IQuestionBoxProps) => {
const { projectId, taskId } = useParams();

const dispatch = useTypedDispatch();
Expand Down Expand Up @@ -119,7 +124,7 @@ const QuestionBox = ({ flyable, setFlyable }: IQuestionBoxProps) => {
</Button>
</div>
</motion.div>
{flyable === 'yes' && <UploadsBox />}
{flyable === 'yes' && haveNoImages && <UploadsBox />}
</div>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/* eslint-disable no-unused-vars */
import { Button } from '@Components/RadixComponents/Button';
import { toggleModal } from '@Store/actions/common';
import { setFiles, showPopover } from '@Store/actions/droneOperatorTask';
import { setFiles } from '@Store/actions/droneOperatorTask';
import { useTypedDispatch, useTypedSelector } from '@Store/hooks';

const UploadsBox = () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
const UploadsInformation = ({ data }: { data: Record<string, any>[] }) => {
return (
<>
<div className="naxatw-flex naxatw-w-full naxatw-flex-col naxatw-gap-5">
<div className="naxatw-flex naxatw-flex-col naxatw-gap-3">
<p className="naxatw-text-[0.875rem] naxatw-font-semibold naxatw-leading-normal naxatw-tracking-[0.0175rem] naxatw-text-[#D73F3F]">
Upload Information
</p>
</div>

{data.map(information => (
<div
className="naxatw-flex naxatw-w-full naxatw-gap-2"
key={information?.name}
>
<p className="naxatw-w-[6.875rem] naxatw-text-[0.75rem] naxatw-text-[#484848]">
{information?.name}
</p>
<p className="naxatw-text-[0.75rem] naxatw-text-[#484848]">:</p>
<p className="naxatw-text-[0.75rem] naxatw-text-[#484848]">
{information?.value}
</p>
</div>
))}
</div>
</>
);
};
export default UploadsInformation;
2 changes: 2 additions & 0 deletions src/frontend/src/services/tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,5 @@ export const postTaskWaypoint = (payload: Record<string, any>) => {
},
);
};
export const getTaskAssetsInfo = (projectId: string, taskId: string) =>
authenticated(api).get(`/projects/assets/${projectId}/${taskId}/`);

0 comments on commit 1b7520a

Please sign in to comment.