mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-13 17:56:25 +00:00
change search ux
This commit is contained in:
@@ -212,6 +212,10 @@ class NoteList extends React.Component {
|
|||||||
.map((uniqueKey) => data.noteMap.get(uniqueKey))
|
.map((uniqueKey) => data.noteMap.get(uniqueKey))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (location.pathname.match(/\/searched/)) {
|
||||||
|
return this.getSearchNotes()
|
||||||
|
}
|
||||||
|
|
||||||
let storageKey = params.storageKey
|
let storageKey = params.storageKey
|
||||||
let folderKey = params.folderKey
|
let folderKey = params.folderKey
|
||||||
let storage = data.storageMap.get(storageKey)
|
let storage = data.storageMap.get(storageKey)
|
||||||
@@ -349,6 +353,71 @@ class NoteList extends React.Component {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getSearchNotes () {
|
||||||
|
let { data } = this.props
|
||||||
|
let search = document.getElementsByClassName('TopBar__control-search-input___browser-main-TopBar-')[0].childNodes[0].value
|
||||||
|
let notes = data.noteMap.map((note) => note)
|
||||||
|
if (search.trim().length === 0) return []
|
||||||
|
let searchBlocks = search.split(' ')
|
||||||
|
searchBlocks.forEach((block) => {
|
||||||
|
if (block.match(/^!#.+/)) {
|
||||||
|
let tag = block.match(/^!#(.+)/)[1]
|
||||||
|
let regExp = new RegExp(_.escapeRegExp(tag), 'i')
|
||||||
|
notes = notes
|
||||||
|
.filter((note) => {
|
||||||
|
if (!_.isArray(note.tags)) return false
|
||||||
|
return note.tags.some((_tag) => {
|
||||||
|
return _tag.match(regExp)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} else if (block.match(/^!.+/)) {
|
||||||
|
let block = block.match(/^!(.+)/)[1]
|
||||||
|
let regExp = new RegExp(_.escapeRegExp(block), 'i')
|
||||||
|
notes = notes.filter((note) => {
|
||||||
|
if (!_.isArray(note.tags) || !note.tags.some((_tag) => {
|
||||||
|
return _tag.match(regExp)
|
||||||
|
})) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (note.type === 'SNIPPET_NOTE') {
|
||||||
|
return !note.description.match(regExp)
|
||||||
|
} else if (note.type === 'MARKDOWN_NOTE') {
|
||||||
|
return !note.content.match(regExp)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
} else if (block.match(/^#.+/)) {
|
||||||
|
let tag = block.match(/#(.+)/)[1]
|
||||||
|
let regExp = new RegExp(_.escapeRegExp(tag), 'i')
|
||||||
|
notes = notes
|
||||||
|
.filter((note) => {
|
||||||
|
if (!_.isArray(note.tags)) return false
|
||||||
|
return note.tags.some((_tag) => {
|
||||||
|
return _tag.match(regExp)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
let regExp = new RegExp(_.escapeRegExp(block), 'i')
|
||||||
|
notes = notes.filter((note) => {
|
||||||
|
if (_.isArray(note.tags) && note.tags.some((_tag) => {
|
||||||
|
return _tag.match(regExp)
|
||||||
|
})) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (note.type === 'SNIPPET_NOTE') {
|
||||||
|
return note.description.match(regExp)
|
||||||
|
} else if (note.type === 'MARKDOWN_NOTE') {
|
||||||
|
return note.content.match(regExp)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return notes
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let { location, notes, config } = this.props
|
let { location, notes, config } = this.props
|
||||||
let sortFunc = config.sortBy === 'CREATED_AT'
|
let sortFunc = config.sortBy === 'CREATED_AT'
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ class TopBar extends React.Component {
|
|||||||
this.state = {
|
this.state = {
|
||||||
search: '',
|
search: '',
|
||||||
searchOptions: [],
|
searchOptions: [],
|
||||||
searchPopupOpen: false
|
isSearching: false
|
||||||
}
|
}
|
||||||
|
|
||||||
this.newNoteHandler = () => {
|
this.newNoteHandler = () => {
|
||||||
@@ -87,79 +87,17 @@ class TopBar extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleSearchChange (e) {
|
handleSearchChange (e) {
|
||||||
|
let { router } = this.context
|
||||||
|
router.push('/searched')
|
||||||
this.setState({
|
this.setState({
|
||||||
search: this.refs.searchInput.value
|
search: this.refs.searchInput.value
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
getOptions () {
|
|
||||||
let { data } = this.props
|
|
||||||
let { search } = this.state
|
|
||||||
let notes = data.noteMap.map((note) => note)
|
|
||||||
if (search.trim().length === 0) return []
|
|
||||||
let searchBlocks = search.split(' ')
|
|
||||||
searchBlocks.forEach((block) => {
|
|
||||||
if (block.match(/^!#.+/)) {
|
|
||||||
let tag = block.match(/^!#(.+)/)[1]
|
|
||||||
let regExp = new RegExp(_.escapeRegExp(tag), 'i')
|
|
||||||
notes = notes
|
|
||||||
.filter((note) => {
|
|
||||||
if (!_.isArray(note.tags)) return false
|
|
||||||
return note.tags.some((_tag) => {
|
|
||||||
return _tag.match(regExp)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
} else if (block.match(/^!.+/)) {
|
|
||||||
let block = block.match(/^!(.+)/)[1]
|
|
||||||
let regExp = new RegExp(_.escapeRegExp(block), 'i')
|
|
||||||
notes = notes.filter((note) => {
|
|
||||||
if (!_.isArray(note.tags) || !note.tags.some((_tag) => {
|
|
||||||
return _tag.match(regExp)
|
|
||||||
})) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if (note.type === 'SNIPPET_NOTE') {
|
|
||||||
return !note.description.match(regExp)
|
|
||||||
} else if (note.type === 'MARKDOWN_NOTE') {
|
|
||||||
return !note.content.match(regExp)
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
} else if (block.match(/^#.+/)) {
|
|
||||||
let tag = block.match(/#(.+)/)[1]
|
|
||||||
let regExp = new RegExp(_.escapeRegExp(tag), 'i')
|
|
||||||
notes = notes
|
|
||||||
.filter((note) => {
|
|
||||||
if (!_.isArray(note.tags)) return false
|
|
||||||
return note.tags.some((_tag) => {
|
|
||||||
return _tag.match(regExp)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
let regExp = new RegExp(_.escapeRegExp(block), 'i')
|
|
||||||
notes = notes.filter((note) => {
|
|
||||||
if (_.isArray(note.tags) && note.tags.some((_tag) => {
|
|
||||||
return _tag.match(regExp)
|
|
||||||
})) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if (note.type === 'SNIPPET_NOTE') {
|
|
||||||
return note.description.match(regExp)
|
|
||||||
} else if (note.type === 'MARKDOWN_NOTE') {
|
|
||||||
return note.content.match(regExp)
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return notes
|
|
||||||
}
|
|
||||||
|
|
||||||
handleOptionClick (uniqueKey) {
|
handleOptionClick (uniqueKey) {
|
||||||
return (e) => {
|
return (e) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
searchPopupOpen: false
|
isSearching: false
|
||||||
}, () => {
|
}, () => {
|
||||||
let { location } = this.props
|
let { location } = this.props
|
||||||
hashHistory.push({
|
hashHistory.push({
|
||||||
@@ -174,7 +112,7 @@ class TopBar extends React.Component {
|
|||||||
|
|
||||||
handleSearchFocus (e) {
|
handleSearchFocus (e) {
|
||||||
this.setState({
|
this.setState({
|
||||||
searchPopupOpen: true
|
isSearching: true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
handleSearchBlur (e) {
|
handleSearchBlur (e) {
|
||||||
@@ -191,7 +129,7 @@ class TopBar extends React.Component {
|
|||||||
}
|
}
|
||||||
if (!isStillFocused) {
|
if (!isStillFocused) {
|
||||||
this.setState({
|
this.setState({
|
||||||
searchPopupOpen: false
|
isSearching: false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -251,7 +189,7 @@ class TopBar extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleOnSearchFocus () {
|
handleOnSearchFocus () {
|
||||||
if (this.state.searchPopupOpen) {
|
if (this.state.isSearching) {
|
||||||
this.refs.search.childNodes[0].blur()
|
this.refs.search.childNodes[0].blur()
|
||||||
} else {
|
} else {
|
||||||
this.refs.search.childNodes[0].focus()
|
this.refs.search.childNodes[0].focus()
|
||||||
@@ -260,27 +198,6 @@ class TopBar extends React.Component {
|
|||||||
|
|
||||||
render () {
|
render () {
|
||||||
let { config, style, data } = this.props
|
let { config, style, data } = this.props
|
||||||
let searchOptionList = this.getOptions()
|
|
||||||
.map((note) => {
|
|
||||||
let storage = data.storageMap.get(note.storage)
|
|
||||||
let folder = _.find(storage.folders, {key: note.folder})
|
|
||||||
return <div styleName='control-search-optionList-item'
|
|
||||||
key={note.storage + '-' + note.key}
|
|
||||||
onClick={(e) => this.handleOptionClick(note.storage + '-' + note.key)(e)}
|
|
||||||
>
|
|
||||||
<div styleName='control-search-optionList-item-folder'
|
|
||||||
style={{borderColor: folder.color}}>
|
|
||||||
{folder.name}
|
|
||||||
<span styleName='control-search-optionList-item-folder-surfix'>in {storage.name}</span>
|
|
||||||
</div>
|
|
||||||
{note.type === 'SNIPPET_NOTE'
|
|
||||||
? <i styleName='control-search-optionList-item-type' className='fa fa-code' />
|
|
||||||
: <i styleName='control-search-optionList-item-type' className='fa fa-file-text-o' />
|
|
||||||
}
|
|
||||||
{note.title}
|
|
||||||
</div>
|
|
||||||
})
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='TopBar'
|
<div className='TopBar'
|
||||||
styleName={config.isSideNavFolded ? 'root--expanded' : 'root'}
|
styleName={config.isSideNavFolded ? 'root--expanded' : 'root'}
|
||||||
@@ -302,14 +219,6 @@ class TopBar extends React.Component {
|
|||||||
placeholder='Search'
|
placeholder='Search'
|
||||||
type='text'
|
type='text'
|
||||||
/>
|
/>
|
||||||
{this.state.searchPopupOpen &&
|
|
||||||
<div styleName='control-search-optionList'>
|
|
||||||
{searchOptionList.length > 0
|
|
||||||
? searchOptionList
|
|
||||||
: <div styleName='control-search-optionList-empty'>Empty List</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
{this.state.search > 0 &&
|
{this.state.search > 0 &&
|
||||||
<button styleName='left-search-clearButton'
|
<button styleName='left-search-clearButton'
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ ReactDOM.render((
|
|||||||
<IndexRedirect to='/home' />
|
<IndexRedirect to='/home' />
|
||||||
<Route path='home' />
|
<Route path='home' />
|
||||||
<Route path='starred' />
|
<Route path='starred' />
|
||||||
|
<Route path='searched' />
|
||||||
<Route path='storages'>
|
<Route path='storages'>
|
||||||
<IndexRedirect to='/home' />
|
<IndexRedirect to='/home' />
|
||||||
<Route path=':storageKey'>
|
<Route path=':storageKey'>
|
||||||
|
|||||||
Reference in New Issue
Block a user