diff --git a/app/components/BookBuilder/BookBuilder.jsx b/app/components/BookBuilder/BookBuilder.jsx index 0a8d419818dd9afd74e0322a16e2ddee6731c0ff..dfed3caa6c5df9a0694f696d3aa9a107a5f0581a 100644 --- a/app/components/BookBuilder/BookBuilder.jsx +++ b/app/components/BookBuilder/BookBuilder.jsx @@ -5,7 +5,7 @@ import { connect } from 'react-redux' import * as Actions from 'pubsweet-frontend/src/actions' import Division from './Division' -import BookBuilderModal from './BookBuilderModal' +import Modal from '../utils/Modal' import styles from './styles/bookBuilder.local.scss' // import { fragmentsOfCollection } from 'pubsweet-core/app/helpers/Utils' @@ -213,7 +213,7 @@ export class BookBuilder extends React.Component { </div> </div> - <BookBuilderModal + <Modal title='Editoria Team Manager' action='EditoriaTeamManager' show={this.state.showTeamManager} diff --git a/app/components/BookBuilder/Chapter/AlignmentBox.jsx b/app/components/BookBuilder/Chapter/AlignmentBox.jsx new file mode 100644 index 0000000000000000000000000000000000000000..8bf5f68083b2d91fcac1afaaacc3362ef63a6d5a --- /dev/null +++ b/app/components/BookBuilder/Chapter/AlignmentBox.jsx @@ -0,0 +1,44 @@ +import { includes } from 'lodash' +import React from 'react' + +import styles from '../styles/bookBuilder.local.scss' + +class AlignmentBox extends React.Component { + constructor (props) { + super(props) + this.onClick = this.onClick.bind(this) + } + + onClick () { + const { chapter, position, update } = this.props + + if (!includes(['left', 'right'], position)) return + + chapter.alignment[position] = !chapter.alignment[position] + update(chapter) + } + + render () { + const { chapter, position } = this.props + const selected = chapter.alignment[position] + + const outerClass = styles.leftRightBox + ' ' + styles.leftBox + const innerClass = selected ? styles.boxActive : styles.boxInactiveHover + + return ( + <li onClick={this.onClick}> + <div className={outerClass}> + <div className={innerClass} /> + </div> + </li> + ) + } +} + +AlignmentBox.propTypes = { + chapter: React.PropTypes.object.isRequired, + position: React.PropTypes.string.isRequired, + update: React.PropTypes.func.isRequired +} + +export default AlignmentBox diff --git a/app/components/BookBuilder/Chapter/AlignmentTool.jsx b/app/components/BookBuilder/Chapter/AlignmentTool.jsx new file mode 100644 index 0000000000000000000000000000000000000000..a8e694718021a5b5f528549a485edfa4d6d44759 --- /dev/null +++ b/app/components/BookBuilder/Chapter/AlignmentTool.jsx @@ -0,0 +1,43 @@ +import React from 'react' + +import AlignmentBox from './AlignmentBox' +import styles from '../styles/bookBuilder.local.scss' + +export class AlignmentTool extends React.Component { + render () { + const { chapter, update } = this.props + + // TODO -- what is boxDiver? divider? + + return ( + <ul className={styles.pagePosition}> + <li>left </li> + + <AlignmentBox + chapter={chapter} + position='left' + update={update} + /> + + <AlignmentBox + chapter={chapter} + position='right' + update={update} + /> + + <li> + <div className={styles.boxDiver} /> + </li> + + <li> right</li> + </ul> + ) + } +} + +AlignmentTool.propTypes = { + chapter: React.PropTypes.object.isRequired, + update: React.PropTypes.func.isRequired +} + +export default AlignmentTool diff --git a/app/components/BookBuilder/Chapter/ChapterButtons.jsx b/app/components/BookBuilder/Chapter/ChapterButtons.jsx index ff09e1fe61891f8af6fa5d852b2415df5d1a7549..7a27522faf8bdd1e592b60bc8ea1adaab68580c5 100644 --- a/app/components/BookBuilder/Chapter/ChapterButtons.jsx +++ b/app/components/BookBuilder/Chapter/ChapterButtons.jsx @@ -4,12 +4,21 @@ import { LinkContainer } from 'react-router-bootstrap' import DeleteModal from './DeleteModal' import EditingNotification from './EditingNotification' -import styles from './styles/bookBuilder.local.scss' +import styles from '../styles/bookBuilder.local.scss' class ChapterButtons extends React.Component { constructor (props) { super(props) + this.canEdit = this.canEdit.bind(this) + this.isLocked = this.isLocked.bind(this) + this.renderDeleteButton = this.renderDeleteButton.bind(this) + this.renderEditButton = this.renderEditButton.bind(this) + this.renderEditingNotification = this.renderEditingNotification.bind(this) + this.renderRenameButton = this.renderRenameButton.bind(this) + this.renderRightArea = this.renderRightArea.bind(this) + this.toggleDeleteModal = this.toggleDeleteModal.bind(this) + this.state = { showDeleteModal: false } diff --git a/app/components/BookBuilder/Chapter/DeleteModal.jsx b/app/components/BookBuilder/Chapter/DeleteModal.jsx index 5ef216705f25e984d2d498f942d61de58a51ad4d..4a10c6b258343a9a3992412cb6bdc4323e8e6f72 100644 --- a/app/components/BookBuilder/Chapter/DeleteModal.jsx +++ b/app/components/BookBuilder/Chapter/DeleteModal.jsx @@ -3,6 +3,11 @@ import React from 'react' import Modal from '../../utils/Modal' class DeleteModal extends React.Component { + constructor (props) { + super(props) + this.onDelete = this.onDelete.bind(this) + } + onDelete () { const { chapter, remove, toggle } = this.props diff --git a/app/components/BookBuilder/Chapter/DropdownTitle.jsx b/app/components/BookBuilder/Chapter/DropdownTitle.jsx index 00155212ab0d633efca635dd75b379595d834add..fb84c654390734b74a8e56c4817cb3749dbf80cc 100644 --- a/app/components/BookBuilder/Chapter/DropdownTitle.jsx +++ b/app/components/BookBuilder/Chapter/DropdownTitle.jsx @@ -124,14 +124,6 @@ class DropdownTitle extends React.Component { update(chapter) } - componentDidMount () { - window.addEventListener('click', this.handleClickOutside) - } - - componentWillUnmount () { - window.removeEventListener('click', this.handleClickOutside) - } - handleClickOutside (event) { var domNode = findDOMNode(this) @@ -142,6 +134,14 @@ class DropdownTitle extends React.Component { } } + componentDidMount () { + window.addEventListener('click', this.handleClickOutside) + } + + componentWillUnmount () { + window.removeEventListener('click', this.handleClickOutside) + } + renderInput () { return ( <div className={styles.dropDownInputContairer}> diff --git a/app/components/BookBuilder/Chapter/EditingNotification.jsx b/app/components/BookBuilder/Chapter/EditingNotification.jsx index d020cf77d932c5352a6f30ccf5ccd8f8fb0ea5e7..40986c81002afd65dda368d46b4be2cd314c5f50 100644 --- a/app/components/BookBuilder/Chapter/EditingNotification.jsx +++ b/app/components/BookBuilder/Chapter/EditingNotification.jsx @@ -9,6 +9,10 @@ class EditingNotification extends React.Component { constructor (props) { super(props) + this.formatDate = this.formatDate.bind(this) + this.isAdmin = this.isAdmin.bind(this) + this.toggleModal = this.toggleModal.bind(this) + this.state = { showModal: false } diff --git a/app/components/BookBuilder/Chapter/PagePositionAlignment.jsx b/app/components/BookBuilder/Chapter/PagePositionAlignment.jsx deleted file mode 100644 index 2c0f603184fdbda43e8a5515e38682bec7839833..0000000000000000000000000000000000000000 --- a/app/components/BookBuilder/Chapter/PagePositionAlignment.jsx +++ /dev/null @@ -1,60 +0,0 @@ -import React from 'react' -import styles from '../styles/bookBuilder.local.scss' -import { includes } from 'lodash' - -export class PagePositionAlignment extends React.Component { - constructor (props) { - super(props) - this._onClickAlignment = this._onClickAlignment.bind(this) - } - - _onClickAlignment (position) { - const { chapter, update } = this.props - if (!includes(['left', 'right'], position)) { return } - - function clickAlignment () { - chapter.alignment[position] = !chapter.alignment[position] - update(chapter) - } - - return clickAlignment - } - - render () { - const { chapter } = this.props - const clickAlignmentLeft = this._onClickAlignment('left') - const clickAlignmentRight = this._onClickAlignment('right') - const align = chapter.alignment - - return ( - <ul className={styles.pagePosition}> - <li>left </li> - - <li onClick={clickAlignmentLeft}> - <div className={styles.leftRightBox + ' ' + styles.leftBox}> - <div className={align.left ? styles.boxActive : styles.boxInactiveHover} /> - </div> - </li> - - <li onClick={clickAlignmentRight}> - <div className={styles.leftRightBox + ' ' + styles.rightBox}> - <div className={align.right ? styles.boxActive : styles.boxInactiveHover} /> - </div> - </li> - - <li> - <div className={styles.boxDiver} /> - </li> - - <li> right</li> - </ul> - ) - } -} - -PagePositionAlignment.propTypes = { - chapter: React.PropTypes.object.isRequired, - update: React.PropTypes.func.isRequired -} - -export default PagePositionAlignment diff --git a/app/components/BookBuilder/Chapter/ProgressItem.jsx b/app/components/BookBuilder/Chapter/ProgressItem.jsx index 82b13339105fee902e782f7b3fc3ad3bdd520678..6afaf89c59bcdb4bd4c42007988729da948771a3 100644 --- a/app/components/BookBuilder/Chapter/ProgressItem.jsx +++ b/app/components/BookBuilder/Chapter/ProgressItem.jsx @@ -1,7 +1,8 @@ -import React from 'react' import { includes } from 'lodash' +import React from 'react' import { Alert } from 'react-bootstrap' -import BookBuilderModal from '../BookBuilderModal' + +import ProgressModal from './ProgressModal' import styles from '../styles/bookBuilder.local.scss' export class ProgressItem extends React.Component { @@ -9,9 +10,12 @@ export class ProgressItem extends React.Component { super(props) this.canChange = this.canChange.bind(this) - this._onClick = this._onClick.bind(this) - this._toggleModal = this._toggleModal.bind(this) - this._changeWorkflowState = this._changeWorkflowState.bind(this) + this.changeProgressState = this.changeProgressState.bind(this) + this.onClick = this.onClick.bind(this) + this.renderErrorMessage = this.renderErrorMessage.bind(this) + this.renderIcon = this.renderIcon.bind(this) + this.renderModal = this.renderModal.bind(this) + this.toggleModal = this.toggleModal.bind(this) // TODO -- move to config this.progressValues = { @@ -22,11 +26,34 @@ export class ProgressItem extends React.Component { } this.state = { - showWarning: false, + showModal: false, showError: false } } + toggleModal () { + this.setState({ + showModal: !this.state.showModal + }) + } + + changeProgressState () { + const { chapter, update, type } = this.props + const { progressValues } = this + + const list = progressValues[type] + const len = list.length + + let position = chapter.progress[type] + position += 1 // move up a level + if (position >= len) position = 0 // or cycle back to the beginning + + chapter.progress[type] = position + update(chapter) + + this.setState({ showWarning: false }) + } + canChange () { const { type, roles, chapter } = this.props @@ -46,79 +73,87 @@ export class ProgressItem extends React.Component { return false } - _onClick () { + onClick () { const { roles } = this.props - if (!this._isAllowedToChange()) { + + if (!this.canChange()) { this.setState({ showError: true }) - setTimeout(() => { this.setState({showError: false}) }, 3000) - return - } else if (includes(roles, 'production-editor')) { - this._changeWorkflowState() - } else { - this._toggleModal() + + return setTimeout(() => { + this.setState({ showError: false }) + }, 3000) } - } - _toggleModal () { - this.setState({ showWarning: !this.state.showWarning }) + if (includes(roles, 'production-editor')) { + return this.changeProgressState() + } + + this.toggleModal() } - _changeWorkflowState () { - const { chapter, update, type, viewOrEdit } = this.props - const { progressValues } = this + renderModal () { + const { chapter, modalContainer, type } = this.props + const { showModal } = this.state - const list = progressValues[type] + const typesWithModal = ['edit', 'review'] + if (!includes(typesWithModal, type)) return null - let position = chapter.progress[type] - position += 1 // move up a level + return ( + <ProgressModal + changeProgressState={this.changeProgressState} + chapter={chapter} + container={modalContainer} + show={showModal} + toggle={this.toggleModal} + /> + ) + } - if (position >= list.length) { - position = 0 // or cycle back to the beginning - } + renderIcon () { + const { hasIcon } = this.props + if (!hasIcon) return null - chapter.progress[type] = position + return (<i className='fa fa-angle-right' />) + } - update(chapter) - this.setState({ showWarning: false }) - viewOrEdit() + renderErrorMessage () { + const { showError } = this.state + if (!showError) return null + + return ( + <Alert + bsStyle='warning' + className={styles.noWritesError} + > + You don't have access to perfom this action. + Please contact your Production Editor. + </Alert> + ) } render () { - const { type, chapter, hasIcon, outerContainer } = this.props + const { type, chapter } = this.props const { progressValues } = this - let ErrorMsg = this.state.showError - ? ( - <Alert bsStyle='warning' className={styles.noWritesError}> - You don't have access to perfom this action. Please contact your Production Editor. - </Alert> - ) - : null + const currentStateValue = chapter.progress[type] + const currentStateText = progressValues[type][currentStateValue] - let icon = '' - if (hasIcon) { - icon = <i className='fa fa-angle-right' /> - } + const errorMessage = this.renderErrorMessage() + const icon = this.renderIcon() + const warningModal = this.renderModal() - const warningModal = ( - <BookBuilderModal - title='Change of workflow status' - action='workflow-warning' - successText='OK' - successAction={this._changeWorkflowState} - show={this.state.showWarning} - toggle={this._toggleModal} - container={outerContainer} - /> - ) + // TODO -- find a nicer way to display the error message return ( <span> - { ErrorMsg } - <li className={'progress' + chapter.progress[type]} - onClick={this._onClick}> + { errorMessage } + + <li + className={'progress' + currentStateValue} + onClick={this.onClick} + > - { progressValues[type][chapter.progress[type]] } + { currentStateText } { icon } { warningModal } @@ -129,13 +164,13 @@ export class ProgressItem extends React.Component { } ProgressItem.propTypes = { - type: React.PropTypes.string.isRequired, chapter: React.PropTypes.object.isRequired, hasIcon: React.PropTypes.bool, - update: React.PropTypes.func.isRequired, + modalContainer: React.PropTypes.object, roles: React.PropTypes.array.isRequired, - outerContainer: React.PropTypes.object.isRequired, - viewOrEdit: React.PropTypes.func + type: React.PropTypes.string.isRequired, + update: React.PropTypes.func.isRequired + // viewOrEdit: React.PropTypes.func } export default ProgressItem diff --git a/app/components/BookBuilder/Chapter/ProgressList.jsx b/app/components/BookBuilder/Chapter/ProgressList.jsx index 163a1b1c59392d52538425c7315c317c255dd1c9..7153d24ab11cd52fc40e900c89e830cd81e492d6 100644 --- a/app/components/BookBuilder/Chapter/ProgressList.jsx +++ b/app/components/BookBuilder/Chapter/ProgressList.jsx @@ -10,40 +10,40 @@ class ProgressList extends React.Component { return ( <ul className={styles.secondActions + ' col-lg-7 col-md-12 col-sm-12 col-xs-12'}> <ProgressItem - type='style' chapter={chapter} - update={update} - roles={roles} - modalContainer={modalContainer} hasIcon + // modalContainer={modalContainer} + roles={roles} + type='style' + update={update} // viewOrEdit={this._viewOrEdit} /> <ProgressItem - type='edit' chapter={chapter} - update={update} - roles={roles} - modalContainer={modalContainer} hasIcon + modalContainer={modalContainer} + roles={roles} + type='edit' + update={update} // viewOrEdit={this._viewOrEdit} /> <ProgressItem - type='review' chapter={chapter} - update={update} - roles={roles} - modalContainer={modalContainer} hasIcon + modalContainer={modalContainer} + roles={roles} + type='review' + update={update} // viewOrEdit={this._viewOrEdit} /> <ProgressItem - type='clean' chapter={chapter} + // modalContainer={modalContainer} roles={roles} - modalContainer={modalContainer} + type='clean' update={update} // viewOrEdit={this._viewOrEdit} /> diff --git a/app/components/BookBuilder/Chapter/ProgressModal.jsx b/app/components/BookBuilder/Chapter/ProgressModal.jsx new file mode 100644 index 0000000000000000000000000000000000000000..d8d543c16a070c80152ad56b1aca99c68029d94b --- /dev/null +++ b/app/components/BookBuilder/Chapter/ProgressModal.jsx @@ -0,0 +1,35 @@ +import React from 'react' + +import Modal from '../../utils/Modal' + +class ProgressModal extends React.Component { + render () { + const { changeProgressState, chapter, container, show, toggle } = this.props + const type = chapter.type + + return ( + <Modal + action='workflow-warning' + chapter={chapter} + container={container} + type={type} + show={show} + successAction={changeProgressState} + successText='OK' + title='Change of workflow status' + toggle={toggle} + /> + + ) + } +} + +ProgressModal.propTypes = { + changeProgressState: React.PropTypes.func.isRequired, + chapter: React.PropTypes.object.isRequired, + container: React.PropTypes.object.isRequired, + show: React.PropTypes.bool.isRequired, + toggle: React.PropTypes.func.isRequired +} + +export default ProgressModal diff --git a/app/components/BookBuilder/Chapter/SecondRow.jsx b/app/components/BookBuilder/Chapter/SecondRow.jsx index 1e2844c1f521269ab80c56102287e3c57f17b366..bbffafa5dc6cd764a03a965dcd45acd83ff8e802 100644 --- a/app/components/BookBuilder/Chapter/SecondRow.jsx +++ b/app/components/BookBuilder/Chapter/SecondRow.jsx @@ -1,8 +1,8 @@ import React from 'react' -import PagePositionAlignment from './PagePositionAlignment' +import AlignmentTool from './AlignmentTool' import ProgressList from './ProgressList' -import UploadWordButton from './UploadWordBtn' +import UploadButton from './UploadButton' import styles from '../styles/bookBuilder.local.scss' @@ -10,11 +10,13 @@ class ChapterSecondRow extends React.Component { render () { const { chapter, ink, outerContainer, roles, update } = this.props + // TODO -- surrounding divs should go inside the components + return ( <div className={styles.secondLineContainer}> <div className={styles.noPadding + ' col-lg-2 col-md-12 col-sm-12 col-xs-12'}> - <UploadWordButton + <UploadButton accept='.docx' ink={ink} title=' ' @@ -30,9 +32,9 @@ class ChapterSecondRow extends React.Component { /> <div className={styles.noPadding + ' col-lg-3 col-md-12 col-sm-12 col-xs-12'}> - <PagePositionAlignment + <AlignmentTool chapter={chapter} - update={this.update} + update={update} /> </div> diff --git a/app/components/BookBuilder/Chapter/UnlockModal.jsx b/app/components/BookBuilder/Chapter/UnlockModal.jsx index 4c3ca1e038b5ebf320e7886bbecc9a4488dc7154..03fdae44fd52a43633a3c7d92dd31578220ba64c 100644 --- a/app/components/BookBuilder/Chapter/UnlockModal.jsx +++ b/app/components/BookBuilder/Chapter/UnlockModal.jsx @@ -3,6 +3,11 @@ import React from 'react' import Modal from '../../utils/Modal' class UnlockModal extends React.Component { + constructor (props) { + super(props) + this.onUnlock = this.onUnlock.bind(this) + } + onUnlock () { const { chapter, toggle, update } = this.props diff --git a/app/components/BookBuilder/Chapter/UploadWordBtn.jsx b/app/components/BookBuilder/Chapter/UploadButton.jsx similarity index 66% rename from app/components/BookBuilder/Chapter/UploadWordBtn.jsx rename to app/components/BookBuilder/Chapter/UploadButton.jsx index 2e827d91b247fa577f9aa467939736fd7c5f3e1e..7c41ead22e6ad33e3d78f0a6b849e9528d3f7388 100644 --- a/app/components/BookBuilder/Chapter/UploadWordBtn.jsx +++ b/app/components/BookBuilder/Chapter/UploadButton.jsx @@ -1,29 +1,12 @@ import React from 'react' import styles from '../styles/bookBuilder.local.scss' -export class UploadWordButton extends React.Component { +export class UploadButton extends React.Component { constructor (props) { super(props) this.handleFileUpload = this.handleFileUpload.bind(this) } - render () { - const { accept, title, type } = this.props - - return ( - <div id='bb-upload' className={styles.btnFile}> - Upload Word - <input - accept={accept} - onChange={this.handleFileUpload} - ref='yes' - title={title} - type={type} - /> - </div> - ) - } - handleFileUpload (event) { event.preventDefault() @@ -35,13 +18,36 @@ export class UploadWordButton extends React.Component { console.log(response) ) } + + render () { + const { accept, title, type } = this.props + + const input = ( + <input + accept={accept} + onChange={this.handleFileUpload} + title={title} + type={type} + /> + ) + + return ( + <div + className={styles.btnFile} + id='bb-upload' + > + Upload Word + { input } + </div> + ) + } } -UploadWordButton.propTypes = { +UploadButton.propTypes = { accept: React.PropTypes.string.isRequired, ink: React.PropTypes.func.isRequired, title: React.PropTypes.string.isRequired, type: React.PropTypes.string.isRequired } -export default UploadWordButton +export default UploadButton diff --git a/app/components/utils/Modal.jsx b/app/components/utils/Modal.jsx index 8d052e7da429b711b3cc13dda8714f0b20fd8caa..b662cad338a2daa1abbe1f8757e4605b1207d9df 100644 --- a/app/components/utils/Modal.jsx +++ b/app/components/utils/Modal.jsx @@ -1,21 +1,21 @@ import React from 'react' import { Modal } from 'react-bootstrap' -import TeamManager from './TeamManager/TeamManager' +import TeamManager from '../BookBuilder/TeamManager/TeamManager' export class BookBuilderModal extends React.Component { render () { const { - title, - show, - toggle, - successText, - successAction, - container, - chapter, - type, action, + chapter, + container, size, + show, + successAction, + successText, teams, + title, + toggle, + type, users, updateTeam } = this.props @@ -28,7 +28,7 @@ export class BookBuilderModal extends React.Component { { successText } </a> : null - // TODO -- move to config + // TODO -- move to individual modal components if (action === 'delete') { modalBodyText = ( <div> @@ -44,6 +44,7 @@ export class BookBuilderModal extends React.Component { </div> ) } else if (action === 'EditoriaTeamManager') { + // TODO -- ESPECIALLY THIS ONE modalBodyText = ( <div> <TeamManager @@ -101,19 +102,19 @@ export class BookBuilderModal extends React.Component { } BookBuilderModal.propTypes = { - chapter: React.PropTypes.object, - title: React.PropTypes.string.isRequired, action: React.PropTypes.string.isRequired, - type: React.PropTypes.string, - successText: React.PropTypes.string, - successAction: React.PropTypes.func, - show: React.PropTypes.bool.isRequired, - toggle: React.PropTypes.func.isRequired, + chapter: React.PropTypes.object, container: React.PropTypes.object.isRequired, + show: React.PropTypes.bool.isRequired, size: React.PropTypes.string, + successAction: React.PropTypes.func, + successText: React.PropTypes.string, teams: React.PropTypes.array, - users: React.PropTypes.array, - updateTeam: React.PropTypes.func + title: React.PropTypes.string.isRequired, + toggle: React.PropTypes.func.isRequired, + type: React.PropTypes.string, + updateTeam: React.PropTypes.func, + users: React.PropTypes.array } export default BookBuilderModal