import React, { FormEvent, PureComponent } from 'react'; import { bindActionCreators } from 'redux'; import { connect, ConnectedProps } from 'react-redux'; 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 { KeyedVariableIdentifier } from '../state/types'; import { VariableHide } from '../types'; import { appEvents } from '../../../core/core'; import { VariableValuesPreview } from './VariableValuesPreview'; import { changeVariableName, onEditorUpdate, variableEditorMount, variableEditorUnMount } from './actions'; 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'; import { getVariable, getVariablesState } from '../state/selectors'; import { toKeyedAction } from '../state/keyedVariablesReducer'; import { StoreState, ThunkDispatch } from '../../../types'; import { toKeyedVariableIdentifier, toVariablePayload } from '../utils'; const mapStateToProps = (state: StoreState, ownProps: OwnProps) => ({ editor: getVariablesState(ownProps.identifier.rootStateKey, state).editor, variable: getVariable(ownProps.identifier, state, false), // we could be renaming a variable and we don't want this to throw }); const mapDispatchToProps = (dispatch: ThunkDispatch) => { return { ...bindActionCreators( { variableEditorMount, variableEditorUnMount, changeVariableName, onEditorUpdate, updateOptions }, dispatch ), changeVariableProp: (identifier: KeyedVariableIdentifier, propName: string, propValue: any) => dispatch( toKeyedAction( identifier.rootStateKey, changeVariableProp(toVariablePayload(identifier, { propName, propValue })) ) ), changeVariableType: (identifier: KeyedVariableIdentifier, newType: VariableType) => dispatch(toKeyedAction(identifier.rootStateKey, changeVariableType(toVariablePayload(identifier, { newType })))), }; }; const connector = connect(mapStateToProps, mapDispatchToProps); export interface OwnProps { identifier: KeyedVariableIdentifier; } type Props = OwnProps & ConnectedProps; 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(this.props.identifier, option.value); }; onLabelChange = (event: FormEvent) => { event.preventDefault(); this.props.changeVariableProp(this.props.identifier, 'label', event.currentTarget.value); }; onDescriptionChange = (event: FormEvent) => { this.props.changeVariableProp(this.props.identifier, 'description', event.currentTarget.value); }; onHideChange = (option: SelectableValue) => { this.props.changeVariableProp(this.props.identifier, 'hide', option.value); }; onPropChanged = async ({ propName, propValue, updateOptions = false }: OnPropChangeArguments) => { this.props.changeVariableProp(this.props.identifier, propName, propValue); if (updateOptions) { await this.props.updateOptions(toKeyedVariableIdentifier(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}
); } } export const VariableEditorEditor = connector(VariableEditorEditorUnConnected);