Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add trash can #297

Merged
merged 5 commits into from
Jul 12, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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