Skip to content

Commit

Permalink
Merge pull request #800 from asmsuechan/componentnize-NewNoteButton
Browse files Browse the repository at this point in the history
Componentnize NewNoteButton
  • Loading branch information
asmsuechan authored Aug 14, 2017
2 parents e5b6762 + a752730 commit f2a03e4
Show file tree
Hide file tree
Showing 4 changed files with 187 additions and 195 deletions.
68 changes: 68 additions & 0 deletions browser/main/NewNoteButton/NewNoteButton.styl
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
.root
position relative
background-color $ui-noteList-backgroundColor
height $topBar-height - 1
margin-left: auto;
width: 64px;
margin-right: -15px;

.root--expanded
@extend .root

$control-height = 34px

.control
position absolute
top 13px
left 8px
right 8px
height $control-height
overflow hidden
display flex

.control-newNoteButton
display block
width 32px
height $control-height - 2
navButtonColor()
font-size 16px
line-height 28px
padding 0
&:active
border-color $ui-button--active-backgroundColor
&:hover .control-newNoteButton-tooltip
opacity 1

.control-newNoteButton-tooltip
tooltip()
position fixed
pointer-events none
top 50px
left 433px
z-index 200
padding 5px
line-height normal
border-radius 2px
opacity 0
transition 0.1s

body[data-theme="dark"]
.root, .root--expanded
background-color $ui-dark-noteList-backgroundColor

.control
border-color $ui-dark-borderColor

.control-newNoteButton
color $ui-inactive-text-color
border-color $ui-dark-borderColor
background-color $ui-dark-noteList-backgroundColor
&:hover
transition 0.15s
color $ui-dark-text-color
&:active
background-color alpha($ui-dark-button--active-backgroundColor, 20%)
border-color $ui-dark-button--active-backgroundColor

.control-newNoteButton-tooltip
darkTooltip()
107 changes: 107 additions & 0 deletions browser/main/NewNoteButton/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import React, { PropTypes } from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './NewNoteButton.styl'
import _ from 'lodash'
import modal from 'browser/main/lib/modal'
import NewNoteModal from 'browser/main/modals/NewNoteModal'
import { hashHistory } from 'react-router'
import eventEmitter from 'browser/main/lib/eventEmitter'
import dataApi from 'browser/main/lib/dataApi'

const { remote } = require('electron')
const { dialog } = remote

const OSX = window.process.platform === 'darwin'

class NewNoteButton extends React.Component {
constructor (props) {
super(props)

this.state = {
}

this.newNoteHandler = () => {
this.handleNewNoteButtonClick()
}
}

componentDidMount () {
eventEmitter.on('top:new-note', this.newNoteHandler)
}

componentWillUnmount () {
eventEmitter.off('top:new-note', this.newNoteHandler)
}

handleNewNoteButtonClick (e) {
const { config, location, dispatch } = this.props
const { storage, folder } = this.resolveTargetFolder()

modal.open(NewNoteModal, {
storage: storage.key,
folder: folder.key,
dispatch,
location
})
}

resolveTargetFolder () {
const { data, params } = this.props
let storage = data.storageMap.get(params.storageKey)

// Find first storage
if (storage == null) {
for (let kv of data.storageMap) {
storage = kv[1]
break
}
}

if (storage == null) this.showMessageBox('No storage to create a note')
let folder = storage.folders[0]
folder = _.find(storage.folders, {key: params.folderKey})
if (folder == null) this.showMessageBox('No folder to create a note')

return {
storage,
folder
}
}

showMessageBox (message) {
dialog.showMessageBox(remote.getCurrentWindow(), {
type: 'warning',
message: message,
buttons: ['OK']
})
}

render () {
const { config, style } = this.props
return (
<div className='NewNoteButton'
styleName={config.isSideNavFolded ? 'root--expanded' : 'root'}
style={style}
>
<div styleName='control'>
<button styleName='control-newNoteButton'
onClick={(e) => this.handleNewNoteButtonClick(e)}>
<i className='fa fa-pencil-square-o' />
<span styleName='control-newNoteButton-tooltip'>
Make a Note {OSX ? '⌘' : '^'} + n
</span>
</button>
</div>
</div>
)
}
}

NewNoteButton.propTypes = {
dispatch: PropTypes.func,
config: PropTypes.shape({
isSideNavFolded: PropTypes.bool
})
}

export default CSSModules(NewNoteButton, styles)
156 changes: 12 additions & 144 deletions browser/main/TopBar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,9 @@ import React, { PropTypes } from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './TopBar.styl'
import _ from 'lodash'
import modal from 'browser/main/lib/modal'
import NewNoteModal from 'browser/main/modals/NewNoteModal'
import { hashHistory } from 'react-router'
import ee from 'browser/main/lib/eventEmitter'
import ConfigManager from 'browser/main/lib/ConfigManager'
import dataApi from 'browser/main/lib/dataApi'
import NewNoteButton from 'browser/main/NewNoteButton'

const { remote } = require('electron')
const { dialog } = remote
Expand All @@ -24,81 +21,19 @@ class TopBar extends React.Component {
isSearching: false
}

this.newNoteHandler = () => {
this.handleNewPostButtonClick()
}

this.focusSearchHandler = () => {
this.handleOnSearchFocus()
}
}

componentDidMount () {
ee.on('top:new-note', this.newNoteHandler)
ee.on('top:focus-search', this.focusSearchHandler)
}

componentWillUnmount () {
ee.off('top:new-note', this.newNoteHandler)
ee.off('top:focus-search', this.focusSearchHandler)
}

handleNewPostButtonClick (e) {
let { config, location } = this.props

if (location.pathname === '/trashed') {
dialog.showMessageBox(remote.getCurrentWindow(), {
type: 'warning',
message: 'Cannot create new note',
detail: 'You cannot create new note in trash box.',
buttons: ['OK']
})
return
}

switch (config.ui.defaultNote) {
case 'MARKDOWN_NOTE':
this.createNote('MARKDOWN_NOTE')
break
case 'SNIPPET_NOTE':
this.createNote('SNIPPET_NOTE')
break
case 'ALWAYS_ASK':
default:
let { dispatch, location } = this.props
let { storage, folder } = this.resolveTargetFolder()

modal.open(NewNoteModal, {
storage: storage.key,
folder: folder.key,
dispatch,
location
})
}
}

resolveTargetFolder () {
let { data, params } = this.props
let storage = data.storageMap.get(params.storageKey)

// Find first storage
if (storage == null) {
for (let kv of data.storageMap) {
storage = kv[1]
break
}
}
if (storage == null) window.alert('No storage to create a note')
let folder = _.find(storage.folders, {key: params.folderKey})
if (folder == null) folder = storage.folders[0]
if (folder == null) window.alert('No folder to create a note')

return {
storage,
folder
}
}

handleSearchChange (e) {
let { router } = this.context
router.push('/searched')
Expand All @@ -107,22 +42,6 @@ class TopBar extends React.Component {
})
}

handleOptionClick (uniqueKey) {
return (e) => {
this.setState({
isSearching: false
}, () => {
let { location } = this.props
hashHistory.push({
pathname: location.pathname,
query: {
key: uniqueKey
}
})
})
}
}

handleSearchFocus (e) {
this.setState({
isSearching: true
Expand All @@ -147,60 +66,6 @@ class TopBar extends React.Component {
}
}

createNote (noteType) {
let { dispatch, location } = this.props
if (noteType !== 'MARKDOWN_NOTE' && noteType !== 'SNIPPET_NOTE') throw new Error('Invalid note type.')

let { storage, folder } = this.resolveTargetFolder()

let newNote = noteType === 'MARKDOWN_NOTE'
? {
type: 'MARKDOWN_NOTE',
folder: folder.key,
title: '',
content: ''
}
: {
type: 'SNIPPET_NOTE',
folder: folder.key,
title: '',
description: '',
snippets: [{
name: '',
mode: 'text',
content: ''
}]
}

dataApi
.createNote(storage.key, newNote)
.then((note) => {
dispatch({
type: 'UPDATE_NOTE',
note: note
})
hashHistory.push({
pathname: location.pathname,
query: {key: note.storage + '-' + note.key}
})
ee.emit('detail:focus')
})
}

setDefaultNote (defaultNote) {
let { config, dispatch } = this.props
let ui = Object.assign(config.ui)
ui.defaultNote = defaultNote
ConfigManager.set({
ui
})

dispatch({
type: 'SET_UI',
config: ConfigManager.get()
})
}

handleOnSearchFocus () {
if (this.state.isSearching) {
this.refs.search.childNodes[0].blur()
Expand All @@ -210,7 +75,7 @@ class TopBar extends React.Component {
}

render () {
let { config, style, data } = this.props
let { config, style, data, location } = this.props
return (
<div className='TopBar'
styleName={config.isSideNavFolded ? 'root--expanded' : 'root'}
Expand Down Expand Up @@ -242,14 +107,17 @@ class TopBar extends React.Component {
}

</div>
<button styleName='control-newPostButton'
onClick={(e) => this.handleNewPostButtonClick(e)}>
<i className='fa fa-pencil-square-o' />
<span styleName='control-newPostButton-tooltip'>
Make a Note {OSX ? '⌘' : '^'} + n
</span>
</button>
</div>
{location.pathname === '/trashed' ? ''
: <NewNoteButton
{..._.pick(this.props, [
'dispatch',
'data',
'config',
'params',
'location'
])}
/>}
</div>
)
}
Expand Down
Loading

0 comments on commit f2a03e4

Please sign in to comment.