+
Comments
+ {taskGetCommentsLoading ? (
+
+ {Array.from({ length: 6 }).map((_, i) => (
+
+ ))}
+
+ ) : filteredTaskCommentsList?.length > 0 ? (
+ filteredTaskCommentsList?.map((comment) => (
+
+
+
{comment?.username}
+
+
+
{comment?.action_date?.split('T')[0]}
+
+
+
{comment?.action_text?.split('-SUBMISSION_INST-')[1]}
+
+ ))
+ ) : (
+
No Comments!
+ )}
+
+ );
+};
+
+export default SubmissionComments;
diff --git a/src/frontend/src/components/common/Accordion.tsx b/src/frontend/src/components/common/Accordion.tsx
index 976cccaec..00036ad75 100644
--- a/src/frontend/src/components/common/Accordion.tsx
+++ b/src/frontend/src/components/common/Accordion.tsx
@@ -10,6 +10,7 @@ interface IAccordion {
onToggle: any;
description?: string;
disableHeaderClickToggle?: boolean;
+ hasSeperator?: boolean;
}
export default function Accordion({
@@ -21,6 +22,7 @@ export default function Accordion({
onToggle,
description,
disableHeaderClickToggle,
+ hasSeperator = true,
}: IAccordion) {
const [collapsed, setCollapsed] = useState(isCollapsed);
@@ -34,7 +36,7 @@ export default function Accordion({
{
if (disableHeaderClickToggle) return;
diff --git a/src/frontend/src/shared/AssetModules.js b/src/frontend/src/shared/AssetModules.js
index 646309bc6..d82dcd7b2 100755
--- a/src/frontend/src/shared/AssetModules.js
+++ b/src/frontend/src/shared/AssetModules.js
@@ -85,6 +85,7 @@ import {
IntegrationInstructions as IntegrationInstructionsIcon,
QrCode2Outlined as QrCode2OutlinedIcon,
BarChart as BarChartIcon,
+ CalendarTodayOutlined as CalendarTodayOutlinedIcon,
} from '@mui/icons-material';
import LockPng from '@/assets/images/lock.png';
import RedLockPng from '@/assets/images/red-lock.png';
@@ -180,4 +181,5 @@ export default {
IntegrationInstructionsIcon,
QrCode2OutlinedIcon,
BarChartIcon,
+ CalendarTodayOutlinedIcon,
};
diff --git a/src/frontend/src/store/slices/SubmissionSlice.ts b/src/frontend/src/store/slices/SubmissionSlice.ts
index a38726106..46e46e2a2 100644
--- a/src/frontend/src/store/slices/SubmissionSlice.ts
+++ b/src/frontend/src/store/slices/SubmissionSlice.ts
@@ -27,6 +27,7 @@ const initialState: SubmissionStateTypes = {
taskId: null,
projectId: null,
reviewState: '',
+ taskUId: null,
},
updateReviewStateLoading: false,
};
diff --git a/src/frontend/src/store/types/ISubmissions.ts b/src/frontend/src/store/types/ISubmissions.ts
index 30b74a43a..6a26defc3 100644
--- a/src/frontend/src/store/types/ISubmissions.ts
+++ b/src/frontend/src/store/types/ISubmissions.ts
@@ -24,4 +24,5 @@ type updateReviewStatusModal = {
taskId: string | null;
projectId: number | null;
reviewState: string;
+ taskUId: string | null;
};
diff --git a/src/frontend/src/views/SubmissionDetails.tsx b/src/frontend/src/views/SubmissionDetails.tsx
index b4df1f404..058054f51 100644
--- a/src/frontend/src/views/SubmissionDetails.tsx
+++ b/src/frontend/src/views/SubmissionDetails.tsx
@@ -9,6 +9,77 @@ import UpdateReviewStatusModal from '@/components/ProjectSubmissions/UpdateRevie
import { useAppSelector } from '@/types/reduxTypes';
import { useNavigate } from 'react-router-dom';
import useDocumentTitle from '@/utilfunctions/useDocumentTitle';
+import Accordion from '@/components/common/Accordion';
+import { GetProjectComments } from '@/api/Project';
+import SubmissionComments from '@/components/SubmissionInstance/SubmissionComments';
+
+const renderValue = (value: any, key: string = '') => {
+ if (key === 'start' || key === 'end') {
+ return (
+ <>
+
{key}
+
+ {value?.split('T')[0]}, {value?.split('T')[1]}
+
+ >
+ );
+ } else if (typeof value === 'object' && Object.values(value).includes('Point')) {
+ return (
+ <>
+ {renderValue(
+ `${value?.type} (${value?.coordinates?.[0]},${value?.coordinates?.[1]},${value?.coordinates?.[2]}`,
+ key,
+ )}
+
+ {renderValue(value?.properties?.accuracy, 'accuracy')}
+ >
+ );
+ } else if (typeof value === 'object') {
+ return (
+
+ {}}
+ hasSeperator={false}
+ header={{key}
}
+ body={
+
+ {Object.entries(value).map(([key, nestedValue]) => {
+ return
{renderValue(nestedValue, key)}
;
+ })}
+
+ }
+ />
+
+ );
+ } else {
+ return (
+ <>
+
+ {key}
+
+
{value}
+ >
+ );
+ }
+};
+
+function removeNullValues(obj: Record
) {
+ const newObj = {};
+ for (const [key, value] of Object.entries(obj)) {
+ if (value !== null) {
+ if (typeof value === 'object') {
+ const nestedObj = removeNullValues(value);
+ if (Object.keys(nestedObj).length > 0) {
+ newObj[key] = nestedObj;
+ }
+ } else {
+ newObj[key] = value;
+ }
+ }
+ }
+ return newObj;
+}
const SubmissionDetails = () => {
useDocumentTitle('Submission Instance');
@@ -18,6 +89,7 @@ const SubmissionDetails = () => {
const projectId = params.projectId;
const paramsInstanceId = params.instanceId;
+ const taskUId = params.taskId;
const projectDashboardDetail = useAppSelector((state) => state.project.projectDashboardDetail);
const projectDashboardLoading = useAppSelector((state) => state.project.projectDashboardLoading);
const submissionDetails = useAppSelector((state) => state.submission.submissionDetails);
@@ -28,6 +100,9 @@ const SubmissionDetails = () => {
? submissionDetails?.task_filter
: '-';
+ const { start, end, today, deviceid, ...restSubmissionDetails } = submissionDetails || {};
+ const dateDeviceDetails = { start, end, today, deviceid };
+
useEffect(() => {
dispatch(GetProjectDashboard(`${import.meta.env.VITE_API_URL}/projects/project_dashboard/${projectId}`));
}, []);
@@ -35,30 +110,23 @@ const SubmissionDetails = () => {
useEffect(() => {
dispatch(
SubmissionService(
- `${import.meta.env.VITE_API_URL}/submission/submission-detail?submission_id=${paramsInstanceId}&project_id=${projectId}`,
+ `${
+ import.meta.env.VITE_API_URL
+ }/submission/submission-detail?submission_id=${paramsInstanceId}&project_id=${projectId}`,
),
);
}, [projectId, paramsInstanceId]);
- function removeNullValues(obj: Record) {
- const newObj = {};
- for (const [key, value] of Object.entries(obj)) {
- if (value !== null) {
- if (typeof value === 'object') {
- const nestedObj = removeNullValues(value);
- if (Object.keys(nestedObj).length > 0) {
- newObj[key] = nestedObj;
- }
- } else {
- newObj[key] = value;
- }
- }
- }
- return newObj;
- }
- const filteredData = submissionDetails ? removeNullValues(submissionDetails) : {};
+ useEffect(() => {
+ if (!taskUId) return;
+ dispatch(GetProjectComments(`${import.meta.env.VITE_API_URL}/tasks/${parseInt(taskUId)}/history/?comment=true`));
+ }, [taskUId]);
+
+ const filteredData = restSubmissionDetails ? removeNullValues(restSubmissionDetails) : {};
- const coordinatesArray: [number, number][] = submissionDetails?.xlocation?.split(';').map(function (coord: string) {
+ const coordinatesArray: [number, number][] = restSubmissionDetails?.xlocation?.split(';').map(function (
+ coord: string,
+ ) {
let coordinate = coord
.trim()
.split(' ')
@@ -86,48 +154,16 @@ const SubmissionDetails = () => {
const pointFeature = {
type: 'Feature',
geometry: {
- ...submissionDetails?.point,
+ ...restSubmissionDetails?.point,
},
properties: {},
};
- const renderValue = (value: any, key: string = '') => {
- if (key === 'start' || key === 'end') {
- return (
-
- {value?.split('T')[0]}, {value?.split('T')[1]}
-
- );
- } else if (typeof value === 'object' && Object.values(value).includes('Point')) {
- return (
-
-
{value?.type} ({value?.coordinates?.[0]},{value?.coordinates?.[1]},
- {value?.coordinates?.[2]}){renderValue(value?.properties)}
-
- );
- } else if (typeof value === 'object') {
- return (
-
- {Object.entries(value).map(([key, nestedValue]) => (
-
-
- {key}:{' '}
-
- {renderValue(nestedValue, key)}
-
- ))}
-
- );
- } else {
- return {value};
- }
- };
-
return (
-
+
{projectDashboardLoading ? (
-
+
) : (
@@ -149,64 +185,90 @@ const SubmissionDetails = () => {
)}
-
+
- {projectDashboardLoading ? (
-
+
+ {projectDashboardLoading ? (
+
+ ) : (
+
+
+ {projectDashboardDetail?.project_name_prefix}
+
+ Task: {taskId}
+
+ Submission Id: {paramsInstanceId}
+
+
+ )}
+
+ {/* start, end, today, deviceid values */}
+ {submissionDetailsLoading ? (
+
+ {Array.from({ length: 4 }).map((_, i) => (
+
+
+
+ ))}
+
) : (
-
-
- {projectDashboardDetail?.project_name_prefix}
-
-
Task: {taskId}
-
Submission Id: {paramsInstanceId}
+
+ {Object.entries(dateDeviceDetails).map(([key, value]) => (
+
+
{renderValue(value, key)}
+
+ ))}
)}
-
-
-
- {submissionDetailsLoading ? (
-
- {Array.from({ length: 8 }).map((_, i) => (
-
-
-
- ))}
-
- ) : (
+
+ {submissionDetailsLoading ? (
+
+ {Array.from({ length: 8 }).map((_, i) => (
+
+
+
+ ))}
+
+ ) : (
+
+ {Object.entries(filteredData).map(([key, value]) => (
+
+
{renderValue(value, key)}
+
+ ))}
+
+ )}
- {Object.entries(filteredData).map(([key, value]) => (
-
-
- {key}
- {renderValue(value, key)}
-
-
- ))}{' '}
+
- )}
+
);
};