Skip to content

Commit

Permalink
fix(frontend): after backend refactoring to events (#1844)
Browse files Browse the repository at this point in the history
* fix(dialogTaskActions): use task_event enum to compare btnId

* fix(submissionTable): on task validate, dispatch GOOD event

* fix(featureSelectionPopup): pass geojsonStyles as args

* fix(project): error toast display on error

* feat(submission): api integration for mappedVsValidated task chart

* fix(projectSubmissions: empty dependency add on api call)
  • Loading branch information
NSUWAL123 authored Oct 30, 2024
1 parent 8db0a04 commit 012410c
Show file tree
Hide file tree
Showing 9 changed files with 66 additions and 98 deletions.
8 changes: 8 additions & 0 deletions src/frontend/src/api/Project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,14 @@ export const UpdateEntityState = (url: string, payload: { entity_id: string; sta
dispatch(ProjectActions.UpdateEntityState(response.data));
dispatch(ProjectActions.UpdateEntityStateLoading(false));
} catch (error) {
dispatch(
CommonActions.SetSnackBar({
open: true,
message: error?.response?.data?.detail || 'Failed to update entity state.',
variant: 'error',
duration: 2000,
}),
);
dispatch(ProjectActions.UpdateEntityStateLoading(false));
}
};
Expand Down
17 changes: 17 additions & 0 deletions src/frontend/src/api/SubmissionService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,20 @@ export const UpdateReviewStateService: Function = (url: string, payload: object)
await UpdateReviewState(url);
};
};

export const MappedVsValidatedTaskService: Function = (url: string) => {
return async (dispatch) => {
const MappedVsValidatedTask = async (url: string) => {
try {
dispatch(SubmissionActions.SetMappedVsValidatedTaskLoading(true));
const response = await CoreModules.axios.get(url);
dispatch(SubmissionActions.SetMappedVsValidatedTask(response.data));
dispatch(SubmissionActions.SetMappedVsValidatedTaskLoading(false));
} catch (error) {
dispatch(SubmissionActions.SetMappedVsValidatedTaskLoading(false));
}
};

await MappedVsValidatedTask(url);
};
};
5 changes: 2 additions & 3 deletions src/frontend/src/components/DialogTaskActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { CreateTaskEvent } from '@/api/TaskEvent';
import MapStyles from '@/hooks/MapStyles';
import CoreModules from '@/shared/CoreModules';
import { CommonActions } from '@/store/slices/CommonSlice';
import { task_event as taskEventEnum, task_state as taskStateEnum } from '@/types/enums';
import { task_event as taskEventEnum, task_state as taskStateEnum, task_event } from '@/types/enums';
import Button from '@/components/common/Button';
import { useNavigate } from 'react-router-dom';
import { GetProjectTaskActivity } from '@/api/Project';
Expand Down Expand Up @@ -109,8 +109,7 @@ export default function Dialog({ taskId, feature }: dialogPropType) {
feature,
),
);
if (btnId === taskStateEnum.LOCKED_FOR_VALIDATION)
navigate(`/project-submissions/${params.id}?tab=table&task_id=${taskId}`);
if (btnId === task_event.VALIDATE) navigate(`/project-submissions/${params.id}?tab=table&task_id=${taskId}`);
} else {
dispatch(
CommonActions.SetSnackBar({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ const TaskFeatureSelectionPopup = ({ featureProperties, taskId, taskFeature }: T
return task?.id == taskId;
})?.[0],
};
const geoStyle = geojsonStyles[taskStateEnum.LOCKED_FOR_MAPPING];
const entity = entityOsmMap.find((x) => x.osm_id === featureProperties?.osm_id);

useEffect(() => {
Expand Down Expand Up @@ -142,7 +141,7 @@ const TaskFeatureSelectionPopup = ({ featureProperties, taskId, taskFeature }: T
taskId.toString(),
authDetails,
{ project_id: currentProjectId },
geoStyle,
geojsonStyles,
taskFeature,
),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ import CoreModules from '@/shared/CoreModules';
import InfographicsCard from '@/components/ProjectSubmissions/InfographicsCard';
import useDocumentTitle from '@/utilfunctions/useDocumentTitle';
import { useAppSelector } from '@/types/reduxTypes';
import { taskHistoryTypes } from '@/models/project/projectModel';
import { formSubmissionType, validatedMappedType } from '@/models/submission/submissionModel';
import { dateNDaysAgo, generateLast30Days, getMonthDate } from '@/utilfunctions/commonUtils';
import { formSubmissionType } from '@/models/submission/submissionModel';
import { dateNDaysAgo, getMonthDate } from '@/utilfunctions/commonUtils';

const SubmissionsInfographics = ({ toggleView, entities }) => {
useDocumentTitle('Submission Infographics');
Expand All @@ -19,98 +18,17 @@ const SubmissionsInfographics = ({ toggleView, entities }) => {
const totalContributorsRef = useRef(null);
const plannedVsActualRef = useRef(null);

const params = CoreModules.useParams();
const projectId = params.projectId;

const submissionContributorsData = useAppSelector((state) => state.submission.submissionContributors);
const submissionContributorsLoading = useAppSelector((state) => state.submission.submissionContributorsLoading);
const [submissionProjection, setSubmissionProjection] = useState<10 | 30>(10);
const taskInfo = useAppSelector((state) => state.task.taskInfo);
const taskLoading = useAppSelector((state) => state.task.taskLoading);
const entityOsmMapLoading = useAppSelector((state) => state.project.entityOsmMapLoading);
const projectTaskList = useAppSelector((state) => state.project.projectTaskBoundries);
const projectDetailsLoading = useAppSelector((state) => state.project.projectDetailsLoading);
const mappedVsValidatedTaskList = useAppSelector((state) => state.submission.mappedVsValidatedTask);
const mappedVsValidatedTaskLoading = useAppSelector((state) => state.submission.mappedVsValidatedTaskLoading);

const today = new Date().toISOString();
const [formSubmissionsData, setFormSubmissionsData] = useState<formSubmissionType[]>([]);
const [validatedVsMappedInfographics, setValidatedVsMappedInfographics] = useState<validatedMappedType[]>([]);

useEffect(() => {
if (!projectTaskList || (projectTaskList && projectTaskList?.length === 0)) return;

const projectIndex = projectTaskList.findIndex((project) => project.id == +projectId);
// task activities history list
const taskActivities = projectTaskList?.[projectIndex]?.taskBoundries?.reduce((acc: taskHistoryTypes[], task) => {
return [...acc, ...(task?.task_history ?? [])];
}, []);

// filter activities for last 30 days
const taskActivities30Days = taskActivities?.filter((activity) => {
const actionDate = new Date(activity?.created_at).toISOString();
return actionDate >= dateNDaysAgo(30) && actionDate <= today;
});

// only filter MAPPED & VALIDATED activities
const groupedData: validatedMappedType[] = taskActivities30Days?.reduce((acc: validatedMappedType[], activity) => {
const date = activity?.created_at.split('T')[0];
const index = acc.findIndex((submission) => submission.date === date);
if (acc?.find((submission) => submission.date === date)) {
if (activity?.comment?.includes('LOCKED_FOR_MAPPING to MAPPED')) {
acc[index].Mapped += 1;
}
if (activity?.comment?.includes('LOCKED_FOR_VALIDATION to VALIDATED')) {
acc[index].Validated += 1;
}
} else {
const splittedDate = date?.split('-');
const label = `${splittedDate[1]}/${splittedDate[2]}`;
if (activity?.comment?.includes('LOCKED_FOR_MAPPING to MAPPED')) {
acc.push({ date: date, Validated: 0, Mapped: 1, label });
}
if (activity?.comment?.includes('LOCKED_FOR_VALIDATION to VALIDATED')) {
acc.push({ date: date, Validated: 1, Mapped: 0, label });
}
}
return acc;
}, []);

// generate validatedMapped data for last 30 days
const last30Days = generateLast30Days().map((datex) => {
const mappedVsValidatedValue = groupedData?.find((group) => {
return group?.date === datex;
});

if (mappedVsValidatedValue) {
return mappedVsValidatedValue;
} else {
// if no validated-mapped date - return count of 0 for both
const splittedDate = datex?.split('-');
const label = `${splittedDate[1]}/${splittedDate[2]}`;
return { date: datex, Validated: 0, Mapped: 0, label: label };
}
});

// sort by ascending date
const sortedValidatedMapped = last30Days?.sort((a, b) => {
const date1: any = new Date(a.date);
const date2: any = new Date(b.date);
return date1 - date2;
});

const cumulativeCount = {
validated: 0,
mapped: 0,
};

// generate cumulative count data
const finalData = sortedValidatedMapped?.map((submission) => {
cumulativeCount.validated += submission.Validated;
cumulativeCount.mapped += submission.Mapped;
return { ...submission, Validated: cumulativeCount.validated, Mapped: cumulativeCount.mapped };
});

setValidatedVsMappedInfographics(finalData);
}, [projectTaskList]);

// data for validated vs mapped graph
useEffect(() => {
Expand Down Expand Up @@ -231,14 +149,14 @@ const SubmissionsInfographics = ({ toggleView, entities }) => {
cardRef={plannedVsActualRef}
header="Validated vs Mapped Task"
body={
projectDetailsLoading ? (
mappedVsValidatedTaskLoading ? (
<CoreModules.Skeleton className="!fmtm-w-full fmtm-h-full" />
) : validatedVsMappedInfographics.length > 0 ? (
) : mappedVsValidatedTaskList.length > 0 ? (
<CustomLineChart
data={validatedVsMappedInfographics}
data={mappedVsValidatedTaskList}
xAxisDataKey="label"
lineOneKey="Validated"
lineTwoKey="Mapped"
lineOneKey="validated"
lineTwoKey="mapped"
xLabel="Submission Date"
yLabel="Task Count"
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ const SubmissionsTable = ({ toggleView }) => {
await dispatch(
CreateTaskEvent(
`${import.meta.env.VITE_API_URL}/tasks/${currentStatus.id}/event`,
task_event.MAP,
task_event.GOOD,
projectId,
filter?.task_id || '',
authDetails || {},
Expand Down
12 changes: 12 additions & 0 deletions src/frontend/src/store/slices/SubmissionSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ const initialState: SubmissionStateTypes = {
taskUid: null,
},
updateReviewStateLoading: false,
mappedVsValidatedTask: [],
mappedVsValidatedTaskLoading: false,
};

const SubmissionSlice = createSlice({
Expand Down Expand Up @@ -94,6 +96,16 @@ const SubmissionSlice = createSlice({
};
}
},
SetMappedVsValidatedTask(state, action) {
const MappedVsValidatedTask = action.payload;
state.mappedVsValidatedTask = MappedVsValidatedTask?.map((task) => ({
...task,
label: task?.date?.split('/').slice(0, 2).join('/'),
}));
},
SetMappedVsValidatedTaskLoading(state, action) {
state.mappedVsValidatedTaskLoading = action.payload;
},
},
});

Expand Down
9 changes: 9 additions & 0 deletions src/frontend/src/store/types/ISubmissions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ export type SubmissionStateTypes = {
submissionTableRefreshing: boolean;
updateReviewStatusModal: updateReviewStatusModal;
updateReviewStateLoading: boolean;
mappedVsValidatedTask: mappedVsValidatedTaskType[];
mappedVsValidatedTaskLoading: boolean;
};

type updateReviewStatusModal = {
Expand All @@ -33,3 +35,10 @@ export type filterType = {
review_state: string | null;
submitted_date: string | null;
};

type mappedVsValidatedTaskType = {
date: string;
mapped: number;
validated: number;
label: string;
};
8 changes: 7 additions & 1 deletion src/frontend/src/views/ProjectSubmissions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { ProjectActions } from '@/store/slices/ProjectSlice';
import { ProjectById, GetEntityInfo } from '@/api/Project';
import { useSearchParams } from 'react-router-dom';
import { useAppSelector } from '@/types/reduxTypes';
import { ProjectContributorsService } from '@/api/SubmissionService';
import { ProjectContributorsService, MappedVsValidatedTaskService } from '@/api/SubmissionService';

const ProjectSubmissions = () => {
const dispatch = CoreModules.useAppDispatch();
Expand Down Expand Up @@ -51,6 +51,12 @@ const ProjectSubmissions = () => {
dispatch(ProjectContributorsService(`${import.meta.env.VITE_API_URL}/projects/contributors/${projectId}`));
}, []);

useEffect(() => {
dispatch(
MappedVsValidatedTaskService(`${import.meta.env.VITE_API_URL}/tasks/activity/?project_id=${projectId}&days=30`),
);
}, []);

useEffect(() => {
if (!searchParams.get('tab')) {
setSearchParams({ tab: 'infographics' });
Expand Down

0 comments on commit 012410c

Please sign in to comment.