From 6c542750f4f68ed88726b196dc5871b6a5060806 Mon Sep 17 00:00:00 2001 From: bimlas Date: Mon, 26 Mar 2018 16:48:07 +0200 Subject: [PATCH 1/8] 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: ![screencast](https://i.imgur.com/PwAdhLe.gif) After: ![screencast](https://i.imgur.com/s3JCaFq.gif) 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? --- browser/components/TagListItem.js | 19 ++++++---- browser/components/TagListItem.styl | 37 ++++++++++++++------ browser/main/NoteList/index.js | 3 +- browser/main/SideNav/index.js | 54 +++++++++++++++++++++++++---- browser/main/index.js | 3 ++ 5 files changed, 90 insertions(+), 26 deletions(-) diff --git a/browser/components/TagListItem.js b/browser/components/TagListItem.js index 4346ac21..cbac00ce 100644 --- a/browser/components/TagListItem.js +++ b/browser/components/TagListItem.js @@ -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}) => ( +
+ + +
) TagListItem.propTypes = { diff --git a/browser/components/TagListItem.styl b/browser/components/TagListItem.styl index 513d112a..4c5c7379 100644 --- a/browser/components/TagListItem.styl +++ b/browser/components/TagListItem.styl @@ -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 diff --git a/browser/main/NoteList/index.js b/browser/main/NoteList/index.js index dedad209..867457ca 100644 --- a/browser/main/NoteList/index.js +++ b/browser/main/NoteList/index.js @@ -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)) }) } diff --git a/browser/main/SideNav/index.js b/browser/main/SideNav/index.js index f8a65013..a9f9f0da 100644 --- a/browser/main/SideNav/index.js +++ b/browser/main/SideNav/index.js @@ -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 = (
({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 { { + 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) => { diff --git a/browser/main/index.js b/browser/main/index.js index 6e8bdcc5..02bf7125 100644 --- a/browser/main/index.js +++ b/browser/main/index.js @@ -112,6 +112,9 @@ ReactDOM.render(( + + + From 68c0f210ccb76a2c12e58120a68d64b9278a663c Mon Sep 17 00:00:00 2001 From: bimlas Date: Sat, 7 Apr 2018 15:43:06 +0200 Subject: [PATCH 2/8] Separate active tags by ` ` instead of `&` Using `&` to separate tags in path (like `/tags/currently&selected&tags`) may interfer with tags including `&` character (like `black&white`). Since ` ` is replaced with `_` when adding tag to notes, it's ideal separator because it's guaranteed that tags are not including this character. --- browser/main/NoteList/index.js | 2 +- browser/main/SideNav/index.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/browser/main/NoteList/index.js b/browser/main/NoteList/index.js index 867457ca..def289fb 100644 --- a/browser/main/NoteList/index.js +++ b/browser/main/NoteList/index.js @@ -343,7 +343,7 @@ class NoteList extends React.Component { } if (location.pathname.match(/\/tags/)) { - const listOfTags = params.tagname.split('&') + const listOfTags = params.tagname.split(' ') return data.noteMap.map(note => { return note }).filter(note => { diff --git a/browser/main/SideNav/index.js b/browser/main/SideNav/index.js index a9f9f0da..b4c1d322 100644 --- a/browser/main/SideNav/index.js +++ b/browser/main/SideNav/index.js @@ -196,7 +196,7 @@ class SideNav extends React.Component { if (tags === 'alltags') { return [] } - return tags.split('&') + return tags.split(' ') } handleClickTagListItem (name) { @@ -229,7 +229,7 @@ class SideNav extends React.Component { } else { listOfTags.push(name) } - router.push(`/tags/${listOfTags.join('&')}`) + router.push(`/tags/${listOfTags.join(' ')}`) } emptyTrash (entries) { From 61ed47dda04edebb276d0df2fa9645502bd47b89 Mon Sep 17 00:00:00 2001 From: bimlas Date: Tue, 10 Apr 2018 14:13:58 +0200 Subject: [PATCH 3/8] Don't narrow list, add plus sign only for related tags It's easier to understand by most of the users. Later I like to add a setting to enable narrowing of tag list to show only the related ones. --- browser/components/TagListItem.js | 11 +++++++---- browser/main/SideNav/index.js | 10 ++++++---- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/browser/components/TagListItem.js b/browser/components/TagListItem.js index cbac00ce..196a5a23 100644 --- a/browser/components/TagListItem.js +++ b/browser/components/TagListItem.js @@ -12,11 +12,14 @@ import CSSModules from 'browser/lib/CSSModules' * @param {bool} isActive */ -const TagListItem = ({name, handleClickTagListItem, handleClickNarrowToTag, isActive, count}) => ( +const TagListItem = ({name, handleClickTagListItem, handleClickNarrowToTag, isActive, isRelated, count}) => (
- + {isRelated + ? + :
+ } - :
+ + + :
}
+
+ +
{ global.process.platform === 'win32' ?
From 24b004bb2d37ccc5d10e9b1ee01bbdb27ac59e18 Mon Sep 17 00:00:00 2001 From: bimlas Date: Wed, 11 Apr 2018 11:45:16 +0200 Subject: [PATCH 7/8] Remove obsolete route path --- browser/main/SideNav/index.js | 2 +- browser/main/index.js | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/browser/main/SideNav/index.js b/browser/main/SideNav/index.js index 7af6bb81..6b53478e 100644 --- a/browser/main/SideNav/index.js +++ b/browser/main/SideNav/index.js @@ -91,7 +91,7 @@ class SideNav extends React.Component { let component // TagsMode is not selected - if (!location.pathname.match('/tags') && !location.pathname.match('/alltags') && !location.pathname.match('/narrowToTag')) { + if (!location.pathname.match('/tags') && !location.pathname.match('/alltags')) { component = (
- - - From c4ec69a43f3ae1d791398bba205ff9f60316ff8d Mon Sep 17 00:00:00 2001 From: bimlas Date: Wed, 11 Apr 2018 15:00:45 +0200 Subject: [PATCH 8/8] Add tests --- .../TagListItem.snapshot.test.js.snap | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/tests/components/__snapshots__/TagListItem.snapshot.test.js.snap b/tests/components/__snapshots__/TagListItem.snapshot.test.js.snap index 0805edcd..0521ca0e 100644 --- a/tests/components/__snapshots__/TagListItem.snapshot.test.js.snap +++ b/tests/components/__snapshots__/TagListItem.snapshot.test.js.snap @@ -1,19 +1,26 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`TagListItem renders correctly 1`] = ` - + +
`;