Skip to content

Commit

Permalink
Merge branch '1062-check-integration-with-unpaywall-org' into 'master'
Browse files Browse the repository at this point in the history
feat(ViewPaper): integrate unpaywall

Closes #1062

See merge request TIBHannover/orkg/orkg-frontend!903
  • Loading branch information
Reddine committed Aug 5, 2022
2 parents 856b4d6 + 1c293ef commit 428a046
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 12 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ The **environment variables** descriptions:
| REACT_APP_URL | ✅ Used | ✅ Used | The full URL of the frontend, including the path. E.g., `https://orkg.org/` |
| REACT_APP_OPEN_CITATIONS_URL | ✅ Used | ✅ Used | URL [OpenCitations](https://opencitations.net/) | |
| REACT_APP_WIKIDATA_URL | ✅ Used | ✅ Used | URL of the [Wikidata](https://www.wikidata.org/w/api.php) API |
| REACT_APP_UNPAYWALL_URL | ✅ Used | ✅ Used | URL of the [Unpaywall](https://unpaywall.org/products/api) API |
| REACT_APP_UNPAYWALL_EMAIL | ✅ Used | ✅ Used | Email used for authentication on the [Unpaywall](https://unpaywall.org/products/api) API |

_PLEASE MAKE SURE YOU USE HTTPS INSTEAD OF HTTP URLS._

Expand Down
2 changes: 2 additions & 0 deletions default.env
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ REACT_APP_GEONAMES_API_SEARCH_URL=https://secure.geonames.org/search
REACT_APP_GEONAMES_API_USERNAME=reddine
REACT_APP_OLS_BASE_URL=https://service.tib.eu/ts4tib/api/
REACT_APP_WIKIDATA_URL=https://www.wikidata.org/w/api.php
REACT_APP_UNPAYWALL_URL=https://api.unpaywall.org/v2/
REACT_APP_UNPAYWALL_EMAIL=[email protected]

# Is testing server: true or false
REACT_APP_IS_TESTING_SERVER=false
Expand Down
2 changes: 2 additions & 0 deletions src/components/ViewPaper/PaperHeaderBar/PaperHeaderBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ function PaperHeaderBar(props) {
editMode={props.editMode}
paperLink={props.paperLink}
toggle={props.toggle}
doi={props.doi}
/>
</ButtonGroup>
</Container>
Expand All @@ -68,6 +69,7 @@ PaperHeaderBar.propTypes = {
toggle: PropTypes.func.isRequired,
paperTitle: PropTypes.string.isRequired,
id: PropTypes.string,
doi: PropTypes.string,
};

export default PaperHeaderBar;
16 changes: 4 additions & 12 deletions src/components/ViewPaper/PaperHeaderBar/PaperMenuBar.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,22 @@
import { useState } from 'react';
import { Button, ButtonDropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap';
import { FontAwesomeIcon as Icon } from '@fortawesome/react-fontawesome';
import { faProjectDiagram, faPen, faTimes, faFile, faEllipsisV } from '@fortawesome/free-solid-svg-icons';
import { faProjectDiagram, faPen, faTimes, faEllipsisV } from '@fortawesome/free-solid-svg-icons';
import RequireAuthentication from 'components/RequireAuthentication/RequireAuthentication';
import PapersWithCodeModal from 'components/PapersWithCodeModal/PapersWithCodeModal';
import PropTypes from 'prop-types';
import { NavLink } from 'react-router-dom';
import ROUTES from 'constants/routes.js';
import { reverse } from 'named-urls';
import ViewPaperButton from 'components/ViewPaper/PaperHeaderBar/ViewPaperButton';

function PaperMenuBar(props) {
const [menuOpen, setMenuOpen] = useState(false);
const [isOpenPWCModal, setIsOpenPWCModal] = useState(false);

return (
<>
{props.paperLink && (
<a
href={props.paperLink}
className="btn btn-secondary flex-shrink-0 btn-sm"
style={{ marginRight: 2 }}
target="_blank"
rel="noopener noreferrer"
>
<Icon icon={faFile} style={{ margin: '2px 4px 0 0' }} /> View paper
</a>
)}
<ViewPaperButton paperLink={props.paperLink} doi={props.doi} title={props.label} />
<Button className="flex-shrink-0" color="secondary" size="sm" style={{ marginRight: 2 }} onClick={() => props.toggle('showGraphModal')}>
<Icon icon={faProjectDiagram} style={{ margin: '2px 4px 0 0' }} /> Graph view
</Button>
Expand Down Expand Up @@ -79,6 +70,7 @@ PaperMenuBar.propTypes = {
id: PropTypes.string,
label: PropTypes.string,
toggle: PropTypes.func.isRequired,
doi: PropTypes.string,
};

export default PaperMenuBar;
75 changes: 75 additions & 0 deletions src/components/ViewPaper/PaperHeaderBar/ViewPaperButton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { faSortDown } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon as Icon } from '@fortawesome/react-fontawesome';
import PropTypes from 'prop-types';
import { useEffect, useState } from 'react';
import ContentLoader from 'react-content-loader';
import { ButtonDropdown, DropdownItem, DropdownMenu, DropdownToggle } from 'reactstrap';
import { getLinksByDoi, getLinksByTitle } from 'services/unpaywall';

const ViewPaperButton = ({ paperLink = null, doi = null, title = null }) => {
const [links, setLinks] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const [isMenuOpen, setIsMenuOpen] = useState(false);
const [hasLoaded, setHasLoaded] = useState(false);

useEffect(() => {
const fetchLinks = async () => {
setIsLoading(true);
if (doi) {
setLinks(await getLinksByDoi(doi));
} else if (title) {
setLinks(await getLinksByTitle(title));
}
setIsLoading(false);
setHasLoaded(true);
};
if (isMenuOpen && !hasLoaded) {
fetchLinks();
}
}, [doi, hasLoaded, isMenuOpen, title]);

return (
<ButtonDropdown isOpen={isMenuOpen} toggle={() => setIsMenuOpen(v => !v)}>
<DropdownToggle style={{ marginRight: 2 }} size="sm" color="secondary" className="px-3 d-flex align-items-center">
View paper <Icon icon={faSortDown} style={{ margin: '-4px 0 0 6px' }} />
</DropdownToggle>
<DropdownMenu>
{paperLink && (
<DropdownItem tag="a" href={paperLink} target="_blank" rel="noopener noreferrer">
Visit paper
</DropdownItem>
)}
{isLoading && (
<DropdownItem disabled>
<ContentLoader height="80" width="200" viewBox="0 0 200 50" speed={2} backgroundColor="#f3f3f3" foregroundColor="#ecebeb">
<rect x="0" y="0" rx="0" ry="0" width="100%" height="20" />
<rect x="0" y="30" rx="0" ry="0" width="100%" height="20" />
</ContentLoader>
</DropdownItem>
)}
{!isLoading && links.length > 0 && (
<>
{paperLink && <DropdownItem divider />}
<DropdownItem tag="a" className="dropdown-header" href="https://unpaywall.org/" target="_blank" rel="noopener noreferrer">
Alternative sources by Unpaywall
</DropdownItem>
{links.map(link => (
<DropdownItem tag="a" href={link.url} target="_blank" rel="noopener noreferrer">
{link.name}
</DropdownItem>
))}
</>
)}
{!isLoading && links.length === 0 && !paperLink && <DropdownItem header>No links found</DropdownItem>}
</DropdownMenu>
</ButtonDropdown>
);
};

ViewPaperButton.propTypes = {
paperLink: PropTypes.string,
doi: PropTypes.string,
title: PropTypes.string,
};

export default ViewPaperButton;
2 changes: 2 additions & 0 deletions src/pages/ViewPaper.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ const ViewPaper = () => {
toggle={toggle}
id={resourceId}
paperTitle={viewPaper.paperResource.label}
doi={viewPaper.doi?.label}
/>
)}
<Breadcrumbs researchFieldId={viewPaper.researchField ? viewPaper.researchField.id : null} />
Expand All @@ -109,6 +110,7 @@ const ViewPaper = () => {
toggle={toggle}
id={resourceId}
label={viewPaper.paperResource?.label}
doi={viewPaper.doi?.label}
/>
}
>
Expand Down
31 changes: 31 additions & 0 deletions src/services/unpaywall/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import env from '@beam-australia/react-env';
import { upperFirst } from 'lodash';
import { submitGetRequest } from 'network';

export const unpaywallUrl = env('UNPAYWALL_URL');

const mapLocations = locations =>
locations?.map(location => ({
name: location.repository_institution || upperFirst(location.host_type),
url: location.url,
})) || [];

export const getLinksByDoi = async doi => {
try {
const result = await submitGetRequest(`${unpaywallUrl}${encodeURIComponent(doi)}?email=${env('UNPAYWALL_EMAIL')}`);
return mapLocations(result?.oa_locations);
} catch (e) {
console.log(e);
return [];
}
};

export const getLinksByTitle = async title => {
try {
const result = await submitGetRequest(`${unpaywallUrl}search?query=${encodeURIComponent(title)}&email=${env('UNPAYWALL_EMAIL')}`);
return mapLocations(result.results?.[0]?.response?.oa_locations);
} catch (e) {
console.log(e);
return [];
}
};

0 comments on commit 428a046

Please sign in to comment.