From 451bd0d01ce118c71ae5e50eaa87337b6c494ad6 Mon Sep 17 00:00:00 2001 From: john <johnbarlas39@gmail.com> Date: Wed, 14 Dec 2016 00:43:12 +0200 Subject: [PATCH] chapter refactor -- part three --- app/components/BookBuilder/BookBuilder.jsx | 4 +- .../BookBuilder/Chapter/AlignmentBox.jsx | 44 +++++ .../BookBuilder/Chapter/AlignmentTool.jsx | 43 +++++ .../BookBuilder/Chapter/ChapterButtons.jsx | 11 +- .../BookBuilder/Chapter/DeleteModal.jsx | 5 + .../BookBuilder/Chapter/DropdownTitle.jsx | 16 +- .../Chapter/EditingNotification.jsx | 4 + .../Chapter/PagePositionAlignment.jsx | 60 ------- .../BookBuilder/Chapter/ProgressItem.jsx | 157 +++++++++++------- .../BookBuilder/Chapter/ProgressList.jsx | 28 ++-- .../BookBuilder/Chapter/ProgressModal.jsx | 35 ++++ .../BookBuilder/Chapter/SecondRow.jsx | 12 +- .../BookBuilder/Chapter/UnlockModal.jsx | 5 + .../{UploadWordBtn.jsx => UploadButton.jsx} | 46 ++--- app/components/utils/Modal.jsx | 39 ++--- 15 files changed, 319 insertions(+), 190 deletions(-) create mode 100644 app/components/BookBuilder/Chapter/AlignmentBox.jsx create mode 100644 app/components/BookBuilder/Chapter/AlignmentTool.jsx delete mode 100644 app/components/BookBuilder/Chapter/PagePositionAlignment.jsx create mode 100644 app/components/BookBuilder/Chapter/ProgressModal.jsx rename app/components/BookBuilder/Chapter/{UploadWordBtn.jsx => UploadButton.jsx} (66%) diff --git a/app/components/BookBuilder/BookBuilder.jsx b/app/components/BookBuilder/BookBuilder.jsx index 0a8d419..dfed3ca 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 0000000..8bf5f68 --- /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 0000000..a8e6947 --- /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 ff09e1f..7a27522 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 5ef2167..4a10c6b 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 0015521..fb84c65 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 d020cf7..40986c8 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 2c0f603..0000000 --- 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 82b1333..6afaf89 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 163a1b1..7153d24 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 0000000..d8d543c --- /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 1e2844c..bbffafa 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 4c3ca1e..03fdae4 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 2e827d9..7c41ead 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 8d052e7..b662cad 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 -- GitLab