import React, { PropTypes } from 'react' import ReactDOM from 'react-dom' import moment from 'moment' import _ from 'lodash' import { switchFolder, updateArticle, // cacheArticle, // saveArticle, // uncacheArticle } from '../../actions' 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 '../../modal/DeleteArticleModal' import ArticleEditor from './ArticleEditor' const electron = require('electron') const ipc = electron.ipcRenderer const remote = electron.remote const { Menu, MenuItem } = remote // const othersMenu = new Menu() // othersMenu.append(new MenuItem({ // label: 'Delete Post', // click: function () { // remote.getCurrentWebContents().send('detail-delete') // } // })) // othersMenu.append(new MenuItem({ // label: 'Discard Change', // click: function (item) { // remote.getCurrentWebContents().send('detail-uncache') // } // })) const BRAND_COLOR = '#18AF90' const OSX = global.process.platform === 'darwin' const editDeleteTutorialElement = ( Edit / Delete a post press `e`/`d` ) const tagSelectTutorialElement = ( Attach some tags here! ) const modeSelectTutorialElement = ( Select code syntax!! ) export default class ArticleDetail extends React.Component { constructor (props) { super(props) this.saveHandler = e => { if (isModalOpen()) return true this.handleSaveButtonClick() } this.deleteHandler = e => { if (isModalOpen()) return true this.handleDeleteButtonClick() } this.uncacheHandler = e => { if (isModalOpen()) return true this.handleUncache() } this.togglePreviewHandler = e => { if (isModalOpen()) return true this.handleTogglePreviewButtonClick() } this.editHandler = e => { if (isModalOpen()) return true this.refs.editor.switchEditMode() } this.state = { article: Object.assign({content: ''}, props.activeArticle), previewMode: true, openShareDropdown: false } if (props.activeArticle != null && props.activeArticle.content.trim().length > 0 && props.activeArticle.mode === 'markdown') this.state.previewMode = true } componentDidMount () { this.refreshTimer = setInterval(() => this.forceUpdate(), 60 * 1000) this.shareDropdownInterceptor = e => { e.stopPropagation() } // ipc.on('detail-save', this.saveHandler) ipc.on('detail-delete', this.deleteHandler) ipc.on('detail-uncache', this.uncacheHandler) ipc.on('detail-toggle-preview', this.togglePreviewHandler) ipc.on('detail-edit', this.editHandler) } componentWillUnmount () { clearInterval(this.refreshTimer) // ipc.removeListener('detail-save', this.saveHandler) ipc.removeListener('detail-delete', this.deleteHandler) ipc.removeListener('detail-uncache', this.uncacheHandler) ipc.removeListener('detail-toggle-preview', this.togglePreviewHandler) ipc.removeListener('detail-edit', this.editHandler) } componentWillReceiveProps (nextProps) { let nextArticle = nextProps.activeArticle let nextModified = nextArticle != null ? _.findWhere(nextProps.modified, {key: nextArticle.key}) : null let article = Object.assign({content: ''}, nextProps.activeArticle, nextModified) let nextState = { article } this.setState(nextState) } editArticle () { ReactDOM.findDOMNode(this.refs.title).focus() ReactDOM.findDOMNode(this.refs.title).select() } cacheArticle () { let { dispatch, status, folders } = this.props let input = Object.assign({}, this.props.activeArticle.key, this.state.article, {updatedAt: new Date()}) dispatch(updateArticle(input)) let targetFolderKey = this.state.article.FolderKey if (status.targetFolders.length > 0) { let targetFolder = _.findWhere(folders, {key: targetFolderKey}) dispatch(switchFolder(targetFolder.name)) } } renderEmpty () { return (
Command(⌘) + N
to create a new post
) } handleSaveButtonClick (e) { // let { dispatch, folders, status } = this.props // let targetFolderKey = this.state.article.FolderKey // dispatch(saveArticle(this.props.activeArticle.key, this.state.article), true) // if (status.targetFolders.length > 0) { // let targetFolder = _.findWhere(folders, {key: targetFolderKey}) // dispatch(switchFolder(targetFolder.name)) // } } handleOthersButtonClick (e) { this.deleteHandler() } handleFolderKeyChange (e) { let article = this.state.article article.FolderKey = e.target.value this.setState({article: article}, () => this.cacheArticle()) } handleTitleChange (e) { let { article } = this.state article.title = e.target.value this.setState({ article }, () => this.cacheArticle()) } handleTagsChange (newTag, tags) { let article = this.state.article article.tags = tags this.setState({ article }, () => this.cacheArticle()) } handleModeChange (value) { let { article } = this.state article.mode = value this.setState({ article }, () => this.cacheArticle()) } handleContentChange (e, value) { let { article } = this.state article.content = value this.setState({ article }, () => this.cacheArticle()) } handleCodeEditorBlur (e) { if (this.state.article.mode === 'markdown' && !this.state.previewMode) { this.setState({ previewMode: true }) } } handleDeleteButtonClick (e) { if (this.props.activeArticle) { openModal(DeleteArticleModal, {articleKey: this.props.activeArticle.key}) } } handleUncache (e) { if (this.props.activeArticle) { let { dispatch, activeArticle } = this.props dispatch(uncacheArticle(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.refs.editor.switchEditMode() } if (e.keyCode === 9 && e.shiftKey) { e.preventDefault() ReactDOM.findDOMNode(this.refs.title).focus() } } 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(this.state.article.createdAt).format('YYYY/MM/DD')} Updated : ${moment(this.state.article.updatedAt).format('YYYY/MM/DD')}` } />
{/*
*/}
{status.isTutorialOpen ? editDeleteTutorialElement : null}
this.handleTagsChange(tags, tag)} suggestTags={tags} /> {status.isTutorialOpen ? tagSelectTutorialElement : null}
this.handleTitleKeyDown(e)} placeholder='(Untitled)' ref='title' value={this.state.article.title} onChange={e => this.handleTitleChange(e)} />
this.handleModeChange(e)} onKeyDown={e => this.handleModeSelectKeyDown(e)} value={this.state.article.mode} className='ArticleDetail-panel-header-mode' />
{status.isTutorialOpen ? modeSelectTutorialElement : null} this.handleContentChange(e, content)} />
) } } ArticleDetail.propTypes = { dispatch: PropTypes.func, status: PropTypes.shape(), tags: PropTypes.array, user: PropTypes.shape(), folders: PropTypes.array, modified: PropTypes.array, activeArticle: PropTypes.shape() } ArticleDetail.prototype.linkState = linkState