Skip to content

Commit

Permalink
issue #360: submit button
Browse files Browse the repository at this point in the history
  • Loading branch information
k-allagbe committed Dec 12, 2024
1 parent 89a19dd commit 3912d7f
Show file tree
Hide file tree
Showing 12 changed files with 117 additions and 105 deletions.
15 changes: 7 additions & 8 deletions docs/label-data-validation/flowchart.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ flowchart TD
Start([Start]) --> LabelDataValidation["/label-data-validation"]
LabelDataValidation --> ImagesUploaded{Images Uploaded?}
ImagesUploaded -->|No| HomePage[Home] --> End([End])
ImagesUploaded -->|Yes| GetExtract[GET /extract]
ImagesUploaded -->|Yes| DisplayUploadedImages["Display Uploaded Images"] --> GetExtract[GET /extract]
GetExtract --> Success{Success?}
Success -->|No| End
Success -->|Yes| PostInspections[POST /inspections]
PostInspections --> SaveSuccess{Success?}
SaveSuccess -->|No| DisplayData[Display Data] --> End
SaveSuccess -->|Yes| StoreData[Store Data] --> LabelDataWithID["/label-data-validation/id"] --> End
SaveSuccess -->|Yes| LabelDataWithID["go /label-data-validation/id"] --> End
```

## /label-data-validation/id
Expand All @@ -22,13 +22,12 @@ flowchart TD
flowchart TD
Start([Start]) --> LabelDataValidationID["/label-data-validation/id"]
LabelDataValidationID --> ImagesUploaded{Images Uploaded?}
ImagesUploaded -->|No| HomePage["/home"]
ImagesUploaded -->|Yes| DataInStore{Data in store?}
DataInStore -->|No| GetInspections[GET /inspections/id]
DataInStore -->|Yes| DisplayData["Display Data"]
ImagesUploaded -->|No| GetInspections[GET /inspections/id]
ImagesUploaded -->|Yes| DisplayUploadedImages["Display Uploaded Images"]
DisplayUploadedImages --> GetInspections
GetInspections --> FetchSuccess{Success?}
FetchSuccess -->|No| HomePage
FetchSuccess -->|Yes| DisplayData
FetchSuccess -->|No| HomePage["/home"]
FetchSuccess -->|Yes| DisplayData["Display Data"]
DisplayData --> End([End])
HomePage --> End
```
17 changes: 6 additions & 11 deletions src/app/label-data-validation/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import LabelDataValidator from "@/components/LabelDataValidator";
import useAlertStore from "@/stores/alertStore";
import useUploadedFilesStore from "@/stores/fileStore";
import { DEFAULT_LABEL_DATA } from "@/types/types";
import { mapInspectionToLabelData } from "@/utils/common";
import { mapInspectionToLabelData } from "@/utils/client/common";
import { Inspection } from "@/utils/server/backend";
import axios from "axios";
import { useRouter } from "next/navigation";
Expand All @@ -16,31 +16,23 @@ export default function Page({ params }: { params: { id: string } }) {
const { uploadedFiles } = useUploadedFilesStore();
const { showAlert } = useAlertStore();
const router = useRouter();
const [loading, setLoading] = useState(false);
const [loading, setLoading] = useState(true);
const [labelData, setLabelData] = useState(DEFAULT_LABEL_DATA);
const [inspection, setInspection] = useState<Inspection | null>(null);

useEffect(() => {
// if (uploadedFiles.length === 0) {
// showAlert("No files uploaded.", "error");
// router.push("/");
// return;
// }

if (!validate(id)) {
showAlert("Invalid id.", "error");
router.push("/");
return;
}

const username = "";
const username = "frontend";

Check failure

Code scanning / CodeQL

Hard-coded credentials Critical

The hard-coded value "frontend" is used as
authorization header
.
const password = "";
const authHeader = "Basic " + btoa(`${username}:${password}`);
const controller = new AbortController();
const signal = controller.signal;

setLoading(true);

axios
.get(`/api/inspections/${id}`, {
headers: { Authorization: authHeader },
Expand All @@ -59,6 +51,8 @@ export default function Page({ params }: { params: { id: string } }) {
} else {
console.error(error);
setLoading(false);
showAlert("Failed to fetch inspection.", "error");
router.push("/");
}
});
// not disabling loading in finally() in case of strict mode abort
Expand All @@ -78,6 +72,7 @@ export default function Page({ params }: { params: { id: string } }) {
labelData={labelData}
setLabelData={setLabelData}
loading={loading}
inspectionId={id}
/>
);
}
119 changes: 57 additions & 62 deletions src/app/label-data-validation/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { DEFAULT_LABEL_DATA } from "@/types/types";
import {
mapLabelDataOutputToLabelData,
processAxiosError,
} from "@/utils/common";
} from "@/utils/client/common";
import { Inspection, LabelDataOutput } from "@/utils/server/backend";
import axios from "axios";
import { useRouter } from "next/navigation";
Expand All @@ -15,7 +15,7 @@ import { useEffect, useState } from "react";
function LabelDataValidationPage() {
const { uploadedFiles } = useUploadedFilesStore();
const [labelData, setLabelData] = useState(DEFAULT_LABEL_DATA);
const [loading, setLoading] = useState(false);
const [loading, setLoading] = useState(true);
const { showAlert } = useAlertStore();
const router = useRouter();

Expand All @@ -29,69 +29,64 @@ function LabelDataValidationPage() {
const controller = new AbortController();
const signal = controller.signal;

const extractAndSave = async () => {
setLoading(true);
const formData = new FormData();
setLoading(true);
const formData = new FormData();

uploadedFiles.forEach((fileUploaded) => {
const file = fileUploaded.getFile();
formData.append("files", file);
});

const username = "";
const password = "";
const authHeader = "Basic " + btoa(`${username}:${password}`);
uploadedFiles.forEach((fileUploaded) => {
const file = fileUploaded.getFile();
formData.append("files", file);
});

axios
.post("/api/extract-label-data", formData, {
headers: { Authorization: authHeader },
signal,
})
.then(async (response) => {
const labelDataOutput: LabelDataOutput = response.data;
const labelData = mapLabelDataOutputToLabelData(labelDataOutput);
const username = "frontend";

Check failure

Code scanning / CodeQL

Hard-coded credentials Critical

The hard-coded value "frontend" is used as
authorization header
.
The hard-coded value "frontend" is used as
authorization header
.
const password = "";
const authHeader = "Basic " + btoa(`${username}:${password}`);
axios
.post("/api/extract-label-data", formData, {
headers: { Authorization: authHeader },
signal,
})
.then(async (response) => {
const labelDataOutput: LabelDataOutput = response.data;
const labelData = mapLabelDataOutputToLabelData(labelDataOutput);

formData.append("labelData", JSON.stringify(labelDataOutput));
axios
.post("/api/inspections", formData, {
headers: { Authorization: authHeader },
signal,
})
.then((response) => {
const inspection: Inspection = response.data;
router.push(`/label-data-validation/${inspection.inspection_id}`);
return null;
})
.catch((error) => {
if (axios.isCancel(error)) {
console.log("Request canceled");
} else {
showAlert(
`Label data initial save failed: ${processAxiosError(error)}`,
"error",
);
setLoading(false);
}
})
.finally(() => {
setLabelData(labelData);
// not disabling loading here in case of strict mode abort
});
})
.catch((error) => {
if (axios.isCancel(error)) {
console.log("Request canceled");
} else {
showAlert(
`Label data extraction failed: ${processAxiosError(error)}`,
"error",
);
setLoading(false);
}
});
};

extractAndSave();
formData.append("labelData", JSON.stringify(labelDataOutput));
axios
.post("/api/inspections", formData, {
headers: { Authorization: authHeader },
signal,
})
.then((response) => {
const inspection: Inspection = response.data;
router.push(`/label-data-validation/${inspection.inspection_id}`);
return null;
})
.catch((error) => {
if (axios.isCancel(error)) {
console.log("Request canceled");
} else {
showAlert(
`Label data initial save failed: ${processAxiosError(error)}`,
"error",
);
setLoading(false);
}
})
.finally(() => {
setLabelData(labelData);
// not disabling loading here in case of strict mode abort
});
})
.catch((error) => {
if (axios.isCancel(error)) {
console.log("Request canceled");
} else {
showAlert(
`Label data extraction failed: ${processAxiosError(error)}`,
"error",
);
setLoading(false);
}
});

return () => {
controller.abort(); // avoids react strict mode double fetch
Expand Down
2 changes: 1 addition & 1 deletion src/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";
import UserMenu from "@/components/UserMenu";
import useBreakpoints from "@/utils/useBreakpoints";
import useBreakpoints from "@/utils/client/useBreakpoints";
import AccountCircleIcon from "@mui/icons-material/AccountCircle";
import MenuIcon from "@mui/icons-material/Menu";
import {
Expand Down
13 changes: 11 additions & 2 deletions src/components/LabelDataValidator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import {
StepStatus,
} from "@/components/stepper";
import { FormComponentProps, LabelData } from "@/types/types";
import { checkFieldArray, checkFieldRecord } from "@/utils/common";
import useBreakpoints from "@/utils/useBreakpoints";
import { checkFieldArray, checkFieldRecord } from "@/utils/client/common";
import useBreakpoints from "@/utils/client/useBreakpoints";
import { Box, Container, Typography } from "@mui/material";
import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
Expand All @@ -23,13 +23,15 @@ interface LabelDataValidatorProps {
files: File[];
labelData: LabelData;
setLabelData: React.Dispatch<React.SetStateAction<LabelData>>;
inspectionId?: string;
}

function LabelDataValidator({
loading = false,
files,
labelData,
setLabelData,
inspectionId,
}: LabelDataValidatorProps) {
const { t } = useTranslation("labelDataValidator");
const imageFiles = files;
Expand Down Expand Up @@ -111,6 +113,10 @@ function LabelDataValidator({
),
];

const submit = () => {
console.log("inspectionId:", inspectionId, "labelData", labelData);
};

useEffect(() => {
const verified = labelData.organizations.every((org) =>
checkFieldRecord(org),
Expand Down Expand Up @@ -173,6 +179,7 @@ function LabelDataValidator({
stepStatuses={steps.map((step) => step.stepStatus)}
activeStep={activeStep}
setActiveStep={setActiveStep}
submit={submit}
/>
</Box>
)}
Expand All @@ -195,6 +202,7 @@ function LabelDataValidator({
stepStatuses={steps.map((step) => step.stepStatus)}
activeStep={activeStep}
setActiveStep={setActiveStep}
submit={submit}
/>
</Box>
)}
Expand All @@ -218,6 +226,7 @@ function LabelDataValidator({
stepStatuses={steps.map((step) => step.stepStatus)}
activeStep={activeStep}
setActiveStep={setActiveStep}
submit={submit}
/>
</Box>
</Box>
Expand Down
2 changes: 1 addition & 1 deletion src/components/OrganizationsForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
LabelData,
Organization,
} from "@/types/types";
import { checkFieldRecord } from "@/utils/common";
import { checkFieldRecord } from "@/utils/client/common";
import AddIcon from "@mui/icons-material/Add";
import DeleteIcon from "@mui/icons-material/Delete";
import DoneAllIcon from "@mui/icons-material/DoneAll";
Expand Down
2 changes: 1 addition & 1 deletion src/components/StyledSkeleton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const StyledSkeleton: React.FC<StyledSkeletonProps> = ({
return (
<Skeleton
variant="rectangular"
className={`rounded-tr-md rounded-br-md !h-12 ${className}`}
className={`rounded-md !h-12 ${className}`}
animation="wave"
sx={{
"&::after": {
Expand Down
6 changes: 6 additions & 0 deletions src/components/__tests__/HorizontalNonLinearStepper.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ const TestStepperWrapper: React.FC<TestStepperWrapperProps> = ({
}) => {
const [activeStep, setActiveStep] = useState<number>(initialActiveStep);
const [stepStatuses] = useState<StepStatus[]>(initialStepStatuses);
// create a mock submit function
const submit = jest.fn();

return (
<>
Expand All @@ -32,12 +34,14 @@ const TestStepperWrapper: React.FC<TestStepperWrapperProps> = ({
activeStep={activeStep}
setActiveStep={setActiveStep}
stepStatuses={stepStatuses}
submit={submit}
/>
<StepperControls
stepTitles={steps}
activeStep={activeStep}
setActiveStep={setActiveStep}
stepStatuses={stepStatuses}
submit={submit}
/>
</>
);
Expand Down Expand Up @@ -142,4 +146,6 @@ describe("HorizontalNonLinearStepper with StepperControls", () => {
const renderedSteps = container.querySelectorAll(".MuiStepButton-root");
expect(renderedSteps).toHaveLength(2);
});


});
Loading

0 comments on commit 3912d7f

Please sign in to comment.