mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-13 17:56:25 +00:00
Narrow list of tags to related ones
When a tag is selected, the tag list narrows to show only the related ones: all tags associated to the currently visible notes. Clicking on the plus sign near another tag narrows the list again to the tags of notes associated with the firstly AND secondly selected tag. To show every tags again, press the tag icon on the top-left corner of Boostnote. Before:  After:  NOTE: Tags are joined with `&` character (`#` not works) in `location.pathname` thus it will make the tags with this character unavailable. Any suggestion to pass multiple values via pathname?
This commit is contained in:
@@ -12,13 +12,18 @@ import CSSModules from 'browser/lib/CSSModules'
|
||||
* @param {bool} isActive
|
||||
*/
|
||||
|
||||
const TagListItem = ({name, handleClickTagListItem, isActive, count}) => (
|
||||
const TagListItem = ({name, handleClickTagListItem, handleClickNarrowToTag, isActive, count}) => (
|
||||
<div styleName='tagList-itemContainer'>
|
||||
<button styleName={isActive ? 'tagList-itemNarrow-active' : 'tagList-itemNarrow'} onClick={() => handleClickNarrowToTag(name)}>
|
||||
<i className={isActive ? 'fa fa-minus-circle' : 'fa fa-plus-circle'} />
|
||||
</button>
|
||||
<button styleName={isActive ? 'tagList-item-active' : 'tagList-item'} onClick={() => handleClickTagListItem(name)}>
|
||||
<span styleName='tagList-item-name'>
|
||||
{`# ${name}`}
|
||||
<span styleName='tagList-item-count'>{count}</span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
|
||||
TagListItem.propTypes = {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
.tagList-item
|
||||
.tagList-itemContainer
|
||||
display flex
|
||||
width 100%
|
||||
|
||||
.tagList-item, .tagList-itemNarrow
|
||||
height 26px
|
||||
background-color transparent
|
||||
color $ui-inactive-text-color
|
||||
padding 0
|
||||
margin-bottom 5px
|
||||
text-align left
|
||||
border none
|
||||
@@ -20,12 +20,18 @@
|
||||
color $ui-button-default-color
|
||||
background-color $ui-button-default--active-backgroundColor
|
||||
|
||||
.tagList-item-active
|
||||
background-color $ui-button-default--active-backgroundColor
|
||||
.tagList-item
|
||||
display flex
|
||||
flex 1
|
||||
width 100%
|
||||
height 26px
|
||||
padding 0
|
||||
|
||||
.tagList-itemNarrow
|
||||
padding 0 4px
|
||||
|
||||
.tagList-item-active, .tagList-itemNarrow-active
|
||||
background-color $ui-button-default--active-backgroundColor
|
||||
height 26px
|
||||
margin-bottom 5px
|
||||
text-align left
|
||||
border none
|
||||
@@ -36,10 +42,19 @@
|
||||
background-color alpha($ui-button-default--active-backgroundColor, 60%)
|
||||
transition 0.2s
|
||||
|
||||
.tagList-item-active
|
||||
display flex
|
||||
flex 1
|
||||
width 100%
|
||||
padding 0
|
||||
|
||||
.tagList-itemNarrow-active
|
||||
padding 0 4px
|
||||
|
||||
.tagList-item-name
|
||||
display block
|
||||
flex 1
|
||||
padding 0 15px
|
||||
padding 0 8px 0 4px
|
||||
height 26px
|
||||
line-height 26px
|
||||
border-width 0 0 0 2px
|
||||
@@ -55,7 +70,7 @@
|
||||
font-size 13px
|
||||
|
||||
body[data-theme="white"]
|
||||
.tagList-item
|
||||
.tagList-item, .tagList-itemNarrow
|
||||
color $ui-inactive-text-color
|
||||
&:hover
|
||||
color $ui-text-color
|
||||
@@ -64,7 +79,7 @@ body[data-theme="white"]
|
||||
color $ui-text-color
|
||||
background-color $ui-button--active-backgroundColor
|
||||
|
||||
.tagList-item-active
|
||||
.tagList-item-active, .tagList-itemNarrow-active
|
||||
background-color $ui-button--active-backgroundColor
|
||||
color $ui-text-color
|
||||
&:hover
|
||||
@@ -73,7 +88,7 @@ body[data-theme="white"]
|
||||
color $ui-text-color
|
||||
|
||||
body[data-theme="dark"]
|
||||
.tagList-item
|
||||
.tagList-item, .tagList-itemNarrow
|
||||
color $ui-dark-inactive-text-color
|
||||
&:hover
|
||||
color $ui-dark-text-color
|
||||
@@ -82,7 +97,7 @@ body[data-theme="dark"]
|
||||
color $ui-dark-text-color
|
||||
background-color $ui-dark-button--active-backgroundColor
|
||||
|
||||
.tagList-item-active
|
||||
.tagList-item-active, .tagList-itemNarrow-active
|
||||
background-color $ui-dark-button--active-backgroundColor
|
||||
color $ui-dark-text-color
|
||||
&:active
|
||||
|
||||
@@ -343,10 +343,11 @@ class NoteList extends React.Component {
|
||||
}
|
||||
|
||||
if (location.pathname.match(/\/tags/)) {
|
||||
const listOfTags = params.tagname.split('&')
|
||||
return data.noteMap.map(note => {
|
||||
return note
|
||||
}).filter(note => {
|
||||
return note.tags.includes(params.tagname)
|
||||
return listOfTags.every((tag) => note.tags.includes(tag))
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ class SideNav extends React.Component {
|
||||
let component
|
||||
|
||||
// TagsMode is not selected
|
||||
if (!location.pathname.match('/tags') && !location.pathname.match('/alltags')) {
|
||||
if (!location.pathname.match('/tags') && !location.pathname.match('/alltags') && !location.pathname.match('/narrowToTag')) {
|
||||
component = (
|
||||
<div>
|
||||
<SideNavFilter
|
||||
@@ -145,10 +145,12 @@ class SideNav extends React.Component {
|
||||
|
||||
tagListComponent () {
|
||||
const { data, location, config } = this.props
|
||||
let tagList = _.sortBy(data.tagNoteMap.map(
|
||||
(tag, name) => ({name, size: tag.size})),
|
||||
['name']
|
||||
)
|
||||
const relatedTags = this.getRelatedTags(this.getActiveTags(location.pathname), data.noteMap)
|
||||
let tagList = _.sortBy(data.tagNoteMap.map((tag, name) => {
|
||||
return { name, size: tag.size }
|
||||
}), ['name']).filter(tag => {
|
||||
return (relatedTags.size === 0) ? true : relatedTags.has(tag.name)
|
||||
})
|
||||
if (config.sortTagsBy === 'COUNTER') {
|
||||
tagList = _.sortBy(tagList, item => (0 - item.size))
|
||||
}
|
||||
@@ -158,6 +160,7 @@ class SideNav extends React.Component {
|
||||
<TagListItem
|
||||
name={tag.name}
|
||||
handleClickTagListItem={this.handleClickTagListItem.bind(this)}
|
||||
handleClickNarrowToTag={this.handleClickNarrowToTag.bind(this)}
|
||||
isActive={this.getTagActive(location.pathname, tag.name)}
|
||||
key={tag.name}
|
||||
count={tag.size}
|
||||
@@ -167,10 +170,33 @@ class SideNav extends React.Component {
|
||||
)
|
||||
}
|
||||
|
||||
getRelatedTags (activeTags, noteMap) {
|
||||
const relatedNotes = noteMap.map(note => {
|
||||
return {key: note.key, tags: note.tags}
|
||||
}).filter((note) => {
|
||||
return activeTags.every((tag) => note.tags.includes(tag))
|
||||
})
|
||||
let relatedTags = new Set()
|
||||
relatedNotes.forEach(note => {
|
||||
note.tags.map(tag => {
|
||||
relatedTags.add(tag)
|
||||
})
|
||||
})
|
||||
return relatedTags
|
||||
}
|
||||
|
||||
getTagActive (path, tag) {
|
||||
const pathTag = this.getActiveTags(path)
|
||||
return pathTag.includes(tag)
|
||||
}
|
||||
|
||||
getActiveTags (path) {
|
||||
const pathSegments = path.split('/')
|
||||
const pathTag = pathSegments[pathSegments.length - 1]
|
||||
return pathTag === tag
|
||||
const tags = pathSegments[pathSegments.length - 1]
|
||||
if (tags === 'alltags') {
|
||||
return []
|
||||
}
|
||||
return tags.split('&')
|
||||
}
|
||||
|
||||
handleClickTagListItem (name) {
|
||||
@@ -192,6 +218,20 @@ class SideNav extends React.Component {
|
||||
})
|
||||
}
|
||||
|
||||
handleClickNarrowToTag (name) {
|
||||
const { router } = this.context
|
||||
const { location } = this.props
|
||||
let listOfTags = this.getActiveTags(location.pathname)
|
||||
if (listOfTags.includes(name)) {
|
||||
listOfTags = listOfTags.filter(function (currentTag) {
|
||||
return name !== currentTag
|
||||
})
|
||||
} else {
|
||||
listOfTags.push(name)
|
||||
}
|
||||
router.push(`/tags/${listOfTags.join('&')}`)
|
||||
}
|
||||
|
||||
emptyTrash (entries) {
|
||||
const { dispatch } = this.props
|
||||
const deletionPromises = entries.map((note) => {
|
||||
|
||||
@@ -112,6 +112,9 @@ ReactDOM.render((
|
||||
<IndexRedirect to='/alltags' />
|
||||
<Route path=':tagname' />
|
||||
</Route>
|
||||
<Route path='narrowToTag'>
|
||||
<Route path=':tag' />
|
||||
</Route>
|
||||
<Route path='storages'>
|
||||
<IndexRedirect to='/home' />
|
||||
<Route path=':storageKey'>
|
||||
|
||||
Reference in New Issue
Block a user