diff --git a/src/components/app.js b/src/components/app.js index 3ef86e2..ea6e34a 100644 --- a/src/components/app.js +++ b/src/components/app.js @@ -58,7 +58,7 @@ export default function App({ user }) { - + diff --git a/src/components/banner.js b/src/components/banner.js index 0f8f94a..01cd5d6 100644 --- a/src/components/banner.js +++ b/src/components/banner.js @@ -7,8 +7,8 @@ export default function Banner() { return (
-

Click here to find preprints on COVID-19 with reviews or requests for reviews.

-

Click here to read OASPA's open letter of intent to ensure rapid review of key work related to COVID-19.

+

Get involved with rapidly reviewing COVID-19 preprints and then view our COVID-19 Dashboard of review activities and recommendations.

+

Read about the OASPA’s initiative to ensure rapid review of key COVID-19 work.

) diff --git a/src/components/dashboard.js b/src/components/dashboard.js index 5ee97b3..990d5ff 100644 --- a/src/components/dashboard.js +++ b/src/components/dashboard.js @@ -11,12 +11,13 @@ import Org from './org'; // hooks import { usePreprintSearchResults } from '../hooks/api-hooks'; +import { useNewPreprints } from '../hooks/ui-hooks'; // utils import { checkIfIsModerated } from '../utils/actions'; import { getUsersRank, isYes } from '../utils/stats'; import { createPreprintQs, apifyPreprintQs } from '../utils/search'; -import { getId } from '../utils/jsonld' +import { getId, unprefix } from '../utils/jsonld' // contexts @@ -27,6 +28,7 @@ import AddButton from './add-button'; import Banner from "./banner.js"; import Button from './button'; +import LoginRequiredModal from './login-required-modal'; import Checkbox from './checkbox'; import SortOptions from './sort-options'; import HeaderBar from './header-bar'; @@ -35,6 +37,9 @@ import SearchBar from './search-bar'; import XLink from './xlink'; import RecentActivity from './recent-activity' import ActiveUser from './active-user' +import PrivateRoute from './private-route'; +import NewPreprint from './new-preprint'; +import Modal from './modal'; export default function Dashboard() { @@ -43,6 +48,7 @@ export default function Dashboard() { const [user] = useUser(); const [loginModalOpenNext, setLoginModalOpenNext] = useState(null); + const [newPreprints, setNewPreprints] = useNewPreprints(); const apiQs = apifyPreprintQs( location.search, @@ -54,7 +60,7 @@ export default function Dashboard() { useEffect(() => { if (!params.get('q')) { - history.replace({ search: createPreprintQs({ text: covidTerms }, location.search) }); + history.replace({ search: createPreprintQs({ text: covidTerms }, location.search), state: location.state }); } }, [apiQs]); @@ -111,15 +117,21 @@ export default function Dashboard() { const handleNewRequest = useCallback( preprint => { if (user) { - history.push('/new', { - preprint: omit(preprint, ['potentialAction']), - tab: 'request', - isSingleStep: true + history.push({ + pathname: '/dashboard/new', + search: history.location.search, + state: { + preprint: omit(preprint, ['potentialAction']), + tab: 'request', + isSingleStep: true + } }); } else { - setLoginModalOpenNext( - `/new?identifier=${preprint.doi || preprint.arXivId}&tab=request` - ); + const search = new URLSearchParams(location.search); + search.set('identifier', preprint.doi || preprint.arXivId); + search.set('tab', 'request'); + + setLoginModalOpenNext(`/dashboard/new?${search}`); } }, [user, history] @@ -128,13 +140,18 @@ export default function Dashboard() { const handleNew = useCallback( preprint => { if (user) { - history.push('/new', { - preprint: omit(preprint, ['potentialAction']) + history.push({ + pathname: '/dashboard/new', + search: history.location.search, + state: { + preprint: omit(preprint, ['potentialAction']) + } }); } else { - setLoginModalOpenNext( - `/new?identifier=${preprint.doi || preprint.arXivId}` - ); + const search = new URLSearchParams(location.search); + search.set('identifier', preprint.doi || preprint.arXivId); + + setLoginModalOpenNext(`/dashboard/new?${search}`); } }, [user, history] @@ -143,15 +160,21 @@ export default function Dashboard() { const handleNewReview = useCallback( preprint => { if (user) { - history.push('/new', { - preprint: omit(preprint, ['potentialAction']), - tab: 'review', - isSingleStep: true + history.push({ + pathname: '/dashboard/new', + search: history.location.search, + state: { + preprint: omit(preprint, ['potentialAction']), + tab: 'review', + isSingleStep: true + } }); } else { - setLoginModalOpenNext( - `/new?identifier=${preprint.doi || preprint.arXivId}&tab=review` - ); + const search = new URLSearchParams(location.search); + search.set('identifier', preprint.doi || preprint.arXivId); + search.set('tab', 'review'); + + setLoginModalOpenNext(`/dashboard/new?${search}`); } }, [user, history] @@ -168,6 +191,53 @@ export default function Dashboard() { setShowLeftPanel(!showLeftPanel); }} /> + {loginModalOpenNext && ( + { + setLoginModalOpenNext(null); + }} + /> + )} + + { + history.push({ pathname: '/dashboard', search: location.search }); + }} + > + + Rapid PREreview • Add entry + + { + history.push({ pathname: '/dashboard', search: location.search }); + }} + onSuccess={(preprint, isNew) => { + history.push({ pathname: '/dashboard', search: location.search }); + if ( + isNew && + !newPreprints.some( + _preprint => getId(_preprint) === getId(preprint) + ) + ) { + setNewPreprints(newPreprints.concat(preprint)); + } + }} + onViewInContext={({ preprint, tab }, isNew) => { + history.push( + `/${unprefix(preprint.doi || preprint.arXivId)}`, + { + preprint: omit(preprint, ['potentialAction']), + tab + } + ); + }} + /> + +
@@ -324,6 +394,23 @@ export default function Dashboard() {
No more preprints.
) : (
    + {newPreprints.length > 0 && ( + newPreprints.map(preprint => ( +
  • + +
  • + )) + )} {preprints.rows.length ? preprints.rows.map(row => (
  • { if (user) { - history.push('/new'); + history.push({ pathname: '/dashboard/new', search: location.search }); } else { - setLoginModalOpenNext('/new'); + setLoginModalOpenNext(`/dashboard/new?${location.search}`); } }} - disabled={location.pathname === '/new'} + disabled={location.pathname === '/dashboard/new'} />
diff --git a/src/components/extension-fallback.js b/src/components/extension-fallback.js index 5023fee..e4c3409 100644 --- a/src/components/extension-fallback.js +++ b/src/components/extension-fallback.js @@ -66,6 +66,7 @@ export default function ExtensionFallback() { Loading PDF}> Loading PDF} /> @@ -80,6 +81,7 @@ export default function ExtensionFallback() { Loading PDF}> Loading PDF} /> diff --git a/src/components/header-bar.css b/src/components/header-bar.css index 40a9a3e..b8bd9da 100644 --- a/src/components/header-bar.css +++ b/src/components/header-bar.css @@ -28,36 +28,6 @@ } } - & .header-bar__give-feedback { - position: fixed; - font: var(--ui-basic-font); - line-height: 1.25em; - background-color: var(--prereview-red); - color: white; - text-shadow: 0px 0px 10px #eb0000; /* improve contrast for accessability */ - right: 0px; - bottom: var(--xlgrd); - width: 56px; - padding: var(--xsgrd); - padding-right: var(--mgrd); - border-top-left-radius: var(--xsgrd); - border-bottom-left-radius: var(--xsgrd); - box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.2); - @media (--narrow-screen) { - bottom: calc(var(--xlgrd) + 50px); - } - @media (--mobile) { - bottom: var(--xlgrd); - } - & :any-link { - color: white; - text-decoration: none; - &:hover { - text-decoration: underline; - } - } - } - /* the hamburder is only visible on narrow screens */ & .header-bar__menu-button { display: none; diff --git a/src/components/header-bar.js b/src/components/header-bar.js index 391b323..8c96152 100644 --- a/src/components/header-bar.js +++ b/src/components/header-bar.js @@ -176,16 +176,6 @@ export default function HeaderBar({ onClickMenuButton, closeGap }) { )}
- {/* TODO link to feedback form */} -
- - Give Feedback - -
); } diff --git a/src/components/new-preprint.js b/src/components/new-preprint.js index 0ab7e4d..217d87e 100644 --- a/src/components/new-preprint.js +++ b/src/components/new-preprint.js @@ -214,7 +214,8 @@ function StepPreprint({ if (location.search) { const qs = new URLSearchParams(location.search); if (qs.get('identifier')) { - history.replace('/new'); + qs.delete('identifier'); + history.replace({ pathname: location.pathname, search: qs.toString() }); } } diff --git a/src/components/pdf-viewer.js b/src/components/pdf-viewer.js index 77b3ac4..37d1a5a 100644 --- a/src/components/pdf-viewer.js +++ b/src/components/pdf-viewer.js @@ -11,7 +11,7 @@ const CSS_MAX_WIDTH = 900; // keep in sync with CSS * This implement an infinite scroll mechanism so that we never load more than a * few pages at the time */ -export default function PdfViewer({ docId, loading }) { +export default function PdfViewer({ docId, pdfUrl, loading }) { const containerEl = useRef(null); const getWidth = () => { const el = containerEl.current; @@ -79,7 +79,7 @@ export default function PdfViewer({ docId, loading }) { { let dims = []; diff --git a/src/components/preprint-card.js b/src/components/preprint-card.js index ca0f0b7..703b241 100644 --- a/src/components/preprint-card.js +++ b/src/components/preprint-card.js @@ -39,7 +39,8 @@ export default function PreprintCard({ onNew, sortOption, hoveredSortOption, - isNew = false + isNew = false, + isDashboardCard = false, }) { const [isOpened, setIsOpened] = useState(false); @@ -93,7 +94,7 @@ export default function PreprintCard({ return (
diff --git a/src/routes/api-routes.js b/src/routes/api-routes.js index f308e76..ed0a772 100644 --- a/src/routes/api-routes.js +++ b/src/routes/api-routes.js @@ -375,16 +375,21 @@ router.get( * due to cross origin restriction we need to proxy the PDF */ router.get('/pdf', async (req, res, next) => { - let pdfUrl; - const preprintId = req.query.preprintId; - try { - const body = await req.db.get(`preprint:${preprintId}`); - pdfUrl = getPdfUrl(body); - if (!pdfUrl) { - return next(createError(500, `Could not determine PDF from prereview: ${JSON.stringify(body)}`)); + let { preprintId, pdfUrl } = req.query; + + // If we already have the pdfUrl, there's no need to look in the database. + // The pdfUrl is present in the case where the preprint is not in the database yet, + // but we were able to resolve it. + if (!pdfUrl) { + try { + const body = await req.db.get(`preprint:${preprintId}`); + pdfUrl = getPdfUrl(body); + if (!pdfUrl) { + return next(createError(500, `Could not determine PDF from prereview: ${JSON.stringify(body)}`)); + } + } catch (err) { + return next(createError(500, `Prereview query failed: ${preprintId} ${JSON.stringify(err)}`)); } - } catch (err) { - return next(createError(500, `Prereview query failed: ${preprintId} ${JSON.stringify(err)}`)); } if (!pdfUrl) {