Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat reviewstate api integration #1376

Merged
35 changes: 35 additions & 0 deletions src/frontend/src/api/SubmissionService.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import CoreModules from '@/shared/CoreModules';
import { CommonActions } from '@/store/slices/CommonSlice';
import { ProjectActions } from '@/store/slices/ProjectSlice';
// import { HomeProjectCardModel } from '@/models/home/homeModel';
import { SubmissionActions } from '@/store/slices/SubmissionSlice';
Expand Down Expand Up @@ -114,3 +115,37 @@ export const SubmissionTableService: Function = (url: string, payload) => {
await fetchSubmissionTable(url, payload);
};
};

export const UpdateReviewStateService: Function = (url: string) => {
return async (dispatch) => {
const UpdateReviewState = async (url: string) => {
try {
dispatch(SubmissionActions.UpdateReviewStateLoading(true));
const response = await CoreModules.axios.post(url);
dispatch(SubmissionActions.UpdateSubmissionTableDataReview(response.data));
dispatch(
SubmissionActions.SetUpdateReviewStatusModal({
toggleModalStatus: false,
projectId: null,
instanceId: null,
taskId: null,
reviewState: '',
}),
);
dispatch(SubmissionActions.UpdateReviewStateLoading(false));
} catch (error) {
dispatch(
CommonActions.SetSnackBar({
open: true,
message: 'Failed to update review state.',
variant: 'error',
duration: 2000,
}),
);
dispatch(SubmissionActions.UpdateReviewStateLoading(false));
}
};

await UpdateReviewState(url);
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import filterParams from '@/utilfunctions/filterParams';
import UpdateReviewStatusModal from '@/components/ProjectSubmissions/UpdateReviewStatusModal';
import { projectInfoType } from '@/models/project/projectModel';
import { useAppSelector } from '@/types/reduxTypes';
import { camelToFlat } from '@/utilfunctions/commonUtils';

type filterType = {
task_id: string | null;
Expand Down Expand Up @@ -406,6 +407,16 @@ const SubmissionsTable = ({ toggleView }) => {
rowClassName="snRow"
dataFormat={(row, _, index) => <span>{index + 1}</span>}
/>
<TableHeader
dataField="Review State"
headerClassName="codeHeader"
rowClassName="codeRow"
dataFormat={(row) => (
<div className="fmtm-w-[7rem] fmtm-overflow-hidden fmtm-truncate">
<span>{row?.__system?.reviewState ? camelToFlat(row?.__system?.reviewState) : '-'}</span>
</div>
)}
/>
{updatedSubmissionFormFields?.map((field: any): React.ReactNode | null => {
if (field) {
return (
Expand Down Expand Up @@ -446,7 +457,10 @@ const SubmissionsTable = ({ toggleView }) => {
dispatch(
SubmissionActions.SetUpdateReviewStatusModal({
toggleModalStatus: true,
submissionId: row?.meta?.instanceID,
instanceId: row?.meta?.instanceID,
taskId: row?.phonenumber,
projectId: decodedId,
reviewState: row?.__system?.reviewState,
}),
);
}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React, { useState } from 'react';
import React, { useEffect, useState } from 'react';
import { Modal } from '@/components/common/Modal';
import CoreModules from '@/shared/CoreModules';
import { useDispatch } from 'react-redux';
import { SubmissionActions } from '@/store/slices/SubmissionSlice';
import { reviewListType } from '@/models/submission/submissionModel';
import { UpdateReviewStateService } from '@/api/SubmissionService';
import TextArea from '../common/TextArea';
import Button from '../common/Button';
import { useAppSelector } from '@/types/reduxTypes';

const reviewList: reviewListType[] = [
{
Expand All @@ -15,7 +16,7 @@ const reviewList: reviewListType[] = [
hoverClass: 'hover:fmtm-text-[#40B449] hover:fmtm-border-[#40B449]',
},
{
id: 'hasIssue',
id: 'hasIssues',
title: 'Has Issue',
className: 'fmtm-bg-[#E9DFCF] fmtm-text-[#D99F00] fmtm-border-[#D99F00]',
hoverClass: 'hover:fmtm-text-[#D99F00] hover:fmtm-border-[#D99F00]',
Expand All @@ -30,9 +31,35 @@ const reviewList: reviewListType[] = [

const UpdateReviewStatusModal = () => {
const dispatch = useDispatch();
const [reviewStatus, setReviewStatus] = useState<string>('');
const [noteComments, setNoteComments] = useState<string>('');
const updateReviewStatusModal = CoreModules.useAppSelector((state) => state.submission.updateReviewStatusModal);
const [noteComments, setNoteComments] = useState('');
const [error, setError] = useState('');
const [reviewStatus, setReviewStatus] = useState('');
const updateReviewStatusModal = useAppSelector((state) => state.submission.updateReviewStatusModal);
const updateReviewStateLoading = useAppSelector((state) => state.submission.updateReviewStateLoading);

useEffect(() => {
setReviewStatus(updateReviewStatusModal.reviewState);
}, [updateReviewStatusModal.reviewState]);

const handleStatusUpdate = () => {
if (!updateReviewStatusModal.instanceId || !updateReviewStatusModal.projectId || !updateReviewStatusModal.taskId) {
return;
}

if (!reviewStatus) {
setError('Review state needs to be selected.');
return;
}
dispatch(
UpdateReviewStateService(
`${import.meta.env.VITE_API_URL}/submission/update_review_state/${
updateReviewStatusModal.projectId
}?project_id=${updateReviewStatusModal.projectId}&task_id=${parseInt(
updateReviewStatusModal.taskId,
)}&instance_id=${updateReviewStatusModal.instanceId}&review_state=${reviewStatus}`,
),
);
};

return (
<Modal
Expand All @@ -44,20 +71,23 @@ const UpdateReviewStatusModal = () => {
className="!fmtm-w-fit !fmtm-outline-none fmtm-rounded-xl"
description={
<div className="fmtm-mt-9">
<div className="fmtm-flex fmtm-justify-between fmtm-gap-2 fmtm-mb-4">
{reviewList.map((reviewBtn) => (
<button
key={reviewBtn.id}
className={`${
reviewBtn.id === reviewStatus
? reviewBtn.className
: `fmtm-border-[#D7D7D7] fmtm-bg-[#F5F5F5] fmtm-text-[#484848] ${reviewBtn.hoverClass} fmtm-duration-150`
} fmtm-pt-2 fmtm-pb-1 fmtm-px-7 fmtm-outline-none fmtm-w-fit fmtm-border-[1px] fmtm-rounded-[40px] fmtm-font-archivo fmtm-text-sm`}
onClick={() => setReviewStatus(reviewBtn.id)}
>
{reviewBtn.title}
</button>
))}
<div className="fmtm-mb-4">
<div className="fmtm-flex fmtm-justify-between fmtm-gap-2">
{reviewList.map((reviewBtn) => (
<button
key={reviewBtn.id}
className={`${
reviewBtn.id === reviewStatus
? reviewBtn.className
: `fmtm-border-[#D7D7D7] fmtm-bg-[#F5F5F5] fmtm-text-[#484848] ${reviewBtn.hoverClass} fmtm-duration-150`
} fmtm-pt-2 fmtm-pb-1 fmtm-px-7 fmtm-outline-none fmtm-w-fit fmtm-border-[1px] fmtm-rounded-[40px] fmtm-font-archivo fmtm-text-sm`}
onClick={() => setReviewStatus(reviewBtn.id)}
>
{reviewBtn.title}
</button>
))}
</div>
{error && <p className="fmtm-mt-1 fmtm-text-left fmtm-text-primaryRed">{error}</p>}
</div>
<TextArea
rows={4}
Expand All @@ -75,25 +105,34 @@ const UpdateReviewStatusModal = () => {
SubmissionActions.SetUpdateReviewStatusModal({
toggleModalStatus: false,
submissionId: null,
instanceId: null,
taskId: null,
reviewState: '',
}),
);
}}
/>
<Button
loadingText="Updating"
isLoading={updateReviewStateLoading}
btnText="Update"
btnType="primary"
className="fmtm-w-full fmtm-justify-center !fmtm-rounded fmtm-font-bold fmtm-text-sm !fmtm-py-2"
onClick={() => {}}
onClick={handleStatusUpdate}
/>
</div>
</div>
}
open={updateReviewStatusModal.toggleModalStatus}
onOpenChange={(value) => {
setError('');
dispatch(
SubmissionActions.SetUpdateReviewStatusModal({
toggleModalStatus: value,
submissionId: null,
projectId: null,
instanceId: null,
taskId: null,
reviewState: '',
}),
);
}}
Expand Down
2 changes: 1 addition & 1 deletion src/frontend/src/models/submission/submissionModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export type taskDataTypes = {
};

export type submissionTableDataTypes = {
results: [];
results: any[];
pagination: {
total: number | null;
page: number | null;
Expand Down
37 changes: 36 additions & 1 deletion src/frontend/src/store/slices/SubmissionSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,14 @@ const initialState: SubmissionStateTypes = {
submissionTableRefreshing: false,
validatedVsMappedInfographics: [],
validatedVsMappedLoading: false,
updateReviewStatusModal: { toggleModalStatus: false, submissionId: null },
updateReviewStatusModal: {
toggleModalStatus: false,
instanceId: null,
taskId: null,
projectId: null,
reviewState: '',
},
updateReviewStateLoading: false,
};

const SubmissionSlice = createSlice({
Expand Down Expand Up @@ -74,6 +81,34 @@ const SubmissionSlice = createSlice({
SetUpdateReviewStatusModal(state, action) {
state.updateReviewStatusModal = action.payload;
},
UpdateReviewStateLoading(state, action) {
state.updateReviewStateLoading = action.payload;
},
UpdateSubmissionTableDataReview(state, action) {
const updatedSubmission = action.payload;

// submission-instance table update
if (state.submissionTableData.results.length > 0) {
const updatedSubmissionDataList = state.submissionTableData.results.map((submissionData: any) => {
if (updatedSubmission.instanceId === submissionData.meta.instanceID) {
return {
...submissionData,
__system: { ...submissionData.__system, reviewState: updatedSubmission.reviewState },
};
}
return submissionData;
});
state.submissionTableData.results = updatedSubmissionDataList;
}

// submission-instance key value pair update
if (state.submissionDetails) {
state.submissionDetails = {
...state.submissionDetails,
__system: { ...state.submissionDetails.__system, reviewState: updatedSubmission.reviewState },
};
}
},
},
});

Expand Down
6 changes: 5 additions & 1 deletion src/frontend/src/store/types/ISubmissions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,13 @@ export type SubmissionStateTypes = {
validatedVsMappedInfographics: validatedVsMappedInfographicsTypes[];
validatedVsMappedLoading: boolean;
updateReviewStatusModal: updateReviewStatusModal;
updateReviewStateLoading: boolean;
};

type updateReviewStatusModal = {
toggleModalStatus: boolean;
submissionId: string | null;
instanceId: string | null;
taskId: string | null;
projectId: number | null;
reviewState: string;
};
4 changes: 4 additions & 0 deletions src/frontend/src/utilfunctions/commonUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@ export const isInputEmpty = (text: string): boolean => {
const trimmedText = text.trim();
return trimmedText === '';
};

export const camelToFlat = (word: string): string => (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The term for output like

Some Title String

is 'title case' so this could be camelToTitleCase

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For reference the other types are

Snake_Case, used by Python

Kebab-case, used in HTML

πŸ‘

(word = word.replace(/[A-Z]/g, ' $&')), word[0].toUpperCase() + word.slice(1)
);
5 changes: 4 additions & 1 deletion src/frontend/src/views/SubmissionDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,10 @@ const SubmissionDetails = () => {
dispatch(
SubmissionActions.SetUpdateReviewStatusModal({
toggleModalStatus: true,
submissionId: paramsInstanceId,
instanceId: paramsInstanceId,
projectId: decodedProjectId,
taskId: taskId,
reviewState: submissionDetails?.__system?.reviewState,
}),
);
}}
Expand Down
Loading