version/0.6 #4

Merged
lamacchinadesiderante merged 5 commits from version/0.5.1 into master 2023-01-16 20:19:10 +00:00
10 changed files with 109 additions and 22 deletions

View File

@ -18,7 +18,7 @@ Occorre clonare il repo e il file contenente gli indici dei libri:
``` ```
git clone https://git.lamacchinadesiderante.org/lamacchinadesiderante/millelibri && cd millelibri git clone https://git.lamacchinadesiderante.org/lamacchinadesiderante/millelibri && cd millelibri
wget https://github.com/zlib-searcher/index/releases/download/0.8.0/index_0.8.0.zip && unzip index_0.8.0.zip wget https://link.storjshare.io/juobea2obv6nadmij22tidrenlfa/millelibri%2Findex%2Frust%2Findex_0.6.zip?download=1 && unzip index_0.6.zip
docker-compose up -d docker-compose up -d
``` ```

View File

@ -2,9 +2,9 @@ version: '3'
services: services:
zlib: zlib:
# image: lamacchinadesiderante/millelibri:latest image: lamacchinadesiderante/millelibri:latest
image: millelibri:v0.4 # image: millelibri:v0.4
# image: millelibri # image: millelibri

View File

@ -1,2 +1,3 @@
# .env.production # .env.production
VITE_BACKEND_BASE_API = 'http://127.0.0.1:7070/' VITE_BACKEND_BASE_API = 'http://127.0.0.1:7070/'
VITE_STORJ_JSON_URL = 'https://link.storjshare.io/juowot6xaa2rz4vjqeal2uo44jka/millelibri%2Findex%2Fjson%2Fmillelibri.json?download=1'

View File

@ -1,2 +1,3 @@
# .env.production # .env.production
VITE_BACKEND_BASE_API = '' VITE_BACKEND_BASE_API = ''
VITE_STORJ_JSON_URL = ''

View File

@ -1,7 +1,7 @@
{ {
"name": "frontend", "name": "frontend",
"private": true, "private": true,
"version": "0.4.4", "version": "0.6",
"type": "module", "type": "module",
"repository": "https://git.lamacchinadesiderante.org/lamacchinadesiderante/millelibri", "repository": "https://git.lamacchinadesiderante.org/lamacchinadesiderante/millelibri",
"scripts": { "scripts": {

View File

@ -19,12 +19,12 @@ interface IProps {
const BookDetailsCard: React.FC<IProps> = (props) => { const BookDetailsCard: React.FC<IProps> = (props) => {
const downloadLinkFromIPFS = (gateway: string, book: Book) => { // const downloadLinkFromIPFS = (gateway: string, book: Book) => {
return ( // return (
`https://${gateway}/ipfs/${book.ipfs_cid}?filename=` + // `https://${gateway}/ipfs/${book.ipfs_cid}?filename=` +
encodeURIComponent(`${book.title}_${book.author}.${book.extension}`) // encodeURIComponent(`${book.title}_${book.author}.${book.extension}`)
); // );
} // }
const { t } = useTranslation(); const { t } = useTranslation();
@ -54,7 +54,7 @@ const BookDetailsCard: React.FC<IProps> = (props) => {
<Divider /> <Divider />
<CardBody> <CardBody>
<SimpleGrid columns={{ sm: 1, md: 3, lg: 4 }} spacing={{ base: 2, md: 4 }}> <SimpleGrid columns={{ sm: 1, md: 3, lg: 4 }} spacing={{ base: 2, md: 4 }}>
<Description name={`${t('book.id') ?? 'zlib/libgen id'}: `}>{id}</Description> {/* <Description name={`${t('book.id') ?? 'zlib/libgen id'}: `}>{id}</Description> */}
<GridItem colSpan={{ sm: 1, md: 2, lg: 3 }}> <GridItem colSpan={{ sm: 1, md: 2, lg: 3 }}>
<Description name={`${t('book.ipfs_cid') ?? 'IPFS CID'}: `}> <Description name={`${t('book.ipfs_cid') ?? 'IPFS CID'}: `}>
{ipfs_cid} {ipfs_cid}
@ -88,7 +88,7 @@ const BookDetailsCard: React.FC<IProps> = (props) => {
</CardBody> </CardBody>
<CardFooter flexDirection="column"> <CardFooter flexDirection="column">
<SimpleGrid columns={{ sm: 2, md: 3, lg: 4, xl: 5 }} spacing={{ base: 2, md: 4 }}> {/* <SimpleGrid columns={{ sm: 2, md: 3, lg: 4, xl: 5 }} spacing={{ base: 2, md: 4 }}>
{ipfsGateways.map((gateway) => ( {ipfsGateways.map((gateway) => (
<Button <Button
as={ExternalLink} as={ExternalLink}
@ -100,9 +100,9 @@ const BookDetailsCard: React.FC<IProps> = (props) => {
</Button> </Button>
))} ))}
</SimpleGrid> </SimpleGrid> */}
{/* <Flex><Text fontWeight={'bold'}>{t('disclaimer.nolink_warning')}</Text></Flex> */} <Flex><Text fontWeight={'bold'}>{t('disclaimer.nolink_warning')}</Text></Flex>
<Flex justify="flex-end"> <Flex justify="flex-end">
<Button <Button

View File

@ -19,6 +19,7 @@ import { useTranslation } from 'react-i18next';
import SearchLanguage from './SearchLanguage'; import SearchLanguage from './SearchLanguage';
import { MEDIA_QUERY_DESKTOP_STARTS, MEDIA_QUERY_MOBILE_ENDS } from '../constants/mediaquery'; import { MEDIA_QUERY_DESKTOP_STARTS, MEDIA_QUERY_MOBILE_ENDS } from '../constants/mediaquery';
import CopyToClipboardButton from './CopyToClipboardButton'; import CopyToClipboardButton from './CopyToClipboardButton';
import { getJsonArchive } from '../scripts/searcher-browser';
function constructQuery(parts: Record<string, string>): string { function constructQuery(parts: Record<string, string>): string {
return Object.keys(parts) return Object.keys(parts)
@ -48,6 +49,8 @@ const Search: React.FC<SearchProps> = ({ setBooks }) => {
const [complexQuery, setComplexQuery] = useState<string>(''); const [complexQuery, setComplexQuery] = useState<string>('');
const [showLanguageDropdown, setShowLanguageDropdown] = useState<boolean>(true) const [showLanguageDropdown, setShowLanguageDropdown] = useState<boolean>(true)
const [booksFromJsonArchive, setBooksFromJsonArchive] = useState<Book[]>([])
useEffect(() => { useEffect(() => {
const params = new Proxy(new URLSearchParams(decodeURIComponent(window.location.search)), { const params = new Proxy(new URLSearchParams(decodeURIComponent(window.location.search)), {
//@ts-ignore //@ts-ignore
@ -66,9 +69,15 @@ const Search: React.FC<SearchProps> = ({ setBooks }) => {
setLanguage(String(params.language)) setLanguage(String(params.language))
setShowLanguageDropdown(false) setShowLanguageDropdown(false)
} }
}, []) }, [])
useEffect(() => {
(async () => {
const jsonArchive = await getJsonArchive() as Book[]
setBooksFromJsonArchive(jsonArchive)
})();
}, []);
const handleLanguageChange = (language: string) => { const handleLanguageChange = (language: string) => {
if (language == 'input') { if (language == 'input') {
setShowLanguageDropdown(false) setShowLanguageDropdown(false)
@ -94,7 +103,7 @@ const Search: React.FC<SearchProps> = ({ setBooks }) => {
} }
const copyToClipboard = () => { const copyToClipboard = () => {
const searchBase = `${window.location.host}/?`; const searchBase = `${window.location.protocol}//${window.location.host}/?`;
const searchQuery = encodeURIComponent(`title=${title}&author=${author}&language=${language}&publisher=${publisher}&isbn=${isbn}&extension=${extension}`) const searchQuery = encodeURIComponent(`title=${title}&author=${author}&language=${language}&publisher=${publisher}&isbn=${isbn}&extension=${extension}`)
navigator.clipboard.writeText(`${searchBase}${searchQuery}`).then(() => { navigator.clipboard.writeText(`${searchBase}${searchQuery}`).then(() => {
@ -104,6 +113,46 @@ const Search: React.FC<SearchProps> = ({ setBooks }) => {
}); });
} }
const filterBooks = (books: Book[]) => {
if (!hasAnySearchBeenMade()) {
return []
}
return books.filter((x) => {
let matchTitle = true;
let matchAuthor = true;
let matchPublisher = true;
let matchExtension = true;
let matchLanguage = true;
if (title !== '') {
matchTitle = x.title.includes(title)
}
if (author !== '') {
matchAuthor = x.author.includes(author)
}
if (publisher !== '' && x.publisher) {
matchPublisher = x.publisher.includes(publisher)
}
if (extension !== '') {
matchExtension = x.extension.includes(extension)
}
if (language !== '') {
matchLanguage = x.language.includes(language)
}
return matchTitle && matchAuthor && matchPublisher && matchExtension && matchLanguage
})
}
useDebounceEffect( useDebounceEffect(
() => { () => {
const query = complexQuery const query = complexQuery
@ -111,7 +160,7 @@ const Search: React.FC<SearchProps> = ({ setBooks }) => {
: constructQuery({ title, author, publisher, extension, language, isbn }); : constructQuery({ title, author, publisher, extension, language, isbn });
search(query, 100).then((books) => { search(query, 100).then((books) => {
setBooks(books); setBooks(complexQuery ? books : books.concat(filterBooks(booksFromJsonArchive)));
}); });
}, },
[title, author, publisher, extension, language, isbn, complexQuery], [title, author, publisher, extension, language, isbn, complexQuery],

View File

@ -0,0 +1 @@
export const JSON_ARCHIVE_WINDOW_KEY = 'JSON_ARCHIVE'

View File

@ -63,7 +63,7 @@
"input": "Input..." "input": "Input..."
}, },
"disclaimer": { "disclaimer": {
"nolink_warning": "WARNING: This platform does not host any kind of link to copyrighted material. It just displays CID related to IPFS resources." "nolink_warning": "WARNING: This platform does not host any kind of link to copyrighted material."
} }
} }
}, },
@ -231,7 +231,7 @@
"input": "Scrivi..." "input": "Scrivi..."
}, },
"disclaimer": { "disclaimer": {
"nolink_warning": "IMPORTANTE: Questa piattaforma non ospita nessun tipo di link a materiale protetto da copyright. Vengono mostrati solamente CID relativi a risorse IPFS." "nolink_warning": "IMPORTANTE: Questa piattaforma non ospita nessun tipo di link a materiale protetto da copyright."
} }
} }
} }

View File

@ -1,11 +1,46 @@
import type { Book } from './searcher'; import type { Book } from './searcher';
import axios from 'axios'; import axios from 'axios';
import { JSON_ARCHIVE_WINDOW_KEY } from '../constants/system';
const http = axios.create({ const http = axios.create({
baseURL: import.meta.env.VITE_BACKEND_BASE_API, baseURL: import.meta.env.VITE_BACKEND_BASE_API,
timeout: 5000 timeout: 5000
}); });
const storj = axios.create({
baseURL: import.meta.env.VITE_STORJ_JSON_URL,
timeout: 5000
});
export const getJsonArchive = async () => {
//@ts-ignore
if (!window[JSON_ARCHIVE_WINDOW_KEY]) {
const response = await storj.get(``);
if (response.status == 200) {
//@ts-ignore
window[JSON_ARCHIVE_WINDOW_KEY] = response.data as Book[];
} else {
console.log(response);
//@ts-ignore
window[JSON_ARCHIVE_WINDOW_KEY] = [];
}
//@ts-ignore
return window[JSON_ARCHIVE_WINDOW_KEY] as Book[];
} else {
//@ts-ignore
return window[JSON_ARCHIVE_WINDOW_KEY] as Book[];
}
}
export default async function search(query: string, limit: number) { export default async function search(query: string, limit: number) {
const response = await http.get(`search?limit=${limit}&query=${query}`); const response = await http.get(`search?limit=${limit}&query=${query}`);
return response.data.books as Book[]; return response.data.books as Book[];