css improvment

This commit is contained in:
louai98 2023-06-09 13:17:28 +02:00
parent 06171b0b62
commit 9cb8fe4f73
12 changed files with 283 additions and 59 deletions

21
package-lock.json generated
View File

@ -12,6 +12,7 @@
"@emotion/styled": "^11.11.0", "@emotion/styled": "^11.11.0",
"@mui/icons-material": "^5.11.16", "@mui/icons-material": "^5.11.16",
"@mui/material": "^5.13.0", "@mui/material": "^5.13.0",
"@react-pdf-viewer/core": "^3.12.0",
"@react-pdf/renderer": "^3.1.9", "@react-pdf/renderer": "^3.1.9",
"@testing-library/jest-dom": "^5.16.5", "@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0", "@testing-library/react": "^13.4.0",
@ -27,6 +28,7 @@
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-pdf": "^6.2.2", "react-pdf": "^6.2.2",
"react-scripts": "^5.0.1", "react-scripts": "^5.0.1",
"react-spinners": "^0.13.8",
"web-vitals": "^2.1.4" "web-vitals": "^2.1.4"
} }
}, },
@ -3541,6 +3543,16 @@
"react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0"
} }
}, },
"node_modules/@react-pdf-viewer/core": {
"version": "3.12.0",
"resolved": "https://registry.npmjs.org/@react-pdf-viewer/core/-/core-3.12.0.tgz",
"integrity": "sha512-8MsdlQJ4jaw3GT+zpCHS33nwnvzpY0ED6DEahZg9WngG++A5RMhk8LSlxdHelwaFFHFiXBjmOaj2Kpxh50VQRg==",
"peerDependencies": {
"pdfjs-dist": "^2.16.105 || ^3.0.279",
"react": ">=16.8.0",
"react-dom": ">=16.8.0"
}
},
"node_modules/@react-pdf/fns": { "node_modules/@react-pdf/fns": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/@react-pdf/fns/-/fns-2.0.1.tgz", "resolved": "https://registry.npmjs.org/@react-pdf/fns/-/fns-2.0.1.tgz",
@ -16139,6 +16151,15 @@
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
}, },
"node_modules/react-spinners": {
"version": "0.13.8",
"resolved": "https://registry.npmjs.org/react-spinners/-/react-spinners-0.13.8.tgz",
"integrity": "sha512-3e+k56lUkPj0vb5NDXPVFAOkPC//XyhKPJjvcGjyMNPWsBKpplfeyialP74G7H7+It7KzhtET+MvGqbKgAqpZA==",
"peerDependencies": {
"react": "^16.0.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/react-transition-group": { "node_modules/react-transition-group": {
"version": "4.4.5", "version": "4.4.5",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",

View File

@ -7,6 +7,7 @@
"@emotion/styled": "^11.11.0", "@emotion/styled": "^11.11.0",
"@mui/icons-material": "^5.11.16", "@mui/icons-material": "^5.11.16",
"@mui/material": "^5.13.0", "@mui/material": "^5.13.0",
"@react-pdf-viewer/core": "^3.12.0",
"@react-pdf/renderer": "^3.1.9", "@react-pdf/renderer": "^3.1.9",
"@testing-library/jest-dom": "^5.16.5", "@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0", "@testing-library/react": "^13.4.0",
@ -22,6 +23,7 @@
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-pdf": "^6.2.2", "react-pdf": "^6.2.2",
"react-scripts": "^5.0.1", "react-scripts": "^5.0.1",
"react-spinners": "^0.13.8",
"web-vitals": "^2.1.4" "web-vitals": "^2.1.4"
}, },
"scripts": { "scripts": {

View File

@ -134,7 +134,7 @@ function App() {
<Stack className="mt-5" direction="horizontal" gap={2}> <Stack className="mt-5" direction="horizontal" gap={2}>
<FeaturedQuestions handleButtonClick={handleSubmit_} /> <FeaturedQuestions handleButtonClick={handleSubmit_} />
<WordCloud_ /> <WordCloud_ handleButtonClick={handleSubmit_}/>
</Stack> </Stack>
</Container> </Container>
</main> </main>

View File

@ -1,6 +1,7 @@
import React, { useState } from "react"; import React, { useState } from "react";
import Stack from "react-bootstrap/esm/Stack"; import Stack from "react-bootstrap/esm/Stack";
import Card from "react-bootstrap/Card"; import Card from "react-bootstrap/Card";
import classes from "./FeaturedQuestions.module.css"
const FeaturedQuestions = ({ handleButtonClick }) => { const FeaturedQuestions = ({ handleButtonClick }) => {
const handleClick = (value) => { const handleClick = (value) => {
@ -24,7 +25,7 @@ const FeaturedQuestions = ({ handleButtonClick }) => {
<Stack gap={4}> <Stack gap={4}>
{fqs.map((fq) => ( {fqs.map((fq) => (
<li key={fq}> <li key={fq}>
<a name="phrase" onClick={() => handleClick(fq)} value={fq}> <a name="phrase" className={classes.pointer} onClick={() => handleClick(fq)} value={fq}>
{fq} {fq}
</a> </a>
</li> </li>

View File

@ -0,0 +1,5 @@
.pointer {
cursor: pointer;
text-decoration: none !important;
color: inherit;
}

View File

@ -4,9 +4,7 @@ import Stack from "react-bootstrap/Stack";
import ResultsItem from "./ResultsItem"; import ResultsItem from "./ResultsItem";
import ResultModal from "../../UI/ResultModal/ResultModal"; import ResultModal from "../../UI/ResultModal/ResultModal";
import ResultsPagination from "../../UI/ResultsPagination/ResultsPagination"; import ResultsPagination from "../../UI/ResultsPagination/ResultsPagination";
import PDFGenerator from "../../PDFGenerator/PDFGenerator"; //import PDFGenerator from "../../PDFGenerator/PDFGenerator";
import { PDFDownloadLink } from "@react-pdf/renderer";
import Button from "react-bootstrap/esm/Button";
const Results = (props) => { const Results = (props) => {
const [showModal, setShowModal] = useState(false); const [showModal, setShowModal] = useState(false);
@ -32,11 +30,8 @@ const Results = (props) => {
return ( return (
<div className="mt-5 mb-5"> <div className="mt-5 mb-5">
{/* <PDFDownloadLink document={<PDFGenerator results={props.results}/>}>
{({loading}) => (loading ? <Button>Loading document...</Button> : <Button>Download</Button>)}
</PDFDownloadLink> */}
{/* <PDFGenerator results={props.results} /> */} {/* <PDFGenerator results={props.results} /> */}
<Card className="secondary p-1"> <Card className="secondary p-1">
<h2 className="text-secondary text-center">{props.searchedPhrase}</h2> <h2 className="text-secondary text-center">{props.searchedPhrase}</h2>

View File

@ -0,0 +1,123 @@
import React, { Fragment } from "react";
import WordCloud from "react-d3-cloud";
import Card from "react-bootstrap/Card";
import classes from "./WordCloud_.module.css"
const data = [
{ text: "Disarmament", value: 1000 },
{
text: "Disarmament",
value: 68.0,
},
{
text: "Demobilization",
value: 60.0,
},
{
text: "Reintegration support",
value: 58.0,
},
{
text: "Reinsertion",
value: 57.0,
},
{
text: "Security Sector",
value: 52.0,
},
{
text: "DDR participants",
value: 51.0,
},
{
text: "Integrated Assessments",
value: 48.0,
},
{
text: "Community Violence Reduction",
value: 46.0,
},
{
text: "Transitional Weapons and Ammunition Management",
value: 43.0,
},
{
text: "Children associated with armed forces and groups",
value: 42.0,
},
{
text: "Community based reintegration",
value: 40.0,
},
{
text: "DDR-related tools",
value: 37.0,
},
{
text: "DDR Programme",
value: 31.0,
},
{
text: "DDR Process",
value: 27.0,
},
{
text: "Foreign combatants",
value: 26.0,
},
{
text: "Pre-DDR",
value: 22.0,
},
{
text: "DDR policy",
value: 19.0,
},
{
text: "DDR Strategy",
value: 17.0,
},
{
text: "Eligibility criteria",
value: 13.0,
},
{
text: "Preventing recruitment",
value: 13.0,
},
];
const WordCloud_ = ({handleButtonClick}) => {
const handleClick = (value) => {
//console.log(event.target.value)
handleButtonClick(value);
};
return (
<Card className="w-50">
<h4 className="text-decoration-underline text-center">
Most Frequent Key-Phrases
</h4>
<WordCloud
//width={200}
data={data}
font="Times"
fontStyle="italic"
//fontWeight="bold"
fontSize={(word) => Math.log2(word.value) * 5 }
//fontSize={33}
spiral="rectangular"
rotate={0}
fill = "gray"
padding={2}
onWordMouseOver = {classes.pointer}
onWordClick={(event, d) => {
console.log(`onWordClick: ${d.text}`);
handleClick(d.text)
}}
/>
</Card>
);
};
export default WordCloud_;

View File

@ -1,7 +1,7 @@
import React, { Fragment } from "react"; import React, { Fragment, useState } from "react";
import WordCloud from "react-d3-cloud"; import WordCloud from "react-d3-cloud";
import Card from "react-bootstrap/Card"; import Card from "react-bootstrap/Card";
import classes from "./WordCloud_.module.css";
const data = [ const data = [
{ text: "Disarmament", value: 1000 }, { text: "Disarmament", value: 1000 },
{ {
@ -86,29 +86,37 @@ const data = [
}, },
]; ];
const WordCloud_ = () => { const WordCloud_ = ({ handleButtonClick }) => {
const handleClick = (value) => {
//console.log(event.target.value)
handleButtonClick(value);
};
return ( return (
<Card className="w-50"> <Card className="w-50">
<h4 className="text-decoration-underline text-center"> <h4 className="text-decoration-underline text-center">
Most Frequent Key-Phrases Most Frequent Key-Phrases
</h4> </h4>
<div className={classes.pointer}>
<WordCloud <WordCloud
//width={200} //width={200}
data={data} data={data}
font="Times" font="Times"
fontStyle="italic" fontStyle="italic"
//fontWeight="bold" //fontWeight="bold"
fontSize={(word) => Math.log2(word.value) * 5 } fontSize={(word) => Math.log2(word.value) * 5}
//fontSize={33} //fontSize={33}
spiral="rectangular" spiral="rectangular"
rotate={0} rotate={0}
fill = "gray" fill="gray"
padding={2} padding={2}
onWordClick={(event, d) => { onWordClick={(event, d) => {
console.log(`onWordClick: ${d.text}`); console.log(`onWordClick: ${d.text}`);
handleClick(d.text);
}} }}
/> />
</Card> </div>
</Card>
); );
}; };

View File

@ -0,0 +1,5 @@
.pointer {
cursor: pointer;
text-decoration: none !important;
color: inherit;
}

View File

@ -1,14 +1,19 @@
import React, { Fragment } from "react"; import React, { Fragment, useState } from "react";
import Button from "react-bootstrap/esm/Button";
import { import {
Document, Document,
Page, Page,
Text, Text,
View, View,
StyleSheet, StyleSheet,
Font Font,
pdf,createWorker
} from "@react-pdf/renderer"; } 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" }); Font.register({ family: "Times-Roman" });
const styles = StyleSheet.create({ const styles = StyleSheet.create({
@ -17,53 +22,91 @@ const styles = StyleSheet.create({
backgroundColor: "#E4E4E4", backgroundColor: "#E4E4E4",
padding: 10, padding: 10,
}, },
text: { text: {
fontFamily: "Times-Roman", fontFamily: "Times-Roman",
fontSize: 12, fontSize: 12,
}, },
title: { title: {
fontSize: 14, fontSize: 14,
} },
}); });
const PDFGenerator = (props) => { const PDFGenerator = (props) => {
const [isLoading, setIsLoading] = useState(false);
const handleDownload = async () => {
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 pdfContent = (
<Document>
<Page size="A4" style={styles.page}>
<View style={styles.content}>
{props.results.map((result, index) => (
<Fragment key={index}>
<Text style={[styles.text, styles.title]}>
Level {result.LevelName}
</Text>
<Text style={[styles.text, styles.title]}>
IDDRS - {result.Module}
</Text>
<Text style={styles.text}>{result.Heading1}</Text>
<Text style={styles.text}>{result.Heading2}</Text>
<Text style={styles.text}>{result.Heading3}</Text>
<Text style={styles.text}>{result.Heading4}</Text>
<Text style={styles.text}>{result.Paragraph}</Text>
<Text style={styles.text}>{result.PageNum}</Text>
</Fragment>
))}
</View>
</Page>
</Document>
);
const result = await worker.renderToString(pdfContent); // Render the PDF content using the web worker
const pdfBlob = new Blob([result], { type: "application/pdf" });
saveAs(pdfBlob, "IDDRS.pdf");
} catch (error) {
console.error("Error generating PDF:", error);
} finally {
setIsLoading(false);
}
};
return ( return (
<Document> <div>
<Page size="A4" style={styles.page}> <Button onClick={handleDownload} disabled={isLoading}>
<View style={styles.content}> {isLoading ? (
{props.results.map((result, index) => ( <ClipLoader
<Fragment> css={css`
<Text key={index} style={[styles.text, styles.title]}> display: block;
Level {result.LevelName} margin: 0 auto;
</Text> border-color: red;
<Text key={index} style={[styles.text, styles.title]}> `}
IDDRS - {result.Module} size={20}
</Text> color={"#ffffff"}
<Text key={index} style={styles.text}> loading={isLoading}
{result.Heading1} />
</Text> ) : (
<Text key={index} style={styles.text}> "Generate and Download PDF"
{result.Heading2} )}
</Text> </Button>
<Text key={index} style={styles.text}> </div>
{result.Heading3}
</Text>
<Text key={index} style={styles.text}>
{result.Heading4}
</Text>
<Text key={index} style={styles.text}>
{result.Paragraph}
</Text>
<Text key={index} style={styles.text}>
{result.PageNum}
</Text>
</Fragment>
))}
</View>
</Page>
</Document>
); );
}; };
export default PDFGenerator;
export default PDFGenerator;

View File

@ -0,0 +1,21 @@
// pdfWorker.js
// Import the necessary libraries
import { pdf } from "react-pdf/dist/umd/entry.parcel";
import { saveAs } from "file-saver";
// Listen for messages from the main thread
self.addEventListener("message", async (event) => {
const pdfContent = event.data;
try {
// Generate PDF content
const pdfBlob = await pdf(pdfContent).toBlob();
// Send the PDF blob back to the main thread
self.postMessage(pdfBlob);
} catch (error) {
console.error("Error generating PDF:", error);
self.postMessage(null);
}
});