1
0
mirror of https://github.com/BoostIo/Boostnote synced 2025-12-13 09:46:22 +00:00

clean code

This commit is contained in:
Rokt33r
2016-05-03 15:41:11 +09:00
parent ea8e31561e
commit 10aae90ae2
15 changed files with 84 additions and 625 deletions

View File

@@ -22,7 +22,7 @@ class ModalBase extends React.Component {
render () { render () {
return ( return (
<div className={'ModalBase' + (this.state.isHidden ? ' hide' : '')}> <div className={'ModalBase' + (this.state.isHidden ? ' hide' : '')}>
<div onClick={e => this.close(e)} className='modalBack'/> <div onClick={(e) => this.close(e)} className='modalBack'/>
{this.state.component == null ? null : ( {this.state.component == null ? null : (
<this.state.component {...this.state.componentProps} close={this.close}/> <this.state.component {...this.state.componentProps} close={this.close}/>
)} )}

View File

@@ -2,10 +2,6 @@ import React, { PropTypes } from 'react'
import ReactDOM from 'react-dom' import ReactDOM from 'react-dom'
import moment from 'moment' import moment from 'moment'
import _ from 'lodash' import _ from 'lodash'
import {
switchFolder,
updateArticle
} from '../../actions'
import linkState from 'browser/lib/linkState' import linkState from 'browser/lib/linkState'
import TagSelect from 'browser/components/TagSelect' import TagSelect from 'browser/components/TagSelect'
import ModeSelect from 'browser/components/ModeSelect' import ModeSelect from 'browser/components/ModeSelect'
@@ -67,25 +63,25 @@ export default class ArticleDetail extends React.Component {
constructor (props) { constructor (props) {
super(props) super(props)
this.deleteHandler = e => { this.deleteHandler = (e) => {
if (isModalOpen()) return true if (isModalOpen()) return true
this.handleDeleteButtonClick() this.handleDeleteButtonClick()
} }
this.uncacheHandler = e => { this.uncacheHandler = (e) => {
if (isModalOpen()) return true if (isModalOpen()) return true
this.handleUncache() this.handleUncache()
} }
this.titleHandler = e => { this.titleHandler = (e) => {
if (isModalOpen()) return true if (isModalOpen()) return true
if (this.refs.title) { if (this.refs.title) {
this.focusTitle() this.focusTitle()
} }
} }
this.editHandler = e => { this.editHandler = (e) => {
if (isModalOpen()) return true if (isModalOpen()) return true
if (this.refs.editor) this.refs.editor.switchEditMode() if (this.refs.editor) this.refs.editor.switchEditMode()
} }
this.previewHandler = e => { this.previewHandler = (e) => {
if (isModalOpen()) return true if (isModalOpen()) return true
if (this.refs.editor) this.refs.editor.switchPreviewMode() if (this.refs.editor) this.refs.editor.switchPreviewMode()
} }
@@ -100,7 +96,7 @@ export default class ArticleDetail extends React.Component {
componentDidMount () { componentDidMount () {
this.refreshTimer = setInterval(() => this.forceUpdate(), 60 * 1000) this.refreshTimer = setInterval(() => this.forceUpdate(), 60 * 1000)
this.shareDropdownInterceptor = e => { this.shareDropdownInterceptor = (e) => {
e.stopPropagation() e.stopPropagation()
} }
@@ -159,12 +155,12 @@ export default class ArticleDetail extends React.Component {
updatedAt: new Date() updatedAt: new Date()
}) })
dispatch(updateArticle(article)) // dispatch(updateArticle(article))
let targetFolderKey = e.target.value let targetFolderKey = e.target.value
if (status.targetFolders.length > 0) { if (status.targetFolders.length > 0) {
let targetFolder = _.findWhere(folders, {key: targetFolderKey}) let targetFolder = _.findWhere(folders, {key: targetFolderKey})
dispatch(switchFolder(targetFolder.name)) // dispatch(switchFolder(targetFolder.name))
} }
} }
@@ -174,7 +170,7 @@ export default class ArticleDetail extends React.Component {
title: e.target.value, title: e.target.value,
updatedAt: new Date() updatedAt: new Date()
}) })
dispatch(updateArticle(article)) // dispatch(updateArticle(article))
} }
handleTagsChange (newTag, tags) { handleTagsChange (newTag, tags) {
@@ -184,7 +180,7 @@ export default class ArticleDetail extends React.Component {
updatedAt: new Date() updatedAt: new Date()
}) })
dispatch(updateArticle(article)) // dispatch(updateArticle(article))
} }
handleModeChange (value) { handleModeChange (value) {
@@ -194,7 +190,7 @@ export default class ArticleDetail extends React.Component {
updatedAt: new Date() updatedAt: new Date()
}) })
dispatch(updateArticle(article)) // dispatch(updateArticle(article))
this.switchEditMode() this.switchEditMode()
} }
@@ -206,7 +202,7 @@ export default class ArticleDetail extends React.Component {
updatedAt: new Date() updatedAt: new Date()
}) })
dispatch(updateArticle(article)) // dispatch(updateArticle(article))
} }
} }
@@ -254,7 +250,7 @@ export default class ArticleDetail extends React.Component {
render () { render () {
let { folders, status, tags, activeArticle, modified, user } = this.props let { folders, status, tags, activeArticle, modified, user } = this.props
if (activeArticle == null) return this.renderEmpty() if (activeArticle == null) return this.renderEmpty()
let folderOptions = folders.map(folder => { let folderOptions = folders.map((folder) => {
return ( return (
<option key={folder.key} value={folder.key}>{folder.name}</option> <option key={folder.key} value={folder.key}>{folder.name}</option>
) )
@@ -269,7 +265,7 @@ export default class ArticleDetail extends React.Component {
<select <select
className='ArticleDetail-info-folder' className='ArticleDetail-info-folder'
value={activeArticle.FolderKey} value={activeArticle.FolderKey}
onChange={e => this.handleFolderKeyChange(e)} onChange={(e) => this.handleFolderKeyChange(e)}
> >
{folderOptions} {folderOptions}
</select> </select>
@@ -282,25 +278,14 @@ export default class ArticleDetail extends React.Component {
/> />
<div className='ArticleDetail-info-control'> <div className='ArticleDetail-info-control'>
{/*<div className={'ArticleDetail-info-control-save' + (!isUnsaved ? ' hide' : '')}>
<button
onClick={e => this.handleSaveButtonClick(e)}
className='ArticleDetail-info-control-save-button'
disabled={!isUnsaved}
>
<i className='fa fa-fw fa-save'/>&nbsp;Save
<span className='tooltip' children={`Save Post (${OSX ? '⌘' : '^'} + S)`}/>
</button>
</div>*/}
<ShareButton <ShareButton
article={activeArticle} article={activeArticle}
user={user} user={user}
/> />
<button className='ArticleDetail-info-control-delete-button' onClick={e => this.handleOthersButtonClick(e)}> <button className='ArticleDetail-info-control-delete-button' onClick={(e) => this.handleOthersButtonClick(e)}>
<i className='fa fa-fw fa-trash'/> <i className='fa fa-fw fa-trash'/>
<span className='tooltip' children={`Delete Post (^ + Del)`}/> <span className='tooltip'>Delete Post (^ + Del)</span>
</button> </button>
</div> </div>
</div> </div>
@@ -319,11 +304,11 @@ export default class ArticleDetail extends React.Component {
<div className='ArticleDetail-panel-header'> <div className='ArticleDetail-panel-header'>
<div className='ArticleDetail-panel-header-title'> <div className='ArticleDetail-panel-header-title'>
<input <input
onKeyDown={e => this.handleTitleKeyDown(e)} onKeyDown={(e) => this.handleTitleKeyDown(e)}
placeholder='(Untitled)' placeholder='(Untitled)'
ref='title' ref='title'
value={activeArticle.title} value={activeArticle.title}
onChange={e => this.handleTitleChange(e)} onChange={(e) => this.handleTitleChange(e)}
style={{ style={{
fontFamily: this.state.fontFamily fontFamily: this.state.fontFamily
}} }}
@@ -331,8 +316,8 @@ export default class ArticleDetail extends React.Component {
</div> </div>
<ModeSelect <ModeSelect
ref='mode' ref='mode'
onChange={e => this.handleModeChange(e)} onChange={(e) => this.handleModeChange(e)}
onKeyDown={e => this.handleModeSelectKeyDown(e)} onKeyDown={(e) => this.handleModeSelectKeyDown(e)}
value={activeArticle.mode} value={activeArticle.mode}
className='ArticleDetail-panel-header-mode' className='ArticleDetail-panel-header-mode'
/> />
@@ -341,7 +326,7 @@ export default class ArticleDetail extends React.Component {
<ArticleEditor <ArticleEditor
ref='editor' ref='editor'
article={activeArticle} article={activeArticle}
onChange={content => this.handleContentChange(content)} onChange={(content) => this.handleContentChange(content)}
/> />
</div> </div>
</div> </div>
@@ -351,11 +336,6 @@ export default class ArticleDetail extends React.Component {
ArticleDetail.propTypes = { ArticleDetail.propTypes = {
dispatch: PropTypes.func, dispatch: PropTypes.func,
status: PropTypes.shape(), repositories: PropTypes.array
tags: PropTypes.array,
user: PropTypes.shape(),
folders: PropTypes.array,
modified: PropTypes.array,
activeArticle: PropTypes.shape()
} }
ArticleDetail.prototype.linkState = linkState ArticleDetail.prototype.linkState = linkState

View File

@@ -2,7 +2,6 @@ import React, { PropTypes } from 'react'
import ReactDOM from 'react-dom' import ReactDOM from 'react-dom'
import ModeIcon from 'browser/components/ModeIcon' import ModeIcon from 'browser/components/ModeIcon'
import moment from 'moment' import moment from 'moment'
import { switchArticle } from '../actions'
import FolderMark from 'browser/components/FolderMark' import FolderMark from 'browser/components/FolderMark'
import TagLink from './TagLink' import TagLink from './TagLink'
import _ from 'lodash' import _ from 'lodash'
@@ -15,7 +14,7 @@ export default class ArticleList extends React.Component {
constructor (props) { constructor (props) {
super(props) super(props)
this.focusHandler = e => this.focus() this.focusHandler = (e) => this.focus()
} }
componentDidMount () { componentDidMount () {
@@ -30,8 +29,8 @@ export default class ArticleList extends React.Component {
} }
componentDidUpdate () { componentDidUpdate () {
let { articles, activeArticle } = this.props return false
var index = articles.indexOf(activeArticle) var index = articles.indexOf(null)
var el = ReactDOM.findDOMNode(this) var el = ReactDOM.findDOMNode(this)
var li = el.querySelectorAll('.ArticleList>div')[index] var li = el.querySelectorAll('.ArticleList>div')[index]
@@ -130,16 +129,12 @@ export default class ArticleList extends React.Component {
} }
render () { render () {
let { articles, modified, activeArticle, folders } = this.props let articles = []
let folders = []
let articleElements = articles.map(article => { let articleElements = articles.map((article) => {
let modifiedArticle = _.findWhere(modified, {key: article.key})
let originalArticle = article let originalArticle = article
if (modifiedArticle) {
article = Object.assign({}, article)
}
let tagElements = Array.isArray(article.tags) && article.tags.length > 0 let tagElements = Array.isArray(article.tags) && article.tags.length > 0
? article.tags.slice().map(tag => { ? article.tags.slice().map((tag) => {
return (<TagLink key={tag} tag={tag}/>) return (<TagLink key={tag} tag={tag}/>)
}) })
: (<span>Not tagged yet</span>) : (<span>Not tagged yet</span>)
@@ -153,27 +148,21 @@ export default class ArticleList extends React.Component {
return ( return (
<div key={'article-' + article.key}> <div key={'article-' + article.key}>
<div onClick={e => this.handleArticleClick(article)(e)} className={'ArticleList-item' + (activeArticle.key === article.key ? ' active' : '')}> <div onClick={(e) => this.handleArticleClick(article)(e)} className={'ArticleList-item' + (article.key === 'ACTIVE_POST_KEY' ? ' active' : '')}>
<div className='ArticleList-item-top'> <div className='ArticleList-item-top'>
{folder != null {folder != null
? folderChanged ? folderChanged
? <span className='folderName'> ? <span className='folderName'>
<FolderMark color={originalFolder.color}/>{originalFolder.name} <FolderMark color={originalFolder.color}/>{originalFolder.name}
-> ->
<FolderMark color={folder.color}/>{folder.name} <FolderMark color={folder.color}/>{folder.name}
</span> </span>
: <span className='folderName'> : <span className='folderName'>
<FolderMark color={folder.color}/>{folder.name} <FolderMark color={folder.color}/>{folder.name}
</span> </span>
: <span><FolderMark color={-1}/>Unknown</span> : <span><FolderMark color={-1}/>Unknown</span>
} }
<span className='updatedAt' <span className='updatedAt'>{moment(article.updatedAt).fromNow()}</span>
children={
modifiedArticle != null
? <span><span className='unsaved-mark'></span> Unsaved</span>
: moment(article.updatedAt).fromNow()
}
/>
</div> </div>
<div className='ArticleList-item-middle'> <div className='ArticleList-item-middle'>
<ModeIcon className='mode' mode={article.mode}/> <div className='title' children={title}/> <ModeIcon className='mode' mode={article.mode}/> <div className='title' children={title}/>
@@ -191,7 +180,7 @@ export default class ArticleList extends React.Component {
}) })
return ( return (
<div tabIndex='3' onKeyDown={e => this.handleArticleListKeyDown(e)} className='ArticleList'> <div tabIndex='3' onKeyDown={(e) => this.handleArticleListKeyDown(e)} className='ArticleList'>
{articleElements} {articleElements}
</div> </div>
) )
@@ -200,8 +189,5 @@ export default class ArticleList extends React.Component {
ArticleList.propTypes = { ArticleList.propTypes = {
dispatch: PropTypes.func, dispatch: PropTypes.func,
folders: PropTypes.array, repositories: PropTypes.array
articles: PropTypes.array,
modified: PropTypes.array,
activeArticle: PropTypes.shape()
} }

View File

@@ -1,13 +1,10 @@
import React, { PropTypes } from 'react' import React, { PropTypes } from 'react'
import ReactDOM from 'react-dom' import ReactDOM from 'react-dom'
import ExternalLink from 'browser/components/ExternalLink' import ExternalLink from 'browser/components/ExternalLink'
import { setSearchFilter, clearSearch, toggleTutorial, saveArticle, switchFolder } from '../actions'
import { isModalOpen } from 'browser/lib/modal' import { isModalOpen } from 'browser/lib/modal'
import keygen from 'browser/lib/keygen'
import activityRecord from 'browser/lib/activityRecord' import activityRecord from 'browser/lib/activityRecord'
const electron = require('electron') const electron = require('electron')
const remote = electron.remote
const ipc = electron.ipcRenderer const ipc = electron.ipcRenderer
const OSX = global.process.platform === 'darwin' const OSX = global.process.platform === 'darwin'
@@ -83,7 +80,7 @@ export default class ArticleTopBar extends React.Component {
this.setState({isLinksDropdownOpen: true}) this.setState({isLinksDropdownOpen: true})
} }
} }
this.linksButton.addEventListener('click', this.showLinksDropdown) // this.linksButton.addEventListener('click', this.showLinksDropdown)
this.hideLinksDropdown = e => { this.hideLinksDropdown = e => {
if (this.state.isLinksDropdownOpen) { if (this.state.isLinksDropdownOpen) {
this.setState({isLinksDropdownOpen: false}) this.setState({isLinksDropdownOpen: false})
@@ -118,11 +115,6 @@ export default class ArticleTopBar extends React.Component {
} }
escape () { escape () {
let { status, dispatch } = this.props
if (status.search.length > 0) {
dispatch(clearSearch())
return
}
} }
focusInput () { focusInput () {
@@ -136,7 +128,7 @@ export default class ArticleTopBar extends React.Component {
handleSearchChange (e) { handleSearchChange (e) {
let { dispatch } = this.props let { dispatch } = this.props
dispatch(setSearchFilter(e.target.value)) // dispatch(setSearchFilter(e.target.value))
this.handleTooltipRequest() this.handleTooltipRequest()
} }
@@ -146,35 +138,13 @@ export default class ArticleTopBar extends React.Component {
} }
handleNewPostButtonClick (e) { handleNewPostButtonClick (e) {
let { dispatch, folders, status } = this.props
let { targetFolders } = status
let isFolderFilterApplied = targetFolders.length > 0
let FolderKey = isFolderFilterApplied
? targetFolders[0].key
: folders[0].key
let newArticle = {
key: keygen(),
title: '',
content: '',
mode: 'markdown',
tags: [],
FolderKey: FolderKey,
craetedAt: new Date(),
updatedAt: new Date()
}
dispatch(saveArticle(newArticle.key, newArticle, true))
if (isFolderFilterApplied) dispatch(switchFolder(targetFolders[0].name))
remote.getCurrentWebContents().send('detail-title')
activityRecord.emit('ARTICLE_CREATE') activityRecord.emit('ARTICLE_CREATE')
} }
handleTutorialButtonClick (e) { handleTutorialButtonClick (e) {
let { dispatch } = this.props let { dispatch } = this.props
dispatch(toggleTutorial()) // dispatch(toggleTutorial())
} }
render () { render () {
@@ -186,16 +156,16 @@ export default class ArticleTopBar extends React.Component {
<i className='fa fa-search fa-fw' /> <i className='fa fa-search fa-fw' />
<input <input
ref='searchInput' ref='searchInput'
onFocus={e => this.handleSearchChange(e)} onFocus={(e) => this.handleSearchChange(e)}
onBlur={e => this.handleSearchChange(e)} onBlur={(e) => this.handleSearchChange(e)}
value={this.props.status.search} value={'this.props.status.search'}
onChange={e => this.handleSearchChange(e)} onChange={(e) => this.handleSearchChange(e)}
placeholder='Search' placeholder='Search'
type='text' type='text'
/> />
{ {
this.props.status.search != null && this.props.status.search.length > 0 'sadf' > 0
? <button onClick={e => this.handleSearchClearButton(e)} className='ArticleTopBar-left-search-clear-button'><i className='fa fa-times'/></button> ? <button onClick={(e) => this.handleSearchClearButton(e)} className='ArticleTopBar-left-search-clear-button'><i className='fa fa-times'/></button>
: null : null
} }
<div className={'tooltip' + (this.state.isTooltipHidden ? ' hide' : '')}> <div className={'tooltip' + (this.state.isTooltipHidden ? ' hide' : '')}>
@@ -207,19 +177,16 @@ export default class ArticleTopBar extends React.Component {
</div> </div>
</div> </div>
{status.isTutorialOpen ? searchTutorialElement : null}
<div className={'ArticleTopBar-left-control'}> <div className={'ArticleTopBar-left-control'}>
<button className='ArticleTopBar-left-control-new-post-button' onClick={e => this.handleNewPostButtonClick(e)}> <button className='ArticleTopBar-left-control-new-post-button' onClick={(e) => this.handleNewPostButtonClick(e)}>
<i className='fa fa-plus'/> <i className='fa fa-plus'/>
<span className='tooltip'>New Post ({OSX ? '⌘' : '^'} + n)</span> <span className='tooltip'>New Post ({OSX ? '⌘' : '^'} + n)</span>
</button> </button>
{status.isTutorialOpen ? newPostTutorialElement : null}
</div> </div>
</div> </div>
<div className='ArticleTopBar-right'> <div className='ArticleTopBar-right'>
<button onClick={e => this.handleTutorialButtonClick(e)}>?<span className='tooltip'>How to use</span> <button onClick={(e) => this.handleTutorialButtonClick(e)}>?<span className='tooltip'>How to use</span>
</button> </button>
<a ref='links' className='ArticleTopBar-right-links-button' href> <a ref='links' className='ArticleTopBar-right-links-button' href>
<img src='../resources/app.png' width='44' height='44'/> <img src='../resources/app.png' width='44' height='44'/>
@@ -240,9 +207,9 @@ export default class ArticleTopBar extends React.Component {
} }
</div> </div>
{status.isTutorialOpen ? ( {false ? (
<div className='tutorial'> <div className='tutorial'>
<div onClick={e => this.handleTutorialButtonClick(e)} className='clickJammer'/> <div onClick={(e) => this.handleTutorialButtonClick(e)} className='clickJammer'/>
<svg width='500' height='250' className='finder'> <svg width='500' height='250' className='finder'>
<text x='100' y='25' fontSize='32' fill={BRAND_COLOR}>Also, you can open Finder!!</text> <text x='100' y='25' fontSize='32' fill={BRAND_COLOR}>Also, you can open Finder!!</text>
<text x='150' y='55' fontSize='18' fill={BRAND_COLOR} children={'with pressing ' + (OSX ? '`⌘ + Alt + s`' : '`Win + Alt + s`')}/> <text x='150' y='55' fontSize='18' fill={BRAND_COLOR} children={'with pressing ' + (OSX ? '`⌘ + Alt + s`' : '`Win + Alt + s`')}/>

View File

@@ -1,14 +1,11 @@
import React, { PropTypes } from 'react' import React, { PropTypes } from 'react'
import store from '../store'
import { setTagFilter } from '../actions'
export default class TagLink extends React.Component { export default class TagLink extends React.Component {
handleClick (e) { handleClick (e) {
store.dispatch(setTagFilter(this.props.tag))
} }
render () { render () {
return ( return (
<a onClick={e => this.handleClick(e)}>{this.props.tag}</a> <a onClick={(e) => this.handleClick(e)}>{this.props.tag}</a>
) )
} }
} }

View File

@@ -1,41 +0,0 @@
import React, { Component, PropTypes } from 'react'
import { Link } from 'react-router'
import ProfileImage from 'browser/components/ProfileImage'
export default class UserNavigator extends Component {
renderUserList () {
if (this.props.users == null) return null
var users = this.props.users.map((user, index) => (
<li key={'user-' + user.id}>
<Link to={'/users/' + user.id} activeClassName='active'>
<ProfileImage email={user.email} size='44'/>
<div className='userTooltip'>{user.name}</div>
{index < 9 ? <div className='keyLabel'>{'⌘' + (index + 1)}</div> : null}
</Link>
</li>
))
return (
<ul className='userList'>
{users}
</ul>
)
}
render () {
return (
<div className='UserNavigator'>
{this.renderUserList()}
<button className='createTeamBtn'>
+
<div className='tooltip'>Create a new team</div>
</button>
</div>
)
}
}
UserNavigator.propTypes = {
users: PropTypes.array
}

View File

@@ -19,26 +19,10 @@ export default class MainContainer extends React.Component {
ipc.send('update-app', 'Deal with it.') ipc.send('update-app', 'Deal with it.')
} }
handleWheel (e) {
if (e.ctrlKey && global.process.platform !== 'darwin') {
if (window.document.body.style.zoom == null) {
window.document.body.style.zoom = 1
}
let zoom = Number(window.document.body.style.zoom)
if (e.deltaY > 0 && zoom < 4) {
document.body.style.zoom = zoom + 0.05
} else if (e.deltaY < 0 && zoom > 0.5) {
document.body.style.zoom = zoom - 0.05
}
}
}
render () { render () {
return ( return (
<div <div
className='Main' className='Main'
onWheel={(e) => this.handleWheel(e)}
> >
{this.state.updateAvailable ? ( {this.state.updateAvailable ? (
<button onClick={this.updateApp} className='appUpdateButton'><i className='fa fa-cloud-download'/> Update available!</button> <button onClick={this.updateApp} className='appUpdateButton'><i className='fa fa-cloud-download'/> Update available!</button>

View File

@@ -1,5 +1,5 @@
import { Provider } from 'react-redux' import { Provider } from 'react-redux'
import MainPage from './MainPage' import Main from './Main'
import store from './store' import store from './store'
import React from 'react' import React from 'react'
import ReactDOM from 'react-dom' import ReactDOM from 'react-dom'
@@ -76,7 +76,7 @@ let el = document.getElementById('content')
ReactDOM.render(( ReactDOM.render((
<div> <div>
<Provider store={store}> <Provider store={store}>
<MainPage/> <Main/>
</Provider> </Provider>
</div> </div>
), el, function () { ), el, function () {

View File

@@ -1,7 +1,6 @@
import React, { PropTypes } from 'react' import React, { PropTypes } from 'react'
import ReactDOM from 'react-dom' import ReactDOM from 'react-dom'
import linkState from 'browser/lib/linkState' import linkState from 'browser/lib/linkState'
import { createFolder } from '../actions'
import store from '../store' import store from '../store'
import FolderMark from 'browser/components/FolderMark' import FolderMark from 'browser/components/FolderMark'
@@ -34,7 +33,7 @@ export default class CreateNewFolder extends React.Component {
color color
} }
try { try {
store.dispatch(createFolder(input)) // store.dispatch(createFolder(input))
} catch (e) { } catch (e) {
this.setState({alert: { this.setState({alert: {
type: 'error', type: 'error',
@@ -47,7 +46,7 @@ export default class CreateNewFolder extends React.Component {
} }
handleColorClick (colorIndex) { handleColorClick (colorIndex) {
return e => { return (e) => {
this.setState({ this.setState({
color: colorIndex color: colorIndex
}) })
@@ -63,20 +62,20 @@ export default class CreateNewFolder extends React.Component {
render () { render () {
let alert = this.state.alert let alert = this.state.alert
let alertElement = alert != null ? ( let alertElement = alert != null ? (
<p className={`alert ${alert.type}`}> <p className={`alert ${alert.type}`}>
{alert.message} {alert.message}
</p> </p>
) : null ) : null
let colorIndexes = [] let colorIndexes = []
for (let i = 0; i < 8; i++) { for (let i = 0; i < 8; i++) {
colorIndexes.push(i) colorIndexes.push(i)
} }
let colorElements = colorIndexes.map(index => { let colorElements = colorIndexes.map((index) => {
let className = 'option' let className = 'option'
if (index === this.state.color) className += ' active' if (index === this.state.color) className += ' active'
return ( return (
<span className={className} key={index} onClick={e => this.handleColorClick(index)(e)}> <span className={className} key={index} onClick={(e) => this.handleColorClick(index)(e)}>
<FolderMark color={index}/> <FolderMark color={index}/>
</span> </span>
) )
@@ -84,17 +83,17 @@ export default class CreateNewFolder extends React.Component {
return ( return (
<div className='CreateNewFolder modal'> <div className='CreateNewFolder modal'>
<button onClick={e => this.handleCloseButton(e)} className='closeBtn'><i className='fa fa-fw fa-times'/></button> <button onClick={(e) => this.handleCloseButton(e)} className='closeBtn'><i className='fa fa-fw fa-times'/></button>
<div className='title'>Create new folder</div> <div className='title'>Create new folder</div>
<input ref='folderName' onKeyDown={e => this.handleKeyDown(e)} className='ipt' type='text' valueLink={this.linkState('name')} placeholder='Enter folder name'/> <input ref='folderName' onKeyDown={(e) => this.handleKeyDown(e)} className='ipt' type='text' valueLink={this.linkState('name')} placeholder='Enter folder name'/>
<div className='colorSelect'> <div className='colorSelect'>
{colorElements} {colorElements}
</div> </div>
{alertElement} {alertElement}
<button onClick={e => this.handleConfirmButton(e)} className='confirmBtn'>Create</button> <button onClick={(e) => this.handleConfirmButton(e)} className='confirmBtn'>Create</button>
</div> </div>
) )
} }

View File

@@ -1,7 +1,6 @@
import React, { PropTypes } from 'react' import React, { PropTypes } from 'react'
import ReactDOM from 'react-dom' import ReactDOM from 'react-dom'
import store from '../store' import store from '../store'
import { destroyArticle } from '../actions'
const electron = require('electron') const electron = require('electron')
const ipc = electron.ipcRenderer const ipc = electron.ipcRenderer
@@ -10,7 +9,7 @@ export default class DeleteArticleModal extends React.Component {
constructor (props) { constructor (props) {
super(props) super(props)
this.confirmHandler = e => this.handleYesButtonClick() this.confirmHandler = (e) => this.handleYesButtonClick()
} }
componentDidMount () { componentDidMount () {
@@ -27,7 +26,7 @@ export default class DeleteArticleModal extends React.Component {
} }
handleYesButtonClick (e) { handleYesButtonClick (e) {
store.dispatch(destroyArticle(this.props.articleKey)) // store.dispatch(destroyArticle(this.props.articleKey))
this.props.close() this.props.close()
} }
@@ -39,8 +38,8 @@ export default class DeleteArticleModal extends React.Component {
<div className='message'>Do you really want to delete?</div> <div className='message'>Do you really want to delete?</div>
<div className='control'> <div className='control'>
<button ref='no' onClick={e => this.handleNoButtonClick(e)}><i className='fa fa-fw fa-close'/> No</button> <button ref='no' onClick={(e) => this.handleNoButtonClick(e)}><i className='fa fa-fw fa-close'/> No</button>
<button ref='yes' onClick={e => this.handleYesButtonClick(e)} className='danger'><i className='fa fa-fw fa-check'/> Yes</button> <button ref='yes' onClick={(e) => this.handleYesButtonClick(e)} className='danger'><i className='fa fa-fw fa-check'/> Yes</button>
</div> </div>
</div> </div>
) )

View File

@@ -1,6 +1,5 @@
import React, { PropTypes } from 'react' import React, { PropTypes } from 'react'
import linkState from 'browser/lib/linkState' import linkState from 'browser/lib/linkState'
import { updateUser } from '../../actions'
import fetchConfig from 'browser/lib/fetchConfig' import fetchConfig from 'browser/lib/fetchConfig'
import hljsTheme from 'browser/lib/hljsThemes' import hljsTheme from 'browser/lib/hljsThemes'
@@ -38,7 +37,7 @@ export default class AppSettingTab extends React.Component {
message: 'Successfully done!' message: 'Successfully done!'
}}) }})
} }
this.handleSettingError = err => { this.handleSettingError = (err) => {
this.setState({keymapAlert: { this.setState({keymapAlert: {
type: 'error', type: 'error',
message: err.message != null ? err.message : 'Error occurs!' message: err.message != null ? err.message : 'Error occurs!'

View File

@@ -2,7 +2,6 @@ import React, { PropTypes } from 'react'
import linkState from 'browser/lib/linkState' import linkState from 'browser/lib/linkState'
import FolderMark from 'browser/components/FolderMark' import FolderMark from 'browser/components/FolderMark'
import store from '../../store' import store from '../../store'
import { updateFolder, destroyFolder, replaceFolder } from '../../actions'
const IDLE = 'IDLE' const IDLE = 'IDLE'
const EDIT = 'EDIT' const EDIT = 'EDIT'
@@ -20,14 +19,14 @@ export default class FolderRow extends React.Component {
handleUpClick (e) { handleUpClick (e) {
let { index } = this.props let { index } = this.props
if (index > 0) { if (index > 0) {
store.dispatch(replaceFolder(index, index - 1)) // store.dispatch(replaceFolder(index, index - 1))
} }
} }
handleDownClick (e) { handleDownClick (e) {
let { index, count } = this.props let { index, count } = this.props
if (index < count - 1) { if (index < count - 1) {
store.dispatch(replaceFolder(index, index + 1)) // store.dispatch(replaceFolder(index, index + 1))
} }
} }
@@ -82,7 +81,7 @@ export default class FolderRow extends React.Component {
folder = Object.assign({}, folder, input) folder = Object.assign({}, folder, input)
try { try {
store.dispatch(updateFolder(folder)) // store.dispatch(updateFolder(folder))
this.setState({ this.setState({
mode: IDLE mode: IDLE
}) })
@@ -98,7 +97,7 @@ export default class FolderRow extends React.Component {
handleDeleteConfirmButtonClick (e) { handleDeleteConfirmButtonClick (e) {
let { folder } = this.props let { folder } = this.props
store.dispatch(destroyFolder(folder.key)) // store.dispatch(destroyFolder(folder.key))
} }
render () { render () {
@@ -111,7 +110,7 @@ export default class FolderRow extends React.Component {
colorIndexes.push(i) colorIndexes.push(i)
} }
let colorOptions = colorIndexes.map(index => { let colorOptions = colorIndexes.map((index) => {
let className = this.state.color === index let className = this.state.color === index
? 'active' ? 'active'
: null : null
@@ -129,12 +128,10 @@ export default class FolderRow extends React.Component {
<FolderMark color={this.state.color}/> <FolderMark color={this.state.color}/>
</button> </button>
{this.state.isColorEditing {this.state.isColorEditing
? ( ? <div className='options'>
<div className='options'> <div className='label'>Color select</div>
<div className='label'>Color select</div> {colorOptions}
{colorOptions} </div>
</div>
)
: null : null
} }
</div> </div>

View File

@@ -1,7 +1,6 @@
import React, { PropTypes } from 'react' import React, { PropTypes } from 'react'
import FolderRow from './FolderRow' import FolderRow from './FolderRow'
import linkState from 'browser/lib/linkState' import linkState from 'browser/lib/linkState'
import { createFolder } from '../../actions'
export default class FolderSettingTab extends React.Component { export default class FolderSettingTab extends React.Component {
constructor (props) { constructor (props) {
@@ -23,9 +22,9 @@ export default class FolderSettingTab extends React.Component {
let { dispatch } = this.props let { dispatch } = this.props
try { try {
dispatch(createFolder({ // dispatch(createFolder({
name: this.state.name // name: this.state.name
})) // }))
} catch (e) { } catch (e) {
this.setState({alert: { this.setState({alert: {
type: 'error', type: 'error',

View File

@@ -1,362 +0,0 @@
import { combineReducers } from 'redux'
import _ from 'lodash'
import {
// Status action type
SWITCH_FOLDER,
SWITCH_ARTICLE,
SET_SEARCH_FILTER,
SET_TAG_FILTER,
CLEAR_SEARCH,
TOGGLE_TUTORIAL,
// user
USER_UPDATE,
// Article action type
ARTICLE_UPDATE,
ARTICLE_DESTROY,
ARTICLE_CACHE,
ARTICLE_UNCACHE,
ARTICLE_UNCACHE_ALL,
ARTICLE_SAVE,
ARTICLE_SAVE_ALL,
// Folder action type
FOLDER_CREATE,
FOLDER_UPDATE,
FOLDER_DESTROY,
FOLDER_REPLACE
} from './actions'
import dataStore from 'browser/lib/dataStore'
import keygen from 'browser/lib/keygen'
import activityRecord from 'browser/lib/activityRecord'
const initialStatus = {
search: '',
isTutorialOpen: false
}
let data = {
articles: [],
folders: []
}
let initialArticles = {
data: data && data.articles ? data.articles : [],
modified: []
}
let initialFolders = data && data.folders ? data.folders : []
let initialUser = {}
function user (state = initialUser, action) {
switch (action.type) {
case USER_UPDATE:
let updated = Object.assign(state, action.data)
dataStore.saveUser(null, updated)
return updated
default:
return state
}
}
function folders (state = initialFolders, action) {
state = state.slice()
switch (action.type) {
case FOLDER_CREATE:
{
let newFolder = action.data.folder
if (!_.isString(newFolder.name)) throw new Error('Folder name must be a string')
newFolder.name = newFolder.name.trim().replace(/\s/g, '_')
Object.assign(newFolder, {
key: keygen(),
createdAt: new Date(),
updatedAt: new Date()
})
if (newFolder.name == null || newFolder.name.length === 0) throw new Error('Folder name is required')
if (newFolder.name.match(/\//)) throw new Error('`/` is not available for folder name')
let conflictFolder = _.find(state, (folder) => folder.name.toLowerCase() === newFolder.name.toLowerCase())
if (conflictFolder != null) throw new Error(`${conflictFolder.name} already exists!`)
state.push(newFolder)
dataStore.setFolders(state)
activityRecord.emit('FOLDER_CREATE')
return state
}
case FOLDER_UPDATE:
{
let folder = action.data.folder
let targetFolder = _.findWhere(state, {key: folder.key})
if (!_.isString(folder.name)) throw new Error('Folder name must be a string')
folder.name = folder.name.trim().replace(/\s/g, '_')
if (folder.name.length === 0) throw new Error('Folder name is required')
if (folder.name.match(/\//)) throw new Error('`/` is not available for folder name')
// Folder existence check
if (targetFolder == null) throw new Error('Folder doesnt exist')
// Name conflict check
if (targetFolder.name !== folder.name) {
let conflictFolder = _.find(state, (_folder) => {
return folder.name.toLowerCase() === _folder.name.toLowerCase() && folder.key !== _folder.key
})
if (conflictFolder != null) throw new Error('Name conflicted')
}
Object.assign(targetFolder, folder, {
updatedAt: new Date()
})
dataStore.setFolders(state)
activityRecord.emit('FOLDER_UPDATE')
return state
}
case FOLDER_DESTROY:
{
if (state.length < 2) throw new Error('Folder must exist more than one')
let targetKey = action.data.key
let targetIndex = _.findIndex(state, (folder) => folder.key === targetKey)
if (targetIndex >= 0) {
state.splice(targetIndex, 1)
}
dataStore.setFolders(state)
activityRecord.emit('FOLDER_DESTROY')
return state
}
case FOLDER_REPLACE:
{
let { a, b } = action.data
let folderA = state[a]
let folderB = state[b]
state.splice(a, 1, folderB)
state.splice(b, 1, folderA)
}
dataStore.setFolders(state)
return state
default:
return state
}
}
function compareArticle (original, modified) {
var keys = _.keys(_.pick(modified, ['mode', 'title', 'tags', 'content', 'FolderKey']))
return keys.reduce((sum, key) => {
if ((key === 'tags' && !_.isEqual(original[key], modified[key])) || (key !== 'tags' && original[key] !== modified[key])) {
if (sum == null) {
sum = {
key: original.key
}
}
sum[key] = modified[key]
}
return sum
}, null)
}
function articles (state = initialArticles, action) {
switch (action.type) {
case ARTICLE_CACHE:
{
let modified = action.data.article
let targetKey = action.data.key
let originalIndex = _.findIndex(state.data, (_article) => targetKey === _article.key)
if (originalIndex === -1) return state
let modifiedIndex = _.findIndex(state.modified, (_article) => targetKey === _article.key)
modified = compareArticle(state.data[originalIndex], modified)
if (modified == null) {
if (modifiedIndex !== -1) state.modified.splice(modifiedIndex, 1)
return state
}
if (modifiedIndex === -1) state.modified.push(modified)
else Object.assign(state.modified[modifiedIndex], modified)
return state
}
case ARTICLE_UNCACHE:
{
let targetKey = action.data.key
let modifiedIndex = _.findIndex(state.modified, _article => targetKey === _article.key)
if (modifiedIndex >= 0) state.modified.splice(modifiedIndex, 1)
return state
}
case ARTICLE_UNCACHE_ALL:
state.modified = []
return state
case ARTICLE_SAVE:
{
let targetKey = action.data.key
let override = action.data.article
let modifiedIndex = _.findIndex(state.modified, _article => targetKey === _article.key)
let modified = modifiedIndex !== -1 ? state.modified.splice(modifiedIndex, 1)[0] : null
let targetIndex = _.findIndex(state.data, _article => targetKey === _article.key)
// Make a new if target article is not found.
if (targetIndex === -1) {
state.data.push(Object.assign({
title: '',
content: '',
mode: 'markdown',
tags: [],
craetedAt: new Date()
}, modified, override, {key: targetKey, updatedAt: new Date()}))
return state
}
Object.assign(state.data[targetIndex], modified, override, {key: targetKey, updatedAt: new Date()})
dataStore.setArticles(state.data)
return state
}
case ARTICLE_SAVE_ALL:
if (state.modified.length > 0) {
state.modified.forEach(modifiedArticle => {
let targetIndex = _.findIndex(state.data, _article => modifiedArticle.key === _article.key)
Object.assign(state.data[targetIndex], modifiedArticle, {key: modifiedArticle.key, updatedAt: new Date()})
})
}
state.modified = []
dataStore.setArticles(state.data)
return state
case ARTICLE_UPDATE:
{
let article = action.data.article
let targetIndex = _.findIndex(state.data, _article => article.key === _article.key)
if (targetIndex < 0) state.data.unshift(article)
else Object.assign(state.data[targetIndex], article)
dataStore.setArticles(state.data)
return state
}
case ARTICLE_DESTROY:
{
let articleKey = action.data.key
let targetIndex = _.findIndex(state.data, _article => articleKey === _article.key)
if (targetIndex >= 0) state.data.splice(targetIndex, 1)
let modifiedIndex = _.findIndex(state.modified, _article => articleKey === _article.key)
if (modifiedIndex >= 0) state.modified.splice(modifiedIndex, 1)
dataStore.setArticles(state.data)
return state
}
case FOLDER_DESTROY:
{
let folderKey = action.data.key
state.data = state.data.filter(article => article.FolderKey !== folderKey)
dataStore.setArticles(state.data)
return state
}
default:
return state
}
}
function status (state = initialStatus, action) {
state = Object.assign({}, state)
switch (action.type) {
case TOGGLE_TUTORIAL:
state.isTutorialOpen = !state.isTutorialOpen
return state
}
switch (action.type) {
case ARTICLE_SAVE:
if (action.data.forceSwitch) {
let article = action.data.article
state.articleKey = article.key
state.search = ''
}
return state
case SWITCH_FOLDER:
state.search = `\/\/${action.data} `
return state
case SWITCH_ARTICLE:
state.articleKey = action.data.key
return state
case SET_SEARCH_FILTER:
state.search = action.data
return state
case SET_TAG_FILTER:
state.search = `#${action.data}`
return state
case CLEAR_SEARCH:
state.search = ''
return state
default:
return state
}
}
/**
* v0.6.* Reducers
*/
/**
* Repositories
* ```
* repositories = [{
* key: String,
* name: String,
* path: String, // path of repository
* status: String, // status of repository [LOADING, IDLE, ERROR]
* folders: {
* name: String,
* color: String
* },
* notes: [{
* key: String,
* title: String,
* content: String,
* folder: String,
* tags: [String],
* createdAt: Date,
* updatedAt: Date
* }]
* }]
* ```
*/
import RepositoryManager from 'browser/lib/RepositoryManager'
const initialRepositories = RepositoryManager.getRepos()
function repositories (state = initialRepositories, action) {
switch (action.type) {
case 'ADD_REPOSITORY':
{
let repos = state.slice()
repos.push(action.data)
return repos
}
case 'REMOVE_REPOSITORY':
{
let repos = state.slice()
let targetIndex = _.findIndex(repos, {key: action.data.key})
if (targetIndex > -1) {
repos.splice(targetIndex, 1)
}
return repos
}
}
return state
}
// v0.6 end
export default combineReducers({
user,
folders,
articles,
status,
repositories
})

View File

@@ -106,48 +106,3 @@ textarea.block-input
&:hover &:hover
opacity 1 opacity 1
background-color lighten(brandColor, 10%) background-color lighten(brandColor, 10%)
.contactButton
position fixed
z-index 2000
bottom 5px
right 5px
padding 10px 15px
border none
border-radius 5px
background-color brandColor
color white
opacity 0.7
&:hover
opacity 1
background-color lighten(brandColor, 10%)
.tooltip
tooltip()
margin-top -22px
margin-left -107px
&:hover .tooltip
opacity 1
.OSSAnnounceModal
height 250
text-align center
.OSSAnnounceModal-title
font-size 32px
padding 45px 0
.OSSAnnounceModal-link
display block
font-size 20px
margin 25px 0 65px
.OSSAnnounceModal-closeBtn
display block
margin 0 auto
border none
border-radius 5px
width 150px
height 33px
background-color brandColor
color white
opacity 0.7
&:hover
opacity 1
background-color lighten(brandColor, 10%)