1
0
mirror of https://github.com/BoostIo/Boostnote synced 2025-12-13 01:36:22 +00:00

Merge pull request #2964 from amedora/filter-tags-and-folders

Filter tags and folders
This commit is contained in:
Junyoung Choi
2020-02-06 16:21:15 +09:00
committed by GitHub
29 changed files with 301 additions and 37 deletions

View File

@@ -1,5 +1,5 @@
.menu
margin-bottom 30px
margin-bottom 20px
.menu-button
navButtonColor()

View File

@@ -1,7 +1,5 @@
.storageList
absolute left right
bottom 37px
top 180px
margin-bottom 37px
overflow-y auto
.storageList-folded

View File

@@ -1,8 +1,5 @@
.top-menu-preference
navButtonColor()
position absolute
top 22px
right 10px
width 2em
background-color transparent
&:hover

View File

@@ -0,0 +1,26 @@
import PropTypes from 'prop-types'
import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './SearchButton.styl'
import i18n from 'browser/lib/i18n'
const SearchButton = ({ onClick, isActive }) => (
<button styleName='top-menu-search' onClick={e => onClick(e)}>
<img
styleName='icon-search'
src={
isActive
? '../resources/icon/icon-search-active.svg'
: '../resources/icon/icon-search.svg'
}
/>
<span styleName='tooltip'>{i18n.__('Search')}</span>
</button>
)
SearchButton.propTypes = {
onClick: PropTypes.func.isRequired,
isActive: PropTypes.bool
}
export default CSSModules(SearchButton, styles)

View File

@@ -0,0 +1,55 @@
.top-menu-search
navButtonColor()
position relative
margin-right 6px
top 3px
width 2em
background-color transparent
&:hover
color $ui-button-default--active-backgroundColor
background-color transparent
.tooltip
opacity 1
&:active, &:active:hover
color $ui-button-default--active-backgroundColor
.icon-search
width 16px
body[data-theme="white"]
.top-menu-search
navWhiteButtonColor()
background-color transparent
&:hover
color #0B99F1
background-color transparent
&:active, &:active:hover
color #0B99F1
background-color transparent
body[data-theme="dark"]
.top-menu-search
navDarkButtonColor()
background-color transparent
&:active
background-color alpha($ui-dark-button--active-backgroundColor, 20%)
background-color transparent
&:hover
background-color alpha($ui-dark-button--active-backgroundColor, 20%)
background-color transparent
.tooltip
tooltip()
position absolute
pointer-events none
top 26px
left -20px
z-index 200
padding 5px
line-height normal
border-radius 2px
opacity 0
transition 0.1s
white-space nowrap

View File

@@ -9,16 +9,47 @@
flex-direction column
.top
padding-bottom 15px
display flex
align-items top
justify-content space-between
padding-bottom 10px
margin 14px 14px 4px
.switch-buttons
background-color transparent
border 0
margin 24px auto 4px 14px
display flex
align-items center
text-align center
.extra-buttons
position relative
display flex
align-items center
.search
position relative
flex 1
display flex
max-height 0
overflow hidden
transition max-height .4s
margin -5px 10px 0
.search-input
flex 1
height 2em
vertical-align middle
font-size 14px
border solid 1px $border-color
border-radius 2px
padding 2px 6px
outline none
.search-clear
width 10px
position absolute
right 8px
top 9px
cursor pointer
.top-menu-label
margin-left 5px
@@ -68,8 +99,15 @@
background-color #2E3235
.switch-buttons
display none
.extra-buttons > button:first-of-type // hide search icon
display none
.top
height 60px
align-items center
margin 0
justify-content center
position relative
left -4px
.top-menu
position static
width $sideNav--folded-width
@@ -98,17 +136,35 @@
.top-menu-preference
position absolute
left 7px
.search
height 28px
.search-input
display none
.search-clear
display none
.search-folded
width 16px
padding-left 4px
margin-bottom 8px
cursor pointer
body[data-theme="white"]
.root, .root--folded
background-color #f9f9f9
color $ui-text-color
.search .search-input
background-color #f9f9f9
color $ui-text-color
body[data-theme="dark"]
.root, .root--folded
border-right 1px solid $ui-dark-borderColor
background-color $ui-dark-backgroundColor
color $ui-dark-text-color
.search .search-input
background-color $ui-dark-backgroundColor
color $ui-dark-text-color
border-color $ui-dark-borderColor
.top
border-color $ui-dark-borderColor
@@ -119,6 +175,11 @@ apply-theme(theme)
background-color get-theme-var(theme, 'backgroundColor')
border-right 1px solid get-theme-var(theme, 'borderColor')
.search .search-input
background-color get-theme-var(theme, 'backgroundColor')
color get-theme-var(theme, 'text-color')
border-color get-theme-var(theme, 'borderColor')
for theme in 'solarized-dark' 'dracula'
apply-theme(theme)

View File

@@ -14,6 +14,7 @@ import StorageList from 'browser/components/StorageList'
import NavToggleButton from 'browser/components/NavToggleButton'
import EventEmitter from 'browser/main/lib/eventEmitter'
import PreferenceButton from './PreferenceButton'
import SearchButton from './SearchButton'
import ListButton from './ListButton'
import TagButton from './TagButton'
import { SortableContainer } from 'react-sortable-hoc'
@@ -38,13 +39,18 @@ class SideNav extends React.Component {
show: false,
color: null,
tagName: null,
targetRect: null
targetRect: null,
showSearch: false,
searchText: ''
}
}
this.dismissColorPicker = this.dismissColorPicker.bind(this)
this.handleColorPickerConfirm = this.handleColorPickerConfirm.bind(this)
this.handleColorPickerReset = this.handleColorPickerReset.bind(this)
this.handleSearchButtonClick = this.handleSearchButtonClick.bind(this)
this.handleSearchInputChange = this.handleSearchInputChange.bind(this)
this.handleSearchInputClear = this.handleSearchInputClear.bind(this)
}
componentDidMount() {
@@ -117,6 +123,26 @@ class SideNav extends React.Component {
openModal(PreferencesModal)
}
handleSearchButtonClick(e) {
const { showSearch } = this.state
this.setState({
showSearch: !showSearch,
searchText: ''
})
}
handleSearchInputClear(e) {
this.setState({
searchText: ''
})
}
handleSearchInputChange(e) {
this.setState({
searchText: e.target.value
})
}
handleHomeButtonClick(e) {
const { dispatch } = this.props
dispatch(push('/home'))
@@ -211,12 +237,19 @@ class SideNav extends React.Component {
handleToggleButtonClick(e) {
const { dispatch, config } = this.props
const { showSearch, searchText } = this.state
ConfigManager.set({ isSideNavFolded: !config.isSideNavFolded })
dispatch({
type: 'SET_IS_SIDENAV_FOLDED',
isFolded: !config.isSideNavFolded
})
if (showSearch && searchText.length === 0) {
this.setState({
showSearch: false
})
}
}
handleTrashedButtonClick(e) {
@@ -243,8 +276,9 @@ class SideNav extends React.Component {
}
}
SideNavComponent(isFolded, storageList) {
const { location, data, config } = this.props
SideNavComponent(isFolded) {
const { location, data, config, dispatch } = this.props
const { showSearch, searchText } = this.state
const isHomeActive = !!location.pathname.match(/^\/home$/)
const isStarredActive = !!location.pathname.match(/^\/starred$/)
@@ -257,6 +291,33 @@ class SideNav extends React.Component {
!location.pathname.match('/tags') &&
!location.pathname.match('/alltags')
) {
let storageMap = data.storageMap
if (showSearch && searchText.length > 0) {
storageMap = storageMap.map(storage => {
const folders = storage.folders.filter(
folder =>
folder.name.toLowerCase().indexOf(searchText.toLowerCase()) !== -1
)
return Object.assign({}, storage, { folders })
})
}
const storageList = storageMap.map((storage, key) => {
const SortableStorageItem = SortableContainer(StorageItem)
return (
<SortableStorageItem
key={storage.key}
storage={storage}
data={data}
location={location}
isFolded={isFolded}
dispatch={dispatch}
onSortEnd={this.onSortEnd.bind(this)(storage)}
useDragHandle
/>
)
})
component = (
<div>
<SideNavFilter
@@ -322,7 +383,7 @@ class SideNav extends React.Component {
tagListComponent() {
const { data, location, config } = this.props
const { colorPicker } = this.state
const { colorPicker, showSearch, searchText } = this.state
const activeTags = this.getActiveTags(location.pathname)
const relatedTags = this.getRelatedTags(activeTags, data.noteMap)
let tagList = sortBy(
@@ -335,6 +396,11 @@ class SideNav extends React.Component {
.filter(tag => tag.size > 0),
['name']
)
if (showSearch && searchText.length > 0) {
tagList = tagList.filter(
tag => tag.name.toLowerCase().indexOf(searchText.toLowerCase()) !== -1
)
}
if (config.ui.enableLiveNoteCounts && activeTags.length !== 0) {
const notesTags = data.noteMap.map(note => note.tags)
tagList = tagList.map(tag => {
@@ -455,26 +521,8 @@ class SideNav extends React.Component {
}
render() {
const { data, location, config, dispatch } = this.props
const { colorPicker: colorPickerState } = this.state
const isFolded = config.isSideNavFolded
const storageList = data.storageMap.map((storage, key) => {
const SortableStorageItem = SortableContainer(StorageItem)
return (
<SortableStorageItem
key={storage.key}
storage={storage}
data={data}
location={location}
isFolded={isFolded}
dispatch={dispatch}
onSortEnd={this.onSortEnd.bind(this)(storage)}
useDragHandle
/>
)
})
const { location, config } = this.props
const { showSearch, searchText, colorPicker: colorPickerState } = this.state
let colorPicker
if (colorPickerState.show) {
@@ -489,9 +537,35 @@ class SideNav extends React.Component {
)
}
const isFolded = config.isSideNavFolded
const style = {}
if (!isFolded) style.width = this.props.width
const isTagActive = /tag/.test(location.pathname)
const navSearch = (
<div styleName='search' style={{ maxHeight: showSearch ? '3em' : '0' }}>
<input
styleName='search-input'
type='text'
onChange={this.handleSearchInputChange}
value={searchText}
placeholder={i18n.__('Filter tags/folders...')}
/>
<img
styleName='search-clear'
src='../resources/icon/icon-x.svg'
onClick={this.handleSearchInputClear}
/>
{isFolded && (
<img
styleName='search-folded'
src='../resources/icon/icon-search-active.svg'
onClick={this.handleSearchButtonClick}
/>
)}
</div>
)
return (
<div
className='SideNav'
@@ -510,11 +584,16 @@ class SideNav extends React.Component {
isTagActive={isTagActive}
/>
</div>
<div>
<PreferenceButton onClick={this.handleMenuButtonClick} />
<div styleName='extra-buttons'>
<SearchButton
onClick={this.handleSearchButtonClick}
isActive={showSearch}
/>
<PreferenceButton onClick={this.handlePreferenceButtonClick} />
</div>
</div>
{this.SideNavComponent(isFolded, storageList)}
{navSearch}
{this.SideNavComponent(isFolded)}
{colorPicker}
</div>
)

View File

@@ -159,6 +159,7 @@
"Spellcheck disabled": "Spellcheck disabled",
"Show menu bar": "Show menu bar",
"Auto Detect": "Auto Detect",
"Filter tags/folders...": "filter tags/folders...",
"Enable HTML label in mermaid flowcharts": "Enable HTML label in mermaid flowcharts ⚠ This option potentially has a risk of XSS.",
"Wrap line in Snippet Note": "Wrap line in Snippet Note"
}

View File

@@ -215,6 +215,7 @@
"Spellcheck disabled": "Spellcheck disabled",
"Show menu bar": "Show menu bar",
"Auto Detect": "Auto Detect",
"Filter tags/folders...": "filter tags/ordner...",
"Enable HTML label in mermaid flowcharts": "Enable HTML label in mermaid flowcharts ⚠ This option potentially has a risk of XSS.",
"Wrap line in Snippet Note": "Wrap line in Snippet Note"
}

View File

@@ -190,6 +190,7 @@
"New notes are tagged with the filtering tags": "New notes are tagged with the filtering tags",
"Show menu bar": "Show menu bar",
"Auto Detect": "Auto Detect",
"Filter tags/folders...": "filter tags/folders...",
"Enable HTML label in mermaid flowcharts": "Enable HTML label in mermaid flowcharts ⚠ This option potentially has a risk of XSS.",
"Wrap line in Snippet Note": "Wrap line in Snippet Note",
"Enable Auto Update": "Enable Auto Update"

View File

@@ -161,6 +161,7 @@
"Show menu bar": "Mostrar barra del menú",
"Auto Detect": "Detección automática",
"Snippet Default Language": "Lenguaje por defecto de los fragmentos de código",
"Filter tags/folders...": "filter etiquetas/carpeta...",
"Enable HTML label in mermaid flowcharts": "Enable HTML label in mermaid flowcharts ⚠ This option potentially has a risk of XSS.",
"Wrap line in Snippet Note": "Wrap line in Snippet Note"
}

View File

@@ -163,6 +163,7 @@
"Spellcheck disabled": "Spellcheck disabled",
"Show menu bar": "Show menu bar",
"Auto Detect": "Auto Detect",
"Filter tags/folders...": "filter tags/folders...",
"Enable HTML label in mermaid flowcharts": "Enable HTML label in mermaid flowcharts ⚠ This option potentially has a risk of XSS.",
"Wrap line in Snippet Note": "Wrap line in Snippet Note"
}

View File

@@ -175,6 +175,7 @@
"Snippet prefix": "Préfixe du snippet",
"Delete Note": "Supprimer la note",
"New notes are tagged with the filtering tags": "Les nouvelles notes sont taggées avec les tags de filtrage",
"Filter tags/folders...": "filtrage tags/dossier...",
"Enable HTML label in mermaid flowcharts": "Enable HTML label in mermaid flowcharts ⚠ This option potentially has a risk of XSS.",
"Wrap line in Snippet Note": "Wrap line in Snippet Note"
}

View File

@@ -183,6 +183,7 @@
"Spellcheck disabled": "Spellcheck disabled",
"Show menu bar": "Show menu bar",
"Auto Detect": "Auto Detect",
"Filter tags/folders...": "filter tags/folders...",
"Enable HTML label in mermaid flowcharts": "Enable HTML label in mermaid flowcharts ⚠ This option potentially has a risk of XSS.",
"Wrap line in Snippet Note": "Wrap line in Snippet Note"
}

View File

@@ -163,6 +163,7 @@
"Spellcheck disabled": "Spellcheck disabled",
"Show menu bar": "Show menu bar",
"Auto Detect": "Auto Detect",
"Filter tags/folders...": "filter tags/folders...",
"Enable HTML label in mermaid flowcharts": "Enable HTML label in mermaid flowcharts ⚠ This option potentially has a risk of XSS.",
"Wrap line in Snippet Note": "Wrap line in Snippet Note"
}

View File

@@ -222,6 +222,7 @@
"Spellcheck disabled": "スペルチェック無効",
"Show menu bar": "メニューバーを表示",
"Auto Detect": "自動検出",
"Filter tags/folders...": "タグ/フォルダをフィルタ...",
"Enable HTML label in mermaid flowcharts": "mermaid flowchartでHTMLラベルを有効にする ⚠ このオプションには潜在的なXSSの危険性があります。",
"Wrap line in Snippet Note": "行を右端で折り返すSnippet Note"
}

View File

@@ -166,6 +166,7 @@
"Spellcheck disabled": "Spellcheck disabled",
"Show menu bar": "Show menu bar",
"Auto Detect": "Auto Detect",
"Filter tags/folders...": "filter tags/folders...",
"Enable HTML label in mermaid flowcharts": "Enable HTML label in mermaid flowcharts ⚠ This option potentially has a risk of XSS.",
"Wrap line in Snippet Note": "Wrap line in Snippet Note"
}

View File

@@ -158,6 +158,7 @@
"Spellcheck disabled": "Spellcheck disabled",
"Show menu bar": "Show menu bar",
"Auto Detect": "Auto Detect",
"Filter tags/folders...": "filter tags/folders...",
"Enable HTML label in mermaid flowcharts": "Enable HTML label in mermaid flowcharts ⚠ This option potentially has a risk of XSS.",
"Wrap line in Snippet Note": "Wrap line in Snippet Note"
}

View File

@@ -168,6 +168,7 @@
"Spellcheck disabled": "Spellcheck disabled",
"Show menu bar": "Show menu bar",
"Auto Detect": "Auto Detect",
"Filter tags/folders...": "filter tags/folders...",
"Enable HTML label in mermaid flowcharts": "Enable HTML label in mermaid flowcharts ⚠ This option potentially has a risk of XSS.",
"Wrap line in Snippet Note": "Wrap line in Snippet Note"
}

View File

@@ -159,6 +159,7 @@
"Spellcheck disabled": "Spellcheck disabled",
"Show menu bar": "Show menu bar",
"Auto Detect": "Auto Detect",
"Filter tags/folders...": "filter tags/folders...",
"Enable HTML label in mermaid flowcharts": "Enable HTML label in mermaid flowcharts ⚠ This option potentially has a risk of XSS.",
"Wrap line in Snippet Note": "Wrap line in Snippet Note"
}

View File

@@ -158,6 +158,7 @@
"Spellcheck disabled": "Spellcheck disabled",
"Show menu bar": "Show menu bar",
"Auto Detect": "Auto Detect",
"Filter tags/folders...": "filter tags/folders...",
"Enable HTML label in mermaid flowcharts": "Enable HTML label in mermaid flowcharts ⚠ This option potentially has a risk of XSS.",
"Wrap line in Snippet Note": "Wrap line in Snippet Note"
}

View File

@@ -156,6 +156,7 @@
"Spellcheck disabled": "Spellcheck disabled",
"Show menu bar": "Show menu bar",
"Auto Detect": "Auto Detect",
"Filter tags/folders...": "filter tags/folders...",
"Enable HTML label in mermaid flowcharts": "Enable HTML label in mermaid flowcharts ⚠ This option potentially has a risk of XSS.",
"Wrap line in Snippet Note": "Wrap line in Snippet Note"
}

View File

@@ -158,6 +158,7 @@
"Spellcheck disabled": "Spellcheck disabled",
"Show menu bar": "Show menu bar",
"Auto Detect": "Auto Detect",
"Filter tags/folders...": "filter tags/folders...",
"Enable HTML label in mermaid flowcharts": "Enable HTML label in mermaid flowcharts ⚠ This option potentially has a risk of XSS.",
"Wrap line in Snippet Note": "Wrap line in Snippet Note"
}

View File

@@ -185,6 +185,7 @@
"Spellcheck disabled": "Spellcheck disabled",
"Show menu bar": "Show menu bar",
"Auto Detect": "Auto Detect",
"Filter tags/folders...": "filter tags/folders...",
"Enable HTML label in mermaid flowcharts": "Enable HTML label in mermaid flowcharts ⚠ This option potentially has a risk of XSS.",
"Wrap line in Snippet Note": "Wrap line in Snippet Note"
}

View File

@@ -158,6 +158,7 @@
"Spellcheck disabled": "Spellcheck disabled",
"Show menu bar": "Show menu bar",
"Auto Detect": "Auto Detect",
"Filter tags/folders...": "filter tags/folders...",
"Enable HTML label in mermaid flowcharts": "Enable HTML label in mermaid flowcharts ⚠ This option potentially has a risk of XSS.",
"Wrap line in Snippet Note": "Wrap line in Snippet Note"
}

1
locales/zh-CN.json Normal file → Executable file
View File

@@ -223,6 +223,7 @@
"Spellcheck disabled": "拼写检查已禁用",
"Show menu bar": "显示菜单栏",
"Auto Detect": "自动检测",
"Filter tags/folders...": "filter tags/folders...",
"Enable HTML label in mermaid flowcharts": "在 mermaid flowcharts 中启用 HTML 标签 ⚠ 这个选项可能会产生 XSS",
"Wrap line in Snippet Note": "在 Snippet Note 里换行",
"Toggle Editor Mode": "切换编辑模式",

1
locales/zh-TW.json Normal file → Executable file
View File

@@ -167,6 +167,7 @@
"Spellcheck disabled": "Spellcheck disabled",
"Show menu bar": "Show menu bar",
"Auto Detect": "Auto Detect",
"Filter tags/folders...": "filter tags/folders...",
"Enable HTML label in mermaid flowcharts": "Enable HTML label in mermaid flowcharts ⚠ This option potentially has a risk of XSS.",
"Wrap line in Snippet Note": "Wrap line in Snippet Note"
}

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg t="1546833265368" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="1101" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200">
<defs>
<style type="text/css"></style>
</defs>
<path
d="M384 768c-213.333333 0-384-170.666667-384-384s170.666667-384 384-384 384 170.666667 384 384S597.333333 768 384 768zM384 85.333333C217.6 85.333333 85.333333 217.6 85.333333 384s132.266667 298.666667 298.666667 298.666667 298.666667-132.266667 298.666667-298.666667S550.4 85.333333 384 85.333333z"
p-id="1102" fill="#1EC38B"></path>
<path
d="M981.333333 1024c-12.8 0-21.333333-4.266667-29.866667-12.8l-341.333333-341.333333c-17.066667-17.066667-17.066667-42.666667 0-59.733333s42.666667-17.066667 59.733333 0l341.333333 341.333333c17.066667 17.066667 17.066667 42.666667 0 59.733333C1002.666667 1019.733333 994.133333 1024 981.333333 1024z"
p-id="1103" fill="#1EC38B"></path>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg t="1546833265368" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="1101" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200">
<defs>
<style type="text/css"></style>
</defs>
<path
d="M384 768c-213.333333 0-384-170.666667-384-384s170.666667-384 384-384 384 170.666667 384 384S597.333333 768 384 768zM384 85.333333C217.6 85.333333 85.333333 217.6 85.333333 384s132.266667 298.666667 298.666667 298.666667 298.666667-132.266667 298.666667-298.666667S550.4 85.333333 384 85.333333z"
p-id="1102" fill="#8A8C8D"></path>
<path
d="M981.333333 1024c-12.8 0-21.333333-4.266667-29.866667-12.8l-341.333333-341.333333c-17.066667-17.066667-17.066667-42.666667 0-59.733333s42.666667-17.066667 59.733333 0l341.333333 341.333333c17.066667 17.066667 17.066667 42.666667 0 59.733333C1002.666667 1019.733333 994.133333 1024 981.333333 1024z"
p-id="1103" fill="#8A8C8D"></path>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB