diff --git a/package-lock.json b/package-lock.json index f77283b..0206641 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,7 @@ "d3": "^7.8.4", "d3-cloud": "^1.2.5", "file-saver": "^2.0.5", + "js-file-download": "^0.4.12", "react": "^18.2.0", "react-bootstrap": "^2.7.4", "react-d3-cloud": "^1.0.6", @@ -29,7 +30,8 @@ "react-pdf": "^6.2.2", "react-scripts": "^5.0.1", "react-spinners": "^0.13.8", - "web-vitals": "^2.1.4" + "web-vitals": "^2.1.4", + "worker-loader": "^3.0.8" } }, "node_modules/@adobe/css-tools": { @@ -12904,6 +12906,11 @@ "jiti": "bin/jiti.js" } }, + "node_modules/js-file-download": { + "version": "0.4.12", + "resolved": "https://registry.npmjs.org/js-file-download/-/js-file-download-0.4.12.tgz", + "integrity": "sha512-rML+NkoD08p5Dllpjo0ffy4jRHeY6Zsapvr/W86N7E0yuzAO6qa5X9+xog6zQNlH102J7IXljNY2FtS6Lj3ucg==" + }, "node_modules/js-sdsl": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.0.tgz", @@ -19040,6 +19047,25 @@ "workbox-core": "6.5.4" } }, + "node_modules/worker-loader": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/worker-loader/-/worker-loader-3.0.8.tgz", + "integrity": "sha512-XQyQkIFeRVC7f7uRhFdNMe/iJOdO6zxAaR3EWbDp45v3mDhrTi+++oswKNxShUNjPC/1xUp5DB29YKLhFo129g==", + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", diff --git a/package.json b/package.json index 6c97038..e4586b2 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "d3": "^7.8.4", "d3-cloud": "^1.2.5", "file-saver": "^2.0.5", + "js-file-download": "^0.4.12", "react": "^18.2.0", "react-bootstrap": "^2.7.4", "react-d3-cloud": "^1.0.6", @@ -24,7 +25,8 @@ "react-pdf": "^6.2.2", "react-scripts": "^5.0.1", "react-spinners": "^0.13.8", - "web-vitals": "^2.1.4" + "web-vitals": "^2.1.4", + "worker-loader": "^3.0.8" }, "scripts": { "start": "react-scripts start", diff --git a/src/App.js b/src/App.js index c9947a2..66a176f 100644 --- a/src/App.js +++ b/src/App.js @@ -6,13 +6,17 @@ import Filter from "./Components/Layout/Filter/Filter"; import ComplainceFilter from "./Components/Layout/Filter/ComplainceFilter"; import Results from "./Components/Layout/Results/Results"; import AppliedFilters from "./Components/Layout/AppliedFilters/AppliedFilters"; -import IddrsImg from "./Static/Imgs/IDDRS.png" +import IddrsImg from "./Static/Imgs/IDDRS.png"; import axios from "axios"; import FeaturedQuestions from "./Components/Layout/FeaturedQuestions/FeaturedQuestions"; import WordCloud_ from "./Components/Layout/WordCloud_/WordCloud_"; import Stack from "react-bootstrap/esm/Stack"; import Container from "react-bootstrap/esm/Container"; -import Image from 'react-bootstrap/Image'; +import Image from "react-bootstrap/Image"; +import Button from "react-bootstrap/esm/Button"; +import { saveAs } from 'file-saver'; +import ClipLoader from "react-spinners/ClipLoader"; +import Classes from "./App.module.css"; function App() { const [data, setData] = useState(""); @@ -22,6 +26,7 @@ function App() { const [filteredResults, setFilteredResults] = useState([]); const [filtersComplaince, setFiltersComplaince] = useState([]); const [filtersStandards, setFiltersStandards] = useState([]); + const [loading, setLoading] = useState(false); // the useEffect hook is used to apply filters whenever the results, // filtersStandards, or filtersComplaince values change @@ -34,31 +39,40 @@ function App() { //################################################################################ const handleSubmit = (event) => { event.preventDefault(); + setLoading(true); // Send the input value to Django axios .post("http://localhost:8000/client_api/get_input/", { data }) .then((response) => { - setPhrase(data['phrase']) + setPhrase(data["phrase"]); setResults(response.data.results); - setShowResults(true) + setShowResults(true); setFilteredResults(response.data.results); + setLoading(false); }) .catch((error) => { console.log(error); + setLoading(false); }); }; const handleSubmit_ = (value) => { + setLoading(true); // Send the input value to Django axios - .post("http://localhost:8000/client_api/get_input/", { data: { phrase: value } }) + .post("http://localhost:8000/client_api/get_input/", { + data: { phrase: value }, + }) .then((response) => { + setPhrase(value); setShowResults(true); setResults(response.data.results); setFilteredResults(response.data.results); + setLoading(false); }) .catch((error) => { console.log(error); + setLoading(false); }); }; @@ -112,6 +126,28 @@ function App() { }); }; + //################################################################################# + // function to export the results as a pdf file + const handleExportPDF = async () => { + setLoading(true); + try { + const response = await axios.post("http://localhost:8000/client_api/exportPDF/", { + params: { + filteredResults: filteredResults, // Replace with the actual filtered results data + phrase: phrase, // Replace with the actual phrase data + }, + }); + + // The response will contain the PDF file data, and you can use it as needed (e.g., to display or download the PDF) + const blob = new Blob([response.data], { type: 'application/pdf' }); + saveAs(blob, 'output.pdf'); + setLoading(false); + } catch (error) { + console.error('Error exporting PDF:', error); + setLoading(false); + } + }; + return (
@@ -122,20 +158,36 @@ function App() { )} - {filtersStandards.length > 0 && } - + {filtersStandards.length > 0 && ( + + )} + {showResults && ( + + )} {showResults && ( )} - + + + {loading && ( +
+ +
+ )}
); diff --git a/src/App.module.css b/src/App.module.css new file mode 100644 index 0000000..564beab --- /dev/null +++ b/src/App.module.css @@ -0,0 +1,9 @@ +.overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.5); /* Adjust the opacity as needed */ + z-index: 9999; + } \ No newline at end of file diff --git a/src/Components/Layout/Results/Results.js b/src/Components/Layout/Results/Results.js index 6bbe59d..458ff9f 100644 --- a/src/Components/Layout/Results/Results.js +++ b/src/Components/Layout/Results/Results.js @@ -4,7 +4,7 @@ import Stack from "react-bootstrap/Stack"; import ResultsItem from "./ResultsItem"; import ResultModal from "../../UI/ResultModal/ResultModal"; import ResultsPagination from "../../UI/ResultsPagination/ResultsPagination"; -//import PDFGenerator from "../../PDFGenerator/PDFGenerator"; +import PDFGenerator from "../../PDFGenerator/PDFGenerator"; const Results = (props) => { const [showModal, setShowModal] = useState(false); diff --git a/src/Components/PDFGenerator/PDFGenerator.js b/src/Components/PDFGenerator/PDFGenerator.js index 0942091..6df5d86 100644 --- a/src/Components/PDFGenerator/PDFGenerator.js +++ b/src/Components/PDFGenerator/PDFGenerator.js @@ -7,13 +7,11 @@ import { View, StyleSheet, Font, - pdf,createWorker + pdf, } from "@react-pdf/renderer"; import { saveAs } from "file-saver"; -import { css } from "@emotion/react"; -import ClipLoader from "react-spinners/ClipLoader"; -//import { createWorker } from "@react-pdf-viewer/core"; // Import the createWorker function +// Register font Font.register({ family: "Times-Roman" }); const styles = StyleSheet.create({ @@ -38,48 +36,32 @@ const PDFGenerator = (props) => { setIsLoading(true); try { - const worker = createWorker(); // Create a new web worker - - await worker.load(); // Load the worker - await worker.setFont("path/to/font/Times-Roman.ttf"); // Set the font path - - worker.onRenderError(() => { - console.error("Error generating PDF"); - setIsLoading(false); - }); - - worker.onRenderProgress((percent) => { - console.log(`PDF rendering progress: ${percent}%`); - }); + const views = props.results.map((result, index) => ( + + + Level {result.LevelName} + + + IDDRS - {result.Module} + + {result.Heading1} + {result.Heading2} + {result.Heading3} + {result.Heading4} + {result.Paragraph} + {result.PageNum} + + )); const pdfContent = ( - - {props.results.map((result, index) => ( - - - Level {result.LevelName} - - - IDDRS - {result.Module} - - {result.Heading1} - {result.Heading2} - {result.Heading3} - {result.Heading4} - {result.Paragraph} - {result.PageNum} - - ))} - + {views} ); - const result = await worker.renderToString(pdfContent); // Render the PDF content using the web worker - - const pdfBlob = new Blob([result], { type: "application/pdf" }); + const pdfBlob = await pdf(pdfContent).toBlob(); saveAs(pdfBlob, "IDDRS.pdf"); } catch (error) { console.error("Error generating PDF:", error); @@ -91,22 +73,10 @@ const PDFGenerator = (props) => { return (
-
+ ); }; + export default PDFGenerator; \ No newline at end of file diff --git a/src/Components/PDFGenerator/PDFWorker.js b/src/Components/PDFGenerator/pdf.worker.js similarity index 100% rename from src/Components/PDFGenerator/PDFWorker.js rename to src/Components/PDFGenerator/pdf.worker.js