From 0dcfdc69b80abcfc2b2dd70b762a1c5c3e365705 Mon Sep 17 00:00:00 2001 From: Nishit Suwal <81785002+NSUWAL123@users.noreply.github.com> Date: Wed, 10 Jul 2024 00:53:15 +0545 Subject: [PATCH] refactor(frontend): simplify infographics API usage (reuse Entities data) (#1601) * fix(submissionInfographics): update taskInfo type & message * fix(taskSlice): increase submission count if status is not 0 * fix(submissionInfographics): use useSelector from reduxTypes * feat(submissionsInfographics): calculate form submissions data on frontend replacing api call * fix(submissionsInfographics): remove data calculation for planned vs actual graph * fix(submissionsInfographics): remove commented code * fix(submissionsInfographics): only count entities with status greater than 1 * fix(taskSlice): only count entities with status greater than 1 * fix(lineChart): remove dot from lines * fix(submissionInfographics): calculate validated vs mapped task data on frontend * fix(projectSubmissions): comment /dashboard api call & pass entities list to child components * fix(projectInfo): display projectInfo data replacing data from project dashboard api * fix(projectSusmissions): use useAppSelector for typed selector * feat(project): add created to projectInfo state * fix(projectInfo): use project creation date form project api * fix(projectSubmmissions): call contributors api on parent component * fix(submissionsInfographics): rename to dateA, dataB to suitable names * feat(commonUtils): add date functions to commonUtils * fix(submissionService): remove infographics chart api call service * fix(submissionInfographics): remove commented service dispatch & shift date functions to utils * fix(submission): remove unused submission state, types * remove commented getProjectDashboard call --- src/frontend/src/api/Project.js | 3 +- src/frontend/src/api/SubmissionService.ts | 34 --- .../ProjectSubmissions/ProjectInfo.tsx | 55 ++-- .../SubmissionsInfographics.tsx | 269 +++++++++--------- .../ProjectSubmissions/SubmissionsTable.tsx | 2 +- .../src/components/common/LineChart.tsx | 4 +- .../src/models/project/projectModel.ts | 1 + .../src/models/submission/submissionModel.ts | 14 +- .../src/store/slices/SubmissionSlice.ts | 16 -- src/frontend/src/store/slices/TaskSlice.ts | 4 +- src/frontend/src/store/types/ISubmissions.ts | 6 - src/frontend/src/utilfunctions/commonUtils.ts | 25 ++ src/frontend/src/views/ProjectSubmissions.tsx | 22 +- 13 files changed, 215 insertions(+), 240 deletions(-) diff --git a/src/frontend/src/api/Project.js b/src/frontend/src/api/Project.js index 7285cac28f..37287839a1 100755 --- a/src/frontend/src/api/Project.js +++ b/src/frontend/src/api/Project.js @@ -48,6 +48,7 @@ export const ProjectById = (existingProjectList, projectId) => { custom_tms_url: projectResp?.custom_tms_url, organisation_id: projectResp?.organisation_id, organisation_logo: projectResp?.organisation_logo, + created: projectResp?.created, }), ); dispatch(ProjectActions.SetProjectDetialsLoading(false)); @@ -183,7 +184,7 @@ export const DownloadTile = (url, payload, toOpfs = false) => { } const filename = response.headers['content-disposition'].split('filename=')[1]; - console.log(filename) + console.log(filename); // Create Blob from ArrayBuffer const blob = new Blob([tileData], { type: response.headers['content-type'] }); const downloadUrl = URL.createObjectURL(blob); diff --git a/src/frontend/src/api/SubmissionService.ts b/src/frontend/src/api/SubmissionService.ts index 9d6a6b18fc..ed070feea0 100644 --- a/src/frontend/src/api/SubmissionService.ts +++ b/src/frontend/src/api/SubmissionService.ts @@ -24,40 +24,6 @@ export const ProjectSubmissionService: Function = (url: string) => { }; }; -export const ProjectSubmissionInfographicsService: Function = (url: string) => { - return async (dispatch) => { - const fetchProjectSubmission = async (url: string) => { - try { - dispatch(SubmissionActions.SetSubmissionInfographicsLoading(true)); - const fetchSubmissionData = await CoreModules.axios.get(url); - const resp: any = fetchSubmissionData.data; - dispatch(SubmissionActions.SetSubmissionInfographicsLoading(false)); - dispatch(SubmissionActions.SetSubmissionInfographics(resp)); - } catch (error) {} - }; - - await fetchProjectSubmission(url); - }; -}; - -export const ValidatedVsMappedInfographicsService: Function = (url: string) => { - return async (dispatch) => { - const fetchProjectSubmission = async (url: string) => { - try { - dispatch(SubmissionActions.SetValidatedVsMappedLoading(true)); - const validatedVsMappedData = await CoreModules.axios.get(url); - const resp: any = validatedVsMappedData.data; - dispatch(SubmissionActions.SetValidatedVsMappedInfographics(resp)); - dispatch(SubmissionActions.SetValidatedVsMappedLoading(false)); - } catch (error) { - dispatch(SubmissionActions.SetValidatedVsMappedLoading(false)); - } - }; - - await fetchProjectSubmission(url); - }; -}; - export const ProjectContributorsService: Function = (url: string) => { return async (dispatch) => { const fetchProjectContributor = async (url: string) => { diff --git a/src/frontend/src/components/ProjectSubmissions/ProjectInfo.tsx b/src/frontend/src/components/ProjectSubmissions/ProjectInfo.tsx index 83f9fd270b..c06cdc2893 100644 --- a/src/frontend/src/components/ProjectSubmissions/ProjectInfo.tsx +++ b/src/frontend/src/components/ProjectSubmissions/ProjectInfo.tsx @@ -2,32 +2,46 @@ import React from 'react'; import CoreModules from '@/shared/CoreModules'; import AssetModules from '@/shared/AssetModules'; import { useNavigate } from 'react-router-dom'; -import { projectDashboardDetailTypes, projectInfoType } from '@/models/project/projectModel'; +import { useAppSelector } from '@/types/reduxTypes'; -const ProjectInfo = () => { +const ProjectInfo = ({ entities }) => { const navigate = useNavigate(); const params = CoreModules.useParams(); const projectId = params.projectId; - const projectInfo: projectInfoType = CoreModules.useAppSelector((state) => state.project.projectInfo); - const projectDashboardDetail: projectDashboardDetailTypes = CoreModules.useAppSelector( - (state) => state.project.projectDashboardDetail, - ); - const projectDashboardLoading: boolean = CoreModules.useAppSelector((state) => state.project.projectDashboardLoading); + const projectInfo = useAppSelector((state) => state.project.projectInfo); + // const projectDashboardDetail = useAppSelector((state) => state.project.projectDashboardDetail); + // const projectDashboardLoading = useAppSelector((state) => state.project.projectDashboardLoading); + const submissionContributorsData = useAppSelector((state) => state.submission.submissionContributors); + + const projectTaskList = useAppSelector((state) => state.project.projectTaskBoundries); + const projectIndex = projectTaskList.findIndex((project) => project.id == +projectId); + const taskActivities = projectTaskList?.[projectIndex]?.taskBoundries; + const projectDetailsLoading = useAppSelector((state) => state.project.projectDetailsLoading); + const entityOsmMapLoading = useAppSelector((state) => state.project.entityOsmMapLoading); + const projectCreationDate = projectInfo?.created ? projectInfo?.created?.split('T')[0] : '-'; + const submissionContributorsLoading = useAppSelector((state) => state.submission.submissionContributorsLoading); + + const latestDateSorted = entities + ?.map((entry) => new Date(entry?.updated_at)) // Convert to Date objects + .sort((a, b) => b - a)?.[0] + ?.toISOString(); + + const updatedDateTime = latestDateSorted ? latestDateSorted?.split('T')[0] : '-'; const dataCard = [ { title: 'Tasks', - count: projectDashboardDetail?.total_tasks, + count: taskActivities?.length, icon: , }, { title: 'Contributors', - count: projectDashboardDetail?.total_contributors, + count: submissionContributorsData?.length, icon: , }, { title: 'Submissions', - count: projectDashboardDetail?.total_submission, + count: entities?.length, icon: , }, ]; @@ -48,7 +62,7 @@ const ProjectInfo = () => { return (
- {projectDashboardLoading ? ( + {projectDetailsLoading ? ( ) : (
@@ -65,31 +79,22 @@ const ProjectInfo = () => {
)}
- {projectDashboardLoading ? ( + {projectDetailsLoading || entityOsmMapLoading ? ( ) : (

{projectInfo?.title}

- Created On:{' '} - - {projectDashboardDetail?.created - ? `${projectDashboardDetail?.created?.split('T')[0]} ${projectDashboardDetail?.created - ?.split('T')[1] - ?.split('.')[0]}` - : '-'} - -

-

- Last active:{' '} - {projectDashboardDetail?.last_active ? projectDashboardDetail?.last_active : '-'} + Created On: + {projectCreationDate}

+

Last active: {updatedDateTime}

)}
- {projectDashboardLoading ? ( + {projectDetailsLoading || submissionContributorsLoading || entityOsmMapLoading ? (
{Array.from({ length: 3 }).map((i) => ( diff --git a/src/frontend/src/components/ProjectSubmissions/SubmissionsInfographics.tsx b/src/frontend/src/components/ProjectSubmissions/SubmissionsInfographics.tsx index 0c7ee65893..ee91040d9a 100644 --- a/src/frontend/src/components/ProjectSubmissions/SubmissionsInfographics.tsx +++ b/src/frontend/src/components/ProjectSubmissions/SubmissionsInfographics.tsx @@ -6,139 +6,145 @@ import Table, { TableHeader } from '@/components/common/CustomTable'; import CustomLineChart from '@/components/common/LineChart'; import CoreModules from '@/shared/CoreModules'; import InfographicsCard from '@/components/ProjectSubmissions/InfographicsCard'; -import { - ProjectContributorsService, - ProjectSubmissionInfographicsService, - ValidatedVsMappedInfographicsService, -} from '@/api/SubmissionService'; -import { - submissionContributorsTypes, - submissionInfographicsTypes, - validatedVsMappedInfographicsTypes, -} from '@/models/submission/submissionModel'; -import { taskSubmissionInfoType } from '@/models/task/taskModel'; - 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'; -const lineKeyData = [ - { - name: '11/25', - Actual: 4000, - Planned: 2400, - amt: 2400, - }, - { - name: '11/26', - Actual: 3000, - Planned: 1398, - amt: 2210, - }, - { - name: '11/27', - Actual: 2000, - Planned: 9800, - amt: 2290, - }, - { - name: '11/28', - Actual: 2780, - Planned: 3908, - amt: 2000, - }, - { - name: '11/29', - Actual: 1890, - Planned: 4800, - amt: 2181, - }, - { - name: '11/30', - Actual: 2390, - Planned: 3800, - amt: 2500, - }, - { - name: '12/01', - Actual: 3490, - Planned: 4300, - amt: 2100, - }, - { - name: '12/02', - Actual: 2780, - Planned: 3908, - amt: 2000, - }, - { - name: '12/03', - Actual: 1890, - Planned: 4800, - amt: 2181, - }, - { - name: '12/04', - Actual: 2390, - Planned: 3800, - amt: 2500, - }, - { - name: '12/05', - Actual: 3490, - Planned: 4300, - amt: 2100, - }, -]; - -const SubmissionsInfographics = ({ toggleView }) => { +const SubmissionsInfographics = ({ toggleView, entities }) => { useDocumentTitle('Submission Infographics'); const formSubmissionRef = useRef(null); const projectProgressRef = useRef(null); const totalContributorsRef = useRef(null); const plannedVsActualRef = useRef(null); - const dispatch = CoreModules.useAppDispatch(); const params = CoreModules.useParams(); const projectId = params.projectId; - const submissionInfographicsData: submissionInfographicsTypes[] = CoreModules.useAppSelector( - (state) => state.submission.submissionInfographics, - ); - const submissionInfographicsLoading: boolean = CoreModules.useAppSelector( - (state) => state.submission.submissionInfographicsLoading, - ); - const submissionContributorsData: submissionContributorsTypes[] = CoreModules.useAppSelector( - (state) => state.submission.submissionContributors, - ); - const submissionContributorsLoading: boolean = CoreModules.useAppSelector( - (state) => state.submission.submissionContributorsLoading, - ); + const submissionContributorsData = useAppSelector((state) => state.submission.submissionContributors); + const submissionContributorsLoading = useAppSelector((state) => state.submission.submissionContributorsLoading); const [submissionProjection, setSubmissionProjection] = useState<10 | 30>(10); - const validatedVsMappedInfographics: validatedVsMappedInfographicsTypes[] = CoreModules.useAppSelector( - (state) => state.submission.validatedVsMappedInfographics, - ); - const validatedVsMappedLoading: boolean = CoreModules.useAppSelector( - (state) => state.submission.validatedVsMappedLoading, - ); - const taskInfo: taskSubmissionInfoType = CoreModules.useAppSelector((state) => state.task.taskInfo); - const taskLoading: boolean = CoreModules.useAppSelector((state) => state.task.taskLoading); + 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); - useEffect(() => { - dispatch( - ProjectSubmissionInfographicsService( - `${import.meta.env.VITE_API_URL}/submission/submission_page/${projectId}?days=${submissionProjection}`, - ), - ); - }, [submissionProjection]); + const today = new Date().toISOString(); + const [formSubmissionsData, setFormSubmissionsData] = useState([]); + const [validatedVsMappedInfographics, setValidatedVsMappedInfographics] = useState([]); useEffect(() => { - dispatch( - ValidatedVsMappedInfographicsService(`${import.meta.env.VITE_API_URL}/tasks/activity/?project_id=${projectId}`), - ); - }, []); + 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?.action_date).toISOString(); + return actionDate >= dateNDaysAgo(30) && actionDate <= today; + }); + + // only filter MAPPED & VALIDATED activities + const groupedData: validatedMappedType[] = taskActivities30Days?.reduce((acc: validatedMappedType[], activity) => { + const date = activity?.action_date.split('T')[0]; + const index = acc.findIndex((submission) => submission.date === date); + if (acc?.find((submission) => submission.date === date)) { + if (activity?.action_text?.includes('LOCKED_FOR_MAPPING to MAPPED')) { + acc[index].Mapped += 1; + } + if (activity?.action_text?.includes('LOCKED_FOR_VALIDATION to VALIDATED')) { + acc[index].Validated += 1; + } + } else { + const splittedDate = date?.split('-'); + const label = `${splittedDate[1]}/${splittedDate[2]}`; + if (activity?.action_text?.includes('LOCKED_FOR_MAPPING to MAPPED')) { + acc.push({ date: date, Validated: 0, Mapped: 1, label }); + } + if (activity?.action_text?.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(() => { - dispatch(ProjectContributorsService(`${import.meta.env.VITE_API_URL}/projects/contributors/${projectId}`)); - }, []); + if (entities?.length === 0) return; + + // get entities updated within the last 10 or 30 days + const updatedEntityLastNDays = entities?.filter((entity) => { + const updatedDate = new Date(entity?.updated_at).toISOString(); + return updatedDate >= dateNDaysAgo(submissionProjection) && updatedDate <= today; + }); + + // group entity submission according to date + const submissions: formSubmissionType[] = []; + updatedEntityLastNDays?.map((entity) => { + if (submissions?.find((submission) => submission.label === getMonthDate(entity.updated_at))) { + const index = submissions.findIndex((submission) => submission.label === getMonthDate(entity.updated_at)); + submissions[index].count += 1; + } else { + submissions.push({ + date: entity.updated_at?.split('T')[0], + label: getMonthDate(entity.updated_at), + count: 1, + }); + } + }); + + // sort submissions by ascending date + const sortedEntitySubmissions = submissions?.sort((a, b) => { + const date1: any = new Date(a.date); + const date2: any = new Date(b.date); + return date1 - date2; + }); + setFormSubmissionsData(sortedEntitySubmissions); + }, [entities, submissionProjection]); const FormSubmissionSubHeader = () => (
@@ -163,7 +169,6 @@ const SubmissionsInfographics = ({ toggleView }) => { const totalFeatureCount = taskInfo.reduce((total, task) => total + task.feature_count, 0); const totalSubmissionCount = taskInfo.reduce((total, task) => total + task.submission_count, 0); - const totalTaskCount = taskInfo.length; const projectProgressData = [ { names: 'Current', @@ -182,21 +187,21 @@ const SubmissionsInfographics = ({ toggleView }) => {
{toggleView}
-
+
} body={ - submissionInfographicsLoading ? ( + entityOsmMapLoading ? ( - ) : submissionInfographicsData.length > 0 ? ( + ) : formSubmissionsData.length > 0 ? ( ) : (
@@ -206,7 +211,7 @@ const SubmissionsInfographics = ({ toggleView }) => { } />
-
+
{
-
+
) : validatedVsMappedInfographics.length > 0 ? ( ) : (
- No tasks validated or mapped yet! + No Tasks Validated or Mapped in the Last 30 Days
) } />
-
+
{ />
-
+ {/*
{ ) } /> -
+
*/}
diff --git a/src/frontend/src/components/ProjectSubmissions/SubmissionsTable.tsx b/src/frontend/src/components/ProjectSubmissions/SubmissionsTable.tsx index ce30b2d91c..d63c9b2115 100644 --- a/src/frontend/src/components/ProjectSubmissions/SubmissionsTable.tsx +++ b/src/frontend/src/components/ProjectSubmissions/SubmissionsTable.tsx @@ -54,7 +54,7 @@ const SubmissionsTable = ({ toggleView }) => { const submissionTableDataLoading = useAppSelector((state) => state.submission.submissionTableDataLoading); const submissionTableRefreshing = useAppSelector((state) => state.submission.submissionTableRefreshing); const taskInfo = useAppSelector((state) => state.task.taskInfo); - const projectInfo: projectInfoType = CoreModules.useAppSelector((state) => state.project.projectInfo); + const projectInfo = useAppSelector((state) => state.project.projectInfo); const josmEditorError = useAppSelector((state) => state.task.josmEditorError); const downloadSubmissionLoading = useAppSelector((state) => state.task.downloadSubmissionLoading); const [numberOfFilters, setNumberOfFilters] = useState(0); diff --git a/src/frontend/src/components/common/LineChart.tsx b/src/frontend/src/components/common/LineChart.tsx index 28cddda77f..137a8142f5 100644 --- a/src/frontend/src/components/common/LineChart.tsx +++ b/src/frontend/src/components/common/LineChart.tsx @@ -49,8 +49,8 @@ const CustomLineChart = ({ data, xAxisDataKey, lineOneKey, lineTwoKey, xLabel, y )} - - + + ); diff --git a/src/frontend/src/models/project/projectModel.ts b/src/frontend/src/models/project/projectModel.ts index d9a3422ba2..f668fd087c 100644 --- a/src/frontend/src/models/project/projectModel.ts +++ b/src/frontend/src/models/project/projectModel.ts @@ -71,6 +71,7 @@ export type projectInfoType = { organisation_logo: string; instructions: string; custom_tms_url: string; + created: string; }; export type downloadProjectFormLoadingType = { type: 'form' | 'geojson' | 'csv' | 'json'; loading: boolean }; diff --git a/src/frontend/src/models/submission/submissionModel.ts b/src/frontend/src/models/submission/submissionModel.ts index b972cd89a9..f62ed1ade0 100644 --- a/src/frontend/src/models/submission/submissionModel.ts +++ b/src/frontend/src/models/submission/submissionModel.ts @@ -1,8 +1,3 @@ -export type submissionInfographicsTypes = { - date: string; - count: 1; -}; - export type submissionContributorsTypes = { user: string; contributions: number; @@ -16,12 +11,6 @@ export type submissionFormFieldsTypes = { selectMultiple: any; }; -export type validatedVsMappedInfographicsTypes = { - date: string; - validated: number; - mapped: number; -}; - export type submissionTableDataTypes = { results: any[]; pagination: { @@ -40,3 +29,6 @@ export type reviewListType = { className: string; hoverClass: string; }; + +export type formSubmissionType = { date: string; count: number; label: string }; +export type validatedMappedType = { date: string; Validated: number; Mapped: number; label: string }; diff --git a/src/frontend/src/store/slices/SubmissionSlice.ts b/src/frontend/src/store/slices/SubmissionSlice.ts index a4ad76d74e..a387261060 100644 --- a/src/frontend/src/store/slices/SubmissionSlice.ts +++ b/src/frontend/src/store/slices/SubmissionSlice.ts @@ -4,8 +4,6 @@ import { SubmissionStateTypes } from '@/store/types/ISubmissions'; const initialState: SubmissionStateTypes = { submissionDetailsLoading: true, submissionDetails: null, - submissionInfographics: [], - submissionInfographicsLoading: false, submissionContributors: [], submissionContributorsLoading: true, submissionFormFields: [], @@ -23,8 +21,6 @@ const initialState: SubmissionStateTypes = { submissionFormFieldsLoading: false, submissionTableDataLoading: false, submissionTableRefreshing: false, - validatedVsMappedInfographics: [], - validatedVsMappedLoading: false, updateReviewStatusModal: { toggleModalStatus: false, instanceId: null, @@ -45,18 +41,6 @@ const SubmissionSlice = createSlice({ SetSubmissionDetails(state, action) { state.submissionDetails = action.payload; }, - SetSubmissionInfographics(state, action) { - state.submissionInfographics = action.payload; - }, - SetSubmissionInfographicsLoading(state, action) { - state.submissionInfographicsLoading = action.payload; - }, - SetValidatedVsMappedInfographics(state, action) { - state.validatedVsMappedInfographics = action.payload; - }, - SetValidatedVsMappedLoading(state, action) { - state.validatedVsMappedLoading = action.payload; - }, SetSubmissionContributors(state, action) { state.submissionContributors = action.payload; }, diff --git a/src/frontend/src/store/slices/TaskSlice.ts b/src/frontend/src/store/slices/TaskSlice.ts index dda28ab5f2..a220c742aa 100644 --- a/src/frontend/src/store/slices/TaskSlice.ts +++ b/src/frontend/src/store/slices/TaskSlice.ts @@ -41,7 +41,7 @@ const TaskSlice = createSlice({ }, SetTaskSubmissionStates(state, action) { - const groupedPayload: Record = action.payload.reduce((acc, item) => { + const groupedPayload: Record = action.payload?.reduce((acc, item) => { if (!acc[item.task_id]) { acc[item.task_id] = []; } @@ -57,7 +57,7 @@ const TaskSlice = createSlice({ let submissionCount = 0; let lastSubmission: string | null = null; items.forEach((item) => { - if (item.status === task_status.MAPPED) { + if (item.status > 1) { submissionCount++; } if (item.updated_at && (!lastSubmission || item.updated_at > lastSubmission)) { diff --git a/src/frontend/src/store/types/ISubmissions.ts b/src/frontend/src/store/types/ISubmissions.ts index fcb6fdc98d..30b74a43ad 100644 --- a/src/frontend/src/store/types/ISubmissions.ts +++ b/src/frontend/src/store/types/ISubmissions.ts @@ -1,16 +1,12 @@ import { submissionContributorsTypes, submissionFormFieldsTypes, - submissionInfographicsTypes, submissionTableDataTypes, - validatedVsMappedInfographicsTypes, } from '@/models/submission/submissionModel'; export type SubmissionStateTypes = { submissionDetailsLoading: boolean; submissionDetails: Record | null; - submissionInfographics: submissionInfographicsTypes[]; - submissionInfographicsLoading: boolean; submissionContributors: submissionContributorsTypes[]; submissionContributorsLoading: boolean; submissionFormFields: submissionFormFieldsTypes[]; @@ -18,8 +14,6 @@ export type SubmissionStateTypes = { submissionFormFieldsLoading: boolean; submissionTableDataLoading: boolean; submissionTableRefreshing: boolean; - validatedVsMappedInfographics: validatedVsMappedInfographicsTypes[]; - validatedVsMappedLoading: boolean; updateReviewStatusModal: updateReviewStatusModal; updateReviewStateLoading: boolean; }; diff --git a/src/frontend/src/utilfunctions/commonUtils.ts b/src/frontend/src/utilfunctions/commonUtils.ts index cf04d93932..3df243017b 100644 --- a/src/frontend/src/utilfunctions/commonUtils.ts +++ b/src/frontend/src/utilfunctions/commonUtils.ts @@ -16,3 +16,28 @@ export const isStatusSuccess = (status: number) => { } return false; }; + +// get date N days ago +export const dateNDaysAgo = (NDays: number) => { + return new Date(new Date().getTime() - NDays * 24 * 60 * 60 * 1000).toISOString(); +}; + +// extract month & day in MM/DD format for chart date labels +export const getMonthDate = (date: string) => { + const splittedDate = date?.split('T')[0]?.split('-'); + return `${splittedDate[1]}/${splittedDate[2]}`; +}; + +// generates an array of date strings for last 30 days +export const generateLast30Days = (): string[] => { + const last30Days: string[] = []; + const today = new Date(); + + for (let i = 0; i < 30; i++) { + const date = new Date(); + date.setDate(today.getDate() - i); + last30Days.push(date.toISOString().split('T')[0]); + } + + return last30Days; +}; diff --git a/src/frontend/src/views/ProjectSubmissions.tsx b/src/frontend/src/views/ProjectSubmissions.tsx index e039044478..56ba67c078 100644 --- a/src/frontend/src/views/ProjectSubmissions.tsx +++ b/src/frontend/src/views/ProjectSubmissions.tsx @@ -6,9 +6,9 @@ import SubmissionsTable from '@/components/ProjectSubmissions/SubmissionsTable.j import CoreModules from '@/shared/CoreModules'; import { ProjectActions } from '@/store/slices/ProjectSlice'; import { ProjectById, GetEntityInfo } from '@/api/Project'; -import { GetProjectDashboard } from '@/api/Project'; import { useSearchParams } from 'react-router-dom'; -import { projectInfoType } from '@/models/project/projectModel'; +import { useAppSelector } from '@/types/reduxTypes'; +import { ProjectContributorsService } from '@/api/SubmissionService'; const ProjectSubmissions = () => { const dispatch = CoreModules.useAppDispatch(); @@ -17,8 +17,10 @@ const ProjectSubmissions = () => { const projectId = params.projectId; - const state = CoreModules.useAppSelector((state) => state.project); - const projectInfo: projectInfoType = CoreModules.useAppSelector((state) => state.project.projectInfo); + const state = useAppSelector((state) => state.project); + const projectInfo = useAppSelector((state) => state.project.projectInfo); + const entityList = useAppSelector((state) => state.project.entityOsmMap); + const updatedEntities = entityList?.filter((entity) => entity?.updated_at && entity?.status > 1); //Fetch project for the first time useEffect(() => { @@ -39,16 +41,16 @@ const ProjectSubmissions = () => { } }, [params.id]); - useEffect(() => { - dispatch(GetProjectDashboard(`${import.meta.env.VITE_API_URL}/projects/project_dashboard/${projectId}`)); - }, []); - // for hot fix to display task-list and show option of task-list for submission table filter // better solution needs to be researched useEffect(() => { dispatch(GetEntityInfo(`${import.meta.env.VITE_API_URL}/projects/${projectId}/entities/statuses`)); }, []); + useEffect(() => { + dispatch(ProjectContributorsService(`${import.meta.env.VITE_API_URL}/projects/contributors/${projectId}`)); + }, []); + useEffect(() => { if (!searchParams.get('tab')) { setSearchParams({ tab: 'infographics' }); @@ -85,11 +87,11 @@ const ProjectSubmissions = () => { return (
- +
{searchParams.get('tab') === 'infographics' ? ( - } /> + } entities={updatedEntities} /> ) : ( } /> )}