From bb5c9b33b5db3c45e26a040562363380c3f02fbd Mon Sep 17 00:00:00 2001 From: Alexandru Munteanu <alexandru.munteanu@thinslices.com> Date: Wed, 21 Feb 2018 14:08:00 +0200 Subject: [PATCH] update dashboard --- .../src/components/Dashboard/Dashboard.js | 5 - .../src/components/Dashboard/DashboardCard.js | 403 ++++++++++++++---- .../components/Dashboard/DashboardFilters.js | 9 +- .../src/components/Dashboard/DashboardPage.js | 6 +- .../src/components/Dashboard/utils.js | 9 +- packages/xpub-faraday/config/default.js | 2 +- 6 files changed, 323 insertions(+), 111 deletions(-) diff --git a/packages/components-faraday/src/components/Dashboard/Dashboard.js b/packages/components-faraday/src/components/Dashboard/Dashboard.js index fbf0cdcb4..6fb0797f1 100644 --- a/packages/components-faraday/src/components/Dashboard/Dashboard.js +++ b/packages/components-faraday/src/components/Dashboard/Dashboard.js @@ -10,12 +10,10 @@ import DashboardItems from './DashboardItems' import DashboardFilters from './DashboardFilters' const Dashboard = ({ - changeViewMode, createDraftSubmission, currentUser, dashboard, deleteProject, - listView, filters, getItems, getFilterOptions, @@ -36,14 +34,11 @@ const Dashboard = ({ </div> <DashboardFilters changeFilterValue={changeFilterValue} - changeView={changeViewMode} getFilterOptions={getFilterOptions} - listView={listView} /> <DashboardItems deleteProject={deleteProject} list={getItems()} - listView={listView} showAbstractModal={showAbstractModal} /> </div> diff --git a/packages/components-faraday/src/components/Dashboard/DashboardCard.js b/packages/components-faraday/src/components/Dashboard/DashboardCard.js index 085967228..97b4952b4 100644 --- a/packages/components-faraday/src/components/Dashboard/DashboardCard.js +++ b/packages/components-faraday/src/components/Dashboard/DashboardCard.js @@ -1,23 +1,18 @@ import React from 'react' -import classnames from 'classnames' import { get, isEmpty } from 'lodash' import styled from 'styled-components' import { Button, Icon } from '@pubsweet/ui' import { parseVersion, getFilesURL, downloadAll } from './utils' -import classes from './Dashboard.local.scss' const DashboardCard = ({ deleteProject, history, - listView, project, version, showAbstractModal, }) => { - const { submitted, author, title, type, version: vers } = parseVersion( - version, - ) + const { submitted, title, type, version: vers } = parseVersion(version) const files = getFilesURL(get(version, 'files')) const status = get(project, 'status') || 'Draft' const hasFiles = !isEmpty(files) @@ -25,96 +20,323 @@ const DashboardCard = ({ const metadata = get(version, 'metadata') return ( - <div className={classes.card}> - <div className={classes.leftSide}> - <div - className={classes.title} - dangerouslySetInnerHTML={{ __html: title }} // eslint-disable-line - /> - - <div className={classes.quickInfo}> - <div className={classes.status}>{status}</div> - <div className={classes.version}>{`v${vers} ${ - submitted ? `- updated on ${submitted}` : '' - }`}</div> - </div> - </div> - <div className={classes.rightSide}> - <div - className={classnames({ - [classes.disabled]: !hasFiles, - [classes.pointer]: true, - })} - onClick={() => (hasFiles ? downloadAll(files) : null)} - > - <Icon>download</Icon> - </div> - <div className={classes.pointer} onClick={() => deleteProject(project)}> - <Icon>trash-2</Icon> - </div> - <div - className={classes.pointer} - onClick={() => - history.push( - `/projects/${project.id}/versions/${version.id}/submit`, - ) - } - > - <Icon>file-text</Icon> - </div> - </div> - {!listView && ( - <div className={classes.expandedView}> - <div className={classes.column3}> - <div className={classes.column2}> - <div>Submission author</div> - <div>Abstract</div> - </div> - <div className={classes.column2}> - <div>{author}</div> - {abstract && ( - <ViewAbstractContainer onClick={showAbstractModal(metadata)}> - <Icon color="#667080" size={18}> - eye - </Icon> - <span>View</span> - </ViewAbstractContainer> - )} - </div> - </div> - <div className={classes.column3}> - <div className={classes.column2}> - <div>Submitted On</div> - <div>Type</div> + <Card> + <ListView> + <Left> + <Title + dangerouslySetInnerHTML={{ __html: title }} // eslint-disable-line + /> + <ManuscriptInfo> + <div> + <Status>{status}</Status> + <DateField>{submitted || ''}</DateField> </div> - <div className={classes.column2}> - <div>{submitted}</div> - <div> - <span className={classes.status}>{type}</span> - </div> + <div> + <Version>{`v${vers} - `}</Version> + <ManuscriptId>{`ID ${version.id.split('-')[0]}`}</ManuscriptId> + <ManuscriptType>{type}</ManuscriptType> </div> + </ManuscriptInfo> + </Left> + <Right> + <ClickableIcon + disabled={!hasFiles} + onClick={() => (hasFiles ? downloadAll(files) : null)} + > + <Icon>download</Icon> + </ClickableIcon> + <ClickableIcon onClick={() => deleteProject(project)}> + <Icon>trash-2</Icon> + </ClickableIcon> + <ClickableIcon> + <Icon>more-horizontal</Icon> + </ClickableIcon> + <Details + onClick={() => + history.push( + `/projects/${project.id}/versions/${version.id}/submit`, + ) + } + > + Details + <Icon color="#667080">chevron-right</Icon> + </Details> + </Right> + </ListView> + <DetailsView> + <LeftDetails> + <JournalTitle>{metadata.journal}</JournalTitle> + <Issue>{metadata.issue}</Issue> + {get(version, 'authors') && ( + <Authors> + <span>Authors:</span> + <AuthorList> + {version.authors + .map(({ firstName, lastName }) => `${firstName} ${lastName}`) + .join(', ')} + </AuthorList> + </Authors> + )} + <PreviewContainer> + {abstract && ( + <ClickableIconContainer onClick={showAbstractModal(metadata)}> + <Icon color="#667080" size={18}> + eye + </Icon> + <span>Abstract</span> + </ClickableIconContainer> + )} + <ClickableIconContainer> + <Icon color="#667080" size={18}> + eye + </Icon> + <span>Cover letter</span> + </ClickableIconContainer> + </PreviewContainer> + </LeftDetails> + <RightDetails> + <div> + <Label>Handling editor</Label> + <ActionButtons>ASSIGN</ActionButtons> </div> - <div className={classes.column3}> - <div className={classes.column2}> - <div>Handling Editor</div> - <div>Reviewers</div> - </div> - <div className={classes.column2}> - <Button className={classes.button} primary> - Invite - </Button> - <Button className={classes.button} primary> - Invite - </Button> - </div> + <div> + <Label>Reviewers</Label> + <ActionButtons>INVITE</ActionButtons> </div> - </div> - )} - </div> + </RightDetails> + </DetailsView> + </Card> ) } -const ViewAbstractContainer = styled.div` +export default DashboardCard + +// #region styled-components +const PreviewContainer = styled.div` + display: flex; + margin-top: 18px; +` + +const AuthorList = styled.span` + color: #667080; + font-family: Helvetica; + font-size: 14px; + overflow: hidden; + text-overflow: ellipsis; + text-align: left; + white-space: nowrap; + max-width: 400px; + width: 400px; +` + +const Authors = styled.div` + align-items: center; + display: flex; + flex-direction: row; + justify-content: flex-start; + margin-top: 15px; + + span:first-child { + color: #667080; + font-family: Helvetica; + font-size: 12px; + margin-right: 8px; + text-align: left; + text-transform: uppercase; + } +` + +const ActionButtons = styled(Button)` + align-items: center; + background-color: #667080; + display: flex; + height: 20px; + padding: 4px 8px; + font-family: Helvetica; + font-size: 12px; + text-align: center; + color: #ffffff; +` + +const LeftDetails = styled.div` + display: flex; + flex: 1; + flex-direction: column; + justify-content: flex-start; + padding: 10px 20px; +` + +const RightDetails = styled.div` + display: flex; + flex: 1; + flex-direction: column; + + div { + align-items: center; + display: flex; + flex-direction: row; + margin: 6px 0; + } +` + +const Label = styled.span` + color: #667080; + font-family: Helvetica; + font-size: 12px; + text-align: left; + text-transform: uppercase; + width: 150px; +` + +const JournalTitle = styled.span` + color: #667080; + font-family: Helvetica; + font-size: 14px; + font-weight: bold; + text-align: left; +` + +const Issue = styled.span` + color: #667080; + font-family: Helvetica; + font-size: 14px; + text-align: left; +` + +const DetailsView = styled.div` + align-items: center; + border-top: 1px solid #667080; + display: flex; + flex-direction: row; + justify-content: space-between; + width: 100%; +` + +const ListView = styled.div` + align-items: center; + display: flex; + flex-direction: row; + justify-content: space-between; + width: 100%; +` + +const ManuscriptId = styled.span` + color: #667080; + font-family: Helvetica; + font-size: 12px; + margin-left: 8px; + text-align: left; + text-decoration: underline; + text-transform: uppercase; +` + +const Version = styled.span` + color: #667080; + font-family: Helvetica; + font-size: 13px; + text-align: left; +` +const Details = styled.div` + align-items: center; + color: #667080; + cursor: pointer; + display: flex; + font-family: Helvetica; + font-size: 14px; + margin-left: 8px; + text-decoration: underline; + text-align: center; +` + +const ClickableIcon = styled.div` + cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')}; + margin: 0 7px; + + svg { + stroke: ${({ disabled }) => (disabled ? '#eee' : '#667080')}; + } +` + +const Card = styled.div` + align-items: center; + border: 1px solid #667080; + display: flex; + flex-direction: column; + justify-content: flex-start; + margin-bottom: 10px; +` + +const Right = styled.div` + align-items: center; + flex: 1; + display: flex; + flex-direction: row; + justify-content: space-between; + margin: 0 15px; +` + +const Left = styled.div` + border-right: 1px solid #667080; + display: flex; + flex-direction: column; + flex: 5; + margin: 10px 0; + padding: 0 10px; +` + +const ManuscriptInfo = styled.div` + align-items: center; + display: flex; + justify-content: space-between; + + div { + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + } +` + +const ManuscriptType = styled.div` + border: 1px solid #667080; + color: #667080; + font-family: Helvetica; + font-size: 12px; + font-weight: bold; + padding: 6px 4px; + margin-left: 10px; + text-align: left; + text-transform: uppercase; +` + +const Title = styled.span` + color: #667080; + font-family: Helvetica; + font-size: 18px; + text-align: left; +` + +const Status = styled.div` + border: 1px solid #667080; + color: #667080; + font-family: Helvetica; + font-size: 12px; + font-weight: bold; + text-align: left; + margin: 0.5em 0; + padding: 0.2em 0.5em; + text-transform: uppercase; +` + +const DateField = styled.span` + color: #667080; + font-family: Helvetica; + font-size: 13px; + margin: 0 8px; + text-align: left; +` + +const ClickableIconContainer = styled.div` align-items: center; cursor: pointer; display: flex; @@ -128,5 +350,4 @@ const ViewAbstractContainer = styled.div` text-decoration: underline; } ` - -export default DashboardCard +// #endregion diff --git a/packages/components-faraday/src/components/Dashboard/DashboardFilters.js b/packages/components-faraday/src/components/Dashboard/DashboardFilters.js index 3a2ae7400..b7ca2b2af 100644 --- a/packages/components-faraday/src/components/Dashboard/DashboardFilters.js +++ b/packages/components-faraday/src/components/Dashboard/DashboardFilters.js @@ -1,5 +1,5 @@ import React from 'react' -import { Icon, Menu } from '@pubsweet/ui' +import { Menu } from '@pubsweet/ui' import { compose, withHandlers } from 'recompose' import classes from './Dashboard.local.scss' @@ -13,7 +13,6 @@ const DashboardFilters = ({ view, status, createdAt, - changeView, listView, changeFilter, changeSort, @@ -42,12 +41,6 @@ const DashboardFilters = ({ <Menu onChange={changeSort} options={sortOptions} /> </div> </div> - <div className={classes.viewMode} onClick={changeView}> - <div className={classes.icon}> - {listView ? <Icon>list</Icon> : <Icon>credit-card</Icon>} - </div> - {listView ? ' List' : ' Card'} View - </div> </div> ) diff --git a/packages/components-faraday/src/components/Dashboard/DashboardPage.js b/packages/components-faraday/src/components/Dashboard/DashboardPage.js index 4154a7b1b..a1a4176b6 100644 --- a/packages/components-faraday/src/components/Dashboard/DashboardPage.js +++ b/packages/components-faraday/src/components/Dashboard/DashboardPage.js @@ -1,9 +1,9 @@ import { get } from 'lodash' +import { compose } from 'recompose' import { connect } from 'react-redux' import { actions } from 'pubsweet-client' import { ConnectPage } from 'xpub-connect' import { withRouter } from 'react-router-dom' -import { compose, withState, withHandlers } from 'recompose' import { newestFirst, selectCurrentUser } from 'xpub-selectors' import { createDraftSubmission } from 'pubsweet-component-wizard/src/redux/conversion' @@ -17,10 +17,6 @@ export default compose( actions.getTeams(), actions.getUsers(), ]), - withState('listView', 'changeView', true), - withHandlers({ - changeViewMode: ({ changeView }) => () => changeView(listView => !listView), - }), connect( state => { const { collections, conversion } = state diff --git a/packages/components-faraday/src/components/Dashboard/utils.js b/packages/components-faraday/src/components/Dashboard/utils.js index 50d39d73b..84a170049 100644 --- a/packages/components-faraday/src/components/Dashboard/utils.js +++ b/packages/components-faraday/src/components/Dashboard/utils.js @@ -53,7 +53,14 @@ export const parseType = version => { export const parseSubmissionDate = version => { const submitted = get(version, 'submitted') - return submitted ? moment(submitted).format('DD-MM-YYYY') : 'N/A' + const submittedDate = moment(submitted) + const today = moment() + const daysAgo = moment.duration(today - moment(submitted)).days() + return submitted + ? `${submittedDate.format('DD.MM.YYYY')} ${ + daysAgo > 0 ? `(${daysAgo} days)` : '' + }` + : 'N/A' } export const parseVersion = version => ({ diff --git a/packages/xpub-faraday/config/default.js b/packages/xpub-faraday/config/default.js index 3fb217500..054318dba 100644 --- a/packages/xpub-faraday/config/default.js +++ b/packages/xpub-faraday/config/default.js @@ -25,7 +25,7 @@ module.exports = { 'pubsweet-client': { API_ENDPOINT: '/api', 'login-redirect': '/', - 'redux-log': true, + 'redux-log': false, theme: process.env.PUBSWEET_THEME, }, 'mail-transport': { -- GitLab