Skip to content

Commit

Permalink
Feat: Implement gcp editor package (#424)
Browse files Browse the repository at this point in the history
* feat: add gcp editor package

* feat: add start processing button on project description about section

* feat(individual-project): create GcpEditor react component from the web component

* feat: add services for all imagery porcess

* feat: store gcp editor visible control and gcp data on redux

* feat(individual-project): show gcp editor
  • Loading branch information
suzit-10 authored Jan 2, 2025
1 parent bcb5b16 commit 6298213
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 31 deletions.
5 changes: 3 additions & 2 deletions src/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"dependencies": {
"@cyntler/react-doc-viewer": "^1.17.0",
"@geomatico/maplibre-cog-protocol": "^0.3.1",
"@hotosm/gcp-editor": "^0.0.6",
"@mapbox/mapbox-gl-draw": "^1.4.2",
"@mapbox/mapbox-gl-draw-static-mode": "^1.0.1",
"@radix-ui/react-popover": "^1.0.6",
Expand All @@ -14,22 +15,22 @@
"@tanstack/react-query-devtools": "^4.32.6",
"@tanstack/react-table": "^8.9.3",
"@turf/area": "^7.0.0",
"@turf/transform-rotate" : "^7.1.0",
"@turf/bbox": "^7.0.0",
"@turf/centroid": "^7.0.0",
"@turf/flatten": "^7.0.0",
"@turf/helpers": "^7.0.0",
"@turf/length": "^7.0.0",
"@turf/meta": "^7.0.0",
"@turf/transform-rotate": "^7.1.0",
"autoprefixer": "^10.4.14",
"axios": "^1.3.4",
"class-variance-authority": "^0.6.1",
"clsx": "^2.0.0",
"countries-list": "^3.1.1",
"exifreader": "^4.25.0",
"date-fns": "^2.30.0",
"dom-to-code": "^1.5.4",
"dotenv": "^16.0.3",
"exifreader": "^4.25.0",
"framer-motion": "^11.2.9",
"geojson": "^0.5.0",
"geojson-validation": "^1.0.2",
Expand Down
52 changes: 52 additions & 0 deletions src/frontend/src/components/IndividualProject/GcpEditor/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { useEffect, createElement } from 'react';
import '@hotosm/gcp-editor';
import '@hotosm/gcp-editor/style.css';
import { useDispatch } from 'react-redux';
import { setProjectState } from '@Store/actions/project';
import { useMutation } from '@tanstack/react-query';
import { processAllImagery } from '@Services/project';
import { useParams } from 'react-router-dom';

const GcpEditor = ({
cogUrl,
finalButtonText,
// handleProcessingStart,
rawImageUrl,
}: any) => {
const { id } = useParams();
const dispatch = useDispatch();
const CUSTOM_EVENT: any = 'start-processing-click';

const { mutate: startImageProcessing } = useMutation({
mutationFn: processAllImagery,
onSuccess: () => {
dispatch(setProjectState({ showGcpEditor: false }));
},
});

const startProcessing = (data: any) => {
const gcpData = data.detail;
const blob = new Blob([gcpData], { type: 'text/plain;charset=utf-8;' });
const gcpFile = new File([blob], 'gcp.txt');
startImageProcessing({ projectId: id, gcp_file: gcpFile });
};

useEffect(() => {
document.addEventListener(CUSTOM_EVENT, data => {
startProcessing(data);
});
return document.removeEventListener(CUSTOM_EVENT, data => {
startProcessing(data);
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [CUSTOM_EVENT, dispatch]);

return createElement('gcp-editor', {
cogUrl,
customEvent: CUSTOM_EVENT,
finalButtonText,
rawImageUrl,
});
};

export default GcpEditor;
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { useDispatch } from 'react-redux';
import { Button } from '@Components/RadixComponents/Button';
import { setProjectState } from '@Store/actions/project';
import ApprovalSection from './ApprovalSection';

const DescriptionSection = ({
Expand All @@ -7,6 +10,7 @@ const DescriptionSection = ({
projectData: Record<string, any>;
page?: 'project-description' | 'project-approval';
}) => {
const dispatch = useDispatch();
return (
<div className="naxatw-mt-4 naxatw-flex naxatw-flex-col naxatw-gap-3">
{page === 'project-approval' && (
Expand Down Expand Up @@ -62,6 +66,18 @@ const DescriptionSection = ({
)}
</div>
</div>
{page !== 'project-approval' && (
<div>
<Button
className="naxatw-bg-red"
onClick={() => {
dispatch(setProjectState({ showGcpEditor: true }));
}}
>
Start Processing
</Button>
</div>
)}
{page === 'project-approval' &&
projectData?.regulator_approval_status === 'PENDING' && (
<ApprovalSection />
Expand Down
9 changes: 9 additions & 0 deletions src/frontend/src/services/project.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable camelcase */
/* eslint-disable import/prefer-default-export */
import { authenticated, api } from '.';

Expand All @@ -13,5 +14,13 @@ export const postTaskStatus = (payload: Record<string, any>) => {
export const getRequestedTasks = () =>
authenticated(api).get('/tasks/requested_tasks/pending');

export const processAllImagery = (data: Record<string, any>) => {
const { projectId, gcp_file } = data;
return authenticated(api).post(
`/projects/process_all_imagery/${projectId}/`,
{ gcp_file },
);
};

// export const getAllAssetsUrl = (projectId: string) =>
// authenticated(api).get(`/projects/assets/${projectId}/`);
4 changes: 4 additions & 0 deletions src/frontend/src/store/slices/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ export interface ProjectState {
projectArea: Record<string, any> | null;
selectedTaskId: string;
taskClickedOnTable: Record<string, any> | null;
showGcpEditor: boolean;
gcpData: any;
}

const initialState: ProjectState = {
Expand All @@ -16,6 +18,8 @@ const initialState: ProjectState = {
projectArea: null,
selectedTaskId: '',
taskClickedOnTable: null,
showGcpEditor: false,
gcpData: null,
};

const setProjectState: CaseReducer<
Expand Down
96 changes: 67 additions & 29 deletions src/frontend/src/views/IndividualProject/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
MapSection,
Tasks,
} from '@Components/IndividualProject';
import GcpEditor from '@Components/IndividualProject/GcpEditor';
import Skeleton from '@Components/RadixComponents/Skeleton';
import DescriptionSection from '@Components/RegulatorsApprovalPage/Description/DescriptionSection';
import { projectOptions } from '@Constants/index';
Expand All @@ -18,6 +19,9 @@ import centroid from '@turf/centroid';
import hasErrorBoundary from '@Utils/hasErrorBoundary';
import { useParams } from 'react-router-dom';

// eslint-disable-next-line camelcase
const { BASE_URL } = process.env;

// function to render the content based on active tab
const getActiveTabContent = (
activeTab: string,
Expand Down Expand Up @@ -60,6 +64,7 @@ const IndividualProject = () => {
state => state.project.individualProjectActiveTab,
);
const tasksList = useTypedSelector(state => state.project.tasksData);
const showGcpEditor = useTypedSelector(state => state.project.showGcpEditor);

const {
data: projectData,
Expand Down Expand Up @@ -106,6 +111,20 @@ const IndividualProject = () => {
return {};
};

// const { mutate: startImageProcessing } = useMutation({
// mutationFn: processAllImagery,
// onSuccess: () => {
// dispatch(setProjectState({ showGcpEditor: false }));
// },
// });

// useEffect(() => {
// if (!gcpData || !showGcpEditor) return;
// const blob = new Blob([gcpData], { type: 'text/plain;charset=utf-8;' });
// const gcpFile = new File([blob], 'gcp.txt');
// startImageProcessing({ projectId: id, gcp_file: gcpFile });
// }, [gcpData, id]);

return (
<section className="individual project naxatw-h-screen-nav naxatw-px-3 naxatw-py-8 lg:naxatw-px-20">
<BreadCrumb
Expand All @@ -114,39 +133,58 @@ const IndividualProject = () => {
{ name: projectData?.name || '--', navLink: '' },
]}
/>
<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-[30rem]">
<Tab
orientation="row"
className="naxatw-bg-transparent hover:naxatw-border-b-2 hover:naxatw-border-red"
activeClassName="naxatw-border-b-2 naxatw-bg-transparent naxatw-border-red"
onTabChange={(val: string | number) =>
dispatch(
setProjectState({ individualProjectActiveTab: String(val) }),
)
}
tabOptions={projectOptions}
activeTab={individualProjectActiveTab}
clickable
{showGcpEditor ? (
<div className="naxatw-relative naxatw-h-full naxatw-bg-slate-300">
<button
type="button"
className="material-icons naxatw-absolute naxatw-right-4 naxatw-top-2 naxatw-cursor-pointer hover:naxatw-text-red"
onClick={() => {
dispatch(setProjectState({ showGcpEditor: false }));
}}
>
close
</button>
<GcpEditor
finalButtonText="Final Processing"
// handleProcessingStart={handleStartProcessingClick}
// eslint-disable-next-line camelcase
rawImageUrl={`${BASE_URL}/gcp/find-project-images/?project_id=${id}`}
/>
<div className="naxatw-h-fit naxatw-max-h-[calc(200px)] naxatw-border-t">
{getActiveTabContent(
individualProjectActiveTab,
projectData as Record<string, any>,
isProjectDataFetching,
handleTableRowClick,
</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-[30rem]">
<Tab
orientation="row"
className="naxatw-bg-transparent hover:naxatw-border-b-2 hover:naxatw-border-red"
activeClassName="naxatw-border-b-2 naxatw-bg-transparent naxatw-border-red"
onTabChange={(val: string | number) =>
dispatch(
setProjectState({ individualProjectActiveTab: String(val) }),
)
}
tabOptions={projectOptions}
activeTab={individualProjectActiveTab}
clickable
/>
<div className="naxatw-h-fit naxatw-max-h-[calc(200px)] naxatw-border-t">
{getActiveTabContent(
individualProjectActiveTab,
projectData as Record<string, any>,
isProjectDataFetching,
handleTableRowClick,
)}
</div>
</div>
<div className="naxatw-order-1 naxatw-h-[calc(100vh-10rem)] naxatw-w-full md:naxatw-order-2">
{isProjectDataFetching ? (
<Skeleton className="naxatw-h-full naxatw-w-full" />
) : (
<MapSection projectData={projectData as Record<string, any>} />
)}
</div>
</div>

<div className="naxatw-order-1 naxatw-h-[calc(100vh-10rem)] naxatw-w-full md:naxatw-order-2">
{isProjectDataFetching ? (
<Skeleton className="naxatw-h-full naxatw-w-full" />
) : (
<MapSection projectData={projectData as Record<string, any>} />
)}
</div>
</div>
)}
</section>
);
};
Expand Down

0 comments on commit 6298213

Please sign in to comment.