Skip to content
Snippets Groups Projects
SimpleEditor.jsx 6.07 KiB
Newer Older
// import { get } from 'lodash'
import React from 'react'
import ReactDOM from 'react-dom'
import { Alert } from 'react-bootstrap'

john's avatar
john committed
import {
  ProseEditorConfigurator as Configurator,
  DocumentSession
} from 'substance'
john's avatar
john committed
import config from './config'
import Editor from './Editor'
import Importer from './SimpleEditorImporter'
import SimpleExporter from './SimpleEditorExporter'

import './SimpleEditor.scss'

export default class SimpleEditor extends React.Component {
  constructor (props) {
    super(props)
    this.save = this.save.bind(this)
    this.updateTrackChangesStatus = this.updateTrackChangesStatus.bind(this)
    this._checkRights = this._checkRights.bind(this)

    this._releaseLock = this._releaseLock.bind(this)
    this._acquireLock = this._acquireLock.bind(this)

    // TODO -- delete, along with Alert
    this.state = {
      canEdit: false
    }
  }

  // TODO -- is this necessary?
  componentWillMount () {
    const { fragment } = this.props
    if (fragment) {
      this._checkRights()
      this._acquireLock()
  }

  createSession () {
    const { fragment } = this.props
    let source
    if (fragment) { source = fragment.source }

john's avatar
john committed
    const configurator = new Configurator().import(config)
    configurator.addImporter('html', Importer)

    const importer = configurator.createImporter('html')
    const doc = importer.importDocument(source)
    const documentSession = new DocumentSession(doc)

    documentSession.setSaveHandler({
      saveDocument: this.save
    })
john's avatar
john committed
      configurator: configurator,
      documentSession: documentSession
  updateTrackChangesStatus () {
    const { fragment, update } = this.props
    fragment.trackChanges = !fragment.trackChanges
    update(fragment)
  }

  save (source, changes, callback) {
    const { onSave } = this.props
john's avatar
john committed
    const config = this.state.config

    const exporter = new SimpleExporter(config)
    const convertedSource = exporter.exportDocument(source)

    onSave(convertedSource, callback)
john's avatar
john committed
  // NOTE -- Theoretically, we shouldn't lock when the editor is in read only
  // mode. This gets complicated however, as the user will be able to be add
  // comments, which will in turn affect the fragment. So, it is better to
  // avoid any possible data corruption until collaboration is added.
  _acquireLock () {
    const { fragment, update, user } = this.props

    fragment.lock = {
      editor: { username: user.username },
      timestamp: new Date()
    }

john's avatar
john committed
    update(fragment)
  }

  _releaseLock () {
    const { fragment, update } = this.props
john's avatar
john committed
    // TODO -- maybe this is causing the lock problems?
    // if (get(fragment, 'lock.editor.username') === user.username) {
    //   fragment.lock = null
    // }

    fragment.lock = null
    update(fragment)
  }

  // TODO -- rewrite cleaner, and as isDisabled (returns boolean)
  _checkRights () {
    const { fragment, user } = this.props

    if (user.admin) return this.setState({ canEdit: true })

    if ((fragment.progress['review'] === 1 && user.teams[0].teamType.name === 'Author') ||
        (fragment.progress['edit'] === 1 && user.teams[0].teamType.name === 'Copy Editor')) {
      this.setState({ canEdit: true })
    } else {
      this.setState({ canEdit: false })
    }
    if (user.teams[0].teamType.name === 'Production Editor') {
      this.setState({ canEdit: true })
    }
  }

  // TODO -- remove when reloading works correctly (by refreshing props)
  componentWillReceiveProps (nextProps) {
    const { fragment } = this.props
    if (fragment) return

    var self = this
    if (nextProps.fragment) {
      setTimeout(function () {
        self._checkRights()
        self.componentDidMount()
      }, 0)
    }
  }

  componentDidMount () {
john's avatar
john committed
    const el = ReactDOM.findDOMNode(this)
john's avatar
john committed

    const { book, fileUpload, fragment, history, onSave, update, user } = this.props
    const { configurator, documentSession } = this.createSession()
    if (!fragment) return

john's avatar
john committed
    const containerId = 'body'

    // TODO -- delete
    const trackChanges = fragment.trackChanges
    const updateTrackChangesStatus = this.updateTrackChangesStatus
    const disabled = !this.state.canEdit

john's avatar
john committed
    // TODO -- justify
john's avatar
john committed
    this.setState({
      config: configurator.config
    })
john's avatar
john committed
    Editor.mount({
john's avatar
john committed
      book,
      configurator,
      containerId,
      disabled,
      documentSession,
      fileUpload,
      fragment,
      history,
      onSave,
      trackChanges,
      update,
      updateTrackChangesStatus,
      user
john's avatar
john committed
    // TODO -- pull all above into its own function

    window.addEventListener('beforeunload', this._releaseLock)
  }

  componentWillUnmount () {
    this._releaseLock()
    window.removeEventListener('beforeunload', this._releaseLock)
  // TODO -- use this for correctly refreshing props when the fragment arrives
  // this.writer does not exist, you have to make it in componentDidMount
  // this.writer = Editor.mount( ....

  // New props arrived, update the editor
  // componentDidUpdate () {
  //   console.log('did update')
  //
  //   var session = this.createSession()
  //   var documentSession = session.documentSession
  //   var configurator = session.configurator
  //
  //   this.writer.extendProps({
  //     documentSession: documentSession,
  //     configurator: configurator
  //   })
  //
  //   console.log(this.writer)
  // }
  //
  // componentWillUnmount () {
  //   this.writer.dispose()
  // }

  // TODO -- do I even need a render here?
    // TODO -- DELETE THIS !!!!!
    let viewMode = !this.state.canEdit
      <Alert bsStyle='warning' className='view-mode'>
        <span>Editor is in Read-Only Mode</span>
      <div className='editor-wrapper'>
      </div>
    )
  }
}

SimpleEditor.propTypes = {
  book: React.PropTypes.object.isRequired,
john's avatar
john committed
  canEdit: React.PropTypes.bool, // needed?
  fragment: React.PropTypes.object,
john's avatar
john committed
  history: React.PropTypes.object.isRequired,
  onSave: React.PropTypes.func.isRequired,
  update: React.PropTypes.func.isRequired,
  fileUpload: React.PropTypes.func.isRequired,
  user: React.PropTypes.object.isRequired
}