This commit is contained in:
Pradeeppon01 2024-07-06 20:24:25 +05:30
parent b8f72c2887
commit d009c07a0b
6 changed files with 775 additions and 2 deletions

5
.env
View File

@ -1,4 +1,5 @@
#VITE_REACT_APP_BACKEND_URL="https://sandbox.exampaper.vidh.ai" #VITE_REACT_APP_BACKEND_URL="https://sandbox.exampaper.vidh.ai"
METABASE_BASE_URL="http://metabase.usln.in/public/question/d8774923-09bb-4cd9-903b-559d417e12cf" METABASE_BASE_URL="http://metabase.usln.in/public/question/d8774923-09bb-4cd9-903b-559d417e12cf"
VITE_REACT_APP_BACKEND_URL="https://api.exampaper.vidh.ai"
#VITE_REACT_APP_BACKEND_URL="http://localhost:9999" VITE_REACT_APP_BACKEND_URL="http://localhost:9999"
# VITE_REACT_APP_BACKEND_URL="https://api.exampaper.vidh.ai"

View File

@ -25,6 +25,8 @@ import BarcodeScanner from "./Components/BarcodeScanner"
import EvQrcode from "./Components/EvQrcode"; import EvQrcode from "./Components/EvQrcode";
import QrcodeCardEditor from "./Components/QrCodeCardEditor"; import QrcodeCardEditor from "./Components/QrCodeCardEditor";
import StudentResultsData from "./Components/StudentsResultsData"; import StudentResultsData from "./Components/StudentsResultsData";
import PlayGrounds from "./Components/PlayGrounds";
import PlayGround from "./Components/PlayGround";
function App() { function App() {
return ( return (
@ -36,6 +38,8 @@ function App() {
<Route path="/sqlPlayground/edit" element={<QueryCardEditor/>}></Route> <Route path="/sqlPlayground/edit" element={<QueryCardEditor/>}></Route>
<Route path="/evQrcode/edit" element={<QrcodeCardEditor/>}></Route> <Route path="/evQrcode/edit" element={<QrcodeCardEditor/>}></Route>
<Route path="/studentsDetails" element={<StudentResultsData/>}></Route> <Route path="/studentsDetails" element={<StudentResultsData/>}></Route>
<Route path="/Playgrounds" element={<PlayGrounds/>}></Route>
<Route path="/Playground/:type" element={<PlayGround/>}></Route>
<Route <Route
path="/anomoly/attendence/reassigned" path="/anomoly/attendence/reassigned"
element={<AnomolyReassigned />} element={<AnomolyReassigned />}

View File

@ -0,0 +1,356 @@
import { Box, Button } from "@mui/material";
import DownloadIcon from "@mui/icons-material/Download";
import { LazyLoadImage } from "react-lazy-load-image-component";
import { Label, MoreHorizTwoTone, RotateRight } from "@mui/icons-material";
import { useState, useEffect,useRef } from "react";
import { ToastContainer, toast } from "react-toastify";
import LoadingContainer from "./LoadingContainer";
import { useNavigate } from "react-router-dom";
const CustomQueryExecutorCard = ({
data,
s3_image_column,
query,
error,
error_reason,
reduxSystemNo,
degreeType,
type,
tableName
}) => {
// console.log("ERROR ============= ",error)
// console.log("ERROR REASON ============== ",error_reason)
// console.log("REDUX SYSTEM NO ================== ",reduxSystemNo)
const navigate = useNavigate();
const [dataValue, setDataValue] = useState({});
const [isLoading, setIsLoading] = useState(false);
// console.log("data in query executor Card : ", data);
const [keys, setKeys] = useState([]);
const [values, setValues] = useState([]);
const [rotateAngle, setRotateAngle] = useState(0);
const [imageName,setImageName] = useState(null)
const [tableNameData,setTableNameData] = useState(null)
const imageEleRef = useRef()
console.log("data =================== ",data)
// console.log("image column ====== ", s3_image_column);
// console.log("s3 image ======= ", data[s3_image_column]);
// console.log("Keys ==== ",keys)
// console.log("Values ===== ",values)
useEffect(()=>{
if(data){
console.log("Image name ====== ",data?.image_name)
setImageName(data?.image_name)
}
if(tableName){
setTableNameData(tableName)
}
},[data])
const updateFront = () => {
console.log("update front");
};
const updateBack = () => {
console.log("update back ..");
};
const initateProcess = () => {
console.log("inititate process..");
};
const rotateLeft = () => {
console.log("rotate left .....");
const newAngle = rotateAngle - 90
setRotateAngle((prev) => prev - 90);
console.log("new angle ....",newAngle)
const newStyle = `rotate(${newAngle}deg)`
imageEleRef.current.style.transform = newStyle
};
const rotateRight = () => {
console.log("rotate right");
const newAngle = rotateAngle + 90
setRotateAngle((prev) => prev + 90);
const newStyle = `rotate(${newAngle}deg)`
imageEleRef.current.style.transform = newStyle
};
const buttonActions = {
PartC: [
{ btnLabel: "Mark As Front", action: updateFront },
{ btnLabel: "Mark As Back", action: updateBack },
{ btnLabel: "Initiate Process", action: initateProcess },
],
};
useEffect(() => {
setDataValue(data);
setKeys(Object.keys(data));
setValues(Object.values(data));
}, [data]);
useEffect(() => {
console.log("Data value ===== ", dataValue);
setKeys(Object.keys(dataValue));
setValues(Object.values(dataValue));
}, [dataValue]);
const mark_as_ev = async () => {
const payload = {
data,
};
try {
setIsLoading(true);
const response = await fetch(
`${import.meta.env.VITE_REACT_APP_BACKEND_URL}/partcEvCoverMarking`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
}
);
setIsLoading(false);
const responseData = await response.json();
if (responseData.status === "success") {
const updatedData = { ...dataValue, is_cover: 1 };
// console.log("Data ===== ", updatedData);
setDataValue(updatedData);
console.log("Updation successfull ....");
toast.success("Record Marked As Ev !...");
} else {
throw new Error(responseData?.message);
}
} catch (error) {
throw new Error(error);
}
};
const mark_as_dummy = async () => {
const payload = {
data,
};
try {
setIsLoading(true);
const response = await fetch(
`${import.meta.env.VITE_REACT_APP_BACKEND_URL}/partcDummyMarking`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
}
);
setIsLoading(false);
const responseData = await response.json();
if (responseData.status === "success") {
console.log("Updation successfull ....");
const updatedData = { ...dataValue, type: 102 };
// console.log("Data ===== ", updatedData);
setDataValue(updatedData);
toast.success("Record Marked as Dummy ! ....");
} else {
throw new Error(responseData?.message);
}
} catch (error) {
throw new Error(error);
}
};
const saveRotatedImage = async () =>{
try{
if(rotateAngle === 0){
return
}
const payload = {
imageName,
tableNameData,
rotateAngle,
s3_path : data[s3_image_column]
}
setIsLoading(true);
const response = await fetch(
`${import.meta.env.VITE_REACT_APP_BACKEND_URL}/saveRotatedImage`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
}
);
setIsLoading(false);
const responseData = await response.json();
if (responseData.status === "success") {
toast.success("Image Rotation Saved Successfully")
}
}catch(error){
setIsLoading(false)
throw new Error(error)
}
}
const mark_as_backpage = async () => {
const payload = {
data,
};
try {
setIsLoading(true);
const response = await fetch(
`${import.meta.env.VITE_REACT_APP_BACKEND_URL}/partcEvBacksideMarking`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
}
);
setIsLoading(false);
const responseData = await response.json();
if (responseData.status === "success") {
console.log("Updation successfull ....");
const updatedData = { ...dataValue, is_backpage: 1 };
// console.log("Data ===== ", updatedData);
setDataValue(updatedData);
toast.success("Record Marked as Backpage ! ....");
} else {
throw new Error(responseData?.message);
}
} catch (error) {
throw new Error(error);
}
};
const rotate_and_process = async () => {
setIsLoading(true);
try {
const payload = {
data,
};
const response = await fetch(
`${import.meta.env.VITE_REACT_APP_BACKEND_URL}/partCRotateProcess`,
{
method: "POST",
header: {
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
}
);
const responseData = await response.json();
setIsLoading(false);
if (responseData.status === "success") {
console.log("Response successfull ...");
}
} catch (error) {
setIsLoading(false);
throw new Error(error);
}
};
return (
<Box className="w-100 rounded shadow mb-5 bg-white">
<ToastContainer />
<Box className="p-4 d-flex justify-content-between align-items-start">
<Box className="text-left p-3 d-flex flex-column justify-content-between align-items-between h-100">
{keys.map((record, index) => (
<p>
<strong>{keys[index]}</strong> : {values[index]}
</p>
))}
</Box>
<Box className="p-1">
<Box className="p-2 d-flex justify-content-end gap-3 align-items-center">
{/* {query.includes("ocr_scanned_part_c_v1") &&
data[s3_image_column] && (
<>
<Button
className="w-50 m-0 bg-primary text-white p-1 rounded"
onClick={() => navigate(`/sqlPlayground/edit?image_name=${data["image_name"]}&table=ocr_scanned_part_c_v1&error=${error}&error_reason=${error_reason}&sysNo=${reduxSystemNo}&degreeType=${degreeType}`)}
>
Edit
</Button>
<Button
className="w-50 m-0 bg-primary text-white p-1 rounded"
onClick={() => {
mark_as_backpage();
}}
>
Mark As Back
</Button>
<Button
className="w-50 m-0 bg-primary text-white p-1 rounded"
onClick={() => {
mark_as_ev();
}}
>
Mark As EV
</Button>
<Button
className="w-50 m-0 bg-primary text-white p-1 rounded"
onClick={() => {
mark_as_dummy();
}}
>
Mark As Dummy
</Button>
</>
)} */}
{type &&
buttonActions[type].map((action) => (
<Button
className="w-50 m-0 bg-primary text-white p-1 rounded"
onClick={action?.action}
>
{action?.btnLabel}
</Button>
))}
<Button className="bg-primary">
<a
href={`https://docs.exampaper.vidh.ai/${data[s3_image_column]}`}
>
<DownloadIcon className="text-light text-white" />
</a>
</Button>
</Box>
<Box className="border border-dark" id={imageName}>
<img
src={`https://docs.exampaper.vidh.ai/${data[s3_image_column]}`}
width="800px"
height="auto"
alt="Image Alt"
ref={imageEleRef}
/>
</Box>
<Box className="d-flex justify-content-between gap-2 my-2">
<Button
className="w-50 m-0 bg-primary text-white p-1 rounded"
onClick={rotateLeft}
>
Rotate left
</Button>
<Button className="w-50 m-0 bg-primary text-white p-1 rounded" onClick={saveRotatedImage}>
Save
</Button>
<Button
className="w-50 m-0 bg-primary text-white p-1 rounded"
onClick={rotateRight}
>
Rotate Right
</Button>
</Box>
</Box>
</Box>
{isLoading && <LoadingContainer loadingText={"Loading ..."} />}
</Box>
);
};
export default CustomQueryExecutorCard;

View File

@ -39,6 +39,10 @@ const Home = () => {
{ {
title:"EV Qrcode", title:"EV Qrcode",
url:"/evQrcode" url:"/evQrcode"
},
{
title:"PlayGrounds",
url:"/Playgrounds"
} }
// { // {
// title:"Marks Verfication", // title:"Marks Verfication",

View File

@ -0,0 +1,374 @@
import React, { useState, useEffect } from "react";
import {
DesktopOutlined,
FileOutlined,
PieChartOutlined,
TeamOutlined,
UserOutlined,
} from "@ant-design/icons";
import { Breadcrumb, Layout, Menu, Typography, theme } from "antd";
import { ToastContainer, toast } from "react-toastify";
import { Box, Button } from "@mui/material";
import TextField from "@mui/material/TextField";
import EditButton from "./EditButton";
import { width } from "@mui/system";
import "react-toastify/dist/ReactToastify.css";
import { useSearchParams } from "react-router-dom";
import LoadingContainer from "./LoadingContainer";
import HomeIcon from "@mui/icons-material/Home";
import ArrowBackIcon from "@mui/icons-material/ArrowBack";
import { useNavigate } from "react-router-dom";
import QueryStatsIcon from "@mui/icons-material/QueryStats";
import RotateLeftIcon from "@mui/icons-material/RotateLeft";
import RotateRightIcon from "@mui/icons-material/RotateRight";
import {
updatePartAanomolyData,
updatePlaygroundCurrentPage,
updatePlaygroundResults,
updatePlaygroundTotalPages,
updateSystemNo,
} from "../redux/actions/actions";
import CustomQueryExecutorCard from "./CustomQueryExecutorCard";
import SimpleDialog from "./SimpleDialog";
import SystemNumberDialog from "./SystemNumberDialog";
import ValidationContainer from "./ValidationContainer";
import QueryExecutorCard from "./QueryExecutorCard";
import ArrowUpwardIcon from "@mui/icons-material/ArrowUpward";
import QueryExecutortextArea from "./QueryExecutortextArea";
import AntdesignLayout from "./AntdesignLayout";
import TextInputField from "./TextInputField";
import { render } from "react-dom";
import { updatePlaygroundQuery } from "../redux/actions/actions";
import { useSelector, useDispatch } from "react-redux";
import PlayGrounds from "./PlayGrounds";
import { useParams } from "react-router-dom";
const { Header, Content, Footer, Sider } = Layout;
const PlayGround = () => {
const { type } = useParams();
console.log("Type ============= ", type);
const [tableName, setTableName] = useState(null);
const tableType = {
PartA: "ocr_scanned_part_a_v1",
PartC: "ocr_scanned_part_c_v1",
Attendence: "attendence_scanned_data",
};
useEffect(() => {
console.log("use effect type ==== ", type);
console.log("use effect table name ===== ", tableName);
console.log("table name ==== ", tableType[type]);
if (!tableName) {
setTableName(tableType[type]);
}
}, [type, tableName]);
const [responseData, setResponseData] = useState([]);
const [totalData, setTotalData] = useState([]);
const [currentPage, setCurrentPage] = useState(1);
const [totalPages, setTotalPages] = useState(0);
const [imageColumn, setImageColumn] = useState(null);
const [query, setQuery] = useState("");
const [isLoading, setIsLoading] = useState(false);
const [paginationPages, setPaginationPages] = useState(null);
const [limit, setLimit] = useState("");
const recordsPerPage = 50;
const navigate = useNavigate();
const dispatch = useDispatch();
const reduxPlaygroundQuery = useSelector((state) => state?.playGroundQuery);
const reduxPlaygroundPageNo = useSelector(
(state) => state?.playGroundCurrentPage
);
const reduxPlaygroundTotalPages = useSelector(
(state) => state?.playGroundtotalPages
);
const reduxPlaygroundResults = useSelector(
(state) => state?.playGroundResults
);
console.log("Redux playground query : ", reduxPlaygroundQuery);
console.log("Redux playground page no : ", reduxPlaygroundPageNo);
console.log("Redux playground total pages : ", reduxPlaygroundTotalPages);
console.log("Redux playground resutls : ", reduxPlaygroundResults);
const {
token: { colorBgContainer, borderRadiusLG },
} = theme.useToken();
useEffect(() => {
if (reduxPlaygroundQuery && !query) {
setQuery(reduxPlaygroundQuery);
}
}, [reduxPlaygroundQuery]);
useEffect(() => {
if (reduxPlaygroundPageNo != 0 && totalPages == 0) {
setTotalPages(reduxPlaygroundTotalPages);
}
}, [reduxPlaygroundTotalPages]);
useEffect(() => {
console.log("1234 ---- useEffect")
if (totalData.length == 0 && reduxPlaygroundResults) {
console.log("Redux playground results if ...");
console.log("reduxPlaygroundResults.type === type ",reduxPlaygroundResults.type === type)
if (reduxPlaygroundResults.type === type) {
console.log("Into if ...")
setTotalData(reduxPlaygroundResults?.data);
setImageColumn("s3_path");
}
}
}, [reduxPlaygroundResults]);
useEffect(() => {
if (currentPage == 0 && reduxPlaygroundPageNo !== 0) {
console.log("Updating in use effect ============================= >");
setCurrentPage(reduxPlaygroundPageNo);
}
}, [reduxPlaygroundPageNo]);
const fetchQueryValue = async () => {
if (query.includes("limit")) {
alert("Please specify the limit in the input field.");
return;
}
if (query.includes(";")) {
alert("Please remove the special character from the query ';'");
return;
}
if (!limit) {
alert("Limit cannot be empty !!");
return;
}
if (
!query.includes("image_name") &&
!query.includes("*") &&
query.includes("ocr_scanned_part_c_v1")
) {
alert(
"Selecting primary Key (image_name) or Selecting all (*) is mandatory"
);
return;
}
if (!query.includes(tableName)) {
alert(`This playground is only for : ${tableName}`);
return;
}
setIsLoading(true);
const payload = {
query: query,
limit: limit,
};
try {
const response = await fetch(
`${import.meta.env.VITE_REACT_APP_BACKEND_URL}/fetchQueryValue`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
}
);
const data = await response.json();
setIsLoading(false);
if (data.status === "success") {
setTotalData(data.results);
var tmp = {};
tmp.type = type;
tmp.data = data?.results;
// dispatch(updatePlaygroundResults(data?.results));
dispatch(updatePlaygroundResults(tmp));
const totalPageCount = Math.ceil(data?.results.length / recordsPerPage);
setTotalPages(totalPageCount);
dispatch(updatePlaygroundTotalPages(totalPages));
setCurrentPage(1);
setResponseData(data.results.slice(0, recordsPerPage));
} else {
toast.error(data.message);
}
} catch (error) {
console.error("Error:", error);
}
};
useEffect(() => {
dispatch(updatePlaygroundQuery(query));
}, [query]);
useEffect(() => {
if (totalData.length > 0) {
setResponseData([]);
console.log(" ===========================>>>>>>>>>>>>>>>>>>>>>>>> ");
setIsLoading(true);
setTimeout(() => {
const startIndex = (currentPage - 1) * recordsPerPage;
const endIndex = startIndex + recordsPerPage;
setResponseData(totalData.slice(startIndex, endIndex));
setIsLoading(false);
}, 1000);
}
dispatch(updatePlaygroundCurrentPage(currentPage));
renderPagination();
}, [currentPage, totalData]);
const renderPagination = () => {
const pages = [];
for (let i = 1; i <= totalPages; i++) {
pages.push(
<span key={i}>
{i > 1 && " | "}
<a
href="#!"
onClick={() => setCurrentPage(i)}
className={i === currentPage ? "active" : ""}
>
{i}
</a>
</span>
);
}
setPaginationPages(pages);
};
useEffect(() => {
renderPagination();
dispatch(updatePlaygroundTotalPages(totalPages));
}, [currentPage, totalPages]);
const getTableData = () => {
if (responseData.length === 0) return null;
const keys = Object.keys(totalData[0]);
return (
<div className="w-100">
<div className="text-left d-flex justify-content-between align-items-center">
<h5>
<strong>Total Results </strong> : {totalData.length}
</h5>
{totalData.length > 0 && (
<div id="footer-container">
<div
id="footer-main"
className="d-flex justify-content-center p-3 align-items-center"
>
<div className="d-flex justify-content-center align-items-center p-1">
<Box className="d-flex flex-column align-items-end">
<Box>{paginationPages}</Box>
<Box>
<strong>{currentPage}</strong>/
<strong>{totalPages}</strong>
</Box>
</Box>
</div>
<div className="d-flex gap-3">
{/* <button
className="btn text-light bg-primary rounded p-2 mx-3"
onClick={() =>
setCurrentPage((prev) => Math.max(prev - 1, 1))
}
>
Previous
</button>
<button
className="btn text-light bg-primary rounded p-2"
onClick={() =>
setCurrentPage((prev) => Math.min(prev + 1, totalPages))
}
>
Next
</button>
{} */}
</div>
</div>
</div>
)}
</div>
<div className="my-2 overflow-auto">
{responseData.map((data) => (
<CustomQueryExecutorCard
type={type}
tableName={tableName}
data={data}
s3_image_column={imageColumn}
query={query}
/>
))}
</div>
</div>
);
};
return (
<AntdesignLayout>
<div className="mx-3">
<div className="my-3 d-flex flex-md-row flex-column">
<div className="w-100 w-md-75">
<QueryExecutortextArea query={query} setQuery={setQuery} />
</div>
<div className="d-none d-md-block w-25">
<div className="w-100 d-flex flex-column gap-2 mx-2">
<TextInputField
placeholder={"limit"}
value={limit}
setValue={setLimit}
/>
<TextInputField
placeholder={"imageColumn"}
value={imageColumn}
setValue={setImageColumn}
/>
<button
className="btn bg-primary text-light"
id="submit-btn"
onClick={fetchQueryValue}
>
Submit
</button>
</div>
</div>
<div className="d-block d-md-none w-100">
<div className="w-100 d-flex flex-column gap-2">
<TextField
className="rounded h6 bg-white"
type="text"
placeholder="Limit"
id="limit-input"
autoComplete="off"
value={limit}
onChange={(e) => setLimit(e.target.value)}
/>
<TextField
className="input rounded h6 bg-white"
type="text"
placeholder="Image column name"
id="image-column-input"
autoComplete="off"
value={imageColumn}
onChange={(e) => setImageColumn(e.target.value)}
/>
<button
className="btn bg-primary text-light"
id="submit-btn"
onClick={fetchQueryValue}
>
Submit
</button>
</div>
</div>
</div>
<div
id="results-container"
className="d-flex w-100 justify-content-center"
>
{getTableData()}
</div>
</div>
{isLoading && <LoadingContainer />}
</AntdesignLayout>
);
};
export default PlayGround;

View File

@ -0,0 +1,34 @@
import React from "react";
import { Box } from "@mui/material";
import HomepageCard from "./HomepageCard";
const PlayGrounds = () => {
const cards = [
{
title: "PART - A",
url: "/Playground/PartA",
},
{
title: "PART - C",
url: "/Playground/PartC",
},
{
title: "ATTENDENCE",
url: "/Playground/Attendence",
},
];
return (
<>
<Box className="d-flex justify-content-center text-light bg-primary rounded py-3">
<h1>Welcome to exampaper.vidh.ai</h1>
</Box>
<Box className="p-3" style={{ width: "100%" }}>
{cards.map((card) => (
<HomepageCard title={card?.title} url={card?.url} />
))}
</Box>
</>
);
};
export default PlayGrounds;