Skip to content

Commit

Permalink
Merge pull request #236 from hotosm/feat/change-take-off-point
Browse files Browse the repository at this point in the history
Feat: Implement task unlock feature and make project description responsive
  • Loading branch information
nrjadkry authored Sep 26, 2024
2 parents dc49e30 + b330474 commit 9b4964b
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,16 @@ const GetCoordinatesOnClick = ({
useEffect(() => {
if (!map || !isMapLoaded) return () => {};
map.getCanvas().style.cursor = 'crosshair';
map.on('click', e => {

const handleClick = (e: any) => {
const latLng = e.lngLat;
getCoordinates(latLng);
});
};
map.on('click', handleClick);

return () => {
map.getCanvas().style.cursor = '';
map.off('click', handleClick);
};
}, [map, isMapLoaded, getCoordinates]);
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ import { GeojsonType } from '@Components/common/MapLibreComponents/types';
import { Button } from '@Components/RadixComponents/Button';
import { postTaskWaypoint } from '@Services/tasks';
import { toggleModal } from '@Store/actions/common';
import { setSelectedTakeOffPoint } from '@Store/actions/droneOperatorTask';
import {
setSelectedTakeOffPoint,
setSelectedTakeOffPointOption,
} from '@Store/actions/droneOperatorTask';
import { useTypedSelector } from '@Store/hooks';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import getBbox from '@turf/bbox';
Expand Down Expand Up @@ -81,6 +84,7 @@ const MapSection = ({ className }: { className?: string }) => {
return data;
});
dispatch(setSelectedTakeOffPoint(null));
dispatch(setSelectedTakeOffPointOption('current_location'));
},
onError: (err: any) => {
toast.error(err?.response?.data?.detail || err.message);
Expand Down Expand Up @@ -158,6 +162,7 @@ const MapSection = ({ className }: { className?: string }) => {
useEffect(
() => () => {
dispatch(setSelectedTakeOffPoint(null));
dispatch(setSelectedTakeOffPointOption('current_location'));
},
[dispatch],
);
Expand Down
59 changes: 43 additions & 16 deletions src/frontend/src/components/IndividualProject/MapSection/index.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,29 @@
/* eslint-disable no-nested-ternary */
/* eslint-disable no-unused-vars */
import { useNavigate, useParams } from 'react-router-dom';
import { useCallback, useEffect, useState } from 'react';
import { useTypedSelector, useTypedDispatch } from '@Store/hooks';
import { useMapLibreGLMap } from '@Components/common/MapLibreComponents';
import VectorLayer from '@Components/common/MapLibreComponents/Layers/VectorLayer';
import MapContainer from '@Components/common/MapLibreComponents/MapContainer';
import { GeojsonType } from '@Components/common/MapLibreComponents/types';
import AsyncPopup from '@Components/common/MapLibreComponents/AsyncPopup';
import getBbox from '@turf/bbox';
import { FeatureCollection } from 'geojson';
import { GeolocateControl, LngLatBoundsLike, Map } from 'maplibre-gl';
import { setProjectState } from '@Store/actions/project';
import {
useGetProjectsDetailQuery,
useGetTaskStatesQuery,
useGetUserDetailsQuery,
} from '@Api/projects';
import lock from '@Assets/images/lock.png';
import BaseLayerSwitcherUI from '@Components/common/BaseLayerSwitcher';
import { useMapLibreGLMap } from '@Components/common/MapLibreComponents';
import AsyncPopup from '@Components/common/MapLibreComponents/AsyncPopup';
import VectorLayer from '@Components/common/MapLibreComponents/Layers/VectorLayer';
import LocateUser from '@Components/common/MapLibreComponents/LocateUser';
import MapContainer from '@Components/common/MapLibreComponents/MapContainer';
import { GeojsonType } from '@Components/common/MapLibreComponents/types';
import { postTaskStatus } from '@Services/project';
import { setProjectState } from '@Store/actions/project';
import { useTypedDispatch, useTypedSelector } from '@Store/hooks';
import { useMutation } from '@tanstack/react-query';
import { toast } from 'react-toastify';
import getBbox from '@turf/bbox';
import hasErrorBoundary from '@Utils/hasErrorBoundary';
import baseLayersData from '@Components/common/MapLibreComponents/BaseLayerSwitcher/baseLayers';
import BaseLayerSwitcherUI from '@Components/common/BaseLayerSwitcher';
import LocateUser from '@Components/common/MapLibreComponents/LocateUser';
import { FeatureCollection } from 'geojson';
import { LngLatBoundsLike, Map } from 'maplibre-gl';
import { useCallback, useEffect, useState } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { toast } from 'react-toastify';
import Legend from './Legend';

const MapSection = () => {
Expand Down Expand Up @@ -85,6 +84,20 @@ const MapSection = () => {
},
});

const { mutate: unLockTask } = useMutation<any, any, any, unknown>({
mutationFn: postTaskStatus,
onSuccess: (res: any) => {
setTaskStatusObj({
...taskStatusObj,
[res.data.task_id]: 'UNLOCKED_TO_MAP',
});
toast.success('Task Unlocked Successfully');
},
onError: (err: any) => {
toast.error(err.message);
},
});

useEffect(() => {
if (!map || !taskStates) return;
// @ts-ignore
Expand Down Expand Up @@ -149,6 +162,14 @@ const MapSection = () => {
});
};

const handleTaskUnLockClick = () => {
unLockTask({
projectId: id,
taskId: selectedTaskId,
data: { event: 'unlock' },
});
};

return (
<MapContainer
map={map}
Expand Down Expand Up @@ -293,6 +314,12 @@ const MapSection = () => {
? handleTaskLockClick()
: navigate(`/projects/${id}/tasks/${selectedTaskId}`)
}
hasSecondaryButton={
taskStatusObj?.[selectedTaskId] === 'LOCKED_FOR_MAPPING' &&
lockedUser?.id === userDetails?.id
}
secondaryButtonText="Unlock Task"
handleSecondaryBtnClick={() => handleTaskUnLockClick()}
/>
<Legend />
</MapContainer>
Expand Down
17 changes: 9 additions & 8 deletions src/frontend/src/components/Projects/MapSection/index.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { useCallback, useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { useMapLibreGLMap } from '@Components/common/MapLibreComponents';
import MapContainer from '@Components/common/MapLibreComponents/MapContainer';
import BaseLayerSwitcher from '@Components/common/MapLibreComponents/BaseLayerSwitcher';
import { useGetProjectsListQuery } from '@Api/projects';
import hasErrorBoundary from '@Utils/hasErrorBoundary';
import centroid from '@turf/centroid';
import { LngLatBoundsLike, Map } from 'maplibre-gl';
import getBbox from '@turf/bbox';
import { useCallback, useEffect, useState } from 'react';
import centroid from '@turf/centroid';
import { FeatureCollection } from 'geojson';
import { useGetProjectsListQuery } from '@Api/projects';
import { useMapLibreGLMap } from '@Components/common/MapLibreComponents';
import AsyncPopup from '@Components/common/MapLibreComponents/AsyncPopup';
import { LngLatBoundsLike, Map } from 'maplibre-gl';
import BaseLayerSwitcher from '@Components/common/MapLibreComponents/BaseLayerSwitcher';
import MapContainer from '@Components/common/MapLibreComponents/MapContainer';
import hasErrorBoundary from '@Utils/hasErrorBoundary';
import VectorLayerWithCluster from './VectorLayerWithCluster';

const ProjectsMapSection = () => {
Expand Down Expand Up @@ -78,6 +78,7 @@ const ProjectsMapSection = () => {
style={{
width: '100%',
height: '100%',
borderRadius: '8px',
}}
>
<BaseLayerSwitcher />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useState } from 'react';
import useOutsideClick from '@Hooks/useOutsideClick';
import { useState } from 'react';
import BaseLayerSwitcher from '../MapLibreComponents/BaseLayerSwitcher';
import baseLayersData from '../MapLibreComponents/BaseLayerSwitcher/baseLayers';
import { MapInstanceType } from '../MapLibreComponents/types';
Expand Down Expand Up @@ -27,6 +27,7 @@ const BaseLayerSwitcherUI = ({
handleToggle();
}}
role="presentation"
title="Layer Switcher"
>
<i className="material-icons-outlined naxatw-text-xl naxatw-font-black">
layers
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
/* eslint-disable no-unused-vars */
/* eslint-disable react/no-danger */
import { useEffect, useRef, useState } from 'react';
import { renderToString } from 'react-dom/server';
import { Popup } from 'maplibre-gl';
import type { MapMouseEvent } from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';
import '@Components/common/MapLibreComponents/map.css';
import { Button } from '@Components/RadixComponents/Button';
import Skeleton from '@Components/RadixComponents/Skeleton';
import type { MapMouseEvent } from 'maplibre-gl';
import { Popup } from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';
import { useEffect, useRef, useState } from 'react';
import { renderToString } from 'react-dom/server';
import { IAsyncPopup } from '../types';

const popup = new Popup({
Expand All @@ -26,6 +26,9 @@ export default function AsyncPopup({
buttonText = 'View More',
hideButton = false,
getCoordOnProperties = false,
hasSecondaryButton = false,
secondaryButtonText = '',
handleSecondaryBtnClick,
showPopup = (_clickedFeature: Record<string, any>) => true,
}: IAsyncPopup) {
const [properties, setProperties] = useState<Record<string, any> | null>(
Expand Down Expand Up @@ -106,14 +109,27 @@ export default function AsyncPopup({
</div>
<div dangerouslySetInnerHTML={{ __html: popupHTML }} />
{!isLoading && !hideButton && (
<div className="naxatw-flex naxatw-items-center naxatw-p-3">
<Button
className="naxatw-mx-auto naxatw-bg-red naxatw-font-primary naxatw-text-white"
size="sm"
onClick={() => handleBtnClick?.(properties)}
>
{buttonText}
</Button>
<div className="naxatw-flex naxatw-w-full naxatw-justify-center naxatw-pt-3">
<div className="naxatw-flex naxatw-gap-2">
{hasSecondaryButton && (
<Button
className="naxatw-mx-auto naxatw-border-red naxatw-font-primary naxatw-text-red"
size="sm"
variant="outline"
onClick={() => handleSecondaryBtnClick?.(properties)}
>
{secondaryButtonText}
</Button>
)}

<Button
className="naxatw-mx-auto naxatw-bg-red naxatw-font-primary naxatw-text-white"
size="sm"
onClick={() => handleBtnClick?.(properties)}
>
{buttonText}
</Button>
</div>
</div>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/* eslint-disable no-unused-vars */
import type { ReactElement } from 'react';
import type { Map, MapOptions } from 'maplibre-gl';
import type { Feature, FeatureCollection, GeoJsonTypes } from 'geojson';
import type { DrawMode } from '@mapbox/mapbox-gl-draw';
import type { Feature, FeatureCollection, GeoJsonTypes } from 'geojson';
import type { Map, MapOptions } from 'maplibre-gl';
import type { ReactElement } from 'react';

export type MapInstanceType = Map;

Expand Down Expand Up @@ -83,6 +83,9 @@ export interface IAsyncPopup {
hideButton?: boolean;
getCoordOnProperties?: boolean;
showPopup?: (clickedFeature: Record<string, any>) => Boolean;
hasSecondaryButton?: boolean;
secondaryButtonText?: string;
handleSecondaryBtnClick?: (properties: Record<string, any>) => void;
}

export type DrawModeTypes = DrawMode | null | undefined;
Expand Down
31 changes: 15 additions & 16 deletions src/frontend/src/views/IndividualProject/index.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
/* eslint-disable jsx-a11y/interactive-supports-focus */
/* eslint-disable jsx-a11y/click-events-have-key-events */
import { useParams, useNavigate } from 'react-router-dom';
import { useTypedDispatch, useTypedSelector } from '@Store/hooks';
import { Flex } from '@Components/common/Layouts';
import { useGetProjectsDetailQuery } from '@Api/projects';
import Tab from '@Components/common/Tabs';
import {
Contributions,
Instructions,
MapSection,
Tasks,
Instructions,
Contributions,
} from '@Components/IndividualProject';
import { useGetProjectsDetailQuery } from '@Api/projects';
import { setProjectState } from '@Store/actions/project';
import { projectOptions } from '@Constants/index';
import { setProjectState } from '@Store/actions/project';
import { useTypedDispatch, useTypedSelector } from '@Store/hooks';
import hasErrorBoundary from '@Utils/hasErrorBoundary';
import { useNavigate, useParams } from 'react-router-dom';

// function to render the content based on active tab
const getActiveTabContent = (
Expand Down Expand Up @@ -66,28 +65,28 @@ const IndividualProject = () => {
});

return (
<section className="individual project naxatw-h-screen-nav naxatw-px-16 naxatw-py-8 xl:naxatw-px-20">
<section className="individual project naxatw-h-screen-nav naxatw-px-3 naxatw-py-8 lg:naxatw-px-20">
{/* <----------- temporary breadcrumb -----------> */}
<div className="breadcrumb naxatw-py-4">
<div className="breadcrumb naxatw-line-clamp-1 naxatw-flex naxatw-py-4">
<span
role="button"
className="naxatw-cursor-pointer naxatw-text-body-md"
className="naxatw-cursor-pointer naxatw-whitespace-nowrap naxatw-text-body-md"
onClick={() => {
navigate('/projects');
}}
>
Project /
</span>
<span className="naxatw-ml-1 naxatw-text-body-md naxatw-font-semibold">
<span className="naxatw-ml-1 naxatw-line-clamp-1 naxatw-text-body-md naxatw-font-semibold">
{
// @ts-ignore
projectData?.name || '--'
}
</span>
{/* <----------- temporary breadcrumb -----------> */}
</div>
<Flex gap={5} className="naxatw-w-full !naxatw-flex-row">
<div className="naxatw-h-[36.375rem] naxatw-w-[37.5%]">
<div className="naxatw-flex naxatw-flex-col naxatw-gap-6 md:naxatw-flex-row">
<div className="naxatw-order-2 naxatw-w-full">
<Tab
orientation="row"
className="naxatw-bg-transparent hover:naxatw-border-b-2 hover:naxatw-border-red"
Expand All @@ -99,18 +98,18 @@ const IndividualProject = () => {
activeTab={individualProjectActiveTab}
clickable
/>
<div className="naxatw-h-[92.5%] naxatw-border-t">
<div className="naxatw-h-fit naxatw-max-h-[calc(200px)] naxatw-border-t">
{getActiveTabContent(
individualProjectActiveTab,
projectData as Record<string, any>,
isProjectDataLoading,
)}
</div>
</div>
<div className="!naxatw-min-h-[calc(100vh-11rem)] naxatw-w-full naxatw-overflow-hidden naxatw-rounded-md">
<div className="naxatw-order-1 naxatw-h-[calc(100vh-10rem)] naxatw-w-full md:naxatw-order-2">
<MapSection />
</div>
</Flex>
</div>
</section>
);
};
Expand Down

0 comments on commit 9b4964b

Please sign in to comment.