Skip to content
Snippets Groups Projects
Commit 0c1c146e authored by Jure's avatar Jure
Browse files

feat: add a way to show a component without a menu

parent bf0d9efe
No related branches found
No related tags found
No related merge requests found
......@@ -14,6 +14,7 @@ import {
IntrospectionFragmentMatcher,
} from 'apollo-cache-inmemory'
import { createUploadLink } from 'apollo-upload-client'
import GlobalStyle from './theme/elements/GlobalStyle'
import introspectionQueryResultData from './fragmentTypes.json'
......@@ -98,7 +99,10 @@ const Root = ({
client={makeApolloClient(makeApolloConfig, connectToWebSocket)}
>
<BrowserRouter>
<ThemeProvider theme={theme}>{routes}</ThemeProvider>
<ThemeProvider theme={theme}>
<GlobalStyle />
{routes}
</ThemeProvider>
</BrowserRouter>
</ApolloProvider>
</div>
......
......@@ -2,11 +2,30 @@ import React, { useContext } from 'react'
import styled from 'styled-components'
import { compose } from 'recompose'
import { useQuery, useApolloClient } from '@apollo/react-hooks'
import { withRouter, matchPath, Router } from 'react-router-dom'
import {
withRouter,
matchPath,
Router,
Route,
Switch,
Redirect,
} from 'react-router-dom'
// import { Action } from '@pubsweet/ui'
import { JournalContext } from './xpub-journal/src'
import { XpubContext } from './xpub-with-context/src'
import GlobalStyle from '../theme/elements/GlobalStyle'
import UsersManager from '../components/component-users-manager'
import Manuscripts from '../components/component-manuscripts'
import Dashboard from '../components/component-dashboard/src/components/Dashboard'
import SubmitPage from '../components/component-submit/src/components/SubmitPage'
import ManuscriptPage from '../components/component-manuscript/src/components/ManuscriptPage'
import ReviewersPage from '../components/component-review/src/components/ReviewersPage'
import ReviewPage from '../components/component-review/src/components/ReviewPage'
import TeamPage from '../components/component-teams-manager/src/components/TeamsManagerPage'
import DecisionPage from '../components/component-review/src/components/DecisionPage'
import FormBuilderPage from '../components/component-formbuilder/src/components/FormBuilderPage'
import NewSubmissionPage from '../components/component-submit/src/components/NewSubmissionPage'
import { Profile } from '../components/component-profile/src'
import queries from '../graphql'
......@@ -34,7 +53,21 @@ const Root = styled.div`
`};
`
const MainPage = ({ children, history, match }) => {
// TODO: Redirect if token expires
const PrivateRoute = ({ component: Component, ...rest }) => (
<Route
{...rest}
render={props =>
localStorage.getItem('token') ? (
<Component {...props} />
) : (
<Redirect to="/login?next=/journal/dashboard" />
)
}
/>
)
const AdminPage = ({ children, history, match }) => {
const client = useApolloClient()
const journal = useContext(JournalContext)
......@@ -48,7 +81,7 @@ const MainPage = ({ children, history, match }) => {
let links = []
const formBuilderLink = `/journal/admin/form-builder`
const profileLink = `/journal/profile`
const homeLink = '/journal/home'
const homeLink = '/journal/dashboard'
if (showLinks) {
const params = getParams(pathname)
......@@ -65,7 +98,7 @@ const MainPage = ({ children, history, match }) => {
}
if (currentUser) {
links.push({ link: homeLink, name: 'Home', icon: 'home' })
links.push({ link: homeLink, name: 'Dashboard', icon: 'home' })
}
if (currentUser && currentUser.admin) {
......@@ -81,17 +114,62 @@ const MainPage = ({ children, history, match }) => {
return (
<Root converting={conversion.converting}>
<GlobalStyle />
<Menu
brand={journal.metadata.name}
brandLink="/journal/home"
loginLink="/login?next=/journal/home"
brandLink="/journal/dashboard"
loginLink="/login?next=/journal/dashboard"
navLinkComponents={links}
user={currentUser}
/>
<Router history={history}>{children}</Router>
<Switch>
<PrivateRoute component={Dashboard} exact path="/journal/dashboard" />
<PrivateRoute
component={NewSubmissionPage}
exact
path="/journal/newSubmission"
/>
<PrivateRoute
component={SubmitPage}
exact
path="/journal/versions/:version/submit"
/>
<PrivateRoute component={TeamPage} exact path="/journal/admin/teams" />
<PrivateRoute
component={FormBuilderPage}
exact
path="/journal/admin/form-builder"
/>
<PrivateRoute
component={ManuscriptPage}
exact
path="/journal/versions/:version/manuscript"
/>
<PrivateRoute
component={ReviewersPage}
exact
path="/journal/versions/:version/reviewers"
/>
<PrivateRoute
component={ReviewPage}
exact
path="/journal/versions/:version/reviews/:review"
/>
<PrivateRoute
component={DecisionPage}
exact
path="/journal/versions/:version/decisions/:decision"
/>
<PrivateRoute component={Profile} exact path="/journal/profile" />
<PrivateRoute component={UsersManager} path="/journal/admin/users" />
<PrivateRoute
component={Manuscripts}
path="/journal/admin/manuscripts"
/>
</Switch>
{/* <Router history={history}>{children}</Router> */}
</Root>
)
}
export default compose(withRouter)(MainPage)
export default compose(withRouter)(AdminPage)
import React from 'react'
import styled, { css } from 'styled-components'
import PropTypes from 'prop-types'
import { override, th, grid, darken } from '@pubsweet/ui-toolkit'
import { override, th, grid, darken, lighten } from '@pubsweet/ui-toolkit'
import { Icon, Action } from '@pubsweet/ui'
import { UserAvatar } from '../components/component-avatar/src'
import { Link } from 'react-router-dom'
import { Link, useHistory } from 'react-router-dom'
const Root = styled.nav`
grid-area: menu;
......@@ -14,8 +14,13 @@ const Root = styled.nav`
// align-items: center;
// justify-content: space-between;
border-right: 1px solid ${th('colorFurniture')};
// background: ${th('colorPrimary')};
// background: linear-gradient(45deg, #191654, #43C6AC);
background: linear-gradient(134deg, ${th('colorPrimary')}, ${lighten(
'colorPrimary',
0.3,
)});
max-height: 100vh;
// ${override('ui.AppBar')};
`
const Section = styled.div`
......@@ -52,47 +57,57 @@ const Item = styled(NavItem)`
display: flex;
align-items: center;
color: ${darken('colorSecondary', 0.5)};
color: ${th('colorTextReverse')};
&:hover {
color: ${th('colorText')};
stroke: ${th('colorText')};
background-color: ${th('colorBackgroundHue')};
background-color: ${lighten('colorPrimary', 0.5)};
svg {
stroke: ${th('colorText')};
}
}
svg {
&:hover {
}
width: 1em;
stroke: ${darken('colorSecondary', 0.5)};
stroke: ${th('colorTextReverse')};
}
${props =>
props.active &&
css`
background-color: ${th('colorFurniture')};
background-color: ${lighten('colorBackgroundHue', 0)};
color: ${th('colorText')};
&:hover {
background-color: ${th('colorFurniture')};
color: ${th('colorText')};
}
svg {
stroke: ${th('colorText')};
}
`}
// align-items: center;
// display: inline-flex;
// margin: calc(${th('gridUnit')} * 3) 1rem calc(${th('gridUnit')} * 3) 0;
`
const UserItem = styled.a`
const UserItem = styled(Link)`
// height: ${grid(5)};
line-height: ${grid(4)};
// line-height: ${grid(2)};
color: ${th('colorTextReverse')};
display: flex;
padding-bottom: ${grid(2)};
// margin-bottom: ${grid(2)};
// border-bottom: 1px solid ${th('colorFurniture')};
`
const UserInfo = styled.div`
margin-left: ${grid(1)};
`
const Menu = ({ className, loginLink = '/login', navLinkComponents, user }) => (
<Root className={className}>
<Section>
......@@ -113,11 +128,13 @@ const Menu = ({ className, loginLink = '/login', navLinkComponents, user }) => (
const UserComponent = ({ user, loginLink }) => (
<Section>
{user && (
<UserItem href="/journal/profile">
<UserAvatar user={user} />
{user.defaultIdentity.name || user.username}
{/* ({user.username}) */}
{user.admin ? ' (admin)' : ''}
<UserItem to="/journal/profile">
<UserAvatar user={user} size={64} />
<UserInfo>
{user.defaultIdentity.name || user.username}
{/* ({user.username}) */}
{user.admin ? ' (admin)' : ''}
</UserInfo>
</UserItem>
)}
{!user && <Item name="Login" link={loginLink} />}
......
......@@ -3,10 +3,10 @@ import { Redirect } from 'react-router-dom'
import PropTypes from 'prop-types'
import { withFormik } from 'formik'
import config from 'config'
import { th, grid } from '@pubsweet/ui-toolkit'
import { th, grid, lighten } from '@pubsweet/ui-toolkit'
import { CenteredColumn, H1, Button } from '@pubsweet/ui'
import styled from 'styled-components'
import { Container, Content, Section } from '../../shared'
import { Section } from '../../shared'
const getNextUrl = () => {
const url = new URL(window.location.href)
......@@ -48,22 +48,34 @@ const getToken = props => {
return null
}
const LoginLink = styled.a`
display: inline-block;
background: ${th('colorPrimary')};
border-radius: ${th('borderRadius')};
line-height: ${grid(4)};
color: ${th('colorTextReverse')};
padding: ${grid(1)} ${grid(2)};
margin-bottom: ${grid(1)};
const LoginButton = styled(Button)`
display: block;
margin-top: ${grid(3)};
width: 100%;
`
const CenteredSection = styled(Section)`
// TODO: Shared?
const Container = styled.div`
background: linear-gradient(134deg, ${th('colorPrimary')}, ${lighten('colorPrimary', 0.3)});
height: 100vh;
display: grid;
place-items: center;
`
const Content = styled.div`
border-radius: ${th('borderRadius')};
box-shadow: ${th('boxShadow')};
padding: ${grid(4)};
max-width: 30em;
background: ${th('colorBackground')};
text-align: center;
h1 {
margin-bottom: ${grid(2)};
}
`
const ORCIDIcon = ({className}) => (
<span className={className}>
<svg viewBox="0 0 256 256">
......@@ -91,7 +103,21 @@ const StyledORCIDIcon = styled(ORCIDIcon)`
height: 1rem;
}
`
const Login = ({ logo = null, redirectLink, orcid, token, ...props }) => {
const Login = ({ logo = null, ...props }) => {
// Is ORCID authentication enabled?
const orcid =
config['pubsweet-component-login'] &&
config['pubsweet-component-login'].orcid
const token = getToken(props)
// If a JWT token is supplied as a query param (e.g. from OAuth)
// go ahead and fetch the redirect URL
const initialRedirectLink = token ? getNextUrl() : null
const [redirectLink, setRedirectLink] = useState(initialRedirectLink)
// Also set the redirect link upon successful login (via handleSubmit)
const onLoggedIn = () => setRedirectLink(getNextUrl())
if (token) {
window.localStorage.setItem('token', token)
return <Redirect to={redirectLink} />
......@@ -101,58 +127,19 @@ const Login = ({ logo = null, redirectLink, orcid, token, ...props }) => {
<Redirect to={redirectLink} />
) : (
<Container>
<H1>Login to SimpleJ</H1>
<Content>
<CenteredSection>
<H1>Login to Kotahi</H1>
SimpleJ uses ORCID <StyledORCIDIcon /> to identify authors and staff. Login with your
Kotahi uses ORCID <StyledORCIDIcon /> to identify authors and staff. Login with your
ORCID account below or{' '}
<a href="https://orcid.org/signin">register at the ORCID website.</a>
<LoginLink href="/auth/orcid" primary>
<LoginButton onClick={() => window.location = "/auth/orcid"} primary>
Login with ORCID
</LoginLink>
</CenteredSection>
</LoginButton>
</Content>
</Container>
)
}
const EnhancedFormik = withFormik({
initialValues: {
username: '',
password: '',
},
mapPropsToValues: props => ({
username: props.username,
password: props.password,
}),
displayName: 'login',
handleSubmit,
})(Login)
export default props => {
// Is ORCID authentication enabled?
const orcid =
config['pubsweet-component-login'] &&
config['pubsweet-component-login'].orcid
const token = getToken(props)
// If a JWT token is supplied as a query param (e.g. from OAuth)
// go ahead and fetch the redirect URL
const initialRedirectLink = token ? getNextUrl() : null
const [redirectLink, setRedirectLink] = useState(initialRedirectLink)
// Also set the redirect link upon successful login (via handleSubmit)
const onLoggedIn = () => setRedirectLink(getNextUrl())
return (
<EnhancedFormik
onLoggedIn={onLoggedIn}
orcid={orcid}
redirectLink={redirectLink}
token={token}
{...props}
/>
)
}
export default Login
\ No newline at end of file
......@@ -2,88 +2,27 @@ import React from 'react'
import { Route, Switch, Redirect } from 'react-router-dom'
import Login from './components/component-login'
import UsersManager from './components/component-users-manager'
import Manuscripts from './components/component-manuscripts'
import Dashboard from './components/component-dashboard/src/components/Dashboard'
import SubmitPage from './components/component-submit/src/components/SubmitPage'
import ManuscriptPage from './components/component-manuscript/src/components/ManuscriptPage'
import ReviewersPage from './components/component-review/src/components/ReviewersPage'
import ReviewPage from './components/component-review/src/components/ReviewPage'
import TeamPage from './components/component-teams-manager/src/components/TeamsManagerPage'
import DecisionPage from './components/component-review/src/components/DecisionPage'
import FormBuilderPage from './components/component-formbuilder/src/components/FormBuilderPage'
import NewSubmissionPage from './components/component-submit/src/components/NewSubmissionPage'
import { Profile } from './components/component-profile/src'
import MainPage from './components/MainPage'
import AdminPage from './components/AdminPage'
// const createReturnUrl = ({ pathname, search = '' }) => pathname + search
// const loginUrl = location => `/login?next=${createReturnUrl(location)}`
// TODO: Redirect if token expires
const PrivateRoute = ({ component: Component, ...rest }) => (
<Route
{...rest}
render={props =>
localStorage.getItem('token') ? (
<Component {...props} />
) : (
<Redirect to="/login?next=/dashboard" />
)
}
/>
)
// const adminWrap = Component => props => (
// <AdminPage {...props}>
// <Component {...props} />
// </AdminPage>
// )
// TODO: use componentDidMount to fetch the current user before rendering?
export default (
<MainPage>
<Switch>
<PrivateRoute component={Dashboard} exact path="/journal/home" />
<PrivateRoute
component={NewSubmissionPage}
exact
path="/journal/newSubmission"
/>
<PrivateRoute
component={SubmitPage}
exact
path="/journal/versions/:version/submit"
/>
<PrivateRoute component={TeamPage} exact path="/journal/admin/teams" />
<PrivateRoute
component={FormBuilderPage}
exact
path="/journal/admin/form-builder"
/>
<PrivateRoute
component={ManuscriptPage}
exact
path="/journal/versions/:version/manuscript"
/>
<PrivateRoute
component={ReviewersPage}
exact
path="/journal/versions/:version/reviewers"
/>
<PrivateRoute
component={ReviewPage}
exact
path="/journal/versions/:version/reviews/:review"
/>
<PrivateRoute
component={DecisionPage}
exact
path="/journal/versions/:version/decisions/:decision"
/>
<PrivateRoute
path="/journal/profile"
component={Profile}
exact
path="/journal/profile"
/>
{/* <PrivateRoute
<Switch>
{/* AdminPage has nested routes within */}
<Route path="/journal">
<AdminPage />
</Route>
{/* <PrivateRoute
component={FindReviewersPage}
exact
path="/journals/:journal/versions/:version/find-reviewers"
......@@ -99,12 +38,6 @@ export default (
path="/journals/:journal/versions/:version/find-reviewers/paper/:id"
/> */}
<Route component={Login} path="/login" />
<PrivateRoute component={UsersManager} path="/journal/admin/users" />
<PrivateRoute component={Manuscripts} path="/journal/admin/manuscripts" />
{/* <PrivateRoute component={Dashboard} path="*" /> */}
</Switch>
{/* <Redirect from="/" to="/dashboard"/> */}
</MainPage>
<Route component={Login} path="/login" />
</Switch>
)
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment