Skip to content
Snippets Groups Projects
ActivityDetails.jsx 5.87 KiB
Newer Older
import React from 'react'
ahamelers's avatar
ahamelers committed
import { Mutation } from 'react-apollo'
import { H2, Button, Action, Link } from '@pubsweet/ui'
Yuci Gou's avatar
Yuci Gou committed
import { th } from '@pubsweet/ui-toolkit'
Yuci Gou's avatar
Yuci Gou committed
import styled from 'styled-components'
Yuci Gou's avatar
Yuci Gou committed
import moment from 'moment'
import { Buttons, CloseModal, Table, Portal, TextArea, Toggle } from '../ui'
ahamelers's avatar
ahamelers committed
import Mailer from '../mailer'
ahamelers's avatar
ahamelers committed
import { CREATE_NOTE } from '../operations'
import EventDescription from './EventDescription'
import { QUERY_ACTIVITY_INFO } from './operations'
Yuci Gou's avatar
Yuci Gou committed
const DetailsTable = styled(Table)`
  width: 100%;
ahamelers's avatar
ahamelers committed
  @media screen and (max-width: 600px) {
    th {
      display: none;
    }
    tr {
      border: ${th('borderWidth')} ${th('borderStyle')} ${th('colorBorder')};
    }
  }
Yuci Gou's avatar
Yuci Gou committed
`
ahamelers's avatar
ahamelers committed
const TD = styled.td`
  font-size: ${th('fontSizeBaseSmall')};
ahamelers's avatar
ahamelers committed
  @media screen and (max-width: 600px) {
    display: inline-block;
    width: 100%;
    border: 0 !important;
  }
ahamelers's avatar
ahamelers committed
`
const TdDate = styled(TD)`
Yuci Gou's avatar
Yuci Gou committed
  vertical-align: top;
  width: 1%;
ahamelers's avatar
ahamelers committed
  @media screen and (max-width: 600px) {
    width: 50%;
    white-space: normal;
  }
Yuci Gou's avatar
Yuci Gou committed
`
const TdPerson = TdDate

ahamelers's avatar
ahamelers committed
const NewMsgBtn = styled(Button)`
  padding: calc(${th('gridUnit')} / 2) ${th('gridUnit')};
  margin-left: ${th('gridUnit')};
  font-size: ${th('fontSizeBaseSmall')};
`
const DetailsHeading = styled.div`
  display: flex;
  align-items: baseline;
  justify-content: space-between;
`
const DetailsToggle = styled.div`
  display: flex;
  align-items: baseline;
  div {
    margin-left: calc(${th('gridUnit')} * 8);
  }
  @media screen and (max-width: 680px) {
    flex: 2;
    display block;
    div {
      margin-left: 0;
      margin-bottom: ${th('gridUnit')};
    }
  }
`
ahamelers's avatar
ahamelers committed
const NewNote = ({ close, manuscriptId, message, onChange }) => (
  <Mutation
    mutation={CREATE_NOTE}
    refetchQueries={() => [
      {
        query: QUERY_ACTIVITY_INFO,
        variables: { id: manuscriptId },
      },
    ]}
  >
    {(createNote, { data }) => {
      const newNote = async () => {
        await createNote({
          variables: {
            data: {
              manuscriptId,
              notesType: 'userMessage',
              content: JSON.stringify(message),
            },
          },
        })
        onChange('')
        close()
      }
      return (
        <Portal transparent>
          <CloseModal onClick={() => close()} />
ahamelers's avatar
ahamelers committed
          <H2>Add a note</H2>
          <TextArea
            label="Note (visible only to administrators)"
            onChange={e => onChange(e.target.value)}
            value={message}
          />
          <Buttons right>
            <Button disabled={!message} onClick={() => newNote()} primary>
              Save
            </Button>
            <Button onClick={() => close()}>Cancel</Button>
          </Buttons>
        </Portal>
      )
    }}
  </Mutation>
)

const ActivityList = ({ audits, manuscript }) =>
  audits.map(audit => (
    <tr key={audit.id}>
      <TdDate>{moment(audit.created).format('DD/MM/YYYY HH:mm')}</TdDate>
      <TdPerson>
        <Link to={`/manage-account/${audit.user.id}`}>
          {`${audit.user.givenNames} ${audit.user.surname}`}
        </Link>
      </TdPerson>
      <TD>
        <EventDescription audit={audit} manuscript={manuscript} />
      </TD>
    </tr>
  ))
Yuci Gou's avatar
Yuci Gou committed
class ActivityDetails extends React.Component {
ahamelers's avatar
ahamelers committed
  state = {
    sendingMail: false,
    newNote: false,
    message: '',
    showAudits: 'all',
    audits: [],
  }
  componentDidMount() {
    this.changeAudits('all')
  }
  componentDidUpdate(prevProps) {
    if (
      this.props.manuscript.audits.length > prevProps.manuscript.audits.length
    ) {
      this.changeAudits(this.state.showAudits)
    }
  }
  changeAudits = showAudits => {
    let audits = this.props.manuscript.audits.slice().reverse()
    if (showAudits !== 'all') {
      audits = audits.filter(a => a.objectType === showAudits)
    }
    this.setState({ audits, showAudits })
ahamelers's avatar
ahamelers committed
  }
Yuci Gou's avatar
Yuci Gou committed
  render() {
    const { currentUser, manuscript } = this.props
    const { audits, showAudits } = this.state
Yuci Gou's avatar
Yuci Gou committed
    return (
      <React.Fragment>
Yuci Gou's avatar
Yuci Gou committed
        <DetailsHeading>
          <DetailsToggle>
Yuci Gou's avatar
Yuci Gou committed
            <H2>Details</H2>
            <Toggle>
              <Action
                className={showAudits === 'all' && 'current'}
                onClick={() => this.changeAudits('all')}
              >
                All
              </Action>
              <Action
                className={showAudits === 'file' && 'current'}
                onClick={() => this.changeAudits('file')}
              >
                Files
              </Action>
              <Action
                className={showAudits === 'note' && 'current'}
                onClick={() => this.changeAudits('note')}
              >
                Messages
              </Action>
            </Toggle>
          </DetailsToggle>
Yuci Gou's avatar
Yuci Gou committed
          <div>
ahamelers's avatar
ahamelers committed
            <NewMsgBtn onClick={() => this.setState({ newNote: true })}>
              Add note
            </NewMsgBtn>
Yuci Gou's avatar
Yuci Gou committed
            <NewMsgBtn
              onClick={() => this.setState({ sendingMail: true })}
              primary
            >
ahamelers's avatar
ahamelers committed
              Send email
Yuci Gou's avatar
Yuci Gou committed
            </NewMsgBtn>
          </div>
        </DetailsHeading>
        <DetailsTable>
          <tbody>
            <tr>
              <th>Date</th>
              <th>Person</th>
Yuci Gou's avatar
Yuci Gou committed
              <th>Event</th>
            </tr>
            <ActivityList audits={audits} manuscript={manuscript} />
Yuci Gou's avatar
Yuci Gou committed
          </tbody>
        </DetailsTable>
        {this.state.sendingMail && (
          <Mailer
            close={() => this.setState({ sendingMail: false })}
            currentUser={currentUser}
            manuscript={manuscript}
          />
        )}
        {this.state.newNote && (
          <NewNote
            close={() => this.setState({ newNote: false })}
            manuscriptId={manuscript.id}
            message={this.state.message}
            onChange={message => this.setState({ message })}
          />
        )}
      </React.Fragment>
Yuci Gou's avatar
Yuci Gou committed
    )
  }
}

export default ActivityDetails