mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-16 19:21:52 +00:00
TagSelect
This commit is contained in:
@@ -3,6 +3,7 @@ import CSSModules from 'browser/lib/CSSModules'
|
|||||||
import styles from './NoteDetail.styl'
|
import styles from './NoteDetail.styl'
|
||||||
import MarkdownEditor from 'browser/components/MarkdownEditor'
|
import MarkdownEditor from 'browser/components/MarkdownEditor'
|
||||||
import queue from 'browser/main/lib/queue'
|
import queue from 'browser/main/lib/queue'
|
||||||
|
import TagSelect from './TagSelect'
|
||||||
|
|
||||||
class NoteDetail extends React.Component {
|
class NoteDetail extends React.Component {
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
@@ -15,9 +16,6 @@ class NoteDetail extends React.Component {
|
|||||||
this.dispatchTimer = null
|
this.dispatchTimer = null
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate (prevProps, prevState) {
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillReceiveProps (nextProps) {
|
componentWillReceiveProps (nextProps) {
|
||||||
if (nextProps.note.key !== this.props.note.key) {
|
if (nextProps.note.key !== this.props.note.key) {
|
||||||
if (this.state.isDispatchQueued) {
|
if (this.state.isDispatchQueued) {
|
||||||
@@ -28,6 +26,7 @@ class NoteDetail extends React.Component {
|
|||||||
isDispatchQueued: false
|
isDispatchQueued: false
|
||||||
}, () => {
|
}, () => {
|
||||||
this.refs.content.reload()
|
this.refs.content.reload()
|
||||||
|
this.refs.tags.reset()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,6 +63,7 @@ class NoteDetail extends React.Component {
|
|||||||
let { note } = this.state
|
let { note } = this.state
|
||||||
|
|
||||||
note.content = this.refs.content.value
|
note.content = this.refs.content.value
|
||||||
|
note.tags = this.refs.tags.value
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
note,
|
note,
|
||||||
@@ -114,8 +114,21 @@ class NoteDetail extends React.Component {
|
|||||||
>
|
>
|
||||||
<div styleName='info'>
|
<div styleName='info'>
|
||||||
<div styleName='info-left'>
|
<div styleName='info-left'>
|
||||||
<div styleName='info-left-folderSelect'>FOLDER SELECT</div>
|
|
||||||
<div styleName='info-left-tagSelect'>TAG SELECT</div>
|
<div styleName='info-left-top'>
|
||||||
|
<button styleName='info-left-top-starButton'>
|
||||||
|
<i className='fa fa-star-o fa-fw'/>
|
||||||
|
</button>
|
||||||
|
<div styleName='info-left-top-folderSelect'>FolderSelect</div>
|
||||||
|
</div>
|
||||||
|
<div styleName='info-left-bottom'>
|
||||||
|
<TagSelect
|
||||||
|
styleName='info-left-bottom-tagSelect'
|
||||||
|
ref='tags'
|
||||||
|
value={this.state.note.tags}
|
||||||
|
onChange={(e) => this.handleChange(e)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div styleName='info-right'>
|
<div styleName='info-right'>
|
||||||
<button styleName='info-right-button'>
|
<button styleName='info-right-button'>
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
$info-height = 80px
|
||||||
|
|
||||||
.root
|
.root
|
||||||
absolute top bottom right
|
absolute top bottom right
|
||||||
border-width 1px 0
|
border-width 1px 0
|
||||||
@@ -6,13 +8,22 @@
|
|||||||
|
|
||||||
.info
|
.info
|
||||||
absolute top left right
|
absolute top left right
|
||||||
height 50px
|
height $info-height
|
||||||
border-bottom $ui-border
|
border-bottom $ui-border
|
||||||
background-color $ui-backgroundColor
|
background-color $ui-backgroundColor
|
||||||
|
|
||||||
.info-left
|
.info-left
|
||||||
float left
|
float left
|
||||||
|
|
||||||
|
.info-left-top
|
||||||
|
height 40px
|
||||||
|
|
||||||
|
.info-left-bottom
|
||||||
|
height 40px
|
||||||
|
|
||||||
|
.info-left-bottom-tagSelect
|
||||||
|
height 40px
|
||||||
|
|
||||||
.info-right
|
.info-right
|
||||||
float right
|
float right
|
||||||
|
|
||||||
@@ -26,13 +37,15 @@
|
|||||||
margin 8px 2px
|
margin 8px 2px
|
||||||
padding 0
|
padding 0
|
||||||
&:active
|
&:active
|
||||||
border-color $ui-button--active-backgroundColor
|
border-color $ui-button--focus-borderColor
|
||||||
&:hover .left-control-newPostButton-tooltip
|
&:hover .left-control-newPostButton-tooltip
|
||||||
display block
|
display block
|
||||||
|
&:focus
|
||||||
|
border-color $ui-button--focus-borderColor
|
||||||
|
|
||||||
.body
|
.body
|
||||||
absolute bottom left right
|
absolute bottom left right
|
||||||
top 50px
|
top $info-height
|
||||||
|
|
||||||
.body-noteEditor
|
.body-noteEditor
|
||||||
absolute top bottom left right
|
absolute top bottom left right
|
||||||
|
|||||||
143
browser/main/Detail/TagSelect.js
Normal file
143
browser/main/Detail/TagSelect.js
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
import React, { PropTypes } from 'react'
|
||||||
|
import CSSModules from 'browser/lib/CSSModules'
|
||||||
|
import styles from './TagSelect.styl'
|
||||||
|
import _ from 'lodash'
|
||||||
|
|
||||||
|
class TagSelect extends React.Component {
|
||||||
|
constructor (props) {
|
||||||
|
super(props)
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
newTag: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount () {
|
||||||
|
this.value = this.props.value
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate () {
|
||||||
|
this.value = this.props.value
|
||||||
|
}
|
||||||
|
|
||||||
|
handleNewTagInputKeyDown (e) {
|
||||||
|
console.log(e.keyCode)
|
||||||
|
switch (e.keyCode) {
|
||||||
|
case 13:
|
||||||
|
this.submitTag()
|
||||||
|
break
|
||||||
|
case 8:
|
||||||
|
if (this.refs.newTag.value.length === 0) {
|
||||||
|
this.removeLastTag()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
removeLastTag () {
|
||||||
|
let { value } = this.props
|
||||||
|
|
||||||
|
value = value.slice()
|
||||||
|
value.pop()
|
||||||
|
value = _.uniq(value)
|
||||||
|
|
||||||
|
this.value = value
|
||||||
|
this.props.onChange()
|
||||||
|
}
|
||||||
|
|
||||||
|
reset () {
|
||||||
|
this.setState({
|
||||||
|
newTag: ''
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
submitTag () {
|
||||||
|
let { value } = this.props
|
||||||
|
let newTag = this.refs.newTag.value.trim()
|
||||||
|
|
||||||
|
if (newTag.length <= 0) {
|
||||||
|
this.setState({
|
||||||
|
newTag: ''
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
value = value.slice()
|
||||||
|
value.push(newTag)
|
||||||
|
value = _.uniq(value)
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
newTag: ''
|
||||||
|
}, () => {
|
||||||
|
this.value = value
|
||||||
|
this.props.onChange()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
handleNewTagInputChange (e) {
|
||||||
|
this.setState({
|
||||||
|
newTag: this.refs.newTag.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTagRemoveButtonClick (tag) {
|
||||||
|
return (e) => {
|
||||||
|
let { value } = this.props
|
||||||
|
|
||||||
|
value.splice(value.indexOf(tag), 1)
|
||||||
|
value = _.uniq(value)
|
||||||
|
|
||||||
|
this.value = value
|
||||||
|
this.props.onChange()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
let { value, className } = this.props
|
||||||
|
|
||||||
|
let tagList = value.map((tag) => {
|
||||||
|
return (
|
||||||
|
<span styleName='tag'
|
||||||
|
key={tag}
|
||||||
|
>
|
||||||
|
<button styleName='tag-removeButton'
|
||||||
|
onClick={(e) => this.handleTagRemoveButtonClick(tag)(e)}
|
||||||
|
>
|
||||||
|
<i className='fa fa-times fa-fw'/>
|
||||||
|
</button>
|
||||||
|
<span styleName='tag-label'>{tag}</span>
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={_.isString(className)
|
||||||
|
? 'TagSelect ' + className
|
||||||
|
: 'TagSelect'
|
||||||
|
}
|
||||||
|
styleName='root'
|
||||||
|
>
|
||||||
|
<i styleName='icon'
|
||||||
|
className='fa fa-tags'
|
||||||
|
/>
|
||||||
|
{tagList}
|
||||||
|
<input styleName='newTag'
|
||||||
|
ref='newTag'
|
||||||
|
value={this.state.newTag}
|
||||||
|
placeholder='Add tag...'
|
||||||
|
onChange={(e) => this.handleNewTagInputChange(e)}
|
||||||
|
onKeyDown={(e) => this.handleNewTagInputKeyDown(e)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TagSelect.propTypes = {
|
||||||
|
className: PropTypes.string,
|
||||||
|
value: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||||
|
onChange: PropTypes.func
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CSSModules(TagSelect, styles)
|
||||||
66
browser/main/Detail/TagSelect.styl
Normal file
66
browser/main/Detail/TagSelect.styl
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
.root
|
||||||
|
position relative
|
||||||
|
line-height 40px
|
||||||
|
user-select none
|
||||||
|
|
||||||
|
.icon
|
||||||
|
display inline-block
|
||||||
|
width 30px
|
||||||
|
line-height 40px
|
||||||
|
vertical-align top
|
||||||
|
text-align center
|
||||||
|
|
||||||
|
.tag
|
||||||
|
display inline-block
|
||||||
|
margin 0 2px
|
||||||
|
vertical-align middle
|
||||||
|
height 20px
|
||||||
|
clearfix()
|
||||||
|
|
||||||
|
.tag-removeButton
|
||||||
|
float left
|
||||||
|
height 20px
|
||||||
|
width 18px
|
||||||
|
margin 0
|
||||||
|
padding 0
|
||||||
|
border $ui-border
|
||||||
|
border-top-left-radius 5px
|
||||||
|
border-bottom-left-radius 5px
|
||||||
|
line-height 18px
|
||||||
|
background-color transparent
|
||||||
|
color $ui-button-color
|
||||||
|
&:hover
|
||||||
|
background-color $ui-button--hover-backgroundColor
|
||||||
|
&:active, &:active:hover
|
||||||
|
color $ui-button--active-color
|
||||||
|
background-color $ui-button--active-backgroundColor
|
||||||
|
border-color $ui-button--focus-borderColor
|
||||||
|
&:focus
|
||||||
|
border-color $ui-button--focus-borderColor
|
||||||
|
|
||||||
|
.tag-label
|
||||||
|
float left
|
||||||
|
height 20px
|
||||||
|
line-height 18px
|
||||||
|
border-top $ui-border
|
||||||
|
border-right $ui-border
|
||||||
|
border-bottom $ui-border
|
||||||
|
border-top-right-radius 5px
|
||||||
|
border-bottom-right-radius 5px
|
||||||
|
padding 0 6px
|
||||||
|
|
||||||
|
.newTag
|
||||||
|
display inline-block
|
||||||
|
margin 0 2px
|
||||||
|
vertical-align middle
|
||||||
|
height 24px
|
||||||
|
box-sizing borde-box
|
||||||
|
border none
|
||||||
|
border-bottom $ui-border
|
||||||
|
background-color transparent
|
||||||
|
outline none
|
||||||
|
padding 0 4px
|
||||||
|
&:focus
|
||||||
|
border-color $ui-input--focus-borderColor = #369DCD
|
||||||
|
&:disabled
|
||||||
|
background-color $ui-input--disabled-backgroundColor = #DDD
|
||||||
@@ -22,6 +22,7 @@ $ui-button-color = #939395
|
|||||||
$ui-button--hover-backgroundColor = rgba(126, 127, 129, 0.08)
|
$ui-button--hover-backgroundColor = rgba(126, 127, 129, 0.08)
|
||||||
$ui-button--active-color = white
|
$ui-button--active-color = white
|
||||||
$ui-button--active-backgroundColor = #6AA5E9
|
$ui-button--active-backgroundColor = #6AA5E9
|
||||||
|
$ui-button--focus-borderColor = lighten(#369DCD, 25%)
|
||||||
|
|
||||||
// UI Tooltip
|
// UI Tooltip
|
||||||
$ui-tooltip-text-color = white
|
$ui-tooltip-text-color = white
|
||||||
|
|||||||
Reference in New Issue
Block a user