Skip to content

Commit

Permalink
Merge pull request #297 from asmsuechan/add-trash-can
Browse files Browse the repository at this point in the history
Add trash can
  • Loading branch information
asmsuechan committed Jul 12, 2017
2 parents ec560ce + 2e628de commit dccb92d
Show file tree
Hide file tree
Showing 12 changed files with 320 additions and 144 deletions.
3 changes: 2 additions & 1 deletion browser/components/NoteItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ NoteItem.propTypes = {
type: PropTypes.string.isRequired,
title: PropTypes.string.isrequired,
tags: PropTypes.array,
isStarred: PropTypes.bool.isRequired
isStarred: PropTypes.bool.isRequired,
isTrashed: PropTypes.bool.isRequired
}),
handleNoteClick: PropTypes.func.isRequired,
handleDragStart: PropTypes.func.isRequired,
Expand Down
12 changes: 10 additions & 2 deletions browser/components/SideNavFilter.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import styles from './SideNavFilter.styl'
*/
const SideNavFilter = ({
isFolded, isHomeActive, handleAllNotesButtonClick,
isStarredActive, handleStarredButtonClick
isStarredActive, handleStarredButtonClick, isTrashedActive, handleTrashedButtonClick
}) => (
<div styleName={isFolded ? 'menu--folded' : 'menu'}>
<button styleName={isHomeActive ? 'menu-button--active' : 'menu-button'}
Expand All @@ -30,6 +30,12 @@ const SideNavFilter = ({
<i className='fa fa-star fa-fw' />
<span styleName='menu-button-label'>Starred</span>
</button>
<button styleName={isTrashedActive ? 'menu-button--active' : 'menu-button'}
onClick={handleTrashedButtonClick}
>
<i className='fa fa-trash fa-fw' />
<span styleName='menu-button-label'>Trashed</span>
</button>
</div>
)

Expand All @@ -38,7 +44,9 @@ SideNavFilter.propTypes = {
isHomeActive: PropTypes.bool.isRequired,
handleAllNotesButtonClick: PropTypes.func.isRequired,
isStarredActive: PropTypes.bool.isRequired,
handleStarredButtonClick: PropTypes.func.isRequired
isTrashedActive: PropTypes.bool.isRequired,
handleStarredButtonClick: PropTypes.func.isRequired,
handleTrashdButtonClick: PropTypes.func.isRequired
}

export default CSSModules(SideNavFilter, styles)
204 changes: 125 additions & 79 deletions browser/main/Detail/MarkdownNoteDetail.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class MarkdownNoteDetail extends React.Component {
note: Object.assign({}, nextProps.note)
}, () => {
this.refs.content.reload()
this.refs.tags.reset()
if (this.refs.tags) this.refs.tags.reset()
})
}
}
Expand Down Expand Up @@ -91,7 +91,7 @@ class MarkdownNoteDetail extends React.Component {
let { note } = this.state

note.content = this.refs.content.value
note.tags = this.refs.tags.value
if (this.refs.tags) note.tags = this.refs.tags.value
note.title = markdown.strip(findNoteTitle(note.content))
note.updatedAt = new Date()

Expand Down Expand Up @@ -176,30 +176,59 @@ class MarkdownNoteDetail extends React.Component {
}

handleTrashButtonClick (e) {
let index = dialog.showMessageBox(remote.getCurrentWindow(), {
let { note } = this.state
const { isTrashed } = note

const popupMessage = isTrashed ? 'This work cannot be undone.' : 'Throw it into trashbox.'

let dialogueButtonIndex = dialog.showMessageBox(remote.getCurrentWindow(), {
type: 'warning',
message: 'Delete a note',
detail: 'This work cannot be undone.',
detail: popupMessage,
buttons: ['Confirm', 'Cancel']
})
if (index === 0) {
let { note, dispatch } = this.props
dataApi
.deleteNote(note.storage, note.key)
.then((data) => {
let dispatchHandler = () => {
dispatch({
type: 'DELETE_NOTE',
storageKey: data.storageKey,
noteKey: data.noteKey
})
}
ee.once('list:moved', dispatchHandler)
ee.emit('list:next')
if (dialogueButtonIndex === 0) {
if (!isTrashed) {
note.isTrashed = true

this.setState({
note
}, () => {
this.save()
})
} else {
let { note, dispatch } = this.props
dataApi
.deleteNote(note.storage, note.key)
.then((data) => {
let dispatchHandler = () => {
dispatch({
type: 'DELETE_NOTE',
storageKey: data.storageKey,
noteKey: data.noteKey
})
}
ee.once('list:moved', dispatchHandler)
})
}
ee.emit('list:next')
}
}

handleUndoButtonClick (e) {
let { note } = this.state

note.isTrashed = false

this.setState({
note
}, () => {
this.save()
this.refs.content.reload()
ee.emit('list:next')
})
}

handleFullScreenButton (e) {
ee.emit('editor:fullscreen')
}
Expand Down Expand Up @@ -254,72 +283,89 @@ class MarkdownNoteDetail extends React.Component {
})
let currentOption = options.filter((option) => option.storage.key === storageKey && option.folder.key === folderKey)[0]

const trashTopBar = <div styleName='info'>
<div styleName='info-left'>
<div styleName='info-left-top'>
<div styleName='info-left-top-folderSelect'>
<i styleName='undo-button'
className='fa fa-undo fa-fw'
onClick={(e) => this.handleUndoButtonClick(e)}
/>
</div>
</div>
</div>
<div styleName='info-right'>
<TrashButton onClick={(e) => this.handleTrashButtonClick(e)} />
</div>
</div>

const detailTopBar = <div styleName='info'>
<div styleName='info-left'>
<StarButton styleName='info-left-button'
onClick={(e) => this.handleStarButtonClick(e)}
isActive={note.isStarred}
/>
<div styleName='info-left-top'>
<FolderSelect styleName='info-left-top-folderSelect'
value={this.state.note.storage + '-' + this.state.note.folder}
ref='folder'
data={data}
onChange={(e) => this.handleFolderChange(e)}
/>
</div>

<TagSelect
ref='tags'
value={this.state.note.tags}
onChange={(e) => this.handleChange(e)}
/>
<TodoListPercentage
percentageOfTodo={this.getPercentageOfCompleteTodo(note.content)}
/>
</div>
<div styleName='info-right'>
{(() => {
const faClassName = `fa ${this.getToggleLockButton()}`
const lockButtonComponent =
<button styleName='control-lockButton'
onFocus={(e) => this.handleFocus(e)}
onMouseDown={(e) => this.handleLockButtonMouseDown(e)}
>
<i className={faClassName} styleName='lock-button' />
<span styleName='control-lockButton-tooltip'>
{this.state.isLocked ? 'Unlock' : 'Lock'}
</span>
</button>
return (
this.state.isLockButtonShown ? lockButtonComponent : ''
)
})()}
<TrashButton onClick={(e) => this.handleTrashButtonClick(e)} />
<button styleName='control-fullScreenButton'
onMouseDown={(e) => this.handleFullScreenButton(e)}
>
<i className='fa fa-expand' styleName='fullScreen-button' />
</button>
<InfoButton
onClick={(e) => this.handleInfoButtonClick(e)}
/>
<InfoPanel
storageName={currentOption.storage.name}
folderName={currentOption.folder.name}
noteKey={location.query.key}
updatedAt={formatDate(note.updatedAt)}
createdAt={formatDate(note.createdAt)}
/>
</div>
</div>

return (
<div className='NoteDetail'
style={this.props.style}
styleName='root'
>
<div styleName='info'>
<div styleName='info-left'>
<StarButton styleName='info-left-button'
onClick={(e) => this.handleStarButtonClick(e)}
isActive={note.isStarred}
/>
<div styleName='info-left-top'>
<FolderSelect styleName='info-left-top-folderSelect'
value={this.state.note.storage + '-' + this.state.note.folder}
ref='folder'
data={data}
onChange={(e) => this.handleFolderChange(e)}
/>
</div>

<TagSelect
ref='tags'
value={this.state.note.tags}
onChange={(e) => this.handleChange(e)}
/>
<TodoListPercentage
percentageOfTodo={this.getPercentageOfCompleteTodo(note.content)}
/>
</div>
<div styleName='info-right'>
{(() => {
const faClassName = `fa ${this.getToggleLockButton()}`
const lockButtonComponent =
<button styleName='control-lockButton'
onFocus={(e) => this.handleFocus(e)}
onMouseDown={(e) => this.handleLockButtonMouseDown(e)}
>
<i className={faClassName} styleName='lock-button' />
<span styleName='control-lockButton-tooltip'>
{this.state.isLocked ? 'Lock' : 'Unlock'}
</span>
</button>
return (
this.state.isLockButtonShown ? lockButtonComponent : ''
)
})()}
<TrashButton
onClick={(e) => this.handleTrashButtonClick(e)}
/>
<button styleName='control-fullScreenButton'
onMouseDown={(e) => this.handleFullScreenButton(e)}
>
<i className='fa fa-expand' styleName='fullScreen-button' />
</button>
<InfoButton
onClick={(e) => this.handleInfoButtonClick(e)}
/>
<InfoPanel
storageName={currentOption.storage.name}
folderName={currentOption.folder.name}
noteKey={location.query.key}
updatedAt={formatDate(note.updatedAt)}
createdAt={formatDate(note.createdAt)}
/>
</div>
</div>

{location.pathname === '/trashed' ? trashTopBar : detailTopBar}

<div styleName='body'>
<MarkdownEditor
Expand Down
12 changes: 12 additions & 0 deletions browser/main/Detail/NoteDetailInfo.styl
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,18 @@ $info-margin-under-border = 27px
bottom 1px
padding-left 30px

.undo-button
position relative
border solid 1px transparent
line-height 34px
vertical-align middle
border-radius 2px
transition 0.15s
user-select none
cursor pointer
&:hover
background-color #D9D9D9

body[data-theme="dark"]
.info
border-color $ui-dark-borderColor
Expand Down
Loading

0 comments on commit dccb92d

Please sign in to comment.