From 6e51954866572112b87b2267d2407eff9bd1c6a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Sat, 24 Oct 2020 09:12:09 +0200 Subject: [PATCH] Moving show filter to where is used --- webapp/src/components/boardComponent.tsx | 29 +++-- webapp/src/components/filterComponent.tsx | 108 ++++++++++--------- webapp/src/components/tableComponent.tsx | 23 ++-- webapp/src/components/workspaceComponent.tsx | 9 +- webapp/src/pages/boardPage.tsx | 36 ------- 5 files changed, 98 insertions(+), 107 deletions(-) diff --git a/webapp/src/components/boardComponent.tsx b/webapp/src/components/boardComponent.tsx index 87941ffe3..2105fa66c 100644 --- a/webapp/src/components/boardComponent.tsx +++ b/webapp/src/components/boardComponent.tsx @@ -25,11 +25,11 @@ import Button from './button' import {CardDialog} from './cardDialog' import {Editable} from './editable' import RootPortal from './rootPortal' +import {FilterComponent} from './filterComponent' type Props = { boardTree?: BoardTree showView: (id: string) => void - showFilter: (el: HTMLElement) => void setSearchText: (text: string) => void } @@ -39,6 +39,7 @@ type State = { viewMenu: boolean isHoverOnCover: boolean selectedCards: Card[] + showFilter: boolean } class BoardComponent extends React.Component { @@ -75,6 +76,7 @@ class BoardComponent extends React.Component { isSearching: Boolean(this.props.boardTree?.getSearchText()), viewMenu: false, selectedCards: [], + showFilter: false, } } @@ -256,10 +258,19 @@ class BoardComponent extends React.Component {
{ - this.filterClicked(e) - }} - >Filter
+ style={{position: 'relative', overflow: 'unset'}} + onClick={this.filterClicked} + > + + {this.state.showFilter && + } +
{ await mutator.changePropertyOptionValue(boardTree, boardTree.groupByProperty, option, text) } - private filterClicked(e: React.MouseEvent) { - this.props.showFilter(e.target as HTMLElement) + private filterClicked = () => { + this.setState({showFilter: true}) + } + + private hideFilter = () => { + this.setState({showFilter: false}) } private async testAddCards(count: number) { diff --git a/webapp/src/components/filterComponent.tsx b/webapp/src/components/filterComponent.tsx index 4c3861df0..dd4d05298 100644 --- a/webapp/src/components/filterComponent.tsx +++ b/webapp/src/components/filterComponent.tsx @@ -13,74 +13,80 @@ import {Utils} from '../utils' type Props = { boardTree: BoardTree - pageX: number - pageY: number onClose: () => void } class FilterComponent extends React.Component { - shouldComponentUpdate(): boolean { - return true + private node: React.RefObject + + public constructor(props: Props) { + super(props) + this.node = React.createRef() + } + + public componentDidMount() { + document.addEventListener('click', this.closeOnBlur, true) + } + + public componentWillUnmount() { + document.removeEventListener('click', this.closeOnBlur, true) + } + + private closeOnBlur = (e: Event) => { + if (this.node && this.node.current && e.target && this.node.current.contains(e.target as Node)) { + return + } + + this.props.onClose() } render(): JSX.Element { const {boardTree} = this.props const {board, activeView} = boardTree - const backgroundRef = React.createRef() - // TODO: Handle FilterGroups (compound filter statements) const filters: FilterClause[] = activeView.filter?.filters.filter((o) => !FilterGroup.isAnInstanceOf(o)) as FilterClause[] || [] return (
{ - if (e.target === backgroundRef.current) { - this.props.onClose() - } - }} + className='octo-modal octo-filter-dialog' + style={{position: 'absolute', top: 25, left: -200}} + ref={this.node} > + {filters.map((filter) => { + const template = board.cardProperties.find((o) => o.id === filter.propertyId) + const propertyName = template ? template.name : '(unknown)' // TODO: Handle error + const key = `${filter.propertyId}-${filter.condition}-${filter.values.join(',')}` + Utils.log(`FilterClause key: ${key}`) + return (
+
this.propertyClicked(e, filter)} + >{propertyName}
+
this.conditionClicked(e, filter)} + >{FilterClause.filterConditionDisplayString(filter.condition)}
+ { + this.filterValue(filter, template) + } +
+
this.deleteClicked(filter)} + >Delete
+
) + })} + +
+
- {filters.map((filter) => { - const template = board.cardProperties.find((o) => o.id === filter.propertyId) - const propertyName = template ? template.name : '(unknown)' // TODO: Handle error - const key = `${filter.propertyId}-${filter.condition}-${filter.values.join(',')}` - Utils.log(`FilterClause key: ${key}`) - return (
-
this.propertyClicked(e, filter)} - >{propertyName}
-
this.conditionClicked(e, filter)} - >{FilterClause.filterConditionDisplayString(filter.condition)}
- { - this.filterValue(filter, template) - } -
-
this.deleteClicked(filter)} - >Delete
-
) - })} - -
- -
this.addFilterClicked()} - >+ Add Filter
-
+ className='octo-button' + onClick={() => this.addFilterClicked()} + >+ Add Filter
) } diff --git a/webapp/src/components/tableComponent.tsx b/webapp/src/components/tableComponent.tsx index 0a719add4..14988e980 100644 --- a/webapp/src/components/tableComponent.tsx +++ b/webapp/src/components/tableComponent.tsx @@ -23,11 +23,11 @@ import {CardDialog} from './cardDialog' import {Editable} from './editable' import RootPortal from './rootPortal' import {TableRow} from './tableRow' +import {FilterComponent} from './filterComponent' type Props = { boardTree?: BoardTree showView: (id: string) => void - showFilter: (el: HTMLElement) => void setSearchText: (text: string) => void } @@ -36,6 +36,7 @@ type State = { isSearching: boolean shownCard?: Card viewMenu: boolean + showFilter: boolean } class TableComponent extends React.Component { @@ -46,7 +47,7 @@ class TableComponent extends React.Component { constructor(props: Props) { super(props) - this.state = {isHoverOnCover: false, isSearching: Boolean(this.props.boardTree?.getSearchText()), viewMenu: false} + this.state = {isHoverOnCover: false, isSearching: Boolean(this.props.boardTree?.getSearchText()), viewMenu: false, showFilter: false} } shouldComponentUpdate(): boolean { @@ -219,14 +220,18 @@ class TableComponent extends React.Component {
{ - this.filterClicked(e) - }} + style={{position: 'relative', overflow: 'unset'}} + onClick={this.filterClicked} > + {this.state.showFilter && + }
@@ -457,8 +462,12 @@ class TableComponent extends React.Component { ) } - private filterClicked(e: React.MouseEvent) { - this.props.showFilter(e.target as HTMLElement) + private filterClicked = () => { + this.setState({showFilter: true}) + } + + private hideFilter = () => { + this.setState({showFilter: false}) } private async headerClicked(e: React.MouseEvent, templateId: string) { diff --git a/webapp/src/components/workspaceComponent.tsx b/webapp/src/components/workspaceComponent.tsx index 620d37d2f..bd7e99519 100644 --- a/webapp/src/components/workspaceComponent.tsx +++ b/webapp/src/components/workspaceComponent.tsx @@ -15,7 +15,6 @@ type Props = { boardTree?: BoardTree showBoard: (id: string) => void showView: (id: string, boardId?: string) => void - showFilter: (el: HTMLElement) => void setSearchText: (text: string) => void setLanguage: (lang: string) => void } @@ -41,7 +40,7 @@ class WorkspaceComponent extends React.Component { } private mainComponent() { - const {boardTree, showFilter, setSearchText, showView} = this.props + const {boardTree, setSearchText, showView} = this.props const {activeView} = boardTree || {} if (!activeView) { @@ -52,19 +51,17 @@ class WorkspaceComponent extends React.Component { case 'board': { return () + />) } case 'table': { return () + />) } default: { diff --git a/webapp/src/pages/boardPage.tsx b/webapp/src/pages/boardPage.tsx index fcc874364..09197a887 100644 --- a/webapp/src/pages/boardPage.tsx +++ b/webapp/src/pages/boardPage.tsx @@ -22,7 +22,6 @@ type State = { viewId: string workspaceTree: MutableWorkspaceTree boardTree?: MutableBoardTree - filterAnchorElement?: HTMLElement } export default class BoardPage extends React.Component { @@ -112,34 +111,6 @@ export default class BoardPage extends React.Component { render(): JSX.Element { const {workspaceTree} = this.state - if (this.state.filterAnchorElement) { - const element = this.state.filterAnchorElement - const bodyRect = document.body.getBoundingClientRect() - const rect = element.getBoundingClientRect() - - // Show at bottom-left of element - const maxX = bodyRect.right - 420 - 100 - const pageX = Math.min(maxX, rect.left - bodyRect.left) - const pageY = rect.bottom - bodyRect.top - - ReactDOM.render( - { - this.showFilter(undefined) - }} - />, - Utils.getElementById('modal'), - ) - } else { - const modal = document.getElementById('modal') - if (modal) { - ReactDOM.render(
, modal) - } - } - Utils.log(`BoardPage.render ${this.state.boardTree?.board?.title}`) return (
@@ -152,9 +123,6 @@ export default class BoardPage extends React.Component { showBoard={(id) => { this.showBoard(id) }} - showFilter={(el) => { - this.showFilter(el) - }} setSearchText={(text) => { this.setSearchText(text) }} @@ -230,10 +198,6 @@ export default class BoardPage extends React.Component { window.history.pushState({path: newUrl}, '', newUrl) } - showFilter(anchorElement?: HTMLElement): void { - this.setState({...this.state, filterAnchorElement: anchorElement}) - } - setSearchText(text?: string): void { this.state.boardTree?.setSearchText(text) this.setState({...this.state, boardTree: this.state.boardTree})