diff --git a/CHANGELOG.md b/CHANGELOG.md index 323af91bd25..f120a54eedf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ 1. [12663](https://github.com/influxdata/influxdb/pull/12663): Insert flux function near cursor in flux editor 1. [12678](https://github.com/influxdata/influxdb/pull/12678): Enable the use of variables in the Data Explorer and Cell Editor Overlay 1. [12655](https://github.com/influxdata/influxdb/pull/12655): Add a variable control bar to dashboards to select values for variables. +1. [12706](https://github.com/influxdata/influxdb/pull/12706): Add ability to add variable to script from the side menu. ### Bug Fixes diff --git a/ui/src/timeMachine/components/TimeMachineFluxEditor.tsx b/ui/src/timeMachine/components/TimeMachineFluxEditor.tsx index a827c4ec02c..b62c681dcf3 100644 --- a/ui/src/timeMachine/components/TimeMachineFluxEditor.tsx +++ b/ui/src/timeMachine/components/TimeMachineFluxEditor.tsx @@ -7,7 +7,7 @@ import {Position} from 'codemirror' import FluxEditor from 'src/shared/components/FluxEditor' import Threesizer from 'src/shared/components/threesizer/Threesizer' import FluxFunctionsToolbar from 'src/timeMachine/components/fluxFunctionsToolbar/FluxFunctionsToolbar' -import VariablesToolbar from 'src/timeMachine/components/variableToolbar/VariableToolbar' +import VariableToolbar from 'src/timeMachine/components/variableToolbar/VariableToolbar' import ToolbarTab from 'src/timeMachine/components/ToolbarTab' // Actions @@ -16,7 +16,8 @@ import {saveAndExecuteQueries} from 'src/timeMachine/actions/queries' // Utils import {getActiveQuery} from 'src/timeMachine/selectors' -import {insertFluxFunction} from 'src/timeMachine/utils/scriptInsertion' +import {insertFluxFunction} from 'src/timeMachine/utils/insertFunction' +import {insertVariable} from 'src/timeMachine/utils/insertVariable' // Constants import {HANDLE_VERTICAL, HANDLE_NONE} from 'src/shared/constants' @@ -114,13 +115,31 @@ class TimeMachineFluxEditor extends PureComponent { ) } - return + return } private handleCursorPosition = (position: Position): void => { this.cursorPosition = position } + private handleInsertVariable = async ( + variableName: string + ): Promise => { + const {activeQueryText} = this.props + const {line, ch} = this.cursorPosition + + const {updatedScript, cursorPosition} = insertVariable( + line, + ch, + activeQueryText, + variableName + ) + + await this.props.onSetActiveQueryText(updatedScript) + + this.handleCursorPosition(cursorPosition) + } + private handleInsertFluxFunction = async ( functionName: string, fluxFunction: string diff --git a/ui/src/timeMachine/components/variableToolbar/VariableItem.tsx b/ui/src/timeMachine/components/variableToolbar/VariableItem.tsx index 6eaec83df51..30b5a8f85b4 100644 --- a/ui/src/timeMachine/components/variableToolbar/VariableItem.tsx +++ b/ui/src/timeMachine/components/variableToolbar/VariableItem.tsx @@ -7,12 +7,17 @@ import BoxTooltip from 'src/shared/components/BoxTooltip' // Types import {Variable} from '@influxdata/influx' +import VariableLabel from 'src/timeMachine/components/variableToolbar/VariableLabel' interface Props { variable: Variable + onClickVariable: (variableName: string) => void } -const VariableItem: FunctionComponent = ({variable}) => { +const VariableItem: FunctionComponent = ({ + variable, + onClickVariable, +}) => { const trigger = useRef(null) const [tooltipVisible, setTooltipVisible] = useState(false) @@ -29,7 +34,7 @@ const VariableItem: FunctionComponent = ({variable}) => { onMouseLeave={() => setTooltipVisible(false)} ref={trigger} > -
{variable.name}
+ {tooltipVisible && ( diff --git a/ui/src/timeMachine/components/variableToolbar/VariableLabel.tsx b/ui/src/timeMachine/components/variableToolbar/VariableLabel.tsx new file mode 100644 index 00000000000..76a35c66126 --- /dev/null +++ b/ui/src/timeMachine/components/variableToolbar/VariableLabel.tsx @@ -0,0 +1,21 @@ +import React, {FunctionComponent} from 'react' + +interface Props { + name: string + onClickVariable: (name: string) => void +} + +const VariableLabel: FunctionComponent = ({onClickVariable, name}) => { + return ( +
{ + onClickVariable(name) + }} + > + {name} +
+ ) +} + +export default VariableLabel diff --git a/ui/src/timeMachine/components/variableToolbar/VariableToolbar.tsx b/ui/src/timeMachine/components/variableToolbar/VariableToolbar.tsx index 4a7f8526e2d..f16d26c6093 100644 --- a/ui/src/timeMachine/components/variableToolbar/VariableToolbar.tsx +++ b/ui/src/timeMachine/components/variableToolbar/VariableToolbar.tsx @@ -18,11 +18,18 @@ import 'src/timeMachine/components/variableToolbar/VariableToolbar.scss' import {Variable} from '@influxdata/influx' import {AppState} from 'src/types/v2' +interface OwnProps { + onClickVariable: (variableName: string) => void +} + interface StateProps { variables: Variable[] } -const VariableToolbar: FunctionComponent = ({variables}) => { +const VariableToolbar: FunctionComponent = ({ + variables, + onClickVariable, +}) => { const [searchTerm, setSearchTerm] = useState('') return ( @@ -33,7 +40,11 @@ const VariableToolbar: FunctionComponent = ({variables}) => { {variables .filter(v => v.name.includes(searchTerm)) .map(v => ( - + ))} diff --git a/ui/src/timeMachine/utils/scriptInsertion.ts b/ui/src/timeMachine/utils/insertFunction.ts similarity index 100% rename from ui/src/timeMachine/utils/scriptInsertion.ts rename to ui/src/timeMachine/utils/insertFunction.ts diff --git a/ui/src/timeMachine/utils/insertVariable.ts b/ui/src/timeMachine/utils/insertVariable.ts new file mode 100644 index 00000000000..44d6fa0c883 --- /dev/null +++ b/ui/src/timeMachine/utils/insertVariable.ts @@ -0,0 +1,60 @@ +import {Position} from 'codemirror' + +const rejoinScript = (scriptLines: string[]): string => { + return scriptLines.join('\n') +} + +const getCursorPosition = ( + currentLineNumber: number, + currentCharacterNumber: number, + variableName: string +) => { + return { + line: currentLineNumber, + ch: currentCharacterNumber + formatVariable(variableName).length, + } +} + +const insertAtCharacter = ( + lineNumber: number, + characterNumber: number, + scriptLines: string[], + variableName: string +): string => { + const lineToEdit = scriptLines[lineNumber] + const front = lineToEdit.slice(0, characterNumber) + const back = lineToEdit.slice(characterNumber, lineToEdit.length) + + const updatedLine = `${front}${formatVariable(variableName)}${back}` + scriptLines[lineNumber] = updatedLine + + return rejoinScript(scriptLines) +} + +const formatVariable = (variableName: string): string => { + return `v.${variableName}` +} + +export const insertVariable = ( + currentLineNumber: number, + currentCharacterNumber: number, + currentScript: string, + variableName: string +): {updatedScript: string; cursorPosition: Position} => { + const scriptLines = currentScript.split('\n') + + const updatedScript = insertAtCharacter( + currentLineNumber, + currentCharacterNumber, + scriptLines, + variableName + ) + + const updatedCursorPosition = getCursorPosition( + currentLineNumber, + currentCharacterNumber, + variableName + ) + + return {updatedScript, cursorPosition: updatedCursorPosition} +}