From cdcba3566ba63472f778aeb4a57770e10ce585b4 Mon Sep 17 00:00:00 2001 From: Deniz Kusefoglu Date: Tue, 16 Jun 2020 19:41:12 -0700 Subject: [PATCH] fix(popovers): Refactor popover to controlled component (#18524) * fix(popovers): Refactor popover to controlled component * fix(labels): Test popover closing --- ui/cypress/e2e/dashboardsIndex.test.ts | 31 +++++++++- .../inlineLabels/InlineLabelPopover.tsx | 7 ++- .../inlineLabels/InlineLabelsEditor.tsx | 57 ++++++++++++++----- 3 files changed, 79 insertions(+), 16 deletions(-) diff --git a/ui/cypress/e2e/dashboardsIndex.test.ts b/ui/cypress/e2e/dashboardsIndex.test.ts index 91f1dd40a9..b53da0141e 100644 --- a/ui/cypress/e2e/dashboardsIndex.test.ts +++ b/ui/cypress/e2e/dashboardsIndex.test.ts @@ -296,7 +296,7 @@ describe('Dashboards', () => { }) }) - it('typing a new label name and pressing ENTER starts label creation flow', () => { + it('typing a new label name and pressing ENTER starts label creation flow, closes popover', () => { const labelName = 'choco' cy.get('@org').then(() => { @@ -304,10 +304,39 @@ describe('Dashboards', () => { .first() .click() + cy.getByTestID('inline-labels--popover--contents').should( + 'be.visible' + ) cy.getByTestID(`inline-labels--popover-field`) .type(labelName) .type('{enter}') cy.getByTestID('overlay--body').should('be.visible') + cy.getByTestID('inline-labels--popover--contents').should( + 'not.be.visible' + ) + }) + }) + it('typing a new label name and clicking name starts label creation flow, closes popover', () => { + // https://github.com/influxdata/influxdb/issues/17964 + const labelName = 'the new new' + + cy.get('@org').then(() => { + cy.getByTestID(`inline-labels--add`) + .first() + .click() + + cy.getByTestID('inline-labels--popover--contents').should( + 'be.visible' + ) + + cy.getByTestID(`inline-labels--popover-field`).type(labelName) + + cy.getByTestID(`inline-labels--create-new`).click() + + cy.getByTestID('overlay--body').should('be.visible') + cy.getByTestID('inline-labels--popover--contents').should( + 'not.be.visible' + ) }) }) diff --git a/ui/src/shared/components/inlineLabels/InlineLabelPopover.tsx b/ui/src/shared/components/inlineLabels/InlineLabelPopover.tsx index 1eb81fd2e3..c3a8077b9a 100644 --- a/ui/src/shared/components/inlineLabels/InlineLabelPopover.tsx +++ b/ui/src/shared/components/inlineLabels/InlineLabelPopover.tsx @@ -42,6 +42,7 @@ interface Props { onInputChange: (e: ChangeEvent) => void filteredLabels: Label[] onAddLabel: (labelID: string) => void + visible: boolean } @ErrorHandling @@ -57,6 +58,7 @@ export default class InlineLabelPopover extends PureComponent { onUpdateSelectedItemID, onInputChange, filteredLabels, + visible, } = this.props return ( @@ -65,8 +67,9 @@ export default class InlineLabelPopover extends PureComponent { position={PopoverPosition.Below} triggerRef={triggerRef} distanceFromTrigger={8} - showEvent={PopoverInteraction.Click} - hideEvent={PopoverInteraction.Click} + visible={visible} + showEvent={PopoverInteraction.None} + hideEvent={PopoverInteraction.None} testID="inline-labels--popover" className="inline-labels--popover" contents={() => ( diff --git a/ui/src/shared/components/inlineLabels/InlineLabelsEditor.tsx b/ui/src/shared/components/inlineLabels/InlineLabelsEditor.tsx index 83de8b134f..84de7ce9f0 100644 --- a/ui/src/shared/components/inlineLabels/InlineLabelsEditor.tsx +++ b/ui/src/shared/components/inlineLabels/InlineLabelsEditor.tsx @@ -9,6 +9,7 @@ import { ButtonShape, ButtonBaseRef, ComponentColor, + ClickOutside, } from '@influxdata/clockface' import InlineLabelPopover from 'src/shared/components/inlineLabels/InlineLabelPopover' import CreateLabelOverlay from 'src/labels/components/CreateLabelOverlay' @@ -53,6 +54,7 @@ interface State { searchTerm: string selectedItemID: string isCreatingLabel: OverlayState + isPopoverVisible: boolean } @ErrorHandling @@ -66,9 +68,14 @@ class InlineLabelsEditor extends Component { selectedItemID: null, searchTerm: '', isCreatingLabel: OverlayState.Closed, + isPopoverVisible: false, } } + public componentDidMount() { + this.handleAddPopoverEventListener() + } + public render() { const {isCreatingLabel, searchTerm} = this.state @@ -101,23 +108,26 @@ class InlineLabelsEditor extends Component { private get popover(): JSX.Element { const {labels, selectedLabels} = this.props - const {searchTerm, selectedItemID} = this.state + const {searchTerm, selectedItemID, isPopoverVisible} = this.state const labelsUsed = labels.length > 0 && labels.length === selectedLabels.length return ( - + + + ) } @@ -145,6 +155,27 @@ class InlineLabelsEditor extends Component { ) } + private handleAddPopoverEventListener = (): void => { + if (!this.popoverTrigger.current) { + return + } + this.popoverTrigger.current.addEventListener('click', () => { + this.setState({ + isPopoverVisible: true, + }) + }) + } + + private onClickOutside = (e: MouseEvent): void => { + if (e.target === this.popoverTrigger.current) { + return + } + + this.setState({ + isPopoverVisible: false, + }) + } + private handleAddLabel = async (labelID: string) => { const {onAddLabel, labels} = this.props @@ -243,7 +274,7 @@ class InlineLabelsEditor extends Component { } private handleStartCreatingLabel = (): void => { - this.setState({isCreatingLabel: OverlayState.Open}) + this.setState({isCreatingLabel: OverlayState.Open, isPopoverVisible: false}) } private handleStopCreatingLabel = (): void => {