first push
This commit is contained in:
parent
604982f150
commit
98b53a0432
2320
package-lock.json
generated
2320
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
15
package.json
15
package.json
@ -3,12 +3,25 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@emotion/react": "^11.11.0",
|
||||||
|
"@emotion/styled": "^11.11.0",
|
||||||
|
"@mui/icons-material": "^5.11.16",
|
||||||
|
"@mui/material": "^5.13.0",
|
||||||
|
"@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",
|
||||||
"@testing-library/user-event": "^13.5.0",
|
"@testing-library/user-event": "^13.5.0",
|
||||||
|
"axios": "^1.4.0",
|
||||||
|
"bootstrap": "^5.2.3",
|
||||||
|
"d3": "^7.8.4",
|
||||||
|
"d3-cloud": "^1.2.5",
|
||||||
|
"file-saver": "^2.0.5",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
|
"react-bootstrap": "^2.7.4",
|
||||||
|
"react-d3-cloud": "^1.0.6",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-scripts": "5.0.1",
|
"react-pdf": "^6.2.2",
|
||||||
|
"react-scripts": "^5.0.1",
|
||||||
"web-vitals": "^2.1.4"
|
"web-vitals": "^2.1.4"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
138
src/App.js
138
src/App.js
@ -1,24 +1,126 @@
|
|||||||
import logo from './logo.svg';
|
import logo from "./logo.svg";
|
||||||
import './App.css';
|
import "./App.css";
|
||||||
|
|
||||||
|
import Search from "./Components/Layout/Search/Search";
|
||||||
|
import Filter from "./Components/Layout/Filter/Filter";
|
||||||
|
import ComplainceFilter from "./Components/Layout/Filter/ComplainceFilter";
|
||||||
|
import Results from "./Components/Layout/Results/Results";
|
||||||
|
import { Fragment, useState, useEffect } from "react";
|
||||||
|
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";
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
|
const [data, setData] = useState("");
|
||||||
|
const [results, setResults] = useState([]);
|
||||||
|
const [filteredResults, setFilteredResults] = useState([]);
|
||||||
|
const [filtersComplaince, setFiltersComplaince] = useState([]);
|
||||||
|
const [filtersStandards, setFiltersStandards] = useState([]);
|
||||||
|
|
||||||
|
// the useEffect hook is used to apply filters whenever the results,
|
||||||
|
// filtersStandards, or filtersComplaince values change
|
||||||
|
useEffect(() => {
|
||||||
|
setFilteredResults(
|
||||||
|
applyFilters(results, filtersStandards, filtersComplaince)
|
||||||
|
);
|
||||||
|
}, [results, filtersStandards, filtersComplaince]);
|
||||||
|
|
||||||
|
//################################################################################
|
||||||
|
const handleSubmit = (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
// Send the input value to Django
|
||||||
|
axios
|
||||||
|
.post("http://localhost:8000/get_input/", { data })
|
||||||
|
.then((response) => {
|
||||||
|
setResults(response.data.results);
|
||||||
|
setFilteredResults(response.data.results);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmit_ = (value) => {
|
||||||
|
// Send the input value to Django
|
||||||
|
axios
|
||||||
|
.post("http://localhost:8000/get_input/", { data: { phrase: value } })
|
||||||
|
.then((response) => {
|
||||||
|
setResults(response.data.results);
|
||||||
|
setFilteredResults(response.data.results);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
//################################################################################
|
||||||
|
// function to apply multiple filters to the results in any order and ensure
|
||||||
|
// that each filter is applied to the recent filtered results
|
||||||
|
function applyFilters(results, filter1, filter2) {
|
||||||
|
let filteredResults__ = results;
|
||||||
|
|
||||||
|
// Apply the Standards filter if it is provided, Array#some method checks if at least one
|
||||||
|
// element in filter1 matches the result.Title value.
|
||||||
|
if (filter1.length > 0) {
|
||||||
|
console.log("filter1");
|
||||||
|
filteredResults__ = filteredResults__.filter((result) => {
|
||||||
|
return filter1.some((filter) => filter == result.Title);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply the second filter if it is provided
|
||||||
|
if (filter2.length > 0) {
|
||||||
|
console.log("filter2");
|
||||||
|
filteredResults__ = filteredResults__.filter((result) => {
|
||||||
|
return filter2.every((filter) => result[filter]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return filteredResults__;
|
||||||
|
}
|
||||||
|
//################################################################################
|
||||||
|
|
||||||
|
// apply the complaince check on the results and then send the new results to the
|
||||||
|
// results component
|
||||||
|
function handleComplainceFilterChange(ComplainceFilterValue) {
|
||||||
|
setFiltersComplaince(ComplainceFilterValue);
|
||||||
|
}
|
||||||
|
//################################################################################
|
||||||
|
|
||||||
|
// apply the standards filter on the results and then send the new results to the
|
||||||
|
// results component
|
||||||
|
function handleStandardsFilterChange(StandardsFilterValue) {
|
||||||
|
setFiltersStandards(StandardsFilterValue);
|
||||||
|
}
|
||||||
|
//################################################################################
|
||||||
|
|
||||||
|
// append the input to the data. The data will be sent later to the
|
||||||
|
// server side
|
||||||
|
const handleChange = (event) => {
|
||||||
|
setData({
|
||||||
|
...data,
|
||||||
|
[event.target.name]: event.target.value,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="App">
|
<Fragment>
|
||||||
<header className="App-header">
|
<main>
|
||||||
<img src={logo} className="App-logo" alt="logo" />
|
<Container>
|
||||||
<p>
|
<Search onSubmit={handleSubmit} onChange={handleChange} />
|
||||||
Edit <code>src/App.js</code> and save to reload.
|
<Filter onFilterChange={handleStandardsFilterChange} />
|
||||||
</p>
|
<ComplainceFilter onFilterChange={handleComplainceFilterChange} />
|
||||||
<a
|
<Results results={filteredResults} />
|
||||||
className="App-link"
|
|
||||||
href="https://reactjs.org"
|
<Stack direction="horizontal" gap={3} as="div" className="d-flex justify-content-between">
|
||||||
target="_blank"
|
<FeaturedQuestions handleButtonClick={handleSubmit_} />
|
||||||
rel="noopener noreferrer"
|
<WordCloud_ />
|
||||||
>
|
</Stack>
|
||||||
Learn React
|
</Container>
|
||||||
</a>
|
</main>
|
||||||
</header>
|
</Fragment>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
40
src/Components/Layout/FeaturedQuestions/FeaturedQuestions.js
Normal file
40
src/Components/Layout/FeaturedQuestions/FeaturedQuestions.js
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import Container from "react-bootstrap/esm/Container";
|
||||||
|
import Stack from "react-bootstrap/esm/Stack";
|
||||||
|
import Card from "react-bootstrap/Card";
|
||||||
|
|
||||||
|
const FeaturedQuestions = ({ handleButtonClick }) => {
|
||||||
|
const handleClick = (value) => {
|
||||||
|
//console.log(event.target.value)
|
||||||
|
handleButtonClick(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const fqs = [
|
||||||
|
"What are DDR-related tools?",
|
||||||
|
"Who participates in a DDR process?",
|
||||||
|
"Which preconditions are required for the implementation of a viable DDR programme?",
|
||||||
|
"What is the difference between a ‘DDR process’ and a ‘DDR programme’?",
|
||||||
|
"How can ex-combatants be best supported in their reintegration?",
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Card className="p-3">
|
||||||
|
<h4 className="text-decoration-underline">
|
||||||
|
Featured Questions About IDDRS Framework
|
||||||
|
</h4>
|
||||||
|
<Stack gap={4}>
|
||||||
|
{fqs.map((fq) => (
|
||||||
|
<li key={fq}>
|
||||||
|
<a name="phrase" onClick={() => handleClick(fq)} value={fq}>
|
||||||
|
{fq}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</Stack>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FeaturedQuestions;
|
44
src/Components/Layout/Filter/ComplainceFilter.js
Normal file
44
src/Components/Layout/Filter/ComplainceFilter.js
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
import ToggleButton from "react-bootstrap/ToggleButton";
|
||||||
|
import ToggleButtonGroup from "react-bootstrap/ToggleButtonGroup";
|
||||||
|
import Container from "react-bootstrap/esm/Container";
|
||||||
|
import classes from "./ComplainceFilter.module.css";
|
||||||
|
|
||||||
|
function ComplainceFilter({ onFilterChange }) {
|
||||||
|
const [value, setValue] = useState([]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The second argument that will be passed to
|
||||||
|
* `handleChange` from `ToggleButtonGroup`
|
||||||
|
* is the SyntheticEvent object, but we are
|
||||||
|
* not using it in this example so we will omit it.
|
||||||
|
*/
|
||||||
|
const handleChange = (val) => {
|
||||||
|
//console.log(val);
|
||||||
|
setValue(val);
|
||||||
|
onFilterChange(val);
|
||||||
|
};
|
||||||
|
const complaince = ["Shall", "Should", "May", "Must", "Can"];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="mt-3">
|
||||||
|
<h5>Compliance Check:</h5>
|
||||||
|
<ToggleButtonGroup type="checkbox" value={value} onChange={handleChange}>
|
||||||
|
{complaince.map((comp, index) => (
|
||||||
|
<ToggleButton
|
||||||
|
type="checkbox"
|
||||||
|
variant="outline-secondary"
|
||||||
|
key={index}
|
||||||
|
id={`comp-btn-${index}`}
|
||||||
|
className={classes["comp-btn"]}
|
||||||
|
value={comp}
|
||||||
|
>
|
||||||
|
{comp}
|
||||||
|
</ToggleButton>
|
||||||
|
))}
|
||||||
|
</ToggleButtonGroup>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ComplainceFilter;
|
59
src/Components/Layout/Filter/Filter copy.js
Normal file
59
src/Components/Layout/Filter/Filter copy.js
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import Dropdown_ from "../../UI/Dropdown/Dropdown_";
|
||||||
|
import Container from "react-bootstrap/Container";
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
const Filter = ({ onFilterChange }) => {
|
||||||
|
const [levels, setLevels] = useState([]);
|
||||||
|
const [standards, setStandards] = useState([]);
|
||||||
|
const [standardsFilter, setStandardsFilter] = useState([]);
|
||||||
|
|
||||||
|
|
||||||
|
// get the filters values to this component
|
||||||
|
function handelOnFilterChange(newFilters){
|
||||||
|
setStandardsFilter(newFilters)
|
||||||
|
onFilterChange(newFilters)
|
||||||
|
//console.log(newFilters)
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
axios
|
||||||
|
.get("http://127.0.0.1:8000/levels/")
|
||||||
|
.then((response) => setLevels(response.data))
|
||||||
|
.catch((error) => console.log(error));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
axios
|
||||||
|
.get("http://127.0.0.1:8000/standards/")
|
||||||
|
.then((response) => setStandards(response.data))
|
||||||
|
.catch((error) => console.log(error));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container className="mt-5">
|
||||||
|
<div>
|
||||||
|
<h5>Filter by standards:</h5>
|
||||||
|
|
||||||
|
<div className="d-flex justify-content-between mt-2">
|
||||||
|
{levels.map((level) => (
|
||||||
|
<Dropdown_
|
||||||
|
key={level.id}
|
||||||
|
id={level.id}
|
||||||
|
className={"level-" + level.levelNumber}
|
||||||
|
name = {level.levelNumber}
|
||||||
|
standards={standards.filter(
|
||||||
|
(standard) => standard.standardLevel === level.levelNumber
|
||||||
|
)}
|
||||||
|
onFilterChange={handelOnFilterChange}
|
||||||
|
>
|
||||||
|
{level.levelName}
|
||||||
|
</Dropdown_>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Filter;
|
84
src/Components/Layout/Filter/Filter.js
Normal file
84
src/Components/Layout/Filter/Filter.js
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
import React, { useEffect, useState, Fragment } from "react";
|
||||||
|
import Container from "react-bootstrap/Container";
|
||||||
|
import Dropdown from "react-bootstrap/Dropdown";
|
||||||
|
import classes from "../../../Static/styles.module.css";
|
||||||
|
import ToggleButton from "react-bootstrap/esm/ToggleButton";
|
||||||
|
import ToggleButtonGroup from "react-bootstrap/esm/ToggleButtonGroup";
|
||||||
|
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
const Filter = ({ onFilterChange }) => {
|
||||||
|
const [levels, setLevels] = useState([]);
|
||||||
|
const [standards, setStandards] = useState([]);
|
||||||
|
const [standardsFilter, setStandardsFilter] = useState([]);
|
||||||
|
|
||||||
|
// get the filters values to this component
|
||||||
|
const handelOnFilterChange = (val) => {
|
||||||
|
// console.log(val);
|
||||||
|
setStandardsFilter(val);
|
||||||
|
onFilterChange(val);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
axios
|
||||||
|
.get("http://127.0.0.1:8000/levels/")
|
||||||
|
.then((response) => setLevels(response.data))
|
||||||
|
.catch((error) => console.log(error));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
axios
|
||||||
|
.get("http://127.0.0.1:8000/standards/")
|
||||||
|
.then((response) => setStandards(response.data))
|
||||||
|
.catch((error) => console.log(error));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="mt-5">
|
||||||
|
<h5>Filter by standards:</h5>
|
||||||
|
|
||||||
|
<div className="d-flex justify-content-between mt-2">
|
||||||
|
{levels.map((level) => (
|
||||||
|
<Dropdown key={level.id}>
|
||||||
|
<Dropdown.Toggle
|
||||||
|
id={level.id}
|
||||||
|
className={classes["level-" + level.levelNumber]}
|
||||||
|
>
|
||||||
|
{level.levelName}
|
||||||
|
</Dropdown.Toggle>
|
||||||
|
|
||||||
|
<Dropdown.Menu className="w-100">
|
||||||
|
<ToggleButtonGroup
|
||||||
|
type="checkbox"
|
||||||
|
value={standardsFilter}
|
||||||
|
onChange={handelOnFilterChange}
|
||||||
|
vertical
|
||||||
|
name={level.levelNumber}
|
||||||
|
>
|
||||||
|
{standards
|
||||||
|
.filter(
|
||||||
|
(standard) => standard.standardLevel === level.levelNumber
|
||||||
|
)
|
||||||
|
.map((standard, index) => (
|
||||||
|
<ToggleButton
|
||||||
|
name="std"
|
||||||
|
type="checkbox"
|
||||||
|
variant="outline-secondary"
|
||||||
|
key={standard.id}
|
||||||
|
id={`std-btn-${standard.id}`}
|
||||||
|
//className={classes["comp-btn"]}
|
||||||
|
value={standard.standardTitle}
|
||||||
|
>
|
||||||
|
{standard.standardTitle}
|
||||||
|
</ToggleButton>
|
||||||
|
))}
|
||||||
|
</ToggleButtonGroup>
|
||||||
|
</Dropdown.Menu>
|
||||||
|
</Dropdown>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Filter;
|
9
src/Components/Layout/KeyPhrases/KeyPhrases.js
Normal file
9
src/Components/Layout/KeyPhrases/KeyPhrases.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
const KeyPhrases=() => {
|
||||||
|
return (
|
||||||
|
<h4>KeyPhrases</h4>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default KeyPhrases
|
84
src/Components/Layout/Results/Results.js
Normal file
84
src/Components/Layout/Results/Results.js
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import Card from "../../UI/Card/Card";
|
||||||
|
import Container from "react-bootstrap/esm/Container";
|
||||||
|
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 { PDFDownloadLink } from "@react-pdf/renderer";
|
||||||
|
import Button from "react-bootstrap/esm/Button";
|
||||||
|
|
||||||
|
const Results = (props) => {
|
||||||
|
const [showModal, setShowModal] = useState(false);
|
||||||
|
const [selectedResult, setSelectedResult] = useState(null);
|
||||||
|
|
||||||
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
|
// eslint-disable-next-line
|
||||||
|
const [postsPerPage, setPostsPerPage] = useState(10);
|
||||||
|
|
||||||
|
const lastPostIndex = currentPage * postsPerPage;
|
||||||
|
const firstPostIndex = lastPostIndex - postsPerPage;
|
||||||
|
const currentPost = props.results.slice(firstPostIndex, lastPostIndex);
|
||||||
|
|
||||||
|
const handleShowModal = (result) => {
|
||||||
|
setSelectedResult(result);
|
||||||
|
setShowModal(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCloseModal = () => {
|
||||||
|
setShowModal(false);
|
||||||
|
setSelectedResult(null);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<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} /> */}
|
||||||
|
|
||||||
|
<Card className="secondary p-1">
|
||||||
|
<h2 className="text-secondary text-center">Searched Phrase</h2>
|
||||||
|
|
||||||
|
<Stack gap={3} className="mt-3">
|
||||||
|
{currentPost.map((result) => (
|
||||||
|
<ResultsItem
|
||||||
|
onClick={() => handleShowModal(result)}
|
||||||
|
key={result.Index}
|
||||||
|
level={result.Level}
|
||||||
|
title={result.Title}
|
||||||
|
heading1={result.Heading1}
|
||||||
|
paragraph={result.Paragraph}
|
||||||
|
></ResultsItem>
|
||||||
|
))}
|
||||||
|
</Stack>
|
||||||
|
<ResultsPagination
|
||||||
|
totalPosts={props.results.length}
|
||||||
|
postsPerPage={postsPerPage}
|
||||||
|
setCurrentPage={setCurrentPage}
|
||||||
|
currentPage={currentPage}
|
||||||
|
></ResultsPagination>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<ResultModal
|
||||||
|
show={showModal}
|
||||||
|
handleClose={handleCloseModal}
|
||||||
|
level={selectedResult ? selectedResult.Level : ""}
|
||||||
|
module={selectedResult ? selectedResult.Module : ""}
|
||||||
|
heading1={selectedResult ? selectedResult.Heading1 : ""}
|
||||||
|
heading2={selectedResult ? selectedResult.Heading2 : ""}
|
||||||
|
heading3={selectedResult ? selectedResult.Heading3 : ""}
|
||||||
|
heading4={selectedResult ? selectedResult.Heading4 : ""}
|
||||||
|
pageNumber={selectedResult ? selectedResult.PageNum : ""}
|
||||||
|
paragraph={selectedResult ? selectedResult.Paragraph : ""}
|
||||||
|
></ResultModal>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Results;
|
28
src/Components/Layout/Results/ResultsItem.js
Normal file
28
src/Components/Layout/Results/ResultsItem.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import React from "react";
|
||||||
|
import Card from "react-bootstrap/Card";
|
||||||
|
import classes from "../../../Static/styles.module.css"
|
||||||
|
|
||||||
|
|
||||||
|
const ResultsItem = (props) => {
|
||||||
|
|
||||||
|
const truncateText = (text, maxLength) =>{
|
||||||
|
if (text.length > maxLength) {
|
||||||
|
return text.substring(0, maxLength) + "...";
|
||||||
|
} else {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Card onClick = {props.onClick}>
|
||||||
|
<Card.Header className={ classes[`level-text-${props.level}`] }>
|
||||||
|
Level {props.level}, {props.title}
|
||||||
|
</Card.Header>
|
||||||
|
<Card.Body>
|
||||||
|
<Card.Title>{props.heading1}</Card.Title>
|
||||||
|
<Card.Text>{truncateText(props.paragraph, 300)} </Card.Text>
|
||||||
|
</Card.Body>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ResultsItem;
|
36
src/Components/Layout/Search/Search.js
Normal file
36
src/Components/Layout/Search/Search.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import Input from "../../UI/Input/Input";
|
||||||
|
import Button_ from "../../UI/Button/Button_";
|
||||||
|
import Form from "react-bootstrap/Form";
|
||||||
|
import Container from "react-bootstrap/Container";
|
||||||
|
|
||||||
|
|
||||||
|
const Search = (props) => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="mt-5">
|
||||||
|
<Form
|
||||||
|
id="searchForm"
|
||||||
|
method="get"
|
||||||
|
className="d-flex align-items-center"
|
||||||
|
onSubmit={props.onSubmit}
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
placeholder="Search IDDRS..."
|
||||||
|
type="text"
|
||||||
|
id="search_input"
|
||||||
|
name="phrase"
|
||||||
|
aria-label="Seach IDDRS..."
|
||||||
|
aria-describedby="basic-addon1"
|
||||||
|
onChange={props.onChange}
|
||||||
|
></Input>
|
||||||
|
|
||||||
|
<Button_ id="submitSearch" type="submit" className="btn-default">
|
||||||
|
Search
|
||||||
|
</Button_>
|
||||||
|
</Form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Search;
|
118
src/Components/Layout/WordCloud_/WordCloud_.js
Normal file
118
src/Components/Layout/WordCloud_/WordCloud_.js
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
import React, { Fragment } from "react";
|
||||||
|
import { render } from "react-dom";
|
||||||
|
import WordCloud from "react-d3-cloud";
|
||||||
|
import Container from "react-bootstrap/esm/Container";
|
||||||
|
import Card from "react-bootstrap/Card";
|
||||||
|
|
||||||
|
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_ = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Card>
|
||||||
|
<h4 className="text-decoration-underline">
|
||||||
|
Most Frequent Key-Phrases
|
||||||
|
</h4>
|
||||||
|
<WordCloud
|
||||||
|
width={1000}
|
||||||
|
data={data}
|
||||||
|
font="Times"
|
||||||
|
fontStyle="italic"
|
||||||
|
//fontWeight="bold"
|
||||||
|
fontSize={(word) => Math.log2(word.value) * 3}
|
||||||
|
spiral="rectangular"
|
||||||
|
rotate={0}
|
||||||
|
fill = "gray"
|
||||||
|
padding={2}
|
||||||
|
onWordClick={(event, d) => {
|
||||||
|
console.log(`onWordClick: ${d.text}`);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default WordCloud_;
|
69
src/Components/PDFGenerator/PDFGenerator.js
Normal file
69
src/Components/PDFGenerator/PDFGenerator.js
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import React, { Fragment } from "react";
|
||||||
|
import {
|
||||||
|
Document,
|
||||||
|
Page,
|
||||||
|
Text,
|
||||||
|
View,
|
||||||
|
StyleSheet,
|
||||||
|
Font
|
||||||
|
} from "@react-pdf/renderer";
|
||||||
|
|
||||||
|
// Register font
|
||||||
|
Font.register({ family: "Times-Roman" });
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
page: {
|
||||||
|
flexDirection: "row",
|
||||||
|
backgroundColor: "#E4E4E4",
|
||||||
|
padding: 10,
|
||||||
|
},
|
||||||
|
|
||||||
|
text: {
|
||||||
|
fontFamily: "Times-Roman",
|
||||||
|
fontSize: 12,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
fontSize: 14,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const PDFGenerator = (props) => {
|
||||||
|
return (
|
||||||
|
<Document>
|
||||||
|
<Page size="A4" style={styles.page}>
|
||||||
|
<View style={styles.content}>
|
||||||
|
{props.results.map((result, index) => (
|
||||||
|
<Fragment>
|
||||||
|
<Text key={index} style={[styles.text, styles.title]}>
|
||||||
|
Level {result.LevelName}
|
||||||
|
</Text>
|
||||||
|
<Text key={index} style={[styles.text, styles.title]}>
|
||||||
|
IDDRS - {result.Module}
|
||||||
|
</Text>
|
||||||
|
<Text key={index} style={styles.text}>
|
||||||
|
{result.Heading1}
|
||||||
|
</Text>
|
||||||
|
<Text key={index} style={styles.text}>
|
||||||
|
{result.Heading2}
|
||||||
|
</Text>
|
||||||
|
<Text key={index} style={styles.text}>
|
||||||
|
{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;
|
0
src/Components/UI/Button/Button.module.css
Normal file
0
src/Components/UI/Button/Button.module.css
Normal file
12
src/Components/UI/Button/Button_.js
Normal file
12
src/Components/UI/Button/Button_.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import React from "react";
|
||||||
|
import Button from "react-bootstrap/Button";
|
||||||
|
|
||||||
|
const Button_ = (props) => {
|
||||||
|
return (
|
||||||
|
<Button id={props.id} type={props.type} className={props.class}>
|
||||||
|
{props.children}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Button_;
|
10
src/Components/UI/Card/Card.js
Normal file
10
src/Components/UI/Card/Card.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import React from "react";
|
||||||
|
import classes from './Card.module.css'
|
||||||
|
|
||||||
|
const Card = props => {
|
||||||
|
return (
|
||||||
|
<div className={`${classes.card} ${props.className} `}>{props.children}</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Card;
|
5
src/Components/UI/Card/Card.module.css
Normal file
5
src/Components/UI/Card/Card.module.css
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
.card{
|
||||||
|
/* background-color: antiquewhite; */
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.26);
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
14
src/Components/UI/Dropdown/DropdownItem.js
Normal file
14
src/Components/UI/Dropdown/DropdownItem.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import React from "react";
|
||||||
|
import Dropdown from "react-bootstrap/Dropdown";
|
||||||
|
import Form from "react-bootstrap/Form";
|
||||||
|
|
||||||
|
const DropdownItem = (props) => {
|
||||||
|
return (
|
||||||
|
|
||||||
|
<Form.Check type="checkbox" id={`check-api-${props.id}`} label={props.children} isValid>
|
||||||
|
|
||||||
|
</Form.Check>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DropdownItem;
|
56
src/Components/UI/Dropdown/Dropdown_.js
Normal file
56
src/Components/UI/Dropdown/Dropdown_.js
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import Dropdown from "react-bootstrap/Dropdown";
|
||||||
|
import DropdownItem from "./DropdownItem";
|
||||||
|
import classes from "../../../Static/styles.module.css";
|
||||||
|
import ToggleButton from "react-bootstrap/esm/ToggleButton";
|
||||||
|
import ToggleButtonGroup from "react-bootstrap/esm/ToggleButtonGroup";
|
||||||
|
|
||||||
|
const Dropdown_ = (props) => {
|
||||||
|
|
||||||
|
const [filterValues, setFilterValues] = useState({});
|
||||||
|
|
||||||
|
// Handle change event for ToggleButtonGroup
|
||||||
|
const handleToggleChange = (name, values) => {
|
||||||
|
setFilterValues((prevState) => ({
|
||||||
|
...prevState,
|
||||||
|
[name]: values,
|
||||||
|
}));
|
||||||
|
|
||||||
|
props.onFilterChange(filterValues)
|
||||||
|
//console.log(filterValues);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dropdown>
|
||||||
|
<Dropdown.Toggle id={props.id} className={classes[props.className]}>
|
||||||
|
{props.children}
|
||||||
|
</Dropdown.Toggle>
|
||||||
|
|
||||||
|
<Dropdown.Menu className="w-100">
|
||||||
|
<ToggleButtonGroup
|
||||||
|
type="checkbox"
|
||||||
|
value={filterValues[props.name] || []}
|
||||||
|
onChange={(values) => handleToggleChange(props.name, values)}
|
||||||
|
vertical
|
||||||
|
name={props.name}
|
||||||
|
>
|
||||||
|
{props.standards.map((standard, index) => (
|
||||||
|
<ToggleButton
|
||||||
|
name="std"
|
||||||
|
type="checkbox"
|
||||||
|
variant="outline-secondary"
|
||||||
|
key={standard.id}
|
||||||
|
id={`std-btn-${standard.id}`}
|
||||||
|
//className={classes["comp-btn"]}
|
||||||
|
value={standard.standardTitle}
|
||||||
|
>
|
||||||
|
{standard.standardTitle}
|
||||||
|
</ToggleButton>
|
||||||
|
))}
|
||||||
|
</ToggleButtonGroup>
|
||||||
|
</Dropdown.Menu>
|
||||||
|
</Dropdown>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Dropdown_;
|
22
src/Components/UI/Input/Input.js
Normal file
22
src/Components/UI/Input/Input.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import React from "react";
|
||||||
|
import Form from "react-bootstrap/Form";
|
||||||
|
import InputGroup from "react-bootstrap/InputGroup";
|
||||||
|
//import classes from "./input.module.css"
|
||||||
|
|
||||||
|
const Input = (props) => {
|
||||||
|
return (
|
||||||
|
|
||||||
|
<Form.Control
|
||||||
|
placeholder={props.placeholder}
|
||||||
|
type={props.type}
|
||||||
|
id={props.id}
|
||||||
|
name={props.name}
|
||||||
|
aria-label={props['aria-label']}
|
||||||
|
aria-describedby = {props['aria-describedby']}
|
||||||
|
onChange = {props.onChange}
|
||||||
|
/>
|
||||||
|
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Input;
|
0
src/Components/UI/Input/Input.module.css
Normal file
0
src/Components/UI/Input/Input.module.css
Normal file
38
src/Components/UI/ResultModal/ResultModal.js
Normal file
38
src/Components/UI/ResultModal/ResultModal.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import Modal from "react-bootstrap/Modal";
|
||||||
|
import Button from "react-bootstrap/esm/Button";
|
||||||
|
import classes from "../../../Static/styles.module.css"
|
||||||
|
|
||||||
|
|
||||||
|
const ResultModal = (props) => {
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
{...props}
|
||||||
|
size='xl'
|
||||||
|
aria-labelledby="example-custom-modal-styling-title"
|
||||||
|
centered
|
||||||
|
onHide={props.handleClose}
|
||||||
|
|
||||||
|
>
|
||||||
|
<Modal.Header closeButton>
|
||||||
|
<Modal.Title id="example-custom-modal-styling-title">
|
||||||
|
<div className={classes[`level-text-${props.level}`]}>Level {props.level}</div>
|
||||||
|
<div className="mb-3">IDDRS - {props.module}</div>
|
||||||
|
<p className="fs-5 fw-light mb-0">{props.heading1}</p>
|
||||||
|
<p className="fs-6 fw-light mb-0">{props.heading2}</p>
|
||||||
|
<p className="fs-6 fw-light mb-0">{props.heading3}</p>
|
||||||
|
<p className="fs-6 fw-light mb-0">{props.heading4}</p>
|
||||||
|
</Modal.Title>
|
||||||
|
</Modal.Header>
|
||||||
|
<Modal.Body>
|
||||||
|
<p className="fs-6 fw-light">{props.paragraph}</p>
|
||||||
|
<div className="fs-5 fw-light mt-4"><p class="text-end">Page: {props.pageNumber}</p></div>
|
||||||
|
</Modal.Body>
|
||||||
|
<Modal.Footer>
|
||||||
|
<Button onClick={props.handleClose}>Close</Button>
|
||||||
|
</Modal.Footer>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ResultModal;
|
103
src/Components/UI/ResultsPagination/ResultsPagination.js
Normal file
103
src/Components/UI/ResultsPagination/ResultsPagination.js
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import classes from "./ResultsPagination.module.css";
|
||||||
|
import Button from "react-bootstrap/esm/Button";
|
||||||
|
import Pagination from "react-bootstrap/Pagination";
|
||||||
|
|
||||||
|
const ResultsPagination = ({
|
||||||
|
totalPosts,
|
||||||
|
postsPerPage,
|
||||||
|
setCurrentPage,
|
||||||
|
currentPage,
|
||||||
|
}) => {
|
||||||
|
const [pageNumberLimit, setpageNumberLimit] = useState(5);
|
||||||
|
const [maxPageNumberLimit, setmaxPageNumberLimit] = useState(5);
|
||||||
|
const [minPageNumberLimit, setminPageNumberLimit] = useState(0);
|
||||||
|
//console.log(maxPageNumberLimit, minPageNumberLimit);
|
||||||
|
let pages = [];
|
||||||
|
for (let i = 1; i <= Math.ceil(totalPosts / postsPerPage); i++) {
|
||||||
|
pages.push(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleNextbtn = () => {
|
||||||
|
setCurrentPage(currentPage + 1);
|
||||||
|
|
||||||
|
if (currentPage + 1 > maxPageNumberLimit) {
|
||||||
|
setmaxPageNumberLimit(maxPageNumberLimit + pageNumberLimit);
|
||||||
|
setminPageNumberLimit(minPageNumberLimit + pageNumberLimit);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePrevbtn = () => {
|
||||||
|
setCurrentPage(currentPage - 1);
|
||||||
|
|
||||||
|
if ((currentPage - 1) % pageNumberLimit == 0) {
|
||||||
|
setmaxPageNumberLimit(maxPageNumberLimit - pageNumberLimit);
|
||||||
|
setminPageNumberLimit(minPageNumberLimit - pageNumberLimit);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFirstbtn = () => {
|
||||||
|
setCurrentPage(1);
|
||||||
|
setmaxPageNumberLimit(5);
|
||||||
|
setminPageNumberLimit(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleLastbtn = () => {
|
||||||
|
setCurrentPage(pages.slice(-1));
|
||||||
|
setmaxPageNumberLimit(Math.floor(pages.slice(-1) / 5) * 5);
|
||||||
|
setminPageNumberLimit(Math.floor(pages.slice(-1) / 5) * 5 - 5);
|
||||||
|
console.log(currentPage)
|
||||||
|
};
|
||||||
|
|
||||||
|
let pageIncrementBtn = null;
|
||||||
|
if (pages.length > maxPageNumberLimit) {
|
||||||
|
pageIncrementBtn = <p> … </p>;
|
||||||
|
}
|
||||||
|
|
||||||
|
let pageDecrementBtn = null;
|
||||||
|
if (minPageNumberLimit >= 1) {
|
||||||
|
pageDecrementBtn = <p> … </p>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={classes.pagination}>
|
||||||
|
<Button onClick={handleFirstbtn} variant="primary">
|
||||||
|
{"<<"}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={handlePrevbtn}
|
||||||
|
disabled={currentPage == pages[0] ? true : false}
|
||||||
|
variant="secondary"
|
||||||
|
>
|
||||||
|
Prev
|
||||||
|
</Button>
|
||||||
|
{pageDecrementBtn}
|
||||||
|
{pages.map((page, index) => {
|
||||||
|
if (page < maxPageNumberLimit + 1 && page > minPageNumberLimit) {
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
key={index}
|
||||||
|
onClick={() => setCurrentPage(page)}
|
||||||
|
className={page == currentPage ? classes.active : ""}
|
||||||
|
>
|
||||||
|
{page}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
{pageIncrementBtn}
|
||||||
|
<Button
|
||||||
|
onClick={handleNextbtn}
|
||||||
|
disabled={currentPage == pages[pages.length - 1] ? true : false}
|
||||||
|
variant="secondary"
|
||||||
|
>
|
||||||
|
Next
|
||||||
|
</Button>
|
||||||
|
<Button onClick={handleLastbtn} variant="primary">
|
||||||
|
{">>"}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ResultsPagination;
|
@ -0,0 +1,27 @@
|
|||||||
|
.pagination {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: 1rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination button {
|
||||||
|
font-family: inherit;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 16px;
|
||||||
|
margin: 0 10px;
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
background: transparent;
|
||||||
|
color: #000000;
|
||||||
|
border-color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination button.active {
|
||||||
|
font-weight: 900;
|
||||||
|
border-color: #101010;
|
||||||
|
background: #0275d8;
|
||||||
|
color: #101010;
|
||||||
|
}
|
7
src/Static/functions.js
Normal file
7
src/Static/functions.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
function truncateText(text, maxLength) {
|
||||||
|
if (text.length > maxLength) {
|
||||||
|
return text.substring(0, maxLength) + "...";
|
||||||
|
} else {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
}
|
53
src/Static/styles.module.css
Normal file
53
src/Static/styles.module.css
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
.level-1 {
|
||||||
|
background-color: #F07F4E !important;
|
||||||
|
border: 0px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level-2 {
|
||||||
|
background-color: #008DCA !important;
|
||||||
|
border: 0px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level-3 {
|
||||||
|
background-color: #00A554 !important;
|
||||||
|
border: 0px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level-4 {
|
||||||
|
background-color: #7366A3 !important;
|
||||||
|
border: 0px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level-5 {
|
||||||
|
background-color: #D10007 !important;
|
||||||
|
border: 0px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level-6 {
|
||||||
|
background-color: #CF7AB2 !important;
|
||||||
|
border: 0px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level-text-1 {
|
||||||
|
color: #F07F4E !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level-text-2 {
|
||||||
|
color: #008DCA !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level-text-3 {
|
||||||
|
color: #00A554 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level-text-4 {
|
||||||
|
color: #7366A3 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level-text-5 {
|
||||||
|
color: #D10007 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.level-text-6 {
|
||||||
|
color: #CF7AB2 !important;
|
||||||
|
}
|
@ -1,9 +1,10 @@
|
|||||||
|
import 'bootstrap/dist/css/bootstrap.css';
|
||||||
|
import 'bootstrap/dist/js/bootstrap.bundle.min.js';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom/client';
|
import ReactDOM from 'react-dom/client';
|
||||||
import './index.css';
|
import './index.css';
|
||||||
import App from './App';
|
import App from './App';
|
||||||
import reportWebVitals from './reportWebVitals';
|
import reportWebVitals from './reportWebVitals';
|
||||||
|
|
||||||
const root = ReactDOM.createRoot(document.getElementById('root'));
|
const root = ReactDOM.createRoot(document.getElementById('root'));
|
||||||
root.render(
|
root.render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
|
Loading…
Reference in New Issue
Block a user