mirror of
https://github.com/BoostIo/Boostnote
synced 2026-02-03 19:17:18 +00:00
Merge pull request #2758 from elfman/colorTag
add feature: colored tags
This commit is contained in:
@@ -437,6 +437,7 @@ class MarkdownNoteDetail extends React.Component {
|
||||
showTagsAlphabetically={config.ui.showTagsAlphabetically}
|
||||
data={data}
|
||||
onChange={this.handleUpdateTag.bind(this)}
|
||||
coloredTags={config.coloredTags}
|
||||
/>
|
||||
<TodoListPercentage onClearCheckboxClick={(e) => this.handleClearTodo(e)} percentageOfTodo={getTodoPercentageOfCompleted(note.content)} />
|
||||
</div>
|
||||
|
||||
@@ -792,6 +792,7 @@ class SnippetNoteDetail extends React.Component {
|
||||
showTagsAlphabetically={config.ui.showTagsAlphabetically}
|
||||
data={data}
|
||||
onChange={(e) => this.handleChange(e)}
|
||||
coloredTags={config.coloredTags}
|
||||
/>
|
||||
</div>
|
||||
<div styleName='info-right'>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import PropTypes from 'prop-types'
|
||||
import React from 'react'
|
||||
import invertColor from 'invert-color'
|
||||
import CSSModules from 'browser/lib/CSSModules'
|
||||
import styles from './TagSelect.styl'
|
||||
import _ from 'lodash'
|
||||
@@ -185,19 +186,34 @@ class TagSelect extends React.Component {
|
||||
}
|
||||
|
||||
render () {
|
||||
const { value, className, showTagsAlphabetically } = this.props
|
||||
const { value, className, showTagsAlphabetically, coloredTags } = this.props
|
||||
|
||||
const tagList = _.isArray(value)
|
||||
? (showTagsAlphabetically ? _.sortBy(value) : value).map((tag) => {
|
||||
const wrapperStyle = {}
|
||||
const textStyle = {}
|
||||
const BLACK = '#333333'
|
||||
const WHITE = '#f1f1f1'
|
||||
const color = coloredTags[tag]
|
||||
const invertedColor = color && invertColor(color, { black: BLACK, white: WHITE })
|
||||
let iconRemove = '../resources/icon/icon-x.svg'
|
||||
if (color) {
|
||||
wrapperStyle.backgroundColor = color
|
||||
textStyle.color = invertedColor
|
||||
}
|
||||
if (invertedColor === WHITE) {
|
||||
iconRemove = '../resources/icon/icon-x-light.svg'
|
||||
}
|
||||
return (
|
||||
<span styleName='tag'
|
||||
key={tag}
|
||||
style={wrapperStyle}
|
||||
>
|
||||
<span styleName='tag-label' onClick={(e) => this.handleTagLabelClick(tag)}>#{tag}</span>
|
||||
<span styleName='tag-label' style={textStyle} onClick={(e) => this.handleTagLabelClick(tag)}>#{tag}</span>
|
||||
<button styleName='tag-removeButton'
|
||||
onClick={(e) => this.handleTagRemoveButtonClick(tag)}
|
||||
>
|
||||
<img className='tag-removeButton-icon' src='../resources/icon/icon-x.svg' width='8px' />
|
||||
<img className='tag-removeButton-icon' src={iconRemove} width='8px' />
|
||||
</button>
|
||||
</span>
|
||||
)
|
||||
@@ -246,7 +262,8 @@ TagSelect.contextTypes = {
|
||||
TagSelect.propTypes = {
|
||||
className: PropTypes.string,
|
||||
value: PropTypes.arrayOf(PropTypes.string),
|
||||
onChange: PropTypes.func
|
||||
onChange: PropTypes.func,
|
||||
coloredTags: PropTypes.object
|
||||
}
|
||||
|
||||
export default CSSModules(TagSelect, styles)
|
||||
|
||||
@@ -1047,6 +1047,7 @@ class NoteList extends React.Component {
|
||||
storageName={this.getNoteStorage(note).name}
|
||||
viewType={viewType}
|
||||
showTagsAlphabetically={config.ui.showTagsAlphabetically}
|
||||
coloredTags={config.coloredTags}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import i18n from 'browser/lib/i18n'
|
||||
import context from 'browser/lib/context'
|
||||
import { remote } from 'electron'
|
||||
import { confirmDeleteNote } from 'browser/lib/confirmDeleteNote'
|
||||
import ColorPicker from 'browser/components/ColorPicker'
|
||||
|
||||
function matchActiveTags (tags, activeTags) {
|
||||
return _.every(activeTags, v => tags.indexOf(v) >= 0)
|
||||
@@ -27,6 +28,22 @@ function matchActiveTags (tags, activeTags) {
|
||||
|
||||
class SideNav extends React.Component {
|
||||
// TODO: should not use electron stuff v0.7
|
||||
constructor (props) {
|
||||
super(props)
|
||||
|
||||
this.state = {
|
||||
colorPicker: {
|
||||
show: false,
|
||||
color: null,
|
||||
tagName: null,
|
||||
targetRect: null
|
||||
}
|
||||
}
|
||||
|
||||
this.dismissColorPicker = this.dismissColorPicker.bind(this)
|
||||
this.handleColorPickerConfirm = this.handleColorPickerConfirm.bind(this)
|
||||
this.handleColorPickerReset = this.handleColorPickerReset.bind(this)
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
EventEmitter.on('side:preferences', this.handleMenuButtonClick)
|
||||
@@ -104,9 +121,64 @@ class SideNav extends React.Component {
|
||||
click: this.deleteTag.bind(this, tag)
|
||||
})
|
||||
|
||||
menu.push({
|
||||
label: i18n.__('Customize Color'),
|
||||
click: this.displayColorPicker.bind(this, tag, e.target.getBoundingClientRect())
|
||||
})
|
||||
|
||||
context.popup(menu)
|
||||
}
|
||||
|
||||
dismissColorPicker () {
|
||||
this.setState({
|
||||
colorPicker: {
|
||||
show: false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
displayColorPicker (tagName, rect) {
|
||||
const { config } = this.props
|
||||
this.setState({
|
||||
colorPicker: {
|
||||
show: true,
|
||||
color: config.coloredTags[tagName],
|
||||
tagName,
|
||||
targetRect: rect
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
handleColorPickerConfirm (color) {
|
||||
const { dispatch, config: {coloredTags} } = this.props
|
||||
const { colorPicker: { tagName } } = this.state
|
||||
const newColoredTags = Object.assign({}, coloredTags, {[tagName]: color.hex})
|
||||
|
||||
const config = { coloredTags: newColoredTags }
|
||||
ConfigManager.set(config)
|
||||
dispatch({
|
||||
type: 'SET_CONFIG',
|
||||
config
|
||||
})
|
||||
this.dismissColorPicker()
|
||||
}
|
||||
|
||||
handleColorPickerReset () {
|
||||
const { dispatch, config: {coloredTags} } = this.props
|
||||
const { colorPicker: { tagName } } = this.state
|
||||
const newColoredTags = Object.assign({}, coloredTags)
|
||||
|
||||
delete newColoredTags[tagName]
|
||||
|
||||
const config = { coloredTags: newColoredTags }
|
||||
ConfigManager.set(config)
|
||||
dispatch({
|
||||
type: 'SET_CONFIG',
|
||||
config
|
||||
})
|
||||
this.dismissColorPicker()
|
||||
}
|
||||
|
||||
handleToggleButtonClick (e) {
|
||||
const { dispatch, config } = this.props
|
||||
|
||||
@@ -207,6 +279,7 @@ class SideNav extends React.Component {
|
||||
|
||||
tagListComponent () {
|
||||
const { data, location, config } = this.props
|
||||
const { colorPicker } = this.state
|
||||
const activeTags = this.getActiveTags(location.pathname)
|
||||
const relatedTags = this.getRelatedTags(activeTags, data.noteMap)
|
||||
let tagList = _.sortBy(data.tagNoteMap.map(
|
||||
@@ -237,10 +310,11 @@ class SideNav extends React.Component {
|
||||
handleClickTagListItem={this.handleClickTagListItem.bind(this)}
|
||||
handleClickNarrowToTag={this.handleClickNarrowToTag.bind(this)}
|
||||
handleContextMenu={this.handleTagContextMenu.bind(this)}
|
||||
isActive={this.getTagActive(location.pathname, tag.name)}
|
||||
isActive={this.getTagActive(location.pathname, tag.name) || (colorPicker.tagName === tag.name)}
|
||||
isRelated={tag.related}
|
||||
key={tag.name}
|
||||
count={tag.size}
|
||||
color={config.coloredTags[tag.name]}
|
||||
/>
|
||||
)
|
||||
})
|
||||
@@ -333,6 +407,7 @@ class SideNav extends React.Component {
|
||||
|
||||
render () {
|
||||
const { data, location, config, dispatch } = this.props
|
||||
const { colorPicker: colorPickerState } = this.state
|
||||
|
||||
const isFolded = config.isSideNavFolded
|
||||
|
||||
@@ -349,6 +424,20 @@ class SideNav extends React.Component {
|
||||
useDragHandle
|
||||
/>
|
||||
})
|
||||
|
||||
let colorPicker
|
||||
if (colorPickerState.show) {
|
||||
colorPicker = (
|
||||
<ColorPicker
|
||||
color={colorPickerState.color}
|
||||
targetRect={colorPickerState.targetRect}
|
||||
onConfirm={this.handleColorPickerConfirm}
|
||||
onCancel={this.dismissColorPicker}
|
||||
onReset={this.handleColorPickerReset}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
const style = {}
|
||||
if (!isFolded) style.width = this.props.width
|
||||
const isTagActive = location.pathname.match(/tag/)
|
||||
@@ -368,6 +457,7 @@ class SideNav extends React.Component {
|
||||
</div>
|
||||
</div>
|
||||
{this.SideNavComponent(isFolded, storageList)}
|
||||
{colorPicker}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -86,7 +86,8 @@ export const DEFAULT_CONFIG = {
|
||||
token: '',
|
||||
username: '',
|
||||
password: ''
|
||||
}
|
||||
},
|
||||
coloredTags: {}
|
||||
}
|
||||
|
||||
function validate (config) {
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
.folderItem-right-button
|
||||
vertical-align middle
|
||||
height 25px
|
||||
margin-top 2.5px
|
||||
margin-top 2px
|
||||
colorDefaultButton()
|
||||
border-radius 2px
|
||||
border $ui-border
|
||||
|
||||
Reference in New Issue
Block a user