Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update develop branch with the main branch #166

Merged
merged 27 commits into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
6ec6f01
feat(project-description): round off area to 3 decimal place and use …
suzit-10 Aug 21, 2024
0970fa5
feat(individual-project): show project boundary on map
suzit-10 Aug 21, 2024
c65079a
feat: create Legend component
suzit-10 Aug 21, 2024
d6c665f
feat(individual-project): add legend on map
suzit-10 Aug 21, 2024
2f77b3a
Merge branch 'main' of github.com:hotosm/drone-tm into minor-updates-…
suzit-10 Aug 21, 2024
d319c8d
style(individual-project): increase project area line width and locke…
suzit-10 Aug 21, 2024
464237b
feat(individual-project): show no-fly-zone on map
suzit-10 Aug 21, 2024
cfb1987
feat(project-creation): add measurementType state on redux slice
suzit-10 Aug 21, 2024
fbed167
feat(project-creation): add option to input `GSD` or `altitude` on p…
suzit-10 Aug 21, 2024
aa82a1b
refactor(project-creartion): move constant data to separate file
suzit-10 Aug 21, 2024
75ed675
feat: get coordinates on properties on map feature click
suzit-10 Aug 22, 2024
856b94a
style(project-creation): replace `-` with `:`
suzit-10 Aug 22, 2024
12aa959
feat(task-description): show description on popup of waypoints point …
suzit-10 Aug 22, 2024
3104866
feat(task-descripion): add altitude on waypoints point click popup
suzit-10 Aug 22, 2024
9f2beda
feat(dashboard): wrap requested task listing component with hasErrorb…
suzit-10 Aug 22, 2024
cc807fc
feat(project-creation): make project description input a text area
suzit-10 Aug 22, 2024
d937fda
feat: add converter function `m2ToKm2`
suzit-10 Aug 22, 2024
c32985c
feat: convert project area m2 to km2
suzit-10 Aug 22, 2024
63ae1a3
fix(project-description): increase text size of instruction
suzit-10 Aug 23, 2024
a254a5f
fix(dashboard): card UI
suzit-10 Aug 23, 2024
ec132c4
feat(project-dashboard): show slug insted of id on cards
suzit-10 Aug 23, 2024
263c290
feat(tsak-description): remove preview images from selected folders u…
suzit-10 Aug 23, 2024
facbf11
feat(task-description): refactor uploading images preview popup
suzit-10 Aug 23, 2024
f048057
feat(task-description): refactor images uploading process
suzit-10 Aug 23, 2024
447f5e1
feat(individual-project): show no-fly zone popup on nofly zone click
suzit-10 Aug 23, 2024
f743cb5
docs: update user roadmap in readme
spwoodcock Aug 24, 2024
c649e7d
Merge pull request #165 from hotosm/minor-updates-fixes
nrjadkry Aug 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 16 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,24 @@ To get started with Drone TM:
<!-- prettier-ignore-start -->
| Status | Feature |
|:--:| :-- |
|✅| simple UI with user sign up and login |
|✅| flight plan generation for DJI .wmpl |
|⚙️| terrain following for flight plans using DEM |
|⚙️| drone imagery upload and processing |
| | user access management |
| | flight plan generation for another drone manufacturers |
| | HOT community mapping drone |
|✅| 🖥️ simple UI with user sign up and login |
|✅| 🖥️ project area subdivision into smaller task areas for operators |
|✅| 📱 flight plan generation in task areas for DJI drones |
|⚙️| 📱 follow terrain during flight plan generation in hilly/mountainous regions |
|⚙️| 📱 allow adjustments to the flight plan orientation based on field conditions |
|⚙️| 🖥️ drone imagery upload merging into a final combined image for the project |
| | 🖥️ user access management for each part of the UI |
| | 📱 & 🖥️ real-time updates for drone flight progress |
| | 📱 flight plan generation for other drone manufacturers |
| | 🖥️ better usage of 3D model data collected by drones |
| | 📱 HOT community mapping drone: cheap, mapping optimized, materials sourced locally |
<!-- prettier-ignore-end -->

> [!Note]
> 📱 for mobile / operators
>
> 🖥️ for desktop / managers / validators

## Contribution

Drone TM is an open-source project, and we welcome contributions from the community. Whether you're a developer, a drone pilot, or just passionate about mapping, you can get involved:
Expand Down
Binary file added src/frontend/src/assets/images/area-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ const CreateprojectLayout = () => {
const requireApprovalFromManagerForLocking = useTypedSelector(
state => state.createproject.requireApprovalFromManagerForLocking,
);
const measurementType = useTypedSelector(
state => state.createproject.measurementType,
);

const initialState: FieldValues = {
name: '',
Expand Down Expand Up @@ -213,6 +216,8 @@ const CreateprojectLayout = () => {
if (isNoflyzonePresent === 'no')
delete refactoredData?.outline_no_fly_zones;
delete refactoredData?.dem;
if (measurementType === 'gsd') delete refactoredData?.altitude_from_ground;
else delete refactoredData?.gsd_cm_px;

// make form data with value JSON stringify to combine value on single json / form data with only 2 keys (backend didn't found project_info on non-stringified data)
const formData = new FormData();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { FormControl, Label, Input } from '@Components/common/FormUI';
import ErrorMessage from '@Components/common/FormUI/ErrorMessage';
import { UseFormPropsType } from '@Components/common/FormUI/types';
import { Controller } from 'react-hook-form';

export default function BasicInformation({
formProps,
}: {
formProps: UseFormPropsType;
}) {
const { register, errors } = formProps;
const { register, errors, control } = formProps;

return (
<div className="naxatw-px-10 naxatw-py-5">
Expand All @@ -23,14 +24,18 @@ export default function BasicInformation({
<ErrorMessage message={errors?.name?.message as string} />
</FormControl>
<FormControl className="naxatw-mt-5 naxatw-gap-1">
<Label required>Description of the project</Label>
<Input
type="text-area"
placeholder="Description of the Project"
{...register('description', {
required: 'Description is Required',
setValueAs: (value: string) => value.trim(),
})}
<Label>Description of the project</Label>
<Controller
control={control}
name="description"
render={({ field: { onChange, onBlur, value, ref, ...others } }) => (
<textarea
className="naxatw-flex naxatw-h-[100px] naxatw-rounded-[4px] naxatw-border naxatw-border-[#555555] naxatw-bg-transparent naxatw-p-2 naxatw-text-body-md file:naxatw-font-medium hover:naxatw-border-red focus:naxatw-border-red focus:naxatw-bg-transparent focus:naxatw-outline-none disabled:naxatw-cursor-not-allowed"
placeholder="Description of the Project"
ref={ref}
{...others}
/>
)}
/>
<ErrorMessage message={errors?.description?.message as string} />
</FormControl>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import RadioButton from '@Components/common/RadioButton';
import { FlexColumn, FlexRow } from '@Components/common/Layouts';
import FileUpload from '@Components/common/UploadArea';
import hasErrorBoundary from '@Utils/hasErrorBoundary';
import { m2ToKm2 } from '@Utils/index';
import {
setCreateProjectState,
resetUploadedAndDrawnAreas,
Expand Down Expand Up @@ -268,7 +269,7 @@ const DefineAOI = ({ formProps }: { formProps: UseFormPropsType }) => {
Reset Project Area
</Button>
<p className="naxatw-mt-2 naxatw-text-body-md">
Total Area: {Math.trunc(totalProjectArea as number)} m²
Total Area: {m2ToKm2(Math.trunc(totalProjectArea as number))}
</p>
<div className="naxatw-mt-2">
<RadioButton
Expand Down Expand Up @@ -304,7 +305,8 @@ const DefineAOI = ({ formProps }: { formProps: UseFormPropsType }) => {
Reset No Fly Zone
</Button>
<p className="naxatw-mt-2 naxatw-text-body-md">
Total Area: {Math.trunc(noFlyZoneArea as number)} m2
Total Area:{' '}
{m2ToKm2(Math.trunc(noFlyZoneArea as number))}
</p>
</>
) : (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,46 +1,34 @@
/* eslint-disable camelcase */
import { useTypedDispatch, useTypedSelector } from '@Store/hooks';
import { FormControl, Label, Input } from '@Components/common/FormUI';
// import RadioButton from '@Components/common/RadioButton';
import RadioButton from '@Components/common/RadioButton';
import ErrorMessage from '@Components/common/FormUI/ErrorMessage';
import { UseFormPropsType } from '@Components/common/FormUI/types';
import { setCreateProjectState } from '@Store/actions/createproject';
import hasErrorBoundary from '@Utils/hasErrorBoundary';
// import { terrainOptions } from '@Constants/createProject';
import orthoPhotoIcon from '@Assets/images/ortho-photo-icon.svg';
import _3DModal from '@Assets/images/3d-model-icon.svg';
import DTMIcon from '@Assets/images/DTM-Icon.svg';
import DSMIcon from '@Assets/images/DSM-icon.svg';
import { FlexRow } from '@Components/common/Layouts';
import Switch from '@Components/RadixComponents/Switch';
import FileUpload from '@Components/common/UploadArea';
import {
FinalOutputOptions,
measurementTypeOptions,
} from '@Constants/createProject';
import { Controller } from 'react-hook-form';
import OutputOptions from './OutputOptions';

const FinalOutputOptions = [
{ label: '2D Orthophoto', value: 'ORTHOPHOTO_2D', icon: orthoPhotoIcon },
{ label: '3D Model', value: 'ORTHOPHOTO_3D', icon: _3DModal },
{
label: 'Digital Terrain Model (DTM)',
value: 'DIGITAL_TERRAIN_MODEL',
icon: DTMIcon,
},
{
label: 'Digital Surface Model (DSM)',
value: 'DIGITAL_SURFACE_MODEL',
icon: DSMIcon,
},
];

const KeyParameters = ({ formProps }: { formProps: UseFormPropsType }) => {
const dispatch = useTypedDispatch();

const { register, errors, watch, control } = formProps;
const { register, errors, watch, control, setValue } = formProps;
const final_output = watch('final_output');

const keyParamOption = useTypedSelector(
state => state.createproject.keyParamOption,
);
const measurementType = useTypedSelector(
state => state.createproject.measurementType,
);
const isTerrainFollow = useTypedSelector(
state => state.createproject.isTerrainFollow,
);
Expand All @@ -60,18 +48,49 @@ const KeyParameters = ({ formProps }: { formProps: UseFormPropsType }) => {
/> */}
{keyParamOption === 'basic' ? (
<>
<FormControl className="naxatw-mt-4 naxatw-gap-1">
<Label required>Ground Sampling Distance (meter)</Label>
<Input
placeholder="Enter GSD in meter"
type="number"
{...register('gsd_cm_px', {
required: 'GSD is required',
valueAsNumber: true,
})}
<FormControl>
<Label>Measurement Type</Label>
<RadioButton
options={measurementTypeOptions}
direction="row"
onChangeData={val => {
dispatch(setCreateProjectState({ measurementType: val }));
setValue('gsd_cm_px', '');
setValue('altitude_from_ground', '');
}}
value={measurementType}
/>
<ErrorMessage message={errors?.gsd_cm_px?.message as string} />
</FormControl>

{measurementType === 'gsd' ? (
<FormControl className="naxatw-mt-4 naxatw-gap-1">
<Label required>Ground Sampling Distance (meter)</Label>
<Input
placeholder="Enter GSD in meter"
type="number"
{...register('gsd_cm_px', {
required: 'GSD is required',
valueAsNumber: true,
})}
/>
<ErrorMessage message={errors?.gsd_cm_px?.message as string} />
</FormControl>
) : (
<FormControl className="naxatw-mt-4 naxatw-gap-1">
<Label required>Altitude From Ground (meter)</Label>
<Input
placeholder="Enter Altitude From Ground in meter"
type="number"
{...register('altitude_from_ground', {
required: 'Altitude From Round is Required',
valueAsNumber: true,
})}
/>
<ErrorMessage
message={errors?.altitude_from_ground?.message as string}
/>
</FormControl>
)}
<FlexRow className="naxatw-grid naxatw-grid-cols-2 naxatw-gap-3">
<FormControl className="naxatw-mt-4 naxatw-gap-1">
<Label required>Front Overlap in (%)</Label>
Expand All @@ -88,7 +107,7 @@ const KeyParameters = ({ formProps }: { formProps: UseFormPropsType }) => {
<ErrorMessage
message={errors?.forward_overlap_percent?.message as string}
/>
<p className="naxatw-text-[#68707F]">Recommended - 75%</p>
<p className="naxatw-text-[#68707F]">Recommended : 75%</p>
</FormControl>
<FormControl className="naxatw-mt-4 naxatw-gap-1">
<Label required>Side Overlap in (%)</Label>
Expand All @@ -105,7 +124,7 @@ const KeyParameters = ({ formProps }: { formProps: UseFormPropsType }) => {
<ErrorMessage
message={errors?.side_overlap_percent?.message as string}
/>
<p className="naxatw-text-[#68707F]">Recommended - 60%</p>
<p className="naxatw-text-[#68707F]">Recommended : 60%</p>
</FormControl>
</FlexRow>
<FormControl className="naxatw-mt-4 naxatw-gap-1">
Expand Down
3 changes: 2 additions & 1 deletion src/frontend/src/components/Dashboard/RequestLogs/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { FlexColumn } from '@Components/common/Layouts';
import { Button } from '@Components/RadixComponents/Button';
import { postTaskStatus } from '@Services/project';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import hasErrorBoundary from '@Utils/hasErrorBoundary';
import { toast } from 'react-toastify';

const RequestLogs = () => {
Expand Down Expand Up @@ -79,4 +80,4 @@ const RequestLogs = () => {
</div>
);
};
export default RequestLogs;
export default hasErrorBoundary(RequestLogs);
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { useParams } from 'react-router-dom';
import { useGetIndividualTaskQuery } from '@Api/tasks';
import { useTypedSelector } from '@Store/hooks';
import { useState } from 'react';
// import { useTypedSelector } from '@Store/hooks';
import { format } from 'date-fns';
import DescriptionBoxComponent from './DescriptionComponent';
import QuestionBox from '../QuestionBox';

const DescriptionBox = () => {
const secondPageStates = useTypedSelector(state => state.droneOperatorTask);
const { secondPage } = secondPageStates;
// const secondPageStates = useTypedSelector(state => state.droneOperatorTask);
const [flyable, setFlyable] = useState('yes');
// const { secondPage } = secondPageStates;
const { taskId } = useParams();

const { data: taskDescription }: Record<string, any> =
Expand All @@ -29,7 +31,7 @@ const DescriptionBox = () => {
{
name: 'Total task area',
value: taskData?.task_area
? `${taskData?.task_area} km²`
? `${Number(taskData?.task_area)?.toFixed(3)} km²`
: null,
},
{
Expand Down Expand Up @@ -88,7 +90,8 @@ const DescriptionBox = () => {
/>
))}
</div>
{!secondPage && <QuestionBox />}
{/* {!secondPage && <QuestionBox />} */}
<QuestionBox setFlyable={setFlyable} flyable={flyable} />
</>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
/* eslint-disable jsx-a11y/interactive-supports-focus */
/* eslint-disable jsx-a11y/no-noninteractive-element-interactions */
/* eslint-disable jsx-a11y/click-events-have-key-events */
import { useState } from 'react';

import {
setSelectedImage,
unCheckImages,
} from '@Store/actions/droneOperatorTask';
import { useTypedDispatch } from '@Store/hooks';
import Skeleton from '@Components/RadixComponents/Skeleton';

interface IImageCardProps {
image: string;
Expand All @@ -23,32 +17,33 @@ const ImageCard = ({
deselectImages,
}: IImageCardProps) => {
const dispatch = useTypedDispatch();
const [loading, setLoading] = useState(true);

const handleLoad = () => {
setLoading(false);
};
return (
<>
{loading && (
<Skeleton className="naxatw-h-[8.75rem] naxatw-w-[8.75rem]" />
)}
<div
className={`naxatw-flex naxatw-w-[8.75rem] naxatw-flex-col naxatw-gap-1 ${loading ? 'naxatw-hidden' : 'naxatw-block'}`}
className="naxatw-flex naxatw-h-24 naxatw-w-[6.75rem] naxatw-flex-col naxatw-gap-1 naxatw-rounded-lg naxatw-bg-gray-100 naxatw-px-1 hover:naxatw-bg-gray-300"
role="presentation"
onClick={() => dispatch(setSelectedImage(image))}
>
<div className="naxatw-w-full naxatw-overflow-hidden naxatw-rounded-[0.25rem]">
<img
src={image}
<div className="naxatw-flex naxatw-h-16 naxatw-w-full naxatw-cursor-pointer naxatw-items-center naxatw-justify-center">
{/* <img
src={image}1
onLoad={handleLoad}
alt=""
className="naxatw-h-[8.75rem] naxatw-w-full naxatw-cursor-pointer naxatw-rounded-[0.25rem] naxatw-transition hover:naxatw-scale-150"
onClick={() => dispatch(setSelectedImage(image))}
/>
/> */}
<i className="material-icons naxatw-text-[65px] naxatw-text-gray-400">
image
</i>
</div>
<div
role="button"
role="presentation"
className="naxatw-flex naxatw-w-full naxatw-cursor-pointer naxatw-items-center naxatw-gap-2 naxatw-overflow-hidden"
onClick={() => dispatch(unCheckImages(deselectImages))}
onClick={e => {
e.stopPropagation();
dispatch(unCheckImages(deselectImages));
}}
>
<input
type="checkbox"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { useTypedSelector } from '@Store/hooks';

const PreviewImage = () => {
const { clickedImage } = useTypedSelector(state => state.droneOperatorTask);
const clickedImage = useTypedSelector(
state => state.droneOperatorTask.clickedImage,
);
return (
<img
src={clickedImage}
Expand Down
Loading
Loading