import { includes, some } from 'lodash' import { ProseEditor, Toolbar // TOCProvider, } from 'substance' import Comments from './panes/Comments/CommentBoxList' import CommentsProvider from './panes/Comments/CommentsProvider' import ContainerEditor from './ContainerEditor' import Notes from './panes/Notes/Notes' import NotesProvider from './panes/Notes/NotesProvider' // import TableOfContents from './panes/TableOfContents/TableOfContents' import TrackChangesProvider from './elements/track_change/TrackChangesProvider' import ModalWarning from './elements/modal_warning/ModalWarning' class Editor extends ProseEditor { constructor (parent, props) { super(parent, props) this.handleActions({ // TODO -- clean them up like changesNotSaved 'trackChangesUpdate': function () { this.updateTrackChange() }, 'trackChangesViewToggle': function () { this.trackChangesViewToggle() }, 'changesNotSaved': this.changesNotSaved, 'closeModal': this.closeModal }) } trackChangesViewToggle () { this.extendState({ trackChangesView: !this.state.trackChangesView }) } updateTrackChange () { // TODO -- clean up this.props and this.refs this.extendProps({ trackChanges: !this.props.trackChanges }) this.props.updateTrackChangesStatus(!this.props.trackChanges) this.refs.toolbar.extendProps({trackChanges: this.props.trackChanges}) } willUpdateState () {} didMount () { this.extendState({ editorReady: true }) this.on('noteSelected', this.scrollTo, this) } render ($$) { // const { trackChangesView } = this.state // const canToggleTrackChanges = this.canToggleTrackChanges() const el = $$('div').addClass('sc-prose-editor') // left side: editor and toolbar let toolbar = this._renderToolbar($$) let toolbarLeft = this._renderToolbarLeft($$) let editor = this._renderEditor($$) let SplitPane = this.componentRegistry.get('split-pane') let ScrollPane = this.componentRegistry.get('scroll-pane') let Overlay = this.componentRegistry.get('overlay') // TODO -- unnecessary // posssibly breaks book builder dnd let ContextMenu = this.componentRegistry.get('context-menu') // new what does it do? // let Dropzones = this.componentRegistry.get('dropzones') // new what does it do? const notesEditorProps = { book: this.props.book, comments: this.props.fragment.comments, containerId: 'notes', history: this.props.history, disabled: this.props.disabled, fragment: this.props.fragment, trackChanges: this.props.trackChanges, trackChangesView: this.state.trackChangesView, update: this.props.update, user: this.props.user } const footerNotes = $$(Notes, notesEditorProps).ref('footer-notes') // const props = { // book: this.props.book, // fragment: this.props.fragment, // history: this.props.history // } // const toc = $$(TableOfContents, props) var commentsPane = this.state.editorReady ? $$(Comments, { // TODO -- should probably remove the || {} comments: this.props.fragment.comments || {}, fragment: this.props.fragment, update: this.props.update, user: this.props.user }).addClass('sc-comments-pane') : $$('div') const editorWithComments = $$(SplitPane, { sizeA: '80%', splitType: 'vertical' }) .append( editor, commentsPane ) const sideNav = $$('div').addClass('sidenav').append(toolbarLeft) const contentPanel = $$(ScrollPane, { name: 'contentPanel', scrollbarPosition: 'right' }) .append(editorWithComments, $$(Overlay), $$(ContextMenu), sideNav ) .attr('id', 'content-panel') .ref('contentPanel') const contentPanelWithSplitPane = $$(SplitPane, { sizeA: '95%', splitType: 'vertical' }) .append( contentPanel, $$('div') ) const ToolbarWithEditor = $$(SplitPane, { splitType: 'horizontal' }) .append( toolbar, contentPanelWithSplitPane ) el.append( $$(SplitPane, { sizeA: '85%', splitType: 'horizontal' }) .append( ToolbarWithEditor, footerNotes ) ) const modal = $$(ModalWarning, { width: 'medium', textAlign: 'center' }) if (this.state.changesNotSaved) { return el.append(modal) } return el } // TODO -- leverage ProseEditor's this._renderToolbar maybe? _renderToolbar ($$) { let viewMode = this.props.disabled ? $$('span') .addClass('view-mode') .append('Editor is in Read-Only mode') : '' let commandStates = this.commandManager.getCommandStates() return $$('div') .addClass('se-toolbar-wrapper') .append( $$(Toolbar, { commandStates: commandStates, trackChanges: this.props.trackChanges, trackChangesView: this.state.trackChangesView, toolGroups: [ 'document', 'annotations', 'track-change-enable', 'track-change-toggle-view' ] }).ref('toolbar') ) .append(viewMode) } _renderToolbarLeft ($$) { let commandStates = this.commandManager.getCommandStates() return $$('div') .addClass('se-toolbar-wrapper') .append( $$(Toolbar, { commandStates: commandStates, trackChanges: this.props.trackChanges, trackChangesView: this.state.trackChangesView, toolGroups: ['text', 'default'] } ) .ref('toolbarLeft') ) } _renderEditor ($$) { const configurator = this.props.configurator const editing = this.props.disabled ? 'selection' : 'full' return $$(ContainerEditor, { disabled: this.props.disabled, editing: editing, editorSession: this.editorSession, commands: configurator.getSurfaceCommandNames(), containerId: 'body', spellcheck: 'native', textTypes: configurator.getTextTypes(), trackChanges: this.props.trackChanges, updateTrackChangesStatus: this.props.updateTrackChangesStatus, history: this.props.history, book: this.props.book }).ref('body') } getInitialState () { return { changesNotSaved: false, editorReady: false, trackChangesView: true } } canToggleTrackChanges () { const { user } = this.props const accepted = ['admin', 'production-editor', 'copy-editor'] return some(accepted, (role) => includes(user.roles, role)) } scrollTo (nodeId) { this.refs.contentPanel.scrollTo(nodeId) } // Modal funcionality changesNotSaved () { this.extendState({ changesNotSaved: true }) } closeModal () { this.extendState({ changesNotSaved: false }) } getChildContext () { const oldContext = super.getChildContext() const doc = this.doc // toc provider // const tocProvider = new TOCProvider(doc, { // containerId: this.props.containerId // }) // notes provider const notesProvider = new NotesProvider(doc, { notesEditorContext: '' }) // comments provider const commentsProvider = new CommentsProvider(doc, { commandManager: this.commandManager, comments: this.props.fragment.comments, containerId: this.props.containerId, controller: this, editorSession: this.editorSession, notesProvider: notesProvider, fragment: this.props.fragment, surfaceManager: this.surfaceManager, update: this.props.update }) // TODO -- do I need all of these? // track changes provider const trackChangesProvider = new TrackChangesProvider(doc, { commandManager: this.commandManager, containerId: this.props.containerId, controller: this, editorSession: this.editorSession, surfaceManager: this.surfaceManager, user: this.props.user }) // attach all to context return { ...oldContext, notesProvider, commentsProvider, trackChangesProvider } } dispose () { this.editorSession.dragManager.dispose() } } export default Editor