Skip to content

Commit

Permalink
feat(frontend): add popup for task feature (entity) selection with li…
Browse files Browse the repository at this point in the history
…nk to odk by intent
  • Loading branch information
spwoodcock committed Apr 16, 2024
1 parent 29f93d3 commit 2557ce7
Show file tree
Hide file tree
Showing 8 changed files with 200 additions and 38 deletions.
14 changes: 14 additions & 0 deletions src/frontend/src/api/Project.js
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,20 @@ export const GetProjectDashboard = (url) => {
};
};

export const GetEntityInfo = (url) => {
return async (dispatch) => {
const getEntityOsmMap = async (url) => {
try {
const response = await CoreModules.axios.get(url);
dispatch(ProjectActions.SetEntityOsmMap(response.data));
} catch (error) {
} finally {
}
};
await getEntityOsmMap(url);
};
};

export const GetProjectComments = (url) => {
return async (dispatch) => {
const getProjectComments = async (url) => {
Expand Down
108 changes: 108 additions & 0 deletions src/frontend/src/components/ProjectDetailsV2/FeatureSelectionPopup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// Popup used to display task feature info & link to ODK Collect

import React from 'react';
import CoreModules from '@/shared/CoreModules';
import AssetModules from '@/shared/AssetModules';
import Button from '@/components/common/Button';
import { ProjectActions } from '@/store/slices/ProjectSlice';

type TaskFeatureSelectionProperties = {
osm_id: number;
tags: string;
timestamp: string;
version: number;
changeset: number;
};

type TaskFeatureSelectionPopupPropType = {
featureProperties: TaskFeatureSelectionProperties | null;
};

const TaskFeatureSelectionPopup = ({ featureProperties }: TaskFeatureSelectionPopupPropType) => {
const dispatch = CoreModules.useAppDispatch();
const taskModalStatus = CoreModules.useAppSelector((state) => state.project.taskModalStatus);
const projectInfo = CoreModules.useAppSelector((state) => state.project.projectInfo);
const entityOsmMap = CoreModules.useAppSelector((state) => state.project.entityOsmMap);
return (
<div
className={`fmtm-duration-1000 fmtm-z-[10002] fmtm-h-fit ${
taskModalStatus
? 'fmtm-bottom-[4.4rem] md:fmtm-top-[50%] md:-fmtm-translate-y-[35%] fmtm-right-0 fmtm-w-[100vw] md:fmtm-w-[50vw] md:fmtm-max-w-[25rem]'
: 'fmtm-top-[calc(100vh)] md:fmtm-top-[calc(40vh)] md:fmtm-left-[calc(100vw)] fmtm-w-[100vw]'
} fmtm-fixed
fmtm-rounded-t-3xl fmtm-border-opacity-50`}
>
<div
className={`fmtm-absolute fmtm-top-[17px] fmtm-right-[20px] ${
taskModalStatus ? '' : 'fmtm-hidden'
} fmtm-cursor-pointer fmtm-flex fmtm-items-center fmtm-gap-3`}
>
<div title="Close">
<AssetModules.CloseIcon
style={{ width: '20px' }}
className="hover:fmtm-text-primaryRed"
onClick={() => dispatch(ProjectActions.ToggleTaskModalStatus(false))}
/>
</div>
</div>
<div
className={`fmtm-bg-[#fbfbfb] ${
taskModalStatus ? 'sm:fmtm-shadow-[-20px_0px_60px_25px_rgba(0,0,0,0.2)] fmtm-border-b sm:fmtm-border-b-0' : ''
} fmtm-rounded-t-2xl md:fmtm-rounded-tr-none md:fmtm-rounded-l-2xl`}
>
<div className="fmtm-flex fmtm-flex-col fmtm-gap-2 fmtm-p-3 sm:fmtm-p-5">
<h4 className="fmtm-text-lg fmtm-font-bold">Feature: {featureProperties?.osm_id}</h4>
</div>

<div className="fmtm-h-fit fmtm-p-2 sm:fmtm-p-5 fmtm-border-t">
<div className="fmtm-flex fmtm-flex-col fmtm-gap-1 fmtm-mt-1">
<p>
<span className="fmtm-font-semibold">Tags: </span>
<span className="fmtm-text-primaryRed fmtm-overflow-hidden fmtm-line-clamp-2">
{featureProperties?.tags}
</span>
</p>
<p>
<span className="fmtm-font-semibold">Timestamp: </span>
<span className="fmtm-text-primaryRed">{featureProperties?.timestamp}</span>
</p>
<p>
<span className="fmtm-font-semibold">Changeset: </span>
<span className="fmtm-text-primaryRed">{featureProperties?.changeset}</span>
</p>
<p>
<span className="fmtm-font-semibold">Version: </span>
<span className="fmtm-text-primaryRed">{featureProperties?.version}</span>
</p>
</div>
</div>

<div className="fmtm-p-2 sm:fmtm-p-5 fmtm-border-t">
<Button
btnText="OPEN FEATURE IN ODK"
btnType="primary"
type="submit"
className="fmtm-font-bold !fmtm-rounded fmtm-text-sm !fmtm-py-2 !fmtm-w-full fmtm-flex fmtm-justify-center"
onClick={() => {
// XForm name is constructed from lower case project title with underscores
const projectName = projectInfo.title.toLowerCase().split(' ').join('_');
const projectCategory = projectInfo.xform_category;
const formName = `${projectName}_${projectCategory}`;

const entity = entityOsmMap.find((x) => x.osm_id === featureProperties?.osm_id);
const entityUuid = entity ? entity.id : null;

if (!formName || !entityUuid) {
return;
}

document.location.href = `odkcollect://form/${formName}?existing=${entityUuid}`;
}}
/>
</div>
</div>
</div>
);
};

export default TaskFeatureSelectionPopup;
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ const TaskSelectionPopup = ({ taskId, body, feature }: TaskSelectionPopupPropTyp
style={{ width: '20px' }}
className="fmtm-text-primaryRed group-hover:fmtm-text-red-700"
/>
<p className="fmtm-text-base fmtm-text-primaryRed group-hover:fmtm-text-red-700">MB TILES</p>
<p className="fmtm-text-base fmtm-text-primaryRed group-hover:fmtm-text-red-700">Basemaps</p>
</div>
<div title="Close">
<AssetModules.CloseIcon
Expand Down
8 changes: 8 additions & 0 deletions src/frontend/src/store/slices/ProjectSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const initialState: ProjectStateTypes = {
total_contributors: null,
last_active: '',
},
entityOsmMap: [],
projectDashboardLoading: false,
geolocationStatus: false,
projectCommentsList: [],
Expand Down Expand Up @@ -100,6 +101,13 @@ const ProjectSlice = createSlice({
SetProjectDashboardDetail(state, action) {
state.projectDashboardDetail = action.payload;
},
SetEntityOsmMap(state, action) {
// Convert osm_id to int before mapping to state
state.entityOsmMap = action.payload.map((entity) => ({
...entity,
osm_id: entity.osm_id ? parseInt(entity.osm_id, 10) : null,
}));
},
SetProjectDashboardLoading(state, action) {
state.projectDashboardLoading = action.payload;
},
Expand Down
6 changes: 6 additions & 0 deletions src/frontend/src/store/slices/TaskSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const initialState: TaskStateTypes = {
taskLoading: false,
taskInfo: [],
selectedTask: null,
selectedFeatureProps: null,
projectBoundaryLoading: false,
projectBoundary: [],
convertToOsmLoading: false,
Expand Down Expand Up @@ -45,10 +46,15 @@ const TaskSlice = createSlice({
const tasks = taskInfo.length;
state.taskData = { ...featureSubmissionCount, task_count: tasks };
},

SetSelectedTask(state, action) {
state.selectedTask = action.payload;
},

SetSelectedFeatureProps(state, action) {
state.selectedFeatureProps = action.payload;
},

GetDownloadProjectBoundary(state, action) {
state.projectBoundary = action.payload;
},
Expand Down
8 changes: 8 additions & 0 deletions src/frontend/src/store/types/IProject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export type ProjectStateTypes = {
mobileFooterSelection: string;
projectDetailsLoading: boolean;
projectDashboardDetail: projectDashboardDetailTypes;
entityOsmMap: EntityOsmMap[];
projectDashboardLoading: boolean;
geolocationStatus: boolean;
projectCommentsList: projectCommentsListTypes[];
Expand All @@ -35,6 +36,13 @@ export type ProjectStateTypes = {
projectActivityLoading: boolean;
};

type EntityOsmMap = {
id: string;
osm_id: string;
status: number;
updated_at: string;
};

type tilesListTypes = {
id: number;
project_id: number;
Expand Down
1 change: 1 addition & 0 deletions src/frontend/src/store/types/ITask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export type TaskStateTypes = {
taskLoading: boolean;
taskInfo: taskInfoType[];
selectedTask: number | null;
selectedFeatureProps: number | null;
projectBoundaryLoading: boolean;
projectBoundary: [];
convertToOsmLoading: boolean;
Expand Down
Loading

0 comments on commit 2557ce7

Please sign in to comment.