Co-authored-by: Nick Quidas <nrfq@users.noreply.github.com>
parent
c3577ccbf7
commit
84b7a9d100
File diff suppressed because it is too large
Load Diff
|
@ -8,14 +8,15 @@
|
|||
"@testing-library/react": "^11.2.7",
|
||||
"@testing-library/user-event": "^12.8.3",
|
||||
"axios": "^0.24.0",
|
||||
"express": "^4.17.1",
|
||||
"fuse": "^0.4.0",
|
||||
"fuse.js": "^6.4.6",
|
||||
"jQuery": "^1.7.4",
|
||||
"react": "^17.0.2",
|
||||
"react-cookie": "^4.1.1",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-markdown": "^8.0.2",
|
||||
"react-router-dom": "^6.3.0",
|
||||
"react-scripts": "4.0.3",
|
||||
"rehype-slug": "^5.0.1",
|
||||
"web-vitals": "^1.1.2"
|
||||
},
|
||||
"scripts": {
|
||||
|
|
|
@ -31,7 +31,7 @@ h2 {
|
|||
|
||||
h3, h4, h5, h6 {
|
||||
color:#494949;
|
||||
font-weight: 500;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
a {
|
||||
|
@ -339,7 +339,7 @@ a{
|
|||
}
|
||||
|
||||
.result {
|
||||
width: 30%;
|
||||
/* width: 30%; */
|
||||
padding: 0.25em 0.5em;
|
||||
}
|
||||
|
||||
|
|
309
src/App.js
309
src/App.js
|
@ -1,4 +1,5 @@
|
|||
import React, { useState, useEffect, createContext } from "react";
|
||||
import { BrowserRouter, Route, Routes } from "react-router-dom";
|
||||
import LangFilters from "./components/LangFilters";
|
||||
import SectDropdown from "./components/SectDropdown";
|
||||
import SearchBar from "./components/SearchBar";
|
||||
|
@ -6,72 +7,17 @@ import SearchResult from "./components/SearchResult";
|
|||
import LightSwitch from "./components/LightSwitch";
|
||||
import axios from "axios";
|
||||
import Fuse from "fuse.js";
|
||||
import { ThemeContext, themes, swapMode } from './darkMode';
|
||||
import { useCookies } from 'react-cookie';
|
||||
import { ThemeContext, themes, swapMode } from "./darkMode";
|
||||
import { useCookies } from "react-cookie";
|
||||
|
||||
import Default from "./components/Default";
|
||||
|
||||
import SunImg from "./img/sun.png";
|
||||
import MoonImg from "./img/moon.png";
|
||||
import BookList from "./components/BookList";
|
||||
|
||||
const fpb = null;
|
||||
|
||||
// eslint-disable-next-line
|
||||
function makeBook(author, hLang, cLang, title, url) {
|
||||
//returns a struct with basic book info (author, human language, computer language, book title, url)
|
||||
return {
|
||||
author: author,
|
||||
hLang: hLang, //human language
|
||||
cLang: cLang, //computer language
|
||||
title: title,
|
||||
url: url,
|
||||
};
|
||||
}
|
||||
|
||||
// eslint-disable-next-line
|
||||
function forEachBook(func, json) {
|
||||
//Runs func on each section, entry, and book in json, which is a list of entries
|
||||
if (typeof func !== "function") {
|
||||
// eslint-disable-next-line
|
||||
throw "ERROR in forEachBook: parameter not a fucntion";
|
||||
}
|
||||
|
||||
for (const hLang in json) {
|
||||
//for each human language
|
||||
if (Array.isArray(hLang.sections)) {
|
||||
//check if sections is an array
|
||||
hLang.sections.forEach(
|
||||
(
|
||||
cLang //for each computer lanuage
|
||||
) => {
|
||||
if (Array.isArray(cLang.entries)) {
|
||||
//verify is entries is an array
|
||||
cLang.entries.forEach(
|
||||
(
|
||||
book //for each book
|
||||
) => {
|
||||
if (typeof book === "object") {
|
||||
//verify that book is an object
|
||||
func(json[hLang], cLang, book); //run the function
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sorts search results by their score
|
||||
// eslint-disable-next-line
|
||||
function sortByScore(results) {
|
||||
results.sort(function (a, b) {
|
||||
return a.score - b.score;
|
||||
});
|
||||
return results;
|
||||
}
|
||||
|
||||
function jsonToArray(json) {
|
||||
let arr = [];
|
||||
let sections = [];
|
||||
|
@ -112,8 +58,7 @@ function App() {
|
|||
const [loading, setLoading] = useState(true); // Determines whether to show spinner
|
||||
const [searchParams, setSearchParams] = useState({ searchTerm: "" });
|
||||
const [searchResults, setSearchResults] = useState([]);
|
||||
const [sectionResults, setSectionResults] = useState([]);
|
||||
const [cookies, setCookie, removeCookie] = useCookies(['lightMode']);
|
||||
const [cookies, setCookie, removeCookie] = useCookies(["lightMode"]);
|
||||
|
||||
const [lightMode, setLightMode] = useState(true);
|
||||
|
||||
|
@ -121,7 +66,6 @@ const [cookies, setCookie, removeCookie] = useCookies(['lightMode']);
|
|||
const [error, setError] = useState("");
|
||||
|
||||
let resultsList = null; // the html string containing the search results
|
||||
let sectionResultsList = null;
|
||||
|
||||
const changeParameter = (param, value) => {
|
||||
// Lets a child component set the value of the search term
|
||||
|
@ -130,7 +74,7 @@ const [cookies, setCookie, removeCookie] = useCookies(['lightMode']);
|
|||
|
||||
// fetches data the first time the page renders
|
||||
useEffect(() => {
|
||||
swapMode(cookies.lightMode ? themes.lightMode : themes.darkMode)
|
||||
swapMode(cookies.lightMode ? themes.lightMode : themes.darkMode);
|
||||
async function fetchData() {
|
||||
try {
|
||||
setLoading(true);
|
||||
|
@ -154,7 +98,7 @@ const [cookies, setCookie, removeCookie] = useCookies(['lightMode']);
|
|||
}, []);
|
||||
|
||||
// fires when searchTerm changes
|
||||
// Finds most relevant title or author
|
||||
// Finds most relevant title or author
|
||||
// THIS IS THE MAIN SEARCH FUNCTION
|
||||
useEffect(() => {
|
||||
if (dataArray) {
|
||||
|
@ -177,17 +121,17 @@ const [cookies, setCookie, removeCookie] = useCookies(['lightMode']);
|
|||
if (value === null || value === "") continue;
|
||||
if (key === "lang.code" || key === "section") {
|
||||
// the '^' means it must be an exact match at the beginning
|
||||
// this is because lang.code and section are strict filters
|
||||
// this is because lang.code and section are strict filters
|
||||
andQuery.push({ [key]: `^${value}` });
|
||||
}
|
||||
if(key === "searchTerm") {
|
||||
orQuery.push({ "author": value});
|
||||
orQuery.push({ "title": value});
|
||||
if (key === "searchTerm") {
|
||||
orQuery.push({ author: value });
|
||||
orQuery.push({ title: value });
|
||||
}
|
||||
}
|
||||
// Nest the 'or' query inside the 'and' query
|
||||
// Necessary step, a quirk with fuse.js
|
||||
andQuery.push({$or: orQuery})
|
||||
andQuery.push({ $or: orQuery });
|
||||
// Perform the search
|
||||
let result = fuse.search({
|
||||
$and: andQuery,
|
||||
|
@ -215,7 +159,7 @@ const [cookies, setCookie, removeCookie] = useCookies(['lightMode']);
|
|||
}
|
||||
|
||||
let id = section;
|
||||
|
||||
|
||||
// Some ids are in HTML tags, so this will extract that id to form proper links
|
||||
if (id.includes("<a")) {
|
||||
let x = id.match(/"(.*?)"/)[0];
|
||||
|
@ -251,15 +195,6 @@ const [cookies, setCookie, removeCookie] = useCookies(['lightMode']);
|
|||
result = relevantLists.concat(result);
|
||||
setSearchResults(result);
|
||||
// console.log(result);
|
||||
|
||||
// No longer needed as the sections aren't being used
|
||||
// let sResults = []; // section results
|
||||
// // Finds the most relevant sections
|
||||
// result.forEach((entry) => {
|
||||
// let section = entry.item.section;
|
||||
// if (!sResults.includes(section)) sResults.push(section);
|
||||
// });
|
||||
// setSectionResults(sResults);
|
||||
}
|
||||
}, [searchParams, dataArray]);
|
||||
|
||||
|
@ -276,128 +211,108 @@ const [cookies, setCookie, removeCookie] = useCookies(['lightMode']);
|
|||
searchResults.map((entry) => {
|
||||
return <SearchResult data={entry.item} />;
|
||||
});
|
||||
// Getting rid of the section results UI renders this irrelevant
|
||||
// sectionResultsList =
|
||||
// sectionResults &&
|
||||
// sectionResults.map((section) => {
|
||||
// return (
|
||||
// <button
|
||||
// onClick={() => {
|
||||
// changeParameter("section", section);
|
||||
// }}
|
||||
// >
|
||||
// {section}
|
||||
// </button>
|
||||
// );
|
||||
// });
|
||||
}
|
||||
return (
|
||||
|
||||
<div
|
||||
className="wrapper"
|
||||
// style={{
|
||||
// color: lightMode ? "black" : "white",
|
||||
// backgroundColor: lightMode ? "white" : "black",
|
||||
// }}
|
||||
>
|
||||
<ThemeContext.Consumer>
|
||||
{ ({ changeTheme }) => {
|
||||
let willBeDarkMode = (cookies.lightMode && cookies.lightMode.toLowerCase() !== "true") //whether or not we are currently light mode and will become dark mode
|
||||
changeTheme(willBeDarkMode ? themes.light : themes.dark)
|
||||
return (<img src={willBeDarkMode ? MoonImg : SunImg}
|
||||
onClick = {()=>{
|
||||
setCookie("lightMode",willBeDarkMode);
|
||||
changeTheme(willBeDarkMode ? themes.light : themes.dark)
|
||||
}}
|
||||
style={{width: "20px", height: "20px",display: "block",
|
||||
marginLeft: "auto"
|
||||
}}
|
||||
/>)}
|
||||
}
|
||||
</ThemeContext.Consumer>
|
||||
<header className="header">
|
||||
|
||||
<h1>
|
||||
<a href="https://ebookfoundation.github.io/free-programming-books/" target="_blank" rel="noreferrer">
|
||||
free-programming-books
|
||||
</a>
|
||||
</h1>
|
||||
|
||||
<p>
|
||||
<img
|
||||
className="emoji"
|
||||
title=":books:"
|
||||
alt=":books:"
|
||||
src="https://github.githubassets.com/images/icons/emoji/unicode/1f4da.png"
|
||||
height="20"
|
||||
width="20"
|
||||
/>{" "}
|
||||
Freely available programming books
|
||||
</p>
|
||||
|
||||
<p className="view">
|
||||
<a href="https://github.com/EbookFoundation/free-programming-books" target="_blank" rel="noreferrer">
|
||||
View the Project on GitHub <small>EbookFoundation/free-programming-books</small>
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
Does a link not work?
|
||||
<br />
|
||||
<a href="https://github.com/EbookFoundation/free-programming-books/issues/" target="_blank" rel="noreferrer">
|
||||
Report an error on GitHub
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<div>
|
||||
<SearchBar changeParameter={changeParameter} />
|
||||
{/* Filters */}
|
||||
<LangFilters changeParameter={changeParameter} data={data} />
|
||||
{/* Keeping sections commented out just in case */}
|
||||
{/* <SectDropdown
|
||||
className="sect-drop"
|
||||
changeParameter={changeParameter}
|
||||
data={data}
|
||||
value={searchParams["section"] || "allSects"}
|
||||
/> */}
|
||||
{/* {sectionResultsList && <h3>Suggestions based on your search</h3>}
|
||||
<div className="search-results section-results">{sectionResultsList}</div> */}
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section className="search-results">
|
||||
{resultsList ? (
|
||||
<div>
|
||||
<br />
|
||||
<h2>Search Results</h2>
|
||||
<ul>{resultsList}</ul>
|
||||
</div>
|
||||
) : searchParams.searchTerm ? (
|
||||
<div>
|
||||
<br />
|
||||
<h2>No results found.</h2>
|
||||
</div>
|
||||
) : (
|
||||
<Default />
|
||||
)}
|
||||
</section>
|
||||
|
||||
<footer>
|
||||
<p>
|
||||
This project is maintained by{" "}
|
||||
<a href="https://github.com/EbookFoundation" target="_blank" rel="noreferrer">
|
||||
EbookFoundation
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
<small>
|
||||
Hosted on GitHub Pages — Theme by{" "}
|
||||
<a href="https://github.com/orderedlist" target="_blank" rel="noreferrer">
|
||||
orderedlist
|
||||
<BrowserRouter>
|
||||
<div className="wrapper">
|
||||
<ThemeContext.Consumer>
|
||||
{({ changeTheme }) => {
|
||||
let willBeDarkMode = cookies.lightMode && cookies.lightMode.toLowerCase() !== "true"; //whether or not we are currently light mode and will become dark mode
|
||||
changeTheme(willBeDarkMode ? themes.light : themes.dark);
|
||||
return (
|
||||
<img
|
||||
src={willBeDarkMode ? MoonImg : SunImg}
|
||||
onClick={() => {
|
||||
setCookie("lightMode", willBeDarkMode);
|
||||
changeTheme(willBeDarkMode ? themes.light : themes.dark);
|
||||
}}
|
||||
style={{ width: "20px", height: "20px", display: "block", marginLeft: "auto" }}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
</ThemeContext.Consumer>
|
||||
<header className="header">
|
||||
<h1>
|
||||
<a href="/free-programming-books-search/">
|
||||
free-programming-books
|
||||
</a>
|
||||
</small>
|
||||
</p>
|
||||
</footer>
|
||||
</div>
|
||||
</h1>
|
||||
|
||||
<p>
|
||||
<img
|
||||
className="emoji"
|
||||
title=":books:"
|
||||
alt=":books:"
|
||||
src="https://github.githubassets.com/images/icons/emoji/unicode/1f4da.png"
|
||||
height="20"
|
||||
width="20"
|
||||
/>{" "}
|
||||
Freely available programming books
|
||||
</p>
|
||||
|
||||
<p className="view">
|
||||
<a href="https://github.com/EbookFoundation/free-programming-books" target="_blank" rel="noreferrer">
|
||||
View the Project on GitHub <small>EbookFoundation/free-programming-books</small>
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
Does a link not work?
|
||||
<br />
|
||||
<a
|
||||
href="https://github.com/EbookFoundation/free-programming-books/issues/"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Report an error on GitHub
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<div>
|
||||
<SearchBar changeParameter={changeParameter} />
|
||||
<LangFilters changeParameter={changeParameter} data={data} langCode={searchParams["lang.code"]} />
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section className="search-results">
|
||||
{resultsList ? (
|
||||
<div>
|
||||
<br />
|
||||
<h2>Search Results</h2>
|
||||
<ul>{resultsList}</ul>
|
||||
</div>
|
||||
) : searchParams.searchTerm ? (
|
||||
<div>
|
||||
<br />
|
||||
<h2>No results found.</h2>
|
||||
</div>
|
||||
) : (
|
||||
<Routes>
|
||||
<Route path="/free-programming-books-search" element={<Default />} />
|
||||
<Route
|
||||
path="/free-programming-books-search/books/:lang"
|
||||
element={<BookList changeParameter={changeParameter} />}
|
||||
/>
|
||||
</Routes>
|
||||
)}
|
||||
</section>
|
||||
<footer>
|
||||
<p>
|
||||
This project is maintained by{" "}
|
||||
<a href="https://github.com/EbookFoundation" target="_blank" rel="noreferrer">
|
||||
EbookFoundation
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
<small>
|
||||
Hosted on GitHub Pages — Theme by{" "}
|
||||
<a href="https://github.com/orderedlist" target="_blank" rel="noreferrer">
|
||||
orderedlist
|
||||
</a>
|
||||
</small>
|
||||
</p>
|
||||
</footer>
|
||||
</div>
|
||||
</BrowserRouter>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
import React, { useEffect, useState } from "react";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import axios from "axios";
|
||||
import { useParams } from "react-router-dom";
|
||||
import rehypeSlug from 'rehype-slug'
|
||||
|
||||
function BookList({changeParameter}) {
|
||||
let [markdown, setMarkdown] = useState(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
let params = useParams();
|
||||
|
||||
useEffect(() => {
|
||||
changeParameter('lang.code', params.lang);
|
||||
}, [params.lang]);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
async function fetchData() {
|
||||
try {
|
||||
setLoading(true);
|
||||
let result = await axios.get(
|
||||
`https://raw.githubusercontent.com/EbookFoundation/free-programming-books/main/books/free-programming-books-${params.lang}.md`
|
||||
);
|
||||
setMarkdown(result.data);
|
||||
} catch (e) {
|
||||
console.log("Couldn't get data. Please try again later")
|
||||
}
|
||||
setLoading(false);
|
||||
}
|
||||
fetchData();
|
||||
}, []);
|
||||
if(loading){
|
||||
return <p>Loading...</p>
|
||||
}
|
||||
console.log(markdown);
|
||||
return <section><ReactMarkdown children={markdown} rehypePlugins={[rehypeSlug]} /></section>;
|
||||
}
|
||||
|
||||
export default BookList;
|
|
@ -69,6 +69,135 @@ function Default() {
|
|||
</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="resources">Resources</h2>
|
||||
|
||||
<p>This project lists books and other resources grouped by genres:</p>
|
||||
|
||||
<h3 id="books">Books</h3>
|
||||
|
||||
<p>
|
||||
<a href="/free-programming-books-search/books/langs/">English, By Programming Language</a>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="/free-programming-books-search/books/subjects/">English, By Subject</a>
|
||||
</p>
|
||||
<h4 id="other-languages">Other Languages</h4>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/ar/">Arabic / al arabiya / العربية</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/az/">Azerbaijani / Азәрбајҹан дили / آذربايجانجا ديلي</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/bn/">Bengali / বাংলা</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/bg/">Bulgarian / български</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/my/">Burmese / မြန်မာဘာသာ</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/zh/">Chinese / 中文</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/cs/">Czech / čeština / český jazyk</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/dk/">Danish / dansk</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/nl/">Dutch / Nederlands</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/et/">Estonian / eesti keel</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/fi/">Finnish / suomi / suomen kieli</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/fr/">French / français</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/de/">German / Deutsch</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/el/">Greek / ελληνικά</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/he/">Hebrew / עברית</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/hi/">Hindi / हिन्दी</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/hu/">Hungarian / magyar / magyar nyelv</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/id/">Indonesian / Bahasa Indonesia</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/it/">Italian / italiano</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/ja/">Japanese / 日本語</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/ko/">Korean / 한국어 [韓國語]</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/no/">Norwegian / Norsk</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/fa_IR/">Persian / Farsi (Iran) / فارسى</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/pl/">Polish / polski / język polski / polszczyzna</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/pt_BR/">Portuguese (Brazil)</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/pt_PT/">Portuguese (Portugal)</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/ro/">Romanian (Romania) / limba română / român</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/ru/">Russian / Русский язык</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/sr/">Serbian / српски језик / srpski jezik</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/sk/">Slovak / slovenčina</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/es/">Spanish / español / castellano</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/sv/">Swedish / Svenska</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/ta/">Tamil / தமிழ்</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/th/">Thai / ไทย</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/tr/">Turkish / Türkçe</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/uk/">Ukrainian / Українська</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/free-programming-books-search/books/vi/">Vietnamese / Tiếng Việt</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="translations">Translations</h2>
|
||||
|
||||
<p>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
|
||||
function LangFilters({ changeParameter, data }) {
|
||||
function LangFilters({ changeParameter, data, langCode }) {
|
||||
const [languages, setLanguages] = useState([]);
|
||||
const [selected, setSelected] = useState("");
|
||||
const [showFilters, setShow] = useState(false);
|
||||
|
@ -11,6 +11,10 @@ function LangFilters({ changeParameter, data }) {
|
|||
setSelected(e.target.value);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setSelected(langCode);
|
||||
}, [langCode]);
|
||||
|
||||
useEffect(
|
||||
// run whenever data changes
|
||||
() => {
|
||||
|
@ -60,7 +64,14 @@ function LangFilters({ changeParameter, data }) {
|
|||
let filterList = (
|
||||
<form className="filters">
|
||||
<label>
|
||||
<input type="radio" key="all" className="sect-select" value="" onChange={handleChange} checked={"" == selected} />
|
||||
<input
|
||||
type="radio"
|
||||
key="all"
|
||||
className="sect-select"
|
||||
value=""
|
||||
onChange={handleChange}
|
||||
checked={"" == selected}
|
||||
/>
|
||||
All Languages
|
||||
</label>
|
||||
{options}
|
||||
|
@ -71,7 +82,7 @@ function LangFilters({ changeParameter, data }) {
|
|||
<div className="langFilters">
|
||||
<div className="filterHeader">
|
||||
<h3>Filter by Language</h3>
|
||||
<button onClick={() => setShow(!showFilters)}>{showFilters? "-" : "+"}</button>
|
||||
<button onClick={() => setShow(!showFilters)}>{showFilters ? "-" : "+"}</button>
|
||||
</div>
|
||||
{showFilters ? filterList : ""}
|
||||
</div>
|
||||
|
|
21092
src/fpb.json
21092
src/fpb.json
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue