Text search
This commit is contained in:
parent
e3dc339be3
commit
87413c3ad9
6 changed files with 92 additions and 7 deletions
|
@ -227,6 +227,11 @@ class BoardPage implements IPageController {
|
|||
this.filterAnchorElement = ahchorElement
|
||||
this.render()
|
||||
}
|
||||
|
||||
setSearchText(text?: string) {
|
||||
this.boardTree.setSearchText(text)
|
||||
this.render()
|
||||
}
|
||||
}
|
||||
|
||||
export { BoardPage }
|
||||
|
|
|
@ -17,6 +17,7 @@ class BoardTree {
|
|||
activeView?: BoardView
|
||||
groupByProperty?: IPropertyTemplate
|
||||
|
||||
private searchText?: string
|
||||
private allCards: IBlock[] = []
|
||||
get allBlocks(): IBlock[] {
|
||||
return [this.board, ...this.views, ...this.allCards]
|
||||
|
@ -93,8 +94,18 @@ class BoardTree {
|
|||
this.applyFilterSortAndGroup()
|
||||
}
|
||||
|
||||
getSearchText(): string | undefined {
|
||||
return this.searchText
|
||||
}
|
||||
|
||||
setSearchText(text?: string) {
|
||||
this.searchText = text
|
||||
this.applyFilterSortAndGroup()
|
||||
}
|
||||
|
||||
applyFilterSortAndGroup() {
|
||||
this.cards = this.filterCards(this.allCards)
|
||||
this.cards = this.searchFilterCards(this.cards)
|
||||
this.cards = this.sortCards(this.cards)
|
||||
|
||||
if (this.activeView.groupById) {
|
||||
|
@ -104,6 +115,15 @@ class BoardTree {
|
|||
}
|
||||
}
|
||||
|
||||
private searchFilterCards(cards: IBlock[]) {
|
||||
const searchText = this.searchText?.toLocaleLowerCase()
|
||||
if (!searchText) { return cards.slice() }
|
||||
|
||||
return cards.filter(card => {
|
||||
if (card.title?.toLocaleLowerCase().indexOf(searchText) !== -1) { return true }
|
||||
})
|
||||
}
|
||||
|
||||
private setGroupByProperty(propertyId: string) {
|
||||
const { board } = this
|
||||
|
||||
|
|
|
@ -25,15 +25,23 @@ type Props = {
|
|||
|
||||
type State = {
|
||||
isHoverOnCover: boolean
|
||||
isSearching: boolean
|
||||
}
|
||||
|
||||
class BoardComponent extends React.Component<Props, State> {
|
||||
private draggedCard: IBlock
|
||||
private draggedHeaderOption: IPropertyOption
|
||||
private searchFieldRef = React.createRef<Editable>()
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props)
|
||||
this.state = { isHoverOnCover: false }
|
||||
this.state = { isHoverOnCover: false, isSearching: !!this.props.boardTree?.getSearchText() }
|
||||
}
|
||||
|
||||
componentDidUpdate(prevPros: Props, prevState: State) {
|
||||
if (this.state.isSearching && !prevState.isSearching) {
|
||||
this.searchFieldRef.current.focus()
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -87,9 +95,18 @@ class BoardComponent extends React.Component<Props, State> {
|
|||
<div className="octo-button" id="groupByButton" onClick={(e) => { this.groupByClicked(e) }}>
|
||||
Group by <span style={groupByStyle} id="groupByLabel">{boardTree.groupByProperty?.name}</span>
|
||||
</div>
|
||||
<div className={ hasFilter ? "octo-button active" : "octo-button"} onClick={(e) => { this.filterClicked(e) }}>Filter</div>
|
||||
<div className={ hasSort ? "octo-button active" : "octo-button"} onClick={(e) => { this.sortClicked(e) }}>Sort</div>
|
||||
<div className="octo-button">Search</div>
|
||||
<div className={hasFilter ? "octo-button active" : "octo-button"} onClick={(e) => { this.filterClicked(e) }}>Filter</div>
|
||||
<div className={hasSort ? "octo-button active" : "octo-button"} onClick={(e) => { this.sortClicked(e) }}>Sort</div>
|
||||
{this.state.isSearching
|
||||
? <Editable
|
||||
ref={this.searchFieldRef}
|
||||
text={boardTree.getSearchText()}
|
||||
placeholderText="Search text"
|
||||
style={{ color: "#000000" }}
|
||||
onChanged={(text) => { this.searchChanged(text) }}
|
||||
onKeyDown={(e) => { this.onSearchKeyDown(e) }}></Editable>
|
||||
: <div className="octo-button" onClick={() => { this.setState({ ...this.state, isSearching: true }) }}>Search</div>
|
||||
}
|
||||
<div className="octo-button" onClick={(e) => { this.optionsClicked(e) }}><div className="imageOptions" /></div>
|
||||
<div className="octo-button filled" onClick={() => { this.addCard(undefined) }}>New</div>
|
||||
</div>
|
||||
|
@ -380,6 +397,19 @@ class BoardComponent extends React.Component<Props, State> {
|
|||
await mutator.changePropertyOptionOrder(board, boardTree.groupByProperty, draggedHeaderOption, destIndex)
|
||||
}
|
||||
}
|
||||
|
||||
onSearchKeyDown(e: React.KeyboardEvent) {
|
||||
if (e.keyCode === 27) { // ESC: Clear search
|
||||
this.searchFieldRef.current.text = ""
|
||||
this.setState({ ...this.state, isSearching: false })
|
||||
this.props.pageController.setSearchText(undefined)
|
||||
e.preventDefault()
|
||||
}
|
||||
}
|
||||
|
||||
searchChanged(text?: string) {
|
||||
this.props.pageController.setSearchText(text)
|
||||
}
|
||||
}
|
||||
|
||||
export { BoardComponent }
|
||||
|
|
|
@ -102,7 +102,6 @@ class Editable extends React.Component<Props, State> {
|
|||
this.text = newText
|
||||
|
||||
this.elementRef.current.classList.remove("active")
|
||||
|
||||
if (onBlur) { onBlur() }
|
||||
}}
|
||||
|
||||
|
|
|
@ -23,16 +23,24 @@ type Props = {
|
|||
|
||||
type State = {
|
||||
isHoverOnCover: boolean
|
||||
isSearching: boolean
|
||||
}
|
||||
|
||||
class TableComponent extends React.Component<Props, State> {
|
||||
private draggedHeaderTemplate: IPropertyTemplate
|
||||
private cardIdToRowMap = new Map<string, React.RefObject<TableRow>>()
|
||||
private cardIdToFocusOnRender: string
|
||||
private searchFieldRef = React.createRef<Editable>()
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props)
|
||||
this.state = { isHoverOnCover: false }
|
||||
this.state = { isHoverOnCover: false, isSearching: !!this.props.boardTree?.getSearchText() }
|
||||
}
|
||||
|
||||
componentDidUpdate(prevPros: Props, prevState: State) {
|
||||
if (this.state.isSearching && !prevState.isSearching) {
|
||||
this.searchFieldRef.current.focus()
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -83,7 +91,16 @@ class TableComponent extends React.Component<Props, State> {
|
|||
<div className="octo-button" onClick={(e) => { this.propertiesClicked(e) }}>Properties</div>
|
||||
<div className={ hasFilter ? "octo-button active" : "octo-button"} onClick={(e) => { this.filterClicked(e) }}>Filter</div>
|
||||
<div className={ hasSort ? "octo-button active" : "octo-button"} onClick={(e) => { this.sortClicked(e) }}>Sort</div>
|
||||
<div className="octo-button">Search</div>
|
||||
{this.state.isSearching
|
||||
? <Editable
|
||||
ref={this.searchFieldRef}
|
||||
text={boardTree.getSearchText()}
|
||||
placeholderText="Search text"
|
||||
style={{ color: "#000000" }}
|
||||
onChanged={(text) => { this.searchChanged(text) }}
|
||||
onKeyDown={(e) => { this.onSearchKeyDown(e) }}></Editable>
|
||||
: <div className="octo-button" onClick={() => { this.setState({ ...this.state, isSearching: true }) }}>Search</div>
|
||||
}
|
||||
<div className="octo-button" onClick={(e) => this.optionsClicked(e)}><div className="imageOptions"></div></div>
|
||||
<div className="octo-button filled" onClick={() => { this.addCard(true) }}>New</div>
|
||||
</div>
|
||||
|
@ -401,6 +418,19 @@ class TableComponent extends React.Component<Props, State> {
|
|||
const destIndex = template ? board.cardProperties.indexOf(template) : 0
|
||||
await mutator.changePropertyTemplateOrder(board, draggedHeaderTemplate, destIndex)
|
||||
}
|
||||
|
||||
onSearchKeyDown(e: React.KeyboardEvent) {
|
||||
if (e.keyCode === 27) { // ESC: Clear search
|
||||
this.searchFieldRef.current.text = ""
|
||||
this.setState({ ...this.state, isSearching: false })
|
||||
this.props.pageController.setSearchText(undefined)
|
||||
e.preventDefault()
|
||||
}
|
||||
}
|
||||
|
||||
searchChanged(text?: string) {
|
||||
this.props.pageController.setSearchText(text)
|
||||
}
|
||||
}
|
||||
|
||||
export { TableComponent }
|
||||
|
|
|
@ -26,6 +26,7 @@ interface IPageController {
|
|||
showCard(card: IBlock): Promise<void>
|
||||
showView(viewId: string): void
|
||||
showFilter(anchorElement?: HTMLElement): void
|
||||
setSearchText(text?: string): void
|
||||
}
|
||||
|
||||
export { IProperty, IBlock, IPageController }
|
||||
|
|
Loading…
Reference in a new issue