Merge pull request 'version/0.6' (#4) from version/0.5.1 into master
Reviewed-on: #4
This commit is contained in:
commit
6ad1ba26a3
|
@ -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
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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'
|
|
@ -1,2 +1,3 @@
|
||||||
# .env.production
|
# .env.production
|
||||||
VITE_BACKEND_BASE_API = ''
|
VITE_BACKEND_BASE_API = ''
|
||||||
|
VITE_STORJ_JSON_URL = ''
|
|
@ -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": {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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],
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
export const JSON_ARCHIVE_WINDOW_KEY = 'JSON_ARCHIVE'
|
|
@ -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."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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[];
|
||||||
|
|
Loading…
Reference in New Issue