mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-13 09:46:22 +00:00
search
This commit is contained in:
@@ -102,6 +102,7 @@ class Main extends React.Component {
|
||||
'dispatch',
|
||||
'storages',
|
||||
'config',
|
||||
'notes',
|
||||
'params',
|
||||
'location'
|
||||
])}
|
||||
|
||||
@@ -36,6 +36,46 @@ $control-height = 34px
|
||||
outline none
|
||||
border none
|
||||
|
||||
.control-search-optionList
|
||||
position fixed
|
||||
z-index 200
|
||||
width 275px
|
||||
height 175px
|
||||
overflow-y auto
|
||||
background-color $modal-background
|
||||
border-radius 2px
|
||||
box-shadow 2px 2px 10px gray
|
||||
|
||||
.control-search-optionList-item
|
||||
height 50px
|
||||
border-bottom $ui-border
|
||||
transition background-color 0.15s
|
||||
padding 5px
|
||||
cursor pointer
|
||||
overflow ellipsis
|
||||
&:hover
|
||||
background-color alpha($ui-active-color, 10%)
|
||||
.control-search-optionList-item-folder
|
||||
border-left 4px solid transparent
|
||||
padding 2px 5px
|
||||
color $ui-text-color
|
||||
overflow ellipsis
|
||||
font-size 12px
|
||||
height 16px
|
||||
margin-bottom 4px
|
||||
.control-search-optionList-item-folder-surfix
|
||||
font-size 10px
|
||||
margin-left 5px
|
||||
color $ui-inactive-text-color
|
||||
.control-search-optionList-item-type
|
||||
font-size 12px
|
||||
color $ui-inactive-text-color
|
||||
padding-right 3px
|
||||
.control-search-optionList-empty
|
||||
height 150px
|
||||
color $ui-inactive-text-color
|
||||
line-height 150px
|
||||
text-align center
|
||||
.control-newPostButton
|
||||
display block
|
||||
absolute top right bottom
|
||||
@@ -51,7 +91,6 @@ $control-height = 34px
|
||||
&:hover .left-control-newPostButton-tooltip
|
||||
display block
|
||||
|
||||
|
||||
.control-newPostButton-tooltip
|
||||
position fixed
|
||||
line-height 1.4
|
||||
|
||||
@@ -7,6 +7,7 @@ import Commander from 'browser/main/lib/Commander'
|
||||
import dataApi from 'browser/main/lib/dataApi'
|
||||
import modal from 'browser/main/lib/modal'
|
||||
import NewNoteModal from 'browser/main/modals/NewNoteModal'
|
||||
import { hashHistory } from 'react-router'
|
||||
|
||||
const OSX = window.process.platform === 'darwin'
|
||||
|
||||
@@ -15,25 +16,12 @@ class TopBar extends React.Component {
|
||||
super(props)
|
||||
|
||||
this.state = {
|
||||
search: ''
|
||||
search: '',
|
||||
searchOptions: [],
|
||||
searchPopupOpen: false
|
||||
}
|
||||
}
|
||||
|
||||
isInputFocused () {
|
||||
return document.activeElement === this.refs.searchInput
|
||||
}
|
||||
|
||||
escape () {
|
||||
}
|
||||
|
||||
focusInput () {
|
||||
this.searchInput.focus()
|
||||
}
|
||||
|
||||
blurInput () {
|
||||
this.searchInput.blur()
|
||||
}
|
||||
|
||||
handleNewPostButtonClick (e) {
|
||||
let { storages, params, dispatch, location } = this.props
|
||||
let storage = _.find(storages, {key: params.storageKey})
|
||||
@@ -51,11 +39,98 @@ class TopBar extends React.Component {
|
||||
})
|
||||
}
|
||||
|
||||
handleTutorialButtonClick (e) {
|
||||
handleSearchChange (e) {
|
||||
this.setState({
|
||||
search: this.refs.searchInput.value
|
||||
})
|
||||
}
|
||||
|
||||
getOptions () {
|
||||
let { notes } = this.props
|
||||
let { search } = this.state
|
||||
if (search.trim().length === 0) return []
|
||||
let searchBlocks = search.split(' ')
|
||||
searchBlocks.forEach((block) => {
|
||||
if (block.match(/^#.+/)) {
|
||||
let tag = block.match(/#(.+)/)[1]
|
||||
notes = notes.filter((note) => note.tags.some((_tag) => _tag === tag))
|
||||
}
|
||||
notes = notes.filter((note) => {
|
||||
if (note.type === 'SNIPPET_NOTE') {
|
||||
return note.description.match(block)
|
||||
} else if (note.type === 'MARKDOWN_NOTE') {
|
||||
return note.content.match(block)
|
||||
}
|
||||
return false
|
||||
})
|
||||
})
|
||||
|
||||
return notes
|
||||
}
|
||||
|
||||
handleOptionClick (uniqueKey) {
|
||||
return (e) => {
|
||||
this.setState({
|
||||
searchPopupOpen: false
|
||||
}, () => {
|
||||
let { location } = this.props
|
||||
hashHistory.push({
|
||||
pathname: location.pathname,
|
||||
query: {
|
||||
key: uniqueKey
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
handleSearchFocus (e) {
|
||||
this.setState({
|
||||
searchPopupOpen: true
|
||||
})
|
||||
}
|
||||
handleSearchBlur (e) {
|
||||
e.stopPropagation()
|
||||
|
||||
let el = e.relatedTarget
|
||||
let isStillFocused = false
|
||||
while (el != null) {
|
||||
if (el === this.refs.search) {
|
||||
isStillFocused = true
|
||||
break
|
||||
}
|
||||
el = el.parentNode
|
||||
}
|
||||
if (!isStillFocused) {
|
||||
this.setState({
|
||||
searchPopupOpen: false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
let { config, style } = this.props
|
||||
let { config, style, storages } = this.props
|
||||
let searchOptionList = this.getOptions()
|
||||
.map((note) => {
|
||||
let storage = _.find(storages, {key: note.storage})
|
||||
let folder = _.find(storage.folders, {key: note.folder})
|
||||
return <div styleName='control-search-optionList-item'
|
||||
key={note.uniqueKey}
|
||||
onClick={(e) => this.handleOptionClick(note.uniqueKey)(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 (
|
||||
<div className='TopBar'
|
||||
styleName={config.isSideNavFolded ? 'root--expanded' : 'root'}
|
||||
@@ -64,16 +139,27 @@ class TopBar extends React.Component {
|
||||
<div styleName='control'>
|
||||
<div styleName='control-search'>
|
||||
<i styleName='control-search-icon' className='fa fa-search fa-fw'/>
|
||||
<div styleName='control-search-input'>
|
||||
<div styleName='control-search-input'
|
||||
onFocus={(e) => this.handleSearchFocus(e)}
|
||||
onBlur={(e) => this.handleSearchBlur(e)}
|
||||
tabIndex='-1'
|
||||
ref='search'
|
||||
>
|
||||
<input
|
||||
ref='searchInput'
|
||||
onFocus={(e) => this.handleSearchChange(e)}
|
||||
onBlur={(e) => this.handleSearchChange(e)}
|
||||
value={this.state.search}
|
||||
onChange={(e) => this.handleSearchChange(e)}
|
||||
placeholder='Search'
|
||||
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>
|
||||
{this.state.search > 0 &&
|
||||
<button styleName='left-search-clearButton'
|
||||
|
||||
Reference in New Issue
Block a user