diff --git a/browser/main/Detail/MarkdownNoteDetail.js b/browser/main/Detail/MarkdownNoteDetail.js index 7694f1e7..df6ce3ea 100755 --- a/browser/main/Detail/MarkdownNoteDetail.js +++ b/browser/main/Detail/MarkdownNoteDetail.js @@ -19,6 +19,7 @@ import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig' import ConfigManager from 'browser/main/lib/ConfigManager' import TrashButton from './TrashButton' import FullscreenButton from './FullscreenButton' +import RestoreButton from './RestoreButton' import PermanentDeleteButton from './PermanentDeleteButton' import InfoButton from './InfoButton' import ToggleModeButton from './ToggleModeButton' @@ -321,10 +322,7 @@ class MarkdownNoteDetail extends React.Component { const trashTopBar =
- this.handleUndoButtonClick(e)} - /> + this.handleUndoButtonClick(e)} />
this.handleTrashButtonClick(e)} /> diff --git a/browser/main/Detail/RestoreButton.js b/browser/main/Detail/RestoreButton.js new file mode 100644 index 00000000..0f9c992e --- /dev/null +++ b/browser/main/Detail/RestoreButton.js @@ -0,0 +1,21 @@ +import PropTypes from 'prop-types' +import React from 'react' +import CSSModules from 'browser/lib/CSSModules' +import styles from './RestoreButton.styl' + +const RestoreButton = ({ + onClick +}) => ( + +) + +RestoreButton.propTypes = { + onClick: PropTypes.func.isRequired +} + +export default CSSModules(RestoreButton, styles) diff --git a/browser/main/Detail/RestoreButton.styl b/browser/main/Detail/RestoreButton.styl new file mode 100644 index 00000000..58ce745d --- /dev/null +++ b/browser/main/Detail/RestoreButton.styl @@ -0,0 +1,22 @@ +.control-restoreButton + top 115px + topBarButtonRight() + &:hover .tooltip + opacity 1 + +.tooltip + tooltip() + position absolute + pointer-events none + top 50px + left 25px + z-index 200 + padding 5px + line-height normal + border-radius 2px + opacity 0 + transition 0.1s + +body[data-theme="dark"] + .control-restoreButton + topBarButtonDark() diff --git a/browser/main/Detail/SnippetNoteDetail.js b/browser/main/Detail/SnippetNoteDetail.js index 791b490e..dbef37ca 100644 --- a/browser/main/Detail/SnippetNoteDetail.js +++ b/browser/main/Detail/SnippetNoteDetail.js @@ -20,6 +20,7 @@ import _ from 'lodash' import { findNoteTitle } from 'browser/lib/findNoteTitle' import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig' import TrashButton from './TrashButton' +import RestoreButton from './RestoreButton' import PermanentDeleteButton from './PermanentDeleteButton' import InfoButton from './InfoButton' import InfoPanel from './InfoPanel' @@ -589,10 +590,7 @@ class SnippetNoteDetail extends React.Component { const trashTopBar =
- this.handleUndoButtonClick(e)} - /> + this.handleUndoButtonClick(e)} />
this.handleTrashButtonClick(e)} /> diff --git a/browser/main/NoteList/index.js b/browser/main/NoteList/index.js index cb71ac07..345dfe0d 100644 --- a/browser/main/NoteList/index.js +++ b/browser/main/NoteList/index.js @@ -66,6 +66,7 @@ class NoteList extends React.Component { this.deleteNote = this.deleteNote.bind(this) this.focusNote = this.focusNote.bind(this) this.pinToTop = this.pinToTop.bind(this) + this.restoreNote = this.restoreNote.bind(this) // TODO: not Selected noteKeys but SelectedNote(for reusing) this.state = { @@ -453,6 +454,7 @@ class NoteList extends React.Component { const pinLabel = note.isPinned ? 'Remove pin' : 'Pin to Top' const deleteLabel = 'Delete Note' const cloneNote = 'Clone Note' + const restoreNote = 'Restore Note' const menu = new Menu() if (!location.pathname.match(/\/starred|\/trash/)) { @@ -461,6 +463,14 @@ class NoteList extends React.Component { click: this.pinToTop })) } + + if (location.pathname.match(/\/trash/)) { + menu.append(new MenuItem({ + label: restoreNote, + click: this.restoreNote + })) + } + menu.append(new MenuItem({ label: deleteLabel, click: this.deleteNote @@ -472,28 +482,50 @@ class NoteList extends React.Component { menu.popup() } - pinToTop () { + updateSelectedNotes (updateFunc, cleanSelection = true) { const { selectedNoteKeys } = this.state const { dispatch } = this.props const notes = this.notes.map((note) => Object.assign({}, note)) const selectedNotes = findNotesByKeys(notes, selectedNoteKeys) + if (!_.isFunction(updateFunc)) { + console.warn('Update function is not defined. No update will happen') + updateFunc = (note) => { return note } + } + Promise.all( - selectedNotes.map((note) => { - note.isPinned = !note.isPinned - return dataApi - .updateNote(note.storage, note.key, note) - }) - ) - .then((updatedNotes) => { - updatedNotes.forEach((note) => { - dispatch({ - type: 'UPDATE_NOTE', - note + selectedNotes.map((note) => { + note = updateFunc(note) + return dataApi + .updateNote(note.storage, note.key, note) }) - }) + ) + .then((updatedNotes) => { + updatedNotes.forEach((note) => { + dispatch({ + type: 'UPDATE_NOTE', + note + }) + }) + }) + + if (cleanSelection) { + this.selectNextNote() + } + } + + pinToTop () { + this.updateSelectedNotes((note) => { + note.isPinned = !note.isPinned + return note + }) + } + + restoreNote () { + this.updateSelectedNotes((note) => { + note.isTrashed = false + return note }) - this.setState({ selectedNoteKeys: [] }) } deleteNote () {