import React, { PropTypes } from 'react' import ReactDOM from 'react-dom' import moment from 'moment' import _ from 'lodash' import linkState from 'browser/lib/linkState' import TagSelect from 'browser/components/TagSelect' import ModeSelect from 'browser/components/ModeSelect' import ShareButton from './ShareButton' import { openModal, isModalOpen } from 'browser/lib/modal' import DeleteArticleModal from '../modals/DeleteArticleModal' import ArticleEditor from './ArticleEditor' const electron = require('electron') const ipc = electron.ipcRenderer import fetchConfig from 'browser/lib/fetchConfig' let config = fetchConfig() ipc.on('config-apply', function (e, newConfig) { config = newConfig }) const BRAND_COLOR = '#18AF90' const OSX = global.process.platform === 'darwin' const tagSelectTutorialElement = ( Attach some tags here! ) const modeSelectTutorialElement = ( Select code syntax!! ) export default class ArticleDetail extends React.Component { constructor (props) { super(props) this.deleteHandler = (e) => { if (isModalOpen()) return true this.handleDeleteButtonClick() } this.uncacheHandler = (e) => { if (isModalOpen()) return true this.handleUncache() } this.titleHandler = (e) => { if (isModalOpen()) return true if (this.refs.title) { this.focusTitle() } } this.editHandler = (e) => { if (isModalOpen()) return true if (this.refs.editor) this.refs.editor.switchEditMode() } this.previewHandler = (e) => { if (isModalOpen()) return true if (this.refs.editor) this.refs.editor.switchPreviewMode() } this.configApplyHandler = (e, config) => this.handleConfigApply(e, config) this.state = { article: Object.assign({content: ''}, props.activeArticle), openShareDropdown: false, fontFamily: config['editor-font-family'] } } componentDidMount () { this.refreshTimer = setInterval(() => this.forceUpdate(), 60 * 1000) this.shareDropdownInterceptor = (e) => { e.stopPropagation() } ipc.on('detail-delete', this.deleteHandler) ipc.on('detail-uncache', this.uncacheHandler) ipc.on('detail-title', this.titleHandler) ipc.on('detail-edit', this.editHandler) ipc.on('detail-preview', this.previewHandler) ipc.on('config-apply', this.configApplyHandler) } componentWillUnmount () { clearInterval(this.refreshTimer) ipc.removeListener('detail-delete', this.deleteHandler) ipc.removeListener('detail-uncache', this.uncacheHandler) ipc.removeListener('detail-title', this.titleHandler) ipc.removeListener('detail-edit', this.editHandler) ipc.removeListener('detail-preview', this.previewHandler) } componentDidUpdate (prevProps, prevState) { if (this.props.activeArticle == null || prevProps.activeArticle == null || this.props.activeArticle.key !== prevProps.activeArticle.key) { if (this.refs.editor) this.refs.editor.resetCursorPosition() } if (prevProps.activeArticle == null && this.props.activeArticle) { } } handleConfigApply (e, config) { this.setState({ fontFamily: config['editor-font-family'] }) } renderEmpty () { return (
{OSX ? 'Command(⌘)' : 'Ctrl(^)'} + N
to create a new post
) } handleOthersButtonClick (e) { this.deleteHandler() } handleFolderKeyChange (e) { let { dispatch, activeArticle, status, folders } = this.props let article = Object.assign({}, activeArticle, { FolderKey: e.target.value, updatedAt: new Date() }) // dispatch(updateArticle(article)) let targetFolderKey = e.target.value if (status.targetFolders.length > 0) { let targetFolder = _.findWhere(folders, {key: targetFolderKey}) // dispatch(switchFolder(targetFolder.name)) } } handleTitleChange (e) { let { dispatch, activeArticle } = this.props let article = Object.assign({}, activeArticle, { title: e.target.value, updatedAt: new Date() }) // dispatch(updateArticle(article)) } handleTagsChange (newTag, tags) { let { dispatch, activeArticle } = this.props let article = Object.assign({}, activeArticle, { tags: tags, updatedAt: new Date() }) // dispatch(updateArticle(article)) } handleModeChange (value) { let { dispatch, activeArticle } = this.props let article = Object.assign({}, activeArticle, { mode: value, updatedAt: new Date() }) // dispatch(updateArticle(article)) this.switchEditMode() } handleContentChange (value) { let { dispatch, activeArticle } = this.props if (activeArticle.content !== value) { let article = Object.assign({}, activeArticle, { content: value, updatedAt: new Date() }) // dispatch(updateArticle(article)) } } handleDeleteButtonClick (e) { if (this.props.activeArticle) { openModal(DeleteArticleModal, {articleKey: this.props.activeArticle.key}) } } handleTitleKeyDown (e) { if (e.keyCode === 9 && !e.shiftKey) { e.preventDefault() this.refs.mode.handleIdleSelectClick() } } handleModeSelectKeyDown (e) { if (e.keyCode === 9 && !e.shiftKey) { e.preventDefault() this.switchEditMode() } if (e.keyCode === 9 && e.shiftKey) { e.preventDefault() this.focusTitle() } if (e.keyCode === 27) { this.focusTitle() } } switchEditMode () { this.refs.editor.switchEditMode() } focusTitle () { if (this.refs.title) { let titleEl = ReactDOM.findDOMNode(this.refs.title) titleEl.focus() titleEl.select() } } render () { let { folders, status, tags, activeArticle, modified, user } = this.props if (activeArticle == null) return this.renderEmpty() let folderOptions = folders.map((folder) => { return ( ) }) let isUnsaved = !!_.findWhere(modified, {key: activeArticle.key}) return (
Unsaved : `Created : ${moment(activeArticle.createdAt).format('YYYY/MM/DD')} Updated : ${moment(activeArticle.updatedAt).format('YYYY/MM/DD')}` } />
this.handleTagsChange(tags, tag)} suggestTags={tags} /> {status.isTutorialOpen ? tagSelectTutorialElement : null}
this.handleTitleKeyDown(e)} placeholder='(Untitled)' ref='title' value={activeArticle.title} onChange={(e) => this.handleTitleChange(e)} style={{ fontFamily: this.state.fontFamily }} />
this.handleModeChange(e)} onKeyDown={(e) => this.handleModeSelectKeyDown(e)} value={activeArticle.mode} className='ArticleDetail-panel-header-mode' /> {status.isTutorialOpen ? modeSelectTutorialElement : null}
this.handleContentChange(content)} />
) } } ArticleDetail.propTypes = { dispatch: PropTypes.func, repositories: PropTypes.array } ArticleDetail.prototype.linkState = linkState