mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-13 17:56:25 +00:00
Merge pull request #1549 from nlopin/restore-note-enhancing
Restore note UX enhancements
This commit is contained in:
@@ -19,6 +19,7 @@ import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
|
|||||||
import ConfigManager from 'browser/main/lib/ConfigManager'
|
import ConfigManager from 'browser/main/lib/ConfigManager'
|
||||||
import TrashButton from './TrashButton'
|
import TrashButton from './TrashButton'
|
||||||
import FullscreenButton from './FullscreenButton'
|
import FullscreenButton from './FullscreenButton'
|
||||||
|
import RestoreButton from './RestoreButton'
|
||||||
import PermanentDeleteButton from './PermanentDeleteButton'
|
import PermanentDeleteButton from './PermanentDeleteButton'
|
||||||
import InfoButton from './InfoButton'
|
import InfoButton from './InfoButton'
|
||||||
import ToggleModeButton from './ToggleModeButton'
|
import ToggleModeButton from './ToggleModeButton'
|
||||||
@@ -321,10 +322,7 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
|
|
||||||
const trashTopBar = <div styleName='info'>
|
const trashTopBar = <div styleName='info'>
|
||||||
<div styleName='info-left'>
|
<div styleName='info-left'>
|
||||||
<i styleName='undo-button'
|
<RestoreButton onClick={(e) => this.handleUndoButtonClick(e)} />
|
||||||
className='fa fa-undo fa-fw'
|
|
||||||
onClick={(e) => this.handleUndoButtonClick(e)}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div styleName='info-right'>
|
<div styleName='info-right'>
|
||||||
<PermanentDeleteButton onClick={(e) => this.handleTrashButtonClick(e)} />
|
<PermanentDeleteButton onClick={(e) => this.handleTrashButtonClick(e)} />
|
||||||
|
|||||||
21
browser/main/Detail/RestoreButton.js
Normal file
21
browser/main/Detail/RestoreButton.js
Normal file
@@ -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
|
||||||
|
}) => (
|
||||||
|
<button styleName='control-restoreButton'
|
||||||
|
onClick={onClick}
|
||||||
|
>
|
||||||
|
<i className='fa fa-undo fa-fw' styleName='iconRestore' />
|
||||||
|
<span styleName='tooltip'>Restore</span>
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
|
||||||
|
RestoreButton.propTypes = {
|
||||||
|
onClick: PropTypes.func.isRequired
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CSSModules(RestoreButton, styles)
|
||||||
22
browser/main/Detail/RestoreButton.styl
Normal file
22
browser/main/Detail/RestoreButton.styl
Normal file
@@ -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()
|
||||||
@@ -20,6 +20,7 @@ import _ from 'lodash'
|
|||||||
import { findNoteTitle } from 'browser/lib/findNoteTitle'
|
import { findNoteTitle } from 'browser/lib/findNoteTitle'
|
||||||
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
|
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
|
||||||
import TrashButton from './TrashButton'
|
import TrashButton from './TrashButton'
|
||||||
|
import RestoreButton from './RestoreButton'
|
||||||
import PermanentDeleteButton from './PermanentDeleteButton'
|
import PermanentDeleteButton from './PermanentDeleteButton'
|
||||||
import InfoButton from './InfoButton'
|
import InfoButton from './InfoButton'
|
||||||
import InfoPanel from './InfoPanel'
|
import InfoPanel from './InfoPanel'
|
||||||
@@ -589,10 +590,7 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
|
|
||||||
const trashTopBar = <div styleName='info'>
|
const trashTopBar = <div styleName='info'>
|
||||||
<div styleName='info-left'>
|
<div styleName='info-left'>
|
||||||
<i styleName='undo-button'
|
<RestoreButton onClick={(e) => this.handleUndoButtonClick(e)} />
|
||||||
className='fa fa-undo fa-fw'
|
|
||||||
onClick={(e) => this.handleUndoButtonClick(e)}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div styleName='info-right'>
|
<div styleName='info-right'>
|
||||||
<PermanentDeleteButton onClick={(e) => this.handleTrashButtonClick(e)} />
|
<PermanentDeleteButton onClick={(e) => this.handleTrashButtonClick(e)} />
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ class NoteList extends React.Component {
|
|||||||
this.deleteNote = this.deleteNote.bind(this)
|
this.deleteNote = this.deleteNote.bind(this)
|
||||||
this.focusNote = this.focusNote.bind(this)
|
this.focusNote = this.focusNote.bind(this)
|
||||||
this.pinToTop = this.pinToTop.bind(this)
|
this.pinToTop = this.pinToTop.bind(this)
|
||||||
|
this.restoreNote = this.restoreNote.bind(this)
|
||||||
|
|
||||||
// TODO: not Selected noteKeys but SelectedNote(for reusing)
|
// TODO: not Selected noteKeys but SelectedNote(for reusing)
|
||||||
this.state = {
|
this.state = {
|
||||||
@@ -453,6 +454,7 @@ class NoteList extends React.Component {
|
|||||||
const pinLabel = note.isPinned ? 'Remove pin' : 'Pin to Top'
|
const pinLabel = note.isPinned ? 'Remove pin' : 'Pin to Top'
|
||||||
const deleteLabel = 'Delete Note'
|
const deleteLabel = 'Delete Note'
|
||||||
const cloneNote = 'Clone Note'
|
const cloneNote = 'Clone Note'
|
||||||
|
const restoreNote = 'Restore Note'
|
||||||
|
|
||||||
const menu = new Menu()
|
const menu = new Menu()
|
||||||
if (!location.pathname.match(/\/starred|\/trash/)) {
|
if (!location.pathname.match(/\/starred|\/trash/)) {
|
||||||
@@ -461,6 +463,14 @@ class NoteList extends React.Component {
|
|||||||
click: this.pinToTop
|
click: this.pinToTop
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (location.pathname.match(/\/trash/)) {
|
||||||
|
menu.append(new MenuItem({
|
||||||
|
label: restoreNote,
|
||||||
|
click: this.restoreNote
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
menu.append(new MenuItem({
|
menu.append(new MenuItem({
|
||||||
label: deleteLabel,
|
label: deleteLabel,
|
||||||
click: this.deleteNote
|
click: this.deleteNote
|
||||||
@@ -472,28 +482,50 @@ class NoteList extends React.Component {
|
|||||||
menu.popup()
|
menu.popup()
|
||||||
}
|
}
|
||||||
|
|
||||||
pinToTop () {
|
updateSelectedNotes (updateFunc, cleanSelection = true) {
|
||||||
const { selectedNoteKeys } = this.state
|
const { selectedNoteKeys } = this.state
|
||||||
const { dispatch } = this.props
|
const { dispatch } = this.props
|
||||||
const notes = this.notes.map((note) => Object.assign({}, note))
|
const notes = this.notes.map((note) => Object.assign({}, note))
|
||||||
const selectedNotes = findNotesByKeys(notes, selectedNoteKeys)
|
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(
|
Promise.all(
|
||||||
selectedNotes.map((note) => {
|
selectedNotes.map((note) => {
|
||||||
note.isPinned = !note.isPinned
|
note = updateFunc(note)
|
||||||
return dataApi
|
return dataApi
|
||||||
.updateNote(note.storage, note.key, note)
|
.updateNote(note.storage, note.key, note)
|
||||||
})
|
|
||||||
)
|
|
||||||
.then((updatedNotes) => {
|
|
||||||
updatedNotes.forEach((note) => {
|
|
||||||
dispatch({
|
|
||||||
type: 'UPDATE_NOTE',
|
|
||||||
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 () {
|
deleteNote () {
|
||||||
|
|||||||
Reference in New Issue
Block a user