import React, { FormEvent, PureComponent } from 'react'; import { isEqual } from 'lodash'; import { AppEvents, LoadingState, SelectableValue, VariableType } from '@grafana/data'; import { Button, Icon, InlineFieldRow, VerticalGroup } from '@grafana/ui'; import { selectors } from '@grafana/e2e-selectors'; import { variableAdapters } from '../adapters'; import { toVariableIdentifier, toVariablePayload, VariableIdentifier } from '../state/types'; import { VariableHide, VariableModel } from '../types'; import { appEvents } from '../../../core/core'; import { VariableValuesPreview } from './VariableValuesPreview'; import { changeVariableName, onEditorUpdate, variableEditorMount, variableEditorUnMount } from './actions'; import { MapDispatchToProps, MapStateToProps } from 'react-redux'; import { StoreState } from '../../../types'; import { VariableEditorState } from './reducer'; import { getVariable } from '../state/selectors'; import { connectWithStore } from '../../../core/utils/connectWithReduxStore'; import { OnPropChangeArguments } from './types'; import { changeVariableProp, changeVariableType } from '../state/sharedReducer'; import { updateOptions } from '../state/actions'; import { VariableTextField } from './VariableTextField'; import { VariableSectionHeader } from './VariableSectionHeader'; import { hasOptions } from '../guard'; import { VariableTypeSelect } from './VariableTypeSelect'; import { VariableHideSelect } from './VariableHideSelect'; export interface OwnProps { identifier: VariableIdentifier; } interface ConnectedProps { editor: VariableEditorState; variable: VariableModel; } interface DispatchProps { variableEditorMount: typeof variableEditorMount; variableEditorUnMount: typeof variableEditorUnMount; changeVariableName: typeof changeVariableName; changeVariableProp: typeof changeVariableProp; onEditorUpdate: typeof onEditorUpdate; changeVariableType: typeof changeVariableType; updateOptions: typeof updateOptions; } type Props = OwnProps & ConnectedProps & DispatchProps; export class VariableEditorEditorUnConnected extends PureComponent { componentDidMount(): void { this.props.variableEditorMount(this.props.identifier); } componentDidUpdate(prevProps: Readonly, prevState: Readonly<{}>, snapshot?: any): void { if (!isEqual(prevProps.editor.errors, this.props.editor.errors)) { Object.values(this.props.editor.errors).forEach((error) => { appEvents.emit(AppEvents.alertWarning, ['Validation', error]); }); } } componentWillUnmount(): void { this.props.variableEditorUnMount(this.props.identifier); } onNameChange = (event: FormEvent) => { event.preventDefault(); this.props.changeVariableName(this.props.identifier, event.currentTarget.value); }; onTypeChange = (option: SelectableValue) => { if (!option.value) { return; } this.props.changeVariableType(toVariablePayload(this.props.identifier, { newType: option.value })); }; onLabelChange = (event: FormEvent) => { event.preventDefault(); this.props.changeVariableProp( toVariablePayload(this.props.identifier, { propName: 'label', propValue: event.currentTarget.value }) ); }; onDescriptionChange = (event: FormEvent) => { this.props.changeVariableProp( toVariablePayload(this.props.identifier, { propName: 'description', propValue: event.currentTarget.value }) ); }; onHideChange = (option: SelectableValue) => { this.props.changeVariableProp( toVariablePayload(this.props.identifier, { propName: 'hide', propValue: option.value, }) ); }; onPropChanged = async ({ propName, propValue, updateOptions = false }: OnPropChangeArguments) => { this.props.changeVariableProp(toVariablePayload(this.props.identifier, { propName, propValue })); if (updateOptions) { await this.props.updateOptions(toVariableIdentifier(this.props.variable)); } }; onHandleSubmit = async (event: FormEvent) => { event.preventDefault(); if (!this.props.editor.isValid) { return; } await this.props.onEditorUpdate(this.props.identifier); }; render() { const { variable } = this.props; const EditorToRender = variableAdapters.get(this.props.variable.type).editor; if (!EditorToRender) { return null; } const loading = variable.state === LoadingState.Loading; return (
{this.props.editor.errors.name && (
{this.props.editor.errors.name}
)}
{EditorToRender && } {hasOptions(this.props.variable) ? : null}
); } } const mapStateToProps: MapStateToProps = (state, ownProps) => ({ editor: state.templating.editor, variable: getVariable(ownProps.identifier.id, state, false), // we could be renaming a variable and we don't want this to throw }); const mapDispatchToProps: MapDispatchToProps = { variableEditorMount, variableEditorUnMount, changeVariableName, changeVariableProp, onEditorUpdate, changeVariableType, updateOptions, }; export const VariableEditorEditor = connectWithStore( VariableEditorEditorUnConnected, mapStateToProps, mapDispatchToProps );