Merge pull request #16054 from grafana/input-to-grafanaui2

Input to grafanaui2
This commit is contained in:
Torkel Ödegaard 2019-03-18 22:49:40 +01:00 committed by GitHub
commit 89bf94b07c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 48 additions and 59 deletions

View File

@ -1,18 +1,16 @@
import React from 'react';
import React from 'react';
import renderer from 'react-test-renderer';
import { shallow } from 'enzyme';
import { Input, EventsWithValidation } from './Input';
import { ValidationEvents } from 'app/types';
import { Input } from './Input';
import { EventsWithValidation } from '../../utils';
import { ValidationEvents } from '../../types';
const TEST_ERROR_MESSAGE = 'Value must be empty or less than 3 chars';
const testBlurValidation: ValidationEvents = {
[EventsWithValidation.onBlur]: [
{
rule: (value: string) => {
if (!value || value.length < 3) {
return true;
}
return false;
return !value || value.length < 3;
},
errorMessage: TEST_ERROR_MESSAGE,
},

View File

@ -1,26 +1,13 @@
import React, { PureComponent } from 'react';
import React, { PureComponent, ChangeEvent } from 'react';
import classNames from 'classnames';
import { ValidationEvents, ValidationRule } from 'app/types';
import { validate, hasValidationEvent } from 'app/core/utils/validate';
import { validate, EventsWithValidation, hasValidationEvent } from '../../utils';
import { ValidationEvents, ValidationRule } from '../../types';
export enum InputStatus {
Invalid = 'invalid',
Valid = 'valid',
}
export enum InputTypes {
Text = 'text',
Number = 'number',
Password = 'password',
Email = 'email',
}
export enum EventsWithValidation {
onBlur = 'onBlur',
onFocus = 'onFocus',
onChange = 'onChange',
}
interface Props extends React.HTMLProps<HTMLInputElement> {
validationEvents?: ValidationEvents;
hideErrorMessage?: boolean;
@ -28,7 +15,7 @@ interface Props extends React.HTMLProps<HTMLInputElement> {
// Override event props and append status as argument
onBlur?: (event: React.FocusEvent<HTMLInputElement>, status?: InputStatus) => void;
onFocus?: (event: React.FocusEvent<HTMLInputElement>, status?: InputStatus) => void;
onChange?: (event: React.FormEvent<HTMLInputElement>, status?: InputStatus) => void;
onChange?: (event: React.ChangeEvent<HTMLInputElement>, status?: InputStatus) => void;
}
export class Input extends PureComponent<Props> {
@ -49,24 +36,24 @@ export class Input extends PureComponent<Props> {
}
validatorAsync = (validationRules: ValidationRule[]) => {
return evt => {
return (evt: ChangeEvent<HTMLInputElement>) => {
const errors = validate(evt.target.value, validationRules);
this.setState(prevState => {
return {
...prevState,
error: errors ? errors[0] : null,
};
return { ...prevState, error: errors ? errors[0] : null };
});
};
};
populateEventPropsWithStatus = (restProps, validationEvents: ValidationEvents) => {
populateEventPropsWithStatus = (restProps: any, validationEvents: ValidationEvents | undefined) => {
const inputElementProps = { ...restProps };
Object.keys(EventsWithValidation).forEach((eventName: EventsWithValidation) => {
if (hasValidationEvent(eventName, validationEvents) || restProps[eventName]) {
inputElementProps[eventName] = async evt => {
if (!validationEvents) {
return inputElementProps;
}
Object.keys(EventsWithValidation).forEach(eventName => {
if (hasValidationEvent(eventName as EventsWithValidation, validationEvents) || restProps[eventName]) {
inputElementProps[eventName] = async (evt: ChangeEvent<HTMLInputElement>) => {
evt.persist(); // Needed for async. https://reactjs.org/docs/events.html#event-pooling
if (hasValidationEvent(eventName, validationEvents)) {
if (hasValidationEvent(eventName as EventsWithValidation, validationEvents)) {
await this.validatorAsync(validationEvents[eventName]).apply(this, [evt]);
}
if (restProps[eventName]) {

View File

@ -25,6 +25,7 @@ export { ValueMappingsEditor } from './ValueMappingsEditor/ValueMappingsEditor';
export { Switch } from './Switch/Switch';
export { EmptySearchResult } from './EmptySearchResult/EmptySearchResult';
export { UnitPicker } from './UnitPicker/UnitPicker';
export { Input, InputStatus } from './Input/Input';
// Visualizations
export { Gauge } from './Gauge/Gauge';

View File

@ -5,3 +5,4 @@ export * from './plugin';
export * from './datasource';
export * from './theme';
export * from './threshold';
export * from './input';

View File

@ -8,3 +8,4 @@ export * from './string';
export * from './displayValue';
export * from './deprecationWarning';
export { getMappedValue } from './valueMappings';
export * from './validate';

View File

@ -0,0 +1,24 @@
import { ValidationRule, ValidationEvents } from '../types/input';
export enum EventsWithValidation {
onBlur = 'onBlur',
onFocus = 'onFocus',
onChange = 'onChange',
}
export const validate = (value: string, validationRules: ValidationRule[]) => {
const errors = validationRules.reduce(
(acc, currRule) => {
if (!currRule.rule(value)) {
return acc.concat(currRule.errorMessage);
}
return acc;
},
[] as string[]
);
return errors.length > 0 ? errors : null;
};
export const hasValidationEvent = (event: EventsWithValidation, validationEvents: ValidationEvents | undefined) => {
return validationEvents && validationEvents[event];
};

View File

@ -1 +0,0 @@
export { Input } from './Input';

View File

@ -1,16 +0,0 @@
import { ValidationRule, ValidationEvents } from 'app/types';
import { EventsWithValidation } from 'app/core/components/Form/Input';
export const validate = (value: string, validationRules: ValidationRule[]) => {
const errors = validationRules.reduce((acc, currRule) => {
if (!currRule.rule(value)) {
return acc.concat(currRule.errorMessage);
}
return acc;
}, []);
return errors.length > 0 ? errors : null;
};
export const hasValidationEvent = (event: EventsWithValidation, validationEvents: ValidationEvents) => {
return validationEvents && validationEvents[event];
};

View File

@ -5,17 +5,12 @@ import React, { PureComponent, ChangeEvent, FocusEvent } from 'react';
import { isValidTimeSpan } from 'app/core/utils/rangeutil';
// Components
import { Switch } from '@grafana/ui';
import { Input } from 'app/core/components/Form';
import { EventsWithValidation } from 'app/core/components/Form/Input';
import { InputStatus } from 'app/core/components/Form/Input';
import { DataSourceSelectItem, EventsWithValidation, Input, InputStatus, Switch, ValidationEvents } from '@grafana/ui';
import { DataSourceOption } from './DataSourceOption';
import { FormLabel } from '@grafana/ui';
// Types
import { PanelModel } from '../state/PanelModel';
import { DataSourceSelectItem } from '@grafana/ui/src/types';
import { ValidationEvents } from 'app/types';
import { PanelModel } from '../state';
const timeRangeValidationEvents: ValidationEvents = {
[EventsWithValidation.onBlur]: [

View File

@ -12,6 +12,5 @@ export * from './plugins';
export * from './organization';
export * from './appNotifications';
export * from './search';
export * from './form';
export * from './explore';
export * from './store';