Skip to content
Snippets Groups Projects
BookBuilder.jsx 7.12 KiB
Newer Older
import _ from 'lodash'
import React from 'react'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'

john's avatar
john committed
import * as Actions from 'pubsweet-frontend/src/actions'
import Division from './Division'
john's avatar
john committed
import Modal from '../utils/Modal'
import styles from './styles/bookBuilder.local.scss'

// import { fragmentsOfCollection } from 'pubsweet-core/app/helpers/Utils'

export class BookBuilder extends React.Component {
  constructor (props) {
    super(props)

    this._toggleTeamManager = this._toggleTeamManager.bind(this)
    // this.enableActions = false

    this._getRoles = this._getRoles.bind(this)
    this._isProductionEditor = this._isProductionEditor.bind(this)
    this._setProductionEditor = this._setProductionEditor.bind(this)

    this.state = {
      outerContainer: {},
      productionEditor: null,
      showTeamManager: false
    }
  }

  componentWillMount () {
    const { getUsers, getTeams, getCollections, getFragments } = this.props.actions

    // console.log(this.props.actions)
john's avatar
john committed

    getUsers().then(
      () => getTeams()
    ).then(
      () => {
        this._setProductionEditor()
        return getCollections()
      }
    ).then(
      // TODO: This will have to work for multiple collections
      (result) => getFragments(result.collections[0])
    )
  }

  componentDidMount () {
    // I'm using the ref inside the render function it was created in
    // So it won't be available until didMount
    // Pass it to the state and use it safely (no undefined scenarios)
    this.setState({ outerContainer: this.refs.outerContainer })
  }

  // temporary HACK to add production editor to collection
  _setProductionEditor () {
    const { book, teams, users } = this.props

    const productionEditorsTeam = _.find(teams, function (t) {
      return t.teamType.name === 'Production Editor' && t.object.id === book.id
    })

    const productionEditors = _.filter(users, function (u) {
      return _.includes(productionEditorsTeam.members, u.id)
    })

    this.setState({ productionEditor: productionEditors[0].username })
  }

  _toggleTeamManager () {
    this.setState({ showTeamManager: !this.state.showTeamManager })
  }

  _getRoles () {
    const { user, book } = this.props

    const teams = _.filter(user.teams, function (t) {
      return t.object.id === book.id
    })

    let roles = []
    if (user.admin) roles.push('admin')

    function addRole (role) {
      roles = _.union(roles, [role])
    }

    _.forEach(teams, function (t) {
      switch (t.teamType.name) {
        case 'Production Editor':
          addRole('production-editor')
          break
        case 'Copy Editor':
          addRole('copy-editor')
          break
        case 'Author':
          addRole('author')
          break
      }
    })

    return roles
  }

  _isProductionEditor () {
john's avatar
john committed
    const userRoles = this._getRoles()
    const accepted = ['production-editor', 'admin']
    const pass = _.some(accepted, (role) => _.includes(userRoles, role))
    return pass
  }

  render () {
    const { book, chapters, teams, users } = this.props
    const { createFragment, deleteFragment, ink, updateFragment, updateTeam } = this.props.actions
    const { outerContainer } = this.state
    const roles = this._getRoles()

    let frontChapters = []
    let bodyChapters = []
    let backChapters = []

    _.forEach(chapters, function (c) {
      switch (c.division) {
        case 'front':
          frontChapters.push(c)
          break
        case 'body':
          bodyChapters.push(c)
          break
        case 'back':
          backChapters.push(c)
          break
      }
    })

    const isProductionEditor = this._isProductionEditor()
    let teamManagerButton = ''
    if (isProductionEditor) {
      teamManagerButton = (
        <div className={styles.teamManagerBtn}
          onClick={this._toggleTeamManager}>
          <a>team manager</a>
        </div>
      )
    }

    const productionEditor = this.state.productionEditor || 'unassigned'

    return (
chris's avatar
chris committed
      <div className='bootstrap modal pubsweet-component pubsweet-component-scroll'>
        <div className={styles.bookBuilder}>
          <div
john's avatar
john committed
            className='col-lg-offset-2 col-lg-8 col-md-8 col-sm-12 col-xs-12'
            ref='outerContainer'>

            <h1>{this.props.book.title}</h1>

            <div className={styles.productionEditorContainer}>
              <span>Production Editor: &nbsp; {productionEditor} </span>
              {teamManagerButton}
              <div className={styles.separator} />
            </div>

            <Division
              add={createFragment}
              chapters={frontChapters}
              ink={ink}
              outerContainer={outerContainer}
              remove={deleteFragment}
              roles={roles}
              title='Front Matter'
              type='front'
              update={updateFragment}
            />

            <div className={styles.sectionDivider} />

            <Division
              add={createFragment}
              chapters={bodyChapters}
              ink={ink}
              outerContainer={outerContainer}
              remove={deleteFragment}
              roles={roles}
              title='Body'
              type='body'
              update={updateFragment}
            />

            <div className={styles.sectionDivider} />

            <Division
              add={createFragment}
              chapters={backChapters}
              ink={ink}
              outerContainer={outerContainer}
              remove={deleteFragment}
              roles={roles}
              title='Back Matter'
              type='back'
              update={updateFragment}
john's avatar
john committed
        <Modal
john's avatar
john committed
          title='Editoria Team Manager'
          action='EditoriaTeamManager'
          show={this.state.showTeamManager}
          toggle={this._toggleTeamManager}
          container={outerContainer}
john's avatar
john committed
          size='large'
          teams={teams}
          users={users}
          updateTeam={updateTeam}
        />

      </div>
    )
  }
}

BookBuilder.propTypes = {
  book: React.PropTypes.object.isRequired,
  chapters: React.PropTypes.array.isRequired,
  actions: React.PropTypes.object.isRequired,
  error: React.PropTypes.string,
  // userRoles: React.PropTypes.array,
  teams: React.PropTypes.array,
  users: React.PropTypes.array,
  user: React.PropTypes.object
}

function mapStateToProps (state, ownProps) {
  let book = _.find(state.collections, function (c) {
    return c.id === ownProps.params.id
  })

  let chapters = _.sortBy(_.filter(state.fragments, function (f) {
    return f.book === book.id && f.id && !f.deleted
  }), 'index')

  let teams = state.teams
  let users = state.users.users
  let user = state.currentUser.user

  let error = state.error

  return {
    book: book || {},
    chapters: chapters,
    teams: teams,
    users: users,
    user: user,
    // userRoles: state.auth.roles,
    errorMessage: error
  }
}

function mapDispatchToProps (dispatch) {
  return {
    actions: bindActionCreators(Actions, dispatch)
  }
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(BookBuilder)