diff --git a/web/ui/react-app/src/App.css b/web/ui/react-app/src/App.css index 51658f4ab..612d3bbc8 100644 --- a/web/ui/react-app/src/App.css +++ b/web/ui/react-app/src/App.css @@ -13,6 +13,7 @@ body { .expression-input textarea { /* font-family: Menlo,Monaco,Consolas,'Courier New',monospace; */ resize: none; + overflow: hidden; } button.execute-btn { diff --git a/web/ui/react-app/src/ExpressionInput.tsx b/web/ui/react-app/src/ExpressionInput.tsx index 338145f85..23026cad8 100644 --- a/web/ui/react-app/src/ExpressionInput.tsx +++ b/web/ui/react-app/src/ExpressionInput.tsx @@ -1,4 +1,3 @@ -import $ from 'jquery'; import React, { Component } from 'react'; import { Button, @@ -8,7 +7,7 @@ import { Input, } from 'reactstrap'; -import Downshift from 'downshift'; +import Downshift, { ControllerStateAndHelpers } from 'downshift'; import fuzzy from 'fuzzy'; import SanitizeHTML from './components/SanitizeHTML'; @@ -25,10 +24,43 @@ interface ExpressionInputProps { loading: boolean; } -class ExpressionInput extends Component { - prevNoMatchValue: string | null = null; +interface ExpressionInputState { + height: number | string; + value: string; +} + +class ExpressionInput extends Component { + private prevNoMatchValue: string | null = null; private exprInputRef = React.createRef(); + constructor(props: ExpressionInputProps) { + super(props); + this.state = { + value: props.value, + height: 'auto' + } + } + + componentDidMount() { + this.setHeight(); + } + + + setHeight = () => { + const { offsetHeight, clientHeight, scrollHeight } = this.exprInputRef.current!; + const offset = offsetHeight - clientHeight; // Needed in order for the height to be more accurate. + this.setState({ height: scrollHeight + offset }); + } + + handleInput = () => { + this.setState({ + height: 'auto', + value: this.exprInputRef.current!.value + }, this.setHeight); + } + + handleDropdownSelection = (value: string) => this.setState({ value }); + handleKeyPress = (event: React.KeyboardEvent) => { if (event.key === 'Enter' && !event.shiftKey) { this.props.executeQuery(this.exprInputRef.current!.value); @@ -36,22 +68,23 @@ class ExpressionInput extends Component { } } - renderAutosuggest = (downshift: any) => { - if (!downshift.isOpen) { + executeQuery = () => this.props.executeQuery(this.exprInputRef.current!.value) + + renderAutosuggest = (downshift: ControllerStateAndHelpers) => { + const { inputValue } = downshift + if (!inputValue || (this.prevNoMatchValue && inputValue.includes(this.prevNoMatchValue))) { + downshift.closeMenu(); return null; } - if (this.prevNoMatchValue && downshift.inputValue.includes(this.prevNoMatchValue)) { - return null; - } - - let matches = fuzzy.filter(downshift.inputValue.replace(/ /g, ''), this.props.metricNames, { + const matches = fuzzy.filter(inputValue.replace(/ /g, ''), this.props.metricNames, { pre: "", post: "", }); if (matches.length === 0) { - this.prevNoMatchValue = downshift.inputValue; + this.prevNoMatchValue = inputValue; + downshift.closeMenu(); return null; } @@ -83,23 +116,12 @@ class ExpressionInput extends Component { ); } - componentDidMount() { - const $exprInput = $(this.exprInputRef.current!); - const resize = () => { - const el = $exprInput.get(0); - const offset = el.offsetHeight - el.clientHeight; - $exprInput.css('height', 'auto').css('height', el.scrollHeight + offset); - }; - resize(); - $exprInput.on('input', resize); - } - render() { + const { value, height } = this.state; return ( {(downshift) => (
@@ -110,6 +132,8 @@ class ExpressionInput extends Component { { - {this.renderAutosuggest(downshift)} + {downshift.isOpen && this.renderAutosuggest(downshift)}
)}